@alan512/experienceengine 0.1.2 → 0.2.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.
Files changed (642) hide show
  1. package/.claude-plugin/marketplace.json +0 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.env.example +0 -0
  4. package/.mcp.json +4 -8
  5. package/LICENSE +21 -0
  6. package/README.md +288 -95
  7. package/README.zh-CN.md +316 -65
  8. package/dist/adapters/claude-code/event-store.d.ts +0 -0
  9. package/dist/adapters/claude-code/event-store.js +0 -0
  10. package/dist/adapters/claude-code/event-store.js.map +0 -0
  11. package/dist/adapters/claude-code/hook-normalizer.d.ts +0 -0
  12. package/dist/adapters/claude-code/hook-normalizer.js +0 -0
  13. package/dist/adapters/claude-code/hook-normalizer.js.map +0 -0
  14. package/dist/adapters/claude-code/runtime-projection.d.ts +0 -0
  15. package/dist/adapters/claude-code/runtime-projection.js +0 -0
  16. package/dist/adapters/claude-code/runtime-projection.js.map +0 -0
  17. package/dist/adapters/claude-code/session-store.d.ts +1 -0
  18. package/dist/adapters/claude-code/session-store.js +24 -1
  19. package/dist/adapters/claude-code/session-store.js.map +1 -1
  20. package/dist/adapters/codex/action-registry.d.ts +84 -0
  21. package/dist/adapters/codex/action-registry.js +277 -0
  22. package/dist/adapters/codex/action-registry.js.map +1 -0
  23. package/dist/adapters/codex/broker-tools.d.ts +114 -0
  24. package/dist/adapters/codex/broker-tools.js +130 -0
  25. package/dist/adapters/codex/broker-tools.js.map +1 -0
  26. package/dist/adapters/codex/instruction-template.d.ts +3 -0
  27. package/dist/adapters/codex/instruction-template.js +12 -0
  28. package/dist/adapters/codex/instruction-template.js.map +1 -0
  29. package/dist/adapters/codex/mcp-server.d.ts +59 -41
  30. package/dist/adapters/codex/mcp-server.js +177 -728
  31. package/dist/adapters/codex/mcp-server.js.map +1 -1
  32. package/dist/analyzer/candidate-signals.d.ts +3 -1
  33. package/dist/analyzer/candidate-signals.js +159 -0
  34. package/dist/analyzer/candidate-signals.js.map +1 -1
  35. package/dist/analyzer/experience-analyzer.d.ts +0 -0
  36. package/dist/analyzer/experience-analyzer.js +0 -0
  37. package/dist/analyzer/experience-analyzer.js.map +0 -0
  38. package/dist/analyzer/extraction-evidence.d.ts +0 -0
  39. package/dist/analyzer/extraction-evidence.js +0 -0
  40. package/dist/analyzer/extraction-evidence.js.map +0 -0
  41. package/dist/analyzer/llm-learning-gate.d.ts +12 -1
  42. package/dist/analyzer/llm-learning-gate.js +672 -16
  43. package/dist/analyzer/llm-learning-gate.js.map +1 -1
  44. package/dist/analyzer/node-deduper.d.ts +0 -0
  45. package/dist/analyzer/node-deduper.js +0 -0
  46. package/dist/analyzer/node-deduper.js.map +0 -0
  47. package/dist/analyzer/node-normalizer.d.ts +0 -0
  48. package/dist/analyzer/node-normalizer.js +0 -0
  49. package/dist/analyzer/node-normalizer.js.map +0 -0
  50. package/dist/analyzer/storage-gate.d.ts +0 -0
  51. package/dist/analyzer/storage-gate.js +0 -0
  52. package/dist/analyzer/storage-gate.js.map +0 -0
  53. package/dist/analyzer/strategy-extractor.d.ts +0 -0
  54. package/dist/analyzer/strategy-extractor.js +0 -0
  55. package/dist/analyzer/strategy-extractor.js.map +0 -0
  56. package/dist/analyzer/warning-extractor.d.ts +0 -0
  57. package/dist/analyzer/warning-extractor.js +0 -0
  58. package/dist/analyzer/warning-extractor.js.map +0 -0
  59. package/dist/cli/commands/backup.d.ts +0 -0
  60. package/dist/cli/commands/backup.js +0 -0
  61. package/dist/cli/commands/backup.js.map +0 -0
  62. package/dist/cli/commands/claude-hook.d.ts +0 -0
  63. package/dist/cli/commands/claude-hook.js +23 -7
  64. package/dist/cli/commands/claude-hook.js.map +1 -1
  65. package/dist/cli/commands/codex-mcp-server.d.ts +0 -0
  66. package/dist/cli/commands/codex-mcp-server.js +0 -0
  67. package/dist/cli/commands/codex-mcp-server.js.map +0 -0
  68. package/dist/cli/commands/codex.d.ts +60 -0
  69. package/dist/cli/commands/codex.js +188 -0
  70. package/dist/cli/commands/codex.js.map +1 -0
  71. package/dist/cli/commands/config.d.ts +0 -0
  72. package/dist/cli/commands/config.js +88 -2
  73. package/dist/cli/commands/config.js.map +1 -1
  74. package/dist/cli/commands/cool.d.ts +0 -0
  75. package/dist/cli/commands/cool.js +0 -0
  76. package/dist/cli/commands/cool.js.map +0 -0
  77. package/dist/cli/commands/disable.d.ts +0 -0
  78. package/dist/cli/commands/disable.js +0 -0
  79. package/dist/cli/commands/disable.js.map +0 -0
  80. package/dist/cli/commands/doctor.d.ts +4 -28
  81. package/dist/cli/commands/doctor.js +156 -68
  82. package/dist/cli/commands/doctor.js.map +1 -1
  83. package/dist/cli/commands/enable.d.ts +0 -0
  84. package/dist/cli/commands/enable.js +0 -0
  85. package/dist/cli/commands/enable.js.map +0 -0
  86. package/dist/cli/commands/evaluate.d.ts +9 -3
  87. package/dist/cli/commands/evaluate.js +31 -5
  88. package/dist/cli/commands/evaluate.js.map +1 -1
  89. package/dist/cli/commands/export.d.ts +0 -0
  90. package/dist/cli/commands/export.js +0 -0
  91. package/dist/cli/commands/export.js.map +0 -0
  92. package/dist/cli/commands/feedback.d.ts +0 -0
  93. package/dist/cli/commands/feedback.js +4 -0
  94. package/dist/cli/commands/feedback.js.map +1 -1
  95. package/dist/cli/commands/import.d.ts +0 -0
  96. package/dist/cli/commands/import.js +0 -0
  97. package/dist/cli/commands/import.js.map +0 -0
  98. package/dist/cli/commands/init.d.ts +28 -0
  99. package/dist/cli/commands/init.js +432 -0
  100. package/dist/cli/commands/init.js.map +1 -0
  101. package/dist/cli/commands/inspect.d.ts +0 -0
  102. package/dist/cli/commands/inspect.js +271 -37
  103. package/dist/cli/commands/inspect.js.map +1 -1
  104. package/dist/cli/commands/install.d.ts +0 -0
  105. package/dist/cli/commands/install.js +9 -0
  106. package/dist/cli/commands/install.js.map +1 -1
  107. package/dist/cli/commands/maintenance.d.ts +0 -0
  108. package/dist/cli/commands/maintenance.js +1 -1
  109. package/dist/cli/commands/maintenance.js.map +1 -1
  110. package/dist/cli/commands/mcp-server.d.ts +0 -0
  111. package/dist/cli/commands/mcp-server.js +4 -0
  112. package/dist/cli/commands/mcp-server.js.map +1 -1
  113. package/dist/cli/commands/models.d.ts +0 -0
  114. package/dist/cli/commands/models.js +0 -0
  115. package/dist/cli/commands/models.js.map +0 -0
  116. package/dist/cli/commands/repair.d.ts +0 -0
  117. package/dist/cli/commands/repair.js +3 -3
  118. package/dist/cli/commands/repair.js.map +1 -1
  119. package/dist/cli/commands/retire.d.ts +0 -0
  120. package/dist/cli/commands/retire.js +0 -0
  121. package/dist/cli/commands/retire.js.map +0 -0
  122. package/dist/cli/commands/rollback.d.ts +0 -0
  123. package/dist/cli/commands/rollback.js +0 -0
  124. package/dist/cli/commands/rollback.js.map +0 -0
  125. package/dist/cli/commands/stats.d.ts +0 -0
  126. package/dist/cli/commands/stats.js +0 -0
  127. package/dist/cli/commands/stats.js.map +0 -0
  128. package/dist/cli/commands/status.d.ts +0 -0
  129. package/dist/cli/commands/status.js +89 -7
  130. package/dist/cli/commands/status.js.map +1 -1
  131. package/dist/cli/commands/upgrade.d.ts +0 -0
  132. package/dist/cli/commands/upgrade.js +0 -0
  133. package/dist/cli/commands/upgrade.js.map +0 -0
  134. package/dist/cli/dispatch.d.ts +0 -0
  135. package/dist/cli/dispatch.js +36 -9
  136. package/dist/cli/dispatch.js.map +1 -1
  137. package/dist/cli/index.d.ts +0 -0
  138. package/dist/cli/index.js.map +0 -0
  139. package/dist/cli/state-model.d.ts +14 -0
  140. package/dist/cli/state-model.js +23 -0
  141. package/dist/cli/state-model.js.map +1 -0
  142. package/dist/config/config-schema.d.ts +209 -0
  143. package/dist/config/config-schema.js +168 -1
  144. package/dist/config/config-schema.js.map +1 -1
  145. package/dist/config/default-config.d.ts +0 -0
  146. package/dist/config/default-config.js +22 -1
  147. package/dist/config/default-config.js.map +1 -1
  148. package/dist/config/load-config.d.ts +0 -0
  149. package/dist/config/load-config.js +91 -2
  150. package/dist/config/load-config.js.map +1 -1
  151. package/dist/config/path-resolver.d.ts +0 -1
  152. package/dist/config/path-resolver.js +0 -2
  153. package/dist/config/path-resolver.js.map +1 -1
  154. package/dist/config/runtime-env.d.ts +8 -0
  155. package/dist/config/runtime-env.js +14 -0
  156. package/dist/config/runtime-env.js.map +1 -0
  157. package/dist/config/secrets-store.d.ts +15 -0
  158. package/dist/config/secrets-store.js +56 -0
  159. package/dist/config/secrets-store.js.map +1 -0
  160. package/dist/config/settings-store.d.ts +29 -0
  161. package/dist/config/settings-store.js +55 -0
  162. package/dist/config/settings-store.js.map +1 -1
  163. package/dist/controller/candidate-retriever.d.ts +49 -2
  164. package/dist/controller/candidate-retriever.js +258 -125
  165. package/dist/controller/candidate-retriever.js.map +1 -1
  166. package/dist/controller/injection-renderer.d.ts +0 -0
  167. package/dist/controller/injection-renderer.js +52 -1
  168. package/dist/controller/injection-renderer.js.map +1 -1
  169. package/dist/controller/injection-scorecard.d.ts +2 -2
  170. package/dist/controller/injection-scorecard.js +47 -1
  171. package/dist/controller/injection-scorecard.js.map +1 -1
  172. package/dist/controller/inline-notice.d.ts +0 -0
  173. package/dist/controller/inline-notice.js +0 -0
  174. package/dist/controller/inline-notice.js.map +0 -0
  175. package/dist/controller/intervention-controller.d.ts +3 -2
  176. package/dist/controller/intervention-controller.js +339 -17
  177. package/dist/controller/intervention-controller.js.map +1 -1
  178. package/dist/controller/lexical-retriever.d.ts +14 -0
  179. package/dist/controller/lexical-retriever.js +117 -0
  180. package/dist/controller/lexical-retriever.js.map +1 -0
  181. package/dist/controller/model-reranker.d.ts +20 -0
  182. package/dist/controller/model-reranker.js +187 -0
  183. package/dist/controller/model-reranker.js.map +1 -0
  184. package/dist/controller/node-ranker.d.ts +0 -0
  185. package/dist/controller/node-ranker.js +1 -0
  186. package/dist/controller/node-ranker.js.map +1 -1
  187. package/dist/controller/policy-enricher.d.ts +10 -0
  188. package/dist/controller/policy-enricher.js +186 -0
  189. package/dist/controller/policy-enricher.js.map +1 -0
  190. package/dist/controller/query-rewrite.d.ts +8 -0
  191. package/dist/controller/query-rewrite.js +69 -0
  192. package/dist/controller/query-rewrite.js.map +1 -0
  193. package/dist/controller/retrieval-context.d.ts +3 -0
  194. package/dist/controller/retrieval-context.js +37 -0
  195. package/dist/controller/retrieval-context.js.map +1 -0
  196. package/dist/controller/second-opinion-gate.d.ts +41 -0
  197. package/dist/controller/second-opinion-gate.js +225 -0
  198. package/dist/controller/second-opinion-gate.js.map +1 -0
  199. package/dist/controller/trigger-evaluator.d.ts +27 -2
  200. package/dist/controller/trigger-evaluator.js +63 -3
  201. package/dist/controller/trigger-evaluator.js.map +1 -1
  202. package/dist/distillation/errors.d.ts +0 -0
  203. package/dist/distillation/errors.js +0 -0
  204. package/dist/distillation/errors.js.map +0 -0
  205. package/dist/distillation/experience-family.d.ts +4 -0
  206. package/dist/distillation/experience-family.js +14 -0
  207. package/dist/distillation/experience-family.js.map +1 -0
  208. package/dist/distillation/host-llm.d.ts +1 -0
  209. package/dist/distillation/host-llm.js +5 -1
  210. package/dist/distillation/host-llm.js.map +1 -1
  211. package/dist/distillation/llm-distiller.d.ts +0 -0
  212. package/dist/distillation/llm-distiller.js +4 -0
  213. package/dist/distillation/llm-distiller.js.map +1 -1
  214. package/dist/distillation/merge-decider.d.ts +0 -0
  215. package/dist/distillation/merge-decider.js +4 -0
  216. package/dist/distillation/merge-decider.js.map +1 -1
  217. package/dist/distillation/model-catalog.d.ts +0 -0
  218. package/dist/distillation/model-catalog.js +0 -0
  219. package/dist/distillation/model-catalog.js.map +0 -0
  220. package/dist/distillation/prompt-contract.d.ts +1 -1
  221. package/dist/distillation/prompt-contract.js +6 -1
  222. package/dist/distillation/prompt-contract.js.map +1 -1
  223. package/dist/distillation/providers/anthropic.d.ts +0 -0
  224. package/dist/distillation/providers/anthropic.js +0 -0
  225. package/dist/distillation/providers/anthropic.js.map +0 -0
  226. package/dist/distillation/providers/azure-openai.d.ts +0 -0
  227. package/dist/distillation/providers/azure-openai.js +0 -0
  228. package/dist/distillation/providers/azure-openai.js.map +0 -0
  229. package/dist/distillation/providers/baidu-qianfan.d.ts +0 -0
  230. package/dist/distillation/providers/baidu-qianfan.js +0 -0
  231. package/dist/distillation/providers/baidu-qianfan.js.map +0 -0
  232. package/dist/distillation/providers/bedrock.d.ts +0 -0
  233. package/dist/distillation/providers/bedrock.js +0 -0
  234. package/dist/distillation/providers/bedrock.js.map +0 -0
  235. package/dist/distillation/providers/dashscope.d.ts +0 -0
  236. package/dist/distillation/providers/dashscope.js +0 -0
  237. package/dist/distillation/providers/dashscope.js.map +0 -0
  238. package/dist/distillation/providers/deepseek.d.ts +0 -0
  239. package/dist/distillation/providers/deepseek.js +0 -0
  240. package/dist/distillation/providers/deepseek.js.map +0 -0
  241. package/dist/distillation/providers/gemini.d.ts +0 -0
  242. package/dist/distillation/providers/gemini.js +5 -1
  243. package/dist/distillation/providers/gemini.js.map +1 -1
  244. package/dist/distillation/providers/google-adc.d.ts +0 -0
  245. package/dist/distillation/providers/google-adc.js +0 -0
  246. package/dist/distillation/providers/google-adc.js.map +0 -0
  247. package/dist/distillation/providers/minimax.d.ts +0 -0
  248. package/dist/distillation/providers/minimax.js +0 -0
  249. package/dist/distillation/providers/minimax.js.map +0 -0
  250. package/dist/distillation/providers/moonshot.d.ts +0 -0
  251. package/dist/distillation/providers/moonshot.js +0 -0
  252. package/dist/distillation/providers/moonshot.js.map +0 -0
  253. package/dist/distillation/providers/openai-compatible-factory.d.ts +0 -0
  254. package/dist/distillation/providers/openai-compatible-factory.js +0 -0
  255. package/dist/distillation/providers/openai-compatible-factory.js.map +0 -0
  256. package/dist/distillation/providers/openai-compatible.d.ts +0 -0
  257. package/dist/distillation/providers/openai-compatible.js +0 -0
  258. package/dist/distillation/providers/openai-compatible.js.map +0 -0
  259. package/dist/distillation/providers/openai.d.ts +0 -0
  260. package/dist/distillation/providers/openai.js +0 -0
  261. package/dist/distillation/providers/openai.js.map +0 -0
  262. package/dist/distillation/providers/openrouter.d.ts +0 -0
  263. package/dist/distillation/providers/openrouter.js +0 -0
  264. package/dist/distillation/providers/openrouter.js.map +0 -0
  265. package/dist/distillation/providers/registry.d.ts +0 -0
  266. package/dist/distillation/providers/registry.js +0 -0
  267. package/dist/distillation/providers/registry.js.map +0 -0
  268. package/dist/distillation/providers/siliconflow.d.ts +0 -0
  269. package/dist/distillation/providers/siliconflow.js +0 -0
  270. package/dist/distillation/providers/siliconflow.js.map +0 -0
  271. package/dist/distillation/providers/tencent-hunyuan.d.ts +0 -0
  272. package/dist/distillation/providers/tencent-hunyuan.js +0 -0
  273. package/dist/distillation/providers/tencent-hunyuan.js.map +0 -0
  274. package/dist/distillation/providers/types.d.ts +0 -0
  275. package/dist/distillation/providers/types.js +0 -0
  276. package/dist/distillation/providers/types.js.map +0 -0
  277. package/dist/distillation/providers/volcengine-ark.d.ts +0 -0
  278. package/dist/distillation/providers/volcengine-ark.js +0 -0
  279. package/dist/distillation/providers/volcengine-ark.js.map +0 -0
  280. package/dist/distillation/providers/zhipu.d.ts +0 -0
  281. package/dist/distillation/providers/zhipu.js +0 -0
  282. package/dist/distillation/providers/zhipu.js.map +0 -0
  283. package/dist/distillation/queue-worker.d.ts +0 -0
  284. package/dist/distillation/queue-worker.js +78 -9
  285. package/dist/distillation/queue-worker.js.map +1 -1
  286. package/dist/distillation/types.d.ts +0 -0
  287. package/dist/distillation/types.js +0 -0
  288. package/dist/distillation/types.js.map +0 -0
  289. package/dist/evaluation/benchmark-report.d.ts +0 -0
  290. package/dist/evaluation/benchmark-report.js +0 -0
  291. package/dist/evaluation/benchmark-report.js.map +0 -0
  292. package/dist/evaluation/benchmark-summary.d.ts +0 -0
  293. package/dist/evaluation/benchmark-summary.js +0 -0
  294. package/dist/evaluation/benchmark-summary.js.map +0 -0
  295. package/dist/evaluation/codex-lifecycle-validation.d.ts +60 -0
  296. package/dist/evaluation/codex-lifecycle-validation.js +233 -0
  297. package/dist/evaluation/codex-lifecycle-validation.js.map +1 -0
  298. package/dist/evaluation/hybrid-phase1-rollout-summary.d.ts +63 -0
  299. package/dist/evaluation/hybrid-phase1-rollout-summary.js +108 -0
  300. package/dist/evaluation/hybrid-phase1-rollout-summary.js.map +1 -0
  301. package/dist/evaluation/hybrid-phase3-gate-metrics.d.ts +26 -0
  302. package/dist/evaluation/hybrid-phase3-gate-metrics.js +23 -0
  303. package/dist/evaluation/hybrid-phase3-gate-metrics.js.map +1 -0
  304. package/dist/evaluation/openclaw-baseline.d.ts +8 -0
  305. package/dist/evaluation/openclaw-baseline.js +27 -0
  306. package/dist/evaluation/openclaw-baseline.js.map +1 -1
  307. package/dist/evaluation/openclaw-scenarios.d.ts +0 -0
  308. package/dist/evaluation/openclaw-scenarios.js +0 -0
  309. package/dist/evaluation/openclaw-scenarios.js.map +0 -0
  310. package/dist/experience-management/governance-observability.d.ts +13 -0
  311. package/dist/experience-management/governance-observability.js +37 -0
  312. package/dist/experience-management/governance-observability.js.map +1 -0
  313. package/dist/experience-management/node-lifecycle-governance.d.ts +8 -0
  314. package/dist/experience-management/node-lifecycle-governance.js +80 -0
  315. package/dist/experience-management/node-lifecycle-governance.js.map +1 -0
  316. package/dist/experience-management/task-management-signals.d.ts +29 -0
  317. package/dist/experience-management/task-management-signals.js +148 -0
  318. package/dist/experience-management/task-management-signals.js.map +1 -0
  319. package/dist/feedback/automatic-attribution.d.ts +0 -0
  320. package/dist/feedback/automatic-attribution.js +0 -0
  321. package/dist/feedback/automatic-attribution.js.map +0 -0
  322. package/dist/feedback/feedback-manager.d.ts +4 -1
  323. package/dist/feedback/feedback-manager.js +11 -22
  324. package/dist/feedback/feedback-manager.js.map +1 -1
  325. package/dist/feedback/harm-detector.d.ts +0 -0
  326. package/dist/feedback/harm-detector.js +0 -0
  327. package/dist/feedback/harm-detector.js.map +0 -0
  328. package/dist/feedback/state-transition.d.ts +6 -1
  329. package/dist/feedback/state-transition.js +14 -2
  330. package/dist/feedback/state-transition.js.map +1 -1
  331. package/dist/feedback/stats-updater.d.ts +0 -0
  332. package/dist/feedback/stats-updater.js +0 -0
  333. package/dist/feedback/stats-updater.js.map +0 -0
  334. package/dist/hybrid/capsule-builder.d.ts +23 -0
  335. package/dist/hybrid/capsule-builder.js +114 -0
  336. package/dist/hybrid/capsule-builder.js.map +1 -0
  337. package/dist/hybrid/explain-provider-client.d.ts +19 -0
  338. package/dist/hybrid/explain-provider-client.js +34 -0
  339. package/dist/hybrid/explain-provider-client.js.map +1 -0
  340. package/dist/hybrid/postmortem-provider-client.d.ts +19 -0
  341. package/dist/hybrid/postmortem-provider-client.js +34 -0
  342. package/dist/hybrid/postmortem-provider-client.js.map +1 -0
  343. package/dist/hybrid/rollout.d.ts +9 -0
  344. package/dist/hybrid/rollout.js +49 -0
  345. package/dist/hybrid/rollout.js.map +1 -0
  346. package/dist/hybrid/router.d.ts +4 -0
  347. package/dist/hybrid/router.js +62 -0
  348. package/dist/hybrid/router.js.map +1 -0
  349. package/dist/hybrid/types.d.ts +140 -0
  350. package/dist/{compiler → hybrid}/types.js +0 -0
  351. package/dist/{packs → hybrid}/types.js.map +1 -1
  352. package/dist/hybrid/validators.d.ts +5 -0
  353. package/dist/hybrid/validators.js +94 -0
  354. package/dist/hybrid/validators.js.map +1 -0
  355. package/dist/hybrid/worker-client.d.ts +61 -0
  356. package/dist/hybrid/worker-client.js +196 -0
  357. package/dist/hybrid/worker-client.js.map +1 -0
  358. package/dist/hybrid/workers/explain-decision-llm.d.ts +8 -0
  359. package/dist/hybrid/workers/explain-decision-llm.js +152 -0
  360. package/dist/hybrid/workers/explain-decision-llm.js.map +1 -0
  361. package/dist/hybrid/workers/explain-decision.d.ts +2 -0
  362. package/dist/hybrid/workers/explain-decision.js +40 -0
  363. package/dist/hybrid/workers/explain-decision.js.map +1 -0
  364. package/dist/hybrid/workers/postmortem-review-llm.d.ts +8 -0
  365. package/dist/hybrid/workers/postmortem-review-llm.js +398 -0
  366. package/dist/hybrid/workers/postmortem-review-llm.js.map +1 -0
  367. package/dist/hybrid/workers/postmortem-review.d.ts +2 -0
  368. package/dist/hybrid/workers/postmortem-review.js +66 -0
  369. package/dist/hybrid/workers/postmortem-review.js.map +1 -0
  370. package/dist/index.d.ts +0 -0
  371. package/dist/index.js +0 -0
  372. package/dist/index.js.map +0 -0
  373. package/dist/input/context-summary-adapter.d.ts +0 -0
  374. package/dist/input/context-summary-adapter.js +0 -0
  375. package/dist/input/context-summary-adapter.js.map +0 -0
  376. package/dist/input/input-adapter.d.ts +0 -0
  377. package/dist/input/input-adapter.js +2 -1
  378. package/dist/input/input-adapter.js.map +1 -1
  379. package/dist/input/outcome-resolver.d.ts +0 -0
  380. package/dist/input/outcome-resolver.js +5 -5
  381. package/dist/input/outcome-resolver.js.map +1 -1
  382. package/dist/input/scope-resolver.d.ts +0 -0
  383. package/dist/input/scope-resolver.js +0 -0
  384. package/dist/input/scope-resolver.js.map +0 -0
  385. package/dist/input/tasktype-resolver.d.ts +0 -0
  386. package/dist/input/tasktype-resolver.js +2 -0
  387. package/dist/input/tasktype-resolver.js.map +1 -1
  388. package/dist/input/tool-event-significance.d.ts +5 -0
  389. package/dist/input/tool-event-significance.js +7 -0
  390. package/dist/input/tool-event-significance.js.map +1 -0
  391. package/dist/install/claude-cli.d.ts +0 -0
  392. package/dist/install/claude-cli.js +0 -0
  393. package/dist/install/claude-cli.js.map +0 -0
  394. package/dist/install/claude-code-doctor.d.ts +8 -2
  395. package/dist/install/claude-code-doctor.js +54 -9
  396. package/dist/install/claude-code-doctor.js.map +1 -1
  397. package/dist/install/claude-code-installer.d.ts +0 -0
  398. package/dist/install/claude-code-installer.js +50 -1
  399. package/dist/install/claude-code-installer.js.map +1 -1
  400. package/dist/install/claude-marketplace-state.d.ts +14 -0
  401. package/dist/install/claude-marketplace-state.js +47 -0
  402. package/dist/install/claude-marketplace-state.js.map +1 -0
  403. package/dist/install/claude-runtime-target.d.ts +0 -0
  404. package/dist/install/claude-runtime-target.js +0 -0
  405. package/dist/install/claude-runtime-target.js.map +0 -0
  406. package/dist/install/codex-cli.d.ts +15 -0
  407. package/dist/install/codex-cli.js +55 -3
  408. package/dist/install/codex-cli.js.map +1 -1
  409. package/dist/install/codex-installer.d.ts +18 -0
  410. package/dist/install/codex-installer.js +91 -1
  411. package/dist/install/codex-installer.js.map +1 -1
  412. package/dist/install/codex-runtime-target.d.ts +0 -0
  413. package/dist/install/codex-runtime-target.js +0 -0
  414. package/dist/install/codex-runtime-target.js.map +0 -0
  415. package/dist/install/host-detection.d.ts +0 -0
  416. package/dist/install/host-detection.js +0 -0
  417. package/dist/install/host-detection.js.map +0 -0
  418. package/dist/install/openclaw-cli.d.ts +11 -0
  419. package/dist/install/openclaw-cli.js +0 -0
  420. package/dist/install/openclaw-cli.js.map +1 -1
  421. package/dist/install/openclaw-installer.d.ts +12 -0
  422. package/dist/install/openclaw-installer.js +198 -31
  423. package/dist/install/openclaw-installer.js.map +1 -1
  424. package/dist/install/public-install.d.ts +14 -4
  425. package/dist/install/public-install.js +20 -7
  426. package/dist/install/public-install.js.map +1 -1
  427. package/dist/install/registry-health.d.ts +0 -0
  428. package/dist/install/registry-health.js +0 -0
  429. package/dist/install/registry-health.js.map +0 -0
  430. package/dist/interaction/operational-actions-service.d.ts +0 -0
  431. package/dist/interaction/operational-actions-service.js +0 -0
  432. package/dist/interaction/operational-actions-service.js.map +0 -0
  433. package/dist/interaction/operational-service.d.ts +0 -0
  434. package/dist/interaction/operational-service.js +0 -0
  435. package/dist/interaction/operational-service.js.map +0 -0
  436. package/dist/interaction/repo-summary.d.ts +3 -17
  437. package/dist/interaction/repo-summary.js +10 -27
  438. package/dist/interaction/repo-summary.js.map +1 -1
  439. package/dist/interaction/service.d.ts +59 -95
  440. package/dist/interaction/service.js +505 -266
  441. package/dist/interaction/service.js.map +1 -1
  442. package/dist/interaction/state-artifact-service.d.ts +0 -0
  443. package/dist/interaction/state-artifact-service.js +0 -0
  444. package/dist/interaction/state-artifact-service.js.map +0 -0
  445. package/dist/maintenance/claude-validate-print.d.ts +0 -0
  446. package/dist/maintenance/claude-validate-print.js +0 -0
  447. package/dist/maintenance/claude-validate-print.js.map +0 -0
  448. package/dist/maintenance/embedding-smoke.d.ts +0 -0
  449. package/dist/maintenance/embedding-smoke.js +0 -0
  450. package/dist/maintenance/embedding-smoke.js.map +0 -0
  451. package/dist/maintenance/redistill-rule-nodes.d.ts +0 -0
  452. package/dist/maintenance/redistill-rule-nodes.js +0 -0
  453. package/dist/maintenance/redistill-rule-nodes.js.map +0 -0
  454. package/dist/maintenance/scope-merge.d.ts +0 -1
  455. package/dist/maintenance/scope-merge.js +0 -20
  456. package/dist/maintenance/scope-merge.js.map +1 -1
  457. package/dist/maintenance/warning-variant-cleanup.d.ts +0 -0
  458. package/dist/maintenance/warning-variant-cleanup.js +0 -0
  459. package/dist/maintenance/warning-variant-cleanup.js.map +0 -0
  460. package/dist/plugin/fixture-sanitizer.d.ts +0 -0
  461. package/dist/plugin/fixture-sanitizer.js +0 -0
  462. package/dist/plugin/fixture-sanitizer.js.map +0 -0
  463. package/dist/plugin/hooks/before-prompt-build.d.ts +1 -0
  464. package/dist/plugin/hooks/before-prompt-build.js +4 -1
  465. package/dist/plugin/hooks/before-prompt-build.js.map +1 -1
  466. package/dist/plugin/hooks/message-sent.d.ts +0 -0
  467. package/dist/plugin/hooks/message-sent.js +0 -0
  468. package/dist/plugin/hooks/message-sent.js.map +0 -0
  469. package/dist/plugin/hooks/tool-result-persist.d.ts +0 -0
  470. package/dist/plugin/hooks/tool-result-persist.js +0 -0
  471. package/dist/plugin/hooks/tool-result-persist.js.map +0 -0
  472. package/dist/plugin/openclaw-install-state.d.ts +39 -0
  473. package/dist/plugin/openclaw-install-state.js +24 -0
  474. package/dist/plugin/openclaw-install-state.js.map +1 -0
  475. package/dist/plugin/openclaw-plugin.d.ts +148 -0
  476. package/dist/plugin/openclaw-plugin.js +98 -7
  477. package/dist/plugin/openclaw-plugin.js.map +1 -1
  478. package/dist/plugin/openclaw-routine-interaction.d.ts +7 -0
  479. package/dist/plugin/openclaw-routine-interaction.js +301 -0
  480. package/dist/plugin/openclaw-routine-interaction.js.map +1 -0
  481. package/dist/plugin/openclaw-runtime-defaults.d.ts +16 -0
  482. package/dist/plugin/openclaw-runtime-defaults.js +16 -0
  483. package/dist/plugin/openclaw-runtime-defaults.js.map +1 -0
  484. package/dist/plugin/runtime-capture.d.ts +0 -0
  485. package/dist/plugin/runtime-capture.js +0 -0
  486. package/dist/plugin/runtime-capture.js.map +0 -0
  487. package/dist/plugin/runtime-helpers.d.ts +0 -0
  488. package/dist/plugin/runtime-helpers.js +0 -0
  489. package/dist/plugin/runtime-helpers.js.map +0 -0
  490. package/dist/runtime/service.d.ts +33 -6
  491. package/dist/runtime/service.js +427 -50
  492. package/dist/runtime/service.js.map +1 -1
  493. package/dist/store/logs/jsonl-logger.d.ts +0 -0
  494. package/dist/store/logs/jsonl-logger.js +0 -0
  495. package/dist/store/logs/jsonl-logger.js.map +0 -0
  496. package/dist/store/sqlite/db.d.ts +0 -0
  497. package/dist/store/sqlite/db.js +37 -0
  498. package/dist/store/sqlite/db.js.map +1 -1
  499. package/dist/store/sqlite/migrations.d.ts +0 -0
  500. package/dist/store/sqlite/migrations.js +0 -0
  501. package/dist/store/sqlite/migrations.js.map +0 -0
  502. package/dist/store/sqlite/repositories/candidate-repo.d.ts +0 -0
  503. package/dist/store/sqlite/repositories/candidate-repo.js +8 -2
  504. package/dist/store/sqlite/repositories/candidate-repo.js.map +1 -1
  505. package/dist/store/sqlite/repositories/distillation-job-repo.d.ts +0 -0
  506. package/dist/store/sqlite/repositories/distillation-job-repo.js +0 -0
  507. package/dist/store/sqlite/repositories/distillation-job-repo.js.map +0 -0
  508. package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.d.ts +11 -0
  509. package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.js +76 -0
  510. package/dist/store/sqlite/repositories/hybrid-invocation-trace-repo.js.map +1 -0
  511. package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.d.ts +11 -0
  512. package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.js +73 -0
  513. package/dist/store/sqlite/repositories/hybrid-review-artifact-repo.js.map +1 -0
  514. package/dist/store/sqlite/repositories/injection-repo.d.ts +1 -0
  515. package/dist/store/sqlite/repositories/injection-repo.js +11 -0
  516. package/dist/store/sqlite/repositories/injection-repo.js.map +1 -1
  517. package/dist/store/sqlite/repositories/input-record-repo.d.ts +3 -0
  518. package/dist/store/sqlite/repositories/input-record-repo.js +35 -0
  519. package/dist/store/sqlite/repositories/input-record-repo.js.map +1 -1
  520. package/dist/store/sqlite/repositories/node-repo.d.ts +3 -0
  521. package/dist/store/sqlite/repositories/node-repo.js +62 -8
  522. package/dist/store/sqlite/repositories/node-repo.js.map +1 -1
  523. package/dist/store/sqlite/repositories/outcome-record-repo.d.ts +0 -0
  524. package/dist/store/sqlite/repositories/outcome-record-repo.js +0 -0
  525. package/dist/store/sqlite/repositories/outcome-record-repo.js.map +0 -0
  526. package/dist/store/sqlite/repositories/review-event-repo.d.ts +0 -0
  527. package/dist/store/sqlite/repositories/review-event-repo.js +0 -0
  528. package/dist/store/sqlite/repositories/review-event-repo.js.map +0 -0
  529. package/dist/store/sqlite/repositories/scope-repo.d.ts +0 -0
  530. package/dist/store/sqlite/repositories/scope-repo.js +0 -0
  531. package/dist/store/sqlite/repositories/scope-repo.js.map +0 -0
  532. package/dist/store/sqlite/repositories/stats-repo.d.ts +0 -0
  533. package/dist/store/sqlite/repositories/stats-repo.js +0 -0
  534. package/dist/store/sqlite/repositories/stats-repo.js.map +0 -0
  535. package/dist/store/sqlite/repositories/task-run-repo.d.ts +2 -0
  536. package/dist/store/sqlite/repositories/task-run-repo.js +18 -2
  537. package/dist/store/sqlite/repositories/task-run-repo.js.map +1 -1
  538. package/dist/store/sqlite/schema.sql +49 -49
  539. package/dist/store/vector/api-embedding-provider.d.ts +2 -0
  540. package/dist/store/vector/api-embedding-provider.js +23 -19
  541. package/dist/store/vector/api-embedding-provider.js.map +1 -1
  542. package/dist/store/vector/embeddings.d.ts +1 -1
  543. package/dist/store/vector/embeddings.js +26 -5
  544. package/dist/store/vector/embeddings.js.map +1 -1
  545. package/dist/store/vector/lancedb.d.ts +0 -0
  546. package/dist/store/vector/lancedb.js +0 -0
  547. package/dist/store/vector/lancedb.js.map +0 -0
  548. package/dist/store/vector/local-provider.d.ts +0 -0
  549. package/dist/store/vector/local-provider.js +0 -0
  550. package/dist/store/vector/local-provider.js.map +0 -0
  551. package/dist/store/vector/node-index.d.ts +0 -0
  552. package/dist/store/vector/node-index.js +0 -0
  553. package/dist/store/vector/node-index.js.map +0 -0
  554. package/dist/store/vector/provider-types.d.ts +0 -0
  555. package/dist/store/vector/provider-types.js +0 -0
  556. package/dist/store/vector/provider-types.js.map +0 -0
  557. package/dist/types/analyzer.d.ts +0 -0
  558. package/dist/types/analyzer.js +0 -0
  559. package/dist/types/analyzer.js.map +0 -0
  560. package/dist/types/domain.d.ts +166 -47
  561. package/dist/types/domain.js +0 -0
  562. package/dist/types/domain.js.map +0 -0
  563. package/dist/types/plugin.d.ts +3 -1
  564. package/dist/types/plugin.js +0 -0
  565. package/dist/types/plugin.js.map +0 -0
  566. package/dist/types/storage.d.ts +0 -0
  567. package/dist/types/storage.js +0 -0
  568. package/dist/types/storage.js.map +0 -0
  569. package/dist/utils/clock.d.ts +0 -0
  570. package/dist/utils/clock.js +0 -0
  571. package/dist/utils/clock.js.map +0 -0
  572. package/dist/utils/errors.d.ts +0 -0
  573. package/dist/utils/errors.js +0 -0
  574. package/dist/utils/errors.js.map +0 -0
  575. package/dist/utils/hashing.d.ts +0 -0
  576. package/dist/utils/hashing.js +0 -0
  577. package/dist/utils/hashing.js.map +0 -0
  578. package/dist/utils/ids.d.ts +0 -0
  579. package/dist/utils/ids.js +0 -0
  580. package/dist/utils/ids.js.map +0 -0
  581. package/dist/utils/text.d.ts +0 -0
  582. package/dist/utils/text.js +0 -0
  583. package/dist/utils/text.js.map +0 -0
  584. package/dist/version/package-version.d.ts +0 -0
  585. package/dist/version/package-version.js +0 -0
  586. package/dist/version/package-version.js.map +0 -0
  587. package/dist/version/remote-release.d.ts +0 -0
  588. package/dist/version/remote-release.js +0 -0
  589. package/dist/version/remote-release.js.map +0 -0
  590. package/docs/releases/v0.1.0.md +0 -0
  591. package/docs/releases/v0.1.1.md +0 -0
  592. package/docs/releases/v0.1.2.md +3 -3
  593. package/docs/releases/v0.1.3.md +95 -0
  594. package/docs/releases/v0.2.0.md +85 -0
  595. package/docs/user-guide.md +263 -133
  596. package/hooks/hooks.json +0 -0
  597. package/openclaw.plugin.json +81 -1
  598. package/package.json +25 -16
  599. package/plugins/claude-code-experienceengine/.claude-plugin/plugin.json +1 -1
  600. package/plugins/claude-code-experienceengine/.mcp.json +4 -3
  601. package/plugins/claude-code-experienceengine/hooks/hooks.json +0 -0
  602. package/plugins/claude-code-experienceengine/scripts/claude-hook.sh +30 -1
  603. package/plugins/claude-code-experienceengine/scripts/install-deps.sh +41 -6
  604. package/scripts/claude-plugin/claude-hook.sh +0 -0
  605. package/scripts/claude-plugin/install-deps.sh +0 -0
  606. package/dist/cli/commands/pack.d.ts +0 -1
  607. package/dist/cli/commands/pack.js +0 -321
  608. package/dist/cli/commands/pack.js.map +0 -1
  609. package/dist/compiler/agents-renderer.d.ts +0 -4
  610. package/dist/compiler/agents-renderer.js +0 -105
  611. package/dist/compiler/agents-renderer.js.map +0 -1
  612. package/dist/compiler/claude-renderer.d.ts +0 -2
  613. package/dist/compiler/claude-renderer.js +0 -40
  614. package/dist/compiler/claude-renderer.js.map +0 -1
  615. package/dist/compiler/codex-renderer.d.ts +0 -2
  616. package/dist/compiler/codex-renderer.js +0 -40
  617. package/dist/compiler/codex-renderer.js.map +0 -1
  618. package/dist/compiler/compiler.d.ts +0 -4
  619. package/dist/compiler/compiler.js +0 -87
  620. package/dist/compiler/compiler.js.map +0 -1
  621. package/dist/compiler/deployer.d.ts +0 -21
  622. package/dist/compiler/deployer.js +0 -64
  623. package/dist/compiler/deployer.js.map +0 -1
  624. package/dist/compiler/github-renderer.d.ts +0 -2
  625. package/dist/compiler/github-renderer.js +0 -63
  626. package/dist/compiler/github-renderer.js.map +0 -1
  627. package/dist/compiler/types.d.ts +0 -45
  628. package/dist/compiler/types.js.map +0 -1
  629. package/dist/interaction/pack-actions-service.d.ts +0 -59
  630. package/dist/interaction/pack-actions-service.js +0 -172
  631. package/dist/interaction/pack-actions-service.js.map +0 -1
  632. package/dist/packs/fs-registry.d.ts +0 -27
  633. package/dist/packs/fs-registry.js +0 -216
  634. package/dist/packs/fs-registry.js.map +0 -1
  635. package/dist/packs/index-sync.d.ts +0 -9
  636. package/dist/packs/index-sync.js +0 -54
  637. package/dist/packs/index-sync.js.map +0 -1
  638. package/dist/packs/types.d.ts +0 -55
  639. package/dist/packs/types.js +0 -2
  640. package/dist/store/sqlite/repositories/pack-repo.d.ts +0 -16
  641. package/dist/store/sqlite/repositories/pack-repo.js +0 -192
  642. package/dist/store/sqlite/repositories/pack-repo.js.map +0 -1
