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,214 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:thread
|
|
3
|
+
description: Create or resume a cross-session thread at .nubos-pilot/threads/<slug>.md. Lifecycle status OPEN → IN_PROGRESS (auto on resume) → RESOLVED (user edits manually, no close command per D-19 Claude's Discretion). No agent spawn. Project-scope only.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:thread
|
|
7
|
+
|
|
8
|
+
Implements UTIL-06. Threads are lightweight cross-session context
|
|
9
|
+
stores for work spanning multiple sessions but not belonging to a
|
|
10
|
+
specific phase. They live under `.nubos-pilot/threads/<slug>.md` with
|
|
11
|
+
lifecycle `OPEN → IN_PROGRESS → RESOLVED` in their frontmatter.
|
|
12
|
+
|
|
13
|
+
Two modes, selected by presence of the target file:
|
|
14
|
+
|
|
15
|
+
- **create** — writes a fresh file with `status: OPEN`; one atomic
|
|
16
|
+
docs commit (ADR-0004).
|
|
17
|
+
- **resume** — reads the file, bumps `status: OPEN → IN_PROGRESS`
|
|
18
|
+
(never downgraded), updates `last_resumed`, displays content.
|
|
19
|
+
Resume does **not** commit — `last_resumed` churn is too noisy.
|
|
20
|
+
|
|
21
|
+
No close command (D-19). User manually sets `status: RESOLVED`.
|
|
22
|
+
Pure-CRUD — no agent spawn, no metrics record (Pitfall 9 exempt).
|
|
23
|
+
|
|
24
|
+
## Initialize
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
SLUG_ARG="$*"
|
|
28
|
+
if [[ -z "$SLUG_ARG" ]]; then
|
|
29
|
+
echo "Usage: /np:thread <slug-or-title>" >&2
|
|
30
|
+
exit 2
|
|
31
|
+
fi
|
|
32
|
+
SLUG=$(node np-tools.cjs generate-slug "$SLUG_ARG" --raw)
|
|
33
|
+
if [[ -z "$SLUG" ]]; then
|
|
34
|
+
echo "Error: argument produced no slug-safe characters." >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
STATE_DIR=$(node -e "console.log(require('./lib/core.cjs').projectStateDir(process.cwd()))")
|
|
38
|
+
THREADS_DIR="${STATE_DIR}/threads"
|
|
39
|
+
THREAD_PATH="${THREADS_DIR}/${SLUG}.md"
|
|
40
|
+
TODAY=$(date +%Y-%m-%d)
|
|
41
|
+
mkdir -p "$THREADS_DIR"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Slug via `generate-slug` (wraps `lib/phase.cjs.phaseSlug`) — only
|
|
45
|
+
`[a-z0-9-]` enters the filename; closes T-10-06-01 (path traversal).
|
|
46
|
+
|
|
47
|
+
## Create vs Resume Branch
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
if [[ -f "$THREAD_PATH" ]]; then
|
|
51
|
+
MODE="resume"
|
|
52
|
+
else
|
|
53
|
+
MODE="create"
|
|
54
|
+
fi
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Create Branch (MODE = create)
|
|
58
|
+
|
|
59
|
+
Use the `Write` tool to create `$THREAD_PATH` with the frontmatter +
|
|
60
|
+
body template below (not a bash heredoc). `${SLUG}` / `${SLUG_ARG}` /
|
|
61
|
+
`${TODAY}` are substituted from the variables above.
|
|
62
|
+
|
|
63
|
+
```markdown
|
|
64
|
+
---
|
|
65
|
+
slug: <SLUG>
|
|
66
|
+
status: OPEN
|
|
67
|
+
created: <TODAY>
|
|
68
|
+
last_resumed: <TODAY>
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
# Thread: <SLUG_ARG>
|
|
72
|
+
|
|
73
|
+
## Status: OPEN
|
|
74
|
+
|
|
75
|
+
## Goal
|
|
76
|
+
|
|
77
|
+
<TBD — user fills in>
|
|
78
|
+
|
|
79
|
+
## Context
|
|
80
|
+
|
|
81
|
+
*Created from conversation on <TODAY>.*
|
|
82
|
+
|
|
83
|
+
## References
|
|
84
|
+
|
|
85
|
+
- *(add links, file paths, or issue numbers)*
|
|
86
|
+
|
|
87
|
+
## Next Steps
|
|
88
|
+
|
|
89
|
+
- *(what the next session should do first)*
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Route the commit through `node np-tools.cjs commit` so
|
|
93
|
+
`lib/git.cjs.assertCommittablePaths()` validates the path before
|
|
94
|
+
`git add` (path-traversal guard from Plan 10-01-T04).
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
if [[ "$MODE" == "create" ]]; then
|
|
98
|
+
node np-tools.cjs commit "docs(10): create thread — ${SLUG}" --files "$THREAD_PATH"
|
|
99
|
+
echo "Thread created: $THREAD_PATH"
|
|
100
|
+
echo ""
|
|
101
|
+
echo "Resume anytime with: /np:thread ${SLUG}"
|
|
102
|
+
fi
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Resume Branch (MODE = resume)
|
|
106
|
+
|
|
107
|
+
Two in-place updates via `lib/core.cjs.atomicWriteFileSync`
|
|
108
|
+
(ADR-0004 crash-safety):
|
|
109
|
+
|
|
110
|
+
1. If current `status === "OPEN"`, bump to `IN_PROGRESS`. Status is
|
|
111
|
+
**never downgraded**: `IN_PROGRESS` / `RESOLVED` remain as-is.
|
|
112
|
+
2. `last_resumed: <TODAY>` — always refreshed.
|
|
113
|
+
|
|
114
|
+
Frontmatter parsed via `lib/frontmatter.cjs.extractFrontmatter` (read)
|
|
115
|
+
and re-serialised via a hand-rolled minimal FM writer (the lib ships
|
|
116
|
+
a reader only) that emits one `key: value` per field in insertion
|
|
117
|
+
order.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
if [[ "$MODE" == "resume" ]]; then
|
|
121
|
+
node -e "
|
|
122
|
+
const fs = require('node:fs');
|
|
123
|
+
const { extractFrontmatter } = require('./lib/frontmatter.cjs');
|
|
124
|
+
const { atomicWriteFileSync } = require('./lib/core.cjs');
|
|
125
|
+
const p = process.argv[1];
|
|
126
|
+
const today = process.argv[2];
|
|
127
|
+
const raw = fs.readFileSync(p, 'utf-8');
|
|
128
|
+
const { frontmatter, body } = extractFrontmatter(raw);
|
|
129
|
+
const next = Object.assign({}, frontmatter);
|
|
130
|
+
const cur = String(next.status || 'OPEN');
|
|
131
|
+
if (cur === 'OPEN') next.status = 'IN_PROGRESS';
|
|
132
|
+
next.last_resumed = today;
|
|
133
|
+
const order = ['slug', 'status', 'created', 'last_resumed'];
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
const lines = ['---'];
|
|
136
|
+
for (const k of order) {
|
|
137
|
+
if (k in next) { lines.push(k + ': ' + next[k]); seen.add(k); }
|
|
138
|
+
}
|
|
139
|
+
for (const k of Object.keys(next)) {
|
|
140
|
+
if (!seen.has(k)) lines.push(k + ': ' + next[k]);
|
|
141
|
+
}
|
|
142
|
+
lines.push('---');
|
|
143
|
+
const out = lines.join('\n') + '\n' + body;
|
|
144
|
+
atomicWriteFileSync(p, out);
|
|
145
|
+
" "$THREAD_PATH" "$TODAY"
|
|
146
|
+
echo "Thread resumed: $THREAD_PATH"
|
|
147
|
+
echo ""
|
|
148
|
+
echo "--- thread content ---"
|
|
149
|
+
node -e "process.stdout.write(require('node:fs').readFileSync(process.argv[1], 'utf-8'))" "$THREAD_PATH"
|
|
150
|
+
fi
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Resume never commits. `last_resumed` churn would flood the log.
|
|
154
|
+
|
|
155
|
+
## Report
|
|
156
|
+
|
|
157
|
+
Echo `Thread <MODE>d: <THREAD_PATH>` with slug/mode/today to stdout.
|
|
158
|
+
|
|
159
|
+
## Scope Guardrail
|
|
160
|
+
|
|
161
|
+
<scope_guardrail>
|
|
162
|
+
**Do:**
|
|
163
|
+
- Use `phaseSlug`-generated slug (T-10-06-01 mitigation).
|
|
164
|
+
- Preserve status monotonicity on resume: `OPEN → IN_PROGRESS` only.
|
|
165
|
+
- Let the user manually flip `status: RESOLVED` (D-19 — no close
|
|
166
|
+
command in this adapted port).
|
|
167
|
+
- Use `lib/core.cjs.atomicWriteFileSync` for any in-place rewrite
|
|
168
|
+
(ADR-0004 crash-safety).
|
|
169
|
+
- Route the create-branch commit through `node np-tools.cjs commit`.
|
|
170
|
+
|
|
171
|
+
**Don't:**
|
|
172
|
+
- Commit `last_resumed`-only updates. Resume is commit-free.
|
|
173
|
+
- Invoke host-specific prompt tools directly (the BARE_ASKUSER lint
|
|
174
|
+
in `bin/check-workflows.cjs` blocks them) — route through
|
|
175
|
+
`node np-tools.cjs askuser --json '…'`.
|
|
176
|
+
- Bypass `atomicWriteFileSync` — rename pair is the invariant.
|
|
177
|
+
- Add a `metrics record` block. No Task/Spawn site here; Pitfall 9 /
|
|
178
|
+
`workflow-missing-metrics` is exempt.
|
|
179
|
+
</scope_guardrail>
|
|
180
|
+
|
|
181
|
+
## Output
|
|
182
|
+
|
|
183
|
+
- `.nubos-pilot/threads/<slug>.md` — thread file. Create mode writes
|
|
184
|
+
a new file with four-field frontmatter (`slug / status:OPEN /
|
|
185
|
+
created / last_resumed`) and four-section body. Resume mode
|
|
186
|
+
updates in-place: `status: IN_PROGRESS` (if OPEN) + refreshed
|
|
187
|
+
`last_resumed`.
|
|
188
|
+
- **Create mode only:** one atomic commit
|
|
189
|
+
`docs(10): create thread — <slug>` (ADR-0004).
|
|
190
|
+
- **Resume mode:** no commit.
|
|
191
|
+
|
|
192
|
+
## Success Criteria
|
|
193
|
+
|
|
194
|
+
- [ ] Slug via `generate-slug` (T-10-06-01 mitigation).
|
|
195
|
+
- [ ] Threads dir via `lib/core.cjs.projectStateDir`.
|
|
196
|
+
- [ ] Mode selected by `[[ -f $THREAD_PATH ]]`.
|
|
197
|
+
- [ ] Create: `Write` tool + `np-tools.cjs commit` atomic unit.
|
|
198
|
+
- [ ] Resume: `extractFrontmatter` round-trip;
|
|
199
|
+
`OPEN → IN_PROGRESS` only; `last_resumed` refreshed.
|
|
200
|
+
- [ ] Resume writes via `atomicWriteFileSync`; no commit.
|
|
201
|
+
- [ ] Lint clean under `bin/check-workflows.cjs` — no BARE_ASKUSER
|
|
202
|
+
violations, no DIRECT_READ matches.
|
|
203
|
+
|
|
204
|
+
## Related Workflows
|
|
205
|
+
|
|
206
|
+
- **`/np:add-todo <title>`** — smaller-scope pending todo capture.
|
|
207
|
+
- **`/np:note [--global] <text>`** — zero-friction free-form capture.
|
|
208
|
+
- **`/np:add-backlog <title>`** — promote a thread to a backlog entry.
|
|
209
|
+
|
|
210
|
+
## Design Notes
|
|
211
|
+
|
|
212
|
+
No list-all mode (no-arg invocation errors). Threads live under
|
|
213
|
+
`.nubos-pilot/threads/` per D-14. Lifecycle frontmatter is the
|
|
214
|
+
machine-readable source-of-truth (no free-text heading parsing).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# np:triage
|
|
2
|
+
|
|
3
|
+
Interactive reviewer that walks the unified queue (see `np:queue`) item-by-item.
|
|
4
|
+
For each item, prompts `promote-to-todo | promote-to-phase | keep | drop`.
|
|
5
|
+
Non-TTY runs default to `keep` — safe in CI.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
node np-tools.cjs triage "$@"
|
|
9
|
+
```
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:ui-phase
|
|
3
|
+
description: Generate UI-SPEC.md for frontend phases via 2-agent revision loop (np-ui-researcher → np-ui-checker) with max 2 iterations and a PASS/FLAG/BLOCK verdict gate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:ui-phase
|
|
7
|
+
|
|
8
|
+
Produces `{phase_dir}/{padded}-UI-SPEC.md` via a researcher → checker
|
|
9
|
+
revision loop (max 2 iterations). Inserts between `/np:discuss-phase` and
|
|
10
|
+
`/np:plan-phase` for UI-heavy phases. Locks the six visual pillars
|
|
11
|
+
(spacing, typography, color, copywriting, design-system, components)
|
|
12
|
+
BEFORE the planner creates tasks so execution stays on-brand.
|
|
13
|
+
|
|
14
|
+
Every Task-spawn site is wrapped in the Plan 09-05 metrics + resolve-model
|
|
15
|
+
pattern (D-06, D-01). `RUNTIME` is detected once at the top of the bash
|
|
16
|
+
block and re-used by every `metrics record` call.
|
|
17
|
+
|
|
18
|
+
## Initialize
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
PHASE="$1"
|
|
22
|
+
if [[ -z "$PHASE" ]]; then
|
|
23
|
+
echo "Usage: /np:ui-phase <phase-number>" >&2
|
|
24
|
+
exit 2
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
INIT=$(node np-tools.cjs init ui-phase "$PHASE")
|
|
28
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
29
|
+
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Parse JSON for: `phase`, `padded`, `phase_dir`, `ui_spec_path`,
|
|
33
|
+
`has_ui_spec`, `template_path`, `max_iterations`,
|
|
34
|
+
`agents.ui_researcher`, `agents.ui_checker`.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
PADDED=$(echo "$INIT" | jq -r '.padded')
|
|
38
|
+
PHASE_DIR=$(echo "$INIT" | jq -r '.phase_dir')
|
|
39
|
+
UI_SPEC_PATH=$(echo "$INIT" | jq -r '.ui_spec_path')
|
|
40
|
+
HAS_UI_SPEC=$(echo "$INIT" | jq -r '.has_ui_spec')
|
|
41
|
+
TEMPLATE_PATH=$(echo "$INIT" | jq -r '.template_path')
|
|
42
|
+
MAX_ITER=$(echo "$INIT" | jq -r '.max_iterations')
|
|
43
|
+
PLAN_ID="${PADDED}-ui"
|
|
44
|
+
TASK_ID="${PADDED}-ui"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Pre-Flight Gates
|
|
48
|
+
|
|
49
|
+
<pre_flight>
|
|
50
|
+
|
|
51
|
+
### Gate 1 — UI-SPEC.md already exists
|
|
52
|
+
|
|
53
|
+
If `has_ui_spec == true`:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
if [[ "$HAS_UI_SPEC" == "true" ]]; then
|
|
57
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
58
|
+
"type": "select",
|
|
59
|
+
"header": "Existing UI-SPEC",
|
|
60
|
+
"question": "UI-SPEC.md already exists for Phase '"$PHASE"'. What would you like to do?",
|
|
61
|
+
"options": [
|
|
62
|
+
{"label": "Update — re-run researcher with existing as baseline", "description": "Re-runs the researcher→checker loop against the current spec."},
|
|
63
|
+
{"label": "View — display current UI-SPEC and exit", "description": "Reads the file and exits without changes."},
|
|
64
|
+
{"label": "Skip — keep current UI-SPEC and exit", "description": "Leaves the file untouched."}
|
|
65
|
+
]
|
|
66
|
+
}')
|
|
67
|
+
case "$CHOICE" in
|
|
68
|
+
"View"*) cat "$UI_SPEC_PATH"; exit 0 ;;
|
|
69
|
+
"Skip"*) exit 0 ;;
|
|
70
|
+
esac
|
|
71
|
+
fi
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
</pre_flight>
|
|
75
|
+
|
|
76
|
+
## Philosophy
|
|
77
|
+
|
|
78
|
+
<philosophy>
|
|
79
|
+
UI-SPEC.md locks the six pillars most often under-specified in frontend
|
|
80
|
+
work: spacing scale (non-multiple-of-4 breaks grids), typography
|
|
81
|
+
(too many sizes or weights create visual noise), color (accent reserved
|
|
82
|
+
for "all interactive elements" defeats the 60/30/10 split), copywriting
|
|
83
|
+
(generic CTAs like "Submit" / "OK" ship as design debt), design-system
|
|
84
|
+
inventory (pull-once, re-use everywhere), and per-component contracts
|
|
85
|
+
(prop shape + a11y + state machine). Running this loop BEFORE
|
|
86
|
+
`/np:plan-phase` surfaces these decisions as an explicit artifact the
|
|
87
|
+
planner, executor, and ui-auditor can enforce.
|
|
88
|
+
</philosophy>
|
|
89
|
+
|
|
90
|
+
## Main Flow
|
|
91
|
+
|
|
92
|
+
The researcher and checker alternate for up to `$MAX_ITER` iterations.
|
|
93
|
+
Each iteration wraps both spawns in the Plan-09-05 metrics pattern.
|
|
94
|
+
The checker emits a structured JSON verdict with `overall_status` set
|
|
95
|
+
to `APPROVED` or `BLOCKED`; `BLOCKED` re-invokes the researcher with
|
|
96
|
+
the checker's issue list as feedback.
|
|
97
|
+
|
|
98
|
+
### Step 0 — Initialize UI-SPEC.md from template
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
if [[ "$HAS_UI_SPEC" != "true" ]]; then
|
|
102
|
+
cp "$TEMPLATE_PATH" "$UI_SPEC_PATH"
|
|
103
|
+
fi
|
|
104
|
+
ITER=0
|
|
105
|
+
VERDICT_PATH="${PHASE_DIR}/${PADDED}-ui-checker-verdict.json"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Revision Loop
|
|
109
|
+
|
|
110
|
+
> NOTE: Serial per iteration. The researcher writes UI-SPEC.md; the
|
|
111
|
+
> checker reads it and emits a verdict. On `BLOCKED`, loop with the
|
|
112
|
+
> verdict as feedback. On `APPROVED` or `$ITER >= $MAX_ITER`, exit.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
while [[ "$ITER" -lt "$MAX_ITER" ]]; do
|
|
116
|
+
ITER=$((ITER + 1))
|
|
117
|
+
ITER_TASK_ID="${TASK_ID}-iter-${ITER}"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Step 1 — UI researcher (np-ui-researcher, sonnet)
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
START=$(node np-tools.cjs metrics start-timestamp)
|
|
124
|
+
MODEL=$(node np-tools.cjs resolve-model np-ui-researcher --profile balanced)
|
|
125
|
+
> NOTE: Spawn agent=np-ui-researcher model=$MODEL
|
|
126
|
+
> NOTE: input: phase_number=$PHASE, ui_spec_path=$UI_SPEC_PATH, iteration=$ITER
|
|
127
|
+
> NOTE: on iter >= 2, also pass prior_verdict=$VERDICT_PATH as revision feedback
|
|
128
|
+
> NOTE: output: fully-populated UI-SPEC.md at $UI_SPEC_PATH
|
|
129
|
+
END=$(node np-tools.cjs metrics end-timestamp)
|
|
130
|
+
node np-tools.cjs metrics record \
|
|
131
|
+
--agent np-ui-researcher --tier sonnet --resolved-model "$MODEL" \
|
|
132
|
+
--phase "$PHASE" --plan "$PLAN_ID" --task "$ITER_TASK_ID" \
|
|
133
|
+
--started "$START" --ended "$END" \
|
|
134
|
+
--tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
|
|
135
|
+
--retry-count 0 --status ok --runtime "$RUNTIME"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### Step 2 — UI checker (np-ui-checker, haiku)
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
START=$(node np-tools.cjs metrics start-timestamp)
|
|
142
|
+
MODEL=$(node np-tools.cjs resolve-model np-ui-checker --profile balanced)
|
|
143
|
+
> NOTE: Spawn agent=np-ui-checker model=$MODEL
|
|
144
|
+
> NOTE: input: ui_spec_path=$UI_SPEC_PATH
|
|
145
|
+
> NOTE: output: structured JSON verdict written to $VERDICT_PATH
|
|
146
|
+
END=$(node np-tools.cjs metrics end-timestamp)
|
|
147
|
+
node np-tools.cjs metrics record \
|
|
148
|
+
--agent np-ui-checker --tier haiku --resolved-model "$MODEL" \
|
|
149
|
+
--phase "$PHASE" --plan "$PLAN_ID" --task "$ITER_TASK_ID" \
|
|
150
|
+
--started "$START" --ended "$END" \
|
|
151
|
+
--tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
|
|
152
|
+
--retry-count 0 --status ok --runtime "$RUNTIME"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Step 3 — Evaluate verdict
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
OVERALL=$(jq -r '.overall_status' "$VERDICT_PATH" 2>/dev/null || echo "BLOCKED")
|
|
159
|
+
VERDICT=$(jq -r '.verdict' "$VERDICT_PATH" 2>/dev/null || echo "BLOCK")
|
|
160
|
+
if [[ "$OVERALL" == "APPROVED" ]]; then
|
|
161
|
+
break
|
|
162
|
+
fi
|
|
163
|
+
done
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Validation Gate
|
|
167
|
+
|
|
168
|
+
After the loop, inspect the final verdict. If still `BLOCKED` after
|
|
169
|
+
`$MAX_ITER` iterations, ask the user to accept with warnings, revise
|
|
170
|
+
manually, or abort. If `APPROVED`, update UI-SPEC.md frontmatter to
|
|
171
|
+
`status: approved` with a review timestamp.
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
OVERALL=$(jq -r '.overall_status' "$VERDICT_PATH" 2>/dev/null || echo "BLOCKED")
|
|
175
|
+
|
|
176
|
+
if [[ "$OVERALL" == "BLOCKED" ]]; then
|
|
177
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
178
|
+
"type": "select",
|
|
179
|
+
"header": "UI-SPEC still BLOCKED after max iterations",
|
|
180
|
+
"question": "The checker still returns BLOCKED. What would you like to do?",
|
|
181
|
+
"options": [
|
|
182
|
+
{"label": "Accept with warnings", "description": "Proceed; unresolved issues are noted in the commit message."},
|
|
183
|
+
{"label": "Revise manually", "description": "Exit so you can edit UI-SPEC.md by hand."},
|
|
184
|
+
{"label": "Abort", "description": "Exit without committing."}
|
|
185
|
+
]
|
|
186
|
+
}')
|
|
187
|
+
case "$CHOICE" in
|
|
188
|
+
"Abort") exit 1 ;;
|
|
189
|
+
"Revise manually") exit 0 ;;
|
|
190
|
+
esac
|
|
191
|
+
else
|
|
192
|
+
REVIEWED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
193
|
+
node np-tools.cjs frontmatter-set "$UI_SPEC_PATH" status approved
|
|
194
|
+
node np-tools.cjs frontmatter-set "$UI_SPEC_PATH" reviewed_at "$REVIEWED_AT"
|
|
195
|
+
fi
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
> NOTE: `frontmatter-set` is the standard nubos-pilot frontmatter editor;
|
|
199
|
+
> if unavailable, use an equivalent in-place sed/Write pattern per the
|
|
200
|
+
> adapted-port invariant (no direct host-tool edits).
|
|
201
|
+
|
|
202
|
+
## Commit
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
git add "$UI_SPEC_PATH"
|
|
206
|
+
git commit -m "docs(${PADDED}): generate UI-SPEC.md via 2-agent revision loop"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Scope Guardrail
|
|
210
|
+
|
|
211
|
+
<scope_guardrail>
|
|
212
|
+
**Do:**
|
|
213
|
+
- Run researcher and checker serially per iteration (max 2 iterations).
|
|
214
|
+
- Emit a metrics record AFTER every Task spawn (D-06).
|
|
215
|
+
- Resolve every MODEL via `np-tools.cjs resolve-model` — no hardcoded IDs.
|
|
216
|
+
- Use `np-tools.cjs askuser` for every prompt (Phase-3 INST-03 invariant).
|
|
217
|
+
- Commit the final UI-SPEC.md when the checker returns APPROVED or the
|
|
218
|
+
user accepts with warnings.
|
|
219
|
+
|
|
220
|
+
**Don't:**
|
|
221
|
+
- Invoke the host-specific prompt tool directly — always route through
|
|
222
|
+
`np-tools.cjs askuser`.
|
|
223
|
+
- Parallelize researcher + checker — the checker reads what the
|
|
224
|
+
researcher just wrote.
|
|
225
|
+
- Exceed `$MAX_ITER` iterations — the revision loop is bounded to
|
|
226
|
+
prevent runaway costs on stubborn BLOCKs.
|
|
227
|
+
- Call any tools binary other than `np-tools.cjs` (the sole CLI entry
|
|
228
|
+
per Plan 09-05 D-14).
|
|
229
|
+
- Reference legacy homedir payload paths — those directories do not
|
|
230
|
+
exist in nubos-pilot projects.
|
|
231
|
+
- Modify UI-SPEC.md from the checker agent — the checker is read-only
|
|
232
|
+
and the researcher owns writes.
|
|
233
|
+
- Skip any metrics record block — the Phase-10 np:stats consumer
|
|
234
|
+
expects one record per Task spawn.
|
|
235
|
+
</scope_guardrail>
|
|
236
|
+
|
|
237
|
+
## Output
|
|
238
|
+
|
|
239
|
+
- `{phase_dir}/{padded}-UI-SPEC.md` — filled-in UI design contract with
|
|
240
|
+
`status: approved` frontmatter when the checker passes.
|
|
241
|
+
- `{phase_dir}/{padded}-ui-checker-verdict.json` — last checker verdict
|
|
242
|
+
(JSON); retained for the planner and ui-auditor to consume.
|
|
243
|
+
- Up to 2 × 2 = 4 metrics records in
|
|
244
|
+
`.nubos-pilot/metrics/phase-${PHASE}.jsonl` (one per Task spawn per
|
|
245
|
+
iteration).
|
|
246
|
+
- One git commit (when APPROVED or user accepts with warnings).
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:ui-review
|
|
3
|
+
description: Retroactive 6-pillar visual audit of a completed phase. Spawns np-ui-auditor to score copywriting, visuals, color, typography, spacing, and experience design against UI-SPEC.md (if present) or abstract best-practice standards. Produces UI-REVIEW.md.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:ui-review
|
|
7
|
+
|
|
8
|
+
Produces `{phase_dir}/{padded}-UI-REVIEW.md` via a single `np-ui-auditor` spawn
|
|
9
|
+
that audits the phase's implemented frontend code. Runs AFTER
|
|
10
|
+
`/np:execute-phase` has landed code — the audit needs a SUMMARY.md to
|
|
11
|
+
know what was built.
|
|
12
|
+
|
|
13
|
+
Two modes:
|
|
14
|
+
|
|
15
|
+
- **Spec-conformance audit** — when `{padded}-UI-SPEC.md` exists (phase
|
|
16
|
+
went through `/np:ui-phase`). Pillars are scored against the declared
|
|
17
|
+
contract.
|
|
18
|
+
- **Retroactive general audit** — when no UI-SPEC is present. Pillars
|
|
19
|
+
are scored against abstract 6-pillar best-practice standards. The
|
|
20
|
+
output file header labels the mode explicitly (Pitfall 10 — avoids
|
|
21
|
+
silent drift between spec-backed and spec-less reviews).
|
|
22
|
+
|
|
23
|
+
The single Task-spawn site is wrapped in the Plan 09-05 metrics +
|
|
24
|
+
resolve-model pattern (D-06, D-01). `RUNTIME` is detected once at the
|
|
25
|
+
top of the bash block and re-used by the `metrics record` call.
|
|
26
|
+
|
|
27
|
+
## Initialize
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
PHASE="$1"
|
|
31
|
+
if [[ -z "$PHASE" ]]; then
|
|
32
|
+
echo "Usage: /np:ui-review <phase-number>" >&2
|
|
33
|
+
exit 2
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
INIT=$(node np-tools.cjs init ui-review "$PHASE")
|
|
37
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
38
|
+
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Parse JSON for: `phase`, `padded`, `phase_dir`, `ui_review_path`,
|
|
42
|
+
`summary_present`, `summary_path`, `ui_spec_path`, `has_ui_spec`,
|
|
43
|
+
`agents.ui_auditor`.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
PADDED=$(echo "$INIT" | jq -r '.padded')
|
|
47
|
+
PHASE_DIR=$(echo "$INIT" | jq -r '.phase_dir')
|
|
48
|
+
UI_REVIEW_PATH=$(echo "$INIT" | jq -r '.ui_review_path')
|
|
49
|
+
SUMMARY_PRESENT=$(echo "$INIT" | jq -r '.summary_present')
|
|
50
|
+
SUMMARY_PATH=$(echo "$INIT" | jq -r '.summary_path')
|
|
51
|
+
UI_SPEC_PATH=$(echo "$INIT" | jq -r '.ui_spec_path')
|
|
52
|
+
HAS_UI_SPEC=$(echo "$INIT" | jq -r '.has_ui_spec')
|
|
53
|
+
PLAN_ID="${PADDED}-ui-review"
|
|
54
|
+
TASK_ID="${PADDED}-ui-review"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Pre-Flight Gates
|
|
58
|
+
|
|
59
|
+
<pre_flight>
|
|
60
|
+
|
|
61
|
+
### Gate 1 — SUMMARY.md must exist
|
|
62
|
+
|
|
63
|
+
A retroactive audit requires a completed phase. If no SUMMARY.md is
|
|
64
|
+
present, the phase hasn't been executed yet and there is nothing to
|
|
65
|
+
audit.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
if [[ "$SUMMARY_PRESENT" != "true" ]]; then
|
|
69
|
+
echo "Error: Phase $PHASE has no SUMMARY.md at $SUMMARY_PATH." >&2
|
|
70
|
+
echo "The phase must be executed (/np:execute-phase) before it can be audited." >&2
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Gate 2 — UI-REVIEW.md already exists
|
|
76
|
+
|
|
77
|
+
If a prior review is present, let the user choose between re-running,
|
|
78
|
+
viewing the current review, or skipping.
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
if [[ -f "$UI_REVIEW_PATH" ]]; then
|
|
82
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
83
|
+
"type": "select",
|
|
84
|
+
"header": "Existing UI-REVIEW",
|
|
85
|
+
"question": "UI-REVIEW.md already exists for Phase '"$PHASE"'. What would you like to do?",
|
|
86
|
+
"options": [
|
|
87
|
+
{"label": "Re-run — replace the current review", "description": "Re-runs np-ui-auditor and overwrites the existing file."},
|
|
88
|
+
{"label": "View — display current review and exit", "description": "Reads the file and exits without changes."},
|
|
89
|
+
{"label": "Skip — keep current review and exit", "description": "Leaves the file untouched."}
|
|
90
|
+
]
|
|
91
|
+
}')
|
|
92
|
+
case "$CHOICE" in
|
|
93
|
+
"View"*) cat "$UI_REVIEW_PATH"; exit 0 ;;
|
|
94
|
+
"Skip"*) exit 0 ;;
|
|
95
|
+
esac
|
|
96
|
+
fi
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Gate 3 — Determine audit mode
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
if [[ "$HAS_UI_SPEC" == "true" ]]; then
|
|
103
|
+
AUDIT_MODE="spec-conformance"
|
|
104
|
+
else
|
|
105
|
+
AUDIT_MODE="retroactive-general"
|
|
106
|
+
fi
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
</pre_flight>
|
|
110
|
+
|
|
111
|
+
## Philosophy
|
|
112
|
+
|
|
113
|
+
<philosophy>
|
|
114
|
+
UI drift is invisible until you measure it. Copy regresses to "Submit"
|
|
115
|
+
and "OK", accent colors multiply past the 60/30/10 split, spacing
|
|
116
|
+
scales fragment into pixel-perfect one-offs, and empty/error/loading
|
|
117
|
+
states go missing. A retroactive 6-pillar audit catches all of that in
|
|
118
|
+
one pass and produces a ranked list of fixes. When a UI-SPEC.md exists,
|
|
119
|
+
the audit is a conformance check. When it doesn't, the audit is a
|
|
120
|
+
best-practice sweep — and the mode label on UI-REVIEW.md makes that
|
|
121
|
+
difference explicit so reviewers don't treat a general audit as if it
|
|
122
|
+
had SPEC backing.
|
|
123
|
+
</philosophy>
|
|
124
|
+
|
|
125
|
+
## Main Flow
|
|
126
|
+
|
|
127
|
+
Single serial spawn — the auditor is self-contained (screenshots,
|
|
128
|
+
pillar scoring, registry safety, report writing all happen inside
|
|
129
|
+
`np-ui-auditor`).
|
|
130
|
+
|
|
131
|
+
### Step 1 — UI auditor (np-ui-auditor, haiku)
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
START=$(node np-tools.cjs metrics start-timestamp)
|
|
135
|
+
MODEL=$(node np-tools.cjs resolve-model np-ui-auditor --profile balanced)
|
|
136
|
+
> NOTE: Spawn agent=np-ui-auditor model=$MODEL
|
|
137
|
+
> NOTE: input: phase_number=$PHASE, phase_dir=$PHASE_DIR,
|
|
138
|
+
> NOTE: summary_path=$SUMMARY_PATH, ui_spec_path=$UI_SPEC_PATH,
|
|
139
|
+
> NOTE: has_ui_spec=$HAS_UI_SPEC, audit_mode=$AUDIT_MODE,
|
|
140
|
+
> NOTE: ui_review_path=$UI_REVIEW_PATH
|
|
141
|
+
> NOTE: output: $UI_REVIEW_PATH with pillar scores, top-3 fixes,
|
|
142
|
+
> NOTE: and a mode label ("spec-conformance" or
|
|
143
|
+
> NOTE: "retroactive-general") in the header frontmatter.
|
|
144
|
+
END=$(node np-tools.cjs metrics end-timestamp)
|
|
145
|
+
node np-tools.cjs metrics record \
|
|
146
|
+
--agent np-ui-auditor --tier haiku --resolved-model "$MODEL" \
|
|
147
|
+
--phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
|
|
148
|
+
--started "$START" --ended "$END" \
|
|
149
|
+
--tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
|
|
150
|
+
--retry-count 0 --status ok --runtime "$RUNTIME"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Validation Gate
|
|
154
|
+
|
|
155
|
+
After the auditor finishes, verify UI-REVIEW.md was written and carries
|
|
156
|
+
the expected mode label. If the file is missing, the spawn failed
|
|
157
|
+
silently and the user is prompted to re-run or abort.
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
if [[ ! -f "$UI_REVIEW_PATH" ]]; then
|
|
161
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
162
|
+
"type": "select",
|
|
163
|
+
"header": "UI-REVIEW.md missing",
|
|
164
|
+
"question": "np-ui-auditor did not write UI-REVIEW.md. What would you like to do?",
|
|
165
|
+
"options": [
|
|
166
|
+
{"label": "Re-run np-ui-auditor", "description": "Spawn the auditor once more."},
|
|
167
|
+
{"label": "Abort", "description": "Exit without committing."}
|
|
168
|
+
]
|
|
169
|
+
}')
|
|
170
|
+
case "$CHOICE" in
|
|
171
|
+
"Abort") exit 1 ;;
|
|
172
|
+
esac
|
|
173
|
+
fi
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Commit
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
git add "$UI_REVIEW_PATH"
|
|
180
|
+
git commit -m "docs(${PADDED}): generate UI-REVIEW.md (${AUDIT_MODE})"
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Scope Guardrail
|
|
184
|
+
|
|
185
|
+
<scope_guardrail>
|
|
186
|
+
**Do:**
|
|
187
|
+
- Run `np-ui-auditor` exactly once per invocation (single-pass audit).
|
|
188
|
+
- Emit a metrics record AFTER the Task spawn (D-06).
|
|
189
|
+
- Resolve MODEL via `np-tools.cjs resolve-model` — no hardcoded IDs.
|
|
190
|
+
- Use `np-tools.cjs askuser` for every prompt (INST-03 invariant).
|
|
191
|
+
- Label the audit mode explicitly in UI-REVIEW.md
|
|
192
|
+
(`spec-conformance` when UI-SPEC.md exists, `retroactive-general`
|
|
193
|
+
otherwise) — Pitfall 10 enforcement.
|
|
194
|
+
- Abort early when SUMMARY.md is missing; retroactive audits are only
|
|
195
|
+
meaningful against executed phases.
|
|
196
|
+
|
|
197
|
+
**Don't:**
|
|
198
|
+
- Run this workflow on a phase that has not been executed — there is
|
|
199
|
+
nothing to audit until SUMMARY.md lands.
|
|
200
|
+
- Invoke host-specific prompt tools directly — always route through
|
|
201
|
+
`np-tools.cjs askuser`.
|
|
202
|
+
- Silently treat a spec-less audit as if it had SPEC backing — the
|
|
203
|
+
mode label in the output header is mandatory.
|
|
204
|
+
- Spawn any additional agent beyond `np-ui-auditor`; if a follow-up
|
|
205
|
+
remediation pass is needed, that is the planner's job, not this
|
|
206
|
+
workflow's.
|
|
207
|
+
- Call any tools binary other than `np-tools.cjs` (the sole CLI entry
|
|
208
|
+
per Plan 09-05 D-14).
|
|
209
|
+
- Reference legacy homedir payload paths — those directories do not
|
|
210
|
+
exist in nubos-pilot projects.
|
|
211
|
+
- Skip the metrics record block — the Phase-10 np:stats consumer
|
|
212
|
+
expects one record per Task spawn.
|
|
213
|
+
</scope_guardrail>
|
|
214
|
+
|
|
215
|
+
## Output
|
|
216
|
+
|
|
217
|
+
- `{phase_dir}/{padded}-UI-REVIEW.md` — pillar scores, top-3 priority
|
|
218
|
+
fixes, detailed findings, and mode label
|
|
219
|
+
(`spec-conformance` or `retroactive-general`).
|
|
220
|
+
- 1 metrics record in `.nubos-pilot/metrics/phase-${PHASE}.jsonl`
|
|
221
|
+
for the single `np-ui-auditor` Task spawn.
|
|
222
|
+
- One git commit when UI-REVIEW.md is produced successfully.
|