chati-dev 4.2.2 → 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.
Files changed (220) hide show
  1. package/README.md +80 -53
  2. package/bin/chati.js +150 -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 +156 -22
  6. package/framework/agents/discover/brownfield-wu.md +24 -14
  7. package/framework/agents/discover/greenfield-wu.md +100 -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 +36 -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 +439 -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 +387 -0
  59. package/framework/orchestrator/chati-update.md +40 -40
  60. package/framework/orchestrator/chati.md +294 -94
  61. package/framework/scaffold/motion-premium/README.md +89 -0
  62. package/framework/scaffold/motion-premium/app/globals.css.template +400 -0
  63. package/framework/scaffold/motion-premium/app/layout.tsx.template +110 -0
  64. package/framework/scaffold/motion-premium/components/animation/BackgroundCrossfadeProvider.tsx.template +170 -0
  65. package/framework/scaffold/motion-premium/components/animation/LenisProvider.tsx.template +49 -0
  66. package/framework/scaffold/motion-premium/components/animation/PageTransitionWrapper.tsx.template +83 -0
  67. package/framework/scaffold/motion-premium/components/animation/Preloader.tsx.template +171 -0
  68. package/framework/scaffold/motion-premium/components/ui/Container.tsx.template +69 -0
  69. package/framework/scaffold/motion-premium/components/ui/PageSection.tsx.template +74 -0
  70. package/framework/scaffold/motion-premium/lib/animations/gsap.ts.template +112 -0
  71. package/framework/scaffold/motion-premium/lib/animations/refreshCoordinator.ts.template +75 -0
  72. package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +119 -0
  73. package/framework/scaffold/motion-premium/lib/animations/useGsapContext.ts.template +92 -0
  74. package/framework/scaffold/motion-premium/lib/animations/useScrollSnapStepper.ts.template +265 -0
  75. package/framework/scaffold/motion-premium/lib/animations/useSmoothScroll.ts.template +67 -0
  76. package/framework/scaffold/motion-premium/lib/brand.ts.template +43 -0
  77. package/framework/scaffold/motion-premium/scaffold.yaml +174 -0
  78. package/framework/scaffold/motion-premium-3d/README.md +80 -0
  79. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoCanvas.tsx.template +81 -0
  80. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoClient.tsx.template +75 -0
  81. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/page.tsx.template +26 -0
  82. package/framework/scaffold/motion-premium-3d/components/3d/CameraRig.tsx.template +100 -0
  83. package/framework/scaffold/motion-premium-3d/components/3d/CanvasProvider.tsx.template +85 -0
  84. package/framework/scaffold/motion-premium-3d/components/3d/InvalidateOnScroll.tsx.template +51 -0
  85. package/framework/scaffold/motion-premium-3d/components/3d/MeshCrossfade.tsx.template +79 -0
  86. package/framework/scaffold/motion-premium-3d/components/3d/ScrollCrossfade.tsx.template +88 -0
  87. package/framework/scaffold/motion-premium-3d/components/3d/ScrollScene.tsx.template +121 -0
  88. package/framework/scaffold/motion-premium-3d/components/webgl/SceneFallback.tsx.template +65 -0
  89. package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +68 -0
  90. package/framework/scaffold/motion-premium-3d/lib/webgl/detect.ts.template +69 -0
  91. package/framework/scaffold/motion-premium-3d/scaffold.yaml +133 -0
  92. package/framework/schemas/session.schema.json +109 -21
  93. package/framework/scripts/reference-capture.js +430 -0
  94. package/framework/scripts/visual-qa.js +674 -0
  95. package/framework/tasks/orchestrator-handoff.md +1 -1
  96. package/framework/tasks/orchestrator-resume.md +1 -1
  97. package/framework/tasks/orchestrator-route.md +1 -1
  98. package/framework/tasks/orchestrator-status.md +3 -3
  99. package/framework/tasks/qa-planning-gate-define.md +1 -1
  100. package/framework/templates/brandbook-html-tmpl.md +1 -1
  101. package/framework/templates/brandbook-tmpl.yaml +1 -1
  102. package/framework/templates/component-spec-tmpl.yaml +1 -1
  103. package/framework/templates/design-token-tmpl.yaml +1 -1
  104. package/framework/templates/icon-system-tmpl.yaml +1 -1
  105. package/framework/templates/team-planning-tasks.yaml +6 -5
  106. package/framework/workflows/brownfield-discovery.yaml +2 -2
  107. package/framework/workflows/brownfield-fullstack.yaml +15 -11
  108. package/framework/workflows/brownfield-service.yaml +14 -10
  109. package/framework/workflows/brownfield-ui.yaml +15 -11
  110. package/framework/workflows/greenfield-fullstack.yaml +16 -13
  111. package/framework/workflows/quick-flow.yaml +3 -3
  112. package/framework/workflows/standard-flow.yaml +12 -9
  113. package/package.json +10 -5
  114. package/src/autonomy/autonomous-gate.js +1 -0
  115. package/src/autonomy/build-state.js +1 -2
  116. package/src/autonomy/progress-reporter.js +1 -1
  117. package/src/config/agent-customizer.js +11 -3
  118. package/src/config/claude-settings-generator.js +27 -7
  119. package/src/config/context-file-generator.js +41 -21
  120. package/src/config/framework-adapter.js +1 -0
  121. package/src/config/gemini-hooks-generator.js +19 -7
  122. package/src/config/mcp-configs.js +1 -0
  123. package/src/context/layers/l1-global.js +2 -1
  124. package/src/dashboard/data-reader.js +4 -3
  125. package/src/dashboard/layout.js +2 -1
  126. package/src/decision/analyzer.js +6 -30
  127. package/src/decision/engine.js +4 -28
  128. package/src/decision/registry-healer.js +3 -2
  129. package/src/decision/registry-updater.js +23 -14
  130. package/src/extensions/loader.js +2 -8
  131. package/src/gates/g1-planning-complete.js +2 -1
  132. package/src/gates/g2-qa-planning.js +2 -1
  133. package/src/gates/g3-implementation.js +2 -1
  134. package/src/gates/g4-qa-implementation.js +3 -2
  135. package/src/gates/g5-deploy-ready.js +2 -1
  136. package/src/health/engine.js +4 -3
  137. package/src/installer/core.js +422 -81
  138. package/src/installer/preflight.js +131 -0
  139. package/src/installer/provider-overlay.js +3 -3
  140. package/src/installer/scaffold-applier.js +358 -0
  141. package/src/installer/templates.js +46 -29
  142. package/src/installer/validator.js +17 -12
  143. package/src/intelligence/registry-manager.js +22 -29
  144. package/src/intelligence/timeline.js +11 -6
  145. package/src/license/commands.js +1 -1
  146. package/src/license/wait.js +102 -0
  147. package/src/memory/agent-memory.js +81 -0
  148. package/src/memory/dream.js +32 -1
  149. package/src/merger/replace-merger.js +28 -15
  150. package/src/orchestrator/agent-selector.js +2 -1
  151. package/src/orchestrator/cli.js +1869 -71
  152. package/src/orchestrator/doctor.js +270 -0
  153. package/src/orchestrator/handoff-engine.js +4 -3
  154. package/src/orchestrator/index.js +2 -0
  155. package/src/orchestrator/pipeline-manager.js +306 -15
  156. package/src/orchestrator/session-manager.js +331 -6
  157. package/src/tasks/handoff.js +3 -2
  158. package/src/telemetry/config.js +4 -3
  159. package/src/telemetry/schema.js +1 -0
  160. package/src/terminal/collector.js +3 -2
  161. package/src/terminal/index.js +1 -2
  162. package/src/terminal/isolation.js +52 -18
  163. package/src/terminal/prompt-builder.js +42 -25
  164. package/src/terminal/run-parallel.js +1 -1
  165. package/src/terminal/run-team.js +3 -3
  166. package/src/terminal/team-task-list.js +43 -4
  167. package/src/upgrade/backup.js +3 -2
  168. package/src/upgrade/checker.js +3 -2
  169. package/src/upgrade/migrator.js +65 -7
  170. package/src/upgrade/tracked-files-detector.js +86 -0
  171. package/src/upgrade/user-messages.js +94 -0
  172. package/src/utils/config-parser.js +2 -1
  173. package/src/utils/feature-flags.js +2 -1
  174. package/src/utils/flatten-entities.js +69 -0
  175. package/src/utils/framework-dir.js +16 -0
  176. package/src/utils/model-id.js +85 -0
  177. package/src/utils/provider-limits.js +84 -23
  178. package/src/utils/schema-validator.js +1 -1
  179. package/src/wizard/i18n.js +5 -4
  180. package/src/wizard/index.js +14 -0
  181. package/assets/logo - c/303/263pia.png +0 -0
  182. package/assets/logo.svg +0 -42
  183. package/assets/logo2.png +0 -0
  184. package/assets/social-preview.png +0 -0
  185. package/scripts/bundle-framework.js +0 -69
  186. package/scripts/changelog-generator.js +0 -222
  187. package/scripts/codebase-mapper.js +0 -728
  188. package/scripts/commit-message-generator.js +0 -167
  189. package/scripts/coverage-analyzer.js +0 -260
  190. package/scripts/dependency-analyzer.js +0 -280
  191. package/scripts/doctor/checks/agents.js +0 -77
  192. package/scripts/doctor/checks/constitution.js +0 -41
  193. package/scripts/doctor/checks/domain-alignment.js +0 -58
  194. package/scripts/doctor/checks/prism-layers.js +0 -84
  195. package/scripts/doctor/checks/registry.js +0 -55
  196. package/scripts/doctor/checks/schemas.js +0 -61
  197. package/scripts/doctor/fixes/reference-fix.js +0 -100
  198. package/scripts/doctor/fixes/registry-fix.js +0 -56
  199. package/scripts/doctor/index.js +0 -212
  200. package/scripts/framework-analyzer.js +0 -308
  201. package/scripts/generate-constitution-domain.js +0 -253
  202. package/scripts/generate-signing-key.js +0 -33
  203. package/scripts/health-check.js +0 -481
  204. package/scripts/ide-sync.js +0 -326
  205. package/scripts/performance-analyzer.js +0 -325
  206. package/scripts/plan-tracker.js +0 -278
  207. package/scripts/populate-entity-registry.js +0 -481
  208. package/scripts/pr-review.js +0 -317
  209. package/scripts/rollback-manager.js +0 -310
  210. package/scripts/semantic-lint.js +0 -328
  211. package/scripts/sign-manifest.js +0 -53
  212. package/scripts/stuck-detector.js +0 -343
  213. package/scripts/test-quality-assessment.js +0 -257
  214. package/scripts/validate-agents.js +0 -368
  215. package/scripts/validate-package.js +0 -505
  216. package/scripts/validate-tasks.js +0 -465
  217. package/src/autonomy/worktree-manager.js +0 -250
  218. package/src/intelligence/decision-engine.js +0 -256
  219. package/src/intelligence/document-sharder.js +0 -221
  220. package/src/intelligence/elicitation.js +0 -265
@@ -1,481 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Health Check — Comprehensive framework integrity validation.
5
- *
6
- * Exports:
7
- * runHealthCheck(frameworkDir) → HealthReport
8
- * formatHealthReport(report) → human-readable string
9
- *
10
- * HealthReport:
11
- * { overall: 'HEALTHY'|'DEGRADED'|'UNHEALTHY', checks: {...}, timestamp }
12
- *
13
- * Each check:
14
- * { pass: boolean, details: string, severity: 'critical'|'warning'|'info' }
15
- */
16
-
17
- import { readFileSync, existsSync, readdirSync } from 'fs';
18
- import { join } from 'path';
19
- import yaml from 'js-yaml';
20
-
21
- // ---------------------------------------------------------------------------
22
- // Individual checks
23
- // ---------------------------------------------------------------------------
24
-
25
- /**
26
- * Check entity-registry.yaml integrity.
27
- */
28
- function checkRegistry(frameworkDir) {
29
- const regPath = join(frameworkDir, 'data', 'entity-registry.yaml');
30
- if (!existsSync(regPath)) {
31
- return { pass: false, details: 'entity-registry.yaml not found', severity: 'critical' };
32
- }
33
-
34
- try {
35
- const content = readFileSync(regPath, 'utf8');
36
- const registry = yaml.load(content);
37
-
38
- if (!registry || !registry.entities) {
39
- return { pass: false, details: 'entity-registry.yaml has no entities section', severity: 'critical' };
40
- }
41
-
42
- // Count all entities across all categories
43
- let entityCount = 0;
44
- for (const category of Object.values(registry.entities)) {
45
- if (typeof category === 'object' && category !== null) {
46
- entityCount += Object.keys(category).length;
47
- }
48
- }
49
-
50
- const declaredCount = registry.metadata?.entity_count || 0;
51
- if (declaredCount > 0 && entityCount !== declaredCount) {
52
- return {
53
- pass: false,
54
- details: `Entity count mismatch: declared ${declaredCount}, actual ${entityCount}`,
55
- severity: 'warning',
56
- };
57
- }
58
-
59
- return { pass: true, details: `${entityCount} entities registered`, severity: 'info' };
60
- } catch (err) {
61
- return { pass: false, details: `Failed to parse: ${err.message}`, severity: 'critical' };
62
- }
63
- }
64
-
65
- /**
66
- * Check that all schema files exist and are valid JSON.
67
- */
68
- function checkSchemas(frameworkDir) {
69
- const schemasDir = join(frameworkDir, 'schemas');
70
- if (!existsSync(schemasDir)) {
71
- return { pass: false, details: 'schemas/ directory not found', severity: 'critical' };
72
- }
73
-
74
- const expectedSchemas = [
75
- 'session.schema.json',
76
- 'config.schema.json',
77
- 'context.schema.json',
78
- 'memory.schema.json',
79
- 'task.schema.json',
80
- ];
81
-
82
- const missing = [];
83
- const invalid = [];
84
-
85
- for (const schema of expectedSchemas) {
86
- const schemaPath = join(schemasDir, schema);
87
- if (!existsSync(schemaPath)) {
88
- missing.push(schema);
89
- continue;
90
- }
91
- try {
92
- JSON.parse(readFileSync(schemaPath, 'utf8'));
93
- } catch {
94
- invalid.push(schema);
95
- }
96
- }
97
-
98
- if (missing.length > 0 || invalid.length > 0) {
99
- const issues = [];
100
- if (missing.length) issues.push(`missing: ${missing.join(', ')}`);
101
- if (invalid.length) issues.push(`invalid JSON: ${invalid.join(', ')}`);
102
- return {
103
- pass: false,
104
- details: issues.join('; '),
105
- severity: missing.length > 0 ? 'critical' : 'warning',
106
- };
107
- }
108
-
109
- const actualSchemas = readdirSync(schemasDir).filter(f => f.endsWith('.json'));
110
- return { pass: true, details: `${actualSchemas.length} schemas valid`, severity: 'info' };
111
- }
112
-
113
- /**
114
- * Check constitution.md exists and has the expected number of articles.
115
- */
116
- function checkConstitution(frameworkDir) {
117
- const constPath = join(frameworkDir, 'constitution.md');
118
- if (!existsSync(constPath)) {
119
- return { pass: false, details: 'constitution.md not found', severity: 'critical' };
120
- }
121
-
122
- try {
123
- const content = readFileSync(constPath, 'utf8');
124
- const articleMatches = content.match(/^## Article [IVXLCDM]+/gm) || [];
125
- const articleCount = articleMatches.length;
126
-
127
- if (articleCount < 10) {
128
- return {
129
- pass: false,
130
- details: `Only ${articleCount} articles found (expected 10+)`,
131
- severity: 'warning',
132
- };
133
- }
134
-
135
- return { pass: true, details: `${articleCount} articles found`, severity: 'info' };
136
- } catch (err) {
137
- return { pass: false, details: `Failed to read: ${err.message}`, severity: 'critical' };
138
- }
139
- }
140
-
141
- /**
142
- * Check that all primary agent definition files exist with valid structure.
143
- */
144
- function checkAgents(frameworkDir) {
145
- const agentsDir = join(frameworkDir, 'agents');
146
- const orchestratorDir = join(frameworkDir, 'orchestrator');
147
-
148
- const expectedAgents = {
149
- 'discover/greenfield-wu.md': 'greenfield-wu',
150
- 'discover/brownfield-wu.md': 'brownfield-wu',
151
- 'discover/brief.md': 'brief',
152
- 'plan/detail.md': 'detail',
153
- 'plan/architect.md': 'architect',
154
- 'plan/ux.md': 'ux',
155
- 'plan/phases.md': 'phases',
156
- 'plan/tasks.md': 'tasks',
157
- 'quality/qa-planning.md': 'qa-planning',
158
- 'quality/qa-implementation.md': 'qa-implementation',
159
- 'build/dev.md': 'dev',
160
- 'deploy/devops.md': 'devops',
161
- };
162
-
163
- const missing = [];
164
- const invalid = [];
165
-
166
- // Check agent files
167
- for (const [relPath, name] of Object.entries(expectedAgents)) {
168
- const fullPath = join(agentsDir, relPath);
169
- if (!existsSync(fullPath)) {
170
- missing.push(name);
171
- continue;
172
- }
173
- try {
174
- const content = readFileSync(fullPath, 'utf8');
175
- if (!content.includes('## Identity') && !content.includes('## Mission')) {
176
- invalid.push(name);
177
- }
178
- } catch {
179
- invalid.push(name);
180
- }
181
- }
182
-
183
- // Check orchestrator
184
- const orchPath = join(orchestratorDir, 'chati.md');
185
- if (!existsSync(orchPath)) {
186
- missing.push('orchestrator');
187
- }
188
-
189
- const total = Object.keys(expectedAgents).length + 1; // +1 for orchestrator
190
- const found = total - missing.length;
191
-
192
- if (missing.length > 0 || invalid.length > 0) {
193
- const issues = [];
194
- if (missing.length) issues.push(`missing: ${missing.join(', ')}`);
195
- if (invalid.length) issues.push(`invalid: ${invalid.join(', ')}`);
196
- return {
197
- pass: false,
198
- details: `${found}/${total} agents found; ${issues.join('; ')}`,
199
- severity: missing.length > 0 ? 'critical' : 'warning',
200
- };
201
- }
202
-
203
- return { pass: true, details: `${found}/${total} agents present`, severity: 'info' };
204
- }
205
-
206
- /**
207
- * Check that workflow files exist and are valid YAML.
208
- */
209
- function checkWorkflows(frameworkDir) {
210
- const workflowsDir = join(frameworkDir, 'workflows');
211
- if (!existsSync(workflowsDir)) {
212
- return { pass: false, details: 'workflows/ directory not found', severity: 'warning' };
213
- }
214
-
215
- const invalid = [];
216
-
217
- let files;
218
- try {
219
- files = readdirSync(workflowsDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
220
- } catch (err) {
221
- return { pass: false, details: `Cannot read workflows/: ${err.message}`, severity: 'warning' };
222
- }
223
-
224
- const total = files.length;
225
- let valid = 0;
226
-
227
- for (const file of files) {
228
- try {
229
- yaml.load(readFileSync(join(workflowsDir, file), 'utf8'));
230
- valid++;
231
- } catch {
232
- invalid.push(file);
233
- }
234
- }
235
-
236
- if (total === 0) {
237
- return { pass: false, details: 'No workflow files found', severity: 'warning' };
238
- }
239
-
240
- if (invalid.length > 0) {
241
- return { pass: false, details: `${valid}/${total} valid; invalid: ${invalid.join(', ')}`, severity: 'warning' };
242
- }
243
-
244
- return { pass: true, details: `${valid} workflows valid`, severity: 'info' };
245
- }
246
-
247
- /**
248
- * Check templates directory.
249
- */
250
- function checkTemplates(frameworkDir) {
251
- const templatesDir = join(frameworkDir, 'templates');
252
- if (!existsSync(templatesDir)) {
253
- return { pass: false, details: 'templates/ directory not found', severity: 'warning' };
254
- }
255
-
256
- let files;
257
- try {
258
- files = readdirSync(templatesDir).filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
259
- } catch {
260
- return { pass: false, details: 'Cannot read templates/', severity: 'warning' };
261
- }
262
-
263
- const total = files.length;
264
- let valid = 0;
265
-
266
- for (const file of files) {
267
- try {
268
- yaml.load(readFileSync(join(templatesDir, file), 'utf8'));
269
- valid++;
270
- } catch {
271
- // Invalid YAML
272
- }
273
- }
274
-
275
- if (total === 0) {
276
- return { pass: false, details: 'No template files found', severity: 'warning' };
277
- }
278
-
279
- return { pass: valid === total, details: `${valid}/${total} templates valid`, severity: valid < total ? 'warning' : 'info' };
280
- }
281
-
282
- /**
283
- * Check quality gates directory.
284
- */
285
- function checkQualityGates(frameworkDir) {
286
- const gatesDir = join(frameworkDir, 'quality-gates');
287
- if (!existsSync(gatesDir)) {
288
- return { pass: false, details: 'quality-gates/ directory not found', severity: 'warning' };
289
- }
290
-
291
- const expected = ['planning-gate.md', 'implementation-gate.md'];
292
- const missing = expected.filter(f => !existsSync(join(gatesDir, f)));
293
-
294
- if (missing.length > 0) {
295
- return { pass: false, details: `Missing: ${missing.join(', ')}`, severity: 'warning' };
296
- }
297
-
298
- return { pass: true, details: `${expected.length} quality gates present`, severity: 'info' };
299
- }
300
-
301
- /**
302
- * Check config.yaml.
303
- */
304
- function checkConfig(frameworkDir) {
305
- const configPath = join(frameworkDir, 'config.yaml');
306
- if (!existsSync(configPath)) {
307
- return { pass: false, details: 'config.yaml not found', severity: 'critical' };
308
- }
309
-
310
- try {
311
- const content = readFileSync(configPath, 'utf8');
312
- // config.yaml has a markdown header line, extract YAML portion
313
- const lines = content.split('\n');
314
- const yamlLines = lines.filter(l => !l.startsWith('#'));
315
- const config = yaml.load(yamlLines.join('\n'));
316
-
317
- if (!config) {
318
- return { pass: false, details: 'config.yaml is empty', severity: 'critical' };
319
- }
320
-
321
- return { pass: true, details: `version: ${config.version || 'unknown'}`, severity: 'info' };
322
- } catch (err) {
323
- return { pass: false, details: `Failed to parse: ${err.message}`, severity: 'critical' };
324
- }
325
- }
326
-
327
- /**
328
- * Check intelligence directory.
329
- */
330
- function checkIntelligence(frameworkDir) {
331
- const intellDir = join(frameworkDir, 'intelligence');
332
- if (!existsSync(intellDir)) {
333
- return { pass: false, details: 'intelligence/ directory not found', severity: 'warning' };
334
- }
335
-
336
- const expectedFiles = [
337
- 'context-engine.md',
338
- 'memory-layer.md',
339
- 'decision-engine.md',
340
- 'confidence.yaml',
341
- 'patterns.yaml',
342
- 'gotchas.yaml',
343
- ];
344
-
345
- const found = expectedFiles.filter(f => existsSync(join(intellDir, f)));
346
-
347
- if (found.length < expectedFiles.length) {
348
- const missing = expectedFiles.filter(f => !found.includes(f));
349
- return {
350
- pass: false,
351
- details: `${found.length}/${expectedFiles.length} present; missing: ${missing.join(', ')}`,
352
- severity: 'warning',
353
- };
354
- }
355
-
356
- return { pass: true, details: `${found.length} intelligence files present`, severity: 'info' };
357
- }
358
-
359
- // ---------------------------------------------------------------------------
360
- // Public API
361
- // ---------------------------------------------------------------------------
362
-
363
- /**
364
- * Run a comprehensive health check on the framework directory.
365
- * @param {string} frameworkDir - Path to the framework directory (e.g., chati.dev/ or framework/).
366
- * @returns {object} HealthReport.
367
- */
368
- export function runHealthCheck(frameworkDir) {
369
- if (!existsSync(frameworkDir)) {
370
- return {
371
- overall: 'UNHEALTHY',
372
- checks: {
373
- frameworkDir: { pass: false, details: `Directory not found: ${frameworkDir}`, severity: 'critical' },
374
- },
375
- timestamp: new Date().toISOString(),
376
- };
377
- }
378
-
379
- const checks = {
380
- registry: checkRegistry(frameworkDir),
381
- schemas: checkSchemas(frameworkDir),
382
- constitution: checkConstitution(frameworkDir),
383
- agents: checkAgents(frameworkDir),
384
- workflows: checkWorkflows(frameworkDir),
385
- templates: checkTemplates(frameworkDir),
386
- qualityGates: checkQualityGates(frameworkDir),
387
- config: checkConfig(frameworkDir),
388
- intelligence: checkIntelligence(frameworkDir),
389
- };
390
-
391
- // Determine overall health
392
- const criticalFailures = Object.values(checks).filter(c => !c.pass && c.severity === 'critical');
393
- const warnings = Object.values(checks).filter(c => !c.pass && c.severity === 'warning');
394
-
395
- let overall;
396
- if (criticalFailures.length > 0) {
397
- overall = 'UNHEALTHY';
398
- } else if (warnings.length > 0) {
399
- overall = 'DEGRADED';
400
- } else {
401
- overall = 'HEALTHY';
402
- }
403
-
404
- return {
405
- overall,
406
- checks,
407
- timestamp: new Date().toISOString(),
408
- summary: {
409
- total: Object.keys(checks).length,
410
- passed: Object.values(checks).filter(c => c.pass).length,
411
- failed: Object.values(checks).filter(c => !c.pass).length,
412
- criticalFailures: criticalFailures.length,
413
- warnings: warnings.length,
414
- },
415
- };
416
- }
417
-
418
- /**
419
- * Format a HealthReport into a human-readable string.
420
- * @param {object} report - HealthReport from runHealthCheck.
421
- * @returns {string} Formatted report string.
422
- */
423
- export function formatHealthReport(report) {
424
- const statusSymbol = {
425
- HEALTHY: '[OK]',
426
- DEGRADED: '[WARN]',
427
- UNHEALTHY: '[FAIL]',
428
- };
429
-
430
- const checkSymbol = (check) => check.pass ? '[PASS]' : '[FAIL]';
431
-
432
- const lines = [
433
- `=== Health Check Report ===`,
434
- `Status: ${statusSymbol[report.overall] || '[ ? ]'} ${report.overall}`,
435
- `Time: ${report.timestamp}`,
436
- '',
437
- ];
438
-
439
- if (report.summary) {
440
- lines.push(`Summary: ${report.summary.passed}/${report.summary.total} checks passed`);
441
- if (report.summary.criticalFailures > 0) {
442
- lines.push(` ${report.summary.criticalFailures} critical failure(s)`);
443
- }
444
- if (report.summary.warnings > 0) {
445
- lines.push(` ${report.summary.warnings} warning(s)`);
446
- }
447
- lines.push('');
448
- }
449
-
450
- lines.push('Checks:');
451
- for (const [name, check] of Object.entries(report.checks)) {
452
- const symbol = checkSymbol(check);
453
- const severity = check.severity !== 'info' ? ` (${check.severity})` : '';
454
- lines.push(` ${symbol} ${name}: ${check.details}${severity}`);
455
- }
456
-
457
- lines.push('');
458
- lines.push('=== End Report ===');
459
-
460
- return lines.join('\n');
461
- }
462
-
463
- // ---------------------------------------------------------------------------
464
- // CLI entrypoint
465
- // ---------------------------------------------------------------------------
466
-
467
- const isMainModule = process.argv[1] && (
468
- process.argv[1].endsWith('health-check.js') ||
469
- process.argv[1].endsWith('health-check')
470
- );
471
-
472
- if (isMainModule) {
473
- const frameworkDir = process.argv[2] || join(process.cwd(), 'chati.dev');
474
-
475
- const report = runHealthCheck(frameworkDir);
476
- console.log(formatHealthReport(report));
477
-
478
- if (report.overall === 'UNHEALTHY') {
479
- process.exit(1);
480
- }
481
- }