test(console): pin what the engine actually emits for every halt category - #294
test(console): pin what the engine actually emits for every halt category#294abrichr wants to merge 3 commits into
Conversation
|
Note for the This is a deliberate interaction, not a conflict. When
The fix is one command plus a read of the diff: and, if the action becomes offerable at a pause, the per-halt |
…gory
A demo or sample fixture stays schema-valid and digest-consistent forever,
because both properties are computed from the fixture itself. Nothing anywhere
asserted that a fixture is still a shape this engine can emit, so the mapping
tables in `console.human_decisions` and the accept-list in `console.attention`
could move -- both did this cycle -- and every downstream test would stay green
while the fixture described last month's product.
This commits `tests/golden/human_decision_tasks.json`, regenerated from real
engine output: one durable pause per halt category the controller can classify,
each projected through `portable_remote_decision_task` (the Cloud-bound
projection, with `presentation` already discarded). The artifact records the
category -> (task_kind, question.template) map, the uncertain-delivery
override, the action vocabulary, the safe-slot and evidence key sets, the slots
the engine never populates, and which task kinds and templates are emitted at
all.
The test walks both documents together, so a failure names the exact field:
golden drift at category_question_map.resolution.question_template: the
engine now emits 'review_halt', the artifact still says 'resolve_ambiguity'
Proven to bite: rewriting `_TASK_COPY["resolution"]` and dropping "resolution"
from `_KNOWN_CATEGORIES` each fail with the field named, and both were restored.
Two facts the artifact now makes checkable by a consumer:
* `never_populated_safe_slots` is `["candidate_count"]`. Any surface that says
"found N matches" is asserting a number the engine has never sent.
* `never_emitted_task_kinds` is `["operator_review"]`. No Flow path emits it.
Regenerate deliberately with `OPENADAPT_UPDATE_GOLDEN=1` and read the diff:
every line of it is a change to what an operator is told.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM
`public-artifacts.json` is the reviewed positive inventory every `.json` in the public source tree must appear in, with its exact SHA-256, before the wheel and sdist boundary check will pass. Regenerated with `--write-public-artifact-inventory`; the diff is exactly one line, the golden artifact this branch adds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM
1b4b70f to
a695e09
Compare
PR #295 made `reject` an always-available attended action, so the engine now emits it in `action_vocabulary` and in `allowed_actions` for every halt category. The committed artifact predates that change and still lists four actions. Regenerated with OPENADAPT_UPDATE_GOLDEN=1. The vocabulary assertion compares `_ACTION_MAP` against `openadapt_types.HumanDecisionAction` rather than a hand-copied list, which is what caught the drift.
a695e09 to
0a22ccb
Compare
|
Closing this stale contract PR without deleting its branch. Current main includes PR #296, where RemoteDecisionProjection adds the outer delivery_tier and halt_context fields. This PR's generator records only projection.task while describing the artifact as the exact Cloud projection, so its current golden cannot validate the contract that Flow now emits. It also conflicts in public-artifacts.json. Preserve the branch for reference. A later focused PR can regenerate the contract from current main and either cover the complete outer projection or narrow the claim to the signed task only. |
The gap
A demo or sample fixture stays schema-valid and digest-consistent forever, because both properties are computed from the fixture. Nothing anywhere asserted that a fixture is still a shape this engine can emit.
That is not theoretical. The mapping tables in
console/human_decisions.pyand the accept-list inconsole/attention.pyboth moved this cycle. Every downstream test would have stayed green while a fixture described last month's product — which is exactly what would have happened silently between the merge of #290 and today.What this adds
tests/golden/human_decision_tasks.json, regenerated from real engine output: one durable pause per halt categorycontroller.classify_halt()can produce, each projected throughportable_remote_decision_task()— the Cloud-bound projection, withpresentationalready discarded, so nothing in the artifact describes evidence the dashboard is not entitled to.The artifact records:
category_question_map(task_kind, question.template)a fixture may claimdelivery_uncertain_overrideaction_vocabularysafe_slot_fields/evidence_fieldsnever_populated_safe_slots=["candidate_count"]never_emitted_task_kinds=["operator_review"]halts[]attention._normal_categorymade of it, the delivery state, the resulting kind/template, non-null slots, allowed actionsFour tests: the golden comparison; the action vocabulary is exactly the portable enum;
teachandescalateare offered at every pause (proven from real capabilities, not from reading_allowed_actions); and an anchor that a replayer-driven halt —Replayer(durable=True).run(...), nobody's hand-built pause — lands on the same golden row.Proof it bites
The comparison walks both documents together, so a failure names the exact field rather than dumping two documents at each other. Two mutations, both restored afterwards:
_TASK_COPY["resolution"] -> ("halt", "review_halt", ...):golden drift at category_question_map.resolution.question_template: the engine now emits 'review_halt', the artifact still says 'resolve_ambiguity'"resolution"fromattention._KNOWN_CATEGORIES:golden drift at halts.resolution.projected_category: the engine now emits 'operator_review', the artifact still says 'resolution'Regenerate deliberately with
OPENADAPT_UPDATE_GOLDEN=1 pytest tests/test_human_decision_golden.py; the run is ~0.9s and adds no CI leg.Boundary
The artifact is closed-vocabulary metadata — enum names, key names, and counts. No values, no run content, no PHI, no tuning. Mechanism, not data, so it is on the public side of
AGENTS.md4.2.Consumers
openadapt-cloudvendors this file and checks its/demo/attentionand?sample=eligibilityfixtures against it (companion PR). Nothing in Flow's behaviour changes here — this PR is test-only.Noted, not fixed
Two findings this work surfaced; both are in the shared attended projection another lane is editing, so neither is touched here:
delivery_uncertainis missing fromattention._KNOWN_CATEGORIES. The golden artifact records it:halts.delivery_uncertain.projected_categoryisoperator_review, notdelivery_uncertain. The task kind still recovers at the next layer, so the operator gets the right question, but the queue headline is the generic "This run needs local operator review" for the one halt where the operator must reconcile rather than retry. Fix is two edits — add the category to_KNOWN_CATEGORIESand give it a_COPYentry — and the golden file will show the change.tests/test_halt_detail.py::test_resolution_halt_says_what_broke_and_what_continue_will_recheckfails onorigin/mainin a freshlyuv sync --all-extras'd tree (halt["target_label"]isNone, expected"Open"), independent of this branch. Flagging for whoever owns_safe_target_label.🤖 Generated with Claude Code
https://claude.ai/code/session_01NyCHrzA1psrKMFfroYbzaM