core/docs/decisions/ADR-0066-turn-level-composition.md
Shay ce8226e9a2 feat(adr-0066): NARRATIVE + EXAMPLE intents with multi-clause composers (Phase 3.3 + 3.4)
Two new intent shapes + composers turn the runtime's corpus
density into operator-visible articulation.  Both consult the
cross-corpus aggregator from ADR-0064; no new ratification needed.

P3.3 — chat/narrative_surface.py + IntentTag.NARRATIVE.

  Classifier patterns (registered BEFORE generic DEFINITION):
    ^tell\s+me\s+about\s+
    ^describe\s+
    ^what\s+(?:can|do)\s+you\s+(?:say|know)\s+about\s+

  narrative_grounded_surface(subject, max_clauses=4) walks every
  reviewed chain rooted on subject across all registered teaching
  corpora.  Dedupes by (connective, object) — cause + verification
  carrying the same predicate emit one clause, not two.  Sorts by
  (intent, connective, object) for replay stability.

  Surface format:
    "{X} — narrative-grounded ({corpus_ids}): {dX1}; {dX2}.
     {X} {conn1} {O1} ({dO1}); {X} {conn2} {O2} ({dO2}).
     No session evidence yet."

  Cross-corpus subjects (e.g. mother in relations_v2) emit
  narrative-grounded (relations_chains_v2) tag; cognition subjects
  emit cognition_chains_v1 tag.  Multi-corpus subjects (when
  applicable) emit composite "corpus_a + corpus_b" tag.

P3.4 — chat/example_surface.py + IntentTag.EXAMPLE.

  Classifier patterns:
    ^(?:give|show)\s+(?:me\s+)?an?\s+(?:example|instance)\s+of\s+
    ^example\s+of\s+

  example_grounded_surface(object_lemma, max_examples=3) walks chains
  where the lemma is the OBJECT — inverts the typical subject-keyed
  access pattern.  Dedupes by subject; sorts by (intent, subject,
  connective).

  Surface format:
    "{X} — example-grounded ({corpus_ids}): {dX1}.
     Example: {subj1} {conn1} {X}; {subj2} {conn2} {X}.
     No session evidence yet."

Cross-cutting:
  - Both intents added to _OOV_INTENT_TAGS — fall through to OOV
    invitation when subject is unknown (Phase 2 gradient discipline).
  - Both tagged grounding_source="teaching" (same provenance tier
    as the existing teaching_grounded_surface).
  - No prose generation, no new mutation surface.

Live verification:
  > Tell me about truth.
    [teaching] truth — narrative-grounded (cognition_chains_v1):
    cognition.truth; logos.core. truth grounds knowledge
    (cognition.knowledge); truth requires evidence (cognition.evidence).

  > Give me an example of knowledge.
    [teaching] knowledge — example-grounded (cognition_chains_v1):
    cognition.knowledge. Example: truth grounds knowledge;
    understanding requires knowledge; evidence grounds knowledge.

  > Tell me about mother.
    [teaching] mother — narrative-grounded (relations_chains_v2):
    kinship.parent.female. mother precedes daughter (kinship.child.female).

  > Describe photosynthesis.
    [oov] I haven't learned 'photosynthesis' yet (intent: narrative). ...

ADR-0066 (this commit completes the ADR).  30 new tests passed.
Full lane: 2067 passed, 2 skipped, 0 failed in 2:32.
2026-05-18 17:01:55 -07:00

8.5 KiB

ADR-0066 — Turn-level composition (Plan Phase 3)

Status: Accepted Date: 2026-05-18 Author: Shay Phase: Plan Phase 3 (turn-level composition — the articulation gap) Builds on: ADR-0048 / ADR-0052 / ADR-0062 / ADR-0064 / ADR-0065


Context

Phases 1 + 2 closed two flywheels: the chain-gap and OOV-gap signal streams. The vocabulary and corpus axes both grow under operator review. But surfaces still felt mechanical — each turn was freshly minted from primitives, never referenced backward.

Three intents were missing from the runtime:

  1. Thread anaphora — "As we just established, X reveals Y, and on this turn..." Conversation reads as a thread, not a series of independent grounded surfaces.
  2. NARRATIVE — "Tell me about X." A multi-clause composer that surfaces everything the system has reviewed about X, across every registered corpus.
  3. EXAMPLE — "Give me an example of X." The converse of NARRATIVE: surfaces chains where X is the object, inverting the typical chain access pattern.

Phase 3 adds all three deterministically — no prose generation, no content synthesis.


Decision

P3.1 — Session-thread context (chat/thread_context.py)

A bounded FIFO of TurnSummary records, owned by ChatRuntime. Each turn appends one summary (intent_tag, subject, grounding_source, chain_id, corpus_id) via the runtime's internal _push_thread_summary. The cold-start path classifies intent up-front unconditionally so the summary captures the subject even when no sink is attached (previously gated on sink attachment — now gated only on gate_decision.source == "empty_vault" + English output).

Default capacity 8 (MAX_THREAD_TURNS). Oldest summaries evict in FIFO order. Frozen TurnSummary dataclass; never mutated post-push.

P3.2 — Anaphora composer (chat/anaphora.py)

thread_anaphora_prefix(ctx, subject, intent_name, source) → str | None. Returns a deterministic backreference when:

  • The current turn is pack/teaching grounded.
  • A prior pack/teaching turn on the same subject exists in the thread context.
  • The prior turn's intent differs from the current intent (same-intent revisits are redundant; the prior turn IS the current surface modulo vault drift).

Prefix shapes (structural-fields-only, no prose):

(Recalling turn N: chain <chain_id>.)            # prior was teaching
(Recalling turn N: <subject> grounded pack.)     # prior was pack

Opt-in via RuntimeConfig.thread_anaphora=False. Default off preserves every pre-P3.2 surface byte-identically.

P3.3 — NARRATIVE intent (chat/narrative_surface.py)

New IntentTag.NARRATIVE. Classifier patterns:

^tell\s+me\s+about\s+
^describe\s+
^what\s+(?:can|do)\s+you\s+(?:say|know)\s+about\s+

Registered BEFORE ^what\s+(?:is|are)\s+ so the more specific patterns win.

Composer: narrative_grounded_surface(subject_lemma, max_clauses=4). Walks every reviewed chain rooted on X across all registered teaching corpora, dedupes by (connective, object), sorts by (intent, connective, object) for replay stability, emits up to max_clauses clauses.

Surface format:

"{X} — narrative-grounded ({corpus_ids}): {dX1}; {dX2}.
 {X} {conn1} {O1} ({dO1}); {X} {conn2} {O2} ({dO2}). No session
 evidence yet."

Tagged grounding_source="teaching" — narrative surfaces are reviewed-corpus content, same provenance tier as teaching_grounded_surface.

P3.4 — EXAMPLE intent (chat/example_surface.py)

New IntentTag.EXAMPLE. Classifier patterns:

^(?:give|show)\s+(?:me\s+)?an?\s+(?:example|instance)\s+of\s+
^example\s+of\s+

Composer: example_grounded_surface(object_lemma, max_examples=3). Reverse-chain access: walks chains where X is the object, not the subject. Dedupes by subject. Sorts by (intent, subject, connective).

Surface format:

"{X} — example-grounded ({corpus_ids}): {dX1}; {dX2}.
 Example: {subject1} {conn1} {X}; {subject2} {conn2} {X}. No
 session evidence yet."

Cross-cutting

  • NARRATIVE + EXAMPLE both fall through to the OOV invitation (P2.1) when the subject is unknown — same gradient discipline as Phase 2.
  • Both composers consult the cross-corpus aggregator from ADR-0064; no new ratification required.
  • No new pack mutation. No new corpus. Phase 3 is pure surface + thread-state work over the Phase 1/2 substrate.

