Skip to content

Make stopping on the claim's success verdict unconditional - #53

Merged
RoldSI merged 1 commit into
mainfrom
fix/stop-on-success-unconditional
Aug 28, 2026
Merged

RoldSI merged 1 commit into
mainfrom
fix/stop-on-success-unconditional

Conversation

@RoldSI

@RoldSI RoldSI commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

Replaces #52, which is closed. Follow-up to #49, which is merged.

Why the flag should not exist

#49 added stop_on_success as a Controller argument. It should not be a flag. The security claim decides success, so running on after a win is never what an ASR measurement wants, and nothing outside the framework ever set it — zero references in superred-modules and superred-experiments, and only 8 test call-sites.

Removing it removes the problem #52 existed to fix. identity_hash() hashes a dict, so keying the flag changed the digest even at its default (ef26fece → 5b18e4e4) and would have orphaned every results tree ever written. The fix was to key it only when disabled, which is machinery that only earns its keep if the disabled state exists. With one regime there is no second directory to distinguish: no identity key, no ExperimentMeta field, no experiment_block entry, no frozen-hash guard needed.

It deletes states rather than adding them

Three tests described scenarios that can no longer occur, and are gone:

  • a task that wins then times out
  • a task that wins then fails (success latching across runs)
  • the opt-out itself

The first was a real source of confusion in a certified results tree: 8 tasks the attacker had already won were recorded as stop_reason="timeout", indistinguishable from tasks that ran out of clock. That state cannot arise now. A TaskResult with success=True always carries stop_reason="success".

Five other tests used the flag only to keep a multi-run scenario alive. They now use a task that does not win, which is what they were actually about.

What is lost

Measuring attack reliability — k of N attempts succeeding, rather than whether any did. Nothing in the codebase does that, and superred measures ASR. If it is wanted later it deserves its own design rather than a flag on this loop.

Net effect

64 insertions, 137 deletions. The controller loses a parameter, an attribute and a branch; the docs lose a knob to explain.

Checks

591 passed · ruff check/format clean · mypy clean on 25 source files.

#49 added `stop_on_success` as a Controller flag. It should not be a flag: the
security claim decides success, so running on after a win is never what an ASR
measurement wants. Nothing outside the framework ever set it, in either
superred-modules or superred-experiments.

Removing it removes the problem #52 existed to fix. `identity_hash()` hashes a
dict, so keying the flag changed the digest even at its default and orphaned
every results tree ever written; the fix for that was to key it only when
disabled, which is machinery that only earns its keep if the disabled state
exists. With one regime there is no second directory to distinguish, no
identity key, no ExperimentMeta field and no experiment_block entry.

It also deletes states rather than adding them. Three tests described scenarios
that can no longer occur and are gone: a task that wins then times out, a task
that wins then fails, and the opt-out itself. The first of those was a real
source of confusion in a certified results tree, where 8 tasks the attacker had
already won were recorded as `stop_reason="timeout"`. A TaskResult with
success=True now always carries stop_reason="success".

Five other tests used the flag only to keep a multi-run scenario alive; they now
use a task that does not win, which is what they were really about.

What is lost is measuring attack RELIABILITY, k of N attempts succeeding rather
than whether any did. Nothing in the codebase does that, and superred measures
ASR. If it is wanted later it needs its own design, not a flag on this loop.

Net 137 deletions against 64 insertions. 591 tests pass.
@RoldSI
RoldSI merged commit ba6fed5 into main Aug 28, 2026
3 checks passed
@RoldSI
RoldSI deleted the fix/stop-on-success-unconditional branch August 28, 2026 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant