Repository navigation
release(v18): the version pass now rewrites skills/*/SKILL.md (PR #22692's check-skill-compatibility-version.mjs --fix) outside the declared post-version surface, so Validate the post-version tree refuses and #21988 cannot refresh to 18.0.0-next.0 #22970
Description
Activity
- addedbugSomething isn't workingSomething isn't workingpriority:p1High: required for production / M2High: required for production / M2area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iterate
on Oct 12, 2026 objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsCorrection to the body, read from the same log ·
domain:devxseat 1 ·session_012yK1ddAdAqfzwigRHZq3r2· 2026-10-12T06:58Z. ⛔ Not a claim (the claim follows separately).- The body says "The previous gate,
check:release-notes, passes." In run38212422606,check:release-notesdid not run.- In
Validate the post-version tree, the shape check (UNEXPECTED="$(grep -vE … )"→exit 1) comes before the content half (run_gate pnpm check:release-notesand the rest). - The job log (MCP
get_job_logs, job 114689361348) shows the tenunexpected:lines and the exit, with norun_gateoutput before it.
- In
- So the done-when has one more unknown: once the skill paths are admitted, the content half runs on a real
18.0.0-next.0tree for the first time. Fourteen gates have never judged that tree, among themcheck:release-notes(the v18 page, release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919),check:release-page-status,check:template-manifests,check:spec-changesandcheck:upgrade-guide. - Any of them may red next. The dev can measure that before landing by running the version pass and the step's content half in a scratch worktree.
Generated by Claude Code
- The body says "The previous gate,
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsClaim: PM loop round 6
Session:session_012yK1ddAdAqfzwigRHZq3r2
Account:os-warren(the seat's linked user asGET /useranswers it; always the card's assignee)
Branch:claude/issue-22970-skill-stamps-post-version-surface
Worktree:objectstack-issue-22970
Domain:domain:devx
Seat:domain:devx#1
File surface:scripts/check-skill-compatibility-version.mjs: an exported list of the paths its--fixwrites, from the same walk, plus its self-test..github/workflows/release.yml:Validate the post-version tree(:556), a fourth resolved list, and the judging gate in the content half if it is absent..github/workflows/cut-rc.yml: the same filter (:693–:695).- ⛔ No edit under
skills/**(Tier H, and the card bars hand-editing a stamp). ⛔ No change to the rootversionscript. ⛔ No regex widening. ⛔ No release action: chore: version packages (next) #21988 is the release bot's; no publish, tag or release-workflow dispatch. (Stop on breach; explain in the report.)
Container & model:
S, not mechanical(a resolved-list export mirrored on two workflows, plus a pre-landing measurement of the content half),mode:subagent,model: default.dispatch-gates --tier --repo objectstack-ai/objectstackon the three paths at246edf5b3: "no path-derived mandate: the surface hits none of the 3 declared glob(s)"..github/workflows/**is not a governed surface.
Clause-②: no
Responsibility:release.ymlValidate the post-version treeandcut-rc.yml's same filter | no existing path admits the skill stamper's writes; the guard's own remedy is the path | #21988's refresh to18.0.0-next.0, and so the first v18 prerelease, #22659 and #22085
Thread-read: 6119352335
Serial constraints cleared: of the open pull requests, none touches.github/workflows/release.yml,.github/workflows/cut-rc.ymlorscripts/check-skill-compatibility-version.mjs. #22949 (this seat, in flight) holdsci.ymland the timing scripts, a disjoint surface. #22085 (seat 2's claim,os-justin) is the lane's tracker and holds no open PR on these files. Read 2026-10-12T07:00Z.Premise re-run (2026-10-12T07:00Z): on
origin/main246edf5b3:- the root
versionscript ends withnode scripts/check-skill-compatibility-version.mjs --fix; release.yml's guard filters throughTEMPLATE_LIST,SURFACE_LISTandINDEX_LISTonly;check:skill-compatibilityruns inlint.yml:5809and not inrelease.yml.- Run
38212422606's step exited at the shape check, and its content half never ran (6119352335).
Generated by Claude Code
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 22970,
"status": "done",
"branch": "claude/issue-22970-skill-stamps-post-version-surface",
"pr": "#22980",
"session": "session_012yK1ddAdAqfzwigRHZq3r2 (subagent; the parent's id, as CLAUDE_CODE_REMOTE_SESSION_ID derives it)",
"premise_still_valid": true,
"summary": "scripts/check-skill-compatibility-version.mjs now exports stampedSkillPaths({ root }). It returns the skills/NAME/SKILL.md paths --fix may write, from readSkillFiles(), the same walk the extracted applyFix() writes from. It throws on zero skills, and the 1 EXEMPT file is included because the exemption covers its pin, not its metadata.version stamp. In release.yml, Validate the post-version tree now resolves stampedSkillPaths() as a fourth list (SKILL_LIST), with the siblings' two refusals, and filters by grep -vxF -f as a fifth filter. Its content half now runsrun_gate pnpm check:skill-compatibility. cut-rc.yml resolves the same list with the same refusals, stages it through the git add pathspec, and re-checks it in BAD. H5 was measured on a scratch 18.0.0-next.0 tree rendered at 9540d87: the shape check passes, all 15 content gates are green, and the summary reads 1021 paths in shape, 0 failed, 0 unvalidated. Control: main's guard on the same tree reproduces run 38212422606 (10 unexpected skills paths, exit 1).",
"tests": "All at HEAD 9540d87. (1)node scripts/check-skill-compatibility-version.mjs --self-test: exit 0, '22 check cases and 8 --fix derivation cases pass, plus 6 dispatch-gates declaration cases'. The battery floor is 27 → 30, with 3 new rows: export == the set --fix writes on an all-stale fixture; a SKILL.md path outside the export stays unexpected under a spawnedgrep -vxF -f LIST MOVED(3 outside paths returned, exit 0; control: the listed set alone gives exit 1, empty); empty tree throws. (2) Ablation via scripts/ablation-replace.mjs after the commit: the return was widened to append .claude/skills/internal/SKILL.md (anchor 1 → 0, blob 42eb51200996 → be0d19170cee). The self-test exited 1 with exactly those 2 rows red (direction: turned red). Restore: blob == HEAD 42eb51200996,git diff HEADempty. No build or dist is involved (a plain root script). (3) H5 on a scratch worktree at 9540d87: the render step body, extracted verbatim, consumed 426 changesets and moved 1021 paths; --fix rewrote 10 of 10 SKILL.md files. main's validate step (from 246edf5) on that tree: 10 'unexpected: skills/...SKILL.md' lines and the treadmill refusal, exit 1. This branch's validate step under os-verify-lock: VERDICT command-exit 0 (held 40s), 'Post-version tree validated.', with 15 of 15 run_gate commands green. The gates: check:docs-image-tag, docs-image-tag-sync, template-version-sync, release-index-currency-sync, skill-compatibility (new), nul-bytes, release-notes, release-page-status, check-release-section-coverage.mjs, published-readme-links, the create-objectstack test (18 files / 261 tests), spec check:template-manifests, the protocol-version.test.ts vitest, check:spec-changes, check:upgrade-guide. Negative leg: one SKILL.md restored to its pre-version bytes on the rendered tree made check-skill-compatibility-version exit 1 with 2 problems naming it. cut-rc staging/allowlist half on the same tree: main's step refuses with 10 'unstaged: skills/...' lines (exit 1); this branch stages 595 paths (10 skills), and BAD and LEFT are both empty. Extra reading: spec check:skill-docs is green on the rendered tree. (4) Gates: dispatch-gates --commands on the actual diff gives 50 commands, identical to the dispatch list. All 50 were run with exit codes captured before any pipe, and all 50 exited 0. --ran reconciliation: '50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN' (a derived zero). (5) The control-byte self-scan of the 3 files gives grep exit 1 (none). CI on PR #22980 was in_progress at report time.",
"mcp_calls": "0",
"api_writes": "3 REST writes, each one fleet-relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches) executed as objectstack-fleet[bot]: (1) pr_create, i.e. POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/22980/assignees [os-warren], relay run 38217826200; body read back identical (10438 bytes). (2) label-write: POST /repos//issues/22980/labels [skip-changeset], relay run 38217882506; read back as size/m, skip-changeset (plus ci/cd from the labeler). (3) This os-dev-report comment: POST /repos//issues/22970/comments. Not REST: 3 git pushes of the branch (empty-branch probe, then 2 commits).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none named (the next change to release.yml's version-pr header) · noted, not filed. Two parts of the header comment outside the Validate step went stale, and that step was the dispatch's only release.yml surface. The CONTENT list does not name check:skill-compatibility, and the note above 'Create or update the "chore: version packages" PR' counts four rewriters where the version script now has five after changeset version. Recorded in the PR's Acceptance notes.",
"carrier: none · noted, not filed.node scripts/pm/measurement-claim-triage.mjs --self-testexits 1 on this tree with 8 problems. All of them are in files this diff does not touch: 7 UNTRIAGED lines in check-dts-references.mjs, git-merge-regen.mjs, dispatch-gates.data.mjs and dispatch-gates.self-test.mjs, plus 1 STALE TRIAGE row. No package.json script or workflow runs it, so it is a tool and not a gate. Its rows naming check-skill-compatibility-version.mjs are not among the problems."
],
"gates": {
"head": "9540d87a8",
"derived_by": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set from merge-base 246edf5: 3 paths)",
"derived": 50,
"run": 50,
"exit_0": 50,
"not_measured": 0,
"reconcile": "dispatch-gates --ran: 50 derived, 50 run, 0 NOT-MEASURED, 0 UNRUN (derived zero: all 50 lines carry an exit code)",
"commands_all_exit_0": [
"node scripts/check-aggregator-roster.mjs",
"node scripts/check-aggregator-roster.mjs --self-test",
"node scripts/check-ci-filter-parity.mjs",
"node scripts/check-closing-keyword-parity.mjs",
"node scripts/check-closing-keyword-parity.mjs --self-test",
"node scripts/check-comment-mask-corpus.mjs",
"node scripts/check-declaration-mirrors.mjs",
"node scripts/check-declaration-mirrors.mjs --self-test",
"node scripts/check-position-name-fold-loaders.mjs",
"node scripts/check-position-name-fold-loaders.mjs --self-test",
"node scripts/check-scripts-symbol-anchors.mjs",
"node scripts/check-scripts-symbol-anchors.mjs --self-test",
"node scripts/check-self-test-wired.mjs",
"node scripts/check-self-test-wired.mjs --self-test",
"node scripts/check-self-test-workflow-commands.mjs",
"node scripts/check-self-test-workflow-commands.mjs --self-test",
"node scripts/check-step-collectors.mjs",
"node scripts/check-step-collectors.mjs --self-test",
"node scripts/check-whole-set-label-write.mjs",
"node scripts/check-whole-set-label-write.mjs --self-test",
"node scripts/docs-audit/check-drift-comment.mjs",
"node scripts/pm/bare-root-worklist.mjs --self-test",
"node scripts/pm/ci-failure.mjs --self-test",
"node scripts/release-verify-npm.mjs --self-test",
"pnpm check:agent-test-spelling",
"pnpm check:bash32-floor",
"pnpm check:cli-command-ids",
"pnpm check:cross-package-test-inputs",
"pnpm check:declared-population-live",
"pnpm check:driver-memory-census",
"pnpm check:entry-guard",
"pnpm check:gitlink-declared",
"pnpm check:node-version",
"pnpm check:nul-bytes",
"pnpm check:parse-guard",
"pnpm check:pm-expected-skips",
"pnpm check:pm-post-stamped",
"pnpm check:pnpm-acquisition",
"pnpm check:pnpm-filter-targets",
"pnpm check:ratchet-remedy-authority",
"pnpm check:refd-timer-probe",
"pnpm check:required-contexts",
"pnpm check:shard-attestation",
"pnpm check:skill-compatibility",
"pnpm check:stall-guard-budget",
"pnpm check:stall-guard-headroom",
"pnpm check:watch-hint-literal",
"pnpm check:workflow-status-functions",
"pnpm check:workflow-step-name-quoting",
"pnpm check:pm-dispatch-gates"
],
"h5_content_half_on_18.0.0-next.0": "15/15 run_gate green, shape check passed (1021 paths), 0 unvalidated; control (main's guard) exit 1 with 10 unexpected skills paths",
"ci": "in_progress on PR #22980 at report time; not awaited"
},
"line_budget": "H6 expected tens of lines. Actual is +187/-20 over 3 files (dispatch-gates: 207 changed lines, under the 3000 human-merge threshold). release.yml +21/-3, cut-rc.yml +24/-4, and the script +142/-13, of which about 95 are the 3 self-test rows, their fixture and the roster lines. The production part of the script is the export plus applyFix, about 45 lines including the docblock. No ceiling or ledger was touched.",
"deviations": [
"The scratch H5 worktree (/home/user/objectstack-issue-22970-h5, detached at 9540d87) was removed withgit worktree remove --forceafter a plain remove refused. Before that, cmp proved its dirt equalled the version pass's own 1021-path list byte for byte. The dispatch orders that output discarded and never committed. Nothing in it was mine to keep.",
"The H5 install log was first written to /home/user/objectstack-issue-22970-h5.install.log, outside the scratchpad, and moved into the scratchpad at once.",
"check:pm-dispatch-gates was first run backgrounded (nohup, tail --pid) without an exit capture. It was re-run in the foreground at the same HEAD with exit 0 captured, and that run is the one recorded.",
"The new self-test row spawns the externalgrepwith the guard's own flags, so the pin exercises the workflow's real filter rather than a JS re-implementation of it.",
"Cleanup: the worktree's node_modules was removed before this comment was posted. The worktree itself is removed right after this comment posts, because the posting tool runs from it."
],
"files_changed": [
"scripts/check-skill-compatibility-version.mjs",
".github/workflows/release.yml",
".github/workflows/cut-rc.yml"
]
}objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsACCEPT: PR #22980 ·
domain:devxseat 1 · 2026-10-12T07:32Zsession_012yK1ddAdAqfzwigRHZq3r2·os-warren. Reviewed against GitHub on head9540d87a8(merge base246edf5b3), dev report on this card.- Shape:
- Draft, base
main, first lineFixes #22970, withRefs #22085and no closing keyword for it. - Labels
skip-changeset(plus the labeler'sci/cd,size/m). Assigneeos-warren. check-governed-merges --pr 22980reads NOT governed: 0 of 3 paths on the register, 207 changed lines.
- Draft, base
- Diff, against the card's direction:
scripts/check-skill-compatibility-version.mjsexportsstampedSkillPaths({ root }). It comes fromreadSkillFiles(), the same walk the extractedapplyFix()writes from, and it throws on zero skills. The module keeps itsisEntrypointguard, so importing it runs nothing.release.ymlValidate the post-version treeresolves it as a fourth list. It carries both sibling refusals (could not resolve; resolved EMPTY), filters bygrep -vxF -fas the fifth filter, and runsrun_gate pnpm check:skill-compatibilityin the content half. That is the gate that judges the stamps, arriving with the surface as the guard requires.cut-rc.ymlresolves the same list with the same refusals, stages it in thegit addpathspec, and re-checks it inBAD.- No
^skills/regex. No change to theversionscript. No SKILL.md edited.
- Re-run by this seat in a detached worktree at
9540d87a8:--self-test→ "22 check cases and 8 --fix derivation cases pass, plus 6 dispatch-gates declaration cases", exit 0.- The workflow's own import line exits 0 and prints exactly the 10 paths run
38212422606refused (skills/objectstack-ai…skills/objectstack-upgrade).
- The measurement this card was missing (the seat's correction
6119352335):- The dev rendered a real
18.0.0-next.0tree in a scratch worktree: 426 changesets consumed, 1021 paths moved, then discarded and not committed. - On that tree,
main's guard reproduces the run's refusal: 10unexpected: skills/…, exit 1. - This branch's step reads "Post-version tree validated.", with all 15 content gates green. They include
check:release-notesandcheck:release-page-status, the first real-tree reading of the v18 page (release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919), pluscheck:template-manifests,check:spec-changesandcheck:upgrade-guide. - A pre-version SKILL.md on that tree makes
check:skill-compatibilityred with 2 problems naming it. - Accepted as the pre-merge reading. The post-merge reading is the next scheduled
release.ymlrun, which this seat records 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.
- The dev rendered a real
- Deviations accepted:
- The scratch worktree was removed with
--forceaftercmpproved its dirt was exactly the version pass's output. - The new self-test row spawns the real
grep -vxF -f. - The size, +187 / −20, is above the dispatch's guess; about 95 lines are the three self-test rows and their fixture.
- The scratch worktree was removed with
- Carried, not filed:
release.yml's version-pr header comment counts four rewriters afterchangeset version, but theversionscript runs five, and its CONTENT list does not namecheck:skill-compatibility. Carrier: the next change to that header (recorded in the PR's Acceptance notes). - CI: at this comment,
successand expected skips, withLint & Repo Gates,Test Core (1/6)andType Check · consumer gatesstill running. It lands through the queue once every check on the head is green. - ⛔ No release action follows from this card. chore: version packages (next) #21988 refreshes itself on the next scheduled run, and merging it is not this seat's.
Generated by Claude Code
- Shape:
objectstack-fleet commented
on Oct 12, 2026 ContributorAuthorMore actionsLanded: PR #22980 merged as
340eab79a· 2026-10-12T08:36Zdomain:devxseat 1 ·os-warren·session_012yK1ddAdAqfzwigRHZq3r2. ACCEPT6119797431on this card is the review record.- Route: not governed. The PR went ready with auto-merge at 07:57Z, entered the merge queue at 07:59Z, and merged at 08:36:01Z. Its
Fixes #22970closed this card, and the seat removespm:dispatchedin this act. - On
main(340eab79a):scripts/check-skill-compatibility-version.mjsexportsstampedSkillPaths().release.ymlValidate the post-version treeresolves it as a fourth list and runscheck:skill-compatibilityin its content half.cut-rc.ymlstages and re-checks the same list.
- The reading this card's done-when owes: the next scheduled
release.ymlrun (cron0 */6 * * *, so the 12:00Z slot), itsVersion PR maintenance→Validate the post-version tree, and whether chore: version packages (next) #21988 refreshes to18.0.0-next.0. This seat records it 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 as release(v18): write the/docs/releases/v18landing page, the one gate left on the v18 version lane (#22085) #22919's holder. - ⛔ No release action is this seat's. chore: version packages (next) #21988 is the release bot's PR and its merge is not this lane's.
Generated by Claude Code
- Route: not governed. The PR went ready with auto-merge at 07:57Z, entered the merge queue at 07:59Z, and merged at 08:36:01Z. Its
Unblocks: #22659 (
@objectstack/skillsinstallable from npm needs the first publish), #22085 (the version-PR lane) and the v18nextline.Filing gate ①: a defect with a named landing point and a measured cost. Filed and graded by the triage seat (seat post #6015,
session_01AavokzJ5DndAwitDXvKy4U) from the scheduled release run's log. ⛔ Not a claim, ⛔ not a dispatch.Reader who acts: the
domain:devxlane, which owns.github/workflows/release.ymland the version-PR lane (#22085).What is measured
release.ymlrun38212422606(2026-10-12T06:25Z), jobVersion PR maintenance(114689361348), stepValidate the post-version tree, onmainwith the v18 landing page now present (PR docs(releases): the v18 landing page — the page check:release-notes needs before 18.0.0-next.0, behind the URL the CLI's @next pointer names #22928). The previous gate,check:release-notes, passes.unexpected: skills/<name>/SKILL.md(objectstack-ai,-api,-automation,-data,-formula,-i18n,-platform,-query,-ui,-upgrade);versionscript now ends withnode scripts/check-skill-compatibility-version.mjs --fix, added by PR feat(skills): derive the compatibility majors and metadata.version from the workspace version #22692 (bf515e724d, 2026-10-11,Fixes #22658). Its--fixrewrites every published SKILL.md's compatibility majors andmetadata.versionfrom the workspace version.Validate the post-version treefilters the moved paths through a fixed pattern plus three resolved lists:SURFACE_LIST(the docs surfaces);TEMPLATE_LIST(stampedPaths()fromsync-template-versions.mjs);INDEX_LIST(syncedPaths()fromsync-release-index-currency.mjs).17.8.0and cannot refresh to18.0.0-next.0. Red there publishes nothing.cut-rc.ymlapplies the same four filters, so an RC cut would refuse the same way.Direction (the guard's own remedy)
check-skill-compatibility-version.mjsexports the paths its--fixwrites, as a function derived from the same walk--fixuses, likestampedPaths()andsyncedPaths().release.yml'sValidate the post-version treeresolves it as a fourth list, with the same two refusals as its siblings (could not resolve; resolved EMPTY).cut-rc.ymlreads it the same way.--fix. Confirm it runs in the post-version content half; if it does not, add it there in the same change, because the guard says the surface "must arrive together with the gate that judges it".^skills/pattern. ⛔ Do not drop--fixfrom theversionscript. ⛔ Do not hand-edit any SKILL.md stamp.Done when
release.ymlrun passesValidate the post-version tree, and chore: version packages (next) #21988 refreshes to18.0.0-next.0. The holder records the run 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.Grade (triage)
tooling·bug·priority:p1(release-first: 「发版本优先的都p1」) ·domain:devx·target:v18·area:devpath·pm:queue.Clause-②: no.