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.
Files changed (222) 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 +8 -7
  23. package/framework/constitution.md +127 -43
  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 +91 -36
  35. package/framework/hooks/license-guard.js +129 -190
  36. package/framework/hooks/mode-governance.js +68 -16
  37. package/framework/hooks/model-governance.js +19 -8
  38. package/framework/hooks/package.json +3 -0
  39. package/framework/hooks/post-dev.js +207 -0
  40. package/framework/hooks/prism-engine.js +288 -105
  41. package/framework/hooks/read-protection.js +37 -9
  42. package/framework/hooks/reasoning-escalator.js +371 -0
  43. package/framework/hooks/reference-trigger.js +117 -0
  44. package/framework/hooks/session-digest.js +94 -20
  45. package/framework/hooks/settings.json +32 -1
  46. package/framework/hooks/style-guard.js +52 -13
  47. package/framework/hooks/team-quality-gate.js +58 -25
  48. package/framework/hooks/undercover-guard.js +34 -13
  49. package/framework/i18n/en.yaml +3 -3
  50. package/framework/i18n/es.yaml +3 -3
  51. package/framework/i18n/fr.yaml +3 -3
  52. package/framework/i18n/pt.yaml +3 -3
  53. package/framework/intelligence/context-engine.md +4 -5
  54. package/framework/intelligence/decision-engine.md +1 -1
  55. package/framework/intelligence/hooks-performance.md +3 -3
  56. package/framework/migrations/v1.0-to-v1.1.yaml +1 -1
  57. package/framework/migrations/v1.4-to-v2.0.yaml +11 -11
  58. package/framework/migrations/v4.0-to-v4.1.yaml +2 -2
  59. package/framework/migrations/v4.2-to-v4.3.yaml +29 -0
  60. package/framework/orchestrator/chati-router.js +387 -0
  61. package/framework/orchestrator/chati-update.md +40 -40
  62. package/framework/orchestrator/chati.md +318 -115
  63. package/framework/scaffold/motion-premium/README.md +89 -0
  64. package/framework/scaffold/motion-premium/app/globals.css.template +400 -0
  65. package/framework/scaffold/motion-premium/app/layout.tsx.template +110 -0
  66. package/framework/scaffold/motion-premium/components/animation/BackgroundCrossfadeProvider.tsx.template +170 -0
  67. package/framework/scaffold/motion-premium/components/animation/LenisProvider.tsx.template +49 -0
  68. package/framework/scaffold/motion-premium/components/animation/PageTransitionWrapper.tsx.template +83 -0
  69. package/framework/scaffold/motion-premium/components/animation/Preloader.tsx.template +171 -0
  70. package/framework/scaffold/motion-premium/components/ui/Container.tsx.template +69 -0
  71. package/framework/scaffold/motion-premium/components/ui/PageSection.tsx.template +74 -0
  72. package/framework/scaffold/motion-premium/lib/animations/gsap.ts.template +112 -0
  73. package/framework/scaffold/motion-premium/lib/animations/refreshCoordinator.ts.template +75 -0
  74. package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +119 -0
  75. package/framework/scaffold/motion-premium/lib/animations/useGsapContext.ts.template +92 -0
  76. package/framework/scaffold/motion-premium/lib/animations/useScrollSnapStepper.ts.template +265 -0
  77. package/framework/scaffold/motion-premium/lib/animations/useSmoothScroll.ts.template +67 -0
  78. package/framework/scaffold/motion-premium/lib/brand.ts.template +43 -0
  79. package/framework/scaffold/motion-premium/scaffold.yaml +174 -0
  80. package/framework/scaffold/motion-premium-3d/README.md +80 -0
  81. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoCanvas.tsx.template +81 -0
  82. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/ScrollDemoClient.tsx.template +75 -0
  83. package/framework/scaffold/motion-premium-3d/app/(3d)/scroll-demo/page.tsx.template +26 -0
  84. package/framework/scaffold/motion-premium-3d/components/3d/CameraRig.tsx.template +100 -0
  85. package/framework/scaffold/motion-premium-3d/components/3d/CanvasProvider.tsx.template +85 -0
  86. package/framework/scaffold/motion-premium-3d/components/3d/InvalidateOnScroll.tsx.template +51 -0
  87. package/framework/scaffold/motion-premium-3d/components/3d/MeshCrossfade.tsx.template +79 -0
  88. package/framework/scaffold/motion-premium-3d/components/3d/ScrollCrossfade.tsx.template +88 -0
  89. package/framework/scaffold/motion-premium-3d/components/3d/ScrollScene.tsx.template +121 -0
  90. package/framework/scaffold/motion-premium-3d/components/webgl/SceneFallback.tsx.template +65 -0
  91. package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +68 -0
  92. package/framework/scaffold/motion-premium-3d/lib/webgl/detect.ts.template +69 -0
  93. package/framework/scaffold/motion-premium-3d/scaffold.yaml +133 -0
  94. package/framework/schemas/session.schema.json +109 -21
  95. package/framework/scripts/reference-capture.js +430 -0
  96. package/framework/scripts/visual-qa.js +674 -0
  97. package/framework/tasks/orchestrator-handoff.md +1 -1
  98. package/framework/tasks/orchestrator-resume.md +1 -1
  99. package/framework/tasks/orchestrator-route.md +1 -1
  100. package/framework/tasks/orchestrator-status.md +3 -3
  101. package/framework/tasks/qa-planning-gate-define.md +1 -1
  102. package/framework/templates/brandbook-html-tmpl.md +1 -1
  103. package/framework/templates/brandbook-tmpl.yaml +1 -1
  104. package/framework/templates/component-spec-tmpl.yaml +1 -1
  105. package/framework/templates/design-token-tmpl.yaml +1 -1
  106. package/framework/templates/icon-system-tmpl.yaml +1 -1
  107. package/framework/templates/team-planning-tasks.yaml +6 -5
  108. package/framework/workflows/brownfield-discovery.yaml +2 -2
  109. package/framework/workflows/brownfield-fullstack.yaml +15 -11
  110. package/framework/workflows/brownfield-service.yaml +14 -10
  111. package/framework/workflows/brownfield-ui.yaml +15 -11
  112. package/framework/workflows/greenfield-fullstack.yaml +16 -13
  113. package/framework/workflows/quick-flow.yaml +3 -3
  114. package/framework/workflows/standard-flow.yaml +12 -9
  115. package/package.json +10 -5
  116. package/src/autonomy/autonomous-gate.js +1 -0
  117. package/src/autonomy/build-state.js +1 -2
  118. package/src/autonomy/progress-reporter.js +1 -1
  119. package/src/config/agent-customizer.js +11 -3
  120. package/src/config/claude-settings-generator.js +226 -0
  121. package/src/config/context-file-generator.js +41 -21
  122. package/src/config/framework-adapter.js +1 -0
  123. package/src/config/gemini-hooks-generator.js +76 -6
  124. package/src/config/mcp-configs.js +1 -0
  125. package/src/context/layers/l1-global.js +2 -1
  126. package/src/dashboard/data-reader.js +4 -3
  127. package/src/dashboard/layout.js +2 -1
  128. package/src/decision/analyzer.js +6 -30
  129. package/src/decision/engine.js +4 -28
  130. package/src/decision/registry-healer.js +3 -2
  131. package/src/decision/registry-updater.js +23 -14
  132. package/src/extensions/loader.js +2 -8
  133. package/src/gates/g1-planning-complete.js +2 -1
  134. package/src/gates/g2-qa-planning.js +2 -1
  135. package/src/gates/g3-implementation.js +2 -1
  136. package/src/gates/g4-qa-implementation.js +3 -2
  137. package/src/gates/g5-deploy-ready.js +2 -1
  138. package/src/health/engine.js +4 -3
  139. package/src/installer/core.js +557 -81
  140. package/src/installer/preflight.js +131 -0
  141. package/src/installer/provider-overlay.js +3 -3
  142. package/src/installer/scaffold-applier.js +358 -0
  143. package/src/installer/templates.js +52 -31
  144. package/src/installer/validator.js +17 -12
  145. package/src/intelligence/registry-manager.js +22 -29
  146. package/src/intelligence/timeline.js +11 -6
  147. package/src/license/commands.js +1 -1
  148. package/src/license/wait.js +102 -0
  149. package/src/memory/agent-memory.js +81 -0
  150. package/src/memory/dream.js +32 -1
  151. package/src/merger/replace-merger.js +28 -15
  152. package/src/orchestrator/agent-selector.js +2 -1
  153. package/src/orchestrator/cli.js +1908 -80
  154. package/src/orchestrator/doctor.js +270 -0
  155. package/src/orchestrator/handoff-engine.js +4 -3
  156. package/src/orchestrator/index.js +2 -0
  157. package/src/orchestrator/pipeline-manager.js +306 -15
  158. package/src/orchestrator/session-manager.js +331 -6
  159. package/src/tasks/handoff.js +3 -2
  160. package/src/telemetry/config.js +4 -3
  161. package/src/telemetry/schema.js +1 -0
  162. package/src/terminal/collector.js +3 -2
  163. package/src/terminal/index.js +1 -2
  164. package/src/terminal/isolation.js +52 -18
  165. package/src/terminal/prompt-builder.js +42 -25
  166. package/src/terminal/run-parallel.js +1 -1
  167. package/src/terminal/run-team.js +3 -3
  168. package/src/terminal/team-task-list.js +43 -4
  169. package/src/upgrade/backup.js +3 -2
  170. package/src/upgrade/checker.js +3 -2
  171. package/src/upgrade/migrator.js +65 -7
  172. package/src/upgrade/tracked-files-detector.js +86 -0
  173. package/src/upgrade/user-messages.js +94 -0
  174. package/src/utils/config-parser.js +2 -1
  175. package/src/utils/feature-flags.js +2 -1
  176. package/src/utils/flatten-entities.js +69 -0
  177. package/src/utils/framework-dir.js +16 -0
  178. package/src/utils/model-id.js +85 -0
  179. package/src/utils/provider-limits.js +84 -23
  180. package/src/utils/schema-validator.js +1 -1
  181. package/src/wizard/i18n.js +5 -4
  182. package/src/wizard/index.js +14 -0
  183. package/assets/logo - c/303/263pia.png +0 -0
  184. package/assets/logo.svg +0 -42
  185. package/assets/logo2.png +0 -0
  186. package/assets/social-preview.png +0 -0
  187. package/scripts/bundle-framework.js +0 -69
  188. package/scripts/changelog-generator.js +0 -222
  189. package/scripts/codebase-mapper.js +0 -728
  190. package/scripts/commit-message-generator.js +0 -167
  191. package/scripts/coverage-analyzer.js +0 -260
  192. package/scripts/dependency-analyzer.js +0 -280
  193. package/scripts/doctor/checks/agents.js +0 -77
  194. package/scripts/doctor/checks/constitution.js +0 -41
  195. package/scripts/doctor/checks/domain-alignment.js +0 -58
  196. package/scripts/doctor/checks/prism-layers.js +0 -84
  197. package/scripts/doctor/checks/registry.js +0 -55
  198. package/scripts/doctor/checks/schemas.js +0 -61
  199. package/scripts/doctor/fixes/reference-fix.js +0 -100
  200. package/scripts/doctor/fixes/registry-fix.js +0 -56
  201. package/scripts/doctor/index.js +0 -212
  202. package/scripts/framework-analyzer.js +0 -308
  203. package/scripts/generate-constitution-domain.js +0 -253
  204. package/scripts/generate-signing-key.js +0 -33
  205. package/scripts/health-check.js +0 -481
  206. package/scripts/ide-sync.js +0 -326
  207. package/scripts/performance-analyzer.js +0 -325
  208. package/scripts/plan-tracker.js +0 -278
  209. package/scripts/populate-entity-registry.js +0 -481
  210. package/scripts/pr-review.js +0 -317
  211. package/scripts/rollback-manager.js +0 -310
  212. package/scripts/semantic-lint.js +0 -328
  213. package/scripts/sign-manifest.js +0 -53
  214. package/scripts/stuck-detector.js +0 -343
  215. package/scripts/test-quality-assessment.js +0 -257
  216. package/scripts/validate-agents.js +0 -368
  217. package/scripts/validate-package.js +0 -367
  218. package/scripts/validate-tasks.js +0 -465
  219. package/src/autonomy/worktree-manager.js +0 -250
  220. package/src/intelligence/decision-engine.js +0 -256
  221. package/src/intelligence/document-sharder.js +0 -221
  222. package/src/intelligence/elicitation.js +0 -265
@@ -8,6 +8,8 @@
8
8
  import { readFileSync, existsSync } from 'fs';
9
9
  import { join } from 'path';
10
10
  import yaml from 'js-yaml';
11
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
12
+ import { flattenEntitiesFromRegistry } from '../utils/flatten-entities.js';
11
13
 
12
14
  /**
13
15
  * Analyze impact of changing an entity.
@@ -38,12 +40,12 @@ export function analyzeImpact(projectDir, entityPath) {
38
40
  }
39
41
 
40
42
  // Load entity details
41
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
43
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
42
44
  const registry = existsSync(registryPath)
43
45
  ? yaml.load(readFileSync(registryPath, 'utf8'))
44
46
  : { entities: {} };
45
47
 
46
- const allEntities = flattenEntities(registry);
48
+ const allEntities = flattenEntitiesFromRegistry(registry);
47
49
  const entityMap = new Map(allEntities.map(e => [e.path, e]));
48
50
 
49
51
  const affectedEntities = affectedPaths.map(path => {
@@ -68,7 +70,7 @@ export function analyzeImpact(projectDir, entityPath) {
68
70
  * @returns {Map<string, string[]>} Map of entityPath -> [dependentPaths]
69
71
  */
70
72
  export function buildDependencyGraph(projectDir) {
71
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
73
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
72
74
  const graph = new Map();
73
75
 
74
76
  if (!existsSync(registryPath)) {
@@ -76,7 +78,7 @@ export function buildDependencyGraph(projectDir) {
76
78
  }
77
79
 
78
80
  const registry = yaml.load(readFileSync(registryPath, 'utf8'));
79
- const entities = flattenEntities(registry);
81
+ const entities = flattenEntitiesFromRegistry(registry);
80
82
 
81
83
  // Initialize graph with all entities
82
84
  entities.forEach(entity => {
@@ -287,29 +289,3 @@ function tokenize(text) {
287
289
  .filter(w => w.length > 2 && !stopwords.has(w));
288
290
  }
289
291
 
290
- /**
291
- * Flatten entity registry into array of entities.
292
- * @private
293
- * @param {object} registry
294
- * @returns {object[]}
295
- */
296
- function flattenEntities(registry) {
297
- const entities = [];
298
-
299
- if (!registry.entities) {
300
- return entities;
301
- }
302
-
303
- Object.entries(registry.entities).forEach(([type, typeEntities]) => {
304
- if (Array.isArray(typeEntities)) {
305
- typeEntities.forEach(entity => {
306
- entities.push({
307
- ...entity,
308
- type
309
- });
310
- });
311
- }
312
- });
313
-
314
- return entities;
315
- }
@@ -12,6 +12,8 @@
12
12
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';
13
13
  import { join } from 'path';
14
14
  import yaml from 'js-yaml';
15
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
16
+ import { flattenEntitiesFromRegistry } from '../utils/flatten-entities.js';
15
17
 
16
18
  /**
17
19
  * Analyze a request against existing entities and recommend action.
@@ -22,7 +24,7 @@ import yaml from 'js-yaml';
22
24
  * @returns {{ recommendation: 'REUSE'|'ADAPT'|'CREATE', score: number, matches: object[], reasoning: string }}
23
25
  */
24
26
  export function analyzeRequest(projectDir, request) {
25
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
27
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
26
28
 
27
29
  if (!existsSync(registryPath)) {
28
30
  return {
@@ -34,7 +36,7 @@ export function analyzeRequest(projectDir, request) {
34
36
  }
35
37
 
36
38
  const registry = yaml.load(readFileSync(registryPath, 'utf8'));
37
- const entities = flattenEntities(registry);
39
+ const entities = flattenEntitiesFromRegistry(registry);
38
40
 
39
41
  // Calculate similarity scores for all entities
40
42
  const scoredMatches = entities
@@ -246,29 +248,3 @@ export function getEngineStats(projectDir) {
246
248
  return stats;
247
249
  }
248
250
 
249
- /**
250
- * Flatten entity registry into array of entities.
251
- * @private
252
- * @param {object} registry
253
- * @returns {object[]}
254
- */
255
- function flattenEntities(registry) {
256
- const entities = [];
257
-
258
- if (!registry.entities) {
259
- return entities;
260
- }
261
-
262
- Object.entries(registry.entities).forEach(([type, typeEntities]) => {
263
- if (Array.isArray(typeEntities)) {
264
- typeEntities.forEach(entity => {
265
- entities.push({
266
- ...entity,
267
- type
268
- });
269
- });
270
- }
271
- });
272
-
273
- return entities;
274
- }
@@ -8,6 +8,7 @@
8
8
  import { readFileSync, writeFileSync, existsSync, statSync, copyFileSync, mkdirSync } from 'fs';
9
9
  import { join, isAbsolute } from 'path';
10
10
  import yaml from 'js-yaml';
11
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
11
12
  import { detectNewEntities, detectRemovedEntities, generateEntityMeta } from './registry-updater.js';
12
13
 
13
14
  /**
@@ -16,7 +17,7 @@ import { detectNewEntities, detectRemovedEntities, generateEntityMeta } from './
16
17
  * @returns {{ registry: object|null, registryPath: string }}
17
18
  */
18
19
  function loadRegistry(projectDir) {
19
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
20
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
20
21
  if (!existsSync(registryPath)) {
21
22
  return { registry: null, registryPath };
22
23
  }
@@ -347,7 +348,7 @@ export function detectCountMismatch(projectDir, preloaded) {
347
348
  * @returns {{ applied: number, backup: string }}
348
349
  */
349
350
  export function applyFixes(projectDir, fixes) {
350
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
351
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
351
352
 
352
353
  if (!existsSync(registryPath)) {
353
354
  return { applied: 0, backup: null };
@@ -8,17 +8,26 @@
8
8
  import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'fs';
9
9
  import { join, basename, relative } from 'path';
10
10
  import yaml from 'js-yaml';
11
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
11
12
 
12
- // Known directories to scan
13
- const KNOWN_DIRS = [
14
- { path: 'chati.dev/agents', type: 'agent' },
15
- { path: 'chati.dev/tasks', type: 'task' },
16
- { path: 'chati.dev/schemas', type: 'schema' },
17
- { path: 'chati.dev/domains', type: 'domain' },
18
- { path: 'chati.dev/hooks', type: 'hook' },
19
- { path: 'chati.dev/workflows', type: 'workflow' },
20
- { path: 'chati.dev/templates', type: 'template' }
21
- ];
13
+ /**
14
+ * Build KNOWN_DIRS using resolveFrameworkDir so paths are correct
15
+ * for both chati.dev/ and .chati.dev/ installations.
16
+ * @param {string} projectDir
17
+ * @returns {{ path: string, type: string }[]}
18
+ */
19
+ function buildKnownDirs(projectDir) {
20
+ const fw = resolveFrameworkDir(projectDir);
21
+ return [
22
+ { path: `${fw}/agents`, type: 'agent' },
23
+ { path: `${fw}/tasks`, type: 'task' },
24
+ { path: `${fw}/schemas`, type: 'schema' },
25
+ { path: `${fw}/domains`, type: 'domain' },
26
+ { path: `${fw}/hooks`, type: 'hook' },
27
+ { path: `${fw}/workflows`, type: 'workflow' },
28
+ { path: `${fw}/templates`, type: 'template' },
29
+ ];
30
+ }
22
31
 
23
32
  /**
24
33
  * Scan project for new/changed files and update registry.
@@ -28,7 +37,7 @@ const KNOWN_DIRS = [
28
37
  */
29
38
  export function updateRegistry(projectDir, options = {}) {
30
39
  const { dryRun = false } = options;
31
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
40
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
32
41
 
33
42
  let registry = {
34
43
  metadata: {
@@ -157,7 +166,7 @@ export function updateRegistry(projectDir, options = {}) {
157
166
  * @returns {object[]} New entity candidates
158
167
  */
159
168
  export function detectNewEntities(projectDir) {
160
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
169
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
161
170
  const existingPaths = new Set();
162
171
 
163
172
  if (existsSync(registryPath)) {
@@ -175,7 +184,7 @@ export function detectNewEntities(projectDir) {
175
184
 
176
185
  const newEntities = [];
177
186
 
178
- KNOWN_DIRS.forEach(({ path: dirPath, type }) => {
187
+ buildKnownDirs(projectDir).forEach(({ path: dirPath, type }) => {
179
188
  const fullPath = join(projectDir, dirPath);
180
189
  if (!existsSync(fullPath)) {
181
190
  return;
@@ -204,7 +213,7 @@ export function detectNewEntities(projectDir) {
204
213
  * @returns {object[]} Removed entity candidates
205
214
  */
206
215
  export function detectRemovedEntities(projectDir) {
207
- const registryPath = join(projectDir, 'chati.dev', 'entity-registry.yaml');
216
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'entity-registry.yaml');
208
217
  if (!existsSync(registryPath)) {
209
218
  return [];
210
219
  }
@@ -11,13 +11,7 @@
11
11
  import { existsSync, readdirSync } from 'fs';
12
12
  import { join, extname, basename } from 'path';
13
13
  import { registerExtension, EXTENSION_POINTS } from './registry.js';
14
-
15
- // ---------------------------------------------------------------------------
16
- // Constants
17
- // ---------------------------------------------------------------------------
18
-
19
- /** Directory relative to project root where extensions are stored. */
20
- const EXTENSIONS_DIR = 'chati.dev/extensions';
14
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
21
15
 
22
16
  /** Required fields in an extension module's default export. */
23
17
  const REQUIRED_FIELDS = ['name', 'point', 'handler'];
@@ -79,7 +73,7 @@ export function discoverExtensions(projectDir) {
79
73
  return { files: [], dir: '' };
80
74
  }
81
75
 
82
- const extDir = join(projectDir, EXTENSIONS_DIR);
76
+ const extDir = join(projectDir, resolveFrameworkDir(projectDir), 'extensions');
83
77
 
84
78
  if (!existsSync(extDir)) {
85
79
  return { files: [], dir: extDir };
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { existsSync, readdirSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
10
11
  import { GateBase } from './gate-base.js';
11
12
  import { loadSession } from '../orchestrator/session-manager.js';
12
13
  import { loadHandoff } from '../tasks/handoff.js';
@@ -37,7 +38,7 @@ export class PlanningCompleteGate extends GateBase {
37
38
  * @returns {object} Evidence about artifact presence, session state, and handoff
38
39
  */
39
40
  _collectEvidence(projectDir) {
40
- const artifactsBase = join(projectDir, 'chati.dev', 'artifacts');
41
+ const artifactsBase = join(projectDir, resolveFrameworkDir(projectDir), 'artifacts');
41
42
  const evidence = {
42
43
  artifacts: {},
43
44
  sessionState: null,
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { existsSync, readdirSync } from 'node:fs';
9
9
  import { join } from 'node:path';
10
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
10
11
  import { GateBase, determineVerdict } from './gate-base.js';
11
12
  import { loadSession } from '../orchestrator/session-manager.js';
12
13
  import { loadHandoff } from '../tasks/handoff.js';
@@ -28,7 +29,7 @@ export class QAPlanningGate extends GateBase {
28
29
  * @returns {object} Evidence about test strategy, coverage plan, risk assessment
29
30
  */
30
31
  _collectEvidence(projectDir) {
31
- const artifactsBase = join(projectDir, 'chati.dev', 'artifacts');
32
+ const artifactsBase = join(projectDir, resolveFrameworkDir(projectDir), 'artifacts');
32
33
  const evidence = {
33
34
  testStrategy: false,
34
35
  coveragePlan: false,
@@ -8,6 +8,7 @@
8
8
 
9
9
  import { existsSync, readdirSync, readFileSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
11
12
  import { GateBase } from './gate-base.js';
12
13
  import { loadSession } from '../orchestrator/session-manager.js';
13
14
  import { loadHandoff } from '../tasks/handoff.js';
@@ -97,7 +98,7 @@ export class ImplementationGate extends GateBase {
97
98
  // Check for security scan results
98
99
  const securityPaths = [
99
100
  join(projectDir, '.security-scan'),
100
- join(projectDir, 'chati.dev', 'artifacts', 'security-report.md'),
101
+ join(projectDir, resolveFrameworkDir(projectDir), 'artifacts', 'security-report.md'),
101
102
  ];
102
103
  for (const secPath of securityPaths) {
103
104
  if (existsSync(secPath)) {
@@ -14,6 +14,7 @@
14
14
 
15
15
  import { existsSync, readFileSync } from 'node:fs';
16
16
  import { join } from 'node:path';
17
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
17
18
  import { GateBase, determineVerdict } from './gate-base.js';
18
19
  import { loadSession } from '../orchestrator/session-manager.js';
19
20
  import { loadHandoff } from '../tasks/handoff.js';
@@ -71,7 +72,7 @@ export class QAImplementationGate extends GateBase {
71
72
 
72
73
  // Check for performance benchmark results — parse content for real findings
73
74
  const perfPaths = [
74
- join(projectDir, 'chati.dev', 'artifacts', 'performance-report.md'),
75
+ join(projectDir, resolveFrameworkDir(projectDir), 'artifacts', 'performance-report.md'),
75
76
  join(projectDir, '.performance-benchmark'),
76
77
  ];
77
78
  for (const perfPath of perfPaths) {
@@ -96,7 +97,7 @@ export class QAImplementationGate extends GateBase {
96
97
 
97
98
  // Check for security scan — parse content for real findings
98
99
  const secPaths = [
99
- join(projectDir, 'chati.dev', 'artifacts', 'security-report.md'),
100
+ join(projectDir, resolveFrameworkDir(projectDir), 'artifacts', 'security-report.md'),
100
101
  join(projectDir, '.security-scan'),
101
102
  ];
102
103
  for (const secPath of secPaths) {
@@ -11,6 +11,7 @@ import { join } from 'node:path';
11
11
  import { GateBase } from './gate-base.js';
12
12
  import { loadSession } from '../orchestrator/session-manager.js';
13
13
  import { loadHandoff } from '../tasks/handoff.js';
14
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
14
15
 
15
16
  export class DeployReadyGate extends GateBase {
16
17
  constructor() {
@@ -75,7 +76,7 @@ export class DeployReadyGate extends GateBase {
75
76
  // Check release notes
76
77
  const releaseNotePaths = [
77
78
  join(projectDir, 'RELEASE.md'),
78
- join(projectDir, 'chati.dev', 'artifacts', 'release-notes.md'),
79
+ join(projectDir, resolveFrameworkDir(projectDir), 'artifacts', 'release-notes.md'),
79
80
  ];
80
81
  for (const rnPath of releaseNotePaths) {
81
82
  if (existsSync(rnPath)) {
@@ -9,6 +9,7 @@
9
9
  import { existsSync, readFileSync } from 'fs';
10
10
  import { join } from 'path';
11
11
  import { isCommandAvailable, parseProviderConfig } from '../utils/config-parser.js';
12
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
12
13
 
13
14
  // ---------------------------------------------------------------------------
14
15
  // Check Result Types
@@ -45,7 +46,7 @@ import { isCommandAvailable, parseProviderConfig } from '../utils/config-parser.
45
46
  */
46
47
  export async function checkCliAvailability(projectDir) {
47
48
  const start = Date.now();
48
- const configPath = join(projectDir, 'chati.dev', 'config.yaml');
49
+ const configPath = join(projectDir, resolveFrameworkDir(projectDir), 'config.yaml');
49
50
 
50
51
  if (!existsSync(configPath)) {
51
52
  return { name: 'cli-availability', status: 'warn', message: 'No config.yaml found', duration: Date.now() - start };
@@ -76,7 +77,7 @@ export async function checkCliAvailability(projectDir) {
76
77
  */
77
78
  export async function checkFrameworkIntegrity(projectDir) {
78
79
  const start = Date.now();
79
- const registryPath = join(projectDir, 'chati.dev', 'data', 'entity-registry.yaml');
80
+ const registryPath = join(projectDir, resolveFrameworkDir(projectDir), 'data', 'entity-registry.yaml');
80
81
 
81
82
  if (!existsSync(registryPath)) {
82
83
  return { name: 'framework-integrity', status: 'warn', message: 'No entity registry found', duration: Date.now() - start };
@@ -133,7 +134,7 @@ export async function checkSessionState(projectDir) {
133
134
  */
134
135
  export async function checkHooksHealth(projectDir) {
135
136
  const start = Date.now();
136
- const hooksDir = join(projectDir, 'chati.dev', 'hooks');
137
+ const hooksDir = join(projectDir, resolveFrameworkDir(projectDir), 'hooks');
137
138
 
138
139
  if (!existsSync(hooksDir)) {
139
140
  return { name: 'hooks-health', status: 'fail', message: 'Hooks directory not found', duration: Date.now() - start };