@moda-ai/cli 1.30.0 → 1.30.2
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-3ba4qcpr.js → cli-c1vhkg8n.js} +1 -1
- package/dist/{cli-5e0rd8mf.js → cli-ts6nhn51.js} +250 -48
- package/dist/cli.js +15 -3
- package/dist/{harness-github-actions-dmy8fz54.js → harness-github-actions-ze17s10y.js} +1 -1
- package/dist/{index-nes2m734.js → index-v3j2848b.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -284,6 +284,7 @@ var HARNESS_REPORT_PATH = join(".moda", "harness-report.json");
|
|
|
284
284
|
var HARNESS_REPORT_MARKDOWN_PATH = join(".moda", "HARNESS_REPORT.md");
|
|
285
285
|
var HARNESS_REPORT_VALIDATION_PATH = join(".moda", "harness-report-validation.json");
|
|
286
286
|
var HARNESS_REPORT_APPROVAL_PATH = join(".moda", "harness-report-approval.json");
|
|
287
|
+
var HARNESS_ANALYZE_CONCERNS = ["topology", "tools", "prompts", "evals"];
|
|
287
288
|
var HARNESS_GRAPH_ARRAY_FIELDS = [
|
|
288
289
|
"agentFamilies",
|
|
289
290
|
"runtimeAgents",
|
|
@@ -713,7 +714,7 @@ function validateHarnessReport(report, rootDir, options) {
|
|
|
713
714
|
}
|
|
714
715
|
}
|
|
715
716
|
}
|
|
716
|
-
validateDeterministicFloor(report, options?.deterministicFloor, check, warn);
|
|
717
|
+
validateDeterministicFloor(report, options?.deterministicFloor, check, warn, options?.concern);
|
|
717
718
|
return {
|
|
718
719
|
schemaVersion: HARNESS_REPORT_VALIDATION_SCHEMA_VERSION,
|
|
719
720
|
reportId: report?.reportId ?? "unknown",
|
|
@@ -725,24 +726,26 @@ function validateHarnessReport(report, rootDir, options) {
|
|
|
725
726
|
warnings
|
|
726
727
|
};
|
|
727
728
|
}
|
|
728
|
-
function validateDeterministicFloor(report, floor, check, warn) {
|
|
729
|
+
function validateDeterministicFloor(report, floor, check, warn, concern) {
|
|
729
730
|
if (!floor)
|
|
730
731
|
return;
|
|
731
732
|
if (process.env.MODA_HARNESS_FLOOR_CHECK === "0")
|
|
732
733
|
return;
|
|
734
|
+
const applyToolFloor = concern === undefined || concern === "tools";
|
|
735
|
+
const applyTopologyFloors = concern === undefined || concern === "topology";
|
|
733
736
|
const graph = isRecord(report?.graph) ? report.graph : {};
|
|
734
737
|
const toolArtifactCount = Array.isArray(graph.artifacts) ? graph.artifacts.filter((artifact) => isRecord(artifact) && artifact.type === "tool").length : 0;
|
|
735
738
|
const providerCount = safeArrayLength(graph.modelProviders);
|
|
736
739
|
const runtimeAgentCount = safeArrayLength(graph.runtimeAgents);
|
|
737
|
-
if (typeof floor.toolCandidates === "number" && floor.toolCandidates >= 5) {
|
|
740
|
+
if (applyToolFloor && typeof floor.toolCandidates === "number" && floor.toolCandidates >= 5) {
|
|
738
741
|
const minimumTools = Math.ceil(0.5 * floor.toolCandidates);
|
|
739
742
|
check("floor_tools", toolArtifactCount >= minimumTools, `Deterministic scan found ${floor.toolCandidates} high-confidence tool definition candidate(s); the report graph must include at least ${minimumTools} tool artifact(s) but has ${toolArtifactCount}.`);
|
|
740
743
|
}
|
|
741
744
|
const providerPackages = Array.isArray(floor.providerPackages) ? floor.providerPackages.filter((name) => typeof name === "string" && name.length > 0) : [];
|
|
742
|
-
if (providerPackages.length > 0) {
|
|
745
|
+
if (applyTopologyFloors && providerPackages.length > 0) {
|
|
743
746
|
check("floor_providers", providerCount > 0, `Manifest dependencies include model-provider package(s) ${providerPackages.join(", ")}, but the report graph.modelProviders is empty.`);
|
|
744
747
|
}
|
|
745
|
-
if (typeof floor.llmCallSites === "number" && floor.llmCallSites > 0 && runtimeAgentCount === 0) {
|
|
748
|
+
if (applyTopologyFloors && typeof floor.llmCallSites === "number" && floor.llmCallSites > 0 && runtimeAgentCount === 0) {
|
|
746
749
|
warn("floor_agents", `Deterministic scan found ${floor.llmCallSites} LLM call site(s) but the report graph.runtimeAgents is empty; sync will be blocked by the zero-agent gate.`);
|
|
747
750
|
}
|
|
748
751
|
}
|
|
@@ -2973,7 +2976,6 @@ function assertHarnessGraphSyncSize(graph) {
|
|
|
2973
2976
|
`));
|
|
2974
2977
|
}
|
|
2975
2978
|
}
|
|
2976
|
-
|
|
2977
2979
|
// src/tui.ts
|
|
2978
2980
|
var STATUS_LABELS = {
|
|
2979
2981
|
pass: "ok",
|
|
@@ -3524,6 +3526,13 @@ async function runHarnessCommand(context) {
|
|
|
3524
3526
|
writeHumanProgress(context, "moda harness analyze is disabled: connect the Moda GitHub App (Settings → Integrations) for automatic analysis, or pass --experimental to run the CLI analyze.");
|
|
3525
3527
|
return { exitCode: 1 };
|
|
3526
3528
|
}
|
|
3529
|
+
const concern = resolveHarnessAnalyzeConcern(context.flags, context.env);
|
|
3530
|
+
if (concern) {
|
|
3531
|
+
const unsupported = context.flags["github-actions"] === "true" ? "--github-actions" : isRemoteHarnessAnalyze(context) ? "hosted (--remote) analysis" : await resolveHarnessAnalystAdapter(context) === "local-scan" ? "--analyst=local-scan" : "";
|
|
3532
|
+
if (unsupported) {
|
|
3533
|
+
throw new CliInputError(`--concern=${concern} is not supported by ${unsupported}.`, "Concern scoping narrows the analyst prompt and gates deterministic seeds, promotion, and floors, which only the local coding-agent analyst does today. Drop --concern, or run with --analyst=claude|codex|cursor.");
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3527
3536
|
await approveScanIfNeeded(scanPlan, {
|
|
3528
3537
|
context,
|
|
3529
3538
|
message: "Run Moda Analyst to investigate this project and produce a cited harness report?",
|
|
@@ -3537,7 +3546,7 @@ async function runHarnessCommand(context) {
|
|
|
3537
3546
|
elapsed_ms: Date.now() - context.startedAt
|
|
3538
3547
|
});
|
|
3539
3548
|
if (context.flags["github-actions"] === "true") {
|
|
3540
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
3549
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-ze17s10y.js");
|
|
3541
3550
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
3542
3551
|
writeReport: (report2) => {
|
|
3543
3552
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -3565,7 +3574,8 @@ async function runHarnessCommand(context) {
|
|
|
3565
3574
|
rootDir,
|
|
3566
3575
|
scanPlan,
|
|
3567
3576
|
tenant,
|
|
3568
|
-
adapter: analyst
|
|
3577
|
+
adapter: analyst,
|
|
3578
|
+
concern
|
|
3569
3579
|
});
|
|
3570
3580
|
}
|
|
3571
3581
|
context.output.writeEvent({
|
|
@@ -3838,7 +3848,8 @@ async function runExternalHarnessAnalyst(options) {
|
|
|
3838
3848
|
const prompt = renderExternalHarnessAnalystPrompt({
|
|
3839
3849
|
adapter: options.adapter,
|
|
3840
3850
|
rootDir: options.rootDir,
|
|
3841
|
-
tenantId: options.tenant?.tenantId
|
|
3851
|
+
tenantId: options.tenant?.tenantId,
|
|
3852
|
+
concern: options.concern
|
|
3842
3853
|
});
|
|
3843
3854
|
const streamAnalystProgress = options.context.outputMode === "agent-stream";
|
|
3844
3855
|
const invocation = resolveExternalHarnessAnalystInvocation({
|
|
@@ -3897,12 +3908,15 @@ async function runExternalHarnessAnalyst(options) {
|
|
|
3897
3908
|
},
|
|
3898
3909
|
onAgentEvent: streamAnalystProgress ? (event) => {
|
|
3899
3910
|
const progress = analystEventProgress(event);
|
|
3900
|
-
if (!progress)
|
|
3911
|
+
if (!progress && !event.usage)
|
|
3901
3912
|
return;
|
|
3902
3913
|
options.context.output.writeEvent({
|
|
3903
3914
|
event: "progress",
|
|
3904
|
-
phase: progress
|
|
3905
|
-
message: progress
|
|
3915
|
+
phase: progress?.phase ?? "analyst_usage",
|
|
3916
|
+
message: progress?.message ?? "analyst usage update",
|
|
3917
|
+
...event.usage ? { usage: event.usage } : {},
|
|
3918
|
+
...event.model ? { model: event.model } : {},
|
|
3919
|
+
...event.durationMs !== undefined ? { duration_ms: event.durationMs } : {},
|
|
3906
3920
|
elapsed_ms: Date.now() - options.context.startedAt
|
|
3907
3921
|
});
|
|
3908
3922
|
} : undefined
|
|
@@ -3921,7 +3935,7 @@ async function runExternalHarnessAnalyst(options) {
|
|
|
3921
3935
|
${result.stderr}`, 1200);
|
|
3922
3936
|
throw new CliInputError(`Harness analyst ${options.adapter} exited with status ${result.status ?? "unknown"}.`, output || "Rerun with the selected coding agent CLI fixed, or choose another analyst with `--analyst=claude|codex|cursor`.");
|
|
3923
3937
|
}
|
|
3924
|
-
const report = readExternalAnalystReport(options.rootDir, result, options.adapter);
|
|
3938
|
+
const report = readExternalAnalystReport(options.rootDir, result, options.adapter, options.concern);
|
|
3925
3939
|
analystTui?.setSummary({
|
|
3926
3940
|
runtimeAgentCount: report.graph.runtimeAgents.length,
|
|
3927
3941
|
agentFamilyCount: report.graph.agentFamilies.length,
|
|
@@ -3940,7 +3954,8 @@ ${result.stderr}`, 1200);
|
|
|
3940
3954
|
});
|
|
3941
3955
|
analystTui?.setValidation("running");
|
|
3942
3956
|
const validation = validateHarnessReport(report, options.rootDir, {
|
|
3943
|
-
deterministicFloor: computeDeterministicFloor(options.rootDir)
|
|
3957
|
+
deterministicFloor: computeDeterministicFloor(options.rootDir),
|
|
3958
|
+
concern: options.concern
|
|
3944
3959
|
});
|
|
3945
3960
|
analystTui?.setValidation(validation.status === "pass" ? "pass" : "fail");
|
|
3946
3961
|
if (!analystTui)
|
|
@@ -3990,10 +4005,10 @@ function buildExternalAnalystEnv(env) {
|
|
|
3990
4005
|
}
|
|
3991
4006
|
return next;
|
|
3992
4007
|
}
|
|
3993
|
-
function readExternalAnalystReport(rootDir, result, adapter) {
|
|
4008
|
+
function readExternalAnalystReport(rootDir, result, adapter, concern) {
|
|
3994
4009
|
const reportPath = resolve5(rootDir, HARNESS_REPORT_PATH);
|
|
3995
4010
|
if (existsSync3(reportPath))
|
|
3996
|
-
return repairExternalAnalystReport(readHarnessReport(reportPath), rootDir);
|
|
4011
|
+
return repairExternalAnalystReport(readHarnessReport(reportPath), rootDir, { concern });
|
|
3997
4012
|
const output = [
|
|
3998
4013
|
result.stdout,
|
|
3999
4014
|
result.stderr,
|
|
@@ -4001,7 +4016,7 @@ function readExternalAnalystReport(rootDir, result, adapter) {
|
|
|
4001
4016
|
extractAgentTextFromOutput(result.stderr)
|
|
4002
4017
|
].filter(Boolean).join(`
|
|
4003
4018
|
`);
|
|
4004
|
-
const parsed = extractHarnessReportFromText(output, rootDir);
|
|
4019
|
+
const parsed = extractHarnessReportFromText(output, rootDir, concern);
|
|
4005
4020
|
if (parsed)
|
|
4006
4021
|
return parsed;
|
|
4007
4022
|
let debugHint = "";
|
|
@@ -4025,11 +4040,11 @@ function readExternalAnalystReport(rootDir, result, adapter) {
|
|
|
4025
4040
|
].filter(Boolean).join(`
|
|
4026
4041
|
`));
|
|
4027
4042
|
}
|
|
4028
|
-
function extractHarnessReportFromText(output, rootDir) {
|
|
4043
|
+
function extractHarnessReportFromText(output, rootDir, concern) {
|
|
4029
4044
|
for (const candidate of reportJsonCandidates(output)) {
|
|
4030
4045
|
const parsed = parseHarnessReportCandidate(candidate);
|
|
4031
4046
|
if (parsed)
|
|
4032
|
-
return repairExternalAnalystReport(parsed, rootDir);
|
|
4047
|
+
return repairExternalAnalystReport(parsed, rootDir, { concern });
|
|
4033
4048
|
}
|
|
4034
4049
|
return;
|
|
4035
4050
|
}
|
|
@@ -4063,13 +4078,32 @@ function parseHarnessReportCandidate(candidate) {
|
|
|
4063
4078
|
}
|
|
4064
4079
|
return;
|
|
4065
4080
|
}
|
|
4066
|
-
function repairExternalAnalystReport(report, rootDir) {
|
|
4081
|
+
function repairExternalAnalystReport(report, rootDir, options = {}) {
|
|
4067
4082
|
const normalized = normalizeHarnessReport(report);
|
|
4068
4083
|
repairCitationLines(normalized, rootDir);
|
|
4069
|
-
mergeDeterministicArtifacts(normalized.graph, rootDir);
|
|
4084
|
+
mergeDeterministicArtifacts(normalized.graph, rootDir, { concern: options.concern });
|
|
4070
4085
|
hydratePromptAndToolBodies(normalized.graph, rootDir);
|
|
4071
4086
|
deriveRelationshipsFromGraph(normalized.graph);
|
|
4072
4087
|
repairReportSummaryCounts(normalized);
|
|
4088
|
+
if (options.concern) {
|
|
4089
|
+
normalized.source = {
|
|
4090
|
+
...normalized.source ?? {
|
|
4091
|
+
graphSchemaVersion: normalized.graph?.schemaVersion ?? SCHEMA_VERSION,
|
|
4092
|
+
graphHash: "",
|
|
4093
|
+
readPlan: normalized.graph?.scan?.readPlan ?? {
|
|
4094
|
+
scope: "broad",
|
|
4095
|
+
rootPaths: ["."],
|
|
4096
|
+
willRead: [],
|
|
4097
|
+
willSkip: [],
|
|
4098
|
+
skipsSecretFiles: true,
|
|
4099
|
+
followsSymlinks: false,
|
|
4100
|
+
uploadsSourceByDefault: false
|
|
4101
|
+
},
|
|
4102
|
+
deterministicInventory: false
|
|
4103
|
+
},
|
|
4104
|
+
concern: options.concern
|
|
4105
|
+
};
|
|
4106
|
+
}
|
|
4073
4107
|
if (normalized.source?.graphHash) {
|
|
4074
4108
|
normalized.source.graphHash = hashStableJson(graphForReport(normalized.graph));
|
|
4075
4109
|
}
|
|
@@ -4111,9 +4145,18 @@ function deriveRelationshipsFromGraph(graph) {
|
|
|
4111
4145
|
}
|
|
4112
4146
|
return { added };
|
|
4113
4147
|
}
|
|
4114
|
-
|
|
4148
|
+
var CONCERN_PROMOTED_ARTIFACT_TYPES = {
|
|
4149
|
+
topology: new Set,
|
|
4150
|
+
tools: new Set(["tool"]),
|
|
4151
|
+
prompts: new Set(["prompt"]),
|
|
4152
|
+
evals: new Set(["model_config"])
|
|
4153
|
+
};
|
|
4154
|
+
function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
|
|
4115
4155
|
if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
|
|
4116
4156
|
return { added: 0 };
|
|
4157
|
+
if (options.concern === "topology")
|
|
4158
|
+
return { added: 0 };
|
|
4159
|
+
const allowedTypes = options.concern ? CONCERN_PROMOTED_ARTIFACT_TYPES[options.concern] : undefined;
|
|
4117
4160
|
let promoted;
|
|
4118
4161
|
try {
|
|
4119
4162
|
promoted = promoteHarnessCandidates(detectHarnessCandidates(rootDir), rootDir);
|
|
@@ -4122,6 +4165,8 @@ function mergeDeterministicArtifacts(graph, rootDir) {
|
|
|
4122
4165
|
}
|
|
4123
4166
|
let added = 0;
|
|
4124
4167
|
for (const artifact of promoted) {
|
|
4168
|
+
if (allowedTypes && !allowedTypes.has(artifact.type))
|
|
4169
|
+
continue;
|
|
4125
4170
|
if (graphCoversPromotedArtifact(graph, artifact))
|
|
4126
4171
|
continue;
|
|
4127
4172
|
graph.artifacts.push(artifact);
|
|
@@ -4442,6 +4487,8 @@ function recordExternalAgentEventLine(line, options) {
|
|
|
4442
4487
|
options.onAgentEvent?.(event);
|
|
4443
4488
|
if (!options.inheritedOutput)
|
|
4444
4489
|
return;
|
|
4490
|
+
if (event.telemetryOnly)
|
|
4491
|
+
return;
|
|
4445
4492
|
options.tui?.recordEvent(event);
|
|
4446
4493
|
if (options.tui)
|
|
4447
4494
|
return;
|
|
@@ -4466,7 +4513,35 @@ function formatExternalAgentDisplayEvent(event, adapter) {
|
|
|
4466
4513
|
return ` ${analystDisplayName(adapter)}: ${event.message}
|
|
4467
4514
|
`;
|
|
4468
4515
|
}
|
|
4516
|
+
function extractAgentEventTelemetry(event) {
|
|
4517
|
+
const message = isRecord3(event.message) ? event.message : undefined;
|
|
4518
|
+
const usage = isRecord3(event.usage) ? event.usage : isRecord3(message?.usage) ? message.usage : undefined;
|
|
4519
|
+
const modelUsage = isRecord3(event.modelUsage) ? event.modelUsage : undefined;
|
|
4520
|
+
const model = stringValue(event.model) ?? stringValue(message?.model) ?? (modelUsage ? Object.keys(modelUsage)[0] : undefined);
|
|
4521
|
+
const durationValue = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
4522
|
+
const durationMs = durationValue(event.duration_ms) ?? durationValue(event.durationMs) ?? durationValue(event.duration_api_ms);
|
|
4523
|
+
if (!usage && !model && durationMs === undefined)
|
|
4524
|
+
return;
|
|
4525
|
+
return {
|
|
4526
|
+
...usage ? { usage } : {},
|
|
4527
|
+
...model ? { model } : {},
|
|
4528
|
+
...durationMs !== undefined ? { durationMs } : {}
|
|
4529
|
+
};
|
|
4530
|
+
}
|
|
4469
4531
|
function parseExternalAgentEvent(event) {
|
|
4532
|
+
const body = parseExternalAgentEventBody(event);
|
|
4533
|
+
if (!isRecord3(event))
|
|
4534
|
+
return body;
|
|
4535
|
+
const telemetry = extractAgentEventTelemetry(event);
|
|
4536
|
+
if (!telemetry)
|
|
4537
|
+
return body;
|
|
4538
|
+
if (body)
|
|
4539
|
+
return { ...body, ...telemetry };
|
|
4540
|
+
if (!telemetry.usage)
|
|
4541
|
+
return;
|
|
4542
|
+
return { kind: "system", message: "usage update", telemetryOnly: true, ...telemetry };
|
|
4543
|
+
}
|
|
4544
|
+
function parseExternalAgentEventBody(event) {
|
|
4470
4545
|
if (!isRecord3(event))
|
|
4471
4546
|
return { kind: "agent_text", message: truncateText(String(event), 500) };
|
|
4472
4547
|
const msg = isRecord3(event.msg) ? event.msg : undefined;
|
|
@@ -4628,6 +4703,17 @@ function isDeterministicLocalAnalyst(raw) {
|
|
|
4628
4703
|
const value = raw?.trim().toLowerCase();
|
|
4629
4704
|
return value === "local-scan" || value === "local" || value === "scripted" || value === "moda";
|
|
4630
4705
|
}
|
|
4706
|
+
function resolveHarnessAnalyzeConcern(flags, env = process.env) {
|
|
4707
|
+
const flagValue = flags.concern && flags.concern !== "true" ? flags.concern : undefined;
|
|
4708
|
+
const raw = flagValue ?? env.MODA_HARNESS_CONCERN;
|
|
4709
|
+
const value = raw?.trim().toLowerCase();
|
|
4710
|
+
if (!value)
|
|
4711
|
+
return;
|
|
4712
|
+
if (HARNESS_ANALYZE_CONCERNS.includes(value)) {
|
|
4713
|
+
return value;
|
|
4714
|
+
}
|
|
4715
|
+
throw new CliInputError(`Unknown harness analyze concern '${raw}'. Valid concerns: ${HARNESS_ANALYZE_CONCERNS.join("|")}.`, `Use --concern=${HARNESS_ANALYZE_CONCERNS.join("|")} (or MODA_HARNESS_CONCERN; the flag wins).`);
|
|
4716
|
+
}
|
|
4631
4717
|
function normalizeAnalystAdapter(raw) {
|
|
4632
4718
|
const value = (raw && raw !== "true" ? raw : "auto").trim().toLowerCase();
|
|
4633
4719
|
if (value === "auto")
|
|
@@ -4765,9 +4851,100 @@ function resolveAnalystModel(adapter, flags) {
|
|
|
4765
4851
|
return raw;
|
|
4766
4852
|
return adapter === "claude" ? DEFAULT_CLAUDE_ANALYST_MODEL : undefined;
|
|
4767
4853
|
}
|
|
4854
|
+
var CONCERN_AGENT_STUB_LINE = 'Runtime agents may be represented ONLY as bare low-confidence stubs when linkage needs a target: id, name, kind:"runtime_agent", root, confidence, evidence — nothing more. Do not investigate agent topology beyond that; the topology concern pass owns it.';
|
|
4855
|
+
var CONCERN_LOCATION_PIN_LINE = "Every artifact you author MUST pin an exact source location so downstream optimization can retrieve the item text: carry a numeric `line` on at least one evidence entry (evidence: [{ path, line, reason }]) at the definition line. The only exception is an artifact whose entire dedicated file is the text — set its sourcePath and cite that file, no line required. When a single file holds multiple inline definitions, give each artifact its own distinct line.";
|
|
4856
|
+
var CONCERN_NO_TRANSCRIPTION_LINE = "Do NOT transcribe prompt/tool text into `body` when it exists verbatim in the repo — pin its exact location instead and Moda hydrates `body` locally after validation. Set `body` inline ONLY for content that cannot be recovered from one pinned location (e.g. fragments assembled at runtime). Redact any secret literals.";
|
|
4857
|
+
var CONCERN_CAPS_LINE = "- Keep going until every in-concern item is represented as an artifact. Respect the hard caps (<=250 claims, <=400 citations): artifacts are uncapped, so keep enumerating them as artifacts and reserve claims/citations for the most important ones.";
|
|
4858
|
+
var CONCERN_PROMPT_SPECS = {
|
|
4859
|
+
topology: {
|
|
4860
|
+
mission: "Your single concern for this pass is TOPOLOGY: the agents and the infrastructure they run on. Other concern passes exhaustively enumerate tools, prompts, and evals — you must not.",
|
|
4861
|
+
taskLines: [
|
|
4862
|
+
"1. Map the harness topology: runtime agents, agent families, channel adapters, identity namespaces, environments, agent frameworks, model providers, deployments, the relationships among them, and open questions.",
|
|
4863
|
+
"2. Do NOT exhaustively enumerate tools, prompts, guardrails, or evals as artifacts — separate concern passes produce those inventories. Keep graph.artifacts minimal: entrypoint artifacts only, plus agent artifactIds references you discover naturally along the way."
|
|
4864
|
+
],
|
|
4865
|
+
protocolLines: [
|
|
4866
|
+
"- Focus EXCLUSIVELY on topology: runtime agents, agent families, channel adapters, identity namespaces, environments, agent frameworks, model providers, deployments, and how they relate.",
|
|
4867
|
+
"- Do NOT enumerate tools, prompts, guardrails, or evals as artifacts. Keep graph.artifacts minimal: entrypoints only.",
|
|
4868
|
+
"- For every runtime agent, read and cite at least one concrete entrypoint or orchestration line, and populate every linkage field (entrypointIds, channelAdapterIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds).",
|
|
4869
|
+
"- Reserve explicit `relationships` entries for what linkage fields cannot express: covered_by_eval, runs_in_environment, invoked_by_channel, deployed_as, shares_artifact_with, resolves_identity_to, emits_telemetry."
|
|
4870
|
+
],
|
|
4871
|
+
contractLines: [
|
|
4872
|
+
'Runtime agents must include id, name, kind:"runtime_agent", root, entrypointIds, channelAdapterIds, artifactIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds, confidence, evidence. Agent linkage fields are the product of this pass — empty linkage means a disconnected map.',
|
|
4873
|
+
"Agent families must include id, name, runtimeAgentIds, sharedArtifactIds, confidence, evidence.",
|
|
4874
|
+
"Frameworks/providers must include packageNames and runtimeAgentIds arrays; providers also include envVars and modelHints arrays.",
|
|
4875
|
+
"Keep graph.artifacts minimal (entrypoints only); do not enumerate tools, prompts, guardrails, or evals."
|
|
4876
|
+
],
|
|
4877
|
+
largeRepoLine: "If the repository is very large, model runtime agents representatively rather than exhaustively, but never drop channel adapters, providers, frameworks, or deployments you have evidence for."
|
|
4878
|
+
},
|
|
4879
|
+
tools: {
|
|
4880
|
+
mission: "Your single concern for this pass is TOOLS: the exhaustive tool inventory. Other concern passes cover agents/topology, prompts, and evals — you must not enumerate those.",
|
|
4881
|
+
taskLines: [
|
|
4882
|
+
"1. Exhaustively enumerate EVERY tool as its own `tool` graph artifact — the complete inventory, not a sample. This report feeds tool optimization, so a missing tool is a real defect.",
|
|
4883
|
+
"2. Do NOT enumerate prompts, guardrails, or evals, and do not map agent topology beyond bare stubs needed for tool linkage."
|
|
4884
|
+
],
|
|
4885
|
+
protocolLines: [
|
|
4886
|
+
"- Tools: emit a `tool` artifact for EVERY tool definition — each `@function_tool` / `function_tool(...)`-decorated function, every hosted/first-party tool class (e.g. WebSearchTool, FileSearchTool, ComputerTool, CodeInterpreterTool, HostedMCPTool, ImageGenerationTool, LocalShellTool), and every `tool({...})` / `createTool(...)` / `new *Tool(...)` factory. Name each artifact after the tool/function and cite its definition line.",
|
|
4887
|
+
"- Populate usedByAgentIds on every tool artifact whenever the using agent is determinable (and ownedByAgentId when a single agent owns it).",
|
|
4888
|
+
`- ${CONCERN_AGENT_STUB_LINE}`,
|
|
4889
|
+
"- Do NOT emit prompt, guardrail, eval, memory, or retrieval_index artifacts — other concern passes own those.",
|
|
4890
|
+
CONCERN_CAPS_LINE
|
|
4891
|
+
],
|
|
4892
|
+
contractLines: [
|
|
4893
|
+
'Artifacts must include id, type:"tool", name, scope, usedByAgentIds, confidence, evidence, and optional sourcePath/contentHash/ownedByAgentId. Emit one artifact PER tool — enumerate them all.',
|
|
4894
|
+
CONCERN_NO_TRANSCRIPTION_LINE,
|
|
4895
|
+
CONCERN_LOCATION_PIN_LINE,
|
|
4896
|
+
CONCERN_AGENT_STUB_LINE
|
|
4897
|
+
],
|
|
4898
|
+
largeRepoLine: "If the repository is very large, keep enumerating tools as artifacts (uncapped) — do not drop tools to save space."
|
|
4899
|
+
},
|
|
4900
|
+
prompts: {
|
|
4901
|
+
mission: "Your single concern for this pass is PROMPTS: the exhaustive prompt inventory. Other concern passes cover agents/topology, tools, and evals — you must not enumerate those.",
|
|
4902
|
+
taskLines: [
|
|
4903
|
+
"1. Exhaustively enumerate EVERY distinct prompt as its own `prompt` graph artifact — dedicated prompt files AND inline system prompts, the complete inventory, not a sample. This report feeds prompt optimization, so a missing prompt is a real defect.",
|
|
4904
|
+
"2. Do NOT enumerate tools, guardrails, or evals, and do not map agent topology beyond bare stubs needed for prompt linkage."
|
|
4905
|
+
],
|
|
4906
|
+
protocolLines: [
|
|
4907
|
+
"- Prompts: emit a `prompt` artifact for EVERY distinct prompt — dedicated prompt files AND inline system prompts (`instructions=`, `system=`, `SYSTEM_PROMPT`, prompt-template strings), one per agent/definition, each with its exact file+line location so the prompt text can be retrieved and optimized later.",
|
|
4908
|
+
"- Populate usedByAgentIds on every prompt artifact whenever the using agent is determinable (and ownedByAgentId when a single agent owns it).",
|
|
4909
|
+
`- ${CONCERN_AGENT_STUB_LINE}`,
|
|
4910
|
+
"- Do NOT emit tool, guardrail, eval, memory, or retrieval_index artifacts — other concern passes own those.",
|
|
4911
|
+
CONCERN_CAPS_LINE
|
|
4912
|
+
],
|
|
4913
|
+
contractLines: [
|
|
4914
|
+
'Artifacts must include id, type:"prompt", name, scope, usedByAgentIds, confidence, evidence, and optional sourcePath/contentHash/ownedByAgentId. Emit one artifact PER prompt (including each inline system prompt) — enumerate them all.',
|
|
4915
|
+
CONCERN_NO_TRANSCRIPTION_LINE,
|
|
4916
|
+
CONCERN_LOCATION_PIN_LINE,
|
|
4917
|
+
CONCERN_AGENT_STUB_LINE
|
|
4918
|
+
],
|
|
4919
|
+
largeRepoLine: "If the repository is very large, keep enumerating prompts as artifacts (uncapped) — do not drop prompts to save space."
|
|
4920
|
+
},
|
|
4921
|
+
evals: {
|
|
4922
|
+
mission: "Your single concern for this pass is EVALS & SAFETY CONFIG: evals, guardrails, model configs, and memory/retrieval stores. Other concern passes cover agents/topology, tools, and prompts — you must not enumerate those.",
|
|
4923
|
+
taskLines: [
|
|
4924
|
+
'1. Exhaustively enumerate EVERY eval (type "eval"), guardrail (type "guardrail"), model configuration (type "model_config"), memory/session store (type "memory"), and retrieval index (type "retrieval_index") as its own graph artifact — the complete inventory, not a sample.',
|
|
4925
|
+
"2. Do NOT enumerate tools or prompts, and do not map agent topology beyond bare stubs needed for linkage."
|
|
4926
|
+
],
|
|
4927
|
+
protocolLines: [
|
|
4928
|
+
'- Emit artifacts for evals/tests-of-agents (type "eval"), guardrails (type "guardrail"), model configuration (type "model_config"), memory/session stores (type "memory"), and retrieval indexes (type "retrieval_index").',
|
|
4929
|
+
"- Short bodies are welcome here: `guardrail` (the rule), `eval` (what it asserts), `model_config` (the config values). Redact any secret literals.",
|
|
4930
|
+
"- Populate usedByAgentIds on every artifact whenever the using agent is determinable.",
|
|
4931
|
+
`- ${CONCERN_AGENT_STUB_LINE}`,
|
|
4932
|
+
"- Do NOT emit tool or prompt artifacts — other concern passes own those.",
|
|
4933
|
+
CONCERN_CAPS_LINE
|
|
4934
|
+
],
|
|
4935
|
+
contractLines: [
|
|
4936
|
+
"Artifacts must include id, type, name, scope, usedByAgentIds, confidence, evidence, and optional sourcePath/contentHash/ownedByAgentId; artifact types for this pass are eval, guardrail, model_config, memory, retrieval_index. Emit one artifact PER item — enumerate them all.",
|
|
4937
|
+
"Short bodies are welcome: `guardrail` (the rule), `eval` (what it asserts), `model_config` (the config values). Redact any secret literals.",
|
|
4938
|
+
CONCERN_AGENT_STUB_LINE
|
|
4939
|
+
],
|
|
4940
|
+
largeRepoLine: "If the repository is very large, keep enumerating evals, guardrails, and model configs as artifacts (uncapped) — do not drop them to save space."
|
|
4941
|
+
}
|
|
4942
|
+
};
|
|
4768
4943
|
function renderExternalHarnessAnalystPrompt(options) {
|
|
4944
|
+
const spec = options.concern ? CONCERN_PROMPT_SPECS[options.concern] : undefined;
|
|
4769
4945
|
return [
|
|
4770
4946
|
"You are Moda Analyst, investigating an agent harness for Moda CLI onboarding.",
|
|
4947
|
+
spec?.mission ?? "",
|
|
4771
4948
|
"",
|
|
4772
4949
|
"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.",
|
|
4773
4950
|
"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.",
|
|
@@ -4777,13 +4954,15 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4777
4954
|
`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.`,
|
|
4778
4955
|
"",
|
|
4779
4956
|
"Your task:",
|
|
4780
|
-
renderExternalAnalystProtocol(),
|
|
4781
|
-
|
|
4782
|
-
|
|
4957
|
+
renderExternalAnalystProtocol(options.concern),
|
|
4958
|
+
...spec ? spec.taskLines : [
|
|
4959
|
+
"1. Identify the runtime agent harnesses, agent families, channel adapters, identity mappings, model providers, frameworks, deployments, and open questions.",
|
|
4960
|
+
"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."
|
|
4961
|
+
],
|
|
4783
4962
|
"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.",
|
|
4784
4963
|
`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).`,
|
|
4785
4964
|
"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.",
|
|
4786
|
-
"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.",
|
|
4965
|
+
spec?.largeRepoLine ?? "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.",
|
|
4787
4966
|
"",
|
|
4788
4967
|
"Final output format:",
|
|
4789
4968
|
REPORT_JSON_BEGIN,
|
|
@@ -4797,7 +4976,7 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4797
4976
|
"- reportId, harnessId, createdAt",
|
|
4798
4977
|
`- analyst: { "id": "moda-${options.adapter}-analyst", "adapter": "${options.adapter}", "mode": "agent", "version": "cli" }`,
|
|
4799
4978
|
'- repo: { root: ".", name, packageManagers, languages }',
|
|
4800
|
-
'- source: { graphSchemaVersion: "harness.v0.1", graphHash: "", readPlan, deterministicInventory: false }',
|
|
4979
|
+
options.concern ? `- source: { graphSchemaVersion: "harness.v0.1", graphHash: "", readPlan, deterministicInventory: false, concern: "${options.concern}" }` : '- source: { graphSchemaVersion: "harness.v0.1", graphHash: "", readPlan, deterministicInventory: false }',
|
|
4801
4980
|
"- summary: numeric fields named runtimeAgentCount, agentFamilyCount, artifactCount, sharedArtifactCount, channelAdapterCount, identityNamespaceCount, environmentCount, agentFrameworkCount, modelProviderCount, deploymentCount, relationshipCount, unknownCount",
|
|
4802
4981
|
"- graph: an exact sanitized harness.v0.1 graph with arrays for agentFamilies, runtimeAgents, developerAgentAdapters, channelAdapters, artifacts, identityNamespaces, environments, agentFrameworks, modelProviders, deployments, relationships, unknowns",
|
|
4803
4982
|
"- claims: cited claims about graph items. Each claim must include kind, subjectId, title, summary, confidence, inference, and citationIds; kind should be one of runtime_agent, agent_family, developer_agent_adapter, artifact, channel_adapter, identity_namespace, environment, agent_framework, model_provider, deployment, relationship, unknown. subjectId should be the id of the runtime agent, agent family, developer adapter, artifact, provider, adapter, deployment, relationship, or unknown being claimed.",
|
|
@@ -4807,13 +4986,15 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4807
4986
|
"",
|
|
4808
4987
|
'Use exact field names and numeric confidence values from 0 to 1. Do not write string confidence values like "high". Do not use confidence >= 0.90 unless the claim is direct evidence from the cited line(s).',
|
|
4809
4988
|
"Each graph item with evidence must use evidence: [{ path, reason }], not citationIds/citations.",
|
|
4810
|
-
|
|
4811
|
-
|
|
4812
|
-
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4989
|
+
...spec ? spec.contractLines : [
|
|
4990
|
+
'Runtime agents must include id, name, kind:"runtime_agent", root, entrypointIds, channelAdapterIds, artifactIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds, confidence, evidence.',
|
|
4991
|
+
"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.",
|
|
4992
|
+
"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.",
|
|
4993
|
+
"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.",
|
|
4994
|
+
"LINKAGE IS MANDATORY, not optional metadata: every artifact you author must carry usedByAgentIds naming each runtime agent that uses it (and ownedByAgentId when a single agent owns it), and every runtime agent's artifactIds must list its prompts, tools, and evals. Moda derives uses_artifact/owns_artifact edges from these fields after your run, so empty linkage means a disconnected map. Reserve explicit `relationships` entries for what linkage fields cannot express: covered_by_eval, runs_in_environment, invoked_by_channel, deployed_as, shares_artifact_with, resolves_identity_to, emits_telemetry.",
|
|
4995
|
+
"Agent families must include id, name, runtimeAgentIds, sharedArtifactIds, confidence, evidence.",
|
|
4996
|
+
"Frameworks/providers must include packageNames and runtimeAgentIds arrays; providers also include envVars and modelHints arrays."
|
|
4997
|
+
],
|
|
4817
4998
|
"Unknowns in graph must include id, question, candidateIds, evidence. Report-level unknowns must include id, question, citationIds.",
|
|
4818
4999
|
"Do not make every claim about the repo or harness id. Claims should name the specific graph item they support.",
|
|
4819
5000
|
"",
|
|
@@ -4821,16 +5002,24 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
4821
5002
|
options.tenantId ? `Tenant ID to include in graph.tenant: ${options.tenantId}` : "No tenant ID was provided for this analysis.",
|
|
4822
5003
|
`Repository root: ${options.rootDir}`,
|
|
4823
5004
|
renderAnalystPreflightSection(options.rootDir),
|
|
4824
|
-
renderAnalystSeedSection(options.rootDir),
|
|
5005
|
+
renderAnalystSeedSection(options.rootDir, options.concern),
|
|
4825
5006
|
"",
|
|
4826
5007
|
"Be conservative. If something is unclear, put it in unknowns instead of inventing an agent."
|
|
4827
5008
|
].filter(Boolean).join(`
|
|
4828
5009
|
`);
|
|
4829
5010
|
}
|
|
4830
|
-
function renderExternalAnalystProtocol() {
|
|
5011
|
+
function renderExternalAnalystProtocol(concern) {
|
|
4831
5012
|
const protocol = process.env.MODA_HARNESS_ANALYST_PROTOCOL?.trim().toLowerCase();
|
|
4832
5013
|
if (protocol === "classic" || protocol === "none" || protocol === "0")
|
|
4833
5014
|
return "";
|
|
5015
|
+
if (concern) {
|
|
5016
|
+
return [
|
|
5017
|
+
"Focused investigation protocol:",
|
|
5018
|
+
"- First build a quick repo map with read-only commands such as pwd, git ls-files, rg, and targeted manifest/doc reads.",
|
|
5019
|
+
...CONCERN_PROMPT_SPECS[concern].protocolLines
|
|
5020
|
+
].join(`
|
|
5021
|
+
`);
|
|
5022
|
+
}
|
|
4834
5023
|
return [
|
|
4835
5024
|
"Focused investigation protocol:",
|
|
4836
5025
|
"- First build a quick repo map with read-only commands such as pwd, git ls-files, rg, and targeted manifest/doc reads.",
|
|
@@ -4879,23 +5068,31 @@ function renderPreflightGroup(label, paths) {
|
|
|
4879
5068
|
return [`${label}:`, ...paths.map((path) => `- ${path}`)];
|
|
4880
5069
|
}
|
|
4881
5070
|
var MAX_SEED_ARTIFACT_LINES = 150;
|
|
4882
|
-
function renderAnalystSeedSection(rootDir) {
|
|
5071
|
+
function renderAnalystSeedSection(rootDir, concern) {
|
|
4883
5072
|
if (process.env.MODA_HARNESS_ANALYST_SEEDS === "0")
|
|
4884
5073
|
return "";
|
|
4885
5074
|
const sections = [];
|
|
5075
|
+
if (concern === undefined || concern === "topology") {
|
|
5076
|
+
try {
|
|
5077
|
+
const lines = renderAnalystSeedLines(scanHarness({ rootDir, dryRun: true, pathWasExplicit: true }));
|
|
5078
|
+
if (lines)
|
|
5079
|
+
sections.push(lines);
|
|
5080
|
+
} catch {}
|
|
5081
|
+
}
|
|
4886
5082
|
try {
|
|
4887
|
-
const lines =
|
|
4888
|
-
if (lines)
|
|
4889
|
-
sections.push(lines);
|
|
4890
|
-
} catch {}
|
|
4891
|
-
try {
|
|
4892
|
-
const lines = renderAnalystCandidateLines(detectHarnessCandidates(rootDir));
|
|
5083
|
+
const lines = renderAnalystCandidateLines(detectHarnessCandidates(rootDir), concern);
|
|
4893
5084
|
if (lines)
|
|
4894
5085
|
sections.push(lines);
|
|
4895
5086
|
} catch {}
|
|
4896
5087
|
return sections.join(`
|
|
4897
5088
|
`);
|
|
4898
5089
|
}
|
|
5090
|
+
var CONCERN_CANDIDATE_KINDS = {
|
|
5091
|
+
topology: ["llm_call_site", "framework_construct"],
|
|
5092
|
+
tools: ["tool_definition", "tool_schema"],
|
|
5093
|
+
prompts: ["prompt_file", "prompt_literal", "message_construction"],
|
|
5094
|
+
evals: ["model_config"]
|
|
5095
|
+
};
|
|
4899
5096
|
var MAX_SEED_CANDIDATES_PER_KIND = 40;
|
|
4900
5097
|
var MAX_SEED_READ_PLAN_FILES = 25;
|
|
4901
5098
|
var SEED_CANDIDATE_KIND_LABELS = {
|
|
@@ -4908,11 +5105,13 @@ var SEED_CANDIDATE_KIND_LABELS = {
|
|
|
4908
5105
|
prompt_literal: "Inline prompt literals",
|
|
4909
5106
|
model_config: "Model configuration"
|
|
4910
5107
|
};
|
|
4911
|
-
function renderAnalystCandidateLines(report) {
|
|
4912
|
-
|
|
5108
|
+
function renderAnalystCandidateLines(report, concern) {
|
|
5109
|
+
const allowedKinds = concern ? new Set(CONCERN_CANDIDATE_KINDS[concern]) : undefined;
|
|
5110
|
+
const candidates = allowedKinds ? report.candidates.filter((candidate) => allowedKinds.has(candidate.kind)) : report.candidates;
|
|
5111
|
+
if (candidates.length === 0)
|
|
4913
5112
|
return "";
|
|
4914
5113
|
const byKind = new Map;
|
|
4915
|
-
for (const candidate of
|
|
5114
|
+
for (const candidate of candidates) {
|
|
4916
5115
|
const bucket = byKind.get(candidate.kind);
|
|
4917
5116
|
if (bucket)
|
|
4918
5117
|
bucket.push(candidate);
|
|
@@ -4921,9 +5120,12 @@ function renderAnalystCandidateLines(report) {
|
|
|
4921
5120
|
}
|
|
4922
5121
|
const lines = [
|
|
4923
5122
|
"",
|
|
4924
|
-
`Deterministic candidate inventory (${report.candidates.length} candidates across ${report.stats.filesWithCandidates} files, scanned in ${report.stats.durationMs}ms):`,
|
|
4925
|
-
"Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file and drop false positives. Verified deterministic candidates are also auto-merged into the graph after your run, so prioritize (1) agents, topology, and relationships, (2) verifying or refuting these candidates (list refuted ones in unknowns), 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."
|
|
5123
|
+
concern ? `Deterministic candidate inventory for the ${concern} concern (${candidates.length} candidates, scanned in ${report.stats.durationMs}ms):` : `Deterministic candidate inventory (${candidates.length} candidates across ${report.stats.filesWithCandidates} files, scanned in ${report.stats.durationMs}ms):`,
|
|
5124
|
+
concern ? "Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file, drop false positives (list refuted ones in unknowns), and hunt for in-concern items the patterns cannot see. Do not cite this list as evidence; cite the files." : "Each entry is path:line [detector] excerpt. Candidates are pattern matches — verify each against the real file and drop false positives. Verified deterministic candidates are also auto-merged into the graph after your run, so prioritize (1) agents, topology, and relationships, (2) verifying or refuting these candidates (list refuted ones in unknowns), 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."
|
|
4926
5125
|
];
|
|
5126
|
+
if (concern === "evals") {
|
|
5127
|
+
lines.push("Note: evals, guardrails, and memory/retrieval stores have no deterministic detector — only model_config candidates are seeded. Discover the rest by investigation.");
|
|
5128
|
+
}
|
|
4927
5129
|
for (const [kind, label] of Object.entries(SEED_CANDIDATE_KIND_LABELS)) {
|
|
4928
5130
|
const bucket = byKind.get(kind);
|
|
4929
5131
|
if (!bucket || bucket.length === 0)
|
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-c1vhkg8n.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-ts6nhn51.js";
|
|
33
33
|
import {
|
|
34
34
|
authFetch,
|
|
35
35
|
clearAuthSession,
|
|
@@ -2240,6 +2240,13 @@ var agentEventSchema = {
|
|
|
2240
2240
|
phase: { type: "string" },
|
|
2241
2241
|
message: { type: "string" },
|
|
2242
2242
|
elapsed_ms: { type: "number" },
|
|
2243
|
+
usage: {
|
|
2244
|
+
type: "object",
|
|
2245
|
+
description: "Per-LLM-call token usage passed through verbatim from the underlying coding-agent stream (e.g. input_tokens/output_tokens/cache_* from claude stream-json).",
|
|
2246
|
+
additionalProperties: true
|
|
2247
|
+
},
|
|
2248
|
+
model: { type: "string", description: "Model id reported by the underlying coding-agent stream for this call." },
|
|
2249
|
+
duration_ms: { type: "number", description: "Duration in ms reported by the underlying coding-agent stream (result events)." },
|
|
2243
2250
|
artifact: agentArtifactSchema,
|
|
2244
2251
|
result: agentEnvelopeSchema,
|
|
2245
2252
|
error: agentErrorSchema,
|
|
@@ -5507,6 +5514,11 @@ Init flags:
|
|
|
5507
5514
|
--analyst-model=MODEL Model for the claude analyst (default: sonnet;
|
|
5508
5515
|
"default" = the claude CLI's own default;
|
|
5509
5516
|
env: MODA_HARNESS_ANALYST_MODEL)
|
|
5517
|
+
--concern=topology|tools|prompts|evals
|
|
5518
|
+
Harness analyze: restrict the pass to one
|
|
5519
|
+
concern (whole repo, one report scope); an
|
|
5520
|
+
orchestrator merges the per-concern reports
|
|
5521
|
+
(env: MODA_HARNESS_CONCERN, flag wins)
|
|
5510
5522
|
--allow-no-agents Allow harness sync to push a graph with zero
|
|
5511
5523
|
runtime agents despite detected LLM usage
|
|
5512
5524
|
--remote Run harness analysis server-side (Moda-hosted,
|
|
@@ -6514,7 +6526,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6514
6526
|
resetApiRequestCountBeforeRun: true,
|
|
6515
6527
|
telemetry: "result",
|
|
6516
6528
|
handler: async (context) => {
|
|
6517
|
-
const { runInit } = await import("./index-
|
|
6529
|
+
const { runInit } = await import("./index-v3j2848b.js");
|
|
6518
6530
|
if (context.outputMode === "agent-stream") {
|
|
6519
6531
|
context.output.writeEvent({
|
|
6520
6532
|
event: "started",
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
runPromptSync,
|
|
10
10
|
runSkillSync,
|
|
11
11
|
upsertSkillManifestRecord
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-c1vhkg8n.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-ts6nhn51.js";
|
|
31
31
|
import {
|
|
32
32
|
selectTenantAndCreateKey
|
|
33
33
|
} from "./cli-pq6rte0w.js";
|
package/package.json
CHANGED