nubos-pilot 0.1.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/agents/np-ai-researcher.md +140 -0
- package/agents/np-code-fixer.md +363 -0
- package/agents/np-code-reviewer.md +351 -0
- package/agents/np-domain-researcher.md +136 -0
- package/agents/np-eval-auditor.md +167 -0
- package/agents/np-eval-planner.md +153 -0
- package/agents/np-executor.md +72 -0
- package/agents/np-framework-selector.md +171 -0
- package/agents/np-nyquist-auditor.md +185 -0
- package/agents/np-plan-checker.md +165 -0
- package/agents/np-planner.md +199 -0
- package/agents/np-researcher.md +150 -0
- package/agents/np-security-auditor.md +206 -0
- package/agents/np-ui-auditor.md +369 -0
- package/agents/np-ui-checker.md +192 -0
- package/agents/np-ui-researcher.md +324 -0
- package/agents/np-verifier.md +79 -0
- package/bin/check-coverage.cjs +40 -0
- package/bin/check-workflows.cjs +171 -0
- package/bin/check-workflows.test.cjs +208 -0
- package/bin/install.js +500 -0
- package/bin/np-tools/_commands.cjs +70 -0
- package/bin/np-tools/add-tests.cjs +171 -0
- package/bin/np-tools/add-tests.test.cjs +122 -0
- package/bin/np-tools/add-todo.cjs +108 -0
- package/bin/np-tools/add-todo.test.cjs +112 -0
- package/bin/np-tools/agent-skills.cjs +14 -0
- package/bin/np-tools/agent-skills.test.cjs +42 -0
- package/bin/np-tools/ai-integration-phase.cjs +109 -0
- package/bin/np-tools/ai-integration-phase.test.cjs +123 -0
- package/bin/np-tools/askuser.cjs +53 -0
- package/bin/np-tools/askuser.test.cjs +49 -0
- package/bin/np-tools/autonomous.cjs +69 -0
- package/bin/np-tools/autonomous.test.cjs +74 -0
- package/bin/np-tools/checkpoint.cjs +101 -0
- package/bin/np-tools/checkpoint.test.cjs +119 -0
- package/bin/np-tools/code-review.cjs +133 -0
- package/bin/np-tools/code-review.test.cjs +96 -0
- package/bin/np-tools/commit-task.cjs +120 -0
- package/bin/np-tools/commit-task.test.cjs +160 -0
- package/bin/np-tools/commit.cjs +103 -0
- package/bin/np-tools/commit.test.cjs +93 -0
- package/bin/np-tools/config.cjs +101 -0
- package/bin/np-tools/config.test.cjs +71 -0
- package/bin/np-tools/discuss-phase-power.cjs +265 -0
- package/bin/np-tools/discuss-phase-power.test.cjs +242 -0
- package/bin/np-tools/discuss-phase.cjs +132 -0
- package/bin/np-tools/discuss-phase.test.cjs +148 -0
- package/bin/np-tools/dispatch.cjs +116 -0
- package/bin/np-tools/doctor.cjs +242 -0
- package/bin/np-tools/eval-review.cjs +116 -0
- package/bin/np-tools/eval-review.test.cjs +123 -0
- package/bin/np-tools/execute-phase.cjs +182 -0
- package/bin/np-tools/execute-phase.test.cjs +116 -0
- package/bin/np-tools/execute-plan.cjs +124 -0
- package/bin/np-tools/execute-plan.test.cjs +82 -0
- package/bin/np-tools/help.cjs +28 -0
- package/bin/np-tools/help.test.cjs +29 -0
- package/bin/np-tools/init-dispatch.test.cjs +91 -0
- package/bin/np-tools/metrics.cjs +97 -0
- package/bin/np-tools/metrics.test.cjs +188 -0
- package/bin/np-tools/new-milestone.cjs +288 -0
- package/bin/np-tools/new-milestone.test.cjs +166 -0
- package/bin/np-tools/new-project.cjs +284 -0
- package/bin/np-tools/new-project.test.cjs +165 -0
- package/bin/np-tools/next.cjs +7 -0
- package/bin/np-tools/next.test.cjs +30 -0
- package/bin/np-tools/park.cjs +48 -0
- package/bin/np-tools/park.test.cjs +50 -0
- package/bin/np-tools/pause-work.cjs +24 -0
- package/bin/np-tools/pause-work.test.cjs +74 -0
- package/bin/np-tools/phase.cjs +71 -0
- package/bin/np-tools/phase.test.cjs +81 -0
- package/bin/np-tools/plan-diff.cjs +57 -0
- package/bin/np-tools/plan-diff.test.cjs +134 -0
- package/bin/np-tools/plan-milestone-gaps.cjs +115 -0
- package/bin/np-tools/plan-milestone-gaps.test.cjs +122 -0
- package/bin/np-tools/plan-phase.cjs +350 -0
- package/bin/np-tools/plan-phase.test.cjs +263 -0
- package/bin/np-tools/progress.cjs +7 -0
- package/bin/np-tools/progress.test.cjs +44 -0
- package/bin/np-tools/queue.cjs +213 -0
- package/bin/np-tools/research-phase.cjs +144 -0
- package/bin/np-tools/research-phase.test.cjs +154 -0
- package/bin/np-tools/reset-slice.cjs +17 -0
- package/bin/np-tools/reset-slice.test.cjs +96 -0
- package/bin/np-tools/resolve-model.cjs +110 -0
- package/bin/np-tools/resolve-model.test.cjs +200 -0
- package/bin/np-tools/resume-work.cjs +76 -0
- package/bin/np-tools/resume-work.test.cjs +91 -0
- package/bin/np-tools/skip.cjs +48 -0
- package/bin/np-tools/skip.test.cjs +66 -0
- package/bin/np-tools/slug.cjs +34 -0
- package/bin/np-tools/slug.test.cjs +46 -0
- package/bin/np-tools/state.cjs +16 -0
- package/bin/np-tools/state.test.cjs +40 -0
- package/bin/np-tools/stats.cjs +151 -0
- package/bin/np-tools/stats.test.cjs +118 -0
- package/bin/np-tools/triage.cjs +128 -0
- package/bin/np-tools/ui-phase.cjs +108 -0
- package/bin/np-tools/ui-phase.test.cjs +121 -0
- package/bin/np-tools/ui-review.cjs +108 -0
- package/bin/np-tools/ui-review.test.cjs +120 -0
- package/bin/np-tools/undo-task.cjs +31 -0
- package/bin/np-tools/undo-task.test.cjs +117 -0
- package/bin/np-tools/undo.cjs +43 -0
- package/bin/np-tools/undo.test.cjs +120 -0
- package/bin/np-tools/unpark.cjs +48 -0
- package/bin/np-tools/unpark.test.cjs +50 -0
- package/bin/np-tools/verify-work.cjs +186 -0
- package/bin/np-tools/verify-work.test.cjs +97 -0
- package/docs/adr/0001-no-daemon-invariant.md +82 -0
- package/docs/adr/0002-zero-runtime-dependencies.md +90 -0
- package/docs/adr/0003-max-six-unit-types.md +85 -0
- package/docs/adr/0004-atomic-commit-per-unit.md +102 -0
- package/docs/adr/0005-three-orthogonal-file-trees.md +98 -0
- package/docs/adr/0006-yaml-dependency-amendment.md +60 -0
- package/docs/adr/README.md +27 -0
- package/docs/agent-frontmatter-schema.md +84 -0
- package/docs/phase-artifact-schemas.md +292 -0
- package/docs/phase-directory-layout.md +82 -0
- package/lib/__tests__/README.md +1 -0
- package/lib/agents.cjs +98 -0
- package/lib/agents.test.cjs +286 -0
- package/lib/askuser.cjs +36 -0
- package/lib/askuser.test.cjs +310 -0
- package/lib/checkpoint.cjs +135 -0
- package/lib/checkpoint.test.cjs +184 -0
- package/lib/core.cjs +165 -0
- package/lib/core.test.cjs +405 -0
- package/lib/fixtures/README.md +1 -0
- package/lib/fixtures/phase-tree/README.md +1 -0
- package/lib/fixtures/plans/cycle/PLAN.md +16 -0
- package/lib/fixtures/plans/cycle/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/cycle/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/cycle/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/linear/PLAN.md +16 -0
- package/lib/fixtures/plans/linear/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/linear/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/linear/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/parallel/PLAN.md +16 -0
- package/lib/fixtures/plans/parallel/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/parallel/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/parallel/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/wave-conflict/PLAN.md +16 -0
- package/lib/fixtures/plans/wave-conflict/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/wave-conflict/tasks/T-02.md +20 -0
- package/lib/fixtures/roadmap/ROADMAP-malformed.md +3 -0
- package/lib/fixtures/roadmap/ROADMAP-minimal.md +51 -0
- package/lib/fixtures/roadmap/roadmap-malformed.yaml +7 -0
- package/lib/fixtures/roadmap/roadmap-minimal.yaml +40 -0
- package/lib/fixtures/roadmap/roadmap-ten-phases.yaml +101 -0
- package/lib/fixtures/templates/phase-context.md +6 -0
- package/lib/fixtures/templates/plan-skeleton.md +6 -0
- package/lib/frontmatter.cjs +251 -0
- package/lib/frontmatter.test.cjs +177 -0
- package/lib/gaps.cjs +197 -0
- package/lib/gaps.test.cjs +200 -0
- package/lib/git.cjs +207 -0
- package/lib/git.test.cjs +305 -0
- package/lib/install/agents-md.cjs +77 -0
- package/lib/install/backup.cjs +70 -0
- package/lib/install/codex-toml.cjs +440 -0
- package/lib/install/managed-block.cjs +30 -0
- package/lib/install/manifest.cjs +148 -0
- package/lib/install/mcp-writer.cjs +127 -0
- package/lib/install/runtime-detect.cjs +44 -0
- package/lib/install/staging.cjs +149 -0
- package/lib/metrics-aggregate.cjs +229 -0
- package/lib/metrics-aggregate.test.cjs +192 -0
- package/lib/metrics.cjs +120 -0
- package/lib/metrics.test.cjs +182 -0
- package/lib/model-aliases.regression.test.cjs +16 -0
- package/lib/model-profiles.cjs +42 -0
- package/lib/model-profiles.test.cjs +61 -0
- package/lib/next.cjs +236 -0
- package/lib/next.test.cjs +194 -0
- package/lib/phase.cjs +95 -0
- package/lib/phase.test.cjs +189 -0
- package/lib/plan-checker-contract.test.cjs +72 -0
- package/lib/plan-diff.cjs +173 -0
- package/lib/plan-diff.test.cjs +217 -0
- package/lib/plan.cjs +85 -0
- package/lib/plan.test.cjs +263 -0
- package/lib/progress.cjs +95 -0
- package/lib/progress.test.cjs +116 -0
- package/lib/researcher-contract.test.cjs +61 -0
- package/lib/roadmap-render.cjs +206 -0
- package/lib/roadmap-render.test.cjs +121 -0
- package/lib/roadmap.cjs +416 -0
- package/lib/roadmap.test.cjs +371 -0
- package/lib/runtime/_contract.test.cjs +61 -0
- package/lib/runtime/_readline.cjs +119 -0
- package/lib/runtime/_readline.test.cjs +126 -0
- package/lib/runtime/claude.cjs +48 -0
- package/lib/runtime/claude.test.cjs +101 -0
- package/lib/runtime/codex.cjs +35 -0
- package/lib/runtime/codex.test.cjs +114 -0
- package/lib/runtime/gemini.cjs +35 -0
- package/lib/runtime/gemini.test.cjs +109 -0
- package/lib/runtime/index.cjs +49 -0
- package/lib/runtime/index.test.cjs +181 -0
- package/lib/runtime/opencode.cjs +35 -0
- package/lib/runtime/opencode.test.cjs +124 -0
- package/lib/state.cjs +205 -0
- package/lib/state.test.cjs +264 -0
- package/lib/surface-audit.test.cjs +46 -0
- package/lib/tasks.cjs +327 -0
- package/lib/tasks.test.cjs +389 -0
- package/lib/template.cjs +66 -0
- package/lib/template.test.cjs +159 -0
- package/lib/undo.cjs +179 -0
- package/lib/undo.test.cjs +261 -0
- package/lib/verify.cjs +116 -0
- package/lib/verify.test.cjs +187 -0
- package/np-tools.cjs +303 -0
- package/package.json +39 -0
- package/templates/AI-SPEC.md +90 -0
- package/templates/CONTEXT.md +32 -0
- package/templates/PLAN.md +69 -0
- package/templates/PROJECT.md +60 -0
- package/templates/REQUIREMENTS.md +38 -0
- package/templates/SECURITY.md +61 -0
- package/templates/UI-SPEC.md +64 -0
- package/templates/VALIDATION.md +76 -0
- package/templates/claude/payload/README.md +11 -0
- package/templates/opencode/opencode.json +6 -0
- package/templates/opencode/payload/AGENTS.md +9 -0
- package/workflows/add-backlog.md +212 -0
- package/workflows/add-tests.md +69 -0
- package/workflows/add-todo.md +222 -0
- package/workflows/ai-integration-phase.md +230 -0
- package/workflows/autonomous.md +94 -0
- package/workflows/cleanup.md +325 -0
- package/workflows/code-review-fix.md +435 -0
- package/workflows/code-review.md +447 -0
- package/workflows/discuss-phase-assumptions.md +269 -0
- package/workflows/discuss-phase-power.md +139 -0
- package/workflows/discuss-phase.md +386 -0
- package/workflows/dispatch.md +9 -0
- package/workflows/doctor.md +10 -0
- package/workflows/eval-review.md +243 -0
- package/workflows/execute-phase.md +142 -0
- package/workflows/execute-plan.md +82 -0
- package/workflows/help.md +8 -0
- package/workflows/new-milestone.md +166 -0
- package/workflows/new-project.md +213 -0
- package/workflows/next.md +8 -0
- package/workflows/note.md +244 -0
- package/workflows/park.md +29 -0
- package/workflows/pause-work.md +34 -0
- package/workflows/plan-milestone-gaps.md +233 -0
- package/workflows/plan-phase.md +351 -0
- package/workflows/progress.md +8 -0
- package/workflows/queue.md +9 -0
- package/workflows/research-phase.md +327 -0
- package/workflows/reset-slice.md +39 -0
- package/workflows/resume-work.md +79 -0
- package/workflows/review.md +489 -0
- package/workflows/secure-phase.md +209 -0
- package/workflows/session-report.md +243 -0
- package/workflows/skip.md +29 -0
- package/workflows/state.md +7 -0
- package/workflows/stats.md +170 -0
- package/workflows/thread.md +214 -0
- package/workflows/triage.md +9 -0
- package/workflows/ui-phase.md +246 -0
- package/workflows/ui-review.md +222 -0
- package/workflows/undo-task.md +42 -0
- package/workflows/undo.md +55 -0
- package/workflows/unpark.md +29 -0
- package/workflows/validate-phase.md +231 -0
- package/workflows/verify-work.md +83 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# ADR-0005: Three Orthogonal File-Trees
|
|
2
|
+
|
|
3
|
+
* Status: Accepted
|
|
4
|
+
* Date: 2026-04-14
|
|
5
|
+
* Supersedes: None
|
|
6
|
+
|
|
7
|
+
## Context and Problem Statement
|
|
8
|
+
|
|
9
|
+
Three distinct concerns have historically been conflated in similar tools:
|
|
10
|
+
|
|
11
|
+
1. **What we (nubos-pilot contributors) author and commit** — the source repository.
|
|
12
|
+
2. **What we ship to end users via `npx nubos-pilot init`** — the install payload landing at the user's `.claude/nubos-pilot/`.
|
|
13
|
+
3. **What an end user's project accumulates** as they plan and execute with nubos-pilot — STATE.md, ROADMAP.md, phase directories, todos, checkpoints, metrics.
|
|
14
|
+
|
|
15
|
+
Mixing these three concerns produces two well-known failure modes:
|
|
16
|
+
|
|
17
|
+
* **Install bit-rot** — the "copy-paste N blocks to remove stale X" problem. When installer files and state files live in the same tree, "clean install" and "clean state" cannot be distinguished.
|
|
18
|
+
* **Contributor confusion** — authors cannot tell, for a given file, whether they are editing something that ships to users, something that only contributors see, or something users will mutate at runtime.
|
|
19
|
+
|
|
20
|
+
The question: how are these three concerns physically separated?
|
|
21
|
+
|
|
22
|
+
## Decision Drivers
|
|
23
|
+
|
|
24
|
+
* **Install correctness** — Phase 7's manifest-based installer (INST-01) needs a distinct payload subtree to manifest against. Mixing it with source code or project state makes the manifest incoherent.
|
|
25
|
+
* **Contributor clarity** — every file answers unambiguously: "do I edit this, does it ship, or does a user's project produce it?"
|
|
26
|
+
* **Removability** — end-user uninstall (INST-08, stale-install cleanup) must be able to operate on one well-defined tree without sweeping scattered files.
|
|
27
|
+
* **Avoiding bit-rot** — stale-install cleanup only works deterministically if payload boundaries are defined precisely enough to diff-check on reinstall.
|
|
28
|
+
|
|
29
|
+
## Considered Options
|
|
30
|
+
|
|
31
|
+
* **Three orthogonal file-trees** — Source tree / Install-Payload tree / Project-State tree, defined below. (CHOSEN)
|
|
32
|
+
* **Single tree with everything intermixed** — installer files, source files, and state files cohabiting in one location.
|
|
33
|
+
* **Two trees** — either merge Install-Payload into Source (ship the source tree directly), or merge Project-State into Install-Payload (state alongside installed tooling).
|
|
34
|
+
|
|
35
|
+
## Decision Outcome
|
|
36
|
+
|
|
37
|
+
Chosen: **"Three orthogonal file-trees"**. The three trees are enumerated in prose below; each tree has a distinct owner, lifecycle, and runtime location. This ADR asserts the boundary as a TEXT INVARIANT only — it does NOT create any of the trees beyond what Phase 1 authors (i.e. only the Source tree's `docs/adr/` subdirectory is materialized by this phase; see the scope disclaimer).
|
|
38
|
+
|
|
39
|
+
### The Three Trees
|
|
40
|
+
|
|
41
|
+
1. **Source tree** — what lives inside the nubos-pilot git repository (this monorepo subdirectory at `tools/nubos-pilot/`). **Owned by** contributors. **Lifecycle:** normal git. **Contains** (over time, as phases complete): a `bin/` subdir for the installer and the CLI helper, a `docs/` subdir (including `docs/adr/` authored now), a staging subdirectory whose contents become the install-payload after `npx nubos-pilot init` runs, a `.planning/` subdir with authoring-time planning artifacts (nubos-pilot's own ROADMAP / STATE / PLAN files), `CLAUDE.md`, `package.json`, and related author-facing artifacts. Committed.
|
|
42
|
+
|
|
43
|
+
2. **Install-Payload tree** — the subset of the Source tree that is copied onto an end user's machine when they run `npx nubos-pilot init`. **Owned by** the end user after install, but **managed** by the installer via a manifest. **Lifecycle:** overwritten on `npx nubos-pilot` reinstall; cleaned up via `np:doctor --fix` against the manifest (Phase 7, INST-01 / INST-05 / INST-08). **Runtime location** on the end user's machine: `.claude/nubos-pilot/` for Claude Code (primary), or `.agents/nubos-pilot/` for other runtimes (Codex/Gemini/OpenCode — forward-reference Phase 8). **Not materialized in this phase** — scaffolded in Phase 7 (INST-01 manifest install).
|
|
44
|
+
|
|
45
|
+
3. **Project-State tree** — state that end users' projects accumulate as they plan and execute: `STATE.md`, `ROADMAP.md`, `phases/<NN>-<slug>/` directories, `todos/pending/`, `backlog/`, `checkpoints/`, `metrics/`. **Owned by** the end user's project. **Lifecycle:** mutated only through nubos-pilot workflows under a single-writer lock (Phase 2, LIB-02). **Runtime location** on the end user's machine: `.nubos-pilot/`. **Not materialized in this phase** — scaffolded starting Phase 4 (base workflows + state schemas).
|
|
46
|
+
|
|
47
|
+
### Orthogonality Rule
|
|
48
|
+
|
|
49
|
+
**No file lives in two trees simultaneously at runtime.** A file is either source (in the contributor's repo), or payload (at the end user's install location), or state (in the end user's project) — **never two at once**. Workflow commands operate on exactly one tree per invocation; a single commit touches files in one tree at a time (see [ADR-0004](0004-atomic-commit-per-unit.md)).
|
|
50
|
+
|
|
51
|
+
### Source-vs-Install-Payload Overlap Nuance
|
|
52
|
+
|
|
53
|
+
The install-payload content ORIGINATES in the Source tree — it is authored by contributors in a staging subdirectory of the repo (e.g. `tools/nubos-pilot/nubos-pilot/…` as a suggested staging layout, finalized in Phase 7). **At install time**, the installer copies those files into a distinct tree at the end user's `.claude/nubos-pilot/` — a different filesystem location entirely. "Orthogonality" applies to **runtime locations** (what exists where when things are running), not to pre-install staging. Authoring in the Source tree is how Install-Payload files come to exist; they become the Install-Payload tree only after `npx nubos-pilot init` has run on the end user's machine. On the contributor's machine, only the Source tree is populated; on the end user's machine, only the Install-Payload and Project-State trees are populated (plus a snapshot of the payload staging subtree if the user also clones the repo, which is an unusual contributor-mode case).
|
|
54
|
+
|
|
55
|
+
### Scope Disclaimer for Phase 1
|
|
56
|
+
|
|
57
|
+
**Phase 1 materializes ONLY the Source tree** — specifically, `docs/adr/` and this ADR itself. Install-Payload and Project-State directories are **deferred**: the Install-Payload tree is scaffolded in Phase 7 (INST-01 manifest install), and the Project-State tree is scaffolded starting Phase 4 (base workflows + state schemas). **No `.gitkeep`, no empty staging directories, no skeleton subtrees are created in Phase 1.** This disclaimer is mandatory per CONTEXT.md D-09 and RESEARCH.md Pitfall 3.
|
|
58
|
+
|
|
59
|
+
### Consequences
|
|
60
|
+
|
|
61
|
+
* Good, because Phase 7 installer (INST-01) has a well-defined source-of-truth for manifest generation — the payload staging subtree inside the repo maps 1:1 to the installed content.
|
|
62
|
+
* Good, because uninstall and stale-cleanup (INST-05, INST-08) are mechanical — operate on the Install-Payload tree only; Project-State is never touched.
|
|
63
|
+
* Good, because `git log` on the nubos-pilot repo contains contributor work only — never end-user state churn (which lives on the user's machine, not in our repo).
|
|
64
|
+
* Good, because users can delete `.nubos-pilot/` to reset their state without disturbing the installed tool, or delete `.claude/nubos-pilot/` to uninstall without losing their plans.
|
|
65
|
+
* Bad, because contributors must remember the staging-subtree-vs-installed-payload distinction — mitigated by this ADR being linked from `bin/install.js` and CLAUDE.md once those artifacts exist in later phases.
|
|
66
|
+
* Neutral, because project-state schema evolves across Phases 2–4 — ADR-0005 is agnostic to the schema, only asserts the tree boundary.
|
|
67
|
+
|
|
68
|
+
## Pros and Cons of the Options
|
|
69
|
+
|
|
70
|
+
### Three orthogonal file-trees — chosen
|
|
71
|
+
|
|
72
|
+
* Good, because it maps cleanly to the three distinct owners (contributor / installed-tool / user-project) without overlap.
|
|
73
|
+
* Good, because each tree has a single, well-defined lifecycle operation (git-commit / npx-reinstall / workflow-mutate).
|
|
74
|
+
* Good, because it makes Phase 7's manifest-based installer (INST-01) implementable without heuristic boundaries.
|
|
75
|
+
* Bad, because contributors must mentally track the staging-vs-installed distinction — the ONE piece of nuance this model requires.
|
|
76
|
+
|
|
77
|
+
### Single tree with everything intermixed — rejected
|
|
78
|
+
|
|
79
|
+
* Good, because it is "simpler" in the sense of having fewer rules.
|
|
80
|
+
* Bad, because it reproduces the "copy-paste N blocks to remove stale X" bit-rot pattern — stale install files cannot be distinguished from stale state files when they cohabit.
|
|
81
|
+
* Bad, because a user who wants to reset state deletes things that look like state but may be installed-tooling, or vice versa.
|
|
82
|
+
* Bad, because manifest-based install becomes undecidable — the installer cannot tell a file it shipped from a file the user created.
|
|
83
|
+
|
|
84
|
+
### Two trees (merge source+payload, or payload+state) — rejected
|
|
85
|
+
|
|
86
|
+
* Good, because it reduces the tree count, superficially simpler.
|
|
87
|
+
* Bad — **merge source+payload:** ships contributor-only artifacts (planning docs, ADRs, internal notes) to end users, bloating installs and leaking internal state.
|
|
88
|
+
* Bad — **merge payload+state:** reintroduces the bit-rot failure mode exactly. A user's state lives alongside installed tooling; reinstall must then distinguish "state I should keep" from "tooling I should overwrite" — the very problem we're avoiding.
|
|
89
|
+
* Bad, because every 2-tree variant reintroduces one of the two failure modes the 3-tree split is designed to eliminate.
|
|
90
|
+
|
|
91
|
+
## More Information
|
|
92
|
+
|
|
93
|
+
* **Related ADR:** [ADR-0002](0002-zero-runtime-dependencies.md) — the Install-Payload tree contains only `.cjs` + markdown; no `node_modules/` subtree ever lives inside it.
|
|
94
|
+
* **Related ADR:** [ADR-0004](0004-atomic-commit-per-unit.md) — commits touch files in a single tree at a time (almost always the Source tree; end-user commits on their own repos are their business and out of nubos-pilot's scope).
|
|
95
|
+
* **REQUIREMENTS.md:** §"Install" → INST-01 (manifest-based install — Install-Payload tree is the consumer), INST-05 (`np:doctor` — Install-Payload tree), INST-08 (stale-install auto-cleanup — Install-Payload tree).
|
|
96
|
+
* **CLAUDE.md:** §"Technology Stack" → "Installation" — confirms the end-user install path `.claude/nubos-pilot/`.
|
|
97
|
+
* **CONTEXT.md:** D-09 — only `docs/adr/` is materialized in Phase 1; other trees are text invariant only.
|
|
98
|
+
* **RESEARCH.md:** Pitfall 3 — do NOT create Install-Payload or Project-State directories in this phase.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ADR-0006: Accept yaml@^2.8 as First Runtime Dependency (Amendment to ADR-0002)
|
|
2
|
+
|
|
3
|
+
* Status: Accepted
|
|
4
|
+
* Date: 2026-04-15
|
|
5
|
+
* Supersedes: None
|
|
6
|
+
* Amends: [ADR-0002](0002-zero-runtime-dependencies.md)
|
|
7
|
+
|
|
8
|
+
## Context and Problem Statement
|
|
9
|
+
|
|
10
|
+
Phase 4 introduces `.nubos-pilot/roadmap.yaml` as the canonical source-of-truth for roadmap data (Phase-4 D-16..D-20). The schema contains nested sequences, mixed scalar types, and per-phase `plans` sub-objects that go well beyond what a hand-rolled regex parser can robustly handle. `lib/frontmatter.cjs` (the hand-rolled parser) already hits its design ceiling on Task-Frontmatter multiline sequences — extending it further to parse the full roadmap YAML would reimplement a real YAML 1.2 parser in-repo, which is strictly worse than vendoring a 50KB battle-tested library.
|
|
11
|
+
|
|
12
|
+
ADR-0002 §"Escape hatch for future exceptions" explicitly foresees this: "if a concrete future feature genuinely requires a runtime dep that builtins cannot satisfy, the exception is introduced by a new ADR […] that either supersedes ADR-0002 wholesale or amends it narrowly with a name-scoped exemption." This ADR is the first exercise of that escape hatch.
|
|
13
|
+
|
|
14
|
+
## Scope
|
|
15
|
+
|
|
16
|
+
* This amendment permits **EXACTLY ONE** additional runtime dependency: `yaml@^2.8`.
|
|
17
|
+
* `package.json.dependencies` is limited to `{"yaml": "^2.8.0"}` — no other key permitted.
|
|
18
|
+
* **No further runtime deps** may be added without a new ADR amendment that either supersedes ADR-0002 again, or amends it with a second narrowly-scoped exemption. The bureaucratic step is deliberate — the escape hatch is load-bearing on the "just add a dep" reflex never becoming the default answer.
|
|
19
|
+
* `devDependencies` remain unconstrained by this amendment (same as ADR-0002 §Scope).
|
|
20
|
+
|
|
21
|
+
## Decision Drivers
|
|
22
|
+
|
|
23
|
+
* **Concrete need** — Phase-4 D-16..D-20 ship `roadmap.yaml` with nested sequences (milestones → phases → plans) that the hand-rolled regex parser cannot express.
|
|
24
|
+
* **Pre-sanctioned by CLAUDE.md** — the project's tech-stack document explicitly identifies `yaml@^2.8` as the acceptable escape-hatch dependency under "Supporting Libraries" / "When to Use Alternative".
|
|
25
|
+
* **Install-footprint minimal** — `yaml@^2.8` has zero transitive dependencies and ships ~50KB of JS. This does not re-open the dep-tree floodgate ADR-0002 guards against.
|
|
26
|
+
* **Type safety** — `YAML.parse` yields typed scalars (number, string, boolean, null, arrays of same) — no ad-hoc type coercion needed in callers.
|
|
27
|
+
* **Round-trip support** — `yaml@^2.8` supports CST-preserving `YAML.parseDocument` for future phases that need to edit YAML while preserving comments.
|
|
28
|
+
|
|
29
|
+
## Considered Options
|
|
30
|
+
|
|
31
|
+
* **Option A — Keep regex parser, extend it to handle nested sequences.** Reject: every step along this road lands in a hand-rolled YAML 1.2 implementation. `lib/frontmatter.cjs` already has edge-cases around stack-demotion and inline vs block arrays; adding plans-objects-inside-phases-inside-milestones is not tenable.
|
|
32
|
+
* **Option B — Write a minimal purpose-built YAML subset parser.** Reject: the effort to correctly support nested sequences + mixed-scalar-types exceeds the install-surface cost of vendoring `yaml@^2.8`. Writing a new parser is also a test-surface multiplier (we'd need the fuzz-corpus `yaml@^2.8` already passes).
|
|
33
|
+
* **Option C — Accept `yaml@^2.8` as the first and only additional runtime dependency.** Chosen: demonstrable concrete need, pre-sanctioned, zero transitive deps, narrow scope preserves ADR-0002's spirit.
|
|
34
|
+
* **Option D — Move the roadmap source-of-truth back to Markdown.** Reject: Phase-4 D-16..D-20 lock roadmap.yaml as source-of-truth specifically because Markdown cannot express the structured plan-object data the downstream renderer/workflows need.
|
|
35
|
+
|
|
36
|
+
## Decision Outcome
|
|
37
|
+
|
|
38
|
+
Chosen: **Option C — accept `yaml@^2.8` as the first runtime dependency**, because the concrete need is documented in Phase-4 decisions D-16..D-20, CLAUDE.md pre-sanctions this specific dep, and the narrow name-scoped amendment preserves ADR-0002's forcing function against "just add a dep" drift.
|
|
39
|
+
|
|
40
|
+
**Audit rule:** Any PR that adds a key to `package.json.dependencies` beyond `yaml` MUST be blocked unless it ships with a new ADR amendment that supersedes this one or adds a second narrowly-scoped exemption. Phase 1's CI-gate enforcement note (ADR-0002 closing paragraph) applies here verbatim — human PR review is the current enforcement, CI-gate is deferred to a later phase.
|
|
41
|
+
|
|
42
|
+
### Consequences
|
|
43
|
+
|
|
44
|
+
* Good, because roadmap.yaml parsing is now robust across nested sequences and YAML 1.2's full scalar type system.
|
|
45
|
+
* Good, because future phases that need structured YAML (e.g. Phase 5 plan-diff, Phase 9 model-profile config) can reuse `yaml@^2.8` without another amendment.
|
|
46
|
+
* Good, because the install-footprint remains effectively flat — `yaml@^2.8` has zero transitive dependencies (confirm with `npm ls --all`).
|
|
47
|
+
* Bad, because `npx nubos-pilot` now performs one actual download at install time on a fresh machine. ADR-0002's "zero-deps ≈ zero failure modes" property is slightly weakened — but only by the thinnest possible amount.
|
|
48
|
+
* Bad, because the escape-hatch is no longer purely theoretical — future PR authors have a concrete precedent to cite. Mitigation: the Scope clause pins this to EXACTLY ONE dep, and the audit rule makes a second exemption equally bureaucratic.
|
|
49
|
+
* Neutral, because Pattern S-1 (atomic write + file lock), S-2 (NubosPilotError envelope), S-5 (sandboxed tests), and S-6 (CJS module footer) remain unchanged — no workflow pattern changes with this amendment.
|
|
50
|
+
|
|
51
|
+
## More Information
|
|
52
|
+
|
|
53
|
+
* **Amended ADR:** [ADR-0002](0002-zero-runtime-dependencies.md) — this amendment exercises the escape hatch documented in §"Escape hatch for future exceptions" (line 37 of ADR-0002).
|
|
54
|
+
* **CLAUDE.md:** §"Supporting Libraries" → row "yaml `^2.8.0`" pre-sanctions this dependency with the condition "Only adopt if a concrete workflow produces frontmatter that the hand-rolled regex parser can't handle (multiline arrays, anchors). Default answer is still 'no'." The Phase-4 roadmap.yaml schema satisfies that concrete-workflow condition.
|
|
55
|
+
* **Phase-4 Context:** `.planning/phases/04-base-workflows-state-schemas/04-CONTEXT.md` D-16..D-20 (roadmap.yaml source-of-truth decisions).
|
|
56
|
+
* **Upstream:** [`yaml` npm package](https://www.npmjs.com/package/yaml) — maintained by Eemeli Aro, version 2.x is YAML 1.2 compliant, zero transitive deps.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
*This ADR does not describe CI enforcement. The dep-growth block (PR blocker on any new `dependencies` key beyond `yaml`) is deferred to a later deploy/CI phase per ROADMAP.md, identical to ADR-0002's deferral. Enforcement in the source-only phases is human PR review with this ADR as the authoritative reference.*
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Architectural Decision Records
|
|
2
|
+
|
|
3
|
+
This directory contains MADR-full ADRs that codify scope invariants of nubos-pilot. Each ADR is authoritative for the constraint it documents. Per CONTEXT.md D-07, decisions are superseded by new ADRs, never rewritten.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
- [`0001-no-daemon-invariant.md`](0001-no-daemon-invariant.md) — No runtime daemon, no background process, no RPC multi-agents (FND-01)
|
|
8
|
+
- [`0002-zero-runtime-dependencies.md`](0002-zero-runtime-dependencies.md) — `package.json` dependencies block stays empty (FND-02)
|
|
9
|
+
- [`0003-max-six-unit-types.md`](0003-max-six-unit-types.md) — Milestone, Phase, Plan, Task, Todo, Backlog — no more (FND-03)
|
|
10
|
+
- [`0004-atomic-commit-per-unit.md`](0004-atomic-commit-per-unit.md) — Every unit-completion = exactly one git commit (FND-04)
|
|
11
|
+
- [`0005-three-orthogonal-file-trees.md`](0005-three-orthogonal-file-trees.md) — Source / Install-Payload / Project-State stay disjoint (FND-05)
|
|
12
|
+
|
|
13
|
+
## Status Lifecycle
|
|
14
|
+
|
|
15
|
+
Each ADR moves through three states:
|
|
16
|
+
|
|
17
|
+
1. **Proposed** — authored but not yet accepted; subject to revision during review.
|
|
18
|
+
2. **Accepted** — decision is binding; downstream work consumes the invariant as-is.
|
|
19
|
+
3. **Deprecated** — superseded by a later ADR (referenced via `Supersedes NNNN`); retained for history.
|
|
20
|
+
|
|
21
|
+
An ADR MAY enter directly as **Accepted** when it is ratified at authoring time (e.g. the FND-01…FND-05 ADRs in Phase 1, which encode invariants already agreed in CONTEXT.md). The `Proposed` state is reserved for ADRs whose decision is still open at commit time.
|
|
22
|
+
|
|
23
|
+
ADRs are append-only. A superseded ADR is never rewritten — instead, a new ADR with a higher number references it via its `Supersedes` line.
|
|
24
|
+
|
|
25
|
+
## Numbering
|
|
26
|
+
|
|
27
|
+
ADRs follow the pattern `NNNN-kebab-title.md` with a zero-padded four-digit sequence starting at `0001`. Numbers are monotonically incremented — no skips, no re-use — so that cross-references (e.g. `ADR-0003`) stay stable across the project's lifetime.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Agent Frontmatter Schema
|
|
2
|
+
|
|
3
|
+
Canonical schema for every `agents/*.md` file shipped by nubos-pilot. Enforced by `lib/agents.cjs` at load time. Introduced in Phase 5 (CONTEXT decisions D-09..D-14).
|
|
4
|
+
|
|
5
|
+
## Canonical Schema (D-09)
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
---
|
|
9
|
+
name: <string> # required; MUST equal the filename stem
|
|
10
|
+
description: <string> # required; single-line summary
|
|
11
|
+
tier: haiku|sonnet|opus # required; see Tier Enum (D-11)
|
|
12
|
+
tools: <comma-list string> # required; e.g. "Read, Write, Bash, Grep"
|
|
13
|
+
color: <string> # optional; UI hint only
|
|
14
|
+
---
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Agent body follows the closing `---`. Body content is free-form markdown, consumed verbatim by the runtime when the agent is spawned.
|
|
18
|
+
|
|
19
|
+
## Required Fields
|
|
20
|
+
|
|
21
|
+
Every required field must be present with a truthy value. Missing or empty fields throw `NubosPilotError('agent-invalid-frontmatter', …)` with `details.field` set to the offender.
|
|
22
|
+
|
|
23
|
+
| Field | Type | Validator Rule | Example |
|
|
24
|
+
|-------|------|----------------|---------|
|
|
25
|
+
| `name` | string | Must equal the filename stem (e.g. `planner.md` → `planner`). | `name: planner` |
|
|
26
|
+
| `description` | string | Non-empty single-line summary; shown in `listAgents` UIs. | `description: Creates executable phase plans …` |
|
|
27
|
+
| `tier` | enum string | Must be one of `haiku`, `sonnet`, `opus`. | `tier: opus` |
|
|
28
|
+
| `tools` | comma-list string | Flat comma-separated list; parsed later by the runtime adapter. | `tools: Read, Write, Bash, Glob, Grep` |
|
|
29
|
+
|
|
30
|
+
Order of checks inside `validateAgentFrontmatter`: REQUIRED → FORBIDDEN → TIER_ENUM → name-match. First failure throws; the remaining checks are short-circuited.
|
|
31
|
+
|
|
32
|
+
## Forbidden Fields (D-10)
|
|
33
|
+
|
|
34
|
+
Presence of any of these fields — even with a falsy value — throws `NubosPilotError('agent-forbidden-field', …)` with `details.field` and `details.hint`.
|
|
35
|
+
|
|
36
|
+
| Field | Why forbidden | Hint returned |
|
|
37
|
+
|-------|---------------|---------------|
|
|
38
|
+
| `model` | Model routing is tier-based in nubos-pilot (D-12..D-14). A concrete model id bypasses the tier abstraction and breaks multi-runtime adapters (Phase 7/8). | `Use "tier" instead.` |
|
|
39
|
+
| `model_profile` | Same reason as `model`: profile-based selection is an out-of-band concern; `tier` is the single source of truth. | `Use "tier" instead.` |
|
|
40
|
+
| `hooks` | Runtime-specific syntax (Claude Code ≠ Codex ≠ Gemini). Hooks live in the runtime-adapter layer introduced in Phase 7/8; they are NOT part of the portable agent contract. | `hooks are runtime-specific and deferred to Phase 7/8.` |
|
|
41
|
+
|
|
42
|
+
Rationale: the FORBIDDEN list is what makes D-09/D-10 testable. Every agent file that slips a forbidden field in gets rejected at load time before the runtime adapter ever sees it.
|
|
43
|
+
|
|
44
|
+
## Tier Enum (D-11)
|
|
45
|
+
|
|
46
|
+
`TIER_ENUM = ['haiku', 'sonnet', 'opus']`. Any other value throws `NubosPilotError('agent-invalid-tier', …)` with `details.value` (the offending input) and `details.allowed` (the canonical enum).
|
|
47
|
+
|
|
48
|
+
Pre-classified assignments (D-13, locked in ROADMAP SC-4):
|
|
49
|
+
|
|
50
|
+
| Agent | Tier | Rationale |
|
|
51
|
+
|-------|------|-----------|
|
|
52
|
+
| `planner` | `opus` | Goal-backward decomposition, dependency-graph reasoning, decision-fidelity checks — deepest model. |
|
|
53
|
+
| `plan-checker` | `opus` | Adversarial validator for planner output; equivalent reasoning depth required. |
|
|
54
|
+
| `researcher` | `sonnet` | Web/MCP fetch + synthesis; wider context tolerance, lighter reasoning load. |
|
|
55
|
+
|
|
56
|
+
No mid-run tier re-selection (D-14). `loadAgent()` re-reads the file on every call — never cached — so edits to the markdown are picked up immediately but cannot be tampered with at runtime.
|
|
57
|
+
|
|
58
|
+
## Plan-Checker Finding Categories (starting set)
|
|
59
|
+
|
|
60
|
+
Canonical identifiers for findings that `agents/np-plan-checker.md` emits. Starting set — extensible by the plan-checker agent as new failure modes are observed.
|
|
61
|
+
|
|
62
|
+
- `missing-success-criterion` — a ROADMAP SC-X is not mapped to any task.
|
|
63
|
+
- `non-atomic-task` — a task bundles multiple distinct deliverables that should be split.
|
|
64
|
+
- `unbounded-scope` — `<action>` uses words like "etc.", "and related", "as needed" without concrete enumeration.
|
|
65
|
+
- `broken-dependency` — `depends_on` references a plan or task that does not exist.
|
|
66
|
+
- `cyclic-dependency` — the wave-graph computation detects a cycle.
|
|
67
|
+
- `fake-promotion-trigger` — plan claims a `tasks/` promotion trigger (parallelism / mixed-tiers / non-linear-deps) that its own task list does not substantiate (D-18..D-20).
|
|
68
|
+
- `missing-coverage-annotation` — a task modifies production code without a `tdd="true"` task or a `<verify><automated>` command (Nyquist rule).
|
|
69
|
+
- `bare-askuser-call` — workflow MD emits `AskUserQuestion` directly instead of `node np-tools.cjs askuser --json '{…}'` (D-04).
|
|
70
|
+
- `hook-field-present` — agent frontmatter contains `hooks:` (D-10).
|
|
71
|
+
- `forbidden-agent-field` — agent frontmatter contains `model:` or `model_profile:` (D-10).
|
|
72
|
+
|
|
73
|
+
Each finding returned by plan-checker carries one of these codes plus an anchor `{file, line}` pair so the planner's revise-mode can address them without re-deriving context.
|
|
74
|
+
|
|
75
|
+
## Validation Flow
|
|
76
|
+
|
|
77
|
+
`validateAgentFrontmatter(fm, agentName)` runs four gates in strict order, throwing the first violation and skipping the rest:
|
|
78
|
+
|
|
79
|
+
1. **REQUIRED** — every field in `REQUIRED = ['name', 'description', 'tier', 'tools']` must be truthy; otherwise `agent-invalid-frontmatter` with `details.field`.
|
|
80
|
+
2. **FORBIDDEN** — no field in `FORBIDDEN = ['model', 'model_profile', 'hooks']` may be defined; otherwise `agent-forbidden-field` with `details.field` and `details.hint`.
|
|
81
|
+
3. **TIER_ENUM** — `fm.tier` must be in `TIER_ENUM = ['haiku', 'sonnet', 'opus']`; otherwise `agent-invalid-tier` with `details.value` and `details.allowed`.
|
|
82
|
+
4. **Name match** — `fm.name` must equal the `agentName` passed in (which `loadAgent` derives from the filename stem); otherwise `agent-invalid-frontmatter` with `details.field === 'name'`, `details.expected`, `details.got`.
|
|
83
|
+
|
|
84
|
+
All error codes are stable identifiers; callers (workflows, plan-checker, test suites) match on `err.code` verbatim rather than on message strings.
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Phase Artifact Schemas
|
|
2
|
+
|
|
3
|
+
Phase-5 defines the canonical on-disk format of the 5 planning artifacts.
|
|
4
|
+
Downstream phases (Phase 6 executor, Phase 10 review commands) parse against
|
|
5
|
+
these schemas. Breaking changes require a Phase-5 amendment or a new phase.
|
|
6
|
+
|
|
7
|
+
All artifacts live under `.nubos-pilot/phases/<padded>-<slug>/` — e.g.
|
|
8
|
+
`.nubos-pilot/phases/05-planning-workflows-agents/05-CONTEXT.md`.
|
|
9
|
+
|
|
10
|
+
| Artifact | Producer | Consumer(s) | Lifecycle |
|
|
11
|
+
| ------------------ | ---------------------------- | ---------------------------------------- | --------------- |
|
|
12
|
+
| `CONTEXT.md` | `/np:discuss-phase` | researcher, planner, plan-checker | rewrite on save |
|
|
13
|
+
| `RESEARCH.md` | `/np:research-phase` | planner, plan-checker | rewrite on save |
|
|
14
|
+
| `PLAN.md` | `/np:plan-phase` planner | plan-checker, executor, verifier | rewrite on save |
|
|
15
|
+
| `PLAN-REVIEW.md` | `/np:plan-phase` loop | user, np:undo, Phase 10 review | append-only |
|
|
16
|
+
| `QUESTIONS.json` | `/np:discuss-phase-power` | power-mode UI, discuss-phase finalize | rewrite on save |
|
|
17
|
+
|
|
18
|
+
## CONTEXT.md
|
|
19
|
+
|
|
20
|
+
Captures user decisions from the adaptive interview. Read by every downstream
|
|
21
|
+
agent. Structure:
|
|
22
|
+
|
|
23
|
+
```markdown
|
|
24
|
+
---
|
|
25
|
+
phase: "<phase-number>"
|
|
26
|
+
padded: "<padded>"
|
|
27
|
+
phase_name: "<human-readable>"
|
|
28
|
+
mode: adaptive | assumptions | power
|
|
29
|
+
finalized: <ISO-8601>
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
# <Phase Name> — Context
|
|
33
|
+
|
|
34
|
+
<domain>
|
|
35
|
+
One-paragraph framing: what user domain is this phase serving?
|
|
36
|
+
</domain>
|
|
37
|
+
|
|
38
|
+
<decisions>
|
|
39
|
+
**D-01:** First locked decision (short imperative)
|
|
40
|
+
- Rationale: …
|
|
41
|
+
- Constraints: …
|
|
42
|
+
|
|
43
|
+
**D-02:** Next decision …
|
|
44
|
+
</decisions>
|
|
45
|
+
|
|
46
|
+
<canonical_refs>
|
|
47
|
+
- path/to/file.ts (why it matters)
|
|
48
|
+
- https://… (spec or vendor doc)
|
|
49
|
+
</canonical_refs>
|
|
50
|
+
|
|
51
|
+
<code_context>
|
|
52
|
+
- `lib/foo.cjs` — current behavior, what we keep, what we replace
|
|
53
|
+
</code_context>
|
|
54
|
+
|
|
55
|
+
<specifics>
|
|
56
|
+
- Concrete inputs/outputs the user insisted on
|
|
57
|
+
</specifics>
|
|
58
|
+
|
|
59
|
+
<deferred>
|
|
60
|
+
- Items explicitly parked for a later phase
|
|
61
|
+
</deferred>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Required tag blocks:** `<domain>`, `<decisions>`, `<canonical_refs>`,
|
|
65
|
+
`<code_context>`, `<specifics>`, `<deferred>`. Tag blocks may be empty but
|
|
66
|
+
must be present — downstream agents assume the structure.
|
|
67
|
+
|
|
68
|
+
**Placeholders** in `templates/CONTEXT.md` (Plan 05-06) use `{{ snake_case }}`;
|
|
69
|
+
`lib/template.cjs` fails loud on unknown keys.
|
|
70
|
+
|
|
71
|
+
## RESEARCH.md
|
|
72
|
+
|
|
73
|
+
Stack, patterns, pitfalls, security domain, open questions. Produced by
|
|
74
|
+
`agents/np-researcher.md` (tier=sonnet). High-level H2 sections — in this order:
|
|
75
|
+
|
|
76
|
+
```markdown
|
|
77
|
+
## Summary
|
|
78
|
+
## Standard Stack
|
|
79
|
+
## Architecture Patterns
|
|
80
|
+
## Don't Hand-Roll
|
|
81
|
+
## Pitfalls
|
|
82
|
+
## Security Domain
|
|
83
|
+
## Validation Architecture
|
|
84
|
+
## Assumptions Log
|
|
85
|
+
## Open Questions
|
|
86
|
+
## Environment Availability
|
|
87
|
+
## Research Coverage
|
|
88
|
+
## Sources
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`## Research Coverage` is **mandatory in offline mode** (no WebFetch/MCP) — it
|
|
92
|
+
lists which areas were covered from local knowledge only so the planner can
|
|
93
|
+
flag gaps. In online mode the section may be empty but the header must be
|
|
94
|
+
present.
|
|
95
|
+
|
|
96
|
+
Each source line in `## Sources` uses:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
- <absolute path or URL> — <one-line relevance note> — <HIGH|MEDIUM|LOW>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## PLAN.md
|
|
103
|
+
|
|
104
|
+
The executor's prompt. YAML frontmatter + body. One PLAN.md per `NN-NN-PLAN.md`
|
|
105
|
+
(phase-scoped — the plan number is the second NN). Produced by
|
|
106
|
+
`agents/np-planner.md` (tier=opus), verified by `agents/np-plan-checker.md` (opus).
|
|
107
|
+
|
|
108
|
+
### Required frontmatter keys
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
---
|
|
112
|
+
phase: "<phase-number>" # string, e.g. "5"
|
|
113
|
+
plan: "<phase>-<plan>" # e.g. "05-01"
|
|
114
|
+
plan_id: "<phase>-<plan>" # stable ID — equal to `plan`
|
|
115
|
+
wave: <integer> # 1..N — planner-assigned execution wave
|
|
116
|
+
depends_on: [<plan_id>, …] # inter-plan dependencies
|
|
117
|
+
files_modified: [<relative-path>] # every path this plan will touch
|
|
118
|
+
autonomous: true | false # true = no human gate needed mid-execution
|
|
119
|
+
requirements: [<REQ-ID>] # roadmap requirement IDs this plan covers
|
|
120
|
+
must_haves: # goal-backward truths + artifacts + links
|
|
121
|
+
truths: [string, …]
|
|
122
|
+
artifacts: [{ path, provides }]
|
|
123
|
+
key_links: [{ from, to, via, pattern }]
|
|
124
|
+
---
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Required body sections
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
<objective>
|
|
131
|
+
Single-paragraph statement of intent.
|
|
132
|
+
</objective>
|
|
133
|
+
|
|
134
|
+
<context>
|
|
135
|
+
@<path> # embed CONTEXT.md, RESEARCH.md, sibling plans, libs
|
|
136
|
+
<interfaces>
|
|
137
|
+
Shape descriptions of APIs this plan touches.
|
|
138
|
+
</interfaces>
|
|
139
|
+
</context>
|
|
140
|
+
|
|
141
|
+
<tasks>
|
|
142
|
+
<task type="auto" tdd="true|false">
|
|
143
|
+
<name>Task N: …</name>
|
|
144
|
+
<files>…</files>
|
|
145
|
+
<read_first>…</read_first>
|
|
146
|
+
<behavior>…</behavior>
|
|
147
|
+
<action>…</action>
|
|
148
|
+
<verify><automated>…</automated></verify>
|
|
149
|
+
<acceptance_criteria>…</acceptance_criteria>
|
|
150
|
+
<done>…</done>
|
|
151
|
+
</task>
|
|
152
|
+
</tasks>
|
|
153
|
+
|
|
154
|
+
<threat_model>
|
|
155
|
+
| Threat ID | Category | Component | Disposition | Mitigation |
|
|
156
|
+
</threat_model>
|
|
157
|
+
|
|
158
|
+
<verification>
|
|
159
|
+
- Shell command(s) the executor runs after the plan completes.
|
|
160
|
+
</verification>
|
|
161
|
+
|
|
162
|
+
<success_criteria>
|
|
163
|
+
- Boolean predicates that must hold after execution.
|
|
164
|
+
</success_criteria>
|
|
165
|
+
|
|
166
|
+
<output>
|
|
167
|
+
Path of the SUMMARY.md that the executor writes.
|
|
168
|
+
</output>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Optional sections
|
|
172
|
+
|
|
173
|
+
- `## Task Promotion` — emitted when Plan 05-04's `shouldPromoteToTasks`
|
|
174
|
+
returns `promote: true`. Lists the triggers (`parallelism`, `mixed-tiers`,
|
|
175
|
+
`non-linear-deps`) and the rationale. The presence of this section tells
|
|
176
|
+
the plan-phase workflow to scaffold `tasks/`. See D-18..D-20.
|
|
177
|
+
|
|
178
|
+
## PLAN-REVIEW.md
|
|
179
|
+
|
|
180
|
+
**Append-only** audit trail of the plan-checker verification loop. One file
|
|
181
|
+
per phase (not per plan). Created by `plan-review-append` verb (Plan 05-10
|
|
182
|
+
Task 1). Never truncated, even on abort (D-16, D-17).
|
|
183
|
+
|
|
184
|
+
Format:
|
|
185
|
+
|
|
186
|
+
```markdown
|
|
187
|
+
# PLAN-REVIEW.md — Phase <N> (<Phase Name>)
|
|
188
|
+
|
|
189
|
+
Append-only audit trail of plan-checker iterations. Never truncate.
|
|
190
|
+
|
|
191
|
+
## Iteration 1 - 2026-04-15T14:22:13.412Z
|
|
192
|
+
|
|
193
|
+
**Planner output:** PLAN.md committed at <sha or 'pending'>
|
|
194
|
+
**Checker verdict:** issues_found
|
|
195
|
+
**Findings:**
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
status: issues_found
|
|
199
|
+
findings:
|
|
200
|
+
- category: missing-success-criterion
|
|
201
|
+
severity: critical
|
|
202
|
+
target: "PLAN.md §SC-3"
|
|
203
|
+
message: "No task addresses SC-3."
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Planner response:** revision
|
|
207
|
+
|
|
208
|
+
## Iteration 2 - 2026-04-15T14:24:41.988Z
|
|
209
|
+
|
|
210
|
+
**Planner output:** PLAN.md committed at <sha>
|
|
211
|
+
**Checker verdict:** passed
|
|
212
|
+
**Findings:**
|
|
213
|
+
|
|
214
|
+
```yaml
|
|
215
|
+
status: passed
|
|
216
|
+
findings: []
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Planner response:** done
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Invariants:
|
|
223
|
+
|
|
224
|
+
- Every iteration section begins with `## Iteration <N> - <ISO_TIMESTAMP>`.
|
|
225
|
+
- The YAML verdict block is fenced with `yaml` language tag (Plan 05-10
|
|
226
|
+
Open Question 4 resolution).
|
|
227
|
+
- Byte-level append-only — pre-existing bytes are a sha256-verified prefix
|
|
228
|
+
of post-append bytes.
|
|
229
|
+
- Survives `plan-phase-abort` (Plan 05-10 Task 1) — abort deletes PLAN.md and
|
|
230
|
+
`tasks/` but never touches PLAN-REVIEW.md.
|
|
231
|
+
|
|
232
|
+
## QUESTIONS.json
|
|
233
|
+
|
|
234
|
+
Power-mode state file. Produced by `discuss-phase-power` (Plan 05-08).
|
|
235
|
+
Single source of truth while power-mode is in progress; CONTEXT.md is a
|
|
236
|
+
derived artifact written only on `finalize` (Pitfall 1 guard).
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"phase": "5",
|
|
241
|
+
"padded": "05",
|
|
242
|
+
"mode": "power",
|
|
243
|
+
"created": "2026-04-15T10:00:00.000Z",
|
|
244
|
+
"questions": [
|
|
245
|
+
{
|
|
246
|
+
"id": "Q-01",
|
|
247
|
+
"area": "decisions",
|
|
248
|
+
"question": "Should we gate the /np:plan-phase dispatcher …?",
|
|
249
|
+
"answer": "Yes, use the registry pattern.",
|
|
250
|
+
"explain": "Matches the registry invariant established in Phase 4 D-21."
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
"answers_status": "pending"
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Schema:
|
|
258
|
+
|
|
259
|
+
| Key | Type | Notes |
|
|
260
|
+
| ----------------- | --------- | -------------------------------------------- |
|
|
261
|
+
| `phase` | string | Phase number (matches CONTEXT.md frontmatter) |
|
|
262
|
+
| `padded` | string | Two-digit padded number |
|
|
263
|
+
| `mode` | string | Always `"power"` here |
|
|
264
|
+
| `created` | string | ISO-8601 creation timestamp |
|
|
265
|
+
| `questions` | array | Ordered list of question objects |
|
|
266
|
+
| `answers_status` | string | `pending` \| `finalized` |
|
|
267
|
+
|
|
268
|
+
Question object:
|
|
269
|
+
|
|
270
|
+
| Key | Type | Notes |
|
|
271
|
+
| ---------- | ---------------------- | ------------------------------------------------------ |
|
|
272
|
+
| `id` | string | `Q-NN` — stable ID |
|
|
273
|
+
| `area` | enum | `domain` \| `decisions` \| `canonical_refs` \| `code_context` \| `specifics` \| `deferred` |
|
|
274
|
+
| `question` | string | Question text (German or English depending on user) |
|
|
275
|
+
| `answer` | string \| null | `null` until the user fills it |
|
|
276
|
+
| `explain` | string \| null | Optional rationale the user adds inline |
|
|
277
|
+
|
|
278
|
+
Lifecycle:
|
|
279
|
+
|
|
280
|
+
- `discuss-phase-power` writes the file on first run and on `refresh`.
|
|
281
|
+
- User edits the JSON directly in their editor.
|
|
282
|
+
- On `finalize`: workflow reads JSON, flips `answers_status` to `finalized`,
|
|
283
|
+
renders CONTEXT.md, and writes both files atomically.
|
|
284
|
+
- CONTEXT.md is **derived** — regenerating QUESTIONS.json always wins.
|
|
285
|
+
|
|
286
|
+
Downstream consumers:
|
|
287
|
+
|
|
288
|
+
- `discuss-phase-power` finalize step — only entry point that touches
|
|
289
|
+
CONTEXT.md from power mode.
|
|
290
|
+
- Phase 6 `np:undo` — reads QUESTIONS.json to detect mid-interview state
|
|
291
|
+
and warn the user before rolling back.
|
|
292
|
+
- Phase 10 review commands — may parse for audit-trail completeness.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Phase Directory Layout
|
|
2
|
+
|
|
3
|
+
**Status:** Canonical — Phase-4 D-24 / D-25
|
|
4
|
+
**Last updated:** 2026-04-15
|
|
5
|
+
|
|
6
|
+
This document is the authoritative spec for what a `.planning/phases/<NN>-<slug>/`
|
|
7
|
+
directory may contain, which files are parser-mandatory, which are produced by
|
|
8
|
+
which workflow, and which are consumed by which agent.
|
|
9
|
+
|
|
10
|
+
## Mandatory files
|
|
11
|
+
|
|
12
|
+
These are the only files that `lib/phase.cjs` / `lib/plan.cjs` / `lib/tasks.cjs`
|
|
13
|
+
read by contract. A phase directory is well-formed when each of its plans has a
|
|
14
|
+
`PLAN.md` and (optionally) a `tasks/` subdirectory with one `.md` file per task.
|
|
15
|
+
|
|
16
|
+
| File | Producer workflow | Parser | Minimal required sections |
|
|
17
|
+
| ---------------------- | --------------------------- | ----------------------- | ------------------------------------------------------------------------------------- |
|
|
18
|
+
| `<NN>-<MM>-PLAN.md` | `np:plan-phase` | `lib/plan.cjs` | Frontmatter: `phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves`; body: `<objective>`, `<tasks>` (may be empty if plan is single-task), `<success_criteria>` |
|
|
19
|
+
| `tasks/<task-id>.md` | `np:plan-phase` | `lib/tasks.cjs` | Frontmatter: full 12-field set per D-01 (`id, phase, plan, type, status, tier, owner, wave, depends_on, files_modified, autonomous, must_haves`); body: freeform task prose |
|
|
20
|
+
|
|
21
|
+
Notes:
|
|
22
|
+
- `tasks/` is **optional at the plan level**: a plan promotes to `tasks/*.md`
|
|
23
|
+
only when parallelism, mixed tiers, or non-linear dependencies demand it.
|
|
24
|
+
A single-task plan may keep its tasks inline inside `PLAN.md`.
|
|
25
|
+
- Every other file in the phase directory is **workflow-produced / workflow-consumed only**.
|
|
26
|
+
Parsers never read them.
|
|
27
|
+
|
|
28
|
+
## Optional files (workflow artifacts)
|
|
29
|
+
|
|
30
|
+
The parser contract does not read these. Each is produced by a specific
|
|
31
|
+
workflow and consumed by a specific downstream agent or workflow step. Missing
|
|
32
|
+
files are never an error — they simply indicate that the corresponding workflow
|
|
33
|
+
step did not run (or has not run yet).
|
|
34
|
+
|
|
35
|
+
| File | Producer workflow | Consumer agent(s) / workflow | Minimal required sections |
|
|
36
|
+
| --------------------------------- | ---------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `<NN>-CONTEXT.md` | `np:discuss-phase` | planner, researcher, plan-checker | `<domain>`, `<decisions>`, `<constraints>`, `<dependencies>`, `<success_criteria>` |
|
|
38
|
+
| `<NN>-RESEARCH.md` | `np:research-phase` | planner, plan-checker | `<sources>` (at least one link with HIGH/MEDIUM/LOW credibility), `<findings>`, `<open_questions>`, `<flags>` |
|
|
39
|
+
| `<NN>-PATTERNS.md` | `np:plan-phase` (pre-plan) | planner, executor | `File Classification` table, per-file `Analog` block, `Shared Patterns` (S-1..S-N) section |
|
|
40
|
+
| `<NN>-VALIDATION.md` | `np:plan-phase` (pre-plan) | planner, executor, verifier | `Validation Strategy`, `Must-Have Truths`, `Artifact Checks`, `Traceability Matrix` |
|
|
41
|
+
| `<NN>-<MM>-SUMMARY.md` | `np:execute-plan` | verifier, `np:progress`, `np:next` | Frontmatter: `phase, plan, subsystem, key-files, decisions, metrics`; body: `Objective`, `What Was Built`, `Key Decisions`, `Deviations`, `Self-Check` |
|
|
42
|
+
| `<NN>-VERIFICATION.md` | `np:verify-work` | `np:next` (rule 4 gate), human reviewer | `Scope`, `Evidence`, `Result` (pass/fail), `Follow-ups`. Presence flips `np:next` from rule-4 to rule-5 for the phase. |
|
|
43
|
+
| `<NN>-DISCUSSION-LOG.md` | `np:discuss-phase` | planner (carry-over), human reviewer | Freeform Q&A transcript — no parser contract |
|
|
44
|
+
| `<NN>-UI-SPEC.md` | `np:ui-phase` | UI executor, reviewer | `Screens`, `Components`, `Interactions`, `Accessibility`, `Design-system references` |
|
|
45
|
+
| `<NN>-AI-SPEC.md` | `np:ai-integration-phase` | AI executor, eval-reviewer | `Framework selector`, `Model profile`, `Prompt contracts`, `Eval strategy`, `Metrics` |
|
|
46
|
+
| `<NN>-REVIEW.md` / `REVIEW-FIX.md`| `np:review` / `np:code-review` | executor (follow-up), verifier | `Findings` table, `Severity`, `Remediation plan` |
|
|
47
|
+
| `<NN>-verify.sh` | `np:plan-phase` (optional) | executor, verifier, CI | POSIX-sh script; exit 0 = pass, non-zero = fail. Each assertion uses `[ -f ... ]` / `grep -q ...` / `node --test ...` style |
|
|
48
|
+
|
|
49
|
+
## Parser contract
|
|
50
|
+
|
|
51
|
+
`lib/phase.cjs` (`findPhaseDir`, `paddedPhase`, `slug`) navigates the directory
|
|
52
|
+
tree by filename convention only. `lib/plan.cjs` (`parsePlan`, `listPlans`)
|
|
53
|
+
reads `PLAN.md` files. `lib/tasks.cjs` (`loadTaskGraph`,
|
|
54
|
+
`validateTaskFrontmatter`) reads `tasks/*.md` if the subdirectory exists.
|
|
55
|
+
|
|
56
|
+
None of these parsers read any of the optional files listed above. Workflows
|
|
57
|
+
that consume optional files do so by explicit path (e.g.
|
|
58
|
+
`fs.readFileSync(path.join(phaseDir, '04-CONTEXT.md'), 'utf-8')`) with
|
|
59
|
+
ENOENT-tolerance — a missing file is a non-error state meaning "that step
|
|
60
|
+
hasn't been run".
|
|
61
|
+
|
|
62
|
+
## Producer-workflow vs. consumer-agent separation
|
|
63
|
+
|
|
64
|
+
Workflow commands (`np:*`) produce files; subagents (planner, researcher,
|
|
65
|
+
executor, verifier, plan-checker) consume them. A well-formed phase directory
|
|
66
|
+
reflects exactly which workflow steps have been completed, which is what
|
|
67
|
+
`np:next` uses to compute the next actionable step (Phase-4 D-12..D-15 gate
|
|
68
|
+
rules).
|
|
69
|
+
|
|
70
|
+
## Relation to D-24 / D-25
|
|
71
|
+
|
|
72
|
+
- **D-24:** Only `PLAN.md` and `tasks/` are parser-mandatory. Every other file
|
|
73
|
+
is workflow-produced and may be absent.
|
|
74
|
+
- **D-25:** This file is the authoritative spec for the optional-file list.
|
|
75
|
+
When a new workflow is added (e.g. Phase 5's `np:research-phase`), it must
|
|
76
|
+
either produce one of the files listed above or extend this table.
|
|
77
|
+
|
|
78
|
+
## References
|
|
79
|
+
|
|
80
|
+
- Phase-4 `04-CONTEXT.md` §decisions D-24, D-25
|
|
81
|
+
- Phase-3 `03-CONTEXT.md` §D-12..D-17 (task-frontmatter baseline)
|
|
82
|
+
- `lib/plan.cjs`, `lib/tasks.cjs`, `lib/phase.cjs` — the only parsers that read this tree
|