token-pilot 0.31.0 → 0.33.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 (53) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/agents/tp-api-surface-tracker.md +1 -1
  4. package/agents/tp-audit-scanner.md +1 -1
  5. package/agents/tp-commit-writer.md +1 -1
  6. package/agents/tp-context-engineer.md +1 -1
  7. package/agents/tp-dead-code-finder.md +1 -1
  8. package/agents/tp-debugger.md +1 -1
  9. package/agents/tp-dep-health.md +1 -1
  10. package/agents/tp-doc-writer.md +1 -1
  11. package/agents/tp-history-explorer.md +1 -1
  12. package/agents/tp-impact-analyzer.md +1 -1
  13. package/agents/tp-incident-timeline.md +1 -1
  14. package/agents/tp-incremental-builder.md +1 -1
  15. package/agents/tp-migration-scout.md +1 -1
  16. package/agents/tp-onboard.md +1 -1
  17. package/agents/tp-performance-profiler.md +1 -1
  18. package/agents/tp-pr-reviewer.md +1 -1
  19. package/agents/tp-refactor-planner.md +1 -1
  20. package/agents/tp-review-impact.md +1 -1
  21. package/agents/tp-run.md +1 -1
  22. package/agents/tp-session-restorer.md +1 -1
  23. package/agents/tp-ship-coordinator.md +1 -1
  24. package/agents/tp-spec-writer.md +1 -1
  25. package/agents/tp-test-coverage-gapper.md +1 -1
  26. package/agents/tp-test-triage.md +1 -1
  27. package/agents/tp-test-writer.md +1 -1
  28. package/dist/ast-index/client.js +17 -1
  29. package/dist/cli/install-agents.d.ts +18 -0
  30. package/dist/cli/install-agents.js +88 -1
  31. package/dist/cli/stats.js +9 -2
  32. package/dist/core/error-log.d.ts +86 -0
  33. package/dist/core/error-log.js +228 -0
  34. package/dist/core/event-log.d.ts +49 -1
  35. package/dist/core/event-log.js +114 -0
  36. package/dist/core/validation.d.ts +25 -9
  37. package/dist/core/validation.js +212 -136
  38. package/dist/handlers/call-tree.d.ts +35 -0
  39. package/dist/handlers/call-tree.js +70 -0
  40. package/dist/handlers/smart-log.js +7 -2
  41. package/dist/hooks/installer.d.ts +40 -0
  42. package/dist/hooks/installer.js +145 -2
  43. package/dist/hooks/pre-task.js +44 -10
  44. package/dist/hooks/safe-runner.d.ts +48 -0
  45. package/dist/hooks/safe-runner.js +73 -0
  46. package/dist/hooks/session-start.d.ts +2 -0
  47. package/dist/hooks/session-start.js +49 -0
  48. package/dist/index.d.ts +11 -0
  49. package/dist/index.js +284 -63
  50. package/dist/server/tool-definitions.d.ts +65 -0
  51. package/dist/server/tool-definitions.js +18 -0
  52. package/dist/server.js +36 -1
  53. package/package.json +1 -1
