Skip to content

fix(release): prove one staged candidate set before publication - #391

Merged
EffortlessSteven merged 19 commits into
mainfrom
fix/release-staged-candidate-gate
Aug 4, 2026
Merged

fix(release): prove one staged candidate set before publication#391
EffortlessSteven merged 19 commits into
mainfrom
fix/release-staged-candidate-gate

Conversation

@EffortlessSteven

@EffortlessSteven EffortlessSteven commented Aug 4, 2026

Copy link
Copy Markdown
Member

Final exact-head proof

Current consolidated head: 27ed2a4bed4d6c8cb826d8168c9fa2922f7e1591

Observed locally on that exact head:

  • cargo fmt --all -- --check — pass
  • bash -n scripts/release-install-smoke.sh — pass
  • PowerShell script parse — pass
  • cargo clippy -p shiplog --all-targets --locked -- -D warnings — pass
  • cargo test -p shiplog --test release_candidate_smoke --locked — 9 passed
  • cargo xtask check-workflows --mode blocking-allowlist — pass
  • cargo xtask check-file-policy --mode blocking-allowlist — pass
  • cargo xtask ci-small — not verified; the lane timed out with an orphaned stalled process and was terminated

The focused suite now covers success/receipt retention, incomplete and duplicate/unknown manifests, workflow identity, checksum mismatch, flat checksum entries, broken executables, and the tag-push/negative-control workflow contract. CandidateFixture remains intentionally private to this integration target.

The exact-tag/source-writer live release proof remains out of scope here; #245 stays open until the source counterpart and an authorized non-public exact-tag run provide observed evidence.

What changed Implements the still-open staged-artifact portion of #245 in the authoritative development repository. ### One exact candidate set - release-preflight resolves both the explicit semver tag and its exact 40-character commit SHA; - every build and downstream job proves it checked out that exact commit; - Stage Release Candidates assembles exactly one copy of all four platform binaries, deterministic SHA256SUMS.txt, and a bounded RELEASE_CANDIDATE.txt manifest containing tag, source SHA, repository, workflow run identity, asset count, and checksum-manifest digest; - the retained verified-release-candidates workflow artifact exposes its artifact id/digest and manifest hashes to downstream jobs. ### Acceptance consumes staged bytes - Linux, macOS Intel, macOS Apple Silicon, and Windows first-use jobs now wait for candidate staging and download the same verified-release-candidates artifact; - Bash and PowerShell smoke scripts accept SHIPLOG_RELEASE_CANDIDATE_DIR plus exact SHIPLOG_RELEASE_SOURCE_SHA, require the complete four-binary bundle, validate manifest identity/checksums, and exercise the local candidate from an empty directory with provider credentials cleared; - public-release download mode remains available for post-publication verification; - each platform uploads produced receipts and diagnostics even on failure. ### Fail-closed release authority - a Linux negative-control job corrupts the staged binary without changing checksums and proves the gate rejects it; - a second control replaces the binary with a failing executable, updates checksums consistently, and proves command execution still rejects it; - terminal Release Candidate Ready requires preflight, staging, release validation, all four first-use lanes, both negative controls, and release-mode tests; - it emits a durable receipt with exact tag/source/artifact/manifests and states that publication still requires explicit source-side human authority. ### Ordinary PR proof A new cross-platform integration target synthesizes the complete four-platform candidate bundle from the cargo-built test binary and drives the real Bash or PowerShell smoke script. It proves: - local staged-candidate success and retained first-use receipts; - checksum corruption fails before execution; and - on Unix, a broken executable with a matching checksum still fails the command boundary. ## Why PR #273 correctly added structural validation for all five first-use receipt artifacts, but explicitly left candidate staging, exact uploaded-byte consumption, four-lane publication gating, and rollback outside scope. The current workflow allowed first-use jobs to race asset upload and the smoke scripts fetched release URLs independently, so the jobs were not bound to one workflow-staged candidate set. This PR closes that implementation gap on the swarm verification surface. It does not add release-write authority to swarm. ## Review map - .github/workflows/release.yml — exact tag binding, candidate assembly, matrix consumption, diagnostics, negative controls, and terminal authority. - scripts/release-install-smoke.sh — complete local candidate-bundle mode plus public release mode, manifest/checksum validation, and explicit command-failure diagnostics. - scripts/release-install-smoke.ps1 — Windows parity for the same contract. - apps/shiplog/tests/release_candidate_smoke.rs — normal-PR execution proof for success, checksum failure, and command failure. ## Expected proof bash bash -n scripts/release-install-smoke.sh pwsh -NoProfile -Command '$null = [scriptblock]::Create((Get-Content scripts/release-install-smoke.ps1 -Raw))' cargo fmt --all -- --check cargo clippy -p shiplog --all-targets --locked -- -D warnings cargo test -p shiplog --test release_candidate_smoke --locked cargo xtask check-workflows --mode blocking-allowlist cargo xtask check-file-policy --mode blocking-allowlist cargo xtask ci-small git diff --check A real release proof additionally requires one explicit tag/owner-approved workflow run whose four first-use jobs consume the same staged artifact and whose Release Candidate Ready job is green. ## Source handoff .github/workflows/release.yml is deliberately source-owned governance. After this shared implementation is merged and promoted, canonical source must port the bounded source-writer counterpart: draft GitHub Release creation/upload may remain source-only, but its four acceptance lanes must consume this same staged candidate set and final publication must remain human-authorized. ## Claim boundary This prepares and proves release candidates in shiplog-swarm. It does not create or publish a GitHub Release, publish crates.io, push or move a tag, sign/notarize artifacts, update Homebrew/Scoop, change the current promotion state, or move release authority from EffortlessMetrics/shiplog. ## Rollback Revert the squash merge. Public release download mode remains unchanged; no tag, release, crate, package channel, or source branch is mutated by this PR. Refs #245. Keep #245 open until the source writer counterpart lands and one exact explicit-tag run records all four target results plus a green Release Candidate Ready receipt.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Summary by CodeRabbit

  • New Features

    • Added comprehensive release-candidate verification across supported platforms before publication.
    • Added staged-bundle testing for installation, checksums, metadata, and executable startup.
    • Added release readiness records summarizing validation results.
  • Bug Fixes

    • Releases are now verified against the exact source revision used to build them.
    • Invalid, corrupted, incomplete, or non-functional release packages are rejected before publication.
  • Documentation

    • Updated installation verification guidance and status messages for staged and published releases.

Walkthrough

The release workflow binds jobs to an immutable commit, stages a four-platform candidate, validates metadata and binaries, performs first-use acceptance, runs negative controls, and records readiness evidence before human-authorized publication.

Changes

Release candidate workflow

Layer / File(s) Summary
Immutable source and candidate staging
.github/workflows/release.yml, policy/workflow-allowlist.toml
The workflow resolves the exact release commit, verifies it across build and staging jobs, and creates deterministic candidate assets with checksums and manifest metadata. The artifact download action is pinned to an exact commit.
Candidate manifest and smoke validation
.github/workflows/release.yml, scripts/release-install-smoke.sh, scripts/release-install-smoke.ps1
Validation supports staged candidates and public releases. It checks candidate identity, metadata, required assets, checksums, versions, commands, and receipts.
Cross-platform acceptance and negative controls
.github/workflows/release.yml, apps/shiplog/tests/release_candidate_smoke.rs
Acceptance jobs test staged candidates on four platforms. Tests and negative controls reject incomplete bundles, corrupted checksums, malformed manifests, and failing executables.
Readiness receipt and publication gate
.github/workflows/release.yml
The workflow verifies the immutable commit in integration tests, requires all release gates, records candidate and artifact digests, and retains a readiness receipt. Publication remains human-authorized.

Estimated code review effort: 5 (Critical) | ~90 minutes

Possibly related issues

Poem

A rabbit checks each checksum bright,
Four platforms run through the night.
Bad bytes stop and failures flee,
Receipts wait beside the tree.
Human approval opens the gate.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: validating one staged release candidate set before publication.
Description check ✅ Passed The description provides detailed change scope, proof commands, claim boundaries, rollback guidance, and issue linkage, with only minor template-section differences.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/release-staged-candidate-gate

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Member Author

CI budget acknowledgement

The PR planner selected the release-package, workflow-policy, and CLI-product risk packs: 11 lanes at an estimated ~165 LEM, placing this in the hard band. ci-budget-override is applied deliberately.

The spend is justified because this PR changes the exact release artifact trust boundary, platform smoke scripts, workflow policy surface, and cross-platform integration proof together. Splitting the workflow from the scripts/tests would create an intermediate contract that cannot prove the bytes it selects and would run overlapping release/policy lanes multiple times.

Skipped nightly, coverage, mutation, and release-only lanes are not claimed as executed proof. A real explicit-tag run remains required before #245 can close.

@EffortlessSteven EffortlessSteven left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

[P1] Make the staged-candidate success path pass receipt validation

Failure mode:
The exact-head hosted Shiplog Rust Small Result run for this PR fails staged_candidate_smoke_uses_local_bundle_and_emits_receipts: report validate --path "$latest_run/intake.report.json" --receipts rejects the generated report because reports.json points at .../out/merge_.../out/merge_.../intake.report.json while the validated file is .../out/merge_.../intake.report.json.

Why here:
The new staged-candidate smoke contract makes this validation a required release gate at scripts/release-install-smoke.sh:258, so the PR's exact hosted gate is currently red even though the other three new tests pass.

Fix direction:
Align the receipt path contract used by the cold-start command and report validate --receipts—either emit the canonical run-relative path expected by the validator or resolve an already run-rooted path without prepending out/<run> again. Keep the regression in release_candidate_smoke so this exact candidate path stays green.

Validation:
Rerun cargo test -p shiplog --test release_candidate_smoke --locked and the routed Shiplog Rust Small Result check on the updated exact head.

Confidence:
High; reproduced in hosted run 30899824202, job 91961327124.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/release.yml (1)

304-316: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Align candidate retention with the receipt retention.

The staged candidate set expires after 5 days. The readiness receipt at Line 732 is retained for 30 days and records candidate_artifact_id and candidate_artifact_digest. For 25 of those days the receipt names bytes that no longer exist, so a human cannot re-verify the digest before authorizing publication.

Set retention-days here to match the receipt, or shorten the receipt retention.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 304 - 316, Update the
retention-days setting in the “Retain exact staged release candidates” step to
30 days, matching the readiness receipt retention and preserving candidate
artifacts for the full verification window.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 516-526: Add an exact-commit verification step immediately after
the checkout step in the job containing “Checkout release scripts,” comparing
git rev-parse HEAD with needs.release-preflight.outputs.release_sha and failing
on mismatch. Keep the existing artifact download and release-install-smoke.sh
flow unchanged.
- Around line 286-296: Update the release candidate metadata generation around
RELEASE_CANDIDATE.txt to derive asset_count from the expected asset array
defined earlier in the workflow instead of hardcoding 4. Ensure the computed
count is written to the asset_count field so validators and smoke tests reflect
every configured target.
- Around line 254-257: Update every actions/download-artifact reference in the
release workflow, including the steps named “Download all binary artifacts” and
the other listed usages, to the immutable commit SHA
3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c and retain a # v8 comment on each
reference.
- Around line 228-230: Update the release workflow step’s shell commands so both
handoff messages, including the statement that Swarm cannot create a GitHub
release, are appended to GITHUB_STEP_SUMMARY rather than only printed to stdout.
Preserve the existing message text and ordering.

In `@apps/shiplog/tests/release_candidate_smoke.rs`:
- Around line 101-107: In the release-candidate smoke test, update the
filesystem operations around the Unix permission setup and the additional sites
near lines 209, 229, 231, 253, and 255 to attach context before propagating
errors. Use static .context descriptions for fixed operations and .with_context
closures with the relevant path for dynamic operations, covering metadata,
set_permissions, and other bare filesystem ? calls while preserving the existing
behavior.
- Around line 246-248: Update scripts/release-install-smoke.ps1 to emit the
distinct “candidate binary failed --version” signal when the candidate command
exits with a nonzero $LASTEXITCODE, while retaining “unexpected version output”
for successful commands with mismatched output. Then remove the #[cfg(unix)]
gate from staged_candidate_smoke_rejects_broken_command_with_matching_checksum
so the same rejection assertion runs on Windows.
- Around line 16-21: Move CandidateFixture and candidate_fixture() out of
release_candidate_smoke.rs into the reusable shiplog-testkit::fixtures module or
an appropriate release-scenario submodule. Preserve the existing
release-candidate metadata and bundle setup, then update the smoke test imports
and usages to reference the shared fixture implementation.

In `@scripts/release-install-smoke.ps1`:
- Around line 66-73: Rename the local $matches collection in the candidate
bundle lookup to a non-automatic variable, and update its Count, error message,
and index references consistently; leave the Assert-CandidateManifest -notmatch
usage unchanged.

In `@scripts/release-install-smoke.sh`:
- Around line 259-264: Normalize `binary_path` to an absolute path before the
subshell changes directories, matching the existing candidate-path normalization
pattern near the release smoke setup. Ensure the invocation in the
`cold_start_dir` subshell uses that absolute `binary_path` while preserving the
current validation arguments.
- Around line 119-134: Update the Bash manifest validation before the existing
schema_version, release_tag, source_sha, and asset_count assertions to detect
and reject duplicate manifest keys, matching the parsing behavior in the
PowerShell validator. Ensure each required field appears exactly once while
preserving the current field-value checks and error handling.
- Around line 188-192: Update the checksum lookup in the SHA256SUMS verification
block to match both flat filenames and directory-prefixed entries, reusing the
basename-matching behavior from the PowerShell smoke script. Escape the asset
value before using it in the awk regular expression, while preserving the
existing missing-entry failure behavior.

---

Outside diff comments:
In @.github/workflows/release.yml:
- Around line 304-316: Update the retention-days setting in the “Retain exact
staged release candidates” step to 30 days, matching the readiness receipt
retention and preserving candidate artifacts for the full verification window.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3dd83058-a03d-4c42-9260-fb97321a663a

📥 Commits

Reviewing files that changed from the base of the PR and between b816b60 and a54884d.

📒 Files selected for processing (4)
  • .github/workflows/release.yml
  • apps/shiplog/tests/release_candidate_smoke.rs
  • scripts/release-install-smoke.ps1
  • scripts/release-install-smoke.sh

Comment thread .github/workflows/release.yml Outdated
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
Comment thread .github/workflows/release.yml
Comment thread apps/shiplog/tests/release_candidate_smoke.rs
Comment thread apps/shiplog/tests/release_candidate_smoke.rs Outdated
Comment thread scripts/release-install-smoke.ps1 Outdated
Comment thread scripts/release-install-smoke.sh Outdated
Comment thread scripts/release-install-smoke.sh
Comment thread scripts/release-install-smoke.sh

@EffortlessSteven EffortlessSteven left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

[P1] Assert the negative-control checkout resolves the preflight SHA

Failure mode:
The release-candidate-negative-controls job checks out ${{ needs.release-preflight.outputs.release_tag }} and immediately runs scripts/release-install-smoke.sh, but never compares git rev-parse HEAD with ${{ needs.release-preflight.outputs.release_sha }}. If the tag resolution changes between preflight and this job, the negative controls can execute a different release-script revision while reporting evidence for the preflight candidate.

Why here:
This PR's core contract is one immutable exact-tag candidate set. Every job that executes release scripts must prove the checkout identity, not only the artifact manifest identity.

Fix direction:
Add the same exact-commit assertion used by the other release jobs immediately after the checkout:
test "$(git rev-parse HEAD)" = "${{ needs.release-preflight.outputs.release_sha }}".
Retain the existing staged-artifact and negative-control assertions.

Validation:
Exercise a tag/ref mismatch fixture or equivalent workflow proof and confirm the negative-control job fails before invoking either smoke script.

Confidence:
High; inspected current head 595e6152c3370c85a069caf9f12b5264c2d5c1ce, .github/workflows/release.yml:516-520.

@EffortlessSteven EffortlessSteven added the full-ci Run broad CI jobs on PRs when default PR lanes are slimmed label Aug 4, 2026 — with ChatGPT Codex Connector

Copy link
Copy Markdown
Member Author

@codex review

Please review the current final head, especially exact tag/source/artifact binding, complete four-platform bundle validation, failure controls, matrix consumption of staged bytes, and the terminal readiness aggregate.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46fd16c469

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +73
git fetch --force --depth=1 origin "refs/tags/$tag:refs/tags/$tag"
git checkout --detach "$tag"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Bind tag-push resolution to the triggering commit

Failure mode: On a tag-push run, this force-fetch resolves the tag from its current remote value instead of binding it to the triggering github.sha; if the tag is moved after the webhook is created but before preflight executes, the workflow can build and certify a different commit while still reporting success for the original tag event. Why here: every downstream comparison uses the newly resolved release_sha, so none detects this initial substitution. Fix direction: for push events, require the peeled tag commit to equal the event SHA (while retaining current-tag resolution for approved manual dispatches). Validation: trigger a run and retarget the tag before this fetch, then verify preflight rejects the mismatch. Confidence: high. This is particularly important because tag and release operations remain source-repository authority.

