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,447 @@
|
|
|
1
|
+
---
|
|
2
|
+
command: np:code-review
|
|
3
|
+
description: Source-file review on a completed phase. Reads files_to_read from --files flag or phase SUMMARY.md key_files. Spawns np-code-reviewer (opus) to produce REVIEW.md with critical/warning/info findings at depth quick|standard|deep. One atomic docs commit. Supports --auto flag (chains to /np:code-review-fix after review).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# np:code-review
|
|
7
|
+
|
|
8
|
+
Produces `{phase_dir}/{padded}-REVIEW.md` via a single `np-code-reviewer` (opus)
|
|
9
|
+
spawn that reviews phase source files at depth `quick|standard|deep`.
|
|
10
|
+
Runs AFTER `/np:execute-phase` has landed code — the audit needs either
|
|
11
|
+
a phase `SUMMARY.md` with `key_files:` or an explicit `--files=...`
|
|
12
|
+
override to know what to review.
|
|
13
|
+
|
|
14
|
+
The single Task-spawn site is wrapped in the Plan 09-05 metrics +
|
|
15
|
+
resolve-model pattern (D-06, D-01). `RUNTIME` is detected once at the
|
|
16
|
+
top of the bash block and re-used by the `metrics record` call. All
|
|
17
|
+
interactive prompts route through `np-tools.cjs askuser` per INST-03.
|
|
18
|
+
|
|
19
|
+
File paths passed via `--files=...` are validated through a
|
|
20
|
+
realpath + repo-root-prefix guard (Pitfall 7 / T-10-03-01 mitigation)
|
|
21
|
+
to reject path-traversal attempts before they reach the agent.
|
|
22
|
+
|
|
23
|
+
## Initialize
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
PHASE="$1"
|
|
27
|
+
if [[ -z "$PHASE" ]]; then
|
|
28
|
+
echo "Usage: /np:code-review <phase-number> [--files=f1,f2] [--depth=quick|standard|deep] [--auto]" >&2
|
|
29
|
+
exit 2
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
INIT=$(node np-tools.cjs init code-review "$PHASE")
|
|
33
|
+
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
34
|
+
RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Parse JSON for: `phase`, `padded`, `phase_dir`, `review_path`,
|
|
38
|
+
`review_fix_path`, `summary_present`, `summary_path`, `has_review`,
|
|
39
|
+
`depth`, `agents.code_reviewer`.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
PADDED=$(echo "$INIT" | jq -r '.padded')
|
|
43
|
+
PHASE_DIR=$(echo "$INIT" | jq -r '.phase_dir')
|
|
44
|
+
REVIEW_PATH=$(echo "$INIT" | jq -r '.review_path')
|
|
45
|
+
SUMMARY_PRESENT=$(echo "$INIT" | jq -r '.summary_present')
|
|
46
|
+
SUMMARY_PATH=$(echo "$INIT" | jq -r '.summary_path')
|
|
47
|
+
HAS_REVIEW=$(echo "$INIT" | jq -r '.has_review')
|
|
48
|
+
DEPTH=$(echo "$INIT" | jq -r '.depth')
|
|
49
|
+
PLAN_ID="${PADDED}-code-review"
|
|
50
|
+
TASK_ID="${PADDED}-code-review"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Argument Parsing
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
FILES_ARG=""
|
|
57
|
+
DEPTH_OVERRIDE=""
|
|
58
|
+
AUTO_MODE="false"
|
|
59
|
+
for arg in "$@"; do
|
|
60
|
+
case "$arg" in
|
|
61
|
+
--files=*) FILES_ARG="${arg#--files=}" ;;
|
|
62
|
+
--depth=*) DEPTH_OVERRIDE="${arg#--depth=}" ;;
|
|
63
|
+
--auto) AUTO_MODE="true" ;;
|
|
64
|
+
esac
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
if [[ -n "$DEPTH_OVERRIDE" ]]; then
|
|
68
|
+
case "$DEPTH_OVERRIDE" in
|
|
69
|
+
quick|standard|deep) DEPTH="$DEPTH_OVERRIDE" ;;
|
|
70
|
+
*) echo "Warning: invalid --depth='$DEPTH_OVERRIDE' (expected quick|standard|deep). Keeping DEPTH=$DEPTH." >&2 ;;
|
|
71
|
+
esac
|
|
72
|
+
fi
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Path-Traversal Guard
|
|
76
|
+
|
|
77
|
+
Every path from `--files=...` is validated against the repository root
|
|
78
|
+
before reaching the agent (T-10-03-01 mitigation). `realpath -m` is
|
|
79
|
+
preferred for correctness; on macOS without `coreutils` a string-match
|
|
80
|
+
fallback is used.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
SAFE_FILES=()
|
|
84
|
+
if [[ -n "$FILES_ARG" ]]; then
|
|
85
|
+
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
|
|
86
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
87
|
+
echo "Error: unable to resolve repository root via 'git rev-parse --show-toplevel'." >&2
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
IFS=',' read -ra FILES_ARR <<< "$FILES_ARG"
|
|
91
|
+
if command -v realpath >/dev/null 2>&1; then
|
|
92
|
+
for F in "${FILES_ARR[@]}"; do
|
|
93
|
+
[[ -z "$F" ]] && continue
|
|
94
|
+
RP=$(realpath -m "$F" 2>/dev/null || true)
|
|
95
|
+
case "$RP" in
|
|
96
|
+
"$REPO_ROOT"/*) SAFE_FILES+=("$F") ;;
|
|
97
|
+
*) echo "Skipping path outside repo: $F" >&2 ;;
|
|
98
|
+
esac
|
|
99
|
+
done
|
|
100
|
+
else
|
|
101
|
+
echo "WARN: realpath not available (macOS users: brew install coreutils). Falling back to string-match guard." >&2
|
|
102
|
+
for F in "${FILES_ARR[@]}"; do
|
|
103
|
+
[[ -z "$F" ]] && continue
|
|
104
|
+
case "$F" in
|
|
105
|
+
*/../*|../*|/*) echo "Skipping unsafe path: $F" >&2 ;;
|
|
106
|
+
*) SAFE_FILES+=("$F") ;;
|
|
107
|
+
esac
|
|
108
|
+
done
|
|
109
|
+
fi
|
|
110
|
+
fi
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Pre-Flight Gates
|
|
114
|
+
|
|
115
|
+
<pre_flight>
|
|
116
|
+
|
|
117
|
+
### Gate 1 — SUMMARY.md must exist
|
|
118
|
+
|
|
119
|
+
A retroactive code review requires a completed phase. If no SUMMARY.md
|
|
120
|
+
is present, the phase has not been executed yet and there is nothing to
|
|
121
|
+
review.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
if [[ "$SUMMARY_PRESENT" != "true" ]]; then
|
|
125
|
+
echo "Error: Phase $PHASE has no SUMMARY.md at $SUMMARY_PATH." >&2
|
|
126
|
+
echo "The phase must be executed (/np:execute-phase) before it can be reviewed." >&2
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Gate 2 — REVIEW.md already exists
|
|
132
|
+
|
|
133
|
+
If a prior review is present, let the user choose between re-running,
|
|
134
|
+
viewing the current review, or skipping.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
if [[ "$HAS_REVIEW" == "true" ]]; then
|
|
138
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
139
|
+
"type": "select",
|
|
140
|
+
"header": "Existing REVIEW",
|
|
141
|
+
"question": "REVIEW.md already exists for Phase '"$PHASE"'. What would you like to do?",
|
|
142
|
+
"options": [
|
|
143
|
+
{"label": "Re-run — replace the current review", "description": "Re-runs np-code-reviewer and overwrites the existing file."},
|
|
144
|
+
{"label": "View — display current review and exit", "description": "Reads the file and exits without changes."},
|
|
145
|
+
{"label": "Skip — keep current review and exit", "description": "Leaves the file untouched."}
|
|
146
|
+
]
|
|
147
|
+
}')
|
|
148
|
+
case "$CHOICE" in
|
|
149
|
+
"View"*) cat "$REVIEW_PATH"; exit 0 ;;
|
|
150
|
+
"Skip"*) exit 0 ;;
|
|
151
|
+
esac
|
|
152
|
+
fi
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Gate 3 — Determine review scope
|
|
156
|
+
|
|
157
|
+
Scope precedence: `--files` override (already path-guarded above) wins;
|
|
158
|
+
otherwise the phase `SUMMARY.md` frontmatter `key_files:` block is the
|
|
159
|
+
source of truth. If neither produces any files, abort with a clear
|
|
160
|
+
error — do NOT fall back to an arbitrary git diff. SUMMARY.md is
|
|
161
|
+
mandatory per Gate 1 and its `key-files:` block is authoritative.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
if [[ ${#SAFE_FILES[@]} -eq 0 ]]; then
|
|
165
|
+
EXTRACTED=$(SUMMARY_PATH="$SUMMARY_PATH" node -e "
|
|
166
|
+
const fs = require('node:fs');
|
|
167
|
+
const { extractFrontmatter } = require('./lib/frontmatter.cjs');
|
|
168
|
+
const raw = fs.readFileSync(process.env.SUMMARY_PATH, 'utf-8');
|
|
169
|
+
const { frontmatter } = extractFrontmatter(raw);
|
|
170
|
+
const kf = (frontmatter && frontmatter['key-files']) || (frontmatter && frontmatter.key_files) || {};
|
|
171
|
+
const out = [];
|
|
172
|
+
if (Array.isArray(kf.created)) for (const p of kf.created) out.push(String(p));
|
|
173
|
+
if (Array.isArray(kf.modified)) for (const p of kf.modified) out.push(String(p));
|
|
174
|
+
if (out.length) process.stdout.write(out.join('\n'));
|
|
175
|
+
" 2>/dev/null || true)
|
|
176
|
+
|
|
177
|
+
if [[ -n "$EXTRACTED" ]]; then
|
|
178
|
+
while IFS= read -r line; do
|
|
179
|
+
[[ -n "$line" ]] && SAFE_FILES+=("$line")
|
|
180
|
+
done <<< "$EXTRACTED"
|
|
181
|
+
fi
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
if [[ ${#SAFE_FILES[@]} -eq 0 ]]; then
|
|
185
|
+
echo "Error: no files to review." >&2
|
|
186
|
+
echo " Provide --files=f1,f2,... OR add key-files.created / key-files.modified to $SUMMARY_PATH." >&2
|
|
187
|
+
exit 1
|
|
188
|
+
fi
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
</pre_flight>
|
|
192
|
+
|
|
193
|
+
## Philosophy
|
|
194
|
+
|
|
195
|
+
<philosophy>
|
|
196
|
+
A code review is not a bug-finding tool — it is a contract-verification
|
|
197
|
+
pass. The reviewer's job is to answer ONE question: did the
|
|
198
|
+
implementation deliver against its plan (CLAUDE.md, ADRs, PROJECT
|
|
199
|
+
constraints, phase `requirements:`) without introducing critical
|
|
200
|
+
defects along the way? Findings are graded critical / warning / info so
|
|
201
|
+
downstream `/np:code-review-fix` can gate on severity. A review that
|
|
202
|
+
produces a 30-item warning list is usually a planning failure, not an
|
|
203
|
+
execution failure — the planner should tighten the spec next round.
|
|
204
|
+
Scope is the phase, not the whole repo; the `--files` override exists
|
|
205
|
+
for targeted re-reviews after a fix pass, not for repo-wide audits.
|
|
206
|
+
|
|
207
|
+
**Depth semantics** (resolved via init payload or `--depth=` override):
|
|
208
|
+
|
|
209
|
+
| Depth | Scope | Typical use |
|
|
210
|
+
|-------|-------|-------------|
|
|
211
|
+
| `quick` | surface-level: obvious bugs, missing error handling, broken imports | post-fix re-review, large scopes (>50 files) |
|
|
212
|
+
| `standard` | default: correctness + security + plan-contract alignment | normal per-phase review |
|
|
213
|
+
| `deep` | exhaustive: performance, edge cases, threat-model vs implementation | security-sensitive phases, pre-release audits |
|
|
214
|
+
|
|
215
|
+
The reviewer agent branches on `$DEPTH` internally; this workflow only
|
|
216
|
+
selects which value to pass. `--depth` override beats the init-payload
|
|
217
|
+
default (`standard`). Invalid values trigger a warning and keep the
|
|
218
|
+
init default rather than crashing — the review should still run.
|
|
219
|
+
|
|
220
|
+
**Scope precedence** (implemented in the Pre-Flight Gates above):
|
|
221
|
+
|
|
222
|
+
1. `--files=a,b,c` override (path-guarded) — highest priority
|
|
223
|
+
2. SUMMARY.md `key-files.created` + `key-files.modified` (agent-owned
|
|
224
|
+
frontmatter produced by `/np:execute-phase`)
|
|
225
|
+
3. Error — no fall-through to git diff. A git-diff fallback would
|
|
226
|
+
produce noisy reviews of unrelated files; the SUMMARY.md
|
|
227
|
+
`key-files:` contract from Phase 9 plan-phase → Phase 9
|
|
228
|
+
execute-phase is authoritative.
|
|
229
|
+
</philosophy>
|
|
230
|
+
|
|
231
|
+
## REVIEW.md Frontmatter Contract
|
|
232
|
+
|
|
233
|
+
The reviewer agent (`np-code-reviewer`) owns the REVIEW.md frontmatter.
|
|
234
|
+
The workflow does NOT author or mutate that block. This workflow's
|
|
235
|
+
contract is: (1) ensure the agent has the right input, (2) commit the
|
|
236
|
+
output file atomically. The agent contract is documented in
|
|
237
|
+
`agents/np-code-reviewer.md`; the keys most relevant to the
|
|
238
|
+
downstream `/np:code-review-fix` consumer are:
|
|
239
|
+
|
|
240
|
+
- `status: clean | issues_found | skipped` — drives fix-workflow gate
|
|
241
|
+
- `depth: quick | standard | deep` — echoes the value this workflow passed
|
|
242
|
+
- `files_reviewed: N` and `files_reviewed_list: [f1, f2, …]` — enables
|
|
243
|
+
scope-persistence across `--auto` re-review iterations
|
|
244
|
+
- `findings.critical / findings.warning / findings.info` counts + bodies
|
|
245
|
+
|
|
246
|
+
If the agent produces a file without these keys, the commit still
|
|
247
|
+
proceeds (the workflow is not a schema validator), but
|
|
248
|
+
`/np:code-review-fix` will refuse to consume it — that workflow's FM
|
|
249
|
+
gate is the defense-in-depth layer (T-10-03-06 mitigation).
|
|
250
|
+
|
|
251
|
+
## Main Flow
|
|
252
|
+
|
|
253
|
+
Single serial spawn — the reviewer is self-contained (file reading,
|
|
254
|
+
finding severity, REVIEW.md writing all happen inside
|
|
255
|
+
`np-code-reviewer`). The agent writes `REVIEW_PATH` with its own
|
|
256
|
+
frontmatter schema (agent-owned, not workflow-owned). See
|
|
257
|
+
`agents/np-code-reviewer.md` for the REVIEW.md FM contract.
|
|
258
|
+
|
|
259
|
+
### Step 1 — Code reviewer (np-code-reviewer, opus)
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
START=$(node np-tools.cjs metrics start-timestamp)
|
|
263
|
+
MODEL=$(node np-tools.cjs resolve-model np-code-reviewer --profile balanced)
|
|
264
|
+
FILES_JSON=$(printf '%s\n' "${SAFE_FILES[@]}" | node -e '
|
|
265
|
+
const chunks = [];
|
|
266
|
+
process.stdin.on("data", (d) => chunks.push(d));
|
|
267
|
+
process.stdin.on("end", () => {
|
|
268
|
+
const lines = Buffer.concat(chunks).toString("utf-8").split("\n").filter((l) => l.length > 0);
|
|
269
|
+
process.stdout.write(JSON.stringify(lines));
|
|
270
|
+
});
|
|
271
|
+
')
|
|
272
|
+
# Spawn agent=np-code-reviewer model=$MODEL
|
|
273
|
+
# input: files_to_read=$FILES_JSON (JSON array, whitespace-safe),
|
|
274
|
+
# review_path=$REVIEW_PATH, depth=$DEPTH,
|
|
275
|
+
# phase_dir=$PHASE_DIR, summary_path=$SUMMARY_PATH
|
|
276
|
+
# output: $REVIEW_PATH with agent-owned REVIEW.md frontmatter
|
|
277
|
+
# (status, depth, files_reviewed, files_reviewed_list,
|
|
278
|
+
# findings.{critical,warning,info}, total)
|
|
279
|
+
Task(
|
|
280
|
+
subagent_type="np-code-reviewer",
|
|
281
|
+
model="$MODEL",
|
|
282
|
+
prompt="<files_to_read>$FILES_JSON</files_to_read><config>phase=$PHASE,phase_dir=$PHASE_DIR,review_path=$REVIEW_PATH,depth=$DEPTH,summary_path=$SUMMARY_PATH</config>"
|
|
283
|
+
)
|
|
284
|
+
END=$(node np-tools.cjs metrics end-timestamp)
|
|
285
|
+
node np-tools.cjs metrics record \
|
|
286
|
+
--agent np-code-reviewer --tier opus --resolved-model "$MODEL" \
|
|
287
|
+
--phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
|
|
288
|
+
--started "$START" --ended "$END" \
|
|
289
|
+
--tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
|
|
290
|
+
--retry-count 0 --status ok --runtime "$RUNTIME"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Validation Gate
|
|
294
|
+
|
|
295
|
+
After the reviewer finishes, verify REVIEW.md was written. If the file
|
|
296
|
+
is missing, the spawn failed silently and the user is prompted to
|
|
297
|
+
re-run or abort.
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
if [[ ! -f "$REVIEW_PATH" ]]; then
|
|
301
|
+
CHOICE=$(node np-tools.cjs askuser --json '{
|
|
302
|
+
"type": "select",
|
|
303
|
+
"header": "REVIEW.md missing",
|
|
304
|
+
"question": "np-code-reviewer did not write REVIEW.md. What would you like to do?",
|
|
305
|
+
"options": [
|
|
306
|
+
{"label": "Re-run np-code-reviewer", "description": "Spawn the reviewer once more."},
|
|
307
|
+
{"label": "Abort", "description": "Exit without committing."}
|
|
308
|
+
]
|
|
309
|
+
}')
|
|
310
|
+
case "$CHOICE" in
|
|
311
|
+
"Abort") exit 1 ;;
|
|
312
|
+
esac
|
|
313
|
+
fi
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Commit
|
|
317
|
+
|
|
318
|
+
```bash
|
|
319
|
+
node np-tools.cjs commit "docs(${PADDED}): add code review report" --files "$REVIEW_PATH"
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## --auto Chain Hint
|
|
323
|
+
|
|
324
|
+
If `--auto` was passed, display a prose directive to the user — the
|
|
325
|
+
follow-up `/np:code-review-fix` invocation stays explicit (in-session
|
|
326
|
+
loop, no daemon per ADR-0001; cross-workflow chaining is the
|
|
327
|
+
`/np:execute-phase` orchestrator's concern, not this workflow's).
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
if [[ "$AUTO_MODE" == "true" ]]; then
|
|
331
|
+
echo ""
|
|
332
|
+
echo "--auto flag set. Next step: /np:code-review-fix $PHASE --auto"
|
|
333
|
+
echo " (re-runs review + fix until clean OR iteration cap 3 reached)"
|
|
334
|
+
fi
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
## Scope Guardrail
|
|
338
|
+
|
|
339
|
+
<scope_guardrail>
|
|
340
|
+
**Do:**
|
|
341
|
+
- Run `np-code-reviewer` exactly once per invocation (single-pass review).
|
|
342
|
+
- Emit a metrics record AFTER the Task spawn (D-06).
|
|
343
|
+
- Resolve MODEL via `np-tools.cjs resolve-model` — no hardcoded IDs.
|
|
344
|
+
- Use `np-tools.cjs askuser` for every prompt (INST-03 invariant).
|
|
345
|
+
- Validate `--files` paths through realpath + repo-root-prefix BEFORE
|
|
346
|
+
passing them to the agent (T-10-03-01 path-traversal mitigation).
|
|
347
|
+
- Route the final commit through `np-tools.cjs commit` so
|
|
348
|
+
`lib/git.cjs.assertCommittablePaths()` runs the gitignore-guard.
|
|
349
|
+
- Abort early when SUMMARY.md is missing; retroactive reviews are only
|
|
350
|
+
meaningful against executed phases.
|
|
351
|
+
|
|
352
|
+
**Don't:**
|
|
353
|
+
- Spawn any additional agent beyond `np-code-reviewer`; the fix pass
|
|
354
|
+
is a separate workflow (`/np:code-review-fix`) per atomic-commit
|
|
355
|
+
discipline (ADR-0004, D-21 exception lives inside that workflow).
|
|
356
|
+
- Invoke host-specific prompt tools directly — always route through
|
|
357
|
+
`np-tools.cjs askuser`.
|
|
358
|
+
- Shell out to `/np:code-review-fix` automatically on `--auto`; that
|
|
359
|
+
would nest workflows and violate the atomic-commit model.
|
|
360
|
+
- Skip the metrics record block — the Phase-10 np:stats consumer
|
|
361
|
+
expects one record per Task spawn.
|
|
362
|
+
- Use a git-diff fallback for scope; SUMMARY.md `key-files:` is the
|
|
363
|
+
single source of truth (Gate 3).
|
|
364
|
+
</scope_guardrail>
|
|
365
|
+
|
|
366
|
+
## Platform Notes
|
|
367
|
+
|
|
368
|
+
<platform_notes>
|
|
369
|
+
**macOS:** `realpath -m` requires GNU coreutils. Install via
|
|
370
|
+
`brew install coreutils` if the path-traversal guard warns about
|
|
371
|
+
"realpath not available". The string-match fallback still rejects
|
|
372
|
+
obvious escapes (`../`, absolute paths) but cannot canonicalize
|
|
373
|
+
symlinks, so valid relative paths with traversal-like components may
|
|
374
|
+
also be rejected — prefer absolute paths under the repo root if the
|
|
375
|
+
fallback rejects a legitimate file.
|
|
376
|
+
|
|
377
|
+
**Windows:** This workflow uses bash features (arrays, process
|
|
378
|
+
substitution). On Windows, it requires Git Bash or WSL. Native
|
|
379
|
+
PowerShell is not supported.
|
|
380
|
+
</platform_notes>
|
|
381
|
+
|
|
382
|
+
## Output
|
|
383
|
+
|
|
384
|
+
- `{phase_dir}/{padded}-REVIEW.md` — agent-owned frontmatter (status,
|
|
385
|
+
depth, files_reviewed, files_reviewed_list, findings summary) plus
|
|
386
|
+
severity-grouped finding bodies.
|
|
387
|
+
- 1 metrics record in `.nubos-pilot/metrics/phase-${PHASE}.jsonl` for
|
|
388
|
+
the single `np-code-reviewer` Task spawn.
|
|
389
|
+
- One git commit when REVIEW.md is produced successfully.
|
|
390
|
+
|
|
391
|
+
## Success Criteria
|
|
392
|
+
|
|
393
|
+
- [ ] Phase validated via init payload before any agent spawn
|
|
394
|
+
- [ ] `--files` paths validated through realpath + repo-root-prefix
|
|
395
|
+
(T-10-03-01 mitigation) before being passed to the agent
|
|
396
|
+
- [ ] File scope resolved from `--files` override OR SUMMARY.md
|
|
397
|
+
`key-files:` — no git-diff fallback
|
|
398
|
+
- [ ] Existing REVIEW.md handled via 3-way askuser prompt (Re-run /
|
|
399
|
+
View / Skip)
|
|
400
|
+
- [ ] Depth resolved with validation (quick|standard|deep); invalid
|
|
401
|
+
`--depth=...` warns and keeps the init-payload default
|
|
402
|
+
- [ ] Empty scope results in explicit error (no silent agent spawn)
|
|
403
|
+
- [ ] Agent spawn wrapped in Pattern S-2 metrics block (D-06) with
|
|
404
|
+
`metrics record` within 30 lines of the Task() call (Pitfall 9)
|
|
405
|
+
- [ ] `metrics record` includes `--runtime "$RUNTIME"` resolved at the
|
|
406
|
+
top of the bash block via `lib/runtime/index.cjs.detect()`
|
|
407
|
+
- [ ] REVIEW.md missing after spawn triggers askuser Re-run / Abort
|
|
408
|
+
- [ ] Final commit routed through `np-tools.cjs commit` so
|
|
409
|
+
`lib/git.cjs.assertCommittablePaths()` enforces the
|
|
410
|
+
gitignore-guard (T-10-03-05 defense-in-depth)
|
|
411
|
+
- [ ] `--auto` flag prints a prose hint; it does NOT auto-invoke
|
|
412
|
+
`/np:code-review-fix` (no-daemon invariant ADR-0001)
|
|
413
|
+
|
|
414
|
+
## Related Workflows
|
|
415
|
+
|
|
416
|
+
- **`/np:code-review-fix <phase> [--auto]`** — consumes REVIEW.md,
|
|
417
|
+
spawns `np-code-fixer` (sonnet), emits per-finding fix commits
|
|
418
|
+
inside the agent (D-21 exception to ADR-0004), then the final
|
|
419
|
+
REVIEW-FIX.md docs commit. The `--auto` iteration loop (capped at
|
|
420
|
+
3) re-reviews the same `files_reviewed_list` across iterations so
|
|
421
|
+
scope is preserved.
|
|
422
|
+
- **`/np:review <phase>`** — cross-AI peer review that fans out a
|
|
423
|
+
phase-scoped prompt to every installed external CLI
|
|
424
|
+
(gemini/claude/codex/coderabbit/opencode/qwen/cursor) and
|
|
425
|
+
concatenates their outputs into REVIEWS.md. Complementary to
|
|
426
|
+
code-review: that workflow asks the agent "did the code deliver
|
|
427
|
+
against the plan"; `/np:review` asks external AIs "would the plan
|
|
428
|
+
itself hold up to adversarial review".
|
|
429
|
+
- **`/np:ui-review <phase>`** — 6-pillar UI audit (copy, visual,
|
|
430
|
+
color, typography, spacing, experience). Spawns `np-ui-auditor`
|
|
431
|
+
(haiku). Orthogonal to code-review; run both on any UI phase.
|
|
432
|
+
- **`/np:secure-phase <phase>`** and **`/np:validate-phase <phase>`**
|
|
433
|
+
(Phase 10 Plan 10-04) — threat-model and test-coverage audits
|
|
434
|
+
respectively. Chain after code-review for security-sensitive
|
|
435
|
+
phases.
|
|
436
|
+
|
|
437
|
+
## Design Notes
|
|
438
|
+
|
|
439
|
+
No git-diff Tier-3 fallback: Phase 9 execute-phase guarantees a
|
|
440
|
+
populated `key-files:` block in every SUMMARY.md, making a git-diff
|
|
441
|
+
scope superfluous and noisy. No config-gate short-circuit: the
|
|
442
|
+
workflow is invoked explicitly by the user, so a flag to "skip when
|
|
443
|
+
invoked" would be redundant. Frontmatter-schema validation is
|
|
444
|
+
delegated to the downstream `/np:code-review-fix` FM-gate, which
|
|
445
|
+
refuses to consume a malformed REVIEW.md — this workflow's commit
|
|
446
|
+
step is intentionally permissive so agent issues surface as
|
|
447
|
+
reviewable diffs rather than hidden skips.
|