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,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:execute-phase
|
|
3
|
+
description: Wave-based phase execution. Spawns executor (sonnet) per task with atomic-commit-per-unit enforced via np-tools.cjs commit-task helper (D-03/D-25).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /np:execute-phase
|
|
7
|
+
|
|
8
|
+
<objective>
|
|
9
|
+
Run every wave of every plan in a given phase: for each task in wave-order,
|
|
10
|
+
start a checkpoint, spawn agents/np-executor.md (sonnet), verify, and invoke
|
|
11
|
+
`node np-tools.cjs commit-task <task-id>` for the atomic commit. All git
|
|
12
|
+
operations route through lib/git.cjs — agents NEVER call `git` directly
|
|
13
|
+
(ADR-0004, CLAUDE.md §Git operations).
|
|
14
|
+
</objective>
|
|
15
|
+
|
|
16
|
+
## Initialize
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
PHASE="$1"
|
|
20
|
+
INIT=$(node np-tools.cjs init execute-phase "$PHASE")
|
|
21
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
22
|
+
AGENT_SKILLS_EXECUTOR=$(node np-tools.cjs agent-skills executor 2>/dev/null)
|
|
23
|
+
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Parse JSON for: `phase`, `padded`, `phase_dir`, `plans[]` (each with
|
|
27
|
+
`plan_path`, `waves`, `task_count`), `executor_tier`, `agent_skills`.
|
|
28
|
+
|
|
29
|
+
`PLAN_ID` is iterated from `plans[]` (e.g. `06-01`) and `TASK_ID` is iterated
|
|
30
|
+
from each plan's `waves[]` entries. Both are used by the metrics-record calls
|
|
31
|
+
in the per-task loop below.
|
|
32
|
+
|
|
33
|
+
## Pre-Flight — orphan-checkpoint guard
|
|
34
|
+
|
|
35
|
+
Detect stale checkpoints from a prior run before starting new work:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
RESUME=$(node np-tools.cjs init resume-work)
|
|
39
|
+
RESUME_STATUS=$(echo "$RESUME" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).status))")
|
|
40
|
+
if [ "$RESUME_STATUS" = "orphan" ]; then
|
|
41
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
42
|
+
"type": "select",
|
|
43
|
+
"header": "Verwaiste Checkpoints gefunden",
|
|
44
|
+
"question": "Vor dem Phase-Start wurden Checkpoint-Dateien ohne passenden STATE.current_task gefunden. Was tun?",
|
|
45
|
+
"options": [
|
|
46
|
+
{"label": "Clean working tree (reset-slice)", "description": "Verwirft die in-flight Task und löscht ihren Checkpoint."},
|
|
47
|
+
{"label": "Resume the orphan task", "description": "Setzt STATE.current_task auf den Checkpoint-Eintrag und spawnt den Executor."},
|
|
48
|
+
{"label": "Abort", "description": "Exit, User entscheidet manuell."}
|
|
49
|
+
]
|
|
50
|
+
}')
|
|
51
|
+
case "$CHOICE" in
|
|
52
|
+
"Abort") exit 0 ;;
|
|
53
|
+
esac
|
|
54
|
+
fi
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Execution — per wave, per task
|
|
58
|
+
|
|
59
|
+
For each plan in `plans[]`, for each wave in `plan.waves`, for each task-id
|
|
60
|
+
in the wave:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
TASK_ID="06-01-T01" # example — iterated from waves[]
|
|
64
|
+
PLAN_ID="06-01" # example — iterated from plans[]
|
|
65
|
+
|
|
66
|
+
# Start crash-safety checkpoint.
|
|
67
|
+
node np-tools.cjs checkpoint start "$TASK_ID" --phase "$PHASE" --plan "$PLAN_ID" --wave 1
|
|
68
|
+
|
|
69
|
+
# Fetch the executor-spawn payload (files_modified + task_name + tier).
|
|
70
|
+
TASK_JSON=$(node np-tools.cjs init execute-phase execute-task "$PHASE" "$TASK_ID")
|
|
71
|
+
if [[ "$TASK_JSON" == @file:* ]]; then TASK_JSON=$(cat "${TASK_JSON#@file:}"); fi
|
|
72
|
+
|
|
73
|
+
# --- Resolve executor model + start metrics clock (D-06) ---
|
|
74
|
+
EXECUTOR_START=$(node np-tools.cjs metrics start-timestamp)
|
|
75
|
+
EXECUTOR_MODEL=$(node np-tools.cjs resolve-model executor --profile balanced)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Spawn `agents/np-executor.md` (tier: sonnet, from `executor_tier`, model
|
|
79
|
+
resolved as `$EXECUTOR_MODEL`) with a `<files_to_read>` block containing: the
|
|
80
|
+
plan file, the task file, prior phase SUMMARY.md files. The host runtime
|
|
81
|
+
consumes `$EXECUTOR_MODEL` via its spawn adapter (empty string → omit the
|
|
82
|
+
`model:` parameter per Phase 8 D-22 inherit-pattern). The executor edits
|
|
83
|
+
EXACTLY the paths in `files_modified` (D-04 — no scope expansion), runs any
|
|
84
|
+
`<verify>` commands, then invokes the commit helper:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
node np-tools.cjs checkpoint transition "$TASK_ID" verifying
|
|
88
|
+
node np-tools.cjs checkpoint transition "$TASK_ID" pre-commit
|
|
89
|
+
|
|
90
|
+
# Atomic commit — LOUD FAIL propagates if every files_modified entry is
|
|
91
|
+
# gitignored (D-25). The helper prints a JSON payload `{ok, task_id, sha, files}`.
|
|
92
|
+
node np-tools.cjs commit-task "$TASK_ID"
|
|
93
|
+
COMMIT_STATUS=$?
|
|
94
|
+
|
|
95
|
+
# --- Close metrics record for this executor task (D-06/D-08) ---
|
|
96
|
+
EXECUTOR_END=$(node np-tools.cjs metrics end-timestamp)
|
|
97
|
+
EXECUTOR_STATUS=ok
|
|
98
|
+
[ "$COMMIT_STATUS" -ne 0 ] && EXECUTOR_STATUS=error
|
|
99
|
+
node np-tools.cjs metrics record \
|
|
100
|
+
--agent np-executor --tier sonnet --resolved-model "$EXECUTOR_MODEL" \
|
|
101
|
+
--phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
|
|
102
|
+
--started "$EXECUTOR_START" --ended "$EXECUTOR_END" \
|
|
103
|
+
--tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
|
|
104
|
+
--retry-count "${RETRY_COUNT:-0}" --status "$EXECUTOR_STATUS" --runtime "$RUNTIME"
|
|
105
|
+
|
|
106
|
+
if [ "$COMMIT_STATUS" -ne 0 ]; then
|
|
107
|
+
echo "[np:execute-phase] commit-task failed for $TASK_ID — aborting wave." >&2
|
|
108
|
+
exit "$COMMIT_STATUS"
|
|
109
|
+
fi
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
After a full phase completes: point the operator at `/np:verify-work
|
|
113
|
+
$PHASE`.
|
|
114
|
+
|
|
115
|
+
## Scope Guardrail
|
|
116
|
+
|
|
117
|
+
<!-- scope_guardrail -->
|
|
118
|
+
**Do:**
|
|
119
|
+
- Start one checkpoint per task before spawning the executor agent.
|
|
120
|
+
- Spawn `agents/np-executor.md` (sonnet) once per task with only the task's
|
|
121
|
+
`files_modified` in scope.
|
|
122
|
+
- Route every commit through `node np-tools.cjs commit-task` so
|
|
123
|
+
`assertCommittablePaths` (D-25) runs.
|
|
124
|
+
- Hard-stop the wave when `commit-task` returns a non-zero exit (D-23
|
|
125
|
+
propagation — don't mask the failure).
|
|
126
|
+
|
|
127
|
+
**Don't:**
|
|
128
|
+
- Invoke `git commit`, `git add`, or any bare git command from this
|
|
129
|
+
workflow or the spawned agent (CLAUDE.md §Git operations).
|
|
130
|
+
- Bundle two tasks into one commit (ADR-0004 atomicity).
|
|
131
|
+
- Skip the checkpoint start step — it's the crash-safety primitive
|
|
132
|
+
`resume-work` depends on.
|
|
133
|
+
- Pass `--no-verify` or `--force` anywhere in the pipeline.
|
|
134
|
+
<!-- /scope_guardrail -->
|
|
135
|
+
|
|
136
|
+
## Output
|
|
137
|
+
|
|
138
|
+
- One git commit per completed task (`task(<phase>-<plan>-T<NN>): <name>`).
|
|
139
|
+
- Per-task checkpoint lifetime: `start` → (`transition verifying|pre-commit`)+
|
|
140
|
+
→ `deleteCheckpoint` (inside commit-task on success).
|
|
141
|
+
- STATE.md updated via `startTask`'s coordinated lock-cycle (D-08).
|
|
142
|
+
- Verified work surface for `/np:verify-work $PHASE`.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:execute-plan
|
|
3
|
+
description: Execute all tasks in a single plan (wave-ordered, atomic-commit-per-task). Sub-case of /np:execute-phase scoped to one plan.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /np:execute-plan
|
|
7
|
+
|
|
8
|
+
<objective>
|
|
9
|
+
Same semantics as `/np:execute-phase` but scoped to one plan — useful when
|
|
10
|
+
re-running or revising a single plan after its peers have already shipped.
|
|
11
|
+
</objective>
|
|
12
|
+
|
|
13
|
+
## Initialize
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
PLAN_ID="$1" # e.g. 06-01
|
|
17
|
+
INIT=$(node np-tools.cjs init execute-plan "$PLAN_ID")
|
|
18
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
19
|
+
AGENT_SKILLS_EXECUTOR=$(node np-tools.cjs agent-skills executor 2>/dev/null)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Parse: `plan_id`, `phase`, `padded`, `plan_path`, `tasks_dir`, `waves`,
|
|
23
|
+
`task_count`, `executor_tier`, `agent_skills`.
|
|
24
|
+
|
|
25
|
+
## Pre-Flight — orphan-checkpoint guard
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
RESUME=$(node np-tools.cjs init resume-work)
|
|
29
|
+
RESUME_STATUS=$(echo "$RESUME" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).status))")
|
|
30
|
+
if [ "$RESUME_STATUS" = "orphan" ]; then
|
|
31
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
32
|
+
"type": "select",
|
|
33
|
+
"header": "Verwaiste Checkpoints gefunden",
|
|
34
|
+
"question": "Checkpoints ohne passenden STATE.current_task gefunden — weitermachen?",
|
|
35
|
+
"options": [
|
|
36
|
+
{"label": "Clean and proceed", "description": "reset-slice + fresh start."},
|
|
37
|
+
{"label": "Abort", "description": "Exit, User entscheidet manuell."}
|
|
38
|
+
]
|
|
39
|
+
}')
|
|
40
|
+
case "$CHOICE" in
|
|
41
|
+
"Abort") exit 0 ;;
|
|
42
|
+
esac
|
|
43
|
+
fi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Execution — per wave, per task
|
|
47
|
+
|
|
48
|
+
For each wave in `waves`, for each `TASK_ID`:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
TASK_ID="06-01-T01"
|
|
52
|
+
node np-tools.cjs checkpoint start "$TASK_ID" --phase "$phase" --plan "$PLAN_ID" --wave 1
|
|
53
|
+
|
|
54
|
+
TASK_JSON=$(node np-tools.cjs init execute-phase execute-task "$phase" "$TASK_ID")
|
|
55
|
+
if [[ "$TASK_JSON" == @file:* ]]; then TASK_JSON=$(cat "${TASK_JSON#@file:}"); fi
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Spawn `agents/np-executor.md` (sonnet) per task with `files_modified`,
|
|
59
|
+
`<files_to_read>` = [plan_path, task_file, prior SUMMARY.md files].
|
|
60
|
+
Executor performs the work, runs the `<verify>` command, then:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node np-tools.cjs checkpoint transition "$TASK_ID" verifying
|
|
64
|
+
node np-tools.cjs checkpoint transition "$TASK_ID" pre-commit
|
|
65
|
+
node np-tools.cjs commit-task "$TASK_ID"
|
|
66
|
+
COMMIT_STATUS=$?
|
|
67
|
+
if [ "$COMMIT_STATUS" -ne 0 ]; then
|
|
68
|
+
echo "[np:execute-plan] commit-task failed for $TASK_ID" >&2
|
|
69
|
+
exit "$COMMIT_STATUS"
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Scope Guardrail
|
|
74
|
+
|
|
75
|
+
**Do:** one commit per task via `commit-task`; one executor per task.
|
|
76
|
+
**Don't:** bundle tasks, call bare `git`, or span multiple plans.
|
|
77
|
+
|
|
78
|
+
## Output
|
|
79
|
+
|
|
80
|
+
- N commits (N = count of tasks in the plan), each
|
|
81
|
+
`task(<plan_id>-T<NN>): <name>`.
|
|
82
|
+
- Plan ready for `/np:verify-work` (phase-scoped).
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:new-milestone
|
|
3
|
+
description: Append a milestone + first phase to an initialized project. Never rewrites PROJECT.md (D-29).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:new-milestone
|
|
7
|
+
|
|
8
|
+
Append a new milestone and its first phase to an already-initialized
|
|
9
|
+
project. This workflow is the counterpart to `np:new-project`: `new-project`
|
|
10
|
+
creates the root; `new-milestone` grows it.
|
|
11
|
+
|
|
12
|
+
## Philosophy
|
|
13
|
+
|
|
14
|
+
<philosophy>
|
|
15
|
+
A milestone is a scope anchor — the unit that ships together and earns a
|
|
16
|
+
retrospective. Adding a milestone is never a rewrite of prior work: the
|
|
17
|
+
previous milestone's phases, plans, and SUMMARY.md files stay exactly as
|
|
18
|
+
they were. Only `roadmap.yaml` and (optionally) `REQUIREMENTS.md` grow.
|
|
19
|
+
PROJECT.md is sacrosanct — see D-29.
|
|
20
|
+
</philosophy>
|
|
21
|
+
|
|
22
|
+
## Scope Guardrail
|
|
23
|
+
|
|
24
|
+
<scope_guardrail>
|
|
25
|
+
This workflow ONLY touches:
|
|
26
|
+
|
|
27
|
+
- `.nubos-pilot/roadmap.yaml` (append milestone + first phase)
|
|
28
|
+
- `.nubos-pilot/ROADMAP.md` (regenerated via lib/roadmap-render)
|
|
29
|
+
- `.nubos-pilot/STATE.md` (advance milestone + current_phase pointers)
|
|
30
|
+
- `.nubos-pilot/phases/<NN>-<slug>/` (new phase directory +
|
|
31
|
+
`<NN>-CONTEXT.md` placeholder)
|
|
32
|
+
- `.nubos-pilot/REQUIREMENTS.md` (APPEND a new H2 section ONLY when
|
|
33
|
+
`create_req_prefix` is `true`)
|
|
34
|
+
|
|
35
|
+
It NEVER writes `.nubos-pilot/PROJECT.md` — D-29 strict invariant. The
|
|
36
|
+
subcommand has a defensive guard (`_writeFile`) that throws
|
|
37
|
+
`new-milestone-forbidden-write` if any code path ever routes a PROJECT.md
|
|
38
|
+
target to it.
|
|
39
|
+
</scope_guardrail>
|
|
40
|
+
|
|
41
|
+
## Downstream Awareness
|
|
42
|
+
|
|
43
|
+
<downstream_awareness>
|
|
44
|
+
Phase numbers are global across the roadmap — a phase dir at
|
|
45
|
+
`.nubos-pilot/phases/<NN>-<slug>/` is keyed by the integer `NN`. The
|
|
46
|
+
subcommand computes the next global number across all milestones before
|
|
47
|
+
seeding the new milestone; this avoids the per-milestone numbering in
|
|
48
|
+
`lib/roadmap.cjs addPhase` (Phase 05-05) which would collide with phase
|
|
49
|
+
1 of the previous milestone on disk.
|
|
50
|
+
</downstream_awareness>
|
|
51
|
+
|
|
52
|
+
## Guard
|
|
53
|
+
|
|
54
|
+
Refuse early when not in an initialized project.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
if [ ! -f .nubos-pilot/PROJECT.md ]; then
|
|
58
|
+
echo "Error: no .nubos-pilot/PROJECT.md found. Run np:new-project first."
|
|
59
|
+
exit 1
|
|
60
|
+
fi
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The subcommand raises `project-not-initialized` anyway, but the shell
|
|
64
|
+
check gives a cleaner message before the interview starts.
|
|
65
|
+
|
|
66
|
+
## Single-Call Init
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
INIT=$(node np-tools.cjs init new-milestone)
|
|
70
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Payload: four questions — `milestone_name`, `milestone_goal`,
|
|
74
|
+
`first_phase_name`, `create_req_prefix` (confirm).
|
|
75
|
+
|
|
76
|
+
## Interview
|
|
77
|
+
|
|
78
|
+
Four questions through `np-tools.cjs askuser`. No runtime-native
|
|
79
|
+
question tool is permitted anywhere in this file.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
ANS_MS_NAME=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone name (e.g. v2.0)?"}')
|
|
83
|
+
ANS_MS_GOAL=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone goal (one sentence)?"}')
|
|
84
|
+
ANS_FIRST_PHASE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First phase name for this milestone?"}')
|
|
85
|
+
ANS_REQ_PREFIX=$(node np-tools.cjs askuser --json '{"type":"confirm","prompt":"Create a new Requirements section for this milestone?","default":false}')
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
<answer_validation>
|
|
89
|
+
The subcommand slugifies `milestone_name` and `first_phase_name`; empty
|
|
90
|
+
results throw `invalid-slug`. Duplicate milestone ids (after slugify)
|
|
91
|
+
throw `roadmap-duplicate-milestone` and this workflow prints the error
|
|
92
|
+
and exits — the user decides whether to pick a different name.
|
|
93
|
+
</answer_validation>
|
|
94
|
+
|
|
95
|
+
## Apply
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
ANSWERS=$(mktemp -t np-new-milestone-answers.XXXXXX)
|
|
99
|
+
trap 'rm -f "$ANSWERS"' EXIT
|
|
100
|
+
|
|
101
|
+
node -e '
|
|
102
|
+
const fs = require("fs");
|
|
103
|
+
const prefix = process.env.ANS_REQ_PREFIX;
|
|
104
|
+
const payload = {
|
|
105
|
+
milestone_name: process.env.ANS_MS_NAME,
|
|
106
|
+
milestone_goal: process.env.ANS_MS_GOAL,
|
|
107
|
+
first_phase_name: process.env.ANS_FIRST_PHASE,
|
|
108
|
+
create_req_prefix: prefix === "true" || prefix === "yes" || prefix === "y",
|
|
109
|
+
};
|
|
110
|
+
fs.writeFileSync(process.env.ANSWERS, JSON.stringify(payload));
|
|
111
|
+
' ANS_MS_NAME="$ANS_MS_NAME" ANS_MS_GOAL="$ANS_MS_GOAL" ANS_FIRST_PHASE="$ANS_FIRST_PHASE" ANS_REQ_PREFIX="$ANS_REQ_PREFIX" ANSWERS="$ANSWERS"
|
|
112
|
+
|
|
113
|
+
node np-tools.cjs init new-milestone --apply "$ANSWERS"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
On success the subcommand emits:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"mode": "apply",
|
|
121
|
+
"milestoneId": "v2-0",
|
|
122
|
+
"phaseNumber": 11,
|
|
123
|
+
"phaseSlug": "second-phase",
|
|
124
|
+
"created_req_prefix": true
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## D-29 Invariant
|
|
129
|
+
|
|
130
|
+
<!--
|
|
131
|
+
Defense-in-depth: the subcommand already refuses to write PROJECT.md via
|
|
132
|
+
_writeFile(). This comment is a reminder for humans reviewing this
|
|
133
|
+
workflow: NEVER add a step here that reads, appends to, or rewrites
|
|
134
|
+
PROJECT.md. If a future change needs to "also update PROJECT.md", it
|
|
135
|
+
belongs in a separate workflow that the user invokes explicitly.
|
|
136
|
+
-->
|
|
137
|
+
|
|
138
|
+
## Optional Commit
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
if [ "$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
142
|
+
git add .nubos-pilot/
|
|
143
|
+
git commit -m "chore: np:new-milestone add $ANS_MS_NAME"
|
|
144
|
+
fi
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Output
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
np:new-milestone complete.
|
|
151
|
+
|
|
152
|
+
Appended milestone: <milestone_name> (id=<slug>)
|
|
153
|
+
First phase: <NN>-<slug>
|
|
154
|
+
|
|
155
|
+
Next: run `np:next` to see the newly-current phase, or start
|
|
156
|
+
`np:discuss-phase <NN>` to gather context for it.
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Errors
|
|
160
|
+
|
|
161
|
+
| Code | Trigger | User action |
|
|
162
|
+
|------|---------|-------------|
|
|
163
|
+
| `project-not-initialized` | no `PROJECT.md` in `.nubos-pilot/` | Run `np:new-project` first |
|
|
164
|
+
| `roadmap-duplicate-milestone` | milestone id (slugified name) already exists | Pick a different name |
|
|
165
|
+
| `invalid-slug` | milestone/phase name has no `[a-z0-9]` content | Pick a different name |
|
|
166
|
+
| `new-milestone-forbidden-write` | internal safeguard tripped | File a bug — should never surface |
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:new-project
|
|
3
|
+
description: Greenfield project scaffold — runs interactive interview, writes PROJECT.md + REQUIREMENTS.md + roadmap.yaml + first phase dir + ROADMAP.md.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:new-project
|
|
7
|
+
|
|
8
|
+
Initialize a new project through a short interview, then scaffold the five
|
|
9
|
+
baseline artifacts (`PROJECT.md`, `REQUIREMENTS.md`, `roadmap.yaml`,
|
|
10
|
+
`ROADMAP.md`, `STATE.md`) plus the first phase directory with a
|
|
11
|
+
`CONTEXT.md` placeholder. This is the greenfield entry point; all other
|
|
12
|
+
`np:*` workflows assume a project exists.
|
|
13
|
+
|
|
14
|
+
## Philosophy
|
|
15
|
+
|
|
16
|
+
<philosophy>
|
|
17
|
+
The most leveraged moment in any project is the first interview. Deep
|
|
18
|
+
questioning up front means better roadmaps, better plans, and better
|
|
19
|
+
executions. `np:new-project` does not try to be clever — it asks five
|
|
20
|
+
specific questions whose answers hard-constrain every downstream workflow,
|
|
21
|
+
writes the five files, and exits. The user can edit `PROJECT.md` and
|
|
22
|
+
`REQUIREMENTS.md` any time; this workflow's job is to produce a
|
|
23
|
+
well-formed scaffold, not to pretend to understand the project.
|
|
24
|
+
</philosophy>
|
|
25
|
+
|
|
26
|
+
## Scope Guardrail
|
|
27
|
+
|
|
28
|
+
<scope_guardrail>
|
|
29
|
+
This workflow ONLY touches `.nubos-pilot/` and creates its first phase
|
|
30
|
+
directory. It NEVER:
|
|
31
|
+
|
|
32
|
+
- runs outside the current working directory
|
|
33
|
+
- writes when `.nubos-pilot/PROJECT.md` already exists (D-28 Pitfall 8)
|
|
34
|
+
- mutates files in parent directories
|
|
35
|
+
- spawns agents or long-running tasks
|
|
36
|
+
|
|
37
|
+
If `.nubos-pilot/PROJECT.md` already exists, the subcommand throws
|
|
38
|
+
`project-already-initialized` and this workflow offers two paths: abort
|
|
39
|
+
or destructively reset (user must confirm destructively).
|
|
40
|
+
</scope_guardrail>
|
|
41
|
+
|
|
42
|
+
## Downstream Awareness
|
|
43
|
+
|
|
44
|
+
<downstream_awareness>
|
|
45
|
+
The five files this workflow writes are consumed by:
|
|
46
|
+
|
|
47
|
+
- `np:next` (reads `.nubos-pilot/STATE.md` + `.nubos-pilot/roadmap.yaml`)
|
|
48
|
+
- `np:discuss-phase` (reads `PROJECT.md` for constraints, writes
|
|
49
|
+
`phases/01-<slug>/01-CONTEXT.md` which we scaffold as placeholder)
|
|
50
|
+
- `np:plan-phase` (reads `REQUIREMENTS.md` for requirement IDs)
|
|
51
|
+
- `np:progress` (reads `roadmap.yaml` for totals)
|
|
52
|
+
|
|
53
|
+
Downstream workflows expect `REQUIREMENTS.md` to have `REQ-*` IDs matching
|
|
54
|
+
the format `**REQ-NN**`. The template seeds `REQ-01` as a TBD — the user
|
|
55
|
+
is expected to edit it before running `np:plan-phase 1`.
|
|
56
|
+
</downstream_awareness>
|
|
57
|
+
|
|
58
|
+
## Single-Call Init
|
|
59
|
+
|
|
60
|
+
All context — the interview question set plus metadata — comes from a
|
|
61
|
+
single `np-tools.cjs init new-project` call.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
INIT=$(node np-tools.cjs init new-project)
|
|
65
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The payload shape:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"mode": "interview",
|
|
73
|
+
"questions": [
|
|
74
|
+
{ "key": "project_name", "type": "input", "question": "Project name?" },
|
|
75
|
+
{ "key": "core_value", "type": "input", "question": "Core value — one sentence…" },
|
|
76
|
+
{ "key": "primary_constraints", "type": "input", "question": "Primary constraints…" },
|
|
77
|
+
{ "key": "first_milestone_name", "type": "input", "question": "First milestone name…" },
|
|
78
|
+
{ "key": "first_phase_name", "type": "input", "question": "First phase name…" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Interview
|
|
84
|
+
|
|
85
|
+
All five questions go through `np-tools.cjs askuser` (Phase 3 D-03). No
|
|
86
|
+
runtime-native question tool is permitted anywhere in this file — the
|
|
87
|
+
gateway subcommand is the single allowed path.
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
ANS_PROJECT_NAME=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Project name?"}')
|
|
91
|
+
ANS_CORE_VALUE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Core value (1 sentence)?"}')
|
|
92
|
+
ANS_CONSTRAINTS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Primary constraints (comma-separated)?"}')
|
|
93
|
+
ANS_FIRST_MS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First milestone name?"}')
|
|
94
|
+
ANS_FIRST_PHASE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First phase name?"}')
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
<answer_validation>
|
|
98
|
+
The subcommand slugifies `first_milestone_name` and `first_phase_name`
|
|
99
|
+
and throws `invalid-slug` if either produces an empty string after
|
|
100
|
+
stripping non-`[a-z0-9-]` characters. The user sees this error immediately
|
|
101
|
+
and can re-run the workflow with a different answer.
|
|
102
|
+
|
|
103
|
+
`project_name`, `core_value`, and `primary_constraints` are stored verbatim
|
|
104
|
+
inside the rendered templates — the subcommand's `render()` helper treats
|
|
105
|
+
them as plain strings, so shell metacharacters, Markdown syntax, and YAML
|
|
106
|
+
control chars are all inert. Task 2's NP-5 test asserts this.
|
|
107
|
+
</answer_validation>
|
|
108
|
+
|
|
109
|
+
## Apply
|
|
110
|
+
|
|
111
|
+
Write the five answers to a tmp JSON file and feed it to the subcommand.
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
ANSWERS=$(mktemp -t np-new-project-answers.XXXXXX)
|
|
115
|
+
trap 'rm -f "$ANSWERS"' EXIT
|
|
116
|
+
|
|
117
|
+
node -e '
|
|
118
|
+
const fs = require("fs");
|
|
119
|
+
const payload = {
|
|
120
|
+
project_name: process.env.ANS_PROJECT_NAME,
|
|
121
|
+
core_value: process.env.ANS_CORE_VALUE,
|
|
122
|
+
primary_constraints: process.env.ANS_CONSTRAINTS,
|
|
123
|
+
first_milestone_name: process.env.ANS_FIRST_MS,
|
|
124
|
+
first_phase_name: process.env.ANS_FIRST_PHASE,
|
|
125
|
+
};
|
|
126
|
+
fs.writeFileSync(process.env.ANSWERS, JSON.stringify(payload));
|
|
127
|
+
' ANS_PROJECT_NAME="$ANS_PROJECT_NAME" ANS_CORE_VALUE="$ANS_CORE_VALUE" ANS_CONSTRAINTS="$ANS_CONSTRAINTS" ANS_FIRST_MS="$ANS_FIRST_MS" ANS_FIRST_PHASE="$ANS_FIRST_PHASE" ANSWERS="$ANSWERS"
|
|
128
|
+
|
|
129
|
+
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
We pass the answers via env → `node -e` → JSON file to keep shell
|
|
133
|
+
metacharacters inert (no heredoc interpolation). The subcommand emits
|
|
134
|
+
`{mode:"apply", milestoneId, firstPhaseNumber, firstPhaseSlug, created: [...]}`
|
|
135
|
+
on success.
|
|
136
|
+
|
|
137
|
+
## Re-Init Guard
|
|
138
|
+
|
|
139
|
+
When `PROJECT.md` already exists, the subcommand throws
|
|
140
|
+
`project-already-initialized`. The workflow catches it and offers a
|
|
141
|
+
decision:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
set +e
|
|
145
|
+
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
146
|
+
APPLY_STATUS=$?
|
|
147
|
+
set -e
|
|
148
|
+
|
|
149
|
+
if [ "$APPLY_STATUS" -ne 0 ]; then
|
|
150
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
151
|
+
"type": "select",
|
|
152
|
+
"prompt": "Project already initialized. Choose:",
|
|
153
|
+
"options": [
|
|
154
|
+
"Abort (recommended)",
|
|
155
|
+
"Delete existing .nubos-pilot/ and retry (destructive)"
|
|
156
|
+
]
|
|
157
|
+
}')
|
|
158
|
+
case "$CHOICE" in
|
|
159
|
+
*destructive*|*Delete*)
|
|
160
|
+
rm -rf ./.nubos-pilot
|
|
161
|
+
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
162
|
+
;;
|
|
163
|
+
*)
|
|
164
|
+
exit 1
|
|
165
|
+
;;
|
|
166
|
+
esac
|
|
167
|
+
fi
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Default on ambiguity: abort. This workflow never deletes `.nubos-pilot/`
|
|
171
|
+
without an explicit `select` answer containing `Delete`.
|
|
172
|
+
|
|
173
|
+
## Optional Commit
|
|
174
|
+
|
|
175
|
+
When `config.commit_docs` is true, commit the scaffold. Use `execFileSync`
|
|
176
|
+
arg arrays (no shell-string concatenation) — see Phase 3 D-03 docs.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
if [ "$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
180
|
+
git add .nubos-pilot/
|
|
181
|
+
git commit -m "chore: np:new-project scaffold"
|
|
182
|
+
fi
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Output
|
|
186
|
+
|
|
187
|
+
On success, print a summary block and point the user at `np:next`:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
np:new-project complete.
|
|
191
|
+
|
|
192
|
+
Created:
|
|
193
|
+
.nubos-pilot/PROJECT.md
|
|
194
|
+
.nubos-pilot/REQUIREMENTS.md
|
|
195
|
+
.nubos-pilot/roadmap.yaml
|
|
196
|
+
.nubos-pilot/ROADMAP.md
|
|
197
|
+
.nubos-pilot/STATE.md
|
|
198
|
+
.nubos-pilot/phases/01-<slug>/01-CONTEXT.md
|
|
199
|
+
|
|
200
|
+
Next: run `np:next` to resume, or edit REQUIREMENTS.md before discussing
|
|
201
|
+
the first phase with `np:discuss-phase 1`.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Errors
|
|
205
|
+
|
|
206
|
+
| Code | Trigger | User action |
|
|
207
|
+
|------|---------|-------------|
|
|
208
|
+
| `project-already-initialized` | `PROJECT.md` exists | Abort or re-run with destructive option |
|
|
209
|
+
| `invalid-slug` | milestone/phase name has no `[a-z0-9]` content | Re-run with a different name |
|
|
210
|
+
| `answers-missing-field` | empty answer | Re-run and fill all 5 fields |
|
|
211
|
+
|
|
212
|
+
All errors propagate from the subcommand as `NubosPilotError` with a
|
|
213
|
+
stable `code` — workflow consumers can script against them.
|