Skip to content

fix(hooks): repair four autoship infra bugs (#2224-#2227)#141

Merged
Maleick merged 2 commits intomainfrom
fix/autoship-infra-quad
Apr 22, 2026
Merged

fix(hooks): repair four autoship infra bugs (#2224-#2227)#141
Maleick merged 2 commits intomainfrom
fix/autoship-infra-quad

Conversation

@Maleick
Copy link
Copy Markdown
Owner

@Maleick Maleick commented Apr 22, 2026

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.

-      tracked=\$(jq -r --arg n \"\$num\" '.issues[\$n] // empty' \"\$STATE_FILE\")
+      tracked=\$(jq -r --arg n \"issue-\$num\" '.issues[\$n] // empty' \"\$STATE_FILE\")

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 -f vs 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:

  • state.json marked issue "merged"
  • GitHub issue state was still OPEN

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 close fired with no PR backing it.

Fix:

  1. Query state.json for \$ISSUE_STATE_FROM_FILE (previously used undefined \$ISSUE_STATE in safety gate at line 127).
  2. Require pr_number + gh pr view --json state == MERGED before invoking gh issue close.
  3. Emit refusal log to poll.log when verification fails.

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

  • Shell syntax: `bash -n` clean on all three hooks
  • Manual: `TZ=UTC date -j -f` diff confirms 5h skew on EST
  • Manual: prefixed jq key resolves state; raw key misses
  • Live: run one full orchestration cycle post-merge and confirm:
    • `[ISSUE_NEW]` silent for already-tracked issues
    • `[BEACON]` fires exactly once per PR merge
    • No false `gh issue close` on session restart

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)
Copilot AI review requested due to automatic review settings April 22, 2026 06:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.sh to use the issue-<N> key format.
  • Fix merge-age computation and add idempotent BEACON gating in monitor-prs.sh.
  • Add safety checks in cleanup-worktree.sh to 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.

Comment thread hooks/cleanup-worktree.sh
Comment on lines +127 to +128
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
Copy link

Copilot AI Apr 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment thread hooks/monitor-prs.sh Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Maleick Maleick merged commit 40b989b into main Apr 22, 2026
@Maleick Maleick deleted the fix/autoship-infra-quad branch April 22, 2026 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants