@pulse-compute/wasm-compiler 0.0.0 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -1
- package/bin/provider-proof-composition.js +34 -0
- package/bin/pulsewasm-extract.js +20 -0
- package/package.json +60 -5
- package/src/artifacts-dir.js +13 -0
- package/src/ast-json.js +52 -0
- package/src/build-manifest.js +354 -0
- package/src/canonical-api-compiler.js +269 -0
- package/src/canonical-native-compiler.js +411 -0
- package/src/canonical-native-plan.js +1478 -0
- package/src/canonical-project-compiler.js +1224 -0
- package/src/canonical-router-compiler.js +25 -0
- package/src/cli-intents.js +1235 -0
- package/src/cli.js +1927 -0
- package/src/codegen/assemblyscript-compile.js +3 -0
- package/src/codegen/assemblyscript-core.js +3 -0
- package/src/codegen/assemblyscript-shape.js +3 -0
- package/src/codegen/assemblyscript-wasm-smoke.js +3 -0
- package/src/codegen/backend-capabilities.js +3 -0
- package/src/codegen/channel-broadcaster.js +3 -0
- package/src/codegen/compiled-handlers.js +3 -0
- package/src/codegen/compiled-wasm-runtime.js +3 -0
- package/src/codegen/config-references.js +248 -0
- package/src/codegen/dispatch-ts.js +145 -0
- package/src/codegen/effect-composition.js +331 -0
- package/src/codegen/effect-runtime.js +418 -0
- package/src/codegen/execution-harness-ts.js +467 -0
- package/src/codegen/handler-bindings-ts.js +298 -0
- package/src/codegen/handler-library-contracts.js +3 -0
- package/src/codegen/host-capabilities.js +3 -0
- package/src/codegen/host-runtime-kernel.js +3 -0
- package/src/codegen/integrated-compiled-app.js +3 -0
- package/src/codegen/json-body.js +3 -0
- package/src/codegen/library-sidecars.js +3 -0
- package/src/codegen/local-harness-ts.js +453 -0
- package/src/codegen/pulse-wrapper.js +217 -0
- package/src/codegen/request-result-headers.js +3 -0
- package/src/codegen/schema-json-compile.js +3 -0
- package/src/codegen/schema-json-sidecar-v2.js +3 -0
- package/src/codegen/schema-json-sidecar.js +3 -0
- package/src/codegen/streaming-passthrough.js +3 -0
- package/src/codegen/wasm-host-abi.js +3 -0
- package/src/codegen/wasm-host-bridge.js +3 -0
- package/src/compiled-wasm-host-runtime-kv.js +3 -0
- package/src/config-resolver.js +813 -0
- package/src/crypto-requirement-planner.js +89 -0
- package/src/definitions/config-schema.js +14 -0
- package/src/definitions/handler-roles.js +14 -0
- package/src/definitions/path-grammar.js +14 -0
- package/src/definitions/router-api.js +14 -0
- package/src/diagnostics/codes.js +14 -0
- package/src/diagnostics/reporter.js +14 -0
- package/src/diagnostics.js +14 -0
- package/src/dispatch-table.js +400 -0
- package/src/events/event-emit.js +265 -0
- package/src/events/event-topology.js +127 -0
- package/src/execution-plan.js +463 -0
- package/src/extractor.js +2816 -0
- package/src/handler-eval.js +1154 -0
- package/src/handler-table.js +326 -0
- package/src/index.js +19 -0
- package/src/javascript-application-plan.js +181 -0
- package/src/kv-provider.js +3 -0
- package/src/path-table.js +60 -0
- package/src/path.js +14 -0
- package/src/patterns/config-define.js +30 -0
- package/src/patterns/dependency-call.js +18 -0
- package/src/patterns/env-lookup.js +13 -0
- package/src/patterns/handler-reference.js +29 -0
- package/src/patterns/path-literal.js +35 -0
- package/src/patterns/result.js +15 -0
- package/src/patterns/router-chain-call.js +50 -0
- package/src/patterns/router-construction.js +19 -0
- package/src/project/package-reachability.js +782 -0
- package/src/project/reachable-graph-builder.js +992 -0
- package/src/project/reachable-graph-contract.js +54 -0
- package/src/project/reachable-graph-implementation.js +36 -0
- package/src/project/router-module-linker.js +710 -0
- package/src/project-config-compiler.js +222 -0
- package/src/project-target-support.js +500 -0
- package/src/provider-toolchain.js +299 -0
- package/src/spine/async-surface-normalizer.js +328 -0
- package/src/spine/canonical-handler-ir.js +336 -0
- package/src/spine/canonical-native-module.js +87 -0
- package/src/spine/canonical-native-plan.js +89 -0
- package/src/spine/canonical-project.js +76 -0
- package/src/spine/canonical-router.js +155 -0
- package/src/spine/canonical-source.js +165 -0
- package/src/spine/diagnostic-authority.js +290 -0
- package/src/spine/equivalence.js +262 -0
- package/src/spine/guest-unit-stage.js +87 -0
- package/src/spine/handler-ir-emitter.js +455 -0
- package/src/spine/handler-ir-managed.js +1598 -0
- package/src/spine/handler-ir.js +797 -0
- package/src/spine/handler-surface-authority.js +588 -0
- package/src/spine/package-operation-seam.js +1015 -0
- package/src/spine/pipeline.js +202 -0
- package/src/spine/plain-handler-frontend.js +545 -0
- package/src/spine/provider-requirement-authority.js +208 -0
- package/src/spine/router-control-contract.js +17 -0
- package/src/spine/router-handler-frontend.js +514 -0
- package/src/spine/router-handler-ir.js +372 -0
- package/src/spine/router-topology-frontend.js +638 -0
- package/src/stable-id.js +14 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { PACKAGE_VERSION, normalizeArtifact, normalizeDiagnostic } = require('../diagnostics.js');
|
|
4
|
+
|
|
5
|
+
const PHASE = '11F';
|
|
6
|
+
const EFFECT_RUNTIME_VERSION = 'pulsewasm.effect-runtime.v1';
|
|
7
|
+
const EFFECT_RUNTIME_CONTRACT_VERSION = 'pulsewasm.effect-runtime-contract.v1';
|
|
8
|
+
const EFFECT_KIND_REGISTRY_VERSION = 'pulsewasm.effect-kind-registry.v1';
|
|
9
|
+
const EFFECT_RESUME_PROTOCOL_VERSION = 'pulsewasm.effect-resume-protocol.v1';
|
|
10
|
+
const EFFECT_TIMEOUT_POLICY_VERSION = 'pulsewasm.effect-timeout-policy.v1';
|
|
11
|
+
|
|
12
|
+
const CONTEXT_STATES = ['active', 'suspended', 'resuming', 'expired', 'completed', 'cleaned'];
|
|
13
|
+
const EFFECT_STATES = ['pending', 'completed', 'failed', 'expired', 'cancelled'];
|
|
14
|
+
|
|
15
|
+
const STEP_RESULTS = [
|
|
16
|
+
{ code: 'STEP_CONTINUE', value: 0, meaning: 'Continue scanning/executing the current Pulse execution plan.' },
|
|
17
|
+
{ code: 'STEP_DONE', value: 1, meaning: 'A result has been produced and the context is completed.' },
|
|
18
|
+
{ code: 'STEP_EFFECT', value: 2, meaning: 'A host effect was recorded; the context is suspended until host resume.' },
|
|
19
|
+
{ code: 'STEP_EXPIRED', value: 3, meaning: 'The context/effect deadline expired.' }
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const EFFECT_KINDS = [
|
|
23
|
+
{
|
|
24
|
+
kind: 'sleep',
|
|
25
|
+
code: 1,
|
|
26
|
+
capability: 'timer',
|
|
27
|
+
status: 'contract-first-proof-target',
|
|
28
|
+
publicSurface: 'ctx.sleep(ms)',
|
|
29
|
+
provider: { kind: 'host-scheduler', name: 'pulse-host-scheduler' },
|
|
30
|
+
preferredProvider: { kind: 'wasi-provider', name: 'wasi:clocks', clock: 'monotonic-clock' },
|
|
31
|
+
hostOwned: true,
|
|
32
|
+
explicitResume: true,
|
|
33
|
+
payload: { ms: 'positive bounded integer duration in milliseconds' },
|
|
34
|
+
notes: 'Sleep is the smallest effect used to prove suspend/resume, deadlines, and stale-resume rejection.'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
kind: 'backend-fetch',
|
|
38
|
+
code: 2,
|
|
39
|
+
capability: 'backend-fetch',
|
|
40
|
+
status: 'reserved-effect-runtime-required',
|
|
41
|
+
publicSurface: 'ctx.fetch("backendKey", requestSpec)',
|
|
42
|
+
provider: { kind: 'host-effect', name: 'pulse-backend-fetch-effect' },
|
|
43
|
+
providerCandidates: [{ kind: 'wasi-provider-candidate', name: 'wasi:http' }],
|
|
44
|
+
hostOwned: true,
|
|
45
|
+
explicitResume: true,
|
|
46
|
+
payload: { backend: 'declared backend key', request: 'static request spec / requestRef' },
|
|
47
|
+
notes: 'Outbound fetch remains unsupported in Wasm mode until the effect/resume runtime is implemented.'
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
kind: 'body-read',
|
|
51
|
+
code: 4,
|
|
52
|
+
capability: 'body',
|
|
53
|
+
status: 'contract-implemented-lazy-text-effect-compatible',
|
|
54
|
+
publicSurface: 'pulse_request_body_text(ctx) / future explicit body read effect',
|
|
55
|
+
provider: { kind: 'host-runtime', name: 'pulse-body-adaptor' },
|
|
56
|
+
hostOwned: true,
|
|
57
|
+
explicitResume: true,
|
|
58
|
+
payload: { mode: 'text | json', maxBytes: 'bounded by JSON/body contract when applicable' },
|
|
59
|
+
notes: 'Body is explicit/lazy. Existing text body seeding remains valid; effect form is the future async/lazy extension.'
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const DIAGNOSTICS = {
|
|
64
|
+
contextTimeout: {
|
|
65
|
+
code: 'PULSEWASM_CONTEXT_TIMEOUT',
|
|
66
|
+
message: 'PulseWasm context deadline expired.',
|
|
67
|
+
statusCode: 504
|
|
68
|
+
},
|
|
69
|
+
effectTimeout: {
|
|
70
|
+
code: 'PULSEWASM_EFFECT_TIMEOUT',
|
|
71
|
+
message: 'PulseWasm host effect deadline expired.',
|
|
72
|
+
statusCode: 504
|
|
73
|
+
},
|
|
74
|
+
requestTimeout: {
|
|
75
|
+
code: 'PULSEWASM_REQUEST_TIMEOUT',
|
|
76
|
+
message: 'Request body/client deadline expired.',
|
|
77
|
+
statusCode: 408
|
|
78
|
+
},
|
|
79
|
+
staleResume: {
|
|
80
|
+
code: 'PULSEWASM_STALE_EFFECT_RESUME',
|
|
81
|
+
message: 'Host attempted to resume an expired, cleaned, or generation-mismatched PulseWasm effect.',
|
|
82
|
+
statusCode: 500
|
|
83
|
+
},
|
|
84
|
+
effectUnsupported: {
|
|
85
|
+
code: 'PULSEWASM_EFFECT_RUNTIME_UNSUPPORTED',
|
|
86
|
+
message: 'The requested PulseWasm effect requires an effect runtime that is not enabled.',
|
|
87
|
+
statusCode: 500
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
function sortedUnique(values) {
|
|
92
|
+
return Array.from(new Set((values || []).filter(Boolean))).sort();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function makeDiagnostic(code, message, hint, details) {
|
|
96
|
+
return normalizeDiagnostic({
|
|
97
|
+
phase: 'effect-runtime',
|
|
98
|
+
severity: 'error',
|
|
99
|
+
code,
|
|
100
|
+
message,
|
|
101
|
+
hint,
|
|
102
|
+
details,
|
|
103
|
+
loc: { file: '<effect-runtime>' }
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function requiredCapabilitiesFromHostCapabilities(hostCapabilities) {
|
|
108
|
+
const fromArtifact = hostCapabilities?.artifact?.requiredCapabilities || hostCapabilities?.requiredCapabilities || [];
|
|
109
|
+
const fromReport = hostCapabilities?.capabilityProviderReport?.capabilities
|
|
110
|
+
?.filter((capability) => capability.requiredByCurrentArtifacts)
|
|
111
|
+
?.map((capability) => capability.capability) || [];
|
|
112
|
+
return sortedUnique([...fromArtifact, ...fromReport]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildEffectRuntimeContract({ generatedBy, requiredCapabilities }) {
|
|
116
|
+
return {
|
|
117
|
+
version: EFFECT_RUNTIME_CONTRACT_VERSION,
|
|
118
|
+
generatedBy,
|
|
119
|
+
phase: PHASE,
|
|
120
|
+
status: 'locked',
|
|
121
|
+
scope: {
|
|
122
|
+
contractOnly: true,
|
|
123
|
+
runtimeImplemented: false,
|
|
124
|
+
sleepImplemented: false,
|
|
125
|
+
fetchImplemented: false,
|
|
126
|
+
assetsImplemented: false,
|
|
127
|
+
bodyReadEffectImplemented: false,
|
|
128
|
+
languageAsyncImplemented: false,
|
|
129
|
+
promisesImplemented: false
|
|
130
|
+
},
|
|
131
|
+
policy: {
|
|
132
|
+
explicitEffectsOnly: true,
|
|
133
|
+
languageLevelAsync: false,
|
|
134
|
+
asyncAwaitAllowed: false,
|
|
135
|
+
promiseHandlersAllowed: false,
|
|
136
|
+
hiddenSuspension: false,
|
|
137
|
+
hostOwnedScheduling: true,
|
|
138
|
+
monotonicClockForDeadlines: true,
|
|
139
|
+
wallClockForDeadlines: false,
|
|
140
|
+
cpuPreemptionV1: false,
|
|
141
|
+
deadlinesEnforcedAtRuntimeAndEffectBoundaries: true,
|
|
142
|
+
loopsRemainRejected: true,
|
|
143
|
+
arbitraryTimersRejected: true,
|
|
144
|
+
noUserTimerQueue: true
|
|
145
|
+
},
|
|
146
|
+
contextStates: CONTEXT_STATES,
|
|
147
|
+
effectStates: EFFECT_STATES,
|
|
148
|
+
stepResults: STEP_RESULTS,
|
|
149
|
+
requiredCapabilities,
|
|
150
|
+
diagnostics: []
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function buildEffectKindRegistry({ generatedBy, requiredCapabilities }) {
|
|
155
|
+
const requiredSet = new Set(requiredCapabilities || []);
|
|
156
|
+
return {
|
|
157
|
+
version: EFFECT_KIND_REGISTRY_VERSION,
|
|
158
|
+
generatedBy,
|
|
159
|
+
phase: PHASE,
|
|
160
|
+
status: 'locked',
|
|
161
|
+
policy: {
|
|
162
|
+
sleepIsFirstProofEffect: true,
|
|
163
|
+
effectKindsAreClosedForV1Contract: true,
|
|
164
|
+
addingEffectRequiresContractUpdate: true,
|
|
165
|
+
effectsAreNotPromises: true
|
|
166
|
+
},
|
|
167
|
+
summary: {
|
|
168
|
+
effectKinds: EFFECT_KINDS.length,
|
|
169
|
+
requiredByCurrentArtifacts: EFFECT_KINDS.filter((effect) => requiredSet.has(effect.capability)).length,
|
|
170
|
+
firstProofTarget: 'sleep',
|
|
171
|
+
fetchReserved: true,
|
|
172
|
+
assetsExcludedFromV1EffectKinds: true,
|
|
173
|
+
streamingBinaryReserved: true,
|
|
174
|
+
bodyReadEffectReserved: true
|
|
175
|
+
},
|
|
176
|
+
effects: EFFECT_KINDS.map((effect) => ({
|
|
177
|
+
...effect,
|
|
178
|
+
requiredByCurrentArtifacts: requiredSet.has(effect.capability)
|
|
179
|
+
}))
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildEffectResumeProtocol({ generatedBy }) {
|
|
184
|
+
return {
|
|
185
|
+
version: EFFECT_RESUME_PROTOCOL_VERSION,
|
|
186
|
+
generatedBy,
|
|
187
|
+
phase: PHASE,
|
|
188
|
+
status: 'locked',
|
|
189
|
+
resumeToken: {
|
|
190
|
+
fields: [
|
|
191
|
+
{ name: 'ctxId', type: 'string | i64', required: true },
|
|
192
|
+
{ name: 'effectId', type: 'string | i64', required: true },
|
|
193
|
+
{ name: 'generation', type: 'i32', required: true },
|
|
194
|
+
{ name: 'effectKind', type: 'EffectKindCode', required: true },
|
|
195
|
+
{ name: 'resumeEntryIndex', type: 'i32', required: true },
|
|
196
|
+
{ name: 'deadlineAtMonotonicMs', type: 'i64', required: true }
|
|
197
|
+
],
|
|
198
|
+
opaqueToUserHandlers: true,
|
|
199
|
+
hostVisible: true
|
|
200
|
+
},
|
|
201
|
+
pulseFrameStack: {
|
|
202
|
+
model: 'runtime-owned Pulse execution frame stack, not the Wasm call stack',
|
|
203
|
+
frameKinds: ['entry', 'mount', 'effect'],
|
|
204
|
+
wasmCallStackCaptured: false,
|
|
205
|
+
continuationIsTableBacked: true
|
|
206
|
+
},
|
|
207
|
+
resumeRules: [
|
|
208
|
+
'context must still exist',
|
|
209
|
+
'context status must be suspended or resuming',
|
|
210
|
+
'resume token generation must match current context generation',
|
|
211
|
+
'effect must still be pending',
|
|
212
|
+
'effect deadline must not be expired',
|
|
213
|
+
'stale resumes are rejected with PULSEWASM_STALE_EFFECT_RESUME'
|
|
214
|
+
],
|
|
215
|
+
hostEntryPoints: {
|
|
216
|
+
reserved: [
|
|
217
|
+
'pulse_resume_effect(ctxRef, effectId, resultRef)',
|
|
218
|
+
'pulse_resume_effect_error(ctxRef, effectId, errorRef)',
|
|
219
|
+
'pulse_cancel_effect(ctxRef, effectId)'
|
|
220
|
+
],
|
|
221
|
+
implementedIn11F: false
|
|
222
|
+
},
|
|
223
|
+
diagnostics: DIAGNOSTICS
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function buildEffectTimeoutPolicy({ generatedBy }) {
|
|
228
|
+
return {
|
|
229
|
+
version: EFFECT_TIMEOUT_POLICY_VERSION,
|
|
230
|
+
generatedBy,
|
|
231
|
+
phase: PHASE,
|
|
232
|
+
status: 'locked',
|
|
233
|
+
defaults: {
|
|
234
|
+
defaultTimeoutMs: 5000,
|
|
235
|
+
hardTimeoutMs: 30000,
|
|
236
|
+
defaultEffectTimeoutMs: 5000,
|
|
237
|
+
schedulerResolutionMs: 10
|
|
238
|
+
},
|
|
239
|
+
policy: {
|
|
240
|
+
hardDeadlineCannotBeExtended: true,
|
|
241
|
+
contextTimeoutStatusCode: 504,
|
|
242
|
+
effectTimeoutStatusCode: 504,
|
|
243
|
+
requestBodyClientTimeoutStatusCode: 408,
|
|
244
|
+
normalFallthroughStatusCode: 404,
|
|
245
|
+
contractViolationStatusCode: 500,
|
|
246
|
+
clockSource: 'monotonic',
|
|
247
|
+
wallClockForDeadlines: false,
|
|
248
|
+
deadlineChecks: ['before effect record', 'before suspend', 'on host resume', 'between runtime steps'],
|
|
249
|
+
cpuPreemption: false
|
|
250
|
+
},
|
|
251
|
+
errors: {
|
|
252
|
+
contextTimeout: DIAGNOSTICS.contextTimeout,
|
|
253
|
+
effectTimeout: DIAGNOSTICS.effectTimeout,
|
|
254
|
+
requestTimeout: DIAGNOSTICS.requestTimeout,
|
|
255
|
+
staleResume: DIAGNOSTICS.staleResume
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function markdownForEffectRuntime(artifact, contract, registry, resumeProtocol, timeoutPolicy) {
|
|
261
|
+
const lines = [];
|
|
262
|
+
lines.push('# PulseWasm Phase 11F Effect Runtime Contract');
|
|
263
|
+
lines.push('');
|
|
264
|
+
lines.push('## Status');
|
|
265
|
+
lines.push('Locked as a contract/artifact phase. No effect execution, language-level async, promises, or platform scheduling is implemented here.');
|
|
266
|
+
lines.push('');
|
|
267
|
+
lines.push('## Core Rule');
|
|
268
|
+
lines.push('PulseWasm async is explicit host effects with continuation/resume, not `async`/`await`, promises, hidden stack suspension, or arbitrary timers.');
|
|
269
|
+
lines.push('');
|
|
270
|
+
lines.push('## Summary');
|
|
271
|
+
lines.push('');
|
|
272
|
+
lines.push(`- effect kinds: ${registry.summary.effectKinds}`);
|
|
273
|
+
lines.push(`- first proof target: ${registry.summary.firstProofTarget}`);
|
|
274
|
+
lines.push(`- context states: ${contract.contextStates.join(', ')}`);
|
|
275
|
+
lines.push(`- default timeout: ${timeoutPolicy.defaults.defaultTimeoutMs}ms`);
|
|
276
|
+
lines.push(`- hard timeout: ${timeoutPolicy.defaults.hardTimeoutMs}ms`);
|
|
277
|
+
lines.push(`- diagnostics: ${artifact.summary.diagnostics}`);
|
|
278
|
+
lines.push('');
|
|
279
|
+
lines.push('## Effect Kinds');
|
|
280
|
+
lines.push('');
|
|
281
|
+
for (const effect of registry.effects) {
|
|
282
|
+
lines.push(`- \`${effect.kind}\` — ${effect.status}; capability: \`${effect.capability}\`; surface: ${effect.publicSurface}.`);
|
|
283
|
+
}
|
|
284
|
+
lines.push('');
|
|
285
|
+
lines.push('## Resume Protocol');
|
|
286
|
+
lines.push('');
|
|
287
|
+
lines.push('Resume tokens include context id, effect id, generation, effect kind, resume entry index, and monotonic deadline. Stale resumes are rejected.');
|
|
288
|
+
lines.push('');
|
|
289
|
+
lines.push('## Timeout Policy');
|
|
290
|
+
lines.push('');
|
|
291
|
+
lines.push('- context/effect timeout => 504');
|
|
292
|
+
lines.push('- request/client body timeout => 408');
|
|
293
|
+
lines.push('- normal fallthrough remains 404');
|
|
294
|
+
lines.push('- contract violation remains 500');
|
|
295
|
+
lines.push('- CPU preemption is not part of v1; loop/long-running syntax remains rejected.');
|
|
296
|
+
lines.push('');
|
|
297
|
+
lines.push('## Non-goals');
|
|
298
|
+
lines.push('');
|
|
299
|
+
lines.push('- no effect runtime execution');
|
|
300
|
+
lines.push('- no sleep implementation');
|
|
301
|
+
lines.push('- no backend fetch execution');
|
|
302
|
+
lines.push('- no asset read execution (assets are reserved host capability/payload surface, not a v1 effect kind)');
|
|
303
|
+
lines.push('- no language-level async or Promise handlers');
|
|
304
|
+
lines.push('- no platform adapter');
|
|
305
|
+
lines.push('- no WIT definition');
|
|
306
|
+
lines.push('');
|
|
307
|
+
return `${lines.join('\n')}\n`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function buildEffectRuntime(inputs = {}) {
|
|
311
|
+
const cwd = inputs.cwd || process.cwd();
|
|
312
|
+
const generatedBy = inputs.generatedBy || PACKAGE_VERSION;
|
|
313
|
+
const diagnostics = [];
|
|
314
|
+
const requiredCapabilities = requiredCapabilitiesFromHostCapabilities(inputs.hostCapabilities);
|
|
315
|
+
const knownEffectCapabilities = new Set(EFFECT_KINDS.map((effect) => effect.capability));
|
|
316
|
+
for (const capability of ['timer', 'backend-fetch']) {
|
|
317
|
+
if (requiredCapabilities.includes(capability) && !knownEffectCapabilities.has(capability)) {
|
|
318
|
+
diagnostics.push(makeDiagnostic(
|
|
319
|
+
'PULSEWASM_EFFECT_CAPABILITY_UNMAPPED',
|
|
320
|
+
`Capability ${JSON.stringify(capability)} requires an effect runtime but has no Phase 11F effect mapping.`,
|
|
321
|
+
'Add an effect kind mapping before using this capability in optimized Wasm mode.',
|
|
322
|
+
{ capability }
|
|
323
|
+
));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const effectRuntimeContract = normalizeArtifact(buildEffectRuntimeContract({ generatedBy, requiredCapabilities }), cwd);
|
|
328
|
+
const effectKindRegistry = normalizeArtifact(buildEffectKindRegistry({ generatedBy, requiredCapabilities }), cwd);
|
|
329
|
+
const effectResumeProtocol = normalizeArtifact(buildEffectResumeProtocol({ generatedBy }), cwd);
|
|
330
|
+
const effectTimeoutPolicy = normalizeArtifact(buildEffectTimeoutPolicy({ generatedBy }), cwd);
|
|
331
|
+
|
|
332
|
+
const effectRuntimeCapabilities = sortedUnique(EFFECT_KINDS.map((effect) => effect.capability));
|
|
333
|
+
const requiredEffectCapabilities = sortedUnique(requiredCapabilities.filter((capability) => effectRuntimeCapabilities.includes(capability)));
|
|
334
|
+
const artifact = normalizeArtifact({
|
|
335
|
+
version: EFFECT_RUNTIME_VERSION,
|
|
336
|
+
generatedBy,
|
|
337
|
+
phase: PHASE,
|
|
338
|
+
status: diagnostics.length === 0 ? 'ok' : 'error',
|
|
339
|
+
scope: {
|
|
340
|
+
semanticsChanged: false,
|
|
341
|
+
runtimeBehaviorChanged: false,
|
|
342
|
+
contractOnly: true,
|
|
343
|
+
effectRuntimeImplemented: false,
|
|
344
|
+
sleepImplemented: false,
|
|
345
|
+
backendFetchImplemented: false,
|
|
346
|
+
assetsAreEffectKind: false,
|
|
347
|
+
assetReadImplemented: false,
|
|
348
|
+
bodyReadEffectImplemented: false,
|
|
349
|
+
platformAdapterImplemented: false,
|
|
350
|
+
witDefined: false,
|
|
351
|
+
languageAsyncImplemented: false
|
|
352
|
+
},
|
|
353
|
+
policy: {
|
|
354
|
+
explicitEffects: true,
|
|
355
|
+
hostOwnedScheduling: true,
|
|
356
|
+
monotonicDeadlines: true,
|
|
357
|
+
resumeTokens: true,
|
|
358
|
+
staleResumeRejected: true,
|
|
359
|
+
pulseExecutionFrameStack: true,
|
|
360
|
+
wasmCallStackCaptured: false,
|
|
361
|
+
asyncAwait: false,
|
|
362
|
+
promises: false,
|
|
363
|
+
hiddenSuspension: false,
|
|
364
|
+
cpuPreemptionV1: false,
|
|
365
|
+
sleepFirstProofTarget: true,
|
|
366
|
+
assetsAreNotV1EffectKind: true,
|
|
367
|
+
assetsUseHostCapabilityAndFuturePayloadStreamingSurface: true,
|
|
368
|
+
stackSwitchingWatchItem: true
|
|
369
|
+
},
|
|
370
|
+
summary: {
|
|
371
|
+
effectKinds: EFFECT_KINDS.length,
|
|
372
|
+
requiredEffectCapabilities: requiredEffectCapabilities.length,
|
|
373
|
+
contextStates: CONTEXT_STATES.length,
|
|
374
|
+
effectStates: EFFECT_STATES.length,
|
|
375
|
+
stepResults: STEP_RESULTS.length,
|
|
376
|
+
diagnostics: diagnostics.length,
|
|
377
|
+
firstProofTarget: 'sleep',
|
|
378
|
+
readyFor12A: diagnostics.length === 0,
|
|
379
|
+
readyForEffectExecution: false,
|
|
380
|
+
readyForFastly: false
|
|
381
|
+
},
|
|
382
|
+
requiredCapabilities,
|
|
383
|
+
requiredEffectCapabilities,
|
|
384
|
+
diagnostics
|
|
385
|
+
}, cwd);
|
|
386
|
+
|
|
387
|
+
const markdown = markdownForEffectRuntime(artifact, effectRuntimeContract, effectKindRegistry, effectResumeProtocol, effectTimeoutPolicy);
|
|
388
|
+
|
|
389
|
+
return {
|
|
390
|
+
artifact,
|
|
391
|
+
effectRuntimeContract,
|
|
392
|
+
effectKindRegistry,
|
|
393
|
+
effectResumeProtocol,
|
|
394
|
+
effectTimeoutPolicy,
|
|
395
|
+
diagnostics,
|
|
396
|
+
files: [
|
|
397
|
+
{ file: 'generated/host/effect-runtime.md', text: markdown }
|
|
398
|
+
]
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
module.exports = {
|
|
403
|
+
EFFECT_RUNTIME_VERSION,
|
|
404
|
+
EFFECT_RUNTIME_CONTRACT_VERSION,
|
|
405
|
+
EFFECT_KIND_REGISTRY_VERSION,
|
|
406
|
+
EFFECT_RESUME_PROTOCOL_VERSION,
|
|
407
|
+
EFFECT_TIMEOUT_POLICY_VERSION,
|
|
408
|
+
EFFECT_KINDS,
|
|
409
|
+
CONTEXT_STATES,
|
|
410
|
+
EFFECT_STATES,
|
|
411
|
+
STEP_RESULTS,
|
|
412
|
+
DIAGNOSTICS,
|
|
413
|
+
buildEffectRuntime,
|
|
414
|
+
buildEffectRuntimeContract,
|
|
415
|
+
buildEffectKindRegistry,
|
|
416
|
+
buildEffectResumeProtocol,
|
|
417
|
+
buildEffectTimeoutPolicy
|
|
418
|
+
};
|