docs(protocol): the 409 unique-constraint refusal is UNIQUE_VIOLATION on the wire; DUPLICATE_RECORD is the engine's in-process code - #15634
Conversation
… on the wire; DUPLICATE_RECORD is the engine's in-process code (#15362) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
|
HOLD (mirror of the ruling on #15362) — PM seat The docs change in PR #15634 (read against the three-dot diff: Option A. #15633 (the deriver gap) is graded PR #15634 is HELD as a draft until #15633 lands; then its dev (or a resumed one) merges Generated by Claude Code |
…ror-handling-unique-violation
|
ACCEPT — PM seat Reviewed against the three-dot diff at What the diff does (unchanged since the HOLD — the docs were correct all along): Measured by this seat on the PR head (plain That is the exact reading the #15633 dev's scratch leg (b) predicted and this seat's post-landing reading on Fences held: one docs file; Generated by Claude Code |
Fixes #15362
Docs-only.
content/docs/protocol/kernel/error-handling.mdxpublishedDUPLICATE_RECORDas a 409 wire code. No route emits that on the wire: the engine'sDuplicateRecordErroris translated at the REST door and every route answersUNIQUE_VIOLATION. The entry is renamed, the example body is replaced with the one the door actually emits, one sentence names the in-process code so a reader who seesDuplicateRecordErrorknows why it never appears on the wire, and the rate-limit snippet's comment is corrected the same way.Blocked on one decision — please read before reviewing
pnpm check:error-status-conformancegoes RED on this branch, and the remedy is outside a docs-only PR. Its verdict line:The runtime does emit
409 UNIQUE_VIOLATION— the gate's deriver cannot see it. Rule R5b inscripts/check-error-status-conformance.mjsmatches a mapper terminal with a body group whose contents are a negated character class excluding both brace characters, so nested braces disqualify the match. The real terminal inpackages/rest/src/error-response.ts(theDuplicateRecordErrorarm, line 992) builds its body with conditional spreads —...(field ? { field } : {})— so the pair straddles a nested brace and R5b skips it.driver-memory's producer is invisible for a different reason: it assignserr.code = UNIQUE_VIOLATION_CODE; err.status = UNIQUE_VIOLATION_STATUS;(packages/drivers/driver-memory/src/memory-unique-constraint.ts:504-505) rather than declaring an object literal, which no rule matches either.Neither remedy the gate offers belongs in this PR: extending the deriver is a gate-script change (and needs its own
--self-testcase), and the baseline path is maintainer-only and would record the opposite of the truth. Filed with the full derivation as #15633. This PR stays draft until that is graded.Tree evidence
The translation site —
packages/rest/src/error-response.ts,structuredCodeAnswer'sDuplicateRecordErrorarm:Its docblock states the ruling this page now matches:
The route test that pins the 409 body —
packages/rest/src/rest-duplicate-record-arm.test.ts, section 1:That is why the example body on the page is now flat with
error/code/field/objectrather than the page's nestedsuccess/error/detailsenvelope with adetails.valueecho: no route emitsdetails, and the door deliberately withholds the offending value (the driver's error stays oncause). The same flat body is already published atcontent/docs/protocol/kernel/http-protocol.mdx:757-762.Grep controls
DUPLICATE_RECORDUNIQUE_VIOLATIONorigin/main(6b8c67778)error-handling.mdx:349heading,:358example code,:950comment)git grepexit 1)476535c9a)error-handling.mdx:364, inside the in-process sentence only:349heading,:357example,:365sentence,:953commentVerification
Gate family derived from the tree, not by hand:
node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstack— 38 commands, all run at commit476535c9a(the branch head; exit codes captured before any pipe).pnpm check:error-status-conformancepnpm check:doc-anchorscheck-doc-anchors: 307 internal #fragment link(s) across 410 source file(s) all resolve to a real headingpnpm check:docs-single-h1405 page(s) under content/docs/ carry no body-level headingpnpm check:nul-bytesOK (scanned 7565 text file(s) ... no raw ASCII control bytes)pnpm check:doc-authoring14808 customer-facing string(s) across 756 spec sources cleanpnpm check:role-wordOK, no new occurrences of the reserved word(236 files, 2 roots)pnpm --filter @objectstack/spec run check:docs230 generated files in sync with packages/specpnpm --filter @objectstack/lint run check:doc-security-posture27 ObjectSchema.create example(s) in 227 marked block(s) ... validate-cleanpnpm --filter @objectstack/lint run check:doc-formula-expressions22 record-scoped formula example(s) across 428 files / 1371 TS blocks judged cleanpnpm --filter @objectstack/spec run check:skill-examples257 prose examples type-check across 3 surface(s)pnpm check:docs-audit-scopeNotes on the results that were not a first-pass measurement:
check:doc-formula-expressions,check:doc-security-postureandcheck:skill-examplesfirst exited 3 / 3 / 1 withPREREQUISITE NOT MET(unbuilt@objectstack/formula,@objectstack/lint,@objectstack/client-react). Those were NOT MEASURED, not findings; afterturbo run buildfor the three packages all re-ran green, as tabled.check:docs-audit-scopefirst reported✗ self-test "every contract declaration admitted is a packages/spec API declaration". Not this diff: the scanner walks the gitignored build artifactpackages/spec/.examples-build/and admits five transpiled doc examples there as contract declarations. With that directory absent — the state CI checks out in — the gate is green on this branch:✓ affected-docs self-test: 568 cases pass./✓ check-audit-scope self-test: 32 cases pass.(exit 0, measured both ways). Already filed ascheck:skill-examplesleavespackages/spec/.examples-build/behind, andcheck:docs-audit-scopethen fails its own self-test in the same working tree #15446.scripts/pm/dispatch-gates.mjsalso named 3 families whose argv carries a CI-only variable — NOT MEASURED here by construction:check-cross-package-test-inputs.mjs --union-into ...,check-shard-attestation.mjs --emit ...,check-test-completeness.mjs ....Scope
One file,
content/docs/protocol/kernel/error-handling.mdx. No code change, no changeset (skip-changeset: nothing is published from a package). Two adjacent items the card itself recorded as not measured are left alone and filed instead: the page-widesuccess/error/detailsenvelope, which no route emits either (#15632), andcontent/docs/api/error-catalog.mdx:355, which still listsDUPLICATE_RECORDunder Conflict Errors (409) with no note that the wire spelling differs (#15631). Out of scope here: #14723 is not re-litigated, and the deriver gap (#15633) is left open.Unblocked by #15633
The deriver gap that reddened
check:error-status-conformanceon this branch landed onmainon 2026-09-05 (PR #15656,f99dbcc45).origin/main(95d5cbb31) is merged into this branch — merge commit082626dc1ab6145f61c4e51faadb516c93bed4aa, a plain merge, no rebase and no force-push. The three-dot diff againstmainis unchanged by the merge: still the one file,content/docs/protocol/kernel/error-handling.mdx, 14 insertions / 14 deletions. Nothing in the docs prose was edited in this update.pnpm check:error-status-conformanceis now GREEN at the merged head (exit code captured before any pipe:EXIT=0). Its own lines, verbatim:UNIQUE_VIOLATIONis now inside the reconciled vocabulary rather than an unpinned documented code, which is exactly what the earlier RED verdict asked for and what this page's rename depends on.Derived family at the merged head
Re-derived on the merged tree, not carried over:
node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstackat commit082626dc1— 39 commands. All 39 exit 0. Exit codes were captured before any pipe; each command's output was redirected to its own file first.pnpm check:error-status-conformance✓ every derivable runtime status is documented, and every documented status is reachable.pnpm check:doc-anchorspnpm check:docs-single-h1pnpm check:doc-authoringpnpm check:corpus-claim-driftpnpm check:docs-transcript-drift@objectstack/lint(first run exited 3, PREREQUISITE NOT MET — not a finding)pnpm check:nul-bytespnpm check:docs-audit-scopepackages/spec/.examples-build/artifact noted in the section above was absent this runpnpm --filter @objectstack/spec run check:docsgen:schemaran as the first step of the spec build (first run exited 1 on the missing gitignoredpackages/spec/json-schematree — NOT MEASURED, not a finding)pnpm --filter @objectstack/spec run check:skill-examples257 prose examples type-check across 3 surface(s)— measured after building@objectstack/client-reactand@objectstack/clientpnpm --filter @objectstack/lint run check:doc-formula-expressions@objectstack/formulapnpm --filter @objectstack/lint run check:doc-security-posture@objectstack/lintEvery prerequisite exit (3, and the two gates that spell theirs as 1) was re-run to a real measurement after the missing build artifact was produced; none is reported here as a green it did not earn. The working tree was clean (
git status --porcelainempty) after every build, so no generated artifact rode along in this branch.Still NOT MEASURED here, by construction: the 3 families whose argv carries a CI-only variable (
check-cross-package-test-inputs.mjs --union-into ...,check-shard-attestation.mjs --emit ...,check-test-completeness.mjs ...), plus the always-runs workflow tail thatdispatch-gatesdoes not enumerate. Those are CI's to report.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code
Generated by Claude Code