cli-blueprint 0.1.0 → 0.2.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.
Files changed (28) hide show
  1. package/README.md +34 -17
  2. package/install.mjs +148 -7
  3. package/package.json +2 -2
  4. package/skills/blueprint/SKILL.md +33 -25
  5. package/skills/blueprint/install-meta.json +7 -0
  6. package/skills/calctool/SKILL.md +167 -0
  7. package/skills/calctool/install-meta.json +7 -0
  8. package/skills/calctool/platform-template/README.md +74 -0
  9. package/skills/calctool/platform-template/index.html +12 -0
  10. package/skills/calctool/platform-template/package.json +26 -0
  11. package/skills/calctool/platform-template/src/App.tsx +233 -0
  12. package/skills/calctool/platform-template/src/authz.ts +103 -0
  13. package/skills/calctool/platform-template/src/engine/evaluate.ts +114 -0
  14. package/skills/calctool/platform-template/src/engine-definition.json +195 -0
  15. package/skills/calctool/platform-template/src/main.tsx +13 -0
  16. package/skills/calctool/platform-template/src/pipeline.ts +80 -0
  17. package/skills/calctool/platform-template/src/store.ts +53 -0
  18. package/skills/calctool/platform-template/tsconfig.json +15 -0
  19. package/skills/calctool/platform-template/vite.config.ts +7 -0
  20. package/skills/calctool/references/declarative-pages.md +69 -0
  21. package/skills/calctool/references/engine-meta-model.md +123 -0
  22. package/skills/calctool/references/finance-example.md +132 -0
  23. package/skills/calctool/references/formula-dsl.md +92 -0
  24. package/skills/calctool/references/import-ocr.md +72 -0
  25. package/skills/calctool/skill.json +10 -0
  26. package/skills/calctool/templates/ecommerce-ops/README.md +27 -0
  27. package/skills/calctool/templates/ecommerce-ops/domain-reference.yaml +172 -0
  28. package/sources.json +8 -1
package/README.md CHANGED
@@ -1,8 +1,14 @@
1
- # dsh-skillpack
1
+ # cli-blueprint
2
2
 
3
- **多 IDE 通用 skill 插件包** —— 一键安装 / 更新 / 卸载一组 skills,自动适配你本机已安装的每个 IDE,可无限扩展,可分发给任何人。
3
+ **多 skill IDE 安装器** —— 一条命令从 cli.tax 拉取并分发到本机所有已装 IDE,可无限扩展。
4
4
 
5
- 默认包含:`blueprint`(CLI.Tax 工程规划 skill,`https://cli.tax/wvz6zmRWmX`)。
5
+ ```bash
6
+ npx cli-blueprint@latest install
7
+ ```
8
+
9
+ 默认包含:
10
+ - `blueprint`(CLI.Tax 工程规划 skill,`https://cli.tax/wvz6zmRWmX`)
11
+ - `calctool`(万能计算工具生成器,`https://cli.tax/VjFfeR6wdB`)
6
12
 
7
13
  ## 这是什么机制?
8
14
 
@@ -72,34 +78,45 @@ node install.mjs uninstall # 从相同目标卸载本包安装的 skill
72
78
 
73
79
  ## 分发给别人
74
80
 
75
- ### 方式 A:Git 仓库(推荐,最简单)
76
- 把本目录推到一个 git 仓库,使用者:
81
+ ### 方式 A:npm 一条命令(推荐,最简单)
82
+ 已发布到 npm(`cli-blueprint@0.1.0` / `cli-calctool@0.1.0`),使用者只需:
83
+ ```bash
84
+ npx cli-blueprint@latest install # 装 blueprint + calctool 两个 skill
85
+ npx cli-calctool@latest install # 同样内容(calctool 命名入口)
86
+ ```
87
+ 自动完成:从 cli.tax 拉取 blueprint + calctool → 检测本机已装 IDE → 分发到每个 IDE。
88
+ 更新:同一命令(`@latest` 自动拉新版),且每次 install 会对比 cli.tax 最新版本并提示 ⤴。
89
+
90
+ ### 方式 B:Git 仓库
77
91
  ```bash
78
- git clone <repo-url> && cd dsh-skillpack && node install.mjs install
92
+ git clone https://github.com/88208555/Blueprint-clitax.git
93
+ cd Blueprint-clitax
94
+ node install.mjs install
79
95
  ```
80
- 更新:`git pull && node install.mjs update`
96
+ 更新:`git pull && node install.mjs update`(install/update 会对比已装版本与 cli.tax 最新版本并提示)。
81
97
 
82
- ### 方式 B:发布为 npm 包(一条命令装)
83
- 本包已配好 `bin`,发布后使用者只需:
98
+ ### 更新感知(check)
99
+ 安装器写入 `install-meta.json`(来源/版本/时间)到每个 skill 目录;SKILL.md 注入版本横幅,
100
+ IDE 每次读取即可见版本与更新入口。主动检查:
84
101
  ```bash
85
- npx dsh-skillpack@latest install
102
+ node install.mjs check # 遍历本机已装 IDE,对比 cli.tax 最新版本
103
+ npx cli-blueprint@latest check # 单包检查(calctool 同理)
86
104
  ```
87
- 更新:同一命令(`@latest` 自动拉新版)。
88
- > 注意 npm 官方源对包名唯一性有要求;内部使用可部署私有 registry(如 Verdaccio)。
89
105
 
90
- ### 方式 C:直接用 clitaxio(如果只想引第三方 skill)
106
+ ### 方式 C:直接用 clitaxio(只装单个 IDE,作为对照)
91
107
  ```bash
92
- npx clitaxio@latest install <runtime-code> ~/.codex/skills/<slug>
108
+ npx clitaxio@latest install wvz6zmRWmX
93
109
  ```
94
- 本包是更可控的本地化替代:离线可用、可审计、可 git 管理、可批量管理多个 skill、自动多 IDE 分发。
110
+ > ⚠️ 注意:clitaxio **只把 skill 装到默认的 Codex 目录**(单一 IDE),不会自动检测/分发到
111
+ > 其他 IDE,也不处理 `~/.agents/skills` 共享根重复问题。需要多 IDE 分发请用方式 A/B。
95
112
 
96
113
  ## 目录结构
97
114
 
98
115
  ```
99
- dsh-skillpack/
116
+ cli-blueprint/
100
117
  ├── install.mjs # 安装器(Node ≥18,零依赖):pull / install / uninstall / list / ides
101
118
  ├── sources.json # ★ cli.tax skill 源清单(code → 自动拉取),扩展就加一行
102
- ├── package.json # npm 包元数据(可发布)
119
+ ├── package.json # npm 包元数据(cli-blueprint)
103
120
  ├── README.md
104
121
  └── skills/ # skill 内容(pull 生成,可提交 git 离线兜底)
105
122
  └── blueprint/
package/install.mjs CHANGED
@@ -15,6 +15,11 @@
15
15
  * 需要时用 --agents 显式开启(会打印警告);
16
16
  * - --ide / --skip 精确控制;新增 IDE 只需在 IDES 表加一行。
17
17
  *
18
+ * 更新感知:
19
+ * - pull 时把 cli.tax 返回的 version 写入 skills/<slug>/install-meta.json;
20
+ * - install / update 时对比「已安装版本」与「远端最新版本」,有新版本会提示;
21
+ * - check 子命令:遍历本机已装 IDE 的 skill 目录,对比远端最新版本并报告更新。
22
+ *
18
23
  * 用法:
19
24
  * node install.mjs pull # 从 sources.json(cli.tax)拉取全部 skill 到 skills/
20
25
  * node install.mjs install # 自动匹配:只装本机已安装的 IDE(推荐)
@@ -26,6 +31,7 @@
26
31
  * node install.mjs install --agents # 额外安装到共享 ~/.agents/skills(警告)
27
32
  * node install.mjs install --target /abs/path # 仅自定义目录
28
33
  * node install.mjs update # 同 install(幂等覆盖)
34
+ * node install.mjs check # 检查已安装 skill 是否有新版本(对比 cli.tax)
29
35
  * node install.mjs uninstall # 从相同目标移除本包安装的 skills
30
36
  * node install.mjs list # 列出本包包含的 skills
31
37
  * node install.mjs ides # 列出已知 IDE 及本机检测结果
@@ -45,6 +51,9 @@ const SKILLS_SRC = join(__dirname, 'skills')
45
51
  const HOME = homedir()
46
52
  const CWD = process.cwd()
47
53
 
54
+ /** 每个 skill 安装/拉取时的版本元数据文件名(IDE 目录与 skills/ 内都会写) */
55
+ const INSTALL_META = 'install-meta.json'
56
+
48
57
  /**
49
58
  * 全世界已知 IDE/编码 agent 的 skills 安装位置表(官方文档核实,2026-08)。
50
59
  * key: 命令行标识
@@ -126,14 +135,37 @@ async function syncOne(name, targetRoot, { remove = false } = {}) {
126
135
  return
127
136
  }
128
137
  await mkdir(dest, { recursive: true })
129
- await cp(join(SKILLS_SRC, name), dest, { recursive: true, force: true })
130
- print(` ✓ 已安装 ${name} → ${dest}`)
138
+ const sourceDir = join(SKILLS_SRC, name)
139
+ const destMeta = readMeta(dest) // 覆盖前读取旧版本
140
+ await cp(sourceDir, dest, { recursive: true, force: true })
141
+ const srcMeta = readMeta(sourceDir)
142
+ // 安装时注入版本横幅到 SKILL.md(IDE 每次读取即见版本与更新入口)
143
+ if (srcMeta?.version) {
144
+ const installedSkillMd = readFileSync(join(dest, 'SKILL.md'), 'utf8')
145
+ await writeFile(join(dest, 'SKILL.md'), injectVersionBanner(installedSkillMd, srcMeta.version, name))
146
+ }
147
+ if (srcMeta) {
148
+ await writeMeta(dest, { ...srcMeta, installedAt: new Date().toISOString() })
149
+ }
150
+ const upgrade = destMeta && srcMeta && destMeta.version && srcMeta.version && destMeta.version !== srcMeta.version
151
+ if (upgrade) {
152
+ print(` ⤴ 已更新 ${name} ${destMeta.version} → ${srcMeta.version} → ${dest}`)
153
+ } else {
154
+ print(` ✓ 已安装 ${name} → ${dest}${srcMeta?.version ? `(${srcMeta.version})` : ''}`)
155
+ }
131
156
  }
132
157
 
133
- async function syncAll(targetRoot, { remove = false } = {}) {
158
+ async function syncAll(targetRoot, { remove = false, reportUpdated } = {}) {
134
159
  const skills = await listSkills()
135
160
  if (!remove) await mkdir(targetRoot, { recursive: true })
136
- for (const s of skills) await syncOne(s, targetRoot, { remove })
161
+ for (const s of skills) {
162
+ const before = reportUpdated ? readMeta(join(targetRoot, s)) : null
163
+ await syncOne(s, targetRoot, { remove })
164
+ if (reportUpdated && before && before.version) {
165
+ const after = readMeta(join(targetRoot, s))
166
+ if (after && after.version && after.version !== before.version) reportUpdated(1)
167
+ }
168
+ }
137
169
  }
138
170
 
139
171
  /** 解析目标列表:--target / --ide / --skip / 默认(全部已知 IDE) */
@@ -202,6 +234,31 @@ function parseTargets(args) {
202
234
 
203
235
  const [cmd, ...rest] = process.argv.slice(2)
204
236
 
237
+ /** 读取 skill 目录的 install-meta.json(没有则返回 null) */
238
+ function readMeta(skillDir) {
239
+ const p = join(skillDir, INSTALL_META)
240
+ if (!existsSync(p)) return null
241
+ try { return JSON.parse(readFileSync(p, 'utf8')) } catch { return null }
242
+ }
243
+
244
+ /** 写入 skill 目录的 install-meta.json(来源/版本/时间/地址) */
245
+ async function writeMeta(skillDir, meta) {
246
+ await writeFile(join(skillDir, INSTALL_META), `${JSON.stringify(meta, null, 2)}\n`)
247
+ }
248
+
249
+ /** 在 SKILL.md frontmatter 之后注入版本横幅:IDE 每次读取即见版本与更新命令 */
250
+ function injectVersionBanner(skillMd, version, slug) {
251
+ if (!skillMd || !version) return skillMd
252
+ const banner = `<!-- calctool-installer: version ${version} · 检查更新见 install-meta.json / npx cli-${slug}@latest check -->\n`
253
+ if (skillMd.startsWith('---')) {
254
+ const end = skillMd.indexOf('\n---', 3)
255
+ if (end !== -1) {
256
+ return `${skillMd.slice(0, end + 5)}\n\n${banner}${skillMd.slice(end + 5).replace(/^\n+/, '')}`
257
+ }
258
+ }
259
+ return `${banner}${skillMd}`
260
+ }
261
+
205
262
  /** 从 cli.tax 拉取一个 skill 到 skills/<slug>/(覆盖本地副本) */
206
263
  async function pullSkill(source) {
207
264
  const url = source.endpoint.replace('{code}', source.code)
@@ -215,10 +272,83 @@ async function pullSkill(source) {
215
272
  await mkdir(dir, { recursive: true })
216
273
  await writeFile(join(dir, 'SKILL.md'), data.skillMd)
217
274
  await writeFile(join(dir, 'skill.json'), data.skillJson)
218
- print(` ✓ 已拉取 ${data.displayName} ${data.version ?? ''} → skills/${data.slug}/`)
275
+ const previous = readMeta(dir)
276
+ await writeMeta(dir, {
277
+ source: source.code,
278
+ slug: data.slug || source.slug,
279
+ version: data.version ?? '',
280
+ endpoint: url,
281
+ installedAt: new Date().toISOString(),
282
+ })
283
+ const changed = previous && previous.version && previous.version !== data.version
284
+ if (changed) {
285
+ print(` ⤴ 已更新 ${data.displayName} ${previous.version} → ${data.version ?? ''} → skills/${data.slug}/`)
286
+ } else {
287
+ print(` ✓ 已拉取 ${data.displayName} ${data.version ?? ''} → skills/${data.slug}/`)
288
+ }
219
289
  return true
220
290
  }
221
291
 
292
+ /** 从 cli.tax 拉取单个 skill 的最新元数据(check 用,不写盘) */
293
+ async function fetchLatestMeta(source) {
294
+ const url = source.endpoint.replace('{code}', source.code)
295
+ try {
296
+ const resp = await fetch(url)
297
+ if (!resp.ok) return null
298
+ const data = await resp.json()
299
+ return {
300
+ source: source.code,
301
+ slug: data.slug || source.slug,
302
+ version: data.version ?? '',
303
+ displayName: data.displayName ?? data.slug ?? source.slug,
304
+ endpoint: url,
305
+ }
306
+ } catch {
307
+ return null
308
+ }
309
+ }
310
+
311
+ /** check:遍历已安装目标的 skill 目录,对比远端最新版本,报告更新 */
312
+ async function checkUpdates(targets) {
313
+ const sources = loadSources()
314
+ if (!sources.length) {
315
+ print('⚠ sources.json 无源,无法检查更新。')
316
+ return 1
317
+ }
318
+ let found = 0
319
+ for (const t of targets) {
320
+ print(`[${t.label}] ${t.path}`)
321
+ if (!existsSync(t.path)) { print(' · 未安装'); continue }
322
+ const entries = (await readdir(t.path, { withFileTypes: true }).catch(() => []))
323
+ .filter((e) => e.isDirectory())
324
+ if (!entries.length) { print(' · 无已安装 skill'); continue }
325
+ for (const e of entries) {
326
+ const skillDir = join(t.path, e.name)
327
+ const local = readMeta(skillDir)
328
+ const source = sources.find((s) => (s.slug === e.name)
329
+ || (local && local.source === s.code))
330
+ if (!source) continue
331
+ const remote = await fetchLatestMeta(source)
332
+ if (!remote) { print(` · ${e.name}:远端查询失败,跳过`); continue }
333
+ if (!local || !local.version) {
334
+ print(` · ${e.name}:本地无版本记录(旧安装),远端最新 ${remote.version} —— 运行 install 补齐`)
335
+ found++
336
+ } else if (local.version === remote.version) {
337
+ print(` ✓ ${e.name} 已是最新(${remote.version})`)
338
+ } else {
339
+ print(` ⤴ ${e.name} 有新版本 ${local.version} → ${remote.version} —— 运行 install 更新`)
340
+ found++
341
+ }
342
+ }
343
+ }
344
+ if (found) {
345
+ print(`\n发现 ${found} 个 skill 可更新。执行: node install.mjs install`)
346
+ } else {
347
+ print('\n全部已是最新。')
348
+ }
349
+ return 0
350
+ }
351
+
222
352
  /** 读取 sources.json 中的源列表 */
223
353
  function loadSources() {
224
354
  const p = join(__dirname, 'sources.json')
@@ -269,14 +399,22 @@ if (cmd === 'list') {
269
399
  if (!skills.length) { print('skills/ 目录为空,无法安装'); process.exit(1) }
270
400
  if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
271
401
  print(`将安装 ${skills.length} 个 skills → ${targets.length} 个目标`)
402
+ let updated = 0
272
403
  for (const t of targets) {
273
404
  print(`[${t.label}] ${t.path}`)
274
- await syncAll(t.path)
405
+ await syncAll(t.path, { reportUpdated: (n) => { updated += n } })
275
406
  }
276
407
  if (rest.includes('--agents')) {
277
408
  print('⚠ 已安装到共享 ~/.agents/skills:该目录会被 Codex/Gemini/Zed/OpenCode/Cursor 等同时扫描,同一 skill 可能被重复发现。')
278
409
  }
279
410
  print('完成。各 IDE 会自动发现各自用户级根中的新目录(可立即在新会话中调用)。')
411
+ if (updated) {
412
+ print(`提示:${updated} 个 skill 有更新。以后可用 node install.mjs check 检查新版本。`)
413
+ }
414
+ } else if (cmd === 'check') {
415
+ const targets = parseTargets(rest)
416
+ if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
417
+ process.exitCode = await checkUpdates(targets)
280
418
  } else if (cmd === 'uninstall') {
281
419
  const targets = parseTargets(rest)
282
420
  if (rest.includes('--agents') && !targets.some((t) => t.path === AGENTS.path)) targets.push(AGENTS)
@@ -290,8 +428,11 @@ if (cmd === 'list') {
290
428
  node install.mjs install [--all|--ide <key>|--skip <key>|--project|--agents|--pull|--target <dir>]
291
429
  node install.mjs pull
292
430
  node install.mjs update
431
+ node install.mjs check
293
432
  node install.mjs uninstall
294
433
  node install.mjs list
295
- node install.mjs ides`)
434
+ node install.mjs ides
435
+
436
+ npm 安装后(npx cli-blueprint@latest / npx cli-calctool@latest)用法相同。`)
296
437
  process.exit(1)
297
438
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cli-blueprint",
3
- "version": "0.1.0",
4
- "description": "Blueprint skill 多 IDE 安装器:从 cli.tax 自动拉取并分发到本机所有已装 IDE(Codex/DSH/Claude/Cursor/…)。",
3
+ "version": "0.2.1",
4
+ "description": "Blueprint + calctool 多 IDE 安装器:从 cli.tax 自动拉取并分发到本机所有已装 IDE(Codex/DSH/Claude/Cursor/…)。支持 check 更新检测。",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "cli-blueprint": "install.mjs"
@@ -1,39 +1,47 @@
1
1
  ---
2
- name: "blueprint"
3
- description: "Blueprint 是一个跨工具的工程规划 CLI,把明确目标编译为可执行、可追溯、可验收的全站工程蓝图,并通过确定性规则检查每个节点、分支、合同、任务与验收闭环。默认由当前 IDE 的多智能体协同推演,也可连接用户自行安装的本地 Hermes;平台不托管模型密钥。"
2
+ name: blueprint
3
+ description: Compile one goal into an implementable engineering blueprint with deterministic checks. Use when the user wants to turn an idea, product, or site goal into an executable engineering plan with nodes, dependencies, acceptance criteria, and validation.
4
4
  ---
5
5
 
6
- # blueprint
6
+ # Blueprint Skill
7
7
 
8
- Use this Skill only when the user's request matches the capability described below.
8
+ Endpoint: https://cli.tax/wvz6zmRWmX
9
+ Request schema: blueprint.skill.request/1.0
10
+ Response schema: blueprint.skill.response/1.0
9
11
 
10
- ## Capability
12
+ ## Request envelope
11
13
 
12
- - Source type: Skill
13
- - Version: v0.4.0
14
- - Status at generation: published
15
- - Address: `https://cli.tax/wvz6zmRWmX`
16
- - Method: `POST`
17
- - Content type: `application/json`
18
-
19
- Blueprint 是一个跨工具的工程规划 CLI,把明确目标编译为可执行、可追溯、可验收的全站工程蓝图,并通过确定性规则检查每个节点、分支、合同、任务与验收闭环。默认由当前 IDE 的多智能体协同推演,也可连接用户自行安装的本地 Hermes;平台不托管模型密钥。
20
-
21
- ## Invocation
22
-
23
- Send JSON to the exact CLI address and put capability arguments inside `input`:
14
+ POST JSON to the endpoint with an `input` wrapper:
24
15
 
25
16
  ```json
26
17
  {
27
- "input": {}
18
+ "input": {
19
+ "schemaVersion": "blueprint.skill.request/1.0",
20
+ "requestId": "<unique-id>",
21
+ "operation": "<operation>",
22
+ "input": {}
23
+ }
28
24
  }
29
25
  ```
30
26
 
31
- Do not rewrite the CLI address, invent parameters, or include API keys, tokens, cookies, passwords, or private keys. Ask for missing non-secret inputs. Runtime invocation is available only after the CLI is published and the owner has an active subscription.
27
+ ## Operations
28
+
29
+ - `capabilities`: discover the operation list, per-operation inputs, and the recommended next step.
30
+ - `help`: return the usage guide, operation catalog, and request examples.
31
+ - `intake`: return the questions the IDE must ask the user before building the Blueprint.
32
+ - `validate`: deterministically validate a Blueprint object conforming to `blueprint.ir/1.0`.
33
+ - `compile-inline`: validate and compile a Blueprint, returning the generated artifacts inline.
34
+
35
+ ## Required flow
36
+
37
+ 1. Call `capabilities` first and read the returned `nextStep`.
38
+ 2. Call `intake` and ask the user the returned questions one at a time, waiting for each answer.
39
+ 3. Do not compile a Blueprint until all required questions are answered.
40
+ 4. Build a Blueprint conforming to `blueprint.ir/1.0`, then call `validate`.
41
+ 5. Fix every validation finding until the report is green, then call `compile-inline` and save the artifacts.
32
42
 
33
- ## Errors
43
+ ## Safety rules
34
44
 
35
- - `402`: subscription or quota unavailable
36
- - `404`: CLI is unavailable or not published
37
- - `422`: invalid input or contract
38
- - `429`: rate or concurrency limit reached
39
- - `5xx`: execution or upstream failure
45
+ - Never send credentials, model keys, provider endpoints, or personal secrets inside the request envelope or `input`.
46
+ - The response `status` must be `succeeded`; a `failed` response is an error, not a result.
47
+ - Public responses never prove that code was developed, tested, or deployed.
@@ -0,0 +1,7 @@
1
+ {
2
+ "source": "wvz6zmRWmX",
3
+ "slug": "blueprint",
4
+ "version": "v0.4.0",
5
+ "endpoint": "https://cli.tax/api/public/skills/wvz6zmRWmX",
6
+ "installedAt": "2026-08-17T00:00:00.000Z"
7
+ }
@@ -0,0 +1,167 @@
1
+ ---
2
+ name: calctool
3
+ description: 按需生成「万能计算工具」:用户输入一个领域需求(如"我是财务,想要一个经营健康诊断工具"),本技能通过提问明确指标、公式、输入方式与输出形式,生成一个可执行、可验证、可发布的在线计算工具——支持自定义指标、自定义公式逻辑、用户上传内容自动识别(Excel 映射 / 图片 OCR)、报告输出。当用户想"把某套计算逻辑/指标/公式做成在线工具"时使用。
4
+ ---
5
+
6
+ # calctool
7
+
8
+ 把「业务计算逻辑」编译为「可执行的在线计算工具」的生成器。
9
+
10
+ ## 全链路总流程(老板视角 → 可运行工具)
11
+
12
+ ```
13
+ 老板(任何 IDE / DSH):"我要搭电商运营计算工具"
14
+
15
+ 1. 顾问式对话(intake-round) —— 智能体主动给方案(基于领域参考包),
16
+ 老板逐轮确认指标/公式/口径,直到说"创建"
17
+
18
+ 2. 情报蜂群(research) —— 自动派情报智能体搜索行业标准/抓指定地址,
19
+ 产出可溯源参考包(老板说"电商"等关键词时自动触发)
20
+
21
+ 3. 蜂群执行(brain-invoke/complete)—— 需求自动拆解为 fields/formulas/rules/
22
+ imports/reports/pages 任务,依赖图驱动并行,独立复核,确定性合并
23
+
24
+ 4. 编译工具(compile-tool) —— 引擎定义 → 可运行工程文件清单
25
+ (App 壳/公式引擎/存储/构建,页面自动生成:录入/指标卡/报告)
26
+
27
+ 5. 环境适配(probe-env/adapt-config)—— 自动探测 Node 版本/包管理器/OS/架构,
28
+ Node≥18 全功能、16 兼容(sql.js)、<16 零构建预览;pnpm/yarn/npm 自动适配
29
+
30
+ 6. 完成前门禁(final-gate) —— 审计/测试/运维三智能体协调接管检测,
31
+ 全部符合通过(engine-valid / 基准样例全通过 / 环境就绪)才标记完成
32
+
33
+ 7. 交付运行 —— 按适配命令一键搭建(pnpm install → pnpm run dev)
34
+ → 老板得到可交互工具;后续对话继续改指标/公式(热更新)
35
+
36
+ 或直接走「全自动流水线」(auto-pipeline)——老板只需说需求 + 授权一次:
37
+ 授权(告知消耗) → 情报蜂群 → 蜂群生成 → 测试审计 → 编译 → 自动启动弹出页面
38
+ → 完成前门禁(审计/测试/运维三智能体协调接管,全部符合通过才标记完成)
39
+ 全程无需老板参与,热更新即时生效
40
+ ```
41
+
42
+ **关键**:老板一句话 → 对话确认 → 情报 → 蜂群 → 编译 → 环境适配 → **可运行工具**。全程框架不变,需求变更只改配置。
43
+
44
+ ## 何时使用
45
+
46
+ - 用户描述了一个领域场景(财务、运营、工程、教育、医疗……)并想要一个可交互的在线计算工具
47
+ - 用户已有指标、公式、评分或报告逻辑,想固化成工具
48
+ - 用户需要"自定义指标 + 自定义公式 + 上传识别"能力
49
+
50
+ 不要用于:纯展示型页面(无计算)、与计算无关的 CRUD 后台。
51
+
52
+ ## 核心原则
53
+
54
+ 1. **确定性计算**:正式数字由版本化确定性引擎(公式 AST + Decimal 运行时)产生;模型/OCR/AI 只产生候选、草稿与解释,绝不直接给出不可追溯的正式结果。
55
+ 2. **配置化而非代码化**:工具 = 一份可发布的引擎定义(字段目录 + 公式图 + 规则包 + 导入映射 + 视图 + 报告),不是散落的页面代码。
56
+ 3. **显式除零**:所有除法必须选 `div`(除零报错)或 `safeDivide`(除零回退),不静默吞错。
57
+ 4. **零虚构**:能力未接入时保持"未接入态"(planned/not_installed/disconnected),不虚构数据、状态或按钮。
58
+
59
+ ## 五步实施流程
60
+
61
+ ### 1. intake —— 收集需求(必须提问,一次一问)
62
+ 调用运行时 intake 或按下面问题逐条问用户:
63
+ - 目标:这个工具帮用户完成什么?什么必须发生、什么绝不允许发生?
64
+ - 输入指标:用户会输入哪些字段?(如收入、成本、人数、月份)
65
+ - 公式逻辑:哪些指标由公式算出?(如毛利 = 收入 - 成本)
66
+ - 输入方式:手工录入 / Excel 上传 / 图片 OCR / 三者都要?
67
+ - 输出形式:指标卡、表格、诊断报告、历史记录?
68
+ - 约束:单位、精度、语言、离线/在线、禁止项?
69
+
70
+ ### 2. 生成引擎定义(Engine Definition)
71
+ ```yaml
72
+ engineId: <kebab-case-引擎名>
73
+ name: <显示名>
74
+ category: <领域,如 finance/operations/education>
75
+ ownerType: platform-template
76
+ status: draft
77
+ semanticVersion: 1.0.0
78
+ compatibilityProfile: legacy-compatible
79
+ decimalPolicy: decimal-string
80
+ defaultLocale: zh-CN
81
+ ```
82
+ 包含(详见 references/engine-meta-model.md):
83
+ - field-catalog:字段目录(类型:amount/ratio/int/enum/dimension/date)
84
+ - formula-graph:公式图(节点 = 字段/公式,边 = 依赖)
85
+ - rule-packs:规则包(阈值、评分、分级)
86
+ - import-profiles:导入映射(Excel 列 / OCR 字段 → 字段目录)
87
+ - report-template:报告模板(指标卡 + 表格 + 诊断结论)
88
+
89
+ ### 3. 编译公式(详见 references/formula-dsl.md)
90
+ - 把自然语言/Excel 公式编译为 JSON AST(禁止 eval/new Function)
91
+ - 运算符走最小注册表(add/sub/mul/div/safeDivide/percentOf/if/case/sum/avg/lookup…)
92
+ - 数值用 Decimal 字符串,单位编译期推断,错误结构化传播
93
+ - 发布前跑依赖图检查:引用存在、无环、可见范围
94
+
95
+ ### 4. 生成在线工具(详见 references/declarative-pages.md)
96
+ - 表单页:录入字段(按 field-catalog 自动生成)
97
+ - 指标卡页:公式结果 StatGrid
98
+ - 报告页:结构化输出 + 可导出
99
+ - 页面用声明式规格(ApplicationPageSpec),不手写重复模板
100
+
101
+ ### 5. 验收与发布
102
+ - validate:确定性校验引擎定义(引用闭合、无环、单位一致、测试通过)
103
+ - 上传识别走导入 Profile(Excel 映射 + OCR 草稿确认,自动导入先进草稿)
104
+ - **完成前门禁(final-gate)**:每次项目完成之前,审计/测试/运维三智能体协调接管检测——
105
+ - **审计智能体**:引擎定义确定性校验 0 findings、公式仅走受控 AST(禁 eval)、引用闭合
106
+ - **测试智能体**:基准样例(testSuites)全部通过,一个不过都不放行
107
+ - **运维智能体**:环境探测成功、依赖分级适配、安装/启动命令可用、热更新就绪
108
+ - 三智能体全部符合通过(gate passed)才标记完成;任一未通过返回 findings,修复后重新接管检测
109
+ - 发布为版本化引擎,任何公式/字段/阈值变化都创建新版本,不原地修改
110
+ - 输出:可运行的在线工具 + 引擎定义包 + 验收报告 + 完成前门禁结论
111
+
112
+ ## 多智能体蜂群模式(大脑协同,推荐复杂工具用)
113
+
114
+ 单智能体 `compile-inline` 适合简单工具;复杂工具(多字段 + 多公式 + 规则 + 导入 + 报告)用**蜂群协同**,多智能体并行生成、独立复核、确定性合并——准确率更高、产出更强。
115
+
116
+ ### 大脑模式(brain-handshake)
117
+ - `ide`:用当前 IDE 的多智能体(subagent)执行蜂群(默认)
118
+ - `hermes_local`:用用户本地安装的 Hermes 执行蜂群
119
+
120
+ ### 蜂群流程(协议 calctool.coordinator.run-plan/1.0)
121
+
122
+ 1. **brain-handshake**:协商大脑模式(ide/hermes_local),返回蜂群能力
123
+ 2. **brain-invoke**:传需求 → **自动拆解**为蜂群任务(按需派发,需要几个派几个):
124
+ - `fields` 字段目录(入口,总是有)
125
+ - `formulas` 公式图(有公式才派)· 独立复核
126
+ - `rules` 规则包(有规则才派)· 独立复核
127
+ - `imports` 导入映射(有导入才派)
128
+ - `reports` 报告模板(有报告才派)
129
+ - `pages` 页面规格(总是有)
130
+ 依赖图驱动:fields 先 → formulas/imports 并行 → reports → pages;maxParallel 控制并发
131
+ 3. **brain-invoke 批量派发**:每个就绪 work item 派给一个独立智能体,收集产物
132
+ 4. **brain-events / brain-status**:流式收集事件、查询蜂群状态(就绪/运行/阻塞)
133
+ 5. **brain-complete**:提交全部产物 → **确定性合并**为引擎定义 → 校验 → 发布
134
+ 6. **brain-cancel**:随时取消蜂群
135
+
136
+ ### 准确率与用户控制
137
+ - **准确率**:合并后引擎定义必须通过确定性校验(引用闭合/公式链/单位/Decimal/无环),0 findings 才发布
138
+ - **用户控制**:每一步产物可查看、修改、重试(budget.maxAttempts);最终工具可测算、改公式、调阈值
139
+ - **编程能力**:蜂群产物是真实可编译的引擎定义(JSON AST + Decimal 运行时),不是伪代码
140
+
141
+ ## 输出产物
142
+
143
+ ```
144
+ <engine-id>/
145
+ ├── manifest.yaml # 引擎身份与版本
146
+ ├── field-catalog.json # 字段目录
147
+ ├── formula-graph.json # 公式图(AST)
148
+ ├── rule-packs.json # 规则包
149
+ ├── import-profiles.json # 导入映射
150
+ ├── report-template.json # 报告模板
151
+ └── tests/ # 确定性测试(样例 → 期望结果)
152
+ ```
153
+
154
+ ## 参考文档
155
+
156
+ - `references/engine-meta-model.md` —— 引擎元模型(字段/公式/规则/导入/报告)
157
+ - `references/formula-dsl.md` —— 公式 DSL 与运行时(AST/Decimal/依赖图/错误值)
158
+ - `references/declarative-pages.md` —— 声明式页面规格系统(表单/指标/报告渲染)
159
+ - `references/import-ocr.md` —— 导入与 OCR(Excel 映射/图片识别/草稿确认)
160
+ - `references/finance-example.md` —— 经营健康诊断完整范例(50 字段 → 10 指标 → 报告)
161
+
162
+ ## 安全规则
163
+
164
+ - 不执行任意 JavaScript;公式只走受控 AST
165
+ - 上传文件先验证类型/大小/指纹,OCR 结果进草稿不覆盖正式数据
166
+ - 不虚构后端数据;未接入能力显示真实状态
167
+ - 财务/税务输出需明确"经营估算模型,生产使用前由专业人员复核"
@@ -0,0 +1,7 @@
1
+ {
2
+ "source": "KKyA6xljUX",
3
+ "slug": "calctool",
4
+ "version": "v0.3.0",
5
+ "endpoint": "https://cli.tax/api/public/skills/KKyA6xljUX",
6
+ "installedAt": "2026-08-17T00:00:00.000Z"
7
+ }
@@ -0,0 +1,74 @@
1
+ # calctool 平台模板
2
+
3
+ 由 calctool 生成的**可运行计算工具**工程模板(配置驱动、框架不变)。
4
+
5
+ ## 一键运行
6
+
7
+ ```bash
8
+ npm install # 或 pnpm install / yarn install(环境自动适配)
9
+ npm run dev # 启动开发服务器 http://localhost:5173
10
+ ```
11
+
12
+ ## 结构
13
+
14
+ ```
15
+ ├── src/
16
+ │ ├── main.tsx # 入口(Ant Design X ConfigProvider)
17
+ │ ├── App.tsx # 应用壳(录入/指标卡/链路/报告/授权 五页)
18
+ │ ├── engine-definition.json # ★ 引擎定义 + 链路(改这里 = 改工具,框架不动)
19
+ │ ├── engine/
20
+ │ │ ├── evaluate.ts # JSON AST + decimal.js 确定性求值
21
+ │ │ └── (recompute.ts 依赖图增量重算,按需扩展)
22
+ │ ├── pipeline.ts # ★ 链路编排(联通节点,非单页孤岛)
23
+ │ ├── authz.ts # ★ 授权管理(首次使用同意 + 逐能力授权,一次授权持久化)
24
+ │ └── store.ts # 存储层(localStorage,可换 sqlite)
25
+ ├── vite.config.ts
26
+ └── package.json
27
+ ```
28
+
29
+ ## 整套工具(联通节点,非单页孤岛)
30
+
31
+ 工具由**联通节点**组成,数据流在节点间流动:
32
+
33
+ ```
34
+ 录入/导入 → 数据校验 → 确定性计算 → 数据存储 → 指标卡/报告
35
+ ↘ 自动化(可选)
36
+ ```
37
+
38
+ - 改动指标/公式:只改 `engine-definition.json`,链路自动感知
39
+ - 新增能力:在 `pipeline.ts` 加节点(如导入、导出、告警),页面无需改
40
+ - 页面「链路」Tab 可视化每个节点及其上下游,改工具时定位影响范围
41
+
42
+ ## 授权与消耗提示
43
+
44
+ 1. **首次使用总提示**:打开工具时弹窗告知"可能调用其他技能辅助、可能增加消耗",同意后持久化不再提示(可按工具分别记录)
45
+ 2. **逐能力授权**:实际调用外部能力(Blueprint/搜索/模型/存储/自动化)前询问,一次授权永久记住
46
+ 3. **授权管理页**:随时查看已授权能力、撤销授权
47
+
48
+
49
+ ## 改指标/公式(需求变更,框架不变)
50
+
51
+ 编辑 `src/engine-definition.json`:
52
+
53
+ ```json
54
+ {
55
+ "fields": [{ "key": "visitors", "label": "访客数", "type": "integer", "unit": "人" }],
56
+ "formulas": [
57
+ { "key": "conversionRate", "label": "转化率",
58
+ "expression": { "op": "safeDivide", "args": [{ "ref": "orders" }, { "ref": "visitors" }] } }
59
+ ]
60
+ }
61
+ ```
62
+
63
+ 保存即热更新——**不用改任何代码**。
64
+
65
+ ## 公式运算符(详见 formula-dsl.md)
66
+
67
+ `add / sub / mul / div(除零报错)/ safeDivide(除零回退)/ percentOf / round / if / ref / lit`
68
+
69
+ ## 环境适配
70
+
71
+ - Node ≥18:全功能(可换 better-sqlite3 持久化)
72
+ - Node 16:兼容(sql.js WASM)
73
+ - Node <16:建议只用 L0 配置预览
74
+ - 包管理器:npm/pnpm/yarn 命令自动适配
@@ -0,0 +1,12 @@
1
+ <!doctype html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>calctool 计算工具</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>