@moda-ai/cli 1.55.54 → 1.55.56

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 (34) hide show
  1. package/dist/{agent-rmmtap23.js → agent-j0syymez.js} +10 -10
  2. package/dist/{cli-3dj84cbk.js → cli-2jwxdhh5.js} +1 -1
  3. package/dist/{cli-1ehmy9rh.js → cli-31ybq5f2.js} +2 -2
  4. package/dist/{cli-4vc2cksg.js → cli-7epk27vq.js} +5 -5
  5. package/dist/{cli-rdh9jjr2.js → cli-94r5x9bg.js} +1 -1
  6. package/dist/{cli-c1k20j6e.js → cli-9a4b1wxz.js} +1 -1
  7. package/dist/{cli-4pzbgxcn.js → cli-9g8kp42c.js} +2 -2
  8. package/dist/{cli-mf37dxpc.js → cli-b918vs2m.js} +4 -4
  9. package/dist/{cli-wry78bg8.js → cli-hawwf30b.js} +1 -1
  10. package/dist/{cli-c1vmgdjb.js → cli-jrf8annc.js} +8 -8
  11. package/dist/{cli-dxxc7tzq.js → cli-m25c0rke.js} +3 -3
  12. package/dist/{cli-7ye5004e.js → cli-p7856v3b.js} +541 -449
  13. package/dist/{cli-40fqk078.js → cli-pnarsb96.js} +1 -1
  14. package/dist/{cli-6hdqp65a.js → cli-rtkjjf0a.js} +1255 -66
  15. package/dist/{cli-gtke9wrw.js → cli-v2h21cgf.js} +1 -1
  16. package/dist/{cli-vswckv9g.js → cli-y5d33a1y.js} +1 -1
  17. package/dist/cli.js +20 -20
  18. package/dist/{doctor-b34em2fm.js → doctor-q8khayre.js} +8 -8
  19. package/dist/{harness-jcqwf5h6.js → harness-2vkcwm85.js} +8 -8
  20. package/dist/{harness-github-actions-rayyxh1w.js → harness-github-actions-yev2yrkr.js} +8 -8
  21. package/dist/{harness-report-rjcjbh93.js → harness-report-gz5d3y48.js} +1 -1
  22. package/dist/{index-cqnp8pfv.js → index-k6xec97f.js} +14 -14
  23. package/dist/{production-intelligence-zek0rkzj.js → production-intelligence-fqvhzq6s.js} +4 -4
  24. package/dist/{profile-commands-nbaec4y9.js → profile-commands-yvpe4d8y.js} +5 -5
  25. package/dist/{prompt-attribution-gyx0g661.js → prompt-attribution-2h9vertk.js} +8 -8
  26. package/dist/prompt-source-mcp.js +8 -8
  27. package/dist/{prompt-sources-qw2p4t5h.js → prompt-sources-1hycgx6r.js} +2 -2
  28. package/dist/{prompts-s4y90zs7.js → prompts-y35emwj0.js} +6 -6
  29. package/dist/{provision-tch8rc3y.js → provision-aqhfbnez.js} +6 -6
  30. package/dist/{registry-tv8fktxc.js → registry-wv1zzyce.js} +4 -4
  31. package/dist/{skills-mwftqzyk.js → skills-etzcqhp8.js} +6 -6
  32. package/dist/{sync-qxf3gkhy.js → sync-ydfxfjs5.js} +10 -10
  33. package/package.json +1 -1
  34. package/skills/integration/index.json +2 -2
@@ -13,16 +13,16 @@ import {
13
13
  import {
14
14
  createCommandContext,
15
15
  stringOption
16
- } from "./cli-gtke9wrw.js";
16
+ } from "./cli-v2h21cgf.js";
17
17
  import {
18
18
  assertFlags,
19
19
  assertPositionals,
20
20
  requireTenant
21
- } from "./cli-1ehmy9rh.js";
21
+ } from "./cli-31ybq5f2.js";
22
22
  import {
23
23
  ApiError,
24
24
  callControlAPI
25
- } from "./cli-wry78bg8.js";
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-40fqk078.js";
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-vswckv9g.js";
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-c1k20j6e.js";
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-6hdqp65a.js";
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 lstatSync8,
112
+ lstatSync as lstatSync7,
111
113
  mkdtempSync as mkdtempSync2,
112
114
  mkdirSync as mkdirSync5,
113
- readFileSync as readFileSync13,
114
- readdirSync as readdirSync5,
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 join10, relative as relative7, resolve as resolve10, sep as sep5 } from "node:path";
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
@@ -12126,7 +12128,7 @@ var LINE_PATTERNS = [
12126
12128
  kind: "prompt_literal",
12127
12129
  signal: "code.prompt_configuration_field",
12128
12130
  confidence: "high",
12129
- pattern: /(?:^|[{,])\s*(?:instructions|systemPrompt|system_prompt)\s*:/,
12131
+ pattern: /(?:^|[{,])\s*["']?(?:instructions?|systemPrompt|system_prompt|systemMessage|system_message|systemInstruction|system_instruction|backstory)["']?\s*:/,
12130
12132
  extensions: JS
12131
12133
  },
12132
12134
  {
@@ -13560,6 +13562,319 @@ function applyPromptDiscovery(graph, discovery) {
13560
13562
  // src/harness-candidate-promotion.ts
13561
13563
  import { readFileSync as readFileSync11 } from "node:fs";
13562
13564
  import { extname as extname7, posix, resolve as resolve9 } from "node:path";
13565
+
13566
+ // src/harness-js-source.ts
13567
+ var import_typescript2 = __toESM(require_typescript(), 1);
13568
+ var JS_EXTENSION = /\.(?:[cm]?[jt]sx?)$/i;
13569
+ function isJsSourcePath(path) {
13570
+ return JS_EXTENSION.test(path);
13571
+ }
13572
+ function scriptKindFor(path) {
13573
+ const lower = path.toLowerCase();
13574
+ if (lower.endsWith(".tsx"))
13575
+ return import_typescript2.default.ScriptKind.TSX;
13576
+ if (lower.endsWith(".ts") || lower.endsWith(".mts") || lower.endsWith(".cts"))
13577
+ return import_typescript2.default.ScriptKind.TS;
13578
+ if (lower.endsWith(".jsx"))
13579
+ return import_typescript2.default.ScriptKind.JSX;
13580
+ return import_typescript2.default.ScriptKind.JS;
13581
+ }
13582
+ function parseJsSource(path, text) {
13583
+ return import_typescript2.default.createSourceFile(path, text, import_typescript2.default.ScriptTarget.Latest, true, scriptKindFor(path));
13584
+ }
13585
+ function codeOnlyLines(source) {
13586
+ const text = source.text;
13587
+ const chars = text.split("");
13588
+ const seen = new Set;
13589
+ const jsxText = [];
13590
+ const collectJsxText = (node) => {
13591
+ if (node.kind === import_typescript2.default.SyntaxKind.JsxText)
13592
+ jsxText.push([node.getFullStart(), node.getEnd()]);
13593
+ import_typescript2.default.forEachChild(node, collectJsxText);
13594
+ };
13595
+ collectJsxText(source);
13596
+ const blank = (range) => {
13597
+ if (seen.has(range.pos))
13598
+ return;
13599
+ if (jsxText.some(([start, end]) => range.pos >= start && range.pos < end))
13600
+ return;
13601
+ seen.add(range.pos);
13602
+ for (let i = range.pos;i < range.end; i += 1) {
13603
+ if (chars[i] !== `
13604
+ ` && chars[i] !== "\r")
13605
+ chars[i] = " ";
13606
+ }
13607
+ };
13608
+ const visit = (node) => {
13609
+ if (node.kind === import_typescript2.default.SyntaxKind.JsxText)
13610
+ return;
13611
+ const children = node.getChildren(source);
13612
+ if (children.length === 0) {
13613
+ for (const range of import_typescript2.default.getLeadingCommentRanges(text, node.getFullStart()) ?? [])
13614
+ blank(range);
13615
+ for (const range of import_typescript2.default.getTrailingCommentRanges(text, node.getEnd()) ?? [])
13616
+ blank(range);
13617
+ return;
13618
+ }
13619
+ for (const child of children)
13620
+ visit(child);
13621
+ };
13622
+ visit(source);
13623
+ for (const range of import_typescript2.default.getLeadingCommentRanges(text, source.endOfFileToken.getFullStart()) ?? [])
13624
+ blank(range);
13625
+ return chars.join("").split(/\r?\n/);
13626
+ }
13627
+ var TRIM_METHODS = new Set(["trim", "trimStart", "trimEnd"]);
13628
+ var TEXT_TAGS = new Map([
13629
+ ["dedent", stripIndent],
13630
+ ["outdent", stripIndent],
13631
+ ["stripIndent", stripIndent],
13632
+ ["stripIndents", (text) => text.replace(/^[ \t]+/gm, "").trim()],
13633
+ ["oneLine", (text) => text.replace(/(?:\n(?:\s*))+/g, " ").trim()],
13634
+ ["oneLineTrim", (text) => text.replace(/(?:\n(?:\s*))+/g, "").trim()]
13635
+ ]);
13636
+ function stripIndent(text) {
13637
+ const indents = text.split(`
13638
+ `).filter((line) => line.trim() !== "").map((line) => /^[ \t]*/.exec(line)[0].length);
13639
+ const common = indents.length > 0 ? Math.min(...indents) : 0;
13640
+ return (common > 0 ? text.replace(new RegExp(`^[ \\t]{${common}}`, "gm"), "") : text).trim();
13641
+ }
13642
+ function stringValueOf(node, source) {
13643
+ if (import_typescript2.default.isStringLiteral(node) || import_typescript2.default.isNoSubstitutionTemplateLiteral(node))
13644
+ return node.text;
13645
+ if (import_typescript2.default.isTemplateExpression(node)) {
13646
+ let out = node.head.text;
13647
+ for (const span of node.templateSpans)
13648
+ out += `\${${span.expression.getText(source)}}${span.literal.text}`;
13649
+ return out;
13650
+ }
13651
+ if (import_typescript2.default.isParenthesizedExpression(node) || import_typescript2.default.isAsExpression(node) || import_typescript2.default.isSatisfiesExpression(node) || import_typescript2.default.isTypeAssertionExpression(node)) {
13652
+ return stringValueOf(node.expression, source);
13653
+ }
13654
+ if (import_typescript2.default.isTaggedTemplateExpression(node)) {
13655
+ const transform = import_typescript2.default.isIdentifier(node.tag) ? TEXT_TAGS.get(node.tag.text) : undefined;
13656
+ const inner = transform && stringValueOf(node.template, source);
13657
+ return inner === undefined || !transform ? undefined : transform(inner);
13658
+ }
13659
+ if (import_typescript2.default.isBinaryExpression(node) && node.operatorToken.kind === import_typescript2.default.SyntaxKind.PlusToken) {
13660
+ const parts = composedParts([node.left, node.right], source);
13661
+ return parts?.join("");
13662
+ }
13663
+ if (import_typescript2.default.isArrayLiteralExpression(node)) {
13664
+ return composedParts(node.elements, source)?.join(`
13665
+ `);
13666
+ }
13667
+ if (import_typescript2.default.isCallExpression(node)) {
13668
+ const callee = node.expression;
13669
+ const array = import_typescript2.default.isPropertyAccessExpression(callee) && callee.name.text === "join" ? unfiltered(callee.expression) : undefined;
13670
+ if (array && import_typescript2.default.isArrayLiteralExpression(array)) {
13671
+ const separatorArg = node.arguments[0];
13672
+ const separator = separatorArg === undefined ? "," : import_typescript2.default.isStringLiteral(separatorArg) || import_typescript2.default.isNoSubstitutionTemplateLiteral(separatorArg) ? separatorArg.text : undefined;
13673
+ if (separator === undefined)
13674
+ return;
13675
+ return composedParts(array.elements, source)?.join(separator);
13676
+ }
13677
+ if (import_typescript2.default.isPropertyAccessExpression(callee) && TRIM_METHODS.has(callee.name.text) && node.arguments.length === 0) {
13678
+ const inner = stringValueOf(callee.expression, source);
13679
+ return inner === undefined ? undefined : callee.name.text === "trimStart" ? inner.trimStart() : callee.name.text === "trimEnd" ? inner.trimEnd() : inner.trim();
13680
+ }
13681
+ const transform = import_typescript2.default.isIdentifier(callee) && node.arguments.length === 1 ? TEXT_TAGS.get(callee.text) : undefined;
13682
+ if (transform) {
13683
+ const inner = stringValueOf(node.arguments[0], source);
13684
+ return inner === undefined ? undefined : transform(inner);
13685
+ }
13686
+ return;
13687
+ }
13688
+ return;
13689
+ }
13690
+ function composedParts(elements, source) {
13691
+ let literal = false;
13692
+ const parts = [];
13693
+ for (const element of elements) {
13694
+ if (import_typescript2.default.isOmittedExpression(element))
13695
+ return;
13696
+ const value = import_typescript2.default.isSpreadElement(element) ? undefined : stringValueOf(element, source);
13697
+ if (value !== undefined)
13698
+ literal = true;
13699
+ parts.push(value ?? `\${${element.getText(source)}}`);
13700
+ }
13701
+ return literal && parts.length > 0 ? parts : undefined;
13702
+ }
13703
+ function unfiltered(node) {
13704
+ let current = node;
13705
+ while (import_typescript2.default.isCallExpression(current) && import_typescript2.default.isPropertyAccessExpression(current.expression) && current.expression.name.text === "filter") {
13706
+ const [predicate] = current.arguments;
13707
+ if (current.arguments.length !== 1 || !import_typescript2.default.isIdentifier(predicate) || predicate.text !== "Boolean")
13708
+ return;
13709
+ current = current.expression.expression;
13710
+ }
13711
+ return current;
13712
+ }
13713
+ var PROMPT_NAME = /prompt|instruction|system|template|rubric|persona|backstory|content/i;
13714
+ function comparable(text) {
13715
+ return text.replace(/\\/g, "").replace(/\s+/g, " ").trim();
13716
+ }
13717
+ function lineOf(source, position) {
13718
+ return source.getLineAndCharacterOfPosition(position).line + 1;
13719
+ }
13720
+ function propertyNameText(name) {
13721
+ if (import_typescript2.default.isIdentifier(name) || import_typescript2.default.isStringLiteral(name) || import_typescript2.default.isPrivateIdentifier(name))
13722
+ return name.text;
13723
+ return;
13724
+ }
13725
+ function enclosingFunctionName(node) {
13726
+ for (let current = node.parent;current; current = current.parent) {
13727
+ if (import_typescript2.default.isFunctionDeclaration(current) || import_typescript2.default.isMethodDeclaration(current)) {
13728
+ return current.name && (import_typescript2.default.isIdentifier(current.name) || import_typescript2.default.isStringLiteral(current.name)) ? current.name.text : undefined;
13729
+ }
13730
+ if (import_typescript2.default.isArrowFunction(current) || import_typescript2.default.isFunctionExpression(current)) {
13731
+ const holder = current.parent;
13732
+ if (holder && import_typescript2.default.isVariableDeclaration(holder) && import_typescript2.default.isIdentifier(holder.name))
13733
+ return holder.name.text;
13734
+ if (holder && import_typescript2.default.isPropertyAssignment(holder))
13735
+ return propertyNameText(holder.name);
13736
+ return;
13737
+ }
13738
+ }
13739
+ return;
13740
+ }
13741
+ function jsLiteralDefinitionAt(source, startLine, excerpt2) {
13742
+ const literal = excerpt2 ? comparable(excerpt2).slice(0, 120) : "";
13743
+ const all = [];
13744
+ const consider = (node, value, def, depth) => {
13745
+ const defLine = lineOf(source, node.getStart(source));
13746
+ const valueLine = lineOf(source, value.getStart(source));
13747
+ const valueEndLine = lineOf(source, value.getEnd());
13748
+ const distance = valueLine === startLine || defLine === startLine ? 0 : defLine === startLine - 1 && valueEndLine >= startLine ? 1 : -1;
13749
+ if (distance < 0)
13750
+ return;
13751
+ const text = stringValueOf(value, source);
13752
+ if (text === undefined)
13753
+ return;
13754
+ all.push({
13755
+ def: { ...def, text, line: defLine },
13756
+ start: node.getStart(source),
13757
+ depth,
13758
+ distance,
13759
+ matches: literal.length > 0 && comparable(value.getText(source)).includes(literal),
13760
+ named: PROMPT_NAME.test(def.key ?? def.identifier ?? "")
13761
+ });
13762
+ };
13763
+ const visit = (node, depth) => {
13764
+ const nodeStart = lineOf(source, node.getStart(source));
13765
+ const nodeEnd = lineOf(source, node.getEnd());
13766
+ if (nodeEnd < startLine - 1 || nodeStart > startLine)
13767
+ return;
13768
+ if (import_typescript2.default.isVariableDeclaration(node) && import_typescript2.default.isIdentifier(node.name) && node.initializer) {
13769
+ consider(node, node.initializer, { identifier: node.name.text }, depth);
13770
+ } else if (import_typescript2.default.isPropertyAssignment(node)) {
13771
+ const key = propertyNameText(node.name);
13772
+ if (key)
13773
+ consider(node, node.initializer, { key }, depth);
13774
+ } else if (import_typescript2.default.isPropertyDeclaration(node) && node.initializer) {
13775
+ const name = propertyNameText(node.name);
13776
+ if (name)
13777
+ consider(node, node.initializer, { identifier: name }, depth);
13778
+ } else if (import_typescript2.default.isBinaryExpression(node) && node.operatorToken.kind === import_typescript2.default.SyntaxKind.EqualsToken) {
13779
+ const target = node.left;
13780
+ const name = import_typescript2.default.isIdentifier(target) ? target.text : import_typescript2.default.isPropertyAccessExpression(target) ? target.name.text : undefined;
13781
+ if (name)
13782
+ consider(node, node.right, { identifier: name }, depth);
13783
+ } else if (import_typescript2.default.isReturnStatement(node) && node.expression) {
13784
+ const name = enclosingFunctionName(node);
13785
+ if (name)
13786
+ consider(node, node.expression, { identifier: name }, depth);
13787
+ }
13788
+ import_typescript2.default.forEachChild(node, (child) => visit(child, depth + 1));
13789
+ };
13790
+ visit(source, 0);
13791
+ const rank = (a, b) => a.distance - b.distance || Number(b.matches) - Number(a.matches) || Number(b.named) - Number(a.named) || b.def.text.length - a.def.text.length || b.depth - a.depth;
13792
+ const best = all.sort(rank)[0];
13793
+ if (!best)
13794
+ return;
13795
+ const earlier = all.some((other) => other.def.line === best.def.line && other.start < best.start);
13796
+ return earlier ? { ...best.def, column: source.getLineAndCharacterOfPosition(best.start).character + 1 } : best.def;
13797
+ }
13798
+ function calleeText(call, source) {
13799
+ return call.expression.getText(source).replace(/\s+/g, "");
13800
+ }
13801
+ function outermostContainer(node) {
13802
+ let current = node;
13803
+ while (current.parent && (import_typescript2.default.isPropertyAssignment(current.parent) || import_typescript2.default.isObjectLiteralExpression(current.parent) || import_typescript2.default.isArrayLiteralExpression(current.parent) || import_typescript2.default.isParenthesizedExpression(current.parent) || import_typescript2.default.isAsExpression(current.parent) || import_typescript2.default.isSatisfiesExpression(current.parent) || import_typescript2.default.isSpreadElement(current.parent) || import_typescript2.default.isShorthandPropertyAssignment(current.parent) || import_typescript2.default.isAwaitExpression(current.parent) || import_typescript2.default.isNonNullExpression(current.parent)))
13804
+ current = current.parent;
13805
+ return current;
13806
+ }
13807
+ function isExportedDeclaration(declaration) {
13808
+ const statement = declaration.parent?.parent;
13809
+ return Boolean(statement && import_typescript2.default.isVariableStatement(statement) && statement.modifiers?.some((modifier) => modifier.kind === import_typescript2.default.SyntaxKind.ExportKeyword));
13810
+ }
13811
+ function followValue(start, source, callees, targets, seen, out) {
13812
+ let current = start;
13813
+ for (;; ) {
13814
+ let parent = current.parent;
13815
+ while (parent && ((import_typescript2.default.isPropertyAccessExpression(parent) || import_typescript2.default.isElementAccessExpression(parent)) && parent.expression === current)) {
13816
+ current = parent;
13817
+ parent = current.parent;
13818
+ }
13819
+ const container = outermostContainer(current);
13820
+ const holder = container.parent;
13821
+ if (holder && (import_typescript2.default.isCallExpression(holder) || import_typescript2.default.isNewExpression(holder)) && (holder.arguments?.includes(container) || import_typescript2.default.isCallExpression(holder) && holder.expression === container)) {
13822
+ callees.push(calleeText(holder, source));
13823
+ targets.push(holder.arguments?.[0]?.getText(source) ?? "");
13824
+ current = holder;
13825
+ continue;
13826
+ }
13827
+ if (holder && import_typescript2.default.isVariableDeclaration(holder) && import_typescript2.default.isIdentifier(holder.name) && holder.initializer === container) {
13828
+ if (seen.has(holder))
13829
+ return;
13830
+ seen.add(holder);
13831
+ const name = holder.name.text;
13832
+ const declaration = holder.name;
13833
+ const before = out.length;
13834
+ if (isExportedDeclaration(holder))
13835
+ out.push({ callees: [...callees], targets: [...targets], display: false, escape: "export" });
13836
+ const visit = (node) => {
13837
+ if (import_typescript2.default.isIdentifier(node) && node.text === name && node !== declaration && !(node.parent && import_typescript2.default.isPropertyAccessExpression(node.parent) && node.parent.name === node)) {
13838
+ followValue(node, source, [...callees], [...targets], seen, out);
13839
+ }
13840
+ import_typescript2.default.forEachChild(node, visit);
13841
+ };
13842
+ visit(source);
13843
+ if (out.length === before)
13844
+ out.push({ callees: [...callees], targets: [...targets], display: false, escape: "unknown" });
13845
+ return;
13846
+ }
13847
+ const display = Boolean(holder && (import_typescript2.default.isJsxExpression(holder) || import_typescript2.default.isJsxSpreadAttribute(holder)));
13848
+ const statement = Boolean(holder && import_typescript2.default.isExpressionStatement(holder));
13849
+ const exported = Boolean(holder && (import_typescript2.default.isExportSpecifier(holder) || import_typescript2.default.isExportAssignment(holder)));
13850
+ out.push({ callees, targets, display, escape: display || statement ? undefined : exported ? "export" : "unknown" });
13851
+ return;
13852
+ }
13853
+ }
13854
+ function keyedValueConsumer(source, line, key, column) {
13855
+ let property;
13856
+ const find = (node) => {
13857
+ if (property)
13858
+ return;
13859
+ if (import_typescript2.default.isPropertyAssignment(node) && lineOf(source, node.getStart(source)) === line && (column === undefined || source.getLineAndCharacterOfPosition(node.getStart(source)).character + 1 === column) && (import_typescript2.default.isIdentifier(node.name) || import_typescript2.default.isStringLiteral(node.name)) && node.name.text === key) {
13860
+ property = node;
13861
+ return;
13862
+ }
13863
+ import_typescript2.default.forEachChild(node, find);
13864
+ };
13865
+ find(source);
13866
+ if (!property)
13867
+ return { kind: "uses", uses: [{ callees: [], targets: [], display: false, escape: "unknown" }] };
13868
+ const owner = property.parent;
13869
+ if (import_typescript2.default.isObjectLiteralExpression(owner) && owner.properties.some((other) => import_typescript2.default.isPropertyAssignment(other) && import_typescript2.default.isIdentifier(other.name) && other.name.text === "role" && (import_typescript2.default.isStringLiteral(other.initializer) || import_typescript2.default.isNoSubstitutionTemplateLiteral(other.initializer)) && /^(?:system|user|assistant|developer|human)$/.test(other.initializer.text))) {
13870
+ return { kind: "chat_message" };
13871
+ }
13872
+ const uses = [];
13873
+ followValue(property, source, [], [], new Set, uses);
13874
+ return { kind: "uses", uses };
13875
+ }
13876
+
13877
+ // src/harness-candidate-promotion.ts
13563
13878
  var PROMOTED_CONFIDENCE = {
13564
13879
  high: 0.85,
13565
13880
  medium: 0.6
@@ -13582,13 +13897,21 @@ function candidateEvidence(candidate) {
13582
13897
  function pathStem(path) {
13583
13898
  return path.replace(/\.[^.]+$/, "");
13584
13899
  }
13900
+ var jsSources = new Map;
13585
13901
  function readFileLines(rootDir, path, cache) {
13586
13902
  const cached = cache.get(path);
13587
13903
  if (cached !== undefined)
13588
13904
  return cached;
13589
13905
  let lines;
13590
13906
  try {
13591
- lines = readFileSync11(resolve9(rootDir, path), "utf8").split(/\r?\n/);
13907
+ const text = readFileSync11(resolve9(rootDir, path), "utf8");
13908
+ if (isJsSourcePath(path)) {
13909
+ const source = parseJsSource(path, text);
13910
+ jsSources.set(`${rootDir}::${path}`, source);
13911
+ lines = codeOnlyLines(source);
13912
+ } else {
13913
+ lines = text.split(/\r?\n/);
13914
+ }
13592
13915
  } catch {
13593
13916
  lines = null;
13594
13917
  }
@@ -13663,6 +13986,12 @@ function buildsPrompts(path, lines) {
13663
13986
  return false;
13664
13987
  return exportedNames(path, lines).some((name) => !UTILITY_EXPORT.test(name) && (BUILDER_VERB.test(name) || PROMPT_NOUN_LAST.test(name)));
13665
13988
  }
13989
+ var TEST_FILE2 = /(?:^|\/)(?:test_[^/]*\.py|[^/]*_test\.py|conftest\.py|[^/]*\.(?:test|spec)\.[^/]+)$/i;
13990
+ var FIXTURE_DIR2 = /(?:^|\/)(?:fixtures?|test-fixtures|__fixtures__|__mocks__)(?:\/|$)/i;
13991
+ var EVAL_HARNESS_PATH = /(?:^|[\/_.-])(?:evals?|evaluations?|judges?|grader|grading|pairwise|quality|rubrics?|benchmarks?)(?:[\/_.-]|$)/i;
13992
+ function isTestInput(path) {
13993
+ return (TEST_FILE2.test(path) || FIXTURE_DIR2.test(path)) && !EVAL_HARNESS_PATH.test(path);
13994
+ }
13666
13995
  function promotePromptFileCandidate(candidate, confidence2) {
13667
13996
  return {
13668
13997
  id: stableId("prompt", candidate.path),
@@ -13694,6 +14023,7 @@ var MODEL_INPUT_KEYS = [
13694
14023
  "text"
13695
14024
  ];
13696
14025
  var DIRECT_PROMPT_KEYS = new Set([
14026
+ "instruction",
13697
14027
  "system",
13698
14028
  "systemPrompt",
13699
14029
  "system_prompt",
@@ -13725,6 +14055,7 @@ var CONFIG_EXTENSIONS = new Set([".json", ".yaml", ".yml"]);
13725
14055
  var PROMPT_NAMED_IDENTIFIER = /prompt|system|instruction/i;
13726
14056
  var SECOND_PERSON_OPENING = /^\s*(?:\[[A-Z]+:\s*|<\w+>\s*)*(?:you|your)\b/i;
13727
14057
  var MIN_UNNAMED_REFERENCED_PROMPT_CHARS = 200;
14058
+ var UNUSED_PROMPT_CONFIDENCE = 0.6;
13728
14059
  var REFERENCED_PROMPT_CONFIDENCE = 0.7;
13729
14060
  var MIN_RESOLVED_PROMPT_CHARS = 20;
13730
14061
  var MIN_CONFIG_PROMPT_CHARS = 40;
@@ -13751,128 +14082,15 @@ function readStringLiteral(text, start) {
13751
14082
  i += 2;
13752
14083
  continue;
13753
14084
  }
13754
- if (opener.length === 1 && opener !== "`" && char === `
14085
+ if (opener.length === 1 && char === `
13755
14086
  `)
13756
14087
  return;
13757
- if (opener === "`" && char === "$" && text[i + 1] === "{") {
13758
- let depth = 1;
13759
- i += 2;
13760
- while (i < text.length && depth > 0) {
13761
- if (text[i] === "`" || text[i] === '"' || text[i] === "'") {
13762
- const nested = readStringLiteral(text, i);
13763
- if (nested) {
13764
- i = nested.end;
13765
- continue;
13766
- }
13767
- if (text[i] === "`")
13768
- return;
13769
- i += 1;
13770
- continue;
13771
- }
13772
- const regexEnd = text[i] === "/" ? regexLiteralEnd(text, i) : undefined;
13773
- if (regexEnd !== undefined) {
13774
- i = regexEnd;
13775
- continue;
13776
- }
13777
- if (text.startsWith("//", i)) {
13778
- const newline = text.indexOf(`
13779
- `, i);
13780
- i = newline < 0 ? text.length : newline;
13781
- continue;
13782
- }
13783
- if (text.startsWith("/*", i)) {
13784
- const close = text.indexOf("*/", i + 2);
13785
- if (close < 0)
13786
- return;
13787
- i = close + 2;
13788
- continue;
13789
- }
13790
- if (text[i] === "{")
13791
- depth += 1;
13792
- else if (text[i] === "}")
13793
- depth -= 1;
13794
- i += 1;
13795
- }
13796
- continue;
13797
- }
13798
14088
  if (text.startsWith(opener, i))
13799
14089
  return { value: text.slice(start + opener.length, i), end: i + opener.length };
13800
14090
  i += 1;
13801
14091
  }
13802
14092
  return;
13803
14093
  }
13804
- var EXPRESSION_KEYWORDS = new Set([
13805
- "return",
13806
- "typeof",
13807
- "instanceof",
13808
- "in",
13809
- "of",
13810
- "new",
13811
- "delete",
13812
- "void",
13813
- "throw",
13814
- "case",
13815
- "do",
13816
- "else",
13817
- "yield",
13818
- "await"
13819
- ]);
13820
- function endsWithOperand(text, end) {
13821
- let i = end;
13822
- while (i > 0 && /\s/.test(text[i - 1]))
13823
- i -= 1;
13824
- if (i === 0)
13825
- return false;
13826
- const char = text[i - 1];
13827
- if (char === ")" || char === "]" || char === '"' || char === "'" || char === "`")
13828
- return true;
13829
- if (/[\w$]/.test(char)) {
13830
- let wordStart = i;
13831
- while (wordStart > 0 && /[\w$]/.test(text[wordStart - 1]))
13832
- wordStart -= 1;
13833
- const word = text.slice(wordStart, i);
13834
- if (/^\d/.test(word))
13835
- return true;
13836
- let before = wordStart;
13837
- while (before > 0 && /\s/.test(text[before - 1]))
13838
- before -= 1;
13839
- const isProperty = text[before - 1] === "." && text[before - 2] !== ".";
13840
- return isProperty || !EXPRESSION_KEYWORDS.has(word);
13841
- }
13842
- if ((char === "+" || char === "-") && text[i - 2] === char)
13843
- return endsWithOperand(text, i - 2);
13844
- if (char === "!" && i >= 2 && /[\w$)\]]/.test(text[i - 2]))
13845
- return endsWithOperand(text, i - 1);
13846
- return false;
13847
- }
13848
- function regexLiteralEnd(text, start) {
13849
- if (text[start + 1] === "/" || text[start + 1] === "*")
13850
- return;
13851
- if (endsWithOperand(text, start))
13852
- return;
13853
- let inClass = false;
13854
- for (let i = start + 1;i < text.length; i += 1) {
13855
- const char = text[i];
13856
- if (char === `
13857
- `)
13858
- return;
13859
- if (char === "\\") {
13860
- i += 1;
13861
- continue;
13862
- }
13863
- if (char === "[")
13864
- inClass = true;
13865
- else if (char === "]")
13866
- inClass = false;
13867
- else if (char === "/" && !inClass) {
13868
- let end = i + 1;
13869
- while (/[a-z]/i.test(text[end] ?? ""))
13870
- end += 1;
13871
- return end;
13872
- }
13873
- }
13874
- return;
13875
- }
13876
14094
  function readStringValue(text, offset) {
13877
14095
  let i = offset;
13878
14096
  const parts = [];
@@ -13929,7 +14147,9 @@ function stringStart(rest) {
13929
14147
  }
13930
14148
  return STRING_OPENER.test(remaining) ? consumed : -1;
13931
14149
  }
13932
- function resolvePromptLiteralDefinition(lines, startLine) {
14150
+ function resolvePromptLiteralDefinition(lines, startLine, jsSource, excerpt2) {
14151
+ if (jsSource)
14152
+ return jsLiteralDefinitionAt(jsSource, startLine, excerpt2);
13933
14153
  const text = lines.join(`
13934
14154
  `);
13935
14155
  for (const index of [startLine - 1, startLine - 2]) {
@@ -14007,16 +14227,8 @@ function resolvePromptLiteralDefinition(lines, startLine) {
14007
14227
  }
14008
14228
  function endsInComment(prefix) {
14009
14229
  let quote;
14010
- let inBlock = false;
14011
14230
  for (let i = 0;i < prefix.length; i += 1) {
14012
14231
  const char = prefix[i];
14013
- if (inBlock) {
14014
- if (prefix.startsWith("*/", i)) {
14015
- inBlock = false;
14016
- i += 1;
14017
- }
14018
- continue;
14019
- }
14020
14232
  if (quote) {
14021
14233
  if (char === "\\")
14022
14234
  i += 1;
@@ -14024,23 +14236,14 @@ function endsInComment(prefix) {
14024
14236
  quote = undefined;
14025
14237
  continue;
14026
14238
  }
14027
- if (char === '"' || char === "'" || char === "`") {
14239
+ if (char === '"' || char === "'") {
14028
14240
  quote = char;
14029
14241
  continue;
14030
14242
  }
14031
- const regexEnd = char === "/" ? regexLiteralEnd(prefix, i) : undefined;
14032
- if (regexEnd !== undefined) {
14033
- i = regexEnd - 1;
14034
- continue;
14035
- }
14036
- if (prefix.startsWith("//", i))
14243
+ if (char === "#")
14037
14244
  return true;
14038
- else if (prefix.startsWith("/*", i)) {
14039
- inBlock = true;
14040
- i += 1;
14041
- }
14042
14245
  }
14043
- return inBlock;
14246
+ return false;
14044
14247
  }
14045
14248
  function readYamlBlockScalar(lines, index, rest) {
14046
14249
  const indicator = /^([|>])([-+]?)\s*(?:#.*)?$/.exec(rest.trim());
@@ -14204,7 +14407,7 @@ function importStatementLines(lines) {
14204
14407
  }
14205
14408
  return covered;
14206
14409
  }
14207
- var MODEL_CALLEE = /model|llm|complet|generat|chat|invoke|infer|prompt|agent|judge|claude|gpt|openai|anthropic|gemini|\.create$/i;
14410
+ var MODEL_CALLEE = /model|llm|complet|generat|chat|invoke|infer|prompt|agent|judge|jev|claude|gpt|openai|anthropic|gemini|\.create$/i;
14208
14411
  function calleeImportedFromModelFile(callee, path, lines, modelFiles) {
14209
14412
  const base = callee.split(".")[0];
14210
14413
  const text = lines.join(`
@@ -14249,7 +14452,10 @@ function localHelperCallsModel(callee, lines) {
14249
14452
  const start = lines.findIndex((line) => head.test(line));
14250
14453
  if (start < 0)
14251
14454
  return false;
14252
- return lines.slice(start + 1, start + 1 + MAX_HELPER_BODY_LINES).some((line) => MODEL_CALL_IN_BODY.test(line));
14455
+ const match = head.exec(lines[start]);
14456
+ const declared = /^\s*(?:export\s+)?(?:async\s+)?(?:function|def|const|let|var)\b/.test(lines[start]);
14457
+ const sameLine = declared && match ? lines[start].slice(match.index + match[0].length) : "";
14458
+ return [sameLine, ...lines.slice(start + 1, start + 1 + MAX_HELPER_BODY_LINES)].some((line) => MODEL_CALL_IN_BODY.test(line));
14253
14459
  }
14254
14460
  function callCarriesChatMessages(lines, index) {
14255
14461
  for (let i = Math.max(0, index - CALL_ROLE_WINDOW_LINES);i < Math.min(lines.length, index + CALL_ROLE_WINDOW_LINES + 1); i += 1) {
@@ -14396,6 +14602,31 @@ function readsAsInstructions(identifier, text) {
14396
14602
  return score >= 2 || secondPerson;
14397
14603
  return secondPerson && score >= 2 && text.length >= MIN_UNNAMED_REFERENCED_PROMPT_CHARS;
14398
14604
  }
14605
+ function readsAsUnusedPrompt(name, text) {
14606
+ if (UI_COPY_NAME.test(name))
14607
+ return false;
14608
+ if (DIRECT_PROMPT_KEYS.has(name) && instructionScore(text) >= 2)
14609
+ return true;
14610
+ return readsAsInstructions(name, text);
14611
+ }
14612
+ var UI_COPY_NAME = /placeholder|label|tooltip|hint|title|caption|toast|button|error|empty_?state|copy/i;
14613
+ function isOnlyDisplayed(lines, identifier, definitionLine) {
14614
+ const ident = escapeRegExp(identifier);
14615
+ const reference = new RegExp(`(?<![\\w$.])${ident}(?![\\w$])`);
14616
+ const display = new RegExp(`\\{\\s*${ident}\\s*\\}(?!\\s*from)|[\\w-]+=\\{\\s*${ident}\\s*\\}|\\b(?:console|logger|log)\\.\\w+\\([^)]*\\b${ident}\\b|\\b(?:toast|alert|notify)\\w*\\([^)]*\\b${ident}\\b`);
14617
+ let references = 0;
14618
+ for (let index = 0;index < lines.length; index += 1) {
14619
+ const line = lines[index];
14620
+ if (index === definitionLine - 1 || !reference.test(line))
14621
+ continue;
14622
+ if (/^\s*(?:\/\/|#|\*|export\s*(?:default\s+)?\{|export\s+default\s+[\w$]+\s*;?\s*$)/.test(line))
14623
+ continue;
14624
+ references += 1;
14625
+ if (!display.test(line))
14626
+ return false;
14627
+ }
14628
+ return references > 0;
14629
+ }
14399
14630
  function hasNearbyRole(lines, line) {
14400
14631
  for (let i = Math.max(0, line - 4);i < Math.min(lines.length, line + 3); i += 1) {
14401
14632
  if (/\brole\b\s*["']?\s*[:=]/.test(lines[i]))
@@ -14410,21 +14641,100 @@ function isDirectModelInput(key, value, path, lines, line, modelFiles) {
14410
14641
  if (modelFiles.has(path)) {
14411
14642
  return DIRECT_PROMPT_KEYS.has(key) || key === "content" && hasNearbyRole(lines, line);
14412
14643
  }
14644
+ if (PROMPT_CONFIG_KEYS.has(key))
14645
+ return true;
14413
14646
  return DIRECT_PROMPT_KEYS.has(key) && instructionScore(value) >= 2;
14414
14647
  }
14648
+ function isModelCallee(callee, path, lines, modelFiles) {
14649
+ return MODEL_CALLEE.test(callee) || calleeImportedFromModelFile(callee, path, lines, modelFiles) || localHelperCallsModel(callee, lines);
14650
+ }
14651
+ function importSpecifiers(lines) {
14652
+ return lines.flatMap((line) => [...line.matchAll(/\bfrom\s+["']?([.\w/@$-]+)["']?|\bimport\s*\(\s*["']([^"']+)["']|\brequire\(\s*["']([^"']+)["']/g)].map((match) => match[1] ?? match[2] ?? match[3]));
14653
+ }
14654
+ var MODEL_ENDPOINT = /api\.anthropic\.com|api\.openai\.com|openrouter\.ai|generativelanguage\.googleapis\.com|api\.mistral\.ai|api\.groq\.com|api\.together\.(?:xyz|ai)|api\.deepseek\.com|\/chat\/completions\b|\/v1\/messages\b|\/v1\/responses\b/;
14655
+ var HTTP_CALLEE = /^(?:fetch|axios(?:\.post|\.request)?|got(?:\.post)?|ky(?:\.post)?|request|ofetch|\$fetch)$/;
14656
+ function targetsModelEndpoint(target, lines) {
14657
+ if (MODEL_ENDPOINT.test(target))
14658
+ return true;
14659
+ const name = /^(?:[A-Za-z_$][\w$]*\.)*([A-Za-z_$][\w$]*)$/.exec(target.trim())?.[1];
14660
+ if (!name)
14661
+ return false;
14662
+ const binding = new RegExp(`\\b${escapeRegExp(name)}\\s*[:=](?!=)`);
14663
+ return lines.some((line, index) => {
14664
+ const match = binding.exec(line);
14665
+ if (!match)
14666
+ return false;
14667
+ const initializer = [line.slice(match.index), ...lines.slice(index + 1, index + 4)].join(`
14668
+ `);
14669
+ const end = initializer.search(/;|,\s*$/m);
14670
+ return MODEL_ENDPOINT.test(end < 0 ? initializer : initializer.slice(0, end));
14671
+ });
14672
+ }
14673
+ function fileReachesModel(path, lines, modelFiles) {
14674
+ if (modelFiles.has(path))
14675
+ return true;
14676
+ if (lines.some((line) => MODEL_ENDPOINT.test(line)))
14677
+ return true;
14678
+ const python = extname7(path) === ".py";
14679
+ return importSpecifiers(lines).some((spec) => [...modelFiles].some((modelFile) => specifierResolvesTo(spec, path, modelFile, python)));
14680
+ }
14681
+ function modelFileImports(path, rootDir, modelFiles, fileCache) {
14682
+ return [...modelFiles].some((modelFile) => {
14683
+ if (modelFile === path)
14684
+ return false;
14685
+ const lines = readFileLines(rootDir, modelFile, fileCache);
14686
+ return Boolean(lines && importSpecifiers(lines).some((spec) => specifierResolvesTo(spec, modelFile, path, extname7(modelFile) === ".py")));
14687
+ });
14688
+ }
14689
+ var PASS_THROUGH_CALLEE = /^(?:Object\.(?:freeze|seal|assign)|structuredClone|Promise\.resolve|JSON\.stringify|(?:_\.|lodash\.)?(?:cloneDeep|clone|merge)|deepFreeze|defu)$/;
14690
+ function escapesAsItself(use, kind) {
14691
+ return use.escape !== undefined && (kind === undefined || use.escape === kind) && use.callees.every((callee) => PASS_THROUGH_CALLEE.test(callee));
14692
+ }
14693
+ function keyedObjectReachesModel(consumer, path, lines, modelFiles) {
14694
+ if (consumer.kind === "chat_message")
14695
+ return true;
14696
+ return consumer.uses.some((use) => escapesAsItself(use) || use.callees.some((callee, index) => isModelCallee(callee, path, lines, modelFiles) || HTTP_CALLEE.test(callee) && targetsModelEndpoint(use.targets[index] ?? "", lines)));
14697
+ }
14698
+ var PROMPT_CONFIG_KEYS = new Set([
14699
+ "instructions",
14700
+ "instruction",
14701
+ "systemPrompt",
14702
+ "system_prompt",
14703
+ "systemMessage",
14704
+ "system_message",
14705
+ "systemInstruction",
14706
+ "system_instruction",
14707
+ "backstory"
14708
+ ]);
14415
14709
  function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache, files) {
14416
14710
  const lines = readFileLines(rootDir, candidate.path, fileCache);
14417
14711
  if (!lines)
14418
14712
  return;
14419
- const definition = resolvePromptLiteralDefinition(lines, candidate.startLine);
14713
+ const definition = resolvePromptLiteralDefinition(lines, candidate.startLine, jsSources.get(`${rootDir}::${candidate.path}`), candidate.excerpt);
14420
14714
  if (!definition)
14421
14715
  return;
14422
14716
  const value = definition.text.trim();
14423
14717
  const literalText = value.replace(/\$\{[^}]*\}|\{[A-Za-z_][\w.]*\}/g, "").trim();
14424
- if (literalText.length < MIN_RESOLVED_PROMPT_CHARS || isCodeLikeContent(value))
14718
+ const minChars = definition.key && PROMPT_CONFIG_KEYS.has(definition.key) ? 1 : MIN_RESOLVED_PROMPT_CHARS;
14719
+ if (literalText.length < minChars || isCodeLikeContent(value))
14720
+ return;
14721
+ if (isTestInput(candidate.path))
14425
14722
  return;
14426
14723
  const key = definition.key ?? (definition.identifier && DIRECT_PROMPT_KEYS.has(definition.identifier) ? definition.identifier : undefined);
14427
14724
  let use;
14725
+ const jsSource = jsSources.get(`${rootDir}::${candidate.path}`);
14726
+ if (definition.key && !PROMPT_CONFIG_KEYS.has(definition.key) && !CONFIG_EXTENSIONS.has(extname7(candidate.path).toLowerCase())) {
14727
+ const exportUsed = () => modelFileImports(candidate.path, rootDir, files.model, fileCache);
14728
+ if (jsSource) {
14729
+ const consumer = keyedValueConsumer(jsSource, definition.line, definition.key, definition.column);
14730
+ if (!fileReachesModel(candidate.path, lines, files.model) && !(consumer.kind === "uses" && consumer.uses.some((use2) => escapesAsItself(use2, "export")) && exportUsed()))
14731
+ return;
14732
+ if (!keyedObjectReachesModel(consumer, candidate.path, lines, files.model))
14733
+ return;
14734
+ } else if (!fileReachesModel(candidate.path, lines, files.model) && !exportUsed()) {
14735
+ return;
14736
+ }
14737
+ }
14428
14738
  if (key && isDirectModelInput(key, value, candidate.path, lines, definition.line, files.model)) {
14429
14739
  use = { path: candidate.path, line: definition.line, key };
14430
14740
  }
@@ -14433,9 +14743,15 @@ function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCach
14433
14743
  allowReference: readsAsInstructions(definition.identifier, value)
14434
14744
  });
14435
14745
  }
14436
- if (!use)
14437
- return;
14438
14746
  const name = definition.identifier ?? definition.key;
14747
+ const unused = !use;
14748
+ if (!use) {
14749
+ if (!name || !readsAsUnusedPrompt(name, value))
14750
+ return;
14751
+ if (definition.identifier && isOnlyDisplayed(lines, definition.identifier, definition.line))
14752
+ return;
14753
+ use = { path: candidate.path, line: definition.line, key: "unused" };
14754
+ }
14439
14755
  const evidence = [{ path: candidate.path, line: definition.line, reason: `deterministic detector ${candidate.signal}` }];
14440
14756
  const sameSite = use.path === candidate.path && use.line === definition.line;
14441
14757
  if (!sameSite) {
@@ -14446,13 +14762,13 @@ function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCach
14446
14762
  });
14447
14763
  }
14448
14764
  return {
14449
- id: stableId("prompt", `${pathStem(candidate.path)}:L${definition.line}`),
14765
+ id: stableId("prompt", `${pathStem(candidate.path)}:L${definition.line}${definition.column ? `C${definition.column}` : ""}`),
14450
14766
  type: "prompt",
14451
14767
  name: name ? titleFromId(name) : `Inline Prompt (${candidate.path}:${definition.line})`,
14452
14768
  scope: "shared",
14453
14769
  usedByAgentIds: [],
14454
- confidence: use.referenceOnly ? Math.min(confidence2, REFERENCED_PROMPT_CONFIDENCE) : confidence2,
14455
- confidenceReason: use.referenceOnly ? `Deterministic: instruction-like literal ${name} is referenced at ${use.path}:${use.line} through ${use.via}, but no prompt key (system, instructions, content) was found at the call.` : sameSite ? `Deterministic: string literal written under the ${use.key} key at ${candidate.path}:${definition.line}.` : `Deterministic: string literal ${name} passed to a model call as ${use.key} at ${use.path}:${use.line}.`,
14770
+ confidence: unused ? Math.min(confidence2, UNUSED_PROMPT_CONFIDENCE) : use.referenceOnly ? Math.min(confidence2, REFERENCED_PROMPT_CONFIDENCE) : confidence2,
14771
+ confidenceReason: unused ? `Deterministic: instruction-like literal ${name} at ${candidate.path}:${definition.line}; no model call using it was found, so it may be unused.` : use.referenceOnly ? `Deterministic: instruction-like literal ${name} is referenced at ${use.path}:${use.line} through ${use.via}, but no prompt key (system, instructions, content) was found at the call.` : sameSite ? `Deterministic: string literal written under the ${use.key} key at ${candidate.path}:${definition.line}.` : `Deterministic: string literal ${name} passed to a model call as ${use.key} at ${use.path}:${use.line}.`,
14456
14772
  evidence,
14457
14773
  body: definition.text
14458
14774
  };
@@ -14484,6 +14800,14 @@ function mergePromotedDuplicate(existing, next) {
14484
14800
  existing.body = next.body;
14485
14801
  }
14486
14802
  function promoteHarnessCandidates(report, rootDir) {
14803
+ jsSources.clear();
14804
+ try {
14805
+ return promoteAll(report, rootDir);
14806
+ } finally {
14807
+ jsSources.clear();
14808
+ }
14809
+ }
14810
+ function promoteAll(report, rootDir) {
14487
14811
  const fileCache = new Map;
14488
14812
  const byId = new Map;
14489
14813
  const files = {
@@ -14500,7 +14824,9 @@ function promoteHarnessCandidates(report, rootDir) {
14500
14824
  artifact = promoteToolCandidate(candidate, rootDir, confidence2, fileCache);
14501
14825
  break;
14502
14826
  case "prompt_file":
14503
- if (candidate.signal === "prompt_module.name_hint" && (TEST_PATH2.test(candidate.path) || !buildsPrompts(candidate.path, readFileLines(rootDir, candidate.path, fileCache))))
14827
+ if (candidate.signal === "prompt_module.name_hint" && (isTestInput(candidate.path) || !buildsPrompts(candidate.path, readFileLines(rootDir, candidate.path, fileCache))))
14828
+ break;
14829
+ if (isTestInput(candidate.path))
14504
14830
  break;
14505
14831
  artifact = promotePromptFileCandidate(candidate, confidence2);
14506
14832
  break;
@@ -14528,245 +14854,6 @@ function promoteHarnessCandidates(report, rootDir) {
14528
14854
  return [...byId.values()];
14529
14855
  }
14530
14856
 
14531
- // src/harness-wrangler-bindings.ts
14532
- import { lstatSync as lstatSync7, readdirSync as readdirSync4, readFileSync as readFileSync12 } from "node:fs";
14533
- import { join as join9, relative as relative6 } from "node:path";
14534
- var WRANGLER_FILE = /^wrangler\.jsonc?$/;
14535
- var SKIPPED_DIRS2 = new Set(["node_modules", ".git", ".wrangler", "dist", "build", ".next", ".turbo", "vendor"]);
14536
- var MAX_DEPTH = 4;
14537
- var AGENT_CLASS = /Agent(?:V\d+)?$/;
14538
- function stripJsonc2(text) {
14539
- let out = "";
14540
- let inString = false;
14541
- for (let i = 0;i < text.length; i += 1) {
14542
- const ch = text[i];
14543
- if (inString) {
14544
- out += ch;
14545
- if (ch === "\\") {
14546
- out += text[i + 1] ?? "";
14547
- i += 1;
14548
- } else if (ch === '"') {
14549
- inString = false;
14550
- }
14551
- continue;
14552
- }
14553
- if (ch === '"') {
14554
- inString = true;
14555
- out += ch;
14556
- } else if (ch === "/" && text[i + 1] === "/") {
14557
- while (i < text.length && text[i] !== `
14558
- `)
14559
- i += 1;
14560
- out += `
14561
- `;
14562
- } else if (ch === "/" && text[i + 1] === "*") {
14563
- i += 2;
14564
- while (i < text.length && !(text[i] === "*" && text[i + 1] === "/")) {
14565
- if (text[i] === `
14566
- `)
14567
- out += `
14568
- `;
14569
- i += 1;
14570
- }
14571
- i += 1;
14572
- } else {
14573
- out += ch;
14574
- }
14575
- }
14576
- return out.replace(/,(\s*[}\]])/g, "$1");
14577
- }
14578
- function findWranglerFiles(rootDir) {
14579
- const found = [];
14580
- const walk = (dir, depth) => {
14581
- let entries;
14582
- try {
14583
- entries = readdirSync4(dir);
14584
- } catch {
14585
- return;
14586
- }
14587
- for (const name of entries) {
14588
- const abs = join9(dir, name);
14589
- let stat;
14590
- try {
14591
- stat = lstatSync7(abs);
14592
- } catch {
14593
- continue;
14594
- }
14595
- if (stat.isDirectory()) {
14596
- if (depth < MAX_DEPTH && !SKIPPED_DIRS2.has(name) && !name.startsWith("."))
14597
- walk(abs, depth + 1);
14598
- } else if (stat.isFile() && WRANGLER_FILE.test(name)) {
14599
- found.push(abs);
14600
- }
14601
- }
14602
- };
14603
- walk(rootDir, 0);
14604
- return found.sort();
14605
- }
14606
- function lineOf(text, className) {
14607
- const index = text.search(new RegExp(`"class_name"\\s*:\\s*"${className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`));
14608
- return index < 0 ? undefined : text.slice(0, index).split(`
14609
- `).length;
14610
- }
14611
- function workerDir(path) {
14612
- const slash = path.lastIndexOf("/");
14613
- return slash < 0 ? "" : path.slice(0, slash);
14614
- }
14615
- function detectBoundRuntimeClasses(rootDir) {
14616
- const byClass = new Map;
14617
- for (const abs of findWranglerFiles(rootDir)) {
14618
- let text;
14619
- let config2;
14620
- try {
14621
- text = readFileSync12(abs, "utf8");
14622
- config2 = JSON.parse(stripJsonc2(text));
14623
- } catch {
14624
- continue;
14625
- }
14626
- if (!config2 || typeof config2 !== "object")
14627
- continue;
14628
- const path = relative6(rootDir, abs).split("\\").join("/");
14629
- const root = config2;
14630
- const sections2 = [root, ...Object.values(root.env ?? {})];
14631
- for (const section of sections2) {
14632
- if (!section || typeof section !== "object")
14633
- continue;
14634
- const s = section;
14635
- const durable = s.durable_objects?.bindings;
14636
- const entries = [
14637
- ...Array.isArray(durable) ? durable.map((b) => ["durable_object", b]) : [],
14638
- ...Array.isArray(s.workflows) ? s.workflows.map((w) => ["workflow", w]) : []
14639
- ];
14640
- for (const [kind, raw] of entries) {
14641
- if (!raw || typeof raw !== "object")
14642
- continue;
14643
- const entry = raw;
14644
- const className = typeof entry.class_name === "string" ? entry.class_name : "";
14645
- const scriptName = typeof entry.script_name === "string" && entry.script_name ? entry.script_name : undefined;
14646
- const key = `${className}|${scriptName ? "external" : `config:${path}`}`;
14647
- if (!className || byClass.has(key))
14648
- continue;
14649
- const binding = typeof (kind === "workflow" ? entry.binding : entry.name) === "string" ? String(kind === "workflow" ? entry.binding : entry.name) : className;
14650
- byClass.set(key, {
14651
- className,
14652
- kind,
14653
- binding,
14654
- ...scriptName ? { scriptName } : {},
14655
- path,
14656
- line: lineOf(text, className)
14657
- });
14658
- }
14659
- }
14660
- }
14661
- return [...byClass.values()];
14662
- }
14663
- function norm(value) {
14664
- return typeof value === "string" ? value.toLowerCase().replace(/[^a-z0-9]/g, "") : "";
14665
- }
14666
- function itemPaths(item) {
14667
- const paths = [];
14668
- for (const value of [item.root, item.sourcePath]) {
14669
- if (typeof value === "string" && value && value !== ".")
14670
- paths.push(value.replace(/^\.\//, ""));
14671
- }
14672
- for (const entry of Array.isArray(item.evidence) ? item.evidence : []) {
14673
- const path = entry && typeof entry === "object" ? entry.path : undefined;
14674
- if (typeof path === "string" && path)
14675
- paths.push(path.replace(/^\.\//, ""));
14676
- }
14677
- return paths;
14678
- }
14679
- function withinWorker(path, dir, otherDirs) {
14680
- const inside = (d) => d === "" || path === d || path.startsWith(`${d}/`);
14681
- return inside(dir) && !otherDirs.some((other) => other.length > dir.length && inside(other));
14682
- }
14683
- function graphNamesClass(graph, bound, all) {
14684
- const target = norm(bound.className);
14685
- const named = (name) => {
14686
- if (typeof name !== "string")
14687
- return false;
14688
- const bare = name.replace(/\s*\([^)]*\)\s*$/, "");
14689
- return norm(bare) === target || bare.split(/[^A-Za-z0-9_]+/).some((word) => norm(word) === target);
14690
- };
14691
- const sameName = bound.scriptName ? [bound] : all.filter((other) => other.className === bound.className && !other.scriptName);
14692
- const dir = workerDir(bound.path);
14693
- const otherDirs = sameName.map((other) => workerDir(other.path)).filter((other) => other !== dir);
14694
- const covers = (item) => {
14695
- if (!named(item.name))
14696
- return false;
14697
- if (sameName.length < 2)
14698
- return true;
14699
- return itemPaths(item).some((path) => withinWorker(path, dir, otherDirs));
14700
- };
14701
- return graph.runtimeAgents.some(covers) || graph.artifacts.some(covers);
14702
- }
14703
- function bindingReason(bound) {
14704
- const what = bound.kind === "workflow" ? "Workflow" : "Durable Object";
14705
- const where = bound.scriptName ? ` served by the external Worker "${bound.scriptName}"` : "";
14706
- return `${what} binding ${bound.binding} -> class ${bound.className}${where}`;
14707
- }
14708
- function uniqueId(base, taken) {
14709
- let id = base;
14710
- for (let n = 2;taken.has(id); n += 1)
14711
- id = `${base}-${n}`;
14712
- taken.add(id);
14713
- return id;
14714
- }
14715
- function mergeBoundRuntimeClasses(graph, rootDir) {
14716
- if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
14717
- return { added: 0 };
14718
- let bound;
14719
- try {
14720
- bound = detectBoundRuntimeClasses(rootDir);
14721
- } catch {
14722
- return { added: 0 };
14723
- }
14724
- const taken = new Set([
14725
- ...graph.runtimeAgents.map((agent) => agent.id),
14726
- ...graph.artifacts.map((artifact) => artifact.id)
14727
- ]);
14728
- let added = 0;
14729
- for (const entry of bound) {
14730
- if (graphNamesClass(graph, entry, bound))
14731
- continue;
14732
- const evidence = [{ path: entry.path, ...entry.line ? { line: entry.line } : {}, reason: bindingReason(entry) }];
14733
- const slug = entry.className.replace(/[^A-Za-z0-9]+/g, "-").toLowerCase();
14734
- if (entry.kind === "durable_object" && AGENT_CLASS.test(entry.className) && !entry.scriptName) {
14735
- const agent = {
14736
- id: uniqueId(`agent.bound.${slug}`, taken),
14737
- name: entry.className,
14738
- kind: "runtime_agent",
14739
- purpose: "Agent class bound as a Durable Object.",
14740
- root: ".",
14741
- entrypointIds: [],
14742
- channelAdapterIds: [],
14743
- artifactIds: [],
14744
- identityNamespaceIds: [],
14745
- deploymentIds: [],
14746
- frameworkIds: [],
14747
- modelProviderIds: [],
14748
- confidence: 0.6,
14749
- evidence
14750
- };
14751
- graph.runtimeAgents.push(agent);
14752
- } else {
14753
- const artifact = {
14754
- id: uniqueId(`entrypoint.bound.${slug}`, taken),
14755
- type: "entrypoint",
14756
- name: entry.className,
14757
- scope: "shared",
14758
- sourcePath: entry.path,
14759
- usedByAgentIds: [],
14760
- confidence: 0.6,
14761
- evidence
14762
- };
14763
- graph.artifacts.push(artifact);
14764
- }
14765
- added += 1;
14766
- }
14767
- return { added };
14768
- }
14769
-
14770
14857
  // src/harness-sync-limits.ts
14771
14858
  var MAX_HARNESS_SYNC_GRAPH_BYTES = 2000000;
14772
14859
  function assertHarnessGraphSyncSize(graph) {
@@ -14785,8 +14872,8 @@ function assertHarnessGraphSyncSize(graph) {
14785
14872
  }
14786
14873
  // src/harness.ts
14787
14874
  var MODA_DIR = ".moda";
14788
- var HARNESS_PATH = join10(MODA_DIR, "harness.json");
14789
- var HARNESS_SUMMARY_PATH = join10(MODA_DIR, "HARNESS.md");
14875
+ var HARNESS_PATH = join9(MODA_DIR, "harness.json");
14876
+ var HARNESS_SUMMARY_PATH = join9(MODA_DIR, "HARNESS.md");
14790
14877
  var SCHEMA_VERSION = "harness.v0.1";
14791
14878
  var REPORT_JSON_BEGIN = "MODA_HARNESS_REPORT_JSON_BEGIN";
14792
14879
  var REPORT_JSON_END = "MODA_HARNESS_REPORT_JSON_END";
@@ -14952,7 +15039,7 @@ async function runHarnessCommand(context) {
14952
15039
  report: {
14953
15040
  reportId: report.reportId,
14954
15041
  reportHash,
14955
- path: normalizePath2(relative7(rootDir, reportPath)) || ".moda/harness-report.json"
15042
+ path: normalizePath2(relative6(rootDir, reportPath)) || ".moda/harness-report.json"
14956
15043
  },
14957
15044
  validation,
14958
15045
  approval: {
@@ -15098,7 +15185,7 @@ async function runHarnessCommand(context) {
15098
15185
  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.");
15099
15186
  }
15100
15187
  if (context.flags["github-actions"] === "true") {
15101
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-rayyxh1w.js");
15188
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-yev2yrkr.js");
15102
15189
  const result = await runGithubActionsAnalyze(rootDir, {
15103
15190
  writeReport: (report2) => {
15104
15191
  const normalized = normalizeHarnessReport(report2);
@@ -15220,7 +15307,7 @@ async function runHarnessCommand(context) {
15220
15307
  report: {
15221
15308
  reportId: approval.report.reportId,
15222
15309
  reportHash: hashHarnessReport(approval.report),
15223
- path: normalizePath2(relative7(rootDir, reportPath)) || ".moda/harness-report.json"
15310
+ path: normalizePath2(relative6(rootDir, reportPath)) || ".moda/harness-report.json"
15224
15311
  },
15225
15312
  validation: approval.validation,
15226
15313
  approval: approval.approval
@@ -15243,6 +15330,7 @@ async function runHarnessCommand(context) {
15243
15330
  throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
15244
15331
  }
15245
15332
  const artifacts = deterministicArtifacts(rootDir, promote === "all" ? undefined : promote);
15333
+ tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
15246
15334
  const promoted = { concern: promote, artifacts };
15247
15335
  const promoteWritten = [];
15248
15336
  if (promoteOut && !context.dryRun) {
@@ -15310,7 +15398,7 @@ async function runHarnessCommand(context) {
15310
15398
  return { exitCode: 0 };
15311
15399
  }
15312
15400
  case "status": {
15313
- const manifestPath = join10(rootDir, HARNESS_PATH);
15401
+ const manifestPath = join9(rootDir, HARNESS_PATH);
15314
15402
  const graph = existsSync8(manifestPath) ? readHarnessGraph(manifestPath) : scanHarness({
15315
15403
  rootDir,
15316
15404
  tenantId: tenant?.tenantId,
@@ -15451,10 +15539,10 @@ function emitWrittenArtifacts(context, written, description) {
15451
15539
  }
15452
15540
  }
15453
15541
  async function runPromptConcernAnalysis(context, rootDir, scanPlan, tenant) {
15454
- const manifest = join10(rootDir, ".moda/prompts.yml");
15542
+ const manifest = join9(rootDir, ".moda/prompts.yml");
15455
15543
  let existing = [];
15456
15544
  if (existsSync8(manifest)) {
15457
- const document = $parseDocument(readFileSync13(manifest, "utf8"));
15545
+ const document = $parseDocument(readFileSync12(manifest, "utf8"));
15458
15546
  if (document.errors.length)
15459
15547
  throw new CliInputError("Invalid prompt manifest.", document.errors[0].message);
15460
15548
  existing = document.toJS({ maxAliasCount: 20 })?.sources ?? [];
@@ -15708,7 +15796,7 @@ function readExternalAnalystReport(rootDir, result, adapter, concern) {
15708
15796
  result.stderr
15709
15797
  ].join(`
15710
15798
  `));
15711
- debugHint = `Raw analyst output saved to ${join10(MODA_DIR, "analyst-debug.log")} for debugging.`;
15799
+ debugHint = `Raw analyst output saved to ${join9(MODA_DIR, "analyst-debug.log")} for debugging.`;
15712
15800
  } catch {}
15713
15801
  throw new CliInputError(`Harness analyst ${adapter} did not return a harness report.`, [
15714
15802
  `Expected ${HARNESS_REPORT_PATH} or final JSON between ${REPORT_JSON_BEGIN} and ${REPORT_JSON_END}.`,
@@ -15819,6 +15907,7 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
15819
15907
  mergeDeterministicArtifacts(normalized.graph, rootDir, { concern: options.concern });
15820
15908
  if (!options.concern || options.concern === "topology")
15821
15909
  mergeBoundRuntimeClasses(normalized.graph, rootDir);
15910
+ tagComponentStatus(normalized.graph, rootDir);
15822
15911
  hydratePromptAndToolBodies(normalized.graph, rootDir);
15823
15912
  const unverified = new Set;
15824
15913
  for (const artifact of normalized.graph.artifacts) {
@@ -16115,7 +16204,7 @@ function repairCitationLines(report, rootDir) {
16115
16204
  continue;
16116
16205
  let text;
16117
16206
  try {
16118
- text = readFileSync13(candidatePath, "utf8");
16207
+ text = readFileSync12(candidatePath, "utf8");
16119
16208
  } catch {
16120
16209
  continue;
16121
16210
  }
@@ -16721,14 +16810,14 @@ function createPromptAnalystIsolation(adapter, rootDir) {
16721
16810
  const serverPath = bundledServer ? bundled : source;
16722
16811
  const command = bundledServer ? process.execPath : resolveBunRuntime();
16723
16812
  const serverArgs = [serverPath, "--root", rootDir];
16724
- const tempPath = mkdtempSync2(join10(tmpdir2(), "moda-prompt-analyst-"));
16813
+ const tempPath = mkdtempSync2(join9(tmpdir2(), "moda-prompt-analyst-"));
16725
16814
  const cleanup = () => {
16726
16815
  try {
16727
16816
  rmSync4(tempPath, { recursive: true, force: true });
16728
16817
  } catch {}
16729
16818
  };
16730
16819
  if (adapter === "claude") {
16731
- const configPath = join10(tempPath, "claude-mcp.json");
16820
+ const configPath = join9(tempPath, "claude-mcp.json");
16732
16821
  writeFileSync5(configPath, JSON.stringify({ mcpServers: { "moda-prompt-source": { command, args: serverArgs } } }));
16733
16822
  return { configPath, cleanup };
16734
16823
  }
@@ -16939,8 +17028,10 @@ function renderExternalHarnessAnalystPrompt(options) {
16939
17028
  "",
16940
17029
  '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).',
16941
17030
  `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.`,
17031
+ "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.",
16942
17032
  '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.',
16943
17033
  "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.",
17034
+ "The harness includes every real harness component, used or not: a prompt, tool, or model config that is defined but never called is still part of the harness (lower its confidence and say so in confidenceReason). A false positive is only something that is not a harness component: SQL, React or UI props and display copy, URL or path templates, test fixtures, and general utilities. Refute only those; never refute a real component because it is unused.",
16944
17035
  '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."',
16945
17036
  "Each graph item with evidence must use evidence: [{ path, reason }], not citationIds/citations.",
16946
17037
  ...spec ? spec.contractLines : [
@@ -17079,7 +17170,7 @@ function renderAnalystCandidateLines(report, concern) {
17079
17170
  const lines = [
17080
17171
  "",
17081
17172
  concern ? `Deterministic candidate inventory for the ${concern} concern (${candidates.length} candidates, scanned in ${report.stats.durationMs}ms):` : `Deterministic candidate inventory (${candidates.length} candidates across ${report.stats.filesWithCandidates} files, scanned in ${report.stats.durationMs}ms):`,
17082
- concern ? 'Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file, drop false positives (list refuted ones in unknowns: an unknown whose id starts with "refuted_", with one evidence entry {path, line, reason} per refuted candidate, using the path:line shown for that candidate and starting the reason with its [detector]), and hunt for in-concern items the patterns cannot see. Do not cite this list as evidence; cite the files.' : 'Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file and drop false positives. Verified deterministic candidates are also auto-merged into the graph after your run, so prioritize (1) agents, topology, and relationships, (2) verifying or refuting these candidates (list refuted ones in unknowns: an unknown whose id starts with "refuted_", with one evidence entry {path, line, reason} per refuted candidate, using the path:line shown for that candidate and starting the reason with its [detector]; refuted candidates are never auto-merged), and (3) artifacts the patterns cannot see (runtime agents, prompts assembled at runtime, cross-file wiring) — rather than re-listing every candidate as an artifact. Do not cite this list as evidence; cite the files.'
17173
+ concern ? 'Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file, drop false positives — things that are not harness components (SQL, UI props or display copy, URL templates, test fixtures, utilities), never a real component merely because it is unused (list refuted ones in unknowns: an unknown whose id starts with "refuted_", with one evidence entry {path, line, reason} per refuted candidate, using the path:line shown for that candidate and starting the reason with its [detector]), and hunt for in-concern items the patterns cannot see. Do not cite this list as evidence; cite the files.' : 'Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file and drop false positives — things that are not harness components (SQL, UI props or display copy, URL templates, test fixtures, utilities), never a real component merely because it is unused. Verified deterministic candidates are also auto-merged into the graph after your run, so prioritize (1) agents, topology, and relationships, (2) verifying or refuting these candidates (list refuted ones in unknowns: an unknown whose id starts with "refuted_", with one evidence entry {path, line, reason} per refuted candidate, using the path:line shown for that candidate and starting the reason with its [detector]; refuted candidates are never auto-merged), and (3) artifacts the patterns cannot see (runtime agents, prompts assembled at runtime, cross-file wiring) — rather than re-listing every candidate as an artifact. Do not cite this list as evidence; cite the files.'
17083
17174
  ];
17084
17175
  if (concern === "evals") {
17085
17176
  lines.push("Note: evals, guardrails, and memory/retrieval stores have no deterministic detector — only model_config candidates are seeded. Discover the rest by investigation.");
@@ -17144,10 +17235,10 @@ function readDirectoryPreflightPaths(rootDir) {
17144
17235
  const stack = ["."];
17145
17236
  while (stack.length > 0 && paths.length < 2000) {
17146
17237
  const current = stack.pop() ?? ".";
17147
- const absolute = current === "." ? rootDir : join10(rootDir, current);
17238
+ const absolute = current === "." ? rootDir : join9(rootDir, current);
17148
17239
  let entries;
17149
17240
  try {
17150
- entries = readdirSync5(absolute);
17241
+ entries = readdirSync4(absolute);
17151
17242
  } catch {
17152
17243
  continue;
17153
17244
  }
@@ -17155,10 +17246,10 @@ function readDirectoryPreflightPaths(rootDir) {
17155
17246
  const child = current === "." ? entry : `${current}/${entry}`;
17156
17247
  if (shouldSkipPreflightPath(child))
17157
17248
  continue;
17158
- const childAbsolute = join10(rootDir, child);
17249
+ const childAbsolute = join9(rootDir, child);
17159
17250
  let stat;
17160
17251
  try {
17161
- stat = lstatSync8(childAbsolute);
17252
+ stat = lstatSync7(childAbsolute);
17162
17253
  } catch {
17163
17254
  continue;
17164
17255
  }
@@ -17220,7 +17311,7 @@ function findOnPath(command) {
17220
17311
  if (command.includes("/") && existsSync8(command))
17221
17312
  return command;
17222
17313
  for (const dir of (process.env.PATH ?? "").split(delimiter).filter(Boolean)) {
17223
- const candidate = join10(dir, command);
17314
+ const candidate = join9(dir, command);
17224
17315
  if (existsSync8(candidate))
17225
17316
  return candidate;
17226
17317
  }
@@ -17274,6 +17365,7 @@ function scanHarness(options = {}) {
17274
17365
  linkFrameworksAndProviders(graph);
17275
17366
  finalizeGraph(graph);
17276
17367
  hydratePromptAndToolBodies(graph, rootDir);
17368
+ tagComponentStatus(graph, rootDir);
17277
17369
  enrichScanCaptureMetadata(graph);
17278
17370
  return graph;
17279
17371
  }
@@ -17298,10 +17390,10 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
17298
17390
  let inventoryFileCount = 0;
17299
17391
  let inventoryTextBytes = 0;
17300
17392
  function walk(current) {
17301
- const path = normalizePath2(relative7(rootDir, current)) || ".";
17393
+ const path = normalizePath2(relative6(rootDir, current)) || ".";
17302
17394
  let stat;
17303
17395
  try {
17304
- stat = lstatSync8(current);
17396
+ stat = lstatSync7(current);
17305
17397
  } catch {
17306
17398
  return;
17307
17399
  }
@@ -17312,8 +17404,8 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
17312
17404
  if (stat.isDirectory()) {
17313
17405
  if (path !== "." && (isSkippedDir(path) || isSkippedPathPrefix(path)))
17314
17406
  return;
17315
- for (const entry of readdirSync5(current).sort())
17316
- walk(join10(current, entry));
17407
+ for (const entry of readdirSync4(current).sort())
17408
+ walk(join9(current, entry));
17317
17409
  return;
17318
17410
  }
17319
17411
  if (!stat.isFile())
@@ -17336,7 +17428,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
17336
17428
  let text = "";
17337
17429
  if (isTextFile(path)) {
17338
17430
  try {
17339
- text = readFileSync13(current, "utf8");
17431
+ text = readFileSync12(current, "utf8");
17340
17432
  inventoryTextBytes += Buffer.byteLength(text, "utf8");
17341
17433
  } catch {
17342
17434
  return;
@@ -17355,7 +17447,7 @@ function buildSourceSnapshot(rootDir) {
17355
17447
  const inputs = collectSnapshotInputs(root, maxFiles, maxTextBytes);
17356
17448
  const repo = detectRepo(root, inputs.map((input) => ({
17357
17449
  path: input.path,
17358
- absPath: join10(root, input.path),
17450
+ absPath: join9(root, input.path),
17359
17451
  rootDir: root,
17360
17452
  text: input.text
17361
17453
  })));
@@ -17369,7 +17461,7 @@ function buildSourceSnapshot(rootDir) {
17369
17461
  }
17370
17462
  function buildCommandScanPlan(context, rootDir) {
17371
17463
  const explicitPath = context.flags.path !== undefined;
17372
- const rel2 = normalizePath2(relative7(context.cwd, rootDir)) || ".";
17464
+ const rel2 = normalizePath2(relative6(context.cwd, rootDir)) || ".";
17373
17465
  const scope = explicitPath && rel2 !== "." ? "narrow" : "broad";
17374
17466
  const machineReadable = context.outputMode !== "human";
17375
17467
  const approvalRequired = context.positional === "analyze" && scope === "broad" && !context.yes;
@@ -17454,7 +17546,7 @@ function writeHumanBlock(context, message) {
17454
17546
  function buildHarnessReadPlan(rootDir, pathWasExplicit) {
17455
17547
  return {
17456
17548
  scope: pathWasExplicit ? "narrow" : "broad",
17457
- rootPaths: [normalizePath2(relative7(rootDir, rootDir)) || "."],
17549
+ rootPaths: [normalizePath2(relative6(rootDir, rootDir)) || "."],
17458
17550
  willRead: [
17459
17551
  "package manifests",
17460
17552
  "source files under the selected path",
@@ -17572,7 +17664,7 @@ async function syncHarnessWithRemote(context, body) {
17572
17664
  }, profileOptions);
17573
17665
  }
17574
17666
  function writeHarnessSyncState(rootDir, state) {
17575
- const path = join10(rootDir, SYNC_STATE_PATH);
17667
+ const path = join9(rootDir, SYNC_STATE_PATH);
17576
17668
  mkdirSync5(dirname7(path), { recursive: true });
17577
17669
  writeFileSync5(path, `${JSON.stringify(state, null, 2)}
17578
17670
  `);
@@ -17586,7 +17678,7 @@ function selectedRuntimeAgentId(flags) {
17586
17678
  return;
17587
17679
  }
17588
17680
  function loadOrScanHarness(rootDir, tenant, context) {
17589
- const manifestPath = join10(rootDir, HARNESS_PATH);
17681
+ const manifestPath = join9(rootDir, HARNESS_PATH);
17590
17682
  if (existsSync8(manifestPath))
17591
17683
  return readHarnessGraph(manifestPath);
17592
17684
  if (context) {
@@ -17643,7 +17735,7 @@ var FRESHER_REPORT_MAX_DIRS = 4000;
17643
17735
  function findFresherHarnessReports(rootDir) {
17644
17736
  let rootMtimeMs = 0;
17645
17737
  try {
17646
- rootMtimeMs = lstatSync8(join10(rootDir, HARNESS_REPORT_PATH)).mtimeMs;
17738
+ rootMtimeMs = lstatSync7(join9(rootDir, HARNESS_REPORT_PATH)).mtimeMs;
17647
17739
  } catch {
17648
17740
  rootMtimeMs = 0;
17649
17741
  }
@@ -17655,19 +17747,19 @@ function findFresherHarnessReports(rootDir) {
17655
17747
  visited += 1;
17656
17748
  let entries;
17657
17749
  try {
17658
- entries = readdirSync5(dir, { withFileTypes: true });
17750
+ entries = readdirSync4(dir, { withFileTypes: true });
17659
17751
  } catch {
17660
17752
  return;
17661
17753
  }
17662
17754
  for (const entry of entries) {
17663
17755
  if (!entry.isDirectory() || entry.name.startsWith(".") || SKIPPED_DIRS.has(entry.name))
17664
17756
  continue;
17665
- const child = join10(dir, entry.name);
17757
+ const child = join9(dir, entry.name);
17666
17758
  try {
17667
- const candidate = lstatSync8(join10(child, HARNESS_REPORT_PATH));
17759
+ const candidate = lstatSync7(join9(child, HARNESS_REPORT_PATH));
17668
17760
  if (candidate.isFile() && candidate.mtimeMs > rootMtimeMs) {
17669
17761
  fresher.push({
17670
- path: normalizePath2(relative7(rootDir, join10(child, HARNESS_REPORT_PATH))),
17762
+ path: normalizePath2(relative6(rootDir, join9(child, HARNESS_REPORT_PATH))),
17671
17763
  mtimeMs: candidate.mtimeMs
17672
17764
  });
17673
17765
  }
@@ -17679,7 +17771,7 @@ function findFresherHarnessReports(rootDir) {
17679
17771
  return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
17680
17772
  }
17681
17773
  function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
17682
- const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath2(relative7(rootDir, resolve10(rootDir, explicitReport))) : undefined;
17774
+ const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath2(relative6(rootDir, resolve10(rootDir, explicitReport))) : undefined;
17683
17775
  if (explicitReportPath && explicitReportPath !== normalizePath2(HARNESS_REPORT_PATH))
17684
17776
  return;
17685
17777
  let fresher;
@@ -17692,16 +17784,16 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
17692
17784
  return;
17693
17785
  const newest = fresher[0];
17694
17786
  const subdir = normalizePath2(dirname7(dirname7(newest.path)));
17695
- const rootState = existsSync8(join10(rootDir, HARNESS_REPORT_PATH)) ? `older ${HARNESS_REPORT_PATH}` : `no ${HARNESS_REPORT_PATH}`;
17787
+ const rootState = existsSync8(join9(rootDir, HARNESS_REPORT_PATH)) ? `older ${HARNESS_REPORT_PATH}` : `no ${HARNESS_REPORT_PATH}`;
17696
17788
  writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
17697
17789
  }
17698
17790
  function readHarnessGraph(manifestPath) {
17699
- return JSON.parse(readFileSync13(manifestPath, "utf8"));
17791
+ return JSON.parse(readFileSync12(manifestPath, "utf8"));
17700
17792
  }
17701
17793
  function writeHarnessArtifacts(graph, rootDir, options = {}) {
17702
- const modaDir = join10(rootDir, MODA_DIR);
17794
+ const modaDir = join9(rootDir, MODA_DIR);
17703
17795
  mkdirSync5(modaDir, { recursive: true });
17704
- const manifestPath = join10(rootDir, HARNESS_PATH);
17796
+ const manifestPath = join9(rootDir, HARNESS_PATH);
17705
17797
  writeFileSync5(manifestPath, `${JSON.stringify(graph, null, 2)}
17706
17798
  `);
17707
17799
  const written = [HARNESS_PATH];
@@ -17711,7 +17803,7 @@ function writeHarnessArtifacts(graph, rootDir, options = {}) {
17711
17803
  return written;
17712
17804
  }
17713
17805
  function writeHarnessSummary(graph, rootDir) {
17714
- const summaryPath = join10(rootDir, HARNESS_SUMMARY_PATH);
17806
+ const summaryPath = join9(rootDir, HARNESS_SUMMARY_PATH);
17715
17807
  mkdirSync5(dirname7(summaryPath), { recursive: true });
17716
17808
  writeFileSync5(summaryPath, renderHarnessMarkdown(graph));
17717
17809
  return HARNESS_SUMMARY_PATH;
@@ -17886,10 +17978,10 @@ function inventoryFiles(rootDir, skipped, options = {}) {
17886
17978
  const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
17887
17979
  let textBytes = 0;
17888
17980
  function walk(current) {
17889
- const rel2 = normalizePath2(relative7(rootReal, current)) || ".";
17981
+ const rel2 = normalizePath2(relative6(rootReal, current)) || ".";
17890
17982
  let stat;
17891
17983
  try {
17892
- stat = lstatSync8(current);
17984
+ stat = lstatSync7(current);
17893
17985
  } catch {
17894
17986
  recordSkipped(skipped, { path: rel2, reason: "stat failed" });
17895
17987
  return;
@@ -17903,8 +17995,8 @@ function inventoryFiles(rootDir, skipped, options = {}) {
17903
17995
  recordSkipped(skipped, { path: rel2, reason: "ignored directory" });
17904
17996
  return;
17905
17997
  }
17906
- for (const entry of readdirSync5(current).sort()) {
17907
- walk(join10(current, entry));
17998
+ for (const entry of readdirSync4(current).sort()) {
17999
+ walk(join9(current, entry));
17908
18000
  }
17909
18001
  return;
17910
18002
  }
@@ -17935,7 +18027,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
17935
18027
  recordSkipped(skipped, { path: rel2, reason: "scan text budget exceeded" });
17936
18028
  } else {
17937
18029
  try {
17938
- item.text = readFileSync13(current, "utf8");
18030
+ item.text = readFileSync12(current, "utf8");
17939
18031
  textBytes += Buffer.byteLength(item.text, "utf8");
17940
18032
  } catch {
17941
18033
  recordSkipped(skipped, { path: rel2, reason: "text read failed" });
@@ -18242,7 +18334,7 @@ function maybeAddPromptArtifact(graph, file) {
18242
18334
  if (!isPrompt)
18243
18335
  return;
18244
18336
  const id = stableId("prompt", file.path);
18245
- const text = file.text ?? readFileSync13(file.absPath, "utf8");
18337
+ const text = file.text ?? readFileSync12(file.absPath, "utf8");
18246
18338
  upsertArtifact(graph, {
18247
18339
  id,
18248
18340
  type: "prompt",
@@ -18820,10 +18912,10 @@ function computeDeterministicFloor(rootDir) {
18820
18912
  }
18821
18913
  function detectProviderPackagesInManifests(rootDir) {
18822
18914
  const present = new Set;
18823
- const packageJsonPath = join10(rootDir, "package.json");
18915
+ const packageJsonPath = join9(rootDir, "package.json");
18824
18916
  if (existsSync8(packageJsonPath)) {
18825
18917
  try {
18826
- const deps = packageDependencyNames(readFileSync13(packageJsonPath, "utf8"));
18918
+ const deps = packageDependencyNames(readFileSync12(packageJsonPath, "utf8"));
18827
18919
  for (const provider of PROVIDER_CATALOG) {
18828
18920
  for (const name of provider.packageNames) {
18829
18921
  if (deps.has(name))
@@ -18832,10 +18924,10 @@ function detectProviderPackagesInManifests(rootDir) {
18832
18924
  }
18833
18925
  } catch {}
18834
18926
  }
18835
- const pyprojectPath = join10(rootDir, "pyproject.toml");
18927
+ const pyprojectPath = join9(rootDir, "pyproject.toml");
18836
18928
  if (existsSync8(pyprojectPath)) {
18837
18929
  try {
18838
- const deps = pyprojectDependencyNames(readFileSync13(pyprojectPath, "utf8"));
18930
+ const deps = pyprojectDependencyNames(readFileSync12(pyprojectPath, "utf8"));
18839
18931
  for (const provider of PROVIDER_CATALOG) {
18840
18932
  for (const name of provider.packageNames) {
18841
18933
  if (deps.has(name.toLowerCase()))
@@ -19237,12 +19329,12 @@ function contentHashForAnnotatedSource(sourcePath, annotation) {
19237
19329
  function readSmallTextFileForHash(absPath, rootDir) {
19238
19330
  if (!existsSync8(absPath))
19239
19331
  return;
19240
- const rel2 = normalizePath2(relative7(rootDir, absPath));
19332
+ const rel2 = normalizePath2(relative6(rootDir, absPath));
19241
19333
  if (isSecretishPath(rel2))
19242
19334
  return;
19243
19335
  let stat;
19244
19336
  try {
19245
- stat = lstatSync8(absPath);
19337
+ stat = lstatSync7(absPath);
19246
19338
  } catch {
19247
19339
  return;
19248
19340
  }
@@ -19252,7 +19344,7 @@ function readSmallTextFileForHash(absPath, rootDir) {
19252
19344
  if (!isTextFile(rel2))
19253
19345
  return;
19254
19346
  try {
19255
- return readFileSync13(absPath, "utf8");
19347
+ return readFileSync12(absPath, "utf8");
19256
19348
  } catch {
19257
19349
  return;
19258
19350
  }