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.
- package/CHANGELOG.md +17 -0
- package/README.md +673 -136
- package/dist/agent/cli/main.cjs +40 -35
- package/dist/agent/cli/main.js +9 -4
- package/dist/agent/cli/main.mjs +9 -4
- package/dist/agent/index.cjs +8 -4
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.js +7 -3
- package/dist/agent/index.mjs +7 -3
- package/dist/chunk-2HQTDLHF.mjs +683 -0
- package/dist/chunk-36I3M4UC.mjs +370 -0
- package/dist/chunk-3AYM6WPJ.js +1629 -0
- package/dist/chunk-3LOYJFRR.cjs +300 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-3Y2RIUMM.js +300 -0
- package/dist/{chunk-VEZNF5GZ.cjs → chunk-4ROBZFL6.cjs} +130 -126
- package/dist/{chunk-3QMOKAS5.js → chunk-52OB2ROS.js} +9 -5
- package/dist/chunk-52PPNNI4.cjs +416 -0
- package/dist/chunk-5EC274J5.cjs +2874 -0
- package/dist/chunk-5QC7LRZ3.js +229 -0
- package/dist/chunk-5VRJNBLZ.mjs +2874 -0
- package/dist/chunk-62AZW6UT.cjs +313 -0
- package/dist/chunk-6IXXWIUM.js +683 -0
- package/dist/chunk-74ZTY6CP.js +2871 -0
- package/dist/chunk-76YMRMH2.cjs +777 -0
- package/dist/chunk-7CMJS3QE.mjs +2871 -0
- package/dist/{chunk-4NHES7VK.mjs → chunk-7JIJOVCT.js} +27 -13
- package/dist/chunk-A2OM6NEH.mjs +194 -0
- package/dist/chunk-AGR5B2BC.cjs +683 -0
- package/dist/chunk-AVNQLJ5V.js +777 -0
- package/dist/chunk-B33ICAKP.js +313 -0
- package/dist/{chunk-ELOOF35R.mjs → chunk-B5JD23U7.mjs} +1 -1
- package/dist/chunk-BABBZK4Y.js +2024 -0
- package/dist/chunk-C3MDXTRZ.js +354 -0
- package/dist/chunk-CIZFIMK5.js +2193 -0
- package/dist/chunk-CZIVE6NT.cjs +354 -0
- package/dist/chunk-DNFJLJMW.mjs +354 -0
- package/dist/chunk-DNFO2EIZ.mjs +777 -0
- package/dist/chunk-EJ6BPYVR.mjs +416 -0
- package/dist/chunk-ENKODRU3.cjs +2193 -0
- package/dist/chunk-EOC4UHBS.mjs +229 -0
- package/dist/{chunk-BMH5AV44.js → chunk-FH2X7BVP.js} +756 -440
- package/dist/{chunk-PPUXIH5R.js → chunk-FHQGHPMO.mjs} +27 -13
- package/dist/{chunk-TGIFUAK4.cjs → chunk-GLE2WY7Z.cjs} +951 -635
- package/dist/{chunk-BDF4AMWX.mjs → chunk-GYM3LLGS.mjs} +756 -440
- package/dist/chunk-HLWLMW2F.mjs +2024 -0
- package/dist/chunk-JF5WGYJJ.cjs +194 -0
- package/dist/chunk-KH4SYAOS.mjs +1629 -0
- package/dist/chunk-KN32XNTH.mjs +313 -0
- package/dist/chunk-KQLYONSE.cjs +2871 -0
- package/dist/{chunk-STVLQ3XD.cjs → chunk-KZJQ723N.cjs} +92 -78
- package/dist/chunk-L2SYFEBS.js +194 -0
- package/dist/chunk-L6VB5N7Q.cjs +104 -0
- package/dist/{chunk-K6M7MDZ4.mjs → chunk-MBEJI5HF.mjs} +9 -5
- package/dist/chunk-MIIYDLGM.js +2874 -0
- package/dist/chunk-MOO4L7F4.mjs +104 -0
- package/dist/chunk-MT3OWDPC.mjs +2193 -0
- package/dist/chunk-MVGUEJ5Z.cjs +370 -0
- package/dist/chunk-OBGZSXTJ.cjs +10 -0
- package/dist/chunk-PD4EJTQC.cjs +229 -0
- package/dist/chunk-PWC3RBQE.mjs +300 -0
- package/dist/chunk-Q2I37RP3.cjs +1629 -0
- package/dist/chunk-RKGKFN2A.js +416 -0
- package/dist/{chunk-R3R2FVLG.cjs → chunk-SA6HUJVI.cjs} +5 -5
- package/dist/chunk-TRM4JUZQ.js +104 -0
- package/dist/chunk-UB4B6OFY.js +370 -0
- package/dist/{chunk-TO7IKXYT.js → chunk-UCUBNWM2.js} +1 -1
- package/dist/chunk-VN44DYYT.cjs +2024 -0
- package/dist/chunk-Y6FXYEAI.mjs +10 -0
- package/dist/client-CZHU674n.d.ts +820 -0
- package/dist/core/index.cjs +198 -4
- package/dist/core/index.d.ts +311 -212
- package/dist/core/index.js +237 -43
- package/dist/core/index.mjs +237 -43
- package/dist/{effect-CMOQKX8y.d.ts → effect-DIUHZ9IN.d.ts} +195 -1
- package/dist/effectRunner-CFLC32IK.cjs +8 -0
- package/dist/effectRunner-L4S7IPT3.js +8 -0
- package/dist/effectRunner-NNGG75QA.mjs +8 -0
- package/dist/http/index.cjs +1227 -2971
- package/dist/http/index.d.ts +826 -280
- package/dist/http/index.js +1089 -2833
- package/dist/http/index.mjs +1089 -2833
- package/dist/http/testing.cjs +161 -0
- package/dist/http/testing.d.ts +43 -0
- package/dist/http/testing.js +161 -0
- package/dist/http/testing.mjs +161 -0
- package/dist/index.cjs +486 -250
- package/dist/index.d.ts +87 -95
- package/dist/index.js +391 -155
- package/dist/index.mjs +391 -155
- package/dist/observability/index.cjs +162 -0
- package/dist/observability/index.d.ts +152 -0
- package/dist/observability/index.js +162 -0
- package/dist/observability/index.mjs +162 -0
- package/dist/perf/cli.cjs +401 -0
- package/dist/perf/cli.d.ts +1 -0
- package/dist/perf/cli.js +401 -0
- package/dist/perf/cli.mjs +401 -0
- package/dist/perf/index.cjs +141 -0
- package/dist/perf/index.d.ts +483 -0
- package/dist/perf/index.js +141 -0
- package/dist/perf/index.mjs +141 -0
- package/dist/schedule-CK3Ml_7p.d.ts +259 -0
- package/dist/schema/index.cjs +29 -0
- package/dist/schema/index.d.ts +179 -0
- package/dist/schema/index.js +29 -0
- package/dist/schema/index.mjs +29 -0
- package/dist/server-GJPg8ZSG.d.ts +675 -0
- package/dist/{stream-FQm9h4Mg.d.ts → stream-B4oK9JFP.d.ts} +1 -1
- package/dist/tracer-Hwt1cl7h.d.ts +189 -0
- package/dist/tracing-DqbTKGcf.d.ts +148 -0
- package/docs/ARCHITECTURE.md +292 -0
- package/docs/README.md +63 -0
- package/docs/adr/0001-ai-context-pack.md +32 -0
- package/docs/agent-apply-mode.md +104 -0
- package/docs/agent-approvals.md +110 -0
- package/docs/agent-batch.md +185 -0
- package/docs/agent-boundaries.md +112 -0
- package/docs/agent-chat-sessions.md +160 -0
- package/docs/agent-ci.md +17 -0
- package/docs/agent-cli.md +405 -0
- package/docs/agent-config.md +480 -0
- package/docs/agent-context-discovery.md +159 -0
- package/docs/agent-copilot-like-dx.md +126 -0
- package/docs/agent-declarative-optimized-planning.md +138 -0
- package/docs/agent-dx.md +224 -0
- package/docs/agent-env-files.md +126 -0
- package/docs/agent-follow-up-context.md +43 -0
- package/docs/agent-global-usage.md +180 -0
- package/docs/agent-init.md +109 -0
- package/docs/agent-install-and-configure.md +516 -0
- package/docs/agent-language-workspace-ux.md +99 -0
- package/docs/agent-llm-adapters.md +123 -0
- package/docs/agent-local-install.md +190 -0
- package/docs/agent-local-tests.md +51 -0
- package/docs/agent-observability.md +155 -0
- package/docs/agent-patch-quality-loop.md +162 -0
- package/docs/agent-presets.md +22 -0
- package/docs/agent-project-commands.md +237 -0
- package/docs/agent-project-intelligence.md +156 -0
- package/docs/agent-redaction.md +18 -0
- package/docs/agent-release-readiness.md +76 -0
- package/docs/agent-rollback-safety.md +162 -0
- package/docs/agent-rollback.md +23 -0
- package/docs/agent-run-artifacts.md +16 -0
- package/docs/agent-vscode-auto-discovery.md +137 -0
- package/docs/agent-vscode-batch-runner.md +100 -0
- package/docs/agent-vscode-chat-layout.md +90 -0
- package/docs/agent-vscode-clean-install.md +147 -0
- package/docs/agent-vscode-code-actions.md +70 -0
- package/docs/agent-vscode-diff-preview.md +45 -0
- package/docs/agent-vscode-inline-assist.md +56 -0
- package/docs/agent-vscode-install.md +186 -0
- package/docs/agent-vscode-model-setup.md +97 -0
- package/docs/agent-vscode-patch-preview.md +92 -0
- package/docs/agent-vscode-problems.md +79 -0
- package/docs/agent-vscode-project-dashboard.md +106 -0
- package/docs/agent-vscode-run-history.md +92 -0
- package/docs/agent-vscode-ux.md +73 -0
- package/docs/ai/INVARIANTS.md +84 -0
- package/docs/ai/PROJECT_MAP.md +338 -0
- package/docs/ai/PUBLIC_API.md +336 -0
- package/docs/ai/VALIDATION_MATRIX.md +67 -0
- package/docs/api-polish.md +37 -0
- package/docs/cancellation.md +162 -0
- package/docs/coverage.md +46 -0
- package/docs/getting-started.md +159 -0
- package/docs/guides/README.md +40 -0
- package/docs/guides/circuit-breaker.md +89 -0
- package/docs/guides/error-handling.md +91 -0
- package/docs/guides/getting-started.md +107 -0
- package/docs/guides/layers.md +189 -0
- package/docs/guides/metrics.md +101 -0
- package/docs/guides/resource-management.md +141 -0
- package/docs/guides/retry.md +215 -0
- package/docs/guides/semaphore.md +66 -0
- package/docs/guides/streams.md +117 -0
- package/docs/guides/supervisors.md +98 -0
- package/docs/guides/testing.md +162 -0
- package/docs/guides/tracing.md +71 -0
- package/docs/http-recipes.md +399 -0
- package/docs/http.md +749 -0
- package/docs/modules.md +285 -0
- package/docs/observability-collector-smoke.md +31 -0
- package/docs/observability-framework-examples.md +98 -0
- package/docs/observability.md +542 -0
- package/docs/otel-collector-smoke.yaml +27 -0
- package/docs/performance-profiler.md +199 -0
- package/docs/production-readiness.md +73 -0
- package/docs/recipes/README.md +12 -0
- package/docs/recipes/http-server.md +45 -0
- package/docs/recipes/layers.md +44 -0
- package/docs/recipes/performance.md +47 -0
- package/docs/recipes/runtime.md +41 -0
- package/docs/recipes/testing.md +41 -0
- package/docs/release.md +53 -0
- package/docs/wasm-bounded-queues.md +44 -0
- package/docs/wasm-engine-observability-benchmarks.md +85 -0
- package/docs/wasm-fiber-engine.md +117 -0
- package/docs/wasm-scheduler-state-machine.md +122 -0
- package/docs/wasm-stream-chunks.md +54 -0
- package/package.json +48 -2
- package/dist/chunk-AR22SXML.js +0 -1043
- package/dist/chunk-BDYEENHT.js +0 -224
- package/dist/chunk-JFPU5GQI.mjs +0 -1043
- package/dist/chunk-MS34J5LY.cjs +0 -224
- package/dist/chunk-UMAZLXAB.mjs +0 -224
- package/dist/chunk-XPZNXSVN.cjs +0 -1043
- package/dist/tracing-DNT9jEbr.d.ts +0 -106
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Public API
|
|
2
|
+
|
|
3
|
+
This file tracks the package surface that users can import.
|
|
4
|
+
|
|
5
|
+
## Package exports
|
|
6
|
+
|
|
7
|
+
Defined in `package.json`:
|
|
8
|
+
|
|
9
|
+
- `brass-runtime` -> `dist/index.*`
|
|
10
|
+
- `brass-runtime/core` -> `dist/core/index.*`
|
|
11
|
+
- `brass-runtime/http` -> `dist/http/index.*`
|
|
12
|
+
- `brass-runtime/http/testing` -> `dist/http/testing.*`
|
|
13
|
+
- `brass-runtime/schema` -> `dist/schema/index.*`
|
|
14
|
+
- `brass-runtime/observability` -> `dist/observability/index.*`
|
|
15
|
+
- `brass-runtime/perf` -> `dist/perf/index.*`
|
|
16
|
+
- `brass-runtime/agent` -> `dist/agent/index.*`
|
|
17
|
+
- `brass-runtime/package.json`
|
|
18
|
+
- `brass-runtime/wasm/pkg/brass_runtime_wasm_engine.js`
|
|
19
|
+
- `brass-runtime/wasm/pkg/brass_runtime_wasm_engine_bg.wasm`
|
|
20
|
+
|
|
21
|
+
CLI:
|
|
22
|
+
|
|
23
|
+
- `brass-agent` -> `dist/agent/cli/main.cjs`
|
|
24
|
+
- `brass-perf` -> `dist/perf/cli.cjs`
|
|
25
|
+
|
|
26
|
+
Bundle entries are defined in `tsup.config.ts`. Package files include `dist`,
|
|
27
|
+
`wasm/pkg`, `README.md`, `CHANGELOG.md`, `docs`, `LICENSE`, and `package.json`.
|
|
28
|
+
|
|
29
|
+
## Root export: `brass-runtime`
|
|
30
|
+
|
|
31
|
+
Source: `src/index.ts`
|
|
32
|
+
|
|
33
|
+
The root export is compatibility-first. New public APIs should prefer a named
|
|
34
|
+
subpath when they belong to an optional subsystem (`brass-runtime/http`,
|
|
35
|
+
`brass-runtime/agent`, future stream/runtime subpaths) instead of widening the
|
|
36
|
+
root surface by default.
|
|
37
|
+
|
|
38
|
+
Primary categories:
|
|
39
|
+
|
|
40
|
+
- effect/core types: `Async`, `ZIO`, `Exit`, `Cause`, `Option`, cancel types
|
|
41
|
+
- runtime execution: `Runtime`, `makeRuntime`, `runPromise`, `runExit`,
|
|
42
|
+
`runEffect`, `fork`, `toPromise`, scheduler/fiber/scope
|
|
43
|
+
- resources and structured concurrency helpers: `Resource`, `managed`,
|
|
44
|
+
`Supervisor`, `makeSupervisor`, `joinSupervised`
|
|
45
|
+
- interruptibility helpers: `uninterruptible`, `interruptible`,
|
|
46
|
+
`uninterruptibleMask`
|
|
47
|
+
- semaphore, circuit breaker, `Ref`, `FiberRef`, declarative `Schedule`,
|
|
48
|
+
`ScheduleDriver`, Schedule 2.0 combinators/observers, shutdown, TS
|
|
49
|
+
`TestRuntime`, `TestScheduler`, `TestClock`, and testing helpers
|
|
50
|
+
- Layer 2.0 dependency graph helpers: `Layer`, `LayerContext`,
|
|
51
|
+
`ServiceTag`, `makeServiceTag`, `layerValue`, `layerEffect`,
|
|
52
|
+
`defineService`, `getService`, `formatLayerError`, `buildLayer`,
|
|
53
|
+
`makeLayerScope`, `provide`, and `provideLayerContext`
|
|
54
|
+
- worker pool, tracing, metrics, runtime observability hooks/events
|
|
55
|
+
- typed errors
|
|
56
|
+
- runtime engines and capabilities
|
|
57
|
+
- streams, buffers, queues, hubs, pipelines, chunks, operators, and root-level
|
|
58
|
+
`Stream` / `Pipeline` DX facades
|
|
59
|
+
|
|
60
|
+
When adding a root export:
|
|
61
|
+
|
|
62
|
+
- Check whether it belongs in core or a subpath.
|
|
63
|
+
- Avoid exporting test/benchmark/internal implementation details.
|
|
64
|
+
- Add or update docs/examples when the export is user-facing.
|
|
65
|
+
- Keep `Cause<E>` compatible with typed failures, defects, interruptions, and
|
|
66
|
+
composed `Then` / `Both` failure trees.
|
|
67
|
+
|
|
68
|
+
## Core export: `brass-runtime/core`
|
|
69
|
+
|
|
70
|
+
Source: `src/core/index.ts`
|
|
71
|
+
|
|
72
|
+
This is the preferred stable core surface for new imports. It intentionally
|
|
73
|
+
exports effect/runtime/resource/layer/schedule/observability helpers without
|
|
74
|
+
the lower-level engine, scheduler queue, ring-buffer, and WASM bridge internals
|
|
75
|
+
that remain available from the root export for compatibility.
|
|
76
|
+
|
|
77
|
+
Observability helpers include `RuntimeHooks`, `RuntimeEvent`,
|
|
78
|
+
`RuntimeEventRecord`, `EventBus`, `makeRuntimeRecorder`, `consoleJsonLogger`,
|
|
79
|
+
`RuntimeRegistry`, `dumpAllFibers`, and `InMemoryTracer`. Core also exposes
|
|
80
|
+
`Resource`, `makeResource`, `resourceAll`, `Schedule` constructors/combinators,
|
|
81
|
+
`Schedule.driver` / `makeScheduleDriver`, runtime-clock-aware schedule runners,
|
|
82
|
+
supervisor APIs, `makeRuntime` / `runPromise` / `runExit`, and Layer 2.0
|
|
83
|
+
primitives for typed service tags, immutable contexts, scoped memoized builds,
|
|
84
|
+
missing-service formatting, and idempotent release.
|
|
85
|
+
|
|
86
|
+
## HTTP export: `brass-runtime/http`
|
|
87
|
+
|
|
88
|
+
Source: `src/http/index.ts`
|
|
89
|
+
|
|
90
|
+
Recommended API order:
|
|
91
|
+
|
|
92
|
+
- `makeDefaultHttpClient` for the one-stop default client with JSON/text
|
|
93
|
+
helpers, lifecycle presets (`production`, `default`, `balanced`, `minimal`),
|
|
94
|
+
compression, stats, cache controls, `cancelAll`, and middleware integration.
|
|
95
|
+
- `makeHttpRouter`, `route` / `httpRoute`, and `makeNodeHttpServerResource`
|
|
96
|
+
for the first-party HTTP server MVP: Node adapter, simple router,
|
|
97
|
+
effect-based middleware, schema validation, observability, runtime
|
|
98
|
+
health/readiness probes, typed path params, and managed `.listen()`
|
|
99
|
+
lifecycle.
|
|
100
|
+
- `HttpServer` for the discoverable server DX object: routes, router, listen,
|
|
101
|
+
resource, JSON/text/empty responses, health/readiness routes, and simple
|
|
102
|
+
middleware helpers.
|
|
103
|
+
- `httpClient` for day-to-day typed text/JSON calls.
|
|
104
|
+
- `s` / `schema` and `validatedJson` for dependency-free HTTP JSON
|
|
105
|
+
validation with typed validation errors.
|
|
106
|
+
- `httpClientBuilder` / `makeHttpClientBuilder` for a discoverable builder
|
|
107
|
+
API over the default client presets and lifecycle layers.
|
|
108
|
+
- `adaptiveLimiterPresets` / `makeAdaptiveLimiterConfig` for documented
|
|
109
|
+
`conservative`, `balanced`, and `aggressive` adaptive concurrency baselines.
|
|
110
|
+
- `makeHttpClient` / `makeLifecycleClient` for cache, deduplication, priority
|
|
111
|
+
queues, retry, lifecycle events, stats, and bulk cancellation.
|
|
112
|
+
- `makeHttp` / `makeHttpStream` for low-level wire behavior and middleware
|
|
113
|
+
authors.
|
|
114
|
+
- `HttpTransport`, `HttpStreamTransport`, `makeFetchTransport`, and
|
|
115
|
+
`makeFetchStreamTransport` for replacing the default fetch-backed transport
|
|
116
|
+
with an effect-based backend such as Axios, undici, or test doubles.
|
|
117
|
+
- `makePromiseHttpTransport`, `promiseHttpTransport`, and
|
|
118
|
+
`normalizeHttpHeaders` for adapting Promise-based clients without writing
|
|
119
|
+
`Async.async` / `Cause.fail` plumbing in consuming projects; the fluent
|
|
120
|
+
builder supports `requestConfig(...).send(...).json()` for
|
|
121
|
+
Axios/Fetch-shaped responses with automatic `AbortSignal` injection.
|
|
122
|
+
- `toHttpError`, `isAbortHttpError`, `isTimeoutHttpError`,
|
|
123
|
+
`isFetchHttpError`, `httpErrorStatus`, `isRetryableHttpStatus`, and
|
|
124
|
+
`isRetryableHttpError` for normalizing external client failures
|
|
125
|
+
(including Axios-like `response.status`, aborts, and timeout codes) and
|
|
126
|
+
deciding retryability.
|
|
127
|
+
- `HttpRequestPolicy`, `HttpRequestPolicyRef`, `HttpPolicyPresets`,
|
|
128
|
+
`ResolveHttpRequestPolicyOptions`, `defineHttpPolicyPresets`, `httpPolicy`,
|
|
129
|
+
`getHttpRequestPolicy`, `withHttpRequestPolicy`, and `withHttpPolicyPresets`
|
|
130
|
+
for structured
|
|
131
|
+
per-request execution knobs (`preset`, `priority`, `dedupKey`, `retry`,
|
|
132
|
+
`poolKey`, `lane`) while preserving legacy top-level request fields.
|
|
133
|
+
- `DefaultHttpClientConfig.policyPresets` for resolving `policy: "name"` and
|
|
134
|
+
`policy: { preset: "name", ...overrides }` before lifecycle middleware.
|
|
135
|
+
- `httpClientWithMeta` for metadata-oriented compatibility helpers.
|
|
136
|
+
|
|
137
|
+
Primary categories:
|
|
138
|
+
|
|
139
|
+
- low-level HTTP client and request/response types
|
|
140
|
+
- effect-based transport boundary with fetch as the default implementation
|
|
141
|
+
- structured per-request policy shared by transport, retry, deduplication,
|
|
142
|
+
priority scheduling, pool/circuit-breaker keying, and DX request helpers
|
|
143
|
+
- ergonomic HTTP client helpers
|
|
144
|
+
- HTTP server router, Node adapter, response helpers, and server resources
|
|
145
|
+
- HTTP runtime probe helpers: `makeRuntimeHealthRoute` and
|
|
146
|
+
`makeRuntimeReadinessRoute`
|
|
147
|
+
- production HTTP client presets (`minimal`, `balanced`, `default`)
|
|
148
|
+
- dependency-free schema validation for JSON responses
|
|
149
|
+
- builder API for default HTTP client configuration
|
|
150
|
+
- adaptive limiter presets, diagnostics, and public config helper
|
|
151
|
+
- pool, circuit breaker, tracing, validation
|
|
152
|
+
- lifecycle cache/dedup/priority/stats APIs
|
|
153
|
+
- retry middleware
|
|
154
|
+
- retry middleware accepts an optional declarative `Schedule` for retry delays
|
|
155
|
+
while preserving `Retry-After`, max retries, elapsed-budget behavior, and
|
|
156
|
+
`onScheduleDecision` observability through the Schedule 2.0 driver
|
|
157
|
+
- response and request compression middleware
|
|
158
|
+
- request batching middleware
|
|
159
|
+
- connection pre-warming utilities and middleware
|
|
160
|
+
|
|
161
|
+
## HTTP testing export: `brass-runtime/http/testing`
|
|
162
|
+
|
|
163
|
+
Source: `src/http/testing.ts`
|
|
164
|
+
|
|
165
|
+
Dependency-free helpers for users' test suites:
|
|
166
|
+
|
|
167
|
+
- `makeMockHttpClient`, `makeSequenceHttpClient`
|
|
168
|
+
- `makeHttpResponse`, `makeTextHttpResponse`, `makeJsonHttpResponse`
|
|
169
|
+
- `runHttpEffect`
|
|
170
|
+
- `installMockFetch`, `withMockFetch`
|
|
171
|
+
- `makeFetchResponse`, `makeJsonFetchResponse`
|
|
172
|
+
|
|
173
|
+
## Schema export: `brass-runtime/schema`
|
|
174
|
+
|
|
175
|
+
Source: `src/schema/index.ts`
|
|
176
|
+
|
|
177
|
+
Dependency-free validation DSL shared by HTTP and any future package area that
|
|
178
|
+
needs runtime data validation:
|
|
179
|
+
|
|
180
|
+
- `s` / `schema` / `Schema`
|
|
181
|
+
- `Schema`, `InferSchema`, `SchemaResult`, `SchemaIssue`
|
|
182
|
+
- primitive/object/array/record/union/literal/enum/custom schemas
|
|
183
|
+
- shortcuts: `email`, `url`, `uuid`, `int`, `positive`, `nonEmptyString`, `dateIso`
|
|
184
|
+
- `optional`, `nullable`, `refine`, `transform`
|
|
185
|
+
- `formatIssues`, `validateValue`, `parseConfig`, `formatConfigError`,
|
|
186
|
+
`isConfigValidationError`
|
|
187
|
+
- `SchemaValidationException`, `ConfigValidationError`
|
|
188
|
+
|
|
189
|
+
When changing HTTP API:
|
|
190
|
+
|
|
191
|
+
- Keep wire/content/meta separation clear.
|
|
192
|
+
- Keep lazy execution and cancellation semantics.
|
|
193
|
+
- `postJson(..., body, { bodySchema })` should infer the request body type from
|
|
194
|
+
`bodySchema` and validate it before network I/O.
|
|
195
|
+
- Public error helpers live in `src/http/errors.ts` and are exported from
|
|
196
|
+
`brass-runtime/http`.
|
|
197
|
+
- `AdaptiveLimiter` exposes per-key TTL eviction, explicit warmup,
|
|
198
|
+
`probeJitterRatio`, slow-start recovery, `headroomStrategy`,
|
|
199
|
+
`baselineStrategy`, `decreaseCooldownSamples`, limit-change `history(key)`,
|
|
200
|
+
weighted windows via `windowDecayFactor`, multi-signal error gradients via
|
|
201
|
+
`errorWeight`, priority queue/load-shedding knobs, `PoolRejected.retryAfterMs`
|
|
202
|
+
backoff hints, `markCircuitOpen(key)`, diagnostics (`keys`, `snapshot`,
|
|
203
|
+
`dump`) with utilization/throughput/error rate, and `destroy()`/`shutdown()`.
|
|
204
|
+
- `AdaptiveLimiterConfig.preset` accepts `conservative`, `balanced`, and
|
|
205
|
+
`aggressive`; caller overrides apply on top of the selected preset.
|
|
206
|
+
- Update `docs/http.md` and `src/http/README.md` for user-visible behavior.
|
|
207
|
+
- Add focused tests under `src/http/__tests__`.
|
|
208
|
+
|
|
209
|
+
## Observability export: `brass-runtime/observability`
|
|
210
|
+
|
|
211
|
+
Source: `src/observability/index.ts`
|
|
212
|
+
|
|
213
|
+
This is the preferred production export surface for taking runtime signals out
|
|
214
|
+
of process without adding mandatory vendor dependencies.
|
|
215
|
+
|
|
216
|
+
Primary categories:
|
|
217
|
+
|
|
218
|
+
- Prometheus text formatting and registry exporters for `MetricsRegistry`
|
|
219
|
+
- OTLP JSON/HTTP exporters for metrics and spans
|
|
220
|
+
- runtime metrics sink for `EventBus.subscribeHooks`
|
|
221
|
+
- structured log sink plus effect-level logging helpers
|
|
222
|
+
- `withSpan` and `spanEvent` for trace spans across effect composition
|
|
223
|
+
- `makeObservability` production preset with `flush()` and `shutdown()`
|
|
224
|
+
- `withHttpObservability` middleware for HTTP client metrics, logs, spans, and
|
|
225
|
+
W3C `traceparent` injection, including request-policy context in logs/spans
|
|
226
|
+
and opt-in policy metric labels
|
|
227
|
+
- `HTTP_OBSERVABILITY_CONTRACT` for stable dashboard metric names, label names,
|
|
228
|
+
span attribute names, and structured log message names
|
|
229
|
+
- adaptive limiter gauges and HTTP span attributes when the wrapped client
|
|
230
|
+
exposes an owned limiter
|
|
231
|
+
- W3C trace-context helpers (`parseTraceparent`, `extractTraceContext`,
|
|
232
|
+
`formatTraceparent`, `injectTraceContext`) plus request adapters for seeding
|
|
233
|
+
runtime traces from incoming headers
|
|
234
|
+
- production hardening helpers for exporter pipelines, sampling, redaction,
|
|
235
|
+
metric-cardinality limiting, environment presets, no-op setup, and inbound
|
|
236
|
+
adapters for Fetch/Node/Express/Fastify-style request objects
|
|
237
|
+
- OTLP log export, server-side HTTP request metrics/spans, span retention
|
|
238
|
+
pruning, single-flight flush behavior, collector smoke script, and
|
|
239
|
+
observability benchmark budgets
|
|
240
|
+
- runtime health helpers: `makeRuntimeHealth`, `runtimeHealth`, `readiness`,
|
|
241
|
+
and `healthToHttpResponse` for runtime/fiber/scope/scheduler plus registered
|
|
242
|
+
circuit breaker/adaptive limiter health
|
|
243
|
+
- runtime supervisor events are counted by runtime metrics sinks and are
|
|
244
|
+
available to structured log/tracing sinks via `RuntimeHooks`
|
|
245
|
+
|
|
246
|
+
When changing observability API:
|
|
247
|
+
|
|
248
|
+
- Keep exporters dependency-free and backend-neutral.
|
|
249
|
+
- Do not let sink/exporter failures affect effect semantics.
|
|
250
|
+
- Keep high-cardinality labels opt-in.
|
|
251
|
+
- Add tests under `src/observability/__tests__`.
|
|
252
|
+
|
|
253
|
+
## Performance export: `brass-runtime/perf`
|
|
254
|
+
|
|
255
|
+
Source: `src/perf/index.ts`
|
|
256
|
+
|
|
257
|
+
This is the built-in performance profiling surface for runtime and HTTP work.
|
|
258
|
+
It is intentionally a separate subpath because it depends on runtime, HTTP, and
|
|
259
|
+
observability modules.
|
|
260
|
+
|
|
261
|
+
Primary categories:
|
|
262
|
+
|
|
263
|
+
- `makePerfRecorder` and `summarizePerfEvents` for low-overhead local
|
|
264
|
+
measurement with a bounded ring buffer.
|
|
265
|
+
- `captureMemorySnapshot`, `diffMemorySnapshots`, and
|
|
266
|
+
`profileMemoryRetention` for heap/rss/external memory reports with optional
|
|
267
|
+
forced GC.
|
|
268
|
+
- `profileRuntimePrimitives` for sampled runtime primitive throughput.
|
|
269
|
+
- `diagnoseRuntimeProfile` for hot primitive, fiber pressure, and hook/recorder
|
|
270
|
+
diagnostics.
|
|
271
|
+
- `profileRuntimeAb` / `formatRuntimeAbReport` for runtime-only baseline vs
|
|
272
|
+
candidate comparisons.
|
|
273
|
+
- `profileRuntimeSoak` / `formatRuntimeSoakReport` for repeated runtime-only
|
|
274
|
+
soak profiles.
|
|
275
|
+
- `runRuntimePerfBudget` for CI-friendly runtime profiler budgets.
|
|
276
|
+
- `profileHttpLayers` for local HTTP layer comparison across `node:http`, wire
|
|
277
|
+
client, default presets, adaptive limiter, and observability.
|
|
278
|
+
- `profileHttpMemoryLab` / `formatHttpMemoryLabReport` for long-run HTTP
|
|
279
|
+
memory comparisons with heap/rss totals, heap per 10k requests, GC signal,
|
|
280
|
+
and per-variant verdicts.
|
|
281
|
+
- `createPerfHistoryEntry`, `recordPerfHistoryRun`, `readPerfHistory`,
|
|
282
|
+
`savePerfBaseline`, `loadPerfBaseline`, `comparePerfToBaseline`, and
|
|
283
|
+
`formatPerfBaselineComparison` for local JSONL perf history and named
|
|
284
|
+
baseline regression checks.
|
|
285
|
+
- `recommendPerformance` for heuristic warnings and next actions.
|
|
286
|
+
- `runBrassPerformanceProfile` and `formatPerformanceReport` for the complete
|
|
287
|
+
report used by `npm run perf`, `npm run perf:json`, `npm run benchmark:perf`,
|
|
288
|
+
`npm run perf:history`, and the `brass-perf` binary.
|
|
289
|
+
|
|
290
|
+
When changing performance API:
|
|
291
|
+
|
|
292
|
+
- Keep profiler defaults small enough for local iteration.
|
|
293
|
+
- Keep long, stable regression checks in `src/benchmarks` and budget scripts.
|
|
294
|
+
- Do not make core depend on HTTP or observability.
|
|
295
|
+
- Prefer JSON-friendly report shapes.
|
|
296
|
+
|
|
297
|
+
## Agent export: `brass-runtime/agent`
|
|
298
|
+
|
|
299
|
+
Source: `src/agent/index.ts`
|
|
300
|
+
|
|
301
|
+
Primary categories:
|
|
302
|
+
|
|
303
|
+
- agent state, reducer, decisions, events, config
|
|
304
|
+
- project commands/profile/context discovery
|
|
305
|
+
- patch quality, rollback safety, redaction, language, batch
|
|
306
|
+
- permissions, approvals, policy, retry, timeout, patch tools
|
|
307
|
+
- node services for shell, filesystem, patching, config, workspace discovery
|
|
308
|
+
- LLM adapters
|
|
309
|
+
|
|
310
|
+
When changing agent API:
|
|
311
|
+
|
|
312
|
+
- Preserve boundaries in `docs/agent-boundaries.md`.
|
|
313
|
+
- Keep CLI/node adapters separate from pure core logic.
|
|
314
|
+
- Update relevant `docs/agent-*.md` files.
|
|
315
|
+
|
|
316
|
+
## Generated outputs
|
|
317
|
+
|
|
318
|
+
Do not edit these directly during normal source changes:
|
|
319
|
+
|
|
320
|
+
- `dist`
|
|
321
|
+
- `coverage`
|
|
322
|
+
- `wasm/pkg`
|
|
323
|
+
|
|
324
|
+
Regenerate them with build/test commands when the task requires generated
|
|
325
|
+
artifacts.
|
|
326
|
+
|
|
327
|
+
## Compatibility checklist
|
|
328
|
+
|
|
329
|
+
For public API changes:
|
|
330
|
+
|
|
331
|
+
- Is the export intentional?
|
|
332
|
+
- Does the package export map expose it?
|
|
333
|
+
- Do both CJS and ESM builds work?
|
|
334
|
+
- Do type declarations include it?
|
|
335
|
+
- Are README/docs examples still correct?
|
|
336
|
+
- Is the change semver-relevant?
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Validation Matrix
|
|
2
|
+
|
|
3
|
+
Use this to choose the smallest useful validation set for a change.
|
|
4
|
+
|
|
5
|
+
## Baseline
|
|
6
|
+
|
|
7
|
+
Run these for normal code changes:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run test:types
|
|
11
|
+
npm test
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Full package confidence
|
|
15
|
+
|
|
16
|
+
Run this before release, package export work, or broad refactors:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm run check:full
|
|
20
|
+
npm run validate:cjs
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Notes:
|
|
24
|
+
|
|
25
|
+
- `npm run build` and `npm run check:full` require `wasm-pack`.
|
|
26
|
+
- `npm run check` includes coverage and is slower than the baseline.
|
|
27
|
+
|
|
28
|
+
## By changed area
|
|
29
|
+
|
|
30
|
+
| Changed area | Useful commands | Also inspect |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `src/core/types` | `npm run test:types`; `npm test -- src/core/types src/core/runtime/__tests__/flatmap` | `docs/ai/INVARIANTS.md`; `docs/ARCHITECTURE.md` |
|
|
33
|
+
| `src/core/runtime` | `npm run test:types`; `npm test -- src/core/runtime/__tests__` | engine parity tests; scheduler/fiber/scope/resource/supervisor invariants |
|
|
34
|
+
| `src/core/runtime/engine` | `npm run test:types`; `npm test -- src/core/runtime/__tests__/engine` | `docs/wasm-fiber-engine.md`; TS/WASM parity |
|
|
35
|
+
| `src/observability` | `npm run test:types`; `npm test -- src/observability/__tests__ src/core/runtime/__tests__/eventBus.test.ts` | `docs/observability.md`; `docs/ai/PUBLIC_API.md` |
|
|
36
|
+
| `src/perf` | `npm run test:types`; `npm test -- src/perf/__tests__`; `npm run perf -- --profile runtime`; `npm run perf:history -- --profile runtime`; `npm run perf:runtime:ab`; `npm run perf:runtime:soak`; `npm run perf:runtime:budget`; `npm run perf:http:memory -- --calls 1000 --concurrency 64 --warmup 0 --variants default-json,default-json-observed`; optional `node --expose-gc --import tsx src/perf/cli.ts --profile http-memory --calls 1000 --concurrency 64 --force-gc` | `docs/performance-profiler.md`; `docs/ai/PUBLIC_API.md` |
|
|
37
|
+
| `src/examples/observability*` | `npm run example:observability:express`; `npm run example:observability:fastify`; `npm run example:observability:nest` after installing optional framework deps | `docs/observability-framework-examples.md` |
|
|
38
|
+
| observability collector smoke | `npm run build:ts`; `docker compose -f docker-compose.observability.yml up`; `npm run smoke:observability:collector` | `docs/observability-collector-smoke.md`; `docs/otel-collector-smoke.yaml` |
|
|
39
|
+
| `src/core/stream` | `npm run test:types`; `npm test -- src/core/stream/__tests__` | stream ordering, backpressure, cancellation |
|
|
40
|
+
| `src/http/client.ts`, `src/http/httpClient.ts` | `npm run test:types`; `npm test -- src/http/__tests__/http` | `docs/http.md`; `src/http/README.md` |
|
|
41
|
+
| `src/http/server.ts` | `npm run test:types`; `npm test -- src/http/__tests__/server.test.ts src/observability/__tests__/productionObservability.test.ts` | `docs/http.md`; `src/http/README.md`; `docs/observability.md` |
|
|
42
|
+
| `src/http/batching.ts`, `src/http/prewarm.ts` | `npm run test:types`; `npm test -- src/http/__tests__/batching.test.ts src/http/__tests__/prewarm.test.ts` | batching encoder/decoder shape; cancellation before flush |
|
|
43
|
+
| `src/http/retry` | `npm run test:types`; `npm test -- src/http/__tests__/retry` | retry budgets, aborts, pool interaction |
|
|
44
|
+
| `src/http/lifecycle` | `npm run test:types`; `npm test -- src/http/__tests__/cacheKey src/http/__tests__/dedup src/http/__tests__/lifecycleClient src/http/__tests__/lruCache src/http/__tests__/priority src/http/__tests__/responseCache src/http/__tests__/stats src/http/__tests__/middleware` | `src/http/lifecycle/README.md` |
|
|
45
|
+
| `src/http/compression` | `npm run test:types`; `npm test -- src/http/__tests__/compression.test.ts` | content/header semantics and environment support |
|
|
46
|
+
| `src/agent` | `npm run test:types`; `npm run agent:test:smoke` | `docs/agent-boundaries.md`; config/policy docs |
|
|
47
|
+
| `extensions/vscode-brass-agent` | extension build/test command if present; `npm run agent:vscode:package` | VS Code install/clean docs |
|
|
48
|
+
| `crates/brass-runtime-wasm-engine` | `npm run build:wasm`; `npm test -- src/core/runtime/__tests__/engine src/core/runtime/__tests__/scheduler` | Rust code, generated bridge shape |
|
|
49
|
+
| `package.json`, `tsup.config.ts`, exports | `npm run build`; `npm run validate:cjs`; `npm run test:types` | `docs/ai/PUBLIC_API.md`; `README.md` install examples |
|
|
50
|
+
| release candidate | `npm run release:check`; optional GC-aware `node --expose-gc --import tsx src/perf/cli.ts --profile http-memory --calls 100000 --concurrency 512 --delay-ms 2 --force-gc` | `docs/release.md`; `CHANGELOG.md`; `docs/recipes/` |
|
|
51
|
+
| docs only | link/path review; optional `npm run context` | `docs/README.md`; public API examples |
|
|
52
|
+
| benchmarks | `npm run benchmark`; `npm run benchmark:json`; `npm run benchmark:runtime`; `npm run benchmark:runtime:budget`; `npm run benchmark:http:budget`; `npm run benchmark:observability`; `npm run benchmark:observability:budget`; `npm run benchmark:perf`; `npm run perf:runtime:budget`; related tests | benchmark thresholds, warnings, profiler output, and heap-per-suspended-fiber details |
|
|
53
|
+
|
|
54
|
+
## Property tests
|
|
55
|
+
|
|
56
|
+
Prefer property tests when changing:
|
|
57
|
+
|
|
58
|
+
- algebra laws (`flatMap`, `map`, reassociation)
|
|
59
|
+
- schedulers, queues, ring buffers, caches
|
|
60
|
+
- stream ordering/backpressure behavior
|
|
61
|
+
- retry/lifecycle policies with many combinations
|
|
62
|
+
|
|
63
|
+
## Test naming conventions
|
|
64
|
+
|
|
65
|
+
- Deterministic unit tests use `*.test.ts`.
|
|
66
|
+
- Property tests use `*.pbt.test.ts` or `*.property.test.ts`.
|
|
67
|
+
- Keep tests under the owning module's `__tests__` directory.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# API Polish Notes
|
|
2
|
+
|
|
3
|
+
First-release DX pass.
|
|
4
|
+
|
|
5
|
+
## Public API audit
|
|
6
|
+
|
|
7
|
+
- Kept existing exports for compatibility.
|
|
8
|
+
- Added small aliases/helpers instead of renaming established APIs.
|
|
9
|
+
- Kept optional subsystems on subpaths: `http`, `schema`, `observability`,
|
|
10
|
+
`perf`, and `agent`.
|
|
11
|
+
- Added a public API release snapshot test for the most important first-release
|
|
12
|
+
symbols.
|
|
13
|
+
|
|
14
|
+
## Happy paths
|
|
15
|
+
|
|
16
|
+
- Runtime: `runPromise`, `runExit`, `makeRuntime`.
|
|
17
|
+
- Layers: `defineService`, `getService`, `provide`, `provideContext`,
|
|
18
|
+
`formatLayerError`.
|
|
19
|
+
- HTTP server: `HttpServer` discoverability object over route/router/listen
|
|
20
|
+
and response helpers.
|
|
21
|
+
- Config/schema: `formatConfigError`, `isConfigValidationError`.
|
|
22
|
+
- Performance: `perf:history`, named baselines, and release recipes.
|
|
23
|
+
|
|
24
|
+
## Type inference
|
|
25
|
+
|
|
26
|
+
Type tests cover:
|
|
27
|
+
|
|
28
|
+
- HTTP client request/response schema inference.
|
|
29
|
+
- HTTP server path param and schema override inference.
|
|
30
|
+
- Schema `InferSchema`.
|
|
31
|
+
- Layer service tags and provide aliases.
|
|
32
|
+
- Runtime `runPromise` / `runExit` return types.
|
|
33
|
+
|
|
34
|
+
## Release posture
|
|
35
|
+
|
|
36
|
+
The first-release gate is `npm run release:check`. A GC-aware HTTP memory lab is
|
|
37
|
+
still recommended manually on the release machine before publishing.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 🛑 Cancellation & Interruption
|
|
2
|
+
|
|
3
|
+
This document explains **how cancellation works** in `brass-runtime`, what `Interrupted` means, and which rules `Async` effects must follow to be truly cancellable.
|
|
4
|
+
|
|
5
|
+
> TL;DR: if an `Async` blocks on external work (timers, fetch, streams, sockets), it **must be cancellable**. Cancellation propagates through **Scope** and via **Fiber.interrupt()**.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Vocabulary
|
|
10
|
+
|
|
11
|
+
- **Fiber**: cooperative unit of execution (similar to a “green thread”).
|
|
12
|
+
- **Scope**: lifetime container that **owns fibers** and **finalizers**.
|
|
13
|
+
- **Interrupted**: cancellation signal. A *value* in the error channel (not a thrown JS exception).
|
|
14
|
+
- **Finalizer**: action executed when a scope closes (success, failure, or interruption).
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Semantic rules
|
|
19
|
+
|
|
20
|
+
### 1) What triggers interruption?
|
|
21
|
+
|
|
22
|
+
A fiber can be interrupted by:
|
|
23
|
+
|
|
24
|
+
- `fiber.interrupt()`
|
|
25
|
+
- `scope.close(...)` (interrupts all child fibers registered in that scope)
|
|
26
|
+
- closing a parent scope (propagates to subscopes)
|
|
27
|
+
|
|
28
|
+
### 2) How do you observe interruption?
|
|
29
|
+
|
|
30
|
+
Interruption is observed as:
|
|
31
|
+
|
|
32
|
+
- an `Exit` with `_tag: "Failure"` and `error: { _tag: "Interrupted" }`.
|
|
33
|
+
|
|
34
|
+
### 3) When does work actually stop?
|
|
35
|
+
|
|
36
|
+
Cancellation is **cooperative**:
|
|
37
|
+
|
|
38
|
+
- CPU-only work is interrupted at **checkpoints** (between interpreter steps).
|
|
39
|
+
- IO/timers/promises are interrupted **only if** the underlying `Async` supports cancellation (next section).
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Cancellable Async: the contract
|
|
44
|
+
|
|
45
|
+
An `Async<R, E, A>` that performs IO must be able to “detach” that IO when interrupted:
|
|
46
|
+
|
|
47
|
+
- **Timers**: `clearTimeout`, `clearInterval`
|
|
48
|
+
- **Fetch**: `AbortController` / `AbortSignal`
|
|
49
|
+
- **Streams**: `reader.cancel()`, `controller.abort()`, etc.
|
|
50
|
+
|
|
51
|
+
### Recommended primitive: `fromPromiseAbortable`
|
|
52
|
+
|
|
53
|
+
If your runtime provides `fromPromiseAbortable`, use it as the canonical way to wrap `Promise` + `AbortSignal` APIs.
|
|
54
|
+
|
|
55
|
+
Example: cancellable `sleep(ms)`
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import type { Async } from "../core/types/asyncEffect";
|
|
59
|
+
import type { Interrupted } from "../core/runtime/fiber";
|
|
60
|
+
import { fromPromiseAbortable } from "../core/runtime/runtime";
|
|
61
|
+
|
|
62
|
+
export function sleep(ms: number): Async<unknown, Interrupted, void> {
|
|
63
|
+
return fromPromiseAbortable<Interrupted, void>(
|
|
64
|
+
(signal) =>
|
|
65
|
+
new Promise<void>((resolve, reject) => {
|
|
66
|
+
const id = setTimeout(resolve, ms);
|
|
67
|
+
|
|
68
|
+
const onAbort = () => {
|
|
69
|
+
clearTimeout(id);
|
|
70
|
+
reject({ _tag: "Interrupted" } satisfies Interrupted);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (signal.aborted) return onAbort();
|
|
74
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
75
|
+
}),
|
|
76
|
+
(e) =>
|
|
77
|
+
typeof e === "object" && e !== null && (e as any)._tag === "Interrupted"
|
|
78
|
+
? (e as Interrupted)
|
|
79
|
+
: ({ _tag: "Interrupted" } as Interrupted)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Scope: finalizers and closing
|
|
87
|
+
|
|
88
|
+
### What does `scope.close()` do?
|
|
89
|
+
|
|
90
|
+
A `Scope` typically:
|
|
91
|
+
|
|
92
|
+
1) Marks the scope as closed
|
|
93
|
+
2) Interrupts child fibers registered in this scope
|
|
94
|
+
3) Runs finalizers (LIFO order)
|
|
95
|
+
4) Prevents new forks in this scope (depending on your implementation)
|
|
96
|
+
|
|
97
|
+
### Finalizers are guaranteed
|
|
98
|
+
|
|
99
|
+
A finalizer runs even when the scope closes due to:
|
|
100
|
+
|
|
101
|
+
- success
|
|
102
|
+
- failure
|
|
103
|
+
- interruption
|
|
104
|
+
|
|
105
|
+
This is the foundation of resource safety (ZIO-style):
|
|
106
|
+
|
|
107
|
+
- acquire
|
|
108
|
+
- use
|
|
109
|
+
- release
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Recommended deterministic test
|
|
114
|
+
|
|
115
|
+
This demonstrates that closing a scope interrupts timers:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { Runtime } from "../core/runtime/runtime";
|
|
119
|
+
import { withScope } from "../core/runtime/scope";
|
|
120
|
+
import type { Exit } from "../core/types/effect";
|
|
121
|
+
|
|
122
|
+
const runtime = new Runtime({ env: {} });
|
|
123
|
+
|
|
124
|
+
withScope(runtime, (scope) => {
|
|
125
|
+
const f = scope.fork(sleep(10_000));
|
|
126
|
+
|
|
127
|
+
setTimeout(() => scope.close(), 50);
|
|
128
|
+
|
|
129
|
+
f.join((ex: Exit<any, any>) => {
|
|
130
|
+
console.log("fiber exit:", ex); // -> Failure(Interrupted)
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
If the timer does not stop, verify:
|
|
136
|
+
|
|
137
|
+
- the runtime actually propagates cancellation to `fromPromiseAbortable`
|
|
138
|
+
- combinators are composing cancellation (e.g. `asyncFlatMap` / `asyncFold`)
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Common anti-patterns
|
|
143
|
+
|
|
144
|
+
### ❌ “sleep” implemented only with setTimeout (no cancellation)
|
|
145
|
+
If you don’t clear the timer on interrupt, the fiber can still complete with success after a scope closes.
|
|
146
|
+
|
|
147
|
+
### ❌ Creating “detached” scopes inside combinators
|
|
148
|
+
Avoid `new Scope(runtime)` inside operators when it breaks the parent/child relationship.
|
|
149
|
+
Prefer `parentScope.subScope()` or a “current scope” inherited by the fiber.
|
|
150
|
+
|
|
151
|
+
### ❌ Mixing HTTP “Abort” and runtime “Interrupted” without a rule
|
|
152
|
+
At the HTTP layer it’s fine to map interruption to `{ _tag: "Abort" }`, but document that convention.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Implementation checklist
|
|
157
|
+
|
|
158
|
+
- [ ] `Scope.close()` interrupts child fibers
|
|
159
|
+
- [ ] `Fiber.interrupt()` results in `Exit.Failure(Interrupted)`
|
|
160
|
+
- [ ] `fromPromiseAbortable` is aborted when the fiber is interrupted
|
|
161
|
+
- [ ] combinators (`asyncFlatMap`, `asyncFold`, etc.) compose cancellation
|
|
162
|
+
- [ ] finalizers always run (Success / Failure / Interrupted)
|
package/docs/coverage.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Coverage
|
|
2
|
+
|
|
3
|
+
Coverage is measured with Vitest and the V8 provider.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm run test:coverage:report
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Builds the text, HTML, JSON, JSON summary, and LCOV reports without enforcing
|
|
12
|
+
thresholds. Open `coverage/index.html` for the browsable report.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm run test:coverage
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Runs the same report with the current honest baseline gate. This should pass in
|
|
19
|
+
normal development and should only move upward when new tests improve real
|
|
20
|
+
coverage.
|
|
21
|
+
|
|
22
|
+
The baseline gate is per executable file: 90% statements, 90% functions, and
|
|
23
|
+
90% lines. Pure re-export barrels and type-only compile checks are excluded
|
|
24
|
+
from the coverage gate because V8 reports them as 0% despite having no runtime
|
|
25
|
+
behavior to exercise.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm run test:coverage:100
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Runs the strict target gate: 100% statements, branches, functions, and lines per
|
|
32
|
+
file. This is intentionally separate until the uncovered modules have tests.
|
|
33
|
+
|
|
34
|
+
## Current Baseline
|
|
35
|
+
|
|
36
|
+
The current full-report baseline is:
|
|
37
|
+
|
|
38
|
+
| Metric | Coverage |
|
|
39
|
+
| --- | ---: |
|
|
40
|
+
| Statements | 95.06% |
|
|
41
|
+
| Branches | 86.98% |
|
|
42
|
+
| Functions | 97.31% |
|
|
43
|
+
| Lines | 97.10% |
|
|
44
|
+
|
|
45
|
+
Do not raise or exclude coverage to make the number look better. Prefer focused
|
|
46
|
+
tests for uncovered behavior, then raise the baseline.
|