@nathapp/nax 0.61.2-canary.1 → 0.61.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/nax.js +57 -103
  2. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -2634,17 +2634,6 @@ function formatDuration(durationMs) {
2634
2634
  function formatCost(cost) {
2635
2635
  return `$${cost.toFixed(4)}`;
2636
2636
  }
2637
- function getStageEmoji(stage) {
2638
- if (stage.includes("routing"))
2639
- return EMOJI.routing;
2640
- if (stage.includes("execution") || stage.includes("agent"))
2641
- return EMOJI.execution;
2642
- if (stage.includes("review"))
2643
- return EMOJI.review;
2644
- if (stage.includes("tdd"))
2645
- return EMOJI.tdd;
2646
- return EMOJI.info;
2647
- }
2648
2637
  function shouldDisplay(entry, mode) {
2649
2638
  if (mode === "json")
2650
2639
  return true;
@@ -2685,7 +2674,7 @@ function formatLogEntry(entry, options) {
2685
2674
  }
2686
2675
  return formatDefault(entry, colorize, timestamp, mode);
2687
2676
  }
2688
- function formatRunStart(entry, c, timestamp, mode) {
2677
+ function formatRunStart(entry, c, timestamp, _mode) {
2689
2678
  const data = entry.data;
2690
2679
  const lines = [];
2691
2680
  lines.push("");
@@ -2704,7 +2693,7 @@ function formatRunStart(entry, c, timestamp, mode) {
2704
2693
  shouldDisplay: true
2705
2694
  };
2706
2695
  }
2707
- function formatStoryStart(entry, c, timestamp, mode) {
2696
+ function formatStoryStart(entry, c, _timestamp, mode) {
2708
2697
  const data = entry.data;
2709
2698
  const storyId = String(data.storyId || entry.storyId || "unknown");
2710
2699
  const title = String(data.storyTitle || data.title || "Untitled story");
@@ -2734,7 +2723,7 @@ function formatStoryStart(entry, c, timestamp, mode) {
2734
2723
  shouldDisplay: true
2735
2724
  };
2736
2725
  }
2737
- function formatStoryComplete(entry, c, timestamp, mode) {
2726
+ function formatStoryComplete(entry, c, _timestamp, mode) {
2738
2727
  const data = entry.data;
2739
2728
  const storyId = String(data.storyId || entry.storyId || "unknown");
2740
2729
  const success = data.success ?? true;
@@ -2766,7 +2755,7 @@ function formatStoryComplete(entry, c, timestamp, mode) {
2766
2755
  shouldDisplay: true
2767
2756
  };
2768
2757
  }
2769
- function formatTDDSession(entry, c, timestamp, mode) {
2758
+ function formatTDDSession(entry, c, _timestamp, mode) {
2770
2759
  if (mode === "quiet") {
2771
2760
  return { output: "", shouldDisplay: false };
2772
2761
  }
@@ -2781,7 +2770,6 @@ function formatTDDSession(entry, c, timestamp, mode) {
2781
2770
  function formatDefault(entry, c, timestamp, mode) {
2782
2771
  const levelEmoji = entry.level === "error" ? EMOJI.failure : entry.level === "warn" ? EMOJI.warning : EMOJI.info;
2783
2772
  const levelColor = entry.level === "error" ? c.red : entry.level === "warn" ? c.yellow : c.gray;
2784
- const stageEmoji = getStageEmoji(entry.stage);
2785
2773
  const parts = [c.gray(`[${timestamp}]`), levelColor(`${levelEmoji} ${entry.stage}`)];
2786
2774
  if (entry.storyId) {
2787
2775
  parts.push(c.dim(`[${entry.storyId}]`));
@@ -3626,7 +3614,14 @@ var init_env = __esm(() => {
3626
3614
 
3627
3615
  // src/agents/acp/parser.ts
3628
3616
  function createParseState() {
3629
- return { text: "", tokenUsage: undefined, exactCostUsd: undefined, stopReason: undefined, error: undefined };
3617
+ return {
3618
+ text: "",
3619
+ tokenUsage: undefined,
3620
+ exactCostUsd: undefined,
3621
+ stopReason: undefined,
3622
+ error: undefined,
3623
+ retryable: false
3624
+ };
3630
3625
  }
3631
3626
  function parseAcpxJsonLine(line, state) {
3632
3627
  try {
@@ -3665,6 +3660,8 @@ function parseAcpxJsonLine(line, state) {
3665
3660
  const suffix = [data.acpxCode, data.detailCode].filter(Boolean).join("/");
3666
3661
  if (suffix)
3667
3662
  errorMsg = `${errorMsg} [${suffix}]`;
3663
+ if (!state.error && data.retryable === true)
3664
+ state.retryable = true;
3668
3665
  }
3669
3666
  if (!state.error)
3670
3667
  state.error = errorMsg;
@@ -3703,7 +3700,8 @@ function finalizeParseState(state) {
3703
3700
  tokenUsage: state.tokenUsage,
3704
3701
  exactCostUsd: state.exactCostUsd,
3705
3702
  stopReason: state.stopReason,
3706
- error: state.error
3703
+ error: state.error,
3704
+ retryable: state.retryable
3707
3705
  };
3708
3706
  }
3709
3707
 
@@ -3828,7 +3826,8 @@ class SpawnAcpSession {
3828
3826
  });
3829
3827
  return {
3830
3828
  messages: [{ role: "assistant", content: errorContent }],
3831
- stopReason: "error"
3829
+ stopReason: "error",
3830
+ retryable: parsedOnError.retryable
3832
3831
  };
3833
3832
  }
3834
3833
  try {
@@ -3904,7 +3903,6 @@ class SpawnAcpSession {
3904
3903
  }
3905
3904
 
3906
3905
  class SpawnAcpClient {
3907
- agentName;
3908
3906
  model;
3909
3907
  cwd;
3910
3908
  timeoutSeconds;
@@ -3918,7 +3916,6 @@ class SpawnAcpClient {
3918
3916
  if (!lastToken || lastToken.startsWith("-")) {
3919
3917
  throw new Error(`[acp-adapter] Could not parse agentName from cmdStr: "${cmdStr}"`);
3920
3918
  }
3921
- this.agentName = lastToken;
3922
3919
  this.cwd = cwd || process.cwd();
3923
3920
  this.timeoutSeconds = timeoutSeconds || 1800;
3924
3921
  this.env = buildAllowedEnv();
@@ -4132,17 +4129,6 @@ function estimateCostByDuration(modelTier, durationMs) {
4132
4129
  confidence: "fallback"
4133
4130
  };
4134
4131
  }
4135
- function formatCostWithConfidence(estimate) {
4136
- const formattedCost = `$${estimate.cost.toFixed(2)}`;
4137
- switch (estimate.confidence) {
4138
- case "exact":
4139
- return formattedCost;
4140
- case "estimated":
4141
- return `~${formattedCost}`;
4142
- case "fallback":
4143
- return `~${formattedCost} (duration-based)`;
4144
- }
4145
- }
4146
4132
  function estimateCostFromTokenUsage(usage, model) {
4147
4133
  const pricing = MODEL_PRICING[model];
4148
4134
  if (!pricing) {
@@ -18177,6 +18163,8 @@ var init_schemas3 = __esm(() => {
18177
18163
  iterationDelayMs: exports_external.number().int().nonnegative(),
18178
18164
  costLimit: exports_external.number().positive({ message: "costLimit must be > 0" }),
18179
18165
  sessionTimeoutSeconds: exports_external.number().int().positive({ message: "sessionTimeoutSeconds must be > 0" }).default(3600),
18166
+ sessionErrorMaxRetries: exports_external.number().int().min(0).max(5).default(1),
18167
+ sessionErrorRetryableMaxRetries: exports_external.number().int().min(0).max(10).default(3),
18180
18168
  verificationTimeoutSeconds: exports_external.number().int().min(1).max(3600).default(300),
18181
18169
  maxStoriesPerFeature: exports_external.number().int().positive(),
18182
18170
  rectification: RectificationConfigSchema,
@@ -19095,7 +19083,9 @@ class AcpAgentAdapter {
19095
19083
  });
19096
19084
  let currentAgent = this.resolveCurrentAgent(config2);
19097
19085
  const rateLimitedRetryAfter = new Map;
19098
- let sessionErrorRetried = false;
19086
+ let sessionErrorRetries = 0;
19087
+ const SESSION_ERROR_MAX_RETRIES = config2?.execution?.sessionErrorMaxRetries ?? 1;
19088
+ const SESSION_ERROR_RETRYABLE_MAX_RETRIES = config2?.execution?.sessionErrorRetryableMaxRetries ?? 3;
19099
19089
  let legacyAttempt = 0;
19100
19090
  let retryCount = 0;
19101
19091
  while (true) {
@@ -19106,11 +19096,15 @@ class AcpAgentAdapter {
19106
19096
  exitCode: result.exitCode,
19107
19097
  ...result.output ? { output: result.output.slice(0, 500) } : {}
19108
19098
  });
19109
- if (result.sessionError && _acpAdapterDeps.shouldRetrySessionError && !sessionErrorRetried) {
19110
- sessionErrorRetried = true;
19099
+ const maxSessionRetries = result.sessionErrorRetryable ? SESSION_ERROR_RETRYABLE_MAX_RETRIES : SESSION_ERROR_MAX_RETRIES;
19100
+ if (result.sessionError && _acpAdapterDeps.shouldRetrySessionError && sessionErrorRetries < maxSessionRetries) {
19101
+ sessionErrorRetries += 1;
19111
19102
  getSafeLogger()?.warn("acp-adapter", "Session error \u2014 retrying with fresh session", {
19112
19103
  storyId: options.storyId,
19113
- featureName: options.featureName
19104
+ featureName: options.featureName,
19105
+ retryable: result.sessionErrorRetryable,
19106
+ attempt: sessionErrorRetries,
19107
+ maxAttempts: maxSessionRetries
19114
19108
  });
19115
19109
  if (options.featureName && options.storyId) {
19116
19110
  await clearAcpSession(options.workdir, options.featureName, options.storyId, options.sessionRole);
@@ -19329,6 +19323,7 @@ class AcpAgentAdapter {
19329
19323
  }
19330
19324
  const success2 = lastResponse?.stopReason === "end_turn";
19331
19325
  const isSessionError = lastResponse?.stopReason === "error";
19326
+ const isSessionErrorRetryable = isSessionError && lastResponse?.retryable === true;
19332
19327
  const output = extractOutput(lastResponse);
19333
19328
  const estimatedCost = totalExactCostUsd ?? (totalTokenUsage.input_tokens > 0 || totalTokenUsage.output_tokens > 0 ? estimateCostFromTokenUsage(totalTokenUsage, options.modelDef.model) : 0);
19334
19329
  const tokenUsage = totalTokenUsage.input_tokens > 0 || totalTokenUsage.output_tokens > 0 ? {
@@ -19347,6 +19342,7 @@ class AcpAgentAdapter {
19347
19342
  output: output.slice(-MAX_AGENT_OUTPUT_CHARS),
19348
19343
  rateLimited: false,
19349
19344
  sessionError: isSessionError,
19345
+ sessionErrorRetryable: isSessionErrorRetryable,
19350
19346
  durationMs,
19351
19347
  estimatedCost,
19352
19348
  tokenUsage
@@ -23020,7 +23016,7 @@ class AutoInteractionPlugin {
23020
23016
  };
23021
23017
  }
23022
23018
  async destroy() {}
23023
- async send(request) {}
23019
+ async send(_request) {}
23024
23020
  async receive(_requestId, _timeout = 60000) {
23025
23021
  throw new Error("Auto plugin requires full request context (not just requestId)");
23026
23022
  }
@@ -24518,7 +24514,7 @@ async function checkHomeEnvValid() {
24518
24514
  message: passed ? `HOME env is valid: ${home}` : home === "" ? "HOME env is not set \u2014 agent may write files to unexpected locations" : `HOME env is not an absolute path ("${home}") \u2014 may cause literal "~" directories in repo`
24519
24515
  };
24520
24516
  }
24521
- async function checkLanguageTools(profile, workdir) {
24517
+ async function checkLanguageTools(profile, _workdir) {
24522
24518
  if (!profile || !profile.language) {
24523
24519
  return {
24524
24520
  name: "language-tools-available",
@@ -25247,7 +25243,7 @@ function countStories(prd) {
25247
25243
  decomposed: prd.userStories.filter((s) => s.status === "decomposed").length
25248
25244
  };
25249
25245
  }
25250
- function markStoryPassed(prd, storyId, statusWriter) {
25246
+ function markStoryPassed(prd, storyId, _statusWriter) {
25251
25247
  const story = prd.userStories.find((s) => s.id === storyId);
25252
25248
  if (story) {
25253
25249
  story.passes = true;
@@ -26180,7 +26176,7 @@ function parseAcceptanceCriteria(specContent) {
26180
26176
  }
26181
26177
  return criteria;
26182
26178
  }
26183
- function buildAcceptanceTestPrompt(criteria, featureName, codebaseContext, testPathConfig, language) {
26179
+ function buildAcceptanceTestPrompt(criteria, featureName, _codebaseContext, testPathConfig, language) {
26184
26180
  const criteriaList = criteria.map((ac) => `${ac.id}: ${ac.text}`).join(`
26185
26181
  `);
26186
26182
  const resolvedTestPath = resolveAcceptanceTestFile2(language, testPathConfig);
@@ -26329,7 +26325,7 @@ ${tests || " // No acceptance criteria found"}
26329
26325
  });
26330
26326
  `;
26331
26327
  }
26332
- function generateGoSkeletonTests(featureName, criteria) {
26328
+ function generateGoSkeletonTests(_featureName, criteria) {
26333
26329
  const sanitize = (text) => text.replace(/[^a-zA-Z0-9 ]/g, "").split(" ").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join("");
26334
26330
  const tests = criteria.map((ac) => {
26335
26331
  const funcName = `Test${sanitize(ac.text) || ac.id.replace("-", "")}`;
@@ -27514,40 +27510,8 @@ var init_claude = __esm(() => {
27514
27510
  function validateAgentForTier(agent, tier) {
27515
27511
  return agent.capabilities.supportedTiers.includes(tier);
27516
27512
  }
27517
- function validateAgentFeature(agent, feature) {
27518
- return agent.capabilities.features.has(feature);
27519
- }
27520
- function describeAgentCapabilities(agent) {
27521
- const tiers = agent.capabilities.supportedTiers.join(",");
27522
- const features = Array.from(agent.capabilities.features).join(",");
27523
- const maxTokens = agent.capabilities.maxContextTokens;
27524
- return `${agent.name}: tiers=[${tiers}], maxTokens=${maxTokens}, features=[${features}]`;
27525
- }
27526
27513
 
27527
27514
  // src/agents/index.ts
27528
- var exports_agents = {};
27529
- __export(exports_agents, {
27530
- validateAgentForTier: () => validateAgentForTier,
27531
- validateAgentFeature: () => validateAgentFeature,
27532
- parseTokenUsage: () => parseTokenUsage,
27533
- getInstalledAgents: () => getInstalledAgents,
27534
- getAllAgentNames: () => getAllAgentNames,
27535
- getAgentVersions: () => getAgentVersions,
27536
- getAgentVersion: () => getAgentVersion,
27537
- getAgent: () => getAgent,
27538
- formatCostWithConfidence: () => formatCostWithConfidence,
27539
- estimateCostFromTokenUsage: () => estimateCostFromTokenUsage,
27540
- estimateCostFromOutput: () => estimateCostFromOutput,
27541
- estimateCostByDuration: () => estimateCostByDuration,
27542
- estimateCost: () => estimateCost,
27543
- describeAgentCapabilities: () => describeAgentCapabilities,
27544
- checkAgentHealth: () => checkAgentHealth,
27545
- MODEL_PRICING: () => MODEL_PRICING,
27546
- CompleteError: () => CompleteError,
27547
- ClaudeCodeAdapter: () => ClaudeCodeAdapter,
27548
- COST_RATES: () => COST_RATES,
27549
- AllAgentsUnavailableError: () => AllAgentsUnavailableError
27550
- });
27551
27515
  var init_agents = __esm(() => {
27552
27516
  init_types2();
27553
27517
  init_claude();
@@ -28114,7 +28078,7 @@ ${stat}
28114
28078
  return `${statPreamble}${truncated}
28115
28079
  ... (truncated at ${DIFF_CAP_BYTES} bytes, showing ${visibleFiles}/${totalFiles} files)`;
28116
28080
  }
28117
- function buildPrompt(story, semanticConfig, diff, stat) {
28081
+ function buildPrompt(story, semanticConfig, diff, _stat) {
28118
28082
  const acList = story.acceptanceCriteria.map((ac, i) => `${i + 1}. ${ac}`).join(`
28119
28083
  `);
28120
28084
  const customRulesSection = semanticConfig.rules.length > 0 ? `
@@ -30002,9 +29966,7 @@ function deriveTestPatterns(contextFiles) {
30002
29966
  async function detectTestDir(workdir) {
30003
29967
  for (const dir of COMMON_TEST_DIRS) {
30004
29968
  const fullPath = path7.join(workdir, dir);
30005
- const file3 = Bun.file(path7.join(fullPath, "."));
30006
29969
  try {
30007
- const dirStat = await Bun.file(fullPath).exists();
30008
29970
  const proc = Bun.spawn(["test", "-d", fullPath], { stdout: "pipe", stderr: "pipe" });
30009
29971
  const exitCode = await proc.exited;
30010
29972
  if (exitCode === 0)
@@ -30805,7 +30767,7 @@ function globToRegex(pattern) {
30805
30767
  const regexStr = filePattern.replace(/\./g, "\\.").replace(/\*/g, "[^/]*").replace(/\{([^}]+)\}/g, (_, group) => `(${group.replace(/,/g, "|")})`).replace(/\\\.\\\*/g, "\\.[^/]*");
30806
30768
  return new RegExp(`${regexStr}$`);
30807
30769
  }
30808
- async function isGreenfieldStory(story, workdir, testPattern = "**/*.{test,spec}.{ts,js,tsx,jsx}") {
30770
+ async function isGreenfieldStory(_story, workdir, testPattern = "**/*.{test,spec}.{ts,js,tsx,jsx}") {
30809
30771
  try {
30810
30772
  const regex = globToRegex(testPattern);
30811
30773
  const testFiles = await scanForTestFiles(workdir, regex);
@@ -33423,7 +33385,7 @@ var init_optimizer2 = __esm(() => {
33423
33385
  init_optimizer();
33424
33386
  optimizerStage = {
33425
33387
  name: "optimizer",
33426
- enabled: (ctx) => {
33388
+ enabled: (_ctx) => {
33427
33389
  return true;
33428
33390
  },
33429
33391
  async execute(ctx) {
@@ -34773,7 +34735,7 @@ var init_classify = __esm(() => {
34773
34735
  });
34774
34736
 
34775
34737
  // src/routing/strategies/llm-prompts.ts
34776
- function buildRoutingPrompt(story, config2) {
34738
+ function buildRoutingPrompt(story, _config) {
34777
34739
  const { title, description, acceptanceCriteria, tags } = story;
34778
34740
  const criteria = acceptanceCriteria.map((c, i) => `${i + 1}. ${c}`).join(`
34779
34741
  `);
@@ -34807,7 +34769,7 @@ Respond with:
34807
34769
  {"complexity":"simple|medium|complex|expert","modelTier":"fast|balanced|powerful","reasoning":"<one line>"}`;
34808
34770
  return wrapJsonPrompt(core2);
34809
34771
  }
34810
- function buildBatchRoutingPrompt(stories, config2) {
34772
+ function buildBatchRoutingPrompt(stories, _config) {
34811
34773
  const storyBlocks = stories.map((story, idx) => {
34812
34774
  const criteria = story.acceptanceCriteria.map((c, i) => ` ${i + 1}. ${c}`).join(`
34813
34775
  `);
@@ -36676,7 +36638,7 @@ var package_default;
36676
36638
  var init_package = __esm(() => {
36677
36639
  package_default = {
36678
36640
  name: "@nathapp/nax",
36679
- version: "0.61.2-canary.1",
36641
+ version: "0.61.2",
36680
36642
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
36681
36643
  type: "module",
36682
36644
  bin: {
@@ -36756,8 +36718,8 @@ var init_version = __esm(() => {
36756
36718
  NAX_VERSION = package_default.version;
36757
36719
  NAX_COMMIT = (() => {
36758
36720
  try {
36759
- if (/^[0-9a-f]{6,10}$/.test("7e54444a"))
36760
- return "7e54444a";
36721
+ if (/^[0-9a-f]{6,10}$/.test("16490524"))
36722
+ return "16490524";
36761
36723
  } catch {}
36762
36724
  try {
36763
36725
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -37104,7 +37066,7 @@ function parseImportStatements(content) {
37104
37066
  }
37105
37067
  return imports;
37106
37068
  }
37107
- function resolveImportPaths(imports, workdir) {
37069
+ function resolveImportPaths(imports, _workdir) {
37108
37070
  const resolved = [];
37109
37071
  for (const imp of imports) {
37110
37072
  if (imp.startsWith(".")) {
@@ -38357,7 +38319,7 @@ function wireHooks(bus, hooks, workdir, feature) {
38357
38319
  return fn().catch((err) => logger?.warn("hooks-subscriber", `Hook "${name}" failed`, { error: String(err) })).catch(() => {});
38358
38320
  };
38359
38321
  const unsubs = [];
38360
- unsubs.push(bus.on("run:started", (ev) => {
38322
+ unsubs.push(bus.on("run:started", (_ev) => {
38361
38323
  return safe("on-start", () => fireHook(hooks, "on-start", hookCtx(feature, { status: "running" }), workdir));
38362
38324
  }));
38363
38325
  unsubs.push(bus.on("story:started", (ev) => {
@@ -38378,7 +38340,7 @@ function wireHooks(bus, hooks, workdir, feature) {
38378
38340
  unsubs.push(bus.on("run:completed", (ev) => {
38379
38341
  return safe("on-complete", () => fireHook(hooks, "on-complete", hookCtx(feature, { status: "complete", cost: ev.totalCost ?? 0 }), workdir));
38380
38342
  }));
38381
- unsubs.push(bus.on("run:resumed", (ev) => {
38343
+ unsubs.push(bus.on("run:resumed", (_ev) => {
38382
38344
  return safe("on-resume", () => fireHook(hooks, "on-resume", hookCtx(feature, { status: "running" }), workdir));
38383
38345
  }));
38384
38346
  unsubs.push(bus.on("story:completed", (ev) => {
@@ -39131,7 +39093,6 @@ var init_pipeline_result_handler = __esm(() => {
39131
39093
  // src/execution/iteration-runner.ts
39132
39094
  import { join as join45 } from "path";
39133
39095
  async function runIteration(ctx, prd, selection, iterations, totalCost, allStoryMetrics) {
39134
- const logger = getSafeLogger();
39135
39096
  const { story, storiesToExecute, routing, isBatchExecution } = selection;
39136
39097
  if (ctx.dryRun) {
39137
39098
  const dryRunResult = await handleDryRun({
@@ -39255,7 +39216,6 @@ async function runIteration(ctx, prd, selection, iterations, totalCost, allStory
39255
39216
  var _iterationRunnerDeps;
39256
39217
  var init_iteration_runner = __esm(() => {
39257
39218
  init_loader();
39258
- init_logger2();
39259
39219
  init_runner();
39260
39220
  init_stages();
39261
39221
  init_prd();
@@ -39373,7 +39333,7 @@ async function executeStoryInWorktree(story, worktreePath, context, routing, eve
39373
39333
  };
39374
39334
  }
39375
39335
  }
39376
- async function executeParallelBatch(stories, projectRoot, config2, context, worktreePaths, maxConcurrency, eventEmitter, storyEffectiveConfigs) {
39336
+ async function executeParallelBatch(stories, _projectRoot, config2, context, worktreePaths, maxConcurrency, eventEmitter, storyEffectiveConfigs) {
39377
39337
  const logger = getSafeLogger();
39378
39338
  const results = {
39379
39339
  pipelinePassed: [],
@@ -40524,7 +40484,7 @@ function detectType(pkg) {
40524
40484
  return "cli";
40525
40485
  return;
40526
40486
  }
40527
- async function detectTestFramework(workdir, language, pkg) {
40487
+ async function detectTestFramework(_workdir, language, pkg) {
40528
40488
  if (language === "go")
40529
40489
  return "go-test";
40530
40490
  if (language === "rust")
@@ -40984,7 +40944,6 @@ import { join as join50 } from "path";
40984
40944
  async function reconcileState(prd, prdPath, workdir, config2) {
40985
40945
  const logger = getSafeLogger();
40986
40946
  let reconciledCount = 0;
40987
- let modified = false;
40988
40947
  for (const story of prd.userStories) {
40989
40948
  if (story.status !== "failed")
40990
40949
  continue;
@@ -41019,7 +40978,6 @@ async function reconcileState(prd, prdPath, workdir, config2) {
41019
40978
  });
41020
40979
  markStoryPassed(prd, story.id);
41021
40980
  reconciledCount++;
41022
- modified = true;
41023
40981
  }
41024
40982
  if (reconciledCount > 0) {
41025
40983
  logger?.info("reconciliation", `Reconciled ${reconciledCount} failed stories from git history`);
@@ -41031,7 +40989,6 @@ async function checkAgentInstalled(config2, dryRun, agentGetFn) {
41031
40989
  if (dryRun)
41032
40990
  return;
41033
40991
  const logger = getSafeLogger();
41034
- const { getAgent: getAgent2 } = await Promise.resolve().then(() => (init_agents(), exports_agents));
41035
40992
  const agent = (agentGetFn ?? _reconcileDeps.getAgent)(config2.autoMode.defaultAgent);
41036
40993
  if (!agent) {
41037
40994
  logger?.error("execution", "Agent not found", {
@@ -74892,7 +74849,7 @@ import { existsSync as existsSync22, readdirSync as readdirSync6 } from "fs";
74892
74849
  import { join as join30 } from "path";
74893
74850
 
74894
74851
  // src/cli/diagnose-analysis.ts
74895
- function detectFailurePattern(story, prd, status) {
74852
+ function detectFailurePattern(story, _prd, status) {
74896
74853
  if (story.status === "passed" && story.priorErrors?.some((err) => err.toLowerCase().includes("greenfield-no-tests"))) {
74897
74854
  return "AUTO_RECOVERED";
74898
74855
  }
@@ -76838,7 +76795,6 @@ async function run(options) {
76838
76795
  let totalCost = 0;
76839
76796
  let runCompleted = false;
76840
76797
  const allStoryMetrics = [];
76841
- const logger = getSafeLogger();
76842
76798
  const registry2 = createAgentRegistry(config2);
76843
76799
  const agentGetFn = registry2.getAgent.bind(registry2);
76844
76800
  let prd;
@@ -76939,20 +76895,20 @@ async function run(options) {
76939
76895
  durationMs
76940
76896
  };
76941
76897
  } finally {
76942
- const logger2 = getSafeLogger();
76943
- logger2?.debug("execution", "Runner finally block \u2014 starting cleanup");
76898
+ const logger = getSafeLogger();
76899
+ logger?.debug("execution", "Runner finally block \u2014 starting cleanup");
76944
76900
  stopHeartbeat();
76945
76901
  cleanupCrashHandlers();
76946
- logger2?.debug("execution", "Runner finally \u2014 sweeping ACP sessions");
76902
+ logger?.debug("execution", "Runner finally \u2014 sweeping ACP sessions");
76947
76903
  await sweepFeatureSessions(workdir, feature).catch(() => {});
76948
- logger2?.debug("execution", "Runner finally \u2014 ACP sweep done");
76904
+ logger?.debug("execution", "Runner finally \u2014 ACP sweep done");
76949
76905
  let branch = "";
76950
76906
  try {
76951
76907
  const { stdout, exitCode } = await gitWithTimeout(["branch", "--show-current"], workdir);
76952
76908
  if (exitCode === 0)
76953
76909
  branch = stdout.trim();
76954
76910
  } catch {}
76955
- logger2?.debug("execution", "Runner finally \u2014 running cleanupRun");
76911
+ logger?.debug("execution", "Runner finally \u2014 running cleanupRun");
76956
76912
  const { cleanupRun: cleanupRun2 } = await Promise.resolve().then(() => (init_run_cleanup(), exports_run_cleanup));
76957
76913
  await cleanupRun2({
76958
76914
  runId,
@@ -76969,7 +76925,7 @@ async function run(options) {
76969
76925
  version: NAX_VERSION,
76970
76926
  runCompleted
76971
76927
  });
76972
- logger2?.debug("execution", "Runner finally \u2014 cleanupRun done, run() returning");
76928
+ logger?.debug("execution", "Runner finally \u2014 cleanupRun done, run() returning");
76973
76929
  }
76974
76930
  }
76975
76931
 
@@ -83955,7 +83911,6 @@ function usePty(options) {
83955
83911
  isRunning: false
83956
83912
  }));
83957
83913
  const [handle, setHandle] = import_react33.useState(null);
83958
- const [ptyProcess, setPtyProcess] = import_react33.useState(null);
83959
83914
  const command = options?.command;
83960
83915
  const argsJson = JSON.stringify(options?.args);
83961
83916
  const cwd2 = options?.cwd;
@@ -83971,7 +83926,6 @@ function usePty(options) {
83971
83926
  stdout: "pipe",
83972
83927
  stderr: "inherit"
83973
83928
  });
83974
- setPtyProcess(proc);
83975
83929
  setState((prev) => ({ ...prev, isRunning: true }));
83976
83930
  (async () => {
83977
83931
  let currentLine = "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.61.2-canary.1",
3
+ "version": "0.61.2",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {