Skip to content

fix(spec): grade flow.description and hook.label/description live — Studio's metadata list and quick-find show them - #20541

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20299-display-annotations-ledger
Sep 29, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-20299-display-annotations-ledger

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Part of #20299
Clause-②: no

Stage 1 of #20299. Three docs-shaped liveness rows move dead → live, because Studio already shows them to a human: flow.description, hook.label and hook.description. The other four rows of the family need objectui code and are objectstack-ai/objectui#11027's: app.areas.description, permission.rowLevelSecurity.label / .description and the view container label. They are untouched here, and #20299 remains open for them.

Ledger data, two README Notes cells and one gate-test fixture only. ⛔ No schema, parse, .describe() or accept-set change. None of the three rows sets authorWarn, so the set of lint warnings does not change. The re-grade reverses no ADR-0033 decision: all three stay docs-shaped, deliberately KEPT and exempt from enforce-or-remove. Each row keeps the note it carried while dead, labelled as history.

Files

  • packages/spec/liveness/flow.json: the description row.
  • packages/spec/liveness/hook.json: the label and description rows, plus one dated sentence appended to the file _note. Its 2026-08-10 lookup ("both verdicts stand unchanged") is now history.
  • packages/spec/liveness/state-counts/flow.md and packages/spec/liveness/state-counts/hook.md: the two per-type count shards, regenerated by gen:liveness-counts, not hand-edited. flow has 35 live and 5 dead (was 34 / 6). hook has 21 live and 1 dead (was 19 / 3). Across all shards, the read-time sum that check:liveness prints is 952 live and 136 dead (was 949 / 139). No file commits that total.
  • packages/spec/liveness/README.md: the flow and hook Notes cells. Both listed these keys as dead.
  • packages/spec/scripts/liveness/check-liveness.test.ts: the "stays GREEN when a dead entry carries the SAME rotted pointer" case borrowed flow.description as its sample dead row. It now uses the flow.active tombstone, which the gate itself holds at dead, and it asserts that precondition.
  • .changeset/20299-display-annotations-ledger.md: a patch changeset for @objectstack/spec. The ledgers ship in its files[] (liveness), and @objectstack/lint reads them.

File-surface declaration. The claim's surface named flow.json, hook.json, the regenerated counts and the changeset. The README cells and the test fixture are outside it. The dispatch's pin sweep required both to move with the flip ("grep for any test, doc or ledger note that asserts these three rows are dead … and move it with the flip"). Without the fixture move, the gate test goes red: see the reverse verification below. The README ships in the same liveness directory.

The lane's call, and the ruling it applies

A Studio list column and the metadata quick-find count as consumers of a DISPLAY-shaped key. That is the #7131 ruling's table in packages/spec/liveness/README.md ("Designer previews count as consumers"): for a display key, being shown to a human is the whole of the claimed effect. The README's producer discipline binds too, so each row names who hands the reader a record.

Premise, reader half: measured at the .objectui-sha pin dd3f7e1be

