Skip to content

Commit 409db99

Browse files
louimartemsavelievclaude
committed
Add issue event history to issue_read behind a feature flag
With the issue_events feature flag on, issue_read gets three more methods: - get_events lists the issue's events: labeled, assigned, closed, renamed and so on. - get_timeline lists the timeline, which adds comments, commits, reviews and cross-references to the events. - get_event fetches one event by event_id. The flag keeps the extra methods out of the default issue_read schema. Responses are converted to MinimalIssueEvent and MinimalTimelineItem. The timeline of github#211 (71 entries) goes from 172KB raw to 27KB. Beyond the basic event fields, the minimal types keep: - The issue, as a MinimalIssueRef, on get_event. The caller passes only an event id, so this is the one place the response names the issue. - commit_repository on timeline entries, parsed from commit_url. Referenced and force-push entries often point at a commit in a fork or another repo, and the SHA alone does not say which. - The commit author and committer on committed entries, which have no actor or user. - The review's state, id, dismissal message and commit on review_dismissed events. Commit parents are dropped. Bodies, commit messages and the dismissal message use sanitize.Content. Titles use sanitize.PlainText. This matches get_comments and get. Without the flag, issue_read keeps its current schema (issue_read.snap is unchanged) and returns "unknown method" for the three new methods. With the flag, issue_number leaves the schema's required list because get_event does not take one. The handler still requires it for the other methods. In lockdown mode, get_events and get_timeline drop entries whose author lacks push access, and get_event returns an error, as issue_read:get does. commented and reviewed entries name their author in User instead of Actor, so both are checked. committed entries carry only a name and email, so lockdown drops them. 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> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 36e5c48 commit 409db99

11 files changed

Lines changed: 1466 additions & 14 deletions

‎README.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,7 @@ The behavior of lockdown mode depends on the tool invoked.
17011701
Following tools will return an error when the author lacks the push access:
17021702

17031703
- `issue_read:get`
1704+
- `issue_read:get_event`
17041705
- `pull_request_read:get`
17051706
- `pull_request_read:get_diff`
17061707
- `pull_request_read:get_files`
@@ -1710,6 +1711,8 @@ Following tools will filter out content from users lacking the push access:
17101711

17111712
- `issue_read:get_comments`
17121713
- `issue_read:get_sub_issues`
1714+
- `issue_read:get_events`
1715+
- `issue_read:get_timeline`
17131716
- `pull_request_read:get_comments`
17141717
- `pull_request_read:get_review_comments`
17151718
- `pull_request_read:get_reviews`

‎docs/feature-flags.md‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,28 @@ as output formatting) won't appear here.
406406
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
407407
- `repo`: The name of the repository (string, required)
408408

409+
### `issue_events`
410+
411+
- **issue_read** - Get issue details
412+
- **OAuth Challenge Scopes**: `repo`
413+
- `event_id`: The ID of the issue event. Required for, and only used by, the get_event method. (number, optional)
414+
- `issue_number`: The number of the issue. Required for every method except get_event. (number, optional)
415+
- `method`: The read operation to perform on a single issue.
416+
Options are:
417+
1. get - Get issue details. Also returns best-effort hierarchy flags (`has_parent`, `has_children`); `parent` and `sub_issues_summary` are optional relationship summaries, and `closed_by_pull_requests` summarizes the pull requests configured to close the issue as `total_count` plus up to 5 `references`.
418+
2. get_comments - Get issue comments.
419+
3. get_sub_issues - Get sub-issues (children) of the issue.
420+
4. get_parent - Get the parent issue, if this issue is a sub-issue of another.
421+
5. get_labels - Get labels assigned to the issue.
422+
6. get_events - Get the issue's event history: labeled, assigned, closed, renamed, referenced and so on.
423+
7. get_timeline - Get the issue's timeline. A superset of get_events that also includes comments, commits and reviews, so prefer it when you need the full narrative and get_events when you only need state changes.
424+
8. get_event - Get a single issue event by its `event_id`. Takes `event_id` instead of `issue_number`.
425+
(string, required)
426+
- `owner`: The owner of the repository (string, required)
427+
- `page`: Page number for pagination (min 1) (number, optional)
428+
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
429+
- `repo`: The name of the repository (string, required)
430+
409431
### `thread_resolution_reason`
410432

411433
- **pull_request_review_write** - Write operations (create, submit, delete) on pull request reviews
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"annotations": {
3+
"idempotentHint": false,
4+
"readOnlyHint": true,
5+
"title": "Get issue details"
6+
},
7+
"description": "Get information about a specific issue in a GitHub repository.",
8+
"inputSchema": {
9+
"properties": {
10+
"event_id": {
11+
"description": "The ID of the issue event. Required for, and only used by, the get_event method.",
12+
"type": "number"
13+
},
14+
"issue_number": {
15+
"description": "The number of the issue. Required for every method except get_event.",
16+
"type": "number"
17+
},
18+
"method": {
19+
"description": "The read operation to perform on a single issue.\nOptions are:\n1. get - Get issue details. Also returns best-effort hierarchy flags (`has_parent`, `has_children`); `parent` and `sub_issues_summary` are optional relationship summaries, and `closed_by_pull_requests` summarizes the pull requests configured to close the issue as `total_count` plus up to 5 `references`.\n2. get_comments - Get issue comments.\n3. get_sub_issues - Get sub-issues (children) of the issue.\n4. get_parent - Get the parent issue, if this issue is a sub-issue of another.\n5. get_labels - Get labels assigned to the issue.\n6. get_events - Get the issue's event history: labeled, assigned, closed, renamed, referenced and so on.\n7. get_timeline - Get the issue's timeline. A superset of get_events that also includes comments, commits and reviews, so prefer it when you need the full narrative and get_events when you only need state changes.\n8. get_event - Get a single issue event by its `event_id`. Takes `event_id` instead of `issue_number`.\n",
20+
"enum": [
21+
"get",
22+
"get_comments",
23+
"get_sub_issues",
24+
"get_parent",
25+
"get_labels",
26+
"get_events",
27+
"get_timeline",
28+
"get_event"
29+
],
30+
"type": "string"
31+
},
32+
"owner": {
33+
"description": "The owner of the repository",
34+
"type": "string"
35+
},
36+
"page": {
37+
"description": "Page number for pagination (min 1)",
38+
"minimum": 1,
39+
"type": "number"
40+
},
41+
"perPage": {
42+
"description": "Results per page for pagination (min 1, max 100)",
43+
"maximum": 100,
44+
"minimum": 1,
45+
"type": "number"
46+
},
47+
"repo": {
48+
"description": "The name of the repository",
49+
"type": "string"
50+
}
51+
},
52+
"required": [
53+
"method",
54+
"owner",
55+
"repo"
56+
],
57+
"type": "object"
58+
},
59+
"name": "issue_read"
60+
}

‎pkg/github/feature_flags.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ const FeatureFlagIssueDependencies = "issue_dependencies"
3535
// opt-in.
3636
const FeatureFlagDuplicateDetection = "duplicate_detection"
3737

38+
// FeatureFlagIssueEvents is the feature flag name for the issue event history
39+
// methods on issue_read (get_events, get_timeline, get_event) and their event_id
40+
// parameter. It is gated to keep them out of the default issue_read schema.
41+
const FeatureFlagIssueEvents = "issue_events"
42+
3843
// FeatureFlagThreadResolutionReason exposes resolution reasons for Copilot review threads.
3944
const FeatureFlagThreadResolutionReason = "thread_resolution_reason"
4045

@@ -52,6 +57,7 @@ var AllowedFeatureFlags = []string{
5257
FeatureFlagFileBlame,
5358
FeatureFlagIssueDependencies,
5459
FeatureFlagDuplicateDetection,
60+
FeatureFlagIssueEvents,
5561
FeatureFlagThreadResolutionReason,
5662
}
5763

‎pkg/github/helper_test.go‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ const (
6262
GetReposIssuesByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}"
6363
GetReposIssuesCommentByOwnerByRepoByCommentID = "GET /repos/{owner}/{repo}/issues/comments/{comment_id}"
6464
GetReposIssuesCommentsByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}/comments"
65+
GetReposIssuesEventsByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}/events"
66+
GetReposIssuesTimelineByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline"
67+
GetReposIssuesEventByOwnerByRepoByEventID = "GET /repos/{owner}/{repo}/issues/events/{event_id}"
6568
PostReposIssuesByOwnerByRepo = "POST /repos/{owner}/{repo}/issues"
6669
PostReposIssuesCommentsByOwnerByRepoByIssueNumber = "POST /repos/{owner}/{repo}/issues/{issue_number}/comments"
6770
PatchReposIssuesCommentByOwnerByRepoByCommentID = "PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"

0 commit comments

Comments
 (0)