Skip to content

fix(ci): changeset-guard.yml now exercises its own PR - #6398

Merged
os-warren merged 2 commits into
mainfrom
claude/issue-6321-gate-self-coverage
Aug 25, 2026
Merged

fix(ci): changeset-guard.yml now exercises its own PR#6398
os-warren merged 2 commits into
mainfrom
claude/issue-6321-gate-self-coverage

Conversation

@os-warren

@os-warrenos-warren commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Fixes#6321

Conclusion: oversight, not deliberate

changeset-guard.yml's paths: filter was .changeset/** alone, on both its pull_request and push triggers. Nothing in the file, its history, or the linked cards (#6245 / PR #6315) recorded a reason for excluding the gate's own YAML or the script its one step runs. Measured against the repo's other six path-filtered workflows, 5 of 7 self-include; changeset-guard.yml and performance-budget.yml (closed in #6315) were the two exceptions. No defensible reason was found in the file for changeset-guard.yml to be the third — this is the oversight branch.

Filter — before / after

Before (pull_request and push, identical):

paths:
- '.changeset/**'

After (both triggers):

paths:
- '.changeset/**'
- '.github/workflows/changeset-guard.yml'
- 'scripts/check-changeset-no-major.mjs'

The ~ partial judgement

Two things were deliberately not added, and the reasoning is recorded in the workflow's own header comment (not just this PR body):

  • scripts/invoked-as.mjs (the gate script's one import) — this repo's majority pattern for a self-including, script-running gate is "list what the run: step executes" (own YAML + the invoked script), not the transitive import graph. node-esm-load-gate.yml, published-dist-gate.yml and spec-range-floors.yml all import this exact same shared helper (isEntrypoint, 40+ importers under scripts/) and none of them lists it. Only half-state-patrol.yml does, and its own header names that as a specific, documented one-off tied to its objectstack port (Install the parameterised half-state patrol (sweeper + workflow pair from objectstack PR #11294) #5791/divergence 2), not a general convention. Adding it here would make changeset-guard.yml the outlier relative to the other three comparable gates, not the convention-follower.
  • scripts/__tests__/check-changeset-no-major.test.ts — this matches the looser ~ partial patternpublished-dist-gate.yml and spec-range-floors.yml already set for their own gate scripts' __tests__ files, not the stricter closure pattern. Verified directly: the file lives under scripts/**, which ci.yml/lint.yml's Decide whether this change needs a full run step does not exclude (only **/*.md and .changeset/** are excluded), so any PR touching the script or its test already gets a real run of the root vitest suite that executes it — the same reasoning the two ~ partial rows rely on. Confirmed both files run under scripts/**/*.test.ts in vitest.config.mts's root project.

So changeset-guard.yml now matches the ~ partial pattern (own YAML + invoked script, not the full transitive closure), same tier as published-dist-gate.yml / spec-range-floors.yml.

Self-coverage confirmed on this PR — READ, not reasoned about

This PR's diff includes .github/workflows/changeset-guard.yml itself. Pulled the check list via get_check_runs after pushing:

"Changeset Bump Policy"status: in_progress, run https://github.com/objectstack-ai/objectui/actions/runs/32892473021/job/97947347455

The gate is present and running on this PR, which is exactly the self-coverage #6321 asked for. (PR #6315 asserted this same thing and turned out wrong because a paths: filter excluded it — this time the check list was actually read.)

Docs updated to match

content/docs/guide/ci-cd-pipeline.md:

  • Workflow Inventory table row for changeset-guard.yml.
  • The path-filter bullet under "The path filters explain most…".
  • The "Some contexts can never be required, structurally" bullet — this one is machine-pinned verbatim by scripts/__tests__/ci-cd-pipeline-doc.test.ts (STRUCTURAL_BLOCKS['changeset-guard.yml'].quotes() reads the live paths: values out of the YAML and requires the doc line to quote all of them); updated and reverified green.
  • The dedicated ### Changeset Guard section.

No conflict with PR #6389 (content/docs/guide/ci-cd-pipeline.md) was hit — my worktree was created after #6389 already landed on main (commit b362c1b47), so this branches from the current file, not a stale copy.

Out of scope (per the triage ruling)

The 22 workflows with no paths: filter at all — they report on every PR, so this gap cannot arise for them.

Tests run

  • pnpm exec vitest run scripts/__tests__/check-changeset-no-major.test.ts scripts/__tests__/check-changeset-presence.test.ts scripts/__tests__/ci-cd-pipeline-doc.test.ts scripts/__tests__/check-pre-install-import-graph.test.ts112 passed, including the pinned regex in check-changeset-no-major.test.ts (.changeset/** still the first paths: entry) and every STRUCTURAL_BLOCKS['changeset-guard.yml'] assertion in ci-cd-pipeline-doc.test.ts.
  • node scripts/check-changeset-no-major.mjs → ✅ no major bump declared.
  • node scripts/check-changeset-presence.mjs → ✅ (this change touches no published package src/; changeset added anyway per dispatch).
  • node scripts/check-doc-links.mjs → ✅ links valid across 17 scan roots.
  • node scripts/check-control-bytes.mjs → ✅.
  • node scripts/check-entry-guard.mjs → ✅ (unaffected, ran as a cheap sanity check since scripts/** was touched).
  • Parsed the updated changeset-guard.yml with yaml.parse to confirm both pull_request.paths and push.paths are syntactically valid and contain the three expected entries.
  • get_check_runs on this PR (see above) — Changeset Bump Policy present and running.

Changeset

.changeset/6321-changeset-guard-self-coverage.md — internal CI/docs-only change, no published package touched.


Generated by Claude Code

The gate's `paths:` filter was `.changeset/**` alone, so it was one of two
exceptions to the repo's 5-of-7 self-inclusion convention for path-filtered
gates: a PR editing the gate's own YAML or the script it runs
(`scripts/check-changeset-no-major.mjs`) never triggered the gate itself —
the first real run landed on someone else's unrelated `.changeset/**` PR.
Add the workflow's own path and the invoked script to both the
`pull_request` and `push` `paths:` lists, matching the majority pattern set
by `node-esm-load-gate.yml`, `published-dist-gate.yml` and
`spec-range-floors.yml` (own YAML + the script the `run:` step executes).
Deliberately NOT added: `scripts/invoked-as.mjs` (a 40+-importer shared
utility that those same three gates import without listing — only
`half-state-patrol.yml` lists it, as a documented one-off) and
`scripts/__tests__/check-changeset-no-major.test.ts` (already covered by the
root vitest suite on any PR touching `scripts/**`, the same `~ partial`
reasoning `published-dist-gate.yml`/`spec-range-floors.yml` apply to their
own gate scripts' `__tests__` files). Both calls are recorded in the
workflow's own header comment.
`content/docs/guide/ci-cd-pipeline.md` updated to match: the inventory table
row, the path-filter bullet, the "contexts that can never be required"
structural claim (pinned verbatim by
`scripts/__tests__/ci-cd-pipeline-doc.test.ts`), and the dedicated
Changeset Guard section.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CZgmFFzqA9cX8tBMhvpFe
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants

@os-warren@claude