@hongmaple0820/scale-engine 0.1.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/LICENSE +15 -0
- package/README.md +64 -0
- package/dist/adapters/ClaudeCodeAdapter.d.ts +48 -0
- package/dist/adapters/ClaudeCodeAdapter.js +188 -0
- package/dist/adapters/ClaudeCodeAdapter.js.map +1 -0
- package/dist/adapters/CodexAdapter.d.ts +14 -0
- package/dist/adapters/CodexAdapter.js +153 -0
- package/dist/adapters/CodexAdapter.js.map +1 -0
- package/dist/api/cli.d.ts +2 -0
- package/dist/api/cli.js +396 -0
- package/dist/api/cli.js.map +1 -0
- package/dist/api/doctor.d.ts +28 -0
- package/dist/api/doctor.js +182 -0
- package/dist/api/doctor.js.map +1 -0
- package/dist/api/mcp.d.ts +32 -0
- package/dist/api/mcp.js +227 -0
- package/dist/api/mcp.js.map +1 -0
- package/dist/artifact/fsm.d.ts +36 -0
- package/dist/artifact/fsm.js +199 -0
- package/dist/artifact/fsm.js.map +1 -0
- package/dist/artifact/fsmDefinitions.d.ts +18 -0
- package/dist/artifact/fsmDefinitions.js +243 -0
- package/dist/artifact/fsmDefinitions.js.map +1 -0
- package/dist/artifact/sqliteStore.d.ts +61 -0
- package/dist/artifact/sqliteStore.js +394 -0
- package/dist/artifact/sqliteStore.js.map +1 -0
- package/dist/artifact/store.d.ts +49 -0
- package/dist/artifact/store.js +118 -0
- package/dist/artifact/store.js.map +1 -0
- package/dist/artifact/types.d.ts +333 -0
- package/dist/artifact/types.js +50 -0
- package/dist/artifact/types.js.map +1 -0
- package/dist/context/ContextBuilder.d.ts +36 -0
- package/dist/context/ContextBuilder.js +53 -0
- package/dist/context/ContextBuilder.js.map +1 -0
- package/dist/core/container.d.ts +14 -0
- package/dist/core/container.js +33 -0
- package/dist/core/container.js.map +1 -0
- package/dist/core/eventBus.d.ts +60 -0
- package/dist/core/eventBus.js +158 -0
- package/dist/core/eventBus.js.map +1 -0
- package/dist/core/logger.d.ts +3 -0
- package/dist/core/logger.js +12 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/evolution/BehaviorTracker.d.ts +38 -0
- package/dist/evolution/BehaviorTracker.js +52 -0
- package/dist/evolution/BehaviorTracker.js.map +1 -0
- package/dist/evolution/EvolutionEngine.d.ts +99 -0
- package/dist/evolution/EvolutionEngine.js +321 -0
- package/dist/evolution/EvolutionEngine.js.map +1 -0
- package/dist/guardrails/Gateway.d.ts +26 -0
- package/dist/guardrails/Gateway.js +57 -0
- package/dist/guardrails/Gateway.js.map +1 -0
- package/dist/guardrails/advancedDetectors.d.ts +26 -0
- package/dist/guardrails/advancedDetectors.js +138 -0
- package/dist/guardrails/advancedDetectors.js.map +1 -0
- package/dist/guardrails/detectors.d.ts +25 -0
- package/dist/guardrails/detectors.js +170 -0
- package/dist/guardrails/detectors.js.map +1 -0
- package/dist/guardrails/roles.d.ts +4 -0
- package/dist/guardrails/roles.js +54 -0
- package/dist/guardrails/roles.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/KnowledgeBase.d.ts +25 -0
- package/dist/knowledge/KnowledgeBase.js +81 -0
- package/dist/knowledge/KnowledgeBase.js.map +1 -0
- package/dist/orchestration/EffectsWiring.d.ts +8 -0
- package/dist/orchestration/EffectsWiring.js +87 -0
- package/dist/orchestration/EffectsWiring.js.map +1 -0
- package/dist/routing/ModelRouter.d.ts +30 -0
- package/dist/routing/ModelRouter.js +69 -0
- package/dist/routing/ModelRouter.js.map +1 -0
- package/dist/tasks/TaskEngine.d.ts +97 -0
- package/dist/tasks/TaskEngine.js +269 -0
- package/dist/tasks/TaskEngine.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SCALE Engine Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# SCALE Engine
|
|
2
|
+
|
|
3
|
+
> **S**caffold · **C**ontrol · **A**rtifact · **L**earn · **E**volve
|
|
4
|
+
>
|
|
5
|
+
> AI 工程化脚手架引擎 — 让 AI Agent 在物理约束下工作,而不是靠提示词自律。
|
|
6
|
+
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
[]()
|
|
10
|
+
|
|
11
|
+
## 核心理念
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
提示词说 "你应该跑测试" → AI 可以假装跑了 ❌
|
|
15
|
+
Stop Hook 检查 "未跑测试" → AI 物理无法跳过 ✅
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 六层架构
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
L1 Context — Token 预算 + 上下文组装
|
|
22
|
+
L2 Guardrails — 8 检测器 + Role 网关
|
|
23
|
+
L3 Observability — EventBus + BehaviorTracker
|
|
24
|
+
L4 Orchestration — TaskEngine + Effects + ModelRouter
|
|
25
|
+
L5 Memory — KnowledgeBase + 衰减算法
|
|
26
|
+
L6 Evolution — Defect→Lesson→Rule→Hook 自进化
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 快速开始
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g @hongmaple0820/scale-engine
|
|
33
|
+
cd your-project
|
|
34
|
+
scale init --agent claude-code
|
|
35
|
+
scale doctor
|
|
36
|
+
scale create Spec "用户导出 Excel 功能"
|
|
37
|
+
scale transition SPEC-xxx refine
|
|
38
|
+
scale transition SPEC-xxx approve # ambiguity > 0.2 物理拦截
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## CLI 命令 (13 个)
|
|
42
|
+
|
|
43
|
+
| 命令 | 说明 |
|
|
44
|
+
|------|------|
|
|
45
|
+
| `scale init` | 初始化 (.scale/ + hooks + CLAUDE.md) |
|
|
46
|
+
| `scale doctor` | 环境诊断 + 健康检查 |
|
|
47
|
+
| `scale create` | 创建 Artifact |
|
|
48
|
+
| `scale list` | 列表查询 |
|
|
49
|
+
| `scale show` | 详情 |
|
|
50
|
+
| `scale transition` | 状态迁移 (含 guard) |
|
|
51
|
+
| `scale role` | 角色切换 |
|
|
52
|
+
| `scale context` | 组装上下文 |
|
|
53
|
+
| `scale evolve` | 进化周期 |
|
|
54
|
+
| `scale stats` | 统计 |
|
|
55
|
+
| `scale session` | 会话管理 |
|
|
56
|
+
| `scale gate` | 网关检查 |
|
|
57
|
+
|
|
58
|
+
## 11 种 Artifact · 4 级自进化 · 8 个检测器
|
|
59
|
+
|
|
60
|
+
详见 `docs/` 目录。
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
MIT
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export interface AdapterConfig {
|
|
2
|
+
projectDir: string;
|
|
3
|
+
scaleDir?: string;
|
|
4
|
+
agentType?: 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'gemini';
|
|
5
|
+
}
|
|
6
|
+
export interface HookEntry {
|
|
7
|
+
matcher: string;
|
|
8
|
+
command: string;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SettingsJson {
|
|
12
|
+
hooks?: Record<string, HookEntry[]>;
|
|
13
|
+
permissions?: {
|
|
14
|
+
allow?: string[];
|
|
15
|
+
deny?: string[];
|
|
16
|
+
};
|
|
17
|
+
mcpServers?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export interface IAgentAdapter {
|
|
20
|
+
readonly agentType: string;
|
|
21
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
22
|
+
getSettingsPath(): string;
|
|
23
|
+
getKnowledgeDocPath(): string;
|
|
24
|
+
generateSettings(): SettingsJson;
|
|
25
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
26
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
27
|
+
isInstalled(): boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface InitResult {
|
|
30
|
+
settingsPath: string;
|
|
31
|
+
knowledgeDocPath: string;
|
|
32
|
+
scaleDir: string;
|
|
33
|
+
created: string[];
|
|
34
|
+
skipped: string[];
|
|
35
|
+
}
|
|
36
|
+
export declare class ClaudeCodeAdapter implements IAgentAdapter {
|
|
37
|
+
readonly agentType = "claude-code";
|
|
38
|
+
private projectDir;
|
|
39
|
+
private scaleDir;
|
|
40
|
+
getSettingsPath(): string;
|
|
41
|
+
getKnowledgeDocPath(): string;
|
|
42
|
+
isInstalled(): boolean;
|
|
43
|
+
generateSettings(): SettingsJson;
|
|
44
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
45
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
46
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
47
|
+
}
|
|
48
|
+
export declare function createAdapter(agentType: string): IAgentAdapter;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// SCALE Engine — Claude Code Adapter (W8)
|
|
2
|
+
// 生成/合并 .claude/settings.json + CLAUDE.md
|
|
3
|
+
// 设计参考:docs/01-ARCHITECTURE.md 原则4 Headless优先
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { logger } from '../core/logger.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Claude Code Adapter
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export class ClaudeCodeAdapter {
|
|
11
|
+
agentType = 'claude-code';
|
|
12
|
+
projectDir = '.';
|
|
13
|
+
scaleDir = '.scale';
|
|
14
|
+
getSettingsPath() {
|
|
15
|
+
return join(this.projectDir, '.claude', 'settings.json');
|
|
16
|
+
}
|
|
17
|
+
getKnowledgeDocPath() {
|
|
18
|
+
return join(this.projectDir, 'CLAUDE.md');
|
|
19
|
+
}
|
|
20
|
+
isInstalled() {
|
|
21
|
+
return existsSync(this.getSettingsPath());
|
|
22
|
+
}
|
|
23
|
+
generateSettings() {
|
|
24
|
+
return {
|
|
25
|
+
hooks: {
|
|
26
|
+
SessionStart: [
|
|
27
|
+
{ matcher: '', command: 'scale session start --agent claude-code --session-id $CLAUDE_SESSION_ID' },
|
|
28
|
+
],
|
|
29
|
+
PreToolUse: [
|
|
30
|
+
{ matcher: 'Bash', command: 'scale gate pre-tool Bash --args-json $TOOL_INPUT_JSON --session-id $CLAUDE_SESSION_ID' },
|
|
31
|
+
{ matcher: 'Edit|Write|MultiEdit', command: 'scale gate pre-tool Edit --args-json $TOOL_INPUT_JSON --session-id $CLAUDE_SESSION_ID' },
|
|
32
|
+
],
|
|
33
|
+
PostToolUse: [
|
|
34
|
+
{ matcher: 'Edit|Write|MultiEdit', command: 'scale gate post-tool Edit --args-json $TOOL_INPUT_JSON --output-json $TOOL_OUTPUT_JSON --session-id $CLAUDE_SESSION_ID' },
|
|
35
|
+
{ matcher: 'Bash', command: 'scale gate post-tool Bash --args-json $TOOL_INPUT_JSON --exit-code $TOOL_EXIT_CODE --session-id $CLAUDE_SESSION_ID' },
|
|
36
|
+
],
|
|
37
|
+
Stop: [
|
|
38
|
+
{ matcher: '', command: 'scale gate before-stop --session-id $CLAUDE_SESSION_ID' },
|
|
39
|
+
],
|
|
40
|
+
SessionEnd: [
|
|
41
|
+
{ matcher: '', command: 'scale session end --session-id $CLAUDE_SESSION_ID' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
permissions: {
|
|
45
|
+
allow: ['Bash(scale:*)'],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
mergeSettings(existing) {
|
|
50
|
+
const generated = this.generateSettings();
|
|
51
|
+
const merged = { ...existing };
|
|
52
|
+
// Merge hooks — add SCALE hooks without overwriting existing
|
|
53
|
+
if (!merged.hooks)
|
|
54
|
+
merged.hooks = {};
|
|
55
|
+
for (const [hookType, entries] of Object.entries(generated.hooks)) {
|
|
56
|
+
if (!merged.hooks[hookType])
|
|
57
|
+
merged.hooks[hookType] = [];
|
|
58
|
+
for (const entry of entries) {
|
|
59
|
+
const alreadyExists = merged.hooks[hookType].some((e) => e.command.includes('scale '));
|
|
60
|
+
if (!alreadyExists) {
|
|
61
|
+
merged.hooks[hookType].push(entry);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Merge permissions
|
|
66
|
+
if (!merged.permissions)
|
|
67
|
+
merged.permissions = {};
|
|
68
|
+
if (!merged.permissions.allow)
|
|
69
|
+
merged.permissions.allow = [];
|
|
70
|
+
for (const perm of generated.permissions.allow) {
|
|
71
|
+
if (!merged.permissions.allow.includes(perm)) {
|
|
72
|
+
merged.permissions.allow.push(perm);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return merged;
|
|
76
|
+
}
|
|
77
|
+
generateKnowledgeDoc(projectName, techStack = []) {
|
|
78
|
+
const stackLine = techStack.length > 0
|
|
79
|
+
? `\n## Tech Stack\n${techStack.map((t) => `- ${t}`).join('\n')}\n`
|
|
80
|
+
: '';
|
|
81
|
+
return `# ${projectName}
|
|
82
|
+
${stackLine}
|
|
83
|
+
## SCALE Engine Integration
|
|
84
|
+
|
|
85
|
+
This project uses SCALE Engine for AI engineering governance.
|
|
86
|
+
|
|
87
|
+
### Commands
|
|
88
|
+
- \`scale create <type> <title>\` — Create artifact (Spec/Plan/Task/...)
|
|
89
|
+
- \`scale transition <id> <action>\` — Transition artifact state
|
|
90
|
+
- \`scale list --type Spec\` — List artifacts
|
|
91
|
+
- \`scale role activate <role>\` — Switch role (explorer/planner/implementer/reviewer)
|
|
92
|
+
- \`scale stats\` — Show engine stats
|
|
93
|
+
|
|
94
|
+
### Workflow
|
|
95
|
+
1. **Explore** → Role: explorer (Read/Grep only)
|
|
96
|
+
2. **Plan** → Create Spec → refine → approve (guard: ambiguity ≤ 0.2)
|
|
97
|
+
3. **Implement** → Role: implementer (Edit/Write/Bash unlocked)
|
|
98
|
+
4. **Verify** → Must run tests before claiming done (Stop gate enforced)
|
|
99
|
+
5. **Learn** → Defects auto-extract to lessons → rules → hooks
|
|
100
|
+
|
|
101
|
+
### Rules
|
|
102
|
+
- 🔴 Dangerous commands (rm -rf, DROP TABLE) are physically blocked
|
|
103
|
+
- 🔴 Hardcoded secrets are blocked on Edit/Write
|
|
104
|
+
- 🟡 3 identical retries triggers brute-retry detection
|
|
105
|
+
- 🟡 Claiming done without running tests is blocked
|
|
106
|
+
- 🟢 All tool calls are tracked in .scale/events/
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
async init(config) {
|
|
110
|
+
this.projectDir = config.projectDir;
|
|
111
|
+
this.scaleDir = config.scaleDir ?? join(config.projectDir, '.scale');
|
|
112
|
+
const created = [];
|
|
113
|
+
const skipped = [];
|
|
114
|
+
// 1. Create .scale/ directory structure
|
|
115
|
+
for (const dir of ['events', 'artifacts', 'rules', 'hooks', 'checkpoints']) {
|
|
116
|
+
const fullDir = join(this.scaleDir, dir);
|
|
117
|
+
if (!existsSync(fullDir)) {
|
|
118
|
+
mkdirSync(fullDir, { recursive: true });
|
|
119
|
+
created.push(fullDir);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
skipped.push(fullDir);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// 2. Create/merge .claude/settings.json
|
|
126
|
+
const settingsPath = this.getSettingsPath();
|
|
127
|
+
const claudeDir = join(this.projectDir, '.claude');
|
|
128
|
+
mkdirSync(claudeDir, { recursive: true });
|
|
129
|
+
if (existsSync(settingsPath)) {
|
|
130
|
+
const existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
131
|
+
const merged = this.mergeSettings(existing);
|
|
132
|
+
writeFileSync(settingsPath, JSON.stringify(merged, null, 2), 'utf-8');
|
|
133
|
+
skipped.push(settingsPath + ' (merged)');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const settings = this.generateSettings();
|
|
137
|
+
writeFileSync(settingsPath, JSON.stringify(settings, null, 2), 'utf-8');
|
|
138
|
+
created.push(settingsPath);
|
|
139
|
+
}
|
|
140
|
+
// 3. Create CLAUDE.md if not exists
|
|
141
|
+
const knowledgeDocPath = this.getKnowledgeDocPath();
|
|
142
|
+
if (!existsSync(knowledgeDocPath)) {
|
|
143
|
+
const projectName = config.projectDir.split(/[/\\]/).pop() ?? 'Project';
|
|
144
|
+
const content = this.generateKnowledgeDoc(projectName);
|
|
145
|
+
writeFileSync(knowledgeDocPath, content, 'utf-8');
|
|
146
|
+
created.push(knowledgeDocPath);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
skipped.push(knowledgeDocPath);
|
|
150
|
+
}
|
|
151
|
+
// 4. Create .gitignore for .scale/
|
|
152
|
+
const gitignorePath = join(this.scaleDir, '.gitignore');
|
|
153
|
+
if (!existsSync(gitignorePath)) {
|
|
154
|
+
writeFileSync(gitignorePath, `# SCALE Engine runtime data
|
|
155
|
+
*.db
|
|
156
|
+
*.db-journal
|
|
157
|
+
events/
|
|
158
|
+
checkpoints/
|
|
159
|
+
hooks/*.sh
|
|
160
|
+
`, 'utf-8');
|
|
161
|
+
created.push(gitignorePath);
|
|
162
|
+
}
|
|
163
|
+
logger.info({ created: created.length, skipped: skipped.length }, 'SCALE init completed');
|
|
164
|
+
return {
|
|
165
|
+
settingsPath,
|
|
166
|
+
knowledgeDocPath,
|
|
167
|
+
scaleDir: this.scaleDir,
|
|
168
|
+
created,
|
|
169
|
+
skipped,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// ============================================================================
|
|
174
|
+
// Adapter Factory
|
|
175
|
+
// ============================================================================
|
|
176
|
+
import { CodexAdapter } from './CodexAdapter.js';
|
|
177
|
+
// ...existing code...
|
|
178
|
+
export function createAdapter(agentType) {
|
|
179
|
+
switch (agentType) {
|
|
180
|
+
case 'claude-code':
|
|
181
|
+
return new ClaudeCodeAdapter();
|
|
182
|
+
case 'codex':
|
|
183
|
+
return new CodexAdapter();
|
|
184
|
+
default:
|
|
185
|
+
throw new Error(`Unsupported agent type: ${agentType}. Supported: claude-code, codex`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=ClaudeCodeAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClaudeCodeAdapter.js","sourceRoot":"","sources":["../../src/adapters/ClaudeCodeAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IAgentAdapter, AdapterConfig, InitResult, SettingsJson } from './ClaudeCodeAdapter.js';
|
|
2
|
+
export declare class CodexAdapter implements IAgentAdapter {
|
|
3
|
+
readonly agentType = "codex";
|
|
4
|
+
private projectDir;
|
|
5
|
+
private scaleDir;
|
|
6
|
+
getSettingsPath(): string;
|
|
7
|
+
getKnowledgeDocPath(): string;
|
|
8
|
+
isInstalled(): boolean;
|
|
9
|
+
generateSettings(): SettingsJson;
|
|
10
|
+
generateCodexConfig(): string;
|
|
11
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
12
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
13
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// SCALE Engine — Codex CLI Adapter (W11)
|
|
2
|
+
// 生成 .codex/config.toml + .codex/hooks.json + AGENTS.md
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Codex CLI Adapter
|
|
7
|
+
// ============================================================================
|
|
8
|
+
export class CodexAdapter {
|
|
9
|
+
agentType = 'codex';
|
|
10
|
+
projectDir = '.';
|
|
11
|
+
scaleDir = '.scale';
|
|
12
|
+
getSettingsPath() {
|
|
13
|
+
return join(this.projectDir, '.codex', 'hooks.json');
|
|
14
|
+
}
|
|
15
|
+
getKnowledgeDocPath() {
|
|
16
|
+
return join(this.projectDir, 'AGENTS.md');
|
|
17
|
+
}
|
|
18
|
+
isInstalled() {
|
|
19
|
+
return existsSync(this.getSettingsPath());
|
|
20
|
+
}
|
|
21
|
+
generateSettings() {
|
|
22
|
+
// Codex hooks.json format
|
|
23
|
+
return {
|
|
24
|
+
hooks: {
|
|
25
|
+
'pre-exec': [
|
|
26
|
+
{ matcher: '', command: 'scale gate pre-tool Bash --args-json "$ARGS" --session-id "$SESSION_ID"' },
|
|
27
|
+
],
|
|
28
|
+
'post-exec': [
|
|
29
|
+
{ matcher: '', command: 'scale gate post-tool Bash --exit-code "$EXIT_CODE" --session-id "$SESSION_ID"' },
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
generateCodexConfig() {
|
|
35
|
+
return `# SCALE Engine — Codex CLI config
|
|
36
|
+
# See: https://github.com/openai/codex
|
|
37
|
+
|
|
38
|
+
[model]
|
|
39
|
+
default = "o4-mini"
|
|
40
|
+
|
|
41
|
+
[approval]
|
|
42
|
+
# SCALE hooks handle safety gates
|
|
43
|
+
auto_approve = ["scale *"]
|
|
44
|
+
|
|
45
|
+
[environment]
|
|
46
|
+
SCALE_AGENT = "codex"
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
mergeSettings(existing) {
|
|
50
|
+
const generated = this.generateSettings();
|
|
51
|
+
const merged = { ...existing };
|
|
52
|
+
if (!merged.hooks)
|
|
53
|
+
merged.hooks = {};
|
|
54
|
+
for (const [hookType, entries] of Object.entries(generated.hooks)) {
|
|
55
|
+
if (!merged.hooks[hookType])
|
|
56
|
+
merged.hooks[hookType] = [];
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const alreadyExists = merged.hooks[hookType].some((e) => e.command.includes('scale '));
|
|
59
|
+
if (!alreadyExists) {
|
|
60
|
+
merged.hooks[hookType].push(entry);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return merged;
|
|
65
|
+
}
|
|
66
|
+
generateKnowledgeDoc(projectName, techStack = []) {
|
|
67
|
+
const stackLine = techStack.length > 0
|
|
68
|
+
? `\n## Tech Stack\n${techStack.map((t) => `- ${t}`).join('\n')}\n`
|
|
69
|
+
: '';
|
|
70
|
+
return `# ${projectName}
|
|
71
|
+
${stackLine}
|
|
72
|
+
## SCALE Engine Integration
|
|
73
|
+
|
|
74
|
+
This project uses SCALE Engine for AI engineering governance.
|
|
75
|
+
|
|
76
|
+
### Workflow
|
|
77
|
+
1. Explore → Plan → Implement → Verify → Learn
|
|
78
|
+
2. All tool calls pass through SCALE gates
|
|
79
|
+
3. Dangerous commands are physically blocked
|
|
80
|
+
4. Tests must pass before completion
|
|
81
|
+
|
|
82
|
+
### Commands
|
|
83
|
+
- \`scale create <type> <title>\` — Create artifact
|
|
84
|
+
- \`scale transition <id> <action>\` — State transition
|
|
85
|
+
- \`scale doctor\` — Health check
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
async init(config) {
|
|
89
|
+
this.projectDir = config.projectDir;
|
|
90
|
+
this.scaleDir = config.scaleDir ?? join(config.projectDir, '.scale');
|
|
91
|
+
const created = [];
|
|
92
|
+
const skipped = [];
|
|
93
|
+
// 1. Create .scale/ structure
|
|
94
|
+
for (const dir of ['events', 'artifacts', 'rules', 'hooks', 'checkpoints']) {
|
|
95
|
+
const fullDir = join(this.scaleDir, dir);
|
|
96
|
+
if (!existsSync(fullDir)) {
|
|
97
|
+
mkdirSync(fullDir, { recursive: true });
|
|
98
|
+
created.push(fullDir);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
skipped.push(fullDir);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// 2. Create .codex/ directory
|
|
105
|
+
const codexDir = join(this.projectDir, '.codex');
|
|
106
|
+
mkdirSync(codexDir, { recursive: true });
|
|
107
|
+
// 3. Create/merge hooks.json
|
|
108
|
+
const hooksPath = this.getSettingsPath();
|
|
109
|
+
if (existsSync(hooksPath)) {
|
|
110
|
+
const existing = JSON.parse(readFileSync(hooksPath, 'utf-8'));
|
|
111
|
+
const merged = this.mergeSettings(existing);
|
|
112
|
+
writeFileSync(hooksPath, JSON.stringify(merged, null, 2), 'utf-8');
|
|
113
|
+
skipped.push(hooksPath + ' (merged)');
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
writeFileSync(hooksPath, JSON.stringify(this.generateSettings(), null, 2), 'utf-8');
|
|
117
|
+
created.push(hooksPath);
|
|
118
|
+
}
|
|
119
|
+
// 4. Create config.toml
|
|
120
|
+
const configPath = join(codexDir, 'config.toml');
|
|
121
|
+
if (!existsSync(configPath)) {
|
|
122
|
+
writeFileSync(configPath, this.generateCodexConfig(), 'utf-8');
|
|
123
|
+
created.push(configPath);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
skipped.push(configPath);
|
|
127
|
+
}
|
|
128
|
+
// 5. Create AGENTS.md
|
|
129
|
+
const agentsPath = this.getKnowledgeDocPath();
|
|
130
|
+
if (!existsSync(agentsPath)) {
|
|
131
|
+
const projectName = config.projectDir.split(/[/\\]/).pop() ?? 'Project';
|
|
132
|
+
writeFileSync(agentsPath, this.generateKnowledgeDoc(projectName), 'utf-8');
|
|
133
|
+
created.push(agentsPath);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
skipped.push(agentsPath);
|
|
137
|
+
}
|
|
138
|
+
// 6. .gitignore
|
|
139
|
+
const gitignorePath = join(this.scaleDir, '.gitignore');
|
|
140
|
+
if (!existsSync(gitignorePath)) {
|
|
141
|
+
writeFileSync(gitignorePath, `*.db\n*.db-journal\nevents/\ncheckpoints/\nhooks/*.sh\n`, 'utf-8');
|
|
142
|
+
created.push(gitignorePath);
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
settingsPath: hooksPath,
|
|
146
|
+
knowledgeDocPath: agentsPath,
|
|
147
|
+
scaleDir: this.scaleDir,
|
|
148
|
+
created,
|
|
149
|
+
skipped,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=CodexAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodexAdapter.js","sourceRoot":"","sources":["../../src/adapters/CodexAdapter.ts"],"names":[],"mappings":"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"}
|