@amalgm/core 0.1.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.
- package/PURPOSE.md +94 -0
- package/README.md +30 -0
- package/dist/adapters/index.d.ts +13 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +11 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/identity/auth-records.d.ts +147 -0
- package/dist/identity/auth-records.d.ts.map +1 -0
- package/dist/identity/auth-records.js +354 -0
- package/dist/identity/auth-records.js.map +1 -0
- package/dist/identity/ids.d.ts +57 -0
- package/dist/identity/ids.d.ts.map +1 -0
- package/dist/identity/ids.js +80 -0
- package/dist/identity/ids.js.map +1 -0
- package/dist/identity/index.d.ts +14 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +14 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/labels.d.ts +115 -0
- package/dist/identity/labels.d.ts.map +1 -0
- package/dist/identity/labels.js +154 -0
- package/dist/identity/labels.js.map +1 -0
- package/dist/identity/layout.d.ts +188 -0
- package/dist/identity/layout.d.ts.map +1 -0
- package/dist/identity/layout.js +233 -0
- package/dist/identity/layout.js.map +1 -0
- package/dist/identity/ports.d.ts +31 -0
- package/dist/identity/ports.d.ts.map +1 -0
- package/dist/identity/ports.js +9 -0
- package/dist/identity/ports.js.map +1 -0
- package/dist/identity/product-state.d.ts +49 -0
- package/dist/identity/product-state.d.ts.map +1 -0
- package/dist/identity/product-state.js +55 -0
- package/dist/identity/product-state.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/supervision/app-health.d.ts +148 -0
- package/dist/supervision/app-health.d.ts.map +1 -0
- package/dist/supervision/app-health.js +165 -0
- package/dist/supervision/app-health.js.map +1 -0
- package/dist/supervision/app-restart.d.ts +105 -0
- package/dist/supervision/app-restart.d.ts.map +1 -0
- package/dist/supervision/app-restart.js +97 -0
- package/dist/supervision/app-restart.js.map +1 -0
- package/dist/supervision/health.d.ts +218 -0
- package/dist/supervision/health.d.ts.map +1 -0
- package/dist/supervision/health.js +227 -0
- package/dist/supervision/health.js.map +1 -0
- package/dist/supervision/index.d.ts +17 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +17 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/supervision/service-registration.d.ts +343 -0
- package/dist/supervision/service-registration.d.ts.map +1 -0
- package/dist/supervision/service-registration.js +543 -0
- package/dist/supervision/service-registration.js.map +1 -0
- package/dist/supervision/update.d.ts +231 -0
- package/dist/supervision/update.d.ts.map +1 -0
- package/dist/supervision/update.js +336 -0
- package/dist/supervision/update.js.map +1 -0
- package/dist/transport/admission.d.ts +235 -0
- package/dist/transport/admission.d.ts.map +1 -0
- package/dist/transport/admission.js +313 -0
- package/dist/transport/admission.js.map +1 -0
- package/dist/transport/auth.d.ts +232 -0
- package/dist/transport/auth.d.ts.map +1 -0
- package/dist/transport/auth.js +266 -0
- package/dist/transport/auth.js.map +1 -0
- package/dist/transport/index.d.ts +21 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +21 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/ingress.d.ts +94 -0
- package/dist/transport/ingress.d.ts.map +1 -0
- package/dist/transport/ingress.js +171 -0
- package/dist/transport/ingress.js.map +1 -0
- package/dist/transport/routing.d.ts +235 -0
- package/dist/transport/routing.d.ts.map +1 -0
- package/dist/transport/routing.js +288 -0
- package/dist/transport/routing.js.map +1 -0
- package/dist/transport/shipped-routes.d.ts +21 -0
- package/dist/transport/shipped-routes.d.ts.map +1 -0
- package/dist/transport/shipped-routes.js +53 -0
- package/dist/transport/shipped-routes.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime health contracts — the probe side of supervision.
|
|
3
|
+
*
|
|
4
|
+
* Axiom 5: supervision flows one way. The CLI parent probes its runtime
|
|
5
|
+
* children over `/healthz`; the children never probe back. This module owns
|
|
6
|
+
* both ends of that contract as pure decision logic:
|
|
7
|
+
*
|
|
8
|
+
* - the healthz body every runtime service publishes,
|
|
9
|
+
* - the parent-side validator that judges a probe answer,
|
|
10
|
+
* - the health/restart policies and the child supervision machine that
|
|
11
|
+
* turns probe results and exits into restart/degrade decisions.
|
|
12
|
+
*
|
|
13
|
+
* The host performs the actual HTTP request, process spawn, and kill; this
|
|
14
|
+
* module decides. Engine sources (production until cutover, axiom 9):
|
|
15
|
+
* `runtime/scripts/amalgm-mcp/server/routes/health.js` and
|
|
16
|
+
* `packages/amalgm/lib/supervisor.js`.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* The healthz body law (engine `server/routes/health.js:11-23`).
|
|
20
|
+
*
|
|
21
|
+
* `/healthz` is a liveness signal: the parent supervisor kills the service
|
|
22
|
+
* after repeated slow answers. It therefore always answers HTTP 200, performs
|
|
23
|
+
* no I/O, and starts no follow-up work — operational counts belong on
|
|
24
|
+
* diagnostic routes. (The engine learned this the hard way: letting the
|
|
25
|
+
* liveness probe inspect the user's state store made a large, healthy
|
|
26
|
+
* installation look dead by blocking its own event loop.)
|
|
27
|
+
*
|
|
28
|
+
* The body carries exactly these six keys and nothing else.
|
|
29
|
+
*/
|
|
30
|
+
export interface RuntimeHealthzBody {
|
|
31
|
+
readonly status: 'ok';
|
|
32
|
+
readonly service: string;
|
|
33
|
+
readonly runtime_label: string;
|
|
34
|
+
readonly runtime_instance_id: string;
|
|
35
|
+
readonly pid: number;
|
|
36
|
+
readonly activeAgentConversations: number;
|
|
37
|
+
}
|
|
38
|
+
/** `/healthz` always answers 200 — liveness is proven by answering at all. */
|
|
39
|
+
export declare const HEALTHZ_STATUS_CODE = 200;
|
|
40
|
+
/**
|
|
41
|
+
* Build the healthz body.
|
|
42
|
+
*
|
|
43
|
+
* KNOWN ENGINE BUG (health.js:17): the engine publishes the raw,
|
|
44
|
+
* un-normalized `AMALGM_RUNTIME_LABEL` (`process.env... || 'main'`). Aliases
|
|
45
|
+
* like `'canary'` therefore leak into the body verbatim, which breaks the
|
|
46
|
+
* UI's token binding — the UI compares against normalized labels
|
|
47
|
+
* (`main`/`preview`/`local`) and refuses to attach to a runtime that calls
|
|
48
|
+
* itself `canary`. This builder takes an ALREADY-NORMALIZED label; the host
|
|
49
|
+
* resolves the label through the identity module before publishing. The
|
|
50
|
+
* wound stays documented here until the engine adopts the SDK and deletes
|
|
51
|
+
* its raw read.
|
|
52
|
+
*
|
|
53
|
+
* The gauge (`activeAgentConversations`) is injected: reading it must be a
|
|
54
|
+
* synchronous in-memory read, never I/O — see the contract rule above.
|
|
55
|
+
*/
|
|
56
|
+
export declare function buildRuntimeHealthzBody(fields: {
|
|
57
|
+
service: string;
|
|
58
|
+
runtimeLabel: string;
|
|
59
|
+
runtimeInstanceId: string;
|
|
60
|
+
pid: number;
|
|
61
|
+
activeAgentConversations: number;
|
|
62
|
+
}): RuntimeHealthzBody;
|
|
63
|
+
export type HealthBodyVerdict = {
|
|
64
|
+
readonly healthy: true;
|
|
65
|
+
readonly reason: null;
|
|
66
|
+
} | {
|
|
67
|
+
readonly healthy: false;
|
|
68
|
+
readonly reason: 'bad_status_code' | 'unparseable_body' | 'runtime_instance_mismatch' | 'service_mismatch';
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Parent-side health-body validator — the decision half of the engine's
|
|
72
|
+
* `checkServiceHealth` (`packages/amalgm/lib/supervisor.js:940-985`); the
|
|
73
|
+
* HTTP transport half stays with the host. The laws, in engine order:
|
|
74
|
+
*
|
|
75
|
+
* 1. `statusCode < 200 || statusCode >= 500` → unhealthy.
|
|
76
|
+
* 2. An unparseable JSON body → unhealthy. An empty body parses as `{}`
|
|
77
|
+
* (the engine parses `text || '{}'`).
|
|
78
|
+
* 3. `runtime_instance_id || runtimeInstanceId` must equal the expected
|
|
79
|
+
* instance id (when one is expected) — a healthy answer from a STALE
|
|
80
|
+
* runtime is an unhealthy answer; this is what catches an old process
|
|
81
|
+
* squatting on the port.
|
|
82
|
+
* 4. `body.service`, if present at all, must equal the expected service.
|
|
83
|
+
* An absent `service` key passes (older runtimes; axiom 7).
|
|
84
|
+
*/
|
|
85
|
+
export declare function validateHealthBody(input: {
|
|
86
|
+
statusCode: number;
|
|
87
|
+
body: string | Record<string, unknown>;
|
|
88
|
+
expectedRuntimeInstanceId?: string;
|
|
89
|
+
expectedService?: string;
|
|
90
|
+
}): HealthBodyVerdict;
|
|
91
|
+
export interface ChildHealthPolicy {
|
|
92
|
+
readonly graceMs: number;
|
|
93
|
+
readonly intervalMs: number;
|
|
94
|
+
readonly timeoutMs: number;
|
|
95
|
+
readonly maxFailures: number;
|
|
96
|
+
}
|
|
97
|
+
/** Engine `supervisor.js:70-75`: the default child health policy. */
|
|
98
|
+
export declare const CHILD_HEALTH_POLICY: ChildHealthPolicy;
|
|
99
|
+
/**
|
|
100
|
+
* Engine `supervisor.js:77-80`: chat-server override — model turns hold the
|
|
101
|
+
* event loop longer, so probes get a longer timeout and a bigger budget.
|
|
102
|
+
*/
|
|
103
|
+
export declare const CHAT_SERVER_HEALTH_POLICY: {
|
|
104
|
+
readonly timeoutMs: number;
|
|
105
|
+
readonly maxFailures: number;
|
|
106
|
+
};
|
|
107
|
+
/** Engine `supervisor.js:304-309`: per-service policy resolution. */
|
|
108
|
+
export declare function healthPolicyForService(serviceName: string): ChildHealthPolicy;
|
|
109
|
+
export interface ChildRestartPolicy {
|
|
110
|
+
readonly initialDelayMs: number;
|
|
111
|
+
readonly maxDelayMs: number;
|
|
112
|
+
readonly stableAfterMs: number;
|
|
113
|
+
readonly maxRestarts: number;
|
|
114
|
+
readonly windowMs: number;
|
|
115
|
+
}
|
|
116
|
+
/** Engine `supervisor.js:62-68`: the child restart budget. */
|
|
117
|
+
export declare const CHILD_RESTART_POLICY: ChildRestartPolicy;
|
|
118
|
+
/**
|
|
119
|
+
* The ready deadline (engine `supervisor.js:1112-1114`): how long a child
|
|
120
|
+
* gets to become healthy before startup is declared failed —
|
|
121
|
+
* `graceMs + ((intervalMs + timeoutMs) * maxFailures)`.
|
|
122
|
+
* Defaults: 8000 + ((10000 + 2500) * 3) = 45500ms.
|
|
123
|
+
*/
|
|
124
|
+
export declare function readyDeadlineMs(policy?: ChildHealthPolicy): number;
|
|
125
|
+
/**
|
|
126
|
+
* Status vocabulary for a supervised child (axiom 8 — exactly these four).
|
|
127
|
+
* The engine additionally writes a transient `'stopping'` marker during
|
|
128
|
+
* shutdown (`supervisor.js:1183`); that is a teardown breadcrumb, not a
|
|
129
|
+
* supervision state, and is deliberately outside this vocabulary.
|
|
130
|
+
*/
|
|
131
|
+
export type ChildStatus = 'starting' | 'running' | 'restarting' | 'degraded';
|
|
132
|
+
export type HealthProbeDecision =
|
|
133
|
+
/** Probe passed while already `running` — reset the failure count, nothing else. */
|
|
134
|
+
{
|
|
135
|
+
readonly action: 'none';
|
|
136
|
+
}
|
|
137
|
+
/** First passing probe: the child is now `running` and its ready promise settles. */
|
|
138
|
+
| {
|
|
139
|
+
readonly action: 'mark-running';
|
|
140
|
+
}
|
|
141
|
+
/** Failure inside `graceMs` of launch — retried without counting (engine `supervisor.js:1049-1051`). */
|
|
142
|
+
| {
|
|
143
|
+
readonly action: 'retry-within-grace';
|
|
144
|
+
}
|
|
145
|
+
/** A counted failure below the budget. `log` matches the engine byte for byte (framing newline excluded). */
|
|
146
|
+
| {
|
|
147
|
+
readonly action: 'count-failure';
|
|
148
|
+
readonly failures: number;
|
|
149
|
+
readonly log: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The budget is spent (engine `supervisor.js:1060-1077`): SIGTERM the
|
|
153
|
+
* child, SIGKILL it after `sigkillAfterMs` if it lingers. The exit event
|
|
154
|
+
* then drives the restart machinery.
|
|
155
|
+
*/
|
|
156
|
+
| {
|
|
157
|
+
readonly action: 'restart';
|
|
158
|
+
readonly reason: 'health_check_failed';
|
|
159
|
+
readonly sigkillAfterMs: 5000;
|
|
160
|
+
readonly log: string;
|
|
161
|
+
};
|
|
162
|
+
export type ChildExitDecision =
|
|
163
|
+
/** Relaunch after `delayMs`; the delay doubles per attempt up to `maxDelayMs`. */
|
|
164
|
+
{
|
|
165
|
+
readonly action: 'restart-after';
|
|
166
|
+
readonly delayMs: number;
|
|
167
|
+
readonly log: string;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* The restart budget is exhausted (engine `supervisor.js:1087-1098`). The
|
|
171
|
+
* child is parked; per axiom 5 the state is reported honestly, and only a
|
|
172
|
+
* supervisor restart hands out a fresh budget.
|
|
173
|
+
*/
|
|
174
|
+
| {
|
|
175
|
+
readonly action: 'degrade';
|
|
176
|
+
readonly state: 'degraded';
|
|
177
|
+
readonly reason: 'restart_limit_exceeded';
|
|
178
|
+
readonly next_retry_at: null;
|
|
179
|
+
readonly log: string;
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* The child supervision machine (engine `supervisor.js:1034-1102` and
|
|
183
|
+
* `supervisor.js:1146-1171`), decisions as data. The host owns timers,
|
|
184
|
+
* spawning, and signals; this machine owns the counting:
|
|
185
|
+
*
|
|
186
|
+
* - probe failures within `graceMs` of a launch retry without counting;
|
|
187
|
+
* - the failure log is `health check failed (${n}/${max})`;
|
|
188
|
+
* - at `maxFailures` the decision is restart (`health_check_failed`,
|
|
189
|
+
* SIGKILL escalation after 5000ms);
|
|
190
|
+
* - exits after `stableAfterMs` of runtime reset the backoff and the
|
|
191
|
+
* crash window; earlier exits consume the `maxRestarts`-per-`windowMs`
|
|
192
|
+
* budget with doubling backoff, and exhausting it parks the child
|
|
193
|
+
* `degraded` with `next_retry_at: null`.
|
|
194
|
+
*
|
|
195
|
+
* All timestamps are injected epoch-ms — the machine never reads a clock.
|
|
196
|
+
* An illegal transition throws: it is a programming error in the host, not
|
|
197
|
+
* a process condition.
|
|
198
|
+
*/
|
|
199
|
+
export declare class ChildSupervisionMachine {
|
|
200
|
+
private readonly healthPolicy;
|
|
201
|
+
private readonly restartPolicy;
|
|
202
|
+
private state;
|
|
203
|
+
private failures;
|
|
204
|
+
private startedAt;
|
|
205
|
+
private restartDelayMs;
|
|
206
|
+
private restartHistory;
|
|
207
|
+
constructor(healthPolicy?: ChildHealthPolicy, restartPolicy?: ChildRestartPolicy);
|
|
208
|
+
get status(): ChildStatus;
|
|
209
|
+
get healthFailures(): number;
|
|
210
|
+
private setState;
|
|
211
|
+
/** The host spawned (or respawned) the process at `now`. */
|
|
212
|
+
launched(now: number): void;
|
|
213
|
+
/** The host completed a health probe at `now` with result `ok`. */
|
|
214
|
+
probe(ok: boolean, now: number): HealthProbeDecision;
|
|
215
|
+
/** The child process exited at `now` (and the host wants it kept alive). */
|
|
216
|
+
exited(now: number): ChildExitDecision;
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/supervision/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime health contracts — the probe side of supervision.
|
|
3
|
+
*
|
|
4
|
+
* Axiom 5: supervision flows one way. The CLI parent probes its runtime
|
|
5
|
+
* children over `/healthz`; the children never probe back. This module owns
|
|
6
|
+
* both ends of that contract as pure decision logic:
|
|
7
|
+
*
|
|
8
|
+
* - the healthz body every runtime service publishes,
|
|
9
|
+
* - the parent-side validator that judges a probe answer,
|
|
10
|
+
* - the health/restart policies and the child supervision machine that
|
|
11
|
+
* turns probe results and exits into restart/degrade decisions.
|
|
12
|
+
*
|
|
13
|
+
* The host performs the actual HTTP request, process spawn, and kill; this
|
|
14
|
+
* module decides. Engine sources (production until cutover, axiom 9):
|
|
15
|
+
* `runtime/scripts/amalgm-mcp/server/routes/health.js` and
|
|
16
|
+
* `packages/amalgm/lib/supervisor.js`.
|
|
17
|
+
*/
|
|
18
|
+
/** `/healthz` always answers 200 — liveness is proven by answering at all. */
|
|
19
|
+
export const HEALTHZ_STATUS_CODE = 200;
|
|
20
|
+
/**
|
|
21
|
+
* Build the healthz body.
|
|
22
|
+
*
|
|
23
|
+
* KNOWN ENGINE BUG (health.js:17): the engine publishes the raw,
|
|
24
|
+
* un-normalized `AMALGM_RUNTIME_LABEL` (`process.env... || 'main'`). Aliases
|
|
25
|
+
* like `'canary'` therefore leak into the body verbatim, which breaks the
|
|
26
|
+
* UI's token binding — the UI compares against normalized labels
|
|
27
|
+
* (`main`/`preview`/`local`) and refuses to attach to a runtime that calls
|
|
28
|
+
* itself `canary`. This builder takes an ALREADY-NORMALIZED label; the host
|
|
29
|
+
* resolves the label through the identity module before publishing. The
|
|
30
|
+
* wound stays documented here until the engine adopts the SDK and deletes
|
|
31
|
+
* its raw read.
|
|
32
|
+
*
|
|
33
|
+
* The gauge (`activeAgentConversations`) is injected: reading it must be a
|
|
34
|
+
* synchronous in-memory read, never I/O — see the contract rule above.
|
|
35
|
+
*/
|
|
36
|
+
export function buildRuntimeHealthzBody(fields) {
|
|
37
|
+
return {
|
|
38
|
+
status: 'ok',
|
|
39
|
+
service: fields.service,
|
|
40
|
+
runtime_label: fields.runtimeLabel,
|
|
41
|
+
runtime_instance_id: fields.runtimeInstanceId,
|
|
42
|
+
pid: fields.pid,
|
|
43
|
+
activeAgentConversations: fields.activeAgentConversations,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Parent-side health-body validator — the decision half of the engine's
|
|
48
|
+
* `checkServiceHealth` (`packages/amalgm/lib/supervisor.js:940-985`); the
|
|
49
|
+
* HTTP transport half stays with the host. The laws, in engine order:
|
|
50
|
+
*
|
|
51
|
+
* 1. `statusCode < 200 || statusCode >= 500` → unhealthy.
|
|
52
|
+
* 2. An unparseable JSON body → unhealthy. An empty body parses as `{}`
|
|
53
|
+
* (the engine parses `text || '{}'`).
|
|
54
|
+
* 3. `runtime_instance_id || runtimeInstanceId` must equal the expected
|
|
55
|
+
* instance id (when one is expected) — a healthy answer from a STALE
|
|
56
|
+
* runtime is an unhealthy answer; this is what catches an old process
|
|
57
|
+
* squatting on the port.
|
|
58
|
+
* 4. `body.service`, if present at all, must equal the expected service.
|
|
59
|
+
* An absent `service` key passes (older runtimes; axiom 7).
|
|
60
|
+
*/
|
|
61
|
+
export function validateHealthBody(input) {
|
|
62
|
+
if (input.statusCode < 200 || input.statusCode >= 500) {
|
|
63
|
+
return { healthy: false, reason: 'bad_status_code' };
|
|
64
|
+
}
|
|
65
|
+
let body;
|
|
66
|
+
if (typeof input.body === 'string') {
|
|
67
|
+
try {
|
|
68
|
+
body = JSON.parse(input.body || '{}');
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return { healthy: false, reason: 'unparseable_body' };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
body = input.body;
|
|
76
|
+
}
|
|
77
|
+
const runtimeInstanceId = String(body['runtime_instance_id'] || body['runtimeInstanceId'] || '');
|
|
78
|
+
if (input.expectedRuntimeInstanceId && runtimeInstanceId !== input.expectedRuntimeInstanceId) {
|
|
79
|
+
return { healthy: false, reason: 'runtime_instance_mismatch' };
|
|
80
|
+
}
|
|
81
|
+
if (input.expectedService && body['service'] && body['service'] !== input.expectedService) {
|
|
82
|
+
return { healthy: false, reason: 'service_mismatch' };
|
|
83
|
+
}
|
|
84
|
+
return { healthy: true, reason: null };
|
|
85
|
+
}
|
|
86
|
+
/** Engine `supervisor.js:70-75`: the default child health policy. */
|
|
87
|
+
export const CHILD_HEALTH_POLICY = {
|
|
88
|
+
graceMs: 8000,
|
|
89
|
+
intervalMs: 10000,
|
|
90
|
+
timeoutMs: 2500,
|
|
91
|
+
maxFailures: 3,
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Engine `supervisor.js:77-80`: chat-server override — model turns hold the
|
|
95
|
+
* event loop longer, so probes get a longer timeout and a bigger budget.
|
|
96
|
+
*/
|
|
97
|
+
export const CHAT_SERVER_HEALTH_POLICY = {
|
|
98
|
+
timeoutMs: 15000,
|
|
99
|
+
maxFailures: 6,
|
|
100
|
+
};
|
|
101
|
+
/** Engine `supervisor.js:304-309`: per-service policy resolution. */
|
|
102
|
+
export function healthPolicyForService(serviceName) {
|
|
103
|
+
return {
|
|
104
|
+
...CHILD_HEALTH_POLICY,
|
|
105
|
+
...(serviceName === 'chat-server' ? CHAT_SERVER_HEALTH_POLICY : {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/** Engine `supervisor.js:62-68`: the child restart budget. */
|
|
109
|
+
export const CHILD_RESTART_POLICY = {
|
|
110
|
+
initialDelayMs: 1000,
|
|
111
|
+
maxDelayMs: 30000,
|
|
112
|
+
stableAfterMs: 30000,
|
|
113
|
+
maxRestarts: 8,
|
|
114
|
+
windowMs: 60000,
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* The ready deadline (engine `supervisor.js:1112-1114`): how long a child
|
|
118
|
+
* gets to become healthy before startup is declared failed —
|
|
119
|
+
* `graceMs + ((intervalMs + timeoutMs) * maxFailures)`.
|
|
120
|
+
* Defaults: 8000 + ((10000 + 2500) * 3) = 45500ms.
|
|
121
|
+
*/
|
|
122
|
+
export function readyDeadlineMs(policy = CHILD_HEALTH_POLICY) {
|
|
123
|
+
return policy.graceMs + ((policy.intervalMs + policy.timeoutMs) * policy.maxFailures);
|
|
124
|
+
}
|
|
125
|
+
const LEGAL = {
|
|
126
|
+
starting: ['starting', 'running', 'restarting', 'degraded'],
|
|
127
|
+
running: ['restarting', 'degraded'],
|
|
128
|
+
restarting: ['starting', 'restarting', 'degraded'],
|
|
129
|
+
degraded: [],
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* The child supervision machine (engine `supervisor.js:1034-1102` and
|
|
133
|
+
* `supervisor.js:1146-1171`), decisions as data. The host owns timers,
|
|
134
|
+
* spawning, and signals; this machine owns the counting:
|
|
135
|
+
*
|
|
136
|
+
* - probe failures within `graceMs` of a launch retry without counting;
|
|
137
|
+
* - the failure log is `health check failed (${n}/${max})`;
|
|
138
|
+
* - at `maxFailures` the decision is restart (`health_check_failed`,
|
|
139
|
+
* SIGKILL escalation after 5000ms);
|
|
140
|
+
* - exits after `stableAfterMs` of runtime reset the backoff and the
|
|
141
|
+
* crash window; earlier exits consume the `maxRestarts`-per-`windowMs`
|
|
142
|
+
* budget with doubling backoff, and exhausting it parks the child
|
|
143
|
+
* `degraded` with `next_retry_at: null`.
|
|
144
|
+
*
|
|
145
|
+
* All timestamps are injected epoch-ms — the machine never reads a clock.
|
|
146
|
+
* An illegal transition throws: it is a programming error in the host, not
|
|
147
|
+
* a process condition.
|
|
148
|
+
*/
|
|
149
|
+
export class ChildSupervisionMachine {
|
|
150
|
+
healthPolicy;
|
|
151
|
+
restartPolicy;
|
|
152
|
+
state = 'starting';
|
|
153
|
+
failures = 0;
|
|
154
|
+
startedAt = 0;
|
|
155
|
+
restartDelayMs;
|
|
156
|
+
restartHistory = [];
|
|
157
|
+
constructor(healthPolicy = CHILD_HEALTH_POLICY, restartPolicy = CHILD_RESTART_POLICY) {
|
|
158
|
+
this.healthPolicy = healthPolicy;
|
|
159
|
+
this.restartPolicy = restartPolicy;
|
|
160
|
+
this.restartDelayMs = restartPolicy.initialDelayMs;
|
|
161
|
+
}
|
|
162
|
+
get status() {
|
|
163
|
+
return this.state;
|
|
164
|
+
}
|
|
165
|
+
get healthFailures() {
|
|
166
|
+
return this.failures;
|
|
167
|
+
}
|
|
168
|
+
setState(next) {
|
|
169
|
+
if (!LEGAL[this.state].includes(next)) {
|
|
170
|
+
throw new Error(`illegal child transition "${this.state}" → "${next}" — ` +
|
|
171
|
+
'the order is starting → running → restarting → starting, with degraded terminal');
|
|
172
|
+
}
|
|
173
|
+
this.state = next;
|
|
174
|
+
}
|
|
175
|
+
/** The host spawned (or respawned) the process at `now`. */
|
|
176
|
+
launched(now) {
|
|
177
|
+
this.setState('starting');
|
|
178
|
+
this.failures = 0;
|
|
179
|
+
this.startedAt = now;
|
|
180
|
+
}
|
|
181
|
+
/** The host completed a health probe at `now` with result `ok`. */
|
|
182
|
+
probe(ok, now) {
|
|
183
|
+
if (ok) {
|
|
184
|
+
this.failures = 0;
|
|
185
|
+
if (this.state !== 'running') {
|
|
186
|
+
this.setState('running');
|
|
187
|
+
return { action: 'mark-running' };
|
|
188
|
+
}
|
|
189
|
+
return { action: 'none' };
|
|
190
|
+
}
|
|
191
|
+
if (now - this.startedAt < this.healthPolicy.graceMs) {
|
|
192
|
+
return { action: 'retry-within-grace' };
|
|
193
|
+
}
|
|
194
|
+
this.failures += 1;
|
|
195
|
+
const log = `health check failed (${this.failures}/${this.healthPolicy.maxFailures})`;
|
|
196
|
+
if (this.failures >= this.healthPolicy.maxFailures) {
|
|
197
|
+
this.setState('restarting');
|
|
198
|
+
return { action: 'restart', reason: 'health_check_failed', sigkillAfterMs: 5000, log };
|
|
199
|
+
}
|
|
200
|
+
return { action: 'count-failure', failures: this.failures, log };
|
|
201
|
+
}
|
|
202
|
+
/** The child process exited at `now` (and the host wants it kept alive). */
|
|
203
|
+
exited(now) {
|
|
204
|
+
const runtimeMs = now - this.startedAt;
|
|
205
|
+
if (runtimeMs >= this.restartPolicy.stableAfterMs) {
|
|
206
|
+
this.restartDelayMs = this.restartPolicy.initialDelayMs;
|
|
207
|
+
this.restartHistory = [];
|
|
208
|
+
}
|
|
209
|
+
this.restartHistory = this.restartHistory.filter((time) => now - time <= this.restartPolicy.windowMs);
|
|
210
|
+
if (this.restartHistory.length >= this.restartPolicy.maxRestarts) {
|
|
211
|
+
this.setState('degraded');
|
|
212
|
+
return {
|
|
213
|
+
action: 'degrade',
|
|
214
|
+
state: 'degraded',
|
|
215
|
+
reason: 'restart_limit_exceeded',
|
|
216
|
+
next_retry_at: null,
|
|
217
|
+
log: `entered degraded state after ${this.restartHistory.length} restarts in ${this.restartPolicy.windowMs}ms`,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
this.restartHistory.push(now);
|
|
221
|
+
const delayMs = this.restartDelayMs;
|
|
222
|
+
this.restartDelayMs = Math.min(this.restartDelayMs * 2, this.restartPolicy.maxDelayMs);
|
|
223
|
+
this.setState('restarting');
|
|
224
|
+
return { action: 'restart-after', delayMs, log: `restart scheduled in ${delayMs}ms` };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/supervision/health.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @amalgm/core — supervision.
|
|
3
|
+
*
|
|
4
|
+
* The cascade that keeps everything running (axiom 5, one way only):
|
|
5
|
+
* launchd → CLI parent → runtime → app supervisor. This module carries the
|
|
6
|
+
* kernel's supervision contracts as pure decision logic — health contracts
|
|
7
|
+
* (probe side and push side), restart/degrade policy, updater laws, host
|
|
8
|
+
* launcher registration, and process identification. Hosts supply every
|
|
9
|
+
* effect (axiom 6); every threshold, vocabulary, and error string is
|
|
10
|
+
* byte-exact with the shipped engine (axiom 8).
|
|
11
|
+
*/
|
|
12
|
+
export { HEALTHZ_STATUS_CODE, CHILD_HEALTH_POLICY, CHAT_SERVER_HEALTH_POLICY, CHILD_RESTART_POLICY, ChildSupervisionMachine, buildRuntimeHealthzBody, healthPolicyForService, readyDeadlineMs, validateHealthBody, type ChildExitDecision, type ChildHealthPolicy, type ChildRestartPolicy, type ChildStatus, type HealthBodyVerdict, type HealthProbeDecision, type RuntimeHealthzBody, } from './health.js';
|
|
13
|
+
export { APP_HEALTH_POLICY, APP_ID_BODY_KEYS, APP_ID_REQUIRED_ERROR, APP_ID_REQUIRED_STATUS, APP_NOT_FOUND_ERROR, APP_NOT_FOUND_STATUS, HEARTBEAT_INTERVAL_BODY_KEYS, acceptsHealthSignals, appIdFromBody, clampIntervalMs, healthSignalRejection, heartbeatIntervalFromBody, heartbeatRecovery, snapshotEntry, sweepAppHealth, unresponsiveAfterMs, type AppHealthEntry, type AppHealthRecord, type AppHealthSnapshot, type AppHealthStatus, type AppRecoveryDecision, type AppSweepTransition, } from './app-health.js';
|
|
14
|
+
export { APP_RESTART_POLICY, appExitDecision, explicitStartReset, recentCrashes, restartDelayMs, type AppDesiredState, type AppExitContext, type AppExitDecision, type AppStatus, } from './app-restart.js';
|
|
15
|
+
export { AUTO_UPDATE_ENV_OVERRIDES, AUTO_UPDATE_POLICY, AUTO_UPDATE_STATUSES, NOT_SERVICE_MANAGED_REASON, NPM_UPDATE_CACHE_DIRNAME, UPDATE_TARGET_MISMATCH, autoUpdateIdleBlockedReason, autoUpdateSupported, comparePrerelease, compareVersions, distTagCheckFailedMessage, envDisablesAutoUpdate, envFlag, globalPrefixForPackageRoot, installFailedMessage, noVersionMessage, npmEnv, npmFailureDetail, npmInstallArgs, npmInstallTag, numberFromEnvValue, parseSemver, resolveAutoUpdateTimings, restartSuppressedDetail, shouldAutoUpdate, updateTargetMismatchError, type AutoUpdateStatus, type RuntimeIdleStatus, type Semver, type UpdateTargetMismatchError, } from './update.js';
|
|
16
|
+
export { PS_LINE_PATTERN, RUNTIME_HEALTH_PATH, RUNTIME_INSTANCE_ARG_PATTERN, SUPERVISOR_COMMAND_SUFFIX, buildLaunchdPlist, buildSystemdUnit, buildWindowsStartupScript, commandLooksLikeAnySupervisor, commandLooksLikeRuntimeService, commandLooksLikeSupervisor, commandRuntimeInstanceId, decideOwnership, deferToExistingInstall, envMatchesAmalgmDir, launchdPlistPath, lockOwnedByAnother, normalizeMode, parsePort, parsePsLine, pathLooksLikeDesktopBundle, plistEscape, releaseAllowed, runtimeInstanceArg, runtimeLaunchServices, runtimePortsFromState, runtimePortsState, runtimeServiceMarkers, runtimeServiceSuffixes, serviceLabel, serviceLabelScope, serviceStateCanOwnRuntime, shellQuote, shippedRuntimeServices, stateMatchesRequest, systemdQuote, systemdUnavailableOutput, systemdUnitPath, vbsString, windowsStartupScriptPath, type OwnershipDecision, type ProcessIdentity, type RuntimeOwnerRecord, type RuntimeStatePorts, type ServiceDeclaration, type ServiceMode, type ServiceState, } from './service-registration.js';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/supervision/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,EAClB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,qBAAqB,EACrB,OAAO,EACP,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,MAAM,EACX,KAAK,yBAAyB,GAC/B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,WAAW,EACX,0BAA0B,EAC1B,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EACjB,yBAAyB,EACzB,UAAU,EACV,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,SAAS,EACT,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @amalgm/core — supervision.
|
|
3
|
+
*
|
|
4
|
+
* The cascade that keeps everything running (axiom 5, one way only):
|
|
5
|
+
* launchd → CLI parent → runtime → app supervisor. This module carries the
|
|
6
|
+
* kernel's supervision contracts as pure decision logic — health contracts
|
|
7
|
+
* (probe side and push side), restart/degrade policy, updater laws, host
|
|
8
|
+
* launcher registration, and process identification. Hosts supply every
|
|
9
|
+
* effect (axiom 6); every threshold, vocabulary, and error string is
|
|
10
|
+
* byte-exact with the shipped engine (axiom 8).
|
|
11
|
+
*/
|
|
12
|
+
export { HEALTHZ_STATUS_CODE, CHILD_HEALTH_POLICY, CHAT_SERVER_HEALTH_POLICY, CHILD_RESTART_POLICY, ChildSupervisionMachine, buildRuntimeHealthzBody, healthPolicyForService, readyDeadlineMs, validateHealthBody, } from './health.js';
|
|
13
|
+
export { APP_HEALTH_POLICY, APP_ID_BODY_KEYS, APP_ID_REQUIRED_ERROR, APP_ID_REQUIRED_STATUS, APP_NOT_FOUND_ERROR, APP_NOT_FOUND_STATUS, HEARTBEAT_INTERVAL_BODY_KEYS, acceptsHealthSignals, appIdFromBody, clampIntervalMs, healthSignalRejection, heartbeatIntervalFromBody, heartbeatRecovery, snapshotEntry, sweepAppHealth, unresponsiveAfterMs, } from './app-health.js';
|
|
14
|
+
export { APP_RESTART_POLICY, appExitDecision, explicitStartReset, recentCrashes, restartDelayMs, } from './app-restart.js';
|
|
15
|
+
export { AUTO_UPDATE_ENV_OVERRIDES, AUTO_UPDATE_POLICY, AUTO_UPDATE_STATUSES, NOT_SERVICE_MANAGED_REASON, NPM_UPDATE_CACHE_DIRNAME, UPDATE_TARGET_MISMATCH, autoUpdateIdleBlockedReason, autoUpdateSupported, comparePrerelease, compareVersions, distTagCheckFailedMessage, envDisablesAutoUpdate, envFlag, globalPrefixForPackageRoot, installFailedMessage, noVersionMessage, npmEnv, npmFailureDetail, npmInstallArgs, npmInstallTag, numberFromEnvValue, parseSemver, resolveAutoUpdateTimings, restartSuppressedDetail, shouldAutoUpdate, updateTargetMismatchError, } from './update.js';
|
|
16
|
+
export { PS_LINE_PATTERN, RUNTIME_HEALTH_PATH, RUNTIME_INSTANCE_ARG_PATTERN, SUPERVISOR_COMMAND_SUFFIX, buildLaunchdPlist, buildSystemdUnit, buildWindowsStartupScript, commandLooksLikeAnySupervisor, commandLooksLikeRuntimeService, commandLooksLikeSupervisor, commandRuntimeInstanceId, decideOwnership, deferToExistingInstall, envMatchesAmalgmDir, launchdPlistPath, lockOwnedByAnother, normalizeMode, parsePort, parsePsLine, pathLooksLikeDesktopBundle, plistEscape, releaseAllowed, runtimeInstanceArg, runtimeLaunchServices, runtimePortsFromState, runtimePortsState, runtimeServiceMarkers, runtimeServiceSuffixes, serviceLabel, serviceLabelScope, serviceStateCanOwnRuntime, shellQuote, shippedRuntimeServices, stateMatchesRequest, systemdQuote, systemdUnavailableOutput, systemdUnitPath, vbsString, windowsStartupScriptPath, } from './service-registration.js';
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/supervision/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,eAAe,EACf,kBAAkB,GAQnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,4BAA4B,EAC5B,oBAAoB,EACpB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,yBAAyB,EACzB,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,mBAAmB,GAOpB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,cAAc,GAKf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,EACtB,2BAA2B,EAC3B,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,qBAAqB,EACrB,OAAO,EACP,0BAA0B,EAC1B,oBAAoB,EACpB,gBAAgB,EAChB,MAAM,EACN,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,wBAAwB,EACxB,uBAAuB,EACvB,gBAAgB,EAChB,yBAAyB,GAK1B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,6BAA6B,EAC7B,8BAA8B,EAC9B,0BAA0B,EAC1B,wBAAwB,EACxB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,aAAa,EACb,SAAS,EACT,WAAW,EACX,0BAA0B,EAC1B,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,YAAY,EACZ,iBAAiB,EACjB,yBAAyB,EACzB,UAAU,EACV,sBAAsB,EACtB,mBAAmB,EACnB,YAAY,EACZ,wBAAwB,EACxB,eAAe,EACf,SAAS,EACT,wBAAwB,GAQzB,MAAM,2BAA2B,CAAC"}
|