chati-dev 1.2.1 → 1.3.2
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/assets/logo.svg +42 -0
- package/assets/logo.txt +3 -3
- package/bin/chati.js +148 -8
- package/framework/constitution.md +77 -7
- package/framework/data/entity-registry.yaml +399 -0
- package/framework/i18n/en.yaml +9 -4
- package/framework/i18n/es.yaml +9 -4
- package/framework/i18n/fr.yaml +9 -4
- package/framework/i18n/pt.yaml +9 -4
- package/framework/intelligence/context-engine.md +163 -0
- package/framework/intelligence/decision-engine.md +134 -0
- package/framework/intelligence/memory-layer.md +187 -0
- package/framework/migrations/v1.1-to-v1.2.yaml +145 -0
- package/framework/orchestrator/chati.md +3 -3
- package/framework/schemas/config.schema.json +1 -1
- package/framework/schemas/context.schema.json +98 -0
- package/framework/schemas/memory.schema.json +79 -0
- package/package.json +14 -7
- package/scripts/bundle-framework.js +1 -1
- package/src/dashboard/data-reader.js +27 -2
- package/src/dashboard/layout.js +21 -0
- package/src/dashboard/renderer.js +11 -8
- package/src/installer/core.js +33 -6
- package/src/installer/validator.js +44 -5
- package/src/intelligence/context-status.js +80 -0
- package/src/intelligence/memory-manager.js +188 -0
- package/src/intelligence/registry-manager.js +202 -0
- package/src/upgrade/backup.js +2 -0
- package/src/upgrade/migrator.js +1 -1
- package/src/utils/logger.js +1 -1
- package/src/wizard/i18n.js +9 -4
- package/src/wizard/index.js +5 -0
- package/framework/agents/build/dev.md +0 -342
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "chati.dev Context Block",
|
|
4
|
+
"description": "Schema for <chati-context> XML block structure injected into agent prompts",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["bracket", "constitution", "mode"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"bracket": {
|
|
9
|
+
"enum": ["FRESH", "MODERATE", "DEPLETED", "CRITICAL"],
|
|
10
|
+
"description": "Current context bracket based on remaining context window"
|
|
11
|
+
},
|
|
12
|
+
"constitution": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"description": "Summarized constitution content (always injected, L0 layer)"
|
|
15
|
+
},
|
|
16
|
+
"mode": {
|
|
17
|
+
"enum": ["clarity", "build", "deploy"],
|
|
18
|
+
"description": "Current execution mode from session state (L1 layer)"
|
|
19
|
+
},
|
|
20
|
+
"agent": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"description": "Active agent scope information (L2 layer, active when bracket >= DEPLETED)",
|
|
23
|
+
"required": ["name", "mission"],
|
|
24
|
+
"properties": {
|
|
25
|
+
"name": { "type": "string", "description": "Agent identifier" },
|
|
26
|
+
"mission": { "type": "string", "description": "One-line agent mission statement" },
|
|
27
|
+
"inputs": { "type": "string", "description": "Expected inputs for this agent" },
|
|
28
|
+
"outputs": { "type": "string", "description": "Expected outputs from this agent" },
|
|
29
|
+
"criteria": { "type": "string", "description": "Success criteria summary" }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"pipeline": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Pipeline state string showing agent progression (L3 layer, active when bracket >= MODERATE)"
|
|
35
|
+
},
|
|
36
|
+
"task": {
|
|
37
|
+
"type": "string",
|
|
38
|
+
"description": "Current task description (L4 layer, active when bracket >= MODERATE)"
|
|
39
|
+
},
|
|
40
|
+
"handoff": {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"description": "Previous agent handoff summary (L4 layer, active when bracket >= MODERATE)",
|
|
43
|
+
"properties": {
|
|
44
|
+
"from": { "type": "string", "description": "Source agent name" },
|
|
45
|
+
"score": { "type": "number", "minimum": 0, "maximum": 100, "description": "Source agent final score" },
|
|
46
|
+
"summary": { "type": "string", "description": "Key context from previous agent" }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"memory": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"description": "Memory injection based on bracket level",
|
|
52
|
+
"properties": {
|
|
53
|
+
"bracket": {
|
|
54
|
+
"enum": ["FRESH", "MODERATE", "DEPLETED", "CRITICAL"],
|
|
55
|
+
"description": "Memory retrieval bracket (mirrors context bracket)"
|
|
56
|
+
},
|
|
57
|
+
"level": {
|
|
58
|
+
"enum": ["none", "metadata", "chunks", "full"],
|
|
59
|
+
"description": "Memory retrieval level: none (FRESH), metadata (MODERATE), chunks (DEPLETED), full (CRITICAL)"
|
|
60
|
+
},
|
|
61
|
+
"entries": {
|
|
62
|
+
"type": "array",
|
|
63
|
+
"items": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"properties": {
|
|
66
|
+
"id": { "type": "string", "description": "Memory entry identifier" },
|
|
67
|
+
"title": { "type": "string", "description": "Memory title" },
|
|
68
|
+
"tier": { "enum": ["hot", "warm", "cold"], "description": "Memory attention tier" },
|
|
69
|
+
"summary": { "type": "string", "description": "Memory summary (L2 chunks level)" },
|
|
70
|
+
"content": { "type": "string", "description": "Full memory content (L3 full level)" }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"token_budget": {
|
|
77
|
+
"type": "object",
|
|
78
|
+
"description": "Token usage estimates",
|
|
79
|
+
"properties": {
|
|
80
|
+
"estimated_used": { "type": "integer", "minimum": 0, "description": "Estimated tokens used" },
|
|
81
|
+
"max_context": { "type": "integer", "minimum": 0, "description": "Maximum context window tokens" },
|
|
82
|
+
"remaining_percent": { "type": "number", "minimum": 0, "maximum": 100, "description": "Percentage of context remaining" },
|
|
83
|
+
"injection_budget": {
|
|
84
|
+
"type": "integer",
|
|
85
|
+
"minimum": 0,
|
|
86
|
+
"description": "Token budget for context injection (FRESH: 2500, MODERATE: 2000, DEPLETED: 1500, CRITICAL: 800)"
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"active_layers": {
|
|
91
|
+
"type": "array",
|
|
92
|
+
"items": {
|
|
93
|
+
"enum": ["L0", "L1", "L2", "L3", "L4"]
|
|
94
|
+
},
|
|
95
|
+
"description": "Currently active injection layers based on bracket"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"title": "chati.dev Memory Entry",
|
|
4
|
+
"description": "Schema for memory entry YAML frontmatter in .chati/memories/",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["id", "type", "agent", "tags", "confidence", "sector", "tier", "created_at"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"id": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"pattern": "^mem-\\d{4}-\\d{2}-\\d{2}-\\d{3}$",
|
|
11
|
+
"description": "Unique memory identifier (mem-YYYY-MM-DD-NNN)"
|
|
12
|
+
},
|
|
13
|
+
"type": {
|
|
14
|
+
"enum": ["decision", "error_pattern", "resolution", "user_correction", "validated_pattern", "gotcha", "lesson"],
|
|
15
|
+
"description": "Classification of what this memory captures"
|
|
16
|
+
},
|
|
17
|
+
"agent": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "Agent that created or owns this memory"
|
|
20
|
+
},
|
|
21
|
+
"tags": {
|
|
22
|
+
"type": "array",
|
|
23
|
+
"items": { "type": "string" },
|
|
24
|
+
"minItems": 1,
|
|
25
|
+
"description": "Searchable tags for similarity matching and retrieval"
|
|
26
|
+
},
|
|
27
|
+
"confidence": {
|
|
28
|
+
"type": "number",
|
|
29
|
+
"minimum": 0,
|
|
30
|
+
"maximum": 1,
|
|
31
|
+
"description": "System confidence in this memory (0.0-1.0)"
|
|
32
|
+
},
|
|
33
|
+
"sector": {
|
|
34
|
+
"enum": ["episodic", "semantic", "procedural", "reflective"],
|
|
35
|
+
"description": "Cognitive sector: episodic (what happened), semantic (what we know), procedural (how to do it), reflective (what we learned)"
|
|
36
|
+
},
|
|
37
|
+
"tier": {
|
|
38
|
+
"enum": ["hot", "warm", "cold"],
|
|
39
|
+
"description": "Attention tier: hot (>0.7, auto-loaded), warm (0.3-0.7, on-demand), cold (<0.3, explicit search)"
|
|
40
|
+
},
|
|
41
|
+
"access_count": {
|
|
42
|
+
"type": "integer",
|
|
43
|
+
"minimum": 0,
|
|
44
|
+
"default": 0,
|
|
45
|
+
"description": "Number of times this memory has been accessed"
|
|
46
|
+
},
|
|
47
|
+
"evidence_count": {
|
|
48
|
+
"type": "integer",
|
|
49
|
+
"minimum": 0,
|
|
50
|
+
"default": 0,
|
|
51
|
+
"description": "Number of corroborating observations"
|
|
52
|
+
},
|
|
53
|
+
"last_accessed": {
|
|
54
|
+
"type": ["string", "null"],
|
|
55
|
+
"format": "date-time",
|
|
56
|
+
"description": "Timestamp of last access"
|
|
57
|
+
},
|
|
58
|
+
"created_at": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"format": "date-time",
|
|
61
|
+
"description": "Timestamp of memory creation"
|
|
62
|
+
},
|
|
63
|
+
"expires_at": {
|
|
64
|
+
"type": ["string", "null"],
|
|
65
|
+
"format": "date-time",
|
|
66
|
+
"description": "Expiration timestamp (null for durable memories)"
|
|
67
|
+
},
|
|
68
|
+
"storage_tier": {
|
|
69
|
+
"enum": ["session", "daily", "durable"],
|
|
70
|
+
"default": "daily",
|
|
71
|
+
"description": "Storage persistence: session (cleaned on restart), daily (archived after 30d), durable (permanent)"
|
|
72
|
+
},
|
|
73
|
+
"scope": {
|
|
74
|
+
"enum": ["shared", "private"],
|
|
75
|
+
"default": "shared",
|
|
76
|
+
"description": "Visibility: shared (all agents) or private (owning agent only)"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chati-dev",
|
|
3
|
-
"version": "1.2
|
|
4
|
-
"description": "AI-Powered Multi-Agent
|
|
3
|
+
"version": "1.3.2",
|
|
4
|
+
"description": "AI-Powered Multi-Agent Orchestration System — 13 agents, 6 IDEs, 4 languages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"chati": "bin/chati.js",
|
|
@@ -19,13 +19,15 @@
|
|
|
19
19
|
"start": "node bin/chati.js",
|
|
20
20
|
"bundle": "node scripts/bundle-framework.js",
|
|
21
21
|
"prepublishOnly": "node scripts/bundle-framework.js",
|
|
22
|
-
"test": "node --test"
|
|
22
|
+
"test": "node --test test/**/*.test.js",
|
|
23
|
+
"lint": "eslint src/ bin/",
|
|
24
|
+
"lint:fix": "eslint src/ bin/ --fix"
|
|
23
25
|
},
|
|
24
26
|
"keywords": [
|
|
25
27
|
"ai",
|
|
26
28
|
"agents",
|
|
27
29
|
"development",
|
|
28
|
-
"
|
|
30
|
+
"system",
|
|
29
31
|
"planning",
|
|
30
32
|
"multi-agent",
|
|
31
33
|
"cli",
|
|
@@ -46,15 +48,20 @@
|
|
|
46
48
|
},
|
|
47
49
|
"dependencies": {
|
|
48
50
|
"@clack/prompts": "^0.7.0",
|
|
51
|
+
"blessed": "^0.1.81",
|
|
49
52
|
"chalk": "^5.3.0",
|
|
50
|
-
"ora": "^8.0.1",
|
|
51
53
|
"cli-progress": "^3.12.0",
|
|
52
54
|
"fs-extra": "^11.2.0",
|
|
53
55
|
"js-yaml": "^4.1.0",
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
+
"ora": "^8.0.1",
|
|
57
|
+
"semver": "^7.6.0"
|
|
56
58
|
},
|
|
57
59
|
"engines": {
|
|
58
60
|
"node": ">=18.0.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@eslint/js": "^10.0.1",
|
|
64
|
+
"eslint": "^10.0.0",
|
|
65
|
+
"globals": "^17.3.0"
|
|
59
66
|
}
|
|
60
67
|
}
|
|
@@ -35,7 +35,7 @@ const dirs = [
|
|
|
35
35
|
'agents/clarity', 'agents/quality', 'agents/build', 'agents/deploy',
|
|
36
36
|
'templates', 'workflows', 'quality-gates',
|
|
37
37
|
'schemas', 'frameworks', 'intelligence', 'patterns',
|
|
38
|
-
'i18n', 'migrations',
|
|
38
|
+
'i18n', 'migrations', 'data',
|
|
39
39
|
];
|
|
40
40
|
|
|
41
41
|
for (const dir of dirs) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { readFileSync, existsSync, readdirSync
|
|
1
|
+
import { readFileSync, existsSync, readdirSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Read all dashboard data from project directory
|
|
7
7
|
*/
|
|
8
|
-
export function readDashboardData(targetDir) {
|
|
8
|
+
export async function readDashboardData(targetDir) {
|
|
9
9
|
const data = {
|
|
10
10
|
session: null,
|
|
11
11
|
config: null,
|
|
@@ -15,6 +15,9 @@ export function readDashboardData(targetDir) {
|
|
|
15
15
|
recentActivity: [],
|
|
16
16
|
blockers: [],
|
|
17
17
|
gotchas: [],
|
|
18
|
+
memoryStats: null,
|
|
19
|
+
contextStatus: null,
|
|
20
|
+
registryStats: null,
|
|
18
21
|
};
|
|
19
22
|
|
|
20
23
|
// Read session.yaml
|
|
@@ -95,5 +98,27 @@ export function readDashboardData(targetDir) {
|
|
|
95
98
|
});
|
|
96
99
|
}
|
|
97
100
|
|
|
101
|
+
// Intelligence Layer data (graceful degradation)
|
|
102
|
+
try {
|
|
103
|
+
const { getMemoryStats } = await import('../intelligence/memory-manager.js');
|
|
104
|
+
data.memoryStats = getMemoryStats(targetDir);
|
|
105
|
+
} catch {
|
|
106
|
+
// Intelligence module not available
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const { getContextStatus } = await import('../intelligence/context-status.js');
|
|
111
|
+
data.contextStatus = getContextStatus(targetDir);
|
|
112
|
+
} catch {
|
|
113
|
+
// Intelligence module not available
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const { getRegistryStats } = await import('../intelligence/registry-manager.js');
|
|
118
|
+
data.registryStats = getRegistryStats(targetDir);
|
|
119
|
+
} catch {
|
|
120
|
+
// Intelligence module not available
|
|
121
|
+
}
|
|
122
|
+
|
|
98
123
|
return data;
|
|
99
124
|
}
|
package/src/dashboard/layout.js
CHANGED
|
@@ -135,6 +135,27 @@ export function buildValidateSection(data) {
|
|
|
135
135
|
];
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Build INTELLIGENCE section
|
|
140
|
+
*/
|
|
141
|
+
export function buildIntelligenceSection(data) {
|
|
142
|
+
const mem = data.memoryStats;
|
|
143
|
+
const ctx = data.contextStatus;
|
|
144
|
+
const reg = data.registryStats;
|
|
145
|
+
|
|
146
|
+
const memText = mem ? `${mem.total} total (H:${mem.byTier.hot} W:${mem.byTier.warm} C:${mem.byTier.cold})` : gray('N/A');
|
|
147
|
+
const ctxText = ctx ? `${ctx.bracket} [${ctx.activeLayers.join(',')}]` : gray('N/A');
|
|
148
|
+
const regText = reg && reg.exists ? `${reg.totalEntities} entities (${reg.countMatch ? green('match') : yellow('mismatch')})` : gray('N/A');
|
|
149
|
+
|
|
150
|
+
return [
|
|
151
|
+
brand('│') + ` ${brand('── INTELLIGENCE')} ${'─'.repeat(41)}` + brand('│'),
|
|
152
|
+
brand('│') + ` │ ${dim('Memory:')} ${memText}` + ' '.repeat(Math.max(1, 35 - String(memText).length)) + brand('│'),
|
|
153
|
+
brand('│') + ` │ ${dim('Context:')} ${ctxText}` + ' '.repeat(Math.max(1, 35 - String(ctxText).length)) + brand('│'),
|
|
154
|
+
brand('│') + ` │ ${dim('Registry:')} ${regText}` + ' '.repeat(Math.max(1, 35 - String(regText).length)) + brand('│'),
|
|
155
|
+
brand('│') + ` ${'─'.repeat(57)}` + brand('│'),
|
|
156
|
+
];
|
|
157
|
+
}
|
|
158
|
+
|
|
138
159
|
/**
|
|
139
160
|
* Build footer with recent activity, blockers, gotchas
|
|
140
161
|
*/
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
buildClaritySection,
|
|
6
6
|
buildBuildSection,
|
|
7
7
|
buildValidateSection,
|
|
8
|
+
buildIntelligenceSection,
|
|
8
9
|
buildFooter,
|
|
9
10
|
} from './layout.js';
|
|
10
11
|
import { dim } from '../utils/colors.js';
|
|
@@ -12,8 +13,8 @@ import { dim } from '../utils/colors.js';
|
|
|
12
13
|
/**
|
|
13
14
|
* Render dashboard once (static mode)
|
|
14
15
|
*/
|
|
15
|
-
export function renderDashboard(targetDir) {
|
|
16
|
-
const data = readDashboardData(targetDir);
|
|
16
|
+
export async function renderDashboard(targetDir) {
|
|
17
|
+
const data = await readDashboardData(targetDir);
|
|
17
18
|
|
|
18
19
|
if (!data.session) {
|
|
19
20
|
console.log('No chati.dev session found. Run `npx chati-dev init` first.');
|
|
@@ -30,6 +31,8 @@ export function renderDashboard(targetDir) {
|
|
|
30
31
|
'',
|
|
31
32
|
...buildValidateSection(data),
|
|
32
33
|
'',
|
|
34
|
+
...buildIntelligenceSection(data),
|
|
35
|
+
'',
|
|
33
36
|
...buildFooter(data),
|
|
34
37
|
];
|
|
35
38
|
|
|
@@ -43,16 +46,16 @@ export function renderDashboard(targetDir) {
|
|
|
43
46
|
/**
|
|
44
47
|
* Render dashboard in watch mode (auto-refresh)
|
|
45
48
|
*/
|
|
46
|
-
export function renderDashboardWatch(targetDir, intervalMs = 5000) {
|
|
49
|
+
export async function renderDashboardWatch(targetDir, intervalMs = 5000) {
|
|
47
50
|
// Initial render
|
|
48
51
|
console.clear();
|
|
49
|
-
renderDashboard(targetDir);
|
|
52
|
+
await renderDashboard(targetDir);
|
|
50
53
|
console.log(dim(` Auto-refreshing every ${intervalMs / 1000}s. Press Ctrl+C to exit.`));
|
|
51
54
|
|
|
52
55
|
// Set up interval
|
|
53
|
-
const timer = setInterval(() => {
|
|
56
|
+
const timer = setInterval(async () => {
|
|
54
57
|
console.clear();
|
|
55
|
-
renderDashboard(targetDir);
|
|
58
|
+
await renderDashboard(targetDir);
|
|
56
59
|
console.log(dim(` Auto-refreshing every ${intervalMs / 1000}s. Press Ctrl+C to exit.`));
|
|
57
60
|
console.log(dim(` Last update: ${new Date().toLocaleTimeString()}`));
|
|
58
61
|
}, intervalMs);
|
|
@@ -70,8 +73,8 @@ export function renderDashboardWatch(targetDir, intervalMs = 5000) {
|
|
|
70
73
|
/**
|
|
71
74
|
* Render plain text fallback (for terminals without TUI support)
|
|
72
75
|
*/
|
|
73
|
-
export function renderPlainDashboard(targetDir) {
|
|
74
|
-
const data = readDashboardData(targetDir);
|
|
76
|
+
export async function renderPlainDashboard(targetDir) {
|
|
77
|
+
const data = await readDashboardData(targetDir);
|
|
75
78
|
|
|
76
79
|
if (!data.session) {
|
|
77
80
|
console.log('No chati.dev session found. Run `npx chati-dev init` first.');
|
package/src/installer/core.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, copyFileSync, existsSync
|
|
1
|
+
import { mkdirSync, writeFileSync, copyFileSync, existsSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import yaml from 'js-yaml';
|
|
5
4
|
import { IDE_CONFIGS } from '../config/ide-configs.js';
|
|
6
5
|
import { generateClaudeMCPConfig } from '../config/mcp-configs.js';
|
|
7
6
|
import { generateSessionYaml, generateConfigYaml, generateClaudeMd } from './templates.js';
|
|
@@ -38,7 +37,7 @@ export async function installFramework(config) {
|
|
|
38
37
|
'agents/clarity', 'agents/quality', 'agents/build', 'agents/deploy',
|
|
39
38
|
'templates', 'workflows', 'quality-gates',
|
|
40
39
|
'schemas', 'frameworks', 'intelligence', 'patterns',
|
|
41
|
-
'i18n', 'migrations',
|
|
40
|
+
'i18n', 'migrations', 'data',
|
|
42
41
|
'artifacts/0-WU', 'artifacts/1-Brief', 'artifacts/2-PRD',
|
|
43
42
|
'artifacts/3-Architecture', 'artifacts/4-UX', 'artifacts/5-Phases',
|
|
44
43
|
'artifacts/6-Tasks', 'artifacts/7-QA-Planning', 'artifacts/8-Validation',
|
|
@@ -49,6 +48,27 @@ export async function installFramework(config) {
|
|
|
49
48
|
createDir(join(frameworkDir, dir));
|
|
50
49
|
}
|
|
51
50
|
|
|
51
|
+
// Create .chati/memories/ directory tree for Memory Layer
|
|
52
|
+
const memoriesBase = join(targetDir, '.chati', 'memories');
|
|
53
|
+
const memoryDirs = [
|
|
54
|
+
'shared/durable', 'shared/daily', 'shared/session',
|
|
55
|
+
'greenfield-wu/durable', 'greenfield-wu/daily',
|
|
56
|
+
'brownfield-wu/durable', 'brownfield-wu/daily',
|
|
57
|
+
'brief/durable', 'brief/daily',
|
|
58
|
+
'detail/durable', 'detail/daily',
|
|
59
|
+
'architect/durable', 'architect/daily',
|
|
60
|
+
'ux/durable', 'ux/daily',
|
|
61
|
+
'phases/durable', 'phases/daily',
|
|
62
|
+
'tasks/durable', 'tasks/daily',
|
|
63
|
+
'qa-planning/durable', 'qa-planning/daily',
|
|
64
|
+
'qa-implementation/durable', 'qa-implementation/daily',
|
|
65
|
+
'dev/durable', 'dev/daily',
|
|
66
|
+
'devops/durable', 'devops/daily',
|
|
67
|
+
];
|
|
68
|
+
for (const dir of memoryDirs) {
|
|
69
|
+
createDir(join(memoriesBase, dir));
|
|
70
|
+
}
|
|
71
|
+
|
|
52
72
|
// Copy framework files from source
|
|
53
73
|
copyFrameworkFiles(frameworkDir);
|
|
54
74
|
|
|
@@ -115,6 +135,8 @@ function copyFrameworkFiles(destDir) {
|
|
|
115
135
|
'schemas/session.schema.json',
|
|
116
136
|
'schemas/config.schema.json',
|
|
117
137
|
'schemas/task.schema.json',
|
|
138
|
+
'schemas/context.schema.json',
|
|
139
|
+
'schemas/memory.schema.json',
|
|
118
140
|
// Frameworks
|
|
119
141
|
'frameworks/quality-dimensions.yaml',
|
|
120
142
|
'frameworks/decision-heuristics.yaml',
|
|
@@ -122,6 +144,9 @@ function copyFrameworkFiles(destDir) {
|
|
|
122
144
|
'intelligence/gotchas.yaml',
|
|
123
145
|
'intelligence/patterns.yaml',
|
|
124
146
|
'intelligence/confidence.yaml',
|
|
147
|
+
'intelligence/context-engine.md',
|
|
148
|
+
'intelligence/memory-layer.md',
|
|
149
|
+
'intelligence/decision-engine.md',
|
|
125
150
|
// Patterns
|
|
126
151
|
'patterns/elicitation.md',
|
|
127
152
|
// i18n
|
|
@@ -131,6 +156,8 @@ function copyFrameworkFiles(destDir) {
|
|
|
131
156
|
'i18n/fr.yaml',
|
|
132
157
|
// Migrations
|
|
133
158
|
'migrations/v1.0-to-v1.1.yaml',
|
|
159
|
+
// Data
|
|
160
|
+
'data/entity-registry.yaml',
|
|
134
161
|
];
|
|
135
162
|
|
|
136
163
|
for (const file of filesToCopy) {
|
|
@@ -182,11 +209,11 @@ This is a thin router. All logic lives in the orchestrator.
|
|
|
182
209
|
}
|
|
183
210
|
} else {
|
|
184
211
|
// For other IDEs, create a rules file pointing to chati.dev/
|
|
185
|
-
const rulesContent = `# chati.dev
|
|
212
|
+
const rulesContent = `# chati.dev System Rules
|
|
186
213
|
# This file configures ${config.name} to work with chati.dev
|
|
187
214
|
|
|
188
|
-
##
|
|
189
|
-
All
|
|
215
|
+
## System Location
|
|
216
|
+
All system content is in the \`chati.dev/\` directory.
|
|
190
217
|
|
|
191
218
|
## Session State
|
|
192
219
|
Runtime session state is in \`.chati/session.yaml\` (IDE-agnostic).
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, readFileSync
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -13,6 +13,9 @@ export async function validateInstallation(targetDir) {
|
|
|
13
13
|
schemas: { pass: false, details: [] },
|
|
14
14
|
workflows: { pass: false, details: [] },
|
|
15
15
|
templates: { pass: false, details: [] },
|
|
16
|
+
intelligence: { pass: false, details: [] },
|
|
17
|
+
registry: { pass: false, details: [] },
|
|
18
|
+
memories: { pass: false, details: [] },
|
|
16
19
|
total: 0,
|
|
17
20
|
passed: 0,
|
|
18
21
|
};
|
|
@@ -56,7 +59,7 @@ export async function validateInstallation(targetDir) {
|
|
|
56
59
|
if (existsSync(constitutionPath)) {
|
|
57
60
|
const content = readFileSync(constitutionPath, 'utf-8');
|
|
58
61
|
const articleCount = (content.match(/^## Article/gm) || []).length;
|
|
59
|
-
results.constitution.pass = articleCount >=
|
|
62
|
+
results.constitution.pass = articleCount >= 15;
|
|
60
63
|
results.constitution.details.push({ articleCount });
|
|
61
64
|
}
|
|
62
65
|
results.total += 1;
|
|
@@ -68,15 +71,18 @@ export async function validateInstallation(targetDir) {
|
|
|
68
71
|
results.total += 1;
|
|
69
72
|
if (results.session.pass) results.passed += 1;
|
|
70
73
|
|
|
71
|
-
// Check schemas
|
|
72
|
-
const schemaFiles = [
|
|
74
|
+
// Check schemas (5 total: session, config, task, context, memory)
|
|
75
|
+
const schemaFiles = [
|
|
76
|
+
'session.schema.json', 'config.schema.json', 'task.schema.json',
|
|
77
|
+
'context.schema.json', 'memory.schema.json',
|
|
78
|
+
];
|
|
73
79
|
let schemaCount = 0;
|
|
74
80
|
for (const file of schemaFiles) {
|
|
75
81
|
if (existsSync(join(targetDir, 'chati.dev', 'schemas', file))) {
|
|
76
82
|
schemaCount++;
|
|
77
83
|
}
|
|
78
84
|
}
|
|
79
|
-
results.schemas.pass = schemaCount ===
|
|
85
|
+
results.schemas.pass = schemaCount === 5;
|
|
80
86
|
results.total += 1;
|
|
81
87
|
if (results.schemas.pass) results.passed += 1;
|
|
82
88
|
|
|
@@ -110,5 +116,38 @@ export async function validateInstallation(targetDir) {
|
|
|
110
116
|
results.total += 1;
|
|
111
117
|
if (results.templates.pass) results.passed += 1;
|
|
112
118
|
|
|
119
|
+
// Check intelligence files (6: 3 specs + 3 yaml)
|
|
120
|
+
const intelligenceFiles = [
|
|
121
|
+
'intelligence/context-engine.md',
|
|
122
|
+
'intelligence/memory-layer.md',
|
|
123
|
+
'intelligence/decision-engine.md',
|
|
124
|
+
'intelligence/gotchas.yaml',
|
|
125
|
+
'intelligence/patterns.yaml',
|
|
126
|
+
'intelligence/confidence.yaml',
|
|
127
|
+
];
|
|
128
|
+
let intelCount = 0;
|
|
129
|
+
for (const file of intelligenceFiles) {
|
|
130
|
+
if (existsSync(join(targetDir, 'chati.dev', file))) {
|
|
131
|
+
intelCount++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
results.intelligence.pass = intelCount === 6;
|
|
135
|
+
results.intelligence.details.push({ found: intelCount, expected: 6 });
|
|
136
|
+
results.total += 1;
|
|
137
|
+
if (results.intelligence.pass) results.passed += 1;
|
|
138
|
+
|
|
139
|
+
// Check entity registry
|
|
140
|
+
const registryPath = join(targetDir, 'chati.dev', 'data', 'entity-registry.yaml');
|
|
141
|
+
results.registry.pass = existsSync(registryPath);
|
|
142
|
+
results.total += 1;
|
|
143
|
+
if (results.registry.pass) results.passed += 1;
|
|
144
|
+
|
|
145
|
+
// Check .chati/memories/ directory tree
|
|
146
|
+
const memoriesPath = join(targetDir, '.chati', 'memories');
|
|
147
|
+
const memoriesShared = join(memoriesPath, 'shared', 'durable');
|
|
148
|
+
results.memories.pass = existsSync(memoriesPath) && existsSync(memoriesShared);
|
|
149
|
+
results.total += 1;
|
|
150
|
+
if (results.memories.pass) results.passed += 1;
|
|
151
|
+
|
|
113
152
|
return results;
|
|
114
153
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
const BRACKETS = [
|
|
5
|
+
{ name: 'FRESH', min: 60, max: 100, layers: ['L0', 'L1', 'L2', 'L3', 'L4'], budget: 2500 },
|
|
6
|
+
{ name: 'MODERATE', min: 40, max: 60, layers: ['L0', 'L1', 'L2', 'L3', 'L4'], budget: 2000 },
|
|
7
|
+
{ name: 'DEPLETED', min: 25, max: 40, layers: ['L0', 'L1', 'L2'], budget: 1500 },
|
|
8
|
+
{ name: 'CRITICAL', min: 0, max: 25, layers: ['L0', 'L1'], budget: 800 },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Get context status based on session state
|
|
13
|
+
* (Advisory — actual bracket is calculated at runtime by the orchestrator)
|
|
14
|
+
*/
|
|
15
|
+
export function getContextStatus(targetDir) {
|
|
16
|
+
const sessionPath = join(targetDir, '.chati', 'session.yaml');
|
|
17
|
+
if (!existsSync(sessionPath)) {
|
|
18
|
+
return {
|
|
19
|
+
bracket: 'FRESH',
|
|
20
|
+
activeLayers: BRACKETS[0].layers,
|
|
21
|
+
tokenBudget: BRACKETS[0].budget,
|
|
22
|
+
memoryLevel: 'none',
|
|
23
|
+
advisory: 'No active session — default FRESH bracket',
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Read session to determine pipeline state
|
|
28
|
+
const sessionContent = readFileSync(sessionPath, 'utf-8');
|
|
29
|
+
const currentAgent = extractYamlValue(sessionContent, 'current_agent');
|
|
30
|
+
const state = extractYamlValue(sessionContent, 'state');
|
|
31
|
+
|
|
32
|
+
// Count completed agents as a rough proxy for context usage
|
|
33
|
+
const completedCount = (sessionContent.match(/status: completed/g) || []).length;
|
|
34
|
+
const inProgressCount = (sessionContent.match(/status: in_progress/g) || []).length;
|
|
35
|
+
|
|
36
|
+
// Estimate context usage based on pipeline progress
|
|
37
|
+
// More agents completed = more context consumed
|
|
38
|
+
const estimatedUsage = Math.min(95, completedCount * 8 + inProgressCount * 5);
|
|
39
|
+
const remainingPercent = 100 - estimatedUsage;
|
|
40
|
+
|
|
41
|
+
const bracket = BRACKETS.find(b => remainingPercent >= b.min && remainingPercent <= b.max) || BRACKETS[0];
|
|
42
|
+
|
|
43
|
+
const memoryLevels = { FRESH: 'none', MODERATE: 'metadata', DEPLETED: 'chunks', CRITICAL: 'full' };
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
bracket: bracket.name,
|
|
47
|
+
activeLayers: bracket.layers,
|
|
48
|
+
tokenBudget: bracket.budget,
|
|
49
|
+
memoryLevel: memoryLevels[bracket.name],
|
|
50
|
+
remainingPercent,
|
|
51
|
+
estimatedUsage,
|
|
52
|
+
currentAgent: currentAgent || 'none',
|
|
53
|
+
pipelineState: state || 'unknown',
|
|
54
|
+
completedAgents: completedCount,
|
|
55
|
+
advisory: `Estimated bracket based on pipeline progress (${completedCount} agents completed)`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Estimate context usage for display purposes
|
|
61
|
+
*/
|
|
62
|
+
export function estimateContextUsage(targetDir) {
|
|
63
|
+
const status = getContextStatus(targetDir);
|
|
64
|
+
return {
|
|
65
|
+
bracket: status.bracket,
|
|
66
|
+
remainingPercent: status.remainingPercent,
|
|
67
|
+
tokenBudget: status.tokenBudget,
|
|
68
|
+
layers: status.activeLayers,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Simple YAML value extractor (avoids js-yaml dependency)
|
|
74
|
+
*/
|
|
75
|
+
function extractYamlValue(content, key) {
|
|
76
|
+
const regex = new RegExp(`^\\s*${key}:\\s*(.+)$`, 'm');
|
|
77
|
+
const match = content.match(regex);
|
|
78
|
+
if (!match) return null;
|
|
79
|
+
return match[1].trim().replace(/^["']|["']$/g, '');
|
|
80
|
+
}
|