@moda-ai/cli 1.55.60 → 1.55.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-ds0qdtxz.js → agent-rc62qxke.js} +18 -17
- package/dist/{cli-94r5x9bg.js → cli-27kkk5z4.js} +1 -1
- package/dist/{cli-bt564t50.js → cli-3t4ft30h.js} +5 -5
- package/dist/{cli-9g8kp42c.js → cli-9rmx2zzy.js} +2 -2
- package/dist/{cli-hawwf30b.js → cli-bpnt0z0y.js} +1 -1
- package/dist/{cli-2jwxdhh5.js → cli-c7mj168q.js} +1 -1
- package/dist/cli-fsgh8mq5.js +1522 -0
- package/dist/{cli-y5d33a1y.js → cli-gmvbapx7.js} +2 -1517
- package/dist/{cli-rtkjjf0a.js → cli-kmq9pgef.js} +68 -1241
- package/dist/{cli-v2h21cgf.js → cli-m702wdtv.js} +1 -1
- package/dist/cli-mfvwvh84.js +1178 -0
- package/dist/{cli-b918vs2m.js → cli-p2tfx93b.js} +4 -4
- package/dist/{cli-m25c0rke.js → cli-rdwy3y4f.js} +3 -3
- package/dist/{cli-hxy54rx3.js → cli-thy08dak.js} +11 -11
- package/dist/{cli-wbd3hzqh.js → cli-tn9dg758.js} +680 -153
- package/dist/{cli-31ybq5f2.js → cli-wcax07xh.js} +2 -2
- package/dist/cli.js +27 -20
- package/dist/{doctor-s9t8e808.js → doctor-ehqrzq5e.js} +8 -8
- package/dist/{harness-bxcetthw.js → harness-e1yawk87.js} +13 -11
- package/dist/{harness-github-actions-acxh0dbf.js → harness-github-actions-bgfnh4tw.js} +11 -9
- package/dist/{harness-report-gz5d3y48.js → harness-report-dc6yf2qv.js} +2 -1
- package/dist/index-gtqxj0fp.js +2956 -0
- package/dist/{index-d8hc0er0.js → index-ma1gt133.js} +31 -29
- package/dist/{production-intelligence-fqvhzq6s.js → production-intelligence-40teyxyv.js} +4 -4
- package/dist/{profile-commands-yvpe4d8y.js → profile-commands-fa2858ez.js} +5 -5
- package/dist/{prompt-attribution-6xc7h59r.js → prompt-attribution-htyrwdjj.js} +13 -11
- package/dist/prompt-source-mcp.js +11 -9
- package/dist/{prompt-sources-1hycgx6r.js → prompt-sources-r2xbxr0r.js} +2 -1
- package/dist/{prompts-e8rhawyc.js → prompts-s5q70jge.js} +6 -6
- package/dist/{provision-aqhfbnez.js → provision-2bb73ywd.js} +6 -6
- package/dist/{registry-wv1zzyce.js → registry-ztn727mn.js} +4 -4
- package/dist/{skills-etzcqhp8.js → skills-c25dmy28.js} +6 -6
- package/dist/{sync-m9htrc8t.js → sync-t1d50rpv.js} +16 -14
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/dist/{cli-pnarsb96.js → cli-15pzedv3.js} +3 -3
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
stripAnsi
|
|
3
|
-
} from "./cli-97fnztpy.js";
|
|
4
1
|
import {
|
|
5
2
|
SYNC_STATE_PATH,
|
|
6
3
|
readHarnessSyncState,
|
|
@@ -10,19 +7,42 @@ import {
|
|
|
10
7
|
renderHarnessAnalyzeHumanResult,
|
|
11
8
|
renderHarnessProgress
|
|
12
9
|
} from "./cli-k0vxtzxb.js";
|
|
10
|
+
import {
|
|
11
|
+
stripAnsi
|
|
12
|
+
} from "./cli-97fnztpy.js";
|
|
13
|
+
import {
|
|
14
|
+
HARNESS_ANALYZE_CONCERNS,
|
|
15
|
+
HARNESS_REPORT_PATH,
|
|
16
|
+
MAX_HARNESS_REPORT_SUMMARY_LENGTH,
|
|
17
|
+
approveHarnessReport,
|
|
18
|
+
artifactHasBody,
|
|
19
|
+
createHarnessReport,
|
|
20
|
+
firstEvidencePath,
|
|
21
|
+
graphForReport,
|
|
22
|
+
hashHarnessReport,
|
|
23
|
+
hashStableJson,
|
|
24
|
+
loadHarnessReportForSync,
|
|
25
|
+
normalizeHarnessReport,
|
|
26
|
+
readHarnessReport,
|
|
27
|
+
requiresArtifactBody,
|
|
28
|
+
resolveHarnessReportPath,
|
|
29
|
+
stampRemoteSnapshotTruncation,
|
|
30
|
+
validateHarnessReport,
|
|
31
|
+
writeHarnessReportArtifacts
|
|
32
|
+
} from "./cli-kmq9pgef.js";
|
|
13
33
|
import {
|
|
14
34
|
createCommandContext,
|
|
15
35
|
stringOption
|
|
16
|
-
} from "./cli-
|
|
36
|
+
} from "./cli-m702wdtv.js";
|
|
17
37
|
import {
|
|
18
38
|
assertFlags,
|
|
19
39
|
assertPositionals,
|
|
20
40
|
requireTenant
|
|
21
|
-
} from "./cli-
|
|
41
|
+
} from "./cli-wcax07xh.js";
|
|
22
42
|
import {
|
|
23
43
|
ApiError,
|
|
24
44
|
callControlAPI
|
|
25
|
-
} from "./cli-
|
|
45
|
+
} from "./cli-bpnt0z0y.js";
|
|
26
46
|
import {
|
|
27
47
|
embeddedTenantIdFromApiKey,
|
|
28
48
|
getActiveProfile,
|
|
@@ -32,7 +52,11 @@ import {
|
|
|
32
52
|
resolveModaBaseUrl,
|
|
33
53
|
resolveTenantId,
|
|
34
54
|
shellArg
|
|
35
|
-
} from "./cli-
|
|
55
|
+
} from "./cli-15pzedv3.js";
|
|
56
|
+
import {
|
|
57
|
+
CliInputError,
|
|
58
|
+
CliInputRequiredError
|
|
59
|
+
} from "./cli-k4tqwah4.js";
|
|
36
60
|
import {
|
|
37
61
|
PYTHON_AGENT_MODULES,
|
|
38
62
|
TYPESCRIPT_AGENT_MODULES,
|
|
@@ -41,10 +65,9 @@ import {
|
|
|
41
65
|
discoverStructuredPromptSources,
|
|
42
66
|
extractCodeSource,
|
|
43
67
|
extractPythonSource,
|
|
44
|
-
require_typescript,
|
|
45
68
|
resolvePromptSource,
|
|
46
69
|
validatePromptSource
|
|
47
|
-
} from "./cli-
|
|
70
|
+
} from "./cli-fsgh8mq5.js";
|
|
48
71
|
import {
|
|
49
72
|
$isMap,
|
|
50
73
|
$isNode,
|
|
@@ -72,38 +95,19 @@ import {
|
|
|
72
95
|
shouldInventoryFile
|
|
73
96
|
} from "./cli-9a4b1wxz.js";
|
|
74
97
|
import {
|
|
75
|
-
HARNESS_ANALYZE_CONCERNS,
|
|
76
|
-
HARNESS_REPORT_PATH,
|
|
77
|
-
MAX_HARNESS_REPORT_SUMMARY_LENGTH,
|
|
78
|
-
approveHarnessReport,
|
|
79
|
-
artifactHasBody,
|
|
80
|
-
createHarnessReport,
|
|
81
|
-
firstEvidencePath,
|
|
82
|
-
graphForReport,
|
|
83
|
-
hashHarnessReport,
|
|
84
|
-
hashStableJson,
|
|
85
|
-
loadHarnessReportForSync,
|
|
86
98
|
mergeBoundRuntimeClasses,
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
requiresArtifactBody,
|
|
90
|
-
resolveHarnessReportPath,
|
|
91
|
-
stampRemoteSnapshotTruncation,
|
|
92
|
-
tagComponentStatus,
|
|
93
|
-
validateHarnessReport,
|
|
94
|
-
writeHarnessReportArtifacts
|
|
95
|
-
} from "./cli-rtkjjf0a.js";
|
|
99
|
+
tagComponentStatus
|
|
100
|
+
} from "./cli-mfvwvh84.js";
|
|
96
101
|
import {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
} from "./cli-k4tqwah4.js";
|
|
102
|
+
require_typescript
|
|
103
|
+
} from "./cli-gmvbapx7.js";
|
|
100
104
|
import {
|
|
101
105
|
__require,
|
|
102
106
|
__toESM
|
|
103
107
|
} from "./cli-0v6na3yp.js";
|
|
104
108
|
|
|
105
109
|
// src/harness.ts
|
|
106
|
-
import { createHash as
|
|
110
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
107
111
|
import { execFileSync as execFileSync3, spawn } from "node:child_process";
|
|
108
112
|
import { homedir, tmpdir as tmpdir2 } from "node:os";
|
|
109
113
|
import { fileURLToPath } from "node:url";
|
|
@@ -113,11 +117,11 @@ import {
|
|
|
113
117
|
mkdtempSync as mkdtempSync2,
|
|
114
118
|
mkdirSync as mkdirSync5,
|
|
115
119
|
readFileSync as readFileSync12,
|
|
116
|
-
readdirSync as
|
|
120
|
+
readdirSync as readdirSync5,
|
|
117
121
|
writeFileSync as writeFileSync5,
|
|
118
122
|
rmSync as rmSync4
|
|
119
123
|
} from "node:fs";
|
|
120
|
-
import { basename as
|
|
124
|
+
import { basename as basename7, delimiter, dirname as dirname7, join as join9, relative as relative6, resolve as resolve10, sep as sep5 } from "node:path";
|
|
121
125
|
import { confirm, select } from "@inquirer/prompts";
|
|
122
126
|
|
|
123
127
|
// src/analyst-tui.ts
|
|
@@ -12111,7 +12115,98 @@ function enrichScanCaptureMetadata(graph) {
|
|
|
12111
12115
|
|
|
12112
12116
|
// src/harness-candidates.ts
|
|
12113
12117
|
import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
12114
|
-
import { basename as
|
|
12118
|
+
import { basename as basename6, dirname as dirname6, extname as extname2, resolve as resolve6 } from "node:path";
|
|
12119
|
+
|
|
12120
|
+
// src/harness-eval-suites.ts
|
|
12121
|
+
import { basename as basename5, extname } from "node:path";
|
|
12122
|
+
var EVAL_FILE_EXTENSIONS = new Set([".ts", ".tsx", ".mts", ".js", ".mjs", ".cjs", ".py", ".yaml", ".yml"]);
|
|
12123
|
+
var EVAL_CASE_DATA_EXTENSIONS = new Set([".json", ".jsonl", ".toml"]);
|
|
12124
|
+
var EVAL_DIR_SEGMENT = /^(?:evals|evaluations)$/i;
|
|
12125
|
+
var EVAL_HARNESS_DIR_SEGMENT = /^eval$/i;
|
|
12126
|
+
var EVAL_FILE_NAME = /(?:^|[._-])evals?(?:[._-]|$)|^promptfoo/i;
|
|
12127
|
+
var DOCS_ROOT = /^(?:docs?|documentation)\//i;
|
|
12128
|
+
var HIDDEN_DIR = /(?:^|\/)\.[^/]+\//;
|
|
12129
|
+
var EVAL_SCRIPT_NAME = /(?:^|[._-])(?:judges?|grader|grading|benchmarks?)(?:[._-]|$)/i;
|
|
12130
|
+
var SCRIPTS_ROOT = /^(?:scripts?|bin)\//i;
|
|
12131
|
+
var EVALUATION_NAME = /(?:^|[._-])evaluat(?:e|ion|ions|or|ors)(?:[._-]|$)/i;
|
|
12132
|
+
var TEST_TREE = /(?:^|\/)(?:tests?|__tests__)\//i;
|
|
12133
|
+
var EVAL_SEED_SCRIPT = /^(?:seed|fetch|scrape|download|populate|extract)[-_]/i;
|
|
12134
|
+
var EVAL_NON_CASE_DATA = /^(?:leaderboards?|results?|scores?|reports?|outputs?|summary|tsconfig|jsconfig|package(?:-lock)?)(?:[._-][^/]*)?\.[^.]+$/i;
|
|
12135
|
+
var TEST_FILE_NAME = /(?:^|\/)(?:test_[^/]*\.py|[^/]*_test\.py|[^/]*\.(?:test|spec)\.[^/]+)$/i;
|
|
12136
|
+
var EVAL_TEST_NAME = /\.evals?\.(?:test|spec)\.[^/.]+$/i;
|
|
12137
|
+
var EVAL_IMPORT = /(?:\bfrom\s+|\bimport\s*\(\s*|\brequire\s*\(\s*|^\s*import\s+)['"][^'"]*(?:\/(?:evals?|evaluations)\/|[\/._-]evals?(?:[._-][^'"/]*)?['"])/m;
|
|
12138
|
+
function evalDirectoryIndex(path) {
|
|
12139
|
+
return path.split("/").slice(0, -1).findIndex((segment) => EVAL_DIR_SEGMENT.test(segment) || EVAL_HARNESS_DIR_SEGMENT.test(segment));
|
|
12140
|
+
}
|
|
12141
|
+
function isEvalHarnessDirectory(path, index) {
|
|
12142
|
+
return index >= 0 && EVAL_HARNESS_DIR_SEGMENT.test(path.split("/")[index] ?? "");
|
|
12143
|
+
}
|
|
12144
|
+
function isEvalSuitePath(path) {
|
|
12145
|
+
const ext = extname(path).toLowerCase();
|
|
12146
|
+
const name = basename5(path);
|
|
12147
|
+
if (DOCS_ROOT.test(path) || HIDDEN_DIR.test(path) || /\.d\.[cm]?ts$/i.test(path) || EVAL_SEED_SCRIPT.test(name))
|
|
12148
|
+
return false;
|
|
12149
|
+
const inEvalDir = evalDirectoryIndex(path) >= 0;
|
|
12150
|
+
if (EVAL_CASE_DATA_EXTENSIONS.has(ext))
|
|
12151
|
+
return inEvalDir && !EVAL_NON_CASE_DATA.test(name);
|
|
12152
|
+
if (!EVAL_FILE_EXTENSIONS.has(ext))
|
|
12153
|
+
return false;
|
|
12154
|
+
return inEvalDir || EVAL_FILE_NAME.test(name) || SCRIPTS_ROOT.test(path) && EVAL_SCRIPT_NAME.test(name) || TEST_TREE.test(path) && EVALUATION_NAME.test(name);
|
|
12155
|
+
}
|
|
12156
|
+
function isTestOfEvalCode(path, text) {
|
|
12157
|
+
return TEST_FILE_NAME.test(path) && !EVAL_TEST_NAME.test(path) && evalDirectoryIndex(path) < 0 && EVAL_IMPORT.test(text);
|
|
12158
|
+
}
|
|
12159
|
+
function isEvalModelSource(path) {
|
|
12160
|
+
if (!isEvalSuitePath(path))
|
|
12161
|
+
return false;
|
|
12162
|
+
return evalDirectoryIndex(path) >= 0 || EVAL_TEST_NAME.test(path) || !TEST_FILE_NAME.test(path);
|
|
12163
|
+
}
|
|
12164
|
+
function evalFileSignal(path, text) {
|
|
12165
|
+
if (!isEvalSuitePath(path) || isTestOfEvalCode(path, text))
|
|
12166
|
+
return;
|
|
12167
|
+
return evalDirectoryIndex(path) < 0 ? "eval.file_name" : "eval.suite_dir";
|
|
12168
|
+
}
|
|
12169
|
+
var EVAL_RUNNER_NAMES = [
|
|
12170
|
+
/^(?:run|runner|main|index|eval|evaluate|cli)\.[^.]+$/i,
|
|
12171
|
+
/^(?:run|runner|main|eval|evaluate)[._-]/i,
|
|
12172
|
+
/(?:^|[._-])evals?(?:[._-]|$)/i
|
|
12173
|
+
];
|
|
12174
|
+
function evalSuiteKey(path) {
|
|
12175
|
+
const index = evalDirectoryIndex(path);
|
|
12176
|
+
const segments = path.split("/");
|
|
12177
|
+
if (isEvalHarnessDirectory(path, index))
|
|
12178
|
+
return segments.slice(0, index + 1).join("/");
|
|
12179
|
+
if (index < 0 || segments.length - 1 <= index + 1)
|
|
12180
|
+
return path;
|
|
12181
|
+
return segments.slice(0, index + 2).join("/");
|
|
12182
|
+
}
|
|
12183
|
+
function promoteEvalSuites(files, confidence2, naming) {
|
|
12184
|
+
const suites = new Map;
|
|
12185
|
+
for (const file of files) {
|
|
12186
|
+
const key = evalSuiteKey(file.path);
|
|
12187
|
+
suites.set(key, [...suites.get(key) ?? [], file]);
|
|
12188
|
+
}
|
|
12189
|
+
return [...suites].map(([key, members]) => {
|
|
12190
|
+
const sorted = [...members].sort((a, b) => a.path.localeCompare(b.path));
|
|
12191
|
+
const runner = EVAL_RUNNER_NAMES.map((name) => sorted.find((file) => name.test(basename5(file.path)))).find(Boolean) ?? sorted[0];
|
|
12192
|
+
const cited = [runner, ...sorted.filter((file) => file !== runner)];
|
|
12193
|
+
const isDirectory = key !== runner.path;
|
|
12194
|
+
const isHarness = isDirectory && isEvalHarnessDirectory(runner.path, evalDirectoryIndex(runner.path));
|
|
12195
|
+
return {
|
|
12196
|
+
id: naming.artifactId(key),
|
|
12197
|
+
type: "eval",
|
|
12198
|
+
name: isHarness ? `${key} eval harness` : isDirectory ? `${basename5(key)} eval suite` : basename5(key),
|
|
12199
|
+
scope: "global",
|
|
12200
|
+
sourcePath: runner.path,
|
|
12201
|
+
usedByAgentIds: [],
|
|
12202
|
+
confidence: confidence2,
|
|
12203
|
+
confidenceReason: isDirectory ? `Deterministic: eval suite directory ${key} (${members.length} source file${members.length === 1 ? "" : "s"}); not checked by the analyst.` : naming.fileReason(runner),
|
|
12204
|
+
evidence: cited.map((file) => ({ path: file.path, line: 1, reason: `deterministic detector ${file.signal}` }))
|
|
12205
|
+
};
|
|
12206
|
+
});
|
|
12207
|
+
}
|
|
12208
|
+
|
|
12209
|
+
// src/harness-candidates.ts
|
|
12115
12210
|
var MAX_CANDIDATES_PER_FILE_PER_SIGNAL = 20;
|
|
12116
12211
|
var MIN_PROMPT_LITERAL_CHARS = 160;
|
|
12117
12212
|
var CONFIDENCE_WEIGHT = {
|
|
@@ -12335,6 +12430,168 @@ var LINE_PATTERNS = [
|
|
|
12335
12430
|
}
|
|
12336
12431
|
];
|
|
12337
12432
|
var CODE_EXTENSIONS = new Set([...JS, ...PY]);
|
|
12433
|
+
var PROVIDER_MODEL_ID = /^(?:anthropic|openai|google|meta-llama|mistralai|deepseek|x-ai|perplexity|qwen|cohere|moonshotai|z-ai|minimax|amazon|nvidia|microsoft|ai21|nousresearch|bytedance|baidu|inception|openrouter)\/[a-z0-9][\w.:-]*$/i;
|
|
12434
|
+
var PROVIDER_COLON_MODEL_ID = /^(?:openai|anthropic|google_genai|google_vertexai|google|groq|mistralai|bedrock|bedrock_converse|azure_openai|ollama|fireworks|together|deepseek|xai|perplexity|cohere|openrouter):([a-z0-9][\w./:-]*)$/i;
|
|
12435
|
+
var CHOSEN_VALUE_PREFIX = /(?:\b[A-Za-z_]\w*\s*=|\bmodel\w*["']?\s*:)\s*$/i;
|
|
12436
|
+
function isChosenProviderColonModel(value, before) {
|
|
12437
|
+
const model = PROVIDER_COLON_MODEL_ID.exec(value)?.[1];
|
|
12438
|
+
return Boolean(model && PROVIDER_MODEL_NAME.test(model) && CHOSEN_VALUE_PREFIX.test(before));
|
|
12439
|
+
}
|
|
12440
|
+
var PROVIDER_MODEL_NAME = /\d|claude|gpt|gemini|gemma|llama|mistral|mixtral|qwen|deepseek|grok|sonar|kimi|glm|command|minimax|auto/i;
|
|
12441
|
+
var BARE_MODEL_ID = /^(?:claude-|gpt-|chatgpt-|gemini-|text-embedding-|deepseek-|mistral-|llama-?|grok-|command-|qwen|kimi-|glm-)[\w.:-]*$/i;
|
|
12442
|
+
var O_SERIES_MODEL_ID = /^o[1-9](?:-(?:mini|pro|preview|deep-research))*(?:-\d{4}-\d{2}-\d{2})?$/i;
|
|
12443
|
+
var NOT_MODEL_ID = /^(?:claude-(?:code|ai|desktop|agent-sdk)|gpt-tokenizer|gpt-3-encoder|gemini-cli)\b/i;
|
|
12444
|
+
var FILE_NAME_SUFFIX = /\.(?:[cm]?[jt]sx?|json|ya?ml|toml|md|txt|py|png|jpe?g|gif|svg|webp|css|html?)$/i;
|
|
12445
|
+
var MODEL_CANDIDATE_VALUE = /^[A-Za-z0-9][\w./:-]{2,80}$/;
|
|
12446
|
+
var IMPORT_LINE = /^\s*(?:import\b|export\s+(?:\*|\{[^}]*\})\s*from\b|from\s+\S+\s+import\b)|\brequire\s*\(|\bimport\s*\(/;
|
|
12447
|
+
var CLASS_ATTRIBUTE_PREFIX = /\bclass(?:Name|List)?\s*[=:]\s*\{?\s*$/;
|
|
12448
|
+
var NON_MODEL_SOURCE_PATH = /\.d\.[cm]?ts$|\.min\.[cm]?js$|(?:^|\/)(?:public|static)\/|(?:^|\/)(?:package(?:-lock)?\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?)$/i;
|
|
12449
|
+
var MODEL_ID_EXTENSIONS = new Set([...CODE_EXTENSIONS, ".json", ".jsonc", ".yaml", ".yml", ".toml"]);
|
|
12450
|
+
function isModelIdLiteral(value) {
|
|
12451
|
+
if (value.length < 4 || value.length > 80 || /\s/.test(value) || NOT_MODEL_ID.test(value) || FILE_NAME_SUFFIX.test(value))
|
|
12452
|
+
return false;
|
|
12453
|
+
if (PROVIDER_MODEL_ID.test(value))
|
|
12454
|
+
return PROVIDER_MODEL_NAME.test(value.slice(value.indexOf("/") + 1));
|
|
12455
|
+
if (O_SERIES_MODEL_ID.test(value))
|
|
12456
|
+
return true;
|
|
12457
|
+
return BARE_MODEL_ID.test(value) && /\d/.test(value);
|
|
12458
|
+
}
|
|
12459
|
+
var HASH_COMMENT_EXTENSIONS = new Set([...PY, ".yaml", ".yml", ".toml"]);
|
|
12460
|
+
var REGEX_PRECEDER = /(?:^|[(,=:[!&|?{};+\-*%<>~^]|\b(?:return|typeof|case|in|of|delete|void|throw|new|yield|await))\s*$/;
|
|
12461
|
+
function startsRegexLiteral(line, start) {
|
|
12462
|
+
const next = line[start + 1];
|
|
12463
|
+
if (next === undefined || next === "/" || next === "*" || next === ">" || line[start - 1] === "<")
|
|
12464
|
+
return false;
|
|
12465
|
+
return REGEX_PRECEDER.test(line.slice(0, start));
|
|
12466
|
+
}
|
|
12467
|
+
function regexLiteralEnd(line, start) {
|
|
12468
|
+
let inClass = false;
|
|
12469
|
+
for (let j = start + 1;j < line.length; j += 1) {
|
|
12470
|
+
const ch = line[j];
|
|
12471
|
+
if (ch === "\\") {
|
|
12472
|
+
j += 1;
|
|
12473
|
+
continue;
|
|
12474
|
+
}
|
|
12475
|
+
if (ch === "[")
|
|
12476
|
+
inClass = true;
|
|
12477
|
+
else if (ch === "]")
|
|
12478
|
+
inClass = false;
|
|
12479
|
+
else if (ch === "/" && !inClass)
|
|
12480
|
+
return j + 1;
|
|
12481
|
+
}
|
|
12482
|
+
return line.length;
|
|
12483
|
+
}
|
|
12484
|
+
function stringLiteralsInLine(line, state, hashComments) {
|
|
12485
|
+
const out = [];
|
|
12486
|
+
const closeAt = (from, close, escapes) => {
|
|
12487
|
+
for (let j = from;j < line.length; j += 1) {
|
|
12488
|
+
if (escapes && line[j] === "\\") {
|
|
12489
|
+
j += 1;
|
|
12490
|
+
continue;
|
|
12491
|
+
}
|
|
12492
|
+
if (line.startsWith(close, j))
|
|
12493
|
+
return j;
|
|
12494
|
+
}
|
|
12495
|
+
return -1;
|
|
12496
|
+
};
|
|
12497
|
+
let i = 0;
|
|
12498
|
+
if (state.open) {
|
|
12499
|
+
const close = state.open === "/*" ? "*/" : state.open;
|
|
12500
|
+
const at = closeAt(0, close, state.open !== "/*");
|
|
12501
|
+
if (at < 0)
|
|
12502
|
+
return out;
|
|
12503
|
+
i = at + close.length;
|
|
12504
|
+
state.open = null;
|
|
12505
|
+
}
|
|
12506
|
+
while (i < line.length) {
|
|
12507
|
+
const ch = line[i];
|
|
12508
|
+
if (hashComments ? ch === "#" : line.startsWith("//", i))
|
|
12509
|
+
break;
|
|
12510
|
+
if (!hashComments && line.startsWith("/*", i)) {
|
|
12511
|
+
const at2 = closeAt(i + 2, "*/", false);
|
|
12512
|
+
if (at2 < 0) {
|
|
12513
|
+
state.open = "/*";
|
|
12514
|
+
break;
|
|
12515
|
+
}
|
|
12516
|
+
i = at2 + 2;
|
|
12517
|
+
continue;
|
|
12518
|
+
}
|
|
12519
|
+
if (!hashComments && ch === "/" && startsRegexLiteral(line, i)) {
|
|
12520
|
+
i = regexLiteralEnd(line, i);
|
|
12521
|
+
continue;
|
|
12522
|
+
}
|
|
12523
|
+
if (ch !== '"' && ch !== "'" && ch !== "`") {
|
|
12524
|
+
i += 1;
|
|
12525
|
+
continue;
|
|
12526
|
+
}
|
|
12527
|
+
const triple = hashComments && line.startsWith(ch.repeat(3), i);
|
|
12528
|
+
const quote = triple ? ch.repeat(3) : ch;
|
|
12529
|
+
const at = closeAt(i + quote.length, quote, true);
|
|
12530
|
+
if (at < 0) {
|
|
12531
|
+
if (triple || ch === "`")
|
|
12532
|
+
state.open = quote;
|
|
12533
|
+
break;
|
|
12534
|
+
}
|
|
12535
|
+
out.push({ value: line.slice(i + quote.length, at), index: i, end: at + quote.length });
|
|
12536
|
+
i = at + quote.length;
|
|
12537
|
+
}
|
|
12538
|
+
return out;
|
|
12539
|
+
}
|
|
12540
|
+
function modelIdLiteralsInScannedLine(line, state, hashComments) {
|
|
12541
|
+
const literals = stringLiteralsInLine(line, state, hashComments);
|
|
12542
|
+
if (line.length > 4000 || IMPORT_LINE.test(line))
|
|
12543
|
+
return [];
|
|
12544
|
+
return literals.filter((literal) => {
|
|
12545
|
+
if (!MODEL_CANDIDATE_VALUE.test(literal.value))
|
|
12546
|
+
return false;
|
|
12547
|
+
const before = line.slice(0, literal.index);
|
|
12548
|
+
return (isModelIdLiteral(literal.value) || isChosenProviderColonModel(literal.value, before)) && !CLASS_ATTRIBUTE_PREFIX.test(before);
|
|
12549
|
+
});
|
|
12550
|
+
}
|
|
12551
|
+
function modelIdLiteralsInLines(lines, path) {
|
|
12552
|
+
const hashComments = HASH_COMMENT_EXTENSIONS.has(extname2(path).toLowerCase());
|
|
12553
|
+
const state = { open: null };
|
|
12554
|
+
return lines.map((line) => modelIdLiteralsInScannedLine(line, state, hashComments));
|
|
12555
|
+
}
|
|
12556
|
+
var HIGH_CONFIDENCE_MODEL_PATTERNS = LINE_PATTERNS.filter((pattern) => pattern.kind === "model_config" && pattern.confidence === "high");
|
|
12557
|
+
function detectModelIdLiterals(file, out) {
|
|
12558
|
+
if (!MODEL_ID_EXTENSIONS.has(extname2(file.path).toLowerCase()) || NON_MODEL_SOURCE_PATH.test(file.path))
|
|
12559
|
+
return;
|
|
12560
|
+
const lines = file.text.split(`
|
|
12561
|
+
`);
|
|
12562
|
+
const literals = modelIdLiteralsInLines(lines, file.path);
|
|
12563
|
+
for (let i = 0;i < lines.length; i += 1) {
|
|
12564
|
+
const line = lines[i];
|
|
12565
|
+
if (literals[i].length === 0)
|
|
12566
|
+
continue;
|
|
12567
|
+
if (HIGH_CONFIDENCE_MODEL_PATTERNS.some((pattern) => pattern.pattern.test(line)))
|
|
12568
|
+
continue;
|
|
12569
|
+
out.push({
|
|
12570
|
+
kind: "model_config",
|
|
12571
|
+
path: file.path,
|
|
12572
|
+
startLine: i + 1,
|
|
12573
|
+
endLine: i + 1,
|
|
12574
|
+
confidence: "high",
|
|
12575
|
+
signal: "model.id_literal",
|
|
12576
|
+
excerpt: normalizeExcerpt(line)
|
|
12577
|
+
});
|
|
12578
|
+
}
|
|
12579
|
+
}
|
|
12580
|
+
function detectEvalFile(file, out) {
|
|
12581
|
+
const signal = evalFileSignal(file.path, file.text);
|
|
12582
|
+
if (!signal)
|
|
12583
|
+
return;
|
|
12584
|
+
out.push({
|
|
12585
|
+
kind: "eval_file",
|
|
12586
|
+
path: file.path,
|
|
12587
|
+
startLine: 1,
|
|
12588
|
+
endLine: Math.max(1, file.text.split(`
|
|
12589
|
+
`).length),
|
|
12590
|
+
confidence: "high",
|
|
12591
|
+
signal,
|
|
12592
|
+
excerpt: normalizeExcerpt(file.text.slice(0, 300))
|
|
12593
|
+
});
|
|
12594
|
+
}
|
|
12338
12595
|
var PROMPT_DOC_EXTENSIONS = new Set([".md", ".mdc", ".txt", ".prompt", ".jinja", ".jinja2", ".j2", ".hbs", ".tpl"]);
|
|
12339
12596
|
var UPPERCASE_DOC_NAME = /^[A-Z0-9][A-Z0-9_-]*\.(?:md|mdc|txt)$/;
|
|
12340
12597
|
var NON_PROMPT_DOC_BASENAMES = new Set([
|
|
@@ -12396,7 +12653,7 @@ function lineAtIndex(offsets, index) {
|
|
|
12396
12653
|
return lo + 1;
|
|
12397
12654
|
}
|
|
12398
12655
|
function detectLinePatterns(file, out) {
|
|
12399
|
-
const ext =
|
|
12656
|
+
const ext = extname2(file.path).toLowerCase();
|
|
12400
12657
|
const lines = file.text.split(`
|
|
12401
12658
|
`);
|
|
12402
12659
|
const perSignal = new Map;
|
|
@@ -12473,7 +12730,7 @@ function detectAdjacentStringBlocks(file, out) {
|
|
|
12473
12730
|
}
|
|
12474
12731
|
var PROMPT_MODULE_NAME_HINT = /(^|[._-])(system[._-]?)?prompts?([._-]|$)/i;
|
|
12475
12732
|
function detectPromptModule(file, out) {
|
|
12476
|
-
const base =
|
|
12733
|
+
const base = basename6(file.path, extname2(file.path));
|
|
12477
12734
|
if (!PROMPT_MODULE_NAME_HINT.test(base))
|
|
12478
12735
|
return;
|
|
12479
12736
|
out.push({
|
|
@@ -12488,7 +12745,7 @@ function detectPromptModule(file, out) {
|
|
|
12488
12745
|
});
|
|
12489
12746
|
}
|
|
12490
12747
|
function detectPromptLiterals(file, out) {
|
|
12491
|
-
const ext =
|
|
12748
|
+
const ext = extname2(file.path).toLowerCase();
|
|
12492
12749
|
const offsets = buildLineIndex(file.text);
|
|
12493
12750
|
let found = 0;
|
|
12494
12751
|
const record = (startIndex, endIndex, content, signal) => {
|
|
@@ -12533,10 +12790,10 @@ function detectPromptLiterals(file, out) {
|
|
|
12533
12790
|
}
|
|
12534
12791
|
}
|
|
12535
12792
|
function detectPromptFile(file, out) {
|
|
12536
|
-
const ext =
|
|
12793
|
+
const ext = extname2(file.path).toLowerCase();
|
|
12537
12794
|
if (!PROMPT_DOC_EXTENSIONS.has(ext))
|
|
12538
12795
|
return;
|
|
12539
|
-
const base =
|
|
12796
|
+
const base = basename6(file.path).toLowerCase();
|
|
12540
12797
|
if (NON_PROMPT_DOC_BASENAMES.has(base))
|
|
12541
12798
|
return;
|
|
12542
12799
|
if (/(^|\/)(docs?|documentation|examples?|\.github)\//i.test(file.path))
|
|
@@ -12553,7 +12810,7 @@ function detectPromptFile(file, out) {
|
|
|
12553
12810
|
} else if (PROMPTS_DIR.test(dir)) {
|
|
12554
12811
|
confidence2 = "high";
|
|
12555
12812
|
signal = "prompt_file.prompts_dir";
|
|
12556
|
-
} else if (dirHint && score >= 3 && !UPPERCASE_DOC_NAME.test(
|
|
12813
|
+
} else if (dirHint && score >= 3 && !UPPERCASE_DOC_NAME.test(basename6(file.path))) {
|
|
12557
12814
|
confidence2 = "medium";
|
|
12558
12815
|
signal = "prompt_file.agent_dir_instruction_text";
|
|
12559
12816
|
} else if (score >= 5) {
|
|
@@ -12574,10 +12831,10 @@ function detectPromptFile(file, out) {
|
|
|
12574
12831
|
});
|
|
12575
12832
|
}
|
|
12576
12833
|
function detectPromptLoaderReferences(file, filesByPath, out) {
|
|
12577
|
-
if (!LOADER_CODE_EXTENSIONS.has(
|
|
12834
|
+
if (!LOADER_CODE_EXTENSIONS.has(extname2(file.path).toLowerCase()) && extname2(file.path).toLowerCase() !== ".md")
|
|
12578
12835
|
return;
|
|
12579
12836
|
const extension = "(?:\\.txt|\\.md)";
|
|
12580
|
-
const pattern =
|
|
12837
|
+
const pattern = extname2(file.path).toLowerCase() === ".rs" ? new RegExp(`\\binclude_str!\\s*\\(\\s*["']([^"']+${extension})["']\\s*\\)`, "g") : new RegExp(`\\b(?:Template\\.from_file|from_file|read_text|readFileSync)\\s*\\(\\s*["']([^"']+${extension})["']`, "g");
|
|
12581
12838
|
let found = 0;
|
|
12582
12839
|
let match;
|
|
12583
12840
|
while (found < MAX_CANDIDATES_PER_FILE_PER_SIGNAL && (match = pattern.exec(file.text)) !== null) {
|
|
@@ -12585,7 +12842,7 @@ function detectPromptLoaderReferences(file, filesByPath, out) {
|
|
|
12585
12842
|
const target = normalizeLoaderTarget(file.path, reference);
|
|
12586
12843
|
if (!target || !filesByPath.has(target))
|
|
12587
12844
|
continue;
|
|
12588
|
-
const targetBase =
|
|
12845
|
+
const targetBase = basename6(target).toLowerCase();
|
|
12589
12846
|
const highConfidence = RUST_PROMPT_PATH_HINT.test(target) || /Template\.from_file/i.test(match[0]);
|
|
12590
12847
|
if (!highConfidence)
|
|
12591
12848
|
continue;
|
|
@@ -12597,7 +12854,7 @@ function detectPromptLoaderReferences(file, filesByPath, out) {
|
|
|
12597
12854
|
endLine: 1,
|
|
12598
12855
|
confidence: "high",
|
|
12599
12856
|
signal: /Template\.from_file/i.test(match[0]) ? "prompt_file.template_loader_reference" : "prompt_file.loader_reference",
|
|
12600
|
-
excerpt: normalizeExcerpt(`${
|
|
12857
|
+
excerpt: normalizeExcerpt(`${basename6(file.path)} loads ${targetBase}`)
|
|
12601
12858
|
});
|
|
12602
12859
|
}
|
|
12603
12860
|
}
|
|
@@ -12625,10 +12882,12 @@ function detectHarnessCandidatesInFiles(files) {
|
|
|
12625
12882
|
if (typeof file.text !== "string" || file.text.length === 0)
|
|
12626
12883
|
continue;
|
|
12627
12884
|
const scoped = { path: file.path, text: file.text };
|
|
12628
|
-
const ext =
|
|
12885
|
+
const ext = extname2(file.path).toLowerCase();
|
|
12629
12886
|
if (CODE_EXTENSIONS.has(ext) || ext === ".json" || ext === ".yaml" || ext === ".yml" || ext === ".toml") {
|
|
12630
12887
|
detectLinePatterns(scoped, candidates);
|
|
12631
12888
|
}
|
|
12889
|
+
detectModelIdLiterals(scoped, candidates);
|
|
12890
|
+
detectEvalFile(scoped, candidates);
|
|
12632
12891
|
if (CODE_EXTENSIONS.has(ext)) {
|
|
12633
12892
|
detectAdjacentStringBlocks(scoped, candidates);
|
|
12634
12893
|
detectPromptModule(scoped, candidates);
|
|
@@ -12658,7 +12917,7 @@ function detectHarnessCandidates(rootDir) {
|
|
|
12658
12917
|
const skipped = [];
|
|
12659
12918
|
const root = resolve6(rootDir);
|
|
12660
12919
|
const inventory = inventoryFiles(root, skipped, {
|
|
12661
|
-
includeFile: (path) => PROMPT_DOC_EXTENSIONS.has(
|
|
12920
|
+
includeFile: (path) => PROMPT_DOC_EXTENSIONS.has(extname2(path).toLowerCase()) || [".json", ".jsonc", ".jsonl", ".yaml", ".yml", ".toml"].includes(extname2(path).toLowerCase()) || extname2(path).toLowerCase() === ".rs" && RUST_PROMPT_PATH_HINT.test(path)
|
|
12662
12921
|
});
|
|
12663
12922
|
const { candidates, files } = detectHarnessCandidatesInFiles(inventory);
|
|
12664
12923
|
const durationMs = Math.max(1, Date.now() - startedAt);
|
|
@@ -12691,7 +12950,7 @@ function writeHarnessCandidatesReport(report, outPath) {
|
|
|
12691
12950
|
|
|
12692
12951
|
// src/harness-prompt-sources.ts
|
|
12693
12952
|
import { createHash as createHash4 } from "node:crypto";
|
|
12694
|
-
import { extname as
|
|
12953
|
+
import { extname as extname7 } from "node:path";
|
|
12695
12954
|
|
|
12696
12955
|
// src/prompt-source-verification/index.ts
|
|
12697
12956
|
import { readFileSync as readFileSync10 } from "node:fs";
|
|
@@ -12699,7 +12958,7 @@ import { z } from "zod";
|
|
|
12699
12958
|
|
|
12700
12959
|
// src/prompt-source-validation.ts
|
|
12701
12960
|
import { existsSync as existsSync7, lstatSync as lstatSync5 } from "node:fs";
|
|
12702
|
-
import { extname as
|
|
12961
|
+
import { extname as extname3, relative as relative4, resolve as resolve7 } from "node:path";
|
|
12703
12962
|
function checkPromptMapping(rootDir, unknownMapping) {
|
|
12704
12963
|
const repairs = [];
|
|
12705
12964
|
const unresolved = [];
|
|
@@ -12779,12 +13038,12 @@ function normalizePromptMapping(value) {
|
|
|
12779
13038
|
return normalized;
|
|
12780
13039
|
}
|
|
12781
13040
|
function isPromptDefinitionPath(path) {
|
|
12782
|
-
return /(^|\/)(?:prompts?|templates?)(?:\/|\.)/i.test(path) || /\.prompt\.(?:md|txt|ya?ml|json)$/i.test(path) || [".jinja", ".j2", ".mustache", ".hbs"].includes(
|
|
13041
|
+
return /(^|\/)(?:prompts?|templates?)(?:\/|\.)/i.test(path) || /\.prompt\.(?:md|txt|ya?ml|json)$/i.test(path) || [".jinja", ".j2", ".mustache", ".hbs"].includes(extname3(path).toLowerCase());
|
|
12783
13042
|
}
|
|
12784
13043
|
|
|
12785
13044
|
// src/prompt-source-verification/evidence.ts
|
|
12786
13045
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
12787
|
-
import { extname as
|
|
13046
|
+
import { extname as extname6 } from "node:path";
|
|
12788
13047
|
|
|
12789
13048
|
// src/prompt-source-verification/paths.ts
|
|
12790
13049
|
import { lstatSync as lstatSync6, realpathSync as realpathSync6 } from "node:fs";
|
|
@@ -12812,13 +13071,13 @@ function safePromptEvidencePath(rootDir, path) {
|
|
|
12812
13071
|
// src/prompt-source-verification/sink-proof.ts
|
|
12813
13072
|
var import_typescript = __toESM(require_typescript(), 1);
|
|
12814
13073
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
12815
|
-
import { extname as
|
|
13074
|
+
import { extname as extname4 } from "node:path";
|
|
12816
13075
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
12817
13076
|
function proveSink(root, sink) {
|
|
12818
13077
|
const file = safePromptEvidencePath(root, sink.path);
|
|
12819
13078
|
const cache = new Map;
|
|
12820
13079
|
if (!cache.has(file)) {
|
|
12821
|
-
if (
|
|
13080
|
+
if (extname4(file) === ".py") {
|
|
12822
13081
|
try {
|
|
12823
13082
|
const rows = JSON.parse(execFileSync2("python3", ["-I", "-c", PYTHON_PROOF], { input: readFileSync7(file, "utf8"), encoding: "utf8", timeout: 1e4, maxBuffer: 2 * 1024 * 1024 }));
|
|
12824
13083
|
cache.set(file, new Map(Object.entries(rows).map(([line, proof]) => [Number(line), proof])));
|
|
@@ -12988,7 +13247,7 @@ print(json.dumps(rows))
|
|
|
12988
13247
|
|
|
12989
13248
|
// src/prompt-source-location.ts
|
|
12990
13249
|
import { readFileSync as readFileSync8 } from "node:fs";
|
|
12991
|
-
import { extname as
|
|
13250
|
+
import { extname as extname5 } from "node:path";
|
|
12992
13251
|
function structuredExcerpt(text, source) {
|
|
12993
13252
|
if (source.selector?.pointer === undefined)
|
|
12994
13253
|
return { line: 1, endLine: text.split(`
|
|
@@ -13028,7 +13287,7 @@ function structuredExcerpt(text, source) {
|
|
|
13028
13287
|
}
|
|
13029
13288
|
function promptDefinitionExcerpt(rootDir, source) {
|
|
13030
13289
|
const file = safePromptEvidencePath(rootDir, source.path);
|
|
13031
|
-
const ext =
|
|
13290
|
+
const ext = extname5(file).toLowerCase();
|
|
13032
13291
|
if (ext === ".py") {
|
|
13033
13292
|
const extraction = extractPythonSource(rootDir, file, source.selector?.symbol);
|
|
13034
13293
|
if (!extraction.range)
|
|
@@ -13052,7 +13311,7 @@ function promptDefinitionRange(rootDir, source) {
|
|
|
13052
13311
|
// src/prompt-source-verification/evidence.ts
|
|
13053
13312
|
function verifyPromptSourceEvidence(rootDir, source) {
|
|
13054
13313
|
const checked = checkPromptMapping(rootDir, source);
|
|
13055
|
-
const dedicated = isPromptDefinitionPath(source.path) && [".md", ".txt", ".jinja", ".j2", ".mustache", ".hbs"].includes(
|
|
13314
|
+
const dedicated = isPromptDefinitionPath(source.path) && [".md", ".txt", ".jinja", ".j2", ".mustache", ".hbs"].includes(extname6(source.path).toLowerCase());
|
|
13056
13315
|
return {
|
|
13057
13316
|
accepted: checked.ok && dedicated && checked.kind !== "builder",
|
|
13058
13317
|
reason: dedicated ? "Dedicated authored prompt file" : "Candidate requires independent semantic review",
|
|
@@ -13306,7 +13565,7 @@ function discoverHarnessPromptSources(rootDir, existing = []) {
|
|
|
13306
13565
|
}
|
|
13307
13566
|
try {
|
|
13308
13567
|
let found = [];
|
|
13309
|
-
const ext =
|
|
13568
|
+
const ext = extname7(path).toLowerCase();
|
|
13310
13569
|
if (CODE.has(ext)) {
|
|
13311
13570
|
if (attempts++ >= MAX_CODE_PROMPT_PATHS) {
|
|
13312
13571
|
issues.push({ path, reason: "Code prompt scan limit (64 files) reached; deferred to analyst review" });
|
|
@@ -13574,8 +13833,9 @@ function applyPromptDiscovery(graph, discovery) {
|
|
|
13574
13833
|
}
|
|
13575
13834
|
|
|
13576
13835
|
// src/harness-candidate-promotion.ts
|
|
13577
|
-
import {
|
|
13578
|
-
import {
|
|
13836
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
13837
|
+
import { readdirSync as readdirSync4, readFileSync as readFileSync11, statSync as statSync3 } from "node:fs";
|
|
13838
|
+
import { extname as extname8, posix, resolve as resolve9 } from "node:path";
|
|
13579
13839
|
|
|
13580
13840
|
// src/harness-js-source.ts
|
|
13581
13841
|
var import_typescript2 = __toESM(require_typescript(), 1);
|
|
@@ -13944,7 +14204,11 @@ var SIGNAL_DESCRIPTIONS = {
|
|
|
13944
14204
|
"prompt_file.agent_dir_instruction_text": "instruction-like text in an agent directory",
|
|
13945
14205
|
"prompt_file.loader_reference": "a file loaded as a prompt by code",
|
|
13946
14206
|
"prompt_file.template_loader_reference": "a file loaded as a prompt template by code",
|
|
13947
|
-
"model.assignment": "a model id assigned in code"
|
|
14207
|
+
"model.assignment": "a model id assigned in code",
|
|
14208
|
+
"model.registry_key": "a model registry key",
|
|
14209
|
+
"model.id_literal": "a model id string literal",
|
|
14210
|
+
"eval.suite_dir": "a file under an eval directory",
|
|
14211
|
+
"eval.file_name": "a file named as an eval"
|
|
13948
14212
|
};
|
|
13949
14213
|
function detectorConfidenceReason(candidate) {
|
|
13950
14214
|
const what = SIGNAL_DESCRIPTIONS[candidate.signal] ?? `the ${candidate.signal} pattern`;
|
|
@@ -14420,7 +14684,7 @@ function localNameIn(specifiers, identifier) {
|
|
|
14420
14684
|
function importedLocalName(importerPath, lines, identifier, definitionPath, exportsDefault = false) {
|
|
14421
14685
|
const text = lines.join(`
|
|
14422
14686
|
`);
|
|
14423
|
-
const python =
|
|
14687
|
+
const python = extname8(importerPath) === ".py";
|
|
14424
14688
|
if (python) {
|
|
14425
14689
|
for (const match of text.matchAll(/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm)) {
|
|
14426
14690
|
if (!specifierResolvesTo(match[1], importerPath, definitionPath, true))
|
|
@@ -14480,7 +14744,7 @@ function calleeImportedFromModelFile(callee, path, lines, modelFiles) {
|
|
|
14480
14744
|
const base = callee.split(".")[0];
|
|
14481
14745
|
const text = lines.join(`
|
|
14482
14746
|
`);
|
|
14483
|
-
const python =
|
|
14747
|
+
const python = extname8(path) === ".py";
|
|
14484
14748
|
const statements = python ? [/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm] : [
|
|
14485
14749
|
/\bimport\s+(?:type\s+)?(?:([A-Za-z_$][\w$]*)\s*,?\s*)?(?:\{([^}]*)\}|\*\s*as\s+([A-Za-z_$][\w$]*))?\s*from\s*["']([^"']+)["']/g,
|
|
14486
14750
|
/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(?:await\s+)?(?:require|import)\(\s*["']([^"']+)["']\s*\)/g
|
|
@@ -14703,7 +14967,7 @@ function hasNearbyRole(lines, line) {
|
|
|
14703
14967
|
return false;
|
|
14704
14968
|
}
|
|
14705
14969
|
function isDirectModelInput(key, value, path, lines, line, modelFiles) {
|
|
14706
|
-
if (CONFIG_EXTENSIONS.has(
|
|
14970
|
+
if (CONFIG_EXTENSIONS.has(extname8(path).toLowerCase())) {
|
|
14707
14971
|
return DIRECT_PROMPT_KEYS.has(key) && value.length >= MIN_CONFIG_PROMPT_CHARS;
|
|
14708
14972
|
}
|
|
14709
14973
|
if (modelFiles.has(path)) {
|
|
@@ -14743,7 +15007,7 @@ function fileReachesModel(path, lines, modelFiles) {
|
|
|
14743
15007
|
return true;
|
|
14744
15008
|
if (lines.some((line) => MODEL_ENDPOINT.test(line)))
|
|
14745
15009
|
return true;
|
|
14746
|
-
const python =
|
|
15010
|
+
const python = extname8(path) === ".py";
|
|
14747
15011
|
return importSpecifiers(lines).some((spec) => [...modelFiles].some((modelFile) => specifierResolvesTo(spec, path, modelFile, python)));
|
|
14748
15012
|
}
|
|
14749
15013
|
function modelFileImports(path, rootDir, modelFiles, fileCache) {
|
|
@@ -14751,7 +15015,7 @@ function modelFileImports(path, rootDir, modelFiles, fileCache) {
|
|
|
14751
15015
|
if (modelFile === path)
|
|
14752
15016
|
return false;
|
|
14753
15017
|
const lines = readFileLines(rootDir, modelFile, fileCache);
|
|
14754
|
-
return Boolean(lines && importSpecifiers(lines).some((spec) => specifierResolvesTo(spec, modelFile, path,
|
|
15018
|
+
return Boolean(lines && importSpecifiers(lines).some((spec) => specifierResolvesTo(spec, modelFile, path, extname8(modelFile) === ".py")));
|
|
14755
15019
|
});
|
|
14756
15020
|
}
|
|
14757
15021
|
var PASS_THROUGH_CALLEE = /^(?:Object\.(?:freeze|seal|assign)|structuredClone|Promise\.resolve|JSON\.stringify|(?:_\.|lodash\.)?(?:cloneDeep|clone|merge)|deepFreeze|defu)$/;
|
|
@@ -14821,7 +15085,7 @@ function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCach
|
|
|
14821
15085
|
use = { path: candidate.path, line: definition.line, key: "system-injection" };
|
|
14822
15086
|
}
|
|
14823
15087
|
const jsSource = jsSources.get(`${rootDir}::${candidate.path}`);
|
|
14824
|
-
if (!use && definition.key && !PROMPT_CONFIG_KEYS.has(definition.key) && !CONFIG_EXTENSIONS.has(
|
|
15088
|
+
if (!use && definition.key && !PROMPT_CONFIG_KEYS.has(definition.key) && !CONFIG_EXTENSIONS.has(extname8(candidate.path).toLowerCase())) {
|
|
14825
15089
|
const exportUsed = () => modelFileImports(candidate.path, rootDir, files.model, fileCache);
|
|
14826
15090
|
if (jsSource) {
|
|
14827
15091
|
const consumer = keyedValueConsumer(jsSource, definition.line, definition.key, definition.column);
|
|
@@ -14871,63 +15135,248 @@ function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCach
|
|
|
14871
15135
|
body: definition.text
|
|
14872
15136
|
};
|
|
14873
15137
|
}
|
|
14874
|
-
|
|
14875
|
-
|
|
14876
|
-
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14880
|
-
|
|
14881
|
-
|
|
14882
|
-
|
|
14883
|
-
|
|
14884
|
-
|
|
14885
|
-
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
|
|
14889
|
-
|
|
14890
|
-
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
|
|
14895
|
-
|
|
14896
|
-
|
|
14897
|
-
|
|
14898
|
-
|
|
15138
|
+
var ALIAS_KEY_SAME_LINE = /^\s*:\s*\{[^}]*?["']?\b(?:model|model_name|model_id|modelName|modelId|[A-Z_]*MODEL[A-Z_]*)["']?\s*[:=]/i;
|
|
15139
|
+
var BLOCK_KEY = /^\s*:\s*\{\s*$/;
|
|
15140
|
+
var MODEL_FIELD = /["']?\b(?:model|model_name|model_id|modelName|modelId|[A-Z_]*MODEL[A-Z_]*)["']?\s*[:=]\s*["'`]/i;
|
|
15141
|
+
var ASSIGNED_FIELD = /([A-Za-z_$][\w$]*)["']?\s*[:=]\s*(?:[A-Za-z_$][\w$.()]*\(\s*)?$/;
|
|
15142
|
+
var COMPARED_BEFORE = /(?:\.(?:startsWith|endsWith|includes|indexOf|match|test)\(\s*|[!=]==?\s*|\bcase\s+|[\w$\])]\[\s*)$/;
|
|
15143
|
+
var COMPARED_AFTER = /^\s*[!=]==?/;
|
|
15144
|
+
function isComparedLiteral(sourceLine, literal) {
|
|
15145
|
+
return COMPARED_BEFORE.test(sourceLine.slice(0, literal.index)) || COMPARED_AFTER.test(sourceLine.slice(literal.end));
|
|
15146
|
+
}
|
|
15147
|
+
var ALIAS_BLOCK_MAX_LINES = 200;
|
|
15148
|
+
function isModelAliasKey(lines, row, literal, path = "") {
|
|
15149
|
+
const after = lines[row].slice(literal.end);
|
|
15150
|
+
if (ALIAS_KEY_SAME_LINE.test(after))
|
|
15151
|
+
return true;
|
|
15152
|
+
const separator = /^\s*:\s*/.exec(after);
|
|
15153
|
+
if (separator && modelIdLiteralsAt(lines, path, row).some((other) => other.index === literal.end + separator[0].length))
|
|
15154
|
+
return true;
|
|
15155
|
+
if (!BLOCK_KEY.test(after))
|
|
15156
|
+
return false;
|
|
15157
|
+
let depth = 1;
|
|
15158
|
+
for (const next of lines.slice(row + 1, row + 1 + ALIAS_BLOCK_MAX_LINES)) {
|
|
15159
|
+
if (depth === 1 && MODEL_FIELD.test(next))
|
|
15160
|
+
return true;
|
|
15161
|
+
for (const ch of next) {
|
|
15162
|
+
if (ch === "{")
|
|
15163
|
+
depth += 1;
|
|
15164
|
+
else if (ch === "}")
|
|
15165
|
+
depth -= 1;
|
|
15166
|
+
}
|
|
15167
|
+
if (depth <= 0)
|
|
15168
|
+
return false;
|
|
15169
|
+
}
|
|
15170
|
+
return false;
|
|
14899
15171
|
}
|
|
14900
|
-
var
|
|
14901
|
-
|
|
14902
|
-
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
15172
|
+
var lineLiterals = new WeakMap;
|
|
15173
|
+
function modelIdLiteralsAt(lines, path, row) {
|
|
15174
|
+
let literals = lineLiterals.get(lines);
|
|
15175
|
+
if (!literals) {
|
|
15176
|
+
literals = modelIdLiteralsInLines(lines, path);
|
|
15177
|
+
lineLiterals.set(lines, literals);
|
|
15178
|
+
}
|
|
15179
|
+
return literals[row] ?? [];
|
|
15180
|
+
}
|
|
15181
|
+
function modelIdsOnCandidateLine(candidate, lines) {
|
|
15182
|
+
const rows = lines ?? [];
|
|
15183
|
+
const row = candidate.startLine - 1;
|
|
15184
|
+
const sourceLine = rows[row] ?? "";
|
|
15185
|
+
const ids = [];
|
|
15186
|
+
const literals = modelIdLiteralsAt(rows, candidate.path, row);
|
|
15187
|
+
const isAliasKey = (value) => literals.some((literal) => literal.value === value && isModelAliasKey(rows, row, literal, candidate.path));
|
|
15188
|
+
if (candidate.signal !== "model.id_literal") {
|
|
15189
|
+
const assignment = MODEL_ASSIGNMENT_VALUE.exec(sourceLine);
|
|
15190
|
+
const [field, assigned] = [assignment?.[1], assignment?.[2]];
|
|
15191
|
+
const preferenceOnly = Boolean(field && MODEL_PREFERENCE_FIELD.test(field) && !FULL_MODEL_ID.test(assigned ?? ""));
|
|
15192
|
+
const registryKey = candidate.signal === "model.registry_key" ? REGISTRY_KEY.exec(sourceLine)?.[1] : undefined;
|
|
15193
|
+
const primary = preferenceOnly ? undefined : (assigned && MODEL_STRING.exec(assigned)?.[1]) ?? registryKey ?? MODEL_STRING.exec(sourceLine)?.[1] ?? MODEL_STRING.exec(candidate.excerpt)?.[1];
|
|
15194
|
+
const compared = (value) => literals.some((literal) => literal.value === value && isComparedLiteral(sourceLine, literal));
|
|
15195
|
+
if (primary && !isAliasKey(primary) && !compared(primary))
|
|
15196
|
+
ids.push(primary);
|
|
15197
|
+
}
|
|
15198
|
+
for (const literal of literals) {
|
|
15199
|
+
const { value, index } = literal;
|
|
15200
|
+
if (ids.includes(value) || isModelAliasKey(rows, row, literal, candidate.path))
|
|
15201
|
+
continue;
|
|
15202
|
+
if (isComparedLiteral(sourceLine, literal))
|
|
15203
|
+
continue;
|
|
15204
|
+
const field = ASSIGNED_FIELD.exec(sourceLine.slice(0, index))?.[1];
|
|
15205
|
+
if (field && MODEL_PREFERENCE_FIELD.test(field) && !FULL_MODEL_ID.test(value))
|
|
15206
|
+
continue;
|
|
15207
|
+
ids.push(value);
|
|
14910
15208
|
}
|
|
14911
|
-
|
|
14912
|
-
|
|
15209
|
+
return ids.filter((id) => !MODEL_FAMILY_ALIAS.test(id.split("/").pop() ?? id));
|
|
15210
|
+
}
|
|
15211
|
+
var OTHER_TEST_PATH = /(?:^|\/)(?:e2e|testdata|__mocks__|spec)\/|\.stories\.[^/.]+$|(?:^|\/)(?:test_[^/]*|[^/]*_test|conftest)\.py$/i;
|
|
15212
|
+
var NON_SOURCE_DIR = /(^|\/)(?:docs?|\.moda)\//i;
|
|
15213
|
+
var EMPTY_MODEL_PATH_CONTEXT = { productionScripts: new Set, rewritingPackages: new Set };
|
|
15214
|
+
function isHarnessModelPath(path, context = EMPTY_MODEL_PATH_CONTEXT) {
|
|
15215
|
+
if (NON_SOURCE_DIR.test(path))
|
|
15216
|
+
return false;
|
|
15217
|
+
if (isEvalModelSource(path))
|
|
15218
|
+
return true;
|
|
15219
|
+
if (SCRIPTS_DIR.test(path) && !isUnderAny(path, context.productionScripts))
|
|
15220
|
+
return false;
|
|
15221
|
+
if (isUnderAny(path, context.rewritingPackages) && !SERVER_SIDE_PATH.test(path))
|
|
15222
|
+
return false;
|
|
15223
|
+
return evalDirectoryIndex(path) < 0 && !TEST_PATH2.test(path) && !OTHER_TEST_PATH.test(path);
|
|
15224
|
+
}
|
|
15225
|
+
function modelPathContext(rootDir) {
|
|
15226
|
+
return { productionScripts: productionScriptPaths(rootDir), rewritingPackages: modelRewritingPackages(rootDir) };
|
|
15227
|
+
}
|
|
15228
|
+
var SERVER_SIDE_PATH = /(?:^|\/)(?:server|host|api)\/|[.+]server\.[cm]?[jt]s$/;
|
|
15229
|
+
var MODEL_REWRITE_CALL = /\bmodel\s*[:=]\s*[a-z]\w*\(\s*(?:\w+\.)*(?:requested\w*|\w*[mM]odel\w*)\s*,/;
|
|
15230
|
+
var REWRITE_SOURCE_FILE = /\.(?:[cm]?[jt]sx?|svelte|vue|py)$/i;
|
|
15231
|
+
var modelRewriteCache = new Map;
|
|
15232
|
+
function modelRewritingPackages(rootDir) {
|
|
15233
|
+
const root = resolve9(rootDir);
|
|
15234
|
+
const cached = modelRewriteCache.get(root);
|
|
15235
|
+
if (cached)
|
|
14913
15236
|
return cached;
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
15237
|
+
const packageRoots = new Set;
|
|
15238
|
+
const sources = [];
|
|
15239
|
+
walkRepo(root, (path, name) => {
|
|
15240
|
+
if (name === "package.json" || name === "pyproject.toml")
|
|
15241
|
+
packageRoots.add(posix.dirname(path));
|
|
15242
|
+
else if (REWRITE_SOURCE_FILE.test(name))
|
|
15243
|
+
sources.push(path);
|
|
15244
|
+
});
|
|
15245
|
+
const found = new Set;
|
|
15246
|
+
for (const path of sources) {
|
|
15247
|
+
let dir = posix.dirname(path);
|
|
15248
|
+
while (dir !== "." && !packageRoots.has(dir))
|
|
15249
|
+
dir = posix.dirname(dir);
|
|
15250
|
+
if (dir === "." || found.has(dir))
|
|
15251
|
+
continue;
|
|
15252
|
+
let text;
|
|
15253
|
+
try {
|
|
15254
|
+
if (statSync3(resolve9(root, path)).size > 512 * 1024)
|
|
15255
|
+
continue;
|
|
15256
|
+
text = readFileSync11(resolve9(root, path), "utf8");
|
|
15257
|
+
} catch {
|
|
15258
|
+
continue;
|
|
15259
|
+
}
|
|
15260
|
+
if (MODEL_REWRITE_CALL.test(text))
|
|
15261
|
+
found.add(dir);
|
|
14918
15262
|
}
|
|
14919
|
-
|
|
15263
|
+
modelRewriteCache.set(root, found);
|
|
15264
|
+
return found;
|
|
15265
|
+
}
|
|
15266
|
+
var MAX_REPO_SCAN_DEPTH = 8;
|
|
15267
|
+
function walkRepo(root, onFile) {
|
|
15268
|
+
const visit = (dir, depth) => {
|
|
15269
|
+
let entries;
|
|
14920
15270
|
try {
|
|
14921
|
-
|
|
14922
|
-
if (statSync3(absolute).size > MAX_MODEL_SOURCE_BYTES)
|
|
14923
|
-
return false;
|
|
14924
|
-
return readFileSync11(absolute, "utf8").includes(modelId);
|
|
15271
|
+
entries = readdirSync4(resolve9(root, dir), { withFileTypes: true });
|
|
14925
15272
|
} catch {
|
|
14926
|
-
return
|
|
15273
|
+
return;
|
|
14927
15274
|
}
|
|
15275
|
+
for (const entry of entries) {
|
|
15276
|
+
const path = dir ? `${dir}/${entry.name}` : entry.name;
|
|
15277
|
+
if (entry.isDirectory()) {
|
|
15278
|
+
if (depth < MAX_REPO_SCAN_DEPTH && !entry.name.startsWith(".") && entry.name !== "node_modules")
|
|
15279
|
+
visit(path, depth + 1);
|
|
15280
|
+
} else if (entry.isFile()) {
|
|
15281
|
+
onFile(path, entry.name);
|
|
15282
|
+
}
|
|
15283
|
+
}
|
|
15284
|
+
};
|
|
15285
|
+
visit("", 0);
|
|
15286
|
+
}
|
|
15287
|
+
function isUnderAny(path, prefixes) {
|
|
15288
|
+
for (const prefix of prefixes)
|
|
15289
|
+
if (path === prefix || path.startsWith(`${prefix}/`))
|
|
15290
|
+
return true;
|
|
15291
|
+
return false;
|
|
15292
|
+
}
|
|
15293
|
+
var SCRIPTS_DIR = /^scripts\//;
|
|
15294
|
+
var DEPLOY_CONFIG_FILE = /^(?:Dockerfile(?:\.[\w.-]+)?|[\w.-]+\.Dockerfile|Procfile|fly\.toml|wrangler(?:\.[\w-]+)?\.(?:toml|jsonc?)|docker-compose(?:\.[\w-]+)?\.ya?ml|compose\.ya?ml|render\.ya?ml|railway\.json|vercel\.json|app\.ya?ml|crontab)$/i;
|
|
15295
|
+
var DEPLOY_PACKAGE_SCRIPT = /^(?:start|serve|prod|deploy|cron|worker)(?:[:_-]|$)/i;
|
|
15296
|
+
var SCRIPT_REFERENCE = /(?:^|[\s"'`=(,./])(scripts\/[\w./-]*[\w-])/g;
|
|
15297
|
+
var COMMENT_LINE = /^\s*(?:#|\/\/|\/\*|\*)/;
|
|
15298
|
+
var productionScriptCache = new Map;
|
|
15299
|
+
function productionScriptPaths(rootDir) {
|
|
15300
|
+
const root = resolve9(rootDir);
|
|
15301
|
+
const cached = productionScriptCache.get(root);
|
|
15302
|
+
if (cached)
|
|
15303
|
+
return cached;
|
|
15304
|
+
const found = new Set;
|
|
15305
|
+
const addReferences = (text) => {
|
|
15306
|
+
for (const line of text.split(`
|
|
15307
|
+
`)) {
|
|
15308
|
+
if (COMMENT_LINE.test(line))
|
|
15309
|
+
continue;
|
|
15310
|
+
for (const match of line.matchAll(SCRIPT_REFERENCE))
|
|
15311
|
+
found.add(match[1].replace(/\/+$/, ""));
|
|
15312
|
+
}
|
|
15313
|
+
};
|
|
15314
|
+
walkRepo(root, (path, name) => {
|
|
15315
|
+
const isDeployConfig = DEPLOY_CONFIG_FILE.test(name);
|
|
15316
|
+
if (!isDeployConfig && name !== "package.json")
|
|
15317
|
+
return;
|
|
15318
|
+
const dir = posix.dirname(path);
|
|
15319
|
+
if (isDeployConfig && SCRIPTS_DIR.test(path))
|
|
15320
|
+
found.add(dir);
|
|
15321
|
+
let text;
|
|
15322
|
+
try {
|
|
15323
|
+
text = readFileSync11(resolve9(root, path), "utf8");
|
|
15324
|
+
} catch {
|
|
15325
|
+
return;
|
|
15326
|
+
}
|
|
15327
|
+
if (isDeployConfig) {
|
|
15328
|
+
addReferences(text);
|
|
15329
|
+
return;
|
|
15330
|
+
}
|
|
15331
|
+
try {
|
|
15332
|
+
const scripts = JSON.parse(text).scripts ?? {};
|
|
15333
|
+
for (const [scriptName, command] of Object.entries(scripts)) {
|
|
15334
|
+
if (DEPLOY_PACKAGE_SCRIPT.test(scriptName) && typeof command === "string")
|
|
15335
|
+
addReferences(command);
|
|
15336
|
+
}
|
|
15337
|
+
} catch {}
|
|
14928
15338
|
});
|
|
14929
|
-
|
|
14930
|
-
return
|
|
15339
|
+
productionScriptCache.set(root, found);
|
|
15340
|
+
return found;
|
|
15341
|
+
}
|
|
15342
|
+
var MAX_MODEL_EVIDENCE = 5;
|
|
15343
|
+
var MAX_EVAL_SUITE_FILES = 100;
|
|
15344
|
+
function capPromotedEvidence(artifact) {
|
|
15345
|
+
const max = artifact.type === "model_config" ? MAX_MODEL_EVIDENCE : artifact.type === "eval" ? MAX_EVAL_SUITE_FILES : undefined;
|
|
15346
|
+
if (max !== undefined && artifact.evidence.length > max)
|
|
15347
|
+
artifact.evidence = artifact.evidence.slice(0, max);
|
|
15348
|
+
}
|
|
15349
|
+
function distinctStableId(prefix, raw) {
|
|
15350
|
+
return `${stableId(prefix, raw.replace(/\./g, "-"))}_${createHash5("sha256").update(raw).digest("hex").slice(0, 8)}`;
|
|
15351
|
+
}
|
|
15352
|
+
function promoteModelIds(occurrences, context) {
|
|
15353
|
+
const out = [];
|
|
15354
|
+
for (const [key, { id, at }] of occurrences) {
|
|
15355
|
+
const inHarness = at.filter((entry) => isHarnessModelPath(entry.path, context));
|
|
15356
|
+
if (inHarness.length === 0)
|
|
15357
|
+
continue;
|
|
15358
|
+
const seen = new Set;
|
|
15359
|
+
const cited = [...inHarness, ...at.filter((entry) => !isHarnessModelPath(entry.path, context))].filter((entry) => {
|
|
15360
|
+
const key2 = `${entry.path}:${entry.line}`;
|
|
15361
|
+
if (seen.has(key2))
|
|
15362
|
+
return false;
|
|
15363
|
+
seen.add(key2);
|
|
15364
|
+
return true;
|
|
15365
|
+
});
|
|
15366
|
+
const first2 = cited[0];
|
|
15367
|
+
const what = SIGNAL_DESCRIPTIONS[first2.signal] ?? `the ${first2.signal} pattern`;
|
|
15368
|
+
out.push({
|
|
15369
|
+
id: distinctStableId("model_config", key),
|
|
15370
|
+
type: "model_config",
|
|
15371
|
+
name: id,
|
|
15372
|
+
scope: "shared",
|
|
15373
|
+
usedByAgentIds: [],
|
|
15374
|
+
confidence: Math.max(...cited.map((entry) => entry.confidence)),
|
|
15375
|
+
confidenceReason: `Deterministic: model id ${id} found by ${what} at ${first2.path}:${first2.line} (${inHarness.length} harness occurrence${inHarness.length === 1 ? "" : "s"}); not checked by the analyst.`,
|
|
15376
|
+
evidence: cited.map((entry) => ({ path: entry.path, line: entry.line, reason: `deterministic detector ${entry.signal}` }))
|
|
15377
|
+
});
|
|
15378
|
+
}
|
|
15379
|
+
return out;
|
|
14931
15380
|
}
|
|
14932
15381
|
function mergePromotedDuplicate(existing, next) {
|
|
14933
15382
|
for (const entry of next.evidence) {
|
|
@@ -14939,10 +15388,16 @@ function mergePromotedDuplicate(existing, next) {
|
|
|
14939
15388
|
if (!existing.body && next.body)
|
|
14940
15389
|
existing.body = next.body;
|
|
14941
15390
|
}
|
|
14942
|
-
function promoteHarnessCandidates(report, rootDir) {
|
|
15391
|
+
function promoteHarnessCandidates(report, rootDir, options = {}) {
|
|
14943
15392
|
jsSources.clear();
|
|
15393
|
+
productionScriptCache.clear();
|
|
15394
|
+
modelRewriteCache.clear();
|
|
14944
15395
|
try {
|
|
14945
|
-
|
|
15396
|
+
const artifacts = promoteAll(report, rootDir);
|
|
15397
|
+
if (!options.fullEvidence)
|
|
15398
|
+
for (const artifact of artifacts)
|
|
15399
|
+
capPromotedEvidence(artifact);
|
|
15400
|
+
return artifacts;
|
|
14946
15401
|
} finally {
|
|
14947
15402
|
jsSources.clear();
|
|
14948
15403
|
}
|
|
@@ -14954,6 +15409,15 @@ function promoteAll(report, rootDir) {
|
|
|
14954
15409
|
model: new Set(report.candidates.filter((candidate) => candidate.kind === "llm_call_site" || candidate.kind === "framework_construct").map((candidate) => candidate.path)),
|
|
14955
15410
|
searchable: new Set(report.files.map((file) => file.path))
|
|
14956
15411
|
};
|
|
15412
|
+
const modelIds = new Map;
|
|
15413
|
+
const evalFiles = [];
|
|
15414
|
+
const add = (artifact) => {
|
|
15415
|
+
const existing = byId.get(artifact.id);
|
|
15416
|
+
if (existing)
|
|
15417
|
+
mergePromotedDuplicate(existing, artifact);
|
|
15418
|
+
else
|
|
15419
|
+
byId.set(artifact.id, artifact);
|
|
15420
|
+
};
|
|
14957
15421
|
for (const candidate of report.candidates) {
|
|
14958
15422
|
const confidence2 = PROMOTED_CONFIDENCE[candidate.confidence];
|
|
14959
15423
|
if (confidence2 === undefined)
|
|
@@ -14977,20 +15441,32 @@ function promoteAll(report, rootDir) {
|
|
|
14977
15441
|
break;
|
|
14978
15442
|
case "model_config":
|
|
14979
15443
|
if (candidate.confidence === "high") {
|
|
14980
|
-
|
|
15444
|
+
for (const id of modelIdsOnCandidateLine(candidate, readFileLines(rootDir, candidate.path, fileCache))) {
|
|
15445
|
+
const key = id.toLowerCase();
|
|
15446
|
+
const entry = modelIds.get(key) ?? { id, at: [] };
|
|
15447
|
+
entry.at.push({ path: candidate.path, line: candidate.startLine, signal: candidate.signal, confidence: confidence2 });
|
|
15448
|
+
modelIds.set(key, entry);
|
|
15449
|
+
}
|
|
14981
15450
|
}
|
|
14982
15451
|
break;
|
|
15452
|
+
case "eval_file":
|
|
15453
|
+
if (candidate.confidence === "high")
|
|
15454
|
+
evalFiles.push(candidate);
|
|
15455
|
+
break;
|
|
14983
15456
|
default:
|
|
14984
15457
|
break;
|
|
14985
15458
|
}
|
|
14986
15459
|
if (!artifact)
|
|
14987
15460
|
continue;
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
|
|
14991
|
-
|
|
14992
|
-
|
|
14993
|
-
|
|
15461
|
+
add(artifact);
|
|
15462
|
+
}
|
|
15463
|
+
for (const artifact of promoteModelIds(modelIds, modelPathContext(rootDir)))
|
|
15464
|
+
add(artifact);
|
|
15465
|
+
for (const artifact of promoteEvalSuites(evalFiles, PROMOTED_CONFIDENCE.high, {
|
|
15466
|
+
artifactId: (suiteKey) => distinctStableId("eval", suiteKey),
|
|
15467
|
+
fileReason: detectorConfidenceReason
|
|
15468
|
+
}))
|
|
15469
|
+
add(artifact);
|
|
14994
15470
|
return [...byId.values()];
|
|
14995
15471
|
}
|
|
14996
15472
|
|
|
@@ -15325,7 +15801,7 @@ async function runHarnessCommand(context) {
|
|
|
15325
15801
|
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.");
|
|
15326
15802
|
}
|
|
15327
15803
|
if (context.flags["github-actions"] === "true") {
|
|
15328
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
15804
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-bgfnh4tw.js");
|
|
15329
15805
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
15330
15806
|
writeReport: (report2) => {
|
|
15331
15807
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -15496,6 +15972,14 @@ async function runHarnessCommand(context) {
|
|
|
15496
15972
|
context.output.writeData({ scanPlan, ...report, written, dryRun: context.dryRun });
|
|
15497
15973
|
return { exitCode: 0 };
|
|
15498
15974
|
}
|
|
15975
|
+
case "extract": {
|
|
15976
|
+
writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
|
|
15977
|
+
const { extractHarness, serializeExtractResult } = await import("./index-gtqxj0fp.js");
|
|
15978
|
+
const result = extractHarness(rootDir, { fresh: true });
|
|
15979
|
+
writeHumanProgress(context, `Harness extract: ${result.callSites.length} call sites, ${result.roles.length} traced roles across ${result.files} files (${result.programs} programs, ${result.durationMs.toLocaleString()} ms).`);
|
|
15980
|
+
context.output.writeData(serializeExtractResult(result));
|
|
15981
|
+
return { exitCode: 0 };
|
|
15982
|
+
}
|
|
15499
15983
|
case "agents": {
|
|
15500
15984
|
const graph = loadOrScanHarness(rootDir, tenant, context);
|
|
15501
15985
|
context.output.writeData({
|
|
@@ -15614,7 +16098,7 @@ async function runHarnessCommand(context) {
|
|
|
15614
16098
|
return { exitCode: 0 };
|
|
15615
16099
|
}
|
|
15616
16100
|
default:
|
|
15617
|
-
throw new CliInputError(`Unknown harness command '${subcommand}'.`, "Usage: moda harness analyze|pull|validate-report|approve|scan|candidates|sync|delete|list|show|versions|diff|agents|graph|explain|write-summary|status|register|registration");
|
|
16101
|
+
throw new CliInputError(`Unknown harness command '${subcommand}'.`, "Usage: moda harness analyze|pull|validate-report|approve|scan|candidates|extract|sync|delete|list|show|versions|diff|agents|graph|explain|write-summary|status|register|registration");
|
|
15618
16102
|
}
|
|
15619
16103
|
}
|
|
15620
16104
|
function writeHarnessAnalyzeResult(context, payload) {
|
|
@@ -16012,7 +16496,7 @@ function isToolGroupPlaceholder(name) {
|
|
|
16012
16496
|
function isDetectedToolDefinitionReason(reason) {
|
|
16013
16497
|
return typeof reason === "string" && (reason.startsWith("deterministic detector ") || reason.startsWith("Tool definition detected"));
|
|
16014
16498
|
}
|
|
16015
|
-
var
|
|
16499
|
+
var MODEL_SOURCE_FILE = /\.(?:[cm]?[jt]sx?|py|json|jsonc|ya?ml|toml)$/i;
|
|
16016
16500
|
var NON_SOURCE_DIR2 = /(^|\/)(?:docs?|\.moda)\//i;
|
|
16017
16501
|
function isSearchableModelId(id) {
|
|
16018
16502
|
return id.length >= 4 && !/\s/.test(id) && /[\d/.:_-]/.test(id);
|
|
@@ -16060,7 +16544,7 @@ function modelIdsUsedInSource(rootDir, ids) {
|
|
|
16060
16544
|
return true;
|
|
16061
16545
|
let entries;
|
|
16062
16546
|
try {
|
|
16063
|
-
entries =
|
|
16547
|
+
entries = readdirSync5(current).sort();
|
|
16064
16548
|
} catch {
|
|
16065
16549
|
return true;
|
|
16066
16550
|
}
|
|
@@ -16072,7 +16556,7 @@ function modelIdsUsedInSource(rootDir, ids) {
|
|
|
16072
16556
|
}
|
|
16073
16557
|
if (!stat.isFile() || stat.size > MAX_SCANNED_FILE_BYTES || isSecretishPath(rel2))
|
|
16074
16558
|
return true;
|
|
16075
|
-
if (TEST_PATH2.test(rel2) || !
|
|
16559
|
+
if (TEST_PATH2.test(rel2) || !MODEL_SOURCE_FILE.test(rel2))
|
|
16076
16560
|
return true;
|
|
16077
16561
|
if (files >= maxFiles) {
|
|
16078
16562
|
complete = false;
|
|
@@ -16259,7 +16743,7 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
|
|
|
16259
16743
|
topology: new Set,
|
|
16260
16744
|
tools: new Set(["tool"]),
|
|
16261
16745
|
prompts: new Set(["prompt"]),
|
|
16262
|
-
evals: new Set(["model_config"])
|
|
16746
|
+
evals: new Set(["model_config", "eval"])
|
|
16263
16747
|
};
|
|
16264
16748
|
function deterministicArtifacts(rootDir, concern) {
|
|
16265
16749
|
const graph = { artifacts: [], unknowns: [] };
|
|
@@ -16275,21 +16759,43 @@ function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
|
|
|
16275
16759
|
const allowedTypes = options.concern ? CONCERN_PROMOTED_ARTIFACT_TYPES[options.concern] : undefined;
|
|
16276
16760
|
let promoted;
|
|
16277
16761
|
try {
|
|
16278
|
-
promoted = promoteHarnessCandidates(detectHarnessCandidates(rootDir), rootDir);
|
|
16762
|
+
promoted = promoteHarnessCandidates(detectHarnessCandidates(rootDir), rootDir, { fullEvidence: true });
|
|
16279
16763
|
} catch {
|
|
16280
16764
|
return { added: 0 };
|
|
16281
16765
|
}
|
|
16282
16766
|
backfillRefutationEvidenceReasons(graph);
|
|
16283
16767
|
const refuted = analystRefutations(graph);
|
|
16284
16768
|
const candidatePaths = new Set(promoted.flatMap((artifact) => artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath2(entry.path) : "").filter(Boolean)));
|
|
16769
|
+
const modelLineCounts = new Map;
|
|
16770
|
+
for (const artifact of promoted) {
|
|
16771
|
+
if (artifact.type !== "model_config")
|
|
16772
|
+
continue;
|
|
16773
|
+
for (const entry of artifact.evidence) {
|
|
16774
|
+
const key = `${entry.path}:${entry.line}`;
|
|
16775
|
+
modelLineCounts.set(key, (modelLineCounts.get(key) ?? 0) + 1);
|
|
16776
|
+
}
|
|
16777
|
+
}
|
|
16778
|
+
const sharedModelLines = new Set([...modelLineCounts].filter(([, count]) => count > 1).map(([key]) => key));
|
|
16779
|
+
const pathContext = modelPathContext(rootDir);
|
|
16285
16780
|
let added = 0;
|
|
16286
16781
|
for (const artifact of promoted) {
|
|
16287
16782
|
if (allowedTypes && !allowedTypes.has(artifact.type))
|
|
16288
16783
|
continue;
|
|
16289
|
-
if (graphCoversPromotedArtifact(graph, artifact))
|
|
16784
|
+
if (graphCoversPromotedArtifact(graph, artifact, sharedModelLines))
|
|
16290
16785
|
continue;
|
|
16786
|
+
if ((artifact.type === "model_config" || artifact.type === "eval") && artifact.evidence.length > 1 && !refuted.candidateIds.has(artifact.id)) {
|
|
16787
|
+
const kept = artifact.evidence.filter((entry) => !isRefutedByAnalyst({ ...artifact, evidence: [entry] }, refuted, candidatePaths));
|
|
16788
|
+
if (kept.length === 0)
|
|
16789
|
+
continue;
|
|
16790
|
+
if (artifact.type === "model_config" && !kept.some((entry) => isHarnessModelPath(entry.path, pathContext)))
|
|
16791
|
+
continue;
|
|
16792
|
+
artifact.evidence = kept;
|
|
16793
|
+
if (artifact.sourcePath && !kept.some((entry) => entry.path === artifact.sourcePath))
|
|
16794
|
+
artifact.sourcePath = kept[0].path;
|
|
16795
|
+
}
|
|
16291
16796
|
if (isRefutedByAnalyst(artifact, refuted, candidatePaths))
|
|
16292
16797
|
continue;
|
|
16798
|
+
capPromotedEvidence(artifact);
|
|
16293
16799
|
graph.artifacts.push(artifact);
|
|
16294
16800
|
added += 1;
|
|
16295
16801
|
}
|
|
@@ -16312,12 +16818,13 @@ var DETECTOR_ARTIFACT_TYPES = {
|
|
|
16312
16818
|
message_construction: "prompt",
|
|
16313
16819
|
tool_definition: "tool",
|
|
16314
16820
|
tool_schema: "tool",
|
|
16315
|
-
model_config: "model_config"
|
|
16821
|
+
model_config: "model_config",
|
|
16822
|
+
eval_file: "eval"
|
|
16316
16823
|
};
|
|
16317
16824
|
function refutedTypes(...texts) {
|
|
16318
16825
|
const types = new Set;
|
|
16319
16826
|
for (const text of texts) {
|
|
16320
|
-
for (const match of String(text ?? "").matchAll(/\b(prompt_literal|prompt_file|message_construction|tool_definition|tool_schema|model_config)\b/g)) {
|
|
16827
|
+
for (const match of String(text ?? "").matchAll(/\b(prompt_literal|prompt_file|message_construction|tool_definition|tool_schema|model_config|eval_file)\b/g)) {
|
|
16321
16828
|
types.add(DETECTOR_ARTIFACT_TYPES[match[1]]);
|
|
16322
16829
|
}
|
|
16323
16830
|
}
|
|
@@ -16379,7 +16886,26 @@ function artifactSourceKey(artifact) {
|
|
|
16379
16886
|
const pinned = Array.isArray(artifact.evidence) ? artifact.evidence.find((entry) => typeof entry.path === "string" && entry.path.length > 0) : undefined;
|
|
16380
16887
|
return pinned ? normalizePath2(pinned.path) : undefined;
|
|
16381
16888
|
}
|
|
16382
|
-
function
|
|
16889
|
+
function mentionsModelId(text, id) {
|
|
16890
|
+
if (!id)
|
|
16891
|
+
return false;
|
|
16892
|
+
const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
16893
|
+
return new RegExp(`(?<![\\w./@-])${escaped}(?![\\w/-]|\\.\\w)`, "i").test(text);
|
|
16894
|
+
}
|
|
16895
|
+
function artifactPaths(artifact) {
|
|
16896
|
+
const paths = Array.isArray(artifact.evidence) ? artifact.evidence.map((entry) => typeof entry.path === "string" ? normalizePath2(entry.path) : "").filter(Boolean) : [];
|
|
16897
|
+
return artifact.sourcePath ? [normalizePath2(artifact.sourcePath), ...paths] : paths;
|
|
16898
|
+
}
|
|
16899
|
+
function graphCoversPromotedArtifact(graph, promoted, sharedModelLines = new Set) {
|
|
16900
|
+
if (promoted.type === "model_config" && graph.artifacts.some((existing) => existing.type === "model_config" && mentionsModelId(`${existing.name ?? ""}
|
|
16901
|
+
${existing.body ?? ""}`, promoted.name)))
|
|
16902
|
+
return true;
|
|
16903
|
+
if (promoted.type === "eval") {
|
|
16904
|
+
const suite = new Set(artifactPaths(promoted));
|
|
16905
|
+
const suiteKey = promoted.sourcePath ? evalSuiteKey(normalizePath2(promoted.sourcePath)) : undefined;
|
|
16906
|
+
if (graph.artifacts.some((existing) => existing.type === "eval" && artifactPaths(existing).some((path) => suite.has(path) || suiteKey !== undefined && evalSuiteKey(path.replace(/\/+$/, "")) === suiteKey)))
|
|
16907
|
+
return true;
|
|
16908
|
+
}
|
|
16383
16909
|
const promotedName = promoted.name.toLowerCase();
|
|
16384
16910
|
const isDefinitionLine = (entry) => typeof entry.line === "number" && !/^(?:passed to a model call|prompt-named literal referenced)/.test(entry.reason ?? "");
|
|
16385
16911
|
const promotedLines = promoted.evidence.filter(isDefinitionLine);
|
|
@@ -16395,7 +16921,7 @@ function graphCoversPromotedArtifact(graph, promoted) {
|
|
|
16395
16921
|
if (!existingSource || !promotedSource || existingSource === promotedSource && !distinctInline)
|
|
16396
16922
|
return true;
|
|
16397
16923
|
}
|
|
16398
|
-
if (existing.type === promoted.type && Array.isArray(existing.evidence) && existing.evidence.some((entry) => isDefinitionLine(entry) && promotedLines.some((line) => line.path === entry.path && line.line === entry.line))) {
|
|
16924
|
+
if (existing.type === promoted.type && !(promoted.type === "model_config" && isModelIdLiteral(existing.name ?? "")) && Array.isArray(existing.evidence) && existing.evidence.some((entry) => isDefinitionLine(entry) && !(promoted.type === "model_config" && sharedModelLines.has(`${entry.path}:${entry.line}`)) && promotedLines.some((line) => line.path === entry.path && line.line === entry.line))) {
|
|
16399
16925
|
return true;
|
|
16400
16926
|
}
|
|
16401
16927
|
if (isWholeFilePrompt && existing.sourcePath === promoted.sourcePath)
|
|
@@ -17401,7 +17927,7 @@ var CONCERN_CANDIDATE_KINDS = {
|
|
|
17401
17927
|
topology: ["llm_call_site", "framework_construct"],
|
|
17402
17928
|
tools: ["tool_definition", "tool_schema"],
|
|
17403
17929
|
prompts: ["prompt_file", "prompt_literal", "message_construction"],
|
|
17404
|
-
evals: ["model_config"]
|
|
17930
|
+
evals: ["model_config", "eval_file"]
|
|
17405
17931
|
};
|
|
17406
17932
|
var MAX_SEED_CANDIDATES_PER_KIND = 40;
|
|
17407
17933
|
var MAX_INLINE_CANDIDATE_EXCERPT_CHARS = 500;
|
|
@@ -17414,7 +17940,8 @@ var SEED_CANDIDATE_KIND_LABELS = {
|
|
|
17414
17940
|
message_construction: "Message constructions",
|
|
17415
17941
|
prompt_file: "Prompt files",
|
|
17416
17942
|
prompt_literal: "Inline prompt literals",
|
|
17417
|
-
model_config: "Model configuration"
|
|
17943
|
+
model_config: "Model configuration",
|
|
17944
|
+
eval_file: "Eval suite files"
|
|
17418
17945
|
};
|
|
17419
17946
|
function renderAnalystCandidateLines(report, concern) {
|
|
17420
17947
|
const allowedKinds = concern ? new Set(CONCERN_CANDIDATE_KINDS[concern]) : undefined;
|
|
@@ -17435,7 +17962,7 @@ function renderAnalystCandidateLines(report, concern) {
|
|
|
17435
17962
|
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.'
|
|
17436
17963
|
];
|
|
17437
17964
|
if (concern === "evals") {
|
|
17438
|
-
lines.push("Note:
|
|
17965
|
+
lines.push("Note: guardrails and memory/retrieval stores have no deterministic detector — only model_config and eval_file candidates are seeded. Discover the rest by investigation.");
|
|
17439
17966
|
}
|
|
17440
17967
|
for (const [kind, label] of Object.entries(SEED_CANDIDATE_KIND_LABELS)) {
|
|
17441
17968
|
const bucket = byKind.get(kind);
|
|
@@ -17500,7 +18027,7 @@ function readDirectoryPreflightPaths(rootDir) {
|
|
|
17500
18027
|
const absolute = current === "." ? rootDir : join9(rootDir, current);
|
|
17501
18028
|
let entries;
|
|
17502
18029
|
try {
|
|
17503
|
-
entries =
|
|
18030
|
+
entries = readdirSync5(absolute);
|
|
17504
18031
|
} catch {
|
|
17505
18032
|
continue;
|
|
17506
18033
|
}
|
|
@@ -17536,7 +18063,7 @@ function shouldSkipPreflightPath(path) {
|
|
|
17536
18063
|
return isSecretishPath(normalized);
|
|
17537
18064
|
}
|
|
17538
18065
|
function isManifestLikePath(path) {
|
|
17539
|
-
const name =
|
|
18066
|
+
const name = basename7(path).toLowerCase();
|
|
17540
18067
|
return /^(package\.json|pyproject\.toml|requirements.*\.txt|uv\.lock|poetry\.lock|pnpm-lock\.yaml|bun\.lockb?|yarn\.lock|cargo\.toml|go\.mod|deno\.json|turbo\.json|langgraph\.json|agents\.json|config\.(ts|js|json|yaml|yml|toml))$/.test(name);
|
|
17541
18068
|
}
|
|
17542
18069
|
function isDocLikePath(path) {
|
|
@@ -17566,7 +18093,7 @@ function resolveAnalystCommand(adapter) {
|
|
|
17566
18093
|
return findOnPath("cursor-agent") || findOnPath("cursor-cli") || findOnPath("cursor") || findOnPath("/Applications/Cursor.app/Contents/Resources/app/bin/cursor");
|
|
17567
18094
|
}
|
|
17568
18095
|
function cursorSubcommandArgs(command, args) {
|
|
17569
|
-
const name =
|
|
18096
|
+
const name = basename7(command);
|
|
17570
18097
|
return name === "cursor" || name === "cursor-cli" ? ["agent", ...args] : args;
|
|
17571
18098
|
}
|
|
17572
18099
|
function findOnPath(command) {
|
|
@@ -17595,7 +18122,7 @@ function scanHarness(options = {}) {
|
|
|
17595
18122
|
const readPlan = buildHarnessReadPlan(rootDir, options.pathWasExplicit === true);
|
|
17596
18123
|
const graph = {
|
|
17597
18124
|
schemaVersion: SCHEMA_VERSION,
|
|
17598
|
-
harnessId: stableId("harness", repo.name ||
|
|
18125
|
+
harnessId: stableId("harness", repo.name || basename7(rootDir) || "repo"),
|
|
17599
18126
|
tenant: options.tenantId ? {
|
|
17600
18127
|
tenantId: options.tenantId,
|
|
17601
18128
|
source: options.tenantSource ?? "scan_option"
|
|
@@ -17666,7 +18193,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
|
|
|
17666
18193
|
if (stat.isDirectory()) {
|
|
17667
18194
|
if (path !== "." && (isSkippedDir(path) || isSkippedPathPrefix(path)))
|
|
17668
18195
|
return;
|
|
17669
|
-
for (const entry of
|
|
18196
|
+
for (const entry of readdirSync5(current).sort())
|
|
17670
18197
|
walk(join9(current, entry));
|
|
17671
18198
|
return;
|
|
17672
18199
|
}
|
|
@@ -18009,7 +18536,7 @@ function findFresherHarnessReports(rootDir) {
|
|
|
18009
18536
|
visited += 1;
|
|
18010
18537
|
let entries;
|
|
18011
18538
|
try {
|
|
18012
|
-
entries =
|
|
18539
|
+
entries = readdirSync5(dir, { withFileTypes: true });
|
|
18013
18540
|
} catch {
|
|
18014
18541
|
return;
|
|
18015
18542
|
}
|
|
@@ -18257,7 +18784,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
|
|
|
18257
18784
|
recordSkipped(skipped, { path: rel2, reason: "ignored directory" });
|
|
18258
18785
|
return;
|
|
18259
18786
|
}
|
|
18260
|
-
for (const entry of
|
|
18787
|
+
for (const entry of readdirSync5(current).sort()) {
|
|
18261
18788
|
walk(join9(current, entry));
|
|
18262
18789
|
}
|
|
18263
18790
|
return;
|
|
@@ -18344,7 +18871,7 @@ function numericEnvAllowZero(name, fallback) {
|
|
|
18344
18871
|
function detectRepo(rootDir, files) {
|
|
18345
18872
|
const packageJson = files.find((file) => file.path === "package.json");
|
|
18346
18873
|
const pyproject = files.find((file) => file.path === "pyproject.toml");
|
|
18347
|
-
const name = packageJson?.text ? safePackageName(packageJson.text) ??
|
|
18874
|
+
const name = packageJson?.text ? safePackageName(packageJson.text) ?? basename7(rootDir) : pyproject?.text ? safeTomlName(pyproject.text) ?? basename7(rootDir) : basename7(rootDir);
|
|
18348
18875
|
const packageManagers = [
|
|
18349
18876
|
files.some((file) => file.path === "bun.lock" || file.path === "bun.lockb") ? "bun" : null,
|
|
18350
18877
|
files.some((file) => file.path === "pnpm-lock.yaml") ? "pnpm" : null,
|
|
@@ -18618,7 +19145,7 @@ function maybeAddSkillArtifact(graph, file) {
|
|
|
18618
19145
|
upsertArtifact(graph, {
|
|
18619
19146
|
id: stableId("skill", file.path),
|
|
18620
19147
|
type: "skill",
|
|
18621
|
-
name: titleFromId(
|
|
19148
|
+
name: titleFromId(basename7(file.path).replace(/\.(md|mdc)$/i, "")),
|
|
18622
19149
|
scope: "global",
|
|
18623
19150
|
sourcePath: file.path,
|
|
18624
19151
|
contentHash: hashText(file.text ?? ""),
|
|
@@ -18661,7 +19188,7 @@ function inferRuntimeAgent(file, graph) {
|
|
|
18661
19188
|
return null;
|
|
18662
19189
|
if (!/\.(ts|tsx|js|mjs|py)$/i.test(file.path))
|
|
18663
19190
|
return null;
|
|
18664
|
-
if (
|
|
19191
|
+
if (basename7(file.path) === "__init__.py")
|
|
18665
19192
|
return null;
|
|
18666
19193
|
const loweredPath = file.path.toLowerCase();
|
|
18667
19194
|
const loweredText = file.text.toLowerCase();
|
|
@@ -18768,7 +19295,7 @@ function inferArtifactsForFile(file, graph) {
|
|
|
18768
19295
|
return false;
|
|
18769
19296
|
if (artifact.sourcePath === file.path)
|
|
18770
19297
|
return true;
|
|
18771
|
-
const base =
|
|
19298
|
+
const base = basename7(artifact.sourcePath);
|
|
18772
19299
|
if (text.includes(base) || text.includes(artifact.sourcePath))
|
|
18773
19300
|
return true;
|
|
18774
19301
|
if (artifact.type === "tool") {
|
|
@@ -19690,13 +20217,13 @@ function titleFromId(id) {
|
|
|
19690
20217
|
return id.replace(/^(agent|family|channel|prompt|tool|skill|eval|identity|deploy|entry|env)_/, "").split(/[_/.-]+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ") || id;
|
|
19691
20218
|
}
|
|
19692
20219
|
function promptNameFromPath(path) {
|
|
19693
|
-
return titleFromId(
|
|
20220
|
+
return titleFromId(basename7(path).replace(/\.(prompt\.)?(md|json|ya?ml)$/i, ""));
|
|
19694
20221
|
}
|
|
19695
20222
|
function normalizePath2(path) {
|
|
19696
20223
|
return path.split(sep5).join("/");
|
|
19697
20224
|
}
|
|
19698
20225
|
function hashText(text) {
|
|
19699
|
-
return
|
|
20226
|
+
return createHash6("sha256").update(text).digest("hex");
|
|
19700
20227
|
}
|
|
19701
20228
|
|
|
19702
20229
|
export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, resolveExternalHarnessAnalystInvocation, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, readOnlyClaudeExtraArgs, 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 };
|