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

246 lines
8.5 KiB
Markdown

# 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.