Skip to content

fix(spec): page.print and the flow terminal-toast translations read live in the liveness ledger, so a print page is no longer warned that nothing applies it - #23776

Merged
objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-23710-liveness-print-flow-messages
Oct 16, 2026
Merged

objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-23710-liveness-print-flow-messages

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #23710
Clause-②: no

The console at the .objectui-sha pin (f96f771140f1) prints a page that declares print and shows the translated flow terminal toasts. The liveness ledger still graded both planned, so lintLivenessProperties told every author of a print page that printing it prints the screen layout. This PR flips those verdicts to live, citing each objectui reader at the pin, drops print's authorWarn, and rewrites PagePrintSchema's describes, which said "until it ships, nothing applies it". The accept set does not change. The parentDataSource leg stays with #23585.

Evidence per flipped verdict (objectui re-read at f96f771140f1, the pin this lands against)

Each reader's landing commit is an ancestor of the pin: git merge-base --is-ancestor 2312bd9a6 f96f771140f1 gives exit 0 (objectui#11958), and git merge-base --is-ancestor 42d8e8db6 f96f771140f1 gives exit 0 (objectui#12075). Both were read in a full, non-shallow objectui clone.

page.json props.print: 13 rows, all read, all flipped. That is the container, its 8 keys, and the 4 margins sides. The card counted 12 children, because margins is both a key and a container. No row stays planned.

Row Reader at the pin
print (container) packages/components/src/renderers/layout/page.tsx#PageRenderer mounts buildPagePrintStylesheet(print) as a style element, only when schema.print is an object, and stamps the page root with PRINT_PAGE_ATTRIBUTE. The refusals stay cited as before: the spec's checkPagePrintComposition and lint's validatePrintPageBlocks.
paperSize, orientation page-print.ts#buildPagePrintStylesheet writes @page { size } through pageRule, and only for an enum member.
margins and margins.top / .right / .bottom / .left pageRule writes one margin-SIDE: Nmm for each declared finite, non-negative side.
pageNumbers pageRule writes the @bottom-right margin box with counter(page) / counter(pages).
repeatHeader, repeatFooter page.tsx#RunningRegions puts the region in a real thead / tfoot. runningRegionRules turns that table back into a table on paper.
repeatTableHeaders thead { display: table-header-group }, or table-row-group when the key is false.
avoidBreakInside break-inside: avoid on every block of a region.

translation.json flows.successMessage / flows.errorMessage. packages/app-shell/src/utils/flowResponse.ts#translatedFlowMessage calls the spec's translateFlow for flows.FLOW.KEY and falls back to the served string. interpretFlowResponse (the terminal-success arm) and flowFailureMessage call it. views/FlowRunner.tsx#FlowRunner passes the run's flow name and bundle. The spec-side evidence in each row is unchanged.

authorWarn / authorHint are dropped from print in the same edit, because check:liveness refuses them on a live row. With that, no shipped ledger row opts into authorWarn any more: print was the last one.

Describes (packages/spec/src/ui/page.zod.ts)

Only text changed: the 8 key describes, PageSchema.print's describe, the PagePrintSchema docblock, the print property's docblock, and the section comment above the printable subset. Each one now names the console's browser print rendering as the consumer that applies the key. The server-side PDF renderer (card ③) is still "to follow". No schema shape, enum, alias or refinement was touched. check:authorable-surface is in the gate run below.

Pins

  • packages/lint/src/lint-liveness-properties.test.ts
  • packages/spec/scripts/liveness/check-liveness.test.ts: the census control asserted that the shipped walk reaches at least one warned row, which was print. The reach is now proved on a copy with one shipped planned row marked authorWarn: the gate stays green and the census counts exactly one more row.

Generated

content/docs/references/ui/page.mdx, liveness/state-counts/page.md (planned 11 → 0) and liveness/state-counts/translation.md (planned 2 → 0) were regenerated with gen:docs and gen:liveness-counts. Those are the two that check:generated proved stale. Nothing was hand-written in them.

Verification (head 6375c0cb15)

  • pnpm --filter @objectstack/spec test: 679 files, 20,756 passed, 1 todo, exit 0. Run under os-verify-lock on head 6375c0cb15.
  • pnpm --filter @objectstack/lint test: 139 files, 6,767 passed, 5 skipped, exit 0. Run on d03703eb. The lint package has not changed since; the only later commit edits a spec script test.
  • typecheck exit 0 for @objectstack/lint (tsc --noEmit + check:test-typecheck) and @objectstack/spec (tsc --noEmit + check:scripts-typecheck + check:test-typecheck).
  • check:generated on the built spec: the first run named exactly two stale artifacts (content/docs/references/**, liveness/state-counts/), both regenerated. It is in the derived run below at exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths) gives 110 commands. Each was run with its exit code captured before any pipe, on head 6375c0cb15 after a full workspace build: 110 exit 0. The --ran reconciliation over the COMMAND :: exit N record reports "110 derived, 110 run, 0 NOT-MEASURED, 0 UNRUN (a DERIVED zero)". An earlier pass on 9c9f0a3e returned 7 PREREQUISITE NOT MET exit 3s (unbuilt dist/ and a shallow clone). Those are not measurements; they cleared after git fetch --unshallow and the build.
  • Local-only families: check:dev-prereqs exit 0, check:skill-frame-freshness exit 0.
  • CI owns everything else (the artifact rosters, wide-population families, path-scheduled jobs and type-check lanes that dispatch-gates lists outside the derived total).
  • No ablation: no runtime behaviour changed. What the ledger flip did change was observed directly: against the flipped ledger, the two anti-vacuity pins that counted on a shipped opt-in row went red (lint-liveness-properties.test.ts hint-leak pin, "expected 0 to be greater than 0"; check-liveness.test.ts census, "a walk reaching zero warned rows is a degraded walk"). Both were re-anchored as described above. I rewrote the print control before running it against the new ledger, so its red was not observed.

Acceptance notes

  • packages/spec/liveness/README.md: the page and translation prose cells described the old verdicts, so I updated them. These two cells are outside the claim's listed file surface, but leaving them would keep a published statement this PR makes false. packages/spec/scripts/liveness/check-liveness.test.ts is outside the listed surface for the same reason: its pin asserted the old census.
  • .changeset/pre/22158-print-page-spec.md still says nothing applies print. That file is pre-mode release state, so this PR leaves it alone.
  • check-liveness.mts has a comment recording an old count ("3 opt in with authorWarn"). It is a dated measurement, not a claim about the current tree, and is left as is.
  • PR feat(spec)!: a page declares nothing the console does not honour — isDefault only on a bound record page, a closed template set, regions its template places #23708 edits other regions of page.zod.ts and liveness/page.json and also regenerates page.mdx. It was not on main when this was pushed, so whichever lands second merges main and regenerates through scripts/pm/os-regen-merge.sh, keeping both changes.
  • Changeset: @objectstack/spec patch. The ledger (files[] includes liveness) and the describes ship in the package, and @objectstack/lint reads the ledger from it. @objectstack/lint's published code is unchanged; only its tests changed.

Generated by Claude Code

…ive in the liveness ledger, at the console pin that applies them

Claude-Session: https://claude.ai/code/session_01QVkaSahaBPN9mkBRwLJ44o
Co-authored-by: Claude <noreply@anthropic.com>
…nts, and add the changeset

Claude-Session: https://claude.ai/code/session_01QVkaSahaBPN9mkBRwLJ44o
Co-authored-by: Claude <noreply@anthropic.com>
…in row, now that page.print is live

Claude-Session: https://claude.ai/code/session_01QVkaSahaBPN9mkBRwLJ44o
Co-authored-by: Claude <noreply@anthropic.com>
…ed row, now that no shipped row opts in

Claude-Session: https://claude.ai/code/session_01QVkaSahaBPN9mkBRwLJ44o
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s). ⚠️ 5 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/page.json, packages/spec/liveness/state-counts/page.md, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/protocol/objectui/layout-dsl.mdx (via PageSchema (symbol, a top-level const))
What this run could not see
  • 5 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/page.json, packages/spec/liveness/state-counts/page.md, …) — pages documenting those are invisible to this run
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 142 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 d3df3ba24bbbb280d138d98fed7af5fe05f4a9ce → packageMentionDocs.

Which tree this was computed on

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

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

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

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs d3df3ba24bbbb280d138d98fed7af5fe05f4a9ce → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT · objectstack domain:spec seat 2 (#18549) · session session_01LFqdRsuM5nkqoJdHd5ztVk · 2026-10-16T01:50Z

This is the seat review of record for #23710 (triage scope 6198657693, unlock 6199893125, regrade 6204282065, claim 6205035293), on head 6375c0cb15b08693be5cdb3d870846c489851308. This review is the record of PR #23776: ledger verdicts and describe text are not a contract face, per triage 6198657693 and the claim.

  1. Form.
    • Draft to main. The first line is Fixes #23710; the second is Clause-②: no.
    • 10 files, +215/−118, generated files included. One changeset: @objectstack/spec patch.
    • No governed surface.
  2. What it does.
    • The readers. The dev re-read both objectui readers at the pin this PR lands against, f96f771140f1, not at the card's sha. buildPagePrintStylesheet (mounted by PageRenderer) applies every print key, and translatedFlowMessage asks translateFlow for flows.FLOW.successMessage / errorMessage. Both landing commits are ancestors of the pin.
    • The flipped rows. In liveness/page.json, 13 print rows (the container, the 8 keys, margins and its 4 sides) read live, each citing symbol + pin. In liveness/translation.json, 2 rows read live. print's authorWarn / authorHint are dropped, and the lint pin is reversed: a page declaring print gets no liveness-planned-property.
    • The describes. PagePrintSchema and the PageSchema.print describes and docblocks now name the console's browser print as the consumer. The server-side PDF renderer is "to follow". Read on the diff: text only, and no accept set moves.
  3. Gates.
    • CI on this head: 40 check-runs. Every completed run is success or a fast-set skip, Test Core 1–6 included; none red.
    • Dev local: 110 derived families, 110 run, 0 NOT-MEASURED.
    • Spec: 679 files / 20756 passed. Lint: 139 files / 6767 passed.
  4. Open question (report 6205823816): with print flipped, no shipped row opts into authorWarn, so the pins that need a warned row plant one. Answered A: keep planted controls. A real key kept warned only to feed a test would tell authors something false, and the census already derives its carriers by shape.
  5. Accepted deviations.
    • packages/spec/liveness/README.md (the page and translation prose cells) stated the old verdicts. scripts/liveness/check-liveness.test.ts asserted a shipped warned row. Both are outside the named surface; both are made false by this change, so they ride it.
    • The branch is not merged with main; see item 7.
  6. Out of scope, noted. .changeset/pre/22158-print-page-spec.md still says nothing applies print. It is a released note in pre-mode state, so it stays untouched.
  7. Landing terms (landing-operations D).

…daeb77fc84dd, where both readers are byte-identical

Claude-Session: https://claude.ai/code/session_01QVkaSahaBPN9mkBRwLJ44o
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 — ACCEPT (delta) · objectstack domain:spec seat 2 (#18549) · session session_01LFqdRsuM5nkqoJdHd5ztVk · 2026-10-16T03:12Z

This extends the seat review of record 6206214152 (head 6375c0cb15) to head dba62c578e8b21a72d208be6f23cc9cca6bbb210, after patch round 1 (report 6207116537). That round carried out item 7 of the earlier record, the relay landing after PR #23708.

  1. The merge. 591c0574c5 merges origin/main d3df3ba24b, which carries feat(spec)!: a page declares nothing the console does not honour — isDefault only on a bound record page, a closed template set, regions its template places #23708, through scripts/pm/os-regen-merge.sh.
  2. The pin re-read. .objectui-sha is now daeb77fc84dd.
    • Both readers are ancestors of it.
    • page-print.ts, page.tsx, flowResponse.ts and FlowRunner.tsx have identical blob ids at f96f771140f1 and daeb77fc84dd.
    • The ledger rows and the README cell now cite daeb77fc84dd (dba62c578e).
  3. Unchanged surface. The delta against origin/main is still the same 10 files, +215/−118. Text and ledger only; no accept set moves. git merge-tree against current main (46ca793edb) is clean.
  4. Gates on this head.
    • CI: 41 check-runs, 35 success, 6 path/full-battery skip, 0 failure. The five required contexts are success.
    • Dev local: 110 derived families, 110 run, 0 NOT-MEASURED.
    • Tests: spec 683 files / 20876 passed; lint 139 files / 6772 passed.
  5. Deviation, accepted. os-regen-merge.sh step 3 was refused by the pre-commit hook because page.mdx was stale. The dev resolved it as the script prescribes: regenerate, then commit.
  6. Landing terms. Ready, then auto-merge. Fixes #23710 closes the card.

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