@nathapp/nax 0.54.6 → 0.54.7
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 +45 -9
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -22352,7 +22352,7 @@ var package_default;
|
|
|
22352
22352
|
var init_package = __esm(() => {
|
|
22353
22353
|
package_default = {
|
|
22354
22354
|
name: "@nathapp/nax",
|
|
22355
|
-
version: "0.54.
|
|
22355
|
+
version: "0.54.7",
|
|
22356
22356
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
22357
22357
|
type: "module",
|
|
22358
22358
|
bin: {
|
|
@@ -22429,8 +22429,8 @@ var init_version = __esm(() => {
|
|
|
22429
22429
|
NAX_VERSION = package_default.version;
|
|
22430
22430
|
NAX_COMMIT = (() => {
|
|
22431
22431
|
try {
|
|
22432
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
22433
|
-
return "
|
|
22432
|
+
if (/^[0-9a-f]{6,10}$/.test("ccfd70c"))
|
|
22433
|
+
return "ccfd70c";
|
|
22434
22434
|
} catch {}
|
|
22435
22435
|
try {
|
|
22436
22436
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -24870,14 +24870,34 @@ async function collectDiff(workdir, storyGitRef) {
|
|
|
24870
24870
|
}
|
|
24871
24871
|
return stdout;
|
|
24872
24872
|
}
|
|
24873
|
-
function
|
|
24873
|
+
async function collectDiffStat(workdir, storyGitRef) {
|
|
24874
|
+
const proc = _semanticDeps.spawn({
|
|
24875
|
+
cmd: ["git", "diff", "--stat", `${storyGitRef}..HEAD`],
|
|
24876
|
+
cwd: workdir,
|
|
24877
|
+
stdout: "pipe",
|
|
24878
|
+
stderr: "pipe"
|
|
24879
|
+
});
|
|
24880
|
+
const [exitCode, stdout] = await Promise.all([
|
|
24881
|
+
proc.exited,
|
|
24882
|
+
new Response(proc.stdout).text(),
|
|
24883
|
+
new Response(proc.stderr).text()
|
|
24884
|
+
]);
|
|
24885
|
+
return exitCode === 0 ? stdout.trim() : "";
|
|
24886
|
+
}
|
|
24887
|
+
function truncateDiff(diff, stat) {
|
|
24874
24888
|
if (diff.length <= DIFF_CAP_BYTES) {
|
|
24875
24889
|
return diff;
|
|
24876
24890
|
}
|
|
24877
24891
|
const truncated = diff.slice(0, DIFF_CAP_BYTES);
|
|
24878
|
-
const
|
|
24879
|
-
|
|
24880
|
-
|
|
24892
|
+
const visibleFiles = (truncated.match(/^diff --git/gm) ?? []).length;
|
|
24893
|
+
const totalFiles = (diff.match(/^diff --git/gm) ?? []).length;
|
|
24894
|
+
const statPreamble = stat ? `## File Summary (all changed files)
|
|
24895
|
+
${stat}
|
|
24896
|
+
|
|
24897
|
+
## Diff (truncated \u2014 ${visibleFiles}/${totalFiles} files shown)
|
|
24898
|
+
` : "";
|
|
24899
|
+
return `${statPreamble}${truncated}
|
|
24900
|
+
... (truncated at ${DIFF_CAP_BYTES} bytes, showing ${visibleFiles}/${totalFiles} files)`;
|
|
24881
24901
|
}
|
|
24882
24902
|
function buildPrompt(story, semanticConfig, diff) {
|
|
24883
24903
|
const acList = story.acceptanceCriteria.map((ac, i) => `${i + 1}. ${ac}`).join(`
|
|
@@ -24984,7 +25004,9 @@ async function runSemanticReview(workdir, storyGitRef, story, semanticConfig, mo
|
|
|
24984
25004
|
}
|
|
24985
25005
|
logger?.info("review", "Running semantic check", { storyId: story.id, modelTier: semanticConfig.modelTier });
|
|
24986
25006
|
const rawDiff = await collectDiff(workdir, storyGitRef);
|
|
24987
|
-
const
|
|
25007
|
+
const needsTruncation = rawDiff.length > DIFF_CAP_BYTES;
|
|
25008
|
+
const stat = needsTruncation ? await collectDiffStat(workdir, storyGitRef) : undefined;
|
|
25009
|
+
const diff = truncateDiff(rawDiff, stat);
|
|
24988
25010
|
const agent = modelResolver(semanticConfig.modelTier);
|
|
24989
25011
|
if (!agent) {
|
|
24990
25012
|
logger?.warn("semantic", "No agent available for semantic review \u2014 skipping", {
|
|
@@ -25020,6 +25042,20 @@ async function runSemanticReview(workdir, storyGitRef, story, semanticConfig, mo
|
|
|
25020
25042
|
}
|
|
25021
25043
|
const parsed = parseLLMResponse(rawResponse);
|
|
25022
25044
|
if (!parsed) {
|
|
25045
|
+
const looksLikeFail = /"passed"\s*:\s*false/.test(rawResponse);
|
|
25046
|
+
if (looksLikeFail) {
|
|
25047
|
+
logger?.warn("semantic", "LLM returned truncated JSON with passed:false \u2014 treating as failure", {
|
|
25048
|
+
rawResponse: rawResponse.slice(0, 200)
|
|
25049
|
+
});
|
|
25050
|
+
return {
|
|
25051
|
+
check: "semantic",
|
|
25052
|
+
success: false,
|
|
25053
|
+
command: "",
|
|
25054
|
+
exitCode: 1,
|
|
25055
|
+
output: "semantic review: LLM response truncated but indicated failure (passed:false found in partial response)",
|
|
25056
|
+
durationMs: Date.now() - startTime
|
|
25057
|
+
};
|
|
25058
|
+
}
|
|
25023
25059
|
logger?.warn("semantic", "LLM returned invalid JSON \u2014 fail-open", { rawResponse: rawResponse.slice(0, 200) });
|
|
25024
25060
|
return {
|
|
25025
25061
|
check: "semantic",
|
|
@@ -25072,7 +25108,7 @@ ${formatFindings(parsed.findings)}`;
|
|
|
25072
25108
|
durationMs
|
|
25073
25109
|
};
|
|
25074
25110
|
}
|
|
25075
|
-
var _semanticDeps, DIFF_CAP_BYTES =
|
|
25111
|
+
var _semanticDeps, DIFF_CAP_BYTES = 102400, DEFAULT_RULES;
|
|
25076
25112
|
var init_semantic = __esm(() => {
|
|
25077
25113
|
init_logger2();
|
|
25078
25114
|
_semanticDeps = {
|