crewly 1.20.193 → 1.20.195

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 (407) hide show
  1. package/config/roles/auditor/prompt.md +2 -2
  2. package/config/roles/orchestrator/fragments/communication.md +1 -1
  3. package/config/roles/orchestrator/prompt.md +15 -505
  4. package/config/skills/agent/computer-use/SKILL.md +6 -0
  5. package/config/skills/agent/core/experiment-card/SKILL.md +101 -0
  6. package/config/skills/agent/core/experiment-card/execute.sh +149 -0
  7. package/config/skills/agent/core/experiment-card/execute.test.sh +97 -0
  8. package/config/skills/agent/desktop-app-control/execute.sh +5 -2
  9. package/config/skills/orchestrator/send-message/execute.sh +19 -2
  10. package/config/skills/orchestrator/send-message/execute.test.sh +80 -0
  11. package/config/skills/registry.json +7 -5
  12. package/config/skills/team-leader/signal-digest/SKILL.md +110 -0
  13. package/config/skills/team-leader/signal-digest/execute.sh +173 -0
  14. package/config/skills/team-leader/signal-digest/execute.test.sh +123 -0
  15. package/config/skills/team-leader/signal-digest/signal-digest.config.example.json +23 -0
  16. package/config/skills/team-leader/signal-digest/signal_digest.py +572 -0
  17. package/config/skills/team-leader/signal-digest/signal_digest.test.py +319 -0
  18. package/dist/backend/backend/src/constants.d.ts +191 -1
  19. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  20. package/dist/backend/backend/src/constants.js +194 -1
  21. package/dist/backend/backend/src/constants.js.map +1 -1
  22. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/chat/chat.controller.js +6 -0
  24. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.d.ts.map +1 -1
  26. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js +3 -1
  27. package/dist/backend/backend/src/controllers/chat-v2/chat-v2.controller.js.map +1 -1
  28. package/dist/backend/backend/src/controllers/experiments/experiments.routes.d.ts +27 -0
  29. package/dist/backend/backend/src/controllers/experiments/experiments.routes.d.ts.map +1 -0
  30. package/dist/backend/backend/src/controllers/experiments/experiments.routes.js +96 -0
  31. package/dist/backend/backend/src/controllers/experiments/experiments.routes.js.map +1 -0
  32. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts +1 -0
  33. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.d.ts.map +1 -1
  34. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js +1 -0
  35. package/dist/backend/backend/src/controllers/marketplace/marketplace.routes.js.map +1 -1
  36. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
  37. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +5 -2
  38. package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
  39. package/dist/backend/backend/src/controllers/request/request.controller.d.ts.map +1 -1
  40. package/dist/backend/backend/src/controllers/request/request.controller.js +5 -1
  41. package/dist/backend/backend/src/controllers/request/request.controller.js.map +1 -1
  42. package/dist/backend/backend/src/controllers/settings/settings.controller.d.ts.map +1 -1
  43. package/dist/backend/backend/src/controllers/settings/settings.controller.js +18 -2
  44. package/dist/backend/backend/src/controllers/settings/settings.controller.js.map +1 -1
  45. package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.d.ts +26 -0
  46. package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.d.ts.map +1 -0
  47. package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.js +100 -0
  48. package/dist/backend/backend/src/controllers/signal-digest/signal-digest.controller.js.map +1 -0
  49. package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts +47 -0
  50. package/dist/backend/backend/src/controllers/trace/trace.controller.d.ts.map +1 -0
  51. package/dist/backend/backend/src/controllers/trace/trace.controller.js +169 -0
  52. package/dist/backend/backend/src/controllers/trace/trace.controller.js.map +1 -0
  53. package/dist/backend/backend/src/index.d.ts.map +1 -1
  54. package/dist/backend/backend/src/index.js +66 -20
  55. package/dist/backend/backend/src/index.js.map +1 -1
  56. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  57. package/dist/backend/backend/src/routes/api.routes.js +14 -0
  58. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  59. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  60. package/dist/backend/backend/src/services/agent/agent-registration.service.js +6 -1
  61. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  62. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
  63. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js +3 -0
  64. package/dist/backend/backend/src/services/agent/auditor-scheduler.service.js.map +1 -1
  65. package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +1 -1
  66. package/dist/backend/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
  67. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts +4 -2
  68. package/dist/backend/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  69. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js +22 -6
  70. package/dist/backend/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  71. package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js +2 -2
  72. package/dist/backend/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
  73. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  74. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
  75. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  76. package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts +6 -0
  77. package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts.map +1 -1
  78. package/dist/backend/backend/src/services/backup/backup-archive.service.js +7 -1
  79. package/dist/backend/backend/src/services/backup/backup-archive.service.js.map +1 -1
  80. package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts +1 -1
  81. package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts.map +1 -1
  82. package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -1
  83. package/dist/backend/backend/src/services/canva/canva-token.service.js +5 -0
  84. package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -1
  85. package/dist/backend/backend/src/services/chat/chat.service.d.ts +78 -2
  86. package/dist/backend/backend/src/services/chat/chat.service.d.ts.map +1 -1
  87. package/dist/backend/backend/src/services/chat/chat.service.js +210 -26
  88. package/dist/backend/backend/src/services/chat/chat.service.js.map +1 -1
  89. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +14 -3
  90. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +28 -4
  92. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  93. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts +4 -3
  94. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js +7 -4
  96. package/dist/backend/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  97. package/dist/backend/backend/src/services/decisions/decision-store.d.ts.map +1 -1
  98. package/dist/backend/backend/src/services/decisions/decision-store.js +5 -1
  99. package/dist/backend/backend/src/services/decisions/decision-store.js.map +1 -1
  100. package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts +10 -1
  101. package/dist/backend/backend/src/services/decisions/decision.wiring.d.ts.map +1 -1
  102. package/dist/backend/backend/src/services/decisions/decision.wiring.js +20 -9
  103. package/dist/backend/backend/src/services/decisions/decision.wiring.js.map +1 -1
  104. package/dist/backend/backend/src/services/experiments/experiment-verdict.d.ts +88 -0
  105. package/dist/backend/backend/src/services/experiments/experiment-verdict.d.ts.map +1 -0
  106. package/dist/backend/backend/src/services/experiments/experiment-verdict.js +226 -0
  107. package/dist/backend/backend/src/services/experiments/experiment-verdict.js.map +1 -0
  108. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts +350 -0
  109. package/dist/backend/backend/src/services/experiments/experiment.service.d.ts.map +1 -0
  110. package/dist/backend/backend/src/services/experiments/experiment.service.js +908 -0
  111. package/dist/backend/backend/src/services/experiments/experiment.service.js.map +1 -0
  112. package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts +88 -0
  113. package/dist/backend/backend/src/services/experiments/experiment.wiring.d.ts.map +1 -0
  114. package/dist/backend/backend/src/services/experiments/experiment.wiring.js +162 -0
  115. package/dist/backend/backend/src/services/experiments/experiment.wiring.js.map +1 -0
  116. package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts +67 -0
  117. package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.d.ts.map +1 -0
  118. package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js +133 -0
  119. package/dist/backend/backend/src/services/experiments/seo-ops-metric.fetcher.js.map +1 -0
  120. package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
  121. package/dist/backend/backend/src/services/google/google-workspace-token.service.js +5 -0
  122. package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
  123. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
  124. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js +7 -0
  125. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
  126. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +11 -3
  127. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  128. package/dist/backend/backend/src/services/messaging/queue-processor.service.js +24 -7
  129. package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  130. package/dist/backend/backend/src/services/microsoft/microsoft-token.service.d.ts.map +1 -1
  131. package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js +5 -0
  132. package/dist/backend/backend/src/services/microsoft/microsoft-token.service.js.map +1 -1
  133. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts +7 -0
  134. package/dist/backend/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  135. package/dist/backend/backend/src/services/monitoring/token-usage.service.js +4 -0
  136. package/dist/backend/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  137. package/dist/backend/backend/src/services/orc/orc-status-router.service.d.ts.map +1 -1
  138. package/dist/backend/backend/src/services/orc/orc-status-router.service.js +12 -3
  139. package/dist/backend/backend/src/services/orc/orc-status-router.service.js.map +1 -1
  140. package/dist/backend/backend/src/services/orc/reply-destination.wiring.d.ts.map +1 -1
  141. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js +16 -0
  142. package/dist/backend/backend/src/services/orc/reply-destination.wiring.js.map +1 -1
  143. package/dist/backend/backend/src/services/people/acting-for.service.d.ts +42 -5
  144. package/dist/backend/backend/src/services/people/acting-for.service.d.ts.map +1 -1
  145. package/dist/backend/backend/src/services/people/acting-for.service.js +80 -5
  146. package/dist/backend/backend/src/services/people/acting-for.service.js.map +1 -1
  147. package/dist/backend/backend/src/services/people/grant-sharing.d.ts +5 -4
  148. package/dist/backend/backend/src/services/people/grant-sharing.d.ts.map +1 -1
  149. package/dist/backend/backend/src/services/people/grant-sharing.js +12 -4
  150. package/dist/backend/backend/src/services/people/grant-sharing.js.map +1 -1
  151. package/dist/backend/backend/src/services/people/people-directory.service.d.ts +71 -13
  152. package/dist/backend/backend/src/services/people/people-directory.service.d.ts.map +1 -1
  153. package/dist/backend/backend/src/services/people/people-directory.service.js +164 -27
  154. package/dist/backend/backend/src/services/people/people-directory.service.js.map +1 -1
  155. package/dist/backend/backend/src/services/project-tickets/project-ticket.service.d.ts.map +1 -1
  156. package/dist/backend/backend/src/services/project-tickets/project-ticket.service.js +2 -0
  157. package/dist/backend/backend/src/services/project-tickets/project-ticket.service.js.map +1 -1
  158. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
  159. package/dist/backend/backend/src/services/reconciler/reconciler.service.js +15 -0
  160. package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
  161. package/dist/backend/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
  162. package/dist/backend/backend/src/services/session/session-handoff.service.js +8 -5
  163. package/dist/backend/backend/src/services/session/session-handoff.service.js.map +1 -1
  164. package/dist/backend/backend/src/services/signal-digest/signal-digest-card.d.ts +75 -0
  165. package/dist/backend/backend/src/services/signal-digest/signal-digest-card.d.ts.map +1 -0
  166. package/dist/backend/backend/src/services/signal-digest/signal-digest-card.js +187 -0
  167. package/dist/backend/backend/src/services/signal-digest/signal-digest-card.js.map +1 -0
  168. package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.d.ts +86 -0
  169. package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.d.ts.map +1 -0
  170. package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.js +307 -0
  171. package/dist/backend/backend/src/services/signal-digest/signal-digest-contract.js.map +1 -0
  172. package/dist/backend/backend/src/services/signal-digest/signal-digest-store.d.ts +85 -0
  173. package/dist/backend/backend/src/services/signal-digest/signal-digest-store.d.ts.map +1 -0
  174. package/dist/backend/backend/src/services/signal-digest/signal-digest-store.js +185 -0
  175. package/dist/backend/backend/src/services/signal-digest/signal-digest-store.js.map +1 -0
  176. package/dist/backend/backend/src/services/signal-digest/signal-digest.service.d.ts +272 -0
  177. package/dist/backend/backend/src/services/signal-digest/signal-digest.service.d.ts.map +1 -0
  178. package/dist/backend/backend/src/services/signal-digest/signal-digest.service.js +570 -0
  179. package/dist/backend/backend/src/services/signal-digest/signal-digest.service.js.map +1 -0
  180. package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.d.ts +51 -0
  181. package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.d.ts.map +1 -0
  182. package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.js +116 -0
  183. package/dist/backend/backend/src/services/signal-digest/signal-digest.wiring.js.map +1 -0
  184. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts +5 -1
  185. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.d.ts.map +1 -1
  186. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js +6 -2
  187. package/dist/backend/backend/src/services/slack/notify-reconciliation.service.js.map +1 -1
  188. package/dist/backend/backend/src/services/slack/slack-bot-ids.d.ts +33 -0
  189. package/dist/backend/backend/src/services/slack/slack-bot-ids.d.ts.map +1 -0
  190. package/dist/backend/backend/src/services/slack/slack-bot-ids.js +56 -0
  191. package/dist/backend/backend/src/services/slack/slack-bot-ids.js.map +1 -0
  192. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +14 -1
  193. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  194. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +30 -10
  195. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  196. package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts +1 -1
  197. package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts.map +1 -1
  198. package/dist/backend/backend/src/services/slack/slack.service.d.ts +31 -1
  199. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  200. package/dist/backend/backend/src/services/slack/slack.service.js +52 -7
  201. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  202. package/dist/backend/backend/src/services/system/auto-update.service.d.ts +2 -2
  203. package/dist/backend/backend/src/services/system/auto-update.service.d.ts.map +1 -1
  204. package/dist/backend/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
  205. package/dist/backend/backend/src/services/task-pool/pool-storage.js +4 -0
  206. package/dist/backend/backend/src/services/task-pool/pool-storage.js.map +1 -1
  207. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  208. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +2 -0
  209. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  210. package/dist/backend/backend/src/services/trace/trace-context.service.d.ts +195 -0
  211. package/dist/backend/backend/src/services/trace/trace-context.service.d.ts.map +1 -0
  212. package/dist/backend/backend/src/services/trace/trace-context.service.js +432 -0
  213. package/dist/backend/backend/src/services/trace/trace-context.service.js.map +1 -0
  214. package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts +42 -0
  215. package/dist/backend/backend/src/services/trace/trace-http.middleware.d.ts.map +1 -0
  216. package/dist/backend/backend/src/services/trace/trace-http.middleware.js +146 -0
  217. package/dist/backend/backend/src/services/trace/trace-http.middleware.js.map +1 -0
  218. package/dist/backend/backend/src/services/trace/trace-markers.d.ts +93 -0
  219. package/dist/backend/backend/src/services/trace/trace-markers.d.ts.map +1 -0
  220. package/dist/backend/backend/src/services/trace/trace-markers.js +162 -0
  221. package/dist/backend/backend/src/services/trace/trace-markers.js.map +1 -0
  222. package/dist/backend/backend/src/services/trace/trace-recorder.d.ts +290 -0
  223. package/dist/backend/backend/src/services/trace/trace-recorder.d.ts.map +1 -0
  224. package/dist/backend/backend/src/services/trace/trace-recorder.js +669 -0
  225. package/dist/backend/backend/src/services/trace/trace-recorder.js.map +1 -0
  226. package/dist/backend/backend/src/services/trace/trace-store.d.ts +269 -0
  227. package/dist/backend/backend/src/services/trace/trace-store.d.ts.map +1 -0
  228. package/dist/backend/backend/src/services/trace/trace-store.js +602 -0
  229. package/dist/backend/backend/src/services/trace/trace-store.js.map +1 -0
  230. package/dist/backend/backend/src/services/trace/trace.types.d.ts +118 -0
  231. package/dist/backend/backend/src/services/trace/trace.types.d.ts.map +1 -0
  232. package/dist/backend/backend/src/services/trace/trace.types.js +85 -0
  233. package/dist/backend/backend/src/services/trace/trace.types.js.map +1 -0
  234. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts +1 -1
  235. package/dist/backend/backend/src/services/v3/owner-receipt/owner-receipt.boot.d.ts.map +1 -1
  236. package/dist/backend/backend/src/services/v3/request.service.d.ts.map +1 -1
  237. package/dist/backend/backend/src/services/v3/request.service.js +4 -0
  238. package/dist/backend/backend/src/services/v3/request.service.js.map +1 -1
  239. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.d.ts.map +1 -1
  240. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js +22 -2
  241. package/dist/backend/backend/src/services/v3/workitem-dispatch.subscriber.js.map +1 -1
  242. package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts +3 -1
  243. package/dist/backend/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
  244. package/dist/backend/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
  245. package/dist/backend/backend/src/services/workflow/message-scheduler.service.d.ts.map +1 -1
  246. package/dist/backend/backend/src/services/workflow/message-scheduler.service.js +3 -0
  247. package/dist/backend/backend/src/services/workflow/message-scheduler.service.js.map +1 -1
  248. package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
  249. package/dist/backend/backend/src/services/workflow/scheduler.service.js +3 -0
  250. package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
  251. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts +3 -0
  252. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.d.ts.map +1 -1
  253. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js +7 -0
  254. package/dist/backend/backend/src/services/worktree/worktree-janitor.service.js.map +1 -1
  255. package/dist/backend/backend/src/types/experiment.types.d.ts +155 -0
  256. package/dist/backend/backend/src/types/experiment.types.d.ts.map +1 -0
  257. package/dist/backend/backend/src/types/experiment.types.js +32 -0
  258. package/dist/backend/backend/src/types/experiment.types.js.map +1 -0
  259. package/dist/backend/backend/src/types/messaging.types.d.ts +6 -0
  260. package/dist/backend/backend/src/types/messaging.types.d.ts.map +1 -1
  261. package/dist/backend/backend/src/types/messaging.types.js.map +1 -1
  262. package/dist/backend/backend/src/types/signal-digest.types.d.ts +185 -0
  263. package/dist/backend/backend/src/types/signal-digest.types.d.ts.map +1 -0
  264. package/dist/backend/backend/src/types/signal-digest.types.js +21 -0
  265. package/dist/backend/backend/src/types/signal-digest.types.js.map +1 -0
  266. package/dist/backend/backend/src/types/v2/request.types.d.ts +4 -0
  267. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  268. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  269. package/dist/backend/backend/src/types/v2/work-item.types.d.ts +4 -0
  270. package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  271. package/dist/backend/backend/src/types/v2/work-item.types.js +1 -0
  272. package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
  273. package/dist/backend/backend/src/utils/security.d.ts +2 -0
  274. package/dist/backend/backend/src/utils/security.d.ts.map +1 -1
  275. package/dist/backend/backend/src/utils/security.js +3 -1
  276. package/dist/backend/backend/src/utils/security.js.map +1 -1
  277. package/dist/backend/backend/src/websocket/chat.gateway.d.ts +9 -0
  278. package/dist/backend/backend/src/websocket/chat.gateway.d.ts.map +1 -1
  279. package/dist/backend/backend/src/websocket/chat.gateway.js +26 -0
  280. package/dist/backend/backend/src/websocket/chat.gateway.js.map +1 -1
  281. package/dist/backend/build-info.json +2 -2
  282. package/dist/cli/backend/src/constants.d.ts +191 -1
  283. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  284. package/dist/cli/backend/src/constants.js +194 -1
  285. package/dist/cli/backend/src/constants.js.map +1 -1
  286. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  287. package/dist/cli/backend/src/services/agent/agent-registration.service.js +6 -1
  288. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  289. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.d.ts.map +1 -1
  290. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js +3 -0
  291. package/dist/cli/backend/src/services/agent/auditor-scheduler.service.js.map +1 -1
  292. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts +1 -1
  293. package/dist/cli/backend/src/services/agent/oauth-relogin-monitor.service.d.ts.map +1 -1
  294. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts +4 -2
  295. package/dist/cli/backend/src/services/agent/runtime-session-recovery.d.ts.map +1 -1
  296. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js +22 -6
  297. package/dist/cli/backend/src/services/agent/runtime-session-recovery.js.map +1 -1
  298. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js +2 -2
  299. package/dist/cli/backend/src/services/ai/prompt-modules/communication.module.js.map +1 -1
  300. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  301. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -0
  302. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  303. package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts +6 -0
  304. package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts.map +1 -1
  305. package/dist/cli/backend/src/services/backup/backup-archive.service.js +7 -1
  306. package/dist/cli/backend/src/services/backup/backup-archive.service.js.map +1 -1
  307. package/dist/cli/backend/src/services/chat/chat.service.d.ts +185 -0
  308. package/dist/cli/backend/src/services/chat/chat.service.d.ts.map +1 -0
  309. package/dist/cli/backend/src/services/chat/chat.service.js +558 -0
  310. package/dist/cli/backend/src/services/chat/chat.service.js.map +1 -0
  311. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +14 -3
  312. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
  313. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +28 -4
  314. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  315. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts +4 -3
  316. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.d.ts.map +1 -1
  317. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js +7 -4
  318. package/dist/cli/backend/src/services/chat-v2/chat-v2.service.js.map +1 -1
  319. package/dist/cli/backend/src/services/decisions/decision-store.d.ts.map +1 -1
  320. package/dist/cli/backend/src/services/decisions/decision-store.js +5 -1
  321. package/dist/cli/backend/src/services/decisions/decision-store.js.map +1 -1
  322. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.d.ts.map +1 -1
  323. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js +7 -0
  324. package/dist/cli/backend/src/services/messaging/owner-message-watchdog.service.js.map +1 -1
  325. package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts +11 -3
  326. package/dist/cli/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  327. package/dist/cli/backend/src/services/messaging/queue-processor.service.js +24 -7
  328. package/dist/cli/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  329. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts +7 -0
  330. package/dist/cli/backend/src/services/monitoring/token-usage.service.d.ts.map +1 -1
  331. package/dist/cli/backend/src/services/monitoring/token-usage.service.js +4 -0
  332. package/dist/cli/backend/src/services/monitoring/token-usage.service.js.map +1 -1
  333. package/dist/cli/backend/src/services/people/acting-for.service.d.ts +42 -5
  334. package/dist/cli/backend/src/services/people/acting-for.service.d.ts.map +1 -1
  335. package/dist/cli/backend/src/services/people/acting-for.service.js +80 -5
  336. package/dist/cli/backend/src/services/people/acting-for.service.js.map +1 -1
  337. package/dist/cli/backend/src/services/people/people-directory.service.d.ts +71 -13
  338. package/dist/cli/backend/src/services/people/people-directory.service.d.ts.map +1 -1
  339. package/dist/cli/backend/src/services/people/people-directory.service.js +164 -27
  340. package/dist/cli/backend/src/services/people/people-directory.service.js.map +1 -1
  341. package/dist/cli/backend/src/services/project-tickets/project-ticket.service.d.ts.map +1 -1
  342. package/dist/cli/backend/src/services/project-tickets/project-ticket.service.js +2 -0
  343. package/dist/cli/backend/src/services/project-tickets/project-ticket.service.js.map +1 -1
  344. package/dist/cli/backend/src/services/session/session-handoff.service.d.ts.map +1 -1
  345. package/dist/cli/backend/src/services/session/session-handoff.service.js +8 -5
  346. package/dist/cli/backend/src/services/session/session-handoff.service.js.map +1 -1
  347. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +14 -1
  348. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  349. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +30 -10
  350. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  351. package/dist/cli/backend/src/services/slack/slack.service.d.ts +31 -1
  352. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  353. package/dist/cli/backend/src/services/slack/slack.service.js +52 -7
  354. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  355. package/dist/cli/backend/src/services/task-pool/pool-storage.d.ts.map +1 -1
  356. package/dist/cli/backend/src/services/task-pool/pool-storage.js +4 -0
  357. package/dist/cli/backend/src/services/task-pool/pool-storage.js.map +1 -1
  358. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  359. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +2 -0
  360. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  361. package/dist/cli/backend/src/services/trace/trace-context.service.d.ts +195 -0
  362. package/dist/cli/backend/src/services/trace/trace-context.service.d.ts.map +1 -0
  363. package/dist/cli/backend/src/services/trace/trace-context.service.js +432 -0
  364. package/dist/cli/backend/src/services/trace/trace-context.service.js.map +1 -0
  365. package/dist/cli/backend/src/services/trace/trace-markers.d.ts +93 -0
  366. package/dist/cli/backend/src/services/trace/trace-markers.d.ts.map +1 -0
  367. package/dist/cli/backend/src/services/trace/trace-markers.js +162 -0
  368. package/dist/cli/backend/src/services/trace/trace-markers.js.map +1 -0
  369. package/dist/cli/backend/src/services/trace/trace-recorder.d.ts +290 -0
  370. package/dist/cli/backend/src/services/trace/trace-recorder.d.ts.map +1 -0
  371. package/dist/cli/backend/src/services/trace/trace-recorder.js +669 -0
  372. package/dist/cli/backend/src/services/trace/trace-recorder.js.map +1 -0
  373. package/dist/cli/backend/src/services/trace/trace-store.d.ts +269 -0
  374. package/dist/cli/backend/src/services/trace/trace-store.d.ts.map +1 -0
  375. package/dist/cli/backend/src/services/trace/trace-store.js +602 -0
  376. package/dist/cli/backend/src/services/trace/trace-store.js.map +1 -0
  377. package/dist/cli/backend/src/services/trace/trace.types.d.ts +118 -0
  378. package/dist/cli/backend/src/services/trace/trace.types.d.ts.map +1 -0
  379. package/dist/cli/backend/src/services/trace/trace.types.js +85 -0
  380. package/dist/cli/backend/src/services/trace/trace.types.js.map +1 -0
  381. package/dist/cli/backend/src/services/v3/request.service.d.ts.map +1 -1
  382. package/dist/cli/backend/src/services/v3/request.service.js +4 -0
  383. package/dist/cli/backend/src/services/v3/request.service.js.map +1 -1
  384. package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts +3 -1
  385. package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -1
  386. package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js.map +1 -1
  387. package/dist/cli/backend/src/types/messaging.types.d.ts +6 -0
  388. package/dist/cli/backend/src/types/messaging.types.d.ts.map +1 -1
  389. package/dist/cli/backend/src/types/messaging.types.js.map +1 -1
  390. package/dist/cli/backend/src/types/v2/request.types.d.ts +4 -0
  391. package/dist/cli/backend/src/types/v2/request.types.d.ts.map +1 -1
  392. package/dist/cli/backend/src/types/v2/request.types.js.map +1 -1
  393. package/dist/cli/backend/src/types/v2/work-item.types.d.ts +4 -0
  394. package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
  395. package/dist/cli/backend/src/types/v2/work-item.types.js +1 -0
  396. package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
  397. package/dist/cli/backend/src/utils/security.d.ts +196 -0
  398. package/dist/cli/backend/src/utils/security.d.ts.map +1 -0
  399. package/dist/cli/backend/src/utils/security.js +538 -0
  400. package/dist/cli/backend/src/utils/security.js.map +1 -0
  401. package/dist/cli/backend/src/websocket/chat.gateway.d.ts +9 -0
  402. package/dist/cli/backend/src/websocket/chat.gateway.d.ts.map +1 -1
  403. package/dist/cli/backend/src/websocket/chat.gateway.js +26 -0
  404. package/dist/cli/backend/src/websocket/chat.gateway.js.map +1 -1
  405. package/frontend/dist/assets/{index-465d1f8f.js → index-800118ca.js} +274 -274
  406. package/frontend/dist/index.html +1 -1
  407. package/package.json +1 -1
@@ -0,0 +1,187 @@
1
+ /**
2
+ * The signal digest card (#987, specs/2026-10-03-signal-digest.md §3): one
3
+ * Slack message, one section per action with its own Do / Skip buttons.
4
+ * Pure: same digest, same blocks.
5
+ *
6
+ * ```
7
+ * [header] Daily signals · visa.careerengine.us
8
+ * [context] Owen · Fri 10/2 · Do opens an experiment ticket · SD-3
9
+ * [context] Sources: GA4 ✓ · Search Console ✗ HTTP 403 · Inbox — not set up
10
+ * [section] *1. Rewrite the /h1b-fee title*
11
+ * Signal: 'h1b visa fee' ranks #2 with 4% CTR on 900 impressions
12
+ * Expected: about +70 clicks a week · Effort: S — 1 h
13
+ * [actions] [Do] [Skip] (or, once answered: ✔ Do → CE-12)
14
+ * …
15
+ * ```
16
+ *
17
+ * @module services/signal-digest/signal-digest-card
18
+ */
19
+ import { SIGNAL_DIGEST_CONSTANTS } from '../../constants.js';
20
+ import { isSignalChoice } from '../../types/signal-digest.types.js';
21
+ const WEEKDAY_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
22
+ /**
23
+ * Escape the characters Slack reserves in mrkdwn.
24
+ *
25
+ * @param text - Plain text
26
+ * @returns Safe mrkdwn
27
+ */
28
+ export function escapeMrkdwn(text) {
29
+ return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
30
+ }
31
+ /**
32
+ * Button value JSON.
33
+ *
34
+ * @param digestId - Digest id
35
+ * @param n - Item number
36
+ * @param choice - do / skip
37
+ * @param instanceId - This instance (Cloud routes the click by it)
38
+ * @returns JSON string
39
+ */
40
+ export function signalButtonValue(digestId, n, choice, instanceId) {
41
+ const v = { s: digestId, n, o: choice, i: instanceId };
42
+ return JSON.stringify(v);
43
+ }
44
+ /**
45
+ * Parse a digest button value.
46
+ *
47
+ * @param raw - `value` of the clicked button
48
+ * @returns The value, or null when it is not a digest button
49
+ */
50
+ export function parseSignalButtonValue(raw) {
51
+ if (typeof raw !== 'string' || !raw.startsWith('{'))
52
+ return null;
53
+ try {
54
+ const v = JSON.parse(raw);
55
+ if (typeof v.s !== 'string' || typeof v.n !== 'number' || !Number.isInteger(v.n) || !isSignalChoice(v.o))
56
+ return null;
57
+ return { s: v.s, n: v.n, o: v.o, i: typeof v.i === 'string' ? v.i : '' };
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ /**
64
+ * The line an answered (or expired) action shows instead of its buttons.
65
+ *
66
+ * @param item - Item
67
+ * @returns mrkdwn line, or null while open
68
+ */
69
+ export function itemOutcomeLine(item) {
70
+ switch (item.status) {
71
+ case 'do':
72
+ if (item.ticketId)
73
+ return `✔ Do → ${escapeMrkdwn(item.ticketId)}${item.experimentId ? ` · ${escapeMrkdwn(item.experimentId)}` : ''}`;
74
+ return `✔ Do — no ticket: ${escapeMrkdwn(item.ticketError ?? 'not created')}`;
75
+ case 'skip':
76
+ return '⤼ Skipped';
77
+ case 'expired':
78
+ return 'No answer — replaced by a newer digest';
79
+ default:
80
+ return null;
81
+ }
82
+ }
83
+ /**
84
+ * The card's source line: what the run could and could not examine.
85
+ *
86
+ * @param sources - Statuses
87
+ * @returns mrkdwn line, or null when there are none
88
+ */
89
+ export function sourcesLine(sources) {
90
+ if (!sources || sources.length === 0)
91
+ return null;
92
+ const parts = sources.map((s) => {
93
+ const label = escapeMrkdwn(SIGNAL_DIGEST_CONSTANTS.SOURCE_LABELS[s.name] ?? s.name);
94
+ if (s.state === 'ok')
95
+ return `${label} ✓`;
96
+ if (s.state === 'not_configured')
97
+ return `${label} — not set up`;
98
+ return `${label} ✗ ${escapeMrkdwn((s.detail ?? 'failed').slice(0, 80))}`;
99
+ });
100
+ return `Sources: ${parts.join(' · ')}`;
101
+ }
102
+ /**
103
+ * `Fri 10/2` for an instant, in the machine's zone.
104
+ *
105
+ * @param iso - Instant
106
+ * @returns Date label
107
+ */
108
+ function dateLabel(iso) {
109
+ const d = new Date(iso);
110
+ return `${WEEKDAY_SHORT[d.getDay()]} ${d.getMonth() + 1}/${d.getDate()}`;
111
+ }
112
+ /**
113
+ * The card's blocks.
114
+ *
115
+ * @param digest - Digest
116
+ * @param instanceId - This instance id (button values)
117
+ * @param askerName - Team lead's display name, when known
118
+ * @returns Blocks
119
+ */
120
+ export function renderDigestCard(digest, instanceId, askerName) {
121
+ const blocks = [
122
+ { type: 'header', text: { type: 'plain_text', text: `Daily signals · ${digest.site}`.slice(0, 150), emoji: true } },
123
+ {
124
+ type: 'context',
125
+ elements: [
126
+ {
127
+ type: 'mrkdwn',
128
+ text: [askerName ? escapeMrkdwn(askerName) : null, dateLabel(digest.createdAt), 'Do opens an experiment ticket · Skip keeps it off the list for 30 days', digest.id]
129
+ .filter(Boolean)
130
+ .join(' · '),
131
+ },
132
+ ],
133
+ },
134
+ ];
135
+ const sources = sourcesLine(digest.sources);
136
+ if (sources)
137
+ blocks.push({ type: 'context', elements: [{ type: 'mrkdwn', text: sources }] });
138
+ for (const item of digest.items) {
139
+ blocks.push({
140
+ type: 'section',
141
+ text: {
142
+ type: 'mrkdwn',
143
+ text: [
144
+ `*${item.n}. ${escapeMrkdwn(item.proposal)}*`,
145
+ `Signal: ${escapeMrkdwn(item.signal)}`,
146
+ `Expected: ${escapeMrkdwn(item.expectedEffect)} · Effort: ${escapeMrkdwn(item.effort)}`,
147
+ ].join('\n'),
148
+ },
149
+ });
150
+ const outcome = itemOutcomeLine(item);
151
+ if (outcome) {
152
+ blocks.push({ type: 'context', elements: [{ type: 'mrkdwn', text: outcome }] });
153
+ continue;
154
+ }
155
+ blocks.push({
156
+ type: 'actions',
157
+ block_id: `signal:${digest.id}:${item.n}`,
158
+ elements: [
159
+ {
160
+ type: 'button',
161
+ action_id: `${SIGNAL_DIGEST_CONSTANTS.ACTION_PREFIX}${item.n}:do`,
162
+ text: { type: 'plain_text', text: 'Do', emoji: true },
163
+ style: 'primary',
164
+ value: signalButtonValue(digest.id, item.n, 'do', instanceId),
165
+ },
166
+ {
167
+ type: 'button',
168
+ action_id: `${SIGNAL_DIGEST_CONSTANTS.ACTION_PREFIX}${item.n}:skip`,
169
+ text: { type: 'plain_text', text: 'Skip', emoji: true },
170
+ value: signalButtonValue(digest.id, item.n, 'skip', instanceId),
171
+ },
172
+ ],
173
+ });
174
+ }
175
+ return blocks;
176
+ }
177
+ /**
178
+ * Notification text of the card (shown in the push / when blocks fail).
179
+ *
180
+ * @param digest - Digest
181
+ * @returns Plain text
182
+ */
183
+ export function digestFallbackText(digest) {
184
+ const open = digest.items.filter((i) => i.status === 'open').length;
185
+ return `Daily signals · ${digest.site}: ${digest.items.length} actions${open < digest.items.length ? ` (${open} waiting)` : ''}`;
186
+ }
187
+ //# sourceMappingURL=signal-digest-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-digest-card.js","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-card.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * The signal digest contract (#987, specs/2026-10-03-signal-digest.md §2):
3
+ * validate a team lead's proposal and work out which actions the site's
4
+ * history blocks. Pure.
5
+ *
6
+ * Every rejection says what to fix, because the reader is an agent that will
7
+ * retry with whatever the error tells it.
8
+ *
9
+ * @module services/signal-digest/signal-digest-contract
10
+ */
11
+ import type { CreateSignalDigestInput, SignalActionInput, SignalDigest, SignalHistoryEntry, SignalSourceStatus } from '../../types/signal-digest.types.js';
12
+ /** A rejected proposal. */
13
+ export declare class SignalDigestError extends Error {
14
+ readonly status: number;
15
+ /**
16
+ * @param status - HTTP status to answer with
17
+ * @param message - What to fix
18
+ */
19
+ constructor(status: number, message: string);
20
+ }
21
+ /** Appended to contract errors. */
22
+ export declare const SIGNAL_DIGEST_EXAMPLE = "Example item: {\"key\":\"gsc:low-ctr:h1b visa fee\",\"source\":\"gsc\",\"signal\":\"'h1b visa fee' ranks #2 with 4% CTR on 900 impressions (7 d)\",\"proposal\":\"Rewrite the title and description of /h1b-fee to answer the fee question\",\"expectedEffect\":\"CTR 4% \u2192 ~12%: about +70 clicks a week\",\"effort\":\"S \u2014 1 h\",\"metric\":\"GSC clicks for 'h1b visa fee'\"}";
23
+ /** A validated proposal. */
24
+ export interface ValidatedSignalDigest {
25
+ site: string;
26
+ project?: string;
27
+ config?: string;
28
+ items: SignalActionInput[];
29
+ /** Source statuses, when the proposal carries them */
30
+ sources?: SignalSourceStatus[];
31
+ }
32
+ /**
33
+ * Normalised identity of an action key (case and spacing do not matter).
34
+ *
35
+ * @param key - Key as sent
36
+ * @returns Comparable key
37
+ */
38
+ export declare function normalizeKey(key: string): string;
39
+ /**
40
+ * Source statuses as `collect` prints them (`{"ga4":"ok","gsc":"error: HTTP 403"}`)
41
+ * or as a list of `{name, state, detail?}`.
42
+ *
43
+ * @param raw - Body field
44
+ * @returns Statuses (sorted by name), or undefined when absent
45
+ * @throws SignalDigestError(400)
46
+ */
47
+ export declare function parseSourceStatuses(raw: unknown): SignalSourceStatus[] | undefined;
48
+ /**
49
+ * Validate a proposal: a site, an optional project, and 3–5 distinct actions,
50
+ * each with key, source, signal, proposal, expected effect and effort.
51
+ *
52
+ * @param input - Request body
53
+ * @returns The proposal
54
+ * @throws SignalDigestError(400) naming what to fix
55
+ */
56
+ export declare function validateSignalDigest(input: CreateSignalDigestInput): ValidatedSignalDigest;
57
+ /**
58
+ * Validate a site name.
59
+ *
60
+ * @param raw - Body field
61
+ * @returns The site
62
+ * @throws SignalDigestError(400)
63
+ */
64
+ export declare function validateSite(raw: unknown): string;
65
+ /**
66
+ * The keys a site's history blocks right now, newest first per key:
67
+ * - a Do blocks its key for {@link SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS} (it was tried);
68
+ * - a Skip blocks it for {@link SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS};
69
+ * - an open item blocks it while it is open.
70
+ * Expired items (replaced unanswered) block nothing.
71
+ *
72
+ * @param digests - All stored digests
73
+ * @param site - Site
74
+ * @param now - Clock
75
+ * @returns Blocked entries, one per key
76
+ */
77
+ export declare function siteHistory(digests: readonly SignalDigest[], site: string, now: Date): SignalHistoryEntry[];
78
+ /**
79
+ * Explain which proposed actions the history blocks.
80
+ *
81
+ * @param items - Proposed actions
82
+ * @param history - {@link siteHistory} of the site
83
+ * @returns One line per blocked action (empty when none)
84
+ */
85
+ export declare function blockedLines(items: readonly SignalActionInput[], history: readonly SignalHistoryEntry[]): string[];
86
+ //# sourceMappingURL=signal-digest-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-digest-contract.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,YAAY,EAEZ,kBAAkB,EAGlB,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAE5C,2BAA2B;AAC3B,qBAAa,iBAAkB,SAAQ,KAAK;IAMxC,QAAQ,CAAC,MAAM,EAAE,MAAM;IALzB;;;OAGG;gBAEQ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM;CAKlB;AAED,mCAAmC;AACnC,eAAO,MAAM,qBAAqB,8XACyT,CAAC;AAE5V,4BAA4B;AAC5B,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,sDAAsD;IACtD,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAChC;AAYD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAmFD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,EAAE,GAAG,SAAS,CAelF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,uBAAuB,GAAG,qBAAqB,CA4C1F;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAKjD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,kBAAkB,EAAE,CA6B3G;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,EAAE,OAAO,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,EAAE,CAYlH"}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * The signal digest contract (#987, specs/2026-10-03-signal-digest.md §2):
3
+ * validate a team lead's proposal and work out which actions the site's
4
+ * history blocks. Pure.
5
+ *
6
+ * Every rejection says what to fix, because the reader is an agent that will
7
+ * retry with whatever the error tells it.
8
+ *
9
+ * @module services/signal-digest/signal-digest-contract
10
+ */
11
+ import { SIGNAL_DIGEST_CONSTANTS } from '../../constants.js';
12
+ import * as path from 'path';
13
+ /** A rejected proposal. */
14
+ export class SignalDigestError extends Error {
15
+ status;
16
+ /**
17
+ * @param status - HTTP status to answer with
18
+ * @param message - What to fix
19
+ */
20
+ constructor(status, message) {
21
+ super(message);
22
+ this.status = status;
23
+ this.name = 'SignalDigestError';
24
+ }
25
+ }
26
+ /** Appended to contract errors. */
27
+ export const SIGNAL_DIGEST_EXAMPLE = 'Example item: {"key":"gsc:low-ctr:h1b visa fee","source":"gsc","signal":"\'h1b visa fee\' ranks #2 with 4% CTR on 900 impressions (7 d)","proposal":"Rewrite the title and description of /h1b-fee to answer the fee question","expectedEffect":"CTR 4% → ~12%: about +70 clicks a week","effort":"S — 1 h","metric":"GSC clicks for \'h1b visa fee\'"}';
28
+ /**
29
+ * Collapse whitespace.
30
+ *
31
+ * @param s - Text
32
+ * @returns One trimmed line
33
+ */
34
+ function oneLine(s) {
35
+ return s.replace(/\s+/g, ' ').trim();
36
+ }
37
+ /**
38
+ * Normalised identity of an action key (case and spacing do not matter).
39
+ *
40
+ * @param key - Key as sent
41
+ * @returns Comparable key
42
+ */
43
+ export function normalizeKey(key) {
44
+ return oneLine(key).toLowerCase();
45
+ }
46
+ /**
47
+ * A required one-line text field.
48
+ *
49
+ * @param item - Raw item
50
+ * @param field - Field name
51
+ * @param max - Max characters
52
+ * @param n - Item number (for the error)
53
+ * @returns The text
54
+ * @throws SignalDigestError(400)
55
+ */
56
+ function textField(item, field, max, n) {
57
+ const raw = item[field];
58
+ const text = typeof raw === 'string' ? oneLine(raw) : '';
59
+ if (!text)
60
+ throw new SignalDigestError(400, `item ${n}: "${field}" is required. ${SIGNAL_DIGEST_EXAMPLE}`);
61
+ if (text.length > max)
62
+ throw new SignalDigestError(400, `item ${n}: "${field}" is too long (max ${max} characters, got ${text.length}). Say it shorter.`);
63
+ return text;
64
+ }
65
+ /** Experiment spec fields kept (strings). */
66
+ const EXPERIMENT_TEXT_FIELDS = ['page', 'query', 'event', 'channel'];
67
+ /**
68
+ * An action's optional experiment spec. Only the shape is checked here; the
69
+ * experiment service validates the measure and filters when a Do creates it.
70
+ *
71
+ * @param raw - `experiment` as sent
72
+ * @param n - Item number (for the error)
73
+ * @returns Spec, or undefined when absent
74
+ * @throws SignalDigestError(400)
75
+ */
76
+ function experimentSpec(raw, n) {
77
+ if (raw === undefined || raw === null)
78
+ return undefined;
79
+ if (typeof raw !== 'object')
80
+ throw new SignalDigestError(400, `item ${n}: "experiment" must be an object like {"source":"gsc","measure":"clicks","query":"…"}.`);
81
+ const e = raw;
82
+ if (e.source !== 'gsc' && e.source !== 'ga4')
83
+ throw new SignalDigestError(400, `item ${n}: experiment.source must be gsc or ga4.`);
84
+ const measure = typeof e.measure === 'string' ? e.measure.trim() : '';
85
+ if (!measure)
86
+ throw new SignalDigestError(400, `item ${n}: experiment.measure is required (gsc: clicks / impressions / ctr / position; ga4: sessions / events).`);
87
+ const spec = { source: e.source, measure };
88
+ for (const f of EXPERIMENT_TEXT_FIELDS) {
89
+ const v = typeof e[f] === 'string' ? oneLine(e[f]) : '';
90
+ if (v)
91
+ spec[f] = v.slice(0, SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS);
92
+ }
93
+ return spec;
94
+ }
95
+ /**
96
+ * One source status from `collect`'s wording: `ok`, `not configured`, or
97
+ * `error: <why>`.
98
+ *
99
+ * @param name - Source name
100
+ * @param raw - Status text, or `{state, detail}`
101
+ * @returns The status
102
+ * @throws SignalDigestError(400)
103
+ */
104
+ function sourceStatus(name, raw) {
105
+ const C = SIGNAL_DIGEST_CONSTANTS;
106
+ const n = oneLine(name).toLowerCase().slice(0, C.SOURCE_NAME_MAX_CHARS);
107
+ if (!n)
108
+ throw new SignalDigestError(400, 'every source needs a name (ga4, gsc, inbox, errors).');
109
+ let state;
110
+ let detail = '';
111
+ if (raw && typeof raw === 'object') {
112
+ const o = raw;
113
+ const s = typeof o.state === 'string' ? o.state.trim().toLowerCase().replace(/\s+/g, '_') : '';
114
+ if (s !== 'ok' && s !== 'not_configured' && s !== 'error')
115
+ throw new SignalDigestError(400, `source ${n}: "state" must be ok, not_configured or error.`);
116
+ state = s;
117
+ detail = typeof o.detail === 'string' ? oneLine(o.detail) : '';
118
+ }
119
+ else if (typeof raw === 'string') {
120
+ const text = oneLine(raw);
121
+ const lower = text.toLowerCase();
122
+ if (lower === 'ok')
123
+ state = 'ok';
124
+ else if (lower === 'not configured' || lower === 'not_configured')
125
+ state = 'not_configured';
126
+ else if (lower.startsWith('error')) {
127
+ state = 'error';
128
+ detail = text.replace(/^error:?\s*/i, '');
129
+ }
130
+ else
131
+ throw new SignalDigestError(400, `source ${n}: status must be "ok", "not configured" or "error: why" (got "${text.slice(0, 40)}").`);
132
+ }
133
+ else {
134
+ throw new SignalDigestError(400, `source ${n}: status must be "ok", "not configured" or "error: why".`);
135
+ }
136
+ return { name: n, state, ...(state === 'error' ? { detail: (detail || 'failed').slice(0, C.SOURCE_DETAIL_MAX_CHARS) } : {}) };
137
+ }
138
+ /**
139
+ * Source statuses as `collect` prints them (`{"ga4":"ok","gsc":"error: HTTP 403"}`)
140
+ * or as a list of `{name, state, detail?}`.
141
+ *
142
+ * @param raw - Body field
143
+ * @returns Statuses (sorted by name), or undefined when absent
144
+ * @throws SignalDigestError(400)
145
+ */
146
+ export function parseSourceStatuses(raw) {
147
+ if (raw === undefined || raw === null)
148
+ return undefined;
149
+ const entries = Array.isArray(raw)
150
+ ? raw.map((x) => [typeof x?.name === 'string' ? x.name : '', x])
151
+ : typeof raw === 'object'
152
+ ? Object.entries(raw)
153
+ : [];
154
+ if (!Array.isArray(raw) && typeof raw !== 'object')
155
+ throw new SignalDigestError(400, '"sources" must be an object like {"ga4":"ok","gsc":"error: why"}.');
156
+ if (entries.length > SIGNAL_DIGEST_CONSTANTS.MAX_SOURCES)
157
+ throw new SignalDigestError(400, `"sources" lists too many sources (max ${SIGNAL_DIGEST_CONSTANTS.MAX_SOURCES}).`);
158
+ const out = new Map();
159
+ for (const [name, value] of entries) {
160
+ const st = sourceStatus(name, value);
161
+ out.set(st.name, st);
162
+ }
163
+ return [...out.values()].sort((a, b) => a.name.localeCompare(b.name));
164
+ }
165
+ /**
166
+ * Validate a proposal: a site, an optional project, and 3–5 distinct actions,
167
+ * each with key, source, signal, proposal, expected effect and effort.
168
+ *
169
+ * @param input - Request body
170
+ * @returns The proposal
171
+ * @throws SignalDigestError(400) naming what to fix
172
+ */
173
+ export function validateSignalDigest(input) {
174
+ const site = typeof input.site === 'string' ? oneLine(input.site) : '';
175
+ if (!site)
176
+ throw new SignalDigestError(400, '"site" is required (e.g. "visa.careerengine.us").');
177
+ if (site.length > SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS)
178
+ throw new SignalDigestError(400, `"site" is too long (max ${SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS} characters).`);
179
+ const project = typeof input.project === 'string' && oneLine(input.project) ? oneLine(input.project) : undefined;
180
+ const config = typeof input.config === 'string' && input.config.trim() ? input.config.trim() : undefined;
181
+ if (config && !path.isAbsolute(config))
182
+ throw new SignalDigestError(400, '"config" must be the absolute path of the seo-ops site config.');
183
+ const raw = input.items;
184
+ const { MIN_ITEMS, MAX_ITEMS } = SIGNAL_DIGEST_CONSTANTS;
185
+ if (!Array.isArray(raw) || raw.length < MIN_ITEMS || raw.length > MAX_ITEMS) {
186
+ const got = Array.isArray(raw) ? raw.length : 0;
187
+ throw new SignalDigestError(400, `give ${MIN_ITEMS}–${MAX_ITEMS} actions (got ${got}): pick the ones worth the owner's tap, ranked best first. ${SIGNAL_DIGEST_EXAMPLE}`);
188
+ }
189
+ const seen = new Set();
190
+ const items = raw.map((value, i) => {
191
+ const n = i + 1;
192
+ if (!value || typeof value !== 'object')
193
+ throw new SignalDigestError(400, `item ${n} must be an object. ${SIGNAL_DIGEST_EXAMPLE}`);
194
+ const item = value;
195
+ const key = textField(item, 'key', SIGNAL_DIGEST_CONSTANTS.KEY_MAX_CHARS, n);
196
+ const source = typeof item.source === 'string' ? item.source.trim().toLowerCase() : '';
197
+ if (!SIGNAL_DIGEST_CONSTANTS.SOURCES.includes(source)) {
198
+ throw new SignalDigestError(400, `item ${n}: "source" must be one of ${SIGNAL_DIGEST_CONSTANTS.SOURCES.join(', ')}.`);
199
+ }
200
+ const norm = normalizeKey(key);
201
+ if (seen.has(norm))
202
+ throw new SignalDigestError(400, `item ${n}: key "${key}" is used twice; each action needs its own key.`);
203
+ seen.add(norm);
204
+ const metricRaw = typeof item.metric === 'string' ? oneLine(item.metric) : '';
205
+ if (metricRaw.length > SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS) {
206
+ throw new SignalDigestError(400, `item ${n}: "metric" is too long (max ${SIGNAL_DIGEST_CONSTANTS.METRIC_MAX_CHARS} characters).`);
207
+ }
208
+ const experiment = experimentSpec(item.experiment, n);
209
+ return {
210
+ key,
211
+ source: source,
212
+ signal: textField(item, 'signal', SIGNAL_DIGEST_CONSTANTS.SIGNAL_MAX_CHARS, n),
213
+ proposal: textField(item, 'proposal', SIGNAL_DIGEST_CONSTANTS.PROPOSAL_MAX_CHARS, n),
214
+ expectedEffect: textField(item, 'expectedEffect', SIGNAL_DIGEST_CONSTANTS.EXPECTED_MAX_CHARS, n),
215
+ effort: textField(item, 'effort', SIGNAL_DIGEST_CONSTANTS.EFFORT_MAX_CHARS, n),
216
+ ...(metricRaw ? { metric: metricRaw } : {}),
217
+ ...(experiment ? { experiment } : {}),
218
+ };
219
+ });
220
+ const sources = parseSourceStatuses(input.sources);
221
+ return { site, ...(project ? { project } : {}), ...(config ? { config } : {}), items, ...(sources ? { sources } : {}) };
222
+ }
223
+ /**
224
+ * Validate a site name.
225
+ *
226
+ * @param raw - Body field
227
+ * @returns The site
228
+ * @throws SignalDigestError(400)
229
+ */
230
+ export function validateSite(raw) {
231
+ const site = typeof raw === 'string' ? oneLine(raw) : '';
232
+ if (!site)
233
+ throw new SignalDigestError(400, '"site" is required (e.g. "visa.careerengine.us").');
234
+ if (site.length > SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS)
235
+ throw new SignalDigestError(400, `"site" is too long (max ${SIGNAL_DIGEST_CONSTANTS.SITE_MAX_CHARS} characters).`);
236
+ return site;
237
+ }
238
+ /**
239
+ * The keys a site's history blocks right now, newest first per key:
240
+ * - a Do blocks its key for {@link SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS} (it was tried);
241
+ * - a Skip blocks it for {@link SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS};
242
+ * - an open item blocks it while it is open.
243
+ * Expired items (replaced unanswered) block nothing.
244
+ *
245
+ * @param digests - All stored digests
246
+ * @param site - Site
247
+ * @param now - Clock
248
+ * @returns Blocked entries, one per key
249
+ */
250
+ export function siteHistory(digests, site, now) {
251
+ const want = site.trim().toLowerCase();
252
+ const byKey = new Map();
253
+ const ordered = [...digests].filter((d) => d.site.trim().toLowerCase() === want).sort((a, b) => Date.parse(b.createdAt) - Date.parse(a.createdAt));
254
+ for (const d of ordered) {
255
+ for (const item of d.items) {
256
+ const norm = normalizeKey(item.key);
257
+ if (byKey.has(norm))
258
+ continue;
259
+ if (item.status === 'open') {
260
+ byKey.set(norm, { key: item.key, status: 'open', at: d.createdAt, proposal: item.proposal, digestId: d.id });
261
+ continue;
262
+ }
263
+ if (item.status !== 'do' && item.status !== 'skip')
264
+ continue;
265
+ const at = item.answeredAt ?? d.updatedAt;
266
+ const span = item.status === 'do' ? SIGNAL_DIGEST_CONSTANTS.DO_BLOCK_MS : SIGNAL_DIGEST_CONSTANTS.SKIP_BLOCK_MS;
267
+ const until = Date.parse(at) + span;
268
+ if (until <= now.getTime())
269
+ continue;
270
+ byKey.set(norm, {
271
+ key: item.key,
272
+ status: item.status,
273
+ at,
274
+ proposal: item.proposal,
275
+ digestId: d.id,
276
+ ...(item.ticketId ? { ticketId: item.ticketId } : {}),
277
+ blockedUntil: new Date(until).toISOString(),
278
+ });
279
+ }
280
+ }
281
+ return [...byKey.values()];
282
+ }
283
+ /**
284
+ * Explain which proposed actions the history blocks.
285
+ *
286
+ * @param items - Proposed actions
287
+ * @param history - {@link siteHistory} of the site
288
+ * @returns One line per blocked action (empty when none)
289
+ */
290
+ export function blockedLines(items, history) {
291
+ const byKey = new Map(history.map((h) => [normalizeKey(h.key), h]));
292
+ const lines = [];
293
+ for (const item of items) {
294
+ const h = byKey.get(normalizeKey(item.key));
295
+ if (!h)
296
+ continue;
297
+ const when = h.at.slice(0, 10);
298
+ if (h.status === 'do')
299
+ lines.push(`"${item.key}": the owner chose Do on ${when} (${h.digestId}${h.ticketId ? `, ${h.ticketId}` : ''}) — it is being tried`);
300
+ else if (h.status === 'skip')
301
+ lines.push(`"${item.key}": the owner skipped it on ${when} (${h.digestId}); not before ${h.blockedUntil?.slice(0, 10)}`);
302
+ else
303
+ lines.push(`"${item.key}": still waiting on the owner in ${h.digestId}`);
304
+ }
305
+ return lines;
306
+ }
307
+ //# sourceMappingURL=signal-digest-contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signal-digest-contract.js","sourceRoot":"","sources":["../../../../../../backend/src/services/signal-digest/signal-digest-contract.ts"],"names":[],"mappings":"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"}