Skip to content

State & Files

The Project-State tree under .nubos-pilot/ is the only place workflows write end-user data. Every file here either is the source of truth for some unit-type, or is a derived artifact regenerated from one.

Top-level layout

.nubos-pilot/
├── PROJECT.md              # core value, constraints, current focus, decisions log
├── REQUIREMENTS.md         # REQ-NN active / validated / out-of-scope
├── roadmap.yaml            # canonical roadmap source (parsed by yaml@^2.8)
├── ROADMAP.md              # rendered from roadmap.yaml; do not hand-edit
├── STATE.md                # current phase, current task, session metadata
├── config.json             # runtime, model_profile, branching, parallelization, …
├── phases/
│   └── <NN>-<slug>/        # one directory per phase
├── todos/
│   └── pending/            # captured-on-the-fly Todos
├── backlog/                # deferred Backlog items
├── checkpoints/            # per-task crash-safety pointers
├── metrics/                # *.jsonl append-only metrics log
├── threads/                # cross-session thread CRUD
├── archive/v<X.Y>/         # completed-milestone archive (np:cleanup)
├── .last-session           # pointer to last session report
├── .install.lock           # installer single-writer lockfile
└── .tmp/                   # init payloads >16KB are spilled here as @file:<path>

Source of truth vs derived

FileSource of truthDerived
roadmap.yaml
ROADMAP.mdrendered from roadmap.yaml
PROJECT.md
REQUIREMENTS.md
STATE.md
config.json
phases/<NN>/<NN>-<MM>-PLAN.md
phases/<NN>/<NN>-<MM>-PLAN-REVIEW.md✓ (append-only)
phases/<NN>/<NN>-VERIFICATION.md
phases/<NN>/<NN>-DISCUSSION-LOG.md
phases/<NN>/<NN>-CONTEXT.md✓ in adaptive mode; derived from QUESTIONS.json in power mode

np:undo of a phase regenerates derived files; only source-of-truth files need to be edited by hand if you ever need to escape the workflow.

Phase directory

A phase directory is the most structured thing in the state tree. Only two file shapes are parser-mandatory:

  • <NN>-<MM>-PLAN.md — read by lib/plan.cjs.
  • tasks/<task-id>.md — read by lib/tasks.cjs when the directory exists.

Every other file (<NN>-CONTEXT.md, <NN>-RESEARCH.md, <NN>-VERIFICATION.md, …) is workflow-produced and read by explicit path with ENOENT-tolerance — missing means "that step has not run yet". Full table in the Phase Directory Layout reference.

Single-writer guarantee

Every workflow that mutates .nubos-pilot/ acquires a file lock through lib/core.cjs.withFileLock. The implementation:

  • Uses O_EXCL writes to a <file>.lock sidecar — atomic on every supported filesystem.
  • Embeds pid + hostname + acquiredAt in the lock payload for diagnostics.
  • Stale-detects locks older than 30 s from a different host, forcibly recovers.
  • Registers a process.on('exit') cleanup so a crashed process does not leave a stuck lock.

Concurrent workflow runs queue rather than race. There is no daemon to coordinate them — the lockfile is the only coordinator (ADR-0001).

Atomic writes

Every state mutation routes through atomicWriteFileSync(path, content):

write(tmp + .pid.rand.tmp) → renameSync(tmp, path)

A crash mid-write leaves either the old content or the new content — never a half-written file.

Checkpoints

.nubos-pilot/checkpoints/<task-id>.json is the per-task crash-safety pointer. The executor transitions through pending → in-progress → verifying → pre-commit via np-tools.cjs checkpoint transition. On a successful commit-task, the checkpoint is deleted. On a crash, np:resume-work reads the checkpoint to classify the session as resume, orphan, or clean.

Metrics

.nubos-pilot/metrics/*.jsonl is append-only. Every workflow can record events through np-tools.cjs metrics record. np:stats aggregates them; np:session-report summarizes since .last-session.

Gitignore guard

commit-task and commit route through lib/git.cjs.assertCommittablePaths(). The guard hard-fails when all declared paths are gitignored (D-25) and warns when only some are (D-26). This is what stops the executor from silently producing empty commits.