Skip to content

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.md

Mandatory files

These are the only files that parsers read by contract.

FileProducerParserMinimal required sections
roadmap.yaml/np:new-project, /np:new-milestone, /np:close-projectlib/roadmap.cjsschema_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 scaffolderFrontmatter: 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, executorFrontmatter: 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).

FileProducer workflowConsumerPurpose
RULES.md/np:new-project (initial scaffold); manual updatesevery agent (read at start)Project-wide always-follow rules; precedence over M<NNN>-CONTEXT.md
M<NNN>-CONTEXT.md/np:discuss-phaseplanner, researcher, plan-checker, executor, architect, security-reviewerLocked decisions D-01..D-NN, deferred ideas, canonical references, domain boundary
M<NNN>-ROADMAP.md/np:plan-phase (planner)plan-checker, verifierSlice list, execution order
M<NNN>-META.json/np:plan-phase (planner)status displaysslice_count, task_count, status
M<NNN>-RESEARCH.md/np:research-phase (reconciler, Stage 2, ADR-0018)planner, plan-checker, architectStack, 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)reconcilerPer-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)reconcilerDeterministic Mehrheit/Union/Schnittmenge merge — proposal, not final answer.
PROJECT-SUMMARY.md (project-level)/np:close-project write-summary (ADR-0016)human reviewer; future archive manifestAggregate 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 lookupFrozen 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-checkerModule boundaries, data-flow sketch, 3–7 ADR-style D-arch-N decisions
M<NNN>-PLAN-REVIEW.md/np:plan-phase (plan-checker loop)human reviewerAppend-only audit trail of each planner/plan-checker iteration
M<NNN>-VERIFICATION.md/np:verify-workhuman reviewer, /np:add-testsPer-success-criterion Pass/Fail/Defer classification
M<NNN>-VALIDATION.md/np:validate-phasehuman reviewerNyquist coverage audit: COVERED/UNDER_SAMPLED/UNCOVERED per requirement
M<NNN>-SECURITY.mdmanual np-security-reviewer spawnhuman reviewer, next-milestone plannerOWASP-aligned audit; per-finding Pass / Risk / Defer classification
state/knowledge-index.jsonnp-tools.cjs knowledge-index (auto-built on first knowledge-search)every agent that runs knowledge-searchBM25-light full-text index; ephemeral, gitignored
state/session-snapshot.jsonnp-tools.cjs pause-worknp-tools.cjs resume-workCaptured continuity context (milestone, task, recent commits, open handoffs); ephemeral, gitignored
S<NNN>-ASSESSMENT.md/np:plan-phase (planner)plan-checker, executorRisk, effort, dependencies, blockers per slice
S<NNN>-RESEARCH.md/np:research-phase (per slice, optional)planner, executorSlice-scoped research notes
S<NNN>-UAT.md/np:plan-phase (planner)plan-checker, verifierAcceptance criteria, happy path, edge cases
S<NNN>-SUMMARY.mdexecutor (last task)verifierPer-wave outcome: changes, verification, follow-ups
T<NNNN>-SUMMARY.mdexecutor (after commit)verifier, human reviewerPer-task outcome: files changed, tests run, follow-ups
S<NNN>/TODO.mdlib/todo.cjs::renderTodoMd (triggered by setTaskStatus + plan-milestone scaffold-all-tasks)human reader, executor resume, verifierCheckbox rollup of all task statuses for the slice. Derived from task frontmatter — never authoritative.
M<NNN>/handoffs/<ts>__<from>-to-<to>__<slug>__<id>.mdlib/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 agentCross-milestone / project-global handoff

Parser contract

  • lib/layout.cjs is the authoritative path module. All milestone/slice/task paths are computed via milestoneDir(n), sliceDir(m, s), taskDir(m, s, t), and related helpers.
  • lib/roadmap.cjs.parseRoadmap reads roadmap.yamlmilestones[].slices[].tasks[] (schema_version 2). Falls back to the legacy milestones[].phases[] shape for projects not yet migrated.
  • lib/tasks.cjs.loadTaskGraph(sliceDir) reads sliceDir/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.writeVerificationMd writes the milestone-level VERIFICATION.
  • lib/todo.cjs.renderTodoMd(sliceFullId, cwd) regenerates S<NNN>/TODO.md atomically. Invoked by setTaskStatus (so commit-task / skip / park / unpark all keep it live) and by plan-milestone scaffold-all-tasks for the initial render.
  • lib/handoff.cjs exposes writeHandoff, 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.cjs exposes createSliceWorktree, removeSliceWorktree, listSliceWorktrees, ffMergeSliceWorktree, hasSliceWorktree, worktreeIsolationEnabled. All git shell-outs route through lib/git.cjs::runGit so the lib/*.cjs → no child_process invariant (ADR-0001 / surface-audit.test.cjs) stays intact. .nubos-pilot/worktrees/ must be in .gitignore; createSliceWorktree checks this via git check-ignore and fails loud if not.
  • lib/dashboard.cjs exposes collectSnapshot (read-only aggregation of milestones, slices, handoffs, worktrees, and git branch) and renderSnapshot (ANSI text layout). The CLI dashboard wraps both. It is a one-shot read-only render with --json and --no-color flags only; there is no --watch and 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.