@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.
Files changed (113) hide show
  1. package/{scripts → all/copy-overwrite/scripts}/check-conflict-markers.mjs +15 -8
  2. package/all/copy-overwrite/scripts/lisa-gates.mjs +1006 -14
  3. package/dist/cli/gate-report-upstream.d.ts +33 -4
  4. package/dist/cli/gate-report-upstream.d.ts.map +1 -1
  5. package/dist/cli/gate-report-upstream.js +69 -11
  6. package/dist/cli/gate-report-upstream.js.map +1 -1
  7. package/dist/cli/gate-report.d.ts.map +1 -1
  8. package/dist/cli/gate-report.js +2 -10
  9. package/dist/cli/gate-report.js.map +1 -1
  10. package/dist/configs/vitest/base.d.ts +16 -12
  11. package/dist/configs/vitest/base.d.ts.map +1 -1
  12. package/dist/configs/vitest/base.js +51 -0
  13. package/dist/configs/vitest/base.js.map +1 -1
  14. package/dist/configs/vitest/cdk.d.ts +2 -2
  15. package/dist/configs/vitest/cdk.d.ts.map +1 -1
  16. package/dist/configs/vitest/cdk.js +4 -2
  17. package/dist/configs/vitest/cdk.js.map +1 -1
  18. package/dist/configs/vitest/harper-fabric.d.ts +2 -2
  19. package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
  20. package/dist/configs/vitest/harper-fabric.js +4 -2
  21. package/dist/configs/vitest/harper-fabric.js.map +1 -1
  22. package/dist/configs/vitest/nestjs.d.ts +2 -2
  23. package/dist/configs/vitest/nestjs.d.ts.map +1 -1
  24. package/dist/configs/vitest/nestjs.js +4 -2
  25. package/dist/configs/vitest/nestjs.js.map +1 -1
  26. package/dist/configs/vitest/phaser.d.ts +2 -2
  27. package/dist/configs/vitest/phaser.d.ts.map +1 -1
  28. package/dist/configs/vitest/phaser.js +4 -2
  29. package/dist/configs/vitest/phaser.js.map +1 -1
  30. package/dist/configs/vitest/scratch-global-setup.d.ts +72 -0
  31. package/dist/configs/vitest/scratch-global-setup.d.ts.map +1 -0
  32. package/dist/configs/vitest/scratch-global-setup.js +168 -0
  33. package/dist/configs/vitest/scratch-global-setup.js.map +1 -0
  34. package/dist/configs/vitest/scratch-setup.d.ts +12 -0
  35. package/dist/configs/vitest/scratch-setup.d.ts.map +1 -0
  36. package/dist/configs/vitest/scratch-setup.js +70 -0
  37. package/dist/configs/vitest/scratch-setup.js.map +1 -0
  38. package/dist/configs/vitest/scratch.d.ts +192 -0
  39. package/dist/configs/vitest/scratch.d.ts.map +1 -0
  40. package/dist/configs/vitest/scratch.js +301 -0
  41. package/dist/configs/vitest/scratch.js.map +1 -0
  42. package/dist/configs/vitest/typescript.d.ts +2 -2
  43. package/dist/configs/vitest/typescript.d.ts.map +1 -1
  44. package/dist/configs/vitest/typescript.js +4 -2
  45. package/dist/configs/vitest/typescript.js.map +1 -1
  46. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  47. package/dist/core/lisa-owned-hash-ledger.js +19 -0
  48. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  49. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  50. package/dist/core/upstream-evidence-manifest.js +23 -6
  51. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  52. package/dist/migrations/ensure-seeded-gates.d.ts +47 -0
  53. package/dist/migrations/ensure-seeded-gates.d.ts.map +1 -0
  54. package/dist/migrations/ensure-seeded-gates.js +139 -0
  55. package/dist/migrations/ensure-seeded-gates.js.map +1 -0
  56. package/dist/migrations/index.d.ts +1 -0
  57. package/dist/migrations/index.d.ts.map +1 -1
  58. package/dist/migrations/index.js +3 -0
  59. package/dist/migrations/index.js.map +1 -1
  60. package/package.json +2 -2
  61. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  63. package/plugins/lisa-agy/plugin.json +1 -1
  64. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  66. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  67. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  68. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  72. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  73. package/plugins/lisa-expo-agy/plugin.json +1 -1
  74. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  77. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  78. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  79. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  82. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  83. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  84. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  87. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  88. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  89. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  92. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  93. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  94. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  97. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  98. package/plugins/lisa-rails-agy/plugin.json +1 -1
  99. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  100. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  102. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  103. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  104. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  105. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  106. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  107. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  108. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  109. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  110. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  111. package/typescript/copy-contents/.husky/pre-push +21 -0
  112. package/typescript/copy-overwrite/.prettierignore +1 -0
  113. 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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"}