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