@hongmaple0820/scale-engine 0.2.0 → 0.5.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 +976 -64
- package/dist/adapters/ClaudeCodeAdapter.d.ts +2 -2
- package/dist/adapters/ClaudeCodeAdapter.js +33 -45
- package/dist/adapters/ClaudeCodeAdapter.js.map +1 -1
- package/dist/adapters/CursorAdapter.d.ts +14 -0
- package/dist/adapters/CursorAdapter.js +169 -0
- package/dist/adapters/CursorAdapter.js.map +1 -0
- package/dist/adapters/GeminiAdapter.d.ts +13 -0
- package/dist/adapters/GeminiAdapter.js +157 -0
- package/dist/adapters/GeminiAdapter.js.map +1 -0
- package/dist/adapters/HermesAdapter.d.ts +13 -0
- package/dist/adapters/HermesAdapter.js +157 -0
- package/dist/adapters/HermesAdapter.js.map +1 -0
- package/dist/adapters/OpenClawAdapter.d.ts +13 -0
- package/dist/adapters/OpenClawAdapter.js +157 -0
- package/dist/adapters/OpenClawAdapter.js.map +1 -0
- package/dist/adapters/OpenCodeAdapter.d.ts +14 -0
- package/dist/adapters/OpenCodeAdapter.js +170 -0
- package/dist/adapters/OpenCodeAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +17 -0
- package/dist/adapters/index.js +42 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/api/cli.js +295 -6
- package/dist/api/cli.js.map +1 -1
- package/dist/artifact/fsmDefinitions.js +41 -1
- package/dist/artifact/fsmDefinitions.js.map +1 -1
- package/dist/artifact/types.d.ts +62 -1
- package/dist/artifact/types.js +27 -0
- package/dist/artifact/types.js.map +1 -1
- package/dist/context/ContextBuilder.d.ts +32 -1
- package/dist/context/ContextBuilder.js +135 -5
- package/dist/context/ContextBuilder.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +21 -4
- package/dist/index.js.map +1 -1
- package/dist/skills/SkillDiscovery.d.ts +28 -0
- package/dist/skills/SkillDiscovery.js +171 -0
- package/dist/skills/SkillDiscovery.js.map +1 -0
- package/dist/workflows/presets.d.ts +34 -0
- package/dist/workflows/presets.js +224 -0
- package/dist/workflows/presets.js.map +1 -0
- package/package.json +48 -48
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export interface AdapterConfig {
|
|
2
2
|
projectDir: string;
|
|
3
3
|
scaleDir?: string;
|
|
4
|
-
agentType?: 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'gemini';
|
|
4
|
+
agentType?: 'claude-code' | 'codex' | 'opencode' | 'cursor' | 'gemini' | 'openclaw' | 'hermes';
|
|
5
|
+
scenarioMode?: 'sandbox' | 'standard' | 'critical';
|
|
5
6
|
}
|
|
6
7
|
export interface HookEntry {
|
|
7
8
|
matcher: string;
|
|
@@ -45,4 +46,3 @@ export declare class ClaudeCodeAdapter implements IAgentAdapter {
|
|
|
45
46
|
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
46
47
|
init(config: AdapterConfig): Promise<InitResult>;
|
|
47
48
|
}
|
|
48
|
-
export declare function createAdapter(agentType: string): IAgentAdapter;
|
|
@@ -78,32 +78,32 @@ export class ClaudeCodeAdapter {
|
|
|
78
78
|
const stackLine = techStack.length > 0
|
|
79
79
|
? `\n## Tech Stack\n${techStack.map((t) => `- ${t}`).join('\n')}\n`
|
|
80
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/
|
|
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
107
|
`;
|
|
108
108
|
}
|
|
109
109
|
async init(config) {
|
|
@@ -151,12 +151,12 @@ This project uses SCALE Engine for AI engineering governance.
|
|
|
151
151
|
// 4. Create .gitignore for .scale/
|
|
152
152
|
const gitignorePath = join(this.scaleDir, '.gitignore');
|
|
153
153
|
if (!existsSync(gitignorePath)) {
|
|
154
|
-
writeFileSync(gitignorePath, `# SCALE Engine runtime data
|
|
155
|
-
*.db
|
|
156
|
-
*.db-journal
|
|
157
|
-
events/
|
|
158
|
-
checkpoints/
|
|
159
|
-
hooks/*.sh
|
|
154
|
+
writeFileSync(gitignorePath, `# SCALE Engine runtime data
|
|
155
|
+
*.db
|
|
156
|
+
*.db-journal
|
|
157
|
+
events/
|
|
158
|
+
checkpoints/
|
|
159
|
+
hooks/*.sh
|
|
160
160
|
`, 'utf-8');
|
|
161
161
|
created.push(gitignorePath);
|
|
162
162
|
}
|
|
@@ -171,18 +171,6 @@ hooks/*.sh
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
// ============================================================================
|
|
174
|
-
// Adapter Factory
|
|
174
|
+
// Adapter Factory — moved to ./index.ts
|
|
175
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
176
|
//# sourceMappingURL=ClaudeCodeAdapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClaudeCodeAdapter.js","sourceRoot":"","sources":["../../src/adapters/ClaudeCodeAdapter.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,0CAA0C;AAC1C,8CAA8C;AAE9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;
|
|
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 CursorAdapter implements IAgentAdapter {
|
|
3
|
+
readonly agentType = "cursor";
|
|
4
|
+
private projectDir;
|
|
5
|
+
private scaleDir;
|
|
6
|
+
getSettingsPath(): string;
|
|
7
|
+
getKnowledgeDocPath(): string;
|
|
8
|
+
getSkillsDir(): string;
|
|
9
|
+
isInstalled(): boolean;
|
|
10
|
+
generateSettings(): SettingsJson;
|
|
11
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
12
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
13
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// SCALE Engine — Cursor Adapter
|
|
2
|
+
// 生成 .cursor/settings.json + .cursorrules + .cursor/skills/
|
|
3
|
+
// Cursor: https://cursor.sh
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { logger } from '../core/logger.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Cursor Adapter
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export class CursorAdapter {
|
|
11
|
+
agentType = 'cursor';
|
|
12
|
+
projectDir = '.';
|
|
13
|
+
scaleDir = '.scale';
|
|
14
|
+
getSettingsPath() {
|
|
15
|
+
return join(this.projectDir, '.cursor', 'settings.json');
|
|
16
|
+
}
|
|
17
|
+
getKnowledgeDocPath() {
|
|
18
|
+
return join(this.projectDir, '.cursorrules');
|
|
19
|
+
}
|
|
20
|
+
getSkillsDir() {
|
|
21
|
+
return join(this.projectDir, '.cursor', 'skills');
|
|
22
|
+
}
|
|
23
|
+
isInstalled() {
|
|
24
|
+
return existsSync(join(this.projectDir, '.cursor'));
|
|
25
|
+
}
|
|
26
|
+
generateSettings() {
|
|
27
|
+
return {
|
|
28
|
+
hooks: {
|
|
29
|
+
'pre-exec': [
|
|
30
|
+
{ matcher: '', command: 'scale gate pre-tool Bash --args-json "$ARGS" --session-id "$SESSION_ID"' },
|
|
31
|
+
{ matcher: 'edit|write', command: 'scale gate pre-tool Edit --args-json "$ARGS" --session-id "$SESSION_ID"' },
|
|
32
|
+
],
|
|
33
|
+
'post-exec': [
|
|
34
|
+
{ matcher: 'edit|write', command: 'scale gate post-tool Edit --args-json "$ARGS" --exit-code "$EXIT_CODE" --session-id "$SESSION_ID"' },
|
|
35
|
+
{ matcher: '', command: 'scale gate post-tool Bash --args-json "$ARGS" --exit-code "$EXIT_CODE" --session-id "$SESSION_ID"' },
|
|
36
|
+
],
|
|
37
|
+
'before-stop': [
|
|
38
|
+
{ matcher: '', command: 'scale gate before-stop --session-id "$SESSION_ID"' },
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
permissions: {
|
|
42
|
+
allow: ['scale:*'],
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
mergeSettings(existing) {
|
|
47
|
+
const generated = this.generateSettings();
|
|
48
|
+
const merged = { ...existing };
|
|
49
|
+
if (!merged.hooks)
|
|
50
|
+
merged.hooks = {};
|
|
51
|
+
for (const [hookType, entries] of Object.entries(generated.hooks)) {
|
|
52
|
+
if (!merged.hooks[hookType])
|
|
53
|
+
merged.hooks[hookType] = [];
|
|
54
|
+
for (const entry of entries) {
|
|
55
|
+
const alreadyExists = merged.hooks[hookType].some((e) => e.command.includes('scale '));
|
|
56
|
+
if (!alreadyExists) {
|
|
57
|
+
merged.hooks[hookType].push(entry);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!merged.permissions)
|
|
62
|
+
merged.permissions = {};
|
|
63
|
+
if (!merged.permissions.allow)
|
|
64
|
+
merged.permissions.allow = [];
|
|
65
|
+
for (const perm of generated.permissions.allow) {
|
|
66
|
+
if (!merged.permissions.allow.includes(perm)) {
|
|
67
|
+
merged.permissions.allow.push(perm);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return merged;
|
|
71
|
+
}
|
|
72
|
+
generateKnowledgeDoc(projectName, techStack = []) {
|
|
73
|
+
const stackLine = techStack.length > 0
|
|
74
|
+
? `\n## Tech Stack\n${techStack.map((t) => `- ${t}`).join('\n')}\n`
|
|
75
|
+
: '';
|
|
76
|
+
return `# ${projectName}
|
|
77
|
+
${stackLine}
|
|
78
|
+
## SCALE Engine Integration (Cursor)
|
|
79
|
+
|
|
80
|
+
This project uses SCALE Engine for AI engineering governance via Cursor.
|
|
81
|
+
|
|
82
|
+
### Commands
|
|
83
|
+
- \`scale create <type> <title>\` — Create artifact
|
|
84
|
+
- \`scale transition <id> <action>\` — Transition artifact state
|
|
85
|
+
- \`scale list --type Spec\` — List artifacts
|
|
86
|
+
- \`scale role activate <role>\` — Switch role
|
|
87
|
+
- \`scale doctor\` — Health check
|
|
88
|
+
|
|
89
|
+
### Workflow
|
|
90
|
+
1. **Explore** → Role: explorer (Read/Grep only)
|
|
91
|
+
2. **Plan** → Create Spec → refine → approve (guard: ambiguity ≤ 0.2)
|
|
92
|
+
3. **Implement** → Role: implementer (Edit/Write/Bash unlocked)
|
|
93
|
+
4. **Verify** → Must run tests before claiming done
|
|
94
|
+
5. **Learn** → Defects → Lessons → Rules → Hooks
|
|
95
|
+
|
|
96
|
+
### Rules
|
|
97
|
+
- 🔴 Dangerous commands are physically blocked
|
|
98
|
+
- 🔴 Hardcoded secrets are blocked on Edit/Write
|
|
99
|
+
- 🟡 3 identical retries triggers brute-retry detection
|
|
100
|
+
- 🟡 Claiming done without running tests is blocked
|
|
101
|
+
- 🟢 All tool calls are tracked in .scale/events/
|
|
102
|
+
`;
|
|
103
|
+
}
|
|
104
|
+
async init(config) {
|
|
105
|
+
this.projectDir = config.projectDir;
|
|
106
|
+
this.scaleDir = config.scaleDir ?? join(config.projectDir, '.scale');
|
|
107
|
+
const created = [];
|
|
108
|
+
const skipped = [];
|
|
109
|
+
// 1. Create .scale/ directory structure
|
|
110
|
+
for (const dir of ['events', 'artifacts', 'rules', 'hooks', 'checkpoints']) {
|
|
111
|
+
const fullDir = join(this.scaleDir, dir);
|
|
112
|
+
if (!existsSync(fullDir)) {
|
|
113
|
+
mkdirSync(fullDir, { recursive: true });
|
|
114
|
+
created.push(fullDir);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
skipped.push(fullDir);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// 2. Create .cursor/ directory + settings.json
|
|
121
|
+
const cursorDir = join(this.projectDir, '.cursor');
|
|
122
|
+
mkdirSync(cursorDir, { recursive: true });
|
|
123
|
+
const settingsPath = this.getSettingsPath();
|
|
124
|
+
if (existsSync(settingsPath)) {
|
|
125
|
+
const existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
126
|
+
const merged = this.mergeSettings(existing);
|
|
127
|
+
writeFileSync(settingsPath, JSON.stringify(merged, null, 2), 'utf-8');
|
|
128
|
+
skipped.push(settingsPath + ' (merged)');
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
writeFileSync(settingsPath, JSON.stringify(this.generateSettings(), null, 2), 'utf-8');
|
|
132
|
+
created.push(settingsPath);
|
|
133
|
+
}
|
|
134
|
+
// 3. Create skills directory
|
|
135
|
+
const skillsDir = this.getSkillsDir();
|
|
136
|
+
if (!existsSync(skillsDir)) {
|
|
137
|
+
mkdirSync(skillsDir, { recursive: true });
|
|
138
|
+
created.push(skillsDir);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
skipped.push(skillsDir);
|
|
142
|
+
}
|
|
143
|
+
// 4. Create .cursorrules
|
|
144
|
+
const knowledgeDocPath = this.getKnowledgeDocPath();
|
|
145
|
+
if (!existsSync(knowledgeDocPath)) {
|
|
146
|
+
const projectName = config.projectDir.split(/[/\\]/).pop() ?? 'Project';
|
|
147
|
+
writeFileSync(knowledgeDocPath, this.generateKnowledgeDoc(projectName), 'utf-8');
|
|
148
|
+
created.push(knowledgeDocPath);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
skipped.push(knowledgeDocPath);
|
|
152
|
+
}
|
|
153
|
+
// 5. .gitignore
|
|
154
|
+
const gitignorePath = join(this.scaleDir, '.gitignore');
|
|
155
|
+
if (!existsSync(gitignorePath)) {
|
|
156
|
+
writeFileSync(gitignorePath, `*.db\n*.db-journal\nevents/\ncheckpoints/\nhooks/*.sh\n`, 'utf-8');
|
|
157
|
+
created.push(gitignorePath);
|
|
158
|
+
}
|
|
159
|
+
logger.info({ created: created.length, skipped: skipped.length }, 'SCALE init (cursor) completed');
|
|
160
|
+
return {
|
|
161
|
+
settingsPath,
|
|
162
|
+
knowledgeDocPath,
|
|
163
|
+
scaleDir: this.scaleDir,
|
|
164
|
+
created,
|
|
165
|
+
skipped,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=CursorAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CursorAdapter.js","sourceRoot":"","sources":["../../src/adapters/CursorAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IAgentAdapter, AdapterConfig, InitResult, SettingsJson } from './ClaudeCodeAdapter.js';
|
|
2
|
+
export declare class GeminiAdapter implements IAgentAdapter {
|
|
3
|
+
readonly agentType = "gemini";
|
|
4
|
+
private projectDir;
|
|
5
|
+
private scaleDir;
|
|
6
|
+
getSettingsPath(): string;
|
|
7
|
+
getKnowledgeDocPath(): string;
|
|
8
|
+
isInstalled(): boolean;
|
|
9
|
+
generateSettings(): SettingsJson;
|
|
10
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
11
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
12
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// SCALE Engine — Gemini Adapter
|
|
2
|
+
// 生成 .gemini/settings.json + GEMINI.md
|
|
3
|
+
// Gemini CLI: https://github.com/google-gemini/gemini-cli
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { logger } from '../core/logger.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Gemini Adapter
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export class GeminiAdapter {
|
|
11
|
+
agentType = 'gemini';
|
|
12
|
+
projectDir = '.';
|
|
13
|
+
scaleDir = '.scale';
|
|
14
|
+
getSettingsPath() {
|
|
15
|
+
return join(this.projectDir, '.gemini', 'settings.json');
|
|
16
|
+
}
|
|
17
|
+
getKnowledgeDocPath() {
|
|
18
|
+
return join(this.projectDir, 'GEMINI.md');
|
|
19
|
+
}
|
|
20
|
+
isInstalled() {
|
|
21
|
+
return existsSync(join(this.projectDir, '.gemini'));
|
|
22
|
+
}
|
|
23
|
+
generateSettings() {
|
|
24
|
+
return {
|
|
25
|
+
hooks: {
|
|
26
|
+
'pre-exec': [
|
|
27
|
+
{ matcher: '', command: 'scale gate pre-tool Bash --args-json "$ARGS" --session-id "$SESSION_ID"' },
|
|
28
|
+
{ matcher: 'edit|write', command: 'scale gate pre-tool Edit --args-json "$ARGS" --session-id "$SESSION_ID"' },
|
|
29
|
+
],
|
|
30
|
+
'post-exec': [
|
|
31
|
+
{ matcher: 'edit|write', command: 'scale gate post-tool Edit --args-json "$ARGS" --exit-code "$EXIT_CODE" --session-id "$SESSION_ID"' },
|
|
32
|
+
{ matcher: '', command: 'scale gate post-tool Bash --args-json "$ARGS" --exit-code "$EXIT_CODE" --session-id "$SESSION_ID"' },
|
|
33
|
+
],
|
|
34
|
+
'before-stop': [
|
|
35
|
+
{ matcher: '', command: 'scale gate before-stop --session-id "$SESSION_ID"' },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
permissions: {
|
|
39
|
+
allow: ['scale:*'],
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
mergeSettings(existing) {
|
|
44
|
+
const generated = this.generateSettings();
|
|
45
|
+
const merged = { ...existing };
|
|
46
|
+
if (!merged.hooks)
|
|
47
|
+
merged.hooks = {};
|
|
48
|
+
for (const [hookType, entries] of Object.entries(generated.hooks)) {
|
|
49
|
+
if (!merged.hooks[hookType])
|
|
50
|
+
merged.hooks[hookType] = [];
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const alreadyExists = merged.hooks[hookType].some((e) => e.command.includes('scale '));
|
|
53
|
+
if (!alreadyExists) {
|
|
54
|
+
merged.hooks[hookType].push(entry);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!merged.permissions)
|
|
59
|
+
merged.permissions = {};
|
|
60
|
+
if (!merged.permissions.allow)
|
|
61
|
+
merged.permissions.allow = [];
|
|
62
|
+
for (const perm of generated.permissions.allow) {
|
|
63
|
+
if (!merged.permissions.allow.includes(perm)) {
|
|
64
|
+
merged.permissions.allow.push(perm);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return merged;
|
|
68
|
+
}
|
|
69
|
+
generateKnowledgeDoc(projectName, techStack = []) {
|
|
70
|
+
const stackLine = techStack.length > 0
|
|
71
|
+
? `\n## Tech Stack\n${techStack.map((t) => `- ${t}`).join('\n')}\n`
|
|
72
|
+
: '';
|
|
73
|
+
return `# ${projectName}
|
|
74
|
+
${stackLine}
|
|
75
|
+
## SCALE Engine Integration (Gemini)
|
|
76
|
+
|
|
77
|
+
This project uses SCALE Engine for AI engineering governance via Gemini CLI.
|
|
78
|
+
|
|
79
|
+
### Commands
|
|
80
|
+
- \`scale create <type> <title>\` — Create artifact
|
|
81
|
+
- \`scale transition <id> <action>\` — Transition artifact state
|
|
82
|
+
- \`scale list --type Spec\` — List artifacts
|
|
83
|
+
- \`scale role activate <role>\` — Switch role
|
|
84
|
+
- \`scale doctor\` — Health check
|
|
85
|
+
|
|
86
|
+
### Workflow
|
|
87
|
+
1. **Explore** → Role: explorer (Read/Grep only)
|
|
88
|
+
2. **Plan** → Create Spec → refine → approve (guard: ambiguity ≤ 0.2)
|
|
89
|
+
3. **Implement** → Role: implementer (Edit/Write/Bash unlocked)
|
|
90
|
+
4. **Verify** → Must run tests before claiming done
|
|
91
|
+
5. **Learn** → Defects → Lessons → Rules → Hooks
|
|
92
|
+
|
|
93
|
+
### Rules
|
|
94
|
+
- 🔴 Dangerous commands are physically blocked
|
|
95
|
+
- 🔴 Hardcoded secrets are blocked on Edit/Write
|
|
96
|
+
- 🟡 3 identical retries triggers brute-retry detection
|
|
97
|
+
- 🟡 Claiming done without running tests is blocked
|
|
98
|
+
- 🟢 All tool calls are tracked in .scale/events/
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
101
|
+
async init(config) {
|
|
102
|
+
this.projectDir = config.projectDir;
|
|
103
|
+
this.scaleDir = config.scaleDir ?? join(config.projectDir, '.scale');
|
|
104
|
+
const created = [];
|
|
105
|
+
const skipped = [];
|
|
106
|
+
// 1. Create .scale/ directory structure
|
|
107
|
+
for (const dir of ['events', 'artifacts', 'rules', 'hooks', 'checkpoints']) {
|
|
108
|
+
const fullDir = join(this.scaleDir, dir);
|
|
109
|
+
if (!existsSync(fullDir)) {
|
|
110
|
+
mkdirSync(fullDir, { recursive: true });
|
|
111
|
+
created.push(fullDir);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
skipped.push(fullDir);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// 2. Create .gemini/ directory + settings.json
|
|
118
|
+
const geminiDir = join(this.projectDir, '.gemini');
|
|
119
|
+
mkdirSync(geminiDir, { recursive: true });
|
|
120
|
+
const settingsPath = this.getSettingsPath();
|
|
121
|
+
if (existsSync(settingsPath)) {
|
|
122
|
+
const existing = JSON.parse(readFileSync(settingsPath, 'utf-8'));
|
|
123
|
+
const merged = this.mergeSettings(existing);
|
|
124
|
+
writeFileSync(settingsPath, JSON.stringify(merged, null, 2), 'utf-8');
|
|
125
|
+
skipped.push(settingsPath + ' (merged)');
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
writeFileSync(settingsPath, JSON.stringify(this.generateSettings(), null, 2), 'utf-8');
|
|
129
|
+
created.push(settingsPath);
|
|
130
|
+
}
|
|
131
|
+
// 3. Create GEMINI.md
|
|
132
|
+
const knowledgeDocPath = this.getKnowledgeDocPath();
|
|
133
|
+
if (!existsSync(knowledgeDocPath)) {
|
|
134
|
+
const projectName = config.projectDir.split(/[/\\]/).pop() ?? 'Project';
|
|
135
|
+
writeFileSync(knowledgeDocPath, this.generateKnowledgeDoc(projectName), 'utf-8');
|
|
136
|
+
created.push(knowledgeDocPath);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
skipped.push(knowledgeDocPath);
|
|
140
|
+
}
|
|
141
|
+
// 4. .gitignore
|
|
142
|
+
const gitignorePath = join(this.scaleDir, '.gitignore');
|
|
143
|
+
if (!existsSync(gitignorePath)) {
|
|
144
|
+
writeFileSync(gitignorePath, `*.db\n*.db-journal\nevents/\ncheckpoints/\nhooks/*.sh\n`, 'utf-8');
|
|
145
|
+
created.push(gitignorePath);
|
|
146
|
+
}
|
|
147
|
+
logger.info({ created: created.length, skipped: skipped.length }, 'SCALE init (gemini) completed');
|
|
148
|
+
return {
|
|
149
|
+
settingsPath,
|
|
150
|
+
knowledgeDocPath,
|
|
151
|
+
scaleDir: this.scaleDir,
|
|
152
|
+
created,
|
|
153
|
+
skipped,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=GeminiAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GeminiAdapter.js","sourceRoot":"","sources":["../../src/adapters/GeminiAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IAgentAdapter, AdapterConfig, InitResult, SettingsJson } from './ClaudeCodeAdapter.js';
|
|
2
|
+
export declare class HermesAdapter implements IAgentAdapter {
|
|
3
|
+
readonly agentType = "hermes";
|
|
4
|
+
private projectDir;
|
|
5
|
+
private scaleDir;
|
|
6
|
+
getSettingsPath(): string;
|
|
7
|
+
getKnowledgeDocPath(): string;
|
|
8
|
+
isInstalled(): boolean;
|
|
9
|
+
generateSettings(): SettingsJson;
|
|
10
|
+
mergeSettings(existing: SettingsJson): SettingsJson;
|
|
11
|
+
generateKnowledgeDoc(projectName: string, techStack?: string[]): string;
|
|
12
|
+
init(config: AdapterConfig): Promise<InitResult>;
|
|
13
|
+
}
|