chati-dev 4.3.0 → 4.4.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 +18 -13
- package/bin/chati.js +32 -4
- package/framework/agents/build/dev.md +9 -5
- package/framework/agents/discover/brief.md +2 -0
- package/framework/agents/discover/brownfield-wu.md +2 -0
- package/framework/agents/discover/greenfield-wu.md +18 -1
- package/framework/agents/plan/detail.md +2 -0
- package/framework/agents/plan/tasks.md +31 -0
- package/framework/agents/plan/ux-brand-architect.md +21 -2
- package/framework/agents/plan/ux-component-engineer.md +10 -0
- package/framework/agents/quality/qa-implementation.md +1 -1
- package/framework/agents/quality/qa-planning.md +1 -1
- package/framework/agents/quality/qa-visual.md +33 -21
- package/framework/config.yaml +5 -4
- package/framework/constitution.md +58 -11
- package/framework/context/governance.md +12 -10
- package/framework/context/root.md +2 -2
- package/framework/data/entity-registry.yaml +12 -4
- package/framework/data/qa-rubrics.yaml +335 -0
- package/framework/domains/constitution.yaml +3 -3
- package/framework/executors/json-validate.js +80 -0
- package/framework/executors/npm-script.js +72 -0
- package/framework/executors/path-check.js +67 -0
- package/framework/executors/registry.yaml +36 -0
- package/framework/hooks/advance-trigger.js +47 -3
- package/framework/hooks/constitution-guard.js +9 -4
- package/framework/hooks/git-push-authority.js +113 -0
- package/framework/hooks/license-guard.js +59 -9
- package/framework/hooks/model-governance.js +40 -17
- package/framework/hooks/prism-engine.js +78 -11
- package/framework/hooks/session-digest.js +12 -3
- package/framework/hooks/settings.json +7 -3
- package/framework/hooks/style-guard.js +52 -3
- package/framework/hooks/team-quality-gate.js +43 -5
- package/framework/i18n/en.yaml +3 -3
- package/framework/i18n/es.yaml +3 -3
- package/framework/i18n/fr.yaml +3 -3
- package/framework/i18n/pt.yaml +3 -3
- package/framework/intelligence/confidence.yaml +85 -6
- package/framework/intelligence/context-engine.md +9 -5
- package/framework/intelligence/decision-engine.md +1 -1
- package/framework/orchestrator/chati-router.js +59 -5
- package/framework/orchestrator/chati-update.md +19 -3
- package/framework/orchestrator/chati.md +20 -1
- package/framework/quality-gates/planning-gate.md +2 -0
- package/framework/rules/human-writing-style.md +47 -0
- package/framework/scaffold/motion-premium/README.md +12 -2
- package/framework/scaffold/motion-premium/lib/animations/tokens.ts.template +1 -1
- package/framework/scaffold/motion-premium/scaffold.yaml +6 -1
- package/framework/scaffold/motion-premium-3d/README.md +10 -0
- package/framework/scaffold/motion-premium-3d/components/webgl/WebGLContext.tsx.template +1 -1
- package/framework/scaffold/motion-premium-3d/scaffold.yaml +3 -0
- package/framework/scaffold/saas-dashboard/README.md +58 -0
- package/framework/scaffold/saas-dashboard/app/dashboard/page.tsx.template +546 -0
- package/framework/scaffold/saas-dashboard/app/globals.css.template +746 -0
- package/framework/scaffold/saas-dashboard/app/layout.tsx.template +192 -0
- package/framework/scaffold/saas-dashboard/app/shell.css.template +1070 -0
- package/framework/scaffold/saas-dashboard/components/data/Chart.tsx.template +725 -0
- package/framework/scaffold/saas-dashboard/components/data/DataTable.tsx.template +623 -0
- package/framework/scaffold/saas-dashboard/components/data/DataTable.types.ts.template +104 -0
- package/framework/scaffold/saas-dashboard/components/data/DataTablePagination.tsx.template +234 -0
- package/framework/scaffold/saas-dashboard/components/data/SkeletonBlock.tsx.template +111 -0
- package/framework/scaffold/saas-dashboard/components/data/StatCard.tsx.template +393 -0
- package/framework/scaffold/saas-dashboard/components/data/StatCardGrid.tsx.template +121 -0
- package/framework/scaffold/saas-dashboard/components/feedback/EmptyState.tsx.template +281 -0
- package/framework/scaffold/saas-dashboard/components/interaction/CommandPalette.tsx.template +767 -0
- package/framework/scaffold/saas-dashboard/components/interaction/Field.tsx.template +351 -0
- package/framework/scaffold/saas-dashboard/components/interaction/Form.tsx.template +424 -0
- package/framework/scaffold/saas-dashboard/components/primitives/Badge.tsx.template +193 -0
- package/framework/scaffold/saas-dashboard/components/primitives/Button.tsx.template +261 -0
- package/framework/scaffold/saas-dashboard/components/primitives/Card.tsx.template +287 -0
- package/framework/scaffold/saas-dashboard/components/primitives/Input.tsx.template +310 -0
- package/framework/scaffold/saas-dashboard/components/primitives/Spinner.tsx.template +135 -0
- package/framework/scaffold/saas-dashboard/components/primitives/index.ts.template +60 -0
- package/framework/scaffold/saas-dashboard/components/shell/AppShell.tsx.template +174 -0
- package/framework/scaffold/saas-dashboard/components/shell/Breadcrumb.tsx.template +186 -0
- package/framework/scaffold/saas-dashboard/components/shell/Container.tsx.template +86 -0
- package/framework/scaffold/saas-dashboard/components/shell/NavItem.tsx.template +147 -0
- package/framework/scaffold/saas-dashboard/components/shell/Sidebar.tsx.template +378 -0
- package/framework/scaffold/saas-dashboard/components/shell/SidebarContext.tsx.template +169 -0
- package/framework/scaffold/saas-dashboard/components/shell/ThemeToggle.tsx.template +128 -0
- package/framework/scaffold/saas-dashboard/components/shell/Topbar.tsx.template +301 -0
- package/framework/scaffold/saas-dashboard/lib/brand.ts.template +324 -0
- package/framework/scaffold/saas-dashboard/scaffold.yaml +225 -0
- package/framework/schemas/session.schema.json +5 -0
- package/framework/schemas/task.schema.json +9 -0
- package/framework/scripts/visual-qa.js +101 -3
- package/framework/tasks/orchestrator-health.md +4 -4
- package/framework/tasks/qa-impl-verdict.md +11 -5
- package/framework/templates/brandbook-html-tmpl.md +1 -1
- package/framework/templates/qa-gate-tmpl.yaml +24 -11
- package/package.json +4 -3
- package/src/config/context-file-generator.js +0 -6
- package/src/dashboard/renderer.js +0 -36
- package/src/executors/runner.js +204 -0
- package/src/installer/core.js +13 -3
- package/src/installer/templates.js +5 -6
- package/src/intelligence/registry-manager.js +1 -1
- package/src/license/client.js +9 -3
- package/src/license/commands.js +12 -2
- package/src/license/machine-id.js +42 -1
- package/src/memory/gotchas.js +58 -40
- package/src/memory/magic-docs.js +1 -1
- package/src/memory/session-digest.js +9 -4
- package/src/orchestrator/cli.js +186 -15
- package/src/orchestrator/doctor.js +98 -16
- package/src/orchestrator/pipeline-manager.js +44 -22
- package/src/orchestrator/session-manager.js +64 -8
- package/src/telemetry/sender.js +7 -19
- package/src/terminal/run-team.js +3 -3
- package/src/upgrade/tracked-files-detector.js +34 -16
- package/src/utils/feature-flags.js +1 -1
- package/src/utils/flatten-entities.js +4 -40
- package/src/utils/schema-validator.js +0 -14
- package/src/wizard/i18n.js +3 -3
- package/src/api/index.js +0 -120
- package/src/autonomy/autonomous-gate.js +0 -294
- package/src/autonomy/build-loop.js +0 -281
- package/src/autonomy/build-state.js +0 -286
- package/src/autonomy/cause-analyzer.js +0 -177
- package/src/autonomy/escalation.js +0 -214
- package/src/autonomy/index.js +0 -51
- package/src/autonomy/mode-manager.js +0 -225
- package/src/autonomy/mode-suggester.js +0 -283
- package/src/autonomy/progress-reporter.js +0 -275
- package/src/autonomy/safety-net.js +0 -370
- package/src/config/agent-customizer.js +0 -231
- package/src/decision/analyzer.js +0 -291
- package/src/decision/engine.js +0 -250
- package/src/decision/index.js +0 -38
- package/src/decision/registry-healer.js +0 -468
- package/src/decision/registry-updater.js +0 -339
- package/src/extensions/loader.js +0 -145
- package/src/extensions/registry.js +0 -134
- package/src/gates/circuit-breaker.js +0 -151
- package/src/gates/g1-planning-complete.js +0 -154
- package/src/gates/g2-qa-planning.js +0 -156
- package/src/gates/g3-implementation.js +0 -215
- package/src/gates/g4-qa-implementation.js +0 -240
- package/src/gates/g5-deploy-ready.js +0 -181
- package/src/gates/gate-base.js +0 -185
- package/src/gates/index.js +0 -46
- package/src/health/auto-fix.js +0 -216
- package/src/health/engine.js +0 -246
- package/src/merger/semantic-merger.js +0 -292
- package/src/preview/detector.js +0 -238
- package/src/preview/index.js +0 -20
- package/src/preview/launcher.js +0 -235
- package/src/preview/log-buffer.js +0 -103
- package/src/quality/metrics-collector.js +0 -281
- package/src/quality/test-runner.js +0 -366
- package/src/tasks/executor.js +0 -195
- package/src/tasks/index.js +0 -4
- package/src/tasks/loader.js +0 -210
- package/src/tasks/router.js +0 -182
- package/src/utils/event-bus.js +0 -126
|
@@ -43,20 +43,6 @@ const AGENT_MODELS = {
|
|
|
43
43
|
devops: { provider: 'claude', model: 'sonnet', tier: 'sonnet' },
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* Upgrade conditions per agent. When context matches, the model
|
|
48
|
-
* should be upgraded to the specified target.
|
|
49
|
-
*/
|
|
50
|
-
const UPGRADE_CONDITIONS = {
|
|
51
|
-
orchestrator: { to: 'opus', condition: 'complex routing or deviation handling' },
|
|
52
|
-
'greenfield-wu': { to: 'sonnet', condition: 'multi-stack or enterprise' },
|
|
53
|
-
brief: { to: 'opus', condition: '10+ integrations' },
|
|
54
|
-
ux: { to: 'opus', condition: 'design system from scratch' },
|
|
55
|
-
phases: { to: 'opus', condition: '20+ requirements' },
|
|
56
|
-
tasks: { to: 'opus', condition: '50+ tasks' },
|
|
57
|
-
devops: { to: 'opus', condition: 'multi-environment or IaC' },
|
|
58
|
-
};
|
|
59
|
-
|
|
60
46
|
function getCurrentAgent(projectDir) {
|
|
61
47
|
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
62
48
|
if (!existsSync(sessionPath)) return null;
|
|
@@ -66,6 +52,27 @@ function getCurrentAgent(projectDir) {
|
|
|
66
52
|
return match ? match[1].trim().replace(/^["']|["']$/g, '') : null;
|
|
67
53
|
}
|
|
68
54
|
|
|
55
|
+
function getSessionField(projectDir, key) {
|
|
56
|
+
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
57
|
+
if (!existsSync(sessionPath)) return null;
|
|
58
|
+
const raw = readFileSync(sessionPath, 'utf-8');
|
|
59
|
+
const match = raw.match(new RegExp(`^\\s*${key}:\\s*(.+)$`, 'm'));
|
|
60
|
+
if (!match) return null;
|
|
61
|
+
const v = match[1].trim().replace(/^["']|["']$/g, '');
|
|
62
|
+
return v === 'null' || v === '' ? null : v;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Collapse a model id to its family so opus and opus[1m] count as the same
|
|
66
|
+
// model for parity purposes (Article XXIV).
|
|
67
|
+
function modelFamily(m) {
|
|
68
|
+
if (!m) return null;
|
|
69
|
+
const s = String(m).toLowerCase();
|
|
70
|
+
for (const fam of ['opus', 'sonnet', 'haiku', 'pro', 'flash', 'codex', 'gemini', 'gpt']) {
|
|
71
|
+
if (s.includes(fam)) return fam;
|
|
72
|
+
}
|
|
73
|
+
return s;
|
|
74
|
+
}
|
|
75
|
+
|
|
69
76
|
async function main() {
|
|
70
77
|
let input = '';
|
|
71
78
|
for await (const chunk of process.stdin) {
|
|
@@ -77,15 +84,31 @@ async function main() {
|
|
|
77
84
|
const projectDir = event.cwd || process.cwd();
|
|
78
85
|
const agent = getCurrentAgent(projectDir);
|
|
79
86
|
|
|
87
|
+
// Advisory context injection via the canonical UserPromptSubmit schema.
|
|
88
|
+
const lines = [];
|
|
89
|
+
|
|
80
90
|
if (agent && AGENT_MODELS[agent]) {
|
|
81
91
|
const assignment = AGENT_MODELS[agent];
|
|
82
92
|
const expected = assignment.model || assignment;
|
|
83
93
|
const provider = assignment.provider || 'claude';
|
|
84
|
-
|
|
94
|
+
lines.push(`[Article XVI] Agent "${agent}" assigned model: ${expected} (provider: ${provider})`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Article XXIV: Model-Harness Parity. When the active model family differs
|
|
98
|
+
// from the model at the last harness audit, advise a re-audit. Advisory
|
|
99
|
+
// only, never blocks; the family comparison ignores variant changes such
|
|
100
|
+
// as opus vs opus[1m].
|
|
101
|
+
const activeModel = getSessionField(projectDir, 'active_model');
|
|
102
|
+
const modelAtLastAudit = getSessionField(projectDir, 'model_at_last_audit');
|
|
103
|
+
if (activeModel && modelAtLastAudit && modelFamily(activeModel) !== modelFamily(modelAtLastAudit)) {
|
|
104
|
+
lines.push(`[Article XXIV] Active model "${activeModel}" differs from the model at the last harness audit ("${modelAtLastAudit}"). Consider running /chati-update to re-audit the harness for this model. This is advisory and does not block your work.`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (lines.length > 0) {
|
|
85
108
|
process.stdout.write(JSON.stringify({
|
|
86
109
|
hookSpecificOutput: {
|
|
87
110
|
hookEventName: 'UserPromptSubmit',
|
|
88
|
-
additionalContext:
|
|
111
|
+
additionalContext: lines.join('\n'),
|
|
89
112
|
},
|
|
90
113
|
}));
|
|
91
114
|
} else {
|
|
@@ -97,7 +120,7 @@ async function main() {
|
|
|
97
120
|
}
|
|
98
121
|
}
|
|
99
122
|
|
|
100
|
-
export { AGENT_MODELS,
|
|
123
|
+
export { AGENT_MODELS, getCurrentAgent };
|
|
101
124
|
|
|
102
125
|
// Only run main when executed directly (not imported by tests).
|
|
103
126
|
// realpathSync resolves symlinks on both sides — important on macOS where
|
|
@@ -32,9 +32,26 @@
|
|
|
32
32
|
* Claude Code Hook: triggers on every user message submission.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
import { existsSync, readFileSync, writeFileSync, renameSync } from 'fs';
|
|
35
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, statSync } from 'fs';
|
|
36
36
|
import { join } from 'path';
|
|
37
37
|
|
|
38
|
+
// mtime-keyed read cache. This is a no-op for the per-prompt hook process
|
|
39
|
+
// (it starts fresh each invocation and must read at least once), but it
|
|
40
|
+
// spares repeated disk reads for long-lived importers of these helpers
|
|
41
|
+
// (status --watch, context-status, tests) that call them many times in one
|
|
42
|
+
// process. The mtime key guarantees a changed file is always re-read, so the
|
|
43
|
+
// cache can never serve stale state.
|
|
44
|
+
const _fileReadCache = new Map(); // absPath -> { mtimeMs, content }
|
|
45
|
+
function readFileCached(absPath) {
|
|
46
|
+
let mtimeMs;
|
|
47
|
+
try { mtimeMs = statSync(absPath).mtimeMs; } catch { return null; }
|
|
48
|
+
const hit = _fileReadCache.get(absPath);
|
|
49
|
+
if (hit && hit.mtimeMs === mtimeMs) return hit.content;
|
|
50
|
+
const content = readFileSync(absPath, 'utf-8');
|
|
51
|
+
_fileReadCache.set(absPath, { mtimeMs, content });
|
|
52
|
+
return content;
|
|
53
|
+
}
|
|
54
|
+
|
|
38
55
|
// ---------------------------------------------------------------------------
|
|
39
56
|
// Context window limits — load from shared JSON, fall back to embedded.
|
|
40
57
|
// ---------------------------------------------------------------------------
|
|
@@ -47,18 +64,23 @@ function loadLimits(projectDir) {
|
|
|
47
64
|
for (const candidate of candidates) {
|
|
48
65
|
if (existsSync(candidate)) {
|
|
49
66
|
try {
|
|
50
|
-
|
|
67
|
+
const content = readFileCached(candidate);
|
|
68
|
+
if (content != null) return JSON.parse(content);
|
|
51
69
|
} catch { /* malformed — fall through */ }
|
|
52
70
|
}
|
|
53
71
|
}
|
|
54
72
|
// Last-resort fallback. Matches chati.dev/data/model-limits.json verbatim.
|
|
55
|
-
// Scan-stale check #25 guards parity between this block
|
|
73
|
+
// Scan-stale check #25 guards parity between this block AND the JSON.
|
|
74
|
+
// 2026-04-18 (context-window-auto-detect-v2): opus and sonnet families
|
|
75
|
+
// default to 1M; haiku stays at 200K. The prior `opus: 200_000` here was a
|
|
76
|
+
// stale regression-lock from PR #3 that silently degraded users to a 5x
|
|
77
|
+
// smaller context budget whenever model-limits.json was unreadable.
|
|
56
78
|
return {
|
|
57
|
-
providers: { claude:
|
|
79
|
+
providers: { claude: 1_000_000, gemini: 1_000_000, codex: 128_000 },
|
|
58
80
|
models: {
|
|
59
|
-
opus:
|
|
81
|
+
opus: 1_000_000,
|
|
60
82
|
'opus[1m]': 1_000_000,
|
|
61
|
-
sonnet:
|
|
83
|
+
sonnet: 1_000_000,
|
|
62
84
|
'sonnet[1m]': 1_000_000,
|
|
63
85
|
haiku: 200_000,
|
|
64
86
|
pro: 1_000_000,
|
|
@@ -117,7 +139,8 @@ function readSessionState(projectDir) {
|
|
|
117
139
|
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
118
140
|
if (!existsSync(sessionPath)) return null;
|
|
119
141
|
|
|
120
|
-
const raw =
|
|
142
|
+
const raw = readFileCached(sessionPath);
|
|
143
|
+
if (raw == null) return null;
|
|
121
144
|
const extract = (key) => {
|
|
122
145
|
const match = raw.match(new RegExp(`^\\s*${key}:\\s*(.+)$`, 'm'));
|
|
123
146
|
if (!match) return null;
|
|
@@ -152,6 +175,7 @@ function readSessionState(projectDir) {
|
|
|
152
175
|
provider: extract('active_provider') || extract('provider') || 'claude',
|
|
153
176
|
// v1.2 context detection fields.
|
|
154
177
|
activeModel: extract('active_model'),
|
|
178
|
+
modelAtLastAudit: extract('model_at_last_audit'),
|
|
155
179
|
contextTokensUsed: extractNum('context_tokens_used') || 0,
|
|
156
180
|
contextWindowTokens: extractNum('context_window_tokens'),
|
|
157
181
|
activeTeamId,
|
|
@@ -302,6 +326,12 @@ async function main() {
|
|
|
302
326
|
context_last_bracket: bracket,
|
|
303
327
|
// If we detected a model and the session did not have one, cache it.
|
|
304
328
|
...(detectedModel && !session.activeModel ? { active_model: detectedModel } : {}),
|
|
329
|
+
// Seed the harness-audit baseline once (Article XXIV). Only when unset,
|
|
330
|
+
// so a later model change leaves the old baseline in place for the
|
|
331
|
+
// model-governance advisory to detect.
|
|
332
|
+
...((detectedModel || session.activeModel) && !session.modelAtLastAudit
|
|
333
|
+
? { model_at_last_audit: detectedModel || session.activeModel }
|
|
334
|
+
: {}),
|
|
305
335
|
});
|
|
306
336
|
} catch (err) {
|
|
307
337
|
process.stderr.write(`[chati] prism-engine write-back failed (non-fatal): ${err.message}\n`);
|
|
@@ -319,6 +349,35 @@ async function main() {
|
|
|
319
349
|
}
|
|
320
350
|
}
|
|
321
351
|
|
|
352
|
+
// 5b. Gotchas block. Surface the most relevant known gotchas to every agent
|
|
353
|
+
// per turn. This is the reliable per-turn, all-agent delivery path; gotchas
|
|
354
|
+
// attached to a handoff alone do not reach interactive agents and do not
|
|
355
|
+
// survive the first agent memory write. Read straight from the shared store;
|
|
356
|
+
// no src/ import (hooks are standalone).
|
|
357
|
+
let gotchasBlock = '';
|
|
358
|
+
if (session.currentAgent && bracket !== 'CRITICAL') {
|
|
359
|
+
const gotchasPath = join(projectDir, '.chati', 'memories', 'shared', 'gotchas.json');
|
|
360
|
+
const rawGotchas = readFileCached(gotchasPath);
|
|
361
|
+
if (rawGotchas) {
|
|
362
|
+
try {
|
|
363
|
+
const all = JSON.parse(rawGotchas);
|
|
364
|
+
const SEV = { CRITICAL: 3, WARNING: 2, INFO: 1 };
|
|
365
|
+
const ranked = (Array.isArray(all) ? all : [])
|
|
366
|
+
.filter((g) => g && !g.resolution)
|
|
367
|
+
.map((g) => ({ g, score: (g.agent === session.currentAgent ? 10 : 0) + (SEV[g.severity] || 1) + Math.min(5, g.count || 1) }))
|
|
368
|
+
.sort((a, b) => b.score - a.score)
|
|
369
|
+
.slice(0, 3);
|
|
370
|
+
if (ranked.length) {
|
|
371
|
+
const items = ranked.map(({ g }) => {
|
|
372
|
+
const msg = String(g.original_message || g.message || '').replace(/[<>]/g, '').replace(/\s+/g, ' ').slice(0, 160);
|
|
373
|
+
return ` <gotcha id="${g.id}" severity="${g.severity || 'INFO'}">${msg}</gotcha>`;
|
|
374
|
+
});
|
|
375
|
+
gotchasBlock = [' <known-gotchas>', ...items, ' </known-gotchas>'].join('\n');
|
|
376
|
+
}
|
|
377
|
+
} catch { /* malformed gotchas store — skip */ }
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
322
381
|
// 6. Team context block (unchanged).
|
|
323
382
|
let teamContextBlock = '';
|
|
324
383
|
if (session.activeTeamId && bracket !== 'CRITICAL') {
|
|
@@ -335,10 +394,16 @@ async function main() {
|
|
|
335
394
|
|
|
336
395
|
// 7. Advisories.
|
|
337
396
|
const frustrationDetected = detectFrustration(promptText);
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
397
|
+
const lowContext = bracket === 'DEPLETED' || bracket === 'CRITICAL';
|
|
398
|
+
const microcompactAdvisory = lowContext
|
|
399
|
+
? ' <advisory priority="medium">Context constrained. Avoid re-reading files already in context. Summarize stale outputs before proceeding.</advisory>'
|
|
400
|
+
: '';
|
|
401
|
+
// During BUILD at low context, prefer a clean session reset (handoff + fresh
|
|
402
|
+
// session) over in-place compaction: compaction keeps the model wrapping up
|
|
403
|
+
// prematurely while code is being written (Article XII reset preference).
|
|
404
|
+
const buildResetAdvisory = (lowContext && session.mode === 'build')
|
|
405
|
+
? ' <advisory priority="high">BUILD phase at low context. Prefer a clean reset: write a handoff and continue in a fresh session, rather than compacting in place.</advisory>'
|
|
406
|
+
: '';
|
|
342
407
|
|
|
343
408
|
// 8. Compose the context block.
|
|
344
409
|
const contextBlock = [
|
|
@@ -347,9 +412,11 @@ async function main() {
|
|
|
347
412
|
session.currentAgent ? ` <agent>${session.currentAgent}</agent>` : '',
|
|
348
413
|
session.pipelinePosition ? ` <pipeline-position>${session.pipelinePosition}</pipeline-position>` : '',
|
|
349
414
|
memoryBlock,
|
|
415
|
+
gotchasBlock,
|
|
350
416
|
teamContextBlock,
|
|
351
417
|
bracket === 'CRITICAL' ? ' <advisory>Context running low. Consider handoff or summary.</advisory>' : '',
|
|
352
418
|
microcompactAdvisory,
|
|
419
|
+
buildResetAdvisory,
|
|
353
420
|
frustrationDetected ? ' <advisory priority="high">User shows signs of frustration. Be more direct, acknowledge the issue explicitly, focus on the solution, avoid repeating previous suggestions.</advisory>' : '',
|
|
354
421
|
'</chati-context>',
|
|
355
422
|
].filter(Boolean).join('\n');
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* recovered after context compaction. Writes to .chati/memories/shared/session/.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'fs';
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync, chmodSync } from 'fs';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
10
11
|
import { join } from 'path';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -250,11 +251,19 @@ async function main() {
|
|
|
250
251
|
content += newEntry;
|
|
251
252
|
}
|
|
252
253
|
writeFileSync(pingsPath, content, 'utf-8');
|
|
254
|
+
// pings.yaml records the installation and private project paths;
|
|
255
|
+
// restrict to owner-only.
|
|
256
|
+
try { chmodSync(pingsPath, 0o600); } catch { /* no-op on Windows / read-only FS */ }
|
|
253
257
|
|
|
254
|
-
// Fire-and-forget telemetry (3s timeout, never blocks)
|
|
258
|
+
// Fire-and-forget telemetry (3s timeout, never blocks).
|
|
259
|
+
// The raw license key is never transmitted. The body carries only a
|
|
260
|
+
// non-reversible installation_id (sha256 of the key, 16 hex) so the
|
|
261
|
+
// server can group sessions per install without ever seeing, logging
|
|
262
|
+
// or storing the key.
|
|
255
263
|
try {
|
|
264
|
+
const installationId = createHash('sha256').update(licenseKey).digest('hex').slice(0, 16);
|
|
256
265
|
const body = JSON.stringify({
|
|
257
|
-
|
|
266
|
+
installation_id: installationId,
|
|
258
267
|
project_name: digest.currentAgent || 'unknown',
|
|
259
268
|
events: [{ type: 'session_active', timestamp: nowIso, properties: { pipeline_phase: digest.mode, current_agent: digest.currentAgent } }],
|
|
260
269
|
});
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"hooks": [
|
|
42
42
|
{
|
|
43
43
|
"type": "command",
|
|
44
|
-
"command": "node chati.dev/hooks/
|
|
44
|
+
"command": "node chati.dev/hooks/brief-validator.js"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"type": "command",
|
|
48
|
-
"command": "node chati.dev/hooks/
|
|
48
|
+
"command": "node chati.dev/hooks/advance-trigger.js"
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"type": "command",
|
|
52
|
-
"command": "node chati.dev/hooks/
|
|
52
|
+
"command": "node chati.dev/hooks/reference-trigger.js"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"type": "command",
|
|
@@ -104,6 +104,10 @@
|
|
|
104
104
|
"type": "command",
|
|
105
105
|
"command": "node chati.dev/hooks/constitution-guard.js"
|
|
106
106
|
},
|
|
107
|
+
{
|
|
108
|
+
"type": "command",
|
|
109
|
+
"command": "node chati.dev/hooks/git-push-authority.js"
|
|
110
|
+
},
|
|
107
111
|
{
|
|
108
112
|
"type": "command",
|
|
109
113
|
"command": "node chati.dev/hooks/undercover-guard.js"
|
|
@@ -21,6 +21,35 @@ const EM_DASH_PATTERN = /[\u2013\u2014]/;
|
|
|
21
21
|
/** Emoji unicode ranges (comprehensive) */
|
|
22
22
|
const EMOJI_PATTERN = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{1FA70}-\u{1FAFF}\u{231A}-\u{231B}\u{23E9}-\u{23F3}\u{23F8}-\u{23FA}\u{25AA}-\u{25AB}\u{25B6}\u{25C0}\u{25FB}-\u{25FE}\u{2614}-\u{2615}\u{2648}-\u{2653}\u{267F}\u{2693}\u{26A1}\u{26AA}-\u{26AB}\u{26BD}-\u{26BE}\u{26C4}-\u{26C5}\u{26CE}\u{26D4}\u{26EA}\u{26F2}-\u{26F3}\u{26F5}\u{26FA}\u{26FD}\u{2702}\u{2705}\u{2708}-\u{270D}\u{270F}]/u;
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* AI-slop phrasing (Article V: no AI-detectable writing patterns). Advisory,
|
|
26
|
+
* not a block: warn so the agent rewrites in specific, concrete language with a
|
|
27
|
+
* real voice. Tuned to the clear tells (formulaic openers, marketing filler,
|
|
28
|
+
* empty intensifiers) to keep false positives low.
|
|
29
|
+
*/
|
|
30
|
+
const SLOP_PHRASES = [
|
|
31
|
+
/\bdelve into\b/i,
|
|
32
|
+
/\bdive into\b/i,
|
|
33
|
+
/\bit'?s important to note\b/i,
|
|
34
|
+
/\bit is important to note\b/i,
|
|
35
|
+
/\bin today'?s (world|fast[- ]paced|digital|landscape)\b/i,
|
|
36
|
+
/\bin the realm of\b/i,
|
|
37
|
+
/\ba testament to\b/i,
|
|
38
|
+
/\bunlock (the|your) (power|potential)\b/i,
|
|
39
|
+
/\bharness the power\b/i,
|
|
40
|
+
/\belevate your\b/i,
|
|
41
|
+
/\bseamless(ly)?\b/i,
|
|
42
|
+
/\bgame[- ]?changer\b/i,
|
|
43
|
+
/\bcutting[- ]edge\b/i,
|
|
44
|
+
/\bto the next level\b/i,
|
|
45
|
+
/\blook no further\b/i,
|
|
46
|
+
/\bembark on (a|your) journey\b/i,
|
|
47
|
+
/\bsupercharge\b/i,
|
|
48
|
+
/\brevolutioniz(e|ing)\b/i,
|
|
49
|
+
/\bbest[- ]in[- ]class\b/i,
|
|
50
|
+
/\bunparalleled\b/i,
|
|
51
|
+
];
|
|
52
|
+
|
|
24
53
|
/**
|
|
25
54
|
* Paths exempt from style enforcement.
|
|
26
55
|
* Framework files, configs, and context files may legitimately contain special chars.
|
|
@@ -54,20 +83,32 @@ function isExemptPath(filePath, projectDir) {
|
|
|
54
83
|
* @returns {{ violations: string[], hasDash: boolean, hasEmoji: boolean }}
|
|
55
84
|
*/
|
|
56
85
|
function checkStyle(content) {
|
|
57
|
-
if (!content || typeof content !== 'string') return { violations: [], hasDash: false, hasEmoji: false };
|
|
86
|
+
if (!content || typeof content !== 'string') return { violations: [], hasDash: false, hasEmoji: false, slopPhrases: [] };
|
|
58
87
|
|
|
59
88
|
const violations = [];
|
|
60
89
|
const hasDash = EM_DASH_PATTERN.test(content);
|
|
61
90
|
const hasEmoji = EMOJI_PATTERN.test(content);
|
|
62
91
|
|
|
92
|
+
const slopPhrases = [];
|
|
93
|
+
for (const re of SLOP_PHRASES) {
|
|
94
|
+
const m = content.match(re);
|
|
95
|
+
if (m) {
|
|
96
|
+
const hit = m[0].toLowerCase();
|
|
97
|
+
if (!slopPhrases.includes(hit)) slopPhrases.push(hit);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
63
101
|
if (hasDash) {
|
|
64
102
|
violations.push('Em-dash or en-dash detected. Use commas, semicolons, colons, or periods instead (Article V).');
|
|
65
103
|
}
|
|
66
104
|
if (hasEmoji) {
|
|
67
105
|
violations.push('Emoji detected. Use icons from approved libraries instead (Directive 1).');
|
|
68
106
|
}
|
|
107
|
+
if (slopPhrases.length) {
|
|
108
|
+
violations.push(`AI-slop phrasing detected: ${slopPhrases.slice(0, 5).join(', ')}. Rewrite in specific, concrete language (Article V).`);
|
|
109
|
+
}
|
|
69
110
|
|
|
70
|
-
return { violations, hasDash, hasEmoji };
|
|
111
|
+
return { violations, hasDash, hasEmoji, slopPhrases };
|
|
71
112
|
}
|
|
72
113
|
|
|
73
114
|
/**
|
|
@@ -129,6 +170,14 @@ async function main() {
|
|
|
129
170
|
return;
|
|
130
171
|
}
|
|
131
172
|
|
|
173
|
+
if (result.slopPhrases && result.slopPhrases.length) {
|
|
174
|
+
// AI-slop phrasing is advisory — warn but allow so the agent rewrites.
|
|
175
|
+
process.stdout.write(JSON.stringify(allowOutput(
|
|
176
|
+
`[Style Guard] AI-slop phrasing detected (${result.slopPhrases.slice(0, 5).join(', ')}). Rewrite in specific, concrete language with a real voice. Avoid formulaic marketing filler (Article V).`
|
|
177
|
+
)));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
132
181
|
process.stdout.write(JSON.stringify(allowOutput()));
|
|
133
182
|
} catch (err) {
|
|
134
183
|
process.stderr.write(`[chati] style-guard: ${err.message}\n`);
|
|
@@ -157,7 +206,7 @@ function allowOutput(reason) {
|
|
|
157
206
|
return out;
|
|
158
207
|
}
|
|
159
208
|
|
|
160
|
-
export { checkStyle, checkBashStyle, isExemptPath, EM_DASH_PATTERN, EMOJI_PATTERN };
|
|
209
|
+
export { checkStyle, checkBashStyle, isExemptPath, EM_DASH_PATTERN, EMOJI_PATTERN, SLOP_PHRASES };
|
|
161
210
|
|
|
162
211
|
// Only run main when executed directly (not imported by tests).
|
|
163
212
|
// realpathSync resolves symlinks on both sides — important on macOS where
|
|
@@ -83,9 +83,13 @@ async function main() {
|
|
|
83
83
|
const event = JSON.parse(input);
|
|
84
84
|
const projectDir = event.cwd || process.cwd();
|
|
85
85
|
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
// The env var is the fast path, but it does not always propagate to a
|
|
87
|
+
// parallel hook process. Fall back to the session file: if the env var is
|
|
88
|
+
// absent AND no team is active in session.yaml, this is genuinely solo mode
|
|
89
|
+
// and we allow. If a team IS active, we enforce isolation even without the
|
|
90
|
+
// env var, otherwise cross-member overwrites slip through unblocked.
|
|
91
|
+
const teamActive = !!process.env.CHATI_TEAM_ID || hasActiveTeamInSession(projectDir);
|
|
92
|
+
if (!teamActive) {
|
|
89
93
|
process.stdout.write(JSON.stringify(allowOutput()));
|
|
90
94
|
return;
|
|
91
95
|
}
|
|
@@ -130,9 +134,25 @@ async function main() {
|
|
|
130
134
|
// Path not owned by anyone specific → allow
|
|
131
135
|
process.stdout.write(JSON.stringify(allowOutput()));
|
|
132
136
|
} catch (err) {
|
|
133
|
-
// Fail-open: hook errors should not block execution
|
|
134
137
|
process.stderr.write(`[chati] team-quality-gate: ${err.message}\n`);
|
|
135
|
-
|
|
138
|
+
// Fail CLOSED while a team is active. A crash in the write-scope guard must
|
|
139
|
+
// not silently permit cross-member overwrites during parallel team
|
|
140
|
+
// execution. Outside team mode this gate guards nothing, so a crash there
|
|
141
|
+
// allows. Re-derive team state defensively from env + session.
|
|
142
|
+
let teamActive = !!process.env.CHATI_TEAM_ID;
|
|
143
|
+
if (!teamActive) {
|
|
144
|
+
try {
|
|
145
|
+
const parsed = JSON.parse(input);
|
|
146
|
+
teamActive = hasActiveTeamInSession(parsed.cwd || process.cwd());
|
|
147
|
+
} catch { /* input unparseable: fall back to the env-only signal */ }
|
|
148
|
+
}
|
|
149
|
+
if (teamActive) {
|
|
150
|
+
process.stdout.write(JSON.stringify(denyOutput(
|
|
151
|
+
`[Team Quality Gate] internal error while enforcing team write isolation (${err.message}). Write blocked as a precaution to prevent cross-member overwrites. Retry once resolved.`
|
|
152
|
+
)));
|
|
153
|
+
} else {
|
|
154
|
+
process.stdout.write(JSON.stringify(allowOutput()));
|
|
155
|
+
}
|
|
136
156
|
}
|
|
137
157
|
}
|
|
138
158
|
|
|
@@ -163,6 +183,24 @@ function detectAgentFromSession(projectDir) {
|
|
|
163
183
|
return match ? match[1].trim().replace(/^["']|["']$/g, '') : null;
|
|
164
184
|
}
|
|
165
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Detect whether a team is active from session.yaml alone, for the case where
|
|
188
|
+
* CHATI_TEAM_ID did not propagate to this hook process. An active team is an
|
|
189
|
+
* entry in teams[] whose status is forming, active or
|
|
190
|
+
* completing. preview.status uses a different vocabulary (inactive/running/
|
|
191
|
+
* approved/adjusting), so matching these specific values is team-specific.
|
|
192
|
+
*/
|
|
193
|
+
function hasActiveTeamInSession(projectDir) {
|
|
194
|
+
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
195
|
+
if (!existsSync(sessionPath)) return false;
|
|
196
|
+
try {
|
|
197
|
+
const raw = readFileSync(sessionPath, 'utf-8');
|
|
198
|
+
return /team_id:\s*\S/.test(raw) && /^\s*status:\s*(active|forming|completing)\b/m.test(raw);
|
|
199
|
+
} catch {
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
166
204
|
// Only run main when executed directly (not imported by tests).
|
|
167
205
|
// realpathSync resolves symlinks on both sides — important on macOS where
|
|
168
206
|
// /tmp is a symlink to /private/tmp. Without realpath the comparison fails
|
package/framework/i18n/en.yaml
CHANGED
|
@@ -31,7 +31,7 @@ installer:
|
|
|
31
31
|
agents_count: "Agent definitions across DISCOVER, PLAN, BUILD, DEPLOY phases"
|
|
32
32
|
workflows_count: "7 workflow blueprints"
|
|
33
33
|
templates_count: "10 templates (PRD, Brownfield PRD, Architecture, Task, QA Gate, Quick Brief, Brandbook, Design Tokens, Component Spec, Icon System)"
|
|
34
|
-
constitution: "Constitution (
|
|
34
|
+
constitution: "Constitution (25 Articles + Preamble)"
|
|
35
35
|
session_mgmt: "Session management system"
|
|
36
36
|
quality_gates: "Quality gates (3-tier verdicts)"
|
|
37
37
|
proceed: "Proceed with installation?"
|
|
@@ -39,7 +39,7 @@ installer:
|
|
|
39
39
|
created_chati: "Created .chati/ session directory"
|
|
40
40
|
created_framework: "Created chati.dev/ system directory (agents, templates, workflows)"
|
|
41
41
|
created_commands: "Created .claude/commands/ (thin router)"
|
|
42
|
-
installed_constitution: "Installed Constitution (Articles I-
|
|
42
|
+
installed_constitution: "Installed Constitution (Articles I-XXV)"
|
|
43
43
|
created_session: "Created session.yaml schema"
|
|
44
44
|
created_claude_md: "Created CLAUDE.md"
|
|
45
45
|
configured_mcps: "Configured MCPs:"
|
|
@@ -47,7 +47,7 @@ installer:
|
|
|
47
47
|
agents_valid: "All agents implement 8 protocols"
|
|
48
48
|
handoff_ok: "Handoff protocol: OK"
|
|
49
49
|
validation_ok: "Self-validation criteria: OK"
|
|
50
|
-
constitution_ok: "Constitution:
|
|
50
|
+
constitution_ok: "Constitution: 25 articles verified"
|
|
51
51
|
created_memories: "Created .chati/memories/ (Memory Layer)"
|
|
52
52
|
installed_intelligence: "Installed Intelligence Layer (Context Engine, Memory, Registry)"
|
|
53
53
|
intelligence_valid: "Intelligence: 6 spec files verified"
|
package/framework/i18n/es.yaml
CHANGED
|
@@ -31,7 +31,7 @@ installer:
|
|
|
31
31
|
agents_count: "Definiciones de agentes en las fases DISCOVER, PLAN, BUILD, DEPLOY"
|
|
32
32
|
workflows_count: "7 blueprints de workflow"
|
|
33
33
|
templates_count: "10 templates (PRD, PRD Brownfield, Arquitectura, Task, QA Gate, Quick Brief, Brandbook, Design Tokens, Component Spec, Icon System)"
|
|
34
|
-
constitution: "Constitucion (
|
|
34
|
+
constitution: "Constitucion (25 Articulos + Preambulo)"
|
|
35
35
|
session_mgmt: "Sistema de gestion de sesion"
|
|
36
36
|
quality_gates: "Quality gates (veredictos en 3 niveles)"
|
|
37
37
|
proceed: "Proceder con la instalacion?"
|
|
@@ -39,7 +39,7 @@ installer:
|
|
|
39
39
|
created_chati: "Creado directorio de sesion .chati/"
|
|
40
40
|
created_framework: "Creado directorio del sistema chati.dev/ (agentes, templates, workflows)"
|
|
41
41
|
created_commands: "Creado .claude/commands/ (enrutador)"
|
|
42
|
-
installed_constitution: "Instalada Constitucion (Artículos I-
|
|
42
|
+
installed_constitution: "Instalada Constitucion (Artículos I-XXV)"
|
|
43
43
|
created_session: "Creado schema session.yaml"
|
|
44
44
|
created_claude_md: "Creado CLAUDE.md"
|
|
45
45
|
configured_mcps: "MCPs configurados:"
|
|
@@ -47,7 +47,7 @@ installer:
|
|
|
47
47
|
agents_valid: "Todos los agentes implementan 8 protocolos"
|
|
48
48
|
handoff_ok: "Protocolo de handoff: OK"
|
|
49
49
|
validation_ok: "Criterios de auto-validacion: OK"
|
|
50
|
-
constitution_ok: "Constitucion:
|
|
50
|
+
constitution_ok: "Constitucion: 25 articulos verificados"
|
|
51
51
|
created_memories: "Creado .chati/memories/ (Memory Layer)"
|
|
52
52
|
installed_intelligence: "Instalada Intelligence Layer (Context Engine, Memory, Registry)"
|
|
53
53
|
intelligence_valid: "Intelligence: 6 archivos de spec verificados"
|
package/framework/i18n/fr.yaml
CHANGED
|
@@ -31,7 +31,7 @@ installer:
|
|
|
31
31
|
agents_count: "Definitions d'agents dans les phases DISCOVER, PLAN, BUILD, DEPLOY"
|
|
32
32
|
workflows_count: "7 blueprints de workflow"
|
|
33
33
|
templates_count: "10 templates (PRD, PRD Brownfield, Architecture, Task, QA Gate, Quick Brief, Brandbook, Design Tokens, Component Spec, Icon System)"
|
|
34
|
-
constitution: "Constitution (
|
|
34
|
+
constitution: "Constitution (25 Articles + Preambule)"
|
|
35
35
|
session_mgmt: "Systeme de gestion de session"
|
|
36
36
|
quality_gates: "Quality gates (verdicts en 3 niveaux)"
|
|
37
37
|
proceed: "Proceder a l'installation?"
|
|
@@ -39,7 +39,7 @@ installer:
|
|
|
39
39
|
created_chati: "Cree le repertoire de session .chati/"
|
|
40
40
|
created_framework: "Cree le repertoire du systeme chati.dev/ (agents, templates, workflows)"
|
|
41
41
|
created_commands: "Cree .claude/commands/ (routeur)"
|
|
42
|
-
installed_constitution: "Installee la Constitution (Articles I-
|
|
42
|
+
installed_constitution: "Installee la Constitution (Articles I-XXV)"
|
|
43
43
|
created_session: "Cree le schema session.yaml"
|
|
44
44
|
created_claude_md: "Cree CLAUDE.md"
|
|
45
45
|
configured_mcps: "MCPs configures:"
|
|
@@ -47,7 +47,7 @@ installer:
|
|
|
47
47
|
agents_valid: "Tous les agents implementent 8 protocoles"
|
|
48
48
|
handoff_ok: "Protocole de passation: OK"
|
|
49
49
|
validation_ok: "Criteres d'auto-validation: OK"
|
|
50
|
-
constitution_ok: "Constitution:
|
|
50
|
+
constitution_ok: "Constitution: 25 articles verifies"
|
|
51
51
|
created_memories: "Cree .chati/memories/ (Memory Layer)"
|
|
52
52
|
installed_intelligence: "Installee Intelligence Layer (Context Engine, Memory, Registry)"
|
|
53
53
|
intelligence_valid: "Intelligence: 6 fichiers de spec verifies"
|
package/framework/i18n/pt.yaml
CHANGED
|
@@ -31,7 +31,7 @@ installer:
|
|
|
31
31
|
agents_count: "Definicoes de agentes nas fases DISCOVER, PLAN, BUILD, DEPLOY"
|
|
32
32
|
workflows_count: "7 blueprints de workflow"
|
|
33
33
|
templates_count: "10 templates (PRD, PRD Brownfield, Arquitetura, Task, QA Gate, Quick Brief, Brandbook, Design Tokens, Component Spec, Icon System)"
|
|
34
|
-
constitution: "Constituicao (
|
|
34
|
+
constitution: "Constituicao (25 Artigos + Preambulo)"
|
|
35
35
|
session_mgmt: "Sistema de gerenciamento de sessao"
|
|
36
36
|
quality_gates: "Quality gates (veredictos em 3 niveis)"
|
|
37
37
|
proceed: "Prosseguir com a instalacao?"
|
|
@@ -39,7 +39,7 @@ installer:
|
|
|
39
39
|
created_chati: "Criado diretorio de sessao .chati/"
|
|
40
40
|
created_framework: "Criado diretorio do sistema chati.dev/ (agentes, templates, workflows)"
|
|
41
41
|
created_commands: "Criado .claude/commands/ (roteador)"
|
|
42
|
-
installed_constitution: "Instalada Constituicao (Artigos I-
|
|
42
|
+
installed_constitution: "Instalada Constituicao (Artigos I-XXV)"
|
|
43
43
|
created_session: "Criado schema session.yaml"
|
|
44
44
|
created_claude_md: "Criado CLAUDE.md"
|
|
45
45
|
configured_mcps: "MCPs configurados:"
|
|
@@ -47,7 +47,7 @@ installer:
|
|
|
47
47
|
agents_valid: "Todos os agentes implementam 8 protocolos"
|
|
48
48
|
handoff_ok: "Protocolo de handoff: OK"
|
|
49
49
|
validation_ok: "Criterios de auto-validacao: OK"
|
|
50
|
-
constitution_ok: "Constituicao:
|
|
50
|
+
constitution_ok: "Constituicao: 25 artigos verificados"
|
|
51
51
|
created_memories: "Criado .chati/memories/ (Memory Layer)"
|
|
52
52
|
installed_intelligence: "Instalada Intelligence Layer (Context Engine, Memory, Registry)"
|
|
53
53
|
intelligence_valid: "Intelligence: 6 arquivos de spec verificados"
|