You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] The objectstack-ai generated reference index advertises 6 schemas the SKILL.md never teaches and omits the one it names — SKILL_MAP in build-skill-references.ts is unreconciled with the body #14462
Out-of-scope by-product of the skills optimization flight on #14305 (audit finding AI-B-04, deferred there by the card's own scope: the generator lives in packages/spec, and that flight was shrink-only inside skills/objectstack-ai/). Filed unassigned. No edit was made — the map is generator-owned and belongs to the spec lane.
That map is the sole input to the generated skills/objectstack-ai/references/_index.md (819 tokens, generator-owned, not ratcheted), which ships to third parties via npx skills add.
Taught, never advertised.ai/solution-blueprint.zod.tsexists (packages/spec/src/ai/solution-blueprint.zod.ts, with its own test) and is the schema behind the solution_design built-in skill the SKILL.md names in its built-in-skills table — but it is absent from SKILL_MAP, so the index never points at it.
The ruling this needs
Either direction is defensible, and they are not the same decision:
Narrow the map to what the body teaches, on the "a published index is a promise" reading. Cheapest; costs the reader nothing, since the omitted schemas have no authoring content anywhere.
Widen the body to earn the extra schemas. Expensive, and it fights the value gate: those surfaces have zero measured consumers, and the ratchet ceiling on that SKILL.md is 6,806 tokens.
Add solution-blueprint — this half looks unambiguous either way, since the body already names the skill it backs.
Worth checking whether the same unreconciled shape exists for the other 10 packages' SKILL_MAP entries; this audit only measured objectstack-ai.
Dedupe: one targeted search_issues over this repo (repo-scoped REST is 403 for the filing seat), validated in-session by a control query that returned its known hit. Nothing open covers this.
Triage: documentation · priority:p2 · pm:queue · domain:spec · type Task. First grading, finding comes off. ⭐ Promoted to the family anchor — see the scope note below.
domain:spec: the map is packages/spec/scripts/build-skill-references.ts:98-109 and the _index.md files are generated from it. ⛔ The generated indexes are not hand-edited.
p2 because the index ships to third parties via npx skills add, and both directions mislead an agent reader: five schemas are advertised that the body never teaches (three with zero consumers outside packages/spec), so an agent following the index Reads into node_modules for guidance that does not exist; and ai/solution-blueprint.zod.ts — the schema behind a built-in skill the body does name — is absent, so the one pointer worth having is missing.
Ruling: narrow the map, add solution-blueprint. ⛔ Do not widen the body.
Narrow is restoration, not a capability removal, and that distinction is why it is dispatchable: an index entry is a pointer, and pointing at a schema the body cannot help with is the defect. The schema keeps existing and stays importable; only the false promise goes. (Stated explicitly so a reviewer can object to the reasoning rather than to the outcome.)
Add solution-blueprint — the card is right that this half is unambiguous in either direction, because the body already names the built-in skill it backs.
⛔ Widening the body is off the table for this card. It fights the value gate on measured grounds (zero consumers for three of the five) and the SKILL.md ratchet ceiling is 6,806 tokens. If someone believes a specific surface deserves teaching, that is a skills-flight card with its own budget, ⛔ not a rider here.
⭐ Scope: run the census for all eleven packages, not just this one
The card's own closing line is the important one — "Worth checking whether the same unreconciled shape exists for the other 10 packages' SKILL_MAP entries; this audit only measured objectstack-ai."It does: #14466 found the same shape on objectstack-automation (the index routes to the ADR-0020-retiredstate-machine.zod.ts and omits both per-node config schemas), filed independently within the hour.
⇒ Two independent discoveries in one hour is a class, not two incidents. ⛔ Reconciling one package per card produces eleven cards and eleven rulings for one mechanical mismatch. This card carries the census — for each of the eleven SKILL_MAP entries, the set difference in both directions against what its SKILL.md teaches — and applies the ruling above uniformly. #14466 stays open as the member card holding automation's specific facts; ⛔ do not close it as a duplicate, its retired-schema pointer is a distinct defect worth its own line in the changeset.
⚠️state-machine.zod.ts being ADR-0020-retired is the sharpest instance and should gate the design: whatever reconciliation lands must make a retired schema in the map impossible, not merely corrected once — otherwise the census is a one-off and the next retirement re-opens it. If deriving the map from a checkable source is out of reach, say so in the PR rather than hand-fixing eleven lists.
Dedup accepted as run — one targeted search_issues validated in-session by a control query that returned its known hit. ⚠️ Worth repeating for future filers: that control is what makes the result readable, because search_issues returns intermittent false zeros in this repo (#13326).
Size/model suggestion: M, sonnet — the census is the work; the edits are small once it exists.
Claim: PM loop round R1 (slot refill) — domain:spec seat (seat post #6017). Family dispatch, this card is the anchor (triage 5506970439 promoted it): the SKILL_MAP reconciliation class in packages/spec/scripts/build-skill-references.ts. Fold-or-serial answered: FOLD, five gates — ① same defect shape and same fix (a generator-owned reference index disagreeing with the owning SKILL.md, repaired in the generator and regenerated; #14565's closure-step mechanism is the same generator's second half, which the triage on #14562 ordered to be designed together with the map gate); ② same file / same worktree / one changeset / one queue slot; ③ every member graded pm:queue · p2 · domain:spec by triage (5506970439 · 5506975178 · 5515135764 · 5514974653), none in the decision box; ④ per-member criterion named below; ⑤ exclusion list named below. Members: #14466 (objectstack-automation: the ADR-0020-retired state-machine.zod.ts pointer leaves, automation/builtin-node-config.zod.ts + automation/io-node-config.zod.ts join), #14562 (objectstack-formula: data/date-macros.zod.ts mapped to two packages), #14565 (objectstack-i18n: the transitive-closure step routes 5 of 7 pointers at schemas unreachable from a bundle). Each member keeps its own claim pointer comment; the shared branch is named here; one PR with one Fixes line per member and one commit per member.
Session: session_01H2oQebDDxYKfWZusyd8GXk (GitHub os-justin)
Branch: claude/issue-14462-skill-map-reconciliation
Worktree: objectstack-issue-14462
Domain: domain:spec
File surface: packages/spec/scripts/build-skill-references.ts (SKILL_MAP entries + the guard(s) the design adds) and the generated skills/*/references/_index.md files it regenerates (9 packages on origin/main9c1bcda3: ai · api · automation · data · formula · i18n · platform · query · ui), a test for the guard if the generator has a test file, a changeset or skip-changeset per the PR #14737 precedent (the labelling fix on this same generator, landed 2026-09-03). ⛔ No hand edit of any _index.md; ⛔ no SKILL.md body widened (a skills-flight card with its own budget, never a rider here); ⛔ no .zod.ts edited. Stop on breach; explain in the report.
Container & model: M, mode:subagent, model: opus — --tier on the generator + one index at 9c1bcda3 (06:33Z): no path-derived mandate; content: tooling + generated pointers, no contract accept/reject behaviour moves. Triage's sonnet suggestion not taken: the design half (a checkable source that makes a retired schema in the map impossible; the closure rule's feasibility) is a judgment.
Clause-②: no Governed surface: skills/** is governed, and check-governed-merges --test at 06:33Z reads the co-edited generator + regenerated indexes as governed (its regeneration exception passes only a pure gen:skill-refs regeneration, and splitting into two PRs leaves check:skill-refs red between them) ⇒ this PR stays draft for human merge: review on this card, review requested from the authorised approvers, listed as "awaiting a human merge" in the round report. Net line budget in skills/**: ≤ +6 lines across all nine _index.md files combined, every added line one of the members' named additions (ai/solution-blueprint.zod.ts, the two automation config files); narrowing should land net-negative.
Serial constraints cleared: 0 open PRs on build-skill-references.ts or any skills/*/references/_index.md at 06:33Z (branch-name read of 18 open PRs; dev re-checks at worktree time); PR #14737 (#14441, the "Sort Node" labelling fix on this generator) landed 2026-09-03 — base on current main; in-flight lane siblings #14414 (automation/execution.zod.ts describes) and #14446 (liveness/**) do not touch this surface (a later regeneration re-merges through os-regen if #14414 lands first); H17 index: automation/webhook.zod.ts (#2657) and ui/view.zod.ts (#8346) are pointed at, not edited — no hit. Exclusion list (look like family, are not): #14441 (labelling, landed); #14611 (gen:declaration-map, a different generator); the four skills flights #14305 · #14308 · #14315 · #14316 (SKILL.md bodies, own budgets); any SKILL.md widening.
Dispatch (R1 slot refill, 2026-09-04T06:36Z) — domain:spec seat, session_01H2oQebDDxYKfWZusyd8GXk (os-justin), seat post #6017. Family dispatch: anchor #14462 + members #14466 · #14562 · #14565 (claims 5536679159 · 5536680100 · 5536681114 · 5536682056). mode:subagent, model: opus, size M, Clause ② no. Governed landing: the PR stays draft for human merge (never flipped ready, never queued by an agent seat). The dev leaves its own Claim: comment on this anchor before its first edit.
Rulings (not re-decidable). Triage 5506970439 on this card, verbatim where operative: "Ruling: narrow the map, add solution-blueprint. ⛔ Do not widen the body." "This card carries the census — for each of the [SKILL_MAP] entries, the set difference in both directions against what its SKILL.md teaches — and applies the ruling above uniformly." "whatever reconciliation lands must make a retired schema in the map impossible, not merely corrected once … If deriving the map from a checkable source is out of reach, say so in the PR rather than hand-fixing eleven lists." Triage 5506975178 (#14466): drop automation/state-machine.zod.ts; the omitted per-node config schemas (automation/builtin-node-config.zod.ts, automation/io-node-config.zod.ts) join — "its retired-schema pointer is a distinct defect worth its own line in the changeset". Triage 5515135764 (#14562): "The class has two mechanisms … ⛔ Do not build the SKILL_MAP-only gate and declare the class closed." Seat ruling for #14562 (claim 5536681114): drop data/date-macros.zod.ts from the formula entry; no duplicate-ownership rule; a loud one-owner guard instead. Triage 5514974653 (#14565): decide the closure rule's feasibility FIRST and say so in the PR body — reachability rule if it can be made precise, else a per-package transitive allowlist/denylist beside SKILL_MAP; ⛔ no hand edit of _index.md. ⛔ No SKILL.md body widened; ⛔ no .zod.ts edited.
PM mechanism assumptions (verify; falsify freely). (a) SKILL_MAP on origin/main9c1bcda3 has 9 entries (data · query · ai · api · automation · ui · platform · i18n · formula; the triage said eleven — count and report), 9 generated skills/*/references/_index.md files. (b) A checkable source for "retired": the file header of automation/state-machine.zod.ts carries the ADR-0020 retirement in prose only; the ADR-0087 registry (packages/spec/src/migrations/entries/retired-defs/**, RETIRED_DEFS_BY_MAJOR) names retired defs, not files; the liveness ledger classifies properties. The dev decides whether any of these is a precise source for a "no retired schema in the map" guard; if none is, the PR says so (the triage accepts that answer) and the guard the PR still ships is the mechanical one: every SKILL_MAP path must exist and be exported by an entry, and appears in at most one package (loud refusal at generation). (c) The census output (per package: advertised-not-taught, taught-not-advertised) belongs in the PR body as a table; the SKILL.md bodies are read, never edited. (d) check:skill-refs is the drift gate (tsx scripts/build-skill-references.ts --check); gen:skill-refs regenerates; a generator with a test file gets a negative test for each guard. (e) Changeset vs skip-changeset: follow PR #14737's precedent on this generator; read that PR's files before choosing.
PM suggested route (optional). One commit per member: anchor (census + the objectstack-ai narrowing + ai/solution-blueprint.zod.ts + the guards), #14466, #14562, #14565 (closure rule or list), then one regeneration commit if the generator emits everything at once. PR body: the census table, the feasibility answer for the closure step, the guard(s) and their negative tests, the net line delta in skills/**.
Surface, budget, gates, report. File surface = the anchor claim 5536679159 (stop on breach). Net line budget in skills/**: ≤ +6 lines across all nine _index.md files combined; every added line one of the members' named additions; over budget ⇒ stop and report, ⛔ never raise it. Derive gates from your actual paths after the last commit (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no path args); at minimum pnpm --filter @objectstack/spec check:skill-refs, check:skill-examples (build its prerequisite first), check:llms-txt, pnpm --filter @objectstack/spec check:scripts-typecheck (or the typecheck composite), pnpm check:doc-authoring, pnpm check:nul-bytes, node scripts/check-system-context-census.mjs, the skills token ratchet family the derivation names. Report: os-dev-report first as a comment on this anchor (members get a one-line pointer each), then as the return; machine-checkable fields only, plus the per-member criterion verdicts and the skills/** net line delta.
Claim:
Session: session_01H2oQebDDxYKfWZusyd8GXk
Branch: claude/issue-14462-skill-map-reconciliation (pushed empty at claim time as the write-route probe; base 9c1bcda3)
Worktree: objectstack-issue-14462
Members covered: #14462 (anchor) · #14466 · #14562 · #14565 — one PR, one commit per member, one Fixes line per member.
File surface (as claimed by the PM at 5536679159, unchanged):
packages/spec/scripts/build-skill-references.ts — the SKILL_MAP entries plus the guards the design adds
the nine generated skills/*/references/_index.md files, regenerated only via pnpm --filter @objectstack/spec gen:skill-refs
a new test file beside the generator in its own convention (packages/spec/scripts/*.test.ts), carrying the negative tests for each guard
the skip-changeset label or a changeset, per the PR fix(spec): give data/query.zod.ts a module header so its pointer rows name the query AST #14737 precedent read
Not touched: any SKILL.md body, any .zod.ts source, content/docs/releases/**, any hand edit of an _index.md.
Net line budget in skills/**: not more than +6 across the nine indexes combined, every added pointer one of the members' named additions. Narrowing lands net-negative.
Clause-②: no
{
"issue": 14462,
"family": [14462, 14466, 14562, 14565],
"status": "done",
"branch": "claude/issue-14462-skill-map-reconciliation",
"pr": "https://github.com/objectstack-ai/objectstack/pull/15268",
"pr_state": "draft (governed surface; never flipped ready, no auto-merge armed)",
"head_sha": "eed6bb0f",
"base": "9c1bcda3, then merged origin/main 1bc3c092 mid-run to clear a dispatch-gates STALE TREE warning on scripts/pm/check-skill-line-ratchet.mjs",
"premise_still_valid": true,
"premise_still_valid_per_member": {
"14462": true,
"14466": true,
"14562": true,
"14565": true
},
"premise_evidence": {
"14462": "SKILL_MAP['objectstack-ai'] at 9c1bcda3 lists conversation/mcp/embedding/knowledge-document/usage and lacks ai/solution-blueprint.zod.ts; that file exists (packages/spec/src/ai/solution-blueprint.zod.ts, 28854 bytes) and the SKILL.md names solution_design at line 374",
"14466": "SKILL_MAP['objectstack-automation'] lists automation/state-machine.zod.ts and lacks both config files; both exist (builtin-node-config 38368 bytes, io-node-config 22085 bytes)",
"14562": "data/date-macros.zod.ts present in both the objectstack-query and objectstack-formula core lists",
"14565": "the i18n index carried all five named unreachable pointers; DRIFT: it carries EIGHT transitive pointers at this base, not the seven the card measured — shared/value-domain.zod.ts joined later via a new import edge. All eight are gone except the two kept deliberately."
},
"pm_assumptions_checked": {
"nine_not_eleven": "CONFIRMED 9 SKILL_MAP entries and 9 generated indexes (triage said eleven); 59 core entries total",
"checkable_retired_source": "FALSIFIED in all three candidate forms - reported in the PR body as the answer the triage said it would accept",
"check_skill_refs_is_the_drift_gate": "CONFIRMED",
"changeset_precedent_14737": "CONFIRMED and read: #14737 took a changeset because it edited packages/spec/src/data/query.zod.ts, which is inside the files allowlist. No .zod.ts is edited here, so skip-changeset applies"
},
"member_criteria": {
"14466": "PASS - state-machine absent from the whole automation index (not merely moved to transitive; grep count 0); both config schemas present as core rows",
"14562": "PASS - the formula entry is one file (shared/expression.zod.ts); the regenerated index carries no date-macros row; the one-owner guard exists with 6 negative tests. DEVIATION on the guard shape, see deviations",
"14565": "PASS - the regenerated i18n index lists none of data/filter, kernel/metadata-protection, shared/expression, data/field-value, shared/suggestions (nor shared/value-domain, the eighth); keeps shared/identifiers; KEEPS data/field.zod.ts, the call left to this seat, because FieldTranslationSchema.options is keyed by select-option value and SelectOptionSchema is the declaration those keys must match",
"14462": "PASS - census run over all 9 entries in both directions and tabled in the PR body; the ai entry narrowed by five and gained solution-blueprint; the two-mechanism question answered explicitly (two guards, one module); the retired-source feasibility answered NO with three measurements"
},
"files_changed": [
"packages/spec/scripts/build-skill-references.ts",
"packages/spec/scripts/lib/skill-map-guards.ts (new)",
"packages/spec/scripts/skill-map-guards.test.ts (new)",
"skills/objectstack-ai/references/_index.md (generated)",
"skills/objectstack-automation/references/_index.md (generated)",
"skills/objectstack-formula/references/_index.md (generated)",
"skills/objectstack-i18n/references/_index.md (generated)"
],
"commits": [
"3e9e2f67 anchor 14462 - ai narrowing, solution-blueprint, checkCoreEntryShape",
"fc2acf06 member 14466 - automation entry swap",
"5607ed5a member 14562 - formula drop, checkSingleOwner, SHARED_CORE_SCHEMAS",
"735fc9d7 member 14565 - TRANSITIVE_ALLOWLIST, checkTransitiveAllowlist, i18n",
"c412a47a merge origin/main",
"eed6bb0f stripInternalIssueIds - the catalog boundary rule the 14466 addition forced"
],
"skills_net_line_delta": {
"net": -9,
"added": 4,
"removed": 13,
"budget": "not more than +6",
"per_index": { "ai": -3, "automation": 1, "formula": -1, "i18n": -6 },
"added_lines_are_named_additions": "3 of 4 - ai/solution-blueprint.zod.ts, automation/builtin-node-config.zod.ts, automation/io-node-config.zod.ts. The 4th is ai/embedding.zod.ts moving from the Core section to Transitive in the same file, not a new pointer: it leaves core in the same diff. Net published pointers for objectstack-ai 20 to 17.",
"other_five_indexes": "byte-identical to origin/main"
},
"label": "skip-changeset applied and read back; union preserved (size/l kept). No changeset added.",
"gates": {
"derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no path args, from the worktree at eed6bb0f - 53 commands, 7 paths, no STALE TREE warning",
"aggregate": "53 of 53 derived commands exit 0, all at head eed6bb0f; exits captured before any pipe",
"named": [
{ "gate": "pnpm --filter @objectstack/spec check:skill-refs", "exit": 0, "verdict": "9 generated files in sync with packages/spec" },
{ "gate": "pnpm --filter @objectstack/spec check:skill-examples", "exit": 0, "verdict": "257 prose examples type-check across 3 surface(s)" },
{ "gate": "pnpm --filter @objectstack/spec check:llms-txt", "exit": 0, "verdict": "packages/spec/llms.txt: 97 claim(s) re-derived" },
{ "gate": "pnpm --filter @objectstack/spec typecheck", "exit": 0, "verdict": "green; tsconfig.scripts.json includes scripts/**/*, so the new lib and its test file are both inside a checked program - verified in the config, not assumed" },
{ "gate": "pnpm check:doc-authoring", "exit": 0, "verdict": "46 published skill files clean - no internal issue-id references" },
{ "gate": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes --self-test: 75 assertions over a temp git repo" },
{ "gate": "node scripts/check-system-context-census.mjs", "exit": 0, "verdict": "106 elevation read sites in 20 packages across 45 files, all anchored" },
{ "gate": "pnpm check:changeset-gate-self-tests", "exit": 0, "verdict": "check-changeset-no-major --self-test: 116 assertions" },
{ "gate": "pnpm check:empty-changeset", "exit": 0, "verdict": "No empty-frontmatter changeset introduced by this diff" },
{ "gate": "node scripts/check-skills-token-ratchet.mjs", "exit": 0, "verdict": "36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted" },
{ "gate": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0, "verdict": "64 cases pass" },
{ "gate": "pnpm check:pm-skill-ratchet", "exit": 0, "verdict": "check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 1 line" },
{ "gate": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "49 declaration(s) across 4 rostered name(s), every one an array" },
{ "gate": "node scripts/pm/bare-root-worklist.mjs --self-test", "exit": 0, "verdict": "54 live row(s), none stale, none missing, none contradicted - the pin on this generator's ROOT_DIR_WATCH_HINTS" },
{ "gate": "pnpm --filter @objectstack/spec check:authorable-surface", "exit": 0, "verdict": "Successfully generated 1603 schemas" },
{ "gate": "pnpm --filter @objectstack/spec exec vitest run scripts/skill-map-guards.test.ts", "exit": 0, "verdict": "Test Files 1 passed (1) - Tests 29 passed (29)" }
],
"prerequisite_then_green": "check:doc-formula-expressions, check:dual-build-cjs-loads, check:type-check-debt and check:skill-examples first answered PREREQUISITE NOT MET (exit 3 or a build refusal) - read as NOT MEASURED, not as findings - and were re-run to exit 0 after pnpm exec turbo run build over the package closure (71 tasks)",
"silent_roster_run_anyway": "the derivation scored 33 families silent because their roster is a file list; the skills ones were run rather than read as clearance: check-skills-token-ratchet (+ self-test), check-published-list-mirrors, check-single-claim-paths, check-partof-closing-keyword - all exit 0",
"not_run": "none of the derived families",
"reverse_verification": "3 guard ablations, all red as predicted, each naming the injected entry: one-owner (exit 1), core-entry-shape (exit 1), transitive-allowlist package name (exit 1); baseline exit 0. Mutations confirmed on disk by counting the injected text; restores are git checkout HEAD -- on absolute paths under a trap, proven by empty git diff HEAD AND a git hash-object match against the HEAD blob. No dist involved: tsx and vitest resolve ./lib/skill-map-guards as a relative source path with no exports boundary, so the mutated bytes are the bytes that ran."
},
"deviations_from_claim_surface": [
"SURFACE: added packages/spec/scripts/lib/skill-map-guards.ts. The claim named the generator plus a test file 'in the generator's own convention'; that convention is measurably lib/NAME.ts paired with scripts/NAME.test.ts (26 such pairs, e.g. lib/export-list.ts with export-list.test.ts). Needed because the generator self-executes on import, so guard logic inside it cannot be unit-tested.",
"RULING: the 14562 one-owner guard ships as 'at most one owner UNLESS declared in SHARED_CORE_SCHEMAS with a reason', not the flat rule. The seat ruling's stated ground was 'zero legitimate instances after this drop'; measurement at base found FOUR duplicates, three deliberate (data/validation.zod.ts data+automation, data/datasource.zod.ts and data/seed.zod.ts data+platform, the last two already carrying their reason as a map comment). The flat rule refuses origin/main's own map. Two extra guards keep the ledger from being an allowlist: a reasonless row is refused, and so is a row whose sharing has gone.",
"RULING: check:doc-authoring's prescribed remedy (strip the tracker id AT THE SOURCE and regenerate) was NOT taken, because that source is a .zod.ts this family may not edit, is a file the package publishes (which would reopen the changeset decision), and its sentence is also projected to content/docs/references/automation/io-node-config.mdx. The strip is applied at the boundary into the skill catalog instead - the corpus the rule is actually about, and the one where the gate flags it. Both deviations are argued in the PR body for a reviewer to overrule."
],
"mcp_calls": 18,
"open_questions": [
{
"question": "The 14562 seat ruling forbade a duplicate-ownership rule on the ground that there would be zero legitimate instances. Three deliberate duplicates exist at base. Keep the declared-ledger guard, or take the flat rule and delete those three published pointers?",
"options": [
"A - keep SHARED_CORE_SCHEMAS as shipped: the next undeclared duplicate still refuses at generation time, and the three existing ones stay published with a stated reason",
"B - flat rule: delete data/validation.zod.ts from objectstack-automation and data/datasource.zod.ts + data/seed.zod.ts from objectstack-platform, then drop the ledger"
],
"recommendation": "A. Option B deletes three pointers no card has adjudicated, and two of them are the surface objectstack-platform absorbed from the retired quickstart skill - the ledger's three rows are read by the gate on every run, which is not the unread spread the ruling was guarding against."
},
{
"question": "Internal tracker ids reaching the published catalog: strip at the boundary (as shipped) or at the source as check:doc-authoring prescribes?",
"options": [
"A - as shipped: stripInternalIssueIds in the generator, covering every future pointer row, no .zod.ts touched, no changeset, no docs tree in the diff",
"B - edit packages/spec/src/automation/io-node-config.zod.ts's module header, add a patch changeset, regenerate content/docs/references/automation/io-node-config.mdx as well"
],
"recommendation": "A. The gate does not flag the identical sentence on the docs page, so the rule is about the skill catalog specifically and the boundary is where it belongs; B costs three surfaces to remove one token, two of them explicitly out of this family's scope."
}
],
"out_of_scope_findings": [
"filed as #15263: ai/solution-blueprint.zod.ts publishes an Exports: list instead of its ADR-0033 sentence - its module header is disqualified by the const that immediately follows it. Same class as the landed #14441, opposite shape (the right block suppressed rather than a wrong block published). Repair is a .zod.ts edit, out of this family's scope.",
"filed as #15264: census residue this PR recorded but did not act on - objectstack-api advertises api/rest-server.zod.ts with zero mentions in its authored markdown, and objectstack-platform's index omits stack.zod.ts although defineStack is the body's whole subject. Unadjudicated rows on a governed customer surface, kept off this PR deliberately."
]
}
ACCEPT (family: #14462 anchor · #14466 · #14562 · #14565) — review of record for PR #15268 (head eed6bb0f), domain:spec seat, session_01H2oQebDDxYKfWZusyd8GXk (os-justin), 2026-09-04T07:56Z. Governed route (skills/** regenerated with its co-edited generator): the PR stays draft for a human merge.
Verified against GitHub and origin/main, not against the report:
PR form: draft, base main, four Fixes lines (one per member) — every member's criterion is delivered in full, so closing all four on merge is right. Body scanned for closing keywords: only those four; every other # mention is bare.
Changed files (7) = generator + new lib/skill-map-guards.ts + its test + four regenerated _index.md (ai · automation · formula · i18n); the other five indexes untouched. No .zod.ts, no SKILL.md body, no hand-edited index, no content/docs/releases/. The lib/ file is a surface deviation from the claim and is accepted: the generator's own convention is lib/NAME.ts + scripts/NAME.test.ts, and the generator self-executes on import.
skills/** net line delta −9 (4 added, 13 removed) against a budget of ≤ +6; three of the four added lines are the members' named additions, the fourth is embedding moving from Core to Transitive in the same file. Published pointers for objectstack-ai: 20 → 17.
Gate readings pinned to head eed6bb0f = the PR head. 53 derived families exit 0; check:skill-refs9 generated files in sync; check:doc-authoring46 published skill files clean; the guard tests 29 passed; reverse verification drives each of the three guards red with a named refusal, restores proven by blob hash. Four prerequisite-gated families re-run green after the closure build; none reported as green without measurement.
CI on eed6bb0f at 07:50Z: 17 completed checks all success (incl. Type Check · source gates, Governed Surface Queue Guard, Spec property liveness, Check Changeset); Lint & Repo Gates, Type Check · workspace / consumer / debt ledger, Build Core, Test Core ×6, Dogfood ×4, Temporal Conformance in_progress. No seat flips this PR; the human merge reads the final conclusions.
Two seat rulings corrected on the record (the dev falsified a premise by measurement — a good run, not a rework):
Tracker ids in the catalog.check:doc-authoring's remedy text says strip at the source; the PR strips at the generator boundary (stripInternalIssueIds on the description path). This seat's reading of the gate: its ROOTS are .claude / docs / skills / content, and the content/docs corpus is held by a baseline of pinned prose ids while skills/** is zero-tolerance — so the rule really is about the customer-loaded catalog, and a boundary rule that makes the class impossible for every future pointer row is the shape the triage asked for ("impossible, not corrected once"). Ruled: option A as shipped. Known rough edge, accepted: an owner/repo#N spelling strips to a sentence with a gap (the test pins removed in — use the rule); pointer rows are one-sentence descriptions and the alternative is a .zod.ts edit + changeset + docs regeneration for one token. A reviewer on the human-merge path may overrule either ruling; both are argued in the PR body.
Out-of-scope findings, listed as a group (sweep criterion: a SKILL_MAP row whose pointer the owning SKILL.md never names, or a schema the body names with no pointer — only rows backed by a consumer census or an ADR retirement were acted on; the rest were recorded): #15263 (solution-blueprint.zod.ts header disqualified by the following const — a .zod.ts repair) and #15264 (objectstack-api → api/rest-server.zod.ts advertised-not-taught; objectstack-platform omits stack.zod.ts). Both filed bare by the dev; this seat labels them finding for the triage round.
Landing (governed): stays draft; review requested from os-zhuang + hotlong by this seat at 07:53Z; listed as "awaiting a human merge" in the round report. On merge the four Fixes lines close the family and pm:dispatched leaves with the closes (the close-out patrol confirms).
Landed (family: #14462 · #14466 · #14562 · #14565) — domain:spec seat, session_01H2oQebDDxYKfWZusyd8GXk, 2026-09-04T11:29Z. PR #15268 went through the governed human path: approved by os-zhuang 07:53Z, enqueued by a human after the seat's nudge, MERGED through the merge queue as 445a25f6 (squash); the four Fixes lines closed the family at 08:59Z. Probed on origin/main6e67b86c (11:27Z): packages/spec/scripts/build-skill-references.ts:38 imports the guards from ./lib/skill-map-guards, packages/spec/scripts/lib/skill-map-guards.ts is present, the formula index carries no date-macros row, the automation index no state-machine row. pm:dispatched stripped on all four (read-modify-write: documentation · priority:p2 · domain:spec kept). The stroke is late by design of the day: the seat crossed the 5-hour usage wall between 09:1xZ and 10:20Z; no card was silently closed in the window (closed domain:spec since 08:44Z = this family + the epic's #15006 / #15007 / #15232, all by their own merged PRs). The two seat rulings corrected on this family's review (5537457796) stand for the maintainer's veto; the two findings the dev filed (#15263, #15264) are in the triage round.
Activity
huangyiirene commentedon Sep 2, 2026
Triage:
documentation·priority:p2·pm:queue·domain:spec· typeTask. First grading,findingcomes off. ⭐ Promoted to the family anchor — see the scope note below.domain:spec: the map ispackages/spec/scripts/build-skill-references.ts:98-109and the_index.mdfiles are generated from it. ⛔ The generated indexes are not hand-edited.p2 because the index ships to third parties via
npx skills add, and both directions mislead an agent reader: five schemas are advertised that the body never teaches (three with zero consumers outsidepackages/spec), so an agent following the indexReads intonode_modulesfor guidance that does not exist; andai/solution-blueprint.zod.ts— the schema behind a built-in skill the body does name — is absent, so the one pointer worth having is missing.Ruling: narrow the map, add
solution-blueprint. ⛔ Do not widen the body.solution-blueprint— the card is right that this half is unambiguous in either direction, because the body already names the built-in skill it backs.⭐ Scope: run the census for all eleven packages, not just this one
The card's own closing line is the important one — "Worth checking whether the same unreconciled shape exists for the other 10 packages'
SKILL_MAPentries; this audit only measuredobjectstack-ai." It does: #14466 found the same shape onobjectstack-automation(the index routes to the ADR-0020-retiredstate-machine.zod.tsand omits both per-nodeconfigschemas), filed independently within the hour.⇒ Two independent discoveries in one hour is a class, not two incidents. ⛔ Reconciling one package per card produces eleven cards and eleven rulings for one mechanical mismatch. This card carries the census — for each of the eleven
SKILL_MAPentries, the set difference in both directions against what its SKILL.md teaches — and applies the ruling above uniformly. #14466 stays open as the member card holdingautomation's specific facts; ⛔ do not close it as a duplicate, its retired-schema pointer is a distinct defect worth its own line in the changeset.state-machine.zod.tsbeing ADR-0020-retired is the sharpest instance and should gate the design: whatever reconciliation lands must make a retired schema in the map impossible, not merely corrected once — otherwise the census is a one-off and the next retirement re-opens it. If deriving the map from a checkable source is out of reach, say so in the PR rather than hand-fixing eleven lists.Dedup accepted as run — one targeted⚠️ Worth repeating for future filers: that control is what makes the result readable, because
search_issuesvalidated in-session by a control query that returned its known hit.search_issuesreturns intermittent false zeros in this repo (#13326).Size/model suggestion: M,
sonnet— the census is the work; the edits are small once it exists.Generated by Claude Code
os-justin commentedon Sep 4, 2026
Claim: PM loop round R1 (slot refill) —
domain:specseat (seat post #6017). Family dispatch, this card is the anchor (triage 5506970439 promoted it): theSKILL_MAPreconciliation class inpackages/spec/scripts/build-skill-references.ts. Fold-or-serial answered: FOLD, five gates — ① same defect shape and same fix (a generator-owned reference index disagreeing with the owning SKILL.md, repaired in the generator and regenerated; #14565's closure-step mechanism is the same generator's second half, which the triage on #14562 ordered to be designed together with the map gate); ② same file / same worktree / one changeset / one queue slot; ③ every member gradedpm:queue·p2·domain:specby triage (5506970439 · 5506975178 · 5515135764 · 5514974653), none in the decision box; ④ per-member criterion named below; ⑤ exclusion list named below. Members: #14466 (objectstack-automation: the ADR-0020-retiredstate-machine.zod.tspointer leaves,automation/builtin-node-config.zod.ts+automation/io-node-config.zod.tsjoin), #14562 (objectstack-formula:data/date-macros.zod.tsmapped to two packages), #14565 (objectstack-i18n: the transitive-closure step routes 5 of 7 pointers at schemas unreachable from a bundle). Each member keeps its own claim pointer comment; the shared branch is named here; one PR with oneFixesline per member and one commit per member.Session:
session_01H2oQebDDxYKfWZusyd8GXk(GitHubos-justin)Branch:
claude/issue-14462-skill-map-reconciliationWorktree:
objectstack-issue-14462Domain:
domain:specFile surface:
packages/spec/scripts/build-skill-references.ts(SKILL_MAPentries + the guard(s) the design adds) and the generatedskills/*/references/_index.mdfiles it regenerates (9 packages onorigin/main9c1bcda3: ai · api · automation · data · formula · i18n · platform · query · ui), a test for the guard if the generator has a test file, a changeset orskip-changesetper the PR #14737 precedent (the labelling fix on this same generator, landed 2026-09-03). ⛔ No hand edit of any_index.md; ⛔ no SKILL.md body widened (a skills-flight card with its own budget, never a rider here); ⛔ no.zod.tsedited. Stop on breach; explain in the report.Container & model: M,
mode:subagent,model: opus—--tieron the generator + one index at9c1bcda3(06:33Z): no path-derived mandate; content: tooling + generated pointers, no contract accept/reject behaviour moves. Triage'ssonnetsuggestion not taken: the design half (a checkable source that makes a retired schema in the map impossible; the closure rule's feasibility) is a judgment.Clause-②: no
Governed surface:
skills/**is governed, andcheck-governed-merges --testat 06:33Z reads the co-edited generator + regenerated indexes as governed (its regeneration exception passes only a puregen:skill-refsregeneration, and splitting into two PRs leavescheck:skill-refsred between them) ⇒ this PR stays draft for human merge: review on this card, review requested from the authorised approvers, listed as "awaiting a human merge" in the round report. Net line budget inskills/**: ≤ +6 lines across all nine_index.mdfiles combined, every added line one of the members' named additions (ai/solution-blueprint.zod.ts, the two automation config files); narrowing should land net-negative.Serial constraints cleared: 0 open PRs on
build-skill-references.tsor anyskills/*/references/_index.mdat 06:33Z (branch-name read of 18 open PRs; dev re-checks at worktree time); PR #14737 (#14441, the "Sort Node" labelling fix on this generator) landed 2026-09-03 — base on currentmain; in-flight lane siblings #14414 (automation/execution.zod.tsdescribes) and #14446 (liveness/**) do not touch this surface (a later regeneration re-merges through os-regen if #14414 lands first); H17 index:automation/webhook.zod.ts(#2657) andui/view.zod.ts(#8346) are pointed at, not edited — no hit. Exclusion list (look like family, are not): #14441 (labelling, landed); #14611 (gen:declaration-map, a different generator); the four skills flights #14305 · #14308 · #14315 · #14316 (SKILL.md bodies, own budgets); any SKILL.md widening.Generated by Claude Code
os-justin commentedon Sep 4, 2026
Dispatch (R1 slot refill, 2026-09-04T06:36Z) —
domain:specseat,session_01H2oQebDDxYKfWZusyd8GXk(os-justin), seat post #6017. Family dispatch: anchor #14462 + members #14466 · #14562 · #14565 (claims 5536679159 · 5536680100 · 5536681114 · 5536682056).mode:subagent,model: opus, size M, Clause ② no. Governed landing: the PR stays draft for human merge (never flipped ready, never queued by an agent seat). The dev leaves its ownClaim:comment on this anchor before its first edit.Rulings (not re-decidable). Triage 5506970439 on this card, verbatim where operative: "Ruling: narrow the map, add
solution-blueprint. ⛔ Do not widen the body." "This card carries the census — for each of the [SKILL_MAP] entries, the set difference in both directions against what its SKILL.md teaches — and applies the ruling above uniformly." "whatever reconciliation lands must make a retired schema in the map impossible, not merely corrected once … If deriving the map from a checkable source is out of reach, say so in the PR rather than hand-fixing eleven lists." Triage 5506975178 (#14466): dropautomation/state-machine.zod.ts; the omitted per-nodeconfigschemas (automation/builtin-node-config.zod.ts,automation/io-node-config.zod.ts) join — "its retired-schema pointer is a distinct defect worth its own line in the changeset". Triage 5515135764 (#14562): "The class has two mechanisms … ⛔ Do not build theSKILL_MAP-only gate and declare the class closed." Seat ruling for #14562 (claim 5536681114): dropdata/date-macros.zod.tsfrom the formula entry; no duplicate-ownership rule; a loud one-owner guard instead. Triage 5514974653 (#14565): decide the closure rule's feasibility FIRST and say so in the PR body — reachability rule if it can be made precise, else a per-package transitive allowlist/denylist besideSKILL_MAP; ⛔ no hand edit of_index.md. ⛔ No SKILL.md body widened; ⛔ no.zod.tsedited.PM mechanism assumptions (verify; falsify freely). (a)
SKILL_MAPonorigin/main9c1bcda3has 9 entries (data · query · ai · api · automation · ui · platform · i18n · formula; the triage said eleven — count and report), 9 generatedskills/*/references/_index.mdfiles. (b) A checkable source for "retired": the file header ofautomation/state-machine.zod.tscarries the ADR-0020 retirement in prose only; the ADR-0087 registry (packages/spec/src/migrations/entries/retired-defs/**,RETIRED_DEFS_BY_MAJOR) names retired defs, not files; the liveness ledger classifies properties. The dev decides whether any of these is a precise source for a "no retired schema in the map" guard; if none is, the PR says so (the triage accepts that answer) and the guard the PR still ships is the mechanical one: everySKILL_MAPpath must exist and be exported by an entry, and appears in at most one package (loud refusal at generation). (c) The census output (per package: advertised-not-taught, taught-not-advertised) belongs in the PR body as a table; the SKILL.md bodies are read, never edited. (d)check:skill-refsis the drift gate (tsx scripts/build-skill-references.ts --check);gen:skill-refsregenerates; a generator with a test file gets a negative test for each guard. (e) Changeset vsskip-changeset: follow PR #14737's precedent on this generator; read that PR's files before choosing.PM suggested route (optional). One commit per member: anchor (census + the
objectstack-ainarrowing +ai/solution-blueprint.zod.ts+ the guards), #14466, #14562, #14565 (closure rule or list), then one regeneration commit if the generator emits everything at once. PR body: the census table, the feasibility answer for the closure step, the guard(s) and their negative tests, the net line delta inskills/**.Surface, budget, gates, report. File surface = the anchor claim 5536679159 (stop on breach). Net line budget in
skills/**: ≤ +6 lines across all nine_index.mdfiles combined; every added line one of the members' named additions; over budget ⇒ stop and report, ⛔ never raise it. Derive gates from your actual paths after the last commit (node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no path args); at minimumpnpm --filter @objectstack/spec check:skill-refs,check:skill-examples(build its prerequisite first),check:llms-txt,pnpm --filter @objectstack/spec check:scripts-typecheck(or thetypecheckcomposite),pnpm check:doc-authoring,pnpm check:nul-bytes,node scripts/check-system-context-census.mjs, the skills token ratchet family the derivation names. Report:os-dev-reportfirst as a comment on this anchor (members get a one-line pointer each), then as the return; machine-checkable fields only, plus the per-member criterion verdicts and theskills/**net line delta.Generated by Claude Code
os-justin commentedon Sep 4, 2026
Claim:
Session:
session_01H2oQebDDxYKfWZusyd8GXkBranch:
claude/issue-14462-skill-map-reconciliation(pushed empty at claim time as the write-route probe; base9c1bcda3)Worktree:
objectstack-issue-14462Members covered: #14462 (anchor) · #14466 · #14562 · #14565 — one PR, one commit per member, one
Fixesline per member.File surface (as claimed by the PM at 5536679159, unchanged):
packages/spec/scripts/build-skill-references.ts— theSKILL_MAPentries plus the guards the design addsskills/*/references/_index.mdfiles, regenerated only viapnpm --filter @objectstack/spec gen:skill-refspackages/spec/scripts/*.test.ts), carrying the negative tests for each guardskip-changesetlabel or a changeset, per the PR fix(spec): givedata/query.zod.tsa module header so its pointer rows name the query AST #14737 precedent readNot touched: any SKILL.md body, any
.zod.tssource,content/docs/releases/**, any hand edit of an_index.md.Net line budget in
skills/**: not more than +6 across the nine indexes combined, every added pointer one of the members' named additions. Narrowing lands net-negative.Clause-②: no
Generated by Claude Code
os-justin commentedon Sep 4, 2026
os-dev-report
{ "issue": 14462, "family": [14462, 14466, 14562, 14565], "status": "done", "branch": "claude/issue-14462-skill-map-reconciliation", "pr": "https://github.com/objectstack-ai/objectstack/pull/15268", "pr_state": "draft (governed surface; never flipped ready, no auto-merge armed)", "head_sha": "eed6bb0f", "base": "9c1bcda3, then merged origin/main 1bc3c092 mid-run to clear a dispatch-gates STALE TREE warning on scripts/pm/check-skill-line-ratchet.mjs", "premise_still_valid": true, "premise_still_valid_per_member": { "14462": true, "14466": true, "14562": true, "14565": true }, "premise_evidence": { "14462": "SKILL_MAP['objectstack-ai'] at 9c1bcda3 lists conversation/mcp/embedding/knowledge-document/usage and lacks ai/solution-blueprint.zod.ts; that file exists (packages/spec/src/ai/solution-blueprint.zod.ts, 28854 bytes) and the SKILL.md names solution_design at line 374", "14466": "SKILL_MAP['objectstack-automation'] lists automation/state-machine.zod.ts and lacks both config files; both exist (builtin-node-config 38368 bytes, io-node-config 22085 bytes)", "14562": "data/date-macros.zod.ts present in both the objectstack-query and objectstack-formula core lists", "14565": "the i18n index carried all five named unreachable pointers; DRIFT: it carries EIGHT transitive pointers at this base, not the seven the card measured — shared/value-domain.zod.ts joined later via a new import edge. All eight are gone except the two kept deliberately." }, "pm_assumptions_checked": { "nine_not_eleven": "CONFIRMED 9 SKILL_MAP entries and 9 generated indexes (triage said eleven); 59 core entries total", "checkable_retired_source": "FALSIFIED in all three candidate forms - reported in the PR body as the answer the triage said it would accept", "check_skill_refs_is_the_drift_gate": "CONFIRMED", "changeset_precedent_14737": "CONFIRMED and read: #14737 took a changeset because it edited packages/spec/src/data/query.zod.ts, which is inside the files allowlist. No .zod.ts is edited here, so skip-changeset applies" }, "member_criteria": { "14466": "PASS - state-machine absent from the whole automation index (not merely moved to transitive; grep count 0); both config schemas present as core rows", "14562": "PASS - the formula entry is one file (shared/expression.zod.ts); the regenerated index carries no date-macros row; the one-owner guard exists with 6 negative tests. DEVIATION on the guard shape, see deviations", "14565": "PASS - the regenerated i18n index lists none of data/filter, kernel/metadata-protection, shared/expression, data/field-value, shared/suggestions (nor shared/value-domain, the eighth); keeps shared/identifiers; KEEPS data/field.zod.ts, the call left to this seat, because FieldTranslationSchema.options is keyed by select-option value and SelectOptionSchema is the declaration those keys must match", "14462": "PASS - census run over all 9 entries in both directions and tabled in the PR body; the ai entry narrowed by five and gained solution-blueprint; the two-mechanism question answered explicitly (two guards, one module); the retired-source feasibility answered NO with three measurements" }, "files_changed": [ "packages/spec/scripts/build-skill-references.ts", "packages/spec/scripts/lib/skill-map-guards.ts (new)", "packages/spec/scripts/skill-map-guards.test.ts (new)", "skills/objectstack-ai/references/_index.md (generated)", "skills/objectstack-automation/references/_index.md (generated)", "skills/objectstack-formula/references/_index.md (generated)", "skills/objectstack-i18n/references/_index.md (generated)" ], "commits": [ "3e9e2f67 anchor 14462 - ai narrowing, solution-blueprint, checkCoreEntryShape", "fc2acf06 member 14466 - automation entry swap", "5607ed5a member 14562 - formula drop, checkSingleOwner, SHARED_CORE_SCHEMAS", "735fc9d7 member 14565 - TRANSITIVE_ALLOWLIST, checkTransitiveAllowlist, i18n", "c412a47a merge origin/main", "eed6bb0f stripInternalIssueIds - the catalog boundary rule the 14466 addition forced" ], "skills_net_line_delta": { "net": -9, "added": 4, "removed": 13, "budget": "not more than +6", "per_index": { "ai": -3, "automation": 1, "formula": -1, "i18n": -6 }, "added_lines_are_named_additions": "3 of 4 - ai/solution-blueprint.zod.ts, automation/builtin-node-config.zod.ts, automation/io-node-config.zod.ts. The 4th is ai/embedding.zod.ts moving from the Core section to Transitive in the same file, not a new pointer: it leaves core in the same diff. Net published pointers for objectstack-ai 20 to 17.", "other_five_indexes": "byte-identical to origin/main" }, "label": "skip-changeset applied and read back; union preserved (size/l kept). No changeset added.", "gates": { "derivation": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, no path args, from the worktree at eed6bb0f - 53 commands, 7 paths, no STALE TREE warning", "aggregate": "53 of 53 derived commands exit 0, all at head eed6bb0f; exits captured before any pipe", "named": [ { "gate": "pnpm --filter @objectstack/spec check:skill-refs", "exit": 0, "verdict": "9 generated files in sync with packages/spec" }, { "gate": "pnpm --filter @objectstack/spec check:skill-examples", "exit": 0, "verdict": "257 prose examples type-check across 3 surface(s)" }, { "gate": "pnpm --filter @objectstack/spec check:llms-txt", "exit": 0, "verdict": "packages/spec/llms.txt: 97 claim(s) re-derived" }, { "gate": "pnpm --filter @objectstack/spec typecheck", "exit": 0, "verdict": "green; tsconfig.scripts.json includes scripts/**/*, so the new lib and its test file are both inside a checked program - verified in the config, not assumed" }, { "gate": "pnpm check:doc-authoring", "exit": 0, "verdict": "46 published skill files clean - no internal issue-id references" }, { "gate": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes --self-test: 75 assertions over a temp git repo" }, { "gate": "node scripts/check-system-context-census.mjs", "exit": 0, "verdict": "106 elevation read sites in 20 packages across 45 files, all anchored" }, { "gate": "pnpm check:changeset-gate-self-tests", "exit": 0, "verdict": "check-changeset-no-major --self-test: 116 assertions" }, { "gate": "pnpm check:empty-changeset", "exit": 0, "verdict": "No empty-frontmatter changeset introduced by this diff" }, { "gate": "node scripts/check-skills-token-ratchet.mjs", "exit": 0, "verdict": "36 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted" }, { "gate": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0, "verdict": "64 cases pass" }, { "gate": "pnpm check:pm-skill-ratchet", "exit": 0, "verdict": "check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 1 line" }, { "gate": "pnpm check:watch-hint-literal", "exit": 0, "verdict": "49 declaration(s) across 4 rostered name(s), every one an array" }, { "gate": "node scripts/pm/bare-root-worklist.mjs --self-test", "exit": 0, "verdict": "54 live row(s), none stale, none missing, none contradicted - the pin on this generator's ROOT_DIR_WATCH_HINTS" }, { "gate": "pnpm --filter @objectstack/spec check:authorable-surface", "exit": 0, "verdict": "Successfully generated 1603 schemas" }, { "gate": "pnpm --filter @objectstack/spec exec vitest run scripts/skill-map-guards.test.ts", "exit": 0, "verdict": "Test Files 1 passed (1) - Tests 29 passed (29)" } ], "prerequisite_then_green": "check:doc-formula-expressions, check:dual-build-cjs-loads, check:type-check-debt and check:skill-examples first answered PREREQUISITE NOT MET (exit 3 or a build refusal) - read as NOT MEASURED, not as findings - and were re-run to exit 0 after pnpm exec turbo run build over the package closure (71 tasks)", "silent_roster_run_anyway": "the derivation scored 33 families silent because their roster is a file list; the skills ones were run rather than read as clearance: check-skills-token-ratchet (+ self-test), check-published-list-mirrors, check-single-claim-paths, check-partof-closing-keyword - all exit 0", "not_run": "none of the derived families", "reverse_verification": "3 guard ablations, all red as predicted, each naming the injected entry: one-owner (exit 1), core-entry-shape (exit 1), transitive-allowlist package name (exit 1); baseline exit 0. Mutations confirmed on disk by counting the injected text; restores are git checkout HEAD -- on absolute paths under a trap, proven by empty git diff HEAD AND a git hash-object match against the HEAD blob. No dist involved: tsx and vitest resolve ./lib/skill-map-guards as a relative source path with no exports boundary, so the mutated bytes are the bytes that ran." }, "deviations_from_claim_surface": [ "SURFACE: added packages/spec/scripts/lib/skill-map-guards.ts. The claim named the generator plus a test file 'in the generator's own convention'; that convention is measurably lib/NAME.ts paired with scripts/NAME.test.ts (26 such pairs, e.g. lib/export-list.ts with export-list.test.ts). Needed because the generator self-executes on import, so guard logic inside it cannot be unit-tested.", "RULING: the 14562 one-owner guard ships as 'at most one owner UNLESS declared in SHARED_CORE_SCHEMAS with a reason', not the flat rule. The seat ruling's stated ground was 'zero legitimate instances after this drop'; measurement at base found FOUR duplicates, three deliberate (data/validation.zod.ts data+automation, data/datasource.zod.ts and data/seed.zod.ts data+platform, the last two already carrying their reason as a map comment). The flat rule refuses origin/main's own map. Two extra guards keep the ledger from being an allowlist: a reasonless row is refused, and so is a row whose sharing has gone.", "RULING: check:doc-authoring's prescribed remedy (strip the tracker id AT THE SOURCE and regenerate) was NOT taken, because that source is a .zod.ts this family may not edit, is a file the package publishes (which would reopen the changeset decision), and its sentence is also projected to content/docs/references/automation/io-node-config.mdx. The strip is applied at the boundary into the skill catalog instead - the corpus the rule is actually about, and the one where the gate flags it. Both deviations are argued in the PR body for a reviewer to overrule." ], "mcp_calls": 18, "open_questions": [ { "question": "The 14562 seat ruling forbade a duplicate-ownership rule on the ground that there would be zero legitimate instances. Three deliberate duplicates exist at base. Keep the declared-ledger guard, or take the flat rule and delete those three published pointers?", "options": [ "A - keep SHARED_CORE_SCHEMAS as shipped: the next undeclared duplicate still refuses at generation time, and the three existing ones stay published with a stated reason", "B - flat rule: delete data/validation.zod.ts from objectstack-automation and data/datasource.zod.ts + data/seed.zod.ts from objectstack-platform, then drop the ledger" ], "recommendation": "A. Option B deletes three pointers no card has adjudicated, and two of them are the surface objectstack-platform absorbed from the retired quickstart skill - the ledger's three rows are read by the gate on every run, which is not the unread spread the ruling was guarding against." }, { "question": "Internal tracker ids reaching the published catalog: strip at the boundary (as shipped) or at the source as check:doc-authoring prescribes?", "options": [ "A - as shipped: stripInternalIssueIds in the generator, covering every future pointer row, no .zod.ts touched, no changeset, no docs tree in the diff", "B - edit packages/spec/src/automation/io-node-config.zod.ts's module header, add a patch changeset, regenerate content/docs/references/automation/io-node-config.mdx as well" ], "recommendation": "A. The gate does not flag the identical sentence on the docs page, so the rule is about the skill catalog specifically and the boundary is where it belongs; B costs three surfaces to remove one token, two of them explicitly out of this family's scope." } ], "out_of_scope_findings": [ "filed as #15263: ai/solution-blueprint.zod.ts publishes an Exports: list instead of its ADR-0033 sentence - its module header is disqualified by the const that immediately follows it. Same class as the landed #14441, opposite shape (the right block suppressed rather than a wrong block published). Repair is a .zod.ts edit, out of this family's scope.", "filed as #15264: census residue this PR recorded but did not act on - objectstack-api advertises api/rest-server.zod.ts with zero mentions in its authored markdown, and objectstack-platform's index omits stack.zod.ts although defineStack is the body's whole subject. Unadjudicated rows on a governed customer surface, kept off this PR deliberately." ] }Generated by Claude Code
os-justin commentedon Sep 4, 2026
ACCEPT (family: #14462 anchor · #14466 · #14562 · #14565) — review of record for PR #15268 (head
eed6bb0f),domain:specseat,session_01H2oQebDDxYKfWZusyd8GXk(os-justin), 2026-09-04T07:56Z. Governed route (skills/**regenerated with its co-edited generator): the PR stays draft for a human merge.Verified against GitHub and
origin/main, not against the report:main, fourFixeslines (one per member) — every member's criterion is delivered in full, so closing all four on merge is right. Body scanned for closing keywords: only those four; every other#mention is bare.lib/skill-map-guards.ts+ its test + four regenerated_index.md(ai · automation · formula · i18n); the other five indexes untouched. No.zod.ts, no SKILL.md body, no hand-edited index, nocontent/docs/releases/. Thelib/file is a surface deviation from the claim and is accepted: the generator's own convention islib/NAME.ts+scripts/NAME.test.ts, and the generator self-executes on import.objectstack-automationreference index routes to the ADR-0020-retiredstate-machine.zod.tsand omits both per-nodeconfigschemas —SKILL_MAPinbuild-skill-references.ts#14466 PASS —state-machine.zod.tsis gone from the automation index entirely (it stays inobjectstack-ai's transitive list throughagent.zod.ts'slifecycle, the one surviving door),builtin-node-config+io-node-configare core rows. [finding] Theobjectstack-formulareference index advertisesdata/date-macros.zod.ts, a surface the SKILL.md routes to objectstack-query —SKILL_MAPinbuild-skill-references.tsmaps it to both #14562 PASS — the formula entry is one file, nodate-macrosrow,checkSingleOwnerrefuses an undeclared duplicate (6 negative tests). [finding] Theobjectstack-i18nreference index routes 5 of its 7 transitive pointers at schemas unreachable from a translation bundle — the closure step inbuild-skill-references.ts#14565 PASS — filter / metadata-protection / expression / field-value / suggestions / value-domain are gone from the i18n index;identifierskept;data/field.zod.tskept on theSelectOptionSchemareasoning, which this seat accepts. [finding] Theobjectstack-aigenerated reference index advertises 6 schemas the SKILL.md never teaches and omits the one it names —SKILL_MAPinbuild-skill-references.tsis unreconciled with the body #14462 PASS — the census table covers all nine entries in both directions (nine, not eleven — the triage's count is corrected on the record);ainarrowed by five and gainedsolution-blueprint; the two-mechanism question is answered with two guards in one module; the retired-source question is answered NO with three measurements, which is the answer the triage said it would accept.skills/**net line delta −9 (4 added, 13 removed) against a budget of ≤ +6; three of the four added lines are the members' named additions, the fourth isembeddingmoving from Core to Transitive in the same file. Published pointers forobjectstack-ai: 20 → 17.skip-changeseton the PR; verified — no.zod.tsedited,packages/spec/scripts/**is outside the package'sfilesallowlist,skills/is in no package. PR fix(spec): givedata/query.zod.tsa module header so its pointer rows name the query AST #14737's changeset was for itsquery.zod.tsedit, which this PR does not have.eed6bb0f= the PR head. 53 derived families exit 0;check:skill-refs9 generated files in sync;check:doc-authoring46 published skill files clean; the guard tests29 passed; reverse verification drives each of the three guards red with a named refusal, restores proven by blob hash. Four prerequisite-gated families re-run green after the closure build; none reported as green without measurement.eed6bb0fat 07:50Z: 17 completed checks allsuccess(incl. Type Check · source gates, Governed Surface Queue Guard, Spec property liveness, Check Changeset); Lint & Repo Gates, Type Check · workspace / consumer / debt ledger, Build Core, Test Core ×6, Dogfood ×4, Temporal Conformancein_progress. No seat flips this PR; the human merge reads the final conclusions.Two seat rulings corrected on the record (the dev falsified a premise by measurement — a good run, not a rework):
objectstack-formulareference index advertisesdata/date-macros.zod.ts, a surface the SKILL.md routes to objectstack-query —SKILL_MAPinbuild-skill-references.tsmaps it to both #14562 one-owner guard. This seat's ruling (5536681114) asked for a flat "at most one owner" rule and refused a declared-sharing ledger on the stated ground of "zero legitimate instances after this drop". Measured onorigin/main97bcd99eby this seat:SKILL_MAPcarries four duplicates, three of them deliberate —data/validation.zod.ts(data + automation,:87/:128),data/datasource.zod.ts(:89/:146) anddata/seed.zod.ts(:90/:147, both data + platform with their reason already in a map comment). The premise was false; the flat rule would red onmain's own map. Ruled: option A as shipped —SHARED_CORE_SCHEMASwith a mandatory reason, plus the two anti-rot guards (a reasonless row is refused; a row whose sharing is gone is refused). The operational demand stands: the next undeclared duplicate refuses at generation time. Correction noted on [finding] Theobjectstack-formulareference index advertisesdata/date-macros.zod.ts, a surface the SKILL.md routes to objectstack-query —SKILL_MAPinbuild-skill-references.tsmaps it to both #14562 as well.check:doc-authoring's remedy text says strip at the source; the PR strips at the generator boundary (stripInternalIssueIdson the description path). This seat's reading of the gate: itsROOTSare.claude/docs/skills/content, and thecontent/docscorpus is held by a baseline of pinned prose ids whileskills/**is zero-tolerance — so the rule really is about the customer-loaded catalog, and a boundary rule that makes the class impossible for every future pointer row is the shape the triage asked for ("impossible, not corrected once"). Ruled: option A as shipped. Known rough edge, accepted: anowner/repo#Nspelling strips to a sentence with a gap (the test pinsremoved in — use the rule); pointer rows are one-sentence descriptions and the alternative is a.zod.tsedit + changeset + docs regeneration for one token. A reviewer on the human-merge path may overrule either ruling; both are argued in the PR body.Out-of-scope findings, listed as a group (sweep criterion: a
SKILL_MAProw whose pointer the owning SKILL.md never names, or a schema the body names with no pointer — only rows backed by a consumer census or an ADR retirement were acted on; the rest were recorded): #15263 (solution-blueprint.zod.tsheader disqualified by the followingconst— a.zod.tsrepair) and #15264 (objectstack-api→api/rest-server.zod.tsadvertised-not-taught;objectstack-platformomitsstack.zod.ts). Both filed bare by the dev; this seat labels themfindingfor the triage round.Landing (governed): stays draft; review requested from
os-zhuang+hotlongby this seat at 07:53Z; listed as "awaiting a human merge" in the round report. On merge the fourFixeslines close the family andpm:dispatchedleaves with the closes (the close-out patrol confirms).Generated by Claude Code
os-justin commentedon Sep 4, 2026
Landed (family: #14462 · #14466 · #14562 · #14565) —
domain:specseat,session_01H2oQebDDxYKfWZusyd8GXk, 2026-09-04T11:29Z. PR #15268 went through the governed human path: approved byos-zhuang07:53Z, enqueued by a human after the seat's nudge, MERGED through the merge queue as445a25f6(squash); the fourFixeslines closed the family at 08:59Z. Probed onorigin/main6e67b86c(11:27Z):packages/spec/scripts/build-skill-references.ts:38imports the guards from./lib/skill-map-guards,packages/spec/scripts/lib/skill-map-guards.tsis present, the formula index carries nodate-macrosrow, the automation index nostate-machinerow.pm:dispatchedstripped on all four (read-modify-write:documentation·priority:p2·domain:speckept). The stroke is late by design of the day: the seat crossed the 5-hour usage wall between 09:1xZ and 10:20Z; no card was silently closed in the window (closeddomain:specsince 08:44Z = this family + the epic's #15006 / #15007 / #15232, all by their own merged PRs). The two seat rulings corrected on this family's review (5537457796) stand for the maintainer's veto; the two findings the dev filed (#15263, #15264) are in the triage round.Generated by Claude Code