This commit is contained in:
commit
8f085a28d3
3220 files changed
+985495
No files matched your search
@@ -0,0 +1 @@
|
||||
{"body": "[Claude #12] Stage 3 code-edit — IMP-33 #61 (R8 u8)\n\nExecuting unit: u8\n\n■ unit_executed\n- id: u8\n- summary: Step 12 AI repair wiring (`src/phase_z2_ai_fallback/step12.py`). New module-level entry `gather_step12_ai_repair_proposals(units, *, route_for_label, get_contract_fn, frame_visual_loader, ...)` layers two structural gates on top of u7 router: (1) IMP-30 provisional gate — units with `provisional=False` are skipped before any route classification (per Stage 2 \"Step 12 IMP-30 provisional only\"); (2) reject gate — units whose V4 label maps to `design_reference_only` are skipped with `skip_reason=\"design_reference_only_no_ai\"` and NEVER call AI (per Stage 2 \"reject remains design_reference_only and no-AI\"). For provisional + `ai_adaptation_required` units, the helper assembles the u7 router inputs (cache_key, v4_result, frame_contract, frame_visual_html, figma_partial_json, internal_region, mdx_text) and invokes `route_ai_fallback(...)` once per unit. Save is NOT performed here — caller-driven AFTER visual_check + user_approved (u6 IMP-46 gate).\n\n■ files_changed\n- src/phase_z2_ai_fallback/step12.py (NEW, 141 lines incl. docstrings)\n- tests/phase_z2_ai_fallback/test_step12.py (NEW, 193 lines, 9 tests)\n\n■ diff_summary\n- `src/phase_z2_ai_fallback/step12.py`:\n - Module path locked by IMP-31-GATE-AUDIT (`src/phase_z2_ai_fallback/`, Stage 1 binding).\n - Module-level constants `_AI_ADAPTATION_ROUTE = \"ai_adaptation_required\"` and `_DESIGN_REFERENCE_ROUTE = \"design_reference_only\"` (mirrors `src/phase_z2_pipeline.py:572-576` `_IMP05_ROUTE_HINTS`).\n - Single import from the fallback package: `route_ai_fallback` (u7). NO Anthropic import, NO `messages.create()` call, NO `save_proposal` import (caller-only per u6 contract), NO MDX I/O (caller supplies loaded artifacts).\n - `gather_step12_ai_repair_proposals(units, *, route_for_label, get_contract_fn, frame_visual_loader, figma_partial_loader=None, internal_region_lookup=None, mdx_text_loader=None) -> list[dict]`:\n 1. Per-unit record schema is stable across every gate decision: `{unit_index, source_section_ids, frame_template_id, label, route_hint, provisional, ai_called, skip_reason, proposal, error}` — downstream Step 12 artifact consumers can rely on a single shape.\n 2. Provisional gate (FIRST): `if not unit.provisional: skip_reason=\"not_provisional\"; continue`. IMP-30 first-render survivors are the only path AI repair can touch.\n 3. Reject gate: `if route_hint == _DESIGN_REFERENCE_ROUTE: skip_reason=\"design_reference_only_no_ai\"; continue`. Reject = design reference only, NEVER AI (per Stage 2 + `feedback_ai_isolation_contract`).\n 4. Non-AI route catch-all: `if route_hint != _AI_ADAPTATION_ROUTE: skip_reason=f\"route_not_ai_adaptation:{route_hint}\"; continue`. Defence-in-depth against future route_hints.\n 5. AI path: build `cache_key = f\"{template_id}::{','.join(sorted(source_section_ids))}\"`, assemble `v4_result = {route, label, frame_id, rank, cardinality}`, resolve `frame_contract` via `get_contract_fn`, `frame_visual_html` via `frame_visual_loader`, optional `figma_partial_json` / `internal_region` / `mdx_text` via injected loaders (raw_content fallback). Call `route_ai_fallback(...)` inside try/except. RuntimeError / API errors → record `ai_called=True`, `error=f\"{type(exc).__name__}: {exc}\"` (no re-raise — pipeline can continue per-unit). `proposal is None` → `skip_reason=\"router_short_circuit\"` (flag-off or route-mismatch inside u7). Non-None → `proposal=proposal.model_dump()`.\n - Save-to-cache responsibility is explicitly NOT in this module — only u6 `save_proposal` (which the helper does not import) can persist proposals, and only AFTER visual_check + user_approved gates.\n- `tests/phase_z2_ai_fallback/test_step12.py` — 9 focused tests covering every Stage 2 axis u8 owns:\n - `test_non_provisional_unit_is_skipped_without_ai_call` — IMP-30 provisional gate; `router.assert_not_called()`.\n - `test_reject_route_is_skipped_without_ai_call` — label=\"reject\" (route_hint=design_reference_only) NEVER calls router; `router.assert_not_called()`.\n - `test_non_ai_route_is_skipped_with_reason` — label=\"light_edit\" (deterministic_minor_adjustment) records skip_reason and does NOT call router.\n - `test_router_short_circuit_returns_none_skip_reason` — router returns None (flag-off / route-mismatch surface) → `ai_called=False`, `skip_reason=\"router_short_circuit\"`.\n - `test_ai_adaptation_call_records_proposal` — label=\"restructure\" + provisional=True → `ai_called=True`, proposal serialized via `model_dump()`, router called with `v4_result.route == \"ai_adaptation_required\"`.\n - `test_router_exception_is_captured_per_record` — `RuntimeError(\"transient_boom\")` → `ai_called=True`, `error=\"RuntimeError: transient_boom\"`, no re-raise.\n - `test_mixed_units_each_independently_classified` — 4-unit mix (use_as_is non-pLine truncated
|
||||
Reference in new issue
Block a user