fix(hooks): repair four autoship infra bugs (#2224-#2227)#141
Conversation
Fixes four interrelated bugs that compound under orchestration load: - monitor-issues.sh: state lookup used raw issue number as jq key, but state.json uses prefixed keys (`issue-<N>`). Tracked check always missed → emitted [ISSUE_NEW] for every open issue on every poll. Fix: prefix key with "issue-" in both NEW and CLOSED paths. (Maleick/TextQuest#2227) - monitor-prs.sh: `date -j -f` on macOS treats UTC timestamps as local, producing 5h-stale epoch (EST). The <60s age gate passed for hours after merge, and [BEACON] had no idempotency check. Result: BEACON transition emitted every 30s poll indefinitely. Fix: `TZ=UTC date -j -f` for correct parse; gate BEACON emission behind SEEN_FILE marker so it fires once per PR. (Maleick/TextQuest#2225) - cleanup-worktree.sh: closed GitHub issues based on state.json=="merged" alone, without verifying the linked PR actually merged. On session restart, sweep-stale triggered cleanup for in-flight issues whose state had been pre-written merged — closing them on GitHub despite no PR existing. Also fixed undefined `$ISSUE_STATE` at pre-cleanup safety gate. Fix: query state.json for ISSUE_STATE; require pr_number + pr_state == MERGED via `gh pr view` before invoking `gh issue close`. (Maleick/TextQuest#2224) - skills/dispatch: documented Agent-tool cwd hazard. Each Bash call spawns a fresh shell; `cd <worktree>` does not persist. Workers without `cd <worktree> &&` prefix drift to parent session's branch on commit. Prefer tmux/Codex app-server for worktree-isolated work. (Maleick/TextQuest#2226)
There was a problem hiding this comment.
Pull request overview
This PR fixes several AutoShip hook behaviors that caused repeated/incorrect event emission and unsafe issue closure during orchestration runs, plus documents an Agent-tool working-directory pitfall.
Changes:
- Fix state key lookup in
monitor-issues.shto use theissue-<N>key format. - Fix merge-age computation and add idempotent BEACON gating in
monitor-prs.sh. - Add safety checks in
cleanup-worktree.shto verify a linked PR is actually MERGED before closing the GitHub issue, and fix a state variable mismatch. - Document Agent-tool CWD non-persistence hazard in dispatch skill docs.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| skills/dispatch/SKILL.md | Documents the Agent-tool CWD hazard and required mitigation. |
| hooks/monitor-prs.sh | Forces UTC parsing for merge timestamps; gates BEACON transition to fire once. |
| hooks/monitor-issues.sh | Uses prefixed issue-<N> keys when checking tracking state. |
| hooks/cleanup-worktree.sh | Verifies linked PR is MERGED before closing issues; reads merge-state from state.json. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ISSUE_STATE_FROM_FILE=$(jq -r --arg key "$ISSUE_KEY" '.issues[$key].state // "unknown"' ".autoship/state.json" 2>/dev/null) || ISSUE_STATE_FROM_FILE="unknown" | ||
| if [[ "$ISSUE_STATE_FROM_FILE" == "merged" ]]; then |
There was a problem hiding this comment.
cleanup-worktree.sh runs with set -u, but the script references $STATE_FILE earlier (for result freshness) without ever defining it. In this hunk you also hard-code .autoship/state.json; please define STATE_FILE once (e.g., STATE_FILE=.autoship/state.json) and use it consistently so the script doesn’t abort on an unset variable and reads a single canonical state path.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Summary
Four interrelated AutoShip hook bugs surfaced during TextQuest orchestration. All fixes landed in one branch because they were filed together and share overlapping test surface.
Fixes
monitor-issues.sh — state key format mismatch
Closes Maleick/TextQuest#2227
State lookup used raw issue number (
\"2227\") but state.json uses prefixed keys (\"issue-2227\"). Tracked check always missed → emitted[ISSUE_NEW]for every open issue on every 60s poll.Applied to both
[ISSUE_NEW]and[ISSUE_CLOSED]paths.monitor-prs.sh — UTC parse + BEACON idempotency
Closes Maleick/TextQuest#2225
BSD `date -j -f` on macOS treats UTC timestamps as local. In EST this produces a 5h-stale epoch; the `<60s` age gate passes for hours.
[BEACON]transition message had no seen-check, so it re-emitted every poll.Fix: force `TZ=UTC` on parse; gate BEACON with `$SEEN_FILE` marker (`:BEACON_MERGED`).
Verified:
TZ=UTC date -j -fvs unscoped produces 18000s diff on EST — this is the bug.cleanup-worktree.sh — verify PR merged before closing issue
Closes Maleick/TextQuest#2224
The script closed GitHub issues whenever:
No check that the linked PR actually merged. On session restart, sweep-stale called cleanup-worktree for in-flight issues whose state had been pre-written merged (by prior partial runs or Haiku triage) — then
gh issue closefired with no PR backing it.Fix:
\$ISSUE_STATE_FROM_FILE(previously used undefined\$ISSUE_STATEin safety gate at line 127).pr_number+gh pr view --json state == MERGEDbefore invokinggh issue close.skills/dispatch — document Agent-tool cwd hazard
Closes Maleick/TextQuest#2226
Each `Bash` tool call in an Agent-tool worker spawns a fresh shell. `cd ` in one call does not persist. Workers without `cd &&` prefix drift to the parent session's branch on commit. Added warning section to dispatch SKILL.md with required mitigation and preferred alternatives (tmux/Codex).
Test plan