create-principles-disciple 1.101.0 → 1.103.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 (317) hide show
  1. package/console/dist/server/config/pd-config-store.d.ts +50 -1
  2. package/console/dist/server/config/pd-config-store.js +364 -1
  3. package/console/dist/server/index.js +9 -0
  4. package/console/dist/server/models/ActivationsConsoleModel.d.ts +44 -5
  5. package/console/dist/server/models/ActivationsConsoleModel.js +118 -16
  6. package/console/dist/server/routes/config.js +92 -2
  7. package/console/dist/server/routes/onboarding.d.ts +34 -0
  8. package/console/dist/server/routes/onboarding.js +324 -0
  9. package/console/dist/ui/App.js +74 -15
  10. package/console/dist/ui/api.d.ts +60 -3
  11. package/console/dist/ui/api.js +63 -2
  12. package/console/dist/ui/components/onboarding/CircuitDiagram.d.ts +8 -0
  13. package/console/dist/ui/components/onboarding/CircuitDiagram.js +18 -0
  14. package/console/dist/ui/components/onboarding/DemoResultView.d.ts +22 -0
  15. package/console/dist/ui/components/onboarding/DemoResultView.js +33 -0
  16. package/console/dist/ui/i18n/en.json +189 -1
  17. package/console/dist/ui/i18n/zh-CN.json +189 -1
  18. package/console/dist/ui/pages/activation/ActivationPage.js +11 -11
  19. package/console/dist/ui/pages/activation/ActivationValidators.js +15 -14
  20. package/console/dist/ui/pages/control-center/AgentCard.js +66 -10
  21. package/console/dist/ui/pages/control-center/ControlCenterPage.js +3 -2
  22. package/console/dist/ui/pages/control-center/RuntimeProfileManager.d.ts +31 -0
  23. package/console/dist/ui/pages/control-center/RuntimeProfileManager.js +234 -0
  24. package/console/dist/ui/pages/debt/DebtPage.js +2 -2
  25. package/console/dist/ui/pages/settings/SettingsPage.js +64 -5
  26. package/console/dist/ui/pages/signal-keywords/KeywordEditDialog.d.ts +12 -0
  27. package/console/dist/ui/pages/signal-keywords/KeywordEditDialog.js +41 -0
  28. package/console/dist/ui/pages/signal-keywords/KeywordListSection.d.ts +10 -0
  29. package/console/dist/ui/pages/signal-keywords/KeywordListSection.js +39 -0
  30. package/console/dist/ui/pages/signal-keywords/PendingTermsSection.d.ts +14 -0
  31. package/console/dist/ui/pages/signal-keywords/PendingTermsSection.js +35 -0
  32. package/console/dist/ui/pages/signal-keywords/SignalKeywordsPage.d.ts +1 -0
  33. package/console/dist/ui/pages/signal-keywords/SignalKeywordsPage.js +49 -0
  34. package/console/dist/ui/pages/welcome/WelcomePage.d.ts +5 -0
  35. package/console/dist/ui/pages/welcome/WelcomePage.js +185 -0
  36. package/console/dist/ui/utils/__tests__/onboarding-state.test.d.ts +1 -0
  37. package/console/dist/ui/utils/__tests__/onboarding-state.test.js +72 -0
  38. package/console/dist/ui/utils/agent-metadata.d.ts +13 -0
  39. package/console/dist/ui/utils/agent-metadata.js +26 -0
  40. package/console/dist/ui/utils/onboarding-state.d.ts +25 -0
  41. package/console/dist/ui/utils/onboarding-state.js +77 -0
  42. package/console/dist/ui/utils/signal-keywords-api.d.ts +68 -0
  43. package/console/dist/ui/utils/signal-keywords-api.js +121 -0
  44. package/console/dist/ui/utils/signal-keywords-types.d.ts +57 -0
  45. package/console/dist/ui/utils/signal-keywords-types.js +10 -0
  46. package/console/dist/ui/utils/signal-keywords-validators.d.ts +20 -0
  47. package/console/dist/ui/utils/signal-keywords-validators.js +114 -0
  48. package/console/dist/ui/utils/validators.d.ts +26 -3
  49. package/console/dist/ui/utils/validators.js +23 -6
  50. package/console/dist/web/assets/app.css +442 -0
  51. package/console/dist/web/assets/app.js +7793 -1966
  52. package/core/dist/index.d.ts +2 -0
  53. package/core/dist/index.d.ts.map +1 -1
  54. package/core/dist/index.js +1 -0
  55. package/core/dist/index.js.map +1 -1
  56. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js +14 -2
  57. package/core/dist/runtime-v2/__tests__/architecture-regression.test.js.map +1 -1
  58. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js +28 -0
  59. package/core/dist/runtime-v2/__tests__/evaluator-runner-vslice-v2.test.js.map +1 -1
  60. package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js +8 -0
  61. package/core/dist/runtime-v2/__tests__/pain-to-principle-service.test.js.map +1 -1
  62. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js +8 -10
  63. package/core/dist/runtime-v2/__tests__/resolve-runtime-config-from-pd-config.test.js.map +1 -1
  64. package/core/dist/runtime-v2/activation/index.d.ts +1 -1
  65. package/core/dist/runtime-v2/activation/index.d.ts.map +1 -1
  66. package/core/dist/runtime-v2/activation/index.js +1 -1
  67. package/core/dist/runtime-v2/activation/index.js.map +1 -1
  68. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js +240 -1
  69. package/core/dist/runtime-v2/activation/writers/__tests__/rule-host-writer.test.js.map +1 -1
  70. package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts +12 -0
  71. package/core/dist/runtime-v2/activation/writers/rule-host-writer.d.ts.map +1 -1
  72. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js +81 -1
  73. package/core/dist/runtime-v2/activation/writers/rule-host-writer.js.map +1 -1
  74. package/core/dist/runtime-v2/adapter/__tests__/l2-resolve-model-compat.test.d.ts +2 -0
  75. package/core/dist/runtime-v2/adapter/__tests__/l2-resolve-model-compat.test.d.ts.map +1 -0
  76. package/core/dist/runtime-v2/adapter/__tests__/l2-resolve-model-compat.test.js +81 -0
  77. package/core/dist/runtime-v2/adapter/__tests__/l2-resolve-model-compat.test.js.map +1 -0
  78. package/core/dist/runtime-v2/adapter/__tests__/pi-ai-runtime-adapter.test.js +19 -0
  79. package/core/dist/runtime-v2/adapter/__tests__/pi-ai-runtime-adapter.test.js.map +1 -1
  80. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts +8 -0
  81. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.d.ts.map +1 -1
  82. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js +4 -1
  83. package/core/dist/runtime-v2/adapter/pi-ai-runtime-adapter.js.map +1 -1
  84. package/core/dist/runtime-v2/candidate-intake-service.d.ts.map +1 -1
  85. package/core/dist/runtime-v2/candidate-intake-service.js +92 -6
  86. package/core/dist/runtime-v2/candidate-intake-service.js.map +1 -1
  87. package/core/dist/runtime-v2/candidate-intake.d.ts +38 -0
  88. package/core/dist/runtime-v2/candidate-intake.d.ts.map +1 -1
  89. package/core/dist/runtime-v2/candidate-intake.js +48 -0
  90. package/core/dist/runtime-v2/candidate-intake.js.map +1 -1
  91. package/core/dist/runtime-v2/config/__tests__/internal-agent-names.test.d.ts +2 -0
  92. package/core/dist/runtime-v2/config/__tests__/internal-agent-names.test.d.ts.map +1 -0
  93. package/core/dist/runtime-v2/config/__tests__/internal-agent-names.test.js +15 -0
  94. package/core/dist/runtime-v2/config/__tests__/internal-agent-names.test.js.map +1 -0
  95. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js +33 -1
  96. package/core/dist/runtime-v2/config/__tests__/pd-config-agent-binding.test.js.map +1 -1
  97. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js +10 -5
  98. package/core/dist/runtime-v2/config/__tests__/pd-config-contract.test.js.map +1 -1
  99. package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.js +1 -0
  100. package/core/dist/runtime-v2/config/__tests__/pd-config-redaction-deep.test.js.map +1 -1
  101. package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js +54 -33
  102. package/core/dist/runtime-v2/config/__tests__/pd-config-validation-edge-cases.test.js.map +1 -1
  103. package/core/dist/runtime-v2/config/index.d.ts +5 -3
  104. package/core/dist/runtime-v2/config/index.d.ts.map +1 -1
  105. package/core/dist/runtime-v2/config/index.js +8 -2
  106. package/core/dist/runtime-v2/config/index.js.map +1 -1
  107. package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts +2 -0
  108. package/core/dist/runtime-v2/config/pd-config-agent-binding.d.ts.map +1 -1
  109. package/core/dist/runtime-v2/config/pd-config-agent-binding.js +3 -0
  110. package/core/dist/runtime-v2/config/pd-config-agent-binding.js.map +1 -1
  111. package/core/dist/runtime-v2/config/pd-config-defaults.d.ts +8 -3
  112. package/core/dist/runtime-v2/config/pd-config-defaults.d.ts.map +1 -1
  113. package/core/dist/runtime-v2/config/pd-config-defaults.js +39 -3
  114. package/core/dist/runtime-v2/config/pd-config-defaults.js.map +1 -1
  115. package/core/dist/runtime-v2/config/pd-config-effective.d.ts.map +1 -1
  116. package/core/dist/runtime-v2/config/pd-config-effective.js +25 -1
  117. package/core/dist/runtime-v2/config/pd-config-effective.js.map +1 -1
  118. package/core/dist/runtime-v2/config/pd-config-redaction.d.ts.map +1 -1
  119. package/core/dist/runtime-v2/config/pd-config-redaction.js +14 -2
  120. package/core/dist/runtime-v2/config/pd-config-redaction.js.map +1 -1
  121. package/core/dist/runtime-v2/config/pd-config-types.d.ts +116 -1
  122. package/core/dist/runtime-v2/config/pd-config-types.d.ts.map +1 -1
  123. package/core/dist/runtime-v2/config/pd-config-types.js +7 -0
  124. package/core/dist/runtime-v2/config/pd-config-types.js.map +1 -1
  125. package/core/dist/runtime-v2/config/pd-config-validate.d.ts.map +1 -1
  126. package/core/dist/runtime-v2/config/pd-config-validate.js +125 -7
  127. package/core/dist/runtime-v2/config/pd-config-validate.js.map +1 -1
  128. package/core/dist/runtime-v2/config/pd-profile-constants.d.ts +27 -0
  129. package/core/dist/runtime-v2/config/pd-profile-constants.d.ts.map +1 -0
  130. package/core/dist/runtime-v2/config/pd-profile-constants.js +145 -0
  131. package/core/dist/runtime-v2/config/pd-profile-constants.js.map +1 -0
  132. package/core/dist/runtime-v2/config/pd-validate-profile.d.ts +28 -0
  133. package/core/dist/runtime-v2/config/pd-validate-profile.d.ts.map +1 -0
  134. package/core/dist/runtime-v2/config/pd-validate-profile.js +482 -0
  135. package/core/dist/runtime-v2/config/pd-validate-profile.js.map +1 -0
  136. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js +26 -0
  137. package/core/dist/runtime-v2/feature-flags/__tests__/feature-flag-contract.test.js.map +1 -1
  138. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.d.ts.map +1 -1
  139. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js +8 -0
  140. package/core/dist/runtime-v2/feature-flags/feature-flag-contract.js.map +1 -1
  141. package/core/dist/runtime-v2/index.d.ts +7 -4
  142. package/core/dist/runtime-v2/index.d.ts.map +1 -1
  143. package/core/dist/runtime-v2/index.js +5 -2
  144. package/core/dist/runtime-v2/index.js.map +1 -1
  145. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder-v2.test.js +32 -0
  146. package/core/dist/runtime-v2/internalization/__tests__/artificer-prompt-builder-v2.test.js.map +1 -1
  147. package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js +139 -0
  148. package/core/dist/runtime-v2/internalization/__tests__/artificer-rule-output.test.js.map +1 -1
  149. package/core/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js +20 -1
  150. package/core/dist/runtime-v2/internalization/__tests__/diag-chain-e2e.test.js.map +1 -1
  151. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.js +7 -0
  152. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-intent-tension.test.js.map +1 -1
  153. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.js +7 -6
  154. package/core/dist/runtime-v2/internalization/__tests__/diag-rootcause-runner.test.js.map +1 -1
  155. package/core/dist/runtime-v2/internalization/__tests__/internalization-task-guards.test.js +1 -53
  156. package/core/dist/runtime-v2/internalization/__tests__/internalization-task-guards.test.js.map +1 -1
  157. package/core/dist/runtime-v2/internalization/__tests__/rule-host-input-builder.test.js +23 -0
  158. package/core/dist/runtime-v2/internalization/__tests__/rule-host-input-builder.test.js.map +1 -1
  159. package/core/dist/runtime-v2/internalization/artificer-output.d.ts +7 -0
  160. package/core/dist/runtime-v2/internalization/artificer-output.d.ts.map +1 -1
  161. package/core/dist/runtime-v2/internalization/artificer-output.js +22 -1
  162. package/core/dist/runtime-v2/internalization/artificer-output.js.map +1 -1
  163. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.d.ts.map +1 -1
  164. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js +2 -0
  165. package/core/dist/runtime-v2/internalization/artificer-prompt-builder.js.map +1 -1
  166. package/core/dist/runtime-v2/internalization/artificer-runner.d.ts.map +1 -1
  167. package/core/dist/runtime-v2/internalization/artificer-runner.js +13 -0
  168. package/core/dist/runtime-v2/internalization/artificer-runner.js.map +1 -1
  169. package/core/dist/runtime-v2/internalization/diag-distiller-runner.js +4 -4
  170. package/core/dist/runtime-v2/internalization/diag-distiller-runner.js.map +1 -1
  171. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.js +5 -5
  172. package/core/dist/runtime-v2/internalization/diag-rootcause-runner.js.map +1 -1
  173. package/core/dist/runtime-v2/internalization/diag-router-runner.js +4 -4
  174. package/core/dist/runtime-v2/internalization/diag-router-runner.js.map +1 -1
  175. package/core/dist/runtime-v2/internalization/evaluator-runner.d.ts.map +1 -1
  176. package/core/dist/runtime-v2/internalization/evaluator-runner.js +7 -1
  177. package/core/dist/runtime-v2/internalization/evaluator-runner.js.map +1 -1
  178. package/core/dist/runtime-v2/internalization/index.d.ts +1 -1
  179. package/core/dist/runtime-v2/internalization/index.d.ts.map +1 -1
  180. package/core/dist/runtime-v2/internalization/index.js +1 -1
  181. package/core/dist/runtime-v2/internalization/index.js.map +1 -1
  182. package/core/dist/runtime-v2/internalization/internalization-task-guards.d.ts +0 -19
  183. package/core/dist/runtime-v2/internalization/internalization-task-guards.d.ts.map +1 -1
  184. package/core/dist/runtime-v2/internalization/internalization-task-guards.js +1 -29
  185. package/core/dist/runtime-v2/internalization/internalization-task-guards.js.map +1 -1
  186. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts +2 -0
  187. package/core/dist/runtime-v2/pain-signal-runtime-factory.d.ts.map +1 -1
  188. package/core/dist/runtime-v2/pain-signal-runtime-factory.js +2 -0
  189. package/core/dist/runtime-v2/pain-signal-runtime-factory.js.map +1 -1
  190. package/core/dist/runtime-v2/signal-collector/__tests__/keyword-stage.test.d.ts +2 -0
  191. package/core/dist/runtime-v2/signal-collector/__tests__/keyword-stage.test.d.ts.map +1 -0
  192. package/core/dist/runtime-v2/signal-collector/__tests__/keyword-stage.test.js +39 -0
  193. package/core/dist/runtime-v2/signal-collector/__tests__/keyword-stage.test.js.map +1 -0
  194. package/core/dist/runtime-v2/signal-collector/__tests__/llm-stage.test.d.ts +2 -0
  195. package/core/dist/runtime-v2/signal-collector/__tests__/llm-stage.test.d.ts.map +1 -0
  196. package/core/dist/runtime-v2/signal-collector/__tests__/llm-stage.test.js +34 -0
  197. package/core/dist/runtime-v2/signal-collector/__tests__/llm-stage.test.js.map +1 -0
  198. package/core/dist/runtime-v2/signal-collector/__tests__/signal-collector.test.d.ts +2 -0
  199. package/core/dist/runtime-v2/signal-collector/__tests__/signal-collector.test.d.ts.map +1 -0
  200. package/core/dist/runtime-v2/signal-collector/__tests__/signal-collector.test.js +222 -0
  201. package/core/dist/runtime-v2/signal-collector/__tests__/signal-collector.test.js.map +1 -0
  202. package/core/dist/runtime-v2/signal-collector/__tests__/types.test.d.ts +2 -0
  203. package/core/dist/runtime-v2/signal-collector/__tests__/types.test.d.ts.map +1 -0
  204. package/core/dist/runtime-v2/signal-collector/__tests__/types.test.js +35 -0
  205. package/core/dist/runtime-v2/signal-collector/__tests__/types.test.js.map +1 -0
  206. package/core/dist/runtime-v2/signal-collector/index.d.ts +5 -0
  207. package/core/dist/runtime-v2/signal-collector/index.d.ts.map +1 -0
  208. package/core/dist/runtime-v2/signal-collector/index.js +5 -0
  209. package/core/dist/runtime-v2/signal-collector/index.js.map +1 -0
  210. package/core/dist/runtime-v2/signal-collector/keyword-stage.d.ts +20 -0
  211. package/core/dist/runtime-v2/signal-collector/keyword-stage.d.ts.map +1 -0
  212. package/core/dist/runtime-v2/signal-collector/keyword-stage.js +61 -0
  213. package/core/dist/runtime-v2/signal-collector/keyword-stage.js.map +1 -0
  214. package/core/dist/runtime-v2/signal-collector/llm-stage.d.ts +16 -0
  215. package/core/dist/runtime-v2/signal-collector/llm-stage.d.ts.map +1 -0
  216. package/core/dist/runtime-v2/signal-collector/llm-stage.js +34 -0
  217. package/core/dist/runtime-v2/signal-collector/llm-stage.js.map +1 -0
  218. package/core/dist/runtime-v2/signal-collector/signal-collector.d.ts +16 -0
  219. package/core/dist/runtime-v2/signal-collector/signal-collector.d.ts.map +1 -0
  220. package/core/dist/runtime-v2/signal-collector/signal-collector.js +71 -0
  221. package/core/dist/runtime-v2/signal-collector/signal-collector.js.map +1 -0
  222. package/core/dist/runtime-v2/signal-collector/types.d.ts +61 -0
  223. package/core/dist/runtime-v2/signal-collector/types.d.ts.map +1 -0
  224. package/core/dist/runtime-v2/signal-collector/types.js +45 -0
  225. package/core/dist/runtime-v2/signal-collector/types.js.map +1 -0
  226. package/core/dist/runtime-v2/store/schema-conformance.test.js +43 -0
  227. package/core/dist/runtime-v2/store/schema-conformance.test.js.map +1 -1
  228. package/core/dist/runtime-v2/types/event-types.d.ts +40 -3
  229. package/core/dist/runtime-v2/types/event-types.d.ts.map +1 -1
  230. package/core/dist/runtime-v2/types/event-types.js +9 -0
  231. package/core/dist/runtime-v2/types/event-types.js.map +1 -1
  232. package/core/dist/runtime-v2/types/index.d.ts +2 -2
  233. package/core/dist/runtime-v2/types/index.d.ts.map +1 -1
  234. package/core/dist/runtime-v2/types/index.js +1 -1
  235. package/core/dist/runtime-v2/types/index.js.map +1 -1
  236. package/core/dist/workflow-funnel-loader.js +1 -1
  237. package/core/dist/workflow-funnel-loader.js.map +1 -1
  238. package/dist/i18n.d.ts.map +1 -1
  239. package/dist/i18n.js +6 -0
  240. package/dist/i18n.js.map +1 -1
  241. package/dist/index.js +12 -3
  242. package/dist/index.js.map +1 -1
  243. package/dist/installer.d.ts +3 -0
  244. package/dist/installer.d.ts.map +1 -1
  245. package/dist/installer.js +150 -1
  246. package/dist/installer.js.map +1 -1
  247. package/dist/mvp-config.d.ts +8 -0
  248. package/dist/mvp-config.d.ts.map +1 -1
  249. package/dist/mvp-config.js +34 -12
  250. package/dist/mvp-config.js.map +1 -1
  251. package/package.json +1 -1
  252. package/pd-cli/dist/commands/__tests__/runtime-probe-config.test.js +2 -2
  253. package/pd-cli/dist/commands/__tests__/runtime-probe-config.test.js.map +1 -1
  254. package/pd-cli/dist/commands/demo-story-a.d.ts.map +1 -1
  255. package/pd-cli/dist/commands/demo-story-a.js +4 -2
  256. package/pd-cli/dist/commands/demo-story-a.js.map +1 -1
  257. package/pd-cli/dist/commands/proven-channel-baseline.d.ts.map +1 -1
  258. package/pd-cli/dist/commands/proven-channel-baseline.js +4 -2
  259. package/pd-cli/dist/commands/proven-channel-baseline.js.map +1 -1
  260. package/pd-cli/dist/commands/runtime-activation.d.ts +4 -0
  261. package/pd-cli/dist/commands/runtime-activation.d.ts.map +1 -1
  262. package/pd-cli/dist/commands/runtime-activation.js +187 -10
  263. package/pd-cli/dist/commands/runtime-activation.js.map +1 -1
  264. package/pd-cli/dist/commands/runtime-canary.d.ts.map +1 -1
  265. package/pd-cli/dist/commands/runtime-canary.js +4 -2
  266. package/pd-cli/dist/commands/runtime-canary.js.map +1 -1
  267. package/pd-cli/dist/commands/runtime-health-snapshot.d.ts.map +1 -1
  268. package/pd-cli/dist/commands/runtime-health-snapshot.js +4 -2
  269. package/pd-cli/dist/commands/runtime-health-snapshot.js.map +1 -1
  270. package/pd-cli/dist/commands/runtime-internalization-integrity.d.ts.map +1 -1
  271. package/pd-cli/dist/commands/runtime-internalization-integrity.js +4 -2
  272. package/pd-cli/dist/commands/runtime-internalization-integrity.js.map +1 -1
  273. package/pd-cli/dist/index.js +5 -63
  274. package/pd-cli/dist/index.js.map +1 -1
  275. package/pd-cli/dist/services/config-doctor.d.ts.map +1 -1
  276. package/pd-cli/dist/services/config-doctor.js +9 -2
  277. package/pd-cli/dist/services/config-doctor.js.map +1 -1
  278. package/pd-cli/dist/services/runtime-adapter-resolver.d.ts.map +1 -1
  279. package/pd-cli/dist/services/runtime-adapter-resolver.js +1 -0
  280. package/pd-cli/dist/services/runtime-adapter-resolver.js.map +1 -1
  281. package/plugin/dist/commands/context.js +17 -11
  282. package/plugin/dist/commands/samples.js +25 -0
  283. package/plugin/dist/core/event-log.d.ts +11 -1
  284. package/plugin/dist/core/event-log.js +13 -0
  285. package/plugin/dist/core/init.js +3 -4
  286. package/plugin/dist/core/rule-host.d.ts +50 -0
  287. package/plugin/dist/core/rule-host.js +116 -19
  288. package/plugin/dist/core/signal-collector-host.d.ts +105 -0
  289. package/plugin/dist/core/signal-collector-host.js +337 -0
  290. package/plugin/dist/hooks/gate.js +1 -1
  291. package/plugin/dist/hooks/prompt.d.ts +3 -2
  292. package/plugin/dist/hooks/prompt.js +48 -586
  293. package/plugin/dist/service/evolution-dedup.d.ts +1 -1
  294. package/plugin/dist/service/evolution-worker.d.ts +7 -31
  295. package/plugin/dist/service/evolution-worker.js +17 -36
  296. package/plugin/dist/service/queue-io.js +14 -2
  297. package/plugin/dist/service/queue-migration.d.ts +27 -26
  298. package/plugin/dist/service/queue-migration.js +57 -0
  299. package/plugin/dist/types/event-types.d.ts +1 -1
  300. package/plugin/dist/types.d.ts +5 -25
  301. package/plugin/dist/types.js +4 -9
  302. package/plugin/dist/utils/hashing.js +1 -1
  303. package/plugin/templates/langs/en/core/AGENTS.md +2 -2
  304. package/plugin/templates/langs/en/core/TOOLS.md +1 -1
  305. package/plugin/templates/langs/zh/core/AGENTS.md +2 -2
  306. package/plugin/templates/langs/zh/core/TOOLS.md +1 -1
  307. package/templates/langs/en/core/AGENTS.md +2 -2
  308. package/templates/langs/en/core/TOOLS.md +1 -1
  309. package/templates/langs/zh/core/AGENTS.md +2 -2
  310. package/templates/langs/zh/core/TOOLS.md +1 -1
  311. package/plugin/dist/constants/diagnostician.d.ts +0 -12
  312. package/plugin/dist/constants/diagnostician.js +0 -65
  313. package/plugin/dist/service/evolution-queue-migration.d.ts +0 -128
  314. package/plugin/dist/service/evolution-queue-migration.js +0 -53
  315. package/plugin/templates/langs/en/skills/pd-diagnostician/SKILL.md +0 -466
  316. package/plugin/templates/langs/zh/skills/pd-diagnostician/SKILL.md +0 -391
  317. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +0 -287
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { useTranslation } from "react-i18next";
4
+ import { Check, X, CheckCheck, XCircle } from "lucide-react";
5
+ import { Badge } from "../../components/ui/badge.js";
6
+ import { Tooltip, TooltipContent, TooltipTrigger, } from "../../components/ui/tooltip.js";
7
+ // ── Helpers ─────────────────────────────────────────────────────────────────
8
+ // ── Component ───────────────────────────────────────────────────────────────
9
+ export function PendingTermsSection({ terms, onConfirm, onIgnore, onConfirmAll, onIgnoreAll, }) {
10
+ const { t, i18n } = useTranslation();
11
+ const [selected, setSelected] = useState(new Set());
12
+ const hasBatchOps = !!onConfirmAll || !!onIgnoreAll;
13
+ const hasRowOps = !!onConfirm || !!onIgnore;
14
+ // 分类中文映射
15
+ const categoryLabel = {
16
+ correction: t("pages.signalKeywords.categoryCorrection"),
17
+ empathy: t("pages.signalKeywords.categoryEmpathy"),
18
+ };
19
+ // 切换选中
20
+ const toggleSelected = (term) => {
21
+ setSelected((prev) => {
22
+ const next = new Set(prev);
23
+ if (next.has(term)) {
24
+ next.delete(term);
25
+ }
26
+ else {
27
+ next.add(term);
28
+ }
29
+ return next;
30
+ });
31
+ };
32
+ return (_jsxs("section", { children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-[15px] font-semibold text-ink", children: t("pages.signalKeywords.pendingTerms.title") }), _jsx("p", { className: "mt-0.5 text-[12px] text-ink-4 leading-[1.5]", children: t("pages.signalKeywords.pendingTerms.subtitle") })] }), _jsx("span", { className: "text-[12px] text-ink-4 tabular-nums", children: t("pages.signalKeywords.nTerms", { count: terms.length }) })] }), terms.length > 0 && hasBatchOps && (_jsxs("div", { className: "flex items-center justify-between mb-3 px-3 py-2 bg-surface border border-line rounded-[4px]", children: [_jsx("span", { className: "text-[12px] text-ink-4", children: selected.size > 0
33
+ ? t("pages.signalKeywords.selectedNOfTotal", { selected: selected.size, total: terms.length })
34
+ : t("pages.signalKeywords.nTermsPendingReview", { count: terms.length }) }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onConfirmAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-green bg-green/10 rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:bg-green/20 transition-colors", children: [_jsx(CheckCheck, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.confirmBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { type: "button", onClick: () => onIgnoreAll?.(), disabled: true, className: "flex items-center gap-1.5 px-2.5 py-1.5 text-[12px] font-medium text-ink-4 bg-surface border border-line rounded-[3px] disabled:opacity-30 disabled:cursor-not-allowed hover:text-danger hover:border-danger/30 transition-colors", children: [_jsx(XCircle, { className: "h-3.5 w-3.5" }), t("pages.signalKeywords.pendingTerms.ignoreBatch")] }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })] })] })), terms.length === 0 ? (_jsxs("div", { className: "px-4 py-12 text-center text-[13px] text-ink-4 border border-dashed border-line-2 rounded-[4px]", children: [_jsx("p", { children: t("pages.signalKeywords.pendingTerms.empty") }), _jsx("p", { className: "mt-2 text-[12px]", children: t("pages.signalKeywords.pendingTerms.emptyDescription") })] })) : (_jsxs("div", { className: "border border-line rounded-[4px] overflow-hidden", children: [_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-2.5 bg-surface text-[11px] font-medium text-ink-4 uppercase tracking-[var(--tracking-wide)] border-b border-line items-center", children: [_jsx("span", {}), _jsx("span", { children: t("pages.signalKeywords.colTerm") }), _jsx("span", { children: t("pages.signalKeywords.colCategory") }), _jsx("span", { children: t("pages.signalKeywords.colPrecision") }), _jsx("span", { children: t("pages.signalKeywords.colReason") }), hasRowOps && _jsx("span", { className: "text-right", children: t("pages.signalKeywords.colActions") })] }), terms.map((term) => (_jsxs("div", { className: "grid grid-cols-[24px_1fr_100px_90px_1fr_100px] gap-3 px-4 py-3 items-start border-b border-line last:border-b-0 hover:bg-surface/50 transition-colors", children: [_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("input", { type: "checkbox", checked: selected.has(term.term), onChange: () => toggleSelected(term.term), disabled: true, className: "mt-0.5 h-3.5 w-3.5 rounded border-line text-gov disabled:opacity-30 disabled:cursor-not-allowed" }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }), _jsxs("div", { className: "min-w-0", children: [_jsx("span", { className: "text-[13px] text-ink font-medium block truncate", children: term.term }), _jsx("span", { className: "text-[11px] text-ink-4 mt-0.5 block", children: new Date(term.discoveredAt).toLocaleDateString(i18n.language) })] }), _jsx(Badge, { variant: term.suggestedCategory === "correction" ? "default" : "amber", children: categoryLabel[term.suggestedCategory] ?? term.suggestedCategory }), _jsx("span", { className: "text-[12px] text-ink-3", children: term.suggestedPrecision === "high" ? (_jsx("span", { className: "text-green", children: t("pages.signalKeywords.precisionHigh") })) : (_jsx("span", { className: "text-amber", children: t("pages.signalKeywords.precisionAmbiguous") })) }), _jsx("span", { className: "text-[12px] text-ink-3 leading-[1.5] line-clamp-2", children: term.reason }), hasRowOps && (_jsxs("div", { className: "flex items-center justify-end gap-1", children: [onConfirm && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onConfirm(term), disabled: true, className: "p-1.5 text-ink-4 hover:text-green disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.confirm"), children: _jsx(Check, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] })), onIgnore && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => onIgnore(term.term), disabled: true, className: "p-1.5 text-ink-4 hover:text-danger disabled:opacity-30 disabled:cursor-not-allowed transition-colors", "aria-label": t("pages.signalKeywords.pendingTerms.ignore"), children: _jsx(X, { className: "h-3.5 w-3.5" }) }) }), _jsx(TooltipContent, { children: t("pages.signalKeywords.phase2Tooltip") })] }))] }))] }, term.term)))] }))] }));
35
+ }
@@ -0,0 +1 @@
1
+ export declare function SignalKeywordsPage(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,49 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect, useCallback } from "react";
3
+ import { useTranslation } from "react-i18next";
4
+ import { useNavigate } from "react-router-dom";
5
+ import { ArrowLeft } from "lucide-react";
6
+ import { listActiveSignalKeywords, listPendingSignalTerms, } from "../../api.js";
7
+ import { KeywordListSection } from "./KeywordListSection.js";
8
+ import { PendingTermsSection } from "./PendingTermsSection.js";
9
+ import { KeywordEditDialog } from "./KeywordEditDialog.js";
10
+ export function SignalKeywordsPage() {
11
+ const { t } = useTranslation();
12
+ const navigate = useNavigate();
13
+ const [keywords, setKeywords] = useState([]);
14
+ const [pendingTerms, setPendingTerms] = useState([]);
15
+ const [loading, setLoading] = useState(true);
16
+ const [error, setError] = useState(null);
17
+ const loadData = useCallback(async () => {
18
+ setLoading(true);
19
+ setError(null);
20
+ try {
21
+ const [kwResult, ptResult] = await Promise.all([
22
+ listActiveSignalKeywords(),
23
+ listPendingSignalTerms(),
24
+ ]);
25
+ if (!kwResult.success) {
26
+ setError(t("pages.signalKeywords.loadError"));
27
+ return;
28
+ }
29
+ if (!ptResult.success) {
30
+ setError(t("pages.signalKeywords.loadError"));
31
+ return;
32
+ }
33
+ setKeywords(kwResult.data ?? []);
34
+ setPendingTerms(ptResult.data ?? []);
35
+ }
36
+ catch {
37
+ setError(t("pages.signalKeywords.loadError"));
38
+ }
39
+ finally {
40
+ setLoading(false);
41
+ }
42
+ }, [t]);
43
+ useEffect(() => {
44
+ loadData();
45
+ }, [loadData]);
46
+ return (_jsxs("div", { className: "max-w-[960px] mx-auto px-6 py-8", children: [_jsxs("div", { className: "flex items-center gap-3 mb-6", children: [_jsxs("button", { type: "button", onClick: () => navigate("/control-center"), className: "flex items-center gap-1.5 text-[13px] text-ink-3 hover:text-ink transition-colors", children: [_jsx(ArrowLeft, { className: "h-4 w-4" }), t("pages.controlCenter.eyebrow")] }), _jsx("span", { className: "text-ink-4 text-[13px]", children: "/" }), _jsx("span", { className: "text-[13px] text-ink font-medium", children: t("pages.signalKeywords.title") })] }), error && (_jsx("div", { className: "mb-6 px-4 py-3 border border-danger rounded-[4px] bg-danger/10 text-[13px] text-danger", children: error })), loading && (_jsx("div", { className: "flex items-center justify-center py-20", children: _jsx("div", { className: "w-6 h-6 border-2 border-gov border-t-transparent rounded-full animate-spin" }) })), !loading && !error && (_jsxs("div", { className: "space-y-8", children: [_jsxs("div", { children: [_jsx("h1", { className: "text-[20px] font-semibold text-ink tracking-[-0.01em]", children: t("pages.signalKeywords.title") }), _jsx("p", { className: "mt-1 text-[13px] text-ink-3 leading-[1.55]", children: t("pages.signalKeywords.subtitle") })] }), _jsx(KeywordListSection, { keywords: keywords }), _jsx(PendingTermsSection, { terms: pendingTerms }), _jsx("div", { className: "pt-2 border-t border-line", children: _jsx(KeywordEditDialog
47
+ // Phase 2: onSubmit
48
+ , {}) })] }))] }));
49
+ }
@@ -0,0 +1,5 @@
1
+ interface WelcomePageProps {
2
+ workspaceId: string;
3
+ }
4
+ export declare function WelcomePage({ workspaceId }: WelcomePageProps): import("react/jsx-runtime").JSX.Element;
5
+ export {};
@@ -0,0 +1,185 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useEffect, useCallback, useRef } from 'react';
3
+ import { useNavigate } from 'react-router-dom';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { CircuitDiagram } from '../../components/onboarding/CircuitDiagram.js';
6
+ import { DemoResultView } from '../../components/onboarding/DemoResultView.js';
7
+ import { getOnboardingState, setOnboardingState } from '../../utils/onboarding-state.js';
8
+ import { request } from '../../api.js';
9
+ // Polling configuration for step 3 evidence detection (spec 6.5.2).
10
+ const TWO_HOURS_MS = 2 * 60 * 60 * 1000;
11
+ const POLL_INTERVAL_MS = 30 * 1000;
12
+ // rc-1/rc-2/rc-4: validate the demo response shape before use.
13
+ // The backend owns this shape, but parsed JSON is treated as unknown.
14
+ function isDemoStage(value) {
15
+ if (typeof value !== 'object' || value === null)
16
+ return false;
17
+ const name = Object.hasOwn(value, 'name') ? Reflect.get(value, 'name') : undefined;
18
+ const status = Object.hasOwn(value, 'status') ? Reflect.get(value, 'status') : undefined;
19
+ if (typeof name !== 'string')
20
+ return false;
21
+ return status === 'passed' || status === 'failed' || status === 'degraded' || status === 'skipped';
22
+ }
23
+ function parseDemoResponse(value) {
24
+ if (typeof value !== 'object' || value === null)
25
+ return null;
26
+ const v = value;
27
+ if (typeof v.simulated !== 'boolean')
28
+ return null;
29
+ if (typeof v.demo !== 'object' || v.demo === null)
30
+ return null;
31
+ const d = v.demo;
32
+ if (typeof d.status !== 'string')
33
+ return null;
34
+ const demo = { status: d.status };
35
+ if (typeof d.generatedAt === 'string')
36
+ demo.generatedAt = d.generatedAt;
37
+ if (typeof d.narrative === 'string')
38
+ demo.narrative = d.narrative;
39
+ if (typeof d.storyDescription === 'string')
40
+ demo.storyDescription = d.storyDescription;
41
+ if (typeof d.simulated === 'boolean')
42
+ demo.simulated = d.simulated;
43
+ if (Object.hasOwn(d, 'stages')) {
44
+ if (!Array.isArray(d.stages) || !d.stages.every(isDemoStage))
45
+ return null;
46
+ demo.stages = d.stages;
47
+ }
48
+ return { demo, simulated: v.simulated };
49
+ }
50
+ export function WelcomePage({ workspaceId }) {
51
+ const { t } = useTranslation();
52
+ const navigate = useNavigate();
53
+ const [step, setStep] = useState(1);
54
+ const [demoStatus, setDemoStatus] = useState('idle');
55
+ const [demoResult, setDemoResult] = useState(null);
56
+ const [demoError, setDemoError] = useState(null);
57
+ const [stateError, setStateError] = useState(null);
58
+ const [pollingActive, setPollingActive] = useState(false);
59
+ const [pollingStatus, setPollingStatus] = useState('idle');
60
+ const [pollingError, setPollingError] = useState(null);
61
+ // Refs for polling cleanup (spec 6.5.2 test case 3: unmount clears timers).
62
+ const pollingIntervalRef = useRef(null);
63
+ const pollingTimeoutRef = useRef(null);
64
+ // P2-2B: track consecutive polling errors; after 3, stop polling and surface
65
+ // the failure (rc-9: no silent fallback). Reset to 0 on any successful poll.
66
+ const errorCountRef = useRef(0);
67
+ // P2-3: baseline record count captured when polling starts, so we only
68
+ // trigger evidence-found on NEW evidence (not pre-existing records).
69
+ const baselineCountRef = useRef(0);
70
+ // If onboarding was already completed for this workspace, skip the wizard.
71
+ useEffect(() => {
72
+ const state = getOnboardingState(workspaceId);
73
+ if (state.completed) {
74
+ navigate('/focus', { replace: true });
75
+ }
76
+ }, [workspaceId, navigate]);
77
+ const completeOnboarding = useCallback((status) => {
78
+ if (!setOnboardingState(workspaceId, {
79
+ completed: true,
80
+ step: 3,
81
+ status,
82
+ completedAt: new Date().toISOString(),
83
+ })) {
84
+ setStateError(t('pages.welcome.stateSaveError'));
85
+ return;
86
+ }
87
+ navigate('/focus', { replace: true });
88
+ }, [workspaceId, navigate, t]);
89
+ const runDemo = useCallback(async () => {
90
+ setDemoStatus('loading');
91
+ setDemoError(null);
92
+ try {
93
+ const response = await request('/api/v1/onboarding/run-demo', { method: 'POST' }, parseDemoResponse);
94
+ if (!response.success) {
95
+ throw new Error(response.error);
96
+ }
97
+ setDemoResult(response.data.demo);
98
+ setDemoStatus('success');
99
+ }
100
+ catch (err) {
101
+ const message = err instanceof Error ? err.message : 'Demo failed to start';
102
+ setDemoError(message);
103
+ setDemoStatus('error');
104
+ }
105
+ }, []);
106
+ const skipOnboarding = useCallback(() => {
107
+ completeOnboarding('skipped');
108
+ }, [completeOnboarding]);
109
+ // EP-05 (Loop State Freshness): each poll fetches fresh evidence.
110
+ const stopPolling = useCallback(() => {
111
+ setPollingActive(false);
112
+ if (pollingIntervalRef.current) {
113
+ clearInterval(pollingIntervalRef.current);
114
+ pollingIntervalRef.current = null;
115
+ }
116
+ if (pollingTimeoutRef.current) {
117
+ clearTimeout(pollingTimeoutRef.current);
118
+ pollingTimeoutRef.current = null;
119
+ }
120
+ }, []);
121
+ const startPolling = useCallback(() => {
122
+ setPollingActive(true);
123
+ setPollingStatus('polling');
124
+ setPollingError(null);
125
+ errorCountRef.current = 0;
126
+ pollingTimeoutRef.current = setTimeout(() => {
127
+ setPollingStatus('timeout');
128
+ stopPolling();
129
+ }, TWO_HOURS_MS);
130
+ // P2-3: capture baseline count on first poll, then only trigger
131
+ // evidence-found when count exceeds baseline (NEW evidence appeared).
132
+ let baselineCaptured = false;
133
+ const checkForEvidence = async () => {
134
+ try {
135
+ const response = await request('/api/v1/evidence-chain');
136
+ // P2-A: request() returns { success: false, error } on HTTP/network
137
+ // errors instead of throwing. Convert non-success into a thrown error
138
+ // so the catch block (error counter + retry UI) actually fires.
139
+ if (!response.success) {
140
+ throw new Error(response.error || 'Failed to fetch evidence');
141
+ }
142
+ if (response.data) {
143
+ const data = response.data;
144
+ if (typeof data === 'object' && data !== null && Object.hasOwn(data, 'records')) {
145
+ const records = data.records;
146
+ if (Array.isArray(records)) {
147
+ // P2-2B: a successful poll with valid data resets the error streak.
148
+ errorCountRef.current = 0;
149
+ if (!baselineCaptured) {
150
+ // First poll: capture baseline count, do not trigger.
151
+ baselineCountRef.current = records.length;
152
+ baselineCaptured = true;
153
+ return;
154
+ }
155
+ if (records.length > baselineCountRef.current) {
156
+ setPollingStatus('evidence-found');
157
+ stopPolling();
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+ catch {
164
+ // P2-2B (rc-9: no silent fallback) — surface the failure instead of
165
+ // swallowing it. After 3 consecutive errors, stop polling and show the
166
+ // error UI so the user can retry rather than waiting up to 2 hours.
167
+ errorCountRef.current += 1;
168
+ setPollingError(t('pages.welcome.step3.pollingError'));
169
+ if (errorCountRef.current >= 3) {
170
+ setPollingStatus('error');
171
+ stopPolling();
172
+ }
173
+ }
174
+ };
175
+ checkForEvidence();
176
+ pollingIntervalRef.current = setInterval(checkForEvidence, POLL_INTERVAL_MS);
177
+ }, [stopPolling, t]);
178
+ // Cleanup on unmount (spec 6.5.2 test case 3: no memory leak).
179
+ useEffect(() => {
180
+ return () => {
181
+ stopPolling();
182
+ };
183
+ }, [stopPolling]);
184
+ return (_jsxs("div", { className: "welcome-page", role: "main", children: [_jsxs("header", { className: "welcome-header", children: [_jsx("h1", { children: t('pages.welcome.title') }), _jsx("p", { className: "welcome-subtitle", children: t('pages.welcome.subtitle') }), _jsx("div", { className: "welcome-step-indicator", role: "progressbar", "aria-valuetext": t('pages.welcome.stepIndicator', { current: step, total: 3 }), children: [1, 2, 3].map((s) => (_jsx("span", { className: `step-dot ${s === step ? 'active' : ''} ${s < step ? 'completed' : ''}` }, s))) })] }), stateError && _jsx("p", { className: "polling-error", role: "alert", children: stateError }), step === 1 && (_jsxs("section", { className: "welcome-step welcome-step-1", "aria-labelledby": "step1-title", children: [_jsx("h2", { id: "step1-title", children: t('pages.welcome.step1.title') }), _jsx("p", { children: t('pages.welcome.step1.description') }), _jsx(CircuitDiagram, {}), _jsxs("div", { className: "welcome-actions", children: [_jsx("button", { className: "pd-btn pd-btn-brand", onClick: () => setStep(2), children: t('pages.welcome.step1.startButton') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: skipOnboarding, children: t('pages.welcome.step1.skipButton') })] })] })), step === 2 && (_jsxs("section", { className: "welcome-step welcome-step-2", "aria-labelledby": "step2-title", children: [_jsx("h2", { id: "step2-title", children: t('pages.welcome.step2.title') }), _jsx("p", { children: t('pages.welcome.step2.description') }), _jsx(DemoResultView, { result: demoResult, loading: demoStatus === 'loading', error: demoError }), _jsxs("div", { className: "welcome-actions", children: [demoStatus === 'idle' && (_jsx("button", { className: "pd-btn pd-btn-brand", onClick: runDemo, children: t('pages.welcome.step2.runDemoButton') })), (demoStatus === 'success' || demoStatus === 'error') && (_jsx("button", { className: "pd-btn pd-btn-alt", onClick: () => setStep(3), children: t('pages.welcome.step2.nextButton') }))] })] })), step === 3 && (_jsxs("section", { className: "welcome-step welcome-step-3", "aria-labelledby": "step3-title", children: [_jsx("h2", { id: "step3-title", children: t('pages.welcome.step3.title') }), _jsx("p", { children: t('pages.welcome.step3.description') }), _jsxs("div", { className: "example-prompt", role: "note", children: [_jsx("span", { className: "prompt-label", children: t('pages.welcome.step3.examplePrompt') }), _jsx("code", { className: "prompt-text", children: t('pages.welcome.step3.examplePromptText') })] }), pollingStatus === 'idle' && (_jsxs(_Fragment, { children: [_jsx("p", { className: "window-hint", children: t('pages.welcome.step3.windowHint') }), _jsxs("div", { className: "welcome-actions", children: [_jsx("button", { className: "pd-btn pd-btn-brand", onClick: () => { startPolling(); }, children: t('pages.welcome.step3.tryNowButton') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: () => completeOnboarding('demo'), children: t('pages.welcome.step3.goToFocusButton') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: skipOnboarding, children: t('pages.welcome.step3.skipButton') })] })] })), pollingStatus === 'polling' && (_jsxs("div", { className: "polling-active", role: "status", "aria-live": "polite", children: [_jsx("p", { children: t('pages.welcome.step3.pollingActive') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: () => { stopPolling(); completeOnboarding('demo'); }, children: t('pages.welcome.step3.stopPollingButton') })] })), pollingStatus === 'evidence-found' && (_jsxs("div", { className: "polling-success", role: "status", children: [_jsx("p", { children: t('pages.welcome.step3.evidenceFound') }), _jsx("button", { className: "pd-btn pd-btn-brand", onClick: () => completeOnboarding('evidence_found'), children: t('pages.welcome.step3.goToFocusButton') })] })), pollingStatus === 'timeout' && (_jsxs("div", { className: "polling-timeout", role: "status", children: [_jsx("p", { children: t('pages.welcome.step3.timeoutHint') }), _jsx("button", { className: "pd-btn pd-btn-brand", onClick: () => completeOnboarding('demo'), children: t('pages.welcome.step3.goToFocusButton') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: skipOnboarding, children: t('pages.welcome.step3.skipButton') })] })), pollingStatus === 'error' && (_jsxs("div", { className: "polling-error", role: "alert", children: [_jsx("p", { children: pollingError ?? t('pages.welcome.step3.pollingError') }), _jsxs("div", { className: "welcome-actions", children: [_jsx("button", { className: "pd-btn pd-btn-brand", onClick: () => { startPolling(); }, children: t('pages.welcome.step3.retryButton') }), _jsx("button", { className: "pd-btn pd-btn-alt", onClick: () => completeOnboarding('demo'), children: t('pages.welcome.step3.goToFocusButton') })] })] }))] }))] }));
185
+ }
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ // Mock localStorage
3
+ const localStorageMock = (() => {
4
+ let store = {};
5
+ return {
6
+ getItem: vi.fn((key) => store[key] ?? null),
7
+ setItem: vi.fn((key, value) => { store[key] = value; }),
8
+ removeItem: vi.fn((key) => { delete store[key]; }),
9
+ clear: vi.fn(() => { store = {}; }),
10
+ };
11
+ })();
12
+ Object.defineProperty(globalThis, 'localStorage', { value: localStorageMock });
13
+ import { getOnboardingState, setOnboardingState, resetOnboardingState, ONBOARDING_STORAGE_KEY_PREFIX } from '../onboarding-state.js';
14
+ describe('Onboarding state with workspaceId dimension', () => {
15
+ beforeEach(() => {
16
+ localStorageMock.clear();
17
+ localStorageMock.getItem.mockClear();
18
+ localStorageMock.setItem.mockClear();
19
+ localStorageMock.removeItem.mockClear();
20
+ });
21
+ it('reports write and reset failures so callers cannot show false success', () => {
22
+ localStorageMock.setItem.mockImplementationOnce(() => { throw new Error('quota'); });
23
+ expect(setOnboardingState('ws-full', { completed: true, step: 3, status: 'demo' })).toBe(false);
24
+ localStorageMock.removeItem.mockImplementationOnce(() => { throw new Error('blocked'); });
25
+ expect(resetOnboardingState('ws-full')).toBe(false);
26
+ });
27
+ it('Given new workspace, When getOnboardingState called, Then returns default incomplete state', () => {
28
+ const state = getOnboardingState('ws-123');
29
+ expect(state.completed).toBe(false);
30
+ expect(state.step).toBe(0);
31
+ expect(state.status).toBe('pending');
32
+ });
33
+ it('Given onboarding completed, When setOnboardingState called with demo status, Then state persisted with workspaceId key', () => {
34
+ setOnboardingState('ws-123', { completed: true, step: 3, status: 'demo' });
35
+ const state = getOnboardingState('ws-123');
36
+ expect(state.completed).toBe(true);
37
+ expect(state.status).toBe('demo');
38
+ expect(state.step).toBe(3);
39
+ });
40
+ it('Given two workspaces, When state set for ws-A, Then ws-B state is independent (no cross-workspace leakage)', () => {
41
+ setOnboardingState('ws-A', { completed: true, step: 3, status: 'demo' });
42
+ const stateB = getOnboardingState('ws-B');
43
+ expect(stateB.completed).toBe(false);
44
+ expect(stateB.status).toBe('pending');
45
+ });
46
+ it('Given completed onboarding, When resetOnboardingState called, Then state returns to default', () => {
47
+ setOnboardingState('ws-123', { completed: true, step: 3, status: 'skipped' });
48
+ resetOnboardingState('ws-123');
49
+ const state = getOnboardingState('ws-123');
50
+ expect(state.completed).toBe(false);
51
+ expect(state.step).toBe(0);
52
+ expect(state.status).toBe('pending');
53
+ });
54
+ it('Given malformed localStorage data, When getOnboardingState called, Then returns safe default (rc-1 treat as unknown)', () => {
55
+ localStorageMock.getItem.mockReturnValueOnce('not-json');
56
+ const state = getOnboardingState('ws-broken');
57
+ expect(state.completed).toBe(false);
58
+ expect(state.status).toBe('pending');
59
+ });
60
+ it('Given non-string completedAt, When state is loaded, Then rejects the malformed contract', () => {
61
+ localStorageMock.getItem.mockReturnValueOnce(JSON.stringify({
62
+ completed: true, step: 3, status: 'evidence_found', completedAt: 123,
63
+ }));
64
+ expect(getOnboardingState('ws-invalid-date')).toEqual({
65
+ completed: false, step: 0, status: 'pending',
66
+ });
67
+ });
68
+ it('Given localStorage key prefix, Then key format is pd_onboarding_<workspaceId>', () => {
69
+ setOnboardingState('ws-123', { completed: true, step: 3, status: 'demo' });
70
+ expect(localStorageMock.setItem).toHaveBeenCalledWith(`${ONBOARDING_STORAGE_KEY_PREFIX}_ws-123`, expect.any(String));
71
+ });
72
+ });
@@ -42,6 +42,19 @@ export interface AgentMeta {
42
42
  /** MVP 状态说明(可选,仅 philosopher/rolloutReviewer 有) */
43
43
  mvpNoteZh?: string;
44
44
  mvpNoteEn?: string;
45
+ /** 操作入口(可选,仅侧链代理用于跳转管理页面) */
46
+ action?: ActionMeta;
47
+ }
48
+ /**
49
+ * 操作入口(可选,仅侧链代理用于跳转管理页面)
50
+ */
51
+ export interface ActionMeta {
52
+ /** 链接文本(中) */
53
+ linkTextZh: string;
54
+ /** 链接文本(英) */
55
+ linkTextEn: string;
56
+ /** 路由路径 */
57
+ to: string;
45
58
  }
46
59
  export interface AgentGroupMeta {
47
60
  id: AgentGroup;
@@ -255,6 +255,11 @@ export const AGENT_METADATA = {
255
255
  techDetailZh: {},
256
256
  techDetailEn: {},
257
257
  isCore: true,
258
+ action: {
259
+ linkTextZh: '管理关键词',
260
+ linkTextEn: 'Manage Keywords',
261
+ to: '/control-center/signal-keywords?category=correction',
262
+ },
258
263
  },
259
264
  empathyObserver: {
260
265
  name: 'empathyObserver',
@@ -271,5 +276,26 @@ export const AGENT_METADATA = {
271
276
  techDetailZh: {},
272
277
  techDetailEn: {},
273
278
  isCore: true,
279
+ action: {
280
+ linkTextZh: '管理关键词',
281
+ linkTextEn: 'Manage Keywords',
282
+ to: '/control-center/signal-keywords?category=empathy',
283
+ },
284
+ },
285
+ signalCollector: {
286
+ name: 'signalCollector',
287
+ group: 'sidechain',
288
+ displayNameZh: '信号采集器',
289
+ displayNameEn: 'Signal Collector',
290
+ roleZh: '统一捕捉用户纠正与情绪反馈(合并原 correction + empathy)',
291
+ roleEn: 'Unified capture of user corrections and emotional feedback (merges former correction + empathy)',
292
+ detailZh: '以前有两套并行的用户反馈检测:correction(抓"你错了")和 empathy(抓情绪挫败),词库重叠且各自维护。\n\n信号采集器把两者合并成一套:关键词快扫 + 本地 LLM 深度判断,按信号强度分流——明确纠错直接触发诊断,情绪推测走 GFI 累积。',
293
+ detailEn: 'Previously there were two parallel user-feedback detectors: correction (catching "you are wrong") and empathy (catching emotional frustration), with overlapping keyword stores maintained separately.\n\nThe Signal Collector merges them into one: keyword fast-scan + local LLM deep judgment, routed by signal strength — explicit corrections trigger diagnosis directly, emotional inference accumulates via GFI.',
294
+ impactLevel: 'amber',
295
+ impactZh: '退回纯关键词检测(高精度短语仍工作),LLM 深度判断关闭。歧义词和未命中场景召回率下降。',
296
+ impactEn: 'Falls back to keyword-only detection (high-precision phrases still work); LLM deep judgment disabled. Recall drops for ambiguous terms and missed cases.',
297
+ techDetailZh: {},
298
+ techDetailEn: {},
299
+ isCore: false,
274
300
  },
275
301
  };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Onboarding state persistence with workspaceId dimension.
3
+ * Prevents cross-workspace state leakage (spec §6.3 改动 1).
4
+ * localStorage is the single source of truth (no cross-device sync — YAGNI).
5
+ */
6
+ export interface OnboardingState {
7
+ completed: boolean;
8
+ step: number;
9
+ status: 'pending' | 'demo' | 'skipped' | 'evidence_found';
10
+ completedAt?: string;
11
+ }
12
+ export declare const ONBOARDING_STORAGE_KEY_PREFIX = "pd_onboarding";
13
+ /**
14
+ * Get onboarding state for a specific workspace.
15
+ * Treats localStorage data as unknown (rc-1) — validates shape before use.
16
+ */
17
+ export declare function getOnboardingState(workspaceId: string): OnboardingState;
18
+ /**
19
+ * Set onboarding state for a specific workspace.
20
+ */
21
+ export declare function setOnboardingState(workspaceId: string, state: OnboardingState): boolean;
22
+ /**
23
+ * Reset onboarding state for a specific workspace (Settings page "reset" button).
24
+ */
25
+ export declare function resetOnboardingState(workspaceId: string): boolean;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Onboarding state persistence with workspaceId dimension.
3
+ * Prevents cross-workspace state leakage (spec §6.3 改动 1).
4
+ * localStorage is the single source of truth (no cross-device sync — YAGNI).
5
+ */
6
+ const DEFAULT_STATE = {
7
+ completed: false,
8
+ step: 0,
9
+ status: 'pending',
10
+ };
11
+ export const ONBOARDING_STORAGE_KEY_PREFIX = 'pd_onboarding';
12
+ function storageKey(workspaceId) {
13
+ return `${ONBOARDING_STORAGE_KEY_PREFIX}_${workspaceId}`;
14
+ }
15
+ /**
16
+ * Type guard for OnboardingState (rc-2: no `as` bypass).
17
+ */
18
+ function isOnboardingState(value) {
19
+ if (typeof value !== 'object' || value === null)
20
+ return false;
21
+ const completed = Object.hasOwn(value, 'completed') ? Reflect.get(value, 'completed') : undefined;
22
+ const step = Object.hasOwn(value, 'step') ? Reflect.get(value, 'step') : undefined;
23
+ const status = Object.hasOwn(value, 'status') ? Reflect.get(value, 'status') : undefined;
24
+ const completedAt = Object.hasOwn(value, 'completedAt') ? Reflect.get(value, 'completedAt') : undefined;
25
+ return (typeof completed === 'boolean' &&
26
+ typeof step === 'number' &&
27
+ (status === 'pending' || status === 'demo' || status === 'skipped' || status === 'evidence_found') &&
28
+ (!Object.hasOwn(value, 'completedAt') || typeof completedAt === 'string'));
29
+ }
30
+ /**
31
+ * Get onboarding state for a specific workspace.
32
+ * Treats localStorage data as unknown (rc-1) — validates shape before use.
33
+ */
34
+ export function getOnboardingState(workspaceId) {
35
+ try {
36
+ const raw = localStorage.getItem(storageKey(workspaceId));
37
+ if (!raw)
38
+ return DEFAULT_STATE;
39
+ // rc-1: treat parsed JSON as unknown, validate shape
40
+ const parsed = JSON.parse(raw);
41
+ if (!isOnboardingState(parsed))
42
+ return DEFAULT_STATE;
43
+ return parsed;
44
+ }
45
+ catch (err) {
46
+ // rc-9: surface the failure — don't silently swallow.
47
+ console.error('[onboarding-state] Failed to read onboarding state:', err);
48
+ return DEFAULT_STATE;
49
+ }
50
+ }
51
+ /**
52
+ * Set onboarding state for a specific workspace.
53
+ */
54
+ export function setOnboardingState(workspaceId, state) {
55
+ try {
56
+ localStorage.setItem(storageKey(workspaceId), JSON.stringify(state));
57
+ return true;
58
+ }
59
+ catch (err) {
60
+ // rc-9: surface the failure — don't silently swallow.
61
+ console.error('[onboarding-state] Failed to save onboarding state:', err);
62
+ return false;
63
+ }
64
+ }
65
+ /**
66
+ * Reset onboarding state for a specific workspace (Settings page "reset" button).
67
+ */
68
+ export function resetOnboardingState(workspaceId) {
69
+ try {
70
+ localStorage.removeItem(storageKey(workspaceId));
71
+ return true;
72
+ }
73
+ catch (err) {
74
+ console.error('[onboarding-state] Failed to reset onboarding state:', err);
75
+ return false;
76
+ }
77
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * signal-keywords-api — 信号关键词 API 层
3
+ *
4
+ * 调用 OpenClaw 插件的信号关键词管理端点。
5
+ * 功能分阶段交付:
6
+ * - Phase 1:只读(fetch keywords + pending)
7
+ * - Phase 2:读写(update / admit / reject)
8
+ *
9
+ * 当前 Phase 1 实现;写方法为 stub,返回"未实现"错误。
10
+ *
11
+ * ERR entries:
12
+ * - rc-1: 所有响应经 validator 校验
13
+ * - rc-2: 无 `as` bypass
14
+ * - rc-9: 降级/失败路径含 reason
15
+ */
16
+ import type { ApiResponse } from '../../types.js';
17
+ import type { UnifiedKeywordStore, PendingTermStore, UpdateKeywordStoreRequest, AdmitPendingTermRequest, SignalKeyword, PendingSignalTerm } from './signal-keywords-types.js';
18
+ /**
19
+ * 获取所有活跃关键词列表(SignalKeywordsPage 使用)
20
+ *
21
+ * 当前 Phase 1: 端点未实现,返回 stub 错误。
22
+ * Phase 2 需对接 /api/plugins/principles/signal-keywords 端点。
23
+ */
24
+ export declare function listActiveSignalKeywords(_signal?: AbortSignal): Promise<ApiResponse<SignalKeyword[]>>;
25
+ /**
26
+ * 获取待确认信号词列表(SignalKeywordsPage 使用)
27
+ *
28
+ * 当前 Phase 1: 端点未实现,返回 stub 错误。
29
+ * Phase 2 需对接 /api/plugins/principles/signal-keywords/pending 端点。
30
+ */
31
+ export declare function listPendingSignalTerms(_signal?: AbortSignal): Promise<ApiResponse<PendingSignalTerm[]>>;
32
+ /**
33
+ * 获取指定分类的信号词库
34
+ *
35
+ * @param category - 分类(correction | empathy)
36
+ * @param signal - 允许外部中止
37
+ */
38
+ export declare function fetchKeywordStore(category: 'correction' | 'empathy', signal?: AbortSignal): Promise<ApiResponse<UnifiedKeywordStore>>;
39
+ /**
40
+ * 获取 PendingTerm 候选池
41
+ *
42
+ * @param signal - 允许外部中止
43
+ */
44
+ export declare function fetchPendingTerms(signal?: AbortSignal): Promise<ApiResponse<PendingTermStore>>;
45
+ /**
46
+ * 更新信号词库
47
+ *
48
+ * Phase 2 实现,当前返回"未实现"。
49
+ */
50
+ export declare function updateKeywordStore(_req: UpdateKeywordStoreRequest, _signal?: AbortSignal): Promise<ApiResponse<{
51
+ version: number;
52
+ }>>;
53
+ /**
54
+ * 审批一个 PendingTerm(移入词库)
55
+ *
56
+ * Phase 2 实现,当前返回"未实现"。
57
+ */
58
+ export declare function admitPendingTerm(_req: AdmitPendingTermRequest, _signal?: AbortSignal): Promise<ApiResponse<{
59
+ version: number;
60
+ }>>;
61
+ /**
62
+ * 拒绝一个 PendingTerm(从候选池移除)
63
+ *
64
+ * Phase 2 实现,当前返回"未实现"。
65
+ */
66
+ export declare function rejectPendingTerm(_term: string, _signal?: AbortSignal): Promise<ApiResponse<{
67
+ version: number;
68
+ }>>;