chati-dev 4.2.1 → 4.2.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/framework/config.yaml +3 -3
- package/framework/constitution.md +2 -1
- package/framework/context/root.md +2 -2
- package/framework/hooks/constitution-guard.js +69 -33
- package/framework/hooks/license-guard.js +92 -188
- package/framework/hooks/mode-governance.js +55 -14
- package/framework/hooks/model-governance.js +18 -8
- package/framework/hooks/package.json +3 -0
- package/framework/hooks/prism-engine.js +22 -8
- package/framework/hooks/read-protection.js +37 -9
- package/framework/hooks/session-digest.js +45 -20
- package/framework/hooks/style-guard.js +30 -10
- package/framework/hooks/team-quality-gate.js +39 -13
- package/framework/hooks/undercover-guard.js +30 -11
- package/framework/orchestrator/chati.md +31 -28
- package/package.json +1 -1
- package/scripts/validate-package.js +146 -8
- package/src/config/claude-settings-generator.js +206 -0
- package/src/config/gemini-hooks-generator.js +58 -0
- package/src/installer/core.js +136 -1
- package/src/installer/templates.js +6 -2
- package/src/orchestrator/cli.js +41 -11
package/src/orchestrator/cli.js
CHANGED
|
@@ -381,24 +381,33 @@ async function handleNext(projectDir) {
|
|
|
381
381
|
// Check for parallel group — with Agent Teams override (Article XXI)
|
|
382
382
|
let action, spawnCommand = null, parallelSpawnCommand = null, parallelAgents = [];
|
|
383
383
|
let teamData = null;
|
|
384
|
+
const teamsEnabled = isAgentTeamsEnabled(projectDir);
|
|
385
|
+
|
|
384
386
|
if (nextInfo.isParallel && nextInfo.group.length > 1) {
|
|
385
|
-
//
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
const teamConfig = TEAM_CONFIGS
|
|
387
|
+
// Planning Team auto-spawn: detail + architect + ux are marked parallel: true
|
|
388
|
+
// in agent-selector. When agent_teams enabled, swap spawn_parallel for spawn_team.
|
|
389
|
+
if (teamsEnabled) {
|
|
390
|
+
const teamConfig = TEAM_CONFIGS.planning;
|
|
389
391
|
const teamId = generateTeamId(teamConfig.slug);
|
|
390
392
|
action = 'spawn_team';
|
|
391
393
|
parallelAgents = teamConfig.members;
|
|
392
|
-
teamData = {
|
|
393
|
-
team_id: teamId,
|
|
394
|
-
team_type: teamType,
|
|
395
|
-
members: teamConfig.members,
|
|
396
|
-
};
|
|
394
|
+
teamData = { team_id: teamId, team_type: 'planning', members: teamConfig.members };
|
|
397
395
|
} else {
|
|
398
396
|
action = 'spawn_parallel';
|
|
399
397
|
parallelAgents = nextInfo.group;
|
|
400
398
|
parallelSpawnCommand = buildParallelSpawnCommand(nextInfo.group, projectDir, lastAgent, modelInfo.provider, 900000);
|
|
401
399
|
}
|
|
400
|
+
} else if (nextAgent === 'dev' && teamsEnabled) {
|
|
401
|
+
// Build Team auto-spawn: dev + qa-implementation are NOT parallel in the
|
|
402
|
+
// classic sense (dev writes, qa reviews per-task), so they're not in a
|
|
403
|
+
// parallel group. But under Agent Teams, they coordinate via mailbox + shared
|
|
404
|
+
// task list, which IS the team mechanism. Spawn Build Team here when dev
|
|
405
|
+
// would otherwise spawn solo.
|
|
406
|
+
const teamConfig = TEAM_CONFIGS.build;
|
|
407
|
+
const teamId = generateTeamId(teamConfig.slug);
|
|
408
|
+
action = 'spawn_team';
|
|
409
|
+
parallelAgents = teamConfig.members;
|
|
410
|
+
teamData = { team_id: teamId, team_type: 'build', members: teamConfig.members };
|
|
402
411
|
} else if (isInteractive) {
|
|
403
412
|
action = 'activate_interactive';
|
|
404
413
|
} else {
|
|
@@ -978,12 +987,33 @@ function generateTeamId(slug) {
|
|
|
978
987
|
return `TM-${date}-${slug}`;
|
|
979
988
|
}
|
|
980
989
|
|
|
990
|
+
/**
|
|
991
|
+
* Agent Teams require BOTH the feature flag AND a Claude provider.
|
|
992
|
+
*
|
|
993
|
+
* Why provider gate: Agent Teams uses Claude Code's native Task tool / subagent
|
|
994
|
+
* spawn API. Gemini and Codex have no equivalent — calling spawn_team for those
|
|
995
|
+
* providers would fail. We always fall back silently to spawn_parallel
|
|
996
|
+
* (Gemini) or spawn_autonomous (Codex) when the active provider is not claude.
|
|
997
|
+
*/
|
|
981
998
|
function isAgentTeamsEnabled(projectDir) {
|
|
982
999
|
const configPath = join(projectDir, 'chati.dev', 'config.yaml');
|
|
983
1000
|
if (!existsSync(configPath)) return false;
|
|
984
1001
|
const raw = readFileSync(configPath, 'utf-8');
|
|
985
|
-
|
|
986
|
-
|
|
1002
|
+
|
|
1003
|
+
// Feature flag check
|
|
1004
|
+
const flagMatch = raw.match(/agent_teams:\s*(true|false)/);
|
|
1005
|
+
const flagOn = flagMatch ? flagMatch[1] === 'true' : false;
|
|
1006
|
+
if (!flagOn) return false;
|
|
1007
|
+
|
|
1008
|
+
// Provider gate — Agent Teams is Claude-only.
|
|
1009
|
+
// Read primary_provider from session.yaml (preferred) or active_provider
|
|
1010
|
+
// field. Default to 'claude' if neither exists (early bootstrap).
|
|
1011
|
+
const sessionPath = join(projectDir, '.chati', 'session.yaml');
|
|
1012
|
+
if (!existsSync(sessionPath)) return true; // No session yet — assume claude
|
|
1013
|
+
const sessionRaw = readFileSync(sessionPath, 'utf-8');
|
|
1014
|
+
const providerMatch = sessionRaw.match(/^\s*(?:active_provider|primary_provider):\s*["']?(\w+)/m);
|
|
1015
|
+
const provider = providerMatch ? providerMatch[1] : 'claude';
|
|
1016
|
+
return provider === 'claude';
|
|
987
1017
|
}
|
|
988
1018
|
|
|
989
1019
|
async function handleSpawnTeam(projectDir, args) {
|