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
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @fileoverview Shared entity-flattening utilities.
3
+ *
4
+ * Two variants exist because the registry YAML stores entities in two different
5
+ * shapes depending on who reads it:
6
+ *
7
+ * - flattenEntitiesFromRegistry: receives the full registry object
8
+ * (i.e. the result of yaml.load()), where each category's value is an Array.
9
+ * Used by decision/analyzer.js and decision/engine.js.
10
+ *
11
+ * - flattenEntitiesMap: receives only the `registry.entities` map,
12
+ * where each category's value is a nested object keyed by entity name.
13
+ * Used by intelligence/registry-manager.js.
14
+ *
15
+ * Keep both functions here so there is a single canonical implementation.
16
+ */
17
+
18
+ /**
19
+ * Flatten a full entity registry (as returned by yaml.load) into a flat array.
20
+ *
21
+ * Each category value must be an Array of entity objects.
22
+ * The `type` field is inferred from the category key.
23
+ *
24
+ * @param {object} registry - Full registry object with a top-level `entities` key.
25
+ * @returns {object[]} Flat array of entity objects, each with a `type` field added.
26
+ */
27
+ export function flattenEntitiesFromRegistry(registry) {
28
+ const entities = [];
29
+
30
+ if (!registry || !registry.entities) {
31
+ return entities;
32
+ }
33
+
34
+ Object.entries(registry.entities).forEach(([type, typeEntities]) => {
35
+ if (Array.isArray(typeEntities)) {
36
+ typeEntities.forEach(entity => {
37
+ entities.push({ ...entity, type });
38
+ });
39
+ }
40
+ });
41
+
42
+ return entities;
43
+ }
44
+
45
+ /**
46
+ * Flatten the `entities` section of the registry (a nested object map) into a flat array.
47
+ *
48
+ * Each category value is an object keyed by entity name, where the value is the entity.
49
+ * Only entities with a `path` property are included.
50
+ *
51
+ * @param {object|null|undefined} entities - The `registry.entities` map.
52
+ * @returns {object[]} Flat array of entity objects, each with a `name` field added.
53
+ */
54
+ export function flattenEntitiesMap(entities) {
55
+ if (!entities) return [];
56
+ const flat = [];
57
+
58
+ for (const [, items] of Object.entries(entities)) {
59
+ if (typeof items === 'object' && items !== null) {
60
+ for (const [name, entity] of Object.entries(items)) {
61
+ if (entity && entity.path) {
62
+ flat.push({ name, ...entity });
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ return flat;
69
+ }
@@ -0,0 +1,16 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+
4
+ /**
5
+ * Resolve the framework directory for a given project.
6
+ * Supports both new (.chati.dev/) and legacy (chati.dev/) structures.
7
+ * New structure (v4.2.3+) uses hidden dot prefix.
8
+ *
9
+ * @param {string} projectDir - Project root directory
10
+ * @returns {string} Framework directory name ('.chati.dev' or 'chati.dev')
11
+ */
12
+ export function resolveFrameworkDir(projectDir) {
13
+ const newPath = join(projectDir, '.chati.dev');
14
+ if (existsSync(newPath)) return '.chati.dev';
15
+ return 'chati.dev'; // Legacy fallback
16
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * @fileoverview Claude model-id parser — single point of truth.
3
+ *
4
+ * Consumers everywhere (provider-limits, prism-engine, status handler,
5
+ * session boot) call parseClaudeModelId() to convert ANY Claude model
6
+ * string into a stable `family[variant]` key. Without this unification,
7
+ * we end up with drift — prism-engine.js historically hard-coded its own
8
+ * variant-blind map, which is how Opus 1M users got false DEPLETED
9
+ * alerts at 10% context used.
10
+ *
11
+ * Canonical output key format: `<family>` or `<family>[<variant>]`
12
+ * opus, opus[1m], sonnet, sonnet[1m], haiku
13
+ *
14
+ * Input tolerance:
15
+ * - full id: claude-opus-4-7, claude-opus-4-7[1m], claude-haiku-4-5-20251001
16
+ * - dated id: claude-3-5-sonnet-20241022
17
+ * - bare family: opus, sonnet, haiku
18
+ * - variant syntax: [1m], (1m), :1m (all equivalent)
19
+ * - case: any case, output is lowercase
20
+ * - whitespace: trimmed
21
+ *
22
+ * Returns `null` (not throws) for anything the parser cannot identify as
23
+ * a known Claude family — downstream code treats `null` as "unknown,
24
+ * fall through to provider/agent defaults".
25
+ */
26
+
27
+ const FAMILIES = new Set(['opus', 'sonnet', 'haiku']);
28
+
29
+ /**
30
+ * @typedef {object} ParsedModelId
31
+ * @property {'opus'|'sonnet'|'haiku'} family
32
+ * @property {'default'|'1m'|string} variant
33
+ * @property {string} normalized - e.g. 'opus', 'opus[1m]'
34
+ * @property {'claude'} provider
35
+ */
36
+
37
+ /**
38
+ * Parse a Claude model id (from env var, hook event, transcript, config)
39
+ * into its canonical `family[variant]` shape.
40
+ *
41
+ * @param {string} raw
42
+ * @returns {ParsedModelId | null}
43
+ */
44
+ export function parseClaudeModelId(raw) {
45
+ if (typeof raw !== 'string') return null;
46
+
47
+ const s = raw.trim().toLowerCase();
48
+ if (!s) return null;
49
+
50
+ // 1) Extract variant hint if present. Accept [1m], (1m), :1m — settle on [].
51
+ let variant = 'default';
52
+ let body = s;
53
+ const variantMatch = body.match(/[[(:]\s*(1m)\s*\)?\]?$/);
54
+ if (variantMatch) {
55
+ variant = variantMatch[1]; // '1m'
56
+ body = body.slice(0, variantMatch.index).trim();
57
+ }
58
+
59
+ // 2) Find the family token. In canonical ids it appears between dashes;
60
+ // a bare family ('opus', 'sonnet', 'haiku') is also accepted.
61
+ let family = null;
62
+ for (const candidate of FAMILIES) {
63
+ // Word-boundary match so 'opus' in 'opuschatter' does not falsely match.
64
+ const re = new RegExp(`(^|-)${candidate}(-|$)`);
65
+ if (re.test(body)) {
66
+ family = candidate;
67
+ break;
68
+ }
69
+ }
70
+ if (!family) return null;
71
+
72
+ const normalized = variant === 'default' ? family : `${family}[${variant}]`;
73
+
74
+ return { family, variant, normalized, provider: 'claude' };
75
+ }
76
+
77
+ /**
78
+ * Convenience: return just the normalized string (or null).
79
+ * @param {string} raw
80
+ * @returns {string | null}
81
+ */
82
+ export function normalizeModelId(raw) {
83
+ const parsed = parseClaudeModelId(raw);
84
+ return parsed ? parsed.normalized : null;
85
+ }
@@ -1,44 +1,105 @@
1
1
  /**
2
2
  * @fileoverview Canonical context window limits by provider and model.
3
3
  *
4
- * Single source of truth for token limits used by
5
- * bracket-tracker, context-status, prompt-builder, and prism-engine hook.
4
+ * Single source of truth for token limits used by bracket-tracker,
5
+ * context-status, prompt-builder, and the prism-engine hook.
6
6
  *
7
- * SYNC: chati.dev/hooks/prism-engine.js has an inline copy of MODEL_LIMITS.
8
- * If you update here, update there too.
7
+ * The table itself lives in `chati.dev/data/model-limits.json` (canonical)
8
+ * and mirrors into `packages/chati-dev/framework/data/model-limits.json`
9
+ * at sync time. This module loads the JSON at import time via a resolution
10
+ * chain (bundled > monorepo > in-tree). Scan check #25 asserts the exports
11
+ * here equal the JSON to catch any drift between consumers.
9
12
  */
10
13
 
14
+ import { readFileSync, existsSync } from 'fs';
15
+ import { join, dirname } from 'path';
16
+ import { fileURLToPath } from 'url';
17
+ import { parseClaudeModelId } from './model-id.js';
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+
21
+ // Resolution chain for model-limits.json:
22
+ // 1. Bundled with the package: {pkgRoot}/framework/data/model-limits.json
23
+ // 2. Monorepo canonical (dev): {repoRoot}/chati.dev/data/model-limits.json
24
+ const CANDIDATE_PATHS = [
25
+ join(__dirname, '..', '..', 'framework', 'data', 'model-limits.json'),
26
+ join(__dirname, '..', '..', '..', '..', 'chati.dev', 'data', 'model-limits.json'),
27
+ ];
28
+
29
+ function loadLimits() {
30
+ for (const candidate of CANDIDATE_PATHS) {
31
+ if (existsSync(candidate)) {
32
+ return JSON.parse(readFileSync(candidate, 'utf-8'));
33
+ }
34
+ }
35
+ // Last-resort embedded fallback — matches model-limits.json verbatim.
36
+ // Scan check #25 asserts parity between this block and the JSON so drift
37
+ // is caught at CI time. Any active install has the JSON present; this
38
+ // branch exists so unit tests that run the module without sync still work.
39
+ // 2026-04-18 (context-window-auto-detect-v2): opus family is 1M by default.
40
+ return {
41
+ providers: { claude: 1_000_000, gemini: 1_000_000, codex: 128_000 },
42
+ models: {
43
+ opus: 1_000_000,
44
+ 'opus[1m]': 1_000_000,
45
+ sonnet: 1_000_000,
46
+ 'sonnet[1m]': 1_000_000,
47
+ haiku: 200_000,
48
+ pro: 1_000_000,
49
+ flash: 1_000_000,
50
+ codex: 128_000,
51
+ },
52
+ };
53
+ }
54
+
55
+ const _data = loadLimits();
56
+
11
57
  /** Provider context window limits (tokens) — fallback when model unknown. */
12
- export const PROVIDER_LIMITS = {
13
- claude: 200_000,
14
- gemini: 1_000_000,
15
- codex: 128_000,
16
- };
58
+ export const PROVIDER_LIMITS = Object.freeze({ ...(_data.providers || {}) });
17
59
 
18
60
  /**
19
61
  * Model-specific context window limits (tokens).
20
62
  * Takes precedence over PROVIDER_LIMITS when model tier is known.
63
+ * Keys are the `normalized` output of parseClaudeModelId() — e.g.
64
+ * "opus", "opus[1m]", "sonnet", "haiku" — plus bare provider models
65
+ * ("pro", "flash", "codex") for other CLIs.
21
66
  */
22
- export const MODEL_LIMITS = {
23
- // Claude models
24
- opus: 1_000_000,
25
- sonnet: 200_000,
26
- haiku: 200_000,
27
- // Gemini models
28
- pro: 1_000_000,
29
- flash: 1_000_000,
30
- // Codex models
31
- codex: 128_000,
32
- };
67
+ export const MODEL_LIMITS = Object.freeze({ ...(_data.models || {}) });
33
68
 
34
69
  /**
35
70
  * Resolve context window limit: model-specific > provider fallback > default.
36
- * @param {string} [model] - Model tier (opus, sonnet, haiku, pro, flash, codex)
71
+ *
72
+ * The model lookup tries (in order):
73
+ * 1. Exact key match (e.g. "opus[1m]", "sonnet")
74
+ * 2. Normalized via parseClaudeModelId (handles "claude-opus-4-7[1m]" input)
75
+ * 3. Bare family without variant (e.g. "opus[1m]" → "opus")
76
+ * Then falls through to PROVIDER_LIMITS[provider], then 200_000.
77
+ *
78
+ * @param {string} [model] - Normalized key OR raw Claude id
37
79
  * @param {string} [provider] - Provider name (claude, gemini, codex)
38
80
  * @returns {number} Context window limit in tokens
39
81
  */
40
82
  export function resolveContextLimit(model, provider) {
41
- if (model && MODEL_LIMITS[model]) return MODEL_LIMITS[model];
42
- if (provider && PROVIDER_LIMITS[provider]) return PROVIDER_LIMITS[provider];
83
+ if (model) {
84
+ // 1. Exact match on the already-normalized key.
85
+ if (MODEL_LIMITS[model] != null) return MODEL_LIMITS[model];
86
+
87
+ // 2. Try parseClaudeModelId to normalize a raw Claude id.
88
+ const parsed = parseClaudeModelId(model);
89
+ if (parsed && MODEL_LIMITS[parsed.normalized] != null) {
90
+ return MODEL_LIMITS[parsed.normalized];
91
+ }
92
+
93
+ // 3. Bare family fallback (variant unknown → family default).
94
+ if (parsed && MODEL_LIMITS[parsed.family] != null) {
95
+ return MODEL_LIMITS[parsed.family];
96
+ }
97
+ }
98
+ if (provider && PROVIDER_LIMITS[provider] != null) return PROVIDER_LIMITS[provider];
99
+ // Final fallback when model + provider are both unknown. 2026-04-18: kept at
100
+ // 200K as the SAFEST value — an unknown model might be Haiku or an older
101
+ // Sonnet variant. When the model IS identified, the map above returns the
102
+ // correct (often 1M) value. This fallback only fires on genuinely-unknown
103
+ // inputs.
43
104
  return 200_000;
44
105
  }
@@ -172,7 +172,7 @@ export const SESSION_SCHEMA = {
172
172
  pipeline_phase: { type: 'string', enum: ['discover', 'plan', 'build', 'deploy', 'completed'] },
173
173
  current_agent: { type: 'string' },
174
174
  governance_mode: { type: 'string', enum: ['planning', 'build', 'deploy'] },
175
- execution_profile: { type: 'string', enum: ['explore', 'guided', 'autonomous'] },
175
+ execution_mode: { type: 'string', enum: ['interactive', 'autonomous'] },
176
176
  context_bracket: { type: 'string', enum: ['FRESH', 'MODERATE', 'DEPLETED', 'CRITICAL'] },
177
177
  },
178
178
  };
@@ -2,6 +2,7 @@ import { readFileSync, existsSync } from 'fs';
2
2
  import { join, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import yaml from 'js-yaml';
5
+ import { resolveFrameworkDir } from '../utils/framework-dir.js';
5
6
 
6
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
7
8
 
@@ -38,7 +39,7 @@ const FALLBACK_EN = {
38
39
  agents_count: 'Specialized agent definitions across DISCOVER, PLAN, BUILD, DEPLOY phases',
39
40
  workflows_count: '6 workflow blueprints',
40
41
  templates_count: '6 templates (PRD, Brownfield PRD, Architecture, Task, QA Gate, Quick Brief)',
41
- constitution: 'Constitution (19 Articles + Preamble)',
42
+ constitution: 'Constitution (23 Articles + Preamble)',
42
43
  session_mgmt: 'Session management system',
43
44
  quality_gates: 'Quality gates (3-tier verdicts)',
44
45
  proceed: 'Proceed with installation?',
@@ -46,7 +47,7 @@ const FALLBACK_EN = {
46
47
  created_chati: 'Created .chati/ session directory',
47
48
  created_framework: 'Created chati.dev/ system directory (agents, templates, workflows)',
48
49
  created_commands: 'Created .claude/commands/ (thin router)',
49
- installed_constitution: 'Installed Constitution (Articles I-XIX)',
50
+ installed_constitution: 'Installed Constitution (Articles I-XXIII)',
50
51
  created_session: 'Created session.yaml schema',
51
52
  created_claude_md: 'Created CLAUDE.md',
52
53
  configured_mcps: 'Configured MCPs:',
@@ -54,7 +55,7 @@ const FALLBACK_EN = {
54
55
  agents_valid: 'All agents implement 8 protocols',
55
56
  handoff_ok: 'Handoff protocol: OK',
56
57
  validation_ok: 'Self-validation criteria: OK',
57
- constitution_ok: 'Constitution: 19 articles verified',
58
+ constitution_ok: 'Constitution: 23 articles verified',
58
59
  created_memories: 'Created .chati/memories/ (Memory Layer)',
59
60
  installed_intelligence: 'Installed Intelligence Layer (Context Engine, Memory, Registry)',
60
61
  intelligence_valid: 'Intelligence: 6 spec files verified',
@@ -126,7 +127,7 @@ export function loadLanguage(lang, targetDir = null) {
126
127
 
127
128
  // Try to load from installed project i18n
128
129
  const paths = [
129
- targetDir && join(targetDir, 'chati.dev', 'i18n', `${lang}.yaml`),
130
+ targetDir && join(targetDir, resolveFrameworkDir(targetDir), 'i18n', `${lang}.yaml`),
130
131
  join(__dirname, '..', '..', 'assets', 'i18n', `${lang}.yaml`),
131
132
  ].filter(Boolean);
132
133
 
@@ -38,6 +38,20 @@ export async function runWizard(targetDir, options = {}) {
38
38
 
39
39
  await runLicenseActivationStep();
40
40
 
41
+ // Preflight: validate system prerequisites (Node >= 20, npm, Git, Playwright)
42
+ const { runPreflightCheck } = await import('../installer/preflight.js');
43
+ const preflight = await runPreflightCheck();
44
+ const preflightFmt = preflight.checks.map(c => {
45
+ const icon = c.status === 'pass' ? '✓' : c.status === 'warn' ? '⚠' : '✗';
46
+ return ` ${icon} ${c.message}`;
47
+ }).join('\n');
48
+ if (!preflight.passed) {
49
+ p.log.error(`System prerequisites not met:\n${preflightFmt}`);
50
+ p.cancel('Fix the issues above and try again.');
51
+ process.exit(1);
52
+ }
53
+ p.log.success(`System check:\n${preflightFmt}`);
54
+
41
55
  // Step 2: Language Selection
42
56
  const language = options.language || await stepLanguage();
43
57
 
Binary file
package/assets/logo.svg DELETED
@@ -1,42 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 620 200">
2
- <defs>
3
- <clipPath id="c">
4
- <path d="M100,8 C155,8 190,40 190,90 C190,140 155,172 100,172 C82,172 66,167 52,159 L22,192 L34,155 C18,140 10,118 10,90 C10,40 45,8 100,8 Z"/>
5
- </clipPath>
6
- <radialGradient id="g" cx="38%" cy="30%" r="68%">
7
- <stop offset="0%" stop-color="#8EC5F5"/>
8
- <stop offset="40%" stop-color="#5DA2E2"/>
9
- <stop offset="75%" stop-color="#4A90D9"/>
10
- <stop offset="100%" stop-color="#2D6BAF"/>
11
- </radialGradient>
12
- <linearGradient id="r" x1="0" y1="0" x2="0" y2="1">
13
- <stop offset="0%" stop-color="rgba(255,255,255,0.5)"/>
14
- <stop offset="30%" stop-color="rgba(255,255,255,0.15)"/>
15
- <stop offset="100%" stop-color="rgba(0,0,0,0)"/>
16
- </linearGradient>
17
- <linearGradient id="bs" x1="0" y1="0" x2="0" y2="1">
18
- <stop offset="0%" stop-color="rgba(0,0,0,0)"/>
19
- <stop offset="65%" stop-color="rgba(0,0,0,0)"/>
20
- <stop offset="100%" stop-color="rgba(15,30,60,0.25)"/>
21
- </linearGradient>
22
- </defs>
23
-
24
- <!-- Chat bubble -->
25
- <path d="M100,8 C155,8 190,40 190,90 C190,140 155,172 100,172 C82,172 66,167 52,159 L22,192 L34,155 C18,140 10,118 10,90 C10,40 45,8 100,8 Z" fill="url(#g)"/>
26
- <ellipse cx="82" cy="38" rx="52" ry="25" fill="rgba(255,255,255,0.18)" clip-path="url(#c)"/>
27
- <path d="M100,8 C155,8 190,40 190,90 C190,140 155,172 100,172 C82,172 66,167 52,159 L22,192 L34,155 C18,140 10,118 10,90 C10,40 45,8 100,8 Z" fill="url(#bs)" clip-path="url(#c)"/>
28
- <path d="M100,8 C155,8 190,40 190,90 C190,140 155,172 100,172 C82,172 66,167 52,159 L22,192 L34,155 C18,140 10,118 10,90 C10,40 45,8 100,8 Z" fill="none" stroke="url(#r)" stroke-width="1.5"/>
29
-
30
- <!-- Eyes -->
31
- <ellipse cx="72" cy="95" rx="18" ry="20" fill="#1a1a2e"/>
32
- <ellipse cx="128" cy="95" rx="18" ry="20" fill="#1a1a2e"/>
33
- <ellipse cx="65" cy="86" rx="7" ry="5" fill="rgba(255,255,255,0.55)"/>
34
- <ellipse cx="121" cy="86" rx="7" ry="5" fill="rgba(255,255,255,0.55)"/>
35
- <ellipse cx="77" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
36
- <ellipse cx="133" cy="100" rx="3.5" ry="2.5" fill="rgba(255,255,255,0.3)"/>
37
-
38
- <!-- "Chati.dev" text inline -->
39
- <text x="210" y="122" font-family="ui-monospace,'SF Mono','Menlo','Consolas','Liberation Mono',monospace" font-weight="700" font-size="68" letter-spacing="-1">
40
- <tspan fill="#e6edf3">Chati</tspan><tspan fill="#4A90D9">.</tspan><tspan fill="#e6edf3">dev</tspan>
41
- </text>
42
- </svg>
package/assets/logo2.png DELETED
Binary file
Binary file
@@ -1,69 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Bundle framework files into the npm package.
5
- * Run before `npm publish` — copies chati.dev/ source files
6
- * into packages/chati-dev/framework/ so they ship with the package.
7
- */
8
-
9
- import { cpSync, mkdirSync, rmSync, 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 PACKAGE_ROOT = join(__dirname, '..');
15
- const MONOREPO_ROOT = join(PACKAGE_ROOT, '..', '..');
16
- const SOURCE = join(MONOREPO_ROOT, 'chati.dev');
17
- const DEST = join(PACKAGE_ROOT, 'framework');
18
-
19
- if (!existsSync(SOURCE)) {
20
- console.error('Error: chati.dev/ source directory not found at:', SOURCE);
21
- process.exit(1);
22
- }
23
-
24
- // Clean previous bundle
25
- if (existsSync(DEST)) {
26
- rmSync(DEST, { recursive: true });
27
- }
28
-
29
- // Copy framework files
30
- console.log('Bundling framework files...');
31
- mkdirSync(DEST, { recursive: true });
32
-
33
- const dirs = [
34
- 'orchestrator',
35
- 'agents/discover', 'agents/plan', 'agents/quality', 'agents/build', 'agents/deploy',
36
- 'templates', 'workflows', 'quality-gates',
37
- 'schemas', 'frameworks', 'intelligence', 'patterns',
38
- 'hooks', 'domains',
39
- 'i18n', 'migrations', 'data',
40
- 'tasks', 'context', 'presets',
41
- ];
42
-
43
- for (const dir of dirs) {
44
- const src = join(SOURCE, dir);
45
- if (existsSync(src)) {
46
- cpSync(src, join(DEST, dir), { recursive: true });
47
- }
48
- }
49
-
50
- // Copy root files
51
- const rootFiles = ['constitution.md', 'config.yaml'];
52
- for (const file of rootFiles) {
53
- const src = join(SOURCE, file);
54
- if (existsSync(src)) {
55
- cpSync(src, join(DEST, file));
56
- }
57
- }
58
-
59
- console.log('Framework bundled to:', DEST);
60
-
61
- // Copy README from monorepo root so npm displays it
62
- const readmeSrc = join(MONOREPO_ROOT, 'README.md');
63
- const readmeDest = join(PACKAGE_ROOT, 'README.md');
64
- if (existsSync(readmeSrc)) {
65
- cpSync(readmeSrc, readmeDest);
66
- console.log('README.md copied to package.');
67
- }
68
-
69
- console.log('Done.');