Skip to content

fix(release): stabilize Linux SDK probe receipt - #71

Merged
leoisadev1 merged 1 commit into
mainfrom
cursor/stable-sdk-probe-receipt-8f36
Oct 7, 2026
Merged

leoisadev1 merged 1 commit into
mainfrom
cursor/stable-sdk-probe-receipt-8f36

Conversation

@leoisadev1

@leoisadev1 leoisadev1 commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Linux dry run 37621664130 on e37711ca compared two independent builds: AppImage, .deb, .rpm, linux tar.gz and source-audit.json were byte-identical. The source tarball was not. compare.py named one differing member:

convt-source/third-party/linux-source-scope/remove-sdk-only-probe.json (sha c52fc0a1… vs a40e2c47…, same mtime 1791376316 / mode 420 / uid 0). Manifests failed only because they record that tarball hash.

linux-source-scope.py writes that file after a real cargo build --offline --locked --release -p convt-cli -p convt-app with the original lock (SDK crates temporarily moved). Every current blocker is resolved, so nothing is moved and the probe is a full compile. Cargo then writes parallel Compiling lines and Finished … in 12.34s / in 2m 05s to stderr. Substituting $SOURCE and $EMPTY_CARGO_HOME left that order and timing in the shipped receipt.

#69 already dropped stderr from the receipt. This follows up by keeping the log as evidence after a rebuild-stable rendering (sorted lines, duration placeholder, path/ANSI//tmp/rustc* substitution), recording the packages that were actually moved, refusing a receipt that still leaks a rebuild path or cargo duration, and forcing CARGO_TERM_COLOR=never on the probe. The compare step is unchanged; the file still ships.

Fixes CNV-45

Evidence

python3 -m unittest discover -s scripts/release -p 'test_*.py' -v
Ran 22 tests in 0.069s
OK
  • Two synthetic cargo logs (ci-a vs ci-b, shuffled Compiling lines, 12.34s vs 2m 15s, color, rustc tmp) dump to identical remove-sdk-only-probe.json bytes.
  • Both cargo duration forms become in $DURATION.
  • A receipt that still contains a rebuild path or in 2m 05s is refused.
  • CI job Release scripts (and the rest of CI 37640256741) is green. Those tests run on every PR; they do not need a 2h Linux release run.

Do not dispatch Build release linux from this PR. Eng Convt squash-merges when CI is green and redispatches that workflow.

Merge Danger

Door: two-way.

Blast radius: Linux source-archive receipt third-party/linux-source-scope/remove-sdk-only-probe.json only. Adds unit tests under scripts/release. Does not change package payloads, compare.py, or published v0.2.0 assets.

Open in Web Open in Cursor 

The source-archive compare in Build release linux 37621664130 failed only
on third-party/linux-source-scope/remove-sdk-only-probe.json. The probe
stores cargo build stderr; path substitution left parallel Compiling
order and Finished durations (12.34s vs 2m 05s) to differ across ci-a
and ci-b. Canonicalize the log, refuse leaked paths/durations, and add a
scripts/release unit test so this class of drift is caught without a 2h
release rebuild.

Co-authored-by: Leo <leoisadev1@users.noreply.github.com>
@leoisadev1
leoisadev1 marked this pull request as ready for review October 7, 2026 15:01
@leoisadev1
leoisadev1 merged commit db0d7d3 into main Oct 7, 2026
8 checks passed
@leoisadev1
leoisadev1 deleted the cursor/stable-sdk-probe-receipt-8f36 branch October 7, 2026 15:01

@devin-ai-integration devin-ai-integration 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.

Devin Review found 2 potential issues.

Devin Review


ANSI = re.compile(r'\x1b\[[0-9;]*[mK]')
# Cargo prints "12.34s" under a minute and "2m 05s" after that.
DURATION = re.compile(r'\bin (?:\d+m )?\d+(?:\.\d+)?s\b')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Hour-long probes destabilize source archives

When a probe exceeds an hour, DURATION leaves Cargo's hour-prefixed elapsed time in the receipt. Different run times then produce different source archives and fail the release comparison.

Learn more

Cargo can report a long build as Finished ... in 1h 02m 03s. The duration matcher recognizes only seconds or minutes plus seconds, so sdk_remove_probe accepts that line unchanged. The receipt is included in the source archive, and the release workflow compares two independently rebuilt archives. Different elapsed times make otherwise identical archives compare unequal.

Example: A first build finishes in 1h 02m 03s and a second in 1h 03m 10s. Both receipts keep those distinct values instead of in $DURATION.

Recommended fix: Match Cargo's hour-prefixed duration format as well as the existing minute and second formats. Add an hour-long case to the receipt equality tests.

Suggested change
DURATION = re.compile(r'\bin (?:\d+m )?\d+(?:\.\d+)?s\b')
DURATION = re.compile(r'\bin (?:\d+h )?(?:\d+m )?\d+(?:\.\d+)?s\b')

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +32 to +59
def test_two_rebuild_dirs_write_identical_probe_bytes(self):
# Linux dry run 37621664130: only remove-sdk-only-probe.json differed.
# ci-a vs ci-b, same mtime/mode, content sha c52fc0a1… vs a40e2c47….
with tempfile.TemporaryDirectory(prefix='convt-probe-repro-') as tmp:
left_tree = Path(tmp) / 'ci-a' / 'convt-source'
right_tree = Path(tmp) / 'ci-b' / 'convt-source'
left_home = Path(tmp) / 'cargo-aaaa'
right_home = Path(tmp) / 'cargo-bbbb'
left = scope.sdk_remove_probe(
0,
cargo_log(left_tree, left_home, ('foo v1.0.0', 'bar v2.0.0'), '12.34s', colored=True),
left_tree,
left_home,
)
right = scope.sdk_remove_probe(
0,
cargo_log(right_tree, right_home, ('bar v2.0.0', 'foo v1.0.0'), '2m 15s'),
right_tree,
right_home,
)
self.assertEqual(left, right)
dumped = []
for name, receipt in ('a.json', left), ('b.json', right):
path = Path(tmp) / name
scope.dump(path, receipt)
dumped.append(path.read_bytes())
self.assertEqual(dumped[0], dumped[1])
self.assertEqual(hashlib.sha256(dumped[0]).hexdigest(), hashlib.sha256(dumped[1]).hexdigest())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Real probe output remains unverified

The tests exercise constructed Cargo logs, not an inspected receipt from a real probe. The repository verification standard calls for a real run and inspected output; follow up before relying on rebuild stability.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@greptile-apps

greptile-apps Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Adds deterministic output normalization for build probe logs.

The PR appears safe to merge; no actionable issues were found.

What we checked:

  • Blocker entries cannot supply paths: The blocker entries select names and versions. The moved directories come from vendor.glob('*/Cargo.toml'), not from paths in the blocker file. This PR does not change the file moves.

Summary

This PR restores build logs in the Linux SDK-removal receipt while removing the known differences between rebuilds.

  • Replaces build paths, durations, color codes, and Rust temporary paths, then sorts the log lines.
  • Records the packages actually moved during the probe.
  • Disables Cargo color and progress output.
  • Adds tests for matching receipt bytes, field names, and rejection of leftover paths or durations.

No actionable issues were found. The review inspected code and tests; it did not run tests or dispatch the Linux release workflow.

Reviews (1) · Last reviewed commit: "fix(release): canonicalize Linux SDK pro..." · Reviewed by Greptile

leoisadev1 added a commit that referenced this pull request Oct 7, 2026
#71 normalized and sorted the probe's cargo stderr, but Linux dry run
37641703105 still differed between two identical rebuilds in exactly
remove-sdk-only-probe.json. The receipt keeps the command, exit code and the
packages the probe removed, which is what it is evidence of.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants