Skip to content

feat(automation): archive terminal runs on delete - #6864

Merged
Hmbown merged 1 commit into
codewhale-hq:wave/0.10.1-nextfrom
asto18089:upstream/run-archive
Oct 6, 2026
Merged

Hmbown merged 1 commit into
codewhale-hq:wave/0.10.1-nextfrom
asto18089:upstream/run-archive

Conversation

@asto18089

@asto18089 asto18089 commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Deleting an automation dropped its terminal run history. delete_automation now refuses while any run is queued or running — an in-flight occurrence has already crossed the admission boundary, so its definition and run binding must stay intact for recovery to settle it. This deliberately reverses the previous behavior of retaining queued/running receipts through deletion; the old contract's guarantee (recovery can neither lose nor repeat the occurrence) is preserved in strictly stronger form, because the definition itself now survives until the receipt settles.

Once settled, completed/failed/canceled runs move under <root>/archive/<automation_id>/ before the live paths are removed (atomic writes, crash-safe: a half-completed delete loses nothing and a retry is idempotent), bounded to the newest 50 per automation by ended_at (falling back to created_at). The archive tree sits beside automations/, runs/, and triggers/, invisible to listings, pending-run recovery, and scheduler scans; list_archived_runs serves it via a new archived query flag on the existing runs endpoint (absent flag = unchanged behavior, #[serde(default)]).

Two existing tests were rewritten for the new contract: deletes_definition_and_settled_runs_but_retains_unfinished_receipts (now delete_refuses_active_receipts_then_archives_settled_runs) and reconciliation_reaches_old_runs_and_runs_of_deleted_definitions (the deleted-definition recovery leg is unreachable by design now; the get-runs-past-window coverage is preserved). The orphan-receipt path (finish_scheduled_run_persists_run_when_automation_deleted_mid_enqueue) is unchanged and still passes.

Disclosures: the refusal check and archive writes run inside the same exclusive transaction/lock as the delete (claim-vs-delete is serialized — no check-then-enqueue window), so a very large run history extends the lock hold; bounded today at 50 archived runs per automation. The include-suppressed half of the active-run scan is defensive: a suppressed active run is not reachable today (suppression is only persisted with a terminal status). Known follow-up: the TUI delete receipt still says "recorded runs deleted: {run_count}", which reads oddly once runs are archived instead of dropped — wording follow-up.

Testing

  • cargo test -p codewhale-tui --lib automation_manager — refuse-while-active (visible queued runs at all three dispatch sites), archive contents and ordering, the 50-run retention bound with exact dropped-set assertions, scheduler-scan isolation after delete, and the reconciliation/settle-then-delete flow
  • cargo clippy -p codewhale-tui --all-targets --all-features --locked
  • cargo fmt --all -- --check

Adapted from the Pinvou fork's automation run-archiving work (Pinvou/CodeWhale branch upstream/u8-run-archive, commit 6e1bc9324), re-derived onto the current automation manager (upstream's ensure_safe_storage_id / atomic-write / delete-refusal idioms).

Checklist

  • Updated docs or comments as needed
  • Added or updated tests where relevant
  • No CHANGELOG.md changes

No-Issue: Retain completed automation history when its definition is deleted.

@asto18089
asto18089 requested a review from Hmbown as a code owner October 5, 2026 11:52
@github-actions github-actions Bot added the contribution-gate Author not yet in .github/APPROVED_CONTRIBUTORS; a maintainer grants access with /lgtm label Oct 5, 2026
Deleting an automation dropped its terminal run history outright. Now
delete_automation refuses while any run is queued or running - an
in-flight occurrence has already crossed the admission boundary, so its
definition and run binding must stay intact for recovery to settle it -
and once deletion proceeds it moves completed, failed, and canceled runs
under <root>/archive/<automation_id>/ before removing the live paths.

The archive is bounded to the most recent 50 terminal runs per
automation (newest-first by ended_at, falling back to created_at; older
runs are pruned) and sits beside automations/, runs/, and triggers/, so
live listings, pending-run recovery, and scheduler scans never see it.
list_archived_runs exposes the retained history, served by the runtime
API runs endpoint through a new archived query flag.

Signed-off-by: asto <asto18089@126.com>
@asto18089
asto18089 force-pushed the upstream/run-archive branch from 9298221 to ca59ff7 Compare October 5, 2026 14:18
@Hmbown Hmbown added this to the v0.10.2 milestone Oct 5, 2026
@Hmbown
Hmbown changed the base branch from main to wave/0.10.1-next October 6, 2026 05:30
@Hmbown
Hmbown merged commit c5f2be8 into codewhale-hq:wave/0.10.1-next Oct 6, 2026
23 of 27 checks passed
Hmbown pushed a commit that referenced this pull request Oct 6, 2026
Reconcile the complete contributions from #6832 (@aboimpinto), #6867
(@hodeswildsmith455-boop), and #6805 (@LIghtJUNction) with the current
Engine, provider identities, reviewed-plugin policy, and task lifecycle.
Original contributor histories are recorded by subsequent resolved merges.

