@mcptoolshop/claude-guardian 1.1.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/HANDBOOK.md +209 -0
  3. package/LICENSE +21 -0
  4. package/README.es.md +185 -0
  5. package/README.fr.md +185 -0
  6. package/README.hi.md +184 -0
  7. package/README.it.md +184 -0
  8. package/README.ja.md +185 -0
  9. package/README.md +184 -0
  10. package/README.pt-BR.md +184 -0
  11. package/README.zh.md +185 -0
  12. package/dist/budget-store.d.ts +33 -0
  13. package/dist/budget-store.js +62 -0
  14. package/dist/budget-store.js.map +1 -0
  15. package/dist/budget.d.ts +52 -0
  16. package/dist/budget.js +136 -0
  17. package/dist/budget.js.map +1 -0
  18. package/dist/cli.d.ts +2 -0
  19. package/dist/cli.js +387 -0
  20. package/dist/cli.js.map +1 -0
  21. package/dist/defaults.d.ts +51 -0
  22. package/dist/defaults.js +67 -0
  23. package/dist/defaults.js.map +1 -0
  24. package/dist/doctor.d.ts +69 -0
  25. package/dist/doctor.js +294 -0
  26. package/dist/doctor.js.map +1 -0
  27. package/dist/errors.d.ts +21 -0
  28. package/dist/errors.js +46 -0
  29. package/dist/errors.js.map +1 -0
  30. package/dist/fs-utils.d.ts +23 -0
  31. package/dist/fs-utils.js +184 -0
  32. package/dist/fs-utils.js.map +1 -0
  33. package/dist/handle-count.d.ts +9 -0
  34. package/dist/handle-count.js +68 -0
  35. package/dist/handle-count.js.map +1 -0
  36. package/dist/incident.d.ts +33 -0
  37. package/dist/incident.js +115 -0
  38. package/dist/incident.js.map +1 -0
  39. package/dist/log-manager.d.ts +17 -0
  40. package/dist/log-manager.js +418 -0
  41. package/dist/log-manager.js.map +1 -0
  42. package/dist/mcp-server.d.ts +8 -0
  43. package/dist/mcp-server.js +503 -0
  44. package/dist/mcp-server.js.map +1 -0
  45. package/dist/process-monitor.d.ts +56 -0
  46. package/dist/process-monitor.js +214 -0
  47. package/dist/process-monitor.js.map +1 -0
  48. package/dist/recovery-plan.d.ts +22 -0
  49. package/dist/recovery-plan.js +146 -0
  50. package/dist/recovery-plan.js.map +1 -0
  51. package/dist/state.d.ts +64 -0
  52. package/dist/state.js +140 -0
  53. package/dist/state.js.map +1 -0
  54. package/dist/types.d.ts +64 -0
  55. package/dist/types.js +2 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/watch-daemon.d.ts +7 -0
  58. package/dist/watch-daemon.js +162 -0
  59. package/dist/watch-daemon.js.map +1 -0
  60. package/dist/watchdog.d.ts +30 -0
  61. package/dist/watchdog.js +225 -0
  62. package/dist/watchdog.js.map +1 -0
  63. package/package.json +50 -0
@@ -0,0 +1,67 @@
1
+ import { homedir } from 'os';
2
+ import { join } from 'path';
3
+ /** The 3 user-facing knobs with sane defaults. */
4
+ export const DEFAULT_CONFIG = {
5
+ maxProjectLogDirMB: 200,
6
+ hangNoActivitySeconds: 300,
7
+ autoRestart: false,
8
+ };
9
+ /** Hardcoded thresholds — not user-configurable in v1. */
10
+ export const THRESHOLDS = {
11
+ /** Disk free below this triggers aggressive mode. */
12
+ diskFreeWarningGB: 5,
13
+ /** Max single file size before trimming. */
14
+ maxFileMB: 25,
15
+ /** How many days of logs to retain during rotation. */
16
+ retainDays: 7,
17
+ /** Days before a session transcript is considered stale and eligible for cleanup. */
18
+ staleSessionDays: 3,
19
+ /** Tail lines to include in doctor bundle per log file. */
20
+ doctorTailLines: 500,
21
+ /** Watchdog poll interval in ms. */
22
+ watchdogPollMs: 2000,
23
+ /** Restart backoff schedule in ms. */
24
+ restartBackoffMs: [2000, 5000, 15000, 60000],
25
+ /** Max restarts before giving up. */
26
+ maxRestarts: 5,
27
+ /** Grace period after first discovering a PID — risk stays ok. */
28
+ graceWindowSeconds: 60,
29
+ /** CPU below this % counts as "low" for hang detection. */
30
+ cpuLowThreshold: 5,
31
+ /** After warn, escalate to critical after this many additional seconds. */
32
+ criticalAfterSeconds: 600,
33
+ /** Rate limit: min seconds between bundles for the same PID. */
34
+ bundleCooldownSeconds: 300,
35
+ };
36
+ /** Budget thresholds for concurrency control. */
37
+ export const BUDGET_THRESHOLDS = {
38
+ /** Maximum concurrency slots (base cap). */
39
+ baseCap: 4,
40
+ /** Cap when risk = warn. */
41
+ warnCap: 2,
42
+ /** Cap when risk = critical. */
43
+ criticalCap: 1,
44
+ /** Seconds of sustained ok before restoring base cap. */
45
+ hysteresisSeconds: 60,
46
+ };
47
+ /** Resolve the Claude projects directory. */
48
+ export function getClaudeProjectsPath() {
49
+ return join(homedir(), '.claude', 'projects');
50
+ }
51
+ /** Resolve the guardian data directory. */
52
+ export function getGuardianDataPath() {
53
+ return join(homedir(), '.claude-guardian');
54
+ }
55
+ /** Resolve the journal file path. */
56
+ export function getJournalPath() {
57
+ return join(getGuardianDataPath(), 'journal.jsonl');
58
+ }
59
+ /** Resolve the archive directory. */
60
+ export function getArchivePath() {
61
+ return join(getGuardianDataPath(), 'archive');
62
+ }
63
+ /** Resolve the budget file path. */
64
+ export function getBudgetPath() {
65
+ return join(getGuardianDataPath(), 'budget.json');
66
+ }
67
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,kDAAkD;AAClD,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,kBAAkB,EAAE,GAAG;IACvB,qBAAqB,EAAE,GAAG;IAC1B,WAAW,EAAE,KAAK;CACnB,CAAC;AAEF,0DAA0D;AAC1D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,qDAAqD;IACrD,iBAAiB,EAAE,CAAC;IAEpB,4CAA4C;IAC5C,SAAS,EAAE,EAAE;IAEb,uDAAuD;IACvD,UAAU,EAAE,CAAC;IAEb,qFAAqF;IACrF,gBAAgB,EAAE,CAAC;IAEnB,2DAA2D;IAC3D,eAAe,EAAE,GAAG;IAEpB,oCAAoC;IACpC,cAAc,EAAE,IAAI;IAEpB,sCAAsC;IACtC,gBAAgB,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;IAE5C,qCAAqC;IACrC,WAAW,EAAE,CAAC;IAEd,kEAAkE;IAClE,kBAAkB,EAAE,EAAE;IAEtB,2DAA2D;IAC3D,eAAe,EAAE,CAAC;IAElB,2EAA2E;IAC3E,oBAAoB,EAAE,GAAG;IAEzB,gEAAgE;IAChE,qBAAqB,EAAE,GAAG;CAClB,CAAC;AAEX,iDAAiD;AACjD,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,4CAA4C;IAC5C,OAAO,EAAE,CAAC;IACV,4BAA4B;IAC5B,OAAO,EAAE,CAAC;IACV,gCAAgC;IAChC,WAAW,EAAE,CAAC;IACd,yDAAyD;IACzD,iBAAiB,EAAE,EAAE;CACb,CAAC;AAEX,6CAA6C;AAC7C,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAChD,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,kBAAkB,CAAC,CAAC;AAC7C,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,mBAAmB,EAAE,EAAE,eAAe,CAAC,CAAC;AACtD,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,CAAC,mBAAmB,EAAE,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,mBAAmB,EAAE,EAAE,aAAa,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { PreflightResult } from './types.js';
2
+ import { type HandleCountResult } from './handle-count.js';
3
+ export interface DoctorBundle {
4
+ /** Path to the generated zip file. */
5
+ zipPath: string;
6
+ /** Summary data included in the bundle. */
7
+ summary: DoctorSummary;
8
+ }
9
+ export interface DoctorSummary {
10
+ timestamp: string;
11
+ system: SystemInfo;
12
+ claudeProjects: PreflightResult;
13
+ biggestFiles: Array<{
14
+ path: string;
15
+ sizeMB: number;
16
+ }>;
17
+ journalEntries: number;
18
+ recentJournal: Array<{
19
+ timestamp: string;
20
+ action: string;
21
+ detail: string;
22
+ }>;
23
+ /** Handle/FD counts for Claude processes at bundle time. */
24
+ handleCounts: HandleCountResult[];
25
+ /** Process snapshot at bundle time. */
26
+ processSnapshot: ProcessSnapshot;
27
+ /** Reconstructed timeline of events. */
28
+ timeline: TimelineEvent[];
29
+ }
30
+ /** Snapshot of running Claude processes at bundle time. */
31
+ export interface ProcessSnapshot {
32
+ timestamp: string;
33
+ processes: Array<{
34
+ pid: number;
35
+ name: string;
36
+ cpuPercent: number;
37
+ memoryMB: number;
38
+ uptimeSeconds: number;
39
+ handleCount: number | null;
40
+ }>;
41
+ activitySignals: {
42
+ logLastModifiedSecondsAgo: number;
43
+ cpuActive: boolean;
44
+ sources: string[];
45
+ };
46
+ }
47
+ /** A single event in the diagnostic timeline. */
48
+ export interface TimelineEvent {
49
+ timestamp: string;
50
+ type: 'risk_change' | 'incident_open' | 'incident_close' | 'bundle_captured' | 'fix_applied' | 'budget_change' | 'journal';
51
+ detail: string;
52
+ }
53
+ export interface SystemInfo {
54
+ platform: string;
55
+ release: string;
56
+ arch: string;
57
+ totalMemoryGB: number;
58
+ freeMemoryGB: number;
59
+ cpuModel: string;
60
+ cpuCores: number;
61
+ diskFreeGB: number;
62
+ nodeVersion: string;
63
+ }
64
+ /** Collect system information. */
65
+ export declare function collectSystemInfo(diskFreeGB: number): SystemInfo;
66
+ /** Generate a full diagnostics bundle. */
67
+ export declare function generateBundle(outputPath?: string): Promise<DoctorBundle>;
68
+ /** Format a doctor summary as a human-readable report. */
69
+ export declare function formatDoctorReport(summary: DoctorSummary): string;
package/dist/doctor.js ADDED
@@ -0,0 +1,294 @@
1
+ import { mkdir, readFile } from 'fs/promises';
2
+ import { join, basename } from 'path';
3
+ import { existsSync, createWriteStream } from 'fs';
4
+ import archiver from 'archiver';
5
+ import { homedir, platform, release, totalmem, freemem, cpus } from 'os';
6
+ import { getClaudeProjectsPath, getGuardianDataPath, THRESHOLDS } from './defaults.js';
7
+ import { listFilesRecursive, getDiskFreeGB, bytesToMB, tailFile, readJournal, pathExists, } from './fs-utils.js';
8
+ import { scanLogs } from './log-manager.js';
9
+ import { findClaudeProcesses, checkActivitySignals } from './process-monitor.js';
10
+ import { getHandleCounts } from './handle-count.js';
11
+ import { readState } from './state.js';
12
+ import { readIncidentLog } from './incident.js';
13
+ /** Collect system information. */
14
+ export function collectSystemInfo(diskFreeGB) {
15
+ const cpuInfo = cpus();
16
+ return {
17
+ platform: platform(),
18
+ release: release(),
19
+ arch: process.arch,
20
+ totalMemoryGB: Math.round((totalmem() / (1024 ** 3)) * 100) / 100,
21
+ freeMemoryGB: Math.round((freemem() / (1024 ** 3)) * 100) / 100,
22
+ cpuModel: cpuInfo[0]?.model || 'unknown',
23
+ cpuCores: cpuInfo.length,
24
+ diskFreeGB,
25
+ nodeVersion: process.version,
26
+ };
27
+ }
28
+ /** Generate a full diagnostics bundle. */
29
+ export async function generateBundle(outputPath) {
30
+ const dataDir = getGuardianDataPath();
31
+ if (!existsSync(dataDir)) {
32
+ await mkdir(dataDir, { recursive: true });
33
+ }
34
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
35
+ const zipPath = outputPath || join(dataDir, `bundle-${timestamp}.zip`);
36
+ // Collect preflight scan
37
+ const claudeProjects = await scanLogs();
38
+ // Collect system info
39
+ const diskFreeGB = await getDiskFreeGB(homedir());
40
+ const systemInfo = collectSystemInfo(diskFreeGB);
41
+ // Find biggest files
42
+ const claudePath = getClaudeProjectsPath();
43
+ const biggestFiles = [];
44
+ if (await pathExists(claudePath)) {
45
+ const allFiles = await listFilesRecursive(claudePath);
46
+ const fileSizes = [];
47
+ for (const f of allFiles) {
48
+ const { stat } = await import('fs/promises');
49
+ const s = await stat(f);
50
+ fileSizes.push({ path: f, sizeMB: bytesToMB(s.size) });
51
+ }
52
+ fileSizes.sort((a, b) => b.sizeMB - a.sizeMB);
53
+ biggestFiles.push(...fileSizes.slice(0, 20));
54
+ }
55
+ // Read journal
56
+ const journal = await readJournal();
57
+ const recentJournal = journal.slice(-50).map(e => ({
58
+ timestamp: e.timestamp,
59
+ action: e.action,
60
+ detail: e.detail,
61
+ }));
62
+ // Collect handle counts for running Claude processes
63
+ const processes = await findClaudeProcesses();
64
+ const handleCounts = processes.length > 0
65
+ ? await getHandleCounts(processes.map(p => p.pid))
66
+ : [];
67
+ // Build process snapshot
68
+ const activity = await checkActivitySignals(processes);
69
+ const processSnapshot = buildProcessSnapshot(processes, handleCounts, activity);
70
+ // Build timeline from journal + incidents
71
+ const timeline = await buildTimeline(journal, recentJournal);
72
+ const summary = {
73
+ timestamp: new Date().toISOString(),
74
+ system: systemInfo,
75
+ claudeProjects,
76
+ biggestFiles,
77
+ journalEntries: journal.length,
78
+ recentJournal,
79
+ handleCounts,
80
+ processSnapshot,
81
+ timeline,
82
+ };
83
+ // Build the zip
84
+ await createZipBundle(zipPath, summary, claudePath);
85
+ return { zipPath, summary };
86
+ }
87
+ /** Create the actual zip file with summary + log tails. */
88
+ async function createZipBundle(zipPath, summary, claudePath) {
89
+ // Ensure parent dir exists
90
+ const parentDir = join(zipPath, '..');
91
+ if (!existsSync(parentDir)) {
92
+ await mkdir(parentDir, { recursive: true });
93
+ }
94
+ return new Promise((resolve, reject) => {
95
+ const output = createWriteStream(zipPath);
96
+ const archive = archiver('zip', { zlib: { level: 9 } });
97
+ output.on('close', resolve);
98
+ archive.on('error', reject);
99
+ archive.pipe(output);
100
+ // Add summary.json
101
+ archive.append(JSON.stringify(summary, null, 2), { name: 'summary.json' });
102
+ // Add log tails (async — we queue them as promises)
103
+ const addTails = async () => {
104
+ if (await pathExists(claudePath)) {
105
+ const allFiles = await listFilesRecursive(claudePath);
106
+ // Only tail the biggest files (top 20 by path, to avoid huge bundles)
107
+ const textFiles = allFiles.filter(f => f.endsWith('.log') || f.endsWith('.jsonl') || f.endsWith('.json') || f.endsWith('.txt')).slice(0, 20);
108
+ for (const f of textFiles) {
109
+ const tail = await tailFile(f, THRESHOLDS.doctorTailLines);
110
+ if (tail.length > 0) {
111
+ // Use relative path from claude projects dir
112
+ const relPath = f.replace(claudePath, '').replace(/^[/\\]/, '');
113
+ archive.append(tail, { name: `log-tails/${relPath}` });
114
+ }
115
+ }
116
+ }
117
+ // Add journal if it exists
118
+ const journalPath = join(getGuardianDataPath(), 'journal.jsonl');
119
+ if (await pathExists(journalPath)) {
120
+ const journalContent = await readFile(journalPath, 'utf-8');
121
+ archive.append(journalContent, { name: 'journal.jsonl' });
122
+ }
123
+ // Add process snapshot
124
+ archive.append(JSON.stringify(summary.processSnapshot, null, 2), { name: 'process.json' });
125
+ // Add timeline
126
+ archive.append(JSON.stringify(summary.timeline, null, 2), { name: 'timeline.json' });
127
+ // Add filtered events (journal entries relevant to recent incidents)
128
+ const events = buildEventLines(summary.recentJournal);
129
+ if (events.length > 0) {
130
+ archive.append(events, { name: 'events.jsonl' });
131
+ }
132
+ // Add current state if available
133
+ const statePath = join(getGuardianDataPath(), 'state.json');
134
+ if (await pathExists(statePath)) {
135
+ const stateContent = await readFile(statePath, 'utf-8');
136
+ archive.append(stateContent, { name: 'state.json' });
137
+ }
138
+ // Add incidents log if available
139
+ const incidentsPath = join(getGuardianDataPath(), 'incidents.jsonl');
140
+ if (await pathExists(incidentsPath)) {
141
+ const incidentsContent = await readFile(incidentsPath, 'utf-8');
142
+ archive.append(incidentsContent, { name: 'incidents.jsonl' });
143
+ }
144
+ archive.finalize();
145
+ };
146
+ addTails().catch(reject);
147
+ });
148
+ }
149
+ /** Build a process snapshot from current processes and handle counts. */
150
+ function buildProcessSnapshot(processes, handleCounts, activity) {
151
+ const handleMap = new Map(handleCounts.map(h => [h.pid, h.count]));
152
+ return {
153
+ timestamp: new Date().toISOString(),
154
+ processes: processes.map(p => ({
155
+ pid: p.pid,
156
+ name: p.name,
157
+ cpuPercent: p.cpuPercent,
158
+ memoryMB: p.memoryMB,
159
+ uptimeSeconds: p.uptimeSeconds,
160
+ handleCount: handleMap.get(p.pid) ?? null,
161
+ })),
162
+ activitySignals: {
163
+ logLastModifiedSecondsAgo: activity.logLastModifiedSecondsAgo,
164
+ cpuActive: activity.cpuActive,
165
+ sources: activity.sources,
166
+ },
167
+ };
168
+ }
169
+ /** Build a chronological timeline from journal and incident history. */
170
+ async function buildTimeline(journal, recentJournal) {
171
+ const events = [];
172
+ // Add journal events
173
+ for (const entry of journal.slice(-100)) {
174
+ let type = 'journal';
175
+ if (entry.action === 'auto-bundle' || entry.action === 'bundle') {
176
+ type = 'bundle_captured';
177
+ }
178
+ else if (entry.action.includes('fix') || entry.action.includes('rotate') || entry.action.includes('trim')) {
179
+ type = 'fix_applied';
180
+ }
181
+ events.push({
182
+ timestamp: entry.timestamp,
183
+ type,
184
+ detail: `${entry.action}: ${entry.detail}`,
185
+ });
186
+ }
187
+ // Add incident events
188
+ const incidents = await readIncidentLog(20);
189
+ for (const inc of incidents) {
190
+ events.push({
191
+ timestamp: inc.startedAt,
192
+ type: 'incident_open',
193
+ detail: `Incident ${inc.id} opened (${inc.peakLevel}): ${inc.reason}`,
194
+ });
195
+ if (inc.closedAt) {
196
+ events.push({
197
+ timestamp: inc.closedAt,
198
+ type: 'incident_close',
199
+ detail: `Incident ${inc.id} closed`,
200
+ });
201
+ }
202
+ if (inc.bundleCaptured && inc.bundlePath) {
203
+ events.push({
204
+ timestamp: inc.startedAt, // approximate
205
+ type: 'bundle_captured',
206
+ detail: `Bundle for incident ${inc.id}: ${inc.bundlePath}`,
207
+ });
208
+ }
209
+ }
210
+ // Add current state info
211
+ const state = await readState();
212
+ if (state) {
213
+ events.push({
214
+ timestamp: state.updatedAt,
215
+ type: 'risk_change',
216
+ detail: `Current risk: ${state.hangRisk.level} | attention: ${state.attention.level}`,
217
+ });
218
+ if (state.budgetSummary && state.budgetSummary.currentCap < state.budgetSummary.baseCap) {
219
+ events.push({
220
+ timestamp: state.updatedAt,
221
+ type: 'budget_change',
222
+ detail: `Budget cap: ${state.budgetSummary.currentCap}/${state.budgetSummary.baseCap} (reduced by ${state.budgetSummary.capSetByRisk})`,
223
+ });
224
+ }
225
+ }
226
+ // Sort chronologically
227
+ events.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
228
+ return events;
229
+ }
230
+ /** Build events.jsonl content from recent journal entries. */
231
+ function buildEventLines(recentJournal) {
232
+ return recentJournal.map(e => JSON.stringify(e)).join('\n');
233
+ }
234
+ /** Format a doctor summary as a human-readable report. */
235
+ export function formatDoctorReport(summary) {
236
+ const lines = [];
237
+ lines.push('=== Claude Guardian Doctor Report ===');
238
+ lines.push(`Generated: ${summary.timestamp}`);
239
+ lines.push('');
240
+ // System
241
+ lines.push('System:');
242
+ lines.push(` Platform: ${summary.system.platform} ${summary.system.release}`);
243
+ lines.push(` Arch: ${summary.system.arch}`);
244
+ lines.push(` Memory: ${summary.system.freeMemoryGB}GB free / ${summary.system.totalMemoryGB}GB total`);
245
+ lines.push(` CPU: ${summary.system.cpuModel} (${summary.system.cpuCores} cores)`);
246
+ lines.push(` Disk free: ${Math.round(summary.system.diskFreeGB * 100) / 100}GB`);
247
+ lines.push(` Node: ${summary.system.nodeVersion}`);
248
+ lines.push('');
249
+ // Claude projects
250
+ lines.push('Claude Projects:');
251
+ lines.push(` Total size: ${summary.claudeProjects.claudeProjectsSizeMB}MB`);
252
+ lines.push(` Issues: ${summary.claudeProjects.actions.length}`);
253
+ lines.push('');
254
+ // Biggest files
255
+ if (summary.biggestFiles.length > 0) {
256
+ lines.push('Biggest files:');
257
+ for (const f of summary.biggestFiles.slice(0, 10)) {
258
+ const name = basename(f.path);
259
+ lines.push(` ${name}: ${f.sizeMB}MB`);
260
+ }
261
+ lines.push('');
262
+ }
263
+ // Process snapshot
264
+ if (summary.processSnapshot.processes.length > 0) {
265
+ lines.push('Process Snapshot:');
266
+ for (const p of summary.processSnapshot.processes) {
267
+ let line = ` PID ${p.pid} (${p.name}): CPU ${p.cpuPercent}% | RAM ${p.memoryMB}MB`;
268
+ if (p.handleCount != null) {
269
+ line += ` | handles=${p.handleCount}`;
270
+ }
271
+ lines.push(line);
272
+ }
273
+ lines.push(` Activity: log=${summary.processSnapshot.activitySignals.logLastModifiedSecondsAgo}s ago | cpu=${summary.processSnapshot.activitySignals.cpuActive ? 'active' : 'idle'}`);
274
+ lines.push('');
275
+ }
276
+ // Timeline
277
+ if (summary.timeline.length > 0) {
278
+ lines.push(`Timeline: ${summary.timeline.length} events`);
279
+ for (const event of summary.timeline.slice(-10)) {
280
+ lines.push(` [${event.timestamp}] ${event.type}: ${event.detail}`);
281
+ }
282
+ lines.push('');
283
+ }
284
+ // Journal
285
+ lines.push(`Guardian journal: ${summary.journalEntries} entries`);
286
+ if (summary.recentJournal.length > 0) {
287
+ lines.push('Recent actions:');
288
+ for (const entry of summary.recentJournal.slice(-5)) {
289
+ lines.push(` [${entry.timestamp}] ${entry.action}: ${entry.detail}`);
290
+ }
291
+ }
292
+ return lines.join('\n');
293
+ }
294
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Structured error type used across CLI + MCP.
3
+ * Every guardian error carries a machine-readable code, a human hint, and optionally the root cause.
4
+ */
5
+ /** Error codes — one per failure mode. */
6
+ export type GuardianErrorCode = 'STATE_CORRUPT' | 'STATE_WRITE_FAILED' | 'BUDGET_CORRUPT' | 'BUDGET_WRITE_FAILED' | 'BUNDLE_FAILED' | 'SCAN_FAILED' | 'FIX_FAILED' | 'PROCESS_SCAN_FAILED' | 'DISK_CHECK_FAILED' | 'UNKNOWN';
7
+ export declare class GuardianError extends Error {
8
+ /** Machine-readable error code. */
9
+ readonly code: GuardianErrorCode;
10
+ /** Human-friendly hint about what to do. */
11
+ readonly hint: string;
12
+ /** Original error (if wrapping). */
13
+ readonly cause?: Error;
14
+ constructor(code: GuardianErrorCode, message: string, hint: string, cause?: Error);
15
+ /** Format for MCP tool responses (no stack traces). */
16
+ toMcpText(): string;
17
+ /** Format for CLI output. */
18
+ toCliText(): string;
19
+ }
20
+ /** Wrap any thrown value into a GuardianError. */
21
+ export declare function wrapError(err: unknown, code: GuardianErrorCode, hint: string): GuardianError;
package/dist/errors.js ADDED
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Structured error type used across CLI + MCP.
3
+ * Every guardian error carries a machine-readable code, a human hint, and optionally the root cause.
4
+ */
5
+ export class GuardianError extends Error {
6
+ /** Machine-readable error code. */
7
+ code;
8
+ /** Human-friendly hint about what to do. */
9
+ hint;
10
+ /** Original error (if wrapping). */
11
+ cause;
12
+ constructor(code, message, hint, cause) {
13
+ super(message);
14
+ this.name = 'GuardianError';
15
+ this.code = code;
16
+ this.hint = hint;
17
+ this.cause = cause;
18
+ }
19
+ /** Format for MCP tool responses (no stack traces). */
20
+ toMcpText() {
21
+ const lines = [`Error [${this.code}]: ${this.message}`];
22
+ lines.push(`Hint: ${this.hint}`);
23
+ if (this.cause) {
24
+ lines.push(`Cause: ${this.cause.message}`);
25
+ }
26
+ return lines.join('\n');
27
+ }
28
+ /** Format for CLI output. */
29
+ toCliText() {
30
+ const lines = [`[guardian] Error: ${this.message}`];
31
+ lines.push(` Code: ${this.code}`);
32
+ lines.push(` Hint: ${this.hint}`);
33
+ if (this.cause) {
34
+ lines.push(` Cause: ${this.cause.message}`);
35
+ }
36
+ return lines.join('\n');
37
+ }
38
+ }
39
+ /** Wrap any thrown value into a GuardianError. */
40
+ export function wrapError(err, code, hint) {
41
+ if (err instanceof GuardianError)
42
+ return err;
43
+ const cause = err instanceof Error ? err : new Error(String(err));
44
+ return new GuardianError(code, cause.message, hint, cause);
45
+ }
46
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAeH,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtC,mCAAmC;IAC1B,IAAI,CAAoB;IACjC,4CAA4C;IACnC,IAAI,CAAS;IACtB,oCAAoC;IAC3B,KAAK,CAAS;IAEvB,YAAY,IAAuB,EAAE,OAAe,EAAE,IAAY,EAAE,KAAa;QAC/E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,uDAAuD;IACvD,SAAS;QACP,MAAM,KAAK,GAAG,CAAC,UAAU,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,6BAA6B;IAC7B,SAAS;QACP,MAAM,KAAK,GAAG,CAAC,qBAAqB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF;AAED,kDAAkD;AAClD,MAAM,UAAU,SAAS,CAAC,GAAY,EAAE,IAAuB,EAAE,IAAY;IAC3E,IAAI,GAAG,YAAY,aAAa;QAAE,OAAO,GAAG,CAAC;IAC7C,MAAM,KAAK,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAClE,OAAO,IAAI,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { JournalEntry } from './types.js';
2
+ /** Get size of a file in bytes. Returns 0 if file doesn't exist. */
3
+ export declare function fileSize(filePath: string): Promise<number>;
4
+ /** Get total size of a directory (recursive) in bytes. */
5
+ export declare function dirSize(dirPath: string): Promise<number>;
6
+ /** List all files in a directory recursively. */
7
+ export declare function listFilesRecursive(dirPath: string): Promise<string[]>;
8
+ /** Get disk free space in GB for the drive containing a given path. */
9
+ export declare function getDiskFreeGB(targetPath: string): Promise<number>;
10
+ /** Gzip a file in place (original → original.gz, original deleted). */
11
+ export declare function gzipFile(filePath: string): Promise<string>;
12
+ /** Read the last N lines of a file. */
13
+ export declare function tailFile(filePath: string, lines: number): Promise<string>;
14
+ /** Trim a file to its last N lines. Returns new size in bytes. */
15
+ export declare function trimFileToLines(filePath: string, keepLines: number): Promise<number>;
16
+ /** Append a journal entry. */
17
+ export declare function writeJournalEntry(entry: JournalEntry): Promise<void>;
18
+ /** Read the journal (last N entries). */
19
+ export declare function readJournal(lastN?: number): Promise<JournalEntry[]>;
20
+ /** Bytes to MB, 2 decimal places. */
21
+ export declare function bytesToMB(bytes: number): number;
22
+ /** Check if a path exists. */
23
+ export declare function pathExists(p: string): Promise<boolean>;