nexus-agents 2.70.0 → 2.71.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.
- package/dist/{chunk-L4XSIHF5.js → chunk-3BKVYSY6.js} +2 -2
- package/dist/{chunk-SU4667UB.js → chunk-7LHQBMBM.js} +2 -2
- package/dist/{chunk-5RMZQEP5.js → chunk-AGVLFRN7.js} +1247 -384
- package/dist/chunk-AGVLFRN7.js.map +1 -0
- package/dist/{chunk-7QWNOE23.js → chunk-KJCSRP34.js} +2 -2
- package/dist/{chunk-7ZPYV4HO.js → chunk-NER7H3RJ.js} +1 -1
- package/dist/chunk-NER7H3RJ.js.map +1 -0
- package/dist/{chunk-UMLBVSW4.js → chunk-POQQ7A5E.js} +1 -1
- package/dist/chunk-POQQ7A5E.js.map +1 -0
- package/dist/{chunk-PPGX45YS.js → chunk-U6BK5DQU.js} +3 -3
- package/dist/cli.js +90 -625
- package/dist/cli.js.map +1 -1
- package/dist/{consensus-vote-WUGHRBYE.js → consensus-vote-EXWACBMR.js} +2 -2
- package/dist/{factory-BHHC6C7W.js → factory-H5BYL4V5.js} +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/{issue-triage-TXQ7J6GG.js → issue-triage-4SEP4WID.js} +3 -3
- package/dist/{setup-command-VMN3XXZN.js → setup-command-5VGIQETA.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-5RMZQEP5.js.map +0 -1
- package/dist/chunk-7ZPYV4HO.js.map +0 -1
- package/dist/chunk-UMLBVSW4.js.map +0 -1
- /package/dist/{chunk-L4XSIHF5.js.map → chunk-3BKVYSY6.js.map} +0 -0
- /package/dist/{chunk-SU4667UB.js.map → chunk-7LHQBMBM.js.map} +0 -0
- /package/dist/{chunk-7QWNOE23.js.map → chunk-KJCSRP34.js.map} +0 -0
- /package/dist/{chunk-PPGX45YS.js.map → chunk-U6BK5DQU.js.map} +0 -0
- /package/dist/{consensus-vote-WUGHRBYE.js.map → consensus-vote-EXWACBMR.js.map} +0 -0
- /package/dist/{factory-BHHC6C7W.js.map → factory-H5BYL4V5.js.map} +0 -0
- /package/dist/{issue-triage-TXQ7J6GG.js.map → issue-triage-4SEP4WID.js.map} +0 -0
- /package/dist/{setup-command-VMN3XXZN.js.map → setup-command-5VGIQETA.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ import "./chunk-32RIOULO.js";
|
|
|
16
16
|
import {
|
|
17
17
|
setupCommandAsync,
|
|
18
18
|
verifyCommand
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7LHQBMBM.js";
|
|
20
20
|
import "./chunk-OF7CYMMA.js";
|
|
21
21
|
import {
|
|
22
22
|
AuthHandler,
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
WorkflowDefinitionSchema,
|
|
35
35
|
addResearchPaper,
|
|
36
36
|
analyzeTools,
|
|
37
|
+
calculateFitnessScore,
|
|
37
38
|
createAgentStages,
|
|
38
39
|
createAnnotationsProxy,
|
|
39
40
|
createAuditLogger,
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
createEventBusBridge,
|
|
44
45
|
createExecutor,
|
|
45
46
|
createFeedbackIntegration,
|
|
47
|
+
createFitnessScoreCalculator,
|
|
46
48
|
createGatewayServerProxy,
|
|
47
49
|
createHarnessExecutor,
|
|
48
50
|
createLearnablePolicy,
|
|
@@ -107,6 +109,7 @@ import {
|
|
|
107
109
|
registerExecuteExpertTool,
|
|
108
110
|
registerExecuteSpecTool,
|
|
109
111
|
registerExtractSymbolsTool,
|
|
112
|
+
registerImprovementReviewTool,
|
|
110
113
|
registerIssueTriageTool,
|
|
111
114
|
registerListExpertsTool,
|
|
112
115
|
registerListWorkflowsTool,
|
|
@@ -146,7 +149,7 @@ import {
|
|
|
146
149
|
validateCommand,
|
|
147
150
|
validateWorkflow,
|
|
148
151
|
wrapInMarkdownFence
|
|
149
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-AGVLFRN7.js";
|
|
150
153
|
import "./chunk-ED6VQWNG.js";
|
|
151
154
|
import {
|
|
152
155
|
resolveToken
|
|
@@ -168,7 +171,7 @@ import {
|
|
|
168
171
|
shutdownToolMemory,
|
|
169
172
|
validateTimeout,
|
|
170
173
|
warnIfSimulatedOutsideTests
|
|
171
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-POQQ7A5E.js";
|
|
172
175
|
import "./chunk-VGZJIR22.js";
|
|
173
176
|
import {
|
|
174
177
|
loadPapersRegistry,
|
|
@@ -182,8 +185,8 @@ import {
|
|
|
182
185
|
evaluatePolicy,
|
|
183
186
|
parsePRUrl,
|
|
184
187
|
sanitizeInput
|
|
185
|
-
} from "./chunk-
|
|
186
|
-
import "./chunk-
|
|
188
|
+
} from "./chunk-KJCSRP34.js";
|
|
189
|
+
import "./chunk-NER7H3RJ.js";
|
|
187
190
|
import "./chunk-LMRKHQG5.js";
|
|
188
191
|
import "./chunk-BC3M4VLP.js";
|
|
189
192
|
import "./chunk-AP2FD37C.js";
|
|
@@ -206,7 +209,7 @@ import {
|
|
|
206
209
|
loadConfig,
|
|
207
210
|
runDoctor,
|
|
208
211
|
validateNexusEnv
|
|
209
|
-
} from "./chunk-
|
|
212
|
+
} from "./chunk-U6BK5DQU.js";
|
|
210
213
|
import {
|
|
211
214
|
DEFAULTS
|
|
212
215
|
} from "./chunk-L2LQ3TSV.js";
|
|
@@ -14176,546 +14179,6 @@ async function demoCommand(subcommand, args, options) {
|
|
|
14176
14179
|
}
|
|
14177
14180
|
}
|
|
14178
14181
|
|
|
14179
|
-
// src/governance/fitness-score.ts
|
|
14180
|
-
import { existsSync as existsSync12, readFileSync as readFileSync6, readdirSync, statSync } from "fs";
|
|
14181
|
-
import { join as join12 } from "path";
|
|
14182
|
-
function findPkgRoot() {
|
|
14183
|
-
let dir = import.meta.dirname;
|
|
14184
|
-
for (let i = 0; i < 10; i++) {
|
|
14185
|
-
const pkgPath = join12(dir, "package.json");
|
|
14186
|
-
if (existsSync12(pkgPath)) {
|
|
14187
|
-
const content = readFileSync6(pkgPath, "utf-8");
|
|
14188
|
-
if (content.includes('"nexus-agents"')) return dir;
|
|
14189
|
-
}
|
|
14190
|
-
dir = join12(dir, "..");
|
|
14191
|
-
}
|
|
14192
|
-
return join12(import.meta.dirname, "../..");
|
|
14193
|
-
}
|
|
14194
|
-
var PKG_ROOT = findPkgRoot();
|
|
14195
|
-
var SRC_ROOT = join12(PKG_ROOT, "src");
|
|
14196
|
-
var REPO_ROOT = join12(PKG_ROOT, "../..");
|
|
14197
|
-
var DOCS_ROOT = join12(REPO_ROOT, "docs");
|
|
14198
|
-
var DETERMINISM_EXCLUDES = [
|
|
14199
|
-
/\.test\.ts$/,
|
|
14200
|
-
/\.spec\.ts$/,
|
|
14201
|
-
/random-provider\.ts$/,
|
|
14202
|
-
/time-provider\.ts$/
|
|
14203
|
-
];
|
|
14204
|
-
function countFiles(dir, pattern) {
|
|
14205
|
-
if (!existsSync12(dir)) return 0;
|
|
14206
|
-
let count = 0;
|
|
14207
|
-
for (const entry of readdirSync(dir)) {
|
|
14208
|
-
const fullPath = join12(dir, entry);
|
|
14209
|
-
const stat2 = statSync(fullPath);
|
|
14210
|
-
if (stat2.isDirectory() && !entry.startsWith(".")) {
|
|
14211
|
-
count += countFiles(fullPath, pattern);
|
|
14212
|
-
} else if (pattern.test(entry)) {
|
|
14213
|
-
count++;
|
|
14214
|
-
}
|
|
14215
|
-
}
|
|
14216
|
-
return count;
|
|
14217
|
-
}
|
|
14218
|
-
function fileContains(filePath, pattern) {
|
|
14219
|
-
if (!existsSync12(filePath)) return false;
|
|
14220
|
-
return pattern.test(readFileSync6(filePath, "utf-8"));
|
|
14221
|
-
}
|
|
14222
|
-
function isExcluded(entry, excludePatterns) {
|
|
14223
|
-
return excludePatterns?.some((p) => p.test(entry)) ?? false;
|
|
14224
|
-
}
|
|
14225
|
-
function countMatchesInFile(fullPath, contentPattern) {
|
|
14226
|
-
const matches = readFileSync6(fullPath, "utf-8").match(contentPattern);
|
|
14227
|
-
return matches?.length ?? 0;
|
|
14228
|
-
}
|
|
14229
|
-
function countPatternInDir(dir, filePattern, contentPattern, excludePatterns) {
|
|
14230
|
-
if (!existsSync12(dir)) return 0;
|
|
14231
|
-
let count = 0;
|
|
14232
|
-
for (const entry of readdirSync(dir)) {
|
|
14233
|
-
const fullPath = join12(dir, entry);
|
|
14234
|
-
const stat2 = statSync(fullPath);
|
|
14235
|
-
if (stat2.isDirectory() && !entry.startsWith(".") && entry !== "node_modules") {
|
|
14236
|
-
count += countPatternInDir(fullPath, filePattern, contentPattern, excludePatterns);
|
|
14237
|
-
} else if (filePattern.test(entry) && !isExcluded(entry, excludePatterns)) {
|
|
14238
|
-
count += countMatchesInFile(fullPath, contentPattern);
|
|
14239
|
-
}
|
|
14240
|
-
}
|
|
14241
|
-
return count;
|
|
14242
|
-
}
|
|
14243
|
-
function clamp2(score, max) {
|
|
14244
|
-
return Math.max(0, Math.min(max, score));
|
|
14245
|
-
}
|
|
14246
|
-
var FitnessScoreCalculator = class {
|
|
14247
|
-
logger;
|
|
14248
|
-
checks = [];
|
|
14249
|
-
constructor(logger17) {
|
|
14250
|
-
this.logger = logger17 ?? createLogger({ component: "FitnessScoreCalculator" });
|
|
14251
|
-
this.registerDefaultChecks();
|
|
14252
|
-
}
|
|
14253
|
-
/** Register default fitness checks. */
|
|
14254
|
-
registerDefaultChecks() {
|
|
14255
|
-
const reg = (dimension, maxPoints, name, check) => {
|
|
14256
|
-
this.checks.push({ dimension, maxPoints, name, check });
|
|
14257
|
-
};
|
|
14258
|
-
reg("canonicalPaths", 20, "Canonical Paths", () => this.checkCanonicalPaths());
|
|
14259
|
-
reg("explicitBehavior", 15, "Explicit Behavior", () => this.checkExplicitBehavior());
|
|
14260
|
-
reg("determinism", 15, "Determinism", () => this.checkDeterminism());
|
|
14261
|
-
reg("observability", 15, "Observability", () => this.checkObservability());
|
|
14262
|
-
reg("configSimplicity", 10, "Config Simplicity", () => this.checkConfigSimplicity());
|
|
14263
|
-
reg("layerSeparation", 10, "Layer Separation", () => this.checkLayerSeparation());
|
|
14264
|
-
reg("operatorErgonomics", 10, "Operator Ergonomics", () => this.checkOperatorErgonomics());
|
|
14265
|
-
reg(
|
|
14266
|
-
"governanceIntegration",
|
|
14267
|
-
5,
|
|
14268
|
-
"Governance Integration",
|
|
14269
|
-
() => this.checkGovernanceIntegration()
|
|
14270
|
-
);
|
|
14271
|
-
}
|
|
14272
|
-
/** Run full fitness audit. */
|
|
14273
|
-
audit(version) {
|
|
14274
|
-
const findings = [];
|
|
14275
|
-
const dimensions = {};
|
|
14276
|
-
for (const check of this.checks) {
|
|
14277
|
-
this.logger.debug(`Running fitness check: ${check.name}`);
|
|
14278
|
-
const result = check.check();
|
|
14279
|
-
dimensions[check.dimension] = result.score;
|
|
14280
|
-
findings.push(...result.findings);
|
|
14281
|
-
}
|
|
14282
|
-
const score = Object.values(dimensions).reduce((sum, val) => sum + val, 0);
|
|
14283
|
-
this.logger.info("Fitness audit complete", { score, version });
|
|
14284
|
-
const safeDim = (k) => dimensions[k] ?? 0;
|
|
14285
|
-
const typedDimensions = {
|
|
14286
|
-
canonicalPaths: safeDim("canonicalPaths"),
|
|
14287
|
-
explicitBehavior: safeDim("explicitBehavior"),
|
|
14288
|
-
determinism: safeDim("determinism"),
|
|
14289
|
-
observability: safeDim("observability"),
|
|
14290
|
-
configSimplicity: safeDim("configSimplicity"),
|
|
14291
|
-
layerSeparation: safeDim("layerSeparation"),
|
|
14292
|
-
operatorErgonomics: safeDim("operatorErgonomics"),
|
|
14293
|
-
governanceIntegration: safeDim("governanceIntegration")
|
|
14294
|
-
};
|
|
14295
|
-
return {
|
|
14296
|
-
score,
|
|
14297
|
-
dimensions: typedDimensions,
|
|
14298
|
-
findings,
|
|
14299
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14300
|
-
version
|
|
14301
|
-
};
|
|
14302
|
-
}
|
|
14303
|
-
// =========================================================================
|
|
14304
|
-
// Individual Checks — real filesystem analysis
|
|
14305
|
-
// =========================================================================
|
|
14306
|
-
/**
|
|
14307
|
-
* Check canonical paths: penalize duplicate router implementations.
|
|
14308
|
-
*
|
|
14309
|
-
* The current minimum is 6 (raised from 5 in #2063 after an audit):
|
|
14310
|
-
* 1. composite-router — pipeline orchestrator
|
|
14311
|
-
* 2. budget-router — budget/cost filtering
|
|
14312
|
-
* 3. zero-router — hard-constraint exclusion
|
|
14313
|
-
* 4. preference-router — user/task preference application
|
|
14314
|
-
* 5. topsis-router — TOPSIS multi-criteria scoring
|
|
14315
|
-
* 6. agreement-cascade-router — agreement-based cascade retry
|
|
14316
|
-
*
|
|
14317
|
-
* Each stage is distinct per CLAUDE.md's documented pipeline:
|
|
14318
|
-
* Task → BudgetRouter → ZeroRouter → PreferenceRouter → TopsisRouter → Agreement → Model
|
|
14319
|
-
*/
|
|
14320
|
-
checkCanonicalPaths() {
|
|
14321
|
-
const findings = [];
|
|
14322
|
-
let score = 20;
|
|
14323
|
-
const routerCount = countFiles(join12(SRC_ROOT, "cli-adapters"), /router\.ts$/);
|
|
14324
|
-
const ROUTER_COUNT_THRESHOLD = 6;
|
|
14325
|
-
if (routerCount > ROUTER_COUNT_THRESHOLD) {
|
|
14326
|
-
const excess = routerCount - ROUTER_COUNT_THRESHOLD;
|
|
14327
|
-
const deduction = Math.min(5, excess);
|
|
14328
|
-
score -= deduction;
|
|
14329
|
-
findings.push(
|
|
14330
|
-
this.finding(
|
|
14331
|
-
"canonicalPaths",
|
|
14332
|
-
"warning",
|
|
14333
|
-
`${String(routerCount)} router implementations found (target: <=${String(ROUTER_COUNT_THRESHOLD)})`,
|
|
14334
|
-
deduction,
|
|
14335
|
-
"Consolidate duplicate routers into CompositeRouter"
|
|
14336
|
-
)
|
|
14337
|
-
);
|
|
14338
|
-
}
|
|
14339
|
-
if (existsSync12(join12(SRC_ROOT, "cli-adapters/composite-router.ts"))) {
|
|
14340
|
-
score += 2;
|
|
14341
|
-
} else {
|
|
14342
|
-
score -= 3;
|
|
14343
|
-
findings.push(
|
|
14344
|
-
this.finding(
|
|
14345
|
-
"canonicalPaths",
|
|
14346
|
-
"critical",
|
|
14347
|
-
"CompositeRouter missing \u2014 no unified routing entry point",
|
|
14348
|
-
3
|
|
14349
|
-
)
|
|
14350
|
-
);
|
|
14351
|
-
}
|
|
14352
|
-
score = this.checkOrchestratorInterface(score, findings);
|
|
14353
|
-
return { score: clamp2(score, 20), findings };
|
|
14354
|
-
}
|
|
14355
|
-
/** Sub-check for IOrchestrator interface and adapter wiring. */
|
|
14356
|
-
checkOrchestratorInterface(score, findings) {
|
|
14357
|
-
const orchPath = join12(SRC_ROOT, "core/types/orchestrator.ts");
|
|
14358
|
-
if (existsSync12(orchPath) && fileContains(orchPath, /interface IOrchestrator/)) {
|
|
14359
|
-
score += 3;
|
|
14360
|
-
} else {
|
|
14361
|
-
score -= 2;
|
|
14362
|
-
findings.push(
|
|
14363
|
-
this.finding("canonicalPaths", "warning", "No IOrchestrator interface in core/types", 2)
|
|
14364
|
-
);
|
|
14365
|
-
}
|
|
14366
|
-
const adapterPath = join12(SRC_ROOT, "orchestration/orchestrator-adapters.ts");
|
|
14367
|
-
if (existsSync12(adapterPath) && fileContains(adapterPath, /TechLeadAdapter|PuppeteerAdapter/)) {
|
|
14368
|
-
score += 2;
|
|
14369
|
-
}
|
|
14370
|
-
return score;
|
|
14371
|
-
}
|
|
14372
|
-
/**
|
|
14373
|
-
* Check explicit behavior: penalize hidden/magic behavior.
|
|
14374
|
-
*
|
|
14375
|
-
* Implementation is intentionally filesystem-signal-based (no AST parse).
|
|
14376
|
-
* The `NEXUS_ALLOW_MOCK_ORCHESTRATION` guard and magic-routing pattern
|
|
14377
|
-
* grep capture the observable failure modes that historically slipped
|
|
14378
|
-
* past review. AST-based detection of implicit fallbacks was considered
|
|
14379
|
-
* but not pursued — it would significantly widen this function's
|
|
14380
|
-
* footprint and the filesystem signals already catch the recurring
|
|
14381
|
-
* regressions. Revisit only if a new class of hidden-behavior bug
|
|
14382
|
-
* surfaces that this grep-over-source approach can't catch.
|
|
14383
|
-
*/
|
|
14384
|
-
checkExplicitBehavior() {
|
|
14385
|
-
const findings = [];
|
|
14386
|
-
let score = 15;
|
|
14387
|
-
const mockGuardCount = countPatternInDir(
|
|
14388
|
-
SRC_ROOT,
|
|
14389
|
-
/\.ts$/,
|
|
14390
|
-
/NEXUS_ALLOW_MOCK_ORCHESTRATION/g,
|
|
14391
|
-
DETERMINISM_EXCLUDES
|
|
14392
|
-
);
|
|
14393
|
-
if (mockGuardCount === 0) {
|
|
14394
|
-
score -= 3;
|
|
14395
|
-
findings.push(
|
|
14396
|
-
this.finding(
|
|
14397
|
-
"explicitBehavior",
|
|
14398
|
-
"warning",
|
|
14399
|
-
"No NEXUS_ALLOW_MOCK_ORCHESTRATION guard found \u2014 mock fallback may be implicit",
|
|
14400
|
-
3,
|
|
14401
|
-
"Require explicit env var for mock orchestration"
|
|
14402
|
-
)
|
|
14403
|
-
);
|
|
14404
|
-
}
|
|
14405
|
-
const magicRouting = countPatternInDir(
|
|
14406
|
-
SRC_ROOT,
|
|
14407
|
-
/\.ts$/,
|
|
14408
|
-
/fallback.*=.*true|implicitRoute/g,
|
|
14409
|
-
DETERMINISM_EXCLUDES
|
|
14410
|
-
);
|
|
14411
|
-
if (magicRouting > 5) {
|
|
14412
|
-
const deduction = Math.min(3, Math.floor(magicRouting / 3));
|
|
14413
|
-
score -= deduction;
|
|
14414
|
-
findings.push(
|
|
14415
|
-
this.finding(
|
|
14416
|
-
"explicitBehavior",
|
|
14417
|
-
"info",
|
|
14418
|
-
`${String(magicRouting)} implicit fallback/routing patterns detected`,
|
|
14419
|
-
deduction
|
|
14420
|
-
)
|
|
14421
|
-
);
|
|
14422
|
-
}
|
|
14423
|
-
return { score: clamp2(score, 15), findings };
|
|
14424
|
-
}
|
|
14425
|
-
/** Check determinism: penalize unseeded random and raw Date.now(). */
|
|
14426
|
-
checkDeterminism() {
|
|
14427
|
-
const findings = [];
|
|
14428
|
-
let score = 15;
|
|
14429
|
-
score = this.checkRandomDeterminism(score, findings);
|
|
14430
|
-
score = this.checkTimeDeterminism(score, findings);
|
|
14431
|
-
return { score: clamp2(score, 15), findings };
|
|
14432
|
-
}
|
|
14433
|
-
/** Sub-check for Math.random() and injectable random provider. */
|
|
14434
|
-
checkRandomDeterminism(score, findings) {
|
|
14435
|
-
const randomCount = countPatternInDir(
|
|
14436
|
-
SRC_ROOT,
|
|
14437
|
-
/\.ts$/,
|
|
14438
|
-
/Math\.random\(\)/g,
|
|
14439
|
-
DETERMINISM_EXCLUDES
|
|
14440
|
-
);
|
|
14441
|
-
if (randomCount > 10) {
|
|
14442
|
-
const deduction = Math.min(5, Math.floor(randomCount / 5));
|
|
14443
|
-
score -= deduction;
|
|
14444
|
-
findings.push(
|
|
14445
|
-
this.finding(
|
|
14446
|
-
"determinism",
|
|
14447
|
-
"warning",
|
|
14448
|
-
`${String(randomCount)} unseeded Math.random() calls in production code`,
|
|
14449
|
-
deduction,
|
|
14450
|
-
"Use getRandomProvider() for injectable randomness"
|
|
14451
|
-
)
|
|
14452
|
-
);
|
|
14453
|
-
} else if (randomCount === 0) {
|
|
14454
|
-
score += 2;
|
|
14455
|
-
}
|
|
14456
|
-
if (existsSync12(join12(SRC_ROOT, "core/random-provider.ts"))) {
|
|
14457
|
-
score += 1;
|
|
14458
|
-
}
|
|
14459
|
-
const randomUsage = countPatternInDir(
|
|
14460
|
-
SRC_ROOT,
|
|
14461
|
-
/\.ts$/,
|
|
14462
|
-
/getRandomProvider\(\)/g,
|
|
14463
|
-
DETERMINISM_EXCLUDES
|
|
14464
|
-
);
|
|
14465
|
-
if (randomUsage > 5) {
|
|
14466
|
-
score += 1;
|
|
14467
|
-
}
|
|
14468
|
-
return score;
|
|
14469
|
-
}
|
|
14470
|
-
/** Sub-check for Date.now() and injectable time provider. */
|
|
14471
|
-
checkTimeDeterminism(score, findings) {
|
|
14472
|
-
const dateNowCount = countPatternInDir(
|
|
14473
|
-
SRC_ROOT,
|
|
14474
|
-
/\.ts$/,
|
|
14475
|
-
/Date\.now\(\)/g,
|
|
14476
|
-
DETERMINISM_EXCLUDES
|
|
14477
|
-
);
|
|
14478
|
-
if (dateNowCount > 50) {
|
|
14479
|
-
score -= 2;
|
|
14480
|
-
findings.push(
|
|
14481
|
-
this.finding(
|
|
14482
|
-
"determinism",
|
|
14483
|
-
"info",
|
|
14484
|
-
`${String(dateNowCount)} Date.now() calls in production code`,
|
|
14485
|
-
2,
|
|
14486
|
-
"Use getTimeProvider() for injectable time"
|
|
14487
|
-
)
|
|
14488
|
-
);
|
|
14489
|
-
}
|
|
14490
|
-
if (existsSync12(join12(SRC_ROOT, "core/time-provider.ts"))) {
|
|
14491
|
-
score += 1;
|
|
14492
|
-
}
|
|
14493
|
-
const timeUsage = countPatternInDir(
|
|
14494
|
-
SRC_ROOT,
|
|
14495
|
-
/\.ts$/,
|
|
14496
|
-
/getTimeProvider\(\)/g,
|
|
14497
|
-
DETERMINISM_EXCLUDES
|
|
14498
|
-
);
|
|
14499
|
-
if (timeUsage > 10) {
|
|
14500
|
-
score += 1;
|
|
14501
|
-
}
|
|
14502
|
-
return score;
|
|
14503
|
-
}
|
|
14504
|
-
/** Check observability: reward tracing, logging, and audit coverage. */
|
|
14505
|
-
checkObservability() {
|
|
14506
|
-
const findings = [];
|
|
14507
|
-
let score = 15;
|
|
14508
|
-
if (existsSync12(join12(SRC_ROOT, "observability/swarm-observer.ts"))) {
|
|
14509
|
-
score += 3;
|
|
14510
|
-
} else {
|
|
14511
|
-
score -= 3;
|
|
14512
|
-
findings.push(
|
|
14513
|
-
this.finding(
|
|
14514
|
-
"observability",
|
|
14515
|
-
"warning",
|
|
14516
|
-
"No SwarmObserver found",
|
|
14517
|
-
3,
|
|
14518
|
-
"Add observability/swarm-observer.ts"
|
|
14519
|
-
)
|
|
14520
|
-
);
|
|
14521
|
-
}
|
|
14522
|
-
if (existsSync12(join12(SRC_ROOT, "core/trace.ts"))) {
|
|
14523
|
-
score += 2;
|
|
14524
|
-
}
|
|
14525
|
-
const loggerCount = countPatternInDir(SRC_ROOT, /\.ts$/, /createLogger\(/g);
|
|
14526
|
-
if (loggerCount > 50) {
|
|
14527
|
-
score += 2;
|
|
14528
|
-
} else {
|
|
14529
|
-
findings.push(
|
|
14530
|
-
this.finding(
|
|
14531
|
-
"observability",
|
|
14532
|
-
"info",
|
|
14533
|
-
`Only ${String(loggerCount)} createLogger() calls (target: >50)`,
|
|
14534
|
-
0
|
|
14535
|
-
)
|
|
14536
|
-
);
|
|
14537
|
-
}
|
|
14538
|
-
if (existsSync12(join12(SRC_ROOT, "audit"))) {
|
|
14539
|
-
score += 2;
|
|
14540
|
-
}
|
|
14541
|
-
return { score: clamp2(score, 15), findings };
|
|
14542
|
-
}
|
|
14543
|
-
/** Check config simplicity: penalize excessive schema sprawl. */
|
|
14544
|
-
checkConfigSimplicity() {
|
|
14545
|
-
const findings = [];
|
|
14546
|
-
let score = 10;
|
|
14547
|
-
const schemaCount = countFiles(join12(SRC_ROOT, "config"), /schema.*\.ts$/);
|
|
14548
|
-
if (schemaCount > 10) {
|
|
14549
|
-
score -= 2;
|
|
14550
|
-
findings.push(
|
|
14551
|
-
this.finding(
|
|
14552
|
-
"configSimplicity",
|
|
14553
|
-
"info",
|
|
14554
|
-
`${String(schemaCount)} config schemas (target: <=10)`,
|
|
14555
|
-
2,
|
|
14556
|
-
"Consolidate related schemas"
|
|
14557
|
-
)
|
|
14558
|
-
);
|
|
14559
|
-
} else {
|
|
14560
|
-
score += 1;
|
|
14561
|
-
}
|
|
14562
|
-
if (existsSync12(join12(SRC_ROOT, "config/config-loader.ts"))) {
|
|
14563
|
-
score += 2;
|
|
14564
|
-
}
|
|
14565
|
-
if (existsSync12(join12(SRC_ROOT, "config/config-manager.ts"))) {
|
|
14566
|
-
score += 1;
|
|
14567
|
-
}
|
|
14568
|
-
return { score: clamp2(score, 10), findings };
|
|
14569
|
-
}
|
|
14570
|
-
/** Check layer separation: penalize cross-layer imports. */
|
|
14571
|
-
checkLayerSeparation() {
|
|
14572
|
-
const findings = [];
|
|
14573
|
-
let score = 10;
|
|
14574
|
-
const adapterAgentImports = countPatternInDir(
|
|
14575
|
-
join12(SRC_ROOT, "adapters"),
|
|
14576
|
-
/\.ts$/,
|
|
14577
|
-
/from ['"]\.\.\/agents\//g
|
|
14578
|
-
);
|
|
14579
|
-
if (adapterAgentImports > 0) {
|
|
14580
|
-
const deduction = Math.min(5, adapterAgentImports);
|
|
14581
|
-
score -= deduction;
|
|
14582
|
-
findings.push(
|
|
14583
|
-
this.finding(
|
|
14584
|
-
"layerSeparation",
|
|
14585
|
-
"warning",
|
|
14586
|
-
`${String(adapterAgentImports)} adapter->agent import violations`,
|
|
14587
|
-
deduction,
|
|
14588
|
-
"Adapters should not import from agents layer"
|
|
14589
|
-
)
|
|
14590
|
-
);
|
|
14591
|
-
} else {
|
|
14592
|
-
score += 2;
|
|
14593
|
-
}
|
|
14594
|
-
const coreMcpImports = countPatternInDir(
|
|
14595
|
-
join12(SRC_ROOT, "core"),
|
|
14596
|
-
/\.ts$/,
|
|
14597
|
-
/from ['"]\.\.\/mcp\//g
|
|
14598
|
-
);
|
|
14599
|
-
if (coreMcpImports > 0) {
|
|
14600
|
-
const deduction = Math.min(3, coreMcpImports);
|
|
14601
|
-
score -= deduction;
|
|
14602
|
-
findings.push(
|
|
14603
|
-
this.finding(
|
|
14604
|
-
"layerSeparation",
|
|
14605
|
-
"critical",
|
|
14606
|
-
`${String(coreMcpImports)} core->MCP import violations`,
|
|
14607
|
-
deduction,
|
|
14608
|
-
"Core must not depend on MCP layer"
|
|
14609
|
-
)
|
|
14610
|
-
);
|
|
14611
|
-
} else {
|
|
14612
|
-
score += 1;
|
|
14613
|
-
}
|
|
14614
|
-
return { score: clamp2(score, 10), findings };
|
|
14615
|
-
}
|
|
14616
|
-
/** Check operator ergonomics: reward rich CLI commands. */
|
|
14617
|
-
checkOperatorErgonomics() {
|
|
14618
|
-
const findings = [];
|
|
14619
|
-
let score = 10;
|
|
14620
|
-
const commandCount = countFiles(join12(SRC_ROOT, "cli"), /\.ts$/);
|
|
14621
|
-
if (commandCount >= 20) {
|
|
14622
|
-
score += 3;
|
|
14623
|
-
} else {
|
|
14624
|
-
findings.push(
|
|
14625
|
-
this.finding(
|
|
14626
|
-
"operatorErgonomics",
|
|
14627
|
-
"info",
|
|
14628
|
-
`${String(commandCount)} CLI commands (target: >=20)`,
|
|
14629
|
-
0
|
|
14630
|
-
)
|
|
14631
|
-
);
|
|
14632
|
-
}
|
|
14633
|
-
score = this.checkCliCommands(score, findings);
|
|
14634
|
-
return { score: clamp2(score, 10), findings };
|
|
14635
|
-
}
|
|
14636
|
-
/** Sub-check for essential CLI commands (doctor, setup, demo, config). */
|
|
14637
|
-
checkCliCommands(score, findings) {
|
|
14638
|
-
const commands = [
|
|
14639
|
-
["cli/doctor.ts", "Doctor command", 2],
|
|
14640
|
-
["cli/setup-command.ts", "Setup wizard", 2],
|
|
14641
|
-
["cli/demo-command.ts", "Demo command", 1],
|
|
14642
|
-
["cli/config-command.ts", "Config command", 1]
|
|
14643
|
-
];
|
|
14644
|
-
for (const [path23, name, bonus] of commands) {
|
|
14645
|
-
if (existsSync12(join12(SRC_ROOT, path23))) {
|
|
14646
|
-
score += bonus;
|
|
14647
|
-
} else {
|
|
14648
|
-
findings.push(this.finding("operatorErgonomics", "info", `Missing ${name} (${path23})`, 0));
|
|
14649
|
-
}
|
|
14650
|
-
}
|
|
14651
|
-
return score;
|
|
14652
|
-
}
|
|
14653
|
-
/** Check governance integration: policy firewall, rate limiter, docs. */
|
|
14654
|
-
checkGovernanceIntegration() {
|
|
14655
|
-
const findings = [];
|
|
14656
|
-
let score = 5;
|
|
14657
|
-
score = this.checkGovernanceDocs(score, findings);
|
|
14658
|
-
score = this.checkGovernanceInfra(score, findings);
|
|
14659
|
-
return { score: clamp2(score, 5), findings };
|
|
14660
|
-
}
|
|
14661
|
-
/** Sub-check for governance documentation artifacts. */
|
|
14662
|
-
checkGovernanceDocs(score, findings) {
|
|
14663
|
-
if (!existsSync12(join12(REPO_ROOT, "CLAUDE.md"))) {
|
|
14664
|
-
score -= 3;
|
|
14665
|
-
findings.push(
|
|
14666
|
-
this.finding("governanceIntegration", "critical", "No CLAUDE.md governance document", 3)
|
|
14667
|
-
);
|
|
14668
|
-
} else {
|
|
14669
|
-
score += 1;
|
|
14670
|
-
}
|
|
14671
|
-
if (existsSync12(join12(DOCS_ROOT, "architecture/wiring-graph.json"))) {
|
|
14672
|
-
score += 1;
|
|
14673
|
-
}
|
|
14674
|
-
if (existsSync12(join12(DOCS_ROOT, "adr"))) {
|
|
14675
|
-
score += 1;
|
|
14676
|
-
} else {
|
|
14677
|
-
findings.push(this.finding("governanceIntegration", "info", "No ADR directory", 0));
|
|
14678
|
-
}
|
|
14679
|
-
return score;
|
|
14680
|
-
}
|
|
14681
|
-
/** Sub-check for governance runtime infrastructure. */
|
|
14682
|
-
checkGovernanceInfra(score, findings) {
|
|
14683
|
-
const hasPolicyFirewall = countPatternInDir(join12(SRC_ROOT, "security"), /\.ts$/, /PolicyGate|policyFirewall/g) > 0;
|
|
14684
|
-
if (hasPolicyFirewall) {
|
|
14685
|
-
score += 1;
|
|
14686
|
-
} else {
|
|
14687
|
-
findings.push(
|
|
14688
|
-
this.finding(
|
|
14689
|
-
"governanceIntegration",
|
|
14690
|
-
"warning",
|
|
14691
|
-
"No policy firewall detected in security layer",
|
|
14692
|
-
0
|
|
14693
|
-
)
|
|
14694
|
-
);
|
|
14695
|
-
}
|
|
14696
|
-
const hasRateLimiter = countPatternInDir(SRC_ROOT, /\.ts$/, /RateLimiter|rateLimiter/g) > 0;
|
|
14697
|
-
if (hasRateLimiter) {
|
|
14698
|
-
score += 1;
|
|
14699
|
-
}
|
|
14700
|
-
return score;
|
|
14701
|
-
}
|
|
14702
|
-
/** Helper to create a FitnessFinding with defaults. */
|
|
14703
|
-
finding(dimension, severity, description, pointsDeducted, suggestion) {
|
|
14704
|
-
const base = { dimension, severity, description, pointsDeducted };
|
|
14705
|
-
if (suggestion !== void 0) {
|
|
14706
|
-
return { ...base, suggestion };
|
|
14707
|
-
}
|
|
14708
|
-
return base;
|
|
14709
|
-
}
|
|
14710
|
-
};
|
|
14711
|
-
function createFitnessScoreCalculator(logger17) {
|
|
14712
|
-
return new FitnessScoreCalculator(logger17);
|
|
14713
|
-
}
|
|
14714
|
-
function calculateFitnessScore(version) {
|
|
14715
|
-
const calculator = createFitnessScoreCalculator();
|
|
14716
|
-
return calculator.audit(version);
|
|
14717
|
-
}
|
|
14718
|
-
|
|
14719
14182
|
// src/cli/fitness-audit.ts
|
|
14720
14183
|
var COLORS = colors;
|
|
14721
14184
|
function formatScore(score, max) {
|
|
@@ -15149,11 +14612,11 @@ async function releaseNotesCommand(args) {
|
|
|
15149
14612
|
}
|
|
15150
14613
|
|
|
15151
14614
|
// src/cli/release-validate-command.ts
|
|
15152
|
-
import { readFileSync as
|
|
14615
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
15153
14616
|
|
|
15154
14617
|
// src/cli/release-validate-helpers.ts
|
|
15155
14618
|
import { execSync as execSync2 } from "child_process";
|
|
15156
|
-
import { existsSync as
|
|
14619
|
+
import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
|
|
15157
14620
|
async function validateSecurity(options) {
|
|
15158
14621
|
const startTime = Date.now();
|
|
15159
14622
|
const findings = [];
|
|
@@ -15172,7 +14635,7 @@ async function validateSecurity(options) {
|
|
|
15172
14635
|
remediation: "Run npm audit fix or review and update vulnerable dependencies."
|
|
15173
14636
|
});
|
|
15174
14637
|
}
|
|
15175
|
-
if (
|
|
14638
|
+
if (existsSync12(".env")) {
|
|
15176
14639
|
findings.push({
|
|
15177
14640
|
severity: "error",
|
|
15178
14641
|
category: "security",
|
|
@@ -15268,7 +14731,7 @@ async function validateArchitecture2(options) {
|
|
|
15268
14731
|
async function validateDocumentation(options) {
|
|
15269
14732
|
const startTime = Date.now();
|
|
15270
14733
|
const findings = [];
|
|
15271
|
-
if (!
|
|
14734
|
+
if (!existsSync12("CHANGELOG.md")) {
|
|
15272
14735
|
findings.push({
|
|
15273
14736
|
severity: "error",
|
|
15274
14737
|
category: "docs",
|
|
@@ -15276,7 +14739,7 @@ async function validateDocumentation(options) {
|
|
|
15276
14739
|
description: "No CHANGELOG.md found in repository root.",
|
|
15277
14740
|
remediation: "Create CHANGELOG.md following Keep a Changelog format."
|
|
15278
14741
|
});
|
|
15279
|
-
} else if (!
|
|
14742
|
+
} else if (!readFileSync6("CHANGELOG.md", "utf-8").includes(options.version)) {
|
|
15280
14743
|
findings.push({
|
|
15281
14744
|
severity: "warning",
|
|
15282
14745
|
category: "docs",
|
|
@@ -15286,7 +14749,7 @@ async function validateDocumentation(options) {
|
|
|
15286
14749
|
});
|
|
15287
14750
|
}
|
|
15288
14751
|
const pkgCl = "packages/nexus-agents/CHANGELOG.md";
|
|
15289
|
-
if (
|
|
14752
|
+
if (existsSync12(pkgCl) && !readFileSync6(pkgCl, "utf-8").includes(options.version)) {
|
|
15290
14753
|
findings.push({
|
|
15291
14754
|
severity: "warning",
|
|
15292
14755
|
category: "docs",
|
|
@@ -15295,7 +14758,7 @@ async function validateDocumentation(options) {
|
|
|
15295
14758
|
remediation: "Run pnpm changeset:version to generate changelog from pending changesets."
|
|
15296
14759
|
});
|
|
15297
14760
|
}
|
|
15298
|
-
if (!
|
|
14761
|
+
if (!existsSync12("README.md")) {
|
|
15299
14762
|
findings.push({
|
|
15300
14763
|
severity: "error",
|
|
15301
14764
|
category: "docs",
|
|
@@ -15304,8 +14767,8 @@ async function validateDocumentation(options) {
|
|
|
15304
14767
|
remediation: "Create README.md with project overview and usage instructions."
|
|
15305
14768
|
});
|
|
15306
14769
|
}
|
|
15307
|
-
if (
|
|
15308
|
-
const claudeMd =
|
|
14770
|
+
if (existsSync12("CLAUDE.md")) {
|
|
14771
|
+
const claudeMd = readFileSync6("CLAUDE.md", "utf-8");
|
|
15309
14772
|
const match = claudeMd.match(/Governance Version: (\d{4}-\d{2}-\d{2})/);
|
|
15310
14773
|
if (match?.[1]) {
|
|
15311
14774
|
const governanceDate = new Date(match[1]);
|
|
@@ -15413,7 +14876,7 @@ var DEFAULT_OPTIONS2 = {
|
|
|
15413
14876
|
};
|
|
15414
14877
|
function readVersionFromPackage() {
|
|
15415
14878
|
try {
|
|
15416
|
-
const raw = JSON.parse(
|
|
14879
|
+
const raw = JSON.parse(readFileSync7("package.json", "utf-8"));
|
|
15417
14880
|
if (typeof raw === "object" && raw !== null && "version" in raw) {
|
|
15418
14881
|
const pkg = raw;
|
|
15419
14882
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
@@ -15527,7 +14990,7 @@ async function releaseValidateCommand(args) {
|
|
|
15527
14990
|
}
|
|
15528
14991
|
|
|
15529
14992
|
// src/cli/release-announce-command.ts
|
|
15530
|
-
import { readFileSync as
|
|
14993
|
+
import { readFileSync as readFileSync8, existsSync as existsSync13 } from "fs";
|
|
15531
14994
|
|
|
15532
14995
|
// src/cli/release-announce-types.ts
|
|
15533
14996
|
var BLUESKY_LIMITS = {
|
|
@@ -15594,8 +15057,8 @@ var DEFAULT_OPTIONS3 = {
|
|
|
15594
15057
|
verbose: false
|
|
15595
15058
|
};
|
|
15596
15059
|
function extractHighlightsFromChangelog(version) {
|
|
15597
|
-
if (!
|
|
15598
|
-
const changelog =
|
|
15060
|
+
if (!existsSync13("CHANGELOG.md")) return [];
|
|
15061
|
+
const changelog = readFileSync8("CHANGELOG.md", "utf-8");
|
|
15599
15062
|
const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15600
15063
|
const versionRegex = new RegExp(`## \\[${escaped}\\][^#]*`, "s");
|
|
15601
15064
|
const match = changelog.match(versionRegex);
|
|
@@ -15857,7 +15320,7 @@ async function releaseAnnounceCommand(args) {
|
|
|
15857
15320
|
version = args.options.version;
|
|
15858
15321
|
} else {
|
|
15859
15322
|
try {
|
|
15860
|
-
const pkg = JSON.parse(
|
|
15323
|
+
const pkg = JSON.parse(readFileSync8("package.json", "utf-8"));
|
|
15861
15324
|
if (!pkg.version) {
|
|
15862
15325
|
console.error(`${colors.red}Error: Could not determine version${colors.reset}`);
|
|
15863
15326
|
return 1;
|
|
@@ -16789,13 +16252,13 @@ function formatEvalDetails(baseline, reflective, improvement, datasetSize) {
|
|
|
16789
16252
|
}
|
|
16790
16253
|
|
|
16791
16254
|
// src/cli/auth-command.ts
|
|
16792
|
-
import { existsSync as
|
|
16255
|
+
import { existsSync as existsSync15, statSync, chmodSync } from "fs";
|
|
16793
16256
|
function isValidAuthSubcommand(value) {
|
|
16794
16257
|
return value === "init" || value === "show" || value === "rotate" || value === "help";
|
|
16795
16258
|
}
|
|
16796
16259
|
function getFilePermissions(filePath) {
|
|
16797
16260
|
try {
|
|
16798
|
-
const stats =
|
|
16261
|
+
const stats = statSync(filePath);
|
|
16799
16262
|
return (stats.mode & 511).toString(8);
|
|
16800
16263
|
} catch {
|
|
16801
16264
|
return void 0;
|
|
@@ -16809,7 +16272,7 @@ function fixPermissions(filePath) {
|
|
|
16809
16272
|
}
|
|
16810
16273
|
function runAuthInit(options) {
|
|
16811
16274
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
16812
|
-
const tokenExists =
|
|
16275
|
+
const tokenExists = existsSync15(tokenFile);
|
|
16813
16276
|
if (tokenExists && options.force !== true) {
|
|
16814
16277
|
return {
|
|
16815
16278
|
success: false,
|
|
@@ -16833,7 +16296,7 @@ function runAuthInit(options) {
|
|
|
16833
16296
|
}
|
|
16834
16297
|
function runAuthShow(options) {
|
|
16835
16298
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
16836
|
-
const tokenExists =
|
|
16299
|
+
const tokenExists = existsSync15(tokenFile);
|
|
16837
16300
|
const token = readStoredToken(tokenFile);
|
|
16838
16301
|
if (!tokenExists || token === void 0) {
|
|
16839
16302
|
return {
|
|
@@ -16854,7 +16317,7 @@ function runAuthShow(options) {
|
|
|
16854
16317
|
}
|
|
16855
16318
|
function runAuthRotate(options) {
|
|
16856
16319
|
const tokenFile = options.tokenFile ?? getDefaultTokenPath();
|
|
16857
|
-
const tokenExists =
|
|
16320
|
+
const tokenExists = existsSync15(tokenFile);
|
|
16858
16321
|
if (!tokenExists) {
|
|
16859
16322
|
return {
|
|
16860
16323
|
success: false,
|
|
@@ -16890,14 +16353,14 @@ function runAuthCommand(options) {
|
|
|
16890
16353
|
success: true,
|
|
16891
16354
|
operation: "help",
|
|
16892
16355
|
tokenFile: getDefaultTokenPath(),
|
|
16893
|
-
tokenExists:
|
|
16356
|
+
tokenExists: existsSync15(getDefaultTokenPath())
|
|
16894
16357
|
};
|
|
16895
16358
|
default:
|
|
16896
16359
|
return {
|
|
16897
16360
|
success: false,
|
|
16898
16361
|
operation: "help",
|
|
16899
16362
|
tokenFile: getDefaultTokenPath(),
|
|
16900
|
-
tokenExists:
|
|
16363
|
+
tokenExists: existsSync15(getDefaultTokenPath()),
|
|
16901
16364
|
error: `Unknown subcommand: ${String(subcommand)}`
|
|
16902
16365
|
};
|
|
16903
16366
|
}
|
|
@@ -17740,22 +17203,22 @@ function isValidCommand(value) {
|
|
|
17740
17203
|
}
|
|
17741
17204
|
|
|
17742
17205
|
// src/cli-commands-handlers.ts
|
|
17743
|
-
import { existsSync as
|
|
17206
|
+
import { existsSync as existsSync20 } from "fs";
|
|
17744
17207
|
|
|
17745
17208
|
// src/cli/init-portable.ts
|
|
17746
17209
|
import {
|
|
17747
|
-
existsSync as
|
|
17210
|
+
existsSync as existsSync19,
|
|
17748
17211
|
mkdirSync as mkdirSync5,
|
|
17749
|
-
readdirSync
|
|
17750
|
-
statSync as
|
|
17212
|
+
readdirSync,
|
|
17213
|
+
statSync as statSync2,
|
|
17751
17214
|
appendFileSync as appendFileSync2,
|
|
17752
|
-
readFileSync as
|
|
17215
|
+
readFileSync as readFileSync11
|
|
17753
17216
|
} from "fs";
|
|
17754
|
-
import { resolve as resolve11, join as
|
|
17217
|
+
import { resolve as resolve11, join as join15, isAbsolute as isAbsolute2 } from "path";
|
|
17755
17218
|
|
|
17756
17219
|
// src/cli/mcp-config-emitter.ts
|
|
17757
|
-
import { existsSync as
|
|
17758
|
-
import { join as
|
|
17220
|
+
import { existsSync as existsSync16, readFileSync as readFileSync9, writeFileSync as writeFileSync5, appendFileSync } from "fs";
|
|
17221
|
+
import { join as join12 } from "path";
|
|
17759
17222
|
var MCP_CONFIG_FILENAME = ".mcp.json";
|
|
17760
17223
|
var NEXUS_SERVER_KEY = "nexus-agents";
|
|
17761
17224
|
function buildNexusServerEntry(dataDir, commandPath) {
|
|
@@ -17778,10 +17241,10 @@ function entriesEqual(a, b) {
|
|
|
17778
17241
|
return true;
|
|
17779
17242
|
}
|
|
17780
17243
|
function loadExistingConfig(path23) {
|
|
17781
|
-
if (!
|
|
17244
|
+
if (!existsSync16(path23)) return { ok: true, value: void 0 };
|
|
17782
17245
|
let raw;
|
|
17783
17246
|
try {
|
|
17784
|
-
raw =
|
|
17247
|
+
raw = readFileSync9(path23, "utf-8");
|
|
17785
17248
|
} catch (e) {
|
|
17786
17249
|
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
17787
17250
|
}
|
|
@@ -17815,12 +17278,12 @@ function decideEmission(existing, desired, force) {
|
|
|
17815
17278
|
return { kind: "write", nextConfig: { ...existing, mcpServers: nextServers } };
|
|
17816
17279
|
}
|
|
17817
17280
|
function autoGitignoreMcpConfig(workspaceDir, dryRun) {
|
|
17818
|
-
const gitDir =
|
|
17819
|
-
if (!
|
|
17820
|
-
const gitignorePath =
|
|
17281
|
+
const gitDir = join12(workspaceDir, ".git");
|
|
17282
|
+
if (!existsSync16(gitDir)) return false;
|
|
17283
|
+
const gitignorePath = join12(workspaceDir, ".gitignore");
|
|
17821
17284
|
let existing = "";
|
|
17822
|
-
if (
|
|
17823
|
-
existing =
|
|
17285
|
+
if (existsSync16(gitignorePath)) {
|
|
17286
|
+
existing = readFileSync9(gitignorePath, "utf-8");
|
|
17824
17287
|
const already = existing.split("\n").some((l) => l.trim() === MCP_CONFIG_FILENAME || l.trim() === `/${MCP_CONFIG_FILENAME}`);
|
|
17825
17288
|
if (already) return false;
|
|
17826
17289
|
}
|
|
@@ -17832,7 +17295,7 @@ function autoGitignoreMcpConfig(workspaceDir, dryRun) {
|
|
|
17832
17295
|
return true;
|
|
17833
17296
|
}
|
|
17834
17297
|
function emitMcpConfig(options) {
|
|
17835
|
-
const mcpConfigPath =
|
|
17298
|
+
const mcpConfigPath = join12(options.workspaceDir, MCP_CONFIG_FILENAME);
|
|
17836
17299
|
const dryRun = options.dryRun === true;
|
|
17837
17300
|
const force = options.force === true;
|
|
17838
17301
|
const desired = buildNexusServerEntry(options.dataDir, options.commandPath);
|
|
@@ -17870,13 +17333,13 @@ function makeFailure(mcpConfigPath, error) {
|
|
|
17870
17333
|
|
|
17871
17334
|
// src/cli/portable-installer.ts
|
|
17872
17335
|
import { execFile } from "child_process";
|
|
17873
|
-
import { existsSync as
|
|
17874
|
-
import { join as
|
|
17336
|
+
import { existsSync as existsSync18, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
17337
|
+
import { join as join14 } from "path";
|
|
17875
17338
|
import { promisify } from "util";
|
|
17876
17339
|
|
|
17877
17340
|
// src/cli/bin-shim.ts
|
|
17878
|
-
import { existsSync as
|
|
17879
|
-
import { join as
|
|
17341
|
+
import { existsSync as existsSync17, readFileSync as readFileSync10, writeFileSync as writeFileSync6, chmodSync as chmodSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
17342
|
+
import { join as join13 } from "path";
|
|
17880
17343
|
var SHIM_BASENAME = "nexus-agents";
|
|
17881
17344
|
var SHIM_MODE = 493;
|
|
17882
17345
|
function buildShimContents(cliEntryPath) {
|
|
@@ -17890,18 +17353,18 @@ function buildShimContents(cliEntryPath) {
|
|
|
17890
17353
|
return lines.join("\n");
|
|
17891
17354
|
}
|
|
17892
17355
|
function writeBinShim(options) {
|
|
17893
|
-
const shimPath =
|
|
17356
|
+
const shimPath = join13(options.binDir, SHIM_BASENAME);
|
|
17894
17357
|
const desired = buildShimContents(options.cliEntryPath);
|
|
17895
17358
|
const dryRun = options.dryRun === true;
|
|
17896
17359
|
try {
|
|
17897
|
-
if (
|
|
17898
|
-
const current =
|
|
17360
|
+
if (existsSync17(shimPath)) {
|
|
17361
|
+
const current = readFileSync10(shimPath, "utf-8");
|
|
17899
17362
|
if (current === desired) {
|
|
17900
17363
|
return { success: true, shimPath, written: false, alreadyMatched: true, error: null };
|
|
17901
17364
|
}
|
|
17902
17365
|
}
|
|
17903
17366
|
if (!dryRun) {
|
|
17904
|
-
if (!
|
|
17367
|
+
if (!existsSync17(options.binDir)) mkdirSync3(options.binDir, { recursive: true });
|
|
17905
17368
|
writeFileSync6(shimPath, desired, "utf-8");
|
|
17906
17369
|
chmodSync2(shimPath, SHIM_MODE);
|
|
17907
17370
|
}
|
|
@@ -17936,10 +17399,10 @@ function writeInstallManifest(cliDir, version) {
|
|
|
17936
17399
|
description: "Local install root for portable nexus-agents (generated; do not commit)",
|
|
17937
17400
|
dependencies: { "nexus-agents": version }
|
|
17938
17401
|
};
|
|
17939
|
-
writeFileSync7(
|
|
17402
|
+
writeFileSync7(join14(cliDir, "package.json"), JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
17940
17403
|
}
|
|
17941
17404
|
function isAlreadyInstalled(cliDir) {
|
|
17942
|
-
return
|
|
17405
|
+
return existsSync18(join14(cliDir, "node_modules", "nexus-agents", "package.json"));
|
|
17943
17406
|
}
|
|
17944
17407
|
async function spawnNpmInstall(cliDir) {
|
|
17945
17408
|
await execFileAsync("npm", ["install", "--no-audit", "--no-fund", "--silent"], {
|
|
@@ -17955,7 +17418,7 @@ function cleanupOnFailure(cliDir) {
|
|
|
17955
17418
|
}
|
|
17956
17419
|
async function runNpmStep(ctx) {
|
|
17957
17420
|
try {
|
|
17958
|
-
if (!
|
|
17421
|
+
if (!existsSync18(ctx.cliDir)) mkdirSync4(ctx.cliDir, { recursive: true });
|
|
17959
17422
|
writeInstallManifest(ctx.cliDir, ctx.version);
|
|
17960
17423
|
await spawnNpmInstall(ctx.cliDir);
|
|
17961
17424
|
return void 0;
|
|
@@ -17966,8 +17429,8 @@ async function runNpmStep(ctx) {
|
|
|
17966
17429
|
}
|
|
17967
17430
|
}
|
|
17968
17431
|
async function installPortable(options) {
|
|
17969
|
-
const cliDir =
|
|
17970
|
-
const binDir =
|
|
17432
|
+
const cliDir = join14(options.dataDir, CLI_SUBDIR);
|
|
17433
|
+
const binDir = join14(options.dataDir, BIN_SUBDIR);
|
|
17971
17434
|
const versionResolution = resolveInstallVersion(options.version);
|
|
17972
17435
|
if (!versionResolution.ok) {
|
|
17973
17436
|
return {
|
|
@@ -17988,7 +17451,7 @@ async function installPortable(options) {
|
|
|
17988
17451
|
}
|
|
17989
17452
|
const npmFailure = await runNpmStep(ctx);
|
|
17990
17453
|
if (npmFailure !== void 0) return npmFailure;
|
|
17991
|
-
const shim = writeBinShim({ binDir, cliEntryPath:
|
|
17454
|
+
const shim = writeBinShim({ binDir, cliEntryPath: join14(cliDir, CLI_ENTRY_RELATIVE) });
|
|
17992
17455
|
if (!shim.success) {
|
|
17993
17456
|
cleanupOnFailure(cliDir);
|
|
17994
17457
|
return {
|
|
@@ -18002,14 +17465,14 @@ async function installPortable(options) {
|
|
|
18002
17465
|
return { success: true, ...ctx, shim, skipped: false, error: null };
|
|
18003
17466
|
}
|
|
18004
17467
|
function uninstallPortable(options) {
|
|
18005
|
-
const cliDir =
|
|
18006
|
-
const binDir =
|
|
17468
|
+
const cliDir = join14(options.dataDir, CLI_SUBDIR);
|
|
17469
|
+
const binDir = join14(options.dataDir, BIN_SUBDIR);
|
|
18007
17470
|
const removed = [];
|
|
18008
17471
|
const notPresent = [];
|
|
18009
17472
|
const dryRun = options.dryRun === true;
|
|
18010
17473
|
try {
|
|
18011
17474
|
for (const dir of [cliDir, binDir]) {
|
|
18012
|
-
if (!
|
|
17475
|
+
if (!existsSync18(dir)) {
|
|
18013
17476
|
notPresent.push(dir);
|
|
18014
17477
|
continue;
|
|
18015
17478
|
}
|
|
@@ -18023,8 +17486,8 @@ function uninstallPortable(options) {
|
|
|
18023
17486
|
}
|
|
18024
17487
|
}
|
|
18025
17488
|
function findBinShim(dataDir) {
|
|
18026
|
-
const shimPath =
|
|
18027
|
-
return
|
|
17489
|
+
const shimPath = join14(dataDir, BIN_SUBDIR, "nexus-agents");
|
|
17490
|
+
return existsSync18(shimPath) ? shimPath : void 0;
|
|
18028
17491
|
}
|
|
18029
17492
|
|
|
18030
17493
|
// src/cli/init-portable.ts
|
|
@@ -18037,13 +17500,13 @@ function resolveTargetPath(rawPath) {
|
|
|
18037
17500
|
return isAbsolute2(rawPath) ? rawPath : resolve11(process.cwd(), rawPath);
|
|
18038
17501
|
}
|
|
18039
17502
|
function isNonEmpty(dir) {
|
|
18040
|
-
if (!
|
|
18041
|
-
const stat2 =
|
|
17503
|
+
if (!existsSync19(dir)) return false;
|
|
17504
|
+
const stat2 = statSync2(dir);
|
|
18042
17505
|
if (!stat2.isDirectory()) return true;
|
|
18043
|
-
return
|
|
17506
|
+
return readdirSync(dir).length > 0;
|
|
18044
17507
|
}
|
|
18045
17508
|
function ensureDir(path23, dryRun, created, alreadyExisted, mode) {
|
|
18046
|
-
if (
|
|
17509
|
+
if (existsSync19(path23)) {
|
|
18047
17510
|
alreadyExisted.push(path23);
|
|
18048
17511
|
return;
|
|
18049
17512
|
}
|
|
@@ -18053,13 +17516,13 @@ function ensureDir(path23, dryRun, created, alreadyExisted, mode) {
|
|
|
18053
17516
|
created.push(path23);
|
|
18054
17517
|
}
|
|
18055
17518
|
function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
|
|
18056
|
-
const gitDir =
|
|
18057
|
-
if (!
|
|
18058
|
-
const gitignorePath =
|
|
17519
|
+
const gitDir = join15(workspaceDir, ".git");
|
|
17520
|
+
if (!existsSync19(gitDir)) return false;
|
|
17521
|
+
const gitignorePath = join15(workspaceDir, ".gitignore");
|
|
18059
17522
|
const entry = `${portableDirName}/`;
|
|
18060
17523
|
let existing = "";
|
|
18061
|
-
if (
|
|
18062
|
-
existing =
|
|
17524
|
+
if (existsSync19(gitignorePath)) {
|
|
17525
|
+
existing = readFileSync11(gitignorePath, "utf-8");
|
|
18063
17526
|
if (existing.split("\n").some((l) => l.trim() === entry || l.trim() === portableDirName)) {
|
|
18064
17527
|
return false;
|
|
18065
17528
|
}
|
|
@@ -18072,18 +17535,18 @@ function maybeUpdateGitignore(workspaceDir, portableDirName, dryRun) {
|
|
|
18072
17535
|
return true;
|
|
18073
17536
|
}
|
|
18074
17537
|
function inspectTarget(target) {
|
|
18075
|
-
const exists =
|
|
17538
|
+
const exists = existsSync19(target);
|
|
18076
17539
|
if (!exists) return { exists: false, nonEmpty: false, isExistingNexusDir: false };
|
|
18077
17540
|
const nonEmpty = isNonEmpty(target);
|
|
18078
|
-
const stat2 =
|
|
18079
|
-
const isExistingNexusDir = stat2.isDirectory() &&
|
|
17541
|
+
const stat2 = statSync2(target);
|
|
17542
|
+
const isExistingNexusDir = stat2.isDirectory() && existsSync19(join15(target, "audit"));
|
|
18080
17543
|
return { exists, nonEmpty, isExistingNexusDir };
|
|
18081
17544
|
}
|
|
18082
17545
|
function createDataLayout(target, dryRun, created, alreadyExisted) {
|
|
18083
17546
|
ensureDir(target, dryRun, created, alreadyExisted);
|
|
18084
17547
|
for (const subdir of DATA_SUBDIRECTORIES) {
|
|
18085
17548
|
const mode = RESTRICTED_SUBDIRS.has(subdir) ? 448 : void 0;
|
|
18086
|
-
ensureDir(
|
|
17549
|
+
ensureDir(join15(target, subdir), dryRun, created, alreadyExisted, mode);
|
|
18087
17550
|
}
|
|
18088
17551
|
}
|
|
18089
17552
|
function makeResult(opts) {
|
|
@@ -18818,7 +18281,8 @@ var REGISTERED_TOOLS = [
|
|
|
18818
18281
|
"registry_import",
|
|
18819
18282
|
"query_trace",
|
|
18820
18283
|
"repo_analyze",
|
|
18821
|
-
"repo_security_plan"
|
|
18284
|
+
"repo_security_plan",
|
|
18285
|
+
"improvement_review"
|
|
18822
18286
|
];
|
|
18823
18287
|
var MOCK_ORCHESTRATION_ENV = "NEXUS_ALLOW_MOCK_ORCHESTRATION";
|
|
18824
18288
|
function createOrchestratorForOrchestration(modelAdapter, logger17, useMockTechLead) {
|
|
@@ -19082,6 +18546,7 @@ function buildStandardDeps(ctx, toolName) {
|
|
|
19082
18546
|
var STANDALONE_TOOLS = [
|
|
19083
18547
|
{ name: "consensus_vote", register: registerConsensusVoteTool },
|
|
19084
18548
|
{ name: "weather_report", register: registerWeatherReportTool },
|
|
18549
|
+
{ name: "improvement_review", register: registerImprovementReviewTool },
|
|
19085
18550
|
{ name: "registry_import", register: registerRegistryImportTool },
|
|
19086
18551
|
{ name: "repo_analyze", register: registerRepoAnalyzeTool },
|
|
19087
18552
|
{ name: "repo_security_plan", register: registerRepoSecurityPlanTool },
|
|
@@ -21109,8 +20574,8 @@ function printFirstRunHint() {
|
|
|
21109
20574
|
const isTTY = process.stderr.isTTY;
|
|
21110
20575
|
if (!isTTY) return;
|
|
21111
20576
|
const dataDir = getNexusDataDir();
|
|
21112
|
-
const hasConfig =
|
|
21113
|
-
if (
|
|
20577
|
+
const hasConfig = existsSync20("./nexus-agents.yaml") || existsSync20("./nexus-agents.yml");
|
|
20578
|
+
if (existsSync20(dataDir) || hasConfig) return;
|
|
21114
20579
|
process.stderr.write(
|
|
21115
20580
|
"\n\x1B[36mnexus-agents\x1B[0m: First time? Run \x1B[1mnexus-agents setup\x1B[0m to configure.\n\n"
|
|
21116
20581
|
);
|
|
@@ -21586,12 +21051,12 @@ function findPackageRoot(startDir) {
|
|
|
21586
21051
|
}
|
|
21587
21052
|
return startDir;
|
|
21588
21053
|
}
|
|
21589
|
-
function
|
|
21054
|
+
function countFiles(dir, pattern) {
|
|
21590
21055
|
if (!fs18.existsSync(dir)) return 0;
|
|
21591
21056
|
let count = 0;
|
|
21592
21057
|
for (const entry of fs18.readdirSync(dir, { withFileTypes: true })) {
|
|
21593
21058
|
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "dist") {
|
|
21594
|
-
count +=
|
|
21059
|
+
count += countFiles(path22.join(dir, entry.name), pattern);
|
|
21595
21060
|
} else if (entry.isFile() && pattern.test(entry.name)) {
|
|
21596
21061
|
count++;
|
|
21597
21062
|
}
|
|
@@ -21623,11 +21088,11 @@ function gatherSystemSummary() {
|
|
|
21623
21088
|
const thisFile = fileURLToPath(import.meta.url);
|
|
21624
21089
|
const pkgRoot = findPackageRoot(path22.dirname(thisFile));
|
|
21625
21090
|
const srcDir = path22.resolve(pkgRoot, "src");
|
|
21626
|
-
const allTs =
|
|
21627
|
-
const testTs =
|
|
21091
|
+
const allTs = countFiles(srcDir, /\.ts$/);
|
|
21092
|
+
const testTs = countFiles(srcDir, /\.test\.ts$/);
|
|
21628
21093
|
const layers = LAYER_DIRS.map(({ name, dir }) => ({
|
|
21629
21094
|
name,
|
|
21630
|
-
files:
|
|
21095
|
+
files: countFiles(path22.join(srcDir, dir), /\.ts$/)
|
|
21631
21096
|
})).filter((l) => l.files > 0);
|
|
21632
21097
|
return {
|
|
21633
21098
|
version: readVersion(pkgRoot),
|
|
@@ -22776,7 +22241,7 @@ function handleStatusCommand2(args) {
|
|
|
22776
22241
|
|
|
22777
22242
|
// src/cli/scenario-command.ts
|
|
22778
22243
|
import { readdir as readdir4 } from "fs/promises";
|
|
22779
|
-
import { join as
|
|
22244
|
+
import { join as join17, resolve as resolve14 } from "path";
|
|
22780
22245
|
|
|
22781
22246
|
// src/testing/e2e/scenario-runner.ts
|
|
22782
22247
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -23146,7 +22611,7 @@ async function handleRun(args) {
|
|
|
23146
22611
|
process.exit(EXIT_CODES.SERVER_START_FAILED);
|
|
23147
22612
|
}
|
|
23148
22613
|
const runner = createScenarioRunner();
|
|
23149
|
-
const fixturePath =
|
|
22614
|
+
const fixturePath = join17(FIXTURES_DIR, `${name}${SCENARIO_SUFFIX}`);
|
|
23150
22615
|
try {
|
|
23151
22616
|
const fixture = await runner.loadFixture(fixturePath);
|
|
23152
22617
|
const result = await runner.run(fixture);
|