Skip to content

feat(bap): classify crash-recovery side-effect outcomes - #214

Draft
seonghobae wants to merge 26 commits into
feat/bap-idempotency-receipt-contractfrom
feat/bap-recovery-outcome-classification
Draft

feat(bap): classify crash-recovery side-effect outcomes#214
seonghobae wants to merge 26 commits into
feat/bap-idempotency-receipt-contractfrom
feat/bap-recovery-outcome-classification

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Scope

Bounded partial implementation of #200, stacked on canonical BAP idempotency owner PR #211. This Draft makes crash-recovery side-effect ambiguity explicit, binds every classification to the exact accepted command receipt and a canonical SHA-256 recovery-evidence identity, and keeps redispatch eligibility fail closed. It does not authenticate recovery evidence, prove that an external side effect occurred, provide durable deduplication, persist evidence, or grant tenant, policy, destination, secret, browser, approval, dispatch, or release authority.

Recovery contract

BapExternalSideEffectOutcome distinguishes ConfirmedNoSideEffect, ConfirmedSideEffect, UnknownOutcome, and ReconciliationRequired.

BapCommandRecovery retains the exact immutable BapCommandReceipt, the external side-effect classification, and a validated BapRecoveryEvidenceDigest in exact sha256: + 64-lowercase-hex form. The digest identifies the durable evidence object supporting the classification; possession of that identity does not authenticate the evidence, prove the classification, or authorize retry.

permits_redispatch() first validates the receipt against the lifecycle's exact latest accepted transition. Stale, foreign, state-only restored, or divergent-history receipts fail closed through the typed receipt contract. Terminal lifecycle states return Ok(false) even for ConfirmedNoSideEffect. An exact receipt whose accepted lifecycle state is ReconciliationRequired also returns Ok(false): an explicit reconciliation hold cannot be bypassed merely because later recovery evidence classifies the interrupted external operation as having caused no side effect. Resolving the hold is a separate lifecycle transition, which makes the retained hold receipt stale for subsequent replay. Any Ok(true) remains only an eligibility signal requiring independent evidence authentication and complete current-authority revalidation before dispatch.

Test-first repair lineage

Earlier stale-receipt, terminal-state, and recovery-evidence binding RED/repair heads on this canonical branch remain historical regression lineage only.

The current run reproduced a further recovery-integrity defect on exact head be3186e1a016275fbf67c7a3da278b11d73a6b87: after an accepted RequireReconciliation transition, ConfirmedNoSideEffect could still make permits_redispatch() return true because ReconciliationRequired is intentionally non-terminal. The realistic regression reconciliation_hold_never_signals_redispatch_before_explicit_resolution failed in CI run 32909362190, Rust contracts job 98000207386, at the test boundary after compilation/formatting had succeeded.

The smallest production repair keeps an exact ReconciliationRequired lifecycle non-replayable while preserving typed stale/foreign receipt errors and all existing terminal-state behavior. The repaired exact head is 8a3463bdb224f1c1226811f88c3d6f3a15d96f8f.

The current stack remains based directly on live #211 head 6ce74587dcfeede71ad6ceea94fe5c72dc0f244a; fresh comparison reports merge base exactly #211, 26 commits ahead / 0 behind. No parent/predecessor evidence transfers.

Exact-current verification

On unchanged exact head 8a3463bdb224f1c1226811f88c3d6f3a15d96f8f against exact live base 6ce74587dcfeede71ad6ceea94fe5c72dc0f244a:

  • protected main: b05d5acca82b9d916ada2c8e82f59f92a89817e1;
  • GitHub reports the PR open, Draft, and mergeable;
  • CI run 32909622402 / Rust contracts job 98001004079: success, including repository contracts, formatting, workspace check, tests, Clippy, and public API documentation;
  • CI run 32909622402 / Production coverage job 98001003929: success;
  • exact coverage artifact 9586099099, digest sha256:8862dd2cfa54ae3fc56f996dfe505dd790fe9c03ddc0ce777f273bd99e3e2c9f;
  • exact owned-production coverage: functions 482/482 = 100%, lines 4084/4084 = 100%, regions 5012/5012 = 100%, branches 584/584 = 100%;
  • fresh formal-review inventory: no submitted reviews;
  • fresh inline-review-thread inventory: no review threads; and
  • fresh exact-head check-run inventory exposes only the two successful CI jobs above.

Same-head SAST, Security Scan, Manifest V3, Noema, Strix, Dependabot, and any other absent gate are not claimed. Historical predecessor checks/reviews/statuses/comments/model output are not promoted to this head.

Stack / authority

This PR remains Draft while #211/#208 remain active. Parent/predecessor checks and reviews do not transfer to this child. Protected-main AGENTS.md remains authoritative: this scheduled writer does not merge, self-approve, force-push, destructively rebase, alter workflows/rulesets/secrets, tag, release, or publish.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

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.

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.

1 participant