@stacknext/regression 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/docs/captures.md +92 -0
- package/docs/comparisons.md +86 -0
- package/docs/index.md +92 -0
- package/docs/storage.md +75 -0
- package/package.json +5 -4
package/dist/constants.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare const STACKNEXT_RUN_FORMAT = "stacknext-test-run";
|
|
|
2
2
|
export declare const STACKNEXT_BASELINE_FORMAT = "stacknext-baseline";
|
|
3
3
|
export declare const STACKNEXT_COMPARISON_FORMAT = "stacknext-comparison";
|
|
4
4
|
export declare const STACKNEXT_REGRESSION_FORMAT_VERSION = 1;
|
|
5
|
-
export declare const STACKNEXT_REGRESSION_ENGINE_VERSION = "0.
|
|
5
|
+
export declare const STACKNEXT_REGRESSION_ENGINE_VERSION = "0.10.0";
|
|
6
6
|
export declare const RUN_STATUSES: readonly ["running", "completed", "failed", "interrupted", "incomplete"];
|
|
7
7
|
export type RunStatus = (typeof RUN_STATUSES)[number];
|
|
8
8
|
export declare const SAMPLE_STATUSES: readonly ["passed", "failed", "timedOut", "skipped", "interrupted"];
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,uBAAuB,CAAA;AACxD,eAAO,MAAM,yBAAyB,uBAAuB,CAAA;AAC7D,eAAO,MAAM,2BAA2B,yBAAyB,CAAA;AACjE,eAAO,MAAM,mCAAmC,IAAI,CAAA;AACpD,eAAO,MAAM,mCAAmC,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,uBAAuB,CAAA;AACxD,eAAO,MAAM,yBAAyB,uBAAuB,CAAA;AAC7D,eAAO,MAAM,2BAA2B,yBAAyB,CAAA;AACjE,eAAO,MAAM,mCAAmC,IAAI,CAAA;AACpD,eAAO,MAAM,mCAAmC,WAAW,CAAA;AAE3D,eAAO,MAAM,YAAY,0EAMf,CAAA;AACV,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AAErD,eAAO,MAAM,eAAe,qEAMlB,CAAA;AACV,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3D,eAAO,MAAM,wBAAwB,0CAA2C,CAAA;AAChF,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE5E,eAAO,MAAM,oBAAoB,qCAAsC,CAAA;AACvE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAA;AAErE,eAAO,MAAM,mBAAmB,iEAKtB,CAAA;AACV,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEnE,eAAO,MAAM,qBAAqB,4CAA6C,CAAA;AAC/E,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEvE,eAAO,MAAM,uBAAuB,mEAM1B,CAAA;AACV,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3E,eAAO,MAAM,qBAAqB,QAAkC,CAAA;AACpE,eAAO,MAAM,mBAAmB,QAAuB,CAAA;AACvD,eAAO,MAAM,iBAAiB,QAAuB,CAAA;AAErD,eAAO,MAAM,0BAA0B;;;;;;;;CAQ7B,CAAA;AAEV,eAAO,MAAM,sBAAsB,krBAOzB,CAAA"}
|
package/dist/constants.js
CHANGED
|
@@ -2,7 +2,7 @@ export const STACKNEXT_RUN_FORMAT = 'stacknext-test-run';
|
|
|
2
2
|
export const STACKNEXT_BASELINE_FORMAT = 'stacknext-baseline';
|
|
3
3
|
export const STACKNEXT_COMPARISON_FORMAT = 'stacknext-comparison';
|
|
4
4
|
export const STACKNEXT_REGRESSION_FORMAT_VERSION = 1;
|
|
5
|
-
export const STACKNEXT_REGRESSION_ENGINE_VERSION = '0.
|
|
5
|
+
export const STACKNEXT_REGRESSION_ENGINE_VERSION = '0.10.0';
|
|
6
6
|
export const RUN_STATUSES = [
|
|
7
7
|
'running',
|
|
8
8
|
'completed',
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAA;AACxD,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAAoB,CAAA;AAC7D,MAAM,CAAC,MAAM,2BAA2B,GAAG,sBAAsB,CAAA;AACjE,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAA;AACpD,MAAM,CAAC,MAAM,mCAAmC,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,oBAAoB,CAAA;AACxD,MAAM,CAAC,MAAM,yBAAyB,GAAG,oBAAoB,CAAA;AAC7D,MAAM,CAAC,MAAM,2BAA2B,GAAG,sBAAsB,CAAA;AACjE,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,CAAA;AACpD,MAAM,CAAC,MAAM,mCAAmC,GAAG,QAAQ,CAAA;AAE3D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,SAAS;IACT,WAAW;IACX,QAAQ;IACR,aAAa;IACb,YAAY;CACJ,CAAA;AAGV,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,QAAQ;IACR,QAAQ;IACR,UAAU;IACV,SAAS;IACT,aAAa;CACL,CAAA;AAGV,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAA;AAGhF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAAU,EAAE,YAAY,CAAU,CAAA;AAGvE,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,UAAU;IACV,WAAW;IACX,WAAW;IACX,cAAc;CACN,CAAA;AAGV,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAU,CAAA;AAG/E,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,UAAU;IACV,OAAO;IACP,aAAa;IACb,OAAO;IACP,SAAS;CACD,CAAA;AAGV,MAAM,CAAC,MAAM,qBAAqB,GAAG,+BAA+B,CAAA;AACpE,MAAM,CAAC,MAAM,mBAAmB,GAAG,oBAAoB,CAAA;AACvD,MAAM,CAAC,MAAM,iBAAiB,GAAG,oBAAoB,CAAA;AAErD,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,UAAU,EAAE,CAAC;IACb,qBAAqB,EAAE,EAAE;IACzB,oBAAoB,EAAE,EAAE;IACxB,sBAAsB,EAAE,EAAE;IAC1B,qBAAqB,EAAE,EAAE;IACzB,kBAAkB,EAAE,CAAC;IACrB,iBAAiB,EAAE,KAAK;CAChB,CAAA;AAEV,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,+FAA+F;IAC/F,oGAAoG;IACpG,0GAA0G;IAC1G,yEAAyE;IACzE,2HAA2H;IAC3H,0KAA0K;CAClK,CAAA"}
|
package/docs/captures.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Captures and baselines
|
|
3
|
+
description: Test run, scenario and sample correlation model, statuses and baseline rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Captures and baselines
|
|
7
|
+
|
|
8
|
+
## Test run lifecycle
|
|
9
|
+
|
|
10
|
+
A run is created by the collector when `stacknext capture` starts a child test
|
|
11
|
+
command. The CLI passes the collector URL, token, run id and capture flag to the
|
|
12
|
+
child environment. The Playwright fixture submits each scenario sample. On exit,
|
|
13
|
+
the CLI completes the run and saves it under `.stacknext/runs`.
|
|
14
|
+
|
|
15
|
+
`TestRun` statuses:
|
|
16
|
+
|
|
17
|
+
| Status | Meaning |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `running` | Registry record is still live. |
|
|
20
|
+
| `completed` | The child exited successfully and telemetry is complete. |
|
|
21
|
+
| `failed` | The child command failed. |
|
|
22
|
+
| `interrupted` | The child received a signal. |
|
|
23
|
+
| `incomplete` | Finalization failed or required telemetry is missing. |
|
|
24
|
+
|
|
25
|
+
Only a `completed` run with verified samples can become a baseline. A failed or
|
|
26
|
+
incomplete run remains readable but supports no regression verdict.
|
|
27
|
+
|
|
28
|
+
## Scenario identity
|
|
29
|
+
|
|
30
|
+
`scenarioIdentity()` prefers, in order:
|
|
31
|
+
|
|
32
|
+
1. an explicit `stacknext.scenario` annotation;
|
|
33
|
+
2. the Playwright `testId`;
|
|
34
|
+
3. file + title + project.
|
|
35
|
+
|
|
36
|
+
Changing the annotation creates a new scenario with no matching baseline.
|
|
37
|
+
|
|
38
|
+
Captured runs use one Playwright worker. Parallel correlation is not verified.
|
|
39
|
+
|
|
40
|
+
## Samples and correlation
|
|
41
|
+
|
|
42
|
+
Each sample records the Playwright status, expected status, retry index, repeat
|
|
43
|
+
index, duration and capture time.
|
|
44
|
+
|
|
45
|
+
A trace reference is `verified` only when the collector:
|
|
46
|
+
|
|
47
|
+
1. finds the injected trace id; and
|
|
48
|
+
2. finds a server span whose parent is the injected span id.
|
|
49
|
+
|
|
50
|
+
There is no time-window, nearest-request or synthetic fallback. If correlation
|
|
51
|
+
is ambiguous, the sample is `incomplete` with a reason such as
|
|
52
|
+
`trace-not-found`, `injected-parent-not-found` or `no-request-trace-recorded`.
|
|
53
|
+
Incomplete samples make the affected comparison inconclusive.
|
|
54
|
+
|
|
55
|
+
Samples are capped at 100 per scenario, 20 traces per sample, and 500 spans,
|
|
56
|
+
200 queries and 100 errors per captured trace.
|
|
57
|
+
|
|
58
|
+
## Baselines
|
|
59
|
+
|
|
60
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
61
|
+
|
|
62
|
+
<!-- coderabbit-ai-generated-section:v1:82f70de6927a543f3381425f6ccfd4279d9449b3dc78859c33e5b620c80a7527 -->
|
|
63
|
+
|
|
64
|
+
Convert a completed run with `baselineFromRun(run, { name })`, then pass the
|
|
65
|
+
resulting `Baseline` to `saveBaseline(projectDir, baseline)` to persist the
|
|
66
|
+
immutable record. A baseline contains:
|
|
67
|
+
|
|
68
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
69
|
+
|
|
70
|
+
- `sourceRunId`, project name, scenario identities and samples;
|
|
71
|
+
- verified trace/query/error evidence;
|
|
72
|
+
- deterministic diagnostic finding references;
|
|
73
|
+
- environment snapshot;
|
|
74
|
+
- stats, notes and limitations.
|
|
75
|
+
|
|
76
|
+
A baseline does not follow later telemetry or application changes. It is never
|
|
77
|
+
auto-deleted. `stacknext baseline remove <id> --yes` is the explicit removal
|
|
78
|
+
path.
|
|
79
|
+
|
|
80
|
+
## Commands
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
stacknext capture --name baseline --quiet --json \
|
|
84
|
+
-- pnpm exec playwright test --workers=1 --repeat-each=3 > baseline.json
|
|
85
|
+
stacknext baseline save <run-id> --name baseline
|
|
86
|
+
stacknext capture --name candidate --quiet --json \
|
|
87
|
+
-- pnpm exec playwright test --workers=1 --repeat-each=3 > candidate.json
|
|
88
|
+
stacknext compare <baseline-id> <candidate-run-id> --fail-on regression
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
See the repository `docs/regression-testing.md` and
|
|
92
|
+
`@stacknext/playwright/docs/index.md`.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Comparisons
|
|
3
|
+
description: Deterministic median and threshold comparison, environment compatibility and inconclusive rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Comparisons
|
|
7
|
+
|
|
8
|
+
## API
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { compareBaseline } from '@stacknext/regression'
|
|
12
|
+
|
|
13
|
+
const comparison = compareBaseline(baseline, candidateRun, {
|
|
14
|
+
minSamples: 3,
|
|
15
|
+
durationRegressionPct: 20,
|
|
16
|
+
durationRegressionMs: 25,
|
|
17
|
+
durationImprovementPct: 20,
|
|
18
|
+
durationImprovementMs: 25,
|
|
19
|
+
countRegressionMin: 1,
|
|
20
|
+
ignoreEnvironment: false,
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`compareBaseline(baseline, candidate, options?, meta?)` returns a
|
|
25
|
+
`Comparison`. Ids and timestamps are never used to match scenarios or traces;
|
|
26
|
+
matching uses stored stable keys.
|
|
27
|
+
|
|
28
|
+
## Defaults
|
|
29
|
+
|
|
30
|
+
`DEFAULT_COMPARISON_OPTIONS`:
|
|
31
|
+
|
|
32
|
+
| Option | Default |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| `minSamples` | 3 |
|
|
35
|
+
| `durationRegressionPct` | 20 |
|
|
36
|
+
| `durationRegressionMs` | 25 |
|
|
37
|
+
| `durationImprovementPct` | 20 |
|
|
38
|
+
| `durationImprovementMs` | 25 |
|
|
39
|
+
| `countRegressionMin` | 1 |
|
|
40
|
+
| `ignoreEnvironment` | false |
|
|
41
|
+
|
|
42
|
+
A duration change must cross both the percent and absolute threshold to be
|
|
43
|
+
classified. Medians reduce noise.
|
|
44
|
+
|
|
45
|
+
## Status and severity
|
|
46
|
+
|
|
47
|
+
Statuses: `improved`, `regressed`, `unchanged`, `inconclusive`.
|
|
48
|
+
|
|
49
|
+
Severity: `high`, `medium`, `low`, `none`, reported separately from status.
|
|
50
|
+
|
|
51
|
+
`inconclusive` is not a pass. It means the evidence cannot support a verdict.
|
|
52
|
+
`unchanged` means no configured threshold was crossed in this sample, not proof
|
|
53
|
+
that nothing changed. `improved` is not automatically good: fewer spans or
|
|
54
|
+
queries can mean missing instrumentation or skipped work.
|
|
55
|
+
|
|
56
|
+
## Why a comparison becomes inconclusive
|
|
57
|
+
|
|
58
|
+
- environment differences, unless `ignoreEnvironment` is set (a warning is still
|
|
59
|
+
recorded);
|
|
60
|
+
- a candidate run that did not complete;
|
|
61
|
+
- incomplete or missing scenario correlation;
|
|
62
|
+
- fewer than `minSamples` verified samples per side;
|
|
63
|
+
- missing scenarios;
|
|
64
|
+
- variable trace shapes within one side or a changed trace key set;
|
|
65
|
+
- changed diagnostic rule-set versions;
|
|
66
|
+
- null database durations for a query-duration metric (unmeasured, not zero).
|
|
67
|
+
|
|
68
|
+
Environment facts include Node.js, Next.js, platform, architecture, runtime,
|
|
69
|
+
database adapters, instrumentation flags, verbose tracing, SDK version, rule-set
|
|
70
|
+
version and Playwright version.
|
|
71
|
+
|
|
72
|
+
## Metrics
|
|
73
|
+
|
|
74
|
+
Comparison metrics can be `duration`, `count`, `test-status`, `error` or
|
|
75
|
+
`finding` kinds. Evidence is bounded to 50 trace keys, 200 span keys, 100 query
|
|
76
|
+
keys, 100 finding keys and 1,000 metrics per scenario.
|
|
77
|
+
|
|
78
|
+
## What comparisons do not claim
|
|
79
|
+
|
|
80
|
+
- No statistical significance, confidence intervals, p-values or effect sizes.
|
|
81
|
+
- No causality.
|
|
82
|
+
- No source, SQL or index analysis.
|
|
83
|
+
- No automatic pass/fail unless the CLI `--fail-on` flag matches.
|
|
84
|
+
|
|
85
|
+
The full methodology is in
|
|
86
|
+
the repository `docs/comparison-methodology.md`.
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "@stacknext/regression"
|
|
3
|
+
description: Capture, baseline, comparison schemas and deterministic local storage for StackNext runtime regression testing.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @stacknext/regression
|
|
7
|
+
|
|
8
|
+
`@stacknext/regression` owns the data model behind `stacknext capture`,
|
|
9
|
+
`stacknext baseline`, `stacknext compare`, the Playwright fixture, the dashboard
|
|
10
|
+
regression views and the MCP regression tools.
|
|
11
|
+
|
|
12
|
+
## Who should read this
|
|
13
|
+
|
|
14
|
+
Maintainers and advanced users building on the regression records. This is an
|
|
15
|
+
**internal implementation package**; applications use the CLI and the optional
|
|
16
|
+
`@stacknext/playwright` fixture instead of importing it directly.
|
|
17
|
+
|
|
18
|
+
## Package boundary
|
|
19
|
+
|
|
20
|
+
`regression` depends on `@stacknext/core` and `@stacknext/diagnostics`. It does
|
|
21
|
+
not run Playwright itself, start a collector, serve HTTP or contact a remote
|
|
22
|
+
service. Storage is local and report-only.
|
|
23
|
+
|
|
24
|
+
## Public API
|
|
25
|
+
|
|
26
|
+
<!-- coderabbit-ai-generated:v1 -->
|
|
27
|
+
|
|
28
|
+
<!-- coderabbit-ai-generated-section:v1:27de812198c94ba1d63f3e6f4ab6e1cc83191a39d69ae91a0151c6ea756a7c51 -->
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import {
|
|
32
|
+
compareBaseline,
|
|
33
|
+
verifyTraceCorrelation,
|
|
34
|
+
capturedSampleFromSubmission,
|
|
35
|
+
buildEnvironmentSnapshot,
|
|
36
|
+
compareEnvironments,
|
|
37
|
+
saveRun,
|
|
38
|
+
loadRun,
|
|
39
|
+
listRuns,
|
|
40
|
+
saveBaseline,
|
|
41
|
+
loadBaseline,
|
|
42
|
+
listBaselines,
|
|
43
|
+
saveComparison,
|
|
44
|
+
loadComparison,
|
|
45
|
+
listComparisons,
|
|
46
|
+
createRunId,
|
|
47
|
+
createBaselineId,
|
|
48
|
+
createComparisonId,
|
|
49
|
+
createSampleId,
|
|
50
|
+
scenarioIdentity,
|
|
51
|
+
DEFAULT_COMPARISON_OPTIONS,
|
|
52
|
+
} from '@stacknext/regression'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
<!-- /coderabbit-ai-generated:v1 -->
|
|
56
|
+
|
|
57
|
+
See the installed declarations for every helper. The main concepts:
|
|
58
|
+
|
|
59
|
+
| Concept | Purpose |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `scenarioIdentity` | Stable `scn-...` id from an explicit annotation, test id or file/title/project fallback. |
|
|
62
|
+
| `verifyTraceCorrelation` | Accepts a sample only when the injected trace and a server span parented to the injected span exist. |
|
|
63
|
+
| `buildEnvironmentSnapshot` | Records Node.js, Next.js, OS, runtime, adapters, instrumentation, rule set and Playwright versions. |
|
|
64
|
+
| `compareEnvironments` | Lists environment differences before a comparison. |
|
|
65
|
+
| `compareBaseline` | Deterministic median/threshold comparison of a baseline and candidate. |
|
|
66
|
+
| `saveRun` / `saveBaseline` / `saveComparison` | Atomic local writes under `.stacknext`. |
|
|
67
|
+
|
|
68
|
+
## Formats
|
|
69
|
+
|
|
70
|
+
| Constant | Value |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| `STACKNEXT_RUN_FORMAT` | `stacknext-test-run` |
|
|
73
|
+
| `STACKNEXT_BASELINE_FORMAT` | `stacknext-baseline` |
|
|
74
|
+
| `STACKNEXT_COMPARISON_FORMAT` | `stacknext-comparison` |
|
|
75
|
+
| `STACKNEXT_REGRESSION_FORMAT_VERSION` | `1` |
|
|
76
|
+
| `STACKNEXT_REGRESSION_ENGINE_VERSION` | The installed package version |
|
|
77
|
+
|
|
78
|
+
Ids are strict: `run-<16 hex>`, `base-<16 hex>`, `cmp-<16 hex>`,
|
|
79
|
+
`scn-<16 hex>` and `smp-<16 hex>`.
|
|
80
|
+
|
|
81
|
+
## Documentation map
|
|
82
|
+
|
|
83
|
+
- [Captures](captures.md) — run and baseline lifecycle, correlation and statuses.
|
|
84
|
+
- [Comparisons](comparisons.md) — metrics, thresholds and inconclusive rules.
|
|
85
|
+
- [Storage](storage.md) — directories, permissions, atomic writes and retention.
|
|
86
|
+
|
|
87
|
+
## Related packages
|
|
88
|
+
|
|
89
|
+
- `@stacknext/playwright` submits correlated samples during `stacknext capture`.
|
|
90
|
+
- `@stacknext/cli` orchestrates capture, baseline and compare commands.
|
|
91
|
+
- `@stacknext/mcp` reads saved runs, baselines and comparisons.
|
|
92
|
+
- `@stacknext/dashboard` renders the same records.
|
package/docs/storage.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Storage
|
|
3
|
+
description: Regression record directories, permissions, atomic writes, validation and retention rules.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Storage
|
|
7
|
+
|
|
8
|
+
## Directories
|
|
9
|
+
|
|
10
|
+
Regression records live under the application's `.stacknext` directory:
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
.stacknext/
|
|
14
|
+
├── runs/ # run-<16 hex>.json
|
|
15
|
+
├── baselines/ # base-<16 hex>.json
|
|
16
|
+
└── comparisons/ # cmp-<16 hex>.json
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The directory is created with mode `0700`; record files use mode `0600`.
|
|
20
|
+
`.stacknext/.gitignore` ignores runtime state, but saved records remain local
|
|
21
|
+
debugging artifacts and should be reviewed before sharing.
|
|
22
|
+
|
|
23
|
+
## API
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import {
|
|
27
|
+
saveRun,
|
|
28
|
+
loadRun,
|
|
29
|
+
listRuns,
|
|
30
|
+
listAllRuns,
|
|
31
|
+
saveBaseline,
|
|
32
|
+
loadBaseline,
|
|
33
|
+
listBaselines,
|
|
34
|
+
saveComparison,
|
|
35
|
+
loadComparison,
|
|
36
|
+
listComparisons,
|
|
37
|
+
regressionDir,
|
|
38
|
+
runsDir,
|
|
39
|
+
baselinesDir,
|
|
40
|
+
comparisonsDir,
|
|
41
|
+
} from '@stacknext/regression'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Writes validate the full record with its versioned Zod schema before touching
|
|
45
|
+
disk. Writes are atomic. A record is never overwritten unless the caller passes
|
|
46
|
+
`overwrite: true`; the CLI only does that on an explicit `--overwrite` request.
|
|
47
|
+
|
|
48
|
+
## Listing
|
|
49
|
+
|
|
50
|
+
List functions return `{ items, total, limit, offset, invalid }`. `limit` is
|
|
51
|
+
clamped to 1–200 with a default of 50. Invalid ids and stale records are counted
|
|
52
|
+
in `invalid` and left visible; they are not repaired or silently deleted.
|
|
53
|
+
|
|
54
|
+
## Size and retention
|
|
55
|
+
|
|
56
|
+
- Each record is capped at 16 MiB.
|
|
57
|
+
- Runs, baselines and comparisons are **never pruned automatically**.
|
|
58
|
+
- StackNext never uploads records.
|
|
59
|
+
- `stacknext uninstall --remove-data` requires explicit confirmation and refuses
|
|
60
|
+
while a StackNext process is running.
|
|
61
|
+
|
|
62
|
+
## Invalid records
|
|
63
|
+
|
|
64
|
+
`RegressionStorageError` carries a code used by callers to distinguish
|
|
65
|
+
`invalid`, `not-found`, `exists` and storage failures. Invalid ids are rejected
|
|
66
|
+
before the filesystem is read. A malformed file is counted, not rewritten.
|
|
67
|
+
|
|
68
|
+
## Privacy
|
|
69
|
+
|
|
70
|
+
Records contain redacted scenario identity, trace/span/query/error evidence,
|
|
71
|
+
diagnostic references, environment facts and a sanitized command snapshot.
|
|
72
|
+
They never contain request/response bodies, headers, cookies, URL query values,
|
|
73
|
+
SQL bind parameters, Playwright screenshots/video/trace archives or the
|
|
74
|
+
collector token. The full boundary is in
|
|
75
|
+
the repository `docs/privacy.md`.
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacknext/regression",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Deterministic Playwright-linked runtime regression capture for StackNext",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"dist"
|
|
8
|
+
"dist",
|
|
9
|
+
"docs"
|
|
9
10
|
],
|
|
10
11
|
"main": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts",
|
|
@@ -18,8 +19,8 @@
|
|
|
18
19
|
"./package.json": "./package.json"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
|
-
"@stacknext/core": "0.
|
|
22
|
-
"@stacknext/diagnostics": "0.
|
|
22
|
+
"@stacknext/core": "0.10.0",
|
|
23
|
+
"@stacknext/diagnostics": "0.10.0",
|
|
23
24
|
"zod": "4.6.7"
|
|
24
25
|
},
|
|
25
26
|
"engines": {
|