nubos-pilot 0.5.0 → 0.5.2
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/bin/install.js +79 -27
- package/package.json +1 -1
- package/workflows/add-tests.md +2 -2
- package/workflows/add-todo.md +8 -8
- package/workflows/discuss-phase.md +16 -16
- package/workflows/discuss-project.md +3 -3
- package/workflows/doctor.md +1 -1
- package/workflows/execute-phase.md +15 -15
- package/workflows/help.md +1 -1
- package/workflows/new-milestone.md +6 -6
- package/workflows/new-project.md +12 -12
- package/workflows/note.md +9 -9
- package/workflows/park.md +1 -1
- package/workflows/pause-work.md +1 -1
- package/workflows/plan-phase.md +20 -20
- package/workflows/research-phase.md +10 -10
- package/workflows/reset-slice.md +1 -1
- package/workflows/resume-work.md +3 -3
- package/workflows/scan-codebase.md +2 -2
- package/workflows/session-report.md +3 -3
- package/workflows/skip.md +1 -1
- package/workflows/state.md +1 -1
- package/workflows/stats.md +5 -5
- package/workflows/thread.md +5 -5
- package/workflows/undo-task.md +1 -1
- package/workflows/undo.md +1 -1
- package/workflows/unpark.md +1 -1
- package/workflows/update-docs.md +2 -2
- package/workflows/validate-phase.md +8 -8
- package/workflows/verify-work.md +5 -5
package/bin/install.js
CHANGED
|
@@ -64,10 +64,25 @@ function _autoAskUser(spec) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
const
|
|
68
|
-
'
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
const LANG_DIRECTIVES = {
|
|
68
|
+
de: 'Sprache: **Deutsch.** Jede nubos-pilot Slash-Command-Ausgabe, jede Frage an den User und jedes Statusupdate in allen `/np:*` Workflows ist auf Deutsch zu schreiben — inklusive Fehlermeldungen und Klärungsfragen. Nur Code, Bash-Kommandos, Tool-Outputs und Commit-Messages bleiben wie sie sind.',
|
|
69
|
+
en: 'Language: **English.** All `/np:*` slash-command output, askuser prompts and status updates respond in English.',
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function _langDirective(responseLanguage) {
|
|
73
|
+
const lang = String(responseLanguage || 'en').toLowerCase();
|
|
74
|
+
if (LANG_DIRECTIVES[lang]) return LANG_DIRECTIVES[lang];
|
|
75
|
+
return 'Language: respond in the ISO-639 language `' + lang + '` for all `/np:*` slash-command output, askuser prompts and status updates.';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function _managedBlockInner(responseLanguage) {
|
|
79
|
+
return (
|
|
80
|
+
'This project uses [nubos-pilot](https://github.com/nubos/nubos-pilot)'
|
|
81
|
+
+ ' for planning and execution.\n\n'
|
|
82
|
+
+ _langDirective(responseLanguage)
|
|
83
|
+
+ '\n\nRun `npx nubos-pilot doctor` to check install integrity.'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
71
86
|
|
|
72
87
|
const VALID_AGENTS = registryMod.listRuntimeIds();
|
|
73
88
|
const VALID_SCOPES = ['local', 'global'];
|
|
@@ -139,6 +154,25 @@ function _opencodeManifestPrefix(scope) {
|
|
|
139
154
|
: OPENCODE_MANIFEST_PREFIX;
|
|
140
155
|
}
|
|
141
156
|
|
|
157
|
+
function _writeToolsShim(projectRoot) {
|
|
158
|
+
const shimDir = path.join(projectRoot, STATE_SUBPATH, 'bin');
|
|
159
|
+
const shimPath = path.join(shimDir, 'np-tools.cjs');
|
|
160
|
+
const target = path.resolve(__dirname, '..', 'np-tools.cjs');
|
|
161
|
+
const body = '#!/usr/bin/env node\n'
|
|
162
|
+
+ "'use strict';\n"
|
|
163
|
+
+ 'const fs = require(\'node:fs\');\n'
|
|
164
|
+
+ 'const TARGET = ' + JSON.stringify(target) + ';\n'
|
|
165
|
+
+ 'if (!fs.existsSync(TARGET)) {\n'
|
|
166
|
+
+ ' process.stderr.write("nubos-pilot: tool binary fehlt unter " + TARGET + "\\nFix: npx nubos-pilot@latest update\\n");\n'
|
|
167
|
+
+ ' process.exit(1);\n'
|
|
168
|
+
+ '}\n'
|
|
169
|
+
+ 'require(TARGET).main();\n';
|
|
170
|
+
fs.mkdirSync(shimDir, { recursive: true });
|
|
171
|
+
atomicWriteFileSync(shimPath, body);
|
|
172
|
+
try { fs.chmodSync(shimPath, 0o755); } catch {}
|
|
173
|
+
return shimPath;
|
|
174
|
+
}
|
|
175
|
+
|
|
142
176
|
function _stateDirFor(projectRoot) {
|
|
143
177
|
return path.join(projectRoot, STATE_SUBPATH);
|
|
144
178
|
}
|
|
@@ -254,37 +288,48 @@ const DEFAULT_CLAUDE_MD = '# CLAUDE.md\n\n'
|
|
|
254
288
|
+ 'Project guidance for Claude Code. Add project-specific instructions above the'
|
|
255
289
|
+ ' managed block — `npx nubos-pilot` only rewrites the block between the markers.\n';
|
|
256
290
|
|
|
257
|
-
function _rewriteManagedMarkdown(projectRoot, runtimes) {
|
|
291
|
+
function _rewriteManagedMarkdown(projectRoot, runtimes, responseLanguage) {
|
|
292
|
+
const innerMd = _managedBlockInner(responseLanguage);
|
|
258
293
|
const claudePath = path.join(projectRoot, 'CLAUDE.md');
|
|
259
|
-
const agentsPath = path.join(projectRoot, 'AGENTS.md');
|
|
260
|
-
const geminiPath = path.join(projectRoot, 'GEMINI.md');
|
|
261
294
|
const claudeBase = fs.existsSync(claudePath)
|
|
262
295
|
? fs.readFileSync(claudePath, 'utf-8')
|
|
263
296
|
: DEFAULT_CLAUDE_MD;
|
|
264
|
-
const
|
|
265
|
-
atomicWriteFileSync(claudePath, claudeNext);
|
|
266
|
-
|
|
267
|
-
const agentsBase = fs.existsSync(agentsPath)
|
|
268
|
-
? fs.readFileSync(agentsPath, 'utf-8')
|
|
269
|
-
: agentsMdMod.generateAgentsMd(claudeNext, 'codex');
|
|
270
|
-
atomicWriteFileSync(agentsPath, managedBlockMod.rewriteBlock(agentsBase, MANAGED_BLOCK_INNER));
|
|
271
|
-
|
|
272
|
-
const geminiBase = fs.existsSync(geminiPath)
|
|
273
|
-
? fs.readFileSync(geminiPath, 'utf-8')
|
|
274
|
-
: agentsMdMod.generateAgentsMd(claudeNext, 'gemini');
|
|
275
|
-
atomicWriteFileSync(geminiPath, managedBlockMod.rewriteBlock(geminiBase, MANAGED_BLOCK_INNER));
|
|
297
|
+
const claudeRendered = managedBlockMod.rewriteBlock(claudeBase, innerMd);
|
|
276
298
|
|
|
277
|
-
const
|
|
278
|
-
|
|
299
|
+
const ids = Array.isArray(runtimes) && runtimes.length ? runtimes : ['claude'];
|
|
300
|
+
const written = new Set();
|
|
301
|
+
for (const id of ids) {
|
|
302
|
+
if (id === 'opencode') continue;
|
|
279
303
|
const meta = registryMod.getRuntimeMeta(id);
|
|
280
304
|
if (!meta) continue;
|
|
281
305
|
const targetPath = registryMod.runtimeAgentsPath(meta, 'local', projectRoot);
|
|
306
|
+
if (written.has(targetPath)) continue;
|
|
307
|
+
written.add(targetPath);
|
|
308
|
+
|
|
309
|
+
if (id === 'claude' && path.resolve(targetPath) === path.resolve(claudePath)) {
|
|
310
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
311
|
+
atomicWriteFileSync(targetPath, claudeRendered);
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
|
|
282
315
|
const base = fs.existsSync(targetPath)
|
|
283
316
|
? fs.readFileSync(targetPath, 'utf-8')
|
|
284
|
-
: agentsMdMod.generateAgentsMd(
|
|
285
|
-
const next = managedBlockMod.rewriteBlock(base, MANAGED_BLOCK_INNER);
|
|
317
|
+
: agentsMdMod.generateAgentsMd(claudeRendered, id === 'gemini' ? 'gemini' : 'codex');
|
|
286
318
|
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
287
|
-
atomicWriteFileSync(targetPath,
|
|
319
|
+
atomicWriteFileSync(targetPath, managedBlockMod.rewriteBlock(base, innerMd));
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const stalePaths = [claudePath, path.join(projectRoot, 'AGENTS.md'), path.join(projectRoot, 'GEMINI.md')];
|
|
323
|
+
for (const p of stalePaths) {
|
|
324
|
+
if (written.has(p)) continue;
|
|
325
|
+
if (!fs.existsSync(p)) continue;
|
|
326
|
+
const current = fs.readFileSync(p, 'utf-8');
|
|
327
|
+
const stripped = managedBlockMod.stripBlock(current);
|
|
328
|
+
if (stripped.trim().length === 0) {
|
|
329
|
+
try { fs.unlinkSync(p); } catch {}
|
|
330
|
+
} else if (stripped !== current) {
|
|
331
|
+
atomicWriteFileSync(p, stripped);
|
|
332
|
+
}
|
|
288
333
|
}
|
|
289
334
|
}
|
|
290
335
|
|
|
@@ -464,7 +509,8 @@ async function _runInstallLocked(ctx) {
|
|
|
464
509
|
}
|
|
465
510
|
|
|
466
511
|
const selectedRuntimes = (initConfig && initConfig.runtimes) || (initConfig ? [initConfig.runtime] : []);
|
|
467
|
-
|
|
512
|
+
const responseLanguage = initConfig && initConfig.response_language;
|
|
513
|
+
_rewriteManagedMarkdown(projectRoot, selectedRuntimes, responseLanguage);
|
|
468
514
|
|
|
469
515
|
if (assetPlans.length) {
|
|
470
516
|
runtimeAssetsMod.writeRuntimeAssets(assetPlans);
|
|
@@ -474,6 +520,10 @@ async function _runInstallLocked(ctx) {
|
|
|
474
520
|
runtimeAssetsMod.removeStaleAssets(assetStale, resolvedScope, projectRoot);
|
|
475
521
|
}
|
|
476
522
|
|
|
523
|
+
try { _writeToolsShim(projectRoot); } catch (err) {
|
|
524
|
+
console.error(yellow + ' [shim] np-tools shim skipped: ' + (err && err.message) + reset);
|
|
525
|
+
}
|
|
526
|
+
|
|
477
527
|
if (initConfig && initConfig.mcp && !dryRun) {
|
|
478
528
|
try {
|
|
479
529
|
const mcpWriter = require('../lib/install/mcp-writer.cjs');
|
|
@@ -631,8 +681,10 @@ async function main() {
|
|
|
631
681
|
return await runInstall({ cwd, mode: detectMode(cwd), flags });
|
|
632
682
|
case '--dry-run':
|
|
633
683
|
return await runInstall({ cwd, mode: detectMode(cwd), dryRun: true, flags });
|
|
634
|
-
case 'update':
|
|
635
|
-
|
|
684
|
+
case 'update': {
|
|
685
|
+
const detected = detectMode(cwd);
|
|
686
|
+
return await runInstall({ cwd, mode: detected === 'init' ? 'init' : 'update', flags });
|
|
687
|
+
}
|
|
636
688
|
case 'uninstall':
|
|
637
689
|
return await runUninstall({ cwd, args: rest.slice(1) });
|
|
638
690
|
case 'doctor': {
|
package/package.json
CHANGED
package/workflows/add-tests.md
CHANGED
|
@@ -17,7 +17,7 @@ sentinels survive regeneration.
|
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
19
|
PHASE="$1"
|
|
20
|
-
INIT=$(node np-tools.cjs init add-tests "$PHASE")
|
|
20
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init add-tests "$PHASE")
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
Parse: `phase`, `target_path`, `verification_path`, `pass_cases[]`,
|
|
@@ -29,7 +29,7 @@ Parse: `phase`, `target_path`, `verification_path`, `pass_cases[]`,
|
|
|
29
29
|
Emit/merge the Sentinel block:
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
node np-tools.cjs init add-tests emit "$PHASE"
|
|
32
|
+
node .nubos-pilot/bin/np-tools.cjs init add-tests emit "$PHASE"
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
Smoke-run the generated file to catch syntax errors early:
|
package/workflows/add-todo.md
CHANGED
|
@@ -18,7 +18,7 @@ metrics record. The `workflow-missing-metrics` lint in
|
|
|
18
18
|
`bin/check-workflows.cjs` only fires on `Task(` / `Spawn agent=` sites,
|
|
19
19
|
so CRUD-only workflows are exempt (Pitfall 9 resolution from
|
|
20
20
|
Plan 10-05). All interactive prompts route through
|
|
21
|
-
`node np-tools.cjs askuser --json` per INST-03.
|
|
21
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json` per INST-03.
|
|
22
22
|
|
|
23
23
|
## Initialize
|
|
24
24
|
|
|
@@ -29,7 +29,7 @@ if [[ -z "$DESCRIPTION" ]]; then
|
|
|
29
29
|
exit 2
|
|
30
30
|
fi
|
|
31
31
|
|
|
32
|
-
INIT=$(node np-tools.cjs init add-todo "$DESCRIPTION")
|
|
32
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init add-todo "$DESCRIPTION")
|
|
33
33
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
34
34
|
|
|
35
35
|
SLUG=$(echo "$INIT" | jq -r '.slug')
|
|
@@ -64,7 +64,7 @@ skip (keep both), or rename-with-counter (append `-2`, `-3`, etc.).
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
if [[ -f "$TODO_PATH" ]]; then
|
|
67
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
67
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
68
68
|
"type": "select",
|
|
69
69
|
"header": "Duplicate todo",
|
|
70
70
|
"question": "A todo already exists at '"${TODO_PATH}"'. What would you like to do?",
|
|
@@ -135,12 +135,12 @@ frontmatter. The lock serialises concurrent writers (two parallel
|
|
|
135
135
|
|
|
136
136
|
## Commit
|
|
137
137
|
|
|
138
|
-
Route through `node np-tools.cjs commit` so
|
|
138
|
+
Route through `node .nubos-pilot/bin/np-tools.cjs commit` so
|
|
139
139
|
`lib/git.cjs.assertCommittablePaths()` validates the paths before
|
|
140
140
|
`git add` (path-traversal guard from Plan 10-01-T04).
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
|
-
node np-tools.cjs commit "docs(10): add todo — ${SLUG}" --files "$TODO_PATH" "$STATE_PATH"
|
|
143
|
+
node .nubos-pilot/bin/np-tools.cjs commit "docs(10): add todo — ${SLUG}" --files "$TODO_PATH" "$STATE_PATH"
|
|
144
144
|
```
|
|
145
145
|
|
|
146
146
|
Both the new todo file and STATE.md land in a single atomic commit per
|
|
@@ -167,16 +167,16 @@ Use /np:next to surface this todo in the next-step picker.
|
|
|
167
167
|
(D-20 single-writer lock; T-10-05-06 mitigation).
|
|
168
168
|
- Use the `Write` tool for the new markdown file — never a bash
|
|
169
169
|
heredoc or `echo >`.
|
|
170
|
-
- Route the final commit through `node np-tools.cjs commit` so
|
|
170
|
+
- Route the final commit through `node .nubos-pilot/bin/np-tools.cjs commit` so
|
|
171
171
|
`lib/git.cjs.assertCommittablePaths()` runs the gitignore-guard.
|
|
172
|
-
- Derive the slug via `node np-tools.cjs init add-todo` (filename
|
|
172
|
+
- Derive the slug via `node .nubos-pilot/bin/np-tools.cjs init add-todo` (filename
|
|
173
173
|
sanitisation, T-10-05-01 mitigation) — not via ad-hoc `sed`.
|
|
174
174
|
- Commit todo file + STATE.md together as a single atomic unit.
|
|
175
175
|
|
|
176
176
|
**Don't:**
|
|
177
177
|
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint in
|
|
178
178
|
`bin/check-workflows.cjs` blocks them) — always route through
|
|
179
|
-
`node np-tools.cjs askuser --json '…'`.
|
|
179
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json '…'`.
|
|
180
180
|
- Read STATE.md via raw filesystem calls (DIRECT_READ lint blocks
|
|
181
181
|
those patterns) — let `mutateState` handle the lock.
|
|
182
182
|
- Add a `metrics record` block. There is no Task/Spawn site in this
|
|
@@ -19,7 +19,7 @@ workflow delivers PLAN-01 and nothing beyond it.
|
|
|
19
19
|
## Initialize
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
INIT=$(node np-tools.cjs init discuss-phase "$PHASE")
|
|
22
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init discuss-phase "$PHASE")
|
|
23
23
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -146,7 +146,7 @@ Text mode applies to ALL workflows in the session, not just discuss-phase.
|
|
|
146
146
|
If `has_context` is `true`, ask the user how to proceed:
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
-
node np-tools.cjs askuser --json '{
|
|
149
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
150
150
|
"type": "select",
|
|
151
151
|
"prompt": "Milestone '"$MILESTONE_ID"' already has a CONTEXT.md. What do you want to do?",
|
|
152
152
|
"options": [
|
|
@@ -184,7 +184,7 @@ user expects (users sometimes discover the roadmap goal is stale before
|
|
|
184
184
|
discussion starts):
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
|
-
node np-tools.cjs askuser --json '{
|
|
187
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
188
188
|
"type": "confirm",
|
|
189
189
|
"prompt": "ROADMAP goal for phase '"$PHASE"': \"'"$GOAL"'\". Still accurate?",
|
|
190
190
|
"default": true
|
|
@@ -195,7 +195,7 @@ If the user says `no`, capture the refined goal with a free-text input call
|
|
|
195
195
|
and record it for the `<domain>` section of CONTEXT.md:
|
|
196
196
|
|
|
197
197
|
```bash
|
|
198
|
-
node np-tools.cjs askuser --json '{
|
|
198
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
199
199
|
"type": "input",
|
|
200
200
|
"prompt": "Refined goal for phase '"$PHASE"':"
|
|
201
201
|
}'
|
|
@@ -208,7 +208,7 @@ generic UI/UX labels — specific decisions like "Session handling", "Error
|
|
|
208
208
|
responses", "Multi-device policy"). Present them via a multi-select:
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
-
node np-tools.cjs askuser --json '{
|
|
211
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
212
212
|
"type": "multiselect",
|
|
213
213
|
"prompt": "Which areas do you want to discuss for '"$PHASE_NAME"'?",
|
|
214
214
|
"options": [
|
|
@@ -233,20 +233,20 @@ Per area, the recommended flow is:
|
|
|
233
233
|
|
|
234
234
|
```bash
|
|
235
235
|
# Decision question (typed as select when options exist)
|
|
236
|
-
node np-tools.cjs askuser --json '{
|
|
236
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
237
237
|
"type": "select",
|
|
238
238
|
"prompt": "For <area>: <specific decision>?",
|
|
239
239
|
"options": ["<choice A>", "<choice B>", "<choice C>"]
|
|
240
240
|
}'
|
|
241
241
|
|
|
242
242
|
# Follow-up free-text capture when the user picks "Other" or needs nuance
|
|
243
|
-
node np-tools.cjs askuser --json '{
|
|
243
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
244
244
|
"type": "input",
|
|
245
245
|
"prompt": "Anything specific about <area> downstream agents must know?"
|
|
246
246
|
}'
|
|
247
247
|
|
|
248
248
|
# Continuation gate
|
|
249
|
-
node np-tools.cjs askuser --json '{
|
|
249
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
250
250
|
"type": "select",
|
|
251
251
|
"prompt": "More questions about <area>, or move on?",
|
|
252
252
|
"options": ["More questions", "Next area"]
|
|
@@ -256,7 +256,7 @@ node np-tools.cjs askuser --json '{
|
|
|
256
256
|
After all selected areas are covered:
|
|
257
257
|
|
|
258
258
|
```bash
|
|
259
|
-
node np-tools.cjs askuser --json '{
|
|
259
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
260
260
|
"type": "select",
|
|
261
261
|
"prompt": "We have discussed <areas>. Anything else before we write CONTEXT.md?",
|
|
262
262
|
"options": ["Explore more gray areas", "I am ready for CONTEXT.md"]
|
|
@@ -277,35 +277,35 @@ Collect short free-text inputs for the remaining required sections before
|
|
|
277
277
|
rendering:
|
|
278
278
|
|
|
279
279
|
```bash
|
|
280
|
-
node np-tools.cjs askuser --json '{
|
|
280
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
281
281
|
"type": "input",
|
|
282
282
|
"prompt": "Canonical refs (paths to ADRs/specs/docs downstream agents must read) — comma separated or \"none\":"
|
|
283
283
|
}'
|
|
284
284
|
```
|
|
285
285
|
|
|
286
286
|
```bash
|
|
287
|
-
node np-tools.cjs askuser --json '{
|
|
287
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
288
288
|
"type": "input",
|
|
289
289
|
"prompt": "Reusable code / existing assets relevant to this phase — or \"none\":"
|
|
290
290
|
}'
|
|
291
291
|
```
|
|
292
292
|
|
|
293
293
|
```bash
|
|
294
|
-
node np-tools.cjs askuser --json '{
|
|
294
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
295
295
|
"type": "input",
|
|
296
296
|
"prompt": "Specific references (\"I want it like X\" moments) — or \"none\":"
|
|
297
297
|
}'
|
|
298
298
|
```
|
|
299
299
|
|
|
300
300
|
```bash
|
|
301
|
-
node np-tools.cjs askuser --json '{
|
|
301
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
302
302
|
"type": "input",
|
|
303
303
|
"prompt": "Deferred ideas (things we noted but belong in later phases) — or \"none\":"
|
|
304
304
|
}'
|
|
305
305
|
```
|
|
306
306
|
|
|
307
307
|
```bash
|
|
308
|
-
node np-tools.cjs askuser --json '{
|
|
308
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
309
309
|
"type": "input",
|
|
310
310
|
"prompt": "Claude\u2019s Discretion — areas where you want Claude to decide without asking:"
|
|
311
311
|
}'
|
|
@@ -356,7 +356,7 @@ that error. Fix the template or the accumulator, don't mask the failure.
|
|
|
356
356
|
### Step 7: Commit respecting config.commit_docs
|
|
357
357
|
|
|
358
358
|
```bash
|
|
359
|
-
COMMIT_DOCS=$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null || echo "true")
|
|
359
|
+
COMMIT_DOCS=$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.commit_docs 2>/dev/null || echo "true")
|
|
360
360
|
if [[ "$COMMIT_DOCS" == "true" ]]; then
|
|
361
361
|
git add "$CONTEXT_PATH"
|
|
362
362
|
git commit -m "docs($MILESTONE_ID): capture milestone context"
|
|
@@ -369,7 +369,7 @@ opting into manual commit gating.
|
|
|
369
369
|
### Step 8: Confirm and next steps
|
|
370
370
|
|
|
371
371
|
```bash
|
|
372
|
-
node np-tools.cjs askuser --json '{
|
|
372
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
373
373
|
"type": "confirm",
|
|
374
374
|
"prompt": "CONTEXT.md written at '"$CONTEXT_PATH"'. Run np:plan-phase '"$PHASE"' now?",
|
|
375
375
|
"default": true
|
|
@@ -51,7 +51,7 @@ Never:
|
|
|
51
51
|
## Single-Call Init
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
INIT=$(node np-tools.cjs init discuss-project ${BOOTSTRAP:+--bootstrap})
|
|
54
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init discuss-project ${BOOTSTRAP:+--bootstrap})
|
|
55
55
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -134,7 +134,7 @@ REQ_FILE=$(mktemp -t np-proposed-reqs-XXXXXX.json)
|
|
|
134
134
|
ANSWERS=$(mktemp -t np-discuss-project-answers.XXXXXX.json)
|
|
135
135
|
# Write the six answer fields as JSON
|
|
136
136
|
|
|
137
|
-
node np-tools.cjs init discuss-project --apply "$ANSWERS" \
|
|
137
|
+
node .nubos-pilot/bin/np-tools.cjs init discuss-project --apply "$ANSWERS" \
|
|
138
138
|
${BOOTSTRAP:+--bootstrap} \
|
|
139
139
|
${REQ_FILE:+--proposed-requirements "$REQ_FILE"}
|
|
140
140
|
```
|
|
@@ -145,7 +145,7 @@ and appends a "Proposed" block to REQUIREMENTS.md. Both writes are atomic.
|
|
|
145
145
|
### Step 5: Commit respecting config.commit_docs
|
|
146
146
|
|
|
147
147
|
```bash
|
|
148
|
-
COMMIT_DOCS=$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null || echo "true")
|
|
148
|
+
COMMIT_DOCS=$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.commit_docs 2>/dev/null || echo "true")
|
|
149
149
|
if [[ "$COMMIT_DOCS" == "true" ]]; then
|
|
150
150
|
git add .nubos-pilot/PROJECT.md .nubos-pilot/REQUIREMENTS.md 2>/dev/null || true
|
|
151
151
|
git commit -m "docs: np:discuss-project ${BOOTSTRAP:+bootstrap}${BOOTSTRAP:-refresh}" 2>/dev/null || true
|
package/workflows/doctor.md
CHANGED
|
@@ -7,7 +7,7 @@ argument-hint: <milestone-number>
|
|
|
7
7
|
# /np:execute-phase
|
|
8
8
|
|
|
9
9
|
<objective>
|
|
10
|
-
Execute every slice of a milestone in wave order: slice S001 first (all its tasks in parallel), then S002, etc. Per task: start a checkpoint, spawn `agents/np-executor.md` (sonnet), verify, and invoke `node np-tools.cjs commit-task <task-full-id>` for the atomic commit. All git operations route through lib/git.cjs — agents NEVER call `git` directly (ADR-0004, CLAUDE.md §Git operations).
|
|
10
|
+
Execute every slice of a milestone in wave order: slice S001 first (all its tasks in parallel), then S002, etc. Per task: start a checkpoint, spawn `agents/np-executor.md` (sonnet), verify, and invoke `node .nubos-pilot/bin/np-tools.cjs commit-task <task-full-id>` for the atomic commit. All git operations route through lib/git.cjs — agents NEVER call `git` directly (ADR-0004, CLAUDE.md §Git operations).
|
|
11
11
|
|
|
12
12
|
**Wave semantics:** one slice == one wave. Tasks in a slice have no intra-slice deps (they're parallel-safe by planner contract). Cross-slice deps flow forward only: a task in S002 may depend on a task in S001.
|
|
13
13
|
</objective>
|
|
@@ -16,9 +16,9 @@ Execute every slice of a milestone in wave order: slice S001 first (all its task
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
PHASE="$1"
|
|
19
|
-
INIT=$(node np-tools.cjs init execute-milestone "$PHASE")
|
|
19
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init execute-milestone "$PHASE")
|
|
20
20
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
21
|
-
AGENT_SKILLS_EXECUTOR=$(node np-tools.cjs agent-skills executor 2>/dev/null)
|
|
21
|
+
AGENT_SKILLS_EXECUTOR=$(node .nubos-pilot/bin/np-tools.cjs agent-skills executor 2>/dev/null)
|
|
22
22
|
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
23
23
|
```
|
|
24
24
|
|
|
@@ -31,10 +31,10 @@ Parse JSON for: `milestone`, `milestone_id`, `milestone_dir`, `waves[]` (each wi
|
|
|
31
31
|
Detect stale checkpoints from a prior run before starting new work:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
RESUME=$(node np-tools.cjs init resume-work)
|
|
34
|
+
RESUME=$(node .nubos-pilot/bin/np-tools.cjs init resume-work)
|
|
35
35
|
RESUME_STATUS=$(echo "$RESUME" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).status))")
|
|
36
36
|
if [ "$RESUME_STATUS" = "orphan" ]; then
|
|
37
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
37
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
38
38
|
"type": "select",
|
|
39
39
|
"header": "Verwaiste Checkpoints gefunden",
|
|
40
40
|
"question": "Vor dem Milestone-Start wurden Checkpoint-Dateien ohne passenden STATE.current_task gefunden. Was tun?",
|
|
@@ -87,13 +87,13 @@ for WAVE_INDEX in 0 1 2 ...; do
|
|
|
87
87
|
# message (multiple Agent tool use blocks in one send).
|
|
88
88
|
for TASK_ID in $TASK_IDS; do
|
|
89
89
|
# IN PARALLEL:
|
|
90
|
-
node np-tools.cjs checkpoint start "$TASK_ID" --phase "$PHASE" --plan "$SLICE_FULL_ID" --wave "$((WAVE_INDEX+1))"
|
|
90
|
+
node .nubos-pilot/bin/np-tools.cjs checkpoint start "$TASK_ID" --phase "$PHASE" --plan "$SLICE_FULL_ID" --wave "$((WAVE_INDEX+1))"
|
|
91
91
|
|
|
92
|
-
TASK_JSON=$(node np-tools.cjs init execute-milestone execute-task "$PHASE" "$TASK_ID")
|
|
92
|
+
TASK_JSON=$(node .nubos-pilot/bin/np-tools.cjs init execute-milestone execute-task "$PHASE" "$TASK_ID")
|
|
93
93
|
if [[ "$TASK_JSON" == @file:* ]]; then TASK_JSON=$(cat "${TASK_JSON#@file:}"); fi
|
|
94
94
|
|
|
95
|
-
EXECUTOR_START=$(node np-tools.cjs metrics start-timestamp)
|
|
96
|
-
EXECUTOR_MODEL=$(node np-tools.cjs resolve-model executor --profile frontier)
|
|
95
|
+
EXECUTOR_START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
|
|
96
|
+
EXECUTOR_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model executor --profile frontier)
|
|
97
97
|
|
|
98
98
|
# Spawn agents/np-executor.md (tier: sonnet, model resolved as $EXECUTOR_MODEL)
|
|
99
99
|
# with a <files_to_read> block containing: the task plan file, the slice
|
|
@@ -101,15 +101,15 @@ for WAVE_INDEX in 0 1 2 ...; do
|
|
|
101
101
|
# Executor edits EXACTLY the paths in files_modified (D-04 — no scope
|
|
102
102
|
# expansion), runs <verify> commands, then invokes commit-task:
|
|
103
103
|
|
|
104
|
-
node np-tools.cjs checkpoint transition "$TASK_ID" verifying
|
|
105
|
-
node np-tools.cjs checkpoint transition "$TASK_ID" pre-commit
|
|
106
|
-
node np-tools.cjs commit-task "$TASK_ID"
|
|
104
|
+
node .nubos-pilot/bin/np-tools.cjs checkpoint transition "$TASK_ID" verifying
|
|
105
|
+
node .nubos-pilot/bin/np-tools.cjs checkpoint transition "$TASK_ID" pre-commit
|
|
106
|
+
node .nubos-pilot/bin/np-tools.cjs commit-task "$TASK_ID"
|
|
107
107
|
COMMIT_STATUS=$?
|
|
108
108
|
|
|
109
|
-
EXECUTOR_END=$(node np-tools.cjs metrics end-timestamp)
|
|
109
|
+
EXECUTOR_END=$(node .nubos-pilot/bin/np-tools.cjs metrics end-timestamp)
|
|
110
110
|
EXECUTOR_STATUS=ok
|
|
111
111
|
[ "$COMMIT_STATUS" -ne 0 ] && EXECUTOR_STATUS=error
|
|
112
|
-
node np-tools.cjs metrics record \
|
|
112
|
+
node .nubos-pilot/bin/np-tools.cjs metrics record \
|
|
113
113
|
--agent np-executor --tier sonnet --resolved-model "$EXECUTOR_MODEL" \
|
|
114
114
|
--phase "$PHASE" --plan "$SLICE_FULL_ID" --task "$TASK_ID" \
|
|
115
115
|
--started "$EXECUTOR_START" --ended "$EXECUTOR_END" \
|
|
@@ -135,7 +135,7 @@ After every slice completes, point the operator at `/np:validate-phase $PHASE` t
|
|
|
135
135
|
- Move to next slice **only after** every task in the current slice is committed.
|
|
136
136
|
- Start one checkpoint per task before spawning the executor agent.
|
|
137
137
|
- Spawn `agents/np-executor.md` once per task with only that task's `files_modified` in scope.
|
|
138
|
-
- Route every commit through `node np-tools.cjs commit-task` so `assertCommittablePaths` (D-25) runs.
|
|
138
|
+
- Route every commit through `node .nubos-pilot/bin/np-tools.cjs commit-task` so `assertCommittablePaths` (D-25) runs.
|
|
139
139
|
- Hard-stop the wave when `commit-task` returns a non-zero exit.
|
|
140
140
|
|
|
141
141
|
**Don't:**
|
package/workflows/help.md
CHANGED
|
@@ -52,7 +52,7 @@ The subcommand raises `project-not-initialized` anyway, but the shell check give
|
|
|
52
52
|
## Single-Call Init
|
|
53
53
|
|
|
54
54
|
```bash
|
|
55
|
-
INIT=$(node np-tools.cjs init new-milestone)
|
|
55
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init new-milestone)
|
|
56
56
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
57
57
|
```
|
|
58
58
|
|
|
@@ -63,9 +63,9 @@ Payload: three questions — `milestone_name`, `milestone_goal`, `create_req_pre
|
|
|
63
63
|
Three questions through `np-tools.cjs askuser`. No runtime-native question tool is permitted anywhere in this file.
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
|
-
ANS_MS_NAME=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone name (e.g. Auth & Basic UI)?"}')
|
|
67
|
-
ANS_MS_GOAL=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone goal (one sentence)?"}')
|
|
68
|
-
ANS_REQ_PREFIX=$(node np-tools.cjs askuser --json '{"type":"confirm","prompt":"Create a new Requirements section for this milestone?","default":false}')
|
|
66
|
+
ANS_MS_NAME=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone name (e.g. Auth & Basic UI)?"}')
|
|
67
|
+
ANS_MS_GOAL=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"Milestone goal (one sentence)?"}')
|
|
68
|
+
ANS_REQ_PREFIX=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"confirm","prompt":"Create a new Requirements section for this milestone?","default":false}')
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
<answer_validation>
|
|
@@ -89,7 +89,7 @@ node -e '
|
|
|
89
89
|
fs.writeFileSync(process.env.ANSWERS, JSON.stringify(payload));
|
|
90
90
|
' ANS_MS_NAME="$ANS_MS_NAME" ANS_MS_GOAL="$ANS_MS_GOAL" ANS_REQ_PREFIX="$ANS_REQ_PREFIX" ANSWERS="$ANSWERS"
|
|
91
91
|
|
|
92
|
-
node np-tools.cjs init new-milestone --apply "$ANSWERS"
|
|
92
|
+
node .nubos-pilot/bin/np-tools.cjs init new-milestone --apply "$ANSWERS"
|
|
93
93
|
```
|
|
94
94
|
|
|
95
95
|
On success the subcommand emits:
|
|
@@ -117,7 +117,7 @@ belongs in a separate workflow that the user invokes explicitly.
|
|
|
117
117
|
## Optional Commit
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
if [ "$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
120
|
+
if [ "$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
121
121
|
git add .nubos-pilot/
|
|
122
122
|
git commit -m "chore: np:new-milestone add $ANS_MS_NAME"
|
|
123
123
|
fi
|
package/workflows/new-project.md
CHANGED
|
@@ -106,16 +106,16 @@ Use the scan to propose:
|
|
|
106
106
|
The 5 structural questions. All prompts go through the askuser gateway.
|
|
107
107
|
|
|
108
108
|
```bash
|
|
109
|
-
INIT=$(node np-tools.cjs init new-project)
|
|
109
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init new-project)
|
|
110
110
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
ANS_PROJECT_NAME=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Project name?"}')
|
|
115
|
-
ANS_CORE_VALUE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Core value — one sentence that must stay true if everything else fails?"}')
|
|
116
|
-
ANS_CONSTRAINTS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"Primary constraints (comma-separated)?"}')
|
|
117
|
-
ANS_FIRST_MS=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First milestone name?"}')
|
|
118
|
-
ANS_FIRST_PHASE=$(node np-tools.cjs askuser --json '{"type":"input","prompt":"First phase name?"}')
|
|
114
|
+
ANS_PROJECT_NAME=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"Project name?"}')
|
|
115
|
+
ANS_CORE_VALUE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"Core value — one sentence that must stay true if everything else fails?"}')
|
|
116
|
+
ANS_CONSTRAINTS=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"Primary constraints (comma-separated)?"}')
|
|
117
|
+
ANS_FIRST_MS=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"First milestone name?"}')
|
|
118
|
+
ANS_FIRST_PHASE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","prompt":"First phase name?"}')
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
When Phase 0 produced a suggestion, include it as the prompt default in
|
|
@@ -143,7 +143,7 @@ node -e '
|
|
|
143
143
|
ANS_CONSTRAINTS="$ANS_CONSTRAINTS" ANS_FIRST_MS="$ANS_FIRST_MS" \
|
|
144
144
|
ANS_FIRST_PHASE="$ANS_FIRST_PHASE"
|
|
145
145
|
|
|
146
|
-
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
146
|
+
node .nubos-pilot/bin/np-tools.cjs init new-project --apply "$ANSWERS"
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
The six discovery-related PROJECT.md fields (`project_description`,
|
|
@@ -155,12 +155,12 @@ The six discovery-related PROJECT.md fields (`project_description`,
|
|
|
155
155
|
|
|
156
156
|
```bash
|
|
157
157
|
set +e
|
|
158
|
-
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
158
|
+
node .nubos-pilot/bin/np-tools.cjs init new-project --apply "$ANSWERS"
|
|
159
159
|
APPLY_STATUS=$?
|
|
160
160
|
set -e
|
|
161
161
|
|
|
162
162
|
if [ "$APPLY_STATUS" -ne 0 ]; then
|
|
163
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
163
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
164
164
|
"type": "select",
|
|
165
165
|
"prompt": "Project already initialized. Choose:",
|
|
166
166
|
"options": [
|
|
@@ -171,7 +171,7 @@ if [ "$APPLY_STATUS" -ne 0 ]; then
|
|
|
171
171
|
case "$CHOICE" in
|
|
172
172
|
*destructive*|*Delete*)
|
|
173
173
|
rm -rf ./.nubos-pilot
|
|
174
|
-
node np-tools.cjs init new-project --apply "$ANSWERS"
|
|
174
|
+
node .nubos-pilot/bin/np-tools.cjs init new-project --apply "$ANSWERS"
|
|
175
175
|
;;
|
|
176
176
|
*)
|
|
177
177
|
exit 1
|
|
@@ -208,7 +208,7 @@ If Phase 0 reported `file_count > 0` with code files (not only manifests
|
|
|
208
208
|
and docs), offer to run the initial scan now:
|
|
209
209
|
|
|
210
210
|
```bash
|
|
211
|
-
RUN_SCAN=$(node np-tools.cjs askuser --json '{
|
|
211
|
+
RUN_SCAN=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
212
212
|
"type": "confirm",
|
|
213
213
|
"prompt": "Run initial codebase scan now (np:scan-codebase)?",
|
|
214
214
|
"default": true
|
|
@@ -224,7 +224,7 @@ Empty workspaces skip this cleanly.
|
|
|
224
224
|
## Optional Commit
|
|
225
225
|
|
|
226
226
|
```bash
|
|
227
|
-
if [ "$(node np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
227
|
+
if [ "$(node .nubos-pilot/bin/np-tools.cjs config-get workflow.commit_docs 2>/dev/null)" = "true" ]; then
|
|
228
228
|
git add .nubos-pilot/
|
|
229
229
|
git commit -m "chore: np:new-project scaffold + discovery"
|
|
230
230
|
fi
|
package/workflows/note.md
CHANGED
|
@@ -26,7 +26,7 @@ metrics record. The `workflow-missing-metrics` lint in
|
|
|
26
26
|
`bin/check-workflows.cjs` only fires on `Task(` / `Spawn agent=` sites,
|
|
27
27
|
so CRUD-only workflows are exempt (Pitfall 9 resolution from
|
|
28
28
|
Plan 10-05). Interactive prompts route through
|
|
29
|
-
`node np-tools.cjs askuser --json` per INST-03.
|
|
29
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json` per INST-03.
|
|
30
30
|
|
|
31
31
|
## Initialize
|
|
32
32
|
|
|
@@ -68,7 +68,7 @@ fi
|
|
|
68
68
|
mkdir -p "$NOTES_DIR"
|
|
69
69
|
DATE=$(date +%Y-%m-%d)
|
|
70
70
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
71
|
-
SLUG=$(node np-tools.cjs generate-slug "$TEXT" --raw)
|
|
71
|
+
SLUG=$(node .nubos-pilot/bin/np-tools.cjs generate-slug "$TEXT" --raw)
|
|
72
72
|
if [[ -z "$SLUG" ]]; then
|
|
73
73
|
echo "Error: note text produced no slug-safe characters." >&2
|
|
74
74
|
exit 1
|
|
@@ -76,7 +76,7 @@ fi
|
|
|
76
76
|
NOTE_PATH="${NOTES_DIR}/${DATE}-${SLUG}.md"
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
Slug generation is delegated to `node np-tools.cjs generate-slug`
|
|
79
|
+
Slug generation is delegated to `node .nubos-pilot/bin/np-tools.cjs generate-slug`
|
|
80
80
|
(which wraps `lib/layout.cjs.slugify`) — the same filename-safety
|
|
81
81
|
rails used by every capture workflow (only `[a-z0-9-]` enter the
|
|
82
82
|
filename).
|
|
@@ -90,7 +90,7 @@ file.
|
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
92
|
if [[ -f "$NOTE_PATH" ]]; then
|
|
93
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
93
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
94
94
|
"type": "select",
|
|
95
95
|
"header": "Duplicate note",
|
|
96
96
|
"question": "A note already exists at '"${NOTE_PATH}"'. What would you like to do?",
|
|
@@ -148,7 +148,7 @@ for that distinction.
|
|
|
148
148
|
|
|
149
149
|
```bash
|
|
150
150
|
if [[ "$SCOPE" == "project" ]]; then
|
|
151
|
-
node np-tools.cjs commit "docs(10): add note — ${SLUG}" --files "$NOTE_PATH"
|
|
151
|
+
node .nubos-pilot/bin/np-tools.cjs commit "docs(10): add note — ${SLUG}" --files "$NOTE_PATH"
|
|
152
152
|
else
|
|
153
153
|
echo "Global note written to $NOTE_PATH (not committed — lives outside any project)." >&2
|
|
154
154
|
fi
|
|
@@ -177,9 +177,9 @@ Note saved ($SCOPE): $NOTE_PATH
|
|
|
177
177
|
- For global scope, bypass `lib/core.cjs.findProjectRoot` completely
|
|
178
178
|
(Pitfall 10) so the workflow works from any cwd, including non-repo
|
|
179
179
|
directories.
|
|
180
|
-
- Derive the slug via `node np-tools.cjs generate-slug` so only
|
|
180
|
+
- Derive the slug via `node .nubos-pilot/bin/np-tools.cjs generate-slug` so only
|
|
181
181
|
`[a-z0-9-]` enter the filename.
|
|
182
|
-
- Route the project-scope commit through `node np-tools.cjs commit`
|
|
182
|
+
- Route the project-scope commit through `node .nubos-pilot/bin/np-tools.cjs commit`
|
|
183
183
|
for `lib/git.cjs.assertCommittablePaths()` validation.
|
|
184
184
|
|
|
185
185
|
**Don't:**
|
|
@@ -191,7 +191,7 @@ Note saved ($SCOPE): $NOTE_PATH
|
|
|
191
191
|
(T-10-05-03 defence-in-depth).
|
|
192
192
|
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
193
193
|
in `bin/check-workflows.cjs` blocks them) — always route through
|
|
194
|
-
`node np-tools.cjs askuser --json '…'`.
|
|
194
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json '…'`.
|
|
195
195
|
- Mutate STATE.md. Notes are lighter-weight than todos; there is no
|
|
196
196
|
pending-note counter. If you need STATE semantics, use
|
|
197
197
|
`/np:add-todo` instead.
|
|
@@ -216,7 +216,7 @@ Note saved ($SCOPE): $NOTE_PATH
|
|
|
216
216
|
path (Pitfall 10 mitigation — bypasses findProjectRoot).
|
|
217
217
|
- [ ] Project-scope directory resolved via
|
|
218
218
|
`lib/core.cjs.projectStateDir`.
|
|
219
|
-
- [ ] Slug produced via `node np-tools.cjs generate-slug` (only
|
|
219
|
+
- [ ] Slug produced via `node .nubos-pilot/bin/np-tools.cjs generate-slug` (only
|
|
220
220
|
`[a-z0-9-]` enter filename).
|
|
221
221
|
- [ ] Duplicate collisions resolved via `askuser` Pattern S-3
|
|
222
222
|
(Re-run / View / Skip / Append-timestamp).
|
package/workflows/park.md
CHANGED
package/workflows/pause-work.md
CHANGED
package/workflows/plan-phase.md
CHANGED
|
@@ -62,7 +62,7 @@ When `--repromote` is set, skip every gate and the verification loop. Read every
|
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
64
|
if [[ "$REPROMOTE_FLAG" == "1" ]]; then
|
|
65
|
-
SCAFFOLD_JSON=$(node np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE")
|
|
65
|
+
SCAFFOLD_JSON=$(node .nubos-pilot/bin/np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE")
|
|
66
66
|
if [[ "$SCAFFOLD_JSON" == @file:* ]]; then SCAFFOLD_JSON=$(cat "${SCAFFOLD_JSON#@file:}"); fi
|
|
67
67
|
echo "repromote: $SCAFFOLD_JSON" >&2
|
|
68
68
|
exit 0
|
|
@@ -72,10 +72,10 @@ fi
|
|
|
72
72
|
### Read milestone state
|
|
73
73
|
|
|
74
74
|
```bash
|
|
75
|
-
INIT=$(node np-tools.cjs init plan-milestone init "$PHASE")
|
|
75
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init plan-milestone init "$PHASE")
|
|
76
76
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
77
|
-
AGENT_SKILLS_PLANNER=$(node np-tools.cjs agent-skills planner 2>/dev/null)
|
|
78
|
-
AGENT_SKILLS_CHECKER=$(node np-tools.cjs agent-skills plan-checker 2>/dev/null)
|
|
77
|
+
AGENT_SKILLS_PLANNER=$(node .nubos-pilot/bin/np-tools.cjs agent-skills planner 2>/dev/null)
|
|
78
|
+
AGENT_SKILLS_CHECKER=$(node .nubos-pilot/bin/np-tools.cjs agent-skills plan-checker 2>/dev/null)
|
|
79
79
|
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
80
80
|
```
|
|
81
81
|
|
|
@@ -90,7 +90,7 @@ Parse JSON for: `milestone`, `milestone_id`, `milestone_dir`, `milestone_context
|
|
|
90
90
|
If `has_context == false`:
|
|
91
91
|
|
|
92
92
|
```bash
|
|
93
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
93
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
94
94
|
"type": "select",
|
|
95
95
|
"header": "Missing M'"$PHASE"'-CONTEXT.md",
|
|
96
96
|
"question": "Milestone CONTEXT.md is not present. Continue?",
|
|
@@ -124,7 +124,7 @@ fi
|
|
|
124
124
|
If any slice has a `has_plan == true`:
|
|
125
125
|
|
|
126
126
|
```bash
|
|
127
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
127
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
128
128
|
"type": "select",
|
|
129
129
|
"header": "Milestone already planned",
|
|
130
130
|
"question": "One or more slices already have S<NNN>-PLAN.md. Overwrite?",
|
|
@@ -137,11 +137,11 @@ CHOICE=$(node np-tools.cjs askuser --json '{
|
|
|
137
137
|
case "$CHOICE" in
|
|
138
138
|
"Abort") exit 0 ;;
|
|
139
139
|
"Repromote")
|
|
140
|
-
node np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE" >&2
|
|
140
|
+
node .nubos-pilot/bin/np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE" >&2
|
|
141
141
|
exit 0
|
|
142
142
|
;;
|
|
143
143
|
"Overwrite")
|
|
144
|
-
node np-tools.cjs init plan-milestone abort "$PHASE"
|
|
144
|
+
node .nubos-pilot/bin/np-tools.cjs init plan-milestone abort "$PHASE"
|
|
145
145
|
;;
|
|
146
146
|
esac
|
|
147
147
|
```
|
|
@@ -179,13 +179,13 @@ for ITER in 1 2; do
|
|
|
179
179
|
[ "$ITER" = "2" ] && MODE="revise"
|
|
180
180
|
|
|
181
181
|
# --- Spawn planner ---
|
|
182
|
-
PLANNER_START=$(node np-tools.cjs metrics start-timestamp)
|
|
183
|
-
PLANNER_MODEL=$(node np-tools.cjs resolve-model planner --profile frontier)
|
|
182
|
+
PLANNER_START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
|
|
183
|
+
PLANNER_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model planner --profile frontier)
|
|
184
184
|
# Spawn agent=np-planner tier=opus model=$PLANNER_MODEL mode=$MODE milestone=$PHASE
|
|
185
185
|
# milestone_dir=$milestone_dir goal=$goal requirements=$requirements
|
|
186
186
|
# prior_findings=$LAST_FINDINGS agent_skills=$AGENT_SKILLS_PLANNER
|
|
187
|
-
PLANNER_END=$(node np-tools.cjs metrics end-timestamp)
|
|
188
|
-
node np-tools.cjs metrics record \
|
|
187
|
+
PLANNER_END=$(node .nubos-pilot/bin/np-tools.cjs metrics end-timestamp)
|
|
188
|
+
node .nubos-pilot/bin/np-tools.cjs metrics record \
|
|
189
189
|
--agent np-planner --tier opus --resolved-model "$PLANNER_MODEL" \
|
|
190
190
|
--phase "$PHASE" --plan "${milestone_id}-plan" --task "${milestone_id}-planner-run" \
|
|
191
191
|
--started "$PLANNER_START" --ended "$PLANNER_END" \
|
|
@@ -193,13 +193,13 @@ for ITER in 1 2; do
|
|
|
193
193
|
--retry-count 0 --status ok --runtime "$RUNTIME"
|
|
194
194
|
|
|
195
195
|
# --- Spawn plan-checker ---
|
|
196
|
-
CHECKER_START=$(node np-tools.cjs metrics start-timestamp)
|
|
197
|
-
CHECKER_MODEL=$(node np-tools.cjs resolve-model plan-checker --profile frontier)
|
|
196
|
+
CHECKER_START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
|
|
197
|
+
CHECKER_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model plan-checker --profile frontier)
|
|
198
198
|
# Spawn agent=np-plan-checker tier=opus model=$CHECKER_MODEL milestone=$PHASE
|
|
199
199
|
# milestone_dir=$milestone_dir agent_skills=$AGENT_SKILLS_CHECKER
|
|
200
200
|
# Checker writes YAML verdict; orchestrator converts to JSON.
|
|
201
|
-
CHECKER_END=$(node np-tools.cjs metrics end-timestamp)
|
|
202
|
-
node np-tools.cjs metrics record \
|
|
201
|
+
CHECKER_END=$(node .nubos-pilot/bin/np-tools.cjs metrics end-timestamp)
|
|
202
|
+
node .nubos-pilot/bin/np-tools.cjs metrics record \
|
|
203
203
|
--agent np-plan-checker --tier opus --resolved-model "$CHECKER_MODEL" \
|
|
204
204
|
--phase "$PHASE" --plan "${milestone_id}-plan" --task "${milestone_id}-planner-run" \
|
|
205
205
|
--started "$CHECKER_START" --ended "$CHECKER_END" \
|
|
@@ -220,7 +220,7 @@ for ITER in 1 2; do
|
|
|
220
220
|
LAST_FINDINGS="$VERDICT_JSON_PATH"
|
|
221
221
|
|
|
222
222
|
if [ "$ITER" = "2" ]; then
|
|
223
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
223
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
224
224
|
"type": "select",
|
|
225
225
|
"header": "Plan-Checker Stall",
|
|
226
226
|
"question": "Plan-Checker hat 2 Iterationen lang Fail gemeldet. Was tun?",
|
|
@@ -232,12 +232,12 @@ for ITER in 1 2; do
|
|
|
232
232
|
}')
|
|
233
233
|
case "$CHOICE" in
|
|
234
234
|
"Abort"*)
|
|
235
|
-
node np-tools.cjs init plan-milestone abort "$PHASE"
|
|
235
|
+
node .nubos-pilot/bin/np-tools.cjs init plan-milestone abort "$PHASE"
|
|
236
236
|
exit 1
|
|
237
237
|
;;
|
|
238
238
|
"Plan mit Warnings"*) break ;;
|
|
239
239
|
"Manuell editieren"*)
|
|
240
|
-
node np-tools.cjs askuser --json '{"type":"input","question":"Edit slice plans in your editor, then press Enter to re-check."}'
|
|
240
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"input","question":"Edit slice plans in your editor, then press Enter to re-check."}'
|
|
241
241
|
break
|
|
242
242
|
;;
|
|
243
243
|
esac
|
|
@@ -250,7 +250,7 @@ done
|
|
|
250
250
|
After a successful verification (or "commit-with-warnings"), scaffold every `<task>` block into its own directory + files:
|
|
251
251
|
|
|
252
252
|
```bash
|
|
253
|
-
SCAFFOLD_JSON=$(node np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE")
|
|
253
|
+
SCAFFOLD_JSON=$(node .nubos-pilot/bin/np-tools.cjs init plan-milestone scaffold-all-tasks "$PHASE")
|
|
254
254
|
if [[ "$SCAFFOLD_JSON" == @file:* ]]; then SCAFFOLD_JSON=$(cat "${SCAFFOLD_JSON#@file:}"); fi
|
|
255
255
|
echo "scaffold-all-tasks → $SCAFFOLD_JSON" >&2
|
|
256
256
|
```
|
|
@@ -65,7 +65,7 @@ Before exiting, confirm:
|
|
|
65
65
|
3. If the user declined the offline-confirm prompt, RESEARCH.md was NOT
|
|
66
66
|
written (D-23) and the abort message surfaced verbatim.
|
|
67
67
|
|
|
68
|
-
All confirmations route through `node np-tools.cjs askuser --json '{...}'`.
|
|
68
|
+
All confirmations route through `node .nubos-pilot/bin/np-tools.cjs askuser --json '{...}'`.
|
|
69
69
|
Never a bare prompt-tool invocation — Phase-3 D-03 rename rule
|
|
70
70
|
enforced by `bin/check-workflows.cjs` (the guard rejects any line that
|
|
71
71
|
mentions the forbidden Claude-Code prompt-tool identifier outside a
|
|
@@ -87,12 +87,12 @@ fi
|
|
|
87
87
|
## Step 1: Single-Call Init
|
|
88
88
|
|
|
89
89
|
All phase context is gathered in one call to
|
|
90
|
-
`node np-tools.cjs init research-phase <N>`. The subcommand returns a JSON
|
|
90
|
+
`node .nubos-pilot/bin/np-tools.cjs init research-phase <N>`. The subcommand returns a JSON
|
|
91
91
|
payload; larger payloads are written to a tmp file and referenced via
|
|
92
92
|
`@file:<path>`.
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
INIT=$(node np-tools.cjs init research-phase "$PHASE")
|
|
95
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init research-phase "$PHASE")
|
|
96
96
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
97
97
|
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
98
98
|
```
|
|
@@ -146,7 +146,7 @@ than silently clobbering the existing file.
|
|
|
146
146
|
|
|
147
147
|
```bash
|
|
148
148
|
if [[ "$HAS_RESEARCH" == "true" ]]; then
|
|
149
|
-
node np-tools.cjs askuser --json '{
|
|
149
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
150
150
|
"type": "select",
|
|
151
151
|
"prompt": "RESEARCH.md already exists for this phase. How do you want to proceed?",
|
|
152
152
|
"options": ["Overwrite", "Append-update", "Abort"]
|
|
@@ -168,7 +168,7 @@ external docs. Route the verbatim D-21 German confirm prompt through
|
|
|
168
168
|
```bash
|
|
169
169
|
MODE=online
|
|
170
170
|
if [[ "$WEBFETCH_AVAILABLE" == "false" && "$CONTEXT7_AVAILABLE" == "false" ]]; then
|
|
171
|
-
CONFIRM=$(node np-tools.cjs askuser --json '{"type":"confirm","question":"Kein Web-/Context7-Zugriff verfügbar — mit lokalen Quellen (Repo + Prior-Phase-CONTEXT.md) fortfahren?"}')
|
|
171
|
+
CONFIRM=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{"type":"confirm","question":"Kein Web-/Context7-Zugriff verfügbar — mit lokalen Quellen (Repo + Prior-Phase-CONTEXT.md) fortfahren?"}')
|
|
172
172
|
if [[ "$CONFIRM" != "yes" && "$CONFIRM" != "true" ]]; then
|
|
173
173
|
echo "Research aborted. Run \`np:plan-phase $PHASE --skip-research\` to proceed without research."
|
|
174
174
|
exit 0
|
|
@@ -196,8 +196,8 @@ pattern). An empty `$RESEARCHER_MODEL` string signals the runtime adapter to
|
|
|
196
196
|
omit the `model:` parameter at spawn (Phase 8 D-22 inherit-pattern).
|
|
197
197
|
|
|
198
198
|
```bash
|
|
199
|
-
RESEARCHER_START=$(node np-tools.cjs metrics start-timestamp)
|
|
200
|
-
RESEARCHER_MODEL=$(node np-tools.cjs resolve-model researcher --profile balanced)
|
|
199
|
+
RESEARCHER_START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
|
|
200
|
+
RESEARCHER_MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model researcher --profile balanced)
|
|
201
201
|
```
|
|
202
202
|
|
|
203
203
|
```text
|
|
@@ -211,8 +211,8 @@ usage-capture — Phase 10 will enrich this via runtime-adapter support per
|
|
|
211
211
|
RESEARCH §A5).
|
|
212
212
|
|
|
213
213
|
```bash
|
|
214
|
-
RESEARCHER_END=$(node np-tools.cjs metrics end-timestamp)
|
|
215
|
-
node np-tools.cjs metrics record \
|
|
214
|
+
RESEARCHER_END=$(node .nubos-pilot/bin/np-tools.cjs metrics end-timestamp)
|
|
215
|
+
node .nubos-pilot/bin/np-tools.cjs metrics record \
|
|
216
216
|
--agent np-researcher --tier sonnet --resolved-model "$RESEARCHER_MODEL" \
|
|
217
217
|
--phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
|
|
218
218
|
--started "$RESEARCHER_START" --ended "$RESEARCHER_END" \
|
|
@@ -264,7 +264,7 @@ Classify the researcher's structured-return block:
|
|
|
264
264
|
research-skipped (`--skip-research` path in `/np:plan-phase`).
|
|
265
265
|
|
|
266
266
|
```bash
|
|
267
|
-
node np-tools.cjs askuser --json '{
|
|
267
|
+
node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
268
268
|
"type": "select",
|
|
269
269
|
"prompt": "Research artifact written. What next?",
|
|
270
270
|
"options": ["Plan phase", "Review RESEARCH.md", "Done"]
|
package/workflows/reset-slice.md
CHANGED
|
@@ -32,7 +32,7 @@ No argument required. If `STATE.current_task` is null **and** no explicit id was
|
|
|
32
32
|
## Apply
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
RESULT=$(node np-tools.cjs reset-slice ${1:+"$1"})
|
|
35
|
+
RESULT=$(node .nubos-pilot/bin/np-tools.cjs reset-slice ${1:+"$1"})
|
|
36
36
|
echo "$RESULT" | jq .
|
|
37
37
|
```
|
|
38
38
|
|
package/workflows/resume-work.md
CHANGED
|
@@ -13,7 +13,7 @@ on each accordingly.
|
|
|
13
13
|
## Initialize
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
INIT=$(node np-tools.cjs init resume-work)
|
|
16
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init resume-work)
|
|
17
17
|
STATUS=$(echo "$INIT" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).status))")
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -29,7 +29,7 @@ STATE.current_task matches an in-progress checkpoint. Spawn
|
|
|
29
29
|
if [ "$STATUS" = "resume" ]; then
|
|
30
30
|
TASK_ID=$(echo "$INIT" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).task_id))")
|
|
31
31
|
# Hand the task payload + checkpoint to agents/np-executor.md; on completion
|
|
32
|
-
# the agent invokes `node np-tools.cjs commit-task "$TASK_ID"` as usual.
|
|
32
|
+
# the agent invokes `node .nubos-pilot/bin/np-tools.cjs commit-task "$TASK_ID"` as usual.
|
|
33
33
|
echo "Resuming task $TASK_ID via agents/np-executor.md …"
|
|
34
34
|
fi
|
|
35
35
|
```
|
|
@@ -40,7 +40,7 @@ Checkpoints exist but none match `STATE.current_task`:
|
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
42
|
if [ "$STATUS" = "orphan" ]; then
|
|
43
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
43
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
44
44
|
"type": "select",
|
|
45
45
|
"header": "Verwaiste Checkpoints",
|
|
46
46
|
"question": "Es existieren Checkpoint-Dateien, aber STATE.current_task passt nicht. Wie vorgehen?",
|
|
@@ -60,7 +60,7 @@ end.
|
|
|
60
60
|
Scan, group, write manifest + stubs, emit module-facts in one call:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
PLAN=$(node np-tools.cjs scan-codebase --project-name "$PROJECT_NAME")
|
|
63
|
+
PLAN=$(node .nubos-pilot/bin/np-tools.cjs scan-codebase --project-name "$PROJECT_NAME")
|
|
64
64
|
if [[ "$PLAN" == @file:* ]]; then PLAN=$(cat "${PLAN#@file:}"); fi
|
|
65
65
|
```
|
|
66
66
|
|
|
@@ -110,7 +110,7 @@ chance to pause with Ctrl-C. Never eat interrupt signals.
|
|
|
110
110
|
### Step 3: Apply prose per module
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
|
-
node np-tools.cjs scan-codebase --apply-prose \
|
|
113
|
+
node .nubos-pilot/bin/np-tools.cjs scan-codebase --apply-prose \
|
|
114
114
|
--module "$MODULE_ID" \
|
|
115
115
|
--prose-file "$PROSE_FILE"
|
|
116
116
|
```
|
|
@@ -149,11 +149,11 @@ truncated file.
|
|
|
149
149
|
## Commit
|
|
150
150
|
|
|
151
151
|
Both the new report and the updated pointer land in a single atomic
|
|
152
|
-
docs commit per ADR-0004. Route through `node np-tools.cjs commit`
|
|
152
|
+
docs commit per ADR-0004. Route through `node .nubos-pilot/bin/np-tools.cjs commit`
|
|
153
153
|
so `lib/git.cjs.assertCommittablePaths()` validates the paths.
|
|
154
154
|
|
|
155
155
|
```bash
|
|
156
|
-
node np-tools.cjs commit "docs(10): add session report — ${LOCAL_FILENAME_TS}" \
|
|
156
|
+
node .nubos-pilot/bin/np-tools.cjs commit "docs(10): add session report — ${LOCAL_FILENAME_TS}" \
|
|
157
157
|
--files "$REPORT_PATH" "$POINTER"
|
|
158
158
|
```
|
|
159
159
|
|
|
@@ -191,7 +191,7 @@ Session report: $REPORT_PATH
|
|
|
191
191
|
between the two would skip a session.
|
|
192
192
|
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
193
193
|
in `bin/check-workflows.cjs` blocks them) — route through
|
|
194
|
-
`node np-tools.cjs askuser --json '…'`.
|
|
194
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json '…'`.
|
|
195
195
|
- Add a `metrics record` block. No Task/Spawn site; Pitfall 9 /
|
|
196
196
|
`workflow-missing-metrics` is exempt.
|
|
197
197
|
</scope_guardrail>
|
package/workflows/skip.md
CHANGED
package/workflows/state.md
CHANGED
package/workflows/stats.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
command: np:stats
|
|
3
|
-
description: Stats output — phases-table (name/plans/completed/status/%) + metrics aggregation (tokens-in/out per phase, avg duration by tier, retry_count_sum, error_rate). Consumes node np-tools.cjs stats json. Null-token runtimes render as `—` (Phase 9 D-09). Read-only — no commits, no STATE mutation.
|
|
3
|
+
description: Stats output — phases-table (name/plans/completed/status/%) + metrics aggregation (tokens-in/out per phase, avg duration by tier, retry_count_sum, error_rate). Consumes node .nubos-pilot/bin/np-tools.cjs stats json. Null-token runtimes render as `—` (Phase 9 D-09). Read-only — no commits, no STATE mutation.
|
|
4
4
|
argument-hint: [json]
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -23,7 +23,7 @@ metrics record. Pitfall 9 / `workflow-missing-metrics` is exempt.
|
|
|
23
23
|
## Initialize
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
STATS_JSON=$(node np-tools.cjs stats json)
|
|
26
|
+
STATS_JSON=$(node .nubos-pilot/bin/np-tools.cjs stats json)
|
|
27
27
|
if [[ -z "$STATS_JSON" ]]; then
|
|
28
28
|
echo "No stats available (empty project?)" >&2
|
|
29
29
|
exit 0
|
|
@@ -115,7 +115,7 @@ and is rendered by the agent CLI.
|
|
|
115
115
|
|
|
116
116
|
<scope_guardrail>
|
|
117
117
|
**Do:**
|
|
118
|
-
- Consume `node np-tools.cjs stats json` — trust its
|
|
118
|
+
- Consume `node .nubos-pilot/bin/np-tools.cjs stats json` — trust its
|
|
119
119
|
`schema_version: 1` output shape (Plan 10-01-T04 contract).
|
|
120
120
|
- Render `tokens_in` / `tokens_out` as `—` when null (Phase 9 D-09
|
|
121
121
|
non-claude runtimes; D-15 hybrid-output decision).
|
|
@@ -131,7 +131,7 @@ and is rendered by the agent CLI.
|
|
|
131
131
|
- Add a git commit — there is nothing to commit.
|
|
132
132
|
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
133
133
|
in `bin/check-workflows.cjs` blocks them) — route through
|
|
134
|
-
`node np-tools.cjs askuser --json '…'` if prompts are ever added.
|
|
134
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json '…'` if prompts are ever added.
|
|
135
135
|
- Add a `metrics record` block. No Task/Spawn site; Pitfall 9 /
|
|
136
136
|
`workflow-missing-metrics` is exempt.
|
|
137
137
|
</scope_guardrail>
|
|
@@ -144,7 +144,7 @@ and is rendered by the agent CLI.
|
|
|
144
144
|
|
|
145
145
|
## Success Criteria
|
|
146
146
|
|
|
147
|
-
- [ ] Data sourced exclusively from `node np-tools.cjs stats json`
|
|
147
|
+
- [ ] Data sourced exclusively from `node .nubos-pilot/bin/np-tools.cjs stats json`
|
|
148
148
|
(Plan 10-01-T04) — no inline JSONL parsing.
|
|
149
149
|
- [ ] Null `tokens_in` / `tokens_out` render as `—` (D-09 / D-15).
|
|
150
150
|
- [ ] Progress bar is a 20-char block-string (ADR-0002).
|
package/workflows/thread.md
CHANGED
|
@@ -30,7 +30,7 @@ if [[ -z "$SLUG_ARG" ]]; then
|
|
|
30
30
|
echo "Usage: /np:thread <slug-or-title>" >&2
|
|
31
31
|
exit 2
|
|
32
32
|
fi
|
|
33
|
-
SLUG=$(node np-tools.cjs generate-slug "$SLUG_ARG" --raw)
|
|
33
|
+
SLUG=$(node .nubos-pilot/bin/np-tools.cjs generate-slug "$SLUG_ARG" --raw)
|
|
34
34
|
if [[ -z "$SLUG" ]]; then
|
|
35
35
|
echo "Error: argument produced no slug-safe characters." >&2
|
|
36
36
|
exit 1
|
|
@@ -90,13 +90,13 @@ last_resumed: <TODAY>
|
|
|
90
90
|
- *(what the next session should do first)*
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
Route the commit through `node np-tools.cjs commit` so
|
|
93
|
+
Route the commit through `node .nubos-pilot/bin/np-tools.cjs commit` so
|
|
94
94
|
`lib/git.cjs.assertCommittablePaths()` validates the path before
|
|
95
95
|
`git add` (path-traversal guard from Plan 10-01-T04).
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
98
|
if [[ "$MODE" == "create" ]]; then
|
|
99
|
-
node np-tools.cjs commit "docs(10): create thread — ${SLUG}" --files "$THREAD_PATH"
|
|
99
|
+
node .nubos-pilot/bin/np-tools.cjs commit "docs(10): create thread — ${SLUG}" --files "$THREAD_PATH"
|
|
100
100
|
echo "Thread created: $THREAD_PATH"
|
|
101
101
|
echo ""
|
|
102
102
|
echo "Resume anytime with: /np:thread ${SLUG}"
|
|
@@ -167,13 +167,13 @@ Echo `Thread <MODE>d: <THREAD_PATH>` with slug/mode/today to stdout.
|
|
|
167
167
|
command in this adapted port).
|
|
168
168
|
- Use `lib/core.cjs.atomicWriteFileSync` for any in-place rewrite
|
|
169
169
|
(ADR-0004 crash-safety).
|
|
170
|
-
- Route the create-branch commit through `node np-tools.cjs commit`.
|
|
170
|
+
- Route the create-branch commit through `node .nubos-pilot/bin/np-tools.cjs commit`.
|
|
171
171
|
|
|
172
172
|
**Don't:**
|
|
173
173
|
- Commit `last_resumed`-only updates. Resume is commit-free.
|
|
174
174
|
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
175
175
|
in `bin/check-workflows.cjs` blocks them) — route through
|
|
176
|
-
`node np-tools.cjs askuser --json '…'`.
|
|
176
|
+
`node .nubos-pilot/bin/np-tools.cjs askuser --json '…'`.
|
|
177
177
|
- Bypass `atomicWriteFileSync` — rename pair is the invariant.
|
|
178
178
|
- Add a `metrics record` block. No Task/Spawn site here; Pitfall 9 /
|
|
179
179
|
`workflow-missing-metrics` is exempt.
|
package/workflows/undo-task.md
CHANGED
package/workflows/undo.md
CHANGED
package/workflows/unpark.md
CHANGED
package/workflows/update-docs.md
CHANGED
|
@@ -51,7 +51,7 @@ If `.doc-index.json` is missing, fall back to a full rescan via
|
|
|
51
51
|
## Single-Call Init
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
PLAN=$(node np-tools.cjs update-docs)
|
|
54
|
+
PLAN=$(node .nubos-pilot/bin/np-tools.cjs update-docs)
|
|
55
55
|
if [[ "$PLAN" == @file:* ]]; then PLAN=$(cat "${PLAN#@file:}"); fi
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -84,7 +84,7 @@ For each module in `stale_modules ++ added_modules`:
|
|
|
84
84
|
|
|
85
85
|
```bash
|
|
86
86
|
# Build prompt from facts, dispatch agent, capture JSON to $PROSE_FILE
|
|
87
|
-
node np-tools.cjs update-docs --apply-prose \
|
|
87
|
+
node .nubos-pilot/bin/np-tools.cjs update-docs --apply-prose \
|
|
88
88
|
--module "$MODULE_ID" \
|
|
89
89
|
--prose-file "$PROSE_FILE"
|
|
90
90
|
```
|
|
@@ -19,7 +19,7 @@ if [[ -z "$PHASE" ]]; then
|
|
|
19
19
|
exit 2
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
|
-
INIT=$(node np-tools.cjs init verify-work "$PHASE")
|
|
22
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init verify-work "$PHASE")
|
|
23
23
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
24
24
|
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
25
25
|
```
|
|
@@ -60,7 +60,7 @@ If a prior audit is present, let the user choose Re-run / View / Skip. The templ
|
|
|
60
60
|
```bash
|
|
61
61
|
RERUN="false"
|
|
62
62
|
if [[ -f "$VALIDATION_PATH" ]]; then
|
|
63
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
63
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
64
64
|
"type": "select",
|
|
65
65
|
"header": "Existing VALIDATION.md",
|
|
66
66
|
"question": "VALIDATION.md already exists for milestone '"$MILESTONE_ID"'. What would you like to do?",
|
|
@@ -105,8 +105,8 @@ fi
|
|
|
105
105
|
The auditor reads `REQUIREMENTS.md`, filters to the milestone's declared requirement IDs (from `roadmap.yaml milestones[].requirements`), and scans every task PLAN.md frontmatter `requirements:` field plus every slice's SUMMARY.md for cross-reference coverage. It then inspects test files for each requirement ID.
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
|
-
START=$(node np-tools.cjs metrics start-timestamp)
|
|
109
|
-
MODEL=$(node np-tools.cjs resolve-model np-nyquist-auditor --profile frontier)
|
|
108
|
+
START=$(node .nubos-pilot/bin/np-tools.cjs metrics start-timestamp)
|
|
109
|
+
MODEL=$(node .nubos-pilot/bin/np-tools.cjs resolve-model np-nyquist-auditor --profile frontier)
|
|
110
110
|
|
|
111
111
|
# Build the read list from the init payload:
|
|
112
112
|
SLICE_PLANS=$(find "$MILESTONE_DIR/slices" -maxdepth 2 -name 'S*-PLAN.md' 2>/dev/null)
|
|
@@ -120,8 +120,8 @@ TASK_SUMMARIES=$(find "$MILESTONE_DIR/slices" -path '*/tasks/*/T*-SUMMARY.md' 2>
|
|
|
120
120
|
# output: $VALIDATION_PATH with per-requirement Nyquist scoring
|
|
121
121
|
# (COVERED / UNDER_SAMPLED / UNCOVERED), using templates/VALIDATION.md as skeleton.
|
|
122
122
|
|
|
123
|
-
END=$(node np-tools.cjs metrics end-timestamp)
|
|
124
|
-
node np-tools.cjs metrics record \
|
|
123
|
+
END=$(node .nubos-pilot/bin/np-tools.cjs metrics end-timestamp)
|
|
124
|
+
node .nubos-pilot/bin/np-tools.cjs metrics record \
|
|
125
125
|
--agent np-nyquist-auditor --tier haiku --resolved-model "$MODEL" \
|
|
126
126
|
--phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
|
|
127
127
|
--started "$START" --ended "$END" \
|
|
@@ -133,7 +133,7 @@ node np-tools.cjs metrics record \
|
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
135
|
if [[ ! -f "$VALIDATION_PATH" ]]; then
|
|
136
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
136
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
137
137
|
"type": "select",
|
|
138
138
|
"header": "VALIDATION.md missing",
|
|
139
139
|
"question": "np-nyquist-auditor did not write VALIDATION.md. What would you like to do?",
|
|
@@ -149,7 +149,7 @@ fi
|
|
|
149
149
|
## Commit
|
|
150
150
|
|
|
151
151
|
```bash
|
|
152
|
-
node np-tools.cjs commit "docs(${MILESTONE_ID}): add validation audit report" --files "$VALIDATION_PATH"
|
|
152
|
+
node .nubos-pilot/bin/np-tools.cjs commit "docs(${MILESTONE_ID}): add validation audit report" --files "$VALIDATION_PATH"
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
One atomic docs commit per ADR-0004. The commit helper routes through `lib/git.cjs.assertCommittablePaths` (gitignore-guard) before staging.
|
package/workflows/verify-work.md
CHANGED
|
@@ -16,9 +16,9 @@ Slice-level acceptance (UAT) is validated separately by `/np:validate-phase <N>`
|
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
18
|
PHASE="$1"
|
|
19
|
-
INIT=$(node np-tools.cjs init verify-work "$PHASE")
|
|
19
|
+
INIT=$(node .nubos-pilot/bin/np-tools.cjs init verify-work "$PHASE")
|
|
20
20
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
21
|
-
AGENT_SKILLS_VERIFIER=$(node np-tools.cjs agent-skills verifier 2>/dev/null)
|
|
21
|
+
AGENT_SKILLS_VERIFIER=$(node .nubos-pilot/bin/np-tools.cjs agent-skills verifier 2>/dev/null)
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
Parse: `milestone`, `milestone_id`, `milestone_dir`, `milestone_name`, `success_criteria`, `draft_results`, `verification_path`, `slice_uat`, `verifier_tier`, `agent_skills`.
|
|
@@ -35,7 +35,7 @@ The agent emits a structured verdict per SC: Pass | Fail | Needs-User-Confirm |
|
|
|
35
35
|
Persist the deterministic draft:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
node np-tools.cjs init verify-work emit-draft "$PHASE"
|
|
38
|
+
node .nubos-pilot/bin/np-tools.cjs init verify-work emit-draft "$PHASE"
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Pass 2 — user-driven gate for needs_user_confirm
|
|
@@ -44,7 +44,7 @@ For each result flagged `needs_user_confirm` by Pass 1, ask the user:
|
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
46
|
# Example — iterated by the workflow over each needs_user_confirm SC.
|
|
47
|
-
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
47
|
+
CHOICE=$(node .nubos-pilot/bin/np-tools.cjs askuser --json '{
|
|
48
48
|
"type": "select",
|
|
49
49
|
"header": "SC-3: UX feels responsive",
|
|
50
50
|
"question": "Ist dieses Kriterium erfüllt?",
|
|
@@ -55,7 +55,7 @@ CHOICE=$(node np-tools.cjs askuser --json '{
|
|
|
55
55
|
{"label": "Re-investigate", "description": "Brauche mehr Evidence — spawn Verifier nochmal."}
|
|
56
56
|
]
|
|
57
57
|
}')
|
|
58
|
-
node np-tools.cjs init verify-work record-sc "$PHASE" "SC-3" "$CHOICE"
|
|
58
|
+
node .nubos-pilot/bin/np-tools.cjs init verify-work record-sc "$PHASE" "SC-3" "$CHOICE"
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
## Hard-stop on Fail
|