Skip to content

fix(service): restore Zod 4 query coercion - #1256

Merged
rickylabs merged 2 commits into
mainfrom
fix/onboarding-quickwin-1250
Aug 4, 2026
Merged

fix(service): restore Zod 4 query coercion#1256
rickylabs merged 2 commits into
mainfrom
fix/onboarding-quickwin-1250

Conversation

@rickylabs

@rickylabs rickylabs commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

Correct the oRPC smart-coercion adapter used by @netscript/service so scaffolded Zod-4 contracts accept numeric query/path parameters sent as HTTP strings. The regression generates the OpenAPI parameter and issues the Scalar/docs-shaped GET /issues/board?cycleId=1 request, asserting the handler receives numeric 1.

Scope

Slices

  • S0 Re-baseline, lock the plan, and open the draft review surface — cf773ec38
  • S1 Add RED proof and switch the handler to the Zod-4 coercion adapter — b29105add
  • S2 Complete scoped package/doctrine/JSR gates and composed evaluation handoff — b29105add

Validation

  • RED→GREEN docs-shaped HTTP request: 400 with the Zod-3 plugin → 200 with numeric cycleId: 1
  • Generated OpenAPI parameter: cycleId is a numeric query parameter
  • Scoped check/lint/fmt: 42 files, 0 findings
  • packages/service test task: 87 passed, 0 failed
  • MCP OpenAPI read tools: 5 passed, 0 failed
  • Scoped quality scan: 0 findings / 0 allowances; doctrine scan: 0 FAIL
  • Full export-map doc lint: 3 entrypoints, 0 diagnostics
  • Package publish dry-run: pass, no slow types
  • Plan-Gate: composed per milestone-run.md (orchestrator waiver)

Harness

  • Run dir: .llm/runs/fix-onboarding-quickwin-1250--1250/
  • Phase: implementation evaluation
  • Evaluation: draft→ready augment + label-triggered OpenHands + orchestrator pre-merge gate

Drift / Debt

  • The worktree arrived with an unrelated one-line deno.lock modification; it is excluded.
  • The live issue is broader than the implementation brief: its fresh-seeded-project box remains unticked pending the orchestrator-owned scaffold gate.
  • feat(mcp): add OpenAPI introspection read tools #1204 introspection tools describe operations and emit request templates but do not execute service operations. Generated-schema and read-tool evidence is recorded without claiming an MCP call executed the endpoint.
  • Existing packages/service folder-role and Scalar asset debt is unchanged.

Definition of Done

issue: 1250
entries:
  - box-index: 1
    evidence: "Pending orchestrator-owned fresh scaffold gate; not claimed by local package validation."
  - box-index: 2
    evidence: "PR #1256 commit b29105add: exact HTTP query cycleId=1 returns 200 and handler output is numeric 1; RED control returned 400."
  - box-index: 3
    evidence: "Generated OpenAPI parameter is numeric and packages/mcp/tests/openapi-read-tools_test.ts is 5/5 green; #1204 has no operation-execution tool, so final acceptance remains pending orchestrator interpretation."
  - box-index: 4
    evidence: "packages/service/tests/handlers_test.ts at b29105add generates the OpenAPI docs shape and sends a real Request through createOpenAPIHandler, not a typed client."

Acceptance evidence

issue: 1250
entries:
  - box-index: 1
    evidence: "Composed verification on live scaffold at head b29105ad: GET /api/users?page=1&limit=5&sortBy=id&sortOrder=asc -> 200; /api/users/health -> 200; /api/users/1 reaches the handler (message 'User 1 not found' — coercion delivered id as a number; the 500 mapping is #1263, empty seed table is #1262); /api/users/abc -> 400. Full scaffold.runtime suite 69 passed / 0 failed."
  - box-index: 2
    evidence: "list_service_operations(users) called on the live scaffold's MCP server returned v1.users.list GET /users, v1.users.getById GET /users/{id}, health — the same request shapes proven above; suite gate behavior.mcp-endpoint-directory PASSED in the same run."

Copy link
Copy Markdown
Owner Author

[PHASE: RESEARCH]

Issue #1250 was read first and re-baselined against current origin/main at 5957260751.

  • handlers.ts selects the Zod-3 coercion plugin while the sibling OpenAPI converter and scaffolds use Zod 4.
  • oRPC 1.14.6 exports the compatible class from @orpc/zod/zod4 as experimental_ZodSmartCoercionPlugin.
  • Existing handler tests do not exercise query-string coercion.
  • The inherited one-line deno.lock modification is unrelated and excluded.

Run record: .llm/runs/fix-onboarding-quickwin-1250--1250/research.md.

Copy link
Copy Markdown
Owner Author

[PHASE: PLAN]

The implementation plan is locked under milestone ruling D6; no local formal PLAN-EVAL is launched.

The decisive test sends GET /api/issues/board?cycleId=1 through createOpenAPIHandler and asserts the handler receives numeric 1. This catches the reported present-but-inert plugin failure, unlike a plugin-construction test.

Evaluation remains composed through draft→ready augment, OpenHands, and the orchestrator pre-merge gate. Run record: .llm/runs/fix-onboarding-quickwin-1250--1250/plan.md and plan-eval.md.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL]

Commit b29105add restores Zod-4 smart coercion and lands the behavior-first regression.

Evidence

  • RED: the exact GET /api/issues/board?cycleId=1 request matched but returned HTTP 400 with the old Zod-3 plugin.
  • GREEN: unchanged request returns HTTP 200 with {"cycleId":1}; generated OpenAPI declares cycleId as a numeric query parameter.
  • Scoped check/lint/fmt: 42 files, zero findings.
  • Package tests: 87 passed, 0 failed.
  • MCP OpenAPI read-tool tests: 5 passed, 0 failed.
  • Scoped code-quality scan: 0 findings / 0 allowances; doctrine scan: 0 FAIL.
  • Full export-map doc lint: 3 entrypoints, 0 diagnostics.
  • Package publish dry-run: pass, no slow types.
  • Lock hygiene: inherited one-line deno.lock change remains unstaged and outside the commit.

Acceptance precision

The implementation directly proves numeric coercion and the non-typed HTTP/docs-shaped regression. The live issue's broader fresh-seeded-project and MCP-execution wording is not overstated: #1204's tools inspect schemas and emit curl templates but do not execute service operations. The generated schema + existing read-tool suite are recorded as supporting evidence for orchestrator review.

Next

Transition to ready-for-review / status:impl-eval for draft→ready augment, label-triggered OpenHands, and the orchestrator pre-merge gate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:contracts area:service packages/service canary:0.0.5-canary.8 Published NetScript prerelease 0.0.5-canary.8 priority:p1 High status:impl-eval type:fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

service: ZodSmartCoercionPlugin imported from @orpc/zod (Zod 3) while scaffolds use Zod 4 — coercion silently no-ops, every numeric query param 400s

1 participant