| name | debugging-master |
| description | Hypothesis-driven runtime debugging with temporary, auto-cleanable instrumentation across Node/TS, PHP, and browser (via HTTP). Triggers on "debug this", "add temporary logs", "instrument X", "why is this slow/wrong at runtime", "test my theory", comparing failing vs passing runs, intermittent or cross-device bugs. Not for type errors or static code review. |
Debugging Master
Runtime data beats static analysis. Instead of guessing, instrument code with targeted logging, reproduce the bug, and analyze real runtime data.
Critical Rules
- NEVER guess at runtime values or execution flow. Instrument, reproduce, analyze. One
dbg.dump() is worth a hundred lines of static reasoning.
- EVERY ingest call MUST be wrapped in
// #region @dbg / // #endregion @dbg markers — no exceptions. This is what makes cleanup and the git-stash-and-reapply workflow work. A bare dbg.info(...) / LlmLog::info(...) / fetch('http://.../log/...') outside markers is a bug: cleanup cannot find it, cannot stash it, cannot remove it, and it WILL get committed by accident. Wrap every single ingest line (imports, requires, fetch posts, every dbg.* / LlmLog::* call) in its own region block. Use tools debugging-master snippet <type> <label> to generate ready-to-paste, correctly wrapped blocks instead of hand-writing them.
Quick Reference
tools debugging-master start --session <name>
tools debugging-master get
tools debugging-master get -l dump,error
tools debugging-master get --last 5
tools debugging-master expand d2
tools debugging-master expand d2 --full
tools debugging-master expand d2 --query 'x[*].y'
tools debugging-master tail
tools debugging-master sessions
tools debugging-master diff --session s1 --against s2
tools debugging-master cleanup
When to Use
- Runtime bugs: Values aren't what you expect, logic branches wrong
- Performance issues: Something is slow but you don't know what
- Execution flow: Code paths are unclear, order of operations is wrong
- Data inspection: Need to see actual shapes/values at runtime
- Intermittent failures: Need to capture state when the bug occurs
- Comparing runs: Passing vs failing, before vs after
Setup
tools debugging-master start --session fix-auth-bug --path src/utils
tools debugging-master start --session fix-auth-bug
The start command:
- Copies/updates
llm-log.ts (or .php) into the configured snippet path
- Creates a session log file
- Outputs the import path to use in instrumentation
Instrumentation
Rules
- MANDATORY: every ingest call MUST be wrapped in
// #region @dbg / // #endregion @dbg markers. No exceptions — not for imports, not for one-liners, not for fetch('/log/...') HTTP posts, not even for "I'll remove it manually in a second" debug lines. The stash and cleanup tooling is ONLY able to see / move / restore lines that live inside these markers. An un-wrapped ingest line is a leak waiting to be committed.
import { dbg } from '../utils/llm-log';
- Every debug line gets its OWN region block — granular stash + removal, and so a partial cleanup can drop one call without disturbing the others:
dbg.dump('userData', userData);
- Prefer
tools debugging-master snippet <type> <label> to generate blocks — it always emits the markers correctly so you cannot forget them. Hand-written ingest calls are the #1 source of orphan logs that survive cleanup.
API Methods
| Method | Use For | Example |
|---|
dbg.dump(label, data) | Inspect any value | dbg.dump('user', user) |
dbg.info(msg, data?) | Log a message with optional data | dbg.info('auth started') |
dbg.warn(msg, data?) | Warnings | dbg.warn('token expiring', { ttl }) |
dbg.error(msg, err?) | Capture errors with stack | dbg.error('auth failed', err) |
dbg.timerStart(label) | Start a timer | dbg.timerStart('db-query') |
dbg.timerEnd(label) | End timer, log duration | dbg.timerEnd('db-query') |
dbg.checkpoint(label) | Mark execution reached a point | dbg.checkpoint('after-auth') |
dbg.assert(cond, label, ctx?) | Assert + log pass/fail | dbg.assert(user.id > 0, 'valid-id', { id: user.id }) |
dbg.snapshot(label, vars) | Capture multiple variables at once | dbg.snapshot('state', { user, token, config }) |
dbg.trace(label, data?) | Trace with optional data | dbg.trace('enter-handler', { method: req.method }) |
Hypothesis Tagging
Tag instrumentation with hypothesis IDs to filter later:
dbg.dump('token', token, { h: 'H1' });
dbg.dump('session', session, { h: 'H2' });
Then filter: tools debugging-master get --hypothesis H1
Instrumentation Example
import express from 'express';
import { dbg } from '../utils/llm-log';
async function handleAuth(req: Request) {
dbg.dump('reqHeaders', req.headers, { h: 'H1' });
dbg.timerStart('token-verify');
const token = await verifyToken(req.headers.authorization);
dbg.timerEnd('token-verify');
dbg.dump('verifiedToken', token, { h: 'H1' });
if (!token.valid) {
dbg.error('token invalid', new Error('Token verification failed'));
return { status: 401 };
}
dbg.checkpoint('auth-passed');
return { status: 200, user: token.user };
}
Reading Logs — Progressive Detail (3 Levels)
Always start at L1 and drill down. This saves tokens.
L1: Compact Timeline (get)
tools debugging-master get
Output:
Session: fix-auth-bug (23 entries, 4.2s span)
Summary:
5 dump 3 checkpoint 2 error 1 timer-pair (avg 340ms)
8 info 3 trace 1 assert (0 failed) 1 raw
File: src/api.ts
#1 14:32:05.123 info "starting auth flow"
#2 14:32:05.200 dump userData [ref:d2] 2.4KB
#3 14:32:05.201 timer db-query 341ms
File: src/auth/handler.ts
#4 14:32:05.542 checkpoint after-query
#5 14:32:05.543 dump queryResult [ref:d5] 890B
#6 14:32:05.600 error "auth token expired" [ref:e6] stack
Tip: Expand a ref -> tools debugging-master expand d2
Values >200 chars get a [ref:XX]. Use filtering to narrow down:
tools debugging-master get -l dump,error
tools debugging-master get --last 5
tools debugging-master get --hypothesis H1
L2: Schema View (expand, default)
tools debugging-master expand d2
Shows the structure/shape of the data without full values. Three schema modes:
tools debugging-master expand d2
tools debugging-master expand d2 --schema typescript
tools debugging-master expand d2 --schema schema
L3: Full Data (expand --full or --query)
tools debugging-master expand d2 --full
tools debugging-master expand d2 --query 'user.email'
tools debugging-master expand d2 --query 'items[*].name'
Token efficiency rule: L1 -> L2 -> L3. Never jump to --full without checking the schema first.
Workflow: Hypothesis-Driven (Complex Bugs)
Recommended for bugs where the root cause is unclear.
- Form hypotheses (2-3 guesses about what's wrong)
- Start session:
tools debugging-master start --session <descriptive-name>
- Instrument — add targeted
dbg.* calls near suspected code, tag with {h: 'H1'}, {h: 'H2'}
- Ask user to reproduce the bug
- Read L1:
tools debugging-master get — scan summary and timeline
- Drill into refs:
expand <ref> for structure, --query for specific fields
- Analyze — confirm or eliminate hypotheses based on actual data
- Iterate — if not resolved, add more instrumentation and repeat from step 4
- Fix the bug with confidence (you have the data)
- Cleanup:
tools debugging-master cleanup
Workflow: Quick Instrumentation (Simple Bugs)
For straightforward issues where you just need to see a value.
tools debugging-master start --session quick-check
- Add 1-3
dbg.dump() calls
- Ask user to reproduce
tools debugging-master get --last 5
- Fix and
cleanup
Workflow: Performance Profiling
dbg.timerStart('total-request');
dbg.timerStart('db-query');
const data = await db.query(sql);
dbg.timerEnd('db-query');
dbg.timerStart('transform');
const result = transform(data);
dbg.timerEnd('transform');
dbg.timerEnd('total-request');
Read timings: tools debugging-master get -l timer
Workflow: Execution Flow Tracing
dbg.checkpoint('handler-entry');
if (condition) {
dbg.checkpoint('branch-a');
} else {
dbg.checkpoint('branch-b');
}
dbg.checkpoint('before-return');
Read flow: tools debugging-master get -l checkpoint
Workflow: Session Comparison
Compare a failing run against a passing run to spot divergence:
tools debugging-master start --session auth-fail
tools debugging-master start --session auth-pass
tools debugging-master diff --session auth-fail --against auth-pass
tools debugging-master diff --session auth-fail --against auth-pass -l checkpoint
JMESPath Quick Reference
Use with tools debugging-master expand <ref> --query '<expression>':
data.field # Nested field access
data.nested.deep.value # Multi-level nesting
items[0] # First array element
items[-1] # Last array element
items[0:3] # Slice (first 3)
items[*].name # All names from array of objects
items[?status=='active'] # Filter array by condition
items[?age>`25`] # Numeric comparison (backtick numbers)
items[?contains(name, 'foo')] # String contains filter
{id: id, name: name} # Object projection (pick fields)
items[*].{id: id, n: name} # Array of projections
length(items) # Count items
sort_by(items, ×tamp) # Sort by field
max_by(items, &duration) # Max by field
join(', ', items[*].name) # Join names into string
@ # Current node (identity)
Common Patterns
--query 'data.user.email'
--query 'data.errors[*].message'
--query 'data.items[?status==`failed`].id'
--query '{total: length(items), first: items[0].name, last: items[-1].name}'
HTTP Server Mode
For browser debugging or environments where file writes are not possible:
tools debugging-master start --session browser-debug --serve
Send logs via fetch:
fetch('http://127.0.0.1:7243/log/browser-debug', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
level: 'dump',
label: 'componentState',
data: state,
location: 'App.tsx:42',
ts: Date.now()
})
}).catch(() => {});
Use tools debugging-master snippet dump myVar --http to generate these blocks automatically.
PHP Support
Use --language php when starting a PHP project:
tools debugging-master start --session laravel-bug --language php --path app/Support
PHP API uses static methods (LlmLog:: instead of dbg.):
require_once __DIR__ . '/../app/Support/llm-log.php';
LlmLog::dump('userData', $userData);
LlmLog::timerStart('db-query');
$result = DB::table('users')->get();
LlmLog::timerEnd('db-query');
PHP HTTP mode auto-detects Guzzle. If installed, uses Guzzle; otherwise falls back to file_get_contents.
Cleanup Checklist
Cleanup is opt-in — tools debugging-master cleanup with no flags just prints help and exits. You MUST pick an action:
tools debugging-master cleanup --blocks
tools debugging-master cleanup --clean-logs
tools debugging-master cleanup --blocks --clean-logs
tools debugging-master cleanup --blocks --no-stash
tools debugging-master cleanup --blocks --stash-message "auth bug investigation"
tools debugging-master cleanup --clean-logs ./debug-logs/
tools debugging-master cleanup --blocks --repair-formatting
What --blocks does:
- Scans all project files for
// #region @dbg ... // #endregion @dbg blocks (this is why every ingest line MUST be wrapped — see Critical Rules)
- Stashes the @dbg blocks + the
llm-log.{ts,php} snippet into git first (default; --no-stash to skip)
- Removes the blocks from working tree
- Reports any formatting-only diffs;
--repair-formatting git checkouts those files
--stash-message <msg> attaches a custom note to the stash entry
What --clean-logs does:
- Moves the active session jsonl + meta out of
~/.genesis-tools/debugging-master/sessions/
- Default destination is
/tmp/<datetime>-llmlog-<session>.jsonl (cleared on reboot)
- Pass a path to keep them permanently:
--clean-logs ./debug-logs/
Re-applying a stash
The stash is the recovery mechanism. Recommend apply (NOT pop) so the stash sticks around for repeated re-application:
git stash list
git stash apply stash@{0}
git stash show -p stash@{0}
git stash drop stash@{0}
What cleanup does NOT do:
- Delete sessions from config (use the sessions CLI for that)
- Permanently delete log data —
--clean-logs archives, never rm
- Leave unrelated edits untouched in files that contain
@dbg blocks — note that --blocks stashes whole files, so any non-debug edits in those files move into the stash too
- Find or stash any ingest line that's missing its
// #region @dbg markers (this is the failure mode the wrap-mandate prevents)
Token Efficiency Tips
- Filter with
-l <level> — don't load all entries when you only need dumps
- Use
--last N — when the log is long, read only recent entries
- Use
expand before expand --full — check schema/shape first
- Use
--query with JMESPath — extract only the fields you need
- Use
--format json for machine processing (pipe to tools json)
- Use
--hypothesis <tag> — filter to specific hypothesis when multiple are tagged
- Use
get -l timer for performance work — skip everything except timing data