@tomflow/proflow-execution-runtime 0.1.5 → 0.1.7

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/DOCS.md ADDED
@@ -0,0 +1,27 @@
1
+ # @tomflow/proflow-execution-runtime — Module Docs
2
+
3
+ Module ref: `execution-runtime`
4
+ Domain: `execution`
5
+ Kind: `service`
6
+
7
+ Durable, policy-controlled Execution Core orchestration over SQLite and controlled executor ports.
8
+
9
+ ## Standard management surface
10
+
11
+ `install / uninstall / status / setup / docs / start / stop`
12
+
13
+ ## Provides
14
+
15
+ - `execution` `1.0.0`
16
+
17
+ ## Requires
18
+
19
+ - `execution-local` `>=1.0.0 <2.0.0`
20
+
21
+ ## Public setup inputs
22
+
23
+ - None. Deterministic/private values and cross-Module shared facts are not public configuration.
24
+
25
+ ## Ownership boundary
26
+
27
+ Module business APIs and any module-specific extra commands remain package-owned. Platform does not proxy or interpret them. Current human/external preparation is documented in `SETUP.md`.
package/SETUP.md ADDED
@@ -0,0 +1,7 @@
1
+ # @tomflow/proflow-execution-runtime — Module Setup
2
+
3
+ No user or external setup is required by the current frozen Module contract. `Module.install` completes deterministic preparation; `Module.setup` only re-observes current reality and must not ask the user to supply private paths, loopback endpoints, tokens or cross-Module facts.
4
+
5
+ ## Completion
6
+
7
+ Setup is complete only when the Module's own `status` reports `setupStatus=READY`. Re-running setup must re-observe reality; it must not resume from a blind historical step index.
@@ -1,362 +1,134 @@
1
- type ProcessService = {
2
- start(): Promise<{
3
- host: string;
4
- port: number;
5
- }>;
6
- stop(): Promise<void>;
7
- restart(): Promise<{
8
- host: string;
9
- port: number;
10
- }>;
11
- status(): {
12
- readiness: "READY" | "NOT_READY";
13
- };
14
- };
15
- export declare function createBehaviorAdapter(service?: ProcessService, config?: Record<string, string>, configValid?: boolean): {
16
- describe: () => {
17
- result: {
18
- readonly contract: "deployment.result.v1";
19
- readonly ok: true;
20
- readonly status: "SUCCEEDED";
21
- readonly moduleRef: "execution-runtime";
22
- readonly moduleVersion: "0.1.5";
23
- };
24
- observedEffects: never[];
25
- };
26
- preflight: () => {
27
- result: {
28
- readonly contract: "deployment.result.v1";
29
- readonly ok: true;
30
- readonly status: "SUCCEEDED";
31
- readonly moduleRef: "execution-runtime";
32
- readonly moduleVersion: "0.1.5";
33
- };
34
- observedEffects: never[];
35
- };
36
- status: () => {
1
+ import { type ModuleCommandContext } from "@tomflow/proflow-module-contract";
2
+ export declare const behaviorAdapter: {
3
+ readonly install: (context: ModuleCommandContext) => Promise<{
37
4
  result: {
38
5
  contract: "deployment.result.v1";
39
6
  ok: true;
40
7
  status: "SUCCEEDED";
41
8
  moduleRef: "execution-runtime";
42
- moduleVersion: "0.1.5";
9
+ moduleVersion: "0.1.7";
43
10
  data: {
44
- configStatus: "INCOMPLETE" | "INVALID" | "READY";
45
- missingConfig?: string[] | undefined;
46
- runtimeStatus: "FAILED" | "RUNNING" | "STOPPED" | "UNKNOWN";
47
- };
48
- };
49
- observedEffects: never[];
50
- };
51
- verify: () => {
52
- result: {
53
- contract: "deployment.result.v1";
54
- ok: true;
55
- status: "SUCCEEDED";
56
- moduleRef: "execution-runtime";
57
- moduleVersion: "0.1.5";
58
- checks: {
59
- id: string;
60
- status: "FAIL" | "PASS";
61
- message: string;
62
- }[];
63
- } | {
64
- contract: "deployment.result.v1";
65
- moduleRef: "execution-runtime";
66
- moduleVersion: "0.1.5";
67
- ok: false;
68
- status: "ACTION_REQUIRED";
69
- actionRequired: {
70
- readonly action: "bind-runtime";
71
- readonly description: "Bind a configured Execution Runtime service";
72
- };
73
- checks: {
74
- id: string;
75
- status: "FAIL" | "PASS";
76
- message: string;
77
- }[];
78
- } | {
79
- contract: "deployment.result.v1";
80
- moduleRef: "execution-runtime";
81
- moduleVersion: "0.1.5";
82
- ok: false;
83
- status: "ACTION_REQUIRED";
84
- actionRequired: {
85
- action: string;
86
- description: string;
11
+ endpoint: string;
12
+ transportCredentialFile: string;
13
+ databasePath: string;
14
+ projectRoot: string;
15
+ artifactRoot: string;
87
16
  };
88
- checks: {
89
- id: string;
90
- status: "FAIL" | "PASS";
91
- message: string;
92
- }[];
93
17
  };
94
18
  observedEffects: never[];
95
- };
96
- doctor: () => {
19
+ }>;
20
+ readonly uninstall: (context: ModuleCommandContext) => Promise<{
97
21
  result: {
98
22
  readonly contract: "deployment.result.v1";
99
23
  readonly ok: true;
100
24
  readonly status: "SUCCEEDED";
101
25
  readonly moduleRef: "execution-runtime";
102
- readonly moduleVersion: "0.1.5";
26
+ readonly moduleVersion: "0.1.7";
103
27
  };
104
- observedEffects: never[];
105
- };
106
- start: () => Promise<{
28
+ observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
29
+ }>;
30
+ readonly status: (context: ModuleCommandContext) => Promise<{
107
31
  result: {
108
- readonly contract: "deployment.result.v1";
109
- readonly moduleRef: "execution-runtime";
110
- readonly moduleVersion: "0.1.5";
111
- readonly ok: false;
112
- readonly status: "ACTION_REQUIRED";
113
- readonly actionRequired: {
114
- readonly action: "bind-runtime";
115
- readonly description: "Bind a configured Execution Runtime service";
116
- };
117
- } | {
118
32
  contract: "deployment.result.v1";
119
33
  ok: true;
120
34
  status: "SUCCEEDED";
121
35
  moduleRef: "execution-runtime";
122
- moduleVersion: "0.1.5";
36
+ moduleVersion: "0.1.7";
123
37
  data: {
124
- host: string;
125
- port: number;
38
+ setupStatus: "FAILED" | "READY";
39
+ runtimeStatus: "RUNNING" | "STOPPED";
126
40
  };
127
41
  };
128
- observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
129
- }>;
130
- stop: () => Promise<{
131
- result: {
132
- readonly contract: "deployment.result.v1";
133
- readonly ok: true;
134
- readonly status: "SUCCEEDED";
135
- readonly moduleRef: "execution-runtime";
136
- readonly moduleVersion: "0.1.5";
137
- } | {
138
- readonly contract: "deployment.result.v1";
139
- readonly moduleRef: "execution-runtime";
140
- readonly moduleVersion: "0.1.5";
141
- readonly ok: false;
142
- readonly status: "ACTION_REQUIRED";
143
- readonly actionRequired: {
144
- readonly action: "bind-runtime";
145
- readonly description: "Bind a configured Execution Runtime service";
146
- };
147
- };
148
- observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
42
+ observedEffects: never[];
149
43
  }>;
150
- uninstall: () => Promise<{
44
+ readonly setup: (context: ModuleCommandContext) => Promise<{
151
45
  result: {
152
46
  readonly contract: "deployment.result.v1";
153
47
  readonly ok: true;
154
48
  readonly status: "SUCCEEDED";
155
49
  readonly moduleRef: "execution-runtime";
156
- readonly moduleVersion: "0.1.5";
157
- };
158
- observedEffects: "Runs the single backend Execution Runtime service"[];
159
- }>;
160
- restart: () => Promise<{
161
- result: {
162
- readonly contract: "deployment.result.v1";
163
- readonly moduleRef: "execution-runtime";
164
- readonly moduleVersion: "0.1.5";
165
- readonly ok: false;
166
- readonly status: "ACTION_REQUIRED";
167
- readonly actionRequired: {
168
- readonly action: "bind-runtime";
169
- readonly description: "Bind a configured Execution Runtime service";
170
- };
50
+ readonly moduleVersion: "0.1.7";
171
51
  } | {
172
52
  contract: "deployment.result.v1";
173
- ok: true;
174
- status: "SUCCEEDED";
175
53
  moduleRef: "execution-runtime";
176
- moduleVersion: "0.1.5";
177
- data: {
178
- host: string;
179
- port: number;
54
+ moduleVersion: "0.1.7";
55
+ ok: false;
56
+ status: "FAILED";
57
+ error: {
58
+ code: "SETUP_FAILED" | "START_FAILED" | "STOP_FAILED";
59
+ message: string;
60
+ retryable: boolean;
180
61
  };
181
62
  };
182
- observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
183
- }>;
184
- };
185
- export declare const behaviorAdapter: {
186
- describe: () => {
187
- result: {
188
- readonly contract: "deployment.result.v1";
189
- readonly ok: true;
190
- readonly status: "SUCCEEDED";
191
- readonly moduleRef: "execution-runtime";
192
- readonly moduleVersion: "0.1.5";
193
- };
194
- observedEffects: never[];
195
- };
196
- preflight: () => {
197
- result: {
198
- readonly contract: "deployment.result.v1";
199
- readonly ok: true;
200
- readonly status: "SUCCEEDED";
201
- readonly moduleRef: "execution-runtime";
202
- readonly moduleVersion: "0.1.5";
203
- };
204
63
  observedEffects: never[];
205
- };
206
- status: () => {
64
+ }>;
65
+ readonly docs: (_context: ModuleCommandContext) => Promise<{
207
66
  result: {
208
67
  contract: "deployment.result.v1";
209
68
  ok: true;
210
69
  status: "SUCCEEDED";
211
70
  moduleRef: "execution-runtime";
212
- moduleVersion: "0.1.5";
71
+ moduleVersion: "0.1.7";
213
72
  data: {
214
- configStatus: "INCOMPLETE" | "INVALID" | "READY";
215
- missingConfig?: string[] | undefined;
216
- runtimeStatus: "FAILED" | "RUNNING" | "STOPPED" | "UNKNOWN";
73
+ docs: string;
74
+ setup: string;
217
75
  };
218
76
  };
219
77
  observedEffects: never[];
220
- };
221
- verify: () => {
78
+ }>;
79
+ readonly start: (context: ModuleCommandContext) => Promise<{
222
80
  result: {
223
81
  contract: "deployment.result.v1";
224
82
  ok: true;
225
83
  status: "SUCCEEDED";
226
84
  moduleRef: "execution-runtime";
227
- moduleVersion: "0.1.5";
228
- checks: {
229
- id: string;
230
- status: "FAIL" | "PASS";
231
- message: string;
232
- }[];
233
- } | {
85
+ moduleVersion: "0.1.7";
86
+ data: unknown;
87
+ };
88
+ observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
89
+ } | {
90
+ result: {
234
91
  contract: "deployment.result.v1";
235
92
  moduleRef: "execution-runtime";
236
- moduleVersion: "0.1.5";
93
+ moduleVersion: "0.1.7";
237
94
  ok: false;
238
- status: "ACTION_REQUIRED";
239
- actionRequired: {
240
- readonly action: "bind-runtime";
241
- readonly description: "Bind a configured Execution Runtime service";
242
- };
243
- checks: {
244
- id: string;
245
- status: "FAIL" | "PASS";
95
+ status: "FAILED";
96
+ error: {
97
+ code: "SETUP_FAILED" | "START_FAILED" | "STOP_FAILED";
246
98
  message: string;
247
- }[];
248
- } | {
249
- contract: "deployment.result.v1";
250
- moduleRef: "execution-runtime";
251
- moduleVersion: "0.1.5";
252
- ok: false;
253
- status: "ACTION_REQUIRED";
254
- actionRequired: {
255
- action: string;
256
- description: string;
99
+ retryable: boolean;
257
100
  };
258
- checks: {
259
- id: string;
260
- status: "FAIL" | "PASS";
261
- message: string;
262
- }[];
263
101
  };
264
102
  observedEffects: never[];
265
- };
266
- doctor: () => {
267
- result: {
268
- readonly contract: "deployment.result.v1";
269
- readonly ok: true;
270
- readonly status: "SUCCEEDED";
271
- readonly moduleRef: "execution-runtime";
272
- readonly moduleVersion: "0.1.5";
273
- };
274
- observedEffects: never[];
275
- };
276
- start: () => Promise<{
277
- result: {
278
- readonly contract: "deployment.result.v1";
279
- readonly moduleRef: "execution-runtime";
280
- readonly moduleVersion: "0.1.5";
281
- readonly ok: false;
282
- readonly status: "ACTION_REQUIRED";
283
- readonly actionRequired: {
284
- readonly action: "bind-runtime";
285
- readonly description: "Bind a configured Execution Runtime service";
286
- };
287
- } | {
288
- contract: "deployment.result.v1";
289
- ok: true;
290
- status: "SUCCEEDED";
291
- moduleRef: "execution-runtime";
292
- moduleVersion: "0.1.5";
293
- data: {
294
- host: string;
295
- port: number;
296
- };
297
- };
298
- observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
299
103
  }>;
300
- stop: () => Promise<{
104
+ readonly stop: (context: ModuleCommandContext) => Promise<{
301
105
  result: {
302
106
  readonly contract: "deployment.result.v1";
303
107
  readonly ok: true;
304
108
  readonly status: "SUCCEEDED";
305
109
  readonly moduleRef: "execution-runtime";
306
- readonly moduleVersion: "0.1.5";
307
- } | {
308
- readonly contract: "deployment.result.v1";
309
- readonly moduleRef: "execution-runtime";
310
- readonly moduleVersion: "0.1.5";
311
- readonly ok: false;
312
- readonly status: "ACTION_REQUIRED";
313
- readonly actionRequired: {
314
- readonly action: "bind-runtime";
315
- readonly description: "Bind a configured Execution Runtime service";
316
- };
110
+ readonly moduleVersion: "0.1.7";
317
111
  };
318
112
  observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
319
- }>;
320
- uninstall: () => Promise<{
113
+ } | {
321
114
  result: {
322
115
  readonly contract: "deployment.result.v1";
323
116
  readonly ok: true;
324
117
  readonly status: "SUCCEEDED";
325
118
  readonly moduleRef: "execution-runtime";
326
- readonly moduleVersion: "0.1.5";
327
- };
328
- observedEffects: "Runs the single backend Execution Runtime service"[];
329
- }>;
330
- restart: () => Promise<{
331
- result: {
332
- readonly contract: "deployment.result.v1";
333
- readonly moduleRef: "execution-runtime";
334
- readonly moduleVersion: "0.1.5";
335
- readonly ok: false;
336
- readonly status: "ACTION_REQUIRED";
337
- readonly actionRequired: {
338
- readonly action: "bind-runtime";
339
- readonly description: "Bind a configured Execution Runtime service";
340
- };
119
+ readonly moduleVersion: "0.1.7";
341
120
  } | {
342
121
  contract: "deployment.result.v1";
343
- ok: true;
344
- status: "SUCCEEDED";
345
122
  moduleRef: "execution-runtime";
346
- moduleVersion: "0.1.5";
347
- data: {
348
- host: string;
349
- port: number;
123
+ moduleVersion: "0.1.7";
124
+ ok: false;
125
+ status: "FAILED";
126
+ error: {
127
+ code: "SETUP_FAILED" | "START_FAILED" | "STOP_FAILED";
128
+ message: string;
129
+ retryable: boolean;
350
130
  };
351
131
  };
352
- observedEffects: ("Persists execution state, output references and evidence in WAL SQLite" | "Runs the single backend Execution Runtime service")[];
132
+ observedEffects: never[];
353
133
  }>;
354
134
  };
355
- export declare function createProductionBinding(input: {
356
- moduleRef: string;
357
- config: Record<string, string>;
358
- configByModuleRef: ReadonlyMap<string, Record<string, string>>;
359
- }): Promise<{
360
- behaviorAdapter: Record<string, unknown>;
361
- }>;
362
- export {};
@@ -1,6 +1,8 @@
1
- import { createServer } from "node:net";
2
- import { observeDeclaredModuleStatus } from "@tomflow/proflow-module-contract";
1
+ import { mkdir, readFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { deterministicLoopbackPort, ensureModuleSecretFile, moduleWorkspaceStateDirectory, readModuleSharedFacts, writeModuleSharedFacts, } from "@tomflow/proflow-module-contract";
3
4
  import { descriptor } from "./descriptor.js";
5
+ const services = new Map();
4
6
  const base = {
5
7
  contract: "deployment.result.v1",
6
8
  ok: true,
@@ -8,247 +10,182 @@ const base = {
8
10
  moduleRef: descriptor.moduleRef,
9
11
  moduleVersion: descriptor.moduleVersion,
10
12
  };
11
- const unbound = {
12
- ...base,
13
- ok: false,
14
- status: "ACTION_REQUIRED",
15
- actionRequired: {
16
- action: "bind-runtime",
17
- description: "Bind a configured Execution Runtime service",
18
- },
19
- };
20
- async function listenerPreflight(listener) {
21
- const port = listener.port === "" ? 80 : Number(listener.port);
22
- const host = listener.hostname.replace(/^\[(.*)\]$/, "$1");
23
- const address = `${host}:${port}`;
13
+ const key = (context) => resolve(context.workspaceRoot);
14
+ const factString = (facts, name) => (typeof facts?.[name] === "string" ? String(facts[name]) : undefined);
15
+ async function ownFacts(context) {
16
+ const state = moduleWorkspaceStateDirectory(context, descriptor.moduleRef);
17
+ await mkdir(state, { recursive: true, mode: 0o700 });
18
+ const facts = {
19
+ endpoint: `http://127.0.0.1:${deterministicLoopbackPort(context, descriptor.moduleRef)}`,
20
+ transportCredentialFile: await ensureModuleSecretFile(context, descriptor.moduleRef, "transport"),
21
+ databasePath: join(state, "execution.sqlite"),
22
+ projectRoot: key(context),
23
+ artifactRoot: join(key(context), ".proflow", "artifacts", "execution"),
24
+ };
25
+ await mkdir(facts.artifactRoot, { recursive: true, mode: 0o700 });
26
+ await writeModuleSharedFacts(context, descriptor.moduleRef, facts);
27
+ return facts;
28
+ }
29
+ async function baseDependencies(context) {
30
+ const host = await readModuleSharedFacts(context, "platform-host");
31
+ const model = await readModuleSharedFacts(context, "model-runtime");
32
+ const identityEndpoint = factString(host, "endpoint");
33
+ const identityTokenFile = factString(host, "identityTokenFile");
34
+ const modelEndpoint = factString(model, "endpoint");
35
+ const modelCredentialFile = factString(model, "transportCredentialFile");
36
+ return identityEndpoint &&
37
+ identityTokenFile &&
38
+ modelEndpoint &&
39
+ modelCredentialFile
40
+ ? {
41
+ identityEndpoint,
42
+ identityTokenFile,
43
+ modelEndpoint,
44
+ modelCredentialFile,
45
+ }
46
+ : undefined;
47
+ }
48
+ async function dependencies(context) {
49
+ const base = await baseDependencies(context);
50
+ const browser = await readModuleSharedFacts(context, "execution-browser-extension");
51
+ const browserExecutorConfigPath = factString(browser, "browserExecutorConfigPath");
52
+ return base && browserExecutorConfigPath
53
+ ? {
54
+ ...base,
55
+ browserExecutorConfigPath,
56
+ }
57
+ : undefined;
58
+ }
59
+ async function running(context) {
60
+ const own = await ownFacts(context);
24
61
  try {
25
- const response = await fetch(new URL("/ready", listener), {
62
+ const token = (await readFile(own.transportCredentialFile, "utf8")).trim();
63
+ return (await fetch(`${own.endpoint}/ready`, {
64
+ headers: { authorization: `Bearer ${token}` },
26
65
  signal: AbortSignal.timeout(500),
27
- });
28
- if (response.ok)
29
- return {
30
- result: {
31
- ...base,
32
- checks: [
33
- {
34
- id: "execution-runtime-listener",
35
- status: "PASS",
36
- message: `Execution Runtime listener ${address} is already READY`,
37
- },
38
- ],
39
- },
40
- observedEffects: [],
41
- };
66
+ })).ok;
42
67
  }
43
68
  catch {
44
- // A stopped runtime is expected here; continue with a bind-only port probe.
69
+ return false;
45
70
  }
46
- const probe = await new Promise((resolve) => {
47
- const server = createServer();
48
- server.once("error", (error) => resolve({
49
- available: false,
50
- message: error instanceof Error ? error.message : String(error),
51
- }));
52
- server.listen({ host, port, exclusive: true }, () => server.close(() => resolve({
53
- available: true,
54
- message: `Execution Runtime listener ${address} is available`,
55
- })));
56
- });
57
- return probe.available
58
- ? {
59
- result: {
60
- ...base,
61
- checks: [
62
- {
63
- id: "execution-runtime-listener",
64
- status: "PASS",
65
- message: probe.message,
66
- },
67
- ],
71
+ }
72
+ async function compose(context) {
73
+ const own = await ownFacts(context);
74
+ const deps = await dependencies(context);
75
+ if (!deps)
76
+ throw new Error("required Platform Host, Model Runtime, or Browser Executor shared facts are unavailable");
77
+ const [{ createFormalExecutionRuntimeLifecycle }, { parseExecutionRuntimeProcessConfig },] = await Promise.all([
78
+ import("../src/formal-process.js"),
79
+ import("../src/service.js"),
80
+ ]);
81
+ const url = new URL(own.endpoint);
82
+ return createFormalExecutionRuntimeLifecycle({
83
+ config: parseExecutionRuntimeProcessConfig({
84
+ host: url.hostname,
85
+ port: Number(url.port),
86
+ databasePath: own.databasePath,
87
+ projectRoot: own.projectRoot,
88
+ artifactRoot: own.artifactRoot,
89
+ browserExecutorConfigPath: deps.browserExecutorConfigPath,
90
+ transportCredentialFile: own.transportCredentialFile,
91
+ identity: {
92
+ endpoint: deps.identityEndpoint,
93
+ tokenFile: deps.identityTokenFile,
68
94
  },
69
- observedEffects: [],
70
- }
71
- : {
72
- result: {
73
- ...base,
74
- ok: false,
75
- status: "ACTION_REQUIRED",
76
- actionRequired: {
77
- action: "free-execution-runtime-port",
78
- description: `Execution Runtime listener ${address} is unavailable (${probe.message}); stop the conflicting process or configure a different endpoint before platform start`,
79
- },
80
- checks: [
81
- {
82
- id: "execution-runtime-listener",
83
- status: "FAIL",
84
- message: probe.message,
85
- },
86
- ],
95
+ modelDecision: {
96
+ endpoint: deps.modelEndpoint,
97
+ credentialFile: deps.modelCredentialFile,
87
98
  },
88
- observedEffects: [],
89
- };
99
+ exactNetworkTargets: [],
100
+ }),
101
+ });
90
102
  }
91
- export function createBehaviorAdapter(service, config, configValid = true) {
92
- return {
93
- describe: () => ({ result: base, observedEffects: [] }),
94
- preflight: () => ({ result: base, observedEffects: [] }),
95
- status: () => {
96
- const status = service?.status();
97
- const ready = status?.readiness === "READY";
98
- const data = observeDeclaredModuleStatus(descriptor, config, ready ? "RUNNING" : service ? "FAILED" : "UNKNOWN", configValid);
103
+ const failed = (code, message) => ({
104
+ ...base,
105
+ ok: false,
106
+ status: "FAILED",
107
+ error: { code, message, retryable: true },
108
+ });
109
+ export const behaviorAdapter = {
110
+ install: async (context) => ({
111
+ result: { ...base, data: await ownFacts(context) },
112
+ observedEffects: [],
113
+ }),
114
+ uninstall: async (context) => {
115
+ const service = services.get(key(context));
116
+ if (service) {
117
+ await service.stop();
118
+ services.delete(key(context));
119
+ }
120
+ return {
121
+ result: base,
122
+ observedEffects: service
123
+ ? [...descriptor.effects.map((item) => item.description)]
124
+ : [],
125
+ };
126
+ },
127
+ status: async (context) => ({
128
+ result: {
129
+ ...base,
130
+ data: {
131
+ setupStatus: (await dependencies(context))
132
+ ? "READY"
133
+ : "FAILED",
134
+ runtimeStatus: (await running(context))
135
+ ? "RUNNING"
136
+ : "STOPPED",
137
+ },
138
+ },
139
+ observedEffects: [],
140
+ }),
141
+ setup: async (context) => ({
142
+ result: (await dependencies(context))
143
+ ? base
144
+ : failed("SETUP_FAILED", "required producer shared facts are unavailable"),
145
+ observedEffects: [],
146
+ }),
147
+ docs: async (_context) => ({
148
+ result: { ...base, data: { docs: "DOCS.md", setup: "SETUP.md" } },
149
+ observedEffects: [],
150
+ }),
151
+ start: async (context) => {
152
+ try {
153
+ const service = await compose(context);
154
+ const data = await service.start();
155
+ services.set(key(context), service);
99
156
  return {
100
157
  result: { ...base, data },
101
- observedEffects: [],
158
+ observedEffects: [
159
+ ...descriptor.effects.map((item) => item.description),
160
+ ],
102
161
  };
103
- },
104
- verify: () => {
105
- const status = service?.status();
106
- const ready = status?.readiness === "READY";
162
+ }
163
+ catch (error) {
107
164
  return {
108
- result: {
109
- ...(service && ready
110
- ? base
111
- : service
112
- ? {
113
- ...base,
114
- ok: false,
115
- status: "ACTION_REQUIRED",
116
- actionRequired: {
117
- action: "repair-execution-runtime",
118
- description: "Execution Runtime is not READY",
119
- },
120
- }
121
- : unbound),
122
- checks: [
123
- {
124
- id: "execution-runtime-critical-proofs",
125
- status: ready ? "PASS" : "FAIL",
126
- message: service
127
- ? `Execution Runtime readiness is ${status?.readiness ?? "NOT_READY"}`
128
- : "No configured Execution Runtime process is bound",
129
- },
130
- ],
131
- },
165
+ result: failed("START_FAILED", error instanceof Error
166
+ ? error.message
167
+ : "execution-runtime start failed"),
132
168
  observedEffects: [],
133
169
  };
134
- },
135
- doctor: () => ({ result: base, observedEffects: [] }),
136
- start: async () => ({
137
- result: service ? { ...base, data: await service.start() } : unbound,
138
- observedEffects: service
139
- ? [...descriptor.effects.map((item) => item.description)]
140
- : [],
141
- }),
142
- stop: async () => {
143
- if (service)
144
- await service.stop();
145
- return {
146
- result: service ? base : unbound,
147
- observedEffects: service
148
- ? [...descriptor.effects.map((item) => item.description)]
149
- : [],
150
- };
151
- },
152
- uninstall: async () => {
153
- if (service)
154
- await service.stop();
170
+ }
171
+ },
172
+ stop: async (context) => {
173
+ const service = services.get(key(context));
174
+ if (service) {
175
+ await service.stop();
176
+ services.delete(key(context));
155
177
  return {
156
- // Uninstall is idempotent: an unbound service means there is no
157
- // process to stop before package removal. Runtime readiness still
158
- // fails closed in status/start/verify.
159
178
  result: base,
160
- observedEffects: service
161
- ? descriptor.effects
162
- .filter((item) => item.retention === "remove")
163
- .map((item) => item.description)
164
- : [],
179
+ observedEffects: [
180
+ ...descriptor.effects.map((item) => item.description),
181
+ ],
165
182
  };
166
- },
167
- restart: async () => ({
168
- result: service ? { ...base, data: await service.restart() } : unbound,
169
- observedEffects: service
170
- ? [...descriptor.effects.map((item) => item.description)]
171
- : [],
172
- }),
173
- };
174
- }
175
- export const behaviorAdapter = createBehaviorAdapter();
176
- export async function createProductionBinding(input) {
177
- const unboundBinding = (configValid = true) => ({
178
- behaviorAdapter: createBehaviorAdapter(undefined, input.config, configValid),
179
- });
180
- const required = [
181
- "databasePath",
182
- "projectRoot",
183
- "artifactRoot",
184
- "browserExecutorConfigPath",
185
- "transportCredentialFile",
186
- "identity.endpoint",
187
- "identity.tokenFile",
188
- "modelDecision.endpoint",
189
- "modelDecision.credentialFile",
190
- ];
191
- if (!required.every((key) => input.config[key]))
192
- return unboundBinding();
193
- for (const key of ["identity.endpoint", "modelDecision.endpoint"]) {
194
- try {
195
- const endpoint = new URL(input.config[key] ?? "");
196
- if (endpoint.protocol !== "http:")
197
- return unboundBinding(false);
198
183
  }
199
- catch {
200
- return unboundBinding(false);
201
- }
202
- }
203
- const platformHost = input.configByModuleRef.get("platform-host");
204
- const advertised = platformHost?.executionBaseUrl;
205
- if (!advertised)
206
- return unboundBinding();
207
- let listener;
208
- try {
209
- listener = new URL(advertised);
210
- }
211
- catch {
212
- return unboundBinding();
213
- }
214
- if (listener.protocol !== "http:" || listener.pathname !== "/")
215
- return unboundBinding();
216
- const port = listener.port === "" ? 80 : Number(listener.port);
217
- if (!Number.isInteger(port) || port <= 0 || port > 65_535)
218
- return unboundBinding();
219
- const [{ createFormalExecutionRuntimeLifecycle }, { parseExecutionRuntimeProcessConfig },] = await Promise.all([
220
- import("../src/formal-process.js"),
221
- import("../src/service.js"),
222
- ]);
223
- let service;
224
- try {
225
- service = createFormalExecutionRuntimeLifecycle({
226
- config: parseExecutionRuntimeProcessConfig({
227
- host: listener.hostname,
228
- port,
229
- databasePath: input.config.databasePath,
230
- projectRoot: input.config.projectRoot,
231
- artifactRoot: input.config.artifactRoot,
232
- browserExecutorConfigPath: input.config.browserExecutorConfigPath,
233
- transportCredentialFile: input.config.transportCredentialFile,
234
- identity: {
235
- endpoint: input.config["identity.endpoint"],
236
- tokenFile: input.config["identity.tokenFile"],
237
- },
238
- modelDecision: {
239
- endpoint: input.config["modelDecision.endpoint"],
240
- credentialFile: input.config["modelDecision.credentialFile"],
241
- },
242
- }),
243
- });
244
- }
245
- catch {
246
- return unboundBinding(false);
247
- }
248
- return {
249
- behaviorAdapter: {
250
- ...createBehaviorAdapter(service, input.config),
251
- preflight: () => listenerPreflight(listener),
252
- },
253
- };
254
- }
184
+ return {
185
+ result: (await running(context))
186
+ ? failed("STOP_FAILED", "execution-runtime is running without an owned lifecycle handle")
187
+ : base,
188
+ observedEffects: [],
189
+ };
190
+ },
191
+ };
@@ -3,7 +3,7 @@ export declare const descriptor: {
3
3
  readonly contractVersion: "1.0.0";
4
4
  readonly moduleRef: "execution-runtime";
5
5
  readonly packageName: "@tomflow/proflow-execution-runtime";
6
- readonly moduleVersion: "0.1.5";
6
+ readonly moduleVersion: "0.1.7";
7
7
  readonly kind: "service";
8
8
  readonly templateVersion: "1.0.0";
9
9
  readonly platformCompatibility: ">=1.0.0 <2.0.0";
@@ -28,65 +28,7 @@ export declare const descriptor: {
28
28
  readonly path: ".proflow";
29
29
  readonly access: "read-write";
30
30
  }];
31
- readonly configSlots: readonly [{
32
- readonly key: "databasePath";
33
- readonly type: "path";
34
- readonly required: true;
35
- readonly description: "Execution SQLite database";
36
- }, {
37
- readonly key: "projectRoot";
38
- readonly type: "path";
39
- readonly required: true;
40
- readonly description: "Canonical project boundary consumed by the local executor";
41
- }, {
42
- readonly key: "artifactRoot";
43
- readonly type: "path";
44
- readonly required: true;
45
- readonly description: "Execution-owned Artifact/Evidence filesystem root";
46
- }, {
47
- readonly key: "browserExecutorConfigPath";
48
- readonly type: "path";
49
- readonly required: true;
50
- readonly description: "Absolute configuration path for the formal Browser Reality Bridge composition";
51
- }, {
52
- readonly key: "transportCredentialFile";
53
- readonly type: "path";
54
- readonly required: true;
55
- readonly sensitive: true;
56
- readonly description: "File containing the Execution Runtime transport credential";
57
- }, {
58
- readonly key: "identity.endpoint";
59
- readonly type: "url";
60
- readonly required: true;
61
- readonly description: "Loopback platform-host execution identity endpoint";
62
- }, {
63
- readonly key: "identity.tokenFile";
64
- readonly type: "path";
65
- readonly required: true;
66
- readonly sensitive: true;
67
- readonly description: "File containing the Execution-to-platform-host identity transport credential";
68
- }, {
69
- readonly key: "modelDecision.endpoint";
70
- readonly type: "url";
71
- readonly required: true;
72
- readonly description: "Loopback Model Runtime endpoint used by execution.command-risk.v1";
73
- }, {
74
- readonly key: "modelDecision.credentialFile";
75
- readonly type: "path";
76
- readonly required: true;
77
- readonly sensitive: true;
78
- readonly description: "File containing the Execution-to-Model transport credential";
79
- }];
80
- readonly lifecycle: {
81
- readonly supported: readonly ["describe", "preflight", "status", "verify", "doctor", "start", "stop", "restart", "uninstall"];
82
- };
83
- readonly verification: {
84
- readonly checks: readonly [{
85
- readonly id: "execution-runtime-critical-proofs";
86
- readonly description: "Execution Runtime critical proofs pass";
87
- readonly lifecycle: "verify";
88
- }];
89
- };
31
+ readonly configSlots: readonly [];
90
32
  readonly effects: readonly [{
91
33
  readonly kind: "process";
92
34
  readonly description: "Runs the single backend Execution Runtime service";
@@ -96,13 +38,8 @@ export declare const descriptor: {
96
38
  readonly description: "Persists execution state, output references and evidence in WAL SQLite";
97
39
  readonly retention: "preserve";
98
40
  }];
99
- readonly documentation: readonly [{
100
- readonly id: "overview";
101
- readonly path: "./README.md";
102
- readonly description: "Execution Runtime package overview";
103
- }, {
104
- readonly id: "configuration";
105
- readonly path: "./CONFIGURATION.md";
106
- readonly description: "Module configuration fields, sources and materialization instructions";
107
- }];
41
+ readonly documentation: {
42
+ readonly docs: "DOCS.md";
43
+ readonly setup: "SETUP.md";
44
+ };
108
45
  };
@@ -3,7 +3,7 @@ export const descriptor = {
3
3
  contractVersion: "1.0.0",
4
4
  moduleRef: "execution-runtime",
5
5
  packageName: "@tomflow/proflow-execution-runtime",
6
- moduleVersion: "0.1.5",
6
+ moduleVersion: "0.1.7",
7
7
  kind: "service",
8
8
  templateVersion: "1.0.0",
9
9
  platformCompatibility: ">=1.0.0 <2.0.0",
@@ -35,87 +35,7 @@ export const descriptor = {
35
35
  access: "read-write",
36
36
  },
37
37
  ],
38
- configSlots: [
39
- {
40
- key: "databasePath",
41
- type: "path",
42
- required: true,
43
- description: "Execution SQLite database",
44
- },
45
- {
46
- key: "projectRoot",
47
- type: "path",
48
- required: true,
49
- description: "Canonical project boundary consumed by the local executor",
50
- },
51
- {
52
- key: "artifactRoot",
53
- type: "path",
54
- required: true,
55
- description: "Execution-owned Artifact/Evidence filesystem root",
56
- },
57
- {
58
- key: "browserExecutorConfigPath",
59
- type: "path",
60
- required: true,
61
- description: "Absolute configuration path for the formal Browser Reality Bridge composition",
62
- },
63
- {
64
- key: "transportCredentialFile",
65
- type: "path",
66
- required: true,
67
- sensitive: true,
68
- description: "File containing the Execution Runtime transport credential",
69
- },
70
- {
71
- key: "identity.endpoint",
72
- type: "url",
73
- required: true,
74
- description: "Loopback platform-host execution identity endpoint",
75
- },
76
- {
77
- key: "identity.tokenFile",
78
- type: "path",
79
- required: true,
80
- sensitive: true,
81
- description: "File containing the Execution-to-platform-host identity transport credential",
82
- },
83
- {
84
- key: "modelDecision.endpoint",
85
- type: "url",
86
- required: true,
87
- description: "Loopback Model Runtime endpoint used by execution.command-risk.v1",
88
- },
89
- {
90
- key: "modelDecision.credentialFile",
91
- type: "path",
92
- required: true,
93
- sensitive: true,
94
- description: "File containing the Execution-to-Model transport credential",
95
- },
96
- ],
97
- lifecycle: {
98
- supported: [
99
- "describe",
100
- "preflight",
101
- "status",
102
- "verify",
103
- "doctor",
104
- "start",
105
- "stop",
106
- "restart",
107
- "uninstall",
108
- ],
109
- },
110
- verification: {
111
- checks: [
112
- {
113
- id: "execution-runtime-critical-proofs",
114
- description: "Execution Runtime critical proofs pass",
115
- lifecycle: "verify",
116
- },
117
- ],
118
- },
38
+ configSlots: [],
119
39
  effects: [
120
40
  {
121
41
  kind: "process",
@@ -128,16 +48,8 @@ export const descriptor = {
128
48
  retention: "preserve",
129
49
  },
130
50
  ],
131
- documentation: [
132
- {
133
- id: "overview",
134
- path: "./README.md",
135
- description: "Execution Runtime package overview",
136
- },
137
- {
138
- id: "configuration",
139
- path: "./CONFIGURATION.md",
140
- description: "Module configuration fields, sources and materialization instructions",
141
- },
142
- ],
51
+ documentation: {
52
+ docs: "DOCS.md",
53
+ setup: "SETUP.md",
54
+ },
143
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomflow/proflow-execution-runtime",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -20,17 +20,18 @@
20
20
  "proflow.module.json",
21
21
  "conformance.json",
22
22
  "README.md",
23
- "CONFIGURATION.md"
23
+ "DOCS.md",
24
+ "SETUP.md"
24
25
  ],
25
26
  "dependencies": {
26
- "@tomflow/proflow-execution-contracts": "^0.1.2",
27
- "@tomflow/proflow-module-contract": "^0.1.1",
28
- "@tomflow/proflow-model-contracts": "^0.1.2",
29
- "@tomflow/proflow-execution-local": "^0.1.3",
30
- "@tomflow/proflow-execution-browser-extension": "^0.1.3"
27
+ "@tomflow/proflow-module-contract": "^0.1.4",
28
+ "@tomflow/proflow-execution-browser-extension": "^0.1.5",
29
+ "@tomflow/proflow-execution-contracts": "^0.1.4",
30
+ "@tomflow/proflow-model-contracts": "^0.1.4",
31
+ "@tomflow/proflow-execution-local": "^0.1.5"
31
32
  },
32
33
  "devDependencies": {
33
- "@tomflow/proflow-deployment-conformance": "^0.1.2"
34
+ "@tomflow/proflow-deployment-conformance": "^0.1.4"
34
35
  },
35
36
  "description": "Durable, policy-controlled Execution Core orchestration over SQLite and controlled executor ports.",
36
37
  "keywords": [
@@ -3,7 +3,7 @@
3
3
  "contractVersion": "1.0.0",
4
4
  "moduleRef": "execution-runtime",
5
5
  "packageName": "@tomflow/proflow-execution-runtime",
6
- "moduleVersion": "0.1.5",
6
+ "moduleVersion": "0.1.7",
7
7
  "kind": "service",
8
8
  "templateVersion": "1.0.0",
9
9
  "platformCompatibility": ">=1.0.0 <2.0.0",
@@ -35,87 +35,7 @@
35
35
  "access": "read-write"
36
36
  }
37
37
  ],
38
- "configSlots": [
39
- {
40
- "key": "databasePath",
41
- "type": "path",
42
- "required": true,
43
- "description": "Execution SQLite database"
44
- },
45
- {
46
- "key": "projectRoot",
47
- "type": "path",
48
- "required": true,
49
- "description": "Canonical project boundary consumed by the local executor"
50
- },
51
- {
52
- "key": "artifactRoot",
53
- "type": "path",
54
- "required": true,
55
- "description": "Execution-owned Artifact/Evidence filesystem root"
56
- },
57
- {
58
- "key": "browserExecutorConfigPath",
59
- "type": "path",
60
- "required": true,
61
- "description": "Absolute configuration path for the formal Browser Reality Bridge composition"
62
- },
63
- {
64
- "key": "transportCredentialFile",
65
- "type": "path",
66
- "required": true,
67
- "sensitive": true,
68
- "description": "File containing the Execution Runtime transport credential"
69
- },
70
- {
71
- "key": "identity.endpoint",
72
- "type": "url",
73
- "required": true,
74
- "description": "Loopback platform-host execution identity endpoint"
75
- },
76
- {
77
- "key": "identity.tokenFile",
78
- "type": "path",
79
- "required": true,
80
- "sensitive": true,
81
- "description": "File containing the Execution-to-platform-host identity transport credential"
82
- },
83
- {
84
- "key": "modelDecision.endpoint",
85
- "type": "url",
86
- "required": true,
87
- "description": "Loopback Model Runtime endpoint used by execution.command-risk.v1"
88
- },
89
- {
90
- "key": "modelDecision.credentialFile",
91
- "type": "path",
92
- "required": true,
93
- "sensitive": true,
94
- "description": "File containing the Execution-to-Model transport credential"
95
- }
96
- ],
97
- "lifecycle": {
98
- "supported": [
99
- "describe",
100
- "preflight",
101
- "status",
102
- "verify",
103
- "doctor",
104
- "start",
105
- "stop",
106
- "restart",
107
- "uninstall"
108
- ]
109
- },
110
- "verification": {
111
- "checks": [
112
- {
113
- "id": "execution-runtime-critical-proofs",
114
- "description": "Execution Runtime critical proofs pass",
115
- "lifecycle": "verify"
116
- }
117
- ]
118
- },
38
+ "configSlots": [],
119
39
  "effects": [
120
40
  {
121
41
  "kind": "process",
@@ -128,16 +48,8 @@
128
48
  "retention": "preserve"
129
49
  }
130
50
  ],
131
- "documentation": [
132
- {
133
- "id": "overview",
134
- "path": "./README.md",
135
- "description": "Execution Runtime package overview"
136
- },
137
- {
138
- "id": "configuration",
139
- "path": "./CONFIGURATION.md",
140
- "description": "Module configuration fields, sources and materialization instructions"
141
- }
142
- ]
51
+ "documentation": {
52
+ "docs": "DOCS.md",
53
+ "setup": "SETUP.md"
54
+ }
143
55
  }
package/CONFIGURATION.md DELETED
@@ -1,31 +0,0 @@
1
- # execution-runtime configuration
2
-
3
- Canonical public config: `.proflow/config/execution-runtime.json`
4
-
5
- This file is Workspace-owned data. `platform uninstall` does not delete it. Values are JSON strings. Raw secrets must not be stored here; `secretRef` fields contain opaque references only.
6
-
7
- ## Fields
8
-
9
- | Key | Type | Required | Sensitive | Source | Meaning |
10
- |---|---|---:|---:|---|---|
11
- | `databasePath` | `path` | yes | no | User or owning Module supplies an absolute/local path that exists on this Workspace. | Execution SQLite database |
12
- | `projectRoot` | `path` | yes | no | User or owning Module supplies an absolute/local path that exists on this Workspace. | Canonical project boundary consumed by the local executor |
13
- | `artifactRoot` | `path` | yes | no | User or owning Module supplies an absolute/local path that exists on this Workspace. | Execution-owned Artifact/Evidence filesystem root |
14
- | `browserExecutorConfigPath` | `path` | yes | no | User or owning Module supplies an absolute/local path that exists on this Workspace. | Absolute configuration path for the formal Browser Reality Bridge composition |
15
- | `transportCredentialFile` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Execution Runtime transport credential |
16
- | `identity.endpoint` | `url` | yes | no | User or owning external/runtime Module supplies the reachable endpoint URL. | Loopback platform-host execution identity endpoint |
17
- | `identity.tokenFile` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Execution-to-platform-host identity transport credential |
18
- | `modelDecision.endpoint` | `url` | yes | no | User or owning external/runtime Module supplies the reachable endpoint URL. | Loopback Model Runtime endpoint used by execution.command-risk.v1 |
19
- | `modelDecision.credentialFile` | `path` | yes | yes | User or owning Module supplies an absolute/local path that exists on this Workspace. | File containing the Execution-to-Model transport credential |
20
-
21
- ## Materialize
22
-
23
- Create or update the canonical JSON object at:
24
-
25
- `.proflow/config/execution-runtime.json`
26
-
27
- Use only declared keys and string values. Do not create a second Platform configuration database.
28
-
29
- ## Base completion check
30
-
31
- Run `platform modules`. This Module should no longer report required keys in `missingConfig`. `platform start` performs the authoritative Module-owned validation before starting anything.