@moda-ai/cli 1.28.5 → 1.28.6
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/{cli-g931ntph.js → cli-793dhrgb.js} +149 -13
- package/dist/{cli-x1a56ws9.js → cli-n5qz81m0.js} +1 -1
- package/dist/cli.js +8 -3
- package/dist/{harness-github-actions-ct8fwzdr.js → harness-github-actions-wd1ahhxz.js} +1 -1
- package/dist/{index-g3gt62rm.js → index-djg29jhz.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -3153,6 +3153,8 @@ async function runHarnessCommand(context) {
|
|
|
3153
3153
|
if (!approved && !context.dryRun) {
|
|
3154
3154
|
throw new CliInputError("Harness report is not approved; refusing to sync.", "Run `moda harness validate-report`, review the report, then run `moda harness approve --yes` before syncing.");
|
|
3155
3155
|
}
|
|
3156
|
+
if (!context.dryRun)
|
|
3157
|
+
assertHarnessGraphSyncQuality(report.graph, context.flags);
|
|
3156
3158
|
const syncGraph2 = graphForReport(report.graph);
|
|
3157
3159
|
const sourceCommit2 = report.source.sourceCommit ?? getGitCommit(rootDir);
|
|
3158
3160
|
const localGraphHash2 = hashStableJson(syncGraph2);
|
|
@@ -3233,6 +3235,8 @@ async function runHarnessCommand(context) {
|
|
|
3233
3235
|
tenantSource: tenant?.source,
|
|
3234
3236
|
pathWasExplicit: context.flags.path !== undefined
|
|
3235
3237
|
});
|
|
3238
|
+
if (!context.dryRun)
|
|
3239
|
+
assertHarnessGraphSyncQuality(graph, context.flags);
|
|
3236
3240
|
const syncGraph = graphForSync(graph);
|
|
3237
3241
|
const sourceCommit = getGitCommit(rootDir);
|
|
3238
3242
|
const localGraphHash = hashStableJson2(syncGraph);
|
|
@@ -3338,7 +3342,7 @@ async function runHarnessCommand(context) {
|
|
|
3338
3342
|
elapsed_ms: Date.now() - context.startedAt
|
|
3339
3343
|
});
|
|
3340
3344
|
if (context.flags["github-actions"] === "true") {
|
|
3341
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
3345
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-wd1ahhxz.js");
|
|
3342
3346
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
3343
3347
|
writeReport: (report2) => {
|
|
3344
3348
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -3669,7 +3673,7 @@ async function runExternalHarnessAnalyst(options) {
|
|
|
3669
3673
|
reportPath: HARNESS_REPORT_PATH
|
|
3670
3674
|
}));
|
|
3671
3675
|
}
|
|
3672
|
-
const timeoutMs = numericEnv("MODA_HARNESS_ANALYST_TIMEOUT_MS",
|
|
3676
|
+
const timeoutMs = numericEnv("MODA_HARNESS_ANALYST_TIMEOUT_MS", 1800000);
|
|
3673
3677
|
try {
|
|
3674
3678
|
const result = await runExternalAnalystWithRetries(invocation, {
|
|
3675
3679
|
cwd: options.rootDir,
|
|
@@ -3799,10 +3803,25 @@ function readExternalAnalystReport(rootDir, result, adapter) {
|
|
|
3799
3803
|
const parsed = extractHarnessReportFromText(output, rootDir);
|
|
3800
3804
|
if (parsed)
|
|
3801
3805
|
return parsed;
|
|
3806
|
+
let debugHint = "";
|
|
3807
|
+
try {
|
|
3808
|
+
const debugPath = resolve4(rootDir, MODA_DIR, "analyst-debug.log");
|
|
3809
|
+
mkdirSync3(dirname4(debugPath), { recursive: true });
|
|
3810
|
+
writeFileSync3(debugPath, [
|
|
3811
|
+
`# analyst=${adapter} status=${result.status} signal=${result.signal} timedOut=${result.timedOut} maxBufferExceeded=${result.maxBufferExceeded}`,
|
|
3812
|
+
"# ----- stdout -----",
|
|
3813
|
+
result.stdout,
|
|
3814
|
+
"# ----- stderr -----",
|
|
3815
|
+
result.stderr
|
|
3816
|
+
].join(`
|
|
3817
|
+
`));
|
|
3818
|
+
debugHint = `Raw analyst output saved to ${join2(MODA_DIR, "analyst-debug.log")} for debugging.`;
|
|
3819
|
+
} catch {}
|
|
3802
3820
|
throw new CliInputError(`Harness analyst ${adapter} did not return a harness report.`, [
|
|
3803
3821
|
`Expected ${HARNESS_REPORT_PATH} or final JSON between ${REPORT_JSON_BEGIN} and ${REPORT_JSON_END}.`,
|
|
3822
|
+
debugHint,
|
|
3804
3823
|
"Retry with the selected coding agent CLI fixed, choose another analyst, or run `moda harness analyze --analyst=local-scan --summary` for deterministic fallback."
|
|
3805
|
-
].join(`
|
|
3824
|
+
].filter(Boolean).join(`
|
|
3806
3825
|
`));
|
|
3807
3826
|
}
|
|
3808
3827
|
function extractHarnessReportFromText(output, rootDir) {
|
|
@@ -4112,7 +4131,7 @@ function isRetryableExternalAnalystFailure(result) {
|
|
|
4112
4131
|
return false;
|
|
4113
4132
|
const output = `${result.stdout}
|
|
4114
4133
|
${result.stderr}`;
|
|
4115
|
-
return /\b529\b|overloaded|server-side issue|temporar(?:y|ily)|try again|rate limit|too many requests
|
|
4134
|
+
return /\b529\b|\b429\b|\b5(?:00|02|03|04)\b|overloaded|server-side issue|temporar(?:y|ily)|try again|rate limit|too many requests|service unavailable|internal server error|connection (?:closed|reset|error)|mid-response|econnreset|econnrefused|etimedout|socket hang ?up|fetch failed|network error|stream (?:closed|disconnected|error)/i.test(output);
|
|
4116
4135
|
}
|
|
4117
4136
|
function externalAnalystMaxAttempts(adapter) {
|
|
4118
4137
|
const defaultRetries = adapter === "claude" ? 2 : 1;
|
|
@@ -4352,12 +4371,14 @@ function resolveExternalHarnessAnalystInvocation(options) {
|
|
|
4352
4371
|
}
|
|
4353
4372
|
if (options.adapter === "claude") {
|
|
4354
4373
|
const extraArgs = externalAnalystExtraArgs(options.adapter);
|
|
4355
|
-
const
|
|
4374
|
+
const model = resolveAnalystModel(options.adapter, options.flags);
|
|
4375
|
+
const permission = mode === "write" ? ["--permission-mode", "acceptEdits", "--allowedTools", "Read,Grep,Glob,Edit,Write,Bash"] : ["--allowedTools", `Read,Grep,Glob,Write(${HARNESS_REPORT_PATH}),Bash(pwd),Bash(ls *),Bash(find *),Bash(rg *),Bash(grep *),Bash(cat *),Bash(git status *),Bash(git ls-files *),Bash(git grep *)`];
|
|
4356
4376
|
return {
|
|
4357
4377
|
adapter: options.adapter,
|
|
4358
4378
|
command,
|
|
4359
4379
|
args: [
|
|
4360
4380
|
"--print",
|
|
4381
|
+
...model ? ["--model", model] : [],
|
|
4361
4382
|
...extraArgs,
|
|
4362
4383
|
...permission,
|
|
4363
4384
|
...options.stream ? ["--verbose"] : [],
|
|
@@ -4418,7 +4439,7 @@ async function runCodingAgent(options) {
|
|
|
4418
4439
|
stream,
|
|
4419
4440
|
mode: options.mode
|
|
4420
4441
|
});
|
|
4421
|
-
const timeoutMs = options.timeoutMs ?? numericEnv("MODA_HARNESS_ANALYST_TIMEOUT_MS",
|
|
4442
|
+
const timeoutMs = options.timeoutMs ?? numericEnv("MODA_HARNESS_ANALYST_TIMEOUT_MS", 1800000);
|
|
4422
4443
|
const result = await runExternalAnalystWithRetries(invocation, {
|
|
4423
4444
|
cwd: options.rootDir,
|
|
4424
4445
|
env: buildExternalAnalystEnv(options.env ?? process.env),
|
|
@@ -4447,24 +4468,34 @@ async function runCodingAgent(options) {
|
|
|
4447
4468
|
function externalAnalystExtraArgs(adapter) {
|
|
4448
4469
|
return splitCommandLine(process.env[`MODA_HARNESS_ANALYST_${adapter.toUpperCase()}_ARGS`] ?? "");
|
|
4449
4470
|
}
|
|
4471
|
+
var DEFAULT_CLAUDE_ANALYST_MODEL = "sonnet";
|
|
4472
|
+
function resolveAnalystModel(adapter, flags) {
|
|
4473
|
+
const flagValue = flags["analyst-model"] && flags["analyst-model"] !== "true" ? flags["analyst-model"] : undefined;
|
|
4474
|
+
const raw = (flagValue ?? process.env.MODA_HARNESS_ANALYST_MODEL)?.trim();
|
|
4475
|
+
if (raw?.toLowerCase() === "default")
|
|
4476
|
+
return;
|
|
4477
|
+
if (raw)
|
|
4478
|
+
return raw;
|
|
4479
|
+
return adapter === "claude" ? DEFAULT_CLAUDE_ANALYST_MODEL : undefined;
|
|
4480
|
+
}
|
|
4450
4481
|
function renderExternalHarnessAnalystPrompt(options) {
|
|
4451
4482
|
return [
|
|
4452
4483
|
"You are Moda Analyst, investigating an agent harness for Moda CLI onboarding.",
|
|
4453
4484
|
"",
|
|
4454
|
-
"Do real repository investigation. Do not call `moda harness scan
|
|
4485
|
+
"Do real repository investigation. Do not call `moda harness scan` or `moda harness analyze` yourself. When Moda provides deterministic scanner seeds below, treat them as navigation candidates to verify against the real files — never as evidence or as a complete inventory.",
|
|
4455
4486
|
"Only inspect the Repository root named below and files/directories under it. Do not inspect parent directories, sibling projects, the Moda CLI implementation, or this monorepo unless the Repository root itself is that directory.",
|
|
4456
4487
|
"Inspect package manifests, source files, prompt files, tool definitions, skills/rules, evals, deployment config, and README/AGENTS docs as needed.",
|
|
4457
4488
|
"Do not read secret-looking files such as .env files, private keys, credential files, or token stores.",
|
|
4458
4489
|
"You are running as a read-only analyst. Do not edit source files, configuration files, git state, dependency files, or project metadata.",
|
|
4459
|
-
|
|
4490
|
+
`The ONLY path you may write is ${HARNESS_REPORT_PATH}. Write the final report JSON there with the Write tool as soon as it is complete — the file is the durable deliverable and survives a dropped connection, unlike a long printed message. If (and only if) the write fails, print the report JSON between the sentinel markers instead.`,
|
|
4460
4491
|
"",
|
|
4461
4492
|
"Your task:",
|
|
4462
4493
|
renderExternalAnalystProtocol(),
|
|
4463
4494
|
"1. Identify the runtime agent harnesses, agent families, channel adapters, identity mappings, model providers, frameworks, deployments, and open questions.",
|
|
4464
4495
|
"2. Exhaustively enumerate EVERY prompt, tool, guardrail, and eval as its own graph artifact — the complete inventory, not a sample. This report feeds prompt optimization and tool optimization, so a missing tool or prompt is a real defect. Runtime agents may be modeled representatively on framework/example repos, but prompts and tools must be complete.",
|
|
4465
4496
|
"3. Cite every narrative claim with local file paths, exact line numbers, and excerpts. File citations without line numbers are invalid for agent-authored reports. Enumerated artifacts only need evidence:[{path, reason}], so completeness of the artifact inventory is not limited by the citation cap.",
|
|
4466
|
-
`4. After completing investigation, print the report JSON between ${REPORT_JSON_BEGIN} and ${REPORT_JSON_END}. Moda CLI
|
|
4467
|
-
"
|
|
4497
|
+
`4. After completing investigation, WRITE the report JSON to ${HARNESS_REPORT_PATH} with the Write tool, then print a one-line confirmation naming the file. Only if that write fails, print the report JSON between ${REPORT_JSON_BEGIN} and ${REPORT_JSON_END}. Moda CLI validates whichever it finds (the file wins).`,
|
|
4498
|
+
"Do not end with commentary about being read-only and do not summarize without delivering the report: either the written file or the sentinel-wrapped JSON must exist before you finish.",
|
|
4468
4499
|
"If the repository is very large, keep enumerating prompts/tools/guardrails/evals as artifacts (uncapped) and only summarize runtime AGENTS representatively — do not drop tools or prompts to save space.",
|
|
4469
4500
|
"",
|
|
4470
4501
|
"Final output format:",
|
|
@@ -4491,7 +4522,7 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4491
4522
|
"Each graph item with evidence must use evidence: [{ path, reason }], not citationIds/citations.",
|
|
4492
4523
|
'Runtime agents must include id, name, kind:"runtime_agent", root, entrypointIds, channelAdapterIds, artifactIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds, confidence, evidence.',
|
|
4493
4524
|
"Artifacts must include id, type, name, scope, usedByAgentIds, confidence, evidence, and optional sourcePath/contentHash/ownedByAgentId. Emit one artifact PER tool, PER prompt (including each inline system prompt), PER guardrail, and PER eval — enumerate them all; artifact types are entrypoint, prompt, tool, skill, eval, retrieval_index, memory, guardrail, model_config, unknown.",
|
|
4494
|
-
"
|
|
4525
|
+
"Do NOT transcribe prompt/tool text into `body` when it exists verbatim in the repo — pin its exact location instead (sourcePath for a dedicated file, or evidence [{ path, line, reason }] at the definition line) and Moda hydrates `body` locally from that location after validation. Set `body` inline ONLY for content that cannot be recovered from one pinned location: dynamically assembled prompts, fragments concatenated at runtime, or values you had to derive. Short bodies for `guardrail` (the rule), `eval` (what it asserts), and `model_config` (the config values) are still welcome. Redact any secret literals.",
|
|
4495
4526
|
"For every `prompt` and `tool` artifact, at least one evidence entry MUST pin an exact source location so downstream optimization can retrieve the item text: carry a numeric `line` (the definition line, or the first line of the range) — evidence: [{ path, line, reason }]. The only exception is an artifact whose entire dedicated file is the text (e.g. a standalone prompt file); set its sourcePath and cite that same file and no line is required. When a single file holds multiple inline prompts or tool definitions, give each its own distinct line — a bare { path, reason } is a defect there.",
|
|
4496
4527
|
"Agent families must include id, name, runtimeAgentIds, sharedArtifactIds, confidence, evidence.",
|
|
4497
4528
|
"Frameworks/providers must include packageNames and runtimeAgentIds arrays; providers also include envVars and modelHints arrays.",
|
|
@@ -4502,6 +4533,7 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4502
4533
|
options.tenantId ? `Tenant ID to include in graph.tenant: ${options.tenantId}` : "No tenant ID was provided for this analysis.",
|
|
4503
4534
|
`Repository root: ${options.rootDir}`,
|
|
4504
4535
|
renderAnalystPreflightSection(options.rootDir),
|
|
4536
|
+
renderAnalystSeedSection(options.rootDir),
|
|
4505
4537
|
"",
|
|
4506
4538
|
"Be conservative. If something is unclear, put it in unknowns instead of inventing an agent."
|
|
4507
4539
|
].filter(Boolean).join(`
|
|
@@ -4520,7 +4552,7 @@ function renderExternalAnalystProtocol() {
|
|
|
4520
4552
|
'- Also emit artifacts for guardrails (type "guardrail"), evals/tests-of-agents (type "eval"), memory/session stores (type "memory"), retrieval indexes (type "retrieval_index"), and model configuration (type "model_config").',
|
|
4521
4553
|
"- Only runtime AGENTS may be modeled representatively: if the repo is a framework/SDK/examples collection, you need not treat every example as a distinct production agent — but you MUST still enumerate every distinct tool, prompt, guardrail, and eval as its own artifact.",
|
|
4522
4554
|
"- Each enumerated artifact needs evidence: [{ path, reason }] (file path + short reason); a full line+excerpt citation is required only for the narrative `claims`, NOT for every artifact — so listing hundreds of tools/prompts is cheap and expected.",
|
|
4523
|
-
"-
|
|
4555
|
+
"- Bodies are hydrated locally by Moda from pinned locations — do not copy file text into `body`. Spend your output budget on coverage (every artifact, exact definition locations), not transcription. Inline `body` only for content not recoverable from a single location (e.g. prompts assembled from fragments at runtime), plus short bodies for guardrails/evals/model configs.",
|
|
4524
4556
|
"- EXCEPTION — `prompt` and `tool` artifacts MUST pin an exact location: put a numeric `line` on at least one evidence entry (evidence: [{ path, line, reason }]) at the definition line. That structured location is what lets downstream optimization retrieve the exact prompt/tool text; when one file has several inline prompts or tools, each artifact gets its own line. The only case that needs no line is a whole dedicated file whose entire content is the artifact (set sourcePath to that file and cite it). Still no excerpt required — just the line.",
|
|
4525
4557
|
"- For every runtime agent, read and cite at least one concrete entrypoint or orchestration line, and link its prompts/tools via artifactIds.",
|
|
4526
4558
|
"- Keep going until every prompt, tool, guardrail, and eval in scope is represented as an artifact. Use unknowns only for genuinely ambiguous items — never to skip enumeration. Respect the hard caps (<=250 claims, <=400 citations): artifacts are uncapped, so when there are many items keep enumerating them as artifacts and reserve claims/citations for the most important ones."
|
|
@@ -4528,7 +4560,7 @@ function renderExternalAnalystProtocol() {
|
|
|
4528
4560
|
`);
|
|
4529
4561
|
}
|
|
4530
4562
|
function renderAnalystPreflightSection(rootDir) {
|
|
4531
|
-
if (process.env.MODA_HARNESS_ANALYST_PREFLIGHT
|
|
4563
|
+
if (process.env.MODA_HARNESS_ANALYST_PREFLIGHT === "0")
|
|
4532
4564
|
return "";
|
|
4533
4565
|
const paths = listAnalystPreflightPaths(rootDir);
|
|
4534
4566
|
if (paths.length === 0)
|
|
@@ -4558,6 +4590,91 @@ function renderPreflightGroup(label, paths) {
|
|
|
4558
4590
|
return [];
|
|
4559
4591
|
return [`${label}:`, ...paths.map((path) => `- ${path}`)];
|
|
4560
4592
|
}
|
|
4593
|
+
var MAX_SEED_ARTIFACT_LINES = 150;
|
|
4594
|
+
function renderAnalystSeedSection(rootDir) {
|
|
4595
|
+
if (process.env.MODA_HARNESS_ANALYST_SEEDS === "0")
|
|
4596
|
+
return "";
|
|
4597
|
+
const sections = [];
|
|
4598
|
+
try {
|
|
4599
|
+
const lines = renderAnalystSeedLines(scanHarness({ rootDir, dryRun: true, pathWasExplicit: true }));
|
|
4600
|
+
if (lines)
|
|
4601
|
+
sections.push(lines);
|
|
4602
|
+
} catch {}
|
|
4603
|
+
try {
|
|
4604
|
+
const lines = renderAnalystCandidateLines(detectHarnessCandidates(rootDir));
|
|
4605
|
+
if (lines)
|
|
4606
|
+
sections.push(lines);
|
|
4607
|
+
} catch {}
|
|
4608
|
+
return sections.join(`
|
|
4609
|
+
`);
|
|
4610
|
+
}
|
|
4611
|
+
var MAX_SEED_CANDIDATES_PER_KIND = 40;
|
|
4612
|
+
var MAX_SEED_READ_PLAN_FILES = 25;
|
|
4613
|
+
var SEED_CANDIDATE_KIND_LABELS = {
|
|
4614
|
+
llm_call_site: "LLM call sites",
|
|
4615
|
+
framework_construct: "Agent-framework constructs",
|
|
4616
|
+
tool_definition: "Tool definitions",
|
|
4617
|
+
tool_schema: "Tool schemas",
|
|
4618
|
+
message_construction: "Message constructions",
|
|
4619
|
+
prompt_file: "Prompt files",
|
|
4620
|
+
prompt_literal: "Inline prompt literals",
|
|
4621
|
+
model_config: "Model configuration"
|
|
4622
|
+
};
|
|
4623
|
+
function renderAnalystCandidateLines(report) {
|
|
4624
|
+
if (report.candidates.length === 0)
|
|
4625
|
+
return "";
|
|
4626
|
+
const byKind = new Map;
|
|
4627
|
+
for (const candidate of report.candidates) {
|
|
4628
|
+
const bucket = byKind.get(candidate.kind);
|
|
4629
|
+
if (bucket)
|
|
4630
|
+
bucket.push(candidate);
|
|
4631
|
+
else
|
|
4632
|
+
byKind.set(candidate.kind, [candidate]);
|
|
4633
|
+
}
|
|
4634
|
+
const lines = [
|
|
4635
|
+
"",
|
|
4636
|
+
`Deterministic candidate inventory (${report.candidates.length} candidates across ${report.stats.filesWithCandidates} files, scanned in ${report.stats.durationMs}ms):`,
|
|
4637
|
+
"Each entry is path:line [detector] excerpt. Verify each candidate against the real file, then represent every confirmed tool/prompt/eval/model-config as a graph artifact pinned to that location. Candidates are pattern matches — drop false positives, and investigate what patterns cannot see (agent topology, relationships, prompts assembled at runtime). Do not cite this list as evidence; cite the files."
|
|
4638
|
+
];
|
|
4639
|
+
for (const [kind, label] of Object.entries(SEED_CANDIDATE_KIND_LABELS)) {
|
|
4640
|
+
const bucket = byKind.get(kind);
|
|
4641
|
+
if (!bucket || bucket.length === 0)
|
|
4642
|
+
continue;
|
|
4643
|
+
const shown = bucket.slice(0, MAX_SEED_CANDIDATES_PER_KIND);
|
|
4644
|
+
lines.push(`${label} (${bucket.length}${bucket.length > shown.length ? `, showing ${shown.length}` : ""}):`);
|
|
4645
|
+
for (const candidate of shown) {
|
|
4646
|
+
lines.push(`- ${candidate.path}:${candidate.startLine} [${candidate.signal}] ${candidate.excerpt}`);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
const readPlan = report.files.slice(0, MAX_SEED_READ_PLAN_FILES);
|
|
4650
|
+
if (readPlan.length > 0) {
|
|
4651
|
+
lines.push(`Highest-signal files to read first (${readPlan.length} of ${report.files.length}):`, ...readPlan.map((file) => `- ${file.path} (score ${Math.round(file.score)}; ${file.kinds.join(", ")})`));
|
|
4652
|
+
}
|
|
4653
|
+
return lines.join(`
|
|
4654
|
+
`);
|
|
4655
|
+
}
|
|
4656
|
+
function renderAnalystSeedLines(graph) {
|
|
4657
|
+
const providers = graph.modelProviders.map((provider) => `- ${provider.name}${provider.packageNames.length ? ` (packages: ${provider.packageNames.join(", ")})` : ""}`);
|
|
4658
|
+
const frameworks = graph.agentFrameworks.map((framework) => `- ${framework.name}${framework.packageNames.length ? ` (packages: ${framework.packageNames.join(", ")})` : ""}`);
|
|
4659
|
+
const artifacts = graph.artifacts.slice(0, MAX_SEED_ARTIFACT_LINES).map((artifact) => `- [${artifact.type}] ${artifact.sourcePath ?? artifact.name}`);
|
|
4660
|
+
if (providers.length === 0 && frameworks.length === 0 && artifacts.length === 0)
|
|
4661
|
+
return "";
|
|
4662
|
+
const lines = [
|
|
4663
|
+
"",
|
|
4664
|
+
"Deterministic scanner seeds (candidates, not ground truth):",
|
|
4665
|
+
"Moda's static scanner pre-detected the items below from package manifests and filename patterns. Verify each against the real files before including it, correct or drop mislabeled entries, and focus your investigation on what pattern matching cannot see: runtime agents, inline prompts, decorated/registered tool definitions, and the relationships between them. Do not cite this list as evidence."
|
|
4666
|
+
];
|
|
4667
|
+
if (providers.length > 0)
|
|
4668
|
+
lines.push("Detected model providers:", ...providers);
|
|
4669
|
+
if (frameworks.length > 0) {
|
|
4670
|
+
lines.push("Detected agent frameworks (package-name matches; may be false positives):", ...frameworks);
|
|
4671
|
+
}
|
|
4672
|
+
if (artifacts.length > 0) {
|
|
4673
|
+
lines.push(`Detected artifact candidates (${graph.artifacts.length} total${graph.artifacts.length > MAX_SEED_ARTIFACT_LINES ? `, showing first ${MAX_SEED_ARTIFACT_LINES}` : ""}):`, ...artifacts);
|
|
4674
|
+
}
|
|
4675
|
+
return lines.join(`
|
|
4676
|
+
`);
|
|
4677
|
+
}
|
|
4561
4678
|
function listAnalystPreflightPaths(rootDir) {
|
|
4562
4679
|
const gitPaths = readGitTrackedPaths(rootDir);
|
|
4563
4680
|
const paths = gitPaths.length > 0 ? gitPaths : readDirectoryPreflightPaths(rootDir);
|
|
@@ -5257,6 +5374,25 @@ function renderFrameworkAndProviderLines(graph) {
|
|
|
5257
5374
|
}
|
|
5258
5375
|
return lines;
|
|
5259
5376
|
}
|
|
5377
|
+
function assertHarnessGraphSyncQuality(graph, flags) {
|
|
5378
|
+
if (flags["allow-no-agents"] === "true")
|
|
5379
|
+
return;
|
|
5380
|
+
if (graph.runtimeAgents.length > 0)
|
|
5381
|
+
return;
|
|
5382
|
+
const evidence = [];
|
|
5383
|
+
if (graph.modelProviders.length > 0) {
|
|
5384
|
+
evidence.push(`model providers (${graph.modelProviders.map((provider) => provider.name).join(", ")})`);
|
|
5385
|
+
}
|
|
5386
|
+
if (graph.agentFrameworks.length > 0) {
|
|
5387
|
+
evidence.push(`agent frameworks (${graph.agentFrameworks.map((framework) => framework.name).join(", ")})`);
|
|
5388
|
+
}
|
|
5389
|
+
const promptOrToolCount = graph.artifacts.filter((artifact) => artifact.type === "prompt" || artifact.type === "tool").length;
|
|
5390
|
+
if (promptOrToolCount > 0)
|
|
5391
|
+
evidence.push(`${promptOrToolCount} prompt/tool artifacts`);
|
|
5392
|
+
if (evidence.length === 0)
|
|
5393
|
+
return;
|
|
5394
|
+
throw new CliInputError(`Refusing to sync: the harness graph has zero runtime agents but detected ${evidence.join(", ")}.`, "Agent detection likely under-ran (the deterministic scanner only finds agents via @moda annotations). Run `moda harness analyze --analyst=claude` for semantic detection, or pass --allow-no-agents to sync this graph anyway.");
|
|
5395
|
+
}
|
|
5260
5396
|
function graphForSync(graph) {
|
|
5261
5397
|
return sortJson2({
|
|
5262
5398
|
...graph,
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runPromptsCommand,
|
|
9
9
|
runSkillsCommand,
|
|
10
10
|
runStatusCommand
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-n5qz81m0.js";
|
|
12
12
|
import {
|
|
13
13
|
ApiError,
|
|
14
14
|
HARNESS_REPORT_APPROVAL_PATH,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
summarizeHarness,
|
|
30
30
|
terminalStyles,
|
|
31
31
|
validateHarnessReport
|
|
32
|
-
} from "./cli-
|
|
32
|
+
} from "./cli-793dhrgb.js";
|
|
33
33
|
import {
|
|
34
34
|
authFetch,
|
|
35
35
|
clearAuthSession,
|
|
@@ -5499,6 +5499,11 @@ Init flags:
|
|
|
5499
5499
|
--yes Accept all defaults (non-interactive)
|
|
5500
5500
|
--analyst=auto|claude|codex|cursor|local-scan
|
|
5501
5501
|
Choose harness analyst adapter
|
|
5502
|
+
--analyst-model=MODEL Model for the claude analyst (default: sonnet;
|
|
5503
|
+
"default" = the claude CLI's own default;
|
|
5504
|
+
env: MODA_HARNESS_ANALYST_MODEL)
|
|
5505
|
+
--allow-no-agents Allow harness sync to push a graph with zero
|
|
5506
|
+
runtime agents despite detected LLM usage
|
|
5502
5507
|
--remote Run harness analysis server-side (Moda-hosted,
|
|
5503
5508
|
the default): upload a safe source snapshot; no
|
|
5504
5509
|
local coding agent required
|
|
@@ -6491,7 +6496,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6491
6496
|
resetApiRequestCountBeforeRun: true,
|
|
6492
6497
|
telemetry: "result",
|
|
6493
6498
|
handler: async (context) => {
|
|
6494
|
-
const { runInit } = await import("./index-
|
|
6499
|
+
const { runInit } = await import("./index-djg29jhz.js");
|
|
6495
6500
|
if (context.outputMode === "agent-stream") {
|
|
6496
6501
|
context.output.writeEvent({
|
|
6497
6502
|
event: "started",
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
runPromptSync,
|
|
10
10
|
runSkillSync,
|
|
11
11
|
upsertSkillManifestRecord
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-n5qz81m0.js";
|
|
13
13
|
import {
|
|
14
14
|
codingAgentDisplayName,
|
|
15
15
|
describeCodingAgentEvent,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
runHarnessCommand,
|
|
28
28
|
startRemoteAnalyze,
|
|
29
29
|
stripAnsi
|
|
30
|
-
} from "./cli-
|
|
30
|
+
} from "./cli-793dhrgb.js";
|
|
31
31
|
import {
|
|
32
32
|
selectTenantAndCreateKey
|
|
33
33
|
} from "./cli-pq6rte0w.js";
|
package/package.json
CHANGED