@nathapp/nax 0.67.14 → 0.67.16
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 +158 -32
- package/package.json +1 -1
package/dist/nax.js
CHANGED
|
@@ -52720,6 +52720,71 @@ var init_context2 = __esm(() => {
|
|
|
52720
52720
|
});
|
|
52721
52721
|
|
|
52722
52722
|
// src/execution/story-orchestrator.ts
|
|
52723
|
+
async function refreshReviewInputForDispatch(opName, input) {
|
|
52724
|
+
if (opName !== "semantic-review" && opName !== "adversarial-review")
|
|
52725
|
+
return input;
|
|
52726
|
+
const i = input;
|
|
52727
|
+
const { _refresh } = i;
|
|
52728
|
+
if (!_refresh || !i.workdir)
|
|
52729
|
+
return input;
|
|
52730
|
+
try {
|
|
52731
|
+
if (opName === "semantic-review") {
|
|
52732
|
+
const { _refresh: _, ...semInput } = input;
|
|
52733
|
+
const fresh2 = await _storyOrchestratorDeps.prepareSemanticReviewInput({
|
|
52734
|
+
workdir: semInput.workdir,
|
|
52735
|
+
projectDir: _refresh.projectDir,
|
|
52736
|
+
storyId: _refresh.storyId,
|
|
52737
|
+
storyGitRef: _refresh.storyGitRef,
|
|
52738
|
+
config: _refresh.config,
|
|
52739
|
+
naxIgnoreIndex: _refresh.naxIgnoreIndex,
|
|
52740
|
+
resolvedTestPatterns: _refresh.resolvedTestPatterns,
|
|
52741
|
+
semanticConfig: semInput.semanticConfig
|
|
52742
|
+
});
|
|
52743
|
+
return {
|
|
52744
|
+
...semInput,
|
|
52745
|
+
stat: fresh2.stat,
|
|
52746
|
+
diff: fresh2.diff,
|
|
52747
|
+
excludePatterns: fresh2.excludePatterns,
|
|
52748
|
+
storyGitRef: fresh2.effectiveRef ?? semInput.storyGitRef
|
|
52749
|
+
};
|
|
52750
|
+
}
|
|
52751
|
+
const { _refresh: __, ...advInput } = input;
|
|
52752
|
+
const fresh = await _storyOrchestratorDeps.prepareAdversarialReviewInput({
|
|
52753
|
+
workdir: advInput.workdir,
|
|
52754
|
+
projectDir: _refresh.projectDir,
|
|
52755
|
+
storyId: _refresh.storyId,
|
|
52756
|
+
storyGitRef: _refresh.storyGitRef,
|
|
52757
|
+
config: _refresh.config,
|
|
52758
|
+
naxIgnoreIndex: _refresh.naxIgnoreIndex,
|
|
52759
|
+
resolvedTestPatterns: _refresh.resolvedTestPatterns,
|
|
52760
|
+
adversarialConfig: advInput.adversarialConfig
|
|
52761
|
+
});
|
|
52762
|
+
return {
|
|
52763
|
+
...advInput,
|
|
52764
|
+
stat: fresh.stat,
|
|
52765
|
+
diff: fresh.diff,
|
|
52766
|
+
testInventory: fresh.testInventory,
|
|
52767
|
+
excludePatterns: fresh.excludePatterns,
|
|
52768
|
+
testGlobs: fresh.testGlobs,
|
|
52769
|
+
refExcludePatterns: fresh.refExcludePatterns,
|
|
52770
|
+
storyGitRef: fresh.effectiveRef ?? advInput.storyGitRef
|
|
52771
|
+
};
|
|
52772
|
+
} catch (err) {
|
|
52773
|
+
getSafeLogger()?.warn("story-orchestrator", "review input refresh failed \u2014 dispatching with stale input", {
|
|
52774
|
+
storyId: _refresh.storyId,
|
|
52775
|
+
phase: opName,
|
|
52776
|
+
error: errorMessage(err)
|
|
52777
|
+
});
|
|
52778
|
+
const { _refresh: _stripped, ...fallback } = input;
|
|
52779
|
+
return fallback;
|
|
52780
|
+
}
|
|
52781
|
+
}
|
|
52782
|
+
function formatPhaseResultMessage(opName, success2) {
|
|
52783
|
+
if (opName === "greenfield-gate") {
|
|
52784
|
+
return success2 ? "Greenfield-gate: pre-existing tests detected (not greenfield) \u2014 proceeding with normal TDD" : "Greenfield-gate: no pre-existing tests \u2014 greenfield run, pausing TDD test-writer";
|
|
52785
|
+
}
|
|
52786
|
+
return success2 ? `Phase passed: ${opName}` : `Phase failed: ${opName}`;
|
|
52787
|
+
}
|
|
52723
52788
|
function isSlot(value) {
|
|
52724
52789
|
return value !== null && typeof value === "object" && "op" in value && "input" in value && typeof value.op?.kind === "string";
|
|
52725
52790
|
}
|
|
@@ -52832,19 +52897,18 @@ function collectRectificationPhases(state) {
|
|
|
52832
52897
|
].filter((phase) => phase !== undefined);
|
|
52833
52898
|
}
|
|
52834
52899
|
function phasesToRevalidate(strategiesRun, allPhases) {
|
|
52835
|
-
const sourceFiltered = allPhases.filter((p) => p.kind !== "verifier");
|
|
52836
52900
|
if (!strategiesRun || strategiesRun.length === 0)
|
|
52837
|
-
return
|
|
52901
|
+
return allPhases;
|
|
52838
52902
|
const unknown2 = strategiesRun.some((name) => STRATEGY_TO_REVALIDATION_PHASES[name] === undefined);
|
|
52839
52903
|
if (unknown2)
|
|
52840
|
-
return
|
|
52904
|
+
return allPhases;
|
|
52841
52905
|
const needed = new Set;
|
|
52842
52906
|
for (const name of strategiesRun) {
|
|
52843
52907
|
for (const kind of STRATEGY_TO_REVALIDATION_PHASES[name] ?? []) {
|
|
52844
52908
|
needed.add(kind);
|
|
52845
52909
|
}
|
|
52846
52910
|
}
|
|
52847
|
-
return
|
|
52911
|
+
return allPhases.filter((p) => needed.has(p.kind));
|
|
52848
52912
|
}
|
|
52849
52913
|
function toReviewDecisionPayload(opName, output) {
|
|
52850
52914
|
if (output === null || output === undefined || typeof output !== "object")
|
|
@@ -52928,10 +52992,11 @@ function logDeterministicPhaseOutcome(storyId, opName, output, durationMs, isTdd
|
|
|
52928
52992
|
data.findingsCount = findingsCount;
|
|
52929
52993
|
if (status !== undefined)
|
|
52930
52994
|
data.status = status;
|
|
52995
|
+
const message = formatPhaseResultMessage(opName, success2);
|
|
52931
52996
|
if (success2) {
|
|
52932
|
-
logger?.info("story-orchestrator",
|
|
52997
|
+
logger?.info("story-orchestrator", message, data);
|
|
52933
52998
|
} else {
|
|
52934
|
-
logger?.warn("story-orchestrator",
|
|
52999
|
+
logger?.warn("story-orchestrator", message, data);
|
|
52935
53000
|
}
|
|
52936
53001
|
}
|
|
52937
53002
|
function logUnifiedReviewPhaseResult(storyId, opName, output) {
|
|
@@ -52989,7 +53054,8 @@ async function runPhase(ctx, slot, phaseCosts, phaseOutputs, isThreeSession = fa
|
|
|
52989
53054
|
const opName = slot.op.name;
|
|
52990
53055
|
const isTddPhase = isThreeSession && TDD_OP_NAMES.has(opName);
|
|
52991
53056
|
const beforeRef = isTddPhase ? await _storyOrchestratorDeps.captureGitRef(ctx.packageDir) : undefined;
|
|
52992
|
-
|
|
53057
|
+
let dispatchInput = isTddPhase && beforeRef ? { ...slot.input, beforeRef } : slot.input;
|
|
53058
|
+
dispatchInput = await refreshReviewInputForDispatch(opName, dispatchInput);
|
|
52993
53059
|
if (isTddPhase) {
|
|
52994
53060
|
logger?.info("tdd", `-> Session: ${opName}`, { storyId: ctx.storyId, role: opName });
|
|
52995
53061
|
} else if (isThreeSession && opName === "full-suite-gate") {
|
|
@@ -53100,13 +53166,26 @@ async function runRectification(ctx, state, phaseCosts, phaseOutputs) {
|
|
|
53100
53166
|
await runPhase(ctx, phase.slot, phaseCosts, phaseOutputs);
|
|
53101
53167
|
if (shouldSkipPhaseForRectification(phase, state, phaseOutputs))
|
|
53102
53168
|
continue;
|
|
53103
|
-
|
|
53169
|
+
const output = phaseOutputs[phase.slot.op.name];
|
|
53170
|
+
findings.push(...extractPhaseFindings(output));
|
|
53171
|
+
if (!phasePassed(phase.slot.op.name, output, ctx.storyId)) {
|
|
53172
|
+
getSafeLogger()?.warn("story-orchestrator", "Short-circuiting revalidation on phase failure", {
|
|
53173
|
+
storyId: ctx.storyId,
|
|
53174
|
+
phase: phase.slot.op.name
|
|
53175
|
+
});
|
|
53176
|
+
break;
|
|
53177
|
+
}
|
|
53104
53178
|
}
|
|
53105
53179
|
return rectification.postValidate ? await rectification.postValidate(findings, _validateCtx) : findings;
|
|
53106
53180
|
}
|
|
53107
53181
|
};
|
|
53108
53182
|
const cycleResult = await _storyOrchestratorDeps.runFixCycle(cycle, ctx, "story-orchestrator-rectification", { callOp: wrappedCallOp });
|
|
53109
|
-
phaseOutputs.rectification = {
|
|
53183
|
+
phaseOutputs.rectification = {
|
|
53184
|
+
success: cycleResult.exitReason === "resolved",
|
|
53185
|
+
iterationCount: cycleResult.iterations.length,
|
|
53186
|
+
exitReason: cycleResult.exitReason,
|
|
53187
|
+
finalFindingsCount: cycleResult.finalFindings.length
|
|
53188
|
+
};
|
|
53110
53189
|
const rectLogger = getSafeLogger();
|
|
53111
53190
|
const rectSummary = {
|
|
53112
53191
|
storyId: ctx.storyId,
|
|
@@ -53160,13 +53239,6 @@ class ExecutionPlan {
|
|
|
53160
53239
|
const phaseOutputs = {};
|
|
53161
53240
|
const startedAt = Date.now();
|
|
53162
53241
|
const logger = getSafeLogger();
|
|
53163
|
-
const verifierPresent = this.state.verifier !== undefined;
|
|
53164
|
-
const rectificationExempt = this.state.rectification ? [
|
|
53165
|
-
...this.state.fullSuiteGate ? [this.state.fullSuiteGate.slot.op.name] : [],
|
|
53166
|
-
...this.state.verifier ? [this.state.verifier.slot.op.name] : []
|
|
53167
|
-
] : [];
|
|
53168
|
-
const verifierExempt = verifierPresent && this.state.fullSuiteGate ? [this.state.fullSuiteGate.slot.op.name] : [];
|
|
53169
|
-
const shortCircuitExempt = new Set([...rectificationExempt, ...verifierExempt]);
|
|
53170
53242
|
for (const phase of collectOrderedPhases(this.state)) {
|
|
53171
53243
|
try {
|
|
53172
53244
|
await runPhase(this.ctx, phase.slot, phaseCosts, phaseOutputs, this.isThreeSession);
|
|
@@ -53179,16 +53251,40 @@ class ExecutionPlan {
|
|
|
53179
53251
|
throw error48;
|
|
53180
53252
|
}
|
|
53181
53253
|
if (!phasePassed(phase.slot.op.name, phaseOutputs[phase.slot.op.name], this.ctx.storyId)) {
|
|
53182
|
-
|
|
53183
|
-
|
|
53254
|
+
logger?.warn("story-orchestrator", "Short-circuiting on phase failure", {
|
|
53255
|
+
storyId: this.ctx.storyId,
|
|
53256
|
+
phase: phase.slot.op.name
|
|
53257
|
+
});
|
|
53258
|
+
break;
|
|
53259
|
+
}
|
|
53260
|
+
}
|
|
53261
|
+
const rectResult = await runRectification(this.ctx, this.state, phaseCosts, phaseOutputs);
|
|
53262
|
+
if (this.state.rectification && !rectResult.rectificationExhausted) {
|
|
53263
|
+
for (const phase of collectOrderedPhases(this.state)) {
|
|
53264
|
+
const name = phase.slot.op.name;
|
|
53265
|
+
if (name in phaseOutputs && phasePassed(name, phaseOutputs[name], this.ctx.storyId)) {
|
|
53266
|
+
continue;
|
|
53267
|
+
}
|
|
53268
|
+
try {
|
|
53269
|
+
await runPhase(this.ctx, phase.slot, phaseCosts, phaseOutputs, this.isThreeSession);
|
|
53270
|
+
} catch (error48) {
|
|
53271
|
+
logger?.error("story-orchestrator", "Phase threw unexpected error (post-rectification resume)", {
|
|
53184
53272
|
storyId: this.ctx.storyId,
|
|
53185
|
-
phase:
|
|
53273
|
+
phase: name,
|
|
53274
|
+
error: errorMessage(error48)
|
|
53275
|
+
});
|
|
53276
|
+
throw error48;
|
|
53277
|
+
}
|
|
53278
|
+
if (!phasePassed(name, phaseOutputs[name], this.ctx.storyId)) {
|
|
53279
|
+
logger?.warn("story-orchestrator", "Terminal phase failure (post-rectification resume \u2014 bypasses rectification)", {
|
|
53280
|
+
storyId: this.ctx.storyId,
|
|
53281
|
+
phase: name,
|
|
53282
|
+
source: "post-rectification-resume"
|
|
53186
53283
|
});
|
|
53187
53284
|
break;
|
|
53188
53285
|
}
|
|
53189
53286
|
}
|
|
53190
53287
|
}
|
|
53191
|
-
const rectResult = await runRectification(this.ctx, this.state, phaseCosts, phaseOutputs);
|
|
53192
53288
|
const verifierName = this.state.verifier?.slot.op.name;
|
|
53193
53289
|
const gateName = this.state.fullSuiteGate?.slot.op.name;
|
|
53194
53290
|
const verifierPassedSsot = verifierName !== undefined && phaseExplicitlyPassed(phaseOutputs[verifierName]);
|
|
@@ -53295,11 +53391,14 @@ var init_story_orchestrator = __esm(() => {
|
|
|
53295
53391
|
init_logger2();
|
|
53296
53392
|
init_operations();
|
|
53297
53393
|
init_call();
|
|
53394
|
+
init_prepare_inputs();
|
|
53298
53395
|
init_git();
|
|
53299
53396
|
_storyOrchestratorDeps = {
|
|
53300
53397
|
callOp,
|
|
53301
53398
|
runFixCycle,
|
|
53302
|
-
captureGitRef
|
|
53399
|
+
captureGitRef,
|
|
53400
|
+
prepareSemanticReviewInput,
|
|
53401
|
+
prepareAdversarialReviewInput
|
|
53303
53402
|
};
|
|
53304
53403
|
TDD_OP_NAMES = new Set(["test-writer", "implementer", "verifier"]);
|
|
53305
53404
|
STRICT_VERDICT_PHASE_NAMES = new Set([
|
|
@@ -53340,12 +53439,27 @@ var init_story_orchestrator = __esm(() => {
|
|
|
53340
53439
|
"lint-check",
|
|
53341
53440
|
"typecheck-check",
|
|
53342
53441
|
"full-suite-gate",
|
|
53442
|
+
"verifier",
|
|
53343
53443
|
"verify-scoped",
|
|
53344
53444
|
"semantic-review",
|
|
53345
53445
|
"adversarial-review"
|
|
53346
53446
|
],
|
|
53347
|
-
"autofix-test-writer": [
|
|
53348
|
-
|
|
53447
|
+
"autofix-test-writer": [
|
|
53448
|
+
"lint-check",
|
|
53449
|
+
"typecheck-check",
|
|
53450
|
+
"full-suite-gate",
|
|
53451
|
+
"verifier",
|
|
53452
|
+
"verify-scoped",
|
|
53453
|
+
"adversarial-review"
|
|
53454
|
+
],
|
|
53455
|
+
"full-suite-rectify": [
|
|
53456
|
+
"lint-check",
|
|
53457
|
+
"typecheck-check",
|
|
53458
|
+
"full-suite-gate",
|
|
53459
|
+
"verifier",
|
|
53460
|
+
"verify-scoped",
|
|
53461
|
+
"semantic-review"
|
|
53462
|
+
]
|
|
53349
53463
|
};
|
|
53350
53464
|
});
|
|
53351
53465
|
|
|
@@ -53584,8 +53698,6 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
53584
53698
|
resolvedTestPatterns,
|
|
53585
53699
|
semanticConfig: ctx.config.review.semantic
|
|
53586
53700
|
});
|
|
53587
|
-
if (prepared.skipReason)
|
|
53588
|
-
return;
|
|
53589
53701
|
return {
|
|
53590
53702
|
workdir: ctx.workdir,
|
|
53591
53703
|
story,
|
|
@@ -53597,7 +53709,15 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
53597
53709
|
excludePatterns: prepared.excludePatterns,
|
|
53598
53710
|
featureCtxBlock: buildFeatureCtxBlock(ctx, "reviewer-semantic"),
|
|
53599
53711
|
priorSemanticIterations: ctx.priorSemanticIterations,
|
|
53600
|
-
blockingThreshold: ctx.config.review.blockingThreshold
|
|
53712
|
+
blockingThreshold: ctx.config.review.blockingThreshold,
|
|
53713
|
+
_refresh: {
|
|
53714
|
+
projectDir: ctx.projectDir,
|
|
53715
|
+
storyId: story.id,
|
|
53716
|
+
storyGitRef: ctx.storyGitRef,
|
|
53717
|
+
config: ctx.config,
|
|
53718
|
+
naxIgnoreIndex: ctx.naxIgnoreIndex,
|
|
53719
|
+
resolvedTestPatterns
|
|
53720
|
+
}
|
|
53601
53721
|
};
|
|
53602
53722
|
})() : undefined;
|
|
53603
53723
|
const adversarialEnabled = ctx.config.review?.enabled === true && ctx.config.review.checks?.includes("adversarial") && !!ctx.config.review.adversarial;
|
|
@@ -53612,8 +53732,6 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
53612
53732
|
resolvedTestPatterns,
|
|
53613
53733
|
adversarialConfig: ctx.config.review.adversarial
|
|
53614
53734
|
});
|
|
53615
|
-
if (prepared.skipReason)
|
|
53616
|
-
return;
|
|
53617
53735
|
return {
|
|
53618
53736
|
workdir: ctx.workdir,
|
|
53619
53737
|
story,
|
|
@@ -53628,7 +53746,15 @@ async function assemblePlanInputsFromCtx(ctx) {
|
|
|
53628
53746
|
refExcludePatterns: prepared.refExcludePatterns,
|
|
53629
53747
|
featureCtxBlock: buildFeatureCtxBlock(ctx, "reviewer-adversarial"),
|
|
53630
53748
|
priorAdversarialIterations: ctx.priorAdversarialIterations,
|
|
53631
|
-
blockingThreshold: ctx.config.review.blockingThreshold
|
|
53749
|
+
blockingThreshold: ctx.config.review.blockingThreshold,
|
|
53750
|
+
_refresh: {
|
|
53751
|
+
projectDir: ctx.projectDir,
|
|
53752
|
+
storyId: story.id,
|
|
53753
|
+
storyGitRef: ctx.storyGitRef,
|
|
53754
|
+
config: ctx.config,
|
|
53755
|
+
naxIgnoreIndex: ctx.naxIgnoreIndex,
|
|
53756
|
+
resolvedTestPatterns
|
|
53757
|
+
}
|
|
53632
53758
|
};
|
|
53633
53759
|
})() : undefined;
|
|
53634
53760
|
const rectificationInput = ctx.config.execution?.rectification?.enabled === true ? {
|
|
@@ -57683,7 +57809,7 @@ var package_default;
|
|
|
57683
57809
|
var init_package = __esm(() => {
|
|
57684
57810
|
package_default = {
|
|
57685
57811
|
name: "@nathapp/nax",
|
|
57686
|
-
version: "0.67.
|
|
57812
|
+
version: "0.67.16",
|
|
57687
57813
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
57688
57814
|
type: "module",
|
|
57689
57815
|
bin: {
|
|
@@ -57778,8 +57904,8 @@ var init_version = __esm(() => {
|
|
|
57778
57904
|
NAX_VERSION = package_default.version;
|
|
57779
57905
|
NAX_COMMIT = (() => {
|
|
57780
57906
|
try {
|
|
57781
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
57782
|
-
return "
|
|
57907
|
+
if (/^[0-9a-f]{6,10}$/.test("215c9e93"))
|
|
57908
|
+
return "215c9e93";
|
|
57783
57909
|
} catch {}
|
|
57784
57910
|
try {
|
|
57785
57911
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|