@cleocode/core 2026.6.14 → 2026.6.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/check/pr-gate.d.ts +6 -2
  2. package/dist/check/pr-gate.d.ts.map +1 -1
  3. package/dist/check/pr-gate.js +14 -32
  4. package/dist/check/pr-gate.js.map +1 -1
  5. package/dist/config/config-repair.d.ts +70 -0
  6. package/dist/config/config-repair.d.ts.map +1 -0
  7. package/dist/config/config-repair.js +248 -0
  8. package/dist/config/config-repair.js.map +1 -0
  9. package/dist/config/registry.d.ts.map +1 -1
  10. package/dist/config/registry.js +4 -4
  11. package/dist/config/registry.js.map +1 -1
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +11 -10
  14. package/dist/config.js.map +1 -1
  15. package/dist/docs/export-document.js +58 -16
  16. package/dist/docs/export-document.js.map +2 -2
  17. package/dist/gc/cleanup.d.ts +23 -8
  18. package/dist/gc/cleanup.d.ts.map +1 -1
  19. package/dist/gc/cleanup.js +287 -22
  20. package/dist/gc/cleanup.js.map +1 -1
  21. package/dist/gc/janitor.d.ts +149 -0
  22. package/dist/gc/janitor.d.ts.map +1 -0
  23. package/dist/gc/janitor.js +760 -0
  24. package/dist/gc/janitor.js.map +1 -0
  25. package/dist/internal.d.ts +1 -0
  26. package/dist/internal.d.ts.map +1 -1
  27. package/dist/internal.js +3 -0
  28. package/dist/internal.js.map +1 -1
  29. package/dist/llm/cli-ops.d.ts +31 -4
  30. package/dist/llm/cli-ops.d.ts.map +1 -1
  31. package/dist/llm/cli-ops.js +110 -26
  32. package/dist/llm/cli-ops.js.map +1 -1
  33. package/dist/llm/credential-pool.d.ts +62 -0
  34. package/dist/llm/credential-pool.d.ts.map +1 -1
  35. package/dist/llm/credential-pool.js +161 -0
  36. package/dist/llm/credential-pool.js.map +1 -1
  37. package/dist/llm/cross-provider-selector.d.ts +254 -0
  38. package/dist/llm/cross-provider-selector.d.ts.map +1 -0
  39. package/dist/llm/cross-provider-selector.js +635 -0
  40. package/dist/llm/cross-provider-selector.js.map +1 -0
  41. package/dist/llm/index.d.ts +2 -0
  42. package/dist/llm/index.d.ts.map +1 -1
  43. package/dist/llm/index.js +1 -0
  44. package/dist/llm/index.js.map +1 -1
  45. package/dist/llm/local-model-fit.d.ts +260 -0
  46. package/dist/llm/local-model-fit.d.ts.map +1 -0
  47. package/dist/llm/local-model-fit.js +563 -0
  48. package/dist/llm/local-model-fit.js.map +1 -0
  49. package/dist/llm/plugin-facade.js +883 -231
  50. package/dist/llm/plugin-facade.js.map +3 -3
  51. package/dist/llm/provider-registry/builtin/ollama.d.ts +18 -0
  52. package/dist/llm/provider-registry/builtin/ollama.d.ts.map +1 -1
  53. package/dist/llm/provider-registry/builtin/ollama.js +20 -2
  54. package/dist/llm/provider-registry/builtin/ollama.js.map +1 -1
  55. package/dist/llm/role-resolver.d.ts.map +1 -1
  56. package/dist/llm/role-resolver.js +45 -10
  57. package/dist/llm/role-resolver.js.map +1 -1
  58. package/dist/llm/transports/codex-responses.d.ts +111 -88
  59. package/dist/llm/transports/codex-responses.d.ts.map +1 -1
  60. package/dist/llm/transports/codex-responses.js +456 -258
  61. package/dist/llm/transports/codex-responses.js.map +1 -1
  62. package/dist/release/index.d.ts +2 -2
  63. package/dist/release/index.d.ts.map +1 -1
  64. package/dist/release/index.js +1 -1
  65. package/dist/release/index.js.map +1 -1
  66. package/dist/release/reconcile.d.ts +97 -0
  67. package/dist/release/reconcile.d.ts.map +1 -1
  68. package/dist/release/reconcile.js +412 -5
  69. package/dist/release/reconcile.js.map +1 -1
  70. package/dist/resources/backend.d.ts +155 -0
  71. package/dist/resources/backend.d.ts.map +1 -0
  72. package/dist/resources/backend.js +23 -0
  73. package/dist/resources/backend.js.map +1 -0
  74. package/dist/resources/linux-backend.d.ts +167 -0
  75. package/dist/resources/linux-backend.d.ts.map +1 -0
  76. package/dist/resources/linux-backend.js +259 -0
  77. package/dist/resources/linux-backend.js.map +1 -0
  78. package/dist/resources/monitor.d.ts +230 -0
  79. package/dist/resources/monitor.d.ts.map +1 -0
  80. package/dist/resources/monitor.js +255 -0
  81. package/dist/resources/monitor.js.map +1 -0
  82. package/dist/resources/spawn-wrapper.d.ts +265 -0
  83. package/dist/resources/spawn-wrapper.d.ts.map +1 -0
  84. package/dist/resources/spawn-wrapper.js +304 -0
  85. package/dist/resources/spawn-wrapper.js.map +1 -0
  86. package/dist/selfimprove/budget.d.ts +11 -2
  87. package/dist/selfimprove/budget.d.ts.map +1 -1
  88. package/dist/selfimprove/budget.js +11 -2
  89. package/dist/selfimprove/budget.js.map +1 -1
  90. package/dist/selfimprove/fix-gen-context.d.ts +172 -0
  91. package/dist/selfimprove/fix-gen-context.d.ts.map +1 -0
  92. package/dist/selfimprove/fix-gen-context.js +218 -0
  93. package/dist/selfimprove/fix-gen-context.js.map +1 -0
  94. package/dist/selfimprove/fix-gen.d.ts +285 -0
  95. package/dist/selfimprove/fix-gen.d.ts.map +1 -0
  96. package/dist/selfimprove/fix-gen.js +346 -0
  97. package/dist/selfimprove/fix-gen.js.map +1 -0
  98. package/dist/selfimprove/op-source-map.d.ts +92 -0
  99. package/dist/selfimprove/op-source-map.d.ts.map +1 -0
  100. package/dist/selfimprove/op-source-map.js +187 -0
  101. package/dist/selfimprove/op-source-map.js.map +1 -0
  102. package/dist/selfimprove/probe-helper.d.ts +61 -0
  103. package/dist/selfimprove/probe-helper.d.ts.map +1 -0
  104. package/dist/selfimprove/probe-helper.js +64 -0
  105. package/dist/selfimprove/probe-helper.js.map +1 -0
  106. package/dist/selfimprove/run-loop.d.ts +44 -4
  107. package/dist/selfimprove/run-loop.d.ts.map +1 -1
  108. package/dist/selfimprove/run-loop.js +73 -6
  109. package/dist/selfimprove/run-loop.js.map +1 -1
  110. package/dist/selfimprove/scenarios/seeded-code-regression/golden.json +18 -0
  111. package/dist/selfimprove/scenarios/seeded-code-regression/scenario.json +12 -0
  112. package/dist/sentient/cross-project-hygiene.d.ts +11 -2
  113. package/dist/sentient/cross-project-hygiene.d.ts.map +1 -1
  114. package/dist/sentient/cross-project-hygiene.js +73 -10
  115. package/dist/sentient/cross-project-hygiene.js.map +1 -1
  116. package/dist/sentient/daemon.d.ts.map +1 -1
  117. package/dist/sentient/daemon.js +7 -2
  118. package/dist/sentient/daemon.js.map +1 -1
  119. package/dist/sentient/worktree-dispatch.d.ts.map +1 -1
  120. package/dist/sentient/worktree-dispatch.js +8 -1
  121. package/dist/sentient/worktree-dispatch.js.map +1 -1
  122. package/dist/setup/index.d.ts +1 -0
  123. package/dist/setup/index.d.ts.map +1 -1
  124. package/dist/setup/index.js +1 -0
  125. package/dist/setup/index.js.map +1 -1
  126. package/dist/setup/sections/models-roles.d.ts +32 -1
  127. package/dist/setup/sections/models-roles.d.ts.map +1 -1
  128. package/dist/setup/sections/models-roles.js +118 -19
  129. package/dist/setup/sections/models-roles.js.map +1 -1
  130. package/dist/setup/whoami-summary.d.ts +34 -0
  131. package/dist/setup/whoami-summary.d.ts.map +1 -0
  132. package/dist/setup/whoami-summary.js +106 -0
  133. package/dist/setup/whoami-summary.js.map +1 -0
  134. package/dist/spawn/branch-lock.d.ts.map +1 -1
  135. package/dist/spawn/branch-lock.js +7 -1
  136. package/dist/spawn/branch-lock.js.map +1 -1
  137. package/dist/store/attachment-repair.d.ts +110 -0
  138. package/dist/store/attachment-repair.d.ts.map +1 -0
  139. package/dist/store/attachment-repair.js +326 -0
  140. package/dist/store/attachment-repair.js.map +1 -0
  141. package/dist/store/attachment-store.d.ts.map +1 -1
  142. package/dist/store/attachment-store.js +24 -7
  143. package/dist/store/attachment-store.js.map +1 -1
  144. package/dist/tasks/evidence.d.ts +34 -2
  145. package/dist/tasks/evidence.d.ts.map +1 -1
  146. package/dist/tasks/evidence.js +293 -35
  147. package/dist/tasks/evidence.js.map +1 -1
  148. package/dist/verification/verify-tools.d.ts.map +1 -1
  149. package/dist/verification/verify-tools.js +5 -6
  150. package/dist/verification/verify-tools.js.map +1 -1
  151. package/package.json +22 -12
  152. package/templates/workflows/release-prepare.yml.tmpl +48 -2
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Bounded file-content loader for the fix-gen stage (T11988).
3
+ *
4
+ * The self-improvement fix-gen stage builds a prompt for the LLM
5
+ * ({@link "./fix-gen.js".buildFixGenPrompt}). Without file context the model
6
+ * can only see the regression diff entries (e.g.
7
+ * `op tasks.show (#0) at data/task/status: actual="pending" expected="active"`)
8
+ * and rationally responds `NO_PATCH` because it cannot locate the responsible code.
9
+ *
10
+ * This module resolves the relevant source files for each regressing op-coordinate
11
+ * via the static map ({@link "./op-source-map.js"}) and reads their content with a
12
+ * **hard context budget** so the prompt stays bounded regardless of file size.
13
+ *
14
+ * ## Budget model
15
+ *
16
+ * Two independent byte-level caps:
17
+ *
18
+ * - `perFileBudget` (default {@link DEFAULT_PER_FILE_BUDGET}): the maximum bytes
19
+ * read from any single file. Files larger than this are truncated at a
20
+ * newline boundary and a `<… TRUNCATED …>` marker is appended.
21
+ * - `totalBudget` (default {@link DEFAULT_TOTAL_BUDGET}): the maximum total bytes
22
+ * across ALL included files. Files are added in order (handler files first, then
23
+ * core files); once the total would be exceeded the remaining files are
24
+ * summarised as a path-only `<file listed but not loaded — budget exhausted>` stub.
25
+ *
26
+ * The caller embeds the resolved {@link LoadedFileContext} into the prompt. The LLM
27
+ * prompt builder ({@link "./fix-gen.js".buildFixGenPrompt}) inserts the file blocks
28
+ * between the regression description and the "produce the diff" instruction, giving
29
+ * the model concrete code to work from.
30
+ *
31
+ * Import-time side-effect-free: no logger init, no native handles.
32
+ *
33
+ * @module @cleocode/core/selfimprove/fix-gen-context
34
+ * @epic T11889
35
+ * @task T11988
36
+ */
37
+ import { readFileSync } from 'node:fs';
38
+ import { join } from 'node:path';
39
+ import { collectOpSourceFiles } from './op-source-map.js';
40
+ // ── Budget constants ────────────────────────────────────────────────────────
41
+ /**
42
+ * Per-file byte cap (default): any single file is truncated to at most 24 KB
43
+ * before being included in the prompt. Chosen to comfortably fit a large-ish
44
+ * handler or core module without overwhelming the model context.
45
+ */
46
+ export const DEFAULT_PER_FILE_BUDGET = 24_576; // 24 KB
47
+ /**
48
+ * Total byte cap (default): the combined content of all included files must not
49
+ * exceed 65 KB. Keeps the combined code context section to a model-digestible
50
+ * slice of the context window even when multiple files are included.
51
+ */
52
+ export const DEFAULT_TOTAL_BUDGET = 65_536; // 64 KB
53
+ // ── Implementation ───────────────────────────────────────────────────────────
54
+ /**
55
+ * Truncate `content` to at most `maxBytes` bytes, cutting at a newline boundary
56
+ * wherever possible, and appending a marker.
57
+ *
58
+ * Operates on raw bytes via `Buffer` so multi-byte characters don't produce
59
+ * partial surrogate pairs in the truncated output.
60
+ *
61
+ * @param content - The full file content string.
62
+ * @param maxBytes - The per-file byte cap.
63
+ * @returns `{ text, truncated }` — the (possibly shortened) string and a flag.
64
+ * @internal
65
+ */
66
+ export function truncateToByteLimit(content, maxBytes) {
67
+ const buf = Buffer.from(content, 'utf8');
68
+ if (buf.length <= maxBytes) {
69
+ return { text: content, truncated: false };
70
+ }
71
+ // Cut at a newline boundary within the budget to avoid broken lines.
72
+ let cutAt = maxBytes;
73
+ while (cutAt > 0 && buf[cutAt] !== 0x0a /* '\n' */) {
74
+ cutAt--;
75
+ }
76
+ if (cutAt === 0)
77
+ cutAt = maxBytes; // no newline found — hard cut
78
+ const truncated = buf.slice(0, cutAt).toString('utf8');
79
+ return { text: `${truncated}\n<… TRUNCATED at ${maxBytes} bytes …>`, truncated: true };
80
+ }
81
+ /**
82
+ * Load bounded file content for the op-coordinates in a fix-gen request.
83
+ *
84
+ * Resolves the handler + core files for each `opCoord` via
85
+ * {@link collectOpSourceFiles}, reads them against `projectRoot`, applies the
86
+ * per-file and total byte budgets, and returns a structured
87
+ * {@link LoadedFileContext} describing every entry (loaded, truncated, skipped, or
88
+ * errored). NEVER throws — read errors produce `{ content: null, readError: true }`.
89
+ *
90
+ * @param opts - See {@link LoadFileContextOptions}.
91
+ * @returns The resolved {@link LoadedFileContext}.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const ctx = loadFileContext({
96
+ * projectRoot: '/repo',
97
+ * opCoords: ['tasks.show'],
98
+ * });
99
+ * // ctx.entries[0].repoRelativePath === 'packages/cleo/src/dispatch/domains/tasks.ts'
100
+ * // ctx.entries[1].repoRelativePath === 'packages/core/src/tasks/show.ts'
101
+ * // ctx.totalBytes <= DEFAULT_TOTAL_BUDGET
102
+ * ```
103
+ */
104
+ export function loadFileContext(opts) {
105
+ const perFileBudget = opts.perFileBudget ?? DEFAULT_PER_FILE_BUDGET;
106
+ const totalBudget = opts.totalBudget ?? DEFAULT_TOTAL_BUDGET;
107
+ // Resolve the unique set of source files for all op-coords.
108
+ const { handlerFiles, coreFiles } = collectOpSourceFiles(opts.opCoords);
109
+ // Handler files first (they contain the dispatch glue the model needs to locate
110
+ // where to apply the fix); core modules follow (they contain the business logic).
111
+ const allRelPaths = [...handlerFiles, ...coreFiles];
112
+ const entries = [];
113
+ let totalBytes = 0;
114
+ let truncatedCount = 0;
115
+ let budgetSkippedCount = 0;
116
+ let errorCount = 0;
117
+ for (const relPath of allRelPaths) {
118
+ const absPath = join(opts.projectRoot, relPath);
119
+ // Total budget exhausted — list the file but do not load it.
120
+ if (totalBytes >= totalBudget) {
121
+ entries.push({
122
+ repoRelativePath: relPath,
123
+ content: null,
124
+ truncated: false,
125
+ budgetExhausted: true,
126
+ readError: false,
127
+ });
128
+ budgetSkippedCount++;
129
+ continue;
130
+ }
131
+ // Read the file, gracefully handling any IO error.
132
+ let raw;
133
+ try {
134
+ raw = readFileSync(absPath, 'utf8');
135
+ }
136
+ catch {
137
+ entries.push({
138
+ repoRelativePath: relPath,
139
+ content: null,
140
+ truncated: false,
141
+ budgetExhausted: false,
142
+ readError: true,
143
+ });
144
+ errorCount++;
145
+ continue;
146
+ }
147
+ // Apply per-file budget.
148
+ const { text, truncated } = truncateToByteLimit(raw, perFileBudget);
149
+ const textBytes = Buffer.byteLength(text, 'utf8');
150
+ // If adding this file would bust the total budget, use a shorter slice that
151
+ // fits, then mark the file as budget-exhausted.
152
+ const remaining = totalBudget - totalBytes;
153
+ if (textBytes > remaining) {
154
+ const { text: fitted, truncated: fTrunc } = truncateToByteLimit(raw, remaining);
155
+ const fittedBytes = Buffer.byteLength(fitted, 'utf8');
156
+ entries.push({
157
+ repoRelativePath: relPath,
158
+ content: fittedBytes > 0 ? fitted : null,
159
+ truncated: fTrunc || truncated,
160
+ budgetExhausted: true,
161
+ readError: false,
162
+ });
163
+ totalBytes += fittedBytes;
164
+ truncatedCount += fTrunc || truncated ? 1 : 0;
165
+ budgetSkippedCount++;
166
+ continue;
167
+ }
168
+ entries.push({
169
+ repoRelativePath: relPath,
170
+ content: text,
171
+ truncated,
172
+ budgetExhausted: false,
173
+ readError: false,
174
+ });
175
+ totalBytes += textBytes;
176
+ if (truncated)
177
+ truncatedCount++;
178
+ }
179
+ return { entries, totalBytes, truncatedCount, budgetSkippedCount, errorCount };
180
+ }
181
+ /**
182
+ * Render a {@link LoadedFileContext} as the file-context section of a fix-gen
183
+ * prompt.
184
+ *
185
+ * Produces a human-readable block listing each file with its content (or a stub
186
+ * explaining why the content was omitted). Suitable for direct embedding in the
187
+ * LLM user-turn after the regression description.
188
+ *
189
+ * @param ctx - The loaded file context.
190
+ * @returns A string ready for embedding in the prompt (empty string when no files).
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * const section = renderFileContextSection(ctx);
195
+ * // --- packages/core/src/tasks/show.ts ---
196
+ * // <content or stub>
197
+ * ```
198
+ */
199
+ export function renderFileContextSection(ctx) {
200
+ if (ctx.entries.length === 0)
201
+ return '';
202
+ const lines = ['Relevant source files (bounded — apply the diff against these):'];
203
+ for (const entry of ctx.entries) {
204
+ lines.push('');
205
+ lines.push(`--- ${entry.repoRelativePath} ---`);
206
+ if (entry.readError) {
207
+ lines.push('<file not readable — patch by path only>');
208
+ }
209
+ else if (entry.budgetExhausted && entry.content === null) {
210
+ lines.push('<file listed but not loaded — context budget exhausted>');
211
+ }
212
+ else if (entry.content !== null) {
213
+ lines.push(entry.content);
214
+ }
215
+ }
216
+ return lines.join('\n');
217
+ }
218
+ //# sourceMappingURL=fix-gen-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-gen-context.js","sourceRoot":"","sources":["../../src/selfimprove/fix-gen-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Fix-generation stage for the self-improvement loop (T11889 · T11975).
3
+ *
4
+ * This is the missing autonomous link the v1 loop explicitly stubbed out
5
+ * ("NO autonomous fix-gen in v1", see {@link "./run-loop.js"}): given a detected
6
+ * regression (an open `selfimprove_dhq` + its envelope-diff) plus minimal repo
7
+ * context, it asks the LLM to PROPOSE a unified-diff patch and writes that patch
8
+ * to the path the draft-PR egress ({@link "./draft-pr.js".openDraftPr}) already
9
+ * `existsSync`-checks: `<cwd>/selfimprove-<scenario>.patch`. Once the patch is on
10
+ * disk the existing egress guard opens ONE DRAFT PR — closing the
11
+ * DHQ → fix → draft-PR pipeline end-to-end.
12
+ *
13
+ * ## Hard safety posture (unchanged from v1 — P5 spec §B.7)
14
+ *
15
+ * - **LLM ONLY via the E9 chokepoint.** The real generator
16
+ * ({@link createLlmFixGenerator}) resolves its model strictly through
17
+ * {@link "../llm/system-resolver.js".resolveLLMForSystem} → {@link ModelRunner}
18
+ * (Gate-13). It constructs NO raw provider client, reads NO `*_API_KEY` env,
19
+ * and hardcodes no model id — the resolver/registry is the SSoT. The
20
+ * plaintext token is materialized only at the wire boundary (E10).
21
+ * - **Draft-PR-ONLY, never auto-merge.** This module produces a PATCH FILE only;
22
+ * the egress that consumes it always opens a `--draft` PR against a feature
23
+ * branch (never `main`). This module performs NO git/gh action.
24
+ * - **Graceful degrade, never a rogue mutation.** Every failure (no credential,
25
+ * LLM error, empty / non-unified-diff output) returns a typed
26
+ * {@link FixGenResult} of kind `'skipped'` and writes NO patch file — so the
27
+ * existing egress guard (`existsSync` on the patch path) simply skips the PR.
28
+ * This function NEVER throws.
29
+ * - **Injectable seam.** The LLM dependency is the {@link FixGenerator} port;
30
+ * unit tests inject a deterministic fake that returns a canned patch, so NO
31
+ * real LLM is reached in tests.
32
+ *
33
+ * CORE-first: this engine lives in `core` and owns the `FixGenerator` port TYPE.
34
+ * Import-time side-effect-free.
35
+ *
36
+ * @module @cleocode/core/selfimprove/fix-gen
37
+ * @epic T11889
38
+ * @task T11975
39
+ */
40
+ import type { Logger } from 'pino';
41
+ import type { DiffEntry } from './envelope-diff.js';
42
+ import { type LoadedFileContext, type LoadFileContextOptions } from './fix-gen-context.js';
43
+ /**
44
+ * The structured request handed to a {@link FixGenerator}. Carries only what the
45
+ * generator needs to draft a patch: the DHQ identity, the scenario, the
46
+ * regression diff, and a minimal slice of repo context.
47
+ */
48
+ export interface FixGenRequest {
49
+ /** The stable `'DHQ-###'` handle of the open regression. */
50
+ readonly dhqId: string;
51
+ /** The scenario whose replay diverged from the golden. */
52
+ readonly scenario: string;
53
+ /** The idempotency hash tying this request to ONE open DHQ row. */
54
+ readonly questionHash: string;
55
+ /** The structured regression entries (the evidence) from the envelope diff. */
56
+ readonly regressions: readonly DiffEntry[];
57
+ /**
58
+ * Minimal repo context the generator may use to ground the patch (e.g. the
59
+ * project root, a short description). Kept small on purpose — the loop does NOT
60
+ * stuff the whole repo into the prompt.
61
+ */
62
+ readonly repoContext: FixGenRepoContext;
63
+ }
64
+ /** Minimal repo context grounding a fix-generation request. */
65
+ export interface FixGenRepoContext {
66
+ /** Absolute project root the patch is generated against. */
67
+ readonly projectRoot: string;
68
+ /** Optional one-line summary of what the scenario exercises. */
69
+ readonly summary?: string;
70
+ /**
71
+ * Optional override for the file-context loading options (per-file budget,
72
+ * total budget). When absent the defaults from {@link "./fix-gen-context.js"}
73
+ * apply ({@link DEFAULT_PER_FILE_BUDGET} / {@link DEFAULT_TOTAL_BUDGET}).
74
+ *
75
+ * Setting `perFileBudget: 0` and `totalBudget: 0` effectively disables file
76
+ * context injection (the prompt degrades to the regression-only view — the model
77
+ * may still produce NO_PATCH, which is the honest outcome when context is
78
+ * insufficient).
79
+ *
80
+ * @task T11988
81
+ */
82
+ readonly contextBudget?: Pick<LoadFileContextOptions, 'perFileBudget' | 'totalBudget'>;
83
+ }
84
+ /** A generated patch, or an explicit "no usable patch" signal. */
85
+ export type FixGenOutput = {
86
+ /** The generator produced a candidate unified-diff patch. */
87
+ readonly kind: 'patch';
88
+ /** The raw unified-diff text (validated by {@link generateFixPatch}). */
89
+ readonly diff: string;
90
+ /** The model id that produced it (for audit). */
91
+ readonly model: string;
92
+ } | {
93
+ /** The generator produced no usable patch (degrade — never an error throw). */
94
+ readonly kind: 'none';
95
+ /** Machine-stable reason for the absence. */
96
+ readonly reason: string;
97
+ /**
98
+ * Credential-redacted, byte-bounded excerpt of the raw model reply (when the
99
+ * reason is `'model-declined'`). Absent for failure modes that have no reply
100
+ * (e.g. `'no-credential-resolved'`). Callers that log or persist this field
101
+ * MUST NOT additionally redact — it is pre-sanitized by the generator.
102
+ */
103
+ readonly rawReply?: string;
104
+ };
105
+ /**
106
+ * The injectable fix-generation port (the LLM seam).
107
+ *
108
+ * The real implementation ({@link createLlmFixGenerator}) drives the E9 chokepoint;
109
+ * tests inject a deterministic fake returning a canned patch. A `FixGenerator`
110
+ * MUST NOT throw — it encodes "no patch" as `{ kind: 'none', reason }`.
111
+ */
112
+ export interface FixGenerator {
113
+ /**
114
+ * Propose a unified-diff patch for one regression.
115
+ *
116
+ * @param request - The structured {@link FixGenRequest}.
117
+ * @returns A {@link FixGenOutput} — a candidate patch or an explicit "none".
118
+ */
119
+ propose(request: FixGenRequest): Promise<FixGenOutput>;
120
+ }
121
+ /** The terminal outcome of {@link generateFixPatch}. */
122
+ export type FixGenResult = {
123
+ /** A validated patch was written to {@link FixGenResultWritten.patchPath}. */
124
+ readonly kind: 'written';
125
+ /** Absolute path the patch was written to. */
126
+ readonly patchPath: string;
127
+ /** Byte length of the written patch. */
128
+ readonly bytes: number;
129
+ /** The model id that produced the patch. */
130
+ readonly model: string;
131
+ } | {
132
+ /** No patch was written; the egress guard will skip the PR. */
133
+ readonly kind: 'skipped';
134
+ /** Machine-stable reason recorded on the DHQ evidence. */
135
+ readonly reason: string;
136
+ /**
137
+ * Credential-redacted, byte-bounded excerpt of the raw model reply for
138
+ * `'model-declined'` and `'fixgen-not-a-diff'` outcomes. Absent for
139
+ * generator errors and other failure modes that have no usable reply text.
140
+ * Persisted on the DHQ evidence row so the loop operator can diagnose the
141
+ * model's actual output without re-running.
142
+ */
143
+ readonly replyExcerpt?: string;
144
+ };
145
+ /**
146
+ * Options for {@link generateFixPatch}.
147
+ */
148
+ export interface GenerateFixPatchOptions {
149
+ /** The structured fix-generation request. */
150
+ readonly request: FixGenRequest;
151
+ /** The injected generator (real LLM impl or a test fake). */
152
+ readonly generator: FixGenerator;
153
+ /**
154
+ * Working directory the patch path is resolved against — MUST match the `cwd`
155
+ * the downstream {@link "./draft-pr.js".openDraftPr} uses, so the file it writes
156
+ * is the file the egress finds.
157
+ */
158
+ readonly cwd?: string;
159
+ /** Injectable logger (defaults to the module logger). */
160
+ readonly logger?: Logger;
161
+ }
162
+ /**
163
+ * Compute the patch path the draft-PR egress expects for a scenario:
164
+ * `<cwd>/selfimprove-<scenario>.patch`. The scenario is sanitized to a safe file
165
+ * stem so a hostile scenario name cannot escape the cwd.
166
+ *
167
+ * @param scenario - The scenario name.
168
+ * @param cwd - The working directory to resolve against (defaults to `process.cwd`).
169
+ * @returns The absolute patch path.
170
+ */
171
+ export declare function fixPatchPath(scenario: string, cwd?: string): string;
172
+ /**
173
+ * Is `text` a plausible unified diff?
174
+ *
175
+ * A real `git apply`-able patch always carries at least one of the canonical
176
+ * unified-diff markers ({@link UNIFIED_DIFF_MARKERS}). An LLM that returns prose,
177
+ * an apology, or an empty string fails this guard, so the loop degrades to "no
178
+ * patch" rather than writing junk the egress would then fail to `git apply`.
179
+ *
180
+ * This is a cheap structural sniff, NOT a full parse — the authoritative
181
+ * applicability check is `git apply` inside the egress (which fails the PR cut on
182
+ * a bad patch, never `main`).
183
+ *
184
+ * @param text - Candidate patch text.
185
+ * @returns `true` when the text looks like a unified diff.
186
+ */
187
+ export declare function looksLikeUnifiedDiff(text: string): boolean;
188
+ /**
189
+ * Build the system + user prompt the real generator sends to the LLM. Pure
190
+ * (no IO) so it is unit-testable in isolation when an explicit `fileContext` is
191
+ * passed; the default path calls {@link loadFileContext} to resolve the relevant
192
+ * source files for each regressing op-coordinate (IO-bearing path used in
193
+ * production).
194
+ *
195
+ * The prompt is deliberately strict: "respond with ONLY a unified diff" — anything
196
+ * else fails {@link looksLikeUnifiedDiff} downstream and degrades to "no patch".
197
+ * When file context is available it is embedded between the regression description
198
+ * and the "produce the diff" instruction so the model can locate the responsible
199
+ * code. When context is absent (unmapped op or budget exhausted) the model is
200
+ * explicitly told it may respond `NO_PATCH` — this keeps the prompt honest.
201
+ *
202
+ * @param request - The fix-generation request.
203
+ * @param fileContext - Optional pre-loaded file context (injected for pure unit
204
+ * tests). When absent, {@link loadFileContext} is called with the request's
205
+ * `repoContext.projectRoot` and the op-coordinates from `regressions`.
206
+ * @returns The `{ system, user }` prompt pair.
207
+ *
208
+ * @task T11988
209
+ */
210
+ export declare function buildFixGenPrompt(request: FixGenRequest, fileContext?: LoadedFileContext): {
211
+ system: string;
212
+ user: string;
213
+ };
214
+ /**
215
+ * Produce a credential-redacted, byte-bounded excerpt of a raw model reply for
216
+ * safe logging and DHQ evidence attachment.
217
+ *
218
+ * The excerpt is at most {@link REPLY_EXCERPT_MAX_BYTES} UTF-8 bytes. When the
219
+ * reply is longer a `…[truncated <N> bytes]` marker replaces the tail so the
220
+ * caller can distinguish a genuinely-short reply from a truncated one. The
221
+ * returned string is already passed through {@link redact} so no downstream
222
+ * scrubbing is needed.
223
+ *
224
+ * @param reply - The raw model reply text.
225
+ * @returns A scrubbed, bounded excerpt string.
226
+ */
227
+ export declare function truncateReply(reply: string): string;
228
+ /**
229
+ * Run the fix-generation stage: ask the injected {@link FixGenerator} for a patch,
230
+ * validate it as a unified diff, and write it to the egress-expected patch path.
231
+ *
232
+ * This function NEVER throws and NEVER mutates anything but the single patch file.
233
+ * On ANY degrade path — generator returns `'none'`, the generator throws, or the
234
+ * returned text is not a unified diff — it writes NO file and returns
235
+ * `{ kind: 'skipped', reason }`, so the downstream `existsSync` egress guard
236
+ * simply skips the PR. The caller records the `reason` on the DHQ evidence.
237
+ *
238
+ * @param opts - See {@link GenerateFixPatchOptions}.
239
+ * @returns A {@link FixGenResult}.
240
+ *
241
+ * @example
242
+ * ```ts
243
+ * const res = await generateFixPatch({
244
+ * request: { dhqId: 'DHQ-abcd1234', scenario, questionHash, regressions, repoContext },
245
+ * generator: createLlmFixGenerator(),
246
+ * cwd: projectRoot,
247
+ * });
248
+ * if (res.kind === 'written') { // openDraftPr will now find selfimprove-<scenario>.patch }
249
+ * ```
250
+ */
251
+ export declare function generateFixPatch(opts: GenerateFixPatchOptions): Promise<FixGenResult>;
252
+ /**
253
+ * Construct the REAL fix generator — the one that drives the E9 LLM chokepoint.
254
+ *
255
+ * Resolution funnels through {@link resolveLLMForSystem}(`'task-executor'`) →
256
+ * {@link ModelRunner.build} → `session.send` (ONE non-streaming completion).
257
+ * It constructs NO raw provider client, reads NO API-key env, and hardcodes no
258
+ * model id (Gate-13). The plaintext credential is materialized ONLY at the
259
+ * `ModelRunner` wire boundary (E10) via the sealed handle. When no credential is
260
+ * reachable it returns `{ kind: 'none' }` — the loop degrades to "no patch", no
261
+ * PR. This function constructs nothing at call time (lazy dynamic imports keep the
262
+ * module import-time side-effect-free + the E9 deps off the hot import path).
263
+ *
264
+ * @param opts - Optional project root threaded into the resolver.
265
+ * @returns A {@link FixGenerator} backed by the E9 chokepoint.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * const gen = createLlmFixGenerator({ projectRoot });
270
+ * const out = await gen.propose(request); // resolves model via E9, never raw client
271
+ * ```
272
+ */
273
+ export declare function createLlmFixGenerator(opts?: {
274
+ projectRoot?: string;
275
+ }): FixGenerator;
276
+ /**
277
+ * Strip a single surrounding markdown code fence (```diff … ```), if present, so a
278
+ * model that wraps its diff still yields an applyable patch. A bare diff passes
279
+ * through untouched.
280
+ *
281
+ * @param text - Candidate patch text (already trimmed).
282
+ * @returns The fence-stripped text.
283
+ */
284
+ export declare function stripCodeFences(text: string): string;
285
+ //# sourceMappingURL=fix-gen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-gen.d.ts","sourceRoot":"","sources":["../../src/selfimprove/fix-gen.ts"],"names":[],"mappings":"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"}