nexus-agents 8.76.0 → 8.76.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -156,7 +156,7 @@ import {
156
156
  validateNexusEnv,
157
157
  validateWorkflow,
158
158
  wrapInMarkdownFence
159
- } from "./chunk-EKUTAEL6.js";
159
+ } from "./chunk-F6P6LQDM.js";
160
160
  import "./chunk-DXTTIJL4.js";
161
161
  import "./chunk-4GDMHCKX.js";
162
162
  import "./chunk-7ETWTSTB.js";
@@ -176,7 +176,7 @@ import {
176
176
  doctorCommand,
177
177
  initDataDirectories,
178
178
  runDoctor
179
- } from "./chunk-HHPDVL75.js";
179
+ } from "./chunk-TRO6LUWV.js";
180
180
  import "./chunk-ASF4HCLR.js";
181
181
  import {
182
182
  shutdownExpertBridge
@@ -198,7 +198,7 @@ import {
198
198
  registerConsensusVoteTool,
199
199
  seatFallbacks,
200
200
  toRecordDecision
201
- } from "./chunk-IJCXL57M.js";
201
+ } from "./chunk-46JQ7H5D.js";
202
202
  import {
203
203
  buildOpenAICompatAdapters,
204
204
  readOpenAICompatEndpoint,
@@ -240,18 +240,18 @@ import {
240
240
  registerImprovementReviewTool,
241
241
  runImprovementReview,
242
242
  scanForSecrets
243
- } from "./chunk-TJIUBTSN.js";
243
+ } from "./chunk-HIEIQQLS.js";
244
244
  import {
245
245
  createDefaultPolicyFirewall,
246
246
  setGlobalPolicyFirewall,
247
247
  setSecureHandlerAuditLogger,
248
248
  stagePolicyFirewallForRollout
249
- } from "./chunk-55QYPH5F.js";
249
+ } from "./chunk-4SUZEE7Q.js";
250
250
  import {
251
251
  NODE_ENGINE_RANGE,
252
252
  VERSION,
253
253
  isNodeVersionSupported
254
- } from "./chunk-HRCJYS3M.js";
254
+ } from "./chunk-KEQHO2Y2.js";
255
255
  import {
256
256
  claimGlobalRegistry,
257
257
  createUnifiedRegistry,
@@ -17155,10 +17155,10 @@ function parseConventionalCommit(hash, message) {
17155
17155
  function extractIssueNumbers(message) {
17156
17156
  const issueRegex = /#(\d+)/g;
17157
17157
  const matches = message.matchAll(issueRegex);
17158
- return Array.from(matches, (m) => `#${m[1]}`);
17158
+ return Array.from(matches, (m) => `#${m[1] ?? ""}`);
17159
17159
  }
17160
17160
  function mapTypeToCategory(type) {
17161
- return COMMIT_TYPE_TO_CATEGORY[type.toLowerCase()] || "Maintenance";
17161
+ return COMMIT_TYPE_TO_CATEGORY[type.toLowerCase()] ?? "Maintenance";
17162
17162
  }
17163
17163
  function groupCommitsByCategory(commits) {
17164
17164
  const categoryMap = /* @__PURE__ */ new Map();
@@ -17183,7 +17183,7 @@ function groupCommitsByCategory(commits) {
17183
17183
  return categories;
17184
17184
  }
17185
17185
  function formatCommitEntry(commit) {
17186
- const scopePart = commit.scope ? `**${commit.scope}**: ` : "";
17186
+ const scopePart = commit.scope !== void 0 && commit.scope.length > 0 ? `**${commit.scope}**: ` : "";
17187
17187
  const issuesPart = commit.issues.length > 0 ? ` (${commit.issues.join(", ")})` : "";
17188
17188
  const breakingPrefix = commit.breaking ? "**BREAKING**: " : "";
17189
17189
  return `- ${breakingPrefix}${scopePart}${commit.subject}${issuesPart}`;
@@ -17232,9 +17232,9 @@ function generateMarkdownFormat(version, categories) {
17232
17232
  const totalCount = categories.reduce((sum, c) => sum + c.commits.length, 0);
17233
17233
  lines.push("## Highlights");
17234
17234
  lines.push("");
17235
- lines.push(`This release includes **${totalCount}** changes:`);
17236
- if (featCount > 0) lines.push(`- ${featCount} new features`);
17237
- if (fixCount > 0) lines.push(`- ${fixCount} bug fixes`);
17235
+ lines.push(`This release includes **${String(totalCount)}** changes:`);
17236
+ if (featCount > 0) lines.push(`- ${String(featCount)} new features`);
17237
+ if (fixCount > 0) lines.push(`- ${String(fixCount)} bug fixes`);
17238
17238
  lines.push("");
17239
17239
  for (const category of categories) {
17240
17240
  lines.push(`## ${category.name}`);
@@ -17254,13 +17254,13 @@ function suggestNextVersion(currentVersion, commits) {
17254
17254
  const patch = parts[2] ?? 0;
17255
17255
  const hasBreaking = commits.some((c) => c.breaking);
17256
17256
  if (hasBreaking) {
17257
- return `${major + 1}.0.0`;
17257
+ return `${String(major + 1)}.0.0`;
17258
17258
  }
17259
17259
  const hasFeatures = commits.some((c) => c.type === "feat");
17260
17260
  if (hasFeatures) {
17261
- return `${major}.${minor + 1}.0`;
17261
+ return `${String(major)}.${String(minor + 1)}.0`;
17262
17262
  }
17263
- return `${major}.${minor}.${patch + 1}`;
17263
+ return `${String(major)}.${String(minor)}.${String(patch + 1)}`;
17264
17264
  }
17265
17265
 
17266
17266
  // src/cli/release-notes-command.ts
@@ -17269,84 +17269,71 @@ var DEFAULT_OPTIONS = {
17269
17269
  dryRun: false,
17270
17270
  verbose: false
17271
17271
  };
17272
- async function runReleaseNotes(options = {}) {
17272
+ function isGivenRef(ref) {
17273
+ return ref !== void 0 && ref !== "";
17274
+ }
17275
+ function earlyResult(fields, startTime) {
17276
+ return {
17277
+ ...fields,
17278
+ version: "unknown",
17279
+ commitCount: 0,
17280
+ categories: [],
17281
+ usedConsensus: false,
17282
+ durationMs: Date.now() - startTime
17283
+ };
17284
+ }
17285
+ function parseCommitLines(commitLines) {
17286
+ return commitLines.map((line) => {
17287
+ const spaceIndex = line.indexOf(" ");
17288
+ const hash = line.substring(0, spaceIndex);
17289
+ const message = line.substring(spaceIndex + 1);
17290
+ return parseConventionalCommit(hash, message);
17291
+ });
17292
+ }
17293
+ function renderReleaseNotes(format, version, categories) {
17294
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
17295
+ switch (format) {
17296
+ case "json":
17297
+ return generateJsonFormat(version, today, categories);
17298
+ case "markdown":
17299
+ return generateMarkdownFormat(version, categories);
17300
+ case "changelog":
17301
+ default:
17302
+ return generateChangelogFormat(version, today, categories);
17303
+ }
17304
+ }
17305
+ function buildReleaseNotes(options) {
17273
17306
  const startTime = Date.now();
17274
17307
  const opts = { ...DEFAULT_OPTIONS, ...options };
17275
- const fromRef = opts.from || getLatestTag() || "HEAD~50";
17276
- const toRef = opts.to || "HEAD";
17308
+ const fromRef = isGivenRef(opts.from) ? opts.from : getLatestTag() ?? "HEAD~50";
17309
+ const toRef = isGivenRef(opts.to) ? opts.to : "HEAD";
17277
17310
  if (opts.verbose) {
17278
17311
  console.log(`${colors.dim}Analyzing commits from ${fromRef} to ${toRef}...${colors.reset}`);
17279
17312
  }
17280
17313
  const commitsResult = tryGetCommitsBetween(fromRef, toRef);
17281
17314
  if (commitsResult.kind === "invalid_ref") {
17282
- return {
17283
- success: false,
17284
- content: `Invalid git ref: "${commitsResult.ref}". Refs may only contain [a-zA-Z0-9._\\-/~^].`,
17285
- version: "unknown",
17286
- fromRef,
17287
- toRef,
17288
- commitCount: 0,
17289
- categories: [],
17290
- usedConsensus: false,
17291
- durationMs: Date.now() - startTime
17292
- };
17315
+ const content = `Invalid git ref: "${commitsResult.ref}". Refs may only contain [a-zA-Z0-9._\\-/~^].`;
17316
+ return earlyResult({ success: false, content, fromRef, toRef }, startTime);
17293
17317
  }
17294
17318
  if (commitsResult.kind === "git_failed") {
17295
- return {
17296
- success: false,
17297
- content: `git log failed for ${fromRef}..${toRef}: ${commitsResult.reason}`,
17298
- version: "unknown",
17299
- fromRef,
17300
- toRef,
17301
- commitCount: 0,
17302
- categories: [],
17303
- usedConsensus: false,
17304
- durationMs: Date.now() - startTime
17305
- };
17319
+ const content = `git log failed for ${fromRef}..${toRef}: ${commitsResult.reason}`;
17320
+ return earlyResult({ success: false, content, fromRef, toRef }, startTime);
17306
17321
  }
17307
- const commitLines = commitsResult.commits;
17308
- if (commitLines.length === 0) {
17309
- return {
17310
- success: true,
17311
- content: "No commits found in range.",
17312
- version: "unknown",
17313
- fromRef,
17314
- toRef,
17315
- commitCount: 0,
17316
- categories: [],
17317
- usedConsensus: false,
17318
- durationMs: Date.now() - startTime
17319
- };
17322
+ if (commitsResult.commits.length === 0) {
17323
+ const content = "No commits found in range.";
17324
+ return earlyResult({ success: true, content, fromRef, toRef }, startTime);
17320
17325
  }
17321
- const commits = commitLines.map((line) => {
17322
- const spaceIndex = line.indexOf(" ");
17323
- const hash = line.substring(0, spaceIndex);
17324
- const message = line.substring(spaceIndex + 1);
17325
- return parseConventionalCommit(hash, message);
17326
- });
17326
+ const commits = parseCommitLines(commitsResult.commits);
17327
17327
  if (opts.verbose) {
17328
- console.log(`${colors.dim}Found ${commits.length} commits${colors.reset}`);
17328
+ console.log(`${colors.dim}Found ${String(commits.length)} commits${colors.reset}`);
17329
17329
  }
17330
17330
  const categories = groupCommitsByCategory(commits);
17331
- const currentVersion = fromRef.replace(/^v/, "") || "0.0.0";
17331
+ const stripped = fromRef.replace(/^v/, "");
17332
+ const currentVersion = stripped === "" ? "0.0.0" : stripped;
17332
17333
  const suggestedVersion = suggestNextVersion(currentVersion, commits);
17333
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
17334
- let output2;
17335
- switch (opts.format) {
17336
- case "json":
17337
- output2 = generateJsonFormat(suggestedVersion, today, categories);
17338
- break;
17339
- case "markdown":
17340
- output2 = generateMarkdownFormat(suggestedVersion, categories);
17341
- break;
17342
- case "changelog":
17343
- default:
17344
- output2 = generateChangelogFormat(suggestedVersion, today, categories);
17345
- break;
17346
- }
17347
17334
  return {
17348
17335
  success: true,
17349
- content: output2,
17336
+ content: renderReleaseNotes(opts.format, suggestedVersion, categories),
17350
17337
  version: suggestedVersion,
17351
17338
  fromRef,
17352
17339
  toRef,
@@ -17356,6 +17343,9 @@ async function runReleaseNotes(options = {}) {
17356
17343
  durationMs: Date.now() - startTime
17357
17344
  };
17358
17345
  }
17346
+ function runReleaseNotes(options = {}) {
17347
+ return Promise.resolve(buildReleaseNotes(options));
17348
+ }
17359
17349
  function printReleaseNotesResult(result, verbose = false) {
17360
17350
  if (verbose) {
17361
17351
  console.log("");
@@ -17363,16 +17353,16 @@ function printReleaseNotesResult(result, verbose = false) {
17363
17353
  console.log(`${colors.dim}${"\u2500".repeat(50)}${colors.reset}`);
17364
17354
  console.log(`${colors.dim}Version:${colors.reset} ${result.version}`);
17365
17355
  console.log(`${colors.dim}Range:${colors.reset} ${result.fromRef}..${result.toRef}`);
17366
- console.log(`${colors.dim}Commits:${colors.reset} ${result.commitCount}`);
17367
- console.log(`${colors.dim}Categories:${colors.reset} ${result.categories.length}`);
17368
- console.log(`${colors.dim}Duration:${colors.reset} ${result.durationMs}ms`);
17356
+ console.log(`${colors.dim}Commits:${colors.reset} ${String(result.commitCount)}`);
17357
+ console.log(`${colors.dim}Categories:${colors.reset} ${String(result.categories.length)}`);
17358
+ console.log(`${colors.dim}Duration:${colors.reset} ${String(result.durationMs)}ms`);
17369
17359
  console.log(`${colors.dim}${"\u2500".repeat(50)}${colors.reset}`);
17370
17360
  console.log("");
17371
17361
  }
17372
17362
  console.log(result.content);
17373
17363
  }
17374
17364
  async function releaseNotesCommand(args) {
17375
- const format = args.options.format || "changelog";
17365
+ const format = args.options.format !== void 0 && args.options.format !== "" ? args.options.format : "changelog";
17376
17366
  const options = {
17377
17367
  format,
17378
17368
  dryRun: args.options.dryRun ?? false,
@@ -17382,7 +17372,7 @@ async function releaseNotesCommand(args) {
17382
17372
  if (args.options.to !== void 0) options.to = args.options.to;
17383
17373
  const result = await runReleaseNotes(options);
17384
17374
  if (!result.success) {
17385
- console.error(`${colors.red}Error: ${result.error}${colors.reset}`);
17375
+ console.error(`${colors.red}Error: ${result.error ?? result.content}${colors.reset}`);
17386
17376
  return 1;
17387
17377
  }
17388
17378
  printReleaseNotesResult(result, args.options.verbose);
@@ -17485,7 +17475,7 @@ function runNpmAudit() {
17485
17475
  return unavailableNpmAuditFinding(reason);
17486
17476
  }
17487
17477
  }
17488
- async function validateSecurity(options) {
17478
+ function validateSecurity(_options) {
17489
17479
  const startTime = Date.now();
17490
17480
  const findings = [];
17491
17481
  const auditFinding = runNpmAudit();
@@ -17517,7 +17507,7 @@ async function validateSecurity(options) {
17517
17507
  remediation: "Review commits for any exposed credentials."
17518
17508
  });
17519
17509
  }
17520
- return {
17510
+ return Promise.resolve({
17521
17511
  expert: "security",
17522
17512
  // whenEmpty = false: an empty list genuinely means "scanned, nothing
17523
17513
  // found" — every check above records a finding when it cannot run, which
@@ -17526,9 +17516,36 @@ async function validateSecurity(options) {
17526
17516
  confidence: 0.85,
17527
17517
  findings,
17528
17518
  durationMs: Date.now() - startTime
17529
- };
17519
+ });
17530
17520
  }
17531
- async function validateArchitecture2(options) {
17521
+ function fitnessScoreFinding(fitnessScore) {
17522
+ if (fitnessScore < 90) {
17523
+ return {
17524
+ severity: "error",
17525
+ category: "architecture",
17526
+ title: `Fitness score below threshold: ${String(fitnessScore)}/100`,
17527
+ description: "Release gate requires fitness score >= 90.",
17528
+ remediation: "Address fitness audit findings before release."
17529
+ };
17530
+ }
17531
+ return {
17532
+ severity: "info",
17533
+ category: "architecture",
17534
+ title: `Fitness score: ${String(fitnessScore)}/100`,
17535
+ description: "Fitness score meets release threshold."
17536
+ };
17537
+ }
17538
+ function fitnessDimensionFindings(audit) {
17539
+ const auditFindings = audit["findings"];
17540
+ if (!Array.isArray(auditFindings)) return [];
17541
+ return auditFindings.map((finding) => ({
17542
+ severity: "info",
17543
+ category: "architecture",
17544
+ title: typeof finding["message"] === "string" ? finding["message"] : "Fitness finding",
17545
+ description: typeof finding["suggestion"] === "string" ? finding["suggestion"] : ""
17546
+ }));
17547
+ }
17548
+ function validateArchitecture2(_options) {
17532
17549
  const startTime = Date.now();
17533
17550
  const findings = [];
17534
17551
  try {
@@ -17539,33 +17556,7 @@ async function validateArchitecture2(options) {
17539
17556
  });
17540
17557
  const audit = JSON.parse(result);
17541
17558
  const fitnessScore = typeof audit["score"] === "number" ? audit["score"] : 0;
17542
- if (fitnessScore < 90) {
17543
- findings.push({
17544
- severity: "error",
17545
- category: "architecture",
17546
- title: `Fitness score below threshold: ${fitnessScore}/100`,
17547
- description: "Release gate requires fitness score >= 90.",
17548
- remediation: "Address fitness audit findings before release."
17549
- });
17550
- } else {
17551
- findings.push({
17552
- severity: "info",
17553
- category: "architecture",
17554
- title: `Fitness score: ${fitnessScore}/100`,
17555
- description: "Fitness score meets release threshold."
17556
- });
17557
- }
17558
- const auditFindings = audit["findings"];
17559
- if (Array.isArray(auditFindings)) {
17560
- for (const finding of auditFindings) {
17561
- findings.push({
17562
- severity: "info",
17563
- category: "architecture",
17564
- title: typeof finding["message"] === "string" ? finding["message"] : "Fitness finding",
17565
- description: typeof finding["suggestion"] === "string" ? finding["suggestion"] : ""
17566
- });
17567
- }
17568
- }
17559
+ findings.push(fitnessScoreFinding(fitnessScore), ...fitnessDimensionFindings(audit));
17569
17560
  } catch {
17570
17561
  findings.push({
17571
17562
  severity: "warning",
@@ -17576,15 +17567,15 @@ async function validateArchitecture2(options) {
17576
17567
  });
17577
17568
  }
17578
17569
  const hasErrors = findings.some((f) => f.severity === "error");
17579
- return {
17570
+ return Promise.resolve({
17580
17571
  expert: "architecture",
17581
17572
  passed: !hasErrors,
17582
17573
  confidence: 0.9,
17583
17574
  findings,
17584
17575
  durationMs: Date.now() - startTime
17585
- };
17576
+ });
17586
17577
  }
17587
- async function validateDocumentation(options) {
17578
+ function validateDocumentation(options) {
17588
17579
  const startTime = Date.now();
17589
17580
  const findings = [];
17590
17581
  if (!existsSync15("CHANGELOG.md")) {
@@ -17624,88 +17615,71 @@ async function validateDocumentation(options) {
17624
17615
  });
17625
17616
  }
17626
17617
  const hasErrors = findings.some((f) => f.severity === "error");
17627
- return {
17618
+ return Promise.resolve({
17628
17619
  expert: "documentation",
17629
17620
  passed: !hasErrors,
17630
17621
  confidence: 0.85,
17631
17622
  findings,
17632
17623
  durationMs: Date.now() - startTime
17633
- };
17624
+ });
17634
17625
  }
17635
- async function validateDevOps(options) {
17636
- const startTime = Date.now();
17637
- const findings = [];
17638
- try {
17639
- execSync5("pnpm build 2>/dev/null", {
17640
- encoding: "utf-8",
17641
- stdio: ["pipe", "pipe", "pipe"],
17642
- timeout: CLI_SUBPROCESS_TIMEOUTS.releaseValidateMs
17643
- });
17644
- findings.push({
17645
- severity: "info",
17646
- category: "ci",
17647
- title: "Build passes",
17648
- description: "pnpm build completed successfully."
17649
- });
17650
- } catch {
17651
- findings.push({
17652
- severity: "error",
17653
- category: "ci",
17654
- title: "Build failed",
17655
- description: "pnpm build failed.",
17656
- remediation: "Fix build errors before release."
17657
- });
17658
- }
17659
- try {
17660
- execSync5("pnpm lint 2>/dev/null", {
17661
- encoding: "utf-8",
17662
- stdio: ["pipe", "pipe", "pipe"],
17663
- timeout: CLI_SUBPROCESS_TIMEOUTS.releaseBuildMs
17664
- });
17665
- findings.push({
17666
- severity: "info",
17667
- category: "ci",
17668
- title: "Lint passes",
17669
- description: "pnpm lint completed successfully."
17670
- });
17671
- } catch {
17672
- findings.push({
17673
- severity: "error",
17674
- category: "ci",
17675
- title: "Lint failed",
17676
- description: "pnpm lint failed.",
17677
- remediation: "Fix lint errors before release."
17678
- });
17626
+ var CI_GATES = [
17627
+ {
17628
+ command: "pnpm build 2>/dev/null",
17629
+ timeoutMs: CLI_SUBPROCESS_TIMEOUTS.releaseValidateMs,
17630
+ name: "Build",
17631
+ script: "pnpm build",
17632
+ remediation: "Fix build errors before release."
17633
+ },
17634
+ {
17635
+ command: "pnpm lint 2>/dev/null",
17636
+ timeoutMs: CLI_SUBPROCESS_TIMEOUTS.releaseBuildMs,
17637
+ name: "Lint",
17638
+ script: "pnpm lint",
17639
+ remediation: "Fix lint errors before release."
17640
+ },
17641
+ {
17642
+ command: "pnpm typecheck 2>/dev/null",
17643
+ timeoutMs: CLI_SUBPROCESS_TIMEOUTS.releaseValidateMs,
17644
+ name: "Type check",
17645
+ script: "pnpm typecheck",
17646
+ remediation: "Fix type errors before release."
17679
17647
  }
17648
+ ];
17649
+ function runCiGate(gate) {
17680
17650
  try {
17681
- execSync5("pnpm typecheck 2>/dev/null", {
17651
+ execSync5(gate.command, {
17682
17652
  encoding: "utf-8",
17683
17653
  stdio: ["pipe", "pipe", "pipe"],
17684
- timeout: CLI_SUBPROCESS_TIMEOUTS.releaseValidateMs
17654
+ timeout: gate.timeoutMs
17685
17655
  });
17686
- findings.push({
17656
+ return {
17687
17657
  severity: "info",
17688
17658
  category: "ci",
17689
- title: "Type check passes",
17690
- description: "pnpm typecheck completed successfully."
17691
- });
17659
+ title: `${gate.name} passes`,
17660
+ description: `${gate.script} completed successfully.`
17661
+ };
17692
17662
  } catch {
17693
- findings.push({
17663
+ return {
17694
17664
  severity: "error",
17695
17665
  category: "ci",
17696
- title: "Type check failed",
17697
- description: "pnpm typecheck failed.",
17698
- remediation: "Fix type errors before release."
17699
- });
17666
+ title: `${gate.name} failed`,
17667
+ description: `${gate.script} failed.`,
17668
+ remediation: gate.remediation
17669
+ };
17700
17670
  }
17671
+ }
17672
+ function validateDevOps(_options) {
17673
+ const startTime = Date.now();
17674
+ const findings = CI_GATES.map(runCiGate);
17701
17675
  const hasErrors = findings.some((f) => f.severity === "error");
17702
- return {
17676
+ return Promise.resolve({
17703
17677
  expert: "devops",
17704
17678
  passed: !hasErrors,
17705
17679
  confidence: 0.95,
17706
17680
  findings,
17707
17681
  durationMs: Date.now() - startTime
17708
- };
17682
+ });
17709
17683
  }
17710
17684
 
17711
17685
  // src/cli/release-validate-command.ts
@@ -17895,6 +17869,12 @@ var DEFAULT_OPTIONS3 = {
17895
17869
  dryRun: false,
17896
17870
  verbose: false
17897
17871
  };
17872
+ function isNonEmpty(value) {
17873
+ return value !== void 0 && value !== "";
17874
+ }
17875
+ function isoDateToday() {
17876
+ return (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
17877
+ }
17898
17878
  function extractHighlightsFromChangelog(version) {
17899
17879
  if (!existsSync16("CHANGELOG.md")) return [];
17900
17880
  const changelog = readFileSync14("CHANGELOG.md", "utf-8");
@@ -17903,17 +17883,22 @@ function extractHighlightsFromChangelog(version) {
17903
17883
  const match = changelog.match(versionRegex);
17904
17884
  if (!match) return [];
17905
17885
  const addedMatch = match[0].match(/### Added\n((?:- .+\n)+)/);
17906
- if (addedMatch?.[1]) {
17907
- return addedMatch[1].split("\n").filter((l) => l.startsWith("- ")).slice(0, 5).map(
17886
+ const added = addedMatch?.[1];
17887
+ if (added !== void 0) {
17888
+ return added.split("\n").filter((l) => l.startsWith("- ")).slice(0, 5).map(
17908
17889
  (l) => l.replace(/^- /, "").replace(/\(#\d+\)/g, "").trim()
17909
17890
  );
17910
17891
  }
17911
17892
  return [];
17912
17893
  }
17913
- function generateBlogPost(options) {
17914
- const highlights = options.highlights || extractHighlightsFromChangelog(options.version);
17915
- const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0] ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
17916
- const fromRef = getLatestTag() || "HEAD~50";
17894
+ function resolveHighlights(options) {
17895
+ return options.highlights ?? extractHighlightsFromChangelog(options.version);
17896
+ }
17897
+ function resolveReleaseUrl(options) {
17898
+ return isNonEmpty(options.releaseUrl) ? options.releaseUrl : `https://github.com/nexus-substrate/nexus-agents/releases/tag/v${options.version}`;
17899
+ }
17900
+ function collectBlogCommitStats() {
17901
+ const fromRef = getLatestTag() ?? "HEAD~50";
17917
17902
  const commitsResult = tryGetCommitsBetween(fromRef, "HEAD");
17918
17903
  const commits = commitsResult.kind === "ok" ? commitsResult.commits : [];
17919
17904
  if (commitsResult.kind !== "ok") {
@@ -17927,29 +17912,37 @@ function generateBlogPost(options) {
17927
17912
  return parseConventionalCommit(line.substring(0, spaceIndex), line.substring(spaceIndex + 1));
17928
17913
  });
17929
17914
  const categories = groupCommitsByCategory(parsedCommits);
17930
- const featCount = categories.find((c) => c.name === "Added")?.commits.length ?? 0;
17931
- const fixCount = categories.find((c) => c.name === "Fixed")?.commits.length ?? 0;
17932
- const refactorCount = categories.find((c) => c.name === "Changed")?.commits.length ?? 0;
17933
- const frontmatter = {
17934
- title: `nexus-agents v${options.version} Released: Multi-Agent Orchestration Improvements`,
17935
- date: today,
17936
- description: `Announcing nexus-agents v${options.version} with ${featCount} new features, ${fixCount} bug fixes, and improved multi-agent orchestration capabilities.`,
17937
- tags: ["nexus-agents", "release", "mcp", "ai", "multi-agent"],
17938
- author: "William Zujkowski"
17915
+ const countOf = (name) => categories.find((c) => c.name === name)?.commits.length ?? 0;
17916
+ return {
17917
+ totalCommits: commits.length,
17918
+ featCount: countOf("Added"),
17919
+ fixCount: countOf("Fixed"),
17920
+ refactorCount: countOf("Changed"),
17921
+ categories
17939
17922
  };
17940
- const content = `---
17923
+ }
17924
+ function renderTopCommits(categories, name) {
17925
+ const commits = categories.find((c) => c.name === name)?.commits.slice(0, 5) ?? [];
17926
+ if (commits.length === 0) return "See CHANGELOG.md for details.";
17927
+ return commits.map((c) => `- ${isNonEmpty(c.scope) ? `**${c.scope}**: ` : ""}${c.subject}`).join("\n");
17928
+ }
17929
+ function renderBlogFrontmatter(frontmatter) {
17930
+ return `---
17941
17931
  title: "${frontmatter.title}"
17942
17932
  date: ${frontmatter.date}
17943
17933
  description: "${frontmatter.description}"
17944
17934
  tags: [${frontmatter.tags.map((t) => `"${t}"`).join(", ")}]
17945
17935
  author: "${frontmatter.author}"
17946
17936
  ---
17947
-
17948
- # nexus-agents v${options.version} Released
17937
+ `;
17938
+ }
17939
+ function renderBlogSummary(version, stats, highlights) {
17940
+ return `
17941
+ # nexus-agents v${version} Released
17949
17942
 
17950
17943
  **BLUF (Bottom Line Up Front):**
17951
17944
 
17952
- I've released nexus-agents v${options.version} with ${commits.length} changes including ${featCount} new features and ${fixCount} bug fixes. This release focuses on improved multi-agent orchestration, better developer experience, and enhanced reliability.
17945
+ I've released nexus-agents v${version} with ${String(stats.totalCommits)} changes including ${String(stats.featCount)} new features and ${String(stats.fixCount)} bug fixes. This release focuses on improved multi-agent orchestration, better developer experience, and enhanced reliability.
17953
17946
 
17954
17947
  **Why it matters:** Multi-agent AI orchestration is becoming essential for complex software development tasks. This release makes it easier to leverage multiple AI models effectively.
17955
17948
 
@@ -17965,29 +17958,35 @@ ${highlights.map((h) => `- **${h}**`).join("\n")}
17965
17958
 
17966
17959
  I analyzed the changes in this release:
17967
17960
 
17968
- - **Total commits:** ${commits.length}
17969
- - **New features:** ${featCount}
17970
- - **Bug fixes:** ${fixCount}
17971
- - **Refactoring:** ${refactorCount}
17961
+ - **Total commits:** ${String(stats.totalCommits)}
17962
+ - **New features:** ${String(stats.featCount)}
17963
+ - **Bug fixes:** ${String(stats.fixCount)}
17964
+ - **Refactoring:** ${String(stats.refactorCount)}
17972
17965
 
17973
17966
  ---
17974
-
17967
+ `;
17968
+ }
17969
+ function renderBlogChanges(categories) {
17970
+ return `
17975
17971
  ## Key Changes
17976
17972
 
17977
17973
  ### New Features
17978
17974
 
17979
- ${categories.find((c) => c.name === "Added")?.commits.slice(0, 5).map((c) => `- ${c.scope ? `**${c.scope}**: ` : ""}${c.subject}`).join("\n") || "See CHANGELOG.md for details."}
17975
+ ${renderTopCommits(categories, "Added")}
17980
17976
 
17981
17977
  ### Bug Fixes
17982
17978
 
17983
- ${categories.find((c) => c.name === "Fixed")?.commits.slice(0, 5).map((c) => `- ${c.scope ? `**${c.scope}**: ` : ""}${c.subject}`).join("\n") || "See CHANGELOG.md for details."}
17979
+ ${renderTopCommits(categories, "Fixed")}
17984
17980
 
17985
17981
  ---
17986
-
17982
+ `;
17983
+ }
17984
+ function renderBlogFooter(version, releaseUrl) {
17985
+ return `
17987
17986
  ## Installation
17988
17987
 
17989
17988
  \`\`\`bash
17990
- npm install -g nexus-agents@${options.version}
17989
+ npm install -g nexus-agents@${version}
17991
17990
  nexus-agents doctor # Verify installation
17992
17991
  \`\`\`
17993
17992
 
@@ -18004,7 +18003,7 @@ nexus-agents doctor # Verify installation
18004
18003
  ## Further Reading
18005
18004
 
18006
18005
  ### Official Resources
18007
- - [GitHub Release](${options.releaseUrl || `https://github.com/nexus-substrate/nexus-agents/releases/tag/v${options.version}`})
18006
+ - [GitHub Release](${releaseUrl})
18008
18007
  - [Full Changelog](https://github.com/nexus-substrate/nexus-agents/blob/main/CHANGELOG.md)
18009
18008
  - [Documentation](https://github.com/nexus-substrate/nexus-agents)
18010
18009
 
@@ -18012,12 +18011,24 @@ nexus-agents doctor # Verify installation
18012
18011
 
18013
18012
  *Released via multi-agent orchestration*
18014
18013
  `;
18015
- return content;
18014
+ }
18015
+ function generateBlogPost(options) {
18016
+ const highlights = resolveHighlights(options);
18017
+ const stats = collectBlogCommitStats();
18018
+ const frontmatter = {
18019
+ title: `nexus-agents v${options.version} Released: Multi-Agent Orchestration Improvements`,
18020
+ date: isoDateToday(),
18021
+ description: `Announcing nexus-agents v${options.version} with ${String(stats.featCount)} new features, ${String(stats.fixCount)} bug fixes, and improved multi-agent orchestration capabilities.`,
18022
+ tags: ["nexus-agents", "release", "mcp", "ai", "multi-agent"],
18023
+ author: "William Zujkowski"
18024
+ };
18025
+ return renderBlogFrontmatter(frontmatter) + renderBlogSummary(options.version, stats, highlights) + renderBlogChanges(stats.categories) + renderBlogFooter(options.version, resolveReleaseUrl(options));
18016
18026
  }
18017
18027
  function generateBlueskyPost(options) {
18018
- const highlights = options.highlights || extractHighlightsFromChangelog(options.version);
18019
- const highlight = highlights[0] || "new features and improvements";
18020
- const releaseUrl = options.releaseUrl || `https://github.com/nexus-substrate/nexus-agents/releases/tag/v${options.version}`;
18028
+ const highlights = resolveHighlights(options);
18029
+ const firstHighlight = highlights[0];
18030
+ const highlight = isNonEmpty(firstHighlight) ? firstHighlight : "new features and improvements";
18031
+ const releaseUrl = resolveReleaseUrl(options);
18021
18032
  let post = `\u{1F680} nexus-agents v${options.version} released!
18022
18033
 
18023
18034
  `;
@@ -18034,9 +18045,9 @@ function generateBlueskyPost(options) {
18034
18045
  }
18035
18046
  return post;
18036
18047
  }
18037
- async function announceToBlog(options) {
18048
+ function announceToBlog(options) {
18038
18049
  const content = generateBlogPost(options);
18039
- const filename = `${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}-nexus-agents-v${options.version.replace(/\./g, "-")}-release.md`;
18050
+ const filename = `${isoDateToday()}-nexus-agents-v${options.version.replace(/\./g, "-")}-release.md`;
18040
18051
  if (options.dryRun) {
18041
18052
  return {
18042
18053
  channel: "blog",
@@ -18107,7 +18118,7 @@ async function runReleaseAnnounce(options) {
18107
18118
  let result;
18108
18119
  switch (channel) {
18109
18120
  case "blog":
18110
- result = await announceToBlog(opts);
18121
+ result = announceToBlog(opts);
18111
18122
  break;
18112
18123
  case "bluesky":
18113
18124
  result = await announceToBluesky(opts);
@@ -18117,7 +18128,7 @@ async function runReleaseAnnounce(options) {
18117
18128
  channel,
18118
18129
  success: false,
18119
18130
  content: "",
18120
- error: `Unknown channel: ${channel}`
18131
+ error: `Unknown channel: ${String(channel)}`
18121
18132
  };
18122
18133
  }
18123
18134
  results.push(result);
@@ -18135,15 +18146,15 @@ function printReleaseAnnounceResult(result, verbose = false) {
18135
18146
  console.log(`${colors.cyan}${colors.bold}Release Announcement Report${colors.reset}`);
18136
18147
  console.log(`${colors.dim}${"\u2550".repeat(50)}${colors.reset}`);
18137
18148
  console.log(`${colors.dim}Version:${colors.reset} ${result.version}`);
18138
- console.log(`${colors.dim}Duration:${colors.reset} ${result.durationMs}ms`);
18149
+ console.log(`${colors.dim}Duration:${colors.reset} ${String(result.durationMs)}ms`);
18139
18150
  console.log("");
18140
18151
  for (const channel of result.channels) {
18141
18152
  const status = channel.success ? `${colors.green}\u2713${colors.reset}` : `${colors.red}\u2717${colors.reset}`;
18142
18153
  console.log(`${status} ${colors.bold}${channel.channel.toUpperCase()}${colors.reset}`);
18143
- if (channel.url) {
18154
+ if (isNonEmpty(channel.url)) {
18144
18155
  console.log(` ${colors.dim}URL:${colors.reset} ${channel.url}`);
18145
18156
  }
18146
- if (channel.error) {
18157
+ if (isNonEmpty(channel.error)) {
18147
18158
  console.log(` ${colors.red}Error:${colors.reset} ${channel.error}`);
18148
18159
  }
18149
18160
  if (verbose) {
@@ -18161,24 +18172,22 @@ function printReleaseAnnounceResult(result, verbose = false) {
18161
18172
  console.log(`${colors.yellow}${colors.bold}\u26A0 Some announcements failed${colors.reset}`);
18162
18173
  }
18163
18174
  }
18175
+ function resolveAnnounceVersion(explicit) {
18176
+ if (isNonEmpty(explicit)) return explicit;
18177
+ try {
18178
+ const pkg = JSON.parse(readFileSync14("package.json", "utf-8"));
18179
+ return isNonEmpty(pkg.version) ? pkg.version : void 0;
18180
+ } catch {
18181
+ return void 0;
18182
+ }
18183
+ }
18164
18184
  async function releaseAnnounceCommand(args) {
18165
- let version;
18166
- if (args.options.version) {
18167
- version = args.options.version;
18168
- } else {
18169
- try {
18170
- const pkg = JSON.parse(readFileSync14("package.json", "utf-8"));
18171
- if (!pkg.version) {
18172
- console.error(`${colors.red}Error: Could not determine version${colors.reset}`);
18173
- return 1;
18174
- }
18175
- version = pkg.version;
18176
- } catch {
18177
- console.error(`${colors.red}Error: Could not determine version${colors.reset}`);
18178
- return 1;
18179
- }
18185
+ const version = resolveAnnounceVersion(args.options.version);
18186
+ if (version === void 0) {
18187
+ console.error(`${colors.red}Error: Could not determine version${colors.reset}`);
18188
+ return 1;
18180
18189
  }
18181
- const channelList = args.options.channels?.split(",") || ["blog", "bluesky"];
18190
+ const channelList = args.options.channels?.split(",") ?? ["blog", "bluesky"];
18182
18191
  const channels = channelList.filter(
18183
18192
  (c) => c === "blog" || c === "bluesky"
18184
18193
  );
@@ -19701,7 +19710,7 @@ function startImprovementReviewScheduler(options) {
19701
19710
  let running = false;
19702
19711
  const runOnce = async () => {
19703
19712
  try {
19704
- const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-PKWQXPPH.js");
19713
+ const { runImprovementReview: runImprovementReview2, ImprovementReviewInputSchema: ImprovementReviewInputSchema2 } = await import("./improvement-review-6T3DFLCQ.js");
19705
19714
  const input = ImprovementReviewInputSchema2.parse({ fileIssues });
19706
19715
  const result = await runImprovementReview2(input, { logger: logger22 });
19707
19716
  logger22.info("Scheduled improvement_review complete", {
@@ -23775,7 +23784,7 @@ function resolveTargetPath(rawPath) {
23775
23784
  }
23776
23785
  return isAbsolute2(rawPath) ? rawPath : resolve12(process.cwd(), rawPath);
23777
23786
  }
23778
- function isNonEmpty(dir) {
23787
+ function isNonEmpty2(dir) {
23779
23788
  if (!existsSync23(dir)) return false;
23780
23789
  const stat2 = statSync2(dir);
23781
23790
  if (!stat2.isDirectory()) return true;
@@ -23813,7 +23822,7 @@ function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
23813
23822
  function inspectTarget(target) {
23814
23823
  const exists = existsSync23(target);
23815
23824
  if (!exists) return { exists: false, nonEmpty: false, isExistingNexusDir: false };
23816
- const nonEmpty = isNonEmpty(target);
23825
+ const nonEmpty = isNonEmpty2(target);
23817
23826
  const stat2 = statSync2(target);
23818
23827
  const isExistingNexusDir = stat2.isDirectory() && existsSync23(join19(target, "audit"));
23819
23828
  return { exists, nonEmpty, isExistingNexusDir };