@helmetfire-labs/cartridge-common 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +206 -0
  2. package/dist/action-schema.d.ts +71 -0
  3. package/dist/action-schema.js +94 -0
  4. package/dist/action-schema.js.map +1 -0
  5. package/dist/actions.d.ts +4 -0
  6. package/dist/actions.js +5 -0
  7. package/dist/actions.js.map +1 -1
  8. package/dist/container-reducer.d.ts +104 -0
  9. package/dist/container-reducer.js +178 -0
  10. package/dist/container-reducer.js.map +1 -0
  11. package/dist/durable-dispatcher.d.ts +90 -0
  12. package/dist/durable-dispatcher.js +198 -0
  13. package/dist/durable-dispatcher.js.map +1 -0
  14. package/dist/durable-reducer.d.ts +108 -0
  15. package/dist/durable-reducer.js +40 -0
  16. package/dist/durable-reducer.js.map +1 -0
  17. package/dist/index.d.ts +25 -2
  18. package/dist/index.js +21 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/logger.d.ts +10 -3
  21. package/dist/logger.js +24 -1
  22. package/dist/logger.js.map +1 -1
  23. package/dist/namespace.d.ts +99 -0
  24. package/dist/namespace.js +161 -0
  25. package/dist/namespace.js.map +1 -0
  26. package/dist/policy.d.ts +118 -0
  27. package/dist/policy.js +204 -0
  28. package/dist/policy.js.map +1 -0
  29. package/dist/tags.d.ts +3 -0
  30. package/dist/tags.js +3 -0
  31. package/dist/tags.js.map +1 -1
  32. package/dist/trace.d.ts +57 -0
  33. package/dist/trace.js +57 -0
  34. package/dist/trace.js.map +1 -1
  35. package/dist/trust-score.d.ts +132 -0
  36. package/dist/trust-score.js +233 -0
  37. package/dist/trust-score.js.map +1 -0
  38. package/dist/trust-tiers.d.ts +68 -0
  39. package/dist/trust-tiers.js +264 -0
  40. package/dist/trust-tiers.js.map +1 -0
  41. package/dist/verify.d.ts +36 -0
  42. package/dist/verify.js +110 -0
  43. package/dist/verify.js.map +1 -0
  44. package/package.json +10 -6
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # @helmetfire-labs/cartridge-common
2
+
3
+ Shared logging, error boundaries, trace helpers, durable reducer runtime, and trust infrastructure for AgentRuntime cartridges.
4
+
5
+ This is a **library**, not a service. It provides the building blocks that all cartridges use for structured logging, error handling, multi-agent state isolation, and auditable state management.
6
+
7
+ ## Philosophy
8
+
9
+ Every cartridge is a process with a behavioral contract. It declares what it does (action schema), what it's allowed to do (process policy), and how its state changes over time (reducer). All three are cryptographically bound — the action log is hash-chained, the policy is signed at write time, and the verifier can replay any cartridge's history to prove correctness.
10
+
11
+ Infrastructure cartridges never expose admin APIs. The operator reads logs and edits config — the Conversational Control Plane. Trust is earned through observable behavior: verified action logs, policy compliance, and operator attestation feed a scoring engine that automates tier promotion from T0 (untrusted) through T5 (community-verified).
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ npm install @helmetfire-labs/cartridge-common
17
+ ```
18
+
19
+ ## Exports
20
+
21
+ ### Logging & Observability
22
+
23
+ | Export | Module | Description |
24
+ |--------|--------|-------------|
25
+ | `logEvent`, `LogEventOpts` | `logger` | Structured log event emitter |
26
+ | `TAGS`, `isValidTag`, `TagKey`, `TagValue` | `tags` | Standard tag constants and validation |
27
+ | `ACTIONS`, `ActionKey`, `ActionValue` | `actions` | Standard action verb constants |
28
+ | `generateTraceId`, `extractTraceId`, `traceMetadata`, `extractHop`, `NO_TRACE` | `trace` | Trace ID generation and propagation |
29
+ | `extractShape` | `shape` | Error shape extraction |
30
+ | `withErrorBoundary`, `classifyError`, `ERROR_SHAPES`, `ErrorShapeKey` | `errors` | Error boundary wrapper and classification |
31
+
32
+ ### Namespace Scope (Multi-Agent State Isolation)
33
+
34
+ | Export | Module | Description |
35
+ |--------|--------|-------------|
36
+ | `extractNamespace`, `ScopedStateManager` | `namespace` | Multi-agent namespace isolation |
37
+ | `ScopeMode`, `CrossNamespacePolicy`, `NamespaceScopeConfig`, `NamespaceInfo` | `namespace` | Namespace type definitions |
38
+
39
+ ### Durable Reducer Runtime
40
+
41
+ | Export | Module | Description |
42
+ |--------|--------|-------------|
43
+ | `sha256`, `hashState`, `hashLine` | `durable-reducer` | Cryptographic hashing for state and action logs |
44
+ | `DurableReducer`, `DurableActionLogEntry`, `VerifyResult`, `VerifyFailure` | `durable-reducer` | Reducer types and verification result types |
45
+ | `DurableDispatcher`, `DispatcherConfig` | `durable-dispatcher` | Persistent dispatcher with hash-chained action logging |
46
+ | `verify` | `verify` | Replay-based action log verification |
47
+ | `containerReducer`, `containerActionSchema`, `ContainerStatus`, `ContainerState`, `ContainerAction` | `container-reducer` | Built-in reducer for container lifecycle |
48
+
49
+ ### Action Schemas
50
+
51
+ | Export | Module | Description |
52
+ |--------|--------|-------------|
53
+ | `defineActionSchema`, `action`, `writeActionSchema`, `getSchemaHash`, `validateAction` | `action-schema` | Schema definition, validation, and persistence |
54
+ | `ActionSchema`, `ActionVariant`, `FieldType` | `action-schema` | Schema type definitions |
55
+
56
+ ### Process Policy
57
+
58
+ | Export | Module | Description |
59
+ |--------|--------|-------------|
60
+ | `hashPolicy`, `writePolicy`, `readPolicy`, `verifyPolicy` | `policy` | Cryptographically-verified process policy lifecycle |
61
+ | `isNetworkAllowed`, `isFilesystemAllowed`, `isSpawnAllowed` | `policy` | Runtime permission checks |
62
+ | `DEFAULT_POLICY`, `INSTALL_POLICY` | `policy` | Standard policy presets |
63
+ | `CartridgePolicy`, `FilesystemPolicy`, `NetworkPolicy`, `NetworkEndpoint`, `ProcessPolicy`, `PolicyVerifyResult` | `policy` | Policy type definitions |
64
+
65
+ ### Trust Tiers & Scoring
66
+
67
+ | Export | Module | Description |
68
+ |--------|--------|-------------|
69
+ | `evaluateTrust`, `checkT3`, `checkT4` | `trust-tiers` | Automated trust tier evaluation (T0–T5) |
70
+ | `TrustTier`, `TierCheck`, `TrustAssessment` | `trust-tiers` | Trust tier type definitions |
71
+ | `computeTrustDelta`, `applyDecay`, `updateTrustScore`, `computeTrustBadge`, `badgeLabel` | `trust-score` | T5 consensus trust scoring engine |
72
+ | `countAnchorConsistency`, `recencyWeight`, `getOperatorWeight`, `initialTrustScoreState` | `trust-score` | Scoring utilities and initial state |
73
+ | `OperatorTier`, `TrustBadge`, `TrustSignal`, `TrustScoreState`, `AnchorConsistencyInput` | `trust-score` | Scoring type definitions |
74
+
75
+ ## Durable Reducer Runtime
76
+
77
+ The reducer runtime gives every cartridge an auditable, replay-verifiable state machine.
78
+
79
+ ```typescript
80
+ import {
81
+ DurableDispatcher,
82
+ containerReducer,
83
+ type ContainerState,
84
+ type ContainerAction,
85
+ } from "@helmetfire-labs/cartridge-common";
86
+
87
+ // Create a dispatcher — persists hash-chained action.log
88
+ const dispatcher = new DurableDispatcher<ContainerState, ContainerAction>({
89
+ reducer: containerReducer,
90
+ configDir: "./config",
91
+ skipProjection: true, // don't write clear.json (incremental integration)
92
+ });
93
+
94
+ // Dispatch typed actions — each entry gets a stateHash binding
95
+ dispatcher.dispatch({ type: "start", name: "registry", pid: 1234, timestamp: Date.now() });
96
+
97
+ // Verify the log — replays all actions and checks hash chain integrity
98
+ import { verify } from "@helmetfire-labs/cartridge-common";
99
+ const result = await verify(containerReducer, "./config/action.log");
100
+ // result.ok === true if the log is tamper-free
101
+ ```
102
+
103
+ ### Action Schemas
104
+
105
+ Define typed, validated action schemas for your reducer:
106
+
107
+ ```typescript
108
+ import { defineActionSchema, action } from "@helmetfire-labs/cartridge-common";
109
+
110
+ const schema = defineActionSchema("my-cartridge", [
111
+ action("init", { name: "string" }),
112
+ action("update", { value: "number", reason: "string?" }), // ? = optional
113
+ action("reset"),
114
+ ]);
115
+ ```
116
+
117
+ ## Process Policy
118
+
119
+ Self-declared, cryptographically-verified permissions for cartridge sandboxing:
120
+
121
+ ```typescript
122
+ import { writePolicy, verifyPolicy, isNetworkAllowed } from "@helmetfire-labs/cartridge-common";
123
+
124
+ // Write a signed policy to config/
125
+ await writePolicy("./config", {
126
+ filesystem: { read: ["./data/**"], write: ["./state/**"], deny: ["/etc/**"] },
127
+ network: { allow: [{ host: "api.example.com", port: 443 }], denyAll: false },
128
+ process: { allowSpawn: false, allowedCommands: [] },
129
+ });
130
+
131
+ // Verify policy hasn't been tampered with
132
+ const result = await verifyPolicy("./config");
133
+ // result.ok === true
134
+
135
+ // Runtime permission checks
136
+ isNetworkAllowed(policy, "api.example.com", 443); // true
137
+ ```
138
+
139
+ ## Namespace Scope (Multi-Agent State Isolation)
140
+
141
+ When multiple agents connect to the same SSE MCP tool server, each agent needs its own isolated state. The supervisor assigns each agent a namespace via `?ns=<name>` on the SSE URL. Agents never control their own namespace — the supervisor asserts the identity.
142
+
143
+ ```typescript
144
+ import { extractNamespace, ScopedStateManager } from "@helmetfire-labs/cartridge-common";
145
+
146
+ const state = new ScopedStateManager({
147
+ mode: "isolated", // "isolated" | "shared" | "hybrid"
148
+ crossNamespace: "allow" // "allow" | "log" | "deny"
149
+ }, "brw");
150
+
151
+ const ns = extractNamespace(req.url); // e.g. "claude" from ?ns=claude
152
+ state.registerSession(transport.sessionId, ns);
153
+ const store = state.getStore(transport.sessionId, "view_page");
154
+ ```
155
+
156
+ ### Scope Modes
157
+
158
+ | Mode | Behavior |
159
+ |------|----------|
160
+ | `isolated` | Each agent gets its own state partition |
161
+ | `shared` | All agents share one state pool, `ns` tracks attribution |
162
+ | `hybrid` | Some tools isolated, some shared (configured via `sharedTools`) |
163
+
164
+ ### Cross-Namespace Policy
165
+
166
+ | Policy | Behavior |
167
+ |--------|----------|
168
+ | `allow` | No enforcement (default, for development) |
169
+ | `log` | Access permitted but logged with attribution |
170
+ | `deny` | Access rejected, escalation requires attributed override |
171
+
172
+ ## Standard Tags
173
+
174
+ | Key | Tag | Cartridge |
175
+ |-----|-----|-----------|
176
+ | `mutex` | `mtx` | mcp-mutex |
177
+ | `semaphore` | `sem` | mcp-semaphore |
178
+ | `readonly` | `rdo` | mcp-readonly |
179
+ | `retry` | `rty` | mcp-retry |
180
+ | `timeout` | `tmo` | mcp-timeout |
181
+ | `circuitBreaker` | `brk` | mcp-circuit-breaker |
182
+ | `router` | `rtr` | mcp-router |
183
+ | `cache` | `cch` | mcp-cache |
184
+ | `auth` | `aut` | mcp-auth |
185
+ | `transform` | `tfm` | mcp-transform |
186
+ | `sanitize` | `san` | mcp-sanitize |
187
+ | `webhook` | `whk` | mcp-webhook |
188
+ | `cron` | `crn` | mcp-cron |
189
+ | `audit` | `aud` | mcp-audit |
190
+ | `relay` | `rly` | mcp-relay |
191
+ | `mock` | `mck` | mcp-mock |
192
+ | `shadow` | `shd` | mcp-shadow |
193
+ | `bridge` | `brg` | mcp-bridge |
194
+ | `tee` | `tee` | mcp-tee |
195
+ | `approval` | `apv` | mcp-approval |
196
+ | `verify` | `vfy` | mcp-verify |
197
+ | `browser` | `brw` | tools-browser |
198
+ | `namespace` | `nsp` | namespace scope |
199
+
200
+ ## Build
201
+
202
+ ```bash
203
+ npm run build # compile TypeScript
204
+ npm run typecheck # type-check only
205
+ npm test # run tests (239 tests)
206
+ ```
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Action schema — runtime-inspectable declaration of a cartridge's action types.
3
+ *
4
+ * TypeScript types are erased at runtime. The action schema bridges this gap:
5
+ * cartridge authors declare their action variants as data (not just types),
6
+ * and the schema generator outputs action-schema.json for the marketplace.
7
+ *
8
+ * The schema serves three purposes:
9
+ * 1. Marketplace declaration — "here are the actions this cartridge can take"
10
+ * 2. Verification input — auditors know what action types to expect
11
+ * 3. Population consensus — the registry compares action distributions
12
+ *
13
+ * Usage:
14
+ * const schema = defineActionSchema("container", [
15
+ * action("start", { ts: "number" }),
16
+ * action("ready", { pid: "number", port: "number?", ts: "number" }),
17
+ * action("stop", { reason: "string", ts: "number" }),
18
+ * // ...
19
+ * ]);
20
+ *
21
+ * writeActionSchema(configDir, schema);
22
+ * // → config/action-schema.json
23
+ *
24
+ * Patent M: Reducer-Based Auditable Cartridge Runtime
25
+ */
26
+ export type FieldType = "string" | "number" | "boolean" | "string?" | "number?" | "boolean?" | "unknown";
27
+ export interface ActionVariant {
28
+ /** The discriminant value (e.g. "start", "stop", "crash") */
29
+ type: string;
30
+ /** Field name → type. Every variant implicitly has `type: string`. */
31
+ fields: Record<string, FieldType>;
32
+ /** Human-readable description of what this action represents */
33
+ description?: string;
34
+ }
35
+ export interface ActionSchema {
36
+ /** Schema format version */
37
+ version: 1;
38
+ /** Cartridge/reducer name */
39
+ name: string;
40
+ /** All declared action variants */
41
+ actions: ActionVariant[];
42
+ /** SHA-256 of the canonical JSON representation (for identity binding) */
43
+ hash: string;
44
+ /** When this schema was generated */
45
+ generatedAt: number;
46
+ }
47
+ /**
48
+ * Declare a single action variant.
49
+ */
50
+ export declare function action(type: string, fields: Record<string, FieldType>, description?: string): ActionVariant;
51
+ /**
52
+ * Build a complete action schema from declared variants.
53
+ * Computes the hash over the canonical representation (sorted, no whitespace).
54
+ */
55
+ export declare function defineActionSchema(name: string, actions: ActionVariant[]): ActionSchema;
56
+ /**
57
+ * Write action-schema.json to the cartridge's config/ directory.
58
+ */
59
+ export declare function writeActionSchema(configDir: string, schema: ActionSchema): void;
60
+ /**
61
+ * Get just the hash of a schema (for embedding in static.json).
62
+ */
63
+ export declare function getSchemaHash(schema: ActionSchema): string;
64
+ /**
65
+ * Validate that an action payload conforms to a declared schema.
66
+ * Returns null if valid, or an error string if not.
67
+ */
68
+ export declare function validateAction(actionPayload: {
69
+ type: string;
70
+ [key: string]: unknown;
71
+ }, schema: ActionSchema): string | null;
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Action schema — runtime-inspectable declaration of a cartridge's action types.
3
+ *
4
+ * TypeScript types are erased at runtime. The action schema bridges this gap:
5
+ * cartridge authors declare their action variants as data (not just types),
6
+ * and the schema generator outputs action-schema.json for the marketplace.
7
+ *
8
+ * The schema serves three purposes:
9
+ * 1. Marketplace declaration — "here are the actions this cartridge can take"
10
+ * 2. Verification input — auditors know what action types to expect
11
+ * 3. Population consensus — the registry compares action distributions
12
+ *
13
+ * Usage:
14
+ * const schema = defineActionSchema("container", [
15
+ * action("start", { ts: "number" }),
16
+ * action("ready", { pid: "number", port: "number?", ts: "number" }),
17
+ * action("stop", { reason: "string", ts: "number" }),
18
+ * // ...
19
+ * ]);
20
+ *
21
+ * writeActionSchema(configDir, schema);
22
+ * // → config/action-schema.json
23
+ *
24
+ * Patent M: Reducer-Based Auditable Cartridge Runtime
25
+ */
26
+ import { writeFileSync } from "node:fs";
27
+ import { resolve } from "node:path";
28
+ import { sha256 } from "./durable-reducer.js";
29
+ // ── Builder ─────────────────────────────────────────────────────────────────
30
+ /**
31
+ * Declare a single action variant.
32
+ */
33
+ export function action(type, fields, description) {
34
+ return { type, fields, description };
35
+ }
36
+ /**
37
+ * Build a complete action schema from declared variants.
38
+ * Computes the hash over the canonical representation (sorted, no whitespace).
39
+ */
40
+ export function defineActionSchema(name, actions) {
41
+ // Sort actions by type for canonical ordering
42
+ const sorted = [...actions].sort((a, b) => a.type.localeCompare(b.type));
43
+ // Canonical representation for hashing (no whitespace, sorted keys)
44
+ const canonical = JSON.stringify({ name, actions: sorted });
45
+ const hash = sha256(canonical);
46
+ return {
47
+ version: 1,
48
+ name,
49
+ actions: sorted,
50
+ hash,
51
+ generatedAt: Date.now(),
52
+ };
53
+ }
54
+ // ── Persistence ─────────────────────────────────────────────────────────────
55
+ /**
56
+ * Write action-schema.json to the cartridge's config/ directory.
57
+ */
58
+ export function writeActionSchema(configDir, schema) {
59
+ const filePath = resolve(configDir, "action-schema.json");
60
+ writeFileSync(filePath, JSON.stringify(schema, null, 2), "utf-8");
61
+ }
62
+ /**
63
+ * Get just the hash of a schema (for embedding in static.json).
64
+ */
65
+ export function getSchemaHash(schema) {
66
+ return schema.hash;
67
+ }
68
+ // ── Validation ──────────────────────────────────────────────────────────────
69
+ /**
70
+ * Validate that an action payload conforms to a declared schema.
71
+ * Returns null if valid, or an error string if not.
72
+ */
73
+ export function validateAction(actionPayload, schema) {
74
+ const variant = schema.actions.find(a => a.type === actionPayload.type);
75
+ if (!variant) {
76
+ return `unknown action type: "${actionPayload.type}" (declared: ${schema.actions.map(a => a.type).join(", ")})`;
77
+ }
78
+ for (const [field, fieldType] of Object.entries(variant.fields)) {
79
+ const value = actionPayload[field];
80
+ const isOptional = fieldType.endsWith("?");
81
+ const baseType = fieldType.replace("?", "");
82
+ if (value === undefined || value === null) {
83
+ if (!isOptional) {
84
+ return `missing required field "${field}" on action "${actionPayload.type}"`;
85
+ }
86
+ continue;
87
+ }
88
+ if (baseType !== "unknown" && typeof value !== baseType) {
89
+ return `field "${field}" on action "${actionPayload.type}": expected ${baseType}, got ${typeof value}`;
90
+ }
91
+ }
92
+ return null;
93
+ }
94
+ //# sourceMappingURL=action-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-schema.js","sourceRoot":"","sources":["../src/action-schema.ts"],"names":[],"mappings":"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"}
package/dist/actions.d.ts CHANGED
@@ -30,6 +30,10 @@ export declare const ACTIONS: {
30
30
  readonly pending: "pending";
31
31
  readonly approved: "approved";
32
32
  readonly rejected: "rejected";
33
+ readonly verify: "verify";
34
+ readonly mismatch: "mismatch";
35
+ readonly signed: "signed";
36
+ readonly anchored: "anchored";
33
37
  };
34
38
  export type ActionKey = keyof typeof ACTIONS;
35
39
  export type ActionValue = (typeof ACTIONS)[ActionKey];
package/dist/actions.js CHANGED
@@ -39,5 +39,10 @@ export const ACTIONS = {
39
39
  pending: 'pending',
40
40
  approved: 'approved',
41
41
  rejected: 'rejected',
42
+ // Verification
43
+ verify: 'verify',
44
+ mismatch: 'mismatch',
45
+ signed: 'signed',
46
+ anchored: 'anchored',
42
47
  };
43
48
  //# sourceMappingURL=actions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,YAAY;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IAExB,UAAU;IACV,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAElB,QAAQ;IACR,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IAEd,kBAAkB;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IAEtB,QAAQ;IACR,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IAEtB,OAAO;IACP,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAElB,YAAY;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,YAAY;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,UAAU,EAAE,YAAY;IAExB,UAAU;IACV,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAElB,QAAQ;IACR,GAAG,EAAE,KAAK;IACV,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IAEd,kBAAkB;IAClB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;IAEtB,QAAQ;IACR,KAAK,EAAE,OAAO;IACd,SAAS,EAAE,WAAW;IAEtB,OAAO;IACP,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAElB,YAAY;IACZ,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAEhB,WAAW;IACX,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IAEpB,eAAe;IACf,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,QAAQ,EAAE,UAAU;CACZ,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Container lifecycle reducer — the first DurableReducer adopter.
3
+ *
4
+ * Extracts the container state machine (previously implicit in Container.ts
5
+ * and ContainerManager.ts) into a pure, testable function. Every legal
6
+ * container lifecycle transition is one case in the switch. Illegal
7
+ * transitions return the input state unchanged.
8
+ *
9
+ * State machine:
10
+ *
11
+ * start
12
+ * ┌──────────┐ ────────────────── ▶ ┌──────────┐
13
+ * │ stopped │ │ starting │
14
+ * └──────────┘ └──────────┘
15
+ * ▲ │ │
16
+ * │ ready │ err │
17
+ * │ ▼ ▼
18
+ * │ ┌─────────┐ ┌─────────┐
19
+ * │ │ running │ │ crashed │
20
+ * │ ◀──── stop/kill ───────────│ │◀─┘ │
21
+ * │ └─────────┘ │
22
+ * │ │ │ ▲ │
23
+ * │ freeze │ │ └──────────────┘
24
+ * │ ▼ │ thaw
25
+ * │ ┌─────────┐
26
+ * │ ◀──── stop/kill ───────────│ frozen │
27
+ * │ └─────────┘
28
+ * │
29
+ * │ health_fail ┌────────────┐
30
+ * │ ◀──── stop/kill ───────────│health-fail │
31
+ * │ └────────────┘
32
+ * │ ▲
33
+ * │ │ health_fail (consecutive)
34
+ * │ │
35
+ * └──────────────────────────── running
36
+ * │
37
+ * │ throttle
38
+ * ▼
39
+ * ┌───────────┐
40
+ * │ throttled │
41
+ * └───────────┘
42
+ *
43
+ * Patent M: Reducer-Based Auditable Cartridge Runtime
44
+ */
45
+ import type { DurableReducer } from "./durable-reducer.js";
46
+ import { type ActionSchema } from "./action-schema.js";
47
+ export type ContainerStatus = "stopped" | "starting" | "running" | "crashed" | "frozen" | "throttled" | "health-failing";
48
+ export interface ContainerState {
49
+ status: ContainerStatus;
50
+ pid: number | null;
51
+ port: number | null;
52
+ muted: boolean;
53
+ startedAt: number | null;
54
+ updatedAt: number;
55
+ }
56
+ export type ContainerAction = {
57
+ type: "start";
58
+ ts: number;
59
+ } | {
60
+ type: "ready";
61
+ pid: number;
62
+ port?: number;
63
+ ts: number;
64
+ } | {
65
+ type: "stop";
66
+ reason: string;
67
+ ts: number;
68
+ } | {
69
+ type: "crash";
70
+ exitCode: number;
71
+ signal?: string;
72
+ ts: number;
73
+ } | {
74
+ type: "freeze";
75
+ ts: number;
76
+ } | {
77
+ type: "thaw";
78
+ ts: number;
79
+ } | {
80
+ type: "kill";
81
+ reason: string;
82
+ ts: number;
83
+ } | {
84
+ type: "health_fail";
85
+ consecutive: number;
86
+ ts: number;
87
+ } | {
88
+ type: "health_recover";
89
+ ts: number;
90
+ } | {
91
+ type: "mute";
92
+ ts: number;
93
+ } | {
94
+ type: "unmute";
95
+ ts: number;
96
+ } | {
97
+ type: "throttle";
98
+ ts: number;
99
+ } | {
100
+ type: "unthrottle";
101
+ ts: number;
102
+ };
103
+ export declare const containerReducer: DurableReducer<ContainerState, ContainerAction>;
104
+ export declare const containerActionSchema: ActionSchema;