@nathapp/nax 0.51.0 → 0.51.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 (3) hide show
  1. package/README.md +177 -104
  2. package/dist/nax.js +35 -27
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -33,15 +33,20 @@ nax run -f my-feature --plan --from spec.md
33
33
  ## How It Works
34
34
 
35
35
  ```
36
- analyze → route → execute → verify → (loop until all stories pass) → regression gate
36
+ (plan) acceptance setup → route → execute → verify → (escalate) → regression gate → acceptance
37
37
  ```
38
38
 
39
- 1. **Analyze** each user story classify complexity, select test strategy
40
- 2. **Route** to the right model tier (cheap standard premium)
41
- 3. **Execute** an agent session (Claude Code by default)
42
- 4. **Verify** tests pass; escalate model tier on failure
43
- 5. **Loop** until all stories are complete or a cost/iteration limit is hit
44
- 6. **Regression gate** — deferred full-suite verification after all stories pass
39
+ 1. **Plan** *(optional)* `nax run --plan` generates a `prd.json` from a spec file using an LLM
40
+ 2. **Acceptance setup** *(pre-run)* generate acceptance tests and assert RED (tests must fail before implementation)
41
+ 3. **Route** classify story complexity and select model tier (fast balanced → powerful)
42
+ 4. **Context** gather relevant code, tests, and project standards
43
+ 5. **Execute** run an agent session (Claude Code, Codex, Gemini CLI, or ACP)
44
+ 6. **Verify** — run scoped tests; if failing, **rectify** before escalating
45
+ 7. **Review** — lint + typecheck; if failing, **autofix** before escalating
46
+ 8. **Escalate** — on repeated failure, retry with a higher model tier
47
+ 9. **Loop** — repeat steps 3–8 per story until all pass or a cost/iteration limit is hit
48
+ 10. **Regression gate** — deferred full-suite run after all stories pass
49
+ 11. **Acceptance** *(post-run)* — run the generated acceptance tests against the completed feature
45
50
 
46
51
  ---
47
52
 
@@ -49,7 +54,7 @@ analyze → route → execute → verify → (loop until all stories pass) → r
49
54
 
50
55
  ### `nax init`
51
56
 
52
- Initialize nax in your project. Creates the `nax/` folder structure.
57
+ Initialize nax in your project. Creates the `.nax/` folder structure.
53
58
 
54
59
  ```bash
55
60
  nax init
@@ -57,7 +62,7 @@ nax init
57
62
 
58
63
  Creates:
59
64
  ```
60
- nax/
65
+ .nax/
61
66
  ├── config.json # Project-level config
62
67
  └── features/ # One folder per feature
63
68
  ```
@@ -68,7 +73,7 @@ nax/
68
73
  nax init --package packages/api
69
74
  ```
70
75
 
71
- Creates `packages/api/nax/context.md` for per-package agent context.
76
+ Creates `.nax/mono/packages/api/context.md` for per-package agent context.
72
77
 
73
78
  ---
74
79
 
@@ -80,7 +85,7 @@ Scaffold a new feature.
80
85
  nax features create user-auth
81
86
  ```
82
87
 
83
- Creates `nax/features/user-auth/prd.json` — edit this file to define your user stories.
88
+ Creates `.nax/features/user-auth/spec.md` — fill in the overview, user stories, and acceptance criteria, then run `nax plan` to generate `prd.json`.
84
89
 
85
90
  ### `nax features list`
86
91
 
@@ -135,7 +140,7 @@ nax run -f my-feature
135
140
  | Flag | Description |
136
141
  |:-----|:------------|
137
142
  | `-f, --feature <name>` | Feature name |
138
- | `-a, --agent <name>` | Force a specific agent (`claude`, `opencode`, `codex`, etc.) |
143
+ | `-a, --agent <name>` | Force a specific agent (`claude`, `opencode`, `codex`, etc.). Only applies when `agent.protocol = "cli"` — ignored when using ACP protocol. |
139
144
  | `--plan` | Run plan phase first (requires `--from`) |
140
145
  | `--from <spec-path>` | Spec file for `--plan` |
141
146
  | `--one-shot` | Skip interactive Q&A during planning (ACP only) |
@@ -201,21 +206,28 @@ nax status -f my-feature
201
206
 
202
207
  ---
203
208
 
204
- ### `nax logs -f <name>`
209
+ ### `nax logs`
205
210
 
206
- Stream logs from the current or last run.
211
+ Stream logs from the current or last run. Run from your project directory.
207
212
 
208
213
  ```bash
209
- nax logs -f my-feature
214
+ # List all recorded runs
215
+ nax logs --list
210
216
 
211
- # Follow in real-time
212
- nax logs -f my-feature --follow
217
+ # Follow current run in real-time
218
+ nax logs --follow
213
219
 
214
220
  # Filter by story
215
- nax logs -f my-feature --story US-003
221
+ nax logs --story US-003
216
222
 
217
- # Filter by level
218
- nax logs -f my-feature --level error
223
+ # Filter by log level
224
+ nax logs --level error
225
+
226
+ # Select a specific run by ID
227
+ nax logs --run <runId>
228
+
229
+ # Raw JSONL output (for scripting)
230
+ nax logs --json
219
231
  ```
220
232
 
221
233
  ---
@@ -255,7 +267,7 @@ Output sections:
255
267
 
256
268
  ### `nax generate`
257
269
 
258
- Generate agent config files from `nax/context.md`. Supports Claude Code, OpenCode, Codex, Cursor, Windsurf, Aider, and Gemini.
270
+ Generate agent config files from `.nax/context.md`. Supports Claude Code, OpenCode, Codex, Cursor, Windsurf, Aider, and Gemini.
259
271
 
260
272
  ```bash
261
273
  nax generate
@@ -265,7 +277,7 @@ nax generate
265
277
 
266
278
  | Flag | Description |
267
279
  |:-----|:------------|
268
- | `-c, --context <path>` | Context file path (default: `nax/context.md`) |
280
+ | `-c, --context <path>` | Context file path (default: `.nax/context.md`) |
269
281
  | `-o, --output <dir>` | Output directory (default: project root) |
270
282
  | `-a, --agent <name>` | Generate for a specific agent only (`claude`, `opencode`, `cursor`, `windsurf`, `aider`, `codex`, `gemini`) |
271
283
  | `--dry-run` | Preview without writing files |
@@ -287,7 +299,7 @@ nax generate
287
299
 
288
300
  **Workflow:**
289
301
 
290
- 1. Create `nax/context.md` — describe your project's architecture, conventions, and coding standards
302
+ 1. Create `.nax/context.md` — describe your project's architecture, conventions, and coding standards
291
303
  2. Run `nax generate` — writes agent config files to the project root (and per-package if configured)
292
304
  3. Commit the generated files — your agents will automatically pick them up
293
305
 
@@ -301,7 +313,7 @@ nax generate --package packages/api
301
313
  nax generate --all-packages
302
314
  ```
303
315
 
304
- Each package can have its own `nax/context.md` at `<package>/nax/context.md` for package-specific agent instructions.
316
+ Each package can have its own context file at `.nax/mono/<package>/context.md` for package-specific agent instructions (created via `nax init --package <package>`).
305
317
 
306
318
  ---
307
319
 
@@ -317,7 +329,7 @@ nax prompts -f my-feature
317
329
 
318
330
  | Flag | Description |
319
331
  |:-----|:------------|
320
- | `--init` | Export default role templates to `nax/templates/` for customization |
332
+ | `--init` | Export default role templates to `.nax/templates/` for customization |
321
333
  | `--role <role>` | Show prompt for a specific role (`implementer`, `test-writer`, `verifier`, `tdd-simple`) |
322
334
 
323
335
  After running `--init`, edit the templates and nax will use them automatically via `prompts.overrides` config.
@@ -354,12 +366,19 @@ nax agents
354
366
 
355
367
  ---
356
368
 
357
- ### `nax config --explain`
369
+ ### `nax config`
358
370
 
359
- Display the effective merged configuration with inline explanations for every field.
371
+ Display the effective merged configuration (global + project layers).
360
372
 
361
373
  ```bash
362
- nax config -f my-feature --explain
374
+ # Show merged config
375
+ nax config
376
+
377
+ # Show with field descriptions
378
+ nax config --explain
379
+
380
+ # Show only fields where project overrides global
381
+ nax config --diff
363
382
  ```
364
383
 
365
384
  ---
@@ -371,7 +390,7 @@ Config is layered — project overrides global:
371
390
  | File | Scope |
372
391
  |:-----|:------|
373
392
  | `~/.nax/config.json` | Global (all projects) |
374
- | `nax/config.json` | Project-level override |
393
+ | `.nax/config.json` | Project-level override |
375
394
 
376
395
  **Key options:**
377
396
 
@@ -414,7 +433,7 @@ Review commands (`lint`, `typecheck`) are executed directly via `Bun.spawn` —
414
433
  }
415
434
  ```
416
435
  ```json
417
- // nax/config.json
436
+ // .nax/config.json
418
437
  "quality": {
419
438
  "commands": {
420
439
  "typecheck": "bun run build-and-check"
@@ -442,13 +461,15 @@ Use `testScoped` to define the exact scoped test command with a `{{files}}` plac
442
461
 
443
462
  If `testScoped` is not configured, nax falls back to a heuristic that replaces the last path-like token in the `test` command. **Recommended:** always configure `testScoped` explicitly to avoid surprises.
444
463
 
445
- **TDD strategy options:**
464
+ **TDD strategy options:** <a name="tdd-strategy-options"></a>
446
465
 
447
466
  | Value | Behaviour |
448
467
  |:------|:----------|
449
- | `auto` | nax decides based on complexity and tags |
450
- | `lite` | Prefer `three-session-tdd-lite` for complex stories |
451
- | `strict` | Always use full `three-session-tdd` for complex stories |
468
+ | `auto` | nax decides based on complexity and tags — simple→`tdd-simple`, security/public-api→`three-session-tdd`, else→`three-session-tdd-lite` |
469
+ | `strict` | Always use `three-session-tdd` (strictest all stories) |
470
+ | `lite` | Always use `three-session-tdd-lite` |
471
+ | `simple` | Always use `tdd-simple` (1 session) |
472
+ | `off` | No TDD — tests written after implementation (`test-after`) |
452
473
 
453
474
  ---
454
475
 
@@ -462,12 +483,12 @@ Customize the instructions sent to each agent role for your project's specific n
462
483
 
463
484
  ```bash
