ygl-trees 0.68.0 → 0.69.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,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.69.0(2026-10-17)MCP Server——R8 研究设计的工程落地
4
+ - **`ygl-trees mcp`**:启动 stdio MCP 服务器(JSON-RPC 2.0),Claude Desktop / Cursor / VS Code 等 IDE Agent 可直接连接
5
+ - **8 工具面**(三支柱理论驱动):agent_brief · agent_match · kb_search · claim_evaluate · tree_state · produce_report · doctor · task_advance
6
+ - **每个工具继承 CLI 冻结契约**(幂等写入、JSON 纯净、snake_case)——Agent 调用工具不需要解析命令行
7
+ - **实现**:`packages/ops/tools/src/mcp.ts`——readline stdio + JSON-RPC 路由 + `cliJson()` 子进程调用(`process.argv[1]` 自引用,bundle/源码双兼容)
8
+ - 实测:initialize ✓ · tools/list(8) ✓ · agent_brief(project) ✓ · kb_search(CJK 命中) ✓ · doctor(9 项) ✓
9
+
3
10
  ## 0.68.0(2026-10-17)锁设计修复——serve/CLI 共存 + PID 活锁检测 + JSON 纯净 + v9 时间纪律
4
11
  - **F1(P0):webui serve 不再持排他锁**——原实现进程级锁让 serve 生命周期内挡掉一切 CLI 命令;现 serve 跳过锁(`YGL_SERVE=1` 旁路),SQLite WAL 天然支持并发读 + 序列化写;CLI 短命令仍锁(单写者保护写窗口)
5
12
  - **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());
@@ -1,64 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- //#region \0rolldown/runtime.js
4
- var __create = Object.create;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
- var __getOwnPropNames = Object.getOwnPropertyNames;
8
- var __getProtoOf = Object.getPrototypeOf;
9
- var __hasOwnProp = Object.prototype.hasOwnProperty;
10
- var __esmMin = (fn, res, err) => () => {
11
- if (err) throw err[0];
12
- try {
13
- return fn && (res = fn(fn = 0)), res;
14
- } catch (e) {
15
- throw err = [e], e;
16
- }
17
- };
18
- var __exportAll = (all, no_symbols) => {
19
- let target = {};
20
- for (var name in all) __defProp(target, name, {
21
- get: all[name],
22
- enumerable: true
23
- });
24
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
25
- return target;
26
- };
27
- var __copyProps = (to, from, except, desc) => {
28
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
29
- key = keys[i];
30
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
31
- get: ((k) => from[k]).bind(null, key),
32
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
33
- });
34
- }
35
- return to;
36
- };
37
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
38
- value: mod,
39
- enumerable: true
40
- }) : target, mod));
41
- var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
42
- //#endregion
3
+ const require_rolldown_runtime = require("./rolldown-runtime-C96Ew50Q.cjs");
43
4
  let node_os = require("node:os");
44
- node_os = __toESM(node_os);
5
+ node_os = require_rolldown_runtime.__toESM(node_os);
45
6
  let node_path = require("node:path");
46
- node_path = __toESM(node_path);
7
+ node_path = require_rolldown_runtime.__toESM(node_path);
47
8
  let node_sqlite3_wasm = require("node-sqlite3-wasm");
48
9
  let node_fs = require("node:fs");
49
- node_fs = __toESM(node_fs);
10
+ node_fs = require_rolldown_runtime.__toESM(node_fs);
50
11
  let node_crypto = require("node:crypto");
51
12
  let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
52
13
  let _deepseek_ai_cordis_plugin_timer = require("@deepseek-ai/cordis-plugin-timer");
53
- _deepseek_ai_cordis_plugin_timer = __toESM(_deepseek_ai_cordis_plugin_timer);
14
+ _deepseek_ai_cordis_plugin_timer = require_rolldown_runtime.__toESM(_deepseek_ai_cordis_plugin_timer);
54
15
  let node_child_process = require("node:child_process");
55
16
  let _deepseek_ai_dsh_atomic_write = require("@deepseek-ai/dsh-atomic-write");
56
17
  require("reflect-metadata");
57
18
  let typeorm = require("typeorm");
58
19
  let _deepseek_ai_schemastery = require("@deepseek-ai/schemastery");
59
- _deepseek_ai_schemastery = __toESM(_deepseek_ai_schemastery);
20
+ _deepseek_ai_schemastery = require_rolldown_runtime.__toESM(_deepseek_ai_schemastery);
60
21
  //#region packages/core/text/src/text.ts
61
- var text_exports = /* @__PURE__ */ __exportAll({
22
+ var text_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
62
23
  clip: () => clip,
63
24
  contentHash: () => contentHash,
64
25
  ngram: () => ngram,
@@ -167,7 +128,7 @@ function splitTags(v) {
167
128
  return (v || "").split(/[,,;;\s]+/).map((s) => s.trim()).filter(Boolean);
168
129
  }
169
130
  var CJK, CJK_RUN_RE, CJK_ONLY_RE;
170
- var init_text = __esmMin((() => {
131
+ var init_text = require_rolldown_runtime.__esmMin((() => {
171
132
  CJK = "\\u4e00-\\u9fff\\u3400-\\u4dbf\\uf900-\\ufaff";
172
133
  new RegExp(`[${CJK}]`, "u");
173
134
  CJK_RUN_RE = new RegExp(`[${CJK}]+|[^\\s${CJK}]+`, "gu");
@@ -181,7 +142,7 @@ var init_text = __esmMin((() => {
181
142
  * Everything — skills, research state, evidence, drafts, knowledge notes and
182
143
  * schedules — lives in one SQLite file. No sidecar JSON, no git-as-database.
183
144
  */
184
- var db_exports = /* @__PURE__ */ __exportAll({
145
+ var db_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
185
146
  COND_KINDS: () => COND_KINDS,
186
147
  DB: () => DB,
187
148
  EDGE_MODES: () => EDGE_MODES,
@@ -195,7 +156,7 @@ function dbPath(home) {
195
156
  return node_path.join(home, "ygl-trees.db");
196
157
  }
197
158
  var SCHEMA_SQL, DB, EDGE_RELS, EDGE_MODES, COND_KINDS;
198
- var init_db = __esmMin((() => {
159
+ var init_db = require_rolldown_runtime.__esmMin((() => {
199
160
  init_text();
200
161
  SCHEMA_SQL = `
201
162
  -- ---------------------------------------------------------------- meta
@@ -1425,7 +1386,7 @@ function mapOutcome(r, high = .7, low = .4) {
1425
1386
  };
1426
1387
  }
1427
1388
  var GATEWAY_URL, MODEL_ID, NO_TOKEN;
1428
- var init_eval = __esmMin((() => {
1389
+ var init_eval = require_rolldown_runtime.__esmMin((() => {
1429
1390
  GATEWAY_URL = "https://ai-gateway.vercel.sh/v4/ai/evaluation-model";
1430
1391
  MODEL_ID = "typesafe-ai/jev";
1431
1392
  NO_TOKEN = "no evaluator configured (set config decision_model_llm_token, or AI_GATEWAY_API_KEY / ~/.vercel.ai-gateway.env)";
@@ -1937,7 +1898,7 @@ var TreeStore = class {
1937
1898
  /** Full-text search over nodes. Title/key substring hits outrank same-hit
1938
1899
  * rows (same ranking semantics as kb/skill/source search). */
1939
1900
  nodeSearch(treeId, q, limit = 20) {
1940
- const tokens = Array.from(new Set(String((init_text(), __toCommonJS(text_exports)).ngram(q) || "").split(/\s+/).filter(Boolean)));
1901
+ const tokens = Array.from(new Set(String((init_text(), require_rolldown_runtime.__toCommonJS(text_exports)).ngram(q) || "").split(/\s+/).filter(Boolean)));
1941
1902
  if (!tokens.length) return [];
1942
1903
  const agg = /* @__PURE__ */ new Map();
1943
1904
  const st = this.db.db.prepare(`SELECT n.id,n.key,n.name,n.tier, bm25(nodes_fts) AS score
@@ -2591,7 +2552,7 @@ function apply(ctx) {
2591
2552
  *
2592
2553
  * @module @ygl/ops-tools/plugins
2593
2554
  */
2594
- var plugins_exports = /* @__PURE__ */ __exportAll({
2555
+ var plugins_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
2595
2556
  initProfile: () => initProfile,
2596
2557
  installPlugin: () => installPlugin,
2597
2558
  listPlugins: () => listPlugins,
@@ -2842,7 +2803,7 @@ function loadUserPlugins(home) {
2842
2803
  };
2843
2804
  }
2844
2805
  var PROFILE_PKG, cachedPm, q2;
2845
- var init_plugins = __esmMin((() => {
2806
+ var init_plugins = require_rolldown_runtime.__esmMin((() => {
2846
2807
  PROFILE_PKG = () => ({
2847
2808
  name: "ygl-user-plugins",
2848
2809
  private: true,
@@ -3073,7 +3034,7 @@ function runPluginCommand(env, action, rest, args) {
3073
3034
  bad(ctx, `'${name}' is not in the user bundle`);
3074
3035
  return 1;
3075
3036
  }
3076
- const bundle = (init_plugins(), __toCommonJS(plugins_exports)).readUserBundle(home).find((p) => p.name === name);
3037
+ const bundle = (init_plugins(), require_rolldown_runtime.__toCommonJS(plugins_exports)).readUserBundle(home).find((p) => p.name === name);
3077
3038
  out(ctx, JSON.stringify(bundle?.config ?? {}, null, 2));
3078
3039
  return 0;
3079
3040
  }
@@ -3484,7 +3445,7 @@ function preflightTypeCheck(db) {
3484
3445
  function __decorateMetadata(k, v) {
3485
3446
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
3486
3447
  }
3487
- var init_decorateMetadata = __esmMin((() => {}));
3448
+ var init_decorateMetadata = require_rolldown_runtime.__esmMin((() => {}));
3488
3449
  //#endregion
3489
3450
  //#region \0@oxc-project+runtime@0.154.0/helpers/esm/decorate.js
3490
3451
  function __decorate(decorators, target, key, desc) {
@@ -3493,7 +3454,7 @@ function __decorate(decorators, target, key, desc) {
3493
3454
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
3494
3455
  return c > 3 && r && Object.defineProperty(target, key, r), r;
3495
3456
  }
3496
- var init_decorate = __esmMin((() => {}));
3457
+ var init_decorate = require_rolldown_runtime.__esmMin((() => {}));
3497
3458
  //#endregion
3498
3459
  //#region packages/research/pipeline/src/entities.ts
3499
3460
  /**
@@ -3508,7 +3469,7 @@ var init_decorate = __esmMin((() => {}));
3508
3469
  * stay raw SQL in store.ts (see docs/plan.md TypeORM boundaries).
3509
3470
  */
3510
3471
  var Project, Query, Source, QuerySource, Evidence, Claim, ClaimEvidence, RESEARCH_ENTITIES;
3511
- var init_entities$1 = __esmMin((() => {
3472
+ var init_entities$1 = require_rolldown_runtime.__esmMin((() => {
3512
3473
  init_decorateMetadata();
3513
3474
  init_decorate();
3514
3475
  Project = class Project {
@@ -3882,7 +3843,7 @@ var init_entities$1 = __esmMin((() => {
3882
3843
  /** Cross-cutting entities (audit trail). Research-domain entities live in
3883
3844
  * research.ts; both are registered in src/orm.ts. */
3884
3845
  var Event, CORE_ENTITIES;
3885
- var init_entities = __esmMin((() => {
3846
+ var init_entities = require_rolldown_runtime.__esmMin((() => {
3886
3847
  init_decorateMetadata();
3887
3848
  init_decorate();
3888
3849
  Event = class Event {
@@ -3948,7 +3909,7 @@ var init_entities = __esmMin((() => {
3948
3909
  * - CLI commands using the ORM must return a Promise (main() awaits) so
3949
3910
  * the DataSource settles before the wasm DB closes.
3950
3911
  */
3951
- var orm_exports = /* @__PURE__ */ __exportAll({
3912
+ var orm_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
3952
3913
  closeOrm: () => closeOrm,
3953
3914
  getOrm: () => getOrm
3954
3915
  });
@@ -3979,14 +3940,14 @@ async function closeOrm() {
3979
3940
  }
3980
3941
  }
3981
3942
  var cached;
3982
- var init_orm = __esmMin((() => {
3943
+ var init_orm = require_rolldown_runtime.__esmMin((() => {
3983
3944
  init_entities$1();
3984
3945
  init_entities();
3985
3946
  cached = null;
3986
3947
  }));
3987
3948
  //#endregion
3988
3949
  //#region packages/research/pipeline/src/writes.ts
3989
- var writes_exports = /* @__PURE__ */ __exportAll({
3950
+ var writes_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
3990
3951
  artifactAdd: () => artifactAdd,
3991
3952
  claimAdd: () => claimAdd,
3992
3953
  claimLink: () => claimLink,
@@ -4611,7 +4572,7 @@ async function projectCreate(ds, name, question = "") {
4611
4572
  });
4612
4573
  }
4613
4574
  var TASK_STATUSES;
4614
- var init_writes = __esmMin((() => {
4575
+ var init_writes = require_rolldown_runtime.__esmMin((() => {
4615
4576
  init_entities$1();
4616
4577
  init_entities();
4617
4578
  init_text();
@@ -4623,7 +4584,7 @@ var init_writes = __esmMin((() => {
4623
4584
  }));
4624
4585
  //#endregion
4625
4586
  //#region packages/ops/tools/src/db-cmds.ts
4626
- var db_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$12 });
4587
+ var db_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$12 });
4627
4588
  init_db();
4628
4589
  /**
4629
4590
  * Cold-start: import the built-in skills that ship with this package, so a
@@ -4645,9 +4606,9 @@ async function autoImportBuiltinSkills(env, dbFile) {
4645
4606
  }
4646
4607
  }
4647
4608
  if (!skillsDir) return 0;
4648
- const { getOrm } = (init_orm(), __toCommonJS(orm_exports));
4649
- const writes = (init_writes(), __toCommonJS(writes_exports));
4650
- const { parseFrontmatter } = (init_text(), __toCommonJS(text_exports));
4609
+ const { getOrm } = (init_orm(), require_rolldown_runtime.__toCommonJS(orm_exports));
4610
+ const writes = (init_writes(), require_rolldown_runtime.__toCommonJS(writes_exports));
4611
+ const { parseFrontmatter } = (init_text(), require_rolldown_runtime.__toCommonJS(text_exports));
4651
4612
  const ds = await getOrm(dbFile);
4652
4613
  let count = 0;
4653
4614
  for (const entry of fs2.readdirSync(skillsDir)) {
@@ -4674,16 +4635,16 @@ function run$12(env, action, rest, args) {
4674
4635
  switch (action) {
4675
4636
  case "init": {
4676
4637
  node_fs.mkdirSync(home, { recursive: true });
4677
- const d = new (init_db(), __toCommonJS(db_exports)).DB(file);
4638
+ const d = new (init_db(), require_rolldown_runtime.__toCommonJS(db_exports)).DB(file);
4678
4639
  d.metaSet("created", (/* @__PURE__ */ new Date()).toISOString());
4679
- d.metaSet("schema_version", String((init_db(), __toCommonJS(db_exports)).SCHEMA_VERSION));
4640
+ d.metaSet("schema_version", String((init_db(), require_rolldown_runtime.__toCommonJS(db_exports)).SCHEMA_VERSION));
4680
4641
  d.close();
4681
4642
  ok(ctx, `workspace ready: ${home}`);
4682
4643
  ok(ctx, `database: ${file}`);
4683
4644
  autoImportBuiltinSkills(env, file).then(async (n) => {
4684
4645
  if (n > 0) ok(ctx, `built-in skills: ${n} imported (agent match ready)`);
4685
4646
  try {
4686
- const { closeOrm } = (init_orm(), __toCommonJS(orm_exports));
4647
+ const { closeOrm } = (init_orm(), require_rolldown_runtime.__toCommonJS(orm_exports));
4687
4648
  await closeOrm();
4688
4649
  } catch {}
4689
4650
  });
@@ -5029,7 +4990,7 @@ function configReset(db, key) {
5029
4990
  }
5030
4991
  //#endregion
5031
4992
  //#region packages/ops/tools/src/config-cmds.ts
5032
- var config_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$11 });
4993
+ var config_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$11 });
5033
4994
  function run$11(env, action, rest, args) {
5034
4995
  const { ctx, db } = env;
5035
4996
  switch (action) {
@@ -5115,7 +5076,7 @@ function run$11(env, action, rest, args) {
5115
5076
  //#region packages/ops/tools/src/job-cmds.ts
5116
5077
  /** job group — batch + schedule. `job tick` is what cron/systemctl drives.
5117
5078
  * Writes (add) run on the TypeORM write service (src/writes.ts). */
5118
- var job_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$10 });
5079
+ var job_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$10 });
5119
5080
  init_text();
5120
5081
  init_orm();
5121
5082
  init_writes();
@@ -5319,7 +5280,7 @@ function withTickLock(env, fn) {
5319
5280
  }
5320
5281
  //#endregion
5321
5282
  //#region packages/ops/tools/src/agent-cmds.ts
5322
- var agent_cmds_exports = /* @__PURE__ */ __exportAll({
5283
+ var agent_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
5323
5284
  buildBrief: () => buildBrief,
5324
5285
  run: () => run$9
5325
5286
  });
@@ -5565,7 +5526,7 @@ function validateEnum(ctx, flags, name, allowed, required = false) {
5565
5526
  }
5566
5527
  //#endregion
5567
5528
  //#region packages/ops/tools/src/eval-enhance.ts
5568
- var eval_enhance_exports = /* @__PURE__ */ __exportAll({
5529
+ var eval_enhance_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
5569
5530
  assessEvidenceQuality: () => assessEvidenceQuality,
5570
5531
  evaluateClaimConfidence: () => evaluateClaimConfidence,
5571
5532
  semanticReRank: () => semanticReRank
@@ -5693,7 +5654,7 @@ async function assessEvidenceQuality(ctx, token) {
5693
5654
  usage: r.usage
5694
5655
  };
5695
5656
  }
5696
- var init_eval_enhance = __esmMin((() => {
5657
+ var init_eval_enhance = require_rolldown_runtime.__esmMin((() => {
5697
5658
  init_eval();
5698
5659
  }));
5699
5660
  //#endregion
@@ -5701,7 +5662,7 @@ var init_eval_enhance = __esmMin((() => {
5701
5662
  /** research group — collect → screen → extract → claim.
5702
5663
  * `source fetch` is async (Node 18+ global fetch) and returns a promise.
5703
5664
  * List commands run on TypeORM (src/orm.ts); search stays raw SQL (FTS5). */
5704
- var cmds_exports$2 = /* @__PURE__ */ __exportAll({ run: () => run$8 });
5665
+ var cmds_exports$2 = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$8 });
5705
5666
  init_text();
5706
5667
  init_orm();
5707
5668
  init_writes();
@@ -6028,7 +5989,7 @@ function run$8(env, action, rest, args) {
6028
5989
  bad(ctx, `evidence not found: ${id}`);
6029
5990
  return 1;
6030
5991
  }
6031
- const { assessEvidenceQuality } = (init_eval_enhance(), __toCommonJS(eval_enhance_exports));
5992
+ const { assessEvidenceQuality } = (init_eval_enhance(), require_rolldown_runtime.__toCommonJS(eval_enhance_exports));
6032
5993
  return assessEvidenceQuality({
6033
5994
  quote: ev.quote,
6034
5995
  locator: ev.locator,
@@ -6120,7 +6081,7 @@ function run$8(env, action, rest, args) {
6120
6081
  return getOrm(env.db.path).then((ds) => claimLink(ds, rest[1], rest[2], stance)).then((r) => {
6121
6082
  ok(ctx, `linked; claim status now: ${r.status}`);
6122
6083
  try {
6123
- const { evaluateClaimConfidence } = (init_eval_enhance(), __toCommonJS(eval_enhance_exports));
6084
+ const { evaluateClaimConfidence } = (init_eval_enhance(), require_rolldown_runtime.__toCommonJS(eval_enhance_exports));
6124
6085
  const evRows = store.db.all(`SELECT e.quote, ce.stance, s.title AS source_title
6125
6086
  FROM claim_evidence ce
6126
6087
  JOIN evidence e ON e.id = ce.evidence_id
@@ -6202,7 +6163,7 @@ function run$8(env, action, rest, args) {
6202
6163
  JOIN evidence e ON e.id = ce.evidence_id
6203
6164
  LEFT JOIN sources s ON s.id = e.source_id
6204
6165
  WHERE ce.claim_id = ?`, [id]);
6205
- const { evaluateClaimConfidence } = (init_eval_enhance(), __toCommonJS(eval_enhance_exports));
6166
+ const { evaluateClaimConfidence } = (init_eval_enhance(), require_rolldown_runtime.__toCommonJS(eval_enhance_exports));
6206
6167
  return (async () => {
6207
6168
  const result = await evaluateClaimConfidence({
6208
6169
  claim_text: claim.text,
@@ -6277,7 +6238,7 @@ function run$8(env, action, rest, args) {
6277
6238
  }
6278
6239
  //#endregion
6279
6240
  //#region packages/research/produce/src/project-cmds.ts
6280
- var project_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$7 });
6241
+ var project_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$7 });
6281
6242
  init_orm();
6282
6243
  init_writes();
6283
6244
  init_entities$1();
@@ -6415,7 +6376,7 @@ function run$7(env, action, rest, args) {
6415
6376
  /** produce group — evidence-backed outline → sections → report.
6416
6377
  * Writes run on the TypeORM write service (src/writes.ts); reads stay on
6417
6378
  * Store until their own migration batch. */
6418
- var produce_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$6 });
6379
+ var produce_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$6 });
6419
6380
  init_text();
6420
6381
  init_orm();
6421
6382
  init_writes();
@@ -7305,7 +7266,7 @@ async function importTree(ds, spec, opts = {}) {
7305
7266
  * ygl-trees node validate sanity checks
7306
7267
  * ygl-trees node export [--out file] portable JSON
7307
7268
  */
7308
- var cmds_exports$1 = /* @__PURE__ */ __exportAll({ run: () => run$5 });
7269
+ var cmds_exports$1 = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$5 });
7309
7270
  init_orm();
7310
7271
  init_eval();
7311
7272
  init_text();
@@ -8151,7 +8112,7 @@ function parseState(args) {
8151
8112
  //#region packages/knowledge/skills/src/skill-cmds.ts
8152
8113
  /** skill group — the L1/L2/L3 registry agents query before acting.
8153
8114
  * Writes run on the TypeORM write service (src/writes.ts). */
8154
- var skill_cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$4 });
8115
+ var skill_cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$4 });
8155
8116
  init_text();
8156
8117
  init_orm();
8157
8118
  init_writes();
@@ -8404,7 +8365,7 @@ function wrap(text, indent = 4) {
8404
8365
  //#region packages/knowledge/skills/src/cmds.ts
8405
8366
  /** kb group — long-term knowledge: store, retrieve, connect, promote to skill.
8406
8367
  * Writes (add/ingest) run on the TypeORM write service (src/writes.ts). */
8407
- var cmds_exports = /* @__PURE__ */ __exportAll({ run: () => run$3 });
8368
+ var cmds_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run$3 });
8408
8369
  init_text();
8409
8370
  init_orm();
8410
8371
  init_writes();
@@ -8453,7 +8414,7 @@ function run$3(env, action, rest, args) {
8453
8414
  }
8454
8415
  const raw = store.kbSearch(q, Number(args.flags.limit || configGetNumber(env.db, "search.limit")));
8455
8416
  if (args.flags.eval) {
8456
- const { semanticReRank } = (init_eval_enhance(), __toCommonJS(eval_enhance_exports));
8417
+ const { semanticReRank } = (init_eval_enhance(), require_rolldown_runtime.__toCommonJS(eval_enhance_exports));
8457
8418
  return semanticReRank(q, raw.map((r) => ({
8458
8419
  id: r.id,
8459
8420
  title: r.title,
@@ -8708,7 +8669,7 @@ function run$3(env, action, rest, args) {
8708
8669
  }
8709
8670
  //#endregion
8710
8671
  //#region packages/ops/tools/src/rels.ts
8711
- var rels_exports = /* @__PURE__ */ __exportAll({
8672
+ var rels_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
8712
8673
  REL_TYPES: () => REL_TYPES,
8713
8674
  RelError: () => RelError,
8714
8675
  relAdd: () => relAdd,
@@ -9014,7 +8975,7 @@ function run$2(env, action, rest, args) {
9014
8975
  }
9015
8976
  //#endregion
9016
8977
  //#region packages/ops/tools/src/webui.ts
9017
- var webui_exports = /* @__PURE__ */ __exportAll({
8978
+ var webui_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
9018
8979
  createDashboardServer: () => createDashboardServer,
9019
8980
  gatherData: () => gatherData,
9020
8981
  generateHTML: () => generateHTML,
@@ -9936,7 +9897,7 @@ function serve(env, args) {
9936
9897
  }
9937
9898
  //#endregion
9938
9899
  //#region packages/ops/tools/src/doctor.ts
9939
- var doctor_exports = /* @__PURE__ */ __exportAll({ run: () => run });
9900
+ var doctor_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ run: () => run });
9940
9901
  init_eval();
9941
9902
  init_db();
9942
9903
  init_plugins();
@@ -10363,6 +10324,11 @@ async function main(argv) {
10363
10324
  out(ctx, generateLlmsManifest());
10364
10325
  return 0;
10365
10326
  }
10327
+ if (group === "mcp") {
10328
+ const { serveMcp } = await Promise.resolve().then(() => require("./mcp-C27lIHd1.cjs"));
10329
+ serveMcp();
10330
+ return new Promise(() => {});
10331
+ }
10366
10332
  if (!group || group === "help" || group === "-h" || group === "--help") {
10367
10333
  if (!ctx.json) out(ctx, usage());
10368
10334
  return 0;
@@ -10437,7 +10403,7 @@ async function main(argv) {
10437
10403
  db?.close();
10438
10404
  } catch {}
10439
10405
  try {
10440
- (init_db(), __toCommonJS(db_exports)).DB.releaseLockFor(file);
10406
+ (init_db(), require_rolldown_runtime.__toCommonJS(db_exports)).DB.releaseLockFor(file);
10441
10407
  } catch {}
10442
10408
  });
10443
10409
  process.on("SIGINT", () => shutdown.interrupt(0));
@@ -0,0 +1,276 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C96Ew50Q.cjs");
2
+ let node_readline = require("node:readline");
3
+ node_readline = require_rolldown_runtime.__toESM(node_readline);
4
+ //#region packages/ops/tools/src/mcp.ts
5
+ /**
6
+ * MCP (Model Context Protocol) Server — stdio transport.
7
+ *
8
+ * Eight-tool surface designed by the unified three-pillar theory (R8 research):
9
+ * agent_brief · agent_match · kb_search · claim_evaluate
10
+ * tree_state · produce_report · doctor · task_advance
11
+ *
12
+ * Each tool routes to the CLI --json backend, inheriting its frozen contracts
13
+ * (idempotent writes, pure JSON errors, snake_case fields). Agents call tools
14
+ * directly — no command-line parsing layer.
15
+ *
16
+ * Protocol: JSON-RPC 2.0 over stdio (one message per line).
17
+ * → {"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
18
+ * ← {"jsonrpc":"2.0","id":1,"result":{...}}
19
+ *
20
+ * @module @ygl/ops-tools/mcp
21
+ */
22
+ /** Build a CLI invocation and capture JSON stdout.
23
+ * Uses process.argv[1] (the running script — bundle or source) to re-invoke
24
+ * the CLI as a child process. This works in both dev (dist/apps/...) and
25
+ * bundle (dist/bundle/bin.cjs) contexts. */
26
+ function cliJson(parts) {
27
+ const { spawn } = require("node:child_process");
28
+ const self = process.argv[1];
29
+ return new Promise((resolve, reject) => {
30
+ const child = spawn(process.execPath, [
31
+ self,
32
+ "--json",
33
+ ...parts
34
+ ], {
35
+ env: {
36
+ ...process.env,
37
+ YGL_SERVE: "1",
38
+ YGL_MCP_CHILD: "1"
39
+ },
40
+ stdio: [
41
+ "ignore",
42
+ "pipe",
43
+ "pipe"
44
+ ]
45
+ });
46
+ let out = "";
47
+ let err = "";
48
+ child.stdout.on("data", (d) => out += d);
49
+ child.stderr.on("data", (d) => err += d);
50
+ child.on("close", (code) => {
51
+ if (out.trim()) try {
52
+ resolve(JSON.parse(out));
53
+ return;
54
+ } catch {}
55
+ reject(/* @__PURE__ */ new Error(`CLI rc=${code}: ${err.slice(0, 200) || out.slice(0, 200)}`));
56
+ });
57
+ child.on("error", (e) => reject(e));
58
+ });
59
+ }
60
+ function buildTools() {
61
+ return [
62
+ {
63
+ name: "agent_brief",
64
+ description: "Current workspace state: project, progress, counts, next actions, available skills. Always start here.",
65
+ inputSchema: {
66
+ type: "object",
67
+ properties: {}
68
+ },
69
+ execute: () => cliJson(["agent", "brief"])
70
+ },
71
+ {
72
+ name: "agent_match",
73
+ description: "Discover which skill handles a task. Returns matched skills with relevance scores.",
74
+ inputSchema: {
75
+ type: "object",
76
+ properties: { query: {
77
+ type: "string",
78
+ description: "Task description to match"
79
+ } },
80
+ required: ["query"]
81
+ },
82
+ execute: (a) => cliJson([
83
+ "agent",
84
+ "match",
85
+ String(a.query)
86
+ ])
87
+ },
88
+ {
89
+ name: "kb_search",
90
+ description: "Search knowledge notes (CJK full-text). Returns notes with title, body, tags, confidence.",
91
+ inputSchema: {
92
+ type: "object",
93
+ properties: {
94
+ query: {
95
+ type: "string",
96
+ description: "Search query (Chinese supported)"
97
+ },
98
+ eval: {
99
+ type: "boolean",
100
+ description: "Enable decision-model semantic re-ranking"
101
+ }
102
+ },
103
+ required: ["query"]
104
+ },
105
+ execute: (a) => {
106
+ const parts = [
107
+ "kb",
108
+ "search",
109
+ String(a.query)
110
+ ];
111
+ if (a.eval) parts.push("--eval");
112
+ return cliJson(parts);
113
+ }
114
+ },
115
+ {
116
+ name: "claim_evaluate",
117
+ description: "Decision model evaluates a claim's confidence (score 0-5 → grade A/B/C/D).",
118
+ inputSchema: {
119
+ type: "object",
120
+ properties: { claim_id: {
121
+ type: "string",
122
+ description: "Claim ID to evaluate"
123
+ } },
124
+ required: ["claim_id"]
125
+ },
126
+ execute: (a) => cliJson([
127
+ "research",
128
+ "claim",
129
+ "evaluate",
130
+ String(a.claim_id)
131
+ ])
132
+ },
133
+ {
134
+ name: "tree_state",
135
+ description: "All trees with node states (locked/unlocked). Visualize the dependency graph.",
136
+ inputSchema: {
137
+ type: "object",
138
+ properties: { tree: {
139
+ type: "string",
140
+ description: "Optional tree name (omit for all)"
141
+ } }
142
+ },
143
+ execute: (a) => cliJson([
144
+ "node",
145
+ "list",
146
+ ...a.tree ? [String(a.tree)] : []
147
+ ])
148
+ },
149
+ {
150
+ name: "produce_report",
151
+ description: "Assemble claims + evidence into a markdown report. Returns report ID and content.",
152
+ inputSchema: {
153
+ type: "object",
154
+ properties: {}
155
+ },
156
+ execute: () => cliJson(["produce", "report"])
157
+ },
158
+ {
159
+ name: "doctor",
160
+ description: "9-item workspace health check. Pass fix=true to auto-fix safe issues.",
161
+ inputSchema: {
162
+ type: "object",
163
+ properties: { fix: {
164
+ type: "boolean",
165
+ description: "Auto-fix dirty index + stale locks"
166
+ } }
167
+ },
168
+ execute: (a) => cliJson(["doctor", ...a.fix ? ["--fix"] : []])
169
+ },
170
+ {
171
+ name: "task_advance",
172
+ description: "Advance a task through the state machine: todo → doing → done (or roll back).",
173
+ inputSchema: {
174
+ type: "object",
175
+ properties: {
176
+ task_id: {
177
+ type: "string",
178
+ description: "Task artifact ID"
179
+ },
180
+ action: {
181
+ type: "string",
182
+ enum: [
183
+ "doing",
184
+ "done",
185
+ "todo"
186
+ ],
187
+ description: "Target status"
188
+ }
189
+ },
190
+ required: ["task_id", "action"]
191
+ },
192
+ execute: (a) => cliJson([
193
+ "task",
194
+ String(a.action),
195
+ String(a.task_id)
196
+ ])
197
+ }
198
+ ];
199
+ }
200
+ /** Run the MCP server on stdio. */
201
+ function serveMcp() {
202
+ const tools = buildTools();
203
+ const rl = node_readline.createInterface({ input: process.stdin });
204
+ const respond = (id, result) => {
205
+ process.stdout.write(JSON.stringify({
206
+ jsonrpc: "2.0",
207
+ id,
208
+ result
209
+ }) + "\n");
210
+ };
211
+ const respondErr = (id, code, message) => {
212
+ process.stdout.write(JSON.stringify({
213
+ jsonrpc: "2.0",
214
+ id,
215
+ error: {
216
+ code,
217
+ message
218
+ }
219
+ }) + "\n");
220
+ };
221
+ rl.on("line", (line) => {
222
+ if (!line.trim()) return;
223
+ let msg;
224
+ try {
225
+ msg = JSON.parse(line);
226
+ } catch {
227
+ return;
228
+ }
229
+ const { id, method, params } = msg;
230
+ switch (method) {
231
+ case "initialize":
232
+ respond(id, {
233
+ protocolVersion: "2024-11-05",
234
+ capabilities: { tools: {} },
235
+ serverInfo: {
236
+ name: "ygl-trees",
237
+ version: "0.69.0"
238
+ }
239
+ });
240
+ break;
241
+ case "tools/list":
242
+ respond(id, { tools: tools.map((t) => ({
243
+ name: t.name,
244
+ description: t.description,
245
+ inputSchema: t.inputSchema
246
+ })) });
247
+ break;
248
+ case "tools/call": {
249
+ const name = params?.name;
250
+ const tool = tools.find((t) => t.name === name);
251
+ if (!tool) {
252
+ respondErr(id, -32602, `Unknown tool: ${name}`);
253
+ break;
254
+ }
255
+ tool.execute(params?.arguments || {}).then((data) => respond(id, { content: [{
256
+ type: "text",
257
+ text: JSON.stringify(data, null, 2)
258
+ }] })).catch((e) => respond(id, {
259
+ content: [{
260
+ type: "text",
261
+ text: `Error: ${e?.message || e}`
262
+ }],
263
+ isError: true
264
+ }));
265
+ break;
266
+ }
267
+ case "ping":
268
+ respond(id, {});
269
+ break;
270
+ default: if (id !== void 0) respondErr(id, -32601, `Method not found: ${method}`);
271
+ }
272
+ });
273
+ process.stderr.write("[ygl-trees MCP] stdio server ready — 8 tools\n");
274
+ }
275
+ //#endregion
276
+ exports.serveMcp = serveMcp;
@@ -0,0 +1,64 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __esmMin = (fn, res, err) => () => {
9
+ if (err) throw err[0];
10
+ try {
11
+ return fn && (res = fn(fn = 0)), res;
12
+ } catch (e) {
13
+ throw err = [e], e;
14
+ }
15
+ };
16
+ var __exportAll = (all, no_symbols) => {
17
+ let target = {};
18
+ for (var name in all) __defProp(target, name, {
19
+ get: all[name],
20
+ enumerable: true
21
+ });
22
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
23
+ return target;
24
+ };
25
+ var __copyProps = (to, from, except, desc) => {
26
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
27
+ key = keys[i];
28
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
29
+ get: ((k) => from[k]).bind(null, key),
30
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
31
+ });
32
+ }
33
+ return to;
34
+ };
35
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
36
+ value: mod,
37
+ enumerable: true
38
+ }) : target, mod));
39
+ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
40
+ //#endregion
41
+ Object.defineProperty(exports, "__esmMin", {
42
+ enumerable: true,
43
+ get: function() {
44
+ return __esmMin;
45
+ }
46
+ });
47
+ Object.defineProperty(exports, "__exportAll", {
48
+ enumerable: true,
49
+ get: function() {
50
+ return __exportAll;
51
+ }
52
+ });
53
+ Object.defineProperty(exports, "__toCommonJS", {
54
+ enumerable: true,
55
+ get: function() {
56
+ return __toCommonJS;
57
+ }
58
+ });
59
+ Object.defineProperty(exports, "__toESM", {
60
+ enumerable: true,
61
+ get: function() {
62
+ return __toESM;
63
+ }
64
+ });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.apply = exports.OpsService = exports.MIRROR_TABLES = exports.migrateToPg = exports.syncToPg = exports.configAll = exports.configReset = exports.configSet = exports.configGetBool = exports.configGetNumber = exports.configGet = exports.CONFIG_REGISTRY = void 0;
3
+ exports.buildTools = exports.serveMcp = exports.apply = exports.OpsService = exports.MIRROR_TABLES = exports.migrateToPg = exports.syncToPg = exports.configAll = exports.configReset = exports.configSet = exports.configGetBool = exports.configGetNumber = exports.configGet = exports.CONFIG_REGISTRY = void 0;
4
4
  /**
5
5
  * @module @ygl/ops-tools
6
6
  */
@@ -20,3 +20,6 @@ Object.defineProperty(exports, "MIRROR_TABLES", { enumerable: true, get: functio
20
20
  var plugin_1 = require("./plugin");
21
21
  Object.defineProperty(exports, "OpsService", { enumerable: true, get: function () { return plugin_1.OpsService; } });
22
22
  Object.defineProperty(exports, "apply", { enumerable: true, get: function () { return plugin_1.apply; } });
23
+ var mcp_1 = require("./mcp");
24
+ Object.defineProperty(exports, "serveMcp", { enumerable: true, get: function () { return mcp_1.serveMcp; } });
25
+ Object.defineProperty(exports, "buildTools", { enumerable: true, get: function () { return mcp_1.buildTools; } });
@@ -0,0 +1,233 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildTools = buildTools;
37
+ exports.serveMcp = serveMcp;
38
+ /**
39
+ * MCP (Model Context Protocol) Server — stdio transport.
40
+ *
41
+ * Eight-tool surface designed by the unified three-pillar theory (R8 research):
42
+ * agent_brief · agent_match · kb_search · claim_evaluate
43
+ * tree_state · produce_report · doctor · task_advance
44
+ *
45
+ * Each tool routes to the CLI --json backend, inheriting its frozen contracts
46
+ * (idempotent writes, pure JSON errors, snake_case fields). Agents call tools
47
+ * directly — no command-line parsing layer.
48
+ *
49
+ * Protocol: JSON-RPC 2.0 over stdio (one message per line).
50
+ * → {"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
51
+ * ← {"jsonrpc":"2.0","id":1,"result":{...}}
52
+ *
53
+ * @module @ygl/ops-tools/mcp
54
+ */
55
+ const readline = __importStar(require("node:readline"));
56
+ /** Build a CLI invocation and capture JSON stdout.
57
+ * Uses process.argv[1] (the running script — bundle or source) to re-invoke
58
+ * the CLI as a child process. This works in both dev (dist/apps/...) and
59
+ * bundle (dist/bundle/bin.cjs) contexts. */
60
+ function cliJson(parts) {
61
+ const { spawn } = require("node:child_process");
62
+ const self = process.argv[1]; // the bin.cjs or bin.js that's running this MCP server
63
+ return new Promise((resolve, reject) => {
64
+ const child = spawn(process.execPath, [self, "--json", ...parts], {
65
+ env: { ...process.env, YGL_SERVE: "1", YGL_MCP_CHILD: "1" },
66
+ stdio: ["ignore", "pipe", "pipe"],
67
+ });
68
+ let out = "";
69
+ let err = "";
70
+ child.stdout.on("data", (d) => (out += d));
71
+ child.stderr.on("data", (d) => (err += d));
72
+ child.on("close", (code) => {
73
+ if (out.trim()) {
74
+ try {
75
+ resolve(JSON.parse(out));
76
+ return;
77
+ }
78
+ catch { /* fall through */ }
79
+ }
80
+ reject(new Error(`CLI rc=${code}: ${err.slice(0, 200) || out.slice(0, 200)}`));
81
+ });
82
+ child.on("error", (e) => reject(e));
83
+ });
84
+ }
85
+ function buildTools() {
86
+ return [
87
+ {
88
+ name: "agent_brief",
89
+ description: "Current workspace state: project, progress, counts, next actions, available skills. Always start here.",
90
+ inputSchema: { type: "object", properties: {} },
91
+ execute: () => cliJson(["agent", "brief"]),
92
+ },
93
+ {
94
+ name: "agent_match",
95
+ description: "Discover which skill handles a task. Returns matched skills with relevance scores.",
96
+ inputSchema: {
97
+ type: "object",
98
+ properties: { query: { type: "string", description: "Task description to match" } },
99
+ required: ["query"],
100
+ },
101
+ execute: (a) => cliJson(["agent", "match", String(a.query)]),
102
+ },
103
+ {
104
+ name: "kb_search",
105
+ description: "Search knowledge notes (CJK full-text). Returns notes with title, body, tags, confidence.",
106
+ inputSchema: {
107
+ type: "object",
108
+ properties: {
109
+ query: { type: "string", description: "Search query (Chinese supported)" },
110
+ eval: { type: "boolean", description: "Enable decision-model semantic re-ranking" },
111
+ },
112
+ required: ["query"],
113
+ },
114
+ execute: (a) => {
115
+ const parts = ["kb", "search", String(a.query)];
116
+ if (a.eval)
117
+ parts.push("--eval");
118
+ return cliJson(parts);
119
+ },
120
+ },
121
+ {
122
+ name: "claim_evaluate",
123
+ description: "Decision model evaluates a claim's confidence (score 0-5 → grade A/B/C/D).",
124
+ inputSchema: {
125
+ type: "object",
126
+ properties: { claim_id: { type: "string", description: "Claim ID to evaluate" } },
127
+ required: ["claim_id"],
128
+ },
129
+ execute: (a) => cliJson(["research", "claim", "evaluate", String(a.claim_id)]),
130
+ },
131
+ {
132
+ name: "tree_state",
133
+ description: "All trees with node states (locked/unlocked). Visualize the dependency graph.",
134
+ inputSchema: {
135
+ type: "object",
136
+ properties: { tree: { type: "string", description: "Optional tree name (omit for all)" } },
137
+ },
138
+ execute: (a) => cliJson(["node", "list", ...(a.tree ? [String(a.tree)] : [])]),
139
+ },
140
+ {
141
+ name: "produce_report",
142
+ description: "Assemble claims + evidence into a markdown report. Returns report ID and content.",
143
+ inputSchema: { type: "object", properties: {} },
144
+ execute: () => cliJson(["produce", "report"]),
145
+ },
146
+ {
147
+ name: "doctor",
148
+ description: "9-item workspace health check. Pass fix=true to auto-fix safe issues.",
149
+ inputSchema: {
150
+ type: "object",
151
+ properties: { fix: { type: "boolean", description: "Auto-fix dirty index + stale locks" } },
152
+ },
153
+ execute: (a) => cliJson(["doctor", ...(a.fix ? ["--fix"] : [])]),
154
+ },
155
+ {
156
+ name: "task_advance",
157
+ description: "Advance a task through the state machine: todo → doing → done (or roll back).",
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: {
161
+ task_id: { type: "string", description: "Task artifact ID" },
162
+ action: { type: "string", enum: ["doing", "done", "todo"], description: "Target status" },
163
+ },
164
+ required: ["task_id", "action"],
165
+ },
166
+ execute: (a) => cliJson(["task", String(a.action), String(a.task_id)]),
167
+ },
168
+ ];
169
+ }
170
+ /** Run the MCP server on stdio. */
171
+ function serveMcp() {
172
+ const tools = buildTools();
173
+ const rl = readline.createInterface({ input: process.stdin });
174
+ const respond = (id, result) => {
175
+ process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, result }) + "\n");
176
+ };
177
+ const respondErr = (id, code, message) => {
178
+ process.stdout.write(JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } }) + "\n");
179
+ };
180
+ rl.on("line", (line) => {
181
+ if (!line.trim())
182
+ return;
183
+ let msg;
184
+ try {
185
+ msg = JSON.parse(line);
186
+ }
187
+ catch {
188
+ return;
189
+ }
190
+ const { id, method, params } = msg;
191
+ switch (method) {
192
+ case "initialize":
193
+ respond(id, {
194
+ protocolVersion: "2024-11-05",
195
+ capabilities: { tools: {} },
196
+ serverInfo: { name: "ygl-trees", version: "0.69.0" },
197
+ });
198
+ break;
199
+ case "tools/list":
200
+ respond(id, {
201
+ tools: tools.map((t) => ({
202
+ name: t.name,
203
+ description: t.description,
204
+ inputSchema: t.inputSchema,
205
+ })),
206
+ });
207
+ break;
208
+ case "tools/call": {
209
+ const name = params?.name;
210
+ const tool = tools.find((t) => t.name === name);
211
+ if (!tool) {
212
+ respondErr(id, -32602, `Unknown tool: ${name}`);
213
+ break;
214
+ }
215
+ tool
216
+ .execute(params?.arguments || {})
217
+ .then((data) => respond(id, { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }))
218
+ .catch((e) => respond(id, {
219
+ content: [{ type: "text", text: `Error: ${e?.message || e}` }],
220
+ isError: true,
221
+ }));
222
+ break;
223
+ }
224
+ case "ping":
225
+ respond(id, {});
226
+ break;
227
+ default:
228
+ if (id !== undefined)
229
+ respondErr(id, -32601, `Method not found: ${method}`);
230
+ }
231
+ });
232
+ process.stderr.write("[ygl-trees MCP] stdio server ready — 8 tools\n");
233
+ }
package/llms.txt CHANGED
@@ -1,4 +1,4 @@
1
- # ygl-trees v0.65.0 — AI Agent Research Workbench
1
+ # ygl-trees v0.69.0 — AI Agent Research Workbench
2
2
 
3
3
  > Single SQLite source of truth. Research → Production → Knowledge Reuse + Tech Tree.
4
4
  > CLI for AI agents: every command supports --json (machine-readable, including errors).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ygl-trees",
3
- "version": "0.68.0",
3
+ "version": "0.69.0",
4
4
  "description": "猿光 · 科技树 — database-centric CLI for research → production → knowledge reuse, built for AI agents.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/apps/cli/index.js",
@@ -26,8 +26,8 @@
26
26
  "typeorm": "^1.1.2",
27
27
  "@deepseek-ai/cordis": "~4.0.5-alpha.2",
28
28
  "@deepseek-ai/cordis-plugin-timer": "~1.1.7-alpha.2",
29
- "@deepseek-ai/schemastery": "~3.18.5-alpha.2",
30
- "@deepseek-ai/cosmokit": "~1.8.6-alpha.2"
29
+ "@deepseek-ai/cosmokit": "~1.8.6-alpha.2",
30
+ "@deepseek-ai/schemastery": "~3.18.5-alpha.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@types/node": "^20.0.0",