@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
@@ -1,4 +1,14 @@
1
1
  import { pickNumber, pickString, toIsoString } from "./value-utils.js";
2
+ export const SLICE_SCOPE_MAX_TASKS = {
3
+ task: 6,
4
+ milestone: 15,
5
+ workstream: 30,
6
+ };
7
+ export const SLICE_SCOPE_TIMEOUT_MULTIPLIER = {
8
+ task: 1,
9
+ milestone: 2.5,
10
+ workstream: 4,
11
+ };
2
12
  export const ORGX_SKILL_BY_DOMAIN = {
3
13
  engineering: "orgx-engineering-agent",
4
14
  product: "orgx-product-agent",
@@ -15,6 +25,57 @@ function safeErrorMessage(err) {
15
25
  return err;
16
26
  return "Unexpected error";
17
27
  }
28
+ function toNullableBoolean(value) {
29
+ if (typeof value === "boolean")
30
+ return value;
31
+ if (typeof value === "number") {
32
+ if (!Number.isFinite(value))
33
+ return null;
34
+ if (value === 1)
35
+ return true;
36
+ if (value === 0)
37
+ return false;
38
+ return null;
39
+ }
40
+ if (typeof value !== "string")
41
+ return null;
42
+ const normalized = value.trim().toLowerCase();
43
+ if (!normalized)
44
+ return null;
45
+ if (["true", "1", "yes", "y", "on", "required"].includes(normalized))
46
+ return true;
47
+ if (["false", "0", "no", "n", "off"].includes(normalized))
48
+ return false;
49
+ return null;
50
+ }
51
+ function normalizeBehaviorAutomationLevel(value) {
52
+ if (typeof value !== "string")
53
+ return null;
54
+ const normalized = value
55
+ .trim()
56
+ .toLowerCase()
57
+ .replace(/[\s-]+/g, "_");
58
+ if (!normalized)
59
+ return null;
60
+ if (normalized === "manual" ||
61
+ normalized === "manual_only" ||
62
+ normalized === "human" ||
63
+ normalized === "human_only") {
64
+ return "manual";
65
+ }
66
+ if (normalized === "supervised" ||
67
+ normalized === "constrained" ||
68
+ normalized === "reviewed" ||
69
+ normalized === "human_review") {
70
+ return "supervised";
71
+ }
72
+ if (normalized === "auto" ||
73
+ normalized === "autonomous" ||
74
+ normalized === "default") {
75
+ return "auto";
76
+ }
77
+ return null;
78
+ }
18
79
  export function readBudgetEnvNumber(name, fallback, bounds = {}) {
19
80
  const raw = process.env[name];
20
81
  if (typeof raw !== "string" || raw.trim().length === 0)
@@ -232,6 +293,42 @@ function normalizeDependencies(record) {
232
293
  ]);
233
294
  return dedupeStrings([...direct, ...nested]);
234
295
  }
296
+ function toPositiveInteger(value) {
297
+ if (typeof value === "number" && Number.isFinite(value)) {
298
+ const normalized = Math.floor(value);
299
+ return normalized > 0 ? normalized : null;
300
+ }
301
+ if (typeof value === "string" && value.trim().length > 0) {
302
+ const parsed = Number(value);
303
+ if (!Number.isFinite(parsed))
304
+ return null;
305
+ const normalized = Math.floor(parsed);
306
+ return normalized > 0 ? normalized : null;
307
+ }
308
+ return null;
309
+ }
310
+ function normalizeSliceScopePreference(value) {
311
+ if (typeof value !== "string")
312
+ return null;
313
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
314
+ if (!normalized)
315
+ return null;
316
+ if (normalized === "adaptive" || normalized === "task" || normalized === "milestone" || normalized === "workstream") {
317
+ return normalized;
318
+ }
319
+ return null;
320
+ }
321
+ function normalizeDependencyMode(value) {
322
+ if (typeof value !== "string")
323
+ return null;
324
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_");
325
+ if (!normalized)
326
+ return null;
327
+ if (normalized === "strict" || normalized === "relaxed") {
328
+ return normalized;
329
+ }
330
+ return null;
331
+ }
235
332
  function normalizeAssignedAgents(record) {
236
333
  const metadata = getRecordMetadata(record);
237
334
  const ids = dedupeStrings([
@@ -350,6 +447,82 @@ function toMissionControlNode(type, entity, fallbackInitiativeId) {
350
447
  : extractedBudget
351
448
  : DEFAULT_BUDGET_USD[type]);
352
449
  const priority = normalizePriorityForEntity(record);
450
+ const behaviorConfigId = pickString(record, ["behavior_config_id", "behaviorConfigId"]) ??
451
+ pickString(metadata, ["behavior_config_id", "behaviorConfigId"]);
452
+ const behaviorConfigVersion = pickString(record, ["behavior_config_version", "behaviorConfigVersion"]) ??
453
+ pickString(metadata, ["behavior_config_version", "behaviorConfigVersion"]);
454
+ const behaviorConfigHash = pickString(record, ["behavior_config_hash", "behaviorConfigHash"]) ??
455
+ pickString(metadata, ["behavior_config_hash", "behaviorConfigHash"]);
456
+ const behaviorPolicySource = pickString(record, ["policy_source", "policySource"]) ??
457
+ pickString(metadata, ["policy_source", "policySource"]);
458
+ const behaviorContext = pickString(record, ["behavior_context", "behaviorContext", "behavior_prompt", "behaviorPrompt"]) ??
459
+ pickString(metadata, ["behavior_context", "behaviorContext", "behavior_prompt", "behaviorPrompt"]);
460
+ const behaviorRequiresApproval = toNullableBoolean(record.behavior_requires_approval ??
461
+ record.behaviorRequiresApproval ??
462
+ record.config_requires_approval ??
463
+ record.configRequiresApproval ??
464
+ record.requires_approval ??
465
+ record.requiresApproval) ??
466
+ toNullableBoolean(metadata.behavior_requires_approval ??
467
+ metadata.behaviorRequiresApproval ??
468
+ metadata.config_requires_approval ??
469
+ metadata.configRequiresApproval ??
470
+ metadata.requires_approval ??
471
+ metadata.requiresApproval);
472
+ const behaviorApprovalStatus = pickString(record, ["behavior_approval_status", "behaviorApprovalStatus", "approval_status", "approvalStatus"]) ??
473
+ pickString(metadata, [
474
+ "behavior_approval_status",
475
+ "behaviorApprovalStatus",
476
+ "approval_status",
477
+ "approvalStatus",
478
+ ]);
479
+ const behaviorApprovalDecisionId = pickString(record, [
480
+ "behavior_approval_decision_id",
481
+ "behaviorApprovalDecisionId",
482
+ "approval_decision_id",
483
+ "approvalDecisionId",
484
+ ]) ??
485
+ pickString(metadata, [
486
+ "behavior_approval_decision_id",
487
+ "behaviorApprovalDecisionId",
488
+ "approval_decision_id",
489
+ "approvalDecisionId",
490
+ ]);
491
+ const behaviorAutomationLevel = normalizeBehaviorAutomationLevel(pickString(record, ["automation_level", "automationLevel"])) ??
492
+ normalizeBehaviorAutomationLevel(pickString(metadata, ["automation_level", "automationLevel"]));
493
+ const sliceScopePreference = normalizeSliceScopePreference(pickString(record, [
494
+ "slice_scope_preference",
495
+ "sliceScopePreference",
496
+ "scope_preference",
497
+ "scopePreference",
498
+ ])) ??
499
+ normalizeSliceScopePreference(pickString(metadata, [
500
+ "slice_scope_preference",
501
+ "sliceScopePreference",
502
+ "scope_preference",
503
+ "scopePreference",
504
+ ]));
505
+ const maxSliceTasks = toPositiveInteger(pickNumber(record, ["max_slice_tasks", "maxSliceTasks", "slice_max_tasks", "sliceMaxTasks"])) ??
506
+ toPositiveInteger(pickNumber(metadata, ["max_slice_tasks", "maxSliceTasks", "slice_max_tasks", "sliceMaxTasks"]));
507
+ const maxParallelAgents = toPositiveInteger(pickNumber(record, [
508
+ "max_parallel_agents",
509
+ "maxParallelAgents",
510
+ "parallel_agents_max",
511
+ "parallelAgentsMax",
512
+ ])) ??
513
+ toPositiveInteger(pickNumber(metadata, [
514
+ "max_parallel_agents",
515
+ "maxParallelAgents",
516
+ "parallel_agents_max",
517
+ "parallelAgentsMax",
518
+ ]));
519
+ const dependencyMode = normalizeDependencyMode(pickString(record, ["dependency_mode", "dependencyMode", "slice_dependency_mode", "sliceDependencyMode"])) ??
520
+ normalizeDependencyMode(pickString(metadata, [
521
+ "dependency_mode",
522
+ "dependencyMode",
523
+ "slice_dependency_mode",
524
+ "sliceDependencyMode",
525
+ ]));
353
526
  return {
354
527
  id: String(record.id ?? ""),
355
528
  type,
@@ -368,6 +541,19 @@ function toMissionControlNode(type, entity, fallbackInitiativeId) {
368
541
  expectedDurationHours: expectedDuration > 0 ? expectedDuration : DEFAULT_DURATION_HOURS[type],
369
542
  expectedBudgetUsd: expectedBudget >= 0 ? expectedBudget : DEFAULT_BUDGET_USD[type],
370
543
  assignedAgents: normalizeAssignedAgents(record),
544
+ behaviorConfigId: behaviorConfigId ?? null,
545
+ behaviorConfigVersion: behaviorConfigVersion ?? null,
546
+ behaviorConfigHash: behaviorConfigHash ?? null,
547
+ behaviorPolicySource: behaviorPolicySource ?? null,
548
+ behaviorContext: behaviorContext ?? null,
549
+ behaviorRequiresApproval,
550
+ behaviorApprovalStatus: behaviorApprovalStatus ?? null,
551
+ behaviorApprovalDecisionId: behaviorApprovalDecisionId ?? null,
552
+ behaviorAutomationLevel: behaviorAutomationLevel ?? null,
553
+ sliceScopePreference: sliceScopePreference ?? null,
554
+ maxSliceTasks: maxSliceTasks ?? null,
555
+ maxParallelAgents: maxParallelAgents ?? null,
556
+ dependencyMode: dependencyMode ?? null,
371
557
  updatedAt: toIsoString(pickString(record, [
372
558
  "updated_at",
373
559
  "updatedAt",
@@ -538,11 +724,54 @@ export async function buildMissionControlGraph(client, initiativeId, options) {
538
724
  candidate.to === edge.to &&
539
725
  candidate.kind === edge.kind) === index);
540
726
  const cyclicEdgeKeys = detectCycleEdgeKeys(edges);
727
+ const cycleDiagnostics = cyclicEdgeKeys.size > 0
728
+ ? {
729
+ detected: true,
730
+ cycleEdgeCount: cyclicEdgeKeys.size,
731
+ removedEdges: [],
732
+ affectedNodes: [],
733
+ }
734
+ : null;
541
735
  if (cyclicEdgeKeys.size > 0) {
542
736
  degraded.push(`Detected ${cyclicEdgeKeys.size} cyclic dependency edge(s); excluded from ETA graph.`);
737
+ if (cycleDiagnostics) {
738
+ const removedEdges = Array.from(cyclicEdgeKeys.values())
739
+ .map((key) => {
740
+ const [from, to] = key.split("->", 2);
741
+ if (!from || !to)
742
+ return null;
743
+ return { from, to };
744
+ })
745
+ .filter((entry) => Boolean(entry));
746
+ cycleDiagnostics.removedEdges = removedEdges;
747
+ }
543
748
  edges = edges.filter((edge) => !cyclicEdgeKeys.has(`${edge.from}->${edge.to}`));
749
+ const affectedNodesById = new Map();
544
750
  for (const node of nodes) {
545
- node.dependencyIds = node.dependencyIds.filter((depId) => !cyclicEdgeKeys.has(`${depId}->${node.id}`));
751
+ const removed = node.dependencyIds.filter((depId) => cyclicEdgeKeys.has(`${depId}->${node.id}`));
752
+ if (removed.length > 0) {
753
+ const existing = affectedNodesById.get(node.id) ?? {
754
+ nodeId: node.id,
755
+ nodeType: node.type,
756
+ removedDependencyIds: new Set(),
757
+ };
758
+ for (const depId of removed) {
759
+ existing.removedDependencyIds.add(depId);
760
+ }
761
+ affectedNodesById.set(node.id, existing);
762
+ }
763
+ node.dependencyIds = node.dependencyIds.filter((depId) => !removed.includes(depId));
764
+ }
765
+ if (cycleDiagnostics) {
766
+ cycleDiagnostics.affectedNodes = Array.from(affectedNodesById.values()).map((entry) => {
767
+ const remaining = nodeMap.get(entry.nodeId)?.dependencyIds ?? [];
768
+ return {
769
+ nodeId: entry.nodeId,
770
+ nodeType: entry.nodeType,
771
+ removedDependencyIds: Array.from(entry.removedDependencyIds.values()),
772
+ remainingDependencyIds: [...remaining],
773
+ };
774
+ });
546
775
  }
547
776
  }
548
777
  const etaMemo = new Map();
@@ -653,6 +882,7 @@ export async function buildMissionControlGraph(client, initiativeId, options) {
653
882
  edges,
654
883
  recentTodos,
655
884
  degraded,
885
+ ...(cycleDiagnostics ? { cycleDiagnostics } : {}),
656
886
  };
657
887
  }
658
888
  export function normalizeEntityMutationPayload(payload) {
@@ -854,6 +1084,106 @@ export function inferExecutionDomainFromText(...values) {
854
1084
  return "orchestration";
855
1085
  return "engineering";
856
1086
  }
1087
+ // ---------------------------------------------------------------------------
1088
+ // Per-scope task selection for autopilot slices
1089
+ // ---------------------------------------------------------------------------
1090
+ export function selectSliceTasksByScope(input) {
1091
+ const { scope, workstreamId, nodeById, includeVerification } = input;
1092
+ const cap = SLICE_SCOPE_MAX_TASKS[scope];
1093
+ const taskIsReady = (node) => node.dependencyIds.every((depId) => {
1094
+ const dep = nodeById.get(depId);
1095
+ return dep ? isDoneStatus(dep.status) : true;
1096
+ });
1097
+ const taskHasBlockedParent = (node) => {
1098
+ const milestone = node.milestoneId ? nodeById.get(node.milestoneId) ?? null : null;
1099
+ const workstream = node.workstreamId ? nodeById.get(node.workstreamId) ?? null : null;
1100
+ return (milestone?.status?.toLowerCase() === "blocked" ||
1101
+ workstream?.status?.toLowerCase() === "blocked");
1102
+ };
1103
+ const isEligible = (node) => Boolean(node &&
1104
+ node.type === "task" &&
1105
+ isTodoStatus(node.status) &&
1106
+ taskIsReady(node) &&
1107
+ !taskHasBlockedParent(node) &&
1108
+ (includeVerification || !/^verification[ \t]+scenario/i.test(String(node.title ?? ""))));
1109
+ if (scope === "milestone") {
1110
+ // Pick tasks from a specific milestone (or the first milestone with ready tasks)
1111
+ const targetMilestoneId = input.milestoneId ?? null;
1112
+ if (targetMilestoneId) {
1113
+ const tasks = input.recentTodos
1114
+ .map((id) => nodeById.get(id))
1115
+ .filter((node) => Boolean(node) &&
1116
+ node.workstreamId === workstreamId &&
1117
+ node.milestoneId === targetMilestoneId &&
1118
+ isEligible(node))
1119
+ .slice(0, cap);
1120
+ return { tasks, milestoneIds: tasks.length > 0 ? [targetMilestoneId] : [] };
1121
+ }
1122
+ // Find first milestone with ready tasks
1123
+ for (const todoId of input.recentTodos) {
1124
+ const node = nodeById.get(todoId);
1125
+ if (!node || node.workstreamId !== workstreamId || !node.milestoneId || !isEligible(node))
1126
+ continue;
1127
+ const msId = node.milestoneId;
1128
+ const tasks = input.recentTodos
1129
+ .map((id) => nodeById.get(id))
1130
+ .filter((n) => Boolean(n) && n.workstreamId === workstreamId && n.milestoneId === msId && isEligible(n))
1131
+ .slice(0, cap);
1132
+ return { tasks, milestoneIds: [msId] };
1133
+ }
1134
+ return { tasks: [], milestoneIds: [] };
1135
+ }
1136
+ if (scope === "workstream") {
1137
+ const milestoneIdSet = new Set();
1138
+ const tasks = input.recentTodos
1139
+ .map((id) => nodeById.get(id))
1140
+ .filter((node) => Boolean(node) && node.workstreamId === workstreamId && isEligible(node))
1141
+ .slice(0, cap);
1142
+ for (const t of tasks) {
1143
+ if (t.milestoneId)
1144
+ milestoneIdSet.add(t.milestoneId);
1145
+ }
1146
+ return { tasks, milestoneIds: Array.from(milestoneIdSet) };
1147
+ }
1148
+ // Default: task scope — current behavior
1149
+ const tasks = input.recentTodos
1150
+ .map((id) => nodeById.get(id))
1151
+ .filter((node) => Boolean(node) && node.workstreamId === workstreamId && isEligible(node))
1152
+ .slice(0, cap);
1153
+ const milestoneIdSet = new Set();
1154
+ for (const t of tasks) {
1155
+ if (t.milestoneId)
1156
+ milestoneIdSet.add(t.milestoneId);
1157
+ }
1158
+ return { tasks, milestoneIds: Array.from(milestoneIdSet) };
1159
+ }
1160
+ // ---------------------------------------------------------------------------
1161
+ // Scope completion evaluation
1162
+ // ---------------------------------------------------------------------------
1163
+ export function evaluateScopeCompletion(input) {
1164
+ const { scope, milestoneIds, workstreamId, nodeById } = input;
1165
+ if (scope === "task") {
1166
+ return { scopeComplete: true, remainingTasks: 0 };
1167
+ }
1168
+ let remaining = 0;
1169
+ for (const [, node] of nodeById) {
1170
+ if (node.type !== "task")
1171
+ continue;
1172
+ if (isDoneStatus(node.status))
1173
+ continue;
1174
+ if (scope === "milestone") {
1175
+ if (node.milestoneId && milestoneIds.includes(node.milestoneId)) {
1176
+ remaining += 1;
1177
+ }
1178
+ }
1179
+ else if (scope === "workstream") {
1180
+ if (node.workstreamId === workstreamId) {
1181
+ remaining += 1;
1182
+ }
1183
+ }
1184
+ }
1185
+ return { scopeComplete: remaining === 0, remainingTasks: remaining };
1186
+ }
857
1187
  export function deriveExecutionPolicy(taskNode, workstreamNode) {
858
1188
  const domainCandidate = taskNode.assignedAgents
859
1189
  .map((agent) => normalizeExecutionDomain(agent.domain))
@@ -866,19 +1196,178 @@ export function deriveExecutionPolicy(taskNode, workstreamNode) {
866
1196
  inferExecutionDomainFromText(taskNode.title, workstreamNode?.title ?? null);
867
1197
  const domain = normalizeExecutionDomain(domainCandidate) ?? "engineering";
868
1198
  const requiredSkill = ORGX_SKILL_BY_DOMAIN[domain] ?? ORGX_SKILL_BY_DOMAIN.engineering;
869
- return { domain, requiredSkills: [requiredSkill] };
1199
+ const profile = taskNode.behaviorConfigId ??
1200
+ workstreamNode?.behaviorConfigId ??
1201
+ null;
1202
+ const sliceScopePreference = taskNode.sliceScopePreference ??
1203
+ workstreamNode?.sliceScopePreference ??
1204
+ null;
1205
+ const maxSliceTasks = taskNode.maxSliceTasks ??
1206
+ workstreamNode?.maxSliceTasks ??
1207
+ null;
1208
+ const maxParallelAgents = taskNode.maxParallelAgents ??
1209
+ workstreamNode?.maxParallelAgents ??
1210
+ null;
1211
+ const dependencyMode = taskNode.dependencyMode ??
1212
+ workstreamNode?.dependencyMode ??
1213
+ null;
1214
+ return {
1215
+ domain,
1216
+ requiredSkills: [requiredSkill],
1217
+ profile,
1218
+ sliceScopePreference,
1219
+ maxSliceTasks,
1220
+ maxParallelAgents,
1221
+ dependencyMode,
1222
+ };
1223
+ }
1224
+ export function deriveBehaviorConfigContext(taskNode, workstreamNode) {
1225
+ const approvalStatusRaw = taskNode.behaviorApprovalStatus ?? workstreamNode?.behaviorApprovalStatus ?? null;
1226
+ const approvalStatus = approvalStatusRaw
1227
+ ? approvalStatusRaw
1228
+ .trim()
1229
+ .toLowerCase()
1230
+ .replace(/[\s-]+/g, "_")
1231
+ : null;
1232
+ const explicitlyRequiresApproval = taskNode.behaviorRequiresApproval ?? workstreamNode?.behaviorRequiresApproval ?? null;
1233
+ const pendingApprovalStatus = approvalStatus === "pending" ||
1234
+ approvalStatus === "requested" ||
1235
+ approvalStatus === "awaiting_approval" ||
1236
+ approvalStatus === "awaiting_review" ||
1237
+ approvalStatus === "in_review" ||
1238
+ approvalStatus === "review_pending" ||
1239
+ approvalStatus === "needs_approval" ||
1240
+ approvalStatus === "open" ||
1241
+ approvalStatus === "queued";
1242
+ const approvedStatus = approvalStatus === "approved" ||
1243
+ approvalStatus === "accepted" ||
1244
+ approvalStatus === "resolved" ||
1245
+ approvalStatus === "completed" ||
1246
+ approvalStatus === "complete";
1247
+ const requiresApproval = explicitlyRequiresApproval === true ? !approvedStatus : pendingApprovalStatus;
1248
+ return {
1249
+ configId: taskNode.behaviorConfigId ?? workstreamNode?.behaviorConfigId ?? null,
1250
+ version: taskNode.behaviorConfigVersion ?? workstreamNode?.behaviorConfigVersion ?? null,
1251
+ hash: taskNode.behaviorConfigHash ?? workstreamNode?.behaviorConfigHash ?? null,
1252
+ policySource: taskNode.behaviorPolicySource ?? workstreamNode?.behaviorPolicySource ?? null,
1253
+ context: taskNode.behaviorContext ?? workstreamNode?.behaviorContext ?? null,
1254
+ requiresApproval,
1255
+ approvalStatus: approvalStatus ?? null,
1256
+ approvalDecisionId: taskNode.behaviorApprovalDecisionId ?? workstreamNode?.behaviorApprovalDecisionId ?? null,
1257
+ };
1258
+ }
1259
+ export function deriveBehaviorAutomationLevel(taskNode, workstreamNode) {
1260
+ return taskNode.behaviorAutomationLevel ?? workstreamNode?.behaviorAutomationLevel ?? "auto";
1261
+ }
1262
+ export function detectBehaviorConfigDrift(input) {
1263
+ const workstream = input.workstreamNode;
1264
+ if (!workstream)
1265
+ return null;
1266
+ const declared = {
1267
+ configId: workstream.behaviorConfigId ?? null,
1268
+ version: workstream.behaviorConfigVersion ?? null,
1269
+ hash: workstream.behaviorConfigHash ?? null,
1270
+ policySource: workstream.behaviorPolicySource ?? null,
1271
+ context: workstream.behaviorContext ?? null,
1272
+ automationLevel: workstream.behaviorAutomationLevel ?? null,
1273
+ };
1274
+ const runtime = {
1275
+ configId: input.behaviorConfig.configId ?? null,
1276
+ version: input.behaviorConfig.version ?? null,
1277
+ hash: input.behaviorConfig.hash ?? null,
1278
+ policySource: input.behaviorConfig.policySource ?? null,
1279
+ context: input.behaviorConfig.context ?? null,
1280
+ automationLevel: input.behaviorAutomationLevel,
1281
+ };
1282
+ const norm = (value) => {
1283
+ if (typeof value !== "string")
1284
+ return null;
1285
+ const trimmed = value.trim();
1286
+ return trimmed.length > 0 ? trimmed : null;
1287
+ };
1288
+ const normContext = (value) => {
1289
+ const normalized = norm(value);
1290
+ if (!normalized)
1291
+ return null;
1292
+ return normalized.replace(/\s+/g, " ");
1293
+ };
1294
+ const normPolicySource = (value) => {
1295
+ const normalized = norm(value);
1296
+ if (!normalized)
1297
+ return null;
1298
+ return normalized.toLowerCase().replace(/[\s-]+/g, "_");
1299
+ };
1300
+ const hasDeclaredConfig = norm(declared.configId) !== null ||
1301
+ norm(declared.version) !== null ||
1302
+ norm(declared.hash) !== null ||
1303
+ norm(declared.policySource) !== null ||
1304
+ normContext(declared.context) !== null ||
1305
+ declared.automationLevel !== null;
1306
+ if (!hasDeclaredConfig)
1307
+ return null;
1308
+ const fields = [];
1309
+ if (norm(declared.configId) !== norm(runtime.configId))
1310
+ fields.push("config_id");
1311
+ if (norm(declared.version) !== norm(runtime.version))
1312
+ fields.push("version");
1313
+ if (norm(declared.hash) !== norm(runtime.hash))
1314
+ fields.push("hash");
1315
+ if (normPolicySource(declared.policySource) !== normPolicySource(runtime.policySource)) {
1316
+ fields.push("policy_source");
1317
+ }
1318
+ if (normContext(declared.context) !== normContext(runtime.context))
1319
+ fields.push("context");
1320
+ if ((declared.automationLevel ?? null) !== runtime.automationLevel)
1321
+ fields.push("automation_level");
1322
+ if (fields.length === 0)
1323
+ return null;
1324
+ return { fields, declared, runtime };
870
1325
  }
871
1326
  export function spawnGuardIsRateLimited(result) {
872
1327
  if (!result || typeof result !== "object")
873
1328
  return false;
874
1329
  const record = result;
875
- const checks = record.checks;
876
- if (!checks || typeof checks !== "object")
877
- return false;
878
- const rateLimit = checks.rateLimit;
879
- if (!rateLimit || typeof rateLimit !== "object")
880
- return false;
881
- return rateLimit.passed === false;
1330
+ const checks = record.checks && typeof record.checks === "object" && !Array.isArray(record.checks)
1331
+ ? record.checks
1332
+ : {};
1333
+ const rateLimitCandidates = [
1334
+ checks.rateLimit,
1335
+ checks.rate_limit,
1336
+ record.rateLimit,
1337
+ record.rate_limit,
1338
+ ].filter((entry) => {
1339
+ return Boolean(entry && typeof entry === "object" && !Array.isArray(entry));
1340
+ });
1341
+ for (const candidate of rateLimitCandidates) {
1342
+ if (candidate.passed === false)
1343
+ return true;
1344
+ if (candidate.rateLimited === true || candidate.rate_limited === true || candidate.limited === true) {
1345
+ return true;
1346
+ }
1347
+ const current = pickNumber(candidate, ["current", "count", "value", "used", "attempts"]) ?? null;
1348
+ const max = pickNumber(candidate, ["max", "limit", "threshold", "allowed"]) ?? null;
1349
+ if (typeof current === "number" &&
1350
+ Number.isFinite(current) &&
1351
+ typeof max === "number" &&
1352
+ Number.isFinite(max) &&
1353
+ max > 0 &&
1354
+ current >= max) {
1355
+ return true;
1356
+ }
1357
+ }
1358
+ if (record.rateLimited === true || record.rate_limited === true)
1359
+ return true;
1360
+ const blockedReason = pickString(record, [
1361
+ "blockedReason",
1362
+ "blocked_reason",
1363
+ "reason",
1364
+ "message",
1365
+ "error",
1366
+ ]);
1367
+ if (blockedReason && /\brate[ -]?limit(?:ed)?\b|\btoo many requests\b/i.test(blockedReason)) {
1368
+ return true;
1369
+ }
1370
+ return false;
882
1371
  }
883
1372
  export function summarizeSpawnGuardBlockReason(result) {
884
1373
  if (!result || typeof result !== "object")
@@ -0,0 +1,23 @@
1
+ export type SentinelDomain = "engineering" | "sales" | "product" | "operations" | "marketing";
2
+ export type BuiltInSentinel = {
3
+ id: string;
4
+ domain: SentinelDomain;
5
+ name: string;
6
+ summary: string;
7
+ signal: "error_log" | "ci_failure" | "dependency_scan" | "accessibility_audit" | "deal_stagnation" | "lead_response" | "cost_anomaly" | "sla_breach" | "content_performance" | "budget_monitor";
8
+ severity: "high" | "medium";
9
+ schedule: {
10
+ cadence: "realtime" | "hourly";
11
+ windowMinutes: number;
12
+ };
13
+ trigger: {
14
+ operator: "gt" | "eq";
15
+ threshold: number;
16
+ unit: "events" | "failures" | "findings" | "hours" | "minutes" | "percent";
17
+ };
18
+ defaultAction: string;
19
+ };
20
+ export declare function listBuiltInSentinels(input?: {
21
+ domain?: string | null;
22
+ signal?: string | null;
23
+ }): BuiltInSentinel[];