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.
- package/agents/np-code-fixer.md +22 -4
- package/agents/np-code-reviewer.md +6 -5
- package/agents/np-codebase-documenter.md +176 -0
- package/agents/np-executor.md +54 -7
- package/agents/np-planner.md +1 -0
- package/agents/np-researcher.md +7 -0
- package/bin/install.js +81 -8
- package/bin/np-tools/discuss-project.cjs +377 -0
- package/bin/np-tools/discuss-project.test.cjs +238 -0
- package/bin/np-tools/doctor.cjs +103 -0
- package/bin/np-tools/doctor.test.cjs +112 -0
- package/bin/np-tools/new-project.cjs +6 -0
- package/bin/np-tools/scan-codebase.cjs +204 -0
- package/bin/np-tools/scan-codebase.test.cjs +165 -0
- package/bin/np-tools/update-docs.cjs +216 -0
- package/bin/np-tools/update-docs.test.cjs +130 -0
- package/docs/adr/0007-codebase-docs-layer.md +273 -0
- package/docs/adr/README.md +2 -0
- package/lib/codebase-docs.cjs +450 -0
- package/lib/codebase-docs.test.cjs +266 -0
- package/lib/codebase-manifest.cjs +171 -0
- package/lib/codebase-manifest.test.cjs +156 -0
- package/lib/git.cjs +38 -0
- package/lib/install/runtime-assets.cjs +145 -0
- package/lib/install/runtimes-registry.cjs +4 -0
- package/lib/workspace-scan.cjs +290 -0
- package/lib/workspace-scan.test.cjs +212 -0
- package/np-tools.cjs +3 -0
- package/package.json +1 -1
- package/templates/PROJECT.md +26 -4
- package/workflows/discuss-project.md +177 -0
- package/workflows/new-project.md +141 -94
- package/workflows/scan-codebase.md +155 -0
- package/workflows/update-docs.md +132 -0
package/templates/PROJECT.md
CHANGED
|
@@ -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
|
-
{{
|
|
11
|
-
|
|
12
|
-
|
|
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 |
|
package/workflows/new-project.md
CHANGED
|
@@ -1,26 +1,34 @@
|
|
|
1
1
|
---
|
|
2
2
|
command: np:new-project
|
|
3
|
-
description: Greenfield project scaffold — runs
|
|
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
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
specific
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
-
|
|
33
|
-
- writes when `.nubos-pilot/PROJECT.md` already exists (
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
- `np:
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
##
|
|
63
|
+
## Phase 0: Workspace Scan
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
single `np-tools.cjs init new-project` call.
|
|
65
|
+
Probe the workspace for context before asking anything:
|
|
62
66
|
|
|
63
67
|
```bash
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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
|
|
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
|
-
|
|
98
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
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
|
-
|
|
171
|
-
without an explicit `select` answer containing `Delete`.
|
|
182
|
+
## Phase 2: Project Discovery (obligatory)
|
|
172
183
|
|
|
173
|
-
|
|
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
|
-
|
|
176
|
-
|
|
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
|
-
|
|
201
|
-
|
|
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 |
|