GitHub Link Tracking & Live Status: Design Exploration
Status: Design exploration for GitHub link tracking & live status (Phase 2, Agent Orchestration Program) — not yet implemented
Problem
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 autonomous queue (Phase 4) 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 (V1)
- 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.
Defer
- 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. multicode supports it; jackin❯ V1 should too if cost is low (Octocrab handles GHE clients with one extra config line). Confirm in design. - PR review summary text (who approved, what comments). Just state in V1.
- Cross-link aggregation ("show me all open PRs across all instances"). Defer until Phase 4.
- GitLab / Bitbucket. Defer indefinitely; if demand surfaces, abstract the fetcher behind a
LinkProvidertrait.
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 for V1; 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. Long-term, a GitHub App (with per-installation tokens) is more durable than a PAT. Defer the design but flag it for the multi-tenant Kubernetes future.
Related Files
- 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
See Also
- 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