@devilsdev/rag-pipeline-utils 2.4.3 → 2.4.4

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/BENCHMARKS.md ADDED
@@ -0,0 +1,338 @@
1
+ # Benchmarks
2
+
3
+ This document describes **how we measure** performance in
4
+ `@devilsdev/rag-pipeline-utils` and **how you reproduce the numbers**
5
+ yourself. It deliberately does not publish a headline "N ops/sec" figure.
6
+
7
+ ## Philosophy
8
+
9
+ Benchmark numbers that are not reproducible are marketing, not engineering.
10
+ RAG pipelines are particularly sensitive to factors outside the framework:
11
+ embedding model choice, vector store, LLM provider and region, corpus
12
+ size, query distribution, and hardware. A single number hides all of
13
+ that.
14
+
15
+ Instead, we ship:
16
+
17
+ - A **deterministic, in-process benchmark suite** that measures framework
18
+ overhead — DAG execution, retry policies, logging, memory patterns.
19
+ These numbers are comparable across runs on the same hardware and
20
+ make regressions easy to catch.
21
+ - A **methodology and reference harness** that lets you benchmark your
22
+ own end-to-end pipeline with your actual provider, data, and hardware.
23
+ These are the only numbers that matter for your workload.
24
+
25
+ When you need a headline number for a decision, generate it on the
26
+ system you'll deploy to, with the providers you'll actually use.
27
+
28
+ ## What the suite measures
29
+
30
+ The built-in suite (`scripts/benchmark.js`) exercises **framework
31
+ overhead only**. Every benchmark is in-process, network-free, and
32
+ deterministic up to GC and OS jitter.
33
+
34
+ | Category | What it measures | Why it matters |
35
+ | ----------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------ |
36
+ | **DAG execution** (5 / 10 / 25 / 50 nodes) | Linear chain of async nodes, cold and warm | Baseline overhead of the pipeline orchestrator |
37
+ | **Concurrent DAG** (1 / 2 / 5 / 10 parallelism) | Tree of 20 nodes with configurable concurrency | How well the engine scales intra-query parallelism |
38
+ | **Retry policies** (none / conservative / aggressive) | Simulated 30% failure rate, retries with jittered backoff | Cost of reliability guarantees on the happy path |
39
+ | **Structured logging** (JSON / console / correlated) | Single log call with contextual payload | Per-log-line overhead when observability is on |
40
+ | **Memory allocation** | Array + Map + Set construction and processing | Establishes a memory-pressure floor to compare against |
41
+ | **CPU intensive** | Fibonacci + JSON round-trip + string ops | Sanity check against the hosting CPU |
42
+
43
+ Each benchmark reports:
44
+
45
+ - `mean`, `median`, `min`, `max` latency (ms)
46
+ - `p95`, `p99` latency (ms)
47
+ - `standardDeviation` (ms)
48
+ - `throughput` (ops/sec)
49
+ - `memory.avgDeltaHeapUsed`, `memory.peakHeapUsed`
50
+ - `successRate` (%) and `errors` count
51
+
52
+ All measurements include a warmup phase (default 10 iterations) and use
53
+ `perf_hooks.performance.now()` for timing. If the Node process is
54
+ started with `--expose-gc`, the suite forces a GC before each run.
55
+
56
+ ## What the suite does **not** measure
57
+
58
+ The built-in suite does not exercise:
59
+
60
+ - **Embedder throughput** — provider- and model-dependent
61
+ - **Retrieval latency** — vector store, index size, and network bound
62
+ - **LLM inference latency** — model, region, and token-count bound
63
+ - **End-to-end query latency** — dominated by the three above
64
+ - **Cost per query** — provider pricing + token usage
65
+
66
+ These are intentional omissions. Claiming a number here without
67
+ disclosing the full stack would be misleading. Use the
68
+ **end-to-end harness template** below to measure them against your
69
+ actual stack.
70
+
71
+ ## Running the suite
72
+
73
+ Three presets ship in `package.json`:
74
+
75
+ ```bash
76
+ # 20 iterations per benchmark — fast sanity check (~30s)
77
+ npm run benchmark:quick
78
+
79
+ # 100 iterations, verbose — default (~2 min)
80
+ npm run benchmark
81
+
82
+ # 500 iterations, verbose — release-gate quality (~8 min)
83
+ npm run benchmark:full
84
+ ```
85
+
86
+ Direct invocation:
87
+
88
+ ```bash
89
+ node scripts/benchmark.js \
90
+ --iterations 200 \
91
+ --output ./my-results \
92
+ --verbose
93
+
94
+ # With deterministic GC
95
+ node --expose-gc scripts/benchmark.js --iterations 200
96
+ ```
97
+
98
+ Results are written to `./benchmark-results/`:
99
+
100
+ - `latest.json` — most recent run
101
+ - `benchmark-<timestamp>.json` — archived run
102
+
103
+ A human-readable summary is printed to stdout on completion.
104
+
105
+ ## Environment disclosure template
106
+
107
+ When sharing benchmark numbers (issue reports, blog posts, PR descriptions),
108
+ include the following so they're interpretable:
109
+
110
+ ```text
111
+ Package: @devilsdev/rag-pipeline-utils@<version>
112
+ Node: <version> (v8 <version>)
113
+ OS: <distro/version>, kernel <version>
114
+ CPU: <model>, <cores> cores, <base/boost GHz>
115
+ Memory: <total GB>
116
+ Storage: <NVMe/SSD/HDD>, <filesystem>
117
+ Container: <bare-metal / Docker / K8s / Lambda / etc.>
118
+ Providers: embedder=<…>, retriever=<…>, llm=<…>
119
+ Corpus: <N documents, total tokens, chunk size>
120
+ Query set: <N queries, source>
121
+ Iterations: <N>, warmup: <N>
122
+ GC control: --expose-gc=<yes/no>
123
+ ```
124
+
125
+ The JSON report already captures `nodeVersion`, `platform`, `arch`,
126
+ `cpus`, `totalMemory`, and `loadAverage` automatically in its
127
+ `environment` block.
128
+
129
+ ## Report schema
130
+
131
+ Each run produces a JSON document of the shape:
132
+
133
+ ```json
134
+ {
135
+ "timestamp": "2026-04-16T22:00:00.000Z",
136
+ "environment": {
137
+ "nodeVersion": "v20.x.x",
138
+ "platform": "linux",
139
+ "arch": "x64",
140
+ "cpus": 8,
141
+ "totalMemory": "16384MB",
142
+ "loadAverage": [0.12, 0.08, 0.05]
143
+ },
144
+ "benchmarks": {
145
+ "DAG execution (10 nodes)": {
146
+ "iterations": 100,
147
+ "errors": 0,
148
+ "successRate": 100,
149
+ "timing": {
150
+ "mean": 0.0,
151
+ "median": 0.0,
152
+ "min": 0.0,
153
+ "max": 0.0,
154
+ "p95": 0.0,
155
+ "p99": 0.0,
156
+ "standardDeviation": 0.0
157
+ },
158
+ "memory": {
159
+ "avgDeltaHeapUsed": "0KB",
160
+ "totalHeapDelta": "0KB",
161
+ "peakHeapUsed": "0KB"
162
+ },
163
+ "throughput": 0.0
164
+ }
165
+ },
166
+ "meta": {
167
+ "totalDuration": "0ms",
168
+ "totalBenchmarks": 0,
169
+ "completedAt": "2026-04-16T22:00:00.000Z"
170
+ }
171
+ }
172
+ ```
173
+
174
+ The numeric fields are intentionally left at `0.0` in this schema —
175
+ fill them by running the suite.
176
+
177
+ ## End-to-end benchmarking your pipeline
178
+
179
+ The harness below is the minimal template for honest end-to-end numbers.
180
+ Adapt it to your pipeline, provider mix, and query distribution.
181
+
182
+ ```js
183
+ // scripts/e2e-benchmark.mjs
184
+ import { performance } from "node:perf_hooks";
185
+ import { writeFileSync } from "node:fs";
186
+ import { createRagPipeline } from "@devilsdev/rag-pipeline-utils";
187
+
188
+ const pipeline = createRagPipeline({
189
+ /* your real config — same as production */
190
+ });
191
+
192
+ const queries = [
193
+ /* your real query set — at least 50 queries drawn from production logs */
194
+ ];
195
+
196
+ const WARMUP = 10;
197
+ const ITERATIONS = 100;
198
+
199
+ async function run(query) {
200
+ const t0 = performance.now();
201
+ const result = await pipeline.run({ query });
202
+ const t1 = performance.now();
203
+ return {
204
+ ms: t1 - t0,
205
+ retrievedCount: result.results?.length ?? 0,
206
+ answerChars: result.answer?.length ?? 0,
207
+ tokens: result.usage?.totalTokens ?? null,
208
+ };
209
+ }
210
+
211
+ // Warmup
212
+ for (let i = 0; i < WARMUP; i++) {
213
+ await run(queries[i % queries.length]);
214
+ }
215
+
216
+ // Measured run
217
+ const samples = [];
218
+ for (let i = 0; i < ITERATIONS; i++) {
219
+ samples.push(await run(queries[i % queries.length]));
220
+ }
221
+
222
+ const ms = samples.map((s) => s.ms).sort((a, b) => a - b);
223
+ const percentile = (p) => ms[Math.floor(ms.length * p)];
224
+
225
+ const report = {
226
+ timestamp: new Date().toISOString(),
227
+ iterations: ITERATIONS,
228
+ warmup: WARMUP,
229
+ latencyMs: {
230
+ mean: ms.reduce((a, b) => a + b, 0) / ms.length,
231
+ p50: percentile(0.5),
232
+ p95: percentile(0.95),
233
+ p99: percentile(0.99),
234
+ min: ms[0],
235
+ max: ms[ms.length - 1],
236
+ },
237
+ avgTokens: samples.reduce((a, b) => a + (b.tokens ?? 0), 0) / samples.length,
238
+ avgRetrieved:
239
+ samples.reduce((a, b) => a + b.retrievedCount, 0) / samples.length,
240
+ };
241
+
242
+ writeFileSync("e2e-benchmark.json", JSON.stringify(report, null, 2));
243
+ console.table(report.latencyMs);
244
+ ```
245
+
246
+ Run it the same way on every comparison — same corpus, same query set,
247
+ same providers, same hardware. Don't compare a warm run to a cold one.
248
+
249
+ ## Interpreting results
250
+
251
+ ### Timing percentiles
252
+
253
+ - **mean** is easy to move around by outliers; don't report it alone
254
+ - **p50** (median) is the "typical" experience
255
+ - **p95** is the tail a user will notice
256
+ - **p99** is where GC, cold caches, and network hiccups live — useful
257
+ for SLO design
258
+ - **standardDeviation** much larger than the mean signals high variance;
259
+ your benchmark is probably too short, too concurrent, or sharing a
260
+ noisy host
261
+
262
+ ### Throughput
263
+
264
+ - Throughput is computed as `iterations / (mean_seconds)`. It's
265
+ single-process throughput with the harness's concurrency settings —
266
+ not a statement about your production service's throughput under a
267
+ real load mix.
268
+ - If you want realistic multi-tenant throughput numbers, build a
269
+ load-test harness (`autocannon`, `k6`, `artillery`) that hits the
270
+ HTTP surface you actually deploy, not the library directly.
271
+
272
+ ### Memory
273
+
274
+ - `avgDeltaHeapUsed` is the _growth per iteration_. Trending up across
275
+ a long run means you have a leak.
276
+ - `peakHeapUsed` tells you the upper bound for right-sizing containers.
277
+ - On Windows or containerized Linux, RSS is not the same as heap used;
278
+ prefer platform metrics for capacity planning.
279
+
280
+ ### Common pitfalls
281
+
282
+ 1. **No warmup** — first-iteration numbers are dominated by JIT and
283
+ cold caches. Always discard a warmup window.
284
+ 2. **Too few iterations** — 10 iterations on a ~1ms operation is mostly
285
+ noise. 100+ is a reasonable floor for framework benchmarks;
286
+ end-to-end benchmarks need enough iterations to cover your query
287
+ distribution.
288
+ 3. **Correlated runs** — running the suite twice back-to-back on a
289
+ laptop will show the second run as faster because caches are warm.
290
+ For comparisons, use fresh processes and cold caches, or explicitly
291
+ measure warm paths.
292
+ 4. **Shared hosts** — CI runners, personal machines with open browsers,
293
+ and containers on bin-packed hosts all have neighbors that will add
294
+ noise. Dedicated bare metal or bare VMs give the cleanest numbers.
295
+ 5. **Stream-based workloads** — retrieval latency is not end-to-end
296
+ latency when the LLM streams tokens. Measure time-to-first-token
297
+ (TTFT) separately from total completion time.
298
+
299
+ ## Regression testing in CI
300
+
301
+ The benchmark suite is deterministic enough to catch gross regressions
302
+ in CI. Recommended pattern:
303
+
304
+ 1. Run `npm run benchmark:quick` on every PR against the default branch
305
+ 2. Compare `latest.json` to the baseline in `main` using the keys in
306
+ `benchmarks.*.timing.mean`
307
+ 3. Fail the gate if any benchmark's mean regresses by more than a
308
+ disclosed threshold (e.g. 25%)
309
+
310
+ This project does not yet gate on benchmark regressions in CI by default
311
+ — numbers on shared GitHub runners are too noisy to trust automatically.
312
+ If you run the suite on dedicated hardware as part of a release gate,
313
+ we'd welcome the workflow contribution.
314
+
315
+ ## Contributing benchmark data
316
+
317
+ If you run the suite on a representative production-class host and want
318
+ to share the results:
319
+
320
+ 1. Open a PR adding your report to `benchmark-results/community/` as
321
+ `<hostname-slug>-<date>.json`
322
+ 2. Include the full environment disclosure block above in the PR
323
+ description
324
+ 3. We will not average, normalize, or rank contributed numbers — they
325
+ remain raw data points for other users comparing against similar
326
+ hardware profiles
327
+
328
+ Community benchmark data is licensed under CC0 1.0 (public domain)
329
+ when contributed.
330
+
331
+ ## See also
332
+
333
+ - [Performance guide](docs-site/docs/Performance.md) — optimization
334
+ strategies by component (embedding, retrieval, LLM, memory)
335
+ - [`scripts/benchmark.js`](scripts/benchmark.js) — the benchmark
336
+ harness source
337
+ - [SECURITY.md](SECURITY.md) — security hardening, not performance,
338
+ but often on the same reviewer checklist
package/CHANGELOG.md CHANGED
@@ -9,6 +9,52 @@ Older history (pre-2.4.0) is preserved in the
9
9
  [GitHub releases](https://github.com/DevilsDev/rag-pipeline-utils/releases)
10
10
  page.
11
11
 
12
+ ## [2.4.4] - 2026-04-16
13
+
14
+ ### Added
15
+
16
+ - **`BENCHMARKS.md`** (root, ships in tarball) — methodology-first
17
+ benchmarks doc covering what we measure, what we don't, how to
18
+ run the suite, environment disclosure template, JSON report schema,
19
+ end-to-end harness template for benchmarking your own stack,
20
+ interpretation guide (percentiles, throughput, memory), common
21
+ pitfalls, and a CI regression pattern.
22
+ - **`SEMVER.md`** (root, ships in tarball) — API stability policy.
23
+ Defines public surface, what counts as breaking, deprecation
24
+ process (one-minor warning window minimum), supported runtimes,
25
+ TypeScript and ESM/CJS commitments.
26
+ - **`docs-site/docs/Security-Capabilities.md`** — capability matrix
27
+ distinguishing what's battle-tested (🟢) vs. recommended practice
28
+ (🟡) vs. example code requiring hardening (🟠) vs. out of scope
29
+ (🔴), across pre-retrieval, retrieval-time, and post-generation
30
+ guardrails plus supply-chain, auth, logging, input validation, and
31
+ data governance.
32
+ - **`docs-site/docs/Concepts-Core.md`**,
33
+ `Concepts-Connectors.md`, `Concepts-Evaluation.md`,
34
+ `Concepts-Guardrails.md` — four conceptual-module overviews mapped
35
+ to a future `rag-core` / `rag-connectors` / `rag-eval` /
36
+ `rag-guardrails` package boundary, so reviewers can reason about
37
+ blast radius without us splitting the codebase.
38
+ - **`docs-site/docs/Comparison.md`** — honest comparison vs.
39
+ LangChain.js and LlamaIndex.TS, including where we lose and a
40
+ decision framework. Currency dated to April 2026.
41
+ - **`examples/fastify-rag-demo/`** — runnable end-to-end RAG service:
42
+ Fastify 5 + OpenAI + in-memory retriever + 3-layer guardrails
43
+ - citations + evaluation. Ships with Dockerfile, Fly.io `fly.toml`,
44
+ Railway `railway.json`, ingest + smoke-test scripts, and a complete
45
+ README. ~150 lines of `server.js`.
46
+ - **`examples/README.md`** — index of runnable examples with
47
+ contribution guidance.
48
+
49
+ ### Changed
50
+
51
+ - README "Documentation" section now links to BENCHMARKS, SECURITY,
52
+ CHANGELOG (added in 2.4.3) plus SEMVER, the Security Capabilities
53
+ matrix, the Comparison page, and the runnable demo.
54
+ - Sidebar adds two new categories: "Concepts" (4 pages) and a
55
+ Comparison page under Overview. Security-Capabilities slotted under
56
+ Enterprise.
57
+
12
58
  ## [2.4.3] - 2026-04-16
13
59
 
14
60
  ### Security
@@ -78,6 +124,7 @@ First public release on the 2.4 line, introducing the v2.4 feature set.
78
124
  For release notes prior to v2.4.0, see
79
125
  [github.com/DevilsDev/rag-pipeline-utils/releases](https://github.com/DevilsDev/rag-pipeline-utils/releases).
80
126
 
127
+ [2.4.4]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.4
81
128
  [2.4.3]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.3
82
129
  [2.4.2]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.2
83
130
  [2.4.1]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.1
package/README.md CHANGED
@@ -157,6 +157,13 @@ import {
157
157
  - **[Architecture](https://devilsdev.github.io/rag-pipeline-utils/docs/Architecture)** — plugin contracts, pipeline internals
158
158
  - **[API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)** — complete export index
159
159
  - **[Examples](https://devilsdev.github.io/rag-pipeline-utils/docs/Examples)** — chatbot, Q&A, code search, support
160
+ - **[Comparison vs LangChain.js / LlamaIndex.TS](https://devilsdev.github.io/rag-pipeline-utils/docs/Comparison)** — honest decision framework
161
+ - **[Runnable demo](examples/fastify-rag-demo)** — Fastify + OpenAI + guardrails, deployable in one command
162
+ - **[Benchmarks & methodology](BENCHMARKS.md)** — how we measure, how you reproduce
163
+ - **[Security policy](SECURITY.md)** — responsible disclosure, supported versions
164
+ - **[Security capability matrix](https://devilsdev.github.io/rag-pipeline-utils/docs/Security-Capabilities)** — what's battle-tested vs. recommended vs. example
165
+ - **[API stability policy (SEMVER.md)](SEMVER.md)** — what counts as breaking, deprecation windows
166
+ - **[Changelog](CHANGELOG.md)** — release history
160
167
 
161
168
  ## Roadmap
162
169
 
package/SEMVER.md ADDED
@@ -0,0 +1,184 @@
1
+ # API Stability Policy
2
+
3
+ This document defines what counts as a breaking change for
4
+ `@devilsdev/rag-pipeline-utils`, how long each release line is
5
+ supported, and the deprecation process for public API surface.
6
+
7
+ It is the contract you can plan against.
8
+
9
+ ## Versioning
10
+
11
+ We follow [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html):
12
+
13
+ | Release | When it lands | What changes |
14
+ | ----------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
15
+ | **Patch** (2.4.x) | Bug fixes, security patches, docs, internal refactors | Nothing public-facing breaks. Safe to adopt without reading release notes. |
16
+ | **Minor** (2.x.0) | New features, additive API surface, new plugins, non-breaking behavior tweaks | Review the [CHANGELOG](CHANGELOG.md) before upgrading. Backward compatible. |
17
+ | **Major** (x.0.0) | Breaking changes to public API or required Node versions | Requires active migration. Each major ships with a migration guide. |
18
+
19
+ Pre-release versions (`x.y.z-rc.N`, `-beta.N`, `-alpha.N`) are for
20
+ testing. They have no stability guarantees and may change or disappear
21
+ before general availability.
22
+
23
+ ## Public API surface
24
+
25
+ The **public API surface** — everything covered by SemVer — is
26
+ everything reachable from the package entry point:
27
+
28
+ ```js
29
+ import { ... } from "@devilsdev/rag-pipeline-utils";
30
+ ```
31
+
32
+ Plus the CLI (`npx rag-pipeline …`) and the plugin contract schemas
33
+ in `contracts/`.
34
+
35
+ The following are **not** part of the public API surface and may
36
+ change in any release, including patches:
37
+
38
+ - Any import path with `/internal/` in it
39
+ - Default export behavior of submodules not documented in the
40
+ [API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)
41
+ - Imports reaching into `dist/` or `src/` directly (e.g.
42
+ `@devilsdev/rag-pipeline-utils/src/core/dag/executor.js`)
43
+ - Behavior of items marked `@internal` in JSDoc
44
+ - Behavior marked **experimental** in release notes or JSDoc
45
+ - The on-disk format of internal caches, logs, or temporary files
46
+ - Exact wording of log messages and error `message` strings
47
+ - Node version support _below_ the documented minimum (see "Supported
48
+ runtime" below)
49
+
50
+ If you depend on any of the above, you accept that patch-level upgrades
51
+ may break your integration.
52
+
53
+ ## Breaking changes
54
+
55
+ A **breaking change** is any change that would force a user of the
56
+ public API surface to modify their code, configuration, or deployment.
57
+ Concretely:
58
+
59
+ - Removing or renaming a public export
60
+ - Removing a method or property on a public class
61
+ - Changing the signature of a public method in a way existing callers
62
+ can't satisfy (added required parameter, removed optional parameter
63
+ type, etc.)
64
+ - Changing the shape of a public configuration object
65
+ - Tightening a type that was previously accepting
66
+ - Changing the default value of a public option when the new default
67
+ produces different behavior
68
+ - Throwing a new error class from a public method where callers
69
+ previously got a different class or a string
70
+ - Raising the minimum Node.js version
71
+ - Raising the minimum TypeScript version for typed consumers
72
+ - Removing support for a bundler or module format (ESM/CJS)
73
+
74
+ The following are **not** breaking changes (they ship in minors and
75
+ patches freely):
76
+
77
+ - Adding new exports, methods, or options
78
+ - Relaxing a type that was previously restrictive
79
+ - Widening an accepted input (e.g. accepting `Buffer` where we
80
+ previously only accepted `string`)
81
+ - Adding new optional parameters at the end of a signature
82
+ - Improving error messages or adding context to them
83
+ - Changing the shape of _logs_ (not errors)
84
+ - Performance improvements that don't change observable behavior
85
+ - Internal refactors invisible to the public API
86
+
87
+ ## Deprecation process
88
+
89
+ When we need to remove public API surface, the removal is preceded by
90
+ at least **one minor release** with a deprecation warning.
91
+
92
+ Timeline:
93
+
94
+ 1. **Minor X.Y.0** — API marked deprecated
95
+ - JSDoc `@deprecated` tag with migration guidance
96
+ - TypeScript `@deprecated` in type declarations (strikethrough in
97
+ IDEs)
98
+ - Runtime warning printed once per process when the API is called
99
+ (`util.deprecate` or equivalent)
100
+ - Documentation updated with the recommended replacement
101
+ - Mentioned in the [CHANGELOG](CHANGELOG.md)
102
+ 2. **Minor X.Y.Z** and beyond — API still present, still warning
103
+ 3. **Major (X+1).0.0** — API removed
104
+
105
+ The minimum one-minor window means a user running `npm update`
106
+ regularly will see deprecation warnings before the next major ships.
107
+ We will extend the window longer than one minor for widely-used API
108
+ surface.
109
+
110
+ ## Supported runtime
111
+
112
+ The minimum supported Node.js version is declared in
113
+ [`package.json` `engines.node`](./package.json). We support Node LTS
114
+ versions that are in active maintenance at the time of each major
115
+ release.
116
+
117
+ Dropping support for a Node version is a **breaking change** and
118
+ lands only in major releases.
119
+
120
+ Current: **Node.js ≥ 18**. The next major release is planned to
121
+ require **Node.js ≥ 20** to track LTS support timelines.
122
+
123
+ ## Supported release lines
124
+
125
+ See [SECURITY.md](SECURITY.md#supported-versions). In summary:
126
+
127
+ - **Latest minor** receives bug fixes and security patches
128
+ - **Previous minor** receives a 30-day security-only patch window
129
+ after a new minor ships
130
+ - **Older minors** are unsupported
131
+
132
+ The same matrix applies to non-security bug fixes.
133
+
134
+ ## TypeScript
135
+
136
+ Type declarations ship in `dist/index.d.ts` and are considered part of
137
+ the public API surface. Breaking changes to _types_ that require
138
+ consumer code changes follow the same SemVer rules as runtime API.
139
+
140
+ Type-widening changes (making a type more permissive) are not breaking.
141
+ Type-narrowing changes (making a type more restrictive, causing
142
+ previously-compiling code to fail) are breaking.
143
+
144
+ We target the TypeScript version currently listed in
145
+ `package.json` `devDependencies`. Consumers using older TypeScript
146
+ versions may see type errors that are not regressions.
147
+
148
+ ## ESM and CommonJS
149
+
150
+ The package ships **dual-module builds** — both ESM (`dist/index.mjs`)
151
+ and CommonJS (`dist/index.cjs`). `package.json` `exports` resolves the
152
+ correct entry point based on how the consumer imports it.
153
+
154
+ The ESM build is the primary development target. The CommonJS build
155
+ is a compatibility layer. When a feature can only be expressed in ESM
156
+ (e.g. top-level await, real dynamic imports), we ship it in ESM and
157
+ document the CJS limitation.
158
+
159
+ Dropping CommonJS support is a breaking change and will land only in
160
+ a major release, with a full minor of deprecation warnings first.
161
+
162
+ ## What this means for you
163
+
164
+ If you are building on top of this package, you can:
165
+
166
+ - **Auto-merge patch updates** with confidence. Nothing public-facing
167
+ breaks.
168
+ - **Review minor updates** via the CHANGELOG before merging. No
169
+ required code changes, but new features may be worth adopting.
170
+ - **Plan for major updates.** Each major ships with a
171
+ `docs-site/docs/Migration.md` covering every breaking change and the
172
+ new call site.
173
+
174
+ If you find a case where a patch or minor change broke your
175
+ integration without a deprecation warning, open an issue — we treat
176
+ that as a bug against this policy.
177
+
178
+ ## See also
179
+
180
+ - [SECURITY.md](SECURITY.md) — supported version windows and CVE
181
+ handling
182
+ - [CHANGELOG.md](CHANGELOG.md) — what actually changed per release
183
+ - [Migration guide](https://devilsdev.github.io/rag-pipeline-utils/docs/Migration)
184
+ — upgrade instructions between majors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devilsdev/rag-pipeline-utils",
3
- "version": "2.4.3",
3
+ "version": "2.4.4",
4
4
  "description": "Composable RAG for Node.js — with built-in evaluation, citations, guardrails, and observability.",
5
5
  "main": "dist/index.cjs",
6
6
  "type": "commonjs",
@@ -153,7 +153,9 @@
153
153
  "README.md",
154
154
  "LICENSE",
155
155
  "SECURITY.md",
156
- "CHANGELOG.md"
156
+ "CHANGELOG.md",
157
+ "BENCHMARKS.md",
158
+ "SEMVER.md"
157
159
  ],
158
160
  "publishConfig": {
159
161
  "access": "public"