mirror of
https://github.com/garrytan/gstack.git
synced 2026-06-17 07:10:12 +02:00
feat: deploy the Conductor AskUserQuestion hook (setup + upgrade migration)
The PreToolUse hook only delivers its Conductor-prose guarantee if it's installed, but setup skips hook registration in non-interactive (conductor/CI) setups. Two fixes so layer 3 actually deploys: - setup: treat a Conductor workspace as an implicit opt-in for the PreToolUse hook on the silent fall-through (never overriding an explicit opt-out). - migration v1.58.0.0: re-register the hook for existing Conductor installs on /gstack-upgrade, idempotent and respecting plan_tune_hooks=no. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# Migration: v1.58.0.0 — register the PreToolUse AskUserQuestion hook for
|
||||
# existing Conductor installs.
|
||||
#
|
||||
# Why a migration: v1.58 makes the PreToolUse question-preference-hook also
|
||||
# deny the flaky Conductor AskUserQuestion and redirect to a prose decision
|
||||
# brief. But setup's hook-install block skips silently in non-interactive
|
||||
# (conductor/CI) setups, and existing users who previously declined plan-tune
|
||||
# hooks would never pick up the new Conductor backstop. This re-registers the
|
||||
# hook for Conductor users so layer 3 actually deploys.
|
||||
#
|
||||
# Affected: users who run gstack inside Conductor and don't already have the
|
||||
# PreToolUse hook installed.
|
||||
#
|
||||
# Scope guard: only acts inside a Conductor session (CONDUCTOR_* present) and
|
||||
# never overrides an explicit `plan_tune_hooks` opt-out.
|
||||
#
|
||||
# Idempotent: gstack-settings-hook dedupes by (event, matcher, source), and a
|
||||
# .done touchfile gates re-runs.
|
||||
|
||||
set -u
|
||||
|
||||
GSTACK_HOME="${HOME}/.gstack"
|
||||
MIGRATION_DIR="${GSTACK_HOME}/.migrations"
|
||||
DONE="${MIGRATION_DIR}/v1.58.0.0.done"
|
||||
mkdir -p "${MIGRATION_DIR}" 2>/dev/null || true
|
||||
[ -f "${DONE}" ] && exit 0
|
||||
|
||||
# Only relevant inside Conductor — the prose-default behavior is Conductor-scoped.
|
||||
if [ -z "${CONDUCTOR_WORKSPACE_PATH:-}" ] && [ -z "${CONDUCTOR_PORT:-}" ]; then
|
||||
touch "${DONE}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
SETTINGS_HOOK="${SCRIPT_DIR}/bin/gstack-settings-hook"
|
||||
PREF_HOOK="${SCRIPT_DIR}/hosts/claude/hooks/question-preference-hook"
|
||||
CONFIG_BIN="${SCRIPT_DIR}/bin/gstack-config"
|
||||
|
||||
# Respect an explicit opt-out — don't force a hook on a user who said no.
|
||||
_PT=$("${CONFIG_BIN}" get plan_tune_hooks 2>/dev/null || echo "")
|
||||
_PT=$(printf '%s' "${_PT}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')
|
||||
case "${_PT}" in
|
||||
n|no|false|skip|off|0)
|
||||
echo " [v1.58.0.0] plan_tune_hooks opted out — leaving Conductor on guidance-only prose." >&2
|
||||
touch "${DONE}"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -x "${SETTINGS_HOOK}" ] && [ -x "${PREF_HOOK}" ]; then
|
||||
"${SETTINGS_HOOK}" add-event \
|
||||
--event PreToolUse \
|
||||
--matcher '(AskUserQuestion|mcp__.*__AskUserQuestion)' \
|
||||
--command "${PREF_HOOK}" \
|
||||
--source plan-tune-cathedral \
|
||||
--timeout 5 2>/dev/null \
|
||||
&& echo " [v1.58.0.0] Conductor AskUserQuestion prose hook registered (PreToolUse)." >&2 \
|
||||
|| echo " [v1.58.0.0] WARN: could not register the PreToolUse hook; run ./setup --plan-tune-hooks." >&2
|
||||
fi
|
||||
|
||||
touch "${DONE}"
|
||||
exit 0
|
||||
@@ -1371,6 +1371,17 @@ if [ "$NO_TEAM_MODE" -ne 1 ] \
|
||||
*) PT_DECISION="prompt" ;;
|
||||
esac
|
||||
|
||||
# Conductor host reliability: the PreToolUse preference hook also carries the
|
||||
# Conductor-prose enforcement (deny the flaky mcp__conductor__AskUserQuestion,
|
||||
# redirect to a prose decision brief). A Conductor workspace setup otherwise
|
||||
# falls through to "prompt" → the non-interactive skip below, leaving Conductor
|
||||
# users without that backstop. Treat Conductor as an implicit opt-in — but
|
||||
# only on the silent fall-through, never overriding an explicit --no-plan-tune-hooks.
|
||||
if [ "$PT_DECISION" = "prompt" ] && { [ -n "${CONDUCTOR_WORKSPACE_PATH:-}" ] || [ -n "${CONDUCTOR_PORT:-}" ]; }; then
|
||||
PT_DECISION="yes"
|
||||
_PT_CONDUCTOR_AUTO=1
|
||||
fi
|
||||
|
||||
_install_plan_tune_hooks() {
|
||||
"$SETTINGS_HOOK" add-event \
|
||||
--event PostToolUse \
|
||||
@@ -1405,10 +1416,15 @@ if [ "$NO_TEAM_MODE" -ne 1 ] \
|
||||
log ""
|
||||
log "Plan-tune hooks already installed. Run \`$SETTINGS_HOOK list-sources\` to inspect."
|
||||
elif [ "$PT_DECISION" = "yes" ]; then
|
||||
# Explicit opt-in (flag / env / config). Non-interactive.
|
||||
# Explicit opt-in (flag / env / config) or Conductor implicit opt-in. Non-interactive.
|
||||
_install_plan_tune_hooks
|
||||
log ""
|
||||
log "Plan-tune hooks installed. Run /plan-tune anytime to inspect."
|
||||
if [ "${_PT_CONDUCTOR_AUTO:-0}" -eq 1 ]; then
|
||||
log "AskUserQuestion reliability hooks installed (Conductor detected): decisions"
|
||||
log "render as a prose brief instead of the flaky AskUserQuestion tool. Inspect with /plan-tune."
|
||||
else
|
||||
log "Plan-tune hooks installed. Run /plan-tune anytime to inspect."
|
||||
fi
|
||||
touch "$PLAN_TUNE_INSTALL_MARKER"
|
||||
elif [ "$PT_DECISION" = "no" ]; then
|
||||
# Explicit opt-out (flag / env / config). Non-interactive.
|
||||
|
||||
Reference in New Issue
Block a user