refactor(dispatcher): extract SKILL.md bash to dispatcher-tick.sh + lib-dispatch.sh - #71
Merged
Merged
Conversation
…ib-dispatch.sh
PR-3 of the pipeline-docs plan. Pure refactor — behavior preserved.
skills/autonomous-dispatcher/SKILL.md slimmed from 438 lines (224 of which
were inline bash code blocks the agent re-typed each tick) to 114 lines of
prose. The dispatcher agent now invokes a single command per tick:
bash "$PROJECT_DIR/scripts/dispatcher-tick.sh"
That script orchestrates Steps 1-5 in one process, with JUST_DISPATCHED
as a normal in-process bash array. All gh/jq logic lives in the new
lib-dispatch.sh as composable helpers (count_active, list_new_issues,
check_deps_resolved, count_retries, mark_stalled, extract_dev_session_id,
pid_alive, fetch_pr_for_issue, ci_is_green, pr_idle_seconds,
last_reviewed_head, label_swap, was_just_dispatched).
New files:
- skills/autonomous-dispatcher/scripts/lib-dispatch.sh (helpers)
- skills/autonomous-dispatcher/scripts/dispatcher-tick.sh (entry)
- tests/unit/test-lib-dispatch.sh (19 tests)
- docs/designs/dispatcher-skill-slim.md (canvas)
Modified:
- skills/autonomous-dispatcher/SKILL.md (438 -> 114, prose only)
- docs/pipeline/dispatcher-flow.md (cite new helper names per step)
- .github/workflows/ci.yml (extend ShellCheck to new scripts)
- tests/unit/test-{pid-guard,retry-counter-reset,skip-redundant-review,
stale-alive-with-pr}.sh (point at dispatcher-tick.sh + lib-dispatch.sh
instead of SKILL.md; preserve regression-guard intent)
Behavior preservation:
- Same labels at same transitions, same comment phrasings (the [INV-06]
keyword contract depends on this, byte-for-byte).
- Same retry-counter cutoff rule [INV-05], same JUST_DISPATCHED skip
[INV-09], same strict > 300s idle gate [INV-10], same fail-closed
semantics on jq/date errors, same mktemp CWE-377 mitigation.
- All 12 unit tests pass (existing 11 + new test-lib-dispatch.sh).
- shellcheck -S error clean on all dispatcher scripts.
PR-3 unit testing surfaced a real latent bug in the original SKILL.md:
extract_dev_session_id used Python-style (?P<id>...) regex syntax which
jq 1.6+ rejects with "Regex failure: undefined group option". Filed as
issue #70. PR-3 PRESERVES this bug byte-for-byte (one-char fix would
mix refactor with behavior change); test asserts the broken behavior
explicitly. Fix bundled into PR-4.
Out of scope:
- #58 readlink-vendor (lib-agent.sh, separate file) - PR-4
- #59 resume-on-completed-session (new gate) - PR-5
- #60 wall-clock timeout (lib-agent.sh) - PR-5
- #61 MERGED dependency check (mixes refactor + fix) - PR-4
- #62 multi-repo dispatch (major) - PR-6
- #67 INV-15 SIGTERM race (wrapper-side) - separate PR
- #70 Dev Session ID regex (mixes refactor + fix) - PR-4
There was a problem hiding this comment.
Review Summary
This refactoring successfully extracts dispatcher logic from SKILL.md into dedicated scripts, improving testability and maintainability. However, 7 critical defects block merge:
Critical Issues (Must Fix):
- Portability Bug:
grep -oP(Perl regex) fails on macOS/BSD, breaking dependency detection - Word Splitting Bug: Unquoted
$depsiteration causes incorrect parsing of multiple dependencies - Security Risk (CWE-377): Predictable
/tmpPID file paths create race condition vulnerability - Missing Error Handling: All 4 GitHub API query functions (
list_new_issues,list_pending_review,list_pending_dev,list_stale_candidates) lack error handling, causing script crashes on API failures instead of graceful degradation
Positive Aspects:
- Comprehensive unit test coverage with 90 assertions
- Proper preservation of behavior contracts (INV-04 through INV-10)
- Excellent documentation of known issue #70
- Clean separation of concerns with helper functions
Action Required: Address the 7 critical defects above before merge. The portability and error handling issues will cause production failures on non-GNU systems and during GitHub API outages.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
This was referenced May 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR-3 of the pipeline-docs plan. Pure refactor — behavior preserved byte-for-byte.
skills/autonomous-dispatcher/SKILL.mdslimmed from 438 lines (224 of which were inline bash) to 114 lines of prose. The dispatcher agent now invokes a single command per cron tick:bash "$PROJECT_DIR/scripts/dispatcher-tick.sh"That script orchestrates Steps 1–5 in one process. All gh/jq logic lives in the new
lib-dispatch.shas composable helpers.What changed
New files:
skills/autonomous-dispatcher/scripts/lib-dispatch.sh— 13 helper functions (count_active,list_new_issues,check_deps_resolved,count_retries,mark_stalled,extract_dev_session_id,pid_alive,fetch_pr_for_issue,ci_is_green,pr_idle_seconds,last_reviewed_head,label_swap,was_just_dispatched).skills/autonomous-dispatcher/scripts/dispatcher-tick.sh— single entry point. Sources lib, runs all 5 steps in one process withJUST_DISPATCHEDas a normal in-process bash array.tests/unit/test-lib-dispatch.sh— 19 new unit tests for the helpers.docs/designs/dispatcher-skill-slim.md— design canvas.Modified:
skills/autonomous-dispatcher/SKILL.md— 438 → 114 lines, prose + delegation only.docs/pipeline/dispatcher-flow.md— cite new helper names per step..github/workflows/ci.yml— extend ShellCheck to new scripts.tests/unit/test-{pid-guard,retry-counter-reset,skip-redundant-review,stale-alive-with-pr}.sh— point at new scripts instead of SKILL.md, regression-guard intent preserved.Behavior preservation (verified byte-for-byte)
Code reviewer ran a side-by-side comparison against
mainand confirmed:[INV-04]Reviewed-HEAD trailer regex — identical[INV-05]retry-counter cutoff query — identical[INV-06]crash-keyword regex — identical (Task appears to have crashed \\(no PR found\\)\|process not found)[INV-09]JUST_DISPATCHED skip rule — preserved[INV-10]strict> 300sidle gate — logically equivalent (> 300then SIGTERM ⇔<= 300then continue)[INV-06]keyword contract depends on this).date, PID re-verify before SIGTERM — all preserved.Surfaced bug: issue #70
PR-3 unit testing surfaced a real latent bug in the original SKILL.md:
extract_dev_session_iduses(?P<id>...)(Python-style regex) which jq 1.6+ Oniguruma rejects. Resume mode was probably never extracting session IDs in production. Filed as #70. PR-3 preserves the bug byte-for-byte (test asserts the broken behavior so a future fix triggers test failure as intended). Fix bundled into PR-4.Pipeline Docs (CONTRIBUTING.md Rule 1)
Test Plan
Out of scope (deferred)