BOHICA-LABS / BOHICA-LABS/vsdd-factory
process-gap(orchestrator+adversary): wave-level adversarial dispatch has no pre-flight local-vs-origin sync check — halts on stale checkout when STATE.md is ahead of local develop
- Dominant language
- Rust
- Stars
- 2
- Forks
- 1
- Avg merge
- 6h 43m
- Merged PRs (30d)
- 29
Description
## Summary
When a session resumes after prior work has merged PRs to `origin/develop`, the local `develop` branch may be behind origin. `STATE.md` correctly records the merged SHA (from the prior session's authoritative view), but the checkout does not. Wave-level (or per-story) adversarial dispatch that reads the working tree then halts with a state-integrity CRITICAL because the referenced implementation files "do not exist" — when in fact they exist on `origin/develop` and the checkout is simply stale.
This wastes one full adversary pass on a diagnosable precondition failure.
## Evidence — switchboard-blue Wave-6 Tranche B wave-level Pass-1 (2026-07-01)
- Prior session merged 3 PRs to `origin/develop`: S-7.01 (#43, 5c658e7), S-7.02 (#55, c54a8ad), S-BL.ROUTER-ADDR (#56, 91d5675).
- Prior session's state-manager correctly updated `.factory/STATE.md`:
- `develop_head: 91d5675`
- `phase_3_completed_stories: [..., S-7.01, S-7.02, S-BL.ROUTER-ADDR]`
- `wave_6_tranche_b_closed_at: 2026-07-01`
- This session's local `develop`: `446efce` (3 commits behind `origin/develop`).
- Wave-level Pass-1 adversary dispatched, expected `develop @ 91d5675`.
- Adversary correctly halted with dispatch-integrity CRITICAL:
> \`internal/arq/fec.go\` — Glob returned no files.
> \`internal/discovery/\` — does not exist.
> \`PathSnapshot\` — has no \`RouterAddr\` field.
> \`refs/heads/develop\` = 446efce, not 91d5675.
- Diagnosis: local checkout stale. Single fix: \`git fetch origin && git merge --ff-only origin/develop\` (3831 insertions FF'd). Re-dispatched Pass-1 → substantive findings.
The adversary's halt was correct behavior on its own; the gap is upstream — orchestrator dispatch of wave-level review has no preflight guarding against this class of miss.
## Root cause
Adversarial dispatch (wave-level and per-story) is defined relative to a specific SHA in STATE.md, but the working tree at that SHA is only guaranteed if the local checkout is at least as fresh as \`origin/HEAD\`. On session resume — the exact case where the freshest work was done by a prior session — this invariant is at highest risk of being violated.
## Proposed fix
Insert a preflight step into wave-level and per-story adversarial dispatch (either in the orchestrator's dispatch template or as a check the adversary itself performs first):
\`\`\`bash
git fetch origin --quiet
LOCAL=\$(git rev-parse develop)
REMOTE=\$(git rev-parse origin/develop)
STATE_HEAD=\$(yq '.develop_head' .factory/STATE.md) # or grep
if [ \"\$LOCAL\" != \"\$REMOTE\" ] || [ \"\$LOCAL\" != \"\$STATE_HEAD\"* ]; then
echo \"CHECKOUT DRIFT: local=\$LOCAL, origin=\$REMOTE, state=\$STATE_HEAD\"
echo \"Fix: git merge --ff-only origin/develop, then re-dispatch\"
exit 1
fi
\`\`\`
Alternative: encode as a factory-health check that runs at session-resume time (adjacent to worktree-health).
## Cross-refs
- Adjacent to but distinct from #389 (dispatch-tuple embedding inaccurate symbol path — that's a symbol-mapping error, this is a base-SHA freshness error).
- Adjacent to but distinct from #386 (adversary stall on large context — that's a runtime hang, this is a wasted deterministic pass).
## Impact
- One full wave-level or per-story adversary pass wasted per session-resume with a stale checkout.
- False-CRITICAL findings could be mis-interpreted as "merge lost" or "STATE.md wrong" and trigger a destructive recovery attempt (fortunately caught here by explicit diagnosis).
## Severity
MEDIUM. Wastes tokens/time; masquerades as a data-integrity emergency until diagnosed.
Contributor guide
Assessment
This issue has not been assessed yet.