Skip to content

feat(ci): announce a published nightly on the Version Packages PR - #133

Merged
thecodedrift merged 3 commits into
mainfrom
feat/nightly-region-on-changeset-pr
Aug 21, 2026
Merged

feat(ci): announce a published nightly on the Version Packages PR#133
thecodedrift merged 3 commits into
mainfrom
feat/nightly-region-on-changeset-pr

Conversation

@thecodedrift

Copy link
Copy Markdown
Member

When a nightly publishes, the open changesets "Version Packages" pull request (head changeset-release/main, currently #74) gains a build-info region at the end of its body:

<!-- nightly -->
### Build Info
`npx @taskless/cli-nightly@0.11.0-20260818123456x05b3c88`

**Built from:** 05b3c88
**Built at:** 2026-08-18 12:34:56
<!-- /nightly -->

Those reviewers are exactly the audience for a build of the work the pending changesets describe.

⚠️ One deviation from the issue text — please overrule me if you disagree

The issue writes the install line as npx @taskless/cli@<version>. Nightlies publish under @taskless/cli-nightly (.github/scripts/nightly-pack.cjs, design D2 — the pack rewrites name before packing), and @taskless/cli@0.11.0-20260818123456x05b3c88 does not exist on npm. That line would 404, or at best send a reviewer to the last release.

So the region names @taskless/cli-nightly — the package that will actually install. Everything else matches the issue's format byte for byte. If you want the literal text instead, it is one constant in nightly-breadcrumb.cjs.

How it is built

A third job, breadcrumb, holding pull-requests: write and no credential. The publish job holds an OIDC identity authorized to publish under the @taskless scope; adding pull-requests: write to it would widen what a compromised step there can reach from "publish a package" to "publish a package and rewrite pull request text" — including the text of the PR that gates the next release. Same boundary the file already draws between gate and publish, drawn once more. No id-token, no environment, no contents write beyond checkout-read.

needs: publish is what "block on a successful publish" means mechanically — a job whose dependency was skipped does not run, so a suppressed nightly (either gate false) never reaches it.

The version arrives as a job output, and every fact is parsed back out of it. The stamp is <n.m.k>-<yyyymmddhhmmss>x<sha>, so it already carries the build time and the commit. A fresh Date.now() would print a time that disagrees with the version on the line above it, and a fresh git rev-parse would print a sha the published tarball does not carry. The "stamped exactly once" rule is already load-bearing here (--print-version); this is its third consumer and it obeys it.

No open Version Packages PR exits 0. changeset-release/main exists only while changesets are pending, and a nightly can publish in the seconds before changesets opens it — a cosmetic breadcrumb must never fail a run that already published to npm. That is deliberately not the same branch as a failed API call: gh api is allowed to exit non-zero and fail the step, with no || echo '[]' fallback collapsing the two (the same fail-open closed in gate 2 by task 4.13).

gh api -X PATCH repos/{owner}/{repo}/pulls/<n>, never gh pr edit — its GraphQL path is broken by the Projects (classic) deprecation (CLAUDE.md).

Upsert semantics, and what the tests cover

The region is removed and re-appended at the end rather than replaced in place, so it converges from any starting state. .github/scripts/nightly-breadcrumb.test.cjs (16 tests) covers:

  • repeated publishes replace, never accumulate (one region after N publishes)
  • appends at the end when absent; idempotent for one version
  • a manually deleted region is re-attached
  • a region a human moved mid-body is moved back to the end, not duplicated
  • coexistence with <!-- stack --> — that region is left byte-for-byte alone across two publishes, and a stack region containing the word "nightly" is not mistaken for one
  • a non-array pulls response throws (empty vs. malformed are different answers)

Not reusing stack-breadcrumb.cjs

Its REGION_PATTERN hardcodes the name stack and upsertCarriedRegion is keyed to PR numbers. Neither generalizes to a singleton region under another name, and widening them would make a working, well-tested file serve two callers with different invariants. Fresh zero-dependency helpers in the same style, with a .test.cjs sibling picked up by validate.yml's node --test .github/scripts/*.test.cjs.

Spec

openspec/changes/nightly-cli-builds is still open, so this adds D11 to design.md, task 4.14, and a requirement (A published nightly is announced on the pending release pull request) to the cli-nightly-builds delta.

Verification (all run locally in the worktree)

Command Result
pnpm lint pass (eslint, exit 0)
pnpm typecheck pass (1/1 task; cache hit — no TS changed)
pnpm test pass — 51 files, 630 tests
node --test .github/scripts/*.test.cjs pass — 161 tests, 0 fail (16 new)
pnpm openspec validate --all --strict 24 passed, 0 failed
node .github/scripts/openspec-visibility.cjs every requirement in 23 specs visible

Also smoke-tested the script end to end against fixture pulls.json payloads: an existing region is replaced, an empty list exits 0 with changed=false, and an error object exits 1.

Conflict heads-up

The PR for #127 is being written in parallel and also touches .github/workflows/release-cli-nightly.yml (it changes how the workflow triggers). Edits here are localized — an outputs: block on publish and one appended job — but whichever merges second will need a rebase.

CI-only, no user-facing release note → skip-changeset. Per .github/workflows/changeset.yml the check is advisory now; the label suppresses the warning rather than unblocking a merge.

Fixes #128

Copilot AI lite review requested due to automatic review settings August 21, 2026 04:42
@thecodedrift thecodedrift added the skip-changeset PR intentionally ships no release note (bypasses the changeset requirement) label Aug 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a post-publish nightly build breadcrumb to the pending Version Packages PR.

Changes:

  • Adds a least-privileged breadcrumb workflow job.
  • Implements breadcrumb parsing, rendering, upsert logic, and tests.
  • Updates OpenSpec design, requirements, and tasks.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Summary Review comments
openspec/changes/nightly-cli-builds/tasks.md Adds task 4.14. No final comments.
openspec/changes/nightly-cli-builds/specs/cli-nightly-builds/spec.md Adds announcement requirements and scenarios. No final comments.
openspec/changes/nightly-cli-builds/design.md Documents design D11. No final comments.
.github/workflows/release-cli-nightly.yml Adds the post-publish PR annotation job. Critical: Full-body updates can lose concurrent changes; use re-fetch-and-merge or coordinate writers.
.github/scripts/nightly-breadcrumb.test.cjs Tests parsing, rendering, replacement, and edge cases. No final comments.
.github/scripts/nightly-breadcrumb.cjs Implements version parsing and breadcrumb upsertion. Moderate: Global newline normalization can alter unrelated user-authored content; limit it to removed-region boundaries and add a regression test.
Suppressed comments (3)

.github/scripts/nightly-breadcrumb.cjs:183

  • This helper places the nightly region at the end only for the body it currently receives. If the Version Packages PR also has carried <!-- PR:N --> regions, the existing stack canonicalizer treats <!-- nightly --> as description and appends carried regions after it, so the next stack reconcile/carry moves nightly away from the required final position. Preserve this marker in the shared canonical layout and cover the carried-region case.
function upsertRegion(body, version) {
  const region = renderRegion(version);
  const description = stripRegion(body);
  return description.length === 0 ? region : `${description}\n\n${region}`;

.github/workflows/release-cli-nightly.yml:386

  • The head filter does not constrain the base branch. GitHub permits multiple open PRs from the same head branch to different bases, so a PR from changeset-release/main targeting another branch could be returned and selected for this PATCH instead of the Version Packages PR. Add base=main to the query (or validate pull.base.ref in the selector) before writing.
          gh api "repos/${REPO}/pulls?state=open&head=${OWNER}:changeset-release/main" > nightly-pulls.json

.github/workflows/release-cli-nightly.yml:357

  • This workflow deliberately has no cross-run concurrency, but this job writes the single shared “latest nightly” region. Two pushes can publish concurrently; if the older run reaches this job after the newer run, its PATCH will leave the Version Packages PR pointing at the stale build. needs: publish only orders jobs within one run, so serialize or cancel stale breadcrumb jobs (or reject an older stamped version before writing).
  breadcrumb:
    name: Link the nightly on the Version Packages PR
    needs: publish

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/scripts/nightly-breadcrumb.cjs Outdated
Comment thread .github/workflows/release-cli-nightly.yml
@thecodedrift

Copy link
Copy Markdown
Member Author

Rebased onto main at 423363a (the archived-change main) — no merge commit, history stays linear. Force-pushed with a lease; the single commit is GPG-signed (G).

The nightly-cli-builds change was archived while this was in flight, so the three files I had edited under openspec/changes/nightly-cli-builds/ no longer exist. Git followed the rename and put my edits inside openspec/changes/archive/2026-08-21-nightly-cli-builds/; those are dropped — an archived change is closed and does not get reopened.

The spec content is re-homed accordingly:

  • The requirement (A published nightly is announced on the pending release pull request, five scenarios) now lives directly in openspec/specs/cli-nightly-builds/spec.md, appended after A nightly publish carries the same attestation as a release.
  • Design decision D11 has nowhere to live, so its reasoning is folded into the header comment of .github/workflows/release-cli-nightly.yml, under ANNOUNCING THE NIGHTLY ON THE VERSION PACKAGES PR — why a third job rather than a step in publish, why the version is parsed rather than re-measured, why not stack-breadcrumb.cjs, and why the region names @taskless/cli-nightly and not the issue's literal @taskless/cli. That file is where someone editing this behavior will actually be looking.
  • openspec/specs/vale-binary-packages/spec.md is untouched — the Vale-environment requirement stays withheld pending Finish nightly-cli-builds: move Vale to npm-autopublish and verify the acceptance criteria #131.

The diff against main is now four files: the two new .github/scripts/nightly-breadcrumb*.cjs, the workflow, and the spec. Nothing under openspec/changes/.

Re-verified after the rebase: pnpm lint exit 0 · pnpm typecheck 1/1 · pnpm test 51 files / 630 tests · node --test .github/scripts/*.test.cjs 161 pass, 0 fail · pnpm openspec validate --all --strict 24 passed, 0 failed · openspec-visibility.cjs all requirements in 24 specs visible.

@thecodedrift

Copy link
Copy Markdown
Member Author

@claude /review

@claude

claude Bot commented Aug 21, 2026

Copy link
Copy Markdown

Claude finished @thecodedrift's task in 5m 43s —— View job


Review mode: incremental — read 2 prior review thread(s) before reviewing.

Both prior threads (from copilot-pull-request-reviewer) are still isResolved: false with no addressed-marker reply, so I re-raised both as [Unchanged since last review]:

  • .github/scripts/nightly-breadcrumb.cjs:162 — global newline collapse in stripRegion can alter unrelated user-authored content.
  • .github/workflows/release-cli-nightly.yml:446 — full-body PATCH is a GET-then-write with no re-fetch/merge, vulnerable to lost updates from concurrent writers of the same PR body (changesets bot, stack-breadcrumb.yml).

The prior review also had 3 suppressed (collapsed, non-thread) Copilot comments — lower confidence, never posted as inline threads, so they don't carry isResolved state. I re-examined each against the current code rather than skip them:

  • Missing base check in selectVersionPullRequest — held up, re-raised as [New].
  • No concurrency/staleness protection on the breadcrumb job across separate workflow runs — held up, re-raised as [New].
  • Possible interaction with stack-breadcrumb.cjs's canonical body layout moving the region away from the end — I traced this through `stack-breadcrumb.cjs` (`ownDescription` / `canonicalizeBody`) and confirmed the mechanism concretely: it survives when carried regions are also present. Re-raised as [New] with the trace.

Findings (5 inline comments posted)

  1. [Unchanged] nightly-breadcrumb.cjs:162 — unconditional \n{3,}\n\n collapse whenever any region is/was present, not scoped to the removal seam.
  2. [Unchanged] release-cli-nightly.yml:446 — full-body PATCH from an earlier snapshot; lost-update window against other writers of the same PR body.
  3. [New] nightly-breadcrumb.cjs:205selectVersionPullRequest matches only on head.ref, never base.ref; a second open PR from changeset-release/main to a non-main base could be mis-selected.
  4. [New] release-cli-nightly.yml:399needs: publish only orders jobs within one run; no concurrency group means an older run's breadcrumb job can finish after a newer run's and write stale build info.
  5. [New] nightly-breadcrumb.cjs:183 — if the Version Packages PR carries stack-breadcrumb.cjs `` regions, its next reconcile treats the nightly region as ordinary description and can re-lay it before those carried blocks, breaking the "always at the end" requirement. Not exercised by either test suite.

Everything else — version parsing/rendering, the upsert idempotency, the gh api -X PATCH (not gh pr edit) choice, job permission scoping, the gate/publish/breadcrumb split, and the spec scenarios — reads correctly and matches what the extensive header comments describe. Test coverage for the parts that are tested (16 new tests) is solid.

I did not run lint/typecheck/tests myself — CI (Validate, Changeset) already reports those as green on this PR.
· Branch

Comment thread .github/scripts/nightly-breadcrumb.cjs Outdated
Comment thread .github/workflows/release-cli-nightly.yml
Comment thread .github/scripts/nightly-breadcrumb.cjs
Comment thread .github/workflows/release-cli-nightly.yml
Comment thread .github/scripts/nightly-breadcrumb.cjs
thecodedrift added a commit that referenced this pull request Aug 21, 2026
Copilot review on #133. `stripRegion` collapsed every 3+ newline run in the
body, so an intentional blank-line run anywhere in the description was
rewritten on each republish — content this file does not own.

The removal pattern now eats the newlines around the region and the replacer
decides what belongs there: a blank line between two pieces of prose, nothing
at the top or the bottom of the body. Prose elsewhere is untouched. Two
regression tests cover it, including the republish, which is the path where
the collapse used to fire.

Also documents the lost-update window the same review raised: a PR body is
replaced whole and GitHub offers no compare-and-swap, so the nightly region,
the changesets release notes, and the stack breadcrumb can each overwrite one
another. Accepted rather than coordinated — all three writers are additive and
self-healing, so a lost write costs one cycle, and a lock would couple a
release workflow to a cosmetic breadcrumb.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
@thecodedrift

Copy link
Copy Markdown
Member Author

@claude /review

@claude

claude Bot commented Aug 21, 2026

Copy link
Copy Markdown

Claude finished @thecodedrift's task in 3m 17s —— View job


Review mode: incremental — read 7 prior review thread(s) before reviewing.

Treated as ADDRESSED (not repeated), both closed by commit 8c74d51:

  • .github/scripts/nightly-breadcrumb.cjs — the global \n{3,}\n\n whitespace collapse in stripRegion (2 threads: the original Copilot thread and my earlier [Unchanged] re-raise). Verified in the current code: REGION_SEAM_PATTERN now captures only the newlines immediately adjacent to a region and the replacer decides "" vs "\n\n" based on whether the match sat at the start/end of the body. Two new regression tests (blank lines elsewhere in the description survive a republish, the seam left by a mid-body region becomes exactly one blank line) exercise exactly the case that broke before. This holds up — no bug left here.
  • .github/workflows/release-cli-nightly.yml:468 — the full-body PATCH lost-update window (2 threads, same pattern). Not engineered around (correctly — PR bodies have no compare-and-swap), but now explicitly documented as an accepted risk with real reasoning (all three writers on this PR body are additive/self-healing, so a lost write costs one cycle, not data) in a comment added directly above the step. Marked resolved by the author with the AI-Coding-Agent marker; I agree the tradeoff is reasonable and don't have a stronger alternative to propose.

Still open — re-raised as [Unchanged since last review] (3 inline comments posted), none touched by 8c74d51 (that commit only changed the whitespace-seam logic and added the two documentation comments above):

  1. .github/scripts/nightly-breadcrumb.cjs:214selectVersionPullRequest still matches only pull.head.ref, never pull.base.ref; the workflow's gh api query has no base= filter either. A second open PR from changeset-release/main to a non-main base could still be mis-selected.
  2. .github/workflows/release-cli-nightly.yml:399 — still no concurrency group or cross-run ordering on the breadcrumb job; an older run's job finishing after a newer run's can still leave the PR pointing at a stale build.
  3. .github/scripts/nightly-breadcrumb.cjs:192 — the stack-breadcrumb.cjs interaction is still real and now more concrete: I re-read stack-breadcrumb.cjs's ownDescription (lines 214-221) and canonicalizeBody (lines 339-362) directly — ownDescription strips only the and markers, so a stack reconcile on a stacked Version Packages PR still rebuilds the body as breadcrumb → description(nightly region embedded) → carried regions, moving the nightly region ahead of the carried blocks. This is now a direct conflict with the requirement text added in this PR itself (openspec/specs/cli-nightly-builds/spec.md:166: "SHALL be placed at the end… SHALL NOT modify any other managed region"), and neither test suite exercises this direction.

Newly reviewed this pass: the delta since the last review is just commit 8c74d51 (REGION_SEAM_PATTERN, stripRegion, two new tests, and two documentation comments in the workflow). I traced the new seam-matching logic (offset/atStart/atEnd against the un-mutated original string, consistent with how String.replaceAll computes match offsets) against several edge cases — region with single vs. double newlines on either side, region as the entire body, region flanked by other regions — and didn't find a new bug; the two added regression tests cover the case that mattered. I found nothing else new since the last review.

Nothing else in the diff (version parsing/rendering, upsert idempotency, the gh api -X PATCH choice, job permission scoping, the spec scenarios) changed since the last pass, and it still reads correctly.

I did not run lint/typecheck/tests myself — CI (Validate, Changeset) reports those on this PR.
· Branch

Comment thread .github/scripts/nightly-breadcrumb.cjs
Comment thread .github/workflows/release-cli-nightly.yml
Comment thread .github/scripts/nightly-breadcrumb.cjs
thecodedrift added a commit that referenced this pull request Aug 21, 2026
Three findings from the claude review on #133.

**The pull request was selected on its head ref alone.** GitHub allows several
open pull requests from one head branch to different bases, so
`head=<owner>:changeset-release/main` can return more than one and `.find()`
would annotate whichever the API listed first. Both refs are now matched in
the script, and the query carries `base=main` as well — the script re-checks
so that widening the query cannot silently widen what gets written.

**An older run could roll the region back.** `needs:` orders jobs inside one
run, and this workflow has no concurrency group on purpose, so two pushes in
quick succession can leave the older run's breadcrumb job writing last. The
write is now monotonic: the version already on the pull request is read back
out of the install line and compared on the 14-digit UTC stamp, which is
fixed-width precisely so a lexical compare orders builds. A concurrency group
would have been the wrong instrument — it would cancel in-progress publishes
to fix a cosmetic race.

**"At the end" was claimed unconditionally, and the stack breadcrumb can
break it.** `stack-breadcrumb.cjs`'s `canonicalizeBody` re-lays a stacked
body as breadcrumb → description → carried regions, and its `ownDescription`
strips only the regions it owns — so this one rides inside "description" and
lands above the carried blocks. Nothing here runs at that moment. The spec now
asserts placement of the write and requires the next publish to return the
region to the end, with a scenario for each; the script says where the real
fix belongs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
thecodedrift and others added 3 commits August 21, 2026 09:40
After a nightly publishes, the open `changeset-release/main` pull request
gains a `<!-- nightly -->` region at the end of its body naming the build:
the install line, the commit it was built from, and the time it was built.
Reviewers of that PR are exactly the audience for a build of the work its
changesets describe.

The region is removed and re-appended on every publish, so a hand-deleted
region comes back, repeated publishes replace rather than accumulate, and
a body someone has reordered converges. It never touches the `<!-- stack -->`
region stack-breadcrumb.yml may maintain on the same body.

A THIRD JOB, holding `pull-requests: write` and no credential — never a
step in `publish`, which would then hold both an npm OIDC identity and the
ability to rewrite pull request text. It `needs: publish`, so a suppressed
nightly never reaches it, and the version arrives as a job output: the
stamp already encodes the build time and the sha, so both are parsed back
out rather than read from a second clock.

No open Version Packages PR exits 0 — the branch exists only while
changesets are pending — but a failed `gh api` query still fails the step.

Note: the issue writes the install line as `npx @taskless/cli@<version>`.
Nightlies publish as `@taskless/cli-nightly`, and that version does not
exist under the released name, so the region names the package that will
actually install.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
Copilot review on #133. `stripRegion` collapsed every 3+ newline run in the
body, so an intentional blank-line run anywhere in the description was
rewritten on each republish — content this file does not own.

The removal pattern now eats the newlines around the region and the replacer
decides what belongs there: a blank line between two pieces of prose, nothing
at the top or the bottom of the body. Prose elsewhere is untouched. Two
regression tests cover it, including the republish, which is the path where
the collapse used to fire.

Also documents the lost-update window the same review raised: a PR body is
replaced whole and GitHub offers no compare-and-swap, so the nightly region,
the changesets release notes, and the stack breadcrumb can each overwrite one
another. Accepted rather than coordinated — all three writers are additive and
self-healing, so a lost write costs one cycle, and a lock would couple a
release workflow to a cosmetic breadcrumb.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
Three findings from the claude review on #133.

**The pull request was selected on its head ref alone.** GitHub allows several
open pull requests from one head branch to different bases, so
`head=<owner>:changeset-release/main` can return more than one and `.find()`
would annotate whichever the API listed first. Both refs are now matched in
the script, and the query carries `base=main` as well — the script re-checks
so that widening the query cannot silently widen what gets written.

**An older run could roll the region back.** `needs:` orders jobs inside one
run, and this workflow has no concurrency group on purpose, so two pushes in
quick succession can leave the older run's breadcrumb job writing last. The
write is now monotonic: the version already on the pull request is read back
out of the install line and compared on the 14-digit UTC stamp, which is
fixed-width precisely so a lexical compare orders builds. A concurrency group
would have been the wrong instrument — it would cancel in-progress publishes
to fix a cosmetic race.

**"At the end" was claimed unconditionally, and the stack breadcrumb can
break it.** `stack-breadcrumb.cjs`'s `canonicalizeBody` re-lays a stacked
body as breadcrumb → description → carried regions, and its `ownDescription`
strips only the regions it owns — so this one rides inside "description" and
lands above the carried blocks. Nothing here runs at that moment. The spec now
asserts placement of the write and requires the next publish to return the
region to the end, with a scenario for each; the script says where the real
fix belongs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
@thecodedrift
thecodedrift force-pushed the feat/nightly-region-on-changeset-pr branch from bc6ccd3 to b7b3b32 Compare August 21, 2026 16:40
@thecodedrift
thecodedrift merged commit 20f18f6 into main Aug 21, 2026
2 checks passed
thecodedrift added a commit that referenced this pull request Aug 21, 2026
Copilot review on #133. `stripRegion` collapsed every 3+ newline run in the
body, so an intentional blank-line run anywhere in the description was
rewritten on each republish — content this file does not own.

The removal pattern now eats the newlines around the region and the replacer
decides what belongs there: a blank line between two pieces of prose, nothing
at the top or the bottom of the body. Prose elsewhere is untouched. Two
regression tests cover it, including the republish, which is the path where
the collapse used to fire.

Also documents the lost-update window the same review raised: a PR body is
replaced whole and GitHub offers no compare-and-swap, so the nightly region,
the changesets release notes, and the stack breadcrumb can each overwrite one
another. Accepted rather than coordinated — all three writers are additive and
self-healing, so a lost write costs one cycle, and a lock would couple a
release workflow to a cosmetic breadcrumb.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
@thecodedrift
thecodedrift deleted the feat/nightly-region-on-changeset-pr branch August 21, 2026 16:42
thecodedrift added a commit that referenced this pull request Aug 21, 2026
#133 and #132 crossed. The nightly moved to `workflow_run` in #132, where
every checkout must carry `ref: github.event.workflow_run.head_sha`; the
`breadcrumb` job added by #133 was written against the `push` trigger and
merged without it.

Under `workflow_run` that is not an error. `github.sha` is the default branch
tip at event time, so the job checks out whatever `main` had moved to and
succeeds — running a copy of nightly-breadcrumb.cjs that Validate never saw,
while announcing a nightly built from a different commit. An empty `ref:`
fails the same way, silently, which is why the other two jobs assert HEAD
rather than trusting the checkout.

Cosmetic output does not lower the bar: it is the same fail-open shape, and
it reads as a normal green run. The job now pins the ref and asserts HEAD
against it, matching gate and publish line for line.

Nothing else moves. `breadcrumb` still reaches gate 0 transitively — a skipped
`gate` skips `publish`, which skips this — so it restates none of those four
conditions, and it consumes the publish job's stamped version rather than
re-deriving a short sha.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
thecodedrift added a commit that referenced this pull request Aug 21, 2026
#133 and #132 crossed. The nightly moved to `workflow_run` in #132, where
every checkout must carry `ref: github.event.workflow_run.head_sha`; the
`breadcrumb` job added by #133 was written against the `push` trigger and
merged without it.

Under `workflow_run` that is not an error. `github.sha` is the default branch
tip at event time, so the job checks out whatever `main` had moved to and
succeeds — running a copy of nightly-breadcrumb.cjs that Validate never saw,
while announcing a nightly built from a different commit. An empty `ref:`
fails the same way, silently, which is why the other two jobs assert HEAD
rather than trusting the checkout.

Cosmetic output does not lower the bar: it is the same fail-open shape, and
it reads as a normal green run. The job now pins the ref and asserts HEAD
against it, matching gate and publish line for line.

Nothing else moves. `breadcrumb` still reaches gate 0 transitively — a skipped
`gate` skips `publish`, which skips this — so it restates none of those four
conditions, and it consumes the publish job's stamped version rather than
re-deriving a short sha.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jwc9FFroR3mTZ4hLiSkkX3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-changeset PR intentionally ships no release note (bypasses the changeset requirement)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Link to latest Nightly is added to the Changeset PR

2 participants