nexus-agents 3.8.9 → 3.9.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.
@@ -52,7 +52,7 @@ import {
52
52
  } from "./chunk-OQLFRJCW.js";
53
53
 
54
54
  // src/version.ts
55
- var VERSION = true ? "3.8.9" : "dev";
55
+ var VERSION = true ? "3.9.0" : "dev";
56
56
 
57
57
  // src/config/schemas-core.ts
58
58
  import { z } from "zod";
@@ -2324,7 +2324,7 @@ async function runDoctorFix(result) {
2324
2324
  writeLine2("\u2500".repeat(40));
2325
2325
  let fixCount = 0;
2326
2326
  if (!result.dataDirectory.rootExists || result.dataDirectory.subdirectories.some((d) => !d.exists || !d.writable)) {
2327
- const { runSetup } = await import("./setup-command-P4M4QAWA.js");
2327
+ const { runSetup } = await import("./setup-command-LYPCG3O4.js");
2328
2328
  const setupResult = runSetup({
2329
2329
  skipMcp: true,
2330
2330
  skipRules: true,
@@ -2437,4 +2437,4 @@ export {
2437
2437
  startStdioServer,
2438
2438
  closeServer
2439
2439
  };
2440
- //# sourceMappingURL=chunk-WU5JH5QS.js.map
2440
+ //# sourceMappingURL=chunk-M5H2WS5Z.js.map
@@ -8,7 +8,7 @@ import {
8
8
  checkSqlite,
9
9
  defaultConfig,
10
10
  initDataDirectories
11
- } from "./chunk-WU5JH5QS.js";
11
+ } from "./chunk-M5H2WS5Z.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-DNFPG7PU.js.map
2004
+ //# sourceMappingURL=chunk-PGMF6I7D.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-WU5JH5QS.js";
25
+ } from "./chunk-M5H2WS5Z.js";
26
26
  import {
27
27
  executeExpert
28
28
  } from "./chunk-EGUKCGGM.js";
@@ -46634,15 +46634,34 @@ var PrReviewVoteCountsSchema = z92.object({
46634
46634
  error: z92.number().int().nonnegative(),
46635
46635
  total: z92.number().int().nonnegative()
46636
46636
  }).strict();
46637
+ var PrReviewDiffSourceSchema = z92.enum(["canonical-git", "caller-supplied"]);
46638
+ var PrReviewDiffProvenanceSchema = z92.object({
46639
+ /** How the reviewed diff was obtained. */
46640
+ source: PrReviewDiffSourceSchema,
46641
+ /**
46642
+ * Whether the reviewed diff carried parseable `^diff --git` FILE BOUNDARIES
46643
+ * (sourced from the real `splitByFile` result, not a second regex). The one
46644
+ * signal a consumer genuinely CANNOT re-derive from the other record fields:
46645
+ * `looksLikeUnifiedDiff` deliberately accepts plain `diff -u` output, which
46646
+ * has no `diff --git` headers, so a record can be bound to a real diff whose
46647
+ * per-file attribution is unavailable. `false` means "a diff, but the packer
46648
+ * saw it as one undifferentiated blob".
46649
+ */
46650
+ fileBoundaries: z92.boolean()
46651
+ }).strict();
46637
46652
  var PrReviewRecordSchema = z92.object({
46638
46653
  /**
46639
- * Schema version. '1.1' is the Option-C binding (#3831): the record binds to
46654
+ * Schema version. '1.1' was the Option-C binding (#3831): the record binds to
46640
46655
  * `{prNumber, baseSha, reviewedDiffHash}` instead of the rejected `headSha`.
46641
- * Clean break the committed `governance/pr-review-records.jsonl` ledger is
46642
- * empty on every install (no producer ever wrote a '1.0' record), so there is
46643
- * no '1.0' data to migrate.
46656
+ * '1.2' (#4459) marks the boundary at which records began carrying
46657
+ * {@link diffProvenance} an honest pre/post marker so a reader can tell
46658
+ * "this record predates provenance" from "this record's provenance was
46659
+ * dropped". Clean break, as with '1.0'→'1.1': the committed
46660
+ * `governance/pr-review-records.jsonl` ledger is EMPTY on every install (0
46661
+ * records at the time of this bump), so there is no data to migrate and no
46662
+ * reason to keep a tolerant version union.
46644
46663
  */
46645
- version: z92.literal("1.1"),
46664
+ version: z92.literal("1.2"),
46646
46665
  /**
46647
46666
  * Monotonic sequence number (integer ≥ 0). Assigned as (max existing
46648
46667
  * sequence)+1 at write time. Sorted, the set of sequences must cover
@@ -46683,6 +46702,13 @@ var PrReviewRecordSchema = z92.object({
46683
46702
  summary: z92.string(),
46684
46703
  /** Optional correlation/decision id linking to the cost rollup / trace. */
46685
46704
  correlationId: z92.string().min(1).optional(),
46705
+ /**
46706
+ * What this record was DERIVED FROM (#4459). OPTIONAL by necessity: the
46707
+ * schema is `.strict()`, so a required field would reject every record
46708
+ * written before it existed. Absent ⇒ the producer did not state a
46709
+ * provenance; a consumer must NOT read that as `canonical-git`.
46710
+ */
46711
+ diffProvenance: PrReviewDiffProvenanceSchema.optional(),
46686
46712
  /**
46687
46713
  * ADVISORY hash of the tip record at write time (absent for the first).
46688
46714
  * Retained for audit texture but NOT covered by `hash` and NOT verified —
@@ -46712,7 +46738,24 @@ function computePrReviewRecordHash(payload) {
46712
46738
  total: payload.voteCounts.total
46713
46739
  },
46714
46740
  summary: payload.summary,
46715
- correlationId: payload.correlationId ?? null
46741
+ correlationId: payload.correlationId ?? null,
46742
+ // #4459 provenance, INSIDE the hash. This projection is an explicit
46743
+ // allowlist, so a schema field omitted here would sit OUTSIDE
46744
+ // tamper-evidence — `caller-supplied` could be edited to `canonical-git`
46745
+ // with no `hash_mismatch`.
46746
+ //
46747
+ // Absent ⇒ the key is OMITTED entirely (not emitted as `null`, unlike
46748
+ // `correlationId` which has always been in the projection). `JSON.stringify`
46749
+ // drops `undefined` values, so a record written WITHOUT provenance produces
46750
+ // a canonical string byte-identical to the pre-#4459 one and keeps its hash.
46751
+ // Emitting `null` here would flip every such record to `hash_mismatch`.
46752
+ // Rebuilt in schema order for the same reason `voteCounts` is (#3962).
46753
+ ...payload.diffProvenance !== void 0 ? {
46754
+ diffProvenance: {
46755
+ source: payload.diffProvenance.source,
46756
+ fileBoundaries: payload.diffProvenance.fileBoundaries
46757
+ }
46758
+ } : {}
46716
46759
  });
46717
46760
  return crypto3.createHash("sha256").update(canonical).digest("hex");
46718
46761
  }
@@ -46724,7 +46767,7 @@ var MAX_SUMMARY_RECORD_CHARS = 500;
46724
46767
  function buildPrReviewRecord(input) {
46725
46768
  const summaryTruncated = input.summary.length > MAX_SUMMARY_RECORD_CHARS ? input.summary.slice(0, MAX_SUMMARY_RECORD_CHARS) + "..." : input.summary;
46726
46769
  const payload = {
46727
- version: "1.1",
46770
+ version: "1.2",
46728
46771
  sequence: input.sequence ?? 0,
46729
46772
  prNumber: input.prNumber,
46730
46773
  baseSha: input.baseSha,
@@ -46740,6 +46783,7 @@ function buildPrReviewRecord(input) {
46740
46783
  total: input.voteCounts.total
46741
46784
  },
46742
46785
  summary: summaryTruncated,
46786
+ ...input.diffProvenance !== void 0 ? { diffProvenance: input.diffProvenance } : {},
46743
46787
  ...input.correlationId !== void 0 ? { correlationId: input.correlationId } : {},
46744
46788
  ...input.previousHash !== void 0 ? { previousHash: input.previousHash } : {}
46745
46789
  };
@@ -46867,6 +46911,7 @@ function extractPath(fileText) {
46867
46911
  if (m !== null) return m[2];
46868
46912
  return firstLine.replace(/^diff --git\s*/, "").trim();
46869
46913
  }
46914
+ var UNSTRUCTURED_SEGMENT_PATH = "(unstructured)";
46870
46915
  function splitByFile(diff) {
46871
46916
  if (diff.length === 0) return [];
46872
46917
  const headerRe = /^diff --git .*$/gm;
@@ -46876,7 +46921,7 @@ function splitByFile(diff) {
46876
46921
  starts.push(m.index);
46877
46922
  }
46878
46923
  if (starts.length === 0) {
46879
- return [{ path: "(unstructured)", text: diff, bytes: byteLen(diff) }];
46924
+ return [{ path: UNSTRUCTURED_SEGMENT_PATH, text: diff, bytes: byteLen(diff) }];
46880
46925
  }
46881
46926
  const files = [];
46882
46927
  const firstStart = starts[0];
@@ -46892,6 +46937,10 @@ function splitByFile(diff) {
46892
46937
  }
46893
46938
  return files;
46894
46939
  }
46940
+ function hasFileBoundaries(diff) {
46941
+ const segments = splitByFile(diff);
46942
+ return segments.length > 0 && segments.every((s) => s.path !== UNSTRUCTURED_SEGMENT_PATH);
46943
+ }
46895
46944
  function truncateWithMarker(file, budget) {
46896
46945
  const marker = `
46897
46946
  [... TRUNCATED: file ${file.path} is ${String(file.bytes)} bytes, over the ${String(budget)}-byte review budget; showing a partial prefix \u2014 this file is listed in droppedFiles as partially-seen ...]
@@ -46976,19 +47025,25 @@ function applyPartialCoverageGate(aggregate, coverage) {
46976
47025
  }
46977
47026
 
46978
47027
  // src/mcp/tools/pr-review-record-producer.ts
47028
+ function warnIfDiffTruncated(diff, prNumber, logger59) {
47029
+ if (!reviewedDiffWasTruncated(diff)) return;
47030
+ logger59.warn(
47031
+ "Reviewed diff exceeds the hash byte cap; content past it is unbound in reviewedDiffHash",
47032
+ { prNumber }
47033
+ );
47034
+ }
47035
+ function diffProvenanceOf(source, diff) {
47036
+ return { source, fileBoundaries: hasFileBoundaries(diff) };
47037
+ }
46979
47038
  function buildAndPersist(prNumber, baseSha, args) {
46980
- const { input, aggregate, counts, reviewCount, logger: logger59, coverage } = args;
47039
+ const { input, aggregate, counts, reviewCount, logger: logger59, coverage, diffSource } = args;
46981
47040
  const coverageSuffix = coverage?.partial === true ? ` [partial coverage: ${String(coverage.reviewedFiles)}/${String(coverage.totalFiles)} files reviewed, dropped: ${coverage.droppedFiles.join(", ")}]` : "";
46982
- if (reviewedDiffWasTruncated(input.prDiff)) {
46983
- logger59.warn(
46984
- "Reviewed diff exceeds the hash byte cap; content past it is unbound in reviewedDiffHash",
46985
- { prNumber }
46986
- );
46987
- }
47041
+ warnIfDiffTruncated(input.prDiff, prNumber, logger59);
46988
47042
  const record = persistPrReviewRecord({
46989
47043
  prNumber,
46990
47044
  baseSha,
46991
47045
  reviewedDiffHash: computeReviewedDiffHash(input.prDiff),
47046
+ diffProvenance: diffProvenanceOf(diffSource, input.prDiff),
46992
47047
  verdict: aggregate.decision,
46993
47048
  verified: aggregate.verified,
46994
47049
  voteCounts: {
@@ -47315,6 +47370,9 @@ async function executePrReviewBody(input, logger59, gatewayAdapters) {
47315
47370
  });
47316
47371
  }
47317
47372
  const recordOutcome3 = persistReviewRecord({
47373
+ // #4459: `input.prDiff` is opaque MCP input — it passed the unified-diff
47374
+ // shape gate (#4451), but nothing here establishes it is the PR's real diff.
47375
+ diffSource: "caller-supplied",
47318
47376
  input,
47319
47377
  aggregate,
47320
47378
  counts,
@@ -54348,4 +54406,4 @@ export {
54348
54406
  shutdownFeedbackSubscriber,
54349
54407
  createEventBusBridge
54350
54408
  };
54351
- //# sourceMappingURL=chunk-U6KYY22D.js.map
54409
+ //# sourceMappingURL=chunk-SDZUHQYI.js.map