Consequences

Capability unlocked

Intent Pre-Phase-3 Post-Phase-3
"Tell me about X" universal disclosure multi-clause narrative across corpora
"Give me an example of X" universal disclosure reverse-chain example surface
Subject-anaphora across turns none opt-in deterministic backreference

Live verification

> Tell me about truth.
  [teaching] truth — narrative-grounded (cognition_chains_v1):
  cognition.truth; logos.core. truth grounds knowledge (cognition.knowledge);
  truth requires evidence (cognition.evidence). No session evidence yet.

> Give me an example of knowledge.
  [teaching] knowledge — example-grounded (cognition_chains_v1):
  cognition.knowledge. Example: truth grounds knowledge;
  understanding requires knowledge; evidence grounds knowledge.
  No session evidence yet.

> Tell me about mother.
  [teaching] mother — narrative-grounded (relations_chains_v2):
  kinship.parent.female; kinship.parent. mother precedes daughter
  (kinship.child.female). No session evidence yet.

# With thread_anaphora=True, after a teaching turn on "light":
> What is light?
  [pack] (Recalling turn 0: chain cause_light_reveals_truth.)
  light — pack-grounded (en_core_cognition_v1):
  cognition.illumination; logos.core; perception.clarity.

Cognition lane: byte-identical

Phase 3 is additive — every existing intent classifier rule and composer behaviour preserved.

public:  intent 100% / surface 100% / term 91.7% / closure 100%
holdout: intent 100% / surface 100% / term 83.3% / closure 100%

Trust boundaries

  • No prose generation. The anaphora prefix is structural fields only (turn_index + chain_id or grounding tier). NARRATIVE and EXAMPLE composers emit only pack atoms, chain content, and fixed template strings.
  • No new mutation surfaces. Phase 3 reads the reviewed corpora; it never writes.
  • Anaphora is opt-in. Default thread_anaphora=False keeps surfaces byte-identical to pre-P3.2.
  • Bounded. Thread context capped at 8 turns; NARRATIVE capped at 4 clauses; EXAMPLE capped at 3 examples. All defaults configurable.

Files changed

chat/thread_context.py                                   NEW (~165 lines)
chat/anaphora.py                                         NEW (~90 lines)
chat/narrative_surface.py                                NEW (~165 lines)
chat/example_surface.py                                  NEW (~115 lines)
chat/oov_surface.py                                      added NARRATIVE/EXAMPLE
chat/runtime.py                                          wired all three composers + thread push
core/config.py                                           thread_anaphora flag
generate/intent.py                                       NARRATIVE / EXAMPLE enum + patterns
tests/test_thread_context.py                             NEW (20 tests)
tests/test_anaphora.py                                   NEW (12 tests)
tests/test_narrative_example_intents.py                  NEW (30 tests)
docs/decisions/ADR-0066-turn-level-composition.md        NEW (this file)
docs/decisions/README.md                                 ADR-0066 index entry

Verification

tests/test_thread_context.py                             20 passed
tests/test_anaphora.py                                   12 passed
tests/test_narrative_example_intents.py                  30 passed
Curated lanes (all green):
  smoke 67 / cognition 121 / teaching 17 / packs 6 / runtime 19 / algebra 132
Cognition eval byte-identical.

Future ADRs unlocked

  • Anaphora on the walk path. Today thread anaphora fires only when both turns are pack/teaching tier. Extending to vault-path turns (the typical mid-session surface) needs a parallel hook in the walk return path. Natural follow-up.
  • Multi-intent NARRATIVE composition. Current NARRATIVE walks one corpus dimension. Future work: extend composed-surface (ADR-0062) to operate on the NARRATIVE clause set, producing "narrative-of-narratives" surfaces.
  • EXAMPLE with hypothetical counterexamples. Today EXAMPLE surfaces only positive corpus chains. Future: when the corpus contains contradicting/superseded chains, EXAMPLE can show contrast.