brass-runtime 1.15.0 → 1.16.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.
Files changed (209) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +673 -136
  3. package/dist/agent/cli/main.cjs +40 -35
  4. package/dist/agent/cli/main.js +9 -4
  5. package/dist/agent/cli/main.mjs +9 -4
  6. package/dist/agent/index.cjs +8 -4
  7. package/dist/agent/index.d.ts +1 -1
  8. package/dist/agent/index.js +7 -3
  9. package/dist/agent/index.mjs +7 -3
  10. package/dist/chunk-2HQTDLHF.mjs +683 -0
  11. package/dist/chunk-36I3M4UC.mjs +370 -0
  12. package/dist/chunk-3AYM6WPJ.js +1629 -0
  13. package/dist/chunk-3LOYJFRR.cjs +300 -0
  14. package/dist/chunk-3RG5ZIWI.js +10 -0
  15. package/dist/chunk-3Y2RIUMM.js +300 -0
  16. package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
  17. package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
  18. package/dist/chunk-52PPNNI4.cjs +416 -0
  19. package/dist/chunk-5EC274J5.cjs +2874 -0
  20. package/dist/chunk-5QC7LRZ3.js +229 -0
  21. package/dist/chunk-5VRJNBLZ.mjs +2874 -0
  22. package/dist/chunk-62AZW6UT.cjs +313 -0
  23. package/dist/chunk-6IXXWIUM.js +683 -0
  24. package/dist/chunk-74ZTY6CP.js +2871 -0
  25. package/dist/chunk-76YMRMH2.cjs +777 -0
  26. package/dist/chunk-7CMJS3QE.mjs +2871 -0
  27. package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
  28. package/dist/chunk-A2OM6NEH.mjs +194 -0
  29. package/dist/chunk-AGR5B2BC.cjs +683 -0
  30. package/dist/chunk-AVNQLJ5V.js +777 -0
  31. package/dist/chunk-B33ICAKP.js +313 -0
  32. package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
  33. package/dist/chunk-BABBZK4Y.js +2024 -0
  34. package/dist/chunk-C3MDXTRZ.js +354 -0
  35. package/dist/chunk-CIZFIMK5.js +2193 -0
  36. package/dist/chunk-CZIVE6NT.cjs +354 -0
  37. package/dist/chunk-DNFJLJMW.mjs +354 -0
  38. package/dist/chunk-DNFO2EIZ.mjs +777 -0
  39. package/dist/chunk-EJ6BPYVR.mjs +416 -0
  40. package/dist/chunk-ENKODRU3.cjs +2193 -0
  41. package/dist/chunk-EOC4UHBS.mjs +229 -0
  42. package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
  43. package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
  44. package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
  45. package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
  46. package/dist/chunk-HLWLMW2F.mjs +2024 -0
  47. package/dist/chunk-JF5WGYJJ.cjs +194 -0
  48. package/dist/chunk-KH4SYAOS.mjs +1629 -0
  49. package/dist/chunk-KN32XNTH.mjs +313 -0
  50. package/dist/chunk-KQLYONSE.cjs +2871 -0
  51. package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
  52. package/dist/chunk-L2SYFEBS.js +194 -0
  53. package/dist/chunk-L6VB5N7Q.cjs +104 -0
  54. package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
  55. package/dist/chunk-MIIYDLGM.js +2874 -0
  56. package/dist/chunk-MOO4L7F4.mjs +104 -0
  57. package/dist/chunk-MT3OWDPC.mjs +2193 -0
  58. package/dist/chunk-MVGUEJ5Z.cjs +370 -0
  59. package/dist/chunk-OBGZSXTJ.cjs +10 -0
  60. package/dist/chunk-PD4EJTQC.cjs +229 -0
  61. package/dist/chunk-PWC3RBQE.mjs +300 -0
  62. package/dist/chunk-Q2I37RP3.cjs +1629 -0
  63. package/dist/chunk-RKGKFN2A.js +416 -0
  64. package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
  65. package/dist/chunk-TRM4JUZQ.js +104 -0
  66. package/dist/chunk-UB4B6OFY.js +370 -0
  67. package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
  68. package/dist/chunk-VN44DYYT.cjs +2024 -0
  69. package/dist/chunk-Y6FXYEAI.mjs +10 -0
  70. package/dist/client-CZHU674n.d.ts +820 -0
  71. package/dist/core/index.cjs +198 -4
  72. package/dist/core/index.d.ts +311 -212
  73. package/dist/core/index.js +237 -43
  74. package/dist/core/index.mjs +237 -43
  75. package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
  76. package/dist/effectRunner-CFLC32IK.cjs +8 -0
  77. package/dist/effectRunner-L4S7IPT3.js +8 -0
  78. package/dist/effectRunner-NNGG75QA.mjs +8 -0
  79. package/dist/http/index.cjs +1227 -2971
  80. package/dist/http/index.d.ts +826 -280
  81. package/dist/http/index.js +1089 -2833
  82. package/dist/http/index.mjs +1089 -2833
  83. package/dist/http/testing.cjs +161 -0
  84. package/dist/http/testing.d.ts +43 -0
  85. package/dist/http/testing.js +161 -0
  86. package/dist/http/testing.mjs +161 -0
  87. package/dist/index.cjs +486 -250
  88. package/dist/index.d.ts +87 -95
  89. package/dist/index.js +391 -155
  90. package/dist/index.mjs +391 -155
  91. package/dist/observability/index.cjs +162 -0
  92. package/dist/observability/index.d.ts +152 -0
  93. package/dist/observability/index.js +162 -0
  94. package/dist/observability/index.mjs +162 -0
  95. package/dist/perf/cli.cjs +401 -0
  96. package/dist/perf/cli.d.ts +1 -0
  97. package/dist/perf/cli.js +401 -0
  98. package/dist/perf/cli.mjs +401 -0
  99. package/dist/perf/index.cjs +141 -0
  100. package/dist/perf/index.d.ts +483 -0
  101. package/dist/perf/index.js +141 -0
  102. package/dist/perf/index.mjs +141 -0
  103. package/dist/schedule-CK3Ml_7p.d.ts +259 -0
  104. package/dist/schema/index.cjs +29 -0
  105. package/dist/schema/index.d.ts +179 -0
  106. package/dist/schema/index.js +29 -0
  107. package/dist/schema/index.mjs +29 -0
  108. package/dist/server-GJPg8ZSG.d.ts +675 -0
  109. package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
  110. package/dist/tracer-Hwt1cl7h.d.ts +189 -0
  111. package/dist/tracing-DqbTKGcf.d.ts +148 -0
  112. package/docs/ARCHITECTURE.md +292 -0
  113. package/docs/README.md +63 -0
  114. package/docs/adr/0001-ai-context-pack.md +32 -0
  115. package/docs/agent-apply-mode.md +104 -0
  116. package/docs/agent-approvals.md +110 -0
  117. package/docs/agent-batch.md +185 -0
  118. package/docs/agent-boundaries.md +112 -0
  119. package/docs/agent-chat-sessions.md +160 -0
  120. package/docs/agent-ci.md +17 -0
  121. package/docs/agent-cli.md +405 -0
  122. package/docs/agent-config.md +480 -0
  123. package/docs/agent-context-discovery.md +159 -0
  124. package/docs/agent-copilot-like-dx.md +126 -0
  125. package/docs/agent-declarative-optimized-planning.md +138 -0
  126. package/docs/agent-dx.md +224 -0
  127. package/docs/agent-env-files.md +126 -0
  128. package/docs/agent-follow-up-context.md +43 -0
  129. package/docs/agent-global-usage.md +180 -0
  130. package/docs/agent-init.md +109 -0
  131. package/docs/agent-install-and-configure.md +516 -0
  132. package/docs/agent-language-workspace-ux.md +99 -0
  133. package/docs/agent-llm-adapters.md +123 -0
  134. package/docs/agent-local-install.md +190 -0
  135. package/docs/agent-local-tests.md +51 -0
  136. package/docs/agent-observability.md +155 -0
  137. package/docs/agent-patch-quality-loop.md +162 -0
  138. package/docs/agent-presets.md +22 -0
  139. package/docs/agent-project-commands.md +237 -0
  140. package/docs/agent-project-intelligence.md +156 -0
  141. package/docs/agent-redaction.md +18 -0
  142. package/docs/agent-release-readiness.md +76 -0
  143. package/docs/agent-rollback-safety.md +162 -0
  144. package/docs/agent-rollback.md +23 -0
  145. package/docs/agent-run-artifacts.md +16 -0
  146. package/docs/agent-vscode-auto-discovery.md +137 -0
  147. package/docs/agent-vscode-batch-runner.md +100 -0
  148. package/docs/agent-vscode-chat-layout.md +90 -0
  149. package/docs/agent-vscode-clean-install.md +147 -0
  150. package/docs/agent-vscode-code-actions.md +70 -0
  151. package/docs/agent-vscode-diff-preview.md +45 -0
  152. package/docs/agent-vscode-inline-assist.md +56 -0
  153. package/docs/agent-vscode-install.md +186 -0
  154. package/docs/agent-vscode-model-setup.md +97 -0
  155. package/docs/agent-vscode-patch-preview.md +92 -0
  156. package/docs/agent-vscode-problems.md +79 -0
  157. package/docs/agent-vscode-project-dashboard.md +106 -0
  158. package/docs/agent-vscode-run-history.md +92 -0
  159. package/docs/agent-vscode-ux.md +73 -0
  160. package/docs/ai/INVARIANTS.md +84 -0
  161. package/docs/ai/PROJECT_MAP.md +338 -0
  162. package/docs/ai/PUBLIC_API.md +336 -0
  163. package/docs/ai/VALIDATION_MATRIX.md +67 -0
  164. package/docs/api-polish.md +37 -0
  165. package/docs/cancellation.md +162 -0
  166. package/docs/coverage.md +46 -0
  167. package/docs/getting-started.md +159 -0
  168. package/docs/guides/README.md +40 -0
  169. package/docs/guides/circuit-breaker.md +89 -0
  170. package/docs/guides/error-handling.md +91 -0
  171. package/docs/guides/getting-started.md +107 -0
  172. package/docs/guides/layers.md +189 -0
  173. package/docs/guides/metrics.md +101 -0
  174. package/docs/guides/resource-management.md +141 -0
  175. package/docs/guides/retry.md +215 -0
  176. package/docs/guides/semaphore.md +66 -0
  177. package/docs/guides/streams.md +117 -0
  178. package/docs/guides/supervisors.md +98 -0
  179. package/docs/guides/testing.md +162 -0
  180. package/docs/guides/tracing.md +71 -0
  181. package/docs/http-recipes.md +399 -0
  182. package/docs/http.md +749 -0
  183. package/docs/modules.md +285 -0
  184. package/docs/observability-collector-smoke.md +31 -0
  185. package/docs/observability-framework-examples.md +98 -0
  186. package/docs/observability.md +542 -0
  187. package/docs/otel-collector-smoke.yaml +27 -0
  188. package/docs/performance-profiler.md +199 -0
  189. package/docs/production-readiness.md +73 -0
  190. package/docs/recipes/README.md +12 -0
  191. package/docs/recipes/http-server.md +45 -0
  192. package/docs/recipes/layers.md +44 -0
  193. package/docs/recipes/performance.md +47 -0
  194. package/docs/recipes/runtime.md +41 -0
  195. package/docs/recipes/testing.md +41 -0
  196. package/docs/release.md +53 -0
  197. package/docs/wasm-bounded-queues.md +44 -0
  198. package/docs/wasm-engine-observability-benchmarks.md +85 -0
  199. package/docs/wasm-fiber-engine.md +117 -0
  200. package/docs/wasm-scheduler-state-machine.md +122 -0
  201. package/docs/wasm-stream-chunks.md +54 -0
  202. package/package.json +48 -2
  203. package/dist/chunk-AR22SXML.js +0 -1043
  204. package/dist/chunk-BDYEENHT.js +0 -224
  205. package/dist/chunk-JFPU5GQI.mjs +0 -1043
  206. package/dist/chunk-MS34J5LY.cjs +0 -224
  207. package/dist/chunk-UMAZLXAB.mjs +0 -224
  208. package/dist/chunk-XPZNXSVN.cjs +0 -1043
  209. package/dist/tracing-DNT9jEbr.d.ts +0 -106
package/README.md CHANGED
@@ -1,11 +1,39 @@
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,
4
+ runtime diagnostics, pull-based streams, and a production-grade HTTP client.
4
5
 
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.
6
+ Built without `Promise`/`async`/`await` as the primary semantic primitive. Effects are values lazy, composable, and cancelable by default.
7
7
 
8
- > You can still interop with the outside world (timers, fetch, Node APIs) via explicit, cancellable bridges such as `fromPromiseAbortable`.
8
+ ```bash
9
+ npm i brass-runtime
10
+ ```
11
+
12
+ ---
13
+
14
+ ## What it does
15
+
16
+ **Runtime** — algebraic effects, fibers, scopes, scheduler, interruptibility
17
+ regions, fiber-local refs, typed layers, semaphores, circuit breakers, rich
18
+ `Cause<E>` failures, metrics, tracing, and an opt-in flight recorder.
19
+
20
+ **Streams** — pull-based streams with backpressure, bounded buffers, hubs,
21
+ pipelines, fusion optimization, and a small fluent DX facade.
22
+
23
+ **HTTP** — lazy/cancelable client and server primitives with typed routing,
24
+ schema validation, health/readiness probes, adaptive concurrency, compression,
25
+ batching, prewarm, cache, dedup, priority, retry, and observability.
26
+
27
+ **Production signals** — dependency-free schemas, Prometheus/OTLP exporters,
28
+ structured logs, W3C trace propagation, sampling, redaction, bounded exporters,
29
+ and explicit flush/shutdown.
30
+
31
+ **Performance profiler** — runtime primitives, HTTP layer comparison, memory
32
+ retention reports, observability overhead, CLI/JSON output, and actionable
33
+ recommendations.
34
+
35
+ **Optional engine and tools** — Rust/WASM-backed state machines plus the
36
+ experimental Brass Agent CLI/VS Code workflow.
9
37
 
10
38
  ---
11
39
 
@@ -15,223 +43,732 @@ Higher-level modules (HTTP, streaming utilities, integrations) are built **on to
15
43
  - **Async is explicit** — no hidden Promise semantics
16
44
  - **Concurrency is structured** — fibers, scopes, finalizers
17
45
  - **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.
46
+ - **Higher-level APIs are libraries** — HTTP, streams, agent are built on top of core
21
47
 
22
48
  ---
23
49
 
24
- ## Core concepts
50
+ ## Quick start
25
51
 
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
52
+ ### Run an effect
32
53
 
33
- For new code that only needs the stable runtime surface, prefer
34
- `brass-runtime/core`. The package root remains broad for compatibility.
54
+ ```ts
55
+ import { runPromise, succeed } from "brass-runtime";
35
56
 
36
- ---
57
+ const value = await runPromise(succeed(42));
58
+ ```
37
59
 
38
- ## Install
60
+ Use `makeRuntime` when you want explicit runtime options, and `runExit` when
61
+ you want the full `Exit`/`Cause` instead of a rejected promise.
39
62
 
40
- ```bash
41
- npm i brass-runtime
63
+ ### Inspect failure causes
64
+
65
+ ```ts
66
+ import { Cause, formatCause } from "brass-runtime";
67
+
68
+ const cause = Cause.then(
69
+ Cause.fail("database unavailable"),
70
+ Cause.both(Cause.interrupt(), Cause.die(new Error("release failed"))),
71
+ );
72
+
73
+ console.log(formatCause(cause));
42
74
  ```
43
75
 
44
- ---
76
+ `Cause<E>` preserves typed failures, defects, interruptions, and sequential or
77
+ parallel composition (`Then` / `Both`) so diagnostics can explain what happened
78
+ without flattening every failure into a single thrown value.
45
79
 
46
- ## Quick start
80
+ ### Mask interruption
47
81
 
48
- ### Run an effect
82
+ ```ts
83
+ import { async, flatMap, succeed, uninterruptibleMask } from "brass-runtime";
84
+
85
+ const effect = uninterruptibleMask((restore) =>
86
+ flatMap(succeed("acquired"), (resource) =>
87
+ restore(async((_env, cb) => {
88
+ setTimeout(() => cb({ _tag: "Success", value: `used:${resource}` }), 10);
89
+ })),
90
+ ),
91
+ );
92
+ ```
93
+
94
+ Use `uninterruptible(effect)` for critical regions and
95
+ `uninterruptibleMask((restore) => ...)` when only part of the region should be
96
+ interruptible again. Pending interruption is deferred until the protected region
97
+ exits; restored sub-effects remain cancelable.
98
+
99
+ ### Fiber-local context
100
+
101
+ ```ts
102
+ import { Runtime, makeFiberRef } from "brass-runtime";
103
+
104
+ const requestId = makeFiberRef("anonymous");
105
+ const runtime = Runtime.make({});
106
+
107
+ const result = await runtime.toPromise(
108
+ requestId.locally("req-123", requestId.get()),
109
+ );
110
+ ```
111
+
112
+ `FiberRef` values are local to the running fiber, inherited by child fibers at
113
+ fork time, isolated from child mutations, and restored after `locally` regions
114
+ even when the region fails or is interrupted.
115
+
116
+ ### Explain runtime behavior
49
117
 
50
118
  ```ts
51
- import { Runtime, succeed, toPromise } from "brass-runtime";
119
+ import { Runtime, async, makeRuntimeRecorder } from "brass-runtime";
120
+
121
+ const recorder = makeRuntimeRecorder({ maxEvents: 5000 });
122
+ const runtime = new Runtime({ env: {}, hooks: recorder.hooks });
52
123
 
53
- const runtime = new Runtime({ env: {} });
124
+ await runtime.toPromise(async((_env, cb) => {
125
+ setTimeout(() => cb({ _tag: "Success", value: "ok" }), 10);
126
+ }));
54
127
 
