| name | diagnose-bug |
|---|---|
| description | Hypothesis-driven bug diagnosis workflow for unclear or intermittent failures. Use when the user asks to debug, diagnose, reproduce, instrument, trace, or investigate a bug whose root cause is unknown and evidence should be gathered before fixing. Do not use for straightforward errors with obvious fixes. |
Use an evidence-first workflow. Do not jump to fixes.
Capture the expected behavior, actual behavior, reproduction steps, and error messages.
Read the relevant source code before changing anything. Understand the call chain and data flow.
Produce numbered, testable hypotheses:
Based on my analysis, here are my hypotheses:
1. [H1] What might be wrong and why
2. [H2] What might be wrong and why
3. [H3] What might be wrong and why
Include obvious and non-obvious causes such as race conditions, stale state, timing issues, type coercion, and off-by-one errors.
Add the smallest amount of temporary instrumentation needed to confirm or rule out the hypotheses.
Write all debug output to an absolute log path:
- Preferred path:
{project_root}/.codex/diagnose-bug/debug.log - Fallback path for non-writable or remote environments:
/tmp/codex-diagnose-bug/debug.log
Infer project_root from known file paths in the task. Hardcode it in the instrumentation. Do not detect it dynamically with process.cwd(), __dirname, path.resolve(), or similar runtime helpers.
Before each reproduction:
- Create
.codex/diagnose-bug/if needed. - Clear
debug.log.
Server-side instrumentation:
- Append directly to the log file with file APIs such as
fs.appendFileSync.
Browser-side instrumentation:
- Create
{project_root}/.codex/diagnose-bug/debug-server.js. - Start it in a long-lived
exec_commandsession so it keeps running. - Record the returned
session_id. - Send browser logs to
http://localhost:9999/debug-log. - Stop the server during cleanup with
write_stdinand Ctrl-C.
Use this Bun template when Bun is available:
const LOG_FILE = "{project_root}/.codex/diagnose-bug/debug.log";
const CORS = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "POST, OPTIONS",
"Access-Control-Allow-Headers": "Content-Type",
};
Bun.serve({
port: 9999,
async fetch(req) {
if (req.method === "OPTIONS") {
return new Response(null, { headers: CORS });
}
if (req.method === "POST" && new URL(req.url).pathname === "/debug-log") {
const { message } = await req.json();
const existing = await Bun.file(LOG_FILE).text().catch(() => "");
await Bun.write(Bun.file(LOG_FILE), `${existing}${message}\n`);
return new Response("ok", { headers: CORS });
}
return new Response("not found", { status: 404 });
},
});If Bun is unavailable, use another installed runtime to expose the same POST /debug-log endpoint.
If the frontend has a Content Security Policy, temporarily allow localhost:9999 and remove that allowance during cleanup.
Wrap all temporary instrumentation in removable debug markers:
// #region DEBUG
...debug code...
// #endregion DEBUG
Language-specific variants are fine as long as the marker text stays #region DEBUG / #endregion DEBUG.
After instrumenting, ask the user to reproduce the bug and stop.
Check the log size first. If it is large, use targeted reads such as tail or rg "[DEBUG H" instead of reading the whole file.
Map each log line back to the hypotheses and classify them as confirmed or ruled out.
Present the diagnosis in this shape:
## Diagnosis
Root cause: explanation backed by evidence
Evidence:
- [H1] Ruled out: why
- [H2] Confirmed: what the log proved
If the evidence is inconclusive, create new hypotheses, re-instrument, clear the log, and repeat.
Implement the fix, but keep the debug instrumentation in place.
Clear debug.log, ask the user to verify the fix, and stop.
If the fix is confirmed:
- Remove all
#region DEBUGblocks. - Delete
.codex/diagnose-bug/debug.log. - Delete
.codex/diagnose-bug/debug-server.jsif it was created. - Stop any long-lived debug server session.
If the fix is not confirmed:
- Read the new logs.
- Ask what the user observed.
- Return to hypothesis generation.
- Never skip the diagnosis and instrumentation phases.
- Never remove instrumentation before the user confirms the fix.
- Never use
console.log,print, or stdout/stderr for debug output. - Always include hypothesis IDs such as
[DEBUG H1]in log messages. - Always clear the log before each reproduction.
- Always wait for the user after asking them to reproduce or verify.