nexus-agents 4.1.0 → 4.1.3

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.
@@ -8,7 +8,7 @@ import {
8
8
  checkSqlite,
9
9
  defaultConfig,
10
10
  initDataDirectories
11
- } from "./chunk-6Q2RAJYX.js";
11
+ } from "./chunk-MBVEKLJO.js";
12
12
  import {
13
13
  BUILT_IN_EXPERTS
14
14
  } from "./chunk-YPNQPT2F.js";
@@ -2001,4 +2001,4 @@ export {
2001
2001
  setupCommand,
2002
2002
  setupCommandAsync
2003
2003
  };
2004
- //# sourceMappingURL=chunk-DQ3GEMM4.js.map
2004
+ //# sourceMappingURL=chunk-HKHOJHQO.js.map
@@ -52,7 +52,7 @@ import {
52
52
  } from "./chunk-OQLFRJCW.js";
53
53
 
54
54
  // src/version.ts
55
- var VERSION = true ? "4.1.0" : "dev";
55
+ var VERSION = true ? "4.1.3" : "dev";
56
56
 
57
57
  // src/config/schemas-core.ts
58
58
  import { z } from "zod";
@@ -2339,7 +2339,7 @@ async function runDoctorFix(result) {
2339
2339
  writeLine2("\u2500".repeat(40));
2340
2340
  let fixCount = 0;
2341
2341
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2342
- const { runSetup } = await import("./setup-command-VWTOGR2N.js");
2342
+ const { runSetup } = await import("./setup-command-HEDE6RSE.js");
2343
2343
  const setupResult = runSetup({
2344
2344
  skipMcp: true,
2345
2345
  skipRules: true,
@@ -2452,4 +2452,4 @@ export {
2452
2452
  startStdioServer,
2453
2453
  closeServer
2454
2454
  };
2455
- //# sourceMappingURL=chunk-6Q2RAJYX.js.map
2455
+ //# sourceMappingURL=chunk-MBVEKLJO.js.map
@@ -22,7 +22,7 @@ import {
22
22
  DEFAULT_TASK_TTL_MS,
23
23
  DEFAULT_TOOL_RATE_LIMITS,
24
24
  clampTaskTtl
25
- } from "./chunk-6Q2RAJYX.js";
25
+ } from "./chunk-MBVEKLJO.js";
26
26
  import {
27
27
  executeExpert
28
28
  } from "./chunk-4Z2Z52C7.js";
@@ -43073,8 +43073,10 @@ function verifyEvent(event, index, priorHash) {
43073
43073
  return null;
43074
43074
  }
43075
43075
  function verifyChain(events) {
43076
- if (events.length === 0) return { ok: true, eventCount: 0 };
43077
- if (events[0]?.hash === void 0) return { ok: true, eventCount: events.length };
43076
+ if (events.length === 0) return { ok: true, eventCount: 0, notVerified: "empty" };
43077
+ if (events[0]?.hash === void 0) {
43078
+ return { ok: true, eventCount: events.length, notVerified: "unchained" };
43079
+ }
43078
43080
  let priorHash = void 0;
43079
43081
  for (let i = 0; i < events.length; i++) {
43080
43082
  const event = events[i];
@@ -44543,7 +44545,10 @@ function buildHarnessResult(planResult, tasks) {
44543
44545
  tasks,
44544
44546
  voteIterations: planResult.iterations,
44545
44547
  qaIterations: 0,
44546
- securityPassed: false
44548
+ // Harness mode hands the tasks back for someone else to implement, so the
44549
+ // scan never ran. `securityPassed: false` alone would read as a rejection.
44550
+ securityPassed: false,
44551
+ securityRan: false
44547
44552
  };
44548
44553
  }
44549
44554
  async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateMode) {
@@ -44558,7 +44563,9 @@ async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateM
44558
44563
  tasks: implResult.completedTasks.length > 0 ? implResult.completedTasks : tasks,
44559
44564
  voteIterations: planResult.iterations,
44560
44565
  qaIterations: implResult.totalIterations,
44561
- securityPassed: false
44566
+ // The gate short-circuited before the scan — absence, not a verdict.
44567
+ securityPassed: false,
44568
+ securityRan: false
44562
44569
  };
44563
44570
  }
44564
44571
  const security = await withStep(
@@ -44579,7 +44586,8 @@ async function runImplSecurityPhase(planResult, tasks, stages, sid, qualityGateM
44579
44586
  tasks: implResult.completedTasks.length > 0 ? implResult.completedTasks : tasks,
44580
44587
  voteIterations: planResult.iterations,
44581
44588
  qaIterations: implResult.totalIterations,
44582
- securityPassed: security.passed
44589
+ securityPassed: security.passed,
44590
+ securityRan: true
44583
44591
  };
44584
44592
  }
44585
44593
  async function runQualityGateStage(stages, mode) {
@@ -48440,6 +48448,8 @@ async function loadAuditEvents(dir, logger59) {
48440
48448
  const entries = await fs9.readdir(dir);
48441
48449
  const auditFiles = entries.filter((name) => name.startsWith("audit-") && name.endsWith(".jsonl")).sort();
48442
48450
  const events = [];
48451
+ let skippedLines = 0;
48452
+ let unreadableFiles = 0;
48443
48453
  for (const filename of auditFiles) {
48444
48454
  const fullPath = path8.join(dir, filename);
48445
48455
  let content;
@@ -48448,6 +48458,7 @@ async function loadAuditEvents(dir, logger59) {
48448
48458
  } catch (cause) {
48449
48459
  const msg = cause instanceof Error ? cause.message : String(cause);
48450
48460
  logger59.warn("Skipping unreadable audit log file", { filename, error: msg });
48461
+ unreadableFiles++;
48451
48462
  continue;
48452
48463
  }
48453
48464
  for (const line of content.split("\n")) {
@@ -48462,14 +48473,16 @@ async function loadAuditEvents(dir, logger59) {
48462
48473
  filename,
48463
48474
  error: validated.error.message
48464
48475
  });
48476
+ skippedLines++;
48465
48477
  }
48466
48478
  } catch (cause) {
48467
48479
  const msg = cause instanceof Error ? cause.message : String(cause);
48468
48480
  logger59.warn("Skipping unparseable audit event", { filename, error: msg });
48481
+ skippedLines++;
48469
48482
  }
48470
48483
  }
48471
48484
  }
