# Learning-Loop Demo — Cold Turn to Grounded Surface, End-to-End **Date:** 2026-05-18 **Runner:** `evals/learning_loop/run_demo.py` **CLI:** `core demo learning-loop` (`--json` for machine-readable output) **Contract tests:** `tests/test_learning_loop_demo.py` (7 passing) **Reference ADRs:** [0055](../adr/ADR-0055-inter-session-memory-discovery-promotion.md), [0056](../adr/ADR-0056-contemplation-loop-c1.md), [0057](../adr/ADR-0057-teaching-chain-proposal-review.md) ![learning-loop demo](assets/learning_loop.gif) ## Headline claim > A single deterministic prompt, `"Why does thought exist?"`, produces: > > - **Before** the loop runs: `[none] I don't know — insufficient grounding for that yet.` > - **After** one operator accept: `[teaching] thought — teaching-grounded (cognition_chains_v1): cognition.thought; logos.internal. thought reveals meaning (cognition.meaning). No session evidence yet.` > > The active corpus on disk is byte-identical pre/post. The change lives entirely in a transient corpus the demo writes to and then swaps the runtime's `_CORPUS_PATH` to — the same pattern the replay-equivalence gate uses. ## What CORE has that other systems do not | Property | Continuous pre-training / RLHF | CORE learning loop | |---|---|---| | **Per-fact provenance** | None (gradient updates are diffuse) | `Provenance(adr_id, source, review_date, raw)` on every appended chain | | **Replay-equivalence guarantee** | Offline eval at checkpoint cadence | Inline gate runs the full cognition lane on every admission | | **Audit trail** | Training logs | `ProposalLog` events: `created` → `replay` → `transition` → `accepted_corpus_append` | | **Replayable across runs** | No (stochastic; weight checkpoints diverge) | SHA-256 deterministic `proposal_id`; bit-identical artifacts (see [`teaching_loop_bench.md`](teaching_loop_bench.md)) | | **Operator gate** | Implicit (deployment cadence) | Explicit `core teaching review --accept --review-date YYYY-MM-DD` | | **Roll-back semantics** | Restore checkpoint | `core teaching supersede ` (append-only at disk; active view derived) | This is the architecture deployments that need to answer *"why did the system say this today that it would not have said yesterday?"* require. ## Trust boundary The demo writes only to a tempdir-scoped transient corpus. The active teaching corpus on disk is byte-identical pre/post. The swap pattern: ```python real_path = _tg._CORPUS_PATH try: _tg._CORPUS_PATH = transient _tg._corpus_index.cache_clear() rt2 = ChatRuntime() response = rt2.chat("Why does thought exist?") finally: _tg._CORPUS_PATH = real_path _tg._corpus_index.cache_clear() ``` This is the same mechanism `teaching/replay.py:_swap_corpus_path` uses during the replay-equivalence gate. No clock-time read anywhere in the loop. ## Five scenes | Scene | What runs | Trust property | |---|---|---| | **S1. Cold turn** | Real `ChatRuntime.chat("Why does thought exist?")` | No `(thought, cause)` chain exists → universal disclosure; `grounding_source=none`. | | **S2. Discovery emission** | Discovery sink + contemplation enrich the candidate | Active corpus untouched; emission is sink-only. | | **S3. Operator proposal** | `propose_from_candidate()` runs real `run_replay_equivalence()` | Cognition lane runs twice; no regression → `state=pending`. | | **S4. Operator accept** | `accept_proposal()` against a **transient** corpus path | Active corpus byte-identical; transient gains exactly 1 line; provenance `adr-0057:discovery_promoted:2026-05-18`. | | **S5. Replay** | `_CORPUS_PATH` swapped to transient; fresh `ChatRuntime` runs the same prompt | Surface contains subject / humanised connective / object; `grounding_source=teaching`. | ## Sample run ```text ──────────────────────────────────────────────────────────────────────── S1. Cold turn — runtime cannot ground the prompt ──────────────────────────────────────────────────────────────────────── prompt : Why does thought exist? surface : I don't know — insufficient grounding for that yet. grounding_source : none discovery candidates : 1 (emitted post-turn) ──────────────────────────────────────────────────────────────────────── S2. Discovery candidate — structured evidence, not a mutation ──────────────────────────────────────────────────────────────────────── candidate_id : 17673a2f15c8da21… trigger : would_have_grounded proposed_chain : {'connective': None, 'intent': 'cause', 'object': None, 'subject': 'thought'} polarity : undetermined claim_domain : factual pack_consistent : True boundary_clean : True evidence (pack-only) : [{'epistemic_status': 'coherent', 'polarity': 'affirms', 'ref': 'thought', 'source': 'pack'}] ──────────────────────────────────────────────────────────────────────── S3. Operator-authored proposal — replay-equivalence gate runs ──────────────────────────────────────────────────────────────────────── proposal_id : 016252428267e4f339969524988c4794 proposed_chain : {'subject': 'thought', 'intent': 'cause', 'connective': 'reveals', 'object': 'meaning'} evidence (corpus ref) : cause_creation_reveals_meaning replay baseline : {'intent_accuracy': 1.0, 'surface_groundedness': 1.0, 'term_capture_rate': 0.9167, 'versor_closure_rate': 1.0} replay candidate : {'intent_accuracy': 1.0, 'surface_groundedness': 1.0, 'term_capture_rate': 0.9167, 'versor_closure_rate': 1.0} regressed_metrics : [] replay_equivalent : True state : pending ──────────────────────────────────────────────────────────────────────── S4. Operator accept — transient corpus, active corpus untouched ──────────────────────────────────────────────────────────────────────── appended chain_id : cause_thought_reveals_meaning transient corpus path : /tmp/learning_loop_demo_xxxxxx/cognition_chains_v1.jsonl transient lines before : 10 transient lines after : 11 active corpus byte-eq : True ──────────────────────────────────────────────────────────────────────── S5. Same prompt — now deterministically teaching-grounded ──────────────────────────────────────────────────────────────────────── prompt : Why does thought exist? surface : thought — teaching-grounded (cognition_chains_v1): cognition.thought; logos.internal. thought reveals meaning (cognition.meaning). No session evidence yet. grounding_source : teaching ════════════════════════════════════════════════════════════════════════ BEFORE / AFTER (single deterministic prompt, one accept between) ════════════════════════════════════════════════════════════════════════ prompt : Why does thought exist? before : [none] I don't know — insufficient grounding for that yet. after : [teaching] thought — teaching-grounded (cognition_chains_v1): cognition.thought; logos.internal. thought reveals meaning (cognition.meaning). No session evidence yet. learning_loop_closed : True active corpus byte-identical : True ``` ## How to reproduce ```bash core demo learning-loop # human output (preamble + scenes + before/after) core demo learning-loop --json # machine-readable DemoReport python -m pytest tests/test_learning_loop_demo.py -q # ~15s ``` ## Falsifiable claims If any of these stops holding, the headline claim no longer holds: - `report.learning_loop_closed` is `True`. - `report.active_corpus_byte_identical` is `True`. - `report.before.grounding_source == "none"`; surface contains `"insufficient grounding"`. - `report.after.grounding_source == "teaching"`; surface contains `"thought"` AND `"reveal"` AND `"meaning"` AND `"teaching-grounded"`. - S3: `replay_evidence.replay_equivalent is True`, `regressed_metrics == []`, `state == "pending"`. - S4: `transient_lines_after == transient_lines_before + 1` AND `active_corpus_byte_identical is True`. - The same prompt drives both surfaces (`report.prompt == "Why does thought exist?"`). ## Why "thought" is the demo subject The subject must satisfy three pre-conditions for the demo to fire deterministically: 1. **Pack-resident** (otherwise the discovery candidate isn't emitted) — confirmed by `'thought' in _pack_index()`. 2. **No active `(thought, cause)` chain** (otherwise the cold turn would already be teaching-grounded) — confirmed by the active corpus snapshot. 3. **Intent classifier picks `CAUSE` on a natural prompt** — `"Why does thought exist?"` classifies as `CAUSE / subject="thought"` deterministically. The operator-authored chain (`thought reveals meaning`) cites `cause_creation_reveals_meaning` as affirming evidence. Both endpoint lemmas (`thought`, `meaning`) are pack-resident; the connective `reveals` is in the canonical predicate set. ## Related - Anti-regression demo: [`anti_regression_demo.md`](anti_regression_demo.md) — the inverse demo showing each gate refusing a bad proposal. - Determinism benchmark: [`teaching_loop_bench.md`](teaching_loop_bench.md) — N-run byte-identical-artifact proof on this exact pipeline. - Operator surface: see the [Inter-Session Memory section in README](../../README.md#inter-session-memory--reviewed-learning).