@floless/app 0.6.1 → 0.6.2

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/launch.mjs CHANGED
@@ -312,16 +312,32 @@ function enumerateProcesses() {
312
312
  }
313
313
  }
314
314
 
315
+ // Build the `taskkill` argv for one pid. `tree` (default true) adds /T to also kill the
316
+ // target's whole child-process tree — correct for teardown/uninstall, where the
317
+ // supervisor's spawned --serve child must die WITH it. The update-apply path running
318
+ // inside the SERVE passes tree:false: there the caller IS the supervisor's --serve child
319
+ // (and the process that must survive to launch Update.exe), so a /T tree-kill of the
320
+ // supervisor would also kill the caller itself. tree:false kills ONLY the supervisor and
321
+ // lets the serve exit on its own. Pure + exported so the /T decision is unit-tested.
322
+ export function taskkillArgs(pid, { tree = true } = {}) {
323
+ return tree ? ['/PID', String(pid), '/T', '/F'] : ['/PID', String(pid), '/F'];
324
+ }
325
+
315
326
  // Kill the --supervise watchdog FIRST (Codex B1) so it can't respawn the server in
316
327
  // the gap before stopServer(). Matches THIS app's exe + the supervise action, never
317
328
  // process.pid (self-kill guard lives in supervisorPidsToKill). Idempotent; win32-only.
318
329
  //
330
+ // `tree` (default true) tree-kills (/T) — teardown/uninstall, where the supervisor's
331
+ // --serve child must die too. The update-apply path INSIDE the serve passes {tree:false}
332
+ // (the serve is itself the supervisor's child and must survive to launch Update.exe, then
333
+ // exit on its own) — see taskkillArgs above and index.ts /api/update/apply.
334
+ //
319
335
  // SAFETY (review #1): in the npm channel process.execPath is the GENERIC node.exe, so
320
336
  // matching on it alone could kill ANY `node … supervise` process (e.g. a third-party
321
337
  // watchdog). When we detect that channel, also require the launcher script (this
322
338
  // launch.mjs) in the command line — our supervisor runs `node … launch.mjs supervise`.
323
339
  // The packaged exe (unique FlolessApp.exe) passes no scriptMatch — its match is exact.
324
- function killSupervisor() {
340
+ export function killSupervisor({ tree = true } = {}) {
325
341
  if (!isWin) return;
326
342
  const isNpmChannel = /^node(\.exe)?$/i.test(basename(process.execPath));
327
343
  const scriptMatch = isNpmChannel ? basename(fileURLToPath(import.meta.url)) : undefined; // 'launch.mjs'
@@ -339,7 +355,7 @@ function killSupervisor() {
339
355
  log(`stopping supervisor (pid ${pid})…`);
340
356
  // execFileSync (no shell) with an argv array — pid is already Number()-coerced in
341
357
  // parseProcessList, and avoiding the shell rules out any injection entirely.
342
- try { execFileSync('taskkill', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true }); } catch { /* already gone */ }
358
+ try { execFileSync('taskkill', taskkillArgs(pid, { tree }), { stdio: 'ignore', windowsHide: true }); } catch { /* already gone */ }
343
359
  }
344
360
  }
345
361
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floless/app",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "description": "Thin localhost host for floless.app — serves web/ and shells the aware CLI. No engine, no LLM.",
6
6
  "bin": {