create-kudzu 0.1.156 → 0.1.157

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/README.md CHANGED
@@ -10,13 +10,13 @@ cd my-app
10
10
  npm run dev
11
11
  ```
12
12
 
13
- The generated project is a working showcase on `@kudzujs/core@^0.16.34` with reusable components, an interactive state example, a zero-JavaScript static route, page metadata, responsive CSS, and `npm run check`. Configuration remains optional until the app needs custom assets, document defaults, navigation, or build hooks.
13
+ The generated project is a working showcase on `@kudzujs/core@^0.16.36` with reusable components, an interactive state example, a zero-JavaScript static route, page metadata, responsive CSS, and `npm run check`. Configuration remains optional until the app needs custom assets, document defaults, navigation, or build hooks.
14
14
 
15
15
  Use `--no-install` to create the files without installing dependencies.
16
16
 
17
17
  ## Optional AI authoring guidance
18
18
 
19
- `create-kudzu@0.1.156` adds optional local AI developer tools:
19
+ `create-kudzu@0.1.157` provides optional local AI developer tools with managed check cancellation:
20
20
 
21
21
  ```bash
22
22
  npm create kudzu@latest my-app -- --ai
@@ -53,6 +53,11 @@ npm run ai -- check --timeout-ms 600000
53
53
  log excerpt. Failure stays nonzero. The default timeout is five minutes; choose
54
54
  an integer from 1 to 1,200,000 ms. Timeout/cancellation terminates the spawned
55
55
  process group on Unix or process tree on Windows and reports failure.
56
+ Under the existing `KUDZU_AI_DELIVERY_GROUP=1` managed-runner contract, Unix
57
+ checks inherit their outer group so a hard group cancellation also reaches
58
+ their ordinary descendants. A check-local timeout or interruption uses native
59
+ `ps` PID/parent-PID inspection to stop only that check's descendant snapshot,
60
+ preserving sibling work; inspection errors are reported as failures.
56
61
  - Full stdout/stderr are retained in a unique `.kudzu-ai/check-*/output.log`.
57
62
  Large logs show the first/last 2,048 bytes with an omission marker; an error may
58
63
  be in the omitted middle. Read the full log when needed. Old logs are not deleted
package/ai.mjs CHANGED
@@ -41,20 +41,34 @@ export async function check(root, timeoutMs = 300000) {
41
41
  const directory = await mkdtemp(join(logs, "check-")), path = join(directory, "output.log")
42
42
  const log = await open(path, "wx+")
43
43
  const start = performance.now()
44
+ const managed = process.env.KUDZU_AI_DELIVERY_GROUP === "1"
44
45
  try {
45
46
  const result = await new Promise(resolveRun => {
46
47
  const child = spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["run", "check"], {
47
- cwd: root, detached: process.platform !== "win32", shell: process.platform === "win32",
48
+ cwd: root, detached: process.platform !== "win32" && !managed, shell: process.platform === "win32",
48
49
  stdio: ["ignore", log.fd, log.fd], env: { ...process.env, FORCE_COLOR: "0", KUDZU_AI_CHECK_ROOT: root },
49
50
  })
50
51
  let timedOut = false, interrupted = null, error = null
51
52
  const terminate = () => {
52
- if (!child.pid) return
53
+ if (!child.pid || child.exitCode !== null || child.signalCode !== null) return
53
54
  if (process.platform === "win32") {
54
55
  const killed = spawnSync("taskkill", ["/pid", String(child.pid), "/T", "/F"], { encoding: "utf8" })
55
56
  if (killed.status !== 0) error = killed.error?.message ?? killed.stderr ?? "Could not terminate check tree"
56
57
  } else {
57
- try { process.kill(-child.pid, "SIGKILL") } catch (failure) { if (failure.code !== "ESRCH") error = failure.message }
58
+ const pids = [managed ? child.pid : -child.pid]
59
+ if (managed) {
60
+ // Keep the outer group alive on this tool's timeout; stop only its ordinary descendants.
61
+ const table = spawnSync("ps", ["-A", "-o", "pid=", "-o", "ppid="], { encoding: "utf8", timeout: 1000, maxBuffer: 1024 * 1024 })
62
+ if (table.status !== 0) error = table.error?.message || table.stderr?.trim() || "Could not inspect managed check descendants"
63
+ else {
64
+ const parents = table.stdout.trim().split("\n").map(line => line.trim().split(/\s+/).map(Number))
65
+ if (parents.some(row => row.length !== 2 || row.some(id => !Number.isSafeInteger(id) || id < 0))) error = "Invalid managed check process table"
66
+ else for (let index = 0; index < pids.length; index++) for (const [pid, parent] of parents) {
67
+ if (parent === pids[index] && pid > 1 && pid !== process.pid && !pids.includes(pid)) pids.push(pid)
68
+ }
69
+ }
70
+ }
71
+ for (const pid of pids.reverse()) try { process.kill(pid, "SIGKILL") } catch (failure) { if (failure.code !== "ESRCH") error = failure.message }
58
72
  }
59
73
  }
60
74
  const onInterrupt = signal => { interrupted = signal; terminate() }
package/index.mjs CHANGED
@@ -34,7 +34,7 @@ const files = {
34
34
  check: "tsc --noEmit && kudzu build"
35
35
  },
36
36
  dependencies: {
37
- "@kudzujs/core": "^0.16.34"
37
+ "@kudzujs/core": "^0.16.36"
38
38
  },
39
39
  devDependencies: {
40
40
  typescript: "^5.9.2"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kudzu",
3
- "version": "0.1.156",
3
+ "version": "0.1.157",
4
4
  "description": "Create a Kudzu project",
5
5
  "type": "module",
6
6
  "license": "MIT",