@vima_tech/flywheel 1.0.0 → 1.1.1

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/bin/flywheel.js CHANGED
@@ -1,39 +1,200 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Flywheel CLI
4
- * Global entry point for @renmengkai/flywheel npm package
5
- */
6
- const { spawn } = require('child_process');
2
+ const { spawn, execSync } = require('child_process');
7
3
  const path = require('path');
8
4
  const fs = require('fs');
5
+ const readline = require('readline');
9
6
 
10
- const REPO_DIR = process.env.FLYWHEEL_DIR || process.cwd();
7
+ const REPO_DIR = process.env.FLYWHEEL_DIR || path.dirname(path.dirname(__dirname));
8
+ const NPM_PKG = '@vima_tech/flywheel';
11
9
 
12
10
  function resolveScript(name) {
13
- const scripts = {
14
- 'flywheel-install': path.join(__dirname, '../scripts/flywheel-install.sh'),
15
- 'auto-distill': path.join(__dirname, '../scripts/auto-distill.sh'),
16
- 'feedback-hook': path.join(__dirname, '../scripts/feedback-hook.sh'),
17
- 'bridge-to-coder': path.join(__dirname, '../scripts/bridge-to-coder.sh'),
18
- };
19
- return scripts[name];
11
+ return path.join(__dirname, '../scripts/' + name + '.sh');
12
+ }
13
+
14
+ function resolveKernelFile(name) {
15
+ return path.join(__dirname, '../' + name);
20
16
  }
21
17
 
22
18
  function runScript(scriptPath, args) {
23
19
  return new Promise((resolve, reject) => {
24
20
  const child = spawn('bash', [scriptPath, ...args], {
25
- cwd: REPO_DIR,
21
+ cwd: process.cwd(),
26
22
  stdio: 'inherit',
27
- env: { ...process.env, FLYWHEEL_DIR: REPO_DIR },
23
+ env: { ...process.env, FLYWHEEL_DIR: process.cwd() },
28
24
  });
29
25
  child.on('exit', (code) => {
30
26
  if (code === 0) resolve(0);
31
- else reject(new Error(`exit code ${code}`));
27
+ else reject(new Error('exit code ' + code));
32
28
  });
33
29
  });
34
30
  }
35
31
 
36
- const [,, command, ...args] = process.argv;
32
+ function downloadFile(url, destPath) {
33
+ return new Promise((resolve, reject) => {
34
+ const file = fs.createWriteStream(destPath);
35
+ spawn('curl', ['-fsSL', url, '-o', destPath], { stdio: 'ignore' })
36
+ .on('exit', (code) => {
37
+ if (code === 0) resolve(0);
38
+ else reject(new Error('curl failed'));
39
+ });
40
+ });
41
+ }
42
+
43
+ async function initKernel(dir, skill) {
44
+ const kernelFiles = [
45
+ 'CLAUDE.md', '.gitignore',
46
+ '.claude/commands/flywheel.md', '.claude/commands/skill.md',
47
+ 'scripts/auto-distill.sh', 'scripts/feedback-hook.sh',
48
+ 'scripts/bridge-to-coder.sh', 'scripts/flywheel-install.sh',
49
+ 'templates/state.json',
50
+ 'skills/_kernel/distillation.md',
51
+ 'skills/_template/skill.yaml', 'skills/_template/domain.md',
52
+ 'skills/_template/feedback-questions.sh',
53
+ ];
54
+
55
+ const optionalFiles = [
56
+ 'skills/_template/artifacts.md',
57
+ ];
58
+
59
+ const baseUrl = 'https://raw.githubusercontent.com/renmengkai/flywheel/main';
60
+ const skillFiles = skill ? [
61
+ 'skills/' + skill + '/skill.yaml',
62
+ 'skills/' + skill + '/domain.md',
63
+ 'skills/' + skill + '/feedback-questions.sh',
64
+ ] : [];
65
+
66
+ for (const f of kernelFiles) {
67
+ const dest = path.join(dir, f);
68
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
69
+ const srcPath = resolveKernelFile(f);
70
+ if (fs.existsSync(srcPath)) {
71
+ fs.copyFileSync(srcPath, dest);
72
+ } else {
73
+ await downloadFile(baseUrl + '/' + f, dest);
74
+ }
75
+ }
76
+
77
+ for (const f of optionalFiles) {
78
+ const dest = path.join(dir, f);
79
+ const srcPath = resolveKernelFile(f);
80
+ if (fs.existsSync(srcPath)) fs.copyFileSync(srcPath, dest);
81
+ }
82
+
83
+ if (skill) {
84
+ for (const f of skillFiles) {
85
+ const dest = path.join(dir, f);
86
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
87
+ const srcPath = resolveKernelFile(f);
88
+ if (fs.existsSync(srcPath)) {
89
+ fs.copyFileSync(srcPath, dest);
90
+ } else {
91
+ await downloadFile(baseUrl + '/' + f, dest);
92
+ }
93
+ }
94
+ }
95
+
96
+ fs.mkdirSync(path.join(dir, '.distill-needed'), { recursive: true });
97
+ fs.mkdirSync(path.join(dir, 'episodic-logs'), { recursive: true });
98
+ fs.mkdirSync(path.join(dir, 'projects'), { recursive: true });
99
+ fs.mkdirSync(path.join(dir, 'memory'), { recursive: true });
100
+ fs.writeFileSync(path.join(dir, '.distill-needed/.gitkeep'), '');
101
+ fs.writeFileSync(path.join(dir, 'episodic-logs/.gitkeep'), '');
102
+ fs.writeFileSync(path.join(dir, 'projects/.gitkeep'), '');
103
+ fs.writeFileSync(path.join(dir, 'memory/.gitkeep'), '');
104
+
105
+ if (!fs.existsSync(path.join(dir, '.gitignore'))) {
106
+ fs.writeFileSync(path.join(dir, '.gitignore'), `# flywheel-managed\nprojects/*/\nepisodic-logs/\n.distill-needed/*\n!.distill-needed/.gitkeep\nmemory/.gitkeep\n*.log\n`);
107
+ }
108
+
109
+ try {
110
+ execSync('chmod +x ' + path.join(dir, 'scripts/*.sh'), { stdio: 'ignore', shell: true });
111
+ } catch (e) {}
112
+ }
113
+
114
+ async function cmdNew(args) {
115
+ if (args.length < 1) {
116
+ console.error('用法: flywheel new <project-name> [--agent claude|opencode] [--skill req-mining]');
117
+ process.exit(1);
118
+ }
119
+
120
+ const projectName = args[0];
121
+ const dirName = projectName;
122
+ const targetDir = path.join(process.cwd(), dirName);
123
+
124
+ if (fs.existsSync(targetDir)) {
125
+ console.error('❌ 目录已存在: ' + targetDir);
126
+ process.exit(1);
127
+ }
128
+
129
+ let agent = 'claude';
130
+ let skill = 'req-mining';
131
+
132
+ for (let i = 1; i < args.length; i++) {
133
+ if (args[i] === '--agent' && args[i + 1]) {
134
+ agent = args[i + 1];
135
+ i++;
136
+ } else if (args[i] === '--skill' && args[i + 1]) {
137
+ skill = args[i + 1];
138
+ i++;
139
+ }
140
+ }
141
+
142
+ console.log('');
143
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
144
+ console.log(' Flywheel 初始化');
145
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
146
+ console.log(' 项目: ' + projectName);
147
+ console.log(' 目录: ' + targetDir);
148
+ console.log(' Agent: ' + agent);
149
+ console.log(' Skill: ' + skill);
150
+ console.log('');
151
+
152
+ console.log('📦 初始化内核文件...');
153
+ fs.mkdirSync(targetDir, { recursive: true });
154
+ await initKernel(targetDir, skill);
155
+ console.log(' ✓ 内核安装完成');
156
+
157
+ console.log('');
158
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
159
+ console.log(' ✅ 项目创建完成!');
160
+ console.log('');
161
+ console.log(' 进入目录并启动 ' + agent + ':');
162
+ console.log(' cd ' + dirName + ' && flywheel start');
163
+ console.log('');
164
+ console.log(' 或手动启动:cd ' + dirName + ' && claude');
165
+ console.log(' 然后输入 /sfw 开始飞轮工作');
166
+ console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
167
+ }
168
+
169
+ async function cmdStart() {
170
+ const agent = detectAgent();
171
+ if (!agent) {
172
+ console.error('❌ 未检测到 Claude Code 或 OpenCode');
173
+ console.error('请先安装 Claude Code 或 OpenCode');
174
+ process.exit(1);
175
+ }
176
+
177
+ console.log('🚀 启动 ' + agent + '...');
178
+ spawn(agent, [], {
179
+ cwd: process.cwd(),
180
+ stdio: 'inherit',
181
+ shell: true,
182
+ env: { ...process.env, FLYWHEEL_DIR: process.cwd() },
183
+ });
184
+ }
185
+
186
+ function detectAgent() {
187
+ const agents = ['claude', 'claude-code', 'opencode', 'codex'];
188
+ for (const a of agents) {
189
+ try {
190
+ execSync('which ' + a, { stdio: 'ignore' });
191
+ return a;
192
+ } catch (e) {}
193
+ }
194
+ return null;
195
+ }
196
+
197
+ const [, , command, ...args] = process.argv;
37
198
 
38
199
  if (!command) {
39
200
  console.log(`
@@ -42,54 +203,94 @@ Flywheel CLI — 自成长 AI Agent 飞轮框架
42
203
  用法: flywheel <command> [args]
43
204
 
44
205
  可用命令:
45
- install <skill> 安装 skill 包
46
- list 列出已安装的 skill
47
- update [skill] 更新 skill 包
48
- distill [project] 手动触发蒸馏
49
- help 显示帮助
206
+ new|create|init 创建新项目
207
+ start|run|launch 启动 Claude Code 或 OpenCode
208
+ -v|--version 显示版本号
209
+ install|add|i 安装 skill 包
210
+ list|ls 列出已安装的 skill
211
+ update|upgrade 更新 flywheel 或 skill
212
+ distill|dist 手动触发蒸馏
213
+ -h|--help|h 显示帮助
50
214
 
51
215
  示例:
216
+ flywheel new my-project
217
+ cd my-project && flywheel start
52
218
  flywheel install req-mining
53
- flywheel list
54
- flywheel update
55
- flywheel distill proj_20260515_01
219
+ flywheel update flywheel # 更新 flywheel 本身
56
220
  `);
57
221
  process.exit(0);
58
222
  }
59
223
 
60
224
  switch (command) {
225
+ case '-v':
226
+ case '--version':
227
+ case '-V':
228
+ case 'version':
229
+ console.log('@vima_tech/flywheel v1.1.0');
230
+ break;
231
+ case 'new':
232
+ case 'create':
233
+ case 'init':
234
+ cmdNew(args).catch((e) => { console.error(e); process.exit(1); });
235
+ break;
236
+ case 'start':
237
+ case 'run':
238
+ case 'launch':
239
+ cmdStart();
240
+ break;
241
+ case '-h':
242
+ case '--help':
243
+ case '-?':
61
244
  case 'help':
245
+ case 'h':
62
246
  console.log(`
63
247
  Flywheel CLI — 自成长 AI Agent 飞轮框架
64
248
 
65
249
  用法: flywheel <command> [args]
66
250
 
67
251
  可用命令:
68
- install <skill> 安装 skill 包
69
- list 列出已安装的 skill
70
- update [skill] 更新 skill 包
71
- distill [project] 手动触发蒸馏
252
+ new <name> 创建新项目 (new|create|init)
253
+ start 启动 Claude Code 或 OpenCode (start|run|launch)
254
+ version 显示版本号 (-v|--version)
255
+ update 更新 flywheel 到最新版本
256
+ install <skill> 安装 skill 包 (install|add|i)
257
+ list 列出已安装的 skill (list|ls)
258
+ update skill 更新 skill 包 (update|upgrade)
259
+ distill [project] 手动触发蒸馏 (distill|dist)
260
+ help 显示帮助 (-h|--help)
72
261
 
73
262
  示例:
263
+ flywheel new my-project
264
+ cd my-project && flywheel start
74
265
  flywheel install req-mining
75
- flywheel list
76
- flywheel update
77
- flywheel distill proj_20260515_01
78
266
  `);
79
267
  break;
80
268
  case 'install':
269
+ case 'add':
270
+ case 'i':
81
271
  runScript(resolveScript('flywheel-install'), ['add', ...args]).catch((e) => process.exit(1));
82
272
  break;
83
273
  case 'list':
274
+ case 'ls':
84
275
  runScript(resolveScript('flywheel-install'), ['list']).catch((e) => process.exit(1));
85
276
  break;
86
277
  case 'update':
87
- runScript(resolveScript('flywheel-install'), ['update', ...args]).catch((e) => process.exit(1));
278
+ case 'upgrade':
279
+ if (args[0] === 'flywheel' || args[0] === 'self') {
280
+ spawn('npm', ['install', '-g', '@vima_tech/flywheel'], {
281
+ cwd: process.cwd(),
282
+ stdio: 'inherit',
283
+ }).on('exit', (code) => process.exit(code));
284
+ } else {
285
+ runScript(resolveScript('flywheel-install'), ['update', ...args]).catch((e) => process.exit(1));
286
+ }
88
287
  break;
89
288
  case 'distill':
289
+ case 'dist':
90
290
  runScript(resolveScript('auto-distill'), args).catch((e) => process.exit(1));
91
291
  break;
92
292
  default:
93
- console.error(`未知命令: ${command}`)
293
+ console.error('未知命令: ' + command);
294
+ console.error('运行 flywheel help 查看用法');
94
295
  process.exit(1);
95
296
  }
package/package.json CHANGED
@@ -1,11 +1,18 @@
1
1
  {
2
2
  "name": "@vima_tech/flywheel",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "自成长 AI Agent 飞轮框架 — 让任何需要积累迭代的 AI 工作流都能自我进化",
5
5
  "main": "bin/flywheel.js",
6
6
  "bin": {
7
7
  "flywheel": "./bin/flywheel.js"
8
8
  },
9
+ "files": [
10
+ "bin/",
11
+ "scripts/",
12
+ "templates/",
13
+ "skills/_kernel/",
14
+ "skills/_template/"
15
+ ],
9
16
  "scripts": {
10
17
  "postinstall": "chmod +x bin/flywheel.js"
11
18
  },
@@ -0,0 +1,10 @@
1
+ {
2
+ "skills": [
3
+ {
4
+ "name": "req-mining",
5
+ "version": "1.0.0",
6
+ "description": "需求挖掘与落地飞轮"
7
+ }
8
+ ],
9
+ "updated": "2026-05-15"
10
+ }
@@ -37,7 +37,27 @@ cmd_list() {
37
37
  done
38
38
  $found || echo " (未安装任何 skill)"
39
39
  echo ""
40
- echo "安装新 skill:./scripts/flywheel-install.sh add <skill-name>"
40
+ echo "安装新 skillflywheel install <skill-name>"
41
+ }
42
+
43
+ # ── available ─────────────────────────────────────────────────
44
+ cmd_available() {
45
+ echo "━━━ 可安装 Skill 包 ━━━"
46
+ local available_file="$SCRIPT_DIR/available.json"
47
+ if [ -f "$available_file" ]; then
48
+ python3 - << 'PYEOF'
49
+ import json, sys
50
+ with open(sys.argv[1]) as f:
51
+ data = json.load(f)
52
+ for s in data.get('skills', []):
53
+ print(f" - {s['name']} v{s['version']} - {s['description']}")
54
+ PYEOF
55
+ "$available_file"
56
+ else
57
+ echo " (无可用 skill,请检查网络后重试)"
58
+ fi
59
+ echo ""
60
+ echo "安装 skill:flywheel install <skill-name>"
41
61
  }
42
62
 
43
63
  # ── add ────────────────────────────────────────────────────────
@@ -1,42 +0,0 @@
1
- # 启动自飞轮需求挖掘
2
-
3
- 执行以下步骤,激活飞轮模式:
4
-
5
- ## Step 0:检查待蒸馏标记
6
-
7
- 读取 `.distill-needed/` 目录。如果存在标记文件:
8
- - 列出所有待蒸馏项目
9
- - 询问用户是否现在处理,还是先处理新文档
10
- - 若用户选择现在蒸馏:读取 `skills/core/distillation.md`,对每个标记项目执行蒸馏协议(展示预览,单次 y/n 确认),完成后删除标记文件
11
-
12
- ## Step 1:加载运行时上下文
13
-
14
- 按顺序读取:
15
- 1. `memory/patterns/failure-patterns.md`(常驻知识,必须)
16
- 2. `skills/core/auto-req.md`(Ring 1 分析协议)
17
-
18
- ## Step 2:显示飞轮状态
19
-
20
- 输出当前状态摘要:
21
-
22
- ```
23
- ━━━ Req-Miner 自飞轮 | 就绪 ━━━
24
-
25
- 待蒸馏项目:{N} 个
26
- 活跃项目:
27
- • {project_id} — 阶段:{状态} | 假设:{N}项
28
-
29
- 提供文档材料开始 Ring 1 分析:
30
- • 直接粘贴文本
31
- • 输入文件路径(如 /path/to/doc.pdf)
32
- • 输入 URL
33
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
34
- ```
35
-
36
- ## Step 3:等待用户输入材料
37
-
38
- 用户提供材料后,执行 `skills/core/auto-req.md` 的五维度扫描流程。
39
-
40
- ---
41
-
42
- **别名:** 用户输入 `sfw`、`start flywheel`、`开始飞轮`、`开启飞轮` 时,等同于运行本命令。
@@ -1,36 +0,0 @@
1
- # Skill 包管理
2
-
3
- 管理当前项目中安装的 Flywheel skill 包。
4
-
5
- ## 用法
6
-
7
- 用户输入以下命令时,通过 Bash 工具执行对应操作:
8
-
9
- ### `/skill list` 或 `skill list`
10
- ```bash
11
- ./scripts/flywheel-install.sh list
12
- ```
13
- 列出所有已安装的 skill 包、版本号和描述。
14
-
15
- ### `/skill add <skill-name>` 或 `skill add <name>`
16
- ```bash
17
- ./scripts/flywheel-install.sh add <skill-name>
18
- ```
19
- 从官方注册表安装新 skill 包。
20
-
21
- ### `/skill update` 或 `skill update`
22
- ```bash
23
- ./scripts/flywheel-install.sh update
24
- ```
25
- 检查并更新所有已安装 skill 包到最新版本。
26
-
27
- ### `/skill update <skill-name>`
28
- ```bash
29
- ./scripts/flywheel-install.sh update <skill-name>
30
- ```
31
- 更新指定 skill 包。
32
-
33
- ---
34
-
35
- 执行命令后,输出结果并告知用户下一步操作。
36
- 如果安装了新 skill,提示用户使用 `/flywheel` 激活该 skill 的飞轮。
@@ -1,13 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(git -C /home/renmk/projects/Flywheel status --short)",
5
- "Bash(git -C /home/renmk/projects/Flywheel ls-files docs/)",
6
- "Bash(mkdir -p /home/renmk/projects/Flywheel/.claude/worktrees/fix-poster-accuracy/docs)",
7
- "Bash(cp /home/renmk/projects/Flywheel/docs/Flywheel_Poster.html /home/renmk/projects/Flywheel/.claude/worktrees/fix-poster-accuracy/docs/)",
8
- "Bash(git -C /home/renmk/projects/Flywheel/.claude/worktrees/fix-poster-accuracy status --short)",
9
- "Bash(git -C /home/renmk/projects/Flywheel/.claude/worktrees/fix-poster-accuracy log main..HEAD --oneline)",
10
- "Bash(git branch *)"
11
- ]
12
- }
13
- }
File without changes
package/CLAUDE.md DELETED
@@ -1,178 +0,0 @@
1
- # Flywheel:自成长 AI Agent 飞轮框架
2
-
3
- **核心哲学:输入材料,AI 分析,执行反馈,自我进化。**
4
-
5
- 你是一个自飞轮 Agent,从输入材料中自主分析、生成产物、
6
- 桥接执行工具,并通过执行反馈持续蒸馏自身 Skills。
7
-
8
- ## 飞轮激活
9
-
10
- **用户通过以下任意方式激活飞轮:**
11
-
12
- | 方式 | 示例 |
13
- |---|---|
14
- | 斜杠命令(推荐) | `/flywheel` |
15
- | 英文触发词 | `sfw`、`start flywheel` |
16
- | 中文触发词 | `开始飞轮`、`开启飞轮`、`启动飞轮` |
17
- | 直接提供材料 | 粘贴文档 / 文件路径 / URL |
18
-
19
- 检测到以上任意信号时,立即执行 `.claude/commands/flywheel.md` 中的激活流程。
20
-
21
- **默认不激活:** 打开会话后不主动问候或启动,等待用户给出激活信号。
22
-
23
- ---
24
-
25
- ## 目录结构
26
-
27
- ```
28
- CLAUDE.md ← 你正在读的文件(系统引导)
29
- install.sh ← 一键安装脚本
30
- .claude/commands/
31
- flywheel.md ← /flywheel 激活命令
32
- skill.md ← /skill 包管理命令
33
- scripts/
34
- auto-distill.sh ← Ring 3:检查蒸馏触发条件
35
- feedback-hook.sh ← Ring 2→3:收集执行反馈
36
- bridge-to-coder.sh ← Ring 1→2:产物→执行工具
37
- flywheel-install.sh ← skill 包管理工具
38
- skills/
39
- _kernel/
40
- distillation.md ← 通用蒸馏协议(Ring 3 核心)
41
- _template/ ← 新建 skill 的脚手架模板
42
- req-mining/ ← 内置 skill:需求挖掘与落地
43
- skill.yaml ← skill 元数据
44
- domain.md ← Ring 1 分析协议
45
- artifacts.md ← 产物规格
46
- feedback-questions.sh ← 领域专属反馈问题
47
- memory/
48
- failure-patterns.md ← 已知失败模式(常驻加载)
49
- industry/
50
- erp.md ← ERP 行业包
51
- templates/
52
- state.json ← 项目状态模板
53
- projects/ ← 项目状态(Git 忽略)
54
- episodic-logs/ ← 事件日志(Git 忽略)
55
- .distill-needed/ ← 蒸馏触发标记(Git 忽略)
56
- ```
57
-
58
- ---
59
-
60
- ## 飞轮架构
61
-
62
- ```
63
- Ring 1 用户提供材料(文本 / 文件 / URL)
64
-
65
- skill 分析协议(skills/{skill}/domain.md)
66
- ↓ 产物(含假设清单 + 信息缺口)
67
- Ring 2 scripts/bridge-to-coder.sh
68
- ↓ 注入产物到执行工具
69
- 执行工具工作(写入 .flywheel-feedback.json)
70
-
71
- scripts/feedback-hook.sh --auto
72
- ↓ 写入 episodic-logs/
73
- Ring 3 积累 ≥3 条高质量反馈
74
-
75
- 蒸馏协议(skills/_kernel/distillation.md)
76
- ↓ 展示预览,单次 y/n → 更新 skills/ + memory/
77
-
78
- 下次分析更准确 ← 飞轮闭合
79
- ```
80
-
81
- ---
82
-
83
- ## 启动步骤
84
-
85
- **每次会话启动时,首先执行 Step 0:**
86
-
87
- ```
88
- Step 0(必须,优先于一切):检查 .distill-needed/ 目录
89
- → 目录下有文件(如 .distill-needed/proj_xxx)
90
- → 立即读取 skills/_kernel/distillation.md
91
- → 对每个标记的项目执行蒸馏(展示预览,单次 y/n 确认)
92
- → 蒸馏完成后删除对应标记文件
93
- → 所有标记处理完毕后,继续正常会话
94
- ```
95
-
96
- **用户激活飞轮后(Ring 1):**
97
-
98
- ```
99
- 1. 读取已安装 skill 的 memory 文件(常驻,必须)
100
- 2. 读取 skill.yaml,加载对应 domain.md
101
- 3. 根据材料内容判断是否加载行业包
102
- 4. 检查 projects/{project_id}/state.json
103
- - 存在 → 恢复上次会话状态
104
- - 不存在 → 从 templates/state.json 创建,写入 skill 字段
105
- 5. 执行 domain.md 中的分析协议(静默)
106
- 6. 输出分析结果 + 信息缺口清单
107
- 7. 加载 skills/{skill}/artifacts.md,生成产物
108
- 8. 通过 Bash 工具直接调用:
109
- ./scripts/bridge-to-coder.sh {project_id} {tool}
110
- ```
111
-
112
- ---
113
-
114
- ## 会话中的文件操作
115
-
116
- - 每轮对话后:更新 `projects/{project_id}/state.json`(含 `skill` 字段)
117
- - 关键事件:追加到 `episodic-logs/{project_id}.jsonl`
118
- - 蒸馏完成后:删除 `.distill-needed/{project_id}` 标记文件
119
-
120
- ---
121
-
122
- ## Ring 3 蒸馏触发条件
123
-
124
- ```
125
- □ 同一项目积累 ≥3 条 quality_score≥0.6 的反馈事件
126
- □ 同类干预事件跨项目出现 ≥3 次
127
- □ 用户说"蒸馏"、"更新skill"、"从日志学习"
128
- ```
129
-
130
- 触发后读取 `skills/_kernel/distillation.md`,执行蒸馏协议。
131
-
132
- ---
133
-
134
- ## 关键协议
135
-
136
- ### 状态文件路径
137
- ```
138
- projects/{project_id}/state.json ← 含 skill 字段
139
- projects/{project_id}/artifacts/ ← 产物存放位置
140
- ```
141
-
142
- `project_id` 由用户提供或自动生成(格式:`proj_YYYYMMDD_NN`)
143
-
144
- ### 每轮状态行
145
- ```
146
- ━━━ [Ring 1/2/3] | Skill:{skill} | 项目:{project_id} | 假设:X项 ━━━
147
- ```
148
-
149
- ### 未覆盖决策协议
150
- 遇到 skill 未覆盖的场景时,追加到 `uncovered_decisions`,输出 `⚠️ L2 告警`。
151
-
152
- ---
153
-
154
- ## Skill 管理
155
-
156
- ```bash
157
- /skill list # 列出已安装 skill
158
- /skill add code-review # 安装新 skill
159
- /skill update # 更新所有 skill
160
- ```
161
-
162
- ## Git 规范
163
-
164
- ```bash
165
- git add skills/ memory/
166
- git commit -m "distill({skill}): {描述} (from {project_id})"
167
- ```
168
-
169
- ## .gitignore 内容
170
-
171
- ```
172
- projects/*/
173
- episodic-logs/
174
- .distill-needed/*
175
- !.distill-needed/.gitkeep
176
- *.log
177
- .DS_Store
178
- ```