Skip to content

fix(release): stop asserting one repo's CI shape as permanent fact in gate 1 - #1385

Merged
fdaviddpt merged 2 commits into
mainfrom
fix/1375
Sep 9, 2026
Merged

fix(release): stop asserting one repo's CI shape as permanent fact in gate 1#1385
fdaviddpt merged 2 commits into
mainfrom
fix/1375

Conversation

@fdaviddpt

Copy link
Copy Markdown
Contributor

Closes #1375.
Gate 1 in commands/release.md stated, as settled fact, that this repository is one instance of exactly that shape -- describing claude-oss's own CI setup (a reduced push matrix, full coverage reserved for a workflow_dispatch input, #1246) as though every managed repo shared it, inside a document every managed repo's release reads identically.
Read against a different real repo (claude-supertool at commit c5e3044), whose push trigger already runs the full matrix and defines no such workflow_dispatch input, that assertion is simply false there. A releaser following the gate literally, plus the post-push CI-wait section's (#1266/#1324) own unconditional dispatch instruction, waits forever (PENDING) on a dispatched run that will never appear. This is exactly the class CLAUDE.md's own governing rule names: a fact about one repository must never live in shared code.
What changed

  1. Gate 1: removed the hardcoded claim. Reworded so the reduced/full split is derived per repo (grep .github/workflows/*.yml at release time), never asserted as fact for one named repo.
  2. Post-push CI-wait section: reworked the same way, plus closed a real functional gap the derivation instruction alone left open -- a repo without the wider dispatch shape now waits on its own plain push-triggered run before tagging, rather than either spinning forever or skipping the wait outright.
  3. New test tests/test_release_gate1_repo_specific_1375.py: red before the fix (the hardcoded phrase matched, via a whitespace-tolerant regex since it wraps across a markdown line break), green after. No existing test covered commands/*.md for repo-specific facts -- confirmed by reading test_content_invariants.py directly (COMMANDS is not in its _fact_bearing_documents() sweep).
  4. changelog.d/1375.fixed.md.
    Self-review
    Two rounds. Round 1 (Explore + oss:auditor against commit de3fa2b) found two real problems in that commit: the new skip-this-section wording was scoped too broadly (it could be read as skipping the CI wait and tag-creation step themselves, reproducing the v0.27.0 tag-before-CI regression on exactly the repo shape this fix names as its own example), and the second test asserted substrings that already existed, verbatim, in the file's unchanged part -- so it proved nothing about the actual diff. Both fixed in commit d9fd6fe. Since that fix touched 3 files, scripts/fix_commit_scope.py returned needs-second-pass, so a lighter round 2 ran over the fix commit alone (Explore + oss:auditor again): NO FINDINGS from both, verified by hand against both the pre-fix and post-fix file content.
    Full reviewer exchange and by-hand verification transcripts are in the developer report's note file.
    Pushback / judgment call
    The issue named the post-push section as presumably needing the same treatment and left it to my judgment how much surrounding text to adjust. It needed more than a wording tweak: the original unconditional instruction had no defined behavior for a repo that genuinely lacks the wider workflow_dispatch shape (the exact claude-supertool case the issue raises), so I added a parallel plain-wait path rather than only softening the prose. This is a slightly larger change than delete one sentence but the round-1 self-review confirmed it was necessary -- the narrower fix left a real regression risk on the shape the issue is about.
    🤖 Generated with Claude Code
    https://claude.ai/code/session_01QYm4rkixzFWu3MXm2r9hhG

[AI-generated]

fdaviddpt and others added 2 commits September 9, 2026 21:44
…in gate 1

Gate 1 in commands/release.md stated, as settled fact, that "this
repository is one instance of exactly that shape" (a reduced push
matrix, full coverage reserved for a `workflow_dispatch` input,
#1246) -- inside a document every managed repo release reads
identically. Read against claude-supertool at commit c5e3044, whose
push trigger already runs the full matrix and defines no such
workflow_dispatch input, that assertion is simply false there, and a
releaser following the gate literally waits forever on a dispatched
run that will never appear (release_ci_wait.py's PENDING state,
spun with --require-event workflow_dispatch and nothing to satisfy
it).

Gate 1 now frames the reduced/full split as something to derive per
repo -- by reading that repo own .github/workflows/*.yml at release
time -- rather than a fact asserted for one named repo, per
CLAUDE.md own governing rule: a fact about one repository must never
live in shared code. The post-push CI-wait section (#1266, #1324)
carried the same unconditional assumption in its own worked example
and additionally never stated what to do when a repo genuinely lacks
this shape; it now says explicitly to skip the second dispatch
entirely when the push trigger already runs full coverage, closing
the gap that produced the eternal-PENDING failure mode.

Added tests/test_release_gate1_repo_specific_1375.py: red before the
fix (the hardcoded phrase matched), green after (removed, while the
per-repo derivation instruction is still present). No existing test
covered commands/*.md for repo-specific claims --
test_content_invariants.py's HARDCODED sweep only reaches
skills/agents/phase files, not commands/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYm4rkixzFWu3MXm2r9hhG
…t itself

Two findings from the Explore self-review spawn against de3fa2b:

1. The post-push section's new "skip the rest of this section entirely"
   instruction, on a repo whose push trigger already runs full coverage,
   scoped too broadly: "this section" also holds the
   `--require-event workflow_dispatch` wait's exit-code handling and the
   tag-creation step itself. Following the instruction literally either
   tags with no CI wait on the release commit at all (reproducing the
   v0.27.0 regression on exactly the repo shape this fix names as its own
   motivating example), or strands the tag-creation steps with nothing
   left to trigger them. Fixed: the skip is now scoped to only the
   dispatch step and its --require-event wait -- the paragraph above still
   applies unconditionally, and a repo without the wider shape now waits
   on the plain push-triggered run (`release_ci_wait.py --commit
   "$COMMIT_SHA" --wait`, no --require-event) before proceeding to the
   same tag-creation step.

2. tests/test_release_gate1_repo_specific_1375.py's second test asserted
   two substrings that already existed, verbatim, in the *other* paragraph
   (the post-push section) before this fix -- so it passed on the pre-fix
   file too and exercised nothing about the actual change. Fixed: the test
   now isolates gate 1's own paragraph (anchored on the phrase "does not
   satisfy this gate", asserted unique in the file) and checks the
   derivation instruction within it specifically. Verified this version is
   red against the pre-fix file (the "never something to assume here"
   phrasing is absent there) and green against the current file.

Both reviewers classified with scripts/review_return.py: the Explore spawn
as states-findings (2 findings, both handled above), oss:auditor as
no-findings (0 findings; checked absence/guard/injection/platform classes,
none applicable to a prose-only change).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYm4rkixzFWu3MXm2r9hhG
@fdaviddpt
fdaviddpt merged commit e06f9af into main Sep 9, 2026
10 checks passed
@fdaviddpt
fdaviddpt deleted the fix/1375 branch September 9, 2026 20:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

release gate 1 asserts claude-supertool reserves coverage behind a full_matrix dispatch; it does not

1 participant