Add issue-work skill for end-to-end ticket workflow #9

Merged
bryan merged 9 commits from claude/tender-jepsen-a86af3 into main 2026-04-18 04:34:41 +00:00
Owner

Summary

Adds a Claude Code skill (dot-claude/skills/issue-work/) plus two supporting sub-agents (dot-claude/agents/ticket-analyst.md, dot-claude/agents/impl-reviewer.md) that codify a consistent multi-repo ticket workflow.

State lives under ~/.claude/issue-work/{owner}-{repo}-{N}/ so resume works even after worktree teardown.

Standalone — no Athena Notes dependency.

Files

  • dot-claude/skills/issue-work/SKILL.md — orchestrator
  • dot-claude/skills/issue-work/references/fetch-ticket.md — long-form gh/tea fetch recipes
  • dot-claude/skills/issue-work/references/repo-resolution.md — local clone discovery
  • dot-claude/agents/ticket-analyst.md — haiku, fetch + digest
  • dot-claude/agents/impl-reviewer.md — sonnet, lens-scoped reviewer

After merge

These files were created first at the real paths ~/.claude/skills/issue-work/... and ~/.claude/agents/.... To switch to stow-managed symlinks:

rm -rf ~/.claude/skills/issue-work
rm -f ~/.claude/agents/ticket-analyst.md ~/.claude/agents/impl-reviewer.md
cd ~/code/dotfiles && stow . --dotfiles --target $HOME

Test plan

  • Skill appears in skills list after a fresh Claude Code session
  • Pasting a GitHub issue URL auto-invokes the skill
  • ticket-analyst produces a clean context.md on a real issue with comments + linked refs
  • Ordered source detection (GitHub before Forgejo) handles both correctly
  • Parallel Explore agents run concurrently during plan phase
  • Approval checkpoint blocks implementation until user confirms
  • Three reviewers run in parallel, each produces review-{lens}.md
  • Resuming on an existing ticket reads progress.md status correctly
  • Forgejo flow works (env token + API paths)
## Summary Adds a Claude Code skill (`dot-claude/skills/issue-work/`) plus two supporting sub-agents (`dot-claude/agents/ticket-analyst.md`, `dot-claude/agents/impl-reviewer.md`) that codify a consistent multi-repo ticket workflow. State lives under `~/.claude/issue-work/{owner}-{repo}-{N}/` so resume works even after worktree teardown. Standalone — no Athena Notes dependency. ## Files - `dot-claude/skills/issue-work/SKILL.md` — orchestrator - `dot-claude/skills/issue-work/references/fetch-ticket.md` — long-form gh/tea fetch recipes - `dot-claude/skills/issue-work/references/repo-resolution.md` — local clone discovery - `dot-claude/agents/ticket-analyst.md` — haiku, fetch + digest - `dot-claude/agents/impl-reviewer.md` — sonnet, lens-scoped reviewer ## After merge These files were created first at the real paths `~/.claude/skills/issue-work/...` and `~/.claude/agents/...`. To switch to stow-managed symlinks: ```bash rm -rf ~/.claude/skills/issue-work rm -f ~/.claude/agents/ticket-analyst.md ~/.claude/agents/impl-reviewer.md cd ~/code/dotfiles && stow . --dotfiles --target $HOME ``` ## Test plan - [ ] Skill appears in skills list after a fresh Claude Code session - [ ] Pasting a GitHub issue URL auto-invokes the skill - [ ] `ticket-analyst` produces a clean `context.md` on a real issue with comments + linked refs - [ ] Ordered source detection (GitHub before Forgejo) handles both correctly - [ ] Parallel Explore agents run concurrently during plan phase - [ ] Approval checkpoint blocks implementation until user confirms - [ ] Three reviewers run in parallel, each produces `review-{lens}.md` - [ ] Resuming on an existing ticket reads `progress.md` status correctly - [ ] Forgejo flow works (env token + API paths)
Adds a Claude Code skill (dot-claude/skills/issue-work/) plus two
supporting sub-agents (dot-claude/agents/ticket-analyst.md,
dot-claude/agents/impl-reviewer.md) that codify a consistent
multi-repo ticket workflow: intake → plan → implement → self-review,
with a human approval checkpoint before implementation and three
parallel review lenses (correctness / security / simplicity) before
returning for human review.

ticket-analyst (haiku) fetches + digests the ticket via gh or Forgejo
REST API. impl-reviewer (sonnet) runs three parallel instances, each
loading engineering:code-review, security-review, or simplify.

State lives under ~/.claude/issue-work/{owner}-{repo}-{N}/ and
survives worktree teardown for resumability.
- Add missing Write tool to impl-reviewer frontmatter (runtime bug)
- Fix ExitPlanMode contradiction in edge-case table
- Repair garbled sentence in Phase 3.6
- Align curl flags to -sS in ticket-analyst for louder API errors
- Reorder test-detection table so monorepo drivers win over package.json
- Enumerate valid progress.md status values near State Root
- Anchor GitHub/Forgejo URL regexes with /?$ to avoid over-match
- Note SSRF-adjacent risk on WebFetch of ticket URLs
- Call out false-match behavior of the SHA regex
- fetch-ticket: use mktemp for linked-ref scratch file; /tmp/txt was
  vulnerable to parallel-run collision and symlink-clobber on shared hosts
- SKILL: split progress.md status "implementing" into "implementing"
  (in-flight, code may be half-written) vs "implemented" (tests green,
  Phase 4 not yet run) so resume picks the right phase
- repo-resolution: verify remote URL against the ticket's forge host
  (FORGE_HOST), not just "github.com" — Forgejo/Gitea/Codeberg clones
  were previously never recognized
- SKILL: add Forgejo default-branch snippet (was a pointer to a section
  that didn't exist); branch pre-flight auth check by FORGE so GitHub and
  Forgejo tickets don't cross-run each other's checks
- SKILL: read gh pr create title from context.md frontmatter via awk,
  avoiding shell-metachar mangling on titles with quotes/backticks/\$
- fetch-ticket: align Forgejo auth form with ticket-analyst.md
  (\${X:-\${Y:-}} is safe under set -u; \${X:=Y} isn't)
- repo-resolution: drop redundant git@github.com: grep alternative —
  [:/] already covers HTTPS and SSH remotes in one class
- SKILL: promote Plan Mode / ExitPlanMode aside out of a parenthetical
- SKILL.md: make Forgejo token check safe under `set -u`, matching
  ticket-analyst.md and fetch-ticket.md.
- SKILL.md: warn on `git fetch` failure instead of silently continuing
  with a stale ref.
- SKILL.md + ticket-analyst.md: accept browser-pasted URL subroutes and
  `#issuecomment-...` fragments (`([/#].*)?` suffix).
- SKILL.md: strip surrounding quotes when reading `title:` from the
  context frontmatter for `gh pr create`.
- ticket-analyst.md: the `rg` snippet now reads from a `mktemp` scratch
  file, matching the long form and avoiding a stdin hang.
- fetch-ticket.md: require a host allowlist before `WebFetch` on
  ticket-extracted URLs (SSRF guardrail).
- repo-resolution.md: anchor the remote URL match in the fallback loop
  so `github.com.attacker.tld` substrings cannot false-positive.
- Strip `:port` suffix from the parsed host so `github.com:22` still
  matches the `github.com` allowlist entry instead of slipping through
  to the catch-all.
- Reject empty hosts up front (e.g. malformed `https:///path` URLs)
  before the case statement, so an unset or empty `FORGE_HOST` cannot
  accidentally match an empty host.
- Comment that the surrounding loop is a precondition for the `continue`
  statements in the case arms.
- Close SSRF allowlist bypass: `${host%%:*}` alone was stripped at the
  first colon, so a URL like `https://github.com:anything@evil.internal/x`
  resolved to host=`github.com` (allowlisted) even though WebFetch would
  actually hit `evil.internal`. Strip userinfo (`${host##*@}`) BEFORE
  port so the real host is what the case-statement checks.
- Broaden dirty-tree porcelain match to include `T` (type change) and
  `U` (unmerged / mid-conflict), plus the `^ [MD]` case where the
  change is only in the working tree. Prevents resuming into a merge
  conflict being classified as a clean tree.
- Make the Forgejo comments paginator robust: capture HTTP status
  alongside the body so a mid-loop 401/403 (non-array error object)
  fails loudly instead of never-matching the `[]` break and blowing
  up `jq -s 'add'` on a non-array.
- Trim trailing sentence punctuation (`.,;:!?`) from extracted URLs so
  prose like "see https://example.com." does not 404 every linked-ref
  title fetch. Applied in both fetch-ticket.md and ticket-analyst.md.
- Buffer Forgejo pages into an array and run `jq -s 'add // []'` after
  the loop, instead of piping `while … | jq`. A pipeline puts each
  side in its own subshell, so the mid-loop `exit 1` on a 401/403
  only killed the loop's subshell — `jq` still ran over the partial
  aggregate, silently succeeding on incomplete data. Post-loop jq
  makes the failure propagate. `// []` also handles the zero-page
  case cleanly instead of jq erroring on empty input.
- Extend the worktree-only arm of the dirty-tree grep from `[MD]`
  to `[MDT]` so ` T` (type change only in the working tree) is
  caught alongside ` M` and ` D`. Rare but real.
Add gitignore allowlist for dot-claude/ mirroring the opencode pattern:
only agents/ and skills/ are tracked; anything Claude Code writes locally
(settings.local.json, projects/, etc.) is ignored so 'stow --adopt' and
inadvertent commits cannot pull in machine-specific state.

Exclude the root .claude/ directory from stow so the local-only
worktrees/ tree is not symlinked alongside dot-claude/.

Document at the top of issue-work/SKILL.md that the skill and its
companion agents are Claude Code only and explain why they live under
dot-claude/ instead of dot-config/opencode/.
- ticket-analyst: use array form AUTH=(-H ...) for Forgejo curl calls, matching
  the hardened pattern in fetch-ticket.md. Protects against tokens containing
  shell metacharacters or spaces.
- issue-work SKILL: each parallel Explore agent writes its own
  explore-{area-slug}.md file instead of appending to a shared explore.md.
  Eliminates the concurrent-write race when two Explores run in parallel.
  Phase 2.3 now reads every explore-*.md and merges them.
- impl-reviewer: reword the Write-tool constraint so it's not self-contradictory
  ('No Write' followed by an implicit exception). Now states explicitly that
  Write is restricted to the review-{lens}.md output file.
bryan merged commit 3a4253cfb3 into main 2026-04-18 04:34:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bryan/dotfiles!9
No description provided.