# Codex Review Sweep Synthesis — 2026-05-17

31 adversarial reviews fired in one supervisory pass on SF dogfood. 105 findings (5 critical, 57 high, 42 medium, 1 low). Every review verdict: **needs-attention**. This doc surfaces the cross-cutting patterns the per-review headlines don't make obvious.

## Cross-cutting bug classes (ranked by review count)

### 1. Default-on inline dispatch — flagged by 12 reviews
Single most flagged issue. The 2026-05-17 flip from `=== "1"` (opt-in) to `!== "0"` (default-on) is concrete evidence of all of:
- **Cost** [critical]: inline path bypasses unit_metrics ledger, budget enforcement, cache-hit tracking, subscription token updates → SF can spend off-ledger
- **Skills** [high]: bypasses 3-reviewer parallel validate-milestone path documented in dispatching-subagents skill
- **Routing args** [high]: `buildReassessRoadmapPrompt` called with slice title as filesystem base path (positional argument bug)
- **Retry context** [high]: `tryInlineDispatch` ignores `prompt` parameter (named `_prompt`), rebuilds via `buildPromptForUnit`, losing phases-unit retry/repair prompt mutations
- **Permission profile** [medium]: unknown profile falls open to `medium` not `minimal`
- **Cache** [medium]: `promptCacheSplit` dropped on inline rebuild → cache miss every cycle
- **Silent fallback** [high]: DispatchLayer construction error returns `null` → silent legacy routing without observation
- **Test theater** [multiple]: tests mirror the boolean condition instead of exercising `runUnit`

**R074 (hard runtime gate) addresses this; until M048+R066 land, the right move is `=== "1"` opt-in.**

### 2. v73 migration was a mess (my work) — flagged by 5 reviews
- [critical] `SCHEMA_VERSION` not bumped → migration unreachable on existing v72 DBs — **FIXED**
- [high] Migration only set `tier`, not `sequence` → starvation class preserved within tier — **FIXED**
- [high] `state-db.js:661` re-sorts tier-aware rows back to sequence-only queue order — **NOT YET FIXED** (codex:codex-rescue investigating)
- [high] Migration silently succeeds with missing milestone rows (`UPDATE` not checked for `.changes`)
- [high] Failed migration is swallowed by `runMigrationStep`, runtime continues on incompatible schema
- [medium] `insertMilestone` / `importManifest` omit `tier` column → new rows default to 5

### 3. Completion-path bug class (T02 root cause) — flagged by 4 reviews
- [high] `sf-db-tasks.js:431` `setTaskSummaryMd` is a standalone writer that doesn't touch status columns
- [high] `state-db.js:597` `reconcileSliceTasks` detects drift, warns, leaves redispatchable
- [medium] `sf-db-tasks.js:452` `setTaskSummaryFields` partial repair (status yes, task_status no)
- [high] `complete_task` accepts empty `verificationEvidence` and marks status=complete
- [medium] `auto-completion-nudge` stops on `complete_slice` attempt (tool_execution_start), not on success

R072 detector is the right shape; missing piece is the atomic single-writer + reconciler-that-repairs-or-quarantines.

### 4. MessageBus R016 ack-without-deliver — flagged by 3 reviews
- [high] `_busDispatch:318` acks via `bus.send()` without verifying target PersistentAgent inbox can read it
- [high] `agent-runner:242` generic `agent.receive(true)` uses 30s time-based cache, can miss newly dispatched work
- [high] A2A `dispatchAndWait` returns `reply:null` silently when SF_A2A_ENABLED=1 (no synchronous wait implemented)
- [medium] Multi-message coalescing: all marked read, only last sender gets reply
- Concrete repro: warm inbox via `runAgentTurn`, dispatch second message via separate bus within 30s, agent returns no work from stale cache

### 5. Atomic-write violations everywhere — flagged by 4 reviews
- [high] `notification-store:510` rewrites notifications.jsonl without lock under contention
- [high] `web/api/files:161` writes `.sf` files via `writeFileSync` with no atomicity, mtime check, or per-path lock
- [high] Sleeptime jobs (`loop.js:309`) selected and processed without atomic claim → duplication under concurrent drainers
- [medium] R070 `/swarms` aggregator has no atomic-read contract for source `.sf/state.json`
- Cross-cutting fix: standard atomic helper (temp + fsync + rename + ENOENT/parse-tolerant readers)

### 6. Auth / secrets / privilege boundaries — flagged by 2 reviews (security, CLI)
- [high] A2A agent server: NO client authentication on JSON-RPC control endpoint (any local process can submit)
- [high] A2A envelopes parsed and persisted without schema validation
- [high] MCP HTTP auth: project-local `.sf/mcp.json` expands `${ANTHROPIC_API_KEY}`/`${OPENROUTER_API_KEY}` into Authorization headers → malicious repo can exfiltrate API keys
- [high] systemd unit wrote ANTHROPIC_API_KEY into world-readable unit file (subagent residue) — **FIXED by deletion**
- [medium] Permission profile fails open to `medium` on unknown/missing
- [medium] `GET /api/terminal/stream` creates PTY (not read-only)

### 7. Silent-failure / fail-open masks — flagged by 6 reviews
- [high] Default-on inline silent fallback (covered above)
- [high] Tier migration silently succeeds with missing milestones
- [high] Singularity Memory sync reports success without actually syncing (`syncMemoryToSm` called without await and wrong arg shape)
- [high] Routing fallback failure recorded with wrong schema → demotion signal lost
- [medium] `insertLlmTaskOutcome` catches+returns false without logging
- [medium] `finally` cleanup error replaces original send error

### 8. Doctrine / ADR-0000 drift — flagged by 3 reviews
- [high] Default-on inline runs ahead of R020 equivalence + R066 quarantine (named in code comment as risk)
- [high] Solver/executor collapsed in swarm dispatch with synthetic checkpoint injection
- [high] complete_task accepts empty verificationEvidence
- [medium] PDD eight-field gate not enforced by plan-milestone or plan-slice
- [medium] purpose_anchor mostly NULL (R071 plumbing exists but writers don't supply it)
- [high] Tier order put crash-loop self-heal behind infrastructure it should protect (M011/M038 in Tier 2 originally) — **FIXED via reorder**

### 9. Test theater — flagged by 4 reviews
- [high] v73 migration untested
- [high] R016 ack-without-deliver not reproduced by failing test
- [medium] Inline routing tests mirror boolean expression instead of exercising `runUnit`
- [medium] dispatchAndWait race test is sequential + mocks inbox under test
- [medium] Manifest drift can't catch src-vs-dist skew
- [medium] reconcileSliceTasks drift branch covered only by warnings, not assertions
- **Cross-cutting fix: source-vs-dist drift gate + integration tests over runtime path, not mirrored predicates**

### 10. Bayesian routing — flagged by 1 review (routing-learning)
- [high] `ucbBonus()` returns 1000-point fixed bonus for untried models → any zero-history model beats proven incumbent in `blendedRanking()`. SF can serially try unknown models on production work.
- [high] Fallback failure recorded with snake_case schema → validation rejects → silent demotion-signal loss

### 11. Memory / federation (Singularity Memory) — flagged by 1 review
- [high] Memory extraction drops user/operator/tool messages → high-value durable facts learned only if assistant restates them
- [high] Embedding backfill ignores model changes → stale vectors silently degrade ranking
- [high] Remote SM recall admits untenantable cross-project memories by default (only `SM_REQUIRE_TENANT_CLAIM=true` fails closed)
- [high] SM sync claims success without actually posting

### 12. Sleeptime / reflection — flagged by 1 review
- [high] Sleeptime jobs no atomic claim → race with concurrent drainers
- [high] Failed consolidation turns marked `done` (not `error` + retryable)
- [medium] `unknown` milestone-summary classification treated as terminal → dispatch on incomplete

### 13. Hook system — flagged by 1 review
- [high] `session-start` / `session-end` shell hooks documented but never fired (only pre-tool/post-tool wired)
- [high] Sync IO + spawnSync on every tool boundary, 5s × N hooks of blocking latency
- [medium] Blocking tool_call handlers short-circuit later audit/safety observers

### 14. Notification / journal / observability — flagged by 2 reviews
- [high] Swarm-dispatch journal events have no `flowId`/`seq` → audit projection can't reconstruct causal chain
- [medium] USER_VISIBLE info notifications dropped from persistence
- (observability review failed — codex couldn't inspect repo; re-run candidate)

### 15. Manifest / composition — flagged by 1 review
- [high] Manifest tool-policy fields ignored by `scopeActiveToolsForUnitType` (rewrite-docs gets all tools, not docs-only)
- [medium] Builders can silently omit manifest-declared knowledge context (workflow-preferences, reactive-execute)
- [medium] Manifest drift test doesn't catch src-vs-dist skew
- [medium] Template-variable failures are late runtime crashes, not inventory gate

### 16. CLI / build — flagged by 2 reviews
- [high] pkg/package.json pinned to 2.75.3 while root is 2.75.4 → versioned-json gate doesn't catch
- [medium] Headless parser drops unknown flags silently before command
- [medium] Documented `sf headless autonomous --yolo <file>` flag orphaned
- [medium] Changed test file fails Biome format
- [high] systemd timeout configured as failure → daemon restarts every cycle (the subagent residue, deleted)

### 17. Triage drain — flagged by 1 review
- [high] `applyTriagePlan` reports success while `fix` decisions remain unresolved → entries stay open while claim file exits clean
- [medium] purpose_anchor not populated by main `report_issue` writer
- [medium] Sleeptime drain blocks autonomous loop synchronously (60s × 10 jobs = 10min hidden latency)
- [medium] Duplicate suppression only keys on random id → recurring R072-style anomalies amplify queue

### 18. Architecture / pivots — flagged by 4 reviews
- M053 multi-swarm daemon: collapses blast radius + reintroduces federation surface — **RESCOPED to per-repo systemd + read-only projection**
- A2A plan Phase 5/6 still directs internal default-on — **OBSOLETED**
- Lane primitive lacks conflict contract (R046/R057) — R067 filed
- DB-via-Bus on incoherent bus (R016+R058 dep) — R016 must land first

## Actions taken during the sweep

| Action | Outcome |
|---|---|
| 2 A2A `SF_A2A_ENABLED` truthy gates | fixed to `=== "1"` |
| ASSESS suffix in `auto/loop.js:1222` | fixed (try ASSESSMENT then ASSESS) |
| SCHEMA_VERSION 72 → 73 | fixed |
| v73 migration: add sequence updates within tier | fixed |
| `packages/daemon/src/systemd.ts` subagent residue (secret-exposure bug) | deleted |
| M048/M038 swap (codex argued M048 first) | landed |
| Milestone reorder (Tier 1: M048, M038, M011) | landed via sequence updates |
| R072 Status-Completion-Drift Detector | filed |
| R073 Dispatcher honors priority tier | filed + implemented (v73 migration) |
| R074 Hard runtime gate on inline-eligible dispatch | filed |
| R075 Model-Diverse Adversarial Review (autonomous) | filed + reassigned to M048/S05 |
| M048/S05 slice for R075 | added |
| `.sf/reviews/ledger.jsonl` | 31 reviews captured |
| `.sf/self-feedback.jsonl` | 105 adversarial-finding entries |

## Open critical work (still on the list)

| Bug | File | Severity | Owner |
|---|---|---|---|
| state-db.js re-sorts tier-aware rows | state-db.js:661 | high | codex:codex-rescue investigating |
| Completion-path leaky writer (setTaskSummaryMd) | sf-db-tasks.js:431 | high | codex:codex-rescue investigating |
| MCP HTTP auth env-secret exfiltration | packages/coding-agent/.../mcp/auth.ts:22 | high | codex:codex-rescue investigating |
| MessageBus R016 ack-without-deliver | swarm-dispatch.js:318 | high | filed self-feedback |
| pkg/package.json version skew | pkg/package.json:3 | high | mechanical fix candidate |
| Biome format on run-unit-inline.test.mjs | test file | medium | mechanical fix candidate |

## Recommendation

SF's autonomous loop (currently on M048/S01) will deliver M048 next — the regression firewall that captures last-green + smoke fixture + crash-loop classifier. Once M048 lands, the 105 filed adversarial-findings become triageable signals for R066 quarantine. The flow:

1. SF lands M048 (firewall) → 24/7 autonomous safety net in place
2. SF lands M038 (Wiggums detectors including R072 drift) → runtime stuck patterns caught
3. SF lands M011 (defective-complete self-heal) → deadlock class repaired
4. SF lands M048/S05 (R075 model-diverse review service) → autonomous adversarial reviews continue without operator
5. The 105 filed findings get consumed by R075's triage pipeline + M038 detectors

This pass cost roughly $1-3 in codex tokens, caught ≥11 critical/high real bugs (some in code I had just written), and gave SF a concrete backlog of 105 findings to autonomously address. The ROI is order-of-magnitude positive.
