@pulse-compute/cli 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/API.md +572 -0
- package/CHANGELOG.md +71 -0
- package/README.md +71 -1
- package/bin/pulse.js +15 -0
- package/bin/pulsewasm-extract.js +22 -0
- package/cli-spec.json +575 -0
- package/completions/_pulse +106 -0
- package/completions/pulse.bash +31 -0
- package/completions/pulse.fish +76 -0
- package/docs/README.md +77 -0
- package/docs/architecture/current-contracts.md +470 -0
- package/docs/architecture/overview.md +93 -0
- package/docs/architecture/vision.md +515 -0
- package/docs/concepts/bodies.md +186 -0
- package/docs/concepts/compilation-and-lowering.md +496 -0
- package/docs/concepts/contracts-and-providers.md +158 -0
- package/docs/concepts/effects-and-continuations.md +300 -0
- package/docs/concepts/entities-and-adapters.md +71 -0
- package/docs/concepts/package-owned-lowering.md +175 -0
- package/docs/concepts/targets-and-hosts.md +70 -0
- package/docs/contributing/README.md +38 -0
- package/docs/contributing/adding-core-provider.md +315 -0
- package/docs/contributing/adding-first-party-lowerer.md +327 -0
- package/docs/contributing/entities-lowering.md +91 -0
- package/docs/contributing/package-lowerer-contract.md +383 -0
- package/docs/contributing/pulse-aware-packages.md +149 -0
- package/docs/examples.md +112 -0
- package/docs/fixtures/inspect-fetch-composition.selected.json +181 -0
- package/docs/getting-started.md +128 -0
- package/docs/guides/compatibility-imports.md +60 -0
- package/docs/guides/deploying-fastly.md +188 -0
- package/docs/guides/deploying-node.md +143 -0
- package/docs/guides/events.md +233 -0
- package/docs/guides/fastly-capabilities.md +153 -0
- package/docs/guides/fetching-and-composition.md +101 -0
- package/docs/guides/grip.md +94 -0
- package/docs/guides/json-schemas.md +233 -0
- package/docs/guides/migrating-from-express.md +192 -0
- package/docs/guides/project-lifecycle.md +143 -0
- package/docs/guides/routing.md +202 -0
- package/docs/guides/troubleshooting.md +47 -0
- package/docs/maintainers/README.md +60 -0
- package/docs/maintainers/codex-maintainer.md +71 -0
- package/docs/maintainers/documentation-deployment.md +147 -0
- package/docs/maintainers/documentation-system.md +58 -0
- package/docs/maintainers/documentation-versioning.md +65 -0
- package/docs/maintainers/maintainer-charter.md +100 -0
- package/docs/maintainers/maintenance-policy.json +809 -0
- package/docs/maintainers/maintenance-policy.md +124 -0
- package/docs/maintainers/npm-publishing.md +154 -0
- package/docs/maintainers/plugin-readiness.json +19 -0
- package/docs/maintainers/plugin-readiness.md +31 -0
- package/docs/maintainers/public-site.md +158 -0
- package/docs/maintainers/release-acceptance.md +293 -0
- package/docs/maintainers/release-manifest.md +89 -0
- package/docs/maintainers/repository-setup.md +145 -0
- package/docs/maintainers/scope-policy.md +105 -0
- package/docs/maintainers/support-and-triage.md +74 -0
- package/docs/maintainers/testing.md +334 -0
- package/docs/packages/README.md +60 -0
- package/docs/packages/assets.md +85 -0
- package/docs/packages/cli.md +190 -0
- package/docs/packages/crypto.md +78 -0
- package/docs/packages/entities.md +129 -0
- package/docs/packages/grip.md +82 -0
- package/docs/packages/implementation-packages.md +122 -0
- package/docs/packages/jwt.md +55 -0
- package/docs/packages/provider-fastly.md +243 -0
- package/docs/packages/pulse.md +159 -0
- package/docs/packages/runtime.md +265 -0
- package/docs/packages/s3.md +101 -0
- package/docs/preview-scope.md +142 -0
- package/docs/reference/README.md +33 -0
- package/docs/reference/cli-spec.json +575 -0
- package/docs/reference/cli.md +457 -0
- package/docs/reference/compatibility-matrix.md +169 -0
- package/docs/reference/diagnostics.md +1872 -0
- package/docs/reference/documentation-versions.json +22 -0
- package/docs/reference/environment.md +347 -0
- package/docs/reference/handler-authoring.md +264 -0
- package/docs/reference/project-config.md +582 -0
- package/docs/reference/project-config.schema.json +981 -0
- package/docs/reference/release-manifest.json +441 -0
- package/docs/reference/shell-completion.md +23 -0
- package/documentation-site.json +668 -0
- package/documentation-versions.json +22 -0
- package/examples/01-hello-json/.pulse/.gitignore +3 -0
- package/examples/01-hello-json/.pulse/config.ts +16 -0
- package/examples/01-hello-json/README.md +119 -0
- package/examples/01-hello-json/package.json +20 -0
- package/examples/01-hello-json/src/index.ts +9 -0
- package/examples/01-hello-json/tests/pulse.harness.ts +22 -0
- package/examples/01-hello-json/tsconfig.json +14 -0
- package/examples/02-request-schema/.pulse/.gitignore +3 -0
- package/examples/02-request-schema/.pulse/config.ts +17 -0
- package/examples/02-request-schema/README.md +145 -0
- package/examples/02-request-schema/package.json +20 -0
- package/examples/02-request-schema/src/index.ts +18 -0
- package/examples/02-request-schema/src/schemas.ts +20 -0
- package/examples/02-request-schema/tests/pulse.harness.ts +37 -0
- package/examples/02-request-schema/tsconfig.json +14 -0
- package/examples/03-fetch-composition/.pulse/.gitignore +3 -0
- package/examples/03-fetch-composition/.pulse/config.ts +31 -0
- package/examples/03-fetch-composition/README.md +210 -0
- package/examples/03-fetch-composition/package.json +20 -0
- package/examples/03-fetch-composition/src/index.ts +60 -0
- package/examples/03-fetch-composition/tests/pulse.harness.ts +47 -0
- package/examples/03-fetch-composition/tsconfig.json +14 -0
- package/examples/05-fastly-capabilities/.pulse/.gitignore +3 -0
- package/examples/05-fastly-capabilities/.pulse/config.ts +57 -0
- package/examples/05-fastly-capabilities/README.md +257 -0
- package/examples/05-fastly-capabilities/package.json +22 -0
- package/examples/05-fastly-capabilities/src/index.ts +55 -0
- package/examples/05-fastly-capabilities/tests/pulse.harness.ts +66 -0
- package/examples/05-fastly-capabilities/tsconfig.json +14 -0
- package/examples/07-opaque-proxy/.pulse/.gitignore +3 -0
- package/examples/07-opaque-proxy/.pulse/config.ts +38 -0
- package/examples/07-opaque-proxy/README.md +150 -0
- package/examples/07-opaque-proxy/package.json +21 -0
- package/examples/07-opaque-proxy/src/index.ts +9 -0
- package/examples/07-opaque-proxy/tests/pulse.harness.ts +25 -0
- package/examples/07-opaque-proxy/tsconfig.json +14 -0
- package/examples/09-router-lowering/.pulse/.gitignore +3 -0
- package/examples/09-router-lowering/.pulse/config.ts +22 -0
- package/examples/09-router-lowering/README.md +287 -0
- package/examples/09-router-lowering/package.json +22 -0
- package/examples/09-router-lowering/src/index.ts +65 -0
- package/examples/09-router-lowering/tests/pulse.harness.ts +91 -0
- package/examples/09-router-lowering/tsconfig.json +14 -0
- package/examples/10-entities-tools/.pulse/.gitignore +4 -0
- package/examples/10-entities-tools/.pulse/config.ts +23 -0
- package/examples/10-entities-tools/README.md +165 -0
- package/examples/10-entities-tools/package.json +21 -0
- package/examples/10-entities-tools/src/handlers.ts +15 -0
- package/examples/10-entities-tools/src/index.ts +31 -0
- package/examples/10-entities-tools/src/schemas.ts +18 -0
- package/examples/10-entities-tools/tests/pulse.harness.ts +40 -0
- package/examples/10-entities-tools/tools-facade.cjs +158 -0
- package/examples/10-entities-tools/tsconfig.json +14 -0
- package/examples/11-events/.pulse/.gitignore +4 -0
- package/examples/11-events/.pulse/config.ts +24 -0
- package/examples/11-events/README.md +194 -0
- package/examples/11-events/package.json +20 -0
- package/examples/11-events/src/index.ts +27 -0
- package/examples/11-events/src/schemas.ts +19 -0
- package/examples/11-events/tests/pulse.harness.ts +34 -0
- package/examples/11-events/tsconfig.json +15 -0
- package/examples/12-mcp-proxy/.pulse/.gitignore +3 -0
- package/examples/12-mcp-proxy/.pulse/config.ts +25 -0
- package/examples/12-mcp-proxy/README.md +149 -0
- package/examples/12-mcp-proxy/package.json +20 -0
- package/examples/12-mcp-proxy/src/index.ts +17 -0
- package/examples/12-mcp-proxy/tests/pulse.harness.ts +29 -0
- package/examples/12-mcp-proxy/tsconfig.json +14 -0
- package/examples/13-jwt-es256/.pulse/config.ts +19 -0
- package/examples/13-jwt-es256/README.md +195 -0
- package/examples/13-jwt-es256/package.json +21 -0
- package/examples/13-jwt-es256/src/index.ts +21 -0
- package/examples/13-jwt-es256/tests/pulse.harness.ts +54 -0
- package/examples/13-jwt-es256/tsconfig.json +14 -0
- package/examples/README.md +36 -0
- package/package.json +66 -6
- package/project-config.schema.json +981 -0
- package/release-manifest.json +441 -0
- package/src/command-spec.js +279 -0
- package/src/completion.js +113 -0
- package/src/diagnostics.js +350 -0
- package/src/documentation.js +45 -0
- package/src/index.d.ts +133 -0
- package/src/index.js +15 -0
- package/src/internal/command-executor.d.ts +29 -0
- package/src/internal/command-executor.js +143 -0
- package/src/internal/command-plan.d.ts +9 -0
- package/src/internal/command-plan.js +73 -0
- package/src/internal/command-reporter.d.ts +15 -0
- package/src/internal/command-reporter.js +133 -0
- package/src/internal/command-request.d.ts +35 -0
- package/src/internal/command-request.js +154 -0
- package/src/internal/node-http.js +54 -0
- package/src/internal/project-context.d.ts +66 -0
- package/src/internal/project-context.js +175 -0
- package/src/project-config-reference.js +4 -0
- package/src/project-config-schema.d.ts +23 -0
- package/src/project-config-schema.js +271 -0
- package/src/project-config.js +724 -0
- package/src/project-execution.js +2946 -0
- package/src/provider-drivers.js +3 -0
- package/src/target-support.js +3 -0
- package/src/typescript-module-loader.js +269 -0
- package/src/workflow.js +78 -0
- package/src/workspace.js +82 -0
package/docs/examples.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Canonical examples
|
|
2
|
+
|
|
3
|
+
Every top-level example is a complete Pulse project with a handler, config,
|
|
4
|
+
tests, TypeScript config, and package metadata. The executable documentation
|
|
5
|
+
lane runs every example except 10 through `doctor`, `inspect`, `test`, and
|
|
6
|
+
`build`; it also starts the hello project with `dev`, sends a request, and
|
|
7
|
+
verifies shutdown. Example 10 uses its focused orchestration proof while
|
|
8
|
+
ordinary package-loader and Native-intrinsic integration remain candidate
|
|
9
|
+
blockers.
|
|
10
|
+
|
|
11
|
+
| Example | Demonstrates |
|
|
12
|
+
|---|---|
|
|
13
|
+
| [`01-hello-json`](../examples/01-hello-json/) | Request branching and JSON/text responses. |
|
|
14
|
+
| [`02-request-schema`](../examples/02-request-schema/) | Explicit request and response schemas. |
|
|
15
|
+
| [`03-fetch-composition`](../examples/03-fetch-composition/) | One fetch, sequential composition, and explicit `ctx.parallel` concurrency. |
|
|
16
|
+
| [`05-fastly-capabilities`](../examples/05-fastly-capabilities/) | Config, secrets, KV, a named backend, and package-root GRIP broadcast. |
|
|
17
|
+
| [`07-opaque-proxy`](../examples/07-opaque-proxy/) | Direct binary/stream pass-through without body inspection. |
|
|
18
|
+
| [`09-router-lowering`](../examples/09-router-lowering/) | Mounted routes, scoped terminal middleware, fallthrough, error transfer, parameters, wildcards, and entry-aware effects. |
|
|
19
|
+
| [`10-entities-tools`](../examples/10-entities-tools/) | Experimental schema-bound entities, deterministic catalog discovery, JSON-RPC dispatch, and an external tools facade. |
|
|
20
|
+
| [`11-events`](../examples/11-events/) | Static event ingress, schema/no-payload frames, exact outbound acceptance, and separate HTTP/event entries. |
|
|
21
|
+
| [`12-mcp-proxy`](../examples/12-mcp-proxy/) | A bounded JSON-RPC request seam and opaque upstream response pass-through. |
|
|
22
|
+
| [`13-jwt-es256`](../examples/13-jwt-es256/) | ES256 bearer verification with an explicit guest-linked Native realization. |
|
|
23
|
+
|
|
24
|
+
## Wasm size at a glance
|
|
25
|
+
|
|
26
|
+
The Native rows compare the ordinary build with
|
|
27
|
+
`pulse build --experimental-native-size`. Values are uncompressed on-disk
|
|
28
|
+
sizes; each example page includes exact byte counts.
|
|
29
|
+
|
|
30
|
+
| Example | Default Native Wasm | Size-optimized Native Wasm | Reduction | Deployable Fastly module |
|
|
31
|
+
|---|---:|---:|---:|---:|
|
|
32
|
+
| `01-hello-json` | 2.2 KiB | 2.0 KiB | 7.0% | — |
|
|
33
|
+
| `02-request-schema` | 38.9 KiB | 30.8 KiB | 20.6% | — |
|
|
34
|
+
| `03-fetch-composition` | 5.0 KiB | 4.2 KiB | 15.0% | — |
|
|
35
|
+
| `05-fastly-capabilities` | 5.3 KiB | 4.8 KiB | 10.4% | 40.4 → 33.7 KiB |
|
|
36
|
+
| `07-opaque-proxy` | 2.1 KiB | 2.1 KiB | 4.5% | 28.9 → 25.3 KiB |
|
|
37
|
+
| `09-router-lowering` | 6.1 KiB | 5.4 KiB | 12.4% | — |
|
|
38
|
+
| `10-entities-tools` | — | — | Not applicable | JavaScript-first candidate |
|
|
39
|
+
| `11-events` | 38.4 KiB | 30.6 KiB | 20.4% | — |
|
|
40
|
+
| `12-mcp-proxy` | 2.5 KiB | 2.4 KiB | 6.6% | — |
|
|
41
|
+
| `13-jwt-es256` | 23.1 KiB | 22.9 KiB | 0.8% | — |
|
|
42
|
+
|
|
43
|
+
Run the normal workflow from any example directory:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pulse doctor
|
|
47
|
+
pulse test
|
|
48
|
+
pulse dev
|
|
49
|
+
pulse build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Use `pulse inspect` when you need to examine the plan; it is not required before
|
|
53
|
+
`build`. Each example README contains exact source-bound handler/config blocks
|
|
54
|
+
and executable evidence selected by the docs lane. Every page also records the
|
|
55
|
+
default and experimental size-optimized Wasm outputs; Fastly pages separate the
|
|
56
|
+
provider-neutral guest from the deployable module, and the JavaScript-first
|
|
57
|
+
Entities page explicitly records that no comparable application Wasm is
|
|
58
|
+
emitted. The same gate rebuilds and verifies every exact byte count. See
|
|
59
|
+
[Project lifecycle](./guides/project-lifecycle.md).
|
|
60
|
+
|
|
61
|
+
Examples 01, 02, 03, 05, 07, 11, 12, and 13 use current package-root application
|
|
62
|
+
surfaces. Example 09 retains the lower-level Router surface. Example 10 uses
|
|
63
|
+
the synchronized `@pulse-compute/entities` Beta package; executable examples do
|
|
64
|
+
not themselves authorize publication. Example 11 is executable only through
|
|
65
|
+
the Node JavaScript/Native reference adapter. It does not claim a public
|
|
66
|
+
listener, delivery, or Fastly/browser/ESP32 event support; see
|
|
67
|
+
[Static events and outbound emission](./guides/events.md).
|
|
68
|
+
|
|
69
|
+
Example 12 is an MCP-shaped HTTP proxy, not an MCP server. The incoming body is
|
|
70
|
+
materialized once as bounded text because Pulse has no opaque incoming-body
|
|
71
|
+
forwarding contract; the fetched response remains opaque.
|
|
72
|
+
|
|
73
|
+
Example 13 pins the guest-linked ES256 realization for Native. Its harness
|
|
74
|
+
executes valid, invalid-signature, and disallowed-algorithm cases against the
|
|
75
|
+
exact linked artifact; only the public P-256 JWK is included in the example.
|
|
76
|
+
|
|
77
|
+
## Verified native Fastly build
|
|
78
|
+
|
|
79
|
+
This documented build is executed against the config/secret example and must
|
|
80
|
+
produce the configured-provider native Fastly module. The portable compiler
|
|
81
|
+
runs before the exact artifact crosses the provider boundary; the provider
|
|
82
|
+
target receives no compiler service and does not invoke one.
|
|
83
|
+
|
|
84
|
+
<!-- pulse-doc-run {"project":"examples/05-fastly-capabilities","args":["build","--out",".pulse-docs-build","--json"],"timeoutMs":360000} -->
|
|
85
|
+
```bash
|
|
86
|
+
pulse build --out .pulse-docs-build --json
|
|
87
|
+
```
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"status": "built",
|
|
91
|
+
"provider": "fastly",
|
|
92
|
+
"manifest": {
|
|
93
|
+
"providerTarget": {
|
|
94
|
+
"sourceOnly": false,
|
|
95
|
+
"compiledWasmPresent": true,
|
|
96
|
+
"target": "fastly-compute-native",
|
|
97
|
+
"javascriptRuntime": false,
|
|
98
|
+
"compiler": {
|
|
99
|
+
"package": "assemblyscript",
|
|
100
|
+
"version": "0.28.18",
|
|
101
|
+
"invoked": false
|
|
102
|
+
},
|
|
103
|
+
"wasm": {
|
|
104
|
+
"file": "bin/main.wasm",
|
|
105
|
+
"magic": "0061736d01000000"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Fastly configured tests and `pulse dev` use the local-conformance runtime. The separate reality profile delegates execution of the native provider module to `fastly compute serve`.
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "ok",
|
|
3
|
+
"project": {
|
|
4
|
+
"provider": "node",
|
|
5
|
+
"entry": "src/index.ts"
|
|
6
|
+
},
|
|
7
|
+
"compiler": {
|
|
8
|
+
"version": "pulse.canonical-api-compiler.v7",
|
|
9
|
+
"capabilities": [
|
|
10
|
+
"fetch",
|
|
11
|
+
"response.json",
|
|
12
|
+
"response.text"
|
|
13
|
+
],
|
|
14
|
+
"effects": [
|
|
15
|
+
{
|
|
16
|
+
"id": "fetch-1",
|
|
17
|
+
"kind": "fetch",
|
|
18
|
+
"operation": "dispatch",
|
|
19
|
+
"capability": "fetch",
|
|
20
|
+
"resource": {
|
|
21
|
+
"kind": "literal",
|
|
22
|
+
"value": "https://users.example.test/users/123",
|
|
23
|
+
"origin": "https://users.example.test"
|
|
24
|
+
},
|
|
25
|
+
"grouped": false
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": "fetch-2",
|
|
29
|
+
"kind": "fetch",
|
|
30
|
+
"operation": "dispatch",
|
|
31
|
+
"capability": "fetch",
|
|
32
|
+
"resource": {
|
|
33
|
+
"kind": "literal",
|
|
34
|
+
"value": "https://users.example.test/users/123",
|
|
35
|
+
"origin": "https://users.example.test"
|
|
36
|
+
},
|
|
37
|
+
"grouped": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"id": "fetch-3",
|
|
41
|
+
"kind": "fetch",
|
|
42
|
+
"operation": "dispatch",
|
|
43
|
+
"capability": "fetch",
|
|
44
|
+
"resource": {
|
|
45
|
+
"kind": "literal",
|
|
46
|
+
"value": "https://stats.example.test/users/123",
|
|
47
|
+
"origin": "https://stats.example.test"
|
|
48
|
+
},
|
|
49
|
+
"grouped": true
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "fetch-4",
|
|
53
|
+
"kind": "fetch",
|
|
54
|
+
"operation": "dispatch",
|
|
55
|
+
"capability": "fetch",
|
|
56
|
+
"resource": {
|
|
57
|
+
"kind": "literal",
|
|
58
|
+
"value": "https://flags.example.test/users/123",
|
|
59
|
+
"origin": "https://flags.example.test"
|
|
60
|
+
},
|
|
61
|
+
"grouped": true
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": "fetch-5",
|
|
65
|
+
"kind": "fetch",
|
|
66
|
+
"operation": "dispatch",
|
|
67
|
+
"capability": "fetch",
|
|
68
|
+
"resource": {
|
|
69
|
+
"kind": "literal",
|
|
70
|
+
"value": "https://users.example.test/users/123",
|
|
71
|
+
"origin": "https://users.example.test"
|
|
72
|
+
},
|
|
73
|
+
"grouped": true,
|
|
74
|
+
"groupKey": "user"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": "fetch-6",
|
|
78
|
+
"kind": "fetch",
|
|
79
|
+
"operation": "dispatch",
|
|
80
|
+
"capability": "fetch",
|
|
81
|
+
"resource": {
|
|
82
|
+
"kind": "literal",
|
|
83
|
+
"value": "https://stats.example.test/users/123",
|
|
84
|
+
"origin": "https://stats.example.test"
|
|
85
|
+
},
|
|
86
|
+
"grouped": true,
|
|
87
|
+
"groupKey": "stats"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "fetch-7",
|
|
91
|
+
"kind": "fetch",
|
|
92
|
+
"operation": "dispatch",
|
|
93
|
+
"capability": "fetch",
|
|
94
|
+
"resource": {
|
|
95
|
+
"kind": "literal",
|
|
96
|
+
"value": "https://flags.example.test/users/123",
|
|
97
|
+
"origin": "https://flags.example.test"
|
|
98
|
+
},
|
|
99
|
+
"grouped": true,
|
|
100
|
+
"groupKey": "flags"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"continuations": [
|
|
104
|
+
{
|
|
105
|
+
"id": "continuation-1",
|
|
106
|
+
"kind": "single-fetch",
|
|
107
|
+
"effectIds": [
|
|
108
|
+
"fetch-1"
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "continuation-2",
|
|
113
|
+
"kind": "fetch-group",
|
|
114
|
+
"effectIds": [
|
|
115
|
+
"fetch-2",
|
|
116
|
+
"fetch-3",
|
|
117
|
+
"fetch-4"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "continuation-3",
|
|
122
|
+
"kind": "parallel-group",
|
|
123
|
+
"effectIds": [
|
|
124
|
+
"fetch-5",
|
|
125
|
+
"fetch-6",
|
|
126
|
+
"fetch-7"
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"providerLowering": {
|
|
131
|
+
"version": "pulse.canonical-provider-plan.v1",
|
|
132
|
+
"contractVersion": "pulse.canonical-provider-contract.v1",
|
|
133
|
+
"provider": "node",
|
|
134
|
+
"requirements": [
|
|
135
|
+
"fetch",
|
|
136
|
+
"response.json",
|
|
137
|
+
"response.text"
|
|
138
|
+
],
|
|
139
|
+
"operations": [
|
|
140
|
+
{
|
|
141
|
+
"id": "fetch-1",
|
|
142
|
+
"lowering": "node.fetch.dispatch",
|
|
143
|
+
"binding": "https://users.example.test"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"id": "fetch-2",
|
|
147
|
+
"lowering": "node.fetch.dispatch",
|
|
148
|
+
"binding": "https://users.example.test"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"id": "fetch-3",
|
|
152
|
+
"lowering": "node.fetch.dispatch",
|
|
153
|
+
"binding": "https://stats.example.test"
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"id": "fetch-4",
|
|
157
|
+
"lowering": "node.fetch.dispatch",
|
|
158
|
+
"binding": "https://flags.example.test"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"id": "fetch-5",
|
|
162
|
+
"lowering": "node.fetch.dispatch",
|
|
163
|
+
"binding": "https://users.example.test"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"id": "fetch-6",
|
|
167
|
+
"lowering": "node.fetch.dispatch",
|
|
168
|
+
"binding": "https://stats.example.test"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "fetch-7",
|
|
172
|
+
"lowering": "node.fetch.dispatch",
|
|
173
|
+
"binding": "https://flags.example.test"
|
|
174
|
+
}
|
|
175
|
+
],
|
|
176
|
+
"providerSpecificUserland": false,
|
|
177
|
+
"providerSdkUserland": false,
|
|
178
|
+
"capabilityDiscoveryFromUserland": false
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Getting started
|
|
2
|
+
|
|
3
|
+
This page creates and verifies a first project. The normal application journey
|
|
4
|
+
continues through `init → doctor → test → dev → build`; see [Project
|
|
5
|
+
lifecycle](./guides/project-lifecycle.md) for the canonical sequence and the
|
|
6
|
+
optional `inspect` and advanced `compile` branches.
|
|
7
|
+
|
|
8
|
+
## Requirements
|
|
9
|
+
|
|
10
|
+
- Node.js `22.14.0` or newer on the 22.x line, or Node.js 24.x (`^22.14.0 || ^24.0.0`).
|
|
11
|
+
- npm 10 or another npm-compatible package manager.
|
|
12
|
+
- A repository checkout with its lockfile-pinned dependencies restored, using `pnpm pulse -- <command>`, or the synchronized public package set produced by release acceptance.
|
|
13
|
+
- A Fastly local execution engine only when running the external Fastly Compute reality workflow. Native compilation and configured-provider builds do not require one. The gate accepts the Fastly CLI through `PATH`/`PULSE_FASTLY_BIN` or direct Viceroy through `PULSE_VICEROY_BIN`.
|
|
14
|
+
|
|
15
|
+
## Create a project
|
|
16
|
+
|
|
17
|
+
The command and documented result below are executed by the documentation test lane.
|
|
18
|
+
|
|
19
|
+
<!-- pulse-doc-run {"temp":true,"args":["init","hello-pulse","--json"],"display":"pnpm pulse -- init ./hello-pulse --json"} -->
|
|
20
|
+
```bash
|
|
21
|
+
pnpm pulse -- init ./hello-pulse --json
|
|
22
|
+
```
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"status": "initialized",
|
|
26
|
+
"files": [
|
|
27
|
+
".gitignore",
|
|
28
|
+
".pulse/.gitignore",
|
|
29
|
+
".pulse/config.ts",
|
|
30
|
+
"README.md",
|
|
31
|
+
"package.json",
|
|
32
|
+
"src/index.ts",
|
|
33
|
+
"tests/pulse.harness.ts",
|
|
34
|
+
"tsconfig.json"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Then enter the project and install the exact dependencies written by `pulse init`:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
cd ./hello-pulse
|
|
43
|
+
npm install
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`pulse init` never runs a package manager or performs hidden network work.
|
|
47
|
+
|
|
48
|
+
The generated project uses the conventional `.pulse/config.ts` workspace,
|
|
49
|
+
an async `Pulse` application root from `@pulse-compute/pulse`, and a dedicated
|
|
50
|
+
`tests/pulse.harness.ts` case module. The `.pulse/.gitignore` keeps generated
|
|
51
|
+
workspace artifacts out of version control while retaining the project config.
|
|
52
|
+
|
|
53
|
+
## Verify the project
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm run doctor
|
|
57
|
+
npm test
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- `doctor` validates configuration, entry resolution, schema declarations, provider support, output safety, and required toolchains.
|
|
61
|
+
- `test` executes the configured cases through the selected provider’s local runtime.
|
|
62
|
+
|
|
63
|
+
Use `npm run inspect` when you need the capabilities, effects, continuations,
|
|
64
|
+
schemas, target-support decision, or provider lowering required by the handler.
|
|
65
|
+
It is observability, not a required lifecycle stage.
|
|
66
|
+
|
|
67
|
+
## Run locally
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
npm run dev
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`pulse dev` is a foreground server. It watches the handler and schema dependency graph, recompiles on change, and exits when the process receives a normal termination signal. It does not create a daemon or background worker. The executable docs lane starts it with `--once`, sends a real request, verifies the response, and checks clean shutdown.
|
|
74
|
+
|
|
75
|
+
## Advanced: compile portable Pulse Wasm
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npm run compile
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`pulse compile` lowers the canonical handler into a deterministic provider-neutral execution plan and writes compact Pulse-owned WebAssembly. The output includes `pulse-compile.json`, `canonical-native-plan.json`, generated AssemblyScript, Wasm, WAT, and the native ABI manifest. It does not package a deployment provider or embed the Fastly JavaScript runtime.
|
|
82
|
+
|
|
83
|
+
The provider selected by the active `.pulse/config.ts` profile remains relevant to `test`, `dev`, and `build`, but it does not change the portable artifact produced by `compile`. Normal projects can proceed directly from `dev` to `build`; `compile` is not a prerequisite.
|
|
84
|
+
|
|
85
|
+
## Build
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
npm run build
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For Node, the build emits the canonical handler, program metadata, schema registry/codecs when configured, and `pulse-build.json`.
|
|
92
|
+
|
|
93
|
+
For Fastly, `pulse build` reads the provider and bindings from the selected `.pulse/config.ts` profile, compiles the same provider-neutral native plan, and emits generated Fastly-targeted AssemblyScript plus compact direct-host-ABI WebAssembly at `bin/main.wasm`:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run build
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The public CLI does not accept provider overrides. Use `pulse compile` when only the portable `pulse_host` module is needed; use `pulse build` when the configured deployment realization is needed. Native builds always preserve generated source and Wasm together.
|
|
100
|
+
|
|
101
|
+
Provider-neutral compilation and Native provider builds may opt into the
|
|
102
|
+
explicitly experimental size optimizer:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pulse compile --experimental-native-size
|
|
106
|
+
pulse build --experimental-native-size
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The Native compiler resolves that intent to its experimental size profile. The
|
|
110
|
+
current runtime and export surface remain unchanged, the default build is
|
|
111
|
+
unaffected, and portable and provider manifests record the resolved profile.
|
|
112
|
+
JavaScript build targets reject the flag.
|
|
113
|
+
|
|
114
|
+
For candidate-specific output and proof boundaries, continue with [Node build
|
|
115
|
+
and execution](./guides/deploying-node.md) or [Fastly deployment
|
|
116
|
+
candidates](./guides/deploying-fastly.md).
|
|
117
|
+
|
|
118
|
+
## Diagnose failures
|
|
119
|
+
|
|
120
|
+
Run `pulse doctor --json` and use the stable diagnostic code. See [Troubleshooting](guides/troubleshooting.md) and the [diagnostics reference](reference/diagnostics.md).
|
|
121
|
+
|
|
122
|
+
## Next steps
|
|
123
|
+
|
|
124
|
+
- Start with [`examples/01-hello-json`](../examples/01-hello-json/).
|
|
125
|
+
- Add upstream data with [fetching and composition](./guides/fetching-and-composition.md).
|
|
126
|
+
- Add bounded validation with [explicit JSON schemas](./guides/json-schemas.md).
|
|
127
|
+
- Map platform data using [Fastly capabilities](./guides/fastly-capabilities.md).
|
|
128
|
+
- Check source eligibility in [Managed handler TypeScript and JavaScript](./reference/handler-authoring.md), then confirm the selected mode in [Provider and target compatibility](./reference/compatibility-matrix.md).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Compatibility imports and migration
|
|
2
|
+
|
|
3
|
+
Current application code imports Assets and GRIP from their package roots:
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { assets } from '@pulse-compute/assets'
|
|
7
|
+
import { grip } from '@pulse-compute/grip'
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Older fixtures may import `@pulse-compute/assets/pulsewasm` or
|
|
11
|
+
`@pulse-compute/grip/pulsewasm`. Those subpaths remain bounded compatibility
|
|
12
|
+
surfaces; they are not the recommended starting point for a new application and
|
|
13
|
+
do not define a general package-extension convention.
|
|
14
|
+
|
|
15
|
+
## Assets
|
|
16
|
+
|
|
17
|
+
Replace the compatibility import with the package root:
|
|
18
|
+
|
|
19
|
+
```diff
|
|
20
|
+
- import { assets } from '@pulse-compute/assets/pulsewasm'
|
|
21
|
+
+ import { assets } from '@pulse-compute/assets'
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The supported package-root surface uses `assets.lookup(ctx, ...)` for the
|
|
25
|
+
request-bound effect and `assets.respond(...)` for response adoption. Check
|
|
26
|
+
argument eligibility when the selected target is Native; JavaScript execution
|
|
27
|
+
does not widen the Native lowering contract.
|
|
28
|
+
|
|
29
|
+
See the [Assets package guide](../packages/assets.md).
|
|
30
|
+
|
|
31
|
+
## GRIP
|
|
32
|
+
|
|
33
|
+
GRIP migration is an API migration, not only an import rewrite. The compatibility
|
|
34
|
+
facade exposes the older `channel`, `hold`, and `publish` shape. The package root
|
|
35
|
+
separates pure HTTP framing from the request-bound broadcast effect:
|
|
36
|
+
|
|
37
|
+
- `grip.isWebSocket(request)` classifies a request;
|
|
38
|
+
- `grip.subscribe(response, options)` decorates a response;
|
|
39
|
+
- `grip.handoff(options)` constructs a gateway handoff response;
|
|
40
|
+
- `await grip.broadcast(ctx, message)` emits configured outbound work.
|
|
41
|
+
|
|
42
|
+
Move new route code to that package-root model and keep gateway connection
|
|
43
|
+
ownership outside Pulse. The canonical Fastly example now uses the package-root
|
|
44
|
+
`grip.broadcast` contract; the older compatibility fixture is no longer part of
|
|
45
|
+
the public examples set.
|
|
46
|
+
|
|
47
|
+
See the [GRIP package guide](../packages/grip.md) and
|
|
48
|
+
[GRIP/Fanout guide](./grip.md).
|
|
49
|
+
|
|
50
|
+
## Internal filenames are not authoring paths
|
|
51
|
+
|
|
52
|
+
First-party packages still contain names such as `pulsewasm.manifest.cjs`,
|
|
53
|
+
`pulsewasm.compiler.cjs`, and `pulsewasm.lowerable-library-manifest.v2`. Those
|
|
54
|
+
are repository and toolchain protocol names. They do not imply that an
|
|
55
|
+
application should import a `/pulsewasm` subpath or that third-party compiler
|
|
56
|
+
builders can self-register.
|
|
57
|
+
|
|
58
|
+
The current trust boundary is documented in
|
|
59
|
+
[Package-owned lowering](../concepts/package-owned-lowering.md). Contributor
|
|
60
|
+
protocol details remain internal to the synchronized release set.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Fastly deployment candidates
|
|
2
|
+
|
|
3
|
+
Pulse produces separate Fastly Native and Fastly JavaScript Compute candidates.
|
|
4
|
+
Local conformance, target building, external provider reality, remote
|
|
5
|
+
deployment, and service activation are different proof levels.
|
|
6
|
+
|
|
7
|
+
This guide does not claim that a local simulation or offline build is a
|
|
8
|
+
production deployment.
|
|
9
|
+
|
|
10
|
+
## Configure bindings and target
|
|
11
|
+
|
|
12
|
+
The config/secret example is source-bound to a Fastly Native profile:
|
|
13
|
+
|
|
14
|
+
<!-- pulse-doc-source: examples/05-fastly-capabilities/.pulse/config.ts -->
|
|
15
|
+
```ts
|
|
16
|
+
import { defineConfig } from '@pulse-compute/pulse'
|
|
17
|
+
|
|
18
|
+
export default defineConfig((scope) => ({
|
|
19
|
+
pulse: {
|
|
20
|
+
entry: 'src/index.ts',
|
|
21
|
+
tests: 'tests/pulse.harness.ts',
|
|
22
|
+
defaultProfile: 'local',
|
|
23
|
+
strict: true,
|
|
24
|
+
},
|
|
25
|
+
local: {
|
|
26
|
+
host: 'fastly',
|
|
27
|
+
target: 'native',
|
|
28
|
+
outDir: 'dist',
|
|
29
|
+
apiBase: scope.config('API_BASE'),
|
|
30
|
+
apiToken: scope.secret('API_TOKEN'),
|
|
31
|
+
dev: {
|
|
32
|
+
config: { API_BASE: 'https://api.example.com' },
|
|
33
|
+
secrets: {
|
|
34
|
+
API_TOKEN: 'local-example-secret',
|
|
35
|
+
GRIP_TOKEN: 'local-grip-secret',
|
|
36
|
+
},
|
|
37
|
+
kv: {
|
|
38
|
+
sessions: { 'session:123': { userId: 123 } },
|
|
39
|
+
},
|
|
40
|
+
fetches: {
|
|
41
|
+
'https://api.example.com/users/7': {
|
|
42
|
+
value: { id: 7, name: 'Ada' },
|
|
43
|
+
},
|
|
44
|
+
'POST https://publisher.example.com/publish': {
|
|
45
|
+
status: 202,
|
|
46
|
+
value: { accepted: true, messageId: 'message-1' },
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
fastly: {
|
|
51
|
+
bindings: {
|
|
52
|
+
configStore: 'app_config',
|
|
53
|
+
secretStore: 'app_secrets',
|
|
54
|
+
kv: { sessions: 'app_sessions' },
|
|
55
|
+
backends: {
|
|
56
|
+
'https://api.example.com': 'api_backend',
|
|
57
|
+
'https://publisher.example.com': 'publisher_backend',
|
|
58
|
+
},
|
|
59
|
+
dynamicBackends: false,
|
|
60
|
+
grip: {
|
|
61
|
+
publishEndpoint: 'https://publisher.example.com/publish',
|
|
62
|
+
publishBackend: 'publisher_backend',
|
|
63
|
+
authentication: {
|
|
64
|
+
scheme: 'bearer',
|
|
65
|
+
secretRef: 'GRIP_TOKEN',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
build: { name: 'pulse-fastly-capabilities-example' },
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
}))
|
|
73
|
+
```
|
|
74
|
+
<!-- /pulse-doc-source -->
|
|
75
|
+
|
|
76
|
+
Select the JavaScript candidate explicitly with `target: 'javascript'`.
|
|
77
|
+
|
|
78
|
+
The `dev` values and fixtures are local conformance inputs. They do not create
|
|
79
|
+
or populate Fastly Config Stores, Secret Stores, KV Stores, backends, Fanout
|
|
80
|
+
resources, or services. Deployment resource names belong under
|
|
81
|
+
`fastly.bindings`.
|
|
82
|
+
|
|
83
|
+
## Validate locally
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
pulse doctor
|
|
87
|
+
pulse test
|
|
88
|
+
pulse dev
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
For both Fastly targets, `test` and `dev` use provider-owned local execution.
|
|
92
|
+
Fastly JavaScript identifies this as provider emulation. Fastly Native uses the
|
|
93
|
+
canonical local runtime. Neither path contacts or proves a deployed service.
|
|
94
|
+
|
|
95
|
+
## Build Fastly Native
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pulse build
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
With `target: 'native'`, Pulse compiles the provider-neutral plan and emits
|
|
102
|
+
generated `src/main.as.ts` plus compact direct-host-ABI:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
bin/main.wasm
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The Wasm imports the required `fastly_*` hostcalls directly. It does not contain
|
|
109
|
+
the Fastly JavaScript runtime, `pulse_host`, or a WASI dependency. The build
|
|
110
|
+
manifest records exact provider bindings, required capabilities, target
|
|
111
|
+
identity, compiler identity, and artifact hashes.
|
|
112
|
+
|
|
113
|
+
## Build Fastly JavaScript
|
|
114
|
+
|
|
115
|
+
With `target: 'javascript'`, `pulse build` emits a deterministic source and
|
|
116
|
+
deployment closure:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
src/index.js
|
|
120
|
+
src/application.js
|
|
121
|
+
fastly.toml
|
|
122
|
+
package.json
|
|
123
|
+
pulse-esbuild.config.js
|
|
124
|
+
pulse-fastly-javascript-candidate.json
|
|
125
|
+
pulse-fastly-javascript-deployment.json
|
|
126
|
+
pulse-fastly-javascript-source-package.json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The closure pins `esbuild` and `@fastly/js-compute`, bundles the reachable Pulse
|
|
130
|
+
application and supported package implementations, and contains no Pulse
|
|
131
|
+
Native artifact. Its downstream build produces `bin/main.wasm`; the candidate
|
|
132
|
+
and deployment manifests bind that runtime artifact by SHA-256 and retain
|
|
133
|
+
`automaticFallback: false`.
|
|
134
|
+
|
|
135
|
+
Pulse claims deterministic bytes for its source closure and deployment
|
|
136
|
+
metadata. It does not claim byte-identical Wizer-owned runtime snapshots.
|
|
137
|
+
|
|
138
|
+
## Provider reality is a separate gate
|
|
139
|
+
|
|
140
|
+
The external Native reality lane discovers the Fastly CLI and invokes:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
fastly compute serve --file <candidate>/bin/main.wasm
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
and sends real HTTP requests through the generated module. It covers schemas,
|
|
147
|
+
config, secrets, KV persistence, named-backend fetch, opaque bytes, repeated
|
|
148
|
+
headers, and GRIP hold/publish.
|
|
149
|
+
|
|
150
|
+
The Fastly JavaScript offline candidate lane runs the exact pinned downstream
|
|
151
|
+
compiler and validates the resulting runtime Wasm. It does not currently claim
|
|
152
|
+
the same `fastly compute serve` reality execution.
|
|
153
|
+
|
|
154
|
+
The Sprint 7 final candidate must pass its mandatory external reality gate in
|
|
155
|
+
the later packed/provider-reality checkpoint. Checkpoint 5 documents the
|
|
156
|
+
boundary; it does not mark that external gate complete.
|
|
157
|
+
|
|
158
|
+
## Remote deployment and activation
|
|
159
|
+
|
|
160
|
+
`pulse build` never runs `fastly compute deploy`. After candidate review, a
|
|
161
|
+
human deployment owner must:
|
|
162
|
+
|
|
163
|
+
1. create or select the Fastly service and required resources;
|
|
164
|
+
2. ensure every configured binding names the intended resource;
|
|
165
|
+
3. supply account, service, and token authority outside the handler;
|
|
166
|
+
4. run the provider deployment command against the reviewed candidate;
|
|
167
|
+
5. verify the deployed service and external origins;
|
|
168
|
+
6. decide activation, traffic migration, and rollback.
|
|
169
|
+
|
|
170
|
+
Remote deployment and activation require explicit human authorization. A
|
|
171
|
+
successful local conformance run, offline build, downstream JavaScript compile,
|
|
172
|
+
or Native reality serve does not authorize those actions.
|
|
173
|
+
|
|
174
|
+
## Proof-level checklist
|
|
175
|
+
|
|
176
|
+
| Proof level | What it establishes | What it does not establish |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| `pulse test` / `pulse dev` | Canonical behavior and configured local mapping | Remote resources or deployed service health |
|
|
179
|
+
| `pulse build` | Deterministic provider candidate and metadata | External provider execution or deployment |
|
|
180
|
+
| Native reality gate | Real Fastly CLI-managed host-ABI execution | Remote service deployment or activation |
|
|
181
|
+
| JavaScript offline candidate gate | Exact downstream runtime compilation | Fastly serve, remote deployment, or activation |
|
|
182
|
+
| Human remote verification | Deployed service/resource behavior | Permission to publish or promote other release surfaces |
|
|
183
|
+
|
|
184
|
+
See [Project lifecycle](./project-lifecycle.md), [Fastly config, secrets, and
|
|
185
|
+
KV](./fastly-capabilities.md), [`@pulse-compute/provider-fastly`](../packages/provider-fastly.md),
|
|
186
|
+
[Managed handler TypeScript and JavaScript](../reference/handler-authoring.md),
|
|
187
|
+
[Provider and target compatibility](../reference/compatibility-matrix.md),
|
|
188
|
+
and [Release acceptance](../maintainers/release-acceptance.md).
|