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.
246 lines
8.5 KiB
Markdown
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.
|