Skip to content

objectql's engine docblock still states the RETIRED per-row previous rule — and it ships in the published .d.ts, so the next spec release makes two packages state opposite contracts #17975

Description

@os-bill

Two published packages are about to state opposite rules about the same contract, and one of them ships the wrong one inside its .d.ts.

Filed by the domain:spec execution seat, session session_01MkQhmuuJAVDjmeWNixwDDH, 2026-09-13T08:57Z, out of the at-tier post-hoc contract review of merged PR #17249 (record on that PR, Served-tier: 112/112 claude-fable-5-1). ⛔ No domain:* or priority:* applied — routing and grading are triage's.

⏰ This has a deadline: before the next @objectstack/spec release

PR #17249 rewrote the contract on ctx.previous for a multi: true bulk write, per ruling #16074: a per-row previous-conditioned, same-key-set, in-place rewrite is now admitted, where the old text said previous was there "not so a rewrite can be aimed". That changeset is unconsumed — the new rule has not shipped yet.

Two sites on origin/main still state the retired rule, in the present tense:

  • packages/objectql/src/engine.ts:3448-3451 — the docblock of private async dispatchPerRowBeforeHooks
  • packages/objectql/src/bulk-write-per-row-hooks.test.ts:570 — a test comment

⇒ the moment @objectstack/spec releases, @objectstack/spec says the shape is admitted and @objectstack/objectql says it is not.

Why the private docblock is not an internal comment

⚠️ JSDoc on a private member survives .d.ts emit. Measured in the already-shipped @objectstack/objectql@17.4.0: the retired sentence is present in 6 dist files, including dist/util-*.d.ts:3554.

So this is not "a stale comment in our source". It is published text on an npm package, which every consumer's editor surfaces on hover, and it contradicts the contract the sibling package declares. An author who writes the in-place rewrite the ruling admits will be told by their own tooling that it is out of contract.

Reading, with controls

git grep on origin/main for the fragment not so a rewrite → 8 hits. Six are legitimate: the changeset (quoting the old text), docs/adr/0058-*.md:236 (a dated record carrying a forward pointer), and four CHANGELOG history lines. The two named above are the live restatements. Control terms lit: ROW-INVARIANT-IN-EFFECT 3 files, MULTI_UPDATE_HOOK_KEY_DIVERGENCE 28 files.

Conforming implementations already exist and are correct — the three provenance stamps (email-template-provenance.ts:88-91, sharing-rule-provenance.ts:77-80, webhook-provenance.ts:79-82) all assign in place. So the code follows the new rule and only the prose lags, which is exactly the failure that goes quietly wrong instead of red.

The repair

Refresh both sites to the #16074 ruling: row-invariant-in-effect, in-place assignment admitted, key divergence refused. Docs-only; no changeset owed unless the .d.ts text is treated as published surface — in which case patch.

⚠️ PR #17249's own body disclosed both sites and marked them 「承接者:无」, and the at-tier delta review said "File at ACCEPT, objectql lane". Neither produced a card. That is why this one exists: an acceptance note with no named carrier is not a disposition.


Generated by Claude Code

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions