brass-runtime 1.14.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 (90) hide show
  1. package/README.md +410 -135
  2. package/dist/agent/cli/main.cjs +49 -43
  3. package/dist/agent/cli/main.js +11 -5
  4. package/dist/agent/cli/main.mjs +11 -5
  5. package/dist/agent/index.cjs +8 -3
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +7 -2
  8. package/dist/agent/index.mjs +7 -2
  9. package/dist/{chunk-BMRF4FN6.js → chunk-2WC63LJK.mjs} +68 -242
  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-7HUOJA4W.cjs +493 -0
  14. package/dist/{chunk-4N2JEK4H.mjs → chunk-7LVI2GIN.js} +252 -495
  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-CY33PGEX.mjs +1110 -0
  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-G3XGCZDQ.js +131 -0
  24. package/dist/{chunk-JT7D6M5H.js → chunk-G6IQOE4P.mjs} +252 -495
  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-J3H54ZRV.mjs +131 -0
  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-XTMZTVIT.cjs → chunk-N6VHMOWB.cjs} +140 -134
  36. package/dist/{chunk-WJESVBWN.js → chunk-NC5SDRYE.js} +16 -10
  37. package/dist/chunk-NOYZIMUJ.mjs +144 -0
  38. package/dist/chunk-NYL4D7SK.cjs +131 -0
  39. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  40. package/dist/{chunk-UWMMYKVK.mjs → chunk-OOGJ73B6.js} +68 -242
  41. package/dist/chunk-PNVFW245.js +144 -0
  42. package/dist/chunk-PRWCB3QL.mjs +2491 -0
  43. package/dist/chunk-QY5FKYEQ.js +1110 -0
  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-BKBFSOGT.cjs → chunk-WQ5QNU5R.cjs} +460 -703
  51. package/dist/chunk-XDZOO4L5.js +354 -0
  52. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  53. package/dist/{chunk-MQF7HZ7Y.mjs → chunk-ZGLD4TVZ.mjs} +16 -10
  54. package/dist/client-CtFmoDvM.d.ts +645 -0
  55. package/dist/core/index.cjs +284 -0
  56. package/dist/core/index.d.ts +567 -0
  57. package/dist/core/index.js +284 -0
  58. package/dist/core/index.mjs +284 -0
  59. package/dist/{effect-DM56H743.d.ts → effect-CGNl5Rqp.d.ts} +118 -11
  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 +4130 -890
  64. package/dist/http/index.d.ts +2289 -219
  65. package/dist/http/index.js +4116 -876
  66. package/dist/http/index.mjs +4116 -876
  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 +305 -1168
  72. package/dist/index.d.ts +9 -701
  73. package/dist/index.js +176 -1039
  74. package/dist/index.mjs +176 -1039
  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-dvSs0QS5.d.ts +74 -0
  86. package/dist/tracer-B5tRH9H7.d.ts +230 -0
  87. package/dist/tracing-Dt9S_6V8.d.ts +148 -0
  88. package/package.json +37 -3
  89. package/dist/chunk-SKVY72E5.cjs +0 -667
  90. package/dist/stream-Oqe6WeLE.d.ts +0 -173
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,220 +34,476 @@ 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
- ---
45
+ ```ts
46
+ import { Runtime, succeed } from "brass-runtime";
34
47
 
35
- ## Install
48
+ const runtime = Runtime.make({});
49
+ const value = await runtime.toPromise(succeed(42));
50
+ ```
36
51
 
37
- ```bash
38
- npm i brass-runtime
52
+ ### Recommended HTTP client
53
+
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());
39
73
  ```
40
74
 
41
- ---
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.
42
80
 
43
- ## 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.
44
86
 
45
- ### 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:
46
93
 
47
94
  ```ts
48
- import { Runtime, succeed, toPromise } from "brass-runtime";
95
+ import { Schema } from "brass-runtime/schema";
49
96
 
50
- const runtime = new Runtime({ env: {} });
97
+ const Config = Schema.object({
98
+ port: Schema.int({ min: 1 }),
99
+ callbackUrl: Schema.url(),
100
+ });
51
101
 
52
- const value = await toPromise(succeed(123), runtime.env);
53
- console.log(value); // 123
102
+ const config = Config.parse({ port: 3000, callbackUrl: "https://example.com/cb" });
54
103
  ```
55
104
 
56
- ### Structured concurrency with Scope
105
+ Schemas can validate request bodies before the HTTP request is sent:
57
106
 
58
107
  ```ts
59
- import { Runtime, withScope } from "brass-runtime";
108
+ import { Schema } from "brass-runtime/schema";
109
+
110
+ const CreateUser = Schema.object({
111
+ name: Schema.string({ minLength: 1 }),
112
+ });
60
113
 
61
- const runtime = new Runtime({ env: {} });
114
+ await http.postJson(
115
+ "/users",
116
+ { name: "Ada" },
117
+ { bodySchema: CreateUser, schema: User }
118
+ ).unsafeRunPromise();
119
+ ```
62
120
 
63
- withScope(runtime, (scope) => {
64
- const f = scope.fork(/* Async effect */);
65
- // later...
66
- scope.close(); // interrupts child fibers + runs finalizers
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
126
+
127
+ ```ts
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
+ ```
141
+
142
+ ### HTTP test helpers
143
+
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" }));
153
+ ```
154
+
155
+ Domain-specific layers still fit in the same config:
156
+
157
+ ```ts
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
+ },
67
169
  });
170
+
171
+ const response = await http.getJson<User>("/users/1").unsafeRunPromise();
68
172
  ```
69
173
 
70
- > `toPromise` is just a convenience bridge for examples/DX. The runtime semantics remain explicit.
174
+ ### Adaptive concurrency
71
175
 
72
- ---
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
+ }),
191
+ });
73
192
 
74
- ## Modules built on top of brass-runtime
193
+ console.log(http.adaptiveLimiter?.dump());
194
+ console.log(http.adaptiveLimiter?.history("https://api.example.com"));
195
+ http.shutdown?.();
196
+ ```
75
197
 
76
- These are optional layers, implemented using the runtime primitives.
198
+ More end-to-end examples live in [`docs/http-recipes.md`](docs/http-recipes.md).
77
199
 
78
- ### 🌐 HTTP client (brass-http layer)
200
+ ### Connection pre-warming
79
201
 
80
- A ZIO-style HTTP client built on top of fibers and `Async`.
202
+ ```ts
203
+ import { makePrewarmManager } from "brass-runtime/http";
81
204
 
82
- - Lazy & cancelable HTTP requests
83
- - Explicit wire/content separation
84
- - Middleware-friendly (logging, retry, timeout, etc.)
85
- - Integrated with fiber interruption via `AbortController`
205
+ const prewarm = makePrewarmManager({
206
+ origins: ["https://api.example.com", "https://cdn.example.com"],
207
+ keepAliveDurationMs: 55000,
208
+ autoRefresh: true,
209
+ });
86
210
 
87
- 👉 **Docs:** [HTTP module](./docs/http.md)
211
+ await prewarm.warmAll();
212
+ // Subsequent requests skip TCP+TLS handshake
213
+ ```
88
214
 
89
- Example:
215
+ ### Response compression
90
216
 
91
217
  ```ts
92
- import { Runtime, toPromise } from "brass-runtime";
93
- import { httpClientStream } from "brass-runtime/http";
218
+ import { makeCompressionMiddleware, makeDefaultHttpClient } from "brass-runtime/http";
94
219
 
95
- type Post = { id: number; title: string; body: string };
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
+ ```
96
228
 
97
- const runtime = new Runtime({ env: {} });
229
+ ### Production observability
98
230
 
99
- const client = httpClientStream({ baseUrl: "https://jsonplaceholder.typicode.com" });
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
+ });
100
259
 
101
- const res = await toPromise(client.getJson<Post>("/posts/1"), runtime.env);
102
- console.log(res.status, res.value.title);
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();
103
267
  ```
104
268
 
105
- ---
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.
106
273
 
107
- ### 🤖 Brass Agent (experimental)
274
+ ### Structured concurrency
108
275
 
109
- 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.
276
+ ```ts
277
+ import { Runtime, asyncSucceed, withScope } from "brass-runtime";
110
278
 
111
- Start here:
279
+ const runtime = Runtime.make({});
112
280
 
113
- - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
114
- - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
115
- - [Brass Agent CLI](./docs/agent-cli.md)
116
- - [Project intelligence](./docs/agent-project-intelligence.md)
117
- - [Global usage and workspace discovery](./docs/agent-global-usage.md)
118
- - [VS Code local install](./docs/agent-vscode-install.md)
119
- - [VS Code auto-discovery](./docs/agent-vscode-auto-discovery.md)
120
- - [VS Code model setup](./docs/agent-vscode-model-setup.md)
121
- - [VS Code chat layout / focus mode](./docs/agent-vscode-chat-layout.md)
281
+ await runtime.toPromise(
282
+ withScope(runtime, (scope) => {
283
+ scope.fork(asyncSucceed("child"));
284
+ // scope close interrupts children + runs finalizers
285
+ })
286
+ );
287
+ ```
122
288
 
123
- ```bash
124
- npm run agent:vscode:install
125
- # then open any repo in VS Code and use Brass Agent -> Chat
289
+ ### Streams
126
290
 
127
- npm run build
128
- npm run agent:link
129
- brass-agent --where
130
- brass-agent --doctor
131
- brass-agent --init
132
- brass-agent --preset inspect
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]
133
299
  ```
134
300
 
135
301
  ---
136
302
 
137
- ### 🌊 Streams (ZStream-like)
303
+ ## Package exports
138
304
 
139
- Pull-based, resource-aware streams with backpressure.
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) |
140
314
 
141
- - `ZStream<R, E, A>`
142
- - `Pull` semantics
143
- - Bounded buffers
144
- - Deterministic resource cleanup
315
+ CLI: `brass-agent`
145
316
 
146
- Examples:
317
+ ---
147
318
 
148
- - `src/examples/fromPromise.ts`
149
- - `src/examples/mergeStreamSync.ts`
319
+ ## HTTP middleware pipeline
150
320
 
151
- ---
321
+ The lifecycle client composes middleware in this order (innermost to outermost):
152
322
 
153
- ## Docs
323
+ ```
324
+ Wire → Priority → Retry → Cache → Batch → Dedup
325
+ ```
154
326
 
155
- - [Getting Started](./docs/getting-started.md)
156
- - [Architecture](./docs/ARCHITECTURE.md)
157
- - [Cancellation & Interruption](./docs/cancellation.md)
158
- - [Observability: Hooks & Tracing](./docs/observability.md)
159
- - [HTTP module](./docs/http.md)
160
- - [Modules overview](./docs/modules.md)
161
- - [Install and configure Brass Agent](./docs/agent-install-and-configure.md)
162
- - [Declarative optimized planning roadmap](./docs/agent-declarative-optimized-planning.md)
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.
163
349
 
164
350
  ---
165
351
 
166
- ## What’s new (recent changes)
352
+ ## WASM engine
353
+
354
+ Optional Rust/WASM-backed components for strict execution:
355
+
356
+ - Fiber engine state machine
357
+ - Scheduler queue
358
+ - Bounded queues
359
+ - Permit pool
360
+ - Retry planner
361
+
362
+ ```bash
363
+ npm run build:wasm # requires wasm-pack
364
+ ```
167
365
 
168
- - Stream buffering with backpressure (`buffer`)
169
- - Abortable async integration (`fromPromiseAbortable`)
170
- - Fiber-safe `toPromise` for examples & DX
171
- - HTTP client module built on top of the runtime
366
+ The WASM engine never silently falls back to TypeScript — if you request WASM and it's unavailable, it fails explicitly.
172
367
 
173
368
  ---
174
369
 
175
- ## Features (status)
370
+ ## Brass Agent (experimental)
176
371
 
177
- ### Runtime (core)
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.
178
373
 
179
- - [x] Sync core: `Effect`
180
- - [x] Async algebra: `Async`
181
- - [x] Cooperative `Scheduler`
182
- - [x] Fibers with interruption & finalizers
183
- - [x] Structured `Scope`
184
- - [x] Resource safety (`acquireRelease`)
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
+ ```
185
380
 
186
- ### Concurrency & Streams
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)
187
382
 
188
- - [x] `race`, `zipPar`, `collectAllPar`
189
- - [x] ZStream-like core
190
- - [x] Bounded buffers & backpressure
191
- - [x] Stream merge / zip
192
- - [x] Hubs / Broadcast
193
- - [x] Pipelines (`ZPipeline`-style)
383
+ ---
384
+
385
+ ## Testing
194
386
 
195
- ### Libraries
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
+ ```
196
402
 
197
- - [x] HTTP client
198
- - [ ] Retry / timeout middleware
199
- - [ ] Logging / metrics layers
403
+ Property-based tests use `fast-check` with 100+ iterations per property. Each HTTP middleware has dedicated property tests verifying correctness invariants.
200
404
 
201
405
  ---
202
406
 
203
- ## Design notes
407
+ ## Docs
204
408
 
205
- - **No hidden Promises**: async is always modeled explicitly
206
- - **Deterministic execution**: scheduler is observable & testable
207
- - **Resource safety is structural**: scopes guarantee cleanup
208
- - **Libraries compose via functions**: middleware, not inheritance
409
+ - [Getting Started](./docs/getting-started.md)
410
+ - [Architecture](./docs/ARCHITECTURE.md)
411
+ - [Cancellation & Interruption](./docs/cancellation.md)
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)
415
+ - [HTTP module](./docs/http.md)
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)
209
420
 
210
421
  ---
211
422
 
212
- ## Contributing
423
+ ## Features
213
424
 
214
- - Runtime invariants matter — avoid sneaking Promises into semantics
215
- - Prefer libraries on top of the runtime over changes in the core
216
- - Small, focused PRs are welcome (your repo may enforce PR-only changes)
425
+ ### Runtime (core)
426
+
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)
430
+ - [x] Fibers with interruption & finalizers
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
217
483
 
218
484
  ---
219
485
 
220
- ## License
486
+ ## Design notes
221
487
 
222
- MIT License © 2025
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
223
494
 
224
- ## Brass Agent local smoke tests
495
+ ---
225
496
 
226
- Run local smoke tests without CI or a real LLM provider:
497
+ ## Contributing
227
498
 
228
- ```bash
229
- npm run agent:test:local
230
- ```
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
231
504
 
232
- This builds the project and runs a fake-LLM smoke test against the `brass-agent` CLI.
505
+ ---
506
+
507
+ ## License
233
508
 
234
- See also: [Agent language and workspace setup UX](docs/agent-language-workspace-ux.md).
509
+ MIT © 2025