@nathapp/nax 0.54.0 → 0.54.1
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/README.md +4 -2
- package/dist/nax.js +34 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,7 +12,9 @@ nax is an **orchestrator, not an agent** — it doesn't write code itself. It dr
|
|
|
12
12
|
- **TDD-enforced** — acceptance tests must fail before implementation starts
|
|
13
13
|
- **Loop until done** — verify, retry, escalate, and regression-check automatically
|
|
14
14
|
- **Monorepo-ready** — per-package config and per-story working directories
|
|
15
|
-
- **Extensible** — plugin system for routing, review, and
|
|
15
|
+
- **Extensible** — plugin system for routing, review, reporting, and post-run actions
|
|
16
|
+
- **Language-aware** — auto-detects Go, Rust, Python, TypeScript from manifest files; adapts commands, test structure, and mocking patterns per language
|
|
17
|
+
- **Semantic review** — LLM-based behavioral review against story acceptance criteria; catches stubs, placeholders, and out-of-scope changes
|
|
16
18
|
|
|
17
19
|
## Install
|
|
18
20
|
|
|
@@ -160,7 +162,7 @@ See [Hooks Guide](docs/guides/hooks.md).
|
|
|
160
162
|
|
|
161
163
|
### Plugins
|
|
162
164
|
|
|
163
|
-
Extensible plugin architecture for prompt optimization, custom routing, code review, and reporting. Plugins live in `.nax/plugins/` (project) or `~/.nax/plugins/` (global).
|
|
165
|
+
Extensible plugin architecture for prompt optimization, custom routing, code review, and reporting. Plugins live in `.nax/plugins/` (project) or `~/.nax/plugins/` (global). Post-run action plugins (e.g. auto-PR creation) can implement `IPostRunAction` for results-aware post-completion workflows.
|
|
164
166
|
|
|
165
167
|
See [Plugins Guide](docs/guides/agents.md#plugins).
|
|
166
168
|
|
package/dist/nax.js
CHANGED
|
@@ -18839,6 +18839,7 @@ __export(exports_generator, {
|
|
|
18839
18839
|
generateAcceptanceTests: () => generateAcceptanceTests,
|
|
18840
18840
|
extractTestCode: () => extractTestCode,
|
|
18841
18841
|
buildAcceptanceTestPrompt: () => buildAcceptanceTestPrompt,
|
|
18842
|
+
buildAcceptanceRunCommand: () => buildAcceptanceRunCommand,
|
|
18842
18843
|
acceptanceTestFilename: () => acceptanceTestFilename,
|
|
18843
18844
|
_generatorPRDDeps: () => _generatorPRDDeps
|
|
18844
18845
|
});
|
|
@@ -18867,6 +18868,26 @@ function acceptanceTestFilename(language) {
|
|
|
18867
18868
|
return "acceptance.test.ts";
|
|
18868
18869
|
}
|
|
18869
18870
|
}
|
|
18871
|
+
function buildAcceptanceRunCommand(testPath, testFramework, commandOverride) {
|
|
18872
|
+
if (commandOverride) {
|
|
18873
|
+
const resolved = commandOverride.replace(/\{\{files\}\}/g, testPath).replace(/\{\{file\}\}/g, testPath).replace(/\{\{FILE\}\}/g, testPath);
|
|
18874
|
+
return resolved.trim().split(/\s+/);
|
|
18875
|
+
}
|
|
18876
|
+
switch (testFramework?.toLowerCase()) {
|
|
18877
|
+
case "vitest":
|
|
18878
|
+
return ["npx", "vitest", "run", testPath];
|
|
18879
|
+
case "jest":
|
|
18880
|
+
return ["npx", "jest", testPath];
|
|
18881
|
+
case "pytest":
|
|
18882
|
+
return ["pytest", testPath];
|
|
18883
|
+
case "go-test":
|
|
18884
|
+
return ["go", "test", testPath];
|
|
18885
|
+
case "cargo-test":
|
|
18886
|
+
return ["cargo", "test", "--test", "acceptance"];
|
|
18887
|
+
default:
|
|
18888
|
+
return ["bun", "test", testPath, "--timeout=60000"];
|
|
18889
|
+
}
|
|
18890
|
+
}
|
|
18870
18891
|
async function generateFromPRD(_stories, refinedCriteria, options) {
|
|
18871
18892
|
const logger = getLogger();
|
|
18872
18893
|
const criteria = refinedCriteria.map((c, i) => ({
|
|
@@ -22299,7 +22320,7 @@ var package_default;
|
|
|
22299
22320
|
var init_package = __esm(() => {
|
|
22300
22321
|
package_default = {
|
|
22301
22322
|
name: "@nathapp/nax",
|
|
22302
|
-
version: "0.54.
|
|
22323
|
+
version: "0.54.1",
|
|
22303
22324
|
description: "AI Coding Agent Orchestrator \u2014 loops until done",
|
|
22304
22325
|
type: "module",
|
|
22305
22326
|
bin: {
|
|
@@ -22376,8 +22397,8 @@ var init_version = __esm(() => {
|
|
|
22376
22397
|
NAX_VERSION = package_default.version;
|
|
22377
22398
|
NAX_COMMIT = (() => {
|
|
22378
22399
|
try {
|
|
22379
|
-
if (/^[0-9a-f]{6,10}$/.test("
|
|
22380
|
-
return "
|
|
22400
|
+
if (/^[0-9a-f]{6,10}$/.test("5282117"))
|
|
22401
|
+
return "5282117";
|
|
22381
22402
|
} catch {}
|
|
22382
22403
|
try {
|
|
22383
22404
|
const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
|
|
@@ -24041,6 +24062,7 @@ function areAllStoriesComplete(ctx) {
|
|
|
24041
24062
|
}
|
|
24042
24063
|
var acceptanceStage;
|
|
24043
24064
|
var init_acceptance2 = __esm(() => {
|
|
24065
|
+
init_generator();
|
|
24044
24066
|
init_logger2();
|
|
24045
24067
|
init_prd();
|
|
24046
24068
|
acceptanceStage = {
|
|
@@ -24072,14 +24094,8 @@ var init_acceptance2 = __esm(() => {
|
|
|
24072
24094
|
});
|
|
24073
24095
|
return { action: "continue" };
|
|
24074
24096
|
}
|
|
24075
|
-
const
|
|
24076
|
-
|
|
24077
|
-
if (acceptanceCmd) {
|
|
24078
|
-
const resolved = acceptanceCmd.includes("{{FILE}}") ? acceptanceCmd.replace("{{FILE}}", testPath) : acceptanceCmd;
|
|
24079
|
-
testCmdParts = resolved.trim().split(/\s+/);
|
|
24080
|
-
} else {
|
|
24081
|
-
testCmdParts = ["bun", "test", testPath, "--timeout=60000"];
|
|
24082
|
-
}
|
|
24097
|
+
const testCmdParts = buildAcceptanceRunCommand(testPath, effectiveConfig.project?.testFramework, effectiveConfig.acceptance.command);
|
|
24098
|
+
logger.info("acceptance", "Running acceptance command", { cmd: testCmdParts.join(" ") });
|
|
24083
24099
|
const proc = Bun.spawn(testCmdParts, {
|
|
24084
24100
|
cwd: ctx.workdir,
|
|
24085
24101
|
stdout: "pipe",
|
|
@@ -24252,6 +24268,7 @@ var init_acceptance_setup = __esm(() => {
|
|
|
24252
24268
|
init_generator();
|
|
24253
24269
|
init_registry();
|
|
24254
24270
|
init_config();
|
|
24271
|
+
init_logger2();
|
|
24255
24272
|
_acceptanceSetupDeps = {
|
|
24256
24273
|
getAgent,
|
|
24257
24274
|
fileExists: async (_path) => {
|
|
@@ -24282,14 +24299,8 @@ var init_acceptance_setup = __esm(() => {
|
|
|
24282
24299
|
writeMeta: async (metaPath, meta3) => {
|
|
24283
24300
|
await Bun.write(metaPath, JSON.stringify(meta3, null, 2));
|
|
24284
24301
|
},
|
|
24285
|
-
runTest: async (_testPath, _workdir,
|
|
24286
|
-
|
|
24287
|
-
if (_testCmd) {
|
|
24288
|
-
const parts = _testCmd.trim().split(/\s+/);
|
|
24289
|
-
cmd = [...parts, _testPath];
|
|
24290
|
-
} else {
|
|
24291
|
-
cmd = ["bun", "test", _testPath];
|
|
24292
|
-
}
|
|
24302
|
+
runTest: async (_testPath, _workdir, _cmd) => {
|
|
24303
|
+
const cmd = _cmd;
|
|
24293
24304
|
const proc = Bun.spawn(cmd, {
|
|
24294
24305
|
cwd: _workdir,
|
|
24295
24306
|
stdout: "pipe",
|
|
@@ -24386,8 +24397,10 @@ ${stderr}` };
|
|
|
24386
24397
|
ctx.acceptanceSetup = { totalCriteria, testableCount, redFailCount: 0 };
|
|
24387
24398
|
return { action: "continue" };
|
|
24388
24399
|
}
|
|
24389
|
-
const
|
|
24390
|
-
const
|
|
24400
|
+
const effectiveConfig = ctx.effectiveConfig ?? ctx.config;
|
|
24401
|
+
const runCmd = buildAcceptanceRunCommand(testPath, effectiveConfig.project?.testFramework, effectiveConfig.acceptance.command);
|
|
24402
|
+
getSafeLogger()?.info("acceptance-setup", "Running acceptance RED gate command", { cmd: runCmd.join(" ") });
|
|
24403
|
+
const { exitCode } = await _acceptanceSetupDeps.runTest(testPath, ctx.workdir, runCmd);
|
|
24391
24404
|
if (exitCode === 0) {
|
|
24392
24405
|
ctx.acceptanceSetup = { totalCriteria, testableCount, redFailCount: 0 };
|
|
24393
24406
|
return {
|