@nathapp/nax 0.69.6 → 0.69.8

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 (3) hide show
  1. package/README.md +12 -6
  2. package/dist/nax.js +436 -327
  3. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -18041,7 +18041,7 @@ function redactSecrets(input) {
18041
18041
  }
18042
18042
  var SECRET_KEY_PATTERN, SECRET_VALUE_PATTERNS, REDACTED = "[REDACTED]";
18043
18043
  var init_redact = __esm(() => {
18044
- SECRET_KEY_PATTERN = /(SECRET|TOKEN|API_?KEY|PASSWORD|PRIVATE_?KEY|ACCESS_?KEY|WEBHOOK)/i;
18044
+ SECRET_KEY_PATTERN = /(SECRET|TOKEN(?!s\b)|API_?KEY|PASSWORD|PRIVATE_?KEY|ACCESS_?KEY|WEBHOOK)/i;
18045
18045
  SECRET_VALUE_PATTERNS = [
18046
18046
  /sk-[A-Za-z0-9_-]{16,}/g,
18047
18047
  /ghp_[A-Za-z0-9]{16,}/g,
@@ -24993,12 +24993,15 @@ async function getGitRootMemo(workdir) {
24993
24993
  }
24994
24994
  return result ?? null;
24995
24995
  }
24996
- function extractPatternSuffix(pattern) {
24997
- const lastStar = pattern.lastIndexOf("*");
24998
- if (lastStar === -1)
24996
+ function extractBasenamePattern(pattern) {
24997
+ const basename4 = pattern.slice(pattern.lastIndexOf("/") + 1);
24998
+ const parts = basename4.split("*");
24999
+ if (parts.length !== 2)
24999
25000
  return null;
25000
- const suffix = pattern.slice(lastStar + 1);
25001
- return suffix.length > 0 ? suffix : null;
25001
+ const [prefix, suffix] = parts;
25002
+ if (!prefix && !suffix)
25003
+ return null;
25004
+ return { prefix, suffix };
25002
25005
  }
25003
25006
  function extractSearchTerms(sourceFile) {
25004
25007
  const withoutPrefix = sourceFile.replace(/^(?:.*\/)?src\//, "");
@@ -25036,28 +25039,11 @@ async function importGrepFallback(sourceFiles, workdir, testFilePatterns) {
25036
25039
  return results.filter((p) => p !== null);
25037
25040
  }
25038
25041
  async function mapSourceToTests(sourceFiles, workdir, packagePrefix, testFilePatterns = [...DEFAULT_TEST_FILE_PATTERNS]) {
25039
- const testSuffixes = [...new Set(testFilePatterns.map(extractPatternSuffix).filter((s) => s !== null))];
25042
+ const shapes = dedupeBasenamePatterns(testFilePatterns);
25043
+ const testDirs = [...new Set([...DEFAULT_SEPARATED_TEST_DIRS, ...extractTestDirs(testFilePatterns)])];
25040
25044
  const result = [];
25041
25045
  for (const sourceFile of sourceFiles) {
25042
- const sourceWithoutExt = sourceFile.replace(/\.[^.]+$/, "");
25043
- let innerRelative;
25044
- let testBase;
25045
- if (packagePrefix) {
25046
- const srcRoot = `${packagePrefix}/src/`;
25047
- const inner = sourceFile.startsWith(srcRoot) ? sourceFile.slice(srcRoot.length) : sourceFile.replace(/^.*\/src\//, "");
25048
- innerRelative = inner.replace(/\.[^.]+$/, "");
25049
- testBase = `${workdir}/${packagePrefix}`;
25050
- } else {
25051
- innerRelative = sourceFile.replace(/^src\//, "").replace(/\.[^.]+$/, "");
25052
- testBase = workdir;
25053
- }
25054
- const candidates = [];
25055
- for (const suffix of testSuffixes) {
25056
- for (const testDir of DEFAULT_SEPARATED_TEST_DIRS) {
25057
- candidates.push(`${testBase}/${testDir}/${innerRelative}${suffix}`);
25058
- }
25059
- candidates.push(`${workdir}/${sourceWithoutExt}${suffix}`);
25060
- }
25046
+ const candidates = buildTestCandidates(sourceFile, workdir, packagePrefix, shapes, testDirs);
25061
25047
  const existsFlags = await Promise.all(candidates.map((c) => _bunDeps.file(c).exists()));
25062
25048
  candidates.forEach((c, i) => {
25063
25049
  if (existsFlags[i])
@@ -25066,6 +25052,58 @@ async function mapSourceToTests(sourceFiles, workdir, packagePrefix, testFilePat
25066
25052
  }
25067
25053
  return result;
25068
25054
  }
25055
+ function dedupeBasenamePatterns(testFilePatterns) {
25056
+ const seen = new Set;
25057
+ const shapes = [];
25058
+ for (const pattern of testFilePatterns) {
25059
+ const shape = extractBasenamePattern(pattern);
25060
+ if (!shape)
25061
+ continue;
25062
+ const key = `${shape.prefix}\x00${shape.suffix}`;
25063
+ if (seen.has(key))
25064
+ continue;
25065
+ seen.add(key);
25066
+ shapes.push(shape);
25067
+ }
25068
+ return shapes;
25069
+ }
25070
+ function buildTestCandidates(sourceFile, workdir, packagePrefix, shapes, testDirs) {
25071
+ const sourceWithoutExt = sourceFile.replace(/\.[^.]+$/, "");
25072
+ let innerRelative;
25073
+ let testBase;
25074
+ if (packagePrefix) {
25075
+ const srcRoot = `${packagePrefix}/src/`;
25076
+ const inner = sourceFile.startsWith(srcRoot) ? sourceFile.slice(srcRoot.length) : sourceFile.replace(/^.*\/src\//, "");
25077
+ innerRelative = inner.replace(/\.[^.]+$/, "");
25078
+ testBase = `${workdir}/${packagePrefix}`;
25079
+ } else {
25080
+ innerRelative = sourceFile.replace(/^src\//, "").replace(/\.[^.]+$/, "");
25081
+ testBase = workdir;
25082
+ }
25083
+ const lastSlash = innerRelative.lastIndexOf("/");
25084
+ const innerDir = lastSlash === -1 ? "" : innerRelative.slice(0, lastSlash);
25085
+ const baseName = lastSlash === -1 ? innerRelative : innerRelative.slice(lastSlash + 1);
25086
+ const sourceDirAbs = sourceWithoutExt.includes("/") ? `${workdir}/${sourceWithoutExt.slice(0, sourceWithoutExt.lastIndexOf("/"))}` : workdir;
25087
+ const candidates = [];
25088
+ for (const { prefix, suffix } of shapes) {
25089
+ if (prefix === "") {
25090
+ for (const testDir of testDirs) {
25091
+ candidates.push(`${testBase}/${testDir}/${innerRelative}${suffix}`);
25092
+ }
25093
+ candidates.push(`${workdir}/${sourceWithoutExt}${suffix}`);
25094
+ } else {
25095
+ const named = `${prefix}${baseName}${suffix}`;
25096
+ for (const testDir of testDirs) {
25097
+ candidates.push(`${testBase}/${testDir}/${innerDir ? `${innerDir}/` : ""}${named}`);
25098
+ if (innerDir)
25099
+ candidates.push(`${testBase}/${testDir}/${named}`);
25100
+ }
25101
+ candidates.push(`${sourceDirAbs}/${named}`);
25102
+ }
25103
+ }
25104
+ const sourceAbs = `${workdir}/${sourceFile}`;
25105
+ return [...new Set(candidates)].filter((c) => c !== sourceAbs);
25106
+ }
25069
25107
  function buildSmartTestCommand(testFiles, baseCommand) {
25070
25108
  if (testFiles.length === 0) {
25071
25109
  return baseCommand;
@@ -37392,7 +37430,7 @@ var init_write_test = __esm(() => {
37392
37430
  if (!input.beforeRef)
37393
37431
  return parsed;
37394
37432
  const allowedPaths = ctx.config.tdd?.testWriterAllowedPaths ?? ["src/index.ts", "src/**/index.ts"];
37395
- const testFilePatterns = typeof ctx.packageView.config.execution?.smartTestRunner === "object" && ctx.packageView.config.execution.smartTestRunner !== null ? ctx.packageView.config.execution.smartTestRunner.testFilePatterns : undefined;
37433
+ const testFilePatterns = input.resolvedTestPatterns?.globs;
37396
37434
  const isolation = await verifyTestWriterIsolation(ctx.packageView.packageDir, input.beforeRef, allowedPaths, testFilePatterns, input.lite ? "lite" : "strict");
37397
37435
  return { ...parsed, isolation };
37398
37436
  }
@@ -38376,57 +38414,69 @@ var init_plan_critic_llm = __esm(() => {
38376
38414
  });
38377
38415
 
38378
38416
  // src/context/greenfield.ts
38379
- import { readdir as readdir2 } from "fs/promises";
38380
- import { join as join23 } from "path";
38381
- async function scanForTestFiles(dir, testPatterns, isRootCall = true) {
38382
- const results = [];
38383
- const ignoreDirs = new Set(["node_modules", "dist", "build", ".next", ".git"]);
38417
+ async function gitLsFiles2(workdir) {
38384
38418
  try {
38385
- const entries = await readdir2(dir, { withFileTypes: true });
38386
- for (const entry of entries) {
38387
- const fullPath = join23(dir, entry.name);
38388
- if (entry.isDirectory()) {
38389
- if (ignoreDirs.has(entry.name))
38390
- continue;
38391
- const subResults = await scanForTestFiles(fullPath, testPatterns, false);
38392
- results.push(...subResults);
38393
- } else if (entry.isFile()) {
38394
- if (testPatterns.some((re) => re.test(entry.name))) {
38395
- results.push(fullPath);
38396
- }
38419
+ const proc = _greenfieldDeps.spawn(["git", "ls-files"], {
38420
+ cwd: workdir,
38421
+ stdout: "pipe",
38422
+ stderr: "pipe"
38423
+ });
38424
+ const exitCode = await proc.exited;
38425
+ if (exitCode !== 0)
38426
+ return null;
38427
+ const output = await new Response(proc.stdout).text();
38428
+ return output.split(`
38429
+ `).filter(Boolean);
38430
+ } catch {
38431
+ return null;
38432
+ }
38433
+ }
38434
+ async function hasTestFiles(workdir, patterns) {
38435
+ const files = await gitLsFiles2(workdir);
38436
+ if (files !== null) {
38437
+ return files.some((f) => isTestFileByPatterns(f, patterns));
38438
+ }
38439
+ for (const pattern of patterns) {
38440
+ const g = new Bun.Glob(pattern);
38441
+ for await (const path5 of g.scan({ cwd: workdir, onlyFiles: true })) {
38442
+ if (!path5.split("/").some((seg) => IGNORE_DIRS.has(seg))) {
38443
+ return true;
38397
38444
  }
38398
38445
  }
38399
- } catch (error48) {
38400
- if (isRootCall) {
38401
- throw error48;
38402
- }
38403
38446
  }
38404
- return results;
38447
+ return false;
38405
38448
  }
38406
38449
  async function isGreenfieldStory(_story, workdir, patterns) {
38407
38450
  try {
38408
- const regexes = globsToTestRegex(patterns ?? GREENFIELD_FALLBACK_PATTERNS);
38409
- const testFiles = await scanForTestFiles(workdir, regexes);
38410
- return testFiles.length === 0;
38411
- } catch (error48) {
38451
+ return !await hasTestFiles(workdir, patterns ?? DEFAULT_TEST_FILE_PATTERNS);
38452
+ } catch {
38412
38453
  return false;
38413
38454
  }
38414
38455
  }
38415
- var GREENFIELD_FALLBACK_PATTERNS;
38456
+ var _greenfieldDeps, IGNORE_DIRS;
38416
38457
  var init_greenfield = __esm(() => {
38417
- init_conventions();
38418
- GREENFIELD_FALLBACK_PATTERNS = Object.freeze([
38419
- "**/*.test.ts",
38420
- "**/*.test.js",
38421
- "**/*.test.tsx",
38422
- "**/*.test.jsx",
38423
- "**/*.spec.ts",
38424
- "**/*.spec.js",
38425
- "**/*.spec.tsx",
38426
- "**/*.spec.jsx",
38427
- "**/*_test.go",
38428
- "test_*.py",
38429
- "*_test.py"
38458
+ init_test_runners();
38459
+ _greenfieldDeps = {
38460
+ spawn: Bun.spawn
38461
+ };
38462
+ IGNORE_DIRS = new Set([
38463
+ "node_modules",
38464
+ "dist",
38465
+ ".next",
38466
+ ".nuxt",
38467
+ ".cache",
38468
+ "coverage",
38469
+ "vendor",
38470
+ "__pycache__",
38471
+ ".venv",
38472
+ "venv",
38473
+ ".eggs",
38474
+ "target",
38475
+ ".gradle",
38476
+ "out",
38477
+ "tmp",
38478
+ "temp",
38479
+ ".git"
38430
38480
  ]);
38431
38481
  });
38432
38482
 
@@ -38589,13 +38639,13 @@ __export(exports_runners, {
38589
38639
  _regressionRunnerDeps: () => _regressionRunnerDeps
38590
38640
  });
38591
38641
  import { existsSync as existsSync6 } from "fs";
38592
- import { join as join24 } from "path";
38642
+ import { join as join23 } from "path";
38593
38643
  async function verifyAssets(workingDirectory, expectedFiles) {
38594
38644
  if (!expectedFiles || expectedFiles.length === 0)
38595
38645
  return { success: true, missingFiles: [] };
38596
38646
  const missingFiles = [];
38597
38647
  for (const file3 of expectedFiles) {
38598
- if (!existsSync6(join24(workingDirectory, file3)))
38648
+ if (!existsSync6(join23(workingDirectory, file3)))
38599
38649
  missingFiles.push(file3);
38600
38650
  }
38601
38651
  if (missingFiles.length > 0) {
@@ -39042,7 +39092,7 @@ var init_apply_test_edit_declarations = __esm(() => {
39042
39092
  });
39043
39093
 
39044
39094
  // src/operations/validate-mock-structure-files.ts
39045
- import { join as join25 } from "path";
39095
+ import { join as join24 } from "path";
39046
39096
  async function validateMockStructureFiles(declarations, resolvedTestPatterns, packageDir, deps) {
39047
39097
  const fileExists = deps?.fileExists ?? defaultFileExists;
39048
39098
  const valid = [];
@@ -39055,7 +39105,7 @@ async function validateMockStructureFiles(declarations, resolvedTestPatterns, pa
39055
39105
  const files = d.files ?? [d.file];
39056
39106
  let allValid = true;
39057
39107
  for (const file3 of files) {
39058
- const absolutePath = join25(packageDir, file3);
39108
+ const absolutePath = join24(packageDir, file3);
39059
39109
  const exists = await fileExists(absolutePath);
39060
39110
  if (!exists) {
39061
39111
  allValid = false;
@@ -39763,28 +39813,47 @@ var init_verify_scoped = __esm(() => {
39763
39813
  timeoutSeconds: scopedTimeout,
39764
39814
  isFullSuite: selection.isFullSuite
39765
39815
  });
39816
+ const runTests = async (command) => {
39817
+ const result2 = await deps.regression({
39818
+ workdir: cmdWorkdir,
39819
+ command,
39820
+ timeoutSeconds: scopedTimeout,
39821
+ forceExit: quality.quality?.forceExit,
39822
+ detectOpenHandles: quality.quality?.detectOpenHandles,
39823
+ detectOpenHandlesRetries: quality.quality?.detectOpenHandlesRetries,
39824
+ gracePeriodMs: quality.quality?.gracePeriodMs,
39825
+ drainTimeoutMs: quality.quality?.drainTimeoutMs,
39826
+ shell: quality.quality?.shell,
39827
+ stripEnvVars: quality.quality?.stripEnvVars
39828
+ });
39829
+ const parsed2 = result2.output ? deps.parseTestOutput(result2.output) : { passed: 0, failed: 0, failures: [] };
39830
+ return { result: result2, parsed: parsed2 };
39831
+ };
39766
39832
  const start = Date.now();
39767
- const result = await deps.regression({
39768
- workdir: cmdWorkdir,
39769
- command: selection.effectiveCommand,
39770
- timeoutSeconds: quality.execution?.regressionGate?.timeoutSeconds ?? 600,
39771
- forceExit: quality.quality?.forceExit,
39772
- detectOpenHandles: quality.quality?.detectOpenHandles,
39773
- detectOpenHandlesRetries: quality.quality?.detectOpenHandlesRetries,
39774
- gracePeriodMs: quality.quality?.gracePeriodMs,
39775
- drainTimeoutMs: quality.quality?.drainTimeoutMs,
39776
- shell: quality.quality?.shell,
39777
- stripEnvVars: quality.quality?.stripEnvVars
39778
- });
39833
+ let effectiveCommand = selection.effectiveCommand;
39834
+ let isFullSuite = selection.isFullSuite;
39835
+ let scopeTestFallback = selection.scopeTestFallback;
39836
+ let { result, parsed } = await runTests(effectiveCommand);
39837
+ const ranNoTests = parsed.passed === 0 && parsed.failed === 0 && parsed.failures.length === 0;
39838
+ if (!result.success && result.status !== "TIMEOUT" && !isFullSuite && ranNoTests) {
39839
+ logger.warn("verify[scoped]", "Scoped run executed no tests \u2014 falling back to full suite", {
39840
+ storyId: input.storyId,
39841
+ command: effectiveCommand,
39842
+ exitCode: result.exitCode
39843
+ });
39844
+ effectiveCommand = baseCommand;
39845
+ isFullSuite = true;
39846
+ scopeTestFallback = true;
39847
+ ({ result, parsed } = await runTests(effectiveCommand));
39848
+ }
39779
39849
  const durationMs = Date.now() - start;
39780
- const parsed = result.output ? deps.parseTestOutput(result.output) : { passed: 0, failed: 0, failures: [] };
39781
39850
  if (result.success) {
39782
39851
  logger.info("verify[scoped]", "Scoped tests passed", {
39783
39852
  storyId: input.storyId,
39784
39853
  passCount: parsed.passed,
39785
39854
  durationMs,
39786
- scopeTestFallback: selection.scopeTestFallback ?? false,
39787
- isFullSuite: selection.isFullSuite
39855
+ scopeTestFallback: scopeTestFallback ?? false,
39856
+ isFullSuite
39788
39857
  });
39789
39858
  return {
39790
39859
  success: true,
@@ -39792,16 +39861,16 @@ var init_verify_scoped = __esm(() => {
39792
39861
  findings: [],
39793
39862
  durationMs,
39794
39863
  passCount: parsed.passed,
39795
- isFullSuite: selection.isFullSuite,
39796
- scopeTestFallback: selection.scopeTestFallback
39864
+ isFullSuite,
39865
+ scopeTestFallback
39797
39866
  };
39798
39867
  }
39799
39868
  if (result.status === "TIMEOUT") {
39800
39869
  logger.warn("verify[scoped]", "Scoped tests timed out", {
39801
39870
  storyId: input.storyId,
39802
39871
  durationMs,
39803
- scopeTestFallback: selection.scopeTestFallback ?? false,
39804
- isFullSuite: selection.isFullSuite
39872
+ scopeTestFallback: scopeTestFallback ?? false,
39873
+ isFullSuite
39805
39874
  });
39806
39875
  return {
39807
39876
  success: false,
@@ -39809,8 +39878,8 @@ var init_verify_scoped = __esm(() => {
39809
39878
  findings: [],
39810
39879
  durationMs,
39811
39880
  passCount: parsed.passed,
39812
- isFullSuite: selection.isFullSuite,
39813
- scopeTestFallback: selection.scopeTestFallback
39881
+ isFullSuite,
39882
+ scopeTestFallback
39814
39883
  };
39815
39884
  }
39816
39885
  logger.warn("verify[scoped]", "Scoped tests failed", {
@@ -39818,17 +39887,35 @@ var init_verify_scoped = __esm(() => {
39818
39887
  passCount: parsed.passed,
39819
39888
  failCount: parsed.failed,
39820
39889
  durationMs,
39821
- scopeTestFallback: selection.scopeTestFallback ?? false,
39822
- isFullSuite: selection.isFullSuite
39890
+ scopeTestFallback: scopeTestFallback ?? false,
39891
+ isFullSuite
39823
39892
  });
39893
+ let findings = deps.testSummaryToFindings(parsed);
39894
+ if (findings.length === 0) {
39895
+ logger.warn("verify[scoped]", "Scoped verify execution-failed \u2014 emitting synth finding", {
39896
+ storyId: input.storyId,
39897
+ command: effectiveCommand,
39898
+ exitCode: result.exitCode,
39899
+ cwd: cmdWorkdir
39900
+ });
39901
+ findings = [
39902
+ executionFailureToFinding({
39903
+ command: result.command ?? effectiveCommand,
39904
+ exitCode: result.exitCode,
39905
+ output: result.output ?? "",
39906
+ packageDir: input.packagePrefix,
39907
+ cwd: cmdWorkdir
39908
+ })
39909
+ ];
39910
+ }
39824
39911
  return {
39825
39912
  success: false,
39826
39913
  status: "failed",
39827
- findings: deps.testSummaryToFindings(parsed),
39914
+ findings,
39828
39915
  durationMs,
39829
39916
  passCount: parsed.passed,
39830
- isFullSuite: selection.isFullSuite,
39831
- scopeTestFallback: selection.scopeTestFallback
39917
+ isFullSuite,
39918
+ scopeTestFallback
39832
39919
  };
39833
39920
  }
39834
39921
  };
@@ -40618,7 +40705,7 @@ var init_lint_parsing = __esm(() => {
40618
40705
  });
40619
40706
 
40620
40707
  // src/review/scoped-lint.ts
40621
- import { join as join26, relative as relative10 } from "path";
40708
+ import { join as join25, relative as relative10 } from "path";
40622
40709
  function shellQuotePath4(path5) {
40623
40710
  return `'${path5.replaceAll("'", "'\\''")}'`;
40624
40711
  }
@@ -40666,7 +40753,7 @@ function uniqueFiles(files) {
40666
40753
  async function filterFilesToScope(files, workdir, projectDir, activePackageDir) {
40667
40754
  const inScope = [];
40668
40755
  for (const relPath of files) {
40669
- const absPath = join26(workdir, relPath);
40756
+ const absPath = join25(workdir, relPath);
40670
40757
  const exists = await _scopedLintDeps.fileExists(absPath);
40671
40758
  if (!exists)
40672
40759
  continue;
@@ -44040,7 +44127,7 @@ var init_call = __esm(() => {
44040
44127
 
44041
44128
  // src/runtime/cost-aggregator.ts
44042
44129
  import { mkdirSync as mkdirSync2 } from "fs";
44043
- import { join as join27 } from "path";
44130
+ import { join as join26 } from "path";
44044
44131
  function makeCorrelationId() {
44045
44132
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
44046
44133
  }
@@ -44231,7 +44318,7 @@ class CostAggregator {
44231
44318
  if (events.length === 0 && errors3.length === 0)
44232
44319
  return;
44233
44320
  mkdirSync2(this._drainDir, { recursive: true });
44234
- const path5 = join27(this._drainDir, `${this._runId}.jsonl`);
44321
+ const path5 = join26(this._drainDir, `${this._runId}.jsonl`);
44235
44322
  const sorted = [...events, ...errors3].sort((a, b) => a.ts - b.ts);
44236
44323
  await _costAggDeps.write(path5, `${sorted.map((e) => JSON.stringify(e)).join(`
44237
44324
  `)}
@@ -44271,7 +44358,7 @@ var init_cost_aggregator = __esm(() => {
44271
44358
  // src/runtime/prompt-auditor.ts
44272
44359
  import { appendFileSync } from "fs";
44273
44360
  import { mkdir as mkdir4 } from "fs/promises";
44274
- import { join as join28 } from "path";
44361
+ import { join as join27 } from "path";
44275
44362
  function createNoOpPromptAuditor() {
44276
44363
  return {
44277
44364
  record() {},
@@ -44337,8 +44424,8 @@ class PromptAuditor {
44337
44424
  _jsonlPath;
44338
44425
  _featureDir;
44339
44426
  constructor(runId, flushDir, featureName) {
44340
- this._featureDir = join28(flushDir, featureName);
44341
- this._jsonlPath = join28(this._featureDir, `${runId}.jsonl`);
44427
+ this._featureDir = join27(flushDir, featureName);
44428
+ this._jsonlPath = join27(this._featureDir, `${runId}.jsonl`);
44342
44429
  }
44343
44430
  record(entry) {
44344
44431
  this._enqueue(entry);
@@ -44387,7 +44474,7 @@ class PromptAuditor {
44387
44474
  const auditEntry = entry;
44388
44475
  const filename = deriveTxtFilename(auditEntry);
44389
44476
  try {
44390
- await _promptAuditorDeps.write(join28(this._featureDir, filename), buildTxtContent(auditEntry));
44477
+ await _promptAuditorDeps.write(join27(this._featureDir, filename), buildTxtContent(auditEntry));
44391
44478
  } catch (err) {
44392
44479
  throw tagAuditError(err, "txt");
44393
44480
  }
@@ -44525,6 +44612,7 @@ function createPackageView(config2, packageDir, repoRoot, hasOverride) {
44525
44612
  function createPackageRegistry(loader, repoRoot) {
44526
44613
  const cache = new Map;
44527
44614
  const mergedConfigs = new Map;
44615
+ let hydrated = false;
44528
44616
  function toRelativeKey(packageDir) {
44529
44617
  if (!packageDir)
44530
44618
  return "";
@@ -44543,6 +44631,9 @@ function createPackageRegistry(loader, repoRoot) {
44543
44631
  }
44544
44632
  const overrideConfig = mergedConfigs.get(key);
44545
44633
  const hasOverride = overrideConfig !== undefined;
44634
+ if (!hasOverride && key && !hydrated) {
44635
+ _packagesDeps.getSafeLogger()?.warn("packages", "resolve() called for non-root package before hydrate(); returning root config (per-package overrides not applied)", { packageDir: key });
44636
+ }
44546
44637
  const config2 = overrideConfig ?? loader.current();
44547
44638
  const view = createPackageView(config2, key, repoRoot, hasOverride);
44548
44639
  cache.set(key, view);
@@ -44563,6 +44654,7 @@ function createPackageRegistry(loader, repoRoot) {
44563
44654
  cache.delete(dir);
44564
44655
  }
44565
44656
  }
44657
+ hydrated = true;
44566
44658
  }
44567
44659
  return {
44568
44660
  all() {
@@ -44575,8 +44667,11 @@ function createPackageRegistry(loader, repoRoot) {
44575
44667
  hydrate
44576
44668
  };
44577
44669
  }
44670
+ var _packagesDeps;
44578
44671
  var init_packages = __esm(() => {
44579
44672
  init_config();
44673
+ init_logger2();
44674
+ _packagesDeps = { getSafeLogger };
44580
44675
  });
44581
44676
 
44582
44677
  // src/runtime/agent-stream-events.ts
@@ -45535,7 +45630,7 @@ var init_pid_registry = __esm(() => {
45535
45630
  // src/session/manager-deps.ts
45536
45631
  import { randomUUID as randomUUID3 } from "crypto";
45537
45632
  import { mkdir as mkdir5 } from "fs/promises";
45538
- import { isAbsolute as isAbsolute9, join as join29, relative as relative11, sep as sep2 } from "path";
45633
+ import { isAbsolute as isAbsolute9, join as join28, relative as relative11, sep as sep2 } from "path";
45539
45634
  function resolveProjectDirFromScratchDir(scratchDir) {
45540
45635
  const marker = `${sep2}.nax${sep2}features${sep2}`;
45541
45636
  const markerIdx = scratchDir.lastIndexOf(marker);
@@ -45556,7 +45651,7 @@ var init_manager_deps = __esm(() => {
45556
45651
  now: () => new Date().toISOString(),
45557
45652
  nowMs: () => Date.now(),
45558
45653
  uuid: () => randomUUID3(),
45559
- sessionScratchDir: (projectDir, featureName, sessionId) => join29(projectDir, ".nax", "features", featureName, "sessions", sessionId),
45654
+ sessionScratchDir: (projectDir, featureName, sessionId) => join28(projectDir, ".nax", "features", featureName, "sessions", sessionId),
45560
45655
  writeDescriptor: async (scratchDir, descriptor, projectDir) => {
45561
45656
  await mkdir5(scratchDir, { recursive: true });
45562
45657
  const { handle: _handle, ...persistable } = descriptor;
@@ -45567,7 +45662,7 @@ var init_manager_deps = __esm(() => {
45567
45662
  persistable.scratchDir = toProjectRelativePath(derivedProjectDir, persistable.scratchDir);
45568
45663
  }
45569
45664
  }
45570
- await Bun.write(join29(scratchDir, "descriptor.json"), JSON.stringify(persistable, null, 2));
45665
+ await Bun.write(join28(scratchDir, "descriptor.json"), JSON.stringify(persistable, null, 2));
45571
45666
  }
45572
45667
  };
45573
45668
  });
@@ -46318,7 +46413,7 @@ __export(exports_runtime, {
46318
46413
  CostAggregator: () => CostAggregator,
46319
46414
  AgentStreamEventBus: () => AgentStreamEventBus
46320
46415
  });
46321
- import { basename as basename5, join as join30 } from "path";
46416
+ import { basename as basename5, join as join29 } from "path";
46322
46417
  function createRuntime(config2, workdir, opts) {
46323
46418
  const runId = crypto.randomUUID();
46324
46419
  const controller = new AbortController;
@@ -46334,10 +46429,10 @@ function createRuntime(config2, workdir, opts) {
46334
46429
  const outputDir = projectOutputDir(projectKey, config2.outputDir);
46335
46430
  const globalDir = globalOutputDir();
46336
46431
  const curatorRollupPathValue = curatorRollupPath(globalDir, config2.curator?.rollupPath);
46337
- const costDir = join30(outputDir, "cost");
46432
+ const costDir = join29(outputDir, "cost");
46338
46433
  const costAggregator = opts?.costAggregator ?? new CostAggregator(runId, costDir);
46339
46434
  const auditEnabled = config2.agent?.promptAudit?.enabled ?? false;
46340
- const auditDir = config2.agent?.promptAudit?.dir ?? join30(outputDir, "prompt-audit");
46435
+ const auditDir = config2.agent?.promptAudit?.dir ?? join29(outputDir, "prompt-audit");
46341
46436
  let promptAuditor;
46342
46437
  if (opts?.promptAuditor) {
46343
46438
  promptAuditor = opts.promptAuditor;
@@ -46490,9 +46585,9 @@ async function allSettledBounded(tasks, limit) {
46490
46585
 
46491
46586
  // src/context/injector.ts
46492
46587
  import { existsSync as existsSync8 } from "fs";
46493
- import { join as join31 } from "path";
46588
+ import { join as join30 } from "path";
46494
46589
  async function detectNode(workdir) {
46495
- const pkgPath = join31(workdir, "package.json");
46590
+ const pkgPath = join30(workdir, "package.json");
46496
46591
  if (!existsSync8(pkgPath))
46497
46592
  return null;
46498
46593
  try {
@@ -46509,7 +46604,7 @@ async function detectNode(workdir) {
46509
46604
  }
46510
46605
  }
46511
46606
  async function detectGo(workdir) {
46512
- const goMod = join31(workdir, "go.mod");
46607
+ const goMod = join30(workdir, "go.mod");
46513
46608
  if (!existsSync8(goMod))
46514
46609
  return null;
46515
46610
  try {
@@ -46533,7 +46628,7 @@ async function detectGo(workdir) {
46533
46628
  }
46534
46629
  }
46535
46630
  async function detectRust(workdir) {
46536
- const cargoPath = join31(workdir, "Cargo.toml");
46631
+ const cargoPath = join30(workdir, "Cargo.toml");
46537
46632
  if (!existsSync8(cargoPath))
46538
46633
  return null;
46539
46634
  try {
@@ -46549,8 +46644,8 @@ async function detectRust(workdir) {
46549
46644
  }
46550
46645
  }
46551
46646
  async function detectPython(workdir) {
46552
- const pyproject = join31(workdir, "pyproject.toml");
46553
- const requirements = join31(workdir, "requirements.txt");
46647
+ const pyproject = join30(workdir, "pyproject.toml");
46648
+ const requirements = join30(workdir, "requirements.txt");
46554
46649
  if (!existsSync8(pyproject) && !existsSync8(requirements))
46555
46650
  return null;
46556
46651
  try {
@@ -46569,7 +46664,7 @@ async function detectPython(workdir) {
46569
46664
  }
46570
46665
  }
46571
46666
  async function detectPhp(workdir) {
46572
- const composerPath = join31(workdir, "composer.json");
46667
+ const composerPath = join30(workdir, "composer.json");
46573
46668
  if (!existsSync8(composerPath))
46574
46669
  return null;
46575
46670
  try {
@@ -46582,7 +46677,7 @@ async function detectPhp(workdir) {
46582
46677
  }
46583
46678
  }
46584
46679
  async function detectRuby(workdir) {
46585
- const gemfile = join31(workdir, "Gemfile");
46680
+ const gemfile = join30(workdir, "Gemfile");
46586
46681
  if (!existsSync8(gemfile))
46587
46682
  return null;
46588
46683
  try {
@@ -46594,9 +46689,9 @@ async function detectRuby(workdir) {
46594
46689
  }
46595
46690
  }
46596
46691
  async function detectJvm(workdir) {
46597
- const pom = join31(workdir, "pom.xml");
46598
- const gradle = join31(workdir, "build.gradle");
46599
- const gradleKts = join31(workdir, "build.gradle.kts");
46692
+ const pom = join30(workdir, "pom.xml");
46693
+ const gradle = join30(workdir, "build.gradle");
46694
+ const gradleKts = join30(workdir, "build.gradle.kts");
46600
46695
  if (!existsSync8(pom) && !existsSync8(gradle) && !existsSync8(gradleKts))
46601
46696
  return null;
46602
46697
  try {
@@ -46604,7 +46699,7 @@ async function detectJvm(workdir) {
46604
46699
  const content2 = await Bun.file(pom).text();
46605
46700
  const nameMatch = content2.match(/<artifactId>([^<]+)<\/artifactId>/);
46606
46701
  const deps2 = [...content2.matchAll(/<artifactId>([^<]+)<\/artifactId>/g)].map((m) => m[1]).filter((d) => d !== nameMatch?.[1]).slice(0, 10);
46607
- const lang2 = existsSync8(join31(workdir, "src/main/kotlin")) ? "Kotlin" : "Java";
46702
+ const lang2 = existsSync8(join30(workdir, "src/main/kotlin")) ? "Kotlin" : "Java";
46608
46703
  return { name: nameMatch?.[1], lang: lang2, dependencies: deps2 };
46609
46704
  }
46610
46705
  const gradleFile = existsSync8(gradleKts) ? gradleKts : gradle;
@@ -46858,7 +46953,7 @@ var init_windsurf = __esm(() => {
46858
46953
 
46859
46954
  // src/context/generator.ts
46860
46955
  import { existsSync as existsSync9 } from "fs";
46861
- import { join as join32, relative as relative12 } from "path";
46956
+ import { join as join31, relative as relative12 } from "path";
46862
46957
  async function loadContextContent(options, config2) {
46863
46958
  if (!_generatorDeps.existsSync(options.contextPath)) {
46864
46959
  throw new Error(`Context file not found: ${options.contextPath}`);
@@ -46876,7 +46971,7 @@ async function generateFor(agent, options, config2) {
46876
46971
  try {
46877
46972
  const context = await loadContextContent(options, config2);
46878
46973
  const content = generator.generate(context);
46879
- const outputPath = join32(options.outputDir, generator.outputFile);
46974
+ const outputPath = join31(options.outputDir, generator.outputFile);
46880
46975
  validateFilePath(outputPath, options.outputDir);
46881
46976
  if (!options.dryRun) {
46882
46977
  await _generatorDeps.writeFile(outputPath, content);
@@ -46894,7 +46989,7 @@ async function generateAll(options, config2, agentFilter) {
46894
46989
  for (const [agentKey, generator] of entries) {
46895
46990
  try {
46896
46991
  const content = generator.generate(context);
46897
- const outputPath = join32(options.outputDir, generator.outputFile);
46992
+ const outputPath = join31(options.outputDir, generator.outputFile);
46898
46993
  validateFilePath(outputPath, options.outputDir);
46899
46994
  if (!options.dryRun) {
46900
46995
  await _generatorDeps.writeFile(outputPath, content);
@@ -46914,7 +47009,7 @@ async function discoverPackages(repoRoot) {
46914
47009
  const glob = new Bun.Glob(pattern);
46915
47010
  for await (const match of glob.scan({ cwd: repoRoot, dot: true })) {
46916
47011
  const pkgRelative = match.replace(/^\.nax\/mono\//, "").replace(/\/context\.md$/, "");
46917
- const pkgAbsolute = join32(repoRoot, pkgRelative);
47012
+ const pkgAbsolute = join31(repoRoot, pkgRelative);
46918
47013
  if (!seen.has(pkgAbsolute)) {
46919
47014
  seen.add(pkgAbsolute);
46920
47015
  packages.push(pkgAbsolute);
@@ -46946,14 +47041,14 @@ async function discoverWorkspacePackages2(repoRoot) {
46946
47041
  }
46947
47042
  }
46948
47043
  }
46949
- const turboPath = join32(repoRoot, "turbo.json");
47044
+ const turboPath = join31(repoRoot, "turbo.json");
46950
47045
  try {
46951
47046
  const turbo = JSON.parse(await _generatorDeps.readTextFile(turboPath));
46952
47047
  if (Array.isArray(turbo.packages)) {
46953
47048
  await resolveGlobs(turbo.packages);
46954
47049
  }
46955
47050
  } catch {}
46956
- const pkgPath = join32(repoRoot, "package.json");
47051
+ const pkgPath = join31(repoRoot, "package.json");
46957
47052
  try {
46958
47053
  const pkg = JSON.parse(await _generatorDeps.readTextFile(pkgPath));
46959
47054
  const ws = pkg.workspaces;
@@ -46961,7 +47056,7 @@ async function discoverWorkspacePackages2(repoRoot) {
46961
47056
  if (patterns.length > 0)
46962
47057
  await resolveGlobs(patterns);
46963
47058
  } catch {}
46964
- const pnpmPath = join32(repoRoot, "pnpm-workspace.yaml");
47059
+ const pnpmPath = join31(repoRoot, "pnpm-workspace.yaml");
46965
47060
  try {
46966
47061
  const raw = await _generatorDeps.readTextFile(pnpmPath);
46967
47062
  const lines = raw.split(`
@@ -46987,7 +47082,7 @@ async function discoverWorkspacePackages2(repoRoot) {
46987
47082
  async function generateForPackage(packageDir, config2, dryRun = false, repoRoot) {
46988
47083
  const resolvedRepoRoot = repoRoot ?? packageDir;
46989
47084
  const relativePkgPath = relative12(resolvedRepoRoot, packageDir);
46990
- const contextPath = join32(resolvedRepoRoot, ".nax", "mono", relativePkgPath, "context.md");
47085
+ const contextPath = join31(resolvedRepoRoot, ".nax", "mono", relativePkgPath, "context.md");
46991
47086
  if (!_generatorDeps.existsSync(contextPath)) {
46992
47087
  return [
46993
47088
  {
@@ -47055,7 +47150,7 @@ var init_generator2 = __esm(() => {
47055
47150
  });
47056
47151
 
47057
47152
  // src/analyze/scanner.ts
47058
- import { join as join33 } from "path";
47153
+ import { join as join32 } from "path";
47059
47154
  function resolveFrameworkAndRunner(language, pkg) {
47060
47155
  if (language === "go")
47061
47156
  return { framework: "", testRunner: "go-test" };
@@ -47077,7 +47172,7 @@ async function scanSourceRoots(workdir) {
47077
47172
  });
47078
47173
  try {
47079
47174
  const language = await deps.detectLanguage(workdir);
47080
- const pkg = await deps.readPackageJson(join33(workdir, "package.json"));
47175
+ const pkg = await deps.readPackageJson(join32(workdir, "package.json"));
47081
47176
  const { framework, testRunner } = resolveFrameworkAndRunner(language, pkg);
47082
47177
  return [{ path: ".", language, framework, testRunner }];
47083
47178
  } catch {
@@ -47095,9 +47190,9 @@ async function scanSourceRoots(workdir) {
47095
47190
  packages = packages.slice(0, MAX_SOURCE_ROOTS);
47096
47191
  }
47097
47192
  return Promise.all(packages.map(async (pkgPath) => {
47098
- const pkgDir = pkgPath === "." ? workdir : join33(workdir, pkgPath);
47193
+ const pkgDir = pkgPath === "." ? workdir : join32(workdir, pkgPath);
47099
47194
  const language = await deps.detectLanguage(pkgDir);
47100
- const pkg = await deps.readPackageJson(join33(pkgDir, "package.json"));
47195
+ const pkg = await deps.readPackageJson(join32(pkgDir, "package.json"));
47101
47196
  const { framework, testRunner } = resolveFrameworkAndRunner(language, pkg);
47102
47197
  return { path: pkgPath, language, framework, testRunner };
47103
47198
  }));
@@ -47130,7 +47225,7 @@ var init_analyze = __esm(() => {
47130
47225
  });
47131
47226
 
47132
47227
  // src/debate/pre-phase/grounder.ts
47133
- import { join as join34 } from "path";
47228
+ import { join as join33 } from "path";
47134
47229
  async function buildCodebaseContext(workdir) {
47135
47230
  const roots = await _grounderDeps.scanSourceRoots(workdir);
47136
47231
  return buildSourceRootsSection(normalizeRoots(workdir, roots));
@@ -47142,7 +47237,7 @@ function normalizeRoots(workdir, roots) {
47142
47237
  }));
47143
47238
  }
47144
47239
  async function writeManifestArtifact(ctx, manifest) {
47145
- const manifestPath = join34(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "facts-manifest.json");
47240
+ const manifestPath = join33(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "facts-manifest.json");
47146
47241
  await _grounderDeps.write(manifestPath, JSON.stringify(manifest, null, 2));
47147
47242
  }
47148
47243
  var _grounderDeps, grounderStrategy = async (ctx) => {
@@ -47485,7 +47580,7 @@ function formatSpecDeltas(blockers, manifest) {
47485
47580
 
47486
47581
  // src/debate/verifiers/checks.ts
47487
47582
  import { existsSync as defaultExistsSync } from "fs";
47488
- import { join as join35 } from "path";
47583
+ import { join as join34 } from "path";
47489
47584
  function checkFilesExist(prd, workdir, deps) {
47490
47585
  const existsSync10 = deps?.existsSync ?? defaultExistsSync;
47491
47586
  const findings = [];
@@ -47495,7 +47590,7 @@ function checkFilesExist(prd, workdir, deps) {
47495
47590
  for (const entry of story.contextFiles) {
47496
47591
  const filePath = typeof entry === "string" ? entry : entry.path;
47497
47592
  const factId = typeof entry === "string" ? undefined : entry.factId;
47498
- const absPath = join35(workdir, filePath);
47593
+ const absPath = join34(workdir, filePath);
47499
47594
  if (existsSync10(absPath))
47500
47595
  continue;
47501
47596
  if (factId) {
@@ -47606,7 +47701,7 @@ var init_checks3 = () => {};
47606
47701
 
47607
47702
  // src/debate/verifiers/plan-checklist.ts
47608
47703
  import { existsSync as existsSync10 } from "fs";
47609
- import { join as join36 } from "path";
47704
+ import { join as join35 } from "path";
47610
47705
  function parsePrd(output) {
47611
47706
  if (!output)
47612
47707
  return null;
@@ -47617,7 +47712,7 @@ function parsePrd(output) {
47617
47712
  }
47618
47713
  }
47619
47714
  async function loadManifest(ctx) {
47620
- const manifestPath = join36(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "facts-manifest.json");
47715
+ const manifestPath = join35(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "facts-manifest.json");
47621
47716
  const raw = await _planChecklistDeps.readFile(manifestPath);
47622
47717
  if (!raw)
47623
47718
  return null;
@@ -47630,7 +47725,7 @@ async function loadManifest(ctx) {
47630
47725
  }
47631
47726
  }
47632
47727
  async function emitSpecDeltas(ctx, blockers, manifest) {
47633
- const artifactPath = join36(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "spec-deltas.md");
47728
+ const artifactPath = join35(ctx.workdir, ".nax", "runs", ctx.ctx.runtime.runId, "plan", ctx.storyId, "spec-deltas.md");
47634
47729
  const content = formatSpecDeltas(blockers, manifest ?? { repoFacts: [], specClaims: [], gaps: [] });
47635
47730
  await _planChecklistDeps.write(artifactPath, content);
47636
47731
  return artifactPath;
@@ -47976,7 +48071,7 @@ var init_runner_plan_helpers = __esm(() => {
47976
48071
  });
47977
48072
 
47978
48073
  // src/debate/runner-plan.ts
47979
- import { join as join37 } from "path";
48074
+ import { join as join36 } from "path";
47980
48075
  async function runPlan(ctx, taskContext, outputFormat, opts) {
47981
48076
  const logger = _debateSessionDeps.getSafeLogger();
47982
48077
  const config2 = ctx.stageConfig;
@@ -48035,7 +48130,7 @@ async function runPlan(ctx, taskContext, outputFormat, opts) {
48035
48130
  sessionMode: ctx.stageConfig.sessionMode ?? "one-shot",
48036
48131
  proposers: ctx.stageConfig.proposers
48037
48132
  });
48038
- const outputPaths = resolved.map((_, i) => join37(opts.outputDir, `prd-debate-${i}.json`));
48133
+ const outputPaths = resolved.map((_, i) => join36(opts.outputDir, `prd-debate-${i}.json`));
48039
48134
  const successful = [];
48040
48135
  let rebuttalList;
48041
48136
  if (selectorKind === "verifier-pick") {
@@ -50278,9 +50373,9 @@ function validateFeatureName(feature) {
50278
50373
 
50279
50374
  // src/plan/critic.ts
50280
50375
  import { mkdir as mkdir6 } from "fs/promises";
50281
- import { dirname as dirname7, join as join40 } from "path";
50376
+ import { dirname as dirname7, join as join39 } from "path";
50282
50377
  async function writeSpecDeltas(findings, workdir, runId, storyId, manifest) {
50283
- const path7 = join40(workdir, ".nax", "runs", runId, "plan", storyId, "spec-deltas.md");
50378
+ const path7 = join39(workdir, ".nax", "runs", runId, "plan", storyId, "spec-deltas.md");
50284
50379
  await mkdir6(dirname7(path7), { recursive: true });
50285
50380
  await Bun.write(path7, formatSpecDeltas(findings, manifest));
50286
50381
  return path7;
@@ -51493,9 +51588,9 @@ __export(exports_plan_decompose, {
51493
51588
  runReplanLoop: () => runReplanLoop,
51494
51589
  planDecomposeCommand: () => planDecomposeCommand
51495
51590
  });
51496
- import { join as join41 } from "path";
51591
+ import { join as join40 } from "path";
51497
51592
  async function planDecomposeCommand(workdir, config2, options) {
51498
- const prdPath = join41(workdir, ".nax", "features", options.feature, "prd.json");
51593
+ const prdPath = join40(workdir, ".nax", "features", options.feature, "prd.json");
51499
51594
  if (!_planDeps.existsSync(prdPath)) {
51500
51595
  throw new NaxError(`PRD not found: ${prdPath}`, "PRD_NOT_FOUND", {
51501
51596
  stage: "decompose",
@@ -51669,7 +51764,7 @@ var init_plan_decompose = __esm(() => {
51669
51764
 
51670
51765
  // src/cli/plan-runtime.ts
51671
51766
  import { existsSync as existsSync15 } from "fs";
51672
- import { join as join42 } from "path";
51767
+ import { join as join41 } from "path";
51673
51768
  function isRuntimeWithAgentManager(value) {
51674
51769
  return typeof value === "object" && value !== null && "agentManager" in value;
51675
51770
  }
@@ -51721,7 +51816,7 @@ var init_plan_runtime = __esm(() => {
51721
51816
  writeFile: (path7, content) => Bun.write(path7, content).then(() => {}),
51722
51817
  scanSourceRoots: (workdir) => scanSourceRoots(workdir),
51723
51818
  createRuntime: (cfg, wd, featureName) => createRuntime(cfg, wd, { featureName }),
51724
- readPackageJson: (workdir) => Bun.file(join42(workdir, "package.json")).json().catch(() => null),
51819
+ readPackageJson: (workdir) => Bun.file(join41(workdir, "package.json")).json().catch(() => null),
51725
51820
  spawnSync: (cmd, opts) => {
51726
51821
  const result = Bun.spawnSync(cmd, opts ? { cwd: opts.cwd } : {});
51727
51822
  return { stdout: result.stdout, exitCode: result.exitCode };
@@ -52106,7 +52201,7 @@ var init_metrics = __esm(() => {
52106
52201
 
52107
52202
  // src/commands/common.ts
52108
52203
  import { existsSync as existsSync16, readdirSync as readdirSync2, realpathSync as realpathSync3 } from "fs";
52109
- import { join as join43, resolve as resolve13 } from "path";
52204
+ import { join as join42, resolve as resolve13 } from "path";
52110
52205
  function resolveProject(options = {}) {
52111
52206
  const { dir, feature } = options;
52112
52207
  let projectRoot;
@@ -52114,12 +52209,12 @@ function resolveProject(options = {}) {
52114
52209
  let configPath;
52115
52210
  if (dir) {
52116
52211
  projectRoot = realpathSync3(resolve13(dir));
52117
- naxDir = join43(projectRoot, ".nax");
52212
+ naxDir = join42(projectRoot, ".nax");
52118
52213
  if (!existsSync16(naxDir)) {
52119
52214
  throw new NaxError(`Directory does not contain a nax project: ${projectRoot}
52120
52215
  Expected to find: ${naxDir}`, "NAX_DIR_NOT_FOUND", { projectRoot, naxDir });
52121
52216
  }
52122
- configPath = join43(naxDir, "config.json");
52217
+ configPath = join42(naxDir, "config.json");
52123
52218
  if (!existsSync16(configPath)) {
52124
52219
  throw new NaxError(`.nax directory found but config.json is missing: ${naxDir}
52125
52220
  Expected to find: ${configPath}`, "CONFIG_NOT_FOUND", { naxDir, configPath });
@@ -52127,17 +52222,17 @@ Expected to find: ${configPath}`, "CONFIG_NOT_FOUND", { naxDir, configPath });
52127
52222
  } else {
52128
52223
  const found = findProjectRoot(process.cwd());
52129
52224
  if (!found) {
52130
- const cwdNaxDir = join43(process.cwd(), ".nax");
52225
+ const cwdNaxDir = join42(process.cwd(), ".nax");
52131
52226
  if (existsSync16(cwdNaxDir)) {
52132
- const cwdConfigPath = join43(cwdNaxDir, "config.json");
52227
+ const cwdConfigPath = join42(cwdNaxDir, "config.json");
52133
52228
  throw new NaxError(`.nax directory found but config.json is missing: ${cwdNaxDir}
52134
52229
  Expected to find: ${cwdConfigPath}`, "CONFIG_NOT_FOUND", { naxDir: cwdNaxDir, configPath: cwdConfigPath });
52135
52230
  }
52136
52231
  throw new NaxError("No nax project found. Run this command from within a nax project directory, or use -d flag to specify the project path.", "PROJECT_NOT_FOUND", { cwd: process.cwd() });
52137
52232
  }
52138
52233
  projectRoot = found;
52139
- naxDir = join43(projectRoot, ".nax");
52140
- configPath = join43(naxDir, "config.json");
52234
+ naxDir = join42(projectRoot, ".nax");
52235
+ configPath = join42(naxDir, "config.json");
52141
52236
  }
52142
52237
  let featureDir;
52143
52238
  if (feature) {
@@ -52146,8 +52241,8 @@ Expected to find: ${cwdConfigPath}`, "CONFIG_NOT_FOUND", { naxDir: cwdNaxDir, co
52146
52241
  } catch (error48) {
52147
52242
  throw new NaxError(error48.message, "FEATURE_INVALID", { feature });
52148
52243
  }
52149
- const featuresDir = join43(naxDir, "features");
52150
- featureDir = join43(featuresDir, feature);
52244
+ const featuresDir = join42(naxDir, "features");
52245
+ featureDir = join42(featuresDir, feature);
52151
52246
  if (!existsSync16(featureDir)) {
52152
52247
  const availableFeatures = existsSync16(featuresDir) ? readdirSync2(featuresDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name) : [];
52153
52248
  const availableMsg = availableFeatures.length > 0 ? `
@@ -52180,7 +52275,7 @@ async function resolveProjectAsync(options = {}) {
52180
52275
  }
52181
52276
  const isPlainName = !dir.includes("/") && !dir.includes("\\");
52182
52277
  if (isPlainName) {
52183
- const registryIdentityPath = join43(globalConfigDir(), dir, ".identity");
52278
+ const registryIdentityPath = join42(globalConfigDir(), dir, ".identity");
52184
52279
  const identityFile = Bun.file(registryIdentityPath);
52185
52280
  if (await identityFile.exists()) {
52186
52281
  try {
@@ -52212,12 +52307,12 @@ function findProjectRoot(startDir) {
52212
52307
  let current = resolve13(startDir);
52213
52308
  let depth = 0;
52214
52309
  while (depth < MAX_DIRECTORY_DEPTH) {
52215
- const naxDir = join43(current, ".nax");
52216
- const configPath = join43(naxDir, "config.json");
52310
+ const naxDir = join42(current, ".nax");
52311
+ const configPath = join42(naxDir, "config.json");
52217
52312
  if (existsSync16(configPath)) {
52218
52313
  return realpathSync3(current);
52219
52314
  }
52220
- const parent = join43(current, "..");
52315
+ const parent = join42(current, "..");
52221
52316
  if (parent === current) {
52222
52317
  break;
52223
52318
  }
@@ -52544,8 +52639,8 @@ var init_semantic_verdict = __esm(() => {
52544
52639
  await Bun.write(filePath, content);
52545
52640
  },
52546
52641
  readdir: async (dir) => {
52547
- const { readdir: readdir3 } = await import("fs/promises");
52548
- return readdir3(dir);
52642
+ const { readdir: readdir2 } = await import("fs/promises");
52643
+ return readdir2(dir);
52549
52644
  },
52550
52645
  readFile: async (filePath) => {
52551
52646
  return Bun.file(filePath).text();
@@ -52996,10 +53091,10 @@ var init_acceptance_setup = __esm(() => {
52996
53091
  },
52997
53092
  deleteSemanticVerdicts: async (featureDir) => {
52998
53093
  const dir = `${featureDir}/semantic-verdicts`;
52999
- const { readdir: readdir3, unlink: unlink2 } = await import("fs/promises");
53094
+ const { readdir: readdir2, unlink: unlink2 } = await import("fs/promises");
53000
53095
  let files;
53001
53096
  try {
53002
- files = await readdir3(dir);
53097
+ files = await readdir2(dir);
53003
53098
  } catch (err) {
53004
53099
  if (err.code === "ENOENT")
53005
53100
  return;
@@ -53376,10 +53471,10 @@ var init_effectiveness = __esm(() => {
53376
53471
 
53377
53472
  // src/execution/progress.ts
53378
53473
  import { appendFile as appendFile2, mkdir as mkdir7 } from "fs/promises";
53379
- import { join as join46 } from "path";
53474
+ import { join as join45 } from "path";
53380
53475
  async function appendProgress(featureDir, storyId, status, message) {
53381
53476
  await mkdir7(featureDir, { recursive: true });
53382
- const progressPath = join46(featureDir, "progress.txt");
53477
+ const progressPath = join45(featureDir, "progress.txt");
53383
53478
  const timestamp = new Date().toISOString();
53384
53479
  const entry = `[${timestamp}] ${storyId} \u2014 ${status.toUpperCase()} \u2014 ${message}
53385
53480
  `;
@@ -53573,7 +53668,7 @@ var init_completion = __esm(() => {
53573
53668
 
53574
53669
  // src/constitution/loader.ts
53575
53670
  import { existsSync as existsSync19 } from "fs";
53576
- import { join as join47 } from "path";
53671
+ import { join as join46 } from "path";
53577
53672
  function truncateToTokens(text, maxTokens) {
53578
53673
  const maxChars = maxTokens * 3;
53579
53674
  if (text.length <= maxChars) {
@@ -53595,7 +53690,7 @@ async function loadConstitution(projectDir, config2) {
53595
53690
  }
53596
53691
  let combinedContent = "";
53597
53692
  if (!config2.skipGlobal) {
53598
- const globalPath = join47(globalConfigDir(), config2.path);
53693
+ const globalPath = join46(globalConfigDir(), config2.path);
53599
53694
  if (existsSync19(globalPath)) {
53600
53695
  const validatedPath = validateFilePath(globalPath, globalConfigDir());
53601
53696
  const globalFile = Bun.file(validatedPath);
@@ -53605,7 +53700,7 @@ async function loadConstitution(projectDir, config2) {
53605
53700
  }
53606
53701
  }
53607
53702
  }
53608
- const projectPath = join47(projectDir, config2.path);
53703
+ const projectPath = join46(projectDir, config2.path);
53609
53704
  if (existsSync19(projectPath)) {
53610
53705
  const validatedPath = validateFilePath(projectPath, projectDir);
53611
53706
  const projectFile = Bun.file(validatedPath);
@@ -55039,7 +55134,7 @@ var init_story_orchestrator = __esm(() => {
55039
55134
  });
55040
55135
 
55041
55136
  // src/execution/build-plan-for-strategy.ts
55042
- import { join as join48 } from "path";
55137
+ import { join as join47 } from "path";
55043
55138
  function requiresInitialRefCapture(strategy) {
55044
55139
  return isThreeSessionStrategy(strategy);
55045
55140
  }
@@ -55085,7 +55180,7 @@ async function buildPlanForStrategy(ctx, story, config2, testStrategy, inputs) {
55085
55180
  }
55086
55181
  if (shouldRunRectification(config2) && inputs.rectification) {
55087
55182
  const sink = makeDeclarationSink();
55088
- const packageDir = join48(ctx.packageDir, story.workdir ?? "");
55183
+ const packageDir = join47(ctx.packageDir, story.workdir ?? "");
55089
55184
  const resolvedTestPatterns = await resolveTestFilePatterns(config2, ctx.packageDir, story.workdir);
55090
55185
  const strategies = [];
55091
55186
  const pkgQuality = ctx.packageView.select(qualityConfigSelector).quality;
@@ -55155,8 +55250,27 @@ var init_build_plan_for_strategy = __esm(() => {
55155
55250
  init_story_orchestrator();
55156
55251
  });
55157
55252
 
55253
+ // src/utils/paths.ts
55254
+ import { join as join48, relative as relative13, sep as sep4 } from "path";
55255
+ function packageDirRelative(projectDir, workdir) {
55256
+ if (!projectDir || !workdir || workdir === projectDir)
55257
+ return;
55258
+ const rel = relative13(projectDir, workdir);
55259
+ if (rel === ".." || rel.startsWith(`..${sep4}`))
55260
+ return;
55261
+ return rel && rel !== "." ? rel : undefined;
55262
+ }
55263
+ function getRunsDir() {
55264
+ return process.env.NAX_RUNS_DIR ?? join48(globalConfigDir(), "runs");
55265
+ }
55266
+ function getEventsRootDir() {
55267
+ return join48(globalConfigDir(), "events");
55268
+ }
55269
+ var init_paths3 = __esm(() => {
55270
+ init_paths();
55271
+ });
55272
+
55158
55273
  // src/execution/plan-inputs.ts
55159
- import { relative as relative13, sep as sep4 } from "path";
55160
55274
  function validatePlanInputs(story, config2) {
55161
55275
  if (!story.id || story.id.trim() === "") {
55162
55276
  throw new NaxError("Story ID is required and must be non-empty", "STORY_ID_INVALID", {
@@ -55232,15 +55346,8 @@ async function assemblePlanInputsFromCtx(ctx) {
55232
55346
  if (!_isTdd && !ctx.prompt?.trim()) {
55233
55347
  throw new NaxError(`Prompt missing for strategy "${ctx.routing.testStrategy}" \u2014 non-TDD strategies require ctx.prompt`, "PROMPT_NOT_BUILT", { stage: "plan-inputs", storyId: story.id, testStrategy: ctx.routing.testStrategy });
55234
55348
  }
55235
- const packageDirRelative = (() => {
55236
- if (ctx.workdir === ctx.projectDir)
55237
- return;
55238
- const rel = relative13(ctx.projectDir, ctx.workdir);
55239
- if (rel === ".." || rel.startsWith(`..${sep4}`))
55240
- return;
55241
- return rel && rel !== "." ? rel : undefined;
55242
- })();
55243
- const resolvedTestPatterns = await resolveTestFilePatterns(config2, ctx.projectDir, packageDirRelative);
55349
+ const packageDirRel = packageDirRelative(ctx.projectDir, ctx.workdir);
55350
+ const resolvedTestPatterns = await resolveTestFilePatterns(config2, ctx.projectDir, packageDirRel);
55244
55351
  const [testWriterPrompt, implementerPrompt, verifierPrompt] = _isTdd ? await Promise.all([
55245
55352
  _isFreshRun ? buildThreeSessionPrompt("test-writer", ctx, isLite) : Promise.resolve(""),
55246
55353
  buildThreeSessionPrompt("implementer", ctx, isLite),
@@ -55251,7 +55358,8 @@ async function assemblePlanInputsFromCtx(ctx) {
55251
55358
  promptMarkdown: testWriterPrompt,
55252
55359
  featureContextMarkdown: ctx.featureContextMarkdown,
55253
55360
  constitution: ctx.constitution?.content,
55254
- lite: isLite
55361
+ lite: isLite,
55362
+ resolvedTestPatterns
55255
55363
  } : undefined;
55256
55364
  const greenfieldGateInput = _isTdd && _isFreshRun && resolvedTestPatterns ? { story, workdir: ctx.workdir, resolvedTestPatterns } : undefined;
55257
55365
  const implementerInput = {
@@ -55276,7 +55384,7 @@ async function assemblePlanInputsFromCtx(ctx) {
55276
55384
  naxIgnoreIndex: ctx.naxIgnoreIndex,
55277
55385
  regressionMode: toVerifyScopedMode(ctx.config.execution?.regressionGate?.mode),
55278
55386
  repoRoot: ctx.projectDir,
55279
- packagePrefix: packageDirRelative,
55387
+ packagePrefix: packageDirRel,
55280
55388
  resolvedTestPatterns
55281
55389
  } : undefined;
55282
55390
  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;
@@ -55381,6 +55489,7 @@ var init_plan_inputs = __esm(() => {
55381
55489
  init_prompts();
55382
55490
  init_review();
55383
55491
  init_resolver();
55492
+ init_paths3();
55384
55493
  });
55385
55494
 
55386
55495
  // src/pipeline/stages/execution-helpers.ts
@@ -56446,6 +56555,8 @@ var init_queue_check = __esm(() => {
56446
56555
  // src/pipeline/stages/routing.ts
56447
56556
  var routingStage, _routingDeps;
56448
56557
  var init_routing2 = __esm(() => {
56558
+ init_test_runners();
56559
+ init_paths3();
56449
56560
  init_greenfield();
56450
56561
  init_logger2();
56451
56562
  init_prd();
@@ -56489,7 +56600,16 @@ var init_routing2 = __esm(() => {
56489
56600
  const greenfieldDetectionEnabled = ctx.config.tdd.greenfieldDetection ?? true;
56490
56601
  if (greenfieldDetectionEnabled && routing.testStrategy.startsWith("three-session-tdd")) {
56491
56602
  const greenfieldScanDir = ctx.workdir;
56492
- const isGreenfield = await _routingDeps.isGreenfieldStory(ctx.story, greenfieldScanDir);
56603
+ const root = ctx.projectDir ?? ctx.workdir;
56604
+ const packageDir = packageDirRelative(root, ctx.workdir);
56605
+ const resolved = await _routingDeps.resolveTestFilePatterns(ctx.config, root, packageDir, { storyId: ctx.story.id }).catch((err) => {
56606
+ logger.debug("routing", "Test-pattern resolution failed; using default greenfield patterns", {
56607
+ storyId: ctx.story.id,
56608
+ error: errorMessage(err)
56609
+ });
56610
+ return;
56611
+ });
56612
+ const isGreenfield = await _routingDeps.isGreenfieldStory(ctx.story, greenfieldScanDir, resolved?.globs);
56493
56613
  if (isGreenfield) {
56494
56614
  logger.info("routing", "Greenfield detected \u2014 forcing test-after strategy", {
56495
56615
  storyId: ctx.story.id,
@@ -56517,6 +56637,7 @@ var init_routing2 = __esm(() => {
56517
56637
  resolveRouting,
56518
56638
  complexityToModelTier,
56519
56639
  isGreenfieldStory,
56640
+ resolveTestFilePatterns,
56520
56641
  clearCache,
56521
56642
  savePRD
56522
56643
  };
@@ -59433,18 +59554,6 @@ var init_loader4 = __esm(() => {
59433
59554
  FALLBACK_TEST_FILE_RE = /\.(test|spec)\.(ts|js|tsx|jsx|mjs)$/;
59434
59555
  });
59435
59556
 
59436
- // src/utils/paths.ts
59437
- import { join as join68 } from "path";
59438
- function getRunsDir() {
59439
- return process.env.NAX_RUNS_DIR ?? join68(globalConfigDir(), "runs");
59440
- }
59441
- function getEventsRootDir() {
59442
- return join68(globalConfigDir(), "events");
59443
- }
59444
- var init_paths3 = __esm(() => {
59445
- init_paths();
59446
- });
59447
-
59448
59557
  // src/utils/command-argv.ts
59449
59558
  function parseCommandToArgv(command) {
59450
59559
  const safeEnv = buildAllowedEnv();
@@ -59499,7 +59608,7 @@ var init_command_argv = __esm(() => {
59499
59608
  });
59500
59609
 
59501
59610
  // src/hooks/runner.ts
59502
- import { join as join75 } from "path";
59611
+ import { join as join74 } from "path";
59503
59612
  function createDrainDeadline2(deadlineMs) {
59504
59613
  let timeoutId;
59505
59614
  const promise2 = new Promise((resolve16) => {
@@ -59518,14 +59627,14 @@ async function loadHooksConfig(projectDir, globalDir) {
59518
59627
  let globalHooks = { hooks: {} };
59519
59628
  let projectHooks = { hooks: {} };
59520
59629
  let skipGlobal = false;
59521
- const projectPath = join75(projectDir, "hooks.json");
59630
+ const projectPath = join74(projectDir, "hooks.json");
59522
59631
  const projectData = await loadJsonFile(projectPath, "hooks");
59523
59632
  if (projectData) {
59524
59633
  projectHooks = projectData;
59525
59634
  skipGlobal = projectData.skipGlobal ?? false;
59526
59635
  }
59527
59636
  if (!skipGlobal && globalDir) {
59528
- const globalPath = join75(globalDir, "hooks.json");
59637
+ const globalPath = join74(globalDir, "hooks.json");
59529
59638
  const globalData = await loadJsonFile(globalPath, "hooks");
59530
59639
  if (globalData) {
59531
59640
  globalHooks = globalData;
@@ -59695,7 +59804,7 @@ var package_default;
59695
59804
  var init_package = __esm(() => {
59696
59805
  package_default = {
59697
59806
  name: "@nathapp/nax",
59698
- version: "0.69.6",
59807
+ version: "0.69.8",
59699
59808
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
59700
59809
  type: "module",
59701
59810
  bin: {
@@ -59790,8 +59899,8 @@ var init_version = __esm(() => {
59790
59899
  NAX_VERSION = package_default.version;
59791
59900
  NAX_COMMIT = (() => {
59792
59901
  try {
59793
- if (/^[0-9a-f]{6,10}$/.test("97a1e367"))
59794
- return "97a1e367";
59902
+ if (/^[0-9a-f]{6,10}$/.test("0b7fc5bf"))
59903
+ return "0b7fc5bf";
59795
59904
  } catch {}
59796
59905
  try {
59797
59906
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -60668,15 +60777,15 @@ var init_acceptance_loop = __esm(() => {
60668
60777
 
60669
60778
  // src/session/scratch-purge.ts
60670
60779
  import { mkdir as mkdir12, rename, rm } from "fs/promises";
60671
- import { dirname as dirname12, join as join76 } from "path";
60780
+ import { dirname as dirname12, join as join75 } from "path";
60672
60781
  async function purgeStaleScratch(projectDir, featureName, retentionDays, archiveInsteadOfDelete = false) {
60673
- const sessionsDir = join76(projectDir, ".nax", "features", featureName, "sessions");
60782
+ const sessionsDir = join75(projectDir, ".nax", "features", featureName, "sessions");
60674
60783
  const sessionIds = await _scratchPurgeDeps.listSessionDirs(sessionsDir);
60675
60784
  const cutoffMs = _scratchPurgeDeps.now() - retentionDays * 86400000;
60676
60785
  let purged = 0;
60677
60786
  for (const sessionId of sessionIds) {
60678
- const sessionDir = join76(sessionsDir, sessionId);
60679
- const descriptorPath = join76(sessionDir, "descriptor.json");
60787
+ const sessionDir = join75(sessionsDir, sessionId);
60788
+ const descriptorPath = join75(sessionDir, "descriptor.json");
60680
60789
  if (!await _scratchPurgeDeps.fileExists(descriptorPath))
60681
60790
  continue;
60682
60791
  let lastActivityAt;
@@ -60692,7 +60801,7 @@ async function purgeStaleScratch(projectDir, featureName, retentionDays, archive
60692
60801
  if (new Date(lastActivityAt).getTime() >= cutoffMs)
60693
60802
  continue;
60694
60803
  if (archiveInsteadOfDelete) {
60695
- const archiveDest = join76(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
60804
+ const archiveDest = join75(projectDir, ".nax", "features", featureName, "_archive", "sessions", sessionId);
60696
60805
  await _scratchPurgeDeps.move(sessionDir, archiveDest);
60697
60806
  } else {
60698
60807
  await _scratchPurgeDeps.remove(sessionDir);
@@ -61430,12 +61539,12 @@ var DEFAULT_MAX_BATCH_SIZE = 4;
61430
61539
 
61431
61540
  // src/pipeline/subscribers/events-writer.ts
61432
61541
  import { appendFile as appendFile4, mkdir as mkdir13 } from "fs/promises";
61433
- import { basename as basename13, join as join77 } from "path";
61542
+ import { basename as basename13, join as join76 } from "path";
61434
61543
  function wireEventsWriter(bus, feature, runId, workdir) {
61435
61544
  const logger = getSafeLogger();
61436
61545
  const project = basename13(workdir);
61437
- const eventsDir = join77(getEventsRootDir(), project);
61438
- const eventsFile = join77(eventsDir, "events.jsonl");
61546
+ const eventsDir = join76(getEventsRootDir(), project);
61547
+ const eventsFile = join76(eventsDir, "events.jsonl");
61439
61548
  let dirReady = false;
61440
61549
  const write = (line) => {
61441
61550
  return (async () => {
@@ -61616,12 +61725,12 @@ var init_interaction2 = __esm(() => {
61616
61725
 
61617
61726
  // src/pipeline/subscribers/registry.ts
61618
61727
  import { mkdir as mkdir14, writeFile as writeFile2 } from "fs/promises";
61619
- import { basename as basename14, join as join78 } from "path";
61728
+ import { basename as basename14, join as join77 } from "path";
61620
61729
  function wireRegistry(bus, feature, runId, workdir, outputDir) {
61621
61730
  const logger = getSafeLogger();
61622
61731
  const project = basename14(workdir);
61623
- const runDir = join78(getRunsDir(), `${project}-${feature}-${runId}`);
61624
- const metaFile = join78(runDir, "meta.json");
61732
+ const runDir = join77(getRunsDir(), `${project}-${feature}-${runId}`);
61733
+ const metaFile = join77(runDir, "meta.json");
61625
61734
  const unsub = bus.on("run:started", (_ev) => {
61626
61735
  return (async () => {
61627
61736
  try {
@@ -61631,8 +61740,8 @@ function wireRegistry(bus, feature, runId, workdir, outputDir) {
61631
61740
  project,
61632
61741
  feature,
61633
61742
  workdir,
61634
- statusPath: join78(outputDir, "features", feature, "status.json"),
61635
- eventsDir: join78(outputDir, "features", feature, "runs"),
61743
+ statusPath: join77(outputDir, "features", feature, "status.json"),
61744
+ eventsDir: join77(outputDir, "features", feature, "runs"),
61636
61745
  registeredAt: new Date().toISOString()
61637
61746
  };
61638
61747
  await writeFile2(metaFile, JSON.stringify(meta3, null, 2));
@@ -61878,7 +61987,7 @@ var init_types9 = __esm(() => {
61878
61987
 
61879
61988
  // src/worktree/dependencies.ts
61880
61989
  import { existsSync as existsSync30 } from "fs";
61881
- import { join as join79 } from "path";
61990
+ import { join as join78 } from "path";
61882
61991
  async function prepareWorktreeDependencies(options) {
61883
61992
  const mode = options.config.execution.worktreeDependencies.mode;
61884
61993
  const resolvedCwd = resolveDependencyCwd(options);
@@ -61892,7 +62001,7 @@ async function prepareWorktreeDependencies(options) {
61892
62001
  }
61893
62002
  }
61894
62003
  function resolveDependencyCwd(options) {
61895
- return options.storyWorkdir ? join79(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
62004
+ return options.storyWorkdir ? join78(options.worktreeRoot, options.storyWorkdir) : options.worktreeRoot;
61896
62005
  }
61897
62006
  function resolveInheritedDependencies(options, resolvedCwd) {
61898
62007
  if (hasDependencyManifests(options.worktreeRoot, resolvedCwd)) {
@@ -61902,7 +62011,7 @@ function resolveInheritedDependencies(options, resolvedCwd) {
61902
62011
  }
61903
62012
  function hasDependencyManifests(worktreeRoot, resolvedCwd) {
61904
62013
  const directories = resolvedCwd === worktreeRoot ? [worktreeRoot] : [worktreeRoot, resolvedCwd];
61905
- return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(join79(directory, filename))));
62014
+ return directories.some((directory) => PHASE_ONE_INHERIT_UNSUPPORTED_FILES.some((filename) => _worktreeDependencyDeps.existsSync(join78(directory, filename))));
61906
62015
  }
61907
62016
  async function provisionDependencies(config2, worktreeRoot, resolvedCwd) {
61908
62017
  const setupCommand2 = config2.execution.worktreeDependencies.setupCommand;
@@ -61966,13 +62075,13 @@ __export(exports_manager, {
61966
62075
  });
61967
62076
  import { existsSync as existsSync31, symlinkSync } from "fs";
61968
62077
  import { mkdir as mkdir15 } from "fs/promises";
61969
- import { join as join80 } from "path";
62078
+ import { join as join79 } from "path";
61970
62079
 
61971
62080
  class WorktreeManager {
61972
62081
  async ensureGitExcludes(projectRoot) {
61973
62082
  const logger = getSafeLogger();
61974
- const infoDir = join80(projectRoot, ".git", "info");
61975
- const excludePath = join80(infoDir, "exclude");
62083
+ const infoDir = join79(projectRoot, ".git", "info");
62084
+ const excludePath = join79(infoDir, "exclude");
61976
62085
  try {
61977
62086
  await mkdir15(infoDir, { recursive: true });
61978
62087
  let existing = "";
@@ -61999,7 +62108,7 @@ ${missing.join(`
61999
62108
  }
62000
62109
  async create(projectRoot, storyId) {
62001
62110
  validateStoryId(storyId);
62002
- const worktreePath = join80(projectRoot, ".nax-wt", storyId);
62111
+ const worktreePath = join79(projectRoot, ".nax-wt", storyId);
62003
62112
  const branchName = `nax/${storyId}`;
62004
62113
  try {
62005
62114
  const pruneProc = _managerDeps.spawn(["git", "worktree", "prune"], {
@@ -62040,9 +62149,9 @@ ${missing.join(`
62040
62149
  }
62041
62150
  throw new Error(`Failed to create worktree: ${String(error48)}`);
62042
62151
  }
62043
- const envSource = join80(projectRoot, ".env");
62152
+ const envSource = join79(projectRoot, ".env");
62044
62153
  if (existsSync31(envSource)) {
62045
- const envTarget = join80(worktreePath, ".env");
62154
+ const envTarget = join79(worktreePath, ".env");
62046
62155
  try {
62047
62156
  symlinkSync(envSource, envTarget, "file");
62048
62157
  } catch (error48) {
@@ -62053,7 +62162,7 @@ ${missing.join(`
62053
62162
  }
62054
62163
  async remove(projectRoot, storyId) {
62055
62164
  validateStoryId(storyId);
62056
- const worktreePath = join80(projectRoot, ".nax-wt", storyId);
62165
+ const worktreePath = join79(projectRoot, ".nax-wt", storyId);
62057
62166
  const branchName = `nax/${storyId}`;
62058
62167
  try {
62059
62168
  const proc = _managerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
@@ -62865,10 +62974,10 @@ var init_merge_conflict_rectify = __esm(() => {
62865
62974
  });
62866
62975
 
62867
62976
  // src/execution/pipeline-result-handler.ts
62868
- import { join as join81 } from "path";
62977
+ import { join as join80 } from "path";
62869
62978
  async function removeWorktreeDirectory(projectRoot, storyId) {
62870
62979
  const logger = getSafeLogger();
62871
- const worktreePath = join81(projectRoot, ".nax-wt", storyId);
62980
+ const worktreePath = join80(projectRoot, ".nax-wt", storyId);
62872
62981
  try {
62873
62982
  const proc = _resultHandlerDeps.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
62874
62983
  cwd: projectRoot,
@@ -63085,7 +63194,7 @@ var init_pipeline_result_handler = __esm(() => {
63085
63194
 
63086
63195
  // src/execution/iteration-runner.ts
63087
63196
  import { existsSync as existsSync32 } from "fs";
63088
- import { join as join82 } from "path";
63197
+ import { join as join81 } from "path";
63089
63198
  async function runIteration(ctx, prd, selection, iterations, totalCost, allStoryMetrics) {
63090
63199
  const { story, storiesToExecute, routing, isBatchExecution } = selection;
63091
63200
  if (ctx.dryRun) {
@@ -63110,7 +63219,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
63110
63219
  const storyStartTime = Date.now();
63111
63220
  let effectiveWorkdir = ctx.workdir;
63112
63221
  if (ctx.config.execution.storyIsolation === "worktree") {
63113
- const worktreePath = join82(ctx.workdir, ".nax-wt", story.id);
63222
+ const worktreePath = join81(ctx.workdir, ".nax-wt", story.id);
63114
63223
  const worktreeExists = _iterationRunnerDeps.existsSync(worktreePath);
63115
63224
  if (!worktreeExists) {
63116
63225
  await _iterationRunnerDeps.worktreeManager.ensureGitExcludes(ctx.workdir);
@@ -63130,7 +63239,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
63130
63239
  }
63131
63240
  const accumulatedAttemptCost = (story.priorFailures || []).reduce((sum, f) => sum + (f.cost || 0), 0);
63132
63241
  const profileOverride = ctx.config.profile && ctx.config.profile !== "default" ? { profile: ctx.config.profile } : undefined;
63133
- const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(join82(ctx.workdir, ".nax", "config.json"), story.workdir, profileOverride) : ctx.config;
63242
+ const effectiveConfig = story.workdir ? await _iterationRunnerDeps.loadConfigForWorkdir(join81(ctx.workdir, ".nax", "config.json"), story.workdir, profileOverride) : ctx.config;
63134
63243
  let dependencyContext;
63135
63244
  if (ctx.config.execution.storyIsolation === "worktree") {
63136
63245
  try {
@@ -63157,7 +63266,7 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
63157
63266
  };
63158
63267
  }
63159
63268
  }
63160
- const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ? join82(effectiveWorkdir, story.workdir) : effectiveWorkdir : story.workdir ? join82(ctx.workdir, story.workdir) : ctx.workdir;
63269
+ const resolvedWorkdir = dependencyContext?.cwd ? dependencyContext.cwd : ctx.config.execution.storyIsolation === "worktree" ? story.workdir ? join81(effectiveWorkdir, story.workdir) : effectiveWorkdir : story.workdir ? join81(ctx.workdir, story.workdir) : ctx.workdir;
63161
63270
  const pipelineContext = {
63162
63271
  config: effectiveConfig,
63163
63272
  rootConfig: ctx.config,
@@ -63359,7 +63468,7 @@ __export(exports_parallel_worker, {
63359
63468
  buildWorktreePipelineContext: () => buildWorktreePipelineContext,
63360
63469
  _parallelWorkerDeps: () => _parallelWorkerDeps
63361
63470
  });
63362
- import { join as join83 } from "path";
63471
+ import { join as join82 } from "path";
63363
63472
  function buildWorktreePipelineContext(base, _story) {
63364
63473
  return { ...base, prd: structuredClone(base.prd) };
63365
63474
  }
@@ -63382,7 +63491,7 @@ async function executeStoryInWorktree(story, worktreePath, dependencyContext, co
63382
63491
  story,
63383
63492
  stories: [story],
63384
63493
  projectDir: context.projectDir,
63385
- workdir: dependencyContext.cwd ?? (story.workdir ? join83(worktreePath, story.workdir) : worktreePath),
63494
+ workdir: dependencyContext.cwd ?? (story.workdir ? join82(worktreePath, story.workdir) : worktreePath),
63386
63495
  worktreeDependencyContext: dependencyContext,
63387
63496
  routing,
63388
63497
  storyGitRef: storyGitRef ?? undefined
@@ -64269,7 +64378,7 @@ async function writeStatusFile(filePath, status) {
64269
64378
  var init_status_file = () => {};
64270
64379
 
64271
64380
  // src/execution/status-writer.ts
64272
- import { join as join84 } from "path";
64381
+ import { join as join83 } from "path";
64273
64382
 
64274
64383
  class StatusWriter {
64275
64384
  statusFile;
@@ -64388,7 +64497,7 @@ class StatusWriter {
64388
64497
  if (!this._prd)
64389
64498
  return;
64390
64499
  const safeLogger = getSafeLogger();
64391
- const featureStatusPath = join84(featureDir, "status.json");
64500
+ const featureStatusPath = join83(featureDir, "status.json");
64392
64501
  const write = async () => {
64393
64502
  try {
64394
64503
  const base = this.getSnapshot(totalCost, iterations);
@@ -64420,7 +64529,7 @@ __export(exports_migrate, {
64420
64529
  detectGeneratedContent: () => detectGeneratedContent
64421
64530
  });
64422
64531
  import { existsSync as existsSync33 } from "fs";
64423
- import { mkdir as mkdir16, readdir as readdir6, rename as rename3 } from "fs/promises";
64532
+ import { mkdir as mkdir16, readdir as readdir5, rename as rename3 } from "fs/promises";
64424
64533
  import path22 from "path";
64425
64534
  async function detectGeneratedContent(naxDir) {
64426
64535
  if (!existsSync33(naxDir))
@@ -64428,7 +64537,7 @@ async function detectGeneratedContent(naxDir) {
64428
64537
  const candidates = [];
64429
64538
  let entries = [];
64430
64539
  try {
64431
- entries = await readdir6(naxDir);
64540
+ entries = await readdir5(naxDir);
64432
64541
  } catch {
64433
64542
  return [];
64434
64543
  }
@@ -64441,13 +64550,13 @@ async function detectGeneratedContent(naxDir) {
64441
64550
  if (existsSync33(featuresDir)) {
64442
64551
  let featureDirs = [];
64443
64552
  try {
64444
- featureDirs = await readdir6(featuresDir);
64553
+ featureDirs = await readdir5(featuresDir);
64445
64554
  } catch {}
64446
64555
  for (const fid of featureDirs) {
64447
64556
  const featureDir = path22.join(featuresDir, fid);
64448
64557
  let subEntries = [];
64449
64558
  try {
64450
- subEntries = await readdir6(featureDir);
64559
+ subEntries = await readdir5(featureDir);
64451
64560
  } catch {
64452
64561
  continue;
64453
64562
  }
@@ -64462,7 +64571,7 @@ async function detectGeneratedContent(naxDir) {
64462
64571
  const storiesDir = path22.join(featureDir, "stories");
64463
64572
  let storyDirs = [];
64464
64573
  try {
64465
- storyDirs = await readdir6(storiesDir);
64574
+ storyDirs = await readdir5(storiesDir);
64466
64575
  } catch {
64467
64576
  continue;
64468
64577
  }
@@ -64470,7 +64579,7 @@ async function detectGeneratedContent(naxDir) {
64470
64579
  const storyDir = path22.join(storiesDir, sid);
64471
64580
  let storyEntries = [];
64472
64581
  try {
64473
- storyEntries = await readdir6(storyDir);
64582
+ storyEntries = await readdir5(storyDir);
64474
64583
  } catch {
64475
64584
  continue;
64476
64585
  }
@@ -64822,7 +64931,7 @@ __export(exports_run_initialization, {
64822
64931
  initializeRun: () => initializeRun,
64823
64932
  _reconcileDeps: () => _reconcileDeps
64824
64933
  });
64825
- import { join as join85 } from "path";
64934
+ import { join as join84 } from "path";
64826
64935
  async function reconcileState(prd, prdPath, workdir, config2) {
64827
64936
  const logger = getSafeLogger();
64828
64937
  let reconciledCount = 0;
@@ -64839,7 +64948,7 @@ async function reconcileState(prd, prdPath, workdir, config2) {
64839
64948
  });
64840
64949
  continue;
64841
64950
  }
64842
- const effectiveWorkdir = story.workdir ? join85(workdir, story.workdir) : workdir;
64951
+ const effectiveWorkdir = story.workdir ? join84(workdir, story.workdir) : workdir;
64843
64952
  try {
64844
64953
  const reviewResult = await _reconcileDeps.runReview(config2.review, effectiveWorkdir, config2.execution);
64845
64954
  if (!reviewResult.success) {
@@ -94643,7 +94752,7 @@ __export(exports_curator, {
94643
94752
  });
94644
94753
  import { readdirSync as readdirSync8 } from "fs";
94645
94754
  import { unlink as unlink4 } from "fs/promises";
94646
- import { basename as basename15, join as join87 } from "path";
94755
+ import { basename as basename15, join as join86 } from "path";
94647
94756
  function getProjectKey(config2, projectDir) {
94648
94757
  return config2.name?.trim() || basename15(projectDir);
94649
94758
  }
@@ -94726,7 +94835,7 @@ async function curatorStatus(options) {
94726
94835
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
94727
94836
  const projectKey = getProjectKey(config2, resolved.projectDir);
94728
94837
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
94729
- const runsDir = join87(outputDir, "runs");
94838
+ const runsDir = join86(outputDir, "runs");
94730
94839
  const runIds = listRunIds(runsDir);
94731
94840
  let runId;
94732
94841
  if (options.run) {
@@ -94743,8 +94852,8 @@ async function curatorStatus(options) {
94743
94852
  runId = runIds[runIds.length - 1];
94744
94853
  }
94745
94854
  console.log(`Run: ${runId}`);
94746
- const runDir = join87(runsDir, runId);
94747
- const observationsPath = join87(runDir, "observations.jsonl");
94855
+ const runDir = join86(runsDir, runId);
94856
+ const observationsPath = join86(runDir, "observations.jsonl");
94748
94857
  const observations = await parseObservations(observationsPath);
94749
94858
  const counts = new Map;
94750
94859
  for (const obs of observations) {
@@ -94754,7 +94863,7 @@ async function curatorStatus(options) {
94754
94863
  for (const [kind, count] of counts.entries()) {
94755
94864
  console.log(` ${kind}: ${count}`);
94756
94865
  }
94757
- const proposalsPath = join87(runDir, "curator-proposals.md");
94866
+ const proposalsPath = join86(runDir, "curator-proposals.md");
94758
94867
  const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
94759
94868
  if (proposalText !== null) {
94760
94869
  console.log("");
@@ -94768,8 +94877,8 @@ async function curatorCommit(options) {
94768
94877
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
94769
94878
  const projectKey = getProjectKey(config2, resolved.projectDir);
94770
94879
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
94771
- const runDir = join87(outputDir, "runs", options.runId);
94772
- const proposalsPath = join87(runDir, "curator-proposals.md");
94880
+ const runDir = join86(outputDir, "runs", options.runId);
94881
+ const proposalsPath = join86(runDir, "curator-proposals.md");
94773
94882
  const proposalText = await _curatorCmdDeps.readFile(proposalsPath).catch(() => null);
94774
94883
  if (proposalText === null) {
94775
94884
  console.log(`curator-proposals.md not found for run ${options.runId}.`);
@@ -94785,7 +94894,7 @@ async function curatorCommit(options) {
94785
94894
  const dropFileState = new Map;
94786
94895
  const skippedDrops = new Set;
94787
94896
  for (const drop2 of drops) {
94788
- const targetPath = join87(resolved.projectDir, drop2.canonicalFile);
94897
+ const targetPath = join86(resolved.projectDir, drop2.canonicalFile);
94789
94898
  if (!dropFileState.has(targetPath)) {
94790
94899
  const fileExists2 = await Bun.file(targetPath).exists();
94791
94900
  const existing = fileExists2 ? await _curatorCmdDeps.readFile(targetPath).catch(() => "") : "";
@@ -94819,7 +94928,7 @@ async function curatorCommit(options) {
94819
94928
  if (skippedDrops.has(drop2)) {
94820
94929
  continue;
94821
94930
  }
94822
- const targetPath = join87(resolved.projectDir, drop2.canonicalFile);
94931
+ const targetPath = join86(resolved.projectDir, drop2.canonicalFile);
94823
94932
  const existing = await _curatorCmdDeps.readFile(targetPath).catch(() => "");
94824
94933
  const filtered = filterDropContent(existing, drop2.description);
94825
94934
  await _curatorCmdDeps.writeFile(targetPath, filtered);
@@ -94828,7 +94937,7 @@ async function curatorCommit(options) {
94828
94937
  }
94829
94938
  const adds = proposals.filter((p) => p.action === "add" || p.action === "advisory");
94830
94939
  for (const add2 of adds) {
94831
- const targetPath = join87(resolved.projectDir, add2.canonicalFile);
94940
+ const targetPath = join86(resolved.projectDir, add2.canonicalFile);
94832
94941
  const content = buildAddContent(add2);
94833
94942
  await _curatorCmdDeps.appendFile(targetPath, content);
94834
94943
  modifiedFiles.add(targetPath);
@@ -94865,7 +94974,7 @@ async function curatorDryrun(options) {
94865
94974
  const config2 = await _curatorCmdDeps.loadConfig(resolved.projectDir);
94866
94975
  const projectKey = getProjectKey(config2, resolved.projectDir);
94867
94976
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
94868
- const runsDir = join87(outputDir, "runs");
94977
+ const runsDir = join86(outputDir, "runs");
94869
94978
  const runIds = listRunIds(runsDir);
94870
94979
  if (runIds.length === 0) {
94871
94980
  console.log("No runs found.");
@@ -94876,7 +94985,7 @@ async function curatorDryrun(options) {
94876
94985
  console.log(`Run ${options.run} not found in ${runsDir}.`);
94877
94986
  return;
94878
94987
  }
94879
- const observationsPath = join87(runsDir, runId, "observations.jsonl");
94988
+ const observationsPath = join86(runsDir, runId, "observations.jsonl");
94880
94989
  const observations = await parseObservations(observationsPath);
94881
94990
  const thresholds = getThresholds(config2);
94882
94991
  const proposals = runHeuristics(observations, thresholds);
@@ -94917,12 +95026,12 @@ async function curatorGc(options) {
94917
95026
  await _curatorCmdDeps.writeFile(rollupPath, newContent);
94918
95027
  const projectKey = getProjectKey(config2, resolved.projectDir);
94919
95028
  const outputDir = _curatorCmdDeps.projectOutputDir(projectKey, config2.outputDir);
94920
- const perRunsDir = join87(outputDir, "runs");
95029
+ const perRunsDir = join86(outputDir, "runs");
94921
95030
  for (const runId of uniqueRunIds) {
94922
95031
  if (!keepSet.has(runId)) {
94923
- const runDir = join87(perRunsDir, runId);
94924
- await _curatorCmdDeps.removeFile(join87(runDir, "observations.jsonl"));
94925
- await _curatorCmdDeps.removeFile(join87(runDir, "curator-proposals.md"));
95032
+ const runDir = join86(perRunsDir, runId);
95033
+ await _curatorCmdDeps.removeFile(join86(runDir, "observations.jsonl"));
95034
+ await _curatorCmdDeps.removeFile(join86(runDir, "curator-proposals.md"));
94926
95035
  }
94927
95036
  }
94928
95037
  console.log(`[gc] Pruned rollup to ${keep} most recent runs (was ${uniqueRunIds.length}).`);
@@ -94967,7 +95076,7 @@ var init_curator2 = __esm(() => {
94967
95076
  init_source();
94968
95077
  import { existsSync as existsSync35, mkdirSync as mkdirSync7 } from "fs";
94969
95078
  import { homedir as homedir3 } from "os";
94970
- import { basename as basename16, join as join88 } from "path";
95079
+ import { basename as basename16, join as join87 } from "path";
94971
95080
 
94972
95081
  // node_modules/commander/esm.mjs
94973
95082
  var import__ = __toESM(require_commander(), 1);
@@ -94991,12 +95100,12 @@ init_errors();
94991
95100
  init_operations();
94992
95101
 
94993
95102
  // src/plan/strategies/context-builder.ts
94994
- import { join as join39 } from "path";
95103
+ import { join as join38 } from "path";
94995
95104
  init_config();
94996
95105
  init_errors();
94997
95106
  init_interaction();
94998
95107
  async function buildPlanModeContext(workdir, fullConfig, options, deps) {
94999
- const naxDir = join39(workdir, ".nax");
95108
+ const naxDir = join38(workdir, ".nax");
95000
95109
  if (!deps.existsSync(naxDir)) {
95001
95110
  throw new NaxError(`.nax directory not found. Run 'nax init' first in ${workdir}`, "PLAN_CONTEXT_NO_NAX_DIR", {
95002
95111
  stage: "plan",
@@ -95004,8 +95113,8 @@ async function buildPlanModeContext(workdir, fullConfig, options, deps) {
95004
95113
  });
95005
95114
  }
95006
95115
  validateFeatureName(options.feature);
95007
- const outputDir = join39(naxDir, "features", options.feature);
95008
- const outputPath = join39(outputDir, "prd.json");
95116
+ const outputDir = join38(naxDir, "features", options.feature);
95117
+ const outputPath = join38(outputDir, "prd.json");
95009
95118
  const [specContent, sourceRoots, pkg] = await Promise.all([
95010
95119
  deps.readFile(options.from),
95011
95120
  deps.scanSourceRoots(workdir),
@@ -95020,7 +95129,7 @@ async function buildPlanModeContext(workdir, fullConfig, options, deps) {
95020
95129
  ...new Set(sourceRoots.map((root) => root.path).filter((path7) => path7 !== ".").map((path7) => path7.startsWith("/") ? path7.replace(`${workdir}/`, "") : path7))
95021
95130
  ];
95022
95131
  const packageDetails = relativePackages.length === 0 ? [] : await Promise.all(relativePackages.map(async (relativePath) => {
95023
- const packageJson = await deps.readPackageJsonAt(join39(workdir, relativePath, "package.json"));
95132
+ const packageJson = await deps.readPackageJsonAt(join38(workdir, relativePath, "package.json"));
95024
95133
  return buildPackageSummary(relativePath, packageJson);
95025
95134
  }));
95026
95135
  const projectName = detectProjectName(workdir, pkg);
@@ -95623,7 +95732,7 @@ init_interaction();
95623
95732
  init_prd();
95624
95733
  init_runtime();
95625
95734
  import { existsSync as existsSync17, readdirSync as readdirSync3 } from "fs";
95626
- import { basename as basename7, join as join44, resolve as resolve14 } from "path";
95735
+ import { basename as basename7, join as join43, resolve as resolve14 } from "path";
95627
95736
  var _statusFeaturesDeps = {
95628
95737
  projectOutputDir,
95629
95738
  loadConfig
@@ -95637,7 +95746,7 @@ function isPidAlive(pid) {
95637
95746
  }
95638
95747
  }
95639
95748
  async function loadStatusFile(featureDir) {
95640
- const statusPath = join44(featureDir, "status.json");
95749
+ const statusPath = join43(featureDir, "status.json");
95641
95750
  if (!existsSync17(statusPath)) {
95642
95751
  return null;
95643
95752
  }
@@ -95652,7 +95761,7 @@ async function loadProjectStatusFile(projectDir) {
95652
95761
  const config2 = await _statusFeaturesDeps.loadConfig(projectDir).catch(() => null);
95653
95762
  const projectKey = config2?.name?.trim() || basename7(projectDir);
95654
95763
  const outputDir = _statusFeaturesDeps.projectOutputDir(projectKey, config2?.outputDir);
95655
- const statusPath = join44(outputDir, "status.json");
95764
+ const statusPath = join43(outputDir, "status.json");
95656
95765
  if (!existsSync17(statusPath)) {
95657
95766
  return null;
95658
95767
  }
@@ -95664,7 +95773,7 @@ async function loadProjectStatusFile(projectDir) {
95664
95773
  }
95665
95774
  }
95666
95775
  async function getFeatureSummary(featureName, featureDir) {
95667
- const prdPath = join44(featureDir, "prd.json");
95776
+ const prdPath = join43(featureDir, "prd.json");
95668
95777
  if (!existsSync17(prdPath)) {
95669
95778
  return {
95670
95779
  name: featureName,
@@ -95707,7 +95816,7 @@ async function getFeatureSummary(featureName, featureDir) {
95707
95816
  };
95708
95817
  }
95709
95818
  }
95710
- const runsDir = join44(featureDir, "runs");
95819
+ const runsDir = join43(featureDir, "runs");
95711
95820
  if (existsSync17(runsDir)) {
95712
95821
  const runs = readdirSync3(runsDir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(".jsonl") && e.name !== "latest.jsonl").map((e) => e.name).sort().reverse();
95713
95822
  if (runs.length > 0) {
@@ -95721,7 +95830,7 @@ async function displayAllFeatures(projectDir) {
95721
95830
  const config2 = await _statusFeaturesDeps.loadConfig(projectDir).catch(() => null);
95722
95831
  const projectKey = config2?.name?.trim() || basename7(projectDir);
95723
95832
  const outputDir = _statusFeaturesDeps.projectOutputDir(projectKey, config2?.outputDir);
95724
- const featuresDir = join44(outputDir, "features");
95833
+ const featuresDir = join43(outputDir, "features");
95725
95834
  if (!existsSync17(featuresDir)) {
95726
95835
  console.log(source_default.dim("No features found."));
95727
95836
  return;
@@ -95762,7 +95871,7 @@ async function displayAllFeatures(projectDir) {
95762
95871
  console.log();
95763
95872
  }
95764
95873
  }
95765
- const summaries = await Promise.all(features.map((name) => getFeatureSummary(name, join44(featuresDir, name))));
95874
+ const summaries = await Promise.all(features.map((name) => getFeatureSummary(name, join43(featuresDir, name))));
95766
95875
  console.log(source_default.bold(`\uD83D\uDCCA Features
95767
95876
  `));
95768
95877
  const header = ` ${"Feature".padEnd(25)} ${"Done".padEnd(6)} ${"Failed".padEnd(8)} ${"Pending".padEnd(9)} ${"Last Run".padEnd(22)} ${"Cost".padEnd(10)} Status`;
@@ -95788,7 +95897,7 @@ async function displayAllFeatures(projectDir) {
95788
95897
  console.log();
95789
95898
  }
95790
95899
  async function displayFeatureDetails(featureName, featureDir) {
95791
- const prdPath = join44(featureDir, "prd.json");
95900
+ const prdPath = join43(featureDir, "prd.json");
95792
95901
  if (!existsSync17(prdPath)) {
95793
95902
  console.log(source_default.bold(`
95794
95903
  \uD83D\uDCCA ${featureName}
@@ -95934,7 +96043,7 @@ async function displayFeatureStatus(options = {}) {
95934
96043
  const config2 = await _statusFeaturesDeps.loadConfig(projectDir).catch(() => null);
95935
96044
  const projectKey = config2?.name?.trim() || basename7(projectDir);
95936
96045
  const outputDir = _statusFeaturesDeps.projectOutputDir(projectKey, config2?.outputDir);
95937
- featureDir = join44(outputDir, "features", options.feature);
96046
+ featureDir = join43(outputDir, "features", options.feature);
95938
96047
  } else {
95939
96048
  const resolved = resolveProject({ feature: options.feature });
95940
96049
  if (!resolved.featureDir) {
@@ -95954,7 +96063,7 @@ init_errors();
95954
96063
  init_logger2();
95955
96064
  init_runtime();
95956
96065
  import { existsSync as existsSync18, readdirSync as readdirSync4 } from "fs";
95957
- import { basename as basename8, join as join45 } from "path";
96066
+ import { basename as basename8, join as join44 } from "path";
95958
96067
  async function resolveOutputDir2(workdir, override) {
95959
96068
  if (override)
95960
96069
  return override;
@@ -95978,7 +96087,7 @@ async function runsListCommand(options) {
95978
96087
  const logger = getLogger();
95979
96088
  const { feature, workdir } = options;
95980
96089
  const outputDir = await resolveOutputDir2(workdir, options.outputDir);
95981
- const runsDir = join45(outputDir, "features", feature, "runs");
96090
+ const runsDir = join44(outputDir, "features", feature, "runs");
95982
96091
  if (!existsSync18(runsDir)) {
95983
96092
  logger.info("cli", "No runs found for feature", { feature, hint: `Directory not found: ${runsDir}` });
95984
96093
  return;
@@ -95990,7 +96099,7 @@ async function runsListCommand(options) {
95990
96099
  }
95991
96100
  logger.info("cli", `Runs for ${feature}`, { count: files.length });
95992
96101
  for (const file3 of files.sort().reverse()) {
95993
- const logPath = join45(runsDir, file3);
96102
+ const logPath = join44(runsDir, file3);
95994
96103
  const entries = await parseRunLog(logPath);
95995
96104
  const startEvent = entries.find((e) => e.message === "run.start");
95996
96105
  const completeEvent = entries.find((e) => e.message === "run.complete");
@@ -96017,7 +96126,7 @@ async function runsShowCommand(options) {
96017
96126
  const logger = getLogger();
96018
96127
  const { runId, feature, workdir } = options;
96019
96128
  const outputDir = await resolveOutputDir2(workdir, options.outputDir);
96020
- const logPath = join45(outputDir, "features", feature, "runs", `${runId}.jsonl`);
96129
+ const logPath = join44(outputDir, "features", feature, "runs", `${runId}.jsonl`);
96021
96130
  if (!existsSync18(logPath)) {
96022
96131
  logger.error("cli", "Run not found", { runId, feature, logPath });
96023
96132
  throw new NaxError("Run not found", "RUN_NOT_FOUND", { runId, feature, logPath });
@@ -97363,19 +97472,19 @@ async function detectCommand(options) {
97363
97472
  // src/commands/logs.ts
97364
97473
  init_common();
97365
97474
  import { existsSync as existsSync28 } from "fs";
97366
- import { join as join71 } from "path";
97475
+ import { join as join70 } from "path";
97367
97476
 
97368
97477
  // src/commands/logs-formatter.ts
97369
97478
  init_source();
97370
97479
  init_formatter();
97371
97480
  import { readdirSync as readdirSync7 } from "fs";
97372
- import { join as join70 } from "path";
97481
+ import { join as join69 } from "path";
97373
97482
 
97374
97483
  // src/commands/logs-reader.ts
97375
97484
  init_paths3();
97376
97485
  import { existsSync as existsSync27, readdirSync as readdirSync6 } from "fs";
97377
- import { readdir as readdir4 } from "fs/promises";
97378
- import { join as join69 } from "path";
97486
+ import { readdir as readdir3 } from "fs/promises";
97487
+ import { join as join68 } from "path";
97379
97488
  var _logsReaderDeps = {
97380
97489
  getRunsDir
97381
97490
  };
@@ -97383,13 +97492,13 @@ async function resolveRunFileFromRegistry(runId) {
97383
97492
  const runsDir = _logsReaderDeps.getRunsDir();
97384
97493
  let entries;
97385
97494
  try {
97386
- entries = await readdir4(runsDir);
97495
+ entries = await readdir3(runsDir);
97387
97496
  } catch {
97388
97497
  throw new Error(`Run not found in registry: ${runId}`);
97389
97498
  }
97390
97499
  let matched = null;
97391
97500
  for (const entry of entries) {
97392
- const metaPath = join69(runsDir, entry, "meta.json");
97501
+ const metaPath = join68(runsDir, entry, "meta.json");
97393
97502
  try {
97394
97503
  const meta3 = await Bun.file(metaPath).json();
97395
97504
  if (meta3.runId === runId || meta3.runId.startsWith(runId)) {
@@ -97411,14 +97520,14 @@ async function resolveRunFileFromRegistry(runId) {
97411
97520
  return null;
97412
97521
  }
97413
97522
  const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
97414
- return join69(matched.eventsDir, specificFile ?? files[0]);
97523
+ return join68(matched.eventsDir, specificFile ?? files[0]);
97415
97524
  }
97416
97525
  async function selectRunFile(runsDir) {
97417
97526
  const files = readdirSync6(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
97418
97527
  if (files.length === 0) {
97419
97528
  return null;
97420
97529
  }
97421
- return join69(runsDir, files[0]);
97530
+ return join68(runsDir, files[0]);
97422
97531
  }
97423
97532
  async function extractRunSummary(filePath) {
97424
97533
  const file3 = Bun.file(filePath);
@@ -97504,7 +97613,7 @@ Runs:
97504
97613
  console.log(source_default.gray(" Timestamp Stories Duration Cost Status"));
97505
97614
  console.log(source_default.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
97506
97615
  for (const file3 of files) {
97507
- const filePath = join70(runsDir, file3);
97616
+ const filePath = join69(runsDir, file3);
97508
97617
  const summary = await extractRunSummary(filePath);
97509
97618
  const timestamp = file3.replace(".jsonl", "");
97510
97619
  const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
@@ -97618,7 +97727,7 @@ async function logsCommand(options) {
97618
97727
  return;
97619
97728
  }
97620
97729
  const resolved = resolveProject({ dir: options.dir });
97621
- const naxDir = join71(resolved.projectDir, ".nax");
97730
+ const naxDir = join70(resolved.projectDir, ".nax");
97622
97731
  const configPath = resolved.configPath;
97623
97732
  const configFile = Bun.file(configPath);
97624
97733
  const config2 = await configFile.json();
@@ -97626,8 +97735,8 @@ async function logsCommand(options) {
97626
97735
  if (!featureName) {
97627
97736
  throw new Error("No feature specified in config.json");
97628
97737
  }
97629
- const featureDir = join71(naxDir, "features", featureName);
97630
- const runsDir = join71(featureDir, "runs");
97738
+ const featureDir = join70(naxDir, "features", featureName);
97739
+ const runsDir = join70(featureDir, "runs");
97631
97740
  if (!existsSync28(runsDir)) {
97632
97741
  throw new Error(`No runs directory found for feature: ${featureName}`);
97633
97742
  }
@@ -97653,7 +97762,7 @@ init_prd();
97653
97762
  init_precheck();
97654
97763
  init_common();
97655
97764
  import { existsSync as existsSync29 } from "fs";
97656
- import { join as join72 } from "path";
97765
+ import { join as join71 } from "path";
97657
97766
  async function precheckCommand(options) {
97658
97767
  const resolved = resolveProject({
97659
97768
  dir: options.dir,
@@ -97675,9 +97784,9 @@ async function precheckCommand(options) {
97675
97784
  process.exit(1);
97676
97785
  }
97677
97786
  }
97678
- const naxDir = join72(resolved.projectDir, ".nax");
97679
- const featureDir = join72(naxDir, "features", featureName);
97680
- const prdPath = join72(featureDir, "prd.json");
97787
+ const naxDir = join71(resolved.projectDir, ".nax");
97788
+ const featureDir = join71(naxDir, "features", featureName);
97789
+ const prdPath = join71(featureDir, "prd.json");
97681
97790
  if (!existsSync29(featureDir)) {
97682
97791
  console.error(source_default.red(`Feature not found: ${featureName}`));
97683
97792
  process.exit(1);
@@ -97699,8 +97808,8 @@ async function precheckCommand(options) {
97699
97808
  // src/commands/runs.ts
97700
97809
  init_source();
97701
97810
  init_paths3();
97702
- import { readdir as readdir5 } from "fs/promises";
97703
- import { join as join73 } from "path";
97811
+ import { readdir as readdir4 } from "fs/promises";
97812
+ import { join as join72 } from "path";
97704
97813
  var DEFAULT_LIMIT = 20;
97705
97814
  var _runsCmdDeps = {
97706
97815
  getRunsDir
@@ -97748,14 +97857,14 @@ async function runsCommand(options = {}) {
97748
97857
  const runsDir = _runsCmdDeps.getRunsDir();
97749
97858
  let entries;
97750
97859
  try {
97751
- entries = await readdir5(runsDir);
97860
+ entries = await readdir4(runsDir);
97752
97861
  } catch {
97753
97862
  console.log("No runs found.");
97754
97863
  return;
97755
97864
  }
97756
97865
  const rows = [];
97757
97866
  for (const entry of entries) {
97758
- const metaPath = join73(runsDir, entry, "meta.json");
97867
+ const metaPath = join72(runsDir, entry, "meta.json");
97759
97868
  let meta3;
97760
97869
  try {
97761
97870
  meta3 = await Bun.file(metaPath).json();
@@ -97832,7 +97941,7 @@ async function runsCommand(options = {}) {
97832
97941
 
97833
97942
  // src/commands/unlock.ts
97834
97943
  init_source();
97835
- import { join as join74 } from "path";
97944
+ import { join as join73 } from "path";
97836
97945
  function isProcessAlive2(pid) {
97837
97946
  try {
97838
97947
  process.kill(pid, 0);
@@ -97847,7 +97956,7 @@ function formatLockAge(ageMs) {
97847
97956
  }
97848
97957
  async function unlockCommand(options) {
97849
97958
  const workdir = options.dir ?? process.cwd();
97850
- const lockPath = join74(workdir, "nax.lock");
97959
+ const lockPath = join73(workdir, "nax.lock");
97851
97960
  const lockFile = Bun.file(lockPath);
97852
97961
  const exists = await lockFile.exists();
97853
97962
  if (!exists) {
@@ -106272,7 +106381,7 @@ Next: nax generate --package ${options.package}`));
106272
106381
  }
106273
106382
  return;
106274
106383
  }
106275
- const naxDir = join88(workdir, ".nax");
106384
+ const naxDir = join87(workdir, ".nax");
106276
106385
  if (existsSync35(naxDir) && !options.force) {
106277
106386
  console.log(source_default.yellow("nax already initialized. Use --force to overwrite."));
106278
106387
  return;
@@ -106301,11 +106410,11 @@ Next: nax generate --package ${options.package}`));
106301
106410
  }
106302
106411
  }
106303
106412
  }
106304
- mkdirSync7(join88(naxDir, "features"), { recursive: true });
106305
- mkdirSync7(join88(naxDir, "hooks"), { recursive: true });
106413
+ mkdirSync7(join87(naxDir, "features"), { recursive: true });
106414
+ mkdirSync7(join87(naxDir, "hooks"), { recursive: true });
106306
106415
  const initConfig = options.name ? { ...DEFAULT_CONFIG, name: options.name } : DEFAULT_CONFIG;
106307
- await Bun.write(join88(naxDir, "config.json"), JSON.stringify(initConfig, null, 2));
106308
- await Bun.write(join88(naxDir, "hooks.json"), JSON.stringify({
106416
+ await Bun.write(join87(naxDir, "config.json"), JSON.stringify(initConfig, null, 2));
106417
+ await Bun.write(join87(naxDir, "hooks.json"), JSON.stringify({
106309
106418
  hooks: {
106310
106419
  "on-start": { command: 'echo "nax started: $NAX_FEATURE"', enabled: false },
106311
106420
  "on-complete": { command: 'echo "nax complete: $NAX_FEATURE"', enabled: false },
@@ -106313,12 +106422,12 @@ Next: nax generate --package ${options.package}`));
106313
106422
  "on-error": { command: 'echo "nax error: $NAX_REASON"', enabled: false }
106314
106423
  }
106315
106424
  }, null, 2));
106316
- await Bun.write(join88(naxDir, ".gitignore"), `# nax temp files
106425
+ await Bun.write(join87(naxDir, ".gitignore"), `# nax temp files
106317
106426
  *.tmp
106318
106427
  .paused.json
106319
106428
  .nax-verifier-verdict.json
106320
106429
  `);
106321
- await Bun.write(join88(naxDir, "context.md"), `# Project Context
106430
+ await Bun.write(join87(naxDir, "context.md"), `# Project Context
106322
106431
 
106323
106432
  This document defines coding standards, architectural decisions, and forbidden patterns for this project.
106324
106433
  Run \`nax generate\` to regenerate agent config files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) from this file.
@@ -106466,8 +106575,8 @@ program2.command("run").description("Run the orchestration loop for a feature").
106466
106575
  console.error(source_default.red("nax not initialized. Run: nax init"));
106467
106576
  process.exit(1);
106468
106577
  }
106469
- const featureDir = join88(naxDir, "features", options.feature);
106470
- const prdPath = join88(featureDir, "prd.json");
106578
+ const featureDir = join87(naxDir, "features", options.feature);
106579
+ const prdPath = join87(featureDir, "prd.json");
106471
106580
  if (options.plan && options.from) {
106472
106581
  if (existsSync35(prdPath) && !options.force) {
106473
106582
  console.error(source_default.red(`Error: prd.json already exists for feature "${options.feature}".`));
@@ -106489,10 +106598,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
106489
106598
  }
106490
106599
  }
106491
106600
  try {
106492
- const planLogDir = join88(featureDir, "plan");
106601
+ const planLogDir = join87(featureDir, "plan");
106493
106602
  mkdirSync7(planLogDir, { recursive: true });
106494
106603
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
106495
- const planLogPath = join88(planLogDir, `${planLogId}.jsonl`);
106604
+ const planLogPath = join87(planLogDir, `${planLogId}.jsonl`);
106496
106605
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
106497
106606
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
106498
106607
  console.log(source_default.dim(" [Planning phase: generating PRD from spec]"));
@@ -106538,10 +106647,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
106538
106647
  resetLogger();
106539
106648
  const projectKey = config2.name?.trim() || basename16(workdir);
106540
106649
  const outputDir = projectOutputDir(projectKey, config2.outputDir);
106541
- const runsDir = join88(outputDir, "features", options.feature, "runs");
106650
+ const runsDir = join87(outputDir, "features", options.feature, "runs");
106542
106651
  mkdirSync7(runsDir, { recursive: true });
106543
106652
  const runId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
106544
- const logFilePath = join88(runsDir, `${runId}.jsonl`);
106653
+ const logFilePath = join87(runsDir, `${runId}.jsonl`);
106545
106654
  const isTTY = process.stdout.isTTY ?? false;
106546
106655
  const headlessFlag = options.headless ?? false;
106547
106656
  const headlessEnv = process.env.NAX_HEADLESS === "1";
@@ -106559,7 +106668,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
106559
106668
  config2.agent.default = options.agent;
106560
106669
  }
106561
106670
  config2.execution.maxIterations = Number.parseInt(options.maxIterations, 10);
106562
- const globalNaxDir = join88(homedir3(), ".nax");
106671
+ const globalNaxDir = join87(homedir3(), ".nax");
106563
106672
  const hooks = await loadHooksConfig(naxDir, globalNaxDir);
106564
106673
  const eventEmitter = new PipelineEventEmitter;
106565
106674
  const agentStreamEvents = useHeadless ? undefined : new AgentStreamEventBus;
@@ -106579,12 +106688,12 @@ program2.command("run").description("Run the orchestration loop for a feature").
106579
106688
  events: eventEmitter,
106580
106689
  ptyOptions: null,
106581
106690
  agentStreamEvents,
106582
- queueFilePath: join88(workdir, ".queue.txt")
106691
+ queueFilePath: join87(workdir, ".queue.txt")
106583
106692
  });
106584
106693
  } else {
106585
106694
  console.log(source_default.dim(" [Headless mode \u2014 pipe output]"));
106586
106695
  }
106587
- const statusFilePath = join88(outputDir, "status.json");
106696
+ const statusFilePath = join87(outputDir, "status.json");
106588
106697
  let parallel;
106589
106698
  if (options.parallel !== undefined) {
106590
106699
  parallel = Number.parseInt(options.parallel, 10);
@@ -106611,7 +106720,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
106611
106720
  skipPrecheck: options.skipPrecheck ?? false,
106612
106721
  agentStreamEvents
106613
106722
  });
106614
- const latestSymlink = join88(runsDir, "latest.jsonl");
106723
+ const latestSymlink = join87(runsDir, "latest.jsonl");
106615
106724
  try {
106616
106725
  if (existsSync35(latestSymlink)) {
106617
106726
  Bun.spawnSync(["rm", latestSymlink]);
@@ -106672,9 +106781,9 @@ features.command("create <name>").description("Create a new feature").option("-d
106672
106781
  console.error(source_default.red("nax not initialized. Run: nax init"));
106673
106782
  process.exit(1);
106674
106783
  }
106675
- const featureDir = join88(naxDir, "features", name);
106784
+ const featureDir = join87(naxDir, "features", name);
106676
106785
  mkdirSync7(featureDir, { recursive: true });
106677
- await Bun.write(join88(featureDir, "spec.md"), `# Feature: ${name}
106786
+ await Bun.write(join87(featureDir, "spec.md"), `# Feature: ${name}
106678
106787
 
106679
106788
  ## Overview
106680
106789
 
@@ -106707,7 +106816,7 @@ features.command("create <name>").description("Create a new feature").option("-d
106707
106816
 
106708
106817
  <!-- What this feature explicitly does NOT cover. -->
106709
106818
  `);
106710
- await Bun.write(join88(featureDir, "progress.txt"), `# Progress: ${name}
106819
+ await Bun.write(join87(featureDir, "progress.txt"), `# Progress: ${name}
106711
106820
 
106712
106821
  Created: ${new Date().toISOString()}
106713
106822
 
@@ -106733,7 +106842,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
106733
106842
  console.error(source_default.red("nax not initialized."));
106734
106843
  process.exit(1);
106735
106844
  }
106736
- const featuresDir = join88(naxDir, "features");
106845
+ const featuresDir = join87(naxDir, "features");
106737
106846
  if (!existsSync35(featuresDir)) {
106738
106847
  console.log(source_default.dim("No features yet."));
106739
106848
  return;
@@ -106748,7 +106857,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
106748
106857
  Features:
106749
106858
  `));
106750
106859
  for (const name of entries) {
106751
- const prdPath = join88(featuresDir, name, "prd.json");
106860
+ const prdPath = join87(featuresDir, name, "prd.json");
106752
106861
  if (existsSync35(prdPath)) {
106753
106862
  const prd = await loadPRD(prdPath);
106754
106863
  const c = countStories(prd);
@@ -106783,10 +106892,10 @@ Use: nax plan -f <feature> --from <spec>`));
106783
106892
  cliOverrides.profile = options.profile;
106784
106893
  }
106785
106894
  const config2 = await loadConfig(workdir, cliOverrides);
106786
- const featureLogDir = join88(naxDir, "features", options.feature, "plan");
106895
+ const featureLogDir = join87(naxDir, "features", options.feature, "plan");
106787
106896
  mkdirSync7(featureLogDir, { recursive: true });
106788
106897
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
106789
- const planLogPath = join88(featureLogDir, `${planLogId}.jsonl`);
106898
+ const planLogPath = join87(featureLogDir, `${planLogId}.jsonl`);
106790
106899
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
106791
106900
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
106792
106901
  try {