principles-disciple 1.8.1 → 1.8.3

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 (508) hide show
  1. package/ADVANCED_CONFIG_ZH.md +97 -0
  2. package/AGENT_INSTALL.md +173 -0
  3. package/AGENT_INSTALL_EN.md +173 -0
  4. package/INSTALL.md +256 -0
  5. package/SKILL.md +63 -0
  6. package/docs/COMMAND_REFERENCE.md +76 -0
  7. package/docs/COMMAND_REFERENCE_EN.md +79 -0
  8. package/esbuild.config.js +75 -0
  9. package/openclaw.plugin.json +4 -4
  10. package/package.json +11 -13
  11. package/scripts/build-web.mjs +46 -0
  12. package/scripts/install-dependencies.cjs +47 -0
  13. package/scripts/sync-plugin.mjs +802 -0
  14. package/scripts/verify-build.mjs +109 -0
  15. package/src/agents/nocturnal-dreamer.md +152 -0
  16. package/src/agents/nocturnal-philosopher.md +138 -0
  17. package/src/agents/nocturnal-reflector.md +126 -0
  18. package/src/agents/nocturnal-scribe.md +164 -0
  19. package/src/commands/capabilities.ts +85 -0
  20. package/{dist/commands/context.js → src/commands/context.ts} +78 -38
  21. package/src/commands/evolution-status.ts +146 -0
  22. package/src/commands/export.ts +111 -0
  23. package/src/commands/focus.ts +533 -0
  24. package/src/commands/nocturnal-review.ts +311 -0
  25. package/src/commands/nocturnal-rollout.ts +763 -0
  26. package/src/commands/nocturnal-train.ts +1002 -0
  27. package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
  28. package/src/commands/principle-rollback.ts +27 -0
  29. package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
  30. package/src/commands/samples.ts +60 -0
  31. package/src/commands/strategy.ts +38 -0
  32. package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
  33. package/src/commands/workflow-debug.ts +128 -0
  34. package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
  35. package/src/config/errors.ts +163 -0
  36. package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
  37. package/src/constants/diagnostician.ts +66 -0
  38. package/src/constants/tools.ts +62 -0
  39. package/src/core/adaptive-thresholds.ts +476 -0
  40. package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
  41. package/{dist/core/config.js → src/core/config.ts} +158 -46
  42. package/src/core/control-ui-db.ts +435 -0
  43. package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
  44. package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
  45. package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
  46. package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
  47. package/src/core/empathy-keyword-matcher.ts +327 -0
  48. package/src/core/empathy-types.ts +218 -0
  49. package/src/core/event-log.ts +544 -0
  50. package/src/core/evolution-engine.ts +612 -0
  51. package/src/core/evolution-logger.ts +353 -0
  52. package/src/core/evolution-migration.ts +77 -0
  53. package/src/core/evolution-reducer.ts +731 -0
  54. package/src/core/evolution-types.ts +456 -0
  55. package/src/core/external-training-contract.ts +527 -0
  56. package/src/core/focus-history.ts +1458 -0
  57. package/src/core/hygiene/tracker.ts +117 -0
  58. package/{dist/core/init.js → src/core/init.ts} +39 -26
  59. package/src/core/local-worker-routing.ts +617 -0
  60. package/{dist/core/migration.js → src/core/migration.ts} +18 -11
  61. package/src/core/model-deployment-registry.ts +722 -0
  62. package/src/core/model-training-registry.ts +813 -0
  63. package/src/core/nocturnal-arbiter.ts +706 -0
  64. package/src/core/nocturnal-candidate-scoring.ts +392 -0
  65. package/src/core/nocturnal-compliance.ts +1075 -0
  66. package/src/core/nocturnal-dataset.ts +668 -0
  67. package/src/core/nocturnal-executability.ts +428 -0
  68. package/src/core/nocturnal-export.ts +390 -0
  69. package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
  70. package/src/core/nocturnal-trajectory-extractor.ts +484 -0
  71. package/src/core/nocturnal-trinity.ts +1384 -0
  72. package/src/core/pain.ts +122 -0
  73. package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
  74. package/{dist/core/paths.js → src/core/paths.ts} +13 -4
  75. package/src/core/principle-training-state.ts +450 -0
  76. package/src/core/profile.ts +226 -0
  77. package/src/core/promotion-gate.ts +822 -0
  78. package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
  79. package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +175 -62
  80. package/src/core/shadow-observation-registry.ts +534 -0
  81. package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
  82. package/src/core/thinking-models.ts +217 -0
  83. package/src/core/training-program.ts +630 -0
  84. package/src/core/trajectory-types.ts +243 -0
  85. package/src/core/trajectory.ts +1673 -0
  86. package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
  87. package/src/hooks/bash-risk.ts +171 -0
  88. package/src/hooks/edit-verification.ts +295 -0
  89. package/src/hooks/gate-block-helper.ts +160 -0
  90. package/src/hooks/gate.ts +210 -0
  91. package/src/hooks/gfi-gate.ts +177 -0
  92. package/src/hooks/lifecycle.ts +326 -0
  93. package/{dist/hooks/llm.js → src/hooks/llm.ts} +160 -80
  94. package/src/hooks/message-sanitize.ts +45 -0
  95. package/src/hooks/pain.ts +384 -0
  96. package/src/hooks/progressive-trust-gate.ts +174 -0
  97. package/src/hooks/prompt.ts +920 -0
  98. package/src/hooks/subagent.ts +207 -0
  99. package/src/hooks/thinking-checkpoint.ts +73 -0
  100. package/src/hooks/trajectory-collector.ts +290 -0
  101. package/src/http/principles-console-route.ts +716 -0
  102. package/src/i18n/commands.ts +117 -0
  103. package/src/index.ts +694 -0
  104. package/src/service/central-database.ts +831 -0
  105. package/src/service/control-ui-query-service.ts +888 -0
  106. package/src/service/evolution-query-service.ts +405 -0
  107. package/src/service/evolution-worker.ts +1646 -0
  108. package/src/service/health-query-service.ts +836 -0
  109. package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +235 -79
  110. package/src/service/nocturnal-service.ts +1015 -0
  111. package/src/service/nocturnal-target-selector.ts +532 -0
  112. package/src/service/phase3-input-filter.ts +237 -0
  113. package/src/service/runtime-summary-service.ts +757 -0
  114. package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
  115. package/{dist/service/subagent-workflow/empathy-observer-workflow-manager.js → src/service/subagent-workflow/empathy-observer-workflow-manager.ts} +240 -117
  116. package/src/service/subagent-workflow/index.ts +51 -0
  117. package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
  118. package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
  119. package/{dist/service/subagent-workflow/types.d.ts → src/service/subagent-workflow/types.ts} +137 -18
  120. package/src/service/subagent-workflow/workflow-store.ts +328 -0
  121. package/src/service/trajectory-service.ts +15 -0
  122. package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
  123. package/src/tools/deep-reflect.ts +349 -0
  124. package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
  125. package/src/types/event-types.ts +453 -0
  126. package/src/types/hygiene-types.ts +31 -0
  127. package/src/types/principle-tree-schema.ts +244 -0
  128. package/src/types/runtime-summary.ts +49 -0
  129. package/src/types.ts +74 -0
  130. package/src/utils/file-lock.ts +391 -0
  131. package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
  132. package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
  133. package/src/utils/io.ts +110 -0
  134. package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
  135. package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
  136. package/src/utils/subagent-probe.ts +94 -0
  137. package/templates/langs/en/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  138. package/templates/langs/en/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  139. package/templates/langs/en/skills/ai-sprint-orchestration/SKILL.md +67 -0
  140. package/templates/langs/en/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  141. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  142. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  143. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  144. package/templates/langs/en/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  145. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  146. package/templates/langs/en/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  147. package/templates/langs/en/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  148. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  149. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  150. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  151. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  152. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  153. package/templates/langs/en/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  154. package/templates/langs/zh/skills/ai-sprint-orchestration/EXAMPLES.md +63 -0
  155. package/templates/langs/zh/skills/ai-sprint-orchestration/REFERENCE.md +136 -0
  156. package/templates/langs/zh/skills/ai-sprint-orchestration/SKILL.md +67 -0
  157. package/templates/langs/zh/skills/ai-sprint-orchestration/references/agent-registry.json +214 -0
  158. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/bugfix-complex-template.json +107 -0
  159. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/feature-complex-template.json +107 -0
  160. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal-verify.json +105 -0
  161. package/templates/langs/zh/skills/ai-sprint-orchestration/references/specs/workflow-validation-minimal.json +108 -0
  162. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1-acceptance-checklist.md +58 -0
  163. package/templates/langs/zh/skills/ai-sprint-orchestration/references/workflow-v1.4-work-unit-handoff.md +190 -0
  164. package/templates/langs/zh/skills/ai-sprint-orchestration/runtime/.gitignore +2 -0
  165. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/archive.mjs +310 -0
  166. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/contract-enforcement.mjs +683 -0
  167. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/decision.mjs +604 -0
  168. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/state-store.mjs +32 -0
  169. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/lib/task-specs.mjs +707 -0
  170. package/templates/langs/zh/skills/ai-sprint-orchestration/scripts/run.mjs +3419 -0
  171. package/templates/langs/zh/skills/ai-sprint-orchestration/test/archive.test.mjs +230 -0
  172. package/templates/langs/zh/skills/ai-sprint-orchestration/test/contract-enforcement.test.mjs +672 -0
  173. package/templates/langs/zh/skills/ai-sprint-orchestration/test/decision.test.mjs +1321 -0
  174. package/templates/langs/zh/skills/ai-sprint-orchestration/test/run.test.mjs +1419 -0
  175. package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
  176. package/templates/pain_settings.json +2 -1
  177. package/tests/README.md +120 -0
  178. package/tests/build-artifacts.test.ts +111 -0
  179. package/tests/commands/evolution-status.test.ts +222 -0
  180. package/tests/commands/evolver.test.ts +22 -0
  181. package/tests/commands/export.test.ts +78 -0
  182. package/tests/commands/nocturnal-review.test.ts +448 -0
  183. package/tests/commands/nocturnal-train.test.ts +97 -0
  184. package/tests/commands/pain.test.ts +108 -0
  185. package/tests/commands/samples.test.ts +65 -0
  186. package/tests/commands/strategy.test.ts +34 -0
  187. package/tests/commands/thinking-os.test.ts +88 -0
  188. package/tests/core/adaptive-thresholds.test.ts +261 -0
  189. package/tests/core/config-service.test.ts +89 -0
  190. package/tests/core/config.test.ts +90 -0
  191. package/tests/core/control-ui-db.test.ts +75 -0
  192. package/tests/core/core-template-guidance.test.ts +21 -0
  193. package/tests/core/detection-funnel.test.ts +63 -0
  194. package/tests/core/detection-service.test.ts +50 -0
  195. package/tests/core/dictionary-service.test.ts +116 -0
  196. package/tests/core/dictionary.test.ts +168 -0
  197. package/tests/core/empathy-keyword-matcher.test.ts +209 -0
  198. package/tests/core/event-log.test.ts +181 -0
  199. package/tests/core/evolution-e2e.test.ts +58 -0
  200. package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
  201. package/tests/core/evolution-engine.test.ts +562 -0
  202. package/tests/core/evolution-logger.test.ts +148 -0
  203. package/tests/core/evolution-migration.test.ts +50 -0
  204. package/tests/core/evolution-paths.test.ts +21 -0
  205. package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
  206. package/tests/core/evolution-reducer.test.ts +180 -0
  207. package/tests/core/evolution-types-loop.test.ts +48 -0
  208. package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
  209. package/tests/core/external-training-contract.test.ts +463 -0
  210. package/tests/core/focus-history.test.ts +682 -0
  211. package/tests/core/init-flatten.test.ts +69 -0
  212. package/tests/core/init-refactor.test.ts +87 -0
  213. package/tests/core/init-v1.3.test.ts +46 -0
  214. package/tests/core/init.test.ts +190 -0
  215. package/tests/core/local-worker-routing.test.ts +757 -0
  216. package/tests/core/migration.test.ts +84 -0
  217. package/tests/core/model-deployment-registry.test.ts +845 -0
  218. package/tests/core/model-training-registry.test.ts +889 -0
  219. package/tests/core/nocturnal-arbiter.test.ts +494 -0
  220. package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
  221. package/tests/core/nocturnal-compliance.test.ts +646 -0
  222. package/tests/core/nocturnal-dataset.test.ts +892 -0
  223. package/tests/core/nocturnal-executability.test.ts +357 -0
  224. package/tests/core/nocturnal-export.test.ts +462 -0
  225. package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
  226. package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
  227. package/tests/core/nocturnal-trinity.test.ts +953 -0
  228. package/tests/core/pain.test.ts +33 -0
  229. package/tests/core/path-resolver.test.ts +57 -0
  230. package/tests/core/paths-refactor.test.ts +42 -0
  231. package/tests/core/phase7-rollout-integration.test.ts +477 -0
  232. package/tests/core/principle-training-state.test.ts +712 -0
  233. package/tests/core/profile.test.ts +56 -0
  234. package/tests/core/promotion-gate.test.ts +556 -0
  235. package/tests/core/risk-calculator.test.ts +168 -0
  236. package/tests/core/session-tracker.test.ts +191 -0
  237. package/tests/core/training-program.test.ts +472 -0
  238. package/tests/core/trajectory.test.ts +265 -0
  239. package/tests/core/workspace-context-factory.test.ts +18 -0
  240. package/tests/core/workspace-context.test.ts +134 -0
  241. package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
  242. package/tests/fixtures/production-compatibility.test.ts +147 -0
  243. package/tests/fixtures/production-mock-generator.ts +282 -0
  244. package/tests/hooks/bash-risk-integration.test.ts +137 -0
  245. package/tests/hooks/bash-risk.test.ts +81 -0
  246. package/tests/hooks/edit-verification.test.ts +678 -0
  247. package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
  248. package/tests/hooks/gate-edit-verification.test.ts +435 -0
  249. package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
  250. package/tests/hooks/gate.test.ts +271 -0
  251. package/tests/hooks/gfi-gate-unit.test.ts +422 -0
  252. package/tests/hooks/gfi-gate.test.ts +669 -0
  253. package/tests/hooks/lifecycle.test.ts +248 -0
  254. package/tests/hooks/llm.test.ts +308 -0
  255. package/tests/hooks/message-sanitize.test.ts +36 -0
  256. package/tests/hooks/pain.test.ts +141 -0
  257. package/tests/hooks/progressive-trust-gate.test.ts +277 -0
  258. package/tests/hooks/prompt.test.ts +1411 -0
  259. package/tests/hooks/subagent.test.ts +467 -0
  260. package/tests/hooks/thinking-gate.test.ts +313 -0
  261. package/tests/http/principles-console-route.test.ts +140 -0
  262. package/tests/hygiene-tracker.test.ts +77 -0
  263. package/tests/index.integration.test.ts +179 -0
  264. package/tests/index.shadow-routing.integration.test.ts +140 -0
  265. package/tests/index.test.ts +9 -0
  266. package/tests/integration/empathy-workflow-integration.test.ts +627 -0
  267. package/tests/service/control-ui-query-service.test.ts +121 -0
  268. package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
  269. package/tests/service/evolution-worker.test.ts +585 -0
  270. package/tests/service/nocturnal-runtime.test.ts +470 -0
  271. package/tests/service/nocturnal-service.test.ts +577 -0
  272. package/tests/service/nocturnal-target-selector.test.ts +615 -0
  273. package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
  274. package/tests/service/phase3-input-filter.test.ts +289 -0
  275. package/tests/service/runtime-summary-service.test.ts +919 -0
  276. package/tests/task-compliance.test.ts +166 -0
  277. package/tests/test-utils.ts +48 -0
  278. package/tests/tools/critique-prompt.test.ts +260 -0
  279. package/tests/tools/deep-reflect.test.ts +232 -0
  280. package/tests/tools/model-index.test.ts +246 -0
  281. package/tests/ui/app.test.tsx +114 -0
  282. package/tests/utils/file-lock.test.ts +407 -0
  283. package/tests/utils/hashing.test.ts +32 -0
  284. package/tests/utils/io.test.ts +39 -0
  285. package/tests/utils/nlp.test.ts +53 -0
  286. package/tests/utils/plugin-logger.test.ts +156 -0
  287. package/tsconfig.json +16 -0
  288. package/tsconfig.tsbuildinfo +1 -0
  289. package/ui/src/App.tsx +45 -0
  290. package/ui/src/api.ts +216 -0
  291. package/ui/src/charts.tsx +586 -0
  292. package/ui/src/components/ErrorState.tsx +6 -0
  293. package/ui/src/components/Loading.tsx +13 -0
  294. package/ui/src/components/ProtectedRoute.tsx +12 -0
  295. package/ui/src/components/Shell.tsx +91 -0
  296. package/ui/src/components/WorkspaceConfig.tsx +146 -0
  297. package/ui/src/components/index.ts +5 -0
  298. package/ui/src/context/auth.tsx +80 -0
  299. package/ui/src/context/theme.tsx +66 -0
  300. package/ui/src/hooks/useAutoRefresh.ts +39 -0
  301. package/ui/src/i18n/ui.ts +363 -0
  302. package/ui/src/main.tsx +16 -0
  303. package/ui/src/pages/EvolutionPage.tsx +352 -0
  304. package/ui/src/pages/FeedbackPage.tsx +140 -0
  305. package/ui/src/pages/GateMonitorPage.tsx +136 -0
  306. package/ui/src/pages/LoginPage.tsx +88 -0
  307. package/ui/src/pages/OverviewPage.tsx +238 -0
  308. package/ui/src/pages/SamplesPage.tsx +174 -0
  309. package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
  310. package/ui/src/styles.css +1661 -0
  311. package/ui/src/types.ts +368 -0
  312. package/ui/src/utils/format.ts +15 -0
  313. package/vitest.config.ts +23 -0
  314. package/dist/commands/capabilities.d.ts +0 -3
  315. package/dist/commands/capabilities.js +0 -73
  316. package/dist/commands/context.d.ts +0 -5
  317. package/dist/commands/evolution-status.d.ts +0 -4
  318. package/dist/commands/evolution-status.js +0 -117
  319. package/dist/commands/evolver.d.ts +0 -9
  320. package/dist/commands/evolver.js +0 -26
  321. package/dist/commands/export.d.ts +0 -2
  322. package/dist/commands/export.js +0 -98
  323. package/dist/commands/focus.d.ts +0 -14
  324. package/dist/commands/focus.js +0 -457
  325. package/dist/commands/nocturnal-review.d.ts +0 -24
  326. package/dist/commands/nocturnal-review.js +0 -265
  327. package/dist/commands/nocturnal-rollout.d.ts +0 -27
  328. package/dist/commands/nocturnal-rollout.js +0 -671
  329. package/dist/commands/nocturnal-train.d.ts +0 -25
  330. package/dist/commands/nocturnal-train.js +0 -919
  331. package/dist/commands/pain.d.ts +0 -5
  332. package/dist/commands/principle-rollback.d.ts +0 -4
  333. package/dist/commands/principle-rollback.js +0 -22
  334. package/dist/commands/rollback.d.ts +0 -19
  335. package/dist/commands/samples.d.ts +0 -2
  336. package/dist/commands/samples.js +0 -55
  337. package/dist/commands/strategy.d.ts +0 -3
  338. package/dist/commands/strategy.js +0 -29
  339. package/dist/commands/thinking-os.d.ts +0 -2
  340. package/dist/config/defaults/runtime.d.ts +0 -40
  341. package/dist/config/errors.d.ts +0 -84
  342. package/dist/config/errors.js +0 -94
  343. package/dist/config/index.js +0 -7
  344. package/dist/constants/diagnostician.d.ts +0 -12
  345. package/dist/constants/diagnostician.js +0 -56
  346. package/dist/constants/tools.d.ts +0 -17
  347. package/dist/constants/tools.js +0 -54
  348. package/dist/core/adaptive-thresholds.d.ts +0 -186
  349. package/dist/core/adaptive-thresholds.js +0 -300
  350. package/dist/core/config-service.d.ts +0 -15
  351. package/dist/core/config.d.ts +0 -129
  352. package/dist/core/control-ui-db.d.ts +0 -95
  353. package/dist/core/control-ui-db.js +0 -292
  354. package/dist/core/detection-funnel.d.ts +0 -33
  355. package/dist/core/detection-service.d.ts +0 -15
  356. package/dist/core/dictionary-service.d.ts +0 -15
  357. package/dist/core/dictionary.d.ts +0 -38
  358. package/dist/core/event-log.d.ts +0 -82
  359. package/dist/core/event-log.js +0 -463
  360. package/dist/core/evolution-engine.d.ts +0 -118
  361. package/dist/core/evolution-engine.js +0 -464
  362. package/dist/core/evolution-logger.d.ts +0 -137
  363. package/dist/core/evolution-logger.js +0 -256
  364. package/dist/core/evolution-migration.d.ts +0 -5
  365. package/dist/core/evolution-migration.js +0 -65
  366. package/dist/core/evolution-reducer.d.ts +0 -98
  367. package/dist/core/evolution-reducer.js +0 -465
  368. package/dist/core/evolution-types.d.ts +0 -287
  369. package/dist/core/evolution-types.js +0 -78
  370. package/dist/core/external-training-contract.d.ts +0 -276
  371. package/dist/core/external-training-contract.js +0 -269
  372. package/dist/core/focus-history.d.ts +0 -210
  373. package/dist/core/focus-history.js +0 -1185
  374. package/dist/core/hygiene/tracker.d.ts +0 -22
  375. package/dist/core/hygiene/tracker.js +0 -106
  376. package/dist/core/init.d.ts +0 -12
  377. package/dist/core/local-worker-routing.d.ts +0 -175
  378. package/dist/core/local-worker-routing.js +0 -525
  379. package/dist/core/migration.d.ts +0 -6
  380. package/dist/core/model-deployment-registry.d.ts +0 -218
  381. package/dist/core/model-deployment-registry.js +0 -503
  382. package/dist/core/model-training-registry.d.ts +0 -295
  383. package/dist/core/model-training-registry.js +0 -475
  384. package/dist/core/nocturnal-arbiter.d.ts +0 -159
  385. package/dist/core/nocturnal-arbiter.js +0 -534
  386. package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
  387. package/dist/core/nocturnal-candidate-scoring.js +0 -266
  388. package/dist/core/nocturnal-compliance.d.ts +0 -175
  389. package/dist/core/nocturnal-compliance.js +0 -824
  390. package/dist/core/nocturnal-dataset.d.ts +0 -224
  391. package/dist/core/nocturnal-dataset.js +0 -443
  392. package/dist/core/nocturnal-executability.d.ts +0 -85
  393. package/dist/core/nocturnal-executability.js +0 -331
  394. package/dist/core/nocturnal-export.d.ts +0 -124
  395. package/dist/core/nocturnal-export.js +0 -275
  396. package/dist/core/nocturnal-paths.d.ts +0 -124
  397. package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
  398. package/dist/core/nocturnal-trajectory-extractor.js +0 -307
  399. package/dist/core/nocturnal-trinity.d.ts +0 -311
  400. package/dist/core/nocturnal-trinity.js +0 -880
  401. package/dist/core/pain.d.ts +0 -4
  402. package/dist/core/pain.js +0 -70
  403. package/dist/core/path-resolver.d.ts +0 -46
  404. package/dist/core/paths.d.ts +0 -65
  405. package/dist/core/principle-training-state.d.ts +0 -121
  406. package/dist/core/principle-training-state.js +0 -321
  407. package/dist/core/profile.d.ts +0 -62
  408. package/dist/core/profile.js +0 -210
  409. package/dist/core/promotion-gate.d.ts +0 -238
  410. package/dist/core/promotion-gate.js +0 -529
  411. package/dist/core/risk-calculator.d.ts +0 -22
  412. package/dist/core/session-tracker.d.ts +0 -101
  413. package/dist/core/shadow-observation-registry.d.ts +0 -217
  414. package/dist/core/shadow-observation-registry.js +0 -308
  415. package/dist/core/system-logger.d.ts +0 -8
  416. package/dist/core/thinking-models.d.ts +0 -38
  417. package/dist/core/thinking-models.js +0 -170
  418. package/dist/core/training-program.d.ts +0 -233
  419. package/dist/core/training-program.js +0 -433
  420. package/dist/core/trajectory.d.ts +0 -411
  421. package/dist/core/trajectory.js +0 -1307
  422. package/dist/core/workspace-context.d.ts +0 -71
  423. package/dist/hooks/bash-risk.d.ts +0 -57
  424. package/dist/hooks/bash-risk.js +0 -137
  425. package/dist/hooks/edit-verification.d.ts +0 -62
  426. package/dist/hooks/edit-verification.js +0 -256
  427. package/dist/hooks/gate-block-helper.d.ts +0 -44
  428. package/dist/hooks/gate-block-helper.js +0 -119
  429. package/dist/hooks/gate.d.ts +0 -24
  430. package/dist/hooks/gate.js +0 -173
  431. package/dist/hooks/gfi-gate.d.ts +0 -40
  432. package/dist/hooks/gfi-gate.js +0 -113
  433. package/dist/hooks/lifecycle.d.ts +0 -5
  434. package/dist/hooks/lifecycle.js +0 -284
  435. package/dist/hooks/llm.d.ts +0 -13
  436. package/dist/hooks/message-sanitize.d.ts +0 -3
  437. package/dist/hooks/message-sanitize.js +0 -37
  438. package/dist/hooks/pain.d.ts +0 -5
  439. package/dist/hooks/pain.js +0 -301
  440. package/dist/hooks/progressive-trust-gate.d.ts +0 -52
  441. package/dist/hooks/progressive-trust-gate.js +0 -134
  442. package/dist/hooks/prompt.d.ts +0 -49
  443. package/dist/hooks/prompt.js +0 -905
  444. package/dist/hooks/subagent.d.ts +0 -10
  445. package/dist/hooks/subagent.js +0 -387
  446. package/dist/hooks/thinking-checkpoint.d.ts +0 -37
  447. package/dist/hooks/thinking-checkpoint.js +0 -51
  448. package/dist/hooks/trajectory-collector.d.ts +0 -32
  449. package/dist/hooks/trajectory-collector.js +0 -256
  450. package/dist/http/principles-console-route.d.ts +0 -9
  451. package/dist/http/principles-console-route.js +0 -681
  452. package/dist/i18n/commands.d.ts +0 -26
  453. package/dist/i18n/commands.js +0 -116
  454. package/dist/index.d.ts +0 -7
  455. package/dist/index.js +0 -581
  456. package/dist/service/central-database.d.ts +0 -104
  457. package/dist/service/central-database.js +0 -649
  458. package/dist/service/control-ui-query-service.d.ts +0 -221
  459. package/dist/service/control-ui-query-service.js +0 -543
  460. package/dist/service/empathy-observer-manager.d.ts +0 -88
  461. package/dist/service/empathy-observer-manager.js +0 -414
  462. package/dist/service/evolution-query-service.d.ts +0 -155
  463. package/dist/service/evolution-query-service.js +0 -258
  464. package/dist/service/evolution-worker.d.ts +0 -101
  465. package/dist/service/evolution-worker.js +0 -975
  466. package/dist/service/health-query-service.d.ts +0 -170
  467. package/dist/service/health-query-service.js +0 -662
  468. package/dist/service/nocturnal-runtime.d.ts +0 -183
  469. package/dist/service/nocturnal-service.d.ts +0 -163
  470. package/dist/service/nocturnal-service.js +0 -787
  471. package/dist/service/nocturnal-target-selector.d.ts +0 -145
  472. package/dist/service/nocturnal-target-selector.js +0 -315
  473. package/dist/service/phase3-input-filter.d.ts +0 -73
  474. package/dist/service/phase3-input-filter.js +0 -172
  475. package/dist/service/runtime-summary-service.d.ts +0 -122
  476. package/dist/service/runtime-summary-service.js +0 -485
  477. package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
  478. package/dist/service/subagent-workflow/index.d.ts +0 -4
  479. package/dist/service/subagent-workflow/index.js +0 -3
  480. package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
  481. package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
  482. package/dist/service/subagent-workflow/types.js +0 -11
  483. package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
  484. package/dist/service/subagent-workflow/workflow-store.js +0 -165
  485. package/dist/service/trajectory-service.d.ts +0 -2
  486. package/dist/service/trajectory-service.js +0 -15
  487. package/dist/tools/critique-prompt.d.ts +0 -14
  488. package/dist/tools/deep-reflect.d.ts +0 -39
  489. package/dist/tools/deep-reflect.js +0 -350
  490. package/dist/tools/model-index.d.ts +0 -9
  491. package/dist/types/event-types.d.ts +0 -306
  492. package/dist/types/event-types.js +0 -106
  493. package/dist/types/hygiene-types.d.ts +0 -20
  494. package/dist/types/hygiene-types.js +0 -12
  495. package/dist/types/runtime-summary.d.ts +0 -47
  496. package/dist/types/runtime-summary.js +0 -1
  497. package/dist/types.d.ts +0 -50
  498. package/dist/types.js +0 -22
  499. package/dist/utils/file-lock.d.ts +0 -71
  500. package/dist/utils/file-lock.js +0 -309
  501. package/dist/utils/glob-match.d.ts +0 -28
  502. package/dist/utils/hashing.d.ts +0 -9
  503. package/dist/utils/io.d.ts +0 -6
  504. package/dist/utils/io.js +0 -106
  505. package/dist/utils/nlp.d.ts +0 -9
  506. package/dist/utils/plugin-logger.d.ts +0 -39
  507. package/dist/utils/subagent-probe.d.ts +0 -34
  508. package/dist/utils/subagent-probe.js +0 -81
