feat(llm): hypothesis-edge suggestion through the corpus firewall (26 H.4)#173
Merged
bryanmatthewsimonson merged 2 commits intoJul 18, 2026
Conversation
… H.4)
Phase 26 slice H.4 (docs/HYPOTHESIS_MAP_DESIGN.md §3) — completes the
hypothesis-map ladder (H.5 wire kind stays deferred).
Shape decision (documented in corpus-prompts.js): one REDUCE-shaped
call over the dossier digest + the map's hypothesis rows — no
per-member map re-run. The digest's claims index is the id-authority
(the 20.6 discipline), and an edge's quote grounds against the
REFERENCED CLAIM's own verbatim text+quote rather than a member
article — stricter and local.
- corpus-prompts.js — propose_hypothesis_edges tool (NO numeric slot,
machine-checked) + system prompt with the both-sides requirement
('propose for EVERY hypothesis, on BOTH sides') and the never-pick
rule; hyp-edges-v1 version pin.
- llm-client.js runHypothesisEdgePass — same triple gate as the corpus
passes (caseSynthesis + llmAssist + key, re-checked in the worker),
forced tool_choice, RAW tool output returned; max_tokens stop is an
error, never truncated parsing.
- background: xray:llm:hypothesis-edges message.
- hypothesis-suggest.js (pure) — validate (schema-walker) → ground
(quote must locate in the claim's own record; drops disclosed) →
filter (ids resolve against the SAME set the digest was built from;
dup-vs-existing rejected with reason; batch dups silent) →
unopposedHypotheses (the both-sides post-check, disclosed as
'unexamined, not established', never auto-retried or scored).
- Portal: gated 'Suggest edges (LLM)…' beside Add hypothesis —
spend-confirm naming claim+hypothesis counts, per-proposal
Accept/Dismiss (nothing auto-applies), accepted records stamped
suggested_by 'llm:<model>', seeds promoted at accept, disclosure
line (checked/dropped/rejected), rejected rows shown with reasons.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 16, 2026
Closed
Confirmed findings from the multi-agent review of the H.2..H.4 diff: - Delete-hypothesis confirm stated the TRUNCATED edge count (the view model caps sections at 12) while delete removes them all. Cards now carry the uncapped per-role coverage counts and the confirm uses them. - groundEdgeQuotes indexed text+quote as ONE concatenated string, so a model quote straddling the boundary grounded via the normalized tier and persisted a stitched span that appears in neither field. The two fields are indexed separately; a straddling quote drops (tested). - A second Suggest run used the map captured at render time, so edges accepted in the previous panel bypassed the already-attached filter and seeds stayed under their seed: ids. The panel now re-collects the map fresh on every mount. - Two rapid Accept clicks could interleave the multi-await read-modify-write on hypothesis_edges and the later write clobbered the earlier edge. All model mutators now run through a same-context write chain (regression test: concurrent creates both persist). - The suggest button stays disabled while a pass is in flight (no second paid call, no interleaved panels), re-enabling on settle. - The spend-confirm now states what is actually sent: digestDossier caps its claim index (DIGEST_CLAIM_CAP=150, now exported), the confirm names the capped count and discloses truncation, and the validation/grounding claim set is capped to the SAME list (the 20.6 discipline, now exact). - Guard coverage: the suggest status line is a pure exported composer walked by the guard, the failure/malformed strings are guarded constants, and the truncation paths (14-edge section: full-count heading, 12 rendered, "… +2 more"; 8 dangling capped at 6) are exercised and guard-walked. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase-26 slice H.4 — the last hypothesis-map slice (H.5 wire kind stays deferred). Stacked on #172 (→ #171 → #170 → #169); merge in order.
Shape decision
One reduce-shaped call over the dossier digest + the map's hypothesis rows — no per-member map re-run. The digest's
claimsindex is the id-authority (the 20.6 discipline), and an edge's quote grounds against the referenced claim's own verbatim text rather than a member article — stricter than the brief's member-text grounding, and fully local.The firewall, piece by piece (design §3)
corpusGate()triple (caseSynthesis+llmAssist+ API key), re-checked in the worker; the portal button is advisory surface-gating only. No new flag.propose_hypothesis_edgesemits{hypothesis_id, claim_ref, role, quote, why}; no numeric slot, machine-checked by a test that walks everytypein the schema.suggested_by: 'llm:<model>'.unopposedHypothesespost-check discloses any hypothesis left with zero undermining scrutiny ("treat its support as unexamined, not established") — never auto-retried, never scored.Tests: 1,766 green (8 new) · build clean · lint 0 errors.
Next
CF.1 (
traceClaimDependencies— the structural counterfactual) follows per the approved COUNTERFACTUAL_DESIGN.md.🤖 Generated with Claude Code