harnery 0.45.0 → 0.45.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 (235) hide show
  1. package/dist/commander.js +0 -1
  2. package/dist/commands/files.d.ts +2 -2
  3. package/dist/commands/files.d.ts.map +1 -1
  4. package/dist/commands/files.js +4 -7
  5. package/dist/commands/servers.d.ts.map +1 -1
  6. package/dist/commands/servers.js +17 -11
  7. package/dist/commands/tunnel.d.ts +0 -15
  8. package/dist/commands/tunnel.d.ts.map +1 -1
  9. package/dist/commands/tunnel.js +153 -453
  10. package/dist/commands/workflow.d.ts.map +1 -1
  11. package/dist/commands/workflow.js +6 -45
  12. package/dist/core/agents/coord-client.d.ts.map +1 -1
  13. package/dist/core/agents/coord-client.js +0 -18
  14. package/dist/core/agents/live-authority-v3.d.ts +0 -1
  15. package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
  16. package/dist/core/agents/live-authority-v3.js +0 -11
  17. package/dist/core/agents/live-lifecycle-v3.d.ts +2 -4
  18. package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
  19. package/dist/core/agents/live-lifecycle-v3.js +7 -28
  20. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  21. package/dist/core/agents/state/heartbeat-writer.js +14 -25
  22. package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -1
  23. package/dist/core/agents/state/live-coordination-writer.js +0 -5
  24. package/dist/core/agents/state/pidmap.d.ts.map +1 -1
  25. package/dist/core/agents/state/pidmap.js +2 -7
  26. package/dist/core/agents/state/proc-start.d.ts +20 -31
  27. package/dist/core/agents/state/proc-start.d.ts.map +1 -1
  28. package/dist/core/agents/state/proc-start.js +37 -70
  29. package/dist/core/agents/state/service-process.d.ts +61 -0
  30. package/dist/core/agents/state/service-process.d.ts.map +1 -0
  31. package/dist/core/agents/state/service-process.js +143 -0
  32. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  33. package/dist/core/agents/state/stale-sweep.js +70 -180
  34. package/dist/core/artifacts/activity.d.ts +4 -1
  35. package/dist/core/artifacts/activity.d.ts.map +1 -1
  36. package/dist/core/artifacts/activity.js +8 -2
  37. package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
  38. package/dist/core/artifacts/delivery-card.js +1 -2
  39. package/dist/core/artifacts/index.d.ts.map +1 -1
  40. package/dist/core/artifacts/index.js +38 -12
  41. package/dist/core/context/index.d.ts +6 -4
  42. package/dist/core/context/index.d.ts.map +1 -1
  43. package/dist/core/context/index.js +194 -256
  44. package/dist/core/context/observation.d.ts +9 -9
  45. package/dist/core/context/observation.d.ts.map +1 -1
  46. package/dist/core/context/observation.js +37 -6
  47. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  48. package/dist/core/events/v3/authority-outbox.js +0 -29
  49. package/dist/core/events/v3/producers/coordination-recorder.d.ts +0 -1
  50. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  51. package/dist/core/events/v3/producers/coordination-recorder.js +0 -7
  52. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  53. package/dist/core/events/v3/producers/recorder.js +64 -77
  54. package/dist/core/events/v3/runtime-build.d.ts +14 -0
  55. package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
  56. package/dist/core/events/v3/runtime-build.js +44 -0
  57. package/dist/core/governor/index.d.ts +2 -1
  58. package/dist/core/governor/index.d.ts.map +1 -1
  59. package/dist/core/governor/index.js +2 -1
  60. package/dist/core/governor/service-read.d.ts +3 -10
  61. package/dist/core/governor/service-read.d.ts.map +1 -1
  62. package/dist/core/governor/service-read.js +10 -94
  63. package/dist/core/governor/service.d.ts +3 -7
  64. package/dist/core/governor/service.d.ts.map +1 -1
  65. package/dist/core/governor/service.js +17 -182
  66. package/dist/core/hooks/cli.js +78 -48
  67. package/dist/core/hooks/resolve/owner.js +2 -2
  68. package/dist/core/resources/sampler.js +2 -2
  69. package/dist/core/resources/service-status.d.ts +2 -14
  70. package/dist/core/resources/service-status.d.ts.map +1 -1
  71. package/dist/core/resources/service-status.js +3 -23
  72. package/dist/core/resources/service.d.ts +3 -7
  73. package/dist/core/resources/service.d.ts.map +1 -1
  74. package/dist/core/resources/service.js +12 -101
  75. package/dist/core/resources/status.d.ts.map +1 -1
  76. package/dist/core/resources/status.js +3 -2
  77. package/dist/core/semantic/service.d.ts.map +1 -1
  78. package/dist/core/semantic/service.js +9 -2
  79. package/dist/core/servers/index.d.ts +11 -10
  80. package/dist/core/servers/index.d.ts.map +1 -1
  81. package/dist/core/servers/index.js +82 -192
  82. package/dist/core/servers/tunnels.d.ts +3 -5
  83. package/dist/core/servers/tunnels.d.ts.map +1 -1
  84. package/dist/core/servers/tunnels.js +2 -45
  85. package/dist/core/storage/durable-history.js +56 -22
  86. package/dist/core/storage/segments.d.ts.map +1 -1
  87. package/dist/core/storage/segments.js +73 -17
  88. package/dist/core/supervisor/service.d.ts +4 -7
  89. package/dist/core/supervisor/service.d.ts.map +1 -1
  90. package/dist/core/supervisor/service.js +23 -122
  91. package/dist/core/supervisor/services.js +2 -2
  92. package/dist/core/supervisor/status.d.ts +3 -17
  93. package/dist/core/supervisor/status.d.ts.map +1 -1
  94. package/dist/core/supervisor/status.js +7 -70
  95. package/dist/core/work/state.js +7 -7
  96. package/dist/core/workflow/engine.d.ts.map +1 -1
  97. package/dist/core/workflow/engine.js +23 -66
  98. package/dist/core/workflow/index.d.ts +3 -4
  99. package/dist/core/workflow/index.d.ts.map +1 -1
  100. package/dist/core/workflow/index.js +2 -2
  101. package/dist/core/workflow/live-session-v3.d.ts +0 -6
  102. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  103. package/dist/core/workflow/live-session-v3.js +5 -126
  104. package/dist/core/workflow/proof.d.ts +4 -4
  105. package/dist/core/workflow/proof.d.ts.map +1 -1
  106. package/dist/core/workflow/proof.js +34 -86
  107. package/dist/core/workflow/resume-lock.d.ts +17 -0
  108. package/dist/core/workflow/resume-lock.d.ts.map +1 -0
  109. package/dist/core/workflow/resume-lock.js +158 -0
  110. package/dist/core/workflow/run-state.d.ts +0 -21
  111. package/dist/core/workflow/run-state.d.ts.map +1 -1
  112. package/dist/core/workflow/run-state.js +3 -174
  113. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  114. package/dist/core/workflow/spawn-claude.js +0 -19
  115. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  116. package/dist/core/workflow/spawn-codex.js +0 -13
  117. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  118. package/dist/core/workflow/spawn-cursor.js +0 -19
  119. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -1
  120. package/dist/core/workflow/spawn-opencode.js +0 -14
  121. package/dist/core/workflow/types.d.ts +11 -54
  122. package/dist/core/workflow/types.d.ts.map +1 -1
  123. package/dist/core/workflow/workspaces/leases.d.ts +4 -0
  124. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  125. package/dist/core/workflow/workspaces/leases.js +1 -1
  126. package/dist/core/workflow/workspaces/local-git.js +91 -210
  127. package/dist/core/workflow/workspaces/ownership.d.ts +0 -7
  128. package/dist/core/workflow/workspaces/ownership.d.ts.map +1 -1
  129. package/dist/core/workflow/workspaces/ownership.js +3 -130
  130. package/dist/core/workflow/workspaces/reclaim.d.ts +4 -7
  131. package/dist/core/workflow/workspaces/reclaim.d.ts.map +1 -1
  132. package/dist/core/workflow/workspaces/reclaim.js +0 -4
  133. package/dist/core/workflow/workspaces/recovery.d.ts +1 -1
  134. package/dist/core/workflow/workspaces/recovery.d.ts.map +1 -1
  135. package/dist/core/workflow/workspaces/recovery.js +1 -1
  136. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  137. package/dist/core/workflow/workspaces/state.js +1 -4
  138. package/dist/lib/identities/assume.d.ts.map +1 -1
  139. package/dist/lib/identities/assume.js +0 -4
  140. package/dist/lib/tunnel/state.d.ts +6 -13
  141. package/dist/lib/tunnel/state.d.ts.map +1 -1
  142. package/dist/lib/tunnel/state.js +12 -58
  143. package/package.json +1 -6
  144. package/src/commander.ts +0 -10
  145. package/src/commands/files.ts +5 -13
  146. package/src/commands/servers.ts +23 -12
  147. package/src/commands/tunnel.ts +166 -533
  148. package/src/commands/workflow.ts +8 -58
  149. package/src/core/agents/coord-client.ts +0 -20
  150. package/src/core/agents/live-authority-v3.ts +0 -17
  151. package/src/core/agents/live-lifecycle-v3.ts +14 -52
  152. package/src/core/agents/state/heartbeat-writer.ts +12 -29
  153. package/src/core/agents/state/live-coordination-writer.ts +0 -29
  154. package/src/core/agents/state/pidmap.ts +2 -15
  155. package/src/core/agents/state/proc-start.ts +41 -69
  156. package/src/core/agents/state/service-process.ts +217 -0
  157. package/src/core/agents/state/stale-sweep.ts +82 -247
  158. package/src/core/artifacts/activity.ts +9 -2
  159. package/src/core/artifacts/delivery-card.ts +1 -7
  160. package/src/core/artifacts/index.ts +45 -12
  161. package/src/core/context/index.ts +207 -272
  162. package/src/core/context/observation.ts +40 -9
  163. package/src/core/events/v3/authority-outbox.ts +0 -56
  164. package/src/core/events/v3/producers/coordination-recorder.ts +0 -15
  165. package/src/core/events/v3/producers/recorder.ts +68 -94
  166. package/src/core/events/v3/runtime-build.ts +62 -0
  167. package/src/core/governor/index.ts +1 -2
  168. package/src/core/governor/service-read.ts +15 -114
  169. package/src/core/governor/service.ts +36 -220
  170. package/src/core/hooks/cli.ts +85 -47
  171. package/src/core/hooks/resolve/owner.ts +2 -2
  172. package/src/core/resources/sampler.ts +3 -2
  173. package/src/core/resources/service-status.ts +6 -35
  174. package/src/core/resources/service.ts +23 -133
  175. package/src/core/resources/status.ts +3 -2
  176. package/src/core/semantic/service.ts +8 -2
  177. package/src/core/servers/index.ts +86 -228
  178. package/src/core/servers/tunnels.ts +3 -55
  179. package/src/core/storage/durable-history.ts +52 -20
  180. package/src/core/storage/segments.ts +79 -17
  181. package/src/core/supervisor/service.ts +33 -155
  182. package/src/core/supervisor/services.ts +2 -2
  183. package/src/core/supervisor/status.ts +10 -85
  184. package/src/core/work/state.ts +7 -7
  185. package/src/core/workflow/engine.ts +22 -74
  186. package/src/core/workflow/index.ts +2 -13
  187. package/src/core/workflow/live-session-v3.ts +5 -146
  188. package/src/core/workflow/proof.ts +40 -104
  189. package/src/core/workflow/resume-lock.ts +179 -0
  190. package/src/core/workflow/run-state.ts +3 -207
  191. package/src/core/workflow/spawn-claude.ts +0 -18
  192. package/src/core/workflow/spawn-codex.ts +0 -13
  193. package/src/core/workflow/spawn-cursor.ts +0 -18
  194. package/src/core/workflow/spawn-opencode.ts +0 -14
  195. package/src/core/workflow/types.ts +11 -41
  196. package/src/core/workflow/workspaces/leases.ts +1 -1
  197. package/src/core/workflow/workspaces/local-git.ts +120 -239
  198. package/src/core/workflow/workspaces/ownership.ts +3 -158
  199. package/src/core/workflow/workspaces/reclaim.ts +3 -9
  200. package/src/core/workflow/workspaces/recovery.ts +1 -1
  201. package/src/core/workflow/workspaces/state.ts +1 -5
  202. package/src/lib/identities/assume.ts +0 -4
  203. package/src/lib/tunnel/state.ts +15 -70
  204. package/dist/commands/turn-rollback.d.ts +0 -5
  205. package/dist/commands/turn-rollback.d.ts.map +0 -1
  206. package/dist/commands/turn-rollback.js +0 -76
  207. package/dist/core/agents/state/process-handle.d.ts +0 -26
  208. package/dist/core/agents/state/process-handle.d.ts.map +0 -1
  209. package/dist/core/agents/state/process-handle.js +0 -121
  210. package/dist/core/agents/state/unchanged-file.d.ts +0 -44
  211. package/dist/core/agents/state/unchanged-file.d.ts.map +0 -1
  212. package/dist/core/agents/state/unchanged-file.js +0 -390
  213. package/dist/core/events/v3/generation-custody.d.ts +0 -5
  214. package/dist/core/events/v3/generation-custody.d.ts.map +0 -1
  215. package/dist/core/events/v3/generation-custody.js +0 -50
  216. package/dist/core/turn-rollback/content.d.ts +0 -53
  217. package/dist/core/turn-rollback/content.d.ts.map +0 -1
  218. package/dist/core/turn-rollback/content.js +0 -396
  219. package/dist/core/turn-rollback/index.d.ts +0 -72
  220. package/dist/core/turn-rollback/index.d.ts.map +0 -1
  221. package/dist/core/turn-rollback/index.js +0 -443
  222. package/dist/core/workflow/failure-evidence.d.ts +0 -16
  223. package/dist/core/workflow/failure-evidence.d.ts.map +0 -1
  224. package/dist/core/workflow/failure-evidence.js +0 -114
  225. package/dist/core/workflow/recovery-audit.d.ts +0 -30
  226. package/dist/core/workflow/recovery-audit.d.ts.map +0 -1
  227. package/dist/core/workflow/recovery-audit.js +0 -116
  228. package/src/commands/turn-rollback.ts +0 -111
  229. package/src/core/agents/state/process-handle.ts +0 -165
  230. package/src/core/agents/state/unchanged-file.ts +0 -456
  231. package/src/core/events/v3/generation-custody.ts +0 -59
  232. package/src/core/turn-rollback/content.ts +0 -499
  233. package/src/core/turn-rollback/index.ts +0 -580
  234. package/src/core/workflow/failure-evidence.ts +0 -141
  235. package/src/core/workflow/recovery-audit.ts +0 -181
@@ -1,101 +1,15 @@
1
1
  import { closeSync, existsSync, openSync, readFileSync, readSync, statSync } from "node:fs";
2
- import { hostname } from "node:os";
3
2
  import { join, resolve } from "node:path";
4
3
  import { gunzipSync } from "node:zlib";
5
4
  import { coordEnv } from "../../lib/env.js";
6
- import { verifyProcessGeneration, } from "../agents/state/proc-start.js";
7
- import { currentHarneryRuntimeBuild } from "../events/v3/runtime-build.js";
5
+ import { observeServiceProcess, } from "../agents/state/service-process.js";
6
+ import { serviceBuildStatus } from "../events/v3/runtime-build.js";
8
7
  import { createStorageCatalog } from "../storage/catalog.js";
9
8
  import { parseLogRecord } from "../storage/jsonl.js";
10
9
  import { familyLogDirectory, readSegmentManifest } from "../storage/segments.js";
11
10
  const MAX_FILE_BYTES = 512 * 1024;
12
11
  const MAX_LOG_RECORDS = 10_000;
13
12
  const MAX_GOALS = 100;
14
- export function currentGovernorServiceBuild() {
15
- let version = "unknown";
16
- let revision = "unknown";
17
- try {
18
- const manifest = JSON.parse(readFileSync(new URL("../../../package.json", import.meta.url), "utf8"));
19
- if (typeof manifest.version === "string" && manifest.version.length <= 100) {
20
- version = manifest.version;
21
- }
22
- }
23
- catch {
24
- // Missing package metadata cannot establish that the running build is current.
25
- }
26
- try {
27
- revision = currentHarneryRuntimeBuild();
28
- }
29
- catch {
30
- // Status still reports the unavailable build instead of guessing a match.
31
- }
32
- return { version, revision };
33
- }
34
- export function governorServiceBuildStatus(record) {
35
- const installed_build = currentGovernorServiceBuild();
36
- const candidate = record?.running_build;
37
- const running_build = candidate &&
38
- typeof candidate.version === "string" &&
39
- candidate.version.length > 0 &&
40
- candidate.version.length <= 100 &&
41
- typeof candidate.revision === "string" &&
42
- candidate.revision.length > 0 &&
43
- candidate.revision.length <= 100 &&
44
- candidate.version !== "unknown" &&
45
- candidate.revision !== "unknown"
46
- ? candidate
47
- : null;
48
- const restart_needed = running_build === null ||
49
- installed_build.version === "unknown" ||
50
- installed_build.revision === "unknown" ||
51
- running_build.version !== installed_build.version ||
52
- running_build.revision !== installed_build.revision;
53
- return {
54
- running_build,
55
- installed_build,
56
- restart_needed,
57
- build_status: running_build === null
58
- ? "running build unknown; restart needed"
59
- : restart_needed
60
- ? "restart needed"
61
- : "current",
62
- };
63
- }
64
- /** An unknown token or process probe cannot establish a running or stopped owner. */
65
- export function observeGovernorServiceProcess(record, dependencies = {}) {
66
- if (!record)
67
- return { generation: "unknown", liveness: "stopped" };
68
- const generation = record.host === hostname()
69
- ? verifyProcessGeneration(record.pid, record.start_token, dependencies.readToken)
70
- : "unknown";
71
- if (record.host !== hostname())
72
- return { generation, liveness: "unknown" };
73
- try {
74
- const present = (dependencies.probePid ?? probePid)(record.pid);
75
- if (!present)
76
- return { generation, liveness: "stopped" };
77
- }
78
- catch (error) {
79
- return {
80
- generation,
81
- liveness: error.code === "ESRCH" ? "stopped" : "unknown",
82
- };
83
- }
84
- return {
85
- generation,
86
- liveness: generation === "same"
87
- ? record.state === "stopped"
88
- ? "stopped"
89
- : "running"
90
- : generation === "different"
91
- ? "stopped"
92
- : "unknown",
93
- };
94
- }
95
- function probePid(pid) {
96
- process.kill(pid, 0);
97
- return true;
98
- }
99
13
  export function readGovernorServiceConfig(coordRootRaw) {
100
14
  const coordRoot = resolve(coordRootRaw);
101
15
  const config = readBoundedJson(join(serviceDir(coordRoot), "config.json"), "governor service configuration");
@@ -151,15 +65,17 @@ export function readGovernorServiceStatus(coordRootRaw, dependencies = {}) {
151
65
  catch {
152
66
  // Runtime is recoverable and must not make the dashboard unreadable.
153
67
  }
154
- const observation = observeGovernorServiceProcess(record, dependencies);
155
- if (!record && existsSync(join(serviceDir(coordRoot), "status.json"))) {
156
- observation.liveness = "unknown";
157
- }
68
+ const observation = record
69
+ ? observeServiceProcess(record, dependencies)
70
+ : {
71
+ generation: "unknown",
72
+ liveness: existsSync(join(serviceDir(coordRoot), "status.json")) ? "unknown" : "stopped",
73
+ };
158
74
  return {
159
- running: observation.liveness === "running" && record?.state !== "stopped",
75
+ running: observation.liveness === "running",
160
76
  stale: observation.liveness === "stopped" && record !== undefined && record.state !== "stopped",
161
77
  ...observation,
162
- ...governorServiceBuildStatus(record),
78
+ ...serviceBuildStatus(record?.running_build),
163
79
  record,
164
80
  config,
165
81
  runtime,
@@ -1,4 +1,5 @@
1
- import { type ProcessGenerationSignalDependencies, type ProcessGenerationVerdict } from "../agents/state/proc-start.js";
1
+ import { type ProcessGenerationVerdict } from "../agents/state/proc-start.js";
2
+ import { type ServiceProcessDependencies } from "../agents/state/service-process.js";
2
3
  import { type NormalizedPolicy, type PolicyIsolation } from "../policy/index.js";
3
4
  import type { RunWorkItemInput } from "../work/index.js";
4
5
  import { type GovernorRunReport, type GovernorStopReason } from "./runner.js";
@@ -55,9 +56,6 @@ export interface GovernorServiceBuild {
55
56
  version: string;
56
57
  revision: string;
57
58
  }
58
- export interface GovernorServiceProcessDependencies extends ProcessGenerationSignalDependencies {
59
- probePid?: (pid: number) => boolean;
60
- }
61
59
  export interface GovernorServiceStatusRecord {
62
60
  schema_version: typeof GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION;
63
61
  pid: number;
@@ -122,10 +120,8 @@ export interface RunGovernorServiceDaemonInput {
122
120
  }
123
121
  export declare function configureGovernorService(input: ConfigureGovernorServiceInput): GovernorServiceConfig;
124
122
  export declare function readGovernorServiceConfig(coordRootRaw: string): GovernorServiceConfig;
125
- export declare function readGovernorServiceRuntime(coordRootRaw: string): GovernorServiceRuntime | undefined;
126
- export declare function readGovernorServiceStatus(coordRootRaw: string, dependencies?: GovernorServiceProcessDependencies): GovernorServiceStatus;
127
123
  export declare function spawnGovernorService(coordRootRaw: string): Promise<GovernorServiceStatus>;
128
- export declare function requestGovernorServiceStop(coordRootRaw: string, dependencies?: GovernorServiceProcessDependencies): GovernorServiceStatus;
124
+ export declare function requestGovernorServiceStop(coordRootRaw: string, dependencies?: ServiceProcessDependencies): GovernorServiceStatus;
129
125
  export declare function runGovernorServiceSweep(input: RunGovernorServiceSweepInput): Promise<GovernorServiceSweepReport>;
130
126
  export declare function runGovernorServiceDaemon(input: RunGovernorServiceDaemonInput): Promise<GovernorServiceStatusRecord>;
131
127
  export declare function governorServiceLogPath(coordRoot: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/core/governor/service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/core/governor/service.ts"],"names":[],"mappings":"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"}
@@ -1,17 +1,19 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { randomBytes, randomUUID } from "node:crypto";
3
- import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
3
+ import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
4
4
  import { hostname } from "node:os";
5
5
  import { dirname, join, resolve } from "node:path";
6
6
  import { coordEnv } from "../../lib/env.js";
7
- import { processStartToken, signalIfSameGeneration, } from "../agents/state/proc-start.js";
7
+ import { processStartToken } from "../agents/state/proc-start.js";
8
+ import { acquireServiceLease, requestServiceStop, serviceStartRefusal, } from "../agents/state/service-process.js";
8
9
  import { resolveBinName } from "../config.js";
10
+ import { installedHarneryBuild } from "../events/v3/runtime-build.js";
9
11
  import { normalizePolicy } from "../policy/index.js";
10
12
  import { closeProcessLoggers, legacyLogFields, processLogger } from "../storage/logger.js";
11
13
  import { stateDirMode, stateFileMode } from "../storage/modes.js";
12
14
  import { RotatingTextSink } from "../storage/process-log.js";
13
15
  import { runGovernor } from "./runner.js";
14
- import { currentGovernorServiceBuild, governorServiceBuildStatus, observeGovernorServiceProcess, } from "./service-read.js";
16
+ import { readGovernorServiceRuntime, readGovernorServiceStatus } from "./service-read.js";
15
17
  import { readGovernor } from "./state.js";
16
18
  export const GOVERNOR_SERVICE_CONFIG_SCHEMA_VERSION = 1;
17
19
  export const GOVERNOR_SERVICE_RUNTIME_SCHEMA_VERSION = 1;
@@ -21,15 +23,9 @@ const MAX_GOALS = 100;
21
23
  const MAX_ERROR = 2_000;
22
24
  export function configureGovernorService(input) {
23
25
  const coordRoot = resolve(input.coordRoot);
24
- const active = readStatusRecord(coordRoot);
25
- if (!active && existsSync(serviceStatusPath(coordRoot))) {
26
- throw serviceStartRefusal(coordRoot, undefined, "unknown");
27
- }
28
- if (active) {
29
- const liveness = statusOwnerIsLive(active);
30
- if (liveness !== "stopped")
31
- throw serviceStartRefusal(coordRoot, active.pid, liveness);
32
- }
26
+ const current = readGovernorServiceStatus(coordRoot);
27
+ if (current.liveness !== "stopped")
28
+ throw startRefusal(coordRoot, current.record?.pid, current.liveness);
33
29
  const goalIds = unique(input.goalIds.map((value) => value.trim()).filter(Boolean));
34
30
  if (goalIds.length < 1 || goalIds.length > MAX_GOALS) {
35
31
  throw new Error(`governor service requires from 1 to ${MAX_GOALS} unique goal ids`);
@@ -65,57 +61,12 @@ export function readGovernorServiceConfig(coordRootRaw) {
65
61
  validateConfig(coordRoot, config);
66
62
  return config;
67
63
  }
68
- export function readGovernorServiceRuntime(coordRootRaw) {
69
- const coordRoot = resolve(coordRootRaw);
70
- if (!existsSync(serviceRuntimePath(coordRoot)))
71
- return undefined;
72
- const runtime = readBoundedJson(serviceRuntimePath(coordRoot), "governor service runtime");
73
- if (runtime.schema_version !== GOVERNOR_SERVICE_RUNTIME_SCHEMA_VERSION ||
74
- !validTimestamp(runtime.config_created_at) ||
75
- !validTimestamp(runtime.updated_at) ||
76
- !runtime.goals ||
77
- typeof runtime.goals !== "object" ||
78
- Array.isArray(runtime.goals)) {
79
- throw new Error("governor service runtime has an unsupported schema");
80
- }
81
- return runtime;
82
- }
83
- export function readGovernorServiceStatus(coordRootRaw, dependencies = {}) {
84
- const coordRoot = resolve(coordRootRaw);
85
- const record = readStatusRecord(coordRoot);
86
- let config;
87
- let runtime;
88
- try {
89
- config = readGovernorServiceConfig(coordRoot);
90
- }
91
- catch {
92
- // A service has no usable configuration until explicitly configured.
93
- }
94
- try {
95
- runtime = readGovernorServiceRuntime(coordRoot);
96
- }
97
- catch {
98
- // Status remains readable when recoverable runtime state is corrupt.
99
- }
100
- const observation = observeGovernorServiceProcess(record, dependencies);
101
- if (!record && existsSync(serviceStatusPath(coordRoot)))
102
- observation.liveness = "unknown";
103
- return {
104
- running: observation.liveness === "running" && record?.state !== "stopped",
105
- stale: observation.liveness === "stopped" && record !== undefined && record.state !== "stopped",
106
- ...observation,
107
- ...governorServiceBuildStatus(record),
108
- record,
109
- config,
110
- runtime,
111
- };
112
- }
113
64
  export async function spawnGovernorService(coordRootRaw) {
114
65
  const coordRoot = resolve(coordRootRaw);
115
66
  readGovernorServiceConfig(coordRoot);
116
67
  const current = readGovernorServiceStatus(coordRoot);
117
68
  if (current.liveness !== "stopped") {
118
- throw serviceStartRefusal(coordRoot, current.record?.pid, current.liveness);
69
+ throw startRefusal(coordRoot, current.record?.pid, current.liveness);
119
70
  }
120
71
  mkdirSync(serviceDir(coordRoot), { recursive: true, mode: stateDirMode() });
121
72
  const sharedLogs = coordEnv("SHARED_LOGS") !== "0";
@@ -164,18 +115,7 @@ export function requestGovernorServiceStop(coordRootRaw, dependencies = {}) {
164
115
  if ((status.record?.state === "stopped" || !status.record) && status.liveness === "stopped") {
165
116
  return { ...status, signal_sent: false, signal_verdict: status.generation };
166
117
  }
167
- writePrivateJsonAtomic(serviceStopPath(coordRoot), {
168
- requested_at: new Date().toISOString(),
169
- requested_by_pid: process.pid,
170
- });
171
- const signal = status.record?.host === hostname() && status.record.state !== "stopped"
172
- ? signalIfSameGeneration(status.record.pid, status.record.start_token, "SIGTERM", dependencies)
173
- : { sent: false, verdict: status.generation };
174
- return {
175
- ...readGovernorServiceStatus(coordRoot, dependencies),
176
- signal_sent: signal.sent,
177
- signal_verdict: signal.verdict,
178
- };
118
+ return requestServiceStop(status, () => readGovernorServiceStatus(coordRoot, dependencies), serviceStopPath(coordRoot), dependencies);
179
119
  }
180
120
  export async function runGovernorServiceSweep(input) {
181
121
  const coordRoot = resolve(input.coordRoot);
@@ -313,23 +253,17 @@ export async function runGovernorServiceSweep(input) {
313
253
  export async function runGovernorServiceDaemon(input) {
314
254
  const coordRoot = resolve(input.coordRoot);
315
255
  const config = readGovernorServiceConfig(coordRoot);
316
- const existing = readStatusRecord(coordRoot);
317
- if (!existing && existsSync(serviceStatusPath(coordRoot))) {
318
- throw serviceStartRefusal(coordRoot, undefined, "unknown");
319
- }
320
- if (existing) {
321
- const liveness = statusOwnerIsLive(existing);
322
- if (liveness !== "stopped")
323
- throw serviceStartRefusal(coordRoot, existing.pid, liveness);
324
- }
325
- const release = acquireServiceLease(coordRoot);
256
+ const current = readGovernorServiceStatus(coordRoot);
257
+ if (current.liveness !== "stopped")
258
+ throw startRefusal(coordRoot, current.record?.pid, current.liveness);
259
+ const { release } = acquireServiceLease(serviceLeasePath(coordRoot), (pid, liveness) => startRefusal(coordRoot, pid, liveness), { running_build: installedHarneryBuild() });
326
260
  rmSync(serviceStopPath(coordRoot), { force: true });
327
261
  const now = new Date().toISOString();
328
262
  const status = {
329
263
  schema_version: GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION,
330
264
  pid: process.pid,
331
265
  start_token: processStartToken(process.pid) ?? undefined,
332
- running_build: currentGovernorServiceBuild(),
266
+ running_build: installedHarneryBuild(),
333
267
  host: hostname(),
334
268
  nonce: randomUUID(),
335
269
  state: "starting",
@@ -537,107 +471,8 @@ function normalizeIsolation(value) {
537
471
  }
538
472
  throw new Error("service isolation must be shared, worktree, sandbox, or remote");
539
473
  }
540
- function acquireServiceLease(coordRoot) {
541
- const path = serviceLeasePath(coordRoot);
542
- mkdirSync(dirname(path), { recursive: true, mode: stateDirMode() });
543
- const owner = {
544
- pid: process.pid,
545
- start_token: processStartToken(process.pid) ?? undefined,
546
- running_build: currentGovernorServiceBuild(),
547
- host: hostname(),
548
- nonce: randomUUID(),
549
- created_at: new Date().toISOString(),
550
- };
551
- const acquire = () => {
552
- try {
553
- const fd = openSync(path, "wx", stateFileMode());
554
- try {
555
- writeFileSync(fd, `${JSON.stringify(owner)}\n`, "utf8");
556
- }
557
- finally {
558
- closeSync(fd);
559
- }
560
- return true;
561
- }
562
- catch (error) {
563
- if (error.code !== "EEXIST")
564
- throw error;
565
- return false;
566
- }
567
- };
568
- if (!acquire()) {
569
- const existing = readLease(path);
570
- const liveness = existing ? leaseOwnerIsLive(existing) : "unknown";
571
- if (liveness !== "stopped") {
572
- throw serviceStartRefusal(coordRoot, existing?.pid, liveness);
573
- }
574
- unlinkSync(path);
575
- if (!acquire())
576
- throw new Error("governor service lease raced with another process");
577
- }
578
- return () => {
579
- try {
580
- const existing = readLease(path);
581
- if (existing?.nonce === owner.nonce)
582
- unlinkSync(path);
583
- }
584
- catch {
585
- // A stale lease is recoverable by the next explicit service start.
586
- }
587
- };
588
- }
589
- function readLease(path) {
590
- try {
591
- const value = JSON.parse(readFileSync(path, "utf8"));
592
- return Number.isSafeInteger(value.pid) &&
593
- (value.pid ?? 0) > 0 &&
594
- typeof value.host === "string" &&
595
- typeof value.nonce === "string" &&
596
- typeof value.created_at === "string"
597
- ? {
598
- ...value,
599
- start_token: typeof value.start_token === "string" ? value.start_token : undefined,
600
- }
601
- : null;
602
- }
603
- catch {
604
- return null;
605
- }
606
- }
607
- function leaseOwnerIsLive(lease) {
608
- return observeGovernorServiceProcess({ ...lease, state: "running" }).liveness;
609
- }
610
- function readStatusRecord(coordRoot) {
611
- if (!existsSync(serviceStatusPath(coordRoot)))
612
- return undefined;
613
- try {
614
- const value = readBoundedJson(serviceStatusPath(coordRoot), "governor service status");
615
- if (value.schema_version !== GOVERNOR_SERVICE_STATUS_SCHEMA_VERSION ||
616
- !Number.isSafeInteger(value.pid) ||
617
- value.pid < 1 ||
618
- typeof value.host !== "string" ||
619
- typeof value.nonce !== "string" ||
620
- !validTimestamp(value.started_at) ||
621
- !validTimestamp(value.heartbeat_at)) {
622
- return undefined;
623
- }
624
- return {
625
- ...value,
626
- start_token: typeof value.start_token === "string" ? value.start_token : undefined,
627
- };
628
- }
629
- catch {
630
- return undefined;
631
- }
632
- }
633
- function statusOwnerIsLive(record) {
634
- return observeGovernorServiceProcess(record).liveness;
635
- }
636
- function serviceStartRefusal(coordRoot, pid, liveness) {
637
- const reason = liveness === "unknown"
638
- ? `governor service process generation is unknown${pid ? ` for pid ${pid}` : ""}`
639
- : `governor service process is still running under pid ${pid}`;
640
- return new Error(`${reason}; run \`${resolveBinName(coordRoot)} governor service stop\` to write a durable stop request before starting or reconfiguring it`);
474
+ function startRefusal(coordRoot, pid, liveness) {
475
+ return serviceStartRefusal("governor service", `${resolveBinName(coordRoot)} governor service stop`, pid, liveness);
641
476
  }
642
477
  export function appendGovernorServiceDiagnostic(coordRoot, data) {
643
478
  if (coordEnv("SHARED_LOGS") !== "0") {
@@ -631,6 +631,9 @@ async function main() {
631
631
  if (eventName === "runtime-context-retry") {
632
632
  return runRuntimeContextRetryWorker(coordRoot, adapter, extra);
633
633
  }
634
+ if (eventName === SESSION_MAINTENANCE_EVENT) {
635
+ return runSessionMaintenanceWorker(coordRoot, adapter);
636
+ }
634
637
  const ledgerRoute = resolveLiveEventLedgerRouteV3(coordRoot);
635
638
  // Always log a breadcrumb, useful when an event_type maps to null or owner
636
639
  // resolution fails. Stays cheap (one append) and self-prunes via repo log
@@ -1007,7 +1010,7 @@ function recordContextTelemetry(run) {
1007
1010
  }
1008
1011
  }
1009
1012
  async function handleSessionStarted(run) {
1010
- const { coordRoot, adapter, behavior, payload, owner, sessionId, data } = run;
1013
+ const { coordRoot, adapter, payload, owner, sessionId, data } = run;
1011
1014
  // A configured backup runs out of process and is freshness-gated per host.
1012
1015
  // Startup never waits for restic or a remote provider; the child owns no
1013
1016
  // hook stdio, so the harness is not held open until it finishes. A failed
@@ -1019,53 +1022,10 @@ async function handleSessionStarted(run) {
1019
1022
  catch (err) {
1020
1023
  logError(coordRoot, err, { phase: "backup-schedule" });
1021
1024
  }
1022
- // Effect (journal-maintaining adapters): prune stale journal archives +
1023
- // sweep orphans. The recovery-cue is merged into the session-start
1024
- // additionalContext inside emitSessionStartSystemMessage.
1025
- if (behavior.journalMaintenance)
1026
- journalJanitor(coordRoot);
1027
- imageJanitor(coordRoot);
1028
- // Session start is the only caller of the artifact janitor and the storage
1029
- // maintenance pass, so both load here instead of on every tool call.
1030
- const { autoCleanArtifacts } = await import("../artifacts/index.js");
1031
- const { autoCleanEventV3Archives } = await import("../events/v3/archive-retention.js");
1032
- const { createAutomaticMaintenanceComposition, runAutomaticMaintenancePass } = await import("../storage/maintenance-providers.js");
1033
- // Effect: throttled hourly artifact sweep (see autoCleanArtifacts). It
1034
- // deletes expired workspaces, plus unheld workspaces over the per-bundle
1035
- // ceiling or repository budget once they have been idle past
1036
- // artifacts.idle_grace_hours. Each deletion is rechecked first and recorded
1037
- // in .harnery/artifact-deletions.jsonl. Best-effort like every janitor
1038
- // here: a failure logs and never blocks session start.
1039
- try {
1040
- autoCleanArtifacts(coordRoot);
1041
- }
1042
- catch (err) {
1043
- logError(coordRoot, err, { phase: "artifact-auto-clean" });
1044
- }
1045
- // Effect: apply the same daily throttle to closed V3 epochs. The newest
1046
- // recovery epochs remain protected by the archive retention policy.
1047
- try {
1048
- autoCleanEventV3Archives(coordRoot);
1049
- }
1050
- catch (err) {
1051
- logError(coordRoot, err, { phase: "event-v3-archive-auto-clean" });
1052
- }
1053
- // Plan one bounded, claim-first global slice from cached pressure only.
1054
- // Existing owner janitors above remain the only active executors until
1055
- // each provider receives a separate production activation.
1056
- try {
1057
- await runAutomaticMaintenancePass(createAutomaticMaintenanceComposition(coordRoot, {
1058
- journal: () => {
1059
- if (behavior.journalMaintenance)
1060
- journalJanitor(coordRoot);
1061
- },
1062
- images: () => imageJanitor(coordRoot),
1063
- artifacts: () => autoCleanArtifacts(coordRoot),
1064
- }));
1065
- }
1066
- catch (err) {
1067
- logError(coordRoot, err, { phase: "storage-maintenance-auto" });
1068
- }
1025
+ // Storage maintenance can walk large stores. It runs in a detached worker so
1026
+ // session start emits its context without waiting for it; an adapter that
1027
+ // stops a slow hook would otherwise drop that context entirely.
1028
+ scheduleSessionMaintenance(coordRoot, adapter);
1069
1029
  let recovery = null;
1070
1030
  if (payload?.source === "compact") {
1071
1031
  try {
@@ -1518,6 +1478,76 @@ async function handleCompletedResponse(run) {
1518
1478
  });
1519
1479
  return 0;
1520
1480
  }
1481
+ const SESSION_MAINTENANCE_EVENT = "session-maintenance";
1482
+ function scheduleSessionMaintenance(coordRoot, adapter) {
1483
+ const modulePath = process.argv[1];
1484
+ if (!modulePath)
1485
+ return;
1486
+ try {
1487
+ const child = spawn(process.execPath, [modulePath, SESSION_MAINTENANCE_EVENT, "--adapter", adapter], {
1488
+ cwd: coordRoot,
1489
+ detached: true,
1490
+ stdio: "ignore",
1491
+ env: childEnv(coordRoot),
1492
+ });
1493
+ child.unref();
1494
+ }
1495
+ catch (err) {
1496
+ logError(coordRoot, err, { phase: "session-maintenance-spawn" });
1497
+ }
1498
+ }
1499
+ /**
1500
+ * Session-start storage maintenance, run out of the hook's process. Every step
1501
+ * is best-effort and throttled by its own stamp: a failure logs and never
1502
+ * reaches the session.
1503
+ */
1504
+ async function runSessionMaintenanceWorker(coordRoot, adapter) {
1505
+ const journalMaintenance = adapter ? adapterBehavior(adapter).journalMaintenance : false;
1506
+ // Effect (journal-maintaining adapters): prune stale journal archives +
1507
+ // sweep orphans. The recovery cue is read separately at session start.
1508
+ if (journalMaintenance)
1509
+ journalJanitor(coordRoot);
1510
+ imageJanitor(coordRoot);
1511
+ const { autoCleanArtifacts } = await import("../artifacts/index.js");
1512
+ const { autoCleanEventV3Archives } = await import("../events/v3/archive-retention.js");
1513
+ const { createAutomaticMaintenanceComposition, runAutomaticMaintenancePass } = await import("../storage/maintenance-providers.js");
1514
+ // Effect: throttled hourly artifact sweep (see autoCleanArtifacts). It
1515
+ // deletes expired workspaces, plus unheld workspaces over the per-bundle
1516
+ // ceiling or repository budget once they have been idle past
1517
+ // artifacts.idle_grace_hours. Each deletion is rechecked first and recorded
1518
+ // in .harnery/artifact-deletions.jsonl.
1519
+ try {
1520
+ autoCleanArtifacts(coordRoot);
1521
+ }
1522
+ catch (err) {
1523
+ logError(coordRoot, err, { phase: "artifact-auto-clean" });
1524
+ }
1525
+ // Effect: apply the same daily throttle to closed V3 epochs. The newest
1526
+ // recovery epochs remain protected by the archive retention policy.
1527
+ try {
1528
+ autoCleanEventV3Archives(coordRoot);
1529
+ }
1530
+ catch (err) {
1531
+ logError(coordRoot, err, { phase: "event-v3-archive-auto-clean" });
1532
+ }
1533
+ // Plan one bounded, claim-first global slice from cached pressure only.
1534
+ // Existing owner janitors above remain the only active executors until
1535
+ // each provider receives a separate production activation.
1536
+ try {
1537
+ await runAutomaticMaintenancePass(createAutomaticMaintenanceComposition(coordRoot, {
1538
+ journal: () => {
1539
+ if (journalMaintenance)
1540
+ journalJanitor(coordRoot);
1541
+ },
1542
+ images: () => imageJanitor(coordRoot),
1543
+ artifacts: () => autoCleanArtifacts(coordRoot),
1544
+ }));
1545
+ }
1546
+ catch (err) {
1547
+ logError(coordRoot, err, { phase: "storage-maintenance-auto" });
1548
+ }
1549
+ return 0;
1550
+ }
1521
1551
  function scheduleRuntimeContextRetry(coordRoot, adapter, nativeSessionId) {
1522
1552
  const modulePath = process.argv[1];
1523
1553
  if (!modulePath)
@@ -4,7 +4,7 @@ import { join } from "node:path";
4
4
  import { coordEnv } from "../../../lib/env.js";
5
5
  import { resolveOwnerBySessionEnv } from "../../agents/coord-client.js";
6
6
  import { readLiveCoordinationRow } from "../../agents/state/live-coordination-view.js";
7
- import { checkPidToken } from "../../agents/state/proc-start.js";
7
+ import { verifyProcessGeneration } from "../../agents/state/proc-start.js";
8
8
  /**
9
9
  * Resolve the canonical `instance_id` for the current hook invocation.
10
10
  *
@@ -91,7 +91,7 @@ export function resolveOwner(opts) {
91
91
  // A row whose start token disagrees with the process now holding this
92
92
  // pid is about a different, earlier process. Believing it hands this
93
93
  // session another agent's identity, so walk past it.
94
- const recycled = checkPidToken(pid, startToken || undefined) === "mismatch";
94
+ const recycled = verifyProcessGeneration(pid, startToken) === "different";
95
95
  if (owner && owner.length > 0 && !recycled) {
96
96
  return {
97
97
  instance_id: owner,
@@ -5,7 +5,7 @@ import { basename, join } from "node:path";
5
5
  import { performance } from "node:perf_hooks";
6
6
  import { readLiveCoordinationRows } from "../agents/state/live-coordination-view.js";
7
7
  import { parsePidmapRow } from "../agents/state/pidmap.js";
8
- import { checkPidToken } from "../agents/state/proc-start.js";
8
+ import { verifyProcessGeneration } from "../agents/state/proc-start.js";
9
9
  import { RESOURCE_SNAPSHOT_SCHEMA_VERSION, } from "./contract.js";
10
10
  import { collectWindowsHost, collectWindowsHostInBackground, sampleNativeResources, } from "./native.js";
11
11
  import { collectSystemResources } from "./system.js";
@@ -266,7 +266,7 @@ function readOwnershipAnchors(coordRoot, procRoot, readings, services, liveSessi
266
266
  continue;
267
267
  try {
268
268
  const row = parsePidmapRow(readFileSync(join(directory, entry), "utf8"));
269
- if (!row.instanceId || checkPidToken(pid, row.startToken) === "mismatch")
269
+ if (!row.instanceId || verifyProcessGeneration(pid, row.startToken) === "different")
270
270
  continue;
271
271
  anchors.set(pid, { kind: "agent", id: row.instanceId, source: "pid-map" });
272
272
  }
@@ -1,16 +1,4 @@
1
- import { type ProcessGenerationVerdict } from "../agents/state/proc-start.js";
1
+ import { type ServiceProcessDependencies } from "../agents/state/service-process.js";
2
2
  import { type ResourceServiceStatus } from "./contract.js";
3
- export interface ResourceProcessDependencies {
4
- readToken?: (pid: number) => string | null;
5
- probePid?: (pid: number) => unknown;
6
- }
7
- export declare function readResourceServiceStatus(coordRoot: string, nowMs?: number, dependencies?: ResourceProcessDependencies): ResourceServiceStatus;
8
- export declare function resourceProcessLiveness(owner: {
9
- pid: number;
10
- host: string;
11
- start_token?: string;
12
- }, dependencies?: ResourceProcessDependencies): {
13
- generation: ProcessGenerationVerdict;
14
- liveness: ResourceServiceStatus["liveness"];
15
- };
3
+ export declare function readResourceServiceStatus(coordRoot: string, nowMs?: number, dependencies?: ServiceProcessDependencies): ResourceServiceStatus;
16
4
  //# sourceMappingURL=service-status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service-status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service-status.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,wBAAwB,EAE9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,eAAe,CAAC;AAKvB,MAAM,WAAW,2BAA2B;IAC1C,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACrC;AAED,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,YAAY,GAAE,2BAAgC,GAC7C,qBAAqB,CA2BvB;AAcD,wBAAgB,uBAAuB,CACrC,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EAC1D,YAAY,GAAE,2BAAgC,GAC7C;IAAE,UAAU,EAAE,wBAAwB,CAAC;IAAC,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAA;CAAE,CAgBvF"}
1
+ {"version":3,"file":"service-status.d.ts","sourceRoot":"","sources":["../../../src/core/resources/service-status.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,0BAA0B,EAChC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,eAAe,CAAC;AAKvB,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,KAAK,SAAa,EAClB,YAAY,GAAE,0BAA+B,GAC5C,qBAAqB,CAyBvB"}