Skip to content

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

Closed

Description

@objectstack-fleet

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.yml route 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 the GREEN 3 battery (:913-923).
  • Control: git show origin/main:packages/skills/package.json → "files": ["dist", "README.md", "CHANGELOG.md"], and the build is sync-catalog.mjs.

Dedupe

MCP search_issues on this repo, closed included:

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

  1. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade · tooling · priority:p3 · domain:devx · area:devpath · pm:queue · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-14T09:55Z

    Read fresh. On main 61b12584f, scripts/check-empty-changeset.mjs:513 still prints "It releases nothing (… skills/ …)". AGENTS.md's checklist gives a skills/** change a patch changeset.

  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_012VGBku7tEi8DX2uvi1gtXk
    Account: os-support-ai (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23451-skills-changeset-route2
    Worktree: objectstack-issue-23451
    Domain: domain:devx
    Seat: domain:devx#1
    File surface: at origin/main 2d2e3ce43, read 2026-10-14T10:00Z. scripts/check-empty-changeset.mjs: the route-2 remedy text (:513), the GREEN 3 battery (:913-923) and its roster row (:679), and any header sentence that asserts skills/** 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: S judged as M (text-only, but which sentences are false is a judgment), mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/objectstack at 2d2e3ce43: "no path-derived mandate … floor sonnet · default opus · ceiling fable"). The governed-text contract review runs at TIER_DEFAULT on the maintainer's order 6162674390 (this session), never CONTRACT_REVIEW_TIER.
    Clause-②: no
    Responsibility: scripts/check-empty-changeset.mjs and .github/workflows/pr-automation.yml route 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 a skills/**-only PR skip-changeset on the gate's word reaches it; the named instance is PR #23443, which is now corrected
    Thread-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:dispatched cards' newest Claim: read) names either file. No same-day commit touches either file on origin/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 triage 6165705508 (「新增门禁默认否」).


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT · PR #23457 · domain:devx seat 1 · session_012VGBku7tEi8DX2uvi1gtXk · 2026-10-14T10:47Z. Seat check 6166582837; contract review PASS 6166565290 at TIER_DEFAULT; maintainer quick-read 6166594536. Tier H (.github/workflows/**): the PR stays draft with needs-user-decision, and review is requested from os-zhuang and hotlong. It lands after an authorized APPROVED review.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23457 · domain:devx seat 1 · session_012VGBku7tEi8DX2uvi1gtXk · 2026-10-14T11:09Z

    reading value
    PR #23457 merged 2026-10-14T11:08Z through the merge queue as 8d5b7bb94, after os-zhuang's APPROVED review on 7463fab7c
    origin/main 8d5b7bb94 is an ancestor of origin/main; scripts/check-empty-changeset.mjs on main carries "a skills/** change does: it ships in @objectstack/skills"; queue branch gh-readonly-queue/main/pr-23457-* gone

    State: closed completed by Fixes #23451; pm:dispatched removed in this landing act. The only issue closed since 11:00Z is this card.


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions