core/chat
Shay 46ac737767 feat(pack-grounding): selector-ready gloss wiring via PackSurfaceCandidate
Wires the gloss resolver (Phase B2) through pack_grounded_surface
WITHOUT hard-coding around the future SurfaceSelector.  Per the
2026-05-19 design review:

  > don't let glosses hard-code around the selector.  If they ship
  > first, keep the integration deliberately narrow:
  > pack_grounded_surface() may use glosses temporarily, but the
  > data model should already look like future SurfaceCandidate
  > input.  That avoids a second migration.

The integration uses a typed intermediate dataclass that matches the
selector's expected candidate shape:

  chat/pack_surface_candidate.py
    @dataclass(frozen=True, slots=True)
    class PackSurfaceCandidate:
        surface: str               # rendered final string
        grounding_source: str      # "pack" today
        pack_id: str               # provenance
        gloss: str | None          # reviewed natural-language form
        semantic_domains: tuple    # audit-trail content
        lemma: str
        pos: str
        is_user_facing_safe: bool  # honesty flag for selector
        is_fluent_sentence: bool   # gloss-backed vs. dotted-disclosure

When the SurfaceSelector lands:
  - This type becomes one variant in the selector's typed candidate
    union (alongside RefusalCandidate, TeachingCandidate, OOVCandidate).
  - pack_grounded_surface() becomes a provider that emits the
    candidate; the selector picks across providers' candidates by
    ranked authority + is_fluent_sentence preference.
  - No data migration — only the rendering step relocates.

Surface composition (chat/pack_grounding.py):

  build_pack_surface_candidate(lemma) -> PackSurfaceCandidate
    1. resolve_lemma(lemma) — required (None when OOV).
    2. resolve_gloss(lemma) — when present AND same pack as lexicon,
       compose POS-framed fluent sentence:
         "Truth is a claim or state grounded by evidence and
          coherent judgment. Pack-grounded (en_core_cognition_v1)."
       sets is_fluent_sentence=True.
    3. Else fallback to original ADR-0048 dotted-disclosure form:
         "truth — pack-grounded (en_core_cognition_v1):
          cognition.truth; logos.core; epistemic.ground.
          No session evidence yet."
       sets is_fluent_sentence=False.

  pack_grounded_surface(lemma) -> str | None
    Renders the candidate's surface field.  Returns None for OOV.
    Both fluent and disclosure surfaces carry the
    "pack-grounded ({pack_id})" provenance marker so existing
    substring-permissive tests continue to pass through the
    transition.

POS-framed sentence templates (_frame_gloss):
    NOUN  -> "{Lemma} is {gloss}."
    VERB  -> "To {lemma} means {gloss}."
    ADJ   -> "Something is {lemma} when it {gloss}."
    ADV   -> "{Lemma} indicates {gloss}."
    ADP   -> "{Lemma} is a relation of {gloss}."
    SCONJ -> "{Lemma} introduces {gloss}."
    PRON  -> "{Lemma} asks for {gloss}."
    AUX   -> "{Lemma} expresses {gloss}."
    INTJ  -> "{Lemma} is uttered to {gloss}."
    DET   -> "{Lemma} specifies {gloss}."
    NUM   -> "{Lemma} is the cardinal value {gloss}."

Phase C glosses (sitting in /tmp from the 5-subagent parallel
dispatch) are authored to fit these frames exactly.

NO GLOSSES SHIP IN THIS COMMIT.  This is the wiring; the content
arrives in the Phase C commit.  Today every pack still emits the
original dotted-disclosure form because no glosses.jsonl exists yet
on any pack.

Verification:
  97/97 affected tests green (pack grounding, resolver, glosses,
  procedure surface, correction topic, meta pack).
  Cognition eval byte-identical on both splits.
  Live probe with no glosses: surface format identical to pre-fix.
2026-05-19 07:26:46 -07:00
..
__init__.py
__main__.py
anaphora.py feat(adr-0066): session-thread context + opt-in anaphora prefix (Phase 3.1 + 3.2) 2026-05-18 17:01:34 -07:00
cross_pack_grounding.py feat(adr-0067): cross-pack teaching chains — Plan Phase 4 closed 2026-05-18 17:22:43 -07:00
example_surface.py feat(adr-0067): cross-pack teaching chains — Plan Phase 4 closed 2026-05-18 17:22:43 -07:00
narrative_surface.py feat(adr-0067): cross-pack teaching chains — Plan Phase 4 closed 2026-05-18 17:22:43 -07:00
oov_surface.py feat(adr-0066): NARRATIVE + EXAMPLE intents with multi-clause composers (Phase 3.3 + 3.4) 2026-05-18 17:01:55 -07:00
pack_grounding.py feat(pack-grounding): selector-ready gloss wiring via PackSurfaceCandidate 2026-05-19 07:26:46 -07:00
pack_resolver.py feat(pack-resolver): gloss resolver with lexicon-residency + dual-checksum hardening 2026-05-19 07:24:36 -07:00
pack_surface_candidate.py feat(pack-grounding): selector-ready gloss wiring via PackSurfaceCandidate 2026-05-19 07:26:46 -07:00
partial_surface.py feat(adr-0065): OOV cliff → five-tier honesty gradient (Phase 2.1 + 2.2) 2026-05-18 16:41:45 -07:00
refusal.py
runtime.py fix(runtime): config-replace + thin API wrappers + stale docstring 2026-05-19 07:04:10 -07:00
teaching_grounding.py feat(packs): en_core_relations_v2 — pronouns + role-fillers (Phase 2.4) 2026-05-18 16:42:02 -07:00
telemetry.py feat(adr-0059): correction-pass telemetry emission — backward perturbation auditable 2026-05-18 13:47:48 -07:00
thread_context.py feat(adr-0066): session-thread context + opt-in anaphora prefix (Phase 3.1 + 3.2) 2026-05-18 17:01:34 -07:00
verdicts.py