Skip to content

docs(drivers): scope the reference_to refusal docblocks to the authoring face - #14489

Merged
os-musk merged 1 commit into
mainfrom
claude/issue-13851-reference-to-docblocks
Sep 2, 2026
Merged

docs(drivers): scope the reference_to refusal docblocks to the authoring face#14489
os-musk merged 1 commit into
mainfrom
claude/issue-13851-reference-to-docblocks

Conversation

@os-musk

@os-musk os-musk commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Fixes #13851

Comment-only. Two driver docblocks asserted that reference_to "is a REJECTED
ALIAS, not a normalised one". Since the field-reference-to-alias conversion
landed, that holds on the AUTHORING face only — stored sys_metadata
rehydration and os migrate meta now NORMALISE the key — so a reader was one
step from inferring "a stored reference_to stays verbatim forever" from a
driver comment. Both docblocks now scope the original assertion and quote the
split the conversion's own registry docblock already states. No behaviour, no
assertion, no public type, no gate scaffolding moved.

Wording source — quoted, not re-invented

packages/spec/src/conversions/registry.ts, fieldReferenceToAlias
(id: 'field-reference-to-alias', toMajor: 18, retiredFromLoadPath: true,
surface: 'field.reference_to' — all four read from the entry, confirming the
retiredFromLoadPath shape the card describes). Its docblock:

  • the entry "covers the two paths that serve or rewrite EXISTING data — stored
    rehydration and os migrate meta";
  • "The DDL doors above keep guarding the third path (metadata handed straight
    to a driver, around both the gate and the stored pass); they are downstream
    of this entry, not replaced by it."

Both edited docblocks quote those two clauses verbatim rather than paraphrasing
a parallel formulation.

Measured on this tree, before writing a word of it

FieldSchema from packages/spec built from this tree (packages/spec/dist/data/index.mjs):

input result
{ name:'parent', type:'lookup', reference_to:'p' } success:false, one issue, code = unrecognized_keys
{ name:'company_id', type:'lookup', reference_to:'company' } same
{ name:'company_id', type:'text', reference_to:'company' } same
reference_to valued 'company' / null / '' same, all three
{ type:'lookup', reference:'company', reference_to:'company' } same
{ name:'company_id', type:'lookup' } (no reference) success:false, code = custom, path ["reference"]
{ name:'company_id', type:'lookup', reference:'' } success:false, code = custom, path ["reference"]
{ name:'parent_id', type:'master_detail' } (no reference) success:false, code = custom, path ["reference"]
{ name:'company_id', type:'lookup', reference:'company' } success:true
canonical output own keys reference_to is NOT an own key

Two readings matter:

  1. The unrecognized_keys verdict is unchanged. The #13927 superRefine
    does not add a second issue to the reference_to fixtures — every rejected
    alias case still answers with exactly one unrecognized_keys issue. So the
    code blocks inside both docblocks, the "any type, any value" claim, and the
    complete-case-split argument next to the join-index arm are all still exact.
    Only the "not a normalised one" half needed a face named on it.
  2. The targetless-lookup claim flipped. { type:'lookup' } with no
    reference and { type:'lookup', reference:'' } are now REFUSED, where two
    driver comments record them as parsing successfully. That is the second
    instance folded into this card.

PR #13927 landed as commit 0fb8760be (subject: "require a non-empty
reference on lookup/master_detail fields"), an ancestor of origin/main; the refinement is the
[#13632] superRefine block added to packages/spec/src/data/field.zod.ts
(around the former line 1691), which is what produces the custom issue on the
reference path above.

Per-mention ledger — every reference_to mention on the declared surface

site verdict why
packages/drivers/driver-sql/src/sql-driver.ts (the #11567 docblock, now around :1488) CHANGED Carries "not a normalised one" unqualified. Assertion scoped to the authoring face; the two-face split appended, quoting the registry.
packages/drivers/driver-mongodb/src/mongodb-schema.ts (the #13222 docblock, now around :113) CHANGED Same sentence, same fix, plus one clause naming why the third path is exactly the one this driver sits on (syncSchema(object, schema: unknown) casts and forwards verbatim, with no Zod and no stored pass).
mongodb-schema.ts:40FieldDef.reference_to docblock NOT changed Its claims are "a REJECTED ALIAS of reference" and "FieldSchema answers unrecognized_keys for this key", plus a measurement that 'company' / null / '' draw one identical verdict. All three are authoring-face statements and all three re-measured true above. It makes no claim about data at rest, so the two-face split falsifies nothing in it.
mongodb-schema.ts:261 — the join-index arm comment NOT changed It is a historical statement about the pre-part-(2) arm at this seam: reference_to was refused at the door, so the old conjunct was unreachable. Re-measured true (every non-undefined value refused; undefined is falsy). The conversion runs on the stored and migrate paths, which never reach this arm, so it falsifies nothing here.
mongodb-13222-reference-to-refusal.test.ts header (:6) NOT changed "FieldSchema answers unrecognized_keys for it on any field type, carrying any value" — measured true, and a statement about FieldSchema is by construction about the authoring face only.
sql-driver-11567-lookup-no-foreign-key.test.ts NOT changed, not on the surface Read anyway: no "not a normalised one" sentence, and its one prose measurement ("0 FK constraints … before this change") is explicitly historical and still true.
.changeset/mongodb-lookup-index-canonical-reference.md:8 NOT changed Pending changeset text, authoring-face claim, true as written; editing a queued changeset is not this card.

Bounded in-place fix, declared

Two edits go past the card's literal two-docblock naming, both inside files
already on the claim's declared file surface, both the same defect class the
card is about (driver prose left behind by a spec tightening), both with the
correct shape pinned by the measurement above:

  1. mongodb-schema.ts, the FieldDef.reference docblock (around :66) —
    carried the exact same stale sentence as the second instance: { type: 'lookup' } with no reference and { type:'lookup', reference:'' } "both
    parse SUCCESSFULLY … a shape an author can really publish". Now records the
    refusal, names #13927, and keeps the truthiness conclusion on the reason
    that survives: the shape still reaches this arm because metadata gets here
    without meeting Zod at all.
  2. mongodb-13222-reference-to-refusal.test.ts, the last case's comment — the
    second instance named on the card, same refresh. No assertion changed:
    the test drives syncCollectionSchema directly, which is the seam that
    bypasses Zod, so the targetless-lookup case is still reachable and the
    expected index set is still exactly what the arm produces. It passes
    unchanged.

Neither edit touches code. Nothing else in sql-driver.ts was read or written
beyond the one docblock (the in-flight #13564 measurement reads that file).

Changeset — decided by measurement, not by assumption

Both packages publish (private absent; files: ["dist", "README.md", "CHANGELOG.md"]). Built both after the edit
(pnpm --filter @objectstack/driver-sql --filter @objectstack/driver-mongodb build,
after the dependency closure) and grepped the emitted artifacts for a phrase
unique to the new text, "authoring face and only the authoring face":

  • packages/drivers/driver-sql/dist/index.d.tsabsent
  • packages/drivers/driver-sql/dist/index.d.mtsabsent
  • packages/drivers/driver-mongodb/dist/index.d.tsabsent
  • packages/drivers/driver-mongodb/dist/index.d.mtsabsent
  • present only in dist/index.js.map / dist/index.mjs.map of both, via
    sourcesContent (stated for completeness: dist ships, so the sourcemap
    copy does travel — but it is not a type, not an API and not observable
    behaviour)

refuseRejectedReferenceAlias is module-private in both packages and FieldDef
is a non-exported interface, which is why nothing reaches the declaration files.
Neither docblock reaches dist/*.d.ts, so per the dispatched criterion this PR
takes the skip-changeset label rather than a patch changeset. Deferring to
Check Changeset / check-empty-changeset on CI if they read it differently.

Verification — union run AFTER the final commit, at f2884adc3

Gate family re-derived on the real change set:
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands
(stderr confirms it answered for objectstack-ai/objectstack at 9e286e248,
this checkout) — 3 paths, 28 commands. The dispatch's 36 included the 8
changeset-path families, which the script itself reports as "apply once this
card's changeset exists"; with skip-changeset there is no changeset path.

  • 25 of 28 green. Every exit code captured after a redirect, never through a pipe.
  • 3 answered NOT MEASURED (exit 3), in their own words — all three are
    prerequisite failures needing a full monorepo build, none is a finding:
    • node scripts/check-test-completeness.mjs — "Nothing was measured … ⛔ It is
      NOT a finding" (wants a saved turbo run test log).
    • pnpm check:dual-build-cjs-loads — "PREREQUISITE NOT MET — this gate reads
      built output, and some package has no dist/ … ⛔ This is NOT a pass".
    • pnpm check:type-check-debt — "39 workspace dependenc(ies) … have no built
      type entry point on disk … ⛔ This is NOT a pass and NOT a finding".
  • Always-runs, all green: pnpm lint (full repo, eslint . --no-inline-config,
    exit 0, no narrowing claimed), pnpm check:nul-bytes
    ("OK (scanned 7913 text file(s) … no raw ASCII control bytes)"),
    pnpm check:error-status-conformance ("✓ every derivable runtime status is
    documented, and every documented status is reachable").
  • pnpm --filter @objectstack/driver-sql typecheck and
    pnpm --filter @objectstack/driver-mongodb typecheck — both exit 0.
    ⚠️ NOT MEASURED for the edited test file: driver-mongodb's tsconfig excludes
    **/*.test.ts, so that typecheck says nothing about
    mongodb-13222-reference-to-refusal.test.ts. The vitest run below is what
    covers it.
  • pnpm --filter @objectstack/driver-mongodb exec vitest run --maxWorkers=2 src/mongodb-13222-reference-to-refusal.test.ts src/mongodb-schema-declared-indexes.test.ts — "Test Files 2 passed (2) ·
    Tests 16 passed (16)", assertions untouched.
  • Lane's standing conformance reading, both lines quoted and identical:
    • before the first edit: check-driver-conformance: OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt.
    • after the final commit: check-driver-conformance: OK — 50 covered cell(s), 0 in the DEBT ledger, 0 exempt.

No ablation is owed: the change is comments only.

Clause-② self-reading: no. Comments only — no accept/reject behaviour, no
public type, no gate moves. The diff is three files, +50/-15, every line inside
a comment or docblock.

🤖 Generated with Claude Code

https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68


Generated by Claude Code

…oring face

The SQL DDL door (#11567) and the Mongo schema-sync door (#13222) each assert
that `reference_to` "is a REJECTED ALIAS, not a normalised one". After the
`field-reference-to-alias` conversion landed, that is true on the AUTHORING
face only: stored `sys_metadata` rehydration and `os migrate meta` now
NORMALISE the key. Left as written, the next reader infers "a stored
`reference_to` stays verbatim forever" from a driver comment, which is false.

Both docblocks now scope the original assertion to the authoring face and
quote the split the conversion's own registry docblock already states, rather
than inventing a parallel formulation.

Two prose measurements in driver-mongodb that a later spec tightening left
behind are refreshed in the same stroke: `{ type: 'lookup' }` with no
`reference` and `{ type: 'lookup', reference: '' }` no longer "parse
successfully" — the superRefine added on the relationship types refuses both
with `custom` on the `reference` path. The shape still reaches the join-index
arm, because `syncSchema(object, schema: unknown)` casts and forwards verbatim
with no Zod, so no assertion changes.

Comments only: no behaviour, no assertion, no public type. Card #13851.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68
@github-actions github-actions Bot added the size/s label Sep 2, 2026
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 2 changed package(s); no hand-written page names any of them. ⚠️ 1 changed file(s) yielded no anchor (packages/drivers/driver-sql/src/sql-driver.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/drivers/driver-sql/src/sql-driver.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 9 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json e5812fa435d27bd103afeec442bf7d420a28f8d6packageMentionDocs.

Which tree this was computed on

This run read content/docs from 28b21226bd3ad460f9b8df21c59db6b0fa0160c5 — the merge of head f2884adc328fd9544127feb3f8403a527d0187b1 into base e5812fa435d27bd103afeec442bf7d420a28f8d6, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 28b21226bd3ad460f9b8df21c59db6b0fa0160c5 && git checkout 28b21226bd3ad460f9b8df21c59db6b0fa0160c5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e5812fa435d27bd103afeec442bf7d420a28f8d6 f2884adc328fd9544127feb3f8403a527d0187b1 && git checkout -B drift-repro e5812fa435d27bd103afeec442bf7d420a28f8d6 && git merge --no-ff f2884adc328fd9544127feb3f8403a527d0187b1

node scripts/docs-audit/affected-docs.mjs --json e5812fa435d27bd103afeec442bf7d420a28f8d6

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

os-musk commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Landing provenance (engine execution seat, session_0112hMx9hjJ9BgB28X97DS68) — flipped to ready and auto-merge (squash) armed at 09:42Z on head f2884adc3.


Generated by Claude Code

@os-musk
os-musk added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit 7251bdb Sep 2, 2026
39 checks passed
@os-musk
os-musk deleted the claude/issue-13851-reference-to-docblocks branch September 2, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants