@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
@@ -0,0 +1,123 @@
1
+ /** Birth-bound process-group draining shared by the supervisor and reaper. */
2
+ import { isProcessAlive } from "../configs/vitest/scratch.js";
3
+ import { processBirthFingerprint } from "../configs/vitest/scratch-owner.js";
4
+ /**
5
+ * Reject unsupported platforms before any scratch root or companion exists.
6
+ * @param platform - Runtime platform
7
+ */
8
+ export function assertTestRunPlatform(platform = process.platform) {
9
+ if (platform !== "darwin" && platform !== "linux") {
10
+ throw new Error(`lisa-test-run requires Darwin or Linux process-group authority; received ${platform}`);
11
+ }
12
+ }
13
+ /** Time allowed for each process-group drain phase. */
14
+ const DRAIN_GRACE_MS = 2_000;
15
+ /** Poll interval for bounded group drain. */
16
+ const DRAIN_POLL_MS = 25;
17
+ /** Attempts allowed when a live process has no readable birth fingerprint. */
18
+ const BIRTH_PROBE_ATTEMPTS = 4;
19
+ /**
20
+ * Whether any member still occupies a process group.
21
+ * @param pgid - Armed process-group identifier
22
+ * @returns Whether the group still resolves
23
+ */
24
+ function processGroupAlive(pgid) {
25
+ try {
26
+ process.kill(-pgid, 0);
27
+ return true;
28
+ }
29
+ catch (error) {
30
+ return error.code === "EPERM";
31
+ }
32
+ }
33
+ /**
34
+ * Signal a group without turning an already-absent group into a failure.
35
+ * @param pgid - Armed process-group identifier
36
+ * @param signal - Signal to deliver
37
+ */
38
+ function signalGroup(pgid, signal) {
39
+ try {
40
+ process.kill(-pgid, signal);
41
+ }
42
+ catch (error) {
43
+ const code = error.code;
44
+ if (code !== "ESRCH" && code !== "EPERM")
45
+ throw error;
46
+ }
47
+ }
48
+ /**
49
+ * Wait without leaving a permanent timer handle.
50
+ * @param milliseconds - Bounded poll delay
51
+ * @returns Promise settled after the delay
52
+ */
53
+ const delay = async (milliseconds) => await new Promise(resolve => setTimeout(resolve, milliseconds));
54
+ /** Real operating-system probes used outside deterministic unit controls. */
55
+ const DEFAULT_PROBES = {
56
+ isProcessAlive,
57
+ processBirthFingerprint,
58
+ processGroupAlive,
59
+ signalGroup,
60
+ delay,
61
+ };
62
+ /**
63
+ * Establish that a live leader is still the exact process originally armed.
64
+ * @param target - Armed leader identity
65
+ * @param probes - Operating-system probes
66
+ * @param attempt - Current bounded unavailable-probe attempt
67
+ * @returns Whether the armed leader remains present with birth authority
68
+ */
69
+ async function assertTargetBirthAuthority(target, probes, attempt = 0) {
70
+ if (!probes.isProcessAlive(target.pid))
71
+ return false;
72
+ const observed = probes.processBirthFingerprint(target.pid);
73
+ if (observed === target.processBirthFingerprint)
74
+ return true;
75
+ if (observed !== undefined) {
76
+ throw new Error("target leader process-birth fingerprint changed; refusing group signal");
77
+ }
78
+ if (attempt + 1 < BIRTH_PROBE_ATTEMPTS) {
79
+ await probes.delay(DRAIN_POLL_MS);
80
+ return await assertTargetBirthAuthority(target, probes, attempt + 1);
81
+ }
82
+ throw new Error("target leader process-birth fingerprint remained unavailable");
83
+ }
84
+ /**
85
+ * Drain only the group whose leader still has its armed process birth.
86
+ * @param target - Armed leader and group identity
87
+ * @param options - Optional deterministic probe overrides
88
+ */
89
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- fail-closed birth and two-phase signal authority are one bounded decision
90
+ export async function drainTestRunTarget(target, options = {}) {
91
+ if (target === undefined)
92
+ return;
93
+ const probes = { ...DEFAULT_PROBES, ...options.probes };
94
+ const targetPresent = await assertTargetBirthAuthority(target, probes);
95
+ const groupPresent = probes.processGroupAlive(target.pgid);
96
+ if (!targetPresent) {
97
+ if (groupPresent) {
98
+ throw new Error("target leader is absent while its process group is live; refusing group signal");
99
+ }
100
+ return;
101
+ }
102
+ if (!groupPresent)
103
+ return;
104
+ const deadline = Date.now() + DRAIN_GRACE_MS;
105
+ probes.signalGroup(target.pgid, "SIGTERM");
106
+ while (probes.processGroupAlive(target.pgid) && Date.now() < deadline) {
107
+ await probes.delay(DRAIN_POLL_MS);
108
+ }
109
+ if (probes.processGroupAlive(target.pgid)) {
110
+ if (!(await assertTargetBirthAuthority(target, probes))) {
111
+ throw new Error("target leader is absent while its process group is live; refusing group signal");
112
+ }
113
+ const killDeadline = Date.now() + DRAIN_GRACE_MS;
114
+ probes.signalGroup(target.pgid, "SIGKILL");
115
+ while (probes.processGroupAlive(target.pgid) && Date.now() < killDeadline) {
116
+ await probes.delay(DRAIN_POLL_MS);
117
+ }
118
+ }
119
+ if (probes.processGroupAlive(target.pgid)) {
120
+ throw new Error("target process group survived bounded drain");
121
+ }
122
+ }
123
+ //# sourceMappingURL=lisa-test-run-process-group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-process-group.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-process-group.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=lisa-test-run-reaper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-reaper.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-reaper.ts"],"names":[],"mappings":""}
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env node
2
+ /** Detached one-run reaper for supervisor death and scratch cleanup. */
3
+ import { env } from "node:process";
4
+ import { materializeOwnedScratchRunRoot, openOwnedScratchRunRoot, removeOwnedScratchRunRoot, } from "../configs/vitest/scratch.js";
5
+ import { processBirthFingerprint, writeScratchOwnerRecord, } from "../configs/vitest/scratch-owner.js";
6
+ import { parseScratchProtocolMessage, validateScratchRunRootIntent, } from "../configs/vitest/scratch-supervision.js";
7
+ import { drainTestRunTarget, } from "./lisa-test-run-process-group.js";
8
+ /** Private deterministic fault seam, stripped before payload execution. */
9
+ const TEST_FAULT_ENV = "LISA_TEST_RUN_TEST_FAULT";
10
+ /**
11
+ * Validate and arm one pre-materialization root intent.
12
+ * @param value - Exact root-intent message
13
+ * @returns Immutable root intent
14
+ */
15
+ function armRootIntent(value) {
16
+ const candidate = validateScratchRunRootIntent(value["intent"]);
17
+ if (value["correlation"] !== candidate.token ||
18
+ openOwnedScratchRunRoot(candidate) !== undefined ||
19
+ env[TEST_FAULT_ENV] === "reaper-refuse-root-intent") {
20
+ throw new Error("Scratch root intent was not conclusively absent");
21
+ }
22
+ return candidate;
23
+ }
24
+ /**
25
+ * Materialize the exact armed intent inside the detached authority.
26
+ * @param value - Exact correlated materialization request
27
+ * @param intent - Previously armed root intent
28
+ * @returns Newly persisted root identity
29
+ */
30
+ function materializeArmedRoot(value, intent) {
31
+ if (intent === undefined ||
32
+ value["correlation"] !== intent.token ||
33
+ openOwnedScratchRunRoot(intent) !== undefined) {
34
+ throw new Error("Scratch root materialization does not match armed intent");
35
+ }
36
+ const owned = materializeOwnedScratchRunRoot(intent, {
37
+ writeOwnerRecord: (root, owner) => {
38
+ if (env[TEST_FAULT_ENV] === "pause-before-owner-marker") {
39
+ process.kill(process.pid, "SIGSTOP");
40
+ }
41
+ writeScratchOwnerRecord(root, owner);
42
+ },
43
+ });
44
+ return owned.owner.root;
45
+ }
46
+ /**
47
+ * Validate and arm one birth-bound target before root materialization.
48
+ * @param value - Exact target-intent message
49
+ * @param intent - Previously armed root intent
50
+ * @returns Immutable target authority
51
+ */
52
+ function armTargetIntent(value, intent) {
53
+ const candidate = value["target"];
54
+ if (intent === undefined ||
55
+ value["correlation"] !== intent.token ||
56
+ openOwnedScratchRunRoot(intent) !== undefined ||
57
+ processBirthFingerprint(candidate.pid) !==
58
+ candidate.processBirthFingerprint ||
59
+ env[TEST_FAULT_ENV] === "reaper-refuse-target-intent") {
60
+ throw new Error("Target intent does not match the armed root correlation");
61
+ }
62
+ return candidate;
63
+ }
64
+ /**
65
+ * Run detached recovery once, then exit with no permanent companion.
66
+ * @param state - Reaper lifecycle state
67
+ */
68
+ async function recover(state) {
69
+ if (state.recovering || state.disarmed)
70
+ return;
71
+ // eslint-disable-next-line functional/immutable-data -- exactly-once recovery transition
72
+ state.recovering = true;
73
+ try {
74
+ if (env[TEST_FAULT_ENV] === "pause-recovery-before-drain") {
75
+ process.kill(process.pid, "SIGSTOP");
76
+ }
77
+ await drainTestRunTarget(state.target);
78
+ if (state.intent !== undefined)
79
+ removeOwnedScratchRunRoot(state.intent);
80
+ process.exit(0);
81
+ }
82
+ catch (error) {
83
+ process.stderr.write(`lisa-test-run reaper failed: ${error instanceof Error ? error.message : String(error)}\n`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ /**
88
+ * Send one exact acknowledgement or enter detached recovery.
89
+ * @param state - Reaper lifecycle state
90
+ * @param type - Exact acknowledgement type
91
+ * @param correlation - Optional root token correlation
92
+ * @param body - Exact type-specific acknowledgement fields
93
+ * @param onSent - Optional terminal action after the IPC callback flushes
94
+ */
95
+ function sendAcknowledgement(state, type, correlation, body = {}, onSent) {
96
+ if (env[TEST_FAULT_ENV] === "reaper-close-root-armed" &&
97
+ type === "ROOT_ARMED" &&
98
+ process.connected) {
99
+ process.disconnect();
100
+ }
101
+ if (!process.connected || process.send === undefined) {
102
+ void recover(state);
103
+ return;
104
+ }
105
+ try {
106
+ process.send({
107
+ schema: 1,
108
+ type,
109
+ ...(correlation === undefined ? {} : { correlation }),
110
+ ...body,
111
+ }, error => {
112
+ if (error !== null)
113
+ void recover(state);
114
+ else
115
+ onSent?.();
116
+ });
117
+ }
118
+ catch {
119
+ void recover(state);
120
+ }
121
+ }
122
+ /**
123
+ * Apply one exact message to the current reaper phase.
124
+ * @param state - Reaper lifecycle state
125
+ * @param message - Untrusted IPC message
126
+ */
127
+ // eslint-disable-next-line sonarjs/cognitive-complexity -- four explicit protocol phases are kept visibly fail-closed
128
+ function handleMessage(state, message) {
129
+ const value = parseScratchProtocolMessage(message);
130
+ if (state.phase === "await-root-intent" && value.type === "ROOT_INTENT") {
131
+ const intent = armRootIntent(value);
132
+ // eslint-disable-next-line functional/immutable-data -- immutable authority captured once
133
+ state.intent = intent;
134
+ // eslint-disable-next-line functional/immutable-data -- ordered protocol transition
135
+ state.phase = "await-target-intent";
136
+ sendAcknowledgement(state, "ROOT_INTENT_ARMED", intent.token);
137
+ return;
138
+ }
139
+ if (state.phase === "await-target-intent" && value.type === "TARGET_INTENT") {
140
+ const target = armTargetIntent(value, state.intent);
141
+ // eslint-disable-next-line functional/immutable-data -- immutable target captured once
142
+ state.target = target;
143
+ // eslint-disable-next-line functional/immutable-data -- ordered protocol transition
144
+ state.phase = "await-materialization";
145
+ sendAcknowledgement(state, "TARGET_ARMED", state.intent?.token);
146
+ return;
147
+ }
148
+ if (state.phase === "await-materialization" &&
149
+ value.type === "MATERIALIZE_ROOT") {
150
+ const root = materializeArmedRoot(value, state.intent);
151
+ // eslint-disable-next-line functional/immutable-data -- ordered protocol transition
152
+ state.phase = "armed";
153
+ sendAcknowledgement(state, "ROOT_ARMED", state.intent?.token, { root });
154
+ return;
155
+ }
156
+ if (state.phase === "armed" && value.type === "CLEANED") {
157
+ if (state.intent !== undefined &&
158
+ openOwnedScratchRunRoot(state.intent) !== undefined) {
159
+ throw new Error("Foreground cleanup did not remove the armed root");
160
+ }
161
+ // eslint-disable-next-line functional/immutable-data -- terminal disarm transition
162
+ state.disarmed = true;
163
+ // eslint-disable-next-line functional/immutable-data -- terminal disarm transition
164
+ state.phase = "disarmed";
165
+ sendAcknowledgement(state, "DISARMED", undefined, {}, () => {
166
+ process.disconnect();
167
+ process.exit(0);
168
+ });
169
+ return;
170
+ }
171
+ throw new Error(`Unexpected ${value.type} in reaper state ${state.phase}`);
172
+ }
173
+ /** Start the one-shot detached recovery protocol. */
174
+ function main() {
175
+ const state = {
176
+ disarmed: false,
177
+ recovering: false,
178
+ phase: "await-root-intent",
179
+ };
180
+ process.on("message", message => {
181
+ try {
182
+ handleMessage(state, message);
183
+ }
184
+ catch (error) {
185
+ process.stderr.write(`lisa-test-run reaper refused protocol: ${error instanceof Error ? error.message : String(error)}\n`);
186
+ void recover(state);
187
+ }
188
+ });
189
+ process.once("disconnect", () => void recover(state));
190
+ sendAcknowledgement(state, "REAPER_READY");
191
+ }
192
+ if (env[TEST_FAULT_ENV] === "reaper-startup")
193
+ process.exit(77);
194
+ main();
195
+ //# sourceMappingURL=lisa-test-run-reaper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-reaper.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-reaper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /** Runtime-only companion, environment, and signal escalation primitives. */
2
+ import { type ChildProcess } from "node:child_process";
3
+ import { type ScratchRouteProfile } from "../configs/vitest/scratch-route-profile.js";
4
+ import type { PayloadOutcome } from "./lisa-test-run-ipc.js";
5
+ import { type TestRunTargetIntent } from "./lisa-test-run-process-group.js";
6
+ /** Catchable signals forwarded to the target process group. */
7
+ export declare const FORWARDED_SIGNALS: readonly NodeJS.Signals[];
8
+ /** Cancellable escalation armed by the first forwarded catchable signal. */
9
+ export interface SignalEscalation {
10
+ readonly promise: Promise<PayloadOutcome>;
11
+ readonly begin: (signal: NodeJS.Signals) => void;
12
+ readonly cancel: () => void;
13
+ }
14
+ /**
15
+ * Start one source-or-built sibling as a detached IPC child.
16
+ * @param name - Sibling module basename
17
+ * @returns Detached protocol companion
18
+ */
19
+ export declare function forkDetachedSibling(name: string): ChildProcess;
20
+ /**
21
+ * Convert inherited values plus the frozen lease to the spawn contract.
22
+ * @param lease - Serialized exact suite lease
23
+ * @param profile - Frozen wrapper route profile
24
+ * @param directScratchRoot - Direct-adapter platform temp root, when applicable
25
+ * @returns String-only payload environment
26
+ */
27
+ export declare function payloadEnvironment(lease: string, profile: ScratchRouteProfile, directScratchRoot?: string): Record<string, string>;
28
+ /**
29
+ * Reject if the detached cleanup authority exits during the payload.
30
+ * @param reaper - Armed detached reaper
31
+ * @returns Promise that only rejects on exit
32
+ */
33
+ export declare function rejectOnReaperExit(reaper: ChildProcess): Promise<never>;
34
+ /**
35
+ * Drain with deterministic birth-probe failures only in dedicated controls.
36
+ * @param target - Armed target authority
37
+ * @returns Bounded drain promise
38
+ */
39
+ export declare function drainSupervisedTarget(target: TestRunTargetIntent | undefined): Promise<void>;
40
+ /**
41
+ * Build one cancellable TERM-to-KILL escalation.
42
+ * @param target - Armed birth-bound target
43
+ * @returns Cancellable escalation
44
+ */
45
+ export declare function createSignalEscalation(target: TestRunTargetIntent): SignalEscalation;
46
+ //# sourceMappingURL=lisa-test-run-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-runtime.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-runtime.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,OAAO,EAAQ,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAK7D,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,4CAA4C,CAAC;AAEpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,kCAAkC,CAAC;AAQ1C,+DAA+D;AAC/D,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,CAAC,OAAO,EAItD,CAAC;AAEF,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAC1C,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,CAY9D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAC5B,iBAAiB,CAAC,EAAE,MAAM,GACzB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmBxB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CASvE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,mBAAmB,GAAG,SAAS,GACtC,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,mBAAmB,GAC1B,gBAAgB,CA+BlB"}
@@ -0,0 +1,123 @@
1
+ /** Runtime-only companion, environment, and signal escalation primitives. */
2
+ import { fork } from "node:child_process";
3
+ import { env } from "node:process";
4
+ import { fileURLToPath } from "node:url";
5
+ import * as path from "node:path";
6
+ import { SCRATCH_PREFIXES_ENV, SCRATCH_SUITE_ENV, } from "../configs/vitest/scratch-route-profile.js";
7
+ import { SCRATCH_SUPERVISION_LEASE_ENV } from "../configs/vitest/scratch-supervision.js";
8
+ import { drainTestRunTarget, } from "./lisa-test-run-process-group.js";
9
+ /** Grace period for a payload to honor a forwarded catchable signal. */
10
+ const FORWARDED_SIGNAL_GRACE_MS = 1_000;
11
+ /** Private deterministic protocol-fault seam. */
12
+ const TEST_FAULT_ENV = "LISA_TEST_RUN_TEST_FAULT";
13
+ /** Catchable signals forwarded to the target process group. */
14
+ export const FORWARDED_SIGNALS = [
15
+ "SIGINT",
16
+ "SIGTERM",
17
+ "SIGHUP",
18
+ ];
19
+ /**
20
+ * Start one source-or-built sibling as a detached IPC child.
21
+ * @param name - Sibling module basename
22
+ * @returns Detached protocol companion
23
+ */
24
+ export function forkDetachedSibling(name) {
25
+ const self = fileURLToPath(import.meta.url);
26
+ const modulePath = path.join(path.dirname(self), `${name}${path.extname(self)}`);
27
+ return fork(modulePath, [], {
28
+ cwd: process.cwd(),
29
+ detached: true,
30
+ execArgv: process.execArgv,
31
+ stdio: ["ignore", "inherit", "inherit", "ipc"],
32
+ });
33
+ }
34
+ /**
35
+ * Convert inherited values plus the frozen lease to the spawn contract.
36
+ * @param lease - Serialized exact suite lease
37
+ * @param profile - Frozen wrapper route profile
38
+ * @param directScratchRoot - Direct-adapter platform temp root, when applicable
39
+ * @returns String-only payload environment
40
+ */
41
+ export function payloadEnvironment(lease, profile, directScratchRoot) {
42
+ return Object.fromEntries(Object.entries({
43
+ ...env,
44
+ [SCRATCH_SUPERVISION_LEASE_ENV]: lease,
45
+ [SCRATCH_SUITE_ENV]: profile.suiteLabel,
46
+ [SCRATCH_PREFIXES_ENV]: JSON.stringify(profile.registeredPrefixes),
47
+ ...(directScratchRoot === undefined
48
+ ? {}
49
+ : {
50
+ TMPDIR: directScratchRoot,
51
+ TMP: directScratchRoot,
52
+ TEMP: directScratchRoot,
53
+ }),
54
+ }).filter((entry) => entry[0] !== TEST_FAULT_ENV && entry[1] !== undefined));
55
+ }
56
+ /**
57
+ * Reject if the detached cleanup authority exits during the payload.
58
+ * @param reaper - Armed detached reaper
59
+ * @returns Promise that only rejects on exit
60
+ */
61
+ export function rejectOnReaperExit(reaper) {
62
+ return new Promise((_, reject) => {
63
+ const onExit = () => {
64
+ reaper.off("exit", onExit);
65
+ reject(new Error("Detached reaper exited while the payload was active"));
66
+ };
67
+ reaper.once("exit", onExit);
68
+ if (reaper.exitCode !== null || reaper.signalCode !== null)
69
+ onExit();
70
+ });
71
+ }
72
+ /**
73
+ * Drain with deterministic birth-probe failures only in dedicated controls.
74
+ * @param target - Armed target authority
75
+ * @returns Bounded drain promise
76
+ */
77
+ export function drainSupervisedTarget(target) {
78
+ const fault = env[TEST_FAULT_ENV];
79
+ if (fault === "stop-send-closed" || fault === "stop-send-rejected") {
80
+ return Promise.resolve();
81
+ }
82
+ if (fault === "birth-unavailable-on-drain") {
83
+ return drainTestRunTarget(target, {
84
+ probes: { processBirthFingerprint: () => undefined },
85
+ });
86
+ }
87
+ if (fault === "birth-mismatch-on-drain") {
88
+ return drainTestRunTarget(target, {
89
+ probes: { processBirthFingerprint: () => "mismatched-birth-control" },
90
+ });
91
+ }
92
+ return drainTestRunTarget(target);
93
+ }
94
+ /**
95
+ * Build one cancellable TERM-to-KILL escalation.
96
+ * @param target - Armed birth-bound target
97
+ * @returns Cancellable escalation
98
+ */
99
+ export function createSignalEscalation(target) {
100
+ const state = { started: false };
101
+ const promise = new Promise((resolve, reject) => {
102
+ // eslint-disable-next-line functional/immutable-data -- one promise settlement handle
103
+ state.settle = { resolve, reject };
104
+ });
105
+ return {
106
+ promise,
107
+ begin: signal => {
108
+ if (state.started)
109
+ return;
110
+ // eslint-disable-next-line functional/immutable-data -- first forwarded signal wins
111
+ state.started = true;
112
+ // eslint-disable-next-line functional/immutable-data -- cancellable bounded timer
113
+ state.timer = setTimeout(() => {
114
+ void drainSupervisedTarget(target).then(() => state.settle?.resolve({ code: null, signal }), error => state.settle?.reject(error));
115
+ }, FORWARDED_SIGNAL_GRACE_MS);
116
+ },
117
+ cancel: () => {
118
+ if (state.timer !== undefined)
119
+ clearTimeout(state.timer);
120
+ },
121
+ };
122
+ }
123
+ //# sourceMappingURL=lisa-test-run-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-runtime.js","sourceRoot":"","sources":["../../src/cli/lisa-test-run-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ScratchRouteProfile } from "../configs/vitest/scratch-route-profile.js";
2
+ import { type PayloadOutcome } from "./lisa-test-run-ipc.js";
3
+ /** Explicit scratch delivery selected by each generated route. */
4
+ export type TestRunAdapter = "vitest" | "direct";
5
+ /**
6
+ * Arm and execute one supervised command.
7
+ * @param argv - Exact payload argv
8
+ * @param profile - Frozen wrapper route profile
9
+ * @param adapter - Explicit payload delivery adapter
10
+ * @returns Payload outcome after proven cleanup
11
+ */
12
+ export declare function superviseTestRun(argv: readonly [string, ...string[]], profile: ScratchRouteProfile, adapter: TestRunAdapter): Promise<PayloadOutcome>;
13
+ //# sourceMappingURL=lisa-test-run-supervisor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lisa-test-run-supervisor.d.ts","sourceRoot":"","sources":["../../src/cli/lisa-test-run-supervisor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AAKtF,OAAO,EAML,KAAK,cAAc,EACpB,MAAM,wBAAwB,CAAC;AAgBhC,kEAAkE;AAClE,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAmSjD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EACpC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,cAAc,CAAC,CAsBzB"}