Skip to content

fix(objectql): sync IntrospectedColumn.isUnique consumer docblock to the producer's PRIMARY KEY exclusion - #12035

Merged
os-warren merged 1 commit into
mainfrom
claude/issue-11826-introspected-isunique-consumer-sync
Aug 25, 2026
Merged

fix(objectql): sync IntrospectedColumn.isUnique consumer docblock to the producer's PRIMARY KEY exclusion#12035
os-warren merged 1 commit into
mainfrom
claude/issue-11826-introspected-isunique-consumer-sync

Conversation

@os-warren

Copy link
Copy Markdown
Collaborator

Fixes#11826

Prose-only sync of the consumer-side IntrospectedColumn.isUnique docblock in packages/objectql/src/util.ts to the producer's current contract sentence in packages/drivers/driver-sql/src/sql-driver.ts (SqlDriver's IntrospectedColumn.isUnique). No behaviour change, no export change, no test change.

What the producer says now (added by #11654)

A PRIMARY KEY is NOT a unique constraint to this flag (#11654), on any
dialect and for any key type. `isUnique` means a *declared* single-column
UNIQUE constraint; key membership has a lossless face of its own
({@link IntrospectedTable.primaryKeys} and `primaryKey` below), so
excluding keys keeps the two flags non-overlapping and drops no fact. Note
this is a statement about what KIND of constraint the flag reports, never
a claim that a key column admits duplicates. A key column that separately
carries its own single-column unique constraint is still flagged — the
constraint is what is being reported, not the column.

What the consumer copy said before (drift)

The consumer copy had no PRIMARY KEY clause at all — it still read as though isUnique could include a PK, which is exactly the reading #11654 retired on the producer side:

Whether this column ALONE carries a single-column unique constraint —
true iff some unique constraint covers this column and nothing else.
Membership of a COMPOSITE constraint is deliberately not represented
(#11202): `UNIQUE (a, b)` constrains the pair, and a per-column boolean
cannot say that. The producer's declaration —
`SqlDriver`'s `IntrospectedColumn.isUnique` in `@objectstack/driver-sql`
— is the contract sentence; this is the consumer-side copy of the same
key and must not drift from it. An absent flag on a composite member
means "not single-column unique", never "no constraint".

The fix

Appended the producer's PRIMARY KEY paragraph (transfers essentially verbatim — {@link IntrospectedTable.primaryKeys} resolves to this same file's own IntrospectedTable.primaryKeys declaration, and primaryKey is inherited from the same spec contract on both sides) to the consumer's isUnique docblock, immediately after the still-accurate composite paragraph. The composite paragraph (#11202) was left untouched — it had not drifted.

Deliberately NOT copied: the producer's closing paragraph ("All three dialect arms of {@link SqlDriver.introspectUniqueConstraints} produce it through one predicate — see {@link singleColumnUniqueColumns}."). That paragraph is producer-internal implementation provenance (its @links name SqlDriver-only symbols that do not exist in @objectstack/objectql), predates #11654 entirely (confirmed via git show on the #11654 commit — it was not touched), and was never part of the consumer's mirrored text before. It is not "the contract sentence."

Second copy in the same docblock — checked, not touched

IntrospectedForeignKey.referencedSchema at util.ts:70-86 carries the identical "must not drift" clause, mirroring SqlDriver's IntrospectedForeignKey.referencedSchema. Compared both sides line by line: not drifted. Both landed together in #11906 and the producer side has had no edit since (git log 0010797373..HEAD -- packages/drivers/driver-sql/src/sql-driver.ts shows one unrelated commit, #11785, touching boolean aggregate casting — no referencedSchema lines). Negative reading, no action, no card filed.

Tests

No behaviour change — introspectedSchemaToObjects/convertIntrospectedSchemaToObjects is unmodified, only a TSDoc comment moved. No ablation is owed for a prose-only change; the package suite is the regression check:

  • pnpm --filter '@objectstack/objectql^...' build — dependency closure, exit 0.
  • pnpm --filter @objectstack/objectql testTest Files 232 passed (232), Tests 4117 passed (4117), exit 0.
  • pnpm --filter @objectstack/objectql typechecktsc --noEmit && tsc --noEmit -p tsconfig.scripts.json, exit 0.
  • node scripts/check-nul-bytes.mjsOK (scanned 6665 text file(s) ... no raw ASCII control bytes), exit 0.

Gate union derived from the actual diff (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack), re-run at the final commit 8b58aa7304 — same single-path change set both times, same 9 matched families. All 9 run in the foreground, each EXIT=0 captured before any pipe:

check:durability-log-level, check:published-files, check:slot-lookup, check:test-source-alias, check:type-source-resolution, check-engine-split-ratio.mjs (report-only, 97.6%), check-plugin-teardown-shape.mjs, docs-audit/check-affected-docs.mjs, docs-audit/check-drift-comment.mjs.

skip-changeset per triage grading — no behaviour, no export. check:empty-changeset's own self-tests (GREEN 3) confirm a PR with no changeset and the skip-changeset label is exactly what that gate expects to see, so no changeset was written.


Generated by Claude Code

…the producer's PRIMARY KEY exclusion (#11826)
The consumer-side copy of `IntrospectedColumn.isUnique` in
packages/objectql/src/util.ts declares it "must not drift" from the
producer's contract sentence (`SqlDriver`'s `IntrospectedColumn.isUnique`
in @objectstack/driver-sql). #11654 added a PRIMARY KEY exclusion clause
to the producer's sentence; this copy had not been synced.
Prose only — introspectedSchemaToObjects/convertIntrospectedSchemaToObjects
is unchanged, and the package's own test fixture already modeled a key
column as { primaryKey: true } with no isUnique, so the data already
agreed with the new convention.
Checked the docblock's second "must not drift" copy
(IntrospectedForeignKey.referencedSchema) against its producer too — not
drifted, no action needed.
skip-changeset: no behaviour, no export.
Claude-Session: https://claude.ai/code/session_01W6HFzyH98W1YaQXhJUJt6o
Co-authored-by: Claude <noreply@anthropic.com>
@os-warrenos-warren added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/s labels Aug 25, 2026 — with Claude
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to listnot a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • 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 — 14 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 1e79aa4f812708d5d097ca33d9b7040e02b958c6packageMentionDocs.

Which tree this was computed on

This run read content/docs from 2014b85ec21c93acf5de15dfb8e77e6c41407dc6 — the merge of head 8b58aa7304c5e921ae43d995945cf819ed5435c5 into base 1e79aa4f812708d5d097ca33d9b7040e02b958c6, 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 2014b85ec21c93acf5de15dfb8e77e6c41407dc6 && git checkout 2014b85ec21c93acf5de15dfb8e77e6c41407dc6
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 1e79aa4f812708d5d097ca33d9b7040e02b958c6 8b58aa7304c5e921ae43d995945cf819ed5435c5 && git checkout -B drift-repro 1e79aa4f812708d5d097ca33d9b7040e02b958c6 && git merge --no-ff 8b58aa7304c5e921ae43d995945cf819ed5435c5
node scripts/docs-audit/affected-docs.mjs --json 1e79aa4f812708d5d097ca33d9b7040e02b958c6

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

@os-warren
os-warren marked this pull request as ready for review August 25, 2026 08:13
@os-warren
os-warren added this pull request to the merge queueAug 25, 2026
Merged via the queue into main with commit 3b9da58Aug 25, 2026
38 checks passed
@os-warren
os-warren deleted the claude/issue-11826-introspected-isunique-consumer-sync branch August 25, 2026 08:31
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[finding] objectql's consumer copy of IntrospectedColumn.isUnique under-specifies it after #11654 excluded PRIMARY KEYs

2 participants

@os-warren@claude