@jakkrichm/create-nexus-devflow 2.0.25 → 2.0.27

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 (122) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/create-nexus-devflow.d.ts +18 -1
  3. package/dist/bin/create-nexus-devflow.js +439 -11
  4. package/dist/bin/create-nexus-devflow.js.map +1 -1
  5. package/dist/lib/command-catalog.d.ts +11 -0
  6. package/dist/lib/command-catalog.js +63 -0
  7. package/dist/lib/command-catalog.js.map +1 -0
  8. package/dist/lib/current-work.js +94 -48
  9. package/dist/lib/current-work.js.map +1 -1
  10. package/dist/lib/dashboard-page.d.ts +2 -0
  11. package/dist/lib/dashboard-page.js +201 -0
  12. package/dist/lib/dashboard-page.js.map +1 -0
  13. package/dist/lib/dashboard-snapshot.d.ts +49 -0
  14. package/dist/lib/dashboard-snapshot.js +96 -0
  15. package/dist/lib/dashboard-snapshot.js.map +1 -0
  16. package/dist/lib/dashboard.d.ts +2 -0
  17. package/dist/lib/dashboard.js +360 -8
  18. package/dist/lib/dashboard.js.map +1 -1
  19. package/dist/lib/discoveries.d.ts +19 -0
  20. package/dist/lib/discoveries.js +81 -0
  21. package/dist/lib/discoveries.js.map +1 -0
  22. package/dist/lib/doctor.d.ts +26 -0
  23. package/dist/lib/doctor.js +474 -0
  24. package/dist/lib/doctor.js.map +1 -0
  25. package/dist/lib/findings.d.ts +26 -2
  26. package/dist/lib/findings.js +165 -1
  27. package/dist/lib/findings.js.map +1 -1
  28. package/dist/lib/gatekeeper.d.ts +19 -0
  29. package/dist/lib/gatekeeper.js +77 -0
  30. package/dist/lib/gatekeeper.js.map +1 -0
  31. package/dist/lib/git-hooks.d.ts +16 -0
  32. package/dist/lib/git-hooks.js +78 -0
  33. package/dist/lib/git-hooks.js.map +1 -0
  34. package/dist/lib/history.d.ts +6 -1
  35. package/dist/lib/history.js +98 -11
  36. package/dist/lib/history.js.map +1 -1
  37. package/dist/lib/ideas.d.ts +26 -0
  38. package/dist/lib/ideas.js +179 -0
  39. package/dist/lib/ideas.js.map +1 -0
  40. package/dist/lib/status.d.ts +2 -0
  41. package/dist/lib/status.js +60 -6
  42. package/dist/lib/status.js.map +1 -1
  43. package/dist/lib/update.js +2 -2
  44. package/dist/lib/update.js.map +1 -1
  45. package/dist/lib/version-check.d.ts +22 -0
  46. package/dist/lib/version-check.js +59 -0
  47. package/dist/lib/version-check.js.map +1 -0
  48. package/dist/lib/workflow-state.d.ts +23 -0
  49. package/dist/lib/workflow-state.js +112 -0
  50. package/dist/lib/workflow-state.js.map +1 -0
  51. package/dist/scripts/prepare-template.js +3 -3
  52. package/package.json +1 -1
  53. package/template/{.claude/skills/00-discover → .agents/skills/00-explore}/SKILL.md +10 -10
  54. package/template/.agents/skills/10-define/SKILL.md +4 -4
  55. package/template/.agents/skills/20-spec/SKILL.md +2 -3
  56. package/template/.agents/skills/30-plan/SKILL.md +2 -3
  57. package/template/.agents/skills/40-execute/SKILL.md +2 -2
  58. package/template/.agents/skills/50-verify/SKILL.md +2 -2
  59. package/template/.agents/skills/60-report/SKILL.md +3 -3
  60. package/template/{.claude/skills/70-release → .agents/skills/70-deliver}/SKILL.md +7 -13
  61. package/template/.agents/skills/adopt/SKILL.md +136 -73
  62. package/template/.agents/skills/audit/SKILL.md +275 -0
  63. package/template/.agents/skills/autopilot/SKILL.md +228 -147
  64. package/template/.agents/skills/brainstorm/SKILL.md +3 -3
  65. package/template/.agents/skills/brief/SKILL.md +74 -51
  66. package/template/.agents/skills/check/SKILL.md +96 -76
  67. package/template/.agents/skills/ci/SKILL.md +140 -61
  68. package/template/.agents/skills/complete/SKILL.md +156 -101
  69. package/template/.agents/skills/convert-any-to-md/SKILL.md +2 -2
  70. package/template/.agents/skills/debug/SKILL.md +124 -49
  71. package/template/.agents/skills/devflow/SKILL.md +16 -10
  72. package/template/.agents/skills/discovery/SKILL.md +166 -0
  73. package/template/.agents/skills/doctor/SKILL.md +188 -72
  74. package/template/.agents/skills/feature/SKILL.md +195 -102
  75. package/template/.agents/skills/fix/SKILL.md +41 -90
  76. package/template/.agents/skills/idea/SKILL.md +3 -3
  77. package/template/.agents/skills/implement/SKILL.md +189 -46
  78. package/template/.agents/skills/onboard/SKILL.md +215 -85
  79. package/template/.agents/skills/overview/SKILL.md +51 -85
  80. package/template/.agents/skills/prototype/SKILL.md +82 -27
  81. package/template/.agents/skills/release/SKILL.md +160 -0
  82. package/template/.agents/skills/report-html/SKILL.md +2 -2
  83. package/template/.agents/skills/rollback/SKILL.md +123 -77
  84. package/template/.agents/skills/status/SKILL.md +109 -0
  85. package/template/.agents/skills/test/SKILL.md +2 -2
  86. package/template/.agents/skills/tests/SKILL.md +126 -0
  87. package/template/.agents/skills/try/SKILL.md +77 -65
  88. package/template/{.agents/skills/00-discover → .claude/skills/00-explore}/SKILL.md +9 -9
  89. package/template/.claude/skills/10-define/SKILL.md +2 -2
  90. package/template/.claude/skills/20-spec/SKILL.md +1 -1
  91. package/template/.claude/skills/30-plan/SKILL.md +1 -1
  92. package/template/.claude/skills/60-report/SKILL.md +1 -1
  93. package/template/{.agents/skills/70-release → .claude/skills/70-deliver}/SKILL.md +6 -12
  94. package/template/.claude/skills/adopt/SKILL.md +2 -2
  95. package/template/.claude/skills/audit/SKILL.md +141 -0
  96. package/template/.claude/skills/autopilot/SKILL.md +74 -52
  97. package/template/.claude/skills/brief/SKILL.md +67 -45
  98. package/template/.claude/skills/ci/SKILL.md +1 -1
  99. package/template/.claude/skills/complete/SKILL.md +1 -1
  100. package/template/.claude/skills/debug/SKILL.md +1 -1
  101. package/template/.claude/skills/devflow/SKILL.md +7 -7
  102. package/template/.claude/skills/discovery/SKILL.md +145 -0
  103. package/template/.claude/skills/doctor/SKILL.md +1 -1
  104. package/template/.claude/skills/feature/SKILL.md +67 -18
  105. package/template/.claude/skills/fix/SKILL.md +1 -1
  106. package/template/.claude/skills/idea/SKILL.md +2 -2
  107. package/template/.claude/skills/onboard/SKILL.md +3 -3
  108. package/template/.claude/skills/overview/SKILL.md +39 -88
  109. package/template/.claude/skills/prototype/SKILL.md +1 -1
  110. package/template/.claude/skills/release/SKILL.md +171 -0
  111. package/template/.claude/skills/rollback/SKILL.md +2 -2
  112. package/template/AGENTS.md +5 -5
  113. package/template/devflow/build-plan.md +40 -0
  114. package/template/devflow/context/ai-interaction.md +4 -4
  115. package/template/devflow/context/coding-standards.md +3 -3
  116. package/template/devflow/context/current-stage.md +1 -1
  117. package/template/devflow/context/findings.md +1 -1
  118. package/template/devflow/history/HISTORY.md +2 -2
  119. package/template/devflow/project-plan.md +27 -0
  120. package/template/devflow/reference/mockup.html +476 -0
  121. package/template/devflow/reference/project-overview-template.md +39 -0
  122. package/template/devflow/reference/running-id-contract.md +24 -2
package/README.md CHANGED
@@ -45,7 +45,7 @@ The installer overlays the DevFlow workflow layer into your workspace:
45
45
  ### 2. Deep-Track (Architect Mode — 8 Steps)
46
46
  *Recommended for large architectural epics and database migrations:*
47
47
  ```text
48
- 00-discover ──▶ 10-define ──▶ 20-spec ──▶ 30-plan ──▶ 40-execute ──▶ 50-verify ──▶ 60-report ──▶ 70-release
48
+ 00-explore ──▶ 10-define ──▶ 20-spec ──▶ 30-plan ──▶ 40-execute ──▶ 50-verify ──▶ 60-report ──▶ 70-deliver
49
49
  ```
50
50
 
51
51
  ---
@@ -1,6 +1,23 @@
1
1
  #!/usr/bin/env node
2
+ import { type FindingSeverity, type FindingStatus } from "../lib/findings.js";
3
+ import { type GitHookType } from "../lib/git-hooks.js";
2
4
  interface CliOptions {
3
- command: "install" | "status" | "ui" | "update" | "uninstall" | "eject";
5
+ command: "dashboard" | "install" | "status" | "ui" | "update" | "uninstall" | "eject" | "idea" | "ideas" | "findings" | "doctor" | "archive" | "check-gate" | "hook";
6
+ subcommandAction?: "add" | "list" | "resolve" | "stats" | "install" | "uninstall";
7
+ subcommandArg?: string;
8
+ hookType?: GitHookType;
9
+ ideaTitle?: string;
10
+ findingStatus?: FindingStatus;
11
+ findingSeverity?: FindingSeverity;
12
+ findingId?: string;
13
+ findingLocation?: string;
14
+ findingImpact?: string;
15
+ findingRemediation?: string;
16
+ blockersOnly: boolean;
17
+ fix: boolean;
18
+ statsOnly: boolean;
19
+ strict: boolean;
20
+ deprecatedUi: boolean;
4
21
  target: string | null;
5
22
  adapter: string;
6
23
  force: boolean;
@@ -5,11 +5,19 @@ import readline from "node:readline/promises";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { openDashboard, startDashboardServer } from "../lib/dashboard.js";
7
7
  import { formatHumanStatus, readProjectStatus, shouldUseColor } from "../lib/status.js";
8
+ import { addIdea, formatIdeasHuman, readIdeas } from "../lib/ideas.js";
9
+ import { addFinding, formatFindingsHuman, readFindings, resolveFinding } from "../lib/findings.js";
10
+ import { formatDoctorHuman, runDoctor } from "../lib/doctor.js";
11
+ import { formatHistoryHuman, readHistory } from "../lib/history.js";
12
+ import { evaluateGate, formatGateReport } from "../lib/gatekeeper.js";
13
+ import { installGitHook, uninstallGitHooks } from "../lib/git-hooks.js";
8
14
  import { createSpinner, createStyle } from "../lib/ui.js";
9
15
  import { applyPreparedUpdate, prepareUpdate } from "../lib/update.js";
10
16
  import { applyUninstall, prepareUninstall } from "../lib/uninstall.js";
11
17
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
- const packageRoot = path.resolve(__dirname, "..", "..");
18
+ const packageRoot = fsSync.existsSync(path.join(__dirname, "..", "package.json"))
19
+ ? path.resolve(__dirname, "..")
20
+ : path.resolve(__dirname, "..", "..");
13
21
  const templateRoot = path.join(packageRoot, "template");
14
22
  const adapterChoices = new Set(["codex", "antigravity", "claude", "copilot", "both", "all"]);
15
23
  async function main(args = process.argv.slice(2)) {
@@ -23,6 +31,9 @@ async function main(args = process.argv.slice(2)) {
23
31
  return;
24
32
  }
25
33
  const targetDir = path.resolve(process.cwd(), options.target || ".");
34
+ if (options.deprecatedUi) {
35
+ console.warn("Warning: `ui` is deprecated; use `dashboard` instead.");
36
+ }
26
37
  if (options.command === "status") {
27
38
  const status = await readProjectStatus(targetDir);
28
39
  console.log(options.json
@@ -30,7 +41,163 @@ async function main(args = process.argv.slice(2)) {
30
41
  : formatHumanStatus(status, { color: shouldUseColor() }));
31
42
  return;
32
43
  }
33
- if (options.command === "ui") {
44
+ if (options.command === "check-gate") {
45
+ const report = await evaluateGate(targetDir, {
46
+ strict: options.strict,
47
+ color: shouldUseColor()
48
+ });
49
+ if (options.json) {
50
+ console.log(JSON.stringify(report, null, 2));
51
+ }
52
+ else {
53
+ console.log(formatGateReport(report, { color: shouldUseColor() }));
54
+ }
55
+ if (!report.passed) {
56
+ process.exitCode = 1;
57
+ }
58
+ return;
59
+ }
60
+ if (options.command === "hook") {
61
+ if (options.subcommandAction === "uninstall") {
62
+ const result = await uninstallGitHooks(targetDir);
63
+ if (options.json) {
64
+ console.log(JSON.stringify(result, null, 2));
65
+ }
66
+ else {
67
+ const style = createStyle(shouldUseColor());
68
+ console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
69
+ }
70
+ return;
71
+ }
72
+ // Default: install
73
+ const hookType = options.hookType || "pre-commit";
74
+ const result = await installGitHook(targetDir, hookType, { strict: options.strict });
75
+ if (options.json) {
76
+ console.log(JSON.stringify(result, null, 2));
77
+ }
78
+ else {
79
+ const style = createStyle(shouldUseColor());
80
+ if (result.success) {
81
+ console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
82
+ console.log(` ${style.dim("Hook:")} ${style.cyan(result.path)}`);
83
+ }
84
+ else {
85
+ console.error(`\n${style.red("✖")} ${style.bold(result.message)}`);
86
+ process.exitCode = 1;
87
+ }
88
+ }
89
+ return;
90
+ }
91
+ if (options.command === "idea" || options.command === "ideas") {
92
+ if (options.subcommandAction === "add") {
93
+ const text = options.subcommandArg || "";
94
+ if (!text.trim()) {
95
+ throw new Error("Idea text is required. Example: nexus-devflow idea add \"My idea\"");
96
+ }
97
+ const created = await addIdea(targetDir, {
98
+ text,
99
+ title: options.ideaTitle
100
+ });
101
+ if (options.json) {
102
+ console.log(JSON.stringify(created, null, 2));
103
+ }
104
+ else {
105
+ const style = createStyle(shouldUseColor());
106
+ console.log(`\n${style.green("✔")} ${style.bold("Idea added successfully!")}`);
107
+ console.log(` ${style.dim("ID :")} ${style.bold(style.cyan(created.id))}`);
108
+ console.log(` ${style.dim("Title:")} ${style.bold(created.title)}`);
109
+ console.log(` ${style.dim("Start:")} ${style.yellow(`/feature ${created.id}`)} or ${style.yellow(`/00-explore ${created.id}`)}`);
110
+ }
111
+ return;
112
+ }
113
+ const ideas = await readIdeas(targetDir);
114
+ console.log(options.json
115
+ ? JSON.stringify(ideas, null, 2)
116
+ : formatIdeasHuman(ideas, { color: shouldUseColor() }));
117
+ return;
118
+ }
119
+ if (options.command === "findings") {
120
+ if (options.subcommandAction === "add") {
121
+ const title = options.subcommandArg || "";
122
+ if (!title.trim()) {
123
+ throw new Error('Finding title is required. Example: nexus-devflow findings add "Hardcoded secret" --severity P0');
124
+ }
125
+ const result = await addFinding(targetDir, title, {
126
+ id: options.findingId,
127
+ severity: options.findingSeverity,
128
+ status: options.findingStatus,
129
+ location: options.findingLocation,
130
+ impact: options.findingImpact,
131
+ remediation: options.findingRemediation
132
+ });
133
+ if (options.json) {
134
+ console.log(JSON.stringify(result, null, 2));
135
+ }
136
+ else {
137
+ const style = createStyle(shouldUseColor());
138
+ console.log(`\n${style.green("✔")} ${style.bold("Finding recorded successfully!")}`);
139
+ console.log(` ${style.dim("ID :")} ${style.bold(style.cyan(result.finding?.id || ""))}`);
140
+ const sev = result.finding?.severity || "P2";
141
+ const isBlocker = sev === "P0" || sev === "P1";
142
+ console.log(` ${style.dim("Severity:")} ${style.bold(isBlocker ? style.red(`[${sev}]`) : style.yellow(`[${sev}]`))}`);
143
+ console.log(` ${style.dim("Status :")} ${style.yellow(result.finding?.status || "")}`);
144
+ console.log(` ${style.dim("Title :")} ${style.bold(result.finding?.title || "")}`);
145
+ console.log(` ${style.dim("File :")} ${style.dim(result.filePath)}`);
146
+ }
147
+ return;
148
+ }
149
+ if (options.subcommandAction === "resolve") {
150
+ const findingId = options.subcommandArg || "";
151
+ if (!findingId.trim()) {
152
+ throw new Error("Finding ID is required. Example: nexus-devflow findings resolve FIND-001");
153
+ }
154
+ const statusToSet = options.findingStatus || "closed";
155
+ const result = await resolveFinding(targetDir, findingId, statusToSet);
156
+ if (options.json) {
157
+ console.log(JSON.stringify(result, null, 2));
158
+ }
159
+ else {
160
+ const style = createStyle(shouldUseColor());
161
+ if (result.success) {
162
+ console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
163
+ }
164
+ else {
165
+ console.error(`\n${style.red("✖")} ${style.bold(result.message)}`);
166
+ process.exitCode = 1;
167
+ }
168
+ }
169
+ return;
170
+ }
171
+ const findings = await readFindings(targetDir);
172
+ console.log(options.json
173
+ ? JSON.stringify(findings, null, 2)
174
+ : formatFindingsHuman(findings, {
175
+ blockersOnly: options.blockersOnly,
176
+ color: shouldUseColor()
177
+ }));
178
+ return;
179
+ }
180
+ if (options.command === "doctor") {
181
+ const report = await runDoctor(targetDir, {
182
+ fix: options.fix,
183
+ color: shouldUseColor()
184
+ });
185
+ console.log(options.json
186
+ ? JSON.stringify(report, null, 2)
187
+ : formatDoctorHuman(report, { color: shouldUseColor() }));
188
+ return;
189
+ }
190
+ if (options.command === "archive") {
191
+ const history = await readHistory(targetDir);
192
+ console.log(options.json
193
+ ? JSON.stringify(history, null, 2)
194
+ : formatHistoryHuman(history, {
195
+ statsOnly: options.statsOnly,
196
+ color: shouldUseColor()
197
+ }));
198
+ return;
199
+ }
200
+ if (options.command === "dashboard" || options.command === "ui") {
34
201
  const server = await startDashboardServer(targetDir);
35
202
  const style = createStyle();
36
203
  console.log(style.bold(style.cyan(`Nexus-DevFlow Dashboard live at ${server.url}`)));
@@ -137,6 +304,21 @@ async function main(args = process.argv.slice(2)) {
137
304
  }
138
305
  function parseArgs(args) {
139
306
  let command = "install";
307
+ let subcommandAction;
308
+ let subcommandArg;
309
+ let hookType;
310
+ let ideaTitle;
311
+ let findingStatus;
312
+ let findingSeverity;
313
+ let findingId;
314
+ let findingLocation;
315
+ let findingImpact;
316
+ let findingRemediation;
317
+ let blockersOnly = false;
318
+ let fix = false;
319
+ let statsOnly = false;
320
+ let strict = false;
321
+ let deprecatedUi = false;
140
322
  let target = null;
141
323
  let adapter = "both";
142
324
  let force = false;
@@ -182,6 +364,110 @@ function parseArgs(args) {
182
364
  keepHistory = true;
183
365
  continue;
184
366
  }
367
+ if (arg === "--blockers") {
368
+ blockersOnly = true;
369
+ continue;
370
+ }
371
+ if (arg === "--fix") {
372
+ fix = true;
373
+ continue;
374
+ }
375
+ if (arg === "--stats") {
376
+ statsOnly = true;
377
+ continue;
378
+ }
379
+ if (arg === "--strict") {
380
+ strict = true;
381
+ continue;
382
+ }
383
+ if (arg === "--title") {
384
+ const next = args[++i];
385
+ if (!next) {
386
+ throw new Error(`${arg} requires a title string`);
387
+ }
388
+ ideaTitle = next;
389
+ continue;
390
+ }
391
+ if (arg.startsWith("--title=")) {
392
+ ideaTitle = arg.slice("--title=".length);
393
+ continue;
394
+ }
395
+ if (arg === "--status") {
396
+ const next = args[++i];
397
+ if (!next) {
398
+ throw new Error(`${arg} requires a status string (e.g. closed, accepted, invalid)`);
399
+ }
400
+ findingStatus = next.toLowerCase();
401
+ continue;
402
+ }
403
+ if (arg.startsWith("--status=")) {
404
+ findingStatus = arg.slice("--status=".length).toLowerCase();
405
+ continue;
406
+ }
407
+ if (arg === "--severity" || arg === "-s") {
408
+ const next = args[++i];
409
+ if (!next) {
410
+ throw new Error(`${arg} requires a severity level (P0, P1, P2, P3)`);
411
+ }
412
+ const sev = next.toUpperCase();
413
+ if (sev !== "P0" && sev !== "P1" && sev !== "P2" && sev !== "P3") {
414
+ throw new Error(`Invalid severity "${next}". Expected one of: P0, P1, P2, P3`);
415
+ }
416
+ findingSeverity = sev;
417
+ continue;
418
+ }
419
+ if (arg.startsWith("--severity=")) {
420
+ const sev = arg.slice("--severity=".length).toUpperCase();
421
+ if (sev !== "P0" && sev !== "P1" && sev !== "P2" && sev !== "P3") {
422
+ throw new Error(`Invalid severity "${sev}". Expected one of: P0, P1, P2, P3`);
423
+ }
424
+ findingSeverity = sev;
425
+ continue;
426
+ }
427
+ if (arg === "--id") {
428
+ const next = args[++i];
429
+ if (!next)
430
+ throw new Error(`${arg} requires an ID string`);
431
+ findingId = next;
432
+ continue;
433
+ }
434
+ if (arg.startsWith("--id=")) {
435
+ findingId = arg.slice("--id=".length);
436
+ continue;
437
+ }
438
+ if (arg === "--location") {
439
+ const next = args[++i];
440
+ if (!next)
441
+ throw new Error(`${arg} requires a location string`);
442
+ findingLocation = next;
443
+ continue;
444
+ }
445
+ if (arg.startsWith("--location=")) {
446
+ findingLocation = arg.slice("--location=".length);
447
+ continue;
448
+ }
449
+ if (arg === "--impact") {
450
+ const next = args[++i];
451
+ if (!next)
452
+ throw new Error(`${arg} requires an impact string`);
453
+ findingImpact = next;
454
+ continue;
455
+ }
456
+ if (arg.startsWith("--impact=")) {
457
+ findingImpact = arg.slice("--impact=".length);
458
+ continue;
459
+ }
460
+ if (arg === "--remediation") {
461
+ const next = args[++i];
462
+ if (!next)
463
+ throw new Error(`${arg} requires a remediation string`);
464
+ findingRemediation = next;
465
+ continue;
466
+ }
467
+ if (arg.startsWith("--remediation=")) {
468
+ findingRemediation = arg.slice("--remediation=".length);
469
+ continue;
470
+ }
185
471
  if (arg === "--target" || arg === "-t") {
186
472
  const next = args[++i];
187
473
  if (!next) {
@@ -216,27 +502,130 @@ function parseArgs(args) {
216
502
  positional.push(arg);
217
503
  }
218
504
  if (positional.length > 0) {
219
- if (positional[0] === "status") {
505
+ const first = positional[0].toLowerCase();
506
+ if (first === "status") {
220
507
  command = "status";
221
508
  target = positional[1] || target || ".";
222
509
  }
223
- else if (positional[0] === "ui") {
224
- command = "ui";
510
+ else if (first === "check-gate") {
511
+ command = "check-gate";
225
512
  target = positional[1] || target || ".";
226
513
  }
227
- else if (positional[0] === "update") {
514
+ else if (first === "hook" || first === "hooks") {
515
+ command = "hook";
516
+ if (positional[1] === "uninstall") {
517
+ subcommandAction = "uninstall";
518
+ target = positional[2] || target || ".";
519
+ }
520
+ else if (positional[1] === "install") {
521
+ subcommandAction = "install";
522
+ if (positional[2] === "pre-commit" || positional[2] === "pre-push") {
523
+ hookType = positional[2];
524
+ target = positional[3] || target || ".";
525
+ }
526
+ else {
527
+ target = positional[2] || target || ".";
528
+ }
529
+ }
530
+ else if (positional[1] === "pre-commit" || positional[1] === "pre-push") {
531
+ subcommandAction = "install";
532
+ hookType = positional[1];
533
+ target = positional[2] || target || ".";
534
+ }
535
+ else {
536
+ subcommandAction = "install";
537
+ target = positional[1] || target || ".";
538
+ }
539
+ }
540
+ else if (first === "dashboard") {
541
+ command = "dashboard";
542
+ target = positional[1] || target || ".";
543
+ }
544
+ else if (first === "ui") {
545
+ command = "dashboard";
546
+ deprecatedUi = true;
547
+ target = positional[1] || target || ".";
548
+ }
549
+ else if (first === "update") {
228
550
  command = "update";
229
551
  target = positional[1] || target || ".";
230
552
  }
231
- else if (positional[0] === "uninstall") {
553
+ else if (first === "uninstall") {
232
554
  command = "uninstall";
233
555
  target = positional[1] || target || ".";
234
556
  }
235
- else if (positional[0] === "eject") {
557
+ else if (first === "eject") {
236
558
  command = "eject";
237
559
  target = positional[1] || target || ".";
238
560
  }
239
- else if (positional[0] === "install") {
561
+ else if (first === "idea" || first === "ideas") {
562
+ command = first === "idea" ? "idea" : "ideas";
563
+ if (positional[1] === "add") {
564
+ subcommandAction = "add";
565
+ subcommandArg = positional[2];
566
+ target = positional[3] || target || ".";
567
+ }
568
+ else if (positional[1] === "list") {
569
+ subcommandAction = "list";
570
+ target = positional[2] || target || ".";
571
+ }
572
+ else if (positional[1] && !positional[1].startsWith("-")) {
573
+ subcommandAction = "add";
574
+ subcommandArg = positional[1];
575
+ target = positional[2] || target || ".";
576
+ }
577
+ else {
578
+ subcommandAction = "list";
579
+ target = positional[1] || target || ".";
580
+ }
581
+ }
582
+ else if (first === "findings") {
583
+ command = "findings";
584
+ if (positional[1] === "add") {
585
+ subcommandAction = "add";
586
+ subcommandArg = positional[2];
587
+ target = positional[3] || target || ".";
588
+ }
589
+ else if (positional[1] === "resolve") {
590
+ subcommandAction = "resolve";
591
+ subcommandArg = positional[2];
592
+ target = positional[3] || target || ".";
593
+ }
594
+ else if (positional[1] === "list") {
595
+ subcommandAction = "list";
596
+ target = positional[2] || target || ".";
597
+ }
598
+ else if (positional[1] && !positional[1].startsWith("-")) {
599
+ subcommandAction = "add";
600
+ subcommandArg = positional[1];
601
+ target = positional[2] || target || ".";
602
+ }
603
+ else {
604
+ subcommandAction = "list";
605
+ target = positional[1] || target || ".";
606
+ }
607
+ }
608
+ else if (first === "doctor") {
609
+ command = "doctor";
610
+ target = positional[1] || target || ".";
611
+ }
612
+ else if (first === "archive") {
613
+ command = "archive";
614
+ if (positional[1] === "list") {
615
+ subcommandAction = "list";
616
+ target = positional[2] || target || ".";
617
+ }
618
+ else if (positional[1] === "stats") {
619
+ subcommandAction = "stats";
620
+ statsOnly = true;
621
+ target = positional[2] || target || ".";
622
+ }
623
+ else {
624
+ subcommandAction = "list";
625
+ target = positional[1] || target || ".";
626
+ }
627
+ }
628
+ else if (first === "install") {
240
629
  command = "install";
241
630
  target = positional[1] || target || ".";
242
631
  }
@@ -246,6 +635,21 @@ function parseArgs(args) {
246
635
  }
247
636
  return {
248
637
  command,
638
+ subcommandAction,
639
+ subcommandArg,
640
+ hookType,
641
+ ideaTitle,
642
+ findingStatus,
643
+ findingSeverity,
644
+ findingId,
645
+ findingLocation,
646
+ findingImpact,
647
+ findingRemediation,
648
+ blockersOnly,
649
+ fix,
650
+ statsOnly,
651
+ strict,
652
+ deprecatedUi,
249
653
  target,
250
654
  adapter,
251
655
  force,
@@ -282,18 +686,42 @@ ${style.bold(style.cyan("Nexus-DevFlow CLI"))} ${style.bold(`v${readPackageVersi
282
686
  ${style.bold("Usage:")}
283
687
  ${style.cyan("npx @jakkrichm/create-nexus-devflow")} [target-dir] [options]
284
688
  ${style.cyan("nexus-devflow status")} [target-dir] [options]
285
- ${style.cyan("nexus-devflow ui")} [target-dir] [options]
689
+ ${style.cyan("nexus-devflow check-gate")} [--strict] [--json]
690
+ ${style.cyan("nexus-devflow hook install")} [pre-commit|pre-push]
691
+ ${style.cyan("nexus-devflow hook uninstall")}
692
+ ${style.cyan("nexus-devflow dashboard")} [target-dir] [options]
693
+ ${style.cyan("nexus-devflow idea")} add "<text>" [--title "<title>"]
694
+ ${style.cyan("nexus-devflow ideas")} [list] [--json]
695
+ ${style.cyan("nexus-devflow findings add")} "<title>" [--severity P0|P1|P2|P3] [--location <loc>]
696
+ ${style.cyan("nexus-devflow findings")} [list] [--blockers] [--json]
697
+ ${style.cyan("nexus-devflow findings resolve")} <ID> [--status <status>]
698
+ ${style.cyan("nexus-devflow doctor")} [--fix] [--json]
699
+ ${style.cyan("nexus-devflow archive")} [list|stats] [--json]
286
700
  ${style.cyan("nexus-devflow update")} [target-dir] [options]
287
701
  ${style.cyan("nexus-devflow uninstall")} [target-dir] [options]
288
702
  ${style.cyan("nexus-devflow eject")} [target-dir] [options]
289
703
 
290
704
  ${style.bold("Commands:")}
291
705
  ${style.brightCyan("status")} Show project overview, progress, findings, git status, and next action
292
- ${style.brightCyan("ui")} Run local interactive web dashboard for Nexus-DevFlow
706
+ ${style.brightCyan("check-gate")} CI/CD quality gatekeeper check (returns exit code 0 or 1)
707
+ ${style.brightCyan("hook")} Install or remove local Git pre-commit/pre-push gatekeeper hooks
708
+ ${style.brightCyan("dashboard")} Run local interactive web dashboard for Nexus-DevFlow (alias: ui)
709
+ ${style.brightCyan("idea, ideas")} Manage idea backlog: add new ideas or list pending ideas
710
+ ${style.brightCyan("findings")} Inspect findings ledger, record new findings, filter blockers, or resolve
711
+ ${style.brightCyan("doctor")} Inspect project workspace health and auto-heal missing files (--fix)
712
+ ${style.brightCyan("archive")} Explore delivered runs and release statistics from devflow/history/
293
713
  ${style.brightCyan("update")} Update existing DevFlow installation without overwriting user changes
294
714
  ${style.brightCyan("uninstall, eject")} Completely remove DevFlow workflow files and adapters from project
295
715
 
296
716
  ${style.bold("Options:")}
717
+ ${style.cyan("--strict")} Strict mode for check-gate (blocks unverified runs)
718
+ ${style.cyan("--title <text>")} Custom title for idea add
719
+ ${style.cyan("--severity, -s")} Finding severity: P0, P1, P2, P3 (default: P2)
720
+ ${style.cyan("--status <name>")} Status to set when resolving finding (default: closed)
721
+ ${style.cyan("--location <path>")} Finding source code file and line location
722
+ ${style.cyan("--blockers")} Filter findings to only active P0/P1 blockers
723
+ ${style.cyan("--fix")} Automatically repair/create missing context files in doctor
724
+ ${style.cyan("--stats")} Display history summary statistics only
297
725
  ${style.cyan("--adapter <name>")} Tool adapters to install: codex, antigravity, claude, copilot, both, all
298
726
  ${style.cyan("--no-open")} Start local dashboard without opening a browser
299
727
  ${style.cyan("--keep-history")} Keep devflow/history/ directory during uninstall