fix(sf): clear last 2 stale failures from gsd-2 compat sweep

auto-session-encapsulation invariant: the parallel session refactored
auto.ts to use the getAutoSession() factory; the test still expected
`new AutoSession()` literally. Updated the regex + the allowedPatterns
list to accept both shapes — the invariant is "exactly one module-level
binding for the AutoSession instance", not which constructor expression
yields it.

silent-catch-diagnostics #3348: auto-supervisor.ts:53 swallowed signal-
handler exceptions silently. Added logWarning("session", ...) — the
intent stays the same (signal handler must not throw), but cleanup-path
errors are now visible in the journal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikael Hugo 2026-05-02 22:51:42 +02:00
parent 3e8c5b192f
commit 8299c7ac2b
2 changed files with 17 additions and 5 deletions

View file

@ -7,6 +7,7 @@
import { clearLock } from "./crash-recovery.js";
import { nativeHasChanges } from "./native-git-bridge.js";
import { releaseSessionLock } from "./session-lock.js";
import { logWarning } from "./workflow-logger.js";
// ─── Signal Handling ─────────────────────────────────────────────────────────
@ -50,8 +51,13 @@ export function registerSigtermHandler(
const handler = () => {
try {
onSignal?.();
} catch {
// Best-effort: signal handler must not throw.
} catch (err) {
// Best-effort: signal handler must not throw — log and continue
// to lock cleanup so the user can still exit cleanly.
logWarning(
"session",
`auto-supervisor signal handler threw: ${(err as Error).message}`,
);
}
clearLock(currentBasePath);
releaseSessionLock(currentBasePath);

View file

@ -79,14 +79,19 @@ test("auto.ts has exactly one module-level const for AutoSession", () => {
const source = getAutoTsSource();
const lines = source.split("\n");
// Accept either historical shape: a direct `new AutoSession()` instantiation
// OR the current factory pattern `getAutoSession()` (auto/session.ts owns
// the singleton). The invariant is "exactly one module-level binding for
// the AutoSession instance" — not which constructor expression yielded it.
const sessionConsts = lines.filter((line) =>
/^const\s+\w+\s*=\s*new\s+AutoSession/.test(line),
/^const\s+\w+\s*=\s*(new\s+AutoSession|getAutoSession\s*\()/.test(line),
);
assert.equal(
sessionConsts.length,
1,
`auto.ts should have exactly one \`const s = new AutoSession()\`. ` +
`auto.ts should have exactly one module-level AutoSession binding ` +
`(\`const s = new AutoSession()\` or \`const s = getAutoSession()\`). ` +
`Found ${sessionConsts.length}: ${sessionConsts.join(", ")}`,
);
});
@ -212,7 +217,8 @@ test("auto.ts module-level consts are only AutoSession instance, true constants,
// Patterns that are acceptable at module level
const allowedPatterns = [
/^const s = new AutoSession/, // The session singleton
/^const s = new AutoSession/, // The session singleton (legacy shape)
/^const s = getAutoSession\s*\(/, // The session singleton (factory shape)
/^const [A-Z_]+\s*=/, // UPPER_CASE constants
/^const \w+StateAccessors/, // Static accessor objects
/^const \w+:\s*\w+\s*=/, // Typed constants