cli-calctool 1.0.0 → 1.0.2
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 +9 -161
- package/cli.mjs +238 -0
- package/package.json +12 -14
- package/{skills/calctool → skill}/SKILL.md +9 -5
- package/{skills/calctool → skill}/skill.json +2 -2
- package/LICENSE +0 -201
- package/install.mjs +0 -442
- package/skills/blueprint/SKILL.md +0 -47
- package/skills/blueprint/install-meta.json +0 -7
- package/skills/blueprint/skill.json +0 -10
- package/skills/calctool/install-meta.json +0 -7
- package/skills/calctool/platform-template/README.md +0 -74
- package/skills/calctool/platform-template/index.html +0 -12
- package/skills/calctool/platform-template/package.json +0 -26
- package/skills/calctool/platform-template/src/App.tsx +0 -233
- package/skills/calctool/platform-template/src/authz.ts +0 -103
- package/skills/calctool/platform-template/src/engine/evaluate.ts +0 -114
- package/skills/calctool/platform-template/src/engine-definition.json +0 -195
- package/skills/calctool/platform-template/src/main.tsx +0 -13
- package/skills/calctool/platform-template/src/pipeline.ts +0 -80
- package/skills/calctool/platform-template/src/store.ts +0 -53
- package/skills/calctool/platform-template/tsconfig.json +0 -15
- package/skills/calctool/platform-template/vite.config.ts +0 -7
- package/skills/calctool/references/declarative-pages.md +0 -69
- package/skills/calctool/references/engine-meta-model.md +0 -123
- package/skills/calctool/references/finance-example.md +0 -132
- package/skills/calctool/references/formula-dsl.md +0 -92
- package/skills/calctool/references/import-ocr.md +0 -72
- package/skills/calctool/templates/ecommerce-ops/README.md +0 -27
- package/skills/calctool/templates/ecommerce-ops/domain-reference.yaml +0 -172
- package/skills/swarm/SKILL.md +0 -120
- package/skills/swarm/install-meta.json +0 -7
- package/skills/swarm/references/ops-heartbeat.md +0 -45
- package/skills/swarm/references/org-chart.md +0 -50
- package/skills/swarm/references/security-guard.md +0 -56
- package/skills/swarm/references/task-lifecycle.md +0 -53
- package/skills/swarm/references/traffic-light.md +0 -52
- package/skills/swarm/skill.json +0 -10
- package/skills/swarm/swarm-runtime.mjs +0 -600
- package/sources.json +0 -25
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"engineId": "ecommerce-ops-dashboard",
|
|
3
|
-
"name": "电商运营仪表盘",
|
|
4
|
-
"semanticVersion": "1.0.0",
|
|
5
|
-
"category": "ecommerce",
|
|
6
|
-
"decimalPolicy": "decimal-string",
|
|
7
|
-
"fields": [
|
|
8
|
-
{
|
|
9
|
-
"key": "visitors",
|
|
10
|
-
"label": "访客数",
|
|
11
|
-
"type": "integer",
|
|
12
|
-
"unit": "人",
|
|
13
|
-
"required": true
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"key": "orders",
|
|
17
|
-
"label": "订单数",
|
|
18
|
-
"type": "integer",
|
|
19
|
-
"unit": "单",
|
|
20
|
-
"required": true
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"key": "gmv",
|
|
24
|
-
"label": "GMV",
|
|
25
|
-
"type": "money",
|
|
26
|
-
"unit": "CNY",
|
|
27
|
-
"required": true
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"key": "adSpend",
|
|
31
|
-
"label": "广告费",
|
|
32
|
-
"type": "money",
|
|
33
|
-
"unit": "CNY",
|
|
34
|
-
"required": true
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
"key": "customRate",
|
|
38
|
-
"label": "自定义转化率修正",
|
|
39
|
-
"type": "percent",
|
|
40
|
-
"unit": "%"
|
|
41
|
-
}
|
|
42
|
-
],
|
|
43
|
-
"formulas": [
|
|
44
|
-
{
|
|
45
|
-
"key": "conversionRate",
|
|
46
|
-
"label": "转化率",
|
|
47
|
-
"expression": {
|
|
48
|
-
"op": "safeDivide",
|
|
49
|
-
"args": [
|
|
50
|
-
{
|
|
51
|
-
"ref": "orders"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"ref": "visitors"
|
|
55
|
-
}
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
"key": "aov",
|
|
61
|
-
"label": "客单价",
|
|
62
|
-
"expression": {
|
|
63
|
-
"op": "safeDivide",
|
|
64
|
-
"args": [
|
|
65
|
-
{
|
|
66
|
-
"ref": "gmv"
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"ref": "orders"
|
|
70
|
-
}
|
|
71
|
-
]
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
"key": "roas",
|
|
76
|
-
"label": "ROAS",
|
|
77
|
-
"expression": {
|
|
78
|
-
"op": "safeDivide",
|
|
79
|
-
"args": [
|
|
80
|
-
{
|
|
81
|
-
"ref": "gmv"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
"ref": "adSpend"
|
|
85
|
-
}
|
|
86
|
-
]
|
|
87
|
-
}
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
"key": "gmvPerVisitor",
|
|
91
|
-
"label": "访客价值",
|
|
92
|
-
"expression": {
|
|
93
|
-
"op": "safeDivide",
|
|
94
|
-
"args": [
|
|
95
|
-
{
|
|
96
|
-
"ref": "gmv"
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
"ref": "visitors"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
],
|
|
105
|
-
"rules": [],
|
|
106
|
-
"views": [],
|
|
107
|
-
"testSuites": [
|
|
108
|
-
{
|
|
109
|
-
"name": "基准样例",
|
|
110
|
-
"inputs": {
|
|
111
|
-
"visitors": 10000,
|
|
112
|
-
"orders": 300,
|
|
113
|
-
"gmv": 50000,
|
|
114
|
-
"adSpend": 12000
|
|
115
|
-
},
|
|
116
|
-
"expect": {
|
|
117
|
-
"conversionRate": "3",
|
|
118
|
-
"aov": "166.6667",
|
|
119
|
-
"roas": "4.1667"
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
],
|
|
123
|
-
"pipeline": {
|
|
124
|
-
"engineId": "ecommerce-ops-dashboard",
|
|
125
|
-
"nodes": [
|
|
126
|
-
{
|
|
127
|
-
"id": "input",
|
|
128
|
-
"kind": "input",
|
|
129
|
-
"label": "录入/导入",
|
|
130
|
-
"inputs": [],
|
|
131
|
-
"outputs": [
|
|
132
|
-
"validate"
|
|
133
|
-
]
|
|
134
|
-
},
|
|
135
|
-
{
|
|
136
|
-
"id": "validate",
|
|
137
|
-
"kind": "validate",
|
|
138
|
-
"label": "数据校验",
|
|
139
|
-
"inputs": [
|
|
140
|
-
"input"
|
|
141
|
-
],
|
|
142
|
-
"outputs": [
|
|
143
|
-
"compute"
|
|
144
|
-
]
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
"id": "compute",
|
|
148
|
-
"kind": "compute",
|
|
149
|
-
"label": "确定性计算",
|
|
150
|
-
"inputs": [
|
|
151
|
-
"validate"
|
|
152
|
-
],
|
|
153
|
-
"outputs": [
|
|
154
|
-
"store",
|
|
155
|
-
"output"
|
|
156
|
-
]
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
"id": "store",
|
|
160
|
-
"kind": "store",
|
|
161
|
-
"label": "数据存储",
|
|
162
|
-
"inputs": [
|
|
163
|
-
"compute"
|
|
164
|
-
],
|
|
165
|
-
"outputs": [
|
|
166
|
-
"output"
|
|
167
|
-
]
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"id": "output",
|
|
171
|
-
"kind": "output",
|
|
172
|
-
"label": "指标卡/报告",
|
|
173
|
-
"inputs": [
|
|
174
|
-
"compute",
|
|
175
|
-
"store"
|
|
176
|
-
],
|
|
177
|
-
"outputs": []
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
"id": "automate",
|
|
181
|
-
"kind": "automate",
|
|
182
|
-
"label": "自动化(可选)",
|
|
183
|
-
"inputs": [
|
|
184
|
-
"store"
|
|
185
|
-
],
|
|
186
|
-
"outputs": [
|
|
187
|
-
"output"
|
|
188
|
-
],
|
|
189
|
-
"config": {
|
|
190
|
-
"enabled": false
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
]
|
|
194
|
-
}
|
|
195
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import ReactDOM from 'react-dom/client'
|
|
3
|
-
import { ConfigProvider } from 'antd'
|
|
4
|
-
import zhCN from 'antd/locale/zh_CN'
|
|
5
|
-
import App from './App'
|
|
6
|
-
|
|
7
|
-
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
8
|
-
<React.StrictMode>
|
|
9
|
-
<ConfigProvider locale={zhCN}>
|
|
10
|
-
<App />
|
|
11
|
-
</ConfigProvider>
|
|
12
|
-
</React.StrictMode>,
|
|
13
|
-
)
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// calctool 链路编排:整套工具 = 联通节点(非单页孤岛)
|
|
2
|
-
// 定义数据如何在节点间流动:输入 → 校验 → 计算 → 存储 → 输出 → 自动化
|
|
3
|
-
// 节点可增删改,链路随之更新 —— 后期改工具只动这里,不改页面
|
|
4
|
-
|
|
5
|
-
import type { FormulaNode } from './engine/evaluate'
|
|
6
|
-
|
|
7
|
-
export type PipelineNodeKind =
|
|
8
|
-
| 'input' // 数据输入(表单/导入)
|
|
9
|
-
| 'validate' // 校验(必填/类型/范围)
|
|
10
|
-
| 'compute' // 确定性计算(公式引擎)
|
|
11
|
-
| 'store' // 数据存储(持久化)
|
|
12
|
-
| 'output' // 输出(指标卡/报告/导出)
|
|
13
|
-
| 'automate' // 自动化(触发器/定时/通知)
|
|
14
|
-
|
|
15
|
-
export type PipelineNode = {
|
|
16
|
-
id: string
|
|
17
|
-
kind: PipelineNodeKind
|
|
18
|
-
label: string
|
|
19
|
-
inputs: string[] // 上游节点 id
|
|
20
|
-
outputs: string[] // 下游节点 id
|
|
21
|
-
config?: Record<string, unknown>
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export type Pipeline = {
|
|
25
|
-
engineId: string
|
|
26
|
-
nodes: PipelineNode[]
|
|
27
|
-
// 数据流:input -> validate -> compute -> store -> output (+ automate)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** 默认链路:整套工具的骨架(模块联通,非孤岛) */
|
|
31
|
-
export function defaultPipeline(engineId: string): Pipeline {
|
|
32
|
-
return {
|
|
33
|
-
engineId,
|
|
34
|
-
nodes: [
|
|
35
|
-
{ id: 'input', kind: 'input', label: '录入/导入', inputs: [], outputs: ['validate'] },
|
|
36
|
-
{ id: 'validate', kind: 'validate', label: '数据校验', inputs: ['input'], outputs: ['compute'] },
|
|
37
|
-
{ id: 'compute', kind: 'compute', label: '确定性计算', inputs: ['validate'], outputs: ['store', 'output'] },
|
|
38
|
-
{ id: 'store', kind: 'store', label: '数据存储', inputs: ['compute'], outputs: ['output'] },
|
|
39
|
-
{ id: 'output', kind: 'output', label: '指标卡/报告', inputs: ['compute', 'store'], outputs: [] },
|
|
40
|
-
{ id: 'automate', kind: 'automate', label: '自动化(可选)', inputs: ['store'], outputs: ['output'], config: { enabled: false } },
|
|
41
|
-
],
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export type FieldDef = {
|
|
46
|
-
key: string
|
|
47
|
-
label: string
|
|
48
|
-
type: 'number' | 'integer' | 'money' | 'percent' | 'text' | 'date' | 'enum'
|
|
49
|
-
unit?: string
|
|
50
|
-
required?: boolean
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export type FormulaDef = {
|
|
54
|
-
key: string
|
|
55
|
-
label: string
|
|
56
|
-
expression: FormulaNode
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export type EngineDefinition = {
|
|
60
|
-
engineId: string
|
|
61
|
-
name: string
|
|
62
|
-
semanticVersion: string
|
|
63
|
-
category: string
|
|
64
|
-
decimalPolicy: string
|
|
65
|
-
fields: FieldDef[]
|
|
66
|
-
formulas: FormulaDef[]
|
|
67
|
-
rules: unknown[]
|
|
68
|
-
pipeline: Pipeline
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** 在链路中找节点的上下游(改工具时定位影响范围) */
|
|
72
|
-
export function nodeNeighbors(pipeline: Pipeline, nodeId: string) {
|
|
73
|
-
const node = pipeline.nodes.find((n) => n.id === nodeId)
|
|
74
|
-
if (!node) return null
|
|
75
|
-
return {
|
|
76
|
-
node,
|
|
77
|
-
upstream: pipeline.nodes.filter((n) => node.inputs.includes(n.id)),
|
|
78
|
-
downstream: pipeline.nodes.filter((n) => n.inputs.includes(nodeId)),
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// calctool 存储层:数据持久化
|
|
2
|
-
// 默认 localStorage(零依赖,任何环境可用);Node 全功能模式可换 better-sqlite3
|
|
3
|
-
export type ToolRecord = {
|
|
4
|
-
id: string
|
|
5
|
-
engineId: string
|
|
6
|
-
inputs: Record<string, string | number>
|
|
7
|
-
results: Record<string, string>
|
|
8
|
-
createdAt: string
|
|
9
|
-
updatedAt: string
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const KEY_PREFIX = 'calctool:record:'
|
|
13
|
-
|
|
14
|
-
export class ToolStore {
|
|
15
|
-
constructor(private readonly engineId: string) {}
|
|
16
|
-
|
|
17
|
-
list(): ToolRecord[] {
|
|
18
|
-
if (typeof localStorage === 'undefined') return []
|
|
19
|
-
const records: ToolRecord[] = []
|
|
20
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
21
|
-
const key = localStorage.key(i)
|
|
22
|
-
if (key?.startsWith(`${KEY_PREFIX}${this.engineId}:`)) {
|
|
23
|
-
try {
|
|
24
|
-
records.push(JSON.parse(localStorage.getItem(key) ?? 'null'))
|
|
25
|
-
} catch { /* 跳过损坏记录 */ }
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
save(inputs: Record<string, string | number>, results: Record<string, string>): ToolRecord {
|
|
32
|
-
const now = new Date().toISOString()
|
|
33
|
-
const record: ToolRecord = {
|
|
34
|
-
id: `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
|
|
35
|
-
engineId: this.engineId,
|
|
36
|
-
inputs, results, createdAt: now, updatedAt: now,
|
|
37
|
-
}
|
|
38
|
-
if (typeof localStorage !== 'undefined') {
|
|
39
|
-
localStorage.setItem(`${KEY_PREFIX}${this.engineId}:${record.id}`, JSON.stringify(record))
|
|
40
|
-
}
|
|
41
|
-
return record
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
clear(): void {
|
|
45
|
-
if (typeof localStorage === 'undefined') return
|
|
46
|
-
const keys: string[] = []
|
|
47
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
48
|
-
const key = localStorage.key(i)
|
|
49
|
-
if (key?.startsWith(`${KEY_PREFIX}${this.engineId}:`)) keys.push(key)
|
|
50
|
-
}
|
|
51
|
-
keys.forEach((k) => localStorage.removeItem(k))
|
|
52
|
-
}
|
|
53
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "ESNext",
|
|
5
|
-
"moduleResolution": "bundler",
|
|
6
|
-
"jsx": "react-jsx",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
"resolveJsonModule": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"noEmit": true,
|
|
12
|
-
"types": ["vite/client"]
|
|
13
|
-
},
|
|
14
|
-
"include": ["src"]
|
|
15
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
# 声明式页面规格系统
|
|
2
|
-
|
|
3
|
-
把"信息型页面"从代码降级为**数据声明**,用通用渲染器渲染几十个页面,避免复制粘贴页面结构。这是生成工具页面的核心机制。
|
|
4
|
-
|
|
5
|
-
## 1. 规格 Schema
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
interface ApplicationPageSpec {
|
|
9
|
-
title: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
tabs?: TabSpec[];
|
|
12
|
-
actions?: ActionSpec[]; // 页头操作(default|primary|danger)
|
|
13
|
-
sections?: SectionSpec[]; // 内容分区
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface SectionSpec {
|
|
17
|
-
layout: 'rows' | 'grid' | 'table' | 'steps';
|
|
18
|
-
rows?: RowSpec[]; // 标签/值/说明/状态/行内操作
|
|
19
|
-
metrics?: MetricSpec[]; // 指标卡
|
|
20
|
-
columns?: ColumnSpec[];
|
|
21
|
-
data?: (string | number)[][]; // 表格数据
|
|
22
|
-
empty?: EmptyStateSpec; // 空状态(标题/说明/操作)
|
|
23
|
-
}
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## 2. 注册与路由匹配
|
|
27
|
-
|
|
28
|
-
- 规格文件按域拆分(core/settings/management/finance/studio/supplementary),每份是 `Record<string, ApplicationPageSpec>` + 路由映射
|
|
29
|
-
- 支持参数化路由:`/tools/:toolId/runs/:runId`、`/automations/:automationId/edit`
|
|
30
|
-
- 匹配算法:按路径段数**从长到短**排序 → 逐段精确匹配(`:` 前缀为参数位)→ 命中后提取 params → `encodeURIComponent` 回填规格内 `href`
|
|
31
|
-
|
|
32
|
-
## 3. 渲染器
|
|
33
|
-
|
|
34
|
-
`ApplicationPageSpec → 通用构建块组件树`:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
PageShell(内容 768px)
|
|
38
|
-
→ PageHeader(标题/说明/操作)
|
|
39
|
-
→ SectionCard × N(分区)
|
|
40
|
-
→ 按 layout 分发:
|
|
41
|
-
rows → SettingRow 行
|
|
42
|
-
grid → 网格卡
|
|
43
|
-
table → 表格
|
|
44
|
-
steps → 步骤条
|
|
45
|
-
empty → EmptyState
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
- 无 `href` 的操作自动 `disabled`——保证"未接入"按钮不产生假交互
|
|
49
|
-
- 所有构建块来自共享组件(PageShell/PageHeader/SectionCard/SettingRow/EmptyState/StatGrid/PageList/Toolbar),页面只提供数据
|
|
50
|
-
- 单文件 ≤ 1000 行(审计脚本强制),接近上限必须拆分
|
|
51
|
-
|
|
52
|
-
## 4. 生成工具时的页面映射
|
|
53
|
-
|
|
54
|
-
| 工具模块 | 页面规格 |
|
|
55
|
-
|---|---|
|
|
56
|
-
| 录入表单 | 字段目录 → 自动生成 rows/grid 表单(含必填/类型/单位) |
|
|
57
|
-
| 指标卡 | 公式结果 → metrics 数组(StatGrid) |
|
|
58
|
-
| 专题工具 | 每个专题 → 独立 SectionCard(增值税/盈亏平衡/定价/利润率优化) |
|
|
59
|
-
| 历史记录 | table 布局 + 分页 |
|
|
60
|
-
| 诊断报告 | 指标卡 + 表格 + 诊断结论 + 建议 |
|
|
61
|
-
| 空状态 | 无数据时 EmptyState(不虚构装饰图标) |
|
|
62
|
-
|
|
63
|
-
## 5. 硬约束(从工具项目继承)
|
|
64
|
-
|
|
65
|
-
- 正文内容容器统一 768px(与 Composer 同宽),窄屏等比收窄,禁止按页面类型自由设宽
|
|
66
|
-
- 禁内联 style、禁硬编码颜色、禁阴影
|
|
67
|
-
- 图标统一 Lucide、14px、描边 2
|
|
68
|
-
- 空页面不显示装饰图标,不虚构状态/数据/提示/按钮
|
|
69
|
-
- 能拆成组件的内容禁止堆积在页面文件中
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
# 引擎元模型(Engine Meta-Model)
|
|
2
|
-
|
|
3
|
-
一个可发布、可运行、可验收的"计算工具"= 一份**引擎定义**。本文件规定引擎定义的结构与约束。
|
|
4
|
-
|
|
5
|
-
## 1. 顶级对象
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
interface EngineDefinition {
|
|
9
|
-
id: string; // kebab-case 稳定机器标识
|
|
10
|
-
name: string; // 中文显示名,可改
|
|
11
|
-
semanticVersion: string; // 语义版本,发布后不可原地修改
|
|
12
|
-
status: 'draft' | 'review' | 'published' | 'retired';
|
|
13
|
-
compatibilityProfile?: string; // 如 legacy-compatible(复现旧口径)
|
|
14
|
-
decimalPolicy: 'decimal-string' | 'source-compatible-float';
|
|
15
|
-
inputSchema: JsonSchema; // 输入校验
|
|
16
|
-
fields: FieldDefinition[]; // 字段目录
|
|
17
|
-
tables: TableDefinition[]; // 表格定义(如成本结构表)
|
|
18
|
-
dimensions: DimensionDefinition[]; // 维度(公司/部门/周期)
|
|
19
|
-
entities: EntitySchemaDefinition[]; // 实体
|
|
20
|
-
relations: RelationDefinition[]; // 关系
|
|
21
|
-
choiceSources: ChoiceSourceDefinition[];
|
|
22
|
-
interactionRules: InteractionRuleDefinition[];
|
|
23
|
-
formulas: FormulaDefinition[]; // 公式图
|
|
24
|
-
rules: RuleDefinition[]; // 规则包(阈值/评分/分级)
|
|
25
|
-
views: ViewDefinition[]; // 视图
|
|
26
|
-
documents: MarkdownDocumentDefinition[]; // Markdown 说明/报告
|
|
27
|
-
approvalPolicyRefs: string[];
|
|
28
|
-
importProfiles: ImportProfile[]; // 导入映射
|
|
29
|
-
reports: ReportDefinition[]; // 报告模板
|
|
30
|
-
outputs: OutputContract[]; // 输出契约(跨引擎引用用)
|
|
31
|
-
permissions: EnginePermissionPolicy;
|
|
32
|
-
testSuites: EngineTestSuite[]; // 确定性测试
|
|
33
|
-
migrationFrom?: EngineMigration[];
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**铁律**:
|
|
38
|
-
- `id` 与字段 `key` 是稳定机器标识;中文标签可以改,ID 不改
|
|
39
|
-
- 所有引用用 ID,不用页面标题或表格坐标作主键
|
|
40
|
-
- 发布版本不可原地修改;运行记录绑定精确的 `engineVersionId`
|
|
41
|
-
- 跨引擎只允许引用对方声明的输出契约
|
|
42
|
-
|
|
43
|
-
## 2. 字段类型
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
number, money, percent, integer, text, richText, boolean,
|
|
47
|
-
date, dateTime, enum, singleSelect, multiSelect, dimensionRef,
|
|
48
|
-
entityRef, file, image, object, repeatGroup, table, reference, derived
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
每个数值字段至少含:
|
|
52
|
-
- `key`(稳定 ID)、`label`(中文标签)、`type`
|
|
53
|
-
- `required` / `defaultValue`
|
|
54
|
-
- `precision` / `rounding`(金额、比例、整数分别定义)
|
|
55
|
-
- `unit`(如 CNY、CNY/person、%)
|
|
56
|
-
- 枚举字段含 `choiceSourceRef`
|
|
57
|
-
|
|
58
|
-
## 3. 公式定义
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
interface FormulaDefinition {
|
|
62
|
-
key: string;
|
|
63
|
-
label: string;
|
|
64
|
-
type: 'derived' | 'score' | 'aggregate' | 'lookup';
|
|
65
|
-
expression: FormulaAst; // 编译后的 AST(见 formula-dsl.md)
|
|
66
|
-
source?: string; // 可读字符串(仅编辑用,保存必须 AST)
|
|
67
|
-
outputUnit?: string;
|
|
68
|
-
description?: string;
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## 4. 规则包(Rule Pack)
|
|
73
|
-
|
|
74
|
-
```ts
|
|
75
|
-
interface RuleDefinition {
|
|
76
|
-
id: string;
|
|
77
|
-
name: string;
|
|
78
|
-
kind: 'threshold' | 'scoring' | 'grading' | 'validation';
|
|
79
|
-
// 阈值:区间 → 级别
|
|
80
|
-
// 评分:指标值 → 0-100 分(可曲线/分段)
|
|
81
|
-
// 分级:总分 → 健康等级(如 优/良/中/差)
|
|
82
|
-
inputs: string[]; // 引用字段/公式 key
|
|
83
|
-
evaluation: RuleAst; // 条件 AST
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## 5. 导入 Profile
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
interface ImportProfile {
|
|
91
|
-
id: string;
|
|
92
|
-
kind: 'excel' | 'ocr' | 'manual';
|
|
93
|
-
sourceFormat: string; // Excel 列 / OCR 字段布局
|
|
94
|
-
mapping: { source: string; targetField: string; transform?: string }[];
|
|
95
|
-
verification: 'draft' | 'auto'; // 自动导入先进草稿
|
|
96
|
-
}
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## 6. 报告模板
|
|
100
|
-
|
|
101
|
-
```ts
|
|
102
|
-
interface ReportDefinition {
|
|
103
|
-
id: string;
|
|
104
|
-
name: string;
|
|
105
|
-
sections: ReportSection[];
|
|
106
|
-
// 指标卡 / 表格 / 诊断结论 / 历史分位 / 建议
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## 7. 版本与迁移
|
|
111
|
-
|
|
112
|
-
- `1.x legacy-compatible`:复现原工具结果(保留旧公式、边界、取整)
|
|
113
|
-
- `2.x corrected`:修正数据质量问题(通过显式迁移发布,绝不静默改变旧运行)
|
|
114
|
-
- 任何公式/字段/阈值/导入映射/报告变化 → 新版本
|
|
115
|
-
|
|
116
|
-
## 8. 引擎状态机(能力接入)
|
|
117
|
-
|
|
118
|
-
```text
|
|
119
|
-
planned → not_installed → disconnected → configuring
|
|
120
|
-
→ pending_verification → connected → disabled | unavailable
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
健康状态 `healthy/degraded/failed/unknown` **只在真实连接与探针后出现**;客户端不能提交健康状态。
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# 范例:经营健康诊断引擎(finance-health-diagnosis)
|
|
2
|
-
|
|
3
|
-
完整走通「50 输入字段 → 归类 → 利润 → 十大指标评分 → 健康度 → 报告」的引擎定义范例。这是 calctool 的 reference implementation:任何新工具都可对照此结构生成。
|
|
4
|
-
|
|
5
|
-
## 1. 引擎身份
|
|
6
|
-
|
|
7
|
-
```yaml
|
|
8
|
-
engineId: finance-health-diagnosis
|
|
9
|
-
name: 经营健康诊断
|
|
10
|
-
category: finance
|
|
11
|
-
ownerType: platform-template
|
|
12
|
-
status: published
|
|
13
|
-
semanticVersion: 1.0.0
|
|
14
|
-
compatibilityProfile: legacy-compatible
|
|
15
|
-
decimalPolicy: decimal-string
|
|
16
|
-
defaultCurrency: CNY
|
|
17
|
-
defaultLocale: zh-CN
|
|
18
|
-
schemaVersion: engine-spec/1
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
版本族:`1.x legacy-compatible`(复现原工具);`2.x corrected`(修正财务口径,显式迁移发布)。
|
|
22
|
-
|
|
23
|
-
## 2. 六层计算链路
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
输入层:利润表 50 个基础字段(货品成本、账单/订单/流量费用、薪酬、仓储…)
|
|
27
|
-
→ 归类层:商品成本 / 账单费用 / 订单费用 / 流量费用 / 薪酬 / 仓储费用
|
|
28
|
-
→ 利润层:GSV / 运营毛利 GP_oper / 管理费用 / 税前净利润 NP / 占比
|
|
29
|
-
→ 诊断层:十大指标 / 动态阈值 / 单项得分 / 健康等级 / 加权健康度
|
|
30
|
-
→ 专题层:增值税 / 盈亏平衡 / 私域复购 / 单品定价 / 利润率优化
|
|
31
|
-
→ 展示层:历史分位 / 诊断重点 / HTML 报告 / 历史记录 / OGSM 执行方案
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## 3. 十大指标权重(默认)
|
|
35
|
-
|
|
36
|
-
| 指标 | 权重 |
|
|
37
|
-
|---|---:|
|
|
38
|
-
| 定价倍数 | 30% |
|
|
39
|
-
| GSV | 17% |
|
|
40
|
-
| 薪酬效率 | 15% |
|
|
41
|
-
| GSV 人效 | 5% |
|
|
42
|
-
| 毛利人效 | 5% |
|
|
43
|
-
| 净利人效 | 5% |
|
|
44
|
-
| 增值税率 | 10% |
|
|
45
|
-
| 人均办公费用 | 3% |
|
|
46
|
-
| 仓储费用占比 | 5% |
|
|
47
|
-
| 单件发货成本 | 5% |
|
|
48
|
-
|
|
49
|
-
## 4. 通用评分曲线(0-100)
|
|
50
|
-
|
|
51
|
-
高值更优:
|
|
52
|
-
```text
|
|
53
|
-
S_high(A;P,E) = clamp(60 + 30 × (A-P)/(E-P), 0, 100)
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
低值更优(E < P,斜率自然为负):
|
|
57
|
-
```text
|
|
58
|
-
S_low(A;P,E) = clamp(60 + 30 × (A-P)/(E-P), 0, 100)
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
带盈亏点的分段函数(定价倍数、GSV):
|
|
62
|
-
```text
|
|
63
|
-
若 A < B: S_break = clamp(round(30 + 30 × (A-B)/(P-B)), 0, 100)
|
|
64
|
-
否则: S_break = clamp(round(60 + 30 × (A-P)/(E-P)), 0, 100)
|
|
65
|
-
```
|
|
66
|
-
(B=盈亏平衡,P=合格,E=优秀)
|
|
67
|
-
|
|
68
|
-
## 5. 分数等级
|
|
69
|
-
|
|
70
|
-
| 分数 | 等级 |
|
|
71
|
-
|---:|---|
|
|
72
|
-
| 非有限/空 | 需要优化成本结构而非数值 |
|
|
73
|
-
| <60 | 危险 |
|
|
74
|
-
| 60-<70 | 合格 |
|
|
75
|
-
| 70-<80 | 良好 |
|
|
76
|
-
| 80-<90 | 优秀 |
|
|
77
|
-
| >=90 | 卓越 |
|
|
78
|
-
|
|
79
|
-
## 6. 指标定义(当前值公式 + 目标 + 样例)
|
|
80
|
-
|
|
81
|
-
| 指标 | 公式 | 合格/良好/优秀 | 样例分 |
|
|
82
|
-
|---|---|---|---|
|
|
83
|
-
| 定价倍数 | `S / 货品成本` | 动态阈值 | 63 |
|
|
84
|
-
| GSV | `S` | 动态 | 63 |
|
|
85
|
-
| 薪酬效率 | `GP_oper / 薪酬福利` | 2.0 / 2.5 / 3.0 | 71 |
|
|
86
|
-
| GSV 人效 | `S / 正式员工数` | 100k / 120k / 150k | 60 |
|
|
87
|
-
| 毛利人效 | `GP_oper / 正式员工数` | 17k / 20.4k / 25.5k | 61 |
|
|
88
|
-
| 净利人效 | `NP / 正式员工数` | 5k / 6k / 7.5k | 64 |
|
|
89
|
-
| 增值税率 | `C_tax / S` | 综合税率×1.0/0.9/0.8 | 38.4 |
|
|
90
|
-
| 人均办公费用 | `办公费用 / 正式员工数` | 1,600 / 1,200 / 800 | 63.75 |
|
|
91
|
-
| 仓储费用占比 | `仓储费用 / S` | 4.0% / 3.5% / 3.0% | 63 |
|
|
92
|
-
| 单件发货成本 | `仓储费用 / 真实发货单量` | 1.80 / 1.60 / 1.40 | 76.5 |
|
|
93
|
-
|
|
94
|
-
动态定价倍数阈值:
|
|
95
|
-
```text
|
|
96
|
-
c = 货品成本 / S
|
|
97
|
-
n = 当前税前净利率
|
|
98
|
-
盈亏倍数 B = 1 / (c + n)
|
|
99
|
-
合格倍数 P = 1 / (c + n - 5%)
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 7. 总健康分
|
|
103
|
-
|
|
104
|
-
- 加权:`总分 = Σ(指标分 × 权重)`,保留 2 位小数
|
|
105
|
-
- 样例:62.2362(健康)
|
|
106
|
-
- 历史百分位:程序按当前版本重算每条历史记录的十大指标,与全站用户样本比较
|
|
107
|
-
|
|
108
|
-
## 8. 引擎定义产物(calctool 生成模板)
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
finance-health-diagnosis/
|
|
112
|
-
├── manifest.yaml # 引擎身份(见 §1)
|
|
113
|
-
├── field-catalog.json # 50 个输入字段 + 10 个派生指标
|
|
114
|
-
├── scope-dimensions.json # 公司 / 周期 维度
|
|
115
|
-
├── formula-graph.json # 六层公式图(§2)
|
|
116
|
-
├── rule-packs.json # 权重 + 评分曲线 + 等级(§3-5)
|
|
117
|
-
├── import-profiles.json # Excel 单元格映射 + OCR 字段映射
|
|
118
|
-
├── report-template.json # 指标卡 + 表格 + 诊断结论 + 建议
|
|
119
|
-
└── tests/ # 样例复算(健康分 62.2362 等)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## 9. 导入映射要点
|
|
123
|
-
|
|
124
|
-
- 原工具为 Excel 导入:F 列单元格映射到字段目录,配置表覆盖顺序以算法主文档为准
|
|
125
|
-
- 原生表格确定性解析,不做 OCR;截图/扫描件走 OCR + 人工草稿确认
|
|
126
|
-
- 所有自动导入先进入草稿,人工确认后才写正式数据
|
|
127
|
-
|
|
128
|
-
## 10. 生产注意事项
|
|
129
|
-
|
|
130
|
-
- 增值税模块属于经营估算模型,生产使用前必须由持证财税人员复核
|
|
131
|
-
- 本引擎复现的是当前产品口径,不代表会计准则、税法意见或税务筹划建议
|
|
132
|
-
- 模型(Hermes/MiMo/OCR)只生成候选、草稿和解释,不能替代已发布确定性引擎给出正式财务数字
|