Appearance
ADR-0003: Unit-Type Ontology
- Status: Accepted (revised)
- Date: 2026-04-20
- Supersedes: initial v1 "Max Six Unit-Types" (2026-04-14)
Context and Problem Statement
Planning ontologies tend to grow without upper bound: epics, stories, sub-stories, initiatives, spikes, tickets, tasks, subtasks. Each new type fragments workflows, multiplies templates, and forces the user to internalize yet another naming distinction. For nubos-pilot the question is: how many user-facing planning nouns exist, and what are they?
For the purpose of this ADR, a unit-type is a user-facing, persistence-bearing noun with its own template, its own file path in the project-state tree, and its own lifecycle. An AI prompt variable, an internal helper module, a configuration key, or a subsection inside a file are not unit-types; they are implementation details invisible to the user's mental model.
Decision
nubos-pilot uses a fixed three-level execution ontology plus three lightweight capture types:
Execution ontology (three levels)
Milestone: a top-level project goal. Each milestone lives at
.nubos-pilot/milestones/M<NNN>/and contains its own CONTEXT/ROADMAP/META files plus aslices/subdirectory. Milestones are what the user plans, executes, and verifies as a unit.Slice: an execution wave inside a milestone. Each slice lives at
.nubos-pilot/milestones/M<NNN>/slices/S<NNN>/and contains its own PLAN/ASSESSMENT/UAT files plus atasks/subdirectory. All tasks inside one slice run in parallel; slices run serially. Cross-slice dependencies flow forward only.Task: an atomic unit of work inside a slice. Each task lives at
.nubos-pilot/milestones/M<NNN>/slices/S<NNN>/tasks/T<NNNN>/with its ownT<NNNN>-PLAN.mdandT<NNNN>-SUMMARY.md. A task is the smallest unit that produces exactly one git commit (ADR-0004).
Capture types (three)
Todo: a captured-on-the-fly idea under
.nubos-pilot/todos/pending/. Todos are the lightweight capture path for ideas that surface during execution but don't yet belong to any milestone.Note: a free-form scratch note under
.nubos-pilot/notes/(project-scoped, committed) or~/.nubos-pilot/notes/(global, uncommitted).Thread: a cross-session context store at
.nubos-pilot/threads/<slug>.mdwith a lifecycle frontmatter (OPEN → IN_PROGRESS → RESOLVED).
Naming note on "phase"
The user-facing slash-commands keep the word "phase" as a synonym for "milestone" for continuity: /np:plan-phase 1 plans milestone M001, /np:execute-phase 1 executes it. This is purely a command-name choice; on disk and in IDs the noun is milestone.
Consequences
- Good: execution ontology is exactly three levels (milestone / slice / task). Users internalize it quickly.
- Good: slice = wave semantics collapse two concepts into one: there is no separate "wave" type.
- Good: every task has a globally unique ID
M<NNN>-S<NNN>-T<NNNN>that carries its position in the hierarchy. - Bad: users coming from Jira-like tools must map "epic" / "story" / "sprint" / "initiative" onto Milestone / Slice. Accepted trade-off.
- Neutral: adding a seventh capture type is not forbidden forever; it requires a superseding ADR.
Rejected Alternatives
- Milestone / Phase / Plan / Task (four-level execution). The intermediate "Plan" level added artifacts (
PLAN.mddistinct from the phase) without producing distinct deliverables. Collapsed into "Slice == Plan" and the file is simplyS<NNN>-PLAN.md. - Open-ended type system. Fragments the workflow library; every
np:*either swallows unknown types or errors. Rejected. - Flat "ticket" model. Loses granularity between a 5-minute Todo and a 3-week Milestone. Rejected.
Enforcement
Type boundaries are enforced at the file-path level by lib/layout.cjs (milestone / slice / task path helpers are the only supported constructors). Lifecycle is enforced by lib/tasks.cjs (TASK_STATUS_ENUM) and lib/verify.cjs (milestone status derived from per-SC verdicts).
