chati-dev 3.0.0 → 3.0.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/README.md +95 -24
- package/bin/chati.js +1 -1
- package/framework/agents/plan/phases.md +2 -2
- package/framework/config.yaml +2 -2
- package/framework/constitution.md +4 -4
- package/framework/context/governance.md +16 -3
- package/framework/context/root.md +3 -3
- package/framework/data/entity-registry.yaml +1 -1
- package/framework/domains/agents/detail.yaml +1 -1
- package/framework/domains/agents/phases.yaml +2 -2
- package/framework/domains/agents/tasks.yaml +2 -2
- package/framework/domains/constitution.yaml +2 -2
- package/framework/hooks/read-protection.js +1 -0
- package/framework/i18n/en.yaml +11 -4
- package/framework/i18n/es.yaml +11 -4
- package/framework/i18n/fr.yaml +11 -4
- package/framework/i18n/pt.yaml +11 -4
- package/framework/intelligence/context-engine.md +2 -2
- package/framework/intelligence/decision-engine.md +1 -1
- package/framework/patterns/elicitation-library.yaml +2 -2
- package/framework/tasks/brownfield-wu-dependency-scan.md +1 -1
- package/framework/tasks/brownfield-wu-migration-plan.md +4 -4
- package/framework/tasks/brownfield-wu-risk-assess.md +2 -2
- package/framework/tasks/detail-expand-prd.md +2 -2
- package/framework/tasks/greenfield-wu-report.md +1 -1
- package/framework/tasks/orchestrator-handoff.md +2 -2
- package/framework/tasks/orchestrator-resume.md +1 -1
- package/framework/tasks/qa-impl-performance-test.md +2 -2
- package/framework/tasks/qa-impl-sast-scan.md +6 -6
- package/framework/tasks/qa-planning-consolidate.md +1 -1
- package/framework/tasks/qa-planning-coverage-plan.md +9 -9
- package/framework/tasks/qa-planning-gate-define.md +6 -6
- package/framework/tasks/qa-planning-risk-matrix.md +1 -1
- package/framework/tasks/tasks-consolidate.md +5 -5
- package/package.json +1 -1
- package/scripts/changelog-generator.js +2 -2
- package/scripts/ide-sync.js +9 -4
- package/scripts/pr-review.js +5 -5
- package/scripts/semantic-lint.js +3 -3
- package/src/autonomy/build-state.js +1 -1
- package/src/autonomy/execution-profile.js +1 -1
- package/src/config/context-file-generator.js +20 -26
- package/src/config/ide-configs.js +6 -6
- package/src/gates/g2-qa-planning.js +1 -1
- package/src/gates/g4-qa-implementation.js +1 -1
- package/src/health/engine.js +7 -12
- package/src/installer/core.js +54 -16
- package/src/installer/templates.js +131 -2
- package/src/installer/validator.js +5 -3
- package/src/intelligence/registry-manager.js +2 -2
- package/src/preview/detector.js +1 -1
- package/src/terminal/adapters/claude-adapter.js +3 -13
- package/src/terminal/adapters/codex-adapter.js +3 -13
- package/src/terminal/adapters/copilot-adapter.js +3 -13
- package/src/terminal/adapters/gemini-adapter.js +3 -17
- package/src/terminal/cli-registry.js +20 -48
- package/src/terminal/prompt-builder.js +4 -18
- package/src/terminal/run-agent.js +2 -1
- package/src/terminal/spawner.js +27 -7
- package/src/terminal/wave-analyzer.js +1 -1
- package/src/utils/config-parser.js +97 -0
- package/src/wizard/feedback.js +1 -1
- package/src/wizard/i18n.js +11 -4
- package/src/wizard/index.js +22 -10
- package/src/wizard/questions.js +50 -2
package/src/health/engine.js
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* Constitution Article XIV — Framework Registry Governance.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { existsSync, readFileSync
|
|
9
|
+
import { existsSync, readFileSync } from 'fs';
|
|
10
10
|
import { join } from 'path';
|
|
11
|
+
import { isCommandAvailable, parseProviderConfig } from '../utils/config-parser.js';
|
|
11
12
|
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Check Result Types
|
|
@@ -50,19 +51,13 @@ export async function checkCliAvailability(projectDir) {
|
|
|
50
51
|
return { name: 'cli-availability', status: 'warn', message: 'No config.yaml found', duration: Date.now() - start };
|
|
51
52
|
}
|
|
52
53
|
|
|
53
|
-
const
|
|
54
|
-
const providers = ['claude', 'gemini', 'codex', 'copilot'];
|
|
54
|
+
const { enabled } = parseProviderConfig(projectDir);
|
|
55
55
|
const missing = [];
|
|
56
56
|
|
|
57
|
-
for (const provider of
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
try {
|
|
62
|
-
execSync(`which ${provider}`, { stdio: 'ignore' });
|
|
63
|
-
} catch {
|
|
64
|
-
missing.push(provider);
|
|
65
|
-
}
|
|
57
|
+
for (const provider of enabled) {
|
|
58
|
+
const available = await isCommandAvailable(provider);
|
|
59
|
+
if (!available) {
|
|
60
|
+
missing.push(provider);
|
|
66
61
|
}
|
|
67
62
|
}
|
|
68
63
|
|
package/src/installer/core.js
CHANGED
|
@@ -3,7 +3,8 @@ import { join, dirname } from 'path';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { IDE_CONFIGS } from '../config/ide-configs.js';
|
|
5
5
|
import { generateClaudeMCPConfig } from '../config/mcp-configs.js';
|
|
6
|
-
import { generateSessionYaml, generateConfigYaml, generateClaudeMd, generateClaudeLocalMd } from './templates.js';
|
|
6
|
+
import { generateSessionYaml, generateConfigYaml, generateClaudeMd, generateClaudeLocalMd, generateGeminiRouter, generateCopilotAgent } from './templates.js';
|
|
7
|
+
import { generateContextFiles } from '../config/context-file-generator.js';
|
|
7
8
|
import { verifyManifest } from './manifest.js';
|
|
8
9
|
|
|
9
10
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -18,7 +19,7 @@ const FRAMEWORK_SOURCE = existsSync(BUNDLED_SOURCE) ? BUNDLED_SOURCE : MONOREPO_
|
|
|
18
19
|
* Install Chati.dev framework into target directory
|
|
19
20
|
*/
|
|
20
21
|
export async function installFramework(config) {
|
|
21
|
-
const { targetDir, projectType, language, selectedIDEs, selectedMCPs, projectName, version } = config;
|
|
22
|
+
const { targetDir, projectType, language, selectedIDEs, selectedMCPs, projectName, version, llmProvider } = config;
|
|
22
23
|
|
|
23
24
|
// 0. Verify framework signature (supply chain protection)
|
|
24
25
|
const manifestPath = join(FRAMEWORK_SOURCE, 'manifest.json');
|
|
@@ -38,7 +39,7 @@ export async function installFramework(config) {
|
|
|
38
39
|
createDir(join(targetDir, '.chati'));
|
|
39
40
|
writeFileSync(
|
|
40
41
|
join(targetDir, '.chati', 'session.yaml'),
|
|
41
|
-
generateSessionYaml({ projectName, projectType, language, selectedIDEs, selectedMCPs }),
|
|
42
|
+
generateSessionYaml({ projectName, projectType, language, selectedIDEs, selectedMCPs, llmProvider }),
|
|
42
43
|
'utf-8'
|
|
43
44
|
);
|
|
44
45
|
|
|
@@ -91,7 +92,7 @@ export async function installFramework(config) {
|
|
|
91
92
|
// Write config.yaml
|
|
92
93
|
writeFileSync(
|
|
93
94
|
join(frameworkDir, 'config.yaml'),
|
|
94
|
-
generateConfigYaml({ version, projectType, language, selectedIDEs }),
|
|
95
|
+
generateConfigYaml({ version, projectType, language, selectedIDEs, llmProvider }),
|
|
95
96
|
'utf-8'
|
|
96
97
|
);
|
|
97
98
|
|
|
@@ -101,13 +102,13 @@ export async function installFramework(config) {
|
|
|
101
102
|
}
|
|
102
103
|
|
|
103
104
|
// 4. Copy context files to .claude/rules/chati/ (auto-loaded by Claude Code)
|
|
104
|
-
const rulesDir = join(targetDir, '.claude', 'rules', 'chati');
|
|
105
|
-
createDir(rulesDir);
|
|
106
105
|
const contextFiles = ['root.md', 'governance.md', 'protocols.md', 'quality.md'];
|
|
106
|
+
const claudeRulesDir = join(targetDir, '.claude', 'rules', 'chati');
|
|
107
|
+
createDir(claudeRulesDir);
|
|
107
108
|
for (const file of contextFiles) {
|
|
108
109
|
const src = join(FRAMEWORK_SOURCE, 'context', file);
|
|
109
110
|
if (existsSync(src)) {
|
|
110
|
-
copyFileSync(src, join(
|
|
111
|
+
copyFileSync(src, join(claudeRulesDir, file));
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
|
|
@@ -124,6 +125,14 @@ export async function installFramework(config) {
|
|
|
124
125
|
generateClaudeLocalMd(),
|
|
125
126
|
'utf-8'
|
|
126
127
|
);
|
|
128
|
+
|
|
129
|
+
// 7. Generate context files for non-Claude providers (GEMINI.md, AGENTS.md)
|
|
130
|
+
// Copilot CLI natively reads AGENTS.md + CLAUDE.md + GEMINI.md — no separate COPILOT.md needed.
|
|
131
|
+
const hasNonClaudeProvider = (llmProvider && llmProvider !== 'claude') ||
|
|
132
|
+
selectedIDEs.some(ide => ['gemini-cli', 'github-copilot'].includes(ide));
|
|
133
|
+
if (hasNonClaudeProvider) {
|
|
134
|
+
generateContextFiles(targetDir);
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
/**
|
|
@@ -157,12 +166,14 @@ function copyFrameworkFiles(destDir) {
|
|
|
157
166
|
'templates/fullstack-architecture-tmpl.yaml',
|
|
158
167
|
'templates/task-tmpl.yaml',
|
|
159
168
|
'templates/qa-gate-tmpl.yaml',
|
|
169
|
+
'templates/quick-brief-tmpl.yaml',
|
|
160
170
|
// Workflows
|
|
161
171
|
'workflows/greenfield-fullstack.yaml',
|
|
162
172
|
'workflows/brownfield-fullstack.yaml',
|
|
163
173
|
'workflows/brownfield-discovery.yaml',
|
|
164
174
|
'workflows/brownfield-service.yaml',
|
|
165
175
|
'workflows/brownfield-ui.yaml',
|
|
176
|
+
'workflows/quick-flow.yaml',
|
|
166
177
|
// Quality gates
|
|
167
178
|
'quality-gates/planning-gate.md',
|
|
168
179
|
'quality-gates/implementation-gate.md',
|
|
@@ -191,6 +202,7 @@ function copyFrameworkFiles(destDir) {
|
|
|
191
202
|
'hooks/session-digest.js',
|
|
192
203
|
'hooks/model-governance.js',
|
|
193
204
|
'hooks/settings.json',
|
|
205
|
+
'hooks/read-protection.js',
|
|
194
206
|
// Domains (PRISM Context Engine)
|
|
195
207
|
'domains/constitution.yaml',
|
|
196
208
|
'domains/global.yaml',
|
|
@@ -212,6 +224,7 @@ function copyFrameworkFiles(destDir) {
|
|
|
212
224
|
'domains/workflows/brownfield-discovery.yaml',
|
|
213
225
|
'domains/workflows/brownfield-service.yaml',
|
|
214
226
|
'domains/workflows/brownfield-ui.yaml',
|
|
227
|
+
'domains/workflows/quick-flow.yaml',
|
|
215
228
|
// i18n
|
|
216
229
|
'i18n/en.yaml',
|
|
217
230
|
'i18n/pt.yaml',
|
|
@@ -294,10 +307,32 @@ Pass through all context: session state, handoffs, artifacts, and user input.
|
|
|
294
307
|
'utf-8'
|
|
295
308
|
);
|
|
296
309
|
}
|
|
310
|
+
} else if (ideKey === 'gemini-cli') {
|
|
311
|
+
// Gemini CLI: TOML command file (native format for /chati command)
|
|
312
|
+
writeFileSync(join(targetDir, '.gemini', 'commands', 'chati.toml'), generateGeminiRouter(), 'utf-8');
|
|
313
|
+
} else if (ideKey === 'github-copilot') {
|
|
314
|
+
// GitHub Copilot: agent file (.github/agents/chati.md) for @chati invocation
|
|
315
|
+
writeFileSync(join(targetDir, '.github', 'agents', 'chati.md'), generateCopilotAgent(), 'utf-8');
|
|
316
|
+
|
|
317
|
+
// Copilot instructions file (auto-loaded by Copilot CLI)
|
|
318
|
+
createDir(dirname(join(targetDir, config.rulesFile)));
|
|
319
|
+
writeFileSync(join(targetDir, config.rulesFile), generateProviderInstructions(config.name), 'utf-8');
|
|
297
320
|
} else {
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
321
|
+
// VS Code, Cursor, AntiGravity — generic rules file
|
|
322
|
+
if (config.rulesFile) {
|
|
323
|
+
createDir(dirname(join(targetDir, config.rulesFile)));
|
|
324
|
+
writeFileSync(join(targetDir, config.rulesFile), generateProviderInstructions(config.name), 'utf-8');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Generate provider-agnostic instructions file content.
|
|
331
|
+
* Used for non-Claude IDEs (.github/copilot-instructions.md, .vscode/chati/rules.md, etc.)
|
|
332
|
+
*/
|
|
333
|
+
function generateProviderInstructions(providerName) {
|
|
334
|
+
return `# Chati.dev System Rules
|
|
335
|
+
# This file configures ${providerName} to work with Chati.dev
|
|
301
336
|
|
|
302
337
|
## System Location
|
|
303
338
|
All system content is in the \`chati.dev/\` directory.
|
|
@@ -310,7 +345,15 @@ The orchestrator is at \`chati.dev/orchestrator/chati.md\`.
|
|
|
310
345
|
Read it to understand routing, session management, and agent activation.
|
|
311
346
|
|
|
312
347
|
## Constitution
|
|
313
|
-
Governance rules are in \`chati.dev/constitution.md\` (
|
|
348
|
+
Governance rules are in \`chati.dev/constitution.md\` (19 Articles).
|
|
349
|
+
|
|
350
|
+
## Pipeline
|
|
351
|
+
\`\`\`
|
|
352
|
+
DISCOVER: WU -> Brief
|
|
353
|
+
PLAN: Detail -> Architect -> UX -> Phases -> Tasks -> QA-Planning
|
|
354
|
+
BUILD: Dev -> QA-Implementation
|
|
355
|
+
DEPLOY: DevOps
|
|
356
|
+
\`\`\`
|
|
314
357
|
|
|
315
358
|
## Agents
|
|
316
359
|
- DISCOVER: chati.dev/agents/discover/ (3 agents)
|
|
@@ -319,11 +362,6 @@ Governance rules are in \`chati.dev/constitution.md\` (17 Articles).
|
|
|
319
362
|
- BUILD: chati.dev/agents/build/ (1 agent)
|
|
320
363
|
- DEPLOY: chati.dev/agents/deploy/ (1 agent)
|
|
321
364
|
`;
|
|
322
|
-
if (config.rulesFile) {
|
|
323
|
-
createDir(dirname(join(targetDir, config.rulesFile)));
|
|
324
|
-
writeFileSync(join(targetDir, config.rulesFile), rulesContent, 'utf-8');
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
365
|
}
|
|
328
366
|
|
|
329
367
|
/**
|
|
@@ -4,7 +4,7 @@ import yaml from 'js-yaml';
|
|
|
4
4
|
* Generate session.yaml content
|
|
5
5
|
*/
|
|
6
6
|
export function generateSessionYaml(config) {
|
|
7
|
-
const { projectName, projectType, language, selectedIDEs, selectedMCPs } = config;
|
|
7
|
+
const { projectName, projectType, language, selectedIDEs, selectedMCPs, llmProvider } = config;
|
|
8
8
|
|
|
9
9
|
const session = {
|
|
10
10
|
project: {
|
|
@@ -13,16 +13,19 @@ export function generateSessionYaml(config) {
|
|
|
13
13
|
state: 'discover',
|
|
14
14
|
},
|
|
15
15
|
execution_mode: 'interactive',
|
|
16
|
+
execution_profile: 'guided',
|
|
16
17
|
current_agent: '',
|
|
17
18
|
language: language,
|
|
18
19
|
ides: selectedIDEs,
|
|
19
20
|
mcps: selectedMCPs,
|
|
21
|
+
providers_enabled: [llmProvider || 'claude'],
|
|
20
22
|
user_level: 'auto',
|
|
21
23
|
user_level_confidence: 0.0,
|
|
22
24
|
agents: {},
|
|
23
25
|
backlog: [],
|
|
24
26
|
last_handoff: '',
|
|
25
27
|
deviations: [],
|
|
28
|
+
profile_transitions: [],
|
|
26
29
|
};
|
|
27
30
|
|
|
28
31
|
// Initialize all 12 agent statuses
|
|
@@ -44,11 +47,56 @@ export function generateSessionYaml(config) {
|
|
|
44
47
|
return yaml.dump(session, { lineWidth: -1, quotingType: '"', forceQuotes: false });
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Optimal model assignments per provider.
|
|
52
|
+
* Deep reasoning agents (architect, qa, dev, detail, brownfield-wu) get the top model.
|
|
53
|
+
* Lightweight agents (brief, phases, ux, greenfield-wu, devops, orchestrator) get the fast model.
|
|
54
|
+
*/
|
|
55
|
+
const PROVIDER_MODEL_MAPS = {
|
|
56
|
+
claude: {
|
|
57
|
+
deep: 'opus', light: 'sonnet', minimal: 'haiku',
|
|
58
|
+
agents: {
|
|
59
|
+
orchestrator: 'sonnet', 'greenfield-wu': 'haiku', 'brownfield-wu': 'opus',
|
|
60
|
+
brief: 'sonnet', detail: 'opus', architect: 'opus', ux: 'sonnet',
|
|
61
|
+
phases: 'sonnet', tasks: 'sonnet', 'qa-planning': 'opus',
|
|
62
|
+
dev: 'opus', 'qa-implementation': 'opus', devops: 'sonnet',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
gemini: {
|
|
66
|
+
deep: 'pro', light: 'flash', minimal: 'flash',
|
|
67
|
+
agents: {
|
|
68
|
+
orchestrator: 'flash', 'greenfield-wu': 'flash', 'brownfield-wu': 'pro',
|
|
69
|
+
brief: 'flash', detail: 'pro', architect: 'pro', ux: 'flash',
|
|
70
|
+
phases: 'flash', tasks: 'flash', 'qa-planning': 'pro',
|
|
71
|
+
dev: 'pro', 'qa-implementation': 'pro', devops: 'flash',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
codex: {
|
|
75
|
+
deep: 'codex', light: 'mini', minimal: 'mini',
|
|
76
|
+
agents: {
|
|
77
|
+
orchestrator: 'mini', 'greenfield-wu': 'mini', 'brownfield-wu': 'codex',
|
|
78
|
+
brief: 'mini', detail: 'codex', architect: 'codex', ux: 'mini',
|
|
79
|
+
phases: 'mini', tasks: 'mini', 'qa-planning': 'codex',
|
|
80
|
+
dev: 'codex', 'qa-implementation': 'codex', devops: 'mini',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
copilot: {
|
|
84
|
+
deep: 'claude-sonnet', light: 'claude-sonnet', minimal: 'gpt-5',
|
|
85
|
+
agents: {
|
|
86
|
+
orchestrator: 'claude-sonnet', 'greenfield-wu': 'gpt-5', 'brownfield-wu': 'claude-sonnet',
|
|
87
|
+
brief: 'claude-sonnet', detail: 'claude-sonnet', architect: 'claude-sonnet', ux: 'claude-sonnet',
|
|
88
|
+
phases: 'claude-sonnet', tasks: 'claude-sonnet', 'qa-planning': 'claude-sonnet',
|
|
89
|
+
dev: 'claude-sonnet', 'qa-implementation': 'claude-sonnet', devops: 'claude-sonnet',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
47
94
|
/**
|
|
48
95
|
* Generate config.yaml content
|
|
49
96
|
*/
|
|
50
97
|
export function generateConfigYaml(config) {
|
|
51
|
-
const { version, projectType, language, selectedIDEs } = config;
|
|
98
|
+
const { version, projectType, language, selectedIDEs, llmProvider } = config;
|
|
99
|
+
const provider = llmProvider || 'claude';
|
|
52
100
|
|
|
53
101
|
const configData = {
|
|
54
102
|
version: version,
|
|
@@ -58,8 +106,25 @@ export function generateConfigYaml(config) {
|
|
|
58
106
|
project_type: projectType,
|
|
59
107
|
language: language,
|
|
60
108
|
ides: selectedIDEs,
|
|
109
|
+
providers: {
|
|
110
|
+
claude: { enabled: true, primary: provider === 'claude' },
|
|
111
|
+
gemini: { enabled: provider === 'gemini' || selectedIDEs.includes('gemini-cli'), model_default: 'pro', primary: provider === 'gemini' },
|
|
112
|
+
codex: { enabled: provider === 'codex', model_default: 'codex', primary: provider === 'codex' },
|
|
113
|
+
copilot: { enabled: provider === 'copilot' || selectedIDEs.includes('github-copilot'), primary: provider === 'copilot' },
|
|
114
|
+
},
|
|
61
115
|
};
|
|
62
116
|
|
|
117
|
+
// Add agent_overrides with optimal model map for the selected provider
|
|
118
|
+
if (provider !== 'claude') {
|
|
119
|
+
const modelMap = PROVIDER_MODEL_MAPS[provider];
|
|
120
|
+
if (modelMap) {
|
|
121
|
+
configData.agent_overrides = {};
|
|
122
|
+
for (const [agent, model] of Object.entries(modelMap.agents)) {
|
|
123
|
+
configData.agent_overrides[agent] = { provider, model };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
63
128
|
return yaml.dump(configData, { lineWidth: -1, quotingType: '"', forceQuotes: false });
|
|
64
129
|
}
|
|
65
130
|
|
|
@@ -81,6 +146,70 @@ Type \`/chati\` to start.
|
|
|
81
146
|
`;
|
|
82
147
|
}
|
|
83
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Generate Gemini CLI TOML command (.gemini/commands/chati.toml)
|
|
151
|
+
*
|
|
152
|
+
* Gemini CLI custom commands use TOML format with `description` and `prompt` fields.
|
|
153
|
+
* Supports {{args}} for user arguments and @{file} for file injection.
|
|
154
|
+
*/
|
|
155
|
+
export function generateGeminiRouter() {
|
|
156
|
+
return `description = "Activate Chati.dev orchestrator"
|
|
157
|
+
prompt = """
|
|
158
|
+
CRITICAL — Language Override:
|
|
159
|
+
Read \`.chati/session.yaml\` field \`language\` BEFORE anything else.
|
|
160
|
+
ALL responses MUST be in this language (en, pt, es, fr).
|
|
161
|
+
If session.yaml does not exist or has no language field, default to English.
|
|
162
|
+
|
|
163
|
+
Read and execute the full orchestrator at \`chati.dev/orchestrator/chati.md\`.
|
|
164
|
+
|
|
165
|
+
Context to load:
|
|
166
|
+
- \`.chati/session.yaml\` (session state — includes language)
|
|
167
|
+
- \`chati.dev/artifacts/handoffs/\` (latest handoff)
|
|
168
|
+
- \`chati.dev/config.yaml\` (version info)
|
|
169
|
+
|
|
170
|
+
User input: {{args}}
|
|
171
|
+
"""
|
|
172
|
+
`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Generate GitHub Copilot agent file (.github/agents/chati.md)
|
|
177
|
+
*
|
|
178
|
+
* Copilot CLI uses .github/agents/*.md for custom agents.
|
|
179
|
+
* The user invokes with @chati in the Copilot CLI.
|
|
180
|
+
*/
|
|
181
|
+
export function generateCopilotAgent() {
|
|
182
|
+
return `# Chati.dev Orchestrator
|
|
183
|
+
|
|
184
|
+
You are the Chati.dev orchestrator agent for GitHub Copilot CLI.
|
|
185
|
+
|
|
186
|
+
## CRITICAL — Language Override
|
|
187
|
+
|
|
188
|
+
Read \`.chati/session.yaml\` field \`language\` BEFORE anything else.
|
|
189
|
+
ALL responses MUST be in this language. This overrides any global setting.
|
|
190
|
+
|
|
191
|
+
| Value | Language |
|
|
192
|
+
|-------|----------|
|
|
193
|
+
| \`en\` | English |
|
|
194
|
+
| \`pt\` | Portugues |
|
|
195
|
+
| \`es\` | Espanol |
|
|
196
|
+
| \`fr\` | Francais |
|
|
197
|
+
|
|
198
|
+
If session.yaml does not exist or has no language field, default to English.
|
|
199
|
+
|
|
200
|
+
## Load
|
|
201
|
+
|
|
202
|
+
Read and execute the full orchestrator at \`chati.dev/orchestrator/chati.md\`.
|
|
203
|
+
|
|
204
|
+
Pass through all context: session state, handoffs, artifacts, and user input.
|
|
205
|
+
|
|
206
|
+
**Context to pass:**
|
|
207
|
+
- \`.chati/session.yaml\` (session state — includes language)
|
|
208
|
+
- \`chati.dev/artifacts/handoffs/\` (latest handoff)
|
|
209
|
+
- \`chati.dev/config.yaml\` (version info)
|
|
210
|
+
`;
|
|
211
|
+
}
|
|
212
|
+
|
|
84
213
|
/**
|
|
85
214
|
* Generate CLAUDE.local.md content (runtime state — auto-gitignored, never committed)
|
|
86
215
|
*/
|
|
@@ -63,7 +63,7 @@ export async function validateInstallation(targetDir) {
|
|
|
63
63
|
if (existsSync(constitutionPath)) {
|
|
64
64
|
const content = readFileSync(constitutionPath, 'utf-8');
|
|
65
65
|
const articleCount = (content.match(/^## Article/gm) || []).length;
|
|
66
|
-
results.constitution.pass = articleCount >=
|
|
66
|
+
results.constitution.pass = articleCount >= 19;
|
|
67
67
|
results.constitution.details.push({ articleCount });
|
|
68
68
|
}
|
|
69
69
|
results.total += 1;
|
|
@@ -94,6 +94,7 @@ export async function validateInstallation(targetDir) {
|
|
|
94
94
|
const workflowFiles = [
|
|
95
95
|
'greenfield-fullstack.yaml', 'brownfield-fullstack.yaml',
|
|
96
96
|
'brownfield-discovery.yaml', 'brownfield-service.yaml', 'brownfield-ui.yaml',
|
|
97
|
+
'quick-flow.yaml',
|
|
97
98
|
];
|
|
98
99
|
let workflowCount = 0;
|
|
99
100
|
for (const file of workflowFiles) {
|
|
@@ -101,7 +102,7 @@ export async function validateInstallation(targetDir) {
|
|
|
101
102
|
workflowCount++;
|
|
102
103
|
}
|
|
103
104
|
}
|
|
104
|
-
results.workflows.pass = workflowCount ===
|
|
105
|
+
results.workflows.pass = workflowCount === 6;
|
|
105
106
|
results.total += 1;
|
|
106
107
|
if (results.workflows.pass) results.passed += 1;
|
|
107
108
|
|
|
@@ -109,6 +110,7 @@ export async function validateInstallation(targetDir) {
|
|
|
109
110
|
const templateFiles = [
|
|
110
111
|
'prd-tmpl.yaml', 'brownfield-prd-tmpl.yaml',
|
|
111
112
|
'fullstack-architecture-tmpl.yaml', 'task-tmpl.yaml', 'qa-gate-tmpl.yaml',
|
|
113
|
+
'quick-brief-tmpl.yaml',
|
|
112
114
|
];
|
|
113
115
|
let templateCount = 0;
|
|
114
116
|
for (const file of templateFiles) {
|
|
@@ -116,7 +118,7 @@ export async function validateInstallation(targetDir) {
|
|
|
116
118
|
templateCount++;
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
|
-
results.templates.pass = templateCount ===
|
|
121
|
+
results.templates.pass = templateCount === 6;
|
|
120
122
|
results.total += 1;
|
|
121
123
|
if (results.templates.pass) results.passed += 1;
|
|
122
124
|
|
|
@@ -131,8 +131,8 @@ export function runHealthCheck(targetDir) {
|
|
|
131
131
|
if (existsSync(constitutionPath)) {
|
|
132
132
|
const content = readFileSync(constitutionPath, 'utf-8');
|
|
133
133
|
const articleCount = (content.match(/^## Article/gm) || []).length;
|
|
134
|
-
checks.constitution.pass = articleCount >=
|
|
135
|
-
checks.constitution.details = `${articleCount}/
|
|
134
|
+
checks.constitution.pass = articleCount >= 19;
|
|
135
|
+
checks.constitution.details = `${articleCount}/19 articles`;
|
|
136
136
|
} else {
|
|
137
137
|
checks.constitution.details = 'Not found';
|
|
138
138
|
}
|
package/src/preview/detector.js
CHANGED
|
@@ -191,7 +191,7 @@ export function detectProjectKind(projectDir) {
|
|
|
191
191
|
* @returns {{ command: string, args: string[], description: string, framework: string, defaultPort: number }}
|
|
192
192
|
*/
|
|
193
193
|
function resolveFrameworkCommand(projectDir, detector) {
|
|
194
|
-
const { framework, defaultPort
|
|
194
|
+
const { framework, defaultPort } = detector;
|
|
195
195
|
|
|
196
196
|
// Django has its own command
|
|
197
197
|
if (framework === 'django') {
|
|
@@ -18,26 +18,16 @@
|
|
|
18
18
|
* @returns {{ command: string, args: string[], stdinPrompt: string|null }}
|
|
19
19
|
*/
|
|
20
20
|
export function buildCommand(config, provider) {
|
|
21
|
-
const args = [
|
|
21
|
+
const args = [...provider.baseArgs];
|
|
22
22
|
|
|
23
23
|
if (config.model) {
|
|
24
24
|
const resolvedModel = provider.modelMap[config.model] || config.model;
|
|
25
|
-
args.push(
|
|
25
|
+
args.push(provider.modelFlag, resolvedModel);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
return {
|
|
29
|
-
command:
|
|
29
|
+
command: provider.command,
|
|
30
30
|
args,
|
|
31
31
|
stdinPrompt: config.prompt || null,
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Build environment variables specific to Claude Code.
|
|
37
|
-
*
|
|
38
|
-
* @param {SpawnConfig} config
|
|
39
|
-
* @returns {Record<string, string>}
|
|
40
|
-
*/
|
|
41
|
-
export function buildEnv(config) {
|
|
42
|
-
return {};
|
|
43
|
-
}
|
|
@@ -13,29 +13,19 @@
|
|
|
13
13
|
* @returns {{ command: string, args: string[], stdinPrompt: string|null }}
|
|
14
14
|
*/
|
|
15
15
|
export function buildCommand(config, provider) {
|
|
16
|
-
const args = [
|
|
16
|
+
const args = [...provider.baseArgs];
|
|
17
17
|
|
|
18
18
|
if (config.model) {
|
|
19
19
|
const resolvedModel = provider.modelMap[config.model] || config.model;
|
|
20
|
-
args.push(
|
|
20
|
+
args.push(provider.modelFlag, resolvedModel);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Codex exec reads prompt from stdin when `-` is passed
|
|
24
24
|
args.push('-');
|
|
25
25
|
|
|
26
26
|
return {
|
|
27
|
-
command:
|
|
27
|
+
command: provider.command,
|
|
28
28
|
args,
|
|
29
29
|
stdinPrompt: config.prompt || null,
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Build environment variables specific to Codex CLI.
|
|
35
|
-
*
|
|
36
|
-
* @param {import('../spawner.js').SpawnConfig} config
|
|
37
|
-
* @returns {Record<string, string>}
|
|
38
|
-
*/
|
|
39
|
-
export function buildEnv(config) {
|
|
40
|
-
return {};
|
|
41
|
-
}
|
|
@@ -13,26 +13,16 @@
|
|
|
13
13
|
* @returns {{ command: string, args: string[], stdinPrompt: string|null }}
|
|
14
14
|
*/
|
|
15
15
|
export function buildCommand(config, provider) {
|
|
16
|
-
const args = [
|
|
16
|
+
const args = [...provider.baseArgs];
|
|
17
17
|
|
|
18
18
|
if (config.model) {
|
|
19
19
|
const resolvedModel = provider.modelMap[config.model] || config.model;
|
|
20
|
-
args.push(
|
|
20
|
+
args.push(provider.modelFlag, resolvedModel);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
return {
|
|
24
|
-
command:
|
|
24
|
+
command: provider.command,
|
|
25
25
|
args,
|
|
26
26
|
stdinPrompt: config.prompt || null,
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Build environment variables specific to Copilot CLI.
|
|
32
|
-
*
|
|
33
|
-
* @param {import('../spawner.js').SpawnConfig} config
|
|
34
|
-
* @returns {Record<string, string>}
|
|
35
|
-
*/
|
|
36
|
-
export function buildEnv(config) {
|
|
37
|
-
return {};
|
|
38
|
-
}
|
|
@@ -13,30 +13,16 @@
|
|
|
13
13
|
* @returns {{ command: string, args: string[], stdinPrompt: string|null }}
|
|
14
14
|
*/
|
|
15
15
|
export function buildCommand(config, provider) {
|
|
16
|
-
const args = [];
|
|
16
|
+
const args = [...provider.baseArgs];
|
|
17
17
|
|
|
18
18
|
if (config.model) {
|
|
19
19
|
const resolvedModel = provider.modelMap[config.model] || config.model;
|
|
20
|
-
args.push(
|
|
20
|
+
args.push(provider.modelFlag, resolvedModel);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
// Gemini CLI uses --prompt for non-interactive mode
|
|
24
|
-
// When stdin is piped, Gemini reads from stdin automatically
|
|
25
|
-
args.push('--prompt');
|
|
26
|
-
|
|
27
23
|
return {
|
|
28
|
-
command:
|
|
24
|
+
command: provider.command,
|
|
29
25
|
args,
|
|
30
26
|
stdinPrompt: config.prompt || null,
|
|
31
27
|
};
|
|
32
28
|
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Build environment variables specific to Gemini CLI.
|
|
36
|
-
*
|
|
37
|
-
* @param {import('../spawner.js').SpawnConfig} config
|
|
38
|
-
* @returns {Record<string, string>}
|
|
39
|
-
*/
|
|
40
|
-
export function buildEnv(config) {
|
|
41
|
-
return {};
|
|
42
|
-
}
|