Good. The diff matches what was provided. Now here's the review:

---

### CLAUDE.md (new file)
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: UNRELATED
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: N/A
INTEGRATION: N/A
REASONING: Standard project documentation file. Content is reasonable. Not related to the issue but harmless.
---

### ftl_project_expert/cli.py:summary (reasons.db path)
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: ADDRESSES
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The `reasons list` call now uses `--status IN --by-impact`, both of which are confirmed valid flags (verified via `reasons list --help`). Filtering to IN-only beliefs is sensible — OUT beliefs shouldn't contribute to a summary. Sorting by impact (dependent count descending) means the top-500 cap retains the most structurally important beliefs. The truncation logic is correct: `total_count` captures the full line count, then `lines` is sliced to `max_beliefs` before joining. `belief_count` correctly reflects the post-truncation count. The only caller of `build_summary_prompt` is updated with the new `total_count` parameter.
---

### ftl_project_expert/cli.py:summary (beliefs.md path)
VERDICT: CONCERN
CORRECTNESS: QUESTIONABLE
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: PARTIAL
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The `beliefs.md` truncation uses `re.split(r"(?=^### \S+)", full_text, flags=re.MULTILINE)` to split by `### ` headers, then takes the first 500 sections. Two issues: (1) Unlike the reasons.db path which sorts by impact, the beliefs.md path has no ranking — it just takes the first 500 sections in file order, which may not be the most important. The user-facing message says "by impact" but that's only true for the reasons path. (2) Any content before the first `### ` header (e.g., a preamble, title, or metadata) gets treated as section 0 and counts toward the 500 limit. This is a minor concern since the preamble is typically small, but it means the count could be off by one compared to the actual belief count. The issue mentions the failure occurred with `reasons.db` (10,822 beliefs), so the `beliefs.md` path is a secondary fix, but the "by impact" claim in the status message at line 2067-2070 is misleading for this code path — it should say "first" or "by file order" when coming from beliefs.md.
---

### ftl_project_expert/cli.py:summary (error reporting)
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: ADDRESSES
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The error message now includes the prompt size in KB and the model name, directly addressing issue suggestion #4 ("Report the actual failure clearly"). `prompt_size_kb` is computed before the `invoke()` call so it's available in the exception handler. This is a meaningful diagnostic improvement — the original error was `Model claude failed:` with no size context.
---

### ftl_project_expert/prompts/summary.py:build_summary_prompt
VERDICT: PASS
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: ADDRESSES
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED
REASONING: The new `total_count` parameter has a default of 0, maintaining backward compatibility (though there are no other callers). The conditional logic is correct: when `total_count > belief_count`, the LLM is told it's seeing a subset ranked by impact. This is important context for the LLM so it doesn't assume the belief set is exhaustive. The prompt text is well-structured.
---

### Overall assessment
VERDICT: CONCERN
CORRECTNESS: VALID
SPEC_COMPLIANCE: N/A
ISSUE_COMPLIANCE: ADDRESSES
BELIEF_COMPLIANCE: N/A
TEST_COVERAGE: UNTESTED
INTEGRATION: WIRED

**Summary**: The changes directly address the root cause described in the issue — massive prompt size from passing all 10k+ beliefs to the LLM. The fix is pragmatic: filter to IN beliefs, sort by impact, cap at 500. The `reasons` CLI flags are confirmed valid. The error reporting improvement is useful.

**Key concerns**:

1. **No tests** — Neither the summary function nor `build_summary_prompt` has any test coverage (confirmed by observations). For a fix targeting a production failure, at minimum a unit test for `build_summary_prompt` with `total_count > belief_count` and a test verifying the truncation logic would be appropriate.

2. **Misleading "by impact" message for beliefs.md path** — When beliefs come from `beliefs.md` (not `reasons.db`), the status message claims "by impact" but the truncation is actually by file order. This is a minor UX inaccuracy.

3. **Magic number** — `max_beliefs = 500` is hardcoded with no CLI flag or config option to override it. For a first pass this is acceptable, but users with different context window sizes or models may want to tune this.

---

### SELF_REVIEW
LIMITATIONS: I verified the `reasons list` CLI flags exist but could not test the actual subprocess behavior with a large belief network. I could not verify whether 500 beliefs consistently fits within Claude CLI input limits — the cap is a reasonable heuristic but not validated against actual token counts. I also could not see the `invoke()` function to verify whether it provides any additional error context that the new error message might duplicate.
---

### FEATURE_REQUESTS
- Include the `invoke()` / `llm.py` function body in observations when it's referenced in the error handling path — the review needs to verify what exceptions it raises and what context they already include.
- When a diff modifies subprocess calls with new CLI flags, automatically verify those flags exist (e.g., by checking the target CLI's `--help` output or argparse definitions).
---
