Repository navigation
ci(release): the post-version guard admits the SKILL.md stamps through stampedSkillPaths() - #22980
Merged
objectstack-fleet[bot] merged 2 commits intoOct 12, 2026
Conversation
…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
Bot
deleted the
claude/issue-22970-skill-stamps-post-version-surface
branch
October 12, 2026 08:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #22970
Clause-②: no
Refs #22085 (the version-PR lane: the first scheduled
release.ymlrun after this lands is the reading owed there).What changed
scripts/check-skill-compatibility-version.mjsexportsstampedSkillPaths({ root }): every repo-relativeskills/NAME/SKILL.mdpath its--fixmay write, in walk order, derived fromreadSkillFiles(). The--fixleg itself moved into an exportedapplyFix(scanned, pkgs, root)that writes from that same walk, so the list and the writes come from one walk. Zero skills throws, the same waystampedPaths()does. The one EXEMPT file (skills/objectstack-upgrade/SKILL.md) is in the list, because the exemption covers its pin and not itsmetadata.versionstamp.main()prints the same lines as before.release.yml(theValidate the post-version treestep only):SKILL_LISTis resolved bynode --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.run_gate pnpm check:skill-compatibility(self-test plus check, no--fix) now runs in the content half, aftercheck:release-index-currency-sync.cut-rc.yml(Build the single version commit): the same resolve and the same two refusals.SKILL_SURFACESjoins thegit add -Apathspec, andSKILL_LISTjoins theBADre-check as the fifth filter.skills/**, the rootversionscript,.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.ymlValidate the post-version treeand atcut-rc.yml'sBADfilter, as stated. I rangit grepforTEMPLATE_LIST|SURFACE_LIST|INDEX_LIST|post-version-paths|stampedPaths|syncedPathsoutside the two workflows and the two rewriters. It hits only:stampedPaths()test;scripts/cross-package-test-inputs.mjs;H43_/H48_SURFACE_LIST_CAPconstants inscripts/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-wiredcredits 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 statusstays clean), and exits 0.pnpm check:entry-guardis 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-upgradeincluded.H4 (the judging gate).
check:skill-compatibilitywas absent fromrelease.ymland is now added to its content half.cut-rc.ymlcarries no post-version content half: its gates are pre-version and read.changeset/. So norun_gatewas added there. ItsVersion the workspacestep already goes red on a wrong stamp, because--fixre-checks what it wrote and exits 1.H5 (the content half on a real
18.0.0-next.0tree). 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/main246edf5b3plus the two commits here) and ranpnpm install --frozen-lockfile. I then ran theRender the post-version treeandValidate the post-version treestep bodies, extracted verbatim from this branch'srelease.yml, withRUNNER_TEMPandGITHUB_STEP_SUMMARYpointed at scratch files. The scratch tree was discarded afterwards, and nothing from the version pass was committed.check-skill-compatibility-version --fixreported "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.tsdid not move.main(the step extracted from246edf5b3), run on the same rendered tree: 10 lines ofunexpected: skills/...SKILL.md, then the treadmill refusal, exit 1. This is run 38212422606's signature.Post-version tree validated.(verify-lockVERDICT command-exit 0).run_gate)18.0.0-next.0treepnpm check:docs-image-tagpnpm check:docs-image-tag-syncpnpm check:template-version-syncpnpm check:release-index-currency-syncpnpm check:skill-compatibility(new)pnpm check:nul-bytespnpm check:release-notespnpm check:release-page-statusnode scripts/check-release-section-coverage.mjspnpm check:published-readme-linkspnpm --filter create-objectstack --fail-if-no-match testpnpm --filter @objectstack/spec --fail-if-no-match check:template-manifestspnpm --filter @objectstack/spec ... vitest run --project local src/kernel/protocol-version.test.tspnpm --filter @objectstack/spec --fail-if-no-match check:spec-changespnpm --filter @objectstack/spec --fail-if-no-match check:upgrade-guideTwo more readings on the same rendered tree:
skills/objectstack-ai/SKILL.mdto its pre-version bytes.node scripts/check-skill-compatibility-version.mjsthen exited 1 with 2 problems naming that file: the17.7.0stamp and the17.xpin.--fixput it back.cut-rc.yml's staging and allowlist half (from theSURFACE_LISTresolve down to theLEFTcheck, with no git config, reset or commit):mainrefuses with 10unstaged: skills/...SKILL.mdlines (exit 1), so an RC cut would fail the same way;BADandLEFTare both empty.pnpm --filter @objectstack/spec check:skill-docsis 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.--fixwrites. 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 setapplyFixwrites 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.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).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, blob42eb51200996→be0d19170cee). The self-test then exited 1 with exactly the first two rows red:The tool restored the file and confirmed the restore: blob equals HEAD
42eb51200996, andgit diff HEADis empty.Gates (at
9540d87a8)I derived the gate list with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon 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-gatesended 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-testreports "22 check cases and 8 --fix derivation cases pass". A control-byte self-scan of the three files found none.Acceptance notes
release.yml'sversion-prheader comment sits outside theValidate the post-version treestep, so I did not edit it. Two parts of it are now stale:check:skill-compatibility;Create or update the "chore: version packages" PRcounts the version script's rewriters as four. The script has five afterchangeset 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 rendermainat whatever sha it reads, somainlanding 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 atValidate 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.ymlrequires pre-mode tagrc, and.changeset/pre.jsoncurrently saysnext. So the cut-rc reading above is a simulation of its staging and allowlist half on thenext.0tree, not a dispatch.Generated by Claude Code