chati-dev 4.2.2 → 4.3.1

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 (221) hide show
  1. package/README.md +80 -53
  2. package/bin/chati.js +170 -5
  3. package/framework/agents/build/dev.md +509 -76
  4. package/framework/agents/deploy/devops.md +40 -25
  5. package/framework/agents/discover/brief.md +158 -22
  6. package/framework/agents/discover/brownfield-wu.md +26 -14
  7. package/framework/agents/discover/greenfield-wu.md +102 -14
  8. package/framework/agents/plan/architect-data-engineer.md +6 -6
  9. package/framework/agents/plan/architect-system.md +46 -12
  10. package/framework/agents/plan/architect.md +40 -20
  11. package/framework/agents/plan/detail.md +38 -24
  12. package/framework/agents/plan/phases.md +36 -26
  13. package/framework/agents/plan/tasks.md +114 -33
  14. package/framework/agents/plan/ux-brand-architect.md +240 -8
  15. package/framework/agents/plan/ux-component-engineer.md +28 -13
  16. package/framework/agents/plan/ux-researcher.md +7 -6
  17. package/framework/agents/plan/ux.md +55 -22
  18. package/framework/agents/quality/qa-implementation.md +143 -74
  19. package/framework/agents/quality/qa-planning.md +115 -42
  20. package/framework/agents/quality/qa-visual.md +448 -0
  21. package/framework/agents/shared/visualizer.md +128 -0
  22. package/framework/config.yaml +7 -6
  23. package/framework/constitution.md +127 -44
  24. package/framework/context/governance.md +12 -7
  25. package/framework/context/quality.md +6 -5
  26. package/framework/context/root.md +6 -6
  27. package/framework/data/entity-registry.yaml +377 -4
  28. package/framework/data/model-limits.json +19 -0
  29. package/framework/domains/agents/qa-visual.yaml +74 -0
  30. package/framework/domains/constitution.yaml +46 -2
  31. package/framework/domains/workflows/greenfield-fullstack.yaml +2 -2
  32. package/framework/hooks/advance-trigger.js +131 -0
  33. package/framework/hooks/brief-validator.js +83 -0
  34. package/framework/hooks/constitution-guard.js +24 -5
  35. package/framework/hooks/license-guard.js +62 -27
  36. package/framework/hooks/mode-governance.js +13 -2
  37. package/framework/hooks/model-governance.js +1 -0
  38. package/framework/hooks/post-dev.js +207 -0
  39. package/framework/hooks/prism-engine.js +274 -105
  40. package/framework/hooks/reasoning-escalator.js +371 -0
  41. package/framework/hooks/reference-trigger.js +117 -0
  42. package/framework/hooks/session-digest.js +50 -1
  43. package/framework/hooks/settings.json +32 -1
  44. package/framework/hooks/style-guard.js +25 -6
  45. package/framework/hooks/team-quality-gate.js +19 -12
  46. package/framework/hooks/undercover-guard.js +4 -2
  47. package/framework/i18n/en.yaml +3 -3
  48. package/framework/i18n/es.yaml +3 -3
  49. package/framework/i18n/fr.yaml +3 -3
  50. package/framework/i18n/pt.yaml +3 -3
  51. package/framework/intelligence/context-engine.md +4 -5
  52. package/framework/intelligence/decision-engine.md +1 -1
  53. package/framework/intelligence/hooks-performance.md +3 -3
  54. package/framework/migrations/v1.0-to-v1.1.yaml +1 -1
  55. package/framework/migrations/v1.4-to-v2.0.yaml +11 -11
  56. package/framework/migrations/v4.0-to-v4.1.yaml +2 -2
  57. package/framework/migrations/v4.2-to-v4.3.yaml +29 -0
  58. package/framework/orchestrator/chati-router.js +441 -0
  59. package/framework/orchestrator/chati-update.md +40 -40
  60. package/framework/orchestrator/chati.md +295 -94
  61. package/framework/rules/human-writing-style.md +47 -0
  62. package/framework/scaffold/motion-premium/README.md +99 -0
  63. package/framework/scaffold/motion-premium/app/globals.css.template +400 -0
  64. package/framework/scaffold/motion-premium/app/layout.tsx.template +110 -0
  65. package/framework/scaffold/motion-premium/components/animation/BackgroundCrossfadeProvider.tsx.template +170 -0
  66. package/framework/scaffold/motion-premium/components/animation/LenisProvider.tsx.template +49 -0
  67. package/framework/scaffold/motion-premium/components/animation/PageTransitionWrapper.tsx.template +83 -0
  68. package/framework/scaffold/motion-premium/components/animation/Preloader.tsx.template +171 -0
  69. package/framework/scaffold/motion-premium/components/ui/Container.tsx.template +69 -0
  70. package/framework/scaffold/motion-premium/components/ui/PageSection.tsx.template +74 -0
  71. package/framework/scaffold/motion-premium/lib/animations/gsap.ts.template +112 -0
  72. package/framework/scaffold/motion-premium/lib/animations/refreshCoordinator.ts.template +75 -0
  73. package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +119 -0
  74. package/framework/scaffold/motion-premium/lib/animations/useGsapContext.ts.template +92 -0
  75. package/framework/scaffold/motion-premium/lib/animations/useScrollSnapStepper.ts.template +265 -0
  76. package/framework/scaffold/motion-premium/lib/animations/useSmoothScroll.ts.template +67 -0
  77. package/framework/scaffold/motion-premium/lib/brand.ts.template +43 -0
  78. package/framework/scaffold/motion-premium/scaffold.yaml +178 -0
  79. package/framework/scaffold/motion-premium-3d/README.md +90 -0
  80. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoCanvas.tsx.template +81 -0
  81. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoClient.tsx.template +75 -0
  82. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/page.tsx.template +26 -0
  83. package/framework/scaffold/motion-premium-3d/components/3d/CameraRig.tsx.template +100 -0
  84. package/framework/scaffold/motion-premium-3d/components/3d/CanvasProvider.tsx.template +85 -0
  85. package/framework/scaffold/motion-premium-3d/components/3d/InvalidateOnScroll.tsx.template +51 -0
  86. package/framework/scaffold/motion-premium-3d/components/3d/MeshCrossfade.tsx.template +79 -0
  87. package/framework/scaffold/motion-premium-3d/components/3d/ScrollCrossfade.tsx.template +88 -0
  88. package/framework/scaffold/motion-premium-3d/components/3d/ScrollScene.tsx.template +121 -0
  89. package/framework/scaffold/motion-premium-3d/components/webgl/SceneFallback.tsx.template +65 -0
  90. package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +68 -0
  91. package/framework/scaffold/motion-premium-3d/lib/webgl/detect.ts.template +69 -0
  92. package/framework/scaffold/motion-premium-3d/scaffold.yaml +136 -0
  93. package/framework/schemas/session.schema.json +109 -21
  94. package/framework/scripts/reference-capture.js +430 -0
  95. package/framework/scripts/visual-qa.js +686 -0
  96. package/framework/tasks/orchestrator-handoff.md +1 -1
  97. package/framework/tasks/orchestrator-resume.md +1 -1
  98. package/framework/tasks/orchestrator-route.md +1 -1
  99. package/framework/tasks/orchestrator-status.md +3 -3
  100. package/framework/tasks/qa-planning-gate-define.md +1 -1
  101. package/framework/templates/brandbook-html-tmpl.md +2 -2
  102. package/framework/templates/brandbook-tmpl.yaml +1 -1
  103. package/framework/templates/component-spec-tmpl.yaml +1 -1
  104. package/framework/templates/design-token-tmpl.yaml +1 -1
  105. package/framework/templates/icon-system-tmpl.yaml +1 -1
  106. package/framework/templates/team-planning-tasks.yaml +6 -5
  107. package/framework/workflows/brownfield-discovery.yaml +2 -2
  108. package/framework/workflows/brownfield-fullstack.yaml +15 -11
  109. package/framework/workflows/brownfield-service.yaml +14 -10
  110. package/framework/workflows/brownfield-ui.yaml +15 -11
  111. package/framework/workflows/greenfield-fullstack.yaml +16 -13
  112. package/framework/workflows/quick-flow.yaml +3 -3
  113. package/framework/workflows/standard-flow.yaml +12 -9
  114. package/package.json +12 -6
  115. package/src/autonomy/autonomous-gate.js +1 -0
  116. package/src/autonomy/build-state.js +1 -2
  117. package/src/autonomy/progress-reporter.js +1 -1
  118. package/src/config/agent-customizer.js +11 -3
  119. package/src/config/claude-settings-generator.js +27 -7
  120. package/src/config/context-file-generator.js +41 -21
  121. package/src/config/framework-adapter.js +1 -0
  122. package/src/config/gemini-hooks-generator.js +19 -7
  123. package/src/config/mcp-configs.js +1 -0
  124. package/src/context/layers/l1-global.js +2 -1
  125. package/src/dashboard/data-reader.js +4 -3
  126. package/src/dashboard/layout.js +2 -1
  127. package/src/decision/analyzer.js +6 -30
  128. package/src/decision/engine.js +4 -28
  129. package/src/decision/registry-healer.js +3 -2
  130. package/src/decision/registry-updater.js +23 -14
  131. package/src/extensions/loader.js +2 -8
  132. package/src/gates/g1-planning-complete.js +2 -1
  133. package/src/gates/g2-qa-planning.js +2 -1
  134. package/src/gates/g3-implementation.js +2 -1
  135. package/src/gates/g4-qa-implementation.js +3 -2
  136. package/src/gates/g5-deploy-ready.js +2 -1
  137. package/src/health/engine.js +4 -3
  138. package/src/installer/core.js +431 -81
  139. package/src/installer/preflight.js +131 -0
  140. package/src/installer/provider-overlay.js +3 -3
  141. package/src/installer/scaffold-applier.js +358 -0
  142. package/src/installer/templates.js +46 -29
  143. package/src/installer/validator.js +17 -12
  144. package/src/intelligence/registry-manager.js +22 -29
  145. package/src/intelligence/timeline.js +11 -6
  146. package/src/license/commands.js +1 -1
  147. package/src/license/wait.js +102 -0
  148. package/src/memory/agent-memory.js +81 -0
  149. package/src/memory/dream.js +32 -1
  150. package/src/merger/replace-merger.js +28 -15
  151. package/src/orchestrator/agent-selector.js +2 -1
  152. package/src/orchestrator/cli.js +1880 -71
  153. package/src/orchestrator/doctor.js +270 -0
  154. package/src/orchestrator/handoff-engine.js +4 -3
  155. package/src/orchestrator/index.js +2 -0
  156. package/src/orchestrator/pipeline-manager.js +306 -15
  157. package/src/orchestrator/session-manager.js +339 -6
  158. package/src/tasks/handoff.js +3 -2
  159. package/src/telemetry/config.js +4 -3
  160. package/src/telemetry/schema.js +1 -0
  161. package/src/terminal/collector.js +3 -2
  162. package/src/terminal/index.js +1 -2
  163. package/src/terminal/isolation.js +52 -18
  164. package/src/terminal/prompt-builder.js +42 -25
  165. package/src/terminal/run-parallel.js +1 -1
  166. package/src/terminal/run-team.js +3 -3
  167. package/src/terminal/team-task-list.js +43 -4
  168. package/src/upgrade/backup.js +3 -2
  169. package/src/upgrade/checker.js +3 -2
  170. package/src/upgrade/migrator.js +65 -7
  171. package/src/upgrade/tracked-files-detector.js +86 -0
  172. package/src/upgrade/user-messages.js +94 -0
  173. package/src/utils/config-parser.js +2 -1
  174. package/src/utils/feature-flags.js +2 -1
  175. package/src/utils/flatten-entities.js +69 -0
  176. package/src/utils/framework-dir.js +16 -0
  177. package/src/utils/model-id.js +85 -0
  178. package/src/utils/provider-limits.js +84 -23
  179. package/src/utils/schema-validator.js +1 -1
  180. package/src/wizard/i18n.js +5 -4
  181. package/src/wizard/index.js +14 -0
  182. package/assets/logo - c/303/263pia.png +0 -0
  183. package/assets/logo.svg +0 -42
  184. package/assets/logo2.png +0 -0
  185. package/assets/social-preview.png +0 -0
  186. package/scripts/bundle-framework.js +0 -69
  187. package/scripts/changelog-generator.js +0 -222
  188. package/scripts/codebase-mapper.js +0 -728
  189. package/scripts/commit-message-generator.js +0 -167
  190. package/scripts/coverage-analyzer.js +0 -260
  191. package/scripts/dependency-analyzer.js +0 -280
  192. package/scripts/doctor/checks/agents.js +0 -77
  193. package/scripts/doctor/checks/constitution.js +0 -41
  194. package/scripts/doctor/checks/domain-alignment.js +0 -58
  195. package/scripts/doctor/checks/prism-layers.js +0 -84
  196. package/scripts/doctor/checks/registry.js +0 -55
  197. package/scripts/doctor/checks/schemas.js +0 -61
  198. package/scripts/doctor/fixes/reference-fix.js +0 -100
  199. package/scripts/doctor/fixes/registry-fix.js +0 -56
  200. package/scripts/doctor/index.js +0 -212
  201. package/scripts/framework-analyzer.js +0 -308
  202. package/scripts/generate-constitution-domain.js +0 -253
  203. package/scripts/generate-signing-key.js +0 -33
  204. package/scripts/health-check.js +0 -481
  205. package/scripts/ide-sync.js +0 -326
  206. package/scripts/performance-analyzer.js +0 -325
  207. package/scripts/plan-tracker.js +0 -278
  208. package/scripts/populate-entity-registry.js +0 -481
  209. package/scripts/pr-review.js +0 -317
  210. package/scripts/rollback-manager.js +0 -310
  211. package/scripts/semantic-lint.js +0 -328
  212. package/scripts/sign-manifest.js +0 -53
  213. package/scripts/stuck-detector.js +0 -343
  214. package/scripts/test-quality-assessment.js +0 -257
  215. package/scripts/validate-agents.js +0 -368
  216. package/scripts/validate-package.js +0 -505
  217. package/scripts/validate-tasks.js +0 -465
  218. package/src/autonomy/worktree-manager.js +0 -250
  219. package/src/intelligence/decision-engine.js +0 -256
  220. package/src/intelligence/document-sharder.js +0 -221
  221. package/src/intelligence/elicitation.js +0 -265
