Development record
A successful bootstrap install is rendered to the user as a third 'SessionStart:startup hook error', indistinguishable from the two genuine failures above it. hooks/bootstrap.sh's notice() exits 2 deliberately, and its comment gives the sound reason: a SessionStart hook's stdout becomes model context, while only a non-zero exit puts stderr in front of the human. But the harness renders ANY non-zero SessionStart exit as a '<hook name> hook error' notice — the docs confirm exit 2 'renders in the transcript as a <hook name> hook error notice, the same way a non-blocking error does'. So there is no 'notice' channel distinct from 'error', and the checksum-verified happy path is labelled a fault. Observed on the first manual install (2026-08-10): three consecutive hook-error lines, of which the third was the install SUCCEEDING. Fix direction: fold this into the single chained SessionStart entry proposed in iss-204 and lead the visible first line with the success, since the transcript shows only the first line of stderr; the honest-failure posture for the genuinely-no-binary window is unaffected.
A successful bootstrap install is rendered to the user as a third 'SessionStart:startup hook error', indistinguishable from the two genuine failures above it. hooks/bootstrap.sh's notice() exits 2 deliberately, and its comment gives the sound reason: a SessionStart hook's stdout becomes model context, while only a non-zero exit puts stderr in front of the human. But the harness renders ANY non-zero SessionStart exit as a '<hook name> hook error' notice — the docs confirm exit 2 'renders in the transcript as a <hook name> hook error notice, the same way a non-blocking error does'. So there is no 'notice' channel distinct from 'error', and the checksum-verified happy path is labelled a fault. Observed on the first manual install (2026-08-10): three consecutive hook-error lines, of which the third was the install SUCCEEDING. Fix direction: fold this into the single chained SessionStart entry proposed in iss-204 and lead the visible first line with the success, since the transcript shows only the first line of stderr; the honest-failure posture for the genuinely-no-binary window is unaffected.
Frontmatter
| id | iss-208 |
|---|---|
| type | issue |
| lifecycle | resolved |
| severity | minor |
.abcd/work/issues/resolved/iss-208-a-successful-bootstrap-install-is.md
open on GitHub ↗ · commit history ↗
References1
- iss-204hooks/hooks.json puts bootstrap.sh and the two binary-backed SessionStart hooks in ONE event group and relies on list order, but the harness runs all matching hooks in PARALLEL — the Claude Code hooks reference states verbatim 'All matching hooks run in parallel.' spc-21 asserts the opposite: 'Ordering within one event's hook list is preserved by the harness, so the binary-backed session hooks run after the bootstrap in the same event.' That warrant is false, and it is load-bearing. On a fresh install the two gated hooks evaluate [ -f "$CLAUDE_PLUGIN_ROOT/abcd" ] while bootstrap.sh is still downloading the ~10.7MB release binary (timeout 240), lose the race, and both print 'the plugin binary is not installed'. Observed on the first manual marketplace install (2026-08-10): both errors printed BEFORE bootstrap's own success notice, which is direct evidence of parallel execution. Consequence is not only noise — 'hook prompt-router-reset' and 'hook session-start' genuinely do not run for that session, and itd-105 AC#1 ('every hook executes successfully — no No such file or directory, no unguarded-shell warning') fails on every fresh install AND every plugin update, since each update lands in a fresh commit-stamped cache directory with no binary. Fix direction: collapse the three entries into ONE SessionStart command that runs bootstrap.sh and then the two binary calls in a single shell, so the sequencing is owned here rather than assumed of the harness.blocked by
mentions3
- iss-2608282026177429itd-154 does not ship the literal 'provisioning the abcd binary...' stderr line spc-47 AC2 asks for, and the reason is a conflict inside the record rather than an oversight: only the FIRST line of a hook's stderr reaches the transcript (iss-208, measured on the first manual install), and bootstrap.sh already spends that line on the success notice's one-time ahoy-install instruction, placed first for exactly that reason (iss-207). An announcement printed ahead of it takes the line from the success and, worse, from the refusal's cause on the failing path — which is the silence itd-154 exists to end. Both orderings were reproduced during the adversarial review. What ships instead is the EXIT trap that converts a silent death into the same loud refusal, naming provisioning in the one line it emits; the residue is a run that HANGS (process still alive, trap not yet fired) or is SIGKILLed, which still leaves nothing. The fix that would satisfy both is a breadcrumb: write a marker at the start of provisioning, remove it on any terminal line, and have the next session fold 'a previous attempt did not finish' into its own terminal line rather than into a new one. Detector: kill -9 a provisioning run, start a second session, expect the next run's first line to name the previous failure.
- iss-2609230949466602itd-154 ac-2 not met: hooks/bootstrap.sh deliberately prints no eager 'provisioning the abcd binary…' line when it fetches the binary (the phrase is reserved for the EXIT trap's death report), so a successful provisioning run emits only the terminal 'abcd bootstrap: installed' line; the intent's criterion promised a visible loud-staged provisioning line on every fetch. The reasoning (only the first stderr line reaches the transcript, iss-208/iss-207) is recorded in the script, not in the intent or its spec — the record and the delivery disagree and one of them should move
- spc-21a-fresh-plugin-install-just-works-the-hook-binary-survives