brass-runtime 1.15.0 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +409 -137
  2. package/dist/agent/cli/main.cjs +40 -35
  3. package/dist/agent/cli/main.js +9 -4
  4. package/dist/agent/cli/main.mjs +9 -4
  5. package/dist/agent/index.cjs +8 -4
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +7 -3
  8. package/dist/agent/index.mjs +7 -3
  9. package/dist/{chunk-PPUXIH5R.js → chunk-2WC63LJK.mjs} +11 -7
  10. package/dist/chunk-3RG5ZIWI.js +10 -0
  11. package/dist/chunk-45F7OKGT.cjs +104 -0
  12. package/dist/chunk-5YOQOXEQ.cjs +2491 -0
  13. package/dist/{chunk-STVLQ3XD.cjs → chunk-7HUOJA4W.cjs} +78 -74
  14. package/dist/{chunk-BMH5AV44.js → chunk-7LVI2GIN.js} +251 -370
  15. package/dist/chunk-7TL2LHQJ.js +2491 -0
  16. package/dist/chunk-7V4KY4RL.mjs +104 -0
  17. package/dist/chunk-7XOPAB5Q.js +2143 -0
  18. package/dist/chunk-CCKHV5BT.mjs +193 -0
  19. package/dist/{chunk-AR22SXML.js → chunk-CY33PGEX.mjs} +488 -421
  20. package/dist/chunk-DJQ7OMMB.cjs +144 -0
  21. package/dist/chunk-F5EUMJL7.mjs +2143 -0
  22. package/dist/chunk-FM4W4QPL.js +193 -0
  23. package/dist/{chunk-TO7IKXYT.js → chunk-G3XGCZDQ.js} +1 -1
  24. package/dist/{chunk-BDF4AMWX.mjs → chunk-G6IQOE4P.mjs} +251 -370
  25. package/dist/chunk-GOV47PPB.mjs +552 -0
  26. package/dist/chunk-H55LI6WY.js +93 -0
  27. package/dist/chunk-IJT6RRQ5.cjs +93 -0
  28. package/dist/{chunk-ELOOF35R.mjs → chunk-J3H54ZRV.mjs} +1 -1
  29. package/dist/chunk-JF4XXPZ5.cjs +552 -0
  30. package/dist/chunk-JNFRRJYH.cjs +2143 -0
  31. package/dist/chunk-JX3LZQJH.cjs +354 -0
  32. package/dist/chunk-K2T3DV26.mjs +93 -0
  33. package/dist/chunk-KCPT2D6G.js +552 -0
  34. package/dist/chunk-MWXMNYJS.cjs +1110 -0
  35. package/dist/{chunk-VEZNF5GZ.cjs → chunk-N6VHMOWB.cjs} +130 -126
  36. package/dist/{chunk-3QMOKAS5.js → chunk-NC5SDRYE.js} +9 -5
  37. package/dist/chunk-NOYZIMUJ.mjs +144 -0
  38. package/dist/{chunk-R3R2FVLG.cjs → chunk-NYL4D7SK.cjs} +5 -5
  39. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  40. package/dist/{chunk-4NHES7VK.mjs → chunk-OOGJ73B6.js} +11 -7
  41. package/dist/chunk-PNVFW245.js +144 -0
  42. package/dist/chunk-PRWCB3QL.mjs +2491 -0
  43. package/dist/{chunk-JFPU5GQI.mjs → chunk-QY5FKYEQ.js} +488 -421
  44. package/dist/chunk-ROJC3NBJ.js +104 -0
  45. package/dist/chunk-SPUEME2B.cjs +343 -0
  46. package/dist/chunk-TDVMADDN.js +343 -0
  47. package/dist/chunk-TVN5I4U6.cjs +193 -0
  48. package/dist/chunk-U5KWK3PX.mjs +343 -0
  49. package/dist/chunk-VFIUZG7J.mjs +354 -0
  50. package/dist/{chunk-TGIFUAK4.cjs → chunk-WQ5QNU5R.cjs} +459 -578
  51. package/dist/chunk-XDZOO4L5.js +354 -0
  52. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  53. package/dist/{chunk-K6M7MDZ4.mjs → chunk-ZGLD4TVZ.mjs} +9 -5
  54. package/dist/client-CtFmoDvM.d.ts +645 -0
  55. package/dist/core/index.cjs +72 -4
  56. package/dist/core/index.d.ts +92 -198
  57. package/dist/core/index.js +106 -38
  58. package/dist/core/index.mjs +106 -38
  59. package/dist/{effect-CMOQKX8y.d.ts → effect-CGNl5Rqp.d.ts} +107 -1
  60. package/dist/effectRunner-3ZHAD3LE.cjs +8 -0
  61. package/dist/effectRunner-A4CHJXJI.js +8 -0
  62. package/dist/effectRunner-OPUF6QRN.mjs +8 -0
  63. package/dist/http/index.cjs +2189 -1271
  64. package/dist/http/index.d.ts +830 -270
  65. package/dist/http/index.js +2008 -1090
  66. package/dist/http/index.mjs +2008 -1090
  67. package/dist/http/testing.cjs +159 -0
  68. package/dist/http/testing.d.ts +42 -0
  69. package/dist/http/testing.js +159 -0
  70. package/dist/http/testing.mjs +159 -0
  71. package/dist/index.cjs +246 -178
  72. package/dist/index.d.ts +9 -35
  73. package/dist/index.js +120 -52
  74. package/dist/index.mjs +120 -52
  75. package/dist/observability/index.cjs +677 -0
  76. package/dist/observability/index.d.ts +79 -0
  77. package/dist/observability/index.js +677 -0
  78. package/dist/observability/index.mjs +677 -0
  79. package/dist/schedule-Fque9Abz.d.ts +70 -0
  80. package/dist/schema/index.cjs +25 -0
  81. package/dist/schema/index.d.ts +177 -0
  82. package/dist/schema/index.js +25 -0
  83. package/dist/schema/index.mjs +25 -0
  84. package/dist/server-C8hDXA74.d.ts +674 -0
  85. package/dist/{stream-FQm9h4Mg.d.ts → stream-dvSs0QS5.d.ts} +1 -1
  86. package/dist/tracer-B5tRH9H7.d.ts +230 -0
  87. package/dist/tracing-Dt9S_6V8.d.ts +148 -0
  88. package/package.json +27 -1
  89. package/dist/chunk-BDYEENHT.js +0 -224
  90. package/dist/chunk-MS34J5LY.cjs +0 -224
  91. package/dist/chunk-UMAZLXAB.mjs +0 -224
  92. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  93. package/dist/tracing-DNT9jEbr.d.ts +0 -106
package/README.md CHANGED
@@ -1,11 +1,30 @@
1
- # 🛠️ brass-runtime — Mini ZIO-like runtime in TypeScript
1
+ # brass-runtime
2
2
 
3
- A small experimental runtime inspired by **ZIO 2**, implemented in vanilla TypeScript and intentionally built without using `Promise` / `async`/`await` as the **primary semantic primitive**.
3
+ A ZIO-inspired effect runtime for TypeScript with structured concurrency, pull-based streams, and a production-grade HTTP client.
4
4
 
5
- `brass-runtime` is the foundation: it provides an effect system, fibers, scheduler, scopes, and streams.
6
- Higher-level modules (HTTP, streaming utilities, integrations) are built **on top of the runtime**, not baked into it.
5
+ Built without `Promise`/`async`/`await` as the primary semantic primitive. Effects are values lazy, composable, and cancelable by default.
7
6
 
8
- > You can still interop with the outside world (timers, fetch, Node APIs) via explicit, cancellable bridges such as `fromPromiseAbortable`.
7
+ ```bash
8
+ npm i brass-runtime
9
+ ```
10
+
11
+ ---
12
+
13
+ ## What it does
14
+
15
+ **Core runtime** — algebraic effects, fibers, scopes, scheduler, layers, semaphores, circuit breakers, metrics, tracing.
16
+
17
+ **Streams** — pull-based with backpressure, bounded buffers, queues, hubs, pipelines, fusion optimization.
18
+
19
+ **HTTP client** — lazy/cancelable requests with a full middleware pipeline: adaptive concurrency, compression, batching, connection pre-warming, caching, deduplication, priority scheduling, and retry with backoff.
20
+
21
+ **Schema validation** — dependency-free runtime schemas for JSON, config, and protocol boundaries, with typed inference and path-rich validation issues.
22
+
23
+ **Observability export** — Prometheus metrics, OTLP metrics/traces/logs, structured logging, W3C trace-context propagation, request adapters, sampling, redaction, bounded exporters, and production flush/shutdown controls.
24
+
25
+ **WASM engine** — optional Rust/WASM-backed state machines for strict scheduling and bounded queues.
26
+
27
+ **Brass Agent** — experimental CLI coding agent with workspace inspection, LLM integration, and VS Code extension.
9
28
 
10
29
  ---