48472
- return { events, fileCount: auditFiles.length };
48485
+ return { events, fileCount: auditFiles.length, skippedLines, unreadableFiles };
48473
48486
  }
48474
48487
  async function handler2(args, ctx) {
48475
48488
  const parsed = VerifyAuditChainInputSchema.safeParse(args);
@@ -48496,12 +48509,17 @@ async function handler2(args, ctx) {
48496
48509
  message: `logDir "${resolvedDir}" is not a directory`
48497
48510
  });
48498
48511
  }
48499
- const { events, fileCount } = await loadAuditEvents(resolvedDir, ctx.logger);
48512
+ const { events, fileCount, skippedLines, unreadableFiles } = await loadAuditEvents(
48513
+ resolvedDir,
48514
+ ctx.logger
48515
+ );
48500
48516
  const verification = verifyChain(events);
48501
48517
  const response = {
48502
48518
  logDir: resolvedDir,
48503
48519
  fileCount,
48504
48520
  eventCount: events.length,
48521
+ ...skippedLines > 0 ? { skippedLines } : {},
48522
+ ...unreadableFiles > 0 ? { unreadableFiles } : {},
48505
48523
  verification
48506
48524
  };
48507
48525
  return toolSuccess(JSON.stringify(response, null, 2));
@@ -48513,7 +48531,7 @@ function registerVerifyAuditChainTool(server, deps) {
48513
48531
  "Filesystem path to the FileAuditStorage log directory. Tool reads all `audit-*.jsonl` files and verifies the combined hash chain."
48514
48532
  )
48515
48533
  };
48516
- const description = "Verify the hash chain of a persisted FileAuditStorage audit log. Reads all `audit-*.jsonl` files in the given directory, parses events, and runs `verifyChain()` to detect tampering. Returns a structured result with eventCount, fileCount, and one of three tamper signals if detected (hash_mismatch, previous_hash_mismatch, missing_hash). Read-only \u2014 never writes or deletes events.";
48534
+ const description = "Verify the hash chain of a persisted FileAuditStorage audit log. Reads all `audit-*.jsonl` files in the given directory, parses events, and runs `verifyChain()` to detect tampering. Returns a structured result with eventCount, fileCount, and one of three tamper signals if detected (hash_mismatch, previous_hash_mismatch, missing_hash). Reports skippedLines/unreadableFiles when part of the log could not be read, so a verdict over a partial log is never mistaken for a complete one. Read-only \u2014 never writes or deletes events.";
48517
48535
  const secureHandler = createSecureHandler(handler2, {
48518
48536
  toolName: "verify_audit_chain",
48519
48537
  rateLimiter: deps.rateLimiter,
@@ -49764,6 +49782,13 @@ function buildStructuredOutput(result, simulated) {
49764
49782
  ...simulated ? { simulated: true } : {},
49765
49783
  completed: result.completed,
49766
49784
  securityPassed: result.securityPassed,
49785
+ // #4772: these two are what make `completed: false` legible. Without them a
49786
+ // caller cannot tell a failed planner from a successful dry run, or a
49787
+ // security rejection from a gate that never ran — which is the whole point
49788
+ // of the fields. They were added to DevPipelineResult and then not listed
49789
+ // here, so they never reached the MCP surface.
49790
+ ...result.securityRan !== void 0 ? { securityRan: result.securityRan } : {},
49791
+ ...result.planStatus !== void 0 ? { planStatus: result.planStatus } : {},
49767
49792
  voteIterations: result.voteIterations,
49768
49793
  qaIterations: result.qaIterations,
49769
49794
  plan: result.plan,
@@ -50235,13 +50260,26 @@ function detectEngineFailure(result) {
50235
50260
  const record = result;
50236
50261
  if (record["success"] === false) {
50237
50262
  const detail = typeof record["error"] === "string" ? record["error"] : "no error message";
50238
- return `Engine reported failure: ${detail}`;
50263
+ return { message: `Engine reported failure: ${detail}` };
50239
50264
  }
50240
50265
  if (record["completed"] === false) {
50241
- return "Engine reported failure: the dev pipeline did not complete";
50266
+ return { message: describeIncompletePipeline(record), detail: record };
50242
50267
  }
50243
50268
  return null;
50244
50269
  }
50270
+ function describeIncompletePipeline(record) {
50271
+ const prefix = "Engine reported failure:";
50272
+ if (record["planStatus"] === "empty") {
50273
+ return `${prefix} the planner returned no plan, so nothing was built`;
50274
+ }
50275
+ if (record["securityRan"] === true) {
50276
+ return `${prefix} the security gate rejected the change`;
50277
+ }
50278
+ if (record["securityRan"] === false) {
50279
+ return `${prefix} the run stopped before the security gate, which never ran`;
50280
+ }
50281
+ return `${prefix} the dev pipeline did not complete`;
50282
+ }
50245
50283
  async function executeRunBody(input, logger59, trustTier, gatewayAdapters) {
50246
50284
  try {
50247
50285
  const exec2 = await executeGoal(input, {
@@ -50260,7 +50298,11 @@ async function executeRunBody(input, logger59, trustTier, gatewayAdapters) {
50260
50298
  decisionId: exec2.decisionId,
50261
50299
  strategy: exec2.strategy
50262
50300
  });
50263
- return toolStructuredError({ errorCategory: "business", message: engineFailure });
50301
+ return toolStructuredError({
50302
+ errorCategory: "business",
50303
+ message: engineFailure.message,
50304
+ ...engineFailure.detail !== void 0 ? { detail: engineFailure.detail } : {}
50305
+ });
50264
50306
  }
50265
50307
  return toolSuccess(JSON.stringify(exec2, null, 2));
50266
50308
  } catch (err2) {
@@ -54414,4 +54456,4 @@ export {
54414
54456
  shutdownFeedbackSubscriber,
54415
54457
  createEventBusBridge
54416
54458
  };
54417
- //# sourceMappingURL=chunk-4XRV4MIQ.js.map
54459
+ //# sourceMappingURL=chunk-ZZLKJ3OB.js.map