ppxans-harness 2.6.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +195 -195
  3. package/bin/ppx-channels.js +2 -2
  4. package/bin/ppx-serve.js +5 -5
  5. package/bin/ppx-setup.js +124 -0
  6. package/bin/ppx-web.js +140 -0
  7. package/bin/ppx.js +2 -2
  8. package/config/identity.md +6 -6
  9. package/config/ishiki.md +16 -16
  10. package/config/ppx.json +6 -124
  11. package/config/ppx.json.example +143 -0
  12. package/package.json +16 -6
  13. package/skills/.usage.json +6 -0
  14. package/skills/agent-professional-training/SKILL.md +94 -0
  15. package/skills/agent-professional-training/trajectories/2026-09-11-dpo-pairs.jsonl +2 -0
  16. package/skills/agent-professional-training/trajectories/2026-09-11-round2-trajectory.json +15 -0
  17. package/skills/agent-professional-training/trajectories/2026-09-13-first-run-trajectory.json +17 -0
  18. package/skills/brainstorm/SKILL.md +24 -0
  19. package/skills/cupid-lover-comms/SKILL.md +37 -0
  20. package/skills/debug/SKILL.md +26 -0
  21. package/skills/plan/SKILL.md +25 -0
  22. package/skills/ponytail/SKILL.md +25 -0
  23. package/skills/ppx-memory/SKILL.md +91 -0
  24. package/skills/ppx-memory/scripts/cli.js +192 -0
  25. package/skills/ppx-memory/scripts/experience.js +133 -0
  26. package/skills/ppx-memory/scripts/fact-store.js +842 -0
  27. package/skills/ppx-memory/scripts/l0.js +52 -0
  28. package/skills/ppx-memory/scripts/l2.js +146 -0
  29. package/skills/ppx-memory/scripts/l3.js +112 -0
  30. package/skills/ppx-memory/scripts/memory-ticker.js +238 -0
  31. package/skills/ppx-memory/scripts/pii.js +42 -0
  32. package/skills/ppx-memory/scripts/schema.js +80 -0
  33. package/skills/ppx-memory/scripts/session.js +398 -0
  34. package/skills/ppx-memory/scripts/similarity.js +43 -0
  35. package/skills/ppx-memory/scripts/store.js +116 -0
  36. package/skills/ppx-memory/scripts/wal.js +38 -0
  37. package/skills/ppx-selfheal/SKILL.md +24 -0
  38. package/skills/ppx-selfheal/scripts/cli.js +80 -0
  39. package/skills/ppx-selfheal/scripts/healer.js +184 -0
  40. package/skills/ppx-selfheal/scripts/logger.js +17 -0
  41. package/skills/ppx-selfheal/scripts/store.js +116 -0
  42. package/skills/prompt-depth-kit/SKILL.md +28 -0
  43. package/skills/session-naming/SKILL.md +36 -0
  44. package/skills/verify/SKILL.md +25 -0
  45. package/src/agent/index.js +1352 -717
  46. package/src/agent/prompts.js +46 -2
  47. package/src/aml-server.js +197 -151
  48. package/src/ans/eviction.js +123 -143
  49. package/src/ans/guard.js +159 -120
  50. package/src/ans/lifecycle.js +96 -93
  51. package/src/ans/proactive.js +112 -129
  52. package/src/ans/reward.js +95 -111
  53. package/src/ans/values.js +15 -15
  54. package/src/audit/audit-chain.js +43 -7
  55. package/src/audit/verifier.js +157 -120
  56. package/src/bus/circuit-breaker.js +9 -1
  57. package/src/bus/runtime-bus.js +107 -93
  58. package/src/channels/base.js +57 -34
  59. package/src/channels/feishu.js +118 -126
  60. package/src/channels/http.js +1090 -651
  61. package/src/channels/index.js +111 -110
  62. package/src/channels/log.js +29 -29
  63. package/src/channels/wechat-crypto.js +73 -74
  64. package/src/channels/wechat.js +191 -197
  65. package/src/channels/workspace.js +94 -0
  66. package/src/channels-cli.js +126 -124
  67. package/src/cli.js +129 -120
  68. package/src/commands/index.js +142 -0
  69. package/src/config/channels.js +137 -170
  70. package/src/config/index.js +277 -224
  71. package/src/config/placeholder.js +31 -0
  72. package/src/config/providers.js +148 -182
  73. package/src/config/settings.js +156 -182
  74. package/src/core/policy.js +69 -18
  75. package/src/core/trace.js +8 -6
  76. package/src/edit/editblock.js +266 -0
  77. package/src/edit/snapshot.js +67 -0
  78. package/src/evidence/index.js +153 -0
  79. package/src/evolve/playbook.js +9 -10
  80. package/src/hooks/index.js +113 -0
  81. package/src/llm/client.js +4 -3
  82. package/src/llm/dsml.js +74 -74
  83. package/src/llm/embedder.js +41 -35
  84. package/src/llm/fence.js +52 -52
  85. package/src/llm/index.js +4 -4
  86. package/src/llm/local-embedder.js +94 -0
  87. package/src/llm/presets.js +113 -0
  88. package/src/llm/pricing.js +93 -0
  89. package/src/llm/retry.js +73 -73
  90. package/src/llm/router.js +92 -89
  91. package/src/mcp/admin.js +44 -10
  92. package/src/mcp/client.js +487 -477
  93. package/src/mcp/http.js +23 -37
  94. package/src/mcp/index.js +116 -116
  95. package/src/mcp/server.js +23 -18
  96. package/src/mcp/tasks.js +9 -14
  97. package/src/memory/asset-hub.js +6 -11
  98. package/src/memory/canvas.js +2 -5
  99. package/src/memory/compaction.js +28 -28
  100. package/src/memory/experience.js +133 -122
  101. package/src/memory/fact-store.js +914 -698
  102. package/src/memory/failure-episode.js +20 -11
  103. package/src/memory/fork.js +17 -8
  104. package/src/memory/index.js +8 -6
  105. package/src/memory/l0.js +53 -52
  106. package/src/memory/l2.js +145 -130
  107. package/src/memory/l3.js +111 -111
  108. package/src/memory/legion-board.js +71 -0
  109. package/src/memory/memory-ticker.js +239 -240
  110. package/src/memory/session.js +398 -397
  111. package/src/memory/sqlite-store.js +581 -0
  112. package/src/mode/blackboard.js +49 -49
  113. package/src/mode/graph.js +42 -41
  114. package/src/mode/index.js +64 -64
  115. package/src/mode/legion.js +54 -51
  116. package/src/mode/plan-exec.js +50 -50
  117. package/src/mode/router.js +28 -40
  118. package/src/orchestrator/agent-worker.js +69 -69
  119. package/src/orchestrator/dag.js +90 -83
  120. package/src/orchestrator/experts.js +76 -0
  121. package/src/orchestrator/index.js +1 -1
  122. package/src/orchestrator/legion.js +179 -187
  123. package/src/orchestrator/supervisor.js +6 -8
  124. package/src/permissions/index.js +378 -0
  125. package/src/persona/index.js +28 -29
  126. package/src/plugin/builtin.js +313 -215
  127. package/src/plugin/context.js +80 -79
  128. package/src/plugin/index.js +62 -62
  129. package/src/plugin/v3.js +73 -0
  130. package/src/protocol/index.js +148 -0
  131. package/src/repomap/index.js +309 -0
  132. package/src/review/index.js +393 -0
  133. package/src/seam/registry.js +3 -0
  134. package/src/seam/shell.js +55 -55
  135. package/src/security/injection.js +79 -0
  136. package/src/selfheal/evolve.js +67 -67
  137. package/src/selfheal/healer.js +184 -167
  138. package/src/selfheal/run.js +9 -9
  139. package/src/server.js +63 -60
  140. package/src/services/diagnose.js +180 -0
  141. package/src/services/learning-service.js +9 -0
  142. package/src/services/memory-health.js +34 -6
  143. package/src/services/memory-service.js +42 -9
  144. package/src/services/triage.js +138 -0
  145. package/src/session/parts.js +76 -0
  146. package/src/session/projection.js +73 -0
  147. package/src/session/rollout.js +54 -0
  148. package/src/session/turn.js +137 -0
  149. package/src/skills/lint.js +72 -0
  150. package/src/skills/loader.js +231 -150
  151. package/src/skills/search.js +58 -0
  152. package/src/skills/verify.js +95 -100
  153. package/src/tools/advanced.js +388 -352
  154. package/src/tools/builtin.js +384 -297
  155. package/src/tools/catalog.js +283 -159
  156. package/src/tools/command-guard.js +112 -112
  157. package/src/tools/custom.js +47 -47
  158. package/src/tools/delegate.js +383 -297
  159. package/src/tools/document.js +254 -253
  160. package/src/tools/git.js +151 -0
  161. package/src/tools/governance.js +47 -20
  162. package/src/tools/index.js +16 -11
  163. package/src/tools/methods.js +178 -178
  164. package/src/tools/ocr.js +59 -59
  165. package/src/tools/sandbox-worker.js +40 -0
  166. package/src/tools/sandbox.js +92 -0
  167. package/src/tools/seam.js +162 -125
  168. package/src/tools/selfmod.js +196 -176
  169. package/src/tools/v3.js +225 -0
  170. package/src/tools/vad.js +176 -0
  171. package/src/tools/voice.js +238 -0
  172. package/src/utils/async.js +14 -0
  173. package/src/utils/config-file.js +53 -0
  174. package/src/utils/crashguard.js +88 -0
  175. package/src/utils/http.js +53 -0
  176. package/src/utils/id.js +8 -0
  177. package/src/utils/json-state.js +33 -0
  178. package/src/utils/logger.js +17 -17
  179. package/src/utils/ndjson.js +25 -0
  180. package/src/utils/pii.js +42 -42
  181. package/src/utils/rate-limit.js +50 -0
  182. package/src/utils/schema.js +80 -0
  183. package/src/utils/similarity.js +43 -0
  184. package/src/utils/store.js +170 -108
  185. package/src/utils/text.js +15 -15
  186. package/src/utils/trace.js +153 -153
  187. package/src/utils/wal.js +39 -0
  188. package/src/utils/winutf8.js +16 -15
  189. package/src/wiki/index.js +170 -0
@@ -1,122 +1,133 @@
1
- // src/memory/experience.js - 经验库 (自学习)
2
- // 从每次任务结果中提炼经验, 供后续任务参考 (参考 openhanako experience)
3
- // 跨 agent 共享: 支持全局经验目录 (globalDataDir), 写入用文件锁防并发覆盖
4
- // v1.0.7: 同义经验相似合并 (bigram overlap, 词序/措辞变体命中合并而非新增)
5
- import path from "node:path";
6
- import { ensureDir, readJson, writeJson, nowISO, withFileLock } from "../utils/store.js";
7
-
8
- // 同义合并阈值: 经验 lesson 的 bigram overlap 达到此值视为同一条
9
- // 用真实生产变体校准: 同义改写 0.50-0.55, 相关但不同 0.29, 不相关 0.0 → 0.5 能抓同义不误伤
10
- const SIM_THRESHOLD = 0.5;
11
-
12
- // bigram 集合 (去空白, 中文按字符)
13
- function _bigrams(s) {
14
- const chars = Array.from(String(s).replace(/\s+/g, ""));
15
- const out = new Set();
16
- for (let i = 0; i < chars.length - 1; i++) out.add(chars[i] + chars[i + 1]);
17
- return out;
18
- }
19
-
20
- // overlap 系数: 交集 / 较短者 bigram 数 (对词序变化容忍, 与 FactStore._overlap 同思路)
21
- export function lessonOverlap(a, b) {
22
- const A = _bigrams(a), B = _bigrams(b);
23
- if (!A.size || !B.size) return 0;
24
- let inter = 0;
25
- for (const x of A) if (B.has(x)) inter++;
26
- return inter / Math.min(A.size, B.size);
27
- }
28
-
29
- // 模板句判定: 去掉数字后完全相同 (如 "A 经验教训 0" vs "A 经验教训 1")
30
- // 这类"仅编号不同"的条目是不同内容, 不参与同义合并 (防误伤)
31
- function _isTemplateLike(a, b) {
32
- return String(a).replace(/\d+/g, "#") === String(b).replace(/\d+/g, "#");
33
- }
34
-
35
- export class Experience {
36
- constructor(dataDir) {
37
- this.dir = path.join(dataDir, "experience");
38
- ensureDir(this.dir);
39
- this.file = path.join(this.dir, "lessons.json");
40
- this.lessons = readJson(this.file, []);
41
- }
42
-
43
- learn({ task, outcome, lesson, tags = [] }) {
44
- const entry = {
45
- id: "e_" + Math.random().toString(36).slice(2, 10),
46
- task: String(task || "").slice(0, 300),
47
- outcome: String(outcome || "").slice(0, 300),
48
- lesson: String(lesson || "").slice(0, 500),
49
- tags,
50
- ts: nowISO(),
51
- uses: 0,
52
- };
53
- if (!entry.lesson || entry.lesson.length < 5) return null;
54
- // 内容去重: 同一 lesson 已存在则命中加分 (uses+1) 而非新增, 防高频学习路径写放大
55
- // 归一化: 去首尾空白 + 折叠连续空白 (与 FactStore._norm 同策略)
56
- const normKey = String(lesson).trim().replace(/\s+/g, " ");
57
- // 锁内读-改-写: 防止多 agent 共享经验库时并发覆盖
58
- return withFileLock(this.file, () => {
59
- this.lessons = readJson(this.file, []);
60
- const existing = this.lessons.find((l) => String(l.lesson || "").trim().replace(/\s+/g, " ") === normKey);
61
- if (existing) {
62
- existing.uses += 1;
63
- existing.ts = nowISO(); // 刷新时间, 让近期命中经验排到 context 前面
64
- writeJson(this.file, this.lessons);
65
- return existing;
66
- }
67
- // 同义合并 (v1.0.7): 措辞/词序不同的变体 (逃过精确去重) 语义相似时合并, 防同义经验堆积
68
- // 排除"仅编号不同"的模板句 (如 A 经验教训 0/1 → 视为不同条目)
69
- const similar = this.lessons.find((l) => {
70
- const la = String(l.lesson || "");
71
- if (_isTemplateLike(la, entry.lesson)) return false;
72
- return lessonOverlap(la, entry.lesson) >= SIM_THRESHOLD;
73
- });
74
- if (similar) {
75
- similar.uses += 1;
76
- similar.ts = nowISO();
77
- writeJson(this.file, this.lessons);
78
- return similar;
79
- }
80
- this.lessons.push(entry);
81
- this._prune();
82
- writeJson(this.file, this.lessons);
83
- return entry;
84
- });
85
- }
86
-
87
- recall(taskDesc) {
88
- const q = String(taskDesc || "").toLowerCase();
89
- const scored = this.lessons
90
- .map((l) => {
91
- let s = 0;
92
- const hay = (l.lesson + " " + l.task + " " + l.tags.join(" ")).toLowerCase();
93
- if (q && hay.includes(q)) s += 10;
94
- if (l.uses > 0) s += Math.min(l.uses, 5);
95
- return { ...l, score: s };
96
- })
97
- .filter((l) => l.score > 0)
98
- .sort((a, b) => b.score - a.score);
99
- return scored.slice(0, 5);
100
- }
101
-
102
- use(id) {
103
- withFileLock(this.file, () => {
104
- this.lessons = readJson(this.file, []);
105
- const l = this.lessons.find((x) => x.id === id);
106
- if (l) { l.uses += 1; writeJson(this.file, this.lessons); }
107
- });
108
- }
109
-
110
- _prune() {
111
- // 最多保留 200 条
112
- if (this.lessons.length > 200) {
113
- this.lessons.sort((a, b) => b.uses - a.uses);
114
- this.lessons = this.lessons.slice(0, 200);
115
- }
116
- }
117
-
118
- context() {
119
- const recent = [...this.lessons].sort((a, b) => new Date(b.ts) - new Date(a.ts)).slice(0, 5);
120
- return recent.map((l) => `- 经验: ${l.lesson}`).join("\n") || "(暂无经验)";
121
- }
122
- }
1
+ // src/memory/experience.js - 经验库 (自学习)
2
+ // 从每次任务结果中提炼经验, 供后续任务参考 (参考 openhanako experience)
3
+ // 跨 agent 共享: 支持全局经验目录 (globalDataDir), 写入用文件锁防并发覆盖
4
+ // v1.0.7: 同义经验相似合并 (bigram overlap, 词序/措辞变体命中合并而非新增)
5
+ import path from "node:path";
6
+ import { ensureDir, readJson, writeJson, nowISO, withFileLock } from "../utils/store.js";
7
+ import { overlapCoefficient } from "../utils/similarity.js";
8
+
9
+ // 同义合并阈值: 经验 lesson 的 bigram overlap 达到此值视为同一条
10
+ // 用真实生产变体校准: 同义改写 0.50-0.55, 相关但不同 0.29, 不相关 0.0 → 0.5 能抓同义不误伤
11
+ const SIM_THRESHOLD = 0.5;
12
+
13
+ // overlap 系数 (交集 / 较短者): 对词序变化容忍, 实现收敛到 utils/similarity
14
+ // (与 FactStore._overlap 同思路, 但分词/阈值各自独立)
15
+ export const lessonOverlap = overlapCoefficient;
16
+
17
+ // 模板句判定: 去掉数字后完全相同 (如 "A 经验教训 0" vs "A 经验教训 1")
18
+ // 这类"仅编号不同"的条目是不同内容, 不参与同义合并 (防误伤)
19
+ function _isTemplateLike(a, b) {
20
+ return String(a).replace(/\d+/g, "#") === String(b).replace(/\d+/g, "#");
21
+ }
22
+
23
+ export class Experience {
24
+ constructor(dataDir) {
25
+ this.dir = path.join(dataDir, "experience");
26
+ ensureDir(this.dir);
27
+ this.file = path.join(this.dir, "lessons.json");
28
+ this.lessons = readJson(this.file, []);
29
+ }
30
+
31
+ learn({ task, outcome, lesson, tags = [] }) {
32
+ const entry = {
33
+ id: "e_" + Math.random().toString(36).slice(2, 10),
34
+ task: String(task || "").slice(0, 300),
35
+ outcome: String(outcome || "").slice(0, 300),
36
+ lesson: String(lesson || "").slice(0, 500),
37
+ tags,
38
+ ts: nowISO(),
39
+ uses: 0,
40
+ };
41
+ if (!entry.lesson || entry.lesson.length < 5) return null;
42
+ // 内容去重: 同一 lesson 已存在则命中加分 (uses+1) 而非新增, 防高频学习路径写放大
43
+ // 归一化: 去首尾空白 + 折叠连续空白 (与 FactStore._norm 同策略)
44
+ const normKey = String(lesson).trim().replace(/\s+/g, " ");
45
+ // 锁内读-改-写: 防止多 agent 共享经验库时并发覆盖
46
+ return withFileLock(this.file, () => {
47
+ this.lessons = readJson(this.file, []);
48
+ const existing = this.lessons.find((l) => String(l.lesson || "").trim().replace(/\s+/g, " ") === normKey);
49
+ if (existing) {
50
+ existing.uses += 1;
51
+ existing.ts = nowISO(); // 刷新时间, 让近期命中经验排到 context 前面
52
+ writeJson(this.file, this.lessons);
53
+ return existing;
54
+ }
55
+ // 同义合并 (v1.0.7): 措辞/词序不同的变体 (逃过精确去重) 语义相似时合并, 防同义经验堆积
56
+ // 排除"仅编号不同"的模板句 (如 A 经验教训 0/1 → 视为不同条目)
57
+ const similar = this.lessons.find((l) => {
58
+ const la = String(l.lesson || "");
59
+ if (_isTemplateLike(la, entry.lesson)) return false;
60
+ return lessonOverlap(la, entry.lesson) >= SIM_THRESHOLD;
61
+ });
62
+ if (similar) {
63
+ similar.uses += 1;
64
+ similar.ts = nowISO();
65
+ writeJson(this.file, this.lessons);
66
+ return similar;
67
+ }
68
+ this.lessons.push(entry);
69
+ this._prune();
70
+ writeJson(this.file, this.lessons);
71
+ return entry;
72
+ });
73
+ }
74
+
75
+ recall(taskDesc) {
76
+ const q = String(taskDesc || "").toLowerCase();
77
+ const scored = this.lessons
78
+ .map((l) => {
79
+ let s = 0;
80
+ const hay = (l.lesson + " " + l.task + " " + l.tags.join(" ")).toLowerCase();
81
+ if (q && hay.includes(q)) s += 10;
82
+ if (l.uses > 0) s += Math.min(l.uses, 5);
83
+ return { ...l, score: s };
84
+ })
85
+ .filter((l) => l.score > 0)
86
+ .sort((a, b) => b.score - a.score);
87
+ return scored.slice(0, 5);
88
+ }
89
+
90
+ use(id) {
91
+ withFileLock(this.file, () => {
92
+ this.lessons = readJson(this.file, []);
93
+ const l = this.lessons.find((x) => x.id === id);
94
+ if (l) { l.uses += 1; writeJson(this.file, this.lessons); }
95
+ });
96
+ }
97
+
98
+ // 经验清单 (公开读 API): 默认按命中次数降序, 同次数按时间新→旧
99
+ // 供 fork 快照 / 外部观测使用 (调用方无需触碰 this.lessons 内部数组)
100
+ list({ limit = 0, sort = "uses" } = {}) {
101
+ const all = [...this.lessons];
102
+ if (sort === "uses") {
103
+ all.sort((a, b) => (b.uses || 0) - (a.uses || 0) || new Date(b.ts || 0) - new Date(a.ts || 0));
104
+ } else if (sort === "ts") {
105
+ all.sort((a, b) => new Date(b.ts || 0) - new Date(a.ts || 0));
106
+ }
107
+ const n = Number(limit) || 0;
108
+ return n > 0 ? all.slice(0, n) : all;
109
+ }
110
+
111
+ // 条目数 (可观测)
112
+ count() {
113
+ return this.lessons.length;
114
+ }
115
+
116
+ _prune() {
117
+ // 最多保留 200 条
118
+ if (this.lessons.length > 200) {
119
+ this.lessons.sort((a, b) => b.uses - a.uses);
120
+ this.lessons = this.lessons.slice(0, 200);
121
+ }
122
+ }
123
+
124
+ context() {
125
+ // 优先命中次数 (高频教训浮上来, 让反复发生的硬拒绝/跨会话坑真正影响行为),
126
+ // 同次数按时间新→旧 (近期教训仍可见)。蒸馏接缝: B3 auto-self-review 教训 uses 随复发上涨,
127
+ // 从而在上下文里越来越突出, 形成「经验→长期准则」的浮升链路。
128
+ const picked = [...this.lessons]
129
+ .sort((a, b) => (b.uses || 0) - (a.uses || 0) || new Date(b.ts || 0) - new Date(a.ts || 0))
130
+ .slice(0, 5);
131
+ return picked.map((l) => `- 经验: ${l.lesson}`).join("\n") || "(暂无经验)";
132
+ }
133
+ }