@@ -0,0 +1,228 @@
1
+ /**
2
+ * v0.34.0 — error / diagnostic channel for token-pilot hooks + CLI.
3
+ *
4
+ * Why a separate file from `hook-events.jsonl`:
5
+ * - hook-events lives in `<projectRoot>/.token-pilot/`. When the hook
6
+ * itself fails BEFORE projectRoot is resolved (B8 WSL detection,
7
+ * missing dir, ENOENT), there is nowhere to write the regular log.
8
+ * - Errors must outlive a single project — when a user reports
9
+ * "nothing logs anymore" we want one absolute path to look at.
10
+ *
11
+ * Layout:
12
+ * ~/.token-pilot/hook-errors.jsonl
13
+ *
14
+ * Format: one JSON record per line. Schema in `HookErrorRecord` below.
15
+ *
16
+ * Discipline:
17
+ * - Never throws. The error logger is itself the last line of defence —
18
+ * a throw here would defeat the wrapper that calls it.
19
+ * - Cap-and-rotate: when the file passes MAX_BYTES the writer renames
20
+ * it to `hook-errors.<ts>.jsonl` and starts fresh. Old archives
21
+ * past RETENTION_MS are pruned best-effort on each append.
22
+ * - `TOKEN_PILOT_NO_ERROR_LOG=1` opts out entirely.
23
+ *
24
+ * Privacy:
25
+ * - The `input` field is whatever the hook chose to record. Callers
26
+ * MUST sanitize before passing it in — no full paths, no file
27
+ * content, no prompts. Helpers `safeBasename()` / `safePathInfo()`
28
+ * are provided for the common cases.
29
+ */
30
+ import * as fs from "node:fs/promises";
31
+ import { existsSync } from "node:fs";
32
+ import { homedir } from "node:os";
33
+ import { basename, dirname, join, resolve } from "node:path";
34
+ // ─── constants ───────────────────────────────────────────────────────
35
+ const MAX_BYTES = 5 * 1024 * 1024; // 5 MB before rotate
36
+ const RETENTION_MS = 30 * 24 * 3600 * 1000; // 30d archive retention
37
+ const ARCHIVE_RE = /^hook-errors\.(\d+)\.jsonl$/;
38
+ const CURRENT = "hook-errors.jsonl";
39
+ // ─── path resolution ─────────────────────────────────────────────────
40
+ export function errorLogDir() {
41
+ return join(homedir(), ".token-pilot");
42
+ }
43
+ export function errorLogPath() {
44
+ return join(errorLogDir(), CURRENT);
45
+ }
46
+ // ─── env opt-out ─────────────────────────────────────────────────────
47
+ function isOptedOut() {
48
+ return process.env.TOKEN_PILOT_NO_ERROR_LOG === "1";
49
+ }
50
+ // ─── sanitizers ──────────────────────────────────────────────────────
51
+ /**
52
+ * Reduce a path to its basename. Use everywhere a path could leak:
53
+ * the user's project tree, file content, anything not strictly an
54
+ * identifier. Returns `"<empty>"` for missing input rather than null
55
+ * so the field stays shape-stable.
56
+ */
57
+ export function safeBasename(p) {
58
+ if (typeof p !== "string" || p.length === 0)
59
+ return "<empty>";
60
+ return basename(p);
61
+ }
62
+ /**
63
+ * Capture only the metadata about a path — basename + length + ext —
64
+ * dropping the absolute path entirely. Useful when the analysis
65
+ * benefits from "kind of file" without revealing where it lived.
66
+ */
67
+ export function safePathInfo(p) {
68
+ if (typeof p !== "string" || p.length === 0) {
69
+ return { name: "<empty>", ext: "" };
70
+ }
71
+ const name = basename(p);
72
+ const dot = name.lastIndexOf(".");
73
+ return {
74
+ name,
75
+ ext: dot >= 0 ? name.slice(dot).toLowerCase() : "",
76
+ };
77
+ }
78
+ // ─── error classification ────────────────────────────────────────────
79
+ /**
80
+ * Map a thrown value to a stable, searchable `code`. The classifier
81
+ * is intentionally simple — node ErrnoException codes pass through,
82
+ * everything else falls into a coarse bucket. New cases land here
83
+ * only when a pattern shows up repeatedly in the wild.
84
+ */
85
+ export function classifyError(err) {
86
+ if (err && typeof err === "object") {
87
+ const e = err;
88
+ if (typeof e.code === "string" && e.code.length > 0)
89
+ return e.code;
90
+ const name = e.name;
91
+ if (name === "SyntaxError")
92
+ return "parse_error";
93
+ if (name === "TypeError")
94
+ return "type_error";
95
+ }
96
+ if (err instanceof Error) {
97
+ const m = err.message.toLowerCase();
98
+ if (m.includes("timeout"))
99
+ return "timeout";
100
+ if (m.includes("not initialized"))
101
+ return "not_initialized";
102
+ if (m.includes("permission denied"))
103
+ return "EACCES";
104
+ }
105
+ return "unknown";
106
+ }
107
+ // ─── rotate + retention ──────────────────────────────────────────────
108
+ async function rotateIfNeeded() {
109
+ const p = errorLogPath();
110
+ try {
111
+ const stat = await fs.stat(p);
112
+ if (stat.size < MAX_BYTES)
113
+ return;
114
+ const archive = join(errorLogDir(), `hook-errors.${Date.now()}.jsonl`);
115
+ await fs.rename(p, archive);
116
+ }
117
+ catch {
118
+ /* missing or stat failure — append will create */
119
+ }
120
+ }
121
+ async function pruneArchives() {
122
+ const dir = errorLogDir();
123
+ let entries;
124
+ try {
125
+ entries = await fs.readdir(dir);
126
+ }
127
+ catch {
128
+ return;
129
+ }
130
+ const cutoff = Date.now() - RETENTION_MS;
131
+ for (const name of entries) {
132
+ const m = name.match(ARCHIVE_RE);
133
+ if (!m)
134
+ continue;
135
+ const ts = Number(m[1]);
136
+ if (!Number.isFinite(ts))
137
+ continue;
138
+ if (ts < cutoff) {
139
+ try {
140
+ await fs.unlink(join(dir, name));
141
+ }
142
+ catch {
143
+ /* best-effort */
144
+ }
145
+ }
146
+ }
147
+ }
148
+ // ─── append ──────────────────────────────────────────────────────────
149
+ export async function appendError(rec) {
150
+ if (isOptedOut())
151
+ return;
152
+ try {
153
+ await fs.mkdir(errorLogDir(), { recursive: true });
154
+ await rotateIfNeeded();
155
+ await fs.appendFile(errorLogPath(), JSON.stringify(rec) + "\n");
156
+ // best-effort retention sweep — not awaited tightly because a slow
157
+ // FS shouldn't slow the hook hot-path; failures are silent.
158
+ pruneArchives().catch(() => { });
159
+ }
160
+ catch {
161
+ /* logger of last resort — never throw */
162
+ }
163
+ }
164
+ export async function loadErrors(opts = {}) {
165
+ const p = opts.path ?? errorLogPath();
166
+ let raw;
167
+ try {
168
+ raw = await fs.readFile(p, "utf-8");
169
+ }
170
+ catch {
171
+ return [];
172
+ }
173
+ const out = [];
174
+ for (const line of raw.split("\n")) {
175
+ if (!line.trim())
176
+ continue;
177
+ try {
178
+ const rec = JSON.parse(line);
179
+ if (opts.code && rec.code !== opts.code)
180
+ continue;
181
+ if (opts.hook && rec.hook !== opts.hook)
182
+ continue;
183
+ if (opts.level && rec.level !== opts.level)
184
+ continue;
185
+ out.push(rec);
186
+ }
187
+ catch {
188
+ /* skip malformed */
189
+ }
190
+ }
191
+ // Newest first — most useful default ordering for a tail view.
192
+ out.sort((a, b) => (b.ts || 0) - (a.ts || 0));
193
+ if (opts.tail && opts.tail > 0) {
194
+ return out.slice(0, opts.tail);
195
+ }
196
+ return out;
197
+ }
198
+ // ─── format ──────────────────────────────────────────────────────────
199
+ export function formatErrorList(records) {
200
+ if (records.length === 0) {
201
+ return "No errors logged.";
202
+ }
203
+ const counts = new Map();
204
+ for (const r of records) {
205
+ counts.set(r.code, (counts.get(r.code) ?? 0) + 1);
206
+ }
207
+ const top = Array.from(counts.entries())
208
+ .sort((a, b) => b[1] - a[1])
209
+ .slice(0, 10);
210
+ const lines = [];
211
+ lines.push(`token-pilot errors — ${records.length} total`);
212
+ lines.push("");
213
+ lines.push("Top codes:");
214
+ for (const [code, n] of top) {
215
+ lines.push(` ${String(n).padStart(4)}× ${code}`);
216
+ }
217
+ lines.push("");
218
+ lines.push("Most recent:");
219
+ const recent = records.slice(0, 20);
220
+ for (const r of recent) {
221
+ const when = new Date(r.ts).toISOString().slice(11, 19);
222
+ lines.push(` [${when}] ${r.level.toUpperCase().padEnd(5)} ${r.hook} ${r.code} — ${r.msg}`);
223
+ }
224
+ return lines.join("\n");
225
+ }
226
+ // ─── exports for indirection from index.ts ───────────────────────────
227
+ export { existsSync, resolve, dirname };
228
+ //# sourceMappingURL=error-log.js.map
@@ -28,7 +28,7 @@ export interface HookEvent {
28
28
  /** null for top-level session; agent_type string inside a subagent. */
29
29
  agent_type: string | null;
30
30
  agent_id: string | null;
31
- event: "denied" | "allowed" | "bypass" | "pass-through" | "task" | string;
31
+ event: "denied" | "allowed" | "bypass" | "pass-through" | "task" | "diagnostic" | string;
32
32
  file: string;
33
33
  lines: number;
34
34
  estTokens: number;
@@ -36,6 +36,18 @@ export interface HookEvent {
36
36
  summaryTokens: number;
37
37
  /** estTokens - summaryTokens; 0 for allow/bypass. */
38
38
  savedTokens: number;
39
+ /** "info" | "warn" | "error" — severity of the diagnostic. */
40
+ level?: "info" | "warn" | "error";
41
+ /** Stable searchable identifier — e.g. `force_subagents_no_agents`. */
42
+ code?: string;
43
+ /** Optional small map of context — must be sanitised by caller. */
44
+ detail?: Record<string, unknown>;
45
+ /**
46
+ * Wall-clock duration of the hook handler that emitted this event,
47
+ * milliseconds. Always optional — only the safe-runner wrapper sets
48
+ * it, and only on the FINAL diagnostic record per hook invocation.
49
+ */
50
+ duration_ms?: number;
39
51
  /** The subagent_type Claude Code dispatched (`tp-*` or `general-purpose`…). */
40
52
  subagent_type?: string;
41
53
  /**
@@ -78,12 +90,48 @@ export declare function retentionDeletions(files: Array<{
78
90
  * here must not break hook dispatch.
79
91
  */
80
92
  export declare function appendEvent(projectRoot: string, event: HookEvent): Promise<void>;
93
+ /**
94
+ * v0.34.0 — convenience wrapper for emitting a `diagnostic` event.
95
+ *
96
+ * Diagnostics describe edge-case branches inside a normal handler
97
+ * run (matcher returned no agents, WSL path rejected, MCP arg
98
+ * coerced, etc.). They live in the project-local hook-events.jsonl
99
+ * alongside the regular events so `stats --diagnostics` can count
100
+ * them by code.
101
+ *
102
+ * If the projectRoot is not yet resolvable (the failure happened
103
+ * before detection), prefer `appendError` from `core/error-log.ts`
104
+ * — it falls back to a user-level path.
105
+ *
106
+ * Pure-ish: never throws. Same best-effort semantics as appendEvent.
107
+ */
108
+ export declare function appendDiagnostic(projectRoot: string, args: {
109
+ code: string;
110
+ level?: "info" | "warn" | "error";
111
+ detail?: Record<string, unknown>;
112
+ sessionId?: string;
113
+ agentType?: string | null;
114
+ agentId?: string | null;
115
+ durationMs?: number;
116
+ }): Promise<void>;
81
117
  /**
82
118
  * Read all events from the current log file. Malformed JSONL lines are
83
119
  * skipped silently (a corrupted line should not poison the whole
84
120
  * dataset). Returns [] if the file is missing.
85
121
  */
86
122
  export declare function loadEvents(projectRoot: string): Promise<HookEvent[]>;
123
+ /**
124
+ * v0.33.0 (B5) — load events from EVERY `.token-pilot/hook-events.jsonl`
125
+ * found at or below `repoRoot`. The hook writer resolves its own
126
+ * project root from `process.cwd()` at the moment Claude Code spawns
127
+ * us, which can land in a subdirectory of the actual repo (apps/admin,
128
+ * apps/api, packages/prisma, …). Without this, `token-pilot stats`
129
+ * sees only the top-level log and reports a fraction of the savings.
130
+ *
131
+ * Walks up to `maxDepth` levels and merges chronologically. Pure on
132
+ * filesystem read errors — missing dirs are silently skipped.
133
+ */
134
+ export declare function loadEventsTree(repoRoot: string, maxDepth?: number): Promise<HookEvent[]>;
87
135
  /**
88
136
  * Apply age + size retention. Safe to call on startup; no-op when the
89
137
  * directory does not exist.
@@ -117,6 +117,40 @@ export async function appendEvent(projectRoot, event) {
117
117
  /* silent — telemetry is best-effort */
118
118
  }
119
119
  }
