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.
Files changed (273) hide show
  1. package/agents/np-ai-researcher.md +140 -0
  2. package/agents/np-code-fixer.md +363 -0
  3. package/agents/np-code-reviewer.md +351 -0
  4. package/agents/np-domain-researcher.md +136 -0
  5. package/agents/np-eval-auditor.md +167 -0
  6. package/agents/np-eval-planner.md +153 -0
  7. package/agents/np-executor.md +72 -0
  8. package/agents/np-framework-selector.md +171 -0
  9. package/agents/np-nyquist-auditor.md +185 -0
  10. package/agents/np-plan-checker.md +165 -0
  11. package/agents/np-planner.md +199 -0
  12. package/agents/np-researcher.md +150 -0
  13. package/agents/np-security-auditor.md +206 -0
  14. package/agents/np-ui-auditor.md +369 -0
  15. package/agents/np-ui-checker.md +192 -0
  16. package/agents/np-ui-researcher.md +324 -0
  17. package/agents/np-verifier.md +79 -0
  18. package/bin/check-coverage.cjs +40 -0
  19. package/bin/check-workflows.cjs +171 -0
  20. package/bin/check-workflows.test.cjs +208 -0
  21. package/bin/install.js +500 -0
  22. package/bin/np-tools/_commands.cjs +70 -0
  23. package/bin/np-tools/add-tests.cjs +171 -0
  24. package/bin/np-tools/add-tests.test.cjs +122 -0
  25. package/bin/np-tools/add-todo.cjs +108 -0
  26. package/bin/np-tools/add-todo.test.cjs +112 -0
  27. package/bin/np-tools/agent-skills.cjs +14 -0
  28. package/bin/np-tools/agent-skills.test.cjs +42 -0
  29. package/bin/np-tools/ai-integration-phase.cjs +109 -0
  30. package/bin/np-tools/ai-integration-phase.test.cjs +123 -0
  31. package/bin/np-tools/askuser.cjs +53 -0
  32. package/bin/np-tools/askuser.test.cjs +49 -0
  33. package/bin/np-tools/autonomous.cjs +69 -0
  34. package/bin/np-tools/autonomous.test.cjs +74 -0
  35. package/bin/np-tools/checkpoint.cjs +101 -0
  36. package/bin/np-tools/checkpoint.test.cjs +119 -0
  37. package/bin/np-tools/code-review.cjs +133 -0
  38. package/bin/np-tools/code-review.test.cjs +96 -0
  39. package/bin/np-tools/commit-task.cjs +120 -0
  40. package/bin/np-tools/commit-task.test.cjs +160 -0
  41. package/bin/np-tools/commit.cjs +103 -0
  42. package/bin/np-tools/commit.test.cjs +93 -0
  43. package/bin/np-tools/config.cjs +101 -0
  44. package/bin/np-tools/config.test.cjs +71 -0
  45. package/bin/np-tools/discuss-phase-power.cjs +265 -0
  46. package/bin/np-tools/discuss-phase-power.test.cjs +242 -0
  47. package/bin/np-tools/discuss-phase.cjs +132 -0
  48. package/bin/np-tools/discuss-phase.test.cjs +148 -0
  49. package/bin/np-tools/dispatch.cjs +116 -0
  50. package/bin/np-tools/doctor.cjs +242 -0
  51. package/bin/np-tools/eval-review.cjs +116 -0
  52. package/bin/np-tools/eval-review.test.cjs +123 -0
  53. package/bin/np-tools/execute-phase.cjs +182 -0
  54. package/bin/np-tools/execute-phase.test.cjs +116 -0
  55. package/bin/np-tools/execute-plan.cjs +124 -0
  56. package/bin/np-tools/execute-plan.test.cjs +82 -0
  57. package/bin/np-tools/help.cjs +28 -0
  58. package/bin/np-tools/help.test.cjs +29 -0
  59. package/bin/np-tools/init-dispatch.test.cjs +91 -0
  60. package/bin/np-tools/metrics.cjs +97 -0
  61. package/bin/np-tools/metrics.test.cjs +188 -0
  62. package/bin/np-tools/new-milestone.cjs +288 -0
  63. package/bin/np-tools/new-milestone.test.cjs +166 -0
  64. package/bin/np-tools/new-project.cjs +284 -0
  65. package/bin/np-tools/new-project.test.cjs +165 -0
  66. package/bin/np-tools/next.cjs +7 -0
  67. package/bin/np-tools/next.test.cjs +30 -0
  68. package/bin/np-tools/park.cjs +48 -0
  69. package/bin/np-tools/park.test.cjs +50 -0
  70. package/bin/np-tools/pause-work.cjs +24 -0
  71. package/bin/np-tools/pause-work.test.cjs +74 -0
  72. package/bin/np-tools/phase.cjs +71 -0
  73. package/bin/np-tools/phase.test.cjs +81 -0
  74. package/bin/np-tools/plan-diff.cjs +57 -0
  75. package/bin/np-tools/plan-diff.test.cjs +134 -0
  76. package/bin/np-tools/plan-milestone-gaps.cjs +115 -0
  77. package/bin/np-tools/plan-milestone-gaps.test.cjs +122 -0
  78. package/bin/np-tools/plan-phase.cjs +350 -0
  79. package/bin/np-tools/plan-phase.test.cjs +263 -0
  80. package/bin/np-tools/progress.cjs +7 -0
  81. package/bin/np-tools/progress.test.cjs +44 -0
  82. package/bin/np-tools/queue.cjs +213 -0
  83. package/bin/np-tools/research-phase.cjs +144 -0
  84. package/bin/np-tools/research-phase.test.cjs +154 -0
  85. package/bin/np-tools/reset-slice.cjs +17 -0
  86. package/bin/np-tools/reset-slice.test.cjs +96 -0
  87. package/bin/np-tools/resolve-model.cjs +110 -0
  88. package/bin/np-tools/resolve-model.test.cjs +200 -0
  89. package/bin/np-tools/resume-work.cjs +76 -0
  90. package/bin/np-tools/resume-work.test.cjs +91 -0
  91. package/bin/np-tools/skip.cjs +48 -0
  92. package/bin/np-tools/skip.test.cjs +66 -0
  93. package/bin/np-tools/slug.cjs +34 -0
  94. package/bin/np-tools/slug.test.cjs +46 -0
  95. package/bin/np-tools/state.cjs +16 -0
  96. package/bin/np-tools/state.test.cjs +40 -0
  97. package/bin/np-tools/stats.cjs +151 -0
  98. package/bin/np-tools/stats.test.cjs +118 -0
  99. package/bin/np-tools/triage.cjs +128 -0
  100. package/bin/np-tools/ui-phase.cjs +108 -0
  101. package/bin/np-tools/ui-phase.test.cjs +121 -0
  102. package/bin/np-tools/ui-review.cjs +108 -0
  103. package/bin/np-tools/ui-review.test.cjs +120 -0
  104. package/bin/np-tools/undo-task.cjs +31 -0
  105. package/bin/np-tools/undo-task.test.cjs +117 -0
  106. package/bin/np-tools/undo.cjs +43 -0
  107. package/bin/np-tools/undo.test.cjs +120 -0
  108. package/bin/np-tools/unpark.cjs +48 -0
  109. package/bin/np-tools/unpark.test.cjs +50 -0
  110. package/bin/np-tools/verify-work.cjs +186 -0
  111. package/bin/np-tools/verify-work.test.cjs +97 -0
  112. package/docs/adr/0001-no-daemon-invariant.md +82 -0
  113. package/docs/adr/0002-zero-runtime-dependencies.md +90 -0
  114. package/docs/adr/0003-max-six-unit-types.md +85 -0
  115. package/docs/adr/0004-atomic-commit-per-unit.md +102 -0
  116. package/docs/adr/0005-three-orthogonal-file-trees.md +98 -0
  117. package/docs/adr/0006-yaml-dependency-amendment.md +60 -0
  118. package/docs/adr/README.md +27 -0
  119. package/docs/agent-frontmatter-schema.md +84 -0
  120. package/docs/phase-artifact-schemas.md +292 -0
  121. package/docs/phase-directory-layout.md +82 -0
  122. package/lib/__tests__/README.md +1 -0
  123. package/lib/agents.cjs +98 -0
  124. package/lib/agents.test.cjs +286 -0
  125. package/lib/askuser.cjs +36 -0
  126. package/lib/askuser.test.cjs +310 -0
  127. package/lib/checkpoint.cjs +135 -0
  128. package/lib/checkpoint.test.cjs +184 -0
  129. package/lib/core.cjs +165 -0
  130. package/lib/core.test.cjs +405 -0
  131. package/lib/fixtures/README.md +1 -0
  132. package/lib/fixtures/phase-tree/README.md +1 -0
  133. package/lib/fixtures/plans/cycle/PLAN.md +16 -0
  134. package/lib/fixtures/plans/cycle/tasks/T-01.md +20 -0
  135. package/lib/fixtures/plans/cycle/tasks/T-02.md +20 -0
  136. package/lib/fixtures/plans/cycle/tasks/T-03.md +20 -0
  137. package/lib/fixtures/plans/linear/PLAN.md +16 -0
  138. package/lib/fixtures/plans/linear/tasks/T-01.md +20 -0
  139. package/lib/fixtures/plans/linear/tasks/T-02.md +20 -0
  140. package/lib/fixtures/plans/linear/tasks/T-03.md +20 -0
  141. package/lib/fixtures/plans/parallel/PLAN.md +16 -0
  142. package/lib/fixtures/plans/parallel/tasks/T-01.md +20 -0
  143. package/lib/fixtures/plans/parallel/tasks/T-02.md +20 -0
  144. package/lib/fixtures/plans/parallel/tasks/T-03.md +20 -0
  145. package/lib/fixtures/plans/wave-conflict/PLAN.md +16 -0
  146. package/lib/fixtures/plans/wave-conflict/tasks/T-01.md +20 -0
  147. package/lib/fixtures/plans/wave-conflict/tasks/T-02.md +20 -0
  148. package/lib/fixtures/roadmap/ROADMAP-malformed.md +3 -0
  149. package/lib/fixtures/roadmap/ROADMAP-minimal.md +51 -0
  150. package/lib/fixtures/roadmap/roadmap-malformed.yaml +7 -0
  151. package/lib/fixtures/roadmap/roadmap-minimal.yaml +40 -0
  152. package/lib/fixtures/roadmap/roadmap-ten-phases.yaml +101 -0
  153. package/lib/fixtures/templates/phase-context.md +6 -0
  154. package/lib/fixtures/templates/plan-skeleton.md +6 -0
  155. package/lib/frontmatter.cjs +251 -0
  156. package/lib/frontmatter.test.cjs +177 -0
  157. package/lib/gaps.cjs +197 -0
  158. package/lib/gaps.test.cjs +200 -0
  159. package/lib/git.cjs +207 -0
  160. package/lib/git.test.cjs +305 -0
  161. package/lib/install/agents-md.cjs +77 -0
  162. package/lib/install/backup.cjs +70 -0
  163. package/lib/install/codex-toml.cjs +440 -0
  164. package/lib/install/managed-block.cjs +30 -0
  165. package/lib/install/manifest.cjs +148 -0
  166. package/lib/install/mcp-writer.cjs +127 -0
  167. package/lib/install/runtime-detect.cjs +44 -0
  168. package/lib/install/staging.cjs +149 -0
  169. package/lib/metrics-aggregate.cjs +229 -0
  170. package/lib/metrics-aggregate.test.cjs +192 -0
  171. package/lib/metrics.cjs +120 -0
  172. package/lib/metrics.test.cjs +182 -0
  173. package/lib/model-aliases.regression.test.cjs +16 -0
  174. package/lib/model-profiles.cjs +42 -0
  175. package/lib/model-profiles.test.cjs +61 -0
  176. package/lib/next.cjs +236 -0
  177. package/lib/next.test.cjs +194 -0
  178. package/lib/phase.cjs +95 -0
  179. package/lib/phase.test.cjs +189 -0
  180. package/lib/plan-checker-contract.test.cjs +72 -0
  181. package/lib/plan-diff.cjs +173 -0
  182. package/lib/plan-diff.test.cjs +217 -0
  183. package/lib/plan.cjs +85 -0
  184. package/lib/plan.test.cjs +263 -0
  185. package/lib/progress.cjs +95 -0
  186. package/lib/progress.test.cjs +116 -0
  187. package/lib/researcher-contract.test.cjs +61 -0
  188. package/lib/roadmap-render.cjs +206 -0
  189. package/lib/roadmap-render.test.cjs +121 -0
  190. package/lib/roadmap.cjs +416 -0
  191. package/lib/roadmap.test.cjs +371 -0
  192. package/lib/runtime/_contract.test.cjs +61 -0
  193. package/lib/runtime/_readline.cjs +119 -0
  194. package/lib/runtime/_readline.test.cjs +126 -0
  195. package/lib/runtime/claude.cjs +48 -0
  196. package/lib/runtime/claude.test.cjs +101 -0
  197. package/lib/runtime/codex.cjs +35 -0
  198. package/lib/runtime/codex.test.cjs +114 -0
  199. package/lib/runtime/gemini.cjs +35 -0
  200. package/lib/runtime/gemini.test.cjs +109 -0
  201. package/lib/runtime/index.cjs +49 -0
  202. package/lib/runtime/index.test.cjs +181 -0
  203. package/lib/runtime/opencode.cjs +35 -0
  204. package/lib/runtime/opencode.test.cjs +124 -0
  205. package/lib/state.cjs +205 -0
  206. package/lib/state.test.cjs +264 -0
  207. package/lib/surface-audit.test.cjs +46 -0
  208. package/lib/tasks.cjs +327 -0
  209. package/lib/tasks.test.cjs +389 -0
  210. package/lib/template.cjs +66 -0
  211. package/lib/template.test.cjs +159 -0
  212. package/lib/undo.cjs +179 -0
  213. package/lib/undo.test.cjs +261 -0
  214. package/lib/verify.cjs +116 -0
  215. package/lib/verify.test.cjs +187 -0
  216. package/np-tools.cjs +303 -0
  217. package/package.json +39 -0
  218. package/templates/AI-SPEC.md +90 -0
  219. package/templates/CONTEXT.md +32 -0
  220. package/templates/PLAN.md +69 -0
  221. package/templates/PROJECT.md +60 -0
  222. package/templates/REQUIREMENTS.md +38 -0
  223. package/templates/SECURITY.md +61 -0
  224. package/templates/UI-SPEC.md +64 -0
  225. package/templates/VALIDATION.md +76 -0
  226. package/templates/claude/payload/README.md +11 -0
  227. package/templates/opencode/opencode.json +6 -0
  228. package/templates/opencode/payload/AGENTS.md +9 -0
  229. package/workflows/add-backlog.md +212 -0
  230. package/workflows/add-tests.md +69 -0
  231. package/workflows/add-todo.md +222 -0
  232. package/workflows/ai-integration-phase.md +230 -0
  233. package/workflows/autonomous.md +94 -0
  234. package/workflows/cleanup.md +325 -0
  235. package/workflows/code-review-fix.md +435 -0
  236. package/workflows/code-review.md +447 -0
  237. package/workflows/discuss-phase-assumptions.md +269 -0
  238. package/workflows/discuss-phase-power.md +139 -0
  239. package/workflows/discuss-phase.md +386 -0
  240. package/workflows/dispatch.md +9 -0
  241. package/workflows/doctor.md +10 -0
  242. package/workflows/eval-review.md +243 -0
  243. package/workflows/execute-phase.md +142 -0
  244. package/workflows/execute-plan.md +82 -0
  245. package/workflows/help.md +8 -0
  246. package/workflows/new-milestone.md +166 -0
  247. package/workflows/new-project.md +213 -0
  248. package/workflows/next.md +8 -0
  249. package/workflows/note.md +244 -0
  250. package/workflows/park.md +29 -0
  251. package/workflows/pause-work.md +34 -0
  252. package/workflows/plan-milestone-gaps.md +233 -0
  253. package/workflows/plan-phase.md +351 -0
  254. package/workflows/progress.md +8 -0
  255. package/workflows/queue.md +9 -0
  256. package/workflows/research-phase.md +327 -0
  257. package/workflows/reset-slice.md +39 -0
  258. package/workflows/resume-work.md +79 -0
  259. package/workflows/review.md +489 -0
  260. package/workflows/secure-phase.md +209 -0
  261. package/workflows/session-report.md +243 -0
  262. package/workflows/skip.md +29 -0
  263. package/workflows/state.md +7 -0
  264. package/workflows/stats.md +170 -0
  265. package/workflows/thread.md +214 -0
  266. package/workflows/triage.md +9 -0
  267. package/workflows/ui-phase.md +246 -0
  268. package/workflows/ui-review.md +222 -0
  269. package/workflows/undo-task.md +42 -0
  270. package/workflows/undo.md +55 -0
  271. package/workflows/unpark.md +29 -0
  272. package/workflows/validate-phase.md +231 -0
  273. package/workflows/verify-work.md +83 -0
@@ -0,0 +1,435 @@
1
+ ---
2
+ command: np:code-review-fix
3
+ description: Auto-fixer that consumes REVIEW.md, applies fixes finding-by-finding as per-finding atomic commits (D-21 exception), writes REVIEW-FIX.md. Supports --auto iteration cap 3, --fix-scope=critical|warning|info|all filter. Spawns np-code-fixer (sonnet). Final commit is the REVIEW-FIX.md docs commit.
4
+ ---
5
+
6
+ # np:code-review-fix
7
+
8
+ Consumes `{phase_dir}/{padded}-REVIEW.md` (produced by `/np:code-review`) and
9
+ applies fixes via a `np-code-fixer` (sonnet) spawn that emits per-finding
10
+ `fix(...)` commits INSIDE the agent (D-21 exception to ADR-0004) and
11
+ writes `REVIEW-FIX.md` with `status: all_fixed | partial | none_fixed`.
12
+
13
+ The workflow's own final commit is the REVIEW-FIX.md docs commit — it
14
+ is NOT re-emitted for the per-finding fixes. See the Commit section for
15
+ the exact atomic-commit ownership contract between workflow and agent.
16
+
17
+ The single Task-spawn site is wrapped in the Plan 09-05 metrics +
18
+ resolve-model pattern (D-06, D-01). `RUNTIME` is detected once at the
19
+ top of the bash block. All prompts route through `np-tools.cjs askuser`
20
+ (INST-03 invariant).
21
+
22
+ Gate logic: before spawning the fixer, the workflow reads REVIEW.md's
23
+ frontmatter via `lib/frontmatter.cjs.extractFrontmatter`, validates the
24
+ schema (`files_reviewed_list` + `status` + `depth` + `findings`) and
25
+ short-circuits if `status` is `clean` or `skipped` (T-10-03-06
26
+ mitigation, Pitfall 2 defense-in-depth). A malformed REVIEW.md triggers
27
+ an exit before any fix attempt — producer/consumer FM drift is surfaced
28
+ at this layer, not hidden by the agent.
29
+
30
+ ## Initialize
31
+
32
+ ```bash
33
+ PHASE="$1"
34
+ if [[ -z "$PHASE" ]]; then
35
+ echo "Usage: /np:code-review-fix <phase-number> [--fix-scope=critical|warning|info|all] [--auto] [--iteration=N]" >&2
36
+ exit 2
37
+ fi
38
+
39
+ INIT=$(node np-tools.cjs init code-review "$PHASE")
40
+ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
41
+ RUNTIME=$(node -e "console.log(require('./lib/runtime/index.cjs').detect().runtime)")
42
+ ```
43
+
44
+ Parse JSON for: `phase`, `padded`, `phase_dir`, `review_path`,
45
+ `review_fix_path`, `agents.code_fixer`. Note: the init dispatcher
46
+ `code-review` covers both reviewer and fixer workflows — same payload
47
+ shape, different fields consumed.
48
+
49
+ ```bash
50
+ PADDED=$(echo "$INIT" | jq -r '.padded')
51
+ PHASE_DIR=$(echo "$INIT" | jq -r '.phase_dir')
52
+ REVIEW_PATH=$(echo "$INIT" | jq -r '.review_path')
53
+ REVIEW_FIX_PATH=$(echo "$INIT" | jq -r '.review_fix_path')
54
+ PLAN_ID="${PADDED}-code-review-fix"
55
+ TASK_ID="${PADDED}-code-review-fix"
56
+ ```
57
+
58
+ ## Argument Parsing
59
+
60
+ ```bash
61
+ FIX_SCOPE="all"
62
+ AUTO_MODE="false"
63
+ ITERATION=1
64
+ for arg in "$@"; do
65
+ case "$arg" in
66
+ --fix-scope=*) FIX_SCOPE="${arg#--fix-scope=}" ;;
67
+ --auto) AUTO_MODE="true" ;;
68
+ --iteration=*) ITERATION="${arg#--iteration=}" ;;
69
+ esac
70
+ done
71
+
72
+ case "$FIX_SCOPE" in
73
+ critical|warning|info|all) ;;
74
+ *) echo "Warning: invalid --fix-scope='$FIX_SCOPE' (expected critical|warning|info|all). Using 'all'." >&2
75
+ FIX_SCOPE="all" ;;
76
+ esac
77
+
78
+ if ! [[ "$ITERATION" =~ ^[0-9]+$ ]]; then
79
+ echo "Warning: invalid --iteration='$ITERATION' (expected non-negative integer). Using 1." >&2
80
+ ITERATION=1
81
+ fi
82
+ ```
83
+
84
+ ## Pre-Flight Gates
85
+
86
+ <pre_flight>
87
+
88
+ ### Gate 1 — REVIEW.md presence
89
+
90
+ REVIEW.md MUST exist before fixing. Do NOT auto-run code-review — the
91
+ user's explicit review intent is the contract.
92
+
93
+ ```bash
94
+ if [[ ! -f "$REVIEW_PATH" ]]; then
95
+ echo "Error: $REVIEW_PATH not found. Run /np:code-review $PHASE first." >&2
96
+ exit 1
97
+ fi
98
+ ```
99
+
100
+ ### Gate 2 — REVIEW.md frontmatter schema + status gate
101
+
102
+ Load the REVIEW.md frontmatter once via `lib/frontmatter.cjs` and
103
+ validate the fields downstream consumers depend on. If any required
104
+ field is missing, exit with a clear error — producer/consumer FM drift
105
+ is T-10-03-06 and MUST NOT be silently fixed here.
106
+
107
+ ```bash
108
+ FM_JSON=$(REVIEW_PATH="$REVIEW_PATH" node -e "
109
+ const fs = require('node:fs');
110
+ const { extractFrontmatter } = require('./lib/frontmatter.cjs');
111
+ const raw = fs.readFileSync(process.env.REVIEW_PATH, 'utf-8');
112
+ const { frontmatter } = extractFrontmatter(raw);
113
+ process.stdout.write(JSON.stringify(frontmatter || {}));
114
+ " 2>/dev/null || echo '{}')
115
+
116
+ STATUS=$(echo "$FM_JSON" | jq -r '.status // empty')
117
+ DEPTH=$(echo "$FM_JSON" | jq -r '.depth // empty')
118
+ HAS_FILES_LIST=$(echo "$FM_JSON" | jq -r 'has("files_reviewed_list") // false')
119
+ HAS_FINDINGS=$(echo "$FM_JSON" | jq -r 'has("findings") // false')
120
+
121
+ MISSING=""
122
+ [[ -z "$STATUS" ]] && MISSING="$MISSING status"
123
+ [[ -z "$DEPTH" ]] && MISSING="$MISSING depth"
124
+ [[ "$HAS_FILES_LIST" != "true" ]] && MISSING="$MISSING files_reviewed_list"
125
+ [[ "$HAS_FINDINGS" != "true" ]] && MISSING="$MISSING findings"
126
+
127
+ if [[ -n "$MISSING" ]]; then
128
+ echo "Error: REVIEW.md frontmatter missing required fields:$MISSING" >&2
129
+ echo " Expected schema (owned by np-code-reviewer):" >&2
130
+ echo " status: clean | issues_found | skipped" >&2
131
+ echo " depth: quick | standard | deep" >&2
132
+ echo " files_reviewed_list: [path, ...]" >&2
133
+ echo " findings: { critical: N, warning: N, info: N, total: N }" >&2
134
+ echo " Re-run /np:code-review $PHASE to regenerate." >&2
135
+ exit 1
136
+ fi
137
+ ```
138
+
139
+ Short-circuit on non-actionable statuses:
140
+
141
+ ```bash
142
+ case "$STATUS" in
143
+ clean|skipped)
144
+ echo "Nothing to fix — REVIEW.md status=$STATUS."
145
+ exit 0
146
+ ;;
147
+ issues_found)
148
+ : # proceed
149
+ ;;
150
+ *)
151
+ echo "Warning: unknown REVIEW.md status='$STATUS' (expected clean|skipped|issues_found). Proceeding with fix attempt." >&2
152
+ ;;
153
+ esac
154
+ ```
155
+
156
+ ### Gate 3 — Existing REVIEW-FIX.md
157
+
158
+ If a prior fix report is present, let the user choose between re-running,
159
+ viewing the current report, or skipping (Pattern S-3).
160
+
161
+ ```bash
162
+ if [[ -f "$REVIEW_FIX_PATH" ]]; then
163
+ CHOICE=$(node np-tools.cjs askuser --json '{
164
+ "type": "select",
165
+ "header": "Existing REVIEW-FIX",
166
+ "question": "REVIEW-FIX.md already exists for Phase '"$PHASE"'. What would you like to do?",
167
+ "options": [
168
+ {"label": "Re-run — replace the current fix report", "description": "Re-runs np-code-fixer and overwrites the existing file + emits additional per-finding fix commits if new fixes apply."},
169
+ {"label": "View — display current fix report and exit", "description": "Reads the file and exits without changes."},
170
+ {"label": "Skip — keep current fix report and exit", "description": "Leaves the file untouched."}
171
+ ]
172
+ }')
173
+ case "$CHOICE" in
174
+ "View"*) cat "$REVIEW_FIX_PATH"; exit 0 ;;
175
+ "Skip"*) exit 0 ;;
176
+ esac
177
+ fi
178
+ ```
179
+
180
+ </pre_flight>
181
+
182
+ ## Philosophy
183
+
184
+ <philosophy>
185
+ A fix workflow that re-emits bulk commits loses the one thing atomic
186
+ commits buy: the ability to `git revert` a single bad fix without
187
+ clobbering the others. The D-21 exception to ADR-0004 exists for
188
+ exactly this reason — the agent owns per-finding `fix(...)` commits
189
+ because the agent is the one that knows which file changes map to
190
+ which REVIEW.md finding ID. The workflow's job is the envelope: gate
191
+ the inputs, resolve the model, wrap the spawn in metrics, and commit
192
+ the final REVIEW-FIX.md artifact ONCE.
193
+
194
+ Fix-scope filtering (`--fix-scope=critical|warning|info|all`) is
195
+ deliberately a coarse filter, not a per-finding whitelist. A
196
+ per-finding whitelist would require the user to read REVIEW.md ahead of
197
+ time, which defeats the auto-fix value proposition. Severity-level
198
+ filtering is the right granularity: "only fix critical issues; I'll
199
+ triage warnings manually."
200
+
201
+ The `--auto` iteration loop (cap 3) drives in-session
202
+ auto-fix attempts. Each iteration re-reviews the SAME
203
+ `files_reviewed_list` captured in REVIEW.md's frontmatter — scope
204
+ does NOT drift across iterations. When `status === clean` is reached,
205
+ the loop exits early. When iteration 3 still returns `partial`,
206
+ remaining issues stay documented in REVIEW-FIX.md for manual triage.
207
+
208
+ Why no workflow-level fix-commit bundling? Because `git log --grep` is
209
+ how users navigate fix history, and a bundled `fix(): apply N fixes`
210
+ commit destroys the grep signal. Per-finding commits with the finding
211
+ ID (e.g., `fix(10-03-T02): CR-042 rename shadowed variable`) are
212
+ searchable, revertable, and reviewable — the atomic-commit tax is
213
+ worth the observability dividend.
214
+ </philosophy>
215
+
216
+ ## REVIEW.md → np-code-fixer Contract
217
+
218
+ The fixer agent (`np-code-fixer`) owns BOTH the per-finding fix
219
+ commits AND the final `docs(...)` REVIEW-FIX.md commit. This workflow
220
+ does NOT re-commit after the agent returns. The contract:
221
+
222
+ 1. Agent reads `$REVIEW_PATH` frontmatter (same schema validated in
223
+ Gate 2).
224
+ 2. Agent filters findings by `--fix-scope` (critical|warning|info|all).
225
+ 3. For each finding in scope: agent applies the fix, runs
226
+ `node np-tools.cjs commit "fix(${PADDED}): ${FINDING_ID} <one-line>" --files <path>`
227
+ exactly once per finding (T-10-02-02 mitigation — never raw
228
+ `git commit` shell strings).
229
+ 4. Agent writes `$REVIEW_FIX_PATH` with frontmatter:
230
+ `status: all_fixed | partial | none_fixed`, `findings_in_scope: N`,
231
+ `fixed: N`, `skipped: N`, `iteration: $ITERATION`.
232
+ 5. Agent emits the final `docs(${PADDED}): add code review fix report`
233
+ commit for REVIEW-FIX.md itself.
234
+
235
+ If the agent produces REVIEW-FIX.md but skips the final docs commit
236
+ (malfunction), the workflow's post-validation below will re-emit it
237
+ from outside the agent — but that is a fallback, not the primary path.
238
+
239
+ ## Main Flow
240
+
241
+ ### Step 1 — Code fixer (np-code-fixer, sonnet)
242
+
243
+ ```bash
244
+ START=$(node np-tools.cjs metrics start-timestamp)
245
+ MODEL=$(node np-tools.cjs resolve-model np-code-fixer --profile balanced)
246
+ # Spawn agent=np-code-fixer model=$MODEL
247
+ # input: review_path=$REVIEW_PATH, review_fix_path=$REVIEW_FIX_PATH,
248
+ # phase=$PHASE, padded=$PADDED, phase_dir=$PHASE_DIR,
249
+ # fix_scope=$FIX_SCOPE, auto=$AUTO_MODE, iteration=$ITERATION
250
+ # output: $REVIEW_FIX_PATH + 0..N per-finding fix(...) commits
251
+ # (D-21 exception — commits happen INSIDE the agent, not
252
+ # after the Task returns) + final docs(...) REVIEW-FIX.md
253
+ # commit emitted by the agent itself
254
+ Task(
255
+ subagent_type="np-code-fixer",
256
+ model="$MODEL",
257
+ prompt="<files_to_read>$REVIEW_PATH</files_to_read><config>review_path=$REVIEW_PATH,review_fix_path=$REVIEW_FIX_PATH,phase=$PHASE,padded=$PADDED,phase_dir=$PHASE_DIR,fix_scope=$FIX_SCOPE,auto=$AUTO_MODE,iteration=$ITERATION</config>"
258
+ )
259
+ END=$(node np-tools.cjs metrics end-timestamp)
260
+ node np-tools.cjs metrics record \
261
+ --agent np-code-fixer --tier sonnet --resolved-model "$MODEL" \
262
+ --phase "$PHASE" --plan "$PLAN_ID" --task "$TASK_ID" \
263
+ --started "$START" --ended "$END" \
264
+ --tokens-in "${TOKENS_IN:-0}" --tokens-out "${TOKENS_OUT:-0}" \
265
+ --retry-count 0 --status ok --runtime "$RUNTIME"
266
+ ```
267
+
268
+ ## Validation Gate
269
+
270
+ After the fixer returns, verify REVIEW-FIX.md exists and has a
271
+ `status:` field. If missing, the agent likely failed mid-run; per-
272
+ finding commits that already landed stay in git log for review.
273
+
274
+ ```bash
275
+ if [[ ! -f "$REVIEW_FIX_PATH" ]]; then
276
+ echo "Warning: REVIEW-FIX.md not written at $REVIEW_FIX_PATH." >&2
277
+ echo "Agent may have failed mid-run; any fix(...) commits already emitted are in git log." >&2
278
+ echo "Check: git log --oneline --grep=\"fix($PADDED)\"" >&2
279
+ exit 1
280
+ fi
281
+
282
+ FIX_STATUS=$(REVIEW_FIX_PATH="$REVIEW_FIX_PATH" node -e "
283
+ const fs = require('node:fs');
284
+ const { extractFrontmatter } = require('./lib/frontmatter.cjs');
285
+ const raw = fs.readFileSync(process.env.REVIEW_FIX_PATH, 'utf-8');
286
+ const { frontmatter } = extractFrontmatter(raw);
287
+ process.stdout.write((frontmatter && frontmatter.status) || '');
288
+ " 2>/dev/null)
289
+
290
+ if [[ -z "$FIX_STATUS" ]]; then
291
+ echo "Warning: REVIEW-FIX.md missing status field in frontmatter." >&2
292
+ fi
293
+ ```
294
+
295
+ ## Commit
296
+
297
+ **D-21 EXCEPTION TO ADR-0004:** per-finding `fix(...)` commits were
298
+ already emitted by `np-code-fixer` during its execution. The agent
299
+ also owns the final `docs(...)` commit for REVIEW-FIX.md. This
300
+ workflow does NOT re-commit the fix report on the agent's behalf —
301
+ routing through `git log --oneline` after the spawn will show the
302
+ complete commit chain:
303
+
304
+ ```
305
+ docs(10-XX): add code review fix report <- agent-owned final commit
306
+ fix(10-XX): CR-042 rename shadowed var <- per-finding commit
307
+ fix(10-XX): CR-041 add null check <- per-finding commit
308
+ ...
309
+ ```
310
+
311
+ Fallback path — if the agent wrote REVIEW-FIX.md but did NOT commit it
312
+ (e.g., agent crashed between Write and commit), emit the missing docs
313
+ commit from the workflow:
314
+
315
+ ```bash
316
+ if ! git diff --cached --quiet "$REVIEW_FIX_PATH" 2>/dev/null || \
317
+ git status --porcelain "$REVIEW_FIX_PATH" 2>/dev/null | grep -q .; then
318
+ echo "Note: REVIEW-FIX.md is uncommitted — agent did not emit final docs commit."
319
+ echo "Emitting fallback docs commit from workflow (D-21 fallback path)."
320
+ node np-tools.cjs commit "docs(${PADDED}): add code review fix report" --files "$REVIEW_FIX_PATH"
321
+ fi
322
+ ```
323
+
324
+ ## --auto Iteration Hint
325
+
326
+ If `--auto` AND FIX_STATUS is `partial`, display a prose directive to
327
+ re-run the review + fix cycle. Do NOT shell-out automatically
328
+ (ADR-0001 no-daemon, in-session loop only). The downstream user
329
+ invokes `/np:code-review $PHASE --auto` → `/np:code-review-fix $PHASE
330
+ --auto --iteration=2` etc., capped at 3 per the agent's contract.
331
+
332
+ ```bash
333
+ if [[ "$AUTO_MODE" == "true" ]] && [[ "$FIX_STATUS" == "partial" ]]; then
334
+ NEXT=$((ITERATION + 1))
335
+ if [[ $NEXT -le 3 ]]; then
336
+ echo ""
337
+ echo "--auto: fix status=partial. Next iteration ($NEXT/3):"
338
+ echo " /np:code-review $PHASE --auto"
339
+ echo " /np:code-review-fix $PHASE --auto --iteration=$NEXT"
340
+ else
341
+ echo ""
342
+ echo "--auto: iteration cap 3 reached with status=partial."
343
+ echo "Remaining issues documented in $REVIEW_FIX_PATH — triage manually."
344
+ fi
345
+ fi
346
+ ```
347
+
348
+ ## Scope Guardrail
349
+
350
+ <scope_guardrail>
351
+ **Do:**
352
+ - Spawn `np-code-fixer` exactly once per invocation (single-pass fix).
353
+ - Validate REVIEW.md frontmatter schema in Gate 2 BEFORE spawning the
354
+ fixer (T-10-03-06 producer/consumer drift mitigation).
355
+ - Let the agent own per-finding `fix(...)` commits (D-21 exception).
356
+ - Let the agent own the final `docs(...)` REVIEW-FIX.md commit; this
357
+ workflow's fallback path only fires when the agent skipped it.
358
+ - Emit a metrics record AFTER the Task spawn (D-06).
359
+ - Resolve MODEL via `np-tools.cjs resolve-model` — no hardcoded IDs.
360
+ - Use `np-tools.cjs askuser` for every prompt (INST-03 invariant).
361
+ - Short-circuit on REVIEW.md `status: clean | skipped` — no agent
362
+ spawn, no commit, exit 0.
363
+ - Route every commit (agent-side or fallback) through
364
+ `np-tools.cjs commit` so the gitignore-guard runs.
365
+
366
+ **Don't:**
367
+ - Auto-run `/np:code-review` from this workflow if REVIEW.md is
368
+ missing — require explicit user intent before producing a review.
369
+ - Bundle per-finding fixes into a single commit — atomicity buys
370
+ revertability per finding (D-21).
371
+ - Re-emit the docs commit unconditionally — the agent owns it; this
372
+ workflow's fallback only fires on uncommitted REVIEW-FIX.md.
373
+ - Shell out to `/np:code-review` or `/np:code-review-fix` recursively
374
+ on `--auto`; the iteration hint is prose, user-driven (ADR-0001).
375
+ - Invoke host-specific prompt tools directly — always route through
376
+ `np-tools.cjs askuser`.
377
+ - Skip the metrics record block — the Phase-10 np:stats consumer
378
+ expects one record per Task spawn.
379
+ </scope_guardrail>
380
+
381
+ ## Output
382
+
383
+ - `{phase_dir}/{padded}-REVIEW-FIX.md` — agent-owned frontmatter
384
+ (status, findings_in_scope, fixed, skipped, iteration) plus a
385
+ per-finding applied/skipped table with commit hashes.
386
+ - 0..N `fix(${PADDED}): <FINDING_ID> <one-line>` commits (one per
387
+ applied finding; D-21 exception to ADR-0004).
388
+ - 1 `docs(${PADDED}): add code review fix report` commit for
389
+ REVIEW-FIX.md itself (agent-owned; workflow has a fallback).
390
+ - 1 metrics record in `.nubos-pilot/metrics/phase-${PHASE}.jsonl` for
391
+ the single `np-code-fixer` Task spawn.
392
+
393
+ ## Success Criteria
394
+
395
+ - [ ] REVIEW.md presence verified (explicit error if missing — no
396
+ auto-run of /np:code-review)
397
+ - [ ] REVIEW.md frontmatter schema validated
398
+ (files_reviewed_list + status + depth + findings present;
399
+ T-10-03-06 mitigation / Pitfall 2)
400
+ - [ ] Short-circuit on REVIEW.md `status: clean | skipped` (exit 0,
401
+ no spawn, no commit)
402
+ - [ ] `--fix-scope` validated to critical|warning|info|all (invalid
403
+ warns and falls back to `all`)
404
+ - [ ] Existing REVIEW-FIX.md handled via 3-way askuser prompt
405
+ - [ ] Agent spawn wrapped in Pattern S-2 metrics block with
406
+ `metrics record` within 30 lines of Task()
407
+ - [ ] Per-finding fix commits happen INSIDE np-code-fixer (D-21),
408
+ NEVER re-emitted by this workflow
409
+ - [ ] Final REVIEW-FIX.md docs commit happens INSIDE np-code-fixer;
410
+ workflow fallback only fires when agent skipped it
411
+ - [ ] `--auto` prints iteration hint (cap 3); does NOT shell-out
412
+ recursively (ADR-0001)
413
+
414
+ ## Related Workflows
415
+
416
+ - **`/np:code-review <phase>`** — produces the REVIEW.md that this
417
+ workflow consumes. Run it first. Without REVIEW.md this workflow
418
+ exits with an error.
419
+ - **`/np:review <phase>`** — cross-AI peer review; orthogonal to the
420
+ code-review/fix pair. Runs a fan-out across external CLIs and does
421
+ not interact with REVIEW.md.
422
+
423
+ ## Platform Notes
424
+
425
+ <platform_notes>
426
+ **Windows:** This workflow uses bash features (arrays, variable
427
+ expansion, `jq`, process substitution). On Windows, it requires Git
428
+ Bash or WSL. Native PowerShell is not supported.
429
+
430
+ **`jq` dependency:** Gate 2 pipes the frontmatter JSON through `jq`
431
+ for field extraction. `jq` is present on nearly all dev machines
432
+ where nubos-pilot runs (it is the same dependency surface the
433
+ `/np:execute-phase` workflow relies on). If `jq` is missing, install
434
+ via `brew install jq` (macOS) or the distro's package manager.
435
+ </platform_notes>