GitHub Link Tracking & Live Status: Design Exploration
Designs GitHub link recognition, status refresh, caching, and operator presentation for work attached to agent sessions.
Research state: Incomplete
Summary
GitHub links should attach to agent sessions as typed work references with cached status and explicit refresh behavior.
This exploration informs GitHub link tracking and live status in the Agent Orchestration Program.
Research question
Once the agent has emitted <jackin:issue> or <jackin:pr> tags via the agent tag protocol, the operator wants to see their live state: is the issue still open? Did the PR get approved? Did CI go green? Today jackin❯ has no GitHub status awareness at all — the operator switches to a browser tab to check.
Polling GitHub for every link on every console redraw would burn the rate limit instantly, so this needs a small cache and an awareness of which states change rarely vs frequently.
Why it matters
- It's the most operator-visible payoff of the tag protocol — without live status, the protocol just stores URLs.
- It lets the roadmap-owned Autonomous task queue act on PR state ("re-queue a task whose PR was rejected") without re-implementing GitHub polling inside the queue.
- It's the lowest-risk way to introduce a third-party network dependency (Octocrab) into jackin❯ runtime — the surface is narrow (read-only status fetches) and the failure mode is obvious (status cell shows "?").
Inspiration in multicode
Sources:
- README — Git / GitHub integration (status icons + their meanings)
- Source —
lib/src/services/github_status_service.rs(cadence table, octocrab client, SQLite cache) - Source —
lib/src/schema.rs(github_link_statusestable definition)
multicode polls GitHub via Octocrab on a per-link cadence that varies by state. Cached in per-workspace SQLite (.multicode/cache.sqlite), table github_link_statuses. Refresh windows:
| State | Refresh after |
|---|---|
| Open issue | 10 min |
| Closed issue | 60 min |
| PR building | 1 min |
| PR built, review pending | 5 min |
| PR approved, awaiting merge | 10 min |
| PR closed/merged | 60 min |
| On fetch error | 5 min retry |
Cached fields per row include: URL, kind (issue/PR), host, owner, repo, resource number, issue state, PR state, build state, review state, draft flag, fetched-at, refresh-after, last error.
The TUI renders icons:
- Issue: blue circle (open), gray X (closed)
- PR: state colors plus draft badge, build status (running/success/fail), review status (none/pending/changes/approved)
Recommended shape
Reuse multicode's polling cadence model verbatim — they did the work to calibrate it against real GitHub usage. Use Octocrab as the client. Persist via the persistent storage layer.
Auth source
Reuses the credential source pattern: the operator's GitHub PAT comes from one of env, command, op://, or keychain. Required scopes: public_repo for public repos, repo for private. read:user for resolving avatars later.
The existing gh CLI passthrough is separate and remains how the container talks to GitHub. The link-tracking client is operator-host only — the agent doesn't see the token.
Schema (in the SQLite layer)
CREATE TABLE github_link_statuses (
url TEXT PRIMARY KEY,
kind TEXT NOT NULL, -- 'issue' or 'pr'
host TEXT NOT NULL,
owner TEXT NOT NULL,
repo TEXT NOT NULL,
resource_number INTEGER NOT NULL,
issue_state TEXT, -- 'open' | 'closed' | NULL
pr_state TEXT, -- 'open' | 'merged' | 'closed' | NULL
build_state TEXT, -- 'pending' | 'success' | 'failure' | 'error' | NULL
review_state TEXT, -- 'none' | 'pending' | 'changes_requested' | 'approved'
pr_is_draft BOOLEAN,
fetched_at INTEGER NOT NULL, -- epoch seconds
refresh_after INTEGER NOT NULL, -- epoch seconds
last_error TEXT
);Cache is per-instance (each ~/.jackin/data/<container>/ has its own SQLite). Sharing a cache across instances would be a small efficiency win but creates state-isolation questions — defer.
Fetcher loop
A single async task per running console session (not per-instance) walks all known links across instances, picks ones whose refresh_after is in the past, fetches in batches of N (default 5) to avoid burst rate limit consumption, updates the cache.
Failures: log to last_error, set refresh_after = now + 5 min, console renders a yellow "?" until success.
Console rendering
Each instance row gets a "Links" cell (or expand-to-detail panel) that shows captured <jackin:issue> and <jackin:pr> markers as colored icons, with hover/select revealing details. Clicking opens via the web handler.
Scope
- Octocrab-based fetcher with multicode's cadence table.
- Per-instance SQLite cache (depends on persistent storage layer).
- Console icons for issue/PR state, build, review.
- Operator-host PAT via the existing credential resolution (
op://,${env.VAR}, literal). New backends added when credential source pattern lands. - Console "Links" panel/cell rendering.
- Click-to-open via the
webhandler from operator handler system.
Out of scope
- Custom-link CRUD from the console (multicode allows manually adding links not emitted by the agent). Useful but waits — the agent-emitted flow covers the 95% case.
- GitHub Enterprise host support beyond the standard
https://github.com/<owner>/<repo>URL pattern. - PR review summary text beyond status.
- Cross-link aggregation across all instances.
- GitLab and Bitbucket providers; a future provider need should introduce a
LinkProviderboundary.
Limitations and open questions
- Per-instance cache vs operator-global. Per-instance matches jackin❯ existing data layout but means a link tracked by two instances gets fetched twice. Recommended default: per-instance; revisit if rate-limit pressure shows up.
- Token scope guidance. What's the minimum-privilege token the docs should recommend?
public_repoworks for public-only; private repos needrepo. multicode docs are clear on this; jackin❯ docs should match. - GitHub App alternative. A GitHub App with per-installation tokens is more durable than a PAT but remains outside the current single-operator design.
Code touchpoints
- New module (e.g.
src/runtime/link_tracking.rs) — fetcher loop + cadence + cache writes crates/jackin-capsule/src/pr_context.rs— existing focused-instance PR context this feature extendssrc/console/tui/view/— icon rendering- The persistent-storage module owns the SQL schema
Related work
- GitHub link tracking & live status — roadmap item
- Agent Orchestration Program
- Agent tag protocol — input
- Persistent storage layer — cache home
- Operator handler system — click-to-open target
- Credential source pattern — GitHub PAT plumbing