chati-dev 4.2.0 → 4.2.1
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/framework/config.yaml +2 -2
- package/framework/constitution.md +2 -1
- package/framework/context/governance.md +24 -1
- package/framework/context/quality.md +14 -1
- package/framework/context/root.md +4 -3
- package/package.json +1 -1
- package/scripts/validate-package.js +110 -0
- package/src/installer/core.js +87 -128
- package/src/installer/templates.js +34 -0
package/framework/config.yaml
CHANGED
|
@@ -755,6 +755,7 @@ If any check is NO, the compliance block itself is an ERROR and the report canno
|
|
|
755
755
|
|
|
756
756
|
---
|
|
757
757
|
|
|
758
|
-
*Chati.dev Constitution v4.2.
|
|
758
|
+
*Chati.dev Constitution v4.2.1 — 22 Articles + Preamble*
|
|
759
759
|
*v4.2.0 Amendments: Article V amended (Team Communication); Article VIII amended (Team Handoff Envelope); Article XII amended (PRISM L6 Team Roster); Article XXI added (Agent Teams Governance); Article XXII added (Fault Vector Protocol)*
|
|
760
|
+
*v4.2.1 Fixes: installer refactor (recursive copy), features block in config, context files sync*
|
|
760
761
|
*All agents are bound by this Constitution. Violations are enforced per article.*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Chati.dev Governance Rules
|
|
2
2
|
|
|
3
|
-
Extracted from `chati.dev/constitution.md` (
|
|
3
|
+
Extracted from `chati.dev/constitution.md` (22 Articles). Read the full constitution for complete rules.
|
|
4
4
|
|
|
5
5
|
## Mode Governance (Article XI)
|
|
6
6
|
- **3 modes**: planning (read all, write chati.dev/ only), build (full access), deploy (full + infra)
|
|
@@ -50,3 +50,26 @@ Extracted from `chati.dev/constitution.md` (19 Articles). Read the full constitu
|
|
|
50
50
|
- Provider selected at install time, auto-configures optimal models per agent
|
|
51
51
|
- Resolution chain: agent_overrides > agent default > primary provider
|
|
52
52
|
- Context files auto-generated for non-Claude providers (GEMINI.md, AGENTS.md)
|
|
53
|
+
|
|
54
|
+
## Anti-Loop Protocol (Article XX)
|
|
55
|
+
- 3-Strike Rule: 3 edits to same file without resolution = STOP
|
|
56
|
+
- Mandatory Diagnosis Mode: read complete file, trace path, root cause in one sentence
|
|
57
|
+
- Paradigm Change required after diagnosis (CSS failed → try JavaScript, etc.)
|
|
58
|
+
- Escalation after 5 total attempts: present honestly, ask for direction
|
|
59
|
+
- Task score capped at 0% for violations
|
|
60
|
+
|
|
61
|
+
## Agent Teams Governance (Article XXI)
|
|
62
|
+
- Feature-flagged (`agent_teams: true` in config.yaml), defaults to OFF
|
|
63
|
+
- 2 canonical teams: Planning Team (Detail+Architect+UX) and Build Team (Dev+QA)
|
|
64
|
+
- Only orchestrator can form/dissolve teams
|
|
65
|
+
- Intra-team communication via Team Mailbox (Article V amendment)
|
|
66
|
+
- Cross-team communication still orchestrator-mediated
|
|
67
|
+
- Team Quality Gate: all tasks complete + scores pass + mailbox clean
|
|
68
|
+
- Max 2 Team Correction Cycles before degraded dissolution
|
|
69
|
+
- Graceful fallback to sequential pipeline when unavailable (Gemini/Codex/flag off)
|
|
70
|
+
|
|
71
|
+
## Fault Vector Protocol (Article XXII)
|
|
72
|
+
- Root Layer Routing: classify fault origin (INTENT/SPEC/CODE/DEFER) before correction
|
|
73
|
+
- Evidence-Bound Verdicts: ERROR findings require tool evidence (lint/typecheck/test/screenshot)
|
|
74
|
+
- Decision Trail: append-only log of known-bad states to prevent cyclical re-introduction
|
|
75
|
+
- Echo Detection: content-similarity matching to detect same defect reappearing across review cycles
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
|-------|--------------|
|
|
6
6
|
| qa-planning | 95% |
|
|
7
7
|
| qa-implementation | 95% |
|
|
8
|
-
|
|
|
8
|
+
| Standard agents | 90% |
|
|
9
|
+
| Discovery agents (WU, brief) | 85% |
|
|
9
10
|
|
|
10
11
|
## Review Range
|
|
11
12
|
Scores within 5 points below threshold trigger REVIEW (human confirmation required even in autonomous mode).
|
|
@@ -26,3 +27,15 @@ Scores within 5 points below threshold trigger REVIEW (human confirmation requir
|
|
|
26
27
|
## Blocker Taxonomy
|
|
27
28
|
- **C01-C15**: Code blockers (technical)
|
|
28
29
|
- **G01-G08**: General blockers (process, communication, dependency)
|
|
30
|
+
|
|
31
|
+
## Fault Vector Protocol (Article XXII)
|
|
32
|
+
- **Root Layer Routing**: INTENT (requirement wrong) -> Brief/Detail | SPEC (spec wrong) -> Architect/Tasks | CODE (implementation wrong) -> Dev | DEFER (out of scope) -> Backlog
|
|
33
|
+
- **Evidence-Bound Verdicts**: ERROR/WARNING require tool evidence. Without evidence -> downgraded to SUGGESTION (non-blocking)
|
|
34
|
+
- **Decision Trail**: Known-bad states logged in session.yaml `decision_trail[]`. Agents read before iterating.
|
|
35
|
+
- **Echo Detection**: Similarity >= 0.85 with prior Decision Trail entry = ECHO. Escalate immediately, no more automated loops.
|
|
36
|
+
- **FVP Compliance Checklist**: Mandatory in every QA correction report
|
|
37
|
+
|
|
38
|
+
## Team Quality Gate (Article XXI)
|
|
39
|
+
- All team tasks complete + all scores pass tier threshold + mailbox clean
|
|
40
|
+
- Max 2 Team Correction Cycles before degraded dissolution
|
|
41
|
+
- Team score = average of member task scores
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Chati.dev System Context
|
|
2
2
|
|
|
3
3
|
## Framework
|
|
4
|
-
- **Version**: 4.1
|
|
4
|
+
- **Version**: 4.2.1
|
|
5
5
|
- **Agents**: Specialized agents across DISCOVER, PLAN, BUILD, DEPLOY phases
|
|
6
|
-
- **Constitution**:
|
|
7
|
-
- **Quality**: 5 pipeline gates + 3-tier verdicts
|
|
6
|
+
- **Constitution**: 22 Articles + Preamble
|
|
7
|
+
- **Quality**: 5 pipeline gates + 3-tier verdicts + Fault Vector Protocol (Article XXII)
|
|
8
|
+
- **Agent Teams**: Native Claude Code teams with peer communication (Article XXI, feature-flagged)
|
|
8
9
|
|
|
9
10
|
## Key References
|
|
10
11
|
- **Session State**: `.chati/session.yaml` (runtime — not committed)
|
package/package.json
CHANGED
|
@@ -166,6 +166,114 @@ function checkBinExists(packageRoot, results) {
|
|
|
166
166
|
}
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Validate that every hook referenced in hooks/settings.json exists on disk.
|
|
171
|
+
* Prevents shipping a bundle where settings.json references a hook file that
|
|
172
|
+
* was never copied.
|
|
173
|
+
*/
|
|
174
|
+
function checkHooksParity(packageRoot, results) {
|
|
175
|
+
results.checks++;
|
|
176
|
+
const settingsPath = join(packageRoot, 'framework', 'hooks', 'settings.json');
|
|
177
|
+
if (!existsSync(settingsPath)) {
|
|
178
|
+
results.warnings.push('framework/hooks/settings.json not found — skipping hooks parity check.');
|
|
179
|
+
results.passed++;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
185
|
+
const missing = new Set();
|
|
186
|
+
const hooksDir = join(packageRoot, 'framework', 'hooks');
|
|
187
|
+
|
|
188
|
+
// Walk all hook events and collect referenced .js files
|
|
189
|
+
for (const event of Object.keys(settings.hooks || {})) {
|
|
190
|
+
for (const matcher of settings.hooks[event] || []) {
|
|
191
|
+
for (const hook of matcher.hooks || []) {
|
|
192
|
+
if (hook.type === 'command' && typeof hook.command === 'string') {
|
|
193
|
+
// command format: "node chati.dev/hooks/foo.js"
|
|
194
|
+
const match = hook.command.match(/hooks\/([^\s]+\.js)/);
|
|
195
|
+
if (match) {
|
|
196
|
+
const hookFile = match[1];
|
|
197
|
+
if (!existsSync(join(hooksDir, hookFile))) {
|
|
198
|
+
missing.add(hookFile);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (missing.size === 0) {
|
|
207
|
+
results.passed++;
|
|
208
|
+
} else {
|
|
209
|
+
results.errors.push(`Hooks referenced in settings.json but missing from framework/hooks/: ${[...missing].join(', ')}`);
|
|
210
|
+
}
|
|
211
|
+
} catch (err) {
|
|
212
|
+
results.errors.push(`Failed to parse hooks/settings.json: ${err.message}`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Parity check: every file in source chati.dev/ (that belongs to a copied
|
|
218
|
+
* directory) must exist in framework/. Catches bundling bugs where new files
|
|
219
|
+
* are added to the source but not included in the bundle.
|
|
220
|
+
*
|
|
221
|
+
* Only runs when the monorepo source is available (skipped inside the
|
|
222
|
+
* published package since the source is not shipped).
|
|
223
|
+
*/
|
|
224
|
+
function checkSourceBundleParity(packageRoot, results) {
|
|
225
|
+
results.checks++;
|
|
226
|
+
const monorepoSource = join(packageRoot, '..', '..', 'chati.dev');
|
|
227
|
+
const bundleDir = join(packageRoot, 'framework');
|
|
228
|
+
|
|
229
|
+
if (!existsSync(monorepoSource)) {
|
|
230
|
+
// Running inside the published package — skip (nothing to compare against)
|
|
231
|
+
results.passed++;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Collect all files in source, grouped by the top-level directory
|
|
236
|
+
const missing = [];
|
|
237
|
+
const COPIED_DIRS = [
|
|
238
|
+
'orchestrator', 'agents', 'templates', 'workflows', 'quality-gates',
|
|
239
|
+
'schemas', 'frameworks', 'intelligence', 'patterns', 'hooks',
|
|
240
|
+
'domains', 'i18n', 'migrations', 'data', 'context', 'tasks', 'presets',
|
|
241
|
+
];
|
|
242
|
+
const COPIED_ROOT_FILES = ['constitution.md'];
|
|
243
|
+
|
|
244
|
+
function walk(srcDir, relBase) {
|
|
245
|
+
if (!existsSync(srcDir)) return;
|
|
246
|
+
for (const entry of readdirSync(srcDir, { withFileTypes: true })) {
|
|
247
|
+
const srcPath = join(srcDir, entry.name);
|
|
248
|
+
const relPath = relBase ? `${relBase}/${entry.name}` : entry.name;
|
|
249
|
+
if (entry.isDirectory()) {
|
|
250
|
+
walk(srcPath, relPath);
|
|
251
|
+
} else if (entry.isFile()) {
|
|
252
|
+
const bundlePath = join(bundleDir, relPath);
|
|
253
|
+
if (!existsSync(bundlePath)) missing.push(relPath);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
for (const file of COPIED_ROOT_FILES) {
|
|
259
|
+
const src = join(monorepoSource, file);
|
|
260
|
+
const bundled = join(bundleDir, file);
|
|
261
|
+
if (existsSync(src) && !existsSync(bundled)) missing.push(file);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
for (const dir of COPIED_DIRS) {
|
|
265
|
+
walk(join(monorepoSource, dir), dir);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (missing.length === 0) {
|
|
269
|
+
results.passed++;
|
|
270
|
+
} else {
|
|
271
|
+
const sample = missing.slice(0, 10).join(', ');
|
|
272
|
+
const more = missing.length > 10 ? ` (+ ${missing.length - 10} more)` : '';
|
|
273
|
+
results.errors.push(`Files in source chati.dev/ missing from framework/ bundle: ${sample}${more}`);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
169
277
|
/**
|
|
170
278
|
* Compare entity count in registry vs actual files in framework/.
|
|
171
279
|
*/
|
|
@@ -216,6 +324,8 @@ export function validatePackage(packageRoot) {
|
|
|
216
324
|
checkExportsResolve(packageRoot, results);
|
|
217
325
|
checkBinExists(packageRoot, results);
|
|
218
326
|
checkEntityCount(packageRoot, results);
|
|
327
|
+
checkHooksParity(packageRoot, results);
|
|
328
|
+
checkSourceBundleParity(packageRoot, results);
|
|
219
329
|
|
|
220
330
|
return results;
|
|
221
331
|
}
|
package/src/installer/core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, copyFileSync, existsSync, readFileSync } from 'fs';
|
|
1
|
+
import { mkdirSync, writeFileSync, copyFileSync, existsSync, readFileSync, readdirSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { IDE_CONFIGS, IDE_TO_PROVIDER } from '../config/ide-configs.js';
|
|
@@ -146,144 +146,103 @@ export async function installFramework(config) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/**
|
|
149
|
-
*
|
|
149
|
+
* Framework directories to copy recursively from source to target.
|
|
150
|
+
* This list controls WHICH top-level directories under chati.dev/ get copied.
|
|
151
|
+
* Everything inside each directory is copied automatically — no need to
|
|
152
|
+
* enumerate individual files.
|
|
153
|
+
*
|
|
154
|
+
* New files added to the source framework are picked up automatically.
|
|
150
155
|
*/
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
'agents/plan/phases.md',
|
|
171
|
-
'agents/plan/tasks.md',
|
|
172
|
-
// Quality agents
|
|
173
|
-
'agents/quality/qa-planning.md',
|
|
174
|
-
'agents/quality/qa-implementation.md',
|
|
175
|
-
// BUILD + DEPLOY agents
|
|
176
|
-
'agents/build/dev.md',
|
|
177
|
-
'agents/deploy/devops.md',
|
|
178
|
-
// Templates
|
|
179
|
-
'templates/prd-tmpl.yaml',
|
|
180
|
-
'templates/brownfield-prd-tmpl.yaml',
|
|
181
|
-
'templates/fullstack-architecture-tmpl.yaml',
|
|
182
|
-
'templates/task-tmpl.yaml',
|
|
183
|
-
'templates/qa-gate-tmpl.yaml',
|
|
184
|
-
'templates/quick-brief-tmpl.yaml',
|
|
185
|
-
'templates/brandbook-tmpl.yaml',
|
|
186
|
-
'templates/brandbook-html-tmpl.md',
|
|
187
|
-
'templates/design-token-tmpl.yaml',
|
|
188
|
-
'templates/component-spec-tmpl.yaml',
|
|
189
|
-
'templates/icon-system-tmpl.yaml',
|
|
190
|
-
'templates/session-memory-tmpl.yaml',
|
|
191
|
-
// Workflows
|
|
192
|
-
'workflows/greenfield-fullstack.yaml',
|
|
193
|
-
'workflows/brownfield-fullstack.yaml',
|
|
194
|
-
'workflows/brownfield-discovery.yaml',
|
|
195
|
-
'workflows/brownfield-service.yaml',
|
|
196
|
-
'workflows/brownfield-ui.yaml',
|
|
197
|
-
'workflows/quick-flow.yaml',
|
|
198
|
-
'workflows/standard-flow.yaml',
|
|
199
|
-
// Quality gates
|
|
200
|
-
'quality-gates/planning-gate.md',
|
|
201
|
-
'quality-gates/implementation-gate.md',
|
|
202
|
-
// Schemas
|
|
203
|
-
'schemas/session.schema.json',
|
|
204
|
-
'schemas/config.schema.json',
|
|
205
|
-
'schemas/task.schema.json',
|
|
206
|
-
'schemas/context.schema.json',
|
|
207
|
-
'schemas/memory.schema.json',
|
|
208
|
-
// Frameworks
|
|
209
|
-
'frameworks/quality-dimensions.yaml',
|
|
210
|
-
'frameworks/decision-heuristics.yaml',
|
|
211
|
-
// Intelligence
|
|
212
|
-
'intelligence/gotchas.yaml',
|
|
213
|
-
'intelligence/patterns.yaml',
|
|
214
|
-
'intelligence/confidence.yaml',
|
|
215
|
-
'intelligence/context-engine.md',
|
|
216
|
-
'intelligence/memory-layer.md',
|
|
217
|
-
'intelligence/decision-engine.md',
|
|
218
|
-
// Patterns
|
|
219
|
-
'patterns/elicitation.md',
|
|
220
|
-
'patterns/elicitation-library.yaml',
|
|
221
|
-
// Hooks
|
|
222
|
-
'hooks/prism-engine.js',
|
|
223
|
-
'hooks/mode-governance.js',
|
|
224
|
-
'hooks/constitution-guard.js',
|
|
225
|
-
'hooks/session-digest.js',
|
|
226
|
-
'hooks/model-governance.js',
|
|
227
|
-
'hooks/settings.json',
|
|
228
|
-
'hooks/read-protection.js',
|
|
229
|
-
// Domains (PRISM Context Engine)
|
|
230
|
-
'domains/constitution.yaml',
|
|
231
|
-
'domains/global.yaml',
|
|
232
|
-
'domains/agents/orchestrator.yaml',
|
|
233
|
-
'domains/agents/greenfield-wu.yaml',
|
|
234
|
-
'domains/agents/brownfield-wu.yaml',
|
|
235
|
-
'domains/agents/brief.yaml',
|
|
236
|
-
'domains/agents/detail.yaml',
|
|
237
|
-
'domains/agents/architect.yaml',
|
|
238
|
-
'domains/agents/ux.yaml',
|
|
239
|
-
'domains/agents/phases.yaml',
|
|
240
|
-
'domains/agents/tasks.yaml',
|
|
241
|
-
'domains/agents/qa-planning.yaml',
|
|
242
|
-
'domains/agents/qa-implementation.yaml',
|
|
243
|
-
'domains/agents/dev.yaml',
|
|
244
|
-
'domains/agents/devops.yaml',
|
|
245
|
-
'domains/workflows/greenfield-fullstack.yaml',
|
|
246
|
-
'domains/workflows/brownfield-fullstack.yaml',
|
|
247
|
-
'domains/workflows/brownfield-discovery.yaml',
|
|
248
|
-
'domains/workflows/brownfield-service.yaml',
|
|
249
|
-
'domains/workflows/brownfield-ui.yaml',
|
|
250
|
-
'domains/workflows/quick-flow.yaml',
|
|
251
|
-
'domains/workflows/standard-flow.yaml',
|
|
252
|
-
// i18n
|
|
253
|
-
'i18n/en.yaml',
|
|
254
|
-
'i18n/pt.yaml',
|
|
255
|
-
'i18n/es.yaml',
|
|
256
|
-
'i18n/fr.yaml',
|
|
257
|
-
// Migrations
|
|
258
|
-
'migrations/v1.0-to-v1.1.yaml',
|
|
259
|
-
// Data
|
|
260
|
-
'data/entity-registry.yaml',
|
|
261
|
-
// Context (@ import chain for CLAUDE.md)
|
|
262
|
-
'context/root.md',
|
|
263
|
-
'context/governance.md',
|
|
264
|
-
'context/protocols.md',
|
|
265
|
-
'context/quality.md',
|
|
266
|
-
];
|
|
267
|
-
|
|
268
|
-
for (const file of filesToCopy) {
|
|
269
|
-
const src = join(FRAMEWORK_SOURCE, file);
|
|
270
|
-
const dest = join(destDir, file);
|
|
156
|
+
const FRAMEWORK_DIRS_TO_COPY = [
|
|
157
|
+
'orchestrator',
|
|
158
|
+
'agents',
|
|
159
|
+
'templates',
|
|
160
|
+
'workflows',
|
|
161
|
+
'quality-gates',
|
|
162
|
+
'schemas',
|
|
163
|
+
'frameworks',
|
|
164
|
+
'intelligence',
|
|
165
|
+
'patterns',
|
|
166
|
+
'hooks',
|
|
167
|
+
'domains',
|
|
168
|
+
'i18n',
|
|
169
|
+
'migrations',
|
|
170
|
+
'data',
|
|
171
|
+
'context',
|
|
172
|
+
'tasks',
|
|
173
|
+
'presets',
|
|
174
|
+
];
|
|
271
175
|
|
|
272
|
-
|
|
273
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Loose files at the root of chati.dev/ that get copied directly.
|
|
178
|
+
*/
|
|
179
|
+
const FRAMEWORK_ROOT_FILES = [
|
|
180
|
+
'constitution.md',
|
|
181
|
+
];
|
|
274
182
|
|
|
275
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Recursively copy a directory from source to destination, applying provider
|
|
185
|
+
* adaptation for files listed in ADAPTABLE_FILES when the provider is not Claude.
|
|
186
|
+
*/
|
|
187
|
+
function copyDirRecursive(srcDir, destDir, provider, relBase = '') {
|
|
188
|
+
if (!existsSync(srcDir)) return;
|
|
189
|
+
createDir(destDir);
|
|
190
|
+
|
|
191
|
+
const entries = readdirSync(srcDir, { withFileTypes: true });
|
|
192
|
+
for (const entry of entries) {
|
|
193
|
+
const srcPath = join(srcDir, entry.name);
|
|
194
|
+
const destPath = join(destDir, entry.name);
|
|
195
|
+
const relPath = relBase ? join(relBase, entry.name) : entry.name;
|
|
196
|
+
|
|
197
|
+
if (entry.isDirectory()) {
|
|
198
|
+
copyDirRecursive(srcPath, destPath, provider, relPath);
|
|
199
|
+
} else if (entry.isFile()) {
|
|
200
|
+
if (provider !== 'claude' && ADAPTABLE_FILES.has(relPath)) {
|
|
276
201
|
// Non-Claude provider: read, adapt, write
|
|
277
|
-
const content = readFileSync(
|
|
278
|
-
writeFileSync(
|
|
202
|
+
const content = readFileSync(srcPath, 'utf-8');
|
|
203
|
+
writeFileSync(destPath, adaptFrameworkFile(content, relPath, provider), 'utf-8');
|
|
279
204
|
} else {
|
|
280
205
|
// Claude or non-adaptable: direct copy
|
|
281
|
-
copyFileSync(
|
|
206
|
+
copyFileSync(srcPath, destPath);
|
|
282
207
|
}
|
|
283
208
|
}
|
|
284
209
|
}
|
|
285
210
|
}
|
|
286
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Copy framework files from the Chati.dev source directory.
|
|
214
|
+
*
|
|
215
|
+
* Uses recursive directory copy instead of a hardcoded file list, so that
|
|
216
|
+
* new files added to the framework source are automatically picked up.
|
|
217
|
+
*
|
|
218
|
+
* @param {string} destDir - Target framework directory (e.g., {project}/chati.dev/)
|
|
219
|
+
* @param {string} provider - Primary provider for text adaptation ('claude' | 'gemini' | 'codex')
|
|
220
|
+
*/
|
|
221
|
+
export function copyFrameworkFiles(destDir, provider = 'claude') {
|
|
222
|
+
if (!existsSync(FRAMEWORK_SOURCE)) return;
|
|
223
|
+
|
|
224
|
+
// Copy loose root files
|
|
225
|
+
for (const file of FRAMEWORK_ROOT_FILES) {
|
|
226
|
+
const src = join(FRAMEWORK_SOURCE, file);
|
|
227
|
+
if (!existsSync(src)) continue;
|
|
228
|
+
const dest = join(destDir, file);
|
|
229
|
+
createDir(dirname(dest));
|
|
230
|
+
if (provider !== 'claude' && ADAPTABLE_FILES.has(file)) {
|
|
231
|
+
const content = readFileSync(src, 'utf-8');
|
|
232
|
+
writeFileSync(dest, adaptFrameworkFile(content, file, provider), 'utf-8');
|
|
233
|
+
} else {
|
|
234
|
+
copyFileSync(src, dest);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Copy each framework directory recursively
|
|
239
|
+
for (const dir of FRAMEWORK_DIRS_TO_COPY) {
|
|
240
|
+
const srcDir = join(FRAMEWORK_SOURCE, dir);
|
|
241
|
+
const destSubDir = join(destDir, dir);
|
|
242
|
+
copyDirRecursive(srcDir, destSubDir, provider, dir);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
287
246
|
/**
|
|
288
247
|
* Configure a specific IDE
|
|
289
248
|
*/
|
|
@@ -108,6 +108,40 @@ export function generateConfigYaml(config) {
|
|
|
108
108
|
},
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
+
// Feature flags (Intelligence Upgrade + Article XXI Agent Teams)
|
|
112
|
+
// Must match source chati.dev/config.yaml features block.
|
|
113
|
+
configData.features = {
|
|
114
|
+
hybrid_budget: true,
|
|
115
|
+
anti_dash: true,
|
|
116
|
+
rate_limiter_integration: true,
|
|
117
|
+
l5_keywords: true,
|
|
118
|
+
prompt_size_guard: true,
|
|
119
|
+
ids_decision_engine: true,
|
|
120
|
+
surface_criteria: true,
|
|
121
|
+
parallel_fallback: true,
|
|
122
|
+
tool_mesh: true,
|
|
123
|
+
tech_presets: true,
|
|
124
|
+
doctor_autofix: true,
|
|
125
|
+
brandbook: true,
|
|
126
|
+
// Intelligence Upgrade (v4.0.5 — Claude Code patterns)
|
|
127
|
+
undercover_mode: true,
|
|
128
|
+
memory_extraction: true,
|
|
129
|
+
memory_consolidation: true,
|
|
130
|
+
daily_digest: true,
|
|
131
|
+
structured_session_memory: true,
|
|
132
|
+
static_prism_boundary: true,
|
|
133
|
+
token_bracket_estimation: true,
|
|
134
|
+
model_fallback: true,
|
|
135
|
+
frustration_detection: true,
|
|
136
|
+
bash_security_checks: true,
|
|
137
|
+
// Agent Teams (v4.2.0 — Article XXI)
|
|
138
|
+
agent_teams: false,
|
|
139
|
+
team_planning_size: 3,
|
|
140
|
+
team_build_size: 2,
|
|
141
|
+
team_echo_threshold: 0.92,
|
|
142
|
+
team_correction_cycles_max: 2,
|
|
143
|
+
};
|
|
144
|
+
|
|
111
145
|
// Add telemetry config
|
|
112
146
|
configData.telemetry = {
|
|
113
147
|
enabled: config.telemetryEnabled !== false,
|