Skip to content

ci(release): the post-version guard admits the SKILL.md stamps through stampedSkillPaths() - #22980

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22970-skill-stamps-post-version-surface
Oct 12, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-22970-skill-stamps-post-version-surface

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22970
Clause-②: no

Refs #22085 (the version-PR lane: the first scheduled release.yml run after this lands is the reading owed there).

What changed

  • The export. scripts/check-skill-compatibility-version.mjs exports stampedSkillPaths({ root }): every repo-relative skills/NAME/SKILL.md path its --fix may write, in walk order, derived from readSkillFiles(). The --fix leg itself moved into an exported applyFix(scanned, pkgs, root) that writes from that same walk, so the list and the writes come from one walk. Zero skills throws, the same way stampedPaths() does. The one EXEMPT file (skills/objectstack-upgrade/SKILL.md) is in the list, because the exemption covers its pin and not its metadata.version stamp. main() prints the same lines as before.
  • The fourth list, release.yml (the Validate the post-version tree step only): SKILL_LIST is resolved by node --input-type=module -e 'import { stampedSkillPaths } ...'. It has the siblings' two refusals: could not resolve, and resolved EMPTY. It is added as a fifth whole-line exact filter, grep -vxF -f "${SKILL_LIST}", after the three existing lists.
  • The judging gate. run_gate pnpm check:skill-compatibility (self-test plus check, no --fix) now runs in the content half, after check:release-index-currency-sync.
  • The fourth list, cut-rc.yml (Build the single version commit): the same resolve and the same two refusals. SKILL_SURFACES joins the git add -A pathspec, and SKILL_LIST joins the BAD re-check as the fifth filter.
  • Not touched: skills/**, the root version script, .changeset/**, content/docs/releases/**. There is no regex widening: the skill paths are admitted only by exact match against the exported list.

The dispatch's hypotheses, measured

  • H1 (where the guard sits, parity checkers). The guard is at release.yml Validate the post-version tree and at cut-rc.yml's BAD filter, as stated. I ran git grep for TEMPLATE_LIST|SURFACE_LIST|INDEX_LIST|post-version-paths|stampedPaths|syncedPaths outside the two workflows and the two rewriters. It hits only:

    • create-objectstack's own stampedPaths() test;
    • a comment in scripts/cross-package-test-inputs.mjs;
    • two unrelated H43_/H48_SURFACE_LIST_CAP constants in scripts/pm/check-half-states.mjs.

    No parity checker pins the list count or the three names, so none had to learn the fourth list. check-self-test-wired credits the new ./scripts/... import the same way it credits the existing ones, and it stays green.

  • H2 (import safety). The script already carried the entry-point guard (if (isEntrypoint(import.meta.url)) main();). Importing it the workflow way prints the 10 paths, writes nothing (git status stays clean), and exits 0. pnpm check:entry-guard is green.

  • H3 (the list). On this tree the list is the 10 published skills. They are exactly the 10 unexpected: paths of run 38212422606, objectstack-upgrade included.

  • H4 (the judging gate). check:skill-compatibility was absent from release.yml and is now added to its content half. cut-rc.yml carries no post-version content half: its gates are pre-version and read .changeset/. So no run_gate was added there. Its Version the workspace step already goes red on a wrong stamp, because --fix re-checks what it wrote and exits 1.

  • H5 (the content half on a real 18.0.0-next.0 tree). Measured below.

  • H6 (size). +187/-20 over 3 files. The workflows are +45/-7. The script is +142/-13, about 95 of which are the self-test rows and their fixture.

H5: the version pass and the step, run on a scratch tree

I made a scratch worktree at this branch's 9540d87a8 (origin/main 246edf5b3 plus the two commits here) and ran pnpm install --frozen-lockfile. I then ran the Render the post-version tree and Validate the post-version tree step bodies, extracted verbatim from this branch's release.yml, with RUNNER_TEMP and GITHUB_STEP_SUMMARY pointed at scratch files. The scratch tree was discarded afterwards, and nothing from the version pass was committed.

  • Render: 426 pending changesets consumed and 1021 paths moved. check-skill-compatibility-version --fix reported "10 of 10 SKILL.md file(s) rewritten" (@objectstack/spec 17.x → 18.x, metadata.version "17.7.0" → "18.0.0-next.0"; the upgrade skill's stamp only), then its own check passed. protocol-version.ts did not move.
  • Control: the guard as it is on main (the step extracted from 246edf5b3), run on the same rendered tree: 10 lines of unexpected: skills/...SKILL.md, then the treadmill refusal, exit 1. This is run 38212422606's signature.
  • This branch's guard on the same tree: the shape check passed and the content half ran in full. Step summary: 1021 paths, all inside the reviewed shape; template stamps moved: 3; content gates failed: 0; unvalidated: 0. It ended with Post-version tree validated. (verify-lock VERDICT command-exit 0).
content gate (run_gate) verdict on the 18.0.0-next.0 tree
pnpm check:docs-image-tag green (3/3 surfaces, pins at the newest GA 17.7.0, pre mode)
pnpm check:docs-image-tag-sync green
pnpm check:template-version-sync green
pnpm check:release-index-currency-sync green
pnpm check:skill-compatibility (new) green: 10 files, 11 pins at 18.x, 10 stamps at 18.0.0-next.0, 1 exemption
pnpm check:nul-bytes green (10995 text files)
pnpm check:release-notes green
pnpm check:release-page-status green (v16, v17 in scope)
node scripts/check-release-section-coverage.mjs green
pnpm check:published-readme-links green
pnpm --filter create-objectstack --fail-if-no-match test green (18 files, 261 tests)
pnpm --filter @objectstack/spec --fail-if-no-match check:template-manifests green
pnpm --filter @objectstack/spec ... vitest run --project local src/kernel/protocol-version.test.ts green
pnpm --filter @objectstack/spec --fail-if-no-match check:spec-changes green
pnpm --filter @objectstack/spec --fail-if-no-match check:upgrade-guide green

Two more readings on the same rendered tree:

  • The judging gate can fail. I restored skills/objectstack-ai/SKILL.md to its pre-version bytes. node scripts/check-skill-compatibility-version.mjs then exited 1 with 2 problems naming that file: the 17.7.0 stamp and the 17.x pin. --fix put it back.
  • cut-rc.yml's staging and allowlist half (from the SURFACE_LIST resolve down to the LEFT check, with no git config, reset or commit):
    • the step as it is on main refuses with 10 unstaged: skills/...SKILL.md lines (exit 1), so an RC cut would fail the same way;
    • this branch stages 595 paths, 10 of them the skill stamps, and BAD and LEFT are both empty.
  • Not part of the step, read because AGENTS.md ties SKILL.md edits to it: pnpm --filter @objectstack/spec check:skill-docs is green on the rendered tree.

Self-test pin and ablation

check:skill-compatibility's self-test gains three registered rows. The battery floor moves 27 → 30.

  • The export equals the set --fix writes. The fixture is all-stale: two skills plus the exempt-shaped one, a skill directory with no SKILL.md, skills/README.md, and an internal .claude/skills/internal/SKILL.md. The export is compared against the set applyFix writes on that fixture, in walk order. The row also checks that the writes landed under the fixture root and that the internal skill was not touched.
  • A SKILL.md write outside the export stays unexpected. The row writes the list the way the workflows print it and spawns the guard's own grep -vxF -f LIST MOVED. Three outside paths (.claude/skills/internal/SKILL.md, skills/a/nested/SKILL.md, skills/no-skill-md/SKILL.md) come back as unexpected, exit 0. Control: the listed set alone is all admitted (exit 1, no output).
  • An empty tree throws. It never yields an empty list.

Ablation (one-off, after the commit, through scripts/ablation-replace.mjs). The mutation widened the export's return to append .claude/skills/internal/SKILL.md, and the tool confirmed it landed (anchor 1 → 0, blob 42eb51200996 → be0d19170cee). The self-test then exited 1 with exactly the first two rows red:

  • "--fix wrote [3 paths], the export lists [4 paths]";
  • "unexpected [2 paths], wanted [3 paths]".

The tool restored the file and confirmed the restore: blob equals HEAD 42eb51200996, and git diff HEAD is empty.

Gates (at 9540d87a8)

I derived the gate list with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on the actual diff. It returned 50 commands, identical to the dispatch's list. I ran all 50 and recorded each exit code before any pipe. All 50 exited 0. check:pm-dispatch-gates ended with "1828 cases pass" (fast tier). Reconciled with --ran: "50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN", a derived zero because all 50 lines carry an exit code. node scripts/check-skill-compatibility-version.mjs --self-test reports "22 check cases and 8 --fix derivation cases pass". A control-byte self-scan of the three files found none.

Acceptance notes

  • release.yml's version-pr header comment sits outside the Validate the post-version tree step, so I did not edit it. Two parts of it are now stale:

    • the CONTENT gate list does not name check:skill-compatibility;
    • the note above Create or update the "chore: version packages" PR counts the version script's rewriters as four. The script has five after changeset version, and the skill stamper is the fifth.

    Carrier: the next change to that header; none is named yet.

  • The self-test's success line counts the three new rows inside "--fix derivation cases". They are registered and floored like every other row; only the label is loose.

  • The H5 reading is for 9540d87a8. The scheduled run will render main at whatever sha it reads, so main landing more before then can still move a verdict. That run is the done-when reading on release(v18): the version-pr lane refuses the major boundary at Validate the post-version tree, so #21988 never refreshes into 18.0.0-next.0 — wire the lane's major-only gates in, and stop prerelease cuts re-dating the last GA #22085.

  • cut-rc.yml requires pre-mode tag rc, and .changeset/pre.json currently says next. So the cut-rc reading above is a simulation of its staging and allowlist half on the next.0 tree, not a dispatch.


Generated by Claude Code

…Paths()

The root `version` script ends with this script's `--fix`, so the SKILL.md
files it restamps are a version-time output. Export the paths `--fix` may
write, derived from the same walk (`readSkillFiles`) the extracted `applyFix`
leg writes from, for the post-version shape guard to resolve the way it
resolves `stampedPaths()` and `syncedPaths()`. Zero skills throws.

Self-test: the export equals the set `--fix` writes on an all-stale fixture,
a SKILL.md path outside the export stays unexpected under the guard's own
`grep -vxF -f` filter, and an empty tree refuses.

Claude-Session: https://claude.ai/code/session_012yK1ddAdAqfzwigRHZq3r2
Co-authored-by: Claude <noreply@anthropic.com>
…dSkillPaths()

`Validate the post-version tree` resolves the SKILL.md stamps the version
pass's last step writes as a fourth list, with its siblings' two refusals
(could not resolve; resolved EMPTY), filters by whole-line exact match, and
runs the gate that judges them, `check:skill-compatibility`, in the content
half. `cut-rc.yml` resolves the same list, stages it, and re-checks the staged
set against it.

Claude-Session: https://claude.ai/code/session_012yK1ddAdAqfzwigRHZq3r2
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 12, 2026
@github-actions github-actions Bot added the ci/cd label Oct 12, 2026
@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 12, 2026 07:57
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 12, 2026 07:57
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 12, 2026
Merged via the queue into main with commit 340eab7 Oct 12, 2026
36 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-22970-skill-stamps-post-version-surface branch October 12, 2026 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants