nubos-pilot 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/np-ai-researcher.md +140 -0
- package/agents/np-code-fixer.md +363 -0
- package/agents/np-code-reviewer.md +351 -0
- package/agents/np-domain-researcher.md +136 -0
- package/agents/np-eval-auditor.md +167 -0
- package/agents/np-eval-planner.md +153 -0
- package/agents/np-executor.md +72 -0
- package/agents/np-framework-selector.md +171 -0
- package/agents/np-nyquist-auditor.md +185 -0
- package/agents/np-plan-checker.md +165 -0
- package/agents/np-planner.md +199 -0
- package/agents/np-researcher.md +150 -0
- package/agents/np-security-auditor.md +206 -0
- package/agents/np-ui-auditor.md +369 -0
- package/agents/np-ui-checker.md +192 -0
- package/agents/np-ui-researcher.md +324 -0
- package/agents/np-verifier.md +79 -0
- package/bin/check-coverage.cjs +40 -0
- package/bin/check-workflows.cjs +171 -0
- package/bin/check-workflows.test.cjs +208 -0
- package/bin/install.js +500 -0
- package/bin/np-tools/_commands.cjs +70 -0
- package/bin/np-tools/add-tests.cjs +171 -0
- package/bin/np-tools/add-tests.test.cjs +122 -0
- package/bin/np-tools/add-todo.cjs +108 -0
- package/bin/np-tools/add-todo.test.cjs +112 -0
- package/bin/np-tools/agent-skills.cjs +14 -0
- package/bin/np-tools/agent-skills.test.cjs +42 -0
- package/bin/np-tools/ai-integration-phase.cjs +109 -0
- package/bin/np-tools/ai-integration-phase.test.cjs +123 -0
- package/bin/np-tools/askuser.cjs +53 -0
- package/bin/np-tools/askuser.test.cjs +49 -0
- package/bin/np-tools/autonomous.cjs +69 -0
- package/bin/np-tools/autonomous.test.cjs +74 -0
- package/bin/np-tools/checkpoint.cjs +101 -0
- package/bin/np-tools/checkpoint.test.cjs +119 -0
- package/bin/np-tools/code-review.cjs +133 -0
- package/bin/np-tools/code-review.test.cjs +96 -0
- package/bin/np-tools/commit-task.cjs +120 -0
- package/bin/np-tools/commit-task.test.cjs +160 -0
- package/bin/np-tools/commit.cjs +103 -0
- package/bin/np-tools/commit.test.cjs +93 -0
- package/bin/np-tools/config.cjs +101 -0
- package/bin/np-tools/config.test.cjs +71 -0
- package/bin/np-tools/discuss-phase-power.cjs +265 -0
- package/bin/np-tools/discuss-phase-power.test.cjs +242 -0
- package/bin/np-tools/discuss-phase.cjs +132 -0
- package/bin/np-tools/discuss-phase.test.cjs +148 -0
- package/bin/np-tools/dispatch.cjs +116 -0
- package/bin/np-tools/doctor.cjs +242 -0
- package/bin/np-tools/eval-review.cjs +116 -0
- package/bin/np-tools/eval-review.test.cjs +123 -0
- package/bin/np-tools/execute-phase.cjs +182 -0
- package/bin/np-tools/execute-phase.test.cjs +116 -0
- package/bin/np-tools/execute-plan.cjs +124 -0
- package/bin/np-tools/execute-plan.test.cjs +82 -0
- package/bin/np-tools/help.cjs +28 -0
- package/bin/np-tools/help.test.cjs +29 -0
- package/bin/np-tools/init-dispatch.test.cjs +91 -0
- package/bin/np-tools/metrics.cjs +97 -0
- package/bin/np-tools/metrics.test.cjs +188 -0
- package/bin/np-tools/new-milestone.cjs +288 -0
- package/bin/np-tools/new-milestone.test.cjs +166 -0
- package/bin/np-tools/new-project.cjs +284 -0
- package/bin/np-tools/new-project.test.cjs +165 -0
- package/bin/np-tools/next.cjs +7 -0
- package/bin/np-tools/next.test.cjs +30 -0
- package/bin/np-tools/park.cjs +48 -0
- package/bin/np-tools/park.test.cjs +50 -0
- package/bin/np-tools/pause-work.cjs +24 -0
- package/bin/np-tools/pause-work.test.cjs +74 -0
- package/bin/np-tools/phase.cjs +71 -0
- package/bin/np-tools/phase.test.cjs +81 -0
- package/bin/np-tools/plan-diff.cjs +57 -0
- package/bin/np-tools/plan-diff.test.cjs +134 -0
- package/bin/np-tools/plan-milestone-gaps.cjs +115 -0
- package/bin/np-tools/plan-milestone-gaps.test.cjs +122 -0
- package/bin/np-tools/plan-phase.cjs +350 -0
- package/bin/np-tools/plan-phase.test.cjs +263 -0
- package/bin/np-tools/progress.cjs +7 -0
- package/bin/np-tools/progress.test.cjs +44 -0
- package/bin/np-tools/queue.cjs +213 -0
- package/bin/np-tools/research-phase.cjs +144 -0
- package/bin/np-tools/research-phase.test.cjs +154 -0
- package/bin/np-tools/reset-slice.cjs +17 -0
- package/bin/np-tools/reset-slice.test.cjs +96 -0
- package/bin/np-tools/resolve-model.cjs +110 -0
- package/bin/np-tools/resolve-model.test.cjs +200 -0
- package/bin/np-tools/resume-work.cjs +76 -0
- package/bin/np-tools/resume-work.test.cjs +91 -0
- package/bin/np-tools/skip.cjs +48 -0
- package/bin/np-tools/skip.test.cjs +66 -0
- package/bin/np-tools/slug.cjs +34 -0
- package/bin/np-tools/slug.test.cjs +46 -0
- package/bin/np-tools/state.cjs +16 -0
- package/bin/np-tools/state.test.cjs +40 -0
- package/bin/np-tools/stats.cjs +151 -0
- package/bin/np-tools/stats.test.cjs +118 -0
- package/bin/np-tools/triage.cjs +128 -0
- package/bin/np-tools/ui-phase.cjs +108 -0
- package/bin/np-tools/ui-phase.test.cjs +121 -0
- package/bin/np-tools/ui-review.cjs +108 -0
- package/bin/np-tools/ui-review.test.cjs +120 -0
- package/bin/np-tools/undo-task.cjs +31 -0
- package/bin/np-tools/undo-task.test.cjs +117 -0
- package/bin/np-tools/undo.cjs +43 -0
- package/bin/np-tools/undo.test.cjs +120 -0
- package/bin/np-tools/unpark.cjs +48 -0
- package/bin/np-tools/unpark.test.cjs +50 -0
- package/bin/np-tools/verify-work.cjs +186 -0
- package/bin/np-tools/verify-work.test.cjs +97 -0
- package/docs/adr/0001-no-daemon-invariant.md +82 -0
- package/docs/adr/0002-zero-runtime-dependencies.md +90 -0
- package/docs/adr/0003-max-six-unit-types.md +85 -0
- package/docs/adr/0004-atomic-commit-per-unit.md +102 -0
- package/docs/adr/0005-three-orthogonal-file-trees.md +98 -0
- package/docs/adr/0006-yaml-dependency-amendment.md +60 -0
- package/docs/adr/README.md +27 -0
- package/docs/agent-frontmatter-schema.md +84 -0
- package/docs/phase-artifact-schemas.md +292 -0
- package/docs/phase-directory-layout.md +82 -0
- package/lib/__tests__/README.md +1 -0
- package/lib/agents.cjs +98 -0
- package/lib/agents.test.cjs +286 -0
- package/lib/askuser.cjs +36 -0
- package/lib/askuser.test.cjs +310 -0
- package/lib/checkpoint.cjs +135 -0
- package/lib/checkpoint.test.cjs +184 -0
- package/lib/core.cjs +165 -0
- package/lib/core.test.cjs +405 -0
- package/lib/fixtures/README.md +1 -0
- package/lib/fixtures/phase-tree/README.md +1 -0
- package/lib/fixtures/plans/cycle/PLAN.md +16 -0
- package/lib/fixtures/plans/cycle/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/cycle/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/cycle/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/linear/PLAN.md +16 -0
- package/lib/fixtures/plans/linear/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/linear/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/linear/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/parallel/PLAN.md +16 -0
- package/lib/fixtures/plans/parallel/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/parallel/tasks/T-02.md +20 -0
- package/lib/fixtures/plans/parallel/tasks/T-03.md +20 -0
- package/lib/fixtures/plans/wave-conflict/PLAN.md +16 -0
- package/lib/fixtures/plans/wave-conflict/tasks/T-01.md +20 -0
- package/lib/fixtures/plans/wave-conflict/tasks/T-02.md +20 -0
- package/lib/fixtures/roadmap/ROADMAP-malformed.md +3 -0
- package/lib/fixtures/roadmap/ROADMAP-minimal.md +51 -0
- package/lib/fixtures/roadmap/roadmap-malformed.yaml +7 -0
- package/lib/fixtures/roadmap/roadmap-minimal.yaml +40 -0
- package/lib/fixtures/roadmap/roadmap-ten-phases.yaml +101 -0
- package/lib/fixtures/templates/phase-context.md +6 -0
- package/lib/fixtures/templates/plan-skeleton.md +6 -0
- package/lib/frontmatter.cjs +251 -0
- package/lib/frontmatter.test.cjs +177 -0
- package/lib/gaps.cjs +197 -0
- package/lib/gaps.test.cjs +200 -0
- package/lib/git.cjs +207 -0
- package/lib/git.test.cjs +305 -0
- package/lib/install/agents-md.cjs +77 -0
- package/lib/install/backup.cjs +70 -0
- package/lib/install/codex-toml.cjs +440 -0
- package/lib/install/managed-block.cjs +30 -0
- package/lib/install/manifest.cjs +148 -0
- package/lib/install/mcp-writer.cjs +127 -0
- package/lib/install/runtime-detect.cjs +44 -0
- package/lib/install/staging.cjs +149 -0
- package/lib/metrics-aggregate.cjs +229 -0
- package/lib/metrics-aggregate.test.cjs +192 -0
- package/lib/metrics.cjs +120 -0
- package/lib/metrics.test.cjs +182 -0
- package/lib/model-aliases.regression.test.cjs +16 -0
- package/lib/model-profiles.cjs +42 -0
- package/lib/model-profiles.test.cjs +61 -0
- package/lib/next.cjs +236 -0
- package/lib/next.test.cjs +194 -0
- package/lib/phase.cjs +95 -0
- package/lib/phase.test.cjs +189 -0
- package/lib/plan-checker-contract.test.cjs +72 -0
- package/lib/plan-diff.cjs +173 -0
- package/lib/plan-diff.test.cjs +217 -0
- package/lib/plan.cjs +85 -0
- package/lib/plan.test.cjs +263 -0
- package/lib/progress.cjs +95 -0
- package/lib/progress.test.cjs +116 -0
- package/lib/researcher-contract.test.cjs +61 -0
- package/lib/roadmap-render.cjs +206 -0
- package/lib/roadmap-render.test.cjs +121 -0
- package/lib/roadmap.cjs +416 -0
- package/lib/roadmap.test.cjs +371 -0
- package/lib/runtime/_contract.test.cjs +61 -0
- package/lib/runtime/_readline.cjs +119 -0
- package/lib/runtime/_readline.test.cjs +126 -0
- package/lib/runtime/claude.cjs +48 -0
- package/lib/runtime/claude.test.cjs +101 -0
- package/lib/runtime/codex.cjs +35 -0
- package/lib/runtime/codex.test.cjs +114 -0
- package/lib/runtime/gemini.cjs +35 -0
- package/lib/runtime/gemini.test.cjs +109 -0
- package/lib/runtime/index.cjs +49 -0
- package/lib/runtime/index.test.cjs +181 -0
- package/lib/runtime/opencode.cjs +35 -0
- package/lib/runtime/opencode.test.cjs +124 -0
- package/lib/state.cjs +205 -0
- package/lib/state.test.cjs +264 -0
- package/lib/surface-audit.test.cjs +46 -0
- package/lib/tasks.cjs +327 -0
- package/lib/tasks.test.cjs +389 -0
- package/lib/template.cjs +66 -0
- package/lib/template.test.cjs +159 -0
- package/lib/undo.cjs +179 -0
- package/lib/undo.test.cjs +261 -0
- package/lib/verify.cjs +116 -0
- package/lib/verify.test.cjs +187 -0
- package/np-tools.cjs +303 -0
- package/package.json +39 -0
- package/templates/AI-SPEC.md +90 -0
- package/templates/CONTEXT.md +32 -0
- package/templates/PLAN.md +69 -0
- package/templates/PROJECT.md +60 -0
- package/templates/REQUIREMENTS.md +38 -0
- package/templates/SECURITY.md +61 -0
- package/templates/UI-SPEC.md +64 -0
- package/templates/VALIDATION.md +76 -0
- package/templates/claude/payload/README.md +11 -0
- package/templates/opencode/opencode.json +6 -0
- package/templates/opencode/payload/AGENTS.md +9 -0
- package/workflows/add-backlog.md +212 -0
- package/workflows/add-tests.md +69 -0
- package/workflows/add-todo.md +222 -0
- package/workflows/ai-integration-phase.md +230 -0
- package/workflows/autonomous.md +94 -0
- package/workflows/cleanup.md +325 -0
- package/workflows/code-review-fix.md +435 -0
- package/workflows/code-review.md +447 -0
- package/workflows/discuss-phase-assumptions.md +269 -0
- package/workflows/discuss-phase-power.md +139 -0
- package/workflows/discuss-phase.md +386 -0
- package/workflows/dispatch.md +9 -0
- package/workflows/doctor.md +10 -0
- package/workflows/eval-review.md +243 -0
- package/workflows/execute-phase.md +142 -0
- package/workflows/execute-plan.md +82 -0
- package/workflows/help.md +8 -0
- package/workflows/new-milestone.md +166 -0
- package/workflows/new-project.md +213 -0
- package/workflows/next.md +8 -0
- package/workflows/note.md +244 -0
- package/workflows/park.md +29 -0
- package/workflows/pause-work.md +34 -0
- package/workflows/plan-milestone-gaps.md +233 -0
- package/workflows/plan-phase.md +351 -0
- package/workflows/progress.md +8 -0
- package/workflows/queue.md +9 -0
- package/workflows/research-phase.md +327 -0
- package/workflows/reset-slice.md +39 -0
- package/workflows/resume-work.md +79 -0
- package/workflows/review.md +489 -0
- package/workflows/secure-phase.md +209 -0
- package/workflows/session-report.md +243 -0
- package/workflows/skip.md +29 -0
- package/workflows/state.md +7 -0
- package/workflows/stats.md +170 -0
- package/workflows/thread.md +214 -0
- package/workflows/triage.md +9 -0
- package/workflows/ui-phase.md +246 -0
- package/workflows/ui-review.md +222 -0
- package/workflows/undo-task.md +42 -0
- package/workflows/undo.md +55 -0
- package/workflows/unpark.md +29 -0
- package/workflows/validate-phase.md +231 -0
- package/workflows/verify-work.md +83 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:add-backlog
|
|
3
|
+
description: Add a 999.x backlog item to ROADMAP.md. Uses lib/roadmap.cjs.addBacklogEntry (file-locked) to append to the synthetic "backlog" milestone. Creates .nubos-pilot/phases/999.X-<slug>/.gitkeep. One atomic docs commit.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:add-backlog
|
|
7
|
+
|
|
8
|
+
Implements UTIL-05c. Mints a new entry in the synthetic `backlog`
|
|
9
|
+
milestone (id: `backlog`) using 999.x numbering. Unlike normal phases,
|
|
10
|
+
backlog items live outside the active milestone sequence — they are
|
|
11
|
+
the parking lot for "not-ready-to-plan" ideas that still deserve a
|
|
12
|
+
home in the roadmap.
|
|
13
|
+
|
|
14
|
+
The authoritative numbering and ROADMAP/roadmap.yaml update are
|
|
15
|
+
performed inside `lib/roadmap.cjs.addBacklogEntry` (landed in
|
|
16
|
+
Plan 10-01-T05). That helper is file-locked via `_mutate()` so two
|
|
17
|
+
parallel invocations serialise on the same 999.x counter (T-10-05-04
|
|
18
|
+
is accepted because the lock resolves the race inside the mutator).
|
|
19
|
+
The preview number shown to the user is computed OUTSIDE the lock and
|
|
20
|
+
is advisory only — the authoritative number comes back in the
|
|
21
|
+
helper's return value.
|
|
22
|
+
|
|
23
|
+
This is a pure-CRUD workflow — no agent spawn, no resolve-model, no
|
|
24
|
+
metrics record. The `workflow-missing-metrics` lint in
|
|
25
|
+
`bin/check-workflows.cjs` only fires on `Task(` / `Spawn agent=` sites,
|
|
26
|
+
so CRUD-only workflows are exempt (Pitfall 9 resolution from
|
|
27
|
+
Plan 10-05). Interactive prompts route through
|
|
28
|
+
`node np-tools.cjs askuser --json` per INST-03.
|
|
29
|
+
|
|
30
|
+
## Initialize
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
TITLE="$*"
|
|
34
|
+
if [[ -z "$TITLE" ]]; then
|
|
35
|
+
echo "Usage: /np:add-backlog <title>" >&2
|
|
36
|
+
exit 2
|
|
37
|
+
fi
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Compute Preview
|
|
41
|
+
|
|
42
|
+
Info-only preview — the preview number is NOT used as the commit
|
|
43
|
+
subject. The authoritative 999.X is assigned inside the lock and
|
|
44
|
+
returned in `RESULT` below.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
NEXT_NUMBER=$(node np-tools.cjs phase next-decimal 999 --raw)
|
|
48
|
+
SLUG=$(node np-tools.cjs generate-slug "$TITLE" --raw)
|
|
49
|
+
if [[ -z "$SLUG" ]]; then
|
|
50
|
+
echo "Error: title produced no slug-safe characters." >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
echo "Will add backlog item: ${NEXT_NUMBER} — ${TITLE}"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Confirm
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
60
|
+
"type": "select",
|
|
61
|
+
"header": "Backlog Item Preview",
|
|
62
|
+
"question": "Add backlog item '"${NEXT_NUMBER}"' — '"${TITLE}"'?",
|
|
63
|
+
"options": [
|
|
64
|
+
{"label": "Yes — append to ROADMAP + create phase dir", "description": "One atomic docs commit (ROADMAP.md + roadmap.yaml + .gitkeep)."},
|
|
65
|
+
{"label": "Cancel", "description": "Exit without changes."}
|
|
66
|
+
]
|
|
67
|
+
}')
|
|
68
|
+
case "$CHOICE" in
|
|
69
|
+
"Cancel"*) exit 0 ;;
|
|
70
|
+
esac
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Append to ROADMAP
|
|
74
|
+
|
|
75
|
+
The real append happens through `lib/roadmap.cjs.addBacklogEntry`
|
|
76
|
+
which owns (1) input validation (500-char cap, YAML-separator reject),
|
|
77
|
+
(2) the file lock, and (3) the 999.X numbering computed inside the
|
|
78
|
+
mutator. The helper returns `{backlog_number, backlog_slug}`; we use
|
|
79
|
+
those values — NOT the preview values — for the phase directory and
|
|
80
|
+
commit subject.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
RESULT=$(node -e "const r=require('./lib/roadmap.cjs').addBacklogEntry(process.argv[1]); process.stdout.write(JSON.stringify(r));" "$TITLE")
|
|
84
|
+
BACKLOG_NUMBER=$(echo "$RESULT" | jq -r '.backlog_number')
|
|
85
|
+
BACKLOG_SLUG=$(echo "$RESULT" | jq -r '.backlog_slug')
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
T-10-05-03 (description-breaks-YAML) is mitigated inside
|
|
89
|
+
`addBacklogEntry`: it rejects descriptions containing the YAML
|
|
90
|
+
separator pattern and caps length at 500 chars, then re-parses
|
|
91
|
+
roadmap.yaml inside the lock to validate the post-mutation document.
|
|
92
|
+
|
|
93
|
+
## Create Phase Dir Stub
|
|
94
|
+
|
|
95
|
+
The backlog phase gets an empty `.gitkeep` directory so
|
|
96
|
+
`/np:discuss-phase 999.X` and `/np:plan-phase 999.X` have a place to
|
|
97
|
+
write CONTEXT/RESEARCH/PLAN artefacts when the idea graduates from
|
|
98
|
+
parking lot to active planning.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
STATE_DIR=$(node -e "console.log(require('./lib/core.cjs').projectStateDir(process.cwd()))")
|
|
102
|
+
PHASE_DIR="${STATE_DIR}/phases/${BACKLOG_NUMBER}-${BACKLOG_SLUG}"
|
|
103
|
+
mkdir -p "$PHASE_DIR"
|
|
104
|
+
touch "${PHASE_DIR}/.gitkeep"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Commit
|
|
108
|
+
|
|
109
|
+
Route through `node np-tools.cjs commit` so
|
|
110
|
+
`lib/git.cjs.assertCommittablePaths()` validates each path before
|
|
111
|
+
`git add`. ROADMAP.md (rendered), roadmap.yaml (canonical source), and
|
|
112
|
+
the phase-dir `.gitkeep` land together as a single atomic unit per
|
|
113
|
+
ADR-0004.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
node np-tools.cjs commit "docs(10): add backlog item ${BACKLOG_NUMBER} — ${TITLE}" \
|
|
117
|
+
--files "${STATE_DIR}/ROADMAP.md" "${STATE_DIR}/roadmap.yaml" "${PHASE_DIR}/.gitkeep"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Report
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
Backlog item added: ${BACKLOG_NUMBER} — ${TITLE}
|
|
124
|
+
Directory: ${PHASE_DIR}/
|
|
125
|
+
|
|
126
|
+
This item lives in the backlog parking lot.
|
|
127
|
+
Use /np:discuss-phase ${BACKLOG_NUMBER} to explore it further.
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Scope Guardrail
|
|
131
|
+
|
|
132
|
+
<scope_guardrail>
|
|
133
|
+
**Do:**
|
|
134
|
+
- Use `lib/roadmap.cjs.addBacklogEntry` (file-locked + atomic
|
|
135
|
+
YAML+MD write) — it is the single sanctioned mutator for the
|
|
136
|
+
synthetic `backlog` milestone.
|
|
137
|
+
- Use `node np-tools.cjs phase next-decimal 999 --raw` for the
|
|
138
|
+
preview number ONLY. The authoritative number comes from
|
|
139
|
+
`addBacklogEntry`'s return value (re-computed inside the lock).
|
|
140
|
+
- Commit ROADMAP.md + roadmap.yaml + phase-dir `.gitkeep` together
|
|
141
|
+
as a single atomic unit per ADR-0004.
|
|
142
|
+
- Route the commit through `node np-tools.cjs commit` for
|
|
143
|
+
`lib/git.cjs.assertCommittablePaths()` validation.
|
|
144
|
+
- Confirm via `askuser` Pattern S-3 before the mutation — the
|
|
145
|
+
roadmap.yaml write is visible in git history forever.
|
|
146
|
+
|
|
147
|
+
**Don't:**
|
|
148
|
+
- Hand-edit ROADMAP.md. The synthetic backlog milestone renders via
|
|
149
|
+
`lib/roadmap-render.cjs` (Plan 10-01-T05); direct edits will be
|
|
150
|
+
overwritten on the next render pass.
|
|
151
|
+
- Use the preview number as the final commit subject. A concurrent
|
|
152
|
+
`/np:add-backlog` may race and claim the same number; only the
|
|
153
|
+
lock-returned `BACKLOG_NUMBER` is authoritative.
|
|
154
|
+
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
155
|
+
in `bin/check-workflows.cjs` blocks them) — always route through
|
|
156
|
+
`node np-tools.cjs askuser --json '…'`.
|
|
157
|
+
- Add a `metrics record` block. There is no Task/Spawn site here;
|
|
158
|
+
Pitfall 9 / `workflow-missing-metrics` is exempt.
|
|
159
|
+
</scope_guardrail>
|
|
160
|
+
|
|
161
|
+
## Output
|
|
162
|
+
|
|
163
|
+
- `.nubos-pilot/ROADMAP.md` — updated via
|
|
164
|
+
`lib/roadmap-render.cjs` to include the new 999.X entry under
|
|
165
|
+
the synthetic `## Backlog` H2 section (Plan 10-01-T05).
|
|
166
|
+
- `.nubos-pilot/roadmap.yaml` — canonical source-of-truth with the
|
|
167
|
+
new phase appended to the `backlog` milestone's `phases:` array.
|
|
168
|
+
- `.nubos-pilot/phases/999.X-<slug>/.gitkeep` — empty stub so
|
|
169
|
+
subsequent `/np:discuss-phase 999.X` invocations have a working
|
|
170
|
+
directory.
|
|
171
|
+
- One atomic git commit
|
|
172
|
+
`docs(10): add backlog item 999.X — <title>` containing the three
|
|
173
|
+
files above (ADR-0004).
|
|
174
|
+
|
|
175
|
+
## Success Criteria
|
|
176
|
+
|
|
177
|
+
- [ ] Title validated (non-empty) before any roadmap read.
|
|
178
|
+
- [ ] Preview number generated via
|
|
179
|
+
`node np-tools.cjs phase next-decimal 999 --raw` — info only.
|
|
180
|
+
- [ ] Confirmation via `askuser` Pattern S-3 before mutation.
|
|
181
|
+
- [ ] Authoritative 999.X comes from
|
|
182
|
+
`lib/roadmap.cjs.addBacklogEntry` return value (NOT the
|
|
183
|
+
preview number).
|
|
184
|
+
- [ ] Phase directory created at
|
|
185
|
+
`${STATE_DIR}/phases/${BACKLOG_NUMBER}-${BACKLOG_SLUG}/` with
|
|
186
|
+
`.gitkeep` stub.
|
|
187
|
+
- [ ] Single atomic commit via `np-tools.cjs commit` containing
|
|
188
|
+
ROADMAP.md + roadmap.yaml + `.gitkeep`.
|
|
189
|
+
- [ ] Lint clean under `bin/check-workflows.cjs` — no BARE_ASKUSER
|
|
190
|
+
violations and no DIRECT_READ pattern matches for the project
|
|
191
|
+
state directory.
|
|
192
|
+
|
|
193
|
+
## Related Workflows
|
|
194
|
+
|
|
195
|
+
- **`/np:add-todo <title>`** — smaller-scope pending todo capture
|
|
196
|
+
with STATE.md counter increment. Use when the idea is actionable
|
|
197
|
+
within a current plan.
|
|
198
|
+
- **`/np:note [--global] <text>`** — zero-friction free-form capture
|
|
199
|
+
with no ROADMAP mutation. Use when the idea isn't yet scoped.
|
|
200
|
+
- **`/np:discuss-phase 999.X`** — explore a backlog item
|
|
201
|
+
interactively to graduate it from parking-lot to active planning.
|
|
202
|
+
- **`/np:plan-phase 999.X`** — produce a CONTEXT/RESEARCH/PLAN stack
|
|
203
|
+
for a backlog item once it is ready for implementation.
|
|
204
|
+
|
|
205
|
+
## Design Notes
|
|
206
|
+
|
|
207
|
+
Numbering + roadmap mutation run through
|
|
208
|
+
`lib/roadmap.cjs.addBacklogEntry` (Plan 10-01-T05). The lib-level
|
|
209
|
+
helper is file-locked and touches both the canonical `roadmap.yaml`
|
|
210
|
+
AND the rendered ROADMAP.md atomically — ROADMAP.md is rendered
|
|
211
|
+
output, not source-of-truth. The `.gitkeep` phase-dir stub keeps the
|
|
212
|
+
working directory legible before planning lands.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:add-tests
|
|
3
|
+
description: Persist Pass-SCs from VERIFICATION.md as node:test UAT blocks in test/uat/phase-<padded>-<slug>.test.cjs. Sentinel-preserving (D-20, Pitfall 8).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# /np:add-tests
|
|
7
|
+
|
|
8
|
+
<objective>
|
|
9
|
+
After `/np:verify-work` emits VERIFICATION.md with SC classifications,
|
|
10
|
+
convert each Pass-SC into a runnable `node:test` case as a UAT regression
|
|
11
|
+
suite. User-authored tests outside the `>>> np:add-tests begin … <<< end`
|
|
12
|
+
sentinels survive regeneration.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
## Initialize
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
PHASE="$1"
|
|
19
|
+
INIT=$(node np-tools.cjs init add-tests "$PHASE")
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Parse: `phase`, `target_path`, `verification_path`, `pass_cases[]`,
|
|
23
|
+
`skip_cases[]`. Target path is
|
|
24
|
+
`<pkgRoot>/test/uat/phase-<padded>-<slug>.test.cjs`.
|
|
25
|
+
|
|
26
|
+
## Execution
|
|
27
|
+
|
|
28
|
+
Emit/merge the Sentinel block:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
node np-tools.cjs init add-tests emit "$PHASE"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Smoke-run the generated file to catch syntax errors early:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
node --test "$(echo "$INIT" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).target_path))")"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Meta-commit
|
|
41
|
+
|
|
42
|
+
UAT tests are a PHASE artifact, not a TASK artifact, so ADR-0004
|
|
43
|
+
atomic-per-task does not apply — per D-19 this is a phase-level meta
|
|
44
|
+
commit. Scope it tightly to the UAT file only (never `git add .`):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
TARGET=$(echo "$INIT" | node -e "process.stdin.on('data', d => console.log(JSON.parse(d).target_path))")
|
|
48
|
+
git add "$TARGET"
|
|
49
|
+
git commit -m "docs(${PHASE}): persist UAT from verification"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Scope Guardrail
|
|
53
|
+
|
|
54
|
+
**Do:**
|
|
55
|
+
- Render only the sentinel-bounded block; preserve everything outside.
|
|
56
|
+
- Use `test.skip(..., { todo: ... })` for Fail/Defer cases so the suite
|
|
57
|
+
tracks them without failing CI.
|
|
58
|
+
- `git add <target>` — single explicit path.
|
|
59
|
+
|
|
60
|
+
**Don't:**
|
|
61
|
+
- Overwrite user-authored tests outside the sentinels.
|
|
62
|
+
- Commit the VERIFICATION.md and the UAT file together (separate commits;
|
|
63
|
+
VERIFICATION.md is committed by `/np:verify-work`).
|
|
64
|
+
|
|
65
|
+
## Output
|
|
66
|
+
|
|
67
|
+
- `test/uat/phase-<padded>-<slug>.test.cjs` with the sentinel-bounded
|
|
68
|
+
block updated.
|
|
69
|
+
- Meta-commit `docs(<padded>): persist UAT from verification`.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:add-todo
|
|
3
|
+
description: Capture a pending todo to .nubos-pilot/todos/pending/YYYY-MM-DD-<slug>.md; increments STATE.md pending_todos count via lib/state.cjs.mutateState single-writer lock. One atomic docs commit. No agent spawn.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:add-todo
|
|
7
|
+
|
|
8
|
+
Implements UTIL-05a. Captures a free-form idea, task, or issue that
|
|
9
|
+
surfaces mid-session as a structured
|
|
10
|
+
pending todo so the originating workflow can continue without losing
|
|
11
|
+
context. The todo lives under `.nubos-pilot/todos/pending/` and the
|
|
12
|
+
pending-todo counter in STATE.md is bumped via the single-writer lock
|
|
13
|
+
in `lib/state.cjs.mutateState` (D-20 invariant).
|
|
14
|
+
|
|
15
|
+
This is a pure-CRUD workflow — no agent spawn, no resolve-model, no
|
|
16
|
+
metrics record. The `workflow-missing-metrics` lint in
|
|
17
|
+
`bin/check-workflows.cjs` only fires on `Task(` / `Spawn agent=` sites,
|
|
18
|
+
so CRUD-only workflows are exempt (Pitfall 9 resolution from
|
|
19
|
+
Plan 10-05). All interactive prompts route through
|
|
20
|
+
`node np-tools.cjs askuser --json` per INST-03.
|
|
21
|
+
|
|
22
|
+
## Initialize
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
DESCRIPTION="$*"
|
|
26
|
+
if [[ -z "$DESCRIPTION" ]]; then
|
|
27
|
+
echo "Usage: /np:add-todo <description>" >&2
|
|
28
|
+
exit 2
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
INIT=$(node np-tools.cjs init add-todo "$DESCRIPTION")
|
|
32
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
33
|
+
|
|
34
|
+
SLUG=$(echo "$INIT" | jq -r '.slug')
|
|
35
|
+
DATE=$(echo "$INIT" | jq -r '.date')
|
|
36
|
+
TIMESTAMP=$(echo "$INIT" | jq -r '.timestamp')
|
|
37
|
+
PENDING_DIR=$(echo "$INIT" | jq -r '.pending_dir')
|
|
38
|
+
STATE_PATH=$(echo "$INIT" | jq -r '.state_path')
|
|
39
|
+
TODO_PATH="${PENDING_DIR}/${DATE}-${SLUG}.md"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Extract from init JSON: `commit_docs`, `date`, `timestamp`, `slug`,
|
|
43
|
+
`todo_count`, `todos_dir_exists`, `pending_dir`, `state_path`. The
|
|
44
|
+
init handler sanitises the slug through `lib/phase.cjs.phaseSlug`
|
|
45
|
+
(strips to `[a-z0-9-]` only; T-10-05-01 filename-injection
|
|
46
|
+
mitigation) and validates the description length (<= 500 chars) before
|
|
47
|
+
any filesystem write occurs.
|
|
48
|
+
|
|
49
|
+
## Create Pending Dir
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
mkdir -p "$PENDING_DIR"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The directory is created idempotently; no-op if it already exists.
|
|
56
|
+
|
|
57
|
+
## Duplicate Check
|
|
58
|
+
|
|
59
|
+
If a todo with this `DATE-SLUG` already exists in `pending/`,
|
|
60
|
+
let the user resolve the collision via `askuser` Pattern S-3. The
|
|
61
|
+
prompt surfaces four options: re-run (overwrite), view existing,
|
|
62
|
+
skip (keep both), or rename-with-counter (append `-2`, `-3`, etc.).
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
if [[ -f "$TODO_PATH" ]]; then
|
|
66
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
67
|
+
"type": "select",
|
|
68
|
+
"header": "Duplicate todo",
|
|
69
|
+
"question": "A todo already exists at '"${TODO_PATH}"'. What would you like to do?",
|
|
70
|
+
"options": [
|
|
71
|
+
{"label": "Re-run — overwrite existing todo", "description": "Replaces the current todo body."},
|
|
72
|
+
{"label": "View — display the existing todo and exit", "description": "No changes."},
|
|
73
|
+
{"label": "Skip — keep existing and exit", "description": "Leaves the file untouched."},
|
|
74
|
+
{"label": "Rename — append -2/-3 counter to filename", "description": "Writes a new file beside the existing one."}
|
|
75
|
+
]
|
|
76
|
+
}')
|
|
77
|
+
case "$CHOICE" in
|
|
78
|
+
"View"*) cat "$TODO_PATH"; exit 0 ;;
|
|
79
|
+
"Skip"*) exit 0 ;;
|
|
80
|
+
"Rename"*)
|
|
81
|
+
i=2
|
|
82
|
+
while [[ -f "${PENDING_DIR}/${DATE}-${SLUG}-${i}.md" ]]; do i=$((i + 1)); done
|
|
83
|
+
TODO_PATH="${PENDING_DIR}/${DATE}-${SLUG}-${i}.md"
|
|
84
|
+
;;
|
|
85
|
+
esac
|
|
86
|
+
fi
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Write Todo File
|
|
90
|
+
|
|
91
|
+
Use the `Write` tool (not a bash heredoc) to create `$TODO_PATH` with
|
|
92
|
+
the following frontmatter + body. The agent invokes the `Write` tool
|
|
93
|
+
directly — this is documented here as the contract, not executed as a
|
|
94
|
+
shell step.
|
|
95
|
+
|
|
96
|
+
```markdown
|
|
97
|
+
---
|
|
98
|
+
title_short: <first 100 chars of DESCRIPTION, single line>
|
|
99
|
+
created: <TIMESTAMP>
|
|
100
|
+
status: pending
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
<DESCRIPTION>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Specifically: `title_short` = the first 100 chars of `$DESCRIPTION`
|
|
107
|
+
flattened to a single line (newlines replaced with spaces) so the
|
|
108
|
+
frontmatter stays parseable even when the raw description contains
|
|
109
|
+
YAML metacharacters or multiple lines, `created` = `$TIMESTAMP`
|
|
110
|
+
(init-supplied ISO-8601), `status` always `pending`. The body carries
|
|
111
|
+
the full raw description verbatim so the file is self-contained when
|
|
112
|
+
read weeks later. This mirrors the `note.md` pattern (truncated
|
|
113
|
+
frontmatter field + full body) and pairs with the
|
|
114
|
+
`add-todo-invalid-description` YAML-separator guard in
|
|
115
|
+
`bin/np-tools/add-todo.cjs._buildPayload`. Do **not** include
|
|
116
|
+
`status: completed` or any other status here — the completion flow
|
|
117
|
+
lives in a separate workflow.
|
|
118
|
+
|
|
119
|
+
## Update STATE.md
|
|
120
|
+
|
|
121
|
+
STATE.md is mutated through `lib/state.cjs.mutateState` which wraps
|
|
122
|
+
`withFileLock` (D-20 single-writer invariant, T-10-05-06 mitigation).
|
|
123
|
+
The node one-liner is the sanctioned surface; direct filesystem
|
|
124
|
+
reads of the project state directory from this workflow would bypass
|
|
125
|
+
the lock and are explicitly forbidden by the check-workflows lint.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
node -e "require('./lib/state.cjs').mutateState(function (doc) { doc.frontmatter.pending_todos = (doc.frontmatter.pending_todos || 0) + 1; return doc; });"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The mutator increments the `pending_todos` counter on the STATE.md
|
|
132
|
+
frontmatter. The lock serialises concurrent writers (two parallel
|
|
133
|
+
`/np:add-todo` invocations converge on the correct count).
|
|
134
|
+
|
|
135
|
+
## Commit
|
|
136
|
+
|
|
137
|
+
Route through `node np-tools.cjs commit` so
|
|
138
|
+
`lib/git.cjs.assertCommittablePaths()` validates the paths before
|
|
139
|
+
`git add` (path-traversal guard from Plan 10-01-T04).
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
node np-tools.cjs commit "docs(10): add todo — ${SLUG}" --files "$TODO_PATH" "$STATE_PATH"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Both the new todo file and STATE.md land in a single atomic commit per
|
|
146
|
+
ADR-0004 (one commit per unit).
|
|
147
|
+
|
|
148
|
+
## Report
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
Todo saved: $TODO_PATH
|
|
152
|
+
|
|
153
|
+
Title: $DESCRIPTION
|
|
154
|
+
Status: pending
|
|
155
|
+
Created: $TIMESTAMP
|
|
156
|
+
|
|
157
|
+
Pending todo count bumped via lib/state.cjs.mutateState.
|
|
158
|
+
Use /np:next to surface this todo in the next-step picker.
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Scope Guardrail
|
|
162
|
+
|
|
163
|
+
<scope_guardrail>
|
|
164
|
+
**Do:**
|
|
165
|
+
- Always go through `lib/state.cjs.mutateState` for STATE.md updates
|
|
166
|
+
(D-20 single-writer lock; T-10-05-06 mitigation).
|
|
167
|
+
- Use the `Write` tool for the new markdown file — never a bash
|
|
168
|
+
heredoc or `echo >`.
|
|
169
|
+
- Route the final commit through `node np-tools.cjs commit` so
|
|
170
|
+
`lib/git.cjs.assertCommittablePaths()` runs the gitignore-guard.
|
|
171
|
+
- Derive the slug via `node np-tools.cjs init add-todo` (filename
|
|
172
|
+
sanitisation, T-10-05-01 mitigation) — not via ad-hoc `sed`.
|
|
173
|
+
- Commit todo file + STATE.md together as a single atomic unit.
|
|
174
|
+
|
|
175
|
+
**Don't:**
|
|
176
|
+
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint in
|
|
177
|
+
`bin/check-workflows.cjs` blocks them) — always route through
|
|
178
|
+
`node np-tools.cjs askuser --json '…'`.
|
|
179
|
+
- Read STATE.md via raw filesystem calls (DIRECT_READ lint blocks
|
|
180
|
+
those patterns) — let `mutateState` handle the lock.
|
|
181
|
+
- Add a `metrics record` block. There is no Task/Spawn site in this
|
|
182
|
+
workflow, so Pitfall 9 / the `workflow-missing-metrics` lint is
|
|
183
|
+
exempt.
|
|
184
|
+
- Touch the completed-todos subtree — completion is a separate
|
|
185
|
+
workflow concern.
|
|
186
|
+
</scope_guardrail>
|
|
187
|
+
|
|
188
|
+
## Output
|
|
189
|
+
|
|
190
|
+
- `.nubos-pilot/todos/pending/YYYY-MM-DD-<slug>.md` — new todo file
|
|
191
|
+
with `title / created / status: pending` frontmatter and the
|
|
192
|
+
description as body text.
|
|
193
|
+
- `.nubos-pilot/STATE.md` — `pending_todos` frontmatter counter
|
|
194
|
+
incremented via `mutateState`.
|
|
195
|
+
- One atomic git commit `docs(10): add todo — <slug>` containing
|
|
196
|
+
both files (ADR-0004).
|
|
197
|
+
|
|
198
|
+
## Success Criteria
|
|
199
|
+
|
|
200
|
+
- [ ] Description validated (non-empty, <= 500 chars) via the init
|
|
201
|
+
handler before any filesystem write.
|
|
202
|
+
- [ ] Slug derived via `phaseSlug` so only `[a-z0-9-]` enter the
|
|
203
|
+
filename (T-10-05-01 mitigation).
|
|
204
|
+
- [ ] Pending todo directory created idempotently.
|
|
205
|
+
- [ ] Duplicate collisions resolved via `askuser` Pattern S-3
|
|
206
|
+
(Re-run / View / Skip / Rename-with-counter).
|
|
207
|
+
- [ ] Todo file written via the `Write` tool with valid frontmatter.
|
|
208
|
+
- [ ] STATE.md `pending_todos` counter incremented via
|
|
209
|
+
`lib/state.cjs.mutateState` (D-20 single-writer lock).
|
|
210
|
+
- [ ] Both files committed atomically via `np-tools.cjs commit`.
|
|
211
|
+
- [ ] Lint clean under `bin/check-workflows.cjs` — no BARE_ASKUSER
|
|
212
|
+
violations and no DIRECT_READ pattern matches for the project
|
|
213
|
+
state directory.
|
|
214
|
+
|
|
215
|
+
## Related Workflows
|
|
216
|
+
|
|
217
|
+
- **`/np:note <text>`** — zero-friction free-form capture (no STATE
|
|
218
|
+
mutation, no todo semantics). Use when the idea isn't yet actionable.
|
|
219
|
+
- **`/np:add-backlog <title>`** — larger-scope capture for ideas that
|
|
220
|
+
deserve a full backlog phase (`999.x` in ROADMAP.md).
|
|
221
|
+
- **`/np:next`** — surfaces the next actionable item; a pending todo
|
|
222
|
+
can be the pointer when no active plan has a runnable task.
|