Skip to content

[#24] Narrow bare except in ApiExecutor + synthesize_overviews_api; doc xbrain diff#31

Merged
VGonPa merged 2 commits into
developfrom
ws-24-narrow-except
May 23, 2026
Merged

[#24] Narrow bare except in ApiExecutor + synthesize_overviews_api; doc xbrain diff#31
VGonPa merged 2 commits into
developfrom
ws-24-narrow-except

Conversation

@VGonPa
Copy link
Copy Markdown
Owner

@VGonPa VGonPa commented May 23, 2026

Closes #24.

Summary

Two changes in one PR — both small, both follow-ups to the prior review pipelines:

Doc fix (#18 follow-up)

ARCHITECTURE.md gains a new "Snapshot diffing" section that actually explains what xbrain diff does. Until now the module appeared only in the file-tree at "Where things live"; spec-compliance reviewer on PR #28 flagged the gap. The new section covers:

  • Report shape (Items / Topics / Vocab / Summary)
  • Why TF cosine over TF-IDF or embeddings (no new deps, IDF degenerates on N=2)
  • The 5-member growth floor + Latin-1 tokenizer
  • JSON vs text output
  • How diff is the foundation for drift monitoring + WS3 eval (WS3 — enrichment evaluation harness #8)

Narrow bare-except (#24 main scope)

ApiExecutor.enrich_items and synthesize_overviews_api had except Exception as exc: print(warn:...); continue. Surfaced by silent-failure-hunter on PR #23 and #29 as a pre-existing issue.

Before: every exception including AttributeError, KeyboardInterrupt, anthropic.AuthenticationError was swallowed. A 100%-broken run printed N warn-lines and exited 0.

After:

  • New _recoverable_errors() tuple: (anthropic.APIError, ValueError, json.JSONDecodeError, KeyError). Lazy-imported because anthropic is optional in some test setups.
  • Per-item / per-topic failure counter.
  • RuntimeError raised when EVERY input failed (successes == 0 and failures > 0) — CLI's _handle_cli_errors catches RuntimeError and exits 1 cleanly.
  • Partial-failure summary line on stderr (enriched: N, failed: M).
  • Programmer bugs (AttributeError) and KeyboardInterrupt propagate.

Tests

4 new in total (2 per module):

  • test_api_executor_raises_when_all_items_fail — total failure raises RuntimeError.
  • test_api_executor_propagates_programmer_bugsAttributeError is not caught.
  • Same two for synthesize_overviews_api.
  • Existing partial-failure tests updated to use anthropic.APIError instead of RuntimeError + assert the new summary line.

Total: 352 tests (up from 348), coverage 89%, uv run poe check all-green.

Specs

  • PRD: vault/zz-support-files/docs/prds/2026-05-23-xbrain-24-narrow-bare-except.md
  • (No separate plan file — XS sizing, the PRD acceptance criteria carry the plan.)

Test plan

  • Total-failure raises RuntimeError → CLI exits 1
  • Partial-failure preserves successes + prints summary
  • Non-recoverable errors propagate (AttributeError test)
  • uv run poe check all-green
  • ARCHITECTURE.md xbrain diff explainer

🤖 Generated with Claude Code

VGonPa and others added 2 commits May 23, 2026 10:42
…f in ARCHITECTURE

Closes #24. Two changes in one PR:

1) ARCHITECTURE.md — new "Snapshot diffing" section explaining xbrain diff
(#18) end-to-end. The module was listed in "Where things live" but had no
narrative. Now covers: what the report contains (Items / Topics / Vocab /
Summary), the pure-Python TF cosine choice and rationale (no new deps,
IDF degenerates on N=2), the 5-member growth floor, JSON vs text output,
and how diff is the foundation for drift monitoring + WS3 eval (#8).

2) ApiExecutor.enrich_items + synthesize_overviews_api — narrow the
catch-everything except, count failures, raise on total-failure batches.

The pre-fix behaviour:
- `except Exception as exc:` swallowed every exception including
  AttributeError, KeyboardInterrupt, anthropic.AuthenticationError, etc.
- A 100%-broken run printed N warn-lines and exited 0. The CLI's
  downstream commands (xbrain topics, xbrain generate) silently consumed
  the empty result. The user got a stale wiki without a signal.

The fix:
- New `_recoverable_errors()` tuple per module:
  (anthropic.APIError, ValueError, json.JSONDecodeError, KeyError).
  `pydantic.ValidationError` is a ValueError subclass, covered.
  Lazy-imported because `anthropic` is optional in some test setups.
- Per-item / per-topic failure counter.
- `RuntimeError` raised when every input failed (`successes == 0 and
  failures > 0`) — CLI's _handle_cli_errors catches RuntimeError →
  clean exit-1.
- Partial-failure summary line printed to stderr (`enriched: N, failed: M`
  / `synthesized: N, failed: M`).
- Programmer bugs (AttributeError, ...) and KeyboardInterrupt now
  propagate — Ctrl-C works again during development, tracebacks surface.

Tests (4 new):
- `test_api_executor_skips_item_on_api_failure` (updated): uses
  anthropic.APIError + asserts the partial-failure summary line.
- `test_api_executor_raises_when_all_items_fail` (new): every call raises
  APIError → RuntimeError("All N items failed enrichment").
- `test_api_executor_propagates_programmer_bugs` (new): AttributeError
  propagates instead of being swallowed.
- Same three for synthesize_overviews_api in test_topic_synth.py.

Total: 352 tests (up from 348), coverage 89%, `uv run poe check` all-green.

PRD: vault/zz-support-files/docs/prds/2026-05-23-xbrain-24-narrow-bare-except.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Addresses the actionable findings from PR #31's 3-reviewer panel
(code-reviewer SHIP IT; silent-failure-hunter + test-analyzer
flagged improvements):

silent-failure-hunter M2 — partial-failure summary line was
indistinguishable from the per-item `warn:` lines that precede it. A
1000-item batch with 50 failures buried the single summary at the end
of 50 noise lines.
- Prefix with `SUMMARY:` so the line stands out. Trivial.
- Existing partial-failure asserts updated accordingly.

test-analyzer gap #1 (rating 7) — KeyboardInterrupt propagation was
implicitly correct (KeyboardInterrupt is a BaseException, not Exception,
so the narrow tuple naturally excludes it) but no regression test
pinned it. A future refactor that widens the catch to BaseException
would silently break Ctrl-C.
- New `test_*_propagates_keyboard_interrupt` for both modules.

test-analyzer improvement #2 (rating 5) — no negative assert that the
all-failed branch does NOT print the summary line (it raises first; a
future refactor that moves the print above the raise would slip).
- New `test_*_emits_no_summary_on_total_failure` for both modules.

test-analyzer improvement #3 (rating 4) — no negative assert that the
all-succeed path stays silent on stderr.
- New `test_*_emits_no_summary_when_all_succeed` for both modules.

Skipped: silent-failure M1 (`except ImportError` opacity for a
misinstalled anthropic SDK). The reviewer themselves noted it is
"actually safe (loud failure)" since downstream code would propagate
the SDK error as a bug rather than catch it silently. Borderline,
non-blocker.

Total: 358 tests (up from 352), coverage 89%, `uv run poe check`
all-green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@VGonPa VGonPa merged commit b137f92 into develop May 23, 2026
1 check passed
@VGonPa VGonPa deleted the ws-24-narrow-except branch May 23, 2026 09:29
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