Debug Mode
Use this skill only after the user explicitly invokes debug-mode,
$debug-mode, debug mode, or instrumented debugging.
If the user did not explicitly opt in, debug normally. Mention this skill only when temporary runtime instrumentation would materially help.
Core Loop
Run a hypothesis-driven debugging loop:
- Read the relevant code, repro details, and existing logs.
- List 2-5 ranked hypotheses with IDs such as
H1,H2, andH3. Each hypothesis must predict what a runtime probe will show. - Start or reuse the loopback collector (Collector Contract).
- Add 3-8 targeted probes that distinguish the hypotheses. Use structured
events sent to
DEBUG_URL + "/log", never stdout/stderr. Follow Event Shape, Region Markers, and Helpers below. - Stop at the manual checkpoint. Send a Checkpoint Template. Do not analyze,
fix, or remove probes until the user replies with
A,B, orC. - After
A, inspect the printedLOG_FILE, classify each hypothesis asCONFIRMED,REJECTED, orINCONCLUSIVE, and make the smallest fix only when the logs explain the root cause. Follow Evidence Summary below. - Keep probes active for one post-fix run tagged with
runId: "post-fix". - After the user replies
Bto the post-fix checkpoint, remove all instrumentation and run relevant checks. Follow Cleanup Checklist below.
Hard Rules
- Never skip the manual reproduction checkpoint after adding probes.
- Never fix from guesswork while this skill is active.
- Never remove probes before the user confirms the post-fix check.
- Never commit debug logs or temporary instrumentation.
- Never log secrets, tokens, cookies, authorization headers, API keys, raw request bodies, raw responses that may contain private data, or unnecessary personal data.
Collector Contract
The bundled collector is intentionally small:
GET /healthchecks whether an existing collector is reusable.POST /logaccepts one JSON object and appends one NDJSON line asynchronously. It returns200after validation; the line is written in the background.- Different sessions write to separate files with independent queues, so writes can proceed in parallel across sessions.
- Logs live under the OS temp directory by default, outside the workspace.
--ensureprintsDEBUG_URL,SESSION_ID,LOG_DIR,LOG_FILE, andHEALTH_URL.- The collector creates
LOG_FILEon the first event. Do nottouch, pre-create, truncate, or clear it after a repro. - The collector is loopback-only. Do not bind it to
0.0.0.0or any public interface.
Start or reuse it with:
node <skill-dir>/scripts/log-server.mjs --ensure --session <session_id> --host 127.0.0.1 --port 0
In managed sandboxes that block local port listeners, request the agent's normal approval on the first attempt. Scope the reason to starting or reusing this loopback-only debug collector.
Checkpoint Templates
After adding probes, stop and send this shape with real session details:
I added debug-mode probes and the collector is writing:
- Session: <session_id>
- Log file: <LOG_FILE>
- Debug endpoint: <DEBUG_URL>/log
Please reproduce the bug manually, then reply:
A - Reproduced
B - Fixed
C - Other; describe what happened
For post-fix verification, change only the opening sentence:
I kept debug-mode probes active for post-fix verification and the collector is writing:
- Session: <session_id>
- Log file: <LOG_FILE>
- Debug endpoint: <DEBUG_URL>/log
Please verify the original bug manually, then reply:
A - Reproduced
B - Fixed
C - Other; describe what happened
Interpret checkpoint replies as a small state machine:
Abefore a fix: read the NDJSON log, classify hypothesis evidence, then fix only a confirmed cause or add narrower probes.Aafter a fix: the bug still reproduced. Read the post-fix log and continue with narrower hypotheses or probes.Bbefore a fix: not a terminal state. Treat it as evidence that the bug did not reproduce under instrumentation and ask for clarification or a narrower repro.Bafter a fix: remove probes and run final checks.Cat any time: treat the user's text as evidence. Adjust the repro, hypotheses, or probes.
Event Shape
Use structured, low-volume events. A typical event looks like:
{
"session": "<session_id>",
"runId": "pre-fix",
"probe": "settings.beforePersist",
"hypothesis": "H1",
"file": "src/settings/save.ts",
"fn": "saveSettings",
"vars": {
"enabled": true,
"userId": "redacted"
}
}
Use runId: "pre-fix" before the fix and runId: "post-fix" for verification.
For high-frequency paths, log only on state changes or sample aggressively.
Region Markers
Wrap all temporary instrumentation so cleanup can be mechanical:
// #region DEBUG_MODE_PROBE <session_id> settings-before-persist
debugModeLog({
probe: "settings.beforePersist",
hypothesis: "H1",
file: "src/settings/save.ts",
fn: "saveSettings",
vars: { enabled, userId: "redacted" },
});
// #endregion DEBUG_MODE_PROBE <session_id>
Common comment forms:
// #region DEBUG_MODE_PROBE <session_id> ... JavaScript, TypeScript, Java, C#, Go, Rust, C, C++
# #region DEBUG_MODE_PROBE <session_id> ... Python, Ruby, Shell, YAML
<!-- #region DEBUG_MODE_PROBE <session_id> --> HTML, Vue, Svelte
/* #region DEBUG_MODE_PROBE <session_id> */ CSS and C-style block contexts
-- #region DEBUG_MODE_PROBE <session_id> ... SQL, Lua
Helpers
For browser or frontend JavaScript, use assets/browser-log-helper.js as the
canonical helper template. Copy it into the instrumented module or script,
replace <session_id> and <DEBUG_URL>, and keep the function name
debugModeLog.
For Node.js or server-side JavaScript, use assets/node-log-helper.js as the
canonical helper template. Copy it into the instrumented module or script,
replace <session_id> and <DEBUG_URL>, and keep the function name
debugModeLog.
For Python without third-party dependencies:
# #region DEBUG_MODE_PROBE <session_id> debug-log-helper
import json
import urllib.request
DEBUG_MODE_URL = "<DEBUG_URL>/log"
def debug_mode_log(event):
try:
payload = {"session": "<session_id>", **event}
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
DEBUG_MODE_URL,
data=data,
headers={"content-type": "application/json"},
method="POST",
)
urllib.request.urlopen(req, timeout=0.5).close()
except Exception:
pass
# #endregion DEBUG_MODE_PROBE <session_id>
Evidence Summary
After an A reply, summarize evidence before editing code:
H1 settings state is lost before API call
Status: CONFIRMED
Evidence: settings.beforePersist logged enabled=false while the UI event logged enabled=true.
H2 API rejects the value
Status: REJECTED
Evidence: no API call happened in this repro.
Next action: fix the local state handoff between onToggle and saveSettings.
If every hypothesis is REJECTED or INCONCLUSIVE, generate new hypotheses
from a different subsystem and add narrower probes. Do not patch from vibes.
Troubleshooting
- Empty log: confirm the app executed the instrumented path, the session id
matches, and the endpoint includes
/log. - Browser blocked request: check mixed content, CSP
connect-src, extension isolation, or content-script context. - CORS/preflight issue: the collector handles
OPTIONS; if it still fails, trynavigator.sendBeacon, a same-origin dev-server proxy, or server-side instrumentation. - Host rejected: use
127.0.0.1,localhost, or::1; never bind to LAN or public interfaces. - Sandbox blocks listener: retry once with the required approval for this loopback collector. If approval is denied, explain that local collection is blocked and fall back only when a safe file-based probe path exists.
- Too many logs: replace noisy probes with narrower state-change probes.
- Cannot reproduce: ask for exact steps, environment, input data, or a screen recording; do not invent a fix.
Cleanup Checklist
Before declaring the task done:
- Re-run the original repro or the closest available automated check.
- Remove every paired region marked
DEBUG_MODE_PROBE <session_id>. - Search for the session id,
DEBUG_MODE_PROBE,#region DEBUG_MODE_PROBE, and#endregion DEBUG_MODE_PROBE. - Remove the session NDJSON log at the printed
LOG_FILE, or confirm it should be kept as local evidence. - Keep only the product fix and any useful regression test.