@codyswann/lisa 3.58.0 → 3.59.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/{scripts → all/copy-overwrite/scripts}/check-conflict-markers.mjs +15 -8
- package/all/copy-overwrite/scripts/lisa-gates.mjs +1006 -14
- package/dist/cli/gate-report-upstream.d.ts +33 -4
- package/dist/cli/gate-report-upstream.d.ts.map +1 -1
- package/dist/cli/gate-report-upstream.js +69 -11
- package/dist/cli/gate-report-upstream.js.map +1 -1
- package/dist/cli/gate-report.d.ts.map +1 -1
- package/dist/cli/gate-report.js +2 -10
- package/dist/cli/gate-report.js.map +1 -1
- package/dist/configs/vitest/base.d.ts +16 -12
- package/dist/configs/vitest/base.d.ts.map +1 -1
- package/dist/configs/vitest/base.js +51 -0
- package/dist/configs/vitest/base.js.map +1 -1
- package/dist/configs/vitest/cdk.d.ts +2 -2
- package/dist/configs/vitest/cdk.d.ts.map +1 -1
- package/dist/configs/vitest/cdk.js +4 -2
- package/dist/configs/vitest/cdk.js.map +1 -1
- package/dist/configs/vitest/harper-fabric.d.ts +2 -2
- package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
- package/dist/configs/vitest/harper-fabric.js +4 -2
- package/dist/configs/vitest/harper-fabric.js.map +1 -1
- package/dist/configs/vitest/nestjs.d.ts +2 -2
- package/dist/configs/vitest/nestjs.d.ts.map +1 -1
- package/dist/configs/vitest/nestjs.js +4 -2
- package/dist/configs/vitest/nestjs.js.map +1 -1
- package/dist/configs/vitest/phaser.d.ts +2 -2
- package/dist/configs/vitest/phaser.d.ts.map +1 -1
- package/dist/configs/vitest/phaser.js +4 -2
- package/dist/configs/vitest/phaser.js.map +1 -1
- package/dist/configs/vitest/scratch-global-setup.d.ts +72 -0
- package/dist/configs/vitest/scratch-global-setup.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-global-setup.js +168 -0
- package/dist/configs/vitest/scratch-global-setup.js.map +1 -0
- package/dist/configs/vitest/scratch-setup.d.ts +12 -0
- package/dist/configs/vitest/scratch-setup.d.ts.map +1 -0
- package/dist/configs/vitest/scratch-setup.js +70 -0
- package/dist/configs/vitest/scratch-setup.js.map +1 -0
- package/dist/configs/vitest/scratch.d.ts +192 -0
- package/dist/configs/vitest/scratch.d.ts.map +1 -0
- package/dist/configs/vitest/scratch.js +301 -0
- package/dist/configs/vitest/scratch.js.map +1 -0
- package/dist/configs/vitest/typescript.d.ts +2 -2
- package/dist/configs/vitest/typescript.d.ts.map +1 -1
- package/dist/configs/vitest/typescript.js +4 -2
- package/dist/configs/vitest/typescript.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +19 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +23 -6
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/migrations/ensure-seeded-gates.d.ts +47 -0
- package/dist/migrations/ensure-seeded-gates.d.ts.map +1 -0
- package/dist/migrations/ensure-seeded-gates.js +139 -0
- package/dist/migrations/ensure-seeded-gates.js.map +1 -0
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +3 -0
- package/dist/migrations/index.js.map +1 -1
- package/package.json +2 -2
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/typescript/copy-contents/.husky/pre-push +21 -0
- package/typescript/copy-overwrite/.prettierignore +1 -0
- package/typescript/package-lisa/package.lisa.json +1 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upper bound on entries the namespace may hold once a run has torn down.
|
|
3
|
+
*
|
|
4
|
+
* A run allocates one root per process — the main process plus one per worker —
|
|
5
|
+
* and several runs share a workstation, so a healthy namespace legitimately
|
|
6
|
+
* holds tens of entries while work is in flight. This ceiling is not a tuning
|
|
7
|
+
* knob for that; it is the point past which the namespace is provably becoming
|
|
8
|
+
* the very thing it replaced.
|
|
9
|
+
*/
|
|
10
|
+
export declare const MAX_NAMESPACE_ENTRIES = 512;
|
|
11
|
+
/** What an inspection of the namespace found. */
|
|
12
|
+
export interface NamespaceResidue {
|
|
13
|
+
/** Entries whose owning process is gone but which were not removed */
|
|
14
|
+
readonly orphaned: readonly string[];
|
|
15
|
+
/** Entries that do not follow the run-root naming scheme at all */
|
|
16
|
+
readonly unrecognised: readonly string[];
|
|
17
|
+
/** Total entries present */
|
|
18
|
+
readonly total: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Classifies what is left in the namespace.
|
|
22
|
+
*
|
|
23
|
+
* `unrecognised` is the interesting bucket. The sweep identifies residue by
|
|
24
|
+
* parsing the owning pid out of a directory's name, so a change to that naming
|
|
25
|
+
* scheme does not break the sweep loudly — it makes the sweep silently match
|
|
26
|
+
* nothing while continuing to report success. Naming that case separately turns
|
|
27
|
+
* that regression into a failure instead of a slow leak.
|
|
28
|
+
* @param dir - Namespace directory to inspect
|
|
29
|
+
* @param alive - Liveness probe, overridable for tests
|
|
30
|
+
* @returns The classified residue.
|
|
31
|
+
*/
|
|
32
|
+
export declare const inspectNamespace: (dir?: string, alive?: (pid: number) => boolean) => NamespaceResidue;
|
|
33
|
+
/**
|
|
34
|
+
* Builds the failure message for a namespace that is accumulating.
|
|
35
|
+
*
|
|
36
|
+
* Every branch names the directory and the offending entries, because the
|
|
37
|
+
* failure this replaces was a 60-second timeout that named nothing.
|
|
38
|
+
*
|
|
39
|
+
* `unrecognised` is deliberately NOT a failure. It was, and it wedged: one
|
|
40
|
+
* foreign directory in the namespace failed every subsequent run, forever, with
|
|
41
|
+
* a message a downstream user could not act on. Those entries are reclaimed on
|
|
42
|
+
* age by the sweep instead. What remains here are the two conditions that mean
|
|
43
|
+
* this fix itself has stopped working — residue the sweep should have taken and
|
|
44
|
+
* did not, and a namespace growing without bound.
|
|
45
|
+
* @param dir - Namespace directory inspected
|
|
46
|
+
* @param residue - What the inspection found
|
|
47
|
+
* @returns The message, or `undefined` when the namespace is healthy.
|
|
48
|
+
*/
|
|
49
|
+
export declare const describeResidueFailure: (dir: string, residue: NamespaceResidue) => string | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Reclaims residue from previous runs, then refuses to start into a namespace
|
|
52
|
+
* that is accumulating.
|
|
53
|
+
* @throws When residue is present that the sweep cannot or did not reclaim.
|
|
54
|
+
*/
|
|
55
|
+
export declare const setup: () => void;
|
|
56
|
+
/**
|
|
57
|
+
* Reclaims what this run allocated.
|
|
58
|
+
*
|
|
59
|
+
* This hook cannot fail a run — see the module header: Vitest swallows a throw
|
|
60
|
+
* from here. So it does the one thing it can do reliably, which is the cleanup;
|
|
61
|
+
* the judgement is made by {@link setup} on the next run, where a throw is
|
|
62
|
+
* actually honoured.
|
|
63
|
+
*
|
|
64
|
+
* The namespace directory itself is deliberately left in place. Creating a name
|
|
65
|
+
* inside a saturated shared temp root is the expensive operation this whole
|
|
66
|
+
* module exists to stop paying repeatedly; keeping one directory forever means
|
|
67
|
+
* the cost is paid once on a machine rather than once per run, and it is what
|
|
68
|
+
* makes "one entry in the shared temp root, ever" literally true rather than
|
|
69
|
+
* approximately true.
|
|
70
|
+
*/
|
|
71
|
+
export declare const teardown: () => void;
|
|
72
|
+
//# sourceMappingURL=scratch-global-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch-global-setup.d.ts","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-global-setup.ts"],"names":[],"mappings":"AA8CA;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,mEAAmE;IACnE,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,4BAA4B;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAK,MAA8B,EACnC,QAAO,CAAC,GAAG,EAAE,MAAM,KAAK,OAAwB,KAC/C,gBAWF,CAAC;AAUF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,GACjC,KAAK,MAAM,EACX,SAAS,gBAAgB,KACxB,MAAM,GAAG,SAoBX,CAAC;AA2BF;;;;GAIG;AACH,eAAO,MAAM,KAAK,QAAO,IAYxB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,QAAQ,QAAO,IAE3B,CAAC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest Configuration - Scratch namespace lifecycle (global setup)
|
|
3
|
+
*
|
|
4
|
+
* Runs once in the main Vitest process, on either side of the whole run.
|
|
5
|
+
*
|
|
6
|
+
* `setup` reclaims residue left by runs that were killed and then REFUSES TO
|
|
7
|
+
* START a run whose namespace is accumulating — the accumulation being the
|
|
8
|
+
* entire defect this exists to prevent, arriving one directory at a time.
|
|
9
|
+
* `teardown` reclaims what this run allocated.
|
|
10
|
+
*
|
|
11
|
+
* The check is deliberately a hard failure. A previous version of this problem
|
|
12
|
+
* was invisible for a working day because every instrument that met the
|
|
13
|
+
* saturated directory returned something a caller could mistake for an answer:
|
|
14
|
+
* an empty count, a dead process, a plausible duration. A guard that merely
|
|
15
|
+
* printed a warning would reproduce exactly that.
|
|
16
|
+
*
|
|
17
|
+
* It lives in `setup` for a measured reason, not an aesthetic one. Vitest
|
|
18
|
+
* SWALLOWS a throw from globalSetup teardown: it prints `error during close`
|
|
19
|
+
* and the process still exits 0. The same throw from `setup` exits 1. Measured
|
|
20
|
+
* both ways on vitest 4.1.9 rather than assumed —
|
|
21
|
+
*
|
|
22
|
+
* ```
|
|
23
|
+
* teardown throws -> Test Files 1 passed ... error during close ... exit 0
|
|
24
|
+
* setup throws -> Error: PROBE: setup refused to start the run exit 1
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* — because the first draft of this module put the check in `teardown`, where
|
|
28
|
+
* it reported a real overflow into a stream nothing gated on. A guard placed in
|
|
29
|
+
* a hook the runner ignores is the exact defect this file was written to stop,
|
|
30
|
+
* reproduced inside the guard itself.
|
|
31
|
+
*
|
|
32
|
+
* Checking at the start rather than the end costs nothing that matters: a run's
|
|
33
|
+
* own residue is reclaimed by the next run's sweep, and the next run's check
|
|
34
|
+
* sees whatever that sweep could not take. Accumulation is a trend, and a trend
|
|
35
|
+
* is still visible one run later.
|
|
36
|
+
* @see {@link module:configs/vitest/scratch} for the reclaim rules
|
|
37
|
+
* @module configs/vitest/scratch-global-setup
|
|
38
|
+
*/
|
|
39
|
+
import { isProcessAlive, parseRunRootName, readNamespaceEntries, scratchNamespaceDir, sweepScratchNamespace, } from "./scratch.js";
|
|
40
|
+
/**
|
|
41
|
+
* Upper bound on entries the namespace may hold once a run has torn down.
|
|
42
|
+
*
|
|
43
|
+
* A run allocates one root per process — the main process plus one per worker —
|
|
44
|
+
* and several runs share a workstation, so a healthy namespace legitimately
|
|
45
|
+
* holds tens of entries while work is in flight. This ceiling is not a tuning
|
|
46
|
+
* knob for that; it is the point past which the namespace is provably becoming
|
|
47
|
+
* the very thing it replaced.
|
|
48
|
+
*/
|
|
49
|
+
export const MAX_NAMESPACE_ENTRIES = 512;
|
|
50
|
+
/**
|
|
51
|
+
* Classifies what is left in the namespace.
|
|
52
|
+
*
|
|
53
|
+
* `unrecognised` is the interesting bucket. The sweep identifies residue by
|
|
54
|
+
* parsing the owning pid out of a directory's name, so a change to that naming
|
|
55
|
+
* scheme does not break the sweep loudly — it makes the sweep silently match
|
|
56
|
+
* nothing while continuing to report success. Naming that case separately turns
|
|
57
|
+
* that regression into a failure instead of a slow leak.
|
|
58
|
+
* @param dir - Namespace directory to inspect
|
|
59
|
+
* @param alive - Liveness probe, overridable for tests
|
|
60
|
+
* @returns The classified residue.
|
|
61
|
+
*/
|
|
62
|
+
export const inspectNamespace = (dir = scratchNamespaceDir(), alive = isProcessAlive) => {
|
|
63
|
+
const entries = readNamespaceEntries(dir);
|
|
64
|
+
return {
|
|
65
|
+
orphaned: entries.filter(name => {
|
|
66
|
+
const owner = parseRunRootName(name);
|
|
67
|
+
return owner !== undefined && !alive(owner.pid);
|
|
68
|
+
}),
|
|
69
|
+
unrecognised: entries.filter(name => parseRunRootName(name) === undefined),
|
|
70
|
+
total: entries.length,
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Renders at most a handful of names for a failure message.
|
|
75
|
+
* @param names - Offending entry names
|
|
76
|
+
* @returns A comma-separated sample, elided beyond five.
|
|
77
|
+
*/
|
|
78
|
+
const sample = (names) => names.slice(0, 5).join(", ") + (names.length > 5 ? ", …" : "");
|
|
79
|
+
/**
|
|
80
|
+
* Builds the failure message for a namespace that is accumulating.
|
|
81
|
+
*
|
|
82
|
+
* Every branch names the directory and the offending entries, because the
|
|
83
|
+
* failure this replaces was a 60-second timeout that named nothing.
|
|
84
|
+
*
|
|
85
|
+
* `unrecognised` is deliberately NOT a failure. It was, and it wedged: one
|
|
86
|
+
* foreign directory in the namespace failed every subsequent run, forever, with
|
|
87
|
+
* a message a downstream user could not act on. Those entries are reclaimed on
|
|
88
|
+
* age by the sweep instead. What remains here are the two conditions that mean
|
|
89
|
+
* this fix itself has stopped working — residue the sweep should have taken and
|
|
90
|
+
* did not, and a namespace growing without bound.
|
|
91
|
+
* @param dir - Namespace directory inspected
|
|
92
|
+
* @param residue - What the inspection found
|
|
93
|
+
* @returns The message, or `undefined` when the namespace is healthy.
|
|
94
|
+
*/
|
|
95
|
+
export const describeResidueFailure = (dir, residue) => {
|
|
96
|
+
if (residue.orphaned.length > 0) {
|
|
97
|
+
return (`Test scratch namespace ${dir} still holds ${String(residue.orphaned.length)} ` +
|
|
98
|
+
`root(s) whose owning process is gone, after a sweep that should have ` +
|
|
99
|
+
`removed them: ${sample(residue.orphaned)}. Reclaim-on-start is not ` +
|
|
100
|
+
`working, so a killed run's residue is now permanent.`);
|
|
101
|
+
}
|
|
102
|
+
if (residue.total > MAX_NAMESPACE_ENTRIES) {
|
|
103
|
+
return (`Test scratch namespace ${dir} holds ${String(residue.total)} entries, past ` +
|
|
104
|
+
`the ceiling of ${String(MAX_NAMESPACE_ENTRIES)}. Scratch space is ` +
|
|
105
|
+
`accumulating rather than being reclaimed — the condition this guard ` +
|
|
106
|
+
`exists to prevent.`);
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Sweeps the namespace and reports what survived.
|
|
112
|
+
* @param dir - Namespace directory
|
|
113
|
+
* @returns The residue remaining after the sweep.
|
|
114
|
+
*/
|
|
115
|
+
const sweepThenInspect = (dir) => {
|
|
116
|
+
sweepScratchNamespace({ dir });
|
|
117
|
+
return inspectNamespace(dir);
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Audits the namespace, tolerating a sibling run's worker exiting mid-audit.
|
|
121
|
+
*
|
|
122
|
+
* That worker's root becomes orphaned in the window between the sweep and the
|
|
123
|
+
* inspection, through no fault of this run. Sweeping once more before treating
|
|
124
|
+
* an orphan as a defect keeps a guard built to catch a permanent leak from
|
|
125
|
+
* failing on a transient one.
|
|
126
|
+
* @param dir - Namespace directory
|
|
127
|
+
* @returns The residue to judge.
|
|
128
|
+
*/
|
|
129
|
+
const auditNamespace = (dir) => {
|
|
130
|
+
const first = sweepThenInspect(dir);
|
|
131
|
+
return first.orphaned.length > 0 ? sweepThenInspect(dir) : first;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Reclaims residue from previous runs, then refuses to start into a namespace
|
|
135
|
+
* that is accumulating.
|
|
136
|
+
* @throws When residue is present that the sweep cannot or did not reclaim.
|
|
137
|
+
*/
|
|
138
|
+
export const setup = () => {
|
|
139
|
+
// The namespace directory is not created here. `createRunRoot` makes it
|
|
140
|
+
// recursively in whichever worker allocates first, and both the sweep and the
|
|
141
|
+
// inspection treat an absent namespace as an empty one — so creating it would
|
|
142
|
+
// be a side effect ahead of the audit that buys nothing.
|
|
143
|
+
const dir = scratchNamespaceDir();
|
|
144
|
+
const residue = auditNamespace(dir);
|
|
145
|
+
const failure = describeResidueFailure(dir, residue);
|
|
146
|
+
if (failure !== undefined) {
|
|
147
|
+
throw new Error(failure);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Reclaims what this run allocated.
|
|
152
|
+
*
|
|
153
|
+
* This hook cannot fail a run — see the module header: Vitest swallows a throw
|
|
154
|
+
* from here. So it does the one thing it can do reliably, which is the cleanup;
|
|
155
|
+
* the judgement is made by {@link setup} on the next run, where a throw is
|
|
156
|
+
* actually honoured.
|
|
157
|
+
*
|
|
158
|
+
* The namespace directory itself is deliberately left in place. Creating a name
|
|
159
|
+
* inside a saturated shared temp root is the expensive operation this whole
|
|
160
|
+
* module exists to stop paying repeatedly; keeping one directory forever means
|
|
161
|
+
* the cost is paid once on a machine rather than once per run, and it is what
|
|
162
|
+
* makes "one entry in the shared temp root, ever" literally true rather than
|
|
163
|
+
* approximately true.
|
|
164
|
+
*/
|
|
165
|
+
export const teardown = () => {
|
|
166
|
+
sweepScratchNamespace({ dir: scratchNamespaceDir() });
|
|
167
|
+
};
|
|
168
|
+
//# sourceMappingURL=scratch-global-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch-global-setup.js","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-global-setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Points this process's temp directory at a run root it owns, creating the root
|
|
3
|
+
* on first call and reusing it afterwards.
|
|
4
|
+
*
|
|
5
|
+
* All three of `TMPDIR`, `TMP` and `TEMP` are set: Node reads `TMPDIR` on POSIX
|
|
6
|
+
* and `TEMP`/`TMP` on Windows, and non-Node tools spawned by fixtures read
|
|
7
|
+
* whichever their platform prefers. Setting one would leave the others pointing
|
|
8
|
+
* at the shared directory for exactly the callers hardest to see.
|
|
9
|
+
* @returns Absolute path of this process's run root.
|
|
10
|
+
*/
|
|
11
|
+
export declare const installScratchRoot: () => string;
|
|
12
|
+
//# sourceMappingURL=scratch-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch-setup.d.ts","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-setup.ts"],"names":[],"mappings":"AAgDA;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,QAAO,MA4BrC,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest Configuration - Per-process scratch redirection (setup file)
|
|
3
|
+
*
|
|
4
|
+
* Wired as a Vitest `setupFiles` entry, so it executes inside every test worker
|
|
5
|
+
* before any test file runs. It points `os.tmpdir()` at a run root this process
|
|
6
|
+
* owns, which relocates EVERY `mkdtemp(os.tmpdir())` call in the suite without
|
|
7
|
+
* editing a single test — in Lisa's own suite, 481 call sites across 211 files.
|
|
8
|
+
*
|
|
9
|
+
* `os.tmpdir()` re-reads the environment on every call rather than caching it at
|
|
10
|
+
* startup, which is the seam this relies on:
|
|
11
|
+
*
|
|
12
|
+
* ```
|
|
13
|
+
* $ node -e 'const os=require("os"); console.log(os.tmpdir());
|
|
14
|
+
* process.env.TMPDIR="/tmp/probe"; console.log(os.tmpdir())'
|
|
15
|
+
* /var/folders/<...>/T
|
|
16
|
+
* /tmp/probe
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Because the assignment mutates the process environment, subprocesses the
|
|
20
|
+
* tests spawn inherit the redirection too — a fixture's `git`, `npm pack` or
|
|
21
|
+
* `tsc` child writes into the same bounded root, so a child that outlives its
|
|
22
|
+
* test cannot leak into the shared directory either.
|
|
23
|
+
*
|
|
24
|
+
* The work is done once per process, not once per test file, even though Vitest
|
|
25
|
+
* re-executes setup files for each file.
|
|
26
|
+
* @see {@link module:configs/vitest/scratch} for why the root is shaped this way
|
|
27
|
+
* @module configs/vitest/scratch-setup
|
|
28
|
+
*/
|
|
29
|
+
import * as fs from "node:fs";
|
|
30
|
+
import { env } from "node:process";
|
|
31
|
+
import { SCRATCH_ROOT_ENV, reclaimAndCreateRunRoot, removeScratchDir, scratchBaseDir, scratchNamespaceDir, } from "./scratch.js";
|
|
32
|
+
/** Key under which the per-process run root is memoised. */
|
|
33
|
+
const RUN_ROOT_KEY = "__lisaScratchRunRoot__";
|
|
34
|
+
/**
|
|
35
|
+
* Points this process's temp directory at a run root it owns, creating the root
|
|
36
|
+
* on first call and reusing it afterwards.
|
|
37
|
+
*
|
|
38
|
+
* All three of `TMPDIR`, `TMP` and `TEMP` are set: Node reads `TMPDIR` on POSIX
|
|
39
|
+
* and `TEMP`/`TMP` on Windows, and non-Node tools spawned by fixtures read
|
|
40
|
+
* whichever their platform prefers. Setting one would leave the others pointing
|
|
41
|
+
* at the shared directory for exactly the callers hardest to see.
|
|
42
|
+
* @returns Absolute path of this process's run root.
|
|
43
|
+
*/
|
|
44
|
+
export const installScratchRoot = () => {
|
|
45
|
+
const scope = globalThis;
|
|
46
|
+
const existing = scope[RUN_ROOT_KEY];
|
|
47
|
+
if (existing !== undefined && fs.existsSync(existing)) {
|
|
48
|
+
return existing;
|
|
49
|
+
}
|
|
50
|
+
// Read before the redirection lands: `scratchNamespaceDir()` derives from
|
|
51
|
+
// `os.tmpdir()`, so once TMPDIR moves, a later call in this process — or in a
|
|
52
|
+
// child that inherits the environment — would otherwise compute a namespace
|
|
53
|
+
// NESTED INSIDE the run root and sweep the wrong directory. Recording the
|
|
54
|
+
// base makes the resolution idempotent under its own side effect.
|
|
55
|
+
const base = scratchBaseDir();
|
|
56
|
+
const root = reclaimAndCreateRunRoot(scratchNamespaceDir());
|
|
57
|
+
scope[RUN_ROOT_KEY] = root;
|
|
58
|
+
env[SCRATCH_ROOT_ENV] = base;
|
|
59
|
+
env["TMPDIR"] = root;
|
|
60
|
+
env["TMP"] = root;
|
|
61
|
+
env["TEMP"] = root;
|
|
62
|
+
// Covers an ordinary exit, including one where tests failed. A signalled exit
|
|
63
|
+
// does not run this — nothing can — and is handled by the next run's sweep.
|
|
64
|
+
process.once("exit", () => {
|
|
65
|
+
removeScratchDir(root);
|
|
66
|
+
});
|
|
67
|
+
return root;
|
|
68
|
+
};
|
|
69
|
+
installScratchRoot();
|
|
70
|
+
//# sourceMappingURL=scratch-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch-setup.js","sourceRoot":"","sources":["../../../src/configs/vitest/scratch-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,4DAA4D;AAC5D,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAQ9C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAW,EAAE;IAC7C,MAAM,KAAK,GAAG,UAA2B,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,0EAA0E;IAC1E,8EAA8E;IAC9E,4EAA4E;IAC5E,0EAA0E;IAC1E,kEAAkE;IAClE,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,uBAAuB,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE5D,KAAK,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;IAC3B,GAAG,CAAC,gBAAgB,CAAC,GAAG,IAAI,CAAC;IAC7B,GAAG,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;IACrB,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;IAClB,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAEnB,8EAA8E;IAC9E,4EAA4E;IAC5E,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;QACxB,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single directory name every Lisa scratch root nests under.
|
|
3
|
+
*
|
|
4
|
+
* The name is the contract: it is what makes "one entry in the shared temp
|
|
5
|
+
* root, ever" checkable, and what the sweep enumerates instead of the
|
|
6
|
+
* (unenumerable) platform root.
|
|
7
|
+
*/
|
|
8
|
+
export declare const SCRATCH_NAMESPACE = "lisa-scratch";
|
|
9
|
+
/** Prefix identifying a per-process run root inside the namespace. */
|
|
10
|
+
export declare const RUN_ROOT_PREFIX = "run-";
|
|
11
|
+
/**
|
|
12
|
+
* Backstop age after which a run root is reclaimed even though its recorded pid
|
|
13
|
+
* still resolves to a live process.
|
|
14
|
+
*
|
|
15
|
+
* Pids are recycled, so liveness alone can pin an abandoned root forever if an
|
|
16
|
+
* unrelated process happens to inherit its number. Six hours is longer than any
|
|
17
|
+
* legitimate suite and short enough that a recycled pid cannot hold a root
|
|
18
|
+
* across a working day.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DEFAULT_RECLAIM_AGE_MS: number;
|
|
21
|
+
/** Environment variable that relocates the namespace away from the platform temp root. */
|
|
22
|
+
export declare const SCRATCH_ROOT_ENV = "LISA_TEST_SCRATCH_ROOT";
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the directory the namespace lives in.
|
|
25
|
+
*
|
|
26
|
+
* Honours `LISA_TEST_SCRATCH_ROOT` first so an operator or CI job can point
|
|
27
|
+
* scratch space at a specific volume, then `os.tmpdir()` — which itself re-reads
|
|
28
|
+
* `TMPDIR` on every call, so the pre-existing `export TMPDIR=...` mitigation
|
|
29
|
+
* composes with this rather than being defeated by it.
|
|
30
|
+
* @returns Absolute path to the directory containing the scratch namespace.
|
|
31
|
+
*/
|
|
32
|
+
export declare const scratchBaseDir: () => string;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute path of the shared namespace directory.
|
|
35
|
+
* @returns Path to `<base>/lisa-scratch`.
|
|
36
|
+
*/
|
|
37
|
+
export declare const scratchNamespaceDir: () => string;
|
|
38
|
+
/**
|
|
39
|
+
* Builds the name of a per-process run root.
|
|
40
|
+
*
|
|
41
|
+
* The pid is encoded in the name because it is the only durable record of who
|
|
42
|
+
* owns the directory: a killed process leaves no other trace, and the sweep has
|
|
43
|
+
* to tell an abandoned root from one a sibling run is using right now.
|
|
44
|
+
* @param pid - Owning process id
|
|
45
|
+
* @param startedAt - Epoch milliseconds the root was created
|
|
46
|
+
* @param suffix - Random suffix disambiguating two roots created in the same millisecond
|
|
47
|
+
* @returns The directory name, without any leading path.
|
|
48
|
+
*/
|
|
49
|
+
export declare const runRootName: (pid: number, startedAt: number, suffix: string) => string;
|
|
50
|
+
/** Ownership recorded in a run root's directory name. */
|
|
51
|
+
export interface RunRootOwner {
|
|
52
|
+
/** Process id that created the root */
|
|
53
|
+
readonly pid: number;
|
|
54
|
+
/** Epoch milliseconds the root was created */
|
|
55
|
+
readonly startedAt: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Recovers the pid and creation time encoded in a run root's name.
|
|
59
|
+
* @param name - A directory name from inside the namespace
|
|
60
|
+
* @returns The owner, or `undefined` when the name was not produced by {@link runRootName}.
|
|
61
|
+
*/
|
|
62
|
+
export declare const parseRunRootName: (name: string) => RunRootOwner | undefined;
|
|
63
|
+
/** Inputs deciding whether one namespace entry may be removed. */
|
|
64
|
+
export interface ReclaimDecisionInput {
|
|
65
|
+
/** Directory name inside the namespace */
|
|
66
|
+
readonly name: string;
|
|
67
|
+
/** Current epoch milliseconds */
|
|
68
|
+
readonly now: number;
|
|
69
|
+
/** Reports whether a pid still resolves to a running process */
|
|
70
|
+
readonly isProcessAlive: (pid: number) => boolean;
|
|
71
|
+
/** Age after which a live-pid root is reclaimed anyway */
|
|
72
|
+
readonly maxAgeMs?: number;
|
|
73
|
+
/** Name of the caller's own root, which is never reclaimed */
|
|
74
|
+
readonly selfName?: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Decides whether a namespace entry is abandoned residue.
|
|
78
|
+
*
|
|
79
|
+
* A name this module did not produce is not judged here — see
|
|
80
|
+
* {@link isStaleForeignEntry}, which reclaims it on age alone. Deleting another
|
|
81
|
+
* tool's fresh data is not this sweep's business; leaving it forever would let
|
|
82
|
+
* one stray directory wedge every future run.
|
|
83
|
+
* @param input - The entry and the facts needed to judge it
|
|
84
|
+
* @param input.name - Directory name inside the namespace
|
|
85
|
+
* @param input.now - Current epoch milliseconds
|
|
86
|
+
* @param input.isProcessAlive - Liveness probe for the recorded pid
|
|
87
|
+
* @param input.maxAgeMs - Age after which a live-pid root is reclaimed anyway
|
|
88
|
+
* @param input.selfName - Caller's own root name, never reclaimed
|
|
89
|
+
* @returns True when the entry may be removed.
|
|
90
|
+
*/
|
|
91
|
+
export declare const isReclaimable: ({ name, now, isProcessAlive, maxAgeMs, selfName, }: ReclaimDecisionInput) => boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Reports whether a pid resolves to a running process.
|
|
94
|
+
*
|
|
95
|
+
* `kill(pid, 0)` sends no signal; it only asks the kernel whether the target
|
|
96
|
+
* exists. `EPERM` means it exists and belongs to someone else, which still
|
|
97
|
+
* counts as alive.
|
|
98
|
+
* @param pid - Process id to probe
|
|
99
|
+
* @returns True when a process with that id exists.
|
|
100
|
+
*/
|
|
101
|
+
export declare const isProcessAlive: (pid: number) => boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Decides whether an entry this module did not create may be removed.
|
|
104
|
+
*
|
|
105
|
+
* Age is the only signal available: a foreign name carries no owner, so there is
|
|
106
|
+
* nothing to ask the kernel about. Reclaiming on the same backstop the pid arm
|
|
107
|
+
* uses means the namespace self-heals from anything parked in it — an older
|
|
108
|
+
* release's naming scheme, a stray `mktemp` — without this sweep ever deleting
|
|
109
|
+
* something a live tool is still writing to.
|
|
110
|
+
*
|
|
111
|
+
* The alternative was to treat a foreign name as a hard failure. That was tried
|
|
112
|
+
* and rejected: it wedges permanently on one stray directory, and the message a
|
|
113
|
+
* downstream user gets — "run roots must be named by runRootName()" — names
|
|
114
|
+
* something they cannot act on.
|
|
115
|
+
* @param entryPath - Absolute path of the entry
|
|
116
|
+
* @param now - Current epoch milliseconds
|
|
117
|
+
* @param maxAgeMs - Age past which a foreign entry is reclaimed
|
|
118
|
+
* @returns True when the entry is old enough to remove.
|
|
119
|
+
*/
|
|
120
|
+
export declare const isStaleForeignEntry: (entryPath: string, now: number, maxAgeMs: number) => boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Lists the namespace's direct children, treating an absent namespace as empty.
|
|
123
|
+
*
|
|
124
|
+
* A directory that cannot be read is not a directory that is empty — but for the
|
|
125
|
+
* one case that occurs here, the namespace not existing yet, the two are the
|
|
126
|
+
* same answer and every caller wants to continue rather than fail.
|
|
127
|
+
* @param dir - Namespace directory to list
|
|
128
|
+
* @returns The entry names, or an empty list.
|
|
129
|
+
*/
|
|
130
|
+
export declare const readNamespaceEntries: (dir: string) => readonly string[];
|
|
131
|
+
/** Outcome of one sweep of the namespace. */
|
|
132
|
+
export interface SweepResult {
|
|
133
|
+
/** Names removed as abandoned residue */
|
|
134
|
+
readonly removed: readonly string[];
|
|
135
|
+
/** Names left in place because a live owner still holds them */
|
|
136
|
+
readonly kept: readonly string[];
|
|
137
|
+
}
|
|
138
|
+
/** Options controlling one sweep. */
|
|
139
|
+
export interface SweepOptions {
|
|
140
|
+
/** Namespace directory to sweep (defaults to the resolved namespace) */
|
|
141
|
+
readonly dir?: string;
|
|
142
|
+
/** Current epoch milliseconds */
|
|
143
|
+
readonly now?: number;
|
|
144
|
+
/** Liveness probe, overridable for tests */
|
|
145
|
+
readonly isProcessAlive?: (pid: number) => boolean;
|
|
146
|
+
/** Age after which a live-pid root is reclaimed anyway */
|
|
147
|
+
readonly maxAgeMs?: number;
|
|
148
|
+
/** Caller's own root name, never reclaimed */
|
|
149
|
+
readonly selfName?: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Removes abandoned run roots from the namespace.
|
|
153
|
+
*
|
|
154
|
+
* This is the arm of the design that survives a kill. It runs at the START of a
|
|
155
|
+
* run precisely because the run that leaked cannot be the one to clean up.
|
|
156
|
+
* @param options - Sweep inputs
|
|
157
|
+
* @param options.dir - Namespace directory to sweep
|
|
158
|
+
* @param options.now - Current epoch milliseconds
|
|
159
|
+
* @param options.isProcessAlive - Liveness probe for recorded pids
|
|
160
|
+
* @param options.maxAgeMs - Age after which a live-pid root is reclaimed anyway
|
|
161
|
+
* @param options.selfName - Caller's own root name, never reclaimed
|
|
162
|
+
* @returns Which entries were removed and which were kept.
|
|
163
|
+
*/
|
|
164
|
+
export declare const sweepScratchNamespace: ({ dir, now, isProcessAlive: alive, maxAgeMs, selfName, }?: SweepOptions) => SweepResult;
|
|
165
|
+
/**
|
|
166
|
+
* Creates a run root owned by the current process and returns its path.
|
|
167
|
+
* @param options - Overrides for the namespace directory and clock
|
|
168
|
+
* @param options.dir - Namespace directory to create the root inside
|
|
169
|
+
* @param options.now - Epoch milliseconds recorded in the root's name
|
|
170
|
+
* @returns Absolute path of this process's run root.
|
|
171
|
+
*/
|
|
172
|
+
export declare const createRunRoot: ({ dir, now, }?: {
|
|
173
|
+
readonly dir?: string;
|
|
174
|
+
readonly now?: number;
|
|
175
|
+
}) => string;
|
|
176
|
+
/**
|
|
177
|
+
* Reclaims abandoned roots, then allocates one for this process.
|
|
178
|
+
*
|
|
179
|
+
* The order is the point, and it is why this is one function rather than two
|
|
180
|
+
* calls at the call site: reclaiming AFTER allocating leaves a window in which
|
|
181
|
+
* the namespace holds both, and reclaiming somewhere else entirely is how a
|
|
182
|
+
* caller ends up allocating without ever reclaiming at all.
|
|
183
|
+
* @param dir - Namespace directory
|
|
184
|
+
* @returns Absolute path of the newly created run root.
|
|
185
|
+
*/
|
|
186
|
+
export declare const reclaimAndCreateRunRoot: (dir: string) => string;
|
|
187
|
+
/**
|
|
188
|
+
* Removes a directory tree, ignoring an already-absent path.
|
|
189
|
+
* @param dir - Directory to remove
|
|
190
|
+
*/
|
|
191
|
+
export declare const removeScratchDir: (dir: string) => void;
|
|
192
|
+
//# sourceMappingURL=scratch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scratch.d.ts","sourceRoot":"","sources":["../../../src/configs/vitest/scratch.ts"],"names":[],"mappings":"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"}
|