Bundle of 5 hot-path optimizations + 1 dead-code removal + 1 import
sweep + 1 helper fold, surfaced by a comb pass through the cognitive
spine starting from ``CognitiveTurnPipeline.run()`` and walking
outward through ChatRuntime, intent classification, the graph
planner, the realizer, and the vault. All eval lanes byte-identical
to MEMORY baseline; null-lift confirmed by ``core eval cognition``
across public / dev / holdout splits.
Hot-path fixes:
1. ``ChatRuntime._apply_oov_policy`` no longer rescans every
manifest per OOV token. Two precomputed booleans on
``self`` capture the FAIL_CLOSED-all and PROPOSE_VOCAB-any
aggregates at construction time. Manifests are immutable
post-construction so the cache is safe. Turns the path from
O(packs × OOV) to O(OOV).
2. ``CognitiveTurnPipeline.run`` calls ``classify_compound_intent``
once and takes its dominant ``compound.primary`` as the seeded
intent. Pre-fix the pipeline called both ``classify_intent``
and ``classify_compound_intent`` on every turn — and
``classify_compound_intent`` internally invokes
``classify_intent`` on the dominant fragment, so every non-
compound prompt walked the 15-regex cascade twice.
3. ``TeachingStore.triples()`` materializes once per turn.
Pre-fix ``_maybe_transitive_walk`` and ``_maybe_compose_relations``
each called ``self.teaching_store.triples()`` independently,
doubling the per-turn O(N) filter+tuple-build cost. Both
helpers now accept an optional ``triples`` arg; the pipeline
computes once and passes through.
5. ``realize_semantic`` and ``realize_target`` build a
``node_id → obj`` map once and look up each step in O(1)
instead of an O(N) linear scan of ``graph.nodes`` per step.
The cost was invisible on today's 1-2 node graphs but would
have become an O(N²) regression on the multi-node graphs
ADR-0089 Phase C2 plans to introduce.
Dead-code / cleanup:
- Removed dead ``CognitiveTurnPipeline._fold_compose_into_surface``
(no callers since PR #76 routed all surface composition
through ``resolve_surface``).
- Folded ``_serialize_walk`` + ``_serialize_compose`` (identical
bodies) into one ``_serialize_operator`` helper.
- Hoisted ``import json`` and ``RatifiedIntent`` from inside hot
method bodies to module top (same pattern PR #76 applied to
``_is_useful_surface``).
- Dead-defensiveness sweep on ``ChatResponse`` field reads in
``pipeline.run()``: ``getattr(response, "<field>", default)``
where the field always exists on the dataclass with a default
is replaced by direct attribute access (6 sites:
``realizer_grounded_authority``, ``recalled_words``,
``grounding_source``, ``register_canonical_surface``,
``pre_decoration_surface``, ``admissibility_trace``,
``region_was_unconstrained``). ``refusal_reason`` retains the
guarded read because ADR-0024 Phase 2 leaves its
materialisation site dormant.
Benchmark profiler:
- ``benchmarks/pipeline_profiler.py`` rebound from
``classify_intent`` to ``classify_compound_intent`` (the new
single-classification site). All other timing hooks unchanged.
Tests:
- 4 new tests in ``tests/test_comb_pass_hot_path.py`` pin: OOV
aggregates exist as bools; compound classifier runs exactly
once per turn; ``triples()`` materializes exactly once per
turn; realizer correctly resolves obj slots across an 8-node
graph.
- All existing tests pass. ``core eval cognition`` byte-identical:
public 100/100/91.7/100, dev 100/100/78.6/100, holdout
100/100/83.3/100.
- ``core test --suite cognition`` 120/0/1, ``smoke`` 67/0,
``runtime`` 19/0.