fix(hooks): bound the SessionEnd teardown budget; docs(interceptor): Linux + Flatpak browser failure class - #1682
Open
pkumaschow wants to merge 1 commit into
Conversation
The SessionEnd hook was being killed by the harness, surfacing only as
"Hook cancelled" with no detail. Adding a timeout bounded the failure but
did not prevent it.
The cause is not one slow call but a serial chain inside the 30s kill
window, on teardown:
transcript parses x2 ~0.2s (measured 74ms/pass over 14MB - not the
culprit, despite looking like one)
deterministic checks small
runInferenceAnalysis <=15s spawns the `claude` CLI, Sonnet tier;
measured 6573ms on a 10318-char context
deliberate sleep 3s "so the voice line plays first"
notifyVoice fetch <=3s
RebuildArchSummary UNBOUNDED spawned `bun <generator> generate`
~21s consumed before an unbounded subprocess even started. The hook cannot
self-report: its fatal path exits 0 and every handler call is individually
try/caught, so a harness kill is the only signal that survives.
Three changes:
1. Inference is off on the SessionEnd path. It catches what grep cannot -
a doc claiming behaviour the source no longer has - but buying one
semantic correction at the risk of losing the whole deterministic pass,
which is the part that actually fixes broken refs and counts, is a bad
trade on teardown. DOCINTEGRITY_INFERENCE=1 opts back in for a manual
run; non-SessionEnd triggers are unaffected.
2. The 3s voice-ordering sleep is skipped on SessionEnd. There is no main
voice line to sequence against when the session is ending.
3. RebuildArchSummary's generator subprocess is bounded at 8s with a
SIGKILL and a legible log line, so a slow generator reports as a slow
generator rather than as an unexplained cancellation.
Also corrects the DocCrossRefIntegrity header, which still read
"TRIGGER: Stop hook" - a leftover that made this harder to diagnose.
Measured on a real 5.8MB transcript carrying hook edits, so the cross-ref
path was actually reached rather than early-returning:
SessionEnd default inference skipped, handler 18ms, hook 265ms
DOCINTEGRITY_INFERENCE=1 inference runs, 6573ms - opt-in intact
8s bound a deliberately 20s generator killed at 8008ms
timer cleanup process exits in 262ms; a leaked timer would
have held it ~8s
docs(interceptor): encode the Linux + Flatpak browser failure class
Four faults found bringing Interceptor up on Fedora with Chrome installed
as a Flatpak. The first symptom looks like a dead extension and is not.
1. A daemon socket created INSIDE the sandbox is not connectable from the
host CLI even though the file is plainly visible. /tmp is genuinely
shared both directions, so `ls` shows the socket while `interceptor
status` says "daemon: not running" in the same second. The endpoint
lives in the sandbox namespace; the visible file is a shadow. The fix is
a non-sandboxed browser, not a Flatpak permission tweak.
2. A windowless orphaned Flatpak instance can hold the daemon port
invisibly. The operator sees no browser window and reasonably reports
none is open, while the sandboxed daemon starves every relay that starts
afterwards - including a different browser's. `kill` on the visible pid
does not propagate through bwrap; `flatpak kill <app-id>` does.
3. The relay only attaches to a singleton it spawned itself, and a losing
duplicate unlinks the winner's socket on exit. Consequence: CLI calls
are self-destructive while another daemon owns the port, so diagnosing
the problem re-causes it.
4. --load-extension is dead (Chrome 137+, confirmed ignored on 150), so the
picker is the only route; in a Flatpak browser it goes through the XDG
Document Portal, so `/run/flatpak/doc/<id>/...` in an error is normal.
Dotfolders are hidden in GTK pickers - Ctrl+H, or the operator cannot
navigate to the extension at all.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two independent changes found while bringing a Linux install up. Happy to split into separate PRs if you'd prefer — they share only the session that surfaced them.
1.
fix(hooks)— take DocIntegrity off the SessionEnd teardown budgetThe SessionEnd hook was being killed by the harness, surfacing only as
Hook cancelledwith no detail. A timeout bounded the failure but didn't prevent it.The cause isn't one slow call, it's a serial chain inside the 30s kill window:
runInferenceAnalysisclaudeCLI; measured 6573ms on a 10318-char contextnotifyVoicefetchRebuildArchSummarybun <generator> generate~21s consumed before an unbounded subprocess even starts. The hook can't self-report: its fatal path exits 0 and every handler call is individually try/caught, so a harness kill is the only surviving signal.
Three changes:
DOCINTEGRITY_INFERENCE=1opts back in for a manual run; non-SessionEnd triggers are unaffected.RebuildArchSummary's generator subprocess is bounded at 8s with a SIGKILL and a legible log line, so a slow generator reports as a slow generator rather than as an unexplained cancellation.Measured on a real 5.8MB transcript carrying hook edits, so the cross-ref path was actually reached rather than early-returning:
DOCINTEGRITY_INFERENCE=1This part is platform-agnostic — it was found on Linux but nothing in it is Linux-specific.
Overlap with #1591: that PR corrects the stale
TRIGGER: Stop hooknaming across ten files, including one line each inDocCrossRefIntegrity.tsandRebuildArchSummary.ts. This PR also corrects theDocCrossRefIntegrityheader, since the wrong trigger name is what made the failure hard to diagnose. The substance doesn't overlap, but those header lines will conflict trivially. Happy to drop my header change and rebase once #1591 lands — whichever ordering suits you.2.
docs(interceptor)— encode the Linux + Flatpak browser failure classFour faults hit in one session on Fedora with Chrome installed as a Flatpak. The first symptom looks like a dead extension and isn't, which is what makes this worth documenting rather than leaving each person to rediscover.
/tmpis genuinely shared both directions, solsshows the socket whileinterceptor statussaysdaemon: not runningin the same second. The endpoint lives in the sandbox namespace; the visible file is a shadow. The fix is a non-sandboxed browser, not a Flatpak permission tweak.killon the visible PID doesn't propagate throughbwrap;flatpak kill <app-id>does.--load-extensionis dead (Chrome 137+, confirmed ignored on 150), so the picker is the only route; in a Flatpak browser it goes through the XDG Document Portal, so/run/flatpak/doc/<id>/...in an error is normal and not the fault. GTK pickers hide dotfolders — Ctrl+H, or the extension directory can't be navigated to at all.Docs only; no behaviour change.