464
485
  nax prompts --init # Create default templates
465
- # Edit nax/templates/*.md
486
+ # Edit .nax/templates/*.md
466
487
  nax prompts --export test-writer # Preview a role's prompt
467
488
  nax run -f my-feature # Uses your custom prompts
468
489
  ```
469
490
 
470
- **Full guide:** See [Prompt Customization Guide](docs/prompt-customization.md) for detailed instructions, role reference, and best practices.
491
+ **Full guide:** See [Prompt Customization Guide](docs/guides/prompt-customization.md) for detailed instructions, role reference, and best practices.
471
492
 
472
493
  ---
473
494
 
@@ -477,12 +498,13 @@ nax selects a test strategy per story based on complexity and tags:
477
498
 
478
499
  | Strategy | Sessions | When | Description |
479
500
  |:---------|:---------|:-----|:------------|
480
- | `test-after` | 1 | Refactors, deletions, config, docs | Single session, no TDD discipline |
501
+ | `no-test` | 1 | Config, docs, CI, pure refactors with no behavior change | No tests written or run — requires `noTestJustification` in prd.json |
502
+ | `test-after` | 1 | Refactors, deletions | Single session, tests written after implementation |
481
503
  | `tdd-simple` | 1 | Simple stories | Single session with TDD prompt (red-green-refactor) |
482
504
  | `three-session-tdd-lite` | 3 | Medium stories | Three sessions, relaxed isolation rules |
483
505
  | `three-session-tdd` | 3 | Complex/security stories | Three sessions, strict file isolation |
484
506
 
485
- Configure the default TDD behavior in `nax/config.json`:
507
+ Configure the default TDD behavior in `.nax/config.json`:
486
508
 
487
509
  ```json
488
510
  {
@@ -492,11 +514,7 @@ Configure the default TDD behavior in `nax/config.json`:
492
514
  }
493
515
  ```
494
516
 
495
- | Value | Behaviour |
496
- |:------|:----------|
497
- | `auto` | nax decides based on complexity and tags (default) |
498
- | `lite` | Prefer `three-session-tdd-lite` for complex stories |
499
- | `strict` | Always use full `three-session-tdd` for complex stories |
517
+ See [TDD strategy options](#tdd-strategy-options) for all values.
500
518
 
501
519
  ---
502
520
 
@@ -544,7 +562,7 @@ Configured under `quality.testing` — supports **per-package override** in mono
544
562
 
545
563
  > **Tip:** `externalBoundaries` and `mockGuidance` complement `context.md`. nax provides the rule ("mock all I/O"), while `context.md` provides project-specific knowledge ("use `ioredis-mock` for Redis"). Use both for best results.
546
564
 
547
- > **Monorepo:** Each package can override `quality.testing` in its own `packages/<name>/nax/config.json`. For example, `packages/api` can specify Redis boundaries while `packages/web` specifies HTTP-only.
565
+ > **Monorepo:** Each package can override `quality.testing` in its own `.nax/mono/<package>/config.json`. For example, `packages/api` can specify Redis boundaries while `apps/web` specifies HTTP-only.
548
566
 
549
567
  > **Opt-out:** Set `quality.testing.hermetic: false` if your project requires real integration calls (e.g. live database tests against a local dev container).
550
568
 
@@ -552,34 +570,41 @@ Configured under `quality.testing` — supports **per-package override** in mono
552
570
 
553
571
  ## Story Decomposition
554
572
 
555
- When a story is too large (complex/expert with >6 acceptance criteria), nax can automatically decompose it into smaller sub-stories. This runs during the routing stage.
573
+ Story decomposition is **opt-in** disabled by default. Enable it by adding a `decompose` block to `.nax/config.json`.
556
574
 
557
- **Trigger:** The `story-oversized` interaction trigger fires when a story exceeds the configured thresholds. You can approve decomposition, skip the story, or continue as-is.
558
-
559
- **How it works:**
560
-
561
- 1. The `DecomposeBuilder` constructs a prompt with the target story, sibling stories (to prevent overlap), and codebase context
562
- 2. An LLM generates sub-stories with IDs, titles, descriptions, acceptance criteria, and dependency ordering
563
- 3. Post-decompose validators check:
564
- - **Overlap** — sub-stories must not duplicate scope of existing stories
565
- - **Coverage** — sub-stories must cover all parent acceptance criteria
566
- - **Complexity** — each sub-story must be simpler than the parent
567
- - **Dependencies** — dependency graph must be acyclic with valid references
568
- 4. The parent story is replaced in the PRD with the validated sub-stories
575
+ When enabled, nax checks during the routing stage whether a story is oversized (complex/expert complexity with more ACs than `maxAcceptanceCriteria`). If so, an LLM breaks it into smaller sub-stories and replaces the original in the PRD.
569
576
 
570
577
  **Configuration:**
571
578
 
572
579
  ```json
