@nathapp/nax 0.67.1 → 0.67.2

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 +48 -11
  2. package/package.json +1 -1
package/dist/nax.js CHANGED
@@ -35108,6 +35108,24 @@ async function getChangedFiles(workdir, fromRef = "HEAD") {
35108
35108
  return output.trim().split(`
35109
35109
  `).filter(Boolean);
35110
35110
  }
35111
+ async function getAddedLinesPerFile(workdir, fromRef = "HEAD") {
35112
+ const proc = _isolationDeps.spawn(["git", "diff", "--numstat", fromRef], {
35113
+ cwd: workdir,
35114
+ stdout: "pipe",
35115
+ stderr: "pipe"
35116
+ });
35117
+ const output = await Bun.readableStreamToText(proc.stdout);
35118
+ await proc.exited;
35119
+ const result = new Map;
35120
+ for (const line of output.trim().split(`
35121
+ `).filter(Boolean)) {
35122
+ const [addedStr, _deletedStr, path4] = line.split("\t");
35123
+ const added = Number.parseInt(addedStr ?? "", 10);
35124
+ if (path4 && Number.isFinite(added))
35125
+ result.set(path4, added);
35126
+ }
35127
+ return result;
35128
+ }
35111
35129
  function matchesAllowedPath(filePath, allowedPaths) {
35112
35130
  return allowedPaths.some((pattern) => {
35113
35131
  const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
@@ -35115,17 +35133,25 @@ function matchesAllowedPath(filePath, allowedPaths) {
35115
35133
  return regex.test(filePath);
35116
35134
  });
35117
35135
  }
35118
- async function verifyTestWriterIsolation(workdir, beforeRef, allowedPaths = ["src/index.ts", "src/**/index.ts"], testFilePatterns = DEFAULT_TEST_FILE_PATTERNS) {
35136
+ async function verifyTestWriterIsolation(workdir, beforeRef, allowedPaths = ["src/index.ts", "src/**/index.ts"], testFilePatterns = DEFAULT_TEST_FILE_PATTERNS, mode = "strict") {
35119
35137
  const changed = await getChangedFiles(workdir, beforeRef);
35120
35138
  const sourceFiles = changed.filter((f) => isSourceFile(f) && !isTestFileByPatterns(f, testFilePatterns));
35139
+ const addedLines = mode === "lite" && sourceFiles.length > 0 ? await getAddedLinesPerFile(workdir, beforeRef) : null;
35121
35140
  const softViolations = [];
35122
35141
  const violations = [];
35123
35142
  for (const file3 of sourceFiles) {
35124
35143
  if (matchesAllowedPath(file3, allowedPaths)) {
35125
35144
  softViolations.push(file3);
35126
- } else {
35127
- violations.push(file3);
35145
+ continue;
35146
+ }
35147
+ if (addedLines) {
35148
+ const added = addedLines.get(file3) ?? Number.POSITIVE_INFINITY;
35149
+ if (added <= LITE_STUB_ADDED_LINES_CEILING) {
35150
+ softViolations.push(file3);
35151
+ continue;
35152
+ }
35128
35153
  }
35154
+ violations.push(file3);
35129
35155
  }
35130
35156
  return {
35131
35157
  passed: violations.length === 0,
@@ -35151,7 +35177,7 @@ async function verifyImplementerIsolation(workdir, beforeRef, testFilePatterns =
35151
35177
  description: "Implementer should not modify test files"
35152
35178
  };
35153
35179
  }
35154
- var _isolationDeps, SRC_PATTERNS;
35180
+ var _isolationDeps, SRC_PATTERNS, LITE_STUB_ADDED_LINES_CEILING = 20;
35155
35181
  var init_isolation = __esm(() => {
35156
35182
  init_test_runners();
35157
35183
  init_bun_deps();
@@ -35235,7 +35261,7 @@ var init_write_test = __esm(() => {
35235
35261
  return parsed;
35236
35262
  const allowedPaths = ctx.config.tdd?.testWriterAllowedPaths ?? ["src/index.ts", "src/**/index.ts"];
35237
35263
  const testFilePatterns = typeof ctx.packageView.config.execution?.smartTestRunner === "object" && ctx.packageView.config.execution.smartTestRunner !== null ? ctx.packageView.config.execution.smartTestRunner.testFilePatterns : undefined;
35238
- const isolation = await verifyTestWriterIsolation(ctx.packageView.packageDir, input.beforeRef, allowedPaths, testFilePatterns);
35264
+ const isolation = await verifyTestWriterIsolation(ctx.packageView.packageDir, input.beforeRef, allowedPaths, testFilePatterns, input.lite ? "lite" : "strict");
35239
35265
  return { ...parsed, isolation };
35240
35266
  }
35241
35267
  };
@@ -54368,10 +54394,13 @@ class ExecutionPlan {
54368
54394
  const phaseOutputs = {};
54369
54395
  const startedAt = Date.now();
54370
54396
  const logger = getSafeLogger();
54371
- const shortCircuitExempt = this.state.rectification ? new Set([
54397
+ const verifierPresent = this.state.verifier !== undefined;
54398
+ const rectificationExempt = this.state.rectification ? [
54372
54399
  ...this.state.fullSuiteGate ? [this.state.fullSuiteGate.slot.op.name] : [],
54373
54400
  ...this.state.verifier ? [this.state.verifier.slot.op.name] : []
54374
- ]) : new Set;
54401
+ ] : [];
54402
+ const verifierExempt = verifierPresent && this.state.fullSuiteGate ? [this.state.fullSuiteGate.slot.op.name] : [];
54403
+ const shortCircuitExempt = new Set([...rectificationExempt, ...verifierExempt]);
54375
54404
  for (const phase of collectOrderedPhases(this.state)) {
54376
54405
  try {
54377
54406
  await runPhase(this.ctx, phase.slot, phaseCosts, phaseOutputs, this.isThreeSession);
@@ -54599,7 +54628,8 @@ async function assemblePlanInputsFromCtx(ctx) {
54599
54628
  story,
54600
54629
  promptMarkdown: testWriterPrompt,
54601
54630
  featureContextMarkdown: ctx.featureContextMarkdown,
54602
- constitution: ctx.constitution?.content
54631
+ constitution: ctx.constitution?.content,
54632
+ lite: isLite
54603
54633
  } : undefined;
54604
54634
  const greenfieldGateInput = _isTdd && _isFreshRun && resolvedTestPatterns ? { story, workdir: ctx.workdir, resolvedTestPatterns } : undefined;
54605
54635
  const implementerInput = {
@@ -54800,6 +54830,13 @@ function deriveTddFailureCategory(phaseOutputs) {
54800
54830
  }
54801
54831
  return "tests-failing";
54802
54832
  }
54833
+ const verifierPassed = verifierOutput?.success === true;
54834
+ if (!verifierPassed) {
54835
+ const gateOutput = phaseOutputs[fullSuiteGateOp.name];
54836
+ if (gateOutput && (gateOutput.success === false || gateOutput.passed === false)) {
54837
+ return "tests-failing";
54838
+ }
54839
+ }
54803
54840
  const implOutput = phaseOutputs[implementerOp.name];
54804
54841
  if (implOutput?.success === false) {
54805
54842
  return "session-failure";
@@ -59182,7 +59219,7 @@ var package_default;
59182
59219
  var init_package = __esm(() => {
59183
59220
  package_default = {
59184
59221
  name: "@nathapp/nax",
59185
- version: "0.67.1",
59222
+ version: "0.67.2",
59186
59223
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
59187
59224
  type: "module",
59188
59225
  bin: {
@@ -59277,8 +59314,8 @@ var init_version = __esm(() => {
59277
59314
  NAX_VERSION = package_default.version;
59278
59315
  NAX_COMMIT = (() => {
59279
59316
  try {
59280
- if (/^[0-9a-f]{6,10}$/.test("be0f8521"))
59281
- return "be0f8521";
59317
+ if (/^[0-9a-f]{6,10}$/.test("d2b13ea6"))
59318
+ return "d2b13ea6";
59282
59319
  } catch {}
59283
59320
  try {
59284
59321
  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.67.1",
3
+ "version": "0.67.2",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {