Skip to content

skills(upgrade): optimization flight — the stale pinned registry snapshot cut, the rule stated once, --yes and the --stored exit-code contract taught (net −1,134 tokens) - #14465

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-14307-skills-upgrade-optimization
Sep 2, 2026
Merged

skills(upgrade): optimization flight — the stale pinned registry snapshot cut, the rule stated once, --yes and the --stored exit-code contract taught (net −1,134 tokens)#14465
os-zhuang merged 4 commits into
mainfrom
claude/issue-14307-skills-upgrade-optimization

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Part of #14307

Skills catalog optimization program #14292, member card #14307 (maintainer mandate 2026-09-02: 「审核所有的 skills,进行全面的优化。」). Verdict DIET, implemented on one file.

Not Fixes: UPG-H-01 (the evals/ package) is deferred to #14296 item 2, so #14307 stays open. #14296 is not addressed here.

Governed face ⇒ this PR stays draft. needs:contract-review is on both carriers: the --stored exit-code contract, the --yes non-TTY semantics, the --json error codes and the ranged engines.protocol reading are all CLI / manifest contract claims.

Token delta

File before after ceiling headroom after
skills/objectstack-upgrade/SKILL.md 8,333 7,199 8,333 1,134

Net −1,134 tok on 8,333 = −13.6% (693 lines → 597). Bundle total 176,225 → 175,091. No ceiling raise, no new file, no re-wrap-as-payment, ratchet script untouched.

The card's target was ≈ −1,808. The −674 gap is itemised, not smoothed — it is entirely the audit's per-finding Δtok estimates coming in optimistic on the rewrite-as-construct rows, plus three additions written longer than estimated because the measured contract needed more words than the audit budgeted. Measured per cluster:

cluster est. Δtok measured Δtok why it differs
D-01 + D-02 (incl. the 2.1 fold-in) −734 −534 the surviving re-measure command is a 9-line node block, not a one-liner
E-04 + E-05 −245 −67 the 3-row table still carries three outcomes and three evidence rules; the estimate assumed a much terser table
D-07 −190 −238 better than estimated
D-03 −180 −108 the surviving "carry each printed gate into the report" rule needed its own sentence
B-02 −170 −167 on estimate
C-01 −70 −54 the platform route is kept (see the A-01 follow-up below), so only 2 of 4 bullets went
D-04 + D-05 −230 −106 D-05's second half was already delivered inside the E-04 rewrite, so it could not be counted twice
D-06 + D-08 + B-03 −163 −115 D-06 became a one-sentence collapse rather than a straight deletion
E-02 + E-03 + F-03 +50 +168 E-03 needed the floor rule plus the never-read-the-upper-bound guard (see below)
F-01 + F-02 (and the E-03 tighten) +90 +159 F-01 landed as a titled 3.6 with a runnable command, not a bare list row
A-02 + G-01 −100 −72 G-01 must keep the phrase "at the TARGET major" verbatim (see below)

Per-item 落点 | before | after

id 落点 before after
UPG-D-01 the whole "v17 prescription set, as of 17.0.0-rc.5" section (65 lines) six pinned readings, every one wrong against the installed 17.2.0 deleted. The measurement survives, not the number: the spec-changes.json reading folded into the 2.1 source table, now deriving the target major from protocolVersion instead of hardcoding 17, plus a rule against carrying a remembered count into the report
UPG-D-02 "Why these two tables are short" narrated the platform's own retirement-registration policy over two registry files this same skill declares unreachable from a consumer project deleted with D-01
UPG-E-04 3.5 one recipe, a re-quoted error block available verbatim from the install, and a 3-outcome prose list a 3-row outcome → what it means → your acceptance evidence table
UPG-E-05 3.5 probe recipe illustrated as producing the schema-gate refusal plus the rule that makes it true: write the probe as a plain data literal, no define* call
UPG-D-03 "Data migrations are not metadata migrations" a 2-row cost table and a closing paragraph, both near-verbatim what the run prints the one non-CLI decision: carry every printed gate into the report as pending, by name
UPG-D-07 the preamble + Layer table "this skill turns one session into an upgrade agent", three-layers prose, 3-row Layer table the pipeline line alone; the section headings already were the construct
UPG-B-02 "Guardrails (binding)" 6 rules, 4 restating the boundary verbatim and #6 restating the data-gate rule section deleted; the one non-duplicate (one conversionId per commit) moved into the boundary, #6 now lives where the gates are printed
UPG-D-05 the replay rule stated 5 times 3 (the 3.3 callout, the failure-modes row, the 3.5 table row that states the evidence rather than re-teaching)
UPG-D-04 the AST-is-lossy rationale 3 sentences of rationale before the rule the rule: --out is the oracle you diff against, never the file you ship
UPG-D-06 "What that does and does not mean" 2 bullets restating the paragraph above them one sentence
UPG-D-08 "Section 5 earns its place…" a justification of a template row already in the template deleted
UPG-B-03 the [REMOVED] grep 4 copies 2 (the 2.1 anchor and the name-only variant 2.6 needs). The .upgrade/ workspace list, which named a file nothing writes any more, now names retired-names.txt
UPG-C-01 "Cross-skill routing" 4 bullets, 3 of them owned by skills/README.md and by the domain skills' own frontmatter 2 bullets. The README routing row is deferred with A-01 (see below)
UPG-E-02 the stored --apply line --stored --apply # rewrite the rows (prompts) — falsehood 4 --stored --apply --yes, plus why: non-TTY refuses with confirmation_required
UPG-E-03 source (1) of the FROM major only worked form was an exact '16.0.0' the range rule (see the correction below)
UPG-F-01 3 acceptance absent a 3.6: --stored --json exits 0 = every row canonical, 1 = work left
UPG-F-02 failure-modes table two machine-readable failures named in prose only the five stable --json error codes, as a list under the table (see the construct note below)
UPG-F-03 the flag block positional config path never shown one line; a monorepo with more than one stack could not follow the skill as written
UPG-A-02 description 3 negative routes, 2 of them routing nowhere a customer can go 2 real ones: author new metadata → domain skills; physical DB drift → objectstack-platform
UPG-G-01 compatibility a 5-line folded block hedging a pinned constant one line like the nine domain siblings

premise_false

None. Every finding's premise was re-verified against this branch's base (a98b61b3) and held. Two implementation divergences, both deliberate and both measured:

1. UPG-E-03 — the audit's proposed clause is wrong; the delivered platform row is right. The audit proposed writing "a range declares compatibility, not authorship — '^17' means runs on 17, so fall to source (2)". That contradicts what objectstack-platform's delivered flight teaches for the same manifest row (origin/claude/issue-14299-skills-platform-optimization, "Manifest Reference": "the metadata-protocol major the app is authored against"). The platform row is the correct one, measured three ways:

  • packages/cli/src/utils/protocol-version-gap.ts names the field declaredMajor = "Major the app's declared compatibility range targets", and its header explicitly rejects a naive leading-integer re-parse as a third opinion.
  • packages/create-objectstack/src/template-consistency.test.ts:186 mechanically requires the caret form of every scaffold: "objectstack.config.ts stamps engines.protocol at the scaffolder's major (ADR-0087 D1)".
  • packages/metadata/src/plugin.ts:779 calls it the "authored engines.protocol floor".

So the shipped clause teaches the range's floor'^17'--from 17, '>=15 <18'--from 15, never the upper bound. This agrees with the manifest row objectstack-platform's delivered flight teaches.

2. UPG-F-02 — the codes ship as a list, not as a 4th table column. Measured: the failure-modes table has 8 rows and only 2 map to a code, so a column would be 6 empty cells; and 2 of the 5 codes (missing_from_major, database_busy) have no row at all, so a column cannot carry them. A compact list under the table carries all five and costs less. The finding's decision — an agent scripting the run branches on the code, not the prose — is delivered in full.

Re-measured counts (with their commands)

All re-measured on this branch's base, not copied from the audit (which measured at a59f78d; packages/spec/src/migrations/registry.ts has moved +78 lines since).

reading skill claimed measured at a98b61b3
D2 conversions, major 17 45 58
D3 semantic entries, major 17 29 77
retiredKey( sites in shipped *.zod.ts 113, across 32 files 179, across 44 files
RETIRED_KEYS_BY_MAJOR[17] "3 entries" 29
RETIRED_DEFS_BY_MAJOR[17] "1 entry" 53
MIGRATION_SUPPORT_FLOOR 10 10 (the one reading that held)
node -e "const s=require('./packages/spec/spec-changes.json');const m=s.perMajor.find(x=>x.to===17);
  console.log(m.converted.length, m.migrated.length);"                      # 58 77
grep -rho "retiredKey(" packages/spec/src --include='*.zod.ts' | wc -l      # 179
grep -rlo "retiredKey(" packages/spec/src --include='*.zod.ts' | wc -l      # 44
npx tsx -e "import {RETIRED_KEYS_BY_MAJOR, RETIRED_DEFS_BY_MAJOR} from './packages/spec/src/migrations/registry.ts';
  console.log(RETIRED_KEYS_BY_MAJOR[17].length, RETIRED_DEFS_BY_MAJOR[17].length);"   # 29 53

Also measured: data/ExternalFieldMapping:transform, one of the three keys the skill listed, has been removed from the bucket. The deleted reconciliation rule anticipated only additions ("post-rc.5 registrations are expected to add entries"), so a reader reconciling that delta was pointed the wrong way. After D-01 the skill carries no pinned snapshot at all — only the two re-measure commands, so a reader measures instead of trusting a number.

Two gate mechanisms this flight had to obey

  • check-skill-compatibility-version.mjs exempts this file, and the exemption is warranted by a regex over the live text (rationale: /at\s+the\s+TARGET\s+major/i). A cross-major skill pinned to the current major would be actively wrong, so the G-01 one-liner keeps the phrase "at the TARGET major" verbatim — rewriting it away would have killed the exemption and turned the gate red. Gate confirms: "2 justified exemption(s), each with its stated reason still true of the file."
  • check-skill-identifier-liveness Leg 2 binds sections by heading. Run before the first deletion: 8 registered exhaustive sections, none of them in this file, so the retired-key and tombstone tables were free to delete. Green after, still 8 / 0 gaps.

G-01 also drops the "protocol 10 at the time of writing" hedge rather than restating the number: after D-01 the frontmatter was the last rottable copy of that constant, so the line now points at MIGRATION_SUPPORT_FLOOR instead of quoting it.

Follow-up for objectstack-platform / skills/README.md (UPG-A-01, deferred)

Not done here — this flight edits one package. Recorded for whoever owns those files:

  1. skills/objectstack-platform/SKILL.md description needs one negative route: do not use for a protocol-major metadata upgrade — see objectstack-upgrade. Platform's description today claims "operations (CLI commands, migrations, deployment…)" while its migration table lists only os migrate plan / os migrate apply; os migrate meta, files-to-references and value-shapes appear nowhere in it. A customer agent asked "run the migrations for the new spec" loads platform and gets physical-DB drift reconciliation. This PR fixed the mirror half inside upgrade's own description (A-02), so the hole is now one-sided rather than two-sided.
  2. skills/README.md "Cross-skill routing" needs an upgrade-vs-platform row — the half of UPG-C-01 that could not land here (the deletion half did).

UPG-H-01 (an evals/ package for this skill) stays deferred to #14296 item 2.

Gates

Head sha ecdddf53 — every reading below is from that commit, after the final commit, with exit codes captured before any pipe.

Named on the card:

gate verdict
node scripts/check-skills-token-ratchet.mjs ✅ 7199 / 8333, headroom 1134
pnpm --filter @objectstack/spec check:skill-examples ✅ "265 prose examples type-check across 3 surface(s)" — after building @objectstack/spec + the @objectstack/client-react closure; it refused rather than false-greening until the build existed
pnpm check:skill-compatibility ✅ 11 files reconciled, "2 justified exemption(s), each with its stated reason still true"
pnpm check:skill-identifier-liveness ✅ Leg 1: 490 citations / 47 files; Leg 2: 8 sections, 0 gaps
pnpm --filter @objectstack/spec check:skill-docs ✅ "Skill docs in sync"

Re-derived family — node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, derived after regeneration, from the script's own merge-base changeset (2 paths, no hand-fed list): 36 commands. 35 green, 1 NOT MEASURED.

The one non-green is node scripts/check-test-completeness.mjs, exit 3 = PREREQUISITE NOT MET, which the gate itself defines as not-a-finding: it grades a saved turbo run test log, CI tees one and passes the path, and there is no local log to hand it. Recorded as NOT MEASURED per the script's own instruction, not as a red.

pnpm check:nul-bytes ✅ (7,902 files, no raw control bytes).

Why skip-changeset

Nothing is released by any package. Verified rather than assumed: neither changed path lies inside a publishable package — skills/ and content/ have no package.json of their own, and no publishable package's directory is a prefix of either path.

Files

  • skills/objectstack-upgrade/SKILL.md — the flight.
  • content/docs/ai/skills-reference.mdxgenerator output only (pnpm --filter @objectstack/spec gen:skill-docs), forced by check:skill-docs, which was red on this file and named the command. One line, the description change.

skills/README.md regenerated byte-identical — it does not carry the description prose — so it is not in this diff at all, which is tighter than the claim comment anticipated.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…1, UPG-D-02)

The "v17 prescription set, as of 17.0.0-rc.5" section pinned six readings that
are now wrong against the installed 17.2.0 spec: 45 vs 58 D2 conversions, 29 vs
77 semantic entries, 113-across-32-files vs 179-across-44 retiredKey() sites,
RETIRED_KEYS_BY_MAJOR[17] "3 entries" vs 29, RETIRED_DEFS_BY_MAJOR[17] "1 entry"
vs 53. Nothing in the skill branched on a count, and the section itself told the
reader "the install wins" -- so the pin bought nothing and cost a reader who
trusted it. Its reconciliation rule also pointed the wrong way: it anticipated
only additions, while data/ExternalFieldMapping:transform was REMOVED from the
bucket.

Deleted with it (UPG-D-02): the "why these two tables are short" paragraph,
which narrated the platform's own retirement-registration policy over two files
this same skill declares unreachable from a consumer project.

What survives is the measurement, not the number: the spec-changes.json reading
folded into the 2.1 source table, now deriving the target major from
protocolVersion instead of hardcoding 17, plus a rule against carrying a
remembered count into the report.

Ratchet: 8333 -> 7799 (ceiling 8333).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…02, B-03, C-01)

Nine findings, all the same shape: a rule the file already states, or prose
re-teaching what the CLI prints for itself.

- E-04/E-05 §3.5 becomes a 3-row outcome -> evidence table; the re-quoted error
  block was already available verbatim from the install. The new probe rule is
  the E-05 fix: `os validate` loads WITHOUT authoredSource (validate.ts:159;
  config.ts:224 "Set by `os migrate meta` only"), so a probe calling `define*`
  throws inside the load and never reaches the gate the recipe is proving.
- D-03 the data-gate table is printed by the run itself (meta.ts:106-141,
  measured: the two `unlocks` strings, the deployment scoping and the dry-run
  sentence are all emitted). Only the non-CLI half survives -- carry each
  printed gate into the report as pending, by name.
- D-07 the three-layers preamble and Layer table; the section headings and the
  pipeline line already are the construct.
- B-02 the Guardrails section: 4 of 6 restated the boundary verbatim and #6
  restated the data-gate rule. The one non-duplicate (one conversionId per
  commit) moves into the boundary; #6 now lives where the gates are printed.
- D-04 the AST-is-lossy rationale, D-05 the 2nd of five statements of
  "replay from the target major", D-06 two bullets restating the paragraph
  above them, D-08 a justification of a template row already in the template,
  B-03 the 3rd copy of the [REMOVED] grep, C-01 routing owned by README and by
  the domain skills' own frontmatter.

B-03 left the .upgrade/ workspace listing a file nothing writes any more; that
list now names retired-names.txt, which 2.6 actually produces.

Ratchet: 7799 -> 6944 (ceiling 8333).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…ed protocol (UPG-E-02, E-03, F-01, F-02, F-03, A-02, G-01)

Five funded additions, each paid by a deletion in the same file, plus the
frontmatter shrink.

- E-02 (falsehood 4) `os migrate meta --stored --apply` was documented as
  "(prompts)". It does not prompt for this skill's reader: meta.ts:501-511
  refuses in any non-TTY -- every agent session -- exiting 1 with
  `confirmation_required`. The CLI's own example list already spells
  `--stored --apply --yes --json`.
- E-03 the ranged `engines.protocol`. The skill's only worked form was an exact
  '16.0.0'; all four real configs (showcase, crm, todo, the blank template)
  write `engines: { protocol: '^17' }`, and template-consistency.test.ts:186
  MECHANICALLY REQUIRES the caret form of every scaffold. Reading rule is the
  range's floor, matching `declaredMajor` ("Major the app's declared
  compatibility range targets", protocol-version-gap.ts) and agreeing with the
  Manifest Reference objectstack-platform's delivered flight teaches.
- F-01 the `--stored` exit contract (meta.ts:577-578, 621; documented at
  :451-453) becomes a 3.6: exit 0 = every row canonical, 1 = work left, which
  is what makes "this deployment is on protocol N" a CI check.
- F-02 the five stable `--json` error codes an agent branches on
  (meta.ts:262, 279, 414, 477, 504).
- F-03 the positional config path (meta.ts:191-193) -- a monorepo with more
  than one stack could not follow the skill as written.
- A-02 drops the two "do not use" clauses that route nowhere a customer can go
  (an internal playbook outside the published catalog, and a body rule restated
  in the trigger) and adds the real one: physical DB drift is platform's job.
- G-01 compatibility becomes one line like the nine domain siblings. The phrase
  "at the TARGET major" is kept verbatim ON PURPOSE: it is the warrant for this
  file's exemption in check-skill-compatibility-version.mjs, whose rationale
  regex dies with the text. The "protocol 10 at the time of writing" hedge is
  gone rather than restated -- after D-01 the frontmatter was the last rottable
  copy of that constant.

Ratchet: 6944 -> 7199 (ceiling 8333). Net for the flight so far: 8333 -> 7199.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
…r shrink

Generator output only (`pnpm --filter @objectstack/spec gen:skill-docs`), forced
by check:skill-docs, which was red on this file and named the command.

skills/README.md regenerated byte-identical -- it does not carry the description
prose -- so this flight's whole file surface is SKILL.md plus this one line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-zhuang
os-zhuang marked this pull request as ready for review September 2, 2026 11:24
@os-zhuang
os-zhuang enabled auto-merge September 2, 2026 11:24
@os-zhuang
os-zhuang added this pull request to the merge queue Sep 2, 2026
Merged via the queue into main with commit 310dd01 Sep 2, 2026
36 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14307-skills-upgrade-optimization branch September 2, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants