The Skeptic Protocol

Adversarial review that stays independent by design

Why adversarial review matters

  • A reviewer who has seen the implementer's reasoning is anchored to that framing
  • Self-review catches typos. It does not catch flawed assumptions.
  • The value of review is independence - seeing the output without the justification
  • The Skeptic sees only the output and the adversarial brief, never the Worker's reasoning process
  • This is not optional polish. It is the protocol's primary quality gate.
A resumed Skeptic has heard its own prior criticism - it gets polite and misses things. Fresh context is what gives the review teeth.

The core loop

Primary agent spawns Worker (with adversarial brief + task)
    |
Worker implements, returns output
    |
Primary agent spawns fresh Skeptic (with brief + output)
    |
Skeptic classifies findings: Critical / Major / Minor
    |
No Critical/Major? ──> Sign-off granted ──> Done
    |
Critical/Major found? ──> Route to new Worker ──> Loop back
  1. The primary agent orchestrates - it never implements Elevated work itself
  2. Each Worker is a fresh spawn with accumulated context from prior rounds
  3. Each Skeptic is a fresh spawn - never continued, never resumed
  4. The loop repeats until the Skeptic grants sign-off or the re-route limit is hit

The adversarial brief

The brief defines the threat model the Skeptic must adopt. It is domain-specific - not generic.

"An attacker controls one compromised account and one compromised device. What can they access, modify, or forge? Look for: session fixation, token replay, privilege escalation paths, and any state the server trusts without re-verifying."

  • The primary agent writes it (or extends a template) and passes it to both Worker and Skeptic verbatim
  • The agent must not soften, summarize, or editorialize the brief
  • Templates exist for: auth, API endpoints, crypto, DB migrations, data pipelines, smart contracts, architecture docs, general code review
Generic briefs produce generic findings. The brief is where you aim the Skeptic at what actually matters for this change.

Findings classification

Critical
Blocks sign-off. Must be resolved. Security vulnerabilities, correctness failures, data loss paths.
Major
Blocks sign-off unless the Worker provides a compelling documented reason to defer. Missing error handling, silent failure edge cases, DRY violations and missed abstractions (duplication, copy-paste programming, reinventing existing helpers).
Minor
Never blocks sign-off. Applied automatically by a background agent after sign-off. Style, logging gaps, low-impact optimizations.
Every finding must be classified. Unclassified findings default to Major. The Skeptic cannot wave something through without saying what it is.

Escalation and round limits

  • Max 3 fix passes (hard cap): within any Skeptic or QA loop (Phase 6/6b and any ad-hoc loop), the conductor applies a maximum of 3 fix passes before escalating to the human
  • 2 re-route limit (per finding): same finding contested across 2+ rounds without resolution - escalate with both positions
  • Simple changes: capped at 1 round - Critical/Major findings escalate directly
  • Standard Elevated changes: the 2-re-route rule applies
  • The primary agent tracks each finding by its text across all rounds

Loop-context override (inside /ds-implement-ticket Phase 6): the 2-re-route rule is replaced by a stricter contract - 1 re-raise of a Critical finding after a claimed fix triggers convergence failure escalation immediately. Outside a named loop, the 2-re-route rule is unchanged.

The 3-pass cap and the per-finding 2-re-route rule are separate ceilings. Either can trigger escalation first. Inside a persistence loop, convergence failure escalates even faster.

The resolved issues preflight + findings_log

On round 2+, the primary agent prepends a preflight list to the brief so the fresh Skeptic doesn't re-raise already-fixed issues:

The following issues were identified and resolved in prior rounds.
Do not re-raise them unless the resolution is genuinely insufficient:

[C1: Missing auth check on /admin endpoint → Added middleware guard]
[M1: No error handling on payment callback → Added try/catch with rollback]

Inside the persistence loop: the preflight list is backed by findings_log - a structured in-context accumulator tracking every finding across all iterations (id, severity, first_raised, status, claimed_fix, re_raised). When the Skeptic re-raises a previously-addressed finding, it uses [PREV: <id>] so the conductor can mechanically detect it and update re_raised: true.

Auto-close rule: when the Skeptic grants sign-off (zero new findings), ALL findings_log entries with status: open or status: addressed are automatically closed. The absence of re-raise is an implicit confirmation that all fixes were accepted.

Fresh context for independence. Preflight list for efficiency. findings_log for accountability across iterations.

Four new Skeptic obligations (1/2)

Module manifest check
On any non-trivial file touched by the Worker (exports a public symbol, ~50+ LOC, or side-effecting): verify a module manifest header exists and reflects the current file. The result is output-required via a fixed Manifest check: sign-off line.

Tiered: missing = Minor (non-blocking, hygiene); stale = Major (blocks sign-off); stale-on-correctness/security path = Critical.
Regression test verification
Before granting sign-off on any round where a Critical or Major finding was fixed: verify a regression test was added - a test that would have failed without the fix.

Missing test without a documented exception = Major finding.
These checks run alongside existing findings classification - not instead of it. Comprehension, regression, CI-wiring, and observability gates layered on top of Critical/Major/Minor.

Four new Skeptic obligations (2/2)

Telemetry emit check
At every instrumented boundary (engineer/skeptic/qa spawn or Trivial-path direct edit): verify .agentic/events.jsonl received the matching spawn_start/spawn_complete or conductor_direct events.

Missing emit = Minor (non-blocking; keeps /ds-cost dashboards accurate).
New-test-CI-wiring check
For each new test file in the diff: verify a matching reference exists in a CI workflow (an exact file reference, a covering glob, or an auto-discovering runner). The result is output-required via a fixed Test-CI-wiring check: sign-off line.

No matching CI invocation = Major finding - a test that never runs provides no regression protection.
All four obligations run alongside the standard Skeptic pass. Manifest enforcement catches comprehension drift; regression tests close the fix loop; CI-wiring checks close the "silent dead test" gap; telemetry keeps cost and calibration dashboards accurate.

Cognitive surrender check

Cognitive offloading (good)
Delegating mechanics to the agent - boilerplate, search, transformation. Judgment stays with the human and the Skeptic.
Cognitive surrender (bad)
Treating the LLM as System 3. A Skeptic that agrees with the Worker on every point with zero findings across two iterations is a rubber-stamp signal.
Cure: an audit-note Minor attesting the Skeptic re-read the diff end-to-end with independent attention. Documents what was checked, not what was wrong. Exempt from /ds-implement-ticket Phase 6 re-raise and convergence-failure detection - bookkeeping, not contested findings.

Calibration layer (1/2)

The audit-note Minor is the per-spawn defense against rubber-stamping. The calibration layer is the long-horizon backstop - it detects drift in aggregate over time without enlarging the per-spawn review surface.

  • Findings counters in events.jsonl - every Skeptic spawn_complete carries findings_count, diff_lines, signed_off, and iteration inside data. Conductor builds the merged JSON inline; subagents do not write to .agentic/.
  • 5% sampled meta-Skeptic - deterministic bucket from hash(task_id+iteration) % 100 < 5. Background fire-and-forget; conductor declares the unit complete without waiting. Meta-Skeptic returns text only; conductor parses and emits meta_review_complete.
Threat model: drift detection in a non-adversarial conductor relationship. Not a cheating-prevention mechanism - a compromised conductor can mis-emit. The target is operator self-deception over time, not adversarial spoofing.

Calibration layer (2/2)

  • Surfacing - Critical/Major divergence on a sampled spawn surfaces as one inline META-DIVERGENCE: line. Original sign-off remains binding; the notice is advisory. Surfacing fires both in-session (Phase 6 turn boundaries) and at session start (catches async returns from prior sessions). The sweep paginates via .meta-divergence-last-sweep timestamp tracker.
  • Inspection CLI - agentic-calibrate density (findings per 100 diff-lines, excludes zero-diff rows) and agentic-calibrate divergence (meta-Skeptic rubber-stamp rate). Warming-up line shown until 10 qualifying spawns observed.
Per-spawn: audit-note Minor attests the Skeptic re-read the diff end-to-end. Long-horizon: calibration layer catches aggregate drift across sessions. Two layers, two timescales.

Fresh. Independent. Classified.

Every finding named. Every round tracked. Every escalation clean.

github.com/Space-Dinosaurs/DinoStack