core/teaching
Shay 07d35c0f54 feat(adr-0055): Phase B — DiscoveryCandidate emission from turn loop
Lands the first deterministic trigger of the discovery → reviewed-
memory loop. Candidates are structured evidence; emission is
opt-in via attach_discovery_sink and NEVER mutates the active
teaching corpus.

- teaching/discovery.py: DiscoveryCandidate dataclass + pure
  extract_discovery_candidates(turn_event, intent, subject) rule
  firing. Phase B fires only the would_have_grounded trigger:
    grounding_source == "none"
    AND intent ∈ {CAUSE, VERIFICATION}
    AND subject lemma in ratified cognition pack
    AND (subject, intent) NOT in active corpus
  candidate_id = SHA-256 of canonical JSON payload — replay-stable.
  Other DiscoveryTrigger literals (successful_comparison,
  hedge_acknowledged, oov_resolved_via_decomp) are reserved for
  later phases.

- teaching/discovery_sink.py: DiscoveryCandidateSink protocol,
  DiscoveryBufferSink (in-memory), DiscoveryMonthlyFileSink
  (append-only JSONL, <root>/<YYYY>/<YYYY-MM>.jsonl rollover,
  injectable clock).

- chat/runtime.py: opt-in attach_discovery_sink, post-turn
  emission inside _stub_response only when caller threads
  classified intent forward (gate-fire fall-through site).
  Intent classification at the call site reuses the same
  deterministic classifier already invoked by
  _maybe_pack_grounded_surface for the empty-vault English path.

Trust boundary: candidates write to a separate sink/file path
only; the active corpus on disk is never touched. Tests
explicitly assert corpus bytes are byte-identical before and
after a candidate-emitting turn.

Tests: tests/test_discovery_candidates.py — 24 tests covering
pure-predicate rule firing, every short-circuit path,
deterministic candidate_id, sink opt-in, runtime parity with no
sink, monthly rollover semantics, append-only behaviour, no
corpus mutation.

Lanes: smoke 67, cognition 121, runtime 19, teaching 17, packs 6
— all green. Cognition eval metrics unchanged on dev / public /
holdout splits. versor_condition < 1e-6 invariant untouched.
2026-05-18 08:26:04 -07:00
..
cognition_chains feat(adr-0053): cognition lane closure — corpus expansion + CORRECTION acknowledgement 2026-05-18 07:43:39 -07:00
__init__.py feat(adr-0021): epistemic_status surface wired across teaching + trace 2026-05-16 20:20:35 -07:00
audit.py feat(adr-0055): Phase A — teaching corpus audit, supersession, typed provenance 2026-05-18 08:15:23 -07:00
correction.py feat: add reviewed teaching loop for controlled correction learning 2026-05-14 20:32:28 -07:00
discovery.py feat(adr-0055): Phase B — DiscoveryCandidate emission from turn loop 2026-05-18 08:26:04 -07:00
discovery_sink.py feat(adr-0055): Phase B — DiscoveryCandidate emission from turn loop 2026-05-18 08:26:04 -07:00
epistemic.py feat(adr-0021): epistemic_status surface wired across teaching + trace 2026-05-16 20:20:35 -07:00
provenance.py feat(adr-0055): Phase A — teaching corpus audit, supersession, typed provenance 2026-05-18 08:15:23 -07:00
relation_parse.py feat(phase3): transitive_walk + path_recall operator bundle (ADR-0018) 2026-05-16 15:04:43 -07:00
review.py fix(gaps): close G1+G2+G3 + identity vocab + pipeline safety-stub honour 2026-05-16 21:21:06 -07:00
store.py feat(epistemic): contradiction coherence checker — CONTESTED transitions wired, last Tier 4.5 row closes 2026-05-17 10:36:48 -07:00