chati-dev 3.3.1 → 4.0.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 +4 -4
- package/TERMS_OF_USE.md +56 -0
- package/framework/config.yaml +23 -3
- package/framework/constitution.md +12 -10
- package/framework/context/governance.md +2 -0
- package/framework/context/root.md +1 -1
- package/framework/intelligence/context-engine.md +22 -17
- package/package.json +3 -2
- package/scripts/doctor/checks/agents.js +77 -0
- package/scripts/doctor/checks/constitution.js +41 -0
- package/scripts/doctor/checks/domain-alignment.js +58 -0
- package/scripts/doctor/checks/prism-layers.js +84 -0
- package/scripts/doctor/checks/registry.js +55 -0
- package/scripts/doctor/checks/schemas.js +61 -0
- package/scripts/doctor/fixes/reference-fix.js +100 -0
- package/scripts/doctor/fixes/registry-fix.js +56 -0
- package/scripts/doctor/index.js +212 -0
- package/scripts/health-check.js +8 -8
- package/src/autonomy/surface-criteria.js +226 -0
- package/src/context/bracket-tracker.js +44 -13
- package/src/context/domain-loader.js +22 -0
- package/src/context/engine.js +18 -7
- package/src/context/formatter.js +21 -1
- package/src/context/layers/l5-keywords.js +53 -0
- package/src/installer/templates.js +1 -1
- package/src/intelligence/context-status.js +20 -9
- package/src/intelligence/decision-engine.js +253 -0
- package/src/orchestrator/pipeline-manager.js +80 -9
- package/src/telemetry/config.js +1 -1
- package/src/telemetry/index.js +1 -1
- package/src/telemetry/schema.js +60 -11
- package/src/terminal/prompt-builder.js +341 -1
- package/src/terminal/run-agent.js +61 -1
- package/src/terminal/run-parallel.js +77 -5
- package/src/terminal/spawner.js +13 -0
- package/src/utils/feature-flags.js +106 -0
- package/src/wizard/i18n.js +8 -3
- package/src/wizard/index.js +35 -9
- package/src/wizard/questions.js +19 -10
package/README.md
CHANGED
|
@@ -266,7 +266,7 @@ Three systems operate transparently behind the pipeline:
|
|
|
266
266
|
|
|
267
267
|
| System | What it does |
|
|
268
268
|
|--------|-------------|
|
|
269
|
-
| **Context Engine (PRISM)** | Injects the right context at the right time.
|
|
269
|
+
| **Context Engine (PRISM)** | Injects the right context at the right time. 6 layers of context (from constitution rules down to keyword-matched domain rules). Uses Progressive Reinforcement: as context degrades, injection budgets INCREASE (1.5% to 5.0% of provider context window). Provider-aware for Claude (200K), Gemini (1M), and Codex (128K). |
|
|
270
270
|
| **Memory System (RECALL)** | Remembers decisions, gotchas, and lessons across sessions. Organized into 4 sectors: what happened (episodic), what we know (semantic), how we do things (procedural), and what we learned (reflective). |
|
|
271
271
|
| **Decision Engine (COMPASS)** | Before creating something new, checks if a similar component already exists. Decides whether to reuse, adapt, or create from scratch. Keeps a registry of all project entities. |
|
|
272
272
|
|
|
@@ -390,8 +390,8 @@ your-project/
|
|
|
390
390
|
│ │ ├── quality/ # QA-Planning, QA-Implementation
|
|
391
391
|
│ │ ├── build/ # Dev
|
|
392
392
|
│ │ └── deploy/ # DevOps
|
|
393
|
-
│ ├── workflows/ #
|
|
394
|
-
│ ├── templates/ #
|
|
393
|
+
│ ├── workflows/ # 7 workflow blueprints
|
|
394
|
+
│ ├── templates/ # 10 artifact templates
|
|
395
395
|
│ ├── schemas/ # 5 JSON schemas
|
|
396
396
|
│ ├── intelligence/ # PRISM, RECALL, COMPASS specs
|
|
397
397
|
│ ├── domains/ # Per-agent and per-workflow configs
|
|
@@ -454,5 +454,5 @@ For security concerns, see our [Security Policy](.github/SECURITY.md).
|
|
|
454
454
|
|
|
455
455
|
<p align="center">
|
|
456
456
|
<sub>Built with structure, validated by agents, governed by constitution.</sub><br>
|
|
457
|
-
<sub>Chati.dev © 2026</sub>
|
|
457
|
+
<sub>Chati.dev v4.0 "Pegasus" © 2026</sub>
|
|
458
458
|
</p>
|
package/TERMS_OF_USE.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Chati.dev Terms of Use
|
|
2
|
+
|
|
3
|
+
Last updated: 2026-03-03
|
|
4
|
+
|
|
5
|
+
## 1. Acceptance
|
|
6
|
+
|
|
7
|
+
By installing and using Chati.dev, you agree to these Terms of Use.
|
|
8
|
+
|
|
9
|
+
## 2. Anonymous Usage Data Collection
|
|
10
|
+
|
|
11
|
+
Chati.dev collects anonymous usage data by default to improve the product. This includes:
|
|
12
|
+
|
|
13
|
+
- **Agents used** — which pipeline agents are invoked (e.g., brief, architect, dev)
|
|
14
|
+
- **Pipeline duration** — how long each pipeline phase takes
|
|
15
|
+
- **Gate scores** — quality gate evaluation scores
|
|
16
|
+
- **Circuit breaker events** — when safety mechanisms are triggered
|
|
17
|
+
- **Error types** — categorized error codes (no stack traces or file paths)
|
|
18
|
+
|
|
19
|
+
### What is NOT collected
|
|
20
|
+
|
|
21
|
+
- No source code, file contents, or file paths
|
|
22
|
+
- No personal information (name, email, IP address)
|
|
23
|
+
- No project names or repository URLs
|
|
24
|
+
- No prompts, conversations, or AI responses
|
|
25
|
+
|
|
26
|
+
### Anonymous Identification
|
|
27
|
+
|
|
28
|
+
A random UUID is generated locally for your installation. This ID cannot be traced back to you.
|
|
29
|
+
|
|
30
|
+
## 3. Opting Out
|
|
31
|
+
|
|
32
|
+
You can disable telemetry at any time:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
npx chati-dev telemetry disable
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
You can re-enable it with:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
npx chati-dev telemetry enable
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Check current status:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
npx chati-dev telemetry
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 4. Data Handling
|
|
51
|
+
|
|
52
|
+
Data is sent to Chati.dev telemetry servers and used solely for product improvement. Data is not sold or shared with third parties.
|
|
53
|
+
|
|
54
|
+
## 5. License
|
|
55
|
+
|
|
56
|
+
Chati.dev is licensed under the Elastic License 2.0. See LICENSE for full terms.
|
package/framework/config.yaml
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# chati.dev Configuration
|
|
2
|
-
version: "
|
|
2
|
+
version: "4.0.0"
|
|
3
3
|
installed_at: "2026-02-07T10:00:00Z"
|
|
4
|
-
updated_at: "2026-03-
|
|
5
|
-
installer_version: "
|
|
4
|
+
updated_at: "2026-03-17T00:00:00Z"
|
|
5
|
+
installer_version: "4.0.0"
|
|
6
6
|
project_type: greenfield
|
|
7
7
|
language: en
|
|
8
8
|
ides: [claude-code]
|
|
@@ -27,3 +27,23 @@ providers:
|
|
|
27
27
|
# brownfield-wu:
|
|
28
28
|
# provider: gemini
|
|
29
29
|
# model: pro
|
|
30
|
+
|
|
31
|
+
# Feature flags — toggle new capabilities (v4.0 Pegasus)
|
|
32
|
+
features:
|
|
33
|
+
hybrid_budget: true
|
|
34
|
+
anti_dash: true
|
|
35
|
+
rate_limiter_integration: true
|
|
36
|
+
l5_keywords: true
|
|
37
|
+
prompt_size_guard: true
|
|
38
|
+
ids_decision_engine: true
|
|
39
|
+
surface_criteria: true
|
|
40
|
+
parallel_fallback: true
|
|
41
|
+
tool_mesh: true
|
|
42
|
+
tech_presets: true
|
|
43
|
+
doctor_autofix: true
|
|
44
|
+
brandbook: true
|
|
45
|
+
|
|
46
|
+
# Telemetry — opt-in anonymous usage tracking
|
|
47
|
+
telemetry:
|
|
48
|
+
enabled: true
|
|
49
|
+
anonymous_id: d0ae24af-0a62-472c-b501-2104f03aa6af
|
|
@@ -32,13 +32,13 @@ Chati.dev is a planning-first AI-assisted orchestration system that coordinates
|
|
|
32
32
|
|
|
33
33
|
### Exclusion List
|
|
34
34
|
|
|
35
|
-
The following items
|
|
36
|
-
- CI/CD pipelines, release scripts, publish scripts
|
|
35
|
+
The following items are explicitly out of scope for Chati.dev:
|
|
36
|
+
- CI/CD pipelines, release scripts, publish scripts (contributor tooling)
|
|
37
37
|
- Husky/lint-staged configs (contributor tooling)
|
|
38
38
|
- npm package configs (.npmignore, .npmrc)
|
|
39
39
|
- Dashboard web UI (separate product)
|
|
40
40
|
- Monitor Server (separate product)
|
|
41
|
-
-
|
|
41
|
+
- Standalone installer packages (CLI handles installation)
|
|
42
42
|
- execution-n8n skill (removed — code-only focus)
|
|
43
43
|
- Generic tasks redundant with agent self-validation protocols
|
|
44
44
|
- Duplicate checklists already covered by agent self-validation
|
|
@@ -270,7 +270,8 @@ The pipeline operates in three execution modes that control agent permissions. M
|
|
|
270
270
|
1. The orchestrator SHALL calculate the context bracket (FRESH, MODERATE, DEPLETED, CRITICAL) before every agent interaction.
|
|
271
271
|
|
|
272
272
|
2. Context injection layers SHALL be reduced according to bracket level:
|
|
273
|
-
- FRESH
|
|
273
|
+
- FRESH: All 6 layers (L0-L5)
|
|
274
|
+
- MODERATE: L0 + L1 + L2 + L3 + L5 (skip L4 task detail)
|
|
274
275
|
- DEPLETED: L0 (Constitution) + L1 (Mode) + L2 (Agent) only
|
|
275
276
|
- CRITICAL: L0 (Constitution) + L1 (Mode) only
|
|
276
277
|
|
|
@@ -280,11 +281,12 @@ The pipeline operates in three execution modes that control agent permissions. M
|
|
|
280
281
|
|
|
281
282
|
4. The Constitution (L0) and Mode governance (L1) are NON-NEGOTIABLE and SHALL be injected in ALL brackets, including CRITICAL.
|
|
282
283
|
|
|
283
|
-
5. Token budgets per bracket:
|
|
284
|
-
-
|
|
285
|
-
-
|
|
286
|
-
-
|
|
287
|
-
-
|
|
284
|
+
5. Token budgets per bracket (Progressive Reinforcement Model — as context degrades, reinforcement increases):
|
|
285
|
+
- Budgets are expressed as a percentage of the provider's context window
|
|
286
|
+
- FRESH: 1.5% of context window (Claude: 3000, Gemini: 15000, Codex: 1920)
|
|
287
|
+
- MODERATE: 2.5% of context window (Claude: 5000, Gemini: 25000, Codex: 3200)
|
|
288
|
+
- DEPLETED: 4.0% of context window (Claude: 8000, Gemini: 40000, Codex: 5120)
|
|
289
|
+
- CRITICAL: 5.0% of context window (Claude: 10000, Gemini: 50000, Codex: 6400)
|
|
288
290
|
|
|
289
291
|
6. Autonomous spawn capability varies by IDE:
|
|
290
292
|
- Full autonomy: Claude Code, AntiGravity, Gemini CLI
|
|
@@ -472,5 +474,5 @@ When multiple CLI providers are enabled, the system SHALL coordinate agent execu
|
|
|
472
474
|
|
|
473
475
|
---
|
|
474
476
|
|
|
475
|
-
*Chati.dev Constitution
|
|
477
|
+
*Chati.dev Constitution v4.0.0 — 19 Articles + Preamble*
|
|
476
478
|
*All agents are bound by this Constitution. Violations are enforced per article.*
|
|
@@ -10,6 +10,8 @@ Extracted from `chati.dev/constitution.md` (19 Articles). Read the full constitu
|
|
|
10
10
|
## Context Bracket (Article XII)
|
|
11
11
|
- 4 brackets: FRESH, MODERATE, DEPLETED, CRITICAL
|
|
12
12
|
- CRITICAL = Constitution + Global layers only (no agent/task context)
|
|
13
|
+
- Progressive Reinforcement: budget INCREASES as context degrades (1.5% → 2.5% → 4.0% → 5.0% of provider context window)
|
|
14
|
+
- Provider-aware: budgets scale proportionally to context window size (Claude 200K, Gemini 1M, Codex 128K)
|
|
13
15
|
- Handoff before bracket drops below 15%
|
|
14
16
|
|
|
15
17
|
## Memory (Article XIII)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Chati.dev System Context
|
|
2
2
|
|
|
3
3
|
## Framework
|
|
4
|
-
- **Version**:
|
|
4
|
+
- **Version**: 4.0.0
|
|
5
5
|
- **Agents**: 13 (12 specialized + orchestrator)
|
|
6
6
|
- **Constitution**: 19 Articles + Preamble
|
|
7
7
|
- **Quality**: 5 pipeline gates + 3-tier verdicts (APPROVED / NEEDS_REVISION / BLOCKED)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Purpose
|
|
4
4
|
|
|
5
|
-
The Context Engine monitors context window usage and adapts what information is injected into each agent's prompt. As the context fills, fewer layers are injected to
|
|
5
|
+
The Context Engine monitors context window usage and adapts what information is injected into each agent's prompt. As the context fills, fewer layers are injected to maintain focus, while per-layer reinforcement INCREASES to compensate for the model forgetting initial instructions (Progressive Reinforcement Model).
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -12,16 +12,16 @@ Four brackets define behavior based on remaining context:
|
|
|
12
12
|
|
|
13
13
|
| Bracket | Context Remaining | Behavior |
|
|
14
14
|
|---------|-------------------|----------|
|
|
15
|
-
| **FRESH** | 60-100% | All
|
|
16
|
-
| **MODERATE** | 40-60% |
|
|
17
|
-
| **DEPLETED** | 25-40% |
|
|
18
|
-
| **CRITICAL** | <25% |
|
|
15
|
+
| **FRESH** | 60-100% | All 6 layers active. Minimal reinforcement (1.5%) — context is plentiful. No memory injection. |
|
|
16
|
+
| **MODERATE** | 40-60% | 5 layers (skip L4). Growing reinforcement (2.5%) — model starting to forget. Metadata memory. |
|
|
17
|
+
| **DEPLETED** | 25-40% | 3 layers (L0-L2). Heavy reinforcement (4.0%) — significant context loss. Chunk memory recovery. |
|
|
18
|
+
| **CRITICAL** | <25% | 2 layers (L0-L1). Maximum reinforcement (5.0%) — last interactions before handoff. Full memory dump. |
|
|
19
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
22
22
|
## Layered Context Injection
|
|
23
23
|
|
|
24
|
-
The orchestrator injects context through
|
|
24
|
+
The orchestrator injects context through 6 hierarchical layers:
|
|
25
25
|
|
|
26
26
|
| Layer | Name | Source | When Active |
|
|
27
27
|
|-------|------|--------|-------------|
|
|
@@ -30,15 +30,18 @@ The orchestrator injects context through 5 hierarchical layers:
|
|
|
30
30
|
| **L2** | Agent Scope | `chati.dev/agents/{agent}/` — mission, inputs, outputs, criteria | When agent is active |
|
|
31
31
|
| **L3** | Pipeline State | `.chati/session.yaml` — pipeline position, scores, backlog | When session is active |
|
|
32
32
|
| **L4** | Task Context | Active artifact + previous agent's handoff | When task is active |
|
|
33
|
+
| **L5** | Keywords | `chati.dev/domains/keywords/` — dynamic rules from user prompt | FRESH + MODERATE only |
|
|
33
34
|
|
|
34
35
|
### Layer Activation by Bracket
|
|
35
36
|
|
|
36
|
-
| Bracket | Active Layers |
|
|
37
|
-
|
|
38
|
-
| FRESH | L0, L1, L2, L3, L4 |
|
|
39
|
-
| MODERATE | L0, L1, L2, L3,
|
|
40
|
-
| DEPLETED | L0, L1, L2 |
|
|
41
|
-
| CRITICAL | L0, L1 |
|
|
37
|
+
| Bracket | Active Layers | Budget Ratio | Claude (200K) | Gemini (1M) | Codex (128K) |
|
|
38
|
+
|---------|--------------|-------------|---------------|-------------|--------------|
|
|
39
|
+
| FRESH | L0, L1, L2, L3, L4, L5 | 1.5% | 3,000 | 15,000 | 1,920 |
|
|
40
|
+
| MODERATE | L0, L1, L2, L3, L5 | 2.5% | 5,000 | 25,000 | 3,200 |
|
|
41
|
+
| DEPLETED | L0, L1, L2 | 4.0% | 8,000 | 40,000 | 5,120 |
|
|
42
|
+
| CRITICAL | L0, L1 | 5.0% | 10,000 | 50,000 | 6,400 |
|
|
43
|
+
|
|
44
|
+
Budgets are proportional to the provider's context window. As context degrades, fewer layers are active (focus) but each active layer receives MORE reinforcement tokens (strength).
|
|
42
45
|
|
|
43
46
|
---
|
|
44
47
|
|
|
@@ -145,12 +148,14 @@ If Smart Continuation is insufficient, the orchestrator spawns a new session:
|
|
|
145
148
|
|
|
146
149
|
## Integration with Memory Layer
|
|
147
150
|
|
|
151
|
+
Memory injection follows the same progressive reinforcement principle: as context degrades, memory becomes MORE important.
|
|
152
|
+
|
|
148
153
|
| Bracket | Memory Level | Behavior |
|
|
149
154
|
|---------|-------------|----------|
|
|
150
|
-
| FRESH |
|
|
151
|
-
| MODERATE |
|
|
152
|
-
| DEPLETED |
|
|
153
|
-
| CRITICAL |
|
|
155
|
+
| FRESH | none | Context is sufficient — no memory injection needed |
|
|
156
|
+
| MODERATE | metadata | Light reminder of relevant memories (~50 tokens) |
|
|
157
|
+
| DEPLETED | chunks | Context recovery via memory summaries (~200 tokens) |
|
|
158
|
+
| CRITICAL | full | Full memory dump for session handoff (~1000+ tokens) |
|
|
154
159
|
|
|
155
160
|
---
|
|
156
161
|
|
|
@@ -160,7 +165,7 @@ If Smart Continuation is insufficient, the orchestrator spawns a new session:
|
|
|
160
165
|
|
|
161
166
|
---
|
|
162
167
|
|
|
163
|
-
*Context Engine
|
|
168
|
+
*Context Engine v2.0 — Chati.dev Intelligence Layer (Progressive Reinforcement Model)*
|
|
164
169
|
|
|
165
170
|
---
|
|
166
171
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chati-dev",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "AI-Powered Multi-Agent Orchestration System — Structured vibe coding for Full Stack Development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"assets/",
|
|
22
22
|
"framework/",
|
|
23
23
|
"scripts/",
|
|
24
|
-
"LICENSE"
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"TERMS_OF_USE.md"
|
|
25
26
|
],
|
|
26
27
|
"scripts": {
|
|
27
28
|
"start": "node bin/chati.js",
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Doctor check: Agent definition files.
|
|
3
|
+
*
|
|
4
|
+
* Validates that all 13 agent definition files exist with valid structure.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
const EXPECTED_AGENTS = {
|
|
11
|
+
'discover/greenfield-wu.md': 'greenfield-wu',
|
|
12
|
+
'discover/brownfield-wu.md': 'brownfield-wu',
|
|
13
|
+
'discover/brief.md': 'brief',
|
|
14
|
+
'plan/detail.md': 'detail',
|
|
15
|
+
'plan/architect.md': 'architect',
|
|
16
|
+
'plan/ux.md': 'ux',
|
|
17
|
+
'plan/phases.md': 'phases',
|
|
18
|
+
'plan/tasks.md': 'tasks',
|
|
19
|
+
'quality/qa-planning.md': 'qa-planning',
|
|
20
|
+
'quality/qa-implementation.md': 'qa-implementation',
|
|
21
|
+
'build/dev.md': 'dev',
|
|
22
|
+
'deploy/devops.md': 'devops',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Run agents check.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} frameworkDir - Path to framework directory
|
|
29
|
+
* @returns {{ pass: boolean, details: string, severity: string, fixable: boolean, fixId: string|null }}
|
|
30
|
+
*/
|
|
31
|
+
export function checkAgents(frameworkDir) {
|
|
32
|
+
const agentsDir = join(frameworkDir, 'agents');
|
|
33
|
+
const orchestratorDir = join(frameworkDir, 'orchestrator');
|
|
34
|
+
|
|
35
|
+
const missing = [];
|
|
36
|
+
const invalid = [];
|
|
37
|
+
|
|
38
|
+
for (const [relPath, name] of Object.entries(EXPECTED_AGENTS)) {
|
|
39
|
+
const fullPath = join(agentsDir, relPath);
|
|
40
|
+
if (!existsSync(fullPath)) {
|
|
41
|
+
missing.push(name);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const content = readFileSync(fullPath, 'utf8');
|
|
46
|
+
if (!content.includes('## Identity') && !content.includes('## Mission')) {
|
|
47
|
+
invalid.push(name);
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
invalid.push(name);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Check orchestrator
|
|
55
|
+
const orchPath = join(orchestratorDir, 'chati.md');
|
|
56
|
+
if (!existsSync(orchPath)) {
|
|
57
|
+
missing.push('orchestrator');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const total = Object.keys(EXPECTED_AGENTS).length + 1;
|
|
61
|
+
const found = total - missing.length;
|
|
62
|
+
|
|
63
|
+
if (missing.length > 0 || invalid.length > 0) {
|
|
64
|
+
const issues = [];
|
|
65
|
+
if (missing.length) issues.push(`missing: ${missing.join(', ')}`);
|
|
66
|
+
if (invalid.length) issues.push(`invalid: ${invalid.join(', ')}`);
|
|
67
|
+
return {
|
|
68
|
+
pass: false,
|
|
69
|
+
details: `${found}/${total} agents found; ${issues.join('; ')}`,
|
|
70
|
+
severity: missing.length > 0 ? 'critical' : 'warning',
|
|
71
|
+
fixable: false,
|
|
72
|
+
fixId: null,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { pass: true, details: `${found}/${total} agents present`, severity: 'info', fixable: false, fixId: null };
|
|
77
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Doctor check: Constitution integrity.
|
|
3
|
+
*
|
|
4
|
+
* Validates constitution.md exists and contains the expected number of articles.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, existsSync } from 'fs';
|
|
8
|
+
import { join } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Run constitution integrity check.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} frameworkDir - Path to framework directory
|
|
14
|
+
* @returns {{ pass: boolean, details: string, severity: string, fixable: boolean, fixId: string|null }}
|
|
15
|
+
*/
|
|
16
|
+
export function checkConstitution(frameworkDir) {
|
|
17
|
+
const constPath = join(frameworkDir, 'constitution.md');
|
|
18
|
+
if (!existsSync(constPath)) {
|
|
19
|
+
return { pass: false, details: 'constitution.md not found', severity: 'critical', fixable: false, fixId: null };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const content = readFileSync(constPath, 'utf8');
|
|
24
|
+
const articleMatches = content.match(/^## Article [IVXLCDM]+/gm) || [];
|
|
25
|
+
const articleCount = articleMatches.length;
|
|
26
|
+
|
|
27
|
+
if (articleCount < 10) {
|
|
28
|
+
return {
|
|
29
|
+
pass: false,
|
|
30
|
+
details: `Only ${articleCount} articles found (expected 10+)`,
|
|
31
|
+
severity: 'warning',
|
|
32
|
+
fixable: false,
|
|
33
|
+
fixId: null,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { pass: true, details: `${articleCount} articles found`, severity: 'info', fixable: false, fixId: null };
|
|
38
|
+
} catch (err) {
|
|
39
|
+
return { pass: false, details: `Failed to read: ${err.message}`, severity: 'critical', fixable: false, fixId: null };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Doctor check: Domain-Agent alignment.
|
|
3
|
+
*
|
|
4
|
+
* Validates that each agent domain YAML has a corresponding agent .md file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readdirSync } from 'fs';
|
|
8
|
+
import { join, basename } from 'path';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Run domain-agent alignment check.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} frameworkDir - Path to framework directory
|
|
14
|
+
* @returns {{ pass: boolean, details: string, severity: string, fixable: boolean, fixId: string|null }}
|
|
15
|
+
*/
|
|
16
|
+
export function checkDomainAlignment(frameworkDir) {
|
|
17
|
+
const domainsDir = join(frameworkDir, 'domains', 'agents');
|
|
18
|
+
if (!existsSync(domainsDir)) {
|
|
19
|
+
return { pass: false, details: 'domains/agents/ directory not found', severity: 'warning', fixable: false, fixId: null };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const domainFiles = readdirSync(domainsDir).filter(f => f.endsWith('.yaml'));
|
|
23
|
+
const mismatches = [];
|
|
24
|
+
|
|
25
|
+
for (const file of domainFiles) {
|
|
26
|
+
const agentName = basename(file, '.yaml');
|
|
27
|
+
|
|
28
|
+
// Orchestrator has a different path
|
|
29
|
+
if (agentName === 'orchestrator') {
|
|
30
|
+
if (!existsSync(join(frameworkDir, 'orchestrator', 'chati.md'))) {
|
|
31
|
+
mismatches.push('orchestrator');
|
|
32
|
+
}
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Other agents: check all category dirs
|
|
37
|
+
const agentDirs = ['agents/discover', 'agents/plan', 'agents/quality', 'agents/build', 'agents/deploy'];
|
|
38
|
+
const found = agentDirs.some(dir =>
|
|
39
|
+
existsSync(join(frameworkDir, dir, `${agentName}.md`))
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!found) {
|
|
43
|
+
mismatches.push(agentName);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (mismatches.length > 0) {
|
|
48
|
+
return {
|
|
49
|
+
pass: false,
|
|
50
|
+
details: `Mismatched agents: ${mismatches.join(', ')}`,
|
|
51
|
+
severity: 'warning',
|
|
52
|
+
fixable: false,
|
|
53
|
+
fixId: null,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { pass: true, details: `${domainFiles.length} domain-agent pairs aligned`, severity: 'info', fixable: false, fixId: null };
|
|
58
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Doctor check: PRISM Layer integrity.
|
|
3
|
+
*
|
|
4
|
+
* Validates that all 6 PRISM layers (L0-L5) have the required
|
|
5
|
+
* domain files and configuration in place.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readdirSync, readFileSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Run PRISM layers integrity check.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} frameworkDir - Path to framework directory
|
|
15
|
+
* @returns {{ pass: boolean, details: string, severity: string, fixable: boolean, fixId: string|null }}
|
|
16
|
+
*/
|
|
17
|
+
export function checkPrismLayers(frameworkDir) {
|
|
18
|
+
const domainsDir = join(frameworkDir, 'domains');
|
|
19
|
+
if (!existsSync(domainsDir)) {
|
|
20
|
+
return { pass: false, details: 'domains/ directory not found', severity: 'critical', fixable: false, fixId: null };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const issues = [];
|
|
24
|
+
|
|
25
|
+
// L0: Constitution domain
|
|
26
|
+
const constitutionDomain = join(domainsDir, 'constitution.yaml');
|
|
27
|
+
if (!existsSync(constitutionDomain)) {
|
|
28
|
+
issues.push('L0: constitution.yaml missing');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// L1: Global domain
|
|
32
|
+
const globalDomain = join(domainsDir, 'global.yaml');
|
|
33
|
+
if (!existsSync(globalDomain)) {
|
|
34
|
+
issues.push('L1: global.yaml missing');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// L2: Agent domains
|
|
38
|
+
const agentsDir = join(domainsDir, 'agents');
|
|
39
|
+
if (!existsSync(agentsDir)) {
|
|
40
|
+
issues.push('L2: agents/ directory missing');
|
|
41
|
+
} else {
|
|
42
|
+
const agentDomains = readdirSync(agentsDir).filter(f => f.endsWith('.yaml'));
|
|
43
|
+
if (agentDomains.length < 12) {
|
|
44
|
+
issues.push(`L2: only ${agentDomains.length}/12 agent domains found`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// L3: Workflow domains
|
|
49
|
+
const workflowsDir = join(domainsDir, 'workflows');
|
|
50
|
+
if (!existsSync(workflowsDir)) {
|
|
51
|
+
issues.push('L3: workflows/ directory missing');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// L4: Task context (checked via task domain files or inline)
|
|
55
|
+
// L4 is dynamic (loaded from handoff data), so we check that the task
|
|
56
|
+
// processing layer module exists
|
|
57
|
+
const l4Module = join(frameworkDir, '..', 'src', 'context', 'layers', 'l4-task.js');
|
|
58
|
+
if (!existsSync(l4Module)) {
|
|
59
|
+
issues.push('L4: l4-task.js module missing');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// L5: Keywords domains
|
|
63
|
+
const keywordsDir = join(domainsDir, 'keywords');
|
|
64
|
+
if (!existsSync(keywordsDir)) {
|
|
65
|
+
issues.push('L5: keywords/ directory missing');
|
|
66
|
+
} else {
|
|
67
|
+
const keywordFiles = readdirSync(keywordsDir).filter(f => f.endsWith('.yaml'));
|
|
68
|
+
if (keywordFiles.length === 0) {
|
|
69
|
+
issues.push('L5: no keyword domain files found');
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (issues.length > 0) {
|
|
74
|
+
return {
|
|
75
|
+
pass: false,
|
|
76
|
+
details: issues.join('; '),
|
|
77
|
+
severity: issues.some(i => i.includes('L0') || i.includes('L1')) ? 'critical' : 'warning',
|
|
78
|
+
fixable: false,
|
|
79
|
+
fixId: null,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return { pass: true, details: 'All 6 PRISM layers (L0-L5) validated', severity: 'info', fixable: false, fixId: null };
|
|
84
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Doctor check: Entity Registry integrity.
|
|
3
|
+
*
|
|
4
|
+
* Validates entity-registry.yaml exists, parses correctly,
|
|
5
|
+
* entity count matches metadata, and all entity paths exist.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync, existsSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
import yaml from 'js-yaml';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Run entity registry integrity check.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} frameworkDir - Path to framework directory
|
|
16
|
+
* @returns {{ pass: boolean, details: string, severity: string, fixable: boolean, fixId: string|null }}
|
|
17
|
+
*/
|
|
18
|
+
export function checkRegistry(frameworkDir) {
|
|
19
|
+
const regPath = join(frameworkDir, 'data', 'entity-registry.yaml');
|
|
20
|
+
if (!existsSync(regPath)) {
|
|
21
|
+
return { pass: false, details: 'entity-registry.yaml not found', severity: 'critical', fixable: false, fixId: null };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const content = readFileSync(regPath, 'utf8');
|
|
26
|
+
const registry = yaml.load(content);
|
|
27
|
+
|
|
28
|
+
if (!registry || !registry.entities) {
|
|
29
|
+
return { pass: false, details: 'entity-registry.yaml has no entities section', severity: 'critical', fixable: false, fixId: null };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Count all entities across all categories
|
|
33
|
+
let entityCount = 0;
|
|
34
|
+
for (const category of Object.values(registry.entities)) {
|
|
35
|
+
if (typeof category === 'object' && category !== null) {
|
|
36
|
+
entityCount += Object.keys(category).length;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const declaredCount = registry.metadata?.entity_count || 0;
|
|
41
|
+
if (declaredCount > 0 && entityCount !== declaredCount) {
|
|
42
|
+
return {
|
|
43
|
+
pass: false,
|
|
44
|
+
details: `Entity count mismatch: declared ${declaredCount}, actual ${entityCount}`,
|
|
45
|
+
severity: 'warning',
|
|
46
|
+
fixable: true,
|
|
47
|
+
fixId: 'registry-count',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return { pass: true, details: `${entityCount} entities registered`, severity: 'info', fixable: false, fixId: null };
|
|
52
|
+
} catch (err) {
|
|
53
|
+
return { pass: false, details: `Failed to parse: ${err.message}`, severity: 'critical', fixable: false, fixId: null };
|
|
54
|
+
}
|
|
55
|
+
}
|