Skip to content

fix: the served gate trusts only the runner's own marker, and a findings JSON must hold one value - #168

Merged
STRML merged 2 commits into
mainfrom
fix/served-gate-provenance
Oct 29, 2026
Merged

STRML merged 2 commits into
mainfrom
fix/served-gate-provenance

Conversation

@STRML

@STRML STRML commented Oct 29, 2026

Copy link
Copy Markdown
Owner

Closes #167.

AUTODREAM_L1_REQUIRE_SERVED=1 decided a cached record was the runner's own by reading its keys, which a worker can write too. And every findings check used jq -e, which judges only the last value in a file.

Shape a substituted model writes Before After
{"error":"unreadable","findings":[]} kept as the runner's, verdict skipped, session never retriaged no runner marker, held to its verdict, retriaged
{"no_engine":true,"error":"x","findings":[]}, source has no engine kept dropped, the runner writes its own marked record
{"findings":[forged]} then {"skipped":true,"findings":[]} passed every check, L2 read the forged finding not a result, gate or no gate, retriaged
runner writes a record ─▶ <hash>.json + <hash>.json.served = "runner"
                                              │
drop_unacceptable_l1_cache ─▶ verdict runner + findings [] ? keep : verdict match ? keep : drop
  • The dispatcher writes .served reading runner beside each of its five records (unreadable, noise gate, normalize failure, no engine, final-round stub). That marker is the only exemption from the verdict.
  • A no-engine record is still dropped by its shape once its source resolves an engine. A forged one buys a retriage, nothing more.
  • L1_FINDINGS_OK under jq -s (one value, an object, a findings array) replaces the five jq -e ".findings | arrays" checks. It is the rule merge-chunks.sh --check already applied to chunk answers.
  • Runner records written before this change have no marker, so with the gate on they are triaged once more and come back marked. With the gate off nothing changes beyond the single-value check.

Tests: test_require_served_trusts_only_the_runners_own_marker and test_a_findings_json_with_two_values_is_not_a_result, 13 assertions, all red on main. Full suite 3,097 passed. The 4 failures only happen inside the Claude Code sandbox (no ps, no TTY) and are the same as on main. Both shellcheck gates are clean.

STRML added 2 commits October 29, 2026 14:16
…ngs JSON must hold one value

Root cause: drop_unacceptable_l1_cache decided a record was the runner's own from its keys (error or skipped with findings: []), which a worker can write as easily as the runner. A substituted model's {"error":"unreadable","findings":[]} skipped the served verdict and left its session untriaged. Separately, every findings check used jq -e, which judges only the last value in a file, so a forged object followed by a valid one passed and L2 read the first.

- The dispatcher writes .served = runner beside each record it writes itself (unreadable, noise gate, normalize failure, no engine, final-round stub). Under AUTODREAM_L1_REQUIRE_SERVED=1 that marker, plus empty findings, is the only exemption from the verdict. A runner record from before the marker is triaged once more.
- A no-engine record is still dropped by shape once its source resolves an engine; keeping one under the gate now takes the marker.
- One filter, L1_FINDINGS_OK under jq -s (exactly one value, an object, a findings array), replaces the five jq -e checks.

Closes #167
…und's result

Root cause (Codex round 1 on PR 168): the worker rejected a cached file that failed L1_FINDINGS_OK but left it in place, and every later step treats a non-empty $output as a result. A chunk that kept failing then skipped the final-round stub and the rejected file reached L2. It now moves to <hash>.json.rejected, which no *.json glob reaches, before anything else runs.

Also documents the limit the served markers share with the match verdict: a worker that rewrites another session's record and .served together is not caught by checks on files in the findings dir.
@STRML
STRML merged commit 82fdd83 into main Oct 29, 2026
6 checks passed
@STRML
STRML deleted the fix/served-gate-provenance branch October 29, 2026 18:46
drycode added a commit to drycode/cc-autodream that referenced this pull request Oct 29, 2026
STRML#165 was squash-merged upstream as 2875df0 after two review rounds,
and STRML#168 (82fdd83) closed the last two cache-verdict holes on top of
it. The fork's only content beyond the shared base was the three
pre-review STRML#165 commits from PR #2, all superseded by the reviewed
version, so every path takes upstream's: the tree is upstream's main.
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.

REQUIRE_SERVED still trusts the file to say who wrote it

1 participant