@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.
Files changed (191) hide show
  1. package/API.md +572 -0
  2. package/CHANGELOG.md +71 -0
  3. package/README.md +71 -1
  4. package/bin/pulse.js +15 -0
  5. package/bin/pulsewasm-extract.js +22 -0
  6. package/cli-spec.json +575 -0
  7. package/completions/_pulse +106 -0
  8. package/completions/pulse.bash +31 -0
  9. package/completions/pulse.fish +76 -0
  10. package/docs/README.md +77 -0
  11. package/docs/architecture/current-contracts.md +470 -0
  12. package/docs/architecture/overview.md +93 -0
  13. package/docs/architecture/vision.md +515 -0
  14. package/docs/concepts/bodies.md +186 -0
  15. package/docs/concepts/compilation-and-lowering.md +496 -0
  16. package/docs/concepts/contracts-and-providers.md +158 -0
  17. package/docs/concepts/effects-and-continuations.md +300 -0
  18. package/docs/concepts/entities-and-adapters.md +71 -0
  19. package/docs/concepts/package-owned-lowering.md +175 -0
  20. package/docs/concepts/targets-and-hosts.md +70 -0
  21. package/docs/contributing/README.md +38 -0
  22. package/docs/contributing/adding-core-provider.md +315 -0
  23. package/docs/contributing/adding-first-party-lowerer.md +327 -0
  24. package/docs/contributing/entities-lowering.md +91 -0
  25. package/docs/contributing/package-lowerer-contract.md +383 -0
  26. package/docs/contributing/pulse-aware-packages.md +149 -0
  27. package/docs/examples.md +112 -0
  28. package/docs/fixtures/inspect-fetch-composition.selected.json +181 -0
  29. package/docs/getting-started.md +128 -0
  30. package/docs/guides/compatibility-imports.md +60 -0
  31. package/docs/guides/deploying-fastly.md +188 -0
  32. package/docs/guides/deploying-node.md +143 -0
  33. package/docs/guides/events.md +233 -0
  34. package/docs/guides/fastly-capabilities.md +153 -0
  35. package/docs/guides/fetching-and-composition.md +101 -0
  36. package/docs/guides/grip.md +94 -0
  37. package/docs/guides/json-schemas.md +233 -0
  38. package/docs/guides/migrating-from-express.md +192 -0
  39. package/docs/guides/project-lifecycle.md +143 -0
  40. package/docs/guides/routing.md +202 -0
  41. package/docs/guides/troubleshooting.md +47 -0
  42. package/docs/maintainers/README.md +60 -0
  43. package/docs/maintainers/codex-maintainer.md +71 -0
  44. package/docs/maintainers/documentation-deployment.md +147 -0
  45. package/docs/maintainers/documentation-system.md +58 -0
  46. package/docs/maintainers/documentation-versioning.md +65 -0
  47. package/docs/maintainers/maintainer-charter.md +100 -0
  48. package/docs/maintainers/maintenance-policy.json +809 -0
  49. package/docs/maintainers/maintenance-policy.md +124 -0
  50. package/docs/maintainers/npm-publishing.md +154 -0
  51. package/docs/maintainers/plugin-readiness.json +19 -0
  52. package/docs/maintainers/plugin-readiness.md +31 -0
  53. package/docs/maintainers/public-site.md +158 -0
  54. package/docs/maintainers/release-acceptance.md +293 -0
  55. package/docs/maintainers/release-manifest.md +89 -0
  56. package/docs/maintainers/repository-setup.md +145 -0
  57. package/docs/maintainers/scope-policy.md +105 -0
  58. package/docs/maintainers/support-and-triage.md +74 -0
  59. package/docs/maintainers/testing.md +334 -0
  60. package/docs/packages/README.md +60 -0
  61. package/docs/packages/assets.md +85 -0
  62. package/docs/packages/cli.md +190 -0
  63. package/docs/packages/crypto.md +78 -0
  64. package/docs/packages/entities.md +129 -0
  65. package/docs/packages/grip.md +82 -0
  66. package/docs/packages/implementation-packages.md +122 -0
  67. package/docs/packages/jwt.md +55 -0
  68. package/docs/packages/provider-fastly.md +243 -0
  69. package/docs/packages/pulse.md +159 -0
  70. package/docs/packages/runtime.md +265 -0
  71. package/docs/packages/s3.md +101 -0
  72. package/docs/preview-scope.md +142 -0
  73. package/docs/reference/README.md +33 -0
  74. package/docs/reference/cli-spec.json +575 -0
  75. package/docs/reference/cli.md +457 -0
  76. package/docs/reference/compatibility-matrix.md +169 -0
  77. package/docs/reference/diagnostics.md +1872 -0
  78. package/docs/reference/documentation-versions.json +22 -0
  79. package/docs/reference/environment.md +347 -0
  80. package/docs/reference/handler-authoring.md +264 -0
  81. package/docs/reference/project-config.md +582 -0
  82. package/docs/reference/project-config.schema.json +981 -0
  83. package/docs/reference/release-manifest.json +441 -0
  84. package/docs/reference/shell-completion.md +23 -0
  85. package/documentation-site.json +668 -0
  86. package/documentation-versions.json +22 -0
  87. package/examples/01-hello-json/.pulse/.gitignore +3 -0
  88. package/examples/01-hello-json/.pulse/config.ts +16 -0
  89. package/examples/01-hello-json/README.md +119 -0
  90. package/examples/01-hello-json/package.json +20 -0
  91. package/examples/01-hello-json/src/index.ts +9 -0
  92. package/examples/01-hello-json/tests/pulse.harness.ts +22 -0
  93. package/examples/01-hello-json/tsconfig.json +14 -0
  94. package/examples/02-request-schema/.pulse/.gitignore +3 -0
  95. package/examples/02-request-schema/.pulse/config.ts +17 -0
  96. package/examples/02-request-schema/README.md +145 -0
  97. package/examples/02-request-schema/package.json +20 -0
  98. package/examples/02-request-schema/src/index.ts +18 -0
  99. package/examples/02-request-schema/src/schemas.ts +20 -0
  100. package/examples/02-request-schema/tests/pulse.harness.ts +37 -0
  101. package/examples/02-request-schema/tsconfig.json +14 -0
  102. package/examples/03-fetch-composition/.pulse/.gitignore +3 -0
  103. package/examples/03-fetch-composition/.pulse/config.ts +31 -0
  104. package/examples/03-fetch-composition/README.md +210 -0
  105. package/examples/03-fetch-composition/package.json +20 -0
  106. package/examples/03-fetch-composition/src/index.ts +60 -0
  107. package/examples/03-fetch-composition/tests/pulse.harness.ts +47 -0
  108. package/examples/03-fetch-composition/tsconfig.json +14 -0
  109. package/examples/05-fastly-capabilities/.pulse/.gitignore +3 -0
  110. package/examples/05-fastly-capabilities/.pulse/config.ts +57 -0
  111. package/examples/05-fastly-capabilities/README.md +257 -0
  112. package/examples/05-fastly-capabilities/package.json +22 -0
  113. package/examples/05-fastly-capabilities/src/index.ts +55 -0
  114. package/examples/05-fastly-capabilities/tests/pulse.harness.ts +66 -0
  115. package/examples/05-fastly-capabilities/tsconfig.json +14 -0
  116. package/examples/07-opaque-proxy/.pulse/.gitignore +3 -0
  117. package/examples/07-opaque-proxy/.pulse/config.ts +38 -0
  118. package/examples/07-opaque-proxy/README.md +150 -0
  119. package/examples/07-opaque-proxy/package.json +21 -0
  120. package/examples/07-opaque-proxy/src/index.ts +9 -0
  121. package/examples/07-opaque-proxy/tests/pulse.harness.ts +25 -0
  122. package/examples/07-opaque-proxy/tsconfig.json +14 -0
  123. package/examples/09-router-lowering/.pulse/.gitignore +3 -0
  124. package/examples/09-router-lowering/.pulse/config.ts +22 -0
  125. package/examples/09-router-lowering/README.md +287 -0
  126. package/examples/09-router-lowering/package.json +22 -0
  127. package/examples/09-router-lowering/src/index.ts +65 -0
  128. package/examples/09-router-lowering/tests/pulse.harness.ts +91 -0
  129. package/examples/09-router-lowering/tsconfig.json +14 -0
  130. package/examples/10-entities-tools/.pulse/.gitignore +4 -0
  131. package/examples/10-entities-tools/.pulse/config.ts +23 -0
  132. package/examples/10-entities-tools/README.md +165 -0
  133. package/examples/10-entities-tools/package.json +21 -0
  134. package/examples/10-entities-tools/src/handlers.ts +15 -0
  135. package/examples/10-entities-tools/src/index.ts +31 -0
  136. package/examples/10-entities-tools/src/schemas.ts +18 -0
  137. package/examples/10-entities-tools/tests/pulse.harness.ts +40 -0
  138. package/examples/10-entities-tools/tools-facade.cjs +158 -0
  139. package/examples/10-entities-tools/tsconfig.json +14 -0
  140. package/examples/11-events/.pulse/.gitignore +4 -0
  141. package/examples/11-events/.pulse/config.ts +24 -0
  142. package/examples/11-events/README.md +194 -0
  143. package/examples/11-events/package.json +20 -0
  144. package/examples/11-events/src/index.ts +27 -0
  145. package/examples/11-events/src/schemas.ts +19 -0
  146. package/examples/11-events/tests/pulse.harness.ts +34 -0
  147. package/examples/11-events/tsconfig.json +15 -0
  148. package/examples/12-mcp-proxy/.pulse/.gitignore +3 -0
  149. package/examples/12-mcp-proxy/.pulse/config.ts +25 -0
  150. package/examples/12-mcp-proxy/README.md +149 -0
  151. package/examples/12-mcp-proxy/package.json +20 -0
  152. package/examples/12-mcp-proxy/src/index.ts +17 -0
  153. package/examples/12-mcp-proxy/tests/pulse.harness.ts +29 -0
  154. package/examples/12-mcp-proxy/tsconfig.json +14 -0
  155. package/examples/13-jwt-es256/.pulse/config.ts +19 -0
  156. package/examples/13-jwt-es256/README.md +195 -0
  157. package/examples/13-jwt-es256/package.json +21 -0
  158. package/examples/13-jwt-es256/src/index.ts +21 -0
  159. package/examples/13-jwt-es256/tests/pulse.harness.ts +54 -0
  160. package/examples/13-jwt-es256/tsconfig.json +14 -0
  161. package/examples/README.md +36 -0
  162. package/package.json +66 -6
  163. package/project-config.schema.json +981 -0
  164. package/release-manifest.json +441 -0
  165. package/src/command-spec.js +279 -0
  166. package/src/completion.js +113 -0
  167. package/src/diagnostics.js +350 -0
  168. package/src/documentation.js +45 -0
  169. package/src/index.d.ts +133 -0
  170. package/src/index.js +15 -0
  171. package/src/internal/command-executor.d.ts +29 -0
  172. package/src/internal/command-executor.js +143 -0
  173. package/src/internal/command-plan.d.ts +9 -0
  174. package/src/internal/command-plan.js +73 -0
  175. package/src/internal/command-reporter.d.ts +15 -0
  176. package/src/internal/command-reporter.js +133 -0
  177. package/src/internal/command-request.d.ts +35 -0
  178. package/src/internal/command-request.js +154 -0
  179. package/src/internal/node-http.js +54 -0
  180. package/src/internal/project-context.d.ts +66 -0
  181. package/src/internal/project-context.js +175 -0
  182. package/src/project-config-reference.js +4 -0
  183. package/src/project-config-schema.d.ts +23 -0
  184. package/src/project-config-schema.js +271 -0
  185. package/src/project-config.js +724 -0
  186. package/src/project-execution.js +2946 -0
  187. package/src/provider-drivers.js +3 -0
  188. package/src/target-support.js +3 -0
  189. package/src/typescript-module-loader.js +269 -0
  190. package/src/workflow.js +78 -0
  191. package/src/workspace.js +82 -0
@@ -0,0 +1,202 @@
1
+ # Static Router authoring
2
+
3
+ Use `Router` when an application has several method/path entry points or needs compile-time middleware. It is a static authoring marker from `@pulse-compute/runtime`, not a JavaScript runtime dispatcher. The shared async/static restrictions are defined in [Managed handler TypeScript and JavaScript](../reference/handler-authoring.md); target claims live in the [compatibility matrix](../reference/compatibility-matrix.md).
4
+
5
+ <!-- pulse-doc-source: examples/09-router-lowering/src/index.ts -->
6
+ ```ts
7
+ import { Router } from '@pulse-compute/runtime'
8
+
9
+ interface User {
10
+ id: number
11
+ name: string
12
+ }
13
+
14
+ const users = new Router()
15
+ const api = new Router()
16
+ const app = new Router()
17
+
18
+ app.use(async (ctx, next) => {
19
+ if (ctx.req.header('x-pulse-deny') === '1') {
20
+ return ctx.json(
21
+ { error: 'denied by middleware' },
22
+ { status: 401 },
23
+ )
24
+ }
25
+ return next()
26
+ })
27
+
28
+ api.use(async (ctx, next) => {
29
+ if (ctx.req.header('x-api-state') === 'closed') {
30
+ return ctx.text('api closed', { status: 503 })
31
+ }
32
+ return next()
33
+ })
34
+
35
+ users.get('/:id', async (ctx) => {
36
+ const id = ctx.param('id')
37
+ const user = await ctx
38
+ .fetch('https://users.example.test/users/' + id)
39
+ .json<User>()
40
+ return ctx.json({ route: 'user', id, user })
41
+ })
42
+
43
+ api.get('/health', async (ctx, next) => {
44
+ if (ctx.req.header('x-health-handler') === 'fallback') {
45
+ return next()
46
+ }
47
+ return ctx.json({ ok: true, handler: 'primary' })
48
+ })
49
+ api.get('/health', async (ctx) => ctx.json({ ok: true, handler: 'fallback' }))
50
+ api.head('/health', async (ctx) => ctx.text('', {
51
+ status: 204,
52
+ headers: [['x-pulse-route', 'health']],
53
+ }))
54
+ api.post('/users', async (ctx) => ctx.json(
55
+ { route: 'create', method: ctx.req.method },
56
+ { status: 201 },
57
+ ))
58
+ api.get('/files/*', async (ctx) => ctx.text(ctx.req.path))
59
+ api.get('/failure', async (ctx, next) => next('documented-failure'))
60
+
61
+ api.mount('/users', users)
62
+ app.mount('/api', api)
63
+
64
+ app.error(async (error, ctx, next) => {
65
+ if (error === 'documented-failure') {
66
+ return ctx.json({ error: 'handled' }, { status: 418 })
67
+ }
68
+ return next(error)
69
+ })
70
+
71
+ export default app
72
+ ```
73
+ <!-- /pulse-doc-source -->
74
+
75
+ ## Supported v2 surface
76
+
77
+ - `new Router()` with a default-exported root router;
78
+ - `use(handler)` and `use(path, handler)` middleware;
79
+ - `get`, `head`, `post`, `put`, `patch`, and `delete` registrations;
80
+ - exact paths, named `:parameters`, and a trailing `*` wildcard;
81
+ - static acyclic `mount` composition;
82
+ - named or inline async-shaped route handlers using `(ctx)` or `(ctx, next)`;
83
+ - async-shaped middleware using `(ctx, next)`;
84
+ - async-shaped error middleware using `(error, ctx, next)`;
85
+ - `ctx.param('name')` for a parameter declared by the matched route;
86
+ - first-match order, explicit route fallthrough, and compiler-owned 404/500 exhaustion.
87
+
88
+ Every Router handler uses the normal canonical context. Fetches, schemas, config, secrets, KV, opaque responses, and trusted package effects lower into the same native execution plan as single-handler authoring.
89
+
90
+ `Pulse` inherits the same route registration methods. Each registration matches
91
+ its exact HTTP method; a method mismatch advances the route cursor and normal
92
+ exhaustion remains `404`. There is no automatic `OPTIONS` or `405` response.
93
+ Ingress route methods do not widen the separate outbound `ctx.fetch` contract.
94
+
95
+ The `catalog-router-parity` conformance task exercises the original Catalog
96
+ consumer probe and all 14 of its PUT/PATCH/DELETE operations with their existing
97
+ methods and paths. Its shared cases check mounted parameters, request text,
98
+ middleware state, exact method misses, registration order, terminal fallthrough,
99
+ 404 exhaustion and handled errors on Node/Fastly JavaScript and Native. Native
100
+ lanes execute compiled Wasm; Fastly evidence uses local provider emulation and
101
+ the target ABI mock host, not a deployed service. The fixtures establish routing
102
+ acceptance only; they do not implement Catalog persistence or authorization.
103
+
104
+ ```sh
105
+ node wasm/scripts/run-wasm-tests.cjs --task catalog-router-parity --no-report
106
+ ```
107
+
108
+ ## `next()` is a terminal transfer
109
+
110
+ `next()` is not an onion-style callback. It is a compiler-visible control transfer:
111
+
112
+ ```ts
113
+ app.use(async (ctx, next) => {
114
+ if (!authorized(ctx)) return ctx.text('unauthorized', { status: 401 })
115
+ return next()
116
+ })
117
+ ```
118
+
119
+ After `return next()`, the current handler is finished permanently. The Router cursor advances to the next applicable middleware or route. The handler never resumes and `next()` has no downstream response value.
120
+
121
+ These forms are rejected:
122
+
123
+ ```ts
124
+ next()
125
+ return ctx.text('too late')
126
+ ```
127
+
128
+ ```ts
129
+ const response = next()
130
+ return response
131
+ ```
132
+
133
+ Use `return next(error)` to enter the error lane:
134
+
135
+ ```ts
136
+ app.get('/account', async (ctx, next) => {
137
+ if (!ctx.req.header('x-account')) return next('missing-account')
138
+ return ctx.text('ok')
139
+ })
140
+
141
+ app.error(async (error, ctx, next) => {
142
+ if (error === 'missing-account') return ctx.text('account required', { status: 400 })
143
+ return next(error)
144
+ })
145
+ ```
146
+
147
+ If the normal lane is exhausted, Pulse returns `404 Not Found`. If the error lane is exhausted, Pulse returns `500 Internal Server Error`.
148
+
149
+ ## Middleware scope and effects
150
+
151
+ A path-scoped `use('/api', handler)` applies only to that subtree. Middleware declared on a mounted child Router is naturally limited to the mounted subtree.
152
+
153
+ Middleware may request normal canonical effects before transferring control:
154
+
155
+ ```ts
156
+ app.use(async (ctx, next) => {
157
+ const access = await ctx.fetch('https://auth.example.test/check').json<{ allowed: boolean }>()
158
+ if (!access.allowed) return ctx.text('denied', { status: 403 })
159
+ return next()
160
+ })
161
+ ```
162
+
163
+ Pulse owns suspension and resumption for the effect. `pulse inspect` attributes the effect and continuation to the middleware entry and then resumes the same flat Router execution graph.
164
+
165
+
166
+ Use `ctx.parallel({ ... })` inside any managed route or middleware when named
167
+ operations must begin together on both JavaScript and Native targets. Its fixed
168
+ object-literal property order owns effect identity and result reconstruction, and
169
+ the group settles completely before Router execution continues. Separate awaits
170
+ retain ordinary sequential JavaScript behavior; Native may additionally group
171
+ adjacent eligible effects as an optimization.
172
+
173
+
174
+ ## Deliberately outside v2
175
+
176
+ Canonical Router v2 does not support onion-style post-`next()` work, assigning or awaiting `next()`, user-authored `throw` as Router transfer, post-response hooks, realtime lifecycle registrations, channels, timeout scopes, `ctx.resolve`, or `ctx.resolved`.
177
+
178
+ Observability and explicit post-response work should use dedicated future contracts such as trace or defer effects rather than hidden middleware unwinding.
179
+
180
+ ## Inspect the lowering
181
+
182
+ ```bash
183
+ pulse inspect examples/09-router-lowering --json
184
+ ```
185
+
186
+ Look at:
187
+
188
+ ```text
189
+ compiler.authoring.kind
190
+ compiler.routing.entries
191
+ compiler.routing.semantics
192
+ compiler.effects[*].routerEntryStableId
193
+ compiler.continuations[*].routerEntryStableId
194
+ compiler.native.planHash
195
+ ```
196
+
197
+ The same project can then be compiled or built normally:
198
+
199
+ ```bash
200
+ pulse compile examples/09-router-lowering
201
+ pulse build examples/09-router-lowering
202
+ ```
@@ -0,0 +1,47 @@
1
+ # Troubleshooting
2
+
3
+ Start with the command that owns the workflow:
4
+
5
+ ```bash
6
+ pulse doctor --json
7
+ ```
8
+
9
+ Then use:
10
+
11
+ ```bash
12
+ pulse inspect --json
13
+ ```
14
+
15
+ The diagnostic `code` is the stable diagnostic code and identifier. `category`, `remediation`, and `docs` are included in CLI JSON, failed doctor checks, configured expected test errors, and local development error responses.
16
+
17
+ See [Managed handler TypeScript and
18
+ JavaScript](../reference/handler-authoring.md) for source-form boundaries and
19
+ the [compatibility matrix](../reference/compatibility-matrix.md) for
20
+ target-selection boundaries, then use the [diagnostics
21
+ reference](../reference/diagnostics.md) for exit codes and common failures.
22
+
23
+ ## Compilation failures
24
+
25
+ Read nested diagnostics under `error.diagnostics`. Fix the first concrete source/schema diagnostic rather than the top-level `PULSE_PROJECT_COMPILE_FAILED` wrapper. A Native eligibility failure never causes an automatic JavaScript retry; select a JavaScript profile deliberately only when that is the intended target.
26
+
27
+ ## Provider failures
28
+
29
+ Use `pulse inspect --json` to compare compiler requirements with provider bindings. Fastly Native builds realize compact direct-host-ABI Wasm, while Fastly JavaScript builds produce a distinct source/deployment closure. External Fastly reality execution still requires the Fastly CLI and remains a separate environment-dependent gate. See [Fastly deployment candidates](./deploying-fastly.md).
30
+
31
+ ## Runtime failures
32
+
33
+ Use a configured `pulse test` case to reproduce schema errors, fetch failures, and timeout behavior without relying on a live origin.
34
+
35
+ ## Event eligibility and harness failures
36
+
37
+ Use `pulse inspect --json` to compare event registrations and emission
38
+ callsites with `events.targetSupport`. Node JavaScript and Native expose the
39
+ bounded reference adapter; Fastly event projects fail before output with
40
+ `PULSE_FASTLY_EVENT_INGRESS_UNSUPPORTED` or
41
+ `PULSE_FASTLY_EVENT_EMIT_UNSUPPORTED`. Pulse will not translate the event plane
42
+ through HTTP or GRIP and will not switch targets.
43
+
44
+ For `PULSE_TEST_EVENT_INVALID`, check the explicit `kind: 'event'`
45
+ discriminant, use exactly one `schema` field, include payload only for a
46
+ non-null schema, and keep `expect.emitted` as an ordered array. See [Static
47
+ events and outbound emission](./events.md).
@@ -0,0 +1,60 @@
1
+ <!-- pulse-doc-meta:start
2
+ owner: maintainer-council
3
+ status: active
4
+ last-reviewed: 2026-07-25
5
+ review-by: 2027-01-25
6
+ pulse-doc-meta:end -->
7
+
8
+ # Maintainer documentation
9
+
10
+ This index is the entry point for repository governance, release operations,
11
+ publication, deployment, and evidence procedures. These are maintainer
12
+ artifacts, not application-author reference material.
13
+
14
+ ## Governance and support
15
+
16
+ - [Maintainer charter](./maintainer-charter.md) — division of responsibility between Codex and the human architecture/release authority.
17
+ - [Scope policy](./scope-policy.md) — change classes, protected boundaries, and the pull-request declaration.
18
+ - [Codex maintainer operation](./codex-maintainer.md) — how native review and the manual policy review workflow are used safely.
19
+ - [Repository setup](./repository-setup.md) — GitHub team, ruleset, protected environments, action allowlist, labels, Codex, npm, Object Storage, and Fastly configuration that cannot be committed as files.
20
+ - [Support and triage](./support-and-triage.md) — issue intake, response posture, escalation, and quiet-launch operating rules.
21
+ - [Generated maintenance policy](./maintenance-policy.md) — exact classes, boundaries, checks, action pins, environments, and forms.
22
+
23
+ ## Release and publication
24
+
25
+ - [Release manifest and package policy](./release-manifest.md) — synchronized version, package set, support tiers, and target inventory.
26
+ - [Testing Pulse](./testing.md) — focused tasks, profiles, dependency restoration, and evidence expectations.
27
+ - [Release packages and clean-consumer acceptance](./release-acceptance.md) — package construction, packed-consumer checks, and seal evidence.
28
+ - [npm publishing](./npm-publishing.md) — sealed tarballs, trusted publishing, dependency-safe retries, and registry verification.
29
+
30
+ ## Documentation operations
31
+
32
+ - [Documentation system and release workflow](./documentation-system.md) — canonical sources, synchronization, ownership, and release snapshots.
33
+ - [Public site and documentation presentation](./public-site.md) — editorial manifest, navigation, rendering, accessibility, and site validation.
34
+ - [Documentation versions](./documentation-versioning.md) — exact snapshots, the moving alias, search, and installed copies.
35
+ - [Documentation deployment](./documentation-deployment.md) — immutable Object Storage releases, root/latest promotion, and Fastly VCL delivery.
36
+
37
+ ## Protected implementation boundaries
38
+
39
+ - [Public plugin API readiness](./plugin-readiness.md) — the explicit boundary around first-party lowerers and provider bootstrap.
40
+ - [Contributor extension guides](../contributing/) — first-party package lowerers, providers, and Pulse-aware package authoring.
41
+
42
+ ## Authority model
43
+
44
+ Pulse uses a resident-maintainer control plane to keep the public Beta
45
+ supportable without transferring product authority to automation. The control
46
+ plane combines machine-readable scope policy, deterministic path
47
+ classification, repository-local Codex instructions, GitHub ownership, and
48
+ human approval.
49
+
50
+ The system is deliberately asymmetric:
51
+
52
+ ```text
53
+ repository invariants and deterministic checks
54
+
55
+ Codex analysis and patch preparation
56
+
57
+ human architecture and release authority
58
+ ```
59
+
60
+ Codex is a resident maintainer, not a repository principal. It may inspect, classify, reproduce, review, document, and prepare bounded changes. It may not merge, publish, change repository settings, or approve a change to a protected boundary.
@@ -0,0 +1,71 @@
1
+ <!-- pulse-doc-meta:start
2
+ owner: maintainer-council
3
+ status: active
4
+ last-reviewed: 2026-07-16
5
+ review-by: 2027-01-16
6
+ pulse-doc-meta:end -->
7
+
8
+ # Codex resident maintainer
9
+
10
+ Pulse supports two complementary Codex paths. Both remain advisory, inherit repository-local constraints, and stay subordinate to deterministic checks and human approval.
11
+
12
+ ## Repository instructions
13
+
14
+ Codex reads `AGENTS.md` from the repository root toward the file being inspected. The root file defines product invariants and authority. Nested files add compiler, CLI, provider, documentation, release, and GitHub-specific constraints.
15
+
16
+ The machine-readable source remains `release/maintenance-policy.json`. It owns change classes, protected boundaries, path classification, reviewed GitHub Action pins, the protected environment name, and the authority model. `AGENTS.md` explains how to apply that policy; it does not replace the policy or release gates.
17
+
18
+ ## Native GitHub code review
19
+
20
+ A repository owner may connect the repository to Codex and enable code review in Codex settings. Review can then be requested through the connected GitHub integration, or automatic review can be enabled for pull requests.
21
+
22
+ Native review is useful for normal correctness findings. It does not approve a protected-boundary decision and does not replace the deterministic scope check, CODEOWNER approval, or repository validation.
23
+
24
+ ## Manual policy review workflow
25
+
26
+ The **Codex maintainer review** Actions workflow is deliberately manual. It can run only when dispatched from the repository's default branch, and the review job is attached to the protected `codex-maintainer` environment. A trusted maintainer supplies a pull-request number and optional focus.
27
+
28
+ The workflow:
29
+
30
+ 1. checks out GitHub's pull-request merge ref without persisting credentials;
31
+ 2. obtains and sanitizes pull-request metadata through GitHub's API;
32
+ 3. verifies that the merge-ref parents match the API-reported base and head commits;
33
+ 4. creates a nested Git checkout fixed at the trusted base commit, removes its remote, and exposes the proposed base, head, and merge objects only through local review refs;
34
+ 5. places untrusted pull-request metadata in `.pulse-maintainer-review/` inside that trusted checkout, then removes the outer proposed working tree from the Actions workspace;
35
+ 6. runs the base commit's deterministic classifier against a precomputed NUL-delimited changed-file list;
36
+ 7. invokes the reviewed, full-commit-pinned `openai/codex-action` with the trusted checkout as its working directory, the built-in `:read-only` permission profile, and privilege dropping;
37
+ 8. uses the base commit's prompt and generated JSON Schema; and
38
+ 9. uses a separate, narrowly privileged job to update one marked pull-request comment.
39
+
40
+ The Codex job has read-only repository permissions. It cannot post, push, merge, approve, publish, or alter repository settings. The posting job does not receive the OpenAI secret, run Codex, or check out pull-request code. It receives only the schema-constrained review result and pull-request number.
41
+
42
+ ## Trust boundary and prompt injection
43
+
44
+ The working tree visible to Codex is the trusted base. Proposed `AGENTS.md`, policy, prompt, schema, source, fixture, workflow, generated artifact, commit message, and pull-request text remain review material. They can be inspected through the local head ref, but they do not become governing instructions for the same review.
45
+
46
+ The workflow prompt requires Codex to:
47
+
48
+ - read the trusted root and nearest nested `AGENTS.md` files;
49
+ - compare the proposed diff with the deterministic scope report;
50
+ - treat all proposed content as untrusted evidence;
51
+ - avoid checking out or executing the proposed head;
52
+ - focus on concrete containment, authority, correctness, release, and scope failures;
53
+ - avoid network access and file modification;
54
+ - produce only schema-valid structured output; and
55
+ - state uncertainty rather than invent findings.
56
+
57
+ This separation is important because Codex automatically discovers repository instructions. Running from a nested trusted-base checkout prevents a pull request from supplying the instructions that govern its own privileged review.
58
+
59
+ ## Secret and environment protection
60
+
61
+ Store `OPENAI_API_KEY` as an environment secret on `codex-maintainer`, not as a general repository secret. Restrict that environment to the default branch and, when appropriate for the repository plan, require a human reviewer before the job receives the secret.
62
+
63
+ Every external GitHub Action used by the repository is pinned to a reviewed full commit SHA. The version comment beside the SHA is documentation only; it is not the executable reference.
64
+
65
+ ## Asking Codex to prepare a patch
66
+
67
+ Patch preparation should happen through an explicit maintainer task or normal Codex cloud task, not inside the read-only review workflow. The task should include the issue or reproduction, intended change class, and any approved protected boundaries. Codex must still run the repository checks and leave merge and release decisions to a human.
68
+
69
+ ## Failure behavior
70
+
71
+ Codex availability is not a required status check. If the API, action, protected environment, or connected review service is unavailable, deterministic classification and repository validation continue to protect the branch. This keeps the repository operable without making an external model service part of release correctness.
@@ -0,0 +1,147 @@
1
+ <!-- pulse-doc-meta:start
2
+ owner: maintainer-council
3
+ status: active
4
+ last-reviewed: 2026-07-25
5
+ review-by: 2027-01-25
6
+ pulse-doc-meta:end -->
7
+
8
+ # Documentation deployment
9
+
10
+ Pulse documentation is generated static output. It is not deployed as a Pulse Compute application. The production path stores exact-version and moving-alias objects in Fastly Object Storage, then serves them through a small VCL delivery layer.
11
+
12
+ ```text
13
+ source documentation + release catalogs
14
+ → generated site
15
+ → sealed object manifest
16
+ → immutable exact-version upload
17
+ → matching npm release verification
18
+ → root/latest promotion
19
+ → public verification through Fastly
20
+ ```
21
+
22
+ The machine-readable deployment contract is `release/documentation-deployment.json`. The production workflow is `.github/workflows/documentation-deploy.yml`. Reviewed VCL templates and the operating guide live under `infra/fastly/documentation/`.
23
+
24
+ ## Validation and production are separate
25
+
26
+ The **Documentation** workflow runs for pull requests and `main`. It validates generated documentation, builds the exact-version site, seals a preview object manifest, and uploads a short-lived Actions artifact. It has no storage secret and no deployment job.
27
+
28
+ The **Documentation deployment** workflow is dispatched **from the exact release tag**, and its `release_tag` input must name the same tag. A branch-dispatched run fails before candidate construction. The candidate job builds and seals the site without credentials. Its `deploy` job is attached to the protected `documentation-production` environment, reuses the same tagged tooling and source identity, and receives credentials only after a human release/infrastructure authority approves the environment.
29
+
30
+ GitHub Pages deployment is no longer part of the repository workflow. The release catalog's current public origin must be changed to the final Fastly-served hostname before production activation; the deployment verifier rejects an environment-provided public origin that differs from `release/pulse-release-manifest.json`.
31
+
32
+ ## Object classes
33
+
34
+ The `1.0.0-beta.2` layout is:
35
+
36
+ ```text
37
+ <bucket>/pulse/
38
+ index.html mutable
39
+ 404.html mutable
40
+ latest/** mutable
41
+ versions.json mutable
42
+ site-manifest.json mutable
43
+ public-site-manifest.json mutable
44
+ v1.0.0-beta.2/** immutable
45
+ deployments/v1.0.0-beta.2.json immutable receipt
46
+ ```
47
+
48
+ The exact-version tree is the archival release. Root and `latest` are convenience surfaces promoted only after exact-version verification and matching npm package verification.
49
+
50
+ The deployment workflow and script never delete objects. Historical versions and unrelated bucket content are not candidates for synchronization. For an immutable key:
51
+
52
+ ```text
53
+ missing
54
+ → upload
55
+
56
+ present with matching bytes, content type, and cache policy
57
+ → accept as idempotent
58
+
59
+ present with different bytes or metadata
60
+ → fail before promotion
61
+ ```
62
+
63
+ Mutable objects may be replaced during a deliberate promotion. Their cache lifetime is short; exact-version objects are published with one-year immutable caching.
64
+
65
+ ## Sealed deployment candidate
66
+
67
+ Build and inspect locally:
68
+
69
+ ```bash
70
+ npm run docs:site
71
+ npm run docs:deployment:prepare
72
+ npm run docs:deployment:verify
73
+ ```
74
+
75
+ `.pulse-documentation-deployment/documentation-deployment-manifest.json` records every object key, local source, byte length, SHA-256, content type, cache class, mutability, source commit, public documentation route, and independent storage prefix. Its deterministic deployment receipt records the complete generated-site digest and the exact-version object inventory and tree digest for `deployments/v1.0.0-beta.2.json`. Candidate verification rejects any root or site file outside that sealed inventory.
76
+
77
+ A local adapter exercised by `npm run publication:check` proves:
78
+
79
+ - first immutable upload;
80
+ - idempotent retry;
81
+ - rejection of an altered immutable object;
82
+ - npm-gated mutable promotion; and
83
+ - preservation of unrelated objects without any delete operation.
84
+
85
+ ## Object Storage credentials
86
+
87
+ Use separate bucket-limited credentials:
88
+
89
+ | Principal | Required scope | Repository location |
90
+ |---|---|---|
91
+ | GitHub deployment workflow | read/write | `documentation-production` environment secrets |
92
+ | Fastly private origin | read-only | protected Fastly service configuration |
93
+
94
+ The GitHub environment provides:
95
+
96
+ ```text
97
+ Secrets
98
+ FASTLY_OBJECT_STORAGE_ACCESS_KEY_ID
99
+ FASTLY_OBJECT_STORAGE_SECRET_ACCESS_KEY
100
+
101
+ Variables
102
+ FASTLY_OBJECT_STORAGE_BUCKET
103
+ FASTLY_OBJECT_STORAGE_REGION
104
+ FASTLY_OBJECT_STORAGE_ENDPOINT
105
+ PULSE_DOCUMENTATION_ORIGIN
106
+ PULSE_DOCUMENTATION_BASE_PATH
107
+ ```
108
+
109
+ The deployer supplies only these bucket credentials to AWS CLI v2. It clears ambient profiles, session tokens, web-identity roles, container-credential endpoints, and generic AWS endpoint overrides, and points AWS config and shared-credential lookup at the platform null device. This prevents unrelated runner credentials from influencing Object Storage requests.
110
+
111
+ The workflow requires AWS CLI v2, maps the two secrets to its standard credential variables and sends S3-compatible requests to the selected Fastly regional endpoint. Fastly Object Storage rejects the AWS CLI's optional request-checksum behavior, so both the protected deployment job and the deployment adapter set `AWS_REQUEST_CHECKSUM_CALCULATION=when_required`. Storage reads likewise use `AWS_RESPONSE_CHECKSUM_VALIDATION=when_required`. These are fixed compatibility settings, not repository environment variables or credentials.
112
+
113
+ The read-only VCL origin key must never be reused as the deployment key, and the read/write deployment key must never be embedded in VCL.
114
+
115
+ ## VCL delivery boundary
116
+
117
+ The VCL service owns delivery concerns, not content generation:
118
+
119
+ - host or path routing;
120
+ - GET and HEAD admission;
121
+ - directory `index.html` normalization and canonical slash redirects;
122
+ - private Object Storage SigV4 origin signing;
123
+ - bucket and object-prefix rewriting;
124
+ - immutable versus moving-alias cache policy;
125
+ - branded 404 behavior;
126
+ - content and security headers; and
127
+ - removal of storage-specific response headers.
128
+
129
+ The checked-in snippets contain protected credential placeholders and are not activated automatically. A human infrastructure/release owner must create and configure the Fastly service, test a non-production service version, and activate it.
130
+
131
+ ## Promotion and public verification
132
+
133
+ The production workflow performs these steps in order:
134
+
135
+ 1. verify the downloaded documentation candidate and its exact release-tag identity;
136
+ 2. upload or verify every immutable exact-version object and immutable release receipt;
137
+ 3. query npm for all 18 matching package versions and configured dist-tags;
138
+ 4. upload mutable manifests, error pages, and alias payloads using that npm verification report, then write `latest/index.html` and root `index.html` last as the release-owned publication points;
139
+ 5. verify the mutable objects directly in Object Storage;
140
+ 6. request homepage, latest, getting started, the moving site manifest, exact version, CSS, and a missing path through the configured Fastly public origin; and
141
+ 7. retain object, registry, and HTTP evidence as workflow artifacts.
142
+
143
+ Public verification checks that the moving routes and `site-manifest.json` expose the new release version. It retries within the release-owned window so the one-minute alias cache can converge without a privileged CDN purge token.
144
+
145
+ No bucket-wide synchronization or delete operation is used. Mutable promotion is resumable and idempotent, but it is not presented as a cross-object atomic transaction. Writing the two publication points last minimizes partially visible promotions; a failed run is rerun against the same sealed candidate.
146
+
147
+ Codex may diagnose a failed deployment and prepare a patch. It may not approve `documentation-production`, supply credentials, alter the public origin, activate VCL, or promote documentation independently of human release authority.
@@ -0,0 +1,58 @@
1
+ <!-- pulse-doc-meta:start
2
+ owner: maintainer-council
3
+ status: active
4
+ last-reviewed: 2026-07-16
5
+ review-by: 2027-01-16
6
+ pulse-doc-meta:end -->
7
+
8
+ # Documentation system and release workflow
9
+
10
+ Pulse documentation and the public product site have three synchronized delivery forms:
11
+
12
+ 1. repository Markdown for review and source-bound examples;
13
+ 2. installed Markdown, references, schemas, examples, and completions in the CLI package;
14
+ 3. a generated public homepage plus a searchable, versioned static-site artifact under `.pulse-docs-site/`, with committed immutable exact-version archives for prior releases.
15
+
16
+ ## Canonical owners
17
+
18
+ - `release/pulse-release-manifest.json` owns the release version, hosted documentation route, runtime targets, package set, support tiers, and supported entry points.
19
+ - `release/documentation-site.json` owns editable homepage copy, named document destinations, public navigation grouping and order, and homepage composition.
20
+ - `release/maintenance-policy.json` owns change classes, protected boundaries, validation selection, CODEOWNERS/label generation, and the resident-maintainer authority model.
21
+ - `wasm/packages/cli/src/command-spec.js` owns public commands and options; it generates help, the CLI reference, and shell completions.
22
+ - `wasm/packages/cli/src/project-config-schema.js` owns core config fields, defaults, and runtime constraints.
23
+ - `packages/provider-fastly/src/config-schema.json` owns Fastly provider defaults.
24
+ - the diagnostic and environment catalogs own their generated references.
25
+ - `release/documentation-versions.json` owns the version selector and latest alias.
26
+ - `scripts/documentation-site/` owns shared presentation tokens, the vendored Starry Night dark theme, components, browser behavior, the favicon, and the deterministic decorative Pulse field.
27
+
28
+ Do not hand-edit generated copies under `wasm/packages/cli/docs`, `wasm/packages/cli/completions`, or `.pulse-docs-site`. Edit the editorial manifest, canonical catalogs, Markdown, or shared site assets instead. The site directory is an ignored build artifact, not a source tree. Prior exact releases are the exception: `release/documentation-site-archives/v<version>/` contains a byte-preserved site subtree created while that release is still current.
29
+
30
+ ## Update loop
31
+
32
+ ```bash
33
+ npm run maintainer:sync
34
+ pnpm docs:sync
35
+ pnpm docs:check
36
+ pnpm docs:site:check
37
+ node scripts/documentation-release.cjs
38
+ ```
39
+
40
+ `maintainer:sync` refreshes generated governance outputs. `docs:sync` refreshes references, package metadata, shell completions, installed documentation, ownership metadata, and source-bound examples. `docs:check` fails when any checked-in generated surface is stale. `docs:site:check` builds and validates the hosted artifact in a temporary directory; `docs:site` writes `.pulse-docs-site/` for inspection or deployment.
41
+
42
+ For local presentation work, `pnpm docs:preview` performs the synchronization and build, mounts the artifact at `/`, and serves it at `http://127.0.0.1:4173/`. The preview adapter does not rewrite production HTTPS origins or release manifests. `pnpm docs:preview -- --smoke` exercises the local HTTP surface and exits, while `--watch` rebuilds when documentation or presentation sources change. Preview roots are symlink-checked and carry a generator ownership marker; populated unowned directories are rejected, and `--no-build` can only reuse a complete owned artifact.
43
+
44
+ ## Publishing the site
45
+
46
+ The Pages workflow builds `.pulse-docs-site/` for pull requests and main-branch changes, but those events are validation-only. The base route is a generated product homepage; `latest` remains a documentation redirect tree. Publication requires an explicit manual dispatch or a `v<version>` tag that exactly matches `release/pulse-release-manifest.json`. The canonical documentation release lives under `/v<version>/`; `/latest/` contains redirects to the version marked latest. The homepage uses the current release’s exact-version CSS and JavaScript so its shipped presentation is archived with that release. Every exact subtree owns its HTML, assets, search index, release manifest, and version-site manifest.
47
+
48
+ Before changing the release version, run `pnpm docs:site -- --snapshot` while the old release is still current and commit the resulting `release/documentation-site-archives/v<version>/` directory. Add the new version entry only after the archive exists. The builder imports and validates every non-current archive; missing or mismatched history is a release error rather than a Pages deployment that drops old URLs.
49
+
50
+ ## Ownership and review dates
51
+
52
+ Contributor and handwritten maintainer pages carry a generated
53
+ `pulse-doc-meta` block. The
54
+ release gate requires a known owner, status, last-reviewed date, and non-expired
55
+ review-by date. Update the ownership catalog and review the page content
56
+ together; do not merely extend a date without verifying the document.
57
+
58
+ The detailed editing contract, navigation rules, hero motion requirements, and presentation-specific gates are documented in [Public site and documentation presentation](./public-site.md).
@@ -0,0 +1,65 @@
1
+ <!-- pulse-doc-meta:start
2
+ owner: maintainer-council
3
+ status: active
4
+ last-reviewed: 2026-07-16
5
+ review-by: 2027-01-16
6
+ pulse-doc-meta:end -->
7
+
8
+ # Documentation versions, search, and installed copies
9
+
10
+ Pulse publishes a generated product homepage at the configured base path, exact documentation snapshots, and a moving `latest` alias.
11
+
12
+ ## Public product homepage
13
+
14
+ The base route for this repository is:
15
+
16
+ ```text
17
+ https://pulsecompute.io/
18
+ ```
19
+
20
+ It is a generated product homepage, not an alias or redirect. Its copy, named actions, section order, and navigation come from `release/documentation-site.json`; release facts and runtime targets come from `release/pulse-release-manifest.json`; CLI workflow summaries come from the public command specification. The homepage links into `latest` for browsing, while diagnostics and package metadata continue to use exact-version URLs.
21
+
22
+ The homepage and exact current documentation load the same assets under `/v<version>/assets/`. This keeps the visual system consistent and ensures a release snapshot retains the CSS, JavaScript, favicon, no-JavaScript fallback, and hero-graph implementation it shipped with.
23
+
24
+ ## Exact release URLs
25
+
26
+ The canonical URL for this release begins with:
27
+
28
+ ```text
29
+ https://pulsecompute.io/v1.0.0-beta.2/
30
+ ```
31
+
32
+ Diagnostics, package status blocks, and package metadata use exact-version URLs. This prevents a diagnostic emitted by an older CLI from silently opening instructions for a newer contract.
33
+
34
+ Each exact release subtree carries its HTML, release-local search data, public machine-readable references, design tokens, CSS, JavaScript, favicon, editorial site manifest, and version manifest under the same `v<version>/` segment. The release remains renderable and searchable without mutable assets. A small root `versions.json` index may refresh the cross-version selector as newer releases are added; it cannot change the archived page content, styling, or search index.
35
+
36
+ ## The `latest` alias
37
+
38
+ `/latest/` redirects to the release marked current in `release/documentation-versions.json`. It is convenient for browsing, but tools and emitted diagnostics should use the exact release segment.
39
+
40
+ ## Search
41
+
42
+ Every published release has its own generated `search-index.json`. Navigation grouping, breadcrumbs, previous/next order, and the on-page outline are generated from the same editorial navigation model. Search runs locally in the browser and never mixes pages from different release versions. Page titles, headings, text, owner, and review status are indexed.
43
+
44
+ ## Installed and offline documentation
45
+
46
+ `@pulse-compute/cli` ships the public Markdown hierarchy, examples, schemas, command specification, release manifest, version manifest, and shell-completion files. Installed copies remain usable when the hosted site is unavailable. Hosted links are preferred when a stable anchor or cross-package destination is required.
47
+
48
+ ## Adding a documentation version
49
+
50
+ Before changing the release manifest, snapshot the still-current exact site:
51
+
52
+ ```bash
53
+ pnpm docs:site -- --snapshot
54
+ ```
55
+
56
+ This writes `release/documentation-site-archives/v<current-version>/`. Commit that directory unchanged. Then:
57
+
58
+ 1. add the new release to `release/documentation-versions.json` and leave the old entry in place;
59
+ 2. update `release/pulse-release-manifest.json` with the new version and exact segment;
60
+ 3. run the generated-documentation and site gates;
61
+ 4. publish the combined site artifact.
62
+
63
+ The builder copies every non-current version from `release/documentation-site-archives/` and validates its version manifest, release manifest, public-site manifest, search index, pages, and versioned assets before deployment. The moving root homepage is regenerated for the current release; the archived exact subtree preserves the old release’s presentation and routes. A version bump therefore fails rather than silently dropping or rebuilding an older exact release. Existing archive directories are never overwritten unless the snapshot command is given `--force` deliberately.
64
+
65
+ The release gate also rejects a current release that is missing from the versions manifest or whose version segment does not match the release manifest.