@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
|
@@ -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.
|