@@ -1,253 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Generate Constitution Domain — Extracts governance rules from constitution.md
5
- * and generates a structured YAML domain file.
6
- *
7
- * Exports:
8
- * generateConstitutionDomain(frameworkDir) → writes domains/constitution.yaml
9
- */
10
-
11
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
12
- import { join } from 'path';
13
- import yaml from 'js-yaml';
14
-
15
- /**
16
- * Map Roman numerals to integers.
17
- * @param {string} roman - Roman numeral string.
18
- * @returns {number} Integer value.
19
- */
20
- function romanToInt(roman) {
21
- const values = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
22
- let result = 0;
23
- for (let i = 0; i < roman.length; i++) {
24
- const current = values[roman[i]] || 0;
25
- const next = values[roman[i + 1]] || 0;
26
- result += current < next ? -current : current;
27
- }
28
- return result;
29
- }
30
-
31
- /**
32
- * Extract articles from constitution.md content.
33
- * @param {string} content - Full constitution markdown.
34
- * @returns {object[]} Array of { id, numeral, title, rules, enforcement }.
35
- */
36
- function extractArticles(content) {
37
- const articles = [];
38
-
39
- // Split by article headers
40
- const articleRegex = /^## Article ([IVXLCDM]+):\s*(.+)/gm;
41
- let match;
42
- const articlePositions = [];
43
-
44
- while ((match = articleRegex.exec(content)) !== null) {
45
- articlePositions.push({
46
- numeral: match[1],
47
- title: match[2].trim(),
48
- start: match.index,
49
- });
50
- }
51
-
52
- for (let i = 0; i < articlePositions.length; i++) {
53
- const pos = articlePositions[i];
54
- const end = i + 1 < articlePositions.length ? articlePositions[i + 1].start : content.length;
55
- const section = content.slice(pos.start, end);
56
-
57
- // Extract enforcement
58
- const enforcementMatch = section.match(/\*\*Enforcement:\s*(BLOCK|GUIDE|WARN)\*\*/);
59
- const enforcement = enforcementMatch ? enforcementMatch[1].toLowerCase() : 'unknown';
60
-
61
- // Extract numbered rules (lines starting with number followed by period)
62
- const rules = [];
63
- const ruleLines = section.match(/^\d+\.\s+.+/gm) || [];
64
- for (const line of ruleLines) {
65
- const ruleText = line.replace(/^\d+\.\s+/, '').replace(/\*\*/g, '').trim();
66
- if (ruleText.length > 10) {
67
- rules.push(ruleText);
68
- }
69
- }
70
-
71
- articles.push({
72
- id: pos.numeral,
73
- number: romanToInt(pos.numeral),
74
- title: pos.title,
75
- rules,
76
- enforcement,
77
- });
78
- }
79
-
80
- return articles;
81
- }
82
-
83
- /**
84
- * Extract mode definitions from Article XI.
85
- * @param {string} content - Full constitution markdown.
86
- * @returns {object|null} Mode definitions.
87
- */
88
- function extractModes(content) {
89
- // Find Article XI section
90
- const xiMatch = content.match(/## Article XI[\s\S]*?(?=## Article [IVXLCDM]+:|$)/);
91
- if (!xiMatch) return null;
92
-
93
- const section = xiMatch[0];
94
-
95
- const modes = {};
96
-
97
- // Extract from the table
98
- const tableRegex = /\|\s*\*\*(\w+)\*\*\s*\|([^|]*)\|([^|]*)\|([^|]*)\|/g;
99
- let tableMatch;
100
-
101
- while ((tableMatch = tableRegex.exec(section)) !== null) {
102
- const modeName = tableMatch[1].toLowerCase();
103
- const states = tableMatch[2].trim();
104
- const reads = tableMatch[3].trim();
105
- const writes = tableMatch[4].trim();
106
-
107
- modes[modeName] = {
108
- states: states.split(',').map(s => s.trim()).filter(Boolean),
109
- reads: reads || 'Entire project',
110
- writes: writes || 'unknown',
111
- };
112
- }
113
-
114
- return Object.keys(modes).length > 0 ? modes : null;
115
- }
116
-
117
- /**
118
- * Extract blocker codes from constitution content.
119
- * @param {string} content - Full constitution markdown.
120
- * @returns {{ critical: string[], general: string[] }}
121
- */
122
- function extractBlockers(content) {
123
- const critical = [];
124
- const general = [];
125
-
126
- // Look for C01-C99 pattern (critical blockers)
127
- const criticalMatches = content.match(/C\d{2}/g) || [];
128
- for (const c of [...new Set(criticalMatches)]) {
129
- critical.push(c);
130
- }
131
-
132
- // Look for G01-G99 pattern (general blockers)
133
- const generalMatches = content.match(/G\d{2}/g) || [];
134
- for (const g of [...new Set(generalMatches)]) {
135
- general.push(g);
136
- }
137
-
138
- return { critical: critical.sort(), general: general.sort() };
139
- }
140
-
141
- /**
142
- * Extract quality thresholds from constitution content.
143
- * @param {string} content - Full constitution markdown.
144
- * @returns {object} Quality thresholds.
145
- */
146
- function extractQualityThresholds(content) {
147
- const thresholds = {};
148
-
149
- // Look for percentage thresholds
150
- const selfValidation = content.match(/>= (\d+)%.*(?:self|validation|criteria|quality)/i);
151
- if (selfValidation) {
152
- thresholds.selfValidation = parseInt(selfValidation[1], 10);
153
- }
154
-
155
- const testCoverage = content.match(/test coverage.*?>= (\d+)%/i) || content.match(/>= (\d+)%.*?test coverage/i);
156
- if (testCoverage) {
157
- thresholds.testCoverage = parseInt(testCoverage[1], 10);
158
- }
159
-
160
- const maxCorrections = content.match(/(?:max|maximum)\s+(\d+)\s+correction/i);
161
- if (maxCorrections) {
162
- thresholds.maxCorrectionLoops = parseInt(maxCorrections[1], 10);
163
- }
164
-
165
- return thresholds;
166
- }
167
-
168
- /**
169
- * Generate a constitution domain YAML file from constitution.md.
170
- * @param {string} frameworkDir - Path to the framework directory.
171
- * @returns {{ path: string, domain: object }} The generated domain object and file path.
172
- */
173
- export function generateConstitutionDomain(frameworkDir) {
174
- const constPath = join(frameworkDir, 'constitution.md');
175
- if (!existsSync(constPath)) {
176
- throw new Error(`constitution.md not found at: ${constPath}`);
177
- }
178
-
179
- const content = readFileSync(constPath, 'utf8');
180
-
181
- const articles = extractArticles(content);
182
- const modes = extractModes(content);
183
- const blockers = extractBlockers(content);
184
- const thresholds = extractQualityThresholds(content);
185
-
186
- const domain = {
187
- constitution: {
188
- version: '1.0',
189
- source: 'constitution.md',
190
- generatedAt: new Date().toISOString(),
191
- articleCount: articles.length,
192
- articles: articles.map(a => ({
193
- id: a.id,
194
- title: a.title,
195
- enforcement: a.enforcement,
196
- rules: a.rules,
197
- })),
198
- },
199
- };
200
-
201
- if (modes) {
202
- domain.constitution.modes = modes;
203
- }
204
-
205
- if (blockers.critical.length > 0 || blockers.general.length > 0) {
206
- domain.constitution.blockers = blockers;
207
- }
208
-
209
- if (Object.keys(thresholds).length > 0) {
210
- domain.constitution.qualityThresholds = thresholds;
211
- }
212
-
213
- // Write the domain file
214
- const domainsDir = join(frameworkDir, 'domains');
215
- mkdirSync(domainsDir, { recursive: true });
216
-
217
- const outputPath = join(domainsDir, 'constitution.yaml');
218
- const yamlContent = yaml.dump(domain, {
219
- lineWidth: 120,
220
- noRefs: true,
221
- sortKeys: false,
222
- });
223
-
224
- writeFileSync(outputPath, `# Constitution Domain — Auto-generated from constitution.md\n# Do not edit manually. Regenerate with: node scripts/generate-constitution-domain.js\n\n${yamlContent}`, 'utf8');
225
-
226
- return { path: outputPath, domain };
227
- }
228
-
229
- // ---------------------------------------------------------------------------
230
- // CLI entrypoint
231
- // ---------------------------------------------------------------------------
232
-
233
- const isMainModule = process.argv[1] && (
234
- process.argv[1].endsWith('generate-constitution-domain.js') ||
235
- process.argv[1].endsWith('generate-constitution-domain')
236
- );
237
-
238
- if (isMainModule) {
239
- const frameworkDir = process.argv[2] || join(process.cwd(), 'chati.dev');
240
-
241
- console.log(`Generating constitution domain from: ${frameworkDir}`);
242
-
243
- try {
244
- const { path, domain } = generateConstitutionDomain(frameworkDir);
245
- console.log(`Articles extracted: ${domain.constitution.articleCount}`);
246
- console.log(`Modes: ${domain.constitution.modes ? Object.keys(domain.constitution.modes).join(', ') : 'none'}`);
247
- console.log(`Blockers: critical=${domain.constitution.blockers?.critical?.length || 0}, general=${domain.constitution.blockers?.general?.length || 0}`);
248
- console.log(`Written to: ${path}`);
249
- } catch (err) {
250
- console.error(`Error: ${err.message}`);
251
- process.exit(1);
252
- }
253
- }
@@ -1,33 +0,0 @@
1
- /**
2
- * One-time keypair generation for Ed25519 manifest signing.
3
- * Run: node scripts/generate-signing-key.js
4
- *
5
- * Private key: .signing-key.pem (GITIGNORED — never commit)
6
- * Public key: src/installer/signing-public-key.pem (committed — distributed with package)
7
- */
8
- import { generateKeyPairSync } from 'crypto';
9
- import { writeFileSync, existsSync } from 'fs';
10
- import { join, dirname } from 'path';
11
- import { fileURLToPath } from 'url';
12
-
13
- const __dirname = dirname(fileURLToPath(import.meta.url));
14
- const privateKeyPath = join(__dirname, '..', '.signing-key.pem');
15
- const publicKeyPath = join(__dirname, '..', 'src', 'installer', 'signing-public-key.pem');
16
-
17
- if (existsSync(privateKeyPath)) {
18
- console.error('Private key already exists at .signing-key.pem');
19
- console.error('Delete it first if you want to regenerate.');
20
- process.exit(1);
21
- }
22
-
23
- const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
24
- publicKeyEncoding: { type: 'spki', format: 'pem' },
25
- privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
26
- });
27
-
28
- writeFileSync(privateKeyPath, privateKey);
29
- writeFileSync(publicKeyPath, publicKey);
30
-
31
- console.log('Ed25519 keypair generated.');
32
- console.log(` Private: .signing-key.pem (GITIGNORED)`);
33
- console.log(` Public: src/installer/signing-public-key.pem`);