human-to-code 0.1.17 → 0.1.19

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 (63) hide show
  1. package/Readme.md +19 -8
  2. package/SECURITY.md +22 -5
  3. package/dist/agents/direct/candidate-overlay.d.ts +36 -0
  4. package/dist/agents/direct/candidate-overlay.d.ts.map +1 -0
  5. package/dist/agents/direct/candidate-overlay.js +123 -0
  6. package/dist/agents/direct/candidate-overlay.js.map +1 -0
  7. package/dist/agents/direct/candidate-validation.d.ts.map +1 -1
  8. package/dist/agents/direct/candidate-validation.js +6 -0
  9. package/dist/agents/direct/candidate-validation.js.map +1 -1
  10. package/dist/agents/direct/dependency-graph.d.ts +25 -0
  11. package/dist/agents/direct/dependency-graph.d.ts.map +1 -0
  12. package/dist/agents/direct/dependency-graph.js +140 -0
  13. package/dist/agents/direct/dependency-graph.js.map +1 -0
  14. package/dist/agents/direct/discovery.d.ts +4 -2
  15. package/dist/agents/direct/discovery.d.ts.map +1 -1
  16. package/dist/agents/direct/discovery.js +19 -3
  17. package/dist/agents/direct/discovery.js.map +1 -1
  18. package/dist/agents/direct/generation-client.d.ts +11 -0
  19. package/dist/agents/direct/generation-client.d.ts.map +1 -1
  20. package/dist/agents/direct/generation-client.js +20 -9
  21. package/dist/agents/direct/generation-client.js.map +1 -1
  22. package/dist/agents/direct/index.d.ts +4 -0
  23. package/dist/agents/direct/index.d.ts.map +1 -1
  24. package/dist/agents/direct/index.js +4 -0
  25. package/dist/agents/direct/index.js.map +1 -1
  26. package/dist/agents/direct/languages.d.ts +1 -0
  27. package/dist/agents/direct/languages.d.ts.map +1 -1
  28. package/dist/agents/direct/languages.js +13 -0
  29. package/dist/agents/direct/languages.js.map +1 -1
  30. package/dist/agents/direct/presentation.d.ts +1 -1
  31. package/dist/agents/direct/presentation.d.ts.map +1 -1
  32. package/dist/agents/direct/presentation.js +10 -4
  33. package/dist/agents/direct/presentation.js.map +1 -1
  34. package/dist/agents/direct/program-diagnostics.d.ts +39 -0
  35. package/dist/agents/direct/program-diagnostics.d.ts.map +1 -0
  36. package/dist/agents/direct/program-diagnostics.js +170 -0
  37. package/dist/agents/direct/program-diagnostics.js.map +1 -0
  38. package/dist/agents/direct/staged-validation.d.ts +53 -0
  39. package/dist/agents/direct/staged-validation.d.ts.map +1 -0
  40. package/dist/agents/direct/staged-validation.js +182 -0
  41. package/dist/agents/direct/staged-validation.js.map +1 -0
  42. package/dist/agents/direct/types.d.ts +2 -0
  43. package/dist/agents/direct/types.d.ts.map +1 -1
  44. package/dist/cli.d.ts.map +1 -1
  45. package/dist/cli.js +59 -6
  46. package/dist/cli.js.map +1 -1
  47. package/dist/config/config.d.ts.map +1 -1
  48. package/dist/config/config.js +28 -0
  49. package/dist/config/config.js.map +1 -1
  50. package/dist/core/types.d.ts +7 -1
  51. package/dist/core/types.d.ts.map +1 -1
  52. package/dist/prompts/direct-repair.d.ts +30 -0
  53. package/dist/prompts/direct-repair.d.ts.map +1 -0
  54. package/dist/prompts/direct-repair.js +34 -0
  55. package/dist/prompts/direct-repair.js.map +1 -0
  56. package/dist/prompts/index.d.ts +1 -0
  57. package/dist/prompts/index.d.ts.map +1 -1
  58. package/dist/prompts/index.js +1 -0
  59. package/dist/prompts/index.js.map +1 -1
  60. package/docs/ARCHITECTURE.md +22 -8
  61. package/docs/MODULES.md +7 -1
  62. package/docs/SCALABILITY.md +9 -3
  63. package/package.json +3 -4
package/Readme.md CHANGED
@@ -57,9 +57,10 @@ By default this runs the **direct converter**, not an instruction to rewrite the
57
57
  2. Reports marker-shaped requests in unsupported file types and refuses a `.human` request whose sibling output already exists. Intentionally ignored directories and symlinks remain outside discovery.
58
58
  3. Prints a receipt (language, provider, model, and the exact worklist) and asks for confirmation. Nothing is written until you confirm — or pass `-y`/`--yes`. If no request is found it returns `NEEDS_INPUT`.
59
59
  4. On confirmation, converts each item with one model completion per unit, extracts one unambiguous code block, and validates the complete candidate before writing. JavaScript and TypeScript use the TypeScript parser; other supported languages receive a deterministic structural syntax check. Inline validation compares the candidate with the original file and rejects only syntax errors introduced by that replacement, without blaming it for unchanged baseline errors.
60
- 5. Applies each accepted item defensively: new sibling files use exclusive creation, inline markers must still match the bytes found during discovery, and multi-line replacements inherit the marker's indentation. A failing or stale item is skipped with a reason rather than aborting the rest.
60
+ 5. For JavaScript/TypeScript output, additionally stages every accepted unit into an in-memory candidate overlay and type-checks the combined candidate project with the TypeScript Compiler API — imports/exports, methods and properties, argument counts, literal unions, object shapes, readonly rules, and call compatibility across the generated files together. Diagnostics are compared against the unchanged baseline, so pre-existing project errors are never blamed on generated units. A dependency-connected group that introduces new cross-file errors receives at most one bounded repair request per whole-file unit (same provider and model); if it still fails it is skipped **whole** never partially written while units proven independent still apply. Other direct languages keep their per-file validation level.
61
+ 6. Applies each accepted item defensively: new sibling files use exclusive creation, inline markers must still match the bytes found during discovery, and multi-line replacements inherit the marker's indentation. A failing or stale item is skipped with a reason rather than aborting the rest.
61
62
 
62
- The direct converter writes code straight to the working tree. Its syntax gate catches malformed output; it does **not** prove API correctness, run project builds or tests, execute code in a sandbox, create a `.strict.human.json` change contract, produce a `VERIFIED` run, or perform the guided pipeline's repository-wide secret scan — only the indexed declarations it attaches to an inline prompt as context are secret-scanned (a finding is `SECURITY_BLOCKED`). For the reviewed contract → grounding → sandbox-validation lifecycle — where the `.strict.human.json` contract and the `VERIFIED`/`apply`/`rollback` machinery live — use `human-to-code guided` (see [The reviewed change contract](#the-reviewed-change-contract) and the [CLI](#cli) table).
63
+ The direct converter writes code straight to the working tree. Its combined static compiler validation for JS/TS is stronger than syntax parsing, but it is still static analysis: it does **not** execute or import project code, run project builds or tests, prove runtime behavior or external-API grounding, execute code in a sandbox, create a `.strict.human.json` change contract, produce a `VERIFIED` run, or perform the guided pipeline's repository-wide secret scan — only the indexed declarations it attaches to an inline prompt as context are secret-scanned (a finding is `SECURITY_BLOCKED`). For the reviewed contract → grounding → sandbox-validation lifecycle — where the `.strict.human.json` contract and the `VERIFIED`/`apply`/`rollback` machinery live — use `human-to-code guided` (see [The reviewed change contract](#the-reviewed-change-contract) and the [CLI](#cli) table).
63
64
 
64
65
  No configured provider is needed to scan and preview. A default run selects loopback-local Ollama with `qwen2.5-coder:7b`, so a fresh `npx human-to-code .` never transmits code remotely by default. The model must already be installed; the tool never pulls it implicitly. To use another local model, OpenAI, or Ollama Cloud, create and edit a config (the command never overwrites one):
65
66
 
@@ -118,9 +119,12 @@ not opened merely to produce a notice.
118
119
 
119
120
  The host does the orchestration; the model only writes code. For each unit the
120
121
  host issues **one plain model completion** (no tool calls) and applies the
121
- result by exact marker range. This is fast and works with small models — a 1.5B
122
- coder model converts a four-marker file in ~4 seconds. Because it needs no
123
- tool-calling, models that can only do plain text generation work fine.
122
+ result by exact marker range; when combined JS/TS project validation finds a
123
+ repairable cross-file error, a whole-file unit may receive **one additional
124
+ bounded repair completion** with the same provider and model. This is fast and
125
+ works with small models — a 1.5B coder model converts a four-marker file in
126
+ ~4 seconds. Because it needs no tool-calling, models that can only do plain
127
+ text generation work fine.
124
128
 
125
129
  - **Per-marker isolation** — each `@human` marker is generated and applied
126
130
  independently. If one marker's output is bad (e.g. a small model redeclares an
@@ -133,6 +137,13 @@ tool-calling, models that can only do plain text generation work fine.
133
137
  - **Candidate and write guards** — ambiguous fenced responses and malformed
134
138
  candidates are retried; existing sibling files, stale inline markers, and
135
139
  unsafe indentation changes are refused before mutation.
140
+ - **Combined project validation (JS/TS)** — all accepted JavaScript/TypeScript
141
+ units are staged into an in-memory overlay and type-checked together with
142
+ the TypeScript Compiler API before any write. Newly introduced cross-file
143
+ diagnostics reject the whole dependency-connected group (after at most one
144
+ bounded repair attempt per whole-file unit); independent units still apply.
145
+ Pre-existing baseline errors are never attributed to generated code. This is
146
+ static compilation, not sandbox execution, runtime testing, or API grounding.
136
147
  - **Clear, stable output** — a single truncated status line per marker
137
148
  (`✓ app.ts (inline @human, line 12)` / `⊘ skipped … : <reason>`), plus an
138
149
  in-place elapsed spinner while a completion is in flight.
@@ -163,7 +174,7 @@ The draft is deliberately conservative. Do not remove its review question until
163
174
 
164
175
  | Command | Behavior |
165
176
  | --- | --- |
166
- | `human-to-code [root]` | Default direct flow: discover `.human` files and `@human` markers, show a receipt, and on confirmation convert them with the **fast deterministic engine** (one plain model completion per marker; see below). `npx human-to-code .` is the normal entry point. |
177
+ | `human-to-code [root]` | Default direct flow: discover `.human` files and `@human` markers, show a receipt, and on confirmation convert them with the **fast deterministic engine** (one plain model completion per marker, plus at most one bounded cross-file repair completion per whole-file JS/TS unit; see below). `npx human-to-code .` is the normal entry point. |
167
178
  | `human-to-code guided [root]` | Reviewed contract → grounding → sandbox-validation lifecycle. The only path that can reach `VERIFIED`. |
168
179
  | `human-to-code analyze [root] [--json]` | Produce a deterministic multi-workspace project profile and diagnostics. `SUPPORTED` means statically recognized, not certified. |
169
180
  | `human-to-code plan <file.human> [--root <root>]` | Write a review-blocked `ChangeContractV1` draft. |
@@ -205,7 +216,7 @@ This complete local-Ollama example shows the policy fields:
205
216
  ```json
206
217
  {
207
218
  "schemaVersion": 1,
208
- "language": "typescript",
219
+ "languages": ["typescript", "html", "css"],
209
220
  "filesToIgnore": ["node_modules", ".git", "dist"],
210
221
  "allowNonHumanFiles": false,
211
222
  "provider": {
@@ -242,7 +253,7 @@ This complete local-Ollama example shows the policy fields:
242
253
  }
243
254
  ```
244
255
 
245
- `language` is retained for alpha compatibility; static workspace analysis is authoritative in mixed-language repositories. `filesToIgnore` accepts exact file/directory names, not glob expressions. With `sandbox.engine: "auto"`, validation probes Docker first and then Podman; `"docker"` and `"podman"` select one explicitly. Neither runtime being available makes validation `INCONCLUSIVE` and runs no project command.
256
+ `languages` lists every output language enabled for direct conversion (`typescript`, `javascript`, `python`, `rust`, `html`, `css`); its first entry is the default. A `.human` file selects a non-default entry through its inner extension: with the example above, `index.html.human` writes `index.html` and `styles.css.human` writes `styles.css`, while `app.human` falls back to the first entry and writes `app.ts`. An inner extension whose language is not configured is treated as part of the file name. The singular `language` is retained for alpha compatibility and, when set alongside `languages`, must be one of its entries; static workspace analysis is authoritative in mixed-language repositories. `filesToIgnore` accepts exact file/directory names, not glob expressions. With `sandbox.engine: "auto"`, validation probes Docker first and then Podman; `"docker"` and `"podman"` select one explicitly. Neither runtime being available makes validation `INCONCLUSIVE` and runs no project command.
246
257
 
247
258
  ### Budget semantics
248
259
 
package/SECURITY.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `human-to-code` reads attacker-controlled repositories, sends selected evidence to an LLM provider, and may execute project validation commands. The project therefore treats repository content, model output, documentation, provider endpoints, and build/test tooling as untrusted.
4
4
 
5
- Version `0.1.16` is a preview. The shipped ecosystem and provider/model combinations are not certified, so guided generated runs do not reach `VERIFIED` through the CLI and guided automatic application/rollback remain unreachable for normal generated runs. The default direct converter is a separate convenience path that writes accepted units to the working tree after confirmation; it never claims `VERIFIED`. Do not weaken either boundary to make a preview run appear successful.
5
+ Version `0.1.17` is a preview. The shipped ecosystem and provider/model combinations are not certified, so guided generated runs do not reach `VERIFIED` through the CLI and guided automatic application/rollback remain unreachable for normal generated runs. The default direct converter is a separate convenience path that writes accepted units to the working tree after confirmation; it never claims `VERIFIED`. Do not weaken either boundary to make a preview run appear successful.
6
6
 
7
7
  ## Trust boundaries
8
8
 
@@ -34,11 +34,28 @@ verifies exact inline marker bytes again at apply time,
34
34
  and preserves marker indentation. Invalid or stale units are retried within the
35
35
  bounded generation policy and then skipped without mutation.
36
36
 
37
+ JavaScript/TypeScript units additionally pass staged combined validation: the
38
+ generated files form an in-memory candidate overlay, the working tree stays
39
+ unchanged, and the TypeScript Compiler API type-checks the combined candidate
40
+ project against the unchanged baseline. Newly introduced cross-file
41
+ diagnostics (wrong imports/exports, missing members, argument counts, literal
42
+ unions, object shapes, readonly violations, incompatible calls) reject the
43
+ whole dependency-connected group; if safe isolation cannot be proven, the
44
+ entire staged batch fails without partial application. A failing whole-file
45
+ unit may receive one bounded repair request using the same provider and model;
46
+ repair context contains only generated candidate content and normalized
47
+ compiler diagnostics, both treated as untrusted data, and is secret-scanned
48
+ before it may leave the host. No project code is imported or executed and no
49
+ project scripts run during this validation.
50
+
37
51
  These controls prevent the specific malformed-output, overwrite, stale-range,
38
- and indentation failures they check. They do not prove external APIs, types,
39
- project-wide behavior, security properties, or test success, and they do not
40
- execute the candidate in a sandbox. Use the guided contract and validation path
41
- when those stronger boundaries are required.
52
+ indentation, and cross-file-contract failures they check. Static compilation
53
+ is stronger than syntax parsing, but it does not prove runtime behavior,
54
+ external-API grounding, project-wide security properties, or test success,
55
+ and it never executes the candidate in a sandbox or claims `VERIFIED`. Other
56
+ direct languages keep their per-file structural validation level. Use the
57
+ guided contract and validation path when those stronger boundaries are
58
+ required.
42
59
 
43
60
  ### The reviewed contract owns authority
44
61
 
@@ -0,0 +1,36 @@
1
+ import type { ConversionUnit, GeneratedConversionUnit } from "./types.ts";
2
+ /** Extensions that participate in combined TypeScript program validation. */
3
+ export declare const PROJECT_VALIDATION_EXTENSIONS: Set<string>;
4
+ export interface CandidateOverlayFile {
5
+ /** Project-relative POSIX path of the candidate file. */
6
+ path: string;
7
+ /** Absolute path used as the TypeScript program file name. */
8
+ absolutePath: string;
9
+ /** Complete candidate content (baseline plus replacements, or the new file). */
10
+ content: string;
11
+ /** True when the path does not exist in the working tree yet. */
12
+ created: boolean;
13
+ /** The generated units contributing to this candidate file. */
14
+ units: ConversionUnit[];
15
+ }
16
+ export interface CandidateOverlay {
17
+ root: string;
18
+ /** Overlay files keyed by {@link overlayPathKey} of their absolute path. */
19
+ files: Map<string, CandidateOverlayFile>;
20
+ /** Units that could not enter the overlay, with the fail-closed reason. */
21
+ excluded: Array<{
22
+ unit: ConversionUnit;
23
+ reason: string;
24
+ }>;
25
+ }
26
+ /** Canonical map key for absolute paths, honoring platform case sensitivity. */
27
+ export declare function overlayPathKey(path: string): string;
28
+ /** True when this generated unit belongs in the combined JS/TS overlay. */
29
+ export declare function unitParticipatesInProjectValidation(item: GeneratedConversionUnit): boolean;
30
+ /**
31
+ * Build the combined in-memory candidate state for all successful JS/TS units.
32
+ * The working tree is never modified; stale inline markers and already-existing
33
+ * whole-file targets are excluded fail-closed instead of guessed around.
34
+ */
35
+ export declare function buildCandidateOverlay(root: string, generated: readonly GeneratedConversionUnit[]): Promise<CandidateOverlay>;
36
+ //# sourceMappingURL=candidate-overlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-overlay.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/candidate-overlay.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAE1E,6EAA6E;AAC7E,eAAO,MAAM,6BAA6B,aAA0D,CAAC;AAErG,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;IACjB,+DAA+D;IAC/D,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IACzC,2EAA2E;IAC3E,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD;AAMD,2EAA2E;AAC3E,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAI1F;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,SAAS,uBAAuB,EAAE,GAC5C,OAAO,CAAC,gBAAgB,CAAC,CAwF3B"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * In-memory candidate overlay for staged multi-file validation. The overlay
3
+ * combines every successfully generated whole-file output and inline
4
+ * replacement without touching the working tree, so the combined candidate
5
+ * project can be validated before any write occurs.
6
+ */
7
+ import { readFile, stat } from "node:fs/promises";
8
+ import { extname, resolve, sep } from "node:path";
9
+ import ts from "typescript";
10
+ import { replaceInlineMarker } from "./replacement.js";
11
+ /** Extensions that participate in combined TypeScript program validation. */
12
+ export const PROJECT_VALIDATION_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
13
+ /** Canonical map key for absolute paths, honoring platform case sensitivity. */
14
+ export function overlayPathKey(path) {
15
+ const normalized = resolve(path).split(sep).join("/");
16
+ return ts.sys.useCaseSensitiveFileNames ? normalized : normalized.toLowerCase();
17
+ }
18
+ function isValidationExtension(path) {
19
+ return PROJECT_VALIDATION_EXTENSIONS.has(extname(path).toLowerCase());
20
+ }
21
+ /** True when this generated unit belongs in the combined JS/TS overlay. */
22
+ export function unitParticipatesInProjectValidation(item) {
23
+ if (item.error !== undefined || item.code.trim().length === 0)
24
+ return false;
25
+ const target = item.unit.kind === "file" ? item.unit.outputPath : item.unit.sourcePath;
26
+ return isValidationExtension(target);
27
+ }
28
+ /**
29
+ * Build the combined in-memory candidate state for all successful JS/TS units.
30
+ * The working tree is never modified; stale inline markers and already-existing
31
+ * whole-file targets are excluded fail-closed instead of guessed around.
32
+ */
33
+ export async function buildCandidateOverlay(root, generated) {
34
+ const absoluteRoot = resolve(root);
35
+ const files = new Map();
36
+ const excluded = [];
37
+ const participating = generated.filter(unitParticipatesInProjectValidation);
38
+ for (const item of participating.filter((entry) => entry.unit.kind === "file")) {
39
+ const unit = item.unit;
40
+ const absolutePath = resolve(absoluteRoot, unit.outputPath);
41
+ if (!absolutePath.startsWith(absoluteRoot + sep)) {
42
+ excluded.push({ unit, reason: `refusing a candidate outside the project root: ${unit.outputPath}` });
43
+ continue;
44
+ }
45
+ let exists = false;
46
+ try {
47
+ await stat(absolutePath);
48
+ exists = true;
49
+ }
50
+ catch {
51
+ exists = false;
52
+ }
53
+ if (exists) {
54
+ excluded.push({ unit, reason: `existing target ${unit.outputPath} is never overwritten` });
55
+ continue;
56
+ }
57
+ const key = overlayPathKey(absolutePath);
58
+ if (files.has(key)) {
59
+ excluded.push({ unit, reason: `another unit already generates ${unit.outputPath}` });
60
+ continue;
61
+ }
62
+ files.set(key, {
63
+ path: unit.outputPath,
64
+ absolutePath,
65
+ content: item.code.endsWith("\n") ? item.code : `${item.code}\n`,
66
+ created: true,
67
+ units: [unit],
68
+ });
69
+ }
70
+ const inlineByFile = new Map();
71
+ for (const item of participating.filter((entry) => entry.unit.kind === "inline")) {
72
+ const key = overlayPathKey(item.unit.absoluteSource);
73
+ const bucket = inlineByFile.get(key) ?? [];
74
+ bucket.push(item);
75
+ inlineByFile.set(key, bucket);
76
+ }
77
+ for (const bucket of inlineByFile.values()) {
78
+ const first = bucket[0].unit;
79
+ let content;
80
+ try {
81
+ content = await readFile(first.absoluteSource, "utf8");
82
+ }
83
+ catch (error) {
84
+ const reason = `could not read ${first.sourcePath}: ${error instanceof Error ? error.message : String(error)}`;
85
+ for (const item of bucket)
86
+ excluded.push({ unit: item.unit, reason });
87
+ continue;
88
+ }
89
+ // Apply bottom-to-top so earlier ranges stay valid; the exact marker bytes
90
+ // are re-verified for every replacement.
91
+ const ordered = [...bucket].sort((left, right) => (right.unit.range?.start ?? 0) - (left.unit.range?.start ?? 0));
92
+ const applied = [];
93
+ let failed = false;
94
+ for (const item of ordered) {
95
+ try {
96
+ content = replaceInlineMarker(content, item.unit.range, item.unit.expectedMarker, item.code);
97
+ applied.push(item.unit);
98
+ }
99
+ catch (error) {
100
+ failed = true;
101
+ const reason = `${item.unit.sourcePath}: ${error instanceof Error ? error.message : String(error)}`;
102
+ excluded.push({ unit: item.unit, reason });
103
+ }
104
+ }
105
+ if (failed) {
106
+ // A stale marker invalidates every other offset in the same file; the
107
+ // whole file's inline units are excluded rather than partially staged.
108
+ for (const unit of applied) {
109
+ excluded.push({ unit, reason: `${unit.sourcePath}: another inline marker in this file was stale` });
110
+ }
111
+ continue;
112
+ }
113
+ files.set(overlayPathKey(first.absoluteSource), {
114
+ path: first.sourcePath,
115
+ absolutePath: resolve(first.absoluteSource),
116
+ content,
117
+ created: false,
118
+ units: applied,
119
+ });
120
+ }
121
+ return { root: absoluteRoot, files, excluded };
122
+ }
123
+ //# sourceMappingURL=candidate-overlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidate-overlay.js","sourceRoot":"","sources":["../../../src/agents/direct/candidate-overlay.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"candidate-validation.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/candidate-validation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,8BAA+B,SAAQ,KAAK;gBAC3C,OAAO,EAAE,MAAM;CAI5B;AAqID,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9F;AAED,iFAAiF;AACjF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB7F"}
1
+ {"version":3,"file":"candidate-validation.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/candidate-validation.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,8BAA+B,SAAQ,KAAK;gBAC3C,OAAO,EAAE,MAAM;CAI5B;AA0ID,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9F;AAED,iFAAiF;AACjF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB7F"}
@@ -10,6 +10,10 @@ export class DirectCandidateValidationError extends Error {
10
10
  }
11
11
  }
12
12
  const TYPESCRIPT_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
13
+ // Delimiter balancing misreads prose-bearing markup: apostrophes in HTML text
14
+ // and unquoted `url(https://…)` in CSS are legal but read as unterminated
15
+ // strings/comments. These outputs keep only the fence and non-empty gates.
16
+ const UNBALANCED_TEXT_EXTENSIONS = new Set([".html", ".htm", ".css", ".svg", ".md", ".markdown"]);
13
17
  function newlyIntroducedDiagnostic(baseline, candidate) {
14
18
  const remainingBaseline = new Map();
15
19
  for (const diagnostic of baseline) {
@@ -146,6 +150,8 @@ export async function validateGeneratedUnit(unit, code) {
146
150
  throw new DirectCandidateValidationError(`${unit.sourcePath}: model formatting remained in generated source.`);
147
151
  }
148
152
  const sourcePath = unit.kind === "file" ? unit.outputPath : unit.sourcePath;
153
+ if (UNBALANCED_TEXT_EXTENSIONS.has(extname(sourcePath).toLowerCase()))
154
+ return;
149
155
  const { baseline, candidate } = await sourceAndCandidateForUnit(unit, code);
150
156
  const typescript = TYPESCRIPT_EXTENSIONS.has(extname(sourcePath).toLowerCase());
151
157
  const baselineDiagnostics = baseline === undefined
@@ -1 +1 @@
1
- {"version":3,"file":"candidate-validation.js","sourceRoot":"","sources":["../../../src/agents/direct/candidate-validation.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAGvD,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IACvD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gCAAgC,CAAC;IAC/C,CAAC;CACF;AAED,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAOtF,SAAS,yBAAyB,CAChC,QAA8C,EAC9C,SAA+C;IAE/C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpD,KAAK,MAAM,UAAU,IAAI,QAAQ,EAAE,CAAC;QAClC,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,KAAK,MAAM,UAAU,IAAI,SAAS,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,SAAS,GAAG,CAAC;YAAE,iBAAiB,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;;YACnE,OAAO,UAAU,CAAC;IACzB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,yBAAyB,CAAC,IAAY,EAAE,UAAkB;IACjE,MAAM,WAAW,GAAgC,EAAE,CAAC;IACpD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAmC,CAAC;IACxC,IAAI,MAAoC,CAAC;IACzC,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,YAAY,GAAG,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,KAAK,CAAC;IAChE,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjC,YAAY,GAAG,KAAK,CAAC;gBACrB,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;gBACnC,KAAK,IAAI,CAAC,CAAC;gBACX,MAAM,GAAG,SAAS,CAAC;YACrB,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,OAAO;gBAAE,OAAO,GAAG,KAAK,CAAC;iBACxB,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAO,GAAG,IAAI,CAAC;iBAClC,IAAI,IAAI,KAAK,KAAK;gBAAE,KAAK,GAAG,SAAS,CAAC;YAC3C,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,YAAY,GAAG,IAAI,CAAC;YACpB,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACtC,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,MAAM;YACxB,SAAS;QACX,CAAC;QACD,IAAI,YAAY,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjC,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;YACtC,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,MAAM;YACxB,SAAS;QACX,CAAC;QACD,IAAI,SAAS,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;YAC5F,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YACvD,KAAK,IAAI,CAAC,CAAC;YACX,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACjD,KAAK,GAAG,IAAI,CAAC;YACb,SAAS;QACX,CAAC;QACD,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;aAC9D,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YAC/D,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAC7B,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,QAAQ,IAAI,IAAI,EAAE,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,KAAK;QAAE,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,KAAK,EAAE,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC1F,IAAI,MAAM;QAAE,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,MAAM,EAAE,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC,CAAC;IACvG,IAAI,YAAY;QAAE,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,eAAe,EAAE,OAAO,EAAE,+BAA+B,EAAE,CAAC,CAAC;IACvG,KAAK,MAAM,SAAS,IAAI,KAAK,EAAE,CAAC;QAC9B,WAAW,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,aAAa,SAAS,EAAE,EAAE,OAAO,EAAE,2BAA2B,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,2BAA2B,CAAC,IAAY,EAAE,UAAkB;IACnE,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,GAAG,GAAG,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,MAAM,CAAC;IACzD,MAAM,MAAM,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE;QACtC,QAAQ,EAAE,UAAU;QACpB,iBAAiB,EAAE,IAAI;QACvB,eAAe,EAAE;YACf,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM;YAC9B,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM;YAC5B,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,IAAI;SACd;KACF,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;SAC9B,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,KAAK,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC;SAC3E,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;QAClB,MAAM,OAAO,GAAG,EAAE,CAAC,4BAA4B,CAAC,UAAU,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC7E,OAAO,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC;IAC3D,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,IAAoB,EACpB,IAAY;IAEZ,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC7D,OAAO;QACL,QAAQ;QACR,SAAS,EAAE,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAM,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC;KACjF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,IAAoB,EAAE,IAAY;IAC3E,OAAO,CAAC,MAAM,yBAAyB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAoB,EAAE,IAAY;IAC5E,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,8BAA8B,CAAC,GAAG,IAAI,CAAC,UAAU,2BAA2B,CAAC,CAAC;IACtH,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,8BAA8B,CAAC,GAAG,IAAI,CAAC,UAAU,kDAAkD,CAAC,CAAC;IACjH,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,UAAW,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;IAC7E,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC5E,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAChF,MAAM,mBAAmB,GAAG,QAAQ,KAAK,SAAS;QAChD,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,2BAA2B,CAAC,QAAQ,EAAE,UAAU,CAAC;YACnD,CAAC,CAAC,yBAAyB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACtD,MAAM,oBAAoB,GAAG,UAAU;QACrC,CAAC,CAAC,2BAA2B,CAAC,SAAS,EAAE,UAAU,CAAC;QACpD,CAAC,CAAC,yBAAyB,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,yBAAyB,CAAC,mBAAmB,EAAE,oBAAoB,CAAC,CAAC;IACxF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,IAAI,8BAA8B,CACtC,GAAG,UAAU,mDAAmD,UAAU,CAAC,OAAO,GAAG,CACtF,CAAC;IACJ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"candidate-validation.js","sourceRoot":"","sources":["../../../src/agents/direct/candidate-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type CandidateOverlay } from "./candidate-overlay.ts";
2
+ import type { ProjectDiagnostic, ValidationProgramContext } from "./program-diagnostics.ts";
3
+ export interface OverlayDependencyGroups {
4
+ /** Overlay path key -> group id. */
5
+ groupOf: Map<string, number>;
6
+ /** Group id -> overlay path keys in that group. */
7
+ members: Map<number, string[]>;
8
+ }
9
+ export interface DiagnosticAttribution {
10
+ /** Overlay path key -> new diagnostics attributed to that candidate file. */
11
+ byFile: Map<string, ProjectDiagnostic[]>;
12
+ /** Diagnostics that could not be safely attributed to any candidate file. */
13
+ unattributed: ProjectDiagnostic[];
14
+ }
15
+ /** Union overlay files connected by imports in either direction. */
16
+ export declare function buildOverlayDependencyGroups(overlay: CandidateOverlay, context: ValidationProgramContext): OverlayDependencyGroups;
17
+ /**
18
+ * Attribute each newly introduced diagnostic to candidate files. Diagnostics
19
+ * inside a candidate file attach directly; diagnostics in untouched project
20
+ * files are followed through their resolved relative imports (bounded breadth-
21
+ * first search) to the candidate files that could have caused them. Anything
22
+ * that cannot be linked stays unattributed, and the caller must fail the batch.
23
+ */
24
+ export declare function attributeDiagnostics(diagnostics: readonly ProjectDiagnostic[], overlay: CandidateOverlay, context: ValidationProgramContext): DiagnosticAttribution;
25
+ //# sourceMappingURL=dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/dependency-graph.ts"],"names":[],"mappings":"AAOA,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAI5F,MAAM,WAAW,uBAAuB;IACtC,oCAAoC;IACpC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,mDAAmD;IACnD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,6EAA6E;IAC7E,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IACzC,6EAA6E;IAC7E,YAAY,EAAE,iBAAiB,EAAE,CAAC;CACnC;AAoBD,oEAAoE;AACpE,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,wBAAwB,GAChC,uBAAuB,CAuCzB;AAID;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,SAAS,iBAAiB,EAAE,EACzC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,wBAAwB,GAChC,qBAAqB,CA0DvB"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Import-graph dependency grouping and diagnostic-to-unit attribution for the
3
+ * candidate overlay. Groups are connected components of candidate files linked
4
+ * by resolved module imports; a cross-file error rejects its whole group so a
5
+ * broken contract is never partially written.
6
+ */
7
+ import ts from "typescript";
8
+ import { overlayPathKey } from "./candidate-overlay.js";
9
+ import { overlayCompilerHost } from "./program-diagnostics.js";
10
+ import { resolve, sep } from "node:path";
11
+ function resolveImports(fileName, content, context, host) {
12
+ const resolved = [];
13
+ for (const imported of ts.preProcessFile(content, true, true).importedFiles) {
14
+ const resolution = ts.resolveModuleName(imported.fileName, fileName, context.options, host);
15
+ const target = resolution.resolvedModule?.resolvedFileName;
16
+ if (!target)
17
+ continue;
18
+ if (resolution.resolvedModule?.isExternalLibraryImport)
19
+ continue;
20
+ if (resolve(target).split(sep).includes("node_modules"))
21
+ continue;
22
+ resolved.push(resolve(target));
23
+ }
24
+ return resolved;
25
+ }
26
+ /** Union overlay files connected by imports in either direction. */
27
+ export function buildOverlayDependencyGroups(overlay, context) {
28
+ const host = overlayCompilerHost(context, overlay);
29
+ const keys = [...overlay.files.keys()];
30
+ const parent = new Map(keys.map((key) => [key, key]));
31
+ const find = (key) => {
32
+ let current = key;
33
+ while (parent.get(current) !== current)
34
+ current = parent.get(current);
35
+ parent.set(key, current);
36
+ return current;
37
+ };
38
+ const union = (left, right) => {
39
+ const leftRoot = find(left);
40
+ const rightRoot = find(right);
41
+ if (leftRoot !== rightRoot)
42
+ parent.set(leftRoot, rightRoot);
43
+ };
44
+ for (const [key, file] of overlay.files) {
45
+ for (const target of resolveImports(file.absolutePath, file.content, context, host)) {
46
+ const targetKey = overlayPathKey(target);
47
+ if (overlay.files.has(targetKey))
48
+ union(key, targetKey);
49
+ }
50
+ }
51
+ const groupOf = new Map();
52
+ const members = new Map();
53
+ const rootIds = new Map();
54
+ for (const key of keys) {
55
+ const root = find(key);
56
+ let id = rootIds.get(root);
57
+ if (id === undefined) {
58
+ id = rootIds.size;
59
+ rootIds.set(root, id);
60
+ }
61
+ groupOf.set(key, id);
62
+ const bucket = members.get(id) ?? [];
63
+ bucket.push(key);
64
+ members.set(id, bucket);
65
+ }
66
+ return { groupOf, members };
67
+ }
68
+ const ATTRIBUTION_SEARCH_DEPTH = 6;
69
+ /**
70
+ * Attribute each newly introduced diagnostic to candidate files. Diagnostics
71
+ * inside a candidate file attach directly; diagnostics in untouched project
72
+ * files are followed through their resolved relative imports (bounded breadth-
73
+ * first search) to the candidate files that could have caused them. Anything
74
+ * that cannot be linked stays unattributed, and the caller must fail the batch.
75
+ */
76
+ export function attributeDiagnostics(diagnostics, overlay, context) {
77
+ const host = overlayCompilerHost(context, overlay);
78
+ const byRelativePath = new Map();
79
+ for (const [key, file] of overlay.files)
80
+ byRelativePath.set(file.path, key);
81
+ const reachableCache = new Map();
82
+ const reachableOverlayFiles = (absolutePath) => {
83
+ const startKey = overlayPathKey(absolutePath);
84
+ const cached = reachableCache.get(startKey);
85
+ if (cached)
86
+ return cached;
87
+ const found = new Set();
88
+ const visited = new Set([startKey]);
89
+ let frontier = [resolve(absolutePath)];
90
+ for (let depth = 0; depth < ATTRIBUTION_SEARCH_DEPTH && frontier.length > 0; depth += 1) {
91
+ const next = [];
92
+ for (const fileName of frontier) {
93
+ const content = overlay.files.get(overlayPathKey(fileName))?.content ?? host.readFile(fileName);
94
+ if (content === undefined)
95
+ continue;
96
+ for (const target of resolveImports(fileName, content, context, host)) {
97
+ const targetKey = overlayPathKey(target);
98
+ if (visited.has(targetKey))
99
+ continue;
100
+ visited.add(targetKey);
101
+ if (overlay.files.has(targetKey))
102
+ found.add(targetKey);
103
+ else
104
+ next.push(target);
105
+ }
106
+ }
107
+ frontier = next;
108
+ }
109
+ const result = [...found];
110
+ reachableCache.set(startKey, result);
111
+ return result;
112
+ };
113
+ const byFile = new Map();
114
+ const unattributed = [];
115
+ const attach = (key, diagnostic) => {
116
+ const bucket = byFile.get(key) ?? [];
117
+ bucket.push(diagnostic);
118
+ byFile.set(key, bucket);
119
+ };
120
+ for (const diagnostic of diagnostics) {
121
+ if (diagnostic.path === undefined) {
122
+ unattributed.push(diagnostic);
123
+ continue;
124
+ }
125
+ const direct = byRelativePath.get(diagnostic.path);
126
+ if (direct !== undefined) {
127
+ attach(direct, diagnostic);
128
+ continue;
129
+ }
130
+ const reached = reachableOverlayFiles(resolve(overlay.root, ...diagnostic.path.split("/")));
131
+ if (reached.length === 0) {
132
+ unattributed.push(diagnostic);
133
+ continue;
134
+ }
135
+ for (const key of reached)
136
+ attach(key, diagnostic);
137
+ }
138
+ return { byFile, unattributed };
139
+ }
140
+ //# sourceMappingURL=dependency-graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.js","sourceRoot":"","sources":["../../../src/agents/direct/dependency-graph.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import type { ConversionUnit, DirectDiscoveryResult } from "./types.ts";
2
+ /** Bounded direct-path file walk, shared with combined project validation. */
3
+ export declare function walkDirectFiles(root: string): Promise<string[]>;
2
4
  /** Discover units plus actionable notices for marker text that cannot run safely. */
3
- export declare function discoverDirectUnits(root: string, language: string): Promise<DirectDiscoveryResult>;
5
+ export declare function discoverDirectUnits(root: string, language: string | readonly string[]): Promise<DirectDiscoveryResult>;
4
6
  /** Compatibility helper returning only runnable units. */
5
- export declare function discoverUnits(root: string, language: string): Promise<ConversionUnit[]>;
7
+ export declare function discoverUnits(root: string, language: string | readonly string[]): Promise<ConversionUnit[]>;
6
8
  //# sourceMappingURL=discovery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAmCxE,qFAAqF;AACrF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwFxG;AAED,0DAA0D;AAC1D,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAE7F"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/agents/direct/discovery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAmCxE,8EAA8E;AAC9E,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAErE;AAED,qFAAqF;AACrF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC,qBAAqB,CAAC,CAoGhC;AAED,0DAA0D;AAC1D,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GACnC,OAAO,CAAC,cAAc,EAAE,CAAC,CAE3B"}
@@ -1,6 +1,6 @@
1
1
  import { readdir, readFile, stat } from "node:fs/promises";
2
2
  import { basename, extname, join, relative, resolve, sep } from "node:path";
3
- import { languageProfile } from "./languages.js";
3
+ import { languageForExtension, languageProfile } from "./languages.js";
4
4
  import { extractInlineMarkers } from "./marker-parser.js";
5
5
  const SCANNED_EXTENSIONS = new Set([
6
6
  ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs",
@@ -39,10 +39,18 @@ async function walk(root, ignores) {
39
39
  await visit(root, 0);
40
40
  return results.sort();
41
41
  }
42
+ /** Bounded direct-path file walk, shared with combined project validation. */
43
+ export async function walkDirectFiles(root) {
44
+ return walk(resolve(root), DEFAULT_IGNORES);
45
+ }
42
46
  /** Discover units plus actionable notices for marker text that cannot run safely. */
43
47
  export async function discoverDirectUnits(root, language) {
44
48
  const absoluteRoot = resolve(root);
45
- const profile = languageProfile(language);
49
+ const languages = (typeof language === "string" ? [language] : [...language])
50
+ .map((entry) => entry.trim().toLowerCase());
51
+ const primary = languages[0] ?? "typescript";
52
+ const configured = new Set(languages);
53
+ const primaryProfile = languageProfile(primary);
46
54
  const files = await walk(absoluteRoot, DEFAULT_IGNORES);
47
55
  const units = [];
48
56
  const notices = [];
@@ -62,7 +70,13 @@ export async function discoverDirectUnits(root, language) {
62
70
  const prompt = content.trim();
63
71
  if (prompt.length === 0)
64
72
  continue;
65
- const outputPath = `${rel.slice(0, -".human".length)}.${profile.ext}`;
73
+ // Inner-extension routing: `index.html.human` -> `index.html` when the
74
+ // extension's language is configured; otherwise the primary language.
75
+ const stem = rel.slice(0, -".human".length);
76
+ const innerLanguage = languageForExtension(extname(stem));
77
+ const routed = innerLanguage !== undefined && configured.has(innerLanguage);
78
+ const unitLanguage = routed ? innerLanguage : primary;
79
+ const outputPath = routed ? stem : `${stem}.${primaryProfile.ext}`;
66
80
  try {
67
81
  await stat(join(absoluteRoot, ...outputPath.split("/")));
68
82
  notices.push({
@@ -82,6 +96,7 @@ export async function discoverDirectUnits(root, language) {
82
96
  absoluteSource: absolute,
83
97
  prompt,
84
98
  outputPath,
99
+ language: unitLanguage,
85
100
  describe: `${rel} -> ${outputPath}`,
86
101
  });
87
102
  continue;
@@ -128,6 +143,7 @@ export async function discoverDirectUnits(root, language) {
128
143
  sourcePath: rel,
129
144
  absoluteSource: absolute,
130
145
  prompt: marker.prompt,
146
+ language: languageForExtension(extname(absolute)) ?? primary,
131
147
  range: { start: marker.start, end: marker.end },
132
148
  expectedMarker: content.slice(marker.start, marker.end),
133
149
  line,