crafting-table/crafting_table
Kayos 3273d66003 patcher: robust extract_diff_json — handles 5 model-output shapes
The 4 patcher-fired-but-malformed_response failures showed extract_diff_json
was too strict: it required {"diff": "..."} as the top-level JSON shape
with at most 1 brace nesting depth (regex-based). Real model output
varies more.

Now handles:
1. Bare JSON {"diff", "explanation", "confidence"}
2. Fenced JSON: ```json {…} ```
3. Fenced diff + prose: ```diff …unified diff… ``` + loose explanation
4. Bare unified diff (no JSON wrapper, no fence)
5. JSON with deeply-nested {} inside the diff string (struct literals,
   function bodies)

Fixes:
- Replaced regex-based balanced-{} matcher (capped at depth 1) with a
  string-aware depth-tracking generator that handles arbitrary nesting
  + skips brace chars inside JSON string literals
- Walk all fenced blocks not just the first; recognize ```diff and
  ```patch language tags
- Fall back to fenced-diff-with-prose construction when no JSON form
  matches — synthetic payload with surrounding text as explanation
- Final fallback for bare unified diffs (no fence, no wrapper) using a
  simple line-prefix detector
- Normalize alternate keys (patch, content, diff_text → diff)
- Always set confidence (defaults to medium when absent, low for bare
  diffs that have no model commentary)

Tests: 16 → 20 (5 new shape coverage tests). All green.
2026-04-29 15:37:24 -07:00
..
parsers v0.1 wave 2A (steps 5+6): per-language parsers + findings extraction 2026-04-29 08:36:16 -07:00
__init__.py v0.1 wave 2A (steps 5+6): per-language parsers + findings extraction 2026-04-29 08:36:16 -07:00
auth.py v0.1 wave 1 (steps 2+3+4): SQLite ledger + FastAPI skeleton + async job runner 2026-04-29 08:17:41 -07:00
config.py v0.1 wave 1 (steps 2+3+4): SQLite ledger + FastAPI skeleton + async job runner 2026-04-29 08:17:41 -07:00
db.py v0.1 wave 3 (steps 9+10): autonomous patch loop + production recipes 2026-04-29 09:04:48 -07:00
digest.py v0.1 wave 3 (steps 9+10): autonomous patch loop + production recipes 2026-04-29 09:04:48 -07:00
models.py v0.1 wave 2C (step 8): email digest scheduler 2026-04-29 08:33:37 -07:00
patcher.py patcher: robust extract_diff_json — handles 5 model-output shapes 2026-04-29 15:37:24 -07:00
runner.py v0.1 wave 2A (steps 5+6): per-language parsers + findings extraction 2026-04-29 08:36:16 -07:00
server.py v0.1 wave 3 (steps 9+10): autonomous patch loop + production recipes 2026-04-29 09:04:48 -07:00
workspace.py workspace: explicit fetch right after bare clone (populates remote-tracking refs that --bare doesn't) 2026-04-29 13:58:28 -07:00