11
30
 
@@ -15,141 +34,373 @@ Higher-level modules (HTTP, streaming utilities, integrations) are built **on to
15
34
  - **Async is explicit** — no hidden Promise semantics
16
35
  - **Concurrency is structured** — fibers, scopes, finalizers
17
36
  - **Side effects are interpreted** — not executed eagerly
18
- - **Higher-level APIs are libraries, not magic**
19
-
20
- If you like ZIO’s separation between `zio-core`, `zio-streams`, and `zio-http`, this project follows the same spirit.
37
+ - **Higher-level APIs are libraries** — HTTP, streams, agent are built on top of core
21
38
 
22
39
  ---
23
40
 
24
- ## Core concepts
41
+ ## Quick start
25
42
 
26
- - Sync core effect: `Effect<R, E, A>` and `Exit<E, A>`
27
- - Algebraic async representation: `Async<R, E, A>`
28
- - Cooperative `Scheduler` (observable / testable)
29
- - Lightweight `Fiber`s with interruption & finalizers
30
- - Structured `Scope`s for resource safety
31
- - ZStream-style streams with backpressure
43
+ ### Run an effect
32
44
 
33
- For new code that only needs the stable runtime surface, prefer
34
- `brass-runtime/core`. The package root remains broad for compatibility.
45
+ ```ts
46
+ import { Runtime, succeed } from "brass-runtime";
35
47
 
36
- ---
48
+ const runtime = Runtime.make({});
49
+ const value = await runtime.toPromise(succeed(42));
50
+ ```
37
51
 
38
- ## Install
52
+ ### Recommended HTTP client
39
53
 
40
- ```bash
41
- npm i brass-runtime
54
+ ```ts
55
+ import { makeDefaultHttpClient, s } from "brass-runtime/http";
56
+
57
+ const User = s.object({
58
+ id: s.number({ int: true }),
59
+ name: s.string({ minLength: 1 }),
60
+ role: s.enum(["admin", "user"] as const).optional(),
61
+ });
62
+
63
+ const http = makeDefaultHttpClient({
64
+ baseUrl: "https://api.example.com",
65
+ headers: { accept: "application/json" },
66
+ });
67
+
68
+ const user = await http.getJson("/users/1", { schema: User }).unsafeRunPromise();
69
+
70
+ console.log(user.body.name);
71
+ console.log(http.stats());
72
+ console.log(http.compression?.stats());
42
73
  ```
43
74
 
44
- ---
75
+ `makeDefaultHttpClient` is the batteries-included entrypoint: timeout,
76
+ deduplication, priority scheduling, retry, adaptive concurrency, safe-method
77
+ response cache, decompression, stats, `cancelAll`, and JSON/text helpers. Use
78
+ `preset: "balanced"` to skip the default cache, or `preset: "minimal"` for a
79
+ cheap wire client with the same helper API.
45
80
 
46
- ## Quick start
81
+ The HTTP stack is meant to replace the usual `fetch` wrapper plus Zod/Valibot
82
+ glue: schemas are dependency-free, responses and request bodies are validated in
83
+ the same effect, config validation fails at construction time, and the client
84
+ still owns cancellation, retries, compression, observability, and adaptive
85
+ limits as one pipeline.
47
86
 
48
- ### Run an effect
87
+ The default adaptive limiter uses the `aggressive` preset: warmup sample floor,
88
+ P5 baseline, error-rate signal, priority-aware queueing, jittered probes,
89
+ proportional headroom, capped decreases, and TTL-evicted per-key state.
90
+ Call `shutdown()` for explicit cleanup.
91
+
92
+ The same schema DSL is available outside HTTP:
93
+
94
+ ```ts
95
+ import { Schema } from "brass-runtime/schema";
96
+
97
+ const Config = Schema.object({
98
+ port: Schema.int({ min: 1 }),
99
+ callbackUrl: Schema.url(),
100
+ });
101
+
102
+ const config = Config.parse({ port: 3000, callbackUrl: "https://example.com/cb" });
103
+ ```
104
+
105
+ Schemas can validate request bodies before the HTTP request is sent:
106
+
107
+ ```ts
108
+ import { Schema } from "brass-runtime/schema";
109
+
110
+ const CreateUser = Schema.object({
111
+ name: Schema.string({ minLength: 1 }),
112
+ });
113
+
114
+ await http.postJson(
115
+ "/users",
116
+ { name: "Ada" },
117
+ { bodySchema: CreateUser, schema: User }
118
+ ).unsafeRunPromise();
119
+ ```
120
+
121
+ The same validation machinery checks runtime, HTTP, and observability configs
122
+ at construction time, so invalid values fail with field paths like
123
+ `$.otlp.pipeline.batchSize` instead of surfacing later as ambiguous behavior.
124
+
125
+ ### Discoverable HTTP builder
49
126
 
50
127
  ```ts
51
- import { Runtime, succeed, toPromise } from "brass-runtime";
128
+ import { httpClientBuilder } from "brass-runtime/http";
129
+
130
+ declare const token: string;
131
+
132
+ const http = httpClientBuilder()
133
+ .baseUrl("https://api.example.com")
134
+ .balanced()
135
+ .balancedLimiter({ maxLimit: 128 })
136
+ .header("authorization", `Bearer ${token}`)
137
+ .cache({ ttlSeconds: 30, maxEntries: 512 })
138
+ .retry({ maxRetries: 2, baseDelayMs: 100, maxDelayMs: 1_000 })
139
+ .build();
140
+ ```
52
141
 
53
- const runtime = new Runtime({ env: {} });
142
+ ### HTTP test helpers
54
143
 
55
- const value = await toPromise(succeed(123), runtime.env);
56
- console.log(value); // 123
144
+ ```ts
145
+ import {
146
+ makeJsonHttpResponse,
147
+ makeMockHttpClient,
148
+ runHttpEffect,
149
+ } from "brass-runtime/http/testing";
150
+
151
+ const mock = makeMockHttpClient((req) => makeJsonHttpResponse({ url: req.url }));
152
+ const response = await runHttpEffect(mock({ method: "GET", url: "/users/1" }));
57
153
  ```
58
154
 
59
- ### Structured concurrency with Scope
155
+ Domain-specific layers still fit in the same config:
60
156
 
61
157
  ```ts
62
- import { Runtime, withScope } from "brass-runtime";
158
+ const http = makeDefaultHttpClient({
159
+ baseUrl: "https://api.example.com",
160
+ batch: {
161
+ windowMs: 50,
162
+ maxBatchSize: 20,
163
+ batchKey: (req) => req.url.startsWith("/graphql") ? "graphql" : "",
164
+ batch: {
165
+ coalesce: (reqs) => ({ method: "POST", url: "/graphql/batch", body: JSON.stringify(reqs) }),
166
+ split: (res, reqs) => JSON.parse(res.bodyText),
167
+ },
168
+ },
169
+ });
63
170
 
64
- const runtime = new Runtime({ env: {} });
171
+ const response = await http.getJson<User>("/users/1").unsafeRunPromise();
172
+ ```
173
+
174
+ ### Adaptive concurrency
65
175
 
66
- withScope(runtime, (scope) => {
67
- const f = scope.fork(/* Async effect */);
68
- // later...
69
- scope.close(); // interrupts child fibers + runs finalizers
176
+ ```ts
177
+ import { makeAdaptiveLimiterConfig, makeHttp } from "brass-runtime/http";
178
+
179
+ const http = makeHttp({
180
+ adaptiveLimiter: makeAdaptiveLimiterConfig("balanced", {
181
+ maxLimit: 100,
182
+ stateTtlMs: 300_000,
183
+ warmupRequests: 20,
184
+ minSamples: 25,
185
+ decreaseCooldownSamples: 3,
186
+ decreaseThreshold: 0.6,
187
+ maxDecreaseRatio: 0.15,
188
+ historySize: 64,
189
+ onLimitChange: (event) => console.log(`limit: ${event.previousLimit} → ${event.newLimit}`),
190
+ }),
70
191
  });
192
+
193
+ console.log(http.adaptiveLimiter?.dump());
194
+ console.log(http.adaptiveLimiter?.history("https://api.example.com"));
195
+ http.shutdown?.();
71
196
  ```
72
197
 
73
- > `toPromise` is just a convenience bridge for examples/DX. The runtime semantics remain explicit.
198
+ More end-to-end examples live in [`docs/http-recipes.md`](docs/http-recipes.md).
74
199
 
75
- ---
200
+ ### Connection pre-warming
201
+
202
+ ```ts
203
+ import { makePrewarmManager } from "brass-runtime/http";
76
204
 
77
- ## Modules built on top of brass-runtime
205
+ const prewarm = makePrewarmManager({
206
+ origins: ["https://api.example.com", "https://cdn.example.com"],
207
+ keepAliveDurationMs: 55000,
208
+ autoRefresh: true,
209
+ });
78
210
 
79
- These are optional layers, implemented using the runtime primitives.
211
+ await prewarm.warmAll();
212
+ // Subsequent requests skip TCP+TLS handshake
213
+ ```
80
214
 
81
- ### 🌐 HTTP client (brass-http layer)
215
+ ### Response compression
82
216
 
83
- A ZIO-style HTTP client built on top of fibers and `Async`.
217
+ ```ts
218
+ import { makeCompressionMiddleware, makeDefaultHttpClient } from "brass-runtime/http";
84
219
 
85
- - Lazy & cancelable HTTP requests
86
- - Explicit wire/content separation
87
- - Middleware-friendly (logging, retry, timeout, etc.)
88
- - Integrated with fiber interruption via `AbortController`
220
+ const { middleware, stats } = makeCompressionMiddleware({ encodings: ["br", "gzip"] });
221
+ const baseClient = makeDefaultHttpClient({
222
+ baseUrl: "https://api.example.com",
223
+ compression: false,
224
+ });
225
+ const client = baseClient.with(middleware);
226
+ // Responses are transparently decompressed (gzip, brotli, deflate)
227
+ ```
89
228
 
90
- 👉 **Docs:** [HTTP module](./docs/http.md)
229
+ ### Production observability
91
230
 
92
- Example:
231
+ ```ts
232
+ import { Runtime, asyncSucceed } from "brass-runtime/core";
233
+ import {
234
+ makeObservability,
235
+ runObservedHttpServerEffect,
236
+ withHttpObservability,
237
+ } from "brass-runtime/observability";
238
+ import { makeDefaultHttpClient } from "brass-runtime/http";
239
+
240
+ const obs = makeObservability({
241
+ serviceName: "api",
242
+ logs: { minLevel: "info" },
243
+ sampling: { ratio: 0.25, respectRemoteSampled: true, forceSampleOnError: true },
244
+ redaction: {},
245
+ cardinality: { maxValuesPerLabel: 100 },
246
+ otlp: {
247
+ metricsUrl: "http://collector:4318/v1/metrics",
248
+ tracesUrl: "http://collector:4318/v1/traces",
249
+ logsUrl: "http://collector:4318/v1/logs",
250
+ },
251
+ flushIntervalMs: 10_000,
252
+ });
253
+
254
+ const runtime = new Runtime({ env: obs.env, hooks: obs.hooks });
255
+ const client = makeDefaultHttpClient({
256
+ baseUrl: "https://api.example.com",
257
+ middleware: [withHttpObservability(obs)],
258
+ });
259
+
260
+ await runObservedHttpServerEffect(
261
+ obs,
262
+ { method: "GET", route: "/users/:id" },
263
+ asyncSucceed("ok")
264
+ );
265
+ await runtime.toPromise(client.getText("/health"));
266
+ await obs.shutdown();
267
+ ```
268
+
269
+ HTTP client observability automatically reads adaptive limiter diagnostics when
270
+ the wrapped client owns a limiter, exposing gauges for current limit, queue
271
+ depth, utilization, error rate, request/completion rate, rejection rate, and
272
+ state count.
273
+
274
+ ### Structured concurrency
93
275
 
94
276
  ```ts
95
- import { Runtime, toPromise } from "brass-runtime";
96
- import { httpClient } from "brass-runtime/http";
277
+ import { Runtime, asyncSucceed, withScope } from "brass-runtime";
97
278
 
98
- type Post = { id: number; title: string; body: string };
279
+ const runtime = Runtime.make({});
99
280
 
100
- const runtime = new Runtime({ env: {} });
281
+ await runtime.toPromise(
282
+ withScope(runtime, (scope) => {
283
+ scope.fork(asyncSucceed("child"));
284
+ // scope close interrupts children + runs finalizers
285
+ })
286
+ );
287
+ ```
101
288
 
102
- const client = httpClient({ baseUrl: "https://jsonplaceholder.typicode.com" });
289
+ ### Streams
103
290
 
104
- const res = await toPromise(client.getJson<Post>("/posts/1"), runtime.env);
105
- console.log(res.status, res.body.title);
291
+ ```ts
292
+ import { Runtime, collectStream, fromArray, mapP, via } from "brass-runtime";
293
+
294
+ const runtime = Runtime.make({});
295
+ const numbers = fromArray([1, 2, 3, 4, 5]);
296
+ const doubled = via(numbers, mapP((n: number) => n * 2));
297
+ const result = await runtime.toPromise(collectStream(doubled));
298
+ // [2, 4, 6, 8, 10]
106
299
  ```
107
300
 
108
301
  ---
109
302
 
110
- ### 🤖 Brass Agent (experimental)
303
+ ## Package exports
304
+
305
+ | Import | Purpose |
306
+ |--------|---------|
307
+ | `brass-runtime` | Core runtime: effects, fibers, scheduler, streams, layers |
308
+ | `brass-runtime/core` | Stable core surface (preferred for new code) |
309
+ | `brass-runtime/http` | Default HTTP client factory, lifecycle middleware, compression, batching, prewarm, adaptive limiter |
310
+ | `brass-runtime/http/testing` | Dependency-free mock clients, mock fetch, response factories, and effect runner helpers |
311
+ | `brass-runtime/schema` | Dependency-free runtime schema DSL with type inference |
312
+ | `brass-runtime/observability` | Prometheus/OTLP exporters, logs, spans, trace propagation, request adapters |
313
+ | `brass-runtime/agent` | Brass Agent core (experimental) |
111
314
 
112
- A CLI-first coding agent built on top of the runtime. Brass Agent is currently experimental: it can inspect a workspace, discover validation commands, gather bounded context, ask an LLM for a patch, apply/rollback patches through explicit policies, and expose a thin VS Code extension over the CLI protocol.
315
+ CLI: `brass-agent`
113
316
 
114
- Start here:
317
+ ---
115
318
 
116
- - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
117
- - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
118
- - [Brass Agent CLI](./docs/agent-cli.md)
119
- - [Project intelligence](./docs/agent-project-intelligence.md)
120
- - [Global usage and workspace discovery](./docs/agent-global-usage.md)
121
- - [VS Code local install](./docs/agent-vscode-install.md)
122
- - [VS Code auto-discovery](./docs/agent-vscode-auto-discovery.md)
123
- - [VS Code model setup](./docs/agent-vscode-model-setup.md)
124
- - [VS Code chat layout / focus mode](./docs/agent-vscode-chat-layout.md)
319
+ ## HTTP middleware pipeline
125
320
 
126
- ```bash
127
- npm run agent:vscode:install
128
- # then open any repo in VS Code and use Brass Agent -> Chat
321
+ The lifecycle client composes middleware in this order (innermost to outermost):
129
322
 
130
- npm run build
131
- npm run agent:link
132
- brass-agent --where
133
- brass-agent --doctor
134
- brass-agent --init
135
- brass-agent --preset inspect
136
323
  ```
324
+ Wire → Priority → Retry → Cache → Batch → Dedup
325
+ ```
326
+
327
+ Adaptive limiting lives in the wire client, before lifecycle middleware.
328
+ `makeDefaultHttpClient` can then wrap the lifecycle stack with response
329
+ compression and caller middleware; caller middleware is outermost.
330
+
331
+ Each layer is independently optional. Set to `false` or omit to disable.
332
+
333
+ | Layer | What it does |
334
+ |-------|-------------|
335
+ | **Adaptive Limiter** | Gradient-based dynamic concurrency control per origin |
336
+ | **Priority** | Priority queue for request scheduling (0-9 levels) |
337
+ | **Retry** | Exponential backoff with circuit breaker awareness |
338
+ | **Cache** | LRU + TTL + stale-while-revalidate |
339
+ | **Batch** | Time-window request coalescing with split/distribute |
340
+ | **Dedup** | Ref-counted in-flight request deduplication |
341
+ | **Compression** | Transparent gzip/br/deflate decompression |
342
+ | **Prewarm** | Proactive TCP+TLS connection establishment |
343
+
344
+ All layers emit lifecycle events, track stats, and support cancellation.
345
+
346
+ The recommended `makeDefaultHttpClient` factory wires the default preset
347
+ for you and accepts extra middleware, so observability can be attached with
348
+ `middleware: [withHttpObservability(obs)]` without coupling HTTP to exporters.
137
349
 
138
350
  ---
139
351
 
140
- ### 🌊 Streams (ZStream-like)
352
+ ## WASM engine
141
353
 
142
- Pull-based, resource-aware streams with backpressure.
354
+ Optional Rust/WASM-backed components for strict execution:
143
355
 
144
- - `ZStream<R, E, A>`
145
- - `Pull` semantics
146
- - Bounded buffers
147
- - Deterministic resource cleanup
356
+ - Fiber engine state machine
357
+ - Scheduler queue
358
+ - Bounded queues
359
+ - Permit pool
360
+ - Retry planner
148
361
 
149
- Examples:
362
+ ```bash
363
+ npm run build:wasm # requires wasm-pack
364
+ ```
150
365
 
151
- - `src/examples/fromPromise.ts`
152
- - `src/examples/mergeStreamSync.ts`
366
+ The WASM engine never silently falls back to TypeScript — if you request WASM and it's unavailable, it fails explicitly.
367
+
368
+ ---
369
+
370
+ ## Brass Agent (experimental)
371
+
372
+ A CLI-first coding agent built on the runtime. Inspects workspaces, discovers validation commands, gathers bounded context, asks an LLM for patches, and applies/rolls back changes under policy.
373
+
374
+ ```bash
375
+ npm run agent:vscode:install # VS Code extension
376
+ brass-agent --doctor # check setup
377
+ brass-agent --init # initialize workspace
378
+ brass-agent --preset inspect # run inspection
379
+ ```
380
+
381
+ Docs: [Install](./docs/agent-install-and-configure.md) · [CLI](./docs/agent-cli.md) · [Project intelligence](./docs/agent-project-intelligence.md) · [VS Code](./docs/agent-vscode-install.md)
382
+
383
+ ---
384
+
385
+ ## Testing
386
+
387
+ ```bash
388
+ npm test # vitest suite
389
+ npm run test:types # TypeScript type checking
390
+ npm run test:coverage # coverage with baseline gate
391
+ npm run benchmark # runtime, HTTP lifecycle, and 100k local HTTP concurrency
392
+ npm run benchmark -- http-concurrent # HTTP compare mode variants
393
+ node --expose-gc --import tsx src/benchmarks/runner.ts http-concurrent # HTTP memory/limiter diagnostics
394
+ npm run benchmark:adaptive
395
+ npm run benchmark:adaptive:soak
396
+ npm run benchmark:http:budget
397
+ npm run benchmark:http:soak
398
+ npm run benchmark:observability
399
+ npm run benchmark:observability:budget
400
+ npm run smoke:observability:collector # requires local OTEL collector
401
+ ```
402
+
403
+ Property-based tests use `fast-check` with 100+ iterations per property. Each HTTP middleware has dedicated property tests verifying correctness invariants.
153
404
 
154
405
  ---
155
406
 
@@ -159,79 +410,100 @@ Examples:
159
410
  - [Architecture](./docs/ARCHITECTURE.md)
160
411
  - [Cancellation & Interruption](./docs/cancellation.md)
161
412
  - [Observability: Hooks & Tracing](./docs/observability.md)
413
+ - [Observability framework examples](./docs/observability-framework-examples.md)
414
+ - [Observability collector smoke](./docs/observability-collector-smoke.md)
162
415
  - [HTTP module](./docs/http.md)
163
- - [Modules overview](./docs/modules.md)
164
- - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
165
- - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
166
-
167
- ---
168
-
169
- ## What’s new (recent changes)
170
-
171
- - Stream buffering with backpressure (`buffer`)
172
- - Abortable async integration (`fromPromiseAbortable`)
173
- - Fiber-safe `toPromise` for examples & DX
174
- - HTTP client module built on top of the runtime
416
+ - [Production readiness](./docs/production-readiness.md)
417
+ - [Streams guide](./docs/guides/streams.md)
418
+ - [Testing guide](./docs/guides/testing.md)
419
+ - [WASM engine](./docs/wasm-fiber-engine.md)
175
420
 
176
421
  ---
177
422
 
178
- ## Features (status)
423
+ ## Features
179
424
 
180
425
  ### Runtime (core)
181
426
 
182
- - [x] Sync core: `Effect`
183
- - [x] Async algebra: `Async`
184
- - [x] Cooperative `Scheduler`
427
+ - [x] Sync effect values via `ZIO<R, E, A>` aliases
428
+ - [x] Algebraic async: `Async<R, E, A>`
429
+ - [x] Cooperative scheduler (observable, testable)
185
430
  - [x] Fibers with interruption & finalizers
186
- - [x] Structured `Scope`
187
- - [x] Resource safety (`acquireRelease`)
188
-
189
- ### Concurrency & Streams
190
-
191
- - [x] `race`, `zipPar`, `collectAllPar`
192
- - [x] ZStream-like core
193
- - [x] Bounded buffers & backpressure
194
- - [x] Stream merge / zip
195
- - [x] Hubs / Broadcast
196
- - [x] Pipelines (`ZPipeline`-style)
197
-
198
- ### Libraries
199
-
200
- - [x] HTTP client
201
- - [ ] Retry / timeout middleware
202
- - [ ] Logging / metrics layers
431
+ - [x] Structured scopes & resource safety
432
+ - [x] Layers, semaphores, circuit breakers
433
+ - [x] Metrics, tracing, runtime hooks
434
+ - [x] Worker pools
435
+ - [x] WASM engine (optional)
436
+
437
+ ### Streams
438
+
439
+ - [x] Pull-based streams with backpressure
440
+ - [x] Bounded buffers, queues, hubs
441
+ - [x] Pipelines with fusion optimization
442
+ - [x] Stream merge, zip, broadcast
443
+ - [x] Chunks & batch operators
444
+
445
+ ### HTTP
446
+
447
+ - [x] Lazy, cancelable HTTP client
448
+ - [x] Schema-validated JSON helpers
449
+ - [x] Discoverable builder API
450
+ - [x] Test helper subpath
451
+ - [x] Lifecycle client with middleware composition
452
+ - [x] Response cache (LRU + TTL + SWR)
453
+ - [x] Request deduplication (ref-counted)
454
+ - [x] Priority scheduling
455
+ - [x] Retry with exponential backoff
456
+ - [x] Response compression (gzip, br, deflate)
457
+ - [x] Request batching (time-window coalesce/split)
458
+ - [x] Connection pre-warming (probes, auto-refresh)
459
+ - [x] Adaptive concurrency (gradient-based)
460
+ - [x] Adaptive limiter presets, diagnostics, observability gauges, and soak benchmark
461
+ - [x] Circuit breaker
462
+ - [x] Tracing & validation
463
+
464
+ ### Schema
465
+
466
+ - [x] Dependency-free schema DSL
467
+ - [x] Type inference via `InferSchema`
468
+ - [x] Object, array, record, union, enum, literal, custom schemas
469
+ - [x] Optional, nullable, refine, transform
470
+ - [x] Path-rich validation issues
471
+
472
+ ### Observability
473
+
474
+ - [x] Runtime metrics sink and Prometheus exporter
475
+ - [x] OTLP JSON/HTTP exporters for metrics, traces, and logs
476
+ - [x] Structured logging with context propagation and redaction
477
+ - [x] W3C trace-context extract/inject helpers
478
+ - [x] Client and server HTTP observability helpers
479
+ - [x] Adaptive limiter metrics on HTTP client spans and Prometheus gauges
480
+ - [x] Sampling, force-sample-on-error, and bounded trace retention
481
+ - [x] Bounded exporter queues with retry, timeout, drop policy, and single-flight flush
482
+ - [x] Fetch/Node/Express/Fastify/Nest-style examples and collector smoke script
203
483
 
204
484
  ---
205
485
 
206
486
  ## Design notes
207
487
 
208
- - **No hidden Promises**: async is always modeled explicitly
209
- - **Deterministic execution**: scheduler is observable & testable
210
- - **Resource safety is structural**: scopes guarantee cleanup
211
- - **Libraries compose via functions**: middleware, not inheritance
488
+ - **No hidden Promises** async is always modeled explicitly via `Async`
489
+ - **Deterministic execution** scheduler is observable and testable
490
+ - **Resource safety is structural** scopes guarantee cleanup
491
+ - **Middleware composes via functions** `(next: HttpClientFn) => HttpClientFn`
492
+ - **Cancellation propagates** — ref-counted through the entire middleware stack
493
+ - **Stats are frozen snapshots** — no mutable state leaks to consumers
212
494
 
213
495
  ---
214
496
 
215
497
  ## Contributing
216
498
 
217
- - Runtime invariants matter — avoid sneaking Promises into semantics
218
- - Prefer libraries on top of the runtime over changes in the core
219
- - Small, focused PRs are welcome (your repo may enforce PR-only changes)
499
+ - Runtime invariants matter — avoid sneaking Promises into core semantics
500
+ - Prefer libraries on top of the runtime over changes in core
501
+ - Add property tests when an invariant is broad
502
+ - Keep tests close to the changed module
503
+ - Small, focused PRs are welcome
220
504
 
221
505
  ---
222
506
 
223
507
  ## License
224
508
 
225
- MIT License © 2025
226
-
227
- ## Brass Agent local smoke tests
228
-
229
- Run local smoke tests without CI or a real LLM provider:
230
-
231
- ```bash
232
- npm run agent:test:local
233
- ```
234
-
235
- This builds the project and runs a fake-LLM smoke test against the `brass-agent` CLI.
236
-
237
- See also: [Agent language and workspace setup UX](docs/agent-language-workspace-ux.md).
509
+ MIT © 2025