Skip to content

feat(spec): declare record:details section headerColor as a closed six-token enum - #12616

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-12126-headercolor-enum
Aug 26, 2026
Merged

os-zhuang merged 4 commits into
mainfrom
claude/issue-12126-headercolor-enum

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Fixes #12126

Implements maintainer ruling A (2026-08-26, issue comment 5419726057, verbatim provenance 「其他接受你的建议」): declare headerColor on the strict record:details section schema as a closed z.enum over exactly the six tokens objectui#6294 ships.

What changed

Sanity check the ruling delegated

Read objectui/packages/plugin-detail/src/headerColor.ts at objectui origin/main (read-only): its HEADER_COLOR_CLASSES lookup ships exactly muted, muted/50, accent, primary/10, secondary/10, destructive/10 — the enum matches the module one-to-one, and the module's own header states the tints-only reasoning (CardHeader sets no foreground; solids would need a paired text-foreground class, left to the pass-through). No vocabulary adjustment needed, no shape question raised.

The renderer's bg-* pass-through is deliberately NOT declared: it renders only when the host app's Tailwind build happens to generate the class — the capability-illusion shape the old refusal existed to prevent, and ruling A explicitly rejects option B (open string).

Guidance/alias machinery

Checked per the dispatch card: the strict section schema carries NO curated headerColor guidance or alias entry (grep over packages/spec/src — the only headerColor occurrences were the zod comment and the pin test), so there is nothing to remove for the #5013 alias-integrity audit; pnpm check:spec-parsed-alias is green (its verdict line: "ADR-0122 type-alias convention: ... OK").

Verification (union re-run at final head 342070617, tree clean; every command through scripts/pm/os-verify-lock.sh, exit codes captured before any pipe)

  • pnpm --filter @objectstack/spec build — green (check-dts-emitted: 34/34 declared declaration file(s) present).
  • pnpm --filter @objectstack/spec test435 files / 11525 tests passed (vitest summary line: Tests 11525 passed (11525)).
  • pnpm --filter @objectstack/spec typecheck — green, including the test layer: check:test-typecheck: OK — @objectstack/spec's test layer compiles under packages/spec/tsconfig.test.json (the edited test file is covered by that program and is not a debt-ledger entry).
  • Reverse verification (from the committed state at 410f85825; restore via git checkout HEAD -- path, proven by empty git diff HEAD): with component.zod.ts reverted to base d7b3963c2 (mutation confirmed on disk: grep -c "headerColor: z.enum" = 0) and the new tests kept, both new pins turned RED as predicted — the accept test on the unrecognized key, the reject test on the issue-code mismatch — and back green on restore. Direction observed: turned red (the normal direction).
  • pnpm --filter @objectstack/spec check:authorable-surface — green at 342070617; its own verdict: authorable-defaults/ verified against upstream 7a25e7d606b7 — 1255 default(s) unchanged; the base-anchor lag line is printed by the check as informational, not an error.
  • pnpm --filter @objectstack/spec check:generated — green at 342070617: ✓ All 14 generated artifacts are up to date. (An earlier run pre-merge proved api-surface/ stale — dist mtime vs the reverse-verification leg, the same shape the record:details sections: five more renderer-honoured keys remain undeclared by the strict section schema (title / defaultCollapsed / icon / description / headerColor) #11661 batch recorded; rebuilt and regenerated byte-identical, zero tracked-file diff.)
  • Derived gates (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, change set taken by the script from merge-base), re-run at 342070617: check:spec-parsed-alias (ADR-0122 ... OK), check:engine-double-contract (OK — 689 pinned, 134 in the DEBT ledger, 3 exempt), check:where-matcher (303 matcher(s) ... answer the combinator battery correctly or refuse it loudly), check:query-options-erasure (ratchet holds ... none new), check-nul-bytes (OK — scanned 6978 text file(s)). Declared narrowing: the remaining derived families (docs-family checks, CI-filter parity, etc.) are left to CI, which runs the farm on every PR; check:type-check-debt needs the full workspace closure built and the edited test file sits in an existing tsc program with no ledger entry, so the edit cannot move its per-entry counts.

Landing-watch

Both watched PRs landed mid-flight and were merged in, each followed by a full union re-run (build, full spec suite, typecheck, check:generated, check:authorable-surface, ratchet gates): #12614 (spec ui/action.zod.ts + plugin-security) merged at 533fc01b1, then #12613 (kernel CLICommandContributionSchema retirement) merged at final head 342070617. origin/main re-fetched after the final push: no further commits.

The @object-ui/types mirror narrowing is the objectui leg — zero objectui edits here; the PM files that follow-up card.

Stops at DRAFT per the dispatch contract (clause-② contract review; no ready-flip, no auto-merge).

Generated by Claude Code

claude added 3 commits August 26, 2026 22:17
…x-token enum

The #11661 refusal's recorded reason (template-literal Tailwind read
generating no CSS) was repaired by objectui#6294's literal-class lookup;
maintainer ruling A (2026-08-26) declares the key as z.enum over
exactly the six tokens that lookup ships: muted, muted/50, accent,
primary/10, secondary/10, destructive/10. Declared = enforced — values
outside the enum (including bg-* pass-through spellings) are refused at
authoring time instead of shipping a header that silently does not paint.
Optional, no schema default; the title withhold stands and its pin flips
consciously, as its own comment anticipated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xGvxcwPRTJfA7RfjXEYA4
gen:docs wrote this page; gen:schema produced no tracked-file changes
(authorable-surface.base.json lags by design — baseRev allowance).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012xGvxcwPRTJfA7RfjXEYA4
@github-actions

github-actions Bot commented Aug 26, 2026

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
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • 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 — 126 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 7a25e7d606b7694f6bbd6bcc226bec33f546c370packageMentionDocs.

Which tree this was computed on

This run read content/docs from cafdc0e170ab373242e3d4c21032c329abdce286 — the merge of head 34207061784416df3dccd315d4b725ff73f76b0c into base 7a25e7d606b7694f6bbd6bcc226bec33f546c370, 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 cafdc0e170ab373242e3d4c21032c329abdce286 && git checkout cafdc0e170ab373242e3d4c21032c329abdce286
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7a25e7d606b7694f6bbd6bcc226bec33f546c370 34207061784416df3dccd315d4b725ff73f76b0c && git checkout -B drift-repro 7a25e7d606b7694f6bbd6bcc226bec33f546c370 && git merge --no-ff 34207061784416df3dccd315d4b725ff73f76b0c

node scripts/docs-audit/affected-docs.mjs --json 7a25e7d606b7694f6bbd6bcc226bec33f546c370

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:ui tests tooling labels Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/m tests tooling

Projects

None yet

2 participants