Skip to content

feat: Phase 2 automatic isolated Firebreak closed loop - #3

Merged
9thLevelSoftware merged 2 commits into
mainfrom
feat/phase-2-auto-firebreak
Aug 5, 2026
Merged

feat: Phase 2 automatic isolated Firebreak closed loop#3
9thLevelSoftware merged 2 commits into
mainfrom
feat/phase-2-auto-firebreak

Conversation

@9thLevelSoftware

Copy link
Copy Markdown
Owner

Summary

Implements Phase 2 of the production plan: automatic isolated Firebreak closed loop with approval queue.

When a run completes OutOfControl (correct but exceeds containment) with authorized reviewers configured:

  1. Select authorized reviewer
  2. Open isolation workspace
  3. Invoke reviewer backend (generate_with_backend)
  4. Re-verify candidate with the same verification plan
  5. Rank with absolute tree metrics (consistent original vs candidate)
  6. If smaller + within containment + floor pass:
    • Sensitive / require_firebreak_approvalAwaitingApproval (tif approve|reject)
    • Else if auto_apply_firebreak (default true) → apply with baseline + sticky restore
  7. Persist isolation session before apply; audit outcomes; adaptation record
  8. Fail-safe always: never apply unverified / larger / out-of-containment candidates

Key changes

  • RunOrchestrator::run_firebreak_auto production path (not permanently fail-closed when backends exist)
  • Config: approval.auto_apply_firebreak (default true), optional approval_ttl_hours
  • CLI: tif firebreak --auto, tif approve <run_id>, tif reject <run_id>
  • Apply prefers session.candidate_path (reviewer output); skips .tif-candidate on overlay
  • Adaptation stats persisted in local SQLite (tif adaptation)
  • Docs: ROADMAP Phase 2 Done, CHANGELOG, schema, protocol, threat model

Test plan

  • cargo fmt --all
  • cargo clippy --workspace --all-features -- -D warnings
  • cargo test --workspace --all-features (114 tests)
  • E2E mock: oversized metrics → generate → re-verify → apply → rollback
  • Failed backend preserves source
  • Larger candidate not applied
  • Approval required path does not auto-apply; approve applies after re-check

Manual smoke (optional)

# with mock reviewer + auto_apply_firebreak
tif run begin --task ""
tif run complete <id> --auto-firebreak --deps-added 1 …
tif approve <id>   # if AwaitingApproval
tif reject <id>
tif rollback <id>

Safety

  • Correctness floor never lowered
  • Egress still enforced; process env scrub remains
  • Simulated metrics never authorize apply

Copilot AI lite review requested due to automatic review settings August 5, 2026 04:08

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@9thLevelSoftware
9thLevelSoftware merged commit d7eb8cc into main Aug 5, 2026
8 checks passed

@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: 826e1573ac

ℹ️ 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 thread crates/tif/src/main.rs
authorize_apply: authorize,
user_approved: false,
},
)?;

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 Persist auto Firebreak state before propagating apply errors

In the auto reviewer branch, the ? here exits before the post-call record_run when run_firebreak_auto returns an apply error. That method can already have preserved a baseline and set restore_pending on the session, so the audit DB still contains only the pre-call record without isolation_session/baseline_path; a subsequent tif rollback cannot locate the recovery data for a partially modified workspace. Capture the result, record the mutated run, then propagate the error as the explicit-candidate path does.

Useful? React with 👍 / 👎.

Comment thread crates/tif/src/main.rs
// Phase 2 automatic closed loop when --auto or reviewers are configured.
// Persist before apply is handled inside the closed loop (session attach).
store.record_run(&run)?;
let authorize = authorize_apply || auto || cfg.approval.auto_apply_firebreak;

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 Do not let --auto override disabled auto-apply

When a repo sets [approval].auto_apply_firebreak = false, tif run complete --auto-firebreak honors it by passing authorize_apply=false, but tif firebreak --auto sets authorization to true because auto is ORed in here. A smaller non-sensitive candidate will therefore be applied even though the repository explicitly disabled automatic Firebreak apply; --auto should start the closed loop, not bypass the approval policy.

Useful? React with 👍 / 👎.

Comment on lines +554 to +557
let requires_approval = !req.user_approved
&& (req.force_approval
|| req.policy.require_firebreak_approval
|| touches_sensitive(&req.policy, &req.candidate_metrics));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Hold verified candidates for approval when auto-apply is disabled

For automatic flows that pass authorize_apply = config.approval.auto_apply_firebreak, setting auto_apply_firebreak=false produces a smaller verified candidate with apply authorization turned off, but this approval predicate still returns false unless the candidate is sensitive or approval is globally required. The outcome becomes candidate_ready/requires_approval=false, so finalize_firebreak immediately restores instead of entering AwaitingApproval, leaving tif approve unable to apply the held candidate.

Useful? React with 👍 / 👎.

.unwrap_or("unknown"),
reviewer_id: fb.and_then(|f| f.reviewer_id.as_deref()),
};
eng.record_run(outcome);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Make adaptation recording idempotent per run

This appends aggregate counters every time a run is recorded, but the new CLI calls it after run complete, again after firebreak, and again after approve/rollback for the same run. A single run that goes OutOfControl → AwaitingApproval → Applied is counted as multiple total runs and multiple outcomes, skewing the fire-level and reviewer recommendations; persist per-run adaptation state or update the aggregate idempotently by run id.

Useful? React with 👍 / 👎.

@9thLevelSoftware
9thLevelSoftware deleted the feat/phase-2-auto-firebreak branch August 5, 2026 20:26
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