@code-yeongyu/senpi-codemode 2026.10.18-1 → 2026.10.19-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -12,6 +12,32 @@
12
12
 
13
13
  ### Removed
14
14
 
15
+ ## [2026.10.19-1] - 2026-10-19
16
+
17
+ ### Breaking Changes
18
+
19
+ ### Added
20
+
21
+ ### Changed
22
+
23
+ ### Fixed
24
+
25
+ - Stopping a kernel or an environment install whose interpreter failed to start no longer SIGKILLs the host's own process group on Node < 24.22 / 26.10 ([#3706](https://github.com/code-yeongyu/senpi/issues/3706)).
26
+
27
+ ### Removed
28
+
29
+ ## [2026.10.19] - 2026-10-19
30
+
31
+ ### Breaking Changes
32
+
33
+ ### Added
34
+
35
+ ### Changed
36
+
37
+ ### Fixed
38
+
39
+ ### Removed
40
+
15
41
  ## [2026.10.18-1] - 2026-10-18
16
42
 
17
43
  ### Breaking Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@code-yeongyu/senpi-codemode",
3
- "version": "2026.10.18-1",
3
+ "version": "2026.10.19-1",
4
4
  "description": "Source-only senpi extension package for codemode evaluation tools",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -33,15 +33,15 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@babel/parser": "8.0.4",
36
- "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.18-1",
36
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.19-1",
37
37
  "quickjs-wasi": "3.6.2",
38
38
  "typebox": "1.3.34"
39
39
  },
40
40
  "peerDependencies": {
41
- "@code-yeongyu/senpi": "2026.10.18-1"
41
+ "@code-yeongyu/senpi": "2026.10.19-1"
42
42
  },
43
43
  "devDependencies": {
44
- "@code-yeongyu/senpi": "2026.10.18-1"
44
+ "@code-yeongyu/senpi": "2026.10.19-1"
45
45
  },
46
46
  "keywords": [
47
47
  "senpi",
@@ -189,7 +189,8 @@ export function runJsInstall(input: {
189
189
  // installer itself. An abort listener must never throw: nothing above it can catch the error.
190
190
  }
191
191
  }
192
- child.kill("SIGKILL");
192
+ // A child that never started has no pid; on Node < 24.22 / 26.10 its kill() signals our own process group.
193
+ if (child.pid !== undefined) child.kill("SIGKILL");
193
194
  };
194
195
  input.signal.addEventListener("abort", onAbort, { once: true });
195
196
  child.once("error", (error) => {
@@ -229,8 +229,8 @@ export async function runPipInstall(input: {
229
229
  // pip's build backends run in their own subprocesses; stopping only pip would leave them writing.
230
230
  const onAbort = () => {
231
231
  const pid = child.pid;
232
- if (pid === undefined) child.kill("SIGKILL");
233
- else
232
+ // A child that never started has nothing to stop; on Node < 24.22 / 26.10 its kill() signals our own group.
233
+ if (pid !== undefined)
234
234
  termination = terminateProcessTrees([pid], { graceMs: PIP_TREE_GRACE_MS }).catch(() => {
235
235
  child.kill("SIGKILL");
236
236
  });
@@ -147,7 +147,8 @@ export async function hardKill(
147
147
  signalDelivered = child.kill("SIGKILL");
148
148
  }
149
149
  } else {
150
- signalDelivered = child.kill("SIGKILL");
150
+ // A POSIX child that never started has no pid; on Node < 24.22 / 26.10 its kill() signals our own process group.
151
+ signalDelivered = (child.pid !== undefined || process.platform === "win32") && child.kill("SIGKILL");
151
152
  }
152
153
  if (!signalDelivered) {
153
154
  settle();
@@ -182,6 +182,8 @@ export class PythonKernelTransport {
182
182
  const message = error instanceof Error ? error.message : String(error);
183
183
  this.#stderrTail = `${this.#stderrTail}Python interrupt frame write failed: ${message}\n`.slice(-4_000);
184
184
  }
185
+ // Only a started kernel reaches here; the guard keeps that invariant local (senpi#3706).
186
+ if (this.#child.pid === undefined) return;
185
187
  if (process.platform === "win32") this.#child.kill();
186
188
  else this.#child.kill("SIGINT");
187
189
  }
@@ -173,13 +173,13 @@ export class SubprocessProcess {
173
173
  else this.child.kill(signal);
174
174
  return;
175
175
  }
176
- if (this.child.pid !== undefined) {
177
- try {
178
- globalThis.process.kill(-this.child.pid, signal);
179
- return;
180
- } catch (error) {
181
- if (!(error instanceof Error)) throw error;
182
- }
176
+ // A POSIX child that never started has no pid; on Node < 24.22 / 26.10 its kill() signals our own process group.
177
+ if (this.child.pid === undefined) return;
178
+ try {
179
+ globalThis.process.kill(-this.child.pid, signal);
180
+ return;
181
+ } catch (error) {
182
+ if (!(error instanceof Error)) throw error;
183
183
  }
184
184
  this.child.kill(signal);
185
185
  }