@nathapp/nax 0.34.0 → 0.35.0
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 +4711 -4419
- package/package.json +1 -2
- package/src/agents/adapters/codex.ts +153 -0
- package/src/agents/claude-plan.ts +22 -5
- package/src/agents/claude.ts +102 -11
- package/src/agents/index.ts +2 -1
- package/src/agents/model-resolution.ts +43 -0
- package/src/agents/registry.ts +2 -1
- package/src/agents/types-extended.ts +5 -1
- package/src/agents/types.ts +31 -0
- package/src/analyze/classifier.ts +30 -50
- package/src/cli/analyze-parser.ts +8 -1
- package/src/cli/analyze.ts +1 -1
- package/src/cli/plan.ts +1 -0
- package/src/config/types.ts +3 -1
- package/src/interaction/init.ts +8 -7
- package/src/interaction/plugins/auto.ts +41 -25
- package/src/pipeline/stages/routing.ts +4 -1
- package/src/plugins/index.ts +2 -0
- package/src/plugins/loader.ts +4 -2
- package/src/plugins/plugin-logger.ts +41 -0
- package/src/plugins/types.ts +50 -1
- package/src/precheck/checks-blockers.ts +37 -1
- package/src/precheck/checks.ts +1 -0
- package/src/precheck/index.ts +2 -2
- package/src/routing/router.ts +1 -0
- package/src/routing/strategies/llm.ts +53 -36
- package/src/routing/strategy.ts +3 -0
- package/src/tdd/rectification-gate.ts +68 -0
- package/src/tdd/session-runner.ts +16 -0
- package/src/tdd/verdict.ts +1 -0
- package/src/verification/rectification-loop.ts +14 -1
|
@@ -162,6 +162,24 @@ async function runRectificationLoop(
|
|
|
162
162
|
await cleanupProcessTree(rectifyResult.pid);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
if (rectifyResult.success) {
|
|
166
|
+
logger.info("tdd", "Rectification agent session complete", {
|
|
167
|
+
storyId: story.id,
|
|
168
|
+
attempt: rectificationState.attempt,
|
|
169
|
+
cost: rectifyResult.estimatedCost,
|
|
170
|
+
});
|
|
171
|
+
} else {
|
|
172
|
+
logger.warn("tdd", "Rectification agent session failed", {
|
|
173
|
+
storyId: story.id,
|
|
174
|
+
attempt: rectificationState.attempt,
|
|
175
|
+
exitCode: rectifyResult.exitCode,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// BUG-063: Auto-commit after rectification agent — prevents uncommitted changes
|
|
180
|
+
// from leaking into verifier/review stages. Same pattern as session-runner.ts.
|
|
181
|
+
await autoCommitIfDirty(workdir, "rectification", story.id, logger);
|
|
182
|
+
|
|
165
183
|
const rectifyIsolation = lite ? undefined : await verifyImplementerIsolation(workdir, rectifyBeforeRef);
|
|
166
184
|
|
|
167
185
|
if (rectifyIsolation && !rectifyIsolation.passed) {
|
|
@@ -191,6 +209,12 @@ async function runRectificationLoop(
|
|
|
191
209
|
testSummary.failed = newTestSummary.failed;
|
|
192
210
|
testSummary.passed = newTestSummary.passed;
|
|
193
211
|
}
|
|
212
|
+
|
|
213
|
+
logger.warn("tdd", "Full suite still failing after rectification attempt", {
|
|
214
|
+
storyId: story.id,
|
|
215
|
+
attempt: rectificationState.attempt,
|
|
216
|
+
remainingFailures: rectificationState.currentFailures,
|
|
217
|
+
});
|
|
194
218
|
}
|
|
195
219
|
|
|
196
220
|
const finalFullSuite = await executeWithTimeout(testCmd, fullSuiteTimeout, undefined, { cwd: workdir });
|
|
@@ -207,3 +231,47 @@ async function runRectificationLoop(
|
|
|
207
231
|
logger.info("tdd", "Full suite gate passed", { storyId: story.id });
|
|
208
232
|
return true;
|
|
209
233
|
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* BUG-063: Auto-commit safety net for rectification agent sessions.
|
|
237
|
+
*
|
|
238
|
+
* Rectification runs agent.run() directly (not via runTddSession), so it
|
|
239
|
+
* needs its own auto-commit. Without this, uncommitted changes from
|
|
240
|
+
* rectification leak into verifier/review stages causing spurious failures.
|
|
241
|
+
*/
|
|
242
|
+
async function autoCommitIfDirty(
|
|
243
|
+
workdir: string,
|
|
244
|
+
role: string,
|
|
245
|
+
storyId: string,
|
|
246
|
+
logger: ReturnType<typeof getLogger>,
|
|
247
|
+
): Promise<void> {
|
|
248
|
+
try {
|
|
249
|
+
const statusProc = Bun.spawn(["git", "status", "--porcelain"], {
|
|
250
|
+
cwd: workdir,
|
|
251
|
+
stdout: "pipe",
|
|
252
|
+
stderr: "pipe",
|
|
253
|
+
});
|
|
254
|
+
const statusOutput = await new Response(statusProc.stdout).text();
|
|
255
|
+
await statusProc.exited;
|
|
256
|
+
|
|
257
|
+
if (!statusOutput.trim()) return;
|
|
258
|
+
|
|
259
|
+
logger.warn("tdd", `Agent did not commit after ${role} session — auto-committing`, {
|
|
260
|
+
role,
|
|
261
|
+
storyId,
|
|
262
|
+
dirtyFiles: statusOutput.trim().split("\n").length,
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
const addProc = Bun.spawn(["git", "add", "-A"], { cwd: workdir, stdout: "pipe", stderr: "pipe" });
|
|
266
|
+
await addProc.exited;
|
|
267
|
+
|
|
268
|
+
const commitProc = Bun.spawn(["git", "commit", "-m", `chore(${storyId}): auto-commit after ${role} session`], {
|
|
269
|
+
cwd: workdir,
|
|
270
|
+
stdout: "pipe",
|
|
271
|
+
stderr: "pipe",
|
|
272
|
+
});
|
|
273
|
+
await commitProc.exited;
|
|
274
|
+
} catch {
|
|
275
|
+
// Silently ignore — auto-commit is best-effort
|
|
276
|
+
}
|
|
277
|
+
}
|
|
@@ -129,6 +129,22 @@ export async function runTddSession(
|
|
|
129
129
|
await cleanupProcessTree(result.pid);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
if (result.success) {
|
|
133
|
+
logger.info("tdd", `Session complete: ${role}`, {
|
|
134
|
+
role,
|
|
135
|
+
storyId: story.id,
|
|
136
|
+
durationMs: Date.now() - startTime,
|
|
137
|
+
cost: result.estimatedCost,
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
logger.warn("tdd", `Session failed: ${role}`, {
|
|
141
|
+
role,
|
|
142
|
+
storyId: story.id,
|
|
143
|
+
durationMs: Date.now() - startTime,
|
|
144
|
+
exitCode: result.exitCode,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
132
148
|
// BUG-058: Auto-commit if agent left uncommitted changes
|
|
133
149
|
await autoCommitIfDirty(workdir, role, story.id);
|
|
134
150
|
|
package/src/tdd/verdict.ts
CHANGED
|
@@ -153,6 +153,7 @@ export async function readVerdict(workdir: string): Promise<VerifierVerdict | nu
|
|
|
153
153
|
if (!isValidVerdict(parsed)) {
|
|
154
154
|
logger.warn("tdd", "Verifier verdict file missing required fields — ignoring", {
|
|
155
155
|
path: verdictPath,
|
|
156
|
+
content: JSON.stringify(parsed).slice(0, 500),
|
|
156
157
|
});
|
|
157
158
|
return null;
|
|
158
159
|
}
|
|
@@ -78,10 +78,17 @@ export async function runRectificationLoop(opts: RectificationLoopOptions): Prom
|
|
|
78
78
|
dangerouslySkipPermissions: config.execution.dangerouslySkipPermissions,
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
if (
|
|
81
|
+
if (agentResult.success) {
|
|
82
|
+
logger?.info("rectification", `Agent ${label} session complete`, {
|
|
83
|
+
storyId: story.id,
|
|
84
|
+
attempt: rectificationState.attempt,
|
|
85
|
+
cost: agentResult.estimatedCost,
|
|
86
|
+
});
|
|
87
|
+
} else {
|
|
82
88
|
logger?.warn("rectification", `Agent ${label} session failed`, {
|
|
83
89
|
storyId: story.id,
|
|
84
90
|
attempt: rectificationState.attempt,
|
|
91
|
+
exitCode: agentResult.exitCode,
|
|
85
92
|
});
|
|
86
93
|
}
|
|
87
94
|
|
|
@@ -116,6 +123,12 @@ export async function runRectificationLoop(opts: RectificationLoopOptions): Prom
|
|
|
116
123
|
testSummary.failed = newTestSummary.failed;
|
|
117
124
|
testSummary.passed = newTestSummary.passed;
|
|
118
125
|
}
|
|
126
|
+
|
|
127
|
+
logger?.warn("rectification", `${label} still failing after attempt`, {
|
|
128
|
+
storyId: story.id,
|
|
129
|
+
attempt: rectificationState.attempt,
|
|
130
|
+
remainingFailures: rectificationState.currentFailures,
|
|
131
|
+
});
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
if (rectificationState.attempt >= rectificationConfig.maxRetries) {
|