@runcore-sh/runcore 0.1.7 → 0.1.9

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 (173) hide show
  1. package/dist/access/manifest.d.ts +59 -0
  2. package/dist/access/manifest.d.ts.map +1 -0
  3. package/dist/access/manifest.js +251 -0
  4. package/dist/access/manifest.js.map +1 -0
  5. package/dist/activity/log.d.ts +1 -1
  6. package/dist/activity/log.d.ts.map +1 -1
  7. package/dist/agents/autonomous.d.ts.map +1 -1
  8. package/dist/agents/autonomous.js +38 -0
  9. package/dist/agents/autonomous.js.map +1 -1
  10. package/dist/agents/governance.d.ts +70 -0
  11. package/dist/agents/governance.d.ts.map +1 -0
  12. package/dist/agents/governance.js +220 -0
  13. package/dist/agents/governance.js.map +1 -0
  14. package/dist/agents/governed-spawn.d.ts +83 -0
  15. package/dist/agents/governed-spawn.d.ts.map +1 -0
  16. package/dist/agents/governed-spawn.js +186 -0
  17. package/dist/agents/governed-spawn.js.map +1 -0
  18. package/dist/agents/heartbeat.d.ts +91 -0
  19. package/dist/agents/heartbeat.d.ts.map +1 -0
  20. package/dist/agents/heartbeat.js +323 -0
  21. package/dist/agents/heartbeat.js.map +1 -0
  22. package/dist/agents/index.d.ts +4 -1
  23. package/dist/agents/index.d.ts.map +1 -1
  24. package/dist/agents/index.js +6 -1
  25. package/dist/agents/index.js.map +1 -1
  26. package/dist/agents/spawn-policy.d.ts +45 -0
  27. package/dist/agents/spawn-policy.d.ts.map +1 -0
  28. package/dist/agents/spawn-policy.js +202 -0
  29. package/dist/agents/spawn-policy.js.map +1 -0
  30. package/dist/alert.d.ts +16 -0
  31. package/dist/alert.d.ts.map +1 -0
  32. package/dist/alert.js +70 -0
  33. package/dist/alert.js.map +1 -0
  34. package/dist/cli.js +35 -27
  35. package/dist/cli.js.map +1 -1
  36. package/dist/credentials/store.d.ts +1 -1
  37. package/dist/credentials/store.d.ts.map +1 -1
  38. package/dist/credentials/store.js +14 -3
  39. package/dist/credentials/store.js.map +1 -1
  40. package/dist/crystallizer.d.ts +56 -0
  41. package/dist/crystallizer.d.ts.map +1 -0
  42. package/dist/crystallizer.js +159 -0
  43. package/dist/crystallizer.js.map +1 -0
  44. package/dist/distiller.d.ts +48 -0
  45. package/dist/distiller.d.ts.map +1 -0
  46. package/dist/distiller.js +140 -0
  47. package/dist/distiller.js.map +1 -0
  48. package/dist/google/auth.d.ts +2 -0
  49. package/dist/google/auth.d.ts.map +1 -1
  50. package/dist/google/auth.js +2 -0
  51. package/dist/google/auth.js.map +1 -1
  52. package/dist/integrations/gate.d.ts +40 -0
  53. package/dist/integrations/gate.d.ts.map +1 -0
  54. package/dist/integrations/gate.js +100 -0
  55. package/dist/integrations/gate.js.map +1 -0
  56. package/dist/lib/audit.d.ts +43 -0
  57. package/dist/lib/audit.d.ts.map +1 -0
  58. package/dist/lib/audit.js +120 -0
  59. package/dist/lib/audit.js.map +1 -0
  60. package/dist/lib/brain-io.d.ts.map +1 -1
  61. package/dist/lib/brain-io.js +52 -0
  62. package/dist/lib/brain-io.js.map +1 -1
  63. package/dist/lib/dpapi.d.ts +14 -0
  64. package/dist/lib/dpapi.d.ts.map +1 -0
  65. package/dist/lib/dpapi.js +104 -0
  66. package/dist/lib/dpapi.js.map +1 -0
  67. package/dist/lib/glob-match.d.ts +22 -0
  68. package/dist/lib/glob-match.d.ts.map +1 -0
  69. package/dist/lib/glob-match.js +64 -0
  70. package/dist/lib/glob-match.js.map +1 -0
  71. package/dist/lib/locked.d.ts +40 -0
  72. package/dist/lib/locked.d.ts.map +1 -0
  73. package/dist/lib/locked.js +130 -0
  74. package/dist/lib/locked.js.map +1 -0
  75. package/dist/llm/complete.d.ts.map +1 -1
  76. package/dist/llm/complete.js +5 -2
  77. package/dist/llm/complete.js.map +1 -1
  78. package/dist/llm/fetch-guard.d.ts +16 -0
  79. package/dist/llm/fetch-guard.d.ts.map +1 -0
  80. package/dist/llm/fetch-guard.js +61 -0
  81. package/dist/llm/fetch-guard.js.map +1 -0
  82. package/dist/llm/guard.d.ts +40 -0
  83. package/dist/llm/guard.d.ts.map +1 -0
  84. package/dist/llm/guard.js +88 -0
  85. package/dist/llm/guard.js.map +1 -0
  86. package/dist/llm/membrane.d.ts +46 -0
  87. package/dist/llm/membrane.d.ts.map +1 -0
  88. package/dist/llm/membrane.js +123 -0
  89. package/dist/llm/membrane.js.map +1 -0
  90. package/dist/llm/providers/index.d.ts +5 -1
  91. package/dist/llm/providers/index.d.ts.map +1 -1
  92. package/dist/llm/providers/index.js +8 -1
  93. package/dist/llm/providers/index.js.map +1 -1
  94. package/dist/llm/redact.d.ts +39 -0
  95. package/dist/llm/redact.d.ts.map +1 -0
  96. package/dist/llm/redact.js +155 -0
  97. package/dist/llm/redact.js.map +1 -0
  98. package/dist/llm/sensitive-registry.d.ts +33 -0
  99. package/dist/llm/sensitive-registry.d.ts.map +1 -0
  100. package/dist/llm/sensitive-registry.js +106 -0
  101. package/dist/llm/sensitive-registry.js.map +1 -0
  102. package/dist/mcp-server.d.ts +11 -0
  103. package/dist/mcp-server.d.ts.map +1 -0
  104. package/dist/mcp-server.js +520 -0
  105. package/dist/mcp-server.js.map +1 -0
  106. package/dist/mdns.d.ts +17 -0
  107. package/dist/mdns.d.ts.map +1 -0
  108. package/dist/mdns.js +110 -0
  109. package/dist/mdns.js.map +1 -0
  110. package/dist/nerve/push.d.ts +26 -0
  111. package/dist/nerve/push.d.ts.map +1 -0
  112. package/dist/nerve/push.js +170 -0
  113. package/dist/nerve/push.js.map +1 -0
  114. package/dist/nerve/state.d.ts +35 -0
  115. package/dist/nerve/state.d.ts.map +1 -0
  116. package/dist/nerve/state.js +257 -0
  117. package/dist/nerve/state.js.map +1 -0
  118. package/dist/resend/inbox.d.ts +23 -0
  119. package/dist/resend/inbox.d.ts.map +1 -0
  120. package/dist/resend/inbox.js +198 -0
  121. package/dist/resend/inbox.js.map +1 -0
  122. package/dist/resend/webhooks.d.ts +30 -0
  123. package/dist/resend/webhooks.d.ts.map +1 -0
  124. package/dist/resend/webhooks.js +244 -0
  125. package/dist/resend/webhooks.js.map +1 -0
  126. package/dist/server.d.ts +2 -0
  127. package/dist/server.d.ts.map +1 -1
  128. package/dist/server.js +585 -16
  129. package/dist/server.js.map +1 -1
  130. package/dist/settings.d.ts +14 -1
  131. package/dist/settings.d.ts.map +1 -1
  132. package/dist/settings.js +35 -1
  133. package/dist/settings.js.map +1 -1
  134. package/dist/updater.d.ts +32 -0
  135. package/dist/updater.d.ts.map +1 -0
  136. package/dist/updater.js +145 -0
  137. package/dist/updater.js.map +1 -0
  138. package/dist/vault/policy.d.ts +42 -0
  139. package/dist/vault/policy.d.ts.map +1 -0
  140. package/dist/vault/policy.js +159 -0
  141. package/dist/vault/policy.js.map +1 -0
  142. package/dist/vault/store.d.ts +6 -0
  143. package/dist/vault/store.d.ts.map +1 -1
  144. package/dist/vault/store.js +15 -5
  145. package/dist/vault/store.js.map +1 -1
  146. package/dist/vault/transfer.d.ts +33 -0
  147. package/dist/vault/transfer.d.ts.map +1 -0
  148. package/dist/vault/transfer.js +187 -0
  149. package/dist/vault/transfer.js.map +1 -0
  150. package/dist/voucher.d.ts +39 -0
  151. package/dist/voucher.d.ts.map +1 -0
  152. package/dist/voucher.js +105 -0
  153. package/dist/voucher.js.map +1 -0
  154. package/dist/webhooks/handlers.d.ts +10 -0
  155. package/dist/webhooks/handlers.d.ts.map +1 -1
  156. package/dist/webhooks/handlers.js +53 -0
  157. package/dist/webhooks/handlers.js.map +1 -1
  158. package/dist/webhooks/index.d.ts +2 -2
  159. package/dist/webhooks/index.d.ts.map +1 -1
  160. package/dist/webhooks/index.js +2 -2
  161. package/dist/webhooks/index.js.map +1 -1
  162. package/dist/webhooks/verify.d.ts +8 -0
  163. package/dist/webhooks/verify.d.ts.map +1 -1
  164. package/dist/webhooks/verify.js +56 -0
  165. package/dist/webhooks/verify.js.map +1 -1
  166. package/package.json +8 -2
  167. package/public/board.html +8 -3
  168. package/public/browser.html +8 -3
  169. package/public/library.html +8 -3
  170. package/public/observatory.html +8 -3
  171. package/public/ops.html +8 -3
  172. package/public/registry.html +627 -0
  173. package/public/roadmap.html +975 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Agent Governance Gate — CORE-9
3
+ *
4
+ * Pre-spawn validation that replaces the `--dangerously-skip-permissions`
5
+ * prompt with voucher-based authorization, locked-path enforcement, and
6
+ * principle injection.
7
+ *
8
+ * Every governed spawn:
9
+ * 1. Issues a scoped voucher for the task
10
+ * 2. Reads locked paths and builds a deny-list for the agent's prompt
11
+ * 3. Injects core principles as behavioral constraints
12
+ * 4. Wraps the prompt with governance preamble
13
+ * 5. Logs the governance decision to the audit trail
14
+ */
15
+ import { readFile } from "node:fs/promises";
16
+ import { join, resolve } from "node:path";
17
+ import { issueVoucher, checkVoucher, revokeVoucher } from "../voucher.js";
18
+ import { loadLockedPaths } from "../lib/locked.js";
19
+ import { checkSpawnPolicy, loadSpawnPolicy } from "./spawn-policy.js";
20
+ import { logActivity } from "../activity/log.js";
21
+ import { createLogger } from "../utils/logger.js";
22
+ const log = createLogger("governance");
23
+ const BRAIN_DIR = resolve(process.cwd(), "brain");
24
+ // ---------------------------------------------------------------------------
25
+ // Governance preamble components
26
+ // ---------------------------------------------------------------------------
27
+ function buildLockedPathsSection(paths) {
28
+ if (paths.length === 0)
29
+ return "";
30
+ const pathList = paths.map((p) => ` - brain/${p}`).join("\n");
31
+ return `
32
+ ## Locked Paths (DO NOT ACCESS)
33
+ The following paths are locked by governance policy. Do NOT read, write, or
34
+ reference these files. Violations will be logged and may terminate your session.
35
+
36
+ ${pathList}
37
+ `;
38
+ }
39
+ function buildVoucherSection(token, scope) {
40
+ return `
41
+ ## Governance Voucher
42
+ You are operating under voucher \`${token}\` with scope \`${scope}\`.
43
+ This voucher is time-limited. If you receive a governance violation, stop immediately.
44
+ `;
45
+ }
46
+ async function loadPrinciples() {
47
+ try {
48
+ const principlesPath = join(BRAIN_DIR, "identity", "principles.md");
49
+ const content = await readFile(principlesPath, "utf-8");
50
+ // Extract just the key principles, not the full document
51
+ const lines = content.split("\n");
52
+ const keyPrinciples = [];
53
+ for (const line of lines) {
54
+ if (line.startsWith("**") && line.endsWith("**")) {
55
+ keyPrinciples.push(line);
56
+ }
57
+ }
58
+ if (keyPrinciples.length === 0)
59
+ return "";
60
+ return `
61
+ ## Operating Principles
62
+ You must adhere to these principles during execution:
63
+ ${keyPrinciples.map((p) => `- ${p}`).join("\n")}
64
+ `;
65
+ }
66
+ catch {
67
+ log.warn("Could not load principles — proceeding without them");
68
+ return "";
69
+ }
70
+ }
71
+ // ---------------------------------------------------------------------------
72
+ // Main governance gate
73
+ // ---------------------------------------------------------------------------
74
+ /**
75
+ * Run the governance gate before spawning an agent.
76
+ * Returns a GovernanceDecision with the governed prompt (or denial).
77
+ */
78
+ export async function governanceGate(opts) {
79
+ const { taskId, label, prompt, origin, ltm, scope: scopeOverride, voucherTtlMinutes = 30, skipVoucher = false, } = opts;
80
+ const scope = scopeOverride ?? `agent:spawn:${taskId}`;
81
+ const timestamp = new Date().toISOString();
82
+ // 1. Load locked paths
83
+ const lockedPaths = await loadLockedPaths();
84
+ // 1b. Spawn policy check (if agentType provided)
85
+ if (opts.agentType) {
86
+ await loadSpawnPolicy();
87
+ const spawnCheck = checkSpawnPolicy(opts.agentType, opts.currentAgentCount ?? 0, opts.currentTypeCount ?? 0);
88
+ if (!spawnCheck.allowed) {
89
+ const reason = `Spawn policy denied: ${spawnCheck.reason}`;
90
+ log.warn(reason, { taskId, agentType: opts.agentType });
91
+ const auditEntry = {
92
+ timestamp,
93
+ taskId,
94
+ label,
95
+ decision: "deny",
96
+ lockedPathCount: lockedPaths.length,
97
+ reason,
98
+ };
99
+ logActivity({
100
+ source: "agent",
101
+ summary: `Governance DENIED (spawn policy): ${label}`,
102
+ detail: reason,
103
+ actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
104
+ reason: "governance-gate",
105
+ });
106
+ return {
107
+ allowed: false,
108
+ deniedReason: reason,
109
+ governedPrompt: prompt,
110
+ lockedPaths,
111
+ auditEntry,
112
+ };
113
+ }
114
+ }
115
+ // 2. Issue voucher (unless skipped for system tasks)
116
+ let voucherToken;
117
+ if (!skipVoucher) {
118
+ try {
119
+ voucherToken = await issueVoucher(ltm, scope, voucherTtlMinutes);
120
+ log.info("Voucher issued for agent", { taskId, token: voucherToken, scope });
121
+ }
122
+ catch (err) {
123
+ const reason = `Voucher issuance failed: ${err instanceof Error ? err.message : String(err)}`;
124
+ log.error(reason, { taskId });
125
+ const auditEntry = {
126
+ timestamp,
127
+ taskId,
128
+ label,
129
+ decision: "deny",
130
+ lockedPathCount: lockedPaths.length,
131
+ reason,
132
+ };
133
+ logActivity({
134
+ source: "agent",
135
+ summary: `Governance DENIED: ${label}`,
136
+ detail: reason,
137
+ actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
138
+ reason: "governance-gate",
139
+ });
140
+ return {
141
+ allowed: false,
142
+ deniedReason: reason,
143
+ governedPrompt: prompt,
144
+ lockedPaths,
145
+ auditEntry,
146
+ };
147
+ }
148
+ }
149
+ // 3. Load principles
150
+ const principlesSection = await loadPrinciples();
151
+ // 4. Build governed prompt
152
+ const governancePreamble = [
153
+ "## Governance Context",
154
+ "This agent session is governed by the Core orchestration system.",
155
+ "You are running with `--dangerously-skip-permissions`. In exchange,",
156
+ "governance controls replace the permission prompt. Violating these",
157
+ "controls will terminate your session.",
158
+ "",
159
+ voucherToken ? buildVoucherSection(voucherToken, scope) : "",
160
+ buildLockedPathsSection(lockedPaths),
161
+ principlesSection,
162
+ "## Heartbeat Requirement",
163
+ "Your actions are monitored. Extended silence (no file writes, no output)",
164
+ "will trigger a timeout and termination. Stay on task.",
165
+ "",
166
+ "---",
167
+ "",
168
+ ]
169
+ .filter(Boolean)
170
+ .join("\n");
171
+ const governedPrompt = governancePreamble + prompt;
172
+ // 5. Log the decision
173
+ const auditEntry = {
174
+ timestamp,
175
+ taskId,
176
+ label,
177
+ decision: "allow",
178
+ voucherToken,
179
+ voucherScope: scope,
180
+ lockedPathCount: lockedPaths.length,
181
+ };
182
+ logActivity({
183
+ source: "agent",
184
+ summary: `Governance ALLOWED: ${label}`,
185
+ detail: `Voucher: ${voucherToken ?? "skipped"}, locked paths: ${lockedPaths.length}`,
186
+ actionLabel: origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
187
+ reason: "governance-gate",
188
+ });
189
+ log.info("Governance gate passed", { taskId, label, voucherToken });
190
+ return {
191
+ allowed: true,
192
+ voucherToken,
193
+ governedPrompt,
194
+ lockedPaths,
195
+ auditEntry,
196
+ };
197
+ }
198
+ /**
199
+ * Revoke a governance voucher (call on agent completion or termination).
200
+ */
201
+ export async function revokeGovernanceVoucher(ltm, token) {
202
+ try {
203
+ await revokeVoucher(ltm, token);
204
+ log.info("Governance voucher revoked", { token });
205
+ }
206
+ catch (err) {
207
+ log.warn("Failed to revoke voucher", {
208
+ token,
209
+ error: err instanceof Error ? err.message : String(err),
210
+ });
211
+ }
212
+ }
213
+ /**
214
+ * Validate that a voucher is still active (for mid-session checks).
215
+ */
216
+ export async function validateGovernanceVoucher(ltm, token) {
217
+ const result = await checkVoucher(ltm, token);
218
+ return result.valid;
219
+ }
220
+ //# sourceMappingURL=governance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance.js","sourceRoot":"","sources":["../../src/agents/governance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAkB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,CAAC,CAAC;AAEvC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;AAkDlD,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,SAAS,uBAAuB,CAAC,KAAe;IAC9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,OAAO;;;;;EAKP,QAAQ;CACT,CAAC;AACF,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAa,EAAE,KAAa;IACvD,OAAO;;oCAE2B,KAAK,mBAAmB,KAAK;;CAEhE,CAAC;AACF,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QACxD,yDAAyD;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QACD,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAC1C,OAAO;;;EAGT,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;CAC9C,CAAC;IACA,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAChE,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,uBAAuB;AACvB,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAuB;IAEvB,MAAM,EACJ,MAAM,EACN,KAAK,EACL,MAAM,EACN,MAAM,EACN,GAAG,EACH,KAAK,EAAE,aAAa,EACpB,iBAAiB,GAAG,EAAE,EACtB,WAAW,GAAG,KAAK,GACpB,GAAG,IAAI,CAAC;IAET,MAAM,KAAK,GAAG,aAAa,IAAI,eAAe,MAAM,EAAE,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE3C,uBAAuB;IACvB,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAE5C,iDAAiD;IACjD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,MAAM,eAAe,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,gBAAgB,CACjC,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,iBAAiB,IAAI,CAAC,EAC3B,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAC3B,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,wBAAwB,UAAU,CAAC,MAAM,EAAE,CAAC;YAC3D,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;YAExD,MAAM,UAAU,GAAyB;gBACvC,SAAS;gBACT,MAAM;gBACN,KAAK;gBACL,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,WAAW,CAAC,MAAM;gBACnC,MAAM;aACP,CAAC;YAEF,WAAW,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,qCAAqC,KAAK,EAAE;gBACrD,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;gBACxD,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,MAAM;gBACtB,WAAW;gBACX,UAAU;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qDAAqD;IACrD,IAAI,YAAgC,CAAC;IACrC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;YACjE,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9F,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAE9B,MAAM,UAAU,GAAyB;gBACvC,SAAS;gBACT,MAAM;gBACN,KAAK;gBACL,QAAQ,EAAE,MAAM;gBAChB,eAAe,EAAE,WAAW,CAAC,MAAM;gBACnC,MAAM;aACP,CAAC;YAEF,WAAW,CAAC;gBACV,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,sBAAsB,KAAK,EAAE;gBACtC,MAAM,EAAE,MAAM;gBACd,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;gBACxD,MAAM,EAAE,iBAAiB;aAC1B,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,YAAY,EAAE,MAAM;gBACpB,cAAc,EAAE,MAAM;gBACtB,WAAW;gBACX,UAAU;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,iBAAiB,GAAG,MAAM,cAAc,EAAE,CAAC;IAEjD,2BAA2B;IAC3B,MAAM,kBAAkB,GAAG;QACzB,uBAAuB;QACvB,kEAAkE;QAClE,qEAAqE;QACrE,oEAAoE;QACpE,uCAAuC;QACvC,EAAE;QACF,YAAY,CAAC,CAAC,CAAC,mBAAmB,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;QAC5D,uBAAuB,CAAC,WAAW,CAAC;QACpC,iBAAiB;QACjB,0BAA0B;QAC1B,0EAA0E;QAC1E,uDAAuD;QACvD,EAAE;QACF,KAAK;QACL,EAAE;KACH;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,cAAc,GAAG,kBAAkB,GAAG,MAAM,CAAC;IAEnD,sBAAsB;IACtB,MAAM,UAAU,GAAyB;QACvC,SAAS;QACT,MAAM;QACN,KAAK;QACL,QAAQ,EAAE,OAAO;QACjB,YAAY;QACZ,YAAY,EAAE,KAAK;QACnB,eAAe,EAAE,WAAW,CAAC,MAAM;KACpC,CAAC;IAEF,WAAW,CAAC;QACV,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,uBAAuB,KAAK,EAAE;QACvC,MAAM,EAAE,YAAY,YAAY,IAAI,SAAS,mBAAmB,WAAW,CAAC,MAAM,EAAE;QACpF,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;QACxD,MAAM,EAAE,iBAAiB;KAC1B,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAC,wBAAwB,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IAEpE,OAAO;QACL,OAAO,EAAE,IAAI;QACb,YAAY;QACZ,cAAc;QACd,WAAW;QACX,UAAU;KACX,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,GAAwB,EACxB,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE;YACnC,KAAK;YACL,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SACxD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,GAAwB,EACxB,KAAa;IAEb,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Governed Agent Spawn — CORE-9
3
+ *
4
+ * High-level entry point for spawning Claude Code agents with full
5
+ * governance controls. Composes:
6
+ *
7
+ * 1. Governance gate (voucher + locked paths + principles)
8
+ * 2. Agent spawning (via existing pool or direct spawn)
9
+ * 3. Heartbeat monitoring (silence + drift detection)
10
+ * 4. Lifecycle management (cleanup on completion/termination)
11
+ *
12
+ * This replaces raw `--dangerously-skip-permissions` with a governed
13
+ * equivalent where vouchers, locked paths, and principles replace the
14
+ * interactive permission prompt.
15
+ */
16
+ import type { LongTermMemoryStore } from "../memory/long-term.js";
17
+ import type { AgentPool } from "./runtime.js";
18
+ import type { AgentInstance } from "./runtime/types.js";
19
+ import { type GovernanceDecision } from "./governance.js";
20
+ import { type HeartbeatConfig, type HeartbeatTracker } from "./heartbeat.js";
21
+ /** Input for a governed agent spawn. */
22
+ export interface GovernedSpawnRequest {
23
+ /** Task identifier (should be unique). */
24
+ taskId: string;
25
+ /** Human-readable label. */
26
+ label: string;
27
+ /** The actual task prompt. */
28
+ prompt: string;
29
+ /** Working directory for the agent. */
30
+ cwd?: string;
31
+ /** Who initiated the spawn. */
32
+ origin: "user" | "ai" | "system";
33
+ /** Tags for grouping/filtering. */
34
+ tags?: string[];
35
+ /** Parent agent ID (for sub-agent spawns). */
36
+ parentId?: string;
37
+ /** Override heartbeat config. */
38
+ heartbeat?: Partial<HeartbeatConfig>;
39
+ /** Override voucher TTL (minutes). */
40
+ voucherTtlMinutes?: number;
41
+ /** Skip voucher for system-level tasks. */
42
+ skipVoucher?: boolean;
43
+ /** Agent type for spawn policy checks (e.g. "administration", "brand"). */
44
+ agentType?: string;
45
+ /** Current total running agent count (for spawn policy max check). */
46
+ currentAgentCount?: number;
47
+ /** Current running count of this specific agent type. */
48
+ currentTypeCount?: number;
49
+ }
50
+ /** Result of a governed spawn — includes governance metadata. */
51
+ export interface GovernedSpawnResult {
52
+ /** Whether the spawn was allowed and succeeded. */
53
+ success: boolean;
54
+ /** The spawned agent instance (if successful). */
55
+ instance?: AgentInstance;
56
+ /** Governance decision details. */
57
+ governance: GovernanceDecision;
58
+ /** Heartbeat tracker (if spawn succeeded). */
59
+ heartbeat?: HeartbeatTracker;
60
+ /** Trace ID linking all activity for this spawn. */
61
+ traceId: string;
62
+ /** Denial reason (if not allowed). */
63
+ deniedReason?: string;
64
+ }
65
+ /** Dependencies injected into the governed spawn system. */
66
+ export interface GovernedSpawnDeps {
67
+ /** Long-term memory store for voucher operations. */
68
+ ltm: LongTermMemoryStore;
69
+ /** Agent pool for spawning (preferred). */
70
+ pool?: AgentPool;
71
+ }
72
+ /**
73
+ * Spawn a Claude Code agent with full governance controls.
74
+ *
75
+ * Flow:
76
+ * 1. Run governance gate (voucher + locked paths + principles)
77
+ * 2. If denied → return failure with reason
78
+ * 3. Spawn agent via pool with governed prompt
79
+ * 4. Attach heartbeat tracker
80
+ * 5. Wire lifecycle cleanup (voucher revocation on exit)
81
+ */
82
+ export declare function governedSpawn(request: GovernedSpawnRequest, deps: GovernedSpawnDeps): Promise<GovernedSpawnResult>;
83
+ //# sourceMappingURL=governed-spawn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governed-spawn.d.ts","sourceRoot":"","sources":["../../src/agents/governed-spawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAIL,KAAK,kBAAkB,EAExB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAUxB,wCAAwC;AACxC,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC;IACjC,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iCAAiC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACrC,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,2CAA2C;IAC3C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,OAAO,EAAE,OAAO,CAAC;IACjB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,mCAAmC;IACnC,UAAU,EAAE,kBAAkB,CAAC;IAC/B,8CAA8C;IAC9C,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,4DAA4D;AAC5D,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,GAAG,EAAE,mBAAmB,CAAC;IACzB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAMD;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,CAAC,CA+K9B"}
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Governed Agent Spawn — CORE-9
3
+ *
4
+ * High-level entry point for spawning Claude Code agents with full
5
+ * governance controls. Composes:
6
+ *
7
+ * 1. Governance gate (voucher + locked paths + principles)
8
+ * 2. Agent spawning (via existing pool or direct spawn)
9
+ * 3. Heartbeat monitoring (silence + drift detection)
10
+ * 4. Lifecycle management (cleanup on completion/termination)
11
+ *
12
+ * This replaces raw `--dangerously-skip-permissions` with a governed
13
+ * equivalent where vouchers, locked paths, and principles replace the
14
+ * interactive permission prompt.
15
+ */
16
+ import { governanceGate, revokeGovernanceVoucher, } from "./governance.js";
17
+ import { createHeartbeatTracker, removeHeartbeatTracker, extractTaskKeywords, } from "./heartbeat.js";
18
+ import { logActivity, generateTraceId } from "../activity/log.js";
19
+ import { createLogger } from "../utils/logger.js";
20
+ const log = createLogger("governed-spawn");
21
+ // ---------------------------------------------------------------------------
22
+ // Governed spawn
23
+ // ---------------------------------------------------------------------------
24
+ /**
25
+ * Spawn a Claude Code agent with full governance controls.
26
+ *
27
+ * Flow:
28
+ * 1. Run governance gate (voucher + locked paths + principles)
29
+ * 2. If denied → return failure with reason
30
+ * 3. Spawn agent via pool with governed prompt
31
+ * 4. Attach heartbeat tracker
32
+ * 5. Wire lifecycle cleanup (voucher revocation on exit)
33
+ */
34
+ export async function governedSpawn(request, deps) {
35
+ const traceId = generateTraceId();
36
+ const { ltm, pool } = deps;
37
+ log.info("Governed spawn requested", {
38
+ taskId: request.taskId,
39
+ label: request.label,
40
+ origin: request.origin,
41
+ traceId,
42
+ });
43
+ // 1. Run governance gate
44
+ const govOpts = {
45
+ taskId: request.taskId,
46
+ label: request.label,
47
+ prompt: request.prompt,
48
+ origin: request.origin,
49
+ ltm,
50
+ voucherTtlMinutes: request.voucherTtlMinutes,
51
+ skipVoucher: request.skipVoucher,
52
+ agentType: request.agentType,
53
+ currentAgentCount: request.currentAgentCount,
54
+ currentTypeCount: request.currentTypeCount,
55
+ };
56
+ const governance = await governanceGate(govOpts);
57
+ // 2. Check governance decision
58
+ if (!governance.allowed) {
59
+ log.warn("Governed spawn denied", {
60
+ taskId: request.taskId,
61
+ reason: governance.deniedReason,
62
+ traceId,
63
+ });
64
+ return {
65
+ success: false,
66
+ governance,
67
+ traceId,
68
+ deniedReason: governance.deniedReason,
69
+ };
70
+ }
71
+ // 3. Spawn agent via pool
72
+ if (!pool) {
73
+ const reason = "No agent pool available — cannot spawn governed agent";
74
+ log.error(reason, { taskId: request.taskId });
75
+ // Revoke the voucher since we can't use it
76
+ if (governance.voucherToken) {
77
+ await revokeGovernanceVoucher(ltm, governance.voucherToken);
78
+ }
79
+ return {
80
+ success: false,
81
+ governance,
82
+ traceId,
83
+ deniedReason: reason,
84
+ };
85
+ }
86
+ let instance;
87
+ try {
88
+ const spawnRequest = {
89
+ taskId: request.taskId,
90
+ label: request.label,
91
+ prompt: governance.governedPrompt,
92
+ cwd: request.cwd,
93
+ origin: request.origin,
94
+ tags: [
95
+ ...(request.tags ?? []),
96
+ "governed",
97
+ governance.voucherToken ? `voucher:${governance.voucherToken}` : "voucher:none",
98
+ ],
99
+ parentId: request.parentId,
100
+ };
101
+ instance = await pool.spawn(spawnRequest);
102
+ logActivity({
103
+ source: "agent",
104
+ summary: `Governed agent spawned: ${request.label}`,
105
+ detail: `Instance: ${instance.id}, PID: ${instance.pid}, voucher: ${governance.voucherToken ?? "none"}`,
106
+ traceId,
107
+ actionLabel: request.origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
108
+ reason: "governed-spawn",
109
+ });
110
+ }
111
+ catch (err) {
112
+ const reason = `Spawn failed: ${err instanceof Error ? err.message : String(err)}`;
113
+ log.error(reason, { taskId: request.taskId, traceId });
114
+ // Revoke voucher on spawn failure
115
+ if (governance.voucherToken) {
116
+ await revokeGovernanceVoucher(ltm, governance.voucherToken);
117
+ }
118
+ return {
119
+ success: false,
120
+ governance,
121
+ traceId,
122
+ deniedReason: reason,
123
+ };
124
+ }
125
+ // 4. Attach heartbeat tracker
126
+ const taskKeywords = extractTaskKeywords(request.prompt);
127
+ const heartbeat = createHeartbeatTracker(request.taskId, instance.id, {
128
+ taskDescription: request.prompt,
129
+ taskKeywords,
130
+ ...request.heartbeat,
131
+ }, async (instanceId, reason) => {
132
+ // Termination callback from heartbeat
133
+ log.warn("Heartbeat triggered termination", { instanceId, reason, traceId });
134
+ try {
135
+ await pool.terminate(instanceId, reason);
136
+ }
137
+ catch (err) {
138
+ log.error("Failed to terminate via heartbeat", {
139
+ instanceId,
140
+ error: err instanceof Error ? err.message : String(err),
141
+ });
142
+ }
143
+ });
144
+ heartbeat.start();
145
+ // 5. Wire lifecycle cleanup via bus events
146
+ const cleanupHandler = async (event) => {
147
+ if (event.agentId !== instance.id)
148
+ return;
149
+ const terminalStates = new Set(["completed", "failed", "terminated"]);
150
+ if (!terminalStates.has(event.newState))
151
+ return;
152
+ // Remove handler
153
+ pool.runtimeManager.bus.off("agent:lifecycle", cleanupHandler);
154
+ // Stop heartbeat
155
+ removeHeartbeatTracker(instance.id);
156
+ // Revoke voucher
157
+ if (governance.voucherToken) {
158
+ await revokeGovernanceVoucher(ltm, governance.voucherToken);
159
+ }
160
+ logActivity({
161
+ source: "agent",
162
+ summary: `Governed agent ${event.newState}: ${request.label}`,
163
+ detail: `Instance: ${instance.id}, voucher revoked: ${governance.voucherToken ?? "none"}`,
164
+ traceId,
165
+ actionLabel: request.origin === "ai" ? "AUTONOMOUS" : "PROMPTED",
166
+ reason: "governed-lifecycle",
167
+ });
168
+ };
169
+ pool.runtimeManager.bus.on("agent:lifecycle", cleanupHandler);
170
+ log.info("Governed spawn complete", {
171
+ taskId: request.taskId,
172
+ instanceId: instance.id,
173
+ pid: instance.pid,
174
+ voucherToken: governance.voucherToken,
175
+ heartbeatKeywords: taskKeywords.slice(0, 5),
176
+ traceId,
177
+ });
178
+ return {
179
+ success: true,
180
+ instance,
181
+ governance,
182
+ heartbeat,
183
+ traceId,
184
+ };
185
+ }
186
+ //# sourceMappingURL=governed-spawn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governed-spawn.js","sourceRoot":"","sources":["../../src/agents/governed-spawn.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Agent Heartbeat Monitor — CORE-9
3
+ *
4
+ * Action-based heartbeat: every agent action IS the ping.
5
+ * No polling, no timer-based pings. The append-only log is the tracking.
6
+ *
7
+ * Monitors:
8
+ * 1. **Silence detection** — agent produces no output for too long → terminate
9
+ * 2. **Drift detection** — agent's actions diverge from the assigned task → warn/terminate
10
+ * 3. **Heartbeat logging** — append-only JSONL trail of agent pulses
11
+ *
12
+ * Designed to work with the existing activity log system. Each agent gets
13
+ * a HeartbeatTracker that watches for signs of life and task adherence.
14
+ */
15
+ /** A single heartbeat pulse from an agent. */
16
+ export interface HeartbeatPulse {
17
+ timestamp: string;
18
+ taskId: string;
19
+ instanceId: string;
20
+ type: "spawn" | "action" | "output" | "checkpoint" | "complete" | "terminate" | "silence-warning";
21
+ detail?: string;
22
+ /** Semantic summary of what the agent is doing (for drift detection). */
23
+ actionSummary?: string;
24
+ }
25
+ /** Configuration for a heartbeat tracker. */
26
+ export interface HeartbeatConfig {
27
+ /** Max silence before warning (ms). Default: 120_000 (2 min). */
28
+ silenceWarningMs: number;
29
+ /** Max silence before termination (ms). Default: 300_000 (5 min). */
30
+ silenceTerminateMs: number;
31
+ /** Check interval (ms). Default: 15_000 (15s). */
32
+ checkIntervalMs: number;
33
+ /** Task description for drift detection. */
34
+ taskDescription: string;
35
+ /** Keywords from the task for simple drift heuristic. */
36
+ taskKeywords: string[];
37
+ /** Max consecutive drift warnings before termination. Default: 3. */
38
+ maxDriftWarnings: number;
39
+ }
40
+ /** Status of a tracked agent's heartbeat. */
41
+ export interface HeartbeatStatus {
42
+ taskId: string;
43
+ instanceId: string;
44
+ alive: boolean;
45
+ lastPulseAt: string | null;
46
+ silenceMs: number;
47
+ driftWarnings: number;
48
+ totalPulses: number;
49
+ state: "healthy" | "warning" | "critical" | "terminated";
50
+ }
51
+ /** Callback when an agent needs to be terminated. */
52
+ export type TerminateCallback = (instanceId: string, reason: string) => Promise<void>;
53
+ /** Extract meaningful keywords from a task description. */
54
+ export declare function extractTaskKeywords(description: string): string[];
55
+ export declare class HeartbeatTracker {
56
+ readonly taskId: string;
57
+ readonly instanceId: string;
58
+ private config;
59
+ private onTerminate;
60
+ private lastPulseAt;
61
+ private driftWarnings;
62
+ private totalPulses;
63
+ private checkTimer;
64
+ private terminated;
65
+ private traceId;
66
+ constructor(taskId: string, instanceId: string, config: Partial<HeartbeatConfig>, onTerminate: TerminateCallback);
67
+ /** Start monitoring the agent's heartbeat. */
68
+ start(): void;
69
+ /** Stop monitoring (call on agent completion). */
70
+ stop(reason?: "complete" | "terminate"): void;
71
+ /**
72
+ * Record a heartbeat pulse. Call this whenever the agent produces
73
+ * observable output (file write, stdout, checkpoint).
74
+ */
75
+ recordPulse(type: HeartbeatPulse["type"], detail?: string, actionSummary?: string): void;
76
+ /** Get the current heartbeat status. */
77
+ getStatus(): HeartbeatStatus;
78
+ private check;
79
+ private terminateAgent;
80
+ }
81
+ /** Create and register a heartbeat tracker for an agent instance. */
82
+ export declare function createHeartbeatTracker(taskId: string, instanceId: string, config: Partial<HeartbeatConfig>, onTerminate: TerminateCallback): HeartbeatTracker;
83
+ /** Get a tracker by instance ID. */
84
+ export declare function getHeartbeatTracker(instanceId: string): HeartbeatTracker | undefined;
85
+ /** Remove a tracker (call on agent completion). */
86
+ export declare function removeHeartbeatTracker(instanceId: string): void;
87
+ /** Get status of all tracked agents. */
88
+ export declare function getAllHeartbeatStatuses(): HeartbeatStatus[];
89
+ /** Stop all trackers (call on shutdown). */
90
+ export declare function shutdownHeartbeats(): void;
91
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/agents/heartbeat.ts"],"names":[],"mappings":"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"}