@@ -0,0 +1,763 @@
1
+ /**
2
+ * Nocturnal Rollout Command Handler
3
+ * =================================
4
+ *
5
+ * Plugin command handler for nocturnal rollout and promotion operations.
6
+ * Provides commands for:
7
+ * - evaluate-promotion: Evaluate if checkpoint passes promotion gate
8
+ * - advance-promotion: Advance checkpoint promotion state
9
+ * - bind: Bind checkpoint to worker profile
10
+ * - enable-routing: Enable routing for a profile
11
+ * - disable-routing: Disable routing for a profile
12
+ * - rollback: Rollback deployment to previous checkpoint
13
+ * - status: Show deployment status for profiles
14
+ * - show-promotion: Show promotion record for a checkpoint
15
+ *
16
+ * Usage:
17
+ * /nocturnal-rollout evaluate-promotion <checkpointId> [--profile=<profile>]
18
+ * /nocturnal-rollout advance-promotion <checkpointId> [--profile=<profile>] [--review]
19
+ * /nocturnal-rollout bind <checkpointId> --profile=<profile>
20
+ * /nocturnal-rollout enable-routing <profile>
21
+ * /nocturnal-rollout disable-routing <profile>
22
+ * /nocturnal-rollout rollback <profile>
23
+ * /nocturnal-rollout status [--profile=<profile>]
24
+ * /nocturnal-rollout show-promotion <checkpointId>
25
+ */
26
+
27
+ import { WorkspaceContext } from '../core/workspace-context.js';
28
+ import type { PluginCommandContext, PluginCommandResult } from '../openclaw-sdk.js';
29
+ import type { TrainableWorkerProfile } from '../core/external-training-contract.js';
30
+ import {
31
+ evaluatePromotionGate,
32
+ advancePromotion,
33
+ getPromotionRecord,
34
+ listPromotionsByState,
35
+ rejectCheckpoint,
36
+ DEFAULT_BASELINE_METRICS,
37
+ DEFAULT_MIN_DELTA,
38
+ DEFAULT_ALLOWED_MARGIN,
39
+ type PromotionState,
40
+ } from '../core/promotion-gate.js';
41
+ import {
42
+ bindCheckpointToWorkerProfile,
43
+ enableRoutingForProfile,
44
+ disableRoutingForProfile,
45
+ rollbackDeployment,
46
+ getDeployment,
47
+ getDeploymentLineage,
48
+ listDeployments,
49
+ getFullDeploymentRegistry,
50
+ isRoutingEnabledForProfile,
51
+ type WorkerProfile,
52
+ } from '../core/model-deployment-registry.js';
53
+ import {
54
+ classifyTask,
55
+ type RoutingInput,
56
+ } from '../core/local-worker-routing.js';
57
+ import {
58
+ completeShadowObservation,
59
+ completeShadowObservationByTask,
60
+ type ShadowOutcome,
61
+ } from '../core/shadow-observation-registry.js';
62
+ import {
63
+ getCheckpoint,
64
+ listCheckpoints,
65
+ } from '../core/model-training-registry.js';
66
+
67
+ function isZh(ctx: PluginCommandContext): boolean {
68
+ return String(ctx.config?.language || 'en').startsWith('zh');
69
+ }
70
+
71
+ function parseProfile(arg: string | undefined): WorkerProfile {
72
+ if (!arg) return 'local-reader';
73
+ if (arg === 'local-reader' || arg === 'local-editor') {
74
+ return arg;
75
+ }
76
+ return 'local-reader';
77
+ }
78
+
79
+ function formatPromotionState(state: PromotionState, zh: boolean): string {
80
+ const map: Record<PromotionState, { en: string; zh: string }> = {
81
+ rejected: { en: 'Rejected', zh: '已拒绝' },
82
+ candidate_only: { en: 'Candidate Only', zh: '仅候选' },
83
+ shadow_ready: { en: 'Shadow Ready', zh: '待 Shadow' },
84
+ promotable: { en: 'Promotable', zh: '可晋升' },
85
+ };
86
+ return map[state][zh ? 'zh' : 'en'];
87
+ }
88
+
89
+ function formatConstraintCheck(
90
+ check: { constraint: string; actual: number; baseline: number; threshold: number; passed: boolean },
91
+ zh: boolean
92
+ ): string {
93
+ const constraintNames: Record<string, string> = {
94
+ arbiterRejectRate: zh ? 'Arbiter 拒绝率' : 'Arbiter Reject Rate',
95
+ executabilityRejectRate: zh ? '可执行性拒绝率' : 'Executability Reject Rate',
96
+ reviewedSubsetQuality: zh ? '质量分数' : 'Quality Score',
97
+ };
98
+ const name = constraintNames[check.constraint] || check.constraint;
99
+ const icon = check.passed ? (zh ? '✅' : 'PASS') : (zh ? '❌' : 'FAIL');
100
+ return `${icon} ${name}: ${check.actual.toFixed(4)} (baseline: ${check.baseline.toFixed(4)}, threshold: ${check.threshold.toFixed(4)})`;
101
+ }
102
+
103
+ export function handleNocturnalRolloutCommand(ctx: PluginCommandContext): PluginCommandResult {
104
+ const workspaceDir = (ctx.config?.workspaceDir as string) || process.cwd();
105
+ const zh = isZh(ctx);
106
+ const args = (ctx.args || '').trim();
107
+ const parts = args.split(/\s+/).filter(Boolean);
108
+ const [subcommand = 'help'] = parts;
109
+
110
+ // Parse common arguments
111
+ const profileArg = parts.find((p) => p.startsWith('--profile='))?.split('=')[1];
112
+ const checkpointIdArg = parts.find((p) => p.startsWith('--checkpoint-id='))?.split('=')[1];
113
+
114
+ try {
115
+ // ── Help ────────────────────────────────────────────────────────────────
116
+ if (subcommand === 'help' || subcommand === '--help') {
117
+ return {
118
+ text: zh
119
+ ? ` nocturnal-rollout 命令帮助
120
+
121
+ 用法:
122
+ /nocturnal-rollout evaluate-promotion <checkpointId> [--profile=<profile>]
123
+ /nocturnal-rollout advance-promotion <checkpointId> [--profile=<profile>] [--review]
124
+ /nocturnal-rollout bind <checkpointId> --profile=<profile>
125
+ /nocturnal-rollout enable-routing <profile>
126
+ /nocturnal-rollout disable-routing <profile>
127
+ /nocturnal-rollout rollback <profile>
128
+ /nocturnal-rollout status [--profile=<profile>]
129
+ /nocturnal-rollout show-promotion <checkpointId>
130
+
131
+ 说明:
132
+ evaluate-promotion - 评估检查点是否通过晋升门
133
+ advance-promotion - 推进检查点晋升状态 (需要 --review 标志表示人工审核通过)
134
+ bind - 将检查点绑定到工作机配置文件
135
+ enable-routing - 启用配置文件路由
136
+ disable-routing - 禁用配置文件路由
137
+ rollback - 回滚到上一个检查点
138
+ status - 显示所有配置文件部署状态
139
+ show-promotion - 显示检查点晋升记录
140
+
141
+ 配置文件:
142
+ local-reader - 本地阅读器 (Phase 7 首发的唯一配置)
143
+ local-editor - 本地编辑器 (需要显式启用)
144
+
145
+ 阶段状态:
146
+ rejected - 检查点不得路由
147
+ candidate_only - 检查点有效但尚未准备好 shadow
148
+ shadow_ready - 检查点可进入受控 shadow 部署
149
+ promotable - 检查点可替换当前活动检查点
150
+
151
+ 注意事项:
152
+ - 晋升必须经过: 离线 lineage → eval → promotion gate → shadow rollout
153
+ - local-reader 是 Phase 7 唯一允许的 rollout 目标
154
+ - 路由必须在绑定后显式启用`
155
+ : ` nocturnal-rollout command help
156
+
157
+ Usage:
158
+ /nocturnal-rollout evaluate-promotion <checkpointId> [--profile=<profile>]
159
+ /nocturnal-rollout advance-promotion <checkpointId> [--profile=<profile>] [--review]
160
+ /nocturnal-rollout bind <checkpointId> --profile=<profile>
161
+ /nocturnal-rollout enable-routing <profile>
162
+ /nocturnal-rollout disable-routing <profile>
163
+ /nocturnal-rollout rollback <profile>
164
+ /nocturnal-rollout status [--profile=<profile>]
165
+ /nocturnal-rollout show-promotion <checkpointId>
166
+
167
+ Description:
168
+ evaluate-promotion - Evaluate if checkpoint passes promotion gate
169
+ advance-promotion - Advance checkpoint promotion state (requires --review flag for orchestrator review)
170
+ bind - Bind checkpoint to worker profile
171
+ enable-routing - Enable routing for a profile
172
+ disable-routing - Disable routing for a profile
173
+ rollback - Rollback to previous checkpoint
174
+ status - Show deployment status for all profiles
175
+ show-promotion - Show promotion record for a checkpoint
176
+
177
+ Profiles:
178
+ local-reader - Local reader (only allowed profile for Phase 7)
179
+ local-editor - Local editor (requires explicit enablement)
180
+
181
+ Promotion States:
182
+ rejected - Checkpoint must not be routed
183
+ candidate_only - Checkpoint valid but not ready for shadow
184
+ shadow_ready - Checkpoint may enter controlled shadow deployment
185
+ promotable - Checkpoint may replace current active checkpoint
186
+
187
+ Important:
188
+ - Promotion requires: offline lineage → eval → promotion gate → shadow rollout
189
+ - local-reader is the only allowed rollout target for Phase 7
190
+ - Routing must be explicitly enabled after binding`,
191
+ };
192
+ }
193
+
194
+ // ── Evaluate Promotion ────────────────────────────────────────────────
195
+ if (subcommand === 'evaluate-promotion') {
196
+ const checkpointId = parts[1] || checkpointIdArg;
197
+ if (!checkpointId) {
198
+ return { text: zh ? '错误: 需要 checkpointId' : 'Error: checkpointId required' };
199
+ }
200
+
201
+ const profile = parseProfile(profileArg);
202
+ const checkpoint = getCheckpoint(workspaceDir, checkpointId);
203
+
204
+ if (!checkpoint) {
205
+ return { text: zh ? `错误: Checkpoint 未找到: ${checkpointId}` : `Error: Checkpoint not found: ${checkpointId}` };
206
+ }
207
+
208
+ const result = evaluatePromotionGate(workspaceDir, {
209
+ checkpointId,
210
+ targetProfile: profile,
211
+ baselineMetrics: DEFAULT_BASELINE_METRICS,
212
+ minDelta: DEFAULT_MIN_DELTA,
213
+ allowedMargin: DEFAULT_ALLOWED_MARGIN,
214
+ });
215
+
216
+ let text = zh
217
+ ? `=== 晋升门评估 ===
218
+ Checkpoint: ${checkpointId.substring(0, 8)}...
219
+ Profile: ${profile}
220
+ 结果: ${result.passes ? (zh ? '通过' : 'PASS') : (zh ? '未通过' : 'FAIL')}
221
+ 建议状态: ${result.suggestedState ? formatPromotionState(result.suggestedState, zh) : 'N/A'}
222
+
223
+ --- Delta 检查 ---
224
+ ${result.deltaCheck.passed ? (zh ? '✅' : 'PASS') : (zh ? '❌' : 'FAIL')} Delta: ${result.deltaCheck.actual >= 0 ? '+' : ''}${result.deltaCheck.actual.toFixed(4)} (阈值: ${result.deltaCheck.threshold.toFixed(4)})
225
+
226
+ --- 约束检查 ---`
227
+ : `=== Promotion Gate Evaluation ===
228
+ Checkpoint: ${checkpointId.substring(0, 8)}...
229
+ Profile: ${profile}
230
+ Result: ${result.passes ? 'PASS' : 'FAIL'}
231
+ Suggested State: ${result.suggestedState ? formatPromotionState(result.suggestedState, zh) : 'N/A'}
232
+
233
+ --- Delta Check ---
234
+ ${result.deltaCheck.passed ? 'PASS' : 'FAIL'} Delta: ${result.deltaCheck.actual >= 0 ? '+' : ''}${result.deltaCheck.actual.toFixed(4)} (threshold: ${result.deltaCheck.threshold.toFixed(4)})
235
+
236
+ --- Constraint Checks ---`;
237
+
238
+ for (const check of result.constraintChecks) {
239
+ text += `\n${formatConstraintCheck(check, zh)}`;
240
+ }
241
+
242
+ if (result.blockers.length > 0) {
243
+ text += `\n\n--- Blockers ---`;
244
+ for (const blocker of result.blockers) {
245
+ text += `\n - ${blocker}`;
246
+ }
247
+ }
248
+
249
+ text += `\n\n--- 下一步 ---
250
+ ${result.passes
251
+ ? (zh
252
+ ? `1. 推进晋升: /nocturnal-rollout advance-promotion ${checkpointId} --profile=${profile} --review
253
+ 2. 绑定部署: /nocturnal-rollout bind ${checkpointId} --profile=${profile}`
254
+ : `1. Advance promotion: /nocturnal-rollout advance-promotion ${checkpointId} --profile=${profile} --review
255
+ 2. Bind deployment: /nocturnal-rollout bind ${checkpointId} --profile=${profile}`)
256
+ : (zh
257
+ ? `1. 查看 blockers 并修复问题
258
+ 2. 重新运行评估前确保满足所有约束`
259
+ : `1. Review blockers and fix issues
260
+ 2. Ensure all constraints are met before re-evaluation`)}`;
261
+
262
+ return { text };
263
+ }
264
+
265
+ // ── Advance Promotion ─────────────────────────────────────────────────
266
+ if (subcommand === 'advance-promotion') {
267
+ const checkpointId = parts[1] || checkpointIdArg;
268
+ if (!checkpointId) {
269
+ return { text: zh ? '错误: 需要 checkpointId' : 'Error: checkpointId required' };
270
+ }
271
+
272
+ const profile = parseProfile(profileArg);
273
+ const hasReview = args.includes('--review');
274
+ const noteArg = parts.find((p) => p.startsWith('--note='))?.split('=')[1];
275
+
276
+ try {
277
+ const promotion = advancePromotion(workspaceDir, {
278
+ checkpointId,
279
+ targetProfile: profile,
280
+ baselineMetrics: DEFAULT_BASELINE_METRICS,
281
+ orchestratorReviewPassed: hasReview,
282
+ reviewNote: noteArg,
283
+ minDelta: DEFAULT_MIN_DELTA,
284
+ allowedMargin: DEFAULT_ALLOWED_MARGIN,
285
+ });
286
+
287
+ return {
288
+ text: zh
289
+ ? `✅ 晋升状态已更新
290
+ Checkpoint: ${checkpointId.substring(0, 8)}...
291
+ 新状态: ${formatPromotionState(promotion.state, zh)}
292
+ Review: ${promotion.orchestratorReviewPassed ? (zh ? '通过' : 'Passed') : (zh ? '未审核' : 'Not reviewed')}
293
+ Delta: ${promotion.reducedPromptDelta >= 0 ? '+' : ''}${promotion.reducedPromptDelta.toFixed(4)}
294
+
295
+ ${promotion.state === 'shadow_ready'
296
+ ? (zh ? '⚠️ 进入 shadow 部署。请运行 /nocturnal-rollout bind 完成绑定。' : '⚠️ Ready for shadow deployment. Run /nocturnal-rollout bind to complete binding.')
297
+ : promotion.state === 'promotable'
298
+ ? (zh ? '✅ 检查点可晋升到生产环境。' : '✅ Checkpoint is promotable to production.')
299
+ : promotion.state === 'rejected'
300
+ ? (zh ? '❌ 检查点被拒绝。' : '❌ Checkpoint was rejected.')
301
+ : (zh ? '等待进一步审核。' : 'Waiting for further review.')}
302
+ ${promotion.shadowStartedAt ? `Shadow 开始: ${new Date(promotion.shadowStartedAt).toLocaleString()}` : ''}`
303
+ : `✅ Promotion state updated
304
+ Checkpoint: ${checkpointId.substring(0, 8)}...
305
+ New State: ${formatPromotionState(promotion.state, zh)}
306
+ Review: ${promotion.orchestratorReviewPassed ? 'Passed' : 'Not reviewed'}
307
+ Delta: ${promotion.reducedPromptDelta >= 0 ? '+' : ''}${promotion.reducedPromptDelta.toFixed(4)}
308
+
309
+ ${promotion.state === 'shadow_ready'
310
+ ? '⚠️ Ready for shadow deployment. Run /nocturnal-rollout bind to complete binding.'
311
+ : promotion.state === 'promotable'
312
+ ? '✅ Checkpoint is promotable to production.'
313
+ : promotion.state === 'rejected'
314
+ ? '❌ Checkpoint was rejected.'
315
+ : 'Waiting for further review.'}
316
+ ${promotion.shadowStartedAt ? `Shadow started: ${new Date(promotion.shadowStartedAt).toLocaleString()}` : ''}`,
317
+ };
318
+ } catch (err: unknown) {
319
+ return {
320
+ text: zh
321
+ ? `❌ 晋升失败: ${err instanceof Error ? err.message : String(err)}`
322
+ : `❌ Advance promotion failed: ${err instanceof Error ? err.message : String(err)}`,
323
+ };
324
+ }
325
+ }
326
+
327
+ // ── Bind ──────────────────────────────────────────────────────────────
328
+ if (subcommand === 'bind') {
329
+ const checkpointId = parts[1] || checkpointIdArg;
330
+ if (!checkpointId) {
331
+ return { text: zh ? '错误: 需要 checkpointId' : 'Error: checkpointId required' };
332
+ }
333
+
334
+ const profile = parseProfile(profileArg);
335
+ const noteArg = parts.find((p) => p.startsWith('--note='))?.split('=')[1];
336
+
337
+ try {
338
+ const deployment = bindCheckpointToWorkerProfile(workspaceDir, profile, checkpointId, noteArg);
339
+
340
+ return {
341
+ text: zh
342
+ ? `✅ 部署已绑定
343
+ Profile: ${profile}
344
+ Checkpoint: ${checkpointId.substring(0, 8)}...
345
+ Artifact: ${deployment.targetModelFamily}
346
+ 路由启用: ${deployment.routingEnabled ? (zh ? '是' : 'Yes') : (zh ? '否' : 'No')}
347
+
348
+ 下一步:
349
+ 1. 启用路由: /nocturnal-rollout enable-routing ${profile}
350
+ 2. 或保持禁用进行测试`
351
+ : `✅ Deployment bound
352
+ Profile: ${profile}
353
+ Checkpoint: ${checkpointId.substring(0, 8)}...
354
+ Artifact: ${deployment.targetModelFamily}
355
+ Routing Enabled: ${deployment.routingEnabled ? 'Yes' : 'No'}
356
+
357
+ Next steps:
358
+ 1. Enable routing: /nocturnal-rollout enable-routing ${profile}
359
+ 2. Or keep disabled for testing`,
360
+ };
361
+ } catch (err: unknown) {
362
+ return {
363
+ text: zh
364
+ ? `❌ 绑定失败: ${err instanceof Error ? err.message : String(err)}`
365
+ : `❌ Bind failed: ${err instanceof Error ? err.message : String(err)}`,
366
+ };
367
+ }
368
+ }
369
+
370
+ // ── Enable Routing ────────────────────────────────────────────────────
371
+ if (subcommand === 'enable-routing') {
372
+ const profile = parseProfile(profileArg || parts[1]);
373
+
374
+ try {
375
+ const deployment = enableRoutingForProfile(workspaceDir, profile);
376
+
377
+ return {
378
+ text: zh
379
+ ? `✅ 路由已启用
380
+ Profile: ${profile}
381
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
382
+ 路由状态: ${deployment.routingEnabled ? (zh ? '启用' : 'Enabled') : (zh ? '禁用' : 'Disabled')}`
383
+ : `✅ Routing enabled
384
+ Profile: ${profile}
385
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
386
+ Routing: ${deployment.routingEnabled ? 'Enabled' : 'Disabled'}`,
387
+ };
388
+ } catch (err: unknown) {
389
+ return {
390
+ text: zh
391
+ ? `❌ 启用路由失败: ${err instanceof Error ? err.message : String(err)}`
392
+ : `❌ Enable routing failed: ${err instanceof Error ? err.message : String(err)}`,
393
+ };
394
+ }
395
+ }
396
+
397
+ // ── Disable Routing ────────────────────────────────────────────────────
398
+ if (subcommand === 'disable-routing') {
399
+ const profile = parseProfile(profileArg || parts[1]);
400
+
401
+ try {
402
+ const deployment = disableRoutingForProfile(workspaceDir, profile);
403
+
404
+ return {
405
+ text: zh
406
+ ? `✅ 路由已禁用
407
+ Profile: ${profile}
408
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
409
+ 路由状态: ${deployment.routingEnabled ? (zh ? '启用' : 'Enabled') : (zh ? '禁用' : 'Disabled')}
410
+
411
+ 注意: 禁用路由后,该配置文件的流量将返回主代理。`
412
+ : `✅ Routing disabled
413
+ Profile: ${profile}
414
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
415
+ Routing: ${deployment.routingEnabled ? 'Enabled' : 'Disabled'}
416
+
417
+ Note: After disabling routing, traffic for this profile will return to the main agent.`,
418
+ };
419
+ } catch (err: unknown) {
420
+ return {
421
+ text: zh
422
+ ? `❌ 禁用路由失败: ${err instanceof Error ? err.message : String(err)}`
423
+ : `❌ Disable routing failed: ${err instanceof Error ? err.message : String(err)}`,
424
+ };
425
+ }
426
+ }
427
+
428
+ // ── Rollback ──────────────────────────────────────────────────────────
429
+ if (subcommand === 'rollback') {
430
+ const profile = parseProfile(profileArg || parts[1]);
431
+ const noteArg = parts.find((p) => p.startsWith('--note='))?.split('=')[1];
432
+
433
+ try {
434
+ const deployment = rollbackDeployment(workspaceDir, profile, noteArg);
435
+
436
+ return {
437
+ text: zh
438
+ ? `✅ 已回滚
439
+ Profile: ${profile}
440
+ 新 Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
441
+ 上一个 Checkpoint: ${deployment.previousCheckpointId?.substring(0, 8) || 'none'}...
442
+ 路由状态: ${deployment.routingEnabled ? (zh ? '启用' : 'Enabled') : (zh ? '禁用' : 'Disabled')}`
443
+ : `✅ Rolled back
444
+ Profile: ${profile}
445
+ New Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
446
+ Previous Checkpoint: ${deployment.previousCheckpointId?.substring(0, 8) || 'none'}...
447
+ Routing: ${deployment.routingEnabled ? 'Enabled' : 'Disabled'}`,
448
+ };
449
+ } catch (err: unknown) {
450
+ return {
451
+ text: zh
452
+ ? `❌ 回滚失败: ${err instanceof Error ? err.message : String(err)}`
453
+ : `❌ Rollback failed: ${err instanceof Error ? err.message : String(err)}`,
454
+ };
455
+ }
456
+ }
457
+
458
+ // ── Status ─────────────────────────────────────────────────────────────
459
+ if (subcommand === 'status') {
460
+ const profile = profileArg ? parseProfile(profileArg) : undefined;
461
+
462
+ if (profile) {
463
+ const deployment = getDeployment(workspaceDir, profile);
464
+ if (!deployment) {
465
+ return {
466
+ text: zh
467
+ ? `Profile ${profile}: 无部署记录`
468
+ : `Profile ${profile}: No deployment record`,
469
+ };
470
+ }
471
+
472
+ const checkpoint = deployment.activeCheckpointId
473
+ ? getCheckpoint(workspaceDir, deployment.activeCheckpointId)
474
+ : null;
475
+
476
+ const lineage = deployment.activeCheckpointId
477
+ ? getDeploymentLineage(workspaceDir, profile)
478
+ : null;
479
+
480
+ return {
481
+ text: zh
482
+ ? `=== ${profile} 部署状态 ===
483
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
484
+ Deployable: ${checkpoint?.deployable ? (zh ? '是' : 'Yes') : (zh ? '否' : 'No')}
485
+ 路由启用: ${deployment.routingEnabled ? (zh ? '是' : 'Yes') : (zh ? '否' : 'No')}
486
+ 上次更新: ${new Date(deployment.updatedAt).toLocaleString()}
487
+ ${deployment.previousCheckpointId ? `回滚目标: ${deployment.previousCheckpointId.substring(0, 8)}...` : ''}
488
+ ${deployment.note ? `备注: ${deployment.note}` : ''}`
489
+ : `=== ${profile} Deployment Status ===
490
+ Checkpoint: ${deployment.activeCheckpointId?.substring(0, 8) || 'none'}...
491
+ Deployable: ${checkpoint?.deployable ? 'Yes' : 'No'}
492
+ Routing Enabled: ${deployment.routingEnabled ? 'Yes' : 'No'}
493
+ Last Updated: ${new Date(deployment.updatedAt).toLocaleString()}
494
+ ${deployment.previousCheckpointId ? `Rollback target: ${deployment.previousCheckpointId.substring(0, 8)}...` : ''}
495
+ ${deployment.note ? `Note: ${deployment.note}` : ''}`,
496
+ };
497
+ }
498
+
499
+ // Show all profiles
500
+ const profiles: WorkerProfile[] = ['local-reader', 'local-editor'];
501
+ let text = zh ? '=== 部署状态 ===\n' : '=== Deployment Status ===\n';
502
+
503
+ for (const p of profiles) {
504
+ const d = getDeployment(workspaceDir, p);
505
+ const routing = isRoutingEnabledForProfile(workspaceDir, p);
506
+ text += `\n${p}:
507
+ ${d
508
+ ? `Checkpoint: ${d.activeCheckpointId?.substring(0, 8) || 'none'}... | Routing: ${routing ? (zh ? '启用' : 'Enabled') : (zh ? '禁用' : 'Disabled')}`
509
+ : (zh ? ' 无部署记录' : ' No deployment')}`;
510
+ }
511
+
512
+ return { text };
513
+ }
514
+
515
+ // ── Show Promotion ────────────────────────────────────────────────────
516
+ if (subcommand === 'show-promotion') {
517
+ const checkpointId = parts[1] || checkpointIdArg;
518
+ if (!checkpointId) {
519
+ return { text: zh ? '错误: 需要 checkpointId' : 'Error: checkpointId required' };
520
+ }
521
+
522
+ const promotion = getPromotionRecord(workspaceDir, checkpointId);
523
+ if (!promotion) {
524
+ return {
525
+ text: zh
526
+ ? `未找到晋升记录: ${checkpointId}`
527
+ : `No promotion record found: ${checkpointId}`,
528
+ };
529
+ }
530
+
531
+ return {
532
+ text: zh
533
+ ? `=== 晋升记录 ===
534
+ Checkpoint: ${promotion.checkpointId.substring(0, 8)}...
535
+ 状态: ${formatPromotionState(promotion.state, zh)}
536
+ Profile: ${promotion.targetProfile}
537
+ Family: ${promotion.targetModelFamily}
538
+ Delta: ${promotion.reducedPromptDelta >= 0 ? '+' : ''}${promotion.reducedPromptDelta.toFixed(4)}
539
+
540
+ 约束指标:
541
+ Arbiter 拒绝率: ${promotion.constraintMetrics.arbiterRejectRate.toFixed(4)}
542
+ 可执行性拒绝率: ${promotion.constraintMetrics.executabilityRejectRate.toFixed(4)}
543
+ 质量分数: ${promotion.constraintMetrics.reviewedSubsetQuality.toFixed(4)}
544
+
545
+ 基线:
546
+ Arbiter 拒绝率: ${promotion.baselineMetrics.arbiterRejectRate.toFixed(4)}
547
+ 可执行性拒绝率: ${promotion.baselineMetrics.executabilityRejectRate.toFixed(4)}
548
+ 质量分数: ${promotion.baselineMetrics.reviewedSubsetQuality.toFixed(4)}
549
+
550
+ 审核通过: ${promotion.orchestratorReviewPassed ? (zh ? '是' : 'Yes') : (zh ? '否' : 'No')}
551
+ ${promotion.reviewNote ? `审核备注: ${promotion.reviewNote}` : ''}
552
+ 创建: ${new Date(promotion.createdAt).toLocaleString()}
553
+ 状态变更: ${new Date(promotion.stateChangedAt).toLocaleString()}
554
+ ${promotion.shadowStartedAt ? `Shadow 开始: ${new Date(promotion.shadowStartedAt).toLocaleString()}` : ''}
555
+ ${promotion.promotableAt ? `可晋升时间: ${new Date(promotion.promotableAt).toLocaleString()}` : ''}
556
+ ${promotion.previousPromotionId ? `上一个晋升: ${promotion.previousPromotionId.substring(0, 8)}...` : ''}`
557
+ : `=== Promotion Record ===
558
+ Checkpoint: ${promotion.checkpointId.substring(0, 8)}...
559
+ State: ${formatPromotionState(promotion.state, zh)}
560
+ Profile: ${promotion.targetProfile}
561
+ Family: ${promotion.targetModelFamily}
562
+ Delta: ${promotion.reducedPromptDelta >= 0 ? '+' : ''}${promotion.reducedPromptDelta.toFixed(4)}
563
+
564
+ Constraint Metrics:
565
+ Arbiter Reject Rate: ${promotion.constraintMetrics.arbiterRejectRate.toFixed(4)}
566
+ Executability Reject Rate: ${promotion.constraintMetrics.executabilityRejectRate.toFixed(4)}
567
+ Quality Score: ${promotion.constraintMetrics.reviewedSubsetQuality.toFixed(4)}
568
+
569
+ Baseline:
570
+ Arbiter Reject Rate: ${promotion.baselineMetrics.arbiterRejectRate.toFixed(4)}
571
+ Executability Reject Rate: ${promotion.baselineMetrics.executabilityRejectRate.toFixed(4)}
572
+ Quality Score: ${promotion.baselineMetrics.reviewedSubsetQuality.toFixed(4)}
573
+
574
+ Review Passed: ${promotion.orchestratorReviewPassed ? 'Yes' : 'No'}
575
+ ${promotion.reviewNote ? `Review Note: ${promotion.reviewNote}` : ''}
576
+ Created: ${new Date(promotion.createdAt).toLocaleString()}
577
+ State Changed: ${new Date(promotion.stateChangedAt).toLocaleString()}
578
+ ${promotion.shadowStartedAt ? `Shadow Started: ${new Date(promotion.shadowStartedAt).toLocaleString()}` : ''}
579
+ ${promotion.promotableAt ? `Promotable At: ${new Date(promotion.promotableAt).toLocaleString()}` : ''}
580
+ ${promotion.previousPromotionId ? `Previous Promotion: ${promotion.previousPromotionId.substring(0, 8)}...` : ''}`,
581
+ };
582
+ }
583
+
584
+ // ── List by State ─────────────────────────────────────────────────────
585
+ if (subcommand === 'list-by-state') {
586
+ const stateArg = parts[1];
587
+ if (!stateArg) {
588
+ return { text: zh ? '错误: 需要状态参数' : 'Error: state argument required' };
589
+ }
590
+
591
+ const validStates: PromotionState[] = ['rejected', 'candidate_only', 'shadow_ready', 'promotable'];
592
+ if (!validStates.includes(stateArg as PromotionState)) {
593
+ return {
594
+ text: zh
595
+ ? `无效状态: ${stateArg}。有效值: ${validStates.join(', ')}`
596
+ : `Invalid state: ${stateArg}. Valid values: ${validStates.join(', ')}`,
597
+ };
598
+ }
599
+
600
+ const promotions = listPromotionsByState(workspaceDir, stateArg as PromotionState);
601
+ if (promotions.length === 0) {
602
+ return {
603
+ text: zh
604
+ ? `没有 ${stateArg} 状态的检查点`
605
+ : `No checkpoints with state ${stateArg}`,
606
+ };
607
+ }
608
+
609
+ const lines = promotions.map((p) =>
610
+ `${p.checkpointId.substring(0, 8)}... | ${p.targetProfile} | ${p.targetModelFamily} | Delta: ${p.reducedPromptDelta >= 0 ? '+' : ''}${p.reducedPromptDelta.toFixed(4)}`
611
+ );
612
+
613
+ return {
614
+ text: zh
615
+ ? `${stateArg} 检查点 (${promotions.length}):
616
+ ${lines.join('\n')}`
617
+ : `${stateArg} checkpoints (${promotions.length}):
618
+ ${lines.join('\n')}`,
619
+ };
620
+ }
621
+
622
+ // ── Route ───────────────────────────────────────────────────────────────
623
+ // Execute a routing decision for a task. Records shadow observation if routing to shadow.
624
+ if (subcommand === 'route') {
625
+ // Parse routing input arguments
626
+ const intentArg = parts.find((p) => p.startsWith('--intent='))?.slice('--intent='.length) ?? '';
627
+ const descriptionArg = parts.find((p) => p.startsWith('--description='))?.slice('--description='.length) ?? '';
628
+ const toolsArg = parts.find((p) => p.startsWith('--tools='))?.slice('--tools='.length) ?? '';
629
+ const filesArg = parts.find((p) => p.startsWith('--files='))?.slice('--files='.length) ?? '';
630
+ const outputArg = parts.find((p) => p.startsWith('--output='))?.slice('--output='.length) ?? '';
631
+ // Note: --risk= flag is deprecated (risk gating removed from routing)
632
+ const complexityArg = parts.find((p) => p.startsWith('--complexity='))?.slice('--complexity='.length) ?? '';
633
+
634
+ const routingInput: RoutingInput = {
635
+ taskIntent: intentArg || undefined,
636
+ taskDescription: descriptionArg || undefined,
637
+ requestedTools: toolsArg ? toolsArg.split(',').map((t) => t.trim()) : undefined,
638
+ requestedFiles: filesArg ? filesArg.split(',').map((f) => f.trim()) : undefined,
639
+ expectedOutputShape: outputArg || undefined,
640
+ complexityHints: complexityArg ? complexityArg.split(',').map((c) => c.trim()) : undefined,
641
+ targetProfile: parseProfile(profileArg),
642
+ };
643
+
644
+ const decision = classifyTask(routingInput, workspaceDir);
645
+
646
+ const shadowNote = decision.shadowObservationId
647
+ ? `\n\n${zh ? '📝 Shadow 观察已记录' : '📝 Shadow observation recorded'}: ${decision.shadowObservationId}`
648
+ : '';
649
+
650
+ return {
651
+ text: zh
652
+ ? `=== 路由决策 ===
653
+ 决策: ${decision.decision === 'route_local' ? '路由到本地' : '保持在主代理'}
654
+ 目标配置: ${decision.targetProfile ?? 'N/A'}
655
+ 分类: ${decision.classification}
656
+ 原因: ${decision.reason}
657
+ ${decision.blockers.length > 0 ? `阻塞因素:\n${decision.blockers.map((b) => ' - ' + b).join('\n')}` : ''}
658
+ ${decision.activeCheckpointId ? `活动 Checkpoint: ${decision.activeCheckpointId.substring(0, 8)}...` : ''}
659
+ ${decision.activeCheckpointState ? `Checkpoint 状态: ${decision.activeCheckpointState}` : ''}
660
+ ${decision.decision === 'route_local' && decision.activeCheckpointState === 'shadow_ready' ? (zh ? '⚠️ 正在路由到 shadow 检查点' : '⚠️ Routing to shadow checkpoint') : ''}
661
+ ${shadowNote}
662
+
663
+ 下一步:
664
+ ${decision.decision === 'route_local'
665
+ ? (zh ? ' 任务将路由到本地配置文件。任务完成后使用 /nocturnal-rollout complete-shadow 完成 shadow 观察。' : ' Task will be routed to local profile. After task completes, use /nocturnal-rollout complete-shadow to complete the shadow observation.')
666
+ : (zh ? ' 任务必须保留在主代理。' : ' Task must stay on main agent.')}`
667
+ : `=== Routing Decision ===
668
+ Decision: ${decision.decision === 'route_local' ? 'ROUTE_LOCAL' : 'STAY_MAIN'}
669
+ Target Profile: ${decision.targetProfile ?? 'N/A'}
670
+ Classification: ${decision.classification}
671
+ Reason: ${decision.reason}
672
+ ${decision.blockers.length > 0 ? `Blockers:\n${decision.blockers.map((b) => ' - ' + b).join('\n')}` : ''}
673
+ ${decision.activeCheckpointId ? `Active Checkpoint: ${decision.activeCheckpointId.substring(0, 8)}...` : ''}
674
+ ${decision.activeCheckpointState ? `Checkpoint State: ${decision.activeCheckpointState}` : ''}
675
+ ${decision.decision === 'route_local' && decision.activeCheckpointState === 'shadow_ready' ? '⚠️ Routing to shadow checkpoint' : ''}
676
+ ${shadowNote}
677
+
678
+ Next steps:
679
+ ${decision.decision === 'route_local'
680
+ ? ' Task will be routed to local profile. After task completes, use /nocturnal-rollout complete-shadow to complete the shadow observation.'
681
+ : ' Task must stay on main agent.'}`,
682
+ };
683
+ }
684
+
685
+ // ── Complete Shadow Observation ─────────────────────────────────────────
686
+ if (subcommand === 'complete-shadow') {
687
+ const obsIdArg = parts.find((p) => p.startsWith('--observation-id='))?.split('=')[1];
688
+ const fingerprintArg = parts.find((p) => p.startsWith('--fingerprint='))?.split('=')[1];
689
+ const outcomeArg = parts.find((p) => p.startsWith('--outcome='))?.split('=')[1] ?? 'accepted';
690
+ const timedOutArg = parts.includes('--timed-out');
691
+ const threwArg = parts.includes('--threw');
692
+ const invalidArg = parts.includes('--invalid');
693
+ const rejectedArg = parts.includes('--rejected');
694
+
695
+ const validOutcomes: ShadowOutcome[] = ['accepted', 'rejected', 'escalated'];
696
+ const outcome: ShadowOutcome = validOutcomes.includes(outcomeArg as ShadowOutcome)
697
+ ? (outcomeArg as ShadowOutcome)
698
+ : 'accepted';
699
+
700
+ const failureSignals = {
701
+ timedOut: timedOutArg,
702
+ threwException: threwArg,
703
+ invalidOutput: invalidArg,
704
+ profileRejected: rejectedArg,
705
+ extra: {},
706
+ };
707
+
708
+ let observation = null;
709
+
710
+ if (obsIdArg) {
711
+ observation = completeShadowObservation(workspaceDir, {
712
+ observationId: obsIdArg,
713
+ outcome,
714
+ failureSignals,
715
+ });
716
+ } else if (fingerprintArg) {
717
+ // Look up by task fingerprint (recorded during route)
718
+ observation = completeShadowObservationByTask(workspaceDir, fingerprintArg, outcome, failureSignals);
719
+ } else {
720
+ return {
721
+ text: zh
722
+ ? '错误: 需要 --observation-id 或 --fingerprint 参数'
723
+ : 'Error: --observation-id or --fingerprint is required',
724
+ };
725
+ }
726
+
727
+ if (!observation) {
728
+ return {
729
+ text: zh
730
+ ? `未找到 shadow 观察。检查 ID 或指纹是否正确。`
731
+ : `Shadow observation not found. Check the ID or fingerprint.`,
732
+ };
733
+ }
734
+
735
+ return {
736
+ text: zh
737
+ ? `✅ Shadow 观察已完成
738
+ 观察 ID: ${observation.observationId.substring(0, 8)}...
739
+ 结果: ${observation.outcome}
740
+ Checkpoint: ${observation.checkpointId.substring(0, 8)}...
741
+ 完成时间: ${observation.completedAt}`
742
+ : `✅ Shadow observation completed
743
+ Observation ID: ${observation.observationId.substring(0, 8)}...
744
+ Outcome: ${observation.outcome}
745
+ Checkpoint: ${observation.checkpointId.substring(0, 8)}...
746
+ Completed At: ${observation.completedAt}`,
747
+ };
748
+ }
749
+
750
+ // Unknown subcommand
751
+ return {
752
+ text: zh
753
+ ? `未知子命令: ${subcommand}。运行 /nocturnal-rollout help 查看帮助。`
754
+ : `Unknown subcommand: ${subcommand}. Run /nocturnal-rollout help for usage.`,
755
+ };
756
+ } catch (err: unknown) {
757
+ return {
758
+ text: zh
759
+ ? `❌ 命令失败: ${err instanceof Error ? err.message : String(err)}`
760
+ : `❌ Command failed: ${err instanceof Error ? err.message : String(err)}`,
761
+ };
762
+ }
763
+ }