Issue tracker: GitHub#
Issues and specs for SnagBadger live at https://github.com/CosticaPuntaru/SnagBadger/issues. Use the gh CLI for all operations.
Conventions#
- Create an issue:
gh issue create --title "..." --body "...". For multi-line bodies, write the exact text to a temporary UTF-8 file and pass --body-file <path>. Use this for issue and PR bodies and comments. - Read an issue:
gh issue view <number> --json number,title,body,labels,comments. - List issues:
gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'with appropriate--labeland--statefilters. - Make an issue a sub-issue of a parent:
gh issue create --parent <parent> ..., orgh issue edit <parent> --add-sub-issue <child>afterwards (gh2.94+). Oldergh:gh api --method POST repos/<owner>/<repo>/issues/<parent>/sub_issues -F sub_issue_id=<child-db-id>(database id, as in Blocking below). Without sub-issues, putPart of #<parent>at the top of the child body. - Comment on an issue:
gh issue comment <number> --body "..." - Apply / remove labels:
gh issue edit <number> --add-label "..."/--remove-label "..." - Close:
gh issue close <number> --comment "..."
Infer the repo from git remote -v; gh does this automatically when run inside a clone.
Pull requests as a triage surface#
PRs as a request surface: no. (Set to yes if this repo treats external PRs as feature requests; /triage reads this flag.)
When set to yes, PRs run through the same labels and states as issues, using the gh pr equivalents:
- Read a PR:
gh pr view <number> --commentsandgh pr diff <number>for the diff. - List external PRs for triage:
gh api --paginate 'repos/{owner}/{repo}/pulls?state=open' --jq '.[] | select(.author_association | IN("OWNER","MEMBER","COLLABORATOR") | not) | {number, title, author: .user.login, author_association, labels: [.labels[].name]}'. - Comment / label / close:
gh pr comment,gh pr edit --add-label/--remove-label,gh pr close.
GitHub shares one number space across issues and PRs, so a bare #42 may be either: resolve with gh pr view 42 and fall back to gh issue view 42.
When a skill says "publish to the issue tracker"#
Create a GitHub issue.
When a skill says "fetch the relevant ticket"#
Read it as in Read an issue above.
Wayfinding operations#
Used by /wayfinder. The map is a single issue with child issues as tickets.
- Map: a single issue labelled
wayfinder:map, holding the Notes / Decisions-so-far / Fog body.gh issue create --label wayfinder:map. - Child ticket: an issue linked to the map as a GitHub sub-issue (see Make an issue a sub-issue of a parent). Where sub-issues aren't enabled, add the child to a task list in the map body and put
Part of #<map>at the top of the child body. Labels:wayfinder:<type>(research/prototype/grilling/task). Once claimed, the ticket is assigned to the driving dev. - Blocking: GitHub's native issue dependencies, the canonical, UI-visible representation. Add an edge with
gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>, where<blocker-db-id>is the blocker's numeric database id (gh api repos/<owner>/<repo>/issues/<n> --jq .id, not the#numberornode_id). GitHub reportsissue_dependencies_summary.blocked_by(open blockers only, the live gate). Where dependencies aren't available, fall back to aBlocked by: #<n>, #<n>line at the top of the child body. A ticket is unblocked when every blocker is closed. - Frontier query: list the map's open children (
gh issue list --state open, scoped to the map's sub-issues / task list), drop any with an open blocker (issue_dependencies_summary.blocked_by > 0, or an open issue in theBlocked byline) or an assignee; first in map order wins. - Claim:
gh issue edit <n> --add-assignee @me, the session's first write. - Resolve:
gh issue comment <n> --body "<answer>", thengh issue close <n>, then append a context pointer (gist + link) to the map's Decisions-so-far.
Roadmap maintenance and closure on merge#
Standing user preference: every wayfinder session adds newly identified work to its affected roadmaps, ticks completed work off, and closes completed tickets when their implementation PR merges. This is ongoing authorization for evidence-backed tracker reconciliation, not authorization to merge PRs or supply human decisions.
Each map has a ### Progress checklist under Notes. Add - [ ] [Ticket title](issue URL) when creating or linking in-scope work; change it to - [x] when that ticket is completed. Keep partial, blocked, and pending-merge items unchecked. Include decision children and linked implementation backlogs/tasks that deliver the map's scope. This user-requested checklist overrides wayfinder's default of finding open tickets only by query; native children and dependencies still determine the frontier. Detailed answers remain in tickets, with resolution gists in Decisions so far. Leave cancelled/out-of-scope tickets out of completed progress and link their disposition in Out of scope.
- At session start, read the relevant map and live child/dependency states. Check linked PR states for claimed tickets and recorded handoffs; reconcile completed merged work before selecting the next frontier ticket. A status audit may reconcile several previously completed tickets without resolving new decisions.
- Before PR handoff, map each ticket's full acceptance criteria to the final change and exact-commit verification. Put
Closes #<number>in the PR body for each fully delivered implementation ticket. UseRefs #<number>for partial work, parent maps/backlogs, and unresolved decisions. GitHub automatically closes linked issues when the PR merges into the default branch; a merge into a stacking branch does not complete that step. - A decision/prototype ticket qualifies for closure only when its human acceptance is already recorded and its question is resolved. Post a resolution comment with that evidence and remaining scope. If accepted code still awaits merge, link the resolution from the map's Notes and use a closing keyword in its PR; after merge, move the pointer to Decisions so far. Decisions without a code delivery can close on recorded resolution as usual. A code merge alone never supplies human acceptance.
- After merge, verify linked tickets actually closed. For completed tickets missed by closing keywords, post a completion comment linking the merged PR and acceptance/verification evidence, then close as completed. Keep incomplete or acceptance-blocked tickets open with the specific remaining criteria recorded.
- Re-read each affected map immediately before editing to preserve concurrent updates. Add newly identified in-scope work to Progress, creating a ticket when its question or acceptance criteria can be stated precisely; leave less-defined work in Not yet specified. Tick completed tickets off and add or refresh one title-linked resolution pointer per closed decision in Decisions so far; keep detailed answers in the ticket. Keep implementation completion distinct from product decisions. Remove graduated fog, retain remaining scope with its existing owner or create a precise follow-up, and check native blockers/frontier status. Close a map/backlog only when its destination/completion criteria are met.
- Before finishing, read back ticket states and changed map sections. Report completed closures and any tracker update failures. If a session ends before merge, the PR closing links and current roadmap Notes must leave the pending state explicit.
Roadmap updates are performed through gh by the session doing the work or the next wayfinder reconciliation. GitHub closing keywords automate ticket closure; they do not edit map prose. Repository-wide scheduled or Actions-based map editing is not configured by this policy.