|
|
@@ -397,6 +397,7 @@ class SkillWatchManager {
|
|
|
const current = await resolveRootWatchMode(state.root.path, this.config.followSymlinks)
|
|
|
// A child unlink can publish an empty catalog before root unlinkDir arrives.
|
|
|
// Discovery therefore revalidates the retained handle independently.
|
|
|
+ // oxlint-disable-next-line typescript/no-unnecessary-condition -- watcher callbacks can mark unhealthy while the probe awaits
|
|
|
if (!state.unhealthy && sameWatchMode(watcher.mode, current)) return
|
|
|
}
|
|
|
await this.replaceWatcher(state)
|
|
|
@@ -413,6 +414,7 @@ class SkillWatchManager {
|
|
|
/* v8 ignore next -- The loop returns no handle only when teardown wins between awaited probes. */
|
|
|
if (watcher === undefined) return
|
|
|
/* v8 ignore start -- Post-open teardown is timing-dependent; the disposal race has an explicit integration test. */
|
|
|
+ // oxlint-disable-next-line typescript/no-unnecessary-condition -- teardown can race awaited watcher startup
|
|
|
if (this.closing || state.owners.size === 0) {
|
|
|
await this.closeWatcher(watcher)
|
|
|
return
|
|
|
@@ -421,6 +423,7 @@ class SkillWatchManager {
|
|
|
state.watcher = watcher
|
|
|
state.unhealthy = false
|
|
|
} catch (error) {
|
|
|
+ // oxlint-disable-next-line typescript/no-unnecessary-condition -- teardown can race awaited watcher startup
|
|
|
if (!this.closing) {
|
|
|
state.unhealthy = true
|
|
|
this.ctx.logger.warn(`skill-local: failed to watch ${state.root.path}: ${errorMessage(error)}`)
|