chati-dev 4.2.1 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -53
- package/bin/chati.js +150 -5
- package/framework/agents/build/dev.md +509 -76
- package/framework/agents/deploy/devops.md +40 -25
- package/framework/agents/discover/brief.md +156 -22
- package/framework/agents/discover/brownfield-wu.md +24 -14
- package/framework/agents/discover/greenfield-wu.md +100 -14
- package/framework/agents/plan/architect-data-engineer.md +6 -6
- package/framework/agents/plan/architect-system.md +46 -12
- package/framework/agents/plan/architect.md +40 -20
- package/framework/agents/plan/detail.md +36 -24
- package/framework/agents/plan/phases.md +36 -26
- package/framework/agents/plan/tasks.md +114 -33
- package/framework/agents/plan/ux-brand-architect.md +240 -8
- package/framework/agents/plan/ux-component-engineer.md +28 -13
- package/framework/agents/plan/ux-researcher.md +7 -6
- package/framework/agents/plan/ux.md +55 -22
- package/framework/agents/quality/qa-implementation.md +143 -74
- package/framework/agents/quality/qa-planning.md +115 -42
- package/framework/agents/quality/qa-visual.md +439 -0
- package/framework/agents/shared/visualizer.md +128 -0
- package/framework/config.yaml +8 -7
- package/framework/constitution.md +127 -43
- package/framework/context/governance.md +12 -7
- package/framework/context/quality.md +6 -5
- package/framework/context/root.md +6 -6
- package/framework/data/entity-registry.yaml +377 -4
- package/framework/data/model-limits.json +19 -0
- package/framework/domains/agents/qa-visual.yaml +74 -0
- package/framework/domains/constitution.yaml +46 -2
- package/framework/domains/workflows/greenfield-fullstack.yaml +2 -2
- package/framework/hooks/advance-trigger.js +131 -0
- package/framework/hooks/brief-validator.js +83 -0
- package/framework/hooks/constitution-guard.js +91 -36
- package/framework/hooks/license-guard.js +129 -190
- package/framework/hooks/mode-governance.js +68 -16
- package/framework/hooks/model-governance.js +19 -8
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/post-dev.js +207 -0
- package/framework/hooks/prism-engine.js +288 -105
- package/framework/hooks/read-protection.js +37 -9
- package/framework/hooks/reasoning-escalator.js +371 -0
- package/framework/hooks/reference-trigger.js +117 -0
- package/framework/hooks/session-digest.js +94 -20
- package/framework/hooks/settings.json +32 -1
- package/framework/hooks/style-guard.js +52 -13
- package/framework/hooks/team-quality-gate.js +58 -25
- package/framework/hooks/undercover-guard.js +34 -13
- package/framework/i18n/en.yaml +3 -3
- package/framework/i18n/es.yaml +3 -3
- package/framework/i18n/fr.yaml +3 -3
- package/framework/i18n/pt.yaml +3 -3
- package/framework/intelligence/context-engine.md +4 -5
- package/framework/intelligence/decision-engine.md +1 -1
- package/framework/intelligence/hooks-performance.md +3 -3
- package/framework/migrations/v1.0-to-v1.1.yaml +1 -1
- package/framework/migrations/v1.4-to-v2.0.yaml +11 -11
- package/framework/migrations/v4.0-to-v4.1.yaml +2 -2
- package/framework/migrations/v4.2-to-v4.3.yaml +29 -0
- package/framework/orchestrator/chati-router.js +387 -0
- package/framework/orchestrator/chati-update.md +40 -40
- package/framework/orchestrator/chati.md +318 -115
- package/framework/scaffold/motion-premium/README.md +89 -0
- package/framework/scaffold/motion-premium/app/globals.css.template +400 -0
- package/framework/scaffold/motion-premium/app/layout.tsx.template +110 -0
- package/framework/scaffold/motion-premium/components/animation/BackgroundCrossfadeProvider.tsx.template +170 -0
- package/framework/scaffold/motion-premium/components/animation/LenisProvider.tsx.template +49 -0
- package/framework/scaffold/motion-premium/components/animation/PageTransitionWrapper.tsx.template +83 -0
- package/framework/scaffold/motion-premium/components/animation/Preloader.tsx.template +171 -0
- package/framework/scaffold/motion-premium/components/ui/Container.tsx.template +69 -0
- package/framework/scaffold/motion-premium/components/ui/PageSection.tsx.template +74 -0
- package/framework/scaffold/motion-premium/lib/animations/gsap.ts.template +112 -0
- package/framework/scaffold/motion-premium/lib/animations/refreshCoordinator.ts.template +75 -0
- package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +119 -0
- package/framework/scaffold/motion-premium/lib/animations/useGsapContext.ts.template +92 -0
- package/framework/scaffold/motion-premium/lib/animations/useScrollSnapStepper.ts.template +265 -0
- package/framework/scaffold/motion-premium/lib/animations/useSmoothScroll.ts.template +67 -0
- package/framework/scaffold/motion-premium/lib/brand.ts.template +43 -0
- package/framework/scaffold/motion-premium/scaffold.yaml +174 -0
- package/framework/scaffold/motion-premium-3d/README.md +80 -0
- package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoCanvas.tsx.template +81 -0
- package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoClient.tsx.template +75 -0
- package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/page.tsx.template +26 -0
- package/framework/scaffold/motion-premium-3d/components/3d/CameraRig.tsx.template +100 -0
- package/framework/scaffold/motion-premium-3d/components/3d/CanvasProvider.tsx.template +85 -0
- package/framework/scaffold/motion-premium-3d/components/3d/InvalidateOnScroll.tsx.template +51 -0
- package/framework/scaffold/motion-premium-3d/components/3d/MeshCrossfade.tsx.template +79 -0
- package/framework/scaffold/motion-premium-3d/components/3d/ScrollCrossfade.tsx.template +88 -0
- package/framework/scaffold/motion-premium-3d/components/3d/ScrollScene.tsx.template +121 -0
- package/framework/scaffold/motion-premium-3d/components/webgl/SceneFallback.tsx.template +65 -0
- package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +68 -0
- package/framework/scaffold/motion-premium-3d/lib/webgl/detect.ts.template +69 -0
- package/framework/scaffold/motion-premium-3d/scaffold.yaml +133 -0
- package/framework/schemas/session.schema.json +109 -21
- package/framework/scripts/reference-capture.js +430 -0
- package/framework/scripts/visual-qa.js +674 -0
- package/framework/tasks/orchestrator-handoff.md +1 -1
- package/framework/tasks/orchestrator-resume.md +1 -1
- package/framework/tasks/orchestrator-route.md +1 -1
- package/framework/tasks/orchestrator-status.md +3 -3
- package/framework/tasks/qa-planning-gate-define.md +1 -1
- package/framework/templates/brandbook-html-tmpl.md +1 -1
- package/framework/templates/brandbook-tmpl.yaml +1 -1
- package/framework/templates/component-spec-tmpl.yaml +1 -1
- package/framework/templates/design-token-tmpl.yaml +1 -1
- package/framework/templates/icon-system-tmpl.yaml +1 -1
- package/framework/templates/team-planning-tasks.yaml +6 -5
- package/framework/workflows/brownfield-discovery.yaml +2 -2
- package/framework/workflows/brownfield-fullstack.yaml +15 -11
- package/framework/workflows/brownfield-service.yaml +14 -10
- package/framework/workflows/brownfield-ui.yaml +15 -11
- package/framework/workflows/greenfield-fullstack.yaml +16 -13
- package/framework/workflows/quick-flow.yaml +3 -3
- package/framework/workflows/standard-flow.yaml +12 -9
- package/package.json +10 -5
- package/src/autonomy/autonomous-gate.js +1 -0
- package/src/autonomy/build-state.js +1 -2
- package/src/autonomy/progress-reporter.js +1 -1
- package/src/config/agent-customizer.js +11 -3
- package/src/config/claude-settings-generator.js +226 -0
- package/src/config/context-file-generator.js +41 -21
- package/src/config/framework-adapter.js +1 -0
- package/src/config/gemini-hooks-generator.js +76 -6
- package/src/config/mcp-configs.js +1 -0
- package/src/context/layers/l1-global.js +2 -1
- package/src/dashboard/data-reader.js +4 -3
- package/src/dashboard/layout.js +2 -1
- package/src/decision/analyzer.js +6 -30
- package/src/decision/engine.js +4 -28
- package/src/decision/registry-healer.js +3 -2
- package/src/decision/registry-updater.js +23 -14
- package/src/extensions/loader.js +2 -8
- package/src/gates/g1-planning-complete.js +2 -1
- package/src/gates/g2-qa-planning.js +2 -1
- package/src/gates/g3-implementation.js +2 -1
- package/src/gates/g4-qa-implementation.js +3 -2
- package/src/gates/g5-deploy-ready.js +2 -1
- package/src/health/engine.js +4 -3
- package/src/installer/core.js +557 -81
- package/src/installer/preflight.js +131 -0
- package/src/installer/provider-overlay.js +3 -3
- package/src/installer/scaffold-applier.js +358 -0
- package/src/installer/templates.js +52 -31
- package/src/installer/validator.js +17 -12
- package/src/intelligence/registry-manager.js +22 -29
- package/src/intelligence/timeline.js +11 -6
- package/src/license/commands.js +1 -1
- package/src/license/wait.js +102 -0
- package/src/memory/agent-memory.js +81 -0
- package/src/memory/dream.js +32 -1
- package/src/merger/replace-merger.js +28 -15
- package/src/orchestrator/agent-selector.js +2 -1
- package/src/orchestrator/cli.js +1908 -80
- package/src/orchestrator/doctor.js +270 -0
- package/src/orchestrator/handoff-engine.js +4 -3
- package/src/orchestrator/index.js +2 -0
- package/src/orchestrator/pipeline-manager.js +306 -15
- package/src/orchestrator/session-manager.js +331 -6
- package/src/tasks/handoff.js +3 -2
- package/src/telemetry/config.js +4 -3
- package/src/telemetry/schema.js +1 -0
- package/src/terminal/collector.js +3 -2
- package/src/terminal/index.js +1 -2
- package/src/terminal/isolation.js +52 -18
- package/src/terminal/prompt-builder.js +42 -25
- package/src/terminal/run-parallel.js +1 -1
- package/src/terminal/run-team.js +3 -3
- package/src/terminal/team-task-list.js +43 -4
- package/src/upgrade/backup.js +3 -2
- package/src/upgrade/checker.js +3 -2
- package/src/upgrade/migrator.js +65 -7
- package/src/upgrade/tracked-files-detector.js +86 -0
- package/src/upgrade/user-messages.js +94 -0
- package/src/utils/config-parser.js +2 -1
- package/src/utils/feature-flags.js +2 -1
- package/src/utils/flatten-entities.js +69 -0
- package/src/utils/framework-dir.js +16 -0
- package/src/utils/model-id.js +85 -0
- package/src/utils/provider-limits.js +84 -23
- package/src/utils/schema-validator.js +1 -1
- package/src/wizard/i18n.js +5 -4
- package/src/wizard/index.js +14 -0
- package/assets/logo - c/303/263pia.png +0 -0
- package/assets/logo.svg +0 -42
- package/assets/logo2.png +0 -0
- package/assets/social-preview.png +0 -0
- package/scripts/bundle-framework.js +0 -69
- package/scripts/changelog-generator.js +0 -222
- package/scripts/codebase-mapper.js +0 -728
- package/scripts/commit-message-generator.js +0 -167
- package/scripts/coverage-analyzer.js +0 -260
- package/scripts/dependency-analyzer.js +0 -280
- package/scripts/doctor/checks/agents.js +0 -77
- package/scripts/doctor/checks/constitution.js +0 -41
- package/scripts/doctor/checks/domain-alignment.js +0 -58
- package/scripts/doctor/checks/prism-layers.js +0 -84
- package/scripts/doctor/checks/registry.js +0 -55
- package/scripts/doctor/checks/schemas.js +0 -61
- package/scripts/doctor/fixes/reference-fix.js +0 -100
- package/scripts/doctor/fixes/registry-fix.js +0 -56
- package/scripts/doctor/index.js +0 -212
- package/scripts/framework-analyzer.js +0 -308
- package/scripts/generate-constitution-domain.js +0 -253
- package/scripts/generate-signing-key.js +0 -33
- package/scripts/health-check.js +0 -481
- package/scripts/ide-sync.js +0 -326
- package/scripts/performance-analyzer.js +0 -325
- package/scripts/plan-tracker.js +0 -278
- package/scripts/populate-entity-registry.js +0 -481
- package/scripts/pr-review.js +0 -317
- package/scripts/rollback-manager.js +0 -310
- package/scripts/semantic-lint.js +0 -328
- package/scripts/sign-manifest.js +0 -53
- package/scripts/stuck-detector.js +0 -343
- package/scripts/test-quality-assessment.js +0 -257
- package/scripts/validate-agents.js +0 -368
- package/scripts/validate-package.js +0 -367
- package/scripts/validate-tasks.js +0 -465
- package/src/autonomy/worktree-manager.js +0 -250
- package/src/intelligence/decision-engine.js +0 -256
- package/src/intelligence/document-sharder.js +0 -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`);
|