Repository navigation
finding(gates): check-empty-changeset and Check Changeset route 2 still say a skills/**-only PR releases nothing, so it passes with no changeset; since #22658 @objectstack/skills publishes skills/** #23451
Description
Filing gate ①, class (b): one rule, two texts that disagree. AGENTS.md's post-task checklist (AGENTS.md:1085 on origin/main 61b12584f) gives a skills/** change a patch changeset, "never skip-changeset". The changeset gate still teaches the opposite, from before @objectstack/skills existed:
scripts/check-empty-changeset.mjs:513, in the remedy it prints: "It releases nothing (.github/, .claude/, skills/, docs/, content/, examples/, …".- The same file's self-test
GREEN 3: a skills/**-only PR carrying NO changeset (route 2)(:913-923) asserts that such a PR "must be green here". .github/workflows/pr-automation.ymlroute 2's prose rests on the same premise.
Since #22658 (ruling A on #22649), packages/skills publishes skills/** (files: [dist, README.md, CHANGELOG.md], built by scripts/sync-catalog.mjs, version 18.0.0-next.0, in the fixed group). So a skills/**-only PR with no changeset ships text that the @objectstack/skills CHANGELOG never mentions.
reach: a named instance. PR #23443 (card #23268) deletes a row of skills/objectstack-data/references/lint-rules.md. The seat labelled it skip-changeset on the reading "docs/governed text only, no package", and Check Changeset reported skipped on head ce509e82c. Only the contract review caught it (record on PR #23443, ②). The label was removed and a patch changeset is being added; the gate itself would have passed the PR.
Filed by domain:spec seat 3 (#18883) · baozhoutao · session session_01D6F9axfoPzR7t8G1J7Ytzz, at PR #23443's review. ⛔ Not a claim; grading and routing are triage's.
Reader who acts: the seat that owns the changeset gate (scripts/check-empty-changeset.mjs, .github/workflows/pr-automation.yml); triage routes it. The fix aligns the gate's route-2 text and its GREEN 3 fixture with AGENTS.md (a skills/** change owes a @objectstack/skills changeset). Whether the gate should also refuse a skills/** diff carrying no changeset is that seat's call; it changes no other route.
Re-check
git grep -n "skills/" origin/main -- scripts/check-empty-changeset.mjs→ the remedy line (:513) and theGREEN 3battery (:913-923).- Control:
git show origin/main:packages/skills/package.json→"files": ["dist", "README.md", "CHANGELOG.md"], and the build issync-catalog.mjs.
Dedupe
MCP search_issues on this repo, closed included:
check-empty-changeset skills only PR no changeset green @objectstack/skills published route 2 stale→ 0 hits.skills changeset skip-changeset published skills package CHANGELOG→ 40 hits. The top ten are adjacent and closed: [Ruling A on #22649] @objectstack/skills: the published skills catalog ships as a versioned package in the fixed group — the build copies skills/** in and files lists only it; the compatibility line and metadata.version derive from the package version #22658 / [Decision] bind the published skills catalog to the ObjectStack version it teaches: ship skills/** as a versioned package beside @objectstack/spec (A), pin a git ref per release (B), warn on mismatch (C), or keep serving main #22649 / [Ruling A on #22649] docs: the skills install command reads the catalog from the installed @objectstack/skills package; the GitHub path is documented as the next (unreleased main) channel only #22668 (the package's ruling and docs), skills(objectstack-upgrade, catalog READMEs): the upgrade playbook gains the 17→18 skills step and the two READMEs teach the scaffolder's pinned --copy sync (ruling A on #22649, second pass) #23276, docs(skills install): the end state after create-objectstack installs @objectstack/skills — one pinned spelling with --copy, one next.0 exception, and the 17→18 skills step in the upgrade guide (ruling A on #22649, second docs pass) #23275, docs: the skills sync is taught without--copy, so a project that commits its skills hands every clone dangling links into the gitignorednode_modules#23251, Delete the published skills/objectstack-pm-dispatch skill — a stale three-state copy of the internal PM protocol with no known consumer, shipped into every new app — and retire its catalog row, docs page, frame-sync copy, tier-table entry, ratchet pins and gate fixtures (maintainer ruling 2026-09-10) #17311, skills/README.md truth + routing sweep:OLD/NEW"evaluate tonullsince M9.5" is anchored nowhere and contradicts the formula skill; "AI tool params" is not a CEL site; the cross-skill routing list lacks the upgrade-vs-platform and objectui inbound decision points #14794, release(v18): the version pass now rewritesskills/*/SKILL.md(PR #22692'scheck-skill-compatibility-version.mjs --fix) outside the declared post-version surface, soValidate the post-version treerefuses and #21988 cannot refresh to18.0.0-next.0#22970, release(next): #21988 reds on the skills token ratchet at 18.0.0-next.0 (the prerelease version stamp adds 7 bytes to two SKILL.md files with 0 and 1 token of headroom) #23176. None is this gate.
Dedupe words: check-empty-changeset route 2 skills/** stale premise; GREEN 3 skills-only no changeset; @objectstack/skills changeset owed.
Generated by Claude Code
Activity
objectstack-fleet commentedon Oct 14, 2026
Triage: first grade ·
tooling·priority:p3·domain:devx·area:devpath·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-14T09:55ZRead fresh. On
main61b12584f,scripts/check-empty-changeset.mjs:513still prints "It releases nothing (… skills/ …)". AGENTS.md's checklist gives askills/**change apatchchangeset.@objectstack/skills, which publishesskills/**since [Ruling A on #22649] @objectstack/skills: the published skills catalog ships as a versioned package in the fixed group — the build copies skills/** in and files lists only it; the compatibility line and metadata.version derive from the package version #22658) and a measured instance (PR docs(adr): ADR-0090 D11 — external visibility is the EXTERNAL rung; externalSharingModel retired (#23268) #23443).priority:p3: AGENTS.md already states the rule, and the contract review caught the one instance. The gate text misleads, but nothing has shipped wrong.domain:devx(the changeset gate andpr-automation.yml).GREEN 3fixture with AGENTS.md.skills/**diff with no changeset is a new gate behaviour. The maintainer's standing rule is 「新增门禁默认否」, so that half needs the maintainer's word; ⛔ the text fix does not add it.findingleaves on grading.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 2
Session:
session_012VGBku7tEi8DX2uvi1gtXkAccount:
os-support-ai(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23451-skills-changeset-route2Worktree:
objectstack-issue-23451Domain:
domain:devxSeat:
domain:devx#1File surface: at
origin/main2d2e3ce43, read 2026-10-14T10:00Z.scripts/check-empty-changeset.mjs: the route-2 remedy text (:513), theGREEN 3battery (:913-923) and its roster row (:679), and any header sentence that assertsskills/**releases nothing..github/workflows/pr-automation.yml: the route-2 prose (:795-817) and any::error::line that repeats the premise. Text and fixture rationale only; ⛔ no change to what either gate passes or refuses. Stop on breach; explain it in the report.Container & model:
Sjudged asM(text-only, but which sentences are false is a judgment),mode:subagent,model: default(dispatch-gates --tier --repo objectstack-ai/objectstackat2d2e3ce43: "no path-derived mandate … floor sonnet · default opus · ceiling fable"). The governed-text contract review runs atTIER_DEFAULTon the maintainer's order6162674390(this session), neverCONTRACT_REVIEW_TIER.Clause-②: no
Responsibility:
scripts/check-empty-changeset.mjsand.github/workflows/pr-automation.ymlroute 2 produce the risk (their text predates@objectstack/skills) | AGENTS.md's post-task checklist (AGENTS.md:1085) already states the rule, and the contract review caught the one instance | any seat or dev that labels askills/**-only PRskip-changeseton the gate's word reaches it; the named instance is PR #23443, which is now correctedThread-read: 6165705508
Serial constraints cleared: no open PR (all 14 open PRs' file lists read 2026-10-14T10:00Z) and no live claim (21
pm:dispatchedcards' newestClaim:read) names either file. No same-day commit touches either file onorigin/main.Order (maintainer, this seat's session
session_012VGBku7tEi8DX2uvi1gtXk, verbatim): 「23451 派发」. This is a direct dispatch, so it supersedes the session's p1-only order for this card.Landing path: the diff touches
.github/workflows/**, a governed surface, so Tier H. One PR carries both files. It stays draft, and on ACCEPT the seat posts the maintainer quick-read and requests the two authorised reviewers. The new-refusal half stays out, per triage6165705508(「新增门禁默认否」).Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23451, "status": "done", "branch": "claude/issue-23451-skills-changeset-route2", "pr": "https://github.com/objectstack-ai/objectstack/pull/23457", "session": "session_012VGBku7tEi8DX2uvi1gtXk", "premise_still_valid": true, "summary": "Rewrote every false sentence that told an author a skills/** change releases nothing. Four sites: route 2's list and its skills paragraph in pr-automation.yml, the route-2 ::error:: line, and the remedy and GREEN 3 rationale in check-empty-changeset.mjs. Each now says skills/** ships in @objectstack/skills and owes a changeset naming it, never the label. Neither gate's pass/refuse behaviour changed: the Check Changeset verdict step is path-blind, and check-empty-changeset reads only .changeset rows. Premise measured on 2d2e3ce43. packages/skills files is [dist, README.md, CHANGELOG.md], and sync-catalog.mjs copies every regular file under skills/ into dist/skills/ with no exclusions; the package is in the changeset fixed group. Two refinements to the card: (1) AGENTS.md:1085 states the GENERAL rule (bug fix in a released package takes patch; the skip-changeset label is only for a diff that publishes nothing from any released package) and names no skills/** case, so the new texts say 'a changeset naming @objectstack/skills' and fix no bump level. (2) 'so it passes with no changeset' holds only through the label route 2 prescribed: with no changeset and no label, the verdict step reds a skills-only PR. Draft PR #23457 is Tier H (.github/workflows/**), with skip-changeset landed and read back, and the worktree cleaned. Attribution: commit trailers use AGENTS.md's model-free pair (Claude-Session + Co-authored-by: Claude), and the PR footer uses AGENTS.md's session-URL form; the harness reminder's model-named trailer and its emoji footer were not used, because AGENTS.md takes precedence.", "tests": "All at head 7463fab7c. (a) node scripts/check-empty-changeset.mjs --self-test exit 0: '✓ check-empty-changeset --self-test: 170 assertions over real temp git repos (real scan() path)'. (b) Ablation, run once, fix committed first, via scripts/ablation-replace.mjs (no build/dist: a root script run directly). The battery() call was reverted to the old '(route 2)' name with the roster kept at the new name. Anchor 1 -> 0, blob c0df1afc9232 -> ffdbc962df0e. Self-test exit 1: 'registered 2 case(s) but is not declared in SELF_TEST_BATTERIES' and '...nothing to judge DID NOT RUN — 0 cases registered, 2 pinned' (direction: red, as predicted). Restore: blob c0df1afc9232 == HEAD, git diff HEAD empty, git status --porcelain 0 lines. (c) The consumer pin (::error::This PR adds no changeset reaches exit 1 within 900 chars) measures 730 chars after the edit (698 before); the workflow YAML parses (yaml 2.9.1). (d) Gates: dispatch-gates --commands --repo objectstack-ai/objectstack vs merge base 2d2e3ce43 derived 53 commands, and all 53 exited 0 (see gates.results). --ran: '✓ dispatch-gates --ran: 53 derived famil(ies) accounted for — 53 run, 0 NOT-MEASURED (a DERIVED zero — all 53 recorded an exit code and none of them is 3)'. check:pm-dispatch-gates: '✓ dispatch-gates self-test (fast tier): 1841 cases pass', exit 0 on its second run. (e) Lint, proven narrowing: eslint --no-inline-config --format json over both files returned 2 results. scripts/check-empty-changeset.mjs had 0 errors / 0 warnings; pr-automation.yml was 'File ignored because no matching configuration was supplied' (outside eslint's own population). eslint.config.mjs enables no type-aware linting (0 parserOptions.project; stated at its line 327), so the diff cannot move any untouched file's verdict. NOT MEASURED, left to CI per the derivation: 7 workflow-valued families, Test Core job steps, 4 type-check lanes (no TypeScript touched). CI at 10:29Z: 10 success, 11 skipped, 19 in_progress, 0 failure (in_progress, not polled).", "mcp_calls": "0 — no MCP GitHub tool called (reads via gh api REST: card, comments, PR, check-runs, labels)", "api_writes": "3 relay strokes, each one POST /repos/objectstack-ai/objectstack/dispatches from this session, executed as objectstack-fleet[bot]: (1) pr_create: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23457/assignees; (2) label-write labels_add: POST /repos/objectstack-ai/objectstack/issues/23457/labels (skip-changeset); (3) comment: POST /repos/objectstack-ai/objectstack/issues/23451/comments (this report). Plus 2 git push to claude/issue-23451-skills-changeset-route2 (not REST).", "files_changed": [ ".github/workflows/pr-automation.yml", "scripts/check-empty-changeset.mjs" ], "sites": [ { "site": "scripts/check-empty-changeset.mjs:513 (base) remedy 'It releases nothing (.github/, .claude/, skills/, ...'", "verdict": "false", "rewrite": "skills/ dropped from the list; the 'It releases something' bullet reads '-- a skills/** change does: it ships in @objectstack/skills'" }, { "site": "scripts/check-empty-changeset.mjs:913-916 GREEN 3 comment + battery() name ('Such a PR takes the skip-changeset label', '(route 2)')", "verdict": "false", "rewrite": "renamed 'GREEN 3: a skills/**-only PR carrying NO changeset: nothing to judge'; comment: this gate reads only the .changeset rows a diff touches, so it stays silent; the PR still owes a changeset naming @objectstack/skills (AGENTS.md post-task checklist), never the label; asking for it is the Require a changeset step's job, a wrong label is review's catch" }, { "site": "scripts/check-empty-changeset.mjs:679 roster row", "verdict": "follows the rename", "rewrite": "renamed in lockstep with battery(); the floor keys on the name (ablation in tests)" }, { "site": "scripts/check-empty-changeset.mjs:921-922 GREEN 3 assertion messages", "verdict": "true", "rewrite": "unchanged" }, { "site": "scripts/check-empty-changeset.mjs:67 header narrative (skills/** precedent chain #4607/#5130/#5451 -> PR #5799)", "verdict": "true (history)", "rewrite": "unchanged" }, { "site": "scripts/check-empty-changeset.mjs:866-872 RED 1 (#5799 shape: skills/** change + new empty changeset)", "verdict": "true (still refused, still the gate's case)", "rewrite": "unchanged" }, { "site": ".github/workflows/pr-automation.yml:795 route 2 'releases nothing' list", "verdict": "false", "rewrite": "skills/ dropped" }, { "site": ".github/workflows/pr-automation.yml:812-820 route 2 skills/** paragraph ('skills/ ships with no npm package ... That premise is true ... Take the label.')", "verdict": "false", "rewrite": "skills/** is NOT on that list: it ships in @objectstack/skills (its build copies it into the dist its files field publishes); a skills/** change releases that package -- route 1, naming @objectstack/skills, never the label; the old premise is no longer true" }, { "site": ".github/workflows/pr-automation.yml:842 ::error:: ('including any skills/** change -- see #5947')", "verdict": "false", "rewrite": "'Otherwise, if it releases nothing, apply the skip-changeset label; otherwise run pnpm changeset and name the packages (a skills/** change releases @objectstack/skills and never takes the label).' Prefix ::error::This PR adds no changeset. kept (pinned by check-changeset-no-major)" }, { "site": ".github/workflows/pr-automation.yml:846-852 step comment on the skills/** precedent chain", "verdict": "true (history)", "rewrite": "unchanged" } ], "gates": { "head": "7463fab7c", "merge_base": "2d2e3ce43", "derived": 53, "ran": 53, "not_measured": 0, "unrun": 0, "nonzero": [], "results": [ "node scripts/check-aggregator-roster.mjs :: exit 0", "node scripts/check-aggregator-roster.mjs --self-test :: exit 0", "node scripts/check-ci-filter-parity.mjs :: exit 0", "node scripts/check-closing-keyword-parity.mjs :: exit 0", "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0", "node scripts/check-comment-mask-corpus.mjs :: exit 0", "node scripts/check-declaration-mirrors.mjs :: exit 0", "node scripts/check-declaration-mirrors.mjs --self-test :: exit 0", "node scripts/check-empty-changeset.mjs --base origin/main :: exit 0", "node scripts/check-empty-changeset.mjs --self-test :: exit 0", "node scripts/check-position-name-fold-loaders.mjs :: exit 0", "node scripts/check-position-name-fold-loaders.mjs --self-test :: exit 0", "node scripts/check-scripts-symbol-anchors.mjs :: exit 0", "node scripts/check-scripts-symbol-anchors.mjs --self-test :: exit 0", "node scripts/check-self-test-wired.mjs :: exit 0", "node scripts/check-self-test-wired.mjs --self-test :: exit 0", "node scripts/check-self-test-workflow-commands.mjs :: exit 0", "node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0", "node scripts/check-step-collectors.mjs :: exit 0", "node scripts/check-step-collectors.mjs --self-test :: exit 0", "node scripts/check-whole-set-label-write.mjs :: exit 0", "node scripts/check-whole-set-label-write.mjs --self-test :: exit 0", "node scripts/docs-audit/check-drift-comment.mjs :: exit 0", "node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0", "node scripts/pm/ci-failure.mjs --self-test :: exit 0", "pnpm check:agent-test-spelling :: exit 0", "pnpm check:bash32-floor :: exit 0", "pnpm check:changeset-gate-self-tests :: exit 0", "pnpm check:cli-command-ids :: exit 0", "pnpm check:cross-package-test-inputs :: exit 0", "pnpm check:declared-population-live :: exit 0", "pnpm check:driver-memory-census :: exit 0", "pnpm check:entry-guard :: exit 0", "pnpm check:gitlink-declared :: exit 0", "pnpm check:node-version :: exit 0", "pnpm check:nul-bytes :: exit 0", "pnpm check:parse-guard :: exit 0", "pnpm check:pm-expected-skips :: exit 0", "pnpm check:pm-governed-merges :: exit 0", "pnpm check:pm-post-stamped :: exit 0", "pnpm check:pm-record-recognisers :: exit 0", "pnpm check:pnpm-acquisition :: exit 0", "pnpm check:pnpm-filter-targets :: exit 0", "pnpm check:ratchet-remedy-authority :: exit 0", "pnpm check:refd-timer-probe :: exit 0", "pnpm check:required-contexts :: exit 0", "pnpm check:shard-attestation :: exit 0", "pnpm check:stall-guard-budget :: exit 0", "pnpm check:stall-guard-headroom :: exit 0", "pnpm check:watch-hint-literal :: exit 0", "pnpm check:workflow-status-functions :: exit 0", "pnpm check:workflow-step-name-quoting :: exit 0", "pnpm check:pm-dispatch-gates :: exit 0" ] }, "changeset": "none; skip-changeset label landed via label-write and read back at 10:29Z (ci/cd, size/s, skip-changeset). Measured: 72 non-private package.json, 0 files entries leave their package dir; git grep for either file under packages/ (CHANGELOGs excluded) 0 hits, control sync-catalog hits", "clause2": "no (copied from claim 6165808357 into PR body line 3)", "landing": "Tier H (.github/workflows/**), draft, assignee os-support-ai; maintainer quick-read section in body with 席位意见 left empty", "cleanup": "worktree ../objectstack-issue-23451 removed after rm -rf node_modules (no --force needed; branch head == origin at 7463fab7c before removal); no background process left", "deviations": [ "check:pm-dispatch-gates first run was started under nohup without capturing its exit status (its log printed the pass verdict); re-ran with capture, exit 0, and that code is the one recorded in --ran.", "Dispatch prompt framed the rule as 'a skills/** change gets a patch changeset for @objectstack/skills'; AGENTS.md:1085 states only the general rule, so the rewritten texts name the package and fix no bump level (route 1's level rules apply)." ], "open_questions": [], "out_of_scope_findings": [ "carrier: 承接者:无 · route 2's closing tie-break 'If you are unsure between routes 1 and 2, take route 2' left unchanged (general guidance, not skills/**-specific; no measured instance of it misleading) · in PR #23457 Acceptance notes only, noted, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
ACCEPT · PR #23457 ·
domain:devxseat 1 ·session_012VGBku7tEi8DX2uvi1gtXk· 2026-10-14T10:47Z. Seat check6166582837; contract review PASS6166565290atTIER_DEFAULT; maintainer quick-read6166594536. Tier H (.github/workflows/**): the PR stays draft withneeds-user-decision, and review is requested fromos-zhuangandhotlong. It lands after an authorized APPROVED review.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed · PR #23457 ·
domain:devxseat 1 ·session_012VGBku7tEi8DX2uvi1gtXk· 2026-10-14T11:09Z8d5b7bb94, afteros-zhuang's APPROVED review on7463fab7corigin/main8d5b7bb94is an ancestor oforigin/main;scripts/check-empty-changeset.mjsonmaincarries "a skills/** change does: it ships in @objectstack/skills"; queue branchgh-readonly-queue/main/pr-23457-*goneState: closed
completedbyFixes #23451;pm:dispatchedremoved in this landing act. The only issue closed since 11:00Z is this card.Generated by Claude Code