Fix the already integrated contributor cases: snapshot corruption is an
explicit unavailable/error result (#6817), malformed locales cannot select
an incidental script (#6860), image metadata uses the exact uploaded bytes
and respects available decoders (#6858), automation deletion waits for
actual scheduler reconciliation (#6864), and blocking trust/skill reads stay
off the async executor (#6869). Preserve #6857's compaction regression.

Extend #6872's human-wait lifecycle guard to approval/elevation cards;
retire only the matching ended parent request and refresh activity only
after a delivered decision. Enforce configured finite approval deadlines in
the Engine, including deadline/cancellation races and durable receipts.

Serialize Native Windows ACL admission/retirement across Core processes
with a logon-scoped kernel mutex, preserving exact SID/object validation.
Add an actual child-process lock test; serialize DSH host tests in the
existing extension-host lane. Windows execution proof remains hosted CI.

Reconcile the vendored computer-use plugin with canonical main a656f67455fc
while preserving Core's 0.12.1 embedding contract. Canonical b47/a656 tree
passed Ubuntu/macOS/Windows source and package gates, including 28/28
Windows-focused tests and the controlled desktop fixture; this is separate
from the new Engine head's CI verdict.

Partial adaptation of the discovery-cache priority portion from PR #6393
by @AdityaVG13 (original ac33dd4). Preserve the best match under count
and byte limits without importing the unfinished echolocation/fork design;
the broader draft remains open.

Validation:
- npm test: 1286 passed, 0 failed, 7 skipped; web 767/767.
- npm run check:web: lint, typecheck and production build passed.
- Affected Rust selection: 801/803 initially passed; the two fixture/lifecycle
  expectation failures were corrected and each passed a focused rerun.
- Additional focused Rust: approval 28/28, discovery cache 11/11,
  OrcaRouter synthetic catalog 3/3, and 33/33 lifecycle/API/routing checks.
- Final CI-repair selection: 37/39 initially passed; the BMP feature-proxy
  and feature-registry summary failures were corrected; both corrected tests passed (2/2, 0 failures).
- Qualified Clippy: six packages, all targets/all features, passed with
  the CI style allowances. Portable no-default-feature check passed;
  portable policy verifier 6/6 passed; formatting and diff checks passed.
- Runtime contract: 55 measured metrics passed after explicit remeasurement;
  all 21 structural identities were unchanged. Twelve byte/token-estimate
  budgets account for bounded child-wait disclosure and contributor locale
  descriptions; no runtime field/prompt was removed to lower the budget.
- Persistence budget was not qualified locally: the checker requires a
  clean tree and this shared checkout retains an unrelated operator file.
  Clean hosted CI, fresh stamped build and real DeepSeek TUI acceptance
  remain required before the integration PR can merge to main.

Refs #6872, #6843, #6795.

Co-authored-by: Paulo Aboim Pinto <paulo.aboim.pinto@gmail.com>
Co-authored-by: hodeswildsmith455-boop <hodeswildsmith455-boop@users.noreply.github.com>
Co-authored-by: LIghtJUNction <lightjunction.me@gmail.com>
Co-authored-by: AdityaVG13 <adityavgcode@gmail.com>
Signed-off-by: CodeWhale Bot <bot@codewhale.net>
asto18089 added a commit to Pinvou/CodeWhale that referenced this pull request Oct 6, 2026
The endpoint smoke now exercises the delete-refusal contract (400
naming the reason, automation and run untouched, live automation has
no archive) and round-trips a seeded archived record through
?archived=true, which upstream merged red in codewhale-hq#6864. Manager-level
tests gain the running refusal arm, the canceled filter arm, exact
archived file names (created_at stamping, legacy normalization), and
a due-before positive control on the scheduler scan.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/CodeWhale that referenced this pull request Oct 16, 2026
The endpoint smoke now exercises the delete-refusal contract (400
naming the reason, automation and run untouched, live automation has
no archive) and round-trips a seeded archived record through
?archived=true, which upstream merged red in codewhale-hq#6864. Manager-level
tests gain the running refusal arm, the canceled filter arm, exact
archived file names (created_at stamping, legacy normalization), and
a due-before positive control on the scheduler scan.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/CodeWhale that referenced this pull request Oct 19, 2026
The endpoint smoke now exercises the delete-refusal contract (400
naming the reason, automation and run untouched, live automation has
no archive) and round-trips a seeded archived record through
?archived=true, which upstream merged red in codewhale-hq#6864. Manager-level
tests gain the running refusal arm, the canceled filter arm, exact
archived file names (created_at stamping, legacy normalization), and
a due-before positive control on the scheduler scan.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/CodeWhale that referenced this pull request Oct 21, 2026
The endpoint smoke now exercises the delete-refusal contract (400
naming the reason, automation and run untouched, live automation has
no archive) and round-trips a seeded archived record through
?archived=true, which upstream merged red in codewhale-hq#6864. Manager-level
tests gain the running refusal arm, the canceled filter arm, exact
archived file names (created_at stamping, legacy normalization), and
a due-before positive control on the scheduler scan.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
asto18089 added a commit to Pinvou/CodeWhale that referenced this pull request Oct 23, 2026
The endpoint smoke now exercises the delete-refusal contract (400
naming the reason, automation and run untouched, live automation has
no archive) and round-trips a seeded archived record through
?archived=true, which upstream merged red in codewhale-hq#6864. Manager-level
tests gain the running refusal arm, the canceled filter arm, exact
archived file names (created_at stamping, legacy normalization), and
a due-before positive control on the scheduler scan.

Signed-off-by: asto18089 <asto18089@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution-gate Author not yet in .github/APPROVED_CONTRIBUTORS; a maintainer grants access with /lgtm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants