@jakkrichm/create-nexus-devflow 2.0.12 → 2.0.14
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/dist/bin/create-nexus-devflow.d.ts +2 -0
- package/dist/bin/create-nexus-devflow.js +233 -0
- package/dist/bin/create-nexus-devflow.js.map +1 -0
- package/dist/lib/starter-templates.d.ts +6 -0
- package/dist/lib/starter-templates.js +8 -0
- package/dist/lib/starter-templates.js.map +1 -0
- package/dist/lib/update.d.ts +68 -0
- package/dist/lib/update.js +325 -0
- package/dist/lib/update.js.map +1 -0
- package/dist/scripts/clean-template.d.ts +1 -0
- package/dist/scripts/clean-template.js +14 -0
- package/dist/scripts/clean-template.js.map +1 -0
- package/dist/scripts/prepare-template.d.ts +1 -0
- package/dist/scripts/prepare-template.js +89 -0
- package/dist/scripts/prepare-template.js.map +1 -0
- package/package.json +11 -9
- package/template/.agents/skills/00-discover/SKILL.md +2 -0
- package/template/.agents/skills/60-report/SKILL.md +21 -75
- package/template/.agents/skills/70-release/SKILL.md +7 -4
- package/template/.agents/skills/check/SKILL.md +68 -0
- package/template/.agents/skills/ci/SKILL.md +25 -78
- package/template/.agents/skills/commit/SKILL.md +39 -43
- package/template/.agents/skills/complete/SKILL.md +73 -0
- package/template/.agents/skills/debug/SKILL.md +43 -104
- package/template/.agents/skills/deploy/SKILL.md +37 -65
- package/template/.agents/skills/devflow/SKILL.md +89 -80
- package/template/.agents/skills/idea/SKILL.md +57 -0
- package/template/.agents/skills/implement/SKILL.md +64 -0
- package/template/.agents/skills/insight/SKILL.md +27 -116
- package/template/.agents/skills/overview/SKILL.md +114 -0
- package/template/.agents/skills/preview/SKILL.md +24 -103
- package/template/.agents/skills/report-html/SKILL.md +45 -0
- package/template/.agents/skills/review/SKILL.md +53 -37
- package/template/.agents/skills/rollback/SKILL.md +1 -0
- package/template/.agents/skills/security-review/SKILL.md +44 -147
- package/template/.agents/skills/simplify/SKILL.md +48 -57
- package/template/.agents/skills/spec/SKILL.md +105 -0
- package/template/.agents/skills/test/SKILL.md +63 -51
- package/template/.claude/skills/00-discover/SKILL.md +2 -0
- package/template/.claude/skills/60-report/SKILL.md +21 -75
- package/template/.claude/skills/70-release/SKILL.md +7 -4
- package/template/.claude/skills/check/SKILL.md +68 -0
- package/template/.claude/skills/ci/SKILL.md +25 -78
- package/template/.claude/skills/commit/SKILL.md +39 -43
- package/template/.claude/skills/complete/SKILL.md +73 -0
- package/template/.claude/skills/debug/SKILL.md +43 -104
- package/template/.claude/skills/deploy/SKILL.md +37 -65
- package/template/.claude/skills/devflow/SKILL.md +89 -80
- package/template/.claude/skills/idea/SKILL.md +57 -0
- package/template/.claude/skills/implement/SKILL.md +64 -0
- package/template/.claude/skills/insight/SKILL.md +27 -116
- package/template/.claude/skills/overview/SKILL.md +114 -0
- package/template/.claude/skills/preview/SKILL.md +24 -103
- package/template/.claude/skills/report-html/SKILL.md +45 -0
- package/template/.claude/skills/review/SKILL.md +53 -37
- package/template/.claude/skills/rollback/SKILL.md +1 -0
- package/template/.claude/skills/security-review/SKILL.md +44 -147
- package/template/.claude/skills/simplify/SKILL.md +48 -57
- package/template/.claude/skills/spec/SKILL.md +105 -0
- package/template/.claude/skills/test/SKILL.md +63 -51
- package/template/AGENTS.md +71 -74
- package/template/devflow/context/ai-interaction.md +1 -0
- package/template/devflow/context/coding-standards.md +31 -18
- package/template/devflow/context/current-stage.md +3 -3
- package/template/devflow/context/findings.md +10 -6
- package/template/devflow/context/project-overview.md +29 -11
- package/template/devflow/discoveries/.gitkeep +0 -0
- package/template/devflow/history/HISTORY.md +31 -0
- package/template/devflow/ideas.md +15 -0
- package/template/devflow/reference/running-id-contract.md +1 -1
- package/template/devflow/runs/.gitkeep +0 -0
- package/bin/create-nexus-devflow.js +0 -287
- package/lib/starter-templates.js +0 -111
- package/lib/update.js +0 -379
- package/template/.agents/skills/9arm-skills/README.md +0 -51
- package/template/.agents/skills/9arm-skills/debug-mantra/SKILL.md +0 -86
- package/template/.agents/skills/9arm-skills/management-talk/SKILL.md +0 -79
- package/template/.agents/skills/9arm-skills/post-mortem/SKILL.md +0 -71
- package/template/.agents/skills/9arm-skills/scrutinize/SKILL.md +0 -72
- package/template/.agents/skills/browser-testing-with-devtools/SKILL.md +0 -302
- package/template/.agents/skills/ci-cd-and-automation/SKILL.md +0 -390
- package/template/.agents/skills/code-review-and-quality/SKILL.md +0 -392
- package/template/.agents/skills/code-simplification/SKILL.md +0 -331
- package/template/.agents/skills/debugging-and-error-recovery/SKILL.md +0 -298
- package/template/.agents/skills/deployment-procedures/SKILL.md +0 -241
- package/template/.agents/skills/deprecation-and-migration/SKILL.md +0 -206
- package/template/.agents/skills/diagnosing-bugs/SKILL.md +0 -93
- package/template/.agents/skills/git-workflow-and-versioning/SKILL.md +0 -300
- package/template/.agents/skills/human-review-decisions/SKILL.md +0 -74
- package/template/.agents/skills/idea-refine/SKILL.md +0 -178
- package/template/.agents/skills/idea-refine/examples.md +0 -238
- package/template/.agents/skills/idea-refine/frameworks.md +0 -99
- package/template/.agents/skills/idea-refine/refinement-criteria.md +0 -113
- package/template/.agents/skills/idea-refine/scripts/idea-refine.sh +0 -15
- package/template/.agents/skills/incremental-implementation/SKILL.md +0 -248
- package/template/.agents/skills/insight-capture/SKILL.md +0 -84
- package/template/.agents/skills/intelligent-routing/SKILL.md +0 -176
- package/template/.agents/skills/md2html/SKILL.md +0 -154
- package/template/.agents/skills/md2html/components.md +0 -505
- package/template/.agents/skills/md2html/template.html +0 -1152
- package/template/.agents/skills/planning-and-task-breakdown/SKILL.md +0 -239
- package/template/.agents/skills/pr-review/SKILL.md +0 -143
- package/template/.agents/skills/pr-review-analysis/SKILL.md +0 -89
- package/template/.agents/skills/preview-local-check/SKILL.md +0 -59
- package/template/.agents/skills/release-git-operations/SKILL.md +0 -97
- package/template/.agents/skills/review-followup-routing/SKILL.md +0 -98
- package/template/.agents/skills/security-and-hardening/SKILL.md +0 -349
- package/template/.agents/skills/security-and-hardening/security-checklist.md +0 -134
- package/template/.agents/skills/shipping-and-launch/SKILL.md +0 -311
- package/template/.agents/skills/silent-failure-audit/SKILL.md +0 -73
- package/template/.agents/skills/spec-orchestration/SKILL.md +0 -91
- package/template/.agents/skills/specialist-agent-routing/SKILL.md +0 -107
- package/template/.agents/skills/test-driven-development/SKILL.md +0 -422
- package/template/.agents/skills/test-driven-development/testing-patterns.md +0 -236
- package/template/.agents/skills/test-execution-and-coverage/SKILL.md +0 -56
- package/template/.agents/skills/using-agent-skills/SKILL.md +0 -171
- package/template/.agents/skills/verification-orchestration/SKILL.md +0 -68
- package/template/.agents/skills/vulnerability-scanner/SKILL.md +0 -276
- package/template/.agents/skills/vulnerability-scanner/checklists.md +0 -121
- package/template/.agents/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
- package/template/.agents/skills/wiki/SKILL.md +0 -149
- package/template/.agents/skills/workflow-documentation-sync/SKILL.md +0 -87
- package/template/.claude/skills/9arm-skills/README.md +0 -51
- package/template/.claude/skills/9arm-skills/debug-mantra/SKILL.md +0 -86
- package/template/.claude/skills/9arm-skills/management-talk/SKILL.md +0 -79
- package/template/.claude/skills/9arm-skills/post-mortem/SKILL.md +0 -71
- package/template/.claude/skills/9arm-skills/scrutinize/SKILL.md +0 -72
- package/template/.claude/skills/browser-testing-with-devtools/SKILL.md +0 -302
- package/template/.claude/skills/ci-cd-and-automation/SKILL.md +0 -390
- package/template/.claude/skills/code-review-and-quality/SKILL.md +0 -392
- package/template/.claude/skills/code-simplification/SKILL.md +0 -331
- package/template/.claude/skills/debugging-and-error-recovery/SKILL.md +0 -298
- package/template/.claude/skills/deployment-procedures/SKILL.md +0 -241
- package/template/.claude/skills/deprecation-and-migration/SKILL.md +0 -206
- package/template/.claude/skills/diagnosing-bugs/SKILL.md +0 -93
- package/template/.claude/skills/git-workflow-and-versioning/SKILL.md +0 -300
- package/template/.claude/skills/human-review-decisions/SKILL.md +0 -74
- package/template/.claude/skills/idea-refine/SKILL.md +0 -178
- package/template/.claude/skills/idea-refine/examples.md +0 -238
- package/template/.claude/skills/idea-refine/frameworks.md +0 -99
- package/template/.claude/skills/idea-refine/refinement-criteria.md +0 -113
- package/template/.claude/skills/idea-refine/scripts/idea-refine.sh +0 -15
- package/template/.claude/skills/incremental-implementation/SKILL.md +0 -248
- package/template/.claude/skills/insight-capture/SKILL.md +0 -84
- package/template/.claude/skills/intelligent-routing/SKILL.md +0 -176
- package/template/.claude/skills/md2html/SKILL.md +0 -154
- package/template/.claude/skills/md2html/components.md +0 -505
- package/template/.claude/skills/md2html/template.html +0 -1152
- package/template/.claude/skills/planning-and-task-breakdown/SKILL.md +0 -239
- package/template/.claude/skills/pr-review/SKILL.md +0 -143
- package/template/.claude/skills/pr-review-analysis/SKILL.md +0 -89
- package/template/.claude/skills/preview-local-check/SKILL.md +0 -59
- package/template/.claude/skills/release-git-operations/SKILL.md +0 -97
- package/template/.claude/skills/review-followup-routing/SKILL.md +0 -98
- package/template/.claude/skills/security-and-hardening/SKILL.md +0 -349
- package/template/.claude/skills/security-and-hardening/security-checklist.md +0 -134
- package/template/.claude/skills/shipping-and-launch/SKILL.md +0 -311
- package/template/.claude/skills/silent-failure-audit/SKILL.md +0 -73
- package/template/.claude/skills/spec-orchestration/SKILL.md +0 -91
- package/template/.claude/skills/specialist-agent-routing/SKILL.md +0 -107
- package/template/.claude/skills/test-driven-development/SKILL.md +0 -422
- package/template/.claude/skills/test-driven-development/testing-patterns.md +0 -236
- package/template/.claude/skills/test-execution-and-coverage/SKILL.md +0 -56
- package/template/.claude/skills/using-agent-skills/SKILL.md +0 -171
- package/template/.claude/skills/verification-orchestration/SKILL.md +0 -68
- package/template/.claude/skills/vulnerability-scanner/SKILL.md +0 -276
- package/template/.claude/skills/vulnerability-scanner/checklists.md +0 -121
- package/template/.claude/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
- package/template/.claude/skills/wiki/SKILL.md +0 -149
- package/template/.claude/skills/workflow-documentation-sync/SKILL.md +0 -87
- package/template/.nexus/nexus-devflow.json +0 -44
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fsSync from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import readline from "node:readline/promises";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { applyPreparedUpdate, prepareUpdate } from "../lib/update.js";
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const packageRoot = path.resolve(__dirname, "..", "..");
|
|
9
|
+
const templateRoot = path.join(packageRoot, "template");
|
|
10
|
+
const adapterChoices = new Set(["codex", "antigravity", "claude", "both", "all"]);
|
|
11
|
+
async function main() {
|
|
12
|
+
const options = parseArgs(process.argv.slice(2));
|
|
13
|
+
if (options.help) {
|
|
14
|
+
printHelp();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (options.version) {
|
|
18
|
+
console.log(readPackageVersion());
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!fsSync.existsSync(templateRoot)) {
|
|
22
|
+
throw new Error("Installer template is missing. Run `npm run prepare-template` before local testing.");
|
|
23
|
+
}
|
|
24
|
+
const targetDir = path.resolve(process.cwd(), options.target || ".");
|
|
25
|
+
const version = readPackageVersion();
|
|
26
|
+
if (options.command === "update") {
|
|
27
|
+
const prepared = await prepareUpdate({
|
|
28
|
+
targetDir,
|
|
29
|
+
templateRoot,
|
|
30
|
+
version,
|
|
31
|
+
adapter: options.adapter
|
|
32
|
+
});
|
|
33
|
+
printUpdatePlan(prepared);
|
|
34
|
+
if (options.dryRun) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const replaceConflicts = options.force || (await confirmUpdateConflicts(prepared, options));
|
|
38
|
+
const result = await applyPreparedUpdate(prepared, { replaceConflicts });
|
|
39
|
+
printUpdateSuccess(prepared, result);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const prepared = await prepareUpdate({
|
|
43
|
+
targetDir,
|
|
44
|
+
templateRoot,
|
|
45
|
+
version,
|
|
46
|
+
adapter: options.adapter
|
|
47
|
+
});
|
|
48
|
+
printInstallPlan(prepared);
|
|
49
|
+
if (options.dryRun) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (prepared.conflictList.length > 0 && !options.force) {
|
|
53
|
+
const proceed = await confirmInstallConflicts(prepared, options);
|
|
54
|
+
if (!proceed) {
|
|
55
|
+
console.log("Install cancelled.");
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const result = await applyPreparedUpdate(prepared, {
|
|
60
|
+
replaceConflicts: options.force || prepared.conflictList.length > 0
|
|
61
|
+
});
|
|
62
|
+
printInstallSuccess(targetDir, result);
|
|
63
|
+
}
|
|
64
|
+
function parseArgs(args) {
|
|
65
|
+
let command = "install";
|
|
66
|
+
let target = null;
|
|
67
|
+
let adapter = "both";
|
|
68
|
+
let force = false;
|
|
69
|
+
let dryRun = false;
|
|
70
|
+
let help = false;
|
|
71
|
+
let version = false;
|
|
72
|
+
let yes = false;
|
|
73
|
+
const positional = [];
|
|
74
|
+
for (let i = 0; i < args.length; i++) {
|
|
75
|
+
const arg = args[i];
|
|
76
|
+
if (arg === "--help" || arg === "-h") {
|
|
77
|
+
help = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (arg === "--version" || arg === "-v") {
|
|
81
|
+
version = true;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (arg === "--force" || arg === "-f") {
|
|
85
|
+
force = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (arg === "--dry-run") {
|
|
89
|
+
dryRun = true;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (arg === "-y" || arg === "--yes") {
|
|
93
|
+
yes = true;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (arg === "--adapter") {
|
|
97
|
+
const value = args[++i];
|
|
98
|
+
if (!value || !adapterChoices.has(value.toLowerCase())) {
|
|
99
|
+
throw new Error(`Invalid --adapter value "${value}". Expected one of: codex, antigravity, claude, both, all`);
|
|
100
|
+
}
|
|
101
|
+
adapter = value.toLowerCase();
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (arg.startsWith("--adapter=")) {
|
|
105
|
+
const value = arg.slice("--adapter=".length);
|
|
106
|
+
if (!adapterChoices.has(value.toLowerCase())) {
|
|
107
|
+
throw new Error(`Invalid --adapter value "${value}". Expected one of: codex, antigravity, claude, both, all`);
|
|
108
|
+
}
|
|
109
|
+
adapter = value.toLowerCase();
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (arg.startsWith("-")) {
|
|
113
|
+
throw new Error(`Unknown option "${arg}". Use --help to see available options.`);
|
|
114
|
+
}
|
|
115
|
+
positional.push(arg);
|
|
116
|
+
}
|
|
117
|
+
if (positional.length > 0) {
|
|
118
|
+
if (positional[0] === "update") {
|
|
119
|
+
command = "update";
|
|
120
|
+
target = positional[1] || ".";
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
target = positional[0];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
command,
|
|
128
|
+
target,
|
|
129
|
+
adapter,
|
|
130
|
+
force,
|
|
131
|
+
dryRun,
|
|
132
|
+
help,
|
|
133
|
+
version,
|
|
134
|
+
yes
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function readPackageVersion() {
|
|
138
|
+
const pkgPath = path.join(packageRoot, "package.json");
|
|
139
|
+
const content = fsSync.readFileSync(pkgPath, "utf8");
|
|
140
|
+
return JSON.parse(content).version;
|
|
141
|
+
}
|
|
142
|
+
function printHelp() {
|
|
143
|
+
console.log(`
|
|
144
|
+
Nexus-DevFlow Installer v${readPackageVersion()}
|
|
145
|
+
|
|
146
|
+
Usage:
|
|
147
|
+
npx @jakkrichm/create-nexus-devflow [target-dir] [options]
|
|
148
|
+
npx @jakkrichm/create-nexus-devflow update [target-dir] [options]
|
|
149
|
+
|
|
150
|
+
Options:
|
|
151
|
+
--adapter <name> Tool adapters to install: codex, antigravity, claude, both (default: both)
|
|
152
|
+
--force, -f Overwrite conflicting files without prompting
|
|
153
|
+
--dry-run Preview changes without modifying disk
|
|
154
|
+
-y, --yes Automatically confirm interactive prompts
|
|
155
|
+
--version, -v Show version number
|
|
156
|
+
--help, -h Show help screen
|
|
157
|
+
`);
|
|
158
|
+
}
|
|
159
|
+
function printInstallPlan(prepared) {
|
|
160
|
+
console.log(`\nNexus-DevFlow v${readPackageVersion()}`);
|
|
161
|
+
console.log(`Target Directory: ${prepared.targetDir}`);
|
|
162
|
+
console.log(`Active Adapters : ${prepared.activeAdapters.join(", ")}\n`);
|
|
163
|
+
console.log(`Files to create : ${prepared.createList.length}`);
|
|
164
|
+
console.log(`Files to update : ${prepared.updateList.length}`);
|
|
165
|
+
console.log(`Conflicts found : ${prepared.conflictList.length}`);
|
|
166
|
+
if (prepared.conflictList.length > 0) {
|
|
167
|
+
console.log("\nConflicting files:");
|
|
168
|
+
for (const conflict of prepared.conflictList) {
|
|
169
|
+
console.log(` - ${conflict.relativePath} (${conflict.detail})`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
function printUpdatePlan(prepared) {
|
|
174
|
+
console.log(`\nNexus-DevFlow Update Plan (v${readPackageVersion()})`);
|
|
175
|
+
console.log(`Target Directory: ${prepared.targetDir}`);
|
|
176
|
+
console.log(`Active Adapters : ${prepared.activeAdapters.join(", ")}\n`);
|
|
177
|
+
console.log(`Files to create : ${prepared.createList.length}`);
|
|
178
|
+
console.log(`Files to update : ${prepared.updateList.length}`);
|
|
179
|
+
console.log(`Orphaned files : ${prepared.orphanedFiles.length}`);
|
|
180
|
+
console.log(`Conflicts found : ${prepared.conflictList.length}`);
|
|
181
|
+
}
|
|
182
|
+
async function confirmInstallConflicts(prepared, options) {
|
|
183
|
+
if (options.yes)
|
|
184
|
+
return true;
|
|
185
|
+
const rl = readline.createInterface({
|
|
186
|
+
input: process.stdin,
|
|
187
|
+
output: process.stdout
|
|
188
|
+
});
|
|
189
|
+
const answer = await rl.question(`\nOverwrite ${prepared.conflictList.length} conflicting file(s)? [y/N] `);
|
|
190
|
+
rl.close();
|
|
191
|
+
return answer.trim().toLowerCase() === "y";
|
|
192
|
+
}
|
|
193
|
+
async function confirmUpdateConflicts(prepared, options) {
|
|
194
|
+
if (options.yes)
|
|
195
|
+
return true;
|
|
196
|
+
const rl = readline.createInterface({
|
|
197
|
+
input: process.stdin,
|
|
198
|
+
output: process.stdout
|
|
199
|
+
});
|
|
200
|
+
const answer = await rl.question(`\nOverwrite ${prepared.conflictList.length} customized file(s) with update? [y/N] `);
|
|
201
|
+
rl.close();
|
|
202
|
+
return answer.trim().toLowerCase() === "y";
|
|
203
|
+
}
|
|
204
|
+
function printNextSteps() {
|
|
205
|
+
console.log("\nNext steps in your AI IDE (Antigravity, Claude Code, Codex, etc.):");
|
|
206
|
+
console.log(" 1. Project Setup & Baseline:");
|
|
207
|
+
console.log(" - Existing project : Run `/adopt` (or `$adopt`) to scan codebase and bootstrap context.");
|
|
208
|
+
console.log(" - Fresh project : Run `/onboard` (or `$onboard`) to configure project baseline.");
|
|
209
|
+
console.log(" 2. System Health & CI:");
|
|
210
|
+
console.log(" - Health check : Run `/doctor` (or `$doctor`) to verify adapters and setup.");
|
|
211
|
+
console.log(" - CI configuration : Run `/ci` (or `$ci`) to setup GitHub Actions workflow.");
|
|
212
|
+
console.log(" 3. Delivery Flow:");
|
|
213
|
+
console.log(" - Interactive guide: Run `/devflow` (or `$devflow`) for state & routing assistance.");
|
|
214
|
+
console.log(" - Start new work : Run `/00-discover` (or `$00-discover`) to begin delivery lifecycle.");
|
|
215
|
+
}
|
|
216
|
+
function printInstallSuccess(targetDir, result) {
|
|
217
|
+
console.log("\nNexus-DevFlow overlay successfully installed!");
|
|
218
|
+
console.log(`Applied ${result.appliedCount} file(s).`);
|
|
219
|
+
printNextSteps();
|
|
220
|
+
}
|
|
221
|
+
function printUpdateSuccess(prepared, result) {
|
|
222
|
+
console.log("\nNexus-DevFlow update successfully applied!");
|
|
223
|
+
console.log(`Applied ${result.appliedCount} file(s), removed ${result.removedCount} orphaned file(s).`);
|
|
224
|
+
printNextSteps();
|
|
225
|
+
}
|
|
226
|
+
if (process.argv[1] &&
|
|
227
|
+
fsSync.realpathSync(process.argv[1]) === fsSync.realpathSync(fileURLToPath(import.meta.url))) {
|
|
228
|
+
main().catch((err) => {
|
|
229
|
+
console.error(`\nError: ${err instanceof Error ? err.message : String(err)}`);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=create-nexus-devflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-nexus-devflow.js","sourceRoot":"","sources":["../../bin/create-nexus-devflow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starter-templates.js","sourceRoot":"","sources":["../../lib/starter-templates.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,gBAAgB,GAAoC;IAC/D,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,+CAA+C;QAC5D,KAAK,EAAE,EAAE;KACV;CACF,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export declare const CONTROL_DIR = ".nexus";
|
|
2
|
+
export declare const MANIFEST_PATH = ".nexus/nexus-devflow.json";
|
|
3
|
+
export declare const MANIFEST_SCHEMA_VERSION = 1;
|
|
4
|
+
export declare const MANAGED_ROOTS: Record<string, string[]>;
|
|
5
|
+
export interface Manifest {
|
|
6
|
+
schemaVersion: number;
|
|
7
|
+
name: string;
|
|
8
|
+
package: string;
|
|
9
|
+
version: string;
|
|
10
|
+
repository: string;
|
|
11
|
+
artifactLanguage: string;
|
|
12
|
+
adapters: string[];
|
|
13
|
+
workspace: {
|
|
14
|
+
contextDir: string;
|
|
15
|
+
historyDir: string;
|
|
16
|
+
referenceDir: string;
|
|
17
|
+
runsDir: string;
|
|
18
|
+
discoveriesDir: string;
|
|
19
|
+
};
|
|
20
|
+
lifecycle: {
|
|
21
|
+
mainlineStages: string[];
|
|
22
|
+
companionCommands: string[];
|
|
23
|
+
};
|
|
24
|
+
managedFiles: Record<string, string>;
|
|
25
|
+
}
|
|
26
|
+
export interface TemplateFile {
|
|
27
|
+
source: string;
|
|
28
|
+
hash: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Conflict {
|
|
31
|
+
relativePath: string;
|
|
32
|
+
reason: "symlink" | "not_file" | "customized";
|
|
33
|
+
detail: string;
|
|
34
|
+
}
|
|
35
|
+
export interface PreparedUpdate {
|
|
36
|
+
targetDir: string;
|
|
37
|
+
templateRoot: string;
|
|
38
|
+
previousManifest: Manifest | null;
|
|
39
|
+
nextManifest: Manifest;
|
|
40
|
+
activeAdapters: string[];
|
|
41
|
+
templateFiles: Map<string, TemplateFile>;
|
|
42
|
+
createList: string[];
|
|
43
|
+
updateList: string[];
|
|
44
|
+
conflictList: Conflict[];
|
|
45
|
+
orphanedFiles: string[];
|
|
46
|
+
}
|
|
47
|
+
export declare function adapterListFromMode(adapter?: string): string[];
|
|
48
|
+
export declare function createManifest(version: string, adapters: Iterable<string>, templateFiles: Map<string, TemplateFile>): Manifest;
|
|
49
|
+
export declare function collectManagedTemplateFiles(templateRoot: string, adapters: string[]): Promise<Map<string, TemplateFile>>;
|
|
50
|
+
export declare function readManifest(targetDir: string): Promise<Manifest | null>;
|
|
51
|
+
export declare function prepareUpdate({ targetDir, templateRoot, version, adapter }: {
|
|
52
|
+
targetDir: string;
|
|
53
|
+
templateRoot: string;
|
|
54
|
+
version: string;
|
|
55
|
+
adapter?: string;
|
|
56
|
+
}): Promise<PreparedUpdate>;
|
|
57
|
+
export declare function applyPreparedUpdate(prepared: PreparedUpdate, { replaceConflicts }?: {
|
|
58
|
+
replaceConflicts?: boolean;
|
|
59
|
+
}): Promise<{
|
|
60
|
+
appliedCount: number;
|
|
61
|
+
removedCount: number;
|
|
62
|
+
}>;
|
|
63
|
+
export declare function cleanEmptyParentDirectories(targetDir: string, filePath: string): Promise<void>;
|
|
64
|
+
export declare function writeInstallManifest(targetDir: string, manifest: Manifest): Promise<void>;
|
|
65
|
+
export declare function copyFileAtomic(targetDir: string, relativePath: string, sourcePath: string): Promise<void>;
|
|
66
|
+
export declare function targetPath(targetDir: string, relativePath: string): string;
|
|
67
|
+
export declare function assertNoSymlinkParents(targetDir: string, relativePath: string): Promise<void>;
|
|
68
|
+
export declare function hashFile(filePath: string): Promise<string>;
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export const CONTROL_DIR = ".nexus";
|
|
5
|
+
export const MANIFEST_PATH = `${CONTROL_DIR}/nexus-devflow.json`;
|
|
6
|
+
export const MANIFEST_SCHEMA_VERSION = 1;
|
|
7
|
+
export const MANAGED_ROOTS = {
|
|
8
|
+
common: ["AGENTS.md", "CLAUDE.md", "devflow", "LICENSE"],
|
|
9
|
+
codex: [".agents/skills"],
|
|
10
|
+
antigravity: [".agents/skills", ".agent/workflows"],
|
|
11
|
+
claude: [".claude/skills"]
|
|
12
|
+
};
|
|
13
|
+
export function adapterListFromMode(adapter) {
|
|
14
|
+
if (!adapter || adapter === "both" || adapter === "all") {
|
|
15
|
+
return ["codex", "claude"];
|
|
16
|
+
}
|
|
17
|
+
if (adapter === "antigravity") {
|
|
18
|
+
return ["codex"];
|
|
19
|
+
}
|
|
20
|
+
if (adapter === "codex" || adapter === "claude") {
|
|
21
|
+
return [adapter];
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Unknown adapter mode: ${adapter}`);
|
|
24
|
+
}
|
|
25
|
+
export function createManifest(version, adapters, templateFiles) {
|
|
26
|
+
const managedFiles = {};
|
|
27
|
+
for (const [relativePath, file] of [...templateFiles.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
28
|
+
managedFiles[relativePath] = file.hash;
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
schemaVersion: MANIFEST_SCHEMA_VERSION,
|
|
32
|
+
name: "nexus-devflow",
|
|
33
|
+
package: "@jakkrichm/create-nexus-devflow",
|
|
34
|
+
version,
|
|
35
|
+
repository: "https://github.com/Jakkrich/nexus-devflow",
|
|
36
|
+
artifactLanguage: "th",
|
|
37
|
+
adapters: [...adapters].sort(),
|
|
38
|
+
workspace: {
|
|
39
|
+
contextDir: "devflow/context",
|
|
40
|
+
historyDir: "devflow/history",
|
|
41
|
+
referenceDir: "devflow/reference",
|
|
42
|
+
runsDir: "devflow/runs",
|
|
43
|
+
discoveriesDir: "devflow/discoveries"
|
|
44
|
+
},
|
|
45
|
+
lifecycle: {
|
|
46
|
+
mainlineStages: [
|
|
47
|
+
"00-discover",
|
|
48
|
+
"10-define",
|
|
49
|
+
"20-spec",
|
|
50
|
+
"30-plan",
|
|
51
|
+
"40-implement",
|
|
52
|
+
"50-verify",
|
|
53
|
+
"60-report",
|
|
54
|
+
"70-release"
|
|
55
|
+
],
|
|
56
|
+
companionCommands: [
|
|
57
|
+
"goal",
|
|
58
|
+
"brainstorm",
|
|
59
|
+
"research",
|
|
60
|
+
"debug",
|
|
61
|
+
"prd",
|
|
62
|
+
"issue-triage",
|
|
63
|
+
"security-review",
|
|
64
|
+
"check-for-updates",
|
|
65
|
+
"help"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
managedFiles
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export async function collectManagedTemplateFiles(templateRoot, adapters) {
|
|
72
|
+
const files = new Map();
|
|
73
|
+
const roots = [
|
|
74
|
+
...MANAGED_ROOTS.common,
|
|
75
|
+
...adapters.flatMap((adapter) => MANAGED_ROOTS[adapter] || [])
|
|
76
|
+
];
|
|
77
|
+
for (const relativeRoot of roots) {
|
|
78
|
+
const sourceRoot = path.join(templateRoot, ...relativeRoot.split("/"));
|
|
79
|
+
await collectSourceFiles(sourceRoot, relativeRoot, files);
|
|
80
|
+
}
|
|
81
|
+
return files;
|
|
82
|
+
}
|
|
83
|
+
async function collectSourceFiles(sourcePath, relativePath, files) {
|
|
84
|
+
try {
|
|
85
|
+
const stats = await fs.lstat(sourcePath);
|
|
86
|
+
if (stats.isSymbolicLink()) {
|
|
87
|
+
throw new Error(`Managed template path cannot be a symbolic link: ${relativePath}`);
|
|
88
|
+
}
|
|
89
|
+
if (stats.isDirectory()) {
|
|
90
|
+
const children = (await fs.readdir(sourcePath)).sort();
|
|
91
|
+
for (const child of children) {
|
|
92
|
+
await collectSourceFiles(path.join(sourcePath, child), `${relativePath}/${child}`, files);
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (!stats.isFile()) {
|
|
97
|
+
throw new Error(`Managed template path is not a regular file: ${relativePath}`);
|
|
98
|
+
}
|
|
99
|
+
files.set(relativePath, {
|
|
100
|
+
source: sourcePath,
|
|
101
|
+
hash: await hashFile(sourcePath)
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
if (err.code === "ENOENT") {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
throw err;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function readManifest(targetDir) {
|
|
112
|
+
const manifestFile = targetPath(targetDir, MANIFEST_PATH);
|
|
113
|
+
await assertNoSymlinkParents(targetDir, MANIFEST_PATH);
|
|
114
|
+
try {
|
|
115
|
+
const content = await fs.readFile(manifestFile, "utf8");
|
|
116
|
+
const data = JSON.parse(content);
|
|
117
|
+
if (!data || data.schemaVersion !== MANIFEST_SCHEMA_VERSION) {
|
|
118
|
+
throw new Error("Unsupported manifest schema version.");
|
|
119
|
+
}
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (error.code === "ENOENT") {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export async function prepareUpdate({ targetDir, templateRoot, version, adapter }) {
|
|
130
|
+
const requestedAdapters = new Set(adapterListFromMode(adapter));
|
|
131
|
+
const previousManifest = await readManifest(targetDir);
|
|
132
|
+
const activeAdapters = new Set([
|
|
133
|
+
...requestedAdapters,
|
|
134
|
+
...(previousManifest?.adapters || [])
|
|
135
|
+
]);
|
|
136
|
+
const templateFiles = await collectManagedTemplateFiles(templateRoot, [...activeAdapters]);
|
|
137
|
+
const nextManifest = createManifest(version, activeAdapters, templateFiles);
|
|
138
|
+
const createList = [];
|
|
139
|
+
const updateList = [];
|
|
140
|
+
const conflictList = [];
|
|
141
|
+
for (const [relativePath, templateFile] of templateFiles) {
|
|
142
|
+
await assertNoSymlinkParents(targetDir, relativePath);
|
|
143
|
+
const targetFile = targetPath(targetDir, relativePath);
|
|
144
|
+
let targetStats = null;
|
|
145
|
+
try {
|
|
146
|
+
targetStats = await fs.lstat(targetFile);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
if (error.code !== "ENOENT") {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (!targetStats) {
|
|
154
|
+
createList.push(relativePath);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (targetStats.isSymbolicLink()) {
|
|
158
|
+
conflictList.push({
|
|
159
|
+
relativePath,
|
|
160
|
+
reason: "symlink",
|
|
161
|
+
detail: "Target path is a symbolic link."
|
|
162
|
+
});
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (!targetStats.isFile()) {
|
|
166
|
+
conflictList.push({
|
|
167
|
+
relativePath,
|
|
168
|
+
reason: "not_file",
|
|
169
|
+
detail: "Target path exists but is not a regular file."
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
const currentHash = await hashFile(targetFile);
|
|
174
|
+
if (currentHash === templateFile.hash) {
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const recordedHash = previousManifest?.managedFiles?.[relativePath];
|
|
178
|
+
if (recordedHash && recordedHash === currentHash) {
|
|
179
|
+
updateList.push(relativePath);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
conflictList.push({
|
|
183
|
+
relativePath,
|
|
184
|
+
reason: "customized",
|
|
185
|
+
detail: recordedHash
|
|
186
|
+
? "File was modified locally since last install."
|
|
187
|
+
: "File exists in project and differs from template."
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const orphanedFiles = [];
|
|
191
|
+
if (previousManifest) {
|
|
192
|
+
for (const [relativePath, recordedHash] of Object.entries(previousManifest.managedFiles)) {
|
|
193
|
+
if (templateFiles.has(relativePath)) {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
await assertNoSymlinkParents(targetDir, relativePath);
|
|
197
|
+
const targetFile = targetPath(targetDir, relativePath);
|
|
198
|
+
let targetStats = null;
|
|
199
|
+
try {
|
|
200
|
+
targetStats = await fs.lstat(targetFile);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
if (error.code !== "ENOENT") {
|
|
204
|
+
throw error;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (!targetStats || !targetStats.isFile()) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const currentHash = await hashFile(targetFile);
|
|
211
|
+
if (currentHash === recordedHash) {
|
|
212
|
+
orphanedFiles.push(relativePath);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return {
|
|
217
|
+
targetDir,
|
|
218
|
+
templateRoot,
|
|
219
|
+
previousManifest,
|
|
220
|
+
nextManifest,
|
|
221
|
+
activeAdapters: [...activeAdapters].sort(),
|
|
222
|
+
templateFiles,
|
|
223
|
+
createList,
|
|
224
|
+
updateList,
|
|
225
|
+
conflictList,
|
|
226
|
+
orphanedFiles
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
export async function applyPreparedUpdate(prepared, { replaceConflicts = false } = {}) {
|
|
230
|
+
if (prepared.conflictList.length > 0 && !replaceConflicts) {
|
|
231
|
+
throw new Error(`Cannot apply update with ${prepared.conflictList.length} conflict(s). Pass force/replace option or resolve conflicts.`);
|
|
232
|
+
}
|
|
233
|
+
const writeTargets = [
|
|
234
|
+
...prepared.createList,
|
|
235
|
+
...prepared.updateList,
|
|
236
|
+
...(replaceConflicts ? prepared.conflictList.map((item) => item.relativePath) : [])
|
|
237
|
+
];
|
|
238
|
+
let appliedCount = 0;
|
|
239
|
+
for (const relativePath of writeTargets) {
|
|
240
|
+
const templateFile = prepared.templateFiles.get(relativePath);
|
|
241
|
+
if (!templateFile) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
await copyFileAtomic(prepared.targetDir, relativePath, templateFile.source);
|
|
245
|
+
appliedCount++;
|
|
246
|
+
}
|
|
247
|
+
let removedCount = 0;
|
|
248
|
+
for (const relativePath of prepared.orphanedFiles) {
|
|
249
|
+
const fileToRemove = targetPath(prepared.targetDir, relativePath);
|
|
250
|
+
try {
|
|
251
|
+
await fs.unlink(fileToRemove);
|
|
252
|
+
removedCount++;
|
|
253
|
+
await cleanEmptyParentDirectories(prepared.targetDir, fileToRemove);
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
if (error.code !== "ENOENT") {
|
|
257
|
+
throw error;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
await writeInstallManifest(prepared.targetDir, prepared.nextManifest);
|
|
262
|
+
return {
|
|
263
|
+
appliedCount,
|
|
264
|
+
removedCount
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
export async function cleanEmptyParentDirectories(targetDir, filePath) {
|
|
268
|
+
let parentDir = path.dirname(filePath);
|
|
269
|
+
const resolvedTarget = path.resolve(targetDir);
|
|
270
|
+
while (parentDir !== resolvedTarget && parentDir.startsWith(resolvedTarget)) {
|
|
271
|
+
try {
|
|
272
|
+
const entries = await fs.readdir(parentDir);
|
|
273
|
+
if (entries.length === 0) {
|
|
274
|
+
await fs.rmdir(parentDir);
|
|
275
|
+
parentDir = path.dirname(parentDir);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
catch {
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
export async function writeInstallManifest(targetDir, manifest) {
|
|
287
|
+
const manifestFile = targetPath(targetDir, MANIFEST_PATH);
|
|
288
|
+
await fs.mkdir(path.dirname(manifestFile), { recursive: true });
|
|
289
|
+
await fs.writeFile(manifestFile, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
290
|
+
}
|
|
291
|
+
export async function copyFileAtomic(targetDir, relativePath, sourcePath) {
|
|
292
|
+
await assertNoSymlinkParents(targetDir, relativePath);
|
|
293
|
+
const destinationPath = targetPath(targetDir, relativePath);
|
|
294
|
+
await fs.mkdir(path.dirname(destinationPath), { recursive: true });
|
|
295
|
+
const tempPath = `${destinationPath}.tmp-${process.pid}-${Date.now()}`;
|
|
296
|
+
await fs.copyFile(sourcePath, tempPath);
|
|
297
|
+
await fs.rename(tempPath, destinationPath);
|
|
298
|
+
}
|
|
299
|
+
export function targetPath(targetDir, relativePath) {
|
|
300
|
+
return path.resolve(targetDir, ...relativePath.split("/"));
|
|
301
|
+
}
|
|
302
|
+
export async function assertNoSymlinkParents(targetDir, relativePath) {
|
|
303
|
+
const parts = relativePath.split("/");
|
|
304
|
+
let current = path.resolve(targetDir);
|
|
305
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
306
|
+
current = path.join(current, parts[i]);
|
|
307
|
+
try {
|
|
308
|
+
const stats = await fs.lstat(current);
|
|
309
|
+
if (stats.isSymbolicLink()) {
|
|
310
|
+
throw new Error(`Target sub-path "${parts.slice(0, i + 1).join("/")}" is a symbolic link.`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
if (error.code === "ENOENT") {
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
export async function hashFile(filePath) {
|
|
322
|
+
const content = await fs.readFile(filePath);
|
|
323
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=update.js.map
|