120
+ /**
121
+ * v0.34.0 — convenience wrapper for emitting a `diagnostic` event.
122
+ *
123
+ * Diagnostics describe edge-case branches inside a normal handler
124
+ * run (matcher returned no agents, WSL path rejected, MCP arg
125
+ * coerced, etc.). They live in the project-local hook-events.jsonl
126
+ * alongside the regular events so `stats --diagnostics` can count
127
+ * them by code.
128
+ *
129
+ * If the projectRoot is not yet resolvable (the failure happened
130
+ * before detection), prefer `appendError` from `core/error-log.ts`
131
+ * — it falls back to a user-level path.
132
+ *
133
+ * Pure-ish: never throws. Same best-effort semantics as appendEvent.
134
+ */
135
+ export async function appendDiagnostic(projectRoot, args) {
136
+ const rec = {
137
+ ts: Date.now(),
138
+ session_id: args.sessionId ?? "diagnostic",
139
+ agent_type: args.agentType ?? null,
140
+ agent_id: args.agentId ?? null,
141
+ event: "diagnostic",
142
+ file: "",
143
+ lines: 0,
144
+ estTokens: 0,
145
+ summaryTokens: 0,
146
+ savedTokens: 0,
147
+ level: args.level ?? "info",
148
+ code: args.code,
149
+ detail: args.detail,
150
+ duration_ms: args.durationMs,
151
+ };
152
+ await appendEvent(projectRoot, rec);
153
+ }
120
154
  /**
121
155
  * Read all events from the current log file. Malformed JSONL lines are
122
156
  * skipped silently (a corrupted line should not poison the whole
@@ -143,6 +177,86 @@ export async function loadEvents(projectRoot) {
143
177
  }
144
178
  return out;
145
179
  }
180
+ /**
181
+ * v0.33.0 (B5) — load events from EVERY `.token-pilot/hook-events.jsonl`
182
+ * found at or below `repoRoot`. The hook writer resolves its own
183
+ * project root from `process.cwd()` at the moment Claude Code spawns
184
+ * us, which can land in a subdirectory of the actual repo (apps/admin,
185
+ * apps/api, packages/prisma, …). Without this, `token-pilot stats`
186
+ * sees only the top-level log and reports a fraction of the savings.
187
+ *
188
+ * Walks up to `maxDepth` levels and merges chronologically. Pure on
189
+ * filesystem read errors — missing dirs are silently skipped.
190
+ */
191
+ export async function loadEventsTree(repoRoot, maxDepth = 5) {
192
+ const PRUNE = new Set([
193
+ "node_modules",
194
+ ".git",
195
+ "dist",
196
+ "build",
197
+ ".next",
198
+ ".turbo",
199
+ ".cache",
200
+ "coverage",
201
+ ".vercel",
202
+ ".vite",
203
+ ]);
204
+ const seen = new Set();
205
+ const all = [];
206
+ async function visit(dir, depth) {
207
+ if (depth > maxDepth)
208
+ return;
209
+ let entries = [];
210
+ try {
211
+ entries = await fs.readdir(dir);
212
+ }
213
+ catch {
214
+ return;
215
+ }
216
+ if (entries.includes(".token-pilot")) {
217
+ const logPath = join(dir, ".token-pilot", CURRENT_FILE);
218
+ if (!seen.has(logPath)) {
219
+ seen.add(logPath);
220
+ try {
221
+ const raw = await fs.readFile(logPath, "utf-8");
222
+ for (const line of raw.split("\n")) {
223
+ if (!line.trim())
224
+ continue;
225
+ try {
226
+ all.push(JSON.parse(line));
227
+ }
228
+ catch {
229
+ /* skip malformed */
230
+ }
231
+ }
232
+ }
233
+ catch {
234
+ /* missing log */
235
+ }
236
+ }
237
+ }
238
+ for (const name of entries) {
239
+ if (PRUNE.has(name))
240
+ continue;
241
+ if (name.startsWith(".") && name !== ".claude")
242
+ continue;
243
+ const full = join(dir, name);
244
+ try {
245
+ const stat = await fs.stat(full);
246
+ if (stat.isDirectory()) {
247
+ await visit(full, depth + 1);
248
+ }
249
+ }
250
+ catch {
251
+ /* skip */
252
+ }
253
+ }
254
+ }
255
+ await visit(repoRoot, 0);
256
+ // Sort chronologically so per-session aggregations stay correct.
257
+ all.sort((a, b) => (a.ts || 0) - (b.ts || 0));
258
+ return all;
259
+ }
146
260
  /**
147
261
  * Enumerate all archive files (`hook-events.<ts>.jsonl`) with metadata
148
262
  * needed by `retentionDeletions`.
@@ -1,3 +1,15 @@
1
+ /**
2
+ * v0.33.0 (B9) — coerce an `unknown` argument value to an integer.
3
+ *
4
+ * MCP transports frequently round-trip numeric arguments through
5
+ * JSON or environment variables and re-emit them as strings (e.g.
6
+ * `"42"`). Accept that case and reject everything else, including
7
+ * non-finite numbers, decimals, and strings that don't parse cleanly.
8
+ *
9
+ * Returns the integer value or `null` when the input cannot be
10
+ * interpreted as one.
11
+ */
12
+ export declare function coerceIntFromAny(value: unknown): number | null;
1
13
  /**
2
14
  * Resolve a user-provided path and validate it stays within projectRoot.
3
15
  * Prevents path traversal attacks (e.g. ../../etc/passwd).
@@ -22,7 +34,7 @@ export declare function validateReadSymbolArgs(args: unknown): {
22
34
  symbol: string;
23
35
  context_before?: number;
24
36
  context_after?: number;
25
- show?: 'full' | 'head' | 'tail' | 'outline';
37
+ show?: "full" | "head" | "tail" | "outline";
26
38
  };
27
39
  /**
28
40
  * Validate read_symbols arguments (batch multi-symbol read).
@@ -32,7 +44,7 @@ export declare function validateReadSymbolsArgs(args: unknown): {
32
44
  symbols: string[];
33
45
  context_before?: number;
34
46
  context_after?: number;
35
- show?: 'full' | 'head' | 'tail' | 'outline';
47
+ show?: "full" | "head" | "tail" | "outline";
36
48
  };
37
49
  /**
38
50
  * Validate read_range arguments.
@@ -56,11 +68,11 @@ export declare function validateReadDiffArgs(args: unknown): {
56
68
  export interface FindUsagesArgs {
57
69
  symbol: string;
58
70
  scope?: string;
59
- kind?: 'definitions' | 'imports' | 'usages' | 'all';
71
+ kind?: "definitions" | "imports" | "usages" | "all";
60
72
  limit?: number;
61
73
  lang?: string;
62
74
  context_lines?: number;
63
- mode?: 'full' | 'list';
75
+ mode?: "full" | "list";
64
76
  }
65
77
  export declare function validateFindUsagesArgs(args: unknown): FindUsagesArgs;
66
78
  /**
@@ -105,8 +117,12 @@ export declare function validateFindUnusedArgs(args: unknown): {
105
117
  export_only?: boolean;
106
118
  limit?: number;
107
119
  };
120
+ export declare function validateCallTreeArgs(args: unknown): {
121
+ symbol: string;
122
+ depth?: number;
123
+ };
108
124
  export interface CodeAuditArgs {
109
- check: 'pattern' | 'todo' | 'deprecated' | 'annotations' | 'all';
125
+ check: "pattern" | "todo" | "deprecated" | "annotations" | "all";
110
126
  pattern?: string;
111
127
  name?: string;
112
128
  lang?: string;
@@ -118,7 +134,7 @@ export declare function validateCodeAuditArgs(args: unknown): CodeAuditArgs;
118
134
  * v1.1: added include filter.
119
135
  */
120
136
  export interface ProjectOverviewArgs {
121
- include?: Array<'stack' | 'ci' | 'quality' | 'architecture'>;
137
+ include?: Array<"stack" | "ci" | "quality" | "architecture">;
122
138
  }
123
139
  export declare function validateProjectOverviewArgs(args: unknown): ProjectOverviewArgs;
124
140
  /**
@@ -126,14 +142,14 @@ export declare function validateProjectOverviewArgs(args: unknown): ProjectOverv
126
142
  */
127
143
  export interface ModuleInfoArgs {
128
144
  module: string;
129
- check?: 'deps' | 'dependents' | 'api' | 'unused-deps' | 'all';
145
+ check?: "deps" | "dependents" | "api" | "unused-deps" | "all";
130
146
  }
131
147
  export declare function validateModuleInfoArgs(args: unknown): ModuleInfoArgs;
132
148
  /**
133
149
  * Validate smart_diff arguments.
134
150
  */
135
151
  export interface SmartDiffArgs {
136
- scope?: 'unstaged' | 'staged' | 'commit' | 'branch';
152
+ scope?: "unstaged" | "staged" | "commit" | "branch";
137
153
  path?: string;
138
154
  ref?: string;
139
155
  }
@@ -143,7 +159,7 @@ export declare function validateSmartDiffArgs(args: unknown): SmartDiffArgs;
143
159
  */
144
160
  export interface ExploreAreaArgs {
145
161
  path: string;
146
- include?: Array<'outline' | 'imports' | 'tests' | 'changes'>;
162
+ include?: Array<"outline" | "imports" | "tests" | "changes">;
147
163
  }
148
164
  export declare function validateExploreAreaArgs(args: unknown): ExploreAreaArgs;
149
165
  export interface SmartLogArgs {