@bolloon/bolloon-agent 0.5.5 → 0.6.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 (158) hide show
  1. package/dist/agents/execution-entry.js +10 -0
  2. package/dist/agents/goal-flywheel/wiring/seams.js +5 -1
  3. package/dist/agents/parse-tool-call.js +6 -1
  4. package/dist/agents/pi-sdk-session-factory.js +36 -3
  5. package/dist/agents/pi-sdk-tools.js +18 -8
  6. package/dist/agents/pi-sdk.js +749 -1390
  7. package/dist/agents/run-context.js +20 -0
  8. package/dist/agents/runner-resolver.js +3 -1
  9. package/dist/agents/tool-capability/index.js +51 -0
  10. package/dist/agents/workflow-pivot-loop.js +31 -10
  11. package/dist/agents/write-verify.js +60 -0
  12. package/dist/bollharness-integration/integration.js +8 -0
  13. package/dist/bollharness-integration/skill-adapter.js +32 -3
  14. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js +5 -1
  15. package/dist/electron-build/agents/goal-flywheel/wiring/seams.js.map +1 -1
  16. package/dist/electron-build/agents/parse-tool-call.js +6 -1
  17. package/dist/electron-build/agents/parse-tool-call.js.map +1 -1
  18. package/dist/electron-build/agents/pi-sdk-session-factory.js +36 -3
  19. package/dist/electron-build/agents/pi-sdk-session-factory.js.map +1 -1
  20. package/dist/electron-build/agents/pi-sdk-tools.js +21 -11
  21. package/dist/electron-build/agents/pi-sdk-tools.js.map +1 -1
  22. package/dist/electron-build/agents/pi-sdk-types.js.map +1 -1
  23. package/dist/electron-build/agents/pi-sdk.js +750 -1389
  24. package/dist/electron-build/agents/pi-sdk.js.map +1 -1
  25. package/dist/electron-build/agents/run-context.js +24 -0
  26. package/dist/electron-build/agents/run-context.js.map +1 -0
  27. package/dist/electron-build/agents/runner-resolver.js +3 -1
  28. package/dist/electron-build/agents/runner-resolver.js.map +1 -1
  29. package/dist/electron-build/agents/tool-capability/index.js +90 -0
  30. package/dist/electron-build/agents/tool-capability/index.js.map +1 -0
  31. package/dist/electron-build/agents/workflow-pivot-loop.js +31 -10
  32. package/dist/electron-build/agents/workflow-pivot-loop.js.map +1 -1
  33. package/dist/electron-build/agents/write-verify.js +99 -0
  34. package/dist/electron-build/agents/write-verify.js.map +1 -0
  35. package/dist/electron-build/bollharness-integration/integration.js +8 -0
  36. package/dist/electron-build/bollharness-integration/integration.js.map +1 -1
  37. package/dist/electron-build/bollharness-integration/skill-adapter.js +32 -3
  38. package/dist/electron-build/bollharness-integration/skill-adapter.js.map +1 -1
  39. package/dist/electron-build/kernel/channel-actor.js +339 -0
  40. package/dist/electron-build/kernel/channel-actor.js.map +1 -0
  41. package/dist/electron-build/kernel/control.js +102 -0
  42. package/dist/electron-build/kernel/control.js.map +1 -0
  43. package/dist/electron-build/kernel/model-runtime.js +508 -0
  44. package/dist/electron-build/kernel/model-runtime.js.map +1 -0
  45. package/dist/electron-build/kernel/run-lifecycle.js +146 -0
  46. package/dist/electron-build/kernel/run-lifecycle.js.map +1 -0
  47. package/dist/electron-build/kernel/transport.js +119 -0
  48. package/dist/electron-build/kernel/transport.js.map +1 -0
  49. package/dist/electron-build/llm/native-adapter.js +122 -0
  50. package/dist/electron-build/llm/native-adapter.js.map +1 -0
  51. package/dist/index.js +43 -19
  52. package/dist/ios/bolloon-web.json +3 -3
  53. package/dist/ios/client.js +13 -7
  54. package/dist/ios/mobile-core.js +7762 -6289
  55. package/dist/ios/mobile.js +64 -0
  56. package/dist/ios/routes-mobile-tasks.js +2 -1
  57. package/dist/ios/routes-tasks.js +16 -1
  58. package/dist/ios/routes-x402-info.js +28 -1
  59. package/dist/ios/server-storage.js +26 -5
  60. package/dist/ios/server.js +840 -862
  61. package/dist/ios/sw.js +1 -1
  62. package/dist/ios/ui/message-renderer.js +473 -29
  63. package/dist/ios/ui/step-timeline.js +13 -12
  64. package/dist/kernel/channel-actor.js +321 -0
  65. package/dist/kernel/control.js +95 -0
  66. package/dist/kernel/gate-scan.js +1350 -0
  67. package/dist/kernel/model-runtime.js +494 -0
  68. package/dist/kernel/plan-channel-actor.js +305 -0
  69. package/dist/kernel/plan-communication.js +163 -0
  70. package/dist/kernel/plan-constraint.js +152 -0
  71. package/dist/kernel/plan-deletion.js +32 -0
  72. package/dist/kernel/plan-harness.js +78 -0
  73. package/dist/kernel/plan-modelruntime.js +60 -0
  74. package/dist/kernel/plan-runcontext.js +163 -0
  75. package/dist/kernel/plan.js +149 -0
  76. package/dist/kernel/roster.js +244 -0
  77. package/dist/kernel/run-lifecycle.js +138 -0
  78. package/dist/kernel/transport.js +111 -0
  79. package/dist/llm/native-adapter.js +117 -0
  80. package/dist/web/bolloon-web.json +3 -3
  81. package/dist/web/client.js +12 -7
  82. package/dist/web/routes-tasks.js +16 -1
  83. package/dist/web/server.js +838 -862
  84. package/dist/web/sw.js +1 -1
  85. package/dist/web/ui/message-renderer.js +473 -29
  86. package/dist/web/ui/step-timeline.js +13 -12
  87. package/package.json +1 -1
  88. package/scripts/build-web.ts +74 -1
  89. package/dist/constraint-runtime/_archive_helper.d.ts +0 -1
  90. package/dist/constraint-runtime/_archive_helper.js +0 -9
  91. package/dist/constraint-runtime/assistant/index.d.ts +0 -11
  92. package/dist/constraint-runtime/assistant/index.js +0 -12
  93. package/dist/constraint-runtime/bootstrap/index.d.ts +0 -11
  94. package/dist/constraint-runtime/bootstrap/index.js +0 -12
  95. package/dist/constraint-runtime/bridge/index.d.ts +0 -11
  96. package/dist/constraint-runtime/bridge/index.js +0 -12
  97. package/dist/constraint-runtime/buddy/index.d.ts +0 -11
  98. package/dist/constraint-runtime/buddy/index.js +0 -12
  99. package/dist/constraint-runtime/cli/index.d.ts +0 -11
  100. package/dist/constraint-runtime/cli/index.js +0 -12
  101. package/dist/constraint-runtime/components/index.d.ts +0 -11
  102. package/dist/constraint-runtime/components/index.js +0 -12
  103. package/dist/constraint-runtime/constants/index.d.ts +0 -11
  104. package/dist/constraint-runtime/constants/index.js +0 -12
  105. package/dist/constraint-runtime/coordinator/index.d.ts +0 -11
  106. package/dist/constraint-runtime/coordinator/index.js +0 -12
  107. package/dist/constraint-runtime/cost_hook.d.ts +0 -2
  108. package/dist/constraint-runtime/cost_hook.js +0 -4
  109. package/dist/constraint-runtime/entrypoints/index.d.ts +0 -11
  110. package/dist/constraint-runtime/entrypoints/index.js +0 -12
  111. package/dist/constraint-runtime/execution_registry.d.ts +0 -20
  112. package/dist/constraint-runtime/execution_registry.js +0 -44
  113. package/dist/constraint-runtime/hooks/index.d.ts +0 -11
  114. package/dist/constraint-runtime/hooks/index.js +0 -12
  115. package/dist/constraint-runtime/ink.d.ts +0 -1
  116. package/dist/constraint-runtime/ink.js +0 -4
  117. package/dist/constraint-runtime/keybindings/index.d.ts +0 -11
  118. package/dist/constraint-runtime/keybindings/index.js +0 -12
  119. package/dist/constraint-runtime/memdir/index.d.ts +0 -11
  120. package/dist/constraint-runtime/memdir/index.js +0 -12
  121. package/dist/constraint-runtime/migrations/index.d.ts +0 -11
  122. package/dist/constraint-runtime/migrations/index.js +0 -12
  123. package/dist/constraint-runtime/moreright/index.d.ts +0 -11
  124. package/dist/constraint-runtime/moreright/index.js +0 -12
  125. package/dist/constraint-runtime/native_ts/index.d.ts +0 -11
  126. package/dist/constraint-runtime/native_ts/index.js +0 -12
  127. package/dist/constraint-runtime/output_styles/index.d.ts +0 -11
  128. package/dist/constraint-runtime/output_styles/index.js +0 -12
  129. package/dist/constraint-runtime/plugins/index.d.ts +0 -11
  130. package/dist/constraint-runtime/plugins/index.js +0 -12
  131. package/dist/constraint-runtime/port_manifest.d.ts +0 -7
  132. package/dist/constraint-runtime/port_manifest.js +0 -11
  133. package/dist/constraint-runtime/query.d.ts +0 -6
  134. package/dist/constraint-runtime/query.js +0 -1
  135. package/dist/constraint-runtime/remote/index.d.ts +0 -11
  136. package/dist/constraint-runtime/remote/index.js +0 -12
  137. package/dist/constraint-runtime/schemas/index.d.ts +0 -11
  138. package/dist/constraint-runtime/schemas/index.js +0 -12
  139. package/dist/constraint-runtime/screens/index.d.ts +0 -11
  140. package/dist/constraint-runtime/screens/index.js +0 -12
  141. package/dist/constraint-runtime/server/index.d.ts +0 -11
  142. package/dist/constraint-runtime/server/index.js +0 -12
  143. package/dist/constraint-runtime/services/index.d.ts +0 -11
  144. package/dist/constraint-runtime/services/index.js +0 -12
  145. package/dist/constraint-runtime/state/index.d.ts +0 -11
  146. package/dist/constraint-runtime/state/index.js +0 -12
  147. package/dist/constraint-runtime/system_init.d.ts +0 -1
  148. package/dist/constraint-runtime/system_init.js +0 -20
  149. package/dist/constraint-runtime/types/index.d.ts +0 -11
  150. package/dist/constraint-runtime/types/index.js +0 -12
  151. package/dist/constraint-runtime/upstream_proxy/index.d.ts +0 -11
  152. package/dist/constraint-runtime/upstream_proxy/index.js +0 -12
  153. package/dist/constraint-runtime/utils/index.d.ts +0 -11
  154. package/dist/constraint-runtime/utils/index.js +0 -12
  155. package/dist/constraint-runtime/vim/index.d.ts +0 -11
  156. package/dist/constraint-runtime/vim/index.js +0 -12
  157. package/dist/constraint-runtime/voice/index.d.ts +0 -11
  158. package/dist/constraint-runtime/voice/index.js +0 -12
