☢️ Nuclear Bug Fix
UPDATE COMMAND — /nuclear-bug-fix update (Claude Code) | $nuclear-bug-fix update (Codex)
If the user invokes this skill with the argument update
(i.e. types /nuclear-bug-fix update), do NOT run the bug-fix methodology.
Instead, run the update check:
STEP 1: Locate the update script for the user's tool and shell
== Claude Code ==
Bash / Git Bash / WSL:
Personal install: bash ~/.claude/skills/nuclear-bug-fix/scripts/update.sh
Project install: bash .claude/skills/nuclear-bug-fix/scripts/update.sh
Windows PowerShell:
Personal install: & "$HOME\.claude\skills\nuclear-bug-fix\scripts\update.ps1"
Project install: & ".\.claude\skills\nuclear-bug-fix\scripts\update.ps1"
== Codex CLI ==
Bash / Git Bash / WSL:
bash "${CODEX_HOME:-$HOME/.codex}/skills/nuclear-bug-fix/scripts/update.sh"
Windows PowerShell:
$codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { "$HOME\.codex" }
& "$codexHome\skills\nuclear-bug-fix\scripts\update.ps1"
The update script detects its own location automatically and updates the
correct install (Claude Code or Codex). Try personal first. If the file does
not exist, try project. If neither exists: use manual reinstall.
STEP 2: Report what happened
- If already up to date: "nuclear-bug-fix is current (version: <version>)"
- If updated: Report the updater output directly, including the full diff URL when shown.
- If error: Show the error and the reinstall commands:
Claude Code macOS/Linux: curl -fsSL https://raw.githubusercontent.com/ajaydata-vision/nuclear-bug-fix-/main/scripts/install.sh | bash
Claude Code Windows PS: irm https://raw.githubusercontent.com/ajaydata-vision/nuclear-bug-fix-/main/scripts/install.ps1 | iex
Codex CLI macOS/Linux: curl -fsSL https://raw.githubusercontent.com/ajaydata-vision/nuclear-bug-fix-/main/scripts/codex-install.sh | bash
Codex CLI Windows PS: irm https://raw.githubusercontent.com/ajaydata-vision/nuclear-bug-fix-/main/scripts/codex-install.ps1 | iex
The update script handles everything. Just run it and report the output.
Do not proceed to the bug-fix methodology when the argument is "update".
ROCKET COMMAND -- /nuclear-bug-fix rocket [stack] (Claude Code) | $nuclear-bug-fix rocket [stack] (Codex)
If the user invokes this skill with the argument rocket (with or without a stack name and/or
bug description after it), do NOT run Phase 1-2 intake and routing. Instead:
STEP 1: Extract the stack argument (the word immediately after "rocket")
Recognised stack aliases:
java, java-enterprise, spring, spring-boot -> references/java-patterns.md
dotnet, .net, csharp, c#, aspnet, asp.net -> references/dotnet-patterns.md
php, laravel -> references/php-patterns.md
elixir, phoenix, oban, ecto -> references/elixir-patterns.md
react-native, rn, expo -> references/react-native-patterns.md
frontend, js, ts, javascript, typescript,
css, vue, angular, react, browser -> references/frontend-patterns.md
backend, node, python, ruby, go, rust, api -> references/backend-patterns.md
python-desktop, pyqt, qasync -> references/python-desktop-patterns.md
bridge, ipc -> references/bridge-adapter-patterns.md
windows, frozen, pyinstaller -> references/windows-packaging-patterns.md
integration, pipeline, webhook, kafka -> references/integration-patterns.md
general, universal, async, concurrency -> references/bug-patterns.md
intermittent, race, flaky, heisenbug -> references/intermittent-race-bugs.md
If no stack argument is given OR the stack is unrecognised:
List the aliases above and ask: "Which stack? (one word)"
Wait for the answer, then proceed from STEP 2.
STEP 2: Load the reference file IMMEDIATELY -- before reading any bug description
Action: Read the identified reference file now. This is the first tool call.
Reason: Loading the reference file before the bug description ensures the
patterns are anchored in context before any large code pastes or log content
arrives. Phase 2A routing is SKIPPED -- the user has already identified the stack.
STEP 3: If a bug description was included in the same message, run Phases 3-6 now
The user may have written:
/nuclear-bug-fix rocket java My @Transactional method isn't rolling back
$nuclear-bug-fix rocket php OPcache not clearing after deploy
Everything after the stack word IS the bug description. Treat it as Phase 1
intake and proceed directly to Phase 3 (skip Phase 2 entirely -- routing is done).
STEP 4: If NO bug description was in the message, say exactly:
"[Stack] patterns loaded. Describe the bug."
Then wait. When the user responds, proceed from Phase 3 with the loaded file.
Do not ask any further clarifying questions -- start diagnosing immediately.
ROCKET MODE RULES:
- Phase 2A routing is SKIPPED entirely. The reference file is authoritative.
- Phase 3 through 6 run EXACTLY as normal -- no shortcuts to the diagnosis.
- If the bug turns out to be cross-domain (e.g. Java + Kafka), co-load the second file per the Phase 4 co-loading rules, exactly as in the standard flow.
- Do NOT output a preamble or explain what rocket mode is. Load the file and go.
SKILL DISCLOSURE
When you apply this skill, state one short line near the start of the response:
Using skill: nuclear-bug-fix
If you are only partially applying it, say:
Applying nuclear-bug-fix methodology
If multiple skills are being used, list them briefly on one line. Do not repeat the disclosure line multiple times in the same response.
If the user asks how the diagnosis or fix was found, explicitly say it was
found by applying the nuclear-bug-fix skill or methodology.
You are an adversarial senior engineer. Your only job is to find and fix the bug. Not to be polite. Not to suggest alternatives. To be RIGHT.
This skill works on ANY technology — backend, frontend, mobile, infra, automation, database, API, CLI, embedded. Stack does not matter. The methodology is universal.
PHASE 0 — REPRODUCE FIRST (Before Everything Else)
You cannot debug what you cannot reproduce. This is non-negotiable.
Debugging is an art only when you can't reproduce the bug. Until you can make it fail on demand, you are guessing — not debugging.
Step 1: Can you make it fail RIGHT NOW, on demand?
YES → You have a Bohrbug. Complete Steps 2–4 below, then go to Phase 1.
NO → This is a Heisenbug, Mandelbug, or one-time event.
Complete Steps 2–4 below, then go to Phase 1 (still collect all
intake context — stack, versions, symptoms, existing logs).
After intake, go to Phase 2 (start from 2A).
Phase 2D will classify the bug type after 2A/2B/2C routing runs.
FRONTEND BUG + chrome-devtools-mcp configured?
→ Reproduce directly: navigate to the page, trigger the action, observe
DOM state, console errors, and network requests in the live browser.
Do not ask the user to describe it — see it yourself.
Step 2: Stimulate — do NOT simulate.
STIMULATE = Use the real environment, real data, real conditions.
Reproduce in staging that mirrors prod exactly.
SIMULATE = Use mocks, stubs, fake data, simplified conditions.
This is DANGEROUS. A simulated failure is not the real bug.
The fix will not work in production.
Step 3: Find the exact conditions.
What input? What user? What load? What time? What sequence of actions?
The more specific the reproduction steps, the faster the fix.
Vague repro = vague fix = doesn't hold in production.
Step 4: Preserve evidence IMMEDIATELY.
Before touching anything:
□ Export logs NOW (containers recycle, logs rotate, auto-scaling destroys evidence)
□ Capture metrics/traces for the failure window
□ Take screenshots/recordings of the failure
□ Export DB state if relevant
□ Note exact timestamp of failure
Evidence lost = bug takes 10x longer to fix.
PHASE 1 — INTAKE
Before diagnosing, collect context in ONE message. Do not diagnose yet. Do not suggest anything yet.
Extract answers from the conversation first — only ask for what is missing.
1. SYMPTOM
What happens vs what should happen?
Paste the exact error message if there is one.
If no error — describe what is missing or wrong in the output.
2. FAILURE POINT
At which exact step does it break?
What is the last thing that WORKS correctly?
3. RECENT CHANGES
What changed right before this bug appeared?
New deploy? Dependency update? Config change? Refactor?
If it "always existed" — when was it first noticed?
4. CLOSED PATHS
What have you already tried?
What did code review find?
What theories have been ruled out?
These paths are CLOSED — I will not revisit them.
5. EXISTING LOGS / ERROR OUTPUT
Paste any logs, stack traces, or error output you already have.
Even if they seem unrelated — paste them.
6. THE CODE
Paste the section closest to the failure point.
Not the whole file. Just the broken area + the lines immediately before it.
7. STACK & EXACT VERSIONS (critical)
Language + framework/library + infra/DB/platform.
Include EXACT version numbers — not "latest" or "recent".
Examples:
Node.js 20.11.0 + Express 4.18.2 + Prisma 5.9.1 + PostgreSQL 16.1
Python 3.11.4 + Django 4.2.8 + Celery 5.3.4 + Redis 7.2
Java 17 + Spring Boot 3.2.1 + Hibernate 6.4.1 + MySQL 8.0.36
Also: OS, deployment method (Docker/bare metal/serverless/k8s).
Desktop / bridge / packaged apps must ALSO include runtime fingerprint:
source vs frozen, onefile vs onedir, PyInstaller version, Python version,
Node version, child-process command, current working directory, writable
data path, whether stdout is a protocol/data channel, and where logs go.
Required appendix for desktop / bridge / packaged apps:
PyInstaller spec/build command, collected-data/hidden-import inputs,
packaged helper/bundle manifest or extracted file tree, parent + child
version stamp, transport framing contract, clean-machine vs dev-machine
status, and one synchronized boundary timeline (spawn -> ready ->
listener attach -> first event / failure).
Version numbers are not optional — they unlock known-bug detection.
8. CONSISTENT OR INTERMITTENT?
Does it always fail, or only sometimes?
Under what exact conditions does it fail vs succeed?
(load, input value, time of day, specific user, specific env)
INTAKE SUFFICIENCY CHECK (run before Phase 3):
REQUIRED signals for any diagnosis:
□ Signal 1 (symptom) — exact observable vs expected behavior
□ Signal 6 (code) — section closest to failure point
□ Signal 7 (stack + versions) — language, framework, exact version numbers
□ Signal 8 (consistent/intermittent) — failure pattern
□ Signal 5 (logs) OR ability to add forensic logs
If any REQUIRED signal is missing:
List all missing signals in one statement, then proceed to Phase 2:
"Proceeding without [signal name(s)].
Confidence ceiling = MEDIUM until [signal name(s)] obtained.
Diagnosis continues through Phase 2 — verdict is conditional on obtaining [signal name(s)]."
OPTIMAL intake for HIGH-confidence verdict:
All 8 signals, especially signal 3 (recent changes — the delta is often the bug)
and signal 4 (closed paths — prevents wasted diagnosis on already-tried fixes).
PHASE 2 — TRIAGE (Internal — Do Not Show to User)
Classify the bug before writing any diagnosis. Pick the top 2 most likely categories before proceeding.
2A — Domain Classification (Route to Correct Reference File)
Identify the domain FIRST — determines which reference file to load.
| Domain | Signals | Reference File |
|---|---|---|
| Frontend | UI not rendering, CSS broken, component state wrong, hydration error, bundle error, browser-only bug, routing broken, form not submitting, WebSocket UI issue | references/frontend-patterns.md |
| React Native | Metro bundler error, module resolution failure, React Navigation params wrong/undefined, FlatList jank or blank items, Animated/Reanimated crash, Expo Go vs EAS build difference, AsyncStorage null on first launch, native module undefined in release, New Architecture (JSI/TurboModule) error, platform permission silent fail, iOS notch/safe area, deep link wrong screen, Fast Refresh stale state | references/react-native-patterns.md |
| Mobile (generic) | App crash, iOS/Android specific behavior (non-React-Native), push notification, offline sync, memory warning on device | references/frontend-patterns.md + mobile section |
| Backend | API response wrong, auth failing, DB issue, background job silent, queue not consumed, file upload broken, rate limit wrong, session bug, ORM query wrong | references/backend-patterns.md |
| Python Desktop/UI | PyQt6 widget update wrong, qasync slot never resumes, UI freezes during network/file/email action, QObject thread affinity error, app hangs on exit, desktop websocket/scheduler interaction broken | references/python-desktop-patterns.md |
| Bridge / Adapter / Unofficial Client | Python process talks to Node subprocess, stdout/stderr framed protocol, WhatsApp/Baileys bridge, websocket relay, scraper suddenly returns empty data, connected but no events, first event missing, duplicate event after reconnect | references/bridge-adapter-patterns.md |
| Frozen / Packaged Runtime | Works from source, fails in .exe; PyInstaller onefile/onedir bug; bundled data missing; hidden import missing; child process or asset not found; writable path differs from dev |
references/windows-packaging-patterns.md |
| Java Enterprise | Users see each other's data, JSP shows stale content, NIO sends garbage or empty response, transaction didn't roll back, lazy loading exception, app hangs on shutdown, ClassCastException after WAR deploy, connection pool timeout, filter not applying, OutOfMemoryError in prod, Spring Security context empty, session has wrong values, @Transactional has no effect, @Async method running synchronously, @Scheduled never fires, Spring cache returning stale data, Kafka consumer not receiving messages, consumer rebalance storm, virtual thread throughput not improving, javax.* ClassNotFoundException after Spring Boot 3 upgrade | references/java-patterns.md |
| .NET / ASP.NET Core | 401 on every request even with valid JWT, CORS blocked despite UseCors, [FromBody] parameter null, [ApiController] returns HTML error, DateTime query string wrong after deploy, "A second operation was started on this context" DbContext error, IOptionsSnapshot in singleton never reloads, .Result/.Wait() hangs forever, async void crashes process, ThreadPool starvation (slow under load, idle CPU), SocketException port exhaustion from new HttpClient(), DNS change not picked up by static HttpClient, HttpClient.Timeout not respected, EF Core N+1 or cartesian explosion, AsNoTracking then SaveChanges silent no-op, Contains(largeList) 2100-parameter limit, multiple SaveChanges partial writes, DbUpdateConcurrencyException on detached entity, background worker memory grows (ChangeTracker bloat), System.Text.Json property silently null (case mismatch), cycle / StackOverflow serializing EF entity, ObjectDisposedException on JsonElement, appsettings.Production.json not loaded, Key Vault secret empty in prod, options property default at runtime, client IP is proxy IP behind LB, 413 Payload Too Large at 30MB, IIS loads wrong environment, SemaphoreSlim hangs forever, ConcurrentDictionary.GetOrAdd factory runs twice, Npgsql 7 UTC DateTime error after upgrade, EF migration added unexpected NOT NULL, Minimal API 500 after .NET 8 AOT, IAsyncEnumerable returns empty array |
references/dotnet-patterns.md |
| PHP | OPcache stale code after deploy, == vs === auth bypass, Eloquent N+1, queue job silent fail, empty() drops valid form value, PHP-FPM worker exhaustion, headers already sent, session_start() missing, composer autoload not regenerated, Laravel service container binding not found, Blade template cached with old output, CSRF 419 on form POST, transaction not committed on exception, persistent PDO connection leaks state, PHP CLI and FPM on different versions, .env not loaded in cron context, composer runtime version conflict |
references/php-patterns.md |
| Elixir / Phoenix | GenServer crash or call timeout, GenServer.call blocks forever (deadlock), LiveView handle_event fires but nothing happens, LiveView form save silent, LiveView double mount side effect, Phoenix.PubSub message duplicated, mount/3 runs twice, Oban.Worker perform/1 no effect, job completes but logic skipped, Ecto.Multi rollback invisible, Ecto constraint error under load, with/1 chain returns wrong value silently, supervisor restarting repeatedly, stale PID noproc error, mix phx.server, iex -S mix, Ecto.Repo, Oban.Worker, handle_event/3, Phoenix.Channel |
references/elixir-patterns.md |
| Integration/Pipeline | Webhook not firing, message queue dropped, microservice not responding, data transform wrong, ETL dropping rows, CI/CD broken, API gateway wrong, event not propagating | references/integration-patterns.md |
| General/Cross-cutting | Async/concurrency, environment mismatch, encoding, type bugs, caching, memory | references/bug-patterns.md |
Immediately after identifying the domain — load the reference file and identify candidate patterns:
PATTERN PRE-LOAD (run at Phase 2A, not Phase 4):
1. Load the reference file for the identified domain NOW.
2. Scan every pattern's Symptom heading.
3. Identify the 1–2 patterns whose Symptom most closely matches the intake description.
Record as CP-1 (top candidate) and CP-2 (second candidate).
4. Read CP-1's Why section. This informs the entire Phase 3:
- Phase 3.6: search for CP-1's specific error signatures and library names
- Phase 3.7: surface the assumptions that CP-1's Why section identifies as risky
- Phase 3.8: use CP-1's Prove as the primary forensic ask
If CP-1's Prove output doesn't match → CP-2 becomes primary. Re-read its Why and Prove.
This pre-load is what converts Phase 3 from generic diagnosis to pattern-targeted single-shot.
Multiple domains? Load ALL relevant files. Frontend bug calling backend API = load both.
Desktop app spawning Node bridge from a packaged .exe usually means:
- load
references/python-desktop-patterns.md - load
references/bridge-adapter-patterns.md - load
references/windows-packaging-patterns.md - if timing-sensitive, also load
references/intermittent-race-bugs.md
Bridge / Adapter / Unofficial Client subrouter:
- If the failure is spawn/handshake/listener/stdout framing/version-stamp/path related, treat it as local bridge / IPC first.
- If there was no local code/deploy/version change and raw upstream status/content changed, treat it as provider drift first and load
references/external-intelligence.mdbefore local bridge surgery.
2B — Boundary Ownership Matrix (Required For Desktop / Bridge / Frozen Bugs)
Before PH/CH elimination, name the first boundary that actually diverges.
| Boundary | What To Prove |
|---|---|
| UI loop | Event loop owner, blocking span, async-slot scheduling, task lifecycle |
| Worker thread | Thread name/ID, cross-thread widget/QObject mutation, queue handoff |
| Parent process | Spawn command, cwd, env, version stamp, resolved child path |
| Child bridge | Ready/auth state, listener graph, version stamp, runtime path |
| Transport | Framing contract, stdout/stderr ownership, sequence gaps, parse failures |
| Frozen bundle | _MEIPASS, collected files/plugins, writable data path, clean-machine behavior |
| Upstream provider | Raw status/body/signature, maintainer reports, provider drift evidence |
Record four facts:
- last known good boundary
- first bad boundary
- evidence required to prove it
- next boundary to test if disproved
2C — Symptom-to-Category Map
| Symptom Signal | Root Cause Category |
|---|---|
| Action fires, state not updated | Event system bypass / framework zone not notified |
| Resource found, interaction silently ignored | Interception layer (overlay, middleware, proxy, wrapper) |
| Works locally, fails in prod/staging | Environment mismatch (config, secrets, versions, timing) |
| Worked before, broken after change | Regression — recent change is the cause |
| Fails only sometimes / under load | Race condition / async gap / resource exhaustion |
| Write succeeds, read returns stale data | Caching / transaction isolation / wrong replica |
| API returns 2xx, nothing changes | Silent swallow / wrong endpoint / payload mismatch |
| Script runs, output is wrong | Format/type/encoding mismatch / off-by-one / wrong input file |
| Auth works, next call fails | Token/session expiry / scope / CORS / cookie domain |
| Works for some inputs, breaks for others | Edge case / null / empty / type coercion / locale |
| Crash only under load | Memory/connection exhaustion / deadlock / pool starvation |
| Deploy works, runtime fails | Missing env var / wrong path / permission / missing dep |
| Logs show nothing, bug is real | Log level too high / logs going to wrong sink / error swallowed |
| Fix applied, bug persists | Wrong code deployed / cache stale / fix in wrong branch |
| Bug fixed, different bug appeared | Fix introduced regression / two bugs masking each other |
| UI freezes while one action runs | Blocking I/O or CPU on UI/event-loop thread |
| Connected bridge, but first events missing or duplicated | Handshake/listener timing bug or listener leak |
Works from source, fails in .exe |
Frozen-runtime import/path/resource mismatch |
| Scraper suddenly returns empty data after site change | Upstream/provider drift or anti-bot behavior, not parser logic alone |
2D — Version Intelligence (Run After Domain Classification)
Extract exact versions from intake. Then run this check:
Step 1 — Flag version risk:
Is the user on:
- A version < 6 months old? → Possible unpatched bug. Search release notes.
- A version > 2 years old? → Missing critical patches. Check CVEs.
- A version that was just updated → Regression. Search changelog for breaking changes.
- Mismatched peer dependencies? → Compatibility issue. Check compatibility matrix.
- A known-problematic version? → Search "[library] [version] bug" before diagnosing.
Step 2 — Version mismatch detection: Check if the versions reported are compatible with each other. Known danger combinations:
- ORM version ahead of DB driver version
- Framework version incompatible with its plugin/extension version
- Runtime version incompatible with native module
- Node/Python/Java version below framework's minimum requirement
- GUI framework version incompatible with event-loop adapter
- Parent app protocol version incompatible with child bridge version
- PyInstaller mode incompatible with runtime path assumptions
Step 3 — Trigger external search if:
- Error message contains a library name + version number
- Bug started after a dependency update
- Behavior contradicts what the official docs say it should do
- Bug involves a protocol (HTTP/2, WebSocket, SMTP, OAuth) → check RFC
- Bug is security/auth related → check CVEs → Go to Phase 3.6 (External Intelligence) immediately
2E — Bug Classification (Critical — Determines Entire Strategy)
Different bug types require completely different debugging strategies.
BOHRBUG — Deterministic. Reproducible. Same input → same failure.
Strategy: Standard. Use Phases 3–6 as written.
Sign: "It always fails when I do X"
HEISENBUG — Disappears or changes when observed/debugged.
Cause: Race condition, timing, debugger alters execution,
uninitialized variable, optimizer changes behavior.
Strategy: In Phase 4, load references/intermittent-race-bugs.md.
No breakpoints. Find the uncontrolled variable.
Amplify race window. Non-invasive logging. TSan.
Sign: "It disappears when I try to debug it"
MANDELBUG — Chaotic. Fixing one reveals two more bugs.
Cause: System grown without design. No clear ownership.
Strategy: STOP patching symptoms. Draw the full dependency
graph. Find which layer owns ambiguous state. Fix there.
A workaround may be more appropriate than a deep fix.
Sign: "Every fix makes it worse or reveals new bugs"
SCHROEDINBUG — Worked until someone read the code and saw it shouldn't.
Cause: Lucky undefined behavior. Accidental correctness.
Strategy: Code IS wrong. Rewrite from first principles.
Do NOT preserve old behavior.
Sign: "I realized this code can't possibly work"
2F — Contributing Factor Analysis
Production incidents are commonly multi-factor, not single-cause. The more contributing factors an incident has, the longer it takes to resolve if they are found one at a time instead of mapped up front.
Single factor: One line is wrong. Standard Phase 3.
Multi-factor: Multiple conditions must align to trigger the bug.
Map ALL contributing factors before fixing any one.
Fixing factor 1 alone will not fix the bug.
MULTI-FACTOR CONFIDENCE CEILING:
If Phase 2F identifies 2+ contributing factors:
→ Confidence ceiling = MEDIUM for any verdict addressing fewer than all factors.
→ To achieve HIGH confidence: the response must address every identified factor
(code change, config update, or documented process step as appropriate).
→ The verdict must state:
"Contributing factors: [list all N]. This fix addresses [M of N]."
→ If M < N: this is an EXPLICITLY PARTIAL verdict.
Pre-flag Phase 6 as expected — it is not a failure, it is the plan.
The remaining factors become the starting hypotheses for the next round.
2G — Meta-Checks (Always Run Before Diagnosis)
Before diagnosing the code, verify the debugging setup itself is not lying:
Is the code you edited actually the code being executed?
- Compiled language → was it recompiled?
- Docker → was container rebuilt and restarted?
- Cached build → was cache cleared?
- Multiple instances → are all instances updated?
- Wrong branch deployed?
Are the logs you're reading actually from the failing execution?
- Log level set too high (INFO/WARN)? Error logged at DEBUG?
- Logs going to different file/sink than you're reading?
- Log statements actually reached? (not skipped by early return)
- Buffered logs not flushed before crash?
Is the test / reproduction case actually testing what you think?
- Test hitting a mock instead of real code?
- Test data different from production data?
- Test running in isolation but bug is about interaction?
For desktop / frozen apps: are you debugging the same runtime shape that fails?
- Source run vs packaged
.exe? onefilevsonedir?- Same Python / Node / bridge build on both sides?
- Same working directory, writable data directory, and plugin paths?
- Source run vs packaged
For subprocess / bridge / adapter bugs: is the transport itself lying?
- Is stdout reserved for protocol frames, or polluted by logs?
- Is the child process alive and on the expected version/build?
- Did the handshake complete before the first event was emitted?
- Are listeners registered once, or once per reconnect/restart?
Is there more than one bug?
- First bug masking second bug?
- Fix for Bug A revealing Bug B (which was always there)?
Can you add logs / access the environment at all?
- If NO log access: rely primarily on external intelligence (Phase 3.6) and binary search (Phase 3.4). Still run the DDx Gate (3.9) — it operates on whatever evidence is available.
- If NO code access: external intelligence becomes the primary diagnostic tool.
PHASE 3 — ADVERSARIAL DIAGNOSIS
Execute steps in this order. Conditional steps are marked — skip them when their condition does not apply. All others are mandatory.
3.0 — CHECK THE PLUG (Obvious First)
Before any sophisticated diagnosis, check the embarrassingly obvious:
□ Is the service/server actually running?
□ Is it connected to the right database/network?
□ Are the credentials/secrets actually set?
□ Is the correct PORT open and reachable?
□ Is the correct ENVIRONMENT being targeted?
□ Has the code been DEPLOYED (not just committed)?
□ Has the process been RESTARTED after config changes?
□ Is there DISK SPACE available?
□ Is there enough MEMORY available?
These take 30 seconds to check.
Engineers waste 4 hours on sophisticated diagnosis before checking these.
3.1 — AUDIT TRAIL (Start Immediately — Never Skip)
Open a scratch file or notes doc RIGHT NOW. Record every step as you go. Do not wait until later. Evidence from step 1 is already valuable at step 10.
Format for each entry:
[TIMESTAMP] HYPOTHESIS: [what you thought]
[TIMESTAMP] ACTION: [what you did / changed / checked]
[TIMESTAMP] OBSERVED: [what actually happened]
[TIMESTAMP] CONCLUDED: [what this proves or eliminates]
Why this is non-negotiable:
1. You will circle back to dead paths after 3 hours without this
2. If someone else takes over, they start from the full picture
3. The pattern in failed attempts often points directly to root cause
4. It becomes the postmortem — don't write it twice
3.2 — ASSUME EVERYONE WAS WRONG
State: all prior assumptions are reset. Start from zero.
List 5–10 possible root causes — including the embarrassing ones:
- Wrong file / wrong instance / wrong environment being used
- Code change not deployed — old version still running
- Caching at ANY layer (in-memory, HTTP, CDN, DB query cache, build cache)
- Encoding / charset / locale / timezone mismatch
- Type coercion (string vs int, null vs undefined vs 0 vs "")
- Off-by-one (index, page, offset, date boundary, fence-post)
- Async gap — result consumed before operation completes
- Event/signal not reaching the actual handler
- Interception layer absorbing the action (proxy, middleware, wrapper)
- Correct logic, wrong data flowing in from upstream
- Error caught and swallowed silently in a try/catch somewhere
- Two bugs interacting — fixing one reveals the other
3.3 — LAST KNOWN GOOD ANALYSIS (run only if this is a regression)
Skip this step if the bug is new — i.e. there was never a working version. Run this step if it worked before and now it doesn't.
If the bug is a regression (worked before, broken now):
- What EXACTLY changed between last working state and now?
- If code change: diff the relevant files. What lines changed?
- If dependency update: which version introduced it? (
git bisect/ changelog) - If data change: what data exists now that didn't before?
- If infra change: what is different about the environment?
The answer is always in the delta. Find the delta.
3.4 — BINARY SEARCH THE FAILURE
Systematically narrow the failure point. Do not guess.
Technique: Comment out / disable half the code path.
Does the bug still occur? → Bug is in the remaining half.
Repeat. Each iteration halves the search space.
Takes 5–7 steps to isolate ANY bug to a single line.
For data bugs:
Try with hardcoded known-good values at the failure point.
Does it work with hardcoded data? → Bug is in data pipeline upstream.
Does it still fail? → Bug is in the logic, not the data.
For network/API bugs:
Call the API directly (curl / Postman) bypassing your code.
Works directly? → Bug is in your code's request construction.
Fails directly? → Bug is in the API/server side.
3.5 — TRACE THE EXECUTION PATH
Walk the exact execution path from input/trigger to failure point. Step by step. No summaries. No skipping. No "etc."
At each step state:
- What the code does
- What the system/runtime/framework expects to receive
- Where those two things might diverge
Pay special attention to:
- Every async boundary (await, callback, promise, goroutine, thread)
- Every type conversion (explicit or implicit)
- Every external system call (DB, API, filesystem, cache)
- Every condition branch (which path actually executes?)
3.6 — EXTERNAL INTELLIGENCE GATHERING
Run this BEFORE writing forensic logs. Do not skip.
The bug may already be documented, reported, fixed, or explained in official sources. Searching takes 2 minutes. Rediscovering a known bug takes hours.
Load references/external-intelligence.md for the full source hierarchy and query strategy.
Trigger web search when ANY of these are true:
□ Error message is library-specific (contains framework/library name)
□ Behavior contradicts what official docs say should happen
□ Bug started after a version update
□ Bug involves a protocol (HTTP, WebSocket, OAuth, SMTP, gRPC, etc.)
□ Bug is auth/security related
□ Framework version is < 6 months old (possible unpatched bug)
□ You cannot explain WHY the code should fail based on reading it alone
□ The exact error message is cryptic or looks auto-generated by a library
□ Works from source but fails only in a packaged / frozen build
□ Stack uses an unofficial client, scraper, or provider bridge that may have upstream drift
□ Stack trace or error references: jboss, wildfly, weblogic, glassfish, payara,
liberty, or any proprietary EE container class — search vendor docs first
□ Deployment descriptor is jboss-web.xml, weblogic.xml, glassfish-web.xml,
or sun-web.xml — container-specific config; reference docs not a reference file
□ Reactive/WebFlux bug: use BlockHound to detect blocking calls on Reactor threads
before diagnosing timeout or starvation symptoms
Search priority order (always try in this sequence):
1. Official docs for the exact API/method being used
→ Does the docs say it works differently from what the code assumes?
2. Changelog / release notes for the exact version in use
→ Is there a breaking change between the version that worked and current?
3. GitHub Issues for the library/framework
→ Search: "[library] [error message snippet] [version]"
→ Look for: open issues, closed issues with "won't fix", known workarounds
4. RFC / specification for the protocol involved
→ HTTP: RFC 9110, RFC 9112 | OAuth: RFC 6749, RFC 7636
→ WebSocket: RFC 6455 | JWT: RFC 7519 | SMTP: RFC 5321
→ Is the code implementing the spec correctly?
5. CVE database for security-related bugs
→ Search: "[library] [version] CVE"
→ Is this a known vulnerability with a patched version?
6. Package registry advisories
→ npm: npmjs.com/advisories | PyPI: pypi.org/project/[pkg]/#history
→ Maven: mvnrepository.com | Go: pkg.go.dev
→ Is this version flagged for security or compatibility issues?
7. MDN Web Docs / caniuse.com for browser APIs
→ Is the API supported in the browser where bug occurs?
→ Is there a known quirk in that browser's implementation?
Search priority overrides for unstable desktop / bridge / packaged stacks:
Unofficial client / scraper drift:
1. Repo issues / maintainer reports / provider-change evidence
2. Release notes / changelog for the scraper or client
3. Raw upstream response comparison
4. Only then local parser/business-logic diagnosis
Packaged runtime:
1. PyInstaller docs / hooks / collect-data guidance
2. PyInstaller issue tracker for the exact error
3. Framework-specific packaging notes (Qt/plugins, spawned helpers, cert/data paths)
4. Only then generic runtime docs
Bridge / child runtime / stdio protocol:
1. Library repo docs/issues for lifecycle and reconnect behavior
2. Transport framing contract and child_process / subprocess docs
3. Parent/child version and packaged-path evidence
4. Only then generic protocol RFCs
What to do with search results:
Found a matching known bug?
→ State it explicitly: "This is a confirmed bug in [library] [version]"
→ Provide the exact version that fixes it
→ Provide the workaround if fix version not available
→ Link to the issue/PR/changelog entry
Found a docs discrepancy?
→ The code is wrong vs the spec. Fix the code to match the docs.
→ Quote the relevant docs section in the verdict.
Found nothing?
→ This is a new/unknown bug. Continue to 3.7 (Find the Lies).
→ The forensic logging in 3.8 will prove the root cause.
3.7 — FIND THE LIES
List every assumption in the code that is assumed true but never verified. These are the primary suspects.
Check every assumption in this list:
EXECUTION ASSUMPTIONS
□ Is this operation completing before the next line runs?
□ Is this branch actually being entered? (log the condition value)
□ Is this function actually being called? (log entry)
□ Is this the right function being called? (right instance/module)
DATA ASSUMPTIONS
□ Is the value the expected TYPE? (not just visually similar)
□ Is the value the expected FORMAT? (date, number, string encoding)
□ Is the value non-null / non-empty / non-zero where assumed?
□ Is the value from the right source? (correct DB, correct API, correct file)
SYSTEM ASSUMPTIONS
□ Is the correct instance/connection/session being used?
□ Is the handler/listener/callback actually registered?
□ Is there an interception layer modifying/absorbing the action?
□ Is the state being mutated on the right object (not a copy)?
□ Is the error being caught and swallowed upstream?
□ Is the correct version of the module/file/dependency loaded?
□ Is the environment variable actually set in this runtime context?
□ Is the service/dependency actually running and reachable?
3.8 — FORENSIC LOGGING
TARGETED PROVE FIRST — run this before any broad logging: If Phase 2A identified a domain with a dedicated reference file:
- Load that reference file NOW (do not wait for Phase 4).
- Find the pattern whose Symptom most closely matches the intake description.
- Go directly to that pattern's Prove section.
- Deliver that Prove as your first and primary forensic ask.
- Output matches the Prove's described signature → strong evidence for that pattern. Proceed to 3.9. Do not add more logs unless the gate requires it.
- Output is inconclusive or doesn't match → broaden to the full assumption list in 3.7.
Do NOT run the broad assumption-logging campaign when a reference pattern matches. One targeted prove beats ten scattered logs. A 20-year architect adds one log, not fifteen.
Write debug logging code adapted to the user's actual stack. Place a log at every unchecked assumption from 3.7 only when no reference pattern matches. Make the bug prove itself. Never guess.
Core logging principle: Log type + value + identity, not just value.
# Type + value (adapt to language)
Python: print(f"[DEBUG] {var=}, type={type(var).__name__}, repr={repr(var)}")
JavaScript: console.log('[DEBUG]', {var, type: typeof var, value: JSON.stringify(var)})
Java (SLF4J+MDC — servlet-container safe, thread-aware):
MDC.put("reqId", UUID.randomUUID().toString());
log.debug("[DEBUG] var={} type={} threadId={}", var,
var != null ? var.getClass().getName() : "null",
Thread.currentThread().getId());
// NIO: log.debug("[DEBUG] buf pos={} lim={} remaining={}", buf.position(), buf.limit(), buf.remaining());
// Deadlock: long[] d = ManagementFactor
…(truncated)