This repository was archived by the owner on Aug 12, 2026. It is now read-only.
fix(verifier): expect_only_v2 enforces completeness, not just no-side-effects [ENVT-140646] - #139
Draft
samfleet-ai wants to merge 1 commit into
Draft
fix(verifier): expect_only_v2 enforces completeness, not just no-side-effects [ENVT-140646]#139samfleet-ai wants to merge 1 commit into
samfleet-ai wants to merge 1 commit into
Conversation
…-effects expect_only_v2 historically only enforced the no-side-effects half of its contract: an empty diff (agent made zero changes) vacuously satisfied "only expected changes occurred" because the empty set is a subset of any set. This let weight-0.5 ec_diff / validate_expected_changes partials award full credit for total inaction — the perverse incentive where doing nothing scores higher than partial-but-imperfect completion (canonical bug cac765f5, Linear ENVT-140646). Add require_completeness=True (default) to expect_only_v2 on both the sync (SyncSnapshotDiff) and async (AsyncSnapshotDiff) SQLite diff engines, plus the local SnapshotDiff used by tests. When enabled, every spec carrying an explicit type (insert/modify/delete) must also be realised in the current DB — mirroring the completeness half of expect_exactly. Specs without an explicit type (legacy whole-row / single-field specs) are skipped so only the v2 format gets the stricter behaviour. Pass require_completeness=False to preserve the legacy no-side-effects-only semantics. Fixes ENVT-140646.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
expect_only_v2historically only enforced the no-side-effects half of its contract: an empty diff (agent made zero changes) vacuously satisfied "only expected changes occurred" because the empty set is a subset of any set. This let weight-0.5validate_ec_diff/validate_expected_changespartials award full credit for total inaction — the perverse incentive where doing nothing scores higher than partial-but-imperfect completion.Canonical bug:
cac765f5-a7ae-4598-85c7-c3aa06df8a15Linear: ENVT-140646
Closes ENVT-140646
Root cause
expect_only_v2(syncSyncSnapshotDiff, asyncAsyncSnapshotDiff, and the localSnapshotDiffused by tests) checked that no changes occurred outside theexpected_changeslist, but never verified that each expectedinsert/modify/deleteactually occurred. When the agent made zero changes, the diff was empty, the no-side-effects assertion did not raise, and the partial returnedTASK_SUCCESSFUL_SCORE— awarding the full weight (0.5) for doing nothing.Confirmed across four fira tasks (
task_kkv56yscvrsp,task_i5tiyuu6dpc,task_iv8utut98jmo,task_krkgb4vpc9mc) onfira v1.1.101h / cultivacore v0.0.39in the canonical bug's verification evidence.Fix
Add
require_completeness: bool = Truetoexpect_only_v2on all three diff engines. When enabled (the new default), a completeness pass verifies that every spec carrying an explicittype(insert/modify/delete) is realised in the current DB:insert: the row must be present in the current DB (andfieldsvalues match if specified)delete: the row must be absent from the current DBmodify: the row'sresulting_fieldsvalues must match the expected values in the current DBSpecs without an explicit
type(legacy whole-row / single-field specs) are skipped, so only the v2 format gets the stricter behaviour. Passrequire_completeness=Falseto preserve the legacy no-side-effects-only semantics.expect_exactly(which already enforced both halves) is unchanged.Validation
Focused verifier tests in
tests/test_expect_only.py(7 new tests):test_expect_only_v2_completeness_zero_changes_modify_fails— the reported bug: zero DB changes + non-empty modify spec now raisesAssertionErrortest_expect_only_v2_completeness_zero_changes_insert_fails— expected insert that did not occur failstest_expect_only_v2_completeness_zero_changes_delete_fails— row still present fails the delete spectest_expect_only_v2_completeness_seed_already_has_expected_values_passes— if the seed already has the expected resulting state, completeness passes (no false failure)test_expect_only_v2_require_completeness_false_preserves_vacuous_pass— opting out preserves legacy behaviourtest_expect_only_v2_completeness_partial_changes_fails— only some expected changes made → fails for the missing ones onlytest_expect_only_v2_completeness_legacy_specs_skipped— legacy specs withouttypeare not subject to the completeness passEnd-to-end simulation reproducing the fira
validate_ec_diffpartial pattern:TASK_FAILED_SCORE(wasTASK_SUCCESSFUL_SCORE +0.5)require_completeness=False→ legacy vacuous pass preserved (backward compatible)Full suite:
pytest tests/test_expect_exactly.py tests/test_expect_only.py tests/test_verifier_from_string.py→ 151 passed, 11 skipped. (3 pre-existing HTTP-fixture setup errors intest_sqlite_resource_dual_mode.pyare unrelated — they reproduce on cleanmain.)🤖 Created via sandbox session