@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.
Files changed (2) hide show
  1. package/dist/nax.js +45 -9
  2. 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.6",
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("955ab31"))
22433
- return "955ab31";
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 truncateDiff(diff) {
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 fileCount = (truncated.match(/^diff --git/gm) ?? []).length;
24879
- return `${truncated}
24880
- ... (truncated, showing first ${fileCount} files)`;
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 diff = truncateDiff(rawDiff);
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 = 12288, DEFAULT_RULES;
25111
+ var _semanticDeps, DIFF_CAP_BYTES = 102400, DEFAULT_RULES;
25076
25112
  var init_semantic = __esm(() => {
25077
25113
  init_logger2();
25078
25114
  _semanticDeps = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.54.6",
3
+ "version": "0.54.7",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {