@moda-ai/cli 1.55.53 → 1.55.55
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/dist/{agent-0wpfk7ed.js → agent-dc9zkdsm.js} +10 -10
- package/dist/{cli-3dj84cbk.js → cli-2jwxdhh5.js} +1 -1
- package/dist/{cli-1ehmy9rh.js → cli-31ybq5f2.js} +2 -2
- package/dist/{cli-rdh9jjr2.js → cli-94r5x9bg.js} +1 -1
- package/dist/{cli-c1k20j6e.js → cli-9a4b1wxz.js} +1 -1
- package/dist/{cli-4pzbgxcn.js → cli-9g8kp42c.js} +2 -2
- package/dist/{cli-mf37dxpc.js → cli-b918vs2m.js} +4 -4
- package/dist/{cli-thhggczw.js → cli-eqj302as.js} +5 -5
- package/dist/{cli-wry78bg8.js → cli-hawwf30b.js} +1 -1
- package/dist/{cli-r4k0yfkt.js → cli-jnwba1f3.js} +8 -8
- package/dist/{cli-dxxc7tzq.js → cli-m25c0rke.js} +3 -3
- package/dist/{cli-40fqk078.js → cli-pnarsb96.js} +1 -1
- package/dist/{cli-7nghchj8.js → cli-px4dmcy0.js} +107 -306
- package/dist/{cli-6hdqp65a.js → cli-rtkjjf0a.js} +1255 -66
- package/dist/{cli-gtke9wrw.js → cli-v2h21cgf.js} +1 -1
- package/dist/{cli-vswckv9g.js → cli-y5d33a1y.js} +1 -1
- package/dist/cli.js +20 -20
- package/dist/{doctor-wstqcfm4.js → doctor-r16n0me8.js} +8 -8
- package/dist/{harness-github-actions-1031t1kt.js → harness-github-actions-6bex338w.js} +8 -8
- package/dist/{harness-3bcakwrv.js → harness-j0n400bv.js} +8 -8
- package/dist/{harness-report-rjcjbh93.js → harness-report-gz5d3y48.js} +1 -1
- package/dist/{index-msk4gfn5.js → index-ecy3ntzc.js} +14 -14
- package/dist/{production-intelligence-zek0rkzj.js → production-intelligence-fqvhzq6s.js} +4 -4
- package/dist/{profile-commands-nbaec4y9.js → profile-commands-yvpe4d8y.js} +5 -5
- package/dist/{prompt-attribution-2687ns4k.js → prompt-attribution-x84cgdct.js} +8 -8
- package/dist/prompt-source-mcp.js +8 -8
- package/dist/{prompt-sources-qw2p4t5h.js → prompt-sources-1hycgx6r.js} +2 -2
- package/dist/{prompts-887e9w1v.js → prompts-r0mv69yx.js} +6 -6
- package/dist/{provision-tch8rc3y.js → provision-aqhfbnez.js} +6 -6
- package/dist/{registry-tv8fktxc.js → registry-wv1zzyce.js} +4 -4
- package/dist/{skills-mwftqzyk.js → skills-etzcqhp8.js} +6 -6
- package/dist/{sync-dxnw1mwa.js → sync-p4dz7qmn.js} +10 -10
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -13,16 +13,16 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
createCommandContext,
|
|
15
15
|
stringOption
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-v2h21cgf.js";
|
|
17
17
|
import {
|
|
18
18
|
assertFlags,
|
|
19
19
|
assertPositionals,
|
|
20
20
|
requireTenant
|
|
21
|
-
} from "./cli-
|
|
21
|
+
} from "./cli-31ybq5f2.js";
|
|
22
22
|
import {
|
|
23
23
|
ApiError,
|
|
24
24
|
callControlAPI
|
|
25
|
-
} from "./cli-
|
|
25
|
+
} from "./cli-hawwf30b.js";
|
|
26
26
|
import {
|
|
27
27
|
embeddedTenantIdFromApiKey,
|
|
28
28
|
getActiveProfile,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
resolveModaBaseUrl,
|
|
33
33
|
resolveTenantId,
|
|
34
34
|
shellArg
|
|
35
|
-
} from "./cli-
|
|
35
|
+
} from "./cli-pnarsb96.js";
|
|
36
36
|
import {
|
|
37
37
|
PYTHON_AGENT_MODULES,
|
|
38
38
|
TYPESCRIPT_AGENT_MODULES,
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
require_typescript,
|
|
45
45
|
resolvePromptSource,
|
|
46
46
|
validatePromptSource
|
|
47
|
-
} from "./cli-
|
|
47
|
+
} from "./cli-y5d33a1y.js";
|
|
48
48
|
import {
|
|
49
49
|
$isMap,
|
|
50
50
|
$isNode,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
packSnapshot,
|
|
71
71
|
redactDeep,
|
|
72
72
|
shouldInventoryFile
|
|
73
|
-
} from "./cli-
|
|
73
|
+
} from "./cli-9a4b1wxz.js";
|
|
74
74
|
import {
|
|
75
75
|
HARNESS_ANALYZE_CONCERNS,
|
|
76
76
|
HARNESS_REPORT_PATH,
|
|
@@ -83,14 +83,16 @@ import {
|
|
|
83
83
|
hashHarnessReport,
|
|
84
84
|
hashStableJson,
|
|
85
85
|
loadHarnessReportForSync,
|
|
86
|
+
mergeBoundRuntimeClasses,
|
|
86
87
|
normalizeHarnessReport,
|
|
87
88
|
readHarnessReport,
|
|
88
89
|
requiresArtifactBody,
|
|
89
90
|
resolveHarnessReportPath,
|
|
90
91
|
stampRemoteSnapshotTruncation,
|
|
92
|
+
tagComponentStatus,
|
|
91
93
|
validateHarnessReport,
|
|
92
94
|
writeHarnessReportArtifacts
|
|
93
|
-
} from "./cli-
|
|
95
|
+
} from "./cli-rtkjjf0a.js";
|
|
94
96
|
import {
|
|
95
97
|
CliInputError,
|
|
96
98
|
CliInputRequiredError
|
|
@@ -107,15 +109,15 @@ import { homedir, tmpdir as tmpdir2 } from "node:os";
|
|
|
107
109
|
import { fileURLToPath } from "node:url";
|
|
108
110
|
import {
|
|
109
111
|
existsSync as existsSync8,
|
|
110
|
-
lstatSync as
|
|
112
|
+
lstatSync as lstatSync7,
|
|
111
113
|
mkdtempSync as mkdtempSync2,
|
|
112
114
|
mkdirSync as mkdirSync5,
|
|
113
|
-
readFileSync as
|
|
114
|
-
readdirSync as
|
|
115
|
+
readFileSync as readFileSync12,
|
|
116
|
+
readdirSync as readdirSync4,
|
|
115
117
|
writeFileSync as writeFileSync5,
|
|
116
118
|
rmSync as rmSync4
|
|
117
119
|
} from "node:fs";
|
|
118
|
-
import { basename as basename6, delimiter, dirname as dirname7, join as
|
|
120
|
+
import { basename as basename6, delimiter, dirname as dirname7, join as join9, relative as relative6, resolve as resolve10, sep as sep5 } from "node:path";
|
|
119
121
|
import { confirm, select } from "@inquirer/prompts";
|
|
120
122
|
|
|
121
123
|
// src/analyst-tui.ts
|
|
@@ -12320,6 +12322,7 @@ var LINE_PATTERNS = [
|
|
|
12320
12322
|
];
|
|
12321
12323
|
var CODE_EXTENSIONS = new Set([...JS, ...PY]);
|
|
12322
12324
|
var PROMPT_DOC_EXTENSIONS = new Set([".md", ".mdc", ".txt", ".prompt", ".jinja", ".jinja2", ".j2", ".hbs", ".tpl"]);
|
|
12325
|
+
var UPPERCASE_DOC_NAME = /^[A-Z0-9][A-Z0-9_-]*\.(?:md|mdc|txt)$/;
|
|
12323
12326
|
var NON_PROMPT_DOC_BASENAMES = new Set([
|
|
12324
12327
|
"readme.md",
|
|
12325
12328
|
"agents.md",
|
|
@@ -12536,7 +12539,7 @@ function detectPromptFile(file, out) {
|
|
|
12536
12539
|
} else if (PROMPTS_DIR.test(dir)) {
|
|
12537
12540
|
confidence2 = "high";
|
|
12538
12541
|
signal = "prompt_file.prompts_dir";
|
|
12539
|
-
} else if (dirHint && score >= 3) {
|
|
12542
|
+
} else if (dirHint && score >= 3 && !UPPERCASE_DOC_NAME.test(basename5(file.path))) {
|
|
12540
12543
|
confidence2 = "medium";
|
|
12541
12544
|
signal = "prompt_file.agent_dir_instruction_text";
|
|
12542
12545
|
} else if (score >= 5) {
|
|
@@ -13632,6 +13635,36 @@ function promoteToolCandidate(candidate, rootDir, confidence2, fileCache) {
|
|
|
13632
13635
|
body: extractToolBody({ path: candidate.path, rootDir }, { name, reason: candidate.signal })
|
|
13633
13636
|
};
|
|
13634
13637
|
}
|
|
13638
|
+
var UTILITY_EXPORT = /^(?:classify|measure|log|count|parse|validate|detect|is|has|should|estimate|truncate|strip|normalize|hash)(?:[A-Z_]|$)/;
|
|
13639
|
+
var BUILDER_VERB = /^(?:build|render|compose|assemble|generate)(?:[A-Z_]|$)/;
|
|
13640
|
+
var PROMPT_NOUN_LAST = /(?:prompt|instructions?|section|block|template|system)(?:_?for[_A-Z]\w*)?$/i;
|
|
13641
|
+
function exportedNames(path, lines) {
|
|
13642
|
+
const python = path.endsWith(".py");
|
|
13643
|
+
return lines.flatMap((line) => {
|
|
13644
|
+
if (python) {
|
|
13645
|
+
const match = /^(?:async\s+)?(?:def|class)\s+([A-Za-z]\w*)|^([A-Za-z]\w*)\s*(?::[^=]+)?=(?!=)/.exec(line);
|
|
13646
|
+
return match ? [match[1] ?? match[2]] : [];
|
|
13647
|
+
}
|
|
13648
|
+
const declared = /^\s*export\s+(?:default\s+)?(?:async\s+)?(?:function\*?|const|let|var|class)\s+([A-Za-z_$][\w$]*)/.exec(line);
|
|
13649
|
+
if (declared)
|
|
13650
|
+
return [declared[1]];
|
|
13651
|
+
const commonJs = /^\s*(?:module\.)?exports\.([A-Za-z_$][\w$]*)\s*=/.exec(line);
|
|
13652
|
+
if (commonJs)
|
|
13653
|
+
return [commonJs[1]];
|
|
13654
|
+
const list = /^\s*(?:export|module\.exports\s*=)\s*\{([^}]*)\}/.exec(line);
|
|
13655
|
+
if (!list)
|
|
13656
|
+
return [];
|
|
13657
|
+
return list[1].split(",").flatMap((entry) => {
|
|
13658
|
+
const name = entry.trim().replace(/^type\s+/, "").split(/\s+as\s+|\s*:\s*/).pop()?.trim();
|
|
13659
|
+
return name && /^[A-Za-z_$][\w$]*$/.test(name) ? [name] : [];
|
|
13660
|
+
});
|
|
13661
|
+
});
|
|
13662
|
+
}
|
|
13663
|
+
function buildsPrompts(path, lines) {
|
|
13664
|
+
if (!lines)
|
|
13665
|
+
return false;
|
|
13666
|
+
return exportedNames(path, lines).some((name) => !UTILITY_EXPORT.test(name) && (BUILDER_VERB.test(name) || PROMPT_NOUN_LAST.test(name)));
|
|
13667
|
+
}
|
|
13635
13668
|
function promotePromptFileCandidate(candidate, confidence2) {
|
|
13636
13669
|
return {
|
|
13637
13670
|
id: stableId("prompt", candidate.path),
|
|
@@ -14469,7 +14502,7 @@ function promoteHarnessCandidates(report, rootDir) {
|
|
|
14469
14502
|
artifact = promoteToolCandidate(candidate, rootDir, confidence2, fileCache);
|
|
14470
14503
|
break;
|
|
14471
14504
|
case "prompt_file":
|
|
14472
|
-
if (candidate.signal === "prompt_module.name_hint")
|
|
14505
|
+
if (candidate.signal === "prompt_module.name_hint" && (TEST_PATH2.test(candidate.path) || !buildsPrompts(candidate.path, readFileLines(rootDir, candidate.path, fileCache))))
|
|
14473
14506
|
break;
|
|
14474
14507
|
artifact = promotePromptFileCandidate(candidate, confidence2);
|
|
14475
14508
|
break;
|
|
@@ -14497,245 +14530,6 @@ function promoteHarnessCandidates(report, rootDir) {
|
|
|
14497
14530
|
return [...byId.values()];
|
|
14498
14531
|
}
|
|
14499
14532
|
|
|
14500
|
-
// src/harness-wrangler-bindings.ts
|
|
14501
|
-
import { lstatSync as lstatSync7, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "node:fs";
|
|
14502
|
-
import { join as join9, relative as relative6 } from "node:path";
|
|
14503
|
-
var WRANGLER_FILE = /^wrangler\.jsonc?$/;
|
|
14504
|
-
var SKIPPED_DIRS2 = new Set(["node_modules", ".git", ".wrangler", "dist", "build", ".next", ".turbo", "vendor"]);
|
|
14505
|
-
var MAX_DEPTH = 4;
|
|
14506
|
-
var AGENT_CLASS = /Agent(?:V\d+)?$/;
|
|
14507
|
-
function stripJsonc2(text) {
|
|
14508
|
-
let out = "";
|
|
14509
|
-
let inString = false;
|
|
14510
|
-
for (let i = 0;i < text.length; i += 1) {
|
|
14511
|
-
const ch = text[i];
|
|
14512
|
-
if (inString) {
|
|
14513
|
-
out += ch;
|
|
14514
|
-
if (ch === "\\") {
|
|
14515
|
-
out += text[i + 1] ?? "";
|
|
14516
|
-
i += 1;
|
|
14517
|
-
} else if (ch === '"') {
|
|
14518
|
-
inString = false;
|
|
14519
|
-
}
|
|
14520
|
-
continue;
|
|
14521
|
-
}
|
|
14522
|
-
if (ch === '"') {
|
|
14523
|
-
inString = true;
|
|
14524
|
-
out += ch;
|
|
14525
|
-
} else if (ch === "/" && text[i + 1] === "/") {
|
|
14526
|
-
while (i < text.length && text[i] !== `
|
|
14527
|
-
`)
|
|
14528
|
-
i += 1;
|
|
14529
|
-
out += `
|
|
14530
|
-
`;
|
|
14531
|
-
} else if (ch === "/" && text[i + 1] === "*") {
|
|
14532
|
-
i += 2;
|
|
14533
|
-
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) {
|
|
14534
|
-
if (text[i] === `
|
|
14535
|
-
`)
|
|
14536
|
-
out += `
|
|
14537
|
-
`;
|
|
14538
|
-
i += 1;
|
|
14539
|
-
}
|
|
14540
|
-
i += 1;
|
|
14541
|
-
} else {
|
|
14542
|
-
out += ch;
|
|
14543
|
-
}
|
|
14544
|
-
}
|
|
14545
|
-
return out.replace(/,(\s*[}\]])/g, "$1");
|
|
14546
|
-
}
|
|
14547
|
-
function findWranglerFiles(rootDir) {
|
|
14548
|
-
const found = [];
|
|
14549
|
-
const walk = (dir, depth) => {
|
|
14550
|
-
let entries;
|
|
14551
|
-
try {
|
|
14552
|
-
entries = readdirSync4(dir);
|
|
14553
|
-
} catch {
|
|
14554
|
-
return;
|
|
14555
|
-
}
|
|
14556
|
-
for (const name of entries) {
|
|
14557
|
-
const abs = join9(dir, name);
|
|
14558
|
-
let stat;
|
|
14559
|
-
try {
|
|
14560
|
-
stat = lstatSync7(abs);
|
|
14561
|
-
} catch {
|
|
14562
|
-
continue;
|
|
14563
|
-
}
|
|
14564
|
-
if (stat.isDirectory()) {
|
|
14565
|
-
if (depth < MAX_DEPTH && !SKIPPED_DIRS2.has(name) && !name.startsWith("."))
|
|
14566
|
-
walk(abs, depth + 1);
|
|
14567
|
-
} else if (stat.isFile() && WRANGLER_FILE.test(name)) {
|
|
14568
|
-
found.push(abs);
|
|
14569
|
-
}
|
|
14570
|
-
}
|
|
14571
|
-
};
|
|
14572
|
-
walk(rootDir, 0);
|
|
14573
|
-
return found.sort();
|
|
14574
|
-
}
|
|
14575
|
-
function lineOf(text, className) {
|
|
14576
|
-
const index = text.search(new RegExp(`"class_name"\\s*:\\s*"${className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`));
|
|
14577
|
-
return index < 0 ? undefined : text.slice(0, index).split(`
|
|
14578
|
-
`).length;
|
|
14579
|
-
}
|
|
14580
|
-
function workerDir(path) {
|
|
14581
|
-
const slash = path.lastIndexOf("/");
|
|
14582
|
-
return slash < 0 ? "" : path.slice(0, slash);
|
|
14583
|
-
}
|
|
14584
|
-
function detectBoundRuntimeClasses(rootDir) {
|
|
14585
|
-
const byClass = new Map;
|
|
14586
|
-
for (const abs of findWranglerFiles(rootDir)) {
|
|
14587
|
-
let text;
|
|
14588
|
-
let config2;
|
|
14589
|
-
try {
|
|
14590
|
-
text = readFileSync12(abs, "utf8");
|
|
14591
|
-
config2 = JSON.parse(stripJsonc2(text));
|
|
14592
|
-
} catch {
|
|
14593
|
-
continue;
|
|
14594
|
-
}
|
|
14595
|
-
if (!config2 || typeof config2 !== "object")
|
|
14596
|
-
continue;
|
|
14597
|
-
const path = relative6(rootDir, abs).split("\\").join("/");
|
|
14598
|
-
const root = config2;
|
|
14599
|
-
const sections2 = [root, ...Object.values(root.env ?? {})];
|
|
14600
|
-
for (const section of sections2) {
|
|
14601
|
-
if (!section || typeof section !== "object")
|
|
14602
|
-
continue;
|
|
14603
|
-
const s = section;
|
|
14604
|
-
const durable = s.durable_objects?.bindings;
|
|
14605
|
-
const entries = [
|
|
14606
|
-
...Array.isArray(durable) ? durable.map((b) => ["durable_object", b]) : [],
|
|
14607
|
-
...Array.isArray(s.workflows) ? s.workflows.map((w) => ["workflow", w]) : []
|
|
14608
|
-
];
|
|
14609
|
-
for (const [kind, raw] of entries) {
|
|
14610
|
-
if (!raw || typeof raw !== "object")
|
|
14611
|
-
continue;
|
|
14612
|
-
const entry = raw;
|
|
14613
|
-
const className = typeof entry.class_name === "string" ? entry.class_name : "";
|
|
14614
|
-
const scriptName = typeof entry.script_name === "string" && entry.script_name ? entry.script_name : undefined;
|
|
14615
|
-
const key = `${className}|${scriptName ? "external" : `config:${path}`}`;
|
|
14616
|
-
if (!className || byClass.has(key))
|
|
14617
|
-
continue;
|
|
14618
|
-
const binding = typeof (kind === "workflow" ? entry.binding : entry.name) === "string" ? String(kind === "workflow" ? entry.binding : entry.name) : className;
|
|
14619
|
-
byClass.set(key, {
|
|
14620
|
-
className,
|
|
14621
|
-
kind,
|
|
14622
|
-
binding,
|
|
14623
|
-
...scriptName ? { scriptName } : {},
|
|
14624
|
-
path,
|
|
14625
|
-
line: lineOf(text, className)
|
|
14626
|
-
});
|
|
14627
|
-
}
|
|
14628
|
-
}
|
|
14629
|
-
}
|
|
14630
|
-
return [...byClass.values()];
|
|
14631
|
-
}
|
|
14632
|
-
function norm(value) {
|
|
14633
|
-
return typeof value === "string" ? value.toLowerCase().replace(/[^a-z0-9]/g, "") : "";
|
|
14634
|
-
}
|
|
14635
|
-
function itemPaths(item) {
|
|
14636
|
-
const paths = [];
|
|
14637
|
-
for (const value of [item.root, item.sourcePath]) {
|
|
14638
|
-
if (typeof value === "string" && value && value !== ".")
|
|
14639
|
-
paths.push(value.replace(/^\.\//, ""));
|
|
14640
|
-
}
|
|
14641
|
-
for (const entry of Array.isArray(item.evidence) ? item.evidence : []) {
|
|
14642
|
-
const path = entry && typeof entry === "object" ? entry.path : undefined;
|
|
14643
|
-
if (typeof path === "string" && path)
|
|
14644
|
-
paths.push(path.replace(/^\.\//, ""));
|
|
14645
|
-
}
|
|
14646
|
-
return paths;
|
|
14647
|
-
}
|
|
14648
|
-
function withinWorker(path, dir, otherDirs) {
|
|
14649
|
-
const inside = (d) => d === "" || path === d || path.startsWith(`${d}/`);
|
|
14650
|
-
return inside(dir) && !otherDirs.some((other) => other.length > dir.length && inside(other));
|
|
14651
|
-
}
|
|
14652
|
-
function graphNamesClass(graph, bound, all) {
|
|
14653
|
-
const target = norm(bound.className);
|
|
14654
|
-
const named = (name) => {
|
|
14655
|
-
if (typeof name !== "string")
|
|
14656
|
-
return false;
|
|
14657
|
-
const bare = name.replace(/\s*\([^)]*\)\s*$/, "");
|
|
14658
|
-
return norm(bare) === target || bare.split(/[^A-Za-z0-9_]+/).some((word) => norm(word) === target);
|
|
14659
|
-
};
|
|
14660
|
-
const sameName = bound.scriptName ? [bound] : all.filter((other) => other.className === bound.className && !other.scriptName);
|
|
14661
|
-
const dir = workerDir(bound.path);
|
|
14662
|
-
const otherDirs = sameName.map((other) => workerDir(other.path)).filter((other) => other !== dir);
|
|
14663
|
-
const covers = (item) => {
|
|
14664
|
-
if (!named(item.name))
|
|
14665
|
-
return false;
|
|
14666
|
-
if (sameName.length < 2)
|
|
14667
|
-
return true;
|
|
14668
|
-
return itemPaths(item).some((path) => withinWorker(path, dir, otherDirs));
|
|
14669
|
-
};
|
|
14670
|
-
return graph.runtimeAgents.some(covers) || graph.artifacts.some(covers);
|
|
14671
|
-
}
|
|
14672
|
-
function bindingReason(bound) {
|
|
14673
|
-
const what = bound.kind === "workflow" ? "Workflow" : "Durable Object";
|
|
14674
|
-
const where = bound.scriptName ? ` served by the external Worker "${bound.scriptName}"` : "";
|
|
14675
|
-
return `${what} binding ${bound.binding} -> class ${bound.className}${where}`;
|
|
14676
|
-
}
|
|
14677
|
-
function uniqueId(base, taken) {
|
|
14678
|
-
let id = base;
|
|
14679
|
-
for (let n = 2;taken.has(id); n += 1)
|
|
14680
|
-
id = `${base}-${n}`;
|
|
14681
|
-
taken.add(id);
|
|
14682
|
-
return id;
|
|
14683
|
-
}
|
|
14684
|
-
function mergeBoundRuntimeClasses(graph, rootDir) {
|
|
14685
|
-
if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
|
|
14686
|
-
return { added: 0 };
|
|
14687
|
-
let bound;
|
|
14688
|
-
try {
|
|
14689
|
-
bound = detectBoundRuntimeClasses(rootDir);
|
|
14690
|
-
} catch {
|
|
14691
|
-
return { added: 0 };
|
|
14692
|
-
}
|
|
14693
|
-
const taken = new Set([
|
|
14694
|
-
...graph.runtimeAgents.map((agent) => agent.id),
|
|
14695
|
-
...graph.artifacts.map((artifact) => artifact.id)
|
|
14696
|
-
]);
|
|
14697
|
-
let added = 0;
|
|
14698
|
-
for (const entry of bound) {
|
|
14699
|
-
if (graphNamesClass(graph, entry, bound))
|
|
14700
|
-
continue;
|
|
14701
|
-
const evidence = [{ path: entry.path, ...entry.line ? { line: entry.line } : {}, reason: bindingReason(entry) }];
|
|
14702
|
-
const slug = entry.className.replace(/[^A-Za-z0-9]+/g, "-").toLowerCase();
|
|
14703
|
-
if (entry.kind === "durable_object" && AGENT_CLASS.test(entry.className) && !entry.scriptName) {
|
|
14704
|
-
const agent = {
|
|
14705
|
-
id: uniqueId(`agent.bound.${slug}`, taken),
|
|
14706
|
-
name: entry.className,
|
|
14707
|
-
kind: "runtime_agent",
|
|
14708
|
-
purpose: "Agent class bound as a Durable Object.",
|
|
14709
|
-
root: ".",
|
|
14710
|
-
entrypointIds: [],
|
|
14711
|
-
channelAdapterIds: [],
|
|
14712
|
-
artifactIds: [],
|
|
14713
|
-
identityNamespaceIds: [],
|
|
14714
|
-
deploymentIds: [],
|
|
14715
|
-
frameworkIds: [],
|
|
14716
|
-
modelProviderIds: [],
|
|
14717
|
-
confidence: 0.6,
|
|
14718
|
-
evidence
|
|
14719
|
-
};
|
|
14720
|
-
graph.runtimeAgents.push(agent);
|
|
14721
|
-
} else {
|
|
14722
|
-
const artifact = {
|
|
14723
|
-
id: uniqueId(`entrypoint.bound.${slug}`, taken),
|
|
14724
|
-
type: "entrypoint",
|
|
14725
|
-
name: entry.className,
|
|
14726
|
-
scope: "shared",
|
|
14727
|
-
sourcePath: entry.path,
|
|
14728
|
-
usedByAgentIds: [],
|
|
14729
|
-
confidence: 0.6,
|
|
14730
|
-
evidence
|
|
14731
|
-
};
|
|
14732
|
-
graph.artifacts.push(artifact);
|
|
14733
|
-
}
|
|
14734
|
-
added += 1;
|
|
14735
|
-
}
|
|
14736
|
-
return { added };
|
|
14737
|
-
}
|
|
14738
|
-
|
|
14739
14533
|
// src/harness-sync-limits.ts
|
|
14740
14534
|
var MAX_HARNESS_SYNC_GRAPH_BYTES = 2000000;
|
|
14741
14535
|
function assertHarnessGraphSyncSize(graph) {
|
|
@@ -14754,8 +14548,8 @@ function assertHarnessGraphSyncSize(graph) {
|
|
|
14754
14548
|
}
|
|
14755
14549
|
// src/harness.ts
|
|
14756
14550
|
var MODA_DIR = ".moda";
|
|
14757
|
-
var HARNESS_PATH =
|
|
14758
|
-
var HARNESS_SUMMARY_PATH =
|
|
14551
|
+
var HARNESS_PATH = join9(MODA_DIR, "harness.json");
|
|
14552
|
+
var HARNESS_SUMMARY_PATH = join9(MODA_DIR, "HARNESS.md");
|
|
14759
14553
|
var SCHEMA_VERSION = "harness.v0.1";
|
|
14760
14554
|
var REPORT_JSON_BEGIN = "MODA_HARNESS_REPORT_JSON_BEGIN";
|
|
14761
14555
|
var REPORT_JSON_END = "MODA_HARNESS_REPORT_JSON_END";
|
|
@@ -14921,7 +14715,7 @@ async function runHarnessCommand(context) {
|
|
|
14921
14715
|
report: {
|
|
14922
14716
|
reportId: report.reportId,
|
|
14923
14717
|
reportHash,
|
|
14924
|
-
path: normalizePath2(
|
|
14718
|
+
path: normalizePath2(relative6(rootDir, reportPath)) || ".moda/harness-report.json"
|
|
14925
14719
|
},
|
|
14926
14720
|
validation,
|
|
14927
14721
|
approval: {
|
|
@@ -15067,7 +14861,7 @@ async function runHarnessCommand(context) {
|
|
|
15067
14861
|
throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
|
|
15068
14862
|
}
|
|
15069
14863
|
if (context.flags["github-actions"] === "true") {
|
|
15070
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
14864
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-6bex338w.js");
|
|
15071
14865
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
15072
14866
|
writeReport: (report2) => {
|
|
15073
14867
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -15189,7 +14983,7 @@ async function runHarnessCommand(context) {
|
|
|
15189
14983
|
report: {
|
|
15190
14984
|
reportId: approval.report.reportId,
|
|
15191
14985
|
reportHash: hashHarnessReport(approval.report),
|
|
15192
|
-
path: normalizePath2(
|
|
14986
|
+
path: normalizePath2(relative6(rootDir, reportPath)) || ".moda/harness-report.json"
|
|
15193
14987
|
},
|
|
15194
14988
|
validation: approval.validation,
|
|
15195
14989
|
approval: approval.approval
|
|
@@ -15212,6 +15006,7 @@ async function runHarnessCommand(context) {
|
|
|
15212
15006
|
throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
|
|
15213
15007
|
}
|
|
15214
15008
|
const artifacts = deterministicArtifacts(rootDir, promote === "all" ? undefined : promote);
|
|
15009
|
+
tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
|
|
15215
15010
|
const promoted = { concern: promote, artifacts };
|
|
15216
15011
|
const promoteWritten = [];
|
|
15217
15012
|
if (promoteOut && !context.dryRun) {
|
|
@@ -15279,7 +15074,7 @@ async function runHarnessCommand(context) {
|
|
|
15279
15074
|
return { exitCode: 0 };
|
|
15280
15075
|
}
|
|
15281
15076
|
case "status": {
|
|
15282
|
-
const manifestPath =
|
|
15077
|
+
const manifestPath = join9(rootDir, HARNESS_PATH);
|
|
15283
15078
|
const graph = existsSync8(manifestPath) ? readHarnessGraph(manifestPath) : scanHarness({
|
|
15284
15079
|
rootDir,
|
|
15285
15080
|
tenantId: tenant?.tenantId,
|
|
@@ -15420,10 +15215,10 @@ function emitWrittenArtifacts(context, written, description) {
|
|
|
15420
15215
|
}
|
|
15421
15216
|
}
|
|
15422
15217
|
async function runPromptConcernAnalysis(context, rootDir, scanPlan, tenant) {
|
|
15423
|
-
const manifest =
|
|
15218
|
+
const manifest = join9(rootDir, ".moda/prompts.yml");
|
|
15424
15219
|
let existing = [];
|
|
15425
15220
|
if (existsSync8(manifest)) {
|
|
15426
|
-
const document = $parseDocument(
|
|
15221
|
+
const document = $parseDocument(readFileSync12(manifest, "utf8"));
|
|
15427
15222
|
if (document.errors.length)
|
|
15428
15223
|
throw new CliInputError("Invalid prompt manifest.", document.errors[0].message);
|
|
15429
15224
|
existing = document.toJS({ maxAliasCount: 20 })?.sources ?? [];
|
|
@@ -15677,7 +15472,7 @@ function readExternalAnalystReport(rootDir, result, adapter, concern) {
|
|
|
15677
15472
|
result.stderr
|
|
15678
15473
|
].join(`
|
|
15679
15474
|
`));
|
|
15680
|
-
debugHint = `Raw analyst output saved to ${
|
|
15475
|
+
debugHint = `Raw analyst output saved to ${join9(MODA_DIR, "analyst-debug.log")} for debugging.`;
|
|
15681
15476
|
} catch {}
|
|
15682
15477
|
throw new CliInputError(`Harness analyst ${adapter} did not return a harness report.`, [
|
|
15683
15478
|
`Expected ${HARNESS_REPORT_PATH} or final JSON between ${REPORT_JSON_BEGIN} and ${REPORT_JSON_END}.`,
|
|
@@ -15788,6 +15583,7 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
|
|
|
15788
15583
|
mergeDeterministicArtifacts(normalized.graph, rootDir, { concern: options.concern });
|
|
15789
15584
|
if (!options.concern || options.concern === "topology")
|
|
15790
15585
|
mergeBoundRuntimeClasses(normalized.graph, rootDir);
|
|
15586
|
+
tagComponentStatus(normalized.graph, rootDir);
|
|
15791
15587
|
hydratePromptAndToolBodies(normalized.graph, rootDir);
|
|
15792
15588
|
const unverified = new Set;
|
|
15793
15589
|
for (const artifact of normalized.graph.artifacts) {
|
|
@@ -16034,7 +15830,8 @@ function artifactSourceKey(artifact) {
|
|
|
16034
15830
|
}
|
|
16035
15831
|
function graphCoversPromotedArtifact(graph, promoted) {
|
|
16036
15832
|
const promotedName = promoted.name.toLowerCase();
|
|
16037
|
-
const
|
|
15833
|
+
const isDefinitionLine = (entry) => typeof entry.line === "number" && !/^(?:passed to a model call|prompt-named literal referenced)/.test(entry.reason ?? "");
|
|
15834
|
+
const promotedLines = promoted.evidence.filter(isDefinitionLine);
|
|
16038
15835
|
const promotedSource = artifactSourceKey(promoted);
|
|
16039
15836
|
const isWholeFilePrompt = promoted.type === "prompt" && Boolean(promoted.sourcePath);
|
|
16040
15837
|
return graph.artifacts.some((existing) => {
|
|
@@ -16042,10 +15839,12 @@ function graphCoversPromotedArtifact(graph, promoted) {
|
|
|
16042
15839
|
return true;
|
|
16043
15840
|
if (existing.type === promoted.type && existing.name?.toLowerCase() === promotedName) {
|
|
16044
15841
|
const existingSource = artifactSourceKey(existing);
|
|
16045
|
-
|
|
15842
|
+
const existingLines = Array.isArray(existing.evidence) ? existing.evidence.filter(isDefinitionLine) : [];
|
|
15843
|
+
const distinctInline = !existing.sourcePath && !promoted.sourcePath && existingLines.length > 0 && promotedLines.length > 0;
|
|
15844
|
+
if (!existingSource || !promotedSource || existingSource === promotedSource && !distinctInline)
|
|
16046
15845
|
return true;
|
|
16047
15846
|
}
|
|
16048
|
-
if (existing.type === promoted.type && Array.isArray(existing.evidence) && existing.evidence.some((entry) =>
|
|
15847
|
+
if (existing.type === promoted.type && Array.isArray(existing.evidence) && existing.evidence.some((entry) => isDefinitionLine(entry) && promotedLines.some((line) => line.path === entry.path && line.line === entry.line))) {
|
|
16049
15848
|
return true;
|
|
16050
15849
|
}
|
|
16051
15850
|
if (isWholeFilePrompt && existing.sourcePath === promoted.sourcePath)
|
|
@@ -16081,7 +15880,7 @@ function repairCitationLines(report, rootDir) {
|
|
|
16081
15880
|
continue;
|
|
16082
15881
|
let text;
|
|
16083
15882
|
try {
|
|
16084
|
-
text =
|
|
15883
|
+
text = readFileSync12(candidatePath, "utf8");
|
|
16085
15884
|
} catch {
|
|
16086
15885
|
continue;
|
|
16087
15886
|
}
|
|
@@ -16687,14 +16486,14 @@ function createPromptAnalystIsolation(adapter, rootDir) {
|
|
|
16687
16486
|
const serverPath = bundledServer ? bundled : source;
|
|
16688
16487
|
const command = bundledServer ? process.execPath : resolveBunRuntime();
|
|
16689
16488
|
const serverArgs = [serverPath, "--root", rootDir];
|
|
16690
|
-
const tempPath = mkdtempSync2(
|
|
16489
|
+
const tempPath = mkdtempSync2(join9(tmpdir2(), "moda-prompt-analyst-"));
|
|
16691
16490
|
const cleanup = () => {
|
|
16692
16491
|
try {
|
|
16693
16492
|
rmSync4(tempPath, { recursive: true, force: true });
|
|
16694
16493
|
} catch {}
|
|
16695
16494
|
};
|
|
16696
16495
|
if (adapter === "claude") {
|
|
16697
|
-
const configPath =
|
|
16496
|
+
const configPath = join9(tempPath, "claude-mcp.json");
|
|
16698
16497
|
writeFileSync5(configPath, JSON.stringify({ mcpServers: { "moda-prompt-source": { command, args: serverArgs } } }));
|
|
16699
16498
|
return { configPath, cleanup };
|
|
16700
16499
|
}
|
|
@@ -16905,6 +16704,7 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
16905
16704
|
"",
|
|
16906
16705
|
'Use exact field names and numeric confidence values from 0 to 1. Do not write string confidence values like "high". Do not use confidence >= 0.90 unless the claim is direct evidence from the cited line(s).',
|
|
16907
16706
|
`Name each runtime agent after the class or exported symbol that defines it, adding the role in parentheses when helpful, e.g. "AutonomousPlanWorkflow (weekly planner)"; a Cloudflare Workflow or Durable Object class keeps its class name. Never emit an agent whose class is not defined or exported in this source tree: a binding to another worker's class (e.g. a wrangler script_name binding) is a deployment detail, not an agent of this repo.`,
|
|
16707
|
+
"Include every real harness component in your scope whether or not anything uses it: a tool defined but never registered, a prompt file or prompt literal nothing references, an agent, Workflow, or Durable Object class defined or exported but never bound, an eval or fixture that tests the agent, a model config declared but unused. Never drop a component for being unused, dead, or legacy; Moda tags its deployment status separately. A class defined here that nothing binds or instantiates is an `entrypoint` artifact, not a runtime agent.",
|
|
16908
16708
|
'A `tool` artifact is one tool definition. Never emit a group of tools ("MCP server tools", "composio_*", "worker tools") as a tool; record a dynamic tool source (MCP servers, Composio, webhooks) as a graph unknown that cites where the tools are loaded.',
|
|
16909
16709
|
"Ignore any checked-in .moda/ directory: it is the output of an earlier Moda run and is often stale. Never cite it or reuse its entities.",
|
|
16910
16710
|
'Every graph item with confidence below 0.85 must also carry confidenceReason: one sentence naming what held confidence down, e.g. "Inferred from AGENTS.md:231-232 only; no source file defines this agent." or "Entrypoint read, but the tool registry was outside the snapshot."',
|
|
@@ -17110,10 +16910,10 @@ function readDirectoryPreflightPaths(rootDir) {
|
|
|
17110
16910
|
const stack = ["."];
|
|
17111
16911
|
while (stack.length > 0 && paths.length < 2000) {
|
|
17112
16912
|
const current = stack.pop() ?? ".";
|
|
17113
|
-
const absolute = current === "." ? rootDir :
|
|
16913
|
+
const absolute = current === "." ? rootDir : join9(rootDir, current);
|
|
17114
16914
|
let entries;
|
|
17115
16915
|
try {
|
|
17116
|
-
entries =
|
|
16916
|
+
entries = readdirSync4(absolute);
|
|
17117
16917
|
} catch {
|
|
17118
16918
|
continue;
|
|
17119
16919
|
}
|
|
@@ -17121,10 +16921,10 @@ function readDirectoryPreflightPaths(rootDir) {
|
|
|
17121
16921
|
const child = current === "." ? entry : `${current}/${entry}`;
|
|
17122
16922
|
if (shouldSkipPreflightPath(child))
|
|
17123
16923
|
continue;
|
|
17124
|
-
const childAbsolute =
|
|
16924
|
+
const childAbsolute = join9(rootDir, child);
|
|
17125
16925
|
let stat;
|
|
17126
16926
|
try {
|
|
17127
|
-
stat =
|
|
16927
|
+
stat = lstatSync7(childAbsolute);
|
|
17128
16928
|
} catch {
|
|
17129
16929
|
continue;
|
|
17130
16930
|
}
|
|
@@ -17186,7 +16986,7 @@ function findOnPath(command) {
|
|
|
17186
16986
|
if (command.includes("/") && existsSync8(command))
|
|
17187
16987
|
return command;
|
|
17188
16988
|
for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
|
|
17189
|
-
const candidate =
|
|
16989
|
+
const candidate = join9(dir, command);
|
|
17190
16990
|
if (existsSync8(candidate))
|
|
17191
16991
|
return candidate;
|
|
17192
16992
|
}
|
|
@@ -17240,6 +17040,7 @@ function scanHarness(options = {}) {
|
|
|
17240
17040
|
linkFrameworksAndProviders(graph);
|
|
17241
17041
|
finalizeGraph(graph);
|
|
17242
17042
|
hydratePromptAndToolBodies(graph, rootDir);
|
|
17043
|
+
tagComponentStatus(graph, rootDir);
|
|
17243
17044
|
enrichScanCaptureMetadata(graph);
|
|
17244
17045
|
return graph;
|
|
17245
17046
|
}
|
|
@@ -17264,10 +17065,10 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
17264
17065
|
let inventoryFileCount = 0;
|
|
17265
17066
|
let inventoryTextBytes = 0;
|
|
17266
17067
|
function walk(current) {
|
|
17267
|
-
const path = normalizePath2(
|
|
17068
|
+
const path = normalizePath2(relative6(rootDir, current)) || ".";
|
|
17268
17069
|
let stat;
|
|
17269
17070
|
try {
|
|
17270
|
-
stat =
|
|
17071
|
+
stat = lstatSync7(current);
|
|
17271
17072
|
} catch {
|
|
17272
17073
|
return;
|
|
17273
17074
|
}
|
|
@@ -17278,8 +17079,8 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
17278
17079
|
if (stat.isDirectory()) {
|
|
17279
17080
|
if (path !== "." && (isSkippedDir(path) || isSkippedPathPrefix(path)))
|
|
17280
17081
|
return;
|
|
17281
|
-
for (const entry of
|
|
17282
|
-
walk(
|
|
17082
|
+
for (const entry of readdirSync4(current).sort())
|
|
17083
|
+
walk(join9(current, entry));
|
|
17283
17084
|
return;
|
|
17284
17085
|
}
|
|
17285
17086
|
if (!stat.isFile())
|
|
@@ -17302,7 +17103,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
17302
17103
|
let text = "";
|
|
17303
17104
|
if (isTextFile(path)) {
|
|
17304
17105
|
try {
|
|
17305
|
-
text =
|
|
17106
|
+
text = readFileSync12(current, "utf8");
|
|
17306
17107
|
inventoryTextBytes += Buffer.byteLength(text, "utf8");
|
|
17307
17108
|
} catch {
|
|
17308
17109
|
return;
|
|
@@ -17321,7 +17122,7 @@ function buildSourceSnapshot(rootDir) {
|
|
|
17321
17122
|
const inputs = collectSnapshotInputs(root, maxFiles, maxTextBytes);
|
|
17322
17123
|
const repo = detectRepo(root, inputs.map((input) => ({
|
|
17323
17124
|
path: input.path,
|
|
17324
|
-
absPath:
|
|
17125
|
+
absPath: join9(root, input.path),
|
|
17325
17126
|
rootDir: root,
|
|
17326
17127
|
text: input.text
|
|
17327
17128
|
})));
|
|
@@ -17335,7 +17136,7 @@ function buildSourceSnapshot(rootDir) {
|
|
|
17335
17136
|
}
|
|
17336
17137
|
function buildCommandScanPlan(context, rootDir) {
|
|
17337
17138
|
const explicitPath = context.flags.path !== undefined;
|
|
17338
|
-
const rel2 = normalizePath2(
|
|
17139
|
+
const rel2 = normalizePath2(relative6(context.cwd, rootDir)) || ".";
|
|
17339
17140
|
const scope = explicitPath && rel2 !== "." ? "narrow" : "broad";
|
|
17340
17141
|
const machineReadable = context.outputMode !== "human";
|
|
17341
17142
|
const approvalRequired = context.positional === "analyze" && scope === "broad" && !context.yes;
|
|
@@ -17420,7 +17221,7 @@ function writeHumanBlock(context, message) {
|
|
|
17420
17221
|
function buildHarnessReadPlan(rootDir, pathWasExplicit) {
|
|
17421
17222
|
return {
|
|
17422
17223
|
scope: pathWasExplicit ? "narrow" : "broad",
|
|
17423
|
-
rootPaths: [normalizePath2(
|
|
17224
|
+
rootPaths: [normalizePath2(relative6(rootDir, rootDir)) || "."],
|
|
17424
17225
|
willRead: [
|
|
17425
17226
|
"package manifests",
|
|
17426
17227
|
"source files under the selected path",
|
|
@@ -17538,7 +17339,7 @@ async function syncHarnessWithRemote(context, body) {
|
|
|
17538
17339
|
}, profileOptions);
|
|
17539
17340
|
}
|
|
17540
17341
|
function writeHarnessSyncState(rootDir, state) {
|
|
17541
|
-
const path =
|
|
17342
|
+
const path = join9(rootDir, SYNC_STATE_PATH);
|
|
17542
17343
|
mkdirSync5(dirname7(path), { recursive: true });
|
|
17543
17344
|
writeFileSync5(path, `${JSON.stringify(state, null, 2)}
|
|
17544
17345
|
`);
|
|
@@ -17552,7 +17353,7 @@ function selectedRuntimeAgentId(flags) {
|
|
|
17552
17353
|
return;
|
|
17553
17354
|
}
|
|
17554
17355
|
function loadOrScanHarness(rootDir, tenant, context) {
|
|
17555
|
-
const manifestPath =
|
|
17356
|
+
const manifestPath = join9(rootDir, HARNESS_PATH);
|
|
17556
17357
|
if (existsSync8(manifestPath))
|
|
17557
17358
|
return readHarnessGraph(manifestPath);
|
|
17558
17359
|
if (context) {
|
|
@@ -17609,7 +17410,7 @@ var FRESHER_REPORT_MAX_DIRS = 4000;
|
|
|
17609
17410
|
function findFresherHarnessReports(rootDir) {
|
|
17610
17411
|
let rootMtimeMs = 0;
|
|
17611
17412
|
try {
|
|
17612
|
-
rootMtimeMs =
|
|
17413
|
+
rootMtimeMs = lstatSync7(join9(rootDir, HARNESS_REPORT_PATH)).mtimeMs;
|
|
17613
17414
|
} catch {
|
|
17614
17415
|
rootMtimeMs = 0;
|
|
17615
17416
|
}
|
|
@@ -17621,19 +17422,19 @@ function findFresherHarnessReports(rootDir) {
|
|
|
17621
17422
|
visited += 1;
|
|
17622
17423
|
let entries;
|
|
17623
17424
|
try {
|
|
17624
|
-
entries =
|
|
17425
|
+
entries = readdirSync4(dir, { withFileTypes: true });
|
|
17625
17426
|
} catch {
|
|
17626
17427
|
return;
|
|
17627
17428
|
}
|
|
17628
17429
|
for (const entry of entries) {
|
|
17629
17430
|
if (!entry.isDirectory() || entry.name.startsWith(".") || SKIPPED_DIRS.has(entry.name))
|
|
17630
17431
|
continue;
|
|
17631
|
-
const child =
|
|
17432
|
+
const child = join9(dir, entry.name);
|
|
17632
17433
|
try {
|
|
17633
|
-
const candidate =
|
|
17434
|
+
const candidate = lstatSync7(join9(child, HARNESS_REPORT_PATH));
|
|
17634
17435
|
if (candidate.isFile() && candidate.mtimeMs > rootMtimeMs) {
|
|
17635
17436
|
fresher.push({
|
|
17636
|
-
path: normalizePath2(
|
|
17437
|
+
path: normalizePath2(relative6(rootDir, join9(child, HARNESS_REPORT_PATH))),
|
|
17637
17438
|
mtimeMs: candidate.mtimeMs
|
|
17638
17439
|
});
|
|
17639
17440
|
}
|
|
@@ -17645,7 +17446,7 @@ function findFresherHarnessReports(rootDir) {
|
|
|
17645
17446
|
return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
17646
17447
|
}
|
|
17647
17448
|
function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
|
|
17648
|
-
const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath2(
|
|
17449
|
+
const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath2(relative6(rootDir, resolve10(rootDir, explicitReport))) : undefined;
|
|
17649
17450
|
if (explicitReportPath && explicitReportPath !== normalizePath2(HARNESS_REPORT_PATH))
|
|
17650
17451
|
return;
|
|
17651
17452
|
let fresher;
|
|
@@ -17658,16 +17459,16 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
|
|
|
17658
17459
|
return;
|
|
17659
17460
|
const newest = fresher[0];
|
|
17660
17461
|
const subdir = normalizePath2(dirname7(dirname7(newest.path)));
|
|
17661
|
-
const rootState = existsSync8(
|
|
17462
|
+
const rootState = existsSync8(join9(rootDir, HARNESS_REPORT_PATH)) ? `older ${HARNESS_REPORT_PATH}` : `no ${HARNESS_REPORT_PATH}`;
|
|
17662
17463
|
writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
|
|
17663
17464
|
}
|
|
17664
17465
|
function readHarnessGraph(manifestPath) {
|
|
17665
|
-
return JSON.parse(
|
|
17466
|
+
return JSON.parse(readFileSync12(manifestPath, "utf8"));
|
|
17666
17467
|
}
|
|
17667
17468
|
function writeHarnessArtifacts(graph, rootDir, options = {}) {
|
|
17668
|
-
const modaDir =
|
|
17469
|
+
const modaDir = join9(rootDir, MODA_DIR);
|
|
17669
17470
|
mkdirSync5(modaDir, { recursive: true });
|
|
17670
|
-
const manifestPath =
|
|
17471
|
+
const manifestPath = join9(rootDir, HARNESS_PATH);
|
|
17671
17472
|
writeFileSync5(manifestPath, `${JSON.stringify(graph, null, 2)}
|
|
17672
17473
|
`);
|
|
17673
17474
|
const written = [HARNESS_PATH];
|
|
@@ -17677,7 +17478,7 @@ function writeHarnessArtifacts(graph, rootDir, options = {}) {
|
|
|
17677
17478
|
return written;
|
|
17678
17479
|
}
|
|
17679
17480
|
function writeHarnessSummary(graph, rootDir) {
|
|
17680
|
-
const summaryPath =
|
|
17481
|
+
const summaryPath = join9(rootDir, HARNESS_SUMMARY_PATH);
|
|
17681
17482
|
mkdirSync5(dirname7(summaryPath), { recursive: true });
|
|
17682
17483
|
writeFileSync5(summaryPath, renderHarnessMarkdown(graph));
|
|
17683
17484
|
return HARNESS_SUMMARY_PATH;
|
|
@@ -17852,10 +17653,10 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
17852
17653
|
const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
|
|
17853
17654
|
let textBytes = 0;
|
|
17854
17655
|
function walk(current) {
|
|
17855
|
-
const rel2 = normalizePath2(
|
|
17656
|
+
const rel2 = normalizePath2(relative6(rootReal, current)) || ".";
|
|
17856
17657
|
let stat;
|
|
17857
17658
|
try {
|
|
17858
|
-
stat =
|
|
17659
|
+
stat = lstatSync7(current);
|
|
17859
17660
|
} catch {
|
|
17860
17661
|
recordSkipped(skipped, { path: rel2, reason: "stat failed" });
|
|
17861
17662
|
return;
|
|
@@ -17869,8 +17670,8 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
17869
17670
|
recordSkipped(skipped, { path: rel2, reason: "ignored directory" });
|
|
17870
17671
|
return;
|
|
17871
17672
|
}
|
|
17872
|
-
for (const entry of
|
|
17873
|
-
walk(
|
|
17673
|
+
for (const entry of readdirSync4(current).sort()) {
|
|
17674
|
+
walk(join9(current, entry));
|
|
17874
17675
|
}
|
|
17875
17676
|
return;
|
|
17876
17677
|
}
|
|
@@ -17901,7 +17702,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
17901
17702
|
recordSkipped(skipped, { path: rel2, reason: "scan text budget exceeded" });
|
|
17902
17703
|
} else {
|
|
17903
17704
|
try {
|
|
17904
|
-
item.text =
|
|
17705
|
+
item.text = readFileSync12(current, "utf8");
|
|
17905
17706
|
textBytes += Buffer.byteLength(item.text, "utf8");
|
|
17906
17707
|
} catch {
|
|
17907
17708
|
recordSkipped(skipped, { path: rel2, reason: "text read failed" });
|
|
@@ -18208,7 +18009,7 @@ function maybeAddPromptArtifact(graph, file) {
|
|
|
18208
18009
|
if (!isPrompt)
|
|
18209
18010
|
return;
|
|
18210
18011
|
const id = stableId("prompt", file.path);
|
|
18211
|
-
const text = file.text ??
|
|
18012
|
+
const text = file.text ?? readFileSync12(file.absPath, "utf8");
|
|
18212
18013
|
upsertArtifact(graph, {
|
|
18213
18014
|
id,
|
|
18214
18015
|
type: "prompt",
|
|
@@ -18786,10 +18587,10 @@ function computeDeterministicFloor(rootDir) {
|
|
|
18786
18587
|
}
|
|
18787
18588
|
function detectProviderPackagesInManifests(rootDir) {
|
|
18788
18589
|
const present = new Set;
|
|
18789
|
-
const packageJsonPath =
|
|
18590
|
+
const packageJsonPath = join9(rootDir, "package.json");
|
|
18790
18591
|
if (existsSync8(packageJsonPath)) {
|
|
18791
18592
|
try {
|
|
18792
|
-
const deps = packageDependencyNames(
|
|
18593
|
+
const deps = packageDependencyNames(readFileSync12(packageJsonPath, "utf8"));
|
|
18793
18594
|
for (const provider of PROVIDER_CATALOG) {
|
|
18794
18595
|
for (const name of provider.packageNames) {
|
|
18795
18596
|
if (deps.has(name))
|
|
@@ -18798,10 +18599,10 @@ function detectProviderPackagesInManifests(rootDir) {
|
|
|
18798
18599
|
}
|
|
18799
18600
|
} catch {}
|
|
18800
18601
|
}
|
|
18801
|
-
const pyprojectPath =
|
|
18602
|
+
const pyprojectPath = join9(rootDir, "pyproject.toml");
|
|
18802
18603
|
if (existsSync8(pyprojectPath)) {
|
|
18803
18604
|
try {
|
|
18804
|
-
const deps = pyprojectDependencyNames(
|
|
18605
|
+
const deps = pyprojectDependencyNames(readFileSync12(pyprojectPath, "utf8"));
|
|
18805
18606
|
for (const provider of PROVIDER_CATALOG) {
|
|
18806
18607
|
for (const name of provider.packageNames) {
|
|
18807
18608
|
if (deps.has(name.toLowerCase()))
|
|
@@ -19203,12 +19004,12 @@ function contentHashForAnnotatedSource(sourcePath, annotation) {
|
|
|
19203
19004
|
function readSmallTextFileForHash(absPath, rootDir) {
|
|
19204
19005
|
if (!existsSync8(absPath))
|
|
19205
19006
|
return;
|
|
19206
|
-
const rel2 = normalizePath2(
|
|
19007
|
+
const rel2 = normalizePath2(relative6(rootDir, absPath));
|
|
19207
19008
|
if (isSecretishPath(rel2))
|
|
19208
19009
|
return;
|
|
19209
19010
|
let stat;
|
|
19210
19011
|
try {
|
|
19211
|
-
stat =
|
|
19012
|
+
stat = lstatSync7(absPath);
|
|
19212
19013
|
} catch {
|
|
19213
19014
|
return;
|
|
19214
19015
|
}
|
|
@@ -19218,7 +19019,7 @@ function readSmallTextFileForHash(absPath, rootDir) {
|
|
|
19218
19019
|
if (!isTextFile(rel2))
|
|
19219
19020
|
return;
|
|
19220
19021
|
try {
|
|
19221
|
-
return
|
|
19022
|
+
return readFileSync12(absPath, "utf8");
|
|
19222
19023
|
} catch {
|
|
19223
19024
|
return;
|
|
19224
19025
|
}
|