@moda-ai/cli 1.55.61 → 1.55.62

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 (36) hide show
  1. package/dist/{agent-3hdkbyep.js → agent-rc62qxke.js} +18 -17
  2. package/dist/{cli-94r5x9bg.js → cli-27kkk5z4.js} +1 -1
  3. package/dist/{cli-ehf0f84r.js → cli-3t4ft30h.js} +5 -5
  4. package/dist/{cli-9g8kp42c.js → cli-9rmx2zzy.js} +2 -2
  5. package/dist/{cli-hawwf30b.js → cli-bpnt0z0y.js} +1 -1
  6. package/dist/{cli-2jwxdhh5.js → cli-c7mj168q.js} +1 -1
  7. package/dist/cli-fsgh8mq5.js +1522 -0
  8. package/dist/{cli-y5d33a1y.js → cli-gmvbapx7.js} +2 -1517
  9. package/dist/{cli-rtkjjf0a.js → cli-kmq9pgef.js} +68 -1241
  10. package/dist/{cli-v2h21cgf.js → cli-m702wdtv.js} +1 -1
  11. package/dist/cli-mfvwvh84.js +1178 -0
  12. package/dist/{cli-b918vs2m.js → cli-p2tfx93b.js} +4 -4
  13. package/dist/{cli-m25c0rke.js → cli-rdwy3y4f.js} +3 -3
  14. package/dist/{cli-sr3tnzfr.js → cli-thy08dak.js} +11 -11
  15. package/dist/{cli-04q6xpn6.js → cli-tn9dg758.js} +46 -34
  16. package/dist/{cli-31ybq5f2.js → cli-wcax07xh.js} +2 -2
  17. package/dist/cli.js +27 -20
  18. package/dist/{doctor-3x4cnx7p.js → doctor-ehqrzq5e.js} +8 -8
  19. package/dist/{harness-esdbkwwh.js → harness-e1yawk87.js} +13 -11
  20. package/dist/{harness-github-actions-xbfvjpva.js → harness-github-actions-bgfnh4tw.js} +11 -9
  21. package/dist/{harness-report-gz5d3y48.js → harness-report-dc6yf2qv.js} +2 -1
  22. package/dist/index-gtqxj0fp.js +2956 -0
  23. package/dist/{index-10ye3htt.js → index-ma1gt133.js} +31 -29
  24. package/dist/{production-intelligence-fqvhzq6s.js → production-intelligence-40teyxyv.js} +4 -4
  25. package/dist/{profile-commands-yvpe4d8y.js → profile-commands-fa2858ez.js} +5 -5
  26. package/dist/{prompt-attribution-abms6d21.js → prompt-attribution-htyrwdjj.js} +13 -11
  27. package/dist/prompt-source-mcp.js +11 -9
  28. package/dist/{prompt-sources-1hycgx6r.js → prompt-sources-r2xbxr0r.js} +2 -1
  29. package/dist/{prompts-sk27qc29.js → prompts-s5q70jge.js} +6 -6
  30. package/dist/{provision-aqhfbnez.js → provision-2bb73ywd.js} +6 -6
  31. package/dist/{registry-wv1zzyce.js → registry-ztn727mn.js} +4 -4
  32. package/dist/{skills-etzcqhp8.js → skills-c25dmy28.js} +6 -6
  33. package/dist/{sync-4fdqer3h.js → sync-t1d50rpv.js} +16 -14
  34. package/package.json +1 -1
  35. package/skills/integration/index.json +2 -2
  36. package/dist/{cli-pnarsb96.js → cli-15pzedv3.js} +3 -3
@@ -1,6 +1,10 @@
1
1
  import {
2
2
  CliInputError
3
3
  } from "./cli-k4tqwah4.js";
4
+ import {
5
+ HARNESS_COMPONENT_STATUSES,
6
+ normalizeComponentStatus
7
+ } from "./cli-mfvwvh84.js";
4
8
  import {
5
9
  __require
6
10
  } from "./cli-0v6na3yp.js";
@@ -9,1196 +13,19 @@ import {
9
13
  import { createHash } from "node:crypto";
10
14
  import {
11
15
  existsSync,
12
- lstatSync as lstatSync2,
16
+ lstatSync,
13
17
  mkdirSync,
14
- readFileSync as readFileSync3,
18
+ readFileSync,
15
19
  writeFileSync
16
20
  } from "node:fs";
17
- import { basename, dirname, join as join3, relative as relative3, resolve } from "node:path";
18
-
19
- // src/harness-component-status.ts
20
- import { closeSync, openSync, readdirSync as readdirSync2, readFileSync as readFileSync2, readSync } from "node:fs";
21
- import { isAbsolute as isAbsolute2, join as join2, posix as posix2, relative as relative2 } from "node:path";
22
-
23
- // src/harness-wrangler-bindings.ts
24
- import { lstatSync, readdirSync, readFileSync } from "node:fs";
25
- import { isAbsolute, join, posix, relative } from "node:path";
26
- var WRANGLER_FILE = /^wrangler(\.[\w-]+)?\.jsonc?$/;
27
- var ANY_WRANGLER_FILE = /^wrangler(?:\.[\w-]+)?\.(?:jsonc?|toml)$/;
28
- var SKIPPED_DIRS = new Set(["node_modules", ".git", ".wrangler", "dist", "build", ".next", ".turbo", "vendor"]);
29
- var MAX_DEPTH = 4;
30
- var AGENT_CLASS = /Agent(?:V\d+)?$/;
31
- var TEST_SEGMENT = /^(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|e2e|mocks?)$/i;
32
- var TEST_TOKEN = /(?:^|[._-])(?:test|tests|spec|e2e|fixtures?|mocks?)(?:$|[._-])/i;
33
- function isTestWorkerConfig(input) {
34
- const segments = input.path.split("/");
35
- const file = segments[segments.length - 1] ?? "";
36
- const variant = file.replace(/^wrangler\.?/, "").replace(/\.(?:jsonc?|toml)$/, "");
37
- if (segments.slice(0, -1).some((segment) => TEST_SEGMENT.test(segment)))
38
- return true;
39
- if (variant && TEST_TOKEN.test(variant))
40
- return true;
41
- if (typeof input.name === "string" && TEST_TOKEN.test(input.name))
42
- return true;
43
- return (input.mains ?? []).some((main) => typeof main === "string" && main.split("/").slice(0, -1).some((segment) => TEST_SEGMENT.test(segment)));
44
- }
45
- function stripJsonc(text) {
46
- let out = "";
47
- let inString = false;
48
- for (let i = 0;i < text.length; i += 1) {
49
- const ch = text[i];
50
- if (inString) {
51
- out += ch;
52
- if (ch === "\\") {
53
- out += text[i + 1] ?? "";
54
- i += 1;
55
- } else if (ch === '"') {
56
- inString = false;
57
- }
58
- continue;
59
- }
60
- if (ch === '"') {
61
- inString = true;
62
- out += ch;
63
- } else if (ch === "/" && text[i + 1] === "/") {
64
- while (i < text.length && text[i] !== `
65
- `)
66
- i += 1;
67
- out += `
68
- `;
69
- } else if (ch === "/" && text[i + 1] === "*") {
70
- i += 2;
71
- while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) {
72
- if (text[i] === `
73
- `)
74
- out += `
75
- `;
76
- i += 1;
77
- }
78
- i += 1;
79
- } else {
80
- out += ch;
81
- }
82
- }
83
- return out.replace(/,(\s*[}\]])/g, "$1");
84
- }
85
- function findWranglerFiles(rootDir, pattern = WRANGLER_FILE) {
86
- const found = [];
87
- const walk = (dir, depth) => {
88
- let entries;
89
- try {
90
- entries = readdirSync(dir);
91
- } catch {
92
- return;
93
- }
94
- for (const name of entries) {
95
- const abs = join(dir, name);
96
- let stat;
97
- try {
98
- stat = lstatSync(abs);
99
- } catch {
100
- continue;
101
- }
102
- if (stat.isDirectory()) {
103
- if (depth < MAX_DEPTH && !SKIPPED_DIRS.has(name) && !name.startsWith("."))
104
- walk(abs, depth + 1);
105
- } else if (stat.isFile() && pattern.test(name)) {
106
- found.push(abs);
107
- }
108
- }
109
- };
110
- walk(rootDir, 0);
111
- return found.sort();
112
- }
113
- function lineOf(text, className) {
114
- const index = text.search(new RegExp(`"class_name"\\s*:\\s*"${className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`));
115
- return index < 0 ? undefined : text.slice(0, index).split(`
116
- `).length;
117
- }
118
- function workerDir(path) {
119
- const slash = path.lastIndexOf("/");
120
- return slash < 0 ? "" : path.slice(0, slash);
121
- }
122
- function detectBoundRuntimeClasses(rootDir) {
123
- const byClass = new Map;
124
- for (const abs of findWranglerFiles(rootDir)) {
125
- let text;
126
- let config;
127
- try {
128
- text = readFileSync(abs, "utf8");
129
- config = JSON.parse(stripJsonc(text));
130
- } catch {
131
- continue;
132
- }
133
- if (!config || typeof config !== "object")
134
- continue;
135
- const path = relative(rootDir, abs).split("\\").join("/");
136
- const root = config;
137
- if (isTestWorkerConfig({ path, name: root.name, mains: [root.main] }))
138
- continue;
139
- const sections = [root, ...Object.values(root.env ?? {})];
140
- for (const section of sections) {
141
- if (!section || typeof section !== "object")
142
- continue;
143
- const s = section;
144
- const durable = s.durable_objects?.bindings;
145
- const entries = [
146
- ...Array.isArray(durable) ? durable.map((b) => ["durable_object", b]) : [],
147
- ...Array.isArray(s.workflows) ? s.workflows.map((w) => ["workflow", w]) : []
148
- ];
149
- for (const [kind, raw] of entries) {
150
- if (!raw || typeof raw !== "object")
151
- continue;
152
- const entry = raw;
153
- const className = typeof entry.class_name === "string" ? entry.class_name : "";
154
- const scriptName = typeof entry.script_name === "string" && entry.script_name ? entry.script_name : undefined;
155
- const key = `${className}|${scriptName ? "external" : `config:${path}`}`;
156
- if (!className || byClass.has(key))
157
- continue;
158
- const binding = typeof (kind === "workflow" ? entry.binding : entry.name) === "string" ? String(kind === "workflow" ? entry.binding : entry.name) : className;
159
- byClass.set(key, {
160
- className,
161
- kind,
162
- binding,
163
- ...scriptName ? { scriptName } : {},
164
- path,
165
- line: lineOf(text, className)
166
- });
167
- }
168
- }
169
- }
170
- return [...byClass.values()];
171
- }
172
- var RUNTIME_BASES = {
173
- DurableObject: "durable_object",
174
- WorkflowEntrypoint: "workflow",
175
- AgentWorkflow: "workflow",
176
- Agent: "agent",
177
- AIChatAgent: "agent",
178
- Think: "agent",
179
- McpAgent: "agent"
180
- };
181
- var SOURCE_FILE = /\.tsx?$/;
182
- var SKIPPED_SOURCE_FILE = /\.(?:test|spec)\.tsx?$|\.d\.ts$/;
183
- var TEST_DIR = /^(?:tests?|__tests__|__mocks__|e2e|(?:.*[-_.])?fixtures?|__fixtures__)$/i;
184
- var MAX_SOURCE_DEPTH = 12;
185
- var MAX_SOURCE_FILES = 20000;
186
- var MAX_SOURCE_BYTES = 1e6;
187
- var CLASS_DECLARATION = /^[ \t]*(export[ \t]+(?:default[ \t]+)?)?(abstract[ \t]+)?class[ \t]+([A-Za-z_$][\w$]*)(?:[ \t]*<[^\n{]*?>)?[ \t]+extends[ \t]+([A-Za-z_$][\w$]*)/gm;
188
- function findSourceFiles(rootDir) {
189
- const found = [];
190
- const walk = (dir, depth) => {
191
- let entries;
192
- try {
193
- entries = readdirSync(dir).sort();
194
- } catch {
195
- return;
196
- }
197
- for (const name of entries) {
198
- if (found.length >= MAX_SOURCE_FILES)
199
- return;
200
- const abs = join(dir, name);
201
- let stat;
202
- try {
203
- stat = lstatSync(abs);
204
- } catch {
205
- continue;
206
- }
207
- if (stat.isDirectory()) {
208
- if (depth < MAX_SOURCE_DEPTH && !SKIPPED_DIRS.has(name) && !name.startsWith(".") && !TEST_DIR.test(name))
209
- walk(abs, depth + 1);
210
- } else if (stat.isFile() && SOURCE_FILE.test(name) && !SKIPPED_SOURCE_FILE.test(name) && stat.size <= MAX_SOURCE_BYTES) {
211
- found.push(abs);
212
- }
213
- }
214
- };
215
- walk(rootDir, 0);
216
- return found;
217
- }
218
- function bindingsOfSection(section) {
219
- const durable = section.durable_objects?.bindings;
220
- const raw = [...Array.isArray(durable) ? durable : [], ...Array.isArray(section.workflows) ? section.workflows : []];
221
- return raw.flatMap((entry) => {
222
- if (!entry || typeof entry !== "object")
223
- return [];
224
- const { class_name: className, script_name: scriptName } = entry;
225
- if (typeof className !== "string" || !className)
226
- return [];
227
- return [{ className, ...typeof scriptName === "string" && scriptName ? { scriptName } : {} }];
228
- });
229
- }
230
- function readWranglerScope(rootDir, abs) {
231
- let text;
232
- try {
233
- text = readFileSync(abs, "utf8");
234
- } catch {
235
- return;
236
- }
237
- const names = [];
238
- const mains = [];
239
- const bindings = [];
240
- let topName;
241
- let topMain;
242
- if (abs.endsWith(".toml")) {
243
- let header = "";
244
- let binding;
245
- for (const rawLine of text.split(`
246
- `)) {
247
- const line = rawLine.replace(/\s+#.*$/, "").trim();
248
- const table = /^\[\[?\s*([^\]]+?)\s*\]\]?$/.exec(line);
249
- if (table) {
250
- header = table[1];
251
- binding = undefined;
252
- if (/(?:^|\.)(?:durable_objects\.bindings|workflows)$/.test(header) && line.startsWith("[[")) {
253
- binding = { className: "" };
254
- bindings.push(binding);
255
- }
256
- continue;
257
- }
258
- const pair = /^([\w.-]+)\s*=\s*["']([^"']*)["']/.exec(line);
259
- if (!pair)
260
- continue;
261
- const [, key, value] = pair;
262
- const envSection = header === "" || /^env\.[\w-]+$/.test(header);
263
- if (binding && key === "class_name")
264
- binding.className = value;
265
- else if (binding && key === "script_name" && value)
266
- binding.scriptName = value;
267
- else if (envSection && key === "name" && value) {
268
- names.push(value);
269
- if (header === "")
270
- topName = value;
271
- } else if (envSection && key === "main" && value) {
272
- mains.push(value);
273
- if (header === "")
274
- topMain = value;
275
- }
276
- }
277
- } else {
278
- let config;
279
- try {
280
- config = JSON.parse(stripJsonc(text));
281
- } catch {
282
- return;
283
- }
284
- if (!config || typeof config !== "object" || Array.isArray(config))
285
- return;
286
- const root = config;
287
- if (typeof root.name === "string")
288
- topName = root.name;
289
- if (typeof root.main === "string")
290
- topMain = root.main;
291
- for (const section of [root, ...Object.values(root.env ?? {})]) {
292
- if (!section || typeof section !== "object")
293
- continue;
294
- const s = section;
295
- if (typeof s.name === "string" && s.name)
296
- names.push(s.name);
297
- if (typeof s.main === "string" && s.main)
298
- mains.push(s.main);
299
- bindings.push(...bindingsOfSection(s));
300
- }
301
- }
302
- const path = relative(rootDir, abs).split("\\").join("/");
303
- if (isTestWorkerConfig({ path, name: topName, mains: [topMain] }))
304
- return;
305
- const dir = workerDir(path);
306
- const dirs = [dir];
307
- for (const main of mains) {
308
- const mainDir = workerDir(posix.normalize(posix.join(dir || ".", main)).replace(/^\.\//, ""));
309
- if (!mainDir.startsWith("..") && !inside(mainDir, dir) && !dirs.includes(mainDir))
310
- dirs.push(mainDir);
311
- }
312
- return { dirs, names, bindings: bindings.filter((entry) => entry.className) };
313
- }
314
- function inside(path, dir) {
315
- return dir === "" || dir === "." || path === dir || path.startsWith(`${dir}/`);
316
- }
317
- function boundClassResolver(rootDir) {
318
- const scopes = findWranglerFiles(rootDir, ANY_WRANGLER_FILE).map((abs) => readWranglerScope(rootDir, abs)).filter((scope) => Boolean(scope));
319
- const anywhere = new Set;
320
- const external = new Map;
321
- for (const scope of scopes) {
322
- for (const binding of scope.bindings) {
323
- anywhere.add(binding.className);
324
- if (!binding.scriptName)
325
- continue;
326
- const servers = scopes.filter((other) => other.names.includes(binding.scriptName));
327
- if (servers.length === 0)
328
- external.set(binding.className, new Set(["*"]));
329
- for (const server of servers) {
330
- const set = external.get(binding.className) ?? new Set;
331
- server.names.forEach((name) => set.add(name));
332
- external.set(binding.className, set);
333
- }
334
- }
335
- }
336
- return (className, path) => {
337
- if (!anywhere.has(className))
338
- return false;
339
- if (external.get(className)?.has("*"))
340
- return true;
341
- let nearest = -1;
342
- let owners = [];
343
- for (const scope of scopes) {
344
- const depth = Math.max(-1, ...scope.dirs.filter((dir) => inside(path, dir)).map((dir) => dir ? dir.split("/").length : 0));
345
- if (depth < 0 || depth < nearest)
346
- continue;
347
- if (depth > nearest)
348
- owners = [];
349
- nearest = depth;
350
- owners.push(scope);
351
- }
352
- if (owners.length === 0)
353
- return true;
354
- const servedNames = external.get(className);
355
- return owners.some((owner) => owner.bindings.some((binding) => binding.className === className && !binding.scriptName) || servedNames !== undefined && owner.names.some((name) => servedNames.has(name)));
356
- };
357
- }
358
- function relativeImportStems(path, text) {
359
- const stems = new Set;
360
- for (const match of text.matchAll(/\bfrom\s*['"](\.{1,2}\/[^'"\n]*)['"]/g)) {
361
- const joined = posix.normalize(posix.join(workerDir(path) || ".", match[1])).replace(/^\.\//, "");
362
- const stem = joined.replace(/\.(?:[cm]?[jt]sx?)$/, "");
363
- stems.add(stem);
364
- stems.add(`${stem}/index`);
365
- }
366
- return stems;
367
- }
368
- function pickBaseDeclaration(candidates, from, importsOf) {
369
- if (candidates.length < 2)
370
- return candidates[0];
371
- const sameFile = candidates.find((candidate) => candidate.path === from.path);
372
- if (sameFile)
373
- return sameFile;
374
- const imports = importsOf(from.path);
375
- const imported = candidates.find((candidate) => imports.has(candidate.path.replace(/\.(?:[cm]?[jt]sx?)$/, "")));
376
- if (imported)
377
- return imported;
378
- const fromDirs = workerDir(from.path).split("/");
379
- const shared = (candidate) => {
380
- const dirs = workerDir(candidate.path).split("/");
381
- let n = 0;
382
- while (n < dirs.length && n < fromDirs.length && dirs[n] === fromDirs[n] && dirs[n] !== "")
383
- n += 1;
384
- return n;
385
- };
386
- let best = candidates[0];
387
- for (const candidate of candidates)
388
- if (shared(candidate) > shared(best))
389
- best = candidate;
390
- return best;
391
- }
392
- function detectDefinedUnboundRuntimeClasses(rootDir) {
393
- const declarations = [];
394
- const texts = new Map;
395
- for (const abs of findSourceFiles(rootDir)) {
396
- let text;
397
- try {
398
- text = readFileSync(abs, "utf8");
399
- } catch {
400
- continue;
401
- }
402
- if (!text.includes("extends"))
403
- continue;
404
- const path = relative(rootDir, abs).split("\\").join("/");
405
- texts.set(path, text);
406
- for (const match of text.matchAll(CLASS_DECLARATION)) {
407
- declarations.push({
408
- className: match[3],
409
- base: match[4],
410
- exported: Boolean(match[1]),
411
- abstract: Boolean(match[2]),
412
- path,
413
- line: text.slice(0, match.index).split(`
414
- `).length
415
- });
416
- }
417
- }
418
- const byName = new Map;
419
- for (const declaration of declarations) {
420
- const list = byName.get(declaration.className) ?? [];
421
- list.push(declaration);
422
- byName.set(declaration.className, list);
423
- }
424
- const importCache = new Map;
425
- const importsOf = (path) => {
426
- let stems = importCache.get(path);
427
- if (!stems) {
428
- stems = relativeImportStems(path, texts.get(path) ?? "");
429
- importCache.set(path, stems);
430
- }
431
- return stems;
432
- };
433
- const kindOf = (start) => {
434
- let current = start;
435
- for (let depth = 0;current && depth < 8; depth += 1) {
436
- const base = current.base;
437
- const kind = Object.hasOwn(RUNTIME_BASES, base) ? RUNTIME_BASES[base] : undefined;
438
- if (kind)
439
- return kind;
440
- current = pickBaseDeclaration(byName.get(base) ?? [], current, importsOf);
441
- }
442
- return;
443
- };
444
- const isBound = boundClassResolver(rootDir);
445
- const seen = new Set;
446
- const found = [];
447
- for (const declaration of declarations) {
448
- if (!declaration.exported || declaration.abstract || isBound(declaration.className, declaration.path))
449
- continue;
450
- const kind = kindOf(declaration);
451
- const key = `${declaration.className}|${declaration.path}`;
452
- if (!kind || seen.has(key))
453
- continue;
454
- seen.add(key);
455
- found.push({ className: declaration.className, kind, path: declaration.path, line: declaration.line });
456
- }
457
- return found;
458
- }
459
- function definedReason(defined) {
460
- const what = defined.kind === "workflow" ? "Workflow" : defined.kind === "agent" ? "Agent (Durable Object)" : "Durable Object";
461
- return `${what} class defined but not bound in any wrangler config`;
462
- }
463
- function norm(value) {
464
- return typeof value === "string" ? value.toLowerCase().replace(/[^a-z0-9]/g, "") : "";
465
- }
466
- function itemPaths(item) {
467
- const paths = [];
468
- for (const value of [item.root, item.sourcePath]) {
469
- if (typeof value === "string" && value && value !== ".")
470
- paths.push(value.replace(/^\.\//, ""));
471
- }
472
- for (const entry of Array.isArray(item.evidence) ? item.evidence : []) {
473
- const path = entry && typeof entry === "object" ? entry.path : undefined;
474
- if (typeof path === "string" && path)
475
- paths.push(path.replace(/^\.\//, ""));
476
- }
477
- return paths;
478
- }
479
- function withinWorker(path, dir, otherDirs) {
480
- const inside2 = (d) => d === "" || path === d || path.startsWith(`${d}/`);
481
- return inside2(dir) && !otherDirs.some((other) => other.length > dir.length && inside2(other));
482
- }
483
- function namesClass(name, className) {
484
- if (typeof name !== "string")
485
- return false;
486
- const target = norm(className);
487
- const bare = name.replace(/\s*\([^)]*\)\s*$/, "");
488
- return norm(bare) === target || bare.split(/[^A-Za-z0-9_]+/).some((word) => norm(word) === target);
489
- }
490
- function graphNamesClass(graph, bound, all) {
491
- const named = (name) => namesClass(name, bound.className);
492
- const sameName = bound.scriptName ? [bound] : all.filter((other) => other.className === bound.className && !other.scriptName);
493
- const dir = workerDir(bound.path);
494
- const otherDirs = sameName.map((other) => workerDir(other.path)).filter((other) => other !== dir);
495
- const covers = (item) => {
496
- if (!named(item.name))
497
- return false;
498
- if (sameName.length < 2)
499
- return true;
500
- return itemPaths(item).some((path) => withinWorker(path, dir, otherDirs));
501
- };
502
- return graph.runtimeAgents.some(covers) || graph.artifacts.some(covers);
503
- }
504
- function citedFile(rootDir, path) {
505
- let rel = path.trim().replace(/\\/g, "/").replace(/:\d+(?::\d+)?$/, "");
506
- if (isAbsolute(rel))
507
- rel = relative(rootDir, rel).split("\\").join("/");
508
- return posix.normalize(rel).replace(/^\.\//, "");
509
- }
510
- function graphNamesDeclaration(graph, defined, rootDir) {
511
- const named = [...graph.runtimeAgents, ...graph.artifacts].filter((item) => namesClass(item.name, defined.className));
512
- if (named.length === 0)
513
- return false;
514
- const target = citedFile(rootDir, defined.path);
515
- const cited = named.map((item) => filePaths(item).map((path) => citedFile(rootDir, path)));
516
- if (cited.every((paths) => paths.length === 0))
517
- return true;
518
- return cited.some((paths) => paths.includes(target));
519
- }
520
- function filePaths(item) {
521
- const paths = [];
522
- if (typeof item.sourcePath === "string" && item.sourcePath.trim())
523
- paths.push(item.sourcePath);
524
- for (const entry of Array.isArray(item.evidence) ? item.evidence : []) {
525
- const path = entry && typeof entry === "object" ? entry.path : undefined;
526
- if (typeof path === "string" && path.trim())
527
- paths.push(path);
528
- }
529
- return paths;
530
- }
531
- function bindingReason(bound) {
532
- const what = bound.kind === "workflow" ? "Workflow" : "Durable Object";
533
- const where = bound.scriptName ? ` served by the external Worker "${bound.scriptName}"` : "";
534
- return `${what} binding ${bound.binding} -> class ${bound.className}${where}`;
535
- }
536
- function uniqueId(base, taken) {
537
- let id = base;
538
- for (let n = 2;taken.has(id); n += 1)
539
- id = `${base}-${n}`;
540
- taken.add(id);
541
- return id;
542
- }
543
- function mergeBoundRuntimeClasses(graph, rootDir) {
544
- if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
545
- return { added: 0 };
546
- let bound;
547
- let defined;
548
- try {
549
- bound = detectBoundRuntimeClasses(rootDir);
550
- defined = detectDefinedUnboundRuntimeClasses(rootDir);
551
- } catch {
552
- return { added: 0 };
553
- }
554
- const taken = new Set([
555
- ...graph.runtimeAgents.map((agent) => agent.id),
556
- ...graph.artifacts.map((artifact) => artifact.id)
557
- ]);
558
- let added = 0;
559
- for (const entry of bound) {
560
- if (graphNamesClass(graph, entry, bound))
561
- continue;
562
- const evidence = [{ path: entry.path, ...entry.line ? { line: entry.line } : {}, reason: bindingReason(entry) }];
563
- const slug = entry.className.replace(/[^A-Za-z0-9]+/g, "-").toLowerCase();
564
- if (entry.kind === "durable_object" && AGENT_CLASS.test(entry.className) && !entry.scriptName) {
565
- const agent = {
566
- id: uniqueId(`agent.bound.${slug}`, taken),
567
- name: entry.className,
568
- kind: "runtime_agent",
569
- purpose: "Agent class bound as a Durable Object.",
570
- root: ".",
571
- entrypointIds: [],
572
- channelAdapterIds: [],
573
- artifactIds: [],
574
- identityNamespaceIds: [],
575
- deploymentIds: [],
576
- frameworkIds: [],
577
- modelProviderIds: [],
578
- confidence: 0.6,
579
- evidence
580
- };
581
- graph.runtimeAgents.push(agent);
582
- } else {
583
- const artifact = {
584
- id: uniqueId(`entrypoint.bound.${slug}`, taken),
585
- type: "entrypoint",
586
- name: entry.className,
587
- scope: "shared",
588
- sourcePath: entry.path,
589
- usedByAgentIds: [],
590
- confidence: 0.6,
591
- evidence
592
- };
593
- graph.artifacts.push(artifact);
594
- }
595
- added += 1;
596
- }
597
- for (const entry of defined) {
598
- if (graphNamesDeclaration(graph, entry, rootDir))
599
- continue;
600
- const slug = entry.className.replace(/[^A-Za-z0-9]+/g, "-").toLowerCase();
601
- graph.artifacts.push({
602
- id: uniqueId(`entrypoint.defined.${slug}`, taken),
603
- type: "entrypoint",
604
- name: entry.className,
605
- scope: "shared",
606
- sourcePath: entry.path,
607
- usedByAgentIds: [],
608
- confidence: 0.6,
609
- evidence: [{ path: entry.path, line: entry.line, reason: definedReason(entry) }]
610
- });
611
- added += 1;
612
- }
613
- return { added };
614
- }
615
-
616
- // src/harness-component-status.ts
617
- var HARNESS_COMPONENT_STATUSES = new Set(["in_prod", "reachable", "defined_only"]);
618
- var STATUS_ALIASES = {
619
- in_prod: "in_prod",
620
- inprod: "in_prod",
621
- prod: "in_prod",
622
- production: "in_prod",
623
- in_production: "in_prod",
624
- deployed: "in_prod",
625
- live: "in_prod",
626
- reachable: "reachable",
627
- defined_only: "defined_only",
628
- dead: "defined_only",
629
- dead_code: "defined_only",
630
- unused: "defined_only",
631
- unreferenced: "defined_only",
632
- unreachable: "defined_only",
633
- orphan: "defined_only",
634
- orphaned: "defined_only"
635
- };
636
- function normalizeComponentStatus(value) {
637
- if (typeof value !== "string")
638
- return;
639
- return STATUS_ALIASES[value.trim().toLowerCase().replace(/[\s-]+/g, "_")];
640
- }
641
- var SKIPPED_DIRS2 = new Set(["node_modules", "dist", "build", "vendor", "coverage"]);
642
- var NON_DEPLOY_DIR = /^(?:test|tests|__tests__|fixtures?|__fixtures__|examples?|e2e)$/;
643
- var WRANGLER_FILE2 = /^wrangler(?:\.([\w.-]+))?\.(?:json|jsonc|toml)$/;
644
- var NON_DEPLOY_VARIANT = /(?:^|[.-])(?:preview|dev|local|test|example|sample)(?:$|[.-])/i;
645
- var CODE_FILE = /\.(?:[cm]?[jt]sx?)$/;
646
- var TEST_RUNNER_FILE = /(?:^|\/)__tests__\/|\.(?:test|spec)\.[cm]?[jt]sx?$/;
647
- var RESOLVE_EXTS = [".ts", ".tsx", ".mts", ".cts", ".js", ".jsx", ".mjs", ".cjs"];
648
- var TS_FOR_JS = { ".js": [".ts", ".tsx"], ".jsx": [".tsx"], ".mjs": [".mts"], ".cjs": [".cts"] };
649
- var MAX_FILES = 200000;
650
- var MAX_READ_BYTES = 1024 * 1024;
651
- var STATIC_IMPORT = /\b(?:import|export)\s+(type\s+)?([^'";]*?)\bfrom\s*['"]([^'"\n]+)['"]/g;
652
- var SIDE_EFFECT_IMPORT = /\bimport\s*['"]([^'"\n]+)['"]/g;
653
- var DYNAMIC_IMPORT = /\b(?:import|require)\s*\(\s*['"]([^'"\n]+)['"]\s*\)/g;
654
- var CLASS_DECL = /\bclass\s+([A-Za-z_$][\w$]*)/g;
655
- var SCRIPT_FILE = /(?:^|[\s;&|(])(?:bun|node|tsx)\s+((?:-{1,2}[\w-]+(?:=\S+)?\s+)*)(?:run\s+)?([^\s'"&|;()]+)/g;
656
- function listFiles(rootDir) {
657
- const files = new Set;
658
- const walk = (abs, rel) => {
659
- let entries;
660
- try {
661
- entries = readdirSync2(abs, { withFileTypes: true });
662
- } catch {
663
- return;
664
- }
665
- for (const entry of entries) {
666
- if (files.size >= MAX_FILES)
667
- return;
668
- const childRel = rel ? `${rel}/${entry.name}` : entry.name;
669
- if (entry.isDirectory()) {
670
- if (!entry.name.startsWith(".") && !SKIPPED_DIRS2.has(entry.name))
671
- walk(join2(abs, entry.name), childRel);
672
- } else if (entry.isFile()) {
673
- files.add(childRel);
674
- }
675
- }
676
- };
677
- walk(rootDir, "");
678
- return files;
679
- }
680
- function readCapped(abs) {
681
- const fd = openSync(abs, "r");
682
- try {
683
- const buffer = Buffer.alloc(MAX_READ_BYTES);
684
- const read = readSync(fd, buffer, 0, MAX_READ_BYTES, 0);
685
- return buffer.subarray(0, read).toString("utf8");
686
- } finally {
687
- closeSync(fd);
688
- }
689
- }
690
- function readJson(rootDir, rel) {
691
- try {
692
- const parsed = JSON.parse(stripJsonc(readFileSync2(join2(rootDir, rel), "utf8")));
693
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : undefined;
694
- } catch {
695
- return;
696
- }
697
- }
698
- function dirOf(rel) {
699
- const slash = rel.lastIndexOf("/");
700
- return slash < 0 ? "" : rel.slice(0, slash);
701
- }
702
- function joinRel(dir, path) {
703
- const joined = posix2.normalize(posix2.join(dir || ".", path));
704
- return joined === "." ? "" : joined.replace(/^\.\//, "").replace(/\/$/, "");
705
- }
706
- function isRecord(value) {
707
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
708
- }
709
- var PREFERRED_CONDITIONS = ["import", "default", "require", "node"];
710
- function exportTargets(value, out = []) {
711
- if (typeof value === "string")
712
- out.push(value);
713
- else if (Array.isArray(value))
714
- value.forEach((item) => exportTargets(item, out));
715
- else if (isRecord(value)) {
716
- const keys = Object.keys(value).filter((key) => key !== "types" && key !== "typings");
717
- const preferred = keys.filter((key) => PREFERRED_CONDITIONS.includes(key));
718
- for (const key of [...preferred, ...keys.filter((key2) => !preferred.includes(key2))])
719
- exportTargets(value[key], out);
720
- }
721
- return out;
722
- }
723
- function isTypeOnlyClause(clause) {
724
- const braces = /^\{([^{}]*)\}$/.exec(clause.trim());
725
- if (!braces)
726
- return false;
727
- const members = braces[1].split(",").map((member) => member.trim()).filter(Boolean);
728
- return members.length > 0 && members.every((member) => /^type\s+(?!as\s+[\w$]+$)\S/.test(member));
729
- }
730
- function stringLeaves(value, out = []) {
731
- if (typeof value === "string")
732
- out.push(value);
733
- else if (Array.isArray(value))
734
- value.forEach((item) => stringLeaves(item, out));
735
- else if (isRecord(value)) {
736
- for (const [key, item] of Object.entries(value)) {
737
- if (key !== "types" && key !== "typings")
738
- stringLeaves(item, out);
739
- }
740
- }
741
- return out;
742
- }
743
- function boundClassesOf(section) {
744
- const durable = isRecord(section.durable_objects) ? section.durable_objects.bindings : undefined;
745
- const raw = [...Array.isArray(durable) ? durable : [], ...Array.isArray(section.workflows) ? section.workflows : []];
746
- return raw.filter(isRecord).flatMap((entry) => typeof entry.class_name === "string" && entry.class_name ? [{ className: entry.class_name, ...typeof entry.script_name === "string" && entry.script_name ? { scriptName: entry.script_name } : {} }] : []);
747
- }
748
- var PRODUCTION_ENV = /^(?:production|prod)$/i;
749
- function parseWranglerToml(text) {
750
- const names = [];
751
- const mains = [];
752
- const otherMains = [];
753
- const boundClasses = [];
754
- let topName;
755
- let header = "";
756
- let binding;
757
- for (const rawLine of text.split(`
758
- `)) {
759
- const line = rawLine.replace(/\s+#.*$/, "").trim();
760
- const table = /^\[\[?\s*([^\]]+?)\s*\]\]?$/.exec(line);
761
- if (table) {
762
- header = table[1];
763
- binding = undefined;
764
- if (/(?:^|\.)(?:durable_objects\.bindings|workflows)$/.test(header) && line.startsWith("[[")) {
765
- binding = { className: "" };
766
- boundClasses.push(binding);
767
- }
768
- continue;
769
- }
770
- const pair = /^([\w.-]+)\s*=\s*["']([^"']*)["']/.exec(line);
771
- if (!pair)
772
- continue;
773
- const [, key, value] = pair;
774
- const envName = /^env\.([\w-]+)$/.exec(header)?.[1];
775
- const envSection = header === "" || envName !== undefined;
776
- if (binding && key === "class_name")
777
- binding.className = value;
778
- else if (binding && key === "script_name" && value)
779
- binding.scriptName = value;
780
- else if (envSection && key === "name") {
781
- if (header === "")
782
- topName = value;
783
- names.push(value);
784
- } else if (envSection && key === "main") {
785
- (envName === undefined || PRODUCTION_ENV.test(envName) ? mains : otherMains).push(value);
786
- }
787
- }
788
- return { name: topName, names, mains, otherMains, boundClasses: boundClasses.filter((entry) => entry.className) };
789
- }
790
- function readWranglerWorker(rootDir, rel) {
791
- const dir = dirOf(rel);
792
- const fileName = rel.slice(dir ? dir.length + 1 : 0);
793
- const variant = WRANGLER_FILE2.exec(fileName)?.[1] ?? "";
794
- let name;
795
- const names = [];
796
- const mains = [];
797
- const otherMains = [];
798
- const boundClasses = [];
799
- if (rel.endsWith(".toml")) {
800
- let text;
801
- try {
802
- text = readFileSync2(join2(rootDir, rel), "utf8");
803
- } catch {
804
- return;
805
- }
806
- const parsed = parseWranglerToml(text);
807
- name = parsed.name;
808
- names.push(...parsed.names);
809
- mains.push(...parsed.mains);
810
- otherMains.push(...parsed.otherMains);
811
- boundClasses.push(...parsed.boundClasses);
812
- } else {
813
- const config = readJson(rootDir, rel);
814
- if (!config)
815
- return;
816
- name = typeof config.name === "string" && config.name ? config.name : undefined;
817
- const sections = [[undefined, config], ...Object.entries(isRecord(config.env) ? config.env : {})];
818
- for (const [envName, section] of sections) {
819
- if (!isRecord(section))
820
- continue;
821
- if (typeof section.name === "string" && section.name)
822
- names.push(section.name);
823
- if (typeof section.main === "string" && section.main) {
824
- (envName === undefined || PRODUCTION_ENV.test(envName) ? mains : otherMains).push(section.main);
825
- }
826
- boundClasses.push(...boundClassesOf(section));
827
- }
828
- }
829
- const nonDeployDir = rel.split("/").slice(0, -1).some((segment) => NON_DEPLOY_DIR.test(segment));
830
- return {
831
- path: rel,
832
- deployed: Boolean(name) && !nonDeployDir && !NON_DEPLOY_VARIANT.test(variant) && !isTestWorkerConfig({ path: rel, name, mains }),
833
- names,
834
- mains: [...new Set(mains)].map((main) => joinRel(dir, main)),
835
- otherMains: [...new Set(otherMains)].filter((main) => !mains.includes(main)).map((main) => joinRel(dir, main)),
836
- boundClasses,
837
- reach: new Set
838
- };
839
- }
840
- function readWorkspacePackage(rootDir, rel) {
841
- const pkg = readJson(rootDir, rel);
842
- if (!pkg)
843
- return;
844
- const dir = dirOf(rel);
845
- const entries = [];
846
- const subpaths = new Map;
847
- const patterns = [];
848
- for (const field of ["main", "module"]) {
849
- if (typeof pkg[field] === "string")
850
- entries.push(pkg[field]);
851
- }
852
- if (typeof pkg.bin === "string")
853
- entries.push(pkg.bin);
854
- else if (isRecord(pkg.bin))
855
- entries.push(...stringLeaves(pkg.bin));
856
- const exportsField = pkg.exports;
857
- if (isRecord(exportsField) && Object.keys(exportsField).some((key) => key.startsWith("."))) {
858
- for (const [key, value] of Object.entries(exportsField)) {
859
- const targets = exportTargets(value);
860
- const star = key.indexOf("*");
861
- if (star >= 0) {
862
- if (key.indexOf("*", star + 1) < 0)
863
- patterns.push({ prefix: key.slice(0, star), suffix: key.slice(star + 1), targets });
864
- continue;
865
- }
866
- subpaths.set(key, targets);
867
- entries.push(...targets);
868
- }
869
- patterns.sort((a, b) => b.prefix.length - a.prefix.length || b.suffix.length - a.suffix.length);
870
- } else if (exportsField !== undefined) {
871
- const targets = exportTargets(exportsField);
872
- subpaths.set(".", targets);
873
- entries.push(...targets);
874
- }
875
- const scriptFiles = [];
876
- if (isRecord(pkg.scripts)) {
877
- for (const command of Object.values(pkg.scripts)) {
878
- if (typeof command !== "string")
879
- continue;
880
- for (const match of command.matchAll(SCRIPT_FILE))
881
- scriptFiles.push(match[2]);
882
- }
883
- }
884
- return {
885
- dir,
886
- ...typeof pkg.name === "string" && pkg.name ? { name: pkg.name } : {},
887
- entries: entries.filter((entry) => !entry.includes("*")),
888
- subpaths,
889
- patterns,
890
- scriptFiles
891
- };
892
- }
893
- function readPathAliases(rootDir, rel, depth = 0) {
894
- const config = readJson(rootDir, rel);
895
- if (!config)
896
- return [];
897
- const options = isRecord(config.compilerOptions) ? config.compilerOptions : {};
898
- if (isRecord(options.paths)) {
899
- const base = joinRel(dirOf(rel), typeof options.baseUrl === "string" ? options.baseUrl : ".");
900
- return Object.entries(options.paths).flatMap(([pattern, targets]) => {
901
- if (!Array.isArray(targets))
902
- return [];
903
- const star = pattern.indexOf("*");
904
- return [{
905
- prefix: star < 0 ? pattern : pattern.slice(0, star),
906
- suffix: star < 0 ? "" : pattern.slice(star + 1),
907
- wildcard: star >= 0,
908
- targets: targets.filter((target) => typeof target === "string").map((target) => joinRel(base, target))
909
- }];
910
- });
911
- }
912
- if (depth < 3 && typeof config.extends === "string" && config.extends.startsWith(".")) {
913
- const parent = joinRel(dirOf(rel), config.extends.endsWith(".json") ? config.extends : `${config.extends}.json`);
914
- return readPathAliases(rootDir, parent, depth + 1);
915
- }
916
- return [];
917
- }
918
- function analyzeRepository(rootDir) {
919
- const files = listFiles(rootDir);
920
- const workers = [];
921
- const packages = [];
922
- for (const rel of files) {
923
- const fileName = rel.slice(rel.lastIndexOf("/") + 1);
924
- if (WRANGLER_FILE2.test(fileName)) {
925
- const worker = readWranglerWorker(rootDir, rel);
926
- if (worker)
927
- workers.push(worker);
928
- } else if (fileName === "package.json") {
929
- const pkg = readWorkspacePackage(rootDir, rel);
930
- if (pkg)
931
- packages.push(pkg);
932
- }
933
- }
934
- workers.sort((a, b) => a.path.localeCompare(b.path));
935
- const packagesByName = new Map(packages.filter((pkg) => pkg.name).map((pkg) => [pkg.name, pkg]));
936
- const packageDirs = new Set(packages.map((pkg) => pkg.dir));
937
- const resolveFile = (base) => {
938
- if (!base || base.startsWith(".."))
939
- return;
940
- const ext = posix2.extname(base);
941
- for (const tsExt of TS_FOR_JS[ext] ?? []) {
942
- const candidate = base.slice(0, -ext.length) + tsExt;
943
- if (files.has(candidate))
944
- return candidate;
945
- }
946
- if (files.has(base))
947
- return base;
948
- for (const candidate of RESOLVE_EXTS)
949
- if (files.has(base + candidate))
950
- return base + candidate;
951
- for (const candidate of RESOLVE_EXTS)
952
- if (files.has(`${base}/index${candidate}`))
953
- return `${base}/index${candidate}`;
954
- return;
955
- };
956
- const resolveEntry = (dir, entry) => {
957
- const direct = resolveFile(joinRel(dir, entry));
958
- if (direct)
959
- return direct;
960
- const fromSource = entry.replace(/^\.?\/?(?:dist|build|lib|out)\//, "src/").replace(/\.d\.[cm]?ts$/, ".ts");
961
- return fromSource !== entry ? resolveFile(joinRel(dir, fromSource)) : undefined;
962
- };
963
- const aliasCache = new Map;
964
- const aliasesFor = (dir) => {
965
- const cached = aliasCache.get(dir);
966
- if (cached)
967
- return cached;
968
- const tsconfig = dir ? `${dir}/tsconfig.json` : "tsconfig.json";
969
- const aliases = files.has(tsconfig) ? readPathAliases(rootDir, tsconfig) : dir ? aliasesFor(dirOf(dir)) : [];
970
- aliasCache.set(dir, aliases);
971
- return aliases;
972
- };
973
- const resolvePackage = (specifier) => {
974
- const parts = specifier.split("/");
975
- const nameLength = specifier.startsWith("@") ? 2 : 1;
976
- const name = parts.slice(0, nameLength).join("/");
977
- const subpath = parts.slice(nameLength).join("/");
978
- const pkg = packagesByName.get(name);
979
- if (pkg) {
980
- const key = subpath ? `./${subpath}` : ".";
981
- let targets = pkg.subpaths.get(key);
982
- if (!targets && subpath) {
983
- const pattern = pkg.patterns.find((entry) => key.startsWith(entry.prefix) && key.endsWith(entry.suffix) && key.length >= entry.prefix.length + entry.suffix.length);
984
- const captured = pattern ? key.slice(pattern.prefix.length, key.length - pattern.suffix.length) : "";
985
- targets = pattern ? pattern.targets.map((target) => target.split("*").join(captured)) : [];
986
- }
987
- for (const target of targets ?? pkg.entries) {
988
- const resolved = resolveEntry(pkg.dir, target);
989
- if (resolved)
990
- return resolved;
991
- }
992
- if (subpath)
993
- return resolveFile(joinRel(pkg.dir, subpath)) ?? resolveFile(joinRel(pkg.dir, `src/${subpath}`));
994
- return resolveFile(joinRel(pkg.dir, "src/index")) ?? resolveFile(joinRel(pkg.dir, "index"));
995
- }
996
- const leaf = parts[nameLength - 1];
997
- for (const parent of ["packages", "apps", "libs"]) {
998
- const dir = `${parent}/${leaf}`;
999
- if (packageDirs.has(dir))
1000
- continue;
1001
- const resolved = subpath ? resolveFile(`${dir}/src/${subpath}`) ?? resolveFile(`${dir}/${subpath}`) : resolveFile(`${dir}/src/index`) ?? resolveFile(`${dir}/index`);
1002
- if (resolved)
1003
- return resolved;
1004
- }
1005
- return;
1006
- };
1007
- const resolveSpecifier = (raw, from) => {
1008
- const specifier = raw.split("?")[0];
1009
- if (!specifier || specifier.startsWith("node:") || specifier.startsWith("/"))
1010
- return;
1011
- if (specifier.startsWith("."))
1012
- return resolveFile(joinRel(dirOf(from), specifier));
1013
- for (const alias of aliasesFor(dirOf(from))) {
1014
- let captured;
1015
- if (!alias.wildcard && specifier === alias.prefix)
1016
- captured = "";
1017
- else if (alias.wildcard && specifier.startsWith(alias.prefix) && specifier.endsWith(alias.suffix) && specifier.length >= alias.prefix.length + alias.suffix.length) {
1018
- captured = specifier.slice(alias.prefix.length, specifier.length - alias.suffix.length);
1019
- }
1020
- if (captured === undefined)
1021
- continue;
1022
- for (const target of alias.targets) {
1023
- const resolved = resolveFile(alias.wildcard ? target.replace("*", captured) : target);
1024
- if (resolved)
1025
- return resolved;
1026
- }
1027
- }
1028
- return resolvePackage(specifier);
1029
- };
1030
- const classFiles = new Map;
1031
- const edgeCache = new Map;
1032
- const edgesOf = (file) => {
1033
- const cached = edgeCache.get(file);
1034
- if (cached)
1035
- return cached;
1036
- const edges = [];
1037
- edgeCache.set(file, edges);
1038
- if (!CODE_FILE.test(file))
1039
- return edges;
1040
- let text;
1041
- try {
1042
- text = readCapped(join2(rootDir, file));
1043
- } catch {
1044
- return edges;
1045
- }
1046
- text = text.replace(/^\s*\/\/.*$/gm, "");
1047
- const specifiers = [];
1048
- for (const match of text.matchAll(STATIC_IMPORT)) {
1049
- if (!match[1] && !isTypeOnlyClause(match[2]))
1050
- specifiers.push(match[3]);
1051
- }
1052
- for (const match of text.matchAll(SIDE_EFFECT_IMPORT))
1053
- specifiers.push(match[1]);
1054
- for (const match of text.matchAll(DYNAMIC_IMPORT))
1055
- specifiers.push(match[1]);
1056
- for (const specifier of new Set(specifiers)) {
1057
- const resolved = resolveSpecifier(specifier, file);
1058
- if (resolved && resolved !== file)
1059
- edges.push(resolved);
1060
- }
1061
- for (const match of text.matchAll(CLASS_DECL)) {
1062
- const list = classFiles.get(match[1]) ?? [];
1063
- if (!list.includes(file))
1064
- list.push(file);
1065
- classFiles.set(match[1], list);
1066
- }
1067
- return edges;
1068
- };
1069
- const walk = (starts, seen = new Set) => {
1070
- const queue = [...starts].filter((start) => Boolean(start) && !seen.has(start));
1071
- for (const start of queue)
1072
- seen.add(start);
1073
- while (queue.length > 0) {
1074
- const file = queue.pop();
1075
- for (const next of edgesOf(file)) {
1076
- if (!seen.has(next)) {
1077
- seen.add(next);
1078
- queue.push(next);
1079
- }
1080
- }
1081
- }
1082
- return seen;
1083
- };
1084
- const inProd = new Set;
1085
- for (const worker of workers) {
1086
- worker.reach = walk(worker.mains.map((main) => resolveEntry("", main)));
1087
- if (!worker.deployed)
1088
- continue;
1089
- inProd.add(worker.path);
1090
- for (const file of worker.reach)
1091
- inProd.add(file);
1092
- }
1093
- const otherStarts = workers.filter((worker) => !worker.deployed).map((worker) => worker.path);
1094
- for (const worker of workers) {
1095
- if (!worker.deployed)
1096
- otherStarts.push(...worker.reach);
1097
- otherStarts.push(...worker.otherMains.map((main) => resolveEntry("", main)));
1098
- }
1099
- for (const pkg of packages) {
1100
- otherStarts.push(...pkg.entries.map((entry) => resolveEntry(pkg.dir, entry)));
1101
- otherStarts.push(...pkg.scriptFiles.map((script) => resolveFile(joinRel(pkg.dir, script))));
1102
- }
1103
- const all = walk(otherStarts, new Set(inProd));
1104
- const reachable = new Set([...all].filter((file) => !inProd.has(file)));
1105
- return { inProd, reachable, files, workers, classFiles, resolveFile };
1106
- }
1107
- function norm2(value) {
1108
- return typeof value === "string" ? value.toLowerCase().replace(/[^a-z0-9]/g, "") : "";
1109
- }
1110
- function normalizeItemPath(rootDir, path) {
1111
- let rel = path.trim().replace(/\\/g, "/").replace(/:\d+(?::\d+)?$/, "");
1112
- if (isAbsolute2(rel))
1113
- rel = relative2(rootDir, rel).split("\\").join("/");
1114
- return joinRel("", rel);
1115
- }
1116
- function definingPath(item) {
1117
- if (typeof item.sourcePath === "string" && item.sourcePath.trim())
1118
- return item.sourcePath;
1119
- for (const entry of Array.isArray(item.evidence) ? item.evidence : []) {
1120
- const path = isRecord(entry) ? entry.path : undefined;
1121
- if (typeof path === "string" && path.trim())
1122
- return path;
1123
- }
1124
- return;
1125
- }
1126
- function boundClassStatus(analysis, worker, item) {
1127
- const wanted = new Set([norm2(item.name), norm2(typeof item.id === "string" ? item.id.split(".").pop() : "")]);
1128
- const bound = worker.boundClasses.find((entry) => wanted.has(norm2(entry.className)));
1129
- if (!bound)
1130
- return null;
1131
- const servers = bound.scriptName ? analysis.workers.filter((other) => other.names.includes(bound.scriptName)) : [worker];
1132
- const declared = analysis.classFiles.get(bound.className) ?? [];
1133
- if (servers.some((server) => server.deployed && declared.some((file) => server.reach.has(file))))
1134
- return "in_prod";
1135
- if (declared.some((file) => analysis.inProd.has(file) || analysis.reachable.has(file)))
1136
- return "reachable";
1137
- return;
1138
- }
1139
- function itemStatus(analysis, rootDir, item) {
1140
- const raw = definingPath(item);
1141
- if (!raw)
1142
- return;
1143
- const path = normalizeItemPath(rootDir, raw);
1144
- const worker = analysis.workers.find((entry) => entry.path === path);
1145
- if (worker) {
1146
- const classStatus = boundClassStatus(analysis, worker, item);
1147
- if (classStatus !== null)
1148
- return classStatus;
1149
- return worker.deployed ? "in_prod" : "reachable";
1150
- }
1151
- const file = analysis.files.has(path) ? path : analysis.resolveFile(path);
1152
- if (!file)
1153
- return;
1154
- if (analysis.inProd.has(file))
1155
- return "in_prod";
1156
- if (analysis.reachable.has(file))
1157
- return "reachable";
1158
- return CODE_FILE.test(file) && !TEST_RUNNER_FILE.test(file) ? "defined_only" : undefined;
1159
- }
1160
- function tagComponentStatus(graph, rootDir) {
1161
- if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
1162
- return { tagged: 0, counts: {} };
1163
- try {
1164
- const analysis = analyzeRepository(rootDir);
1165
- const counts = { in_prod: 0, reachable: 0, defined_only: 0, unknown: 0 };
1166
- let tagged = 0;
1167
- const items = [
1168
- ...Array.isArray(graph.runtimeAgents) ? graph.runtimeAgents : [],
1169
- ...Array.isArray(graph.artifacts) ? graph.artifacts : []
1170
- ];
1171
- for (const item of items) {
1172
- if (!isRecord(item))
1173
- continue;
1174
- if (item.status === undefined || !HARNESS_COMPONENT_STATUSES.has(item.status)) {
1175
- const status = itemStatus(analysis, rootDir, item);
1176
- if (status) {
1177
- item.status = status;
1178
- tagged += 1;
1179
- } else {
1180
- delete item.status;
1181
- }
1182
- }
1183
- counts[item.status ?? "unknown"] += 1;
1184
- }
1185
- if (isRecord(graph.scan)) {
1186
- graph.scan.componentStatusCounts = counts;
1187
- }
1188
- return { tagged, counts };
1189
- } catch {
1190
- return { tagged: 0, counts: {} };
1191
- }
1192
- }
1193
-
1194
- // src/harness-report.ts
21
+ import { basename, dirname, join, relative, resolve } from "node:path";
1195
22
  var HARNESS_REPORT_SCHEMA_VERSION = "harness_report.v0.1";
1196
23
  var HARNESS_REPORT_VALIDATION_SCHEMA_VERSION = "harness_report_validation.v0.1";
1197
24
  var HARNESS_REPORT_APPROVAL_SCHEMA_VERSION = "harness_report_approval.v0.1";
1198
- var HARNESS_REPORT_PATH = join3(".moda", "harness-report.json");
1199
- var HARNESS_REPORT_MARKDOWN_PATH = join3(".moda", "HARNESS_REPORT.md");
1200
- var HARNESS_REPORT_VALIDATION_PATH = join3(".moda", "harness-report-validation.json");
1201
- var HARNESS_REPORT_APPROVAL_PATH = join3(".moda", "harness-report-approval.json");
25
+ var HARNESS_REPORT_PATH = join(".moda", "harness-report.json");
26
+ var HARNESS_REPORT_MARKDOWN_PATH = join(".moda", "HARNESS_REPORT.md");
27
+ var HARNESS_REPORT_VALIDATION_PATH = join(".moda", "harness-report-validation.json");
28
+ var HARNESS_REPORT_APPROVAL_PATH = join(".moda", "harness-report-approval.json");
1202
29
  var HARNESS_ANALYZE_CONCERNS = ["topology", "tools", "prompts", "evals"];
1203
30
  var HARNESS_GRAPH_ARRAY_FIELDS = [
1204
31
  "agentFamilies",
@@ -1477,7 +304,7 @@ function validateHarnessReport(report, rootDir, options) {
1477
304
  check("graph_present", Boolean(report?.graph?.schemaVersion), "Report must include the sanitized harness graph.");
1478
305
  check("citations_present", Array.isArray(report?.citations) && report.citations.length > 0, "Report must include citations.");
1479
306
  check("claims_present", Array.isArray(report?.claims) && report.claims.length > 0, "Report must include claims.");
1480
- const syncPlan = isRecord2(report?.syncPlan) ? report.syncPlan : undefined;
307
+ const syncPlan = isRecord(report?.syncPlan) ? report.syncPlan : undefined;
1481
308
  check("sync_plan_present", Boolean(syncPlan), "Report must include syncPlan.");
1482
309
  if (syncPlan) {
1483
310
  check("sync_plan_command", typeof syncPlan.command === "string" && syncPlan.command.length > 0, "Report syncPlan must include command.");
@@ -1516,7 +343,7 @@ function validateHarnessReport(report, rootDir, options) {
1516
343
  const requireLineCitations = report?.analyst?.mode === "agent";
1517
344
  for (const [index, citation] of citations.entries()) {
1518
345
  const label = citationLabel(citation, index);
1519
- if (!isRecord2(citation)) {
346
+ if (!isRecord(citation)) {
1520
347
  errors.push(`Citation ${index + 1} must be an object.`);
1521
348
  continue;
1522
349
  }
@@ -1543,7 +370,7 @@ function validateHarnessReport(report, rootDir, options) {
1543
370
  const claimIds = new Set;
1544
371
  for (const [index, claim] of claims.entries()) {
1545
372
  const label = claimLabel(claim, index);
1546
- if (!isRecord2(claim)) {
373
+ if (!isRecord(claim)) {
1547
374
  errors.push(`Claim ${index + 1} must be an object.`);
1548
375
  continue;
1549
376
  }
@@ -1614,7 +441,7 @@ function validateHarnessReport(report, rootDir, options) {
1614
441
  if (unknowns.length > 0) {
1615
442
  warn("unknowns_present", `${unknowns.length} open harness question(s) require human review.`);
1616
443
  for (const [index, unknown] of unknowns.entries()) {
1617
- if (!isRecord2(unknown)) {
444
+ if (!isRecord(unknown)) {
1618
445
  errors.push(`Unknown ${index + 1} must be an object.`);
1619
446
  continue;
1620
447
  }
@@ -1642,7 +469,7 @@ function validateHarnessReport(report, rootDir, options) {
1642
469
  };
1643
470
  }
1644
471
  function refutedToolCandidateCount(graph) {
1645
- const unknowns = Array.isArray(graph.unknowns) ? graph.unknowns.filter(isRecord2) : [];
472
+ const unknowns = Array.isArray(graph.unknowns) ? graph.unknowns.filter(isRecord) : [];
1646
473
  let count = 0;
1647
474
  for (const unknown of unknowns) {
1648
475
  const label = `${String(unknown.id ?? "")} ${String(unknown.question ?? "")}`;
@@ -1661,8 +488,8 @@ function validateDeterministicFloor(report, floor, check, warn, concern) {
1661
488
  return;
1662
489
  const applyToolFloor = concern === undefined || concern === "tools";
1663
490
  const applyTopologyFloors = concern === undefined || concern === "topology";
1664
- const graph = isRecord2(report?.graph) ? report.graph : {};
1665
- const toolArtifactCount = Array.isArray(graph.artifacts) ? graph.artifacts.filter((artifact) => isRecord2(artifact) && artifact.type === "tool").length : 0;
491
+ const graph = isRecord(report?.graph) ? report.graph : {};
492
+ const toolArtifactCount = Array.isArray(graph.artifacts) ? graph.artifacts.filter((artifact) => isRecord(artifact) && artifact.type === "tool").length : 0;
1666
493
  const providerCount = safeArrayLength(graph.modelProviders);
1667
494
  const runtimeAgentCount = safeArrayLength(graph.runtimeAgents);
1668
495
  if (applyToolFloor && typeof floor.toolCandidates === "number" && floor.toolCandidates >= 5) {
@@ -1711,9 +538,9 @@ async function approveHarnessReport(options) {
1711
538
  approved: true,
1712
539
  approvedAt: new Date().toISOString(),
1713
540
  approvedBy,
1714
- reportPath: normalizePath(relative3(options.rootDir, options.reportPath)) || HARNESS_REPORT_PATH
541
+ reportPath: normalizePath(relative(options.rootDir, options.reportPath)) || HARNESS_REPORT_PATH
1715
542
  };
1716
- writeJson(join3(options.rootDir, HARNESS_REPORT_APPROVAL_PATH), approval);
543
+ writeJson(join(options.rootDir, HARNESS_REPORT_APPROVAL_PATH), approval);
1717
544
  return { report, validation, approval };
1718
545
  }
1719
546
  function loadHarnessReportForSync(rootDir, reportPath, options) {
@@ -1723,37 +550,37 @@ function loadHarnessReportForSync(rootDir, reportPath, options) {
1723
550
  throw new CliInputError("Harness report validation failed; cannot sync.", validation.errors.slice(0, 5).join(`
1724
551
  `));
1725
552
  }
1726
- const approvalPath = join3(rootDir, HARNESS_REPORT_APPROVAL_PATH);
1727
- const approval = existsSync(approvalPath) ? JSON.parse(readFileSync3(approvalPath, "utf8")) : null;
553
+ const approvalPath = join(rootDir, HARNESS_REPORT_APPROVAL_PATH);
554
+ const approval = existsSync(approvalPath) ? JSON.parse(readFileSync(approvalPath, "utf8")) : null;
1728
555
  const approved = approval?.schemaVersion === HARNESS_REPORT_APPROVAL_SCHEMA_VERSION && approval.reportId === report.reportId && approval.reportHash === hashHarnessReport(report) && approval.approved === true;
1729
556
  return { report, validation, approval, approved };
1730
557
  }
1731
558
  function readHarnessReport(reportPath) {
1732
- return normalizeHarnessReport(JSON.parse(readFileSync3(reportPath, "utf8")));
559
+ return normalizeHarnessReport(JSON.parse(readFileSync(reportPath, "utf8")));
1733
560
  }
1734
561
  function normalizeHarnessReport(value) {
1735
562
  const report = cloneJson(value);
1736
- if (!isRecord2(report.graph))
563
+ if (!isRecord(report.graph))
1737
564
  return report;
1738
565
  const graph = report.graph;
1739
566
  if (typeof graph.schemaVersion !== "string" && typeof graph.graphSchemaVersion === "string") {
1740
567
  graph.schemaVersion = graph.graphSchemaVersion;
1741
568
  }
1742
- if (typeof graph.schemaVersion !== "string" && isRecord2(report.source) && typeof report.source.graphSchemaVersion === "string") {
569
+ if (typeof graph.schemaVersion !== "string" && isRecord(report.source) && typeof report.source.graphSchemaVersion === "string") {
1743
570
  graph.schemaVersion = report.source.graphSchemaVersion;
1744
571
  }
1745
572
  if (typeof graph.harnessId !== "string" && typeof report.harnessId === "string") {
1746
573
  graph.harnessId = report.harnessId;
1747
574
  }
1748
- if (!isRecord2(graph.repo) && isRecord2(report.repo)) {
575
+ if (!isRecord(graph.repo) && isRecord(report.repo)) {
1749
576
  graph.repo = report.repo;
1750
577
  }
1751
- if (!isRecord2(graph.tenant) && isRecord2(report.tenant)) {
578
+ if (!isRecord(graph.tenant) && isRecord(report.tenant)) {
1752
579
  graph.tenant = report.tenant;
1753
580
  }
1754
- if (!isRecord2(graph.scan)) {
1755
- const source = isRecord2(report.source) ? report.source : {};
1756
- const readPlan = isRecord2(source.readPlan) ? source.readPlan : defaultHarnessReadPlan();
581
+ if (!isRecord(graph.scan)) {
582
+ const source = isRecord(report.source) ? report.source : {};
583
+ const readPlan = isRecord(source.readPlan) ? source.readPlan : defaultHarnessReadPlan();
1757
584
  graph.scan = {
1758
585
  createdAt: typeof report.createdAt === "string" ? report.createdAt : new Date().toISOString(),
1759
586
  scannerVersion: analystAdapter(report),
@@ -1779,7 +606,7 @@ function normalizeHarnessReport(value) {
1779
606
  return report;
1780
607
  }
1781
608
  function normalizeHarnessSyncPlan(report) {
1782
- const syncPlan = isRecord2(report.syncPlan) ? report.syncPlan : {};
609
+ const syncPlan = isRecord(report.syncPlan) ? report.syncPlan : {};
1783
610
  if (typeof syncPlan.command !== "string" || syncPlan.command.length === 0) {
1784
611
  syncPlan.command = `moda harness sync --from-report ${HARNESS_REPORT_PATH}`;
1785
612
  }
@@ -1804,7 +631,7 @@ function normalizeRelationshipEvidence(graph) {
1804
631
  return;
1805
632
  const evidenceById = graphEvidenceById(graph);
1806
633
  for (const relationship of relationships) {
1807
- if (!isRecord2(relationship))
634
+ if (!isRecord(relationship))
1808
635
  continue;
1809
636
  if (Array.isArray(relationship.evidence) && relationship.evidence.length > 0)
1810
637
  continue;
@@ -1827,9 +654,9 @@ function graphEvidenceById(graph) {
1827
654
  if (!Array.isArray(collection))
1828
655
  continue;
1829
656
  for (const item of collection) {
1830
- if (!isRecord2(item) || typeof item.id !== "string" || !Array.isArray(item.evidence))
657
+ if (!isRecord(item) || typeof item.id !== "string" || !Array.isArray(item.evidence))
1831
658
  continue;
1832
- const evidence = item.evidence.filter((entry) => isRecord2(entry) && typeof entry.path === "string" && typeof entry.reason === "string").map((entry) => normalizeEvidenceEntry(entry));
659
+ const evidence = item.evidence.filter((entry) => isRecord(entry) && typeof entry.path === "string" && typeof entry.reason === "string").map((entry) => normalizeEvidenceEntry(entry));
1833
660
  if (evidence.length > 0)
1834
661
  byId.set(item.id, evidence);
1835
662
  }
@@ -1853,7 +680,7 @@ function normalizeEvidenceEntry(item) {
1853
680
  return line ? { path: item.path, reason: item.reason, line } : { path: item.path, reason: item.reason };
1854
681
  }
1855
682
  function normalizeHarnessClaim(claim, graph) {
1856
- if (!isRecord2(claim))
683
+ if (!isRecord(claim))
1857
684
  return claim;
1858
685
  if (typeof claim.subjectId !== "string" && Array.isArray(claim.subjectIds) && typeof claim.subjectIds[0] === "string") {
1859
686
  claim.subjectId = claim.subjectIds[0];
@@ -1901,10 +728,10 @@ function validateGraphItemShapes(graph, errors) {
1901
728
  if (typeof graph.harnessId !== "string" || graph.harnessId.length === 0) {
1902
729
  errors.push("Graph must include harnessId.");
1903
730
  }
1904
- if (!isRecord2(graph.repo)) {
731
+ if (!isRecord(graph.repo)) {
1905
732
  errors.push("Graph must include repo metadata.");
1906
733
  }
1907
- if (!isRecord2(graph.scan)) {
734
+ if (!isRecord(graph.scan)) {
1908
735
  errors.push("Graph must include scan metadata.");
1909
736
  }
1910
737
  validateGraphCollection(graph, errors, "runtimeAgents", {
@@ -1976,7 +803,7 @@ function validateGraphCollection(graph, errors, field, shape) {
1976
803
  return;
1977
804
  for (const [index, item] of collection.entries()) {
1978
805
  const label = graphItemLabel(field, item, index);
1979
- if (!isRecord2(item)) {
806
+ if (!isRecord(item)) {
1980
807
  errors.push(`Graph ${field} item ${index + 1} must be an object.`);
1981
808
  continue;
1982
809
  }
@@ -2005,7 +832,7 @@ function validateGraphCollection(graph, errors, field, shape) {
2005
832
  }
2006
833
  if (Array.isArray(item.evidence)) {
2007
834
  for (const [evidenceIndex, evidence] of item.evidence.entries()) {
2008
- if (!isRecord2(evidence) || typeof evidence.path !== "string" || typeof evidence.reason !== "string") {
835
+ if (!isRecord(evidence) || typeof evidence.path !== "string" || typeof evidence.reason !== "string") {
2009
836
  errors.push(`Graph ${label} evidence ${evidenceIndex + 1} must include path and reason.`);
2010
837
  continue;
2011
838
  }
@@ -2038,7 +865,7 @@ function artifactHasRetrievableLocation(item) {
2038
865
  }
2039
866
  function validateCaptureQuality(graph, warn) {
2040
867
  const scan = graph.scan;
2041
- if (!isRecord2(scan))
868
+ if (!isRecord(scan))
2042
869
  return;
2043
870
  if (scan.truncated === true) {
2044
871
  const reasons = Array.isArray(scan.truncationReasons) && scan.truncationReasons.length > 0 ? scan.truncationReasons.map((reason) => String(reason)).join(", ") : "scan budget or upload cap reached";
@@ -2053,12 +880,12 @@ function isWholeFileArtifact(item) {
2053
880
  return false;
2054
881
  if (!Array.isArray(item.evidence))
2055
882
  return false;
2056
- return item.evidence.some((entry) => isRecord2(entry) && entry.path === item.sourcePath);
883
+ return item.evidence.some((entry) => isRecord(entry) && entry.path === item.sourcePath);
2057
884
  }
2058
885
  function hasEvidenceLine(evidence) {
2059
886
  if (!Array.isArray(evidence))
2060
887
  return false;
2061
- return evidence.some((entry) => isRecord2(entry) && typeof entry.path === "string" && typeof entry.reason === "string" && evidenceLine({
888
+ return evidence.some((entry) => isRecord(entry) && typeof entry.path === "string" && typeof entry.reason === "string" && evidenceLine({
2062
889
  path: entry.path,
2063
890
  reason: entry.reason,
2064
891
  line: typeof entry.line === "number" ? entry.line : undefined
@@ -2087,7 +914,7 @@ var HARNESS_ARTIFACT_TYPES = new Set([
2087
914
  "unknown"
2088
915
  ]);
2089
916
  function normalizeGraphItemFieldAliases(collection, item) {
2090
- if (!isRecord2(item))
917
+ if (!isRecord(item))
2091
918
  return;
2092
919
  if ((collection === "runtimeAgents" || collection === "artifacts") && item.status !== undefined) {
2093
920
  const status = normalizeComponentStatus(item.status);
@@ -2164,14 +991,14 @@ function firstEvidencePath(item) {
2164
991
  if (!Array.isArray(item.evidence))
2165
992
  return;
2166
993
  for (const evidence of item.evidence) {
2167
- if (isRecord2(evidence) && typeof evidence.path === "string" && evidence.path.length > 0) {
994
+ if (isRecord(evidence) && typeof evidence.path === "string" && evidence.path.length > 0) {
2168
995
  return evidence.path;
2169
996
  }
2170
997
  }
2171
998
  return;
2172
999
  }
2173
1000
  function stampRemoteSnapshotTruncation(report) {
2174
- const scanRecord = isRecord2(report.graph.scan) ? report.graph.scan : {};
1001
+ const scanRecord = isRecord(report.graph.scan) ? report.graph.scan : {};
2175
1002
  const truncationReasons = Array.isArray(scanRecord.truncationReasons) ? scanRecord.truncationReasons.map(String) : [];
2176
1003
  const stamped = {
2177
1004
  ...report,
@@ -2196,12 +1023,12 @@ function requiresGraphItemConfidence(collection) {
2196
1023
  return collection !== "relationships" && collection !== "unknowns";
2197
1024
  }
2198
1025
  function graphItemLabel(collection, item, index) {
2199
- if (isRecord2(item) && typeof item.id === "string" && item.id.length > 0)
1026
+ if (isRecord(item) && typeof item.id === "string" && item.id.length > 0)
2200
1027
  return `${collection}.${item.id}`;
2201
1028
  return `${collection} item ${index + 1}`;
2202
1029
  }
2203
1030
  function normalizeConfidenceField(value, fallback) {
2204
- if (!isRecord2(value))
1031
+ if (!isRecord(value))
2205
1032
  return;
2206
1033
  const confidence = confidenceNumberFromUnknown(value.confidence);
2207
1034
  if (confidence !== undefined)
@@ -2246,7 +1073,7 @@ function inferClaimKind(subjectId, graph) {
2246
1073
  ];
2247
1074
  for (const [field, kind] of collectionKinds) {
2248
1075
  const collection = graph[field];
2249
- if (Array.isArray(collection) && collection.some((item) => isRecord2(item) && item.id === subjectId)) {
1076
+ if (Array.isArray(collection) && collection.some((item) => isRecord(item) && item.id === subjectId)) {
2250
1077
  return kind;
2251
1078
  }
2252
1079
  }
@@ -2323,7 +1150,7 @@ function normalizeClaimKind(value, subjectId, graph) {
2323
1150
  return inferred;
2324
1151
  }
2325
1152
  function analystAdapter(report) {
2326
- const analyst = isRecord2(report.analyst) ? report.analyst : {};
1153
+ const analyst = isRecord(report.analyst) ? report.analyst : {};
2327
1154
  return typeof analyst.adapter === "string" ? analyst.adapter : "external-analyst";
2328
1155
  }
2329
1156
  function defaultHarnessReadPlan() {
@@ -2384,12 +1211,12 @@ function resolveHarnessReportPath(rootDir, value) {
2384
1211
  }
2385
1212
  function writeHarnessReportArtifacts(options) {
2386
1213
  const written = [];
2387
- writeJson(join3(options.rootDir, HARNESS_REPORT_PATH), options.report);
1214
+ writeJson(join(options.rootDir, HARNESS_REPORT_PATH), options.report);
2388
1215
  written.push(HARNESS_REPORT_PATH);
2389
- writeJson(join3(options.rootDir, HARNESS_REPORT_VALIDATION_PATH), options.validation);
1216
+ writeJson(join(options.rootDir, HARNESS_REPORT_VALIDATION_PATH), options.validation);
2390
1217
  written.push(HARNESS_REPORT_VALIDATION_PATH);
2391
1218
  if (options.markdown) {
2392
- const markdownPath = join3(options.rootDir, HARNESS_REPORT_MARKDOWN_PATH);
1219
+ const markdownPath = join(options.rootDir, HARNESS_REPORT_MARKDOWN_PATH);
2393
1220
  mkdirSync(dirname(markdownPath), { recursive: true });
2394
1221
  writeFileSync(markdownPath, renderHarnessReportMarkdown(options.report, options.validation));
2395
1222
  written.push(HARNESS_REPORT_MARKDOWN_PATH);
@@ -2397,7 +1224,7 @@ function writeHarnessReportArtifacts(options) {
2397
1224
  return written;
2398
1225
  }
2399
1226
  function renderHarnessReportMarkdown(report, validation) {
2400
- const summary = isRecord2(report.summary) ? report.summary : {};
1227
+ const summary = isRecord(report.summary) ? report.summary : {};
2401
1228
  const citations = Array.isArray(report.citations) ? report.citations : [];
2402
1229
  const claims = Array.isArray(report.claims) ? report.claims : [];
2403
1230
  const unknowns = Array.isArray(report.unknowns) ? report.unknowns : [];
@@ -2421,7 +1248,7 @@ function renderHarnessReportMarkdown(report, validation) {
2421
1248
  ""
2422
1249
  ];
2423
1250
  for (const [index, claim] of claims.slice(0, 80).entries()) {
2424
- const claimRecord = isRecord2(claim) ? claim : {};
1251
+ const claimRecord = isRecord(claim) ? claim : {};
2425
1252
  const citationIds = Array.isArray(claimRecord.citationIds) ? claimRecord.citationIds : [];
2426
1253
  const citedPaths = citationIds.map((id) => citations.find((citation) => citation.id === id)).filter((citation) => Boolean(citation)).map((citation) => `${citation.path ?? citation.id}${citation.line ? `:${citation.line}` : ""}`).join(", ");
2427
1254
  lines.push(`### ${typeof claimRecord.title === "string" ? claimRecord.title : claimLabel(claim, index)}`, "", `- Kind: ${typeof claimRecord.kind === "string" ? claimRecord.kind : "unknown"}`, `- Confidence: ${formatConfidence(claimRecord.confidence)}`, `- Evidence: ${citedPaths || "none"}`, `- Summary: ${typeof claimRecord.summary === "string" ? claimRecord.summary : "unknown"}`, "");
@@ -2432,7 +1259,7 @@ function renderHarnessReportMarkdown(report, validation) {
2432
1259
  if (unknowns.length > 0) {
2433
1260
  lines.push("## Open Questions", "");
2434
1261
  for (const unknown of unknowns) {
2435
- lines.push(`- ${isRecord2(unknown) && typeof unknown.question === "string" ? unknown.question : "Unknown harness question"}`);
1262
+ lines.push(`- ${isRecord(unknown) && typeof unknown.question === "string" ? unknown.question : "Unknown harness question"}`);
2436
1263
  }
2437
1264
  lines.push("");
2438
1265
  }
@@ -2442,7 +1269,7 @@ function renderHarnessReportMarkdown(report, validation) {
2442
1269
  `;
2443
1270
  }
2444
1271
  function claimLabel(claim, index) {
2445
- if (isRecord2(claim)) {
1272
+ if (isRecord(claim)) {
2446
1273
  if (typeof claim.id === "string" && claim.id.length > 0)
2447
1274
  return claim.id;
2448
1275
  if (typeof claim.title === "string" && claim.title.length > 0)
@@ -2451,7 +1278,7 @@ function claimLabel(claim, index) {
2451
1278
  return `claim #${index + 1}`;
2452
1279
  }
2453
1280
  function citationLabel(citation, index) {
2454
- if (isRecord2(citation) && typeof citation.id === "string" && citation.id.length > 0)
1281
+ if (isRecord(citation) && typeof citation.id === "string" && citation.id.length > 0)
2455
1282
  return citation.id;
2456
1283
  return `#${index + 1}`;
2457
1284
  }
@@ -2521,10 +1348,10 @@ function citationExcerpt(rootDir, path, line) {
2521
1348
  if (!isInside(rootDir, absPath) || !existsSync(absPath))
2522
1349
  return {};
2523
1350
  try {
2524
- const stat = lstatSync2(absPath);
1351
+ const stat = lstatSync(absPath);
2525
1352
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 131072)
2526
1353
  return {};
2527
- const lines = readFileSync3(absPath, "utf8").split(/\r?\n/);
1354
+ const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
2528
1355
  const selected = line ? lines[line - 1] : lines.find((candidate) => candidate.trim().length > 0);
2529
1356
  if (!selected)
2530
1357
  return {};
@@ -2534,13 +1361,13 @@ function citationExcerpt(rootDir, path, line) {
2534
1361
  }
2535
1362
  }
2536
1363
  function validateSummaryMatchesGraph(summary, graph, check) {
2537
- if (!isRecord2(graph))
1364
+ if (!isRecord(graph))
2538
1365
  return;
2539
1366
  const fields = {
2540
1367
  runtimeAgentCount: safeArrayLength(graph.runtimeAgents),
2541
1368
  agentFamilyCount: safeArrayLength(graph.agentFamilies),
2542
1369
  artifactCount: safeArrayLength(graph.artifacts),
2543
- sharedArtifactCount: Array.isArray(graph.artifacts) ? graph.artifacts.filter((artifact) => isRecord2(artifact) && artifact.scope === "shared").length : 0,
1370
+ sharedArtifactCount: Array.isArray(graph.artifacts) ? graph.artifacts.filter((artifact) => isRecord(artifact) && artifact.scope === "shared").length : 0,
2544
1371
  channelAdapterCount: safeArrayLength(graph.channelAdapters),
2545
1372
  identityNamespaceCount: safeArrayLength(graph.identityNamespaces),
2546
1373
  environmentCount: safeArrayLength(graph.environments),
@@ -2583,7 +1410,7 @@ function validateClaimSubjectExists(graph, claim, errors, warnings) {
2583
1410
  const collection = graph[collectionName];
2584
1411
  if (!Array.isArray(collection))
2585
1412
  return;
2586
- if (collection.some((item) => isRecord2(item) && item.id === claim.subjectId))
1413
+ if (collection.some((item) => isRecord(item) && item.id === claim.subjectId))
2587
1414
  return;
2588
1415
  const message = `Claim ${claim.id} subject ${claim.subjectId} is not present in graph.${collectionName}.`;
2589
1416
  if (claim.kind === "unknown")
@@ -2592,7 +1419,7 @@ function validateClaimSubjectExists(graph, claim, errors, warnings) {
2592
1419
  errors.push(message);
2593
1420
  }
2594
1421
  function validateClaimQuality(claims, graph, warn) {
2595
- const claimRecords = claims.filter(isRecord2);
1422
+ const claimRecords = claims.filter(isRecord);
2596
1423
  if (claimRecords.length === 0)
2597
1424
  return;
2598
1425
  const graphClaimableItems = graph ? safeArrayLength(graph.runtimeAgents) + safeArrayLength(graph.agentFamilies) + safeArrayLength(graph.developerAgentAdapters) + safeArrayLength(graph.artifacts) + safeArrayLength(graph.channelAdapters) + safeArrayLength(graph.identityNamespaces) + safeArrayLength(graph.agentFrameworks) + safeArrayLength(graph.modelProviders) + safeArrayLength(graph.deployments) + safeArrayLength(graph.relationships) : 0;
@@ -2672,7 +1499,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
2672
1499
  return;
2673
1500
  }
2674
1501
  try {
2675
- const stat = lstatSync2(absPath);
1502
+ const stat = lstatSync(absPath);
2676
1503
  if (stat.isSymbolicLink())
2677
1504
  errors.push(`Citation ${citation.id} points to a symlink.`);
2678
1505
  if (stat.isDirectory()) {
@@ -2681,7 +1508,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
2681
1508
  }
2682
1509
  if (!stat.isFile())
2683
1510
  errors.push(`Citation ${citation.id} does not point to a file.`);
2684
- const lines = readFileSync3(absPath, "utf8").split(/\r?\n/);
1511
+ const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
2685
1512
  if (citation.line !== undefined) {
2686
1513
  const lineCount = lines.length;
2687
1514
  if (citation.line < 1 || citation.line > lineCount) {
@@ -2732,7 +1559,7 @@ function isSecretishPath(path) {
2732
1559
  return name === ".env" || name.startsWith(".env.") || name.includes("secret") || name.includes("private-key") || name.endsWith(".pem");
2733
1560
  }
2734
1561
  function isInside(rootDir, absPath) {
2735
- const rel = relative3(resolve(rootDir), resolve(absPath));
1562
+ const rel = relative(resolve(rootDir), resolve(absPath));
2736
1563
  return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
2737
1564
  }
2738
1565
  function writeJson(path, value) {
@@ -2758,11 +1585,11 @@ function sortJson(value) {
2758
1585
  }
2759
1586
  return value;
2760
1587
  }
2761
- function isRecord2(value) {
1588
+ function isRecord(value) {
2762
1589
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
2763
1590
  }
2764
1591
  function normalizePath(path) {
2765
1592
  return path.replace(/\\/g, "/");
2766
1593
  }
2767
1594
 
2768
- export { mergeBoundRuntimeClasses, tagComponentStatus, HARNESS_REPORT_SCHEMA_VERSION, HARNESS_REPORT_VALIDATION_SCHEMA_VERSION, HARNESS_REPORT_APPROVAL_SCHEMA_VERSION, HARNESS_REPORT_PATH, HARNESS_REPORT_MARKDOWN_PATH, HARNESS_REPORT_VALIDATION_PATH, HARNESS_REPORT_APPROVAL_PATH, HARNESS_ANALYZE_CONCERNS, MAX_HARNESS_REPORT_SUMMARY_LENGTH, createHarnessReport, validateHarnessReport, approveHarnessReport, loadHarnessReportForSync, readHarnessReport, normalizeHarnessReport, requiresArtifactBody, artifactHasBody, firstEvidencePath, stampRemoteSnapshotTruncation, resolveHarnessReportPath, writeHarnessReportArtifacts, renderHarnessReportMarkdown, hashHarnessReport, hashStableJson, graphForReport };
1595
+ export { HARNESS_REPORT_SCHEMA_VERSION, HARNESS_REPORT_VALIDATION_SCHEMA_VERSION, HARNESS_REPORT_APPROVAL_SCHEMA_VERSION, HARNESS_REPORT_PATH, HARNESS_REPORT_MARKDOWN_PATH, HARNESS_REPORT_VALIDATION_PATH, HARNESS_REPORT_APPROVAL_PATH, HARNESS_ANALYZE_CONCERNS, MAX_HARNESS_REPORT_SUMMARY_LENGTH, createHarnessReport, validateHarnessReport, approveHarnessReport, loadHarnessReportForSync, readHarnessReport, normalizeHarnessReport, requiresArtifactBody, artifactHasBody, firstEvidencePath, stampRemoteSnapshotTruncation, resolveHarnessReportPath, writeHarnessReportArtifacts, renderHarnessReportMarkdown, hashHarnessReport, hashStableJson, graphForReport };