@@ -0,0 +1,152 @@
1
+ /**
2
+ * **K1 —— constraint-runtime 三层分类名册 (primitives / runtime-adapters / domain-libraries)**
3
+ *
4
+ * 依据: leo 修订版 K1 —— ① 先统计真实 import ② 移除无调用模块 ③ 删假连接/placeholder
5
+ * ④ 领域模块改显式 Tool Provider ⑤ 最后删旧导出与兼容层。**本文件是第 ① 步的产物** (统计 + 分类), 不是删除本身。
6
+ *
7
+ * 判据: src/test/kernel-constraint.test.ts; 纯函数: src/kernel/gate-scan.ts。
8
+ *
9
+ * K1 真读出来的四条事实 (写在这里, 免得下一轮重新发现):
10
+ * · 源码 **94 文件 / 2492 行** (A 15 / B 24 / C 55);
11
+ * · **33 个 ≤20 行的空壳 index.ts** (共 460 行) —— 移植留下的骨架;
12
+ * · **dist/ 是构建产物, 且被 .gitignore 忽略** (从未进 git) — 但它**运行期必需**:
13
+ * 里面除了编译产物还有 `reference_data/*.json` **32 个快照** (tsc 不复制) ⇒ 见 CONSTRAINT_DIST_DATA_JSON;
14
+ * · constraint-runtime **自带的 4 个测试从来不跑** —— 仓里 vitest 配置把整个 constraint-runtime 目录排除在外 (见 vitest.config.ts 的 exclude)。
15
+ */
16
+ /** 三层分类 (A 原语 / B 领域工具 / C 不进 Kernel) + BUILD/META */
17
+ export const CONSTRAINT_RULES = [
18
+ { key: '__pkg_entry__', cls: 'A', why: "包入口公开面 —— 主仓经它拿到的是原语/会话/技能类型 (具体哪个符号见 A_ENTRY_USES)", phase: 'K1' },
19
+ { key: 'src/constraint/', cls: 'A', why: "约束原语: ToolPermissionContext + BudgetTracker (leo 点名的 A 类)", phase: 'K1' },
20
+ { key: 'src/skills/', cls: 'A', why: "SkillRegistry (技能元数据注册; 与执行器分离)", phase: 'K1' },
21
+ { key: 'src/agent/', cls: 'A', why: "AgentCoordinator: 子任务协调原语", phase: 'K1' },
22
+ { key: 'src/thinking/', cls: 'A', why: "DeepThinkingEngine: 推理原语 (K1 里复核是否该归 adapter)", phase: 'K1' },
23
+ { key: 'src/execution_registry.ts', cls: 'A', why: "执行登记 (幂等/在跑)", phase: 'K1' },
24
+ { key: 'src/tool_pool.ts', cls: 'A', why: "工具池 (调度侧; 不负责副作用)", phase: 'K1' },
25
+ { key: 'src/session_store.ts', cls: 'A', why: "Session 存取 (只读纯函数部分; 可变 Session 不在此册)", phase: 'K1' },
26
+ { key: 'src/cost_tracker.ts', cls: 'A', why: "用量计数 (K6 usage 记录会用到)", phase: 'K1' },
27
+ { key: 'src/models.ts', cls: 'A', why: "模型/能力描述 (capability registry)", phase: 'K1' },
28
+ { key: 'src/cost_hook.ts', cls: 'A', why: "用量钩子", phase: 'K1' },
29
+ { key: 'src/tools/WalletTools/', cls: 'B', why: "WalletTools: 经 Tool Capability 接入", phase: 'K7' },
30
+ { key: 'src/tools/SafeSDK/', cls: 'B', why: "SafeSDK", phase: 'K7' },
31
+ { key: 'src/tools/PolymarketSDK/', cls: 'B', why: "PolymarketSDK", phase: 'K7' },
32
+ { key: 'src/tools/OpenCLI/', cls: 'B', why: "OpenCLI", phase: 'K7' },
33
+ { key: 'src/remote/', cls: 'C', why: "remote/ssh/teleport 占位实现 —— 不进核心", phase: '第一批' },
34
+ { key: 'src/remote_runtime.ts', cls: 'C', why: "假连接/假成功的 remote runtime (leo 第一批点名的清理对象)", phase: '第一批' },
35
+ { key: 'src/upstream_proxy/', cls: 'C', why: "上游代理占位", phase: '第一批' },
36
+ { key: 'src/_archive_helper.ts', cls: 'C', why: "archive 辅助 (不进运行时包)", phase: '第一批' },
37
+ { key: 'src/reference_data/', cls: 'C', why: "reference 数据 (不进运行时包)", phase: '第一批' },
38
+ { key: 'src/parity_audit.ts', cls: 'C', why: "迁移期 parity 审计 (一次性)", phase: '第一批' },
39
+ { key: 'src/migrations/', cls: 'C', why: "迁移脚本 (一次性)", phase: '第一批' },
40
+ { key: 'src/native_ts/', cls: 'C', why: "旧移植层 (native ts)", phase: '第一批' },
41
+ { key: 'src/screens/', cls: 'C', why: "TUI 屏", phase: '第一批' },
42
+ { key: 'src/components/', cls: 'C', why: "TUI 组件", phase: '第一批' },
43
+ { key: 'src/keybindings/', cls: 'C', why: "键位表", phase: '第一批' },
44
+ { key: 'src/vim/', cls: 'C', why: "vim 模式", phase: '第一批' },
45
+ { key: 'src/voice/', cls: 'C', why: "语音", phase: '第一批' },
46
+ { key: 'src/output_styles/', cls: 'C', why: "输出样式", phase: '第一批' },
47
+ { key: 'src/moreright/', cls: 'C', why: "终端渲染 (移植层)", phase: '第一批' },
48
+ { key: 'src/buddy/', cls: 'C', why: "彩蛋壳", phase: '第一批' },
49
+ { key: 'src/assistant/', cls: 'C', why: "助手壳", phase: '第一批' },
50
+ { key: 'src/ink.ts', cls: 'C', why: "ink 渲染入口", phase: '第一批' },
51
+ { key: 'src/setup.ts', cls: 'C', why: "移植层 setup", phase: '第一批' },
52
+ { key: 'src/system_init.ts', cls: 'C', why: "移植层初始化", phase: '第一批' },
53
+ { key: 'src/deferred_init.ts', cls: 'C', why: "移植层延迟初始化", phase: '第一批' },
54
+ { key: 'src/bootstrap_graph.ts', cls: 'C', why: "移植层依赖图", phase: '第一批' },
55
+ { key: 'src/bootstrap/', cls: 'C', why: "移植层 bootstrap", phase: '第一批' },
56
+ { key: 'src/command_graph.ts', cls: 'C', why: "移植层命令图", phase: '第一批' },
57
+ { key: 'src/commands.ts', cls: 'C', why: "移植层命令表", phase: '第一批' },
58
+ { key: 'src/direct_modes.ts', cls: 'C', why: "移植层直接模式", phase: '第一批' },
59
+ { key: 'src/entrypoints/', cls: 'C', why: "移植层入口", phase: '第一批' },
60
+ { key: 'src/cli/', cls: 'C', why: "移植层 CLI", phase: '第一批' },
61
+ { key: 'src/schemas/', cls: 'C', why: "移植层 schema", phase: '第一批' },
62
+ { key: 'src/services/', cls: 'C', why: "移植层服务", phase: '第一批' },
63
+ { key: 'src/server/', cls: 'C', why: "移植层 server", phase: '第一批' },
64
+ { key: 'src/state/', cls: 'C', why: "移植层 state", phase: '第一批' },
65
+ { key: 'src/memdir/', cls: 'C', why: "移植层 memory dir", phase: '第一批' },
66
+ { key: 'src/history.ts', cls: 'C', why: "移植层 history", phase: '第一批' },
67
+ { key: 'src/context.ts', cls: 'C', why: "移植层 context", phase: '第一批' },
68
+ { key: 'src/prefetch.ts', cls: 'C', why: "移植层 prefetch", phase: '第一批' },
69
+ { key: 'src/query.ts', cls: 'C', why: "移植层 query", phase: '第一批' },
70
+ { key: 'src/bridge/', cls: 'C', why: "移植层 bridge", phase: '第一批' },
71
+ { key: 'src/coordinator/', cls: 'C', why: "移植层 coordinator 壳", phase: '第一批' },
72
+ { key: 'src/plugins/', cls: 'C', why: "移植层插件", phase: '第一批' },
73
+ { key: 'src/types/', cls: 'C', why: "移植层类型", phase: '第一批' },
74
+ { key: 'src/utils/', cls: 'C', why: "移植层 utils", phase: '第一批' },
75
+ { key: 'src/constants/', cls: 'C', why: "移植层常量", phase: '第一批' },
76
+ { key: 'src/runtime/', cls: 'C', why: "移植层 runtime", phase: '第一批' },
77
+ { key: 'src/hooks/', cls: 'C', why: "移植层 hooks (与主仓 hooks-engine 无关)", phase: '第一批' },
78
+ { key: 'src/dynamic-tool-loader.ts', cls: 'C', why: "动态工具加载 (占位)", phase: '第一批' },
79
+ { key: 'src/tools.ts', cls: 'C', why: "移植层 tools 聚合", phase: '第一批' },
80
+ { key: 'src/transcript.ts', cls: 'C', why: "移植层 transcript", phase: '第一批' },
81
+ { key: 'src/index.ts', cls: 'C', why: "移植层包入口 (Kernel 不用; 主仓用的是包入口的公开导出)", phase: '第一批' },
82
+ { key: 'src/port_manifest.ts', cls: 'C', why: "移植清单", phase: '第一批' },
83
+ { key: 'src/platform.d.ts', cls: 'C', why: "类型垫片", phase: '第一批' },
84
+ { key: 'dist/', cls: 'BUILD', why: "构建产物 (git 忽略, 不入 git) + **运行期必需的 reference_data/*.json 快照**; 不入三层名单, 单独冻结计数", phase: '第一批' },
85
+ { key: 'tests/', cls: 'C', why: "constraint-runtime 自带测试 (4 文件) —— 但 vitest 配置 `**/constraint-runtime/**` 把整个目录排除了 ⇒ **它们从来不跑** (K1 真发现)", phase: '第一批' },
86
+ { key: 'package.json', cls: 'META', why: "包元数据", phase: 'K1' },
87
+ { key: 'package-lock.json', cls: 'META', why: "锁文件", phase: 'K1' },
88
+ { key: 'tsconfig.json', cls: 'META', why: "包 tsconfig", phase: 'K1' },
89
+ { key: 'node_modules/', cls: 'META', why: "依赖 (不入仓判断)", phase: 'K1' },
90
+ ];
91
+ /** 扫描基座 (相对 src/) + 不算源码的子树 */
92
+ export const CONSTRAINT_ROOT = 'constraint-runtime/';
93
+ export const CONSTRAINT_NON_SOURCE = ['dist/', 'node_modules/'];
94
+ /** 冻结量: 源码 / 空壳 / 构建产物 (棘轮: 只许减) */
95
+ export const CONSTRAINT_SRC_FILES = 59;
96
+ export const CONSTRAINT_SRC_LINES = 1925;
97
+ export const CONSTRAINT_STUB_FILES = 5;
98
+ export const CONSTRAINT_STUB_LINES = 12;
99
+ export const CONSTRAINT_DIST_FILES = 54;
100
+ export const CONSTRAINT_DIST_LINES = 783;
101
+ /**
102
+ * dist/reference_data/*.json —— **快照数据, 运行期真被读**:
103
+ * tools.ts 启动时读 tools_snapshot.json → PORTED_TOOLS (实测 **184 条**) → executeToolFromSnapshot 按 source_hint 动态 import;
104
+ * commands.ts 同理读 commands_snapshot.json。
105
+ * **陷阱**: CR 的 build 只有 `tsc`, 不复制 .json ⇒ 任何 `rm -rf dist && tsc` 都会静默丢掉它们
106
+ * (PORTED_TOOLS 变 0, 只有一行 warn, 无报错) —— 这是"静默降级路径", 见 kernel-constraint.test.ts 的 K1-e 门。
107
+ */
108
+ export const CONSTRAINT_DIST_DATA_JSON = 32;
109
+ /** 各层文件数 / 行数冻结值 */
110
+ export const CONSTRAINT_CLASS_FILES = { "A": 13, "C": 22, "B": 24 };
111
+ export const CONSTRAINT_CLASS_LINES = { "A": 352, "C": 776, "B": 797 };
112
+ export const A_ENTRY_USES = [
113
+ { key: 'src/constraint/', usedVia: 'pkg-entry', evidence: 'agents/constraint-layer.ts 取 ToolPermissionContext / BudgetTracker' },
114
+ { key: 'src/skills/', usedVia: 'pkg-entry', evidence: 'pi-sdk.ts / skill-loader.ts / bollharness skill-adapter 取 SkillRegistry' },
115
+ { key: 'src/agent/', usedVia: 'pkg-entry', evidence: 'pi-sdk.ts 取 AgentCoordinator' },
116
+ { key: 'src/thinking/', usedVia: 'pkg-entry', evidence: 'pi-sdk.ts 取 DeepThinkingEngine' },
117
+ { key: 'src/session_store.ts', usedVia: 'pkg-entry', evidence: 'pi-sdk.ts / pi-sdk-session-manager.ts 取 Session/saveSession/loadSession' },
118
+ { key: 'src/execution_registry.ts', usedVia: 'unused-debt', evidence: '主仓 0 引用 —— 待复核' },
119
+ { key: 'src/tool_pool.ts', usedVia: 'unused-debt', evidence: '主仓 0 引用 —— 待复核' },
120
+ { key: 'src/cost_tracker.ts', usedVia: 'unused-debt', evidence: '主仓 0 引用; K6 的 usage 记录若要用则转 pkg-entry' },
121
+ { key: 'src/cost_hook.ts', usedVia: 'unused-debt', evidence: '主仓 0 引用 —— 待复核' },
122
+ { key: 'src/models.ts', usedVia: 'unused-debt', evidence: '主仓 0 引用; 能力描述可与主仓 provider-registry 合并' },
123
+ ];
124
+ /** A 类里「主仓 0 引用」的条数冻结值 (棘轮: 只许减) */
125
+ export const A_UNUSED_DEBT_FROZEN_AT = 5;
126
+ export const CONSTRAINT_USES = [
127
+ { file: 'agents/constraint-layer.ts', target: '__pkg_entry__', count: 1, kind: 'prod', cls: 'A' },
128
+ { file: 'agents/pi-sdk-session-manager.ts', target: '__pkg_entry__', count: 1, kind: 'prod', cls: 'A' },
129
+ { file: 'agents/pi-sdk.ts', target: '__pkg_entry__', count: 2, kind: 'prod', cls: 'A' },
130
+ { file: 'agents/skill-loader.ts', target: '__pkg_entry__', count: 1, kind: 'prod', cls: 'A' },
131
+ { file: 'bollharness-integration/gate-state-machine.ts', target: '__pkg_entry__', count: 1, kind: 'prod', cls: 'A' },
132
+ { file: 'bollharness-integration/skill-adapter.ts', target: '__pkg_entry__', count: 1, kind: 'prod', cls: 'A' },
133
+ { file: 'test/econ-integration.test.ts', target: 'tools/PolymarketSDK/econ-integration', count: 1, kind: 'test', cls: 'B' },
134
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/cancelOrder', count: 1, kind: 'test', cls: 'B' },
135
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/clobShared', count: 1, kind: 'test', cls: 'B' },
136
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/createOrder', count: 1, kind: 'test', cls: 'B' },
137
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/getMarket', count: 1, kind: 'test', cls: 'B' },
138
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/getOrders', count: 1, kind: 'test', cls: 'B' },
139
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/PolymarketSDK/listMarkets', count: 1, kind: 'test', cls: 'B' },
140
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/WalletTools/createWallet', count: 1, kind: 'test', cls: 'B' },
141
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/WalletTools/getBalance', count: 1, kind: 'test', cls: 'B' },
142
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/WalletTools/importWallet', count: 1, kind: 'test', cls: 'B' },
143
+ { file: 'test/wallet-polymarket-verify.test.ts', target: 'tools/WalletTools/signMessage', count: 1, kind: 'test', cls: 'B' },
144
+ ];
145
+ export const B_DIRECT_IMPORT_DEBT = [];
146
+ export const B_DIRECT_IMPORT_FROZEN_AT = 0; // 12 → 0 (2026-10-02 K1 ④: 领域 SDK 直连改经 Tool Capability 层, 欠账还清)
147
+ /**
148
+ * 引用台账的扫描面**排除名单** (冻结, 只许减):
149
+ * 本门自己的测试文件里有"人造引用"探针串 (判别力自证用), 不排掉它就会被当成一条真引用
150
+ * —— 这就是本仓那条老规矩: 拿子串当判据前, 先排除自己刚写的东西。
151
+ */
152
+ export const CONSTRAINT_SCAN_EXCLUSIONS = ['test/kernel-*.test.ts'];
@@ -0,0 +1,32 @@
1
+ /**
2
+ * **K1 删除就绪台账** —— 每个候选对象给出 verdict + **引用证据**, 不许写「看起来没用」。
3
+ *
4
+ * leo 的五个删除条件 (缺一不许删): ① 有唯一替代路径 ② 全仓无有效 import / 动态引用 / 路由引用
5
+ * ③ 真跑覆盖旧能力 ④ 一次完整回归 + 一次故障恢复 ⑤ 留可回滚提交点。
6
+ *
7
+ * 本文件是 K1 第 ① 步的真实产出: **核验推翻了直觉排序** —— 原以为 dist/ 与 33 个空壳最该先删,
8
+ * 实测两者都是**运行期依赖** (dist 是 main/exports 目标; 33 个 stub 引 reference_data 快照)。
9
+ * 真正 0 引用的只有 2 个 15 行 stub。
10
+ *
11
+ * 判据: src/test/kernel-deletion.test.ts (verdict 必须与盘上引用面**同步**, 不许烂成借口)。
12
+ */
13
+ export const DELETION_VERDICTS = [
14
+ { group: 'CR 源: migrations/', target: 'src/constraint-runtime/src/migrations/', verdict: 'done', blockers: [], reason: "15 行 stub; 仓内(含 constraint-runtime 自身与 dist) 0 引用; **不在 `CR/src/index.ts` 的导出面** ⇒ 可直删" },
15
+ { group: 'CR 源: remote/', target: 'src/constraint-runtime/src/remote/', verdict: 'done', blockers: [], reason: "15 行 stub; 0 引用; 不在导出面 ⇒ 可直删" },
16
+ { group: 'CR/dist 构建产物 (89 文件/1164 行)', target: 'src/constraint-runtime/dist/', verdict: 'blocked', blockers: [{ file: 'src/agents/tool-capability/index.ts', why: "2026-10-02 K1 ④ 收敛后, 领域 SDK 的动态 import 从 pi-sdk-tools.ts 的 6 处**搬到这里** (唯一入口, dist 优先 + src 回落); 因此 dist 的删除仍被阻断, 但阻断点换了位置 —— 台账必须跟着换, 否则指向已不存在的耦合" }, { file: 'Dockerfile', why: "第167行把 src/constraint-runtime/dist COPY 进 node_modules/@bolloon/constraint-runtime/dist" }, { file: 'src/constraint-runtime/package.json', why: "main/exports 指向 dist/index.js; files=['dist/**/*']" }], reason: "**dist 才是运行期目标** (源码树不是) ⇒ 删 dist 直接断掉 B 类工具与包入口。必须先做完 K7 (B 类改 Tool Capability) 才有资格谈" },
17
+ { group: 'CR 源: reference_data/ (子系统快照数据)', target: 'src/constraint-runtime/src/reference_data/', verdict: 'blocked', blockers: [{ file: 'src/constraint-runtime/src/tools.ts', why: "同目录 tools_snapshot.json 是运行期派发台账 (PORTED_TOOLS + executeToolFromSnapshot 按 source_hint import) ⇒ 整个目录不能整删; subsystems/*.json 现在是**孤立数据** (读取者 _archive_helper 已删), 处置要单独决定" }], reason: "26 个存档壳删掉后 subsystems/*.json 只剩数据; 同目录混着运行期台账 ⇒ 需按文件分别判, 不是目录级删除" }, { group: 'CR 源: parity_audit.ts / remote_runtime.ts / native_ts/ / upstream_proxy/', target: 'src/constraint-runtime/src/parity_audit.ts', verdict: 'blocked', blockers: [{ file: 'src/constraint-runtime/src/index.ts', why: "第21-22行 re-export (runParityAudit / runRemoteMode / runSshMode / runTeleportMode)" }, { file: 'src/constraint-runtime/dist/index.js', why: "编译副本同样 re-export ⇒ 删源码还要重建 dist" }], reason: "可达包入口 ⇒ 删除要**同时改 index.ts + 重建 dist**, 属 K1-④ 的活, 不是纯删" },
18
+ { group: 'src/bollharness/ (另一个项目的镜像)', target: 'src/bollharness/', verdict: 'blocked', blockers: [{ file: 'scripts/smoke-esm.mjs', why: "第38行引用 dist/bollharness/src/scripts/context_router.js" }, { file: 'scripts/gen-copyright-source.ts', why: "第25行明写: src/bollharness 是**第三方 vendored 框架** (版权属 bollharness contributors), 不进版权登记" }], reason: "**第三方 vendored 框架** (不是 Bolloon 代码) + 版权归属未处置 + smoke 脚本引用 ⇒ 处置要先定它的归属, 属第一批「审查」而非机械化删除" },
19
+ { group: 'K1 第②步批二: 26 个移植存档壳', target: 'src/constraint-runtime/src/<26 个移植存档壳>/index.ts', verdict: 'done', blockers: [], reason: "包入口闭包外 + 主仓 0 引用 + 快照 0 点名; 自述为 Python placeholder package; 已删 (记录见 DELETION_LEDGER)" },
20
+ { group: 'K1 第②步批二: _archive_helper', target: 'src/constraint-runtime/src/_archive_helper.ts', verdict: 'done', blockers: [], reason: "只被 26 个存档壳调用; 随它们一起删" },
21
+ { group: 'K1 第②步批二: 6 个根级移植残留', target: 'src/constraint-runtime/src/<6 个根级移植残留>.ts', verdict: 'done', blockers: [], reason: "cost_hook/execution_registry/ink/port_manifest/query/system_init; 0 引用 0 点名; 已删" },
22
+ // ★ 下面这条是被编译期抓回来的一类: **环境声明 .d.ts 不是"被 import"的对象, 但它是编译期依赖**
23
+ { group: 'K1 第②步批二: platform.d.ts (撤回!)', target: 'src/constraint-runtime/src/platform.d.ts', verdict: 'not-deletable', blockers: [{ file: 'src/constraint-runtime/src/setup.ts', why: "靠 `declare module 'platform'` 编译; 删掉即 TS7016" }], reason: "**判错过一次**: 静态可达性看不见环境声明 ⇒ 删后 CR tsc 红 (TS7016), 已恢复。判据对 .d.ts 一律不判 ready" },
24
+ ];
25
+ /** 五个删除条件的机器可核验部分 (人/真跑承担的部分写在删除记录的 acceptance 字段) */
26
+ export const DELETION_CONDITIONS = [
27
+ '① 有唯一替代路径',
28
+ '② 全仓无有效 import / 动态引用 / CLI·Web 路由引用',
29
+ '③ 真跑已覆盖旧路径对应能力',
30
+ '④ 一次完整回归 + 一次故障恢复',
31
+ '⑤ 留可回滚提交点 (不丢历史)',
32
+ ];
@@ -0,0 +1,78 @@
1
+ /**
2
+ * plan-harness.ts — K7 台账: **Harness 作为唯一系统调用门**
3
+ *
4
+ * K7 的目标形态 (设计页 §7 第 164 行原文):
5
+ * `discover → permission → policy → budget → idempotency → execute → verify → evidence → event`
6
+ * 覆盖 普通工具 / MCP / Skill / delegate / 子 Agent / 联系人 / 支付 / 文件写入 / 外部通信
7
+ * 判据: **任何绕过 Harness 的代码都视为架构缺陷**; 工具旁路全删。
8
+ *
9
+ * 关键判断 (开工前已定, 不是新建): **Harness 作系统调用门是「提升」不是「新建」** ——
10
+ * `deny → pre-tool-validator → react-harness` 这条顺序**已经存在**且被源码级断言锁着
11
+ * (`src/test/pi-harness.test.ts`: "那唯一一处对 pre-tool-validator 的引用在门面内部 (注入), 不在调用点")。
12
+ * K7 要补的是: ① 把 9 个阶段与 9 个覆盖面**清单化** ② 把"谁在执行"数出来并登记 ③ 收敛旁路。
13
+ *
14
+ * 本文件是**台账 (数据)**, 不含运行时逻辑 —— 与 K3 分档一致 (台账档 ≠ 代码档)。
15
+ */
16
+ export const HARNESS_STAGES = [
17
+ { stage: 'discover', gate: 'src/kernel/roster.ts 的模块名册 + src/agents/tool-registry.ts 的工具名册', why: '模型能看到的工具集合必须是冻结名册的子集 (K0 ⑤ import 白名单 + 工具名册双源)' },
18
+ { stage: 'permission', gate: 'src/agents/deny-pipeline.ts', why: 'deny 最先: 被禁的动作不进后续任何阶段 (顺序不可换)' },
19
+ { stage: 'policy', gate: 'src/agents/pre-tool-validator.ts (经 src/agents/pi-harness.ts 门面注入)', why: '参数级校验 + 策略拒绝; 唯一引用在门面内部 ⇒ 调用点无法绕过' },
20
+ { stage: 'budget', gate: 'src/agents/goal-flywheel/run-closure.ts (HardLimits) + Run 预算', why: '预算穷尽要能在**执行前**拒 (花掉才发现就晚了)' },
21
+ { stage: 'idempotency', gate: 'src/agents/x402/* + src/agents/contacts/* 的幂等键 + 写操作读回自证', why: '支付/联系人/写文件这三类是"重复执行有真实副作用"的, 幂等键必须在门内' },
22
+ { stage: 'execute', gate: 'src/agents/pi-sdk.ts 主执行点 (经门链) + src/agents/tool-registry.ts 统一执行口', why: '执行必须只有一条咽喉; 台账里逐点登记谁在执行 (含旁路)' },
23
+ { stage: 'verify', gate: 'src/agents/pi-sdk-tools.ts 写类工具读回核对', why: '"工具说成功 ≠ 任务成功" 要从规矩变成机制' },
24
+ { stage: 'evidence', gate: 'src/agents/x402/direct-payment.ts 台账 + Run 落盘', why: '有副作用的动作要留可核验证据' },
25
+ { stage: 'event', gate: 'runCtx.eventSink (K2 外置面) → Web/CLI 双面', why: '事件面只许有一个出口 (K2 外置面的 eventSink)' },
26
+ ];
27
+ export const HARNESS_SURFACES = [
28
+ { surface: 'tool', canonical: 'src/agents/tool-registry.ts', why: '普通工具的统一执行口' },
29
+ { surface: 'mcp', canonical: 'src/agents/pi-sdk-tools.ts', why: 'MCP 工具经这里执行 (台账里 1 处)' },
30
+ { surface: 'skill', canonical: 'src/bollharness-integration/skill-adapter.ts', why: 'Skill 执行; **注意现在有两条 skill 路径** (见旁路候选)' },
31
+ { surface: 'delegate', canonical: 'src/web/agent-delegate-server.ts', why: '委派执行面' },
32
+ { surface: 'subagent', canonical: 'src/agents/runner-resolver.ts', why: '子 Agent 经 runner-resolver 拿 session (K5 已接线)' },
33
+ { surface: 'contact', canonical: 'src/agents/contacts/consent.ts', why: '联系人/同意门 (consent 单次 vs grant 长期)' },
34
+ { surface: 'payment', canonical: 'src/agents/x402/direct-payment.ts', why: '支付/收款: 幂等 + 链上核验' },
35
+ { surface: 'file-write', canonical: 'src/agents/tool-path-args.ts', why: '路径参数统一处理 + 敏感子目录护栏' },
36
+ { surface: 'external-comm', canonical: 'src/agents/pi-sdk-tools.ts', why: '外部通信 (HTTP/SSRF 面) 与 MCP 同文件' },
37
+ ];
38
+ /**
39
+ * 实测 (2026-10-02, 剥注释后共 **17** 处 —— K4-B 删老 `runReActLoop` 前是 18) —— 数的口径写在 countHarnessExecSites 里, 判据会重算比对。
40
+ *
41
+ * **规则 (2026-10-02 立): 台账按「符号」不按「行号」。** 行号会随任何一次编辑漂移, 而判据只核**计数**
42
+ * 不核行号 ⇒ 行号一旦写进台账, 它迟早会**指向错的位置而没人发现** (K7 第二步 b 当场发生:
43
+ * 在 pi-sdk 插入 ~35 行后, 台账里的 4144 实际已变 4176)。说清"是哪一处"用函数名/类名/调用形态。
44
+ */
45
+ export const HARNESS_EXEC_SITES = [
46
+ { file: 'src/agents/pi-sdk.ts', count: 5, kinds: ['main', 'skill', 'bypass', 'homonym', 'registry'], why: '**主执行点 1 = pivot 的 `guardedExecute` 端口内那次 `await tool.execute(args)`** (2026-10-02 K4-B: 老 `runReActLoop` 的执行点随 loop 删除, 端口成为唯一主执行点; 它先过 `beforeToolCall` 再执行、执行后过 `afterToolCall`) · skill 2 (`getSkillRegistry()` 暴露的 `skillRegistry.execute` + 内置 `sk.execute`; **2026-10-02 量到: 这两条在生产代码里零调用者** —— 但 `PiAgentSession.executeSkill`/`getSkillRegistry` 是**已发布 npm 包的公开方法** ⇒ 属"不擅动公开契约", 删/收口都要等用户口径) · 内置 tscTool 直调 1 (bypass, 已在 `runTurnEndTypecheck` 内先问门) · `loop.execute` 1 (homonym)' },
47
+ { file: 'src/agents/workflow-pivot-loop.ts', count: 2, kinds: ['bypass', 'homonym'], why: '**pivot loop 直接执行工具** 1 (bypass —— 2026-10-02 已收敛: 走注入的 `guardedExecute` 门端口) · `loop.execute` 1 (homonym)' },
48
+ { file: 'src/agents/tool-registry.ts', count: 1, kinds: ['registry'], why: '注册表统一执行口 (唯一咽喉候选)' },
49
+ { file: 'src/agents/pi-sdk-tools.ts', count: 1, kinds: ['mcp'], why: 'MCP `executeTool` 1' },
50
+ { file: 'src/bollharness-integration/skill-adapter.ts', count: 1, kinds: ['skill'], why: 'skill 第二条路径 (`SkillAdapter.executeSkill` → `registry.execute`)' },
51
+ { file: 'src/agents/browser-cdp.ts', count: 1, kinds: ['homonym'], why: 'CDP `session.execute` —— 浏览器命令, 不是工具执行' },
52
+ { file: 'src/agents/chain/chain-wallet.ts', count: 1, kinds: ['homonym'], why: '`params.execute(signer)` —— 钱包动作, 不是工具执行' },
53
+ { file: 'src/web/agent-delegate-server.ts', count: 1, kinds: ['port-callback'], why: '`options.execute({...})` —— 2026-10-02 定性: 它是**注入的执行器端口** (`execute?: (req: DelegateExecutionRequest) => Promise<DelegateExecutionResult>`, 见该文件顶部接口定义), 委派服务器**自己不执行工具** ⇒ 不是旁路; 但"注入的那个执行器有没有走门"属 delegate 覆盖面的事, 不在这条普查里' },
54
+ { file: 'src/bollharness-integration/index.ts', count: 1, kinds: ['import'], why: 'import 列表里的名字' },
55
+ { file: 'src/pi-ecosystem/index.ts', count: 1, kinds: ['import'], why: 'import 列表里的名字' },
56
+ { file: 'src/pi-ecosystem-mcp/index.ts', count: 1, kinds: ['decl'], why: '`export async function executeTool(` —— 函数定义' },
57
+ { file: 'src/kernel/plan-deletion.ts', count: 1, kinds: ['ledger-string'], why: '台账字符串里的字面' },
58
+ ];
59
+ export const K7_BYPASS_CANDIDATES = [
60
+ { target: 'src/agents/workflow-pivot-loop.ts', symbol: 'guardedExecute', replacesWith: '走 Harness 门链 (与 pi-sdk 主执行点同一条咽喉)', why: 'pivot loop 是第二条工具执行路径 ⇒ 未经 deny/policy 就能执行工具 (架构缺陷定义的那一类)', status: 'converged', evidence: '2026-10-02: `PivotLoopConfig.guardedExecute` 端口 (`044cde2`) + pi-sdk 在 `promptWithPivotLoop` 注入同一 `piHarness().beforeToolCall` (`69397f6`); 用例: 未注入行为不变 / 注入后 `tool.execute` 计数 0 / 端口抛错不执行 / 机械接线断言' },
61
+ { target: 'src/agents/pi-sdk.ts', symbol: 'tscTool.execute', status: 'converged', replacesWith: '经门链执行, 或在台账里登记为"内部诊断白名单"并写明理由', why: '内置诊断工具直调: 要么走门, 要么**显式登记**为白名单 —— 不许处于"没人知道它绕过"的状态。**2026-10-02 选"走门"并已接线**: 回合末尾 TS 自检先问 `beforeToolCall({tool: tsc_check, args: {}, ctx: harnessCtx(), permissionMode})`, 被拒或抛错 ⇒ **不执行**且**可见**报出 (拒绝不静默); 机械断言: 判定在 `tscTool.execute` 之前 + `if (!tscAllowed)` 分支存在 + 拒绝文案存在。**端到端未单独取证** (该路径由"本回合改过 TS"的收尾自检触发, 需要真 LLM 回合) ⇒ **2026-10-02 端到端取证完成** (`src/test/k7-tsc-tool-e2e.test.ts`, 真 LLM 回合 + 真门实例): ① 允许路 —— 门被问过 `tsc_check` 且恰执行一次 (门被问到 `read_file, edit_file, tsc_check`), 结论 `🔎 类型检查` 进对话流; ② 拒绝路 —— 门拒绝 ⇒ `tsc_check` **零执行** + 拒绝文案 (带门给出的理由) 进对话流。**两条变异都真做且判红**: 变异①把问门时的工具名改掉 ⇒ 允许路判红 (`expected [...] to include 「tsc_check」`); 变异②把拒绝分支改成 fail-open (`if (false && !tscAllowed)`) ⇒ 拒绝路判红 (`被门拒绝 ⇒ 一次都不许执行: expected 1 to be +0`)。**如实记边界**: 拒绝路里"拒绝"这个判定是测试注入的 (沿用仓里端口注入法), 产品侧被证的是"**先问门、被拒后不执行**"这一半; "门自己判出来的拒绝"由 pre-tool-validator/react-harness 既有用例覆盖。**踩坑两条**: (a) 少了 `initMinimax()` 装配 ⇒ session 走未初始化模型兜底路 (回显、不调工具), 门一次都不会被问 ⇒ 假红; (b) 少了 `resetAgentSession()` ⇒ `createAgentSession` 复用上一条用例的 session (带着"我改过这个文件了"的记忆) ⇒ 第二条用例的模型回"需求已完整满足"不调工具 ⇒ 前提假红。两条都写进用例头。',
62
+ evidence: '2026-10-02 端到端: `src/test/k7-tsc-tool-e2e.test.ts` (真 LLM 回合 + 真门实例包裹) —— 允许路: 门被问过 `tsc_check` 且恰执行一次, `🔎 类型检查` 进对话流; 拒绝路 (判定注入): `tsc_check` 零执行 + 拒绝文案带理由进对话流。变异①(问门工具名改掉)⇒允许路判红; 变异②(拒绝分支改 fail-open)⇒拒绝路判红。**2026-10-02 K4-B 侦查补正**: 上面两条用的是**默认配置** (老 `runReActLoop`), 而**生产里 web 走 pivot 路径** (`usePivotLoop: true` + 流式入口原先"提前 return") ⇒ 那条自检在生产**一次都没跑过** (早先证据只覆盖非生产形状)。已修: 抽成 `runTurnEndTypecheck()`, **三条路径全挂** (pivot prompt / 老 loop / 流式 pivot); 用例补第三条"生产形状" (注入 touched 状态 ⇒ 判**接线**), **变异 (撤掉流式路径那行) ⇒ 判红** (`expected [] to include tsc_check`)。' },
63
+ { target: 'src/agents/pi-sdk.ts', symbol: 'getSkillRegistry', replacesWith: '返回**受门包装** (`GuardedSkillRegistry`): `execute` / `get().execute` / `list()[].execute` 三条都经 `executeSkill` ⇒ Harness', status: 'converged', evidence: '2026-10-02 按 leo 口径 **(b)** 落地 (原选 a 为纸面约定, leo 裁定走 b): ① 包装堵住**三条**隐藏路径 —— 只堵 `execute` 不够, `get()`/`list()` 返回的 `Skill` 自带裸 `execute`; ② 真跑 `k7-session-skill-gate.test.ts` ⑥: allow 时三条各恰一次 (计数 3), `denyTool` 后**三条全零执行** (计数仍 3); ③ 真变异两条 (`list` 裸透传 / `get` 裸透传) 均判红 (`expected FACADE_EXECUTED to match /^拒绝: /`), 还原回绿; ④ 机械断言: 方法体内无 `return this.skillRegistry;`、`list` 过 `guarded` 映射、**零** `this.skillRegistry.execute(` 直连。⚠️ 行为变更 (可能属破坏性, leo 已知并裁定): 旧 `.execute()` 被拒时**不再执行**, 改为返回 `拒绝: [...]`; 方法名/签名不变 ⇒ 源码级兼容。**管不到的一条 (如实记)**: 调用方自己 `register` 时传进来的那个对象仍有裸 `execute` —— 那是调用方的对象, 不属本出口能管的面', why: '**未过门的原始出口**: 拿到裸 registry 就有三条绕过 Harness 的路径 (`execute` / `get().execute` / `list()[].execute`) —— 公开兼容面不许无声删, 但也**不许不登记** (leo 的最终要求: 任何 skill 执行入口只能经 Harness)' },
64
+ { target: 'src/bollharness-integration/skill-adapter.ts', symbol: 'registry.execute', replacesWith: '收敛成唯一 skill 执行入口 (且该入口经门)', status: 'converged', evidence: '2026-10-02 两条路都真跑取证+变异验证: ① adapter 路 `k7-skill-denylist-e2e.test.ts` (真 session→真 Harness→integration→adapter) ② 公开出口路 `k7-session-skill-gate.test.ts` (`executeSkill` 探针 skill 计数: 允许恰 1 次执行返回标记 · deny **零执行** · 重试仍拒 · 放开又能执行); 两处变异(拆保护/门永远放行)均判红 ⇒ 用例承重', why: 'skill 有两条执行路径 ⇒ 必然一条有门一条没有 ("同一个能力只许有一套实现" 的同型教训). **2026-10-02 实测**: 活路径 = `SkillAdapter.executeSkill` (`bollharness-integration/integration.ts` ← `index.ts` 的 harness 入口); `PiAgentSession.executeSkill` **生产零调用者** (但属公开契约 ⇒ 删除待用户口径). 活路径已接线: 端口 (`setGuardedExecute`, **判定**契约) + integration 透传 (`setSkillGuard`) + `index.ts` 活路径注入 (门建不起来 ⇒ deny-all); **真跑已通 (allow 路)**: `node dist/index.js --harness-skill arch get_gate` 真执行并返回真实 skill 输出 —— **注意读的地方**: 响应经"启动期日志闸门"写进 `~/.bolloon/logs/startup.log` (`[boot] 🎯 Skill <name> 执行结果:`), **stdout 里看不到** (我上一轮据此误判"没走到分发器", 是假阴性); 且无 `[K7] skill 门未能建立` 警告 ⇒ 门确实建起来了。**deny 路已取得 ★真跑**: `k7-skill-denylist-e2e.test.ts` 走**真链** (真 session → 真 Harness 的 deny-list checker → integration → adapter → registry): allow 基线不被拒 · 把 `skill:arch` 放进拒绝列表 ⇒ 结果 `拒绝: [deny-list]` 且拿不到 skill 真实输出 · 重试仍被拒 · 放开名单 ⇒ 又能执行; **变异** (拆掉 adapter 的门分支) ⇒ 该用例判红, 还原 ⇒ 回绿且无 diff ⇒ **用例承重**。**状态仍 open**: 本条目含两条路径, 公开兼容面 (`PiAgentSession.executeSkill`) 未收敛 (leo 第 4 步: 降为兼容转发 ⇒ 唯一 SkillExecutionPort)' },
65
+ ];
66
+ /** K7 验收 (与设计页 §7 的判据对应) */
67
+ export const K7_ACCEPTANCE = [
68
+ '9 个阶段**顺序**即契约, 且每阶段的 gate 是真存在的文件/判据 (不是待建)',
69
+ '9 个覆盖面每个都能说出"现在谁管它", canonical 文件真存在',
70
+ '执行点普查与盘上**逐字一致** (增 = 新旁路未登记 · 减 = 改了盘没改账)',
71
+ '旁路候选逐条有替代路径; 收敛后**旁路数只许减**',
72
+ '收敛动作必须走五条件 (唯一替代路径 · 无有效引用 · 真跑覆盖 · 完整回归 + 故障恢复 · 可回滚提交点)',
73
+ ];
74
+ export const K7_PROGRESS = {
75
+ stage: 'ledger-landed',
76
+ execSitesTotal: 17, // 16 (普查基线) + 1 (K7 第二步 b: pivot loop 端口内执行, 在门之后) —— 2026-10-02 K4-B 删老 loop, 它那处执行点随之消失: 18 → 17
77
+ bypasses: 0, // 3 → 2 (pivot loop) → 1 (getSkillRegistry 受门包装, leo 口径 (b)) → **0** (tscTool 端到端取证完成: 允许路/拒绝路真回合 + 两条变异, 2026-10-02)
78
+ };
@@ -0,0 +1,60 @@
1
+ /**
2
+ * **K6 —— ModelRuntime 台账 + 门的数据面**。
3
+ *
4
+ * K6 的目标 (路线图原文, 不许跳): 以 `ModelRuntime.acquire(modelSnapshot)` 为**只读**入手的多供应商运行时
5
+ * (并发 · 连接池 · timeout · cancellation · 429 退避 · circuit breaker · capability 检查 · provider fallback · usage 记录),
6
+ * **已有的 `selectModel` / registry / catalog / Run snapshot 继续保留, 不重做**。
7
+ *
8
+ * 通用判据 (K2 实操中拦回过一次 assistant 的实现): **新层出现后, 旧写口的调用点数只许不变或减少。**
9
+ * —— 所以 K6 的第一件事不是写运行时, 而是把"旧写口"**数清楚并冻结**, 让"只读"这件事可判、可回退检测。
10
+ */
11
+ /**
12
+ * **旧写口名册 (冻结)** —— 口径: 全仓 (排除 `test/` 与 `kernel/`) 里 `name(` 的匹配次数, **去掉含 `function name` 的声明行**。
13
+ * 判据用同一口径从盘上重算 ⇒ 增 = 新层在偷偷改旧状态 (回退) · 减 = 改了盘没改账。
14
+ */
15
+ export const MODEL_WRITE_PORTS = [
16
+ { name: 'setCustomProviderSnapshot', module: 'llm/provider-registry.ts', callSites: 5 },
17
+ { name: 'addCustomProvider', module: 'llm/custom-provider-store.ts', callSites: 0, note: '主仓零调用 (仅测试/未来向导用) —— 只许不变或减' },
18
+ { name: 'updateCustomProvider', module: 'llm/custom-provider-store.ts', callSites: 0, note: '主仓零调用' },
19
+ { name: 'removeCustomProvider', module: 'llm/custom-provider-store.ts', callSites: 0, note: '主仓零调用' },
20
+ { name: 'writeSessionSelection', module: 'llm/model-selection.ts', callSites: 1 },
21
+ { name: 'clearSessionSelection', module: 'llm/model-selection.ts', callSites: 2 },
22
+ { name: 'resetModelSelection', module: 'llm/model-selection.ts', callSites: 1 },
23
+ { name: 'setSystemPrependProvider', module: 'llm/pi-ai.ts', callSites: 1 },
24
+ { name: 'clearSystemPromptCache', module: 'llm/pi-ai.ts', callSites: 1 },
25
+ ];
26
+ /** 合计冻结值 (棘轮: 只许不变或减少; 要加必须同时改这里 ⇒ diff 里一次显式动作) */
27
+ export const MODEL_WRITE_PORTS_FROZEN_AT = 11;
28
+ /** `acquire` 的**只读**要求 (写成数据, 判据与实现共用) */
29
+ export const MODEL_RUNTIME_ACQUIRE_RULE = {
30
+ readOnly: true,
31
+ rule: '`acquire(modelSnapshot)` 只读: 不许改 provider 配置 / API key / 默认 URL / Global model / Run snapshot',
32
+ ratchet: '新层出现后, 旧写口的调用点数只许不变或减少 (增 = 回退)',
33
+ };
34
+ export const MODEL_RUNTIME_CAPABILITIES = [
35
+ { key: 'multi-provider-concurrency', why: '多供应商并发调用 (各 provider 各自限流)', status: 'done' },
36
+ { key: 'connection-pool', why: '连接复用 (keep-alive), 不每次新建', status: 'done' },
37
+ { key: 'timeout', why: '单次调用超时 (按 snapshot 的预算)', status: 'done' },
38
+ { key: 'cancellation', why: '取消传播 (AbortSignal 透传)', status: 'done' },
39
+ { key: 'rate-limit-backoff', why: '429 退避 (指数 + 抖动, 不许重试风暴)', status: 'done' },
40
+ { key: 'circuit-breaker', why: '连续失败熔断 (半开探测)', status: 'done' },
41
+ { key: 'capability-check', why: '能力检查 (该 provider 是否支持所需能力: 工具/vision/长上下文)', status: 'done' },
42
+ { key: 'provider-fallback', why: '失败回退到备用 provider (按 Run snapshot, 不改全局)', status: 'done' },
43
+ { key: 'usage-recording', why: 'usage 记录 (token/成本按 Run 记账)', status: 'done' },
44
+ ];
45
+ /** **明确不做** (路线图红线; 判据核这几条名字都在, 防止实现时越界) */
46
+ export const MODEL_RUNTIME_OUT_OF_SCOPE = [
47
+ '不自行改 provider 配置',
48
+ '不自行改 API key',
49
+ '不自行改默认 URL',
50
+ '不自行改 Global model',
51
+ '不自行改 Run snapshot',
52
+ ];
53
+ /** K6 进度 (与 K5 的 stage/container 同款: 声明未实现 ⇒ 运行时文件**必须不存在**) */
54
+ export const K6_PROGRESS = {
55
+ stage: 'capabilities-done',
56
+ runtimePath: 'kernel/model-runtime.ts',
57
+ /** 必须等于 `MODEL_RUNTIME_CAPABILITIES` 里 status==='done' 的条数 (判据机械核, 不许自报) */
58
+ capabilitiesDone: 9,
59
+ capabilitiesTotal: MODEL_RUNTIME_CAPABILITIES.length,
60
+ };
@@ -0,0 +1,163 @@
1
+ /**
2
+ * **K2 台账: RunContext 状态外置** —— Pi 实例上的可变运行状态, 要搬进显式 RunContext。
3
+ *
4
+ * 现状 (2026-10-02 真读, 剥注释后计数): `agents/pi-sdk.ts` **4099 行**里 **8 个字段 / 185 处 `this.` 访问**, 且
5
+ * `runReActLoop(onStream?, signal?)` 只收 2 个参数却隐式依赖这 8 个字段 ⇒ 并发 Run 之间靠实例字段互相污染。
6
+ *
7
+ * 门的口径 (`src/test/kernel-runcontext.test.ts`):
8
+ * · 逐字段计数必须与冻结值**双向相等** (多一处 = 新增泄漏; 少一处 = 改了代码没改账, 要显式 rebase);
9
+ * · 标了 `migrated` 的字段 `this.` 访问必须为 **0** (假完成判红);
10
+ * · 8 个字段必须都能在 RunContext 目标清单里找到位置 (不然外置到哪里去)。
11
+ */
12
+ export const RUN_CONTEXT_FILES = ['agents/pi-sdk.ts'];
13
+ export const RUN_CONTEXT_FROZEN_AT = '2026-10-02';
14
+ export const RUN_CONTEXT_ENTRY = 'agents/pi-sdk.ts:1923 runReActLoop(onStream?, signal?) —— 目标签名: runReActLoop(ctx: RunContext)';
15
+ export const RUN_CONTEXT_FIELDS = [
16
+ { name: 'messageHistory', declaredAt: '(已删, 见 K5 步骤⑧)', scope: 'session', accesses: 0, into: 'history', migrated: false, payDownIn: 'K2' },
17
+ { name: 'currentOnStream', declaredAt: 'agents/pi-sdk.ts:442', scope: 'run', accesses: 0, into: 'eventSink', migrated: true, payDownIn: 'K2' },
18
+ { name: 'currentSignal', declaredAt: 'agents/pi-sdk.ts:443', scope: 'run', accesses: 0, into: 'abortSignal', migrated: true, payDownIn: 'K2' },
19
+ { name: 'currentChannelId', declaredAt: '(已删, 见 K5 步骤⑧ 批次4)', scope: 'session', accesses: 0, into: 'channelId', migrated: false, payDownIn: 'K2' },
20
+ { name: 'currentRunId', declaredAt: '(已删, 见 K5 步骤⑧ 批次5)', scope: 'run-boundary', accesses: 0, into: 'runId', migrated: false, payDownIn: 'K2' },
21
+ { name: 'currentIntent', declaredAt: 'agents/pi-sdk.ts:463', scope: 'run', accesses: 0, into: 'intent', migrated: true, payDownIn: 'K2' },
22
+ { name: 'currentGoalId', declaredAt: '(已删, 见 K5 步骤⑧ 批次3)', scope: 'session', accesses: 0, into: 'goalId', migrated: false, payDownIn: 'K2' },
23
+ { name: 'currentAgentId', declaredAt: '(已删, 见 K5 步骤⑧ 批次2)', scope: 'session', accesses: 0, into: 'agentId', migrated: false, payDownIn: 'K2' },
24
+ ];
25
+ /** RunContext 必须带的字段 (leo 的 K2 清单) */
26
+ export const RUN_CONTEXT_TARGET = ["requestId", "channelId", "agentId", "goalId", "runId", "intent", "modelSnapshot", "history", "abortSignal", "budget", "eventSink", "harnessContext"];
27
+ /** 冻结总量 (棘轮只许减) */
28
+ export const RUN_CONTEXT_ACCESS_TOTAL = 0; // 批次5: 8 个字段全部迁出 ⇒ Pi 侧 0 处访问
29
+ /** 已外置字段数 (棘轮: 只许增)。改动这里 = 明确宣告"又搬完一个字段" */
30
+ export const RUN_CONTEXT_MIGRATED_FROZEN = 3;
31
+ /**
32
+ * 已迁移字段的落地位置 (便于人工复核"搬去哪了"):
33
+ * · currentOnStream → `src/agents/run-context.ts` 的 `RunContext.eventSink`
34
+ * (入口 `createRunContext({ eventSink })` 快照; 清空 = 换一个空 Context; 15 处访问归零)
35
+ */
36
+ export const RUN_CONTEXT_DONE = ['currentOnStream', 'currentSignal', 'currentIntent'];
37
+ /** K2 的 per-run 外置面 = scope:'run' 的字段数 (session 级的不算) */
38
+ export const RUN_CONTEXT_RUN_SCOPED = 3;
39
+ /**
40
+ * **K2 第 4 格改判记录: `currentGoalId` 是 session 级, 不搬进 RunContext。**
41
+ *
42
+ * 证据 (2026-10-02 真读 `pi-sdk.ts`):
43
+ * · 写入口① `setGoalId(goalId)` (行 1747) —— **公开 API**, CLI/Web/runner 在 run **之前**注入
44
+ * ("有 goalId 就在该 Goal 下执行" ⇒ 这是会话绑定, 不是本轮状态);
45
+ * · 写入口② run 内部 (行 2024 / 1091): 未绑定时 `findActiveGoal` 或 `createGoal` 再 `startRun({ goalId })`
46
+ * —— **run 会写它, 且必须活到下一个 run**;
47
+ * · 读出口: harness 上下文 (行 1914) · 轨迹/报告 (行 2866/2995/3006/3023) · `bindExternalWait` (1804-1806);
48
+ * · 行 1081/1091 · 2003/2024 有 "暂存-重绑-还原" 模式 (跨块共享)。
49
+ *
50
+ * 为什么不能"入口 copy 一份进 Context": run 内的写会落进 per-run ctx ⇒ 会话字段不被更新 ⇒
51
+ * 下一个 run 走"未绑定 ⇒ 重新 findActiveGoal"分支 ⇒ **行为改变** (旧行为是复用同一绑定)。
52
+ *
53
+ * 结论: 它该收进的是**会话/通道级持有者** (K5 Channel Actor 的 actor 状态), 不是 RunContext。K2 不碰它。
54
+ */
55
+ export const RUN_CONTEXT_SESSION_SCOPED_NOTE = 'currentGoalId: 会话级绑定 (setGoalId 外部注入 + run 内可能重绑), 归 K5 actor 状态, 不进 RunContext';
56
+ /**
57
+ * **K2 第 5~8 格改判记录 (2026-10-02, 一次把剩下 4 个字段全定性)**
58
+ *
59
+ * 逐字段证据 (真读 `pi-sdk.ts` 的**写入点**, 不是看名字):
60
+ *
61
+ * | 字段 | 写入点 | 判定 |
62
+ * | --- | --- | --- |
63
+ * | `currentAgentId` (20) | **只有 1 个**: 构造函数 547 行 `= config.agentId` (createAgentSession 注入) | **session 级** —— 会话创建时定 |
64
+ * | `currentChannelId` (21) | 4 个, 全是 `= channelId ?? this.currentChannelId` (显式**保留**上一轮的值) / 3895 直设 | **session 级** —— 设计上就跨 Run 存活 |
65
+ * | `messageHistory` (53) | 3 个, 全是整体替换 (hydrate 680 / compact 3243 / 真破坏性更新 3445) | **session 级** —— 它就是"会话记忆"本身, 跨 Run 累积 |
66
+ * | `currentRunId` (36) | 1989 行在 resume 里 `= this.resumeRunId` **然后才调 prompt**; 2036 在 run 内; 3034/3038 清空 | **run-boundary** —— 属 Run, 但值在入口之前就设好 ⇒ 必须由入口**显式播种** |
67
+ *
68
+ * ⇒ **K2 的 per-run 外置面只有 3 个字段** (`eventSink` / `abortSignal` / `intent`), **且已 100% 完成**
69
+ * (`RUN_CONTEXT_RUN_SCOPED = 3` == `RUN_CONTEXT_DONE.length`)。
70
+ *
71
+ * ⇒ 剩下 5 个不属于"每轮状态": 4 个 session 级该收进**会话/通道级持有者** (K5 Channel Actor 的 actor 状态);
72
+ * 1 个 run-boundary 需要一个**入口播种**动作 (在 `createRunContext(...)` 里显式带上 runId) ——
73
+ * 播种会新增对旧实例字段的读, 所以它必须作为**独立一格**记账并说明理由, 不能混在"纯减"里。
74
+ *
75
+ * ⇒ **连带结论 (对 K2 验收标准的影响)**: leo 写的「两个并发 Run 的 history 不互相污染」**不是 K2 能靠搬字段达成的**
76
+ * —— `messageHistory` 是会话记忆, 共享是它的本质; 要"不互相污染"必须让**每个 channel 有自己的会话/history**
77
+ * (K5 Channel Actor), 或让每个 Run 在不可变基准上各写各自的分支。**这条验收标准的落点应改判到 K5。**
78
+ */
79
+ export const RUN_CONTEXT_REMAINING_NOTE = 'remaining 4: agentId/channelId/messageHistory = session 级 (K5 actor); runId = 入口播种 (独立一格)';
80
+ /**
81
+ * **K2 收尾 (leo 2026-10-02 口径) —— 播种读取单独记账**
82
+ *
83
+ * `currentRunId` 属 **run-boundary**: 它对 Run 是真状态, 但值在**入口之前**就设好 (resume 路径
84
+ * `this.currentRunId = this.resumeRunId` 然后才调 prompt) ⇒ 循环内部不该再去读实例字段。
85
+ *
86
+ * 允许**一次**显式播种 (只在 `PiAgentSession.seedRunContext()` 里):
87
+ * createRunContext({ runId: this.currentRunId, ...extra })
88
+ *
89
+ * 记账规则 (三条, 由门强制):
90
+ * · `CURRENT_RUN_ID_SEED_READS = 1` —— 播种读取**恰好一处**, 且必须在 `seedRunContext` 体内;
91
+ * · `CURRENT_RUN_ID_SEED_SITES = 2` —— 调用播种的入口恰好两个 (`prompt` / `promptStream`), 且都在循环之外;
92
+ * · `currentRunId.accesses = 38 = 37(历史匹配) + 1(播种)` —— **不计进"必须下降"的纯迁移统计**, 也**不算 K2 未完成**。
93
+ *
94
+ * 性质: 只在进入一次 Run 时发生; 只把已有恢复身份播种给 RunContext; 不是循环内部重新读旧实例状态;
95
+ * 不得成为新的写入口。**K5 完成后**改为 `createRunContext({ runId: request.resumeRunId })`, 届时删除该字段本体。
96
+ */
97
+ export const CURRENT_RUN_ID_SEED_READS = 1;
98
+ export const CURRENT_RUN_ID_SEED_SITES = 2;
99
+ export const CURRENT_RUN_ID_SEED_NOTE = 'run-boundary 播种 (口径=判据同款/匹配次数): 批次5 后 pi-sdk 侧 currentRunId = 0 处 (名字已不存在); 播种读取只剩 seedRunContext 内一处, 读的是本体 actor.state.activeRun';
100
+ /**
101
+ * **K2 验收标准 (leo 2026-10-02 修订 —— 把 history 并发隔离移出)**
102
+ * ① 三个 run 级字段 (eventSink / abortSignal / intent) 全部迁移;
103
+ * ② `RunContext` 接线完整 (入口建 Context · 循环从 Context 取值);
104
+ * ③ 循环使用**显式** Context, 不再隐式读已迁移的 run 级实例字段;
105
+ * ④ 已迁移字段零 `this.` 残留;
106
+ * ⑤ 新 Run **不继承**上一 Run 的 event / signal / intent (未给字段显式置空);
107
+ * ⑥ `currentRunId` 的播种读取**只有一个冻结入口** (`seedRunContext`);
108
+ * ⑦ **不要求** K2 解决 session history 并发隔离 (那条移给 K5)。
109
+ */
110
+ export const K2_ACCEPTANCE = [
111
+ '① run 级 3 字段全迁移',
112
+ '② RunContext 接线完整 (入口建 · 循环从 Context 取)',
113
+ '③ 循环只吃显式 Context',
114
+ '④ 已迁移字段零 this. 残留',
115
+ '⑤ 新 Run 不继承上一 Run 的 event/signal/intent',
116
+ '⑥ currentRunId 播种只有一个冻结入口',
117
+ '⑦ 不含 history 并发隔离 (→ K5)',
118
+ ];
119
+ /**
120
+ * **K5 验收标准 (leo 2026-10-02 增加 —— 承接从 K2 移出的部分)**
121
+ * ① 同 Channel 消息串行 (输入只能排队, 不能并发改 history);
122
+ * ② 不同 Channel history 不交叉 (完全隔离);
123
+ * ③ 同一 Channel 的多个 Run 不互相污染 (靠 Actor 串行调度 + Run 边界隔离);
124
+ * ④ 页面 / CLI / P2P / Supervisor 都进入同一 Actor mailbox;
125
+ * ⑤ Actor 崩溃后可由 Supervisor 恢复;
126
+ * ⑥ `messageHistory` 不再由 Pi 直接拥有。
127
+ */
128
+ export const K5_ACCEPTANCE = [
129
+ '① 同 Channel 串行 (排队, 不并发改 history)',
130
+ '② 不同 Channel history 完全隔离',
131
+ '③ 同 Channel 多 Run 不互相污染',
132
+ '④ 页面/CLI/P2P/Supervisor 进同一 mailbox',
133
+ '⑤ Actor 崩溃可由 Supervisor 恢复',
134
+ '⑥ messageHistory 不再由 Pi 拥有',
135
+ ];
136
+ /** 两个百分比**不能合并** (leo 口径: 合并会产生误导) */
137
+ export const K2_PROGRESS = {
138
+ runContextExternalized: '100%',
139
+ sessionActorization: '未开始',
140
+ };
141
+ /**
142
+ * **口径统一说明 (2026-10-02, 必读, 否则会误读数字)**
143
+ *
144
+ * 判据原先按**行数**计 (`if (rx.test(line)) actual += 1`), 而 K2 收尾新加的播种判据按**匹配次数**计
145
+ * ⇒ 同一条台账在 1916 行那种"一行含两处"的地方给出 37 / 38 两个答案。**已统一为匹配次数**。
146
+ *
147
+ * 因此逐字段冻结值被整体重算过, session 级那几个"变大"**不是新增泄漏, 是口径变化**:
148
+ *
149
+ * | 字段 | 行数口径(旧) | 匹配口径(现) |
150
+ * | --- | --- | --- |
151
+ * | messageHistory | 53 | **56** |
152
+ * | currentChannelId | 21 | **24** |
153
+ * | currentGoalId | 19 | **22** |
154
+ * | currentAgentId | 20 | **21** |
155
+ * | currentRunId | 36(+1播种) | **38** |
156
+ *
157
+ * **同口径的迁移前/后对比** (用匹配口径回算提交 `04f64fb` = K2 第一次迁移之前):
158
+ * 迁移前 **193** → 现在 **161** (净 **-32**)。拆解: 三个 run 级字段 **-33** (15 + 8 + 10)
159
+ * + run-boundary 播种 **+1** (记账例外: 不计入"必须下降"的纯迁移统计, 也不算 K2 未完成)。
160
+ * 三个 run 级字段: currentOnStream 15→0 · currentSignal 8→0 · currentIntent 10→0。
161
+ * 其余 5 个 session/run-boundary 字段在**同口径**下逐字未变 (变大纯属换口径)。
162
+ */
163
+ export const RUN_CONTEXT_COUNT_METHOD = 'match-count (不是行数; 一行含两处记 2)';