@@ -1,12 +1,15 @@
1
- import { compilePack } from "../compiler/compiler.js";
2
- import { deployCompiledPack } from "../compiler/deployer.js";
3
- import { ExperiencePackRegistry } from "../packs/fs-registry.js";
4
1
  import { buildInjectionScorecard } from "../controller/injection-scorecard.js";
5
2
  import { buildBenchmarkSummary } from "../evaluation/benchmark-summary.js";
3
+ import { buildExplainDecisionCapsule } from "../hybrid/capsule-builder.js";
4
+ import { resolveHybridExplainProviderEndpoint } from "../hybrid/explain-provider-client.js";
5
+ import { resolveHybridRolloutState } from "../hybrid/rollout.js";
6
+ import { selectHybridRoute } from "../hybrid/router.js";
7
+ import { HybridWorkerClient } from "../hybrid/worker-client.js";
6
8
  import { resolveScope } from "../input/scope-resolver.js";
7
9
  import { bootstrapDatabase, openDatabase } from "../store/sqlite/db.js";
8
10
  import { CandidateRepository } from "../store/sqlite/repositories/candidate-repo.js";
9
11
  import { DistillationJobRepository } from "../store/sqlite/repositories/distillation-job-repo.js";
12
+ import { HybridInvocationTraceRepository } from "../store/sqlite/repositories/hybrid-invocation-trace-repo.js";
10
13
  import { InputRecordRepository } from "../store/sqlite/repositories/input-record-repo.js";
11
14
  import { InjectionRepository } from "../store/sqlite/repositories/injection-repo.js";
12
15
  import { NodeRepository } from "../store/sqlite/repositories/node-repo.js";
@@ -14,11 +17,78 @@ import { OutcomeRecordRepository } from "../store/sqlite/repositories/outcome-re
14
17
  import { ReviewEventRepository } from "../store/sqlite/repositories/review-event-repo.js";
15
18
  import { ScopeRepository } from "../store/sqlite/repositories/scope-repo.js";
16
19
  import { TaskRunRepository } from "../store/sqlite/repositories/task-run-repo.js";
17
- import { ExperiencePackRepository } from "../store/sqlite/repositories/pack-repo.js";
18
- import { transitionState, transitionValidationState } from "../feedback/state-transition.js";
20
+ import { applyGovernedNodeFeedback, deriveNodeOriginProfileForNode } from "../experience-management/node-lifecycle-governance.js";
21
+ import { deriveGovernanceSignals, isPotentialMisfire } from "../experience-management/governance-observability.js";
19
22
  import { nowIso } from "../utils/clock.js";
20
23
  import { createId } from "../utils/ids.js";
21
24
  import { buildRepoSummary } from "./repo-summary.js";
25
+ const normalizeHybridExplainPrompt = (value) => value
26
+ .toLowerCase()
27
+ .replace(/\s+/g, " ")
28
+ .trim();
29
+ export const isExplicitHybridExplanationRequest = (userMessage) => {
30
+ const message = normalizeHybridExplainPrompt(userMessage);
31
+ const mentionsEe = message.includes("experienceengine")
32
+ || message.includes("experience engine")
33
+ || /\bee\b/.test(message);
34
+ if (!mentionsEe) {
35
+ return false;
36
+ }
37
+ const hasExplainIntent = /\bwhy\b/.test(message)
38
+ || /\bexplain\b/.test(message)
39
+ || (/\bwhat\b/.test(message) && /\binject\b/.test(message))
40
+ || (/\bwhy\b/.test(message) && /\bmatch\b/.test(message))
41
+ || (/\bwhy\b/.test(message) && /\bskip\b/.test(message))
42
+ || (/\bwhy\b/.test(message) && /\bconservative\b/.test(message))
43
+ || message.includes("stayed quiet")
44
+ || message.includes("stay quiet");
45
+ return hasExplainIntent;
46
+ };
47
+ export const decideHybridExplainRoute = (userMessage) => selectHybridRoute({
48
+ taskStage: "prompt",
49
+ explicitExplanationRequest: isExplicitHybridExplanationRequest(userMessage),
50
+ existingConservativePathRequired: false,
51
+ completedRun: false,
52
+ terminalOutcomeRecorded: false,
53
+ boundedPosttaskCapsuleAvailable: false,
54
+ postmortemAlreadyRecorded: false,
55
+ lightweightOrExcludedTask: false,
56
+ directionalCorrectionPresent: false,
57
+ injectedNodeInteractionPresent: false,
58
+ retryOrInvalidationSignaturePresent: false,
59
+ meaningfulFailureSignaturePresent: false,
60
+ conservativeTransitionReviewWorthy: false,
61
+ rolloutAllowsAsyncPostmortem: false
62
+ });
63
+ export const deriveStructuredSilenceReason = (input) => {
64
+ const { inspection, readiness } = input;
65
+ const learningReason = inspection.learningReason?.toLowerCase() ?? "";
66
+ const hasEarlyRepoEvidence = readiness.rawRecords < 3 && readiness.taskRuns < 3 && readiness.candidates === 0 && readiness.nodes === 0;
67
+ if (inspection.learningStatus === "not_applicable") {
68
+ return "non_applicable_turn";
69
+ }
70
+ if (inspection.learningStatus === "rejected" && learningReason.includes("expression-layer refinement")) {
71
+ return "non_applicable_turn";
72
+ }
73
+ if (inspection.scorecard?.decisionReason === "ambiguous_same_family_candidate"
74
+ || inspection.scorecard?.decisionReason === "promising_candidate_quality"
75
+ || inspection.intervention === "shadow"
76
+ || inspection.intervention === "holdout") {
77
+ return "withheld_low_confidence";
78
+ }
79
+ if (hasEarlyRepoEvidence) {
80
+ return "warming_up";
81
+ }
82
+ if (inspection.learningStatus === "captured"
83
+ || learningReason.includes("llm gate failed")
84
+ || learningReason.includes("rule fallback rejected candidate")) {
85
+ return "unknown";
86
+ }
87
+ if (inspection.intervention === "skip" && (readiness.rawRecords > 0 || readiness.taskRuns > 0 || readiness.candidates > 0 || readiness.nodes > 0)) {
88
+ return "no_strong_match";
89
+ }
90
+ return "unknown";
91
+ };
22
92
  const toReviewEvent = (nodeId, eventType, source, taskRunId) => ({
23
93
  id: createId("review"),
24
94
  node_id: nodeId,
@@ -27,6 +97,65 @@ const toReviewEvent = (nodeId, eventType, source, taskRunId) => ({
27
97
  source,
28
98
  created_at: nowIso()
29
99
  });
100
+ const deriveNodeRisk = (node) => {
101
+ if (node.state === "candidate") {
102
+ return "high";
103
+ }
104
+ if (node.state === "priority_candidate") {
105
+ return "medium";
106
+ }
107
+ if (node.state === "cooling" || node.harmed_count > 0 || node.node_type === "warning") {
108
+ return node.harmed_count > node.helped_count ? "high" : "medium";
109
+ }
110
+ return "low";
111
+ };
112
+ const deriveQualityBand = (node) => {
113
+ if (node.state === "retired" || node.harmed_count > node.helped_count || deriveNodeRisk(node) === "high") {
114
+ return "risky";
115
+ }
116
+ if (node.state === "active" &&
117
+ node.validation_state === "validated_by_reuse" &&
118
+ node.harmed_count === 0) {
119
+ return "strong";
120
+ }
121
+ return "building";
122
+ };
123
+ const buildQualityDrivers = (node) => {
124
+ const drivers = [];
125
+ if (node.validation_state === "validated_by_reuse") {
126
+ drivers.push("This node has already been validated by successful reuse.");
127
+ }
128
+ if (node.helped_count > node.harmed_count) {
129
+ drivers.push("Helpful outcomes still outweigh harmful ones for this node.");
130
+ }
131
+ else if (node.harmed_count > node.helped_count) {
132
+ drivers.push("Harmful outcomes currently outweigh helpful ones for this node.");
133
+ }
134
+ if (node.state === "candidate" || node.state === "priority_candidate") {
135
+ drivers.push("This node is still early in its lifecycle and needs more runtime evidence.");
136
+ }
137
+ else if (node.state === "cooling") {
138
+ drivers.push("This node is in cooling state because recent runtime evidence weakened confidence.");
139
+ }
140
+ return drivers.slice(0, 3);
141
+ };
142
+ const deriveConfidence = (node) => {
143
+ if (node.validation_state === "validated_by_reuse" && node.state === "active" && node.harmed_count === 0) {
144
+ return "high";
145
+ }
146
+ if (node.state === "candidate" || node.harmed_count > node.helped_count) {
147
+ return "low";
148
+ }
149
+ return "medium";
150
+ };
151
+ const formatTaskFamily = (taskType) => taskType === "general" ? "general tasks" : `${taskType} tasks`;
152
+ const buildApplicabilityProfile = (node) => ({
153
+ bestFit: `${formatTaskFamily(node.task_type)} in this repo scope`,
154
+ scopeValidity: node.applicability_notes ?? "Use within the same repo scope unless fresh evidence says otherwise.",
155
+ confidence: deriveConfidence(node),
156
+ risk: deriveNodeRisk(node),
157
+ avoidWhen: node.stop_condition ?? node.escalation_condition ?? node.avoid_steps?.[0]
158
+ });
30
159
  const toNodeSummary = (node) => ({
31
160
  id: node.id,
32
161
  type: node.node_type,
@@ -36,13 +165,21 @@ const toNodeSummary = (node) => ({
36
165
  distillationMode: node.distillation_mode_used,
37
166
  distillationSource: node.distillation_source,
38
167
  redistilledFrom: node.redistilled_from,
168
+ promotionSignal: node.promotion_signal,
169
+ promotionReason: node.promotion_reason,
170
+ mergeDecision: node.merge_decision,
171
+ mergeReason: node.merge_reason,
172
+ priorityPromotionApplied: node.priority_promotion_applied,
39
173
  triggerPattern: node.trigger_pattern,
40
174
  evidenceSummary: node.evidence_summary,
41
175
  originRecordIds: node.origin_record_ids,
42
176
  helped: node.helped_count,
43
177
  harmed: node.harmed_count,
44
178
  lastUsedAt: node.last_used_at,
45
- hint: node.compact_hint
179
+ hint: node.compact_hint,
180
+ qualityBand: deriveQualityBand(node),
181
+ qualityDrivers: buildQualityDrivers(node),
182
+ applicabilityProfile: buildApplicabilityProfile(node)
46
183
  });
47
184
  const toNodeDetail = (node) => ({
48
185
  ...toNodeSummary(node),
@@ -57,23 +194,6 @@ const toNodeDetail = (node) => ({
57
194
  helpedRecordIds: node.helped_record_ids,
58
195
  harmedRecordIds: node.harmed_record_ids
59
196
  });
60
- const applyNodeFeedback = (node, feedback) => {
61
- const timestamp = nowIso();
62
- const next = {
63
- ...node,
64
- helped_count: feedback === "helped" ? node.helped_count + 1 : node.helped_count,
65
- harmed_count: feedback === "harmed" ? node.harmed_count + 1 : node.harmed_count,
66
- validation_state: transitionValidationState(node, feedback),
67
- last_helped_at: feedback === "helped" ? timestamp : node.last_helped_at,
68
- last_harmed_at: feedback === "harmed" ? timestamp : node.last_harmed_at,
69
- updated_at: timestamp
70
- };
71
- return {
72
- ...next,
73
- state: node.state === "retired" ? "retired" : transitionState(next)
74
- };
75
- };
76
- const REPO_SUMMARY_TARGETS = ["codex", "agents", "claude", "github"];
77
197
  const summarizeAutomaticFeedback = (events) => {
78
198
  const automatic = events.filter((event) => event.source === "automatic");
79
199
  if (automatic.some((event) => event.event_type === "mark_harmed")) {
@@ -149,51 +269,100 @@ const buildLatestTimeline = (input) => {
149
269
  }
150
270
  return entries.sort((left, right) => left.createdAt.localeCompare(right.createdAt));
151
271
  };
152
- const toScopePackActivation = (pack, activation) => {
153
- if (!pack) {
272
+ const compareIsoDesc = (left, right) => {
273
+ if (!left && !right) {
274
+ return 0;
275
+ }
276
+ if (!left) {
277
+ return 1;
278
+ }
279
+ if (!right) {
280
+ return -1;
281
+ }
282
+ return right.localeCompare(left);
283
+ };
284
+ const buildDecisionExplanation = (input) => {
285
+ const scorecard = input.scorecard;
286
+ if (!scorecard) {
154
287
  return undefined;
155
288
  }
156
- return {
157
- scopeId: activation.scope_id,
158
- packId: activation.pack_id,
159
- status: pack.status,
160
- currentVersion: pack.current_version,
161
- pinnedVersion: activation.pinned_version,
162
- enabled: activation.enabled,
163
- updatedAt: activation.updated_at
164
- };
289
+ if (scorecard.mode === "inject_conservative") {
290
+ if (scorecard.decisionReason === "ambiguous_same_family_candidate") {
291
+ return "ExperienceEngine found a promising same-family match and chose conservative injection instead of skipping.";
292
+ }
293
+ if (scorecard.decisionReason === "promising_candidate_quality") {
294
+ return "ExperienceEngine found a credible candidate, but kept the injection conservative until it has stronger runtime proof.";
295
+ }
296
+ return "ExperienceEngine chose conservative injection because the best match still needs more runtime evidence.";
297
+ }
298
+ if (scorecard.decisionReason === "mature_validated_candidate") {
299
+ return "A mature validated candidate cleared the fast path, so ExperienceEngine injected it normally.";
300
+ }
301
+ if (scorecard.decisionReason === "candidate_quality_positive") {
302
+ return "Candidate quality was strong enough to justify intervention for this task.";
303
+ }
304
+ if (scorecard.mode === "inject") {
305
+ return "ExperienceEngine injected the best available reusable guidance for this task.";
306
+ }
307
+ if (input.intervention === "shadow") {
308
+ return "ExperienceEngine found a usable match, but delivery was suppressed because this run was in shadow mode.";
309
+ }
310
+ if (input.intervention === "holdout") {
311
+ return "ExperienceEngine found a usable match, but delivery was withheld for evaluation.";
312
+ }
313
+ return undefined;
165
314
  };
166
- const toCompiledArtifactWithPack = (packId, artifact) => ({
167
- ...artifact,
168
- packId
169
- });
170
- const summarizePackCompiler = (registry, packIds, versionByPackId) => {
171
- const compiledArtifacts = packIds.flatMap((packId) => registry.listCompiledArtifacts(packId).map((artifact) => toCompiledArtifactWithPack(packId, artifact)));
172
- const stalePublishedPacks = packIds.filter((packId) => {
173
- const currentVersion = versionByPackId.get(packId);
174
- return currentVersion ? registry.getCompileStatus(packId, currentVersion).stale : false;
175
- }).length;
176
- return {
177
- publishedPacks: packIds.length,
178
- compiledTargets: compiledArtifacts.length,
179
- stalePublishedPacks,
180
- latestCompiledArtifact: compiledArtifacts[0]
181
- };
315
+ const buildTrustSummary = (input) => {
316
+ const scorecard = input.scorecard;
317
+ const primaryNode = input.injectedNodes[0];
318
+ if (!scorecard || !primaryNode) {
319
+ return undefined;
320
+ }
321
+ const confidence = scorecard.confidence ? ` ${scorecard.confidence}-confidence` : "";
322
+ return `${scorecard.riskLevel}-risk${confidence} ${primaryNode.state} guidance with ${primaryNode.helped} helped and ${primaryNode.harmed} harmed signal(s).`;
323
+ };
324
+ const buildRetrievalNotes = (scorecard) => {
325
+ if (!scorecard) {
326
+ return [];
327
+ }
328
+ const notes = [];
329
+ if (scorecard.queryRewriteApplied) {
330
+ notes.push("Query rewrite preserved retrieval intent for this task.");
331
+ }
332
+ const rerankSource = scorecard.topCandidates?.[0]?.rerankSource;
333
+ if (rerankSource === "model") {
334
+ notes.push("Model reranking participated in the final ordering.");
335
+ }
336
+ if (scorecard.fastPathApplied) {
337
+ notes.push("A strong candidate fast path was used.");
338
+ }
339
+ const topCandidate = scorecard.topCandidates?.[0];
340
+ if (topCandidate?.retrievalReasons?.length) {
341
+ notes.push(`Top retrieval signals: ${topCandidate.retrievalReasons.slice(0, 2).join(", ")}.`);
342
+ }
343
+ if (topCandidate?.policyReasons?.length) {
344
+ notes.push(`Top policy signals: ${topCandidate.policyReasons.slice(0, 2).join(", ")}.`);
345
+ }
346
+ if (scorecard.rejectedCandidates?.length) {
347
+ notes.push(`Runner-up candidates withheld: ${scorecard.rejectedCandidates.map((candidate) => candidate.id).join(", ")}.`);
348
+ }
349
+ return notes;
182
350
  };
183
351
  export class ExperienceInteractionService {
352
+ config;
353
+ hybridWorkerClient;
184
354
  inputRepo;
185
355
  injectionRepo;
186
356
  nodeRepo;
187
357
  candidateRepo;
188
358
  jobRepo;
359
+ hybridTraceRepo;
189
360
  taskRunRepo;
190
361
  outcomeRepo;
191
362
  reviewEventRepo;
192
363
  scopeRepo;
193
- packRepo;
194
- packRegistry;
195
- packsDir;
196
- constructor(config, options = {}) {
364
+ constructor(config) {
365
+ this.config = config;
197
366
  const db = openDatabase(config);
198
367
  bootstrapDatabase(db);
199
368
  this.inputRepo = new InputRecordRepository(db);
@@ -201,16 +370,90 @@ export class ExperienceInteractionService {
201
370
  this.nodeRepo = new NodeRepository(db);
202
371
  this.candidateRepo = new CandidateRepository(db);
203
372
  this.jobRepo = new DistillationJobRepository(db);
373
+ this.hybridTraceRepo = new HybridInvocationTraceRepository(db);
204
374
  this.taskRunRepo = new TaskRunRepository(db);
205
375
  this.outcomeRepo = new OutcomeRecordRepository(db);
206
376
  this.reviewEventRepo = new ReviewEventRepository(db);
207
377
  this.scopeRepo = new ScopeRepository(db);
208
- this.packRepo = new ExperiencePackRepository(db);
209
- this.packsDir = options.packsDir ?? `${config.dataDir}/packs`;
210
- this.packRegistry = new ExperiencePackRegistry({
211
- packsDir: this.packsDir
378
+ this.hybridWorkerClient = new HybridWorkerClient({
379
+ explainDecisionEnabled: config.hybridEnabled && config.hybridSyncExplainEnabled,
380
+ explainDecisionLlmEnabled: config.hybridEnabled && config.hybridSyncExplainEnabled && config.hybridExplainLlmEnabled
212
381
  });
213
382
  }
383
+ deriveOriginProfile(node) {
384
+ return deriveNodeOriginProfileForNode(this.inputRepo, node);
385
+ }
386
+ decideExplainRoute(userMessage) {
387
+ return decideHybridExplainRoute(userMessage);
388
+ }
389
+ async explainLastDecision(cwd = process.cwd(), userMessage) {
390
+ const inspection = this.inspectLast(cwd);
391
+ if (!inspection) {
392
+ return "There is no recent ExperienceEngine intervention in this workspace yet.";
393
+ }
394
+ const fallback = inspection.decisionExplanation
395
+ ?? "ExperienceEngine used the current bounded decision path, but no deeper explanation is stored for the latest turn.";
396
+ if (!userMessage) {
397
+ return fallback;
398
+ }
399
+ const rollout = resolveHybridRolloutState(this.config, `${cwd}:${userMessage}`);
400
+ if (!rollout.hybridActive) {
401
+ return fallback;
402
+ }
403
+ const routeDecision = this.decideExplainRoute(userMessage);
404
+ if (routeDecision.route !== "ESCALATE_SYNC_EXPLAIN") {
405
+ return fallback;
406
+ }
407
+ const capsule = buildExplainDecisionCapsule({
408
+ schemaVersion: this.config.hybridCapsuleSchemaVersion,
409
+ routeDecision,
410
+ inspection
411
+ });
412
+ const providerResolution = this.config.hybridExplainLlmEnabled
413
+ ? resolveHybridExplainProviderEndpoint(this.config)
414
+ : { status: "disabled", reason: "Phase 2 provider-backed explain is disabled." };
415
+ const phase2ExplainRequested = this.config.hybridExplainLlmEnabled;
416
+ const useProvider = providerResolution.status === "configured";
417
+ const result = phase2ExplainRequested && providerResolution.status === "unavailable"
418
+ ? {
419
+ status: "fallback",
420
+ reason: "provider_unavailable"
421
+ }
422
+ : await this.hybridWorkerClient.runExplainDecision(capsule, useProvider
423
+ ? {
424
+ mode: "provider",
425
+ endpoint: providerResolution.endpoint
426
+ }
427
+ : undefined);
428
+ const timestamp = nowIso();
429
+ this.hybridTraceRepo.upsert({
430
+ id: createId("hybridtrace"),
431
+ surface: "interaction",
432
+ session_id: inspection.sessionId,
433
+ scope_id: inspection.scopeId,
434
+ worker_task: "explain_decision",
435
+ route: routeDecision.route,
436
+ route_policy_version: routeDecision.policyVersion,
437
+ capsule_schema_version: this.config.hybridCapsuleSchemaVersion,
438
+ worker_profile_version: phase2ExplainRequested
439
+ ? this.config.hybridExplainModelProfileVersion
440
+ : this.config.hybridExplainDecisionProfileVersion,
441
+ rollout_mode: rollout.effectiveMode,
442
+ rollout_reason: rollout.reason,
443
+ worker_ran: result.status !== "fallback" || result.reason !== "provider_unavailable",
444
+ validation_status: result.status === "accepted" ? "accepted" : "fallback",
445
+ output_action: result.status === "accepted" && rollout.userVisible ? "surfaced" : "none",
446
+ fallback_reason: result.status === "accepted" ? undefined : result.reason,
447
+ created_at: timestamp
448
+ });
449
+ if (!rollout.userVisible) {
450
+ return fallback;
451
+ }
452
+ if (result.status !== "accepted") {
453
+ return fallback;
454
+ }
455
+ return `${result.value.decision} ${result.value.reason}`.trim();
456
+ }
214
457
  inspectRecord(record) {
215
458
  if (!record) {
216
459
  return undefined;
@@ -248,22 +491,13 @@ export class ExperienceInteractionService {
248
491
  : "inject";
249
492
  const outcomeRecord = taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined;
250
493
  const latestAutomaticFeedback = reviewEvents.find((event) => event.source === "automatic");
251
- const scopePackStatus = this.inspectScopePackStatusByScopeId(record.scope_id);
252
- const matchedPackIds = new Set();
253
- for (const activation of scopePackStatus.activations.filter((entry) => entry.enabled)) {
254
- const version = activation.pinnedVersion ?? activation.currentVersion;
255
- for (const membership of this.packRepo.listMemberships(activation.packId, version)) {
256
- if (selectedNodeIds.includes(membership.node_id)) {
257
- matchedPackIds.add(activation.packId);
258
- }
259
- }
260
- }
261
494
  const autoFeedbackReason = inferAutoFeedbackReason({
262
495
  explicitReason: injectionEvent?.attribution_reason,
263
496
  autoFeedback,
264
497
  intervention,
265
498
  outcome: record.outcome_signal
266
499
  });
500
+ const decisionExplanation = buildDecisionExplanation({ intervention, scorecard });
267
501
  return {
268
502
  sessionId: record.session_id,
269
503
  scopeId: record.scope_id,
@@ -278,6 +512,9 @@ export class ExperienceInteractionService {
278
512
  hints: injectedNodes.map((node) => node.compact_hint),
279
513
  evidence: record.evidence,
280
514
  scorecard,
515
+ decisionExplanation,
516
+ trustSummary: buildTrustSummary({ scorecard, injectedNodes: injectedNodes.map(toNodeSummary) }),
517
+ retrievalNotes: buildRetrievalNotes(scorecard),
281
518
  timeline: buildLatestTimeline({
282
519
  record,
283
520
  taskRunCreatedAt: taskRun?.created_at,
@@ -290,14 +527,110 @@ export class ExperienceInteractionService {
290
527
  autoFeedback,
291
528
  autoFeedbackCreatedAt: latestAutomaticFeedback?.created_at
292
529
  }),
293
- activePacks: scopePackStatus.activations.filter((activation) => activation.enabled),
294
- matchedPacks: scopePackStatus.activations.filter((activation) => matchedPackIds.has(activation.packId)),
530
+ learningStatus: taskRun?.learning_status,
531
+ learningReason: taskRun?.learning_reason,
295
532
  summary: record.task_summary,
296
533
  createdAt: record.created_at
297
534
  };
298
535
  }
299
- inspectLast() {
300
- return this.inspectRecord(this.inputRepo.getLatest());
536
+ inspectInjectionEvent(event) {
537
+ if (!event) {
538
+ return undefined;
539
+ }
540
+ const taskRun = event.session_id ? this.taskRunRepo.getLatestBySessionId(event.session_id) : undefined;
541
+ const latestRecord = event.session_id ? this.inputRepo.getLatestBySessionId(event.session_id) : undefined;
542
+ if (latestRecord) {
543
+ return this.inspectRecord(latestRecord);
544
+ }
545
+ const injectedNodes = this.nodeRepo.listByIds(event.injected_node_ids);
546
+ const reviewEvents = taskRun?.id ? this.reviewEventRepo.listByTaskRunId(taskRun.id) : [];
547
+ const autoFeedback = summarizeAutomaticFeedback(reviewEvents);
548
+ const latestAutomaticFeedback = reviewEvents.find((reviewEvent) => reviewEvent.source === "automatic");
549
+ const intervention = !event.delivered
550
+ ? event.delivery_mode === "holdout"
551
+ ? "holdout"
552
+ : "shadow"
553
+ : "inject";
554
+ const outcomeRecord = taskRun?.id ? this.outcomeRepo.listByTaskRunId(taskRun.id)[0] : undefined;
555
+ const outcome = outcomeRecord?.outcome_signal ??
556
+ (taskRun?.final_status === "success" ? "success" : taskRun?.final_status === "failure" ? "failure" : "unknown");
557
+ const summary = event.task_summary ?? taskRun?.task_summary ?? "Latest injection event";
558
+ const decisionExplanation = buildDecisionExplanation({ intervention, scorecard: event.scorecard });
559
+ return {
560
+ sessionId: event.session_id,
561
+ scopeId: event.scope_id,
562
+ taskType: event.task_type,
563
+ intervention,
564
+ deliveryMode: event.delivery_mode,
565
+ delivered: event.delivered,
566
+ autoFeedback,
567
+ autoFeedbackReason: inferAutoFeedbackReason({
568
+ explicitReason: event.attribution_reason,
569
+ autoFeedback,
570
+ intervention,
571
+ outcome
572
+ }),
573
+ outcome,
574
+ injectedNodes: injectedNodes.map(toNodeSummary),
575
+ hints: injectedNodes.map((node) => node.compact_hint),
576
+ evidence: [],
577
+ scorecard: event.scorecard,
578
+ decisionExplanation,
579
+ trustSummary: buildTrustSummary({ scorecard: event.scorecard, injectedNodes: injectedNodes.map(toNodeSummary) }),
580
+ retrievalNotes: buildRetrievalNotes(event.scorecard),
581
+ timeline: buildLatestTimeline({
582
+ record: {
583
+ record_id: `injection:${event.injection_id}`,
584
+ scope_id: event.scope_id,
585
+ session_id: event.session_id,
586
+ task_type: event.task_type,
587
+ task_summary: summary,
588
+ outcome_signal: outcome,
589
+ context_summary: taskRun?.context_summary,
590
+ evidence: [],
591
+ injected_node_ids: event.injected_node_ids,
592
+ created_at: event.created_at
593
+ },
594
+ taskRunCreatedAt: taskRun?.created_at,
595
+ outcomeCreatedAt: outcomeRecord?.created_at,
596
+ outcomeSummary: outcomeRecord?.summary,
597
+ injectionCreatedAt: event.created_at,
598
+ intervention,
599
+ delivered: event.delivered,
600
+ injectedCount: injectedNodes.length,
601
+ autoFeedback,
602
+ autoFeedbackCreatedAt: latestAutomaticFeedback?.created_at
603
+ }),
604
+ learningStatus: taskRun?.learning_status,
605
+ learningReason: taskRun?.learning_reason,
606
+ summary,
607
+ createdAt: event.created_at
608
+ };
609
+ }
610
+ inspectLast(cwd = process.cwd()) {
611
+ const scope = resolveScope(cwd);
612
+ const latestRecordInScope = this.inputRepo.getLatestByScope(scope.scope_id);
613
+ const latestInjectionInScope = this.injectionRepo.getLatestByScope(scope.scope_id);
614
+ const latestScopedInspection = compareIsoDesc(latestInjectionInScope?.created_at, latestRecordInScope?.created_at) < 0
615
+ ? this.inspectInjectionEvent(latestInjectionInScope)
616
+ : this.inspectRecord(latestRecordInScope);
617
+ if (latestScopedInspection) {
618
+ return latestScopedInspection;
619
+ }
620
+ const latestRecord = this.inputRepo.getLatest();
621
+ const latestInjection = this.injectionRepo.getLatest();
622
+ return compareIsoDesc(latestInjection?.created_at, latestRecord?.created_at) < 0
623
+ ? this.inspectInjectionEvent(latestInjection)
624
+ : this.inspectRecord(latestRecord);
625
+ }
626
+ inspectLatestInjected(cwd = process.cwd()) {
627
+ const scope = resolveScope(cwd);
628
+ const latestScopedInjected = this.inputRepo.getLatestInjectedByScope(scope.scope_id);
629
+ if (latestScopedInjected) {
630
+ return this.inspectRecord(latestScopedInjected);
631
+ }
632
+ const latestInjected = this.inputRepo.getLatestInjected();
633
+ return latestInjected ? this.inspectRecord(latestInjected) : undefined;
301
634
  }
302
635
  inspectRecent(options = {}) {
303
636
  return this.inputRepo.listRecent(options).map((record) => ({
@@ -319,149 +652,6 @@ export class ExperienceInteractionService {
319
652
  const node = this.nodeRepo.getById(nodeId);
320
653
  return node ? toNodeDetail(node) : undefined;
321
654
  }
322
- listPacks() {
323
- return this.packRepo.listPacks().map((pack) => ({
324
- packId: pack.pack_id,
325
- name: pack.name,
326
- description: pack.description,
327
- owner: pack.owner,
328
- status: pack.status,
329
- currentVersion: pack.current_version,
330
- createdAt: pack.created_at,
331
- updatedAt: pack.updated_at,
332
- publishedAt: pack.published_at,
333
- rolledBackAt: pack.rolled_back_at,
334
- scopeHints: pack.scope_hints,
335
- taskFamilies: pack.task_families,
336
- hostCompatibility: pack.host_compatibility
337
- }));
338
- }
339
- inspectPack(packId) {
340
- const pack = this.packRepo.getPack(packId);
341
- if (!pack) {
342
- return undefined;
343
- }
344
- const manifest = this.packRegistry.readVersionManifest(packId, pack.current_version);
345
- const nodes = this.packRegistry.readVersionNodes(packId, pack.current_version);
346
- return {
347
- packId: pack.pack_id,
348
- name: pack.name,
349
- description: pack.description,
350
- owner: pack.owner,
351
- status: pack.status,
352
- currentVersion: pack.current_version,
353
- createdAt: pack.created_at,
354
- updatedAt: pack.updated_at,
355
- publishedAt: pack.published_at,
356
- rolledBackAt: pack.rolled_back_at,
357
- scopeHints: pack.scope_hints,
358
- taskFamilies: pack.task_families,
359
- hostCompatibility: pack.host_compatibility,
360
- manifest,
361
- nodeIds: nodes.map((node) => node.id),
362
- compiledArtifacts: this.packRegistry.listCompiledArtifacts(packId),
363
- compileStatus: this.packRegistry.getCompileStatus(packId, pack.current_version),
364
- activations: this.packRepo.listActivationsByPack(packId).map((activation) => ({
365
- scopeId: activation.scope_id,
366
- enabled: activation.enabled,
367
- pinnedVersion: activation.pinned_version,
368
- updatedAt: activation.updated_at
369
- }))
370
- };
371
- }
372
- enablePack(args) {
373
- const scopeId = resolveScope(args.cwd).scope_id;
374
- const pack = this.packRepo.getPack(args.packId);
375
- if (!pack) {
376
- throw new Error(`Unknown experience pack: ${args.packId}`);
377
- }
378
- const existing = this.packRepo.listActivations(scopeId).find((activation) => activation.pack_id === args.packId);
379
- const updatedAt = nowIso();
380
- this.packRepo.upsertActivation({
381
- scope_id: scopeId,
382
- pack_id: args.packId,
383
- enabled: true,
384
- pinned_version: pack.current_version,
385
- created_at: existing?.created_at ?? updatedAt,
386
- updated_at: updatedAt
387
- });
388
- return {
389
- scopeId,
390
- packId: args.packId,
391
- enabled: true,
392
- pinnedVersion: pack.current_version,
393
- updatedAt
394
- };
395
- }
396
- disablePack(args) {
397
- const scopeId = resolveScope(args.cwd).scope_id;
398
- const existing = this.packRepo.listActivations(scopeId).find((activation) => activation.pack_id === args.packId);
399
- const updatedAt = nowIso();
400
- this.packRepo.upsertActivation({
401
- scope_id: scopeId,
402
- pack_id: args.packId,
403
- enabled: false,
404
- pinned_version: existing?.pinned_version,
405
- created_at: existing?.created_at ?? updatedAt,
406
- updated_at: updatedAt
407
- });
408
- return {
409
- scopeId,
410
- packId: args.packId,
411
- enabled: false,
412
- pinnedVersion: existing?.pinned_version,
413
- updatedAt
414
- };
415
- }
416
- compilePack(args) {
417
- return compilePack({
418
- packsDir: this.packsDir,
419
- packId: args.packId,
420
- version: args.version,
421
- target: args.target
422
- });
423
- }
424
- inspectPackDeploymentStatus(args) {
425
- return deployCompiledPack({
426
- packsDir: this.packsDir,
427
- packId: args.packId,
428
- version: args.version,
429
- target: args.target,
430
- repoPath: args.repoPath,
431
- statusOnly: true
432
- });
433
- }
434
- deployPackPreview(args) {
435
- return deployCompiledPack({
436
- packsDir: this.packsDir,
437
- packId: args.packId,
438
- version: args.version,
439
- target: args.target,
440
- repoPath: args.repoPath,
441
- dryRun: true
442
- });
443
- }
444
- inspectScopePackStatus(cwd = process.cwd()) {
445
- return this.inspectScopePackStatusByScopeId(resolveScope(cwd).scope_id);
446
- }
447
- inspectScopePackStatusByScopeId(scopeId) {
448
- const activations = this.packRepo
449
- .listActivations(scopeId)
450
- .map((activation) => toScopePackActivation(this.packRepo.getPack(activation.pack_id), activation))
451
- .filter((activation) => Boolean(activation));
452
- const publishedPackIds = Array.from(new Set(activations
453
- .filter((activation) => activation.status === "published" || activation.status === "rolled_back")
454
- .map((activation) => activation.packId)));
455
- const compiler = summarizePackCompiler(this.packRegistry, publishedPackIds, new Map(activations
456
- .filter((activation) => activation.status === "published" || activation.status === "rolled_back")
457
- .map((activation) => [activation.packId, activation.currentVersion])));
458
- return {
459
- scopeId,
460
- enabledCount: activations.filter((activation) => activation.enabled).length,
461
- activations,
462
- compiler
463
- };
464
- }
465
655
  listNodesByState(state) {
466
656
  return this.nodeRepo.listByState(state).map(toNodeSummary);
467
657
  }
@@ -474,7 +664,7 @@ export class ExperienceInteractionService {
474
664
  buildLearningSummary(scopeId) {
475
665
  const candidateStates = ["pending", "distilled", "failed", "discarded"];
476
666
  const jobStates = ["pending", "processing", "succeeded", "failed", "discarded"];
477
- const nodeStates = ["candidate", "active", "cooling", "retired"];
667
+ const nodeStates = ["candidate", "priority_candidate", "active", "cooling", "retired"];
478
668
  const nodeSources = ["explicit_provider", "rule", "disabled"];
479
669
  const attributionReasons = [
480
670
  "success_outcome",
@@ -492,10 +682,6 @@ export class ExperienceInteractionService {
492
682
  : candidateStates.flatMap((state) => this.candidateRepo.listByLifecycleState(state));
493
683
  const candidateIds = new Set(candidates.map((candidate) => candidate.id));
494
684
  const jobs = jobStates.flatMap((state) => this.jobRepo.listByStatus(state)).filter((job) => candidateIds.has(job.candidate_id));
495
- const publishedPacks = this.packRepo
496
- .listPacks()
497
- .filter((pack) => pack.status === "published" || pack.status === "rolled_back");
498
- const compiler = summarizePackCompiler(this.packRegistry, publishedPacks.map((pack) => pack.pack_id), new Map(publishedPacks.map((pack) => [pack.pack_id, pack.current_version])));
499
685
  const effectiveness = {
500
686
  decisions: scopeId ? this.injectionRepo.countByScope(scopeId) : this.injectionRepo.count(),
501
687
  live: scopeId ? this.injectionRepo.countByScopeAndDeliveryMode(scopeId, "live") : this.injectionRepo.countByDeliveryMode("live"),
@@ -530,7 +716,6 @@ export class ExperienceInteractionService {
530
716
  outcomes: scopeId ? this.outcomeRepo.countByScope(scopeId) : this.outcomeRepo.count(),
531
717
  reviews: scopeId ? this.reviewEventRepo.countByNodeScope(scopeId) : this.reviewEventRepo.count()
532
718
  },
533
- compiler,
534
719
  latestRecordCreatedAt: latestRecord?.created_at
535
720
  };
536
721
  }
@@ -539,11 +724,6 @@ export class ExperienceInteractionService {
539
724
  const latestRecord = this.inputRepo.getLatestByScope(scope.scope_id);
540
725
  const latest = latestRecord ? this.inspectRecord(latestRecord) : undefined;
541
726
  const learning = this.buildLearningSummary(scope.scope_id);
542
- const scopePackStatus = this.inspectScopePackStatusByScopeId(scope.scope_id);
543
- const activePacks = scopePackStatus.activations.filter((activation) => activation.enabled);
544
- const matchedPackIds = new Set(latest?.matchedPacks.map((pack) => pack.packId) ?? []);
545
- const matchedPacks = scopePackStatus.activations.filter((activation) => matchedPackIds.has(activation.packId));
546
- const deployments = this.inspectRepoDeploymentStatuses(scopePackStatus.activations, cwd);
547
727
  return buildRepoSummary({
548
728
  scope: {
549
729
  scopeId: scope.scope_id,
@@ -551,14 +731,12 @@ export class ExperienceInteractionService {
551
731
  rootPath: scope.root_path
552
732
  },
553
733
  latest: latest && latest.scopeId === scope.scope_id ? latest : undefined,
554
- learning,
555
- activePacks,
556
- matchedPacks,
557
- deployments
734
+ learning
558
735
  });
559
736
  }
560
- inspectFirstValueReadiness() {
561
- const summary = this.inspectLearningSummary();
737
+ inspectFirstValueReadiness(cwd = process.cwd()) {
738
+ const scope = resolveScope(cwd);
739
+ const summary = this.buildLearningSummary(scope.scope_id);
562
740
  const rawRecords = summary.runtime.records;
563
741
  const taskRuns = summary.runtime.taskRuns;
564
742
  const candidates = summary.candidates.pending;
@@ -582,8 +760,99 @@ export class ExperienceInteractionService {
582
760
  nextStep
583
761
  };
584
762
  }
585
- feedbackLast(feedback) {
586
- const record = this.inputRepo.getLatestInjected();
763
+ inspectDecisionHealth(cwd = process.cwd(), limit = 10) {
764
+ const scope = resolveScope(cwd);
765
+ const recentRecords = this.inputRepo.listRecentByScope(scope.scope_id, limit);
766
+ let recentInjects = 0;
767
+ let recentConservativeInjects = 0;
768
+ let recentSkips = 0;
769
+ let recentPotentialMisfires = 0;
770
+ let recentMetaDominantSelections = 0;
771
+ let recentRealDevAlignedSelections = 0;
772
+ let recentFastPathActivations = 0;
773
+ let recentRerankParticipations = 0;
774
+ let recentQueryRewriteUsages = 0;
775
+ let recentSecondOpinionActivations = 0;
776
+ let recentSecondOpinionSkips = 0;
777
+ let recentSecondOpinionConservativeDowngrades = 0;
778
+ const scopedNodes = this.nodeRepo.listByScope(scope.scope_id);
779
+ const recentNodes = scopedNodes.slice(0, limit);
780
+ const currentPriorityCandidates = scopedNodes.filter((node) => node.state === "priority_candidate").length;
781
+ const recentConvergedUpdates = recentNodes.filter((node) => node.merge_decision === "UPDATE").length;
782
+ const recentPriorityPromotions = recentNodes.filter((node) => node.priority_promotion_applied).length;
783
+ let lastDecisionMode;
784
+ for (const record of recentRecords) {
785
+ const injectionEvent = record.session_id
786
+ ? this.injectionRepo.getLatestBySessionId(record.session_id)
787
+ : undefined;
788
+ const decisionMode = injectionEvent?.mode ?? "skip";
789
+ if (!lastDecisionMode) {
790
+ lastDecisionMode = decisionMode;
791
+ }
792
+ if (decisionMode === "inject") {
793
+ recentInjects += 1;
794
+ }
795
+ else if (decisionMode === "inject_conservative") {
796
+ recentConservativeInjects += 1;
797
+ }
798
+ else {
799
+ recentSkips += 1;
800
+ }
801
+ if (isPotentialMisfire(injectionEvent)) {
802
+ recentPotentialMisfires += 1;
803
+ }
804
+ const governance = deriveGovernanceSignals(injectionEvent?.scorecard);
805
+ if (governance.metaDominant) {
806
+ recentMetaDominantSelections += 1;
807
+ }
808
+ if (governance.realDevAligned) {
809
+ recentRealDevAlignedSelections += 1;
810
+ }
811
+ if (injectionEvent?.scorecard?.fastPathApplied) {
812
+ recentFastPathActivations += 1;
813
+ }
814
+ if (injectionEvent?.scorecard?.topCandidates?.some((candidate) => typeof candidate.rerankScore === "number")) {
815
+ recentRerankParticipations += 1;
816
+ }
817
+ if (injectionEvent?.scorecard?.queryRewriteApplied) {
818
+ recentQueryRewriteUsages += 1;
819
+ }
820
+ if (injectionEvent?.scorecard?.secondOpinionApplied) {
821
+ recentSecondOpinionActivations += 1;
822
+ }
823
+ if (injectionEvent?.scorecard?.secondOpinionDecision === "skip") {
824
+ recentSecondOpinionSkips += 1;
825
+ }
826
+ if (injectionEvent?.scorecard?.secondOpinionDecision === "allow_conservative") {
827
+ recentSecondOpinionConservativeDowngrades += 1;
828
+ }
829
+ }
830
+ return {
831
+ scopeId: scope.scope_id,
832
+ recentDecisions: recentRecords.length,
833
+ recentInjects,
834
+ recentConservativeInjects,
835
+ recentSkips,
836
+ recentPotentialMisfires,
837
+ recentMetaDominantSelections,
838
+ recentRealDevAlignedSelections,
839
+ recentFastPathActivations,
840
+ recentRerankParticipations,
841
+ recentQueryRewriteUsages,
842
+ recentSecondOpinionActivations,
843
+ recentSecondOpinionSkips,
844
+ recentSecondOpinionConservativeDowngrades,
845
+ currentPriorityCandidates,
846
+ recentConvergedUpdates,
847
+ recentPriorityPromotions,
848
+ lastDecisionMode
849
+ };
850
+ }
851
+ feedbackLast(feedback, cwd) {
852
+ const scope = cwd ? resolveScope(cwd) : undefined;
853
+ const record = scope
854
+ ? this.inputRepo.getLatestInjectedByScope(scope.scope_id) ?? this.inputRepo.getLatestInjected()
855
+ : this.inputRepo.getLatestInjected();
587
856
  if (!record) {
588
857
  return {
589
858
  status: "not_found",
@@ -601,7 +870,7 @@ export class ExperienceInteractionService {
601
870
  ? this.taskRunRepo.getLatestBySessionId(record.session_id)?.id
602
871
  : undefined;
603
872
  for (const node of nodes) {
604
- this.nodeRepo.upsert(applyNodeFeedback(node, feedback));
873
+ this.nodeRepo.upsert(applyGovernedNodeFeedback(node, feedback, this.deriveOriginProfile(node)));
605
874
  this.reviewEventRepo.upsert(toReviewEvent(node.id, feedback === "helped" ? "mark_helped" : "mark_harmed", "user", taskRunId));
606
875
  }
607
876
  return {
@@ -619,7 +888,7 @@ export class ExperienceInteractionService {
619
888
  nodeId
620
889
  };
621
890
  }
622
- this.nodeRepo.upsert(applyNodeFeedback(node, feedback));
891
+ this.nodeRepo.upsert(applyGovernedNodeFeedback(node, feedback, this.deriveOriginProfile(node)));
623
892
  this.reviewEventRepo.upsert(toReviewEvent(nodeId, feedback === "helped" ? "mark_helped" : "mark_harmed", "user"));
624
893
  return {
625
894
  status: "updated",
@@ -672,35 +941,5 @@ export class ExperienceInteractionService {
672
941
  state: updated.state
673
942
  };
674
943
  }
675
- inspectRepoDeploymentStatuses(activations, repoPath) {
676
- const published = activations.find((activation) => activation.enabled && (activation.status === "published" || activation.status === "rolled_back"));
677
- if (!published) {
678
- return REPO_SUMMARY_TARGETS.map((target) => ({
679
- target,
680
- status: "missing"
681
- }));
682
- }
683
- return REPO_SUMMARY_TARGETS.map((target) => {
684
- try {
685
- const result = this.inspectPackDeploymentStatus({
686
- packId: published.packId,
687
- version: published.pinnedVersion ?? published.currentVersion,
688
- target,
689
- repoPath
690
- });
691
- return {
692
- target,
693
- status: result.deploymentStatus,
694
- destination: result.destinationPath
695
- };
696
- }
697
- catch {
698
- return {
699
- target,
700
- status: "missing"
701
- };
702
- }
703
- });
704
- }
705
944
  }
706
945
  //# sourceMappingURL=service.js.map