tend-cli 0.5.0 → 0.6.1

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;
@@ -584,10 +609,22 @@ declare const RunScopeSchema: z.ZodDefault<z.ZodObject<{
584
609
  }>>;
585
610
  declare const FixPolicySchema: z.ZodDefault<z.ZodObject<{
586
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>;
587
616
  }, "strip", z.ZodTypeAny, {
588
617
  includeTests: boolean;
618
+ include: string[];
619
+ exclude: string[];
620
+ includeGenerated: boolean;
621
+ includeFixtures: boolean;
589
622
  }, {
590
623
  includeTests?: boolean | undefined;
624
+ include?: string[] | undefined;
625
+ exclude?: string[] | undefined;
626
+ includeGenerated?: boolean | undefined;
627
+ includeFixtures?: boolean | undefined;
591
628
  }>>;
592
629
  declare const ReportSchema: z.ZodObject<{
593
630
  findings: z.ZodArray<z.ZodObject<{
@@ -619,22 +656,57 @@ declare const ReportSchema: z.ZodObject<{
619
656
  flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
620
657
  file: z.ZodString;
621
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
+ }>>;
622
675
  }, "strip", z.ZodTypeAny, {
623
676
  file: string;
624
677
  line: number;
678
+ range?: {
679
+ startLine: number;
680
+ startCol: number;
681
+ endLine: number;
682
+ endCol: number;
683
+ } | undefined;
625
684
  }, {
626
685
  file: string;
627
686
  line: number;
687
+ range?: {
688
+ startLine: number;
689
+ startCol: number;
690
+ endLine: number;
691
+ endCol: number;
692
+ } | undefined;
628
693
  }>, "many">>;
629
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>;
630
698
  track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
631
699
  status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
632
700
  attempts: z.ZodNumber;
633
- 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"]>>;
634
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"]>>;
635
704
  firstSeenLoop: z.ZodNumber;
636
705
  lastSeenLoop: z.ZodNumber;
637
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"]>>;
638
710
  }, "strip", z.ZodTypeAny, {
639
711
  id: string;
640
712
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -654,16 +726,29 @@ declare const ReportSchema: z.ZodObject<{
654
726
  attempts: number;
655
727
  firstSeenLoop: number;
656
728
  lastSeenLoop: number;
729
+ inReportScope: boolean;
730
+ inFixScope: boolean;
657
731
  retryId?: string | undefined;
658
732
  helpUri?: string | undefined;
659
733
  flowPath?: {
660
734
  file: string;
661
735
  line: number;
736
+ range?: {
737
+ startLine: number;
738
+ startCol: number;
739
+ endLine: number;
740
+ endCol: number;
741
+ } | undefined;
662
742
  }[] | undefined;
663
743
  remediation?: string | undefined;
664
- 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;
665
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;
666
750
  inScope?: boolean | undefined;
751
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
667
752
  }, {
668
753
  id: string;
669
754
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -688,11 +773,24 @@ declare const ReportSchema: z.ZodObject<{
688
773
  flowPath?: {
689
774
  file: string;
690
775
  line: number;
776
+ range?: {
777
+ startLine: number;
778
+ startCol: number;
779
+ endLine: number;
780
+ endCol: number;
781
+ } | undefined;
691
782
  }[] | undefined;
692
783
  remediation?: string | undefined;
693
- 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;
694
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;
695
790
  inScope?: boolean | undefined;
791
+ inReportScope?: boolean | undefined;
792
+ inFixScope?: boolean | undefined;
793
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
696
794
  }>, "many">;
697
795
  secrets: z.ZodArray<z.ZodObject<{
698
796
  id: z.ZodString;
@@ -723,22 +821,57 @@ declare const ReportSchema: z.ZodObject<{
723
821
  flowPath: z.ZodOptional<z.ZodArray<z.ZodObject<{
724
822
  file: z.ZodString;
725
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
+ }>>;
726
840
  }, "strip", z.ZodTypeAny, {
727
841
  file: string;
728
842
  line: number;
843
+ range?: {
844
+ startLine: number;
845
+ startCol: number;
846
+ endLine: number;
847
+ endCol: number;
848
+ } | undefined;
729
849
  }, {
730
850
  file: string;
731
851
  line: number;
852
+ range?: {
853
+ startLine: number;
854
+ startCol: number;
855
+ endLine: number;
856
+ endCol: number;
857
+ } | undefined;
732
858
  }>, "many">>;
733
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>;
734
863
  track: z.ZodEnum<["ai-fix", "deterministic", "report-only"]>;
735
864
  status: z.ZodEnum<["pending", "fixing", "fixed", "reverted", "unfixable", "skipped"]>;
736
865
  attempts: z.ZodNumber;
737
- 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"]>>;
738
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"]>>;
739
869
  firstSeenLoop: z.ZodNumber;
740
870
  lastSeenLoop: z.ZodNumber;
741
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"]>>;
742
875
  }, "strip", z.ZodTypeAny, {
743
876
  id: string;
744
877
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -758,16 +891,29 @@ declare const ReportSchema: z.ZodObject<{
758
891
  attempts: number;
759
892
  firstSeenLoop: number;
760
893
  lastSeenLoop: number;
894
+ inReportScope: boolean;
895
+ inFixScope: boolean;
761
896
  retryId?: string | undefined;
762
897
  helpUri?: string | undefined;
763
898
  flowPath?: {
764
899
  file: string;
765
900
  line: number;
901
+ range?: {
902
+ startLine: number;
903
+ startCol: number;
904
+ endLine: number;
905
+ endCol: number;
906
+ } | undefined;
766
907
  }[] | undefined;
767
908
  remediation?: string | undefined;
768
- 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;
769
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;
770
915
  inScope?: boolean | undefined;
916
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
771
917
  }, {
772
918
  id: string;
773
919
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
@@ -792,49 +938,227 @@ declare const ReportSchema: z.ZodObject<{
792
938
  flowPath?: {
793
939
  file: string;
794
940
  line: number;
941
+ range?: {
942
+ startLine: number;
943
+ startCol: number;
944
+ endLine: number;
945
+ endCol: number;
946
+ } | undefined;
795
947
  }[] | undefined;
796
948
  remediation?: string | undefined;
797
- 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;
798
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;
799
955
  inScope?: boolean | undefined;
956
+ inReportScope?: boolean | undefined;
957
+ inFixScope?: boolean | undefined;
958
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
800
959
  }>, "many">;
801
- depBumps: z.ZodArray<z.ZodObject<{
802
- findingId: z.ZodString;
803
- remediation: z.ZodString;
804
- }, "strip", z.ZodTypeAny, {
805
- remediation: string;
806
- findingId: string;
807
- }, {
808
- remediation: string;
809
- findingId: string;
810
- }>, "many">;
811
- flaggedBehaviorChanges: z.ZodArray<z.ZodObject<{
812
- findingId: z.ZodString;
813
- file: z.ZodString;
814
- note: z.ZodString;
815
- }, "strip", z.ZodTypeAny, {
816
- file: string;
817
- findingId: string;
818
- note: string;
819
- }, {
820
- file: string;
821
- findingId: string;
822
- note: string;
823
- }>, "many">;
824
- 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>;
825
963
  tool: z.ZodEnum<["sonarjs", "knip", "jscpd", "semgrep", "osv", "gitleaks"]>;
826
- status: z.ZodEnum<["ran", "skipped", "failed"]>;
827
- 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"]>>;
828
1040
  }, "strip", z.ZodTypeAny, {
1041
+ id: string;
829
1042
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
830
- status: "skipped" | "ran" | "failed";
831
- reason?: string | undefined;
832
- }, {
833
- tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
834
- status: "skipped" | "ran" | "failed";
835
- reason?: string | undefined;
836
- }>, "many">>;
837
- runScope: z.ZodDefault<z.ZodObject<{
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;
1156
+ }, {
1157
+ tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1158
+ status: "skipped" | "ran" | "failed";
1159
+ reason?: string | undefined;
1160
+ }>, "many">>;
1161
+ runScope: z.ZodDefault<z.ZodObject<{
838
1162
  type: z.ZodEnum<["all", "scoped"]>;
839
1163
  fileCount: z.ZodOptional<z.ZodNumber>;
840
1164
  }, "strip", z.ZodTypeAny, {
@@ -846,10 +1170,22 @@ declare const ReportSchema: z.ZodObject<{
846
1170
  }>>;
847
1171
  fixPolicy: z.ZodDefault<z.ZodObject<{
848
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>;
849
1177
  }, "strip", z.ZodTypeAny, {
850
1178
  includeTests: boolean;
1179
+ include: string[];
1180
+ exclude: string[];
1181
+ includeGenerated: boolean;
1182
+ includeFixtures: boolean;
851
1183
  }, {
852
1184
  includeTests?: boolean | undefined;
1185
+ include?: string[] | undefined;
1186
+ exclude?: string[] | undefined;
1187
+ includeGenerated?: boolean | undefined;
1188
+ includeFixtures?: boolean | undefined;
853
1189
  }>>;
854
1190
  aiUsage: z.ZodDefault<z.ZodObject<{
855
1191
  estimatedCostUsd: z.ZodNumber;
@@ -873,6 +1209,35 @@ declare const ReportSchema: z.ZodObject<{
873
1209
  cacheReadInputTokens: number;
874
1210
  sessions: number;
875
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>;
876
1241
  loops: z.ZodNumber;
877
1242
  durationMs: z.ZodNumber;
878
1243
  exitStatus: z.ZodNumber;
@@ -896,16 +1261,29 @@ declare const ReportSchema: z.ZodObject<{
896
1261
  attempts: number;
897
1262
  firstSeenLoop: number;
898
1263
  lastSeenLoop: number;
1264
+ inReportScope: boolean;
1265
+ inFixScope: boolean;
899
1266
  retryId?: string | undefined;
900
1267
  helpUri?: string | undefined;
901
1268
  flowPath?: {
902
1269
  file: string;
903
1270
  line: number;
1271
+ range?: {
1272
+ startLine: number;
1273
+ startCol: number;
1274
+ endLine: number;
1275
+ endCol: number;
1276
+ } | undefined;
904
1277
  }[] | undefined;
905
1278
  remediation?: string | undefined;
906
- 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;
907
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;
908
1285
  inScope?: boolean | undefined;
1286
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
909
1287
  }[];
910
1288
  secrets: {
911
1289
  id: string;
@@ -926,16 +1304,72 @@ declare const ReportSchema: z.ZodObject<{
926
1304
  attempts: number;
927
1305
  firstSeenLoop: number;
928
1306
  lastSeenLoop: number;
1307
+ inReportScope: boolean;
1308
+ inFixScope: boolean;
929
1309
  retryId?: string | undefined;
930
1310
  helpUri?: string | undefined;
931
1311
  flowPath?: {
932
1312
  file: string;
933
1313
  line: number;
1314
+ range?: {
1315
+ startLine: number;
1316
+ startCol: number;
1317
+ endLine: number;
1318
+ endCol: number;
1319
+ } | undefined;
934
1320
  }[] | undefined;
935
1321
  remediation?: string | undefined;
936
- 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;
937
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;
938
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;
939
1373
  }[];
940
1374
  depBumps: {
941
1375
  remediation: string;
@@ -957,6 +1391,10 @@ declare const ReportSchema: z.ZodObject<{
957
1391
  };
958
1392
  fixPolicy: {
959
1393
  includeTests: boolean;
1394
+ include: string[];
1395
+ exclude: string[];
1396
+ includeGenerated: boolean;
1397
+ includeFixtures: boolean;
960
1398
  };
961
1399
  aiUsage: {
962
1400
  estimatedCostUsd: number;
@@ -966,6 +1404,17 @@ declare const ReportSchema: z.ZodObject<{
966
1404
  cacheReadInputTokens: number;
967
1405
  sessions: number;
968
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;
969
1418
  loops: number;
970
1419
  durationMs: number;
971
1420
  exitStatus: number;
@@ -994,11 +1443,24 @@ declare const ReportSchema: z.ZodObject<{
994
1443
  flowPath?: {
995
1444
  file: string;
996
1445
  line: number;
1446
+ range?: {
1447
+ startLine: number;
1448
+ startCol: number;
1449
+ endLine: number;
1450
+ endCol: number;
1451
+ } | undefined;
997
1452
  }[] | undefined;
998
1453
  remediation?: string | undefined;
999
- 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;
1000
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;
1001
1460
  inScope?: boolean | undefined;
1461
+ inReportScope?: boolean | undefined;
1462
+ inFixScope?: boolean | undefined;
1463
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1002
1464
  }[];
1003
1465
  secrets: {
1004
1466
  id: string;
@@ -1024,11 +1486,24 @@ declare const ReportSchema: z.ZodObject<{
1024
1486
  flowPath?: {
1025
1487
  file: string;
1026
1488
  line: number;
1489
+ range?: {
1490
+ startLine: number;
1491
+ startCol: number;
1492
+ endLine: number;
1493
+ endCol: number;
1494
+ } | undefined;
1027
1495
  }[] | undefined;
1028
1496
  remediation?: string | undefined;
1029
- 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;
1030
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;
1031
1503
  inScope?: boolean | undefined;
1504
+ inReportScope?: boolean | undefined;
1505
+ inFixScope?: boolean | undefined;
1506
+ scopeExclusionReason?: "generated" | "fixtures" | "tests" | "out-of-scope" | undefined;
1032
1507
  }[];
1033
1508
  depBumps: {
1034
1509
  remediation: string;
@@ -1042,6 +1517,49 @@ declare const ReportSchema: z.ZodObject<{
1042
1517
  loops: number;
1043
1518
  durationMs: number;
1044
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;
1045
1563
  scannerStatuses?: {
1046
1564
  tool: "sonarjs" | "knip" | "jscpd" | "semgrep" | "osv" | "gitleaks";
1047
1565
  status: "skipped" | "ran" | "failed";
@@ -1053,6 +1571,10 @@ declare const ReportSchema: z.ZodObject<{
1053
1571
  } | undefined;
1054
1572
  fixPolicy?: {
1055
1573
  includeTests?: boolean | undefined;
1574
+ include?: string[] | undefined;
1575
+ exclude?: string[] | undefined;
1576
+ includeGenerated?: boolean | undefined;
1577
+ includeFixtures?: boolean | undefined;
1056
1578
  } | undefined;
1057
1579
  aiUsage?: {
1058
1580
  estimatedCostUsd: number;
@@ -1062,16 +1584,289 @@ declare const ReportSchema: z.ZodObject<{
1062
1584
  cacheReadInputTokens: number;
1063
1585
  sessions: number;
1064
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;
1065
1598
  }>;
1066
1599
  type Report = z.infer<typeof ReportSchema>;
1067
1600
  type BehaviorChange = z.infer<typeof BehaviorChangeSchema>;
1068
1601
  type ScannerStatus = z.infer<typeof ScannerStatusSchema>;
1069
1602
  type AiUsage$1 = z.infer<typeof AiUsageSchema>;
1070
1603
  type RunScope = z.infer<typeof RunScopeSchema>;
1071
- type FixPolicy = z.infer<typeof FixPolicySchema>;
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;
1072
1865
 
1073
1866
  //#endregion
1074
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
+
1075
1870
  /** Accumulates per-finding outcomes and run metadata into a validated report.json. */
1076
1871
  declare class ReportBuilder {
1077
1872
  private readonly generateRetryId?;
@@ -1096,58 +1891,6 @@ declare class ReportBuilder {
1096
1891
  }): Report;
1097
1892
  }
1098
1893
 
1099
- //#endregion
1100
- //#region src/output/events.d.ts
1101
- /** What happened to a file in the current dispatched batch. "left" = not attempted. */
1102
- type FileOutcome = "fixed" | "reverted" | "left";
1103
- type TendEvent = {
1104
- type: "snapshot";
1105
- } | {
1106
- type: "detected";
1107
- packageManager: string;
1108
- typescript: boolean;
1109
- testRunner?: string;
1110
- } | {
1111
- type: "scan-start";
1112
- loop: number;
1113
- } | {
1114
- type: "audit";
1115
- loop: number;
1116
- findings: number;
1117
- files: number;
1118
- scanned?: number;
1119
- } | {
1120
- type: "loop-start";
1121
- loop: number;
1122
- files: string[];
1123
- concurrency: number;
1124
- } | {
1125
- type: "file-start";
1126
- loop: number;
1127
- file: string;
1128
- rule?: string;
1129
- } | {
1130
- type: "file-result";
1131
- loop: number;
1132
- file: string;
1133
- outcome: FileOutcome;
1134
- reason?: string;
1135
- } | {
1136
- type: "loop-complete";
1137
- loop: number;
1138
- fixed: number;
1139
- } | {
1140
- type: "done";
1141
- exitStatus: number;
1142
- };
1143
- type Listener = (event: TendEvent) => void;
1144
- /** Minimal synchronous event bus. With no listener, emit is a no-op (silent mode). */
1145
- declare class EventBus {
1146
- private readonly listeners;
1147
- on(listener: Listener): () => void;
1148
- emit(event: TendEvent): void;
1149
- }
1150
-
1151
1894
  //#endregion
1152
1895
  //#region src/output/theme.d.ts
1153
1896
  /**
@@ -1209,55 +1952,6 @@ type RemainingGroup = {
1209
1952
  */
1210
1953
  declare function groupRemaining(report: Report): RemainingGroup[];
1211
1954
 
1212
- //#endregion
1213
- //#region src/orchestrator.d.ts
1214
- type AuditResult = {
1215
- findings: Finding[];
1216
- allScannersMissing?: boolean;
1217
- scanned?: number;
1218
- scannerStatuses?: ScannerStatus$1[];
1219
- };
1220
- type FixOutcome = {
1221
- kept: boolean;
1222
- reason?: RevertReason;
1223
- detail?: string;
1224
- usage?: AiUsage;
1225
- };
1226
- type OrchestrateDeps = {
1227
- /** Run the scanners for a loop and return normalized findings. */
1228
- audit: (loop: number) => Promise<AuditResult>;
1229
- /** Fix one work unit (session + gate); returns whether the fix was kept. */
1230
- fixUnit: (unit: WorkUnit, loop: number) => Promise<FixOutcome>;
1231
- config: {
1232
- maxLoops: number;
1233
- perIssueBudget: number;
1234
- maxSessions: number;
1235
- includeTests?: boolean;
1236
- };
1237
- /** Restrict findings to the fix scope (changed files); defaults to all. */
1238
- inScope?: (findings: Finding[]) => Finding[];
1239
- bus?: EventBus;
1240
- };
1241
- type Termination = "converged" | "max-loops" | "no-progress" | "no-scanners";
1242
- type OrchestrateResult = {
1243
- termination: Termination;
1244
- loops: number;
1245
- exitStatus: number;
1246
- findings: Finding[];
1247
- secrets: Finding[];
1248
- depBumps: Finding[];
1249
- scannerStatuses: ScannerStatus$1[];
1250
- runScope: RunScope;
1251
- /** Estimated AI cost/usage summed across every fix attempt (including reverted ones). */
1252
- usage: AiUsage;
1253
- };
1254
- /**
1255
- * The scan → fix → re-audit loop. Terminates on the first of: converged (0 fixable),
1256
- * no-progress (no dispatchable units or an attempted loop changed no attempt/status
1257
- * state), per-issue budget exhaustion (mark unfixable, keep going), or max-loops.
1258
- */
1259
- declare function orchestrate(deps: OrchestrateDeps): Promise<OrchestrateResult>;
1260
-
1261
1955
  //#endregion
1262
1956
  //#region src/cli.d.ts
1263
1957
  type CliHandlers = {
@@ -1338,4 +2032,4 @@ type RetryResult = {
1338
2032
  declare function retryCommand(id: string, deps: RetryDeps): Promise<RetryResult>;
1339
2033
 
1340
2034
  //#endregion
1341
- 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 };