human-to-code 0.1.17 → 0.1.18
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/Readme.md +17 -6
- package/SECURITY.md +22 -5
- package/dist/agents/direct/candidate-overlay.d.ts +36 -0
- package/dist/agents/direct/candidate-overlay.d.ts.map +1 -0
- package/dist/agents/direct/candidate-overlay.js +123 -0
- package/dist/agents/direct/candidate-overlay.js.map +1 -0
- package/dist/agents/direct/dependency-graph.d.ts +25 -0
- package/dist/agents/direct/dependency-graph.d.ts.map +1 -0
- package/dist/agents/direct/dependency-graph.js +140 -0
- package/dist/agents/direct/dependency-graph.js.map +1 -0
- package/dist/agents/direct/discovery.d.ts +2 -0
- package/dist/agents/direct/discovery.d.ts.map +1 -1
- package/dist/agents/direct/discovery.js +4 -0
- package/dist/agents/direct/discovery.js.map +1 -1
- package/dist/agents/direct/generation-client.d.ts +11 -0
- package/dist/agents/direct/generation-client.d.ts.map +1 -1
- package/dist/agents/direct/generation-client.js +20 -9
- package/dist/agents/direct/generation-client.js.map +1 -1
- package/dist/agents/direct/index.d.ts +4 -0
- package/dist/agents/direct/index.d.ts.map +1 -1
- package/dist/agents/direct/index.js +4 -0
- package/dist/agents/direct/index.js.map +1 -1
- package/dist/agents/direct/presentation.js +2 -2
- package/dist/agents/direct/presentation.js.map +1 -1
- package/dist/agents/direct/program-diagnostics.d.ts +39 -0
- package/dist/agents/direct/program-diagnostics.d.ts.map +1 -0
- package/dist/agents/direct/program-diagnostics.js +170 -0
- package/dist/agents/direct/program-diagnostics.js.map +1 -0
- package/dist/agents/direct/staged-validation.d.ts +53 -0
- package/dist/agents/direct/staged-validation.d.ts.map +1 -0
- package/dist/agents/direct/staged-validation.js +182 -0
- package/dist/agents/direct/staged-validation.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +54 -3
- package/dist/cli.js.map +1 -1
- package/dist/prompts/direct-repair.d.ts +30 -0
- package/dist/prompts/direct-repair.d.ts.map +1 -0
- package/dist/prompts/direct-repair.js +34 -0
- package/dist/prompts/direct-repair.js.map +1 -0
- package/dist/prompts/index.d.ts +1 -0
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +1 -0
- package/dist/prompts/index.js.map +1 -1
- package/docs/ARCHITECTURE.md +22 -8
- package/docs/MODULES.md +7 -1
- package/docs/SCALABILITY.md +9 -3
- package/package.json +3 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agents/direct/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agents/direct/index.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC;AACvC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wBAAwB,CAAC"}
|
|
@@ -13,8 +13,8 @@ export function renderReceipt(units, provider, model, language) {
|
|
|
13
13
|
` Language : ${profile.label} (.${profile.ext})`,
|
|
14
14
|
` Provider : ${provider}`,
|
|
15
15
|
` Model : ${model}`,
|
|
16
|
-
` Engine : direct (one model request per prompt)`,
|
|
17
|
-
` Requests : ${units.length}`,
|
|
16
|
+
` Engine : direct (one model request per prompt; bounded cross-file repair may add requests)`,
|
|
17
|
+
` Requests : ${units.length} planned (up to ${units.length} extra bounded repair requests for JS/TS)`,
|
|
18
18
|
"",
|
|
19
19
|
];
|
|
20
20
|
if (units.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../../src/agents/direct/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,QAAgB,EAChB,KAAa,EACb,QAAgB;IAEhB,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG;QACZ,oCAAoC;QACpC,EAAE;QACF,gBAAgB,OAAO,CAAC,KAAK,MAAM,OAAO,CAAC,GAAG,GAAG;QACjD,gBAAgB,QAAQ,EAAE;QAC1B,gBAAgB,KAAK,EAAE;QACvB,
|
|
1
|
+
{"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../../src/agents/direct/presentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGjD,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAC3B,KAAgC,EAChC,QAAgB,EAChB,KAAa,EACb,QAAgB;IAEhB,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG;QACZ,oCAAoC;QACpC,EAAE;QACF,gBAAgB,OAAO,CAAC,KAAK,MAAM,OAAO,CAAC,GAAG,GAAG;QACjD,gBAAgB,QAAQ,EAAE;QAC1B,gBAAgB,KAAK,EAAE;QACvB,gGAAgG;QAChG,gBAAgB,KAAK,CAAC,MAAM,mBAAmB,KAAK,CAAC,MAAM,2CAA2C;QACtG,EAAE;KACH,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;SACjF,CAAC;QACJ,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QACjD,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,kDAAkD,CAAC,CAAC,CAAC;IACzF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,gBAAgB,CAAC,gFAAgF,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9D,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,gBAAgB,CAAC,oFAAoF,CAAC,CAAC;IACnH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
import { type CandidateOverlay } from "./candidate-overlay.ts";
|
|
3
|
+
/** One normalized error-category compiler diagnostic. */
|
|
4
|
+
export interface ProjectDiagnostic {
|
|
5
|
+
/** Project-relative POSIX path, or undefined for global/options diagnostics. */
|
|
6
|
+
path?: string;
|
|
7
|
+
/** 1-based line, when the diagnostic has a location. */
|
|
8
|
+
line?: number;
|
|
9
|
+
/** TypeScript diagnostic code. */
|
|
10
|
+
code: number;
|
|
11
|
+
message: string;
|
|
12
|
+
}
|
|
13
|
+
export interface ValidationProgramContext {
|
|
14
|
+
root: string;
|
|
15
|
+
options: ts.CompilerOptions;
|
|
16
|
+
/** Host that answers from the overlay first, then the real file system. */
|
|
17
|
+
host: ts.CompilerHost;
|
|
18
|
+
/** On-disk JS/TS root files discovered with the bounded direct walk. */
|
|
19
|
+
projectFiles: string[];
|
|
20
|
+
}
|
|
21
|
+
/** Prepare compiler options, baseline host, and the on-disk JS/TS file list once per run. */
|
|
22
|
+
export declare function createValidationProgramContext(root: string): Promise<ValidationProgramContext>;
|
|
23
|
+
/** Overlay-aware compiler host for module resolution outside program creation. */
|
|
24
|
+
export declare function overlayCompilerHost(context: ValidationProgramContext, overlay: CandidateOverlay): ts.CompilerHost;
|
|
25
|
+
/**
|
|
26
|
+
* Collect error-category diagnostics for the given program state. Diagnostics
|
|
27
|
+
* inside `node_modules` or outside the project root are dropped symmetrically
|
|
28
|
+
* for baseline and candidate, so third-party typing noise never decides a unit.
|
|
29
|
+
*/
|
|
30
|
+
export declare function collectProjectDiagnostics(context: ValidationProgramContext, overlay?: CandidateOverlay): ProjectDiagnostic[];
|
|
31
|
+
/**
|
|
32
|
+
* Diff candidate diagnostics against the baseline so pre-existing project
|
|
33
|
+
* errors are never blamed on generated units. Files the overlay does not touch
|
|
34
|
+
* compare location-aware (path, code, line, message); overlay-modified files
|
|
35
|
+
* compare by multiplicity of (path, code, message) because replacements shift
|
|
36
|
+
* lines; overlay-created files are entirely new, so every diagnostic counts.
|
|
37
|
+
*/
|
|
38
|
+
export declare function newlyIntroducedProjectDiagnostics(baseline: readonly ProjectDiagnostic[], candidate: readonly ProjectDiagnostic[], overlay: CandidateOverlay): ProjectDiagnostic[];
|
|
39
|
+
//# sourceMappingURL=program-diagnostics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-diagnostics.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/program-diagnostics.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAiD,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG9G,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAkDD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC;IAC5B,2EAA2E;IAC3E,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC;IACtB,wEAAwE;IACxE,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAkBD,6FAA6F;AAC7F,wBAAsB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAMpG;AAED,kFAAkF;AAClF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,wBAAwB,EAAE,OAAO,EAAE,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAEjH;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,wBAAwB,EACjC,OAAO,CAAC,EAAE,gBAAgB,GACzB,iBAAiB,EAAE,CAyBrB;AAED;;;;;;GAMG;AACH,wBAAgB,iCAAiC,CAC/C,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,SAAS,EAAE,SAAS,iBAAiB,EAAE,EACvC,OAAO,EAAE,gBAAgB,GACxB,iBAAiB,EAAE,CAiCrB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combined TypeScript program diagnostics over the candidate overlay. This is
|
|
3
|
+
* static compiler validation of the in-memory candidate project — stronger
|
|
4
|
+
* than per-file syntax parsing, but it never imports, executes, or sandboxes
|
|
5
|
+
* project code and never claims runtime verification.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import { dirname, extname, join, relative, resolve, sep } from "node:path";
|
|
10
|
+
import ts from "typescript";
|
|
11
|
+
import { overlayPathKey, PROJECT_VALIDATION_EXTENSIONS } from "./candidate-overlay.js";
|
|
12
|
+
import { walkDirectFiles } from "./discovery.js";
|
|
13
|
+
/**
|
|
14
|
+
* Permissive fixed compiler options: the goal is catching real cross-file
|
|
15
|
+
* contradictions in generated code, not enforcing a strictness style. Bundler
|
|
16
|
+
* resolution accepts extensionless, `.js`-suffixed, and (with noEmit)
|
|
17
|
+
* `.ts`-suffixed relative imports, matching what direct models emit.
|
|
18
|
+
*/
|
|
19
|
+
function validationCompilerOptions(root) {
|
|
20
|
+
const options = {
|
|
21
|
+
target: ts.ScriptTarget.ES2023,
|
|
22
|
+
module: ts.ModuleKind.ESNext,
|
|
23
|
+
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
24
|
+
lib: ["lib.es2023.d.ts"],
|
|
25
|
+
allowJs: true,
|
|
26
|
+
checkJs: true,
|
|
27
|
+
jsx: ts.JsxEmit.Preserve,
|
|
28
|
+
noEmit: true,
|
|
29
|
+
allowImportingTsExtensions: true,
|
|
30
|
+
resolveJsonModule: true,
|
|
31
|
+
skipLibCheck: true,
|
|
32
|
+
forceConsistentCasingInFileNames: true,
|
|
33
|
+
};
|
|
34
|
+
const typeRoots = nodeTypeRoots(root);
|
|
35
|
+
if (typeRoots.length > 0) {
|
|
36
|
+
options.typeRoots = typeRoots;
|
|
37
|
+
options.types = ["node"];
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
options.types = [];
|
|
41
|
+
}
|
|
42
|
+
return options;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Locate `@types/node` so `node:` builtin imports resolve in target projects
|
|
46
|
+
* that have no type dependencies of their own. The project's own copy wins;
|
|
47
|
+
* otherwise the copy shipped with this package is used.
|
|
48
|
+
*/
|
|
49
|
+
function nodeTypeRoots(root) {
|
|
50
|
+
const projectTypes = resolve(root, "node_modules", "@types");
|
|
51
|
+
if (existsSync(join(projectTypes, "node")))
|
|
52
|
+
return [projectTypes];
|
|
53
|
+
try {
|
|
54
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
55
|
+
const packageJson = requireFromHere.resolve("@types/node/package.json");
|
|
56
|
+
return [dirname(dirname(packageJson))];
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return [];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function createOverlayHost(options, overlay) {
|
|
63
|
+
const base = ts.createCompilerHost(options, true);
|
|
64
|
+
if (!overlay || overlay.files.size === 0)
|
|
65
|
+
return base;
|
|
66
|
+
const find = (fileName) => overlay.files.get(overlayPathKey(fileName));
|
|
67
|
+
return {
|
|
68
|
+
...base,
|
|
69
|
+
fileExists: (fileName) => find(fileName) !== undefined || base.fileExists(fileName),
|
|
70
|
+
readFile: (fileName) => find(fileName)?.content ?? base.readFile(fileName),
|
|
71
|
+
getSourceFile: (fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile) => {
|
|
72
|
+
const candidate = find(fileName);
|
|
73
|
+
if (candidate)
|
|
74
|
+
return ts.createSourceFile(fileName, candidate.content, languageVersionOrOptions, true);
|
|
75
|
+
return base.getSourceFile(fileName, languageVersionOrOptions, onError, shouldCreateNewSourceFile);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Prepare compiler options, baseline host, and the on-disk JS/TS file list once per run. */
|
|
80
|
+
export async function createValidationProgramContext(root) {
|
|
81
|
+
const absoluteRoot = resolve(root);
|
|
82
|
+
const options = validationCompilerOptions(absoluteRoot);
|
|
83
|
+
const projectFiles = (await walkDirectFiles(absoluteRoot)).filter((file) => PROJECT_VALIDATION_EXTENSIONS.has(extname(file).toLowerCase()));
|
|
84
|
+
return { root: absoluteRoot, options, host: createOverlayHost(options, undefined), projectFiles };
|
|
85
|
+
}
|
|
86
|
+
/** Overlay-aware compiler host for module resolution outside program creation. */
|
|
87
|
+
export function overlayCompilerHost(context, overlay) {
|
|
88
|
+
return createOverlayHost(context.options, overlay);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Collect error-category diagnostics for the given program state. Diagnostics
|
|
92
|
+
* inside `node_modules` or outside the project root are dropped symmetrically
|
|
93
|
+
* for baseline and candidate, so third-party typing noise never decides a unit.
|
|
94
|
+
*/
|
|
95
|
+
export function collectProjectDiagnostics(context, overlay) {
|
|
96
|
+
const rootNames = new Set(context.projectFiles.map((file) => resolve(file)));
|
|
97
|
+
if (overlay)
|
|
98
|
+
for (const file of overlay.files.values())
|
|
99
|
+
rootNames.add(file.absolutePath);
|
|
100
|
+
const host = overlay ? createOverlayHost(context.options, overlay) : context.host;
|
|
101
|
+
const program = ts.createProgram({ rootNames: [...rootNames], options: context.options, host });
|
|
102
|
+
const diagnostics = [];
|
|
103
|
+
for (const diagnostic of ts.getPreEmitDiagnostics(program)) {
|
|
104
|
+
if (diagnostic.category !== ts.DiagnosticCategory.Error)
|
|
105
|
+
continue;
|
|
106
|
+
const entry = {
|
|
107
|
+
code: diagnostic.code,
|
|
108
|
+
message: ts.flattenDiagnosticMessageText(diagnostic.messageText, " "),
|
|
109
|
+
};
|
|
110
|
+
if (diagnostic.file) {
|
|
111
|
+
const fileName = resolve(diagnostic.file.fileName);
|
|
112
|
+
if (fileName.split(sep).includes("node_modules"))
|
|
113
|
+
continue;
|
|
114
|
+
const rel = relative(context.root, fileName);
|
|
115
|
+
if (rel.startsWith(".."))
|
|
116
|
+
continue;
|
|
117
|
+
entry.path = rel.split(sep).join("/");
|
|
118
|
+
if (diagnostic.start !== undefined) {
|
|
119
|
+
entry.line = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start).line + 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
diagnostics.push(entry);
|
|
123
|
+
}
|
|
124
|
+
return diagnostics;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Diff candidate diagnostics against the baseline so pre-existing project
|
|
128
|
+
* errors are never blamed on generated units. Files the overlay does not touch
|
|
129
|
+
* compare location-aware (path, code, line, message); overlay-modified files
|
|
130
|
+
* compare by multiplicity of (path, code, message) because replacements shift
|
|
131
|
+
* lines; overlay-created files are entirely new, so every diagnostic counts.
|
|
132
|
+
*/
|
|
133
|
+
export function newlyIntroducedProjectDiagnostics(baseline, candidate, overlay) {
|
|
134
|
+
const modified = new Set();
|
|
135
|
+
const created = new Set();
|
|
136
|
+
for (const file of overlay.files.values()) {
|
|
137
|
+
(file.created ? created : modified).add(file.path);
|
|
138
|
+
}
|
|
139
|
+
const keyFor = (diagnostic) => {
|
|
140
|
+
const locationAware = diagnostic.path === undefined || !modified.has(diagnostic.path);
|
|
141
|
+
return JSON.stringify([
|
|
142
|
+
diagnostic.path ?? "",
|
|
143
|
+
diagnostic.code,
|
|
144
|
+
locationAware ? diagnostic.line ?? -1 : -1,
|
|
145
|
+
diagnostic.message,
|
|
146
|
+
]);
|
|
147
|
+
};
|
|
148
|
+
const remaining = new Map();
|
|
149
|
+
for (const diagnostic of baseline) {
|
|
150
|
+
if (diagnostic.path !== undefined && created.has(diagnostic.path))
|
|
151
|
+
continue;
|
|
152
|
+
const key = keyFor(diagnostic);
|
|
153
|
+
remaining.set(key, (remaining.get(key) ?? 0) + 1);
|
|
154
|
+
}
|
|
155
|
+
const introduced = [];
|
|
156
|
+
for (const diagnostic of candidate) {
|
|
157
|
+
if (diagnostic.path !== undefined && created.has(diagnostic.path)) {
|
|
158
|
+
introduced.push(diagnostic);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const key = keyFor(diagnostic);
|
|
162
|
+
const left = remaining.get(key) ?? 0;
|
|
163
|
+
if (left > 0)
|
|
164
|
+
remaining.set(key, left - 1);
|
|
165
|
+
else
|
|
166
|
+
introduced.push(diagnostic);
|
|
167
|
+
}
|
|
168
|
+
return introduced;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=program-diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-diagnostics.js","sourceRoot":"","sources":["../../../src/agents/direct/program-diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type ProjectDiagnostic } from "./program-diagnostics.ts";
|
|
2
|
+
import type { ConversionUnit, GeneratedConversionUnit } from "./types.ts";
|
|
3
|
+
export interface StagedRepairRequest {
|
|
4
|
+
unit: ConversionUnit;
|
|
5
|
+
/** Project-relative path of the candidate being repaired. */
|
|
6
|
+
targetPath: string;
|
|
7
|
+
/** The unit's current generated code (whole file contents). */
|
|
8
|
+
currentCode: string;
|
|
9
|
+
/** Normalized new diagnostics attributed to this candidate's dependency group. */
|
|
10
|
+
diagnostics: ProjectDiagnostic[];
|
|
11
|
+
/** Other generated candidate files in the same dependency group. */
|
|
12
|
+
relatedFiles: Array<{
|
|
13
|
+
path: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export type StagedValidationProgress = {
|
|
18
|
+
kind: "project-validate";
|
|
19
|
+
files: number;
|
|
20
|
+
pass: number;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "repair";
|
|
23
|
+
unit: ConversionUnit;
|
|
24
|
+
attempt: number;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "reject";
|
|
27
|
+
unit: ConversionUnit;
|
|
28
|
+
reason: string;
|
|
29
|
+
};
|
|
30
|
+
export interface StagedValidationOptions {
|
|
31
|
+
/** Bounded cross-file repair callback; omitted means failing groups are rejected directly. */
|
|
32
|
+
repair?: (request: StagedRepairRequest) => Promise<string>;
|
|
33
|
+
/** Repair requests allowed per whole-file unit (default 1). */
|
|
34
|
+
maxRepairAttemptsPerUnit?: number;
|
|
35
|
+
/** Character budget for one repair request's code-and-diagnostics context. */
|
|
36
|
+
contextCharBudget?: number;
|
|
37
|
+
onProgress?: (event: StagedValidationProgress) => void;
|
|
38
|
+
}
|
|
39
|
+
export interface StagedValidationOutcome {
|
|
40
|
+
/** One result per input unit, in input order; rejected units carry `error`. */
|
|
41
|
+
results: GeneratedConversionUnit[];
|
|
42
|
+
/** True when a combined candidate program was actually type-checked. */
|
|
43
|
+
validated: boolean;
|
|
44
|
+
/** Number of bounded repair requests issued. */
|
|
45
|
+
repairRequests: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate the combined candidate project before anything is written and
|
|
49
|
+
* return per-unit accept/reject results. Units that do not produce JS/TS are
|
|
50
|
+
* passed through unchanged and keep their per-unit validation level.
|
|
51
|
+
*/
|
|
52
|
+
export declare function validateCandidateProject(root: string, generated: readonly GeneratedConversionUnit[], options?: StagedValidationOptions): Promise<StagedValidationOutcome>;
|
|
53
|
+
//# sourceMappingURL=staged-validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staged-validation.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/staged-validation.ts"],"names":[],"mappings":"AAeA,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,cAAc,CAAC;IACrB,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,oEAAoE;IACpE,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7D,MAAM,WAAW,uBAAuB;IACtC,8FAA8F;IAC9F,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,+DAA+D;IAC/D,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,uBAAuB;IACtC,+EAA+E;IAC/E,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;CACxB;AA0BD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,uBAAuB,EAAE,EAC7C,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,uBAAuB,CAAC,CAuGlC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staged, project-aware validation for multi-file JS/TS direct conversions.
|
|
3
|
+
* All successfully generated units enter an in-memory candidate overlay; the
|
|
4
|
+
* combined candidate project is compiled with the TypeScript Compiler API and
|
|
5
|
+
* compared against the unchanged baseline. Dependency-connected groups that
|
|
6
|
+
* introduce new diagnostics are repaired within a bounded budget or rejected
|
|
7
|
+
* whole, and only units proven independent of every failure are applied.
|
|
8
|
+
*
|
|
9
|
+
* This is static compiler validation: no project code is imported, executed,
|
|
10
|
+
* or sandboxed here, and passing it is never presented as `VERIFIED`.
|
|
11
|
+
*/
|
|
12
|
+
import { ContextSecurityError, scanSecrets } from "../../context/context.js";
|
|
13
|
+
import { buildCandidateOverlay } from "./candidate-overlay.js";
|
|
14
|
+
import { validateGeneratedUnit } from "./candidate-validation.js";
|
|
15
|
+
import { attributeDiagnostics, buildOverlayDependencyGroups } from "./dependency-graph.js";
|
|
16
|
+
import { collectProjectDiagnostics, createValidationProgramContext, newlyIntroducedProjectDiagnostics, } from "./program-diagnostics.js";
|
|
17
|
+
const MAX_DIAGNOSTICS_PER_REQUEST = 20;
|
|
18
|
+
const MAX_DIAGNOSTIC_MESSAGE_LENGTH = 400;
|
|
19
|
+
const DEFAULT_CONTEXT_CHAR_BUDGET = 48_000;
|
|
20
|
+
/** Strip control characters so compiler output stays plain, single-line data. */
|
|
21
|
+
function sanitizeDiagnostic(diagnostic) {
|
|
22
|
+
const message = diagnostic.message
|
|
23
|
+
.replace(/[\u0000-\u0008\u000b-\u001f\u007f]/gu, " ")
|
|
24
|
+
.replace(/\r?\n/gu, " ")
|
|
25
|
+
.slice(0, MAX_DIAGNOSTIC_MESSAGE_LENGTH);
|
|
26
|
+
return { ...diagnostic, message };
|
|
27
|
+
}
|
|
28
|
+
function describeDiagnostics(diagnostics) {
|
|
29
|
+
const shown = diagnostics.slice(0, 3).map((diagnostic) => {
|
|
30
|
+
const location = diagnostic.path === undefined
|
|
31
|
+
? "project"
|
|
32
|
+
: `${diagnostic.path}${diagnostic.line !== undefined ? `:${diagnostic.line}` : ""}`;
|
|
33
|
+
return `${location} TS${diagnostic.code} ${sanitizeDiagnostic(diagnostic).message}`;
|
|
34
|
+
});
|
|
35
|
+
const more = diagnostics.length - shown.length;
|
|
36
|
+
return `${shown.join("; ")}${more > 0 ? ` (+${more} more)` : ""}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Validate the combined candidate project before anything is written and
|
|
40
|
+
* return per-unit accept/reject results. Units that do not produce JS/TS are
|
|
41
|
+
* passed through unchanged and keep their per-unit validation level.
|
|
42
|
+
*/
|
|
43
|
+
export async function validateCandidateProject(root, generated, options = {}) {
|
|
44
|
+
const results = generated.map((item) => ({ ...item }));
|
|
45
|
+
const maxRepairAttempts = Math.max(0, options.maxRepairAttemptsPerUnit ?? 1);
|
|
46
|
+
const contextCharBudget = options.contextCharBudget ?? DEFAULT_CONTEXT_CHAR_BUDGET;
|
|
47
|
+
const initialOverlay = await buildCandidateOverlay(root, results);
|
|
48
|
+
applyOverlayExclusions(results, initialOverlay, options);
|
|
49
|
+
if (initialOverlay.files.size === 0) {
|
|
50
|
+
return { results, validated: false, repairRequests: 0 };
|
|
51
|
+
}
|
|
52
|
+
const context = await createValidationProgramContext(root);
|
|
53
|
+
const baseline = collectProjectDiagnostics(context);
|
|
54
|
+
const repairAttempts = new Map();
|
|
55
|
+
let repairRequests = 0;
|
|
56
|
+
const activeUnits = new Set();
|
|
57
|
+
for (const file of initialOverlay.files.values())
|
|
58
|
+
for (const unit of file.units)
|
|
59
|
+
activeUnits.add(unit);
|
|
60
|
+
const maxPasses = activeUnits.size * (1 + maxRepairAttempts) + 2;
|
|
61
|
+
const rejectUnit = (unit, reason) => {
|
|
62
|
+
const item = results.find((entry) => entry.unit === unit);
|
|
63
|
+
if (!item || item.error !== undefined)
|
|
64
|
+
return;
|
|
65
|
+
item.error = reason;
|
|
66
|
+
item.code = "";
|
|
67
|
+
options.onProgress?.({ kind: "reject", unit, reason });
|
|
68
|
+
};
|
|
69
|
+
for (let pass = 1; pass <= maxPasses; pass += 1) {
|
|
70
|
+
const overlay = await buildCandidateOverlay(root, results);
|
|
71
|
+
applyOverlayExclusions(results, overlay, options);
|
|
72
|
+
if (overlay.files.size === 0)
|
|
73
|
+
break;
|
|
74
|
+
options.onProgress?.({ kind: "project-validate", files: overlay.files.size, pass });
|
|
75
|
+
const candidate = collectProjectDiagnostics(context, overlay);
|
|
76
|
+
const introduced = newlyIntroducedProjectDiagnostics(baseline, candidate, overlay);
|
|
77
|
+
if (introduced.length === 0)
|
|
78
|
+
break;
|
|
79
|
+
const attribution = attributeDiagnostics(introduced, overlay, context);
|
|
80
|
+
if (attribution.unattributed.length > 0) {
|
|
81
|
+
// Safe isolation cannot be proven, so the whole staged batch fails
|
|
82
|
+
// closed instead of writing a possibly-broken partial application.
|
|
83
|
+
const reason = `combined project validation introduced errors that could not be safely attributed: ${describeDiagnostics(attribution.unattributed)}`;
|
|
84
|
+
for (const file of overlay.files.values())
|
|
85
|
+
for (const unit of file.units)
|
|
86
|
+
rejectUnit(unit, reason);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
const groups = buildOverlayDependencyGroups(overlay, context);
|
|
90
|
+
const groupDiagnostics = new Map();
|
|
91
|
+
for (const [key, diagnostics] of attribution.byFile) {
|
|
92
|
+
const group = groups.groupOf.get(key);
|
|
93
|
+
groupDiagnostics.set(group, [...(groupDiagnostics.get(group) ?? []), ...diagnostics]);
|
|
94
|
+
}
|
|
95
|
+
let repaired = false;
|
|
96
|
+
if (options.repair && maxRepairAttempts > 0) {
|
|
97
|
+
for (const [key, diagnostics] of attribution.byFile) {
|
|
98
|
+
const file = overlay.files.get(key);
|
|
99
|
+
// Only whole-file candidates are repairable; an inline-modified file
|
|
100
|
+
// may hold several markers whose replacements cannot be regenerated
|
|
101
|
+
// independently without guessing, so its group fails closed instead.
|
|
102
|
+
if (!file.created || file.units.length !== 1)
|
|
103
|
+
continue;
|
|
104
|
+
const unit = file.units[0];
|
|
105
|
+
const attempts = repairAttempts.get(unit) ?? 0;
|
|
106
|
+
if (attempts >= maxRepairAttempts)
|
|
107
|
+
continue;
|
|
108
|
+
repairAttempts.set(unit, attempts + 1);
|
|
109
|
+
const item = results.find((entry) => entry.unit === unit);
|
|
110
|
+
const group = groups.groupOf.get(key);
|
|
111
|
+
const request = buildRepairRequest(unit, item.code, overlay, key, groups.members.get(group) ?? [], [
|
|
112
|
+
...(groupDiagnostics.get(group) ?? diagnostics),
|
|
113
|
+
], contextCharBudget);
|
|
114
|
+
if (scanSecrets(`${request.currentCode}\n${request.relatedFiles.map((entry) => entry.content).join("\n")}`).length > 0) {
|
|
115
|
+
// Never send credential-like content in repair context; the unit
|
|
116
|
+
// simply stays unrepaired and its group is rejected on the next pass.
|
|
117
|
+
repairAttempts.set(unit, maxRepairAttempts);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
options.onProgress?.({ kind: "repair", unit, attempt: attempts + 1 });
|
|
121
|
+
repairRequests += 1;
|
|
122
|
+
try {
|
|
123
|
+
const repairedCode = await options.repair(request);
|
|
124
|
+
if (repairedCode.trim().length === 0 || repairedCode === item.code)
|
|
125
|
+
continue;
|
|
126
|
+
await validateGeneratedUnit(unit, repairedCode);
|
|
127
|
+
item.code = repairedCode;
|
|
128
|
+
repaired = true;
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error instanceof ContextSecurityError)
|
|
132
|
+
throw error;
|
|
133
|
+
// A failed or invalid repair keeps the previous candidate; the
|
|
134
|
+
// attempt budget is already consumed.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (repaired)
|
|
139
|
+
continue;
|
|
140
|
+
for (const [group, diagnostics] of groupDiagnostics) {
|
|
141
|
+
const reason = `combined project validation failed for this dependency group: ${describeDiagnostics(diagnostics)}`;
|
|
142
|
+
for (const key of groups.members.get(group) ?? []) {
|
|
143
|
+
for (const unit of overlay.files.get(key).units)
|
|
144
|
+
rejectUnit(unit, reason);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { results, validated: true, repairRequests };
|
|
149
|
+
}
|
|
150
|
+
function applyOverlayExclusions(results, overlay, options) {
|
|
151
|
+
for (const { unit, reason } of overlay.excluded) {
|
|
152
|
+
const item = results.find((entry) => entry.unit === unit);
|
|
153
|
+
if (!item || item.error !== undefined)
|
|
154
|
+
continue;
|
|
155
|
+
item.error = reason;
|
|
156
|
+
item.code = "";
|
|
157
|
+
options.onProgress?.({ kind: "reject", unit, reason });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function buildRepairRequest(unit, currentCode, overlay, ownKey, groupKeys, diagnostics, contextCharBudget) {
|
|
161
|
+
const normalized = diagnostics.slice(0, MAX_DIAGNOSTICS_PER_REQUEST).map(sanitizeDiagnostic);
|
|
162
|
+
let budget = Math.max(0, contextCharBudget - currentCode.length);
|
|
163
|
+
const relatedFiles = [];
|
|
164
|
+
const related = groupKeys
|
|
165
|
+
.filter((key) => key !== ownKey)
|
|
166
|
+
.map((key) => overlay.files.get(key))
|
|
167
|
+
.sort((left, right) => left.path.localeCompare(right.path));
|
|
168
|
+
for (const file of related) {
|
|
169
|
+
if (file.content.length > budget)
|
|
170
|
+
continue;
|
|
171
|
+
relatedFiles.push({ path: file.path, content: file.content });
|
|
172
|
+
budget -= file.content.length;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
unit,
|
|
176
|
+
targetPath: unit.kind === "file" ? unit.outputPath : unit.sourcePath,
|
|
177
|
+
currentCode,
|
|
178
|
+
diagnostics: normalized,
|
|
179
|
+
relatedFiles,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=staged-validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staged-validation.js","sourceRoot":"","sources":["../../../src/agents/direct/staged-validation.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,sGAAsG;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,sGAAsG;AA+wBtG,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiFzD"}
|
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ import { PlanningError, contractPathForSource, createDraftContract, loadReviewed
|
|
|
14
14
|
import { ProviderError } from "./providers/provider.js";
|
|
15
15
|
import { createOllamaProvider, createOpenAIProvider } from "./providers/providers.js";
|
|
16
16
|
import { RunStore } from "./pipeline/run-store.js";
|
|
17
|
-
import { applyUnit, discoverDirectUnits, generateConversionUnits, generateCode, renderReceipt, validateGeneratedUnit, } from "./agents/direct/index.js";
|
|
17
|
+
import { applyUnit, discoverDirectUnits, generateConversionUnits, generateCode, generateRepairCode, renderReceipt, validateCandidateProject, validateGeneratedUnit, } from "./agents/direct/index.js";
|
|
18
18
|
import { applyVerifiedRun, buildContextPreview, generateRun, resolveWorkspaceConfig, rollbackAppliedRun, validateStoredRun, } from "./agents/guided/index.js";
|
|
19
19
|
const HELP = `human-to-code — reviewed, grounded, isolated human-to-code compiler agent
|
|
20
20
|
|
|
@@ -556,6 +556,56 @@ async function buildCommand(cli, rootInput) {
|
|
|
556
556
|
output(cli.json ? { status: "FAILED", error: message } : `\nError: ${message}`, cli.json);
|
|
557
557
|
return 5;
|
|
558
558
|
}
|
|
559
|
+
// Staged project-aware validation: every accepted JS/TS unit joins an
|
|
560
|
+
// in-memory candidate overlay that is type-checked as one TypeScript
|
|
561
|
+
// program against the unchanged baseline before any file is written.
|
|
562
|
+
// Dependency-connected groups that introduce cross-file errors get one
|
|
563
|
+
// bounded repair request per whole-file unit, then fail closed together.
|
|
564
|
+
let repairRequests = 0;
|
|
565
|
+
try {
|
|
566
|
+
const onStagedProgress = interactive
|
|
567
|
+
? (event) => {
|
|
568
|
+
if (event.kind === "project-validate") {
|
|
569
|
+
spinner.label(`validating combined candidate project (${event.files} file(s), pass ${event.pass})`);
|
|
570
|
+
}
|
|
571
|
+
else if (event.kind === "repair") {
|
|
572
|
+
spinner.label(`repairing ${describeUnit(event.unit)} (bounded repair ${event.attempt})`);
|
|
573
|
+
}
|
|
574
|
+
else if (event.kind === "reject") {
|
|
575
|
+
spinner.note(` ⊘ skipped ${describeUnit(event.unit)}: ${event.reason}`);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
: undefined;
|
|
579
|
+
const staged = await validateCandidateProject(root, generated, {
|
|
580
|
+
maxRepairAttemptsPerUnit: 1,
|
|
581
|
+
contextCharBudget: effective.privacy.maxContextTokens * 4,
|
|
582
|
+
repair: (request) => generateRepairCode({
|
|
583
|
+
targetPath: request.targetPath,
|
|
584
|
+
inline: request.unit.kind === "inline",
|
|
585
|
+
instruction: request.unit.prompt,
|
|
586
|
+
currentCode: request.currentCode,
|
|
587
|
+
diagnostics: request.diagnostics,
|
|
588
|
+
relatedFiles: request.relatedFiles,
|
|
589
|
+
}, {
|
|
590
|
+
language,
|
|
591
|
+
provider: providerName,
|
|
592
|
+
model,
|
|
593
|
+
...(baseUrl ? { baseUrl } : {}),
|
|
594
|
+
...(apiKey ? { apiKey } : {}),
|
|
595
|
+
}),
|
|
596
|
+
...(onStagedProgress ? { onProgress: onStagedProgress } : {}),
|
|
597
|
+
});
|
|
598
|
+
generated = staged.results;
|
|
599
|
+
repairRequests = staged.repairRequests;
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
spinner.stop();
|
|
603
|
+
if (error instanceof ContextSecurityError)
|
|
604
|
+
throw error;
|
|
605
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
606
|
+
output(cli.json ? { status: "FAILED", error: message } : `\nError: ${message}`, cli.json);
|
|
607
|
+
return 5;
|
|
608
|
+
}
|
|
559
609
|
spinner.stop();
|
|
560
610
|
// Apply bottom-to-top so replacing a later marker cannot invalidate an
|
|
561
611
|
// earlier marker's range.
|
|
@@ -595,10 +645,11 @@ async function buildCommand(cli, rootInput) {
|
|
|
595
645
|
}
|
|
596
646
|
const seconds = Math.round((Date.now() - started) / 1000);
|
|
597
647
|
if (cli.json) {
|
|
598
|
-
output({ status: written.length === 0 && skipped.length > 0 ? "FAILED" : "DONE", engine: "simple", written, skipped }, true);
|
|
648
|
+
output({ status: written.length === 0 && skipped.length > 0 ? "FAILED" : "DONE", engine: "simple", written, skipped, repairRequests }, true);
|
|
599
649
|
}
|
|
600
650
|
else {
|
|
601
|
-
|
|
651
|
+
const repairs = repairRequests > 0 ? `, ${repairRequests} bounded repair request(s)` : "";
|
|
652
|
+
output(`\nDone in ${seconds}s. ${written.length} written${skipped.length > 0 ? `, ${skipped.length} skipped` : ""}${repairs}.`, false);
|
|
602
653
|
}
|
|
603
654
|
return written.length === 0 && skipped.length > 0 ? 5 : 0;
|
|
604
655
|
}
|