chati-dev 4.5.13 → 4.5.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/framework/agents/build/dev.md +4 -5
- package/framework/agents/deploy/devops.md +9 -10
- package/framework/agents/discover/brief.md +7 -13
- package/framework/agents/discover/brownfield-wu.md +5 -11
- package/framework/agents/discover/greenfield-wu.md +7 -12
- package/framework/agents/plan/architect.md +1 -1
- package/framework/agents/plan/detail.md +5 -5
- package/framework/agents/plan/phases.md +4 -5
- package/framework/agents/plan/tasks.md +4 -5
- package/framework/agents/plan/ux-brand-architect.md +1 -1
- package/framework/agents/plan/ux.md +1 -1
- package/framework/agents/quality/qa-implementation.md +4 -5
- package/framework/agents/quality/qa-planning.md +4 -5
- package/framework/agents/quality/qa-visual.md +4 -4
- package/framework/agents/shared/visualizer.md +1 -1
- package/framework/config.yaml +5 -5
- package/framework/constitution.md +24 -26
- package/framework/context/governance.md +6 -6
- package/framework/context/root.md +4 -3
- package/framework/data/entity-registry.yaml +3 -3
- package/framework/data/model-limits.json +5 -2
- package/framework/hooks/model-governance.js +3 -2
- package/framework/hooks/prism-engine.js +1 -1
- package/framework/i18n/en.yaml +6 -2
- package/framework/i18n/es.yaml +6 -2
- package/framework/i18n/fr.yaml +6 -2
- package/framework/i18n/pt.yaml +6 -2
- package/framework/intelligence/context-engine.md +12 -16
- package/framework/manifest.json +63 -63
- package/framework/manifest.sig +1 -1
- package/framework/orchestrator/chati-router.js +40 -6
- package/framework/orchestrator/chati.md +12 -13
- package/framework/schemas/session.schema.json +1 -1
- package/package.json +1 -1
- package/src/config/context-file-generator.js +54 -246
- package/src/config/framework-adapter.js +45 -208
- package/src/context/bracket-tracker.js +3 -3
- package/src/context/engine.js +1 -1
- package/src/installer/core.js +190 -66
- package/src/installer/provider-overlay.js +1 -1
- package/src/installer/templates.js +55 -65
- package/src/installer-v2/index.js +2 -0
- package/src/memory/magic-docs.js +45 -26
- package/src/orchestrator/cli.js +50 -45
- package/src/orchestrator/handoff-engine.js +7 -5
- package/src/orchestrator/session-manager.js +24 -3
- package/src/terminal/cli-registry.js +5 -5
- package/src/terminal/prompt-builder.js +14 -10
- package/src/terminal/run-agent.js +10 -6
- package/src/terminal/run-parallel.js +6 -2
- package/src/terminal/run-team.js +7 -2
- package/src/terminal/spawner.js +34 -42
- package/src/utils/config-parser.js +2 -2
- package/src/utils/provider-limits.js +3 -1
- package/src/wizard/feedback.js +11 -0
- package/src/wizard/i18n.js +6 -2
- package/src/wizard/index.js +17 -7
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Native harness overlays over a provider-neutral framework.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Constitution Article XIX — framework files are pre-adapted per provider.
|
|
4
|
+
* Shared framework documents contain only Chati invariants and routing
|
|
5
|
+
* contracts. Provider overlays add mechanics that genuinely belong to a
|
|
6
|
+
* harness. They never translate another provider's instructions.
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
|
-
import { PROVIDER_MODEL_MAPS } from '../installer/templates.js';
|
|
12
|
-
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
// Adaptable Files
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Set of framework file paths (relative to chati.dev/) that need
|
|
19
|
-
* provider-specific adaptation when the selected provider is not Claude.
|
|
20
|
-
*/
|
|
21
9
|
export const ADAPTABLE_FILES = new Set([
|
|
22
10
|
'constitution.md',
|
|
23
11
|
'orchestrator/chati.md',
|
|
@@ -36,217 +24,66 @@ export const ADAPTABLE_FILES = new Set([
|
|
|
36
24
|
'agents/deploy/devops.md',
|
|
37
25
|
'context/governance.md',
|
|
38
26
|
'context/root.md',
|
|
27
|
+
'domains/agents/orchestrator.yaml',
|
|
28
|
+
'tasks/orchestrator-escalate.md',
|
|
29
|
+
'tasks/orchestrator-route.md',
|
|
30
|
+
'tasks/orchestrator-status.md',
|
|
31
|
+
'tasks/qa-planning-risk-matrix.md',
|
|
32
|
+
'tasks/qa-planning-test-strategy.md',
|
|
39
33
|
]);
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
localFile: '.gemini/session-lock.md',
|
|
55
|
-
},
|
|
56
|
-
codex: {
|
|
57
|
-
cliName: 'Codex CLI',
|
|
58
|
-
contextFile: 'AGENTS.md',
|
|
59
|
-
localFile: 'AGENTS.override.md',
|
|
60
|
-
},
|
|
61
|
-
grok: {
|
|
62
|
-
cliName: 'Grok CLI',
|
|
63
|
-
contextFile: 'AGENTS.md',
|
|
64
|
-
localFile: '.grok/session-lock.md',
|
|
65
|
-
},
|
|
66
|
-
};
|
|
35
|
+
export const HARNESS_PROFILES = Object.freeze({
|
|
36
|
+
claude: Object.freeze({ contextFile: 'CLAUDE.md', sessionLockFile: 'CLAUDE.local.md', invocation: '/chati' }),
|
|
37
|
+
gemini: Object.freeze({ contextFile: 'GEMINI.md', sessionLockFile: '.gemini/session-lock.md', invocation: '/chati' }),
|
|
38
|
+
codex: Object.freeze({ contextFile: 'AGENTS.md', sessionLockFile: 'AGENTS.override.md', invocation: '$chati' }),
|
|
39
|
+
grok: Object.freeze({ contextFile: 'AGENTS.md', sessionLockFile: '.grok/session-lock.md', invocation: '/chati' }),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export function stripLegacyBuildSurface(content) {
|
|
43
|
+
return content.replace(
|
|
44
|
+
/<!-- CHATI_LEGACY_BUILD_START -->[\s\S]*?<!-- CHATI_LEGACY_BUILD_END -->\s*/g,
|
|
45
|
+
'For installations without `.chati/v2/installation.json`, use the separately bundled legacy compatibility runtime.\n\n',
|
|
46
|
+
);
|
|
47
|
+
}
|
|
67
48
|
|
|
68
49
|
const CODEX_CREDENTIAL_BOUNDARY = `
|
|
69
50
|
## Codex external provider credential boundary
|
|
70
51
|
|
|
71
52
|
Commands returned in any \`spawn_command\`, \`parallel_spawn_command\` or
|
|
72
53
|
\`parallel_spawn_commands\` start another provider CLI. Codex MUST execute each
|
|
73
|
-
|
|
74
|
-
|
|
54
|
+
command through its native local execution path so the child CLI can access its
|
|
55
|
+
existing local credentials:
|
|
75
56
|
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
57
|
+
- If the active Codex host requires approval to leave a restricted workspace
|
|
58
|
+
sandbox, request the narrow native approval it exposes for the exact command.
|
|
59
|
+
- Do not invent approval fields or tool parameters that this Codex host does not
|
|
60
|
+
expose.
|
|
61
|
+
- Explain that Chati needs the selected provider CLI to use its existing local
|
|
62
|
+
authentication.
|
|
63
|
+
- Keep the project working directory and router-provided command unchanged.
|
|
82
64
|
|
|
83
65
|
Never test a routed provider command inside the workspace sandbox first. A
|
|
84
|
-
\`PROVIDER_NOT_READY\` or \`PROVIDER_NOT_AUTHENTICATED\` result obtained
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
Only a failure from that
|
|
88
|
-
failure.
|
|
89
|
-
|
|
66
|
+
\`PROVIDER_NOT_READY\` or \`PROVIDER_NOT_AUTHENTICATED\` result obtained there is
|
|
67
|
+
inconclusive because the sandbox can hide OS credentials. If a sandboxed attempt
|
|
68
|
+
already failed, rerun it once through Codex's native approved local execution
|
|
69
|
+
path. Only a failure from that attempt may be reported as an authentication
|
|
70
|
+
failure.
|
|
71
|
+
Do not repeat the same sandboxed command and do not offer to skip a required
|
|
72
|
+
v2 pipeline stage.
|
|
90
73
|
`;
|
|
91
74
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Build the complete replacement config for a given provider.
|
|
98
|
-
* Returns { strings, patterns } where:
|
|
99
|
-
* - strings: ordered [search, replace] pairs for replaceAll
|
|
100
|
-
* - patterns: { pattern, replacement } objects for regex replace
|
|
101
|
-
*
|
|
102
|
-
* Ordering: most-specific strings first to prevent partial matches.
|
|
103
|
-
*/
|
|
104
|
-
function buildReplacementConfig(provider) {
|
|
105
|
-
const meta = PROVIDER_META[provider];
|
|
106
|
-
const modelMap = PROVIDER_MODEL_MAPS[provider];
|
|
107
|
-
|
|
108
|
-
if (!meta || !modelMap) {
|
|
109
|
-
throw new Error(`Unknown provider: ${provider}`);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const { cliName, contextFile, localFile } = meta;
|
|
113
|
-
const { deep, light, minimal } = modelMap;
|
|
114
|
-
|
|
115
|
-
// --- String replacements (ordered, most specific first) ---
|
|
116
|
-
const strings = [
|
|
117
|
-
// File references (most specific first)
|
|
118
|
-
['CLAUDE.local.md', localFile],
|
|
119
|
-
['CLAUDE.md', contextFile],
|
|
120
|
-
['.claude/rules/chati/', 'chati.dev/context/'],
|
|
121
|
-
|
|
122
|
-
// Provider name (most specific first)
|
|
123
|
-
['Claude Code processes', `${cliName} processes`],
|
|
124
|
-
['Claude Code CLI', cliName],
|
|
125
|
-
['Claude Code', cliName],
|
|
126
|
-
|
|
127
|
-
// Behavioral
|
|
128
|
-
['NEVER act as generic Claude', 'NEVER act as generic AI assistant'],
|
|
129
|
-
|
|
130
|
-
// /model commands (specific model names)
|
|
131
|
-
['/model opus', `/model ${deep}`],
|
|
132
|
-
['/model sonnet', `/model ${light}`],
|
|
133
|
-
['/model haiku', `/model ${minimal}`],
|
|
134
|
-
];
|
|
135
|
-
|
|
136
|
-
// --- Regex patterns for model names in structured contexts ---
|
|
137
|
-
const patterns = [
|
|
138
|
-
// Identity section: **Model**: opus | ...
|
|
139
|
-
{ pattern: /(\*\*Model\*\*:\s*)opus/g, replacement: `$1${deep}` },
|
|
140
|
-
{ pattern: /(\*\*Model\*\*:\s*)sonnet/g, replacement: `$1${light}` },
|
|
141
|
-
{ pattern: /(\*\*Model\*\*:\s*)haiku/g, replacement: `$1${minimal}` },
|
|
142
|
-
|
|
143
|
-
// YAML-like blocks: default: sonnet, upgrade_to: opus, etc.
|
|
144
|
-
{ pattern: /(default:\s*)opus/g, replacement: `$1${deep}` },
|
|
145
|
-
{ pattern: /(default:\s*)sonnet/g, replacement: `$1${light}` },
|
|
146
|
-
{ pattern: /(default:\s*)haiku/g, replacement: `$1${minimal}` },
|
|
147
|
-
{ pattern: /(upgrade_to:\s*)opus/g, replacement: `$1${deep}` },
|
|
148
|
-
{ pattern: /(upgrade_to:\s*)sonnet/g, replacement: `$1${light}` },
|
|
149
|
-
{ pattern: /(downgrade_to:\s*)haiku/g, replacement: `$1${minimal}` },
|
|
150
|
-
{ pattern: /(downgrade_to:\s*)sonnet/g, replacement: `$1${light}` },
|
|
151
|
-
{ pattern: /(recommended:\s*)opus/g, replacement: `$1${deep}` },
|
|
152
|
-
{ pattern: /(recommended:\s*)sonnet/g, replacement: `$1${light}` },
|
|
153
|
-
{ pattern: /(actual:\s*)opus/g, replacement: `$1${deep}` },
|
|
154
|
-
{ pattern: /(actual:\s*)sonnet/g, replacement: `$1${light}` },
|
|
155
|
-
{ pattern: /(model:\s*)opus/g, replacement: `$1${deep}` },
|
|
156
|
-
{ pattern: /(model:\s*)sonnet/g, replacement: `$1${light}` },
|
|
157
|
-
|
|
158
|
-
// Table cells: | opus | or | sonnet | or | haiku |
|
|
159
|
-
{ pattern: /(\|\s*)opus(\s*\|)/g, replacement: `$1${deep}$2` },
|
|
160
|
-
{ pattern: /(\|\s*)sonnet(\s*\|)/g, replacement: `$1${light}$2` },
|
|
161
|
-
{ pattern: /(\|\s*)haiku(\s*\|)/g, replacement: `$1${minimal}$2` },
|
|
162
|
-
|
|
163
|
-
// Upgrade/downgrade conditions in prose: "sonnet if ...", "opus if ..."
|
|
164
|
-
// Negative lookbehind prevents double-prefix when deep model contains a tier name (e.g. claude-sonnet)
|
|
165
|
-
{ pattern: /(?<!-)opus if /g, replacement: `${deep} if ` },
|
|
166
|
-
{ pattern: /(?<!-)sonnet if /g, replacement: `${light} if ` },
|
|
167
|
-
{ pattern: /(?<!-)haiku if /g, replacement: `${minimal} if ` },
|
|
168
|
-
|
|
169
|
-
// Constitution/governance model tier definitions
|
|
170
|
-
{ pattern: /\*\*opus\*\*:/g, replacement: `**${deep}**:` },
|
|
171
|
-
{ pattern: /\*\*sonnet\*\*:/g, replacement: `**${light}**:` },
|
|
172
|
-
{ pattern: /\*\*haiku\*\*:/g, replacement: `**${minimal}**:` },
|
|
173
|
-
{ pattern: /opus \(deep reasoning\)/g, replacement: `${deep} (deep reasoning)` },
|
|
174
|
-
{ pattern: /sonnet \(structured\)/g, replacement: `${light} (structured)` },
|
|
175
|
-
{ pattern: /haiku \(lightweight\)/g, replacement: `${minimal} (lightweight)` },
|
|
176
|
-
|
|
177
|
-
// Provider field in agent Identity: claude (default) with optional conditional
|
|
178
|
-
{ pattern: /- \*\*Provider\*\*: claude \(default\)(?:\s*\|[^\n]*)?/g,
|
|
179
|
-
replacement: `- **Provider**: ${provider} (default)` },
|
|
180
|
-
|
|
181
|
-
// Provider in table rows: | claude (default) | or | claude (default) | gemini (...) |
|
|
182
|
-
{ pattern: /(\|\s*)claude \(default\)(?:\s*\|[^|\n]*)?\s*(\|)/g,
|
|
183
|
-
replacement: `$1${provider} (default) $2` },
|
|
184
|
-
|
|
185
|
-
// "claude" as primary provider in prose
|
|
186
|
-
{ pattern: /primary provider \(claude\)/g, replacement: `primary provider (${provider})` },
|
|
187
|
-
{ pattern: /fallback_provider: claude/g, replacement: `fallback_provider: ${provider}` },
|
|
188
|
-
{ pattern: /fall back to the primary provider \(claude\)/g,
|
|
189
|
-
replacement: `fall back to the primary provider (${provider})` },
|
|
190
|
-
{ pattern: /primary provider: claude/g, replacement: `primary provider: ${provider}` },
|
|
191
|
-
|
|
192
|
-
// /chati providers display: swap PRIMARY designation
|
|
193
|
-
// Note: "Claude Code CLI" may already be replaced by string replacements, so match any trailing text
|
|
194
|
-
{ pattern: /claude\s+PRIMARY\s+Enabled\s+.+/g,
|
|
195
|
-
replacement: `${provider} PRIMARY Enabled ${cliName}` },
|
|
196
|
-
|
|
197
|
-
// CLAUDE.md Update sections in agents
|
|
198
|
-
{ pattern: /### CLAUDE\.md Update/g, replacement: `### ${contextFile} Update` },
|
|
199
|
-
{ pattern: /### CLAUDE\.md Final Update/g, replacement: `### ${contextFile} Final Update` },
|
|
200
|
-
{ pattern: /Update CLAUDE\.md/g, replacement: `Update ${contextFile}` },
|
|
201
|
-
];
|
|
202
|
-
|
|
203
|
-
// Codex CLI uses $chati for skill invocation, not /chati.
|
|
204
|
-
// Lookbehind prevents replacing /chati in file paths (e.g., orchestrator/chati.md).
|
|
205
|
-
if (provider === 'codex') {
|
|
206
|
-
patterns.push({
|
|
207
|
-
pattern: /(?<![/\w])\/chati/g,
|
|
208
|
-
replacement: '$$chati',
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return { strings, patterns };
|
|
75
|
+
function renderNativeInvocation(content, invocation) {
|
|
76
|
+
if (invocation === '/chati') return content;
|
|
77
|
+
return content.replace(/(?<![./\w])\/chati(?![-/\w])/g, invocation);
|
|
213
78
|
}
|
|
214
79
|
|
|
215
|
-
// ---------------------------------------------------------------------------
|
|
216
|
-
// Main Adapter Function
|
|
217
|
-
// ---------------------------------------------------------------------------
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Adapt a single framework file for the target provider.
|
|
221
|
-
*
|
|
222
|
-
* @param {string} content - Original file content (Claude Code version)
|
|
223
|
-
* @param {string} filePath - Relative path within chati.dev/ (e.g. 'orchestrator/chati.md')
|
|
224
|
-
* @param {string} provider - Target provider: 'gemini', 'codex'
|
|
225
|
-
* @returns {string} Adapted content for the target provider
|
|
226
|
-
*/
|
|
227
80
|
export function adaptFrameworkFile(content, filePath, provider) {
|
|
228
81
|
if (!content) return content;
|
|
82
|
+
if (!HARNESS_PROFILES[provider]) throw new Error(`Unknown provider: ${provider}`);
|
|
229
83
|
|
|
230
|
-
let result = content;
|
|
84
|
+
let result = renderNativeInvocation(content, HARNESS_PROFILES[provider].invocation);
|
|
231
85
|
if (filePath === 'orchestrator/chati.md') {
|
|
232
|
-
result = result
|
|
233
|
-
/<!-- CHATI_LEGACY_BUILD_START -->[\s\S]*?<!-- CHATI_LEGACY_BUILD_END -->\s*/g,
|
|
234
|
-
'For installations without `.chati/v2/installation.json`, use the separately bundled legacy compatibility runtime.\n\n',
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (provider === 'claude') return result;
|
|
239
|
-
|
|
240
|
-
const config = buildReplacementConfig(provider);
|
|
241
|
-
|
|
242
|
-
// 1. Apply ordered string replacements (most specific first)
|
|
243
|
-
for (const [search, replace] of config.strings) {
|
|
244
|
-
result = result.replaceAll(search, replace);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// 2. Apply regex patterns (model names + structured contexts)
|
|
248
|
-
for (const { pattern, replacement } of config.patterns) {
|
|
249
|
-
result = result.replace(pattern, replacement);
|
|
86
|
+
result = stripLegacyBuildSurface(result);
|
|
250
87
|
}
|
|
251
88
|
|
|
252
89
|
if (provider === 'codex' && filePath === 'orchestrator/chati.md') {
|
|
@@ -38,11 +38,11 @@ const MEMORY_LEVELS = {
|
|
|
38
38
|
/**
|
|
39
39
|
* Calculate bracket from remaining context percentage.
|
|
40
40
|
* @param {number} remainingPercent - 0 to 100
|
|
41
|
-
* @param {string} [provider=
|
|
41
|
+
* @param {string|null} [provider=null] - Provider name for context window scaling
|
|
42
42
|
* @param {string} [model] - Model tier (opus, sonnet, haiku) for precise context limits
|
|
43
|
-
* @returns {{ bracket: string, activeLayers: string[], tokenBudget: number, budgetRatio: number, memoryLevel: string, handoffRequired: boolean, provider: string }}
|
|
43
|
+
* @returns {{ bracket: string, activeLayers: string[], tokenBudget: number, budgetRatio: number, memoryLevel: string, handoffRequired: boolean, provider: string|null }}
|
|
44
44
|
*/
|
|
45
|
-
export function calculateBracket(remainingPercent, provider =
|
|
45
|
+
export function calculateBracket(remainingPercent, provider = null, model) {
|
|
46
46
|
const pct = Math.max(0, Math.min(100, remainingPercent));
|
|
47
47
|
|
|
48
48
|
let name = 'CRITICAL';
|
package/src/context/engine.js
CHANGED
|
@@ -49,7 +49,7 @@ export function runPrism(input) {
|
|
|
49
49
|
const layers = [];
|
|
50
50
|
|
|
51
51
|
// 1. Calculate bracket (provider-aware for proportional budgets)
|
|
52
|
-
const bracket = calculateBracket(input.remainingPercent, input.provider ||
|
|
52
|
+
const bracket = calculateBracket(input.remainingPercent, input.provider || null);
|
|
53
53
|
|
|
54
54
|
// 2. Build context for layer processors
|
|
55
55
|
const ctx = {
|