@moda-ai/cli 1.55.50 → 1.55.52

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.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  buildDoctorReport
3
- } from "./cli-73x2yznb.js";
3
+ } from "./cli-zgmxsmbt.js";
4
4
  import"./cli-rdh9jjr2.js";
5
- import"./cli-79pzgqtj.js";
5
+ import"./cli-arze1hgb.js";
6
6
  import"./cli-mm48br00.js";
7
7
  import {
8
8
  readHarnessSyncState
@@ -95,7 +95,7 @@ async function buildAgentContext(context) {
95
95
  const graph = readHarnessGraphIfPresent(context.cwd);
96
96
  const reportState = readHarnessReportState(context.cwd);
97
97
  const syncState = readHarnessSyncState(context.cwd);
98
- const harness = graph ? await import("./harness-fx091nmr.js") : undefined;
98
+ const harness = graph ? await import("./harness-t2xjak6g.js") : undefined;
99
99
  const topFindings = doctor.checks.filter((check) => check.status === "fail" || check.status === "warning").slice(0, 12).map(checkToFinding);
100
100
  const evidenceRefs = [
101
101
  ...doctor.checks.map(checkToEvidenceRef),
@@ -5768,7 +5768,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
5768
5768
  const analyzedDefinitions = new Map;
5769
5769
  if (flags["no-analyze"] !== "true") {
5770
5770
  options.onProgress?.("Analyzing prompt sources before sync.");
5771
- const { analyzeHarnessPrompts } = await import("./harness-fx091nmr.js");
5771
+ const { analyzeHarnessPrompts } = await import("./harness-t2xjak6g.js");
5772
5772
  const result = await analyzeHarnessPrompts({
5773
5773
  rootDir: process.cwd(),
5774
5774
  existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
@@ -5796,7 +5796,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
5796
5796
  const mergedSources = mergePromptSources(manifest.sources, extraSources);
5797
5797
  const manifestUpdate = stableJson(mergedSources) === stableJson(mergePromptSources(manifest.sources, [])) ? undefined : $stringify({ version: 2, prompt_paths: manifest.promptPaths, sources: mergedSources });
5798
5798
  const prompts = await discoverPrompts(extraSources);
5799
- const { checkPromptAttribution } = await import("./prompt-attribution-avvkfq8c.js");
5799
+ const { checkPromptAttribution } = await import("./prompt-attribution-ey193cg9.js");
5800
5800
  const attribution = checkPromptAttribution(process.cwd(), prompts.map((prompt) => prompt.key));
5801
5801
  const brokenAttribution = attribution.references.filter((reference) => reference.status === "missing");
5802
5802
  if (brokenAttribution.length) {
@@ -6102,7 +6102,7 @@ async function migratePromptManifest(options = {}) {
6102
6102
  let addedSources = [];
6103
6103
  let pendingSources = [];
6104
6104
  if (options.discover) {
6105
- const { analyzeHarnessPrompts } = await import("./harness-fx091nmr.js");
6105
+ const { analyzeHarnessPrompts } = await import("./harness-t2xjak6g.js");
6106
6106
  const result = await analyzeHarnessPrompts({
6107
6107
  rootDir: root,
6108
6108
  existing: manifest.sources,
@@ -12333,6 +12333,7 @@ var NON_PROMPT_DOC_BASENAMES = new Set([
12333
12333
  "requirements.txt"
12334
12334
  ]);
12335
12335
  var PROMPT_NAME_HINT = /(prompt|system[-_]?message|instruction|persona|sop)/i;
12336
+ var PROMPTS_DIR = /(^|\/)(?:system[-_]?)?prompts?(\/|$)/i;
12336
12337
  var AGENTIC_DIR_HINT = /(^|\/)(agents?|prompts?|llm|ai|assistants?|chains?|crew|graph)s?(\/|$)/i;
12337
12338
  var INSTRUCTION_MARKERS = [
12338
12339
  /\byou are\b/i,
@@ -12532,6 +12533,9 @@ function detectPromptFile(file, out) {
12532
12533
  if (nameHint) {
12533
12534
  confidence2 = "high";
12534
12535
  signal = "prompt_file.name_hint";
12536
+ } else if (PROMPTS_DIR.test(dir)) {
12537
+ confidence2 = "high";
12538
+ signal = "prompt_file.prompts_dir";
12535
12539
  } else if (dirHint && score >= 3) {
12536
12540
  confidence2 = "medium";
12537
12541
  signal = "prompt_file.agent_dir_instruction_text";
@@ -13554,7 +13558,7 @@ function applyPromptDiscovery(graph, discovery) {
13554
13558
 
13555
13559
  // src/harness-candidate-promotion.ts
13556
13560
  import { readFileSync as readFileSync11 } from "node:fs";
13557
- import { resolve as resolve9 } from "node:path";
13561
+ import { extname as extname7, posix, resolve as resolve9 } from "node:path";
13558
13562
  var PROMOTED_CONFIDENCE = {
13559
13563
  high: 0.85,
13560
13564
  medium: 0.6
@@ -13566,7 +13570,6 @@ var JS_ASSIGNMENT_NAME = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=/;
13566
13570
  var JS_PROPERTY_NAME = /^\s*(?:public\s+|readonly\s+)?([A-Za-z_$][\w$]*)\s*:\s*(?:new\s+)?(?:[\w.$]*\.)?(?:tool|functionTool|createTool|dynamicTool|DynamicStructuredTool)\s*\(/;
13567
13571
  var JS_TRAILING_ASSIGNMENT_NAME = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:new\s+)?$/;
13568
13572
  var REGISTRY_CALL_NAME = /\b(?:register_tool|registerTool|add_tool)\s*\(\s*["']?([A-Za-z_$][\w$]*)/;
13569
- var PROMPT_ASSIGNMENT_NAME = /^\s*(?:export\s+)?(?:(?:const|let|var)\s+)?([A-Za-z_$][\w$]*)\s*[:=]/;
13570
13573
  var MODEL_STRING = /["'`]([\w.:/-]*(?:gpt-|o[134](?:-mini)?\b|claude|gemini|llama|mistral|mixtral|deepseek|qwen|grok|sonnet|opus|haiku|command-r|glm|gemma)[\w.:/-]*)["'`]/i;
13571
13574
  function candidateEvidence(candidate) {
13572
13575
  return [{
@@ -13641,17 +13644,786 @@ function promotePromptFileCandidate(candidate, confidence2) {
13641
13644
  evidence: candidateEvidence(candidate)
13642
13645
  };
13643
13646
  }
13644
- function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache) {
13647
+ var MODEL_INPUT_KEYS = [
13648
+ "system",
13649
+ "systemPrompt",
13650
+ "system_prompt",
13651
+ "systemMessage",
13652
+ "system_message",
13653
+ "systemInstruction",
13654
+ "system_instruction",
13655
+ "instructions",
13656
+ "prompt",
13657
+ "userPrompt",
13658
+ "user_prompt",
13659
+ "backstory",
13660
+ "content",
13661
+ "input",
13662
+ "template",
13663
+ "text"
13664
+ ];
13665
+ var DIRECT_PROMPT_KEYS = new Set([
13666
+ "system",
13667
+ "systemPrompt",
13668
+ "system_prompt",
13669
+ "systemMessage",
13670
+ "system_message",
13671
+ "systemInstruction",
13672
+ "system_instruction",
13673
+ "instructions",
13674
+ "prompt",
13675
+ "userPrompt",
13676
+ "user_prompt",
13677
+ "backstory",
13678
+ "system_template",
13679
+ "instance_template"
13680
+ ]);
13681
+ var GENERIC_IDENTIFIERS = new Set([
13682
+ "prompt",
13683
+ "template",
13684
+ "system",
13685
+ "instructions",
13686
+ "content",
13687
+ "text",
13688
+ "message",
13689
+ "input",
13690
+ "body",
13691
+ "value"
13692
+ ]);
13693
+ var CONFIG_EXTENSIONS = new Set([".json", ".yaml", ".yml"]);
13694
+ var PROMPT_NAMED_IDENTIFIER = /prompt|system|instruction/i;
13695
+ var SECOND_PERSON_OPENING = /^\s*(?:\[[A-Z]+:\s*|<\w+>\s*)*(?:you|your)\b/i;
13696
+ var MIN_UNNAMED_REFERENCED_PROMPT_CHARS = 200;
13697
+ var REFERENCED_PROMPT_CONFIDENCE = 0.7;
13698
+ var MIN_RESOLVED_PROMPT_CHARS = 20;
13699
+ var MIN_CONFIG_PROMPT_CHARS = 40;
13700
+ var MAX_BUILDER_LOOKBEHIND_LINES = 40;
13701
+ var DEFINITION_HEAD = /^\s*(?:export\s+)?(?:(?:const|let|var|readonly|static|public|private)\s+)*["']?([A-Za-z_$][\w$]*)["']?\s*(?:(?::\s*[\w$.<>[\]|, ]+?)?\s*(=)(?![=>])|(:))\s*(.*)$/;
13702
+ var VALUE_WRAPPERS = /^(?:\(|\[|(?:textwrap\.)?dedent\(|inspect\.cleandoc\(|outdent|stripIndent)\s*/;
13703
+ var STRING_OPENER = /^(?:[fFrRbBuU]{1,2})?("""|\'\'\'|"|'|`)/;
13704
+ var BUILDER_HEAD = /^\s*(?:export\s+)?(?:async\s+)?(?:function\s+([A-Za-z_$][\w$]*)\s*\(|def\s+([A-Za-z_]\w*)\s*\(|(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>)/;
13705
+ var CODE_LIKE_CONTENT = [
13706
+ /^\s*(?:SELECT|WITH|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b[\s\S]*\b(?:FROM|INTO|SET|TABLE|AS)\b/i,
13707
+ /^\s*[a-z][\w+.-]*:\/\/\S*$/i,
13708
+ /^\s*(?:<![Dd][Oo][Cc][Tt][Yy][Pp][Ee]\b|<(?:html|head|body|div|span|p|a|ul|ol|li|table|tr|td|th|button|img|svg|path|section|header|footer|nav|main|form|input|label|select|option|textarea|h[1-6]|br|hr|meta|link|script|style|template|iframe|video)[\s/>]|<[A-Z][\w.]*[\s/>]|<[A-Za-z][\w.-]*\s+[\w:-]+=)/
13709
+ ];
13710
+ var INLINE_PROMPT_KEY = new RegExp(`(?<![\\w$.])["']?(${[...new Set([...MODEL_INPUT_KEYS, ...DIRECT_PROMPT_KEYS])].join("|")})["']?\\s*(?::|=(?![=>]))\\s*`, "g");
13711
+ function escapeRegExp(value) {
13712
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13713
+ }
13714
+ function readStringLiteral(text, start) {
13715
+ const opener = text.startsWith('"""', start) || text.startsWith("'''", start) ? text.slice(start, start + 3) : text[start];
13716
+ let i = start + opener.length;
13717
+ while (i < text.length) {
13718
+ const char = text[i];
13719
+ if (char === "\\") {
13720
+ i += 2;
13721
+ continue;
13722
+ }
13723
+ if (opener.length === 1 && opener !== "`" && char === `
13724
+ `)
13725
+ return;
13726
+ if (opener === "`" && char === "$" && text[i + 1] === "{") {
13727
+ let depth = 1;
13728
+ i += 2;
13729
+ while (i < text.length && depth > 0) {
13730
+ if (text[i] === "`" || text[i] === '"' || text[i] === "'") {
13731
+ const nested = readStringLiteral(text, i);
13732
+ if (nested) {
13733
+ i = nested.end;
13734
+ continue;
13735
+ }
13736
+ if (text[i] === "`")
13737
+ return;
13738
+ i += 1;
13739
+ continue;
13740
+ }
13741
+ const regexEnd = text[i] === "/" ? regexLiteralEnd(text, i) : undefined;
13742
+ if (regexEnd !== undefined) {
13743
+ i = regexEnd;
13744
+ continue;
13745
+ }
13746
+ if (text.startsWith("//", i)) {
13747
+ const newline = text.indexOf(`
13748
+ `, i);
13749
+ i = newline < 0 ? text.length : newline;
13750
+ continue;
13751
+ }
13752
+ if (text.startsWith("/*", i)) {
13753
+ const close = text.indexOf("*/", i + 2);
13754
+ if (close < 0)
13755
+ return;
13756
+ i = close + 2;
13757
+ continue;
13758
+ }
13759
+ if (text[i] === "{")
13760
+ depth += 1;
13761
+ else if (text[i] === "}")
13762
+ depth -= 1;
13763
+ i += 1;
13764
+ }
13765
+ continue;
13766
+ }
13767
+ if (text.startsWith(opener, i))
13768
+ return { value: text.slice(start + opener.length, i), end: i + opener.length };
13769
+ i += 1;
13770
+ }
13771
+ return;
13772
+ }
13773
+ var EXPRESSION_KEYWORDS = new Set([
13774
+ "return",
13775
+ "typeof",
13776
+ "instanceof",
13777
+ "in",
13778
+ "of",
13779
+ "new",
13780
+ "delete",
13781
+ "void",
13782
+ "throw",
13783
+ "case",
13784
+ "do",
13785
+ "else",
13786
+ "yield",
13787
+ "await"
13788
+ ]);
13789
+ function endsWithOperand(text, end) {
13790
+ let i = end;
13791
+ while (i > 0 && /\s/.test(text[i - 1]))
13792
+ i -= 1;
13793
+ if (i === 0)
13794
+ return false;
13795
+ const char = text[i - 1];
13796
+ if (char === ")" || char === "]" || char === '"' || char === "'" || char === "`")
13797
+ return true;
13798
+ if (/[\w$]/.test(char)) {
13799
+ let wordStart = i;
13800
+ while (wordStart > 0 && /[\w$]/.test(text[wordStart - 1]))
13801
+ wordStart -= 1;
13802
+ const word = text.slice(wordStart, i);
13803
+ if (/^\d/.test(word))
13804
+ return true;
13805
+ let before = wordStart;
13806
+ while (before > 0 && /\s/.test(text[before - 1]))
13807
+ before -= 1;
13808
+ const isProperty = text[before - 1] === "." && text[before - 2] !== ".";
13809
+ return isProperty || !EXPRESSION_KEYWORDS.has(word);
13810
+ }
13811
+ if ((char === "+" || char === "-") && text[i - 2] === char)
13812
+ return endsWithOperand(text, i - 2);
13813
+ if (char === "!" && i >= 2 && /[\w$)\]]/.test(text[i - 2]))
13814
+ return endsWithOperand(text, i - 1);
13815
+ return false;
13816
+ }
13817
+ function regexLiteralEnd(text, start) {
13818
+ if (text[start + 1] === "/" || text[start + 1] === "*")
13819
+ return;
13820
+ if (endsWithOperand(text, start))
13821
+ return;
13822
+ let inClass = false;
13823
+ for (let i = start + 1;i < text.length; i += 1) {
13824
+ const char = text[i];
13825
+ if (char === `
13826
+ `)
13827
+ return;
13828
+ if (char === "\\") {
13829
+ i += 1;
13830
+ continue;
13831
+ }
13832
+ if (char === "[")
13833
+ inClass = true;
13834
+ else if (char === "]")
13835
+ inClass = false;
13836
+ else if (char === "/" && !inClass) {
13837
+ let end = i + 1;
13838
+ while (/[a-z]/i.test(text[end] ?? ""))
13839
+ end += 1;
13840
+ return end;
13841
+ }
13842
+ }
13843
+ return;
13844
+ }
13845
+ function readStringValue(text, offset) {
13846
+ let i = offset;
13847
+ const parts = [];
13848
+ let concatenated = false;
13849
+ let listed = false;
13850
+ for (;; ) {
13851
+ const opener = STRING_OPENER.exec(text.slice(i, i + 5));
13852
+ if (!opener)
13853
+ break;
13854
+ const literal = readStringLiteral(text, i + opener[0].length - opener[1].length);
13855
+ if (!literal)
13856
+ return;
13857
+ parts.push(literal.value);
13858
+ i = literal.end;
13859
+ const separator = /^[\s+,]*/.exec(text.slice(i))[0];
13860
+ if (!STRING_OPENER.test(text.slice(i + separator.length, i + separator.length + 5))) {
13861
+ if (separator.includes("+"))
13862
+ return;
13863
+ break;
13864
+ }
13865
+ if (separator.includes("+") && separator.includes(","))
13866
+ return;
13867
+ if (separator.includes(","))
13868
+ listed = true;
13869
+ else
13870
+ concatenated = true;
13871
+ i += separator.length;
13872
+ }
13873
+ if (parts.length === 0 || concatenated && listed)
13874
+ return;
13875
+ if (!listed)
13876
+ return parts.join("");
13877
+ const join9 = /^[\s,]*\]\s*\.join\(\s*(["'`])((?:\\.|(?!\1).)*)\1\s*\)/.exec(text.slice(i));
13878
+ const joinSeparator = join9 ? join9[2].replace(/\\n/g, `
13879
+ `).replace(/\\t/g, "\t") : `
13880
+ `;
13881
+ return parts.join(joinSeparator);
13882
+ }
13883
+ function textOffsetOfLine(lines, index) {
13884
+ let offset = 0;
13885
+ for (let i = 0;i < index; i += 1)
13886
+ offset += lines[i].length + 1;
13887
+ return offset;
13888
+ }
13889
+ function stringStart(rest) {
13890
+ let consumed = 0;
13891
+ let remaining = rest;
13892
+ for (let guard = 0;guard < 3; guard += 1) {
13893
+ const wrapper = VALUE_WRAPPERS.exec(remaining);
13894
+ if (!wrapper)
13895
+ break;
13896
+ consumed += wrapper[0].length;
13897
+ remaining = remaining.slice(wrapper[0].length);
13898
+ }
13899
+ return STRING_OPENER.test(remaining) ? consumed : -1;
13900
+ }
13901
+ function resolvePromptLiteralDefinition(lines, startLine) {
13902
+ const text = lines.join(`
13903
+ `);
13904
+ for (const index of [startLine - 1, startLine - 2]) {
13905
+ const line2 = lines[index];
13906
+ if (line2 === undefined)
13907
+ continue;
13908
+ const head = DEFINITION_HEAD.exec(line2);
13909
+ if (head) {
13910
+ const [, name, , colon, rest] = head;
13911
+ let valueOffset = -1;
13912
+ const inline = stringStart(rest);
13913
+ if (inline >= 0) {
13914
+ valueOffset = textOffsetOfLine(lines, index) + line2.length - rest.length + inline;
13915
+ } else if (/^(?:\(|\[|(?:textwrap\.)?dedent\(|)\s*$/.test(rest) && lines[index + 1] !== undefined) {
13916
+ const next = lines[index + 1];
13917
+ const nextStart = stringStart(next.trimStart());
13918
+ if (nextStart >= 0)
13919
+ valueOffset = textOffsetOfLine(lines, index + 1) + (next.length - next.trimStart().length) + nextStart;
13920
+ }
13921
+ if (valueOffset < 0 && colon) {
13922
+ const block = readYamlBlockScalar(lines, index, rest);
13923
+ if (block !== undefined)
13924
+ return { key: name, text: block, line: index + 1 };
13925
+ }
13926
+ if (valueOffset < 0)
13927
+ continue;
13928
+ let offset2 = valueOffset;
13929
+ while (!STRING_OPENER.test(text.slice(offset2, offset2 + 5)))
13930
+ offset2 += 1;
13931
+ const value2 = readStringValue(text, offset2);
13932
+ if (value2 === undefined)
13933
+ continue;
13934
+ return colon ? { key: name, text: value2, line: index + 1 } : { identifier: name, text: value2, line: index + 1 };
13935
+ }
13936
+ if (index !== startLine - 1)
13937
+ continue;
13938
+ const returned = /^\s*return\s+(.*)$/.exec(line2);
13939
+ if (!returned)
13940
+ continue;
13941
+ const start = stringStart(returned[1]);
13942
+ if (start < 0)
13943
+ continue;
13944
+ let offset = textOffsetOfLine(lines, index) + line2.length - returned[1].length + start;
13945
+ while (!STRING_OPENER.test(text.slice(offset, offset + 5)))
13946
+ offset += 1;
13947
+ const value = readStringValue(text, offset);
13948
+ if (value === undefined)
13949
+ continue;
13950
+ for (let i = index - 1;i >= Math.max(0, index - MAX_BUILDER_LOOKBEHIND_LINES); i -= 1) {
13951
+ const builder = BUILDER_HEAD.exec(lines[i]);
13952
+ if (builder)
13953
+ return { identifier: builder[1] ?? builder[2] ?? builder[3], text: value, line: index + 1 };
13954
+ }
13955
+ }
13956
+ const line = lines[startLine - 1];
13957
+ if (line === undefined)
13958
+ return;
13959
+ if (/^\s*(?:\/\/|\*(?!\/)|#)/.test(line))
13960
+ return;
13961
+ for (const match of line.matchAll(INLINE_PROMPT_KEY)) {
13962
+ if (endsInComment(line.slice(0, match.index)))
13963
+ break;
13964
+ const after = match.index + match[0].length;
13965
+ const start = stringStart(line.slice(after));
13966
+ if (start < 0)
13967
+ continue;
13968
+ let offset = textOffsetOfLine(lines, startLine - 1) + after + start;
13969
+ while (!STRING_OPENER.test(text.slice(offset, offset + 5)))
13970
+ offset += 1;
13971
+ const value = readStringValue(text, offset);
13972
+ if (value !== undefined)
13973
+ return { key: match[1], text: value, line: startLine };
13974
+ }
13975
+ return;
13976
+ }
13977
+ function endsInComment(prefix) {
13978
+ let quote;
13979
+ let inBlock = false;
13980
+ for (let i = 0;i < prefix.length; i += 1) {
13981
+ const char = prefix[i];
13982
+ if (inBlock) {
13983
+ if (prefix.startsWith("*/", i)) {
13984
+ inBlock = false;
13985
+ i += 1;
13986
+ }
13987
+ continue;
13988
+ }
13989
+ if (quote) {
13990
+ if (char === "\\")
13991
+ i += 1;
13992
+ else if (char === quote)
13993
+ quote = undefined;
13994
+ continue;
13995
+ }
13996
+ if (char === '"' || char === "'" || char === "`") {
13997
+ quote = char;
13998
+ continue;
13999
+ }
14000
+ const regexEnd = char === "/" ? regexLiteralEnd(prefix, i) : undefined;
14001
+ if (regexEnd !== undefined) {
14002
+ i = regexEnd - 1;
14003
+ continue;
14004
+ }
14005
+ if (prefix.startsWith("//", i))
14006
+ return true;
14007
+ else if (prefix.startsWith("/*", i)) {
14008
+ inBlock = true;
14009
+ i += 1;
14010
+ }
14011
+ }
14012
+ return inBlock;
14013
+ }
14014
+ function readYamlBlockScalar(lines, index, rest) {
14015
+ const indicator = /^([|>])([-+]?)\s*(?:#.*)?$/.exec(rest.trim());
14016
+ if (!indicator)
14017
+ return;
14018
+ const [, style, chomping] = indicator;
14019
+ const keyIndent = lines[index].length - lines[index].trimStart().length;
14020
+ const body = [];
14021
+ let blockIndent;
14022
+ for (let i = index + 1;i < lines.length; i += 1) {
14023
+ const line = lines[i];
14024
+ if (!line.trim()) {
14025
+ body.push("");
14026
+ continue;
14027
+ }
14028
+ const indent = line.length - line.trimStart().length;
14029
+ if (indent <= keyIndent)
14030
+ break;
14031
+ blockIndent ??= indent;
14032
+ if (indent < blockIndent)
14033
+ break;
14034
+ body.push(line.slice(blockIndent));
14035
+ }
14036
+ let trailingBlank = 0;
14037
+ while (body.length > 0 && body[body.length - 1] === "") {
14038
+ body.pop();
14039
+ trailingBlank += 1;
14040
+ }
14041
+ if (body.length === 0)
14042
+ return;
14043
+ let text;
14044
+ if (style === "|") {
14045
+ text = body.join(`
14046
+ `);
14047
+ } else {
14048
+ if (body.some((line) => /^\s/.test(line)))
14049
+ return;
14050
+ text = "";
14051
+ let blanks = 0;
14052
+ for (const [i, line] of body.entries()) {
14053
+ if (line === "") {
14054
+ blanks += 1;
14055
+ continue;
14056
+ }
14057
+ text += i === 0 || text === "" ? `
14058
+ `.repeat(blanks) + line : blanks > 0 ? `
14059
+ `.repeat(blanks) + line : ` ${line}`;
14060
+ blanks = 0;
14061
+ }
14062
+ }
14063
+ if (chomping === "-")
14064
+ return text;
14065
+ return chomping === "+" ? text + `
14066
+ `.repeat(trailingBlank + 1) : `${text}
14067
+ `;
14068
+ }
14069
+ function isCodeLikeContent(text) {
14070
+ return CODE_LIKE_CONTENT.some((pattern) => pattern.test(text));
14071
+ }
14072
+ var SOURCE_EXTENSION = /\.(?:[cm]?[jt]sx?|py)$/;
14073
+ function moduleStems(definitionPath) {
14074
+ const stem = definitionPath.replace(/\.[^./]+$/, "");
14075
+ const dir = /\/(?:index|__init__)$/.test(stem) ? stem.replace(/\/[^/]+$/, "") : undefined;
14076
+ return dir ? [stem, dir] : [stem];
14077
+ }
14078
+ function specifierResolvesTo(spec, importerPath, definitionPath, python) {
14079
+ const stems = moduleStems(definitionPath);
14080
+ const importerDir = posix.dirname(importerPath);
14081
+ let target;
14082
+ let exact = true;
14083
+ if (python) {
14084
+ const dots = /^\.*/.exec(spec)[0].length;
14085
+ const rest = spec.slice(dots).split(".").filter(Boolean).join("/");
14086
+ if (dots > 0) {
14087
+ let base = importerDir;
14088
+ for (let i = 1;i < dots; i += 1)
14089
+ base = posix.dirname(base);
14090
+ target = posix.normalize(posix.join(base, rest));
14091
+ } else if (!rest.includes("/")) {
14092
+ return stems.some((stem) => stem === rest || stem === posix.join(importerDir, rest));
14093
+ } else {
14094
+ target = rest;
14095
+ exact = false;
14096
+ }
14097
+ } else if (spec.startsWith(".")) {
14098
+ target = posix.normalize(posix.join(importerDir, spec)).replace(SOURCE_EXTENSION, "");
14099
+ } else {
14100
+ const segments = spec.replace(SOURCE_EXTENSION, "").split("/");
14101
+ if (segments.length > 0 && /^[@~#$]/.test(segments[0]))
14102
+ segments.shift();
14103
+ if (segments.length < 2)
14104
+ return false;
14105
+ target = segments.join("/");
14106
+ exact = false;
14107
+ }
14108
+ return stems.some((stem) => stem === target || !exact && stem.endsWith(`/${target}`));
14109
+ }
14110
+ function localNameIn(specifiers, identifier) {
14111
+ for (const raw of specifiers.replace(/#[^\n]*|\/\/[^\n]*/g, "").replace(/[()]/g, "").split(",")) {
14112
+ const match = /^\s*(?:type\s+)?([A-Za-z_$][\w$]*)(?:\s*(?:\bas\b|:)\s*([A-Za-z_$][\w$]*))?\s*$/.exec(raw);
14113
+ if (match?.[1] === identifier)
14114
+ return match[2] ?? identifier;
14115
+ }
14116
+ return;
14117
+ }
14118
+ function importedLocalName(importerPath, lines, identifier, definitionPath, exportsDefault = false) {
14119
+ const text = lines.join(`
14120
+ `);
14121
+ const python = extname7(importerPath) === ".py";
14122
+ if (python) {
14123
+ for (const match of text.matchAll(/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm)) {
14124
+ if (!specifierResolvesTo(match[1], importerPath, definitionPath, true))
14125
+ continue;
14126
+ const local = localNameIn(match[2].replace(/\\\n/g, " "), identifier);
14127
+ if (local)
14128
+ return local;
14129
+ }
14130
+ for (const match of text.matchAll(/^[ \t]*import\s+([.\w]+)(?:\s+as\s+(\w+))?/gm)) {
14131
+ if (specifierResolvesTo(match[1], importerPath, definitionPath, true))
14132
+ return identifier;
14133
+ }
14134
+ return;
14135
+ }
14136
+ const statements = [
14137
+ /\bimport\s+(?:type\s+)?(?:[A-Za-z_$][\w$]*\s*,\s*)?\{([^}]*)\}\s*from\s*["']([^"']+)["']/g,
14138
+ /\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(?:await\s+)?(?:require|import)\(\s*["']([^"']+)["']\s*\)/g
14139
+ ];
14140
+ for (const pattern of statements) {
14141
+ for (const match of text.matchAll(pattern)) {
14142
+ if (!specifierResolvesTo(match[2], importerPath, definitionPath, false))
14143
+ continue;
14144
+ const local = localNameIn(match[1], identifier);
14145
+ if (local)
14146
+ return local;
14147
+ }
14148
+ }
14149
+ if (exportsDefault) {
14150
+ for (const match of text.matchAll(/\bimport\s+(?:type\s+)?([A-Za-z_$][\w$]*)\s*(?:,\s*(?:\{[^}]*\}|\*\s*as\s+[A-Za-z_$][\w$]*)\s*)?from\s*["']([^"']+)["']/g)) {
14151
+ if (specifierResolvesTo(match[2], importerPath, definitionPath, false))
14152
+ return match[1];
14153
+ }
14154
+ }
14155
+ for (const match of text.matchAll(/\bimport\s*\*\s*as\s+[A-Za-z_$][\w$]*\s+from\s*["']([^"']+)["']/g)) {
14156
+ if (specifierResolvesTo(match[1], importerPath, definitionPath, false))
14157
+ return identifier;
14158
+ }
14159
+ return;
14160
+ }
14161
+ function importStatementLines(lines) {
14162
+ const text = lines.join(`
14163
+ `);
14164
+ const covered = new Set;
14165
+ const statement = /^[ \t]*(?:import\b[^;]*?\bfrom\s*["'][^"'\n]+["']|export\s*(?:type\s*)?\{[^}]*\}\s*from\s*["'][^"'\n]+["']|from\s+[.\w]+\s+import\s*(?:\([^)]*\)|[^\n]*))/gm;
14166
+ for (const match of text.matchAll(statement)) {
14167
+ const first2 = text.slice(0, match.index).split(`
14168
+ `).length - 1;
14169
+ const last = first2 + match[0].split(`
14170
+ `).length - 1;
14171
+ for (let i = first2;i <= last; i += 1)
14172
+ covered.add(i);
14173
+ }
14174
+ return covered;
14175
+ }
14176
+ var MODEL_CALLEE = /model|llm|complet|generat|chat|invoke|infer|prompt|agent|judge|claude|gpt|openai|anthropic|gemini|\.create$/i;
14177
+ function calleeImportedFromModelFile(callee, path, lines, modelFiles) {
14178
+ const base = callee.split(".")[0];
14179
+ const text = lines.join(`
14180
+ `);
14181
+ const python = extname7(path) === ".py";
14182
+ const statements = python ? [/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm] : [
14183
+ /\bimport\s+(?:type\s+)?(?:([A-Za-z_$][\w$]*)\s*,?\s*)?(?:\{([^}]*)\}|\*\s*as\s+([A-Za-z_$][\w$]*))?\s*from\s*["']([^"']+)["']/g,
14184
+ /\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(?:await\s+)?(?:require|import)\(\s*["']([^"']+)["']\s*\)/g
14185
+ ];
14186
+ for (const pattern of statements) {
14187
+ for (const match of text.matchAll(pattern)) {
14188
+ let spec;
14189
+ let names;
14190
+ if (python) {
14191
+ spec = match[1];
14192
+ names = match[2].replace(/[()]/g, "").split(",").map((part) => part.trim().split(/\s+as\s+/).pop() ?? "");
14193
+ } else if (match.length === 5) {
14194
+ spec = match[4];
14195
+ names = [match[1] ?? "", match[3] ?? "", ...(match[2] ?? "").split(",").map((part) => part.trim().split(/\s+as\s+/).pop() ?? "")];
14196
+ } else {
14197
+ spec = match[2];
14198
+ names = match[1].split(",").map((part) => part.trim().split(/\s*:\s*/).pop() ?? "");
14199
+ }
14200
+ if (!names.includes(base))
14201
+ continue;
14202
+ for (const modelPath of modelFiles) {
14203
+ if (specifierResolvesTo(spec, path, modelPath, python))
14204
+ return true;
14205
+ }
14206
+ }
14207
+ }
14208
+ return false;
14209
+ }
14210
+ var INSTRUCTION_KEY = /\b(instruction|instructions|task|brief|goal|message|query|question)["']?\s*[:=]\s*$/;
14211
+ var MODEL_CALL_IN_BODY = /\b[\w$.]*(?:model|llm|complet|generat|chat|claude|gpt|openai|anthropic|gemini)[\w$]*\s*\(|\brole\b\s*["']?\s*[:=]\s*["'](?:system|user|assistant)["']/i;
14212
+ var MAX_HELPER_BODY_LINES = 80;
14213
+ var MAX_CALL_CONTEXT_LINES = 25;
14214
+ var CALL_ROLE_WINDOW_LINES = 8;
14215
+ function localHelperCallsModel(callee, lines) {
14216
+ const ident = escapeRegExp(callee.split(".").pop() ?? callee);
14217
+ const head = new RegExp(`^\\s*(?:export\\s+)?(?:async\\s+)?(?:function\\s+${ident}\\s*[(<]|def\\s+${ident}\\s*\\(|(?:const|let|var)\\s+${ident}\\s*=\\s*(?:async\\s+)?(?:\\(|[A-Za-z_$][\\w$]*\\s*=>)|(?:(?:private|public|protected|static|async)\\s+)*${ident}\\s*\\([^)]*\\)?\\s*[:{])`);
14218
+ const start = lines.findIndex((line) => head.test(line));
14219
+ if (start < 0)
14220
+ return false;
14221
+ return lines.slice(start + 1, start + 1 + MAX_HELPER_BODY_LINES).some((line) => MODEL_CALL_IN_BODY.test(line));
14222
+ }
14223
+ function callCarriesChatMessages(lines, index) {
14224
+ for (let i = Math.max(0, index - CALL_ROLE_WINDOW_LINES);i < Math.min(lines.length, index + CALL_ROLE_WINDOW_LINES + 1); i += 1) {
14225
+ if (/\brole\b\s*["']?\s*[:=]\s*["'](?:system|user|human|assistant)["']/.test(lines[i]))
14226
+ return true;
14227
+ }
14228
+ return false;
14229
+ }
14230
+ function composingPromptName(lines, index, identifier) {
14231
+ for (let i = index;i >= Math.max(0, index - MAX_BUILDER_LOOKBEHIND_LINES); i -= 1) {
14232
+ const builder = BUILDER_HEAD.exec(lines[i]);
14233
+ const assignment = /^\s*(?:export\s+)?(?:(?:const|let|var)\s+)?([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=(?![=>])/.exec(lines[i]);
14234
+ const name = builder ? builder[1] ?? builder[2] ?? builder[3] : assignment?.[1];
14235
+ if (name)
14236
+ return name !== identifier && PROMPT_NAMED_IDENTIFIER.test(name) ? name : undefined;
14237
+ }
14238
+ return;
14239
+ }
14240
+ var OUTPUT_CALLEE = /^(?:console\.\w+|(?:[\w$]+\.)*(?:log|logger|logging)\.\w+|print|log|alert|toast(?:\.\w+)?|(?:[\w$]+\.)*(?:write|writeFile|writeFileSync|appendFile|send|json|setState|set[A-Z]\w*))$/;
14241
+ function enclosingCallee(text, index) {
14242
+ let depth = 0;
14243
+ for (let i = index - 1;i >= 0; i -= 1) {
14244
+ const char = text[i];
14245
+ if (char === ")" || char === "]" || char === "}")
14246
+ depth += 1;
14247
+ else if (char === "[" || char === "{")
14248
+ depth = Math.max(0, depth - 1);
14249
+ else if (char === "(") {
14250
+ if (depth > 0) {
14251
+ depth -= 1;
14252
+ continue;
14253
+ }
14254
+ return /([A-Za-z_$][\w$.]*)\s*$/.exec(text.slice(Math.max(0, i - 200), i))?.[1];
14255
+ }
14256
+ }
14257
+ return;
14258
+ }
14259
+ function findModelInputUse(identifier, definition, files, rootDir, fileCache, options) {
14260
+ const scan = (path, lines, name) => {
14261
+ const ident = escapeRegExp(name);
14262
+ const keyed = new RegExp(`\\b(${MODEL_INPUT_KEYS.join("|")})["']?\\s*[:=]\\s*(?:await\\s+)?(?:(?:this|self)\\.)?(?:[A-Za-z_$][\\w$]*\\.)?${ident}\\b`);
14263
+ const messageCtor = new RegExp(`\\b(SystemMessage|HumanMessage|SystemMessagePromptTemplate\\.from_template|HumanMessagePromptTemplate\\.from_template|PromptTemplate\\.from_template|ChatPromptTemplate\\.from_template)\\s*\\(\\s*(?:content\\s*=\\s*)?${ident}\\b`);
14264
+ const roleTuple = new RegExp(`\\(\\s*["'](system|user|human)["']\\s*,\\s*${ident}\\b`);
14265
+ const interpolated = new RegExp(`\\b(${MODEL_INPUT_KEYS.join("|")})["']?\\s*[:=]\\s*[fF]?[\`"'][^\`"']*(?:\\$\\{|\\{)${ident}\\b`);
14266
+ const shorthand = DIRECT_PROMPT_KEYS.has(name) ? new RegExp(`[{,(]\\s*${ident}\\s*[,})]`) : undefined;
14267
+ const isModelFile = files.model.has(path);
14268
+ for (let i = 0;i < lines.length; i += 1) {
14269
+ if (path === definition.path && i === definition.line - 1)
14270
+ continue;
14271
+ const line = lines[i];
14272
+ if (line.length > 4000 || !line.includes(name))
14273
+ continue;
14274
+ const fixed = messageCtor.exec(line) ?? roleTuple.exec(line);
14275
+ if (fixed)
14276
+ return { path, line: i + 1, key: fixed[1] };
14277
+ const match = keyed.exec(line) ?? interpolated.exec(line);
14278
+ if (match && (isModelFile || DIRECT_PROMPT_KEYS.has(match[1]) || match[1] === "content" && hasNearbyRole(lines, i + 1))) {
14279
+ return { path, line: i + 1, key: match[1] };
14280
+ }
14281
+ if (shorthand?.test(line) && isModelFile)
14282
+ return { path, line: i + 1, key: name };
14283
+ }
14284
+ return;
14285
+ };
14286
+ const firstReference = (path, lines, name) => {
14287
+ const ident = escapeRegExp(name);
14288
+ const reference = new RegExp(`(?<![\\w$])(?:(?:this|self|[A-Za-z_$][\\w$]*)\\.)?${ident}(?![\\w$])`, "g");
14289
+ const jsxAttribute = new RegExp(`[\\w-]+=\\{\\s*${ident}\\s*\\}`);
14290
+ const jsxChild = /\.[jt]sx$/.test(path) ? new RegExp(`(?<!\\$)\\{\\s*${ident}\\s*\\}`) : undefined;
14291
+ const imports = importStatementLines(lines);
14292
+ const isModelFile = files.model.has(path);
14293
+ const declaration = new RegExp(`^\\s*(?:export\\s+)?(?:default\\s+)?(?:async\\s+)?(?:function\\s*\\*?\\s*|def\\s+|(?:const|let|var)\\s+)${ident}\\b`);
14294
+ for (let i = 0;i < lines.length; i += 1) {
14295
+ if (path === definition.path && i === definition.line - 1)
14296
+ continue;
14297
+ const line = lines[i];
14298
+ if (line.length > 4000 || !line.includes(name))
14299
+ continue;
14300
+ if (/^\s*(?:\/\/|#|\*|import\b|export\s*\{|from\s+\S+\s+import\b)/.test(line) || jsxAttribute.test(line) || jsxChild?.test(line))
14301
+ continue;
14302
+ const context = `${lines.slice(Math.max(0, i - MAX_CALL_CONTEXT_LINES), i).join(`
14303
+ `)}
14304
+ `;
14305
+ if (declaration.test(line) || imports.has(i))
14306
+ continue;
14307
+ for (const match of line.matchAll(reference)) {
14308
+ const callee = enclosingCallee(context + line, context.length + match.index);
14309
+ if (callee && OUTPUT_CALLEE.test(callee))
14310
+ continue;
14311
+ const before = (context + line).slice(0, context.length + match.index);
14312
+ const instructionKey = INSTRUCTION_KEY.exec(before)?.[1];
14313
+ const after = line.slice(match.index + match[0].length);
14314
+ const composed = /(?:\$\{\s*|\+\s*|[[,]\s*|^\s*|[^=!<>]=\s*|\breturn\s+|\bawait\s+)$/.test(before) && /^\s*(?:\}|\+|,|\]|;|\(|$)/.test(after);
14315
+ const composedInto = composed ? composingPromptName(lines, i, name) : undefined;
14316
+ const via = isModelFile ? "a file that calls a model" : instructionKey ? `the ${instructionKey} key of an agent call` : callee && MODEL_CALLEE.test(callee) ? `the model-call helper ${callee}` : callee && localHelperCallsModel(callee, lines) ? `the local helper ${callee}, which calls a model` : callee && calleeImportedFromModelFile(callee, path, lines, files.model) ? `${callee}, imported from a module that calls a model` : callee && callCarriesChatMessages(lines, i) ? `a ${callee} call that also carries chat messages` : composedInto && `composition into ${composedInto}`;
14317
+ if (via)
14318
+ return { path, line: i + 1, key: "reference", referenceOnly: true, via };
14319
+ }
14320
+ }
14321
+ return;
14322
+ };
14323
+ const own = readFileLines(rootDir, definition.path, fileCache);
14324
+ const local = own ? scan(definition.path, own, identifier) : undefined;
14325
+ if (local)
14326
+ return local;
14327
+ const importers = [];
14328
+ if (!GENERIC_IDENTIFIERS.has(identifier)) {
14329
+ const ident = escapeRegExp(identifier);
14330
+ const exportsDefault = own?.some((line) => new RegExp(`^\\s*export\\s+default\\s+${ident}\\s*;?\\s*$|\\bexport\\s*\\{[^}]*\\b${ident}\\s+as\\s+default\\b`).test(line)) ?? false;
14331
+ const moduleName = posix.basename(definition.path).replace(/\.[^.]+$/, "");
14332
+ for (const path of files.searchable) {
14333
+ if (path === definition.path)
14334
+ continue;
14335
+ const lines = readFileLines(rootDir, path, fileCache);
14336
+ if (!lines || !lines.some((line) => line.includes(identifier) || exportsDefault && line.includes(moduleName)))
14337
+ continue;
14338
+ const name = importedLocalName(path, lines, identifier, definition.path, exportsDefault);
14339
+ if (!name)
14340
+ continue;
14341
+ const use = scan(path, lines, name);
14342
+ if (use)
14343
+ return use;
14344
+ importers.push({ path, lines, name });
14345
+ }
14346
+ }
14347
+ if (!options.allowReference)
14348
+ return;
14349
+ if (own) {
14350
+ const use = firstReference(definition.path, own, identifier);
14351
+ if (use)
14352
+ return use;
14353
+ }
14354
+ for (const importer of importers) {
14355
+ const use = firstReference(importer.path, importer.lines, importer.name);
14356
+ if (use)
14357
+ return use;
14358
+ }
14359
+ return;
14360
+ }
14361
+ function readsAsInstructions(identifier, text) {
14362
+ const score = instructionScore(text);
14363
+ const secondPerson = SECOND_PERSON_OPENING.test(text);
14364
+ if (PROMPT_NAMED_IDENTIFIER.test(identifier))
14365
+ return score >= 2 || secondPerson;
14366
+ return secondPerson && score >= 2 && text.length >= MIN_UNNAMED_REFERENCED_PROMPT_CHARS;
14367
+ }
14368
+ function hasNearbyRole(lines, line) {
14369
+ for (let i = Math.max(0, line - 4);i < Math.min(lines.length, line + 3); i += 1) {
14370
+ if (/\brole\b\s*["']?\s*[:=]/.test(lines[i]))
14371
+ return true;
14372
+ }
14373
+ return false;
14374
+ }
14375
+ function isDirectModelInput(key, value, path, lines, line, modelFiles) {
14376
+ if (CONFIG_EXTENSIONS.has(extname7(path).toLowerCase())) {
14377
+ return DIRECT_PROMPT_KEYS.has(key) && value.length >= MIN_CONFIG_PROMPT_CHARS;
14378
+ }
14379
+ if (modelFiles.has(path)) {
14380
+ return DIRECT_PROMPT_KEYS.has(key) || key === "content" && hasNearbyRole(lines, line);
14381
+ }
14382
+ return DIRECT_PROMPT_KEYS.has(key) && instructionScore(value) >= 2;
14383
+ }
14384
+ function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache, files) {
13645
14385
  const lines = readFileLines(rootDir, candidate.path, fileCache);
13646
- const assignedName = lines ? PROMPT_ASSIGNMENT_NAME.exec(lines[candidate.startLine - 1] ?? "")?.[1] ?? (candidate.startLine >= 2 ? PROMPT_ASSIGNMENT_NAME.exec(lines[candidate.startLine - 2] ?? "")?.[1] : undefined) : undefined;
14386
+ if (!lines)
14387
+ return;
14388
+ const definition = resolvePromptLiteralDefinition(lines, candidate.startLine);
14389
+ if (!definition)
14390
+ return;
14391
+ const value = definition.text.trim();
14392
+ const literalText = value.replace(/\$\{[^}]*\}|\{[A-Za-z_][\w.]*\}/g, "").trim();
14393
+ if (literalText.length < MIN_RESOLVED_PROMPT_CHARS || isCodeLikeContent(value))
14394
+ return;
14395
+ const key = definition.key ?? (definition.identifier && DIRECT_PROMPT_KEYS.has(definition.identifier) ? definition.identifier : undefined);
14396
+ let use;
14397
+ if (key && isDirectModelInput(key, value, candidate.path, lines, definition.line, files.model)) {
14398
+ use = { path: candidate.path, line: definition.line, key };
14399
+ }
14400
+ if (!use && definition.identifier) {
14401
+ use = findModelInputUse(definition.identifier, { path: candidate.path, line: definition.line }, files, rootDir, fileCache, {
14402
+ allowReference: readsAsInstructions(definition.identifier, value)
14403
+ });
14404
+ }
14405
+ if (!use)
14406
+ return;
14407
+ const name = definition.identifier ?? definition.key;
14408
+ const evidence = [{ path: candidate.path, line: definition.line, reason: `deterministic detector ${candidate.signal}` }];
14409
+ const sameSite = use.path === candidate.path && use.line === definition.line;
14410
+ if (!sameSite) {
14411
+ evidence.push({
14412
+ path: use.path,
14413
+ line: use.line,
14414
+ reason: use.referenceOnly ? "prompt-named literal referenced here (positional or composed model input)" : `passed to a model call as ${use.key}`
14415
+ });
14416
+ }
13647
14417
  return {
13648
- id: stableId("prompt", `${pathStem(candidate.path)}:L${candidate.startLine}`),
14418
+ id: stableId("prompt", `${pathStem(candidate.path)}:L${definition.line}`),
13649
14419
  type: "prompt",
13650
- name: assignedName ? titleFromId(assignedName) : `Inline Prompt (${candidate.path}:${candidate.startLine})`,
14420
+ name: name ? titleFromId(name) : `Inline Prompt (${candidate.path}:${definition.line})`,
13651
14421
  scope: "shared",
13652
14422
  usedByAgentIds: [],
13653
- confidence: confidence2,
13654
- evidence: candidateEvidence(candidate)
14423
+ confidence: use.referenceOnly ? Math.min(confidence2, REFERENCED_PROMPT_CONFIDENCE) : confidence2,
14424
+ 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}.`,
14425
+ evidence,
14426
+ body: definition.text
13655
14427
  };
13656
14428
  }
13657
14429
  function promoteModelConfigCandidate(candidate, rootDir, confidence2, fileCache) {
@@ -13683,6 +14455,10 @@ function mergePromotedDuplicate(existing, next) {
13683
14455
  function promoteHarnessCandidates(report, rootDir) {
13684
14456
  const fileCache = new Map;
13685
14457
  const byId = new Map;
14458
+ const files = {
14459
+ model: new Set(report.candidates.filter((candidate) => candidate.kind === "llm_call_site" || candidate.kind === "framework_construct").map((candidate) => candidate.path)),
14460
+ searchable: new Set(report.files.map((file) => file.path))
14461
+ };
13686
14462
  for (const candidate of report.candidates) {
13687
14463
  const confidence2 = PROMOTED_CONFIDENCE[candidate.confidence];
13688
14464
  if (confidence2 === undefined)
@@ -13693,11 +14469,13 @@ function promoteHarnessCandidates(report, rootDir) {
13693
14469
  artifact = promoteToolCandidate(candidate, rootDir, confidence2, fileCache);
13694
14470
  break;
13695
14471
  case "prompt_file":
14472
+ if (candidate.signal === "prompt_module.name_hint")
14473
+ break;
13696
14474
  artifact = promotePromptFileCandidate(candidate, confidence2);
13697
14475
  break;
13698
14476
  case "prompt_literal":
13699
14477
  if (candidate.confidence === "high") {
13700
- artifact = promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache);
14478
+ artifact = promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache, files);
13701
14479
  }
13702
14480
  break;
13703
14481
  case "model_config":
@@ -13763,6 +14541,7 @@ var HARNESS_FAMILY_FLAGS = [
13763
14541
  "offset",
13764
14542
  "out",
13765
14543
  "path",
14544
+ "promote",
13766
14545
  "remote",
13767
14546
  "report",
13768
14547
  "run",
@@ -14049,7 +14828,7 @@ async function runHarnessCommand(context) {
14049
14828
  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.");
14050
14829
  }
14051
14830
  if (context.flags["github-actions"] === "true") {
14052
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-jfbcsx2s.js");
14831
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-p3g8cjf2.js");
14053
14832
  const result = await runGithubActionsAnalyze(rootDir, {
14054
14833
  writeReport: (report2) => {
14055
14834
  const normalized = normalizeHarnessReport(report2);
@@ -14184,6 +14963,28 @@ async function runHarnessCommand(context) {
14184
14963
  message: "Scan this project for static harness candidates?"
14185
14964
  });
14186
14965
  writeHumanProgress(context, "Harness candidates: static pre-pass (no LLM, no network)...");
14966
+ if (context.flags.promote !== undefined) {
14967
+ const promote = context.flags.promote === "true" ? "all" : context.flags.promote.trim().toLowerCase();
14968
+ if (promote !== "all" && !HARNESS_ANALYZE_CONCERNS.includes(promote)) {
14969
+ throw new CliInputError(`Unknown --promote value "${context.flags.promote}".`, `Use --promote=all or one of: ${HARNESS_ANALYZE_CONCERNS.join(", ")}.`);
14970
+ }
14971
+ const promoteOut = context.flags.out;
14972
+ if (promoteOut === "true") {
14973
+ throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
14974
+ }
14975
+ const artifacts = deterministicArtifacts(rootDir, promote === "all" ? undefined : promote);
14976
+ const promoted = { concern: promote, artifacts };
14977
+ const promoteWritten = [];
14978
+ if (promoteOut && !context.dryRun) {
14979
+ const target = resolve10(context.cwd, promoteOut);
14980
+ mkdirSync5(dirname7(target), { recursive: true });
14981
+ writeFileSync5(target, `${JSON.stringify(promoted, null, 2)}
14982
+ `, "utf8");
14983
+ promoteWritten.push(target);
14984
+ }
14985
+ context.output.writeData({ scanPlan, ...promoted, written: promoteWritten, dryRun: context.dryRun });
14986
+ return { exitCode: 0 };
14987
+ }
14187
14988
  const report = detectHarnessCandidates(rootDir);
14188
14989
  const written = [];
14189
14990
  const outFlag = context.flags.out;
@@ -14656,7 +15457,7 @@ function extractHarnessReportFromText(output, rootDir, concern) {
14656
15457
  }
14657
15458
  function reportJsonCandidates(output) {
14658
15459
  const candidates = [];
14659
- const markerPattern = new RegExp(`${escapeRegExp(REPORT_JSON_BEGIN)}\\s*([\\s\\S]*?)\\s*${escapeRegExp(REPORT_JSON_END)}`, "g");
15460
+ const markerPattern = new RegExp(`${escapeRegExp2(REPORT_JSON_BEGIN)}\\s*([\\s\\S]*?)\\s*${escapeRegExp2(REPORT_JSON_END)}`, "g");
14660
15461
  for (const match of output.matchAll(markerPattern)) {
14661
15462
  if (match[1])
14662
15463
  candidates.push(match[1]);
@@ -14702,6 +15503,17 @@ function applyResolvedPromptSource(artifact, source) {
14702
15503
  artifact.sourcePath = source.sourcePath;
14703
15504
  artifact.contentHash = source.sourceDefinition.sourceHash;
14704
15505
  }
15506
+ function isToolGroupPlaceholder(name) {
15507
+ const trimmed = (name ?? "").trim();
15508
+ if (!trimmed)
15509
+ return false;
15510
+ if (trimmed.includes("*"))
15511
+ return true;
15512
+ return /\s(?:tools|toolkits?|toolsets?)$/i.test(trimmed);
15513
+ }
15514
+ function isDetectedToolDefinitionReason(reason) {
15515
+ return typeof reason === "string" && (reason.startsWith("deterministic detector ") || reason.startsWith("Tool definition detected"));
15516
+ }
14705
15517
  function removeArtifacts(report, ids) {
14706
15518
  const graph = report.graph;
14707
15519
  const keep = (id) => typeof id !== "string" || !ids.has(id);
@@ -14751,6 +15563,33 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
14751
15563
  normalized.graph.unknowns.push({ id: `unresolved_${artifact.id}`, question: error instanceof Error ? error.message : String(error), candidateIds: [artifact.id], evidence: artifact.evidence });
14752
15564
  }
14753
15565
  }
15566
+ for (const artifact of normalized.graph.artifacts) {
15567
+ if (artifact.type !== "tool" || unverified.has(artifact.id) || !isToolGroupPlaceholder(artifact.name))
15568
+ continue;
15569
+ if (artifact.evidence.some((entry) => isDetectedToolDefinitionReason(entry.reason)))
15570
+ continue;
15571
+ unverified.add(artifact.id);
15572
+ normalized.graph.unknowns.push({
15573
+ id: `unresolved_${artifact.id}`,
15574
+ question: `"${artifact.name}" is a dynamic tool source (a group of tools resolved at runtime), not a single tool definition, so its tools are not enumerated in the harness.`,
15575
+ candidateIds: [artifact.id],
15576
+ evidence: artifact.evidence
15577
+ });
15578
+ }
15579
+ for (const artifact of normalized.graph.artifacts) {
15580
+ if (artifact.type !== "model_config" || unverified.has(artifact.id))
15581
+ continue;
15582
+ const paths = artifact.evidence.map((entry) => entry.path).filter((path) => typeof path === "string" && path.length > 0);
15583
+ if (paths.length === 0 || !paths.every((path) => TEST_PATH2.test(path)))
15584
+ continue;
15585
+ unverified.add(artifact.id);
15586
+ normalized.graph.unknowns.push({
15587
+ id: `unresolved_${artifact.id}`,
15588
+ question: `Model ${artifact.name ?? artifact.id} is cited only from test or fixture files, so it is a test input rather than the harness's model configuration.`,
15589
+ candidateIds: [artifact.id],
15590
+ evidence: artifact.evidence
15591
+ });
15592
+ }
14754
15593
  for (const artifact of normalized.graph.artifacts) {
14755
15594
  if (unverified.has(artifact.id) || !requiresArtifactBody(artifact.type))
14756
15595
  continue;
@@ -14834,6 +15673,12 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
14834
15673
  prompts: new Set(["prompt"]),
14835
15674
  evals: new Set(["model_config"])
14836
15675
  };
15676
+ function deterministicArtifacts(rootDir, concern) {
15677
+ const graph = { artifacts: [], unknowns: [] };
15678
+ mergeDeterministicArtifacts(graph, rootDir, { concern });
15679
+ hydratePromptAndToolBodies(graph, rootDir);
15680
+ return graph.artifacts;
15681
+ }
14837
15682
  function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
14838
15683
  if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
14839
15684
  return { added: 0 };
@@ -15064,7 +15909,7 @@ function extractTextFromAgentEvent(event) {
15064
15909
  return textParts.length > 0 ? textParts.join(`
15065
15910
  `) : undefined;
15066
15911
  }
15067
- function escapeRegExp(value) {
15912
+ function escapeRegExp2(value) {
15068
15913
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15069
15914
  }
15070
15915
  var EVENT_CARD_MAX = 100;
@@ -15818,6 +16663,10 @@ function renderExternalHarnessAnalystPrompt(options) {
15818
16663
  "- unknowns: report-level open questions with id, question, and citationIds",
15819
16664
  "",
15820
16665
  '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).',
16666
+ `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.`,
16667
+ '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.',
16668
+ "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.",
16669
+ '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."',
15821
16670
  "Each graph item with evidence must use evidence: [{ path, reason }], not citationIds/citations.",
15822
16671
  ...spec ? spec.contractLines : [
15823
16672
  'Runtime agents must include id, name, kind:"runtime_agent", root, entrypointIds, channelAdapterIds, artifactIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds, confidence, evidence.',
@@ -18221,4 +19070,4 @@ function hashText(text) {
18221
19070
  return createHash5("sha256").update(text).digest("hex");
18222
19071
  }
18223
19072
 
18224
- export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, repairExternalAnalystReport, deriveRelationshipsFromGraph, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };
19073
+ export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };
@@ -4,7 +4,7 @@ import {
4
4
  } from "./cli-rdh9jjr2.js";
5
5
  import {
6
6
  inspectPromptManifest
7
- } from "./cli-79pzgqtj.js";
7
+ } from "./cli-arze1hgb.js";
8
8
  import {
9
9
  readHarnessSyncState,
10
10
  renderDoctorHuman,
@@ -395,7 +395,7 @@ async function harnessCurrentCheck(cwd, manifestPath, manifestExists, tenantId)
395
395
  };
396
396
  }
397
397
  try {
398
- const { scanHarness } = await import("./harness-fx091nmr.js");
398
+ const { scanHarness } = await import("./harness-t2xjak6g.js");
399
399
  const current = scanHarness({
400
400
  rootDir: cwd,
401
401
  scannerVersion: "doctor",
package/dist/cli.js CHANGED
@@ -2145,9 +2145,10 @@ var HARNESS_SUBCOMMAND_HELP = [
2145
2145
  {
2146
2146
  name: "candidates",
2147
2147
  description: "Static pre-pass listing likely agents, prompts, and tools (local; no LLM, no network)",
2148
- usage: "moda harness candidates [--path=<dir>] [--out=<file>] [--dry-run] [--yes]",
2148
+ usage: "moda harness candidates [--path=<dir>] [--out=<file>] [--promote=<concern|all>] [--dry-run] [--yes]",
2149
2149
  flags: [
2150
2150
  HARNESS_PATH_FLAG,
2151
+ { name: "--promote=<concern|all>", description: "Print the deterministic artifacts (tools, prompts, model configs) for one concern (topology, tools, prompts, evals) or all, with bodies, instead of the raw candidates." },
2151
2152
  { name: "--out=<file>", description: "Also write the candidates report to a file." },
2152
2153
  { name: "--dry-run", description: "Do not write --out." },
2153
2154
  { name: "--yes", description: "Approve a broad scan without the prompt." }
@@ -2967,25 +2968,25 @@ function leafManifestFields(leaf, commands) {
2967
2968
  import { fileURLToPath } from "url";
2968
2969
  import { realpathSync } from "fs";
2969
2970
  async function runPromptsCommand(...args) {
2970
- return (await import("./prompts-hcecy2na.js")).runPromptsCommand(...args);
2971
+ return (await import("./prompts-z2v4k4q7.js")).runPromptsCommand(...args);
2971
2972
  }
2972
2973
  async function runSkillsCommand(...args) {
2973
2974
  return (await import("./skills-mwftqzyk.js")).runSkillsCommand(...args);
2974
2975
  }
2975
2976
  async function runHarnessCommand(...args) {
2976
- return (await import("./harness-fx091nmr.js")).runHarnessCommand(...args);
2977
+ return (await import("./harness-t2xjak6g.js")).runHarnessCommand(...args);
2977
2978
  }
2978
2979
  async function runSyncCommand(...args) {
2979
- return (await import("./sync-v0me021f.js")).runSyncCommand(...args);
2980
+ return (await import("./sync-tzvrgzqs.js")).runSyncCommand(...args);
2980
2981
  }
2981
2982
  async function runRegistryCommand(...args) {
2982
2983
  return (await import("./registry-tv8fktxc.js")).runRegistryCommand(...args);
2983
2984
  }
2984
2985
  async function runDoctorCommand(...args) {
2985
- return (await import("./doctor-dz8gfz2h.js")).runDoctorCommand(...args);
2986
+ return (await import("./doctor-66qe8hq9.js")).runDoctorCommand(...args);
2986
2987
  }
2987
2988
  async function runStatusCommand(...args) {
2988
- return (await import("./doctor-dz8gfz2h.js")).runStatusCommand(...args);
2989
+ return (await import("./doctor-66qe8hq9.js")).runStatusCommand(...args);
2989
2990
  }
2990
2991
  async function runAuthCommand(...args) {
2991
2992
  return (await import("./profile-commands-nbaec4y9.js")).runAuthCommand(...args);
@@ -2997,7 +2998,7 @@ async function runProfilesCommand(...args) {
2997
2998
  return (await import("./profile-commands-nbaec4y9.js")).runProfilesCommand(...args);
2998
2999
  }
2999
3000
  async function runAgentCommand(...args) {
3000
- return (await import("./agent-vdqppnq3.js")).runAgentCommand(...args);
3001
+ return (await import("./agent-nxn5df1w.js")).runAgentCommand(...args);
3001
3002
  }
3002
3003
  async function runProductionCommand(...args) {
3003
3004
  return (await import("./production-intelligence-zek0rkzj.js")).runProductionCommand(...args);
@@ -6761,7 +6762,7 @@ var commandRegistry = createCommandRegistry([
6761
6762
  resetApiRequestCountBeforeRun: true,
6762
6763
  telemetry: "result-and-error",
6763
6764
  handler: async (context) => {
6764
- const { runInit } = await import("./index-q2d1fva7.js");
6765
+ const { runInit } = await import("./index-tt5rmqyq.js");
6765
6766
  if (context.outputMode === "agent-stream") {
6766
6767
  context.output.writeEvent({
6767
6768
  event: "started",
@@ -3,9 +3,9 @@ import {
3
3
  promptsDiscoveredCheck,
4
4
  runDoctorCommand,
5
5
  runStatusCommand
6
- } from "./cli-73x2yznb.js";
6
+ } from "./cli-zgmxsmbt.js";
7
7
  import"./cli-rdh9jjr2.js";
8
- import"./cli-79pzgqtj.js";
8
+ import"./cli-arze1hgb.js";
9
9
  import"./cli-mm48br00.js";
10
10
  import"./cli-xq45etg1.js";
11
11
  import"./cli-gtke9wrw.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildSourceSnapshot
3
- } from "./cli-n3bjh1pc.js";
3
+ } from "./cli-xx73daeb.js";
4
4
  import"./cli-97fnztpy.js";
5
5
  import"./cli-xq45etg1.js";
6
6
  import"./cli-gtke9wrw.js";
@@ -13,12 +13,14 @@ import {
13
13
  describeSyncIdentity,
14
14
  describeSyncTenantLabel,
15
15
  detectAvailableCodingAgents,
16
+ deterministicArtifacts,
16
17
  emitWrittenArtifacts,
17
18
  findFresherHarnessReports,
18
19
  graphForSync,
19
20
  inventoryFiles,
20
21
  isDeterministicLocalAnalyst,
21
22
  isRetryableExternalAnalystFailure,
23
+ isToolGroupPlaceholder,
22
24
  mergeDeterministicArtifacts,
23
25
  numericEnv,
24
26
  numericEnvAllowZero,
@@ -41,7 +43,7 @@ import {
41
43
  writeHarnessAnalyzeResult,
42
44
  writeHarnessArtifacts,
43
45
  writeHumanProgress
44
- } from "./cli-n3bjh1pc.js";
46
+ } from "./cli-xx73daeb.js";
45
47
  import"./cli-97fnztpy.js";
46
48
  import"./cli-xq45etg1.js";
47
49
  import"./cli-gtke9wrw.js";
@@ -80,12 +82,14 @@ export {
80
82
  numericEnvAllowZero,
81
83
  numericEnv,
82
84
  mergeDeterministicArtifacts,
85
+ isToolGroupPlaceholder,
83
86
  isRetryableExternalAnalystFailure,
84
87
  isDeterministicLocalAnalyst,
85
88
  inventoryFiles,
86
89
  graphForSync,
87
90
  findFresherHarnessReports,
88
91
  emitWrittenArtifacts,
92
+ deterministicArtifacts,
89
93
  detectAvailableCodingAgents,
90
94
  describeSyncTenantLabel,
91
95
  describeSyncIdentity,
@@ -21,7 +21,7 @@ import {
21
21
  } from "./cli-hcwdz9sd.js";
22
22
  import {
23
23
  buildDoctorReport
24
- } from "./cli-73x2yznb.js";
24
+ } from "./cli-zgmxsmbt.js";
25
25
  import {
26
26
  ConnectCodeError,
27
27
  connectWithCode,
@@ -32,7 +32,7 @@ import {
32
32
  import {
33
33
  initPrompts,
34
34
  runPromptSync
35
- } from "./cli-79pzgqtj.js";
35
+ } from "./cli-arze1hgb.js";
36
36
  import"./cli-mm48br00.js";
37
37
  import {
38
38
  codingAgentDisplayName,
@@ -46,7 +46,7 @@ import {
46
46
  runCodingAgent,
47
47
  runHarnessCommand,
48
48
  startRemoteAnalyze
49
- } from "./cli-n3bjh1pc.js";
49
+ } from "./cli-xx73daeb.js";
50
50
  import {
51
51
  stripAnsi
52
52
  } from "./cli-97fnztpy.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  inventoryFiles,
3
3
  safePromptEvidencePath
4
- } from "./cli-n3bjh1pc.js";
4
+ } from "./cli-xx73daeb.js";
5
5
  import"./cli-97fnztpy.js";
6
6
  import"./cli-xq45etg1.js";
7
7
  import"./cli-gtke9wrw.js";
@@ -3,7 +3,7 @@ import {
3
3
  checkPromptMapping,
4
4
  discoverHarnessPromptSources,
5
5
  safePromptEvidencePath
6
- } from "./cli-n3bjh1pc.js";
6
+ } from "./cli-xx73daeb.js";
7
7
  import"./cli-97fnztpy.js";
8
8
  import"./cli-xq45etg1.js";
9
9
  import"./cli-gtke9wrw.js";
@@ -9,7 +9,7 @@ import {
9
9
  runPromptSync,
10
10
  runPromptsCommand,
11
11
  writePromptSyncProgress
12
- } from "./cli-79pzgqtj.js";
12
+ } from "./cli-arze1hgb.js";
13
13
  import {
14
14
  promptSourceHashPayload
15
15
  } from "./cli-mm48br00.js";
@@ -6,11 +6,11 @@ import"./cli-rjav0vj1.js";
6
6
  import"./cli-hcwdz9sd.js";
7
7
  import {
8
8
  runPromptsCommand
9
- } from "./cli-79pzgqtj.js";
9
+ } from "./cli-arze1hgb.js";
10
10
  import"./cli-mm48br00.js";
11
11
  import {
12
12
  runHarnessCommand
13
- } from "./cli-n3bjh1pc.js";
13
+ } from "./cli-xx73daeb.js";
14
14
  import"./cli-97fnztpy.js";
15
15
  import"./cli-xq45etg1.js";
16
16
  import"./cli-gtke9wrw.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moda-ai/cli",
3
- "version": "1.55.50",
3
+ "version": "1.55.52",
4
4
  "description": "CLI for Moda: production monitoring and evals for AI agents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": "moda.skill_index.v1",
3
- "bundled_at": "2026-10-20T15:58:32.977Z",
4
- "cli_version": "1.55.50",
3
+ "bundled_at": "2026-10-20T23:50:34.577Z",
4
+ "cli_version": "1.55.52",
5
5
  "skills": [
6
6
  {
7
7
  "id": "integration-cloudflare-think",