ygl-trees 0.68.0 → 0.70.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.70.0(2026-10-17)`agent metrics`——从 R11 手动测量到自动化指标
4
+ - **`ygl-trees agent metrics`**:一条命令输出工作台全量量化指标——冷启动(brief 耗时/next actions/可用技能)、知识(总量/7日增长/增长率)、研究(来源/证据/断言/验证率/证据密度)、技能(总数/命中/均命中)、科技树(棵数/节点/解锁率)、活动(7 日 events)
5
+ - **来源**:R11 冷启动量化研究的手动测量 → 自动化——从 `time agent brief` + 手动 grep 统计变为一键输出
6
+ - 135 单测全绿
7
+
8
+ ## 0.69.0(2026-10-17)MCP Server——R8 研究设计的工程落地
9
+ - **`ygl-trees mcp`**:启动 stdio MCP 服务器(JSON-RPC 2.0),Claude Desktop / Cursor / VS Code 等 IDE Agent 可直接连接
10
+ - **8 工具面**(三支柱理论驱动):agent_brief · agent_match · kb_search · claim_evaluate · tree_state · produce_report · doctor · task_advance
11
+ - **每个工具继承 CLI 冻结契约**(幂等写入、JSON 纯净、snake_case)——Agent 调用工具不需要解析命令行
12
+ - **实现**:`packages/ops/tools/src/mcp.ts`——readline stdio + JSON-RPC 路由 + `cliJson()` 子进程调用(`process.argv[1]` 自引用,bundle/源码双兼容)
13
+ - 实测:initialize ✓ · tools/list(8) ✓ · agent_brief(project) ✓ · kb_search(CJK 命中) ✓ · doctor(9 项) ✓
14
+
3
15
  ## 0.68.0(2026-10-17)锁设计修复——serve/CLI 共存 + PID 活锁检测 + JSON 纯净 + v9 时间纪律
4
16
  - **F1(P0):webui serve 不再持排他锁**——原实现进程级锁让 serve 生命周期内挡掉一切 CLI 命令;现 serve 跳过锁(`YGL_SERVE=1` 旁路),SQLite WAL 天然支持并发读 + 序列化写;CLI 短命令仍锁(单写者保护写窗口)
5
17
  - **P1(用户反馈):PID 活锁检测替代 15 分钟 mtime**——Windows 上 `process.on("exit")` 的 rmSync 句柄未释放时静默失败→锁残留→下进程撞白锁;现用 `process.kill(pid, 0)` 探测持有者是否存活(EPERM=活/ESRCH=死),死 PID **立即清锁**(不看 mtime),活 PID **如实报告**(不误报 stale)
@@ -116,132 +116,132 @@ function appVersion() {
116
116
  }
117
117
  // ── Usage text ──
118
118
  // (kept in apps/cli because it's presentation, not domain logic)
119
- const USAGE = `
120
- ${(0, fmt_1.paint)(fmt_1.C.bold, "ygl-trees", true)} 猿光 · 科技树
121
- ${(0, fmt_1.paint)(fmt_1.C.dim, "database-centric CLI: research → production → knowledge reuse", true)}
122
-
123
- ygl-trees <group> <action> [args] [options] add --json for machine output
124
-
125
- ${(0, fmt_1.paint)(fmt_1.C.bold, "config", true)} user-tunable settings (registry defaults + overrides)
126
- list all keys: value + default + note
127
- get <key> resolved value (config table > default)
128
- set <key> <value> validated against registry (type/range); events logged
129
- reset <key> drop override → back to default
130
-
131
- ${(0, fmt_1.paint)(fmt_1.C.bold, "db", true)}
132
- init create the workspace + schema
133
- stats row counts per table
134
- path print the database file path
135
- export <file.sql> [--lean] dump ALL data tables (+ summary); --lean skips derived
136
- sync pg <url> one-way full mirror to PostgreSQL (L1, see docs/pg-compat.md)
137
- migrate pg <url> [--fresh] one-time full-fidelity graduation (constraints + data, atomic)
138
- dups list duplicate-content rows
139
- reset delete the database (asks nothing, be careful)
140
- sql "<sql>" ad-hoc statement (can mutate — power tool, no guardrails)
141
-
142
- ${(0, fmt_1.paint)(fmt_1.C.bold, "skill", true)} L1 description / L2 body / L3 references
143
- import <file.md> import a SKILL.md (frontmatter = L1, body = L2)
144
- add --name --description --body [-f file.md]
145
- list | show <name> | rm <name> | enable <name> | disable <name>
146
- match "<query>" full-text match, prints L1 candidates for an agent
147
- refs add <skill> <path> --body ...
148
-
149
- ${(0, fmt_1.paint)(fmt_1.C.bold, "project", true)}
150
- new <name> -q "<question>" create + select
151
- list | use <name> | show
152
-
153
- ${(0, fmt_1.paint)(fmt_1.C.bold, "research", true)} collect → screen → extract → claim
154
- query add "<text>" register a search query
155
- query attach <qid> <sid> link source to query (recalled count)
156
- query list
157
- source add --title --url [--abstract --content --relevance --confidence --query]
158
- source fetch <url> fetch page, extract title/meta/text (zero side-effect on failure)
159
- source list | search "<q>" | show <id> | rm <id>
160
- evidence add <sourceId> --quote "..." [--note --locator]
161
- evidence list
162
- claim add "<text>" [--confidence A|B|C]
163
- claim link <claimId> <evidenceId> [--stance supports|refutes]
164
- claim resolve <claimId> --as supported|refuted|contested [--note]
165
- claim list
166
-
167
- ${(0, fmt_1.paint)(fmt_1.C.bold, "produce", true)} outline → section → report · spec/design(工程产出)
168
- outline auto-outline from claims
169
- section <title> --body|-f add a section artifact
170
- report assemble claims+evidence+sections into a report
171
- spec <title> --body|-f requirements spec artifact (R12)
172
- design <title> --body|-f design artifact (R12) --design-type ui-ux|arch|decision
173
- list | show <id> | export <id> <file>
174
-
175
- ${(0, fmt_1.paint)(fmt_1.C.bold, "task", true)} 任务清单(todo|doing|done 状态机,R12)
176
- add "<title>" [--note ...] create a task (status todo)
177
- list [--status todo|doing|done]
178
- doing|done <id> move along the state machine(勾销全程留痕)
179
-
180
- ${(0, fmt_1.paint)(fmt_1.C.bold, "kb", true)} long-term knowledge
181
- add --title --body|-f [--tags --confidence]
182
- import <dir|file.md> batch markdown (frontmatter, idempotent, single tx)
183
- search "<q>" | list | show <id>
184
- link <a> <b> [--rel]
185
- ingest <artifactId> import a finished artifact
186
- promote <noteId> [--name] turn a note into a reusable skill
187
-
188
- ${(0, fmt_1.paint)(fmt_1.C.bold, "job", true)} batch + schedule (drive with cron: job tick)
189
- add <title> -- <command> [--every <min>] [--at "YYYY-MM-DD HH:MM"]
190
- list | run <id> | tick | enable <id> | disable <id> | logs
191
-
192
- ${(0, fmt_1.paint)(fmt_1.C.bold, "tree / node", true)} tech-tree node model
193
- tree new <name> [--project p] create a tree (nodes live in it)
194
- tree list | tree use <name>
195
-
196
- node add <key> [--name --kind --tier --cost --tags --payload]
197
- node link <parent> <child> [--rel prereq|unlock|excludes|enables]
198
- [--mode AND|OR|XOR|NOT] [--optional]
199
- [--min-level n] [--weight n]
200
- node unlink <parent> <child> [--rel prereq]
201
- node cond <key> --name <c> [--kind flag|resource|level|quest|time|expr]
202
- [--op >=|==|<=|!=|has] [--value v] [--optional]
203
- [--op eval --value "<布尔问题>"]
204
- [--op eval-choice --value "<问题>" --options "k=desc,..." --answer k]
205
- [--op eval-score --value "<问题>" --levels "级0,..." --min-score n]
206
- [--effect gate|cost_mul] [--weight n]
207
- node index rebuild closure + topo order
208
- node can <key> [--state k=v] evaluate required vs optional gates
209
- (--eval: eval 题型经决策模型判定;
210
- boolean P / choice P(期望答案) / score ±1 灰带)
211
- node ready [--state k=v] [--eval] currently unlockable set
212
- node path <key> dependency-order path to target (all locked ancestors; OR branches not optimized)
213
- node parents|children <key> direct relations
214
- node ancestors|descendants <key> transitive, via closure index
215
- node list | show <key> | search "<q>" | unlock|lock <key>
216
- node validate cycles, dangling edges, dirty index
217
- node export [--out file.json] portable JSON
218
- node import --file <file.json> [--tree name] [--merge] — strict, transactional
219
-
220
- Writes are idempotent (claim/evidence/query/kb/job dedupe by content
221
- hash); pass --force to keep a deliberate duplicate.
222
-
223
- ${(0, fmt_1.paint)(fmt_1.C.bold, "webui", true)} dashboard (zero-dependency)
224
- export [--out <file>] single-file dashboard.html (open in browser)
225
- serve [--port N] live dashboard at http://127.0.0.1:N/ (Ctrl+C to stop)
226
-
227
- ${(0, fmt_1.paint)(fmt_1.C.bold, "rel", true)} 关联织物(spec R9:任意两类实体互相挂接)
228
- add <src> <dst> [--rel t] link two refs: node:key claim:id kb:id artifact:id
229
- skill:name evidence:id source:id query:id
230
- rm <src> <dst> [--rel t] unlink
231
- list [--src r] [--dst r] browse (either side filter, resolves displays)
232
-
233
- ${(0, fmt_1.paint)(fmt_1.C.bold, "plugin", true)} 用户层插件分发(spec R14 L3,业务域扩展位)
234
- init create $YGL_HOME/plugins profile
235
- install <spec> npm package / git url / local dir (auto link:)
236
- remove <name> | list manage the user layer ($YGL_HOME/ygl.user.bundle.json)
237
- 插件契约:export apply(ctx,config) + 可选 commands 贡献 CLI 命令组
238
-
239
- ${(0, fmt_1.paint)(fmt_1.C.bold, "agent", true)} agent-facing views
240
- brief current project state + next actions (start here)
241
- match "<task>" which skill should handle this task
242
- log recent events
243
-
244
- Global: --json --no-color --db <file> --home <dir>
119
+ const USAGE = `
120
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "ygl-trees", true)} 猿光 · 科技树
121
+ ${(0, fmt_1.paint)(fmt_1.C.dim, "database-centric CLI: research → production → knowledge reuse", true)}
122
+
123
+ ygl-trees <group> <action> [args] [options] add --json for machine output
124
+
125
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "config", true)} user-tunable settings (registry defaults + overrides)
126
+ list all keys: value + default + note
127
+ get <key> resolved value (config table > default)
128
+ set <key> <value> validated against registry (type/range); events logged
129
+ reset <key> drop override → back to default
130
+
131
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "db", true)}
132
+ init create the workspace + schema
133
+ stats row counts per table
134
+ path print the database file path
135
+ export <file.sql> [--lean] dump ALL data tables (+ summary); --lean skips derived
136
+ sync pg <url> one-way full mirror to PostgreSQL (L1, see docs/pg-compat.md)
137
+ migrate pg <url> [--fresh] one-time full-fidelity graduation (constraints + data, atomic)
138
+ dups list duplicate-content rows
139
+ reset delete the database (asks nothing, be careful)
140
+ sql "<sql>" ad-hoc statement (can mutate — power tool, no guardrails)
141
+
142
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "skill", true)} L1 description / L2 body / L3 references
143
+ import <file.md> import a SKILL.md (frontmatter = L1, body = L2)
144
+ add --name --description --body [-f file.md]
145
+ list | show <name> | rm <name> | enable <name> | disable <name>
146
+ match "<query>" full-text match, prints L1 candidates for an agent
147
+ refs add <skill> <path> --body ...
148
+
149
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "project", true)}
150
+ new <name> -q "<question>" create + select
151
+ list | use <name> | show
152
+
153
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "research", true)} collect → screen → extract → claim
154
+ query add "<text>" register a search query
155
+ query attach <qid> <sid> link source to query (recalled count)
156
+ query list
157
+ source add --title --url [--abstract --content --relevance --confidence --query]
158
+ source fetch <url> fetch page, extract title/meta/text (zero side-effect on failure)
159
+ source list | search "<q>" | show <id> | rm <id>
160
+ evidence add <sourceId> --quote "..." [--note --locator]
161
+ evidence list
162
+ claim add "<text>" [--confidence A|B|C]
163
+ claim link <claimId> <evidenceId> [--stance supports|refutes]
164
+ claim resolve <claimId> --as supported|refuted|contested [--note]
165
+ claim list
166
+
167
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "produce", true)} outline → section → report · spec/design(工程产出)
168
+ outline auto-outline from claims
169
+ section <title> --body|-f add a section artifact
170
+ report assemble claims+evidence+sections into a report
171
+ spec <title> --body|-f requirements spec artifact (R12)
172
+ design <title> --body|-f design artifact (R12) --design-type ui-ux|arch|decision
173
+ list | show <id> | export <id> <file>
174
+
175
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "task", true)} 任务清单(todo|doing|done 状态机,R12)
176
+ add "<title>" [--note ...] create a task (status todo)
177
+ list [--status todo|doing|done]
178
+ doing|done <id> move along the state machine(勾销全程留痕)
179
+
180
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "kb", true)} long-term knowledge
181
+ add --title --body|-f [--tags --confidence]
182
+ import <dir|file.md> batch markdown (frontmatter, idempotent, single tx)
183
+ search "<q>" | list | show <id>
184
+ link <a> <b> [--rel]
185
+ ingest <artifactId> import a finished artifact
186
+ promote <noteId> [--name] turn a note into a reusable skill
187
+
188
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "job", true)} batch + schedule (drive with cron: job tick)
189
+ add <title> -- <command> [--every <min>] [--at "YYYY-MM-DD HH:MM"]
190
+ list | run <id> | tick | enable <id> | disable <id> | logs
191
+
192
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "tree / node", true)} tech-tree node model
193
+ tree new <name> [--project p] create a tree (nodes live in it)
194
+ tree list | tree use <name>
195
+
196
+ node add <key> [--name --kind --tier --cost --tags --payload]
197
+ node link <parent> <child> [--rel prereq|unlock|excludes|enables]
198
+ [--mode AND|OR|XOR|NOT] [--optional]
199
+ [--min-level n] [--weight n]
200
+ node unlink <parent> <child> [--rel prereq]
201
+ node cond <key> --name <c> [--kind flag|resource|level|quest|time|expr]
202
+ [--op >=|==|<=|!=|has] [--value v] [--optional]
203
+ [--op eval --value "<布尔问题>"]
204
+ [--op eval-choice --value "<问题>" --options "k=desc,..." --answer k]
205
+ [--op eval-score --value "<问题>" --levels "级0,..." --min-score n]
206
+ [--effect gate|cost_mul] [--weight n]
207
+ node index rebuild closure + topo order
208
+ node can <key> [--state k=v] evaluate required vs optional gates
209
+ (--eval: eval 题型经决策模型判定;
210
+ boolean P / choice P(期望答案) / score ±1 灰带)
211
+ node ready [--state k=v] [--eval] currently unlockable set
212
+ node path <key> dependency-order path to target (all locked ancestors; OR branches not optimized)
213
+ node parents|children <key> direct relations
214
+ node ancestors|descendants <key> transitive, via closure index
215
+ node list | show <key> | search "<q>" | unlock|lock <key>
216
+ node validate cycles, dangling edges, dirty index
217
+ node export [--out file.json] portable JSON
218
+ node import --file <file.json> [--tree name] [--merge] — strict, transactional
219
+
220
+ Writes are idempotent (claim/evidence/query/kb/job dedupe by content
221
+ hash); pass --force to keep a deliberate duplicate.
222
+
223
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "webui", true)} dashboard (zero-dependency)
224
+ export [--out <file>] single-file dashboard.html (open in browser)
225
+ serve [--port N] live dashboard at http://127.0.0.1:N/ (Ctrl+C to stop)
226
+
227
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "rel", true)} 关联织物(spec R9:任意两类实体互相挂接)
228
+ add <src> <dst> [--rel t] link two refs: node:key claim:id kb:id artifact:id
229
+ skill:name evidence:id source:id query:id
230
+ rm <src> <dst> [--rel t] unlink
231
+ list [--src r] [--dst r] browse (either side filter, resolves displays)
232
+
233
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "plugin", true)} 用户层插件分发(spec R14 L3,业务域扩展位)
234
+ init create $YGL_HOME/plugins profile
235
+ install <spec> npm package / git url / local dir (auto link:)
236
+ remove <name> | list manage the user layer ($YGL_HOME/ygl.user.bundle.json)
237
+ 插件契约:export apply(ctx,config) + 可选 commands 贡献 CLI 命令组
238
+
239
+ ${(0, fmt_1.paint)(fmt_1.C.bold, "agent", true)} agent-facing views
240
+ brief current project state + next actions (start here)
241
+ match "<task>" which skill should handle this task
242
+ log recent events
243
+
244
+ Global: --json --no-color --db <file> --home <dir>
245
245
  `;
246
246
  function usage() {
247
247
  return USAGE;
@@ -276,6 +276,14 @@ async function main(argv) {
276
276
  (0, fmt_1.out)(ctx, generateLlmsManifest());
277
277
  return 0;
278
278
  }
279
+ // MCP: Model Context Protocol server (stdio) — 8-tool surface.
280
+ // Designed by the unified three-pillar theory (R8 research); each tool
281
+ // routes to CLI --json, inheriting frozen contracts.
282
+ if (group === "mcp") {
283
+ const { serveMcp } = await Promise.resolve().then(() => __importStar(require("../../../packages/ops/tools/src/mcp")));
284
+ serveMcp();
285
+ return new Promise(() => { });
286
+ }
279
287
  if (!group || group === "help" || group === "-h" || group === "--help") {
280
288
  if (!ctx.json)
281
289
  (0, fmt_1.out)(ctx, usage());