Skip to content

Add issue event history to issue_read behind a feature flag - #3178

Open
louim wants to merge 1 commit into
github:mainfrom
louim:issue-events-timeline
Open

Add issue event history to issue_read behind a feature flag#3178
louim wants to merge 1 commit into
github:mainfrom
louim:issue-events-timeline

Conversation

@louim

@louim louim commented Aug 28, 2026

Copy link
Copy Markdown

Summary

Adds three read methods to issue_read (get_events, get_timeline, get_event) exposing an issue's event history, behind a new issue_events feature flag.

Why

Agents can read an issue's state but not how it got there: review requests, label changes, previous titles, referencing commits. Rebuild of @artemsaveliev's #211 on current main, folded into issue_read since that PR predates the go-sdk move and the issue-read consolidation.

@SamMorrowDrums sorry, this PR became much more involved in the current state of the repo. Hopefully it covers everything. Happy to tweak anything you find relevant!

Closes #211
Closes #985
Refs #984

What changed

  • Three methods behind FeatureFlagIssueEvents. get_timeline is a superset of get_events that also carries comments, commits, reviews and cross-references; get_event takes event_id instead of issue_number.
  • New minimal output types, sanitizing every user-authored field.
  • IssueRead / IssueReadWithEvents follow the flag-variant pattern from Expose Copilot review thread resolution reasons #3123.

MCP impact

  • Tool schema or behavior changed

Schema changes only when the flag is on. Ungated issue_read is untouched: issue_read.snap unchanged, and the handler rejects the three methods as unknown when the flag is off.

Prompts tested (tool changes only)

Run against the live API on github/github-mcp-server, cli/cli, golang/go and a private repo.

  • "Who was asked to review this PR, and did anyone review it without being asked?" (get_timeline)
  • "What's the event history of this issue?" (get_events)
  • "What happened on this pull request?" (get_timeline, including cross-repo references)
  • "Look up issue event 17200362448." (get_event)

Also exercised: pagination, renamed, milestone, lock_reason, requested_team against requested_reviewer, and the lockdown paths below.

Security / limits

  • Auth / permissions considered
  • Data exposure, filtering, or token/size limits considered

Lockdown follows the existing split: get_events and get_timeline filter entries whose author lacks push access, get_event refuses the read outright (as issue_read:get does). Verified identical to the pre-existing get_comments path. Attribution reads both Actor and User, since commented and reviewed entries populate only User.

Size is why this is flagged: one 69-entry timeline page is 157KB raw, 26KB trimmed.

Known gap worth a maintainer's opinion: go-github's Timeline type does not model minimized, so a comment hidden as spam or abuse is indistinguishable from a normal one. Same ceiling hides html_url, author_association, updated_at, reactions and lock_reason from get_timeline, making its view of a comment poorer than get_comments.

Tool renaming

  • I am not renaming tools as part of this PR

Lint & tests

  • Linted locally with ./script/lint (0 issues)
  • Tested locally with ./script/test (clean, including -race)

No toolsnap drift; script/generate-docs leaves README.md unchanged.

Docs

  • Updated (README / docs / examples)

Adds three read methods to issue_read, gated behind the new issue_events
feature flag:

- get_events   - the issue's event feed (labeled, assigned, closed, ...)
- get_timeline - the full timeline, a superset that also carries comments,
                 commits, reviews and cross-references
- get_event    - a single event addressed by its own event_id

Behind the flag because the REST payloads are large and the added schema is
not free: a single timeline page measured 157KB raw. Both feeds are trimmed
to minimal types (MinimalIssueEvent, MinimalTimelineItem) that keep the event
semantics and sanitize every user-authored field, in line with the surrounding
issue reads, bringing that page down to 21KB.

Trimming keeps the fields that carry event identity rather than everything the
upstream types can hold:

- The issue is kept as a compact MinimalIssueRef. Only get_event sends one,
  and since it is addressed by event id that ref is the only thing naming the
  issue an event belongs to.
- Timeline entries carry commit_repository, derived from the upstream
  commit_url. A referenced or force-push entry frequently points at a commit
  outside the issue's own repo (a fork branch, or an unrelated repo whose
  commit message mentioned the issue), so a bare commit_id cannot be resolved.
- committed entries carry the commit's author and committer. Those entries have
  no actor and no user, so without them the commit history is anonymous. They
  are the commit object's name/email rather than GitHub logins, which is why
  lockdown still cannot verify them.
- review_dismissed events carry the dismissed review's state, id, dismissal
  message and commit, which the event name alone does not convey.
- Commit ancestry (Timeline.Parents) is dropped: a timeline is read to follow
  the issue, not to walk commit history.

The ungated issue_read is untouched: same schema (issue_read.snap is
unchanged), and the handler rejects the three methods as unknown when the
flag is off. issue_number leaves the schema-level required list on the gated
variant only, since get_event has no issue number to supply; the handler
enforces it per method.

Lockdown mode follows the existing split: get_events and get_timeline filter
out entries whose author lacks push access, while get_event refuses the read
outright, as issue_read:get does. Attribution consults both Actor and User,
since commented and reviewed entries name their author in User and leave
Actor empty.

Refs github#984, github#985
Closes github#211

Co-authored-by: Artem Saveliev <artemsaveliev@github.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@louim
louim requested a review from a team as a code owner August 28, 2026 22:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add tool to get_issue_timeline

1 participant