chati-dev 4.5.11 → 4.5.13
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 +2 -2
- package/framework/constitution.md +21 -22
- package/framework/context/root.md +1 -1
- package/framework/data/entity-registry.yaml +1 -1
- package/framework/domains/constitution.yaml +1 -1
- package/framework/domains/workflows/brownfield-fullstack.yaml +5 -3
- package/framework/domains/workflows/brownfield-service.yaml +2 -3
- package/framework/domains/workflows/brownfield-ui.yaml +2 -3
- package/framework/domains/workflows/greenfield-fullstack.yaml +5 -3
- package/framework/domains/workflows/quick-flow.yaml +7 -6
- package/framework/domains/workflows/standard-flow.yaml +4 -5
- package/framework/frameworks/quality-dimensions.yaml +3 -3
- package/framework/manifest.json +37 -37
- package/framework/manifest.sig +1 -1
- package/framework/schemas/session.schema.json +1 -1
- package/framework/workflows/brownfield-fullstack.yaml +17 -123
- package/framework/workflows/brownfield-service.yaml +15 -109
- package/framework/workflows/brownfield-ui.yaml +15 -115
- package/framework/workflows/greenfield-fullstack.yaml +17 -130
- package/framework/workflows/quick-flow.yaml +20 -111
- package/framework/workflows/standard-flow.yaml +14 -158
- package/package.json +1 -1
- package/src/config/claude-settings-generator.js +4 -3
- package/src/config/context-file-generator.js +10 -1
- package/src/config/framework-adapter.js +31 -0
- package/src/installer/core.js +89 -8
- package/src/installer/templates.js +33 -3
- package/src/installer/validator.js +8 -2
- package/src/intelligence/registry-manager.js +11 -4
- package/src/orchestrator/cli.js +54 -28
- package/src/terminal/handoff-parser.js +23 -4
- package/src/terminal/prompt-builder.js +15 -1
- package/src/terminal/provider-preflight.js +78 -0
- package/src/terminal/run-agent.js +66 -23
- package/src/terminal/spawner.js +5 -1
- package/src/utils/schema-validator.js +5 -2
- package/src/wizard/index.js +1 -0
|
@@ -1,127 +1,36 @@
|
|
|
1
|
-
# Quick Flow Workflow
|
|
2
|
-
# Fast-track pipeline for simple tasks: bug fixes, small features, config changes
|
|
3
|
-
# Skips full DISCOVER/PLAN phases when complexity is low
|
|
4
|
-
|
|
5
1
|
workflow:
|
|
6
2
|
id: quick-flow
|
|
7
|
-
name: Quick Flow
|
|
8
|
-
version: "
|
|
3
|
+
name: Quick Flow
|
|
4
|
+
version: "2.0.0"
|
|
9
5
|
type: any
|
|
10
6
|
project_types: [bug-fix, small-feature, config-change, hotfix, refactor]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Used when the orchestrator detects low complexity: clear requirements,
|
|
14
|
-
known codebase, small scope. Skips Detail, Architect, UX, Phases, Tasks,
|
|
15
|
-
and QA-Planning. Goes straight from Brief (quick) to Dev.
|
|
7
|
+
execution_authority: rail
|
|
8
|
+
description: Condensed planning with the same sealed RAIL and Release contracts as the full workflow.
|
|
16
9
|
|
|
17
10
|
detection:
|
|
18
|
-
# Orchestrator uses these signals to auto-detect quick-flow eligibility
|
|
19
|
-
triggers:
|
|
20
|
-
- "User explicitly requests quick fix or hotfix"
|
|
21
|
-
- "Single, well-defined requirement (can be stated in one sentence)"
|
|
22
|
-
- "Bug report with reproduction steps"
|
|
23
|
-
- "Configuration or environment change"
|
|
24
|
-
- "Small refactoring with clear scope"
|
|
25
|
-
- "User says 'just do it' or 'quick fix' or similar urgency signals"
|
|
26
|
-
- "Simple, fun, or experimental project (single-purpose tool, game, prototype)"
|
|
27
|
-
- "Single-page utility or learning project with no production requirements"
|
|
28
|
-
disqualifiers:
|
|
29
|
-
- "New feature requiring architecture decisions (multiple services, database design, auth system)"
|
|
30
|
-
- "Multiple interconnected requirements (>3 distinct features)"
|
|
31
|
-
- "Complex greenfield project (enterprise, multi-service, compliance requirements)"
|
|
32
|
-
- "Enterprise or compliance context"
|
|
33
|
-
- "User explicitly requests full pipeline"
|
|
34
|
-
- "Scope involves more than 5 files"
|
|
35
|
-
- "Requires database schema changes"
|
|
36
|
-
- "Requires new API endpoints (>2)"
|
|
37
|
-
|
|
38
11
|
confidence_threshold: 0.8
|
|
39
12
|
user_confirmation: true
|
|
13
|
+
disqualifiers:
|
|
14
|
+
- architecture decision required
|
|
15
|
+
- more than five files expected
|
|
16
|
+
- database schema change
|
|
17
|
+
- more than two new API endpoints
|
|
40
18
|
|
|
41
19
|
phases:
|
|
42
20
|
- phase: 0
|
|
43
|
-
name:
|
|
44
|
-
category:
|
|
45
|
-
sequence:
|
|
46
|
-
- agent: brief
|
|
47
|
-
action: quick-extraction
|
|
48
|
-
creates: [artifacts/1-Brief/quick-brief.md]
|
|
49
|
-
notes: >
|
|
50
|
-
Condensed extraction: single-pass, no 5-phase process.
|
|
51
|
-
Capture: what, why, constraints, acceptance criteria.
|
|
52
|
-
Duration: 2-5 min max.
|
|
53
|
-
template: quick-brief-tmpl.yaml
|
|
54
|
-
config:
|
|
55
|
-
max_rounds: 2
|
|
56
|
-
require_approval: true
|
|
57
|
-
|
|
58
|
-
- phase: 1
|
|
59
|
-
name: Implementation
|
|
60
|
-
category: BUILD
|
|
61
|
-
sequence:
|
|
62
|
-
- agent: dev
|
|
63
|
-
action: implement-tasks
|
|
64
|
-
notes: >
|
|
65
|
-
Dev works directly from Quick Brief (no PRD, no architecture doc).
|
|
66
|
-
Scope is tight: fix the bug, add the small feature, make the change.
|
|
67
|
-
Self-critique checklist still applies.
|
|
68
|
-
|
|
69
|
-
- phase: 2
|
|
70
|
-
name: Validation
|
|
71
|
-
category: BUILD
|
|
72
|
-
sequence:
|
|
73
|
-
- agent: qa-implementation
|
|
74
|
-
action: validate-code
|
|
75
|
-
creates: [artifacts/9-QA-Implementation/qa-implementation-report.md]
|
|
76
|
-
notes: >
|
|
77
|
-
Full QA-Implementation validation still applies (no shortcuts on quality).
|
|
78
|
-
Adversarial review still mandatory.
|
|
79
|
-
Tests must pass, SAST must be clean.
|
|
80
|
-
config:
|
|
81
|
-
adversarial_review: true
|
|
82
|
-
minimum_findings: 3
|
|
83
|
-
|
|
84
|
-
- phase: 3
|
|
85
|
-
name: Deployment
|
|
86
|
-
category: DEPLOY
|
|
21
|
+
name: Compact Planning
|
|
22
|
+
category: PLAN
|
|
87
23
|
sequence:
|
|
88
|
-
- agent:
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
24
|
+
- { agent: brief, action: quick-extraction, creates: [artifacts/1-Brief/quick-brief.md] }
|
|
25
|
+
- { agent: tasks, action: compact-sealed-task-graph, creates: [artifacts/6-Tasks/tasks.md] }
|
|
26
|
+
- { agent: qa-planning, action: validate-compact-plan, creates: [artifacts/7-QA-Planning/qa-planning-report.md] }
|
|
27
|
+
- { phase: 1, name: RAIL Execution, category: RAIL, runtime: project-local-rail }
|
|
28
|
+
- { phase: 2, name: Release Lane, category: RELEASE, requires: [rail_complete, independent_review_approved, explicit_human_authorization] }
|
|
92
29
|
|
|
93
30
|
transitions:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
type: automatic
|
|
97
|
-
action: "Skip full PLAN phase, go directly to BUILD"
|
|
98
|
-
notes: "No Detail, Architect, UX, Phases, Tasks, or QA-Planning"
|
|
99
|
-
build_to_validate:
|
|
100
|
-
trigger: "dev.status == completed"
|
|
101
|
-
type: automatic
|
|
102
|
-
action: "Update project.state = validate"
|
|
103
|
-
validate_to_deploy:
|
|
104
|
-
trigger: "qa-implementation.status == approved"
|
|
105
|
-
type: automatic
|
|
106
|
-
action: "Update project.state = deploy"
|
|
107
|
-
notes: "User preview skipped for quick-flow (scope too small)"
|
|
108
|
-
deploy_to_completed:
|
|
109
|
-
trigger: "devops.status == completed"
|
|
110
|
-
type: automatic
|
|
111
|
-
action: "Update project.state = completed"
|
|
31
|
+
plan_to_rail: { trigger: "qa-planning.score >= 95 && tasks.handoff == sealed", target: rail }
|
|
32
|
+
rail_to_release: { trigger: "rail.all_tasks_approved == true", target: release }
|
|
112
33
|
|
|
113
34
|
escalation:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
- "Dev discovers the change is more complex than expected"
|
|
117
|
-
- "QA-Implementation finds architectural issues"
|
|
118
|
-
- "Scope creep detected (>5 files, new APIs, schema changes)"
|
|
119
|
-
- "Dev agent requests escalation"
|
|
120
|
-
action: >
|
|
121
|
-
Pause quick-flow, notify user:
|
|
122
|
-
"This task is more complex than initially estimated.
|
|
123
|
-
Recommend switching to full pipeline for proper planning.
|
|
124
|
-
Options:
|
|
125
|
-
1. Switch to full pipeline (Recommended)
|
|
126
|
-
2. Continue with quick-flow (document risk)
|
|
127
|
-
3. Abort and reassess"
|
|
35
|
+
triggers: [scope-expansion, architecture-decision, planning-gate-failure]
|
|
36
|
+
action: restart with the appropriate full planning workflow
|
|
@@ -1,174 +1,30 @@
|
|
|
1
|
-
# Standard Flow Workflow
|
|
2
|
-
# Mid-tier pipeline for moderate tasks: new features, integrations, brownfield enhancements
|
|
3
|
-
# Uses 8 agents — between Quick Flow (4) and Full Flow (12)
|
|
4
|
-
|
|
5
1
|
workflow:
|
|
6
2
|
id: standard-flow
|
|
7
|
-
name: Standard Flow
|
|
8
|
-
version: "
|
|
3
|
+
name: Standard Flow
|
|
4
|
+
version: "2.0.0"
|
|
9
5
|
type: any
|
|
10
6
|
project_types: [feature, integration, enhancement, module, component, brownfield-moderate]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
but not the full 12-agent pipeline. Skips WU (assumes existing codebase
|
|
14
|
-
context), UX (no design-heavy work), and Phases (tasks agent handles
|
|
15
|
-
scope directly). Ideal for 2-5 requirements in brownfield projects.
|
|
16
|
-
|
|
17
|
-
detection:
|
|
18
|
-
triggers:
|
|
19
|
-
- "Moderate complexity feature with 2-5 requirements"
|
|
20
|
-
- "Brownfield project enhancement or integration"
|
|
21
|
-
- "New module or component within existing architecture"
|
|
22
|
-
- "User explicitly requests standard flow"
|
|
23
|
-
- "Feature that needs architecture review but not full UX design"
|
|
24
|
-
- "API integration or service connection"
|
|
25
|
-
- "Database-backed feature with clear data model"
|
|
26
|
-
disqualifiers:
|
|
27
|
-
- "Quick fix, hotfix, or single-line change (use Quick Flow)"
|
|
28
|
-
- "Enterprise-scale project with compliance requirements (use Full Flow)"
|
|
29
|
-
- "Greenfield project requiring full discovery (use Full Flow)"
|
|
30
|
-
- "UX-heavy feature requiring design system work (use Full Flow)"
|
|
31
|
-
- "Multi-service architecture changes (use Full Flow)"
|
|
32
|
-
- "User explicitly requests full pipeline"
|
|
33
|
-
|
|
34
|
-
confidence_threshold: 0.8
|
|
35
|
-
user_confirmation: true
|
|
36
|
-
|
|
37
|
-
agents:
|
|
38
|
-
included:
|
|
39
|
-
- brief
|
|
40
|
-
- detail
|
|
41
|
-
- architect
|
|
42
|
-
- tasks
|
|
43
|
-
- qa-planning # runs inside Planning Team; score synced via team dissolution
|
|
44
|
-
- dev
|
|
45
|
-
- qa-implementation
|
|
46
|
-
- devops
|
|
47
|
-
excluded:
|
|
48
|
-
- greenfield-wu
|
|
49
|
-
- brownfield-wu
|
|
50
|
-
- ux
|
|
51
|
-
- phases
|
|
7
|
+
execution_authority: rail
|
|
8
|
+
description: Balanced planning followed by the canonical RAIL and Release contracts.
|
|
52
9
|
|
|
53
10
|
phases:
|
|
54
11
|
- phase: 0
|
|
55
12
|
name: Discovery
|
|
56
13
|
category: DISCOVER
|
|
57
14
|
sequence:
|
|
58
|
-
- agent: brief
|
|
59
|
-
action: extract-requirements
|
|
60
|
-
creates: [artifacts/1-Brief/brief.md]
|
|
61
|
-
notes: >
|
|
62
|
-
Full brief extraction (5 phases). Since no WU precedes it,
|
|
63
|
-
Brief must also capture codebase context from user input.
|
|
64
|
-
config:
|
|
65
|
-
max_rounds: 5
|
|
66
|
-
require_approval: true
|
|
67
|
-
|
|
15
|
+
- { agent: brief, action: problem-extraction, creates: [artifacts/1-Brief/brief-report.md] }
|
|
68
16
|
- phase: 1
|
|
69
17
|
name: Planning
|
|
70
18
|
category: PLAN
|
|
71
19
|
sequence:
|
|
72
|
-
- agent: detail
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- agent: architect
|
|
79
|
-
action: design-architecture
|
|
80
|
-
creates: [artifacts/3-Architecture/architecture.md]
|
|
81
|
-
notes: "Architecture decisions, no UX constraints needed"
|
|
82
|
-
parallel_with: [detail]
|
|
83
|
-
|
|
84
|
-
- agent: tasks
|
|
85
|
-
action: create-tasks
|
|
86
|
-
creates: [artifacts/5-Tasks/tasks.md]
|
|
87
|
-
notes: >
|
|
88
|
-
Tasks agent works directly from PRD + Architecture.
|
|
89
|
-
No phases agent — tasks agent determines task breakdown directly.
|
|
90
|
-
|
|
91
|
-
- agent: qa-planning
|
|
92
|
-
action: validate-plan
|
|
93
|
-
creates: [artifacts/6-QA-Planning/qa-planning-report.md]
|
|
94
|
-
notes: >
|
|
95
|
-
Runs inside Planning Team (Article XXI), not as a standalone step.
|
|
96
|
-
Activates after Detail, Architect complete. Score >= 95% required to advance.
|
|
97
|
-
Score synced to session.yaml by orchestrator on team dissolution.
|
|
98
|
-
config:
|
|
99
|
-
minimum_score: 95
|
|
100
|
-
|
|
101
|
-
- phase: 2
|
|
102
|
-
name: Implementation
|
|
103
|
-
category: BUILD
|
|
104
|
-
sequence:
|
|
105
|
-
- agent: dev
|
|
106
|
-
action: implement-tasks
|
|
107
|
-
notes: "Dev works from full PRD + architecture + tasks"
|
|
108
|
-
|
|
109
|
-
- agent: qa-implementation
|
|
110
|
-
action: validate-code
|
|
111
|
-
creates: [artifacts/9-QA-Implementation/qa-implementation-report.md]
|
|
112
|
-
notes: >
|
|
113
|
-
Full QA-Implementation validation. Score >= 95% required.
|
|
114
|
-
Adversarial review mandatory.
|
|
115
|
-
config:
|
|
116
|
-
adversarial_review: true
|
|
117
|
-
minimum_findings: 5
|
|
118
|
-
minimum_score: 95
|
|
119
|
-
|
|
120
|
-
- phase: 3
|
|
121
|
-
name: Deployment
|
|
122
|
-
category: DEPLOY
|
|
123
|
-
sequence:
|
|
124
|
-
- agent: devops
|
|
125
|
-
action: deploy
|
|
126
|
-
creates: [artifacts/10-Deploy/deploy-report.md]
|
|
127
|
-
notes: "Standard deployment process"
|
|
20
|
+
- { agent: detail, action: create-prd, creates: [artifacts/2-PRD/prd.md] }
|
|
21
|
+
- { agent: architect, action: focused-architecture, creates: [artifacts/3-Architecture/architecture.md] }
|
|
22
|
+
- { agent: tasks, action: seal-task-graph, creates: [artifacts/6-Tasks/tasks.md] }
|
|
23
|
+
- { agent: qa-planning, action: validate-planning, creates: [artifacts/7-QA-Planning/qa-planning-report.md] }
|
|
24
|
+
- { phase: 2, name: RAIL Execution, category: RAIL, runtime: project-local-rail }
|
|
25
|
+
- { phase: 3, name: Release Lane, category: RELEASE, requires: [rail_complete, independent_review_approved, explicit_human_authorization] }
|
|
128
26
|
|
|
129
27
|
transitions:
|
|
130
|
-
discover_to_plan:
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
action: "Advance to PLAN phase"
|
|
134
|
-
plan_to_build:
|
|
135
|
-
trigger: "qa-planning.score >= 95"
|
|
136
|
-
type: automatic
|
|
137
|
-
action: "Advance to BUILD phase"
|
|
138
|
-
build_to_validate:
|
|
139
|
-
trigger: "dev.status == completed"
|
|
140
|
-
type: automatic
|
|
141
|
-
action: "Run QA-Implementation"
|
|
142
|
-
validate_to_deploy:
|
|
143
|
-
trigger: "qa-implementation.score >= 95"
|
|
144
|
-
type: user_preview
|
|
145
|
-
action: "User preview gate, then advance to DEPLOY"
|
|
146
|
-
deploy_to_completed:
|
|
147
|
-
trigger: "devops.status == completed"
|
|
148
|
-
type: automatic
|
|
149
|
-
action: "Pipeline complete"
|
|
150
|
-
|
|
151
|
-
escalation:
|
|
152
|
-
to_full_flow:
|
|
153
|
-
triggers:
|
|
154
|
-
- "Architect discovers multi-service complexity"
|
|
155
|
-
- "QA-Planning finds UX requirements not addressed"
|
|
156
|
-
- "Scope creep: more than 5 distinct requirements discovered"
|
|
157
|
-
- "User requests full pipeline"
|
|
158
|
-
action: >
|
|
159
|
-
Pause standard-flow, notify user:
|
|
160
|
-
"This task is more complex than the standard flow can handle.
|
|
161
|
-
Options:
|
|
162
|
-
1. Switch to full pipeline (Recommended)
|
|
163
|
-
2. Continue with standard flow (document gaps)
|
|
164
|
-
3. Reduce scope and continue"
|
|
165
|
-
to_quick_flow:
|
|
166
|
-
triggers:
|
|
167
|
-
- "Detail agent finds only 1 simple requirement"
|
|
168
|
-
- "Architect confirms no architecture changes needed"
|
|
169
|
-
action: >
|
|
170
|
-
Suggest downgrade:
|
|
171
|
-
"This task might be simpler than expected.
|
|
172
|
-
Options:
|
|
173
|
-
1. Switch to quick flow (faster)
|
|
174
|
-
2. Continue with standard flow"
|
|
28
|
+
discover_to_plan: { trigger: "brief.status == completed", target: plan }
|
|
29
|
+
plan_to_rail: { trigger: "qa-planning.score >= 95 && tasks.handoff == sealed", target: rail }
|
|
30
|
+
rail_to_release: { trigger: "rail.all_tasks_approved == true", target: release }
|
package/package.json
CHANGED
|
@@ -176,10 +176,11 @@ const PERMISSIONS_DENY = [
|
|
|
176
176
|
* Group HOOK_REGISTRY entries by event, then by matcher within each event.
|
|
177
177
|
* Returns the shape Claude Code expects under the top-level "hooks" key.
|
|
178
178
|
*/
|
|
179
|
-
function buildHooksObject() {
|
|
179
|
+
function buildHooksObject(options = {}) {
|
|
180
180
|
const events = {};
|
|
181
181
|
|
|
182
182
|
for (const entry of HOOK_REGISTRY) {
|
|
183
|
+
if (options.runtimeVersion === 2 && entry.name === 'post-dev') continue;
|
|
183
184
|
if (!events[entry.event]) events[entry.event] = new Map();
|
|
184
185
|
const matcherGroups = events[entry.event];
|
|
185
186
|
if (!matcherGroups.has(entry.matcher)) {
|
|
@@ -208,7 +209,7 @@ function buildHooksObject() {
|
|
|
208
209
|
*
|
|
209
210
|
* @returns {string} JSON string with trailing newline, ready to write to disk.
|
|
210
211
|
*/
|
|
211
|
-
export function generateClaudeSettings() {
|
|
212
|
+
export function generateClaudeSettings(options = {}) {
|
|
212
213
|
const settings = {
|
|
213
214
|
$schema: 'https://json.schemastore.org/claude-code-settings.json',
|
|
214
215
|
permissions: {
|
|
@@ -216,7 +217,7 @@ export function generateClaudeSettings() {
|
|
|
216
217
|
deny: PERMISSIONS_DENY,
|
|
217
218
|
defaultMode: 'default',
|
|
218
219
|
},
|
|
219
|
-
hooks: buildHooksObject(),
|
|
220
|
+
hooks: buildHooksObject(options),
|
|
220
221
|
};
|
|
221
222
|
|
|
222
223
|
return JSON.stringify(settings, null, 2) + '\n';
|
|
@@ -68,10 +68,17 @@ function buildCodexReplacements(frameworkDir = 'chati.dev') {
|
|
|
68
68
|
['claude --print', 'codex exec'],
|
|
69
69
|
['claude -p', 'codex exec'],
|
|
70
70
|
['CLAUDE.local.md', 'AGENTS.override.md'],
|
|
71
|
-
['/chati', '$chati'],
|
|
72
71
|
];
|
|
73
72
|
}
|
|
74
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Convert the interactive slash command without touching filesystem paths such
|
|
76
|
+
* as `.chati.dev/orchestrator/chati.md`.
|
|
77
|
+
*/
|
|
78
|
+
function adaptCodexInvocation(content) {
|
|
79
|
+
return content.replace(/(?<![\w/])\/chati(?=\s|$|[`'".,;:!?)]|\b)/gm, '$chati');
|
|
80
|
+
}
|
|
81
|
+
|
|
75
82
|
// ---------------------------------------------------------------------------
|
|
76
83
|
// Generators
|
|
77
84
|
// ---------------------------------------------------------------------------
|
|
@@ -144,6 +151,7 @@ export function generateAgentsMd(content, contextFiles = null, frameworkDir = 'c
|
|
|
144
151
|
for (const [search, replace] of replacements) {
|
|
145
152
|
result = result.replaceAll(search, replace);
|
|
146
153
|
}
|
|
154
|
+
result = adaptCodexInvocation(result);
|
|
147
155
|
|
|
148
156
|
// Clean up any double blank lines left by stripping
|
|
149
157
|
result = result.replace(/\n{3,}/g, '\n\n');
|
|
@@ -166,6 +174,7 @@ export function generateAgentsMd(content, contextFiles = null, frameworkDir = 'c
|
|
|
166
174
|
for (const [search, replace] of replacements) {
|
|
167
175
|
adapted = adapted.replaceAll(search, replace);
|
|
168
176
|
}
|
|
177
|
+
adapted = adaptCodexInvocation(adapted);
|
|
169
178
|
sections.push(adapted.trim());
|
|
170
179
|
}
|
|
171
180
|
}
|
|
@@ -65,6 +65,30 @@ const PROVIDER_META = {
|
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
|
|
68
|
+
const CODEX_CREDENTIAL_BOUNDARY = `
|
|
69
|
+
## Codex external provider credential boundary
|
|
70
|
+
|
|
71
|
+
Commands returned in any \`spawn_command\`, \`parallel_spawn_command\` or
|
|
72
|
+
\`parallel_spawn_commands\` start another provider CLI. Codex MUST execute each
|
|
73
|
+
of these commands with native escalated execution so the child CLI can access
|
|
74
|
+
its existing local credentials:
|
|
75
|
+
|
|
76
|
+
- Set \`sandbox_permissions\` to \`require_escalated\`.
|
|
77
|
+
- Explain that Chati needs to run the selected provider CLI using its existing
|
|
78
|
+
local authentication.
|
|
79
|
+
- Offer the narrow reusable prefix made from the first two command arguments:
|
|
80
|
+
\`["node", "<absolute path from the command to run-agent.js>"]\`.
|
|
81
|
+
- Keep the project working directory and the router-provided command unchanged.
|
|
82
|
+
|
|
83
|
+
Never test a routed provider command inside the workspace sandbox first. A
|
|
84
|
+
\`PROVIDER_NOT_READY\` or \`PROVIDER_NOT_AUTHENTICATED\` result obtained inside
|
|
85
|
+
that sandbox is inconclusive because the sandbox can hide OS credentials. If a
|
|
86
|
+
sandboxed attempt already failed, rerun it once with native escalated execution.
|
|
87
|
+
Only a failure from that escalated attempt may be reported as an authentication
|
|
88
|
+
failure. Do not repeat the same sandboxed command and do not offer to skip a
|
|
89
|
+
required v2 pipeline stage.
|
|
90
|
+
`;
|
|
91
|
+
|
|
68
92
|
// ---------------------------------------------------------------------------
|
|
69
93
|
// Replacement Configuration Builder
|
|
70
94
|
// ---------------------------------------------------------------------------
|
|
@@ -225,5 +249,12 @@ export function adaptFrameworkFile(content, filePath, provider) {
|
|
|
225
249
|
result = result.replace(pattern, replacement);
|
|
226
250
|
}
|
|
227
251
|
|
|
252
|
+
if (provider === 'codex' && filePath === 'orchestrator/chati.md') {
|
|
253
|
+
const routedAction = '## Action: Routed Interactive Agent';
|
|
254
|
+
result = result.includes(routedAction)
|
|
255
|
+
? result.replace(routedAction, `${CODEX_CREDENTIAL_BOUNDARY}\n${routedAction}`)
|
|
256
|
+
: `${result.trimEnd()}\n\n${CODEX_CREDENTIAL_BOUNDARY.trimStart()}`;
|
|
257
|
+
}
|
|
258
|
+
|
|
228
259
|
return result;
|
|
229
260
|
}
|
package/src/installer/core.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync, copyFileSync, existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
1
|
+
import { mkdirSync, writeFileSync, copyFileSync, existsSync, readFileSync, readdirSync, statSync, rmSync } from 'fs';
|
|
2
2
|
import { execFileSync } from 'child_process';
|
|
3
3
|
import { join, dirname } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
@@ -12,6 +12,7 @@ import { generateClaudeSettings } from '../config/claude-settings-generator.js';
|
|
|
12
12
|
import { generateProviderOverlays } from './provider-overlay.js';
|
|
13
13
|
import { applyInstalledPathReplacement } from './path-replacement.js';
|
|
14
14
|
import { verifyManifest } from './manifest.js';
|
|
15
|
+
import * as yaml from 'js-yaml';
|
|
15
16
|
|
|
16
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
|
|
@@ -70,7 +71,13 @@ export async function installFramework(config) {
|
|
|
70
71
|
|
|
71
72
|
// 2b. Create artifacts/ at PROJECT ROOT (visible to user — this is their output)
|
|
72
73
|
const artifactsDir = join(targetDir, 'artifacts');
|
|
73
|
-
const
|
|
74
|
+
const isRuntimeV2 = config.runtimeVersion === 2;
|
|
75
|
+
const artifactDirs = isRuntimeV2 ? [
|
|
76
|
+
'0-WU', '1-Brief', '2-PRD',
|
|
77
|
+
'3-Architecture', '4-UX', '5-Phases',
|
|
78
|
+
'6-Tasks', '7-QA-Planning', '8-RAIL', '9-Release',
|
|
79
|
+
'handoffs', 'decisions',
|
|
80
|
+
] : [
|
|
74
81
|
'0-WU', '1-Brief', '2-PRD',
|
|
75
82
|
'3-Architecture', '4-UX', '5-Phases',
|
|
76
83
|
'6-Tasks', '7-QA-Planning', '8-QA-Visual', '9-QA-Implementation', '10-Deploy',
|
|
@@ -96,7 +103,7 @@ export async function installFramework(config) {
|
|
|
96
103
|
|
|
97
104
|
// Create .chati/memories/ directory tree for Memory Layer
|
|
98
105
|
const memoriesBase = join(targetDir, '.chati', 'memories');
|
|
99
|
-
const
|
|
106
|
+
const planningMemoryDirs = [
|
|
100
107
|
'shared/durable', 'shared/daily', 'shared/session',
|
|
101
108
|
'greenfield-wu/durable', 'greenfield-wu/daily',
|
|
102
109
|
'brownfield-wu/durable', 'brownfield-wu/daily',
|
|
@@ -107,11 +114,16 @@ export async function installFramework(config) {
|
|
|
107
114
|
'phases/durable', 'phases/daily',
|
|
108
115
|
'tasks/durable', 'tasks/daily',
|
|
109
116
|
'qa-planning/durable', 'qa-planning/daily',
|
|
117
|
+
];
|
|
118
|
+
const legacyExecutionMemoryDirs = [
|
|
110
119
|
'qa-implementation/durable', 'qa-implementation/daily',
|
|
111
120
|
'qa-visual/durable', 'qa-visual/daily',
|
|
112
121
|
'dev/durable', 'dev/daily',
|
|
113
122
|
'devops/durable', 'devops/daily',
|
|
114
123
|
];
|
|
124
|
+
const memoryDirs = isRuntimeV2
|
|
125
|
+
? [...planningMemoryDirs, 'rail/durable', 'rail/daily', 'release/durable', 'release/daily']
|
|
126
|
+
: [...planningMemoryDirs, ...legacyExecutionMemoryDirs];
|
|
115
127
|
for (const dir of memoryDirs) {
|
|
116
128
|
createDir(join(memoriesBase, dir));
|
|
117
129
|
}
|
|
@@ -125,6 +137,11 @@ export async function installFramework(config) {
|
|
|
125
137
|
generateProviderOverlays(targetDir, FRAMEWORK_SOURCE, allProviders);
|
|
126
138
|
}
|
|
127
139
|
|
|
140
|
+
if (isRuntimeV2) {
|
|
141
|
+
pruneLegacyExecutionSurface(frameworkDir, allProviders || []);
|
|
142
|
+
pruneLegacyRegistryEntities(frameworkDir);
|
|
143
|
+
}
|
|
144
|
+
|
|
128
145
|
// Bundle the CLI source into the framework dir so chati-router.js can run
|
|
129
146
|
// commands locally without depending on `npx chati-dev` (which fetches from
|
|
130
147
|
// the npm registry — version drift causes inconsistent behavior).
|
|
@@ -162,7 +179,7 @@ export async function installFramework(config) {
|
|
|
162
179
|
// Write config.yaml
|
|
163
180
|
writeFileSync(
|
|
164
181
|
join(frameworkDir, 'config.yaml'),
|
|
165
|
-
generateConfigYaml({ version, projectType, language, selectedIDEs, allProviders }),
|
|
182
|
+
generateConfigYaml({ version, projectType, language, selectedIDEs, allProviders, runtimeVersion: config.runtimeVersion }),
|
|
166
183
|
'utf-8'
|
|
167
184
|
);
|
|
168
185
|
|
|
@@ -174,7 +191,12 @@ export async function installFramework(config) {
|
|
|
174
191
|
const orchestratorPath = hasProviderOverlay
|
|
175
192
|
? `.chati.dev/.adapted/${ideProvider}/orchestrator/chati.md`
|
|
176
193
|
: '.chati.dev/orchestrator/chati.md';
|
|
177
|
-
await configureIDE(targetDir, ideKey, selectedMCPs, {
|
|
194
|
+
await configureIDE(targetDir, ideKey, selectedMCPs, {
|
|
195
|
+
orchestratorPath,
|
|
196
|
+
isSecondary: false,
|
|
197
|
+
providerName: ideProvider,
|
|
198
|
+
runtimeVersion: config.runtimeVersion,
|
|
199
|
+
});
|
|
178
200
|
}
|
|
179
201
|
|
|
180
202
|
const hasClaude = selectedIDEs.includes('claude-code');
|
|
@@ -224,6 +246,55 @@ export async function installFramework(config) {
|
|
|
224
246
|
ensureGitRepository(targetDir);
|
|
225
247
|
}
|
|
226
248
|
|
|
249
|
+
function pruneLegacyRegistryEntities(frameworkDir) {
|
|
250
|
+
const registryPath = join(frameworkDir, 'data', 'entity-registry.yaml');
|
|
251
|
+
if (!existsSync(registryPath)) return;
|
|
252
|
+
const registry = yaml.load(readFileSync(registryPath, 'utf-8'));
|
|
253
|
+
if (!registry?.entities) return;
|
|
254
|
+
const legacyPath = /\/(?:agents\/(?:build|deploy)\/|agents\/quality\/qa-(?:implementation|visual)\.md$|hooks\/post-dev\.js$|templates\/team-build-tasks\.yaml$|quality-gates\/implementation-gate\.md$|domains\/agents\/(?:dev|devops|qa-implementation|qa-visual)\.yaml$|tasks\/(?:dev-|devops-|qa-impl-))/;
|
|
255
|
+
let count = 0;
|
|
256
|
+
for (const entities of Object.values(registry.entities)) {
|
|
257
|
+
if (!entities || typeof entities !== 'object') continue;
|
|
258
|
+
for (const [name, entity] of Object.entries(entities)) {
|
|
259
|
+
if (legacyPath.test(entity?.path || '')) delete entities[name];
|
|
260
|
+
else if (entity?.path) count += 1;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
registry.metadata = { ...(registry.metadata || {}), entity_count: count };
|
|
264
|
+
writeFileSync(registryPath, yaml.dump(registry, { lineWidth: -1 }), 'utf-8');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const V2_LEGACY_EXECUTION_PATHS = [
|
|
268
|
+
'agents/build',
|
|
269
|
+
'agents/deploy',
|
|
270
|
+
'agents/quality/qa-implementation.md',
|
|
271
|
+
'agents/quality/qa-visual.md',
|
|
272
|
+
'quality-gates/implementation-gate.md',
|
|
273
|
+
'templates/team-build-tasks.yaml',
|
|
274
|
+
'hooks/post-dev.js',
|
|
275
|
+
'domains/agents/dev.yaml',
|
|
276
|
+
'domains/agents/devops.yaml',
|
|
277
|
+
'domains/agents/qa-implementation.yaml',
|
|
278
|
+
'domains/agents/qa-visual.yaml',
|
|
279
|
+
];
|
|
280
|
+
|
|
281
|
+
function pruneLegacyExecutionSurface(frameworkDir, providers) {
|
|
282
|
+
const roots = [frameworkDir, ...providers.map(provider => join(frameworkDir, '.adapted', provider))];
|
|
283
|
+
for (const root of roots) {
|
|
284
|
+
for (const relativePath of V2_LEGACY_EXECUTION_PATHS) {
|
|
285
|
+
rmSync(join(root, relativePath), { recursive: true, force: true });
|
|
286
|
+
}
|
|
287
|
+
const tasksDir = join(root, 'tasks');
|
|
288
|
+
if (existsSync(tasksDir)) {
|
|
289
|
+
for (const entry of readdirSync(tasksDir)) {
|
|
290
|
+
if (/^(?:dev-|devops-|qa-impl-)/.test(entry)) {
|
|
291
|
+
rmSync(join(tasksDir, entry), { force: true });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
227
298
|
export function ensureGitRepository(targetDir) {
|
|
228
299
|
try {
|
|
229
300
|
execFileSync('git', ['-C', targetDir, 'rev-parse', '--show-toplevel'], { stdio: 'ignore' });
|
|
@@ -415,7 +486,7 @@ Parse the JSON output. This single command already handled: license validation,
|
|
|
415
486
|
// hook system and applies a baseline permission policy. THIS IS THE FILE
|
|
416
487
|
// CLAUDE CODE READS — without it, every hook in chati.dev/hooks/ is dormant.
|
|
417
488
|
// (Pre-v4.2.2 bug: this file was never written, hooks never ran.)
|
|
418
|
-
writeClaudeSettingsWithMerge(join(targetDir, '.claude', 'settings.json'));
|
|
489
|
+
writeClaudeSettingsWithMerge(join(targetDir, '.claude', 'settings.json'), { runtimeVersion: options.runtimeVersion });
|
|
419
490
|
|
|
420
491
|
// Claude project-scope MCP config lives at the project root. Preserve
|
|
421
492
|
// unknown user-managed servers while replacing CHATI's known entries.
|
|
@@ -883,9 +954,9 @@ export function copyCliDependencies(pkgDir, destNodeModules) {
|
|
|
883
954
|
* If the file exists but is malformed: leave it alone, log a warning. We will
|
|
884
955
|
* not silently destroy user data.
|
|
885
956
|
*/
|
|
886
|
-
export function writeClaudeSettingsWithMerge(settingsPath) {
|
|
957
|
+
export function writeClaudeSettingsWithMerge(settingsPath, options = {}) {
|
|
887
958
|
createDir(dirname(settingsPath));
|
|
888
|
-
const fresh = JSON.parse(generateClaudeSettings());
|
|
959
|
+
const fresh = JSON.parse(generateClaudeSettings(options));
|
|
889
960
|
|
|
890
961
|
if (!existsSync(settingsPath)) {
|
|
891
962
|
writeFileSync(settingsPath, JSON.stringify(fresh, null, 2) + '\n', 'utf-8');
|
|
@@ -900,6 +971,16 @@ export function writeClaudeSettingsWithMerge(settingsPath) {
|
|
|
900
971
|
return;
|
|
901
972
|
}
|
|
902
973
|
|
|
974
|
+
if (options.runtimeVersion === 2 && existing.hooks) {
|
|
975
|
+
for (const groups of Object.values(existing.hooks)) {
|
|
976
|
+
if (!Array.isArray(groups)) continue;
|
|
977
|
+
for (const group of groups) {
|
|
978
|
+
if (Array.isArray(group.hooks)) {
|
|
979
|
+
group.hooks = group.hooks.filter(hook => !/\.chati\.dev\/hooks\/post-dev\.js$/.test(hook.command || ''));
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
903
984
|
const merged = mergeClaudeSettings(existing, fresh);
|
|
904
985
|
writeFileSync(settingsPath, JSON.stringify(merged, null, 2) + '\n', 'utf-8');
|
|
905
986
|
}
|