core/docs/adr/ADR-0060-correction-acknowledgment-topic-lemma.md
Shay 54e6bfc0d0
docs: reorganize docs landscape
Implements the 4-phase documentation reorganization master plan.

- Consolidation: Merged brief/, handoff/, planning/, and decisions/ into briefs/, handoffs/, plans/, and adr/ respectively (101 ADRs relocated)
- Root Cleanup: Relocated HANDOFF-gpt55-*.md and key top-level docs (runtime_contracts.md, etc.) to canonical folders. Added superseded alerts.
- Indices & Navigation: Created docs/README.md navigation document, docs/sessions/README.md index, docs/adr/README.md index
- Note: Also includes prior commit adding ADR-0200+ corpus hygiene governance (ADR-0225, dependency map, backfilled cross-references)
2026-06-30 16:59:36 -07:00

7.6 KiB

ADR-0060 — CORRECTION Acknowledgement Carries the Corrected-Topic Lemma

Status: Accepted Date: 2026-05-18 Author: Shay


Context

ADR-0053 introduced pack_grounded_correction_surface() — the cold-start CORRECTION acknowledgement. When a user begins a session with a meta-cognitive correction utterance ("No, that's wrong", "Actually, X means Y"), there is no prior turn to apply the correction to, so the runtime emits a deterministic pack-grounded surface stating that fact:

correction received — pack-grounded (en_core_cognition_v1):
cognition.correction; teaching.review; dialogue.repair.
No prior turn in this session to correct yet.

This surface was honest but topic-blind: a user who said "Actually, truth requires evidence" got a response that referenced correction but never truth. The holdout case correction_truth_040 expected ["truth"] in expected_terms and missed — contributing one of the 5 term-capture misses on the holdout split.

The first curriculum unit (epistemology v1, 2acf71f) closed one corpus-fixable miss (verification_wisdom_036). Three of the remaining four were architectural; correction_truth_040 was the cleanest to address.


Decision

Extend pack_grounded_correction_surface to accept an optional text: str | None argument. When supplied, the surface composer extracts the first pack-resident topical lemma from the utterance (left-to-right token order, excluding the meta-cognition lemma correction itself and dialogue fillers be / have) and weaves it into a fixed template:

correction received — pack-grounded ({pack_id}):
{correction_domains}. Noted topic: {lemma} ({lemma_domains}).
No prior turn in this session to correct yet.

When no topical lemma is found (or text is None), the surface degrades to the ADR-0053 topic-less template byte-identically.

Trust-boundary invariants preserved

  • Every visible non-template token is still either the lemma correction, the topical lemma, or a verbatim semantic_domains string from the ratified pack. No inference, no rewording.
  • Determinism. Same text → same surface bytes. The selector is left-to-right token order; no scoring, no NLP heuristic, no LLM.
  • Backward compatibility. pack_grounded_correction_surface() with no argument returns the ADR-0053 template byte-identically. Existing 15 tests in tests/test_pack_grounded_correction.py continue to pass.
  • The "No prior turn in this session to correct yet." trust-boundary label — distinguishing this cold-start surface from the post-correction teaching-repair path (teaching/correction.py) — is preserved in both variants.

Stopword selection

Two stopword classes are excluded from topic-lemma selection:

  1. The meta-cognition lemma itself (correction, correct) — echoing it as the topic would be circular; it's already the subject of the acknowledgement template.
  2. Dialogue fillers (be, have) — pack-resident lemmas that classify but carry no topical signal in a correction utterance.

This stopword set is deliberately tiny. Expanding it requires an amendment to this ADR — pack-resident lemmas that survive both the "have semantic_domains" gate and the natural-language flow of a correction utterance are real topic candidates by default.

Token normalization

Tokens are lowercased and stripped of attached punctuation (,.;:!?"'()[]{}) before pack-lookup. This handles common surface forms like "truth.", 'truth', truth, without requiring a full tokenizer.


Why text-level extraction, not intent.subject

intent.subject after ADR-0049 head-noun extraction returns ", truth requires evidence" for the prompt "Actually, truth requires evidence" — the correction intent's subject extractor preserves the post-marker tail rather than extracting a single head noun. Using intent.subject would require either:

  1. Extending ADR-0049's head-noun normalization to the CORRECTION intent — substantial change to upstream classification logic.
  2. Re-parsing intent.subject at the surface composer — equivalent work to parsing the raw text.

Parsing the raw text at the surface layer is cleaner: it isolates the fix, doesn't perturb upstream classification, and lets the correction acknowledgement own its own topic-extraction policy.


Verification

tests/test_correction_topic_lemma.py        14 passed
  - extraction: first lemma / skips correction / skips fillers /
    None on empty / strips punctuation / case-insensitive
  - surface: contains corrected lemma / contains topic domains /
    degrades to ADR-0053 / preserves trust label / deterministic /
    correct pack_id
  - end-to-end: correction_truth_040 emits 'truth' / no-pack-lemma
    still grounds

tests/test_pack_grounded_correction.py      15 passed   (ADR-0053; backward compat)

Lanes (regression check):
  core test --suite smoke           67 passed
  core test --suite cognition      121 passed
  core test --suite teaching        17 passed

Cognition lane lift

Split Metric Pre-ADR-0060 Post-ADR-0060
public intent / surface / term / versor 100 / 100 / 91.7 / 100 100 / 100 / 91.7 / 100 (unchanged)
holdout intent / surface / term / versor 100 / 94.7 / 75.0 / 100 100 / 94.7 / 79.2 / 100 (+4.2pp term_capture)

The +4.2pp matches the single-case fix: correction_truth_040 now captures truth. The remaining three holdout misses (procedure_define_010, unknown_spirit_041, unknown_word_018) are out of scope for this ADR.


Consequences

What changes

  • chat/pack_grounding.py_extract_correction_topic_lemma helper and an optional text parameter on pack_grounded_correction_surface.
  • chat/runtime.py — call site passes text through. Single line.

What does not change

  • ADR-0053's contract for the no-text path: byte-identical surface.
  • Refusal priority: a SafetyVerdict violation still pre-empts the acknowledgement (per ADR-0036).
  • The pack-grounded discipline: zero LLM-generated tokens in the surface; every visible word is either lemma, pack-domain, or fixed template constant.
  • versor_condition(F) < 1e-6 invariant: untouched — this ADR only changes surface composition.

Scope limits

  • Single topical lemma per surface. A correction utterance containing multiple pack-resident lemmas ("Actually, truth requires evidence") currently surfaces only the first (truth). Extending to "Noted topics: truth, evidence" is a reasonable follow-up but expands the trust surface (more tokens, more template branches) and was deferred.
  • English path only. The stopword set and tokenizer are English-specific. Non-English correction utterances will not match pack lemmas and will degrade to the topic-less template — no behaviour change vs ADR-0053.
  • No subject-claim propagation to corpus. The corrected claim (truth requires evidence) is acknowledged as a topic, not as a candidate teaching chain. Promoting corrections into the corpus is the teaching/correction.py repair path, which engages only once a prior turn exists.

Cross-References

  • ADR-0053 — the CORRECTION acknowledgement contract this ADR extends.
  • ADR-0049 — the head-noun extraction whose contract this ADR consciously did not extend.
  • Curriculum: epistemology v1 — the first unit that surfaced this gap as one of the architectural misses.