Skip to content

feat(llm): hypothesis-edge suggestion through the corpus firewall (26 H.4)#173

Merged
bryanmatthewsimonson merged 2 commits into
claude/phase-26-h3-attach-affordancefrom
claude/phase-26-h4-llm-edge-suggest
Jul 18, 2026
Merged

feat(llm): hypothesis-edge suggestion through the corpus firewall (26 H.4)#173
bryanmatthewsimonson merged 2 commits into
claude/phase-26-h3-attach-affordancefrom
claude/phase-26-h4-llm-edge-suggest

Conversation

@bryanmatthewsimonson

Copy link
Copy Markdown
Owner

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 claims index 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)

  1. Gate — the existing corpusGate() triple (caseSynthesis + llmAssist + API key), re-checked in the worker; the portal button is advisory surface-gating only. No new flag.
  2. Tool schemapropose_hypothesis_edges emits {hypothesis_id, claim_ref, role, quote, why}; no numeric slot, machine-checked by a test that walks every type in the schema.
  3. Validate → ground → filter — schema-walker contract; quotes must locate verbatim in the claim's record (drops disclosed); every id must resolve against the same claim set the digest was built from; already-attached edges rejected with a reason.
  4. Human-accept — per-proposal Accept/Dismiss; nothing auto-applies; accepted hypothesis promotions and edges stamped suggested_by: 'llm:<model>'.
  5. Both sides — the system prompt requires proposals for every hypothesis on both sides, and the unopposedHypotheses post-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

… 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>
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>
@bryanmatthewsimonson
bryanmatthewsimonson merged commit c663c8b into claude/phase-26-h3-attach-affordance Jul 18, 2026
@bryanmatthewsimonson
bryanmatthewsimonson deleted the claude/phase-26-h4-llm-edge-suggest branch July 18, 2026 05:09
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