fix(hmr,include): settle a failing boot instead of a silent exit 13

Master's transactional loader made the invalid-provider PTY case regress:
the HMR main watcher's initial scan refreshed the include mid-initial-apply,
the concurrent group updates stranded the include fiber, and once serialized
the failing apply's rollback deadlocked on HMR's refresh drain — dsh exited
13 with no diagnostic and the terminal stranded, the exact symptom this
branch fixes. Serialize every include child-tree mutation through one queue
and pass ignoreInitial to the HMR main watcher; the failing boot now settles
through boot()'s labelled rejection with the tree disposed and exit 1. The
PTY case asserts the settled diagnostic; the fail-loud release remains the
guard for rejections boot cannot see.
This commit is contained in:
Turtle
2026-08-03 14:14:20 +08:00
parent b37c22bd0a
commit ad4aeacd19
14 changed files with 156 additions and 28 deletions

View File

@@ -209,6 +209,14 @@ class Hmr extends Service {
...this.config,
cwd: this.baseDir,
ignored: path => match(relative(this.baseDir, path)),
// The initial scan re-announces files the boot just consumed: an `add`
// for a config file refreshes an include whose initial apply may still
// be in flight, and a failing apply then rolls this plugin back while
// the scan-triggered refresh waits on that apply — a teardown deadlock
// that strands boot without a diagnostic. Only events after the scan
// matter here; `registerConfig` keeps its own initial scan because a
// personal config present at registration must apply once.
ignoreInitial: true,
})
// Collect externals: framework modules reachable from the main entry.