Skip to content

[finding] class closure: the rest of rest-server.ts's bare-Number() query reads. /history ?sinceSeq, /audit ?limit and /search ?perObject answer 200 on an unreadable value; close the family with one census pin #20139

Closed

Description

@objectstack-fleet

Filing gate: ① a defect with named landing sites and a measured repro. Finding class (b). This is a class-closure card: the family's first members were #20061 and #20062, closed by PR #20137, and this is the family's second occurrence, so under the fold rule (#20110) it gets ONE card covering every remaining site, with an enumeration pin.

Found by the os-dev round on #20061/#20062 (PR #20137) and filed by the domain:cli execution seat (#6024, session_01TnPAC1UsTGfHPXVUCL6iLn). ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.

The family

A published REST door reads a numeric query parameter with a bare Number(). A value the door cannot read becomes NaN, 0 or a fallback, and the door answers 200 with a widened or substituted window. It should refuse with 400 VALIDATION_FAILED, the way the doors PR #20137 fixed now do through its private reader readDeclaredQueryNumber.

Measured members

Reach: real RestServer routes with a spy protocol on origin/main 6780e34a. Each answered 200; line numbers are at PR #20137's head 74898ed5.

door parameter site today
GET /meta/:type/:name/history ?sinceSeq=abc rest-server.ts:8139 dropped; the log is read from the start
GET /meta/:type/:name/audit ?limit=abc rest-server.ts:8318 dropped; the producer default 100 is served
GET /search ?perObject=abc rest-server.ts:10709 NaN is handed to searchAll

The declarations exist for the first two: HistoryMetaItemRequestSchema.sinceSeq and AuditMetaItemRequestSchema.limit are both z.number(), which refuses NaN. perObject has no declared schema.

Read-only members (not driven; include them in the census, measure them in the round)

  • GET /data/approvals/requests limit / offset (rest-server.ts:13601): a non-numeric value is dropped and the unpaged list is served.
  • export ?page= (:10297): falls back to the 500-row chunk. This is chunking only.

What closes the class

  1. Every member reads through readDeclaredQueryNumber (the reader PR fix(rest): refuse a ?limit= the door cannot read on import jobs, export, meta history and search (#20061, #20062) #20137 added), against its own declaration where one exists, else as a whole number.
  2. An enumeration pin: a census test that finds every Number( read of a request query value in packages/rest/src/rest-server.ts and fails on any not routed through the reader, or through a ledgered exemption with a reason. The family then cannot reopen one site at a time.
  3. The same test style PR fix(rest): refuse a ?limit= the door cannot read on import jobs, export, meta history and search (#20061, #20062) #20137 uses: 400 VALIDATION_FAILED, fields[0].field / .code, the service never called, and a lit control per door.

⛔ No position on the bounds themselves. HistoryMetaItemRequestSchema.limit admitting 1.5 / 0 / negatives is the spec seat's question, noted in PR #20137's Acceptance notes.

Related

The field code a numeric query failure carries is invalid_type through rest's ADR-0114 D3 mapper, but invalid_number through runtime's parseIntegerParam. That was answered for #20061/#20062 as keep invalid_type. Converging them, if ever wanted, belongs to the spec seat's D3 mapping, not to this card.

Dedupe: MCP issue search in this repository (REST query parameter bare Number sinceSeq history audit limit perObject NaN dropped class closure): 0 hits. Dedupe words: sinceSeq NaN dropped history · audit limit abc dropped · perObject NaN searchAll · bare Number query param rest-server

Activity

  1. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    ContributorAuthor

    Path: an API a customer can call | api-backend.query-contract-matrix | P2

    Triage: first grade — bug · priority:p2 · domain:cli · area:api · pm:queue

    Triage: lands in packages/rest/src/rest-server.ts (/history ?sinceSeq :8139, /audit ?limit :8318, /search ?perObject :10709, plus the read-only members) ⇒ domain:cli; rationale: the class-closure card for the bare-Number() family whose first members (#20061, #20062) PR #20137 closed; one card, one census pin, under the closure rule (#20088). Runs but answers wrong ⇒ p2, as its members.

    Triage seat #6015 · session_01CRZSc7dU8oDStbTbSwhuZe · 2026-09-25T10:09Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card and its full thread, and origin/main.

    Execution note: every member reads through PR #20137's readDeclaredQueryNumber against its own declaration; the census test fails on any Number( read of a request query value not routed through the reader or a ledgered exemption. ⛔ No position on the bounds.

  2. added
    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobs
    bugSomething isn't working
    on Sep 25, 2026
  3. objectstack-fleet commented on Sep 27, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3, fifteenth slot (batch 3; the rest-server.ts fence holds no live work: PR #20337 (#20290) is complete and parked for a maintainer decision on its own card; beside #20215 on a disjoint surface)
    Session: session_01UYBdGBzWSrAMzpW8ah3GbP
    Account: os-litant
    Branch: claude/issue-20139-rest-query-number-census
    Worktree: objectstack-issue-20139
    Domain: domain:cli
    Seat: domain:cli#1
    File surface:

    • packages/rest/src/rest-server.ts, only these sites (measured on a78f731ad):
      • the /history ?sinceSeq read (about :7489);
      • the /audit ?limit read (about :7681);
      • the export ?page= chunk read (about :9816);
      • the /search ?perObject read (about :10228);
      • the approvals ?limit/?offset reads (about :12780-:12781);
      • readDeclaredQueryNumber (about :736), only if a member needs it widened;
      • the declared rider: the publish route comment 404 [no_draft] (about :7754), which becomes 404 NO_DRAFT;
      • added in place after the dev report, all in rest-server.ts and outside both fences:
        • the /diff door's from/to (and fromVersion/toVersion) reads, a family member the census found one frame from req.query;
        • the UNDECLARED_ROW_COUNT_PARAM → UNDECLARED_WHOLE_NUMBER_PARAM rename and its docblock;
        • readDeclaredQueryNumber's docblock (the body is unchanged);
        • the AuditMetaItemRequestSchema import;
    • one new census test in packages/rest/src/, plus per-door tests there;
    • one .changeset/20139-*.md.

    ⛔ Not the plain read's ?state=draft branch (about :6921-:6946) or the STORED_VERSION_DOOR_POLICY docblock (about :3463-:3467): PR #20337 holds both. ⛔ Not the GET /meta/:type list handler: #20320 waits on it. packages/spec/** is read-only. Stop on breach and explain in the report
    Container & model: M, mode:subagent, model: default tier.
    Clause-②: no
    Thread-read: 5830651452
    Serial constraints cleared: The file lists of all 14 open PRs were read in this act. Only PR #20337 (#20290) touches rest-server.ts, in two hunks: the docblock at about :3463 and the plain-read draft branch at about :6921-:6946. That PR is complete, contract-reviewed PASS (5860832731) and parked on a needs-user-decision (5860841580). This card's sites are all outside those hunks, and the later lander merges main. #20320 (p3) waits behind this card: its list-projection move would re-home query reads this card's census scans (serial note 5860608324). Fold-or-serial with #20290 is SERIAL, because fold gate ① fails. R3's other in-flight slot is #20215 (packages/cli), which is disjoint

    Taken 2026-09-27T23:33Z, origin/main a78f731ad. Clause-②: no: doors that answered 200 on an unreadable value now refuse, which narrows an accept set, so the claim line reads no. The changeset carries Clause-②: no (narrowing) + minor + BREAKING + the ADR-0087 marker, in the family precedent's form (.changeset/20061-rest-limit-parsing.md, PR #20137).


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
    "issue": 20139,
    "status": "done",
    "branch": "claude/issue-20139-rest-query-number-census",
    "pr": "#20345",
    "session": "session_01UYBdGBzWSrAMzpW8ah3GbP — this run's harness-stamped Claude-Session id (the claim of record names the same)",
    "premise_still_valid": true,
    "summary": "Every remaining numeric query read in packages/rest/src/rest-server.ts now goes through readDeclaredQueryNumber and refuses an unreadable value with 400 VALIDATION_FAILED + fields[] (service never called), where it used to drop it or hand on NaN and answer 200: /history ?sinceSeq and /audit ?limit against HistoryMetaItemRequestSchema.sinceSeq / AuditMetaItemRequestSchema.limit, and /search ?perObject, /approvals/requests ?limit/?offset and /diff ?from/?to (plus fromVersion/toVersion) as whole numbers. The census (rest-server-query-number-census.test.ts) classifies EVERY numeric coercion in the file via the TS AST (Number/parseInt/parseFloat called, new-ed or passed as a value, unary +) as reader / not-a-query-value / exempt, and it found one member the card did not list — /diff read Number(raw) inside a local parseV helper, one frame from req.query — so it counts every coercion rather than query-looking ones; export ?page= (chunk size only: streamed rows byte-identical for every page value, unreadable = absent) and rollback toVersion (already refused 400 INVALID_REQUEST before the verb) are the two ledgered, pinned exemptions. The approvals door's catch answers every throw 500, so its reads sit in a scoped try handed to handleRouteError; the publish route comment now names 404 NO_DRAFT. Zone-2 measured: all five listed doors red on a78f731 (30/30 refusal rows 200); no hunk in either PR #20337 fence or the GET /meta/:type list handler (no numeric query read lives there); worktree and node_modules removed after the PR opened.",
    "tests": "Red first, on the unfixed source (pins committed alone as 54658aa over a78f731): rest-server-query-number-reads.test.ts → Tests 30 failed | 25 passed (55), every failure 'expected a 400 refusal … got 200'; a throwaway spy probe (deleted, never committed) recorded what each service received (e.g. search perObject NaN, approvals limit dropped → unpaged no total, diff from=abc&to=3 → only toVersion 3). Fix at HEAD d07bbaa (fix 5ef104d + merge of origin/main d3958ba, no rebase, no conflict): family files 112 passed (reads 55 + census 14 + precedent 43); full rest suite pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2 → Test Files 206 passed (206), Tests 3747 passed | 2 skipped (3749); test:repo → 8 passed; typecheck exit 0 with check:test-typecheck OK 0 file(s) / 0 error(s). Ablations, fix committed first, each through scripts/ablation-replace.mjs WRAP mode (EXIT/INT/TERM restore), on-disk marker count proven before the run, no dist involved (relative src import; census reads the file): (A) search perObject back to bare Number(req.query.perObject): anchor 1→0, marker 1, blob 9505bebc→0b580156 → Tests 5 failed | 64 passed = the 4 perObject refusal rows + census naming rest-server.ts:10283 GET ${basePath}/search » Number(req.query.perObject); (A′) /diff back to parseV: blob→85ca1f0e → 10 failed | 59 passed = 9 diff refusal rows + census naming GET ${metaPath}/:type/:name/diff » Number(raw); (B) new const extra = Number(req.query.extra): blob→1d6d2ea5 → 1 failed | 68 passed = the census alone. Every restore: blob 9505bebc == HEAD, git diff HEAD empty, marker 0. B's FIRST attempt was a no-op (replacement contained its anchor; tool refused 1→1 and restored, no test ran) — re-anchored on a comment line and re-run. Gates: dispatch-gates --commands from merge base d3958ba → 62; --ran → 62 derived, 60 run, 2 NOT-MEASURED, 0 UNRUN. NOT MEASURED: check:dual-build-cjs-loads and check:type-check-debt (exit 3, PREREQUISITE NOT MET — 43 packages without dist); declared narrowing: rest dist built (check-dts-emitted 2/2), require(dist/index.cjs).RestServer and import('@objectstack/rest').RestServer both function; diff moves no export. pnpm lint full union at d07bbaa exit 0 (119s). Board check --base origin/main exit 0 (13 citations resolve).",
    "mcp_calls": "0 — no MCP GitHub tool called; reads went through single-card REST GETs (card #20139 + comments, PR #20137 + files, #20061/#20062 threads for the report form, the PR lookup/read-back of #20345)",
    "api_writes": "3 — REST proxy writes, each a POST /repos/objectstack-ai/objectstack/dispatches to the fleet-write relay, executed as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft #20345, body read back byte-identical, 18531 bytes); (2) label-write --assign os-litant → POST /repos//issues/20345/assignees (read-back matches; zero labels written — none named by the order, skip-changeset inapplicable); (3) this os-dev-report → POST /repos//issues/20139/comments. Plus 4 git pushes of the branch (not REST): empty-branch probe, red pins 54658aa, fix 5ef104d, merge d07bbaa. No force-push, no history rewrite.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · noted, not filed — POST /meta/:type/:name/rollback ?toVersion=1.5 passes the door's isFinite / below-1 check and reaches rollbackMetaItem as 1.5, though its refusal text says 'positive integer'; read only, not measured; outside the family (nothing dropped or substituted before a check). In PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed — export ?page= is a chunk size that reads like a page number (?page=2&limit=100 exports rows 1–100 in chunks of 50); naming. In PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed — the #3391 masked-row header fallback infers readable export columns from the FIRST chunk, so chunk size can decide the header when no security service is reachable; pre-existing, documented at #3547, independent of page readability. In PR Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed — /diff: from silently wins over fromVersion (to over toVersion) when both are sent; pre-existing precedence, preserved unchanged. In PR Acceptance notes."
    ],
    "gates": [
    {
    "command": "node scripts/check-adr-0087-registration.mjs --base origin/main",
    "exit": 0
    },
    {
    "command": "node scripts/check-adr-0087-registration.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-changeset-no-major.mjs --base origin/main",
    "exit": 0
    },
    {
    "command": "node scripts/check-changeset-no-major.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-ci-filter-parity.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-closing-keyword-parity.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-closing-keyword-parity.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-comment-mask-adoption.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-comment-mask-adoption.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-comment-mask-corpus.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-empty-changeset.mjs --base origin/main",
    "exit": 0
    },
    {
    "command": "node scripts/check-empty-changeset.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-issue-citations.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-keyed-text-bounds.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-keyed-text-bounds.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-platform-object-tenancy-census.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-platform-object-tenancy-census.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-plugin-teardown-shape.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-plugin-teardown-shape.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-registry-log-declared.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-registry-log-declared.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-rest-log-spy-declared.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-rest-log-spy-declared.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-system-context-census.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-system-context-census.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/check-undeclared-dep-imports.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/check-undeclared-dep-imports.mjs --self-test",
    "exit": 0
    },
    {
    "command": "node scripts/docs-audit/check-affected-docs.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/docs-audit/check-drift-comment.mjs",
    "exit": 0
    },
    {
    "command": "node scripts/pm/release-rehearsal-clone.mjs --self-test",
    "exit": 0
    },
    {
    "command": "pnpm --filter @objectstack/spec run check:duration-unit-keys",
    "exit": 0
    },
    {
    "command": "pnpm check:authz-resolver",
    "exit": 0
    },
    {
    "command": "pnpm check:changeset-gate-self-tests",
    "exit": 0
    },
    {
    "command": "pnpm check:cross-package-test-inputs",
    "exit": 0
    },
    {
    "command": "pnpm check:dispatcher-error-vocabulary",
    "exit": 0
    },
    {
    "command": "pnpm check:doc-authoring",
    "exit": 0
    },
    {
    "command": "pnpm check:driver-memory-census",
    "exit": 0
    },
    {
    "command": "pnpm check:dts-closure",
    "exit": 0
    },
    {
    "command": "pnpm check:dual-build-cjs-loads",
    "exit": 3,
    "reading": "NOT MEASURED — PREREQUISITE NOT MET (workspace closure unbuilt)"
    },
    {
    "command": "pnpm check:engine-double-contract",
    "exit": 0
    },
    {
    "command": "pnpm check:gitlink-declared",
    "exit": 0
    },
    {
    "command": "pnpm check:issue-citations",
    "exit": 0
    },
    {
    "command": "pnpm check:lean-entry-closure",
    "exit": 0
    },
    {
    "command": "pnpm check:logger-receiver-detach",
    "exit": 0
    },
    {
    "command": "pnpm check:nul-bytes",
    "exit": 0
    },
    {
    "command": "pnpm check:objectql-double-limit",
    "exit": 0
    },
    {
    "command": "pnpm check:objectui-changeset",
    "exit": 0
    },
    {
    "command": "pnpm check:org-identifier",
    "exit": 0
    },
    {
    "command": "pnpm check:page-declaration-shape",
    "exit": 0
    },
    {
    "command": "pnpm check:pm-changeset-deadline-census",
    "exit": 0
    },
    {
    "command": "pnpm check:published-files",
    "exit": 0
    },
    {
    "command": "pnpm check:query-options-erasure",
    "exit": 0
    },
    {
    "command": "pnpm check:refd-timer-probe",
    "exit": 0
    },
    {
    "command": "pnpm check:route-envelope",
    "exit": 0
    },
    {
    "command": "pnpm check:slot-lookup",
    "exit": 0
    },
    {
    "command": "pnpm check:sourcemap-no-sources-content",
    "exit": 0
    },
    {
    "command": "pnpm check:test-source-alias",
    "exit": 0
    },
    {
    "command": "pnpm check:tier-file-adoption",
    "exit": 0
    },
    {
    "command": "pnpm check:type-check-coverage",
    "exit": 0
    },
    {
    "command": "pnpm check:type-check-debt",
    "exit": 3,
    "reading": "NOT MEASURED — PREREQUISITE NOT MET (workspace closure unbuilt)"
    },
    {
    "command": "pnpm check:watch-hint-literal",
    "exit": 0
    },
    {
    "command": "pnpm check:where-matcher",
    "exit": 0
    },
    {
    "command": "pnpm lint (full union: eslint . --no-inline-config, at d07bbaa)",
    "exit": 0
    },
    {
    "command": "node scripts/check-issue-citations.mjs --base origin/main (after merging origin/main)",
    "exit": 0
    },
    {
    "command": "pnpm --filter @objectstack/rest exec vitest run --project local --maxWorkers=2 (at d07bbaa)",
    "exit": 0
    },
    {
    "command": "pnpm --filter @objectstack/rest run test:repo (at d07bbaa)",
    "exit": 0
    },
    {
    "command": "pnpm --filter @objectstack/rest run typecheck (at d07bbaa)",
    "exit": 0
    },
    {
    "command": "pnpm --filter @objectstack/rest build + require/import of dist (dual-build narrowing)",
    "exit": 0
    },
    {
    "command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran.list",
    "exit": 0
    }
    ],
    "files_changed": [
    ".changeset/20139-rest-query-number-census.md",
    "packages/rest/src/rest-server.ts",
    "packages/rest/src/rest-server-query-number-census.test.ts",
    "packages/rest/src/rest-server-query-number-reads.test.ts"
    ],
    "deviations": [
    "File surface beyond the claim's list (claim-surface supplement, declared here and in the PR body; all in rest-server.ts, outside both fences): the /diff door's from/to reads (a family member the census found — same class on the class-closure card; in-place-fix conditions ①–④ hold); UNDECLARED_ROW_COUNT_PARAM renamed UNDECLARED_WHOLE_NUMBER_PARAM with its docblock (touches the export and search limit call lines by name only); readDeclaredQueryNumber's docblock (refusal paragraph + census pointer; function body unchanged); the AuditMetaItemRequestSchema import.",
    "Clause-② line: the claim of record reads bare Clause-②: no while its prose names no (narrowing); the PR body and changeset carry Clause-②: no (narrowing) per the dispatch order and PR #20137's form (flagged, not silently chosen).",
    "Ablation B's first run was a no-op (its replacement contained the anchor; ablation-replace refused and restored, no test ran); re-anchored and re-run — the reported numbers are from the second run.",
    "Harness attribution reminder (a model-named Co-Authored-By trailer and a different PR footer) not followed: commits carry the order's model-free pair (Claude-Session + Co-authored-by: Claude), and the PR body ends with AGENTS.md's session-URL footer — reporting, per AGENTS.md.",
    "The os-dev-report comment was sent through the shared checkout's scripts/pm relay tools (node builtins only, read-only use) because the worktree had already been removed as the cleanup step."
    ],
    "line_budget": "n/a — no skills/** diff"
    }

  5. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #20345 at d07bbaa7, R3 of the domain:cli seat

    domain:cli execution PM seat #6024 · session session_01UYBdGBzWSrAMzpW8ah3GbP · review of record, written 2026-09-28T00:50Z

    Reviewed against GitHub and origin/main, not against the report.

    Checklist:

    • PR shape: draft, base main. The first line is Fixes #20139, the body's only closing keyword, followed by a line-initial Clause-②: no (narrowing). The claim line carries a bare no, as a claim line always does.

    • Scope: 4 files, none governed (check-governed-merges --pr 20345: NOT governed):

    • Fix: triage's direction (5830651452). Every remaining numeric query read in rest-server.ts goes through PR fix(rest): refuse a ?limit= the door cannot read on import jobs, export, meta history and search (#20061, #20062) #20137's readDeclaredQueryNumber:

      • /history ?sinceSeq and /audit ?limit against their z.number() declarations;
      • /search ?perObject, /approvals/requests ?limit/?offset and /diff ?from/?to as whole numbers.

      An unreadable value is refused with 400 VALIDATION_FAILED + fields[], and the service is never called. The rider is done: the publish route comment now names 404 NO_DRAFT.

    • The census classifies all 10 numeric coercions in the file through the TypeScript AST: reader, not-a-query-value, or exempt. It found /diff's parseV, one frame from req.query, which the card did not list. Two exemptions are ledgered and pinned:

      • export ?page=, which is chunk size only;
      • rollback toVersion, which is already refused before the verb.
    • Tests: 55 per-door rows, which were red first on the unfixed source (30 refusal rows answered 200), and 14 census cases. The ablations went red as predicted:

      • A (perObject back to a bare Number()): 5 red;
      • A′ (/diff back to parseV): 10 red;
      • B (a new bare Number(req.query.x)): the census alone went red.
    • CI on head d07bbaa7: 31 checks success by latest name, including TypeScript Type Check, all six Test Core shards, Lint & Repo Gates and Check Changeset. 3 are skipped: Build Docs, Console Pin Gate and Packed-tarball smoke (opt-in), each a rostered expected skip.

    • Contract review: at-tier, independent, PASS (5861415643).

    Decisions of record:

    Out of scope, Acceptance notes (not filed; each is outside the family or pre-existing):

    The review adds one note: zod's safe-int refusal maps to max_length in zodIssuesToFields. That is pre-existing since #20137, and its carrier is the spec seat's D3 mapper.

    Lane order: once this lands, #20320 (p3, the dispatcher's list divergences) takes the rest-server.ts fence. PR #20337 stays parked on #20290's decision.

    Next: landing through the relay ops pr_ready + automerge_enable.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 28, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #20345 → 329ea2e6fc9315cec8a79225d2b96a1bc6d76a81

    domain:cli execution PM seat #6024 · session session_01UYBdGBzWSrAMzpW8ah3GbP · landing record, written 2026-09-28T01:13Z


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsbugSomething isn't workingdomain:clipriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions