diff --git a/cli/assets/hooks/commit-msg b/cli/assets/hooks/commit-msg index 66bbf7e1..78af0644 100644 --- a/cli/assets/hooks/commit-msg +++ b/cli/assets/hooks/commit-msg @@ -1,4 +1,28 @@ #!/bin/sh set -eu +if ! command -v sce >/dev/null 2>&1; then + # sce brand colors — only emit ANSI when stderr is a real terminal + if [ -t 2 ]; then + RED="$(printf '\033[38;2;220;38;38m')" # red #dc2626 + G="$(printf '\033[38;2;5;150;105m')" # brand green #059669 + BOLD="$(printf '\033[1m')" + R="$(printf '\033[0m')" + else + RED='' G='' BOLD='' R='' + fi + + url="https://sce.crocoder.dev/docs/getting-started#install-cli" + + { + printf '\n' + printf ' %s%s✗%s %ssce CLI not found%s\n' "$BOLD" "$RED" "$R" "$BOLD" "$R" + printf ' %s→%s Install it from:\n' "$G" "$R" + printf ' %s%s%s%s\n' "$BOLD" "$RED" "$url" "$R" + printf '\n' + } >&2 + + exit 0 +fi + exec sce hooks commit-msg "$@" diff --git a/cli/assets/hooks/post-commit b/cli/assets/hooks/post-commit index d8b83e50..a9822c09 100644 --- a/cli/assets/hooks/post-commit +++ b/cli/assets/hooks/post-commit @@ -4,7 +4,26 @@ set -eu remote_url="$(git remote get-url origin 2>/dev/null || true)" if ! command -v sce >/dev/null 2>&1; then - echo "sce CLI not found. Install it from https://sce.crocoder.dev/docs/getting-started#install-cli" >&2 + # sce brand colors — only emit ANSI when stderr is a real terminal + if [ -t 2 ]; then + RED="$(printf '\033[38;2;220;38;38m')" # red #dc2626 + G="$(printf '\033[38;2;5;150;105m')" # brand green #059669 + BOLD="$(printf '\033[1m')" + R="$(printf '\033[0m')" + else + RED='' G='' BOLD='' R='' + fi + + url="https://sce.crocoder.dev/docs/getting-started#install-cli" + + { + printf '\n' + printf ' %s%s✗%s %ssce CLI not found%s\n' "$BOLD" "$RED" "$R" "$BOLD" "$R" + printf ' %s→%s Install it from:\n' "$G" "$R" + printf ' %s%s%s%s\n' "$BOLD" "$RED" "$url" "$R" + printf '\n' + } >&2 + exit 0 fi diff --git a/cli/assets/hooks/pre-commit b/cli/assets/hooks/pre-commit index 42c5cb0e..b4b93a78 100644 --- a/cli/assets/hooks/pre-commit +++ b/cli/assets/hooks/pre-commit @@ -1,4 +1,28 @@ #!/bin/sh set -eu +if ! command -v sce >/dev/null 2>&1; then + # sce brand colors — only emit ANSI when stderr is a real terminal + if [ -t 2 ]; then + RED="$(printf '\033[38;2;220;38;38m')" # red #dc2626 + G="$(printf '\033[38;2;5;150;105m')" # brand green #059669 + BOLD="$(printf '\033[1m')" + R="$(printf '\033[0m')" + else + RED='' G='' BOLD='' R='' + fi + + url="https://sce.crocoder.dev/docs/getting-started#install-cli" + + { + printf '\n' + printf ' %s%s✗%s %ssce CLI not found%s\n' "$BOLD" "$RED" "$R" "$BOLD" "$R" + printf ' %s→%s Install it from:\n' "$G" "$R" + printf ' %s%s%s%s\n' "$BOLD" "$RED" "$url" "$R" + printf '\n' + } >&2 + + exit 0 +fi + exec sce hooks pre-commit "$@" diff --git a/context/context-map.md b/context/context-map.md index 25899712..5a950099 100644 --- a/context/context-map.md +++ b/context/context-map.md @@ -35,12 +35,12 @@ Feature/domain context: - `context/sce/agent-trace-pre-commit-staged-checkpoint.md` (historical pre-commit staged-checkpoint contract; current runtime baseline has replaced this path with a deterministic no-op) - `context/sce/agent-trace-commit-msg-coauthor-policy.md` (current commit-msg canonical co-author trailer policy with enabled-by-default attribution hooks, explicit opt-out controls, `SCE_DISABLED` kill switch, caller-provided `ai_contribution_present` transformer seam wired from staged-diff AI-overlap preflight, idempotent dedupe, the `agent_trace::patches_have_overlap` pure overlap seam, the `StagedDiffAiOverlapResult` three-valued evidence gate, and `sce.hooks.commit_msg.ai_overlap_error` error logging) - `context/sce/agent-trace-post-commit-dual-write.md` (historical post-commit no-op/dual-write reference; current post-commit behavior is documented in `agent-trace-hooks-command-routing.md`) -- `context/sce/agent-trace-hook-doctor.md` (approved operator-environment contract for broadening `sce doctor` into the canonical health-and-repair entrypoint, including stable problem taxonomy, `--fix` semantics, checkout-aware Agent Trace DB reporting, setup-to-doctor alignment rules, and the approved downstream human text-mode layout/status/integration contract) +- `context/sce/agent-trace-hook-doctor.md` (approved operator-environment contract for broadening `sce doctor` into the canonical health-and-repair entrypoint, including stable problem taxonomy, `--fix` semantics, checkout-aware Agent Trace DB reporting, setup-to-doctor alignment rules, canonical Git-hook payload restoration, and the approved downstream human text-mode layout/status/integration contract) - `context/sce/doctor-human-text-contract.md` (implemented `sce doctor` human text layout contract: section order, `[PASS]`/`[FAIL]`/`[MISS]` status vocabulary, simplified hook rows, target-scoped integration checks with configured/detected/empty target resolution, no-installed-integrations guidance, and OpenCode, Claude, plus Pi integration group rendering rules including the `Pi extensions` group) -- `context/sce/setup-githooks-install-contract.md` (T01 canonical `sce setup --hooks` install contract for target-path resolution, idempotent outcomes, remove-and-replace behavior, and doctor-readiness alignment) +- `context/sce/setup-githooks-install-contract.md` (canonical `sce setup --hooks` install contract for target-path resolution, all-hook non-blocking missing-CLI bootstrap behavior, idempotent outcomes, remove-and-replace behavior, and doctor-readiness alignment) - `context/sce/setup-no-backup-policy-seam.md` (implemented unified remove-and-replace install policy for both config-install and required-hook install flows, with no backup creation and deterministic recovery guidance on swap failure) -- `context/sce/setup-githooks-hook-asset-packaging.md` (T02 compile-time `sce setup --hooks` required-hook template packaging contract, including current post-commit missing-`sce` install guidance, origin remote lookup, remote-URL forwarding/fallback behavior, and setup-service accessor surface) -- `context/sce/setup-githooks-install-flow.md` (T03 setup-service required-hook install orchestration with git-truth hooks-path resolution, per-hook installed/updated/skipped outcomes, and remove-and-replace behavior with recovery guidance) +- `context/sce/setup-githooks-hook-asset-packaging.md` (compile-time `sce setup --hooks` required-hook template packaging contract, including all-hook non-blocking missing-`sce` install guidance, available-CLI argument forwarding, post-commit-only origin remote lookup plus remote-URL forwarding/fallback behavior, setup-service accessor surface, and current validation posture) +- `context/sce/setup-githooks-install-flow.md` (setup-service required-hook install orchestration with git-truth hooks-path resolution, canonical missing-CLI payload installation, per-hook installed/updated/skipped outcomes, and remove-and-replace behavior with recovery guidance) - `context/sce/setup-githooks-cli-ux.md` (T04 composable `sce setup` target+`--hooks` / `--repo` command-surface contract, option compatibility validation, and deterministic setup/hook output semantics) - `context/sce/setup-repo-local-config-bootstrap.md` (setup local bootstrap behavior: repo-local `.sce/config.json` create-if-missing via config lifecycle, additive `integrations.target` persistence after successful target installs, plus lifecycle-owned local DB initialization before hooks/config asset dispatch) - `context/sce/cli-security-hardening-contract.md` (T06 CLI redaction contract, setup `--repo` canonicalization/validation, and setup write-permission probe behavior) diff --git a/context/plans/fix-git-hook-cli-guidance.md b/context/plans/fix-git-hook-cli-guidance.md new file mode 100644 index 00000000..83f4d82d --- /dev/null +++ b/context/plans/fix-git-hook-cli-guidance.md @@ -0,0 +1,113 @@ +# Fix Git hook CLI guidance + +## Change summary + +Make the three canonical Git hook assets under `cli/assets/hooks/` consistently tolerate a missing `sce` executable. Each hook must use POSIX `sh`, fail fast for ordinary script errors, detect `sce` with `command -v`, print the canonical installation guidance to stderr when it is unavailable, and exit successfully so Git operations are not blocked solely because the CLI is missing. + +The `pre-commit` and `commit-msg` hooks will add this guard while preserving their existing `sce hooks ...` invocations and argument forwarding. The already-compliant `post-commit` hook will retain its Git remote URL discovery and forwarding behavior; remote URL forwarding remains exclusive to `post-commit` because only that CLI subcommand accepts `--vcs` and `--remote-url`. + +Resolved plan name: `fix-git-hook-cli-guidance`. + +## Success criteria + +- `cli/assets/hooks/pre-commit`, `cli/assets/hooks/commit-msg`, and `cli/assets/hooks/post-commit` remain POSIX `#!/bin/sh` scripts using `set -eu`. +- When `sce` is unavailable, every canonical Git hook prints `sce CLI not found. Install it from https://sce.crocoder.dev/docs/getting-started#install-cli` to stderr and exits with status 0 without attempting its `sce hooks` command. +- When `sce` is available, `pre-commit` executes `sce hooks pre-commit` and forwards all hook arguments unchanged. +- When `sce` is available, `commit-msg` executes `sce hooks commit-msg` and forwards the commit message path and any other arguments unchanged. +- When `sce` is available, `post-commit` preserves its current behavior: it executes `sce hooks post-commit --vcs git`, includes the quoted origin URL through `--remote-url` when non-empty, and forwards all hook arguments unchanged. +- Embedded hook assets used by setup, doctor, and hook lifecycle repair reflect the updated source assets, and repository validation plus direct shell/asset inspection confirm the missing-CLI contract for all three hooks. +- Repository validation passes and shared context accurately documents the non-blocking missing-CLI behavior. + +## Constraints and non-goals + +### Constraints + +- Scope is limited to the canonical Git hooks in `cli/assets/hooks/` and the tests/context needed to protect and document their behavior. +- Keep the scripts POSIX `sh`; do not introduce Bash-only syntax. +- Preserve safe quoting for `"$remote_url"` and `"$@"`, even though the compact request example omitted quotes. +- Use the existing canonical guidance text and URL exactly, with output sent to stderr. +- Missing `sce` is intentionally non-blocking (`exit 0`); failures from an available `sce` continue to propagate through `exec`. +- Keep the hook assets as thin orchestration around the Rust CLI. Do not move hook policy or domain logic into shell. +- Run Rust validation through Nix, with `nix flake check` as the preferred repository-level check. + +### Non-goals + +- Changes to Claude hooks, generated Claude wrappers, OpenCode/Pi integrations, or third-party hooks. +- Adding remote URL options to `pre-commit` or `commit-msg`. +- Changing Rust hook subcommand behavior, CLI parsing, attribution policy, trace persistence, setup installation semantics, or doctor stale-content comparison logic. +- Changing behavior when Git itself is unavailable or when an available `sce` command fails. +- Reformatting unrelated shell scripts or generated configuration. + +## Task stack + +- [x] T01: `Guard every canonical Git hook when sce is unavailable` (status:done) + - Task ID: T01 + - Goal: Add the canonical non-blocking `command -v sce` guard to `pre-commit` and `commit-msg` while preserving the compliant `post-commit` orchestration. + - Boundaries (in/out of scope): + - In: `cli/assets/hooks/pre-commit`, `cli/assets/hooks/commit-msg`, and `cli/assets/hooks/post-commit` only if a consistency adjustment is needed. + - Out: Rust hook runtime/parser behavior, non-Git hook wrappers, generated config trees, setup/doctor lifecycle refactors, and unrelated shell cleanup. + - Done when: all three source assets contain the same exact missing-CLI guidance guard; missing `sce` returns 0 and emits guidance on stderr for each hook; available `sce` receives the expected subcommand and unchanged arguments; `post-commit` still conditionally forwards the origin URL; the change is one coherent atomic commit. + - Verification notes (commands or checks): inspect the three asset diffs, validate the scripts with POSIX `sh -n`, verify the exact guidance string, and rely on `nix flake check` for repository validation. + - Completed: 2026-07-23 + - Files changed: `cli/assets/hooks/pre-commit`, `cli/assets/hooks/commit-msg`, `context/sce/setup-githooks-hook-asset-packaging.md`, `context/context-map.md` + - Evidence: `nix flake check --print-build-logs` passed for tracked check surfaces, including 171/171 Rust unit tests, clippy, rustfmt, and generated-output parity; direct shell/asset inspection passed; `git diff --check` passed. + - Notes: A standalone hook integration suite created during execution was removed at user request, and durable context now records that behavioral shell-asset coverage is not retained. Context sync classified this as a localized change: root shared context was verify-only, while the existing hook-packaging domain document and context-map entry were refreshed to current code truth. + +- [x] T02: `Document non-blocking missing-CLI Git hooks` (status:done) + - Task ID: T02 + - Goal: Synchronize shared context with the canonical Git hook bootstrap behavior introduced by T01. + - Boundaries (in/out of scope): + - In: the existing hook setup/install context documents under `context/sce/` and corresponding `context/context-map.md` entries that describe packaged hook assets, installation, or lifecycle repair; document that all three hooks warn and exit successfully when `sce` is missing, while available-CLI failures still propagate and only `post-commit` forwards remote metadata. + - Out: user-facing website documentation, broad architecture rewrites, decision records, and implementation changes. + - Done when: relevant shared context matches the implemented scripts, no context claims that only `post-commit` provides missing-CLI guidance, context-map descriptions remain accurate, and the documentation update is one coherent atomic commit. + - Verification notes (commands or checks): review `context/sce/setup-githooks-hook-asset-packaging.md`, `context/sce/setup-githooks-install-contract.md`, related hook lifecycle/setup context, and `context/context-map.md`; use `rg -n "sce CLI not found|missing.*sce|post-commit" context/sce context/context-map.md` to find stale statements; inspect the final documentation diff. + - Completed: 2026-07-23 + - Files changed: `context/sce/setup-githooks-install-contract.md`, `context/sce/setup-githooks-install-flow.md`, `context/sce/agent-trace-hook-doctor.md`, `context/context-map.md` + - Evidence: targeted stale-claim and exact-guidance searches matched the all-hook contract; only `cli/assets/hooks/post-commit` contains `--remote-url`; all touched context files remain at or below 250 lines; `git diff --check` passed. + - Notes: Documentation-only task; no build was applicable. Context sync classification is verify-only for root overview/architecture/glossary because the localized behavior was already implemented in T01; domain documents and context-map discoverability were synchronized. + +- [x] T03: `Validate Git hook assets and clean up` (status:done) + - Task ID: T03 + - Goal: Run full repository validation, confirm generated/embedded asset consistency and context sync, and remove any temporary test artifacts. + - Boundaries (in/out of scope): + - In: `nix flake check`, generated-output parity verification if the implementation touches generated files, final shell/asset diff review, context sync verification, worktree cleanliness checks for temporary fake commands or repositories, and only minimal fixes required to make the approved change pass validation. + - Out: new hook behavior, unrelated refactors, and opportunistic documentation changes. + - Done when: `nix flake check` passes; `nix run .#pkl-check-generated` passes if applicable; all three packaged hook assets satisfy the success criteria; no temporary artifacts remain; context accurately reflects behavior; any validation-only correction is landable as at most one coherent atomic commit. + - Verification notes (commands or checks): `nix flake check`; conditionally `nix run .#pkl-check-generated`; `git diff --check`; inspect `git status --short`; verify the exact guidance string appears in all three `cli/assets/hooks/*` files and that only `post-commit` contains `--remote-url`. + - Completed: 2026-07-23 + - Files changed: `context/plans/fix-git-hook-cli-guidance.md`, `context/sce/setup-githooks-hook-asset-packaging.md`, `context/sce/setup-githooks-install-contract.md`, `context/context-map.md`; removed `cli/tests/hook_assets.rs` + - Evidence: `nix flake check --print-build-logs` passed; `nix run .#pkl-check-generated` reported generated outputs up to date; all three hook scripts passed `sh -n`; the exact guidance appeared once in each hook; only `post-commit` contained `--remote-url`; `git diff --check` passed; no task-created temporary artifacts remained. + - Notes: Validation-only final task. The standalone behavioral hook tests were removed at user request after the initial done-gate review, and context was revised to describe the current validation posture. Context-sync classification is verify-only for root shared context because this task introduced no behavior, architecture, policy, or terminology change. + +## Validation report + +### Commands run + +- `nix flake check --print-build-logs` -> exit 0; all compatible-system checks passed, covering the repository test, clippy, rustfmt, generated parity, JavaScript, workflow, portability, and Flatpak validation surfaces. +- `nix run .#pkl-check-generated` -> exit 0; generated outputs are up to date. +- POSIX shell syntax and static asset assertions -> exit 0; all three hooks passed `sh -n`, each contained the exact guidance once, and only `post-commit` contained `--remote-url`. +- Ad hoc isolated hook behavior validation with temporary fake `sce` and `git` commands -> exit 0; all three missing-CLI cases warned and returned success, and all three available-CLI cases forwarded the expected subcommand and arguments, including the quoted post-commit origin URL. +- `git diff --check` -> exit 0. +- Temporary artifact inspection -> no task-created artifacts remain; the temporary validation directory was removed by its command trap, and `cli/tests/` was removed at user request. + +### Success-criteria verification + +- [x] All canonical hooks remain POSIX `#!/bin/sh` scripts using `set -eu` -> direct source inspection and `sh -n`. +- [x] Missing `sce` prints the exact canonical stderr guidance and exits 0 for all three hooks -> isolated behavior validation. +- [x] Available `pre-commit` and `commit-msg` invocations forward all arguments unchanged -> isolated behavior validation. +- [x] Available `post-commit` preserves `--vcs git`, quoted non-empty origin URL forwarding, and unchanged hook arguments -> isolated behavior validation. +- [x] Setup, doctor, and lifecycle repair consume the updated canonical embedded assets -> canonical asset/source inspection plus successful flake build and parity checks. +- [x] Shared context describes the all-hook missing-CLI behavior and post-commit-only remote forwarding -> domain context and context-map review. +- [x] Repository validation and generated-output parity pass -> commands above. + +### Failed checks and follow-ups + +- A direct targeted Cargo integration-test command attempted before the user-requested test removal was blocked by repository bash policy, which requires `nix flake check`; the policy-approved full check passed. No product validation failures remain. + +### Residual risks + +- Behavioral shell-asset tests are not retained in the automated Rust test suite by user request. Final behavior was validated ad hoc, while syntax, embedding, buildability, and generated parity remain covered by repository validation. + +## Open questions + +None. Scope and remote forwarding behavior were resolved during clarification. diff --git a/context/sce/agent-trace-hook-doctor.md b/context/sce/agent-trace-hook-doctor.md index 81651518..c690a542 100644 --- a/context/sce/agent-trace-hook-doctor.md +++ b/context/sce/agent-trace-hook-doctor.md @@ -45,7 +45,7 @@ The runtime in `cli/src/services/doctor/mod.rs` exposes the approved doctor comm - repo-root installed OpenCode integration inventory for `OpenCode plugins`, `OpenCode agents`, `OpenCode commands`, and `OpenCode skills`, Claude integration inventory for `ClaudeCode plugins`, `ClaudeCode agents`, `ClaudeCode commands`, and `ClaudeCode skills`, plus Pi integration inventory for `Pi prompts` and `Pi skills`, scoped to the resolved targets - integration child-row reporting validates installed files against embedded SHA-256 content; missing files render as `[MISS]`, content mismatches render as `[FAIL]`, and any affected parent group renders as `[FAIL]` - OpenCode plugin inventory includes the installed manifest file plus plugin/preset artifacts as required presence-only files; Claude groups are derived from embedded `.claude` assets (`settings.json` and `hooks/**` under `ClaudeCode plugins`, including `.claude/hooks/run-sce-or-show-install-guidance.sh`, then `agents/**`, `commands/**`, and `skills/**`); Pi groups are derived from embedded `.pi` assets (`prompts/**` under `Pi prompts`, `skills/**` under `Pi skills`); generated `config/.opencode/**`, `config/.claude/**`, and `config/.pi/**` trees are not inspected by doctor -- repair-mode delegation to `ServiceLifecycle::fix` implementations: `HooksLifecycle::fix` reuses `install_required_git_hooks` for missing hooks directories plus missing, stale, or non-executable required hooks; `LocalDbLifecycle::fix`, `AuthDbLifecycle::fix`, and `AgentTraceDbLifecycle::fix` handle bootstrap of missing canonical SCE-owned DB parent directories +- repair-mode delegation to `ServiceLifecycle::fix` implementations: `HooksLifecycle::fix` reuses `install_required_git_hooks` for missing hooks directories plus missing, stale, or non-executable required hooks, so repair restores the canonical all-hook non-blocking missing-`sce` guidance, available-CLI argument/failure propagation, and post-commit-only remote forwarding contract; `LocalDbLifecycle::fix`, `AuthDbLifecycle::fix`, and `AgentTraceDbLifecycle::fix` handle bootstrap of missing canonical SCE-owned DB parent directories ## Approved human text-mode contract diff --git a/context/sce/setup-githooks-hook-asset-packaging.md b/context/sce/setup-githooks-hook-asset-packaging.md index ad592370..a926c606 100644 --- a/context/sce/setup-githooks-hook-asset-packaging.md +++ b/context/sce/setup-githooks-hook-asset-packaging.md @@ -14,11 +14,13 @@ Task `sce-setup-githooks-any-repo` `T02` defines how required git-hook templates These templates are emitted into `OUT_DIR/setup_embedded_assets.rs` as `HOOK_EMBEDDED_ASSETS` with deterministic sorted relative paths. -Current `post-commit` template behavior is: +All three templates are POSIX `sh` scripts with `set -eu`. Before invoking `sce`, each checks `command -v sce`; when the CLI is unavailable, it prints branded, multiline installation guidance to stderr and exits successfully so Git operations are not blocked solely by a missing local CLI installation. ANSI styling is emitted only when stderr is a terminal; redirected output remains plain text. Failures from an available `sce` command continue to propagate through `exec`. -- resolve `origin` with `git remote get-url origin`; if `sce` is not on `PATH`, print `sce CLI not found. Install it from https://sce.crocoder.dev/docs/getting-started#install-cli` to stderr and exit successfully so missing local CLI installation does not block the commit -- if the remote lookup returns a non-empty URL, invoke `sce hooks post-commit --vcs git --remote-url "$remote_url" "$@"` -- otherwise still invoke `sce hooks post-commit --vcs git "$@"`; Rust-side validation fails this missing-URL path without blocking git commit completion under the hook script policy. +Available-CLI behavior remains hook-specific: + +- `pre-commit` invokes `sce hooks pre-commit "$@"`. +- `commit-msg` invokes `sce hooks commit-msg "$@"`. +- `post-commit` resolves `origin` with `git remote get-url origin`; when the lookup returns a non-empty URL, it invokes `sce hooks post-commit --vcs git --remote-url "$remote_url" "$@"`, otherwise it invokes `sce hooks post-commit --vcs git "$@"`. Remote metadata forwarding is exclusive to `post-commit`. ## Setup-service accessor surface @@ -35,9 +37,4 @@ Current `post-commit` template behavior is: ## Determinism and validation -Packaging determinism is enforced by setup tests in `cli/src/services/setup/mod.rs`: - -- `embedded_hook_manifest_is_complete_sorted_and_normalized` -- `required_hook_lookup_resolves_each_canonical_hook` - -These tests verify manifest completeness (exactly three required hooks), normalized relative paths, sorted ordering, and stable hook lookup semantics. +Generated-output parity and repository validation verify that the embedded asset manifest remains buildable and synchronized with its canonical source inputs. The hook scripts can also be checked directly with POSIX `sh -n`; behavioral test coverage for these shell assets is not currently retained in the Rust test suite. diff --git a/context/sce/setup-githooks-install-contract.md b/context/sce/setup-githooks-install-contract.md index 6f9268bb..b58cbe2d 100644 --- a/context/sce/setup-githooks-install-contract.md +++ b/context/sce/setup-githooks-install-contract.md @@ -32,6 +32,12 @@ Out of scope for this contract task: No additional hook types are installed by this workflow. +## Installed hook bootstrap behavior + +Every canonical installed hook is a POSIX `sh` script using `set -eu`. Each hook checks `command -v sce` before invocation; when `sce` is unavailable, it prints branded, multiline installation guidance to stderr and exits successfully so the Git operation is not blocked solely by a missing CLI. ANSI styling is emitted only when stderr is a terminal, leaving redirected output unstyled. + +When `sce` is available, hook arguments are forwarded unchanged and failures propagate through `exec`. Remote metadata lookup and `--remote-url` forwarding are exclusive to `post-commit`; `pre-commit` and `commit-msg` invoke only their matching `sce hooks` subcommands. The canonical script details and validation posture live in [setup-githooks-hook-asset-packaging.md](setup-githooks-hook-asset-packaging.md). + ## Target path resolution For a selected target repository, setup resolves effective hook destination using git truth: diff --git a/context/sce/setup-githooks-install-flow.md b/context/sce/setup-githooks-install-flow.md index fa5fedf4..fbea388d 100644 --- a/context/sce/setup-githooks-install-flow.md +++ b/context/sce/setup-githooks-install-flow.md @@ -42,6 +42,8 @@ The flow iterates canonical embedded required hooks (`pre-commit`, `commit-msg`, - `Updated`: hook existed but content and/or executable bit did not match canonical state. - `Skipped`: hook already matched canonical bytes and executable state. +The installed bytes include the shared non-blocking missing-CLI bootstrap: all three hooks warn to stderr and exit successfully when `sce` is unavailable, while an available `sce` receives unchanged hook arguments and its failures propagate. Only `post-commit` performs origin lookup and remote metadata forwarding; see [setup-githooks-hook-asset-packaging.md](setup-githooks-hook-asset-packaging.md) for the canonical payload contract. + ## Staged write and remove-and-replace behavior When replacing an existing hook, setup always writes canonical bytes to a unique staging file in the hooks directory, enforces executable permissions on the staged payload, removes the existing hook directly, and swaps the staged content into the final hook path.