@moda-ai/cli 1.38.0 → 1.39.0

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.
@@ -19,12 +19,13 @@ import {
19
19
  redactDeep,
20
20
  redactString,
21
21
  resolveApiKey,
22
+ resolveApiTenantId,
22
23
  resolveIngestUrl,
23
24
  resolveModaBaseUrl,
24
25
  resolveTenantId,
25
26
  shouldInventoryFile,
26
27
  stringOption
27
- } from "./cli-q79sq80a.js";
28
+ } from "./cli-rp912ypf.js";
28
29
  import {
29
30
  __commonJS,
30
31
  __require,
@@ -9157,7 +9158,7 @@ var require_source_map_support = __commonJS((exports, module) => {
9157
9158
 
9158
9159
  // ../../node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/typescript.js
9159
9160
  var require_typescript = __commonJS((exports, module) => {
9160
- var __dirname = "/home/runner/work/ModaObservability/ModaObservability/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib", __filename = "/home/runner/work/ModaObservability/ModaObservability/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/typescript.js";
9161
+ var __dirname = "/home/runner/_work/ModaObservability/ModaObservability/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib", __filename = "/home/runner/_work/ModaObservability/ModaObservability/node_modules/.bun/typescript@5.9.3/node_modules/typescript/lib/typescript.js";
9161
9162
  /*! *****************************************************************************
9162
9163
  Copyright (c) Microsoft Corporation. All rights reserved.
9163
9164
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
@@ -9453,7 +9454,7 @@ var require_typescript = __commonJS((exports, module) => {
9453
9454
  commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
9454
9455
  commentPragmas: () => commentPragmas,
9455
9456
  commonOptionsWithBuild: () => commonOptionsWithBuild,
9456
- compact: () => compact,
9457
+ compact: () => compact2,
9457
9458
  compareBooleans: () => compareBooleans,
9458
9459
  compareDataObjects: () => compareDataObjects,
9459
9460
  compareDiagnostics: () => compareDiagnostics,
@@ -11973,7 +11974,7 @@ var require_typescript = __commonJS((exports, module) => {
11973
11974
  }
11974
11975
  return true;
11975
11976
  }
11976
- function compact(array) {
11977
+ function compact2(array) {
11977
11978
  let result;
11978
11979
  if (array !== undefined) {
11979
11980
  for (let i = 0;i < array.length; i++) {
@@ -93165,7 +93166,7 @@ ${lanes.join(`
93165
93166
  if (!links2.hasReportedStatementInAmbientContext) {
93166
93167
  return links2.hasReportedStatementInAmbientContext = grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts);
93167
93168
  }
93168
- } else {}
93169
+ }
93169
93170
  }
93170
93171
  return false;
93171
93172
  }
@@ -97630,7 +97631,7 @@ ${lanes.join(`
97630
97631
  const savedPendingExpressions = pendingExpressions;
97631
97632
  pendingExpressions = undefined;
97632
97633
  node = factory2.updateBinaryExpression(node, visitNode(node.left, assignmentTargetVisitor, isExpression), node.operatorToken, visitNode(node.right, visitor, isExpression));
97633
- const expr = some(pendingExpressions) ? factory2.inlineExpressions(compact([...pendingExpressions, node])) : node;
97634
+ const expr = some(pendingExpressions) ? factory2.inlineExpressions(compact2([...pendingExpressions, node])) : node;
97634
97635
  pendingExpressions = savedPendingExpressions;
97635
97636
  return expr;
97636
97637
  }
@@ -102629,7 +102630,7 @@ ${lanes.join(`
102629
102630
  ], 2));
102630
102631
  setParentRecursive(requireStatement, false);
102631
102632
  statements = insertStatementAfterCustomPrologue(statements.slice(), requireStatement);
102632
- } else {}
102633
+ }
102633
102634
  }
102634
102635
  }
102635
102636
  if (statements !== visited.statements) {
@@ -107434,14 +107435,14 @@ ${lanes.join(`
107434
107435
  }
107435
107436
  }
107436
107437
  function createImportCallExpressionAMD(arg, containsLexicalThis) {
107437
- const resolve4 = factory2.createUniqueName("resolve");
107438
+ const resolve5 = factory2.createUniqueName("resolve");
107438
107439
  const reject = factory2.createUniqueName("reject");
107439
107440
  const parameters = [
107440
- factory2.createParameterDeclaration(undefined, undefined, resolve4),
107441
+ factory2.createParameterDeclaration(undefined, undefined, resolve5),
107441
107442
  factory2.createParameterDeclaration(undefined, undefined, reject)
107442
107443
  ];
107443
107444
  const body = factory2.createBlock([
107444
- factory2.createExpressionStatement(factory2.createCallExpression(factory2.createIdentifier("require"), undefined, [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve4, reject]))
107445
+ factory2.createExpressionStatement(factory2.createCallExpression(factory2.createIdentifier("require"), undefined, [factory2.createArrayLiteralExpression([arg || factory2.createOmittedExpression()]), resolve5, reject]))
107445
107446
  ]);
107446
107447
  let func;
107447
107448
  if (languageVersion >= 2) {
@@ -110422,7 +110423,7 @@ ${lanes.join(`
110422
110423
  let parameterProperties;
110423
110424
  if (ctor) {
110424
110425
  const oldDiag2 = getSymbolAccessibilityDiagnostic;
110425
- parameterProperties = compact(flatMap(ctor.parameters, (param) => {
110426
+ parameterProperties = compact2(flatMap(ctor.parameters, (param) => {
110426
110427
  if (!hasSyntacticModifier(param, 31) || shouldStripInternal(param))
110427
110428
  return;
110428
110429
  getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
@@ -141755,7 +141756,7 @@ ${newComment.split(`
141755
141756
  }
141756
141757
  const checker = context.program.getTypeChecker();
141757
141758
  const trackChanges = (cb) => ts_textChanges_exports.ChangeTracker.with(context, cb);
141758
- return compact([
141759
+ return compact2([
141759
141760
  getDeclarationSiteFix(context, expression, errorCode, checker, trackChanges),
141760
141761
  getUseSiteFix(context, expression, errorCode, checker, trackChanges)
141761
141762
  ]);
@@ -160749,7 +160750,7 @@ ${content}
160749
160750
  const lastToken = last(children);
160750
160751
  const separateLastToken = separateTrailingSemicolon && lastToken.kind === 27;
160751
160752
  const rightChildren = children.slice(splitTokenIndex + 1, separateLastToken ? children.length - 1 : undefined);
160752
- const result = compact([
160753
+ const result = compact2([
160753
160754
  leftChildren.length ? createSyntaxList2(leftChildren) : undefined,
160754
160755
  splitToken,
160755
160756
  rightChildren.length ? createSyntaxList2(rightChildren) : undefined
@@ -165453,7 +165454,7 @@ ${options.prefix}` : `
165453
165454
  commandLineOptionOfCustomType: () => commandLineOptionOfCustomType,
165454
165455
  commentPragmas: () => commentPragmas,
165455
165456
  commonOptionsWithBuild: () => commonOptionsWithBuild,
165456
- compact: () => compact,
165457
+ compact: () => compact2,
165457
165458
  compareBooleans: () => compareBooleans,
165458
165459
  compareDataObjects: () => compareDataObjects,
165459
165460
  compareDiagnostics: () => compareDiagnostics,
@@ -177616,8 +177617,8 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
177616
177617
  installPackage(options) {
177617
177618
  this.packageInstallId++;
177618
177619
  const request = { kind: "installPackage", ...options, id: this.packageInstallId };
177619
- const promise = new Promise((resolve4, reject) => {
177620
- (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map)).set(this.packageInstallId, { resolve: resolve4, reject });
177620
+ const promise = new Promise((resolve5, reject) => {
177621
+ (this.packageInstalledPromise ?? (this.packageInstalledPromise = /* @__PURE__ */ new Map)).set(this.packageInstallId, { resolve: resolve5, reject });
177621
177622
  });
177622
177623
  this.installer.send(request);
177623
177624
  return promise;
@@ -177886,14 +177887,18 @@ import {
177886
177887
  lstatSync as lstatSync7,
177887
177888
  mkdtempSync,
177888
177889
  mkdirSync as mkdirSync4,
177889
- readFileSync as readFileSync12,
177890
+ readFileSync as readFileSync13,
177890
177891
  readdirSync,
177891
177892
  writeFileSync as writeFileSync4,
177892
177893
  rmSync
177893
177894
  } from "node:fs";
177894
- import { basename as basename4, delimiter, dirname as dirname5, join as join4, relative as relative6, resolve as resolve10, sep as sep2 } from "node:path";
177895
+ import { basename as basename4, delimiter, dirname as dirname5, join as join4, relative as relative6, resolve as resolve11, sep as sep2 } from "node:path";
177895
177896
  import { confirm as confirm2, select } from "@inquirer/prompts";
177896
177897
 
177898
+ // src/parity-commands.ts
177899
+ import { readFileSync } from "node:fs";
177900
+ import { resolve } from "node:path";
177901
+
177897
177902
  // src/api-client.ts
177898
177903
  var REQUEST_TIMEOUT_MS = 30000;
177899
177904
  var MAX_RETRIES = 3;
@@ -177918,6 +177923,12 @@ class NetworkError extends Error {
177918
177923
  this.name = "NetworkError";
177919
177924
  }
177920
177925
  }
177926
+ function networkErrorMessage(error, url) {
177927
+ const message = error instanceof Error ? error.message : String(error);
177928
+ const cause = error instanceof Error ? error.cause : undefined;
177929
+ const code = typeof cause?.code === "string" ? `: ${cause.code}` : "";
177930
+ return `Network error: ${message} (could not reach ${url.split("?")[0]}${code})`;
177931
+ }
177921
177932
  function isRetryable(status) {
177922
177933
  return status === 429 || status >= 500;
177923
177934
  }
@@ -177932,7 +177943,8 @@ async function callControlAPI(endpoint, options = {}, profileOptions = {}, reque
177932
177943
  }
177933
177944
  async function callModaAPI(url, options, profileOptions = {}, requestOptions = {}) {
177934
177945
  const timeoutMs = requestOptions.timeoutMs ?? REQUEST_TIMEOUT_MS;
177935
- const maxRetries = requestOptions.retries ?? MAX_RETRIES;
177946
+ const method = (options.method ?? "GET").toUpperCase();
177947
+ const maxRetries = requestOptions.retries ?? (method === "GET" || method === "HEAD" ? MAX_RETRIES : 0);
177936
177948
  const initialNetworkRetryBudget = requestOptions.retryOnceOnNetworkError ? 1 : 0;
177937
177949
  let networkRetryBudget = initialNetworkRetryBudget;
177938
177950
  let connectionClose = false;
@@ -177963,12 +177975,17 @@ async function callModaAPI(url, options, profileOptions = {}, requestOptions = {
177963
177975
  }
177964
177976
  throw error;
177965
177977
  }
177966
- return response.json();
177978
+ if (response.status === 204)
177979
+ return null;
177980
+ if (typeof response.text !== "function")
177981
+ return response.json();
177982
+ const text = await response.text();
177983
+ return text.trim() === "" ? null : JSON.parse(text);
177967
177984
  } catch (error) {
177968
177985
  if (error instanceof ApiError)
177969
177986
  throw error;
177970
177987
  const isAbort = error instanceof DOMException && error.name === "AbortError";
177971
- const wrapped = isAbort ? new Error(`Request timed out after ${timeoutMs}ms: ${url}`) : new NetworkError(`Network error: ${error instanceof Error ? error.message : String(error)}`);
177988
+ const wrapped = isAbort ? new Error(`Request timed out after ${timeoutMs}ms: ${url}`) : new NetworkError(networkErrorMessage(error, url));
177972
177989
  if (attempt < maxRetries) {
177973
177990
  continue;
177974
177991
  }
@@ -177992,6 +178009,459 @@ function resetApiRequestCount() {
177992
178009
  apiRequestCount = 0;
177993
178010
  }
177994
178011
 
178012
+ // src/parity-commands.ts
178013
+ var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
178014
+ var WINDOWS = ["24h", "7d", "30d", "90d"];
178015
+ function profileOptions(context) {
178016
+ return { profile: context.profile, env: context.env };
178017
+ }
178018
+ function requireKey(context) {
178019
+ if (!resolveApiKey(profileOptions(context))) {
178020
+ throw new CliInputError(`No Moda API key found for moda ${context.command}.`, "Set MODA_API_KEY, run `moda auth login --api-key`, or select a profile with an API key.");
178021
+ }
178022
+ }
178023
+ function requireTenant(context) {
178024
+ const key = resolveApiKey(profileOptions(context));
178025
+ const keyTenant = key ? embeddedTenantIdFromApiKey(key) : undefined;
178026
+ const flagTenant = context.flags["tenant-id"];
178027
+ if (flagTenant && keyTenant && flagTenant !== keyTenant) {
178028
+ throw new CliInputError(`--tenant-id=${flagTenant} does not match this API key's tenant (${keyTenant}), so nothing was sent.`, "Drop --tenant-id (the key names its tenant) or use a key for that tenant.");
178029
+ }
178030
+ const tenantId = flagTenant || resolveApiTenantId(profileOptions(context));
178031
+ if (!tenantId) {
178032
+ throw new CliInputError("Could not determine the tenant.", "Use a signed API key (it names its tenant), set MODA_TENANT_ID, or pass --tenant-id=<id>.");
178033
+ }
178034
+ return tenantId;
178035
+ }
178036
+ function assertFlags(command, flags, allowed) {
178037
+ if (command.startsWith("signals "))
178038
+ allowed = [...allowed, "tenant-id"];
178039
+ const globals = [
178040
+ "agent",
178041
+ "json",
178042
+ "human",
178043
+ "prose",
178044
+ "quiet",
178045
+ "verbose",
178046
+ "yes",
178047
+ "profile",
178048
+ "progress",
178049
+ "format",
178050
+ "no-telemetry",
178051
+ "no-update-check",
178052
+ "help",
178053
+ "version",
178054
+ "json-schemas",
178055
+ "stream",
178056
+ "no-stream",
178057
+ "tui",
178058
+ "no-tui"
178059
+ ];
178060
+ const known = new Set([...allowed, ...globals]);
178061
+ const unknown = Object.keys(flags).filter((flag) => !known.has(flag));
178062
+ if (unknown.includes("dry-run")) {
178063
+ throw new CliInputError(`'moda ${command}' has no dry-run mode, so nothing was sent.`, "Remove --dry-run to run it for real.");
178064
+ }
178065
+ if (unknown.length > 0) {
178066
+ throw new CliInputError(`Unknown flag${unknown.length > 1 ? "s" : ""} ${unknown.map((flag) => `--${flag}`).join(", ")} for 'moda ${command}'.`, `Valid flags: ${allowed.map((flag) => `--${flag}`).join(", ") || "(none)"}.`);
178067
+ }
178068
+ }
178069
+ function assertPositionals(command, positionals, max, usage) {
178070
+ if (positionals.length > max) {
178071
+ throw new CliInputError(`Unexpected argument${positionals.length - max > 1 ? "s" : ""} '${positionals.slice(max).join(" ")}' for 'moda ${command}', so nothing was sent.`, `Usage: ${usage}`);
178072
+ }
178073
+ }
178074
+ function oneOf(name, value, allowed) {
178075
+ if (value === undefined)
178076
+ return;
178077
+ if (!allowed.includes(value)) {
178078
+ throw new CliInputError(`--${name} must be one of ${allowed.join(", ")} (got '${value}').`);
178079
+ }
178080
+ return value;
178081
+ }
178082
+ function csv(value) {
178083
+ if (value === undefined)
178084
+ return;
178085
+ const items = value.split(",").map((item) => item.trim()).filter(Boolean);
178086
+ return items.length > 0 ? items : undefined;
178087
+ }
178088
+ function readBodyFile(flags, cwd) {
178089
+ if (!flags.file)
178090
+ return {};
178091
+ if (flags.file === "true")
178092
+ throw new CliInputError("Missing path for --file.");
178093
+ let parsed;
178094
+ try {
178095
+ parsed = JSON.parse(readFileSync(resolve(cwd, flags.file), "utf8"));
178096
+ } catch (error) {
178097
+ throw new CliInputError(`Could not read --file ${flags.file}: ${error instanceof Error ? error.message : String(error)}`);
178098
+ }
178099
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
178100
+ throw new CliInputError("--file must contain a JSON object (the request body).");
178101
+ }
178102
+ return parsed;
178103
+ }
178104
+ function compact(value) {
178105
+ return Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
178106
+ }
178107
+ var LLM_WRITE_TIMEOUT_MS = 180000;
178108
+ async function send(context, plane, method, endpoint, body, options = {}) {
178109
+ const init = { method, ...body !== undefined ? { body: JSON.stringify(body) } : {} };
178110
+ if (method !== "GET" && context.dryRun) {
178111
+ context.output.writeData({
178112
+ dryRun: true,
178113
+ planned: { method, endpoint: plane === "data" ? `/api/v1/data${endpoint}` : `/api${endpoint}`, ...body !== undefined ? { body } : {} }
178114
+ }, { summary: { text: `Dry run: would ${method} ${endpoint}. Nothing was sent.`, confidence: "high" } });
178115
+ return;
178116
+ }
178117
+ const requestOptions = method === "GET" ? {} : { retries: 0, ...options.slow ? { timeoutMs: LLM_WRITE_TIMEOUT_MS } : {} };
178118
+ const data = plane === "data" ? await callDataAPI(endpoint, init, requestOptions) : await callControlAPI(endpoint, init, profileOptions(context), requestOptions);
178119
+ context.output.writeData(data ?? { ok: true });
178120
+ }
178121
+ var USER_COHORTS = ["all", "power_users", "heavy_tool_users", "frustrated", "at_risk", "new_this_week", "silent_sufferers"];
178122
+ var USER_SORTS = ["last_seen", "health_score", "conversation_count", "frustration_max"];
178123
+ var HEALTH = ["healthy", "at_risk", "frustrated"];
178124
+ async function runUsersCommand(context) {
178125
+ const flags = context.flags;
178126
+ assertFlags("users", flags, [
178127
+ "window",
178128
+ "page",
178129
+ "page-size",
178130
+ "search",
178131
+ "cohort",
178132
+ "sort",
178133
+ "order",
178134
+ "health-status",
178135
+ "min-health",
178136
+ "max-health",
178137
+ "min-conversations",
178138
+ "min-tool-failures",
178139
+ "tenant-id"
178140
+ ]);
178141
+ if (context.positionals.length > 0) {
178142
+ throw new CliInputError(`'moda users' takes no arguments. For one user use 'moda user <user_id>'.`);
178143
+ }
178144
+ requireKey(context);
178145
+ const tenantId = requireTenant(context);
178146
+ const query = new URLSearchParams(compact({
178147
+ window: oneOf("window", flags.window, WINDOWS),
178148
+ page: flags.page,
178149
+ pageSize: flags["page-size"],
178150
+ search: flags.search,
178151
+ cohort: oneOf("cohort", flags.cohort, USER_COHORTS),
178152
+ sortBy: oneOf("sort", flags.sort, USER_SORTS),
178153
+ sortOrder: oneOf("order", flags.order, ["asc", "desc"]),
178154
+ healthStatus: csv(flags["health-status"])?.map((value) => oneOf("health-status", value, HEALTH)).join(","),
178155
+ minHealthScore: flags["min-health"],
178156
+ maxHealthScore: flags["max-health"],
178157
+ minConversations: flags["min-conversations"],
178158
+ minToolFailures: flags["min-tool-failures"]
178159
+ }));
178160
+ const suffix = query.toString() ? `?${query.toString()}` : "";
178161
+ await send(context, "control", "GET", `/tenants/${encodeURIComponent(tenantId)}/users${suffix}`);
178162
+ return { exitCode: 0 };
178163
+ }
178164
+ async function runUserCommand(context) {
178165
+ const flags = context.flags;
178166
+ assertFlags("user", flags, ["window", "activity-cursor", "tenant-id"]);
178167
+ assertPositionals("user", context.positionals, 1, "moda user <user_id> [--window=24h|7d|30d|90d]");
178168
+ const userId = context.positionals[0];
178169
+ if (!userId)
178170
+ throw new CliInputError("<user_id> is required.", "Usage: moda user <user_id> [--window=24h|7d|30d|90d]");
178171
+ requireKey(context);
178172
+ const tenantId = requireTenant(context);
178173
+ const query = new URLSearchParams(compact({
178174
+ window: oneOf("window", flags.window, WINDOWS),
178175
+ activityCursor: flags["activity-cursor"]
178176
+ }));
178177
+ const suffix = query.toString() ? `?${query.toString()}` : "";
178178
+ await send(context, "control", "GET", `/tenants/${encodeURIComponent(tenantId)}/users/${encodeURIComponent(userId)}${suffix}`);
178179
+ return { exitCode: 0 };
178180
+ }
178181
+ async function runProblemReopenCommand(context) {
178182
+ assertFlags("problem-reopen", context.flags, ["reason", "dry-run"]);
178183
+ assertPositionals("problem-reopen", context.positionals, 1, "moda problem-reopen <problem_id> [--reason=TEXT]");
178184
+ const problemId = context.positionals[0];
178185
+ const usage = "Usage: moda problem-reopen <problem_id> [--reason=TEXT]";
178186
+ if (!problemId || !UUID_RE.test(problemId))
178187
+ throw new CliInputError("<problem_id> (UUID) is required.", usage);
178188
+ const reason = context.flags.reason;
178189
+ if (reason !== undefined && reason.length > 500)
178190
+ throw new CliInputError("--reason must be 500 characters or fewer.");
178191
+ requireKey(context);
178192
+ await send(context, "data", "POST", `/problems/${problemId}/reopen`, compact({ reason }));
178193
+ return { exitCode: 0 };
178194
+ }
178195
+ var SIGNAL_FIELD_FLAGS = [
178196
+ "name",
178197
+ "description",
178198
+ "pass-criteria",
178199
+ "fail-criteria",
178200
+ "polarity",
178201
+ "locus",
178202
+ "tool-names",
178203
+ "keyword-hints",
178204
+ "use-case-id",
178205
+ "message-types",
178206
+ "note",
178207
+ "file"
178208
+ ];
178209
+ function signalBody(flags, cwd) {
178210
+ const fromFile = readBodyFile(flags, cwd);
178211
+ const scope = compact({
178212
+ toolNames: csv(flags["tool-names"]),
178213
+ keywordHints: csv(flags["keyword-hints"]),
178214
+ useCaseId: flags["use-case-id"],
178215
+ messageTypes: csv(flags["message-types"])
178216
+ });
178217
+ return {
178218
+ ...fromFile,
178219
+ ...compact({
178220
+ name: flags.name,
178221
+ description: flags.description,
178222
+ passCriteria: flags["pass-criteria"],
178223
+ failCriteria: flags["fail-criteria"],
178224
+ polarity: oneOf("polarity", flags.polarity, ["violation", "expectation"]),
178225
+ locus: oneOf("locus", flags.locus, ["agent", "tool_output", "user_input"]),
178226
+ note: flags.note
178227
+ }),
178228
+ ...Object.keys(scope).length > 0 ? { scope: { ...fromFile.scope ?? {}, ...scope } } : {}
178229
+ };
178230
+ }
178231
+ var SIGNAL_USAGE = [
178232
+ "moda signals list custom signals",
178233
+ 'moda signals draft --note="…" AI-draft criteria from a description',
178234
+ "moda signals create --name --description --pass-criteria --fail-criteria [--polarity --locus --tool-names=a,b] [--file=body.json]",
178235
+ "moda signals update <id> [same flags] edit a signal",
178236
+ "moda signals activate|pause|delete <id> (delete: drafts only; archive is dashboard-only)",
178237
+ "moda signals examples <id> add|update|remove --conversation-id=ID [--label=fits|does_not_fit --note --msg-index]",
178238
+ 'moda signals refine <id> --request="…" propose a criteria edit',
178239
+ "moda signals revise <id> --conversation-ids=a,b re-derive criteria from labelled traces",
178240
+ "moda signals proposals <id> | accept <id> <proposal_id> | reject <id> <proposal_id>",
178241
+ "moda signals search <id> [--mode=wizard|full] | search-status <id> <search_id> | search-stop <id> <search_id>",
178242
+ "moda signals preview --file=detector.json [--conversation-ids=a,b --max-examples=N]",
178243
+ "All write subcommands accept --dry-run (prints the request, sends nothing)."
178244
+ ].join(`
178245
+ `);
178246
+ async function runSignalsManagementCommand(sub, context) {
178247
+ const flags = context.flags;
178248
+ const args = context.positionals.slice(1);
178249
+ const arity = {
178250
+ draft: 0,
178251
+ create: 0,
178252
+ preview: 0,
178253
+ update: 1,
178254
+ activate: 1,
178255
+ pause: 1,
178256
+ delete: 1,
178257
+ examples: 2,
178258
+ refine: 1,
178259
+ revise: 1,
178260
+ proposals: 1,
178261
+ accept: 2,
178262
+ reject: 2,
178263
+ search: 1,
178264
+ "search-status": 2,
178265
+ "search-stop": 2
178266
+ };
178267
+ if (sub in arity)
178268
+ assertPositionals(`signals ${sub}`, args, arity[sub], SIGNAL_USAGE.split(`
178269
+ `)[0]);
178270
+ const base = () => `/tenants/${encodeURIComponent(requireTenant(context))}/custom-signals`;
178271
+ const id = (index = 0, what = "a signal id") => {
178272
+ const value = args[index];
178273
+ if (!value)
178274
+ throw new CliInputError(`moda signals ${sub} needs ${what}.`, `Usage:
178275
+ ${SIGNAL_USAGE}`);
178276
+ return encodeURIComponent(value);
178277
+ };
178278
+ const start = () => requireKey(context);
178279
+ switch (sub) {
178280
+ case "draft": {
178281
+ assertFlags("signals draft", flags, ["note", "file", "dry-run"]);
178282
+ const body = { ...readBodyFile(flags, context.cwd), ...compact({ note: flags.note }) };
178283
+ if (!body.note)
178284
+ throw new CliInputError("--note is required (describe what the signal should catch).");
178285
+ start();
178286
+ await send(context, "control", "POST", `${base()}/draft`, body, { slow: true });
178287
+ return { exitCode: 0 };
178288
+ }
178289
+ case "create": {
178290
+ assertFlags("signals create", flags, [...SIGNAL_FIELD_FLAGS, "dry-run"]);
178291
+ const body = signalBody(flags, context.cwd);
178292
+ const missing = ["name", "description", "passCriteria", "failCriteria"].filter((field) => !body[field]);
178293
+ if (missing.length > 0) {
178294
+ throw new CliInputError(`Missing ${missing.join(", ")} for signals create.`, 'Pass --name --description --pass-criteria --fail-criteria, or a --file with those fields. Tip: `moda signals draft --note="…"` drafts them.');
178295
+ }
178296
+ start();
178297
+ await send(context, "control", "POST", base(), body);
178298
+ return { exitCode: 0 };
178299
+ }
178300
+ case "update": {
178301
+ assertFlags("signals update", flags, [...SIGNAL_FIELD_FLAGS, "dry-run"]);
178302
+ const signalId = id();
178303
+ const body = signalBody(flags, context.cwd);
178304
+ if (Object.keys(body).length === 0)
178305
+ throw new CliInputError("Nothing to update: pass at least one field flag or --file.");
178306
+ start();
178307
+ await send(context, "control", "PATCH", `${base()}/${signalId}`, body);
178308
+ return { exitCode: 0 };
178309
+ }
178310
+ case "activate":
178311
+ case "pause": {
178312
+ assertFlags(`signals ${sub}`, flags, ["dry-run"]);
178313
+ const signalId = id();
178314
+ start();
178315
+ await send(context, "control", "POST", `${base()}/${signalId}/${sub}`);
178316
+ return { exitCode: 0 };
178317
+ }
178318
+ case "delete": {
178319
+ assertFlags("signals delete", flags, ["dry-run"]);
178320
+ const signalId = id();
178321
+ start();
178322
+ await send(context, "control", "DELETE", `${base()}/${signalId}`);
178323
+ return { exitCode: 0 };
178324
+ }
178325
+ case "examples": {
178326
+ const signalId = id();
178327
+ const action = args[1];
178328
+ const conversationId = flags["conversation-id"];
178329
+ if (!action || !["add", "update", "remove"].includes(action)) {
178330
+ throw new CliInputError("Usage: moda signals examples <id> add|update|remove --conversation-id=ID …");
178331
+ }
178332
+ if (!conversationId)
178333
+ throw new CliInputError("--conversation-id is required.");
178334
+ if (action === "add") {
178335
+ assertFlags("signals examples add", flags, ["conversation-id", "label", "note", "msg-index", "msg-dedup-token", "criteria", "verdict", "dry-run"]);
178336
+ const label = oneOf("label", flags.label, ["fits", "does_not_fit"]);
178337
+ if (!label)
178338
+ throw new CliInputError("--label=fits|does_not_fit is required.");
178339
+ start();
178340
+ await send(context, "control", "POST", `${base()}/${signalId}/examples`, compact({
178341
+ conversationId,
178342
+ label,
178343
+ source: "api",
178344
+ note: flags.note,
178345
+ msgIndex: flags["msg-index"] !== undefined ? Number(flags["msg-index"]) : undefined,
178346
+ msgDedupToken: flags["msg-dedup-token"],
178347
+ criteria: oneOf("criteria", flags.criteria, ["pass", "fail"]),
178348
+ verdict: oneOf("verdict", flags.verdict, ["accept", "reject"])
178349
+ }));
178350
+ } else if (action === "update") {
178351
+ assertFlags("signals examples update", flags, ["conversation-id", "label", "note", "blurb", "dry-run"]);
178352
+ const body = compact({ label: oneOf("label", flags.label, ["fits", "does_not_fit"]), note: flags.note, blurb: flags.blurb });
178353
+ if (Object.keys(body).length === 0)
178354
+ throw new CliInputError("Nothing to update: pass --label, --note, or --blurb.");
178355
+ start();
178356
+ await send(context, "control", "PATCH", `${base()}/${signalId}/examples/${encodeURIComponent(conversationId)}`, body);
178357
+ } else {
178358
+ assertFlags("signals examples remove", flags, ["conversation-id", "dry-run"]);
178359
+ start();
178360
+ await send(context, "control", "DELETE", `${base()}/${signalId}/examples/${encodeURIComponent(conversationId)}`);
178361
+ }
178362
+ return { exitCode: 0 };
178363
+ }
178364
+ case "refine": {
178365
+ assertFlags("signals refine", flags, ["request", "dry-run"]);
178366
+ const signalId = id();
178367
+ const request = flags.request;
178368
+ if (!request || request.length > 2000)
178369
+ throw new CliInputError("--request (1–2000 characters) is required.");
178370
+ start();
178371
+ await send(context, "control", "POST", `${base()}/${signalId}/refine`, { request }, { slow: true });
178372
+ return { exitCode: 0 };
178373
+ }
178374
+ case "revise": {
178375
+ assertFlags("signals revise", flags, ["conversation-ids", "dry-run"]);
178376
+ const signalId = id();
178377
+ const conversationIds = csv(flags["conversation-ids"]);
178378
+ if (!conversationIds)
178379
+ throw new CliInputError("--conversation-ids=a,b is required.");
178380
+ start();
178381
+ await send(context, "control", "POST", `${base()}/${signalId}/revise`, { conversationIds }, { slow: true });
178382
+ return { exitCode: 0 };
178383
+ }
178384
+ case "proposals": {
178385
+ assertFlags("signals proposals", flags, []);
178386
+ const signalId = id();
178387
+ start();
178388
+ await send(context, "control", "GET", `${base()}/${signalId}/proposals`);
178389
+ return { exitCode: 0 };
178390
+ }
178391
+ case "accept":
178392
+ case "reject": {
178393
+ assertFlags(`signals ${sub}`, flags, ["dry-run"]);
178394
+ const signalId = id();
178395
+ const proposalId = id(1, "a proposal id (see `moda signals proposals <id>`)");
178396
+ start();
178397
+ await send(context, "control", "POST", `${base()}/${signalId}/proposals/${proposalId}/${sub}`);
178398
+ return { exitCode: 0 };
178399
+ }
178400
+ case "search": {
178401
+ assertFlags("signals search", flags, ["mode", "exclude-conversation-ids", "dry-run"]);
178402
+ const signalId = id();
178403
+ start();
178404
+ await send(context, "control", "POST", `${base()}/${signalId}/search`, compact({
178405
+ mode: oneOf("mode", flags.mode, ["wizard", "full"]),
178406
+ excludeConversationIds: csv(flags["exclude-conversation-ids"])
178407
+ }), { slow: true });
178408
+ return { exitCode: 0 };
178409
+ }
178410
+ case "search-status":
178411
+ case "search-stop": {
178412
+ assertFlags(`signals ${sub}`, flags, sub === "search-stop" ? ["dry-run"] : []);
178413
+ const signalId = id();
178414
+ const searchId = id(1, "a search id (returned by `moda signals search <id>`)");
178415
+ start();
178416
+ await send(context, "control", sub === "search-stop" ? "POST" : "GET", `${base()}/${signalId}/searches/${searchId}${sub === "search-stop" ? "/stop" : ""}`);
178417
+ return { exitCode: 0 };
178418
+ }
178419
+ case "preview": {
178420
+ assertFlags("signals preview", flags, ["file", "conversation-ids", "max-examples"]);
178421
+ const body = readBodyFile(flags, context.cwd);
178422
+ if (!body.detector)
178423
+ throw new CliInputError('--file must contain {"detector": {...}} (optionally scope).');
178424
+ start();
178425
+ await send(context, "control", "POST", `${base()}/detector-preview`, {
178426
+ ...body,
178427
+ ...compact({
178428
+ conversationIds: csv(flags["conversation-ids"]),
178429
+ maxExamples: flags["max-examples"] !== undefined ? Number(flags["max-examples"]) : undefined
178430
+ })
178431
+ });
178432
+ return { exitCode: 0 };
178433
+ }
178434
+ default:
178435
+ throw unknownSignalsSubcommandError(sub, args);
178436
+ }
178437
+ }
178438
+ var SIGNALS_MANAGEMENT_SUBCOMMANDS = new Set([
178439
+ "draft",
178440
+ "create",
178441
+ "update",
178442
+ "activate",
178443
+ "pause",
178444
+ "delete",
178445
+ "examples",
178446
+ "refine",
178447
+ "revise",
178448
+ "proposals",
178449
+ "accept",
178450
+ "reject",
178451
+ "search",
178452
+ "search-status",
178453
+ "search-stop",
178454
+ "preview"
178455
+ ]);
178456
+ function unknownSignalsSubcommandError(sub, args = []) {
178457
+ if (sub === "archive") {
178458
+ const id = args[0] ?? "<signal_id>";
178459
+ return new CliInputError(`Unknown signals subcommand 'archive': archiving a signal is dashboard-only, so nothing was sent.`, `To stop a signal from running, pause it: moda signals pause ${id}. Drafts can be deleted with moda signals delete ${id}.`);
178460
+ }
178461
+ return new CliInputError(`Unknown signals subcommand '${sub}', so nothing was sent. Valid subcommands: ${[...SIGNALS_MANAGEMENT_SUBCOMMANDS].join(", ")}.`, `Bare 'moda signals' lists custom signals; 'moda signal <signal_id>' opens one. Usage:
178462
+ ${SIGNAL_USAGE}`);
178463
+ }
178464
+
177995
178465
  // src/analyst-tui.ts
177996
178466
  class AnalystTui {
177997
178467
  state;
@@ -178096,16 +178566,16 @@ class AnalystTui {
178096
178566
  this.active = false;
178097
178567
  }
178098
178568
  pushTimeline(label, message) {
178099
- const compact = compactWhitespace(message);
178100
- if (!compact)
178569
+ const compact2 = compactWhitespace(message);
178570
+ if (!compact2)
178101
178571
  return;
178102
178572
  const last = this.state.timeline.at(-1);
178103
- if (last?.label === label && last.message === compact)
178573
+ if (last?.label === label && last.message === compact2)
178104
178574
  return;
178105
178575
  this.state.timeline.push({
178106
178576
  time: timeOfDay(new Date),
178107
178577
  label,
178108
- message: compact
178578
+ message: compact2
178109
178579
  });
178110
178580
  if (this.state.timeline.length > 80)
178111
178581
  this.state.timeline.splice(0, this.state.timeline.length - 80);
@@ -178281,7 +178751,7 @@ function stripAnsi(value) {
178281
178751
  }
178282
178752
 
178283
178753
  // src/harness-remote.ts
178284
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
178754
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
178285
178755
  import { join as join2 } from "node:path";
178286
178756
 
178287
178757
  // src/markdown-terminal.ts
@@ -178429,10 +178899,10 @@ import {
178429
178899
  existsSync,
178430
178900
  lstatSync,
178431
178901
  mkdirSync,
178432
- readFileSync,
178902
+ readFileSync as readFileSync2,
178433
178903
  writeFileSync
178434
178904
  } from "node:fs";
178435
- import { basename, dirname, join, relative, resolve } from "node:path";
178905
+ import { basename, dirname, join, relative, resolve as resolve2 } from "node:path";
178436
178906
  import { confirm } from "@inquirer/prompts";
178437
178907
  var HARNESS_REPORT_SCHEMA_VERSION = "harness_report.v0.1";
178438
178908
  var HARNESS_REPORT_VALIDATION_SCHEMA_VERSION = "harness_report_validation.v0.1";
@@ -178950,12 +179420,12 @@ function loadHarnessReportForSync(rootDir, reportPath, options) {
178950
179420
  `));
178951
179421
  }
178952
179422
  const approvalPath = join(rootDir, HARNESS_REPORT_APPROVAL_PATH);
178953
- const approval = existsSync(approvalPath) ? JSON.parse(readFileSync(approvalPath, "utf8")) : null;
179423
+ const approval = existsSync(approvalPath) ? JSON.parse(readFileSync2(approvalPath, "utf8")) : null;
178954
179424
  const approved = approval?.schemaVersion === HARNESS_REPORT_APPROVAL_SCHEMA_VERSION && approval.reportId === report.reportId && approval.reportHash === hashHarnessReport(report) && approval.approved === true;
178955
179425
  return { report, validation, approval, approved };
178956
179426
  }
178957
179427
  function readHarnessReport(reportPath) {
178958
- return normalizeHarnessReport(JSON.parse(readFileSync(reportPath, "utf8")));
179428
+ return normalizeHarnessReport(JSON.parse(readFileSync2(reportPath, "utf8")));
178959
179429
  }
178960
179430
  function normalizeHarnessReport(value) {
178961
179431
  const report = cloneJson(value);
@@ -179546,7 +180016,7 @@ function limitReportEvidence(claims, citations) {
179546
180016
  };
179547
180017
  }
179548
180018
  function resolveHarnessReportPath(rootDir, value) {
179549
- return resolve(rootDir, value && value !== "true" ? value : HARNESS_REPORT_PATH);
180019
+ return resolve2(rootDir, value && value !== "true" ? value : HARNESS_REPORT_PATH);
179550
180020
  }
179551
180021
  function writeHarnessReportArtifacts(options) {
179552
180022
  const written = [];
@@ -179683,14 +180153,14 @@ function upsertCitation(citations, citationIndex, evidence, rootDir) {
179683
180153
  function citationExcerpt(rootDir, path, line) {
179684
180154
  if (isUnsafeCitationPath(path))
179685
180155
  return {};
179686
- const absPath = resolve(rootDir, path);
180156
+ const absPath = resolve2(rootDir, path);
179687
180157
  if (!isInside(rootDir, absPath) || !existsSync(absPath))
179688
180158
  return {};
179689
180159
  try {
179690
180160
  const stat = lstatSync(absPath);
179691
180161
  if (!stat.isFile() || stat.isSymbolicLink() || stat.size > 128 * 1024)
179692
180162
  return {};
179693
- const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
180163
+ const lines = readFileSync2(absPath, "utf8").split(/\r?\n/);
179694
180164
  const selected = line ? lines[line - 1] : lines.find((candidate) => candidate.trim().length > 0);
179695
180165
  if (!selected)
179696
180166
  return {};
@@ -179828,7 +180298,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
179828
180298
  errors.push(`Citation ${citation.id} points to an unsafe path.`);
179829
180299
  return;
179830
180300
  }
179831
- const absPath = resolve(rootDir, citation.path);
180301
+ const absPath = resolve2(rootDir, citation.path);
179832
180302
  if (!isInside(rootDir, absPath)) {
179833
180303
  errors.push(`Citation ${citation.id} points outside the harness root.`);
179834
180304
  return;
@@ -179847,7 +180317,7 @@ function validateCitation(citation, rootDir, errors, warnings, options) {
179847
180317
  }
179848
180318
  if (!stat.isFile())
179849
180319
  errors.push(`Citation ${citation.id} does not point to a file.`);
179850
- const lines = readFileSync(absPath, "utf8").split(/\r?\n/);
180320
+ const lines = readFileSync2(absPath, "utf8").split(/\r?\n/);
179851
180321
  if (citation.line !== undefined) {
179852
180322
  const lineCount = lines.length;
179853
180323
  if (citation.line < 1 || citation.line > lineCount) {
@@ -179898,7 +180368,7 @@ function isSecretishPath2(path) {
179898
180368
  return name === ".env" || name.startsWith(".env.") || name.includes("secret") || name.includes("private-key") || name.endsWith(".pem");
179899
180369
  }
179900
180370
  function isInside(rootDir, absPath) {
179901
- const rel = relative(resolve(rootDir), resolve(absPath));
180371
+ const rel = relative(resolve2(rootDir), resolve2(absPath));
179902
180372
  return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
179903
180373
  }
179904
180374
  function writeJson(path, value) {
@@ -179958,7 +180428,7 @@ function readRemoteRunState(rootDir) {
179958
180428
  if (!existsSync2(path))
179959
180429
  return;
179960
180430
  try {
179961
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
180431
+ const parsed = JSON.parse(readFileSync3(path, "utf8"));
179962
180432
  if (!parsed || typeof parsed.run_id !== "string" || parsed.run_id.length === 0)
179963
180433
  return;
179964
180434
  return {
@@ -180317,8 +180787,8 @@ async function remoteAnalyzeFetch(url, apiKey, init, timeoutMs) {
180317
180787
  }
180318
180788
 
180319
180789
  // src/harness-artifact-bodies.ts
180320
- import { existsSync as existsSync3, lstatSync as lstatSync2, readFileSync as readFileSync3, realpathSync } from "node:fs";
180321
- import { basename as basename2, dirname as dirname2, isAbsolute, relative as relative2, resolve as resolve2 } from "node:path";
180790
+ import { existsSync as existsSync3, lstatSync as lstatSync2, readFileSync as readFileSync4, realpathSync } from "node:fs";
180791
+ import { basename as basename2, dirname as dirname2, isAbsolute, relative as relative2, resolve as resolve3 } from "node:path";
180322
180792
  var MAX_SCANNED_FILE_BYTES2 = 512 * 1024;
180323
180793
  var SNAPSHOT_BUDGET_SKIP_REASONS = new Set([
180324
180794
  "file too large for harness scan",
@@ -180381,13 +180851,13 @@ function readBoundedRepoText(absPath, rootDir) {
180381
180851
  return;
180382
180852
  }
180383
180853
  try {
180384
- return readFileSync3(absPath, "utf8");
180854
+ return readFileSync4(absPath, "utf8");
180385
180855
  } catch {
180386
180856
  return;
180387
180857
  }
180388
180858
  }
180389
180859
  function readRepoRelativeText(rootDir, relPath) {
180390
- return readBoundedRepoText(resolve2(rootDir, relPath), rootDir);
180860
+ return readBoundedRepoText(resolve3(rootDir, relPath), rootDir);
180391
180861
  }
180392
180862
  function isDedicatedToolFilePath(path) {
180393
180863
  return /(^|\/)tools?\//i.test(path) && /\.(ts|tsx|js|mjs|py)$/i.test(path);
@@ -180414,8 +180884,8 @@ function extractToolBodyFromText(text, toolName) {
180414
180884
  const normalizedName = toolName.replace(/\s+/g, "").toLowerCase();
180415
180885
  for (let index = 0;index < lines.length; index += 1) {
180416
180886
  const line = lines[index];
180417
- const compact = line.replace(/\s+/g, "").toLowerCase();
180418
- const mentionsTool = compact.includes(normalizedName) || compact.includes(`def${normalizedName}`);
180887
+ const compact2 = line.replace(/\s+/g, "").toLowerCase();
180888
+ const mentionsTool = compact2.includes(normalizedName) || compact2.includes(`def${normalizedName}`);
180419
180889
  if (!mentionsTool)
180420
180890
  continue;
180421
180891
  if (line.includes("function_tool") || line.includes("tool(") || line.includes("createTool") || line.includes("functionTool") || line.includes("dynamicTool") || line.includes("new Tool") || line.includes("def ")) {
@@ -180428,14 +180898,14 @@ function annotatedSourceCandidates(sourcePath, annotation) {
180428
180898
  const explicitSourcePath = normalizePath2(sourcePath) !== normalizePath2(annotation.evidence.path);
180429
180899
  if (!explicitSourcePath) {
180430
180900
  return [
180431
- resolve2(annotation.rootDir, sourcePath),
180432
- resolve2(dirname2(annotation.sourceAbsPath), sourcePath),
180901
+ resolve3(annotation.rootDir, sourcePath),
180902
+ resolve3(dirname2(annotation.sourceAbsPath), sourcePath),
180433
180903
  annotation.sourceAbsPath
180434
180904
  ];
180435
180905
  }
180436
- const rootAbs = resolve2(annotation.rootDir);
180437
- const candidates = walkAncestorDirs(dirname2(annotation.sourceAbsPath), rootAbs).map((dir) => resolve2(dir, sourcePath));
180438
- candidates.push(resolve2(annotation.rootDir, sourcePath));
180906
+ const rootAbs = resolve3(annotation.rootDir);
180907
+ const candidates = walkAncestorDirs(dirname2(annotation.sourceAbsPath), rootAbs).map((dir) => resolve3(dir, sourcePath));
180908
+ candidates.push(resolve3(annotation.rootDir, sourcePath));
180439
180909
  return candidates;
180440
180910
  }
180441
180911
  function readAnnotatedSourceText(sourcePath, annotation) {
@@ -180516,9 +180986,9 @@ function readSourcePathRelativeToEvidence(artifact, rootDir) {
180516
180986
  const evidencePath = firstEvidencePath(artifact);
180517
180987
  if (!evidencePath)
180518
180988
  return;
180519
- const rootAbs = resolve2(rootDir);
180520
- for (const dir of walkAncestorDirs(dirname2(resolve2(rootDir, evidencePath)), rootAbs)) {
180521
- const text = readBoundedRepoText(resolve2(dir, artifact.sourcePath), rootDir);
180989
+ const rootAbs = resolve3(rootDir);
180990
+ for (const dir of walkAncestorDirs(dirname2(resolve3(rootDir, evidencePath)), rootAbs)) {
180991
+ const text = readBoundedRepoText(resolve3(dir, artifact.sourcePath), rootDir);
180522
180992
  if (text !== undefined)
180523
180993
  return text;
180524
180994
  }
@@ -180548,7 +181018,7 @@ function enrichScanCaptureMetadata(graph) {
180548
181018
 
180549
181019
  // src/harness-candidates.ts
180550
181020
  import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
180551
- import { basename as basename3, dirname as dirname3, extname, resolve as resolve3 } from "node:path";
181021
+ import { basename as basename3, dirname as dirname3, extname, resolve as resolve4 } from "node:path";
180552
181022
  var EXCERPT_MAX_CHARS = 240;
180553
181023
  var MAX_CANDIDATES_PER_FILE_PER_SIGNAL = 20;
180554
181024
  var MIN_PROMPT_LITERAL_CHARS = 160;
@@ -181076,7 +181546,7 @@ function detectHarnessCandidatesInFiles(files) {
181076
181546
  function detectHarnessCandidates(rootDir) {
181077
181547
  const startedAt = Date.now();
181078
181548
  const skipped = [];
181079
- const root = resolve3(rootDir);
181549
+ const root = resolve4(rootDir);
181080
181550
  const inventory = inventoryFiles(root, skipped, {
181081
181551
  includeFile: (path) => PROMPT_DOC_EXTENSIONS.has(extname(path).toLowerCase()) || [".json", ".yaml", ".yml"].includes(extname(path).toLowerCase()) || extname(path).toLowerCase() === ".rs" && RUST_PROMPT_PATH_HINT.test(path)
181082
181552
  });
@@ -181102,7 +181572,7 @@ function detectHarnessCandidates(rootDir) {
181102
181572
  return redactDeep(report);
181103
181573
  }
181104
181574
  function writeHarnessCandidatesReport(report, outPath) {
181105
- const target = resolve3(outPath);
181575
+ const target = resolve4(outPath);
181106
181576
  mkdirSync3(dirname3(target), { recursive: true });
181107
181577
  writeFileSync3(target, `${JSON.stringify(report, null, 2)}
181108
181578
  `, "utf8");
@@ -181162,8 +181632,8 @@ import { extname as extname8 } from "node:path";
181162
181632
  // src/prompt-sources.ts
181163
181633
  var import_typescript2 = __toESM(require_typescript(), 1);
181164
181634
  import { createHash as createHash2 } from "node:crypto";
181165
- import { lstatSync as lstatSync4, readFileSync as readFileSync6, realpathSync as realpathSync4 } from "node:fs";
181166
- import { extname as extname3, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve6 } from "node:path";
181635
+ import { lstatSync as lstatSync4, readFileSync as readFileSync7, realpathSync as realpathSync4 } from "node:fs";
181636
+ import { extname as extname3, isAbsolute as isAbsolute2, relative as relative3, resolve as resolve7 } from "node:path";
181167
181637
 
181168
181638
  // src/prompt-frameworks.ts
181169
181639
  var PYTHON_AGENT_MODULES = [
@@ -181184,15 +181654,15 @@ var TYPESCRIPT_AGENT_MODULES = [
181184
181654
 
181185
181655
  // src/prompt-source-code.ts
181186
181656
  var import_typescript = __toESM(require_typescript(), 1);
181187
- import { existsSync as existsSync4, lstatSync as lstatSync3, readFileSync as readFileSync4, realpathSync as realpathSync2 } from "node:fs";
181188
- import { dirname as dirname4, extname as extname2, join as join3, resolve as resolve4 } from "node:path";
181657
+ import { existsSync as existsSync4, lstatSync as lstatSync3, readFileSync as readFileSync5, realpathSync as realpathSync2 } from "node:fs";
181658
+ import { dirname as dirname4, extname as extname2, join as join3, resolve as resolve5 } from "node:path";
181189
181659
  var EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
181190
181660
  var MAX_BYTES = 2 * 1024 * 1024;
181191
181661
  var MAX_DEPTH = 32;
181192
181662
  var MAX_FILES = 256;
181193
181663
  var MAX_GRAPH_BYTES = 16 * 1024 * 1024;
181194
181664
  function extractCodeSource(rootDir, sourcePath, symbol, forceDependencyGraph = false) {
181195
- const state = { root: resolve4(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
181665
+ const state = { root: resolve5(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
181196
181666
  const file = safeFile(state.root, state.root, sourcePath);
181197
181667
  const parsed = parseFile(file, state);
181198
181668
  const target = symbol ? findSymbol(parsed, symbol) : findInstructionCandidate(parsed);
@@ -181225,7 +181695,7 @@ function parseFile(filePath, state) {
181225
181695
  const cached = state.parsed.get(path);
181226
181696
  if (cached)
181227
181697
  return cached;
181228
- const text = readFileSync4(path, "utf8");
181698
+ const text = readFileSync5(path, "utf8");
181229
181699
  state.bytesRead += Buffer.byteLength(text);
181230
181700
  state.files.push(path);
181231
181701
  const scriptKind = extname2(path) === ".json" ? import_typescript.default.ScriptKind.JSON : /\.tsx?$/.test(extname2(path)) ? import_typescript.default.ScriptKind.TSX : import_typescript.default.ScriptKind.JSX;
@@ -181240,7 +181710,7 @@ function parseFile(filePath, state) {
181240
181710
  function safeFile(root, base, requested) {
181241
181711
  if (requested.includes("\x00"))
181242
181712
  throw new Error(`Prompt source path contains NUL: ${requested}`);
181243
- const candidate = resolve4(base, requested);
181713
+ const candidate = resolve5(base, requested);
181244
181714
  let cursor = candidate;
181245
181715
  while (cursor !== root) {
181246
181716
  let stat2;
@@ -181256,7 +181726,7 @@ function safeFile(root, base, requested) {
181256
181726
  break;
181257
181727
  cursor = next;
181258
181728
  }
181259
- const rootReal = resolve4(root);
181729
+ const rootReal = resolve5(root);
181260
181730
  let real;
181261
181731
  try {
181262
181732
  real = requireRealpath(candidate);
@@ -181593,7 +182063,7 @@ function isBindingMutated(file, name) {
181593
182063
  function moduleSpecifier(from, specifier) {
181594
182064
  if (!specifier.startsWith("."))
181595
182065
  return;
181596
- const base = resolve4(dirname4(from), specifier);
182066
+ const base = resolve5(dirname4(from), specifier);
181597
182067
  const stripped = /\.(?:js|jsx|mjs|cjs)$/.test(base) ? base.slice(0, base.lastIndexOf(".")) : base;
181598
182068
  for (const candidate of [base, stripped, ...EXTENSIONS.map((ext) => `${base}${ext}`), ...EXTENSIONS.map((ext) => `${stripped}${ext}`), ...EXTENSIONS.map((ext) => join3(base, `index${ext}`)), ...EXTENSIONS.map((ext) => join3(stripped, `index${ext}`))])
181599
182069
  if (existsSync4(candidate) && lstatSync3(candidate).isFile())
@@ -181613,7 +182083,7 @@ function nodeRange(file, node) {
181613
182083
  };
181614
182084
  }
181615
182085
  function inspectCodeSelectors(rootDir, sourcePath, symbol) {
181616
- const state = { root: resolve4(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
182086
+ const state = { root: resolve5(rootDir), files: [], unresolved: [], visiting: new Set, importsVisited: new Set, parsed: new Map, assignments: new Map, bytesRead: 0 };
181617
182087
  const parsed = parseFile(safeFile(state.root, state.root, sourcePath), state);
181618
182088
  if (symbol) {
181619
182089
  const node = findSymbol(parsed, symbol);
@@ -181663,8 +182133,8 @@ function referenceNames(node) {
181663
182133
 
181664
182134
  // src/prompt-source-python.ts
181665
182135
  import { spawnSync } from "node:child_process";
181666
- import { readFileSync as readFileSync5, realpathSync as realpathSync3 } from "node:fs";
181667
- import { resolve as resolve5 } from "node:path";
182136
+ import { readFileSync as readFileSync6, realpathSync as realpathSync3 } from "node:fs";
182137
+ import { resolve as resolve6 } from "node:path";
181668
182138
  var PYTHON_AGENT_MODULES_LITERAL = JSON.stringify(PYTHON_AGENT_MODULES);
181669
182139
  var SELECTOR_HELPER = String.raw`import ast,json,os,sys
181670
182140
  request=json.loads(sys.stdin.read()); root=os.path.realpath(request['root']); path=os.path.abspath(request['path']); wanted=request.get('symbol')
@@ -181725,7 +182195,7 @@ else:
181725
182195
  print(json.dumps({'candidates':found},ensure_ascii=False))`;
181726
182196
  function inspectPythonSelectors(rootDir, sourcePath, symbol) {
181727
182197
  const root = realpathSync3(rootDir);
181728
- const absolute = resolve5(root, sourcePath);
182198
+ const absolute = resolve6(root, sourcePath);
181729
182199
  const result = spawnSync("python3", ["-I", "-c", SELECTOR_HELPER], {
181730
182200
  input: JSON.stringify({ root, path: absolute, ...symbol ? { symbol } : {} }),
181731
182201
  encoding: "utf8",
@@ -181870,7 +182340,7 @@ except SystemExit: pass
181870
182340
  except Exception as error: print(json.dumps({'candidates':[],'error':str(error)}))`;
181871
182341
  function discoverPythonPromptSources(rootDir, sourcePath) {
181872
182342
  const result = spawnSync("python3", ["-I", "-c", DISCOVERY_HELPER], {
181873
- input: JSON.stringify({ root: rootDir, path: resolve5(rootDir, sourcePath) }),
182343
+ input: JSON.stringify({ root: rootDir, path: resolve6(rootDir, sourcePath) }),
181874
182344
  encoding: "utf8",
181875
182345
  maxBuffer: 4 * 1024 * 1024,
181876
182346
  timeout: 1e4
@@ -182130,7 +182600,7 @@ except Exception as e:
182130
182600
  function extractPythonSource(rootDir, sourcePath, symbol, _forceDependencyGraph = false) {
182131
182601
  let raw = "";
182132
182602
  try {
182133
- raw = readFileSync5(sourcePath, "utf8");
182603
+ raw = readFileSync6(sourcePath, "utf8");
182134
182604
  } catch {}
182135
182605
  const result = spawnSync("python3", ["-I", "-c", HELPER], {
182136
182606
  input: JSON.stringify({ root: rootDir, path: sourcePath, symbol, force: _forceDependencyGraph }),
@@ -182224,7 +182694,7 @@ function resolvePromptSource(rootDir, source) {
182224
182694
  } else if (source.selector?.symbol) {
182225
182695
  throw new Error(`${sourcePath}: symbol selectors require a JavaScript, TypeScript, or Python source file`);
182226
182696
  } else if (ext === ".json" || ext === ".yaml" || ext === ".yml" || hasPointer || source.kind === "messages") {
182227
- const parsed = parseStructured(readFileSync6(sourceAbs, "utf8"), sourcePath, ext);
182697
+ const parsed = parseStructured(readFileSync7(sourceAbs, "utf8"), sourcePath, ext);
182228
182698
  const selected = hasPointer ? jsonPointer(parsed, source.selector.pointer, sourcePath) : parsed;
182229
182699
  const selectedField = source.selector?.pointer?.split("/").at(-1)?.replaceAll("~1", "/").replaceAll("~0", "~");
182230
182700
  const inferredKind = !source.kind && selectedField && /^(?:template|system_template|instance_template)$/.test(selectedField) ? "template" : source.kind;
@@ -182234,7 +182704,7 @@ function resolvePromptSource(rootDir, source) {
182234
182704
  messages = structured.messages;
182235
182705
  kind = structured.kind;
182236
182706
  } else {
182237
- const raw = readFileSync6(sourceAbs, "utf8");
182707
+ const raw = readFileSync7(sourceAbs, "utf8");
182238
182708
  if (ext === ".md" && /\.prompt\.md$/i.test(sourcePath)) {
182239
182709
  const legacy = parseLegacyMarkdown(raw);
182240
182710
  content = legacy.content;
@@ -182257,7 +182727,7 @@ function resolvePromptSource(rootDir, source) {
182257
182727
  const depAbs = safePath(root, dependency.path);
182258
182728
  files.add(depAbs);
182259
182729
  if (typeof dependency.selector?.pointer === "string") {
182260
- const parsed = parseStructured(readFileSync6(depAbs, "utf8"), dependency.path, extname3(depAbs).toLowerCase());
182730
+ const parsed = parseStructured(readFileSync7(depAbs, "utf8"), dependency.path, extname3(depAbs).toLowerCase());
182261
182731
  jsonPointer(parsed, dependency.selector.pointer, dependency.path);
182262
182732
  } else if (dependency.selector?.symbol && CODE_EXTENSIONS2.has(extname3(depAbs).toLowerCase())) {
182263
182733
  const dep = extname3(depAbs).toLowerCase() === ".py" ? extractPythonSource(root, depAbs, dependency.selector.symbol) : extractCodeSource(root, depAbs, dependency.selector.symbol);
@@ -182280,7 +182750,7 @@ function resolvePromptSource(rootDir, source) {
182280
182750
  assertSafeMaterializedContent(content, sourcePath);
182281
182751
  else
182282
182752
  assertSafeMaterializedContent(materialized, sourcePath);
182283
- const dependencies = [...files].sort().map((path) => ({ path: relative3(root, path).replaceAll("\\", "/"), contentHash: sha256(readFileSync6(path)) }));
182753
+ const dependencies = [...files].sort().map((path) => ({ path: relative3(root, path).replaceAll("\\", "/"), contentHash: sha256(readFileSync7(path)) }));
182284
182754
  const sourceHash = sha256(JSON.stringify({ kind, content, systemPrompt: systemPrompt ?? null, messages: messages ?? null }));
182285
182755
  const sourceDefinition = {
182286
182756
  schemaVersion: 1,
@@ -182350,7 +182820,7 @@ function discoverStructuredPromptSources(rootDir, sourcePath) {
182350
182820
  const ext = extname3(file).toLowerCase();
182351
182821
  if (![".json", ".yaml", ".yml"].includes(ext))
182352
182822
  return [];
182353
- const value = parseStructured(readFileSync6(file, "utf8"), sourcePath, ext);
182823
+ const value = parseStructured(readFileSync7(file, "utf8"), sourcePath, ext);
182354
182824
  const sources = [];
182355
182825
  const base = sourcePath.replace(/\.[^.]+$/, "").replace(/[^A-Za-z0-9_.-]+/g, ".");
182356
182826
  const dedicatedPath = /(^|\/)prompts?(?:\/|\.[^/]+$)|\.prompt\.[^.]+$/i.test(sourcePath);
@@ -182413,14 +182883,14 @@ function discoverCodePromptCandidates(rootDir, sourcePath) {
182413
182883
  addName(candidate.symbol, candidate.knownBuilder === true);
182414
182884
  modelInputs.add(candidate.symbol);
182415
182885
  }
182416
- for (const match of readFileSync6(file, "utf8").matchAll(/^(?:(?:async\s+)?def\s+([A-Za-z_]\w*)|([A-Za-z_]\w*)\s*=\s*([^\n#]+))/gm)) {
182886
+ for (const match of readFileSync7(file, "utf8").matchAll(/^(?:(?:async\s+)?def\s+([A-Za-z_]\w*)|([A-Za-z_]\w*)\s*=\s*([^\n#]+))/gm)) {
182417
182887
  const name = match[1] ?? match[2];
182418
182888
  const rhs = match[3] ?? "";
182419
182889
  if (name && isPromptName2(name) && (match[1] || /['"`\[({+]/.test(rhs) || /^[A-Za-z_]\w*\s*$/.test(rhs)))
182420
182890
  addName(name, Boolean(match[1]));
182421
182891
  }
182422
182892
  } else {
182423
- const sf = import_typescript2.default.createSourceFile(file, readFileSync6(file, "utf8"), import_typescript2.default.ScriptTarget.Latest, true, import_typescript2.default.ScriptKind.TSX);
182893
+ const sf = import_typescript2.default.createSourceFile(file, readFileSync7(file, "utf8"), import_typescript2.default.ScriptTarget.Latest, true, import_typescript2.default.ScriptKind.TSX);
182424
182894
  const agentConstructors = new Set;
182425
182895
  for (const statement of sf.statements) {
182426
182896
  if (!import_typescript2.default.isImportDeclaration(statement) || !import_typescript2.default.isStringLiteral(statement.moduleSpecifier) || !TYPESCRIPT_AGENT_MODULES.includes(statement.moduleSpecifier.text))
@@ -182602,13 +183072,13 @@ function jsonPointer(value, pointer, path) {
182602
183072
  return current;
182603
183073
  }
182604
183074
  function safeRoot(dir) {
182605
- const root = realpathSync4(resolve6(dir));
183075
+ const root = realpathSync4(resolve7(dir));
182606
183076
  if (!lstatSync4(root).isDirectory())
182607
183077
  throw new Error(`Prompt source root is not a directory: ${dir}`);
182608
183078
  return root;
182609
183079
  }
182610
183080
  function safePath(root, requested) {
182611
- const candidate = resolve6(root, requested);
183081
+ const candidate = resolve7(root, requested);
182612
183082
  rejectSymlinkPath(root, candidate, requested);
182613
183083
  const real = realpathSync4(candidate);
182614
183084
  if (!(real === root || real.startsWith(`${root}/`)))
@@ -182654,12 +183124,12 @@ function sha256(input) {
182654
183124
  }
182655
183125
 
182656
183126
  // src/prompt-source-verification/index.ts
182657
- import { readFileSync as readFileSync10 } from "node:fs";
183127
+ import { readFileSync as readFileSync11 } from "node:fs";
182658
183128
  import { z } from "zod";
182659
183129
 
182660
183130
  // src/prompt-source-validation.ts
182661
183131
  import { existsSync as existsSync5, lstatSync as lstatSync5 } from "node:fs";
182662
- import { extname as extname4, relative as relative4, resolve as resolve7 } from "node:path";
183132
+ import { extname as extname4, relative as relative4, resolve as resolve8 } from "node:path";
182663
183133
  function checkPromptMapping(rootDir, unknownMapping) {
182664
183134
  const repairs = [];
182665
183135
  const unresolved = [];
@@ -182675,10 +183145,10 @@ function checkPromptMapping(rootDir, unknownMapping) {
182675
183145
  if (JSON.stringify(normalized) !== JSON.stringify(sourceValue))
182676
183146
  repairs.push("Omitted empty selector/dependency containers");
182677
183147
  const source = validatePromptSource(normalized);
182678
- const absolute = resolve7(rootDir, source.path);
183148
+ const absolute = resolve8(rootDir, source.path);
182679
183149
  if (!existsSync5(absolute) || !lstatSync5(absolute).isFile())
182680
183150
  throw new Error(`${source.path}: source path is unavailable`);
182681
- const rel = relative4(resolve7(rootDir), absolute).replaceAll("\\", "/");
183151
+ const rel = relative4(resolve8(rootDir), absolute).replaceAll("\\", "/");
182682
183152
  if (rel !== source.path)
182683
183153
  repairs.push(`normalized path to ${rel}`);
182684
183154
  let selected = { ...source, path: rel };
@@ -182743,23 +183213,23 @@ function isPromptDefinitionPath(path) {
182743
183213
  }
182744
183214
 
182745
183215
  // src/prompt-source-verification/evidence.ts
182746
- import { readFileSync as readFileSync9 } from "node:fs";
183216
+ import { readFileSync as readFileSync10 } from "node:fs";
182747
183217
  import { extname as extname7 } from "node:path";
182748
183218
 
182749
183219
  // src/prompt-source-verification/paths.ts
182750
183220
  import { lstatSync as lstatSync6, realpathSync as realpathSync5 } from "node:fs";
182751
- import { isAbsolute as isAbsolute3, relative as relative5, resolve as resolve8, sep } from "node:path";
183221
+ import { isAbsolute as isAbsolute3, relative as relative5, resolve as resolve9, sep } from "node:path";
182752
183222
  function safePromptEvidencePath(rootDir, path) {
182753
183223
  const root = realpathSync5(rootDir);
182754
183224
  if (!path || isAbsolute3(path))
182755
183225
  throw new Error("Evidence path must be repository-relative");
182756
- const absolute = resolve8(root, path);
183226
+ const absolute = resolve9(root, path);
182757
183227
  const rel = relative5(root, absolute);
182758
183228
  if (!rel || rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel))
182759
183229
  throw new Error("Evidence escapes repository");
182760
183230
  let current = root;
182761
183231
  for (const part of rel.split(sep)) {
182762
- current = resolve8(current, part);
183232
+ current = resolve9(current, part);
182763
183233
  if (lstatSync6(current).isSymbolicLink())
182764
183234
  throw new Error("Evidence path is symlinked");
182765
183235
  }
@@ -182773,14 +183243,14 @@ function safePromptEvidencePath(rootDir, path) {
182773
183243
  var import_typescript3 = __toESM(require_typescript(), 1);
182774
183244
  import { execFileSync } from "node:child_process";
182775
183245
  import { extname as extname5 } from "node:path";
182776
- import { readFileSync as readFileSync7 } from "node:fs";
183246
+ import { readFileSync as readFileSync8 } from "node:fs";
182777
183247
  function proveSink(root, sink) {
182778
183248
  const file = safePromptEvidencePath(root, sink.path);
182779
183249
  const cache = new Map;
182780
183250
  if (!cache.has(file)) {
182781
183251
  if (extname5(file) === ".py") {
182782
183252
  try {
182783
- const rows = JSON.parse(execFileSync("python3", ["-I", "-c", PYTHON_PROOF], { input: readFileSync7(file, "utf8"), encoding: "utf8", timeout: 1e4, maxBuffer: 2 * 1024 * 1024 }));
183253
+ const rows = JSON.parse(execFileSync("python3", ["-I", "-c", PYTHON_PROOF], { input: readFileSync8(file, "utf8"), encoding: "utf8", timeout: 1e4, maxBuffer: 2 * 1024 * 1024 }));
182784
183254
  cache.set(file, new Map(Object.entries(rows).map(([line, proof]) => [Number(line), proof])));
182785
183255
  } catch {
182786
183256
  cache.set(file, new Map);
@@ -182947,7 +183417,7 @@ print(json.dumps(rows))
182947
183417
  `;
182948
183418
 
182949
183419
  // src/prompt-source-location.ts
182950
- import { readFileSync as readFileSync8 } from "node:fs";
183420
+ import { readFileSync as readFileSync9 } from "node:fs";
182951
183421
  import { extname as extname6 } from "node:path";
182952
183422
  function structuredExcerpt(text, source) {
182953
183423
  if (source.selector?.pointer === undefined)
@@ -183001,7 +183471,7 @@ function promptDefinitionExcerpt(rootDir, source) {
183001
183471
  return;
183002
183472
  return { ...extraction.range, text: extraction.sourceText, ...extraction.declarationKind ? { declarationKind: extraction.declarationKind } : {} };
183003
183473
  }
183004
- const text = readFileSync8(file, "utf8");
183474
+ const text = readFileSync9(file, "utf8");
183005
183475
  return structuredExcerpt(text, source);
183006
183476
  }
183007
183477
  function promptDefinitionRange(rootDir, source) {
@@ -183028,7 +183498,7 @@ function reviewEvidence(rootDir, source, evidence) {
183028
183498
  for (const item of evidence) {
183029
183499
  let text;
183030
183500
  try {
183031
- text = readFileSync9(safePromptEvidencePath(rootDir, item.path), "utf8");
183501
+ text = readFileSync10(safePromptEvidencePath(rootDir, item.path), "utf8");
183032
183502
  } catch (error) {
183033
183503
  if (item.kind === "model_endpoint")
183034
183504
  return { valid: false, endpointVerified: false, reason: error instanceof Error ? error.message : String(error) };
@@ -183143,7 +183613,7 @@ async function independentlyVerifyPromptSource(rootDir, source, verifier) {
183143
183613
  let priorJudgment;
183144
183614
  try {
183145
183615
  const before = JSON.stringify(checked.resolved.sourceDefinition);
183146
- const sourceBytes = readFileSync10(safePromptEvidencePath(rootDir, source.path), "utf8");
183616
+ const sourceBytes = readFileSync11(safePromptEvidencePath(rootDir, source.path), "utf8");
183147
183617
  const instruction = promptVerificationInstruction(checked.source, checked.sourceHash, promptDefinitionExcerpt(rootDir, checked.source));
183148
183618
  for (let attempt = 0;attempt < 2; attempt++) {
183149
183619
  const repair = attempt ? `
@@ -183174,7 +183644,7 @@ ${output}` : "";
183174
183644
  }
183175
183645
  if (reviewed.truncated || reviewed.sourceHash !== checked.sourceHash)
183176
183646
  return pending("Verifier output is truncated or cites a different source hash", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
183177
- if (before !== snapshot() || readFileSync10(safePromptEvidencePath(rootDir, source.path), "utf8") !== sourceBytes)
183647
+ if (before !== snapshot() || readFileSync11(safePromptEvidencePath(rootDir, source.path), "utf8") !== sourceBytes)
183178
183648
  return pending("Source changed during verification", reviewed.evidence, reviewed.role, normalizeUsage(undefined, false));
183179
183649
  if (reviewed.role === "non_prompt")
183180
183650
  return { status: "rejected", reason: reviewed.reason, evidence: reviewed.evidence, sourceHash: checked.sourceHash, role: reviewed.role, usage: normalizeUsage(undefined, false) };
@@ -183534,8 +184004,8 @@ function applyPromptDiscovery(graph, discovery) {
183534
184004
  }
183535
184005
 
183536
184006
  // src/harness-candidate-promotion.ts
183537
- import { readFileSync as readFileSync11 } from "node:fs";
183538
- import { resolve as resolve9 } from "node:path";
184007
+ import { readFileSync as readFileSync12 } from "node:fs";
184008
+ import { resolve as resolve10 } from "node:path";
183539
184009
  var PROMOTED_CONFIDENCE = {
183540
184010
  high: 0.85,
183541
184011
  medium: 0.6
@@ -183565,7 +184035,7 @@ function readFileLines(rootDir, path, cache) {
183565
184035
  return cached;
183566
184036
  let lines;
183567
184037
  try {
183568
- lines = readFileSync11(resolve9(rootDir, path), "utf8").split(/\r?\n/);
184038
+ lines = readFileSync12(resolve10(rootDir, path), "utf8").split(/\r?\n/);
183569
184039
  } catch {
183570
184040
  lines = null;
183571
184041
  }
@@ -184043,9 +184513,46 @@ var SCHEMA_VERSION = "harness.v0.1";
184043
184513
  var REPORT_JSON_BEGIN = "MODA_HARNESS_REPORT_JSON_BEGIN";
184044
184514
  var REPORT_JSON_END = "MODA_HARNESS_REPORT_JSON_END";
184045
184515
  var EXTERNAL_ANALYST_ADAPTERS = ["claude", "codex", "cursor"];
184516
+ var HARNESS_FAMILY_FLAGS = [
184517
+ "agent-id",
184518
+ "allow-no-agents",
184519
+ "analyst",
184520
+ "analyst-command",
184521
+ "analyst-model",
184522
+ "assist",
184523
+ "concern",
184524
+ "dry-run",
184525
+ "experimental",
184526
+ "from",
184527
+ "from-report",
184528
+ "github-actions",
184529
+ "harness",
184530
+ "limit",
184531
+ "local",
184532
+ "no-remote",
184533
+ "offset",
184534
+ "out",
184535
+ "path",
184536
+ "remote",
184537
+ "report",
184538
+ "run",
184539
+ "run-id",
184540
+ "shards",
184541
+ "summary",
184542
+ "sync",
184543
+ "tenant",
184544
+ "tenant-id",
184545
+ "to",
184546
+ "version"
184547
+ ];
184548
+ var HARNESS_DRY_RUN_SUBCOMMANDS = new Set(["scan", "sync", "delete", "analyze", "validate-report", "candidates"]);
184046
184549
  async function runHarnessCommand(context) {
184047
184550
  const subcommand = context.positionals[0] ?? "scan";
184048
- const rootDir = resolve10(context.cwd, context.flags.path ?? ".");
184551
+ assertFlags(`harness ${subcommand}`, context.flags, HARNESS_FAMILY_FLAGS);
184552
+ if (context.dryRun && !HARNESS_DRY_RUN_SUBCOMMANDS.has(subcommand)) {
184553
+ throw new CliInputError(`'moda harness ${subcommand}' has no dry-run mode, so nothing was sent.`, `Remove --dry-run to run it for real. Harness commands with a real dry-run: ${[...HARNESS_DRY_RUN_SUBCOMMANDS].join(", ")}.`);
184554
+ }
184555
+ const rootDir = resolve11(context.cwd, context.flags.path ?? ".");
184049
184556
  const selectedAgentId = selectedRuntimeAgentId(context.flags);
184050
184557
  const tenant = resolveHarnessTenant(context.flags, context);
184051
184558
  const scanPlan = buildCommandScanPlan(context, rootDir);
@@ -184097,6 +184604,10 @@ async function runHarnessCommand(context) {
184097
184604
  if (!approved && !context.dryRun) {
184098
184605
  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.");
184099
184606
  }
184607
+ const wouldRefuse = context.dryRun ? [
184608
+ ...approved ? [] : ["Harness report is not approved; the real sync would refuse. Run `moda harness approve --yes` first."],
184609
+ ...syncQualityRefusal(report.graph, context.flags)
184610
+ ] : [];
184100
184611
  if (!context.dryRun)
184101
184612
  assertHarnessGraphSyncQuality(report.graph, context.flags);
184102
184613
  const syncGraph2 = graphForReport(report.graph);
@@ -184128,7 +184639,7 @@ async function runHarnessCommand(context) {
184128
184639
  reportHash: approval.reportHash
184129
184640
  } : undefined
184130
184641
  };
184131
- const response2 = await syncHarnessWithRemote(context, syncBody);
184642
+ const response2 = wouldRefuse.length > 0 ? undefined : await syncHarnessWithRemote(context, syncBody);
184132
184643
  const statePath2 = response2 && !context.dryRun ? writeHarnessSyncState(rootDir, {
184133
184644
  schemaVersion: "sync_state.v0.1",
184134
184645
  updatedAt: new Date().toISOString(),
@@ -184168,17 +184679,19 @@ async function runHarnessCommand(context) {
184168
184679
  remote: response2 ?? plannedDryRunRemote(plan2),
184169
184680
  written: written2,
184170
184681
  syncState: statePath2 ? { path: statePath2 } : undefined,
184171
- dryRun: context.dryRun
184172
- });
184173
- return { exitCode: 0 };
184682
+ dryRun: context.dryRun,
184683
+ ...wouldRefuse.length > 0 ? { wouldRefuse } : {}
184684
+ }, wouldRefuse.length > 0 ? { warnings: wouldRefuse, status: "error" } : undefined);
184685
+ return { exitCode: wouldRefuse.length > 0 ? 1 : 0 };
184174
184686
  }
184175
184687
  const graph = scanHarness({
184176
184688
  rootDir,
184177
- dryRun: context.dryRun,
184689
+ dryRun: false,
184178
184690
  tenantId: tenant?.tenantId,
184179
184691
  tenantSource: tenant?.source,
184180
184692
  pathWasExplicit: context.flags.path !== undefined
184181
184693
  });
184694
+ const scanWouldRefuse = context.dryRun ? syncQualityRefusal(graph, context.flags) : [];
184182
184695
  if (!context.dryRun)
184183
184696
  assertHarnessGraphSyncQuality(graph, context.flags);
184184
184697
  const syncGraph = graphForSync(graph);
@@ -184196,7 +184709,7 @@ async function runHarnessCommand(context) {
184196
184709
  const written = context.dryRun ? [] : writeHarnessArtifacts(graph, rootDir, {
184197
184710
  summary: context.flags.summary === "true"
184198
184711
  });
184199
- const response = await syncHarnessWithRemote(context, {
184712
+ const response = scanWouldRefuse.length > 0 ? undefined : await syncHarnessWithRemote(context, {
184200
184713
  graph: syncGraph,
184201
184714
  graphHash: localGraphHash,
184202
184715
  sourceCommit
@@ -184225,20 +184738,21 @@ async function runHarnessCommand(context) {
184225
184738
  remote: response ?? plannedDryRunRemote(plan),
184226
184739
  written,
184227
184740
  syncState: statePath ? { path: statePath } : undefined,
184228
- dryRun: context.dryRun
184229
- });
184230
- return { exitCode: 0 };
184741
+ dryRun: context.dryRun,
184742
+ ...scanWouldRefuse.length > 0 ? { wouldRefuse: scanWouldRefuse } : {}
184743
+ }, scanWouldRefuse.length > 0 ? { warnings: scanWouldRefuse, status: "error" } : undefined);
184744
+ return { exitCode: scanWouldRefuse.length > 0 ? 1 : 0 };
184231
184745
  }
184232
184746
  case "delete": {
184233
184747
  const idOrKey = context.positionals[1] ?? (context.flags.harness && context.flags.harness !== "true" ? context.flags.harness : undefined);
184234
184748
  if (!idOrKey) {
184235
184749
  throw new CliInputError("Missing harness id or key to delete.", "Usage: moda harness delete <harness-id-or-key> [--yes]");
184236
184750
  }
184237
- const profileOptions = { profile: context.profile, env: context.env };
184238
- if (!resolveApiKey(profileOptions) && !context.dryRun) {
184751
+ const profileOptions2 = { profile: context.profile, env: context.env };
184752
+ if (!resolveApiKey(profileOptions2) && !context.dryRun) {
184239
184753
  throw new CliInputError("No Moda API key found for harness delete.", "Run `moda init` first, set MODA_API_KEY, or select a profile with an API key.");
184240
184754
  }
184241
- const identity3 = describeSyncIdentity(profileOptions);
184755
+ const identity3 = describeSyncIdentity(profileOptions2);
184242
184756
  if (identity3) {
184243
184757
  const label = identity3.tenantSource === "api-key" ? describeSyncTenantLabel(identity3) : describeSyncTenantLabel({
184244
184758
  tenantId: tenant?.tenantId ?? identity3.tenantId,
@@ -184256,7 +184770,7 @@ async function runHarnessCommand(context) {
184256
184770
  return { exitCode: 0 };
184257
184771
  }
184258
184772
  await confirmHarnessDelete(context, idOrKey);
184259
- const response = await callControlAPI(`/harnesses/${encodeURIComponent(idOrKey)}`, { method: "DELETE" }, profileOptions);
184773
+ const response = await callControlAPI(`/harnesses/${encodeURIComponent(idOrKey)}`, { method: "DELETE" }, profileOptions2);
184260
184774
  writeHumanProgress(context, `Deleted harness ${response.harnessKey ?? idOrKey} from tenant ${response.tenantId ?? "unknown"} ` + `(${response.deleted?.versions ?? 0} versions, ${response.deleted?.agents ?? 0} agents, ` + `${response.deleted?.artifacts ?? 0} artifacts, ${response.deleted?.relationships ?? 0} relationships).`);
184261
184775
  context.output.writeData({ ...response, dryRun: false });
184262
184776
  return { exitCode: 0 };
@@ -184299,7 +184813,7 @@ async function runHarnessCommand(context) {
184299
184813
  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.");
184300
184814
  }
184301
184815
  if (context.flags["github-actions"] === "true") {
184302
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-qz5d22rz.js");
184816
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-1qt4sgxd.js");
184303
184817
  const result = await runGithubActionsAnalyze(rootDir, {
184304
184818
  writeReport: (report2) => {
184305
184819
  const normalized = normalizeHarnessReport(report2);
@@ -184441,7 +184955,7 @@ async function runHarnessCommand(context) {
184441
184955
  throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --out=<file>");
184442
184956
  }
184443
184957
  if (outFlag && !context.dryRun) {
184444
- written.push(writeHarnessCandidatesReport(report, resolve10(context.cwd, outFlag)));
184958
+ written.push(writeHarnessCandidatesReport(report, resolve11(context.cwd, outFlag)));
184445
184959
  }
184446
184960
  writeHumanProgress(context, `Harness candidates: ${report.stats.candidateCount} candidates across ${report.stats.filesWithCandidates} files (${report.stats.filesScanned} scanned, ${report.stats.filesPerSecond.toLocaleString()} files/sec).`);
184447
184961
  context.output.writeData({ scanPlan, ...report, written, dryRun: context.dryRun });
@@ -184529,8 +185043,43 @@ async function runHarnessCommand(context) {
184529
185043
  });
184530
185044
  return { exitCode: 0 };
184531
185045
  }
185046
+ case "list":
185047
+ case "show":
185048
+ case "versions":
185049
+ case "diff": {
185050
+ const readFlags = { list: ["limit", "offset"], show: ["version"], versions: ["limit", "offset"], diff: ["from", "to"] };
185051
+ assertFlags(`harness ${subcommand}`, context.flags, [...readFlags[subcommand], "path"]);
185052
+ assertPositionals(`harness ${subcommand}`, context.positionals, subcommand === "list" ? 1 : 2, `moda harness ${subcommand}${subcommand === "list" ? "" : " <harness-id-or-key>"}`);
185053
+ for (const flag of readFlags[subcommand]) {
185054
+ if (context.flags[flag] === "true")
185055
+ throw new CliInputError(`--${flag} needs a value.`);
185056
+ }
185057
+ const profileOptions2 = { profile: context.profile, env: context.env };
185058
+ if (!resolveApiKey(profileOptions2)) {
185059
+ throw new CliInputError(`No Moda API key found for harness ${subcommand}.`, "Set MODA_API_KEY, run `moda auth login --api-key`, or select a profile with an API key.");
185060
+ }
185061
+ const query = new URLSearchParams;
185062
+ const idOrKey = context.positionals[1];
185063
+ if (subcommand !== "list" && !idOrKey) {
185064
+ throw new CliInputError(`Missing harness id or key for harness ${subcommand}.`, `Usage: moda harness ${subcommand} <harness-id-or-key>${subcommand === "diff" ? " [--from=<versionId>] [--to=<versionId>]" : ""}. List them with \`moda harness list\`.`);
185065
+ }
185066
+ if ((subcommand === "list" || subcommand === "versions") && context.flags.limit)
185067
+ query.set("limit", context.flags.limit);
185068
+ if ((subcommand === "list" || subcommand === "versions") && context.flags.offset)
185069
+ query.set("offset", context.flags.offset);
185070
+ if (subcommand === "show" && context.flags.version)
185071
+ query.set("versionId", context.flags.version);
185072
+ if (subcommand === "diff" && context.flags.from)
185073
+ query.set("from", context.flags.from);
185074
+ if (subcommand === "diff" && context.flags.to)
185075
+ query.set("to", context.flags.to);
185076
+ const suffix = query.toString() ? `?${query.toString()}` : "";
185077
+ const path = subcommand === "list" ? `/harnesses${suffix}` : `/harnesses/${encodeURIComponent(idOrKey)}${subcommand === "show" ? "" : `/${subcommand}`}${suffix}`;
185078
+ context.output.writeData(await callControlAPI(path, {}, profileOptions2));
185079
+ return { exitCode: 0 };
185080
+ }
184532
185081
  default:
184533
- throw new CliInputError(`Unknown harness command '${subcommand}'.`, "Usage: moda harness analyze|pull|validate-report|approve|scan|candidates|sync|delete|agents|graph|explain|write-summary|status");
185082
+ 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");
184534
185083
  }
184535
185084
  }
184536
185085
  function writeHarnessAnalyzeResult(context, payload) {
@@ -184598,7 +185147,7 @@ async function runPromptConcernAnalysis(context, rootDir, scanPlan, tenant) {
184598
185147
  const manifest = join4(rootDir, ".moda/prompts.yml");
184599
185148
  let existing = [];
184600
185149
  if (existsSync6(manifest)) {
184601
- const document = $parseDocument(readFileSync12(manifest, "utf8"));
185150
+ const document = $parseDocument(readFileSync13(manifest, "utf8"));
184602
185151
  if (document.errors.length)
184603
185152
  throw new CliInputError("Invalid prompt manifest.", document.errors[0].message);
184604
185153
  existing = document.toJS({ maxAliasCount: 20 })?.sources ?? [];
@@ -184827,7 +185376,7 @@ function buildExternalAnalystEnv(env) {
184827
185376
  return next;
184828
185377
  }
184829
185378
  function readExternalAnalystReport(rootDir, result, adapter, concern) {
184830
- const reportPath = resolve10(rootDir, HARNESS_REPORT_PATH);
185379
+ const reportPath = resolve11(rootDir, HARNESS_REPORT_PATH);
184831
185380
  if (existsSync6(reportPath))
184832
185381
  return repairExternalAnalystReport(readHarnessReport(reportPath), rootDir, { concern });
184833
185382
  const output = [
@@ -184842,7 +185391,7 @@ function readExternalAnalystReport(rootDir, result, adapter, concern) {
184842
185391
  return parsed;
184843
185392
  let debugHint = "";
184844
185393
  try {
184845
- const debugPath = resolve10(rootDir, MODA_DIR, "analyst-debug.log");
185394
+ const debugPath = resolve11(rootDir, MODA_DIR, "analyst-debug.log");
184846
185395
  mkdirSync4(dirname5(debugPath), { recursive: true });
184847
185396
  writeFileSync4(debugPath, [
184848
185397
  `# analyst=${adapter} status=${result.status} signal=${result.signal} timedOut=${result.timedOut} maxBufferExceeded=${result.maxBufferExceeded}`,
@@ -185073,12 +185622,12 @@ function repairCitationLines(report, rootDir) {
185073
185622
  if (citation.type !== "file" && citation.type !== "generated_doc" || !citation.path || !citation.excerpt)
185074
185623
  continue;
185075
185624
  const excerpt = citation.excerpt;
185076
- const candidatePath = resolve10(rootDir, citation.path);
185625
+ const candidatePath = resolve11(rootDir, citation.path);
185077
185626
  if (!existsSync6(candidatePath))
185078
185627
  continue;
185079
185628
  let text;
185080
185629
  try {
185081
- text = readFileSync12(candidatePath, "utf8");
185630
+ text = readFileSync13(candidatePath, "utf8");
185082
185631
  } catch {
185083
185632
  continue;
185084
185633
  }
@@ -185678,8 +186227,8 @@ function resolveExternalHarnessAnalystInvocation(options) {
185678
186227
  }
185679
186228
  function createPromptAnalystIsolation(adapter, rootDir) {
185680
186229
  const moduleDir = dirname5(fileURLToPath(import.meta.url));
185681
- const bundled = resolve10(moduleDir, "prompt-source-mcp.js");
185682
- const source = resolve10(moduleDir, "prompt-source-mcp.ts");
186230
+ const bundled = resolve11(moduleDir, "prompt-source-mcp.js");
186231
+ const source = resolve11(moduleDir, "prompt-source-mcp.ts");
185683
186232
  const bundledServer = existsSync6(bundled);
185684
186233
  const serverPath = bundledServer ? bundled : source;
185685
186234
  const command = bundledServer ? process.execPath : resolveBunRuntime();
@@ -186188,11 +186737,11 @@ function splitCommandLine(commandLine) {
186188
186737
  return commandLine.trim().split(/\s+/).filter(Boolean);
186189
186738
  }
186190
186739
  function truncateText(value, maxLength) {
186191
- const compact = value.replace(/\s+/g, " ").trim();
186192
- return compact.length > maxLength ? `${compact.slice(0, maxLength - 1)}...` : compact;
186740
+ const compact2 = value.replace(/\s+/g, " ").trim();
186741
+ return compact2.length > maxLength ? `${compact2.slice(0, maxLength - 1)}...` : compact2;
186193
186742
  }
186194
186743
  function scanHarness(options = {}) {
186195
- const rootDir = resolve10(options.rootDir ?? process.cwd());
186744
+ const rootDir = resolve11(options.rootDir ?? process.cwd());
186196
186745
  const skipped = [];
186197
186746
  const files = inventoryFiles(rootDir, skipped);
186198
186747
  const annotations = files.flatMap((file) => parseAnnotations(file));
@@ -186294,7 +186843,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
186294
186843
  let text = "";
186295
186844
  if (isTextFile(path)) {
186296
186845
  try {
186297
- text = readFileSync12(current, "utf8");
186846
+ text = readFileSync13(current, "utf8");
186298
186847
  inventoryTextBytes += Buffer.byteLength(text, "utf8");
186299
186848
  } catch {
186300
186849
  return;
@@ -186307,7 +186856,7 @@ function collectSnapshotInputs(rootDir, maxFiles, maxTextBytes) {
186307
186856
  return inputs;
186308
186857
  }
186309
186858
  function buildSourceSnapshot(rootDir) {
186310
- const root = resolve10(rootDir);
186859
+ const root = resolve11(rootDir);
186311
186860
  const maxFiles = numericEnv("MODA_HARNESS_MAX_FILES", DEFAULT_MAX_INVENTORY_FILES);
186312
186861
  const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
186313
186862
  const inputs = collectSnapshotInputs(root, maxFiles, maxTextBytes);
@@ -186517,8 +187066,8 @@ function plannedDryRunRemote(plan) {
186517
187066
  }
186518
187067
  async function syncHarnessWithRemote(context, body) {
186519
187068
  assertHarnessGraphSyncSize(body.graph);
186520
- const profileOptions = { profile: context.profile, env: context.env };
186521
- const hasApiKey = Boolean(resolveApiKey(profileOptions));
187069
+ const profileOptions2 = { profile: context.profile, env: context.env };
187070
+ const hasApiKey = Boolean(resolveApiKey(profileOptions2));
186522
187071
  if (context.dryRun && !hasApiKey)
186523
187072
  return;
186524
187073
  return await callControlAPI("/harnesses/sync", {
@@ -186527,14 +187076,14 @@ async function syncHarnessWithRemote(context, body) {
186527
187076
  ...body,
186528
187077
  dryRun: context.dryRun
186529
187078
  })
186530
- }, profileOptions);
187079
+ }, profileOptions2);
186531
187080
  }
186532
187081
  function readHarnessSyncState(rootDir) {
186533
187082
  const path = join4(rootDir, SYNC_STATE_PATH);
186534
187083
  if (!existsSync6(path))
186535
187084
  return;
186536
187085
  try {
186537
- const parsed = JSON.parse(readFileSync12(path, "utf8"));
187086
+ const parsed = JSON.parse(readFileSync13(path, "utf8"));
186538
187087
  if (!isRecord3(parsed) || parsed.schemaVersion !== "sync_state.v0.1") {
186539
187088
  return;
186540
187089
  }
@@ -186651,7 +187200,7 @@ function findFresherHarnessReports(rootDir) {
186651
187200
  return fresher.sort((a, b) => b.mtimeMs - a.mtimeMs);
186652
187201
  }
186653
187202
  function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
186654
- const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative6(rootDir, resolve10(rootDir, explicitReport))) : undefined;
187203
+ const explicitReportPath = explicitReport && explicitReport !== "true" ? normalizePath3(relative6(rootDir, resolve11(rootDir, explicitReport))) : undefined;
186655
187204
  if (explicitReportPath && explicitReportPath !== normalizePath3(HARNESS_REPORT_PATH))
186656
187205
  return;
186657
187206
  let fresher;
@@ -186668,7 +187217,7 @@ function warnFresherSubdirHarnessReports(context, rootDir, explicitReport) {
186668
187217
  writeHarnessNotice(context, `A fresher harness report exists at ${newest.path} (this directory has ${rootState}). If you meant that report, re-run with --path=${subdir}.`);
186669
187218
  }
186670
187219
  function readHarnessGraph(manifestPath) {
186671
- return JSON.parse(readFileSync12(manifestPath, "utf8"));
187220
+ return JSON.parse(readFileSync13(manifestPath, "utf8"));
186672
187221
  }
186673
187222
  function writeHarnessArtifacts(graph, rootDir, options = {}) {
186674
187223
  const modaDir = join4(rootDir, MODA_DIR);
@@ -186780,6 +187329,14 @@ function renderFrameworkAndProviderLines(graph) {
186780
187329
  }
186781
187330
  return lines;
186782
187331
  }
187332
+ function syncQualityRefusal(graph, flags) {
187333
+ try {
187334
+ assertHarnessGraphSyncQuality(graph, flags);
187335
+ return [];
187336
+ } catch (error) {
187337
+ return [`The real sync would refuse: ${error instanceof Error ? error.message : String(error)}`];
187338
+ }
187339
+ }
186783
187340
  function assertHarnessGraphSyncQuality(graph, flags) {
186784
187341
  if (flags["allow-no-agents"] === "true")
186785
187342
  return;
@@ -186845,7 +187402,7 @@ function explainAgent(graph, agent) {
186845
187402
  }
186846
187403
  function inventoryFiles(rootDir, skipped, options = {}) {
186847
187404
  const files = [];
186848
- const rootReal = resolve10(rootDir);
187405
+ const rootReal = resolve11(rootDir);
186849
187406
  const maxFiles = numericEnv("MODA_HARNESS_MAX_FILES", DEFAULT_MAX_INVENTORY_FILES);
186850
187407
  const maxTextBytes = numericEnv("MODA_HARNESS_MAX_TEXT_BYTES", DEFAULT_MAX_INVENTORY_TEXT_BYTES);
186851
187408
  let textBytes = 0;
@@ -186899,7 +187456,7 @@ function inventoryFiles(rootDir, skipped, options = {}) {
186899
187456
  recordSkipped(skipped, { path: rel, reason: "scan text budget exceeded" });
186900
187457
  } else {
186901
187458
  try {
186902
- item.text = readFileSync12(current, "utf8");
187459
+ item.text = readFileSync13(current, "utf8");
186903
187460
  textBytes += Buffer.byteLength(item.text, "utf8");
186904
187461
  } catch {
186905
187462
  recordSkipped(skipped, { path: rel, reason: "text read failed" });
@@ -187206,7 +187763,7 @@ function maybeAddPromptArtifact(graph, file) {
187206
187763
  if (!isPrompt)
187207
187764
  return;
187208
187765
  const id = stableId2("prompt", file.path);
187209
- const text = file.text ?? readFileSync12(file.absPath, "utf8");
187766
+ const text = file.text ?? readFileSync13(file.absPath, "utf8");
187210
187767
  upsertArtifact(graph, {
187211
187768
  id,
187212
187769
  type: "prompt",
@@ -187787,7 +188344,7 @@ function detectProviderPackagesInManifests(rootDir) {
187787
188344
  const packageJsonPath = join4(rootDir, "package.json");
187788
188345
  if (existsSync6(packageJsonPath)) {
187789
188346
  try {
187790
- const deps = packageDependencyNames(readFileSync12(packageJsonPath, "utf8"));
188347
+ const deps = packageDependencyNames(readFileSync13(packageJsonPath, "utf8"));
187791
188348
  for (const provider of PROVIDER_CATALOG) {
187792
188349
  for (const name of provider.packageNames) {
187793
188350
  if (deps.has(name))
@@ -187799,7 +188356,7 @@ function detectProviderPackagesInManifests(rootDir) {
187799
188356
  const pyprojectPath = join4(rootDir, "pyproject.toml");
187800
188357
  if (existsSync6(pyprojectPath)) {
187801
188358
  try {
187802
- const deps = pyprojectDependencyNames(readFileSync12(pyprojectPath, "utf8"));
188359
+ const deps = pyprojectDependencyNames(readFileSync13(pyprojectPath, "utf8"));
187803
188360
  for (const provider of PROVIDER_CATALOG) {
187804
188361
  for (const name of provider.packageNames) {
187805
188362
  if (deps.has(name.toLowerCase()))
@@ -188182,7 +188739,7 @@ function upsertDeployment(graph, next) {
188182
188739
  }
188183
188740
  function contentHashForAnnotatedSource(sourcePath, annotation) {
188184
188741
  const bodyAnnotation = annotation;
188185
- const rootCandidate = resolve10(annotation.rootDir, sourcePath);
188742
+ const rootCandidate = resolve11(annotation.rootDir, sourcePath);
188186
188743
  const candidates = [
188187
188744
  rootCandidate,
188188
188745
  ...annotatedSourceCandidates(sourcePath, bodyAnnotation).filter((c) => c !== rootCandidate)
@@ -188216,7 +188773,7 @@ function readSmallTextFileForHash(absPath, rootDir) {
188216
188773
  if (!isTextFile(rel))
188217
188774
  return;
188218
188775
  try {
188219
- return readFileSync12(absPath, "utf8");
188776
+ return readFileSync13(absPath, "utf8");
188220
188777
  } catch {
188221
188778
  return;
188222
188779
  }
@@ -188309,4 +188866,4 @@ function hashText(text) {
188309
188866
  return createHash4("sha256").update(text).digest("hex");
188310
188867
  }
188311
188868
 
188312
- export { ApiError, callDataAPI, callControlAPI, getApiRequestCount, resetApiRequestCount, $parseDocument, $stringify, require_typescript, inspectCodeSelectors, inspectPythonSelectors, resolvePromptSource, shouldColorTerminalOutput, terminalStyles, stripAnsi2 as stripAnsi, renderMarkdownForTerminal, HARNESS_REPORT_PATH, HARNESS_REPORT_APPROVAL_PATH, HARNESS_ANALYZE_CONCERNS, validateHarnessReport, readHarnessReport, hashHarnessReport, hashStableJson, startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, renderDoctorHuman, renderStatusHuman, renderInitBanner, renderInitStep, renderInitNote, renderInitSetupPlan, renderInitComplete, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, repairExternalAnalystReport, deriveRelationshipsFromGraph, mergeDeterministicArtifacts, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, readHarnessSyncState, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId2 as stableId, titleFromId2 as titleFromId, promptNameFromPath };
188869
+ export { ApiError, callDataAPI, callControlAPI, getApiRequestCount, resetApiRequestCount, $parseDocument, $stringify, require_typescript, inspectCodeSelectors, inspectPythonSelectors, resolvePromptSource, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError, shouldColorTerminalOutput, terminalStyles, stripAnsi2 as stripAnsi, renderMarkdownForTerminal, HARNESS_REPORT_PATH, HARNESS_REPORT_APPROVAL_PATH, HARNESS_ANALYZE_CONCERNS, validateHarnessReport, readHarnessReport, hashHarnessReport, hashStableJson, startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, renderDoctorHuman, renderStatusHuman, renderInitBanner, renderInitStep, renderInitNote, renderInitSetupPlan, renderInitComplete, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, repairExternalAnalystReport, deriveRelationshipsFromGraph, mergeDeterministicArtifacts, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, readHarnessSyncState, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId2 as stableId, titleFromId2 as titleFromId, promptNameFromPath };