Commit graph

1 commit

Author SHA1 Message Date
Shay
c6b4f1d21e fix(runtime): config-replace + thin API wrappers + stale docstring
Three independent hygiene fixes named in the 2026-05-19 design review.
All small, all observable, none architectural.

1. ``RuntimeConfig`` flag drop on pack_id / frame_pack override
   chat/runtime.py:306-320 used to enumerate fields by hand when
   reconstructing RuntimeConfig under the pack_id / frame_pack
   override path.  The list stopped at ``admissibility_margin`` and
   silently dropped FIVE newer flags: identity_pack, ethics_pack,
   forward_graph_constraint, composed_surface, thread_anaphora.
   Caller side-effect:

     ChatRuntime(pack_id="x", config=RuntimeConfig(composed_surface=True))
       .config.composed_surface == False  # silently lost

   Fix: ``dataclasses.replace(config, input_packs=..., frame_pack=...)``.
   Every field on the dataclass survives by construction; future
   additions never need a synchronized edit on this path.

2. Stale CAUSE / VERIFICATION docstring
   tests/test_intent_classification_extensions.py described a sixth
   runtime-side fix (pack_grounded_surface fallback for
   CAUSE/VERIFICATION) that was considered, reverted, and the file's
   own test classes pin the opposite contract.  Docstring now states
   the doctrine correctly: no fallback, deliberately, so the discovery
   layer can log the teaching-gap signal.

3. Thin convenience wrappers: respond / achat / arespond
   tests/test_achat.py and tests/test_language_pack_runtime.py
   referenced these public methods since 2026-05-14, but they were
   never implemented on ChatRuntime — those 12 tests had been red on
   every full-lane run since the rebase.  Added as thin wrappers:

     respond(text) -> ChatResponse.surface
     achat(text)   -> async wrapper around chat()
     arespond(text)-> async wrapper around respond()

   The async wrappers are deliberately NOT genuinely non-blocking —
   the underlying CPU-bound walk/recall/composition remains sync.
   Docstrings say so explicitly.  Callers needing real concurrency
   should wrap in asyncio.to_thread at the call site; promoting the
   wrappers to true async event-loop integration is a future change
   gated by an actual concurrent caller.

Regression coverage:
  tests/test_runtime_config_passthrough.py — 4 tests
    - all 19 RuntimeConfig fields survive a pack_id override
    - all five newer flags survive a frame_pack override
    - no-override path preserves caller config by identity (no rebuild)
    - the four public methods exist and are callable

Verification:
  44/44 affected tests green (was 12 red pre-fix).
  Cognition eval byte-identical on both splits.
  No surface-format change; this commit is pure plumbing.
2026-05-19 07:04:10 -07:00