@nathapp/nax 0.48.1 → 0.48.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nax.js CHANGED
@@ -19241,7 +19241,7 @@ class SpawnAcpSession {
19241
19241
  } catch {}
19242
19242
  this.activeProc = null;
19243
19243
  }
19244
- const cmd = ["acpx", this.agentName, "sessions", "close", this.sessionName];
19244
+ const cmd = ["acpx", "--cwd", this.cwd, this.agentName, "sessions", "close", this.sessionName];
19245
19245
  getSafeLogger()?.debug("acp-adapter", `Closing session: ${this.sessionName}`);
19246
19246
  const proc = _spawnClientDeps.spawn(cmd, { stdout: "pipe", stderr: "pipe" });
19247
19247
  const exitCode = await proc.exited;
@@ -22210,7 +22210,7 @@ var package_default;
22210
22210
  var init_package = __esm(() => {
22211
22211
  package_default = {
22212
22212
  name: "@nathapp/nax",
22213
- version: "0.48.1",
22213
+ version: "0.48.3",
22214
22214
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
22215
22215
  type: "module",
22216
22216
  bin: {
@@ -22283,8 +22283,8 @@ var init_version = __esm(() => {
22283
22283
  NAX_VERSION = package_default.version;
22284
22284
  NAX_COMMIT = (() => {
22285
22285
  try {
22286
- if (/^[0-9a-f]{6,10}$/.test("ae560e9"))
22287
- return "ae560e9";
22286
+ if (/^[0-9a-f]{6,10}$/.test("fa27043"))
22287
+ return "fa27043";
22288
22288
  } catch {}
22289
22289
  try {
22290
22290
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -29366,6 +29366,7 @@ var init_regression2 = __esm(() => {
29366
29366
  });
29367
29367
 
29368
29368
  // src/pipeline/stages/routing.ts
29369
+ import { join as join25 } from "path";
29369
29370
  async function runDecompose(story, prd, config2, _workdir, agentGetFn) {
29370
29371
  const naxDecompose = config2.decompose;
29371
29372
  const builderConfig = {
@@ -29439,11 +29440,13 @@ var init_routing2 = __esm(() => {
29439
29440
  }
29440
29441
  const greenfieldDetectionEnabled = ctx.config.tdd.greenfieldDetection ?? true;
29441
29442
  if (greenfieldDetectionEnabled && routing.testStrategy.startsWith("three-session-tdd")) {
29442
- const isGreenfield = await _routingDeps.isGreenfieldStory(ctx.story, ctx.workdir);
29443
+ const greenfieldScanDir = ctx.story.workdir ? join25(ctx.workdir, ctx.story.workdir) : ctx.workdir;
29444
+ const isGreenfield = await _routingDeps.isGreenfieldStory(ctx.story, greenfieldScanDir);
29443
29445
  if (isGreenfield) {
29444
29446
  logger.info("routing", "Greenfield detected \u2014 forcing test-after strategy", {
29445
29447
  storyId: ctx.story.id,
29446
- originalStrategy: routing.testStrategy
29448
+ originalStrategy: routing.testStrategy,
29449
+ scanDir: greenfieldScanDir
29447
29450
  });
29448
29451
  routing.testStrategy = "test-after";
29449
29452
  routing.reasoning = `${routing.reasoning} [GREENFIELD OVERRIDE: No test files exist, using test-after instead of TDD]`;
@@ -29534,7 +29537,7 @@ var init_crash_detector = __esm(() => {
29534
29537
  });
29535
29538
 
29536
29539
  // src/pipeline/stages/verify.ts
29537
- import { join as join25 } from "path";
29540
+ import { join as join26 } from "path";
29538
29541
  function coerceSmartTestRunner(val) {
29539
29542
  if (val === undefined || val === true)
29540
29543
  return DEFAULT_SMART_RUNNER_CONFIG2;
@@ -29566,7 +29569,7 @@ var init_verify = __esm(() => {
29566
29569
  skipReason: () => "not needed (full-suite gate already passed)",
29567
29570
  async execute(ctx) {
29568
29571
  const logger = getLogger();
29569
- const effectiveConfig = ctx.story.workdir ? await _verifyDeps.loadConfigForWorkdir(join25(ctx.workdir, "nax", "config.json"), ctx.story.workdir) : ctx.config;
29572
+ const effectiveConfig = ctx.story.workdir ? await _verifyDeps.loadConfigForWorkdir(join26(ctx.workdir, "nax", "config.json"), ctx.story.workdir) : ctx.config;
29570
29573
  if (!effectiveConfig.quality.requireTests) {
29571
29574
  logger.debug("verify", "Skipping verification (quality.requireTests = false)", { storyId: ctx.story.id });
29572
29575
  return { action: "continue" };
@@ -29578,7 +29581,7 @@ var init_verify = __esm(() => {
29578
29581
  return { action: "continue" };
29579
29582
  }
29580
29583
  logger.info("verify", "Running verification", { storyId: ctx.story.id });
29581
- const effectiveWorkdir = ctx.story.workdir ? join25(ctx.workdir, ctx.story.workdir) : ctx.workdir;
29584
+ const effectiveWorkdir = ctx.story.workdir ? join26(ctx.workdir, ctx.story.workdir) : ctx.workdir;
29582
29585
  let effectiveCommand = testCommand;
29583
29586
  let isFullSuite = true;
29584
29587
  const smartRunnerConfig = coerceSmartTestRunner(ctx.config.execution.smartTestRunner);
@@ -29752,7 +29755,7 @@ __export(exports_init_context, {
29752
29755
  });
29753
29756
  import { existsSync as existsSync20 } from "fs";
29754
29757
  import { mkdir } from "fs/promises";
29755
- import { basename, join as join29 } from "path";
29758
+ import { basename, join as join30 } from "path";
29756
29759
  async function findFiles(dir, maxFiles = 200) {
29757
29760
  try {
29758
29761
  const proc = Bun.spawnSync([
@@ -29780,7 +29783,7 @@ async function findFiles(dir, maxFiles = 200) {
29780
29783
  return [];
29781
29784
  }
29782
29785
  async function readPackageManifest(projectRoot) {
29783
- const packageJsonPath = join29(projectRoot, "package.json");
29786
+ const packageJsonPath = join30(projectRoot, "package.json");
29784
29787
  if (!existsSync20(packageJsonPath)) {
29785
29788
  return null;
29786
29789
  }
@@ -29798,7 +29801,7 @@ async function readPackageManifest(projectRoot) {
29798
29801
  }
29799
29802
  }
29800
29803
  async function readReadmeSnippet(projectRoot) {
29801
- const readmePath = join29(projectRoot, "README.md");
29804
+ const readmePath = join30(projectRoot, "README.md");
29802
29805
  if (!existsSync20(readmePath)) {
29803
29806
  return null;
29804
29807
  }
@@ -29816,7 +29819,7 @@ async function detectEntryPoints(projectRoot) {
29816
29819
  const candidates = ["src/index.ts", "src/main.ts", "main.go", "src/lib.rs"];
29817
29820
  const found = [];
29818
29821
  for (const candidate of candidates) {
29819
- const path12 = join29(projectRoot, candidate);
29822
+ const path12 = join30(projectRoot, candidate);
29820
29823
  if (existsSync20(path12)) {
29821
29824
  found.push(candidate);
29822
29825
  }
@@ -29827,7 +29830,7 @@ async function detectConfigFiles(projectRoot) {
29827
29830
  const candidates = ["tsconfig.json", "biome.json", "turbo.json", ".env.example"];
29828
29831
  const found = [];
29829
29832
  for (const candidate of candidates) {
29830
- const path12 = join29(projectRoot, candidate);
29833
+ const path12 = join30(projectRoot, candidate);
29831
29834
  if (existsSync20(path12)) {
29832
29835
  found.push(candidate);
29833
29836
  }
@@ -29988,9 +29991,9 @@ function generatePackageContextTemplate(packagePath) {
29988
29991
  }
29989
29992
  async function initPackage(repoRoot, packagePath, force = false) {
29990
29993
  const logger = getLogger();
29991
- const packageDir = join29(repoRoot, packagePath);
29992
- const naxDir = join29(packageDir, "nax");
29993
- const contextPath = join29(naxDir, "context.md");
29994
+ const packageDir = join30(repoRoot, packagePath);
29995
+ const naxDir = join30(packageDir, "nax");
29996
+ const contextPath = join30(naxDir, "context.md");
29994
29997
  if (existsSync20(contextPath) && !force) {
29995
29998
  logger.info("init", "Package context.md already exists (use --force to overwrite)", { path: contextPath });
29996
29999
  return;
@@ -30004,8 +30007,8 @@ async function initPackage(repoRoot, packagePath, force = false) {
30004
30007
  }
30005
30008
  async function initContext(projectRoot, options = {}) {
30006
30009
  const logger = getLogger();
30007
- const naxDir = join29(projectRoot, "nax");
30008
- const contextPath = join29(naxDir, "context.md");
30010
+ const naxDir = join30(projectRoot, "nax");
30011
+ const contextPath = join30(naxDir, "context.md");
30009
30012
  if (existsSync20(contextPath) && !options.force) {
30010
30013
  logger.info("init", "context.md already exists, skipping (use --force to overwrite)", { path: contextPath });
30011
30014
  return;
@@ -30594,6 +30597,7 @@ var init_checks_git = __esm(() => {
30594
30597
  /^.{2} nax\.lock$/,
30595
30598
  /^.{2} nax\/metrics\.json$/,
30596
30599
  /^.{2} nax\/features\/[^/]+\/status\.json$/,
30600
+ /^.{2} nax\/features\/[^/]+\/prd\.json$/,
30597
30601
  /^.{2} nax\/features\/[^/]+\/runs\//,
30598
30602
  /^.{2} nax\/features\/[^/]+\/plan\//,
30599
30603
  /^.{2} nax\/features\/[^/]+\/acp-sessions\.json$/,
@@ -31312,19 +31316,19 @@ var init_precheck = __esm(() => {
31312
31316
  });
31313
31317
 
31314
31318
  // src/hooks/runner.ts
31315
- import { join as join42 } from "path";
31319
+ import { join as join43 } from "path";
31316
31320
  async function loadHooksConfig(projectDir, globalDir) {
31317
31321
  let globalHooks = { hooks: {} };
31318
31322
  let projectHooks = { hooks: {} };
31319
31323
  let skipGlobal = false;
31320
- const projectPath = join42(projectDir, "hooks.json");
31324
+ const projectPath = join43(projectDir, "hooks.json");
31321
31325
  const projectData = await loadJsonFile(projectPath, "hooks");
31322
31326
  if (projectData) {
31323
31327
  projectHooks = projectData;
31324
31328
  skipGlobal = projectData.skipGlobal ?? false;
31325
31329
  }
31326
31330
  if (!skipGlobal && globalDir) {
31327
- const globalPath = join42(globalDir, "hooks.json");
31331
+ const globalPath = join43(globalDir, "hooks.json");
31328
31332
  const globalData = await loadJsonFile(globalPath, "hooks");
31329
31333
  if (globalData) {
31330
31334
  globalHooks = globalData;
@@ -31656,6 +31660,9 @@ function createSignalHandler(ctx) {
31656
31660
  if (ctx.pidRegistry) {
31657
31661
  await ctx.pidRegistry.killAll();
31658
31662
  }
31663
+ if (ctx.onShutdown) {
31664
+ await ctx.onShutdown().catch(() => {});
31665
+ }
31659
31666
  ctx.emitError?.(signal.toLowerCase());
31660
31667
  await writeFatalLog(ctx.jsonlFilePath, signal);
31661
31668
  await writeRunComplete(ctx, signal.toLowerCase());
@@ -31674,6 +31681,9 @@ function createUncaughtExceptionHandler(ctx) {
31674
31681
  if (ctx.pidRegistry) {
31675
31682
  await ctx.pidRegistry.killAll();
31676
31683
  }
31684
+ if (ctx.onShutdown) {
31685
+ await ctx.onShutdown().catch(() => {});
31686
+ }
31677
31687
  ctx.emitError?.("uncaughtException");
31678
31688
  await writeFatalLog(ctx.jsonlFilePath, "uncaughtException", error48);
31679
31689
  await updateStatusToCrashed(ctx.statusWriter, ctx.getTotalCost(), ctx.getIterations(), "uncaughtException", ctx.featureDir);
@@ -31691,6 +31701,9 @@ function createUnhandledRejectionHandler(ctx) {
31691
31701
  if (ctx.pidRegistry) {
31692
31702
  await ctx.pidRegistry.killAll();
31693
31703
  }
31704
+ if (ctx.onShutdown) {
31705
+ await ctx.onShutdown().catch(() => {});
31706
+ }
31694
31707
  ctx.emitError?.("unhandledRejection");
31695
31708
  await writeFatalLog(ctx.jsonlFilePath, "unhandledRejection", error48);
31696
31709
  await updateStatusToCrashed(ctx.statusWriter, ctx.getTotalCost(), ctx.getIterations(), "unhandledRejection", ctx.featureDir);
@@ -32347,12 +32360,12 @@ __export(exports_manager, {
32347
32360
  WorktreeManager: () => WorktreeManager
32348
32361
  });
32349
32362
  import { existsSync as existsSync32, symlinkSync } from "fs";
32350
- import { join as join43 } from "path";
32363
+ import { join as join44 } from "path";
32351
32364
 
32352
32365
  class WorktreeManager {
32353
32366
  async create(projectRoot, storyId) {
32354
32367
  validateStoryId(storyId);
32355
- const worktreePath = join43(projectRoot, ".nax-wt", storyId);
32368
+ const worktreePath = join44(projectRoot, ".nax-wt", storyId);
32356
32369
  const branchName = `nax/${storyId}`;
32357
32370
  try {
32358
32371
  const proc = Bun.spawn(["git", "worktree", "add", worktreePath, "-b", branchName], {
@@ -32377,9 +32390,9 @@ class WorktreeManager {
32377
32390
  }
32378
32391
  throw new Error(`Failed to create worktree: ${String(error48)}`);
32379
32392
  }
32380
- const nodeModulesSource = join43(projectRoot, "node_modules");
32393
+ const nodeModulesSource = join44(projectRoot, "node_modules");
32381
32394
  if (existsSync32(nodeModulesSource)) {
32382
- const nodeModulesTarget = join43(worktreePath, "node_modules");
32395
+ const nodeModulesTarget = join44(worktreePath, "node_modules");
32383
32396
  try {
32384
32397
  symlinkSync(nodeModulesSource, nodeModulesTarget, "dir");
32385
32398
  } catch (error48) {
@@ -32387,9 +32400,9 @@ class WorktreeManager {
32387
32400
  throw new Error(`Failed to symlink node_modules: ${errorMessage(error48)}`);
32388
32401
  }
32389
32402
  }
32390
- const envSource = join43(projectRoot, ".env");
32403
+ const envSource = join44(projectRoot, ".env");
32391
32404
  if (existsSync32(envSource)) {
32392
- const envTarget = join43(worktreePath, ".env");
32405
+ const envTarget = join44(worktreePath, ".env");
32393
32406
  try {
32394
32407
  symlinkSync(envSource, envTarget, "file");
32395
32408
  } catch (error48) {
@@ -32400,7 +32413,7 @@ class WorktreeManager {
32400
32413
  }
32401
32414
  async remove(projectRoot, storyId) {
32402
32415
  validateStoryId(storyId);
32403
- const worktreePath = join43(projectRoot, ".nax-wt", storyId);
32416
+ const worktreePath = join44(projectRoot, ".nax-wt", storyId);
32404
32417
  const branchName = `nax/${storyId}`;
32405
32418
  try {
32406
32419
  const proc = Bun.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
@@ -32790,7 +32803,7 @@ var init_parallel_worker = __esm(() => {
32790
32803
 
32791
32804
  // src/execution/parallel-coordinator.ts
32792
32805
  import os3 from "os";
32793
- import { join as join44 } from "path";
32806
+ import { join as join45 } from "path";
32794
32807
  function groupStoriesByDependencies(stories) {
32795
32808
  const batches = [];
32796
32809
  const processed = new Set;
@@ -32868,7 +32881,7 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
32868
32881
  };
32869
32882
  const worktreePaths = new Map;
32870
32883
  for (const story of batch) {
32871
- const worktreePath = join44(projectRoot, ".nax-wt", story.id);
32884
+ const worktreePath = join45(projectRoot, ".nax-wt", story.id);
32872
32885
  try {
32873
32886
  await worktreeManager.create(projectRoot, story.id);
32874
32887
  worktreePaths.set(story.id, worktreePath);
@@ -32917,7 +32930,7 @@ async function executeParallel(stories, prdPath, projectRoot, config2, hooks, pl
32917
32930
  });
32918
32931
  logger?.warn("parallel", "Worktree preserved for manual conflict resolution", {
32919
32932
  storyId: mergeResult.storyId,
32920
- worktreePath: join44(projectRoot, ".nax-wt", mergeResult.storyId)
32933
+ worktreePath: join45(projectRoot, ".nax-wt", mergeResult.storyId)
32921
32934
  });
32922
32935
  }
32923
32936
  }
@@ -33376,12 +33389,12 @@ var init_parallel_executor = __esm(() => {
33376
33389
  // src/pipeline/subscribers/events-writer.ts
33377
33390
  import { appendFile as appendFile2, mkdir as mkdir2 } from "fs/promises";
33378
33391
  import { homedir as homedir7 } from "os";
33379
- import { basename as basename4, join as join45 } from "path";
33392
+ import { basename as basename4, join as join46 } from "path";
33380
33393
  function wireEventsWriter(bus, feature, runId, workdir) {
33381
33394
  const logger = getSafeLogger();
33382
33395
  const project = basename4(workdir);
33383
- const eventsDir = join45(homedir7(), ".nax", "events", project);
33384
- const eventsFile = join45(eventsDir, "events.jsonl");
33396
+ const eventsDir = join46(homedir7(), ".nax", "events", project);
33397
+ const eventsFile = join46(eventsDir, "events.jsonl");
33385
33398
  let dirReady = false;
33386
33399
  const write = (line) => {
33387
33400
  (async () => {
@@ -33541,12 +33554,12 @@ var init_interaction2 = __esm(() => {
33541
33554
  // src/pipeline/subscribers/registry.ts
33542
33555
  import { mkdir as mkdir3, writeFile } from "fs/promises";
33543
33556
  import { homedir as homedir8 } from "os";
33544
- import { basename as basename5, join as join46 } from "path";
33557
+ import { basename as basename5, join as join47 } from "path";
33545
33558
  function wireRegistry(bus, feature, runId, workdir) {
33546
33559
  const logger = getSafeLogger();
33547
33560
  const project = basename5(workdir);
33548
- const runDir = join46(homedir8(), ".nax", "runs", `${project}-${feature}-${runId}`);
33549
- const metaFile = join46(runDir, "meta.json");
33561
+ const runDir = join47(homedir8(), ".nax", "runs", `${project}-${feature}-${runId}`);
33562
+ const metaFile = join47(runDir, "meta.json");
33550
33563
  const unsub = bus.on("run:started", (_ev) => {
33551
33564
  (async () => {
33552
33565
  try {
@@ -33556,8 +33569,8 @@ function wireRegistry(bus, feature, runId, workdir) {
33556
33569
  project,
33557
33570
  feature,
33558
33571
  workdir,
33559
- statusPath: join46(workdir, "nax", "features", feature, "status.json"),
33560
- eventsDir: join46(workdir, "nax", "features", feature, "runs"),
33572
+ statusPath: join47(workdir, "nax", "features", feature, "status.json"),
33573
+ eventsDir: join47(workdir, "nax", "features", feature, "runs"),
33561
33574
  registeredAt: new Date().toISOString()
33562
33575
  };
33563
33576
  await writeFile(metaFile, JSON.stringify(meta3, null, 2));
@@ -34553,7 +34566,7 @@ async function writeStatusFile(filePath, status) {
34553
34566
  var init_status_file = () => {};
34554
34567
 
34555
34568
  // src/execution/status-writer.ts
34556
- import { join as join47 } from "path";
34569
+ import { join as join48 } from "path";
34557
34570
 
34558
34571
  class StatusWriter {
34559
34572
  statusFile;
@@ -34621,7 +34634,7 @@ class StatusWriter {
34621
34634
  if (!this._prd)
34622
34635
  return;
34623
34636
  const safeLogger = getSafeLogger();
34624
- const featureStatusPath = join47(featureDir, "status.json");
34637
+ const featureStatusPath = join48(featureDir, "status.json");
34625
34638
  try {
34626
34639
  const base = this.getSnapshot(totalCost, iterations);
34627
34640
  if (!base) {
@@ -34962,6 +34975,10 @@ async function setupRun(options) {
34962
34975
  getStoriesCompleted: options.getStoriesCompleted,
34963
34976
  emitError: (reason) => {
34964
34977
  pipelineEventBus.emit({ type: "run:errored", reason, feature: options.feature });
34978
+ },
34979
+ onShutdown: async () => {
34980
+ const { sweepFeatureSessions: sweepFeatureSessions2 } = await Promise.resolve().then(() => (init_adapter2(), exports_adapter));
34981
+ await sweepFeatureSessions2(workdir, feature).catch(() => {});
34965
34982
  }
34966
34983
  });
34967
34984
  let prd = await loadPRD(prdPath);
@@ -65946,7 +65963,7 @@ var require_jsx_dev_runtime = __commonJS((exports, module) => {
65946
65963
  init_source();
65947
65964
  import { existsSync as existsSync34, mkdirSync as mkdirSync6 } from "fs";
65948
65965
  import { homedir as homedir10 } from "os";
65949
- import { join as join48 } from "path";
65966
+ import { join as join49 } from "path";
65950
65967
 
65951
65968
  // node_modules/commander/esm.mjs
65952
65969
  var import__ = __toESM(require_commander(), 1);
@@ -66817,10 +66834,11 @@ async function generateFor(agent, options, config2) {
66817
66834
  return { agent, outputFile: generator.outputFile, content: "", written: false, error: error48 };
66818
66835
  }
66819
66836
  }
66820
- async function generateAll(options, config2) {
66837
+ async function generateAll(options, config2, agentFilter) {
66821
66838
  const context = await loadContextContent(options, config2);
66822
66839
  const results = [];
66823
- for (const [agentKey, generator] of Object.entries(GENERATORS)) {
66840
+ const entries = Object.entries(GENERATORS).filter(([agentKey]) => !agentFilter || agentFilter.length === 0 || agentFilter.includes(agentKey));
66841
+ for (const [agentKey, generator] of entries) {
66824
66842
  try {
66825
66843
  const content = generator.generate(context);
66826
66844
  const outputPath = join11(options.outputDir, generator.outputFile);
@@ -66922,34 +66940,42 @@ async function discoverWorkspacePackages(repoRoot) {
66922
66940
  async function generateForPackage(packageDir, config2, dryRun = false) {
66923
66941
  const contextPath = join11(packageDir, "nax", "context.md");
66924
66942
  if (!existsSync10(contextPath)) {
66925
- return {
66926
- packageDir,
66927
- outputFile: "CLAUDE.md",
66928
- content: "",
66929
- written: false,
66930
- error: `context.md not found: ${contextPath}`
66931
- };
66943
+ return [
66944
+ {
66945
+ packageDir,
66946
+ outputFile: "CLAUDE.md",
66947
+ content: "",
66948
+ written: false,
66949
+ error: `context.md not found: ${contextPath}`
66950
+ }
66951
+ ];
66932
66952
  }
66933
- try {
66934
- const options = {
66935
- contextPath,
66936
- outputDir: packageDir,
66937
- workdir: packageDir,
66938
- dryRun,
66939
- autoInject: true
66940
- };
66941
- const result = await generateFor("claude", options, config2);
66942
- return {
66943
- packageDir,
66944
- outputFile: result.outputFile,
66945
- content: result.content,
66946
- written: result.written,
66947
- error: result.error
66948
- };
66949
- } catch (err) {
66950
- const error48 = err instanceof Error ? err.message : String(err);
66951
- return { packageDir, outputFile: "CLAUDE.md", content: "", written: false, error: error48 };
66953
+ const agentsToGenerate = config2?.generate?.agents && config2.generate.agents.length > 0 ? config2.generate.agents : ["claude"];
66954
+ const options = {
66955
+ contextPath,
66956
+ outputDir: packageDir,
66957
+ workdir: packageDir,
66958
+ dryRun,
66959
+ autoInject: true
66960
+ };
66961
+ const results = [];
66962
+ for (const agent of agentsToGenerate) {
66963
+ try {
66964
+ const result = await generateFor(agent, options, config2);
66965
+ results.push({
66966
+ packageDir,
66967
+ outputFile: result.outputFile,
66968
+ content: result.content,
66969
+ written: result.written,
66970
+ error: result.error
66971
+ });
66972
+ } catch (err) {
66973
+ const error48 = err instanceof Error ? err.message : String(err);
66974
+ const fallbackFile = GENERATORS[agent]?.outputFile ?? `${agent}.md`;
66975
+ results.push({ packageDir, outputFile: fallbackFile, content: "", written: false, error: error48 });
66976
+ }
66952
66977
  }
66978
+ return results;
66953
66979
  }
66954
66980
 
66955
66981
  // src/cli/plan.ts
@@ -68006,7 +68032,7 @@ async function runsShowCommand(options) {
68006
68032
  // src/cli/prompts-main.ts
68007
68033
  init_logger2();
68008
68034
  import { existsSync as existsSync18, mkdirSync as mkdirSync3 } from "fs";
68009
- import { join as join27 } from "path";
68035
+ import { join as join28 } from "path";
68010
68036
 
68011
68037
  // src/pipeline/index.ts
68012
68038
  init_runner();
@@ -68042,7 +68068,7 @@ init_prd();
68042
68068
 
68043
68069
  // src/cli/prompts-tdd.ts
68044
68070
  init_prompts2();
68045
- import { join as join26 } from "path";
68071
+ import { join as join27 } from "path";
68046
68072
  async function handleThreeSessionTddPrompts(story, ctx, outputDir, logger) {
68047
68073
  const [testWriterPrompt, implementerPrompt, verifierPrompt] = await Promise.all([
68048
68074
  PromptBuilder.for("test-writer", { isolation: "strict" }).withLoader(ctx.workdir, ctx.config).story(story).context(ctx.contextMarkdown).constitution(ctx.constitution?.content).testCommand(ctx.config.quality?.commands?.test).build(),
@@ -68061,7 +68087,7 @@ ${frontmatter}---
68061
68087
 
68062
68088
  ${session.prompt}`;
68063
68089
  if (outputDir) {
68064
- const promptFile = join26(outputDir, `${story.id}.${session.role}.md`);
68090
+ const promptFile = join27(outputDir, `${story.id}.${session.role}.md`);
68065
68091
  await Bun.write(promptFile, fullOutput);
68066
68092
  logger.info("cli", "Written TDD prompt file", {
68067
68093
  storyId: story.id,
@@ -68077,7 +68103,7 @@ ${"=".repeat(80)}`);
68077
68103
  }
68078
68104
  }
68079
68105
  if (outputDir && ctx.contextMarkdown) {
68080
- const contextFile = join26(outputDir, `${story.id}.context.md`);
68106
+ const contextFile = join27(outputDir, `${story.id}.context.md`);
68081
68107
  const frontmatter = buildFrontmatter(story, ctx);
68082
68108
  const contextOutput = `---
68083
68109
  ${frontmatter}---
@@ -68091,12 +68117,12 @@ ${ctx.contextMarkdown}`;
68091
68117
  async function promptsCommand(options) {
68092
68118
  const logger = getLogger();
68093
68119
  const { feature, workdir, config: config2, storyId, outputDir } = options;
68094
- const naxDir = join27(workdir, "nax");
68120
+ const naxDir = join28(workdir, "nax");
68095
68121
  if (!existsSync18(naxDir)) {
68096
68122
  throw new Error(`nax directory not found. Run 'nax init' first in ${workdir}`);
68097
68123
  }
68098
- const featureDir = join27(naxDir, "features", feature);
68099
- const prdPath = join27(featureDir, "prd.json");
68124
+ const featureDir = join28(naxDir, "features", feature);
68125
+ const prdPath = join28(featureDir, "prd.json");
68100
68126
  if (!existsSync18(prdPath)) {
68101
68127
  throw new Error(`Feature "${feature}" not found or missing prd.json`);
68102
68128
  }
@@ -68156,10 +68182,10 @@ ${frontmatter}---
68156
68182
 
68157
68183
  ${ctx.prompt}`;
68158
68184
  if (outputDir) {
68159
- const promptFile = join27(outputDir, `${story.id}.prompt.md`);
68185
+ const promptFile = join28(outputDir, `${story.id}.prompt.md`);
68160
68186
  await Bun.write(promptFile, fullOutput);
68161
68187
  if (ctx.contextMarkdown) {
68162
- const contextFile = join27(outputDir, `${story.id}.context.md`);
68188
+ const contextFile = join28(outputDir, `${story.id}.context.md`);
68163
68189
  const contextOutput = `---
68164
68190
  ${frontmatter}---
68165
68191
 
@@ -68223,7 +68249,7 @@ function buildFrontmatter(story, ctx, role) {
68223
68249
  }
68224
68250
  // src/cli/prompts-init.ts
68225
68251
  import { existsSync as existsSync19, mkdirSync as mkdirSync4 } from "fs";
68226
- import { join as join28 } from "path";
68252
+ import { join as join29 } from "path";
68227
68253
  var TEMPLATE_ROLES = [
68228
68254
  { file: "test-writer.md", role: "test-writer" },
68229
68255
  { file: "implementer.md", role: "implementer", variant: "standard" },
@@ -68247,9 +68273,9 @@ var TEMPLATE_HEADER = `<!--
68247
68273
  `;
68248
68274
  async function promptsInitCommand(options) {
68249
68275
  const { workdir, force = false, autoWireConfig = true } = options;
68250
- const templatesDir = join28(workdir, "nax", "templates");
68276
+ const templatesDir = join29(workdir, "nax", "templates");
68251
68277
  mkdirSync4(templatesDir, { recursive: true });
68252
- const existingFiles = TEMPLATE_ROLES.map((t) => t.file).filter((f) => existsSync19(join28(templatesDir, f)));
68278
+ const existingFiles = TEMPLATE_ROLES.map((t) => t.file).filter((f) => existsSync19(join29(templatesDir, f)));
68253
68279
  if (existingFiles.length > 0 && !force) {
68254
68280
  console.warn(`[WARN] nax/templates/ already contains files: ${existingFiles.join(", ")}. No files overwritten.
68255
68281
  Pass --force to overwrite existing templates.`);
@@ -68257,7 +68283,7 @@ async function promptsInitCommand(options) {
68257
68283
  }
68258
68284
  const written = [];
68259
68285
  for (const template of TEMPLATE_ROLES) {
68260
- const filePath = join28(templatesDir, template.file);
68286
+ const filePath = join29(templatesDir, template.file);
68261
68287
  const roleBody = template.role === "implementer" ? buildRoleTaskSection(template.role, template.variant) : buildRoleTaskSection(template.role);
68262
68288
  const content = TEMPLATE_HEADER + roleBody;
68263
68289
  await Bun.write(filePath, content);
@@ -68273,7 +68299,7 @@ async function promptsInitCommand(options) {
68273
68299
  return written;
68274
68300
  }
68275
68301
  async function autoWirePromptsConfig(workdir) {
68276
- const configPath = join28(workdir, "nax.config.json");
68302
+ const configPath = join29(workdir, "nax.config.json");
68277
68303
  if (!existsSync19(configPath)) {
68278
68304
  const exampleConfig = JSON.stringify({
68279
68305
  prompts: {
@@ -68438,7 +68464,7 @@ init_config();
68438
68464
  init_logger2();
68439
68465
  init_prd();
68440
68466
  import { existsSync as existsSync21, readdirSync as readdirSync5 } from "fs";
68441
- import { join as join32 } from "path";
68467
+ import { join as join33 } from "path";
68442
68468
 
68443
68469
  // src/cli/diagnose-analysis.ts
68444
68470
  function detectFailurePattern(story, prd, status) {
@@ -68637,7 +68663,7 @@ function isProcessAlive2(pid) {
68637
68663
  }
68638
68664
  }
68639
68665
  async function loadStatusFile2(workdir) {
68640
- const statusPath = join32(workdir, "nax", "status.json");
68666
+ const statusPath = join33(workdir, "nax", "status.json");
68641
68667
  if (!existsSync21(statusPath))
68642
68668
  return null;
68643
68669
  try {
@@ -68665,7 +68691,7 @@ async function countCommitsSince(workdir, since) {
68665
68691
  }
68666
68692
  }
68667
68693
  async function checkLock(workdir) {
68668
- const lockFile = Bun.file(join32(workdir, "nax.lock"));
68694
+ const lockFile = Bun.file(join33(workdir, "nax.lock"));
68669
68695
  if (!await lockFile.exists())
68670
68696
  return { lockPresent: false };
68671
68697
  try {
@@ -68683,8 +68709,8 @@ async function diagnoseCommand(options = {}) {
68683
68709
  const logger = getLogger();
68684
68710
  const workdir = options.workdir ?? process.cwd();
68685
68711
  const naxSubdir = findProjectDir(workdir);
68686
- let projectDir = naxSubdir ? join32(naxSubdir, "..") : null;
68687
- if (!projectDir && existsSync21(join32(workdir, "nax"))) {
68712
+ let projectDir = naxSubdir ? join33(naxSubdir, "..") : null;
68713
+ if (!projectDir && existsSync21(join33(workdir, "nax"))) {
68688
68714
  projectDir = workdir;
68689
68715
  }
68690
68716
  if (!projectDir)
@@ -68695,7 +68721,7 @@ async function diagnoseCommand(options = {}) {
68695
68721
  if (status2) {
68696
68722
  feature = status2.run.feature;
68697
68723
  } else {
68698
- const featuresDir = join32(projectDir, "nax", "features");
68724
+ const featuresDir = join33(projectDir, "nax", "features");
68699
68725
  if (!existsSync21(featuresDir))
68700
68726
  throw new Error("No features found in project");
68701
68727
  const features = readdirSync5(featuresDir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
@@ -68705,8 +68731,8 @@ async function diagnoseCommand(options = {}) {
68705
68731
  logger.info("diagnose", "No feature specified, using first found", { feature });
68706
68732
  }
68707
68733
  }
68708
- const featureDir = join32(projectDir, "nax", "features", feature);
68709
- const prdPath = join32(featureDir, "prd.json");
68734
+ const featureDir = join33(projectDir, "nax", "features", feature);
68735
+ const prdPath = join33(featureDir, "prd.json");
68710
68736
  if (!existsSync21(prdPath))
68711
68737
  throw new Error(`Feature not found: ${feature}`);
68712
68738
  const prd = await loadPRD(prdPath);
@@ -68749,7 +68775,7 @@ init_interaction();
68749
68775
  init_source();
68750
68776
  init_loader2();
68751
68777
  import { existsSync as existsSync22 } from "fs";
68752
- import { join as join33 } from "path";
68778
+ import { join as join34 } from "path";
68753
68779
  var VALID_AGENTS = ["claude", "codex", "opencode", "cursor", "windsurf", "aider", "gemini"];
68754
68780
  async function generateCommand(options) {
68755
68781
  const workdir = process.cwd();
@@ -68770,16 +68796,18 @@ async function generateCommand(options) {
68770
68796
  console.log(source_default.yellow(" No packages found (no */nax/context.md or */*/nax/context.md)"));
68771
68797
  return;
68772
68798
  }
68773
- console.log(source_default.blue(`\u2192 Generating CLAUDE.md for ${packages.length} package(s)...`));
68799
+ console.log(source_default.blue(`\u2192 Generating agent files for ${packages.length} package(s)...`));
68774
68800
  let errorCount = 0;
68775
68801
  for (const pkgDir of packages) {
68776
- const result = await generateForPackage(pkgDir, config2, dryRun);
68777
- if (result.error) {
68778
- console.error(source_default.red(`\u2717 ${pkgDir}: ${result.error}`));
68779
- errorCount++;
68780
- } else {
68781
- const suffix = dryRun ? " (dry run)" : "";
68782
- console.log(source_default.green(`\u2713 ${pkgDir}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68802
+ const results = await generateForPackage(pkgDir, config2, dryRun);
68803
+ for (const result of results) {
68804
+ if (result.error) {
68805
+ console.error(source_default.red(`\u2717 ${pkgDir}: ${result.error}`));
68806
+ errorCount++;
68807
+ } else {
68808
+ const suffix = dryRun ? " (dry run)" : "";
68809
+ console.log(source_default.green(`\u2713 ${pkgDir}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68810
+ }
68783
68811
  }
68784
68812
  }
68785
68813
  if (errorCount > 0) {
@@ -68790,22 +68818,28 @@ async function generateCommand(options) {
68790
68818
  return;
68791
68819
  }
68792
68820
  if (options.package) {
68793
- const packageDir = join33(workdir, options.package);
68821
+ const packageDir = join34(workdir, options.package);
68794
68822
  if (dryRun) {
68795
68823
  console.log(source_default.yellow("\u26A0 Dry run \u2014 no files will be written"));
68796
68824
  }
68797
- console.log(source_default.blue(`\u2192 Generating CLAUDE.md for package: ${options.package}`));
68798
- const result = await generateForPackage(packageDir, config2, dryRun);
68799
- if (result.error) {
68800
- console.error(source_default.red(`\u2717 ${result.error}`));
68801
- process.exit(1);
68825
+ console.log(source_default.blue(`\u2192 Generating agent files for package: ${options.package}`));
68826
+ const pkgResults = await generateForPackage(packageDir, config2, dryRun);
68827
+ let pkgHasError = false;
68828
+ for (const result of pkgResults) {
68829
+ if (result.error) {
68830
+ console.error(source_default.red(`\u2717 ${result.error}`));
68831
+ pkgHasError = true;
68832
+ } else {
68833
+ const suffix = dryRun ? " (dry run)" : "";
68834
+ console.log(source_default.green(`\u2713 ${options.package}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68835
+ }
68802
68836
  }
68803
- const suffix = dryRun ? " (dry run)" : "";
68804
- console.log(source_default.green(`\u2713 ${options.package}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68837
+ if (pkgHasError)
68838
+ process.exit(1);
68805
68839
  return;
68806
68840
  }
68807
- const contextPath = options.context ? join33(workdir, options.context) : join33(workdir, "nax/context.md");
68808
- const outputDir = options.output ? join33(workdir, options.output) : workdir;
68841
+ const contextPath = options.context ? join34(workdir, options.context) : join34(workdir, "nax/context.md");
68842
+ const outputDir = options.output ? join34(workdir, options.output) : workdir;
68809
68843
  const autoInject = !options.noAutoInject;
68810
68844
  if (!existsSync22(contextPath)) {
68811
68845
  console.error(source_default.red(`\u2717 Context file not found: ${contextPath}`));
@@ -68856,8 +68890,7 @@ async function generateCommand(options) {
68856
68890
  } else {
68857
68891
  console.log(source_default.blue("\u2192 Generating configs for all agents..."));
68858
68892
  }
68859
- const allResults = await generateAll(genOptions, config2);
68860
- const results = agentFilter ? allResults.filter((r) => agentFilter.includes(r.agent)) : allResults;
68893
+ const results = await generateAll(genOptions, config2, agentFilter ?? undefined);
68861
68894
  let errorCount = 0;
68862
68895
  for (const result of results) {
68863
68896
  if (result.error) {
@@ -68876,17 +68909,19 @@ async function generateCommand(options) {
68876
68909
  const packages = await discoverPackages(workdir);
68877
68910
  if (packages.length > 0) {
68878
68911
  console.log(source_default.blue(`
68879
- \u2192 Discovered ${packages.length} package(s) with nax/context.md \u2014 generating CLAUDE.md...`));
68912
+ \u2192 Discovered ${packages.length} package(s) with nax/context.md \u2014 generating agent files...`));
68880
68913
  let pkgErrorCount = 0;
68881
68914
  for (const pkgDir of packages) {
68882
- const result = await generateForPackage(pkgDir, config2, dryRun);
68883
- if (result.error) {
68884
- console.error(source_default.red(`\u2717 ${pkgDir}: ${result.error}`));
68885
- pkgErrorCount++;
68886
- } else {
68887
- const suffix = dryRun ? " (dry run)" : "";
68888
- const rel = pkgDir.startsWith(workdir) ? pkgDir.slice(workdir.length + 1) : pkgDir;
68889
- console.log(source_default.green(`\u2713 ${rel}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68915
+ const pkgResults = await generateForPackage(pkgDir, config2, dryRun);
68916
+ for (const result of pkgResults) {
68917
+ if (result.error) {
68918
+ console.error(source_default.red(`\u2717 ${pkgDir}: ${result.error}`));
68919
+ pkgErrorCount++;
68920
+ } else {
68921
+ const suffix = dryRun ? " (dry run)" : "";
68922
+ const rel = pkgDir.startsWith(workdir) ? pkgDir.slice(workdir.length + 1) : pkgDir;
68923
+ console.log(source_default.green(`\u2713 ${rel}/${result.outputFile} (${result.content.length} bytes${suffix})`));
68924
+ }
68890
68925
  }
68891
68926
  }
68892
68927
  if (pkgErrorCount > 0) {
@@ -68909,7 +68944,7 @@ async function generateCommand(options) {
68909
68944
  // src/cli/config-display.ts
68910
68945
  init_loader2();
68911
68946
  import { existsSync as existsSync24 } from "fs";
68912
- import { join as join35 } from "path";
68947
+ import { join as join36 } from "path";
68913
68948
 
68914
68949
  // src/cli/config-descriptions.ts
68915
68950
  var FIELD_DESCRIPTIONS = {
@@ -69118,7 +69153,7 @@ function deepEqual(a, b) {
69118
69153
  init_defaults();
69119
69154
  init_loader2();
69120
69155
  import { existsSync as existsSync23 } from "fs";
69121
- import { join as join34 } from "path";
69156
+ import { join as join35 } from "path";
69122
69157
  async function loadConfigFile(path14) {
69123
69158
  if (!existsSync23(path14))
69124
69159
  return null;
@@ -69140,7 +69175,7 @@ async function loadProjectConfig() {
69140
69175
  const projectDir = findProjectDir();
69141
69176
  if (!projectDir)
69142
69177
  return null;
69143
- const projectPath = join34(projectDir, "config.json");
69178
+ const projectPath = join35(projectDir, "config.json");
69144
69179
  return await loadConfigFile(projectPath);
69145
69180
  }
69146
69181
 
@@ -69200,7 +69235,7 @@ async function configCommand(config2, options = {}) {
69200
69235
  function determineConfigSources() {
69201
69236
  const globalPath = globalConfigPath();
69202
69237
  const projectDir = findProjectDir();
69203
- const projectPath = projectDir ? join35(projectDir, "config.json") : null;
69238
+ const projectPath = projectDir ? join36(projectDir, "config.json") : null;
69204
69239
  return {
69205
69240
  global: fileExists(globalPath) ? globalPath : null,
69206
69241
  project: projectPath && fileExists(projectPath) ? projectPath : null
@@ -69380,21 +69415,21 @@ async function diagnose(options) {
69380
69415
 
69381
69416
  // src/commands/logs.ts
69382
69417
  import { existsSync as existsSync26 } from "fs";
69383
- import { join as join38 } from "path";
69418
+ import { join as join39 } from "path";
69384
69419
 
69385
69420
  // src/commands/logs-formatter.ts
69386
69421
  init_source();
69387
69422
  init_formatter();
69388
69423
  import { readdirSync as readdirSync7 } from "fs";
69389
- import { join as join37 } from "path";
69424
+ import { join as join38 } from "path";
69390
69425
 
69391
69426
  // src/commands/logs-reader.ts
69392
69427
  import { existsSync as existsSync25, readdirSync as readdirSync6 } from "fs";
69393
69428
  import { readdir as readdir3 } from "fs/promises";
69394
69429
  import { homedir as homedir5 } from "os";
69395
- import { join as join36 } from "path";
69430
+ import { join as join37 } from "path";
69396
69431
  var _deps7 = {
69397
- getRunsDir: () => process.env.NAX_RUNS_DIR ?? join36(homedir5(), ".nax", "runs")
69432
+ getRunsDir: () => process.env.NAX_RUNS_DIR ?? join37(homedir5(), ".nax", "runs")
69398
69433
  };
69399
69434
  async function resolveRunFileFromRegistry(runId) {
69400
69435
  const runsDir = _deps7.getRunsDir();
@@ -69406,7 +69441,7 @@ async function resolveRunFileFromRegistry(runId) {
69406
69441
  }
69407
69442
  let matched = null;
69408
69443
  for (const entry of entries) {
69409
- const metaPath = join36(runsDir, entry, "meta.json");
69444
+ const metaPath = join37(runsDir, entry, "meta.json");
69410
69445
  try {
69411
69446
  const meta3 = await Bun.file(metaPath).json();
69412
69447
  if (meta3.runId === runId || meta3.runId.startsWith(runId)) {
@@ -69428,14 +69463,14 @@ async function resolveRunFileFromRegistry(runId) {
69428
69463
  return null;
69429
69464
  }
69430
69465
  const specificFile = files.find((f) => f === `${matched.runId}.jsonl`);
69431
- return join36(matched.eventsDir, specificFile ?? files[0]);
69466
+ return join37(matched.eventsDir, specificFile ?? files[0]);
69432
69467
  }
69433
69468
  async function selectRunFile(runsDir) {
69434
69469
  const files = readdirSync6(runsDir).filter((f) => f.endsWith(".jsonl") && f !== "latest.jsonl").sort().reverse();
69435
69470
  if (files.length === 0) {
69436
69471
  return null;
69437
69472
  }
69438
- return join36(runsDir, files[0]);
69473
+ return join37(runsDir, files[0]);
69439
69474
  }
69440
69475
  async function extractRunSummary(filePath) {
69441
69476
  const file2 = Bun.file(filePath);
@@ -69520,7 +69555,7 @@ Runs:
69520
69555
  console.log(source_default.gray(" Timestamp Stories Duration Cost Status"));
69521
69556
  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"));
69522
69557
  for (const file2 of files) {
69523
- const filePath = join37(runsDir, file2);
69558
+ const filePath = join38(runsDir, file2);
69524
69559
  const summary = await extractRunSummary(filePath);
69525
69560
  const timestamp = file2.replace(".jsonl", "");
69526
69561
  const stories = summary ? `${summary.passed}/${summary.total}` : "?/?";
@@ -69645,7 +69680,7 @@ async function logsCommand(options) {
69645
69680
  return;
69646
69681
  }
69647
69682
  const resolved = resolveProject({ dir: options.dir });
69648
- const naxDir = join38(resolved.projectDir, "nax");
69683
+ const naxDir = join39(resolved.projectDir, "nax");
69649
69684
  const configPath = resolved.configPath;
69650
69685
  const configFile = Bun.file(configPath);
69651
69686
  const config2 = await configFile.json();
@@ -69653,8 +69688,8 @@ async function logsCommand(options) {
69653
69688
  if (!featureName) {
69654
69689
  throw new Error("No feature specified in config.json");
69655
69690
  }
69656
- const featureDir = join38(naxDir, "features", featureName);
69657
- const runsDir = join38(featureDir, "runs");
69691
+ const featureDir = join39(naxDir, "features", featureName);
69692
+ const runsDir = join39(featureDir, "runs");
69658
69693
  if (!existsSync26(runsDir)) {
69659
69694
  throw new Error(`No runs directory found for feature: ${featureName}`);
69660
69695
  }
@@ -69679,7 +69714,7 @@ init_config();
69679
69714
  init_prd();
69680
69715
  init_precheck();
69681
69716
  import { existsSync as existsSync31 } from "fs";
69682
- import { join as join39 } from "path";
69717
+ import { join as join40 } from "path";
69683
69718
  async function precheckCommand(options) {
69684
69719
  const resolved = resolveProject({
69685
69720
  dir: options.dir,
@@ -69695,9 +69730,9 @@ async function precheckCommand(options) {
69695
69730
  process.exit(1);
69696
69731
  }
69697
69732
  }
69698
- const naxDir = join39(resolved.projectDir, "nax");
69699
- const featureDir = join39(naxDir, "features", featureName);
69700
- const prdPath = join39(featureDir, "prd.json");
69733
+ const naxDir = join40(resolved.projectDir, "nax");
69734
+ const featureDir = join40(naxDir, "features", featureName);
69735
+ const prdPath = join40(featureDir, "prd.json");
69701
69736
  if (!existsSync31(featureDir)) {
69702
69737
  console.error(source_default.red(`Feature not found: ${featureName}`));
69703
69738
  process.exit(1);
@@ -69721,10 +69756,10 @@ async function precheckCommand(options) {
69721
69756
  init_source();
69722
69757
  import { readdir as readdir4 } from "fs/promises";
69723
69758
  import { homedir as homedir6 } from "os";
69724
- import { join as join40 } from "path";
69759
+ import { join as join41 } from "path";
69725
69760
  var DEFAULT_LIMIT = 20;
69726
69761
  var _deps9 = {
69727
- getRunsDir: () => join40(homedir6(), ".nax", "runs")
69762
+ getRunsDir: () => join41(homedir6(), ".nax", "runs")
69728
69763
  };
69729
69764
  function formatDuration3(ms) {
69730
69765
  if (ms <= 0)
@@ -69776,7 +69811,7 @@ async function runsCommand(options = {}) {
69776
69811
  }
69777
69812
  const rows = [];
69778
69813
  for (const entry of entries) {
69779
- const metaPath = join40(runsDir, entry, "meta.json");
69814
+ const metaPath = join41(runsDir, entry, "meta.json");
69780
69815
  let meta3;
69781
69816
  try {
69782
69817
  meta3 = await Bun.file(metaPath).json();
@@ -69853,7 +69888,7 @@ async function runsCommand(options = {}) {
69853
69888
 
69854
69889
  // src/commands/unlock.ts
69855
69890
  init_source();
69856
- import { join as join41 } from "path";
69891
+ import { join as join42 } from "path";
69857
69892
  function isProcessAlive3(pid) {
69858
69893
  try {
69859
69894
  process.kill(pid, 0);
@@ -69868,7 +69903,7 @@ function formatLockAge(ageMs) {
69868
69903
  }
69869
69904
  async function unlockCommand(options) {
69870
69905
  const workdir = options.dir ?? process.cwd();
69871
- const lockPath = join41(workdir, "nax.lock");
69906
+ const lockPath = join42(workdir, "nax.lock");
69872
69907
  const lockFile = Bun.file(lockPath);
69873
69908
  const exists = await lockFile.exists();
69874
69909
  if (!exists) {
@@ -77703,15 +77738,15 @@ Next: nax generate --package ${options.package}`));
77703
77738
  }
77704
77739
  return;
77705
77740
  }
77706
- const naxDir = join48(workdir, "nax");
77741
+ const naxDir = join49(workdir, "nax");
77707
77742
  if (existsSync34(naxDir) && !options.force) {
77708
77743
  console.log(source_default.yellow("nax already initialized. Use --force to overwrite."));
77709
77744
  return;
77710
77745
  }
77711
- mkdirSync6(join48(naxDir, "features"), { recursive: true });
77712
- mkdirSync6(join48(naxDir, "hooks"), { recursive: true });
77713
- await Bun.write(join48(naxDir, "config.json"), JSON.stringify(DEFAULT_CONFIG, null, 2));
77714
- await Bun.write(join48(naxDir, "hooks.json"), JSON.stringify({
77746
+ mkdirSync6(join49(naxDir, "features"), { recursive: true });
77747
+ mkdirSync6(join49(naxDir, "hooks"), { recursive: true });
77748
+ await Bun.write(join49(naxDir, "config.json"), JSON.stringify(DEFAULT_CONFIG, null, 2));
77749
+ await Bun.write(join49(naxDir, "hooks.json"), JSON.stringify({
77715
77750
  hooks: {
77716
77751
  "on-start": { command: 'echo "nax started: $NAX_FEATURE"', enabled: false },
77717
77752
  "on-complete": { command: 'echo "nax complete: $NAX_FEATURE"', enabled: false },
@@ -77719,12 +77754,12 @@ Next: nax generate --package ${options.package}`));
77719
77754
  "on-error": { command: 'echo "nax error: $NAX_REASON"', enabled: false }
77720
77755
  }
77721
77756
  }, null, 2));
77722
- await Bun.write(join48(naxDir, ".gitignore"), `# nax temp files
77757
+ await Bun.write(join49(naxDir, ".gitignore"), `# nax temp files
77723
77758
  *.tmp
77724
77759
  .paused.json
77725
77760
  .nax-verifier-verdict.json
77726
77761
  `);
77727
- await Bun.write(join48(naxDir, "context.md"), `# Project Context
77762
+ await Bun.write(join49(naxDir, "context.md"), `# Project Context
77728
77763
 
77729
77764
  This document defines coding standards, architectural decisions, and forbidden patterns for this project.
77730
77765
  Run \`nax generate\` to regenerate agent config files (CLAUDE.md, AGENTS.md, .cursorrules, etc.) from this file.
@@ -77850,8 +77885,8 @@ program2.command("run").description("Run the orchestration loop for a feature").
77850
77885
  console.error(source_default.red("nax not initialized. Run: nax init"));
77851
77886
  process.exit(1);
77852
77887
  }
77853
- const featureDir = join48(naxDir, "features", options.feature);
77854
- const prdPath = join48(featureDir, "prd.json");
77888
+ const featureDir = join49(naxDir, "features", options.feature);
77889
+ const prdPath = join49(featureDir, "prd.json");
77855
77890
  if (options.plan && options.from) {
77856
77891
  if (existsSync34(prdPath) && !options.force) {
77857
77892
  console.error(source_default.red(`Error: prd.json already exists for feature "${options.feature}".`));
@@ -77873,10 +77908,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
77873
77908
  }
77874
77909
  }
77875
77910
  try {
77876
- const planLogDir = join48(featureDir, "plan");
77911
+ const planLogDir = join49(featureDir, "plan");
77877
77912
  mkdirSync6(planLogDir, { recursive: true });
77878
77913
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
77879
- const planLogPath = join48(planLogDir, `${planLogId}.jsonl`);
77914
+ const planLogPath = join49(planLogDir, `${planLogId}.jsonl`);
77880
77915
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
77881
77916
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
77882
77917
  console.log(source_default.dim(" [Planning phase: generating PRD from spec]"));
@@ -77914,10 +77949,10 @@ program2.command("run").description("Run the orchestration loop for a feature").
77914
77949
  process.exit(1);
77915
77950
  }
77916
77951
  resetLogger();
77917
- const runsDir = join48(featureDir, "runs");
77952
+ const runsDir = join49(featureDir, "runs");
77918
77953
  mkdirSync6(runsDir, { recursive: true });
77919
77954
  const runId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
77920
- const logFilePath = join48(runsDir, `${runId}.jsonl`);
77955
+ const logFilePath = join49(runsDir, `${runId}.jsonl`);
77921
77956
  const isTTY = process.stdout.isTTY ?? false;
77922
77957
  const headlessFlag = options.headless ?? false;
77923
77958
  const headlessEnv = process.env.NAX_HEADLESS === "1";
@@ -77933,7 +77968,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
77933
77968
  config2.autoMode.defaultAgent = options.agent;
77934
77969
  }
77935
77970
  config2.execution.maxIterations = Number.parseInt(options.maxIterations, 10);
77936
- const globalNaxDir = join48(homedir10(), ".nax");
77971
+ const globalNaxDir = join49(homedir10(), ".nax");
77937
77972
  const hooks = await loadHooksConfig(naxDir, globalNaxDir);
77938
77973
  const eventEmitter = new PipelineEventEmitter;
77939
77974
  let tuiInstance;
@@ -77956,7 +77991,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
77956
77991
  } else {
77957
77992
  console.log(source_default.dim(" [Headless mode \u2014 pipe output]"));
77958
77993
  }
77959
- const statusFilePath = join48(workdir, "nax", "status.json");
77994
+ const statusFilePath = join49(workdir, "nax", "status.json");
77960
77995
  let parallel;
77961
77996
  if (options.parallel !== undefined) {
77962
77997
  parallel = Number.parseInt(options.parallel, 10);
@@ -77982,7 +78017,7 @@ program2.command("run").description("Run the orchestration loop for a feature").
77982
78017
  headless: useHeadless,
77983
78018
  skipPrecheck: options.skipPrecheck ?? false
77984
78019
  });
77985
- const latestSymlink = join48(runsDir, "latest.jsonl");
78020
+ const latestSymlink = join49(runsDir, "latest.jsonl");
77986
78021
  try {
77987
78022
  if (existsSync34(latestSymlink)) {
77988
78023
  Bun.spawnSync(["rm", latestSymlink]);
@@ -78020,9 +78055,9 @@ features.command("create <name>").description("Create a new feature").option("-d
78020
78055
  console.error(source_default.red("nax not initialized. Run: nax init"));
78021
78056
  process.exit(1);
78022
78057
  }
78023
- const featureDir = join48(naxDir, "features", name);
78058
+ const featureDir = join49(naxDir, "features", name);
78024
78059
  mkdirSync6(featureDir, { recursive: true });
78025
- await Bun.write(join48(featureDir, "spec.md"), `# Feature: ${name}
78060
+ await Bun.write(join49(featureDir, "spec.md"), `# Feature: ${name}
78026
78061
 
78027
78062
  ## Overview
78028
78063
 
@@ -78030,7 +78065,7 @@ features.command("create <name>").description("Create a new feature").option("-d
78030
78065
 
78031
78066
  ## Acceptance Criteria
78032
78067
  `);
78033
- await Bun.write(join48(featureDir, "plan.md"), `# Plan: ${name}
78068
+ await Bun.write(join49(featureDir, "plan.md"), `# Plan: ${name}
78034
78069
 
78035
78070
  ## Architecture
78036
78071
 
@@ -78038,7 +78073,7 @@ features.command("create <name>").description("Create a new feature").option("-d
78038
78073
 
78039
78074
  ## Dependencies
78040
78075
  `);
78041
- await Bun.write(join48(featureDir, "tasks.md"), `# Tasks: ${name}
78076
+ await Bun.write(join49(featureDir, "tasks.md"), `# Tasks: ${name}
78042
78077
 
78043
78078
  ## US-001: [Title]
78044
78079
 
@@ -78047,7 +78082,7 @@ features.command("create <name>").description("Create a new feature").option("-d
78047
78082
  ### Acceptance Criteria
78048
78083
  - [ ] Criterion 1
78049
78084
  `);
78050
- await Bun.write(join48(featureDir, "progress.txt"), `# Progress: ${name}
78085
+ await Bun.write(join49(featureDir, "progress.txt"), `# Progress: ${name}
78051
78086
 
78052
78087
  Created: ${new Date().toISOString()}
78053
78088
 
@@ -78075,7 +78110,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
78075
78110
  console.error(source_default.red("nax not initialized."));
78076
78111
  process.exit(1);
78077
78112
  }
78078
- const featuresDir = join48(naxDir, "features");
78113
+ const featuresDir = join49(naxDir, "features");
78079
78114
  if (!existsSync34(featuresDir)) {
78080
78115
  console.log(source_default.dim("No features yet."));
78081
78116
  return;
@@ -78090,7 +78125,7 @@ features.command("list").description("List all features").option("-d, --dir <pat
78090
78125
  Features:
78091
78126
  `));
78092
78127
  for (const name of entries) {
78093
- const prdPath = join48(featuresDir, name, "prd.json");
78128
+ const prdPath = join49(featuresDir, name, "prd.json");
78094
78129
  if (existsSync34(prdPath)) {
78095
78130
  const prd = await loadPRD(prdPath);
78096
78131
  const c = countStories(prd);
@@ -78121,10 +78156,10 @@ Use: nax plan -f <feature> --from <spec>`));
78121
78156
  process.exit(1);
78122
78157
  }
78123
78158
  const config2 = await loadConfig(workdir);
78124
- const featureLogDir = join48(naxDir, "features", options.feature, "plan");
78159
+ const featureLogDir = join49(naxDir, "features", options.feature, "plan");
78125
78160
  mkdirSync6(featureLogDir, { recursive: true });
78126
78161
  const planLogId = new Date().toISOString().replace(/:/g, "-").replace(/\..+/, "");
78127
- const planLogPath = join48(featureLogDir, `${planLogId}.jsonl`);
78162
+ const planLogPath = join49(featureLogDir, `${planLogId}.jsonl`);
78128
78163
  initLogger({ level: "info", filePath: planLogPath, useChalk: false, headless: true });
78129
78164
  console.log(source_default.dim(` [Plan log: ${planLogPath}]`));
78130
78165
  try {
@@ -78161,7 +78196,7 @@ program2.command("analyze").description("(deprecated) Parse spec.md into prd.jso
78161
78196
  console.error(source_default.red("nax not initialized. Run: nax init"));
78162
78197
  process.exit(1);
78163
78198
  }
78164
- const featureDir = join48(naxDir, "features", options.feature);
78199
+ const featureDir = join49(naxDir, "features", options.feature);
78165
78200
  if (!existsSync34(featureDir)) {
78166
78201
  console.error(source_default.red(`Feature "${options.feature}" not found.`));
78167
78202
  process.exit(1);
@@ -78177,7 +78212,7 @@ program2.command("analyze").description("(deprecated) Parse spec.md into prd.jso
78177
78212
  specPath: options.from,
78178
78213
  reclassify: options.reclassify
78179
78214
  });
78180
- const prdPath = join48(featureDir, "prd.json");
78215
+ const prdPath = join49(featureDir, "prd.json");
78181
78216
  await Bun.write(prdPath, JSON.stringify(prd, null, 2));
78182
78217
  const c = countStories(prd);
78183
78218
  console.log(source_default.green(`