Repository navigation
fix(service-automation): get_record form descriptor's limit declares minimum 1 - #25441
Conversation
…minimum 1 The contract refuses a get_record limit below 1 at every flow save door; the designer form descriptor offered 0 and negatives. Declare minimum: 1 and pin the descriptor's floor against the contract's refusal boundary. Claude-Session: https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 6 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin ade0e4a6911bccda2ee70ceea922ca388c488b82 && git checkout ade0e4a6911bccda2ee70ceea922ca388c488b82
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 77392e901cce58316e803144971f2741ef049fc4 21ecd5680e82947292252d66b622af0fe8f6884f && git checkout -B drift-repro 77392e901cce58316e803144971f2741ef049fc4 && git merge --no-ff 21ecd5680e82947292252d66b622af0fe8f6884f
node scripts/docs-audit/affected-docs.mjs --json 77392e901cce58316e803144971f2741ef049fc4
|
席位核对 · ACCEPT · 2026-10-23T14:07Z
Generated by Claude Code |
Requested by Sales · project thread
Fixes #25361
Clause-②: no
Metadata-protocol: none
What
The
get_recordnode'slimitis a positive integer in the contract (GetRecordConfigSchema.limit,z.number().int().positive(), narrowed by PR #25357), so every flow save door refuses0, a negative or a fraction. The executor's form descriptor inpackages/services/service-automation/src/builtin/crud-nodes.tsstill declaredlimit: { type: 'integer', title: 'Limit' }, so the designer form offered values the save always refuses.limitnow declaresminimum: 1, the contract's floor.builtin/crud-nodes.ts. Nopackages/specedit, noengine.tsedit.builtin/is derived from its spec Zod today. Every descriptor is a hand-written literal, and the bounded siblings (loop.maxIterations,try_catch.retry.*) declareminimum/maximumby hand, so this follows that pattern.Pin
builtin-node-form-zod-ledger.test.tsgainsget_record.limit: the form's minimum is the contract's refusal boundary. It reads the descriptor'slimit.minimum(asserts1), then parsesGetRecordConfigSchemaat that boundary: the minimum is accepted, one below it is refused, and0is refused. Neither side can move alone.Measurement: other
builtin/descriptors against their contractsEvery numeric property in
builtin/descriptors was compared with its spec Zod at this tree:get_record.limitminimum: 1int().positive()loop.maxIterationsminimum: 1,maximum: LOOP_MAX_ITERATIONS_CEILINGint().min(1).max(LOOP_MAX_ITERATIONS_CEILING)try_catch.retry.maxRetriesint().min(0).max(10)try_catch.retry.backoffMs/maxRetryDelayMsminimum: 0int().min(0)try_catch.retry.backoffMultiplierminimum: 1min(1)http.timeoutMsz.number()(unbounded)screen.fields[].min/maxz.number()(unbounded)No other mismatch was found.
Verification (head
21ecd5680e)pnpm --filter @objectstack/service-automation typecheck && pnpm --filter @objectstack/service-automation test: lock VERDICT command-exit 0; Test Files 198 passed (198), Tests 2619 passed (2619).scripts/ablation-replace.mjs): the anchorminimum: 1was removed (anchor 1 to 0, blobb7d8ec771a76to5c181206f838). The new pin went red:AssertionError: expected undefined to be 1, 1 failed and 9 passed. The file was restored with blob == HEAD andgit diff HEADempty. The test importscrud-nodes.jsfromsrc, so nodist/hop is involved.dispatch-gates.mjs --commands, 67): 66 exit 0.check:dual-build-cjs-loadsexited 3 with PREREQUISITE NOT MET (no full-repodist/), so it is NOT MEASURED locally and is left to CI.Acceptance notes
Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_016g7nYP9wdNx1GDa5XDr7Uy