redweb 0.13.0 → 0.13.1
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/CHANGELOG.md +6 -2
- package/README.md +290 -290
- package/docs/AGENT_READY_ACCEPTANCE.md +19 -4
- package/docs/CLI.md +1 -1
- package/docs/DEVELOPMENT.md +1 -1
- package/docs/GETTING_STARTED.md +1 -1
- package/docs/LIVE_HTML.md +3 -3
- package/docs/MIGRATION.md +1 -1
- package/docs/PRODUCTION_READINESS.md +6 -5
- package/docs/RELEASE_TRUST.md +13 -10
- package/docs/RUNTIME_DIAGNOSTICS.md +1 -1
- package/docs/SOAK_ROTATION_OBSERVATION.md +4 -4
- package/docs/SOCKET_CONTRACTS.md +2 -2
- package/docs/generated.json +2154 -2154
- package/docs/releases/0.13.0.json +2154 -0
- package/docs/releases/audit-0.13.0.json +1549 -0
- package/docs/topics.json +1 -1
- package/package.json +1 -1
- package/src/ws/HeartbeatMonitor.js +16 -10
package/README.md
CHANGED
|
@@ -1,290 +1,290 @@
|
|
|
1
|
-
# Redweb
|
|
2
|
-
|
|
3
|
-
Build a TypeScript website and its realtime backend together. Decorated classes own state and actions; server-rendered JSX updates the browser through WebSockets. No React, frontend bundler, or separate socket glue is required.
|
|
4
|
-
|
|
5
|
-
Use the same package for a live site, static HTML, Express HTTP endpoints, or routed WebSocket services.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
Start with a complete, tested counter application:
|
|
10
|
-
|
|
11
|
-
<!-- redweb:setup:start -->
|
|
12
|
-
> Unreleased development documentation. Package metadata is 0.13.
|
|
13
|
-
|
|
14
|
-
Replace `TARBALL` with the absolute path to the matching Redweb tarball produced by `npm pack` (quoted if it contains spaces). This is an explicit prerequisite, not an npm package name. Both commands must use the same tarball. The published redweb-client dependency installs automatically; no separate client checkout or linking is required:
|
|
15
|
-
|
|
16
|
-
```sh
|
|
17
|
-
npx --yes --package TARBALL redweb init my-realtime --template realtime
|
|
18
|
-
cd my-realtime
|
|
19
|
-
npm install --save-exact TARBALL
|
|
20
|
-
npm test
|
|
21
|
-
npm run dev
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
This prerelease Redweb artifact is development-only until its release checks finish. For released applications, use an available versioned release guide.
|
|
25
|
-
<!-- redweb:setup:end -->
|
|
26
|
-
|
|
27
|
-
Open two tabs at `http://localhost:8181`. Clicking either button changes the counter on the server and updates both tabs.
|
|
28
|
-
|
|
29
|
-
This is the starter's exact `src/app.tsx`. The initializer also supplies its stylesheet, compiler configuration, shutdown helper, and real-network tests; the file is not a standalone copy-and-run program.
|
|
30
|
-
|
|
31
|
-
<!-- redweb:realtime:start -->
|
|
32
|
-
```tsx
|
|
33
|
-
import { action, page, start, state, type LiveHtmlStartOptions } from 'redweb';
|
|
34
|
-
import { runApp } from './run-app';
|
|
35
|
-
|
|
36
|
-
@page('/', { css: 'app.css', shared: true })
|
|
37
|
-
export class CounterPage {
|
|
38
|
-
@state() count = 0;
|
|
39
|
-
|
|
40
|
-
@action()
|
|
41
|
-
increment() { this.count += 1; }
|
|
42
|
-
|
|
43
|
-
render() {
|
|
44
|
-
return (
|
|
45
|
-
<main class="home">
|
|
46
|
-
<h1>A counter owned by the server</h1>
|
|
47
|
-
<p>Open this page in two tabs. Either button updates both.</p>
|
|
48
|
-
<button rw-click="increment">
|
|
49
|
-
Count <output>{this.count}</output>
|
|
50
|
-
</button>
|
|
51
|
-
</main>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export function createApp(options: LiveHtmlStartOptions = {}) {
|
|
57
|
-
return start(CounterPage, { port: Number(process.env.PORT ?? 8181), templateRoot: __dirname, ...options });
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (require.main === module) runApp(createApp);
|
|
61
|
-
```
|
|
62
|
-
<!-- redweb:realtime:end -->
|
|
63
|
-
|
|
64
|
-
## Choose what to build
|
|
65
|
-
|
|
66
|
-
The links below describe each starter and its boundaries. Reuse the version-correct setup above, changing both the directory name and `--template realtime` to your chosen template. Every initialized project includes all application files and real tests; complete generated recipe pages and file contents are also available in the [documentation catalogue](docs/generated.json).
|
|
67
|
-
|
|
68
|
-
| Build | Starter | Recipe notes |
|
|
69
|
-
| --- | --- | --- |
|
|
70
|
-
| Live site with server-owned state | `realtime` | [Counter](recipes/realtime/README.md) |
|
|
71
|
-
| Chatroom with reusable components and presence | `chat` | [Chat](recipes/chat/README.md) |
|
|
72
|
-
| Non-live pages with shared layout and CSS | `site` | [Site](recipes/site/README.md) |
|
|
73
|
-
| Typed `/match` route with join/move/resume handlers | `socket` | [Socket service](recipes/socket/README.md) |
|
|
74
|
-
| Account-private cards with persistent SQLite data | `dashboard` | [Dashboard](recipes/dashboard/README.md), Node 22.13+ |
|
|
75
|
-
| HTTP and raw WebSockets on one port | `http-ws` | [Shared listener](recipes/http-ws/README.md) |
|
|
76
|
-
|
|
77
|
-
Choose the recipe's `--template` option when initializing. Shared memory survives visitors, not server restarts. The dashboard demonstrates application-owned persistence and identity; it is single-process, not a managed database or authentication service.
|
|
78
|
-
|
|
79
|
-
## Live HTML
|
|
80
|
-
|
|
81
|
-
- A page is a decorated class whose `render()` returns server-side TSX.
|
|
82
|
-
- Ordinary expressions over `@state()` update after assignment. Replace arrays/objects rather than mutating them in place.
|
|
83
|
-
- `@action()` explicitly exposes a method to the browser. Validate inputs and authorize the operation on the server.
|
|
84
|
-
- Function components reuse presentation; decorated class components reuse state, actions, and lifecycle.
|
|
85
|
-
- Stable JSX keys preserve DOM identity for lists. CSS lives in ordinary external files.
|
|
86
|
-
- Pages are connection-scoped by default. `shared: true` deliberately shares one instance: do not put private visitor data there.
|
|
87
|
-
|
|
88
|
-
TSX and `html` templates escape text and attribute values and restrict URL protocols. Use external assets instead of inline executable markup. Ordinary `.html` templates remain available; the old executable `.htmx` sandbox does not.
|
|
89
|
-
|
|
90
|
-
See [pages, components, forms, CSS and rendering](docs/LIVE_HTML.md), [private rooms and request identity](docs/ROOM_AUTHORIZATION.md), and [runtime failures and retry limits](docs/RUNTIME_DIAGNOSTICS.md).
|
|
91
|
-
|
|
92
|
-
## HTTP servers (Express)
|
|
93
|
-
|
|
94
|
-
Use `HttpServer` for Express services and `HttpsServer` when Node terminates TLS. HTTP and WebSockets can run independently; the example below combines them on one listener.
|
|
95
|
-
|
|
96
|
-
## WebSocket servers
|
|
97
|
-
|
|
98
|
-
The `http-ws` starter answers `GET /health` and accepts `{"type":"hello"}` at `ws://127.0.0.1:8181/chat`, using the same port. A URL selects a route; a message's `type` selects its handler. No secondary `message.action` dispatcher is needed.
|
|
99
|
-
|
|
100
|
-
<!-- redweb:http-ws:start -->
|
|
101
|
-
```tsx
|
|
102
|
-
import { BaseHandler, HttpServer, METHODS, SocketRoute, SocketServer, type RedWebSocket, type SocketServerOptions } from 'redweb';
|
|
103
|
-
import { runApp } from './run-app';
|
|
104
|
-
|
|
105
|
-
export class Hello extends BaseHandler {
|
|
106
|
-
constructor() { super('hello'); }
|
|
107
|
-
|
|
108
|
-
onMessage(socket: RedWebSocket) {
|
|
109
|
-
socket.sendJson({ type: 'hello', message: 'Hello from the server!' });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export class ChatRoute extends SocketRoute {
|
|
114
|
-
constructor() {
|
|
115
|
-
super({ path: '/chat', handlers: [Hello], allowDuplicateConnections: true });
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function createApp(options: Pick<SocketServerOptions, 'port' | 'bind' | 'logger'> = {}) {
|
|
120
|
-
const http = new HttpServer({
|
|
121
|
-
listen: false,
|
|
122
|
-
publicPaths: [],
|
|
123
|
-
services: [{ serviceName: '/health', method: METHODS.GET, function: (_req, res) => res.json({ ok: true }) }],
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return new SocketServer({
|
|
127
|
-
port: options.port ?? Number(process.env.PORT ?? 8181),
|
|
128
|
-
bind: options.bind ?? '127.0.0.1',
|
|
129
|
-
logger: options.logger,
|
|
130
|
-
server: http.server,
|
|
131
|
-
routes: [ChatRoute],
|
|
132
|
-
listen: true,
|
|
133
|
-
closeServerOnShutdown: true, // One owner closes routes and the shared HTTP listener.
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (require.main === module) runApp(createApp);
|
|
138
|
-
```
|
|
139
|
-
<!-- redweb:http-ws:end -->
|
|
140
|
-
|
|
141
|
-
Follow the [shared-listener notes](recipes/http-ws/README.md) and initialize with `--template http-ws` using the matching artifact above. The socket service explicitly owns cleanup of the supplied HTTP listener. `/health` reports liveness, not readiness. This demonstrates raw JSON messages, not a chatroom UI.
|
|
142
|
-
|
|
143
|
-
For validated, inferred client/server payloads, use [shared socket contracts](docs/SOCKET_CONTRACTS.md). The client wraps your transport; it does not create or reconnect one for you.
|
|
144
|
-
|
|
145
|
-
## One development loop
|
|
146
|
-
|
|
147
|
-
After installing the matching package:
|
|
148
|
-
|
|
149
|
-
```sh
|
|
150
|
-
npm test
|
|
151
|
-
npm run dev
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
Tests compile the application and use real HTTP/WebSocket listeners. Development watches source, CSS, HTML, and root TypeScript configuration, then rebuilds/restarts. Local HTML pages refresh; detected edits require confirmation before reload. This is not autosave or state-preserving hot-module replacement. See [development refresh and inspection](docs/DEVELOPMENT.md).
|
|
155
|
-
|
|
156
|
-
Build with `npm run build`, then run compiled output with `npm start`. Production ships `dist/`, the manifest, and lockfile, with runtime dependencies installed through `npm ci --omit=dev`; it does not need `src/` or TypeScript.
|
|
157
|
-
|
|
158
|
-
## Add to an existing project
|
|
159
|
-
|
|
160
|
-
Use the installed CLI so the tool and application agree:
|
|
161
|
-
|
|
162
|
-
```sh
|
|
163
|
-
npx --no-install redweb init --existing --dry-run --json
|
|
164
|
-
npx --no-install redweb doctor --json
|
|
165
|
-
npx --no-install redweb add page dashboard --dry-run --json
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
Remove `--dry-run` to create missing files. Existing configuration/source is never overwritten. Incremental generation reports imports, registration steps and isolated tests; it does not rewrite startup or silently repair your project. See [CLI prerequisites, commands and limitations](docs/CLI.md).
|
|
169
|
-
|
|
170
|
-
## Fit and production boundaries
|
|
171
|
-
|
|
172
|
-
Good fit: Node-hosted live dashboards, chat, collaboration, server-rendered sites and multiplayer socket endpoints. Static HTML export is a separate deployment mode.
|
|
173
|
-
|
|
174
|
-
Choose something else when you need React compatibility, browser-side components, an edge-only runtime without Node listeners, or managed authentication/database/matchmaking infrastructure.
|
|
175
|
-
|
|
176
|
-
Before public deployment, configure HTTPS/WSS, trusted origins, identity, authorization, resource limits and application persistence. Reconnect is not exactly-once delivery; multiple processes do not automatically share state. See [operations](docs/MULTIPLAYER_OPERATIONS.md), [guarantees and limits](docs/PRODUCTION_READINESS.md), and [runtime compatibility and release verification](docs/RELEASE_TRUST.md).
|
|
177
|
-
|
|
178
|
-
## Exports
|
|
179
|
-
|
|
180
|
-
See the [public TypeScript API](index.d.ts), [complete documentation catalogue](docs/generated.json), and [getting-started guide](docs/GETTING_STARTED.md). The catalogue includes version-labelled Markdown and executable recipes. An [optional read-only MCP adapter](docs/AGENT_ACCESS.md) serves the same source without adding SDK dependencies to your application; it is currently private/unpublished.
|
|
181
|
-
|
|
182
|
-
## Defaults and lifecycle
|
|
183
|
-
|
|
184
|
-
HTTP defaults to port 80; sockets default to 3000. Generated applications explicitly select 8181. Supplied socket listeners are neither started nor closed unless the corresponding options explicitly transfer that responsibility. Await `shutdown()`; forced transport closure does not guarantee completed application work.
|
|
185
|
-
|
|
186
|
-
See [production ownership and lifecycle](docs/PRODUCTION_READINESS.md).
|
|
187
|
-
|
|
188
|
-
## 0.8 migration notes
|
|
189
|
-
|
|
190
|
-
See [strict paths, sanitized errors and borrowed-listener ownership](docs/MIGRATION.md#08-migration-notes).
|
|
191
|
-
|
|
192
|
-
## 0.9 migration notes
|
|
193
|
-
|
|
194
|
-
See [opt-in multiplayer controls and protocol clients](docs/MIGRATION.md#09-migration-notes).
|
|
195
|
-
|
|
196
|
-
## Live HTML migration
|
|
197
|
-
|
|
198
|
-
See [replacing the executable HTMX sandbox and configuring TSX](docs/MIGRATION.md#live-html-migration).
|
|
199
|
-
|
|
200
|
-
## Developing
|
|
201
|
-
|
|
202
|
-
Run `npm test` for unit tests, actual HTTP/HTTPS/WS/WSS integration tests, type checks and enforced 100% instrumented-library statement/branch/function/line coverage. Browser, package, performance and tool verification have separate gates; this is not a claim of exhaustive repository or application coverage.
|
|
203
|
-
|
|
204
|
-
`npm run verify:load` checks the default 32-client/3,200-message workload, p99 latency, throughput and slow-client containment. Its separate `npm run verify:load:coverage` gate combines unit failure tests with real malformed-message, disconnect and timeout integration tests and enforces all-four 100% coverage of the load policy, coordinator, traffic driver and shared socket helper. Coverage runs do not replace clean performance measurements. See the [scope audit](docs/COVERAGE_SCOPE_AUDIT.md) for exact evidence and remaining gaps.
|
|
205
|
-
|
|
206
|
-
Run `npm run verify:cli` to test the actual initializer, doctor and incremental-add commands and enforce 100% coverage of the shipped CLI entrypoint across subprocesses. This complements, rather than replaces, the library's CLI implementation coverage.
|
|
207
|
-
|
|
208
|
-
`npm run verify:package:examples:coverage` checks the packed counter without optional development dependencies, chat with explicit Zod, and generated TypeScript additions in a real installed consumer. Unit and real-socket failure tests require all-four 100% coverage of the three verifier modules. See [packaged-example evidence](docs/PACKAGED_EXAMPLE_VERIFICATION.md); this complements the full browser/package gate.
|
|
209
|
-
|
|
210
|
-
`npm run verify:action:coverage` checks the source-free typed action consumer in both decorator modes, plus real failed upgrades/responses and unit cleanup failures. It requires all-four 100% of the action-input verifier without enlarging the library coverage scope.
|
|
211
|
-
|
|
212
|
-
`npm run verify:reports:coverage` checks that failed starter commands retain available raw reports without overwriting or merging prior evidence. It combines unit faults with real child processes/filesystem checks and requires all-four 100% of the shared retention helper.
|
|
213
|
-
|
|
214
|
-
`npm run verify:starter-coordinators:coverage` checks both starter coverage runners and their shared final-report handling at all-four 100%. Real compiler/test runs prove changed inputs are rejected; filesystem failures cannot turn a failed command into success. See [starter verification](docs/STARTER_COORDINATOR_VERIFICATION.md) for the exact scope and unit/integration boundaries.
|
|
215
|
-
|
|
216
|
-
`npm run verify:starters:lifecycle` requires a nonempty, complete report for the deployed lifecycle helper. Its separate `npm run verify:starters:lifecycle:coverage` command covers the verifier itself. See [lifecycle evidence](docs/STARTER_LIFECYCLE_VERIFICATION.md) for the emitted-JavaScript scope and temporary source-map metadata removal.
|
|
217
|
-
|
|
218
|
-
`npm run verify:package:browser:coverage` covers the shared browser page owner and packed-browser verifier at all-four 100%, combining explicit failure units with actual Chromium counter/chat integration. Late page openings and cleanup failures retain uncertain workspaces. See [browser ownership evidence](docs/BROWSER_OWNER_VERIFICATION.md) for the checkout/package distinction and exact scope.
|
|
219
|
-
|
|
220
|
-
Browser and authored-source coverage share strict source-map and execution-counter validation. Malformed reports are rejected before merging; see [coverage validation evidence](docs/COVERAGE_COUNTER_VALIDATION.md) for the unit and real-browser checks.
|
|
221
|
-
|
|
222
|
-
Feedback and development-refresh verification share bounded browser commands so a disconnected debugging socket reaches cleanup. [Native failure evidence](docs/FEEDBACK_COMMAND_VERIFICATION.md) records the fixes, exact coverage scopes using actual Chromium/server cases, and the remaining acquisition boundary.
|
|
223
|
-
|
|
224
|
-
Development-refresh checks retain uncertain browser-launch cleanup and preserve shutdown failures. [Verification boundaries](docs/BROWSER_OWNER_VERIFICATION.md#development-refresh-launch-cleanup-follow-up) distinguish these fault tests from real generated-app/browser acceptance.
|
|
225
|
-
|
|
226
|
-
`npm run verify:live-html:load` checks 200 expired renders, 110 connected clients, presence/broadcast delivery and heap growth after client closure/session expiry, before server shutdown. Its separate `verify:live-html:load:coverage` command tests the verifier's HTTP/socket ownership, malformed responses, real timeouts and failure handling with unit and native integration tests. It requires all-four 100% coverage of the three verifier modules; instrumented tests do not replace clean memory measurements.
|
|
227
|
-
|
|
228
|
-
`npm run verify:jsx:performance` renders 10,000 component rows and validates their complete markup outside the timed render. CI supervises the command externally; the five-second performance limit cannot itself interrupt synchronous code. `npm run verify:jsx:coverage` separately checks malformed output, measurement limits and the actual CLI, requiring all-four 100% coverage of this verifier.
|
|
229
|
-
|
|
230
|
-
`npm run verify:soak` checks exact per-connection replies, rotation, disconnects and resource trends. It rejects undersampled runs and reports missing replies explicitly; the existing 99% delivery allowance is not a lossless guarantee. Final heap is sampled after client closure/expiry, before server shutdown. `npm run verify:soak:coverage` separately requires all-four 100% coverage of the verifier, policy and socket owner using unit and real-network/process tests. A short test run does not certify the default one-hour workload.
|
|
231
|
-
|
|
232
|
-
`npm run verify:overhead -- <baseline-directory>` compares disabled-feature socket throughput and p99 latency against a separately prepared baseline. Both sides must complete every warm-up and measured exchange with valid, unique reply IDs; malformed output, timeouts and cleanup failures fail the check. The limits remain 3% throughput regression and 5% p99 regression. `npm run verify:overhead:coverage` separately enforces all-four 100% coverage of the six benchmark modules through unit and real-socket/process tests. See [benchmark evidence and limitations](docs/BENCHMARK_VERIFICATION.md); a coverage pass is not a performance pass.
|
|
233
|
-
|
|
234
|
-
Run `npm run verify:recovery:server` from this source checkout for the blocking CI recovery contract: 7,400 exact exchanges with a separately measured server, empty registries, normal worker exits and every storm within 110% of warmed server heap. The original `npm run verify:recovery` remains a visible non-blocking CI diagnostic; its historical failures are not resolved by this measurement change. CI preserves both results and logs. See the [reviewed recovery contract and evidence](docs/SERVER_RECOVERY_CANDIDATE.md).
|
|
235
|
-
|
|
236
|
-
`npm run verify:recovery:coverage` separately enforces all-four 100% coverage of that gate's policy, CLI, and full authored coordinator/worker source. It combines unit boundary tests with actual worker/socket integration without repeating the native workload. The instrumented behavioral run is not used as a clean heap measurement; the normal server recovery command remains separate. See [authored recovery coverage](docs/SPLIT_RECOVERY_COVERAGE.md).
|
|
237
|
-
|
|
238
|
-
`npm run verify:recovery:original:coverage` separately tests the original shared-process verifier with authored-source coverage units and its existing real CLI/socket/snapshot checks. Its 110% limit now compares integer bytes exactly: equality passes, a one-byte excess fails, and any over-budget storm still fails even if the final heap recovers. Displayed ratios and workloads are unchanged. Synthetic unit heap values are not memory evidence, and this rounding correction does not explain larger historical failures. See the [coverage and regression evidence](docs/ORIGINAL_RECOVERY_VERIFICATION.md).
|
|
239
|
-
|
|
240
|
-
Recovery workers also retain non-Error failures and clean up rejected IPC requests immediately; empty error replies cannot masquerade as success. [Real-process regressions and server recovery evidence](docs/SPLIT_RECOVERY_ERROR_HANDLING.md) distinguish correctness fixes from coverage. Short soak checks retain raw results before assertions and preserve original reports if artifact writing fails. A [hosted delivery failure and real rotation controls](docs/SOAK_ROTATION_OBSERVATION.md) remain visible; no delivery threshold was relaxed.
|
|
241
|
-
|
|
242
|
-
Run `npm run verify:recovery:diagnostics` for native-source 100% coverage of the two private heap-analysis tools, including their real command-line entrypoints. It reuses the graph unit cases under Node's test runner to avoid merging Jest-transformed and original source ranges. Parser fixtures and real file/subprocess checks cover graph bounds, shared references, redaction, and malformed input; the separate recovery integration suite also checks actual V8 snapshots and a real server-held object. This gate does not cover the recovery workload verifier itself or waive its failed memory budget.
|
|
243
|
-
|
|
244
|
-
Run `npm run verify:package:tools` for a separate 100% coverage gate over the managed subprocess owner, failure normalizer, and starter/Markdown application verifiers. Tests use actual npm/native commands, descendants, files and generated applications. Use Node 22.13+ to exercise all six recipes, including the SQLite dashboard. Package packing/extraction and consumer checks use the same bounded owner; uncertain cleanup fails verification and retains its workspace. This is a scoped tool gate, verified on Windows, not coverage of every verification script or proof of cross-platform execution; Windows file-lock cases are skipped elsewhere.
|
|
245
|
-
|
|
246
|
-
Every generated starter also has `npm run test:coverage`: real application tests with coverage mapped to its TypeScript, separate from library coverage. In this repository, `npm run measure:starters:coverage` runs all six starter commands and records source/report hashes and run-specific results. It checks that every application module is measured, but does not present incomplete coverage as a passing 100% gate; compiler-generated decorator accessors appear in function counts. The chat and socket recipes include domain and real-network tests for reconnecting, identity conflicts, bounded history and session capacity.
|
|
247
|
-
|
|
248
|
-
`npm run verify:starters:source-coverage` separately instruments original TypeScript before compilation, so compiler-created decorator helpers do not inflate authored function counts. It runs the same application tests plain and instrumented, checks unchanged inputs, retains V8 reports, and enforces 100% of Istanbul's tracked statements/branches/functions/lines. All six starters pass with 104 tests per mode and all 600 statements, 299 branches, 160 functions and 472 lines covered. Integration tests use real networking and persistence; explicitly labelled unit cases exercise defensive failure paths. Istanbul does not independently count optional-chaining short circuits, so this is not an exhaustive semantic-branch claim or a replacement for V8 evidence. Reports identify received process reports, not every spawned child: hard termination can prevent an exit report, while every source module still starts in the denominator at zero. Node 22.13+ is required for all six recipes. Instrumentation and reports are test-only and are not shipped.
|
|
249
|
-
|
|
250
|
-
Run `npm run verify:browser:coverage` for native Chromium tests of the complete emitted Live HTML runtime and development-refresh script. The gate enforces 100% statement/branch/function/line coverage and runs the same cases without instrumentation. Actual HTTP/WebSocket checks cover actions, forms, state updates, reconnection and selection preservation. Refresh checks cover real reloads, draft guards, failed HTTP peers, history restoration and explicit discard under a self-only script policy; instrumentation requires no dynamic code evaluation.
|
|
251
|
-
|
|
252
|
-
The refresh report (`coverage/browser-refresh/report.json`) also retains `historyRestoration.plain.bfcacheRestored` and `historyRestoration.instrumented.bfcacheRestored` for each successfully completed mode. These are actual browser observations, not requirements: history navigation and resumed polling must pass, but the browser may choose to reload instead of restoring from its back/forward cache. A mode that fails before completion may only log its observation.
|
|
253
|
-
|
|
254
|
-
`npm run verify:refresh:coverage` separately requires 100% authored coverage of both refresh verification helpers. It combines explicit failure-boundary units with actual Chromium, HTTP uploads and socket cleanup, and is included in the browser coverage gate. Collection, page-close and socket-release failures remain visible together; a rejected non-Error value cannot become a passing result. The host-side helper map does not measure execution inside browser-expression strings; the separate generated-refresh map and native checks remain required.
|
|
255
|
-
|
|
256
|
-
`npm run verify:development:coverage` additionally covers the generated-app refresh verifier: real TypeScript/CSS rebuilds, browser draft preservation, adverse HTTP peers and process cleanup, plus explicit startup/cleanup failure units. Page openings remain owned if they time out or settle late; uncertain cleanup retains the workspace. CI runs this gate instead of repeating the standalone development browser command. Its 100% scope is the authored coordinator, not embedded browser programs or every possible platform failure.
|
|
257
|
-
|
|
258
|
-
`npm run verify:package:coordinator:coverage` runs the complete isolated-package check alongside explicit failure-boundary units and real listener-cleanup tests. It requires 100% authored coverage of the package coordinator and report helper. Every acquired example server gets its own cleanup attempt; a missing error value cannot become success, and success is printed only after workspace cleanup. CI uses this instead of repeating the standalone package command. The full consumer check requires the dashboard starter's Node version (22.13 or newer); older supported library versions run the native cleanup checks but skip that consumer case.
|
|
259
|
-
|
|
260
|
-
The isolated browser harness copies its verification helpers explicitly and checks their literal relative imports against that copied set. This catches missing test dependencies without falling back to checkout runtime code; the real packed-consumer gate still verifies installation and execution.
|
|
261
|
-
|
|
262
|
-
`npm run verify:evaluation:process:coverage` measures the unchanged evaluation process and evidence-sealing tools at 100% authored coverage. It combines explicit OS-boundary units with actual subprocess, archive, file-lock, CLI and listener checks. A test-only preload instruments selected code in memory; frozen source and sealed evaluation records are not rewritten. Native interface inspection is Windows-only; unsupported platforms are tested for explicit rejection. This coverage gate does not rerun an agent trial or resolve historical cleanup failures.
|
|
263
|
-
|
|
264
|
-
`npm run verify:evaluation:prepare:coverage` separately checks candidate preparation against actual npm archives, catalogue bytes and Git identity, comparing plain and instrumented CLI execution. Real launch-failure checks supplement explicit subprocess-boundary units. It uses owned temporary directories and does not publish packages or rerun sealed agent trials.
|
|
265
|
-
|
|
266
|
-
`npm run verify:evaluation:trial:coverage` checks the unchanged trial runner's input hashes, build outcomes and evidence retention. It combines real archive/CLI checks, explicit failure units and the evaluator's actual HTTP/WebSocket browser control on Windows. Synthetic checker fixtures are not new agent trials or substitutes for packed Redweb acceptance. Uncertain cleanup preserves the outer test workspace and its report, including leftover browser profiles even when no report was saved.
|
|
267
|
-
|
|
268
|
-
`npm run verify:evaluation:controls:coverage` measures the unchanged control validator and browser evaluator together: four working protocol controls and seven deliberately broken variants run in actual Chromium on Windows. Real CLI tests also cover failed builds, early exits, invalid startup URLs and HTTP rejection. Elsewhere, interface inspection must explicitly refuse support, not imply browser success. Separate browser/process/result boundary units cover reporting and cleanup faults; unexpected native outcomes retain their original errors and workspace. These evaluator controls are not new Redweb agent submissions or release acceptance.
|
|
269
|
-
|
|
270
|
-
`npm run verify:live-html:browser:coverage` combines the existing full browser workload (counter, chat, CSS, JSX, components, forms and dashboard) with explicit failure-path unit tests. Its 100% authored-tool coverage is separate from frontend coverage and release acceptance. The native workload requires the dashboard's supported Node version. Known limitations of the unchanged legacy browser tool— including uncertain descendant cleanup—are characterized, not silently fixed or counted as verified cleanup; see the [coverage audit](docs/COVERAGE_SCOPE_AUDIT.md).
|
|
271
|
-
|
|
272
|
-
The frontend is maintained in `redweb-client/live-html`; Redweb emits only a two-line mounting bootstrap.
|
|
273
|
-
|
|
274
|
-
`npm run measure:browser:client` separately serves the exact installed socket-only module with and without instrumentation through the same real HTTP/WebSocket/browser cases and retains its source hash and counters. It exits unsuccessfully until all four coverage metrics reach 100%; incomplete results are not a passing dependency-coverage claim. Reports are local under `coverage/browser-client` and do not alter the installed dependency or published package.
|
|
275
|
-
|
|
276
|
-
`npm run verify:browser:coordinator:coverage` checks the browser coordinator and four runtime/refresh verification helpers together at 100% authored coverage. The umbrella browser gate uses this combined run to avoid repeating the native workloads. Failure units supplement actual Chromium/HTTP/WebSocket checks; the installed-client diagnostic must still report incomplete coverage as failure, not a release pass. CI retains the combined map and separate runtime/refresh/client reports. An additional source-build integration requires `REDWEB_VERIFY_CLIENT_SOURCE=1` and the linked client checkout with its development dependencies; ordinary registry-only CI skips that case. The standalone `verify:client:source-coverage` remains the original-source acceptance gate.
|
|
277
|
-
|
|
278
|
-
Ownership and stopped-poll edge cases also use native-browser unit-style tests; browser and transport APIs are not replaced. Runtime coverage now covers all Live HTML modules inside the linked client bundle, excluding its transport prefix; the development-refresh script is measured separately. Whole-application/tool coverage and cross-browser certification remain separate gates.
|
|
279
|
-
|
|
280
|
-
`npm run verify:client:source-coverage` measures the linked client's original TypeScript/JavaScript using one instrumentation map across its Node tests and the native browser tests. Every executable source module starts at zero; erased declarations and static export linkage are separately audited. Both test passes use identical source/test inputs, every Vitest test realm must report, and plain browser bundles must match the linked build byte-for-byte. Reports retain separate Node/browser contributions under `coverage/client-source/<run-id>`. The gate passes all 791 statements, 521 branches, 125 functions and 659 lines, with 77 Node tests per mode plus native-browser acceptance. The client's default `npm test` uses this same complete gate after linkage, build and type checks. Its original Node-only V8 diagnostic remains separately available as `npm run test:v8`, with unchanged thresholds and known missing-browser coverage. Original-source instrumentation does not count every optional-chain short circuit, replace V8 evidence, or mean all tests are mock-free: isolated unit transports remain, while integration/browser tests use actual networking.
|
|
281
|
-
|
|
282
|
-
Client verification also retains raw worker files before parsing or cleanup, including failed runs. Its private coordinator has a separate 100% coverage gate; real Vitest failure fixtures exercise retention without replacing filesystem, compiler or process APIs. See [client development](docs/CLIENT_DEVELOPMENT.md) for commands and scope.
|
|
283
|
-
|
|
284
|
-
`npm run verify:browser:supplements` combines focused units with the existing real-browser runtime cases to require 100% authored-source coverage of the page-ownership and runtime-frame verification helpers, including anonymous callbacks. It is included in the browser coverage gate; see the [coverage scope audit](docs/COVERAGE_SCOPE_AUDIT.md) for exact boundaries and remaining gaps.
|
|
285
|
-
|
|
286
|
-
`npm run verify:dashboard:coverage` measures the dashboard browser verifier separately: failure-boundary units plus actual Chromium, SQLite, sign-in, private card updates, draft preservation and logout checks. Native dashboard tests require the starter's supported Node version; file-lock retention is Windows-specific. The scope is the authored verifier, not internal coverage of its browser-expression strings.
|
|
287
|
-
|
|
288
|
-
An unresolved Linux CI process-cleanup assertion and the diagnostics added to investigate it are tracked in [process cleanup observations](docs/PROCESS_CLEANUP_OBSERVATION.md). Passing runs do not establish its cause or waive the original failure.
|
|
289
|
-
|
|
290
|
-
Edit canonical recipes/guides, then run `npm run generate:docs`; do not maintain independent copies of the examples. See [documentation maintenance](docs/DOCUMENTATION.md) and the [full acceptance checklist](docs/AGENT_READY_ACCEPTANCE.md) for verification evidence and remaining release work.
|
|
1
|
+
# Redweb
|
|
2
|
+
|
|
3
|
+
Build a TypeScript website and its realtime backend together. Decorated classes own state and actions; server-rendered JSX updates the browser through WebSockets. No React, frontend bundler, or separate socket glue is required.
|
|
4
|
+
|
|
5
|
+
Use the same package for a live site, static HTML, Express HTTP endpoints, or routed WebSocket services.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
Start with a complete, tested counter application:
|
|
10
|
+
|
|
11
|
+
<!-- redweb:setup:start -->
|
|
12
|
+
> Unreleased development documentation. Package metadata is 0.13.1, but these features are not claimed to be published in that npm version. Use the matching Redweb tarball described in the recipe setup; its published client dependency installs automatically. Do not install latest and assume compatibility.
|
|
13
|
+
|
|
14
|
+
Replace `TARBALL` with the absolute path to the matching Redweb tarball produced by `npm pack` (quoted if it contains spaces). This is an explicit prerequisite, not an npm package name. Both commands must use the same tarball. The published redweb-client dependency installs automatically; no separate client checkout or linking is required:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npx --yes --package TARBALL redweb init my-realtime --template realtime
|
|
18
|
+
cd my-realtime
|
|
19
|
+
npm install --save-exact TARBALL
|
|
20
|
+
npm test
|
|
21
|
+
npm run dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This prerelease Redweb artifact is development-only until its release checks finish. For released applications, use an available versioned release guide.
|
|
25
|
+
<!-- redweb:setup:end -->
|
|
26
|
+
|
|
27
|
+
Open two tabs at `http://localhost:8181`. Clicking either button changes the counter on the server and updates both tabs.
|
|
28
|
+
|
|
29
|
+
This is the starter's exact `src/app.tsx`. The initializer also supplies its stylesheet, compiler configuration, shutdown helper, and real-network tests; the file is not a standalone copy-and-run program.
|
|
30
|
+
|
|
31
|
+
<!-- redweb:realtime:start -->
|
|
32
|
+
```tsx
|
|
33
|
+
import { action, page, start, state, type LiveHtmlStartOptions } from 'redweb';
|
|
34
|
+
import { runApp } from './run-app';
|
|
35
|
+
|
|
36
|
+
@page('/', { css: 'app.css', shared: true })
|
|
37
|
+
export class CounterPage {
|
|
38
|
+
@state() count = 0;
|
|
39
|
+
|
|
40
|
+
@action()
|
|
41
|
+
increment() { this.count += 1; }
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
return (
|
|
45
|
+
<main class="home">
|
|
46
|
+
<h1>A counter owned by the server</h1>
|
|
47
|
+
<p>Open this page in two tabs. Either button updates both.</p>
|
|
48
|
+
<button rw-click="increment">
|
|
49
|
+
Count <output>{this.count}</output>
|
|
50
|
+
</button>
|
|
51
|
+
</main>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createApp(options: LiveHtmlStartOptions = {}) {
|
|
57
|
+
return start(CounterPage, { port: Number(process.env.PORT ?? 8181), templateRoot: __dirname, ...options });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (require.main === module) runApp(createApp);
|
|
61
|
+
```
|
|
62
|
+
<!-- redweb:realtime:end -->
|
|
63
|
+
|
|
64
|
+
## Choose what to build
|
|
65
|
+
|
|
66
|
+
The links below describe each starter and its boundaries. Reuse the version-correct setup above, changing both the directory name and `--template realtime` to your chosen template. Every initialized project includes all application files and real tests; complete generated recipe pages and file contents are also available in the [documentation catalogue](docs/generated.json).
|
|
67
|
+
|
|
68
|
+
| Build | Starter | Recipe notes |
|
|
69
|
+
| --- | --- | --- |
|
|
70
|
+
| Live site with server-owned state | `realtime` | [Counter](recipes/realtime/README.md) |
|
|
71
|
+
| Chatroom with reusable components and presence | `chat` | [Chat](recipes/chat/README.md) |
|
|
72
|
+
| Non-live pages with shared layout and CSS | `site` | [Site](recipes/site/README.md) |
|
|
73
|
+
| Typed `/match` route with join/move/resume handlers | `socket` | [Socket service](recipes/socket/README.md) |
|
|
74
|
+
| Account-private cards with persistent SQLite data | `dashboard` | [Dashboard](recipes/dashboard/README.md), Node 22.13+ |
|
|
75
|
+
| HTTP and raw WebSockets on one port | `http-ws` | [Shared listener](recipes/http-ws/README.md) |
|
|
76
|
+
|
|
77
|
+
Choose the recipe's `--template` option when initializing. Shared memory survives visitors, not server restarts. The dashboard demonstrates application-owned persistence and identity; it is single-process, not a managed database or authentication service.
|
|
78
|
+
|
|
79
|
+
## Live HTML
|
|
80
|
+
|
|
81
|
+
- A page is a decorated class whose `render()` returns server-side TSX.
|
|
82
|
+
- Ordinary expressions over `@state()` update after assignment. Replace arrays/objects rather than mutating them in place.
|
|
83
|
+
- `@action()` explicitly exposes a method to the browser. Validate inputs and authorize the operation on the server.
|
|
84
|
+
- Function components reuse presentation; decorated class components reuse state, actions, and lifecycle.
|
|
85
|
+
- Stable JSX keys preserve DOM identity for lists. CSS lives in ordinary external files.
|
|
86
|
+
- Pages are connection-scoped by default. `shared: true` deliberately shares one instance: do not put private visitor data there.
|
|
87
|
+
|
|
88
|
+
TSX and `html` templates escape text and attribute values and restrict URL protocols. Use external assets instead of inline executable markup. Ordinary `.html` templates remain available; the old executable `.htmx` sandbox does not.
|
|
89
|
+
|
|
90
|
+
See [pages, components, forms, CSS and rendering](docs/LIVE_HTML.md), [private rooms and request identity](docs/ROOM_AUTHORIZATION.md), and [runtime failures and retry limits](docs/RUNTIME_DIAGNOSTICS.md).
|
|
91
|
+
|
|
92
|
+
## HTTP servers (Express)
|
|
93
|
+
|
|
94
|
+
Use `HttpServer` for Express services and `HttpsServer` when Node terminates TLS. HTTP and WebSockets can run independently; the example below combines them on one listener.
|
|
95
|
+
|
|
96
|
+
## WebSocket servers
|
|
97
|
+
|
|
98
|
+
The `http-ws` starter answers `GET /health` and accepts `{"type":"hello"}` at `ws://127.0.0.1:8181/chat`, using the same port. A URL selects a route; a message's `type` selects its handler. No secondary `message.action` dispatcher is needed.
|
|
99
|
+
|
|
100
|
+
<!-- redweb:http-ws:start -->
|
|
101
|
+
```tsx
|
|
102
|
+
import { BaseHandler, HttpServer, METHODS, SocketRoute, SocketServer, type RedWebSocket, type SocketServerOptions } from 'redweb';
|
|
103
|
+
import { runApp } from './run-app';
|
|
104
|
+
|
|
105
|
+
export class Hello extends BaseHandler {
|
|
106
|
+
constructor() { super('hello'); }
|
|
107
|
+
|
|
108
|
+
onMessage(socket: RedWebSocket) {
|
|
109
|
+
socket.sendJson({ type: 'hello', message: 'Hello from the server!' });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export class ChatRoute extends SocketRoute {
|
|
114
|
+
constructor() {
|
|
115
|
+
super({ path: '/chat', handlers: [Hello], allowDuplicateConnections: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function createApp(options: Pick<SocketServerOptions, 'port' | 'bind' | 'logger'> = {}) {
|
|
120
|
+
const http = new HttpServer({
|
|
121
|
+
listen: false,
|
|
122
|
+
publicPaths: [],
|
|
123
|
+
services: [{ serviceName: '/health', method: METHODS.GET, function: (_req, res) => res.json({ ok: true }) }],
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return new SocketServer({
|
|
127
|
+
port: options.port ?? Number(process.env.PORT ?? 8181),
|
|
128
|
+
bind: options.bind ?? '127.0.0.1',
|
|
129
|
+
logger: options.logger,
|
|
130
|
+
server: http.server,
|
|
131
|
+
routes: [ChatRoute],
|
|
132
|
+
listen: true,
|
|
133
|
+
closeServerOnShutdown: true, // One owner closes routes and the shared HTTP listener.
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (require.main === module) runApp(createApp);
|
|
138
|
+
```
|
|
139
|
+
<!-- redweb:http-ws:end -->
|
|
140
|
+
|
|
141
|
+
Follow the [shared-listener notes](recipes/http-ws/README.md) and initialize with `--template http-ws` using the matching artifact above. The socket service explicitly owns cleanup of the supplied HTTP listener. `/health` reports liveness, not readiness. This demonstrates raw JSON messages, not a chatroom UI.
|
|
142
|
+
|
|
143
|
+
For validated, inferred client/server payloads, use [shared socket contracts](docs/SOCKET_CONTRACTS.md). The client wraps your transport; it does not create or reconnect one for you.
|
|
144
|
+
|
|
145
|
+
## One development loop
|
|
146
|
+
|
|
147
|
+
After installing the matching package:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
npm test
|
|
151
|
+
npm run dev
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Tests compile the application and use real HTTP/WebSocket listeners. Development watches source, CSS, HTML, and root TypeScript configuration, then rebuilds/restarts. Local HTML pages refresh; detected edits require confirmation before reload. This is not autosave or state-preserving hot-module replacement. See [development refresh and inspection](docs/DEVELOPMENT.md).
|
|
155
|
+
|
|
156
|
+
Build with `npm run build`, then run compiled output with `npm start`. Production ships `dist/`, the manifest, and lockfile, with runtime dependencies installed through `npm ci --omit=dev`; it does not need `src/` or TypeScript.
|
|
157
|
+
|
|
158
|
+
## Add to an existing project
|
|
159
|
+
|
|
160
|
+
Use the installed CLI so the tool and application agree:
|
|
161
|
+
|
|
162
|
+
```sh
|
|
163
|
+
npx --no-install redweb init --existing --dry-run --json
|
|
164
|
+
npx --no-install redweb doctor --json
|
|
165
|
+
npx --no-install redweb add page dashboard --dry-run --json
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Remove `--dry-run` to create missing files. Existing configuration/source is never overwritten. Incremental generation reports imports, registration steps and isolated tests; it does not rewrite startup or silently repair your project. See [CLI prerequisites, commands and limitations](docs/CLI.md).
|
|
169
|
+
|
|
170
|
+
## Fit and production boundaries
|
|
171
|
+
|
|
172
|
+
Good fit: Node-hosted live dashboards, chat, collaboration, server-rendered sites and multiplayer socket endpoints. Static HTML export is a separate deployment mode.
|
|
173
|
+
|
|
174
|
+
Choose something else when you need React compatibility, browser-side components, an edge-only runtime without Node listeners, or managed authentication/database/matchmaking infrastructure.
|
|
175
|
+
|
|
176
|
+
Before public deployment, configure HTTPS/WSS, trusted origins, identity, authorization, resource limits and application persistence. Reconnect is not exactly-once delivery; multiple processes do not automatically share state. See [operations](docs/MULTIPLAYER_OPERATIONS.md), [guarantees and limits](docs/PRODUCTION_READINESS.md), and [runtime compatibility and release verification](docs/RELEASE_TRUST.md).
|
|
177
|
+
|
|
178
|
+
## Exports
|
|
179
|
+
|
|
180
|
+
See the [public TypeScript API](index.d.ts), [complete documentation catalogue](docs/generated.json), and [getting-started guide](docs/GETTING_STARTED.md). The catalogue includes version-labelled Markdown and executable recipes. An [optional read-only MCP adapter](docs/AGENT_ACCESS.md) serves the same source without adding SDK dependencies to your application; it is currently private/unpublished.
|
|
181
|
+
|
|
182
|
+
## Defaults and lifecycle
|
|
183
|
+
|
|
184
|
+
HTTP defaults to port 80; sockets default to 3000. Generated applications explicitly select 8181. Supplied socket listeners are neither started nor closed unless the corresponding options explicitly transfer that responsibility. Await `shutdown()`; forced transport closure does not guarantee completed application work.
|
|
185
|
+
|
|
186
|
+
See [production ownership and lifecycle](docs/PRODUCTION_READINESS.md).
|
|
187
|
+
|
|
188
|
+
## 0.8 migration notes
|
|
189
|
+
|
|
190
|
+
See [strict paths, sanitized errors and borrowed-listener ownership](docs/MIGRATION.md#08-migration-notes).
|
|
191
|
+
|
|
192
|
+
## 0.9 migration notes
|
|
193
|
+
|
|
194
|
+
See [opt-in multiplayer controls and protocol clients](docs/MIGRATION.md#09-migration-notes).
|
|
195
|
+
|
|
196
|
+
## Live HTML migration
|
|
197
|
+
|
|
198
|
+
See [replacing the executable HTMX sandbox and configuring TSX](docs/MIGRATION.md#live-html-migration).
|
|
199
|
+
|
|
200
|
+
## Developing
|
|
201
|
+
|
|
202
|
+
Run `npm test` for unit tests, actual HTTP/HTTPS/WS/WSS integration tests, type checks and enforced 100% instrumented-library statement/branch/function/line coverage. Browser, package, performance and tool verification have separate gates; this is not a claim of exhaustive repository or application coverage.
|
|
203
|
+
|
|
204
|
+
`npm run verify:load` checks the default 32-client/3,200-message workload, p99 latency, throughput and slow-client containment. Its separate `npm run verify:load:coverage` gate combines unit failure tests with real malformed-message, disconnect and timeout integration tests and enforces all-four 100% coverage of the load policy, coordinator, traffic driver and shared socket helper. Coverage runs do not replace clean performance measurements. See the [scope audit](docs/COVERAGE_SCOPE_AUDIT.md) for exact evidence and remaining gaps.
|
|
205
|
+
|
|
206
|
+
Run `npm run verify:cli` to test the actual initializer, doctor and incremental-add commands and enforce 100% coverage of the shipped CLI entrypoint across subprocesses. This complements, rather than replaces, the library's CLI implementation coverage.
|
|
207
|
+
|
|
208
|
+
`npm run verify:package:examples:coverage` checks the packed counter without optional development dependencies, chat with explicit Zod, and generated TypeScript additions in a real installed consumer. Unit and real-socket failure tests require all-four 100% coverage of the three verifier modules. See [packaged-example evidence](docs/PACKAGED_EXAMPLE_VERIFICATION.md); this complements the full browser/package gate.
|
|
209
|
+
|
|
210
|
+
`npm run verify:action:coverage` checks the source-free typed action consumer in both decorator modes, plus real failed upgrades/responses and unit cleanup failures. It requires all-four 100% of the action-input verifier without enlarging the library coverage scope.
|
|
211
|
+
|
|
212
|
+
`npm run verify:reports:coverage` checks that failed starter commands retain available raw reports without overwriting or merging prior evidence. It combines unit faults with real child processes/filesystem checks and requires all-four 100% of the shared retention helper.
|
|
213
|
+
|
|
214
|
+
`npm run verify:starter-coordinators:coverage` checks both starter coverage runners and their shared final-report handling at all-four 100%. Real compiler/test runs prove changed inputs are rejected; filesystem failures cannot turn a failed command into success. See [starter verification](docs/STARTER_COORDINATOR_VERIFICATION.md) for the exact scope and unit/integration boundaries.
|
|
215
|
+
|
|
216
|
+
`npm run verify:starters:lifecycle` requires a nonempty, complete report for the deployed lifecycle helper. Its separate `npm run verify:starters:lifecycle:coverage` command covers the verifier itself. See [lifecycle evidence](docs/STARTER_LIFECYCLE_VERIFICATION.md) for the emitted-JavaScript scope and temporary source-map metadata removal.
|
|
217
|
+
|
|
218
|
+
`npm run verify:package:browser:coverage` covers the shared browser page owner and packed-browser verifier at all-four 100%, combining explicit failure units with actual Chromium counter/chat integration. Late page openings and cleanup failures retain uncertain workspaces. See [browser ownership evidence](docs/BROWSER_OWNER_VERIFICATION.md) for the checkout/package distinction and exact scope.
|
|
219
|
+
|
|
220
|
+
Browser and authored-source coverage share strict source-map and execution-counter validation. Malformed reports are rejected before merging; see [coverage validation evidence](docs/COVERAGE_COUNTER_VALIDATION.md) for the unit and real-browser checks.
|
|
221
|
+
|
|
222
|
+
Feedback and development-refresh verification share bounded browser commands so a disconnected debugging socket reaches cleanup. [Native failure evidence](docs/FEEDBACK_COMMAND_VERIFICATION.md) records the fixes, exact coverage scopes using actual Chromium/server cases, and the remaining acquisition boundary.
|
|
223
|
+
|
|
224
|
+
Development-refresh checks retain uncertain browser-launch cleanup and preserve shutdown failures. [Verification boundaries](docs/BROWSER_OWNER_VERIFICATION.md#development-refresh-launch-cleanup-follow-up) distinguish these fault tests from real generated-app/browser acceptance.
|
|
225
|
+
|
|
226
|
+
`npm run verify:live-html:load` checks 200 expired renders, 110 connected clients, presence/broadcast delivery and heap growth after client closure/session expiry, before server shutdown. Its separate `verify:live-html:load:coverage` command tests the verifier's HTTP/socket ownership, malformed responses, real timeouts and failure handling with unit and native integration tests. It requires all-four 100% coverage of the three verifier modules; instrumented tests do not replace clean memory measurements.
|
|
227
|
+
|
|
228
|
+
`npm run verify:jsx:performance` renders 10,000 component rows and validates their complete markup outside the timed render. CI supervises the command externally; the five-second performance limit cannot itself interrupt synchronous code. `npm run verify:jsx:coverage` separately checks malformed output, measurement limits and the actual CLI, requiring all-four 100% coverage of this verifier.
|
|
229
|
+
|
|
230
|
+
`npm run verify:soak` checks exact per-connection replies, rotation, disconnects and resource trends. It rejects undersampled runs and reports missing replies explicitly; the existing 99% delivery allowance is not a lossless guarantee. Final heap is sampled after client closure/expiry, before server shutdown. `npm run verify:soak:coverage` separately requires all-four 100% coverage of the verifier, policy and socket owner using unit and real-network/process tests. A short test run does not certify the default one-hour workload.
|
|
231
|
+
|
|
232
|
+
`npm run verify:overhead -- <baseline-directory>` compares disabled-feature socket throughput and p99 latency against a separately prepared baseline. Both sides must complete every warm-up and measured exchange with valid, unique reply IDs; malformed output, timeouts and cleanup failures fail the check. The limits remain 3% throughput regression and 5% p99 regression. `npm run verify:overhead:coverage` separately enforces all-four 100% coverage of the six benchmark modules through unit and real-socket/process tests. See [benchmark evidence and limitations](docs/BENCHMARK_VERIFICATION.md); a coverage pass is not a performance pass.
|
|
233
|
+
|
|
234
|
+
Run `npm run verify:recovery:server` from this source checkout for the blocking CI recovery contract: 7,400 exact exchanges with a separately measured server, empty registries, normal worker exits and every storm within 110% of warmed server heap. The original `npm run verify:recovery` remains a visible non-blocking CI diagnostic; its historical failures are not resolved by this measurement change. CI preserves both results and logs. See the [reviewed recovery contract and evidence](docs/SERVER_RECOVERY_CANDIDATE.md).
|
|
235
|
+
|
|
236
|
+
`npm run verify:recovery:coverage` separately enforces all-four 100% coverage of that gate's policy, CLI, and full authored coordinator/worker source. It combines unit boundary tests with actual worker/socket integration without repeating the native workload. The instrumented behavioral run is not used as a clean heap measurement; the normal server recovery command remains separate. See [authored recovery coverage](docs/SPLIT_RECOVERY_COVERAGE.md).
|
|
237
|
+
|
|
238
|
+
`npm run verify:recovery:original:coverage` separately tests the original shared-process verifier with authored-source coverage units and its existing real CLI/socket/snapshot checks. Its 110% limit now compares integer bytes exactly: equality passes, a one-byte excess fails, and any over-budget storm still fails even if the final heap recovers. Displayed ratios and workloads are unchanged. Synthetic unit heap values are not memory evidence, and this rounding correction does not explain larger historical failures. See the [coverage and regression evidence](docs/ORIGINAL_RECOVERY_VERIFICATION.md).
|
|
239
|
+
|
|
240
|
+
Recovery workers also retain non-Error failures and clean up rejected IPC requests immediately; empty error replies cannot masquerade as success. [Real-process regressions and server recovery evidence](docs/SPLIT_RECOVERY_ERROR_HANDLING.md) distinguish correctness fixes from coverage. Short soak checks retain raw results before assertions and preserve original reports if artifact writing fails. A [hosted delivery failure and real rotation controls](docs/SOAK_ROTATION_OBSERVATION.md) remain visible; no delivery threshold was relaxed.
|
|
241
|
+
|
|
242
|
+
Run `npm run verify:recovery:diagnostics` for native-source 100% coverage of the two private heap-analysis tools, including their real command-line entrypoints. It reuses the graph unit cases under Node's test runner to avoid merging Jest-transformed and original source ranges. Parser fixtures and real file/subprocess checks cover graph bounds, shared references, redaction, and malformed input; the separate recovery integration suite also checks actual V8 snapshots and a real server-held object. This gate does not cover the recovery workload verifier itself or waive its failed memory budget.
|
|
243
|
+
|
|
244
|
+
Run `npm run verify:package:tools` for a separate 100% coverage gate over the managed subprocess owner, failure normalizer, and starter/Markdown application verifiers. Tests use actual npm/native commands, descendants, files and generated applications. Use Node 22.13+ to exercise all six recipes, including the SQLite dashboard. Package packing/extraction and consumer checks use the same bounded owner; uncertain cleanup fails verification and retains its workspace. This is a scoped tool gate, verified on Windows, not coverage of every verification script or proof of cross-platform execution; Windows file-lock cases are skipped elsewhere.
|
|
245
|
+
|
|
246
|
+
Every generated starter also has `npm run test:coverage`: real application tests with coverage mapped to its TypeScript, separate from library coverage. In this repository, `npm run measure:starters:coverage` runs all six starter commands and records source/report hashes and run-specific results. It checks that every application module is measured, but does not present incomplete coverage as a passing 100% gate; compiler-generated decorator accessors appear in function counts. The chat and socket recipes include domain and real-network tests for reconnecting, identity conflicts, bounded history and session capacity.
|
|
247
|
+
|
|
248
|
+
`npm run verify:starters:source-coverage` separately instruments original TypeScript before compilation, so compiler-created decorator helpers do not inflate authored function counts. It runs the same application tests plain and instrumented, checks unchanged inputs, retains V8 reports, and enforces 100% of Istanbul's tracked statements/branches/functions/lines. All six starters pass with 104 tests per mode and all 600 statements, 299 branches, 160 functions and 472 lines covered. Integration tests use real networking and persistence; explicitly labelled unit cases exercise defensive failure paths. Istanbul does not independently count optional-chaining short circuits, so this is not an exhaustive semantic-branch claim or a replacement for V8 evidence. Reports identify received process reports, not every spawned child: hard termination can prevent an exit report, while every source module still starts in the denominator at zero. Node 22.13+ is required for all six recipes. Instrumentation and reports are test-only and are not shipped.
|
|
249
|
+
|
|
250
|
+
Run `npm run verify:browser:coverage` for native Chromium tests of the complete emitted Live HTML runtime and development-refresh script. The gate enforces 100% statement/branch/function/line coverage and runs the same cases without instrumentation. Actual HTTP/WebSocket checks cover actions, forms, state updates, reconnection and selection preservation. Refresh checks cover real reloads, draft guards, failed HTTP peers, history restoration and explicit discard under a self-only script policy; instrumentation requires no dynamic code evaluation.
|
|
251
|
+
|
|
252
|
+
The refresh report (`coverage/browser-refresh/report.json`) also retains `historyRestoration.plain.bfcacheRestored` and `historyRestoration.instrumented.bfcacheRestored` for each successfully completed mode. These are actual browser observations, not requirements: history navigation and resumed polling must pass, but the browser may choose to reload instead of restoring from its back/forward cache. A mode that fails before completion may only log its observation.
|
|
253
|
+
|
|
254
|
+
`npm run verify:refresh:coverage` separately requires 100% authored coverage of both refresh verification helpers. It combines explicit failure-boundary units with actual Chromium, HTTP uploads and socket cleanup, and is included in the browser coverage gate. Collection, page-close and socket-release failures remain visible together; a rejected non-Error value cannot become a passing result. The host-side helper map does not measure execution inside browser-expression strings; the separate generated-refresh map and native checks remain required.
|
|
255
|
+
|
|
256
|
+
`npm run verify:development:coverage` additionally covers the generated-app refresh verifier: real TypeScript/CSS rebuilds, browser draft preservation, adverse HTTP peers and process cleanup, plus explicit startup/cleanup failure units. Page openings remain owned if they time out or settle late; uncertain cleanup retains the workspace. CI runs this gate instead of repeating the standalone development browser command. Its 100% scope is the authored coordinator, not embedded browser programs or every possible platform failure.
|
|
257
|
+
|
|
258
|
+
`npm run verify:package:coordinator:coverage` runs the complete isolated-package check alongside explicit failure-boundary units and real listener-cleanup tests. It requires 100% authored coverage of the package coordinator and report helper. Every acquired example server gets its own cleanup attempt; a missing error value cannot become success, and success is printed only after workspace cleanup. CI uses this instead of repeating the standalone package command. The full consumer check requires the dashboard starter's Node version (22.13 or newer); older supported library versions run the native cleanup checks but skip that consumer case.
|
|
259
|
+
|
|
260
|
+
The isolated browser harness copies its verification helpers explicitly and checks their literal relative imports against that copied set. This catches missing test dependencies without falling back to checkout runtime code; the real packed-consumer gate still verifies installation and execution.
|
|
261
|
+
|
|
262
|
+
`npm run verify:evaluation:process:coverage` measures the unchanged evaluation process and evidence-sealing tools at 100% authored coverage. It combines explicit OS-boundary units with actual subprocess, archive, file-lock, CLI and listener checks. A test-only preload instruments selected code in memory; frozen source and sealed evaluation records are not rewritten. Native interface inspection is Windows-only; unsupported platforms are tested for explicit rejection. This coverage gate does not rerun an agent trial or resolve historical cleanup failures.
|
|
263
|
+
|
|
264
|
+
`npm run verify:evaluation:prepare:coverage` separately checks candidate preparation against actual npm archives, catalogue bytes and Git identity, comparing plain and instrumented CLI execution. Real launch-failure checks supplement explicit subprocess-boundary units. It uses owned temporary directories and does not publish packages or rerun sealed agent trials.
|
|
265
|
+
|
|
266
|
+
`npm run verify:evaluation:trial:coverage` checks the unchanged trial runner's input hashes, build outcomes and evidence retention. It combines real archive/CLI checks, explicit failure units and the evaluator's actual HTTP/WebSocket browser control on Windows. Synthetic checker fixtures are not new agent trials or substitutes for packed Redweb acceptance. Uncertain cleanup preserves the outer test workspace and its report, including leftover browser profiles even when no report was saved.
|
|
267
|
+
|
|
268
|
+
`npm run verify:evaluation:controls:coverage` measures the unchanged control validator and browser evaluator together: four working protocol controls and seven deliberately broken variants run in actual Chromium on Windows. Real CLI tests also cover failed builds, early exits, invalid startup URLs and HTTP rejection. Elsewhere, interface inspection must explicitly refuse support, not imply browser success. Separate browser/process/result boundary units cover reporting and cleanup faults; unexpected native outcomes retain their original errors and workspace. These evaluator controls are not new Redweb agent submissions or release acceptance.
|
|
269
|
+
|
|
270
|
+
`npm run verify:live-html:browser:coverage` combines the existing full browser workload (counter, chat, CSS, JSX, components, forms and dashboard) with explicit failure-path unit tests. Its 100% authored-tool coverage is separate from frontend coverage and release acceptance. The native workload requires the dashboard's supported Node version. Known limitations of the unchanged legacy browser tool— including uncertain descendant cleanup—are characterized, not silently fixed or counted as verified cleanup; see the [coverage audit](docs/COVERAGE_SCOPE_AUDIT.md).
|
|
271
|
+
|
|
272
|
+
The frontend is maintained in `redweb-client/live-html`; Redweb emits only a two-line mounting bootstrap. Published `redweb@0.13.0` depends on published `redweb-client@^0.2.0`, so ordinary application installation needs no client checkout or link. Contributors editing the client can still use the [linked development workflow](docs/CLIENT_DEVELOPMENT.md).
|
|
273
|
+
|
|
274
|
+
`npm run measure:browser:client` separately serves the exact installed socket-only module with and without instrumentation through the same real HTTP/WebSocket/browser cases and retains its source hash and counters. It exits unsuccessfully until all four coverage metrics reach 100%; incomplete results are not a passing dependency-coverage claim. Reports are local under `coverage/browser-client` and do not alter the installed dependency or published package.
|
|
275
|
+
|
|
276
|
+
`npm run verify:browser:coordinator:coverage` checks the browser coordinator and four runtime/refresh verification helpers together at 100% authored coverage. The umbrella browser gate uses this combined run to avoid repeating the native workloads. Failure units supplement actual Chromium/HTTP/WebSocket checks; the installed-client diagnostic must still report incomplete coverage as failure, not a release pass. CI retains the combined map and separate runtime/refresh/client reports. An additional source-build integration requires `REDWEB_VERIFY_CLIENT_SOURCE=1` and the linked client checkout with its development dependencies; ordinary registry-only CI skips that case. The standalone `verify:client:source-coverage` remains the original-source acceptance gate.
|
|
277
|
+
|
|
278
|
+
Ownership and stopped-poll edge cases also use native-browser unit-style tests; browser and transport APIs are not replaced. Runtime coverage now covers all Live HTML modules inside the linked client bundle, excluding its transport prefix; the development-refresh script is measured separately. Whole-application/tool coverage and cross-browser certification remain separate gates.
|
|
279
|
+
|
|
280
|
+
`npm run verify:client:source-coverage` measures the linked client's original TypeScript/JavaScript using one instrumentation map across its Node tests and the native browser tests. Every executable source module starts at zero; erased declarations and static export linkage are separately audited. Both test passes use identical source/test inputs, every Vitest test realm must report, and plain browser bundles must match the linked build byte-for-byte. Reports retain separate Node/browser contributions under `coverage/client-source/<run-id>`. The gate passes all 791 statements, 521 branches, 125 functions and 659 lines, with 77 Node tests per mode plus native-browser acceptance. The client's default `npm test` uses this same complete gate after linkage, build and type checks. Its original Node-only V8 diagnostic remains separately available as `npm run test:v8`, with unchanged thresholds and known missing-browser coverage. Original-source instrumentation does not count every optional-chain short circuit, replace V8 evidence, or mean all tests are mock-free: isolated unit transports remain, while integration/browser tests use actual networking.
|
|
281
|
+
|
|
282
|
+
Client verification also retains raw worker files before parsing or cleanup, including failed runs. Its private coordinator has a separate 100% coverage gate; real Vitest failure fixtures exercise retention without replacing filesystem, compiler or process APIs. See [client development](docs/CLIENT_DEVELOPMENT.md) for commands and scope.
|
|
283
|
+
|
|
284
|
+
`npm run verify:browser:supplements` combines focused units with the existing real-browser runtime cases to require 100% authored-source coverage of the page-ownership and runtime-frame verification helpers, including anonymous callbacks. It is included in the browser coverage gate; see the [coverage scope audit](docs/COVERAGE_SCOPE_AUDIT.md) for exact boundaries and remaining gaps.
|
|
285
|
+
|
|
286
|
+
`npm run verify:dashboard:coverage` measures the dashboard browser verifier separately: failure-boundary units plus actual Chromium, SQLite, sign-in, private card updates, draft preservation and logout checks. Native dashboard tests require the starter's supported Node version; file-lock retention is Windows-specific. The scope is the authored verifier, not internal coverage of its browser-expression strings.
|
|
287
|
+
|
|
288
|
+
An unresolved Linux CI process-cleanup assertion and the diagnostics added to investigate it are tracked in [process cleanup observations](docs/PROCESS_CLEANUP_OBSERVATION.md). Passing runs do not establish its cause or waive the original failure.
|
|
289
|
+
|
|
290
|
+
Edit canonical recipes/guides, then run `npm run generate:docs`; do not maintain independent copies of the examples. See [documentation maintenance](docs/DOCUMENTATION.md) and the [full acceptance checklist](docs/AGENT_READY_ACCEPTANCE.md) for verification evidence and remaining release work.
|