Skip to content

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

Description

@os-litant

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/main 89a156af88, 2026-09-03T01:43Z

  1. 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.
  2. 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).
  3. Cross-skill routing list (:94-110, four bullets) lacks two decision points the audits measured as real load-failure modes, in the same shape [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 records for i18n:

Scope and budget

  • 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.

Refs: #14292 · #14566 · #14315 (I18N flight) · #14307 (UPG flight) · objectui#7251 (OUI flight).

Activity

  1. self-assigned this
    on Sep 3, 2026
  2. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    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.


    Generated by Claude Code

  3. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    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/main 89a156af88 — 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 :87 OLD/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.


    Generated by Claude Code

  4. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    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

  5. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    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).


    Generated by Claude Code

  6. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    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.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions