nubos-pilot 0.2.2 → 0.4.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.
@@ -1,4 +1,4 @@
1
- <!-- Placeholders: core_value, created_date, first_milestone_name, first_phase_name, primary_constraints, project_name -->
1
+ <!-- Placeholders: core_value, created_date, domain_text, first_milestone_name, first_phase_name, non_goals_text, primary_constraints, project_description, project_name, strategic_decisions_text, success_criteria_text, target_users_text -->
2
2
  # {{project_name}}
3
3
 
4
4
  ## Project
@@ -7,9 +7,15 @@
7
7
 
8
8
  ## What This Is
9
9
 
10
- {{project_name}} is an early-stage project. Update this section after the first
11
- phase ships with a concrete 2-3 sentence description of what the product does
12
- and who it serves. Use the user's language and framing.
10
+ {{project_description}}
11
+
12
+ ## Domain
13
+
14
+ {{domain_text}}
15
+
16
+ ## Target Users
17
+
18
+ {{target_users_text}}
13
19
 
14
20
  ## Core Value
15
21
 
@@ -18,6 +24,18 @@ and who it serves. Use the user's language and framing.
18
24
  If everything else fails, this one sentence must remain true. It drives
19
25
  prioritization when tradeoffs arise.
20
26
 
27
+ ## Non-Goals
28
+
29
+ {{non_goals_text}}
30
+
31
+ ## Success Criteria
32
+
33
+ {{success_criteria_text}}
34
+
35
+ ## Strategic Decisions
36
+
37
+ {{strategic_decisions_text}}
38
+
21
39
  ## Constraints
22
40
 
23
41
  {{primary_constraints}}
@@ -55,6 +73,10 @@ PROJECT.md evolves throughout the project lifecycle.
55
73
  2. Core Value check — still the right priority?
56
74
  3. Update Current Focus with next milestone/phase
57
75
 
76
+ **When scope or positioning shifts:**
77
+ - Run `np:discuss-project` to refresh Domain, Target Users, Non-Goals,
78
+ Success Criteria, and Strategic Decisions without starting over.
79
+
58
80
  ---
59
81
  *Created: {{created_date}}*
60
82
  *Last updated: {{created_date}} after np:new-project*
@@ -0,0 +1,177 @@
1
+ ---
2
+ command: np:discuss-project
3
+ description: Project-level discovery — adaptive interview that fills (bootstrap) or refreshes (refresh) PROJECT.md sections (Domain, Target Users, Non-Goals, Success Criteria, Strategic Decisions) and proposes REQ candidates.
4
+ ---
5
+
6
+ # np:discuss-project
7
+
8
+ Deep, adaptive interview on project identity. Called automatically from
9
+ `np:new-project` (bootstrap mode — obligatory before roadmap/plan work),
10
+ and on demand later (refresh mode) when positioning or scope shifts.
11
+
12
+ The interview is informed by a codebase scan (so when the project already
13
+ contains code, the discussion builds on what exists rather than asking in
14
+ a vacuum).
15
+
16
+ ## Philosophy
17
+
18
+ <philosophy>
19
+ Five boilerplate questions do not a project understand. PROJECT.md is the
20
+ one artifact every downstream agent reads before asking what to build, and
21
+ its quality caps the quality of every plan that follows. This workflow
22
+ treats the project discussion as a first-class moment — adaptive, grounded
23
+ in the scanned workspace, and ends with a filled PROJECT.md plus a
24
+ user-reviewable list of proposed requirements.
25
+ </philosophy>
26
+
27
+ ## Scope Guardrail
28
+
29
+ <scope_guardrail>
30
+ Writes only:
31
+ - `.nubos-pilot/PROJECT.md` (section bodies only — structure preserved)
32
+ - `.nubos-pilot/REQUIREMENTS.md` (append-only "Proposed" block)
33
+
34
+ Never:
35
+ - rewrites application source
36
+ - touches `.nubos-pilot/codebase/` (that is `np:scan-codebase`'s job)
37
+ - writes requirements into the Active list (user promotes manually)
38
+ </scope_guardrail>
39
+
40
+ ## Downstream Awareness
41
+
42
+ <downstream_awareness>
43
+ - `np:discuss-phase` reads PROJECT.md's Constraints and Domain.
44
+ - `np:planner` reads Non-Goals to avoid scope creep.
45
+ - `np:researcher` reads Strategic Decisions before proposing libraries.
46
+ - REQ-IDs appended by this workflow are consumed by `np:plan-phase` after
47
+ the user promotes them.
48
+ </downstream_awareness>
49
+
50
+ ## Single-Call Init
51
+
52
+ ```bash
53
+ INIT=$(node np-tools.cjs init discuss-project ${BOOTSTRAP:+--bootstrap})
54
+ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
55
+ ```
56
+
57
+ Parse: `mode`, `sub_mode` (`bootstrap` or `refresh`), `project_md_exists`,
58
+ `scan_context`, `questions[]`, `required_fields[]`.
59
+
60
+ ## Process
61
+
62
+ ### Step 1: Ground the user in the scan
63
+
64
+ Show the scan context before questions:
65
+
66
+ ```
67
+ Before we discuss — here is what I found in the workspace:
68
+
69
+ - Files: <scan_context.file_count>
70
+ - Languages: <top 3 from language_distribution>
71
+ - Manifests: <manifest_paths>
72
+ - README head:
73
+ <first 10 lines or "none">
74
+ - Git: <commits[0..2] subjects or "no git repo">
75
+
76
+ Does this match what you expect, or am I missing something?
77
+ ```
78
+
79
+ Let the user correct (e.g. "the README is stale, ignore it"). Record
80
+ corrections — they shape follow-up questions.
81
+
82
+ ### Step 2: Adaptive interview across the six required fields
83
+
84
+ The six required fields come from `required_fields[]`:
85
+
86
+ 1. `project_description` — What This Is (2–3 sentences)
87
+ 2. `domain_text` — Domain / lore / background
88
+ 3. `target_users_text` — Target users
89
+ 4. `non_goals_text` — Explicit Non-Goals
90
+ 5. `success_criteria_text` — Observable success criteria
91
+ 6. `strategic_decisions_text` — Strategic tech/business decisions
92
+
93
+ For each field: ask the seed question from `questions[]`, then follow up
94
+ with 1–3 deepening questions based on the answer. Use `np-tools.cjs
95
+ askuser` for every prompt (SC-5 enforcement — never bypass the gateway).
96
+
97
+ Tailor follow-ups to the scan:
98
+
99
+ - If the workspace has code, ask "I see `src/auth/` and `services/api/` —
100
+ does the Non-Goals list carve out what these will not do?"
101
+ - If no code, ask "For Strategic Decisions, what language/runtime are you
102
+ committing to?"
103
+
104
+ When the user's answer references an existing doc (e.g. "see README
105
+ section X"), fetch it and ground your summary in that.
106
+
107
+ ### Step 3: Propose requirements
108
+
109
+ Based on the Success Criteria + Domain + Non-Goals, propose 3–7 candidate
110
+ REQ entries. Present them for user confirmation:
111
+
112
+ ```
113
+ I see these requirements emerging from your answers. Want me to add them to
114
+ REQUIREMENTS.md under "Proposed"?
115
+
116
+ REQ-02 — must operate offline (no network calls)
117
+ REQ-03 — persists all state as plain Markdown files
118
+ REQ-04 — supports Node 22+ and Python 3.12+
119
+
120
+ (confirm all / pick subset / none)
121
+ ```
122
+
123
+ Write the confirmed list to a JSON file:
124
+
125
+ ```bash
126
+ REQ_FILE=$(mktemp -t np-proposed-reqs-XXXXXX.json)
127
+ # [{"id":"REQ-02","text":"..."}, ...]
128
+ ```
129
+
130
+ ### Step 4: Apply answers
131
+
132
+ ```bash
133
+ ANSWERS=$(mktemp -t np-discuss-project-answers.XXXXXX.json)
134
+ # Write the six answer fields as JSON
135
+
136
+ node np-tools.cjs init discuss-project --apply "$ANSWERS" \
137
+ ${BOOTSTRAP:+--bootstrap} \
138
+ ${REQ_FILE:+--proposed-requirements "$REQ_FILE"}
139
+ ```
140
+
141
+ The subcommand replaces PROJECT.md section bodies (structure preserved)
142
+ and appends a "Proposed" block to REQUIREMENTS.md. Both writes are atomic.
143
+
144
+ ### Step 5: Commit respecting config.commit_docs
145
+
146
+ ```bash
147
+ COMMIT_DOCS=$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null || echo "true")
148
+ if [[ "$COMMIT_DOCS" == "true" ]]; then
149
+ git add .nubos-pilot/PROJECT.md .nubos-pilot/REQUIREMENTS.md 2>/dev/null || true
150
+ git commit -m "docs: np:discuss-project ${BOOTSTRAP:+bootstrap}${BOOTSTRAP:-refresh}" 2>/dev/null || true
151
+ fi
152
+ ```
153
+
154
+ ## Output
155
+
156
+ ```
157
+ np:discuss-project complete (<sub_mode>).
158
+
159
+ Updated:
160
+ .nubos-pilot/PROJECT.md
161
+ .nubos-pilot/REQUIREMENTS.md (if requirements were proposed)
162
+
163
+ Next:
164
+ - Promote proposed REQs to Active in REQUIREMENTS.md
165
+ - Run `np:scan-codebase` if you have not yet (recommended)
166
+ - Run `np:discuss-phase 1` when ready to scope the first phase
167
+ ```
168
+
169
+ ## Errors
170
+
171
+ | Code | Trigger | User action |
172
+ |------|---------|-------------|
173
+ | `discuss-project-not-initialized` | `.nubos-pilot/` missing | Run `np:new-project` |
174
+ | `discuss-project-missing-field` | answer JSON lacks one of six fields | Complete the interview |
175
+ | `discuss-project-cannot-refresh` | refresh mode but PROJECT.md missing | Run bootstrap mode first |
176
+ | `discuss-project-bootstrap-requires-project` | bootstrap but no scaffold | Run `np:new-project` |
177
+ | `discuss-project-answers-parse-error` | answers file not valid JSON | Retry |
@@ -1,26 +1,34 @@
1
1
  ---
2
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.
3
+ description: Greenfield project scaffold — scans existing workspace, runs bootstrap interview (5 questions), scaffolds the baseline artifacts, then chains into obligatory project discovery and initial codebase scan.
4
4
  ---
5
5
 
6
6
  # np:new-project
7
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.
8
+ Initialize a new nubos-pilot project in three phases:
9
+
10
+ 1. **Phase 0 Workspace Scan** (context capture)
11
+ 2. **Phase 1 Bootstrap Interview** (5 structural questions → scaffold)
12
+ 3. **Phase 2 Project Discovery** (obligatory, chains into `np:discuss-project --bootstrap`)
13
+
14
+ Optionally runs an initial codebase scan at the end when the workspace
15
+ contains existing source (`np:scan-codebase`). Everything lands under
16
+ `.nubos-pilot/`; no source files are ever modified.
13
17
 
14
18
  ## Philosophy
15
19
 
16
20
  <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.
21
+ The most leveraged moment in any project is the first interview, and the
22
+ first interview must be grounded in what actually exists. A bare interview
23
+ produces generic PROJECT.md stubs; a grounded one captures the specific
24
+ project under specific constraints. This workflow therefore scans *first*,
25
+ uses the scan to enrich the interview, and then makes the deeper
26
+ discovery step obligatory no more jumping into phases with a skeleton
27
+ PROJECT.md.
28
+
29
+ Runtime-agnostic throughout: scanner is deterministic Node code; interview
30
+ uses the askuser gateway; discovery is delegated to `np:discuss-project`
31
+ which dispatches the documenter agent through whatever host is active.
24
32
  </philosophy>
25
33
 
26
34
  ## Scope Guardrail
@@ -29,86 +37,92 @@ well-formed scaffold, not to pretend to understand the project.
29
37
  This workflow ONLY touches `.nubos-pilot/` and creates its first phase
30
38
  directory. It NEVER:
31
39
 
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
+ - modifies files outside `.nubos-pilot/`
41
+ - writes when `.nubos-pilot/PROJECT.md` already exists (refuses with
42
+ `project-already-initialized`)
43
+ - mutates application source code
44
+ - spawns long-running tasks without user consent (batched codebase scan
45
+ offers pause between batches)
40
46
  </scope_guardrail>
41
47
 
42
48
  ## Downstream Awareness
43
49
 
44
50
  <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`.
51
+ This workflow writes:
52
+ - `.nubos-pilot/PROJECT.md` (section bodies later filled by discovery)
53
+ - `.nubos-pilot/REQUIREMENTS.md` (REQ-01 placeholder)
54
+ - `.nubos-pilot/roadmap.yaml` + `ROADMAP.md`
55
+ - `.nubos-pilot/STATE.md`
56
+ - `.nubos-pilot/phases/01-<slug>/01-CONTEXT.md`
57
+ - (optional) `.nubos-pilot/codebase/` via chained `np:scan-codebase`
58
+
59
+ `np:discuss-project` (Phase 2) chains automatically not skippable.
60
+ `np:scan-codebase` chains when the workspace contains >= 1 source file.
56
61
  </downstream_awareness>
57
62
 
58
- ## Single-Call Init
63
+ ## Phase 0: Workspace Scan
59
64
 
60
- All context — the interview question set plus metadata — comes from a
61
- single `np-tools.cjs init new-project` call.
65
+ Probe the workspace for context before asking anything:
62
66
 
63
67
  ```bash
64
- INIT=$(node np-tools.cjs init new-project)
65
- if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
68
+ SCAN=$(node -e '
69
+ const { scan } = require("./lib/workspace-scan.cjs");
70
+ const r = scan({ cwd: process.cwd(), batchSize: 1000 });
71
+ process.stdout.write(JSON.stringify({
72
+ file_count: r.stats.file_count,
73
+ langs: r.language_distribution,
74
+ manifests: Object.keys(r.manifests),
75
+ docs: Object.keys(r.docs),
76
+ readme_head: r.docs["README.md"]
77
+ ? r.docs["README.md"].content.split("\\n").slice(0, 20).join("\\n")
78
+ : null,
79
+ git: r.git,
80
+ }));
81
+ ')
66
82
  ```
67
83
 
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
- }
84
+ Show findings to the user and offer pre-filled suggestions:
85
+
81
86
  ```
87
+ Workspace inventory:
88
+ - Files: <file_count>
89
+ - Top languages: <top 3>
90
+ - Manifests found: <list>
91
+ - README detected: <yes/no>
92
+ - Git repo: <yes/no, N commits>
93
+
94
+ I can suggest defaults from this scan. Review and adjust.
95
+ ```
96
+
97
+ Use the scan to propose:
98
+ - `project_name` — from directory basename; edit if off
99
+ - `primary_constraints` — derived from manifests (e.g. "Node 22" from
100
+ `package.json.engines.node`)
101
+ - `core_value` — best-effort extraction from README first paragraph
82
102
 
83
- ## Interview
103
+ ## Phase 1: Bootstrap Interview
84
104
 
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.
105
+ The 5 structural questions. All prompts go through the askuser gateway.
106
+
107
+ ```bash
108
+ INIT=$(node np-tools.cjs init new-project)
109
+ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
110
+ ```
88
111
 
89
112
  ```bash
90
113
  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)?"}')
114
+ ANS_CORE_VALUE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Core value one sentence that must stay true if everything else fails?"}')
92
115
  ANS_CONSTRAINTS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Primary constraints (comma-separated)?"}')
93
116
  ANS_FIRST_MS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First milestone name?"}')
94
117
  ANS_FIRST_PHASE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First phase name?"}')
95
118
  ```
96
119
 
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.
120
+ When Phase 0 produced a suggestion, include it as the prompt default in
121
+ the askuser call (e.g. `"prompt":"Project name? (suggested: T-AI)"`).
102
122
 
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>
123
+ ## Apply scaffold
108
124
 
109
- ## Apply
110
-
111
- Write the five answers to a tmp JSON file and feed it to the subcommand.
125
+ Write the five answers to a tmp JSON file and call the subcommand:
112
126
 
113
127
  ```bash
114
128
  ANSWERS=$(mktemp -t np-new-project-answers.XXXXXX)
@@ -116,30 +130,28 @@ trap 'rm -f "$ANSWERS"' EXIT
116
130
 
117
131
  node -e '
118
132
  const fs = require("fs");
119
- const payload = {
133
+ fs.writeFileSync(process.env.ANSWERS, JSON.stringify({
120
134
  project_name: process.env.ANS_PROJECT_NAME,
121
135
  core_value: process.env.ANS_CORE_VALUE,
122
136
  primary_constraints: process.env.ANS_CONSTRAINTS,
123
137
  first_milestone_name: process.env.ANS_FIRST_MS,
124
138
  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"
139
+ }));
140
+ ' ANSWERS="$ANSWERS" \
141
+ ANS_PROJECT_NAME="$ANS_PROJECT_NAME" ANS_CORE_VALUE="$ANS_CORE_VALUE" \
142
+ ANS_CONSTRAINTS="$ANS_CONSTRAINTS" ANS_FIRST_MS="$ANS_FIRST_MS" \
143
+ ANS_FIRST_PHASE="$ANS_FIRST_PHASE"
128
144
 
129
145
  node np-tools.cjs init new-project --apply "$ANSWERS"
130
146
  ```
131
147
 
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.
148
+ The six discovery-related PROJECT.md fields (`project_description`,
149
+ `domain_text`, `target_users_text`, `non_goals_text`,
150
+ `success_criteria_text`, `strategic_decisions_text`) are written as
151
+ `_TBD — filled by /np:discuss-project._` placeholders. Phase 2 fills them.
136
152
 
137
153
  ## Re-Init Guard
138
154
 
139
- When `PROJECT.md` already exists, the subcommand throws
140
- `project-already-initialized`. The workflow catches it and offers a
141
- decision:
142
-
143
155
  ```bash
144
156
  set +e
145
157
  node np-tools.cjs init new-project --apply "$ANSWERS"
@@ -167,38 +179,75 @@ if [ "$APPLY_STATUS" -ne 0 ]; then
167
179
  fi
168
180
  ```
169
181
 
170
- Default on ambiguity: abort. This workflow never deletes `.nubos-pilot/`
171
- without an explicit `select` answer containing `Delete`.
182
+ ## Phase 2: Project Discovery (obligatory)
172
183
 
173
- ## Optional Commit
184
+ Do not let the user skip this. Chain into `np:discuss-project --bootstrap`:
185
+
186
+ ```bash
187
+ BOOTSTRAP=1 /np:discuss-project
188
+ ```
189
+
190
+ The user answers the six adaptive discovery questions (Target Users,
191
+ Domain, What-This-Is, Non-Goals, Success Criteria, Strategic Decisions),
192
+ reviews proposed requirements, and ends with a fully populated PROJECT.md.
193
+
194
+ If the user tries to exit mid-discovery, warn:
195
+
196
+ ```
197
+ PROJECT.md still has _TBD placeholders. Downstream phases will treat
198
+ the project as under-specified. Continue discovery? (yes / no, I will
199
+ finish later)
200
+ ```
201
+
202
+ Record the skip in STATE.md so the next `np:next` reminds the user.
174
203
 
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.
204
+ ## Phase 3 (conditional): Initial Codebase Scan
205
+
206
+ If Phase 0 reported `file_count > 0` with code files (not only manifests
207
+ and docs), offer to run the initial scan now:
208
+
209
+ ```bash
210
+ RUN_SCAN=$(node np-tools.cjs askuser --json '{
211
+ "type": "confirm",
212
+ "prompt": "Run initial codebase scan now (np:scan-codebase)?",
213
+ "default": true
214
+ }')
215
+
216
+ if [[ "$RUN_SCAN" == "true" ]]; then
217
+ /np:scan-codebase
218
+ fi
219
+ ```
220
+
221
+ Empty workspaces skip this cleanly.
222
+
223
+ ## Optional Commit
177
224
 
178
225
  ```bash
179
226
  if [ "$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
180
227
  git add .nubos-pilot/
181
- git commit -m "chore: np:new-project scaffold"
228
+ git commit -m "chore: np:new-project scaffold + discovery"
182
229
  fi
183
230
  ```
184
231
 
185
232
  ## Output
186
233
 
187
- On success, print a summary block and point the user at `np:next`:
188
-
189
234
  ```
190
235
  np:new-project complete.
191
236
 
192
237
  Created:
193
- .nubos-pilot/PROJECT.md
238
+ .nubos-pilot/PROJECT.md (populated by discovery)
194
239
  .nubos-pilot/REQUIREMENTS.md
195
240
  .nubos-pilot/roadmap.yaml
196
241
  .nubos-pilot/ROADMAP.md
197
242
  .nubos-pilot/STATE.md
198
243
  .nubos-pilot/phases/01-<slug>/01-CONTEXT.md
244
+ .nubos-pilot/codebase/ (if initial scan ran)
199
245
 
200
- Next: run `np:next` to resume, or edit REQUIREMENTS.md before discussing
201
- the first phase with `np:discuss-phase 1`.
246
+ Milestone: <milestoneId> · Phase 1: <firstPhaseSlug>
247
+
248
+ Next:
249
+ - /np:discuss-phase 1 to scope the first phase
250
+ - /np:update-docs after any code change (agents will do this automatically)
202
251
  ```
203
252
 
204
253
  ## Errors
@@ -208,6 +257,4 @@ the first phase with `np:discuss-phase 1`.
208
257
  | `project-already-initialized` | `PROJECT.md` exists | Abort or re-run with destructive option |
209
258
  | `invalid-slug` | milestone/phase name has no `[a-z0-9]` content | Re-run with a different name |
210
259
  | `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.
260
+ | `discuss-project-bootstrap-requires-project` | Discovery invoked before scaffold | Restart workflow |