fix(resume): silent-skip event + Failed→Skipped regression test (#125, #126)#130
Conversation
plus regression test for Failed->Skipped transition (#126) ## #125 — silent resume-skip When resume encounters a package whose state is already \`Published\` or \`Skipped\`, the sequential path short-circuited with a stdout info line and \`continue\`, without recording an event. Since \`events.jsonl\` is the **authoritative audit log** (state.json is a projection of it), this left a user-visible gap: an auditor reading only events.jsonl couldn't tell "resume looked at this package and trusted its terminal state" from "resume never touched this package." Surfaced by the synthetic rehearsal test (\`e2e_rehearse.rs\`, PR #124). **Fix:** emit a \`PackageSkipped { reason: \"resume: state already <s>\" }\` event in the already-complete match arm. No receipt entry is pushed — the receipt vector has always excluded already-terminal packages on the resume path, and callers depend on that shape (e.g. \`run_resume_runs_publish_when_state_exists\`). Only the audit-trail behavior changes. ## #126 — Failed->Skipped state drift The issue speculated that resume's stdout-said-Skipped but state.json-still-says-Failed could indicate \`update_state\` not firing on the version-exists short-circuit when the prior state was Failed. **Finding:** the current sequential code handles this correctly — \`reg.version_exists(p) \=\\= true\` triggers \`update_state(Skipped)\` which flushes to state.json, and a targeted test (\`resume_from_failed_ambiguous_updates_state_to_skipped_when_registry_visible\`) passes without any code change. The observation in the issue may have been a stale-state-file artifact in the synthetic rehearsal fixture. Landing the test anyway as a regression guard: if a future refactor breaks this semantics (e.g. parallel mode taking a different path, or state write getting clobbered), the guard fires immediately. ## Tests Two new \`#[serial]\` tests in \`engine::tests\`: - \`resume_emits_package_skipped_event_for_already_published_state\` — seeds state with Published, runs \`run_publish\`, asserts \`PackageSkipped\` appears in events.jsonl. - \`resume_from_failed_ambiguous_updates_state_to_skipped_when_registry_visible\` — seeds state with Failed{Ambiguous}, registry returns 200, asserts reloaded state.json shows Skipped. All 49 existing resume/publish tests remain green.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 1 minutes and 52 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Three-column reconciliation of what's actually merged vs each issue's acceptance checklist. Single source of truth for what closes each pillar issue. **Findings:** - **#90 Recover** — honestly closable. Code side is done (#124 + #130); operator-side real rehearsal is an ops action, not a code gap. - **#97 Prove tier 2** — 85% done. Rehearsal + visibility + hard gate + plan_id binding all landed (#127 + #133). Missing: install/smoke check (cargo install against the rehearsal registry / consumer build). One narrow follow-up PR closes it. - **#98 Remediate** — 60% done. Receipt schema + plan-yank (from-receipt) + yank primitive + fix-forward planning all landed (#121 + #132 + #134). Missing: plan-yank's --starting-crate graph mode, plan execution for yank + fix-forward. Two narrow follow-ups. Also captures the two review concerns on #122 (Trusted Publishing) that were addressed in a follow-up commit to that PR. Recommended next merge order and follow-up PRs spelled out at bottom.
Three-column reconciliation of what's actually merged vs each issue's acceptance checklist. Single source of truth for what closes each pillar issue. **Findings:** - **#90 Recover** — honestly closable. Code side is done (#124 + #130); operator-side real rehearsal is an ops action, not a code gap. - **#97 Prove tier 2** — 85% done. Rehearsal + visibility + hard gate + plan_id binding all landed (#127 + #133). Missing: install/smoke check (cargo install against the rehearsal registry / consumer build). One narrow follow-up PR closes it. - **#98 Remediate** — 60% done. Receipt schema + plan-yank (from-receipt) + yank primitive + fix-forward planning all landed (#121 + #132 + #134). Missing: plan-yank's --starting-crate graph mode, plan execution for yank + fix-forward. Two narrow follow-ups. Also captures the two review concerns on #122 (Trusted Publishing) that were addressed in a follow-up commit to that PR. Recommended next merge order and follow-up PRs spelled out at bottom.
Summary
Two trust-core regressions surfaced by the #90 synthetic rehearsal test (PR #124). Both are small, focused fixes — no refactor.
#125 — Silent resume-skip
Before: resume's already-complete match arm (`Published | Skipped`) logged a stdout info line and `continue`d, without emitting any event. `events.jsonl` had no record that resume had looked at the package.
After: emit `PackageSkipped { reason: "resume: state already " }` before continuing. An auditor reading only events.jsonl can now reconstruct resume's decisions for every planned package.
Receipt shape unchanged — already-complete packages still omit from `receipt.packages`, matching prior contract (tests `run_resume_runs_publish_when_state_exists` et al depend on that emptiness).
#126 — Failed → Skipped state drift
Investigated. Turned out the current sequential code already handles this correctly: when resume sees `Failed` state and `reg.version_exists` returns true, `update_state(Skipped)` is called and flushes to state.json. My targeted regression test passes with zero code changes.
The bad observation reported in the issue likely came from a stale state-dir artifact in the synthetic fixture, not a real bug in this path.
Keeping the test anyway as a regression guard: if a future refactor (parallel mode, concurrent writes, state-write reordering) breaks the semantics, the guard fires before the bug hits release CI.
Tests
Two new `#[serial]` tests in `engine::tests`:
All 49 existing resume/publish tests still pass.
Test plan
Closes