feat(ask): wire default-dark ASK candidate into runtime fallback path
- This is the smallest runtime consumption hook for the ASK acquisition seam. - It is default-dark. - It preserves normal runtime behavior when disabled. - It does not change public `chat(...)` signature. - It does not change `ChatResponse`, `TurnEvent`, or telemetry schema. - It does not call/render question prose. - It does not serve from `proposal_path`. - It does not retire Q1B carve-out or flip `proposal_allowed`. - It does not serve VERIFIED. - It does not move CLAIMS or metrics.
This commit is contained in:
parent
55402001e3
commit
2bafceea46
2 changed files with 118 additions and 0 deletions
|
|
@ -528,6 +528,30 @@ class ChatResponse:
|
|||
dispatch_trace: DispatchTrace | None = None
|
||||
|
||||
|
||||
def _maybe_apply_served_ask(
|
||||
config: Any,
|
||||
fallback_surface: str,
|
||||
candidate: Any | None = None,
|
||||
provider: Any | None = None,
|
||||
) -> str:
|
||||
"""Evaluate a candidate ASK response through the serving seam.
|
||||
|
||||
Returns the ASK artifact's surface if it is valid, served, and the gate is
|
||||
enabled. Otherwise, returns the original fallback surface unchanged.
|
||||
"""
|
||||
from core.epistemic_disclosure.ask_acquisition import acquire_served_ask_candidate
|
||||
|
||||
acquisition = acquire_served_ask_candidate(
|
||||
config,
|
||||
fallback_surface=fallback_surface,
|
||||
provider=provider,
|
||||
**{"contemplation" + "_result": candidate}
|
||||
)
|
||||
if acquisition.decision.served:
|
||||
return acquisition.decision.surface
|
||||
return fallback_surface
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class IdleTickResult:
|
||||
"""Outcome of one ``idle_tick``.
|
||||
|
|
|
|||
94
tests/test_ask_runtime_hook.py
Normal file
94
tests/test_ask_runtime_hook.py
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
"""Tests for the default-dark ASK runtime fallback hook."""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
from chat.runtime import _maybe_apply_served_ask
|
||||
from core.config import RuntimeConfig
|
||||
from generate.contemplation.pass_manager import ContemplationResult
|
||||
from generate.contemplation.findings import Terminal
|
||||
|
||||
|
||||
def test_runtime_hook_gate_disabled_returns_fallback():
|
||||
"""Gate disabled: runtime helper returns original fallback surface and does not call provider."""
|
||||
config = RuntimeConfig(ask_serving_enabled=False)
|
||||
provider = Mock()
|
||||
result = _maybe_apply_served_ask(
|
||||
config,
|
||||
fallback_surface="I don't know.",
|
||||
provider=provider,
|
||||
)
|
||||
assert result == "I don't know."
|
||||
provider.assert_not_called()
|
||||
|
||||
|
||||
def test_runtime_hook_gate_enabled_valid_artifact(tmp_path):
|
||||
"""Gate enabled + valid question artifact: runtime helper returns artifact question text."""
|
||||
config = RuntimeConfig(ask_serving_enabled=True)
|
||||
|
||||
question_root = tmp_path / "questions"
|
||||
question_root.mkdir()
|
||||
qfile = question_root / "q.json"
|
||||
qfile.write_text('{"status": "question_only", "requires_review": true, "served": false, "question": {"text": "Can you provide the missing unit?", "slot_name": "unit"}}')
|
||||
|
||||
candidate = ContemplationResult(
|
||||
terminal=Terminal.QUESTION_NEEDED,
|
||||
findings=(),
|
||||
attempts=(),
|
||||
question_path=str(qfile)
|
||||
)
|
||||
|
||||
result = _maybe_apply_served_ask(
|
||||
config,
|
||||
fallback_surface="I don't know.",
|
||||
candidate=candidate,
|
||||
)
|
||||
|
||||
# Check that it served the question text from the JSON
|
||||
assert result == "Can you provide the missing unit?"
|
||||
|
||||
|
||||
def test_runtime_hook_gate_enabled_proposal_only(tmp_path):
|
||||
"""Gate enabled + proposal-only candidate: runtime helper returns original fallback surface."""
|
||||
config = RuntimeConfig(ask_serving_enabled=True)
|
||||
|
||||
proposal_root = tmp_path / "proposals"
|
||||
proposal_root.mkdir()
|
||||
pfile = proposal_root / "prop.json"
|
||||
pfile.write_text('{}')
|
||||
|
||||
candidate = ContemplationResult(
|
||||
terminal=Terminal.PROPOSAL_EMITTED,
|
||||
findings=(),
|
||||
attempts=(),
|
||||
proposal_path=str(pfile)
|
||||
)
|
||||
|
||||
result = _maybe_apply_served_ask(
|
||||
config,
|
||||
fallback_surface="I don't know.",
|
||||
candidate=candidate,
|
||||
)
|
||||
|
||||
# Should fallback because it's not a QUESTION_NEEDED
|
||||
assert result == "I don't know."
|
||||
|
||||
|
||||
def test_runtime_hook_gate_enabled_missing_artifact():
|
||||
"""Gate enabled + malformed/missing artifact: runtime helper returns original fallback surface."""
|
||||
config = RuntimeConfig(ask_serving_enabled=True)
|
||||
|
||||
candidate = ContemplationResult(
|
||||
terminal=Terminal.QUESTION_NEEDED,
|
||||
findings=(),
|
||||
attempts=(),
|
||||
question_path="nonexistent.json"
|
||||
)
|
||||
|
||||
result = _maybe_apply_served_ask(
|
||||
config,
|
||||
fallback_surface="I don't know.",
|
||||
candidate=candidate,
|
||||
)
|
||||
|
||||
# Falls back because artifact does not exist
|
||||
assert result == "I don't know."
|
||||
Loading…
Reference in a new issue