docs(spec): describe ack()'s post-#11859 refusal set in the DELIVERY_NOT_ELIGIBLE ledger gloss - #13508
docs(spec): describe ack()'s post-#11859 refusal set in the DELIVERY_NOT_ELIGIBLE ledger gloss#13508os-project-manager wants to merge 2 commits into
Conversation
…NOT_ELIGIBLE ledger gloss The INotificationOutbox.ack bullet enumerated a refusal set that #11859 widened: ownership joined the predicate (the (claimed_by, claimed_at) pair rides the record claim() returns), and both backends -- not only SqlNotificationOutbox -- raise the lost-claim refusal. Comment only. No code registered or removed, no wire value changes, no acceptance or refusal behaviour moves. Part of #12283
📓 Docs Drift CheckThis PR changes 1 package(s): 4 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 126 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 b1b2421f296993d2863f232b1df7d8310766d256 && git checkout b1b2421f296993d2863f232b1df7d8310766d256
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 0b9ad00256bfeba4dd78fa10553990cb06088ffc 453ac8d3f95b7fc58a0b1d6c3744c7f86778fd7b && git checkout -B drift-repro 0b9ad00256bfeba4dd78fa10553990cb06088ffc && git merge --no-ff 453ac8d3f95b7fc58a0b1d6c3744c7f86778fd7b
node scripts/docs-audit/affected-docs.mjs --json 0b9ad00256bfeba4dd78fa10553990cb06088ffc
|
|
Docs Drift Check — hand-checked, no drift. No docs edit needed. The four pages are listed via the broad
None restates the falsified claim — neither the "not
Generated by Claude Code |
Fixes #12283
⛔ Parked DRAFT on purpose — do not flip ready, do not enqueue, do not arm auto-merge. The diff lands on the contract-face path (
packages/spec/src/**), so the clause-② PATH limb fires:needs:contract-reviewis on both this PR and the card, and the review chain owns enqueue.What changed
Exactly one bullet of prose in
packages/spec/src/api/error-code-ledger.zod.ts— theDELIVERY_NOT_ELIGIBLE→INotificationOutbox.ackgloss — plus its changeset. No schema, shape, or code change; no new error code; no behaviour moves.The ledger states
DELIVERY_NOT_ELIGIBLE's refusal cases per surface, by enumeration. #11859 (PR #12282, ruled option C — the claim credential rides the recordclaim()returns andack()takes it back) widened that set on the notification surface, and two statements in the bullet stopped being the whole truth.Before
After
Premise re-verified against the merged code, not the card
The card's line numbers were stale (it measured at ~:530-536; the bullet sits at :572 on this branch head), so the bullet was re-located and every claim re-checked against the merged #11859 tree:
INotificationOutbox.ack's interface contract (packages/services/service-messaging/src/outbox.ts) states the precondition as two tests re-stated in the conditional write: the row isin_flight, AND its (claimed_by,claimed_at) pair equals the credential on the record handed back.MemoryNotificationOutbox.ackspells it asr.claimedBy !== claimed.claimedBy || r.claimedAt !== claimed.claimedAt, so a later claim'sclaimedAtrefuses the earlier claim's ack — including the same node's own re-claim.notificationAckNoCredentialMessageis raised before any read or write when the record carries no(claimedBy, claimedAt)pair.notificationAckNotClaimedMessage,notificationAckLostClaimMessage,notificationAckNoCredentialMessage) are defined once inoutbox.tsand raised by bothmemory-outbox.tsandsql-outbox.ts.packages/services/service-messaging/src/outbox-ack-claim-ownership.integration.test.tsrunsdescribe.each([memoryBackend(), sqlBackend()])overMemoryNotificationOutboxandSqlNotificationOutbox, including the case "the credential is the CLAIM, not the node: a stale ack loses to the same node's own re-claim."Same class and same route as PR #12089, which repaired the previous iteration of this exact bullet; this PR mirrors its shape (one ledger edit + one changeset, prose only).
Verification
All gates re-run on the final merged head
453ac8d3(aftergit merge origin/main, deps refreshed, spec rebuilt), each read from the gate's own printed verdict line — never a bare$?behind a pipe:pnpm --filter @objectstack/spec check:generated—✓ All 14 generated artifacts are up to date.pnpm check:error-code-casing—✓ no unlisted lowercase error codes in 5036 scanned file(s) (ADR-0112).pnpm check:dispatcher-error-vocabulary—check-dispatcher-error-vocabulary: OK — 51 unregistered code-stamping site(s), all classified; 1 awaiting a ledger entry (#8846).pnpm --filter @objectstack/spec typecheck—check:test-typecheck: OK(test layer compiles; 54 files / 262 errors held in the shrink-only debt ledger, unchanged by this diff)pnpm --filter @objectstack/spec test—Test Files 443 passed (443) · Tests 11811 passed (11811)Gate family derived mechanically with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(187 families discovered across 28 workflow files; change set read from the merge base, not a hand-built diff). The remaining derived families are repo-wide scans CI runs in full regardless; the ledger-specific ones are named above and were run here.Merged
origin/mainimmediately before finalizing, as the ledger is a cross-lane conflict magnet — six commits came in, none touching this file, and the branch's delta vsmainis still exactly the two intended files (41 insertions, 7 deletions).Generated by Claude Code