Files
improvise/.claude/hooks/session-start.sh
T
Cursor Agent ec30c8a7de fix: address three Codex P2 review findings
1. Shebang (Codex P2): scripts/agent-bootstrap.sh and .claude/hooks/session-start.sh
   now use #!/usr/bin/env bash instead of #!/bin/bash, matching repo convention
   enforced by checkers.sh.

2. Fail-closed bd pin (Codex P2): .claude/hooks/session-start.sh local path now
   exits 2 with a warning when pinned or running version cannot be parsed,
   instead of silently succeeding. An unparseable version is not a pass.

3. pr-reviews failure (Codex P2): scripts/pr-watch no longer uses '|| true' to
   swallow pr-reviews failures. If pr-reviews fails (fetch error, malformed
   response), pr-watch now exits 6 with a warning. Empty successful fetch
   (no reviews) is still exit 0.

   - Added exit 6 to usage text and skill documentation
   - Added test case 'pr-reviews failure exits 6' using malformed JSON fixture
   - All 57 pr-watch tests pass

Co-authored-by: Ed Langley <fiddlerwoaroof@users.noreply.github.com>
2026-09-26 01:30:00 +00:00

63 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# Prepare a Claude Code on the web container for work on this repository.
#
# This hook delegates to the shared `scripts/agent-bootstrap.sh`, which works
# for any coding agent stack (Claude Code, Cursor, etc.). This file exists
# because Claude Code expects hooks at `.claude/hooks/session-start.sh`.
#
# For local checkouts, only the bd pin assertion runs.
# For cloud sessions (CLAUDE_CODE_REMOTE=true), full bootstrap runs.
#
# See also: scripts/agent-bootstrap.sh (the stack-agnostic implementation)
set -uo pipefail
ROOT="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
BOOTSTRAP="$ROOT/scripts/agent-bootstrap.sh"
# Forward the Claude env file variable to the generic name the bootstrap uses
if [ -n "${CLAUDE_ENV_FILE:-}" ]; then
export AGENT_ENV_FILE="$CLAUDE_ENV_FILE"
fi
# For local checkouts, only verify the bd pin (no install, no sync)
if [ "${CLAUDE_CODE_REMOTE:-}" != "true" ]; then
# Inline the pin-check only, since the full bootstrap is cloud-only
cd "$ROOT" || exit 0
beads_pin() {
sed -n 's|.*beads\.url[[:space:]]*=[[:space:]]*"github:[^/]*/[^/]*/v\{0,1\}\([^"]*\)".*|\1|p' \
flake.nix 2>/dev/null | head -1
}
bd_running_version() {
bd version 2>/dev/null | sed -n 's/^bd version \([0-9][0-9.]*\).*/\1/p' | head -1
}
if command -v bd >/dev/null 2>&1; then
pinned=$(beads_pin)
running=$(bd_running_version)
# Fail closed: if we can't parse either version, warn rather than silently pass
if [ -z "$pinned" ]; then
printf '[session-start] WARNING: cannot parse beads pin from flake.nix\n' >&2
printf '[session-start] The pin check is skipped, but mutating bd commands may be unsafe.\n' >&2
exit 2
fi
if [ -z "$running" ]; then
printf '[session-start] WARNING: cannot parse bd version from "bd version"\n' >&2
printf '[session-start] bd: %s\n' "$(command -v bd)" >&2
printf '[session-start] The pin check is skipped, but mutating bd commands may be unsafe.\n' >&2
exit 2
fi
if [ "$running" != "$pinned" ]; then
printf '\n[session-start] ===== BEADS VERSION SKEW =====\n' >&2
printf '[session-start] pinned (flake.nix): %s\n' "$pinned" >&2
printf '[session-start] running: %s (%s)\n' "$running" "$(command -v bd)" >&2
printf '[session-start] Reading is safe. Do NOT run mutating bd commands.\n' >&2
printf '[session-start] Fix: nix develop, or direnv allow.\n' >&2
printf '[session-start] =============================\n\n' >&2
exit 2
fi
fi
exit 0
fi
# Cloud session: run the full bootstrap
exec "$BOOTSTRAP"