Appearance
Milestone Directory Layout
Authoritative spec for what a .nubos-pilot/milestones/M<NNN>/ directory contains, which files are parser-mandatory, which are produced by which workflow, and which are consumed by which agent.
Top layout
.nubos-pilot/
├── PROJECT.md
├── REQUIREMENTS.md
├── RULES.md # project-wide always-follow (precedence over M-CONTEXT)
├── roadmap.yaml # schema_version: 2; optional top-level project_status: active | completed (ADR-0016)
├── ROADMAP.md
├── STATE.md
├── PROJECT-SUMMARY.md # written by /np:close-project (ADR-0016); regenerated on each close
├── config.json
├── learnings/ # carry-over candidate on archive (ADR-0016 default)
├── solutions/ # carry-over candidate on archive (ADR-0016 default)
├── memory/ # opt-in vector store (ADR-0014); never archived, queryable across archives
├── archive/ # archived predecessor projects (ADR-0016)
│ └── <slug>-<YYYYMMDD>[-N]/
│ ├── ARCHIVE.json # manifest: archived_at, project_name, completion_status, blockers, moved[], carried_over[], forced
│ ├── PROJECT.md, REQUIREMENTS.md, RULES.md, ROADMAP.md, STATE.md, roadmap.yaml, milestones/, codebase/, …
│ └── learnings/, solutions/ # only if carry-over included them
├── state/ # ephemeral cache (gitignored)
│ ├── knowledge-index.json # BM25-light index over .nubos-pilot/**/*.md
│ └── session-snapshot.json # captured by pause-work, read by resume-work
├── handoffs/ # cross-milestone agent handoffs (optional)
├── worktrees/ # git worktrees per slice (opt-in; MUST be gitignored)
│ └── M<NNN>/
│ └── S<NNN>/ # isolated working tree on branch np/M<NNN>-S<NNN>
└── milestones/
└── M<NNN>/
├── M<NNN>-CONTEXT.md
├── M<NNN>-ROADMAP.md
├── M<NNN>-META.json
├── M<NNN>-RESEARCH.md (optional) — reconciler output (ADR-0018), research-final schema
├── M<NNN>-PLAN-REVIEW.md (append-only)
├── M<NNN>-VERIFICATION.md (verification schema, ADR-0017)
├── M<NNN>-VALIDATION.md (optional) — validation schema, ADR-0017
├── handoffs/ # milestone-scoped agent handoffs
├── research/ # per-spawn researcher outputs + deterministic merge (ADR-0018)
│ ├── spawn-0.md # researcher-output schema
│ ├── spawn-1.md
│ ├── spawn-2.md
│ └── merge.md # mergeConsensus proposal — input to reconciler
└── slices/
└── S<NNN>/
├── S<NNN>-ASSESSMENT.md
├── S<NNN>-PLAN.md
├── S<NNN>-RESEARCH.md (optional)
├── S<NNN>-UAT.md
├── S<NNN>-SUMMARY.md
├── TODO.md # checkbox rollup (auto-rendered)
└── tasks/
└── T<NNNN>/
├── T<NNNN>-PLAN.md
└── T<NNNN>-SUMMARY.mdMandatory files
These are the only files that parsers read by contract.
| File | Producer | Parser | Minimal required sections |
|---|---|---|---|
roadmap.yaml | /np:new-project, /np:new-milestone, /np:close-project | lib/roadmap.cjs | schema_version, milestones[] with id, number, name, goal, status, slices. Optional top-level project_status: active | completed + completed_at: <ISO> (set by /np:close-project mark-completed, ADR-0016). |
S<NNN>-PLAN.md | /np:plan-phase (planner) | plan-milestone scaffolder | Frontmatter: slice, milestone, type, status, requirements; body: <objective>, <tasks> with <task id="M-S-T" depends_on="…" wave="N" tier="…"> blocks |
T<NNNN>-PLAN.md | /np:plan-phase (scaffolder) | lib/tasks.cjs.loadTaskGraph, executor | Frontmatter: id, slice, milestone, type, status, tier, owner, wave, depends_on, files_modified, autonomous, must_haves; body: freeform task prose |
Optional files (workflow artifacts)
Parsers never read these. Each is produced by a specific workflow and consumed by a specific downstream agent or workflow step. Missing files are never an error; they simply indicate that the corresponding workflow step did not run (or has not run yet).
| File | Producer workflow | Consumer | Purpose |
|---|---|---|---|
RULES.md | /np:new-project (initial scaffold); manual updates | every agent (read at start) | Project-wide always-follow rules; precedence over M<NNN>-CONTEXT.md |
M<NNN>-CONTEXT.md | /np:discuss-phase | planner, researcher, plan-checker, executor, architect, security-reviewer | Locked decisions D-01..D-NN, deferred ideas, canonical references, domain boundary |
M<NNN>-ROADMAP.md | /np:plan-phase (planner) | plan-checker, verifier | Slice list, execution order |
M<NNN>-META.json | /np:plan-phase (planner) | status displays | slice_count, task_count, status |
M<NNN>-RESEARCH.md | /np:research-phase (reconciler, Stage 2, ADR-0018) | planner, plan-checker, architect | Stack, pitfalls, sources, research coverage annotation. Schema-bound (research-final, ADR-0017); frontmatter exposes agreement_score, contested_count, reconciler_verdict. |
M<NNN>/research/spawn-<i>.md (k entries) | /np:research-phase Stage 1 (each np-researcher spawn) | reconciler | Per-spawn researcher output (researcher-output schema, ADR-0018). Required Reasoning field per Decision/Risk/Pattern. Auditable post-hoc. |
M<NNN>/research/merge.md | /np:research-phase Stage 1 (mergeConsensus) | reconciler | Deterministic Mehrheit/Union/Schnittmenge merge — proposal, not final answer. |
PROJECT-SUMMARY.md (project-level) | /np:close-project write-summary (ADR-0016) | human reviewer; future archive manifest | Aggregate verification across every milestone. Regenerated on each close; never authoritative for milestone-level signals (those live in M<NNN>-VERIFICATION.md). |
archive/<slug>-<YYYYMMDD>/ (project-level) | /np:archive-project do / /np:new-project Phase -1 (ADR-0016) | archive-project list, archive-project read, vector-memory cross-project lookup | Frozen predecessor project. Contains a full snapshot at archive time plus ARCHIVE.json manifest. Carry-over copies of learnings/ + solutions/ are kept top-level for the successor. |
M<NNN>-ARCHITECTURE.md | /np:architect-phase (optional) | planner, plan-checker | Module boundaries, data-flow sketch, 3–7 ADR-style D-arch-N decisions |
M<NNN>-PLAN-REVIEW.md | /np:plan-phase (plan-checker loop) | human reviewer | Append-only audit trail of each planner/plan-checker iteration |
M<NNN>-VERIFICATION.md | /np:verify-work | human reviewer, /np:add-tests | Per-success-criterion Pass/Fail/Defer classification |
M<NNN>-VALIDATION.md | /np:validate-phase | human reviewer | Nyquist coverage audit: COVERED/UNDER_SAMPLED/UNCOVERED per requirement |
M<NNN>-SECURITY.md | manual np-security-reviewer spawn | human reviewer, next-milestone planner | OWASP-aligned audit; per-finding Pass / Risk / Defer classification |
state/knowledge-index.json | np-tools.cjs knowledge-index (auto-built on first knowledge-search) | every agent that runs knowledge-search | BM25-light full-text index; ephemeral, gitignored |
state/session-snapshot.json | np-tools.cjs pause-work | np-tools.cjs resume-work | Captured continuity context (milestone, task, recent commits, open handoffs); ephemeral, gitignored |
S<NNN>-ASSESSMENT.md | /np:plan-phase (planner) | plan-checker, executor | Risk, effort, dependencies, blockers per slice |
S<NNN>-RESEARCH.md | /np:research-phase (per slice, optional) | planner, executor | Slice-scoped research notes |
S<NNN>-UAT.md | /np:plan-phase (planner) | plan-checker, verifier | Acceptance criteria, happy path, edge cases |
S<NNN>-SUMMARY.md | executor (last task) | verifier | Per-wave outcome: changes, verification, follow-ups |
T<NNNN>-SUMMARY.md | executor (after commit) | verifier, human reviewer | Per-task outcome: files changed, tests run, follow-ups |
S<NNN>/TODO.md | lib/todo.cjs::renderTodoMd (triggered by setTaskStatus + plan-milestone scaffold-all-tasks) | human reader, executor resume, verifier | Checkbox rollup of all task statuses for the slice. Derived from task frontmatter — never authoritative. |
M<NNN>/handoffs/<ts>__<from>-to-<to>__<slug>__<id>.md | lib/handoff.cjs::writeHandoff (via handoff-write CLI) | target agent (filtered by to_agent) | Milestone-scoped agent-to-agent note for cross-phase signals |
handoffs/<ts>__<from>-to-<to>__<slug>__<id>.md (top-level) | lib/handoff.cjs::writeHandoff (no --milestone) | target agent | Cross-milestone / project-global handoff |
Parser contract
lib/layout.cjsis the authoritative path module. All milestone/slice/task paths are computed viamilestoneDir(n),sliceDir(m, s),taskDir(m, s, t), and related helpers.lib/roadmap.cjs.parseRoadmapreadsroadmap.yaml—milestones[].slices[].tasks[](schema_version 2). Falls back to the legacymilestones[].phases[]shape for projects not yet migrated.lib/tasks.cjs.loadTaskGraph(sliceDir)readssliceDir/tasks/T<NNNN>/T<NNNN>-PLAN.md(one directory per task).TASK_ID_RE = /^M\d{3,}-S\d{3,}-T\d{4,}$/.lib/verify.cjs.writeVerificationMdwrites the milestone-level VERIFICATION.lib/todo.cjs.renderTodoMd(sliceFullId, cwd)regeneratesS<NNN>/TODO.mdatomically. Invoked bysetTaskStatus(socommit-task/skip/park/unparkall keep it live) and byplan-milestone scaffold-all-tasksfor the initial render.lib/handoff.cjsexposeswriteHandoff,listHandoffs,readHandoff,setHandoffStatus. None of the scaffolders or parsers read handoff files — they are agent-to-agent channels outside the plan/verify parse path.lib/worktree.cjsexposescreateSliceWorktree,removeSliceWorktree,listSliceWorktrees,ffMergeSliceWorktree,hasSliceWorktree,worktreeIsolationEnabled. All git shell-outs route throughlib/git.cjs::runGitso thelib/*.cjs → no child_processinvariant (ADR-0001 /surface-audit.test.cjs) stays intact..nubos-pilot/worktrees/must be in.gitignore;createSliceWorktreechecks this viagit check-ignoreand fails loud if not.lib/dashboard.cjsexposescollectSnapshot(read-only aggregation of milestones, slices, handoffs, worktrees, and git branch) andrenderSnapshot(ANSI text layout). The CLIdashboardwraps both. It is a one-shot read-only render with--jsonand--no-colorflags only; there is no--watchand no daemon (ADR-0001).
None of these parsers read any of the optional files listed above. Workflows that consume optional files do so by explicit path with ENOENT-tolerance.
Producer-workflow vs. consumer-agent separation
Workflow commands (/np:*) produce files; subagents (planner, plan-checker, executor, verifier, nyquist-auditor, researcher, codebase-documenter) consume them. A well-formed milestone directory shows exactly which workflow steps have run.
Slices ARE waves
Inside a slice, all tasks run in parallel. Between slices, execution is serial. Cross-slice dependencies flow forward only: a task in S002 may depend on a task in S001, never the reverse. This is enforced by the plan-checker (Dimension 5: Dependency Graph Integrity).
Legacy layout
Prior to v2 the tree looked like .nubos-pilot/phases/<NN>-<slug>/<NN>-<MM>-PLAN.md with flat tasks/<task-id>.md files. /np:plan-phase <N> writes the new layout; the parser accepts the old phases[] roadmap shape as a fallback for read-only operations. /np:doctor flags a stale .nubos-pilot/phases/ directory as legacy-phases-dir (info), which is safe to rm -rf once the new layout is in place.