573
580
  {
574
581
  "decompose": {
575
- "enabled": true,
576
- "maxSubStories": 5,
577
- "minAcceptanceCriteria": 6,
578
- "complexityThreshold": ["complex", "expert"]
582
+ "trigger": "auto",
583
+ "maxAcceptanceCriteria": 6,
584
+ "maxSubstories": 5,
585
+ "maxSubstoryComplexity": "medium",
586
+ "maxRetries": 2,
587
+ "model": "balanced"
579
588
  }
580
589
  }
581
590
  ```
582
591
 
592
+ **Trigger modes:**
593
+
594
+ | Value | Behaviour |
595
+ |:------|:----------|
596
+ | `auto` | Decompose automatically — no confirmation prompt |
597
+ | `confirm` | Show interaction prompt — you approve, skip, or continue as-is |
598
+ | `disabled` | Never decompose — log a warning if story is oversized |
599
+
600
+ > **Note:** `storySizeGate` (under `precheck`) is a separate pre-run guard that warns if stories exceed size limits before execution starts. Decomposition happens during routing, mid-run.
601
+
602
+ **How it works:**
603
+
604
+ 1. An LLM generates sub-stories with IDs, titles, descriptions, acceptance criteria, and dependency ordering
605
+ 2. Post-decompose validators check overlap, coverage, complexity, and dependency ordering
606
+ 3. The parent story is replaced in the PRD with the validated sub-stories
607
+
583
608
  ---
584
609
 
585
610
  ## Regression Gate
@@ -601,8 +626,8 @@ After all stories pass their individual verification, nax can run a deferred ful
601
626
  | Mode | Behaviour |
602
627
  |:-----|:----------|
603
628
  | `disabled` | No regression gate |
604
- | `per-story` | Full suite after each story (expensive) |
605
- | `deferred` | Full suite once after all stories pass (recommended) |
629
+ | `per-story` | Full suite after each story higher cost and slower if stories fail regression |
630
+ | `deferred` | Full suite once after all stories pass (recommended) — **default** |
606
631
 
607
632
  If the regression gate detects failures, nax maps them to the responsible story via git blame and attempts automated rectification. If rectification fails, affected stories are marked as `regression-failed`.
608
633
 
@@ -646,7 +671,9 @@ nax run -f my-feature --parallel 3
646
671
 
647
672
  ## Agents
648
673
 
649
- nax supports multiple coding agents. By default it uses Claude Code via the ACP protocol.
674
+ nax supports multiple coding agents via the [Agent Client Protocol (ACP)](https://github.com/openclaw/acpx). **ACP protocol is recommended** — it provides persistent sessions, structured cost/token reporting, and works with all supported agents.
675
+
676
+ > **CLI protocol** (`agent.protocol: "cli"`) is supported for Claude Code only and is being gradually deprecated in favour of ACP. New projects should use ACP.
650
677
 
651
678
  ```bash
652
679
  # List installed agents and their capabilities
@@ -655,21 +682,16 @@ nax agents
655
682
 
656
683
  **Supported agents:**
657
684
 
658
- | Agent | Protocol | Notes |
659
- |:------|:---------|:------|
660
- | `claude` | ACP (default) | Claude Code via acpx |
661
- | `opencode` | ACP | OpenCode via acpx |
662
- | `codex` | ACP | Codex via acpx |
663
- | `cursor` | ACP | Cursor via acpx |
664
- | `windsurf` | ACP | Windsurf via acpx |
665
- | `aider` | ACP | Aider via acpx |
666
- | `gemini` | ACP | Gemini CLI via acpx |
685
+ | Agent | CLI mode |
686
+ |:------|:---------|
687
+ | `claude` | Stable |
688
+ | All others (`codex`, `gemini`, `opencode`, `cursor`, `copilot`, `kilo`, `qwen`, `kimi`, `iflow`, `droid`, `kiro`, and more) | 🧪 Experimental |
667
689
 
668
- **ACP protocol (default):**
690
+ nax connects to agents via [acpx](https://github.com/openclaw/acpx). All agents run as persistent ACP sessions — nax sends prompts and receives structured JSON-RPC responses including token counts and exact USD cost per session. For the full list of supported agents and their ACP startup commands, see the [acpx agent docs](https://github.com/openclaw/acpx#agents).
669
691
 
670
- nax uses [acpx](https://github.com/nathapp/acpx) as the ACP transport. All agents run as persistent sessions nax sends prompts and receives structured JSON-RPC responses including token counts and exact USD cost per session.
692
+ > **Note:** When `agent.protocol` is set to `"acp"`, the `--agent` CLI flag has no effect all execution routes through the ACP adapter regardless of agent name.
671
693
 
672
- > **Known issue — `acpx` ≤ 0.3.1:** The `--model` flag is not supported. Model selection via `execution.model` or per-package `model` overrides has no effect when using acpx as the ACP transport. This is a limitation in the underlying `@zed-industries/claude-agent-acp` adapter, which ignores runtime model requests and always uses the model configured in Claude Code settings. A fix is being tracked in [openclaw/acpx#49](https://github.com/openclaw/acpx/issues/49). As a workaround, set your preferred model directly in Claude Code settings before running nax.
694
+ > **Known issue — `acpx` ≤ 0.3.1:** The `--model` flag is not supported. Model selection via `execution.model` or per-package `model` overrides has no effect. As a temporary workaround, use the [nathapp-io/acpx](https://github.com/nathapp-io/acpx) fork which adds `--model` support. Upstream fix is tracked in [openclaw/acpx#49](https://github.com/openclaw/acpx/issues/49).
673
695
 
674
696
  **Configuring agents:**
675
697
 
@@ -683,10 +705,11 @@ nax uses [acpx](https://github.com/nathapp/acpx) as the ACP transport. All agent
683
705
  }
684
706
  ```
685
707
 
686
- **Force a specific agent at runtime:**
708
+ **Force a specific agent at runtime (CLI protocol only):**
687
709
 
688
710
  ```bash
689
- nax run -f my-feature --agent opencode
711
+ # Only applies when agent.protocol = "cli" (Claude Code only — other agents experimental)
712
+ nax run -f my-feature --agent claude
690
713
  ```
691
714
 
692
715
  ---
@@ -708,27 +731,27 @@ nax init --package packages/web
708
731
 
709
732
  ### Per-Package Config
710
733
 
711
- Each package can override specific config fields by placing a `nax/config.json` inside the package directory:
734
+ Each package's config and context are stored centrally under the root `.nax/mono/` directory:
712
735
 
713
736
  ```
714
737
  repo-root/
715
- ├── nax/
716
- └── config.json # root config
717
- ├── packages/
718
- ├── api/
719
- │ └── nax/
720
- │ ├── config.json # overrides for api package
721
- │ └── context.md # agent context for api
722
- └── web/
723
- └── nax/
724
- ├── config.json # overrides for web package
725
- └── context.md # agent context for web
738
+ ├── .nax/
739
+ ├── config.json # root config
740
+ │ └── mono/
741
+ ├── packages/
742
+ │ └── api/
743
+ │ ├── config.json # overrides for packages/api
744
+ │ └── context.md # agent context for packages/api
745
+ └── apps/
746
+ └── api/
747
+ ├── config.json # overrides for apps/api
748
+ └── context.md # agent context for apps/api
726
749
  ```
727
750
 
728
751
  **Overridable fields per package:** `execution`, `review`, `acceptance`, `quality`, `context`
729
752
 
730
753
  ```json
731
- // packages/api/nax/config.json
754
+ // .nax/mono/packages/api/config.json
732
755
  {
733
756
  "quality": {
734
757
  "commands": {
@@ -764,7 +787,7 @@ When `nax plan` generates stories for a monorepo, it auto-discovers packages fro
764
787
  - `turbo.json` → `packages` field
765
788
  - `package.json` → `workspaces`
766
789
  - `pnpm-workspace.yaml` → `packages`
767
- - Existing `*/nax/context.md` files
790
+ - Existing `.nax/mono/*/context.md` files
768
791
 
769
792
  ### Generate Agent Files for All Packages
770
793
 
@@ -772,7 +795,7 @@ When `nax plan` generates stories for a monorepo, it auto-discovers packages fro
772
795
  nax generate --all-packages
773
796
  ```
774
797
 
775
- Generates a `CLAUDE.md` (or agent-specific file) in each discovered package directory, using the package's own `nax/context.md` if present.
798
+ Generates a `CLAUDE.md` (or agent-specific file) in each discovered package directory, using the package's own `.nax/mono/<package>/context.md` if present.
776
799
 
777
800
  ---
778
801
 
@@ -780,7 +803,7 @@ Generates a `CLAUDE.md` (or agent-specific file) in each discovered package dire
780
803
 
781
804
  Integrate notifications, CI triggers, or custom scripts via lifecycle hooks.
782
805
 
783
- **Project hooks** (`nax/hooks.json`):
806
+ **Project hooks** (`.nax/hooks.json`):
784
807
 
785
808
  ```json
786
809
  {
@@ -883,7 +906,7 @@ nax can pause execution and prompt you for decisions at critical points. Configu
883
906
  | `max-retries` | 🟡 Yellow | `skip` | Story exhausted all retry attempts — skip and continue? |
884
907
  | `pre-merge` | 🟡 Yellow | `escalate` | Checkpoint before merging to main branch |
885
908
  | `human-review` | 🟡 Yellow | `skip` | Human review required on critical failure |
886
- | `story-oversized` | 🟡 Yellow | `continue` | Story too complex — decompose into sub-stories? |
909
+ | `story-oversized` | 🟡 Yellow | `continue` | Story too complex — decompose into sub-stories? (only fires when `decompose.trigger = "confirm"`) |
887
910
  | `story-ambiguity` | 🟢 Green | `continue` | Story requirements unclear — continue with best effort? |
888
911
  | `review-gate` | 🟢 Green | `continue` | Code review checkpoint before proceeding |
889
912
 
@@ -913,7 +936,7 @@ nax can pause execution and prompt you for decisions at critical points. Configu
913
936
 
914
937
  Extend nax with custom reviewers, reporters, or integrations.
915
938
 
916
- **Project plugins** (`nax/config.json`):
939
+ **Project plugins** (`.nax/config.json`):
917
940
 
918
941
  ```json
919
942
  {
@@ -976,35 +999,85 @@ nax precheck -f my-feature
976
999
 
977
1000
  **Run stopped mid-way**
978
1001
 
979
- nax saves progress in `nax/features/<name>/prd.json`. Re-run with the same command — completed stories are skipped automatically.
1002
+ nax saves progress in `.nax/features/<name>/prd.json`. Re-run with the same command — completed stories are skipped automatically.
980
1003
 
981
1004
  ---
982
1005
 
983
1006
  ## PRD Format
984
1007
 
985
- User stories are defined in `nax/features/<name>/prd.json`:
1008
+ User stories are defined in `.nax/features/<name>/prd.json`. Typically generated by `nax plan` — but you can write it by hand.
986
1009
 
987
1010
  ```json
988
1011
  {
1012
+ "project": "my-app",
989
1013
  "feature": "user-auth",
1014
+ "branchName": "feat/user-auth",
1015
+ "createdAt": "2026-01-01T00:00:00.000Z",
1016
+ "updatedAt": "2026-01-01T00:00:00.000Z",
990
1017
  "userStories": [
991
1018
  {
992
1019
  "id": "US-001",
993
1020
  "title": "Add login endpoint",
994
- "description": "POST /auth/login with email/password",
1021
+ "description": "POST /auth/login accepts email + password, returns signed JWT on success",
995
1022
  "acceptanceCriteria": [
996
- "Returns JWT on success",
997
- "Returns 401 on invalid credentials"
1023
+ "Returns 200 + JWT on valid credentials",
1024
+ "Returns 401 on invalid credentials",
1025
+ "Rate-limits to 5 attempts per minute"
998
1026
  ],
999
- "complexity": "medium",
1000
1027
  "tags": ["auth", "security"],
1001
- "status": "pending"
1028
+ "dependencies": [],
1029
+ "status": "pending",
1030
+ "passes": false,
1031
+ "attempts": 0,
1032
+ "escalations": [],
1033
+ "contextFiles": ["src/auth/types.ts"],
1034
+ "expectedFiles": ["src/auth/login.ts", "test/auth/login.test.ts"]
1035
+ },
1036
+ {
1037
+ "id": "US-002",
1038
+ "title": "Update changelog",
1039
+ "description": "Add v1.0 entry to CHANGELOG.md",
1040
+ "acceptanceCriteria": ["CHANGELOG.md has v1.0 section"],
1041
+ "tags": ["docs"],
1042
+ "dependencies": [],
1043
+ "status": "pending",
1044
+ "passes": false,
1045
+ "attempts": 0,
1046
+ "escalations": [],
1047
+ "routing": {
1048
+ "complexity": "simple",
1049
+ "testStrategy": "no-test",
1050
+ "noTestJustification": "Docs-only change — no executable code",
1051
+ "reasoning": "Pure documentation update"
1052
+ }
1002
1053
  }
1003
1054
  ]
1004
1055
  }
1005
1056
  ```
1006
1057
 
1007
- > **Note:** Use `"status": "passed"` (not `"done"`) to manually mark a story complete.
1058
+ **Key fields:**
1059
+
1060
+ | Field | Required | Description |
1061
+ |:------|:---------|:------------|
1062
+ | `id` | ✅ | Story ID — must be unique (e.g. `US-001`) |
1063
+ | `title` | ✅ | Short story title |
1064
+ | `description` | ✅ | What needs to be built |
1065
+ | `acceptanceCriteria` | ✅ | Testable outcomes — used for acceptance tests |
1066
+ | `tags` | ✅ | Routing hints that influence complexity classification and test strategy selection. Security tags (`auth`, `security`, `jwt`, `oauth`, `rbac`, etc.) and public-API tags (`public-api`, `endpoint`, `sdk`, etc.) force `three-session-tdd`. UI/integration tags (`ui`, `layout`, `cli`, `integration`) prefer `three-session-tdd-lite`. |
1067
+ | `dependencies` | ✅ | Story IDs that must pass before this one runs |
1068
+ | `status` | ✅ | `pending` \| `in-progress` \| `passed` \| `failed` \| `skipped` \| `blocked` \| `paused` |
1069
+ | `passes` | ✅ | `true` once all ACs pass — set by nax, not manually |
1070
+ | `attempts` | ✅ | Retry counter — set by nax |
1071
+ | `escalations` | ✅ | Escalation history — set by nax |
1072
+ | `contextFiles` | optional | Files pre-loaded into agent prompt |
1073
+ | `expectedFiles` | optional | Files that must exist after execution (pre-flight gate) |
1074
+ | `workdir` | optional | Package subdirectory for monorepo stories (e.g. `packages/api`) |
1075
+ | `routing` | optional | Pre-set routing — skip LLM classification if provided |
1076
+ | `routing.testStrategy` | optional | Override test strategy (e.g. `no-test`, `tdd-simple`). Only honored when `routing.contentHash` is absent — omit `contentHash` to prevent the LLM classifier from overriding your manual value. |
1077
+ | `routing.noTestJustification` | required if `no-test` | Explain why no tests are needed |
1078
+ | `storyPoints` | optional | Estimate (default: 1) |
1079
+
1080
+ > **Tip:** Use `"status": "passed"` to manually skip a story that's already done.
1008
1081
 
1009
1082
  ---
1010
1083
 
package/dist/nax.js CHANGED
@@ -3321,7 +3321,8 @@ Decompose this spec into user stories. For each story, provide:
3321
3321
  9. reasoning: Why this complexity level
3322
3322
  10. estimatedLOC: Estimated lines of code to change
3323
3323
  11. risks: Array of implementation risks
3324
- 12. testStrategy: "test-after" | "tdd-simple" | "three-session-tdd" | "three-session-tdd-lite"
3324
+ 12. testStrategy: "no-test" | "test-after" | "tdd-simple" | "three-session-tdd" | "three-session-tdd-lite"
3325
+ 13. noTestJustification: string (REQUIRED when testStrategy is "no-test" \u2014 explain why tests are unnecessary)
3325
3326
 
3326
3327
  ${COMPLEXITY_GUIDE}
3327
3328
 
@@ -21122,7 +21123,7 @@ async function loadConfigForWorkdir(rootConfigPath, packageDir) {
21122
21123
  return rootConfig;
21123
21124
  }
21124
21125
  const repoRoot = dirname2(rootNaxDir);
21125
- const packageConfigPath = join7(repoRoot, PROJECT_NAX_DIR, "packages", packageDir, "config.json");
21126
+ const packageConfigPath = join7(repoRoot, PROJECT_NAX_DIR, "mono", packageDir, "config.json");
21126
21127
  const packageOverride = await loadJsonFile(packageConfigPath, "config");
21127
21128
  if (!packageOverride) {
21128
21129
  return rootConfig;
@@ -22398,7 +22399,7 @@ var package_default;
22398
22399
  var init_package = __esm(() => {
22399
22400
  package_default = {
22400
22401
  name: "@nathapp/nax",
22401
- version: "0.51.0",
22402
+ version: "0.51.2",
22402
22403
  description: "AI Coding Agent Orchestrator \u2014 loops until done",
22403
22404
  type: "module",
22404
22405
  bin: {
@@ -22470,8 +22471,8 @@ var init_version = __esm(() => {
22470
22471
  NAX_VERSION = package_default.version;
22471
22472
  NAX_COMMIT = (() => {
22472
22473
  try {
22473
- if (/^[0-9a-f]{6,10}$/.test("bcb69c6"))
22474
- return "bcb69c6";
22474
+ if (/^[0-9a-f]{6,10}$/.test("7f71f43"))
22475
+ return "7f71f43";
22475
22476
  } catch {}
22476
22477
  try {
22477
22478
  const result = Bun.spawnSync(["git", "rev-parse", "--short", "HEAD"], {
@@ -30553,7 +30554,7 @@ function generatePackageContextTemplate(packagePath) {
30553
30554
  }
30554
30555
  async function initPackage(repoRoot, packagePath, force = false) {
30555
30556
  const logger = getLogger();
30556
- const naxDir = join31(repoRoot, ".nax", "packages", packagePath);
30557
+ const naxDir = join31(repoRoot, ".nax", "mono", packagePath);
30557
30558
  const contextPath = join31(naxDir, "context.md");
30558
30559
  if (existsSync20(contextPath) && !force) {
30559
30560
  logger.info("init", "Package context.md already exists (use --force to overwrite)", { path: contextPath });
@@ -67582,10 +67583,10 @@ async function generateAll(options, config2, agentFilter) {
67582
67583
  async function discoverPackages(repoRoot) {
67583
67584
  const packages = [];
67584
67585
  const seen = new Set;
67585
- for (const pattern of [".nax/packages/*/context.md", ".nax/packages/*/*/context.md"]) {
67586
+ for (const pattern of [".nax/mono/*/context.md", ".nax/mono/*/*/context.md"]) {
67586
67587
  const glob = new Bun.Glob(pattern);
67587
67588
  for await (const match of glob.scan({ cwd: repoRoot, dot: true })) {
67588
- const pkgRelative = match.replace(/^\.nax\/packages\//, "").replace(/\/context\.md$/, "");
67589
+ const pkgRelative = match.replace(/^\.nax\/mono\//, "").replace(/\/context\.md$/, "");
67589
67590
  const pkgAbsolute = join11(repoRoot, pkgRelative);
67590
67591
  if (!seen.has(pkgAbsolute)) {
67591
67592
  seen.add(pkgAbsolute);
@@ -68192,7 +68193,8 @@ Generate a JSON object with this exact structure (no markdown, no explanation \u
68192
68193
  "passes": false,
68193
68194
  "routing": {
68194
68195
  "complexity": "simple | medium | complex | expert",
68195
- "testStrategy": "tdd-simple | three-session-tdd-lite | three-session-tdd | test-after",
68196
+ "testStrategy": "no-test | tdd-simple | three-session-tdd-lite | three-session-tdd | test-after",
68197
+ "noTestJustification": "string \u2014 REQUIRED when testStrategy is no-test, explains why tests are unnecessary",
68196
68198
  "reasoning": "string \u2014 brief classification rationale"
68197
68199
  },
68198
68200
  "escalations": [],
@@ -69569,10 +69571,10 @@ async function generateCommand(options) {
69569
69571
  if (dryRun) {
69570
69572
  console.log(source_default.yellow("\u26A0 Dry run \u2014 no files will be written"));
69571
69573
  }
69572
- console.log(source_default.blue("\u2192 Discovering packages with .nax/packages/*/context.md..."));
69574
+ console.log(source_default.blue("\u2192 Discovering packages with .nax/mono/*/context.md..."));
69573
69575
  const packages = await discoverPackages(workdir);
69574
69576
  if (packages.length === 0) {
69575
- console.log(source_default.yellow(" No packages found (no .nax/packages/*/context.md or .nax/packages/*/*/context.md)"));
69577
+ console.log(source_default.yellow(" No packages found (no .nax/mono/*/context.md or .nax/mono/*/*/context.md)"));
69576
69578
  return;
69577
69579
  }
69578
69580
  console.log(source_default.blue(`\u2192 Generating agent files for ${packages.length} package(s)...`));
@@ -78850,26 +78852,34 @@ features.command("create <name>").description("Create a new feature").option("-d
78850
78852
 
78851
78853
  ## Overview
78852
78854
 
78853
- ## Requirements
78855
+ <!-- One paragraph describing what this feature does and why it's needed. -->
78854
78856
 
78855
- ## Acceptance Criteria
78856
- `);
78857
- await Bun.write(join53(featureDir, "plan.md"), `# Plan: ${name}
78857
+ ## Background / Context
78858
78858
 
78859
- ## Architecture
78859
+ <!-- Optional: relevant background, existing behaviour, or constraints. -->
78860
78860
 
78861
- ## Phases
78861
+ ## User Stories
78862
78862
 
78863
- ## Dependencies
78864
- `);
78865
- await Bun.write(join53(featureDir, "tasks.md"), `# Tasks: ${name}
78863
+ <!-- Describe what users need. Each story becomes a unit of work for nax.
78864
+ Be specific \u2014 the more detail here, the better the generated plan. -->
78866
78865
 
78867
- ## US-001: [Title]
78866
+ - As a [user], I want to [goal] so that [benefit].
78868
78867
 
78869
- ### Description
78868
+ ## Technical Requirements
78870
78869
 
78871
- ### Acceptance Criteria
78872
- - [ ] Criterion 1
78870
+ <!-- Optional: specific technical constraints, patterns to follow, APIs to use, etc. -->
78871
+
78872
+ ## Acceptance Criteria
78873
+
78874
+ <!-- These are parsed by nax to generate acceptance tests.
78875
+ Use clear, testable statements. Each criterion = one AC test. -->
78876
+
78877
+ - [ ] [Describe observable outcome 1]
78878
+ - [ ] [Describe observable outcome 2]
78879
+
78880
+ ## Out of Scope
78881
+
78882
+ <!-- What this feature explicitly does NOT cover. -->
78873
78883
  `);
78874
78884
  await Bun.write(join53(featureDir, "progress.txt"), `# Progress: ${name}
78875
78885
 
@@ -78880,11 +78890,9 @@ Created: ${new Date().toISOString()}
78880
78890
  console.log(source_default.green(`\u2705 Created feature: ${name}`));
78881
78891
  console.log(source_default.dim(` ${featureDir}/`));
78882
78892
  console.log(source_default.dim(" \u251C\u2500\u2500 spec.md"));
78883
- console.log(source_default.dim(" \u251C\u2500\u2500 plan.md"));
78884
- console.log(source_default.dim(" \u251C\u2500\u2500 tasks.md"));
78885
78893
  console.log(source_default.dim(" \u2514\u2500\u2500 progress.txt"));
78886
78894
  console.log(source_default.dim(`
78887
- Next: Edit spec.md and tasks.md, then: nax plan -f ${name} --from spec.md --auto`));
78895
+ Next: Edit spec.md, then: nax plan -f ${name} --from spec.md --auto`));
78888
78896
  });
78889
78897
  features.command("list").description("List all features").option("-d, --dir <path>", "Project directory", process.cwd()).action(async (options) => {
78890
78898
  let workdir;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nathapp/nax",
3
- "version": "0.51.0",
3
+ "version": "0.51.2",
4
4
  "description": "AI Coding Agent Orchestrator — loops until done",
5
5
  "type": "module",
6
6
  "bin": {