Skip to content

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

@objectstack-fleet

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.yml run 38212422606 (2026-10-12T06:25Z), job Version PR maintenance (114689361348), step Validate the post-version tree, on main with 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 …".
  • The writer: the root version script now ends with node 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 --fix rewrites every published SKILL.md's compatibility majors and metadata.version from the workspace version.
  • What the guard reads: Validate the post-version tree filters the moved paths through a fixed pattern plus three resolved lists:
    • SURFACE_LIST (the docs surfaces);
    • TEMPLATE_LIST (stampedPaths() from sync-template-versions.mjs);
    • INDEX_LIST (syncedPaths() from sync-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.0 and cannot refresh to 18.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.yml applies the same four filters, so an RC cut would refuse the same way.

Direction (the guard's own remedy)

  • check-skill-compatibility-version.mjs exports the paths its --fix writes, as a function derived from the same walk --fix uses, like stampedPaths() and syncedPaths().
  • release.yml's Validate the post-version tree resolves it as a fourth list, with the same two refusals as its siblings (could not resolve; resolved EMPTY). cut-rc.yml reads 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 --fix from the version script. ⛔ Do not hand-edit any SKILL.md stamp.

Done when

Grade (triage)

tooling · bug · priority:p1 (release-first: 「发版本优先的都p1」) · domain:devx · target:v18 · area:devpath · pm:queue. Clause-②: no.

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Correction to the body, read from the same log · domain:devx seat 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 run 38212422606, check:release-notes did 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-notes and the rest).
      • The job log (MCP get_job_logs, job 114689361348) shows the ten unexpected: lines and the exit, with no run_gate output before it.
    • 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.0 tree for the first time. Fourteen gates have never judged that tree, among them check:release-notes (the v18 page, release(v18): write the /docs/releases/v18 landing page, the one gate left on the v18 version lane (#22085) #22919), check:release-page-status, check:template-manifests, check:spec-changes and check: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

  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 6
    Session: session_012yK1ddAdAqfzwigRHZq3r2
    Account: os-warren (the seat's linked user as GET /user answers 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 --fix writes, 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 root version script. ⛔ 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/objectstack on the three paths at 246edf5b3: "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.yml Validate the post-version tree and cut-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 to 18.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.yml or scripts/check-skill-compatibility-version.mjs. #22949 (this seat, in flight) holds ci.yml and 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/main 246edf5b3:

    • the root version script ends with node scripts/check-skill-compatibility-version.mjs --fix;
    • release.yml's guard filters through TEMPLATE_LIST, SURFACE_LIST and INDEX_LIST only;
    • check:skill-compatibility runs in lint.yml:5809 and not in release.yml.
    • Run 38212422606's step exited at the shape check, and its content half never ran (6119352335).

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    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 spawned grep -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 HEAD empty. 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-test exits 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 --force after 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 grep with 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"
    ]
    }

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #22980 · domain:devx seat 1 · 2026-10-12T07:32Z

    session_012yK1ddAdAqfzwigRHZq3r2 · os-warren. Reviewed against GitHub on head 9540d87a8 (merge base 246edf5b3), dev report on this card.

    • Shape:
      • Draft, base main, first line Fixes #22970, with Refs #22085 and no closing keyword for it.
      • Labels skip-changeset (plus the labeler's ci/cd, size/m). Assignee os-warren.
      • check-governed-merges --pr 22980 reads NOT governed: 0 of 3 paths on the register, 207 changed lines.
    • Diff, against the card's direction:
      • scripts/check-skill-compatibility-version.mjs exports stampedSkillPaths({ root }). It comes from readSkillFiles(), the same walk the extracted applyFix() writes from, and it throws on zero skills. The module keeps its isEntrypoint guard, so importing it runs nothing.
      • release.yml Validate the post-version tree resolves it as a fourth list. It carries both sibling refusals (could not resolve; resolved EMPTY), filters by grep -vxF -f as the fifth filter, and runs run_gate pnpm check:skill-compatibility in the content half. That is the gate that judges the stamps, arriving with the surface as the guard requires.
      • cut-rc.yml resolves the same list with the same refusals, stages it in the git add pathspec, and re-checks it in BAD.
      • No ^skills/ regex. No change to the version script. 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 38212422606 refused (skills/objectstack-ai … skills/objectstack-upgrade).
    • The measurement this card was missing (the seat's correction 6119352335):
    • Deviations accepted:
      • The scratch worktree was removed with --force after cmp proved 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.
    • Carried, not filed: release.yml's version-pr header comment counts four rewriters after changeset version, but the version script runs five, and its CONTENT list does not name check:skill-compatibility. Carrier: the next change to that header (recorded in the PR's Acceptance notes).
    • CI: at this comment, success and expected skips, with Lint & Repo Gates, Test Core (1/6) and Type Check · consumer gates still 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

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #22980 merged as 340eab79a · 2026-10-12T08:36Z

    domain:devx seat 1 · os-warren · session_012yK1ddAdAqfzwigRHZq3r2. ACCEPT 6119797431 on this card is the review record.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:devxpriority:p1High: required for production / M2target:v18tooling

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions