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.
- package/Readme.md +19 -8
- 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/candidate-validation.d.ts.map +1 -1
- package/dist/agents/direct/candidate-validation.js +6 -0
- package/dist/agents/direct/candidate-validation.js.map +1 -1
- 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 +4 -2
- package/dist/agents/direct/discovery.d.ts.map +1 -1
- package/dist/agents/direct/discovery.js +19 -3
- 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/languages.d.ts +1 -0
- package/dist/agents/direct/languages.d.ts.map +1 -1
- package/dist/agents/direct/languages.js +13 -0
- package/dist/agents/direct/languages.js.map +1 -1
- package/dist/agents/direct/presentation.d.ts +1 -1
- package/dist/agents/direct/presentation.d.ts.map +1 -1
- package/dist/agents/direct/presentation.js +10 -4
- 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/agents/direct/types.d.ts +2 -0
- package/dist/agents/direct/types.d.ts.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +59 -6
- package/dist/cli.js.map +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +28 -0
- package/dist/config/config.js.map +1 -1
- package/dist/core/types.d.ts +7 -1
- package/dist/core/types.d.ts.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
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.
|
|
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
|
|
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
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
"
|
|
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.
|
|
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
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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;
|
|
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;
|
|
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":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,cAAc,EAAyB,MAAM,wBAAwB,CAAC;AAE/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAgBzC,SAAS,cAAc,CACrB,QAAgB,EAChB,OAAe,EACf,OAAiC,EACjC,IAAqB;IAErB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,QAAQ,IAAI,EAAE,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QAC5E,MAAM,UAAU,GAAG,EAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC5F,MAAM,MAAM,GAAG,UAAU,CAAC,cAAc,EAAE,gBAAgB,CAAC;QAC3D,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,IAAI,UAAU,CAAC,cAAc,EAAE,uBAAuB;YAAE,SAAS;QACjE,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,SAAS;QAClE,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,4BAA4B,CAC1C,OAAyB,EACzB,OAAiC;IAEjC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAiB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,CAAC,GAAW,EAAU,EAAE;QACnC,IAAI,OAAO,GAAG,GAAG,CAAC;QAClB,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,OAAO;YAAE,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;QACvE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,KAAa,EAAQ,EAAE;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9B,IAAI,QAAQ,KAAK,SAAS;YAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC9D,CAAC,CAAC;IAEF,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YACpF,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACzC,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,KAAK,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC5C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,WAAyC,EACzC,OAAyB,EACzB,OAAiC;IAEjC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,cAAc,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK;QAAE,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAE5E,MAAM,cAAc,GAAG,IAAI,GAAG,EAAoB,CAAC;IACnD,MAAM,qBAAqB,GAAG,CAAC,YAAoB,EAAY,EAAE;QAC/D,MAAM,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAC1B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;QAChC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAS,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC5C,IAAI,QAAQ,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;QACvC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,wBAAwB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YACxF,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;gBAChG,IAAI,OAAO,KAAK,SAAS;oBAAE,SAAS;gBACpC,KAAK,MAAM,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;oBACtE,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;oBACzC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;wBAAE,SAAS;oBACrC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;oBACvB,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;wBAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;;wBAClD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC1B,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+B,CAAC;IACtD,MAAM,YAAY,GAAwB,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,GAAW,EAAE,UAA6B,EAAQ,EAAE;QAClE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC;IACF,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,IAAI,UAAU,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,OAAO;YAAE,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -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,
|
|
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
|
|
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
|
-
|
|
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,
|