Skip to content

feat(rc-v2): active-loop routes + service (W6-2) - #180

Merged
Ghenghis merged 1 commit into
feat/hermes3d-7-complete-gui-repo-wiringfrom
claude/w6-2-rc-v2-active-loop
May 10, 2026
Merged

Ghenghis merged 1 commit into
feat/hermes3d-7-complete-gui-repo-wiringfrom
claude/w6-2-rc-v2-active-loop

Conversation

@Ghenghis

Copy link
Copy Markdown
Owner

Summary

Ships commits 3-5 of Recovery Controller v2: the active loop beyond drills. After this PR the controller can orchestrate the full sequence
failure -> freeze -> propose -> review -> apply -> resume -> thaw without mocks in the source path. LLM provider calls go through swappable adapter callables; defaults raise ProviderNotConfigured so unconfigured deployments surface 503 with a generic message rather than leaking which env var is missing.

  • 4 new routes (POST under /api/code-operator/recovery/): /propose, /review, /apply, /resume
  • 4 new service methods: propose_fix, review_proposal, apply_proposal, resume_run
  • 8 integration tests, all passing (04_testing/pytest/integration/test_rc_v2_active_loop.py)
  • handoff doc: 03_implementation/docs/handoffs/HERMES_RC_V2_ACTIVE_LOOP_2026-05-09.md

PR #149 added commits 1+2 (state machine + freeze/thaw saga step 2). PR #154 added the read-only GET /recovery/runs route. PR #171 pinned cross-version saga semantics. PR #175 added the W5-5 drill that exercised the full sequence with mocks for fix/review/apply. W6-2 wires the actual route + service surface those drills proved out, so the loop can now run for real.

Saga compensation rule

Apply failure (when code_history.apply_reviewed_patch_proposal raises):

  1. recovery_apply_failed proof event written with redacted error class + summary.
  2. mark_recovery_outcome(status="retry_failed", ...) closes v1 ledger row.
  3. Run transitions APPLYING -> RETRY_FAILED (terminal); proposal stays addressable for forensic review.
  4. File locks remain held until operator-driven thaw_run (or 30 min TTL).

Test plan

  • 8/8 W6-2 integration tests pass: pytest 04_testing/pytest/integration/test_rc_v2_active_loop.py
  • All existing recovery tests still pass (29 passed, 1 skipped):
    • test_recovery_controller_freeze.py
    • test_recovery_controller_cross_version.py
    • test_recovery_runs_route.py
    • test_recovery_loop_drill.py
    • test_rc_v2_active_loop.py (new)
  • No real LLM calls in test path (all adapters mocked via monkeypatch.setattr on _minimax_adapter / _deepseek_adapter)
  • No paid services: every mocked LLM call carries credit_spent_usd: 0.0
  • No secrets in any code or doc; 503 message intentionally generic

Sources

  1. Saga pattern -- Garcia-Molina, H. & Salem, K. (1987). Sagas. ACM SIGMOD Record, 16(3): 249-259. Compensation rule for apply_proposal failure: rollback to RETRY_FAILED, locks held until operator review; proposal remains addressable. Reference: https://temporal.io/blog/saga-pattern-made-easy
  2. FastAPI bigger-applications router pattern -- the four new routes are appended to the existing code_operator APIRouter instance because they share the same prefix, tags, and validation chain. https://fastapi.tiangolo.com/tutorial/bigger-applications/

Hermes evidence chain: PASS

  • Task ID: W6-2-RC-V2-ACTIVE-LOOP-2026-05-09
  • hermes_run_gate: pytest 04_testing/pytest/integration/test_rc_v2_active_loop.py -- 8 passed
  • Lock owner: claude-w6-2-rc-active-loop
  • Files locked (released on PR open):
    • 03_implementation/src/hermes3d/services/recovery_controller.py
    • 03_implementation/src/hermes3d/api/routes/code_operator.py
    • 04_testing/pytest/integration/test_rc_v2_active_loop.py
    • 03_implementation/docs/handoffs/HERMES_RC_V2_ACTIVE_LOOP_2026-05-09.md

🤖 Generated with Claude Code

…apply->resume)

Ships commits 3-5 of Recovery Controller v2: the active loop beyond drills.
After this PR the controller can orchestrate the full sequence
failure -> freeze -> propose -> review -> apply -> resume -> thaw without
mocks in the source path. LLM provider calls go through swappable adapter
callables (`_minimax_adapter` / `_deepseek_adapter`); defaults raise
ProviderNotConfigured so unconfigured deployments surface 503 with a
generic message rather than leaking which env var is missing.

Routes (POST, all under /api/code-operator/recovery/):
  * /propose -- 200 ProposalRecord | 503 provider_not_configured | 409 state
  * /review -- 200 ReviewRecord(approved/rejected/needs-revision)
  * /apply -- requires confirm=true + verdict=approved; 502 on apply failure
              after saga compensation has run
  * /resume -- runs the original gate via run_mcp_gate; green->RECOVERED,
               red->ESCALATED; both paths thaw_run to release file locks

Service (recovery_controller.py): four new methods (propose_fix,
review_proposal, apply_proposal, resume_run), a `ProviderNotConfigured`
exception, swappable module-level adapter callables, version-tagged
proof events per phase via the post-PR #168 helper.

Saga compensation rule (Garcia-Molina + Salem 1987): apply failure ->
mark_recovery_outcome("retry_failed") + transition APPLYING -> RETRY_FAILED;
proposal stays addressable for forensic review; locks remain held until
operator-driven thaw or 30 min TTL.

Tests: 04_testing/pytest/integration/test_rc_v2_active_loop.py (8/8 pass).
All adapters mocked via monkeypatch on module-level callables; every
mocked LLM call carries credit_spent_usd: 0.0 per the no-paid-services
rule. No real LLM calls in the test path.

Doc: 03_implementation/docs/handoffs/HERMES_RC_V2_ACTIVE_LOOP_2026-05-09.md
covers route surface + auth + data flow + operator setup + saga
compensation + 2 sources cited.

Sources:
1. Saga pattern (Garcia-Molina + Salem 1987):
   https://temporal.io/blog/saga-pattern-made-easy
2. FastAPI bigger-applications router pattern:
   https://fastapi.tiangolo.com/tutorial/bigger-applications/

Hermes evidence chain: PASS
Task ID: W6-2-RC-V2-ACTIVE-LOOP-2026-05-09
hermes_run_gate: pytest 04_testing/pytest/integration/test_rc_v2_active_loop.py -- 8 passed

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented May 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eca60773-aa48-4153-ae33-807a7ea7a074

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/w6-2-rc-v2-active-loop

Comment @coderabbitai help to get the list of available commands and usage tips.

@Ghenghis
Ghenghis merged commit cb15d9c into feat/hermes3d-7-complete-gui-repo-wiring May 10, 2026
1 check passed
@Ghenghis
Ghenghis deleted the claude/w6-2-rc-v2-active-loop branch May 10, 2026 04:38
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