@kontextmind/kxm 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/.claude-plugin/marketplace.json +19 -0
  2. package/.kxm/README.md +14 -0
  3. package/.kxm/assets/README.md +5 -0
  4. package/.kxm/assets/retrospectives/README.md +5 -0
  5. package/.kxm/config/README.md +5 -0
  6. package/.kxm/config/agents.json +43 -0
  7. package/.kxm/config/env.example +56 -0
  8. package/.kxm/config/update.example.yaml +9 -0
  9. package/.kxm/config/workflows/fix.json +160 -0
  10. package/.kxm/config/workflows/jira-development.json +116 -0
  11. package/.kxm/config/workflows/provenance-quorum.json +150 -0
  12. package/.kxm/config/workflows/v04-dogfood.json +72 -0
  13. package/CHANGELOG.md +465 -0
  14. package/LICENSE +21 -0
  15. package/README.md +306 -0
  16. package/SECURITY.md +72 -0
  17. package/docs/README.md +48 -0
  18. package/docs/agent-communication-envelopes-and-gates.md +553 -0
  19. package/docs/architecture.md +242 -0
  20. package/docs/assignment-runner.md +241 -0
  21. package/docs/configuration.md +361 -0
  22. package/docs/continuous-improvement.md +114 -0
  23. package/docs/getting-started.md +253 -0
  24. package/docs/kxm-handbook.md +1090 -0
  25. package/docs/operations.md +205 -0
  26. package/docs/provenance-gates.md +291 -0
  27. package/docs/skills.md +45 -0
  28. package/docs/templates/README.md +95 -0
  29. package/docs/templates/adr.md +88 -0
  30. package/docs/templates/architecture.md +120 -0
  31. package/docs/templates/bug-fix.md +109 -0
  32. package/docs/templates/feature.md +108 -0
  33. package/docs/templates/handoff.md +72 -0
  34. package/docs/templates/postmortem.md +77 -0
  35. package/docs/templates/research.md +100 -0
  36. package/docs/templates/review.md +85 -0
  37. package/docs/templates/runbook.md +73 -0
  38. package/docs/templates/test-plan.md +87 -0
  39. package/docs/templates/test-report.md +72 -0
  40. package/docs/test-matrix.md +121 -0
  41. package/docs/troubleshooting.md +249 -0
  42. package/docs/vnext/README.md +62 -0
  43. package/docs/vnext/architecture.md +185 -0
  44. package/docs/vnext/effects-and-recovery.md +172 -0
  45. package/docs/vnext/lifecycles.md +235 -0
  46. package/docs/vnext/migration.md +220 -0
  47. package/docs/vnext/routing.md +184 -0
  48. package/docs/vnext/synchronization.md +172 -0
  49. package/docs/vnext/terminology.md +240 -0
  50. package/docs/vnext/validation.md +335 -0
  51. package/docs/webhook-workflows.md +240 -0
  52. package/docs/workflow-guide.md +1150 -0
  53. package/examples/README.md +102 -0
  54. package/examples/provenance-workflow.json +40 -0
  55. package/examples/requester.ts +30 -0
  56. package/examples/reviewer-agent.ts +29 -0
  57. package/examples/roundtrip.ts +46 -0
  58. package/examples/vnext/.kxm/agents/coordinator.yaml +16 -0
  59. package/examples/vnext/.kxm/agents/critic-1.yaml +16 -0
  60. package/examples/vnext/.kxm/agents/critic-2.yaml +15 -0
  61. package/examples/vnext/.kxm/agents/critic-3.yaml +15 -0
  62. package/examples/vnext/.kxm/agents/implementer.yaml +15 -0
  63. package/examples/vnext/.kxm/agents/planner.yaml +13 -0
  64. package/examples/vnext/.kxm/agents/reproducer.yaml +15 -0
  65. package/examples/vnext/.kxm/agents/reviewer.yaml +15 -0
  66. package/examples/vnext/.kxm/gates.yaml +8 -0
  67. package/examples/vnext/.kxm/models/critic-claude.yaml +11 -0
  68. package/examples/vnext/.kxm/models/critic-gemini.yaml +11 -0
  69. package/examples/vnext/.kxm/models/critic-grok.yaml +12 -0
  70. package/examples/vnext/.kxm/models/implementation.yaml +14 -0
  71. package/examples/vnext/.kxm/models/primary.yaml +17 -0
  72. package/examples/vnext/.kxm/prices.yaml +111 -0
  73. package/examples/vnext/.kxm/project/env.yaml +7 -0
  74. package/examples/vnext/.kxm/project.yaml +32 -0
  75. package/examples/vnext/.kxm/repo/repo.yaml +8 -0
  76. package/examples/vnext/.kxm/workflows/default.yaml +92 -0
  77. package/examples/vnext/.kxm/workflows/fix.yaml +376 -0
  78. package/examples/vnext/.kxm/workflows/improve.yaml +57 -0
  79. package/examples/vnext/README.md +53 -0
  80. package/examples/vnext/records/assignment-result-recorded.json +63 -0
  81. package/examples/vnext/records/assignment-result.json +46 -0
  82. package/examples/vnext/records/context-candidate.json +42 -0
  83. package/examples/vnext/records/delivery-manifest.json +66 -0
  84. package/examples/vnext/records/effect-uncertainty-resolved-sync.json +67 -0
  85. package/examples/vnext/records/effect-uncertainty-resolved.json +62 -0
  86. package/examples/vnext/records/run-created.json +54 -0
  87. package/examples/vnext/records/sync-event.json +65 -0
  88. package/examples/vnext/repositories/api/.kxm/repo/env.yaml +7 -0
  89. package/examples/vnext/repositories/api/.kxm/repo/repo.yaml +8 -0
  90. package/examples/vnext/repositories/web/.kxm/repo/repo.yaml +8 -0
  91. package/examples/workflow-signal.ts +63 -0
  92. package/package.json +129 -0
  93. package/plugins/kxm/.claude-plugin/plugin.json +73 -0
  94. package/plugins/kxm/.mcp.json +19 -0
  95. package/plugins/kxm/README.md +93 -0
  96. package/plugins/kxm/dist/cli.js +42853 -0
  97. package/plugins/kxm/dist/client.js +416 -0
  98. package/plugins/kxm/dist/core.js +1823 -0
  99. package/plugins/kxm/dist/extension.js +3797 -0
  100. package/plugins/kxm/dist/mcp-server.js +17104 -0
  101. package/plugins/kxm/dist/runtime.js +23361 -0
  102. package/plugins/kxm/dist/server.js +13640 -0
  103. package/plugins/kxm/dist/vnext-runtime-supervisor.js +21109 -0
  104. package/plugins/kxm/package.json +12 -0
  105. package/plugins/kxm/skills/kxm/SKILL.md +97 -0
  106. package/plugins/kxm/skills/kxm/references/protocol.md +103 -0
  107. package/plugins/kxm/skills/kxm-session/SKILL.md +53 -0
  108. package/plugins/kxm/src/arbiter.ts +355 -0
  109. package/plugins/kxm/src/artifacts-exist.ts +62 -0
  110. package/plugins/kxm/src/autocomplete.ts +236 -0
  111. package/plugins/kxm/src/cli.ts +3707 -0
  112. package/plugins/kxm/src/client.ts +614 -0
  113. package/plugins/kxm/src/commands.ts +1063 -0
  114. package/plugins/kxm/src/config.ts +290 -0
  115. package/plugins/kxm/src/context/providers.ts +101 -0
  116. package/plugins/kxm/src/context-packet.ts +332 -0
  117. package/plugins/kxm/src/context.ts +499 -0
  118. package/plugins/kxm/src/core.ts +6 -0
  119. package/plugins/kxm/src/database.ts +563 -0
  120. package/plugins/kxm/src/diagnostics.ts +184 -0
  121. package/plugins/kxm/src/envelope.ts +118 -0
  122. package/plugins/kxm/src/extension.ts +895 -0
  123. package/plugins/kxm/src/external-effects.ts +299 -0
  124. package/plugins/kxm/src/github-watch.ts +255 -0
  125. package/plugins/kxm/src/hub-binding.ts +160 -0
  126. package/plugins/kxm/src/hub.ts +2502 -0
  127. package/plugins/kxm/src/improve.ts +383 -0
  128. package/plugins/kxm/src/inbox.ts +10 -0
  129. package/plugins/kxm/src/kxm-install-kind.ts +113 -0
  130. package/plugins/kxm/src/kxm-update-config.ts +39 -0
  131. package/plugins/kxm/src/kxm-update.ts +238 -0
  132. package/plugins/kxm/src/local-snapshot.ts +406 -0
  133. package/plugins/kxm/src/logger.ts +198 -0
  134. package/plugins/kxm/src/mcp-server.ts +143 -0
  135. package/plugins/kxm/src/memory.ts +385 -0
  136. package/plugins/kxm/src/nous-pi.ts +287 -0
  137. package/plugins/kxm/src/nous-provider.ts +729 -0
  138. package/plugins/kxm/src/price-calc.ts +87 -0
  139. package/plugins/kxm/src/prices.ts +121 -0
  140. package/plugins/kxm/src/protocol.ts +172 -0
  141. package/plugins/kxm/src/recovery.ts +211 -0
  142. package/plugins/kxm/src/redact.ts +26 -0
  143. package/plugins/kxm/src/retrospective.ts +400 -0
  144. package/plugins/kxm/src/routing.ts +830 -0
  145. package/plugins/kxm/src/runtime.ts +9 -0
  146. package/plugins/kxm/src/server.ts +117 -0
  147. package/plugins/kxm/src/session-work.ts +571 -0
  148. package/plugins/kxm/src/session.ts +184 -0
  149. package/plugins/kxm/src/skills.ts +535 -0
  150. package/plugins/kxm/src/state.ts +326 -0
  151. package/plugins/kxm/src/store.ts +637 -0
  152. package/plugins/kxm/src/studio-layout.ts +268 -0
  153. package/plugins/kxm/src/suggest.ts +162 -0
  154. package/plugins/kxm/src/task-manager.ts +244 -0
  155. package/plugins/kxm/src/telemetry.ts +116 -0
  156. package/plugins/kxm/src/tui.ts +1046 -0
  157. package/plugins/kxm/src/vnext-bindings.ts +403 -0
  158. package/plugins/kxm/src/vnext-config.ts +1646 -0
  159. package/plugins/kxm/src/vnext-engine-artifacts.ts +86 -0
  160. package/plugins/kxm/src/vnext-engine-command.ts +533 -0
  161. package/plugins/kxm/src/vnext-engine-compile.ts +722 -0
  162. package/plugins/kxm/src/vnext-engine-evidence.ts +273 -0
  163. package/plugins/kxm/src/vnext-engine-fold.ts +1400 -0
  164. package/plugins/kxm/src/vnext-engine-gate-records.ts +583 -0
  165. package/plugins/kxm/src/vnext-engine-plan.ts +717 -0
  166. package/plugins/kxm/src/vnext-engine.ts +2458 -0
  167. package/plugins/kxm/src/vnext-gate-hash.ts +10 -0
  168. package/plugins/kxm/src/vnext-harness.ts +1142 -0
  169. package/plugins/kxm/src/vnext-init.ts +430 -0
  170. package/plugins/kxm/src/vnext-migrate.ts +1848 -0
  171. package/plugins/kxm/src/vnext-oneshot-producer.ts +424 -0
  172. package/plugins/kxm/src/vnext-permission.ts +936 -0
  173. package/plugins/kxm/src/vnext-pi-producer.ts +628 -0
  174. package/plugins/kxm/src/vnext-repair.ts +1094 -0
  175. package/plugins/kxm/src/vnext-runtime-owner.ts +320 -0
  176. package/plugins/kxm/src/vnext-runtime-store.ts +1560 -0
  177. package/plugins/kxm/src/vnext-runtime-supervisor.ts +586 -0
  178. package/plugins/kxm/src/vnext-runtime.ts +663 -0
  179. package/plugins/kxm/src/vnext-template.ts +247 -0
  180. package/plugins/kxm/src/wiki.ts +313 -0
  181. package/plugins/kxm/src/workflow.ts +1548 -0
  182. package/schemas/vnext/README.md +46 -0
  183. package/schemas/vnext/agent.schema.json +40 -0
  184. package/schemas/vnext/assignment-result.schema.json +66 -0
  185. package/schemas/vnext/backup-manifest.schema.json +89 -0
  186. package/schemas/vnext/candidate.schema.json +109 -0
  187. package/schemas/vnext/common.schema.json +422 -0
  188. package/schemas/vnext/context-candidate.schema.json +76 -0
  189. package/schemas/vnext/context-packet.schema.json +192 -0
  190. package/schemas/vnext/delivery-manifest.schema.json +159 -0
  191. package/schemas/vnext/environment.schema.json +66 -0
  192. package/schemas/vnext/gate-registry.schema.json +109 -0
  193. package/schemas/vnext/handoff-manifest.schema.json +146 -0
  194. package/schemas/vnext/init-operation.schema.json +61 -0
  195. package/schemas/vnext/local-repository-bindings.schema.json +30 -0
  196. package/schemas/vnext/memory-record.schema.json +45 -0
  197. package/schemas/vnext/migration-decision.schema.json +26 -0
  198. package/schemas/vnext/migration-plan.schema.json +123 -0
  199. package/schemas/vnext/migration-receipt.schema.json +52 -0
  200. package/schemas/vnext/model.schema.json +42 -0
  201. package/schemas/vnext/permission-diff.schema.json +57 -0
  202. package/schemas/vnext/prices.schema.json +115 -0
  203. package/schemas/vnext/project.schema.json +85 -0
  204. package/schemas/vnext/repository.schema.json +24 -0
  205. package/schemas/vnext/run-event.schema.json +460 -0
  206. package/schemas/vnext/session-brief.schema.json +153 -0
  207. package/schemas/vnext/sync-event.schema.json +234 -0
  208. package/schemas/vnext/template-provenance.schema.json +38 -0
  209. package/schemas/vnext/workflow.schema.json +248 -0
  210. package/scripts/assignment-run.d.mts +354 -0
  211. package/scripts/assignment-run.mjs +4451 -0
  212. package/scripts/build-runtime.mjs +56 -0
  213. package/scripts/check-generated.mjs +77 -0
  214. package/scripts/check-versions.mjs +34 -0
  215. package/scripts/emit-codex-artifacts.d.mts +9 -0
  216. package/scripts/emit-codex-artifacts.mjs +91 -0
  217. package/scripts/harness-run.d.mts +83 -0
  218. package/scripts/harness-run.mjs +2095 -0
  219. package/scripts/kxm-hub.mjs +105 -0
  220. package/scripts/kxm-publish-npm.mjs +327 -0
  221. package/scripts/kxm-release-github.mjs +472 -0
  222. package/scripts/kxm-runtime-supervisor.mjs +7 -0
  223. package/scripts/kxm-worker.mjs +1127 -0
  224. package/scripts/kxm.mjs +27 -0
  225. package/scripts/roster-policy.d.mts +20 -0
  226. package/scripts/roster-policy.mjs +161 -0
  227. package/scripts/smoke-multi-pi.mjs +479 -0
@@ -0,0 +1,184 @@
1
+ export const DIAGNOSTIC_CLASSES = [
2
+ "command_not_found",
3
+ "typecheck_error",
4
+ "test_failure",
5
+ "timeout",
6
+ "cancelled",
7
+ "workflow_scope",
8
+ "invalid_identity",
9
+ "invalid_auth",
10
+ "signal_mismatch",
11
+ "not_waiting",
12
+ "network",
13
+ "parse_error",
14
+ "unresumable_session",
15
+ "quota",
16
+ "provider_error",
17
+ "unknown",
18
+ ] as const;
19
+
20
+ export type DiagnosticClass = (typeof DIAGNOSTIC_CLASSES)[number];
21
+
22
+ export const DIAGNOSTIC_OPERATIONS = [
23
+ "get",
24
+ "wait",
25
+ "checkpoint",
26
+ "journal",
27
+ "signal",
28
+ "await",
29
+ "other",
30
+ ] as const;
31
+
32
+ export type DiagnosticOperation = (typeof DIAGNOSTIC_OPERATIONS)[number];
33
+
34
+ export const NEXT_ACTIONS = [
35
+ "use_assigned_coordinator",
36
+ "wait_then_checkpoint",
37
+ "record_journal_as_coordinator",
38
+ "reconnect_with_current_agent_key",
39
+ "check_project_token",
40
+ "export_retrospective",
41
+ "post_signal",
42
+ "restart_fresh_session",
43
+ "switch_model_or_retry",
44
+ ] as const;
45
+
46
+ export type NextAction = (typeof NEXT_ACTIONS)[number];
47
+
48
+ export interface Diagnostic {
49
+ class: DiagnosticClass;
50
+ tool: string;
51
+ operation: DiagnosticOperation;
52
+ httpStatus?: number;
53
+ code?: string;
54
+ assignedCoordinatorName?: string;
55
+ nextAction?: NextAction;
56
+ exitCode?: number;
57
+ durationMs?: number;
58
+ }
59
+
60
+ export interface ClassifyFailureInput {
61
+ toolName?: string;
62
+ message?: string;
63
+ code?: string;
64
+ statusCode?: number;
65
+ exitCode?: number;
66
+ durationMs?: number;
67
+ assignedCoordinatorName?: string;
68
+ nextAction?: NextAction;
69
+ }
70
+
71
+ const CODE_TO_CLASS: Record<string, DiagnosticClass> = {
72
+ workflow_forbidden: "workflow_scope",
73
+ invalid_agent_identity: "invalid_identity",
74
+ invalid_auth: "invalid_auth",
75
+ workflow_signal_mismatch: "signal_mismatch",
76
+ workflow_not_waiting: "not_waiting",
77
+ workflow_terminal: "not_waiting",
78
+ workflow_not_running: "not_waiting",
79
+ unresumable_session: "unresumable_session",
80
+ provider_quota: "quota",
81
+ provider_error: "provider_error",
82
+ };
83
+
84
+ export function operationForTool(toolName: string | undefined): DiagnosticOperation {
85
+ switch (toolName) {
86
+ case "kxm_workflow_get":
87
+ case "kxm_workflow_list":
88
+ return "get";
89
+ case "kxm_workflow_wait":
90
+ return "wait";
91
+ case "kxm_workflow_checkpoint":
92
+ return "checkpoint";
93
+ case "kxm_workflow_record":
94
+ return "journal";
95
+ case "kxm_await":
96
+ return "await";
97
+ default:
98
+ return "other";
99
+ }
100
+ }
101
+
102
+ export function areaForTool(toolName: string | undefined): "workflow" | "harness" | "implementation" {
103
+ if (toolName?.startsWith("kxm_workflow_")) return "workflow";
104
+ if (toolName?.startsWith("kxm_")) return "harness";
105
+ return "implementation";
106
+ }
107
+
108
+ export function nextActionForCode(code: string | undefined, operation: DiagnosticOperation): NextAction | undefined {
109
+ if (code === "workflow_forbidden") return "use_assigned_coordinator";
110
+ if (code === "invalid_agent_identity") return "reconnect_with_current_agent_key";
111
+ if (code === "invalid_auth") return "check_project_token";
112
+ if (code === "workflow_not_waiting" || code === "workflow_terminal" || code === "workflow_not_running") {
113
+ return operation === "checkpoint" ? "wait_then_checkpoint" : "export_retrospective";
114
+ }
115
+ if (code === "workflow_signal_mismatch") return "post_signal";
116
+ if (code === "unresumable_session") return "restart_fresh_session";
117
+ if (code === "provider_quota" || code === "provider_error") return "switch_model_or_retry";
118
+ return undefined;
119
+ }
120
+
121
+ function classFromTokens(text: string): DiagnosticClass | undefined {
122
+ const value = text.toLowerCase();
123
+ if (/\b(enoent|not recognized|command not found|is not recognized)\b/.test(value)) return "command_not_found";
124
+ if (/\b(ts\d{3,4}|typecheck|type error)\b/.test(value)) return "typecheck_error";
125
+ if (/\b(test failed|assertionerror|not equal)\b/.test(value)) return "test_failure";
126
+ if (/\b(timed out|timeout|deadline)\b/.test(value)) return "timeout";
127
+ if (/\b(aborted|cancelled|canceled|sigint|sigterm)\b/.test(value)) return "cancelled";
128
+ if (/\b(econnrefused|enotfound|fetch failed|network)\b/.test(value)) return "network";
129
+ if (/\b(invalid json|unexpected token|parse error)\b/.test(value)) return "parse_error";
130
+ if (/\b(invalid_request_error|missing_tool_result|unresumable)\b/.test(value)) return "unresumable_session";
131
+ if (/\b(quota reached|quota exceeded|rate limit(?:ed)?|too many requests|resource exhausted|http 429)\b/.test(value)) return "quota";
132
+ if (/\b(not visible|only the assigned coordinator)\b/.test(value)) return "workflow_scope";
133
+ return undefined;
134
+ }
135
+
136
+ export function classifyFailure(input: ClassifyFailureInput): Diagnostic {
137
+ const tool = input.toolName?.trim() || "unknown";
138
+ const operation = operationForTool(input.toolName);
139
+ const fromCode = input.code ? CODE_TO_CLASS[input.code] : undefined;
140
+ const fromTokens = input.message ? classFromTokens(input.message) : undefined;
141
+ const diagnosticClass = fromCode ?? fromTokens ?? "unknown";
142
+ const messageCoordinator = input.message?.match(/assignedCoordinator=([A-Za-z0-9_.-]{1,64})/)?.[1];
143
+ const messageAction = input.message?.match(/nextAction=([a-z_]{1,64})/)?.[1];
144
+ const parsedAction = NEXT_ACTIONS.includes(messageAction as NextAction) ? messageAction as NextAction : undefined;
145
+ const nextAction = input.nextAction ?? parsedAction ?? nextActionForCode(input.code, operation);
146
+ const assignedCoordinatorName = input.assignedCoordinatorName ?? messageCoordinator;
147
+ return {
148
+ class: diagnosticClass,
149
+ tool,
150
+ operation,
151
+ ...(input.statusCode !== undefined ? { httpStatus: input.statusCode } : {}),
152
+ ...(input.code ? { code: input.code } : {}),
153
+ ...(assignedCoordinatorName ? { assignedCoordinatorName } : {}),
154
+ ...(nextAction ? { nextAction } : {}),
155
+ ...(input.exitCode !== undefined ? { exitCode: input.exitCode } : {}),
156
+ ...(input.durationMs !== undefined ? { durationMs: input.durationMs } : {}),
157
+ };
158
+ }
159
+
160
+ export function diagnosticEvidence(diagnostic: Diagnostic, toolCallId?: string): string[] {
161
+ return [
162
+ `tool:${diagnostic.tool}`,
163
+ ...(toolCallId ? [`tool-call:${toolCallId}`] : []),
164
+ `class:${diagnostic.class}`,
165
+ `operation:${diagnostic.operation}`,
166
+ ...(diagnostic.code ? [`code:${diagnostic.code}`] : []),
167
+ ...(diagnostic.nextAction ? [`nextAction:${diagnostic.nextAction}`] : []),
168
+ ...(diagnostic.assignedCoordinatorName ? [`assignedCoordinator:${diagnostic.assignedCoordinatorName}`] : []),
169
+ ];
170
+ }
171
+
172
+ export function diagnosticSummary(diagnostic: Diagnostic): string {
173
+ const coordinator = diagnostic.assignedCoordinatorName ? `; assigned coordinator: ${diagnostic.assignedCoordinatorName}` : "";
174
+ const next = diagnostic.nextAction ? `; next action: ${diagnostic.nextAction}` : "";
175
+ return `Tool ${diagnostic.tool} failed: ${diagnostic.class}${coordinator}${next}`;
176
+ }
177
+
178
+ export function workflowScopeExtras(operation: DiagnosticOperation, assignedCoordinatorName: string) {
179
+ return {
180
+ operation,
181
+ assignedCoordinatorName,
182
+ nextAction: "use_assigned_coordinator" as const,
183
+ };
184
+ }
@@ -0,0 +1,118 @@
1
+ import { nowIso } from "./protocol.ts";
2
+
3
+ export const WORKER_SCHEMA = "kxm.worker.v1" as const;
4
+ export const WORKER_RESULT_SCHEMA = "kxm.worker-result.v1" as const;
5
+ import { parseRoutingRecord } from "./routing.ts";
6
+
7
+ export type WorkerKind = "agent" | "gate";
8
+ export type WorkerDriver = "ai" | "code";
9
+ export type WorkerOutcome = "passed" | "warning" | "failed" | "running";
10
+
11
+ /** Shared worker base. Agents and gates are both workers; they differ only by driver. */
12
+ export interface WorkerBase {
13
+ schema: typeof WORKER_SCHEMA;
14
+ kind: WorkerKind;
15
+ driver: WorkerDriver;
16
+ name: string;
17
+ project?: string;
18
+ purpose?: string;
19
+ }
20
+
21
+ export interface AgentWorker extends WorkerBase {
22
+ kind: "agent";
23
+ driver: "ai";
24
+ model?: string;
25
+ thinking?: string;
26
+ }
27
+
28
+ export interface GateWorker extends WorkerBase {
29
+ kind: "gate";
30
+ driver: "code";
31
+ }
32
+
33
+ export type Worker = AgentWorker | GateWorker;
34
+
35
+ /** Standard result envelope emitted by every worker, AI or code. */
36
+ export interface WorkerResultEnvelope<T extends Worker = Worker> {
37
+ schema: typeof WORKER_RESULT_SCHEMA;
38
+ worker: T;
39
+ command: string;
40
+ ok: boolean;
41
+ outcome: WorkerOutcome;
42
+ createdAt: string;
43
+ summary: string;
44
+ }
45
+
46
+ export function agentWorker(input: {
47
+ name: string;
48
+ project?: string;
49
+ purpose?: string;
50
+ model?: string;
51
+ thinking?: string;
52
+ }): AgentWorker {
53
+ return {
54
+ schema: WORKER_SCHEMA,
55
+ kind: "agent",
56
+ driver: "ai",
57
+ name: input.name,
58
+ ...(input.project ? { project: input.project } : {}),
59
+ ...(input.purpose ? { purpose: input.purpose } : {}),
60
+ ...(input.model ? { model: input.model } : {}),
61
+ ...(input.thinking ? { thinking: input.thinking } : {}),
62
+ };
63
+ }
64
+
65
+ export function gateWorker(input: {
66
+ name: string;
67
+ project?: string;
68
+ purpose?: string;
69
+ }): GateWorker {
70
+ return {
71
+ schema: WORKER_SCHEMA,
72
+ kind: "gate",
73
+ driver: "code",
74
+ name: input.name,
75
+ ...(input.project ? { project: input.project } : {}),
76
+ ...(input.purpose ? { purpose: input.purpose } : {}),
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Build the standard result envelope. Additive payload keys extend the
82
+ * envelope, but hub-owned identity keys (`schema` and `worker`) are written
83
+ * after the payload spread and cannot be clobbered. Caller-owned `summary`,
84
+ * optional `createdAt`, and optional `outcome` are canonical inputs. An explicit `outcome`
85
+ * must not contradict `ok` ("passed" requires ok: true; "failed" requires
86
+ * ok: false); contradictions throw instead of emitting a lying envelope.
87
+ */
88
+ export function workerResult<T extends Worker, P extends Record<string, unknown>>(
89
+ worker: T,
90
+ payload: P & {
91
+ command: string;
92
+ ok: boolean;
93
+ summary: string;
94
+ outcome?: WorkerOutcome;
95
+ createdAt?: string;
96
+ },
97
+ ): WorkerResultEnvelope<T> & P {
98
+ const { summary, outcome, createdAt, ...rest } = payload;
99
+ if (outcome === "passed" && payload.ok === false) {
100
+ throw new Error("workerResult outcome contradicts ok: \"passed\" requires ok: true");
101
+ }
102
+ if (outcome === "failed" && payload.ok === true) {
103
+ throw new Error("workerResult outcome contradicts ok: \"failed\" requires ok: false");
104
+ }
105
+ // Routing records are validated, not trusted: a malformed or body-bearing
106
+ // routing payload fails closed instead of polluting telemetry.
107
+ if (rest.routing !== undefined) {
108
+ parseRoutingRecord(rest.routing);
109
+ }
110
+ return {
111
+ ...rest,
112
+ schema: WORKER_RESULT_SCHEMA,
113
+ worker,
114
+ createdAt: createdAt ?? nowIso(),
115
+ outcome: outcome ?? (payload.ok ? "passed" : "failed"),
116
+ summary,
117
+ } as WorkerResultEnvelope<T> & P;
118
+ }