@useorgx/openclaw-plugin 0.4.9 → 0.7.2

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 (224) hide show
  1. package/README.md +77 -11
  2. package/dashboard/dist/assets/6mILZQ2a.js +1 -0
  3. package/dashboard/dist/assets/6mILZQ2a.js.br +0 -0
  4. package/dashboard/dist/assets/6mILZQ2a.js.gz +0 -0
  5. package/dashboard/dist/assets/8dksYiq4.js +2 -0
  6. package/dashboard/dist/assets/8dksYiq4.js.br +0 -0
  7. package/dashboard/dist/assets/8dksYiq4.js.gz +0 -0
  8. package/dashboard/dist/assets/B5zYRHc3.js +1 -0
  9. package/dashboard/dist/assets/B5zYRHc3.js.br +0 -0
  10. package/dashboard/dist/assets/B5zYRHc3.js.gz +0 -0
  11. package/dashboard/dist/assets/B6wPWJ35.js +1 -0
  12. package/dashboard/dist/assets/B6wPWJ35.js.br +0 -0
  13. package/dashboard/dist/assets/B6wPWJ35.js.gz +0 -0
  14. package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
  15. package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
  16. package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
  17. package/dashboard/dist/assets/BWEwjt1W.js +1 -0
  18. package/dashboard/dist/assets/BWEwjt1W.js.br +0 -0
  19. package/dashboard/dist/assets/BWEwjt1W.js.gz +0 -0
  20. package/dashboard/dist/assets/BgOYB78t.js +4 -0
  21. package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
  22. package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
  23. package/dashboard/dist/assets/BzRbDCAD.css +1 -0
  24. package/dashboard/dist/assets/BzRbDCAD.css.br +0 -0
  25. package/dashboard/dist/assets/BzRbDCAD.css.gz +0 -0
  26. package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
  27. package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
  28. package/dashboard/dist/assets/C8uM3AX8.js +1 -0
  29. package/dashboard/dist/assets/C8uM3AX8.js.br +0 -0
  30. package/dashboard/dist/assets/C8uM3AX8.js.gz +0 -0
  31. package/dashboard/dist/assets/C9jy61eu.js +212 -0
  32. package/dashboard/dist/assets/C9jy61eu.js.br +0 -0
  33. package/dashboard/dist/assets/C9jy61eu.js.gz +0 -0
  34. package/dashboard/dist/assets/CC63EwFD.js +1 -0
  35. package/dashboard/dist/assets/CC63EwFD.js.br +0 -0
  36. package/dashboard/dist/assets/CC63EwFD.js.gz +0 -0
  37. package/dashboard/dist/assets/CL_wXqR7.js +1 -0
  38. package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
  39. package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
  40. package/dashboard/dist/assets/CZaT3ob_.js +1 -0
  41. package/dashboard/dist/assets/CZaT3ob_.js.br +0 -0
  42. package/dashboard/dist/assets/CZaT3ob_.js.gz +0 -0
  43. package/dashboard/dist/assets/CgaottFX.js +1 -0
  44. package/dashboard/dist/assets/CgaottFX.js.br +0 -0
  45. package/dashboard/dist/assets/CgaottFX.js.gz +0 -0
  46. package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
  47. package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
  48. package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
  49. package/dashboard/dist/assets/CzCxAZlW.js +1 -0
  50. package/dashboard/dist/assets/CzCxAZlW.js.br +0 -0
  51. package/dashboard/dist/assets/CzCxAZlW.js.gz +0 -0
  52. package/dashboard/dist/assets/D3iMTYEj.js +1 -0
  53. package/dashboard/dist/assets/D3iMTYEj.js.br +0 -0
  54. package/dashboard/dist/assets/D3iMTYEj.js.gz +0 -0
  55. package/dashboard/dist/assets/D8JNX8kq.js +2 -0
  56. package/dashboard/dist/assets/D8JNX8kq.js.br +0 -0
  57. package/dashboard/dist/assets/D8JNX8kq.js.gz +0 -0
  58. package/dashboard/dist/assets/DnA8dpj6.js +1 -0
  59. package/dashboard/dist/assets/DnA8dpj6.js.br +0 -0
  60. package/dashboard/dist/assets/DnA8dpj6.js.gz +0 -0
  61. package/dashboard/dist/assets/IUexzymk.js +1 -0
  62. package/dashboard/dist/assets/IUexzymk.js.br +0 -0
  63. package/dashboard/dist/assets/IUexzymk.js.gz +0 -0
  64. package/dashboard/dist/assets/cNrhgGc1.js +8 -0
  65. package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
  66. package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
  67. package/dashboard/dist/assets/ic2FaMnh.js +1 -0
  68. package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
  69. package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
  70. package/dashboard/dist/assets/qm8xLgv-.css +1 -0
  71. package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
  72. package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
  73. package/dashboard/dist/assets/rttbDbEx.js +1 -0
  74. package/dashboard/dist/assets/rttbDbEx.js.br +0 -0
  75. package/dashboard/dist/assets/rttbDbEx.js.gz +0 -0
  76. package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
  77. package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
  78. package/dashboard/dist/brand/openai-mark.svg.br +0 -0
  79. package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
  80. package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
  81. package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
  82. package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
  83. package/dashboard/dist/index.html +7 -5
  84. package/dashboard/dist/index.html.br +0 -0
  85. package/dashboard/dist/index.html.gz +0 -0
  86. package/dist/activity-actor-fields.js +26 -4
  87. package/dist/activity-store.js +34 -8
  88. package/dist/agent-context-store.js +79 -17
  89. package/dist/agent-run-store.js +44 -3
  90. package/dist/agent-suite.d.ts +9 -0
  91. package/dist/agent-suite.js +149 -9
  92. package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
  93. package/dist/artifacts/artifact-domain-schemas.js +357 -0
  94. package/dist/artifacts/register-artifact.d.ts +4 -3
  95. package/dist/artifacts/register-artifact.js +170 -57
  96. package/dist/chat-store.d.ts +157 -0
  97. package/dist/chat-store.js +586 -0
  98. package/dist/cli/orgx.js +11 -0
  99. package/dist/contracts/client.d.ts +43 -3
  100. package/dist/contracts/client.js +159 -30
  101. package/dist/contracts/practice-exercise-schema.d.ts +216 -0
  102. package/dist/contracts/practice-exercise-schema.js +314 -0
  103. package/dist/contracts/retro-schema.d.ts +81 -0
  104. package/dist/contracts/retro-schema.js +80 -0
  105. package/dist/contracts/shared-types.d.ts +159 -0
  106. package/dist/contracts/shared-types.js +199 -1
  107. package/dist/contracts/skill-pack-schema.d.ts +192 -0
  108. package/dist/contracts/skill-pack-schema.js +180 -0
  109. package/dist/contracts/types.d.ts +247 -2
  110. package/dist/entities/auto-assignment.js +43 -17
  111. package/dist/event-sanitization.d.ts +11 -0
  112. package/dist/event-sanitization.js +113 -0
  113. package/dist/gateway-watchdog.d.ts +5 -0
  114. package/dist/gateway-watchdog.js +50 -0
  115. package/dist/hooks/post-reporting-event.mjs +1 -5
  116. package/dist/http/helpers/activity-headline.js +13 -132
  117. package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
  118. package/dist/http/helpers/auto-continue-engine.js +3145 -186
  119. package/dist/http/helpers/autopilot-operations.d.ts +19 -0
  120. package/dist/http/helpers/autopilot-operations.js +182 -31
  121. package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
  122. package/dist/http/helpers/autopilot-runtime.js +328 -25
  123. package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
  124. package/dist/http/helpers/autopilot-slice-utils.js +514 -93
  125. package/dist/http/helpers/decision-mapper.d.ts +40 -0
  126. package/dist/http/helpers/decision-mapper.js +223 -7
  127. package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
  128. package/dist/http/helpers/dispatch-lifecycle.js +242 -37
  129. package/dist/http/helpers/kickoff-context.js +104 -0
  130. package/dist/http/helpers/llm-client.d.ts +47 -0
  131. package/dist/http/helpers/llm-client.js +256 -0
  132. package/dist/http/helpers/mission-control.d.ts +102 -3
  133. package/dist/http/helpers/mission-control.js +498 -9
  134. package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
  135. package/dist/http/helpers/sentinel-catalog.js +193 -0
  136. package/dist/http/helpers/session-classification.d.ts +9 -0
  137. package/dist/http/helpers/session-classification.js +564 -0
  138. package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
  139. package/dist/http/helpers/slice-experience-v2.js +677 -0
  140. package/dist/http/helpers/slice-run-projections.d.ts +72 -0
  141. package/dist/http/helpers/slice-run-projections.js +877 -0
  142. package/dist/http/helpers/triage-mapper.d.ts +43 -0
  143. package/dist/http/helpers/triage-mapper.js +549 -0
  144. package/dist/http/helpers/value-utils.js +7 -2
  145. package/dist/http/helpers/workspace-scope.d.ts +15 -0
  146. package/dist/http/helpers/workspace-scope.js +170 -0
  147. package/dist/http/index.js +1420 -105
  148. package/dist/http/routes/agent-suite.d.ts +9 -0
  149. package/dist/http/routes/agent-suite.js +294 -8
  150. package/dist/http/routes/agents-catalog.js +64 -19
  151. package/dist/http/routes/chat.d.ts +19 -0
  152. package/dist/http/routes/chat.js +522 -0
  153. package/dist/http/routes/decision-actions.d.ts +8 -1
  154. package/dist/http/routes/decision-actions.js +42 -5
  155. package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
  156. package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
  157. package/dist/http/routes/entities.d.ts +16 -0
  158. package/dist/http/routes/entities.js +232 -6
  159. package/dist/http/routes/live-legacy.d.ts +5 -0
  160. package/dist/http/routes/live-legacy.js +23 -509
  161. package/dist/http/routes/live-misc.d.ts +12 -0
  162. package/dist/http/routes/live-misc.js +251 -31
  163. package/dist/http/routes/live-snapshot.d.ts +49 -2
  164. package/dist/http/routes/live-snapshot.js +653 -23
  165. package/dist/http/routes/live-terminal.d.ts +11 -0
  166. package/dist/http/routes/live-terminal.js +154 -0
  167. package/dist/http/routes/live-triage.d.ts +61 -0
  168. package/dist/http/routes/live-triage.js +192 -0
  169. package/dist/http/routes/mission-control-actions.d.ts +49 -1
  170. package/dist/http/routes/mission-control-actions.js +1246 -84
  171. package/dist/http/routes/mission-control-read.d.ts +48 -3
  172. package/dist/http/routes/mission-control-read.js +1658 -20
  173. package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
  174. package/dist/http/routes/realtime-orchestrator.js +74 -0
  175. package/dist/http/routes/run-control.d.ts +5 -2
  176. package/dist/http/routes/run-control.js +10 -0
  177. package/dist/http/routes/sentinels-catalog.d.ts +7 -0
  178. package/dist/http/routes/sentinels-catalog.js +24 -0
  179. package/dist/http/routes/summary.js +10 -3
  180. package/dist/http/routes/usage.d.ts +24 -0
  181. package/dist/http/routes/usage.js +362 -0
  182. package/dist/http/routes/work-artifacts.js +28 -9
  183. package/dist/index.js +165 -27
  184. package/dist/local-openclaw.js +29 -6
  185. package/dist/mcp-client-setup.js +3 -3
  186. package/dist/mcp-http-handler.d.ts +3 -0
  187. package/dist/mcp-http-handler.js +34 -60
  188. package/dist/next-up-queue-store.d.ts +16 -1
  189. package/dist/next-up-queue-store.js +89 -7
  190. package/dist/outbox.d.ts +5 -0
  191. package/dist/outbox.js +113 -9
  192. package/dist/paths.js +36 -5
  193. package/dist/reporting/rollups.d.ts +41 -0
  194. package/dist/reporting/rollups.js +113 -0
  195. package/dist/retro/domain-templates.d.ts +45 -0
  196. package/dist/retro/domain-templates.js +297 -0
  197. package/dist/retro/quality-rubric.d.ts +33 -0
  198. package/dist/retro/quality-rubric.js +213 -0
  199. package/dist/runtime-cleanup.d.ts +18 -0
  200. package/dist/runtime-cleanup.js +87 -0
  201. package/dist/services/background.d.ts +11 -0
  202. package/dist/services/background.js +22 -0
  203. package/dist/services/experiment-randomization.d.ts +21 -0
  204. package/dist/services/experiment-randomization.js +63 -0
  205. package/dist/skill-pack-state.d.ts +36 -5
  206. package/dist/skill-pack-state.js +273 -29
  207. package/dist/sync/local-agent-telemetry.d.ts +13 -0
  208. package/dist/sync/local-agent-telemetry.js +128 -0
  209. package/dist/sync/outbox-replay.js +131 -24
  210. package/dist/team-context-store.d.ts +23 -0
  211. package/dist/team-context-store.js +116 -0
  212. package/dist/telemetry/posthog.js +4 -2
  213. package/dist/tools/core-tools.d.ts +10 -14
  214. package/dist/tools/core-tools.js +1289 -24
  215. package/dist/types.d.ts +2 -0
  216. package/dist/types.js +2 -0
  217. package/dist/worker-supervisor.js +23 -0
  218. package/package.json +20 -6
  219. package/dashboard/dist/assets/B3ziCA02.js +0 -8
  220. package/dashboard/dist/assets/B5NEElEI.css +0 -1
  221. package/dashboard/dist/assets/BhapSNAs.js +0 -215
  222. package/dashboard/dist/assets/iFdvE7lx.js +0 -1
  223. package/dashboard/dist/assets/jRJsmpYM.js +0 -1
  224. package/dashboard/dist/assets/sAhvFnpk.js +0 -4
@@ -0,0 +1,297 @@
1
+ import { callLlmJson } from "../http/helpers/llm-client.js";
2
+ const DOMAIN_TEMPLATES = {
3
+ engineering: {
4
+ summaryPrefix: "Engineering execution",
5
+ successWell: [
6
+ "Delivered implementation changes with focused validation evidence.",
7
+ "Kept execution scoped to the active slice and avoided unrelated churn.",
8
+ ],
9
+ successDecisions: ["No immediate intervention required; keep current engineering execution pattern."],
10
+ successFollowUps: [
11
+ {
12
+ title: "Capture engineering implementation notes for future retros",
13
+ priority: "p2",
14
+ },
15
+ ],
16
+ failureDecision: "Escalate blocker triage and assign root-cause owner before the next engineering run.",
17
+ failureFollowUpTitle: "Reproduce failure with a targeted engineering check and patch root cause",
18
+ failureFollowUpReason: "Engineering runs should converge quickly on reproducible failures and ship a corrective change.",
19
+ },
20
+ product: {
21
+ summaryPrefix: "Product execution",
22
+ successWell: [
23
+ "Clarified scope and acceptance criteria for the requested slice.",
24
+ "Converted ambiguous asks into concrete execution steps.",
25
+ ],
26
+ successDecisions: ["Proceed with the current product plan and track any open assumptions."],
27
+ successFollowUps: [{ title: "Log product assumptions and open questions", priority: "p2" }],
28
+ failureDecision: "Resolve product scope/acceptance ambiguity with a direct owner decision before retry.",
29
+ failureFollowUpTitle: "Resolve product requirement ambiguity before next run",
30
+ failureFollowUpReason: "Product loops fail when acceptance criteria and constraints remain underspecified.",
31
+ },
32
+ design: {
33
+ summaryPrefix: "Design execution",
34
+ successWell: [
35
+ "Produced design output aligned with existing system constraints.",
36
+ "Prioritized usability clarity over decorative changes.",
37
+ ],
38
+ successDecisions: ["Continue with the approved design direction and preserve current constraints."],
39
+ successFollowUps: [{ title: "Attach visual QA checklist for handoff", priority: "p2" }],
40
+ failureDecision: "Run a blocking UX triage decision and align acceptance checkpoints before rerun.",
41
+ failureFollowUpTitle: "Run design QA pass and fix blocking UX mismatches",
42
+ failureFollowUpReason: "Design regressions should be validated with explicit viewport and interaction checks.",
43
+ },
44
+ marketing: {
45
+ summaryPrefix: "Marketing execution",
46
+ successWell: [
47
+ "Delivered channel-ready messaging with clear audience targeting.",
48
+ "Maintained consistent narrative and measurable intent.",
49
+ ],
50
+ successDecisions: ["Keep the current campaign direction and monitor defined success signals."],
51
+ successFollowUps: [{ title: "Record campaign hypotheses and success metrics", priority: "p2" }],
52
+ failureDecision: "Decide on updated positioning hypothesis before the next marketing execution cycle.",
53
+ failureFollowUpTitle: "Diagnose marketing execution gap and tighten message-to-metric mapping",
54
+ failureFollowUpReason: "Marketing outcomes need explicit hypotheses, channel constraints, and measurable goals.",
55
+ },
56
+ sales: {
57
+ summaryPrefix: "Sales execution",
58
+ successWell: [
59
+ "Created actionable next steps tied to buyer-stage progression.",
60
+ "Preserved signal quality for follow-up actions and objections.",
61
+ ],
62
+ successDecisions: ["Continue with the current sales motion while maintaining pipeline signal quality."],
63
+ successFollowUps: [{ title: "Document discovery-to-close handoff notes", priority: "p2" }],
64
+ failureDecision: "Trigger a sales unblock decision on objection handling and next-step ownership.",
65
+ failureFollowUpTitle: "Rework sales motion to unblock stalled buyer progression",
66
+ failureFollowUpReason: "Sales stalls usually reflect missing objection handling or unclear next actions.",
67
+ },
68
+ operations: {
69
+ summaryPrefix: "Operations execution",
70
+ successWell: [
71
+ "Stabilized process flow with explicit ownership and runbook alignment.",
72
+ "Reduced operational risk through controlled scope and sequencing.",
73
+ ],
74
+ successDecisions: ["Keep current ops controls and apply runbook deltas from this run."],
75
+ successFollowUps: [{ title: "Add ops runbook delta from this run", priority: "p2" }],
76
+ failureDecision: "Escalate operational owner decision to remove the bottleneck before retrying.",
77
+ failureFollowUpTitle: "Patch operational bottleneck and update runbook controls",
78
+ failureFollowUpReason: "Operations failures should result in tighter runbooks and clearer owner accountability.",
79
+ },
80
+ orchestration: {
81
+ summaryPrefix: "Orchestration execution",
82
+ successWell: [
83
+ "Coordinated dependencies and sequencing across agents effectively.",
84
+ "Maintained clear control flow for decisions and handoffs.",
85
+ ],
86
+ successDecisions: ["Preserve current orchestration sequencing and monitor handoff latency."],
87
+ successFollowUps: [{ title: "Capture orchestration handoff timing insights", priority: "p2" }],
88
+ failureDecision: "Request an orchestration sequencing decision to unblock dependency handoffs.",
89
+ failureFollowUpTitle: "Unblock orchestration handoff failure and re-sequence dependent work",
90
+ failureFollowUpReason: "Orchestration errors should tighten dependency ordering and handoff contracts.",
91
+ },
92
+ general: {
93
+ summaryPrefix: "Execution",
94
+ successWell: ["Completed the requested run without runtime error."],
95
+ successDecisions: ["No immediate action required; continue with the current execution flow."],
96
+ successFollowUps: [],
97
+ failureDecision: "Request a human unblock decision before the next retry.",
98
+ failureFollowUpTitle: "Investigate OpenClaw session failure and unblock task",
99
+ failureFollowUpReason: "Session ended with error.",
100
+ },
101
+ };
102
+ function inferDomainFromAgentId(agentId) {
103
+ const normalized = String(agentId ?? "").trim().toLowerCase();
104
+ if (!normalized)
105
+ return "general";
106
+ const compact = normalized.replace(/[^a-z0-9]/g, "");
107
+ const tokenSet = new Set(normalized.split(/[^a-z0-9]+/g).filter(Boolean));
108
+ const hasToken = (...tokens) => tokens.some((token) => tokenSet.has(token));
109
+ const hasTokenPrefix = (...prefixes) => Array.from(tokenSet).some((token) => prefixes.some((prefix) => token.startsWith(prefix)));
110
+ if (normalized.includes("sentinel") ||
111
+ hasToken("sentinel", "watchdog") ||
112
+ hasTokenPrefix("sentinel", "watch")) {
113
+ return "orchestration";
114
+ }
115
+ if (normalized.includes("engineering") ||
116
+ normalized.includes("developer") ||
117
+ hasToken("eng", "dev", "frontend", "backend", "fullstack", "engineer") ||
118
+ compact.includes("engineering") ||
119
+ compact.includes("developer")) {
120
+ return "engineering";
121
+ }
122
+ if (normalized.includes("product") ||
123
+ hasToken("pm", "prod") ||
124
+ hasTokenPrefix("product", "pm") ||
125
+ compact.includes("productmanager")) {
126
+ return "product";
127
+ }
128
+ if (normalized.includes("design") || tokenSet.has("ux") || tokenSet.has("ui"))
129
+ return "design";
130
+ if (normalized.includes("marketing") ||
131
+ hasToken("mktg", "growth") ||
132
+ hasTokenPrefix("mkt", "market")) {
133
+ return "marketing";
134
+ }
135
+ if (normalized.includes("sales") || hasToken("sdr", "ae") || hasTokenPrefix("sales"))
136
+ return "sales";
137
+ if (normalized.includes("operations") ||
138
+ normalized.includes("platform") ||
139
+ hasToken("ops", "sre", "infra") ||
140
+ hasTokenPrefix("operat", "platform", "infra")) {
141
+ return "operations";
142
+ }
143
+ if (normalized.includes("orchestrat") ||
144
+ hasToken("coord", "router") ||
145
+ hasTokenPrefix("coordinat", "orchestrat", "route")) {
146
+ return "orchestration";
147
+ }
148
+ return "general";
149
+ }
150
+ function isSentinelAgentId(agentId) {
151
+ const normalized = String(agentId ?? "").trim().toLowerCase();
152
+ if (!normalized)
153
+ return false;
154
+ const compact = normalized.replace(/[^a-z0-9]/g, "");
155
+ if (normalized.includes("sentinel") || compact.includes("sentinel")) {
156
+ return true;
157
+ }
158
+ const tokenSet = new Set(normalized.split(/[^a-z0-9]+/g).filter(Boolean));
159
+ return tokenSet.has("watchdog") || Array.from(tokenSet).some((token) => token.startsWith("watch"));
160
+ }
161
+ export function buildRetroTemplateForAgent(input) {
162
+ const domain = inferDomainFromAgentId(input.agentId);
163
+ const isSentinel = isSentinelAgentId(input.agentId);
164
+ const template = DOMAIN_TEMPLATES[domain];
165
+ const errorMessage = input.errorMessage?.trim() || "Session ended with error.";
166
+ const summary = input.taskId
167
+ ? `${template.summaryPrefix} ${input.success ? "completed" : "blocked"} task ${input.taskId}.`
168
+ : `${template.summaryPrefix} run ${input.success ? "completed" : "blocked"} (session ${input.runId}).`;
169
+ if (input.success) {
170
+ return {
171
+ domain,
172
+ summary,
173
+ whatWentWell: template.successWell,
174
+ whatWentWrong: [],
175
+ decisions: template.successDecisions,
176
+ followUps: template.successFollowUps,
177
+ };
178
+ }
179
+ return {
180
+ domain,
181
+ summary,
182
+ whatWentWell: [],
183
+ whatWentWrong: [errorMessage],
184
+ decisions: [
185
+ isSentinel
186
+ ? "Sentinel: resolve decision to unblock dependency handoffs before retrying this run."
187
+ : template.failureDecision,
188
+ ],
189
+ followUps: [
190
+ {
191
+ title: template.failureFollowUpTitle,
192
+ priority: "p0",
193
+ reason: domain === "general"
194
+ ? errorMessage
195
+ : `${template.failureFollowUpReason} Error: ${errorMessage}`,
196
+ },
197
+ ],
198
+ };
199
+ }
200
+ // ---------------------------------------------------------------------------
201
+ // LLM-powered retro generation (falls back to heuristic template above)
202
+ // ---------------------------------------------------------------------------
203
+ const RETRO_SYSTEM_PROMPT = `You generate structured retrospectives for autonomous agent runs. Given the run context, produce a JSON object with these fields: domain (one of: engineering, product, design, marketing, sales, operations, orchestration, general), summary (1 sentence), whatWentWell (1-3 specific items), whatWentWrong (0-3 items, empty if success), decisions (1-2 actionable items), followUps (0-2 items, each with title, priority p0/p1/p2, and reason). Be specific to what actually happened — avoid generic template language.`;
204
+ const VALID_DOMAINS = new Set([
205
+ "engineering",
206
+ "product",
207
+ "design",
208
+ "marketing",
209
+ "sales",
210
+ "operations",
211
+ "orchestration",
212
+ "general",
213
+ ]);
214
+ const VALID_PRIORITIES = new Set(["p0", "p1", "p2"]);
215
+ /**
216
+ * Generate a structured retro using an LLM, falling back to the heuristic
217
+ * template produced by {@link buildRetroTemplateForAgent}.
218
+ *
219
+ * Caller: src/index.ts (~line 971) — `buildRetroTemplateForAgent` is invoked
220
+ * inside the session-stopped handler. Migrate that call site to use this
221
+ * function when ready to enable LLM-powered retros.
222
+ */
223
+ export async function buildRetroWithLlm(input) {
224
+ const lines = [
225
+ `Agent ID: ${input.agentId ?? "(unknown)"}`,
226
+ `Outcome: ${input.success ? "success" : "failure"}`,
227
+ `Task ID: ${input.taskId ?? "(none)"}`,
228
+ `Run ID: ${input.runId}`,
229
+ ];
230
+ if (input.errorMessage) {
231
+ lines.push(`Error: ${input.errorMessage}`);
232
+ }
233
+ if (input.executionContext) {
234
+ lines.push(`Execution context: ${input.executionContext}`);
235
+ }
236
+ const userPrompt = lines.join("\n");
237
+ function parseRetroJson(raw) {
238
+ try {
239
+ const obj = JSON.parse(raw);
240
+ if (typeof obj.domain !== "string" || !VALID_DOMAINS.has(obj.domain))
241
+ return null;
242
+ if (typeof obj.summary !== "string" || obj.summary.length === 0)
243
+ return null;
244
+ if (!Array.isArray(obj.whatWentWell) || !obj.whatWentWell.every((v) => typeof v === "string"))
245
+ return null;
246
+ if (!Array.isArray(obj.whatWentWrong) || !obj.whatWentWrong.every((v) => typeof v === "string"))
247
+ return null;
248
+ if (!Array.isArray(obj.decisions) || !obj.decisions.every((v) => typeof v === "string"))
249
+ return null;
250
+ if (!Array.isArray(obj.followUps))
251
+ return null;
252
+ const followUps = [];
253
+ for (const fu of obj.followUps) {
254
+ if (!fu || typeof fu !== "object")
255
+ return null;
256
+ const rec = fu;
257
+ if (typeof rec.title !== "string" || rec.title.length === 0)
258
+ return null;
259
+ const entry = { title: rec.title };
260
+ if (typeof rec.priority === "string" && VALID_PRIORITIES.has(rec.priority)) {
261
+ entry.priority = rec.priority;
262
+ }
263
+ if (typeof rec.reason === "string") {
264
+ entry.reason = rec.reason;
265
+ }
266
+ followUps.push(entry);
267
+ }
268
+ return {
269
+ domain: obj.domain,
270
+ summary: obj.summary,
271
+ whatWentWell: obj.whatWentWell,
272
+ whatWentWrong: obj.whatWentWrong,
273
+ decisions: obj.decisions,
274
+ followUps,
275
+ };
276
+ }
277
+ catch {
278
+ return null;
279
+ }
280
+ }
281
+ function heuristicFallback() {
282
+ return buildRetroTemplateForAgent(input);
283
+ }
284
+ const response = await callLlmJson({
285
+ taskId: "retro",
286
+ systemPrompt: RETRO_SYSTEM_PROMPT,
287
+ userPrompt,
288
+ model: "openai/gpt-4.1-mini",
289
+ maxTokens: 512,
290
+ temperature: 0.2,
291
+ cacheTtlMs: 6 * 60 * 60_000, // 6 hours
292
+ }, parseRetroJson, heuristicFallback);
293
+ return {
294
+ ...response.result,
295
+ source: response.source,
296
+ };
297
+ }
@@ -0,0 +1,33 @@
1
+ import type { OrgxAgentDomain } from "../contracts/types.js";
2
+ export type RetroQualityRubricInput = {
3
+ success: boolean;
4
+ hadError: boolean;
5
+ errorMessage?: string | null;
6
+ tokens?: number | null;
7
+ costUsd?: number | null;
8
+ decisionsCount?: number;
9
+ followUpsCount?: number;
10
+ whatWentWrongCount?: number;
11
+ /** Agent domain for domain-specific scoring modifiers */
12
+ domain?: OrgxAgentDomain | null;
13
+ /** Artifact metadata from the registered atomic unit */
14
+ artifactMetadata?: Record<string, unknown> | null;
15
+ };
16
+ export type RetroQualityRubricResult = {
17
+ score: number;
18
+ reasons: string[];
19
+ };
20
+ /**
21
+ * Compute domain-specific quality modifier based on artifact metadata.
22
+ * Returns delta (positive = bonus, negative = penalty) and reasons.
23
+ */
24
+ export declare function computeDomainQualityModifier(domain: OrgxAgentDomain | null | undefined, artifactMetadata: Record<string, unknown> | null | undefined): {
25
+ delta: number;
26
+ reasons: string[];
27
+ };
28
+ export declare function computeRetroQualityRubricScore(input: RetroQualityRubricInput): RetroQualityRubricResult;
29
+ export declare function computeRetroQualityWithLlm(input: RetroQualityRubricInput & {
30
+ executionContext?: string | null;
31
+ }): Promise<RetroQualityRubricResult & {
32
+ source: "llm" | "heuristic";
33
+ }>;
@@ -0,0 +1,213 @@
1
+ import { callLlmJson } from "../http/helpers/llm-client.js";
2
+ function toFiniteNumber(value) {
3
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
4
+ }
5
+ function toNonNegativeCount(value) {
6
+ return typeof value === "number" && Number.isFinite(value) && value > 0
7
+ ? Math.floor(value)
8
+ : 0;
9
+ }
10
+ /**
11
+ * Compute domain-specific quality modifier based on artifact metadata.
12
+ * Returns delta (positive = bonus, negative = penalty) and reasons.
13
+ */
14
+ export function computeDomainQualityModifier(domain, artifactMetadata) {
15
+ if (!domain || !artifactMetadata)
16
+ return { delta: 0, reasons: [] };
17
+ let delta = 0;
18
+ const reasons = [];
19
+ const meta = artifactMetadata;
20
+ // Helper to check nested dotted paths or flat keys
21
+ const has = (key) => {
22
+ if (key in meta && meta[key] != null) {
23
+ const v = meta[key];
24
+ if (typeof v === "string")
25
+ return v.trim().length > 0;
26
+ if (Array.isArray(v))
27
+ return v.length > 0;
28
+ return true;
29
+ }
30
+ const parts = key.split(".");
31
+ let cur = meta;
32
+ for (const p of parts) {
33
+ if (cur == null || typeof cur !== "object")
34
+ return false;
35
+ cur = cur[p];
36
+ }
37
+ if (cur == null)
38
+ return false;
39
+ if (typeof cur === "string")
40
+ return cur.trim().length > 0;
41
+ if (Array.isArray(cur))
42
+ return cur.length > 0;
43
+ return true;
44
+ };
45
+ switch (domain) {
46
+ case "engineering":
47
+ if (has("verification.tests_passed") || has("verification")) {
48
+ delta += 1;
49
+ reasons.push("Engineering artifact includes test verification.");
50
+ }
51
+ if (!has("commit_sha")) {
52
+ delta -= 1;
53
+ reasons.push("Engineering artifact missing commit_sha.");
54
+ }
55
+ break;
56
+ case "product":
57
+ if (has("acceptance_criteria")) {
58
+ delta += 1;
59
+ reasons.push("Product artifact includes acceptance criteria.");
60
+ }
61
+ if (!has("success_metric")) {
62
+ delta -= 1;
63
+ reasons.push("Product artifact missing success metric.");
64
+ }
65
+ break;
66
+ case "design":
67
+ if (has("evidence_url")) {
68
+ delta += 1;
69
+ reasons.push("Design artifact includes evidence URL.");
70
+ }
71
+ if (!has("tokens_referenced")) {
72
+ delta -= 1;
73
+ reasons.push("Design artifact missing token references.");
74
+ }
75
+ break;
76
+ case "marketing":
77
+ if (has("measurement_hook")) {
78
+ delta += 1;
79
+ reasons.push("Marketing artifact includes measurement hook.");
80
+ }
81
+ if (!has("audience")) {
82
+ delta -= 1;
83
+ reasons.push("Marketing artifact missing target audience.");
84
+ }
85
+ break;
86
+ case "sales":
87
+ if (has("next_action")) {
88
+ delta += 1;
89
+ reasons.push("Sales artifact includes next action.");
90
+ }
91
+ if (!has("buyer_stage")) {
92
+ delta -= 1;
93
+ reasons.push("Sales artifact missing buyer stage.");
94
+ }
95
+ break;
96
+ case "operations":
97
+ if (has("rollback_path")) {
98
+ delta += 1;
99
+ reasons.push("Operations artifact includes rollback path.");
100
+ }
101
+ if (!has("affected_systems")) {
102
+ delta -= 1;
103
+ reasons.push("Operations artifact missing affected systems.");
104
+ }
105
+ break;
106
+ case "orchestration":
107
+ if (has("unblocked_work")) {
108
+ delta += 1;
109
+ reasons.push("Orchestration artifact includes unblocked work.");
110
+ }
111
+ if (!has("rationale")) {
112
+ delta -= 1;
113
+ reasons.push("Orchestration artifact missing rationale.");
114
+ }
115
+ break;
116
+ }
117
+ return { delta, reasons };
118
+ }
119
+ export function computeRetroQualityRubricScore(input) {
120
+ let score = input.success ? 5 : 2;
121
+ const reasons = [];
122
+ if (input.hadError || (input.errorMessage?.trim() ?? "").length > 0) {
123
+ score -= 1;
124
+ reasons.push("Run ended with error signal.");
125
+ }
126
+ const followUpsCount = toNonNegativeCount(input.followUpsCount);
127
+ if (!input.success && followUpsCount < 1) {
128
+ score -= 1;
129
+ reasons.push("Failure run missing actionable follow-up.");
130
+ }
131
+ const decisionsCount = toNonNegativeCount(input.decisionsCount);
132
+ if (!input.success && decisionsCount < 1) {
133
+ score -= 1;
134
+ reasons.push("Failure run missing decision signal.");
135
+ }
136
+ const wrongCount = toNonNegativeCount(input.whatWentWrongCount);
137
+ if (input.success && wrongCount > 0) {
138
+ score -= 1;
139
+ reasons.push("Success run still reported retrospective issues.");
140
+ }
141
+ const tokens = toFiniteNumber(input.tokens);
142
+ if (tokens === null || tokens <= 0) {
143
+ score -= 1;
144
+ reasons.push("Missing or invalid token telemetry.");
145
+ }
146
+ const costUsd = toFiniteNumber(input.costUsd);
147
+ if (costUsd !== null && costUsd > 10) {
148
+ score -= 1;
149
+ reasons.push("Run cost exceeded preferred threshold ($10).");
150
+ }
151
+ // Domain-specific modifiers (stacks with generic signals)
152
+ const domainMod = computeDomainQualityModifier(input.domain, input.artifactMetadata);
153
+ score += domainMod.delta;
154
+ reasons.push(...domainMod.reasons);
155
+ const normalized = Math.max(1, Math.min(5, Math.round(score)));
156
+ if (reasons.length === 0) {
157
+ reasons.push("Outcome met baseline quality rubric expectations.");
158
+ }
159
+ return { score: normalized, reasons };
160
+ }
161
+ export async function computeRetroQualityWithLlm(input) {
162
+ const lines = [
163
+ `Outcome: ${input.success ? "success" : "failure"}`,
164
+ `Error present: ${input.hadError || (input.errorMessage?.trim() ?? "").length > 0 ? "yes" : "no"}`,
165
+ ];
166
+ if (input.errorMessage?.trim()) {
167
+ lines.push(`Error message: ${input.errorMessage.trim()}`);
168
+ }
169
+ const tokens = toFiniteNumber(input.tokens);
170
+ if (tokens !== null)
171
+ lines.push(`Tokens used: ${tokens}`);
172
+ const costUsd = toFiniteNumber(input.costUsd);
173
+ if (costUsd !== null)
174
+ lines.push(`Cost (USD): ${costUsd.toFixed(4)}`);
175
+ const decisionsCount = toNonNegativeCount(input.decisionsCount);
176
+ lines.push(`Decisions recorded: ${decisionsCount}`);
177
+ const followUpsCount = toNonNegativeCount(input.followUpsCount);
178
+ lines.push(`Follow-ups recorded: ${followUpsCount}`);
179
+ const issuesCount = toNonNegativeCount(input.whatWentWrongCount);
180
+ lines.push(`Issues reported: ${issuesCount}`);
181
+ if (input.executionContext?.trim()) {
182
+ lines.push(`Execution context: ${input.executionContext.trim()}`);
183
+ }
184
+ const userPrompt = lines.join("\n");
185
+ const systemPrompt = "Score this autonomous agent run on a 1-5 quality scale. Consider: task completion, error handling, resource efficiency, follow-up quality, and decision signals. Return JSON: {\"score\": <1-5>, \"reasons\": [\"...\", ...]}. Each reason should be specific and actionable, not generic.";
186
+ const { result, source } = await callLlmJson({
187
+ taskId: "quality_rubric",
188
+ systemPrompt,
189
+ userPrompt,
190
+ model: "openai/gpt-4.1-nano",
191
+ maxTokens: 256,
192
+ cacheTtlMs: 12 * 60 * 60_000,
193
+ }, (raw) => {
194
+ try {
195
+ const parsed = JSON.parse(raw);
196
+ const score = parsed.score;
197
+ if (typeof score !== "number" || !Number.isInteger(score) || score < 1 || score > 5) {
198
+ return null;
199
+ }
200
+ const reasons = parsed.reasons;
201
+ if (!Array.isArray(reasons) ||
202
+ reasons.length === 0 ||
203
+ !reasons.every((r) => typeof r === "string" && r.length > 0)) {
204
+ return null;
205
+ }
206
+ return { score, reasons };
207
+ }
208
+ catch {
209
+ return null;
210
+ }
211
+ }, () => computeRetroQualityRubricScore(input));
212
+ return { ...result, source };
213
+ }
@@ -0,0 +1,18 @@
1
+ type CleanupLogger = {
2
+ info?: (message: string, meta?: Record<string, unknown>) => void;
3
+ warn?: (message: string, meta?: Record<string, unknown>) => void;
4
+ };
5
+ export declare function cleanupOrgxRuntime(logger?: CleanupLogger): Promise<{
6
+ watchdog: {
7
+ pid: number | null;
8
+ wasRunning: boolean;
9
+ stopped: boolean;
10
+ };
11
+ runs: {
12
+ attempted: number;
13
+ stopped: number;
14
+ failed: number;
15
+ markedStopped: number;
16
+ };
17
+ }>;
18
+ export {};
@@ -0,0 +1,87 @@
1
+ import { pathToFileURL } from "node:url";
2
+ import { markAgentRunStopped, readAgentRuns } from "./agent-run-store.js";
3
+ import { stopGatewayWatchdog } from "./gateway-watchdog.js";
4
+ function isPidAlive(pid) {
5
+ if (!Number.isFinite(pid) || pid <= 0)
6
+ return false;
7
+ try {
8
+ process.kill(pid, 0);
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ function sendSignal(pid, signal) {
16
+ try {
17
+ process.kill(-pid, signal);
18
+ return;
19
+ }
20
+ catch {
21
+ // Fall back to direct process kill.
22
+ }
23
+ try {
24
+ process.kill(pid, signal);
25
+ }
26
+ catch {
27
+ // best effort
28
+ }
29
+ }
30
+ async function stopDetachedPid(pid) {
31
+ if (!isPidAlive(pid))
32
+ return true;
33
+ sendSignal(pid, "SIGTERM");
34
+ await new Promise((resolve) => setTimeout(resolve, 450));
35
+ if (isPidAlive(pid)) {
36
+ sendSignal(pid, "SIGKILL");
37
+ await new Promise((resolve) => setTimeout(resolve, 200));
38
+ }
39
+ return !isPidAlive(pid);
40
+ }
41
+ export async function cleanupOrgxRuntime(logger = console) {
42
+ const watchdog = await stopGatewayWatchdog(logger);
43
+ const runningRuns = Object.values(readAgentRuns().runs ?? {}).filter((run) => run?.status === "running");
44
+ let attempted = 0;
45
+ let stopped = 0;
46
+ let failed = 0;
47
+ let markedStopped = 0;
48
+ for (const run of runningRuns) {
49
+ if (!run || typeof run !== "object")
50
+ continue;
51
+ attempted += 1;
52
+ let runStopped = false;
53
+ if (typeof run.pid === "number" && Number.isFinite(run.pid) && run.pid > 0) {
54
+ runStopped = await stopDetachedPid(run.pid);
55
+ }
56
+ else {
57
+ runStopped = true;
58
+ }
59
+ if (runStopped)
60
+ stopped += 1;
61
+ else
62
+ failed += 1;
63
+ if (markAgentRunStopped(run.runId)) {
64
+ markedStopped += 1;
65
+ }
66
+ }
67
+ const summary = {
68
+ watchdog,
69
+ runs: { attempted, stopped, failed, markedStopped },
70
+ };
71
+ logger.info?.("[orgx] Runtime cleanup summary", summary);
72
+ return summary;
73
+ }
74
+ function isDirectRun() {
75
+ const entry = process.argv[1];
76
+ if (!entry)
77
+ return false;
78
+ return import.meta.url === pathToFileURL(entry).href;
79
+ }
80
+ if (isDirectRun()) {
81
+ cleanupOrgxRuntime().catch((err) => {
82
+ const message = err instanceof Error ? err.message : String(err);
83
+ console.error(`[orgx] runtime cleanup failed: ${message}`);
84
+ // Never block uninstall/update for best-effort cleanup.
85
+ process.exitCode = 0;
86
+ });
87
+ }
@@ -15,6 +15,17 @@ export interface RegisterSyncServiceDeps {
15
15
  started: boolean;
16
16
  pid?: number | null;
17
17
  };
18
+ stopGatewayWatchdog?: () => Promise<{
19
+ pid: number | null;
20
+ wasRunning: boolean;
21
+ stopped: boolean;
22
+ }>;
23
+ stopTrackedAgentRuns?: () => Promise<{
24
+ attempted: number;
25
+ stopped: number;
26
+ failed: number;
27
+ markedStopped: number;
28
+ }>;
18
29
  doSync: () => Promise<void>;
19
30
  scheduleNextSync: () => void;
20
31
  setSyncServiceRunning: (running: boolean) => void;