@nathapp/nax 0.69.5 → 0.69.6

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 +63 -26
  2. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -39973,26 +39973,23 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
39973
39973
  costUsd: totalCostUsd
39974
39974
  };
39975
39975
  }
39976
- for (const strategy of active) {
39977
- const attempts = countStrategyAttempts(cycle.iterations, strategy.name);
39978
- if (attempts >= strategy.maxAttempts) {
39979
- logger?.info("findings.cycle", "cycle exited \u2014 strategy attempt cap reached", {
39980
- storyId,
39981
- packageDir,
39982
- cycleName,
39983
- reason: "max-attempts-per-strategy",
39984
- exhaustedStrategy: strategy.name,
39985
- attempts,
39986
- maxAttempts: strategy.maxAttempts
39987
- });
39988
- return {
39989
- iterations: cycle.iterations,
39990
- finalFindings: cycle.findings,
39991
- exitReason: "max-attempts-per-strategy",
39992
- exhaustedStrategy: strategy.name,
39993
- costUsd: totalCostUsd
39994
- };
39995
- }
39976
+ const uncappedActive = active.filter((s) => countStrategyAttempts(cycle.iterations, s.name) < s.maxAttempts);
39977
+ if (uncappedActive.length === 0) {
39978
+ const exhaustedStrategy = active.find((s) => countStrategyAttempts(cycle.iterations, s.name) >= s.maxAttempts);
39979
+ logger?.info("findings.cycle", "cycle exited \u2014 all active strategies exhausted", {
39980
+ storyId,
39981
+ packageDir,
39982
+ cycleName,
39983
+ reason: "max-attempts-per-strategy",
39984
+ exhaustedStrategy: exhaustedStrategy?.name
39985
+ });
39986
+ return {
39987
+ iterations: cycle.iterations,
39988
+ finalFindings: cycle.findings,
39989
+ exitReason: "max-attempts-per-strategy",
39990
+ exhaustedStrategy: exhaustedStrategy?.name,
39991
+ costUsd: totalCostUsd
39992
+ };
39996
39993
  }
39997
39994
  const totalAttempts = countTotalAttempts(cycle.iterations);
39998
39995
  if (totalAttempts >= cycle.config.maxAttemptsTotal) {
@@ -40011,7 +40008,7 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
40011
40008
  costUsd: totalCostUsd
40012
40009
  };
40013
40010
  }
40014
- for (const strategy of active) {
40011
+ for (const strategy of uncappedActive) {
40015
40012
  const bailReason = strategy.bailWhen?.(cycle.iterations) ?? null;
40016
40013
  if (bailReason !== null) {
40017
40014
  logger?.info("findings.cycle", "cycle exited \u2014 bail predicate fired", {
@@ -40031,7 +40028,7 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
40031
40028
  };
40032
40029
  }
40033
40030
  }
40034
- const group = selectExecutionGroup(active);
40031
+ const group = selectExecutionGroup(uncappedActive);
40035
40032
  const startedAt = now();
40036
40033
  const findingsBefore = [...cycle.findings];
40037
40034
  const fixesApplied = [];
@@ -40142,6 +40139,19 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
40142
40139
  };
40143
40140
  }
40144
40141
  if (liteShortCircuited) {
40142
+ const companions = uncappedActive.filter((s) => !group.includes(s));
40143
+ if (companions.length > 0) {
40144
+ const iterCostUsd = fixesApplied.reduce((sum, fa) => sum + (fa.costUsd ?? 0), 0);
40145
+ totalCostUsd += iterCostUsd;
40146
+ logger?.info("findings.cycle", "exclusive strategy exhausted \u2014 continuing to companion strategies", {
40147
+ storyId,
40148
+ packageDir,
40149
+ cycleName,
40150
+ exhaustedStrategies: group.map((s) => s.name),
40151
+ remainingStrategies: companions.map((s) => s.name)
40152
+ });
40153
+ continue;
40154
+ }
40145
40155
  logger?.info("findings.cycle", "cycle exited \u2014 validate short-circuited", {
40146
40156
  storyId,
40147
40157
  packageDir,
@@ -54803,6 +54813,33 @@ class ExecutionPlan {
54803
54813
  }
54804
54814
  }
54805
54815
  }
54816
+ if (this.state.rectification && rectResult.rectificationExhausted) {
54817
+ const mechanicalOnly = !!rectResult.unfixedFindings?.length && rectResult.unfixedFindings.every((f) => f.source === "lint" || f.source === "typecheck");
54818
+ if (mechanicalOnly) {
54819
+ for (const phase of collectOrderedPhases(this.state)) {
54820
+ const name = phase.slot.op.name;
54821
+ if (name in phaseOutputs)
54822
+ continue;
54823
+ try {
54824
+ await runPhase(this.ctx, phase.slot, phaseCosts, phaseOutputs, this.isThreeSession);
54825
+ } catch (error48) {
54826
+ logger?.error("story-orchestrator", "Phase threw unexpected error (mechanical-only resume)", {
54827
+ storyId: this.ctx.storyId,
54828
+ phase: name,
54829
+ error: errorMessage(error48)
54830
+ });
54831
+ throw error48;
54832
+ }
54833
+ if (!phasePassed(name, phaseOutputs[name], this.ctx.storyId)) {
54834
+ logger?.warn("story-orchestrator", "Phase failed in mechanical-only resume", {
54835
+ storyId: this.ctx.storyId,
54836
+ phase: name
54837
+ });
54838
+ break;
54839
+ }
54840
+ }
54841
+ }
54842
+ }
54806
54843
  const advCfg = this.state.adversarialReview ? this.state.nonBlockingFix : undefined;
54807
54844
  const advisoryOut = phaseOutputs["adversarial-review"];
54808
54845
  const advisoryFindings = advisoryOut?.advisoryFindings ?? [];
@@ -55663,7 +55700,7 @@ async function decideStageAction(ctx, planResult, inspection, opts) {
55663
55700
  const sources = new Set(planResult.unfixedFindings.map((f) => f.source));
55664
55701
  const allMechanical = [...sources].every((s) => s === "lint" || s === "typecheck");
55665
55702
  if (allMechanical) {
55666
- logger.warn("execution", "Mechanical-only failure unfixable \u2014 proceeding (LLM review passed)", {
55703
+ logger.warn("execution", "Mechanical-only failure unfixable \u2014 proceeding (style-only errors remain)", {
55667
55704
  storyId: ctx.story.id
55668
55705
  });
55669
55706
  return { action: "continue" };
@@ -59658,7 +59695,7 @@ var package_default;
59658
59695
  var init_package = __esm(() => {
59659
59696
  package_default = {
59660
59697
  name: "@nathapp/nax",
59661
- version: "0.69.5",
59698
+ version: "0.69.6",
59662
59699
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
59663
59700
  type: "module",
59664
59701
  bin: {
@@ -59753,8 +59790,8 @@ var init_version = __esm(() => {
59753
59790
  NAX_VERSION = package_default.version;
59754
59791
  NAX_COMMIT = (() => {
59755
59792
  try {
59756
- if (/^[0-9a-f]{6,10}$/.test("f09a75e2"))
59757
- return "f09a75e2";
59793
+ if (/^[0-9a-f]{6,10}$/.test("97a1e367"))
59794
+ return "97a1e367";
59758
59795
  } catch {}
59759
59796
  try {
59760
59797
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.69.5",
3
+ "version": "0.69.6",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {