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
skills/README.md truth + routing sweep: OLD/NEW "evaluate to null since M9.5" is anchored nowhere and contradicts the formula skill; "AI tool params" is not a CEL site; the cross-skill routing list lacks the upgrade-vs-platform and objectui inbound decision points #14794
Filed by the skills lane seat (session session_01LraLgQVGq8egUwfYZpbYt1) from the optimization programme's audit ledger (#14292: UPG-A-01, OUI-A-01, and two README truth items the per-package flights could not take because skills/README.md was outside every flight's file surface). Bare, unassigned; the seat dispatches it in-lane. Sibling: #14566 (I18N-A-03, the labels-vs-bundles bullet on the same list) — the same flight lands both, one PR, so the routing list is edited once.
Measured at origin/main89a156af88, 2026-09-03T01:43Z
skills/README.md:87 — "Legacy OLD / NEW evaluate to null since M9.5." M9.5 occurs nowhere else in packages/ or skills/; git grep -E '\bOLD\b|\bNEW\b' over packages/formula/src (non-test) returns 0 — no code evaluates those spellings to null. The formula skill says the opposite in substance: skills/objectstack-formula/SKILL.md:345-346 maps OLD.x → previous.x and NEW.x → record.x as legacy spellings to migrate, and :361 states previous is bound only on the events listed there. Two published files disagree; the README's sentence has no anchor. Settle at source (what the CEL parser actually does with a bare OLD) and keep one true clause — most likely "legacy OLD / NEW are not CEL; migrate per objectstack-formula's table" or simply drop the clause.
skills/README.md:105 — the "Any CEL expression" bullet lists "AI tool params" as a CEL site. git grep -i 'cel|formula|expression' over packages/spec/src/ai finds CEL nowhere on tool params — only {{var}} template interpolation on model-registry prompts (model-registry.zod.ts:121-122). The AI domain's real CEL site, per skills/objectstack-ai/SKILL.md:405, is a model-registry predicate. Replace the false item with the true one (or drop it).
UPG-A-01 — upgrade vs platform: an agent moving a project across a protocol major reaches for objectstack-platform (kernel/plugin lifecycle) and never learns objectstack-upgrade (:42 in the index) is the process skill for that; one bullet routing "moving a metadata project across a protocol major / a breaking changeset" to objectstack-upgrade.
OUI-A-01 — inbound route to objectui: the README names objectui only under "Related repositories" (:114); an agent authoring schema-driven UI for an app never learns the objectui skill (separate repo, skills/objectui/) exists; one bullet routing "rendering / composing the UI that consumes this metadata" to the objectui catalog.
One draft PR, first line Fixes #<this> and Fixes #14566. Items 1–2 are corrections (shrink or neutral). Items 3's three bullets are funded additions of roughly +25 tokens each, in the four existing bullets' shape and size — ⛔ no more than that (maintainer 2026-08-21: 「……不能为了一个小功能扩写很多。」); pay inside the file where a strict restatement exists, net as close to 0 as honesty allows, reported per item.
skills/README.md is outside the token-ratchet population (check-skills-token-ratchet.mjs:133); the generated region between <!-- BEGIN/END GENERATED: skills --> is untouched (check:skill-docs --check stays green). PR docs(skills): admit hand-authored reference files under references/ in the catalog anatomy #14786 (at the governed terminal) holds one line of the same file (:55, the anatomy tree) — disjoint hunks; the later to land merges main in.
Governed skills/** ⇒ draft, human merge; skip-changeset.
Claim: skills lane seat — filed and dispatched in one round (priority:p3 + pm:dispatched; domain:* left to triage, its single producer). The seat dispatches its own programme's follow-up in-lane; #14566 (the same list) is claimed in the same stroke so skills/README.md's routing list is edited once.
Session: session_01LraLgQVGq8egUwfYZpbYt1
Branch: claude/issue-14794-readme-truth-routing
Worktree: objectstack-issue-14794
Clause-②: no — catalog routing prose; item 1 is settled at source by the dev and cited, not claimed. Governed skills/** ⇒ draft PR; review requests are the seat's step.
Binding on the flight: the two corrections shrink or stay neutral; the three routing bullets (this card's two + #14566's one) are ~25 tokens each in the existing bullets' shape — the #14566 triage's size ruling (comment 5514978050) applies to all three; ⛔ no edit to any SKILL.md; the generated region of the README untouched; hunks disjoint from PR #14786's :55. First line Fixes #14794 and Fixes #14566; skip-changeset.
Claim: dev seat (os-dev subagent of the dispatching PM session — same session id, distinct seat)
Session: session_01LraLgQVGq8egUwfYZpbYt1
Branch: claude/issue-14794-readme-truth-routing (pushed empty at the branch point as a write-route probe)
Worktree: /home/user/objectstack-issue-14794
Branch point re-measured: origin/main89a156af88 — identical to the card's measurement (2026-09-03T01:43Z), no drift.
Scope taken, exactly as claimed by the lane seat: skills/README.md only — the :87OLD/NEW clause settled at source, the :105 "AI tool params" item corrected against packages/spec/src/ai, and three routing bullets (this card's two + #14566's one) at ~25 tokens each under the #14566 triage ruling (comment 5514978050). No SKILL.md edit, no touch to the README's generated region between the BEGIN/END GENERATED markers, hunks disjoint from PR #14786's anatomy-tree line. One draft PR, skip-changeset, stays draft for human merge.
{
"issue": 14794,
"also_fixes": 14566,
"status": "done",
"branch": "claude/issue-14794-readme-truth-routing",
"head_sha": "39da552e61a526f10a5951e3cf4d6d07ac78710a",
"pr": "https://github.com/objectstack-ai/objectstack/pull/14795",
"branch_point": "89a156af88 — re-measured, identical to the card's measurement, no drift. main has since advanced to 8f9ef6f7c8 (4 commits), none touching skills/README.md; PR #14786 has not landed, so the hunks are disjoint and no merge was needed.",
"items": [
{
"id": "1 — skills/README.md:87",
"before": "`@objectstack/spec`. Legacy `OLD` / `NEW` evaluate to `null` since M9.5.",
"after": "`@objectstack/spec`. Legacy `OLD` / `NEW` are not CEL — use `previous.` / `record.`.",
"source": "False in both halves. (a) M9.5: `git grep -rn 'M9\\.5' -- packages skills docs` returns exactly ONE hit — this README line itself. (b) They do not evaluate to null; they are UNDECLARED IDENTIFIERS. SCOPE_ROOTS (packages/formula/src/cel-engine.ts:95-119) is the published closed set of record-scope roots and contains neither. firstUndeclaredReference (cel-engine.ts:186-205) reports them as bare undeclared references — the class @objectstack/lint raises as an ERROR (packages/lint/src/validate-expressions.ts:490, 'Why it is an error and not a warning'). Measured against the built package, not inferred: SCOPE_ROOTS includes OLD=false NEW=false previous=true record=true; firstUndeclaredReference('OLD.amount != NEW.amount')='OLD'; ('NEW.status')='NEW'; ('previous.amount != record.amount')=null. The replacement's prescription is objectstack-formula's own table, skills/objectstack-formula/SKILL.md:345-346 (OLD.x to previous.x, NEW.x to record.x), so the two published files now agree."
},
{
"id": "2 — skills/README.md:105",
"before": "skill (data validations, automation guards, UI visibility, AI tool params).",
"after": "skill (data validations, automation guards, UI visibility).",
"source": "Diagnosis confirmed, prescribed replacement falsified. packages/spec/src/ai/tool.zod.ts matches cel|formula|expression ZERO times. But there is no model-registry predicate to swap in: 'predicate' occurs 0 times in packages/spec/src/ai/model-registry.zod.ts; its only expression-typed keys are system/user at :121-122, which are TemplateExpressionInputSchema — defined at packages/spec/src/shared/expression.zod.ts:117-124 as dialect 'template', the {{var}} interpolation form, NOT CEL. skills/objectstack-ai/SKILL.md:405-407 says the same in substance. The AI domain therefore has no CEL site at all, so the dispatch's stated alternative was taken: the item is DROPPED, not replaced. Adding an AI entry to a bullet headed 'Any CEL expression' would have swapped one false claim for another."
},
{
"id": "3 — skills/README.md:94-110, three routing bullets",
"before": "four decision points; none about labels, upgrade-vs-platform, or the consuming UI",
"after": "- **Labels vs. bundles** — a `label` you want translated is **objectstack-i18n**. / - **Upgrade vs. platform** — a protocol-major move is **objectstack-upgrade**. / - **Rendering this metadata** — the consuming UI is [objectui `skills/objectui/`](https://github.com/objectstack-ai/objectui).",
"source": "Each checked against the TARGET SKILL'S OWN frontmatter description. i18n: 'Author ObjectStack translation bundles — object/field labels, view text …'. upgrade: 'Use when a project is on an older protocol major and must move to the current one, when @objectstack/spec was bumped across a major …'. objectui: path confirmed on the objectui checkout, `git ls-tree origin/main skills/objectui/` at objectui origin/main 39af82f returns SKILL.md, README.md, evals/, guides/, rules/."
}
],
"premise_false": [
"Item 2's REMEDIATION half is false. The dispatch and the card both instruct: 'The AI domain's real CEL site per skills/objectstack-ai/SKILL.md:405 is a model-registry predicate. Replace the false item with the true one (verify it at packages/spec/src/ai/model-registry.zod.ts — find the predicate field and cite it)'. There is no predicate field: 'predicate' occurs 0 times in that file, and the two expression-typed keys it does carry (system/user, :121-122) are the TEMPLATE dialect, not CEL. The dispatch's own alternative ('or drop the item') was taken. The card's DIAGNOSIS half ('AI tool params is not a CEL site') is confirmed.",
"Item 1's original README claim is false in a sharper way than the card states. The card asks whether OLD/NEW 'evaluate to null'; the measured answer is that they are REJECTED as undeclared references — an error raised by @objectstack/lint — not silently nulled. The clause as written described a silent runtime degradation that does not exist."
],
"gates": [
{ "cmd": "pnpm --filter @objectstack/spec check:skill-docs", "exit": 0, "verdict": "Skill docs in sync (skills/README.md OK) — proves the generated region is byte-identical" },
{ "cmd": "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." },
{ "cmd": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0, "verdict": "check-skills-token-ratchet self-test: 64 cases pass." },
{ "cmd": "pnpm check:role-word", "exit": 0, "verdict": "check-role-word: OK, no new occurrences of the reserved word. 224 files; ledger unchanged at 43 baselined files / 120 occurrences." },
{ "cmd": "pnpm check:skill-identifier-liveness", "exit": 0, "verdict": "OK — Leg 1: 465 citation(s) over 46 published file(s); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)." },
{ "cmd": "pnpm check:skill-compatibility", "exit": 0, "verdict": "11 SKILL.md file(s) reconciled against 79 workspace packages" },
{ "cmd": "pnpm check:published-readme-links", "exit": 0, "verdict": "176 outbound link(s) across 60 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 27 docs-site page(s) resolved, 103/103 relative target(s) found — the new objectui link resolves" },
{ "cmd": "node scripts/check-nul-bytes.mjs", "exit": 0, "verdict": "OK (scanned 8064 text file(s); no raw ASCII control bytes)" },
{ "cmd": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "union member, green" },
{ "cmd": "node scripts/check-cross-package-test-inputs.mjs", "exit": 0, "verdict": "union member, green" },
{ "cmd": "node scripts/check-shard-attestation.mjs", "exit": 0, "verdict": "union member, green" },
{ "cmd": "node scripts/check-test-completeness.mjs", "exit": 3, "verdict": "PREREQUISITE NOT MET — NOT MEASURED, not red. 'grades a saved turbo run test log, and no log was named … the local reading for this gate is NOT MEASURED.' CI tees the log and passes the path, so CI is unaffected." },
{ "cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions", "exit": 0, "verdict": "First pass exited 3 (PREREQUISITE NOT MET — imports compiled @objectstack/formula and @objectstack/lint). Both were BUILT and the gate re-run rather than reported as a non-reading, because it is the gate nearest this change (item 1 puts previous./record. into published prose). Then: '22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean by @objectstack/formula.'" },
{ "cmd": "pnpm --filter @objectstack/spec run check:skill-docs", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:agent-test-spelling", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:corpus-claim-drift", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:doc-authoring", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:merge-driver", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:pm-governed-merges", "exit": 0, "verdict": "union member, green" },
{ "cmd": "pnpm check:skill-frame-sync", "exit": 0, "verdict": "union member, green" }
],
"gate_method": "Every exit code captured by redirect BEFORE any pipe (cmd redirected to a log; EXIT read; then tail). Each verdict quotes the gate's own printed line, never a bare exit status. The union was re-derived AFTER the last edit with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands`; its provenance line reads 'gate list derived from the tree of objectstack-ai/objectstack at commit 39da552e61' with change set '1 path(s) vs merge base 89a156af8' = skills/README.md. All 16 derived commands were run; the 8 dispatch-named gates were run as well.",
"reverse_verification": "check:skill-docs proven able to FAIL and to name this file. Implementation committed FIRST, so the restore leg's HEAD already contains it. Guarded by `trap restore EXIT INT TERM`, absolute paths throughout. Mutation landed on disk proven by grep counts flipping BOTH ways inside the generated region ('Construct ObjectQL queries' 1 to 0, 'Construct ObjectQL queried' 0 to 1) and the worktree blob moving 72afcf31b7 to e60bea9ecc — never by an editor's exit code. Mutated leg: exit 1, verdict 'skills/README.md is out of date — run pnpm --filter @objectstack/spec gen:skill-docs'. Restore leg: `git checkout HEAD -- ABSOLUTE_PATH` (pinned to HEAD, never a bare checkout, so it cannot restore from a polluted index), proven by blob hash equality against the HEAD blob 72afcf31b7 (non-empty AND matching), an EMPTY `git diff HEAD`, and anchor counts back to 1 / 0.",
"eslint": "Not a narrowing — skills/README.md is outside the linted population entirely, with all three pieces. (1) Population read from eslint's OWN config resolution, not from my reading of the globs: `eslint --print-config skills/README.md` emits an empty document (10 bytes); every files: selector in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs} and none matches markdown. (2) Count from --format json for the file: 1 result entry, errorCount 0, warningCount 1, and the single message is eslint's own 'File ignored because no matching configuration was supplied.' — zero rule findings because zero rules apply. (3) Invariance: the repo runs one eslint.config.mjs which 'never enables type-aware linting (no parserOptions.project, no typed @typescript-eslint rules) for ANY file, test or not' (eslint.config.mjs:326-328, carrying its own positive-control measurement), so no untouched file's verdict can move as a function of this diff. A full-repo `pnpm lint` is provably vacuous here.",
"token_delta": {
"method": "ceil(utf8_bytes / 4)",
"file_before": { "bytes": 7941, "tokens": 1986, "at": "89a156af88" },
"file_after": { "bytes": 8237, "tokens": 2060, "at": "39da552e61" },
"file_delta": { "bytes": 296, "tokens": 74 },
"item1": { "before_bytes": 75, "after_bytes": 91, "delta_bytes": 16, "delta_tokens": 4 },
"item2": { "before_bytes": 78, "after_bytes": 62, "delta_bytes": -16, "delta_tokens": -4 },
"items_1_and_2_combined": { "delta_bytes": 0, "delta_tokens": 0, "note": "neutral, as the budget requires — items 1 and 2 fund each other exactly" },
"item3": { "bullet_tokens": [21, 21, 33], "total_tokens": 75, "total_bytes": 296, "ruling": "at the #14566 triage ruling (comment 5514978050): ~25 tokens per bullet, ~75 total" },
"payment": "Item 2's drop of ', AI tool params' (-16 B) exactly funds item 1's truthful replacement (+16 B). A second payment is inside item 3 and is what brought the block from 84 tokens down to the ruling's 75: bullet 2's body does NOT restate 'not objectstack-platform' — the surviving site is the bullet's own heading, 'Upgrade vs. platform', which already names both sides. That is a strict restatement removed, not meaning shaved. NO FURTHER PAYMENT WAS AVAILABLE: the one candidate examined was the process-skill paragraph at :64-66 against the frontmatter rows at :75 (compatibility, 'for a process skill that binds to no schema') and :76 (metadata.domain, 'a delivery-process skill that teaches no schema'); rejected because the paragraph also carries two facts surviving nowhere else — that such a skill 'carries SKILL.md alone' (no references/ directory) and the SKILL_MAP mechanism behind it. Deleting it would have shaved meaning.",
"ratchet_population": "skills/README.md is outside it (scripts/check-skills-token-ratchet.mjs:133); the ratchet is green regardless."
},
"edit_landed_proof": { "M9.5": "1 to 0", "AI tool params": "1 to 0", "objectstack-i18n": "1 to 2", "objectstack-upgrade": "1 to 2", "objectui": "1 to 2" },
"scope_untouched": "No SKILL.md edited. The README's generated region between the BEGIN/END GENERATED markers untouched (check:skill-docs green proves it byte-for-byte). The anatomy tree at :50-62 untouched, so the hunks are disjoint from PR #14786's :55 — this diff's two hunks start at :85 and :104. No other README sentence edited. Diff is 1 file, +7 -2.",
"pr_state": "Draft (draft=true, read back). Label skip-changeset applied and read back as labels=['skip-changeset']. Never flipped ready, no auto-merge, no reviewers requested. skip-changeset justified against scripts/check-empty-changeset.mjs:359-362, which enumerates 'It releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, tests-only, and the like) -to- delete the changeset and apply the skip-changeset label (route 2)', and pins this exact shape as GREEN 3 at :559-565.",
"channel": "REST is 403 for this session (curl to api.github.com/repos/objectstack-ai/objectstack returned 403; gh is not installed), so ALL GitHub writes went through MCP — declaring the switch. Label write used the read-union-write-then-read-back fallback; note that issue_read get_labels cannot resolve a PR number ('Could not resolve to an Issue with the number of 14795'), so the read-back was taken via list_pull_requests filtered to this head branch.",
"mcp_calls": 15,
"out_of_scope_findings": [
"skills/objectstack-ai/SKILL.md:405-407 makes the SAME class of error this PR just fixed in the README, one level down: it writes 'any CEL predicate parses and resolves — in this domain that is a model-registry promptTemplate.system / .user'. Those two keys are TemplateExpressionInputSchema, i.e. dialect 'template' ({{var}} interpolation), NOT CEL — see packages/spec/src/shared/expression.zod.ts:117-124. So a published skill labels a template-dialect expression a 'CEL predicate'. The same sentence also omits the AI domain's other real expression site, the 5-field cron at packages/spec/src/ai/knowledge-source.zod.ts:28. Out of scope here twice over (the dispatch forbids any SKILL.md edit, and #14566's triage forbids expanding sibling skills), and NOT filed per the dispatch's instruction that out-of-scope findings go in the report only. Worth a card at triage's discretion: it is a published-surface truth defect, not cosmetics.",
"skills/README.md:114 'Related repositories' still describes objectui only as 'Studio UI (separate repo)' and does not say it publishes a skills catalog. OUI-A-01 noted this; the new routing bullet now carries the route, so the gap is covered functionally, but the two lines are slightly redundant and a future editor may want to merge them. Left untouched deliberately — the dispatch scoped this flight to the routing list and forbade other README sentences."
]
}
ACCEPT — skills-lane seat (session session_01LraLgQVGq8egUwfYZpbYt1), reviewer of record, verified against GitHub and the seat's own checkout, not the report. Covers #14794 and #14566 (one PR, both Fixes).
Diff read by the seat, item by item: (1) :87Legacy OLD / NEW evaluate to null since M9.5. → Legacy OLD / NEW are not CEL — use previous. / record. — seat re-read packages/formula/src/cel-engine.ts:95-119 at 8f9ef6f7c8: SCOPE_ROOTS is the closed root set (record, previous, input, output, os, vars, …, current_user) and carries neither OLD nor NEW; firstUndeclaredReference (:77, :186-205) reports them as undeclared — the lint's error class, not a silent null. M9.5 was anchored nowhere in packages/ or skills/. The new clause matches skills/objectstack-formula/SKILL.md:345-346. (2) :105 drops , AI tool params: tool.zod.ts has no expression field, and the seat's own brief was wrong that a "model-registry predicate" is the AI domain's CEL site — model-registry.zod.ts:121-122 is TemplateExpressionInputSchema, dialect template (expression.zod.ts:117-124); the dev took the brief's drop branch correctly, and the same false claim in skills/objectstack-ai/SKILL.md:405-406 is now [finding] skills/objectstack-ai/SKILL.md:405-406 calls a model-registry promptTemplate.system / .user "a CEL predicate" — those keys are the template dialect ({{var}}), and the AI domain has no CEL site at all #14797. (3) three routing bullets at :110-113 — labels vs bundles → objectstack-i18n ([finding] Nothing routes an agent authoring object/field/view labels to objectstack-i18n — the cross-skill routing list in skills/README.md has no labels-vs-bundles decision point #14566, verified against that skill's frontmatter), upgrade vs platform → objectstack-upgrade, rendering this metadata → objectui skills/objectui/ (path verified in the objectui checkout).
Seat re-measured at 2026-09-03T02:11Z: M9.5 1 → 0, AI tool params 1 → 0, objectstack-i18n / objectstack-upgrade / objectui 1 → 2 each; hunks at :87, :106, :110-113 — disjoint from PR docs(skills): admit hand-authored reference files under references/ in the catalog anatomy #14786's :55; the generated region between the markers byte-identical (check:skill-docs green; ablation red-then-restored with blob hashes).
CI at 39da552e: every one of the 38 check runs is success or skipped, read at 2026-09-03T02:32Z — Lint & Repo Gates success, the four Type Check legs, all six Test Core shards, Check Changeset success, Governed Surface Queue Guard (draft — correct), Check Documentation Links, the three claim guards.
Recorded on the ledger, not filed: skills/README.md:114 "Related repositories" now slightly overlaps the objectui bullet — left alone by dispatch.
Merge patrol reading 2026-09-03T09:10Z (git fetch origin main, then git log origin/main --grep '(#14795)' in the same minute): PR #14795 merged as f22ed22c24 at 02:35:08Z, landing this card and #14566 together; this card was closed by os-zhuang at 04:12:17Z. The seat's patrols between 02:35Z and 08:31Z kept listing PR #14795 as a draft at the governed terminal — wrong from 02:35Z on; corrected here and in seat post #7623 at this refresh. pm:dispatched removed at 09:12Z; labels now documentation, priority:p3, read back 09:13Z.
Activity
os-litant commentedon Sep 3, 2026
Claim: skills lane seat — filed and dispatched in one round (
priority:p3+pm:dispatched;domain:*left to triage, its single producer). The seat dispatches its own programme's follow-up in-lane; #14566 (the same list) is claimed in the same stroke soskills/README.md's routing list is edited once.Session:
session_01LraLgQVGq8egUwfYZpbYt1Branch:
claude/issue-14794-readme-truth-routingWorktree:
objectstack-issue-14794Clause-②: no — catalog routing prose; item 1 is settled at source by the dev and cited, not claimed. Governed
skills/**⇒ draft PR; review requests are the seat's step.Binding on the flight: the two corrections shrink or stay neutral; the three routing bullets (this card's two + #14566's one) are ~25 tokens each in the existing bullets' shape — the #14566 triage's size ruling (comment 5514978050) applies to all three; ⛔ no edit to any
SKILL.md; the generated region of the README untouched; hunks disjoint from PR #14786's:55. First lineFixes #14794andFixes #14566;skip-changeset.Generated by Claude Code
os-litant commentedon Sep 3, 2026
Claim: dev seat (os-dev subagent of the dispatching PM session — same session id, distinct seat)
Session:
session_01LraLgQVGq8egUwfYZpbYt1Branch:
claude/issue-14794-readme-truth-routing(pushed empty at the branch point as a write-route probe)Worktree:
/home/user/objectstack-issue-14794Branch point re-measured:
origin/main89a156af88— identical to the card's measurement (2026-09-03T01:43Z), no drift.Scope taken, exactly as claimed by the lane seat:
skills/README.mdonly — the:87OLD/NEWclause settled at source, the:105"AI tool params" item corrected againstpackages/spec/src/ai, and three routing bullets (this card's two + #14566's one) at ~25 tokens each under the #14566 triage ruling (comment 5514978050). NoSKILL.mdedit, no touch to the README's generated region between the BEGIN/END GENERATED markers, hunks disjoint from PR #14786's anatomy-tree line. One draft PR,skip-changeset, stays draft for human merge.Generated by Claude Code
os-litant commentedon Sep 3, 2026
os-dev-report
{ "issue": 14794, "also_fixes": 14566, "status": "done", "branch": "claude/issue-14794-readme-truth-routing", "head_sha": "39da552e61a526f10a5951e3cf4d6d07ac78710a", "pr": "https://github.com/objectstack-ai/objectstack/pull/14795", "branch_point": "89a156af88 — re-measured, identical to the card's measurement, no drift. main has since advanced to 8f9ef6f7c8 (4 commits), none touching skills/README.md; PR #14786 has not landed, so the hunks are disjoint and no merge was needed.", "items": [ { "id": "1 — skills/README.md:87", "before": "`@objectstack/spec`. Legacy `OLD` / `NEW` evaluate to `null` since M9.5.", "after": "`@objectstack/spec`. Legacy `OLD` / `NEW` are not CEL — use `previous.` / `record.`.", "source": "False in both halves. (a) M9.5: `git grep -rn 'M9\\.5' -- packages skills docs` returns exactly ONE hit — this README line itself. (b) They do not evaluate to null; they are UNDECLARED IDENTIFIERS. SCOPE_ROOTS (packages/formula/src/cel-engine.ts:95-119) is the published closed set of record-scope roots and contains neither. firstUndeclaredReference (cel-engine.ts:186-205) reports them as bare undeclared references — the class @objectstack/lint raises as an ERROR (packages/lint/src/validate-expressions.ts:490, 'Why it is an error and not a warning'). Measured against the built package, not inferred: SCOPE_ROOTS includes OLD=false NEW=false previous=true record=true; firstUndeclaredReference('OLD.amount != NEW.amount')='OLD'; ('NEW.status')='NEW'; ('previous.amount != record.amount')=null. The replacement's prescription is objectstack-formula's own table, skills/objectstack-formula/SKILL.md:345-346 (OLD.x to previous.x, NEW.x to record.x), so the two published files now agree." }, { "id": "2 — skills/README.md:105", "before": "skill (data validations, automation guards, UI visibility, AI tool params).", "after": "skill (data validations, automation guards, UI visibility).", "source": "Diagnosis confirmed, prescribed replacement falsified. packages/spec/src/ai/tool.zod.ts matches cel|formula|expression ZERO times. But there is no model-registry predicate to swap in: 'predicate' occurs 0 times in packages/spec/src/ai/model-registry.zod.ts; its only expression-typed keys are system/user at :121-122, which are TemplateExpressionInputSchema — defined at packages/spec/src/shared/expression.zod.ts:117-124 as dialect 'template', the {{var}} interpolation form, NOT CEL. skills/objectstack-ai/SKILL.md:405-407 says the same in substance. The AI domain therefore has no CEL site at all, so the dispatch's stated alternative was taken: the item is DROPPED, not replaced. Adding an AI entry to a bullet headed 'Any CEL expression' would have swapped one false claim for another." }, { "id": "3 — skills/README.md:94-110, three routing bullets", "before": "four decision points; none about labels, upgrade-vs-platform, or the consuming UI", "after": "- **Labels vs. bundles** — a `label` you want translated is **objectstack-i18n**. / - **Upgrade vs. platform** — a protocol-major move is **objectstack-upgrade**. / - **Rendering this metadata** — the consuming UI is [objectui `skills/objectui/`](https://github.com/objectstack-ai/objectui).", "source": "Each checked against the TARGET SKILL'S OWN frontmatter description. i18n: 'Author ObjectStack translation bundles — object/field labels, view text …'. upgrade: 'Use when a project is on an older protocol major and must move to the current one, when @objectstack/spec was bumped across a major …'. objectui: path confirmed on the objectui checkout, `git ls-tree origin/main skills/objectui/` at objectui origin/main 39af82f returns SKILL.md, README.md, evals/, guides/, rules/." } ], "premise_false": [ "Item 2's REMEDIATION half is false. The dispatch and the card both instruct: 'The AI domain's real CEL site per skills/objectstack-ai/SKILL.md:405 is a model-registry predicate. Replace the false item with the true one (verify it at packages/spec/src/ai/model-registry.zod.ts — find the predicate field and cite it)'. There is no predicate field: 'predicate' occurs 0 times in that file, and the two expression-typed keys it does carry (system/user, :121-122) are the TEMPLATE dialect, not CEL. The dispatch's own alternative ('or drop the item') was taken. The card's DIAGNOSIS half ('AI tool params is not a CEL site') is confirmed.", "Item 1's original README claim is false in a sharper way than the card states. The card asks whether OLD/NEW 'evaluate to null'; the measured answer is that they are REJECTED as undeclared references — an error raised by @objectstack/lint — not silently nulled. The clause as written described a silent runtime degradation that does not exist." ], "gates": [ { "cmd": "pnpm --filter @objectstack/spec check:skill-docs", "exit": 0, "verdict": "Skill docs in sync (skills/README.md OK) — proves the generated region is byte-identical" }, { "cmd": "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." }, { "cmd": "node scripts/check-skills-token-ratchet.mjs --self-test", "exit": 0, "verdict": "check-skills-token-ratchet self-test: 64 cases pass." }, { "cmd": "pnpm check:role-word", "exit": 0, "verdict": "check-role-word: OK, no new occurrences of the reserved word. 224 files; ledger unchanged at 43 baselined files / 120 occurrences." }, { "cmd": "pnpm check:skill-identifier-liveness", "exit": 0, "verdict": "OK — Leg 1: 465 citation(s) over 46 published file(s); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)." }, { "cmd": "pnpm check:skill-compatibility", "exit": 0, "verdict": "11 SKILL.md file(s) reconciled against 79 workspace packages" }, { "cmd": "pnpm check:published-readme-links", "exit": 0, "verdict": "176 outbound link(s) across 60 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 27 docs-site page(s) resolved, 103/103 relative target(s) found — the new objectui link resolves" }, { "cmd": "node scripts/check-nul-bytes.mjs", "exit": 0, "verdict": "OK (scanned 8064 text file(s); no raw ASCII control bytes)" }, { "cmd": "node scripts/check-ci-filter-parity.mjs", "exit": 0, "verdict": "union member, green" }, { "cmd": "node scripts/check-cross-package-test-inputs.mjs", "exit": 0, "verdict": "union member, green" }, { "cmd": "node scripts/check-shard-attestation.mjs", "exit": 0, "verdict": "union member, green" }, { "cmd": "node scripts/check-test-completeness.mjs", "exit": 3, "verdict": "PREREQUISITE NOT MET — NOT MEASURED, not red. 'grades a saved turbo run test log, and no log was named … the local reading for this gate is NOT MEASURED.' CI tees the log and passes the path, so CI is unaffected." }, { "cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions", "exit": 0, "verdict": "First pass exited 3 (PREREQUISITE NOT MET — imports compiled @objectstack/formula and @objectstack/lint). Both were BUILT and the gate re-run rather than reported as a non-reading, because it is the gate nearest this change (item 1 puts previous./record. into published prose). Then: '22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean by @objectstack/formula.'" }, { "cmd": "pnpm --filter @objectstack/spec run check:skill-docs", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:agent-test-spelling", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:corpus-claim-drift", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:cross-package-test-inputs", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:doc-authoring", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:merge-driver", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:pm-governed-merges", "exit": 0, "verdict": "union member, green" }, { "cmd": "pnpm check:skill-frame-sync", "exit": 0, "verdict": "union member, green" } ], "gate_method": "Every exit code captured by redirect BEFORE any pipe (cmd redirected to a log; EXIT read; then tail). Each verdict quotes the gate's own printed line, never a bare exit status. The union was re-derived AFTER the last edit with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands`; its provenance line reads 'gate list derived from the tree of objectstack-ai/objectstack at commit 39da552e61' with change set '1 path(s) vs merge base 89a156af8' = skills/README.md. All 16 derived commands were run; the 8 dispatch-named gates were run as well.", "reverse_verification": "check:skill-docs proven able to FAIL and to name this file. Implementation committed FIRST, so the restore leg's HEAD already contains it. Guarded by `trap restore EXIT INT TERM`, absolute paths throughout. Mutation landed on disk proven by grep counts flipping BOTH ways inside the generated region ('Construct ObjectQL queries' 1 to 0, 'Construct ObjectQL queried' 0 to 1) and the worktree blob moving 72afcf31b7 to e60bea9ecc — never by an editor's exit code. Mutated leg: exit 1, verdict 'skills/README.md is out of date — run pnpm --filter @objectstack/spec gen:skill-docs'. Restore leg: `git checkout HEAD -- ABSOLUTE_PATH` (pinned to HEAD, never a bare checkout, so it cannot restore from a polluted index), proven by blob hash equality against the HEAD blob 72afcf31b7 (non-empty AND matching), an EMPTY `git diff HEAD`, and anchor counts back to 1 / 0.", "eslint": "Not a narrowing — skills/README.md is outside the linted population entirely, with all three pieces. (1) Population read from eslint's OWN config resolution, not from my reading of the globs: `eslint --print-config skills/README.md` emits an empty document (10 bytes); every files: selector in eslint.config.mjs is {ts,tsx,mts,cts,js,jsx,mjs,cjs} and none matches markdown. (2) Count from --format json for the file: 1 result entry, errorCount 0, warningCount 1, and the single message is eslint's own 'File ignored because no matching configuration was supplied.' — zero rule findings because zero rules apply. (3) Invariance: the repo runs one eslint.config.mjs which 'never enables type-aware linting (no parserOptions.project, no typed @typescript-eslint rules) for ANY file, test or not' (eslint.config.mjs:326-328, carrying its own positive-control measurement), so no untouched file's verdict can move as a function of this diff. A full-repo `pnpm lint` is provably vacuous here.", "token_delta": { "method": "ceil(utf8_bytes / 4)", "file_before": { "bytes": 7941, "tokens": 1986, "at": "89a156af88" }, "file_after": { "bytes": 8237, "tokens": 2060, "at": "39da552e61" }, "file_delta": { "bytes": 296, "tokens": 74 }, "item1": { "before_bytes": 75, "after_bytes": 91, "delta_bytes": 16, "delta_tokens": 4 }, "item2": { "before_bytes": 78, "after_bytes": 62, "delta_bytes": -16, "delta_tokens": -4 }, "items_1_and_2_combined": { "delta_bytes": 0, "delta_tokens": 0, "note": "neutral, as the budget requires — items 1 and 2 fund each other exactly" }, "item3": { "bullet_tokens": [21, 21, 33], "total_tokens": 75, "total_bytes": 296, "ruling": "at the #14566 triage ruling (comment 5514978050): ~25 tokens per bullet, ~75 total" }, "payment": "Item 2's drop of ', AI tool params' (-16 B) exactly funds item 1's truthful replacement (+16 B). A second payment is inside item 3 and is what brought the block from 84 tokens down to the ruling's 75: bullet 2's body does NOT restate 'not objectstack-platform' — the surviving site is the bullet's own heading, 'Upgrade vs. platform', which already names both sides. That is a strict restatement removed, not meaning shaved. NO FURTHER PAYMENT WAS AVAILABLE: the one candidate examined was the process-skill paragraph at :64-66 against the frontmatter rows at :75 (compatibility, 'for a process skill that binds to no schema') and :76 (metadata.domain, 'a delivery-process skill that teaches no schema'); rejected because the paragraph also carries two facts surviving nowhere else — that such a skill 'carries SKILL.md alone' (no references/ directory) and the SKILL_MAP mechanism behind it. Deleting it would have shaved meaning.", "ratchet_population": "skills/README.md is outside it (scripts/check-skills-token-ratchet.mjs:133); the ratchet is green regardless." }, "edit_landed_proof": { "M9.5": "1 to 0", "AI tool params": "1 to 0", "objectstack-i18n": "1 to 2", "objectstack-upgrade": "1 to 2", "objectui": "1 to 2" }, "scope_untouched": "No SKILL.md edited. The README's generated region between the BEGIN/END GENERATED markers untouched (check:skill-docs green proves it byte-for-byte). The anatomy tree at :50-62 untouched, so the hunks are disjoint from PR #14786's :55 — this diff's two hunks start at :85 and :104. No other README sentence edited. Diff is 1 file, +7 -2.", "pr_state": "Draft (draft=true, read back). Label skip-changeset applied and read back as labels=['skip-changeset']. Never flipped ready, no auto-merge, no reviewers requested. skip-changeset justified against scripts/check-empty-changeset.mjs:359-362, which enumerates 'It releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, tests-only, and the like) -to- delete the changeset and apply the skip-changeset label (route 2)', and pins this exact shape as GREEN 3 at :559-565.", "channel": "REST is 403 for this session (curl to api.github.com/repos/objectstack-ai/objectstack returned 403; gh is not installed), so ALL GitHub writes went through MCP — declaring the switch. Label write used the read-union-write-then-read-back fallback; note that issue_read get_labels cannot resolve a PR number ('Could not resolve to an Issue with the number of 14795'), so the read-back was taken via list_pull_requests filtered to this head branch.", "mcp_calls": 15, "out_of_scope_findings": [ "skills/objectstack-ai/SKILL.md:405-407 makes the SAME class of error this PR just fixed in the README, one level down: it writes 'any CEL predicate parses and resolves — in this domain that is a model-registry promptTemplate.system / .user'. Those two keys are TemplateExpressionInputSchema, i.e. dialect 'template' ({{var}} interpolation), NOT CEL — see packages/spec/src/shared/expression.zod.ts:117-124. So a published skill labels a template-dialect expression a 'CEL predicate'. The same sentence also omits the AI domain's other real expression site, the 5-field cron at packages/spec/src/ai/knowledge-source.zod.ts:28. Out of scope here twice over (the dispatch forbids any SKILL.md edit, and #14566's triage forbids expanding sibling skills), and NOT filed per the dispatch's instruction that out-of-scope findings go in the report only. Worth a card at triage's discretion: it is a published-surface truth defect, not cosmetics.", "skills/README.md:114 'Related repositories' still describes objectui only as 'Studio UI (separate repo)' and does not say it publishes a skills catalog. OUI-A-01 noted this; the new routing bullet now carries the route, so the gap is covered functionally, but the two lines are slightly redundant and a future editor may want to merge them. Left untouched deliberately — the dispatch scoped this flight to the routing list and forbade other README sentences." ] }Generated by Claude Code
os-litant commentedon Sep 3, 2026
ACCEPT — skills-lane seat (session
session_01LraLgQVGq8egUwfYZpbYt1), reviewer of record, verified against GitHub and the seat's own checkout, not the report. Covers #14794 and #14566 (one PR, bothFixes).39da552e, one file, +7 −2; labelskip-changeset; noneeds:contract-review(catalog routing prose; item 1 cited at source, not claimed).:87Legacy OLD / NEW evaluate to null since M9.5.→Legacy OLD / NEW are not CEL — use previous. / record.— seat re-readpackages/formula/src/cel-engine.ts:95-119at8f9ef6f7c8:SCOPE_ROOTSis the closed root set (record,previous,input,output,os,vars, …,current_user) and carries neitherOLDnorNEW;firstUndeclaredReference(:77,:186-205) reports them as undeclared — the lint's error class, not a silentnull.M9.5was anchored nowhere inpackages/orskills/. The new clause matchesskills/objectstack-formula/SKILL.md:345-346. (2):105drops, AI tool params:tool.zod.tshas no expression field, and the seat's own brief was wrong that a "model-registry predicate" is the AI domain's CEL site —model-registry.zod.ts:121-122isTemplateExpressionInputSchema, dialecttemplate(expression.zod.ts:117-124); the dev took the brief's drop branch correctly, and the same false claim inskills/objectstack-ai/SKILL.md:405-406is now [finding]skills/objectstack-ai/SKILL.md:405-406calls a model-registrypromptTemplate.system/.user"a CEL predicate" — those keys are thetemplatedialect ({{var}}), and the AI domain has no CEL site at all #14797. (3) three routing bullets at:110-113— labels vs bundles → objectstack-i18n ([finding] Nothing routes an agent authoring object/field/view labels toobjectstack-i18n— the cross-skill routing list inskills/README.mdhas no labels-vs-bundles decision point #14566, verified against that skill's frontmatter), upgrade vs platform → objectstack-upgrade, rendering this metadata → objectuiskills/objectui/(path verified in the objectui checkout).M9.51 → 0,AI tool params1 → 0,objectstack-i18n/objectstack-upgrade/objectui1 → 2 each; hunks at:87,:106,:110-113— disjoint from PR docs(skills): admit hand-authored reference files underreferences/in the catalog anatomy #14786's:55; the generated region between the markers byte-identical (check:skill-docsgreen; ablation red-then-restored with blob hashes).objectstack-i18n— the cross-skill routing list inskills/README.mdhas no labels-vs-bundles decision point #14566 triage's size ruling (comment 5514978050), the three bullets in the existing four's shape. The file is outside the ratchet population; the one further payment candidate (:64-66) was examined and rejected because it carries two facts surviving nowhere else — the seat agrees.39da552e: every one of the 38 check runs is success or skipped, read at 2026-09-03T02:32Z —Lint & Repo Gatessuccess, the fourType Checklegs, all sixTest Coreshards,Check Changesetsuccess,Governed Surface Queue Guard(draft — correct),Check Documentation Links, the three claim guards.skills/README.md:114"Related repositories" now slightly overlaps the objectui bullet — left alone by dispatch.skills/**⇒ stays DRAFT; review requested from os-zhuang + hotlong; human merge is the record. At MERGED the seat stripspm:dispatchedon both skills/README.md truth + routing sweep:OLD/NEW"evaluate tonullsince M9.5" is anchored nowhere and contradicts the formula skill; "AI tool params" is not a CEL site; the cross-skill routing list lacks the upgrade-vs-platform and objectui inbound decision points #14794 and [finding] Nothing routes an agent authoring object/field/view labels toobjectstack-i18n— the cross-skill routing list inskills/README.mdhas no labels-vs-bundles decision point #14566 (Fixes⇒ both close).Generated by Claude Code
os-litant commentedon Sep 3, 2026
Merge patrol reading 2026-09-03T09:10Z (
git fetch origin main, thengit log origin/main --grep '(#14795)'in the same minute): PR #14795 merged asf22ed22c24at 02:35:08Z, landing this card and #14566 together; this card was closed by os-zhuang at 04:12:17Z. The seat's patrols between 02:35Z and 08:31Z kept listing PR #14795 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,priority:p3, read back 09:13Z.Generated by Claude Code