@nathapp/nax 0.69.2 → 0.69.4

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.
Files changed (2) hide show
  1. package/dist/nax.js +48 -19
  2. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -25203,8 +25203,22 @@ async function selectScopedTests(input) {
25203
25203
  if (!smartCfg.enabled || !input.storyGitRef || isMonorepoOrchestrator) {
25204
25204
  return { effectiveCommand: input.testCommand, isFullSuite: true, thresholdFallback: false, isMonorepoOrchestrator };
25205
25205
  }
25206
- const nonTestFiles = await _scopedSelectionDeps.getChangedNonTestFiles(input.workdir, input.storyGitRef, undefined, globsToTestRegex(smartCfg.testFilePatterns), input.naxIgnoreIndex);
25207
- const pass1Files = await _scopedSelectionDeps.mapSourceToTests(nonTestFiles, input.workdir);
25206
+ const repoRoot = input.repoRoot ?? input.workdir;
25207
+ const classifyRegex = input.resolvedTestPatterns?.regex ? [...input.resolvedTestPatterns.regex] : globsToTestRegex(smartCfg.testFilePatterns);
25208
+ const mappingGlobs = input.resolvedTestPatterns?.globs ? [...input.resolvedTestPatterns.globs] : smartCfg.testFilePatterns;
25209
+ const changedTestFiles = await _scopedSelectionDeps.getChangedTestFiles(input.workdir, repoRoot, input.storyGitRef, input.packagePrefix, classifyRegex, input.naxIgnoreIndex);
25210
+ if (changedTestFiles.length > threshold) {
25211
+ logger.warn("verify[scoped]", `Changed test file count ${changedTestFiles.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
25212
+ return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
25213
+ }
25214
+ if (changedTestFiles.length > 0) {
25215
+ logger.info("verify[scoped]", `Pass 0: ${changedTestFiles.length} changed test file(s) detected directly`, {
25216
+ storyId: input.storyId
25217
+ });
25218
+ return scoped(changedTestFiles);
25219
+ }
25220
+ const nonTestFiles = await _scopedSelectionDeps.getChangedNonTestFiles(input.workdir, input.storyGitRef, input.packagePrefix, classifyRegex, input.naxIgnoreIndex, repoRoot);
25221
+ const pass1Files = await _scopedSelectionDeps.mapSourceToTests(nonTestFiles, repoRoot, input.packagePrefix, mappingGlobs);
25208
25222
  if (pass1Files.length > threshold) {
25209
25223
  logger.warn("verify[scoped]", `Scoped test file count ${pass1Files.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
25210
25224
  return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
@@ -25218,7 +25232,7 @@ async function selectScopedTests(input) {
25218
25232
  if (smartCfg.fallback !== "import-grep") {
25219
25233
  return fullSuite();
25220
25234
  }
25221
- const pass2Files = await _scopedSelectionDeps.importGrepFallback(nonTestFiles, input.workdir, smartCfg.testFilePatterns);
25235
+ const pass2Files = await _scopedSelectionDeps.importGrepFallback(nonTestFiles, input.workdir, mappingGlobs);
25222
25236
  if (pass2Files.length > threshold) {
25223
25237
  logger.warn("verify[scoped]", `Scoped test file count ${pass2Files.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
25224
25238
  return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
@@ -25243,6 +25257,7 @@ var init_scoped_selection = __esm(() => {
25243
25257
  };
25244
25258
  _scopedSelectionDeps = {
25245
25259
  getChangedNonTestFiles: _smartRunnerDeps.getChangedNonTestFiles,
25260
+ getChangedTestFiles: _smartRunnerDeps.getChangedTestFiles,
25246
25261
  mapSourceToTests: _smartRunnerDeps.mapSourceToTests,
25247
25262
  importGrepFallback: _smartRunnerDeps.importGrepFallback,
25248
25263
  buildSmartTestCommand: _smartRunnerDeps.buildSmartTestCommand
@@ -38717,13 +38732,14 @@ var init_full_suite_gate = __esm(() => {
38717
38732
  workdir: input.workdir
38718
38733
  });
38719
38734
  }
38720
- return { config: config2, testCmd: resolvedTestCmd, fullSuiteTimeout };
38735
+ const cmdWorkdir = ctx.packageView.hasOverride ? input.workdir : ctx.packageView.repoRoot;
38736
+ return { config: config2, testCmd: resolvedTestCmd, fullSuiteTimeout, cmdWorkdir };
38721
38737
  },
38722
- runTests: async (input, gateCtx) => {
38738
+ runTests: async (_input, gateCtx) => {
38723
38739
  const { regression: regression2 } = await Promise.resolve().then(() => (init_runners(), exports_runners));
38724
38740
  const { parseTestOutput: parseTestOutput2 } = await Promise.resolve().then(() => (init_test_runners(), exports_test_runners));
38725
38741
  const result = await regression2({
38726
- workdir: input.workdir,
38742
+ workdir: gateCtx.cmdWorkdir,
38727
38743
  command: gateCtx.testCmd,
38728
38744
  timeoutSeconds: gateCtx.fullSuiteTimeout,
38729
38745
  acceptOnTimeout: false,
@@ -38773,7 +38789,7 @@ var init_full_suite_gate = __esm(() => {
38773
38789
  logger.info("verify[regression]", "Running full-suite gate", {
38774
38790
  storyId: input.story.id,
38775
38791
  packageDir: input.story.workdir,
38776
- cwd: input.workdir,
38792
+ cwd: gateCtx.cmdWorkdir,
38777
38793
  command: gateCtx.testCmd,
38778
38794
  timeoutSeconds: gateCtx.fullSuiteTimeout
38779
38795
  });
@@ -39363,11 +39379,12 @@ var init_lint_check = __esm(() => {
39363
39379
  });
39364
39380
  return { success: true, status: "skipped", findings: [], durationMs: 0 };
39365
39381
  }
39382
+ const cmdWorkdir = ctx.packageView.hasOverride ? input.workdir : ctx.packageView.repoRoot;
39366
39383
  const start = Date.now();
39367
39384
  const result = await deps.runQualityCommand({
39368
39385
  commandName: "lint",
39369
39386
  command,
39370
- workdir: input.workdir,
39387
+ workdir: cmdWorkdir,
39371
39388
  storyId: input.storyId,
39372
39389
  stripEnvVars: quality?.stripEnvVars ?? []
39373
39390
  });
@@ -39618,11 +39635,12 @@ var init_typecheck_check = __esm(() => {
39618
39635
  });
39619
39636
  return { success: true, status: "skipped", findings: [], durationMs: 0 };
39620
39637
  }
39638
+ const cmdWorkdir = ctx.packageView.hasOverride ? input.workdir : ctx.packageView.repoRoot;
39621
39639
  const start = Date.now();
39622
39640
  const result = await deps.runQualityCommand({
39623
39641
  commandName: "typecheck",
39624
39642
  command,
39625
- workdir: input.workdir,
39643
+ workdir: cmdWorkdir,
39626
39644
  storyId: input.storyId,
39627
39645
  stripEnvVars: quality?.stripEnvVars ?? []
39628
39646
  });
@@ -39682,7 +39700,10 @@ var init_verify_scoped = __esm(() => {
39682
39700
  smartRunnerConfig: quality.execution?.smartTestRunner,
39683
39701
  scopeTestThreshold: quality.quality?.scopeTestThreshold,
39684
39702
  fallbackFullSuiteCommand: quality.quality?.commands?.test,
39685
- naxIgnoreIndex: input.naxIgnoreIndex
39703
+ naxIgnoreIndex: input.naxIgnoreIndex,
39704
+ repoRoot: input.repoRoot,
39705
+ packagePrefix: input.packagePrefix,
39706
+ resolvedTestPatterns: input.resolvedTestPatterns
39686
39707
  });
39687
39708
  if (selection.isFullSuite && regressionMode === "deferred" && !selection.isMonorepoOrchestrator && !selection.thresholdFallback) {
39688
39709
  logger.info("verify[scoped]", "No mapped tests \u2014 deferring to run-end (mode: deferred)", {
@@ -39709,17 +39730,18 @@ var init_verify_scoped = __esm(() => {
39709
39730
  });
39710
39731
  }
39711
39732
  const scopedTimeout = quality.execution?.regressionGate?.timeoutSeconds ?? 600;
39733
+ const cmdWorkdir = ctx.packageView.hasOverride ? input.workdir : ctx.packageView.repoRoot;
39712
39734
  logger.info("verify[scoped]", "Running scoped tests", {
39713
39735
  storyId: input.storyId,
39714
39736
  packageDir: input.packageDir,
39715
- cwd: input.workdir,
39737
+ cwd: cmdWorkdir,
39716
39738
  command: selection.effectiveCommand,
39717
39739
  timeoutSeconds: scopedTimeout,
39718
39740
  isFullSuite: selection.isFullSuite
39719
39741
  });
39720
39742
  const start = Date.now();
39721
39743
  const result = await deps.regression({
39722
- workdir: input.workdir,
39744
+ workdir: cmdWorkdir,
39723
39745
  command: selection.effectiveCommand,
39724
39746
  timeoutSeconds: quality.execution?.regressionGate?.timeoutSeconds ?? 600,
39725
39747
  forceExit: quality.quality?.forceExit,
@@ -44385,12 +44407,14 @@ var init_paths2 = __esm(() => {
44385
44407
  });
44386
44408
 
44387
44409
  // src/runtime/packages.ts
44388
- function createPackageView(config2, packageDir, repoRoot) {
44410
+ function createPackageView(config2, packageDir, repoRoot, hasOverride) {
44389
44411
  const memo = new Map;
44390
44412
  const relativeFromRoot = packageDir ? packageDir.startsWith(repoRoot) ? packageDir.slice(repoRoot.length).replace(/^\//, "") : packageDir : "";
44391
44413
  return {
44392
44414
  packageDir,
44393
44415
  relativeFromRoot,
44416
+ repoRoot,
44417
+ hasOverride,
44394
44418
  config: config2,
44395
44419
  select(selector) {
44396
44420
  if (memo.has(selector.name)) {
@@ -44421,8 +44445,10 @@ function createPackageRegistry(loader, repoRoot) {
44421
44445
  if (cached2 !== undefined) {
44422
44446
  return cached2;
44423
44447
  }
44424
- const config2 = mergedConfigs.get(key) ?? loader.current();
44425
- const view = createPackageView(config2, key, repoRoot);
44448
+ const overrideConfig = mergedConfigs.get(key);
44449
+ const hasOverride = overrideConfig !== undefined;
44450
+ const config2 = overrideConfig ?? loader.current();
44451
+ const view = createPackageView(config2, key, repoRoot, hasOverride);
44426
44452
  cache.set(key, view);
44427
44453
  return view;
44428
44454
  }
@@ -55125,7 +55151,10 @@ async function assemblePlanInputsFromCtx(ctx) {
55125
55151
  storyId: story.id,
55126
55152
  storyGitRef: ctx.storyGitRef,
55127
55153
  naxIgnoreIndex: ctx.naxIgnoreIndex,
55128
- regressionMode: toVerifyScopedMode(ctx.config.execution?.regressionGate?.mode)
55154
+ regressionMode: toVerifyScopedMode(ctx.config.execution?.regressionGate?.mode),
55155
+ repoRoot: ctx.projectDir,
55156
+ packagePrefix: packageDirRelative,
55157
+ resolvedTestPatterns
55129
55158
  } : undefined;
55130
55159
  const lintCheckInput = ctx.config.review?.enabled === true && ctx.config.review.checks?.includes("lint") && ctx.config.quality.commands.lint ? { workdir: ctx.workdir, storyId: story.id } : undefined;
55131
55160
  const typecheckCheckInput = ctx.config.review?.enabled === true && ctx.config.review.checks?.includes("typecheck") && ctx.config.quality.commands.typecheck ? { workdir: ctx.workdir, storyId: story.id } : undefined;
@@ -59543,7 +59572,7 @@ var package_default;
59543
59572
  var init_package = __esm(() => {
59544
59573
  package_default = {
59545
59574
  name: "@nathapp/nax",
59546
- version: "0.69.2",
59575
+ version: "0.69.4",
59547
59576
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
59548
59577
  type: "module",
59549
59578
  bin: {
@@ -59638,8 +59667,8 @@ var init_version = __esm(() => {
59638
59667
  NAX_VERSION = package_default.version;
59639
59668
  NAX_COMMIT = (() => {
59640
59669
  try {
59641
- if (/^[0-9a-f]{6,10}$/.test("99db370f"))
59642
- return "99db370f";
59670
+ if (/^[0-9a-f]{6,10}$/.test("fb1560dd"))
59671
+ return "fb1560dd";
59643
59672
  } catch {}
59644
59673
  try {
59645
59674
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.69.2",
3
+ "version": "0.69.4",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {