Repository navigation
Closed
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:devxDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpriority:p1High: required for production / M2High: required for production / M2target:v18toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surfaceFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
Description
Unblocks: #22659 (@objectstack/skills installable from npm needs the first publish), #22085 (the version-PR lane) and the v18 next line.
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:devx lane, which owns .github/workflows/release.yml and the version-PR lane (#22085).
What is measured
- Scheduled
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. - It refuses with the treadmill guard:
- ten lines
unexpected: skills/<name>/SKILL.md(objectstack-ai,-api,-automation,-data,-formula,-i18n,-platform,-query,-ui,-upgrade); - then "the version pass wrote outside the reviewed post-version surface (paths above). … a new version-time output must arrive together with the gate that judges it. Add the surface to the declaration its rewriter reads, and its gate …".
- ten lines
- The writer: the root
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. - What the guard reads:
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).- The skill rewriter exports no such list, so its writes read as unexpected.
- Cost:
- chore: version packages (next) #21988 stays at
17.8.0and cannot refresh to18.0.0-next.0. Red there publishes nothing. - This is now the only failing gate on the version lane I found in this run.
- The guard's own header says
cut-rc.ymlapplies the same four filters, so an RC cut would refuse the same way.
- chore: version packages (next) #21988 stays at
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.- The gate that judges the stamps: the same script without
--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". - ⛔ No regex widening such as a
^skills/pattern. ⛔ Do not drop--fixfrom theversionscript. ⛔ Do not hand-edit any SKILL.md stamp.
Done when
- The next scheduled
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. - A self-test or pin shows that a SKILL.md write outside the exported list is still refused.
Grade (triage)
tooling · bug · priority:p1 (release-first: 「发版本优先的都p1」) · domain:devx · target:v18 · area:devpath · pm:queue. Clause-②: no.
Metadata
Metadata
Assignees
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:devxDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpriority:p1High: required for production / M2High: required for production / M2target:v18toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surfaceFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
Activity
objectstack-fleet commentedon Oct 12, 2026
Correction to the body, read from the same log ·
domain:devxseat 1 ·session_012yK1ddAdAqfzwigRHZq3r2· 2026-10-12T06:58Z. ⛔ Not a claim (the claim follows separately).check:release-notes, passes." In run38212422606,check:release-notesdid not run.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).get_job_logs, job 114689361348) shows the tenunexpected:lines and the exit, with norun_gateoutput before it.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.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Claim: PM loop round 6
Session:
session_012yK1ddAdAqfzwigRHZq3r2Account:
os-warren(the seat's linked user asGET /useranswers it; always the card's assignee)Branch:
claude/issue-22970-skill-stamps-post-version-surfaceWorktree:
objectstack-issue-22970Domain:
domain:devxSeat:
domain:devx#1File 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).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 #22085Thread-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: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.38212422606's step exited at the shape check, and its content half never ran (6119352335).Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
os-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 runs
run_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 with
git 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 external
grepwith 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 commentedon Oct 12, 2026
ACCEPT: PR #22980 ·
domain:devxseat 1 · 2026-10-12T07:32Zsession_012yK1ddAdAqfzwigRHZq3r2·os-warren. Reviewed against GitHub on head9540d87a8(merge base246edf5b3), dev report on this card.main, first lineFixes #22970, withRefs #22085and no closing keyword for it.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.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.^skills/regex. No change to theversionscript. No SKILL.md edited.9540d87a8:--self-test→ "22 check cases and 8 --fix derivation cases pass, plus 6 dispatch-gates declaration cases", exit 0.38212422606refused (skills/objectstack-ai…skills/objectstack-upgrade).6119352335):18.0.0-next.0tree in a scratch worktree: 426 changesets consumed, 1021 paths moved, then discarded and not committed.main's guard reproduces the run's refusal: 10unexpected: skills/…, exit 1.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.check:skill-compatibilityred with 2 problems naming it.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.--forceaftercmpproved its dirt was exactly the version pass's output.grep -vxF -f.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).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.Generated by Claude Code
objectstack-fleet commentedon Oct 12, 2026
Landed: PR #22980 merged as
340eab79a· 2026-10-12T08:36Zdomain:devxseat 1 ·os-warren·session_012yK1ddAdAqfzwigRHZq3r2. ACCEPT6119797431on this card is the review record.Fixes #22970closed this card, and the seat removespm:dispatchedin this act.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.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.Generated by Claude Code