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.
@@ -1,8 +1,8 @@
1
1
  # chati.dev Configuration
2
- version: "4.2.0"
2
+ version: "4.2.1"
3
3
  installed_at: "2026-02-07T10:00:00Z"
4
4
  updated_at: "2026-04-11T00:00:00Z"
5
- installer_version: "4.2.0"
5
+ installer_version: "4.2.1"
6
6
  project_type: greenfield
7
7
  language: en
8
8
  ides: [claude-code]
@@ -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.0 — 22 Articles + Preamble*
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` (19 Articles). Read the full constitution for complete rules.
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
- | All others | 90% |
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.6
4
+ - **Version**: 4.2.1
5
5
  - **Agents**: Specialized agents across DISCOVER, PLAN, BUILD, DEPLOY phases
6
- - **Constitution**: 19 Articles + Preamble
7
- - **Quality**: 5 pipeline gates + 3-tier verdicts (APPROVED / NEEDS_REVISION / BLOCKED)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chati-dev",
3
- "version": "4.2.0",
3
+ "version": "4.2.1",
4
4
  "description": "AI-Powered Multi-Agent Orchestration System — Structured vibe coding for Full Stack Development",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
  }
@@ -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
- * Copy framework files from the Chati.dev source directory
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
- export function copyFrameworkFiles(destDir, provider = 'claude') {
152
- if (!existsSync(FRAMEWORK_SOURCE)) return;
153
-
154
- const filesToCopy = [
155
- 'constitution.md',
156
- 'orchestrator/chati.md',
157
- // DISCOVER agents
158
- 'agents/discover/greenfield-wu.md',
159
- 'agents/discover/brownfield-wu.md',
160
- 'agents/discover/brief.md',
161
- // PLAN agents
162
- 'agents/plan/detail.md',
163
- 'agents/plan/architect.md',
164
- 'agents/plan/architect-system.md',
165
- 'agents/plan/architect-data-engineer.md',
166
- 'agents/plan/ux.md',
167
- 'agents/plan/ux-brand-architect.md',
168
- 'agents/plan/ux-researcher.md',
169
- 'agents/plan/ux-component-engineer.md',
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
- if (existsSync(src)) {
273
- createDir(dirname(dest));
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
- if (provider !== 'claude' && ADAPTABLE_FILES.has(file)) {
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(src, 'utf-8');
278
- writeFileSync(dest, adaptFrameworkFile(content, file, provider), 'utf-8');
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(src, dest);
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,