@nathapp/nax 0.69.4 → 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.
- package/dist/nax.js +160 -37
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -34389,17 +34389,18 @@ function acSentinelToFinding(sentinel, _output) {
|
|
|
34389
34389
|
}
|
|
34390
34390
|
|
|
34391
34391
|
// src/findings/adapters/typecheck.ts
|
|
34392
|
-
function
|
|
34392
|
+
function genericTypecheckDiagnosticToFinding(d, workdir, tool) {
|
|
34393
34393
|
return {
|
|
34394
34394
|
source: "typecheck",
|
|
34395
|
-
tool
|
|
34395
|
+
tool,
|
|
34396
34396
|
severity: "error",
|
|
34397
34397
|
category: "type-error",
|
|
34398
34398
|
rule: d.code ? `TS${d.code}` : undefined,
|
|
34399
34399
|
file: rebaseToWorkdir(d.file, workdir, workdir),
|
|
34400
34400
|
line: d.line,
|
|
34401
34401
|
column: d.column,
|
|
34402
|
-
message: d.message
|
|
34402
|
+
message: d.message,
|
|
34403
|
+
fixTarget: "source"
|
|
34403
34404
|
};
|
|
34404
34405
|
}
|
|
34405
34406
|
var init_typecheck = __esm(() => {
|
|
@@ -38911,7 +38912,7 @@ function makeAutofixImplementerStrategy(story, config2, sink, opts = {}) {
|
|
|
38911
38912
|
const claimsAdversarial = opts.includeAdversarialReview === true;
|
|
38912
38913
|
return {
|
|
38913
38914
|
name: "autofix-implementer",
|
|
38914
|
-
appliesTo: (f) => f.fixTarget === "source" && IMPLEMENTER_SOURCES.has(f.source) || claimsAdversarial && f.source === "adversarial-review",
|
|
38915
|
+
appliesTo: (f) => (f.fixTarget === "source" || f.fixTarget == null) && IMPLEMENTER_SOURCES.has(f.source) || claimsAdversarial && f.source === "adversarial-review",
|
|
38915
38916
|
fixOp: implementerRectifyOp,
|
|
38916
38917
|
buildInput: (findings, _prior, _cycleCtx) => ({
|
|
38917
38918
|
failedChecks: findingsToFailedChecks(findings),
|
|
@@ -39392,7 +39393,15 @@ var init_lint_check = __esm(() => {
|
|
|
39392
39393
|
return { success: true, status: "passed", findings: [], durationMs: Date.now() - start };
|
|
39393
39394
|
}
|
|
39394
39395
|
const parsed = deps.parseLintOutput(result.output, "auto", { workdir: input.workdir });
|
|
39395
|
-
|
|
39396
|
+
const parsedFindings = parsed?.findings ?? [];
|
|
39397
|
+
const sentinel = {
|
|
39398
|
+
source: "lint",
|
|
39399
|
+
severity: "error",
|
|
39400
|
+
category: "lint-failure",
|
|
39401
|
+
message: `lint failed (no structured findings parsed), please run the lint check command: ${command}`
|
|
39402
|
+
};
|
|
39403
|
+
const findings = parsedFindings.length > 0 ? parsedFindings : [sentinel];
|
|
39404
|
+
return { success: false, findings, durationMs: Date.now() - start };
|
|
39396
39405
|
}
|
|
39397
39406
|
};
|
|
39398
39407
|
});
|
|
@@ -39583,6 +39592,11 @@ function strategiesFor(format) {
|
|
|
39583
39592
|
return [];
|
|
39584
39593
|
return [tscStrategy, typecheckTextBlockStrategy];
|
|
39585
39594
|
}
|
|
39595
|
+
function toolForFormat(format) {
|
|
39596
|
+
if (format === "tsc")
|
|
39597
|
+
return "tsc";
|
|
39598
|
+
return;
|
|
39599
|
+
}
|
|
39586
39600
|
function parseTypecheckOutput(output, format = "auto", opts) {
|
|
39587
39601
|
if (!output.trim())
|
|
39588
39602
|
return null;
|
|
@@ -39590,7 +39604,8 @@ function parseTypecheckOutput(output, format = "auto", opts) {
|
|
|
39590
39604
|
const parsed = strategy.parse(output);
|
|
39591
39605
|
if (parsed && parsed.diagnostics.length > 0) {
|
|
39592
39606
|
if (opts) {
|
|
39593
|
-
const
|
|
39607
|
+
const tool = toolForFormat(parsed.format);
|
|
39608
|
+
const findings = parsed.diagnostics.map((d) => genericTypecheckDiagnosticToFinding(d, opts.workdir, tool));
|
|
39594
39609
|
return { ...parsed, findings };
|
|
39595
39610
|
}
|
|
39596
39611
|
return parsed;
|
|
@@ -39648,7 +39663,16 @@ var init_typecheck_check = __esm(() => {
|
|
|
39648
39663
|
return { success: true, status: "passed", findings: [], durationMs: Date.now() - start };
|
|
39649
39664
|
}
|
|
39650
39665
|
const parsed = deps.parseTypecheckOutput(result.output, "auto", { workdir: input.workdir });
|
|
39651
|
-
|
|
39666
|
+
const parsedFindings = parsed?.findings ?? [];
|
|
39667
|
+
const sentinel = {
|
|
39668
|
+
source: "typecheck",
|
|
39669
|
+
severity: "error",
|
|
39670
|
+
category: "typecheck-failure",
|
|
39671
|
+
fixTarget: "source",
|
|
39672
|
+
message: `typecheck failed (no structured findings parsed), please run the typecheck command: ${command}`
|
|
39673
|
+
};
|
|
39674
|
+
const findings = parsedFindings.length > 0 ? parsedFindings : [sentinel];
|
|
39675
|
+
return { success: false, findings, durationMs: Date.now() - start };
|
|
39652
39676
|
}
|
|
39653
39677
|
};
|
|
39654
39678
|
});
|
|
@@ -39949,26 +39973,23 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
39949
39973
|
costUsd: totalCostUsd
|
|
39950
39974
|
};
|
|
39951
39975
|
}
|
|
39952
|
-
|
|
39953
|
-
|
|
39954
|
-
|
|
39955
|
-
|
|
39956
|
-
|
|
39957
|
-
|
|
39958
|
-
|
|
39959
|
-
|
|
39960
|
-
|
|
39961
|
-
|
|
39962
|
-
|
|
39963
|
-
|
|
39964
|
-
|
|
39965
|
-
|
|
39966
|
-
|
|
39967
|
-
|
|
39968
|
-
|
|
39969
|
-
costUsd: totalCostUsd
|
|
39970
|
-
};
|
|
39971
|
-
}
|
|
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
|
+
};
|
|
39972
39993
|
}
|
|
39973
39994
|
const totalAttempts = countTotalAttempts(cycle.iterations);
|
|
39974
39995
|
if (totalAttempts >= cycle.config.maxAttemptsTotal) {
|
|
@@ -39987,7 +40008,7 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
39987
40008
|
costUsd: totalCostUsd
|
|
39988
40009
|
};
|
|
39989
40010
|
}
|
|
39990
|
-
for (const strategy of
|
|
40011
|
+
for (const strategy of uncappedActive) {
|
|
39991
40012
|
const bailReason = strategy.bailWhen?.(cycle.iterations) ?? null;
|
|
39992
40013
|
if (bailReason !== null) {
|
|
39993
40014
|
logger?.info("findings.cycle", "cycle exited \u2014 bail predicate fired", {
|
|
@@ -40007,7 +40028,7 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
40007
40028
|
};
|
|
40008
40029
|
}
|
|
40009
40030
|
}
|
|
40010
|
-
const group = selectExecutionGroup(
|
|
40031
|
+
const group = selectExecutionGroup(uncappedActive);
|
|
40011
40032
|
const startedAt = now();
|
|
40012
40033
|
const findingsBefore = [...cycle.findings];
|
|
40013
40034
|
const fixesApplied = [];
|
|
@@ -40118,6 +40139,19 @@ async function runFixCycle(cycle, ctx, cycleName, _deps = {}) {
|
|
|
40118
40139
|
};
|
|
40119
40140
|
}
|
|
40120
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
|
+
}
|
|
40121
40155
|
logger?.info("findings.cycle", "cycle exited \u2014 validate short-circuited", {
|
|
40122
40156
|
storyId,
|
|
40123
40157
|
packageDir,
|
|
@@ -40467,6 +40501,67 @@ var init_text_block2 = __esm(() => {
|
|
|
40467
40501
|
};
|
|
40468
40502
|
});
|
|
40469
40503
|
|
|
40504
|
+
// src/review/lint-parsing/strategies/ruff-annotated.ts
|
|
40505
|
+
function parseRuffAnnotated(output) {
|
|
40506
|
+
if (!output.trim())
|
|
40507
|
+
return null;
|
|
40508
|
+
const lines = output.split(/\r?\n/);
|
|
40509
|
+
let hasArrow = false;
|
|
40510
|
+
for (const line of lines) {
|
|
40511
|
+
if (ARROW_RE.test(line)) {
|
|
40512
|
+
hasArrow = true;
|
|
40513
|
+
break;
|
|
40514
|
+
}
|
|
40515
|
+
}
|
|
40516
|
+
if (!hasArrow)
|
|
40517
|
+
return null;
|
|
40518
|
+
const diagnostics = [];
|
|
40519
|
+
let i = 0;
|
|
40520
|
+
while (i < lines.length) {
|
|
40521
|
+
const arrowMatch = ARROW_RE.exec(lines[i]);
|
|
40522
|
+
if (!arrowMatch || !SOURCE_EXT_RE2.test(arrowMatch[1])) {
|
|
40523
|
+
i++;
|
|
40524
|
+
continue;
|
|
40525
|
+
}
|
|
40526
|
+
const file3 = arrowMatch[1];
|
|
40527
|
+
const line = Number.parseInt(arrowMatch[2], 10);
|
|
40528
|
+
const col = arrowMatch[3] ? Number.parseInt(arrowMatch[3], 10) : undefined;
|
|
40529
|
+
const messageLines = [];
|
|
40530
|
+
let j = i - 1;
|
|
40531
|
+
while (j >= 0) {
|
|
40532
|
+
const l = lines[j]?.trim() ?? "";
|
|
40533
|
+
if (!l || ARROW_RE.test(lines[j] ?? "") || CONTEXT_LINE_RE.test(lines[j] ?? ""))
|
|
40534
|
+
break;
|
|
40535
|
+
messageLines.unshift(lines[j] ?? "");
|
|
40536
|
+
j--;
|
|
40537
|
+
}
|
|
40538
|
+
const contextLines = [lines[i]];
|
|
40539
|
+
let k = i + 1;
|
|
40540
|
+
while (k < lines.length && CONTEXT_LINE_RE.test(lines[k])) {
|
|
40541
|
+
contextLines.push(lines[k]);
|
|
40542
|
+
k++;
|
|
40543
|
+
}
|
|
40544
|
+
const raw = [...messageLines, ...contextLines].join(`
|
|
40545
|
+
`);
|
|
40546
|
+
const message = (messageLines[messageLines.length - 1] ?? file3).trim();
|
|
40547
|
+
diagnostics.push({ file: file3, line, column: col, message, raw });
|
|
40548
|
+
i = k;
|
|
40549
|
+
}
|
|
40550
|
+
if (diagnostics.length === 0)
|
|
40551
|
+
return null;
|
|
40552
|
+
return { diagnostics, format: "ruff-annotated" };
|
|
40553
|
+
}
|
|
40554
|
+
var ARROW_RE, CONTEXT_LINE_RE, ruffAnnotatedStrategy;
|
|
40555
|
+
var init_ruff_annotated = __esm(() => {
|
|
40556
|
+
init_text_block2();
|
|
40557
|
+
ARROW_RE = /^\s+-->\s+(.+?):(\d+)(?::(\d+))?$/;
|
|
40558
|
+
CONTEXT_LINE_RE = /^\s*\d*\s*\|/;
|
|
40559
|
+
ruffAnnotatedStrategy = {
|
|
40560
|
+
name: "ruff-annotated",
|
|
40561
|
+
parse: parseRuffAnnotated
|
|
40562
|
+
};
|
|
40563
|
+
});
|
|
40564
|
+
|
|
40470
40565
|
// src/review/lint-parsing/parse.ts
|
|
40471
40566
|
function strategiesFor2(format) {
|
|
40472
40567
|
if (format === "eslint-json")
|
|
@@ -40474,12 +40569,12 @@ function strategiesFor2(format) {
|
|
|
40474
40569
|
if (format === "biome-json")
|
|
40475
40570
|
return [biomeJsonStrategy];
|
|
40476
40571
|
if (format === "text")
|
|
40477
|
-
return [textBlockStrategy];
|
|
40572
|
+
return [ruffAnnotatedStrategy, textBlockStrategy];
|
|
40478
40573
|
if (format === "none")
|
|
40479
40574
|
return [];
|
|
40480
|
-
return [eslintJsonStrategy, biomeJsonStrategy, textBlockStrategy];
|
|
40575
|
+
return [eslintJsonStrategy, biomeJsonStrategy, ruffAnnotatedStrategy, textBlockStrategy];
|
|
40481
40576
|
}
|
|
40482
|
-
function
|
|
40577
|
+
function toolForFormat2(format) {
|
|
40483
40578
|
if (format === "biome-json")
|
|
40484
40579
|
return "biome";
|
|
40485
40580
|
if (format === "eslint-json")
|
|
@@ -40493,7 +40588,7 @@ function parseLintOutput(output, format = "auto", opts) {
|
|
|
40493
40588
|
const parsed = strategy.parse(output);
|
|
40494
40589
|
if (parsed && parsed.diagnostics.length > 0) {
|
|
40495
40590
|
if (opts) {
|
|
40496
|
-
const tool =
|
|
40591
|
+
const tool = toolForFormat2(parsed.format);
|
|
40497
40592
|
const findings = parsed.diagnostics.map((d) => lintDiagnosticToFinding(d, opts.workdir, tool));
|
|
40498
40593
|
return { ...parsed, findings };
|
|
40499
40594
|
}
|
|
@@ -40513,6 +40608,7 @@ var init_parse4 = __esm(() => {
|
|
|
40513
40608
|
init_findings();
|
|
40514
40609
|
init_biome_json();
|
|
40515
40610
|
init_eslint_json();
|
|
40611
|
+
init_ruff_annotated();
|
|
40516
40612
|
init_text_block2();
|
|
40517
40613
|
});
|
|
40518
40614
|
|
|
@@ -54717,6 +54813,33 @@ class ExecutionPlan {
|
|
|
54717
54813
|
}
|
|
54718
54814
|
}
|
|
54719
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
|
+
}
|
|
54720
54843
|
const advCfg = this.state.adversarialReview ? this.state.nonBlockingFix : undefined;
|
|
54721
54844
|
const advisoryOut = phaseOutputs["adversarial-review"];
|
|
54722
54845
|
const advisoryFindings = advisoryOut?.advisoryFindings ?? [];
|
|
@@ -55577,7 +55700,7 @@ async function decideStageAction(ctx, planResult, inspection, opts) {
|
|
|
55577
55700
|
const sources = new Set(planResult.unfixedFindings.map((f) => f.source));
|
|
55578
55701
|
const allMechanical = [...sources].every((s) => s === "lint" || s === "typecheck");
|
|
55579
55702
|
if (allMechanical) {
|
|
55580
|
-
logger.warn("execution", "Mechanical-only failure unfixable \u2014 proceeding (
|
|
55703
|
+
logger.warn("execution", "Mechanical-only failure unfixable \u2014 proceeding (style-only errors remain)", {
|
|
55581
55704
|
storyId: ctx.story.id
|
|
55582
55705
|
});
|
|
55583
55706
|
return { action: "continue" };
|
|
@@ -59572,7 +59695,7 @@ var package_default;
|
|
|
59572
59695
|
var init_package = __esm(() => {
|
|
59573
59696
|
package_default = {
|
|
59574
59697
|
name: "@nathapp/nax",
|
|
59575
|
-
version: "0.69.
|
|
59698
|
+
version: "0.69.6",
|
|
59576
59699
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
59577
59700
|
type: "module",
|
|
59578
59701
|
bin: {
|
|
@@ -59667,8 +59790,8 @@ var init_version = __esm(() => {
|
|
|
59667
59790
|
NAX_VERSION = package_default.version;
|
|
59668
59791
|
NAX_COMMIT = (() => {
|
|
59669
59792
|
try {
|
|
59670
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
59671
|
-
return "
|
|
59793
|
+
if (/^[0-9a-f]{6,10}$/.test("97a1e367"))
|
|
59794
|
+
return "97a1e367";
|
|
59672
59795
|
} catch {}
|
|
59673
59796
|
try {
|
|
59674
59797
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|