tend-cli 0.4.1 → 0.6.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/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import { SimpleGit } from "simple-git";
4
4
 
5
5
  //#region src/findings/finding.d.ts
6
6
  declare const TOOLS: readonly ["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"];
7
+ declare const SCOPE_EXCLUSION_REASONS: readonly ["generated", "fixtures", "tests", "out-of-scope"];
7
8
  declare const FindingSchema: z.ZodObject<{
8
9
  id: z.ZodString;
9
10
  retryId: z.ZodOptional<z.ZodString>;
@@ -33,22 +34,57 @@ declare const FindingSchema: z.ZodObject<{
33
34
  flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
34
35
  file: z.ZodString;
35
36
  line: z.ZodNumber;
37
+ range: z.ZodOptional<z.ZodObject<{
38
+ startLine: z.ZodNumber;
39
+ startCol: z.ZodNumber;
40
+ endLine: z.ZodNumber;
41
+ endCol: z.ZodNumber;
42
+ }, "strip", z.ZodTypeAny, {
43
+ startLine: number;
44
+ startCol: number;
45
+ endLine: number;
46
+ endCol: number;
47
+ }, {
48
+ startLine: number;
49
+ startCol: number;
50
+ endLine: number;
51
+ endCol: number;
52
+ }>>;
36
53
  }, "strip", z.ZodTypeAny, {
37
54
  file: string;
38
55
  line: number;
56
+ range?: {
57
+ startLine: number;
58
+ startCol: number;
59
+ endLine: number;
60
+ endCol: number;
61
+ } | undefined;
39
62
  }, {
40
63
  file: string;
41
64
  line: number;
65
+ range?: {
66
+ startLine: number;
67
+ startCol: number;
68
+ endLine: number;
69
+ endCol: number;
70
+ } | undefined;
42
71
  }>, "many">>;
43
72
  remediation: z.ZodOptional<z.ZodString>;
73
+ autofixable: z.ZodOptional<z.ZodBoolean>;
74
+ repairStrategy: z.ZodOptional<z.ZodEnum<["deterministic-eslint-fix", "deterministic-ts-organize-imports", "deterministic-package-json-cleanup", "single-file-ai-edit", "multi-file-duplicate-refactor", "generated-source-repair", "test-file-repair", "dead-code-cleanup", "unsupported"]>>;
75
+ repairStrategyReason: z.ZodOptional<z.ZodString>;
44
76
  track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
45
77
  status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
46
78
  attempts: z.ZodNumber;
47
- revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
79
+ revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error", "needs-lockfile-update"]>>;
48
80
  revertDetail: z.ZodOptional<z.ZodString>;
81
+ finalFailureClass: z.ZodOptional<z.ZodEnum<["tool-timeout", "rate-limit", "model-tool-failure", "no-edit", "no-op", "regression", "typecheck", "broke-test", "suppression", "needs-lockfile-update"]>>;
49
82
  firstSeenLoop: z.ZodNumber;
50
83
  lastSeenLoop: z.ZodNumber;
51
84
  inScope: z.ZodOptional<z.ZodBoolean>;
85
+ inReportScope: z.ZodDefault<z.ZodBoolean>;
86
+ inFixScope: z.ZodDefault<z.ZodBoolean>;
87
+ scopeExclusionReason: z.ZodOptional<z.ZodEnum<["generated", "fixtures", "tests", "out-of-scope"]>>;
52
88
  }, "strip", z.ZodTypeAny, {
53
89
  id: string;
54
90
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -68,16 +104,29 @@ declare const FindingSchema: z.ZodObject<{
68
104
  attempts: number;
69
105
  firstSeenLoop: number;
70
106
  lastSeenLoop: number;
107
+ inReportScope: boolean;
108
+ inFixScope: boolean;
71
109
  retryId?: string | undefined;
72
110
  helpUri?: string | undefined;
73
111
  flowPath?: {
74
112
  file: string;
75
113
  line: number;
114
+ range?: {
115
+ startLine: number;
116
+ startCol: number;
117
+ endLine: number;
118
+ endCol: number;
119
+ } | undefined;
76
120
  }[] | undefined;
77
121
  remediation?: string | undefined;
78
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
122
+ autofixable?: boolean | undefined;
123
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
124
+ repairStrategyReason?: string | undefined;
125
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
79
126
  revertDetail?: string | undefined;
127
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
80
128
  inScope?: boolean | undefined;
129
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
81
130
  }, {
82
131
  id: string;
83
132
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -102,15 +151,29 @@ declare const FindingSchema: z.ZodObject<{
102
151
  flowPath?: {
103
152
  file: string;
104
153
  line: number;
154
+ range?: {
155
+ startLine: number;
156
+ startCol: number;
157
+ endLine: number;
158
+ endCol: number;
159
+ } | undefined;
105
160
  }[] | undefined;
106
161
  remediation?: string | undefined;
107
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
162
+ autofixable?: boolean | undefined;
163
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
164
+ repairStrategyReason?: string | undefined;
165
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
108
166
  revertDetail?: string | undefined;
167
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
109
168
  inScope?: boolean | undefined;
169
+ inReportScope?: boolean | undefined;
170
+ inFixScope?: boolean | undefined;
171
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
110
172
  }>;
111
173
  type Finding = z.infer<typeof FindingSchema>;
112
174
  type Tool = (typeof TOOLS)[number];
113
175
  type Track = Finding["track"];
176
+ type ScopeExclusionReason = (typeof SCOPE_EXCLUSION_REASONS)[number];
114
177
  /** The components that give a finding its stable identity. */
115
178
  type FingerprintInput = {
116
179
  tool: string;
@@ -137,12 +200,81 @@ type RawFinding = {
137
200
  helpUri?: string;
138
201
  flowPath?: Finding["flowPath"];
139
202
  remediation?: string;
203
+ autofixable?: boolean;
140
204
  };
141
205
  /** Which track a tool's findings flow into. */
142
206
  declare function trackForTool(tool: Tool): Track;
143
207
  /** Turn a raw scanner record into a tracked `Finding` for the given loop. */
144
208
  declare function normalize(raw: RawFinding, loop: number): Finding;
145
209
 
210
+ //#endregion
211
+ //#region src/fixing/change-set.d.ts
212
+ type FileEdit = {
213
+ path: string;
214
+ contents: string;
215
+ };
216
+ /**
217
+ * The atomic unit of a fix: edits to one file plus (optionally) its sibling test,
218
+ * applied and reverted together. Captures each file's prior state on apply so a
219
+ * revert — even after a partial apply — restores the working tree exactly.
220
+ */
221
+ declare class ChangeSet {
222
+ private readonly edits;
223
+ /** path → original contents, or null if the file did not exist before. */
224
+ private readonly originals;
225
+ constructor(edits: FileEdit[]);
226
+ apply(): void;
227
+ revert(): void;
228
+ }
229
+
230
+ //#endregion
231
+ //#region src/session/types.d.ts
232
+ type SessionRequest = {
233
+ /** The file this session owns (plus its sibling test). */
234
+ file: string;
235
+ /** Findings to fix in this file. */
236
+ findings: Finding[];
237
+ /** The fully-rendered prompt for the AI. */
238
+ prompt: string;
239
+ };
240
+ type FailureClass = "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update";
241
+ /**
242
+ * Estimated AI cost/usage for a unit of work. `total_cost_usd` from Claude's
243
+ * stream-json `result` message is a **client-side estimate**, never authoritative
244
+ * billing — always surface it as "estimated AI cost".
245
+ */
246
+ type AiUsage = {
247
+ /** Claude's `total_cost_usd` estimate (USD). A client-side estimate, not a bill. */
248
+ estimatedCostUsd: number;
249
+ inputTokens: number;
250
+ outputTokens: number;
251
+ cacheCreationInputTokens: number;
252
+ cacheReadInputTokens: number;
253
+ /** Number of Claude sessions (result messages) observed. */
254
+ sessions: number;
255
+ };
256
+ /** Cost/token portion of usage parsed from a single stream (sessions tracked separately). */
257
+
258
+ /** A usage record with everything zeroed. */
259
+ declare const zeroUsage: () => AiUsage;
260
+ /** Sum two usage records field-by-field (used to roll usage up through the run). */
261
+ declare function addUsage(a: AiUsage, b: AiUsage): AiUsage;
262
+ type SessionResult = {
263
+ ok: true;
264
+ edits: FileEdit[];
265
+ usage?: AiUsage;
266
+ } | {
267
+ ok: false;
268
+ error: string;
269
+ rateLimited: boolean;
270
+ failureClass: Extract<FailureClass, "tool-timeout" | "rate-limit" | "model-tool-failure">;
271
+ usage?: AiUsage;
272
+ };
273
+ /** One of the two interfaces in tend: drives an AI fix session. */
274
+ interface SessionRunner {
275
+ run(request: SessionRequest): Promise<SessionResult>;
276
+ }
277
+
146
278
  //#endregion
147
279
  //#region src/findings/store.d.ts
148
280
  type RevertReason$1 = NonNullable<Finding["revertReason"]>;
@@ -166,7 +298,8 @@ declare class FindingStore {
166
298
  file?: string;
167
299
  }): Finding[];
168
300
  /** Record a failed fix attempt against a finding's fingerprint. */
169
- recordFailedAttempt(id: string, reason: RevertReason$1, detail?: string): void;
301
+ recordFailedAttempt(id: string, reason: RevertReason$1, detail?: string, failureClass?: FailureClass): void;
302
+ recordFailureWithoutAttempt(id: string, reason: RevertReason$1, detail: string | undefined, failureClass: FailureClass): void;
170
303
  /** A finding's per-issue budget is exhausted once it has used `budget` attempts. */
171
304
  isBudgetExhausted(id: string, budget: number): boolean;
172
305
  /** Serialize to a plain array — `report.json`'s findings section. */
@@ -290,24 +423,43 @@ type GateOutcome = {
290
423
  declare function runGate(checks: Check[]): Promise<GateOutcome>;
291
424
 
292
425
  //#endregion
293
- //#region src/fixing/change-set.d.ts
294
- type FileEdit = {
295
- path: string;
296
- contents: string;
426
+ //#region src/scanners/scope-policy.d.ts
427
+ type FixScopeConfig = {
428
+ include?: string[];
429
+ exclude?: string[];
430
+ includeGenerated?: boolean;
431
+ includeFixtures?: boolean;
432
+ includeTests?: boolean;
297
433
  };
298
- /**
299
- * The atomic unit of a fix: edits to one file plus (optionally) its sibling test,
300
- * applied and reverted together. Captures each file's prior state on apply so a
301
- * revert even after a partial apply restores the working tree exactly.
302
- */
303
- declare class ChangeSet {
304
- private readonly edits;
305
- /** path → original contents, or null if the file did not exist before. */
306
- private readonly originals;
307
- constructor(edits: FileEdit[]);
308
- apply(): void;
309
- revert(): void;
310
- }
434
+
435
+ //#endregion
436
+ //#region src/fixing/repair-strategy.d.ts
437
+ declare const REPAIR_STRATEGIES: readonly ["deterministic-eslint-fix", "deterministic-ts-organize-imports", "deterministic-package-json-cleanup", "single-file-ai-edit", "multi-file-duplicate-refactor", "generated-source-repair", "test-file-repair", "dead-code-cleanup", "unsupported"];
438
+ type RepairStrategy = (typeof REPAIR_STRATEGIES)[number];
439
+ type RepairStrategyReason = ScopeExclusionReason | "generated-source-not-found" | "report-only" | "deterministic-not-dispatched";
440
+ type RepairPlannerInput = {
441
+ finding: Finding;
442
+ scope?: Partial<Pick<Finding, "inFixScope" | "scopeExclusionReason" | "inReportScope" | "inScope">>;
443
+ config?: FixScopeConfig & {
444
+ eslintAutofixableRules?: string[];
445
+ };
446
+ cwd?: string;
447
+ flowPath?: Finding["flowPath"];
448
+ file?: string;
449
+ category?: Finding["category"];
450
+ rule?: string;
451
+ tool?: Finding["tool"];
452
+ };
453
+ type RepairPlan = {
454
+ finding: Finding;
455
+ strategy: RepairStrategy;
456
+ editableFiles: string[];
457
+ verificationTargets: string[];
458
+ reason?: RepairStrategyReason;
459
+ };
460
+ declare function planRepair(input: RepairPlannerInput): RepairPlan;
461
+ declare function applyRepairPlanToFinding(plan: RepairPlan): Finding;
462
+ declare function isAiDispatchStrategy(strategy: RepairStrategy): boolean;
311
463
 
312
464
  //#endregion
313
465
  //#region src/fixing/dispatch.d.ts
@@ -317,6 +469,9 @@ type WorkUnit = {
317
469
  /** Every file this worker reserves — the code file plus any sibling test. */
318
470
  files: string[];
319
471
  findings: Finding[];
472
+ strategy?: RepairStrategy;
473
+ strategies?: RepairStrategy[];
474
+ verificationTargets?: string[];
320
475
  };
321
476
  /** Whether a repo-relative path is a test file (`*.test.*` / `*.spec.*`). */
322
477
 
@@ -325,239 +480,109 @@ type WorkUnit = {
325
480
  * (a code file plus its sibling test). No two sessions ever touch the same file.
326
481
  */
327
482
  declare function planWork(findings: Finding[]): WorkUnit[];
483
+ /**
484
+ * Group planned repairs into disjoint work units. Unlike `planWork`, this honors
485
+ * planner-selected editable files, so cross-file duplicate plans reserve both clone sites.
486
+ */
487
+ declare function planWorkFromRepairs(plans: RepairPlan[]): WorkUnit[];
328
488
  /** Run each work unit through `runUnit`, capped at `concurrency` concurrent sessions. */
329
489
  declare function dispatch<T>(units: WorkUnit[], runUnit: (unit: WorkUnit) => Promise<T>, opts: {
330
490
  concurrency: number;
331
491
  }): Promise<T[]>;
332
492
 
333
493
  //#endregion
334
- //#region src/session/types.d.ts
335
- type SessionRequest = {
336
- /** The file this session owns (plus its sibling test). */
494
+ //#region src/output/events.d.ts
495
+ /** What happened to a file in the current dispatched batch. "left" = not attempted. */
496
+ type FileOutcome = "fixed" | "reverted" | "left";
497
+ type TendEvent = {
498
+ type: "snapshot";
499
+ } | {
500
+ type: "detected";
501
+ packageManager: string;
502
+ typescript: boolean;
503
+ testRunner?: string;
504
+ } | {
505
+ type: "scan-start";
506
+ loop: number;
507
+ } | {
508
+ type: "audit";
509
+ loop: number;
510
+ findings: number;
511
+ files: number;
512
+ scanned?: number;
513
+ } | {
514
+ type: "loop-start";
515
+ loop: number;
516
+ files: string[];
517
+ concurrency: number;
518
+ } | {
519
+ type: "file-start";
520
+ loop: number;
337
521
  file: string;
338
- /** Findings to fix in this file. */
339
- findings: Finding[];
340
- /** The fully-rendered prompt for the AI. */
341
- prompt: string;
522
+ rule?: string;
523
+ } | {
524
+ type: "file-result";
525
+ loop: number;
526
+ file: string;
527
+ outcome: FileOutcome;
528
+ reason?: string;
529
+ } | {
530
+ type: "loop-complete";
531
+ loop: number;
532
+ fixed: number;
533
+ } | {
534
+ type: "done";
535
+ exitStatus: number;
342
536
  };
537
+ type Listener = (event: TendEvent) => void;
538
+ /** Minimal synchronous event bus. With no listener, emit is a no-op (silent mode). */
539
+ declare class EventBus {
540
+ private readonly listeners;
541
+ on(listener: Listener): () => void;
542
+ emit(event: TendEvent): void;
543
+ }
544
+
545
+ //#endregion
546
+ //#region src/report/schema.d.ts
547
+ /** Per-scanner outcome for a run: did it run clean, get skipped, or fail (with a reason). */
548
+ declare const ScannerStatusSchema: z.ZodObject<{
549
+ tool: z.ZodEnum<["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"]>;
550
+ status: z.ZodEnum<["ran", "skipped", "failed"]>;
551
+ reason: z.ZodOptional<z.ZodString>;
552
+ }, "strip", z.ZodTypeAny, {
553
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
554
+ status: "skipped" | "ran" | "failed";
555
+ reason?: string | undefined;
556
+ }, {
557
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
558
+ status: "skipped" | "ran" | "failed";
559
+ reason?: string | undefined;
560
+ }>;
561
+ declare const BehaviorChangeSchema: z.ZodObject<{
562
+ findingId: z.ZodString;
563
+ file: z.ZodString;
564
+ note: z.ZodString;
565
+ }, "strip", z.ZodTypeAny, {
566
+ file: string;
567
+ findingId: string;
568
+ note: string;
569
+ }, {
570
+ file: string;
571
+ findingId: string;
572
+ note: string;
573
+ }>;
343
574
  /**
344
- * Estimated AI cost/usage for a unit of work. `total_cost_usd` from Claude's
345
- * stream-json `result` message is a **client-side estimate**, never authoritative
346
- * billing — always surface it as "estimated AI cost".
575
+ * Estimated AI cost/usage for a run. `estimatedCostUsd` is Claude's client-side
576
+ * `total_cost_usd` estimate never authoritative billing.
347
577
  */
348
- type AiUsage = {
349
- /** Claude's `total_cost_usd` estimate (USD). A client-side estimate, not a bill. */
350
- estimatedCostUsd: number;
351
- inputTokens: number;
352
- outputTokens: number;
353
- cacheCreationInputTokens: number;
354
- cacheReadInputTokens: number;
355
- /** Number of Claude sessions (result messages) observed. */
356
- sessions: number;
357
- };
358
- /** Cost/token portion of usage parsed from a single stream (sessions tracked separately). */
359
-
360
- /** A usage record with everything zeroed. */
361
- declare const zeroUsage: () => AiUsage;
362
- /** Sum two usage records field-by-field (used to roll usage up through the run). */
363
- declare function addUsage(a: AiUsage, b: AiUsage): AiUsage;
364
- type SessionResult = {
365
- ok: true;
366
- edits: FileEdit[];
367
- usage?: AiUsage;
368
- } | {
369
- ok: false;
370
- error: string;
371
- rateLimited: boolean;
372
- usage?: AiUsage;
373
- };
374
- /** One of the two interfaces in tend: drives an AI fix session. */
375
- interface SessionRunner {
376
- run(request: SessionRequest): Promise<SessionResult>;
377
- }
378
-
379
- //#endregion
380
- //#region src/session/claude.d.ts
381
- type ClaudeSpawn = (request: SessionRequest) => Promise<{
382
- stdout: string;
383
- exitCode: number;
384
- }>;
385
- /** Drives a real `claude -p` session and parses its stream-json into edits. */
386
- declare class ClaudeSession implements SessionRunner {
387
- private readonly deps;
388
- constructor(deps: {
389
- spawn: ClaudeSpawn;
390
- });
391
- run(request: SessionRequest): Promise<SessionResult>;
392
- }
393
-
394
- //#endregion
395
- //#region src/git/snapshot.d.ts
396
- /**
397
- * A silent restore point for the working tree, stored as a git commit object pinned by a private
398
- * ref (`refs/tend/snapshot`) — nothing committed to any branch, the editor sees no change. Backs
399
- * `tend undo` (exact restore) and `tend diff` (only the tool's edits). Reuses git's content store,
400
- * so the on-disk record is a 40-char id rather than a copy of every file.
401
- */
402
- declare class Snapshot {
403
- private readonly cwd;
404
- private readonly root;
405
- private readonly sha;
406
- private constructor();
407
- static capture(_git: SimpleGit, cwd: string): Promise<Snapshot>;
408
- /** Serialize to a tiny object for `.tend/snapshot.json` (powers `undo` across invocations). */
409
- toJSON(): {
410
- cwd: string;
411
- root: string;
412
- sha: string;
413
- };
414
- static fromJSON(data: {
415
- cwd: string;
416
- root: string;
417
- sha: string;
418
- }): Snapshot;
419
- /** Files whose contents differ from the snapshot, or that are new/deleted since it (sorted). */
420
- changedSince(_git: SimpleGit): Promise<string[]>;
421
- /** Restore a single file to its captured contents (worktree only — the user's index is untouched). */
422
- restoreFile(rel: string): Promise<void>;
423
- /** Restore the working tree exactly to the captured state (incl. deleting files created since). */
424
- restore(_git: SimpleGit): Promise<void>;
425
- }
426
-
427
- //#endregion
428
- //#region src/git/repo.d.ts
429
- /** Refuse to run outside a git repo — the snapshot/restore safety net needs it. */
430
- declare function assertGitRepo(git: SimpleGit): Promise<void>;
431
- /**
432
- * Files changed vs `HEAD`: tracked modifications/additions/renames plus untracked files,
433
- * scoped and re-based to `git`'s working directory (so a run from `apps/foo` only sees
434
- * `apps/foo`'s changes, pathed as the scanners path them).
435
- */
436
- declare function changedVsHead(git: SimpleGit): Promise<string[]>;
437
- /**
438
- * Concrete files under the given path(s) — tracked plus untracked (so newly-added files
439
- * are scoped too, mirroring `changedVsHead`). `git ls-files` reports paths relative to
440
- * `git`'s working directory and interprets the pathspecs the same way, so the result is
441
- * already in the coordinate system the scanners and `filterToChanged` expect. Expanding to
442
- * concrete files (not bare directories) matters: `filterToChanged` matches exact paths.
443
- */
444
-
445
- /** Revert a single file to its snapshot state. */
446
- declare function revertFile(snapshot: Snapshot, file: string): Promise<void>;
447
-
448
- //#endregion
449
- //#region src/detect/package-manager.d.ts
450
- type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
451
- /** Detect the package manager from the lockfile present; defaults to npm. */
452
- declare function detectPackageManager(cwd: string): PackageManager;
453
-
454
- //#endregion
455
- //#region src/config/config.d.ts
456
- declare const ConfigSchema: z.ZodObject<{
457
- maxSessions: z.ZodDefault<z.ZodNumber>;
458
- maxLoops: z.ZodDefault<z.ZodNumber>;
459
- perIssueBudget: z.ZodDefault<z.ZodNumber>;
460
- test: z.ZodOptional<z.ZodString>;
461
- teethCheck: z.ZodDefault<z.ZodBoolean>;
462
- includeTests: z.ZodDefault<z.ZodBoolean>;
463
- /** Model passed to `claude -p` for fixes — an alias (sonnet/opus/haiku) or a full model id. */
464
- model: z.ZodDefault<z.ZodString>;
465
- /** Reasoning effort for fixes; unset → claude's own default. */
466
- effort: z.ZodOptional<z.ZodEnum<["low", "medium", "high", "xhigh", "max"]>>;
467
- tools: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
468
- enabled: z.ZodDefault<z.ZodBoolean>;
469
- configPath: z.ZodOptional<z.ZodString>;
470
- }, "strip", z.ZodTypeAny, {
471
- enabled: boolean;
472
- configPath?: string | undefined;
473
- }, {
474
- enabled?: boolean | undefined;
475
- configPath?: string | undefined;
476
- }>>>;
477
- }, "strip", z.ZodTypeAny, {
478
- maxSessions: number;
479
- maxLoops: number;
480
- perIssueBudget: number;
481
- teethCheck: boolean;
482
- includeTests: boolean;
483
- model: string;
484
- tools: Record<string, {
485
- enabled: boolean;
486
- configPath?: string | undefined;
487
- }>;
488
- test?: string | undefined;
489
- effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
490
- }, {
491
- maxSessions?: number | undefined;
492
- maxLoops?: number | undefined;
493
- perIssueBudget?: number | undefined;
494
- test?: string | undefined;
495
- teethCheck?: boolean | undefined;
496
- includeTests?: boolean | undefined;
497
- model?: string | undefined;
498
- effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
499
- tools?: Record<string, {
500
- enabled?: boolean | undefined;
501
- configPath?: string | undefined;
502
- }> | undefined;
503
- }>;
504
- type TendConfig = z.infer<typeof ConfigSchema>;
505
- /** CLI flags that can override config; only defined keys take effect. */
506
- type CliOverrides = Partial<Pick<TendConfig, "maxSessions" | "maxLoops" | "perIssueBudget" | "test" | "teethCheck" | "includeTests" | "model" | "effort">>;
507
- /**
508
- * Load config via cosmiconfig (searching from `cwd`), validate with zod, and apply
509
- * zero-config defaults when no file is found. Invalid config throws a clear message.
510
- */
511
- declare function loadConfig(cwd: string): Promise<TendConfig>;
512
- /** Overlay CLI flags onto a loaded config (flags win). */
513
- declare function applyCliOverrides(config: TendConfig, overrides: CliOverrides): TendConfig;
514
-
515
- //#endregion
516
- //#region src/report/retry-id.d.ts
517
- type RetryIdGenerator = () => string;
518
-
519
- //#endregion
520
- //#region src/report/schema.d.ts
521
- /** Ensure every finding in a persisted report has a human-facing id unique to that report. */
522
- /** Per-scanner outcome for a run: did it run clean, get skipped, or fail (with a reason). */
523
- declare const ScannerStatusSchema: z.ZodObject<{
524
- tool: z.ZodEnum<["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"]>;
525
- status: z.ZodEnum<["ran", "skipped", "failed"]>;
526
- reason: z.ZodOptional<z.ZodString>;
527
- }, "strip", z.ZodTypeAny, {
528
- tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
529
- status: "skipped" | "ran" | "failed";
530
- reason?: string | undefined;
531
- }, {
532
- tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
533
- status: "skipped" | "ran" | "failed";
534
- reason?: string | undefined;
535
- }>;
536
- declare const BehaviorChangeSchema: z.ZodObject<{
537
- findingId: z.ZodString;
538
- file: z.ZodString;
539
- note: z.ZodString;
540
- }, "strip", z.ZodTypeAny, {
541
- file: string;
542
- findingId: string;
543
- note: string;
544
- }, {
545
- file: string;
546
- findingId: string;
547
- note: string;
548
- }>;
549
- /**
550
- * Estimated AI cost/usage for a run. `estimatedCostUsd` is Claude's client-side
551
- * `total_cost_usd` estimate — never authoritative billing.
552
- */
553
- declare const AiUsageSchema: z.ZodObject<{
554
- estimatedCostUsd: z.ZodNumber;
555
- inputTokens: z.ZodNumber;
556
- outputTokens: z.ZodNumber;
557
- cacheCreationInputTokens: z.ZodNumber;
558
- cacheReadInputTokens: z.ZodNumber;
559
- sessions: z.ZodNumber;
560
- }, "strip", z.ZodTypeAny, {
578
+ declare const AiUsageSchema: z.ZodObject<{
579
+ estimatedCostUsd: z.ZodNumber;
580
+ inputTokens: z.ZodNumber;
581
+ outputTokens: z.ZodNumber;
582
+ cacheCreationInputTokens: z.ZodNumber;
583
+ cacheReadInputTokens: z.ZodNumber;
584
+ sessions: z.ZodNumber;
585
+ }, "strip", z.ZodTypeAny, {
561
586
  estimatedCostUsd: number;
562
587
  inputTokens: number;
563
588
  outputTokens: number;
@@ -572,6 +597,35 @@ declare const AiUsageSchema: z.ZodObject<{
572
597
  cacheReadInputTokens: number;
573
598
  sessions: number;
574
599
  }>;
600
+ declare const RunScopeSchema: z.ZodDefault<z.ZodObject<{
601
+ type: z.ZodEnum<["all", "scoped"]>;
602
+ fileCount: z.ZodOptional<z.ZodNumber>;
603
+ }, "strip", z.ZodTypeAny, {
604
+ type: "all" | "scoped";
605
+ fileCount?: number | undefined;
606
+ }, {
607
+ type: "all" | "scoped";
608
+ fileCount?: number | undefined;
609
+ }>>;
610
+ declare const FixPolicySchema: z.ZodDefault<z.ZodObject<{
611
+ includeTests: z.ZodDefault<z.ZodBoolean>;
612
+ include: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
613
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
614
+ includeGenerated: z.ZodDefault<z.ZodBoolean>;
615
+ includeFixtures: z.ZodDefault<z.ZodBoolean>;
616
+ }, "strip", z.ZodTypeAny, {
617
+ includeTests: boolean;
618
+ include: string[];
619
+ exclude: string[];
620
+ includeGenerated: boolean;
621
+ includeFixtures: boolean;
622
+ }, {
623
+ includeTests?: boolean | undefined;
624
+ include?: string[] | undefined;
625
+ exclude?: string[] | undefined;
626
+ includeGenerated?: boolean | undefined;
627
+ includeFixtures?: boolean | undefined;
628
+ }>>;
575
629
  declare const ReportSchema: z.ZodObject<{
576
630
  findings: z.ZodArray<z.ZodObject<{
577
631
  id: z.ZodString;
@@ -602,22 +656,57 @@ declare const ReportSchema: z.ZodObject<{
602
656
  flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
603
657
  file: z.ZodString;
604
658
  line: z.ZodNumber;
659
+ range: z.ZodOptional<z.ZodObject<{
660
+ startLine: z.ZodNumber;
661
+ startCol: z.ZodNumber;
662
+ endLine: z.ZodNumber;
663
+ endCol: z.ZodNumber;
664
+ }, "strip", z.ZodTypeAny, {
665
+ startLine: number;
666
+ startCol: number;
667
+ endLine: number;
668
+ endCol: number;
669
+ }, {
670
+ startLine: number;
671
+ startCol: number;
672
+ endLine: number;
673
+ endCol: number;
674
+ }>>;
605
675
  }, "strip", z.ZodTypeAny, {
606
676
  file: string;
607
677
  line: number;
678
+ range?: {
679
+ startLine: number;
680
+ startCol: number;
681
+ endLine: number;
682
+ endCol: number;
683
+ } | undefined;
608
684
  }, {
609
685
  file: string;
610
686
  line: number;
687
+ range?: {
688
+ startLine: number;
689
+ startCol: number;
690
+ endLine: number;
691
+ endCol: number;
692
+ } | undefined;
611
693
  }>, "many">>;
612
694
  remediation: z.ZodOptional<z.ZodString>;
695
+ autofixable: z.ZodOptional<z.ZodBoolean>;
696
+ repairStrategy: z.ZodOptional<z.ZodEnum<["deterministic-eslint-fix", "deterministic-ts-organize-imports", "deterministic-package-json-cleanup", "single-file-ai-edit", "multi-file-duplicate-refactor", "generated-source-repair", "test-file-repair", "dead-code-cleanup", "unsupported"]>>;
697
+ repairStrategyReason: z.ZodOptional<z.ZodString>;
613
698
  track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
614
699
  status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
615
700
  attempts: z.ZodNumber;
616
- revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
701
+ revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error", "needs-lockfile-update"]>>;
617
702
  revertDetail: z.ZodOptional<z.ZodString>;
703
+ finalFailureClass: z.ZodOptional<z.ZodEnum<["tool-timeout", "rate-limit", "model-tool-failure", "no-edit", "no-op", "regression", "typecheck", "broke-test", "suppression", "needs-lockfile-update"]>>;
618
704
  firstSeenLoop: z.ZodNumber;
619
705
  lastSeenLoop: z.ZodNumber;
620
706
  inScope: z.ZodOptional<z.ZodBoolean>;
707
+ inReportScope: z.ZodDefault<z.ZodBoolean>;
708
+ inFixScope: z.ZodDefault<z.ZodBoolean>;
709
+ scopeExclusionReason: z.ZodOptional<z.ZodEnum<["generated", "fixtures", "tests", "out-of-scope"]>>;
621
710
  }, "strip", z.ZodTypeAny, {
622
711
  id: string;
623
712
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -637,16 +726,29 @@ declare const ReportSchema: z.ZodObject<{
637
726
  attempts: number;
638
727
  firstSeenLoop: number;
639
728
  lastSeenLoop: number;
729
+ inReportScope: boolean;
730
+ inFixScope: boolean;
640
731
  retryId?: string | undefined;
641
732
  helpUri?: string | undefined;
642
733
  flowPath?: {
643
734
  file: string;
644
735
  line: number;
736
+ range?: {
737
+ startLine: number;
738
+ startCol: number;
739
+ endLine: number;
740
+ endCol: number;
741
+ } | undefined;
645
742
  }[] | undefined;
646
743
  remediation?: string | undefined;
647
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
744
+ autofixable?: boolean | undefined;
745
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
746
+ repairStrategyReason?: string | undefined;
747
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
648
748
  revertDetail?: string | undefined;
749
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
649
750
  inScope?: boolean | undefined;
751
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
650
752
  }, {
651
753
  id: string;
652
754
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -671,11 +773,24 @@ declare const ReportSchema: z.ZodObject<{
671
773
  flowPath?: {
672
774
  file: string;
673
775
  line: number;
776
+ range?: {
777
+ startLine: number;
778
+ startCol: number;
779
+ endLine: number;
780
+ endCol: number;
781
+ } | undefined;
674
782
  }[] | undefined;
675
783
  remediation?: string | undefined;
676
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
784
+ autofixable?: boolean | undefined;
785
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
786
+ repairStrategyReason?: string | undefined;
787
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
677
788
  revertDetail?: string | undefined;
789
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
678
790
  inScope?: boolean | undefined;
791
+ inReportScope?: boolean | undefined;
792
+ inFixScope?: boolean | undefined;
793
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
679
794
  }>, "many">;
680
795
  secrets: z.ZodArray<z.ZodObject<{
681
796
  id: z.ZodString;
@@ -706,22 +821,57 @@ declare const ReportSchema: z.ZodObject<{
706
821
  flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
707
822
  file: z.ZodString;
708
823
  line: z.ZodNumber;
824
+ range: z.ZodOptional<z.ZodObject<{
825
+ startLine: z.ZodNumber;
826
+ startCol: z.ZodNumber;
827
+ endLine: z.ZodNumber;
828
+ endCol: z.ZodNumber;
829
+ }, "strip", z.ZodTypeAny, {
830
+ startLine: number;
831
+ startCol: number;
832
+ endLine: number;
833
+ endCol: number;
834
+ }, {
835
+ startLine: number;
836
+ startCol: number;
837
+ endLine: number;
838
+ endCol: number;
839
+ }>>;
709
840
  }, "strip", z.ZodTypeAny, {
710
841
  file: string;
711
842
  line: number;
843
+ range?: {
844
+ startLine: number;
845
+ startCol: number;
846
+ endLine: number;
847
+ endCol: number;
848
+ } | undefined;
712
849
  }, {
713
850
  file: string;
714
851
  line: number;
852
+ range?: {
853
+ startLine: number;
854
+ startCol: number;
855
+ endLine: number;
856
+ endCol: number;
857
+ } | undefined;
715
858
  }>, "many">>;
716
859
  remediation: z.ZodOptional<z.ZodString>;
860
+ autofixable: z.ZodOptional<z.ZodBoolean>;
861
+ repairStrategy: z.ZodOptional<z.ZodEnum<["deterministic-eslint-fix", "deterministic-ts-organize-imports", "deterministic-package-json-cleanup", "single-file-ai-edit", "multi-file-duplicate-refactor", "generated-source-repair", "test-file-repair", "dead-code-cleanup", "unsupported"]>>;
862
+ repairStrategyReason: z.ZodOptional<z.ZodString>;
717
863
  track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
718
864
  status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
719
865
  attempts: z.ZodNumber;
720
- revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error"]>>;
866
+ revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error", "needs-lockfile-update"]>>;
721
867
  revertDetail: z.ZodOptional<z.ZodString>;
868
+ finalFailureClass: z.ZodOptional<z.ZodEnum<["tool-timeout", "rate-limit", "model-tool-failure", "no-edit", "no-op", "regression", "typecheck", "broke-test", "suppression", "needs-lockfile-update"]>>;
722
869
  firstSeenLoop: z.ZodNumber;
723
870
  lastSeenLoop: z.ZodNumber;
724
871
  inScope: z.ZodOptional<z.ZodBoolean>;
872
+ inReportScope: z.ZodDefault<z.ZodBoolean>;
873
+ inFixScope: z.ZodDefault<z.ZodBoolean>;
874
+ scopeExclusionReason: z.ZodOptional<z.ZodEnum<["generated", "fixtures", "tests", "out-of-scope"]>>;
725
875
  }, "strip", z.ZodTypeAny, {
726
876
  id: string;
727
877
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -741,16 +891,29 @@ declare const ReportSchema: z.ZodObject<{
741
891
  attempts: number;
742
892
  firstSeenLoop: number;
743
893
  lastSeenLoop: number;
894
+ inReportScope: boolean;
895
+ inFixScope: boolean;
744
896
  retryId?: string | undefined;
745
897
  helpUri?: string | undefined;
746
898
  flowPath?: {
747
899
  file: string;
748
900
  line: number;
901
+ range?: {
902
+ startLine: number;
903
+ startCol: number;
904
+ endLine: number;
905
+ endCol: number;
906
+ } | undefined;
749
907
  }[] | undefined;
750
908
  remediation?: string | undefined;
751
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
909
+ autofixable?: boolean | undefined;
910
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
911
+ repairStrategyReason?: string | undefined;
912
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
752
913
  revertDetail?: string | undefined;
914
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
753
915
  inScope?: boolean | undefined;
916
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
754
917
  }, {
755
918
  id: string;
756
919
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -775,48 +938,255 @@ declare const ReportSchema: z.ZodObject<{
775
938
  flowPath?: {
776
939
  file: string;
777
940
  line: number;
941
+ range?: {
942
+ startLine: number;
943
+ startCol: number;
944
+ endLine: number;
945
+ endCol: number;
946
+ } | undefined;
778
947
  }[] | undefined;
779
948
  remediation?: string | undefined;
780
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
949
+ autofixable?: boolean | undefined;
950
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
951
+ repairStrategyReason?: string | undefined;
952
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
781
953
  revertDetail?: string | undefined;
954
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
782
955
  inScope?: boolean | undefined;
956
+ inReportScope?: boolean | undefined;
957
+ inFixScope?: boolean | undefined;
958
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
783
959
  }>, "many">;
784
- depBumps: z.ZodArray<z.ZodObject<{
785
- findingId: z.ZodString;
786
- remediation: z.ZodString;
787
- }, "strip", z.ZodTypeAny, {
788
- remediation: string;
789
- findingId: string;
790
- }, {
791
- remediation: string;
792
- findingId: string;
793
- }>, "many">;
794
- flaggedBehaviorChanges: z.ZodArray<z.ZodObject<{
795
- findingId: z.ZodString;
796
- file: z.ZodString;
797
- note: z.ZodString;
798
- }, "strip", z.ZodTypeAny, {
799
- file: string;
800
- findingId: string;
801
- note: string;
802
- }, {
803
- file: string;
804
- findingId: string;
805
- note: string;
806
- }>, "many">;
807
- scannerStatuses: z.ZodDefault<z.ZodArray<z.ZodObject<{
960
+ reportOnly: z.ZodDefault<z.ZodArray<z.ZodObject<{
961
+ id: z.ZodString;
962
+ retryId: z.ZodOptional<z.ZodString>;
808
963
  tool: z.ZodEnum<["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"]>;
809
- status: z.ZodEnum<["ran", "skipped", "failed"]>;
810
- reason: z.ZodOptional<z.ZodString>;
964
+ rule: z.ZodString;
965
+ category: z.ZodEnum<["bug", "smell", "dead-code", "duplication", "security", "secret", "vuln-dep"]>;
966
+ severity: z.ZodEnum<["error", "warning", "info"]>;
967
+ file: z.ZodString;
968
+ range: z.ZodObject<{
969
+ startLine: z.ZodNumber;
970
+ startCol: z.ZodNumber;
971
+ endLine: z.ZodNumber;
972
+ endCol: z.ZodNumber;
973
+ }, "strip", z.ZodTypeAny, {
974
+ startLine: number;
975
+ startCol: number;
976
+ endLine: number;
977
+ endCol: number;
978
+ }, {
979
+ startLine: number;
980
+ startCol: number;
981
+ endLine: number;
982
+ endCol: number;
983
+ }>;
984
+ message: z.ZodString;
985
+ helpUri: z.ZodOptional<z.ZodString>;
986
+ flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
987
+ file: z.ZodString;
988
+ line: z.ZodNumber;
989
+ range: z.ZodOptional<z.ZodObject<{
990
+ startLine: z.ZodNumber;
991
+ startCol: z.ZodNumber;
992
+ endLine: z.ZodNumber;
993
+ endCol: z.ZodNumber;
994
+ }, "strip", z.ZodTypeAny, {
995
+ startLine: number;
996
+ startCol: number;
997
+ endLine: number;
998
+ endCol: number;
999
+ }, {
1000
+ startLine: number;
1001
+ startCol: number;
1002
+ endLine: number;
1003
+ endCol: number;
1004
+ }>>;
1005
+ }, "strip", z.ZodTypeAny, {
1006
+ file: string;
1007
+ line: number;
1008
+ range?: {
1009
+ startLine: number;
1010
+ startCol: number;
1011
+ endLine: number;
1012
+ endCol: number;
1013
+ } | undefined;
1014
+ }, {
1015
+ file: string;
1016
+ line: number;
1017
+ range?: {
1018
+ startLine: number;
1019
+ startCol: number;
1020
+ endLine: number;
1021
+ endCol: number;
1022
+ } | undefined;
1023
+ }>, "many">>;
1024
+ remediation: z.ZodOptional<z.ZodString>;
1025
+ autofixable: z.ZodOptional<z.ZodBoolean>;
1026
+ repairStrategy: z.ZodOptional<z.ZodEnum<["deterministic-eslint-fix", "deterministic-ts-organize-imports", "deterministic-package-json-cleanup", "single-file-ai-edit", "multi-file-duplicate-refactor", "generated-source-repair", "test-file-repair", "dead-code-cleanup", "unsupported"]>>;
1027
+ repairStrategyReason: z.ZodOptional<z.ZodString>;
1028
+ track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
1029
+ status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
1030
+ attempts: z.ZodNumber;
1031
+ revertReason: z.ZodOptional<z.ZodEnum<["broke-test", "suppression", "regression", "typecheck", "session-error", "needs-lockfile-update"]>>;
1032
+ revertDetail: z.ZodOptional<z.ZodString>;
1033
+ finalFailureClass: z.ZodOptional<z.ZodEnum<["tool-timeout", "rate-limit", "model-tool-failure", "no-edit", "no-op", "regression", "typecheck", "broke-test", "suppression", "needs-lockfile-update"]>>;
1034
+ firstSeenLoop: z.ZodNumber;
1035
+ lastSeenLoop: z.ZodNumber;
1036
+ inScope: z.ZodOptional<z.ZodBoolean>;
1037
+ inReportScope: z.ZodDefault<z.ZodBoolean>;
1038
+ inFixScope: z.ZodDefault<z.ZodBoolean>;
1039
+ scopeExclusionReason: z.ZodOptional<z.ZodEnum<["generated", "fixtures", "tests", "out-of-scope"]>>;
811
1040
  }, "strip", z.ZodTypeAny, {
1041
+ id: string;
812
1042
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
813
- status: "skipped" | "ran" | "failed";
814
- reason?: string | undefined;
1043
+ status: "pending" | "fixing" | "fixed" | "reverted" | "unfixable" | "skipped";
1044
+ message: string;
1045
+ rule: string;
1046
+ category: "bug" | "smell" | "dead-code" | "duplication" | "security" | "secret" | "vuln-dep";
1047
+ severity: "error" | "warning" | "info";
1048
+ file: string;
1049
+ range: {
1050
+ startLine: number;
1051
+ startCol: number;
1052
+ endLine: number;
1053
+ endCol: number;
1054
+ };
1055
+ track: "ai-fix" | "deterministic" | "report-only";
1056
+ attempts: number;
1057
+ firstSeenLoop: number;
1058
+ lastSeenLoop: number;
1059
+ inReportScope: boolean;
1060
+ inFixScope: boolean;
1061
+ retryId?: string | undefined;
1062
+ helpUri?: string | undefined;
1063
+ flowPath?: {
1064
+ file: string;
1065
+ line: number;
1066
+ range?: {
1067
+ startLine: number;
1068
+ startCol: number;
1069
+ endLine: number;
1070
+ endCol: number;
1071
+ } | undefined;
1072
+ }[] | undefined;
1073
+ remediation?: string | undefined;
1074
+ autofixable?: boolean | undefined;
1075
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1076
+ repairStrategyReason?: string | undefined;
1077
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
1078
+ revertDetail?: string | undefined;
1079
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
1080
+ inScope?: boolean | undefined;
1081
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1082
+ }, {
1083
+ id: string;
1084
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1085
+ status: "pending" | "fixing" | "fixed" | "reverted" | "unfixable" | "skipped";
1086
+ message: string;
1087
+ rule: string;
1088
+ category: "bug" | "smell" | "dead-code" | "duplication" | "security" | "secret" | "vuln-dep";
1089
+ severity: "error" | "warning" | "info";
1090
+ file: string;
1091
+ range: {
1092
+ startLine: number;
1093
+ startCol: number;
1094
+ endLine: number;
1095
+ endCol: number;
1096
+ };
1097
+ track: "ai-fix" | "deterministic" | "report-only";
1098
+ attempts: number;
1099
+ firstSeenLoop: number;
1100
+ lastSeenLoop: number;
1101
+ retryId?: string | undefined;
1102
+ helpUri?: string | undefined;
1103
+ flowPath?: {
1104
+ file: string;
1105
+ line: number;
1106
+ range?: {
1107
+ startLine: number;
1108
+ startCol: number;
1109
+ endLine: number;
1110
+ endCol: number;
1111
+ } | undefined;
1112
+ }[] | undefined;
1113
+ remediation?: string | undefined;
1114
+ autofixable?: boolean | undefined;
1115
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1116
+ repairStrategyReason?: string | undefined;
1117
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
1118
+ revertDetail?: string | undefined;
1119
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
1120
+ inScope?: boolean | undefined;
1121
+ inReportScope?: boolean | undefined;
1122
+ inFixScope?: boolean | undefined;
1123
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1124
+ }>, "many">>;
1125
+ depBumps: z.ZodArray<z.ZodObject<{
1126
+ findingId: z.ZodString;
1127
+ remediation: z.ZodString;
1128
+ }, "strip", z.ZodTypeAny, {
1129
+ remediation: string;
1130
+ findingId: string;
1131
+ }, {
1132
+ remediation: string;
1133
+ findingId: string;
1134
+ }>, "many">;
1135
+ flaggedBehaviorChanges: z.ZodArray<z.ZodObject<{
1136
+ findingId: z.ZodString;
1137
+ file: z.ZodString;
1138
+ note: z.ZodString;
1139
+ }, "strip", z.ZodTypeAny, {
1140
+ file: string;
1141
+ findingId: string;
1142
+ note: string;
1143
+ }, {
1144
+ file: string;
1145
+ findingId: string;
1146
+ note: string;
1147
+ }>, "many">;
1148
+ scannerStatuses: z.ZodDefault<z.ZodArray<z.ZodObject<{
1149
+ tool: z.ZodEnum<["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"]>;
1150
+ status: z.ZodEnum<["ran", "skipped", "failed"]>;
1151
+ reason: z.ZodOptional<z.ZodString>;
1152
+ }, "strip", z.ZodTypeAny, {
1153
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1154
+ status: "skipped" | "ran" | "failed";
1155
+ reason?: string | undefined;
815
1156
  }, {
816
1157
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
817
1158
  status: "skipped" | "ran" | "failed";
818
1159
  reason?: string | undefined;
819
1160
  }>, "many">>;
1161
+ runScope: z.ZodDefault<z.ZodObject<{
1162
+ type: z.ZodEnum<["all", "scoped"]>;
1163
+ fileCount: z.ZodOptional<z.ZodNumber>;
1164
+ }, "strip", z.ZodTypeAny, {
1165
+ type: "all" | "scoped";
1166
+ fileCount?: number | undefined;
1167
+ }, {
1168
+ type: "all" | "scoped";
1169
+ fileCount?: number | undefined;
1170
+ }>>;
1171
+ fixPolicy: z.ZodDefault<z.ZodObject<{
1172
+ includeTests: z.ZodDefault<z.ZodBoolean>;
1173
+ include: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1174
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1175
+ includeGenerated: z.ZodDefault<z.ZodBoolean>;
1176
+ includeFixtures: z.ZodDefault<z.ZodBoolean>;
1177
+ }, "strip", z.ZodTypeAny, {
1178
+ includeTests: boolean;
1179
+ include: string[];
1180
+ exclude: string[];
1181
+ includeGenerated: boolean;
1182
+ includeFixtures: boolean;
1183
+ }, {
1184
+ includeTests?: boolean | undefined;
1185
+ include?: string[] | undefined;
1186
+ exclude?: string[] | undefined;
1187
+ includeGenerated?: boolean | undefined;
1188
+ includeFixtures?: boolean | undefined;
1189
+ }>>;
820
1190
  aiUsage: z.ZodDefault<z.ZodObject<{
821
1191
  estimatedCostUsd: z.ZodNumber;
822
1192
  inputTokens: z.ZodNumber;
@@ -839,6 +1209,35 @@ declare const ReportSchema: z.ZodObject<{
839
1209
  cacheReadInputTokens: number;
840
1210
  sessions: number;
841
1211
  }>>;
1212
+ failureSummary: z.ZodDefault<z.ZodObject<{
1213
+ blockingSecrets: z.ZodNumber;
1214
+ unresolvedEligible: z.ZodNumber;
1215
+ toolFailures: z.ZodNumber;
1216
+ failedDeterministic: z.ZodNumber;
1217
+ sessionErrors: z.ZodNumber;
1218
+ regressions: z.ZodNumber;
1219
+ typecheckFailures: z.ZodNumber;
1220
+ testFailures: z.ZodNumber;
1221
+ }, "strip", z.ZodTypeAny, {
1222
+ blockingSecrets: number;
1223
+ unresolvedEligible: number;
1224
+ toolFailures: number;
1225
+ failedDeterministic: number;
1226
+ sessionErrors: number;
1227
+ regressions: number;
1228
+ typecheckFailures: number;
1229
+ testFailures: number;
1230
+ }, {
1231
+ blockingSecrets: number;
1232
+ unresolvedEligible: number;
1233
+ toolFailures: number;
1234
+ failedDeterministic: number;
1235
+ sessionErrors: number;
1236
+ regressions: number;
1237
+ typecheckFailures: number;
1238
+ testFailures: number;
1239
+ }>>;
1240
+ unresolvedEligibleCount: z.ZodDefault<z.ZodNumber>;
842
1241
  loops: z.ZodNumber;
843
1242
  durationMs: z.ZodNumber;
844
1243
  exitStatus: z.ZodNumber;
@@ -862,16 +1261,29 @@ declare const ReportSchema: z.ZodObject<{
862
1261
  attempts: number;
863
1262
  firstSeenLoop: number;
864
1263
  lastSeenLoop: number;
1264
+ inReportScope: boolean;
1265
+ inFixScope: boolean;
865
1266
  retryId?: string | undefined;
866
1267
  helpUri?: string | undefined;
867
1268
  flowPath?: {
868
1269
  file: string;
869
1270
  line: number;
1271
+ range?: {
1272
+ startLine: number;
1273
+ startCol: number;
1274
+ endLine: number;
1275
+ endCol: number;
1276
+ } | undefined;
870
1277
  }[] | undefined;
871
1278
  remediation?: string | undefined;
872
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
1279
+ autofixable?: boolean | undefined;
1280
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1281
+ repairStrategyReason?: string | undefined;
1282
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
873
1283
  revertDetail?: string | undefined;
1284
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
874
1285
  inScope?: boolean | undefined;
1286
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
875
1287
  }[];
876
1288
  secrets: {
877
1289
  id: string;
@@ -892,16 +1304,72 @@ declare const ReportSchema: z.ZodObject<{
892
1304
  attempts: number;
893
1305
  firstSeenLoop: number;
894
1306
  lastSeenLoop: number;
1307
+ inReportScope: boolean;
1308
+ inFixScope: boolean;
895
1309
  retryId?: string | undefined;
896
1310
  helpUri?: string | undefined;
897
1311
  flowPath?: {
898
1312
  file: string;
899
1313
  line: number;
1314
+ range?: {
1315
+ startLine: number;
1316
+ startCol: number;
1317
+ endLine: number;
1318
+ endCol: number;
1319
+ } | undefined;
900
1320
  }[] | undefined;
901
1321
  remediation?: string | undefined;
902
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
1322
+ autofixable?: boolean | undefined;
1323
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1324
+ repairStrategyReason?: string | undefined;
1325
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
903
1326
  revertDetail?: string | undefined;
1327
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
904
1328
  inScope?: boolean | undefined;
1329
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1330
+ }[];
1331
+ reportOnly: {
1332
+ id: string;
1333
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1334
+ status: "pending" | "fixing" | "fixed" | "reverted" | "unfixable" | "skipped";
1335
+ message: string;
1336
+ rule: string;
1337
+ category: "bug" | "smell" | "dead-code" | "duplication" | "security" | "secret" | "vuln-dep";
1338
+ severity: "error" | "warning" | "info";
1339
+ file: string;
1340
+ range: {
1341
+ startLine: number;
1342
+ startCol: number;
1343
+ endLine: number;
1344
+ endCol: number;
1345
+ };
1346
+ track: "ai-fix" | "deterministic" | "report-only";
1347
+ attempts: number;
1348
+ firstSeenLoop: number;
1349
+ lastSeenLoop: number;
1350
+ inReportScope: boolean;
1351
+ inFixScope: boolean;
1352
+ retryId?: string | undefined;
1353
+ helpUri?: string | undefined;
1354
+ flowPath?: {
1355
+ file: string;
1356
+ line: number;
1357
+ range?: {
1358
+ startLine: number;
1359
+ startCol: number;
1360
+ endLine: number;
1361
+ endCol: number;
1362
+ } | undefined;
1363
+ }[] | undefined;
1364
+ remediation?: string | undefined;
1365
+ autofixable?: boolean | undefined;
1366
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1367
+ repairStrategyReason?: string | undefined;
1368
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
1369
+ revertDetail?: string | undefined;
1370
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
1371
+ inScope?: boolean | undefined;
1372
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
905
1373
  }[];
906
1374
  depBumps: {
907
1375
  remediation: string;
@@ -917,6 +1385,17 @@ declare const ReportSchema: z.ZodObject<{
917
1385
  status: "skipped" | "ran" | "failed";
918
1386
  reason?: string | undefined;
919
1387
  }[];
1388
+ runScope: {
1389
+ type: "all" | "scoped";
1390
+ fileCount?: number | undefined;
1391
+ };
1392
+ fixPolicy: {
1393
+ includeTests: boolean;
1394
+ include: string[];
1395
+ exclude: string[];
1396
+ includeGenerated: boolean;
1397
+ includeFixtures: boolean;
1398
+ };
920
1399
  aiUsage: {
921
1400
  estimatedCostUsd: number;
922
1401
  inputTokens: number;
@@ -925,6 +1404,17 @@ declare const ReportSchema: z.ZodObject<{
925
1404
  cacheReadInputTokens: number;
926
1405
  sessions: number;
927
1406
  };
1407
+ failureSummary: {
1408
+ blockingSecrets: number;
1409
+ unresolvedEligible: number;
1410
+ toolFailures: number;
1411
+ failedDeterministic: number;
1412
+ sessionErrors: number;
1413
+ regressions: number;
1414
+ typecheckFailures: number;
1415
+ testFailures: number;
1416
+ };
1417
+ unresolvedEligibleCount: number;
928
1418
  loops: number;
929
1419
  durationMs: number;
930
1420
  exitStatus: number;
@@ -953,11 +1443,24 @@ declare const ReportSchema: z.ZodObject<{
953
1443
  flowPath?: {
954
1444
  file: string;
955
1445
  line: number;
1446
+ range?: {
1447
+ startLine: number;
1448
+ startCol: number;
1449
+ endLine: number;
1450
+ endCol: number;
1451
+ } | undefined;
956
1452
  }[] | undefined;
957
1453
  remediation?: string | undefined;
958
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
1454
+ autofixable?: boolean | undefined;
1455
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1456
+ repairStrategyReason?: string | undefined;
1457
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
959
1458
  revertDetail?: string | undefined;
1459
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
960
1460
  inScope?: boolean | undefined;
1461
+ inReportScope?: boolean | undefined;
1462
+ inFixScope?: boolean | undefined;
1463
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
961
1464
  }[];
962
1465
  secrets: {
963
1466
  id: string;
@@ -983,11 +1486,24 @@ declare const ReportSchema: z.ZodObject<{
983
1486
  flowPath?: {
984
1487
  file: string;
985
1488
  line: number;
1489
+ range?: {
1490
+ startLine: number;
1491
+ startCol: number;
1492
+ endLine: number;
1493
+ endCol: number;
1494
+ } | undefined;
986
1495
  }[] | undefined;
987
1496
  remediation?: string | undefined;
988
- revertReason?: "broke-test" | "suppression" | "regression" | "typecheck" | "session-error" | undefined;
1497
+ autofixable?: boolean | undefined;
1498
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1499
+ repairStrategyReason?: string | undefined;
1500
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
989
1501
  revertDetail?: string | undefined;
1502
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
990
1503
  inScope?: boolean | undefined;
1504
+ inReportScope?: boolean | undefined;
1505
+ inFixScope?: boolean | undefined;
1506
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
991
1507
  }[];
992
1508
  depBumps: {
993
1509
  remediation: string;
@@ -1001,11 +1517,65 @@ declare const ReportSchema: z.ZodObject<{
1001
1517
  loops: number;
1002
1518
  durationMs: number;
1003
1519
  exitStatus: number;
1520
+ reportOnly?: {
1521
+ id: string;
1522
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1523
+ status: "pending" | "fixing" | "fixed" | "reverted" | "unfixable" | "skipped";
1524
+ message: string;
1525
+ rule: string;
1526
+ category: "bug" | "smell" | "dead-code" | "duplication" | "security" | "secret" | "vuln-dep";
1527
+ severity: "error" | "warning" | "info";
1528
+ file: string;
1529
+ range: {
1530
+ startLine: number;
1531
+ startCol: number;
1532
+ endLine: number;
1533
+ endCol: number;
1534
+ };
1535
+ track: "ai-fix" | "deterministic" | "report-only";
1536
+ attempts: number;
1537
+ firstSeenLoop: number;
1538
+ lastSeenLoop: number;
1539
+ retryId?: string | undefined;
1540
+ helpUri?: string | undefined;
1541
+ flowPath?: {
1542
+ file: string;
1543
+ line: number;
1544
+ range?: {
1545
+ startLine: number;
1546
+ startCol: number;
1547
+ endLine: number;
1548
+ endCol: number;
1549
+ } | undefined;
1550
+ }[] | undefined;
1551
+ remediation?: string | undefined;
1552
+ autofixable?: boolean | undefined;
1553
+ repairStrategy?: "deterministic-eslint-fix" | "deterministic-ts-organize-imports" | "deterministic-package-json-cleanup" | "single-file-ai-edit" | "multi-file-duplicate-refactor" | "generated-source-repair" | "test-file-repair" | "dead-code-cleanup" | "unsupported" | undefined;
1554
+ repairStrategyReason?: string | undefined;
1555
+ revertReason?: "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | "session-error" | undefined;
1556
+ revertDetail?: string | undefined;
1557
+ finalFailureClass?: "tool-timeout" | "rate-limit" | "model-tool-failure" | "no-edit" | "no-op" | "regression" | "typecheck" | "broke-test" | "suppression" | "needs-lockfile-update" | undefined;
1558
+ inScope?: boolean | undefined;
1559
+ inReportScope?: boolean | undefined;
1560
+ inFixScope?: boolean | undefined;
1561
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1562
+ }[] | undefined;
1004
1563
  scannerStatuses?: {
1005
1564
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1006
1565
  status: "skipped" | "ran" | "failed";
1007
1566
  reason?: string | undefined;
1008
1567
  }[] | undefined;
1568
+ runScope?: {
1569
+ type: "all" | "scoped";
1570
+ fileCount?: number | undefined;
1571
+ } | undefined;
1572
+ fixPolicy?: {
1573
+ includeTests?: boolean | undefined;
1574
+ include?: string[] | undefined;
1575
+ exclude?: string[] | undefined;
1576
+ includeGenerated?: boolean | undefined;
1577
+ includeFixtures?: boolean | undefined;
1578
+ } | undefined;
1009
1579
  aiUsage?: {
1010
1580
  estimatedCostUsd: number;
1011
1581
  inputTokens: number;
@@ -1014,14 +1584,289 @@ declare const ReportSchema: z.ZodObject<{
1014
1584
  cacheReadInputTokens: number;
1015
1585
  sessions: number;
1016
1586
  } | undefined;
1587
+ failureSummary?: {
1588
+ blockingSecrets: number;
1589
+ unresolvedEligible: number;
1590
+ toolFailures: number;
1591
+ failedDeterministic: number;
1592
+ sessionErrors: number;
1593
+ regressions: number;
1594
+ typecheckFailures: number;
1595
+ testFailures: number;
1596
+ } | undefined;
1597
+ unresolvedEligibleCount?: number | undefined;
1017
1598
  }>;
1018
1599
  type Report = z.infer<typeof ReportSchema>;
1019
1600
  type BehaviorChange = z.infer<typeof BehaviorChangeSchema>;
1020
1601
  type ScannerStatus = z.infer<typeof ScannerStatusSchema>;
1021
1602
  type AiUsage$1 = z.infer<typeof AiUsageSchema>;
1603
+ type RunScope = z.infer<typeof RunScopeSchema>;
1604
+ type FixPolicy = z.infer<typeof FixPolicySchema>; //#endregion
1605
+ //#region src/orchestrator.d.ts
1606
+ type AuditResult = {
1607
+ findings: Finding[];
1608
+ allScannersMissing?: boolean;
1609
+ scanned?: number;
1610
+ scannerStatuses?: ScannerStatus$1[];
1611
+ };
1612
+ type FixOutcome = {
1613
+ kept: boolean;
1614
+ reason?: RevertReason;
1615
+ detail?: string;
1616
+ failureClass?: FailureClass;
1617
+ usage?: AiUsage;
1618
+ };
1619
+ type OrchestrateDeps = {
1620
+ cwd?: string;
1621
+ /** Run the scanners for a loop and return normalized findings. */
1622
+ audit: (loop: number) => Promise<AuditResult>;
1623
+ /** Fix one work unit (session + gate); returns whether the fix was kept. */
1624
+ fixUnit: (unit: WorkUnit, loop: number) => Promise<FixOutcome>;
1625
+ /** Fix one deterministic work unit without AI usage. */
1626
+ deterministicFixUnit?: (unit: WorkUnit, loop: number) => Promise<FixOutcome>;
1627
+ config: {
1628
+ maxLoops: number;
1629
+ perIssueBudget: number;
1630
+ maxSessions: number;
1631
+ includeTests?: boolean;
1632
+ fix?: FixScopeConfig;
1633
+ };
1634
+ /** Restrict findings to the fix scope (changed files); defaults to all. */
1635
+ inScope?: (findings: Finding[]) => Finding[];
1636
+ bus?: EventBus;
1637
+ };
1638
+ type Termination = "converged" | "max-loops" | "no-progress" | "no-scanners" | "retryable-infrastructure";
1639
+ type OrchestrateResult = {
1640
+ termination: Termination;
1641
+ loops: number;
1642
+ exitStatus: number;
1643
+ findings: Finding[];
1644
+ secrets: Finding[];
1645
+ reportOnly: Finding[];
1646
+ deterministic: Finding[];
1647
+ depBumps: Finding[];
1648
+ scannerStatuses: ScannerStatus$1[];
1649
+ runScope: RunScope;
1650
+ /** Estimated AI cost/usage summed across every fix attempt (including reverted ones). */
1651
+ usage: AiUsage;
1652
+ };
1653
+ /**
1654
+ * The scan → fix → re-audit loop. Terminates on the first of: converged (0 fixable),
1655
+ * no-progress (no dispatchable units or an attempted loop changed no attempt/status
1656
+ * state), per-issue budget exhaustion (mark unfixable, keep going), or max-loops.
1657
+ */
1658
+ declare function orchestrate(deps: OrchestrateDeps): Promise<OrchestrateResult>;
1659
+
1660
+ //#endregion
1661
+ //#region src/gate/checks/tests.d.ts
1662
+ type TestStatus = "pass" | "fail";
1663
+ type TestOutcome = {
1664
+ name: string;
1665
+ status: TestStatus;
1666
+ };
1667
+
1668
+ //#endregion
1669
+ //#region src/fixing/unit-gate.d.ts
1670
+ type UnitGateDeps = {
1671
+ cwd: string;
1672
+ typescript: boolean;
1673
+ runTsc: () => Promise<{
1674
+ exitCode: number;
1675
+ output: string;
1676
+ }>;
1677
+ runBuild?: () => Promise<{
1678
+ exitCode: number;
1679
+ output: string;
1680
+ }>;
1681
+ hasTestRunner: boolean;
1682
+ runRelated: (files: string[]) => Promise<TestOutcome[]>;
1683
+ scanFindings: (files: string[]) => Promise<Finding[]>;
1684
+ baseline: Set<string>;
1685
+ };
1686
+
1687
+ //#endregion
1688
+ //#region src/fixing/deterministic.d.ts
1689
+ interface DeterministicFixer {
1690
+ /** Fix a planned repair unit without starting an AI session. */
1691
+ fix(unit: WorkUnit): Promise<FixOutcome>;
1692
+ }
1693
+ type DeterministicFixUnitDeps = UnitGateDeps;
1694
+ declare function makeDeterministicFixer(deps: DeterministicFixUnitDeps): DeterministicFixer;
1695
+ declare const makeDeterministicFixUnit: (deps: DeterministicFixUnitDeps) => (unit: WorkUnit) => Promise<FixOutcome>;
1696
+
1697
+ //#endregion
1698
+ //#region src/session/claude.d.ts
1699
+ type ClaudeSpawn = (request: SessionRequest) => Promise<{
1700
+ stdout: string;
1701
+ exitCode: number;
1702
+ }>;
1703
+ /** Drives a real `claude -p` session and parses its stream-json into edits. */
1704
+ declare class ClaudeSession implements SessionRunner {
1705
+ private readonly deps;
1706
+ constructor(deps: {
1707
+ spawn: ClaudeSpawn;
1708
+ });
1709
+ run(request: SessionRequest): Promise<SessionResult>;
1710
+ }
1711
+
1712
+ //#endregion
1713
+ //#region src/git/snapshot.d.ts
1714
+ /**
1715
+ * A silent restore point for the working tree, stored as a git commit object pinned by a private
1716
+ * ref (`refs/tend/snapshot`) — nothing committed to any branch, the editor sees no change. Backs
1717
+ * `tend undo` (exact restore) and `tend diff` (only the tool's edits). Reuses git's content store,
1718
+ * so the on-disk record is a 40-char id rather than a copy of every file.
1719
+ */
1720
+ declare class Snapshot {
1721
+ private readonly cwd;
1722
+ private readonly root;
1723
+ private readonly sha;
1724
+ private constructor();
1725
+ static capture(_git: SimpleGit, cwd: string): Promise<Snapshot>;
1726
+ /** Serialize to a tiny object for `.tend/snapshot.json` (powers `undo` across invocations). */
1727
+ toJSON(): {
1728
+ cwd: string;
1729
+ root: string;
1730
+ sha: string;
1731
+ };
1732
+ static fromJSON(data: {
1733
+ cwd: string;
1734
+ root: string;
1735
+ sha: string;
1736
+ }): Snapshot;
1737
+ /** Files whose contents differ from the snapshot, or that are new/deleted since it (sorted). */
1738
+ changedSince(_git: SimpleGit): Promise<string[]>;
1739
+ /** Restore a single file to its captured contents (worktree only — the user's index is untouched). */
1740
+ restoreFile(rel: string): Promise<void>;
1741
+ /** Restore the working tree exactly to the captured state (incl. deleting files created since). */
1742
+ restore(_git: SimpleGit): Promise<void>;
1743
+ }
1744
+
1745
+ //#endregion
1746
+ //#region src/git/repo.d.ts
1747
+ /** Refuse to run outside a git repo — the snapshot/restore safety net needs it. */
1748
+ declare function assertGitRepo(git: SimpleGit): Promise<void>;
1749
+ /**
1750
+ * Files changed vs `HEAD`: tracked modifications/additions/renames plus untracked files,
1751
+ * scoped and re-based to `git`'s working directory (so a run from `apps/foo` only sees
1752
+ * `apps/foo`'s changes, pathed as the scanners path them).
1753
+ */
1754
+ declare function changedVsHead(git: SimpleGit): Promise<string[]>;
1755
+ /**
1756
+ * Concrete files under the given path(s) — tracked plus untracked (so newly-added files
1757
+ * are scoped too, mirroring `changedVsHead`). `git ls-files` reports paths relative to
1758
+ * `git`'s working directory and interprets the pathspecs the same way, so the result is
1759
+ * already in the coordinate system the scanners and `filterToChanged` expect. Expanding to
1760
+ * concrete files (not bare directories) matters: `filterToChanged` matches exact paths.
1761
+ */
1762
+
1763
+ /** Revert a single file to its snapshot state. */
1764
+ declare function revertFile(snapshot: Snapshot, file: string): Promise<void>;
1765
+
1766
+ //#endregion
1767
+ //#region src/detect/package-manager.d.ts
1768
+ type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
1769
+ /** Detect the package manager from the lockfile present; defaults to npm. */
1770
+ declare function detectPackageManager(cwd: string): PackageManager;
1771
+
1772
+ //#endregion
1773
+ //#region src/config/config.d.ts
1774
+ declare const ConfigSchema: z.ZodObject<{
1775
+ maxSessions: z.ZodDefault<z.ZodNumber>;
1776
+ maxLoops: z.ZodDefault<z.ZodNumber>;
1777
+ perIssueBudget: z.ZodDefault<z.ZodNumber>;
1778
+ test: z.ZodOptional<z.ZodString>;
1779
+ teethCheck: z.ZodDefault<z.ZodBoolean>;
1780
+ includeTests: z.ZodDefault<z.ZodBoolean>;
1781
+ /** Model passed to `claude -p` for fixes — an alias (sonnet/opus/haiku) or a full model id. */
1782
+ model: z.ZodDefault<z.ZodString>;
1783
+ /** Reasoning effort for fixes; unset → claude's own default. */
1784
+ effort: z.ZodOptional<z.ZodEnum<["low", "medium", "high", "xhigh", "max"]>>;
1785
+ /** Report/fix scope policy. Reports stay broad; fixes default away from generated/tooling paths. */
1786
+ fix: z.ZodDefault<z.ZodObject<{
1787
+ include: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1788
+ exclude: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
1789
+ includeGenerated: z.ZodDefault<z.ZodBoolean>;
1790
+ includeFixtures: z.ZodDefault<z.ZodBoolean>;
1791
+ }, "strip", z.ZodTypeAny, {
1792
+ include: string[];
1793
+ exclude: string[];
1794
+ includeGenerated: boolean;
1795
+ includeFixtures: boolean;
1796
+ }, {
1797
+ include?: string[] | undefined;
1798
+ exclude?: string[] | undefined;
1799
+ includeGenerated?: boolean | undefined;
1800
+ includeFixtures?: boolean | undefined;
1801
+ }>>;
1802
+ tools: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
1803
+ enabled: z.ZodDefault<z.ZodBoolean>;
1804
+ configPath: z.ZodOptional<z.ZodString>;
1805
+ }, "strip", z.ZodTypeAny, {
1806
+ enabled: boolean;
1807
+ configPath?: string | undefined;
1808
+ }, {
1809
+ enabled?: boolean | undefined;
1810
+ configPath?: string | undefined;
1811
+ }>>>;
1812
+ }, "strip", z.ZodTypeAny, {
1813
+ maxSessions: number;
1814
+ maxLoops: number;
1815
+ perIssueBudget: number;
1816
+ teethCheck: boolean;
1817
+ includeTests: boolean;
1818
+ model: string;
1819
+ fix: {
1820
+ include: string[];
1821
+ exclude: string[];
1822
+ includeGenerated: boolean;
1823
+ includeFixtures: boolean;
1824
+ };
1825
+ tools: Record<string, {
1826
+ enabled: boolean;
1827
+ configPath?: string | undefined;
1828
+ }>;
1829
+ test?: string | undefined;
1830
+ effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
1831
+ }, {
1832
+ maxSessions?: number | undefined;
1833
+ maxLoops?: number | undefined;
1834
+ perIssueBudget?: number | undefined;
1835
+ test?: string | undefined;
1836
+ teethCheck?: boolean | undefined;
1837
+ includeTests?: boolean | undefined;
1838
+ model?: string | undefined;
1839
+ effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
1840
+ fix?: {
1841
+ include?: string[] | undefined;
1842
+ exclude?: string[] | undefined;
1843
+ includeGenerated?: boolean | undefined;
1844
+ includeFixtures?: boolean | undefined;
1845
+ } | undefined;
1846
+ tools?: Record<string, {
1847
+ enabled?: boolean | undefined;
1848
+ configPath?: string | undefined;
1849
+ }> | undefined;
1850
+ }>;
1851
+ type TendConfig = z.infer<typeof ConfigSchema>;
1852
+ /** CLI flags that can override config; only defined keys take effect. */
1853
+ type CliOverrides = Partial<Pick<TendConfig, "maxSessions" | "maxLoops" | "perIssueBudget" | "test" | "teethCheck" | "includeTests" | "model" | "effort">>;
1854
+ /**
1855
+ * Load config via cosmiconfig (searching from `cwd`), validate with zod, and apply
1856
+ * zero-config defaults when no file is found. Invalid config throws a clear message.
1857
+ */
1858
+ declare function loadConfig(cwd: string): Promise<TendConfig>;
1859
+ /** Overlay CLI flags onto a loaded config (flags win). */
1860
+ declare function applyCliOverrides(config: TendConfig, overrides: CliOverrides): TendConfig;
1861
+
1862
+ //#endregion
1863
+ //#region src/report/retry-id.d.ts
1864
+ type RetryIdGenerator = () => string;
1022
1865
 
1023
1866
  //#endregion
1024
1867
  //#region src/report/builder.d.ts
1868
+ /** Ensure every finding in a persisted report has a human-facing id unique to that report. */
1869
+
1025
1870
  /** Accumulates per-finding outcomes and run metadata into a validated report.json. */
1026
1871
  declare class ReportBuilder {
1027
1872
  private readonly generateRetryId?;
@@ -1041,61 +1886,11 @@ declare class ReportBuilder {
1041
1886
  durationMs: number;
1042
1887
  exitStatus: number;
1043
1888
  aiUsage?: AiUsage$1;
1889
+ runScope?: RunScope;
1890
+ fixPolicy?: FixPolicy;
1044
1891
  }): Report;
1045
1892
  }
1046
1893
 
1047
- //#endregion
1048
- //#region src/output/events.d.ts
1049
- /** What happened to a file's fix attempt. "left" = in scope but never dispatched. */
1050
- type FileOutcome = "fixed" | "reverted" | "left";
1051
- type TendEvent = {
1052
- type: "snapshot";
1053
- } | {
1054
- type: "detected";
1055
- packageManager: string;
1056
- typescript: boolean;
1057
- testRunner?: string;
1058
- } | {
1059
- type: "scan-start";
1060
- loop: number;
1061
- } | {
1062
- type: "audit";
1063
- loop: number;
1064
- findings: number;
1065
- files: number;
1066
- scanned?: number;
1067
- } | {
1068
- type: "loop-start";
1069
- loop: number;
1070
- files: string[];
1071
- concurrency: number;
1072
- } | {
1073
- type: "file-start";
1074
- loop: number;
1075
- file: string;
1076
- rule?: string;
1077
- } | {
1078
- type: "file-result";
1079
- loop: number;
1080
- file: string;
1081
- outcome: FileOutcome;
1082
- reason?: string;
1083
- } | {
1084
- type: "loop-complete";
1085
- loop: number;
1086
- fixed: number;
1087
- } | {
1088
- type: "done";
1089
- exitStatus: number;
1090
- };
1091
- type Listener = (event: TendEvent) => void;
1092
- /** Minimal synchronous event bus. With no listener, emit is a no-op (silent mode). */
1093
- declare class EventBus {
1094
- private readonly listeners;
1095
- on(listener: Listener): () => void;
1096
- emit(event: TendEvent): void;
1097
- }
1098
-
1099
1894
  //#endregion
1100
1895
  //#region src/output/theme.d.ts
1101
1896
  /**
@@ -1157,54 +1952,6 @@ type RemainingGroup = {
1157
1952
  */
1158
1953
  declare function groupRemaining(report: Report): RemainingGroup[];
1159
1954
 
1160
- //#endregion
1161
- //#region src/orchestrator.d.ts
1162
- type AuditResult = {
1163
- findings: Finding[];
1164
- allScannersMissing?: boolean;
1165
- scanned?: number;
1166
- scannerStatuses?: ScannerStatus$1[];
1167
- };
1168
- type FixOutcome = {
1169
- kept: boolean;
1170
- reason?: RevertReason;
1171
- detail?: string;
1172
- usage?: AiUsage;
1173
- };
1174
- type OrchestrateDeps = {
1175
- /** Run the scanners for a loop and return normalized findings. */
1176
- audit: (loop: number) => Promise<AuditResult>;
1177
- /** Fix one work unit (session + gate); returns whether the fix was kept. */
1178
- fixUnit: (unit: WorkUnit, loop: number) => Promise<FixOutcome>;
1179
- config: {
1180
- maxLoops: number;
1181
- perIssueBudget: number;
1182
- maxSessions: number;
1183
- includeTests?: boolean;
1184
- };
1185
- /** Restrict findings to the fix scope (changed files); defaults to all. */
1186
- inScope?: (findings: Finding[]) => Finding[];
1187
- bus?: EventBus;
1188
- };
1189
- type Termination = "converged" | "max-loops" | "no-progress" | "no-scanners";
1190
- type OrchestrateResult = {
1191
- termination: Termination;
1192
- loops: number;
1193
- exitStatus: number;
1194
- findings: Finding[];
1195
- secrets: Finding[];
1196
- depBumps: Finding[];
1197
- scannerStatuses: ScannerStatus$1[];
1198
- /** Estimated AI cost/usage summed across every fix attempt (including reverted ones). */
1199
- usage: AiUsage;
1200
- };
1201
- /**
1202
- * The scan → fix → re-audit loop. Terminates on the first of: converged (0 fixable),
1203
- * no-progress (no dispatchable units or an attempted loop changed no attempt/status
1204
- * state), per-issue budget exhaustion (mark unfixable, keep going), or max-loops.
1205
- */
1206
- declare function orchestrate(deps: OrchestrateDeps): Promise<OrchestrateResult>;
1207
-
1208
1955
  //#endregion
1209
1956
  //#region src/cli.d.ts
1210
1957
  type CliHandlers = {
@@ -1285,4 +2032,4 @@ type RetryResult = {
1285
2032
  declare function retryCommand(id: string, deps: RetryDeps): Promise<RetryResult>;
1286
2033
 
1287
2034
  //#endregion
1288
- export { AiUsage, AuditResult, ChangeSet, Check, ClaudeSession, CliHandlers, ConfigSchema, EventBus, FileEdit, Finding, FindingSchema, FindingStore, FixOutcome, GateOutcome, OrchestrateDeps, OrchestrateResult, PackageManager, RawFinding, Report, ReportBuilder, ReportSchema, RetryDeps, RetryResult, RouteResult, RunDeps, ScanContext, ScanResult, Scanner, SessionRequest, SessionResult, SessionRunner, Snapshot, Spawn, TendConfig, TendEvent, Termination, Tool, Track, Which, WorkUnit, addUsage, applyCliOverrides, assertGitRepo, buildProgram, changedFiles, changedVsHead, detectPackageManager, diffCommand, dispatch, filterToChanged, fingerprint, groupRemaining, isAvailable, loadConfig, normalize, orchestrate, planWork, renderSummary, retryCommand, revertFile, route, runCommand, runGate, runScanner, scopeFindings, showCommand, trackForTool, undoCommand, zeroUsage };
2035
+ export { AiUsage, AuditResult, ChangeSet, Check, ClaudeSession, CliHandlers, ConfigSchema, DeterministicFixUnitDeps, DeterministicFixer, EventBus, FileEdit, Finding, FindingSchema, FindingStore, FixOutcome, GateOutcome, OrchestrateDeps, OrchestrateResult, PackageManager, REPAIR_STRATEGIES, RawFinding, RepairPlan, RepairStrategy, Report, ReportBuilder, ReportSchema, RetryDeps, RetryResult, RouteResult, RunDeps, ScanContext, ScanResult, Scanner, SessionRequest, SessionResult, SessionRunner, Snapshot, Spawn, TendConfig, TendEvent, Termination, Tool, Track, Which, WorkUnit, addUsage, applyCliOverrides, applyRepairPlanToFinding, assertGitRepo, buildProgram, changedFiles, changedVsHead, detectPackageManager, diffCommand, dispatch, filterToChanged, fingerprint, groupRemaining, isAiDispatchStrategy, isAvailable, loadConfig, makeDeterministicFixUnit, makeDeterministicFixer, normalize, orchestrate, planRepair, planWork, planWorkFromRepairs, renderSummary, retryCommand, revertFile, route, runCommand, runGate, runScanner, scopeFindings, showCommand, trackForTool, undoCommand, zeroUsage };