55
- const value = await toPromise(succeed(123), runtime.env);
56
- console.log(value); // 123
128
+ console.log(recorder.explain());
57
129
  ```
58
130
 
59
- ### Structured concurrency with Scope
131
+ The flight recorder is opt-in and keeps a bounded ring buffer of runtime events:
132
+ fiber start/end/suspend/resume, scopes, supervisor events, logs, spans, and
133
+ trace context when available.
134
+
135
+ ### Recommended HTTP client
60
136
 
61
137
  ```ts
62
- import { Runtime, withScope } from "brass-runtime";
138
+ import { makeDefaultHttpClient, s } from "brass-runtime/http";
63
139
 
64
- const runtime = new Runtime({ env: {} });
140
+ const User = s.object({
141
+ id: s.number({ int: true }),
142
+ name: s.string({ minLength: 1 }),
143
+ role: s.enum(["admin", "user"] as const).optional(),
144
+ });
65
145
 
66
- withScope(runtime, (scope) => {
67
- const f = scope.fork(/* Async effect */);
68
- // later...
69
- scope.close(); // interrupts child fibers + runs finalizers
146
+ const http = makeDefaultHttpClient({
147
+ baseUrl: "https://api.example.com",
148
+ headers: { accept: "application/json" },
70
149
  });
150
+
151
+ const user = await http.getJson("/users/1", { schema: User }).unsafeRunPromise();
152
+
153
+ console.log(user.body.name);
154
+ console.log(http.stats());
155
+ console.log(http.compression?.stats());
71
156
  ```
72
157
 
73
- > `toPromise` is just a convenience bridge for examples/DX. The runtime semantics remain explicit.
158
+ `makeDefaultHttpClient` is the batteries-included entrypoint: timeout,
159
+ deduplication, priority scheduling, retry, adaptive concurrency, safe-method
160
+ response cache, decompression, stats, `cancelAll`, and JSON/text helpers. Use
161
+ `preset: "production"` when you want that production-ready shape explicitly,
162
+ `preset: "balanced"` to skip the default cache, or `preset: "minimal"` for a
163
+ cheap wire client with the same helper API. `preset: "default"` remains the
164
+ same full preset for compatibility.
74
165
 
75
- ---
166
+ The HTTP stack is meant to replace the usual `fetch` wrapper plus Zod/Valibot
167
+ glue: schemas are dependency-free, responses and request bodies are validated in
168
+ the same effect, config validation fails at construction time, and the client
169
+ still owns cancellation, retries, compression, observability, and adaptive
170
+ limits as one pipeline.
76
171
 
77
- ## Modules built on top of brass-runtime
172
+ Custom Promise clients such as Axios can be injected without making the
173
+ consumer manage `AbortSignal` or `Async` plumbing:
78
174
 
79
- These are optional layers, implemented using the runtime primitives.
175
+ ```ts
176
+ import {
177
+ defineHttpPolicyPresets,
178
+ formatHttpError,
179
+ isRetryableHttpError,
180
+ makeDefaultHttpClient,
181
+ promiseHttpTransport,
182
+ } from "brass-runtime/http";
183
+
184
+ const transport = promiseHttpTransport()
185
+ .requestConfig(({ request, url }) => ({
186
+ url: url.toString(),
187
+ method: request.method,
188
+ headers: request.headers,
189
+ data: request.body,
190
+ responseType: "json",
191
+ }))
192
+ .send((config) => axiosInstance.request(config))
193
+ .json();
194
+
195
+ const axiosHttp = makeDefaultHttpClient({
196
+ baseUrl: "https://api.example.com",
197
+ transport,
198
+ });
80
199
 
81
- ### 🌐 HTTP client (brass-http layer)
200
+ try {
201
+ await axiosHttp.getJson("/users/1").unsafeRunPromise();
202
+ } catch (error) {
203
+ if (isRetryableHttpError(error)) {
204
+ console.warn("transient upstream failure");
205
+ }
206
+ console.error(formatHttpError(error));
207
+ }
208
+ ```
82
209
 
83
- A ZIO-style HTTP client built on top of fibers and `Async`.
210
+ Brass injects the runtime `AbortSignal` into object configs before `send` and
211
+ normalizes external failures with `toHttpError`, including Axios-like
212
+ `response.status`, aborts, and common timeout codes.
84
213
 
85
- - Lazy & cancelable HTTP requests
86
- - Explicit wire/content separation
87
- - Middleware-friendly (logging, retry, timeout, etc.)
88
- - Integrated with fiber interruption via `AbortController`
214
+ Repeated execution intent can be named once with policy presets:
89
215
 
90
- 👉 **Docs:** [HTTP module](./docs/http.md)
216
+ ```ts
217
+ const policies = defineHttpPolicyPresets({
218
+ readModel: {
219
+ lane: "read-model",
220
+ poolKey: "users-api",
221
+ priority: 2,
222
+ retry: { maxRetries: 2, baseDelayMs: 50 },
223
+ },
224
+ });
91
225
 
92
- Example:
226
+ const http = makeDefaultHttpClient({
227
+ baseUrl: "https://api.example.com",
228
+ policyPresets: policies,
229
+ });
230
+
231
+ await http.getJson("/users/1", {
232
+ policy: { preset: "readModel", dedupKey: "users:1" },
233
+ }).unsafeRunPromise();
234
+ ```
235
+
236
+ The default adaptive limiter uses the `aggressive` preset: warmup sample floor,
237
+ P5 baseline, error-rate signal, priority-aware queueing, jittered probes,
238
+ proportional headroom, capped decreases, and TTL-evicted per-key state.
239
+ Call `shutdown()` for explicit cleanup.
240
+
241
+ The same schema DSL is available outside HTTP:
93
242
 
94
243
  ```ts
95
- import { Runtime, toPromise } from "brass-runtime";
96
- import { httpClient } from "brass-runtime/http";
244
+ import { Schema } from "brass-runtime/schema";
245
+
246
+ const Config = Schema.object({
247
+ port: Schema.int({ min: 1 }),
248
+ callbackUrl: Schema.url(),
249
+ });
97
250
 
98
- type Post = { id: number; title: string; body: string };
251
+ const config = Config.parse({ port: 3000, callbackUrl: "https://example.com/cb" });
252
+ ```
253
+
254
+ Schemas can validate request bodies before the HTTP request is sent:
99
255
 
100
- const runtime = new Runtime({ env: {} });
256
+ ```ts
257
+ import { Schema } from "brass-runtime/schema";
101
258
 
102
- const client = httpClient({ baseUrl: "https://jsonplaceholder.typicode.com" });
259
+ const CreateUser = Schema.object({
260
+ name: Schema.string({ minLength: 1 }),
261
+ });
103
262
 
104
- const res = await toPromise(client.getJson<Post>("/posts/1"), runtime.env);
105
- console.log(res.status, res.body.title);
263
+ await http.postJson(
264
+ "/users",
265
+ { name: "Ada" },
266
+ { bodySchema: CreateUser, schema: User }
267
+ ).unsafeRunPromise();
106
268
  ```
107
269
 
108
- ---
270
+ The same validation machinery checks runtime, HTTP, and observability configs
271
+ at construction time, so invalid values fail with field paths like
272
+ `$.otlp.pipeline.batchSize` instead of surfacing later as ambiguous behavior.
273
+
274
+ ### HTTP server
275
+
276
+ ```ts
277
+ import { asyncSucceed, asyncSync, runPromise, useResource } from "brass-runtime";
278
+ import { HttpServer, s } from "brass-runtime/http";
279
+
280
+ const User = s.object({
281
+ id: s.nonEmptyString(),
282
+ name: s.nonEmptyString(),
283
+ });
284
+
285
+ const router = HttpServer.router([
286
+ HttpServer.route("GET", "/users/:id", {
287
+ params: s.object({ id: s.nonEmptyString() }),
288
+ response: User,
289
+ }, (ctx) =>
290
+ asyncSucceed(HttpServer.json({
291
+ id: ctx.params.id,
292
+ name: "Ada",
293
+ })),
294
+ ),
295
+ HttpServer.healthRoute(),
296
+ HttpServer.readinessRoute(),
297
+ ]);
298
+
299
+ await runPromise(
300
+ useResource(
301
+ router.listen({ port: 3000 }),
302
+ (server) => asyncSync(() => {
303
+ console.log(server.url());
304
+ }),
305
+ ),
306
+ );
307
+ ```
308
+
309
+ Routes infer `:params` from the path, optional schemas validate
310
+ params/query/body/response, middleware is effect-based, and the Node listener is
311
+ available as a managed resource for graceful shutdown.
312
+
313
+ ### Discoverable HTTP builder
314
+
315
+ ```ts
316
+ import { httpClientBuilder } from "brass-runtime/http";
317
+
318
+ declare const token: string;
319
+
320
+ const http = httpClientBuilder()
321
+ .baseUrl("https://api.example.com")
322
+ .production()
323
+ .balancedLimiter({ maxLimit: 128 })
324
+ .header("authorization", `Bearer ${token}`)
325
+ .cache({ ttlSeconds: 30, maxEntries: 512 })
326
+ .retry({ maxRetries: 2, baseDelayMs: 100, maxDelayMs: 1_000 })
327
+ .build();
328
+ ```
329
+
330
+ ### HTTP test helpers
331
+
332
+ ```ts
333
+ import {
334
+ makeJsonHttpResponse,
335
+ makeMockHttpClient,
336
+ runHttpEffect,
337
+ } from "brass-runtime/http/testing";
338
+
339
+ const mock = makeMockHttpClient((req) => makeJsonHttpResponse({ url: req.url }));
340
+ const response = await runHttpEffect(mock({ method: "GET", url: "/users/1" }));
341
+ ```
342
+
343
+ Domain-specific layers still fit in the same config:
344
+
345
+ ```ts
346
+ const http = makeDefaultHttpClient({
347
+ baseUrl: "https://api.example.com",
348
+ batch: {
349
+ windowMs: 50,
350
+ maxBatchSize: 20,
351
+ batchKey: (req) => req.url.startsWith("/graphql") ? "graphql" : "",
352
+ batch: {
353
+ coalesce: (reqs) => ({ method: "POST", url: "/graphql/batch", body: JSON.stringify(reqs) }),
354
+ split: (res, reqs) => JSON.parse(res.bodyText),
355
+ },
356
+ },
357
+ });
358
+
359
+ const response = await http.getJson<User>("/users/1").unsafeRunPromise();
360
+ ```
361
+
362
+ ### Adaptive concurrency
363
+
364
+ ```ts
365
+ import { makeAdaptiveLimiterConfig, makeHttp } from "brass-runtime/http";
366
+
367
+ const http = makeHttp({
368
+ adaptiveLimiter: makeAdaptiveLimiterConfig("balanced", {
369
+ maxLimit: 100,
370
+ stateTtlMs: 300_000,
371
+ warmupRequests: 20,
372
+ minSamples: 25,
373
+ decreaseCooldownSamples: 3,
374
+ decreaseThreshold: 0.6,
375
+ maxDecreaseRatio: 0.15,
376
+ historySize: 64,
377
+ onLimitChange: (event) => console.log(`limit: ${event.previousLimit} → ${event.newLimit}`),
378
+ }),
379
+ });
380
+
381
+ console.log(http.adaptiveLimiter?.dump());
382
+ console.log(http.adaptiveLimiter?.history("https://api.example.com"));
383
+ http.shutdown?.();
384
+ ```
109
385
 
110
- ### 🤖 Brass Agent (experimental)
386
+ More end-to-end examples live in [`docs/http-recipes.md`](docs/http-recipes.md).
111
387
 
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.
388
+ ### Connection pre-warming
113
389
 
114
- Start here:
390
+ ```ts
391
+ import { makePrewarmManager } from "brass-runtime/http";
392
+
393
+ const prewarm = makePrewarmManager({
394
+ origins: ["https://api.example.com", "https://cdn.example.com"],
395
+ keepAliveDurationMs: 55000,
396
+ autoRefresh: true,
397
+ });
398
+
399
+ await prewarm.warmAll();
400
+ // Subsequent requests skip TCP+TLS handshake
401
+ ```
402
+
403
+ ### Response compression
115
404
 
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)
405
+ ```ts
406
+ import { makeCompressionMiddleware, makeDefaultHttpClient } from "brass-runtime/http";
407
+
408
+ const { middleware, stats } = makeCompressionMiddleware({ encodings: ["br", "gzip"] });
409
+ const baseClient = makeDefaultHttpClient({
410
+ baseUrl: "https://api.example.com",
411
+ compression: false,
412
+ });
413
+ const client = baseClient.with(middleware);
414
+ // Responses are transparently decompressed (gzip, brotli, deflate)
415
+ ```
416
+
417
+ ### Production observability
418
+
419
+ ```ts
420
+ import { Runtime, asyncSucceed } from "brass-runtime/core";
421
+ import {
422
+ makeObservability,
423
+ runObservedHttpServerEffect,
424
+ withHttpObservability,
425
+ } from "brass-runtime/observability";
426
+ import { makeDefaultHttpClient } from "brass-runtime/http";
427
+
428
+ const obs = makeObservability({
429
+ serviceName: "api",
430
+ logs: { minLevel: "info" },
431
+ sampling: { ratio: 0.25, respectRemoteSampled: true, forceSampleOnError: true },
432
+ redaction: {},
433
+ cardinality: { maxValuesPerLabel: 100 },
434
+ otlp: {
435
+ metricsUrl: "http://collector:4318/v1/metrics",
436
+ tracesUrl: "http://collector:4318/v1/traces",
437
+ logsUrl: "http://collector:4318/v1/logs",
438
+ },
439
+ flushIntervalMs: 10_000,
440
+ });
441
+
442
+ const runtime = new Runtime({ env: obs.env, hooks: obs.hooks });
443
+ const client = makeDefaultHttpClient({
444
+ baseUrl: "https://api.example.com",
445
+ middleware: [withHttpObservability(obs)],
446
+ });
447
+
448
+ await runObservedHttpServerEffect(
449
+ obs,
450
+ { method: "GET", route: "/users/:id" },
451
+ asyncSucceed("ok")
452
+ );
453
+ await runtime.toPromise(client.getText("/health"));
454
+ await obs.shutdown();
455
+ ```
456
+
457
+ HTTP client observability automatically reads adaptive limiter diagnostics when
458
+ the wrapped client owns a limiter, exposing gauges for current limit, queue
459
+ depth, utilization, error rate, request/completion rate, rejection rate, and
460
+ state count.
461
+ It also reads `req.policy` automatically: logs and span attributes include
462
+ `preset`, `lane`, `poolKey`, `dedupKey`, `priority`, and retry overrides when present.
463
+ Metric labels stay conservative by default; opt into stable labels with
464
+ `withHttpObservability({ policy: { labelKeys: ["preset", "lane", "poolKey"] } })`.
465
+
466
+ ### Performance profiler
125
467
 
126
468
  ```bash
127
- npm run agent:vscode:install
128
- # then open any repo in VS Code and use Brass Agent -> Chat
469
+ npm run perf
470
+ npm run perf:json
471
+ npm run benchmark:perf
472
+ npm run perf:runtime:ab
473
+ npm run perf:runtime:soak
474
+ npm run perf:runtime:budget
475
+ npm run perf:http:memory
476
+ npm run perf:history
477
+ ```
129
478
 
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
479
+ ```ts
480
+ import { runBrassPerformanceProfile } from "brass-runtime/perf";
481
+
482
+ const report = await runBrassPerformanceProfile({
483
+ http: {
484
+ calls: 20_000,
485
+ concurrency: 512,
486
+ delayMs: 2,
487
+ forceGc: true,
488
+ variants: ["default-json", "default-json-observed"],
489
+ },
490
+ });
491
+
492
+ console.log(report.recommendations);
136
493
  ```
137
494
 
138
- ---
495
+ The profiler compares runtime primitives, runtime A/B variants, runtime-only
496
+ soak behavior, `node:http`, Brass wire/default HTTP clients, HTTP long-run
497
+ memory, observability overhead, history/baseline regressions, and memory deltas. Use
498
+ [`docs/performance-profiler.md`](docs/performance-profiler.md) for focused
499
+ commands and `node --expose-gc` runs.
139
500
 
140
- ### 🌊 Streams (ZStream-like)
501
+ Perf runs can be persisted and compared locally:
141
502
 
142
- Pull-based, resource-aware streams with backpressure.
503
+ ```bash
504
+ npm run perf -- --profile runtime-ab --record-history --save-baseline runtime-main
505
+ npm run perf -- --profile runtime-ab --compare-baseline runtime-main --fail-on-baseline-regression
506
+ ```
143
507
 
144
- - `ZStream<R, E, A>`
145
- - `Pull` semantics
146
- - Bounded buffers
147
- - Deterministic resource cleanup
508
+ ### First-release recipes
148
509
 
149
- Examples:
510
+ Copyable happy paths live in [`docs/recipes`](docs/recipes/README.md):
150
511
 
151
- - `src/examples/fromPromise.ts`
152
- - `src/examples/mergeStreamSync.ts`
512
+ - runtime execution
513
+ - typed layers
514
+ - HTTP server
515
+ - testing
516
+ - performance baselines
153
517
 
154
- ---
518
+ ### Structured concurrency
155
519
 
156
- ## Docs
520
+ ```ts
521
+ import { Runtime, asyncSucceed, withScope } from "brass-runtime";
157
522
 
158
- - [Getting Started](./docs/getting-started.md)
159
- - [Architecture](./docs/ARCHITECTURE.md)
160
- - [Cancellation & Interruption](./docs/cancellation.md)
161
- - [Observability: Hooks & Tracing](./docs/observability.md)
162
- - [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)
523
+ const runtime = Runtime.make({});
524
+
525
+ await runtime.toPromise(
526
+ withScope(runtime, (scope) => {
527
+ scope.fork(asyncSucceed("child"));
528
+ // scope close interrupts children + runs finalizers
529
+ })
530
+ );
531
+ ```
532
+
533
+ ### Streams
534
+
535
+ ```ts
536
+ import { Runtime, Stream } from "brass-runtime";
537
+
538
+ const runtime = Runtime.make({});
539
+ const result = await Stream
540
+ .from([1, 2, 3, 4, 5])
541
+ .map((n) => n * 2)
542
+ .collect(runtime);
543
+ // [2, 4, 6, 8, 10]
544
+ ```
166
545
 
167
546
  ---
168
547
 
169
- ## What’s new (recent changes)
548
+ ## Package exports
549
+
550
+ | Import | Purpose |
551
+ |--------|---------|
552
+ | `brass-runtime` | Core runtime: effects, fibers, scheduler, streams, layers |
553
+ | `brass-runtime/core` | Stable core surface (preferred for new code) |
554
+ | `brass-runtime/http` | Default HTTP client factory, lifecycle middleware, compression, batching, prewarm, adaptive limiter |
555
+ | `brass-runtime/http/testing` | Dependency-free mock clients, mock fetch, response factories, and effect runner helpers |
556
+ | `brass-runtime/schema` | Dependency-free runtime schema DSL with type inference |
557
+ | `brass-runtime/observability` | Prometheus/OTLP exporters, logs, spans, trace propagation, request adapters |
558
+ | `brass-runtime/perf` | Runtime, HTTP, observability, memory, and baseline performance profiler |
559
+ | `brass-runtime/agent` | Brass Agent core (experimental) |
170
560
 
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
561
+ CLI: `brass-agent`
175
562
 
176
563
  ---
177
564
 
178
- ## Features (status)
565
+ ## HTTP middleware pipeline
179
566
 
180
- ### Runtime (core)
567
+ The lifecycle client composes middleware in this order (innermost to outermost):
181
568
 
182
- - [x] Sync core: `Effect`
183
- - [x] Async algebra: `Async`
184
- - [x] Cooperative `Scheduler`
185
- - [x] Fibers with interruption & finalizers
186
- - [x] Structured `Scope`
187
- - [x] Resource safety (`acquireRelease`)
569
+ ```
570
+ Wire Priority Retry → Cache → Batch → Dedup
571
+ ```
572
+
573
+ Adaptive limiting lives in the wire client, before lifecycle middleware.
574
+ `makeDefaultHttpClient` can then wrap the lifecycle stack with response
575
+ compression and caller middleware; caller middleware is outermost.
188
576
 
189
- ### Concurrency & Streams
577
+ Each layer is independently optional. Set to `false` or omit to disable.
190
578
 
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)
579
+ | Layer | What it does |
580
+ |-------|-------------|
581
+ | **Adaptive Limiter** | Gradient-based dynamic concurrency control per origin |
582
+ | **Priority** | Priority queue for request scheduling (0-9 levels) |
583
+ | **Retry** | Exponential backoff with circuit breaker awareness |
584
+ | **Cache** | LRU + TTL + stale-while-revalidate |
585
+ | **Batch** | Time-window request coalescing with split/distribute |
586
+ | **Dedup** | Ref-counted in-flight request deduplication |
587
+ | **Compression** | Transparent gzip/br/deflate decompression |
588
+ | **Prewarm** | Proactive TCP+TLS connection establishment |
197
589
 
198
- ### Libraries
590
+ All layers emit lifecycle events, track stats, and support cancellation.
199
591
 
200
- - [x] HTTP client
201
- - [ ] Retry / timeout middleware
202
- - [ ] Logging / metrics layers
592
+ The recommended `makeDefaultHttpClient` factory wires the default preset
593
+ for you and accepts extra middleware, so observability can be attached with
594
+ `middleware: [withHttpObservability(obs)]` without coupling HTTP to exporters.
595
+ Per-request `policy` travels through that stack and is visible to observability
596
+ without being forwarded to the host transport.
203
597
 
204
598
  ---
205
599
 
206
- ## Design notes
600
+ ## WASM engine
207
601
 
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
602
+ Optional Rust/WASM-backed components for strict execution:
212
603
 
213
- ---
604
+ - Fiber engine state machine
605
+ - Scheduler queue
606
+ - Bounded queues
607
+ - Permit pool
608
+ - Retry planner
214
609
 
215
- ## Contributing
610
+ ```bash
611
+ npm run build:wasm # requires wasm-pack
612
+ ```
216
613
 
217
- - Runtime invariants matteravoid 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)
614
+ The WASM engine never silently falls back to TypeScript if you request WASM and it's unavailable, it fails explicitly.
220
615
 
221
616
  ---
222
617
 
223
- ## License
618
+ ## Brass Agent (experimental)
619
+
620
+ 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.
621
+
622
+ ```bash
623
+ npm run agent:vscode:install # VS Code extension
624
+ brass-agent --doctor # check setup
625
+ brass-agent --init # initialize workspace
626
+ brass-agent --preset inspect # run inspection
627
+ ```
224
628
 
225
- MIT License © 2025
629
+ 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)
226
630
 
227
- ## Brass Agent local smoke tests
631
+ ---
228
632
 
229
- Run local smoke tests without CI or a real LLM provider:
633
+ ## Testing
230
634
 
231
635
  ```bash
232
- npm run agent:test:local
636
+ npm test # vitest suite
637
+ npm run test:types # TypeScript type checking
638
+ npm run test:coverage # coverage with baseline gate
639
+ npm run release:check # full release gate: types, tests, build, CJS, perf budgets
640
+ npm run benchmark # runtime, HTTP lifecycle, and 100k local HTTP concurrency
641
+ npm run benchmark:runtime # Runtime Performance Track
642
+ npm run benchmark:runtime:budget # Runtime Performance Track regression budget
643
+ npm run perf:runtime:ab # Runtime A/B Performance Lab
644
+ npm run perf:runtime:soak # Runtime-only soak profile
645
+ npm run perf:runtime:budget # Runtime profiler budget
646
+ npm run perf:http:memory # HTTP long-run memory lab
647
+ npm run benchmark -- http-concurrent # HTTP compare mode variants
648
+ node --expose-gc --import tsx src/benchmarks/runner.ts http-concurrent # HTTP memory/limiter diagnostics
649
+ npm run benchmark:adaptive
650
+ npm run benchmark:adaptive:soak
651
+ npm run benchmark:http:budget
652
+ npm run benchmark:http:soak
653
+ npm run benchmark:observability
654
+ npm run benchmark:observability:budget
655
+ npm run smoke:observability:collector # requires local OTEL collector
233
656
  ```
234
657
 
235
- This builds the project and runs a fake-LLM smoke test against the `brass-agent` CLI.
658
+ Property-based tests use `fast-check` with 100+ iterations per property. Each HTTP middleware has dedicated property tests verifying correctness invariants.
659
+
660
+ ---
661
+
662
+ ## Docs
663
+
664
+ - [Getting Started](./docs/getting-started.md)
665
+ - [Architecture](./docs/ARCHITECTURE.md)
666
+ - [Cancellation & Interruption](./docs/cancellation.md)
667
+ - [Observability: Hooks & Tracing](./docs/observability.md)
668
+ - [Observability framework examples](./docs/observability-framework-examples.md)
669
+ - [Observability collector smoke](./docs/observability-collector-smoke.md)
670
+ - [HTTP module](./docs/http.md)
671
+ - [Production readiness](./docs/production-readiness.md)
672
+ - [Streams guide](./docs/guides/streams.md)
673
+ - [Testing guide](./docs/guides/testing.md)
674
+ - [WASM engine](./docs/wasm-fiber-engine.md)
675
+
676
+ ---
677
+
678
+ ## Features
679
+
680
+ ### Runtime (core)
681
+
682
+ - [x] Sync effect values via `ZIO<R, E, A>` aliases
683
+ - [x] Algebraic async: `Async<R, E, A>`
684
+ - [x] Rich `Cause<E>` failure trees with pretty printing
685
+ - [x] Interruptibility regions with `uninterruptible` / `uninterruptibleMask`
686
+ - [x] Fiber-local refs with fork inheritance and scoped restoration
687
+ - [x] TS TestRuntime with deterministic scheduler and virtual clock
688
+ - [x] Schedule 2.0 with drivers, runtime-clock budgets, observability, and HTTP integration
689
+ - [x] Cooperative scheduler (observable, testable)
690
+ - [x] Fibers with interruption & finalizers
691
+ - [x] Structured scopes & resource safety
692
+ - [x] Runtime flight recorder for bounded execution traces
693
+ - [x] Layer 2.0 typed contexts, semaphores, circuit breakers
694
+ - [x] Metrics, tracing, runtime hooks
695
+ - [x] Worker pools
696
+ - [x] WASM engine (optional)
697
+
698
+ ### Streams
699
+
700
+ - [x] Pull-based streams with backpressure
701
+ - [x] Fluent `Stream` / `Pipeline` DX facade
702
+ - [x] Bounded buffers, queues, hubs
703
+ - [x] Pipelines with fusion optimization
704
+ - [x] Stream merge, zip, broadcast
705
+ - [x] Chunks & batch operators
706
+
707
+ ### HTTP
708
+
709
+ - [x] Lazy, cancelable HTTP client
710
+ - [x] Effect-based Node HTTP server listener with resource lifecycle
711
+ - [x] Declarative typed routing with params/query/body/response schemas
712
+ - [x] Health/readiness routes backed by runtime health reports
713
+ - [x] Schema-validated JSON helpers
714
+ - [x] Discoverable builder API
715
+ - [x] Test helper subpath
716
+ - [x] Lifecycle client with middleware composition
717
+ - [x] Response cache (LRU + TTL + SWR)
718
+ - [x] Request deduplication (ref-counted)
719
+ - [x] Priority scheduling
720
+ - [x] Retry with exponential backoff
721
+ - [x] Response compression (gzip, br, deflate)
722
+ - [x] Request batching (time-window coalesce/split)
723
+ - [x] Connection pre-warming (probes, auto-refresh)
724
+ - [x] Adaptive concurrency (gradient-based)
725
+ - [x] Adaptive limiter presets, diagnostics, observability gauges, and soak benchmark
726
+ - [x] Circuit breaker
727
+ - [x] Tracing & validation
728
+
729
+ ### Schema
730
+
731
+ - [x] Dependency-free schema DSL
732
+ - [x] Type inference via `InferSchema`
733
+ - [x] Object, array, record, union, enum, literal, custom schemas
734
+ - [x] Optional, nullable, refine, transform
735
+ - [x] Path-rich validation issues
736
+
737
+ ### Observability
738
+
739
+ - [x] Runtime metrics sink and Prometheus exporter
740
+ - [x] OTLP JSON/HTTP exporters for metrics, traces, and logs
741
+ - [x] Structured logging with context propagation and redaction
742
+ - [x] W3C trace-context extract/inject helpers
743
+ - [x] Client and server HTTP observability helpers
744
+ - [x] Adaptive limiter metrics on HTTP client spans and Prometheus gauges
745
+ - [x] Sampling, force-sample-on-error, and bounded trace retention
746
+ - [x] Bounded exporter queues with retry, timeout, drop policy, and single-flight flush
747
+ - [x] Fetch/Node/Express/Fastify/Nest-style examples and collector smoke script
748
+
749
+ ---
750
+
751
+ ## Design notes
752
+
753
+ - **No hidden Promises** — async is always modeled explicitly via `Async`
754
+ - **Deterministic execution** — scheduler is observable and testable
755
+ - **Resource safety is structural** — scopes guarantee cleanup
756
+ - **Middleware composes via functions** — `(next: HttpClientFn) => HttpClientFn`
757
+ - **Cancellation propagates** — ref-counted through the entire middleware stack
758
+ - **Stats are frozen snapshots** — no mutable state leaks to consumers
759
+
760
+ ---
761
+
762
+ ## Contributing
763
+
764
+ - Runtime invariants matter — avoid sneaking Promises into core semantics
765
+ - Prefer libraries on top of the runtime over changes in core
766
+ - Add property tests when an invariant is broad
767
+ - Keep tests close to the changed module
768
+ - Small, focused PRs are welcome
769
+
770
+ ---
771
+
772
+ ## License
236
773
 
237
- See also: [Agent language and workspace setup UX](docs/agent-language-workspace-ux.md).
774
+ MIT © 2025