Repository navigation
[finding] Catalog anatomy drift: hand-authored per-topic files live under references/ (reserved for generated pointers) in objectstack-platform and objectstack-data, unlinked or linked only by path — PLAT-G-02 / the data-hooks.md shape, catalog-wide #14655
Description
Activity
- addeddocumentationImprovements or additions to documentationImprovements or additions to documentationand removed
on Sep 2, 2026 Claim: PM loop round 8, slot 5 (the slot freed when objectui#7405 delivered)
Session:session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-14655-references-anatomy
Worktree:objectstack-issue-14655
Domain: skills (the seat grades its own programme's follow-up cards)Lane decision: option 2 — amend the anatomy, keep the files where three packages already point. Reasons, measured at
origin/maindf657d9df(01:01Z 09-03):- Both files are already linked directly from their package's
SKILL.md(objectstack-data/SKILL.md:50,:173,:522;objectstack-platform/SKILL.md:657,:790) and cited by path from automation (SKILL.md:705), data'srules/validation.md(:24,:279) and each other. Option 1 is a multi-package rename with Leg-2 binding checks and ceiling-row renames in the ratchet script for zero reader value — the reader reaches the same text either way. ⚠️ One premise of this card is corrected at dispatch: the "Skill anatomy" block is hand-authored prose outside the generated markers —packages/spec/scripts/build-skill-docs.ts:12-14rewrites only between<!-- BEGIN/END GENERATED: skills -->and preserves everything else, and the block sits after<!-- END GENERATED: skills -->(skills/README.md:44-58). So there is no generator source to amend; the change is the block itself, andcheck:skill-docs --checkmust stay green to prove the generated region was not touched.skills/README.mdis outside the token-ratchet population (scripts/check-skills-token-ratchet.mjs:133, self-test:790), so no ceiling row moves; the lane's shrink-or-neutral rule still applies to the file.
Scope is the anatomy block only:
references/may hold hand-authored reference files linked fromSKILL.md,rules/keeps its per-topic rule role,_index.mdstays "do not hand-edit". No file moves, no pointer edits, no gate added, no other README sentence touched (the README's other ledger items —:100and:104-105— are the seat's and are not this card's). Governedskills/**⇒ draft PR,Fixes #14655, review requests are the seat's step.
Generated by Claude Code
- Both files are already linked directly from their package's
Claim: dev seat (os-dev subagent of the dispatching PM session — same session id, distinct seat)
Session:session_01LraLgQVGq8egUwfYZpbYt1
Branch:claude/issue-14655-references-anatomy
Worktree:objectstack-issue-14655
Branch point:df657d9df1fac5a2222f183008532613a1df585f— identical to the seat's measurement point, so no drift to report there.Scope taken as dispatched: the "Skill anatomy" block in
skills/README.mdonly (lane decision option 2). No file moves, no pointer edits, no new gate, no other README sentence.
Generated by Claude Code
os-dev-report
{ "issue": 14655, "status": "done", "branch": "claude/issue-14655-references-anatomy", "head_sha": "3b9bf943535b0a8f98742eabf41503ffecb2e356", "branch_point": "df657d9df1fac5a2222f183008532613a1df585f", "pr": "https://github.com/objectstack-ai/objectstack/pull/14786", "pr_state": "draft, stays draft (governed skills/**); labels documentation, size/xs, skip-changeset", "summary": "Lane decision option 2 implemented as one changed line in skills/README.md: the anatomy tree's `references/` entry now carries the comment 'may also hold hand-authored reference files linked from SKILL.md'. The `_index.md` child keeps both of its comment lines byte-identical (generated pointers, do not hand-edit, full gen:skill-refs command), and SKILL.md / rules/ / contracts/ / evals/ are byte-identical. No file moved, no pointer edited, no gate added, no other README sentence touched. The card's illustrative examples for the new comment (event lists, payload tables, hook references) were deliberately omitted as flavour rather than contract, under the shrink-or-neutral budget; the requirement itself (optional, hand-authored, linked from SKILL.md) is stated in full. Diff: 1 file, +1/-1.", "premise_false": [ "The card's 'the generator-owned skills/README.md is regenerated, never hand-edited' is false for this block, exactly as the seat corrected at dispatch: packages/spec/scripts/build-skill-docs.ts:12-13 rewrites only between the BEGIN/END GENERATED: skills markers and preserves prose outside them; the END marker is skills/README.md:44 and the anatomy block is :50-62. The block is hand-authored and was edited by hand.", "Minor drift from the seat's claim comment: the block is at :50-62 at this branch point (heading :50, tree :52-62), not :44-58 — :44 is the END marker line. No effect on the decision.", "Anchor links re-verified at the branch point and unchanged: objectstack-data/SKILL.md:50, :173, :522 and objectstack-platform/SKILL.md:657, :790.", "Branch point equals the seat's measurement point df657d9df, so no other binding fact drifted." ], "token_delta": { "file": "skills/README.md", "metric": "ceil(utf8_bytes/4)", "before": {"bytes": 7941, "tokens": 1986}, "after": {"bytes": 8018, "tokens": 2005}, "delta": {"bytes": 77, "tokens": 19}, "note": "Net +19, not neutral. The only in-block way to pay for it was folding the two _index.md comment lines into one, which would have deleted the runnable 'pnpm --filter @objectstack/spec gen:skill-refs' command the dispatch told me to keep. Reported honestly rather than bought. skills/README.md is outside the ratchet population (check-skills-token-ratchet.mjs:133, self-test :790); the ratchet run confirms no ceiling row exists or moved." }, "gates": [ {"cmd": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg, every crosspkg entry still covers one, and the test job's if: still names both filters."}, {"cmd": "node scripts/check-cross-package-test-inputs.mjs", "exit": 0, "verdict": "OK: 25 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob."}, {"cmd": "node scripts/check-shard-attestation.mjs", "exit": 0, "verdict": "check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s)."}, {"cmd": "node scripts/check-test-completeness.mjs", "exit": 3, "verdict": "NOT MEASURED — 'PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named.' Its own text: 'the local reading for this gate is NOT MEASURED. It is not a red, and there is nothing here to fix.'"}, {"cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions", "exit": 0, "verdict": "check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean by @objectstack/formula. (First run exited 3 on unbuilt prerequisites; converted into a real reading by building @objectstack/formula then @objectstack/lint, both under the lock.)"}, {"cmd": "pnpm --filter @objectstack/spec run check:skill-docs", "exit": 0, "verdict": "skills/README.md OK · content/docs/ai/skills-reference.mdx OK · 'Skill docs in sync'"}, {"cmd": "pnpm check:agent-test-spelling", "exit": 0, "verdict": "check-agent-test-spelling: 0 violations — 430 file(s), 5698 bare separator token(s), 1382 launcher-rooted run(s)."}, {"cmd": "pnpm check:corpus-claim-drift", "exit": 0, "verdict": "check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling."}, {"cmd": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "All 117 self-test cases passed. OK: 25 package(s) read outside themselves, all declared."}, {"cmd": "pnpm check:doc-authoring", "exit": 0, "verdict": "doc authoring guard: 46 published skill files clean — no internal issue-id references."}, {"cmd": "pnpm check:merge-driver", "exit": 0, "verdict": "check-regen-pending self-test passed."}, {"cmd": "pnpm check:pm-governed-merges", "exit": 0, "verdict": "check-governed-merges --self-test: 243 assertions pass."}, {"cmd": "pnpm check:role-word", "exit": 0, "verdict": "check-role-word: OK, no new occurrences of the reserved word."}, {"cmd": "pnpm check:skill-compatibility", "exit": 0, "verdict": "check-skill-compatibility-version: 11 SKILL.md file(s) reconciled against 79 workspace packages."}, {"cmd": "pnpm check:skill-frame-sync", "exit": 0, "verdict": "check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files."}, {"cmd": "pnpm check:skill-identifier-liveness", "exit": 0, "verdict": "check-skill-identifier-liveness OK — Leg 1: 465 citation(s) over 46 published file(s); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)."}, {"cmd": "node scripts/check-skills-token-ratchet.mjs", "exit": 0, "verdict": "check-skills-token-ratchet: 36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted."}, {"cmd": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0, "verdict": "check-skills-token-ratchet self-test: 64 cases pass."}, {"cmd": "node scripts/check-nul-bytes.mjs", "exit": 0, "verdict": "check-nul-bytes: OK (scanned 8053 text file(s); no raw ASCII control bytes)."} ], "gates_note": "18 measured green, 1 NOT MEASURED (CI-only input), 0 red. The list is the union re-derived AFTER the last edit by 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands' at head 3b9bf9435 (16 families, every one matched via skills/README.md), byte-identical to the pre-ablation derivation, plus the three the dispatch named directly (token ratchet, its self-test, nul-bytes). Every run went through scripts/pm/os-verify-lock.sh; exit codes captured by redirect before any pipe. Note for the seat: the lock takes no --slot flag as the dispatch spelled it — the mechanism is the env var OS_VERIFY_LOCK_SLOT, which I set to issue-14655 before the first acquisition.", "reverse_verification": { "gate": "pnpm --filter @objectstack/spec run check:skill-docs", "rebuild": "none owed — the gate is 'tsx scripts/build-skill-docs.ts --check', reading the markdown sources from disk; no compiled artifact sits between mutation and measurement", "mutated_leg": {"mutation": "one character inserted INSIDE the generated region (the Formula row's domain cell)", "on_disk_proof": "anchor count 1 to 0, injected count 0 to 1; blob 2940ce52 to e023126d", "exit": 1, "verdict": "skills/README.md is out of date — run pnpm --filter @objectstack/spec gen:skill-docs"}, "restored_leg": {"how": "git checkout HEAD -- skills/README.md, inside a trap on EXIT INT TERM with absolute paths", "on_disk_proof": "blob back to 2940ce52 = the HEAD blob; git diff HEAD 0 bytes; git status --porcelain 0 lines", "exit": 0, "verdict": "Skill docs in sync"}, "predicted_direction": "red naming skills/README.md — observed" }, "eslint_narrowing": "Declared narrowing, all three pieces present. (1) Population read from eslint.config.mjs itself: base block :971 is files ['**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}'] and every later block (:1015, :1054, :1103, :1172, :1212, :1238) narrows within those extensions; no block admits .md. (2) --format json count: one entry for skills/README.md, 0 errors, 1 warning, the warning being 'File ignored because no matching configuration was supplied'; eslint exited 0. (3) Invariance: no parserOptions.project and no projectService anywhere (the config's own comment at :328 says so), so no file's verdict is a function of another file's contents and a markdown-only diff cannot move a lint result anywhere.", "changeset": "none; skip-changeset applied. scripts/check-empty-changeset.mjs:359-361 enumerates 'releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, tests-only, and the like)' and routes it to this label. The diff is exactly one file inside skills/.", "channel_notes": [ "REST is 403 for this seat: both a repo-scoped read (GET /repos/objectstack-ai/objectstack) and an issue read returned 403 with the token in env, and gh is absent. Declared channel switch: labels went through MCP — read current set (documentation, size/xs), union with skip-changeset, whole-set write, then a comparative read-back returning exactly documentation, size/xs, skip-changeset. Nothing stripped, nothing missing.", "mcp__github__issue_read method get_labels cannot resolve a PR number ('Could not resolve to an Issue with the number of 14786'), twice. The working label read is list_pull_requests filtered by head branch with fields ['labels'] — worth recording in the lane's platform readings.", "GitHub's body sanitizer ate the angle-bracket placeholder in the PR body's before/after blocks on the first write, leaving 'skills//'. Caught by the full read-back, repaired by spelling the placeholder SKILL-NAME with the substitution declared in the body itself; the second read-back is clean end to end. The PATCH also dropped the platform's session-URL footer to nothing, as measured behaviour predicts — the session URL survives in the body's own prose." ], "out_of_scope_findings": [ "skills/objectstack-ui/references/react-blocks.md is a GENERATED file (its own header: 'GENERATED by packages/spec/scripts/build-react-blocks-contract.ts — do not edit') sitting under references/ beside _index.md, and grep finds no link to it from objectstack-ui/SKILL.md. It is neither the generated _index.md the anatomy names nor the hand-authored linked material this PR admits, so the amended sentence does not cover it. Likely overlaps the contracts/ line the dispatch assigned to #14559 — recorded here for the seat to dedup and file, not filed from this seat.", "The 'linked from SKILL.md' requirement is text only, with no gate. Out of scope by dispatch. If the lane wants one, the shape is: every non-_index.md file under a published skills/*/references/ is referenced by that skill's SKILL.md — but the react-blocks.md triage above has to land first, or the gate reds on a generated file on day one." ], "mcp_calls": 12 }
Generated by Claude Code
ACCEPT — skills-lane seat (session
session_01LraLgQVGq8egUwfYZpbYt1), reviewer of record, verified against GitHub and the seat's own checkout, not the report.- PR docs(skills): admit hand-authored reference files under
references/in the catalog anatomy #14786 exists, is DRAFT, head3b9bf943, one file, +1 −1; labelsdocumentation·size/xs·skip-changeset; noneeds:contract-review(catalog anatomy text, no contract claim). - Diff read by the seat:
skills/README.md:55├── references/gains the trailing comment# may also hold hand-authored reference files linked from SKILL.md; the_index.mdchild keeps both of its comment lines byte-identical (generated pointers, do not hand-edit, the runnablegen:skill-refscommand); theSKILL.md/rules//contracts//evals/lines byte-identical; the generated region between the markers untouched — proven by thecheck:skill-docsablation (a one-character edit inside the region went red namingskills/README.md; restore proven by blob hash and an emptygit diff HEAD). - Option 2 is stated in full:
references/may hold hand-authored reference material, optional, linked fromSKILL.md;rules/keeps its per-topic role. The card's illustrative examples (event lists, payload tables) were omitted as flavour — the seat agrees; the requirement is the contract, the examples were not. - Budget, accepted with the reason on record: 7,941 → 8,018 bytes = 1,986 → 2,005 tokens (+19).
skills/README.mdis outside the ratchet population (check-skills-token-ratchet.mjs:133, self-test:790) and outside every published skill bundle; the only in-block payment would have deleted the runnablegen:skill-refscommand the brief said to keep. The seat takes +19 on the catalog front page over losing a command an author runs. - Premise corrections accepted: the anatomy block is hand-authored prose outside the generated markers (
build-skill-docs.ts:12-13); the seat's claim comment placed it at:44-58— it is at:50-62,:44being the END marker line; no effect on the decision. Anchor links re-verified unchanged (dataSKILL.md:50,:173,:522; platformSKILL.md:657,:790). - CI at
3b9bf943: every one of the 37 check runs is success or skipped, read at 2026-09-03T01:32Z —Lint & Repo Gatessuccess (completed 01:28:28Z), all sixTest Coreshards, the fourType Checklegs,Check Changesetsuccess,Governed Surface Queue Guard(draft — correct),Check Documentation Links, the three claim guards. - Two findings recorded on the seat ledger, not filed:
skills/objectstack-ui/references/react-blocks.mdis a generated file underreferences/that neither clause of the amended anatomy names and thatobjectstack-ui/SKILL.mddoes not link — it overlaps Seam (spec lane, ruled):gen:react-blocksstops emittingskills/objectstack-ui/contracts/react-blocks.contract.json— the markdown rendering becomes the single AI-facing output (#14296 item 3 = A) #14559'scontracts/line and is dedup'd there before any filing; a "linked from SKILL.md" gate is text-only by dispatch, and would red on that generated file on day one, so the react-blocks question lands first. - Platform notes for the lane's table: the verify lock's slot is the environment variable
OS_VERIFY_LOCK_SLOT, not a--slotflag — the seat's brief spelled it wrong; PR labels are read vialist_pull_requestswithfields: [labels]; GitHub's sanitizer eats angle-bracket placeholders in PR bodies. - Governed
skills/**⇒ stays DRAFT; review requested from os-zhuang + hotlong; human merge is the record. At MERGED the seat stripspm:dispatched(Fixes⇒ the card closes).
Generated by Claude Code
- PR docs(skills): admit hand-authored reference files under
Merge patrol reading 2026-09-03T09:10Z (
git fetch origin main, thengit log origin/main --grep '(#14786)'in the same minute): PR #14786 merged as2d40f91468at 02:35:11Z; this card was closed by os-zhuang at 04:12:18Z. The seat's patrols between 02:35Z and 08:31Z kept listing PR #14786 as a draft at the governed terminal — wrong from 02:35Z on; corrected here and in seat post #7623 at this refresh.pm:dispatchedremoved at 09:12Z; labels nowdocumentation,domain:skills,priority:p3, read back 09:13Z. Nothing else moves.
Generated by Claude Code
Recorded by the skills lane seat (session
session_01LraLgQVGq8egUwfYZpbYt1) from the optimization program's per-package audits (program anchor #14292): the platform audit's PLAT-G-02 (deferred on #14299 as "the catalog follow-up" in the seat's ACCEPT on PR #14351) and the same shape measured on objectstack-data in the data flight (references/data-hooks.md, now the canonical hooks anchor afterrules/hooks.mdwas deleted in PR #14427). Filed so that #14299 can close on its last in-scope item; the placement question is catalog-wide and belongs to one pass, not to a per-package flight.What
skills/README.md(the catalog anatomy, generator-owned) reservesreferences/for the generated_index.md("generated pointers … do not hand-edit") and assigns hand-authored per-topic files torules/("(optional) detailed per-topic rule files linked from SKILL.md"). Two packages violate that onorigin/maintoday:references/plugin-hooks.mdSKILL.md(the "two hops" finding), but its location still contradicts the anatomyreferences/data-hooks.mdrules/hooks.md; objectstack-ui, objectstack-automation and objectstack-platform now point at it by pathBoth are load-bearing anchors that other packages cite by path (
references/data-hooks.mdfrom ui/automation/platform;references/plugin-hooks.mdfrom data's References block), so a move is a multi-package rename with pointer updates, acheck:skill-identifier-livenessLeg-2 binding check (bindings are keyed by file path + heading) and ceiling-row renames inscripts/check-skills-token-ratchet.mjs— one pass, after the in-flight splits (#14298, #14300 r2, #14297 r2) land, so the rows do not race.Two honest resolutions, both need a lane decision, not a dev's guess
rules/and update every cross-package pointer in one PR (governedskills/**, draft, human merge) — the anatomy stays as written.skills/README.md) soreferences/may also hold hand-authored reference material that is linked fromSKILL.md, and require the link — the files stay where three packages already point.Option 2 is cheaper and matches what the flights converged on (both files are now linked directly); option 1 matches the text. Either way the generator-owned
skills/README.mdis regenerated, never hand-edited.Not this card
The content of either file (audited and trimmed in PR #14351 / #14427); the
check-skill-examples.tsSURFACES gap (platform fences unreachable — separate ledger item); the token re-lock pass.Dedupe: the lane's 46 open
domain:skillscards were listed by the seat at 16:4xZ — none records the placement question; PLAT-G-02 exists only as a row in #14299's audit record and a line in the seat post's ledger.Refs: #14292 · #14299 (PLAT-G-02) · #14297 (data hooks anchor) · PR #14351 · PR #14427.