Instrument: read-only git -C ../objectui show SHA:PATH and git grep … SHA. Nothing in objectui was edited, checked out or stashed.

  • The Studio route metadata/:type mounts MetadataResourceListPage (packages/app-shell/src/console/AppContent.tsx, both the with-app and the zero-app branch).
  • MetadataResourceListPage renders a registered custom ListPage if one exists, and otherwise DefaultMetadataList. DefaultMetadataList takes config.listColumns ?? defaultColumns(config.primaryKey ?? 'name'). defaultColumns returns the primary key, label and description, and each cell goes through defaultCell.
  • No registration gives flow or hook a ListPage or listColumns. git grep registerMetadataResource over packages and apps gives 44 hits. The non-test registrations are builtinComponents.tsx (object, field, permission, view, dashboard, page, book), anchors.ts#registerBuiltinAnchors, datasource/register.ts and default-schemas.ts, which sets defaultSchema / fieldOrder only. flow and hook register only in anchors.ts, with anchors, create fields and defaults. git grep -E 'ListPage\s*:' hits only datasource/register.ts, the positive control. The shorthand spelling ListPage[,}] / listColumns[,}] has no registration hit.
  • MetadataQuickFind (QuickFind.tsx) indexes every type's items off the same client.list(type) read. It keeps label and description and draws label beside the name and description under it. It is mounted on DirectoryPage and StudioHomePage.
  • MetadataClient.list(type) (packages/data-objectstack/src/metadata-client.ts) is GET {base}/{type}, with base /api/v1/meta. It accepts a top-level array or items.
  • Per-string control at objectui main 5d689c3, counted with git show REF:PATH | grep -cF at both refs. Every cited string counts the same at the pin and at main (1/1 each): the listColumns ?? defaultColumns line, the description and label default-column entries, if (customConfig?.ListPage) {, the :type route element, QuickFind's label: item?.label,, description: item?.description, and {r.description}. The ListPage: and listColumns registration counts also match.

Premise, producer half: measured booted, not read

Instrument: a throwaway @objectstack/verify test in packages/qa/dogfood (deleted after the run, never committed). It booted the real examples/app-showcase composition in-process with bootStack(showcaseStack), signed in as the dev admin and read the exact doors the list page reads. It was run twice, before and after a container restart, with the same result.

door status body rows
GET /api/v1/meta/flow 200 top-level keys type, items 30 flows. All 30 carry their authored label and description, with _packageId: com.example.showcase
GET /api/v1/meta/hook 200 top-level keys type, items 4 hooks. All 4 carry label and description, with _packageId: com.example.showcase
GET /api/v1/meta/package 200 top-level keys type, items com.example.showcase with scope: project, which is what buildPackageScopeOptions admits, so the list page's package scope shows those rows

The server-side list answer is packages/rest/src/meta-item-read-gate.ts#createMetaListAnswer, which both transports serve. Its type-specific steps are for api, app, view, doc and object only. For flow and hook it runs the per-caller gate and the translation step, and neither drops label or description. Each row's producer cites that answer, the route, the list-page fall-through, the registration and the client read.

Verification, at cb0206219c

All heavy runs went through scripts/pm/os-verify-lock.sh with --maxWorkers=2. The box is shared, so wall-clock figures are shared-box readings.

  • pnpm --filter @objectstack/spec run check:liveness: exit 0. "✓ every governed-type property … is classified …" and "✓ packages/spec/liveness/state-counts.md is current".
  • pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 (the whole local project): 573 files, 16835 passed, 1 todo.
  • @objectstack/spec repo project, narrowed. The whole repo project hit its 330 s timeout on the shared box, so that run is NOT MEASURED. It was narrowed to the 10 repo files that read the ledgers: scripts/liveness/evidence.test.ts, scripts/liveness/proof-registry.test.ts and eight *-retirement / *.pin tests. Result: 10 files, 211 passed. CI runs the whole project.
  • pnpm --filter @objectstack/spec typecheck: exit 0. It covers tsc --noEmit, check:scripts-typecheck and check:test-typecheck. tsc -p tsconfig.scripts.json --listFiles names scripts/liveness/check-liveness.test.ts, so the edited test is compiled.
  • Gates. node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 68 commands at cb0206219c. All 68 ran, and each exit code was captured before any pipe. --ran over the exit-coded record reported: "✓ 68 derived famil(ies) accounted for — 68 run, 0 NOT-MEASURED (a DERIVED zero …)".
    • 66 exited 0.
    • check:dual-build-cjs-loads first exited 3 (PREREQUISITE NOT MET: eight unbuilt packages). It was re-measured after building them (all turbo cache hits) and exited 0: "104 published require entry point(s) across 66 package(s) load".
    • check:platform-checklist exits 1 on a finding this diff does not reach. See Acceptance notes.
  • Reverse verification of the moved fixture, after the commit. The fixture's carrier was swapped back to the flipped row through scripts/ablation-replace.mjs (anchor setEvidence(root, 'flow', 'active', hit ×1 → ×0, replacement ×0 → ×1, blob 9ff17ad4 → 1091717a). The case went red: expected 1 to be +0, and the gate named flow/description → packages/plugins/driver-sql/src/sql-driver.ts. That is the old fixture failing because the row is now scanned as live. The tool restored the file: blob after restore 9ff17ad4 equals HEAD, and git diff HEAD is empty. The direction observed was a turn to red, as expected.
  • Upstream check: origin/main has moved to 6427e2cf56 since the base fb386074f5. None of the six paths changed upstream (git diff --name-only BASE origin/main -- PATHS is empty), so the regenerated counts need no merge.

Acceptance notes

  • check:platform-checklist is red on the base and does not involve this diff. docs/qa/platform-checklist/areas/identity-auth.json anchors packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor. Since 7d63088958 (PR fix(plugin-auth): a refused auth setting no longer drops the settings saved with it #20429), that symbol exists in the file only as a member inside a patch object, which symbol-anchors.mjs does not accept as a declaration. The files that finding names (the checklist area, auth-plugin.ts, scripts/check-platform-checklist.mjs, scripts/symbol-anchors.mjs, scripts/checklist-select.mjs) are byte-identical between this branch's base fb386074f5 and origin/main 1378ec7c0c, and none of the six paths here is among them. Carrier: the plugin-auth / checklist owner. Not filed here.
  • Mentions left as they are, because the flip does not make them false. docs/audits/2026-06-flowschema-property-liveness.md records the dated 2026-06 audit and is not a current-state claim. .claude/skills/spec-property-retirement/SKILL.md §0 uses hook.label / flow.description as the example of "build the renderer, do not retire", and that is what happened. liveness/app.json (areas.description) and liveness/job.json cite "the hook.label precedent" for "docs-shaped, kept, not warned", and that is still true.
  • Observation, objectui side (not filed). QuickFind.tsx's docblock calls it a "Cmd+K palette", but it binds Cmd+Shift+M, to leave Cmd+K to CommandPalette. The rows say "metadata quick-find" and name no key.
  • Also noted: hook still has no registered metadata-admin preview. A HookPreview is not needed for these rows, and objectui#11027 already excludes it.

Generated by Claude Code

…he Studio metadata list and quick-find show them

Three docs-shaped liveness rows move dead -> live. Neither `flow` nor
`hook` registers list columns in the Studio metadata admin, so the list
page's default columns draw `label` and `description`, and the metadata
quick-find draws both as well. Each row cites that reader at the
`.objectui-sha` pin, names the producer (route, metadata client read and
the shared `createMetaListAnswer` list answer), and keeps its old note
as history. A booted showcase read of GET /api/v1/meta/flow and
/meta/hook served every authored label and description.

state-counts.md regenerated; the README flow/hook Notes cells and the
liveness gate test that borrowed flow.description as its sample dead
row move with the flip. No schema, parse or describe change.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tests tooling labels Sep 29, 2026
@github-actions

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 5 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/flow.json, packages/spec/liveness/hook.json, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 5 changed file(s) yielded no anchor (packages/spec/liveness/README.md, packages/spec/liveness/flow.json, packages/spec/liveness/hook.json, …) — 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.
  • 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 — 137 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 288611e3e58f6d8af50b889abcdde3e413e0eaa0 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: cb0206219c19b70f51f73fb0b9a1a05e34eb36aa
Local-runs: none

PR #20541 (draft; head repo is the base repo; branch claude/issue-20299-display-annotations-ledger), stage 1 of card #20299 under claim 5880838693. Inputs read: the card body and its four comments (5859600931, 5880539559, 5880838693, 5881642005), objectui#11027 and its grade, the PR body, its one bot comment, its file list, the net diff origin/main...cb02062 (6 files, +47 / -17), packages/spec/liveness/README.md on main ("Designer previews count as consumers" and the citation and producer sections), the objectui tree at .objectui-sha dd3f7e1be through git objects only, packages/rest and packages/spec/scripts/liveness on origin/main, and the check-runs on the head, read once on 2026-09-29 (32 runs). Nothing built, run or re-run; the template call and the post are the only scripts invoked.

① Derived judgments

Accept-set and public surface. The diff touches no schema, no .describe(), no export, no generated artifact but state-counts.md, and no code path but one test fixture. Accept-set change: none, judged RIGHT. check:authorable-surface, check:api-surface and check:docs have nothing to move, and the PR body's "no accept-set change" is what the file list says. Public surface: the @objectstack/spec tarball ships liveness/ (package.json files[]), so the three rows, the two README cells and the counts ARE a published change, and @objectstack/lint (lint-liveness-properties.ts) reads the ledgers at compile. No authorWarn key sits on any of the three rows on either side of the diff (walked at HEAD: flow and hook carry zero authorWarn rows), so the set of advisory warnings does not move. Judged RIGHT.

The lane's call is inside the ruling, from the README's own words. The decisive sentence of the #7131 section is not the preview enumeration but the premise of its table: "The two rules divide on what the property claims, not on what the surface is", with the display row: "Being shown to a human is the whole of the claimed effect. There is no second layer where the 'real' consumer would live, so the preview is not standing in for anything." The mechanical preview lookup is the MINIMUM a sweep takes before writing "no runtime consumer" (an absence to record, not a whitelist of surfaces), and the section's closing move condemns exactly "taking a preview's absence from the search as proof that nothing reads the value, for a key whose only job was ever to be read by a person". A Studio metadata list column and the metadata quick-find are metadata-admin surfaces that show the key to a human, so for flow.description, hook.label and hook.description (three docs-shaped display keys) they settle the question the way JobPreview settled job.label. Not a widening; nothing to escalate. The superseded evidence strings ("no reader either layer", "pure docs, zero runtime readers") were absence claims that a rendered column falsifies under any reading of "reader".

Reader truth at the pin dd3f7e1be, every registration site.

  • views/metadata-admin/ResourceListPage.tsx#MetadataResourceListPage (:89): getMetadataResource(type); a registered ListPage renders and bails (:102), otherwise DefaultMetadataList (:110). DefaultMetadataList :337 takes config.listColumns ?? defaultColumns(config.primaryKey ?? 'name'); defaultColumns :626 returns the primary key, label and description; the row loop :547-:549 draws row.item[c.key] through defaultCell.
  • Non-test registerMetadataResource sites at the pin: services/builtinComponents.tsx (object, field, permission, view, dashboard, page, book, each with listColumns); anchors.ts#registerBuiltinAnchors (__object_field, __object_index, __object_validation, hook, page, view, flow, permission, action, dashboard, report, object; only the object block at :513 sets listColumns, and no ListPage appears in the file); datasource/register.ts (datasource, the one ListPage in the tree); default-schemas.ts#registerDefaultMetadataSchemas (SCHEMAS keys: position, permission, translation, tool, skill, app, page, view, dashboard, report, book, email_template, so neither flow nor hook, and it sets only defaultSchema and fieldOrder). registry.ts#resolveResourceConfig merges the server's /meta/types entry for label, description, domain and allowOrgOverride only, so nothing server-side can inject columns. Conclusion: flow and hook carry no ListPage and no listColumns anywhere at the pin; the fall-through and the default columns are real, and the rows' "the only flow / hook registration" is accurate.
  • QuickFind.tsx#MetadataQuickFind :105-:115 indexes item?.label and item?.description off client.list(t.type) for EVERY type entry, and :276 / :282 draws r.label beside the name and r.description under it; mounted at DirectoryPage.tsx:336 and StudioHomePage.tsx:449. It binds Cmd+Shift+M while its docblock says Cmd+K (the dev's noted drift; the rows name no key).
  • Route: console/AppContent.tsx mounts MetadataResourceListPage at metadata/:type in BOTH branches, the zero-app branch (:980) and the with-app nested metadata block (:1077-:1080). data-objectstack/src/metadata-client.ts#MetadataClient.list (:871-:883) is GET {base}/{type} and accepts a bare array or items.
  • One scope condition, carried correctly by the rows: the list page shows only rows whose _packageId equals the active project-scoped package (:293-:298, ADR-0070 D5); the quick-find has no such scope. The producer cites the showcase package's scope: project; a packaged flow or hook is what the list draws, and every served item is what the quick-find draws.

Producer truth in this repo, read at origin/main. packages/rest/src/meta-item-read-gate.ts#createMetaListAnswer (:2227) is the one chain both transports call after the store read: rest-server.ts:5906 and runtime/src/domains/meta.ts:554 each hand it the protocol's getMetaItems answer (metadata-protocol/src/protocol.ts:7410) and return the same shape. Its eight steps: 1 api only; 2 createMetaListReadGate, which returns the items as given for every type but app, dashboard, book and doc, and even there filters rows, never keys; 3 app only; 4 view only; 5 and 6 doc only; 7 object only; 8 translateMetaList, which returns the list unchanged unless isTranslatableMetaType, and METADATA_DOCUMENT_TRANSLATORS is view, action, object, app, dashboard, dataset, page, so for flow and hook the step is the identity. No projection between the store read and the body touches label or description for any item of either type, not only the showcase's. The rows' phrase "no projection except the translation step" is over-cautious (that step is a no-op here), not wrong. The booted 30 of 30 and 4 of 4 measurement the dev reports is consistent with the code as read; it is the dev's reading, not this record's.

Row shape, against the README and the job.label precedent. Each flipped row carries status: live, verifiedAt: 2026-09-29, evidenceScope: cross-repo, an evidence in the realm-marker form with the pin (objectui @dd3f7e1be: path#symbol, the README-preferred symbol anchor where the precedent used :line), a producer naming who hands the reader a record (the route, the fall-through, the registration, the client read, and framework: packages/rest/src/meta-item-read-gate.ts#createMetaListAnswer, a local anchor the gate resolves), and a note that quotes the superseded evidence, states UNCHANGED (docs-shaped, KEPT, ADR-0033, not authorWarn'd) and carries the prior note verbatim under HISTORY. job.json label and description carry the same six parts. app.json, permission.json and view.json are not in the diff, so the four objectui#11027 rows are untouched. hook.json _note appends one dated sentence and leaves the 2026-08-10 "both verdicts stand unchanged" text in place as history; readable.

Out-of-claim files: both required, both minimal.

  • liveness/README.md: the flow Notes cell said "Remaining dead = description" and the hook cell said "label/description dead". The flip makes both false, the README ships in the tarball's liveness/, and the gate reads only the state table, never the Notes prose, so no gate would have caught it. Required. The rewritten cells agree with the walked ledger at HEAD: flow dead = 5 (active, template, nodes.outputSchema, errorHandling.fallbackNodeId, errorHandling.retryDelayMs, the "5 tombstone entries"), hook dead = 1 (timeout).
  • scripts/liveness/check-liveness.test.ts: the "stays GREEN when a dead entry carries the SAME rotted pointer" case borrowed flow.description as its dead carrier. The gate's scan is status-keyed (check-liveness.mts:878: EVIDENCE_SCANNED_STATUSES.has(status) && led?.evidence), so with the row live the rotted pointer is scanned and the case goes red: a pin the flip broke. The moved case asserts the SAME partition. flow.active is status: dead in the shipped ledger, a retiredKey() tombstone (flow.zod.ts:1066) kept in the walked shape; the tombstone join ([finding] the liveness gate has no reading of a retiredKey() tombstone — a tombstoned key's row may claim live and nothing objects (the mechanism behind #18304) #19062) only forbids a tombstoned row a non-dead status and never removes it from the status partition, so the exclusion is still attributable to dead alone; the same ROTTED string, the same exit-0 and not-contains assertions, plus a new precondition asserting the carrier is dead in the shipped file. The carrier is more stable than before. The file runs in the spec local vitest project (vitest.repo-tests.json does not name it), which CI's Test Core shards run.

state-counts.md. check:liveness renders foldStateCounts and holds the on-disk bytes to it (reconcileStateCounts, countsArtifactErrors, #7377). The Spec property liveness check-run (spec-liveness-check.yml runs check:liveness) is success on this head, so the file is exactly the generator's output. The deltas are the three flips and nothing else: flow 34 to 35 live and 6 to 5 dead, hook 19 to 21 and 3 to 1, total 949 to 952 and 139 to 136, 1103 unchanged. For the record only: open PR #20532 (not merged at this read) removes state-counts.md for per-type shards; whichever lands second owes a merge-and-regenerate round through os-regen-merge.sh.

Gate coverage, from the one read of the check-runs on cb02062. Concluded success: Spec property liveness (the family that owns the ledger, the README table, the counts artifact and the tombstone join; the load-bearing gate for this diff), Check Changeset, Governed Surface Queue Guard, Check PR Size, Check Documentation Links, Flag docs affected by code changes, Auto Label, Type Check · source gates, Dogfood Regression Gate (2/3), the three claim and part-of guards, filter. Concluded skipped: Build Docs, Console Pin Gate, Packed-tarball smoke (opt-in). NOT concluded at the read, named rather than presumed green: Build Core, Lint & Repo Gates, Temporal Conformance (live PG + MySQL), Test Core (1/6) through (6/6), Dogfood Regression Gate (1/3) and (3/3), Dogfood Verify CLI, Type Check · workspace, Type Check · debt ledger, Type Check · consumer gates; the rollup context TypeScript Type Check had not appeared. No check-run on the head carries a failure conclusion. check:platform-checklist (inside Lint & Repo Gates) is red on main per the open carrier #20464: its named inputs (docs/qa/platform-checklist/areas/identity-auth.json, packages/plugins/plugin-auth/src/auth-plugin.ts, the checklist scripts) are none of this diff's six paths, so a red there is main's, not this diff's. Governed surfaces: none of the six paths matches a GOVERNED_SURFACES row (docs/adr/, .claude/, skills/, AGENTS.md, CLAUDE.md, docs/NORTH-STAR.md); the queue guard agrees. 64 changed lines; not a fork.

② Semver level

.changeset/20299-display-annotations-ledger.md: "@objectstack/spec": patch. RIGHT. The diff publishes from a released package (the ledgers and README ship in the spec tarball, and @objectstack/lint reads the ledgers), so skip-changeset is not available; no accept-set, export or authorable key moves, so nothing lifts it to minor. The body describes the three rows, the reader, the producer and the unchanged warning set; no ADR-0087 marker is owed, since nothing is breaking. Check Changeset is green.

Clause-②: no. No accept-set change, no widening, no narrowing; the PR body's line matches.

③ Boundary flags

Dev flags from 5881642005, each answered:

  1. File surface: liveness/README.md and scripts/liveness/check-liveness.test.ts outside the claim's surface. ANSWERED in ①: both required (a shipped statement the flip made false; a pin the flip broke), both minimal, neither touches a schema, objectui or the other four rows. The seat that owns the claim adopts this record and amends the surface; no fork.
  2. hook.json _note gained one dated sentence: inside the surface; the history it appends to reads correctly.
  3. Container restart mid-run, with the local suite and the producer proof re-run: process only; the diff does not depend on it.
  4. Own queued lock waiter killed by its recorded PID and requeued: the only killable shape under Multi-agent discipline §8; no foreign process touched.
  5. PR body footer in the session-URL form: the form AGENTS.md prescribes for PR bodies; correct.

open_questions: none declared. None found.

Out-of-scope findings: (a) check:platform-checklist red on main, carried by open #20464 (pm:queue), so Prime Directive #10 is satisfied without a second card; (b) objectui QuickFind.tsx docblock says Cmd+K while the binding is Cmd+Shift+M: comment drift in the sibling repo, none of the three filing classes, and an acceptance note is the right carrier.

Nits, no action owed on this head: the rows' "no projection except the translation step" could say the step is a no-op for these types; the Studio list's project-package scope is a display condition worth one clause in a future sweep. Owed later, not here: the merge-and-regenerate round against PR #20532 if it lands first.

Implemented-by: claude/issue-20299-display-annotations-ledger
Reviewed-by: session_014EJ1ED8X4MMrT18BhVx4tx

VERDICT: PASS


Generated by Claude Code

Brings in the sharded liveness counts. The modify/delete on
packages/spec/liveness/state-counts.md is resolved by keeping main's
deletion; the per-type shards under state-counts/ are regenerated in
the next commit.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
… the merge

gen:liveness-counts over the merged tree rewrote exactly two shards,
state-counts/flow.md (35 live / 5 dead) and state-counts/hook.md
(21 live / 1 dead): the three flips of this branch. No other shard moved.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
… of the retired state-counts.md

The counts moved into per-type shards on main; the changeset's last
bullet still named the deleted file. Only that bullet changes.

Claude-Session: https://claude.ai/code/session_014EJ1ED8X4MMrT18BhVx4tx
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 29, 2026 02:13
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit 7e5246d Sep 29, 2026
44 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20299-display-annotations-ledger branch September 29, 2026 02:45
This was referenced Sep 29, 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 size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants