Skip to content

fix(generate): answer as soon as the module loader has a verdict - #92

Merged
csdev19 merged 2 commits into
mainfrom
feature/niw2-332-module-loader-reports-a-valid-schema-module-as-a-10-s
Oct 25, 2026
Merged

csdev19 merged 2 commits into
mainfrom
feature/niw2-332-module-loader-reports-a-valid-schema-module-as-a-10-s

Conversation

@csdev19

@csdev19 csdev19 commented Oct 25, 2026

Copy link
Copy Markdown
Owner

What changed and why

A project module that exports a valid Standard Schema but leaves the event loop alive (a setInterval, a DB pool, a file watcher) was reported as {"code":"timeout"} after about 10 s. The child had already printed the correct verdict, but the parent only read stdout in child.on('close'), which never fires while the child stays alive.

Changes in packages/generate/src/load-module.ts:

  • Incremental read. The parent parses stdout as it arrives. On the first complete verdict it resolves.
  • Child exits itself. The child calls process.exit(0) in the stdout write callback, and the parent also sends SIGKILL. The promise resolves only after the child's exit, so no orphan outlives it.
  • Framing. The verdict is now one line prefixed with a per-load token (@laqi-verdict:<uuid>:). This replaces out.lastIndexOf('{"ok":'), which a nested {"ok": inside a schema's examples could fool. JSON never holds a raw newline, so the line is unambiguous, and a module cannot print a matching line without reading this process's environment.
  • The 10 s timeout for a module that hangs during import is unchanged. If a verdict already arrived when it fires, the verdict wins.

Tests were written first and committed before the fix (0483fe1). Two failed against the old loader (timer, nested {"ok":); the third (a module printing a verdict-shaped line) passed before and guards the new framing.

Not in this PR (all NIW2-310): minimal child env, stdout/stderr caps, fd 3 framing, approval changes. The new tests only observe behaviour through loadModuleSchema, so they should survive that rewrite.

How I verified it

  • bun run test packages/generate/src/load-module.test.ts: 13/13 pass (the two new failing tests fail on the old loader).
  • Full gate, run twice in a row, both green (1604 tests): oxlint, oxfmt --check, bun run build, bun run check-types, bun run check-types:scripts, bun run test.
  • Caveat: bun run verify itself exits 1 in the worker's worktree because oxfmt --check . flags .claude/skills/.gc-skill-ownership.json, an untracked, git-ignored file Gas City generates there. CI never sees it. I ran the same steps with oxfmt --check . '!.claude/**'.
  • Local Bun is 1.3.14, not the pinned 1.3.4; the lockfile installed with --frozen-lockfile.

How to test it yourself

  1. Save this as /tmp/timer.mjs:
    setInterval(() => {}, 1000)
    export const S = { '~standard': { version: 1, vendor: 'x', jsonSchema: { output: () => ({ type: 'string' }) } } }
  2. On main it takes about 10 s and returns code: 'timeout'. On this branch it returns { ok: true, ... } in well under a second, and ps shows no leftover node -e child.
  3. Or just run bun run test packages/generate/src/load-module.test.ts.

Refs NIW2-332

Run: Gas City session ni-wisp-ycl2jo6, bead la-2fl, Mac mini

🤖 Generated with Claude Code

csdev19 and others added 2 commits October 24, 2026 22:58
…the module loader

Refs NIW2-332

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The loader waited for the child to exit before reading its verdict, so a
module that left a timer, pool or watcher running was reported as a 10 s
timeout even though the child had already answered correctly.

The verdict is now one framed line carrying a per-load token. The parent
reads it incrementally, resolves, and kills the child; the child also exits
in its write callback. The parent resolves only after the child has exited,
so no orphan outlives the promise. The framing replaces lastIndexOf on
'{"ok":', which a nested value inside a schema could fool.

Refs NIW2-332

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@csdev19
csdev19 merged commit f77f900 into main Oct 25, 2026
1 check passed
@csdev19
csdev19 deleted the feature/niw2-332-module-loader-reports-a-valid-schema-module-as-a-10-s branch October 25, 2026 04:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant