Repository navigation
error-code-ledger: @objectstack/driver-memory becomes an emitter of UNIQUE_VIOLATION with no provenance row — invisible to every gate, which is the point of the row #13254
Description
Activity
- addedpriority:p2Medium: important, M3Medium: important, M3
on Aug 29, 2026 os-project-manager commented
on Aug 29, 2026 CollaboratorMore actionsState correction (domain:spec seat,
session_01KX8wnyjStaZcuMyAMNsy3N, R1), two fixes in one stroke:-
pm:queue→pm:blocked. The card's own deliverable section says: "Land it after PR fix(driver-memory): enforce field-leveluniqueso a colliding write is refused, not landed #13249, which is what makes the claim true." PR fix(driver-memory): enforce field-leveluniqueso a colliding write is refused, not landed #13249 is OPEN (verified this hour), so a queue label would be telling the dispatch scan this card is startable when its ordering constraint is not yet satisfied. Machine-readable edge:([finding] driver-memory enforces no uniqueness, so an out-of-process duplicate autonumber lands SILENTLY and the write succeeds — the #5499 freeze that deferred the fix dissolved 2026-08-11 #13197 is the card PR fix(driver-memory): enforce field-level
uniqueso a colliding write is refused, not landed #13249 closes; when it lands, the unlock scan returns this card to the queue.) -
needs:contract-reviewremoved. Pre-emptive hanging on queue/blocked cards was abolished by the maintainer's 2026-08-28 ruling — the label attaches only when a reviewable contract increment EXISTS (a draft PR or an arrived report), and an open carrier must always mean one real pending review. The Clause-② fact is not lost: it lives in this card's own text, will be declared in the claim comment (Clause-②: yes), and the enqueue gate's PATH limb (packages/spec/src/**) catches the PR mechanically. The label returns when the draft PR exists.
No change to the ruling recorded in the body (option B, add the provenance row) — that stands.
Generated by Claude Code
-
os-project-manager commented
on Aug 30, 2026 CollaboratorMore actions🔓 解锁 · R+37 ——
pm:blocked→pm:queue上游已合并,并已在合并后 ref 现验。
Blocked-by: #13197—— #13197 已 CLOSED,其 PR #13249 于本轮 p0 解封的排空中落地为56c093c(fix(driver-memory): enforce field-leveluniqueso a colliding write is refused, not landed)。⭐ 现验读数(⛔ 不是"上游关了就放行" —— 本仓有 #8103 的先例)
在
origin/main上直接读码,确认本卡的前提已经从假设变成事实:packages/drivers/driver-memory/src/index.ts:29 UNIQUE_VIOLATION_CODE, packages/drivers/driver-memory/src/index.ts:30 UNIQUE_VIOLATION_STATUS, packages/drivers/driver-memory/src/memory-driver.ts:192 * arm-for-arm table): a colliding write is REFUSED — `code: 'UNIQUE_VIOLATION'`, packages/drivers/driver-memory/src/memory-unique-constraint.ts:92 * The wire identity of the refusal (ADR-0112). `UNIQUE_VIOLATION` is the … packages/drivers/driver-memory/src/memory-unique-constraint.test.ts:63-65 expect(err.code).toBe(UNIQUE_VIOLATION_CODE); … expect(err.code).toBe('UNIQUE_VIOLATION');⇒
@objectstack/driver-memory现在确实是UNIQUE_VIOLATION的发射者。 本卡标题里那个"becomes"已经发生,不再是前瞻。⚠️ 本席未能确认另一半(台账里没有 provenance 行)。本席的 grep 打在packages/spec/src/errors/上,零命中,但那个路径是猜的 —— ⛔ 一个打错路径的 grep 的零不是读数。执行者的第一件事是定位真正的台账文件再复验,⛔ 不得引用本席这个零。执行口径
- 卡正文里已记录的裁决(option B,补 provenance 行)不变。
- 条款② 的 PATH 限(
packages/spec/src/**)仍成立 ⇒ PR 停 draft 走合同复审;needs:contract-review按 2026-08-28 裁决在 draft PR 存在时才挂,⛔ 不预挂。 - ⭐ 本卡现在比阻塞前更紧要:发射者已上线而 provenance 行缺失,意味着当下就有一个无出处的错误码在线上。⛔ 但不升 p1 —— 它对任何门都不可见(这正是本卡自己的主张),没有在飞损害。
Generated by Claude Code
State correction (domain:spec seat, session
session_01KX8wnyjStaZcuMyAMNsy3N):pm:queue→pm:blocked— the R+37 unlock was right about #13197 but the card has a SECOND ordering constraint still standing.Blocked-by: #13182
Measured, not recalled: PR #13296 (the delivery for #13182, parked DRAFT in the contract-review chain, CI green on head
5a16c9e1) writespackages/spec/src/api/error-code-ledger.zod.ts— the same single-writer file this card's ledger append must write. Two open PRs on that ledger is the exact single-writer collision the hot-file discipline exists to prevent, so this card starts only after #13296 reaches main (the unlock scan should watch #13182). The #13197 leg stays satisfied; nothing else changes.
Generated by Claude Code
Claim: domain:spec seat (executive PM), dispatching to an os-dev subagent.
- Session:
session_01KX8wnyjStaZcuMyAMNsy3N - Branch:
claude/issue-13254-unique-violation-ledger-row - Worktree:
../objectstack-13254(worktree-first; no stash) - Domain:
domain:spec(the error-code ledger is this lane's single-writer file) - File surface:
packages/spec/src/api/error-code-ledger.zod.ts(driver-memory'sUNIQUE_VIOLATIONemitter entry, pure append in the package's own section) + regenerated ledger reference products + changeset. - Both ordering edges now satisfied, re-verified: [finding] driver-memory enforces no uniqueness, so an out-of-process duplicate autonumber lands SILENTLY and the write succeeds — the #5499 freeze that deferred the fix dissolved 2026-08-11 #13197 landed
56c093c(R+37 unlock's reading stands); ShouldREAD_BACK_FAILEDget a named wire row, asRESUME_FAILEDhas? The #12769 refusal currently rides an unmapped 500 #13182/PR feat(spec,rest): register READ_BACK_FAILED as a named wire row mapped in handleApprovalError #13296 — the other open writer of this ledger — merged 05:42Z, so the single-writer path is clear. Branch from current origin/main (must contain BOTH). - Container & model: dispatched at claude-opus.
--tierover the ledger: "no path-derived mandate… Clause ② SUSPECT surface —packages/spec/src/**— a hint, not a verdict." - Clause-②: content limb judged NOT firing — a ledger append registers an existing, already-landed refusal (the code's existence was ruled on the owning card; fix(driver-memory): enforce field-level
uniqueso a colliding write is refused, not landed #13249 made the claim true); it changes no accept/reject behaviour. The lane's pre-approved ledger-append class applies (pure append, own section, no shape/mechanism change). PATH limb FIRES ⇒ PR parks DRAFT withneeds:contract-reviewon both carriers; review chain owns enqueue.
Generated by Claude Code
- Session:
os-project-manager commented
on Aug 30, 2026 CollaboratorMore actionsDev claim (os-dev seat, dispatched by the domain:spec PM seat above).
- Session:
session_01KX8wnyjStaZcuMyAMNsy3N— the same session id the PM claim carries, because this seat is the os-dev subagent dispatched from it, not a second session. The identifying half is the branch below. - Branch:
claude/issue-13254-unique-violation-ledger-row(pushed empty as the first action, before any edit — write-route probe plus a landing marker for the claim). - Worktree:
../objectstack-13254, based onorigin/mainat881f8d8e. - Ordering edges re-verified on that base, not recalled:
git merge-base --is-ancestor 56c093c HEADreturns 0 (PR fix(driver-memory): enforce field-leveluniqueso a colliding write is refused, not landed #13249 / card [finding] driver-memory enforces no uniqueness, so an out-of-process duplicate autonumber lands SILENTLY and the write succeeds — the #5499 freeze that deferred the fix dissolved 2026-08-11 #13197 present), and5b3ff63c(PR feat(spec,rest): register READ_BACK_FAILED as a named wire row mapped in handleApprovalError #13296, card ShouldREAD_BACK_FAILEDget a named wire row, asRESUME_FAILEDhas? The #12769 refusal currently rides an unmapped 500 #13182 — the other open writer of this ledger) is the most recent commit touchingpackages/spec/src/api/error-code-ledger.zod.ts. Single-writer path is clear. - Scope: the pure append only — one owner key for
@objectstack/driver-memorynamingUNIQUE_VIOLATION, its regenerated reference products, and a changeset. No shape, mechanism, or other package's rows touched. Clause-②PATH limb fires (packages/spec/src/**), so the PR parks DRAFT withneeds:contract-reviewon both carriers; this seat does not flip it ready or enqueue.
Generated by Claude Code
- Session:
os-project-manager commented
on Aug 30, 2026 CollaboratorMore actionsos-dev-report
{ "issue": 13254, "status": "done", "branch": "claude/issue-13254-unique-violation-ledger-row", "pr": "https://github.com/objectstack-ai/objectstack/pull/13354", "premise_still_valid": true, "summary": "Both halves of the card's premise re-measured on origin/main at 881f8d8e (which contains 56c093c for the #13197 leg and 5b3ff63c for the #13182/PR-13296 leg): the ledger had no @objectstack/driver-memory owner key at all, and driver-memory really does stamp code UNIQUE_VIOLATION / status 409. Added exactly that one provenance row, placed beside @objectstack/driver-sql, in the comment form the file's existing rows use. No regeneration was owed and that is measured, not assumed: check:generated prints all 14 artifacts up to date, because the generated pages enumerate the deduped union and the union is unchanged. patch changeset on @objectstack/spec. PR 13354 parks DRAFT with needs:contract-review on both carriers, read back on both.", "tests": "All on final head 659abf77; heavy runs serialised through scripts/pm/os-verify-lock.sh; verdicts quoted from each gate's own line, never a piped $?. build (@objectstack/spec closure) exit 0, 'check-dts-emitted: 34/34 declared declaration file(s) present'. check:generated: 'All 14 generated artifacts are up to date.' check:dispatcher-error-vocabulary: 'OK - 22 unregistered code-stamping site(s), all classified; 1 awaiting a ledger entry (#8846)' (pre-existing, unrelated). check:error-code-casing: 'no unlisted lowercase error codes in 5010 scanned file(s)'. spec ledger pins (error-code-ledger + errors + contract + error-catalog-docs): 'Test Files 4 passed (4) / Tests 102 passed (102)'. driver-memory consumer run: 'Test Files 31 passed (31) / Tests 905 passed (905)'. spec typecheck exit 0. pnpm lint repo-wide (eslint . --no-inline-config), NOT narrowed, exit 0. check:nul-bytes OK over 7401 files. Gate family re-derived from the real diff via dispatch-gates.mjs --repo objectstack-ai/objectstack (2 paths, 34 families) and run: all green except three that measured NOTHING and say so themselves - check-dev-prereqs and check-doc-formula-expressions returned PREREQUISITE NOT MET on an unbuilt workspace (the latter re-ran green after building @objectstack/formula and @objectstack/lint), and check-test-completeness exited 3 with PREREQUISITE NOT MET, which its own text records as NOT MEASURED locally and not a finding. No ablation was performed: nothing here is a guard whose failure needs demonstrating.", "mcp_calls": "7", "open_questions": [], "out_of_scope_findings": [ "filed as #13353: five further packages stamp a registered error code their own ledger owner key does not list (plugin-webhooks/INVALID_REQUEST, cloud-connection/FORBIDDEN, cli/ENVIRONMENT_NOT_FOUND, trigger-api/INVALID_REQUEST, service-datasource/EXTERNAL_IMPORT_ERROR), four of them literal HTTP envelopes, plus one SDK-side sub-class (client/UPLOAD_SESSION_EXPIRED) - the sweep the card asked for, reported and not widened into this PR" ] }Premise readings (re-verified, not recalled)
The R+37 unlock comment explicitly declined to assert the missing-row half, having grepped a guessed path, and told the executor to locate the real ledger file first. Done, against
packages/spec/src/api/error-code-ledger.zod.tson881f8d8e:grep -n 'driver-memory\|UNIQUE_VIOLATION'over that file returns one line —250: 'UNIQUE_VIOLATION',, the@objectstack/restregistration. No@objectstack/driver-memoryowner key exists anywhere in the file. Premise confirmed.- Ordering edges, on the base rather than from the card:
git merge-base --is-ancestor 56c093c HEADexits 0 (PR fix(driver-memory): enforce field-leveluniqueso a colliding write is refused, not landed #13249 present), and5b3ff63c(PR feat(spec,rest): register READ_BACK_FAILED as a named wire row mapped in handleApprovalError #13296, card ShouldREAD_BACK_FAILEDget a named wire row, asRESUME_FAILEDhas? The #12769 refusal currently rides an unmapped 500 #13182) is the newest commit touching the ledger, so the other open writer of this single-writer file has landed.
Emitter evidence for the row's fields
Every field copied from landed code, nothing invented:
packages/drivers/driver-memory/src/memory-unique-constraint.ts:210—export const UNIQUE_VIOLATION_CODE = 'UNIQUE_VIOLATION';packages/drivers/driver-memory/src/memory-unique-constraint.ts:213—export const UNIQUE_VIOLATION_STATUS = 409;packages/drivers/driver-memory/src/memory-unique-constraint.ts:500-506—conflictRefusal(), the one place both declaration surfaces are stamped:err.code = UNIQUE_VIOLATION_CODE; err.status = UNIQUE_VIOLATION_STATUS;packages/drivers/driver-memory/src/index.ts:31-32— both constants re-exported from the package entry- Pinned by value on both surfaces,
codeandstatusthen the literal:memory-unique-constraint.test.ts:63-65,memory-declared-index-unique.test.ts:85-87
The entry
One new owner key
'@objectstack/driver-memory'listing the single code'UNIQUE_VIOLATION', placed immediately before'@objectstack/driver-sql'so the two drivers group. Its comment carries what the file's existing rows carry: the producer and its stamping function; the second-emitter note the header's "provenance, not identity" rule calls for (@objectstack/restregisters the same code for the SQL conflict, and the wire identity is deliberately the same so a suite swapping this driver for SQLite sees one envelope); and the wire-reachability argument in the shape@objectstack/driver-sql's own row makes, against the #8035 test the "Retiring a code" section applies. The file has no ordering constraint on owner keys or codes —error-code-ledger.test.ts's admission rules check casing, per-package duplication, standard-catalog shadowing, owner-key shape and the deduped-sorted-union identity, never order.Regeneration: nothing owed, and measured both ways
check:generated(after a real build, per the stale-dist caveat) prints "All 14 generated artifacts are up to date", each of the 14 individually green. That is the correct outcome rather than a skipped step, and it is confirmed independently:content/docs/references/api/error-code-ledger.mdxcontains no owner key at all — grepping it fordriver-sql,@objectstack/restandERROR_CODE_LEDGERreturns nothing — so the generated pages enumerate only the deduped union, which this append leaves byte-identical. Contrast5b3ff63c, which registered a genuinely new code and therefore did moveerror-code-ledger.mdxandcontract.mdxby one line each.Changeset
.changeset/driver-memory-unique-violation-provenance-row.md,patchon@objectstack/spec. Notminor: the exportedERROR_CODE_LEDGERvalue gains a key, butRegisteredErrorCode,REGISTERED_ERROR_CODESand theErrorCodeunion are unchanged, so no new vocabulary reaches any client. The5b3ff63cprecedent tookminorbecause it added a code.Clause-② posture
PATH limb fires (
packages/spec/src/**). PR #13354 is DRAFT andneeds:contract-reviewis on both carriers — written additively (RESTPOST .../labels, no read-modify-write window) and read back on both: PR #13354 now readssize/s, needs:contract-review, this card readspriority:p2, pm:dispatched, domain:spec, needs:contract-review. This seat did not flip the PR ready, did not enqueue it, and did not clear the label.The sweep the card asked for
Filed as #13353 rather than widened: five further packages stamp a registered code their own owner key does not list, four of them literal HTTP envelopes from the package's own route. The triage discarded prose matches, the ledger's own
STANDARD_SYNONYM_WAIVERStable, and the two cases the ledger already explains in writing (UPDATE_ID_MISMATCHstamped bymetadata-core,FLOW_DISABLED/FLOW_NO_START_NODEstamped byservice-automation— both recorded as deliberate "the door, not the producer, names the wire vocabulary" decisions). None of it is adjudicated in that card, and none of it is in this diff.
Generated by Claude Code
ACCEPT — domain:spec seat, session
session_01KX8wnyjStaZcuMyAMNsy3N. PR: #13354 (DRAFT, head659abf77, parked withneeds:contract-reviewon both carriers per the clause-② path limb).- Premise re-measured on a base containing both ordering edges: the ledger had no
@objectstack/driver-memoryowner key (single grep hit at :250 is rest's row), and the emitter stampsUNIQUE_VIOLATION/409 atmemory-unique-constraint.ts:210/:213/:500-506, value-pinned by two test files. Entry accepted as the lane's pre-approved pure-append class: one provenance row beside driver-sql, existing comment form, no shape/mechanism change. - No regeneration owed — measured, not assumed (
check:generated14/14 up to date; the generated pages enumerate the deduped union, which is unchanged). Patch changeset. Ledger pins 102/102, driver-memory consumer suite 905/905, repo-wide eslint un-narrowed exit 0. - Sweep finding correctly filed as [finding] error-code ledger: five more packages stamp a registered code with no provenance row — the #13254 class, swept #13353 (five packages stamping codes their owner key does not list) rather than widened into this PR; each row still needs the [finding]
MONGODB_MULTI_TENANT_UNSUPPORTEDmay be registered-but-unemittable in the error-code ledger — a boot refusal never reaches a wire envelope #8035 wire-reachability test — triage owns grading. - Review chain owns enqueue; this seat will not ready/arm.
Generated by Claude Code
- Premise re-measured on a base containing both ordering edges: the ledger had no
- added a commit that references this issue
on Sep 28, 2026
Raised by the #13197 os-dev as an open question rather than filed by it, because it is a deliberate, dispatch-mandated non-edit created by PR #13249 — so what was needed was a PM routing decision, not another card from the dev. Filing it here now that the decision is made.
The gap
packages/spec/src/**'serror-code-ledger.zod.tslists a code "once per emitting package — provenance, not identity". PR #13249 (card #13197) makes@objectstack/driver-memoryan emitter ofUNIQUE_VIOLATION— it now refuses a colliding write withcode: 'UNIQUE_VIOLATION',status: 409— and that package has no row.UNIQUE_VIOLATIONis already registered; union membership is whatApiErrorSchemaparses;check:dispatcher-error-vocabularyis green on #13249 (its own line: "OK — 22 unregistered code-stamping site(s), all classified", and the new throw site is not among them precisely because the code is registered). The ledger's admission rules check casing, duplication and shadowing — never who emits.So an unlisted emitter is invisible to every mechanism the repo has. The rows exist to answer "who produces this code?", and that question now has a wrong answer that nothing will ever flag.
Ruling: add the row (the dev's option B)
The dev offered three options and recommended B; I agree, and the reasoning for rejecting the other two is worth recording.
Not A ("leave it — nothing is red"). Tempting, and the strongest version of it is that the row is documentary. But the ledger's own doc comment gives the rows a job: they are how a reader finds every producer of a code. A silently unlisted emitter is the same class of drift the ledger exists to prevent, one grade quieter — and "one grade quieter" is what makes it survive, because nothing complains.
Not C ("fold it into #13249"). ⛔ Right regardless of the answer, and the dev's reason is the correct one: the
packages/spec/src/**exclusion was the dispatch's to set, and the tier change it implies is the PM's to make, not the dev's to absorb mid-card. A dev that quietly widened into spec because the change was small would have made the exclusion meaningless. It stopped and reported, which is what the stop condition was for.The deliverable's path limb is
packages/spec/src/**, so:Clause-②: yes;needs:contract-review, and that label stays through amode:subagentdispatch — ⛔ the review is not discharged by dispatching a higher-tier subagent to perform it;CONTRACT_REVIEW_TIERkeeps the label and waits rather than clearing it.That is the whole reason this is a separate card and not three lines on #13249: the change is genuinely tiny, and the tier it triggers is genuinely not.
Deliverable
Add the provenance row for
@objectstack/driver-memorynamingUNIQUE_VIOLATIONinerror-code-ledger.zod.ts, in the form the file's existing rows use. ⛔ Do not change the code's identity, its union membership, its casing, or any other package's rows.Worth checking while in there whether any other emitter added since the ledger's last sweep is missing a row; ⛔ report rather than widen if so.
Related
#13197 / PR #13249 (the change that creates the gap) · #13239 (the other follow-up from the same card)