@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.
Files changed (171) hide show
  1. package/dist/bin/create-nexus-devflow.d.ts +2 -0
  2. package/dist/bin/create-nexus-devflow.js +233 -0
  3. package/dist/bin/create-nexus-devflow.js.map +1 -0
  4. package/dist/lib/starter-templates.d.ts +6 -0
  5. package/dist/lib/starter-templates.js +8 -0
  6. package/dist/lib/starter-templates.js.map +1 -0
  7. package/dist/lib/update.d.ts +68 -0
  8. package/dist/lib/update.js +325 -0
  9. package/dist/lib/update.js.map +1 -0
  10. package/dist/scripts/clean-template.d.ts +1 -0
  11. package/dist/scripts/clean-template.js +14 -0
  12. package/dist/scripts/clean-template.js.map +1 -0
  13. package/dist/scripts/prepare-template.d.ts +1 -0
  14. package/dist/scripts/prepare-template.js +89 -0
  15. package/dist/scripts/prepare-template.js.map +1 -0
  16. package/package.json +11 -9
  17. package/template/.agents/skills/00-discover/SKILL.md +2 -0
  18. package/template/.agents/skills/60-report/SKILL.md +21 -75
  19. package/template/.agents/skills/70-release/SKILL.md +7 -4
  20. package/template/.agents/skills/check/SKILL.md +68 -0
  21. package/template/.agents/skills/ci/SKILL.md +25 -78
  22. package/template/.agents/skills/commit/SKILL.md +39 -43
  23. package/template/.agents/skills/complete/SKILL.md +73 -0
  24. package/template/.agents/skills/debug/SKILL.md +43 -104
  25. package/template/.agents/skills/deploy/SKILL.md +37 -65
  26. package/template/.agents/skills/devflow/SKILL.md +89 -80
  27. package/template/.agents/skills/idea/SKILL.md +57 -0
  28. package/template/.agents/skills/implement/SKILL.md +64 -0
  29. package/template/.agents/skills/insight/SKILL.md +27 -116
  30. package/template/.agents/skills/overview/SKILL.md +114 -0
  31. package/template/.agents/skills/preview/SKILL.md +24 -103
  32. package/template/.agents/skills/report-html/SKILL.md +45 -0
  33. package/template/.agents/skills/review/SKILL.md +53 -37
  34. package/template/.agents/skills/rollback/SKILL.md +1 -0
  35. package/template/.agents/skills/security-review/SKILL.md +44 -147
  36. package/template/.agents/skills/simplify/SKILL.md +48 -57
  37. package/template/.agents/skills/spec/SKILL.md +105 -0
  38. package/template/.agents/skills/test/SKILL.md +63 -51
  39. package/template/.claude/skills/00-discover/SKILL.md +2 -0
  40. package/template/.claude/skills/60-report/SKILL.md +21 -75
  41. package/template/.claude/skills/70-release/SKILL.md +7 -4
  42. package/template/.claude/skills/check/SKILL.md +68 -0
  43. package/template/.claude/skills/ci/SKILL.md +25 -78
  44. package/template/.claude/skills/commit/SKILL.md +39 -43
  45. package/template/.claude/skills/complete/SKILL.md +73 -0
  46. package/template/.claude/skills/debug/SKILL.md +43 -104
  47. package/template/.claude/skills/deploy/SKILL.md +37 -65
  48. package/template/.claude/skills/devflow/SKILL.md +89 -80
  49. package/template/.claude/skills/idea/SKILL.md +57 -0
  50. package/template/.claude/skills/implement/SKILL.md +64 -0
  51. package/template/.claude/skills/insight/SKILL.md +27 -116
  52. package/template/.claude/skills/overview/SKILL.md +114 -0
  53. package/template/.claude/skills/preview/SKILL.md +24 -103
  54. package/template/.claude/skills/report-html/SKILL.md +45 -0
  55. package/template/.claude/skills/review/SKILL.md +53 -37
  56. package/template/.claude/skills/rollback/SKILL.md +1 -0
  57. package/template/.claude/skills/security-review/SKILL.md +44 -147
  58. package/template/.claude/skills/simplify/SKILL.md +48 -57
  59. package/template/.claude/skills/spec/SKILL.md +105 -0
  60. package/template/.claude/skills/test/SKILL.md +63 -51
  61. package/template/AGENTS.md +71 -74
  62. package/template/devflow/context/ai-interaction.md +1 -0
  63. package/template/devflow/context/coding-standards.md +31 -18
  64. package/template/devflow/context/current-stage.md +3 -3
  65. package/template/devflow/context/findings.md +10 -6
  66. package/template/devflow/context/project-overview.md +29 -11
  67. package/template/devflow/discoveries/.gitkeep +0 -0
  68. package/template/devflow/history/HISTORY.md +31 -0
  69. package/template/devflow/ideas.md +15 -0
  70. package/template/devflow/reference/running-id-contract.md +1 -1
  71. package/template/devflow/runs/.gitkeep +0 -0
  72. package/bin/create-nexus-devflow.js +0 -287
  73. package/lib/starter-templates.js +0 -111
  74. package/lib/update.js +0 -379
  75. package/template/.agents/skills/9arm-skills/README.md +0 -51
  76. package/template/.agents/skills/9arm-skills/debug-mantra/SKILL.md +0 -86
  77. package/template/.agents/skills/9arm-skills/management-talk/SKILL.md +0 -79
  78. package/template/.agents/skills/9arm-skills/post-mortem/SKILL.md +0 -71
  79. package/template/.agents/skills/9arm-skills/scrutinize/SKILL.md +0 -72
  80. package/template/.agents/skills/browser-testing-with-devtools/SKILL.md +0 -302
  81. package/template/.agents/skills/ci-cd-and-automation/SKILL.md +0 -390
  82. package/template/.agents/skills/code-review-and-quality/SKILL.md +0 -392
  83. package/template/.agents/skills/code-simplification/SKILL.md +0 -331
  84. package/template/.agents/skills/debugging-and-error-recovery/SKILL.md +0 -298
  85. package/template/.agents/skills/deployment-procedures/SKILL.md +0 -241
  86. package/template/.agents/skills/deprecation-and-migration/SKILL.md +0 -206
  87. package/template/.agents/skills/diagnosing-bugs/SKILL.md +0 -93
  88. package/template/.agents/skills/git-workflow-and-versioning/SKILL.md +0 -300
  89. package/template/.agents/skills/human-review-decisions/SKILL.md +0 -74
  90. package/template/.agents/skills/idea-refine/SKILL.md +0 -178
  91. package/template/.agents/skills/idea-refine/examples.md +0 -238
  92. package/template/.agents/skills/idea-refine/frameworks.md +0 -99
  93. package/template/.agents/skills/idea-refine/refinement-criteria.md +0 -113
  94. package/template/.agents/skills/idea-refine/scripts/idea-refine.sh +0 -15
  95. package/template/.agents/skills/incremental-implementation/SKILL.md +0 -248
  96. package/template/.agents/skills/insight-capture/SKILL.md +0 -84
  97. package/template/.agents/skills/intelligent-routing/SKILL.md +0 -176
  98. package/template/.agents/skills/md2html/SKILL.md +0 -154
  99. package/template/.agents/skills/md2html/components.md +0 -505
  100. package/template/.agents/skills/md2html/template.html +0 -1152
  101. package/template/.agents/skills/planning-and-task-breakdown/SKILL.md +0 -239
  102. package/template/.agents/skills/pr-review/SKILL.md +0 -143
  103. package/template/.agents/skills/pr-review-analysis/SKILL.md +0 -89
  104. package/template/.agents/skills/preview-local-check/SKILL.md +0 -59
  105. package/template/.agents/skills/release-git-operations/SKILL.md +0 -97
  106. package/template/.agents/skills/review-followup-routing/SKILL.md +0 -98
  107. package/template/.agents/skills/security-and-hardening/SKILL.md +0 -349
  108. package/template/.agents/skills/security-and-hardening/security-checklist.md +0 -134
  109. package/template/.agents/skills/shipping-and-launch/SKILL.md +0 -311
  110. package/template/.agents/skills/silent-failure-audit/SKILL.md +0 -73
  111. package/template/.agents/skills/spec-orchestration/SKILL.md +0 -91
  112. package/template/.agents/skills/specialist-agent-routing/SKILL.md +0 -107
  113. package/template/.agents/skills/test-driven-development/SKILL.md +0 -422
  114. package/template/.agents/skills/test-driven-development/testing-patterns.md +0 -236
  115. package/template/.agents/skills/test-execution-and-coverage/SKILL.md +0 -56
  116. package/template/.agents/skills/using-agent-skills/SKILL.md +0 -171
  117. package/template/.agents/skills/verification-orchestration/SKILL.md +0 -68
  118. package/template/.agents/skills/vulnerability-scanner/SKILL.md +0 -276
  119. package/template/.agents/skills/vulnerability-scanner/checklists.md +0 -121
  120. package/template/.agents/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
  121. package/template/.agents/skills/wiki/SKILL.md +0 -149
  122. package/template/.agents/skills/workflow-documentation-sync/SKILL.md +0 -87
  123. package/template/.claude/skills/9arm-skills/README.md +0 -51
  124. package/template/.claude/skills/9arm-skills/debug-mantra/SKILL.md +0 -86
  125. package/template/.claude/skills/9arm-skills/management-talk/SKILL.md +0 -79
  126. package/template/.claude/skills/9arm-skills/post-mortem/SKILL.md +0 -71
  127. package/template/.claude/skills/9arm-skills/scrutinize/SKILL.md +0 -72
  128. package/template/.claude/skills/browser-testing-with-devtools/SKILL.md +0 -302
  129. package/template/.claude/skills/ci-cd-and-automation/SKILL.md +0 -390
  130. package/template/.claude/skills/code-review-and-quality/SKILL.md +0 -392
  131. package/template/.claude/skills/code-simplification/SKILL.md +0 -331
  132. package/template/.claude/skills/debugging-and-error-recovery/SKILL.md +0 -298
  133. package/template/.claude/skills/deployment-procedures/SKILL.md +0 -241
  134. package/template/.claude/skills/deprecation-and-migration/SKILL.md +0 -206
  135. package/template/.claude/skills/diagnosing-bugs/SKILL.md +0 -93
  136. package/template/.claude/skills/git-workflow-and-versioning/SKILL.md +0 -300
  137. package/template/.claude/skills/human-review-decisions/SKILL.md +0 -74
  138. package/template/.claude/skills/idea-refine/SKILL.md +0 -178
  139. package/template/.claude/skills/idea-refine/examples.md +0 -238
  140. package/template/.claude/skills/idea-refine/frameworks.md +0 -99
  141. package/template/.claude/skills/idea-refine/refinement-criteria.md +0 -113
  142. package/template/.claude/skills/idea-refine/scripts/idea-refine.sh +0 -15
  143. package/template/.claude/skills/incremental-implementation/SKILL.md +0 -248
  144. package/template/.claude/skills/insight-capture/SKILL.md +0 -84
  145. package/template/.claude/skills/intelligent-routing/SKILL.md +0 -176
  146. package/template/.claude/skills/md2html/SKILL.md +0 -154
  147. package/template/.claude/skills/md2html/components.md +0 -505
  148. package/template/.claude/skills/md2html/template.html +0 -1152
  149. package/template/.claude/skills/planning-and-task-breakdown/SKILL.md +0 -239
  150. package/template/.claude/skills/pr-review/SKILL.md +0 -143
  151. package/template/.claude/skills/pr-review-analysis/SKILL.md +0 -89
  152. package/template/.claude/skills/preview-local-check/SKILL.md +0 -59
  153. package/template/.claude/skills/release-git-operations/SKILL.md +0 -97
  154. package/template/.claude/skills/review-followup-routing/SKILL.md +0 -98
  155. package/template/.claude/skills/security-and-hardening/SKILL.md +0 -349
  156. package/template/.claude/skills/security-and-hardening/security-checklist.md +0 -134
  157. package/template/.claude/skills/shipping-and-launch/SKILL.md +0 -311
  158. package/template/.claude/skills/silent-failure-audit/SKILL.md +0 -73
  159. package/template/.claude/skills/spec-orchestration/SKILL.md +0 -91
  160. package/template/.claude/skills/specialist-agent-routing/SKILL.md +0 -107
  161. package/template/.claude/skills/test-driven-development/SKILL.md +0 -422
  162. package/template/.claude/skills/test-driven-development/testing-patterns.md +0 -236
  163. package/template/.claude/skills/test-execution-and-coverage/SKILL.md +0 -56
  164. package/template/.claude/skills/using-agent-skills/SKILL.md +0 -171
  165. package/template/.claude/skills/verification-orchestration/SKILL.md +0 -68
  166. package/template/.claude/skills/vulnerability-scanner/SKILL.md +0 -276
  167. package/template/.claude/skills/vulnerability-scanner/checklists.md +0 -121
  168. package/template/.claude/skills/vulnerability-scanner/scripts/security_scan.py +0 -458
  169. package/template/.claude/skills/wiki/SKILL.md +0 -149
  170. package/template/.claude/skills/workflow-documentation-sync/SKILL.md +0 -87
  171. package/template/.nexus/nexus-devflow.json +0 -44
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -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,6 @@
1
+ export interface StarterTemplate {
2
+ name: string;
3
+ description: string;
4
+ files: Record<string, string>;
5
+ }
6
+ export declare const starterTemplates: Record<string, StarterTemplate>;
@@ -0,0 +1,8 @@
1
+ export const starterTemplates = {
2
+ default: {
3
+ name: "default",
4
+ description: "Default Nexus-DevFlow workspace configuration",
5
+ files: {}
6
+ }
7
+ };
8
+ //# sourceMappingURL=starter-templates.js.map
@@ -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