AGENTS.md reference: AGENTS.md:L14-L17

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

@codex address that feedback

Address the current workflow-only findings without broadening scope:

  1. Pin all four actions/download-artifact@v8 uses to official v8.0.1 commit 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with a version comment.
  2. In create-release, always write the general verification-only summary; keep the pull-request-specific warning additive.
  3. Derive asset_count from the expected array when generating RELEASE_CANDIDATE.txt; pass GitHub expression values through step env variables rather than embedding them directly in the shell body.
  4. In release-candidate-negative-controls, confirm git rev-parse HEAD equals the exact release-preflight.outputs.release_sha before using scripts from the checkout.

Do not move the release fixture to shiplog-testkit; that private integration target deliberately exercises repository scripts and workflow-adjacent behavior, and moving it would add an unrelated crate dependency/public seam. Do not merge or mark the PR ready.

@chatgpt-codex-connector

Copy link
Copy Markdown

Summary

Testing

  • git diff --check
  • cargo xtask check-workflows --mode blocking-allowlist
  • cargo xtask check-file-policy --mode blocking-allowlist

View task →

@EffortlessSteven
EffortlessSteven force-pushed the fix/release-staged-candidate-gate branch from 80b7dd3 to 27ed2a4 Compare August 4, 2026 11:51
@EffortlessSteven
EffortlessSteven marked this pull request as ready for review August 4, 2026 11:52
@factory-droid

factory-droid Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Droid encountered an error —— View job

Failed to checkout PR #391 branch for review

Droid is reviewing code and running a security check…

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/release-install-smoke.sh`:
- Around line 185-188: Normalize both source SHA values to lowercase before the
comparison in the release smoke script, reusing the existing lower_hex
normalization used elsewhere. Update the corresponding comparison in the
PowerShell script as well, preserving the existing mismatch error and exit
behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 1e389ed9-35c9-4477-b1c6-39b290ada800

📥 Commits

Reviewing files that changed from the base of the PR and between a54884d and 27ed2a4.

📒 Files selected for processing (5)
  • .github/workflows/release.yml
  • apps/shiplog/tests/release_candidate_smoke.rs
  • policy/workflow-allowlist.toml
  • scripts/release-install-smoke.ps1
  • scripts/release-install-smoke.sh

Comment on lines +185 to +188
[[ "$source_sha" == "$expected_source_sha" ]] || {
echo "candidate manifest is not bound to source commit $expected_source_sha" >&2
exit 1
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Normalize case before the source_sha comparison.

Line 127 accepts SHIPLOG_RELEASE_SOURCE_SHA in either case, but Line 185 compares it literally against the manifest value. An uppercase input then fails against a lowercase manifest value even though both identify the same commit. The file already added lower_hex for this reason at Lines 215 and 274. scripts/release-install-smoke.ps1 Line 145 has the same case-sensitive comparison.

♻️ Proposed refactor
-  [[ "$source_sha" == "$expected_source_sha" ]] || {
+  [[ "$(lower_hex "$source_sha")" == "$(lower_hex "$expected_source_sha")" ]] || {
     echo "candidate manifest is not bound to source commit $expected_source_sha" >&2
     exit 1
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[[ "$source_sha" == "$expected_source_sha" ]] || {
echo "candidate manifest is not bound to source commit $expected_source_sha" >&2
exit 1
}
[[ "$(lower_hex "$source_sha")" == "$(lower_hex "$expected_source_sha")" ]] || {
echo "candidate manifest is not bound to source commit $expected_source_sha" >&2
exit 1
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/release-install-smoke.sh` around lines 185 - 188, Normalize both
source SHA values to lowercase before the comparison in the release smoke
script, reusing the existing lower_hex normalization used elsewhere. Update the
corresponding comparison in the PowerShell script as well, preserving the
existing mismatch error and exit behavior.

@EffortlessSteven
EffortlessSteven merged commit ac93085 into main Aug 4, 2026
45 of 46 checks passed
@EffortlessSteven
EffortlessSteven deleted the fix/release-staged-candidate-gate branch August 4, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-budget-override full-ci Run broad CI jobs on PRs when default PR lanes are slimmed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant