@nathapp/nax 0.69.3 → 0.69.5
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 +126 -19
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -25203,8 +25203,22 @@ async function selectScopedTests(input) {
|
|
|
25203
25203
|
if (!smartCfg.enabled || !input.storyGitRef || isMonorepoOrchestrator) {
|
|
25204
25204
|
return { effectiveCommand: input.testCommand, isFullSuite: true, thresholdFallback: false, isMonorepoOrchestrator };
|
|
25205
25205
|
}
|
|
25206
|
-
const
|
|
25207
|
-
const
|
|
25206
|
+
const repoRoot = input.repoRoot ?? input.workdir;
|
|
25207
|
+
const classifyRegex = input.resolvedTestPatterns?.regex ? [...input.resolvedTestPatterns.regex] : globsToTestRegex(smartCfg.testFilePatterns);
|
|
25208
|
+
const mappingGlobs = input.resolvedTestPatterns?.globs ? [...input.resolvedTestPatterns.globs] : smartCfg.testFilePatterns;
|
|
25209
|
+
const changedTestFiles = await _scopedSelectionDeps.getChangedTestFiles(input.workdir, repoRoot, input.storyGitRef, input.packagePrefix, classifyRegex, input.naxIgnoreIndex);
|
|
25210
|
+
if (changedTestFiles.length > threshold) {
|
|
25211
|
+
logger.warn("verify[scoped]", `Changed test file count ${changedTestFiles.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
|
|
25212
|
+
return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
|
|
25213
|
+
}
|
|
25214
|
+
if (changedTestFiles.length > 0) {
|
|
25215
|
+
logger.info("verify[scoped]", `Pass 0: ${changedTestFiles.length} changed test file(s) detected directly`, {
|
|
25216
|
+
storyId: input.storyId
|
|
25217
|
+
});
|
|
25218
|
+
return scoped(changedTestFiles);
|
|
25219
|
+
}
|
|
25220
|
+
const nonTestFiles = await _scopedSelectionDeps.getChangedNonTestFiles(input.workdir, input.storyGitRef, input.packagePrefix, classifyRegex, input.naxIgnoreIndex, repoRoot);
|
|
25221
|
+
const pass1Files = await _scopedSelectionDeps.mapSourceToTests(nonTestFiles, repoRoot, input.packagePrefix, mappingGlobs);
|
|
25208
25222
|
if (pass1Files.length > threshold) {
|
|
25209
25223
|
logger.warn("verify[scoped]", `Scoped test file count ${pass1Files.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
|
|
25210
25224
|
return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
|
|
@@ -25218,7 +25232,7 @@ async function selectScopedTests(input) {
|
|
|
25218
25232
|
if (smartCfg.fallback !== "import-grep") {
|
|
25219
25233
|
return fullSuite();
|
|
25220
25234
|
}
|
|
25221
|
-
const pass2Files = await _scopedSelectionDeps.importGrepFallback(nonTestFiles, input.workdir,
|
|
25235
|
+
const pass2Files = await _scopedSelectionDeps.importGrepFallback(nonTestFiles, input.workdir, mappingGlobs);
|
|
25222
25236
|
if (pass2Files.length > threshold) {
|
|
25223
25237
|
logger.warn("verify[scoped]", `Scoped test file count ${pass2Files.length} exceeds threshold ${threshold} \u2014 falling back to full suite`, { storyId: input.storyId });
|
|
25224
25238
|
return fullSuite({ scopeTestFallback: true, thresholdFallback: true });
|
|
@@ -25243,6 +25257,7 @@ var init_scoped_selection = __esm(() => {
|
|
|
25243
25257
|
};
|
|
25244
25258
|
_scopedSelectionDeps = {
|
|
25245
25259
|
getChangedNonTestFiles: _smartRunnerDeps.getChangedNonTestFiles,
|
|
25260
|
+
getChangedTestFiles: _smartRunnerDeps.getChangedTestFiles,
|
|
25246
25261
|
mapSourceToTests: _smartRunnerDeps.mapSourceToTests,
|
|
25247
25262
|
importGrepFallback: _smartRunnerDeps.importGrepFallback,
|
|
25248
25263
|
buildSmartTestCommand: _smartRunnerDeps.buildSmartTestCommand
|
|
@@ -34374,17 +34389,18 @@ function acSentinelToFinding(sentinel, _output) {
|
|
|
34374
34389
|
}
|
|
34375
34390
|
|
|
34376
34391
|
// src/findings/adapters/typecheck.ts
|
|
34377
|
-
function
|
|
34392
|
+
function genericTypecheckDiagnosticToFinding(d, workdir, tool) {
|
|
34378
34393
|
return {
|
|
34379
34394
|
source: "typecheck",
|
|
34380
|
-
tool
|
|
34395
|
+
tool,
|
|
34381
34396
|
severity: "error",
|
|
34382
34397
|
category: "type-error",
|
|
34383
34398
|
rule: d.code ? `TS${d.code}` : undefined,
|
|
34384
34399
|
file: rebaseToWorkdir(d.file, workdir, workdir),
|
|
34385
34400
|
line: d.line,
|
|
34386
34401
|
column: d.column,
|
|
34387
|
-
message: d.message
|
|
34402
|
+
message: d.message,
|
|
34403
|
+
fixTarget: "source"
|
|
34388
34404
|
};
|
|
34389
34405
|
}
|
|
34390
34406
|
var init_typecheck = __esm(() => {
|
|
@@ -38896,7 +38912,7 @@ function makeAutofixImplementerStrategy(story, config2, sink, opts = {}) {
|
|
|
38896
38912
|
const claimsAdversarial = opts.includeAdversarialReview === true;
|
|
38897
38913
|
return {
|
|
38898
38914
|
name: "autofix-implementer",
|
|
38899
|
-
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",
|
|
38900
38916
|
fixOp: implementerRectifyOp,
|
|
38901
38917
|
buildInput: (findings, _prior, _cycleCtx) => ({
|
|
38902
38918
|
failedChecks: findingsToFailedChecks(findings),
|
|
@@ -39377,7 +39393,15 @@ var init_lint_check = __esm(() => {
|
|
|
39377
39393
|
return { success: true, status: "passed", findings: [], durationMs: Date.now() - start };
|
|
39378
39394
|
}
|
|
39379
39395
|
const parsed = deps.parseLintOutput(result.output, "auto", { workdir: input.workdir });
|
|
39380
|
-
|
|
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 };
|
|
39381
39405
|
}
|
|
39382
39406
|
};
|
|
39383
39407
|
});
|
|
@@ -39568,6 +39592,11 @@ function strategiesFor(format) {
|
|
|
39568
39592
|
return [];
|
|
39569
39593
|
return [tscStrategy, typecheckTextBlockStrategy];
|
|
39570
39594
|
}
|
|
39595
|
+
function toolForFormat(format) {
|
|
39596
|
+
if (format === "tsc")
|
|
39597
|
+
return "tsc";
|
|
39598
|
+
return;
|
|
39599
|
+
}
|
|
39571
39600
|
function parseTypecheckOutput(output, format = "auto", opts) {
|
|
39572
39601
|
if (!output.trim())
|
|
39573
39602
|
return null;
|
|
@@ -39575,7 +39604,8 @@ function parseTypecheckOutput(output, format = "auto", opts) {
|
|
|
39575
39604
|
const parsed = strategy.parse(output);
|
|
39576
39605
|
if (parsed && parsed.diagnostics.length > 0) {
|
|
39577
39606
|
if (opts) {
|
|
39578
|
-
const
|
|
39607
|
+
const tool = toolForFormat(parsed.format);
|
|
39608
|
+
const findings = parsed.diagnostics.map((d) => genericTypecheckDiagnosticToFinding(d, opts.workdir, tool));
|
|
39579
39609
|
return { ...parsed, findings };
|
|
39580
39610
|
}
|
|
39581
39611
|
return parsed;
|
|
@@ -39633,7 +39663,16 @@ var init_typecheck_check = __esm(() => {
|
|
|
39633
39663
|
return { success: true, status: "passed", findings: [], durationMs: Date.now() - start };
|
|
39634
39664
|
}
|
|
39635
39665
|
const parsed = deps.parseTypecheckOutput(result.output, "auto", { workdir: input.workdir });
|
|
39636
|
-
|
|
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 };
|
|
39637
39676
|
}
|
|
39638
39677
|
};
|
|
39639
39678
|
});
|
|
@@ -39685,7 +39724,10 @@ var init_verify_scoped = __esm(() => {
|
|
|
39685
39724
|
smartRunnerConfig: quality.execution?.smartTestRunner,
|
|
39686
39725
|
scopeTestThreshold: quality.quality?.scopeTestThreshold,
|
|
39687
39726
|
fallbackFullSuiteCommand: quality.quality?.commands?.test,
|
|
39688
|
-
naxIgnoreIndex: input.naxIgnoreIndex
|
|
39727
|
+
naxIgnoreIndex: input.naxIgnoreIndex,
|
|
39728
|
+
repoRoot: input.repoRoot,
|
|
39729
|
+
packagePrefix: input.packagePrefix,
|
|
39730
|
+
resolvedTestPatterns: input.resolvedTestPatterns
|
|
39689
39731
|
});
|
|
39690
39732
|
if (selection.isFullSuite && regressionMode === "deferred" && !selection.isMonorepoOrchestrator && !selection.thresholdFallback) {
|
|
39691
39733
|
logger.info("verify[scoped]", "No mapped tests \u2014 deferring to run-end (mode: deferred)", {
|
|
@@ -40449,6 +40491,67 @@ var init_text_block2 = __esm(() => {
|
|
|
40449
40491
|
};
|
|
40450
40492
|
});
|
|
40451
40493
|
|
|
40494
|
+
// src/review/lint-parsing/strategies/ruff-annotated.ts
|
|
40495
|
+
function parseRuffAnnotated(output) {
|
|
40496
|
+
if (!output.trim())
|
|
40497
|
+
return null;
|
|
40498
|
+
const lines = output.split(/\r?\n/);
|
|
40499
|
+
let hasArrow = false;
|
|
40500
|
+
for (const line of lines) {
|
|
40501
|
+
if (ARROW_RE.test(line)) {
|
|
40502
|
+
hasArrow = true;
|
|
40503
|
+
break;
|
|
40504
|
+
}
|
|
40505
|
+
}
|
|
40506
|
+
if (!hasArrow)
|
|
40507
|
+
return null;
|
|
40508
|
+
const diagnostics = [];
|
|
40509
|
+
let i = 0;
|
|
40510
|
+
while (i < lines.length) {
|
|
40511
|
+
const arrowMatch = ARROW_RE.exec(lines[i]);
|
|
40512
|
+
if (!arrowMatch || !SOURCE_EXT_RE2.test(arrowMatch[1])) {
|
|
40513
|
+
i++;
|
|
40514
|
+
continue;
|
|
40515
|
+
}
|
|
40516
|
+
const file3 = arrowMatch[1];
|
|
40517
|
+
const line = Number.parseInt(arrowMatch[2], 10);
|
|
40518
|
+
const col = arrowMatch[3] ? Number.parseInt(arrowMatch[3], 10) : undefined;
|
|
40519
|
+
const messageLines = [];
|
|
40520
|
+
let j = i - 1;
|
|
40521
|
+
while (j >= 0) {
|
|
40522
|
+
const l = lines[j]?.trim() ?? "";
|
|
40523
|
+
if (!l || ARROW_RE.test(lines[j] ?? "") || CONTEXT_LINE_RE.test(lines[j] ?? ""))
|
|
40524
|
+
break;
|
|
40525
|
+
messageLines.unshift(lines[j] ?? "");
|
|
40526
|
+
j--;
|
|
40527
|
+
}
|
|
40528
|
+
const contextLines = [lines[i]];
|
|
40529
|
+
let k = i + 1;
|
|
40530
|
+
while (k < lines.length && CONTEXT_LINE_RE.test(lines[k])) {
|
|
40531
|
+
contextLines.push(lines[k]);
|
|
40532
|
+
k++;
|
|
40533
|
+
}
|
|
40534
|
+
const raw = [...messageLines, ...contextLines].join(`
|
|
40535
|
+
`);
|
|
40536
|
+
const message = (messageLines[messageLines.length - 1] ?? file3).trim();
|
|
40537
|
+
diagnostics.push({ file: file3, line, column: col, message, raw });
|
|
40538
|
+
i = k;
|
|
40539
|
+
}
|
|
40540
|
+
if (diagnostics.length === 0)
|
|
40541
|
+
return null;
|
|
40542
|
+
return { diagnostics, format: "ruff-annotated" };
|
|
40543
|
+
}
|
|
40544
|
+
var ARROW_RE, CONTEXT_LINE_RE, ruffAnnotatedStrategy;
|
|
40545
|
+
var init_ruff_annotated = __esm(() => {
|
|
40546
|
+
init_text_block2();
|
|
40547
|
+
ARROW_RE = /^\s+-->\s+(.+?):(\d+)(?::(\d+))?$/;
|
|
40548
|
+
CONTEXT_LINE_RE = /^\s*\d*\s*\|/;
|
|
40549
|
+
ruffAnnotatedStrategy = {
|
|
40550
|
+
name: "ruff-annotated",
|
|
40551
|
+
parse: parseRuffAnnotated
|
|
40552
|
+
};
|
|
40553
|
+
});
|
|
40554
|
+
|
|
40452
40555
|
// src/review/lint-parsing/parse.ts
|
|
40453
40556
|
function strategiesFor2(format) {
|
|
40454
40557
|
if (format === "eslint-json")
|
|
@@ -40456,12 +40559,12 @@ function strategiesFor2(format) {
|
|
|
40456
40559
|
if (format === "biome-json")
|
|
40457
40560
|
return [biomeJsonStrategy];
|
|
40458
40561
|
if (format === "text")
|
|
40459
|
-
return [textBlockStrategy];
|
|
40562
|
+
return [ruffAnnotatedStrategy, textBlockStrategy];
|
|
40460
40563
|
if (format === "none")
|
|
40461
40564
|
return [];
|
|
40462
|
-
return [eslintJsonStrategy, biomeJsonStrategy, textBlockStrategy];
|
|
40565
|
+
return [eslintJsonStrategy, biomeJsonStrategy, ruffAnnotatedStrategy, textBlockStrategy];
|
|
40463
40566
|
}
|
|
40464
|
-
function
|
|
40567
|
+
function toolForFormat2(format) {
|
|
40465
40568
|
if (format === "biome-json")
|
|
40466
40569
|
return "biome";
|
|
40467
40570
|
if (format === "eslint-json")
|
|
@@ -40475,7 +40578,7 @@ function parseLintOutput(output, format = "auto", opts) {
|
|
|
40475
40578
|
const parsed = strategy.parse(output);
|
|
40476
40579
|
if (parsed && parsed.diagnostics.length > 0) {
|
|
40477
40580
|
if (opts) {
|
|
40478
|
-
const tool =
|
|
40581
|
+
const tool = toolForFormat2(parsed.format);
|
|
40479
40582
|
const findings = parsed.diagnostics.map((d) => lintDiagnosticToFinding(d, opts.workdir, tool));
|
|
40480
40583
|
return { ...parsed, findings };
|
|
40481
40584
|
}
|
|
@@ -40495,6 +40598,7 @@ var init_parse4 = __esm(() => {
|
|
|
40495
40598
|
init_findings();
|
|
40496
40599
|
init_biome_json();
|
|
40497
40600
|
init_eslint_json();
|
|
40601
|
+
init_ruff_annotated();
|
|
40498
40602
|
init_text_block2();
|
|
40499
40603
|
});
|
|
40500
40604
|
|
|
@@ -55133,7 +55237,10 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
55133
55237
|
storyId: story.id,
|
|
55134
55238
|
storyGitRef: ctx.storyGitRef,
|
|
55135
55239
|
naxIgnoreIndex: ctx.naxIgnoreIndex,
|
|
55136
|
-
regressionMode: toVerifyScopedMode(ctx.config.execution?.regressionGate?.mode)
|
|
55240
|
+
regressionMode: toVerifyScopedMode(ctx.config.execution?.regressionGate?.mode),
|
|
55241
|
+
repoRoot: ctx.projectDir,
|
|
55242
|
+
packagePrefix: packageDirRelative,
|
|
55243
|
+
resolvedTestPatterns
|
|
55137
55244
|
} : undefined;
|
|
55138
55245
|
const lintCheckInput = ctx.config.review?.enabled === true && ctx.config.review.checks?.includes("lint") && ctx.config.quality.commands.lint ? { workdir: ctx.workdir, storyId: story.id } : undefined;
|
|
55139
55246
|
const typecheckCheckInput = ctx.config.review?.enabled === true && ctx.config.review.checks?.includes("typecheck") && ctx.config.quality.commands.typecheck ? { workdir: ctx.workdir, storyId: story.id } : undefined;
|
|
@@ -59551,7 +59658,7 @@ var package_default;
|
|
|
59551
59658
|
var init_package = __esm(() => {
|
|
59552
59659
|
package_default = {
|
|
59553
59660
|
name: "@nathapp/nax",
|
|
59554
|
-
version: "0.69.
|
|
59661
|
+
version: "0.69.5",
|
|
59555
59662
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
59556
59663
|
type: "module",
|
|
59557
59664
|
bin: {
|
|
@@ -59646,8 +59753,8 @@ var init_version = __esm(() => {
|
|
|
59646
59753
|
NAX_VERSION = package_default.version;
|
|
59647
59754
|
NAX_COMMIT = (() => {
|
|
59648
59755
|
try {
|
|
59649
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
59650
|
-
return "
|
|
59756
|
+
if (/^[0-9a-f]{6,10}$/.test("f09a75e2"))
|
|
59757
|
+
return "f09a75e2";
|
|
59651
59758
|
} catch {}
|
|
59652
59759
|
try {
|
|
59653
59760
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|