fix(framework): per-session ticket files unblock parallel sessions [#439]
The ticket gate required the single .crush/active-ticket file, so two
concurrent sessions overwrote each other's ticket mid-work. The gate now
accepts any non-empty .crush/active-ticket* file; each session keeps its
own (e.g. active-ticket-plant, active-ticket-core). Also prune .crush/
session scratch from both shellcheck scanners so one session's throwaway
probe scripts cannot block the other session's commits. Documented in
AGENTS.md Task Tracking.
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -160,6 +160,10 @@ for a full audit or `--fast` for pre-commit speed. Bypass with `--no-verify`
|
||||
The Crush hook (`hooks/ticket-gate.sh`) blocks modifying operations
|
||||
until this file exists. If no ticket exists, CREATE ONE FIRST via
|
||||
redmine-cli, then set it. Clear when done: `> .crush/active-ticket`.
|
||||
**Parallel sessions:** each session uses its OWN suffixed file (e.g.
|
||||
`.crush/active-ticket-plant`, `.crush/active-ticket-core`) so concurrent
|
||||
sessions never clobber each other's ticket; any non-empty
|
||||
`.crush/active-ticket*` satisfies the gate.
|
||||
- **WORKING.md** is the only in-repo task tracker — a scratchpad for the current
|
||||
session. The pre-commit hook blocks commits while any task remains unchecked.
|
||||
- **Parallel sessions:** when two sessions share this repo (e.g. physical plant
|
||||
|
||||
+12
-7
@@ -9,7 +9,6 @@
|
||||
# run audits, check status, etc.).
|
||||
set -euo pipefail
|
||||
|
||||
TICKET_FILE="${CRUSH_PROJECT_DIR}/.crush/active-ticket"
|
||||
TOOL="${CRUSH_TOOL_NAME:-}"
|
||||
CMD="${CRUSH_TOOL_INPUT_COMMAND:-}"
|
||||
|
||||
@@ -54,12 +53,18 @@ case "$FILE_PATH" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for active ticket
|
||||
if [ -f "$TICKET_FILE" ] && [ -s "$TICKET_FILE" ]; then
|
||||
TICKET=$(cat "$TICKET_FILE")
|
||||
printf '{"context":"Active ticket: %s"}\n' "$TICKET"
|
||||
exit 0
|
||||
fi
|
||||
# Check for active ticket. Parallel sessions each use their OWN file:
|
||||
# .crush/active-ticket (default / single session)
|
||||
# .crush/active-ticket-<name> (suffixed per session; any non-empty one
|
||||
# satisfies the gate — sessions never fight
|
||||
# over one file)
|
||||
GATE_OK=0
|
||||
for f in "$CRUSH_PROJECT_DIR"/.crush/active-ticket*; do
|
||||
[ -f "$f" ] && [ -s "$f" ] || continue
|
||||
GATE_OK=1
|
||||
printf '{"context":"Active ticket(s): %s -> %s"}\n' "$(basename "$f")" "$(cat "$f")"
|
||||
done
|
||||
[ "$GATE_OK" -eq 1 ] && exit 0
|
||||
|
||||
# No active ticket — block
|
||||
cat >&2 <<'MSG'
|
||||
|
||||
@@ -41,7 +41,7 @@ TODAY="$(date +%Y-%m-%d)"
|
||||
# Runs in Docker so the host stays clean (no native shellcheck required).
|
||||
# ----------------------------------------------------------------------------
|
||||
$RULE_VERBOSE && log_step "Shell scripts (shellcheck)"
|
||||
mapfile -d '' SH_FILES < <(find . -path ./.git -prune -o -path ./.tmp -prune -o -path ./vendor -prune -o -path ./archive -prune -o -path ./node_modules -prune -o \( -name '*.sh' -o -name '*.bash' \) -print0 2>/dev/null)
|
||||
mapfile -d '' SH_FILES < <(find . -path ./.git -prune -o -path ./.tmp -prune -o -path ./.crush -prune -o -path ./vendor -prune -o -path ./archive -prune -o -path ./node_modules -prune -o \( -name '*.sh' -o -name '*.bash' \) -print0 2>/dev/null)
|
||||
if [ "${#SH_FILES[@]}" -gt 0 ]; then
|
||||
if have shellcheck; then
|
||||
if shellcheck "${SH_FILES[@]}" >/dev/null 2>&1; then
|
||||
|
||||
+2
-1
@@ -36,7 +36,8 @@ mapfile -t FILES < <(
|
||||
*) echo "$f_abs" ;;
|
||||
esac
|
||||
done < <(find "$ROOT" -type f -name '*.sh' \
|
||||
-not -path '*/.git/*' -not -path "$ROOT/vendor/*")
|
||||
-not -path '*/.git/*' -not -path "$ROOT/vendor/*" \
|
||||
-not -path "$ROOT/.crush/*")
|
||||
fi
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user