@codyswann/lisa 4.28.5 → 4.29.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 (188) hide show
  1. package/all/copy-overwrite/scripts/lisa-gates.mjs +2 -1
  2. package/all/copy-overwrite/scripts/lisa-hooks/sonar-secrets.sh +3 -2
  3. package/cdk/create-only/vitest.config.local.ts +5 -1
  4. package/cdk/package-lisa/package.lisa.json +14 -7
  5. package/dist/cli/lisa-test-run-bootstrap.d.ts +3 -0
  6. package/dist/cli/lisa-test-run-bootstrap.d.ts.map +1 -0
  7. package/dist/cli/lisa-test-run-bootstrap.js +201 -0
  8. package/dist/cli/lisa-test-run-bootstrap.js.map +1 -0
  9. package/dist/cli/lisa-test-run-ipc.d.ts +42 -0
  10. package/dist/cli/lisa-test-run-ipc.d.ts.map +1 -0
  11. package/dist/cli/lisa-test-run-ipc.js +200 -0
  12. package/dist/cli/lisa-test-run-ipc.js.map +1 -0
  13. package/dist/cli/lisa-test-run-process-group.d.ts +30 -0
  14. package/dist/cli/lisa-test-run-process-group.d.ts.map +1 -0
  15. package/dist/cli/lisa-test-run-process-group.js +123 -0
  16. package/dist/cli/lisa-test-run-process-group.js.map +1 -0
  17. package/dist/cli/lisa-test-run-reaper.d.ts +3 -0
  18. package/dist/cli/lisa-test-run-reaper.d.ts.map +1 -0
  19. package/dist/cli/lisa-test-run-reaper.js +195 -0
  20. package/dist/cli/lisa-test-run-reaper.js.map +1 -0
  21. package/dist/cli/lisa-test-run-runtime.d.ts +46 -0
  22. package/dist/cli/lisa-test-run-runtime.d.ts.map +1 -0
  23. package/dist/cli/lisa-test-run-runtime.js +123 -0
  24. package/dist/cli/lisa-test-run-runtime.js.map +1 -0
  25. package/dist/cli/lisa-test-run-supervisor.d.ts +13 -0
  26. package/dist/cli/lisa-test-run-supervisor.d.ts.map +1 -0
  27. package/dist/cli/lisa-test-run-supervisor.js +268 -0
  28. package/dist/cli/lisa-test-run-supervisor.js.map +1 -0
  29. package/dist/cli/lisa-test-run.d.ts +3 -0
  30. package/dist/cli/lisa-test-run.d.ts.map +1 -0
  31. package/dist/cli/lisa-test-run.js +66 -0
  32. package/dist/cli/lisa-test-run.js.map +1 -0
  33. package/dist/configs/vitest/base.d.ts.map +1 -1
  34. package/dist/configs/vitest/base.js +5 -2
  35. package/dist/configs/vitest/base.js.map +1 -1
  36. package/dist/configs/vitest/cdk.d.ts +4 -0
  37. package/dist/configs/vitest/cdk.d.ts.map +1 -1
  38. package/dist/configs/vitest/cdk.js +5 -0
  39. package/dist/configs/vitest/cdk.js.map +1 -1
  40. package/dist/configs/vitest/harper-fabric.d.ts.map +1 -1
  41. package/dist/configs/vitest/harper-fabric.js +1 -0
  42. package/dist/configs/vitest/harper-fabric.js.map +1 -1
  43. package/dist/configs/vitest/nestjs.d.ts.map +1 -1
  44. package/dist/configs/vitest/nestjs.js +1 -0
  45. package/dist/configs/vitest/nestjs.js.map +1 -1
  46. package/dist/configs/vitest/phaser.d.ts.map +1 -1
  47. package/dist/configs/vitest/phaser.js +1 -0
  48. package/dist/configs/vitest/phaser.js.map +1 -1
  49. package/dist/configs/vitest/scratch-authority.d.ts +25 -0
  50. package/dist/configs/vitest/scratch-authority.d.ts.map +1 -0
  51. package/dist/configs/vitest/scratch-authority.js +107 -0
  52. package/dist/configs/vitest/scratch-authority.js.map +1 -0
  53. package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts +5 -0
  54. package/dist/configs/vitest/scratch-bound-cleanup-programs.d.ts.map +1 -0
  55. package/dist/configs/vitest/scratch-bound-cleanup-programs.js +219 -0
  56. package/dist/configs/vitest/scratch-bound-cleanup-programs.js.map +1 -0
  57. package/dist/configs/vitest/scratch-bound-cleanup.d.ts +28 -0
  58. package/dist/configs/vitest/scratch-bound-cleanup.d.ts.map +1 -0
  59. package/dist/configs/vitest/scratch-bound-cleanup.js +155 -0
  60. package/dist/configs/vitest/scratch-bound-cleanup.js.map +1 -0
  61. package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts +17 -0
  62. package/dist/configs/vitest/scratch-bound-root-cleanup.d.ts.map +1 -0
  63. package/dist/configs/vitest/scratch-bound-root-cleanup.js +149 -0
  64. package/dist/configs/vitest/scratch-bound-root-cleanup.js.map +1 -0
  65. package/dist/configs/vitest/scratch-global-setup.d.ts +17 -9
  66. package/dist/configs/vitest/scratch-global-setup.d.ts.map +1 -1
  67. package/dist/configs/vitest/scratch-global-setup.js +103 -35
  68. package/dist/configs/vitest/scratch-global-setup.js.map +1 -1
  69. package/dist/configs/vitest/scratch-leak-setup.d.ts +2 -0
  70. package/dist/configs/vitest/scratch-leak-setup.d.ts.map +1 -0
  71. package/dist/configs/vitest/scratch-leak-setup.js +108 -0
  72. package/dist/configs/vitest/scratch-leak-setup.js.map +1 -0
  73. package/dist/configs/vitest/scratch-namespace-authority.d.ts +80 -0
  74. package/dist/configs/vitest/scratch-namespace-authority.d.ts.map +1 -0
  75. package/dist/configs/vitest/scratch-namespace-authority.js +291 -0
  76. package/dist/configs/vitest/scratch-namespace-authority.js.map +1 -0
  77. package/dist/configs/vitest/scratch-owner.d.ts +131 -0
  78. package/dist/configs/vitest/scratch-owner.d.ts.map +1 -0
  79. package/dist/configs/vitest/scratch-owner.js +297 -0
  80. package/dist/configs/vitest/scratch-owner.js.map +1 -0
  81. package/dist/configs/vitest/scratch-route-profile.d.ts +36 -0
  82. package/dist/configs/vitest/scratch-route-profile.d.ts.map +1 -0
  83. package/dist/configs/vitest/scratch-route-profile.js +217 -0
  84. package/dist/configs/vitest/scratch-route-profile.js.map +1 -0
  85. package/dist/configs/vitest/scratch-run-root-compatibility.d.ts +33 -0
  86. package/dist/configs/vitest/scratch-run-root-compatibility.d.ts.map +1 -0
  87. package/dist/configs/vitest/scratch-run-root-compatibility.js +137 -0
  88. package/dist/configs/vitest/scratch-run-root-compatibility.js.map +1 -0
  89. package/dist/configs/vitest/scratch-run-root-intent.d.ts +66 -0
  90. package/dist/configs/vitest/scratch-run-root-intent.d.ts.map +1 -0
  91. package/dist/configs/vitest/scratch-run-root-intent.js +183 -0
  92. package/dist/configs/vitest/scratch-run-root-intent.js.map +1 -0
  93. package/dist/configs/vitest/scratch-setup.d.ts.map +1 -1
  94. package/dist/configs/vitest/scratch-setup.js +45 -15
  95. package/dist/configs/vitest/scratch-setup.js.map +1 -1
  96. package/dist/configs/vitest/scratch-supervision-intent.d.ts +8 -0
  97. package/dist/configs/vitest/scratch-supervision-intent.d.ts.map +1 -0
  98. package/dist/configs/vitest/scratch-supervision-intent.js +125 -0
  99. package/dist/configs/vitest/scratch-supervision-intent.js.map +1 -0
  100. package/dist/configs/vitest/scratch-supervision-protocol.d.ts +12 -0
  101. package/dist/configs/vitest/scratch-supervision-protocol.d.ts.map +1 -0
  102. package/dist/configs/vitest/scratch-supervision-protocol.js +230 -0
  103. package/dist/configs/vitest/scratch-supervision-protocol.js.map +1 -0
  104. package/dist/configs/vitest/scratch-supervision.d.ts +64 -0
  105. package/dist/configs/vitest/scratch-supervision.d.ts.map +1 -0
  106. package/dist/configs/vitest/scratch-supervision.js +209 -0
  107. package/dist/configs/vitest/scratch-supervision.js.map +1 -0
  108. package/dist/configs/vitest/scratch-sweep.d.ts +66 -0
  109. package/dist/configs/vitest/scratch-sweep.d.ts.map +1 -0
  110. package/dist/configs/vitest/scratch-sweep.js +82 -0
  111. package/dist/configs/vitest/scratch-sweep.js.map +1 -0
  112. package/dist/configs/vitest/scratch.d.ts +14 -187
  113. package/dist/configs/vitest/scratch.d.ts.map +1 -1
  114. package/dist/configs/vitest/scratch.js +18 -285
  115. package/dist/configs/vitest/scratch.js.map +1 -1
  116. package/dist/configs/vitest/typescript.d.ts.map +1 -1
  117. package/dist/configs/vitest/typescript.js +1 -0
  118. package/dist/configs/vitest/typescript.js.map +1 -1
  119. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  120. package/dist/core/lisa-owned-hash-ledger.js +4 -0
  121. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  122. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  123. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  124. package/dist/core/upstream-evidence-manifest.js +59 -13
  125. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  126. package/expo/package-lisa/package.lisa.json +14 -14
  127. package/harper-fabric/package-lisa/package.lisa.json +8 -3
  128. package/nestjs/create-only/vitest.config.local.ts +5 -1
  129. package/nestjs/package-lisa/package.lisa.json +14 -8
  130. package/npm-package/package-lisa/package.lisa.json +8 -0
  131. package/package.json +17 -13
  132. package/phaser/package-lisa/package.lisa.json +9 -3
  133. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  134. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  135. package/plugins/lisa/hooks/sonar-secrets.sh +3 -2
  136. package/plugins/lisa-agy/plugin.json +1 -1
  137. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  138. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  139. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  140. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  141. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  142. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  143. package/plugins/lisa-copilot/hooks/sonar-secrets.sh +3 -2
  144. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  145. package/plugins/lisa-cursor/hooks/sonar-secrets.sh +3 -2
  146. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  147. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  148. package/plugins/lisa-expo-agy/plugin.json +1 -1
  149. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  150. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  151. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  152. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  153. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  154. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  155. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  156. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  157. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  158. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  159. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  160. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  161. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  162. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  163. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  164. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  165. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  166. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  167. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  168. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  169. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  170. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  171. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  172. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  173. package/plugins/lisa-rails-agy/plugin.json +1 -1
  174. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  175. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  176. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  177. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  178. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  179. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  180. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  181. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  182. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  183. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  184. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  185. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  186. package/plugins/src/base/hooks/sonar-secrets.sh +3 -2
  187. package/typescript/create-only/vitest.config.local.ts +5 -1
  188. package/typescript/package-lisa/package.lisa.json +14 -8
@@ -1523,7 +1523,8 @@ const QUALITY_FALLBACKS = Object.freeze({
1523
1523
  ],
1524
1524
  },
1525
1525
  test_node_suites: {
1526
- command: "node <lisa>/scripts/lisa-test-node.mjs",
1526
+ command:
1527
+ "lisa-test-run --profile <stack-or-node> --adapter direct -- node <lisa>/scripts/lisa-test-node.mjs",
1527
1528
  seedRun: ["test:node"],
1528
1529
  steps: ["🧪 Run .mjs suites (lisa-test-node)"],
1529
1530
  },
@@ -137,10 +137,11 @@ is_inactive() {
137
137
  # The FIFO is a rendezvous, not storage: a named pipe holds no data at rest, so
138
138
  # the value still never lands on disk (CWE-922) and a kill at any point leaves an
139
139
  # empty pipe behind rather than a readable token. The directory is `mktemp -d`,
140
- # which is 0700.
140
+ # which is 0700. Its explicit Lisa prefix makes an interrupted resolver
141
+ # attributable to the owning scratch lifecycle instead of anonymous `tmp.*`.
141
142
  resolve_secret() {
142
143
  local resolver="$1" name="$2" value="" child="" dir="" fifo=""
143
- dir="$(mktemp -d)" || return 0
144
+ dir="$(mktemp -d "${TMPDIR:-/tmp}/lisa-sonar-resolver.XXXXXXXX")" || return 0
144
145
  fifo="$dir/resolver"
145
146
  if ! mkfifo -m 600 "$fifo" 2>/dev/null; then
146
147
  rm -rf "$dir"
@@ -28,7 +28,11 @@
28
28
  import type { ViteUserConfig } from "vitest/config";
29
29
 
30
30
  const config: ViteUserConfig = {
31
- // Add project-specific settings here
31
+ test: {
32
+ // Scratch redirection must install before the leak guard, and the guard's
33
+ // afterAll must run after project hooks so cleanup is attributed correctly.
34
+ sequence: { setupFiles: "list", hooks: "stack" },
35
+ },
32
36
  };
33
37
 
34
38
  export default config;
@@ -6,15 +6,16 @@
6
6
  "cdk": "cdk",
7
7
  "build": "tsc --noEmit",
8
8
  "prepare": "husky install || true",
9
- "test": "vitest run",
10
- "test:unit": "vitest run --exclude='**/integration/**'",
11
- "test:integration:lisa": "vitest run '.integration.' 'integration/'",
12
- "test:cov": "vitest run --coverage",
13
- "test:mutation": "node scripts/lisa-mutation.mjs",
14
- "test:watch": "vitest",
9
+ "test": "lisa-test-run --profile cdk --adapter vitest -- vitest run",
10
+ "test:unit": "lisa-test-run --profile cdk --adapter vitest -- vitest run --exclude='**/integration/**'",
11
+ "test:integration:lisa": "lisa-test-run --profile cdk --adapter vitest -- vitest run '.integration.' 'integration/'",
12
+ "test:cov": "lisa-test-run --profile cdk --adapter vitest -- vitest run --coverage",
13
+ "test:cov:unit": "LISA_COVERAGE_SCOPE=unit lisa-test-run --profile cdk --adapter vitest -- vitest run --coverage --exclude='**/integration/**'",
14
+ "test:mutation": "LISA_TEST_SCRATCH_PREFIXES='[\"lisa-mutation-\",\"worker-\"]' lisa-test-run --profile cdk --adapter direct -- node scripts/lisa-mutation.mjs",
15
+ "test:watch": "lisa-test-run --profile cdk --adapter vitest -- vitest",
15
16
  "lint:lisa": "oxlint && eslint . --quiet",
16
17
  "lint:fix": "oxlint --fix && eslint . --fix",
17
- "test:node": "node scripts/lisa-test-node.mjs"
18
+ "test:node": "LISA_TEST_SCRATCH_PREFIXES='[\"node-\"]' lisa-test-run --profile cdk --adapter direct -- node scripts/lisa-test-node.mjs"
18
19
  },
19
20
  "dependencies": {
20
21
  "aws-cdk-github-oidc": "^2.4.1",
@@ -68,6 +69,12 @@
68
69
  "adopt": {
69
70
  "scripts": {
70
71
  "test:integration": [
72
+ "lisa-test-run --profile cdk --adapter vitest -- vitest run '.integration.' 'integration/' --passWithNoTests",
73
+ "lisa-test-run --profile cdk --adapter vitest -- vitest run '.integration.' 'integration/'",
74
+ "lisa-test-run --profile cdk -- vitest run '.integration.' 'integration/' --passWithNoTests",
75
+ "lisa-test-run --profile cdk -- vitest run '.integration.' 'integration/'",
76
+ "lisa-test-run -- vitest run '.integration.' 'integration/' --passWithNoTests",
77
+ "lisa-test-run -- vitest run '.integration.' 'integration/'",
71
78
  "vitest run '.integration.' 'integration/' --passWithNoTests",
72
79
  "vitest run '.integration.' 'integration/'",
73
80
  "vitest run tests/integration",
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=lisa-test-run-bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-bootstrap.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-bootstrap.ts"],"names":[],"mappings":""}
@@ -0,0 +1,201 @@
1
+ #!/usr/bin/env node
2
+ /** Inert process-group leader that gates a supervised test payload on GO. */
3
+ import { spawn } from "node:child_process";
4
+ import { env } from "node:process";
5
+ import { parseScratchProtocolMessage } from "../configs/vitest/scratch-supervision.js";
6
+ /** Private deterministic IPC-close seam, never inherited by the payload. */
7
+ const TEST_FAULT_ENV = "LISA_TEST_RUN_TEST_FAULT";
8
+ /** Signals the foreground supervisor owns and the group leader must survive. */
9
+ const SUPERVISED_SIGNALS = [
10
+ "SIGINT",
11
+ "SIGTERM",
12
+ "SIGHUP",
13
+ ];
14
+ /**
15
+ * Parse the exact bounded inert command envelope.
16
+ * @param value - Parsed IPC command body
17
+ * @returns Validated command
18
+ */
19
+ function validateCommand(value) {
20
+ const candidate = value;
21
+ if (typeof value !== "object" ||
22
+ value === null ||
23
+ candidate.schema !== 1 ||
24
+ !Array.isArray(candidate.argv) ||
25
+ candidate.argv.length === 0 ||
26
+ !candidate.argv.every(argument => typeof argument === "string") ||
27
+ typeof candidate.env !== "object" ||
28
+ candidate.env === null ||
29
+ !Object.values(candidate.env).every(entry => typeof entry === "string")) {
30
+ throw new Error("Invalid lisa-test-run bootstrap command schema");
31
+ }
32
+ return candidate;
33
+ }
34
+ /**
35
+ * Forward one signal to the payload when it is still present.
36
+ * @param payload - Current payload process
37
+ * @param signal - Signal to deliver
38
+ */
39
+ function signalPayload(payload, signal) {
40
+ try {
41
+ payload?.kill(signal);
42
+ }
43
+ catch {
44
+ // A concurrently exiting payload is already drained.
45
+ }
46
+ }
47
+ /**
48
+ * Kill the payload and mark operational failure after channel loss.
49
+ * @param state - Bootstrap lifecycle state
50
+ */
51
+ function failClosed(state) {
52
+ if (state.failingClosed)
53
+ return;
54
+ // eslint-disable-next-line functional/immutable-data -- one-process protocol state transition
55
+ state.failingClosed = true;
56
+ if (!state.payloadExited)
57
+ signalPayload(state.payload, "SIGKILL");
58
+ process.exitCode = 1;
59
+ if (process.connected)
60
+ process.disconnect();
61
+ }
62
+ /**
63
+ * Send one exact response with callback-safe channel settlement.
64
+ * @param state - Bootstrap lifecycle state
65
+ * @param message - Exact protocol response
66
+ */
67
+ function sendResponse(state, message) {
68
+ const type = message["type"];
69
+ const fault = env[TEST_FAULT_ENV];
70
+ const closeForFault = (fault === "bootstrap-close-command-ready" && type === "COMMAND_READY") ||
71
+ (fault === "bootstrap-close-payload-exit" && type === "PAYLOAD_EXIT");
72
+ if (closeForFault && process.connected)
73
+ process.disconnect();
74
+ if (!process.connected || process.send === undefined) {
75
+ failClosed(state);
76
+ return;
77
+ }
78
+ try {
79
+ process.send(message, error => {
80
+ if (error !== null)
81
+ failClosed(state);
82
+ });
83
+ }
84
+ catch {
85
+ failClosed(state);
86
+ }
87
+ }
88
+ /**
89
+ * Start one payload only after the ordered COMMAND/GO handshake.
90
+ * @param state - Bootstrap lifecycle state
91
+ * @param command - Immutable payload command
92
+ */
93
+ function startPayload(state, command) {
94
+ // eslint-disable-next-line functional/immutable-data -- ordered protocol transition before spawn
95
+ state.phase = "running";
96
+ const payload = spawn(command.argv[0], command.argv.slice(1), {
97
+ cwd: process.cwd(),
98
+ env: command.env,
99
+ detached: false,
100
+ shell: false,
101
+ stdio: "inherit",
102
+ });
103
+ // eslint-disable-next-line functional/immutable-data -- single owned payload handle
104
+ state.payload = payload;
105
+ payload.once("error", error => {
106
+ sendResponse(state, {
107
+ schema: 1,
108
+ type: "PAYLOAD_ERROR",
109
+ message: error.message,
110
+ });
111
+ });
112
+ payload.once("exit", (code, signal) => {
113
+ // eslint-disable-next-line functional/immutable-data -- terminal payload state
114
+ state.payloadExited = true;
115
+ // eslint-disable-next-line functional/immutable-data -- terminal payload state
116
+ state.phase = "payload-exited";
117
+ sendResponse(state, { schema: 1, type: "PAYLOAD_EXIT", code, signal });
118
+ });
119
+ }
120
+ /**
121
+ * Deliver a forwarded signal, treating one outside `running` as the race it is.
122
+ *
123
+ * Two windows produce a legitimate out-of-phase SIGNAL: the supervisor arms its
124
+ * handlers before it sends GO, so a signal there arrives in `await-go`; and the
125
+ * payload's own exit records `payload-exited` before PAYLOAD_EXIT reaches the
126
+ * supervisor, so a signal forwarded in that gap arrives after there is anything
127
+ * left to signal. Refusing either would fail this process closed -- exit 1 and
128
+ * an abrupt disconnect -- reporting an ordinary signal-terminated run as a
129
+ * protocol refusal plus an unexpected channel loss.
130
+ * @param state - Bootstrap lifecycle state
131
+ * @param signal - Signal the supervisor forwarded
132
+ */
133
+ function forwardSignal(state, signal) {
134
+ if (state.phase !== "running")
135
+ return;
136
+ signalPayload(state.payload, signal);
137
+ }
138
+ /**
139
+ * Apply one already-validated message to the exact protocol phase.
140
+ * @param state - Bootstrap lifecycle state
141
+ * @param message - Untrusted IPC message
142
+ */
143
+ function handleMessage(state, message) {
144
+ const protocol = parseScratchProtocolMessage(message);
145
+ const type = protocol.type;
146
+ if (state.phase === "await-command" && type === "COMMAND") {
147
+ // eslint-disable-next-line functional/immutable-data -- command becomes immutable after the one accepted transition
148
+ state.command = validateCommand(protocol["command"]);
149
+ // eslint-disable-next-line functional/immutable-data -- ordered protocol transition
150
+ state.phase = "await-go";
151
+ sendResponse(state, { schema: 1, type: "COMMAND_READY" });
152
+ return;
153
+ }
154
+ if (state.phase === "await-go" && type === "GO" && state.command) {
155
+ startPayload(state, state.command);
156
+ return;
157
+ }
158
+ if (type === "SIGNAL") {
159
+ forwardSignal(state, protocol["signal"]);
160
+ return;
161
+ }
162
+ if (type === "STOP" && state.phase !== "stopping") {
163
+ // eslint-disable-next-line functional/immutable-data -- terminal protocol transition
164
+ state.phase = "stopping";
165
+ if (!state.payloadExited)
166
+ signalPayload(state.payload, "SIGKILL");
167
+ process.disconnect();
168
+ process.exit(0);
169
+ }
170
+ throw new Error(`Unexpected ${type} in bootstrap state ${state.phase}`);
171
+ }
172
+ /** Run the process-group leader protocol. */
173
+ function main() {
174
+ const state = {
175
+ payloadExited: false,
176
+ failingClosed: false,
177
+ phase: "await-command",
178
+ };
179
+ for (const signal of SUPERVISED_SIGNALS) {
180
+ process.on(signal, () => undefined);
181
+ }
182
+ sendResponse(state, { schema: 1, type: "BOOTSTRAP_READY", pid: process.pid });
183
+ process.on("message", message => {
184
+ try {
185
+ handleMessage(state, message);
186
+ }
187
+ catch (error) {
188
+ process.stderr.write(`lisa-test-run bootstrap refused protocol: ${error instanceof Error ? error.message : String(error)}\n`);
189
+ failClosed(state);
190
+ }
191
+ });
192
+ process.on("disconnect", () => failClosed(state));
193
+ }
194
+ try {
195
+ main();
196
+ }
197
+ catch (error) {
198
+ process.stderr.write(`lisa-test-run bootstrap failed: ${error instanceof Error ? error.message : String(error)}\n`);
199
+ process.exit(1);
200
+ }
201
+ //# sourceMappingURL=lisa-test-run-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-bootstrap.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /** Exact, bounded parent-side IPC operations for lisa-test-run companions. */
2
+ import type { ChildProcess } from "node:child_process";
3
+ import { type ScratchProtocolMessageV1 } from "../configs/vitest/scratch-supervision.js";
4
+ /** Child outcome retained until cleanup and disarm are proven. */
5
+ export interface PayloadOutcome {
6
+ readonly code: number | null;
7
+ readonly signal: NodeJS.Signals | null;
8
+ }
9
+ /**
10
+ * Wait for one exact child acknowledgement or fail closed.
11
+ * @param child - Protocol companion
12
+ * @param expected - Exact expected type
13
+ * @param correlation - Optional exact root token
14
+ * @returns Promise settled by the exact validated acknowledgement
15
+ */
16
+ export declare function waitForMessage(child: ChildProcess, expected: string, correlation?: string): Promise<ScratchProtocolMessageV1>;
17
+ /**
18
+ * Wait until a protocol companion is absent from the process table.
19
+ * @param child - Protocol companion
20
+ * @returns Promise settled after exit
21
+ */
22
+ export declare function waitForExit(child: ChildProcess): Promise<void>;
23
+ /**
24
+ * Send one versioned message or reject a closed IPC channel.
25
+ * @param child - Protocol companion
26
+ * @param message - Exact message body without schema
27
+ * @returns Callback-settled send promise
28
+ */
29
+ export declare function sendMessage(child: ChildProcess, message: Readonly<Record<string, unknown>>): Promise<void>;
30
+ /**
31
+ * Wait for the payload result and reject every other message.
32
+ * @param bootstrap - Inert bootstrap leader
33
+ * @param signalEscalating - Whether parent signal escalation owns its exit
34
+ * @returns Exact payload result
35
+ */
36
+ export declare function waitForPayload(bootstrap: ChildProcess, signalEscalating?: () => boolean): Promise<PayloadOutcome>;
37
+ /**
38
+ * Stop the inert leader and wait for it to leave the target group.
39
+ * @param bootstrap - Inert bootstrap leader
40
+ */
41
+ export declare function stopBootstrap(bootstrap: ChildProcess): Promise<void>;
42
+ //# sourceMappingURL=lisa-test-run-ipc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-ipc.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-ipc.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,0CAA0C,CAAC;AAgDlD,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;CACxC;AAOD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,wBAAwB,CAAC,CAsCnC;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACzC,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAYD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,YAAY,EACvB,gBAAgB,GAAE,MAAM,OAAqB,GAC5C,OAAO,CAAC,cAAc,CAAC,CAkCzB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAa1E"}
@@ -0,0 +1,200 @@
1
+ import { once } from "node:events";
2
+ import { env } from "node:process";
3
+ import { parseScratchProtocolMessage, } from "../configs/vitest/scratch-supervision.js";
4
+ /** Protocol timeout for one inert local acknowledgement. */
5
+ const ACK_TIMEOUT_MS = 10_000;
6
+ /** Private deterministic protocol-fault seam. */
7
+ const TEST_FAULT_ENV = "LISA_TEST_RUN_TEST_FAULT";
8
+ /**
9
+ * Whether one companion has already reached a terminal child-process state.
10
+ * @param child - Protocol companion
11
+ * @returns Whether Node has recorded an exit code or terminal signal
12
+ */
13
+ function companionExited(child) {
14
+ return child.exitCode !== null || child.signalCode !== null;
15
+ }
16
+ /**
17
+ * Arm one listener-first, cancellable, bounded companion-exit wait.
18
+ * @param child - Protocol companion
19
+ * @returns Exit promise and listener/timer cancellation
20
+ */
21
+ function boundedExitWait(child) {
22
+ const controller = new AbortController();
23
+ const exitEvent = once(child, "exit", { signal: controller.signal }).then(() => undefined);
24
+ const observedExit = companionExited(child) ? Promise.resolve() : exitEvent;
25
+ const timeout = new Promise((_resolve, reject) => {
26
+ const timer = setTimeout(() => reject(new Error("Timed out waiting for bootstrap shutdown")), ACK_TIMEOUT_MS);
27
+ controller.signal.addEventListener("abort", () => clearTimeout(timer), {
28
+ once: true,
29
+ });
30
+ });
31
+ return {
32
+ promise: Promise.race([observedExit, timeout]).finally(() => controller.abort()),
33
+ cancel: () => controller.abort(),
34
+ };
35
+ }
36
+ /** Deterministic test-only representation of a closed IPC transport. */
37
+ class ClosedIpcChannelError extends Error {
38
+ code = "ERR_IPC_CHANNEL_CLOSED";
39
+ }
40
+ /**
41
+ * Wait for one exact child acknowledgement or fail closed.
42
+ * @param child - Protocol companion
43
+ * @param expected - Exact expected type
44
+ * @param correlation - Optional exact root token
45
+ * @returns Promise settled by the exact validated acknowledgement
46
+ */
47
+ export function waitForMessage(child, expected, correlation) {
48
+ return new Promise((resolve, reject) => {
49
+ const timer = setTimeout(() => {
50
+ cleanup();
51
+ reject(new Error(`Timed out waiting for ${expected}`));
52
+ }, ACK_TIMEOUT_MS);
53
+ const onMessage = (message) => {
54
+ try {
55
+ const value = parseScratchProtocolMessage(message);
56
+ if (value.type !== expected ||
57
+ (correlation !== undefined && value["correlation"] !== correlation) ||
58
+ (correlation === undefined && Object.hasOwn(value, "correlation"))) {
59
+ throw new Error(`Unexpected ${value.type} while waiting for ${expected}`);
60
+ }
61
+ cleanup();
62
+ resolve(value);
63
+ }
64
+ catch (error) {
65
+ cleanup();
66
+ reject(error);
67
+ }
68
+ };
69
+ const onExit = () => {
70
+ cleanup();
71
+ reject(new Error(`Protocol process exited before ${expected}`));
72
+ };
73
+ const cleanup = () => {
74
+ clearTimeout(timer);
75
+ child.off("message", onMessage);
76
+ child.off("exit", onExit);
77
+ };
78
+ child.on("message", onMessage);
79
+ child.once("exit", onExit);
80
+ if (companionExited(child))
81
+ onExit();
82
+ });
83
+ }
84
+ /**
85
+ * Wait until a protocol companion is absent from the process table.
86
+ * @param child - Protocol companion
87
+ * @returns Promise settled after exit
88
+ */
89
+ export function waitForExit(child) {
90
+ if (child.exitCode !== null || child.signalCode !== null) {
91
+ return Promise.resolve();
92
+ }
93
+ return new Promise(resolve => child.once("exit", () => resolve()));
94
+ }
95
+ /**
96
+ * Send one versioned message or reject a closed IPC channel.
97
+ * @param child - Protocol companion
98
+ * @param message - Exact message body without schema
99
+ * @returns Callback-settled send promise
100
+ */
101
+ export function sendMessage(child, message) {
102
+ if (env[TEST_FAULT_ENV] === "signal-send-rejected" &&
103
+ message["type"] === "SIGNAL") {
104
+ return Promise.reject(new Error("deterministic signal-send rejection"));
105
+ }
106
+ if (env[TEST_FAULT_ENV] === "stop-send-rejected" &&
107
+ message["type"] === "STOP") {
108
+ return Promise.reject(new Error("deterministic STOP send rejection"));
109
+ }
110
+ if (env[TEST_FAULT_ENV] === "stop-send-closed" &&
111
+ message["type"] === "STOP") {
112
+ return new Promise((_resolve, reject) => {
113
+ child.send({ schema: 1, ...message }, () => {
114
+ reject(new ClosedIpcChannelError("deterministic closed STOP channel"));
115
+ });
116
+ });
117
+ }
118
+ return new Promise((resolve, reject) => {
119
+ child.send({ schema: 1, ...message }, error => {
120
+ if (error === null)
121
+ resolve();
122
+ else
123
+ reject(error);
124
+ });
125
+ });
126
+ }
127
+ /**
128
+ * Whether an IPC send failure proves the channel is already unusable.
129
+ * @param error - IPC callback or synchronous error
130
+ * @returns Whether the channel is conclusively closed
131
+ */
132
+ function isClosedIpcError(error) {
133
+ const code = error.code;
134
+ return code === "ERR_IPC_CHANNEL_CLOSED" || code === "ERR_IPC_DISCONNECTED";
135
+ }
136
+ /**
137
+ * Wait for the payload result and reject every other message.
138
+ * @param bootstrap - Inert bootstrap leader
139
+ * @param signalEscalating - Whether parent signal escalation owns its exit
140
+ * @returns Exact payload result
141
+ */
142
+ export function waitForPayload(bootstrap, signalEscalating = () => false) {
143
+ return new Promise((resolve, reject) => {
144
+ const onMessage = (message) => {
145
+ try {
146
+ const value = parseScratchProtocolMessage(message);
147
+ if (value.type === "PAYLOAD_ERROR") {
148
+ throw new Error(value["message"]);
149
+ }
150
+ if (value.type !== "PAYLOAD_EXIT") {
151
+ throw new Error(`Unexpected ${value.type} during payload execution`);
152
+ }
153
+ cleanup();
154
+ resolve({
155
+ code: value["code"],
156
+ signal: value["signal"],
157
+ });
158
+ }
159
+ catch (error) {
160
+ cleanup();
161
+ reject(error);
162
+ }
163
+ };
164
+ const onExit = () => {
165
+ cleanup();
166
+ if (signalEscalating())
167
+ return;
168
+ reject(new Error("Bootstrap exited before reporting payload result"));
169
+ };
170
+ const cleanup = () => {
171
+ bootstrap.off("message", onMessage);
172
+ bootstrap.off("exit", onExit);
173
+ };
174
+ bootstrap.on("message", onMessage);
175
+ bootstrap.once("exit", onExit);
176
+ if (companionExited(bootstrap))
177
+ onExit();
178
+ });
179
+ }
180
+ /**
181
+ * Stop the inert leader and wait for it to leave the target group.
182
+ * @param bootstrap - Inert bootstrap leader
183
+ */
184
+ export async function stopBootstrap(bootstrap) {
185
+ if (companionExited(bootstrap))
186
+ return;
187
+ const exitWait = boundedExitWait(bootstrap);
188
+ try {
189
+ await sendMessage(bootstrap, { type: "STOP" });
190
+ }
191
+ catch (error) {
192
+ if (!companionExited(bootstrap) && !isClosedIpcError(error)) {
193
+ exitWait.cancel();
194
+ await exitWait.promise.catch(() => undefined);
195
+ throw error;
196
+ }
197
+ }
198
+ await exitWait.promise;
199
+ }
200
+ //# sourceMappingURL=lisa-test-run-ipc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-ipc.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-ipc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Reject unsupported platforms before any scratch root or companion exists.
3
+ * @param platform - Runtime platform
4
+ */
5
+ export declare function assertTestRunPlatform(platform?: NodeJS.Platform): void;
6
+ /** Armed bootstrap leader and process-group identity. */
7
+ export interface TestRunTargetIntent {
8
+ readonly pid: number;
9
+ readonly pgid: number;
10
+ readonly processBirthFingerprint: string;
11
+ }
12
+ /** Injectable probes used to deterministically prove fail-closed authority. */
13
+ export interface TestRunProcessGroupProbes {
14
+ readonly isProcessAlive: (pid: number) => boolean;
15
+ readonly processBirthFingerprint: (pid: number) => string | undefined;
16
+ readonly processGroupAlive: (pgid: number) => boolean;
17
+ readonly signalGroup: (pgid: number, signal: NodeJS.Signals) => void;
18
+ readonly delay: (milliseconds: number) => Promise<void>;
19
+ }
20
+ /** Optional probe overrides for one drain attempt. */
21
+ export interface DrainTestRunTargetOptions {
22
+ readonly probes?: Partial<TestRunProcessGroupProbes>;
23
+ }
24
+ /**
25
+ * Drain only the group whose leader still has its armed process birth.
26
+ * @param target - Armed leader and group identity
27
+ * @param options - Optional deterministic probe overrides
28
+ */
29
+ export declare function drainTestRunTarget(target: TestRunTargetIntent | undefined, options?: DrainTestRunTargetOptions): Promise<void>;
30
+ //# sourceMappingURL=lisa-test-run-process-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-process-group.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-process-group.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,IAAI,CAMN;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;CAC1C;AAED,+EAA+E;AAC/E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAClD,QAAQ,CAAC,uBAAuB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtE,QAAQ,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,sDAAsD;AACtD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,CAAC;CACtD;AAqFD;;;;GAIG;AAEH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,mBAAmB,GAAG,SAAS,EACvC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,IAAI,CAAC,CAkCf"}