debug-toolkit 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -0
- package/SKILL.md +104 -0
- package/dist/capture.d.ts +46 -0
- package/dist/capture.js +246 -0
- package/dist/capture.js.map +1 -0
- package/dist/cleanup.d.ts +12 -0
- package/dist/cleanup.js +103 -0
- package/dist/cleanup.js.map +1 -0
- package/dist/cli.d.ts +40 -0
- package/dist/cli.js +109 -0
- package/dist/cli.js.map +1 -0
- package/dist/context.d.ts +59 -0
- package/dist/context.js +338 -0
- package/dist/context.js.map +1 -0
- package/dist/demo.d.ts +12 -0
- package/dist/demo.js +347 -0
- package/dist/demo.js.map +1 -0
- package/dist/hook.d.ts +17 -0
- package/dist/hook.js +106 -0
- package/dist/hook.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +203 -0
- package/dist/index.js.map +1 -0
- package/dist/injected.js +151 -0
- package/dist/instrument.d.ts +15 -0
- package/dist/instrument.js +87 -0
- package/dist/instrument.js.map +1 -0
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.js +420 -0
- package/dist/mcp.js.map +1 -0
- package/dist/memory.d.ts +73 -0
- package/dist/memory.js +291 -0
- package/dist/memory.js.map +1 -0
- package/dist/methodology.d.ts +7 -0
- package/dist/methodology.js +100 -0
- package/dist/methodology.js.map +1 -0
- package/dist/proxy.d.ts +12 -0
- package/dist/proxy.js +168 -0
- package/dist/proxy.js.map +1 -0
- package/dist/security.d.ts +27 -0
- package/dist/security.js +158 -0
- package/dist/security.js.map +1 -0
- package/dist/session.d.ts +53 -0
- package/dist/session.js +94 -0
- package/dist/session.js.map +1 -0
- package/package.json +33 -0
package/dist/memory.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* memory.ts — Debug session memory across conversations.
|
|
3
|
+
*
|
|
4
|
+
* Three tiers of intelligence:
|
|
5
|
+
* 1. Recall — search past diagnoses for similar errors (keyword overlap)
|
|
6
|
+
* 2. Staleness — flag outdated diagnoses when code has changed since
|
|
7
|
+
* 3. Patterns — detect recurring errors, hot files, regression trends
|
|
8
|
+
*
|
|
9
|
+
* Implementation: JSON file + in-memory inverted index.
|
|
10
|
+
* Zero native dependencies. Fast enough for hundreds of sessions.
|
|
11
|
+
*/
|
|
12
|
+
import { execSync } from "node:child_process";
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync, renameSync } from "node:fs";
|
|
14
|
+
import { join, resolve } from "node:path";
|
|
15
|
+
// ━━━ Git helpers ━━━
|
|
16
|
+
function getGitSha(cwd) {
|
|
17
|
+
try {
|
|
18
|
+
return execSync("git rev-parse --short HEAD 2>/dev/null", { cwd, timeout: 3000 })
|
|
19
|
+
.toString().trim() || null;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Check how many commits have touched a file since a given SHA.
|
|
27
|
+
* Returns null if git isn't available, 0 if unchanged, N if changed.
|
|
28
|
+
*/
|
|
29
|
+
function commitsSince(cwd, sha, file) {
|
|
30
|
+
try {
|
|
31
|
+
const count = execSync(`git rev-list --count ${sha}..HEAD -- "${file}" 2>/dev/null`, { cwd, timeout: 3000 }).toString().trim();
|
|
32
|
+
return parseInt(count, 10);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function checkStaleness(cwd, entry) {
|
|
39
|
+
if (!entry.gitSha)
|
|
40
|
+
return { stale: false, reason: null, commitsBehind: 0, filesChanged: [] };
|
|
41
|
+
let totalCommits = 0;
|
|
42
|
+
const changed = [];
|
|
43
|
+
for (const f of entry.files) {
|
|
44
|
+
// Resolve relative to cwd
|
|
45
|
+
const fullPath = resolve(cwd, f);
|
|
46
|
+
if (!existsSync(fullPath)) {
|
|
47
|
+
changed.push(f);
|
|
48
|
+
totalCommits += 1; // file deleted = definitely stale
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const n = commitsSince(cwd, entry.gitSha, f);
|
|
52
|
+
if (n !== null && n > 0) {
|
|
53
|
+
changed.push(f);
|
|
54
|
+
totalCommits += n;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Also check causeFile if it's different from the error files
|
|
58
|
+
if (entry.rootCause?.causeFile && !entry.files.includes(entry.rootCause.causeFile)) {
|
|
59
|
+
const n = commitsSince(cwd, entry.gitSha, entry.rootCause.causeFile);
|
|
60
|
+
if (n !== null && n > 0) {
|
|
61
|
+
changed.push(entry.rootCause.causeFile);
|
|
62
|
+
totalCommits += n;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (changed.length === 0)
|
|
66
|
+
return { stale: false, reason: null, commitsBehind: 0, filesChanged: [] };
|
|
67
|
+
return {
|
|
68
|
+
stale: true,
|
|
69
|
+
reason: `${changed.length} file(s) changed in ${totalCommits} commit(s) since this diagnosis`,
|
|
70
|
+
commitsBehind: totalCommits,
|
|
71
|
+
filesChanged: changed,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Detect patterns across all stored debug sessions.
|
|
76
|
+
* Cheap — just scans the JSON array, no external calls.
|
|
77
|
+
*/
|
|
78
|
+
export function detectPatterns(cwd) {
|
|
79
|
+
const store = loadStore(cwd);
|
|
80
|
+
if (store.entries.length < 2)
|
|
81
|
+
return [];
|
|
82
|
+
const insights = [];
|
|
83
|
+
// 1. Recurring errors — same errorType in the same file
|
|
84
|
+
const errorFileMap = new Map();
|
|
85
|
+
for (const e of store.entries) {
|
|
86
|
+
for (const f of e.files) {
|
|
87
|
+
const key = `${e.errorType}:${f}`;
|
|
88
|
+
const arr = errorFileMap.get(key);
|
|
89
|
+
if (arr)
|
|
90
|
+
arr.push(e);
|
|
91
|
+
else
|
|
92
|
+
errorFileMap.set(key, [e]);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
for (const [key, entries] of errorFileMap) {
|
|
96
|
+
if (entries.length >= 3) {
|
|
97
|
+
const [errType, file] = key.split(":", 2);
|
|
98
|
+
insights.push({
|
|
99
|
+
type: "recurring_error",
|
|
100
|
+
severity: entries.length >= 5 ? "critical" : "warning",
|
|
101
|
+
message: `${errType} has occurred ${entries.length} times in ${file}`,
|
|
102
|
+
data: { errorType: errType, file, count: entries.length, dates: entries.map((e) => e.timestamp) },
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// 2. Hot files — files that appear in many debug sessions
|
|
107
|
+
const fileCount = new Map();
|
|
108
|
+
for (const e of store.entries) {
|
|
109
|
+
for (const f of e.files) {
|
|
110
|
+
fileCount.set(f, (fileCount.get(f) ?? 0) + 1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const threshold = Math.max(3, Math.ceil(store.entries.length * 0.15));
|
|
114
|
+
for (const [file, count] of fileCount) {
|
|
115
|
+
if (count >= threshold) {
|
|
116
|
+
insights.push({
|
|
117
|
+
type: "hot_file",
|
|
118
|
+
severity: count >= threshold * 2 ? "critical" : "warning",
|
|
119
|
+
message: `${file} appears in ${count}/${store.entries.length} debug sessions (${Math.round(count / store.entries.length * 100)}%)`,
|
|
120
|
+
data: { file, sessions: count, total: store.entries.length },
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// 3. Regressions — same problem diagnosed more than once (diagnosis keywords overlap)
|
|
125
|
+
for (let i = store.entries.length - 1; i >= 1; i--) {
|
|
126
|
+
const current = store.entries[i];
|
|
127
|
+
for (let j = i - 1; j >= Math.max(0, i - 20); j--) { // only check recent 20
|
|
128
|
+
const past = store.entries[j];
|
|
129
|
+
if (current.id === past.id)
|
|
130
|
+
continue;
|
|
131
|
+
// Check if same files AND same errorType — likely a regression
|
|
132
|
+
const sharedFiles = current.files.filter((f) => past.files.includes(f));
|
|
133
|
+
if (sharedFiles.length > 0 && current.errorType === past.errorType) {
|
|
134
|
+
insights.push({
|
|
135
|
+
type: "regression",
|
|
136
|
+
severity: "warning",
|
|
137
|
+
message: `Possible regression: ${current.errorType} in ${sharedFiles[0]} was fixed before (${past.timestamp.slice(0, 10)}) but reappeared`,
|
|
138
|
+
data: {
|
|
139
|
+
currentId: current.id, pastId: past.id,
|
|
140
|
+
file: sharedFiles[0], errorType: current.errorType,
|
|
141
|
+
pastDiagnosis: past.diagnosis, currentProblem: current.problem,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
break; // Only report the most recent regression per entry
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// 4. Error clusters — multiple different errors happening in a short time window
|
|
149
|
+
const sorted = [...store.entries].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
|
|
150
|
+
for (let i = 0; i < sorted.length - 2; i++) {
|
|
151
|
+
const window = sorted.slice(i, i + 3);
|
|
152
|
+
const t0 = new Date(window[0].timestamp).getTime();
|
|
153
|
+
const t2 = new Date(window[2].timestamp).getTime();
|
|
154
|
+
const hoursDiff = (t2 - t0) / (1000 * 60 * 60);
|
|
155
|
+
if (hoursDiff < 2 && hoursDiff > 0) {
|
|
156
|
+
const uniqueErrors = new Set(window.map((e) => e.errorType));
|
|
157
|
+
if (uniqueErrors.size >= 2) {
|
|
158
|
+
insights.push({
|
|
159
|
+
type: "error_cluster",
|
|
160
|
+
severity: "info",
|
|
161
|
+
message: `${window.length} errors in ${Math.round(hoursDiff * 60)} minutes — possible cascading failure`,
|
|
162
|
+
data: {
|
|
163
|
+
errors: window.map((e) => ({ type: e.errorType, file: e.files[0], time: e.timestamp })),
|
|
164
|
+
timeWindowMinutes: Math.round(hoursDiff * 60),
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
i += 2; // Skip past this cluster
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return insights;
|
|
172
|
+
}
|
|
173
|
+
// ━━━ Paths & Persistence ━━━
|
|
174
|
+
function memoryPath(cwd) {
|
|
175
|
+
return join(cwd, ".debug", "memory.json");
|
|
176
|
+
}
|
|
177
|
+
function loadStore(cwd) {
|
|
178
|
+
const p = memoryPath(cwd);
|
|
179
|
+
if (!existsSync(p))
|
|
180
|
+
return { version: 2, entries: [] };
|
|
181
|
+
try {
|
|
182
|
+
const store = JSON.parse(readFileSync(p, "utf-8"));
|
|
183
|
+
// Migrate v1 entries (no gitSha/rootCause)
|
|
184
|
+
for (const e of store.entries) {
|
|
185
|
+
if (e.gitSha === undefined)
|
|
186
|
+
e.gitSha = null;
|
|
187
|
+
if (e.rootCause === undefined)
|
|
188
|
+
e.rootCause = null;
|
|
189
|
+
}
|
|
190
|
+
store.version = 2;
|
|
191
|
+
return store;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return { version: 2, entries: [] };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function saveStore(cwd, store) {
|
|
198
|
+
const p = memoryPath(cwd);
|
|
199
|
+
const tmp = `${p}.tmp_${process.pid}`;
|
|
200
|
+
writeFileSync(tmp, JSON.stringify(store, null, 2));
|
|
201
|
+
renameSync(tmp, p);
|
|
202
|
+
}
|
|
203
|
+
// ━━━ Tokenizer ━━━
|
|
204
|
+
function tokenize(text) {
|
|
205
|
+
return text
|
|
206
|
+
.toLowerCase()
|
|
207
|
+
.replace(/[^a-z0-9_./\-]/g, " ")
|
|
208
|
+
.split(/\s+/)
|
|
209
|
+
.filter((w) => w.length > 2);
|
|
210
|
+
}
|
|
211
|
+
// ━━━ Public API ━━━
|
|
212
|
+
/**
|
|
213
|
+
* Save a completed debug session to memory.
|
|
214
|
+
* Auto-captures the current git SHA for staleness tracking.
|
|
215
|
+
*/
|
|
216
|
+
export function remember(cwd, entry) {
|
|
217
|
+
const store = loadStore(cwd);
|
|
218
|
+
const allText = [
|
|
219
|
+
entry.problem, entry.errorType, entry.category, entry.diagnosis,
|
|
220
|
+
...entry.files,
|
|
221
|
+
entry.rootCause?.trigger ?? "",
|
|
222
|
+
entry.rootCause?.fixDescription ?? "",
|
|
223
|
+
].join(" ");
|
|
224
|
+
const keywords = [...new Set(tokenize(allText))];
|
|
225
|
+
const full = {
|
|
226
|
+
...entry,
|
|
227
|
+
keywords,
|
|
228
|
+
gitSha: getGitSha(cwd),
|
|
229
|
+
rootCause: entry.rootCause ?? null,
|
|
230
|
+
};
|
|
231
|
+
store.entries = store.entries.filter((e) => e.id !== full.id);
|
|
232
|
+
store.entries.push(full);
|
|
233
|
+
if (store.entries.length > 200) {
|
|
234
|
+
store.entries = store.entries.slice(-200);
|
|
235
|
+
}
|
|
236
|
+
saveStore(cwd, store);
|
|
237
|
+
return full;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Search past debug sessions for similar errors.
|
|
241
|
+
* Returns matches ranked by relevance, with staleness info and causal chains.
|
|
242
|
+
*/
|
|
243
|
+
export function recall(cwd, query, limit = 5) {
|
|
244
|
+
const store = loadStore(cwd);
|
|
245
|
+
if (store.entries.length === 0)
|
|
246
|
+
return [];
|
|
247
|
+
const queryTokens = tokenize(query);
|
|
248
|
+
if (queryTokens.length === 0)
|
|
249
|
+
return [];
|
|
250
|
+
const scored = store.entries.map((entry) => {
|
|
251
|
+
let hits = 0;
|
|
252
|
+
for (const qt of queryTokens) {
|
|
253
|
+
for (const ek of entry.keywords) {
|
|
254
|
+
if (ek.includes(qt) || qt.includes(ek)) {
|
|
255
|
+
hits++;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
...entry,
|
|
262
|
+
relevance: hits / queryTokens.length,
|
|
263
|
+
staleness: checkStaleness(cwd, entry),
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
return scored
|
|
267
|
+
.filter((e) => e.relevance > 0.2)
|
|
268
|
+
.sort((a, b) => {
|
|
269
|
+
// Prefer fresh over stale, then by relevance
|
|
270
|
+
if (a.staleness.stale !== b.staleness.stale)
|
|
271
|
+
return a.staleness.stale ? 1 : -1;
|
|
272
|
+
return b.relevance - a.relevance;
|
|
273
|
+
})
|
|
274
|
+
.slice(0, limit);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get memory stats.
|
|
278
|
+
*/
|
|
279
|
+
export function memoryStats(cwd) {
|
|
280
|
+
const store = loadStore(cwd);
|
|
281
|
+
if (store.entries.length === 0) {
|
|
282
|
+
return { entries: 0, oldestDate: null, newestDate: null, patterns: [] };
|
|
283
|
+
}
|
|
284
|
+
return {
|
|
285
|
+
entries: store.entries.length,
|
|
286
|
+
oldestDate: store.entries[0].timestamp,
|
|
287
|
+
newestDate: store.entries[store.entries.length - 1].timestamp,
|
|
288
|
+
patterns: detectPatterns(cwd),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* methodology.ts — The debugging methodology, served as an MCP resource.
|
|
3
|
+
*
|
|
4
|
+
* This is the "hot memory" tier — always available, always loaded.
|
|
5
|
+
* It teaches the agent HOW to debug, not just gives it tools.
|
|
6
|
+
*/
|
|
7
|
+
export declare const METHODOLOGY = "# Debug Toolkit \u2014 Methodology\n\n## The Rule\nDiagnosis quality matters more than fix quality.\nA wrong diagnosis wastes 5-10 agent turns. A wrong fix wastes 1.\nInvest time understanding the error before touching the code.\n\n## The Workflow\n\n### Step 1: Investigate (ALWAYS start here)\nCall `debug_investigate` with the error text.\nYou get back: error classification, source code at the crash site,\ngit context, runtime environment, AND any past solutions for similar errors.\n\nIf past solutions are returned, check the `stale` field:\n- `stale: false` \u2192 the code hasn't changed since. Trust the diagnosis.\n- `stale: true` \u2192 the code has changed. The diagnosis may still apply but verify.\n\nIf a `rootCause` is included, it tells you exactly which file caused\nthe error last time and what was done to fix it. Start there.\n\n### Step 2: Form Hypotheses\nBased on the investigation, form 2-3 theories about the root cause.\nRank them by likelihood. The most common causes are:\n- Null/undefined access (TypeError)\n- Missing import or dependency (ReferenceError, ModuleNotFoundError)\n- Wrong API usage (check framework version in environment)\n- Stale state (recent git changes may have introduced it)\n- Environment mismatch (wrong Node version, missing env var)\n\n### Step 3: Probe (only if needed)\nIf the investigation didn't reveal the cause, use `debug_instrument`\nto add logging at the suspicious code path. Then `debug_capture` to\nsee what values flow through at runtime.\n\nTag each instrument with a hypothesis so captures are linked.\n\n### Step 4: Fix\nApply the minimal fix. Change as few lines as possible.\nIf you're changing more than 10 lines, you probably have the wrong diagnosis.\n\n### Step 5: Verify\nCall `debug_verify` with the test command. Check exit code AND error output.\nDo not trust \"it compiles\" \u2014 silent failures are the #1 problem.\n\n### Step 6: Cleanup\nCall `debug_cleanup` with:\n- `diagnosis`: one-line root cause summary\n- `rootCause`: the causal chain (trigger, errorFile, causeFile, fixDescription)\n\nThis removes all instrumentation and saves BOTH the diagnosis and the\ncausal chain to memory. Future agents can follow the chain directly.\n\n## Causal Chains\nWhen calling `debug_cleanup`, always provide a rootCause object:\n- `trigger`: what caused the error (\"missing null check\", \"wrong import path\")\n- `errorFile`: where the error appeared (the stack trace pointed here)\n- `causeFile`: where the actual bug was (may be different!)\n- `fixDescription`: what you changed (\"added null check before .map()\")\n\nThis is the most valuable data in the system. It teaches future agents\nnot just WHAT the error was, but WHY it happened and WHERE to look.\n\n## Staleness\nEvery diagnosis is tagged with the git SHA at the time it was saved.\nWhen recalled, the system checks if the referenced files have changed.\nStale diagnoses are ranked lower but still shown \u2014 many bugs recur\neven after code changes.\n\n## Patterns\nCall `debug_patterns` periodically to see:\n- **Recurring errors**: same error type in the same file (3+ times = refactor it)\n- **Hot files**: files that keep appearing in debug sessions (fragile code)\n- **Regressions**: bugs that were fixed but came back (missing test coverage)\n- **Error clusters**: multiple errors in a short time (cascading failure)\n\n## Anti-Patterns\n- DO NOT skip Step 1 and jump to fixing. You will guess wrong.\n- DO NOT instrument 10 files at once. Start with 1-2.\n- DO NOT ignore the `nextStep` field in tool responses.\n- DO NOT leave instrumentation in place after fixing.\n- DO NOT apply a fix without running `debug_verify`.\n- DO NOT skip the `rootCause` in cleanup. It's the highest-value data.\n\n## Error Pattern Shortcuts\n- `TypeError: Cannot read properties of undefined` \u2192 check the variable one level up in the call chain\n- `ECONNREFUSED` \u2192 the server/API is not running, period\n- `Cannot find module` \u2192 run npm install, then check import path\n- `ENOENT` \u2192 the file doesn't exist, check spelling and case\n- `ERR_MODULE_NOT_FOUND` \u2192 ESM issue, check file extensions and type:module\n- `401/403` \u2192 auth problem, check token/env vars\n- `500` \u2192 server-side, look at backend logs not frontend\n";
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* methodology.ts — The debugging methodology, served as an MCP resource.
|
|
3
|
+
*
|
|
4
|
+
* This is the "hot memory" tier — always available, always loaded.
|
|
5
|
+
* It teaches the agent HOW to debug, not just gives it tools.
|
|
6
|
+
*/
|
|
7
|
+
export const METHODOLOGY = `# Debug Toolkit — Methodology
|
|
8
|
+
|
|
9
|
+
## The Rule
|
|
10
|
+
Diagnosis quality matters more than fix quality.
|
|
11
|
+
A wrong diagnosis wastes 5-10 agent turns. A wrong fix wastes 1.
|
|
12
|
+
Invest time understanding the error before touching the code.
|
|
13
|
+
|
|
14
|
+
## The Workflow
|
|
15
|
+
|
|
16
|
+
### Step 1: Investigate (ALWAYS start here)
|
|
17
|
+
Call \`debug_investigate\` with the error text.
|
|
18
|
+
You get back: error classification, source code at the crash site,
|
|
19
|
+
git context, runtime environment, AND any past solutions for similar errors.
|
|
20
|
+
|
|
21
|
+
If past solutions are returned, check the \`stale\` field:
|
|
22
|
+
- \`stale: false\` → the code hasn't changed since. Trust the diagnosis.
|
|
23
|
+
- \`stale: true\` → the code has changed. The diagnosis may still apply but verify.
|
|
24
|
+
|
|
25
|
+
If a \`rootCause\` is included, it tells you exactly which file caused
|
|
26
|
+
the error last time and what was done to fix it. Start there.
|
|
27
|
+
|
|
28
|
+
### Step 2: Form Hypotheses
|
|
29
|
+
Based on the investigation, form 2-3 theories about the root cause.
|
|
30
|
+
Rank them by likelihood. The most common causes are:
|
|
31
|
+
- Null/undefined access (TypeError)
|
|
32
|
+
- Missing import or dependency (ReferenceError, ModuleNotFoundError)
|
|
33
|
+
- Wrong API usage (check framework version in environment)
|
|
34
|
+
- Stale state (recent git changes may have introduced it)
|
|
35
|
+
- Environment mismatch (wrong Node version, missing env var)
|
|
36
|
+
|
|
37
|
+
### Step 3: Probe (only if needed)
|
|
38
|
+
If the investigation didn't reveal the cause, use \`debug_instrument\`
|
|
39
|
+
to add logging at the suspicious code path. Then \`debug_capture\` to
|
|
40
|
+
see what values flow through at runtime.
|
|
41
|
+
|
|
42
|
+
Tag each instrument with a hypothesis so captures are linked.
|
|
43
|
+
|
|
44
|
+
### Step 4: Fix
|
|
45
|
+
Apply the minimal fix. Change as few lines as possible.
|
|
46
|
+
If you're changing more than 10 lines, you probably have the wrong diagnosis.
|
|
47
|
+
|
|
48
|
+
### Step 5: Verify
|
|
49
|
+
Call \`debug_verify\` with the test command. Check exit code AND error output.
|
|
50
|
+
Do not trust "it compiles" — silent failures are the #1 problem.
|
|
51
|
+
|
|
52
|
+
### Step 6: Cleanup
|
|
53
|
+
Call \`debug_cleanup\` with:
|
|
54
|
+
- \`diagnosis\`: one-line root cause summary
|
|
55
|
+
- \`rootCause\`: the causal chain (trigger, errorFile, causeFile, fixDescription)
|
|
56
|
+
|
|
57
|
+
This removes all instrumentation and saves BOTH the diagnosis and the
|
|
58
|
+
causal chain to memory. Future agents can follow the chain directly.
|
|
59
|
+
|
|
60
|
+
## Causal Chains
|
|
61
|
+
When calling \`debug_cleanup\`, always provide a rootCause object:
|
|
62
|
+
- \`trigger\`: what caused the error ("missing null check", "wrong import path")
|
|
63
|
+
- \`errorFile\`: where the error appeared (the stack trace pointed here)
|
|
64
|
+
- \`causeFile\`: where the actual bug was (may be different!)
|
|
65
|
+
- \`fixDescription\`: what you changed ("added null check before .map()")
|
|
66
|
+
|
|
67
|
+
This is the most valuable data in the system. It teaches future agents
|
|
68
|
+
not just WHAT the error was, but WHY it happened and WHERE to look.
|
|
69
|
+
|
|
70
|
+
## Staleness
|
|
71
|
+
Every diagnosis is tagged with the git SHA at the time it was saved.
|
|
72
|
+
When recalled, the system checks if the referenced files have changed.
|
|
73
|
+
Stale diagnoses are ranked lower but still shown — many bugs recur
|
|
74
|
+
even after code changes.
|
|
75
|
+
|
|
76
|
+
## Patterns
|
|
77
|
+
Call \`debug_patterns\` periodically to see:
|
|
78
|
+
- **Recurring errors**: same error type in the same file (3+ times = refactor it)
|
|
79
|
+
- **Hot files**: files that keep appearing in debug sessions (fragile code)
|
|
80
|
+
- **Regressions**: bugs that were fixed but came back (missing test coverage)
|
|
81
|
+
- **Error clusters**: multiple errors in a short time (cascading failure)
|
|
82
|
+
|
|
83
|
+
## Anti-Patterns
|
|
84
|
+
- DO NOT skip Step 1 and jump to fixing. You will guess wrong.
|
|
85
|
+
- DO NOT instrument 10 files at once. Start with 1-2.
|
|
86
|
+
- DO NOT ignore the \`nextStep\` field in tool responses.
|
|
87
|
+
- DO NOT leave instrumentation in place after fixing.
|
|
88
|
+
- DO NOT apply a fix without running \`debug_verify\`.
|
|
89
|
+
- DO NOT skip the \`rootCause\` in cleanup. It's the highest-value data.
|
|
90
|
+
|
|
91
|
+
## Error Pattern Shortcuts
|
|
92
|
+
- \`TypeError: Cannot read properties of undefined\` → check the variable one level up in the call chain
|
|
93
|
+
- \`ECONNREFUSED\` → the server/API is not running, period
|
|
94
|
+
- \`Cannot find module\` → run npm install, then check import path
|
|
95
|
+
- \`ENOENT\` → the file doesn't exist, check spelling and case
|
|
96
|
+
- \`ERR_MODULE_NOT_FOUND\` → ESM issue, check file extensions and type:module
|
|
97
|
+
- \`401/403\` → auth problem, check token/env vars
|
|
98
|
+
- \`500\` → server-side, look at backend logs not frontend
|
|
99
|
+
`;
|
|
100
|
+
//# sourceMappingURL=methodology.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methodology.js","sourceRoot":"","sources":["../src/methodology.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4F1B,CAAC"}
|
package/dist/proxy.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ProxyOptions {
|
|
2
|
+
targetPort: number;
|
|
3
|
+
listenPort: number;
|
|
4
|
+
}
|
|
5
|
+
export declare function startProxy(opts: ProxyOptions): {
|
|
6
|
+
close: () => void;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Detect the dev server port by watching child process output.
|
|
10
|
+
* Returns a promise that resolves with the port or rejects after timeout.
|
|
11
|
+
*/
|
|
12
|
+
export declare function detectPort(stdout: NodeJS.ReadableStream, timeoutMs?: number): Promise<number>;
|
package/dist/proxy.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import httpProxy from "http-proxy";
|
|
3
|
+
import { WebSocketServer } from "ws";
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import { join, dirname } from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { onBrowserEvent } from "./capture.js";
|
|
8
|
+
import { createGunzip } from "node:zlib";
|
|
9
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const INJECTED_SCRIPT_TAG = `<script src="/__debug_toolkit/injected.js"></script>`;
|
|
11
|
+
export function startProxy(opts) {
|
|
12
|
+
const { targetPort, listenPort } = opts;
|
|
13
|
+
const target = `http://127.0.0.1:${targetPort}`;
|
|
14
|
+
const proxy = httpProxy.createProxyServer({
|
|
15
|
+
target,
|
|
16
|
+
ws: true,
|
|
17
|
+
selfHandleResponse: true,
|
|
18
|
+
});
|
|
19
|
+
// Handle proxy responses: inject script into HTML
|
|
20
|
+
proxy.on("proxyRes", (proxyRes, req, res) => {
|
|
21
|
+
const contentType = proxyRes.headers["content-type"] ?? "";
|
|
22
|
+
const isHtml = contentType.includes("text/html");
|
|
23
|
+
if (!isHtml) {
|
|
24
|
+
// Pass through non-HTML responses unchanged
|
|
25
|
+
res.writeHead(proxyRes.statusCode ?? 200, proxyRes.headers);
|
|
26
|
+
proxyRes.pipe(res);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Buffer and modify HTML responses
|
|
30
|
+
const chunks = [];
|
|
31
|
+
const encoding = proxyRes.headers["content-encoding"];
|
|
32
|
+
let stream = proxyRes;
|
|
33
|
+
if (encoding === "gzip") {
|
|
34
|
+
stream = proxyRes.pipe(createGunzip());
|
|
35
|
+
}
|
|
36
|
+
stream.on("data", (chunk) => chunks.push(chunk));
|
|
37
|
+
stream.on("end", () => {
|
|
38
|
+
let body = Buffer.concat(chunks).toString("utf-8");
|
|
39
|
+
// Inject our script before </body> or at end of document
|
|
40
|
+
if (body.includes("</body>")) {
|
|
41
|
+
body = body.replace("</body>", `${INJECTED_SCRIPT_TAG}\n</body>`);
|
|
42
|
+
}
|
|
43
|
+
else if (body.includes("</html>")) {
|
|
44
|
+
body = body.replace("</html>", `${INJECTED_SCRIPT_TAG}\n</html>`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
body += `\n${INJECTED_SCRIPT_TAG}`;
|
|
48
|
+
}
|
|
49
|
+
// Send modified response without compression
|
|
50
|
+
const headers = { ...proxyRes.headers };
|
|
51
|
+
delete headers["content-encoding"];
|
|
52
|
+
delete headers["content-length"];
|
|
53
|
+
headers["content-length"] = String(Buffer.byteLength(body));
|
|
54
|
+
res.writeHead(proxyRes.statusCode ?? 200, headers);
|
|
55
|
+
res.end(body);
|
|
56
|
+
});
|
|
57
|
+
stream.on("error", () => {
|
|
58
|
+
// If decompression fails, pass through raw
|
|
59
|
+
res.writeHead(proxyRes.statusCode ?? 200, proxyRes.headers);
|
|
60
|
+
proxyRes.pipe(res);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
proxy.on("error", (err, _req, res) => {
|
|
64
|
+
if (res && "writeHead" in res) {
|
|
65
|
+
res.writeHead(502, { "Content-Type": "text/plain" });
|
|
66
|
+
res.end(`debug-toolkit proxy error: ${err.message}`);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
// HTTP server
|
|
70
|
+
const server = createServer((req, res) => {
|
|
71
|
+
// Serve our injected script
|
|
72
|
+
if (req.url === "/__debug_toolkit/injected.js") {
|
|
73
|
+
const scriptPath = join(__dirname, "injected.js");
|
|
74
|
+
try {
|
|
75
|
+
const script = readFileSync(scriptPath, "utf-8");
|
|
76
|
+
res.writeHead(200, {
|
|
77
|
+
"Content-Type": "application/javascript",
|
|
78
|
+
"Cache-Control": "no-cache",
|
|
79
|
+
});
|
|
80
|
+
res.end(script);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
res.writeHead(404);
|
|
84
|
+
res.end("injected.js not found");
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
// Proxy everything else
|
|
89
|
+
proxy.web(req, res);
|
|
90
|
+
});
|
|
91
|
+
// WebSocket handling
|
|
92
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
93
|
+
wss.on("connection", (ws) => {
|
|
94
|
+
ws.on("message", (data) => {
|
|
95
|
+
try {
|
|
96
|
+
const event = JSON.parse(data.toString());
|
|
97
|
+
onBrowserEvent(event);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// Ignore malformed messages
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
server.on("upgrade", (req, socket, head) => {
|
|
105
|
+
// Our debug WebSocket
|
|
106
|
+
if (req.url === "/__debug_toolkit/ws") {
|
|
107
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
108
|
+
wss.emit("connection", ws, req);
|
|
109
|
+
});
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Proxy all other WebSocket upgrades (e.g., HMR)
|
|
113
|
+
proxy.ws(req, socket, head);
|
|
114
|
+
});
|
|
115
|
+
// Security: bind to localhost only — never expose to network
|
|
116
|
+
server.listen(listenPort, "127.0.0.1", () => {
|
|
117
|
+
// Server started
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
close() {
|
|
121
|
+
wss.close();
|
|
122
|
+
server.close();
|
|
123
|
+
proxy.close();
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Detect the dev server port by watching child process output.
|
|
129
|
+
* Returns a promise that resolves with the port or rejects after timeout.
|
|
130
|
+
*/
|
|
131
|
+
export function detectPort(stdout, timeoutMs = 30_000) {
|
|
132
|
+
return new Promise((resolve, reject) => {
|
|
133
|
+
// Ordered from most specific to least. No greedy catch-all patterns.
|
|
134
|
+
const patterns = [
|
|
135
|
+
/https?:\/\/localhost:(\d+)/,
|
|
136
|
+
/https?:\/\/127\.0\.0\.1:(\d+)/,
|
|
137
|
+
/https?:\/\/0\.0\.0\.0:(\d+)/,
|
|
138
|
+
/https?:\/\/\[::\]:(\d+)/,
|
|
139
|
+
/listening\s+(?:on\s+)?(?:port\s+)?(\d{4,5})/i,
|
|
140
|
+
/localhost:(\d{4,5})/,
|
|
141
|
+
/127\.0\.0\.1:(\d{4,5})/,
|
|
142
|
+
];
|
|
143
|
+
const timer = setTimeout(() => {
|
|
144
|
+
cleanup();
|
|
145
|
+
reject(new Error("Could not auto-detect dev server port within timeout. Use --port to specify."));
|
|
146
|
+
}, timeoutMs);
|
|
147
|
+
function onData(chunk) {
|
|
148
|
+
const text = chunk.toString();
|
|
149
|
+
for (const pattern of patterns) {
|
|
150
|
+
const match = pattern.exec(text);
|
|
151
|
+
if (match) {
|
|
152
|
+
const port = parseInt(match[1], 10);
|
|
153
|
+
if (port >= 1024 && port <= 65535) {
|
|
154
|
+
cleanup();
|
|
155
|
+
resolve(port);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function cleanup() {
|
|
162
|
+
clearTimeout(timer);
|
|
163
|
+
stdout.removeListener("data", onData);
|
|
164
|
+
}
|
|
165
|
+
stdout.on("data", onData);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate that a file path is within the project root.
|
|
3
|
+
* Resolves symlinks and rejects paths that escape the boundary.
|
|
4
|
+
*/
|
|
5
|
+
export declare function validateFilePath(filePath: string, projectRoot: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Validate a command string for obvious injection attempts.
|
|
8
|
+
* We allow commands but reject chaining operators.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateCommand(command: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Redact sensitive information from captured text.
|
|
13
|
+
*/
|
|
14
|
+
export declare function redactSensitiveData(text: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Redact sensitive headers from captured network requests.
|
|
17
|
+
*/
|
|
18
|
+
export declare function redactHeaders(headers: Record<string, string>): Record<string, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Ensure .debug/ is in .gitignore.
|
|
21
|
+
*/
|
|
22
|
+
export declare function ensureGitignore(projectRoot: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Validate that an instrumentation expression is safe to inject.
|
|
25
|
+
* Prevents code injection via the expression parameter.
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateExpression(expression: string): string;
|