Repository navigation
Conversation
…nfigurable partial credit
The scorer fell through to the wrong-effect penalty for the new outcome. It now uses the receipt's scalar (unscored when the receipt has none), and the timeout task accepts a stop after the one right save.
# Conflicts: # packages/flow/tests/test_harness2_adapter.py
Independent adversarial review: APPROVEFrom: Codex. Reviewed 1cdf013 in a fresh detached worktree with fresh locked environments. The finite, below-verified policy checks ( Validation: Types installs without Flow/cv2/onnxruntime; 770 tests pass, 2 skip. Affected Flow reward/Harness and adjacent suites: 184 pass, 7 skip. Types Ruff/oldest-syntax check and Flow Ruff/format/mypy pass (591 sources). Twelve independent probes pass: real SQLite partial receipts for every stop signal, client scalar handling, signature tampering, custom-credit certificate binding, invalid/uncertain receipts, missing baselines and harmful-write precedence. The optional Harness² package was not installed, so its package integration cases skip. Tests used synthetic public fixtures, headless browsers and the Linux resource gate. No training result is claimed. I did not change or push the reviewed branch. |
Part of OpenAdaptAI/openadapt-internal#102 (the code change; a pre-registration is tracked there).
What changed
The reward contract can now score the case where the required effect is present but the policy asked a person instead of declaring done. Until now that case was unscored. New outcome
escalated_after_effect, new scoring classpartial_credit.New field
escalated_after_effect_reward, default 0.5, range [0, 1), finite. A validator refuses it unless it is belowverified_reward. It is part of the contract digest. The docstring and REWARD.md explain that the value sets the policy's threshold for declaring done rather than asking:(x - w) / (v - w), which is 75% with the defaults (1, -1, 0.5).judge_episode: after a halt, refuse or policy-reject signal, if every required effect is CONFIRMED and no forbidden effect is present, the outcome isescalated_after_effectwith no uncertainty.wrong_effect.reconciliation_required, unscored. That keeps the existing handling for an escalation after a wrong write.Evidence receipts: a partial-credit receipt must have a scalar of 0 or more and carry no uncertainty, the same rule as
verified.JSON schemas (
reward-contract-v1.json,reward-evidence-receipt-v1.json), types/docs/REWARD.md and flow/docs/REWARD_WORKER.md are updated to match.Harness² read-back scorer (
integrations/harness2/scorer.py): it fell through to the -0.5 wrong-effect penalty for the new outcome, which CI caught intest_harness2_adapter.py.escalated_after_effectis now the signed receipt's own scalar, the contract's value. With no scalar on the receipt it stays unscored.mockmed/timeouttask now also acceptsescalated_after_effect. A stop after the one right save used to come out asreconciliation_required, which the task accepted. A wrong, stray or duplicate write still never passes.OutcomeLiteralnow list the outcome.How it was tested
types: 770 passed, 2 skipped. New tests:
verified_rewardflow reward tests (
tests/test_reward*.py): 71 passed. New tests: each halt signal with the effect confirmed gives partial credit; a wrong write after a halt is still reconciliation; a forbidden effect after a halt is stillwrong_effect.flow ruff check, ruff format --check, mypy (589 files) and check_consistency.py pass.
Harness²:
tests/test_harness2*.pyandtests/test_reward*.pygive 104 passed, 6 skipped. The 6 skips need the optionalharness2package, which isn't installed locally; CI runs them. Changes and new tests:escalated_after_effectwith 0.5 (it wasreconciliation_required, unscored).What couldn't be tested
pytest -n 6 tests) hung for more than 60 minutes.--timeout 600reached about 12%. The only errors by then were intests/test_desktop_check_it_cli_mockmed.py: its setup times out.test_reward_worker,test_reward_trust_boundary,test_narration_rules,test_undo_proposalandtest_probe_induction(150 passed, 1 skipped). The types tests also pass (770 passed, 2 skipped).