@jakkrichm/create-nexus-devflow 2.0.25 → 2.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/README.md +30 -8
- package/dist/bin/create-nexus-devflow.d.ts +22 -1
- package/dist/bin/create-nexus-devflow.js +658 -11
- package/dist/bin/create-nexus-devflow.js.map +1 -1
- package/dist/lib/branch-context.d.ts +39 -0
- package/dist/lib/branch-context.js +196 -0
- package/dist/lib/branch-context.js.map +1 -0
- package/dist/lib/code-graph.d.ts +30 -0
- package/dist/lib/code-graph.js +209 -0
- package/dist/lib/code-graph.js.map +1 -0
- package/dist/lib/command-catalog.d.ts +11 -0
- package/dist/lib/command-catalog.js +63 -0
- package/dist/lib/command-catalog.js.map +1 -0
- package/dist/lib/context-slicer.d.ts +31 -0
- package/dist/lib/context-slicer.js +234 -0
- package/dist/lib/context-slicer.js.map +1 -0
- package/dist/lib/current-work.js +97 -49
- package/dist/lib/current-work.js.map +1 -1
- package/dist/lib/dashboard-page.d.ts +2 -0
- package/dist/lib/dashboard-page.js +285 -0
- package/dist/lib/dashboard-page.js.map +1 -0
- package/dist/lib/dashboard-snapshot.d.ts +62 -0
- package/dist/lib/dashboard-snapshot.js +114 -0
- package/dist/lib/dashboard-snapshot.js.map +1 -0
- package/dist/lib/dashboard.d.ts +2 -0
- package/dist/lib/dashboard.js +398 -8
- package/dist/lib/dashboard.js.map +1 -1
- package/dist/lib/discoveries.d.ts +19 -0
- package/dist/lib/discoveries.js +81 -0
- package/dist/lib/discoveries.js.map +1 -0
- package/dist/lib/doctor.d.ts +26 -0
- package/dist/lib/doctor.js +474 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/drift-reconciler.d.ts +38 -0
- package/dist/lib/drift-reconciler.js +155 -0
- package/dist/lib/drift-reconciler.js.map +1 -0
- package/dist/lib/findings.d.ts +26 -2
- package/dist/lib/findings.js +165 -1
- package/dist/lib/findings.js.map +1 -1
- package/dist/lib/gatekeeper.d.ts +20 -0
- package/dist/lib/gatekeeper.js +106 -0
- package/dist/lib/gatekeeper.js.map +1 -0
- package/dist/lib/git-hooks.d.ts +16 -0
- package/dist/lib/git-hooks.js +103 -0
- package/dist/lib/git-hooks.js.map +1 -0
- package/dist/lib/history.d.ts +6 -1
- package/dist/lib/history.js +98 -11
- package/dist/lib/history.js.map +1 -1
- package/dist/lib/ide-extension.d.ts +38 -0
- package/dist/lib/ide-extension.js +61 -0
- package/dist/lib/ide-extension.js.map +1 -0
- package/dist/lib/ideas.d.ts +26 -0
- package/dist/lib/ideas.js +179 -0
- package/dist/lib/ideas.js.map +1 -0
- package/dist/lib/mcp.d.ts +36 -0
- package/dist/lib/mcp.js +653 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/status.d.ts +3 -1
- package/dist/lib/status.js +60 -6
- package/dist/lib/status.js.map +1 -1
- package/dist/lib/swarm-orchestrator.d.ts +31 -0
- package/dist/lib/swarm-orchestrator.js +134 -0
- package/dist/lib/swarm-orchestrator.js.map +1 -0
- package/dist/lib/update.js +2 -2
- package/dist/lib/update.js.map +1 -1
- package/dist/lib/version-check.d.ts +22 -0
- package/dist/lib/version-check.js +59 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/lib/webview-studio.d.ts +8 -0
- package/dist/lib/webview-studio.js +463 -0
- package/dist/lib/webview-studio.js.map +1 -0
- package/dist/lib/workflow-state.d.ts +23 -0
- package/dist/lib/workflow-state.js +128 -0
- package/dist/lib/workflow-state.js.map +1 -0
- package/dist/scripts/prepare-template.js +3 -3
- package/package.json +1 -1
- package/template/{.claude/skills/00-discover → .agents/skills/00-explore}/SKILL.md +10 -10
- package/template/.agents/skills/10-define/SKILL.md +4 -4
- package/template/.agents/skills/20-spec/SKILL.md +2 -3
- package/template/.agents/skills/30-plan/SKILL.md +2 -3
- package/template/.agents/skills/40-execute/SKILL.md +2 -2
- package/template/.agents/skills/50-verify/SKILL.md +2 -2
- package/template/.agents/skills/60-report/SKILL.md +3 -3
- package/template/{.claude/skills/70-release → .agents/skills/70-deliver}/SKILL.md +7 -13
- package/template/.agents/skills/adopt/SKILL.md +136 -73
- package/template/.agents/skills/audit/SKILL.md +275 -0
- package/template/.agents/skills/autopilot/SKILL.md +228 -147
- package/template/.agents/skills/brainstorm/SKILL.md +3 -3
- package/template/.agents/skills/brief/SKILL.md +74 -51
- package/template/.agents/skills/check/SKILL.md +96 -76
- package/template/.agents/skills/ci/SKILL.md +140 -61
- package/template/.agents/skills/complete/SKILL.md +156 -101
- package/template/.agents/skills/convert-any-to-md/SKILL.md +2 -2
- package/template/.agents/skills/debug/SKILL.md +124 -49
- package/template/.agents/skills/devflow/SKILL.md +16 -10
- package/template/.agents/skills/discovery/SKILL.md +166 -0
- package/template/.agents/skills/doctor/SKILL.md +188 -72
- package/template/.agents/skills/feature/SKILL.md +195 -102
- package/template/.agents/skills/fix/SKILL.md +41 -90
- package/template/.agents/skills/idea/SKILL.md +3 -3
- package/template/.agents/skills/implement/SKILL.md +189 -46
- package/template/.agents/skills/onboard/SKILL.md +215 -85
- package/template/.agents/skills/overview/SKILL.md +51 -85
- package/template/.agents/skills/prototype/SKILL.md +82 -27
- package/template/.agents/skills/release/SKILL.md +160 -0
- package/template/.agents/skills/report-html/SKILL.md +2 -2
- package/template/.agents/skills/rollback/SKILL.md +123 -77
- package/template/.agents/skills/status/SKILL.md +109 -0
- package/template/.agents/skills/test/SKILL.md +2 -2
- package/template/.agents/skills/tests/SKILL.md +126 -0
- package/template/.agents/skills/try/SKILL.md +77 -65
- package/template/{.agents/skills/00-discover → .claude/skills/00-explore}/SKILL.md +9 -9
- package/template/.claude/skills/10-define/SKILL.md +2 -2
- package/template/.claude/skills/20-spec/SKILL.md +1 -1
- package/template/.claude/skills/30-plan/SKILL.md +1 -1
- package/template/.claude/skills/60-report/SKILL.md +1 -1
- package/template/{.agents/skills/70-release → .claude/skills/70-deliver}/SKILL.md +6 -12
- package/template/.claude/skills/adopt/SKILL.md +2 -2
- package/template/.claude/skills/audit/SKILL.md +141 -0
- package/template/.claude/skills/autopilot/SKILL.md +74 -52
- package/template/.claude/skills/brief/SKILL.md +67 -45
- package/template/.claude/skills/ci/SKILL.md +1 -1
- package/template/.claude/skills/complete/SKILL.md +1 -1
- package/template/.claude/skills/debug/SKILL.md +1 -1
- package/template/.claude/skills/devflow/SKILL.md +7 -7
- package/template/.claude/skills/discovery/SKILL.md +145 -0
- package/template/.claude/skills/doctor/SKILL.md +1 -1
- package/template/.claude/skills/feature/SKILL.md +67 -18
- package/template/.claude/skills/fix/SKILL.md +1 -1
- package/template/.claude/skills/idea/SKILL.md +2 -2
- package/template/.claude/skills/onboard/SKILL.md +3 -3
- package/template/.claude/skills/overview/SKILL.md +39 -88
- package/template/.claude/skills/prototype/SKILL.md +1 -1
- package/template/.claude/skills/release/SKILL.md +171 -0
- package/template/.claude/skills/rollback/SKILL.md +2 -2
- package/template/AGENTS.md +5 -5
- package/template/devflow/build-plan.md +62 -0
- package/template/devflow/context/ai-interaction.md +4 -4
- package/template/devflow/context/coding-standards.md +3 -3
- package/template/devflow/context/current-stage.md +1 -1
- package/template/devflow/context/findings.md +1 -1
- package/template/devflow/history/HISTORY.md +2 -2
- package/template/devflow/project-plan.md +79 -0
- package/template/devflow/reference/mockup.html +476 -0
- package/template/devflow/reference/project-overview-template.md +39 -0
- package/template/devflow/reference/running-id-contract.md +24 -2
- package/template/devflow/reference/studio.html +504 -0
|
@@ -5,11 +5,25 @@ 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 { sliceContextForStage } from "../lib/context-slicer.js";
|
|
14
|
+
import { detectGitDrift, reconcileState } from "../lib/drift-reconciler.js";
|
|
15
|
+
import { renderStudioHtml } from "../lib/webview-studio.js";
|
|
16
|
+
import { buildCodeGraph, calculateBlastRadius } from "../lib/code-graph.js";
|
|
17
|
+
import { generateSwarmPlan } from "../lib/swarm-orchestrator.js";
|
|
18
|
+
import { startMcpServer } from "../lib/mcp.js";
|
|
19
|
+
import { installGitHook, uninstallGitHooks } from "../lib/git-hooks.js";
|
|
8
20
|
import { createSpinner, createStyle } from "../lib/ui.js";
|
|
9
21
|
import { applyPreparedUpdate, prepareUpdate } from "../lib/update.js";
|
|
10
22
|
import { applyUninstall, prepareUninstall } from "../lib/uninstall.js";
|
|
11
23
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
const packageRoot = path.
|
|
24
|
+
const packageRoot = fsSync.existsSync(path.join(__dirname, "..", "package.json"))
|
|
25
|
+
? path.resolve(__dirname, "..")
|
|
26
|
+
: path.resolve(__dirname, "..", "..");
|
|
13
27
|
const templateRoot = path.join(packageRoot, "template");
|
|
14
28
|
const adapterChoices = new Set(["codex", "antigravity", "claude", "copilot", "both", "all"]);
|
|
15
29
|
async function main(args = process.argv.slice(2)) {
|
|
@@ -23,6 +37,146 @@ async function main(args = process.argv.slice(2)) {
|
|
|
23
37
|
return;
|
|
24
38
|
}
|
|
25
39
|
const targetDir = path.resolve(process.cwd(), options.target || ".");
|
|
40
|
+
if (options.deprecatedUi) {
|
|
41
|
+
console.warn("Warning: `ui` is deprecated; use `dashboard` instead.");
|
|
42
|
+
}
|
|
43
|
+
if (options.command === "mcp") {
|
|
44
|
+
startMcpServer(targetDir);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (options.command === "slice") {
|
|
48
|
+
const stage = options.sliceStage || "implement";
|
|
49
|
+
const sliceResult = await sliceContextForStage(targetDir, stage, { maxTokens: options.maxTokens });
|
|
50
|
+
if (options.json) {
|
|
51
|
+
console.log(JSON.stringify(sliceResult, null, 2));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
console.log(`[DevFlow JIT Context Slice - Stage: ${sliceResult.stage}]`);
|
|
55
|
+
console.log(`Estimated Tokens: ~${sliceResult.estimatedTokens} (Reduction: ~${sliceResult.reductionPercentage}%)\n`);
|
|
56
|
+
console.log(sliceResult.content);
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (options.command === "drift") {
|
|
61
|
+
const drift = await detectGitDrift(targetDir);
|
|
62
|
+
if (options.json) {
|
|
63
|
+
console.log(JSON.stringify(drift, null, 2));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const style = createStyle();
|
|
67
|
+
if (!drift.hasDrift && drift.phantomFiles.length === 0) {
|
|
68
|
+
console.log(style.green("✔ No Git drift detected. Living spec is in sync with repository files."));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
console.log(style.bold(style.yellow("Git Drift Detection Report:")));
|
|
72
|
+
if (drift.undocumentedFiles.length > 0) {
|
|
73
|
+
console.log(style.red(` - Undocumented modified files (${drift.undocumentedFiles.length}):`));
|
|
74
|
+
for (const f of drift.undocumentedFiles) {
|
|
75
|
+
console.log(` ✖ ${f}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (drift.phantomFiles.length > 0) {
|
|
79
|
+
console.log(style.yellow(` - Phantom spec files (not modified in git) (${drift.phantomFiles.length}):`));
|
|
80
|
+
for (const f of drift.phantomFiles) {
|
|
81
|
+
console.log(` ⚠ ${f}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (drift.stageDrift.isDrifted) {
|
|
85
|
+
console.log(style.yellow(` - Stage alignment drift: Active branch '${drift.stageDrift.activeBranch}' vs Stage ID '${drift.stageDrift.stageRunningId}'`));
|
|
86
|
+
}
|
|
87
|
+
console.log(`\nRun ${style.cyan("nexus-devflow reconcile --fix")} to auto-heal spec alignment.`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (options.command === "reconcile") {
|
|
93
|
+
const result = await reconcileState(targetDir, {
|
|
94
|
+
autoAddUndocumented: options.fix,
|
|
95
|
+
healStage: options.fix
|
|
96
|
+
});
|
|
97
|
+
if (options.json) {
|
|
98
|
+
console.log(JSON.stringify(result, null, 2));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const style = createStyle();
|
|
102
|
+
if (result.reconciled) {
|
|
103
|
+
console.log(style.green(`✔ ${result.message}`));
|
|
104
|
+
if (result.addedFiles.length > 0) {
|
|
105
|
+
for (const f of result.addedFiles) {
|
|
106
|
+
console.log(style.dim(` + Added to spec: ${f}`));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
console.log(style.dim(result.message));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (options.command === "studio") {
|
|
117
|
+
const html = await renderStudioHtml(targetDir);
|
|
118
|
+
if (options.json) {
|
|
119
|
+
console.log(JSON.stringify({ html }, null, 2));
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
console.log(html);
|
|
123
|
+
}
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (options.command === "swarm") {
|
|
127
|
+
const plan = await generateSwarmPlan(targetDir);
|
|
128
|
+
if (options.json) {
|
|
129
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const style = createStyle();
|
|
133
|
+
console.log(style.bold(style.cyan(`[Nexus-DevFlow Multi-Agent Swarm Matrix: ${plan.runId}]`)));
|
|
134
|
+
console.log(`Title: ${plan.title} (Strategy: ${plan.executionStrategy})\n`);
|
|
135
|
+
for (const t of plan.tasks) {
|
|
136
|
+
const roleIcon = t.role === "coder" ? "👨💻" : t.role === "qa" ? "🕵️" : t.role === "security" ? "🛡️" : "👑";
|
|
137
|
+
console.log(` ${roleIcon} ${style.bold(t.id)}: ${t.title} [Role: ${t.role.toUpperCase()}]`);
|
|
138
|
+
console.log(style.dim(` Context: ${t.requiredContext.join(", ")}`));
|
|
139
|
+
console.log(style.dim(` Verify : ${t.verificationCriterion}`));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (options.command === "graph") {
|
|
145
|
+
const graph = await buildCodeGraph(targetDir);
|
|
146
|
+
if (options.graphFile) {
|
|
147
|
+
const blast = calculateBlastRadius(graph, options.graphFile);
|
|
148
|
+
if (options.json) {
|
|
149
|
+
console.log(JSON.stringify(blast, null, 2));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const style = createStyle();
|
|
153
|
+
console.log(style.bold(style.cyan(`[Code Graph Blast Radius: ${blast.targetFile}]`)));
|
|
154
|
+
console.log(`Impact Score: ${blast.impactScore} | Total Affected: ${blast.totalAffected} files\n`);
|
|
155
|
+
if (blast.directDependents.length > 0) {
|
|
156
|
+
console.log(style.bold("Direct Dependents:"));
|
|
157
|
+
for (const d of blast.directDependents)
|
|
158
|
+
console.log(` - ${d}`);
|
|
159
|
+
}
|
|
160
|
+
if (blast.transitiveDependents.length > 0) {
|
|
161
|
+
console.log(style.bold("Transitive Dependents:"));
|
|
162
|
+
for (const t of blast.transitiveDependents)
|
|
163
|
+
console.log(` ~ ${t}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
if (options.json) {
|
|
169
|
+
console.log(JSON.stringify({ totalFiles: graph.totalFiles, totalEdges: graph.totalEdges, files: Object.keys(graph.nodes) }, null, 2));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const style = createStyle();
|
|
173
|
+
console.log(style.bold(style.cyan("[Nexus-DevFlow Semantic Code Graph]")));
|
|
174
|
+
console.log(`Indexed Files: ${graph.totalFiles} | Total Dependency Edges: ${graph.totalEdges}`);
|
|
175
|
+
console.log(`\nRun ${style.yellow("nexus-devflow graph --file <path>")} to calculate Blast Radius.`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
26
180
|
if (options.command === "status") {
|
|
27
181
|
const status = await readProjectStatus(targetDir);
|
|
28
182
|
console.log(options.json
|
|
@@ -30,7 +184,163 @@ async function main(args = process.argv.slice(2)) {
|
|
|
30
184
|
: formatHumanStatus(status, { color: shouldUseColor() }));
|
|
31
185
|
return;
|
|
32
186
|
}
|
|
33
|
-
if (options.command === "
|
|
187
|
+
if (options.command === "check-gate") {
|
|
188
|
+
const report = await evaluateGate(targetDir, {
|
|
189
|
+
strict: options.strict,
|
|
190
|
+
color: shouldUseColor()
|
|
191
|
+
});
|
|
192
|
+
if (options.json) {
|
|
193
|
+
console.log(JSON.stringify(report, null, 2));
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
console.log(formatGateReport(report, { color: shouldUseColor() }));
|
|
197
|
+
}
|
|
198
|
+
if (!report.passed) {
|
|
199
|
+
process.exitCode = 1;
|
|
200
|
+
}
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (options.command === "hook") {
|
|
204
|
+
if (options.subcommandAction === "uninstall") {
|
|
205
|
+
const result = await uninstallGitHooks(targetDir);
|
|
206
|
+
if (options.json) {
|
|
207
|
+
console.log(JSON.stringify(result, null, 2));
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
const style = createStyle(shouldUseColor());
|
|
211
|
+
console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
// Default: install
|
|
216
|
+
const hookType = options.hookType || "pre-commit";
|
|
217
|
+
const result = await installGitHook(targetDir, hookType, { strict: options.strict });
|
|
218
|
+
if (options.json) {
|
|
219
|
+
console.log(JSON.stringify(result, null, 2));
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
const style = createStyle(shouldUseColor());
|
|
223
|
+
if (result.success) {
|
|
224
|
+
console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
|
|
225
|
+
console.log(` ${style.dim("Hook:")} ${style.cyan(result.path)}`);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
console.error(`\n${style.red("✖")} ${style.bold(result.message)}`);
|
|
229
|
+
process.exitCode = 1;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (options.command === "idea" || options.command === "ideas") {
|
|
235
|
+
if (options.subcommandAction === "add") {
|
|
236
|
+
const text = options.subcommandArg || "";
|
|
237
|
+
if (!text.trim()) {
|
|
238
|
+
throw new Error("Idea text is required. Example: nexus-devflow idea add \"My idea\"");
|
|
239
|
+
}
|
|
240
|
+
const created = await addIdea(targetDir, {
|
|
241
|
+
text,
|
|
242
|
+
title: options.ideaTitle
|
|
243
|
+
});
|
|
244
|
+
if (options.json) {
|
|
245
|
+
console.log(JSON.stringify(created, null, 2));
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
const style = createStyle(shouldUseColor());
|
|
249
|
+
console.log(`\n${style.green("✔")} ${style.bold("Idea added successfully!")}`);
|
|
250
|
+
console.log(` ${style.dim("ID :")} ${style.bold(style.cyan(created.id))}`);
|
|
251
|
+
console.log(` ${style.dim("Title:")} ${style.bold(created.title)}`);
|
|
252
|
+
console.log(` ${style.dim("Start:")} ${style.yellow(`/feature ${created.id}`)} or ${style.yellow(`/00-explore ${created.id}`)}`);
|
|
253
|
+
}
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const ideas = await readIdeas(targetDir);
|
|
257
|
+
console.log(options.json
|
|
258
|
+
? JSON.stringify(ideas, null, 2)
|
|
259
|
+
: formatIdeasHuman(ideas, { color: shouldUseColor() }));
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (options.command === "findings") {
|
|
263
|
+
if (options.subcommandAction === "add") {
|
|
264
|
+
const title = options.subcommandArg || "";
|
|
265
|
+
if (!title.trim()) {
|
|
266
|
+
throw new Error('Finding title is required. Example: nexus-devflow findings add "Hardcoded secret" --severity P0');
|
|
267
|
+
}
|
|
268
|
+
const result = await addFinding(targetDir, title, {
|
|
269
|
+
id: options.findingId,
|
|
270
|
+
severity: options.findingSeverity,
|
|
271
|
+
status: options.findingStatus,
|
|
272
|
+
location: options.findingLocation,
|
|
273
|
+
impact: options.findingImpact,
|
|
274
|
+
remediation: options.findingRemediation
|
|
275
|
+
});
|
|
276
|
+
if (options.json) {
|
|
277
|
+
console.log(JSON.stringify(result, null, 2));
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const style = createStyle(shouldUseColor());
|
|
281
|
+
console.log(`\n${style.green("✔")} ${style.bold("Finding recorded successfully!")}`);
|
|
282
|
+
console.log(` ${style.dim("ID :")} ${style.bold(style.cyan(result.finding?.id || ""))}`);
|
|
283
|
+
const sev = result.finding?.severity || "P2";
|
|
284
|
+
const isBlocker = sev === "P0" || sev === "P1";
|
|
285
|
+
console.log(` ${style.dim("Severity:")} ${style.bold(isBlocker ? style.red(`[${sev}]`) : style.yellow(`[${sev}]`))}`);
|
|
286
|
+
console.log(` ${style.dim("Status :")} ${style.yellow(result.finding?.status || "")}`);
|
|
287
|
+
console.log(` ${style.dim("Title :")} ${style.bold(result.finding?.title || "")}`);
|
|
288
|
+
console.log(` ${style.dim("File :")} ${style.dim(result.filePath)}`);
|
|
289
|
+
}
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (options.subcommandAction === "resolve") {
|
|
293
|
+
const findingId = options.subcommandArg || "";
|
|
294
|
+
if (!findingId.trim()) {
|
|
295
|
+
throw new Error("Finding ID is required. Example: nexus-devflow findings resolve FIND-001");
|
|
296
|
+
}
|
|
297
|
+
const statusToSet = options.findingStatus || "closed";
|
|
298
|
+
const result = await resolveFinding(targetDir, findingId, statusToSet);
|
|
299
|
+
if (options.json) {
|
|
300
|
+
console.log(JSON.stringify(result, null, 2));
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
const style = createStyle(shouldUseColor());
|
|
304
|
+
if (result.success) {
|
|
305
|
+
console.log(`\n${style.green("✔")} ${style.bold(result.message)}`);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
console.error(`\n${style.red("✖")} ${style.bold(result.message)}`);
|
|
309
|
+
process.exitCode = 1;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
const findings = await readFindings(targetDir);
|
|
315
|
+
console.log(options.json
|
|
316
|
+
? JSON.stringify(findings, null, 2)
|
|
317
|
+
: formatFindingsHuman(findings, {
|
|
318
|
+
blockersOnly: options.blockersOnly,
|
|
319
|
+
color: shouldUseColor()
|
|
320
|
+
}));
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (options.command === "doctor") {
|
|
324
|
+
const report = await runDoctor(targetDir, {
|
|
325
|
+
fix: options.fix,
|
|
326
|
+
color: shouldUseColor()
|
|
327
|
+
});
|
|
328
|
+
console.log(options.json
|
|
329
|
+
? JSON.stringify(report, null, 2)
|
|
330
|
+
: formatDoctorHuman(report, { color: shouldUseColor() }));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (options.command === "archive") {
|
|
334
|
+
const history = await readHistory(targetDir);
|
|
335
|
+
console.log(options.json
|
|
336
|
+
? JSON.stringify(history, null, 2)
|
|
337
|
+
: formatHistoryHuman(history, {
|
|
338
|
+
statsOnly: options.statsOnly,
|
|
339
|
+
color: shouldUseColor()
|
|
340
|
+
}));
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
if (options.command === "dashboard" || options.command === "ui") {
|
|
34
344
|
const server = await startDashboardServer(targetDir);
|
|
35
345
|
const style = createStyle();
|
|
36
346
|
console.log(style.bold(style.cyan(`Nexus-DevFlow Dashboard live at ${server.url}`)));
|
|
@@ -137,6 +447,24 @@ async function main(args = process.argv.slice(2)) {
|
|
|
137
447
|
}
|
|
138
448
|
function parseArgs(args) {
|
|
139
449
|
let command = "install";
|
|
450
|
+
let subcommandAction;
|
|
451
|
+
let subcommandArg;
|
|
452
|
+
let graphFile;
|
|
453
|
+
let sliceStage;
|
|
454
|
+
let maxTokens;
|
|
455
|
+
let hookType;
|
|
456
|
+
let ideaTitle;
|
|
457
|
+
let findingStatus;
|
|
458
|
+
let findingSeverity;
|
|
459
|
+
let findingId;
|
|
460
|
+
let findingLocation;
|
|
461
|
+
let findingImpact;
|
|
462
|
+
let findingRemediation;
|
|
463
|
+
let blockersOnly = false;
|
|
464
|
+
let fix = false;
|
|
465
|
+
let statsOnly = false;
|
|
466
|
+
let strict = false;
|
|
467
|
+
let deprecatedUi = false;
|
|
140
468
|
let target = null;
|
|
141
469
|
let adapter = "both";
|
|
142
470
|
let force = false;
|
|
@@ -182,6 +510,137 @@ function parseArgs(args) {
|
|
|
182
510
|
keepHistory = true;
|
|
183
511
|
continue;
|
|
184
512
|
}
|
|
513
|
+
if (arg === "--blockers") {
|
|
514
|
+
blockersOnly = true;
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
if (arg === "--file" && args[i + 1] && !args[i + 1].startsWith("-")) {
|
|
518
|
+
graphFile = args[i + 1];
|
|
519
|
+
i++;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (arg === "--fix") {
|
|
523
|
+
fix = true;
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
if (arg === "--stats") {
|
|
527
|
+
statsOnly = true;
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (arg === "--strict") {
|
|
531
|
+
strict = true;
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
if (arg === "--title") {
|
|
535
|
+
const next = args[++i];
|
|
536
|
+
if (!next) {
|
|
537
|
+
throw new Error(`${arg} requires a title string`);
|
|
538
|
+
}
|
|
539
|
+
ideaTitle = next;
|
|
540
|
+
continue;
|
|
541
|
+
}
|
|
542
|
+
if (arg.startsWith("--title=")) {
|
|
543
|
+
ideaTitle = arg.slice("--title=".length);
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
if (arg === "--status") {
|
|
547
|
+
const next = args[++i];
|
|
548
|
+
if (!next) {
|
|
549
|
+
throw new Error(`${arg} requires a status string (e.g. closed, accepted, invalid)`);
|
|
550
|
+
}
|
|
551
|
+
findingStatus = next.toLowerCase();
|
|
552
|
+
continue;
|
|
553
|
+
}
|
|
554
|
+
if (arg.startsWith("--status=")) {
|
|
555
|
+
findingStatus = arg.slice("--status=".length).toLowerCase();
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
if (arg === "--severity" || arg === "-s") {
|
|
559
|
+
const next = args[++i];
|
|
560
|
+
if (!next) {
|
|
561
|
+
throw new Error(`${arg} requires a severity level (P0, P1, P2, P3)`);
|
|
562
|
+
}
|
|
563
|
+
const sev = next.toUpperCase();
|
|
564
|
+
if (sev !== "P0" && sev !== "P1" && sev !== "P2" && sev !== "P3") {
|
|
565
|
+
throw new Error(`Invalid severity "${next}". Expected one of: P0, P1, P2, P3`);
|
|
566
|
+
}
|
|
567
|
+
findingSeverity = sev;
|
|
568
|
+
continue;
|
|
569
|
+
}
|
|
570
|
+
if (arg.startsWith("--severity=")) {
|
|
571
|
+
const sev = arg.slice("--severity=".length).toUpperCase();
|
|
572
|
+
if (sev !== "P0" && sev !== "P1" && sev !== "P2" && sev !== "P3") {
|
|
573
|
+
throw new Error(`Invalid severity "${sev}". Expected one of: P0, P1, P2, P3`);
|
|
574
|
+
}
|
|
575
|
+
findingSeverity = sev;
|
|
576
|
+
continue;
|
|
577
|
+
}
|
|
578
|
+
if (arg === "--id") {
|
|
579
|
+
const next = args[++i];
|
|
580
|
+
if (!next)
|
|
581
|
+
throw new Error(`${arg} requires an ID string`);
|
|
582
|
+
findingId = next;
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
if (arg.startsWith("--id=")) {
|
|
586
|
+
findingId = arg.slice("--id=".length);
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
if (arg === "--location") {
|
|
590
|
+
const next = args[++i];
|
|
591
|
+
if (!next)
|
|
592
|
+
throw new Error(`${arg} requires a location string`);
|
|
593
|
+
findingLocation = next;
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
if (arg.startsWith("--location=")) {
|
|
597
|
+
findingLocation = arg.slice("--location=".length);
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
if (arg === "--impact") {
|
|
601
|
+
const next = args[++i];
|
|
602
|
+
if (!next)
|
|
603
|
+
throw new Error(`${arg} requires an impact string`);
|
|
604
|
+
findingImpact = next;
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
if (arg.startsWith("--impact=")) {
|
|
608
|
+
findingImpact = arg.slice("--impact=".length);
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
if (arg === "--remediation") {
|
|
612
|
+
const next = args[++i];
|
|
613
|
+
if (!next)
|
|
614
|
+
throw new Error(`${arg} requires a remediation string`);
|
|
615
|
+
findingRemediation = next;
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
if (arg.startsWith("--remediation=")) {
|
|
619
|
+
findingRemediation = arg.slice("--remediation=".length);
|
|
620
|
+
continue;
|
|
621
|
+
}
|
|
622
|
+
if (arg === "--stage") {
|
|
623
|
+
const next = args[++i];
|
|
624
|
+
if (!next)
|
|
625
|
+
throw new Error(`${arg} requires a stage name`);
|
|
626
|
+
sliceStage = next.toLowerCase();
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
if (arg.startsWith("--stage=")) {
|
|
630
|
+
sliceStage = arg.slice("--stage=".length).toLowerCase();
|
|
631
|
+
continue;
|
|
632
|
+
}
|
|
633
|
+
if (arg === "--max-tokens") {
|
|
634
|
+
const next = args[++i];
|
|
635
|
+
if (!next || isNaN(Number(next)))
|
|
636
|
+
throw new Error(`${arg} requires a number`);
|
|
637
|
+
maxTokens = Number(next);
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
if (arg.startsWith("--max-tokens=")) {
|
|
641
|
+
maxTokens = Number(arg.slice("--max-tokens=".length));
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
185
644
|
if (arg === "--target" || arg === "-t") {
|
|
186
645
|
const next = args[++i];
|
|
187
646
|
if (!next) {
|
|
@@ -216,27 +675,164 @@ function parseArgs(args) {
|
|
|
216
675
|
positional.push(arg);
|
|
217
676
|
}
|
|
218
677
|
if (positional.length > 0) {
|
|
219
|
-
|
|
678
|
+
const first = positional[0].toLowerCase();
|
|
679
|
+
if (first === "status") {
|
|
220
680
|
command = "status";
|
|
221
681
|
target = positional[1] || target || ".";
|
|
222
682
|
}
|
|
223
|
-
else if (
|
|
224
|
-
command = "
|
|
683
|
+
else if (first === "mcp") {
|
|
684
|
+
command = "mcp";
|
|
685
|
+
target = positional[1] || target || ".";
|
|
686
|
+
}
|
|
687
|
+
else if (first === "slice") {
|
|
688
|
+
command = "slice";
|
|
689
|
+
if (positional[1] && !positional[1].startsWith("-")) {
|
|
690
|
+
sliceStage = positional[1].toLowerCase();
|
|
691
|
+
target = positional[2] || target || ".";
|
|
692
|
+
}
|
|
693
|
+
else {
|
|
694
|
+
target = positional[1] || target || ".";
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
else if (first === "drift") {
|
|
698
|
+
command = "drift";
|
|
699
|
+
target = positional[1] || target || ".";
|
|
700
|
+
}
|
|
701
|
+
else if (first === "reconcile") {
|
|
702
|
+
command = "reconcile";
|
|
703
|
+
target = positional[1] || target || ".";
|
|
704
|
+
}
|
|
705
|
+
else if (first === "studio") {
|
|
706
|
+
command = "studio";
|
|
707
|
+
target = positional[1] || target || ".";
|
|
708
|
+
}
|
|
709
|
+
else if (first === "swarm") {
|
|
710
|
+
command = "swarm";
|
|
225
711
|
target = positional[1] || target || ".";
|
|
226
712
|
}
|
|
227
|
-
else if (
|
|
713
|
+
else if (first === "graph") {
|
|
714
|
+
command = "graph";
|
|
715
|
+
target = positional[1] || target || ".";
|
|
716
|
+
}
|
|
717
|
+
else if (first === "check-gate") {
|
|
718
|
+
command = "check-gate";
|
|
719
|
+
target = positional[1] || target || ".";
|
|
720
|
+
}
|
|
721
|
+
else if (first === "hook" || first === "hooks") {
|
|
722
|
+
command = "hook";
|
|
723
|
+
if (positional[1] === "uninstall") {
|
|
724
|
+
subcommandAction = "uninstall";
|
|
725
|
+
target = positional[2] || target || ".";
|
|
726
|
+
}
|
|
727
|
+
else if (positional[1] === "install") {
|
|
728
|
+
subcommandAction = "install";
|
|
729
|
+
if (positional[2] === "pre-commit" || positional[2] === "pre-push") {
|
|
730
|
+
hookType = positional[2];
|
|
731
|
+
target = positional[3] || target || ".";
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
target = positional[2] || target || ".";
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
else if (positional[1] === "pre-commit" || positional[1] === "pre-push") {
|
|
738
|
+
subcommandAction = "install";
|
|
739
|
+
hookType = positional[1];
|
|
740
|
+
target = positional[2] || target || ".";
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
subcommandAction = "install";
|
|
744
|
+
target = positional[1] || target || ".";
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
else if (first === "dashboard") {
|
|
748
|
+
command = "dashboard";
|
|
749
|
+
target = positional[1] || target || ".";
|
|
750
|
+
}
|
|
751
|
+
else if (first === "ui") {
|
|
752
|
+
command = "dashboard";
|
|
753
|
+
deprecatedUi = true;
|
|
754
|
+
target = positional[1] || target || ".";
|
|
755
|
+
}
|
|
756
|
+
else if (first === "update") {
|
|
228
757
|
command = "update";
|
|
229
758
|
target = positional[1] || target || ".";
|
|
230
759
|
}
|
|
231
|
-
else if (
|
|
760
|
+
else if (first === "uninstall") {
|
|
232
761
|
command = "uninstall";
|
|
233
762
|
target = positional[1] || target || ".";
|
|
234
763
|
}
|
|
235
|
-
else if (
|
|
764
|
+
else if (first === "eject") {
|
|
236
765
|
command = "eject";
|
|
237
766
|
target = positional[1] || target || ".";
|
|
238
767
|
}
|
|
239
|
-
else if (
|
|
768
|
+
else if (first === "idea" || first === "ideas") {
|
|
769
|
+
command = first === "idea" ? "idea" : "ideas";
|
|
770
|
+
if (positional[1] === "add") {
|
|
771
|
+
subcommandAction = "add";
|
|
772
|
+
subcommandArg = positional[2];
|
|
773
|
+
target = positional[3] || target || ".";
|
|
774
|
+
}
|
|
775
|
+
else if (positional[1] === "list") {
|
|
776
|
+
subcommandAction = "list";
|
|
777
|
+
target = positional[2] || target || ".";
|
|
778
|
+
}
|
|
779
|
+
else if (positional[1] && !positional[1].startsWith("-")) {
|
|
780
|
+
subcommandAction = "add";
|
|
781
|
+
subcommandArg = positional[1];
|
|
782
|
+
target = positional[2] || target || ".";
|
|
783
|
+
}
|
|
784
|
+
else {
|
|
785
|
+
subcommandAction = "list";
|
|
786
|
+
target = positional[1] || target || ".";
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
else if (first === "findings") {
|
|
790
|
+
command = "findings";
|
|
791
|
+
if (positional[1] === "add") {
|
|
792
|
+
subcommandAction = "add";
|
|
793
|
+
subcommandArg = positional[2];
|
|
794
|
+
target = positional[3] || target || ".";
|
|
795
|
+
}
|
|
796
|
+
else if (positional[1] === "resolve") {
|
|
797
|
+
subcommandAction = "resolve";
|
|
798
|
+
subcommandArg = positional[2];
|
|
799
|
+
target = positional[3] || target || ".";
|
|
800
|
+
}
|
|
801
|
+
else if (positional[1] === "list") {
|
|
802
|
+
subcommandAction = "list";
|
|
803
|
+
target = positional[2] || target || ".";
|
|
804
|
+
}
|
|
805
|
+
else if (positional[1] && !positional[1].startsWith("-")) {
|
|
806
|
+
subcommandAction = "add";
|
|
807
|
+
subcommandArg = positional[1];
|
|
808
|
+
target = positional[2] || target || ".";
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
subcommandAction = "list";
|
|
812
|
+
target = positional[1] || target || ".";
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
else if (first === "doctor") {
|
|
816
|
+
command = "doctor";
|
|
817
|
+
target = positional[1] || target || ".";
|
|
818
|
+
}
|
|
819
|
+
else if (first === "archive") {
|
|
820
|
+
command = "archive";
|
|
821
|
+
if (positional[1] === "list") {
|
|
822
|
+
subcommandAction = "list";
|
|
823
|
+
target = positional[2] || target || ".";
|
|
824
|
+
}
|
|
825
|
+
else if (positional[1] === "stats") {
|
|
826
|
+
subcommandAction = "stats";
|
|
827
|
+
statsOnly = true;
|
|
828
|
+
target = positional[2] || target || ".";
|
|
829
|
+
}
|
|
830
|
+
else {
|
|
831
|
+
subcommandAction = "list";
|
|
832
|
+
target = positional[1] || target || ".";
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
else if (first === "install") {
|
|
240
836
|
command = "install";
|
|
241
837
|
target = positional[1] || target || ".";
|
|
242
838
|
}
|
|
@@ -246,6 +842,24 @@ function parseArgs(args) {
|
|
|
246
842
|
}
|
|
247
843
|
return {
|
|
248
844
|
command,
|
|
845
|
+
subcommandAction,
|
|
846
|
+
subcommandArg,
|
|
847
|
+
graphFile,
|
|
848
|
+
sliceStage,
|
|
849
|
+
maxTokens,
|
|
850
|
+
hookType,
|
|
851
|
+
ideaTitle,
|
|
852
|
+
findingStatus,
|
|
853
|
+
findingSeverity,
|
|
854
|
+
findingId,
|
|
855
|
+
findingLocation,
|
|
856
|
+
findingImpact,
|
|
857
|
+
findingRemediation,
|
|
858
|
+
blockersOnly,
|
|
859
|
+
fix,
|
|
860
|
+
statsOnly,
|
|
861
|
+
strict,
|
|
862
|
+
deprecatedUi,
|
|
249
863
|
target,
|
|
250
864
|
adapter,
|
|
251
865
|
force,
|
|
@@ -282,18 +896,51 @@ ${style.bold(style.cyan("Nexus-DevFlow CLI"))} ${style.bold(`v${readPackageVersi
|
|
|
282
896
|
${style.bold("Usage:")}
|
|
283
897
|
${style.cyan("npx @jakkrichm/create-nexus-devflow")} [target-dir] [options]
|
|
284
898
|
${style.cyan("nexus-devflow status")} [target-dir] [options]
|
|
285
|
-
${style.cyan("nexus-devflow
|
|
899
|
+
${style.cyan("nexus-devflow mcp")} [target-dir]
|
|
900
|
+
${style.cyan("nexus-devflow slice")} [--stage <stage>] [--max-tokens <num>] [--json]
|
|
901
|
+
${style.cyan("nexus-devflow drift")} [target-dir] [--json]
|
|
902
|
+
${style.cyan("nexus-devflow reconcile")} [target-dir] [--fix] [--json]
|
|
903
|
+
${style.cyan("nexus-devflow studio")} [target-dir] [--json]
|
|
904
|
+
${style.cyan("nexus-devflow swarm")} [target-dir] [--json]
|
|
905
|
+
${style.cyan("nexus-devflow graph")} [target-dir] [--file <path>] [--json]
|
|
906
|
+
${style.cyan("nexus-devflow check-gate")} [--strict] [--json]
|
|
907
|
+
${style.cyan("nexus-devflow hook install")} [pre-commit|pre-push]
|
|
908
|
+
${style.cyan("nexus-devflow hook uninstall")}
|
|
909
|
+
${style.cyan("nexus-devflow dashboard")} [target-dir] [options]
|
|
910
|
+
${style.cyan("nexus-devflow idea")} add "<text>" [--title "<title>"]
|
|
911
|
+
${style.cyan("nexus-devflow ideas")} [list] [--json]
|
|
912
|
+
${style.cyan("nexus-devflow findings add")} "<title>" [--severity P0|P1|P2|P3] [--location <loc>]
|
|
913
|
+
${style.cyan("nexus-devflow findings")} [list] [--blockers] [--json]
|
|
914
|
+
${style.cyan("nexus-devflow findings resolve")} <ID> [--status <status>]
|
|
915
|
+
${style.cyan("nexus-devflow doctor")} [--fix] [--json]
|
|
916
|
+
${style.cyan("nexus-devflow archive")} [list|stats] [--json]
|
|
286
917
|
${style.cyan("nexus-devflow update")} [target-dir] [options]
|
|
287
918
|
${style.cyan("nexus-devflow uninstall")} [target-dir] [options]
|
|
288
919
|
${style.cyan("nexus-devflow eject")} [target-dir] [options]
|
|
289
920
|
|
|
290
921
|
${style.bold("Commands:")}
|
|
291
922
|
${style.brightCyan("status")} Show project overview, progress, findings, git status, and next action
|
|
292
|
-
${style.brightCyan("
|
|
923
|
+
${style.brightCyan("mcp")} Run Model Context Protocol (MCP) JSON-RPC Stdio Server for AI agents
|
|
924
|
+
${style.brightCyan("slice")} Generate JIT stage-aware context slice (reduces AI tokens by 60-70%)
|
|
925
|
+
${style.brightCyan("check-gate")} CI/CD quality gatekeeper check (returns exit code 0 or 1)
|
|
926
|
+
${style.brightCyan("hook")} Install or remove local Git pre-commit/pre-push gatekeeper hooks
|
|
927
|
+
${style.brightCyan("dashboard")} Run local interactive web dashboard for Nexus-DevFlow (alias: ui)
|
|
928
|
+
${style.brightCyan("idea, ideas")} Manage idea backlog: add new ideas or list pending ideas
|
|
929
|
+
${style.brightCyan("findings")} Inspect findings ledger, record new findings, filter blockers, or resolve
|
|
930
|
+
${style.brightCyan("doctor")} Inspect project workspace health and auto-heal missing files (--fix)
|
|
931
|
+
${style.brightCyan("archive")} Explore delivered runs and release statistics from devflow/history/
|
|
293
932
|
${style.brightCyan("update")} Update existing DevFlow installation without overwriting user changes
|
|
294
933
|
${style.brightCyan("uninstall, eject")} Completely remove DevFlow workflow files and adapters from project
|
|
295
934
|
|
|
296
935
|
${style.bold("Options:")}
|
|
936
|
+
${style.cyan("--strict")} Strict mode for check-gate (blocks unverified runs)
|
|
937
|
+
${style.cyan("--title <text>")} Custom title for idea add
|
|
938
|
+
${style.cyan("--severity, -s")} Finding severity: P0, P1, P2, P3 (default: P2)
|
|
939
|
+
${style.cyan("--status <name>")} Status to set when resolving finding (default: closed)
|
|
940
|
+
${style.cyan("--location <path>")} Finding source code file and line location
|
|
941
|
+
${style.cyan("--blockers")} Filter findings to only active P0/P1 blockers
|
|
942
|
+
${style.cyan("--fix")} Automatically repair/create missing context files in doctor
|
|
943
|
+
${style.cyan("--stats")} Display history summary statistics only
|
|
297
944
|
${style.cyan("--adapter <name>")} Tool adapters to install: codex, antigravity, claude, copilot, both, all
|
|
298
945
|
${style.cyan("--no-open")} Start local dashboard without opening a browser
|
|
299
946
|
${style.cyan("--keep-history")} Keep devflow/history/ directory during uninstall
|