Pre-ADR-0062, the teaching-grounded composer emitted exactly one
reviewed chain per surface — "light reveals truth" — even when the
corpus already contained an immediate follow-up "truth grounds
knowledge". With 21 active chains after curriculum saturation v2,
many grounded prompts had a corpus-ratified follow-up the composer
silently dropped.
ADR-0062 adds the composed composer + an opt-in config flag:
flag OFF (default):
light — teaching-grounded (cognition_chains_v1): cognition.illumination;
logos.core. light reveals truth (cognition.truth). No session evidence yet.
flag ON:
light — teaching-grounded (cognition_chains_v1): cognition.illumination;
logos.core. light reveals truth (cognition.truth), which grounds
knowledge (cognition.knowledge). No session evidence yet.
Follow-up resolution:
- prefer cause; fall back to verification (deterministic preference)
- cycle guard: 1-step cycles (A→B, B→A) blocked
- pack-residency guard: follow-up's object must be pack-resident
- bounded depth: v1 follows exactly one hop
- degrades to single-chain BYTE-IDENTICALLY when no follow-up
survives the guards (drop-in replacement)
Trust-boundary invariants preserved:
- Every visible non-template token is lemma / pack-domain /
humanize_predicate connective / template constant. Only added
template constant: ", which "
- Deterministic: same chains → same surface bytes
- Default-False flag pattern mirrors ADR-0047/0058
- `versor_condition < 1e-6` invariant untouched (surface composition only)
Cognition lane null-drop invariant CI-pinned:
Composed mode emits a strictly LONGER surface (extra follow-up
clause); every expected_term passing flag-OFF must still pass flag-ON.
Asserted in test_cognition_lane_metrics_unchanged_with_composed_flag
for both public and holdout splits. If a future change drops tokens,
the test fails as a deliberate regression.
public flag OFF: intent 100% / surface 100% / term 91.7% / versor 100%
public flag ON : intent 100% / surface 100% / term 91.7% / versor 100% (identical)
holdout flag OFF: intent 100% / surface 100% / term 83.3% / versor 100%
holdout flag ON : intent 100% / surface 100% / term 83.3% / versor 100% (identical)
Live-prompt lift visible on ~12 of 21 active chains; the rest hit
cycle or pack-residency guards. Saturation v2's clusters were
authored partly with composition in mind (thought→meaning→
understanding, inference→evidence→knowledge, etc.).
- core/config.py — `RuntimeConfig.composed_surface: bool = False`
- chat/teaching_grounding.py — `teaching_grounded_surface_composed`
sibling to `teaching_grounded_surface`
- chat/runtime.py — dispatch branch in `_maybe_pack_grounded_surface`
selects composed vs single-chain based on config flag
- tests/test_composed_surface.py — 11 tests pin: function-level
(None on no chain / degrades when no follow-up / two-clause when
follow-up exists / includes intermediate + final domains /
deterministic / cycle guard / trust label preserved); runtime
integration (default single-chain / flag-on composed / frozen
config); cognition-lane null-drop invariant.
Lanes (regression): smoke 67 / cognition 121 / teaching 17 /
composed-surface 11 — all green.
8.2 KiB
ADR-0062 — Composed Teaching-Grounded Surface (Chain-of-Chains)
Status: Accepted Date: 2026-05-18 Author: Shay
Context
Pre-ADR-0062, teaching_grounded_surface emitted exactly one
reviewed chain per surface:
light — teaching-grounded (cognition_chains_v1): cognition.illumination;
logos.core. light reveals truth (cognition.truth).
No session evidence yet.
Every grounded prompt produced a single-clause surface, regardless
of how many follow-up chains the corpus already contained. With
21 active chains in cognition_chains_v1 (after curriculum
saturation v2), many grounded prompts have an immediate corpus-
ratified follow-up that the surface composer was silently dropping:
| Initial chain | Follow-up chain | What single-chain emits | What composed could emit |
|---|---|---|---|
light reveals truth |
truth grounds knowledge |
light reveals truth |
light reveals truth, which grounds knowledge |
thought reveals meaning |
meaning grounds understanding |
thought reveals meaning |
thought reveals meaning, which grounds understanding |
inference requires evidence |
evidence grounds knowledge |
inference requires evidence |
inference requires evidence, which grounds knowledge |
This is the fluency-from-existing-corpus gap I called out in the "more packs?" question: the rate-limiter on articulation isn't pack vocabulary, it's surface composition over chains that already exist.
Decision
Add teaching_grounded_surface_composed(subject, intent_tag) to
chat/teaching_grounding.py alongside the existing single-chain
composer, and route it via a new opt-in
RuntimeConfig.composed_surface: bool = False.
Surface format
"{A} — teaching-grounded ({corpus_id}): {dA1}; {dA2}.
{A} {conn_A} {B} ({dB}), which {conn_B} {C} ({dC}).
No session evidence yet."
Every visible non-template token remains a lemma, a verbatim pack
semantic_domains string, or a humanize_predicate-emitted
connective. The new , which linker is the only added template
constant.
Follow-up resolution rules
- Look up an initial chain
(subject, intent). - Look up a follow-up chain whose
subjectequals the initial chain'sobject. Prefercause; fall back toverification. (Causal continuation reads more naturally than a verification detour; the preference is deterministic.) - Cycle guard. If the follow-up's
objectequals the initialsubjectOR the initialobject, do not follow (1-step cycle or degenerate same-cell mismatch). - Pack-residency guard. If the follow-up's
objectis not pack-resident withsemantic_domains, do not follow (would emit a partially-grounded composition). - If no follow-up survives the guards, degrade to the single-chain surface byte-identically. Drop-in replacement.
Bounded depth
v1 follows exactly one hop. Deeper compositions (A→B→C→D) are deferred to a future ADR. The cycle/pack-residency guards alone don't suffice for unbounded depth — a depth-2 chain can re-enter through a different intent. Bounded depth + visited-set check is the natural next step but adds template-shape complexity not needed today.
Opt-in flag
RuntimeConfig.composed_surface: bool = False. Default preserves
all pre-ADR-0062 behaviour byte-identically. Mirrors the
ADR-0047/0058 forward_graph_constraint pattern: ship the
capability behind a flag, characterise empirically, decide on
default behaviour in a follow-up once downstream consumers have
observed it on their workloads.
Verification
tests/test_composed_surface.py 11 passed
- Pure function: None when no chain / degrades when no follow-up /
produces two-clause when follow-up exists / includes both
intermediate and final domains / deterministic / cycle guard
blocks 1-step cycle / preserves trust-boundary label.
- Runtime: default keeps single-chain / flag-on uses composed /
flag is observable on frozen config.
- Null-drop invariant: cognition-lane metrics byte-identical
flag OFF vs ON on both public and holdout splits.
Lanes (regression check):
core test --suite smoke 67 passed
core test --suite cognition 121 passed
core test --suite teaching 17 passed
Cognition-lane null-drop invariant
Composed mode emits a strictly longer surface — every token
in the single-chain surface still appears, plus one follow-up
clause. So every expected_term and expected_surface_contains
that passed flag-OFF must still pass flag-ON. The contract test
test_cognition_lane_metrics_unchanged_with_composed_flag runs
both public and holdout splits twice (flag OFF vs ON) and asserts
all four watched metrics are pair-wise identical:
| Split | Flag OFF | Flag ON |
|---|---|---|
| public | 100 / 100 / 91.7 / 100 | 100 / 100 / 91.7 / 100 |
| holdout | 100 / 100 / 83.3 / 100 | 100 / 100 / 83.3 / 100 |
If a future change ever drops tokens in composed mode (e.g. shortens the surface to omit the intermediate object), this test fails as the deliberate regression it is.
Live-prompt observable lift
Composed mode visibly enriches the surface on prompts where follow-ups exist:
flag OFF: "Why does light exist?"
→ light — teaching-grounded (cognition_chains_v1):
cognition.illumination; logos.core. light reveals truth
(cognition.truth). No session evidence yet.
flag ON: "Why does light exist?"
→ light — teaching-grounded (cognition_chains_v1):
cognition.illumination; logos.core. light reveals truth
(cognition.truth), which grounds knowledge
(cognition.knowledge). No session evidence yet.
Of the 21 active chains, the follow-up resolution succeeds for
~12 of them (the rest hit cycle guards or pack-residency
guards). Saturation v2's three coherent clusters were authored
partly with this composition in mind — thought reveals meaning
meaning grounds understanding,definition grounds concept+concept requires definition(cycle-blocked, degrades cleanly), etc.
Consequences
What changes
core/config.py—RuntimeConfig.composed_surface: bool = False.chat/teaching_grounding.py—teaching_grounded_surface_composed(subject, intent_tag)sibling toteaching_grounded_surface.chat/runtime.py— dispatch branch in_maybe_pack_grounded_surfaceforIntentTag.CAUSE/IntentTag.VERIFICATIONselects composed vs single-chain based on the config flag. Single-line change.
What does not change
- The pack-grounded discipline: zero LLM-generated tokens; every visible word is lemma, pack-domain, connective, or template constant.
- ADR-0053's cold-start contract: empty session + no chain still emits the universal disclosure.
- Default runtime behaviour: byte-identical to pre-ADR-0062 main.
- The non-negotiable field invariant
(
versor_condition(F) < 1e-6) is unaffected — this ADR only changes surface composition, not rotor construction or sandwich application.
Scope limits
- Depth-1 only. v1 follows one hop.
light reveals truth, which grounds knowledge, which requires evidencewould require a depth-2 composer with visited-set tracking — out of scope here. - No multi-claim aggregation. When the same subject has
multiple ratified chains (e.g.
knowledge requires evidenceANDknowledgeis the object of three other chains), the composer still picks one initial chain. Aggregation across multiple grounded views is a separate ADR. - English path only. The
, whichlinker and thehumanize_predicateconnectives are English-specific. - Flag stays off by default. Operators must opt in. A follow-up ADR will decide on default behaviour after characterising the flag on more workloads (mirrors ADR-0047/0058).
Cross-References
- ADR-0052 — the single-chain teaching-grounded composer this ADR extends.
- ADR-0053 — the cognition- lane closure that exposed the saturation headroom.
- ADR-0058 — the opt-in-default-False + null-lift-invariant pattern this ADR reuses.
- Curriculum: cognition saturation v2 — the unit that produced the 21 chains this composer composes over.