GitHub Issue Workflow
This repo has a repo-local GitHub Issues CLI at scripts/github_issues.py. It talks directly to the GitHub REST API, so it only needs a fine-grained PAT in GH_TOKEN and does not depend on gh.
Auth
Create a fine-grained PAT with access to the target repository and Issues read/write permission. Then export:
export GH_TOKEN=github_pat_xxx
The script uses git remote origin by default. Set GITHUB_REPOSITORY=owner/repo or pass --repo owner/repo only when you want to override that.
If you keep secrets in the ignored root .env, load them into the shell before running the script:
source .env
Scratch Pad Format
ISSUES.md is a temporary scratch pad for newly discovered open issues. GitHub Issues remain the source of truth after creation.
Agents should treat ISSUES.md as mandatory logging for newly detected or newly created issues. If an issue is discovered during implementation, debugging, or review, add or update the corresponding block in ISSUES.md before finishing the task.
Each issue block should look like:
### QAPP-999 Example issue title
- Title: Example issue title
- GitHub: [#123](https://github.com/owner/repo/issues/123)
- Labels: `bug`, `priority:high`, `area:example`
- Problem: Short problem statement.
- Impact: Short impact statement.
- Files: `path/to/File.kt`; `path/to/Other.kt`
The GitHub line is optional. sync-markdown adds or refreshes it for open issues.
Sync Scratch Pad To GitHub
Preview what the sync would do:
python3 scripts/github_issues.py sync-markdown ISSUES.md --dry-run
Create missing GitHub issues and write back GitHub links into ISSUES.md:
python3 scripts/github_issues.py sync-markdown ISSUES.md
What sync-markdown does:
- Creates a GitHub issue for any scratch block that does not already match an existing issue by GitHub link, embedded scratch ID, or unique exact title.
- Adds the managed label
source:issues-mdplus the labels listed in the scratch block. - Writes or refreshes the optional
GitHubline inISSUES.mdfor open issues. - Reports blocks that point at closed GitHub issues, but does not close, reopen, or delete anything.
What it does not do:
- It does not treat
ISSUES.mdas authoritative for updating existing GitHub issues. - It does not auto-close issues when a block disappears from
ISSUES.md. - It does not remove resolved items from
ISSUES.md; that remains a manual cleanup step.
Ongoing Operations
Create an issue directly:
python3 scripts/github_issues.py create \
--title "Add live signal persistence" \
--body-file /tmp/issue-body.md \
--label enhancement
Update an issue:
python3 scripts/github_issues.py update 123 \
--title "Persist strategy outputs and signals" \
--add-label backend \
--remove-label needs-triage
Close an issue with a comment:
python3 scripts/github_issues.py close 123 \
--comment "Fixed in commit abc123."
Add a comment:
python3 scripts/github_issues.py comment 123 --body-file /tmp/comment.md
Inspect issues:
python3 scripts/github_issues.py list --state open --label source:issues-md
python3 scripts/github_issues.py show 123 --comments