Auto Review Loop: Autonomous Research Improvement
🔒 Do not wrap this skill in
/loop,/schedule, orCronCreate. It already loops internally (review → fix → re-review) and the reviewer carries round-to-round memory in onethreadId(codex-reply). An external timer re-enters from the top each tick — freshthreadId, reviewer memory reset — firing the verdict on wall-clock time instead of on artifact change: zero new signal, full token cost. If you want to schedule something, schedule the external wait that precedes it (experiments done → then run this once). Seeshared-references/external-cadence.md.
Autonomously iterate: review → implement fixes → re-review, until an independent reviewer gives a policy-approved positive assessment or MAX_ROUNDS is reached.
Context: $ARGUMENTS
Constants
- MAX_ROUNDS = 4
- POSITIVE_THRESHOLD: score >= 6/10 AND verdict ∈ {"ready", "almost"} — both must hold. This matches the operative Phase-E STOP CONDITION exactly; the verdict vocabulary is {"ready", "almost", "not ready"} (a high score with a "not ready" verdict does NOT stop the loop). Earlier wording here used
orand a stale verdict set ("accept"/"sufficient"/"ready for submission") — that was an internal inconsistency; theANDform is authoritative. - REVIEW_DOC:
review-stage/AUTO_REVIEW.md(cumulative log) (fall back to./AUTO_REVIEW.mdfor legacy projects) - REVIEWER_MODEL =
gpt-6-astra— Default model for the Codex backend. Must be an OpenAI model (e.g.,gpt-6-astra,o3,gpt-4o). Manual backend uses a model the user chooses — it must be a recognized model from a different family (OpenAI, Anthropic, Google, DeepSeek, Moonshot/Kimi, Qwen). - REVIEWER_BACKEND — With no reviewer directive, start as
auto; Step -1 runs exactly one two-call native marker/challenge probe for the first review. A bound Copilot CLI root session usescopilot-native(built-in complementaryrubber-ducksubagent); an unbound/non-Copilot host keeps the existingcodexdefault. Explicit— reviewer: codex,oracle-pro,agy, ormanualbypasses the probe and selects that external backend. Explicit— reviewer: copilotretains the compatibilitycopilot --agentdrive mode and its later Codex/manual finalizer. The native path gets both actual model IDs from host session events; it never needsCOPILOT_CLIor caller-provided--executor-model. Seeshared-references/reviewer-routing.md. - OUTPUT_DIR =
review-stage/— All review-stage outputs go here. Create the directory if it doesn't exist. - HUMAN_CHECKPOINT = false — When
true, pause after each round's review (Phase B) and present the score + weaknesses to the user. Wait for user input before proceeding to Phase C. The user can: approve the suggested fixes, provide custom modification instructions, skip specific fixes, or stop the loop early. Whenfalse(default), the loop runs fully autonomously. - COMPACT = false — When
true, (1) readEXPERIMENT_LOG.mdandfindings.mdinstead of parsing full logs on session recovery, (2) append key findings tofindings.mdafter each round. - REVIEWER_DIFFICULTY = medium — Controls how adversarial the reviewer is. Three levels:
medium(default): Current behavior — MCP-based review, the executor controls what context the reviewer sees.hard: Adds Reviewer Memory (the reviewer tracks its own suspicions across rounds) + Debate Protocol (the executor can rebut, the reviewer rules).nightmare: Everything inhard+ Codex exec reviewer reads the repo directly viacodex exec(the executor cannot filter what the reviewer sees) + Adversarial Verification (the reviewer independently checks if code matches claims).
- RENDER_HTML = true — When
true(default), auto-renderreview-stage/AUTO_REVIEW.mdto HTML on loop termination via/render-html. Uses--no-review(the loop itself IS the cross-model review; the HTML is a structural conversion). Setfalseto skip, or pass— render html: false.
⚠️ Nightmare + Manual incompatibility: If
REVIEWER_BACKEND = manualandREVIEWER_DIFFICULTY = nightmare, STOP with: "difficulty: nightmare requires Codex CLI / codex exec and is not compatible with --reviewer: manual. Use difficulty: hard, or switch reviewer to codex."
💡 Override:
/auto-review-loop "topic" — compact: true, human checkpoint: true, difficulty: hard
Reviewer Calling Convention
When calling the reviewer, branch on REVIEWER_BACKEND:
If no --reviewer: directive was supplied:
Set REVIEWER_BACKEND to auto. At Step -1 of the first round, resolve
copilot_native_evidence.py using the canonical four-layer helper chain.
Generate a fresh binding <run_id>_r<round>_review_<8-random-hex> and invoke
marker, wait, then invoke challenge as two distinct root Bash calls.
Put the literal binding and concrete resolved helper path in both calls;
Copilot Bash calls do not share variables. If the challenge binds, set
REVIEWER_BACKEND to copilot-native and use that same challenge for the
first review. Do not issue a second activation challenge in Phase A. If it
exits 3 because no current Copilot root session is bound, use codex.
Explicit reviewer directives bypass this probe. If the helper is missing,
native acceptance is unavailable; use Codex only if that external backend
is positively available, otherwise emit REVIEW_UNAVAILABLE.
If REVIEWER_BACKEND = copilot-native:
Read the challenge nonce and host-reported executor model. Invoke the host's
native task tool with agent_type: rubber-duck; do not start a subprocess
and do not specify a reviewer model. The prompt contains the exact standalone
ARIS_REVIEW_NONCE=<nonce> line, artifact/diff paths, the output contract,
and (round 2+) review-stage/REVIEWER_MEMORY.md. It contains no executor
summary or fix narrative. After the task completes, invoke
copilot_native_evidence.py verify to create the evidence and raw-response
artifacts. The verifier must observe one successful linked rubber-duck
lifecycle and known, different host-reported model families.
Pass the evidence to both review_gate.py --native-evidence and
save_trace.sh --backend copilot-native --native-evidence. A qualifying
native positive may stop directly; no external finalizer is needed. A native
negative continues with a fresh marker/challenge/subagent next round. Every
verdict-bearing native call—including a hard-mode rebuttal ruling—gets one
unique <run_id, round, purpose> artifact set and exactly one challenge.
Missing, same/unknown-family, malformed, stale, or mismatched evidence is
never a verdict. If native complementary dispatch is unavailable, fall back
only to a positively available opposite-family backend: Anthropic/Google
executor → Codex; OpenAI executor → manual with a reported non-OpenAI model.
Otherwise emit REVIEW_UNAVAILABLE. Full protocol:
shared-references/reviewer-routing.md.
If REVIEWER_BACKEND = copilot:
Require --executor-model: if not provided → emit REVIEW_UNAVAILABLE.
Determine executor family from --executor-model (see reviewer-routing.md).
Router picks opposite-family profile:
- executor_family=openai → profile="aris-reviewer-claude" (anthropic)
- executor_family=anthropic → profile="aris-reviewer-openai" (openai)
- executor_family=google → profile="aris-reviewer-openai" (openai, default cross)
- executor_family=unknown →
REVIEW_UNAVAILABLE(fail closed). Verify the profile file exists at.github/agents/<profile>.agent.md. If missing →REVIEW_UNAVAILABLE. Read itsmodel:field intoREVIEWER_MODEL, derivereviewer_familyfrom that model string, and verify it differs fromexecutor_family. Pass the same value through subprocess--model; never trust a caller-supplied family label or profile-only pinning under an Auto session. Identity assurance:--executor-modelis caller-declared routing input, not runtime attestation. Recordexecutor_model_source: caller-declared, the derivedfamily_relation, andindependence_verified: unverified. A pair of different model strings must never be promoted to independently verified. Capability gate:copilot --helpmust advertise--model,--effort, and--allow-tool; otherwise emitREVIEW_UNAVAILABLE. Use thecopilot --agentsubprocess (documented Copilot CLI form) with the selected profile,--model "$REVIEWER_MODEL",--effort xhigh, and--allow-tool=readfor each review call. Multi-round: each round is a freshcopilot --agentcall with the same profile; reviewer memory is carried viareview-stage/REVIEWER_MEMORY.mdartifact. IfcopilotCLI is unavailable →REVIEW_UNAVAILABLEfor that drive round; do not silently substitute another transport. A later positive Copilot verdict still requires the separately documented Codex/manual finalizer. Seeshared-references/reviewer-routing.mdfor the full copilot contract.
If REVIEWER_BACKEND = codex:
Use mcp__codex__codex for new review threads.
Use mcp__codex__codex-reply for follow-up rounds (reuse threadId).
If REVIEWER_BACKEND = manual:
Use mcp__manual_review__review for new review threads with:
prompt: [exact same prompt that would go to Codex]
config: {"model_reasoning_effort": "xhigh", "executor_model": "", "require_reviewer_model": true}
Save the returned threadId.
Use mcp__manual_review__review_reply for follow-up rounds with:
threadId: [saved manual-review threadId]
prompt: [follow-up prompt]
config: {"model_reasoning_effort": "xhigh", "executor_model": "", "require_reviewer_model": true}
A verdict-bearing manual response MUST begin with
Reviewer-Model: <exact-model-id>. Derive reviewer_family from that model
identity. Missing, unknown, or same-family identity cannot acquit; for a
mandatory escalation, emit REVIEW_UNAVAILABLE rather than guessing.
Prompt fidelity: the manual review task must be exactly the same text that Codex would receive; the transport may add only the required Reviewer-Model: response-format instruction.
Review tracing applies to every backend. Native traces are populated from the
revalidated host-event artifact rather than caller model declarations.
State Persistence (Compact Recovery)
Long-running loops may hit the context window limit, triggering automatic compaction. To survive this, persist state to review-stage/REVIEW_STATE.json after each round:
{
"run_id": "run_20260713_a1b2c3d4",
"round": 2,
"threadId": null,
"reviewer_profile": "rubber-duck",
"reviewer_backend": "copilot-native",
"executor_model": "claude-sonnet-4.6",
"executor_model_source": "host-session-event",
"executor_family": "anthropic",
"requested_reviewer_model": null,
"reported_reviewer_model": "gpt-5.5",
"reviewer_model_source": "host-session-event",
"reviewer_family": "openai",
"family_relation": "different",
"identity_assurance": "host_event_verified",
"independence_verified": true,
"native_evidence_id": "cne_0123456789abcdef0123456789abcdef",
"native_evidence_path": "review-stage/COPILOT_NATIVE_run_20260713_a1b2c3d4_ROUND_2_REVIEW.evidence.json",
"requires_external_acquittal": false,
"status": "in_progress",
"difficulty": "medium",
"last_score": 5.0,
"last_verdict": "not ready",
"pending_experiments": ["screen_name_1"],
"timestamp": "2026-03-13T21:00:00"
}
run_id— Globally unique per invocation. Generated on fresh start asrun_<YYYYMMDD>_<8-char-hex>(e.g.,run_20260713_a1b2c3d4). Preserved across round writes. On resume, read from state file unchanged. This binds all round state, reviewer-memory appends, and acquittal receipts to one run so a stale completed state from a previous invocation cannot leak into the current run's acquittal check.
When REVIEWER_BACKEND = copilot-native, save the evidence ID/path and the
host-event executor/reviewer models, derived families, and sources. Each round
is a fresh rubber-duck subagent and therefore gets a fresh evidence artifact;
there is no persistent child handle. When REVIEWER_BACKEND = compatibility
copilot, retain reviewer_profile, requested model, caller-declared executor
model, independence_verified: "unverified", and the external-finalizer
obligation. For codex save its MCP threadId; for manual save threadId
and the reported reviewer identity. On resume, use reviewer_backend to select
the continuation mechanism and preserve requires_external_acquittal.
Write this file at the end of every Phase E (after documenting the round). Overwrite each time — only the latest round's state matters. The run_id field MUST persist unchanged across overwrites within the same run.
On completion (positive assessment or max rounds), set "status": "completed" so future invocations don't accidentally resume a finished loop.
Append-Only External-Finalizer Receipt
Whenever a Copilot path hands the verdict to an external backend—after a
positive compatibility-drive review or after a pre-verdict native dispatch
failure—maintain an append-only finalizer log at
review-stage/ACQUITTAL_LOG.jsonl. Each line records the Codex/manual reviewer
that completed that run. A successful native rubber-duck round never needs or
writes this receipt; its evidence sidecar is the acceptance record. The
historical filename is retained for compatibility:
{"run_id":"run_20260713_a1b2c3d4","round":3,"backend":"codex","effort":"xhigh","verdict":"ready","score":7.5,"executor_model":"claude-sonnet-4-5","executor_model_source":"caller-declared","executor_family":"anthropic","reviewer_model":"gpt-6-astra","reviewer_model_source":"requested","reviewer_family":"openai","family_relation":"different","identity_assurance":"caller_declared","independence_verified":"unverified","trace_id":"auto-review-loop/2026-07-13_run03","timestamp":"2026-07-13T14:22:00Z"}
Rules (non-negotiable):
| Rule | Detail |
|---|---|
| Append-only | Never delete, never truncate, never overwrite lines. Only >>. |
| Who writes | Only a codex or manual round at xhigh effort when round_requires_external_acquittal was true. A Copilot review/dispatch never writes a finalizer line itself. |
| When to write | At the end of Phase E, after the policy-approved finalizer returns score >= 6 AND verdict ∈ {"ready", "almost"}. A normal default-Codex run does not need this sidecar. |
run_id binding |
Every line carries the current run_id and round so the Copilot → finalizer transition is auditable. |
| Trace linkage | trace_id MUST reference the real trace artifact in .aris/traces/; source and family fields in the receipt must exactly match that trace. |
| Identity honesty | Re-derive family_relation from the model strings, but preserve their sources. With the current caller-declared executor identity, write identity_assurance: "caller_declared" and independence_verified: "unverified"; never promote different strings to independent attestation. |
| No overwrite | REVIEW_STATE.json is overwritten each round (only latest state). ACQUITTAL_LOG.jsonl is NEVER overwritten — it is the permanent, cumulative record. |
Why this exists: REVIEW_STATE.json is overwritten each round. The log
preserves evidence that a compatibility drive verdict or failed native attempt
did not terminate by itself. A successful copilot-native verdict instead
uses its host-event evidence sidecar.
Output Protocols
Follow these shared protocols for all output files:
- Output Versioning Protocol — write timestamped file first, then copy to fixed name
- Output Manifest Protocol — log every output to MANIFEST.md
- Output Language Protocol — respect the project's language setting
Workflow
Initialization
- Check for
review-stage/REVIEW_STATE.json(fall back to./REVIEW_STATE.jsonif not found — legacy path):- If neither path exists: fresh start (normal case, identical to behavior before this feature existed)
- Generate
run_id:run_<YYYYMMDD>_<8-char-hex>(e.g.,run_20260713_a1b2c3d4). Usedate +%Y%m%dand 8 random hex characters. This run_id persists across all round writes and binds acquittal receipts to this invocation.
- Generate
- If it exists AND
statusis"completed": fresh start (previous loop finished normally — but itsACQUITTAL_LOG.jsonlentries are retained as an audit trail with their ownrun_id, and are NOT valid for the current run's stop gate)- Generate a new
run_idfor this invocation.
- Generate a new
- If it exists AND
statusis"in_progress"ANDtimestampis older than 24 hours: fresh start (stale state from a killed/abandoned run — delete the file and start over)- Generate a new
run_idfor this invocation.
- Generate a new
- If it exists AND
statusis"in_progress"ANDtimestampis within 24 hours: resume- Read the state file to recover
run_id,round,threadId(or evidence/profile fields for Copilot backends),reviewer_backend,last_score,pending_experiments - Legacy backward compat: if
reviewer_backendis absent from the state file, default tocodex(pre-copilot-era states did not record this field). Ifrequires_external_acquittalis absent, default it tofalse; a legacy default-Codex run must not inherit the stricter Copilot-finalizer state. Ifrun_idis absent from the state file (pre-run_id era), generate a newrun_idand log: "No run_id in legacy state file; assigned run_<...> for this resume." - Read
review-stage/AUTO_REVIEW.mdto restore full context of prior rounds (fall back to./AUTO_REVIEW.md) - If
pending_experimentsis non-empty, check if they have completed (e.g., check screen sessions) - Resume from the next round (round = saved round + 1)
- Use
reviewer_backendto determine continuation:codex-replyfor codex; a fresh marker/challenge/rubber-duck/evidence cycle forcopilot-native; a freshcopilot --agentsubprocess with the saved profile/model for compatibilitycopilot;manual_review_replyfor manual - Log: "Recovered from context compaction. Resuming at Round N."
- Read the state file to recover
- If neither path exists: fresh start (normal case, identical to behavior before this feature existed)
- Read project narrative documents, memory files, and any prior review documents. When
COMPACT = trueand compact files exist: readfindings.md+EXPERIMENT_LOG.mdinstead of fullreview-stage/AUTO_REVIEW.mdand raw logs — saves context window. - Read recent experiment results (check output directories, logs)
- Identify current weaknesses and open TODOs from prior reviews
- Initialize round counter = 1 (unless recovered from state file)
- Create/update
review-stage/AUTO_REVIEW.mdwith header and timestamp - If this is a fresh run with no explicit reviewer directive, initialize
REVIEWER_BACKEND to
auto. Step -1 of Round 1 performs activation and uses that same challenge for the review. Explicit reviewer directives initialize their selected backend and bypass activation. Do not use environment heuristics.
Loop (repeat up to MAX_ROUNDS)
Step -1 — Resolve the automatic backend and prepare one native challenge:
- If REVIEWER_BACKEND is
auto, resolve the native helper and run one rootmarkercall followed by one rootchallengecall. Use binding<run_id>_r<round>_review_<8-random-hex>and outputreview-stage/COPILOT_NATIVE_<run_id>_ROUND_<round>_REVIEW.challenge.json. A bound challenge sets REVIEWER_BACKEND tocopilot-nativeand NATIVE_CHALLENGE to that path. Exit 3/unbound sets REVIEWER_BACKEND tocodex. Any other failure follows the fail-closed capability rules. - If REVIEWER_BACKEND is already
copilot-native(a later round or a resumed run), create one fresh marker/challenge pair with the same run-scoped naming pattern and set NATIVE_CHALLENGE. An unbound or invalid challenge cannot be treated as a verdict or silently relabeled. - Explicit external or compatibility backends do nothing in this step.
The challenge created here is the challenge consumed by Phase A. Do not run
another marker/challenge for the same review. Run-scoped filenames are
append-only audit identities; never pass --replace to reuse evidence from an
older invocation.
Step 0 — Snapshot current-round state: After Step -1 resolves auto, set round_backend = <current REVIEWER_BACKEND> and round_requires_external_acquittal = <current requires_external_acquittal, default false>. These variables label the backend and obligation that actually governed the CURRENT round. If compatibility-drive escalation occurs later in Phase B.5.1 (copilot → codex/manual), the snapshots retain their pre-escalation values while the forward-looking state is updated for the NEXT round. A native dispatch failure is different because no review occurred: replace both snapshots with the external fallback values before that reviewer call, as specified in Phase A. A successful native call never sets the finalizer obligation. Phase E uses only the resulting snapshots when documenting or writing a finalizer receipt.
Phase A: Review
Route by REVIEWER_BACKEND and REVIEWER_DIFFICULTY.
If REVIEWER_BACKEND = copilot-native, execute one fresh native cycle:
- Use NATIVE_CHALLENGE prepared by Step -1. It must be the run-scoped
..._ROUND_<round>_REVIEW.challenge.jsonartifact created in this round. Do not issue a second marker/challenge here. - Read the returned nonce. Call the host Task tool with
agent_type: rubber-duck, a fresh name, and a prompt whose first line is exactlyARIS_REVIEW_NONCE=<nonce>. Supply paths to claims, methods/code, raw results, diff/current inputs, and reviewer memory—not an executor summary. Require exactly oneScore: X/10andVerdict: ready | almost | not readyplus ranked weaknesses/minimum fixes/memory update. Do not pass a model override: Copilot's complementary strategy selects it. - After Task completes, run
python3 "<resolved-helper>" verify --challenge "$NATIVE_CHALLENGE" --output "review-stage/COPILOT_NATIVE_<run_id>_ROUND_<round>_REVIEW.evidence.json" --response-output "review-stage/COPILOT_NATIVE_<run_id>_ROUND_<round>_REVIEW.response.md"in a new root Bash call. Use only the extracted response artifact for Phase B. - Exit 10 (same/unknown family), incomplete lifecycle, invalid response, or
unavailable complementary model is not a review. Apply the opposite-family
fallback table in
reviewer-routing.md; if none is positively available, emitREVIEW_UNAVAILABLE. Never emulate rubber-duck using a slash prompt,copilot --agent rubber-duck, or generic subagent. Trace a pre-evidence dispatch failure as--backend copilot-native --status errorwithout evidence, then trace the actual fallback separately; this error trace has no authority at the stop gate. Before fallback, runcopilot_native_evidence.py validate-challenge --challenge "$NATIVE_CHALLENGE"and take EXECUTOR_MODEL only from that output. Then:- Anthropic/Google executor + usable Codex → set both REVIEWER_BACKEND and
round_backendtocodexbefore the external call. - OpenAI executor + manual reviewer reporting a known non-OpenAI model → set
both values to
manualbefore the external call. - Set
round_requires_external_acquittal=truefor either fallback, clear NATIVE_EVIDENCE, and pass the validated executor model plus the fallback's resolved reviewer model toreview_gate.py. This deliberately uses the stricter external-finalizer branch, which re-derives and enforces different families. If the external call does not return a usable review, emitREVIEW_UNAVAILABLE.
- Anthropic/Google executor + usable Codex → set both REVIEWER_BACKEND and
If REVIEWER_BACKEND = copilot, enforce opposite-family routing from the declared executor identity FIRST:
- Require
--executor-model <model>parameter. If missing →REVIEW_UNAVAILABLE. Stop. - Derive
executor_familyfromexecutor_model:- Model names containing
gpt,o1,o3,o4,chatgpt→openai - Model names containing
claude,sonnet,opus,haiku→anthropic - Model names containing
gemini→google - Anything else →
unknown
- Model names containing
- If
executor_familyisunknown→REVIEW_UNAVAILABLE(fail closed). Stop. - Treat this as route selection, not attestation: persist
executor_model_source: caller-declared; a derivedfamily_relation: differentremainsindependence_verified: unverifiedunless a future stable runtime signal independently proves the parent executor model. - Router picks opposite-family profile:
openai→"aris-reviewer-claude"(anthropic, forced cross-family)anthropic→"aris-reviewer-openai"(openai, forced cross-family)google→"aris-reviewer-openai"(openai default)
- Verify the profile file exists at
.github/agents/<profile>.agent.md. If missing →REVIEW_UNAVAILABLE. Stop. - Read the profile's first frontmatter
model:value, derive its family, and verify it is known and differs fromexecutor_family. If not, fail closed. - Verify
copilot --helpexposes--model,--effort, and--allow-tool. Older/unpinned CLIs areREVIEW_UNAVAILABLE. - Adapt the Codex MCP calls below to use the
copilot --agentsubprocess (documented Copilot CLI form):- Replace
mcp__codex__codexwithcopilot --agent "<profile>" --model "<parsed-model>" --effort xhigh --allow-tool=read --prompt "..." - Each round is a fresh
copilot --agentcall with the same profile +review-stage/REVIEWER_MEMORY.mdartifact carrying round-to-round state. - The prompt text and Review Tracing are identical to the Codex path.
- If
copilotCLI is unavailable →REVIEW_UNAVAILABLE(no MCP fallback). - If
REVIEWER_DIFFICULTY = nightmare, skip Copilot (nightmare requires Codex exec): emitREVIEW_UNAVAILABLE. Seeshared-references/reviewer-routing.md.
- Replace
If REVIEWER_BACKEND ∈ {codex, manual}: use the backend-specific MCP call per the Reviewer Calling Convention above. The prompt text is the same regardless of backend.
Medium (default) — MCP Review
Send comprehensive context to the independent reviewer using the selected backend.
For codex backend:
mcp__codex__codex:
model: gpt-6-astra
config: {"model_reasoning_effort": "xhigh"}
prompt: |
[Round N/MAX_ROUNDS of autonomous review loop]
Review the work directly from its artifacts — executor notes are not
evidence, so read the files yourself rather than trusting my framing:
- Claims / paper draft: <path>
- Methods / code under review: <path(s)>
- Raw results (verbatim files, not a summary): <path(s)>
- Changed since last round: <changed-file paths> — read the diff, not my description
Please act as a senior ML reviewer (NeurIPS/ICML level). Start from the
assumption that the work is broken somewhere — your job is to find where.
Be adversarial. Trust nothing the author tells you — verify everything
yourself.
1. Score this work 1-10 for a top venue
2. List remaining critical weaknesses (ranked by severity)
3. For each weakness, specify the MINIMUM fix (experiment, analysis, or reframing)
4. State clearly: is this READY for submission? Yes/No/Almost
Be brutally honest. If, after genuinely trying to break it, the work holds
up and is ready, say so clearly.
=== SCOPE LIMITS (these bound what you PROPOSE, never what you look for) ===
Report anything that is actually wrong here — including a rare-looking case, if
this repo actually produces it. Then keep the fix in scope:
1. This is a RESEARCH-WORKFLOW tool, not a security paper. Verification is
welcome; over-defense is not. Assume a cooperating operator on their own
machine — a malicious local user is NOT in the threat model.
2. Do NOT propose SHA / hash / content-fingerprint / digest-binding schemes.
Reporting a real defect in hashing code that already exists is fine.
3. NO speculative machinery: do not add feature flags, migration frameworks,
compat layers, wrappers, pins, or similar mechanisms unless evidence shows
a current repo defect they fix or an explicit existing invariant they must
preserve. "Load-bearing", "compatibility", and "not scaffolding" are labels,
not evidence. Point to the failing path/artifact or invariant, and check the
proposal's factual premises, such as whether a named package version exists.
4. NO corner-case obsession: exotic encodings, symlink races, RTL text and
millisecond races are out of scope unless you can show the case arises here.
5. Where a rubric or checklist is genuinely needed, do not over-mechanize
judgement. A clear sentence a human reads beats a scored table nobody
maintains.
Exception: code that runs remote commands, starts a network service, or installs
an MCP server runs on the user's machine with their credentials — trust-boundary
findings there are in scope and the default is strict.
Say plainly when something is correct. Do not manufacture findings.
For manual backend: use mcp__manual_review__review with the prompt text above and config: {"model_reasoning_effort": "xhigh", "executor_model": "<actual executor model>", "require_reviewer_model": true}. Save the returned threadId.
If this is round 2+, use mcp__codex__codex-reply (codex) or mcp__manual_review__review_reply (manual) with the saved threadId.
Hard — MCP Review + Reviewer Memory
Same as medium, but prepend Reviewer Memory to the prompt. Use the selected backend.
For codex backend:
mcp__codex__codex:
model: gpt-6-astra
config: {"model_reasoning_effort": "xhigh"}
prompt: |
[Round N/MAX_ROUNDS of autonomous review loop]
## Your Reviewer Memory (persistent across rounds)
[Paste full contents of review-stage/REVIEWER_MEMORY.md here]
IMPORTANT: You have memory from prior rounds. Check whether your
previous suspicions were genuinely addressed or merely sidestepped.
The author (the executor model) controls what context you see — be skeptical
of convenient omissions.
Review directly from the artifacts (paths below) — read the files yourself:
- Claims / methods / code: <path(s)>
- Raw results: <path(s)>
- Changed since last round: <changed-file paths> (read the raw diff)
Please act as a senior ML reviewer (NeurIPS/ICML level).
1. Score this work 1-10 for a top venue
2. List remaining critical weaknesses (ranked by severity)
3. For each weakness, specify the MINIMUM fix
4. State clearly: is this READY for submission? Yes/No/Almost
5. **Memory update**: List any new suspicions, unresolved concerns,
or patterns you want to track in future rounds.
Be brutally honest. Actively look for things the author might be hiding.
=== SCOPE LIMITS (these bound what you PROPOSE, never what you look for) ===
Report anything that is actually wrong here — including a rare-looking case, if
this repo actually produces it. Then keep the fix in scope:
1. This is a RESEARCH-WORKFLOW tool, not a security paper. Verification is
welcome; over-defense is not. Assume a cooperating operator on their own
machine — a malicious local user is NOT in the threat model.
2. Do NOT propose SHA / hash / content-fingerprint / digest-binding schemes.
Reporting a real defect in hashing code that already exists is fine.
3. NO speculative machinery: do not add feature flags, migration frameworks,
compat layers, wrappers, pins, or similar mechanisms unless evidence shows
a current repo defect they fix or an explicit existing invariant they must
preserve. "Load-bearing", "compatibility", and "not scaffolding" are labels,
not evidence. Point to the failing path/artifact or invariant, and check the
proposal's factual premises, such as whether a named package version exists.
4. NO corner-case obsession: exotic encodings, symlink races, RTL text and
millisecond races are out of scope unless you can show the case arises here.
5. Where a rubric or checklist is genuinely needed, do not over-mechanize
judgement. A clear sentence a human reads beats a scored table nobody
maintains.
Exception: code that runs remote commands, starts a network service, or installs
an MCP server runs on the user's machine with their credentials — trust-boundary
findings there are in scope and the default is strict.
Say plainly when something is correct. Do not manufacture findings.
Nightmare — Codex Exec (GPT reads repo directly)
Do NOT use MCP. Instead, let GPT access the repo autonomously via codex exec:
codex exec "$(cat <<'PROMPT'
You are an adversarial senior ML reviewer (NeurIPS/ICML level).
This is Round N/MAX_ROUNDS of an autonomous review loop.
## Your Reviewer Memory (persistent across rounds)
[Paste full contents of review-stage/REVIEWER_MEMORY.md]
## Instructions
You have FULL READ ACCESS to this repository. The author (the executor model) does NOT
control what you see — explore freely. Your job is to find problems the
author might hide or downplay.
DO THE FOLLOWING:
1. Read the experiment code, results files (JSON/CSV), and logs YOURSELF
2. Verify that reported numbers match what's actually in the output files
3. Check if evaluation metrics are computed correctly (ground truth, not model output)
4. Look for cherry-picked results, missing ablations, or suspicious hyperparameter choices
5. Read NARRATIVE_REPORT.md or review-stage/AUTO_REVIEW.md for the author's claims — then verify each against code
OUTPUT FORMAT:
- Score: X/10
- Verdict: ready / almost / not ready
- Verified claims: [which claims you independently confirmed]
- Unverified/false claims: [which claims don't match the code or results]
- Weaknesses (ranked): [with MINIMUM fix for each]
- Memory update: [new suspicions and patterns to track next round]
Be adversarial. Trust nothing the author tells you — verify everything yourself.
=== SCOPE LIMITS (these bound what you PROPOSE, never what you look for) ===
Report anything that is actually wrong here — including a rare-looking case, if
this repo actually produces it. Then keep the fix in scope:
1. This is a RESEARCH-WORKFLOW tool, not a security paper. Verification is
welcome; over-defense is not. Assume a cooperating operator on their own
machine — a malicious local user is NOT in the threat model.
2. Do NOT propose SHA / hash / content-fingerprint / digest-binding schemes.
Reporting a real defect in hashing code that already exists is fine.
3. NO speculative machinery: do not add feature flags, migration frameworks,
compat layers, wrappers, pins, or similar mechanisms unless evidence shows
a current repo defect they fix or an explicit existing invariant they must
preserve. "Load-bearing", "compatibility", and "not scaffolding" are labels,
not evidence. Point to the failing path/artifact or invariant, and check the
proposal's factual premises, such as whether a named package version exists.
4. NO corner-case obsession: exotic encodings, symlink races, RTL text and
millisecond races are out of scope unless you can show the case arises here.
5. Where a rubric or checklist is genuinely needed, do not over-mechanize
judgement. A clear sentence a human reads beats a scored table nobody
maintains.
Exception: code that runs remote commands, starts a network service, or installs
an MCP server runs on the user's machine with their credentials — trust-boundary
findings there are in scope and the default is strict.
Say plainly when something is correct. Do not manufacture findings.
PROMPT
)" --skip-git-repo-check 2>&1
Key difference: In nightmare mode, GPT independently reads code, result files, and logs. Claude cannot filter or curate what GPT sees. This is the closest analog to a real hostile reviewer who reads your actual paper + supplementary materials.
Phase B: Parse Assessment
CRITICAL: Save the FULL raw response from the reviewer verbatim (store in a variable for Phase E). For copilot-native, this must be the response artifact extracted by the evidence helper, never text copied by the executor. Do NOT discard or summarize — the raw text is the primary record.
Then extract structured fields:
- Score (numeric 1-10)
- Verdict ("ready" / "almost" / "not ready")
- Action items (ranked list of fixes)
Phase B.5: Reviewer Memory Update
After parsing the assessment, append to the canonical memory artifact at review-stage/REVIEWER_MEMORY.md. Both Copilot backends depend on this file for round-to-round continuity (each native subagent or compatibility subprocess is fresh), so the update runs regardless of REVIEWER_DIFFICULTY. No project-root fallback is permitted; create review-stage/ before the first append:
# Reviewer Memory
## Round 1 — Score: X/10
### Raw Reviewer Response (verbatim)
[Paste the COMPLETE raw reviewer response here — never summarized or curated by the executor.]
### Memory Update
[Reviewer's own memory update section, if provided — verbatim.]
- **Suspicion**: [what the reviewer flagged]
- **Unresolved**: [concerns not yet addressed]
- **Patterns**: [recurring issues the reviewer noticed]
---
## Round 2 — Score: X/10
### Raw Reviewer Response (verbatim)
[Paste the COMPLETE raw reviewer response here.]
### Memory Update
- **Previous suspicions addressed?**: [yes/no for each, with reviewer's judgment]
- **New suspicions**: [...]
- **Unresolved**: [carried forward + new]
---
Rules:
- Append-only — never delete, never truncate. The file is a reviewer-owned audit trail. The executor must never summarize, curate, or edit prior rounds' content. Append the reviewer's full raw response for this round verbatim, then append a memory update section if the reviewer provided one.
- Each round's append must be the reviewer's own words — if the reviewer's response includes a "Memory update" section, copy it verbatim as a
## Round N — Memory Updatesubsection after the raw response. - This file is passed back to the reviewer in the next round's Phase A — it is the reviewer's persistent memory.
- Record the file's SHA-256 hash before each reviewer call and pass it to
save_trace.shvia--memory-hash. Hash the memory as supplied to the call (pre-call artifact), not the post-append version, so the trace proves which memory was in play for that invocation. - If the score REGRESSES round-to-round, don't just write a new memory line:
diff the two rounds' raw
.response.mdfiles in.aris/traces/first and find the exact criterion that flipped (seeshared-references/review-tracing.md§ Debugging With Traces). The memory file is a summary; the trace is evidence.
Phase B.5.1: Stop-Evaluation Gate
STOP CONDITION — branch by round_backend (the backend that actually ran this round), never by the forward-looking REVIEWER_BACKEND. Use the executable transition table in review_gate.py; resolve it through the canonical helper chain in shared-references/integration-contract.md §2. Its JSON decision and next_backend fields are authoritative. If the helper cannot be resolved or executed, emit REVIEW_UNAVAILABLE; do not improvise a transition.
Invoke the gate once per completed round. Pass model strings only—the helper derives families internally and does not accept caller-suppl
…(truncated)