@bretwardjames/ghp-core 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -199,6 +199,8 @@ __export(queries_exports, {
199
199
  PROJECT_FIELDS_QUERY: () => PROJECT_FIELDS_QUERY,
200
200
  PROJECT_ITEMS_QUERY: () => PROJECT_ITEMS_QUERY,
201
201
  PROJECT_VIEWS_QUERY: () => PROJECT_VIEWS_QUERY,
202
+ PR_AUTHORED_SEARCH_QUERY: () => PR_AUTHORED_SEARCH_QUERY,
203
+ PR_REVIEWS_SEARCH_QUERY: () => PR_REVIEWS_SEARCH_QUERY,
202
204
  RECENT_ISSUES_QUERY: () => RECENT_ISSUES_QUERY,
203
205
  REMOVE_BLOCKED_BY_MUTATION: () => REMOVE_BLOCKED_BY_MUTATION,
204
206
  REMOVE_LABELS_MUTATION: () => REMOVE_LABELS_MUTATION,
@@ -761,6 +763,39 @@ var ISSUE_TIMELINE_QUERY = `
761
763
  ... on Issue { number title }
762
764
  }
763
765
  }
766
+ ... on PullRequestReview {
767
+ author { login }
768
+ createdAt
769
+ state
770
+ }
771
+ ... on ReviewRequestedEvent {
772
+ actor { login }
773
+ createdAt
774
+ requestedReviewer {
775
+ ... on User { login }
776
+ }
777
+ }
778
+ }
779
+ }
780
+ }
781
+ }
782
+ }
783
+ }
784
+ `;
785
+ var PR_REVIEWS_SEARCH_QUERY = `
786
+ query($searchQuery: String!) {
787
+ search(query: $searchQuery, type: ISSUE, first: 50) {
788
+ nodes {
789
+ ... on PullRequest {
790
+ number
791
+ title
792
+ url
793
+ author { login }
794
+ reviews(first: 20) {
795
+ nodes {
796
+ author { login }
797
+ state
798
+ submittedAt
764
799
  }
765
800
  }
766
801
  }
@@ -768,6 +803,23 @@ var ISSUE_TIMELINE_QUERY = `
768
803
  }
769
804
  }
770
805
  `;
806
+ var PR_AUTHORED_SEARCH_QUERY = `
807
+ query($searchQuery: String!) {
808
+ search(query: $searchQuery, type: ISSUE, first: 50) {
809
+ nodes {
810
+ ... on PullRequest {
811
+ number
812
+ title
813
+ url
814
+ state
815
+ createdAt
816
+ mergedAt
817
+ mergedBy { login }
818
+ }
819
+ }
820
+ }
821
+ }
822
+ `;
771
823
  var ISSUE_RELATIONSHIPS_QUERY = `
772
824
  query($owner: String!, $name: String!, $number: Int!) {
773
825
  repository(owner: $owner, name: $name) {
@@ -1848,9 +1900,11 @@ var GitHubAPI = class {
1848
1900
  }
1849
1901
  /**
1850
1902
  * Get recent activity across all project items since a given time.
1851
- * Uses a two-pass approach for efficiency:
1903
+ * Multi-pass approach:
1852
1904
  * Pass 1: Fetch all project items, filter by updatedAt client-side
1853
1905
  * Pass 2: Fetch timeline events only for items that changed
1906
+ * Pass 3: Search for PRs reviewed by user (not captured in project items)
1907
+ * Pass 4: Search for PRs authored by user (created/merged)
1854
1908
  */
1855
1909
  async getRecentActivity(repo, since, options) {
1856
1910
  if (!this.graphqlWithAuth) throw new Error("Not authenticated");
@@ -1863,6 +1917,7 @@ var GitHubAPI = class {
1863
1917
  }
1864
1918
  const sinceMs = since.getTime();
1865
1919
  const sinceISO = since.toISOString();
1920
+ const sinceDate = sinceISO.split("T")[0];
1866
1921
  let recentItems = allItems.filter(
1867
1922
  (item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
1868
1923
  );
@@ -1912,6 +1967,33 @@ var GitHubAPI = class {
1912
1967
  }
1913
1968
  }
1914
1969
  }
1970
+ const activityNumbers = new Set(activities.map((a) => a.issue.number));
1971
+ if (this.username) {
1972
+ const reviewActivities = await this.fetchReviewedPRs(
1973
+ repo,
1974
+ this.username,
1975
+ sinceDate,
1976
+ sinceMs,
1977
+ activityNumbers
1978
+ );
1979
+ for (const a of reviewActivities) {
1980
+ activityNumbers.add(a.issue.number);
1981
+ activities.push(a);
1982
+ }
1983
+ }
1984
+ if (this.username) {
1985
+ const authoredActivities = await this.fetchAuthoredPRs(
1986
+ repo,
1987
+ this.username,
1988
+ sinceDate,
1989
+ sinceMs,
1990
+ activityNumbers
1991
+ );
1992
+ for (const a of authoredActivities) {
1993
+ activityNumbers.add(a.issue.number);
1994
+ activities.push(a);
1995
+ }
1996
+ }
1915
1997
  activities.sort((a, b) => {
1916
1998
  const aLatest = a.changes[a.changes.length - 1]?.timestamp || "";
1917
1999
  const bLatest = b.changes[b.changes.length - 1]?.timestamp || "";
@@ -1919,6 +2001,78 @@ var GitHubAPI = class {
1919
2001
  });
1920
2002
  return activities;
1921
2003
  }
2004
+ /**
2005
+ * Search for PRs the user reviewed that aren't already in the activity list.
2006
+ */
2007
+ async fetchReviewedPRs(repo, username, sinceDate, sinceMs, seen) {
2008
+ const searchQuery = `repo:${repo.owner}/${repo.name} reviewed-by:${username} updated:>=${sinceDate} is:pr`;
2009
+ const response = await this.graphqlWithRetry(
2010
+ PR_REVIEWS_SEARCH_QUERY,
2011
+ { searchQuery }
2012
+ );
2013
+ const activities = [];
2014
+ for (const pr of response.search.nodes) {
2015
+ if (seen.has(pr.number)) continue;
2016
+ const recentReviews = pr.reviews.nodes.filter(
2017
+ (r) => r.author?.login === username && new Date(r.submittedAt).getTime() >= sinceMs
2018
+ );
2019
+ if (recentReviews.length === 0) continue;
2020
+ const events = recentReviews.map((r) => {
2021
+ const stateLabel = r.state === "APPROVED" ? "Approved" : r.state === "CHANGES_REQUESTED" ? "Changes requested" : r.state === "COMMENTED" ? "Review comment" : r.state === "DISMISSED" ? "Review dismissed" : r.state;
2022
+ return {
2023
+ type: "review_submitted",
2024
+ actor: username,
2025
+ timestamp: r.submittedAt,
2026
+ details: stateLabel
2027
+ };
2028
+ });
2029
+ activities.push({
2030
+ issue: { number: pr.number, title: pr.title, url: pr.url },
2031
+ status: null,
2032
+ assignees: [],
2033
+ changes: events
2034
+ });
2035
+ }
2036
+ return activities;
2037
+ }
2038
+ /**
2039
+ * Search for PRs the user authored that aren't already in the activity list.
2040
+ * Captures PR creation and merges.
2041
+ */
2042
+ async fetchAuthoredPRs(repo, username, sinceDate, sinceMs, seen) {
2043
+ const searchQuery = `repo:${repo.owner}/${repo.name} author:${username} created:>=${sinceDate} is:pr`;
2044
+ const response = await this.graphqlWithRetry(
2045
+ PR_AUTHORED_SEARCH_QUERY,
2046
+ { searchQuery }
2047
+ );
2048
+ const activities = [];
2049
+ for (const pr of response.search.nodes) {
2050
+ if (seen.has(pr.number)) continue;
2051
+ const events = [];
2052
+ if (new Date(pr.createdAt).getTime() >= sinceMs) {
2053
+ events.push({
2054
+ type: "pr_created",
2055
+ actor: username,
2056
+ timestamp: pr.createdAt
2057
+ });
2058
+ }
2059
+ if (pr.mergedAt && new Date(pr.mergedAt).getTime() >= sinceMs) {
2060
+ events.push({
2061
+ type: "pr_merged",
2062
+ actor: pr.mergedBy?.login || username,
2063
+ timestamp: pr.mergedAt
2064
+ });
2065
+ }
2066
+ if (events.length === 0) continue;
2067
+ activities.push({
2068
+ issue: { number: pr.number, title: pr.title, url: pr.url },
2069
+ status: pr.state === "MERGED" ? "Merged" : pr.state === "OPEN" ? "Open" : "Closed",
2070
+ assignees: [username],
2071
+ changes: events
2072
+ });
2073
+ }
2074
+ return activities;
2075
+ }
1922
2076
  /**
1923
2077
  * Fetch and normalize timeline events for a single issue/PR
1924
2078
  */
@@ -1994,6 +2148,25 @@ var GitHubAPI = class {
1994
2148
  }
1995
2149
  break;
1996
2150
  }
2151
+ case "PullRequestReview": {
2152
+ const stateLabel = node.state === "APPROVED" ? "Approved" : node.state === "CHANGES_REQUESTED" ? "Changes requested" : node.state === "COMMENTED" ? "Review comment" : node.state === "DISMISSED" ? "Review dismissed" : node.state || "Reviewed";
2153
+ events.push({
2154
+ type: "review_submitted",
2155
+ actor,
2156
+ timestamp,
2157
+ details: stateLabel
2158
+ });
2159
+ break;
2160
+ }
2161
+ case "ReviewRequestedEvent": {
2162
+ events.push({
2163
+ type: "review_requested",
2164
+ actor,
2165
+ timestamp,
2166
+ details: node.requestedReviewer?.login
2167
+ });
2168
+ break;
2169
+ }
1997
2170
  }
1998
2171
  }
1999
2172
  return events;
@@ -4135,6 +4308,14 @@ function formatEventLine(event) {
4135
4308
  return `${arrow} Reopened by ${actor} (${timestamp})`;
4136
4309
  case "referenced":
4137
4310
  return `${arrow} ${event.details} linked by ${actor} (${timestamp})`;
4311
+ case "review_submitted":
4312
+ return `${arrow} ${event.details} by ${actor} (${timestamp})`;
4313
+ case "review_requested":
4314
+ return `${arrow} Review requested from ${event.details || "team"} by ${actor} (${timestamp})`;
4315
+ case "pr_created":
4316
+ return `${arrow} PR created by ${actor} (${timestamp})`;
4317
+ case "pr_merged":
4318
+ return `${arrow} PR merged by ${actor} (${timestamp})`;
4138
4319
  default:
4139
4320
  return `${arrow} ${event.type} by ${actor} (${timestamp})`;
4140
4321
  }
package/dist/index.d.cts CHANGED
@@ -442,7 +442,7 @@ interface IssueActivity {
442
442
  * A single activity event on an issue
443
443
  */
444
444
  interface ActivityEvent {
445
- type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced';
445
+ type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced' | 'review_submitted' | 'review_requested' | 'pr_created' | 'pr_merged';
446
446
  actor: string;
447
447
  timestamp: string;
448
448
  details?: string;
@@ -683,13 +683,24 @@ declare class GitHubAPI {
683
683
  getIssueRelationships(repo: RepoInfo, issueNumber: number): Promise<IssueRelationships | null>;
684
684
  /**
685
685
  * Get recent activity across all project items since a given time.
686
- * Uses a two-pass approach for efficiency:
686
+ * Multi-pass approach:
687
687
  * Pass 1: Fetch all project items, filter by updatedAt client-side
688
688
  * Pass 2: Fetch timeline events only for items that changed
689
+ * Pass 3: Search for PRs reviewed by user (not captured in project items)
690
+ * Pass 4: Search for PRs authored by user (created/merged)
689
691
  */
690
692
  getRecentActivity(repo: RepoInfo, since: Date, options?: {
691
693
  mine?: boolean;
692
694
  }): Promise<IssueActivity[]>;
695
+ /**
696
+ * Search for PRs the user reviewed that aren't already in the activity list.
697
+ */
698
+ private fetchReviewedPRs;
699
+ /**
700
+ * Search for PRs the user authored that aren't already in the activity list.
701
+ * Captures PR creation and merges.
702
+ */
703
+ private fetchAuthoredPRs;
693
704
  /**
694
705
  * Fetch and normalize timeline events for a single issue/PR
695
706
  */
@@ -1255,7 +1266,15 @@ declare const ISSUE_WITH_PROJECT_ITEMS_QUERY = "\n query($owner: String!, $na
1255
1266
  * Query to get timeline events for an issue since a given time.
1256
1267
  * Used by the standup command to fetch specific activity details.
1257
1268
  */
1258
- declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n }\n }\n }\n";
1269
+ declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n ... on PullRequestReview {\n author { login }\n createdAt\n state\n }\n ... on ReviewRequestedEvent {\n actor { login }\n createdAt\n requestedReviewer {\n ... on User { login }\n }\n }\n }\n }\n }\n }\n }\n }\n";
1270
+ /**
1271
+ * Search for PRs reviewed by a user in a given repo since a date.
1272
+ */
1273
+ declare const PR_REVIEWS_SEARCH_QUERY = "\n query($searchQuery: String!) {\n search(query: $searchQuery, type: ISSUE, first: 50) {\n nodes {\n ... on PullRequest {\n number\n title\n url\n author { login }\n reviews(first: 20) {\n nodes {\n author { login }\n state\n submittedAt\n }\n }\n }\n }\n }\n }\n";
1274
+ /**
1275
+ * Search for PRs authored by a user in a given repo since a date.
1276
+ */
1277
+ declare const PR_AUTHORED_SEARCH_QUERY = "\n query($searchQuery: String!) {\n search(query: $searchQuery, type: ISSUE, first: 50) {\n nodes {\n ... on PullRequest {\n number\n title\n url\n state\n createdAt\n mergedAt\n mergedBy { login }\n }\n }\n }\n }\n";
1259
1278
  /**
1260
1279
  * Query to get issue relationships (parent and sub-issues)
1261
1280
  */
@@ -1281,6 +1300,8 @@ declare const queries_LABEL_EXISTS_QUERY: typeof LABEL_EXISTS_QUERY;
1281
1300
  declare const queries_PROJECT_FIELDS_QUERY: typeof PROJECT_FIELDS_QUERY;
1282
1301
  declare const queries_PROJECT_ITEMS_QUERY: typeof PROJECT_ITEMS_QUERY;
1283
1302
  declare const queries_PROJECT_VIEWS_QUERY: typeof PROJECT_VIEWS_QUERY;
1303
+ declare const queries_PR_AUTHORED_SEARCH_QUERY: typeof PR_AUTHORED_SEARCH_QUERY;
1304
+ declare const queries_PR_REVIEWS_SEARCH_QUERY: typeof PR_REVIEWS_SEARCH_QUERY;
1284
1305
  declare const queries_RECENT_ISSUES_QUERY: typeof RECENT_ISSUES_QUERY;
1285
1306
  declare const queries_REMOVE_BLOCKED_BY_MUTATION: typeof REMOVE_BLOCKED_BY_MUTATION;
1286
1307
  declare const queries_REMOVE_LABELS_MUTATION: typeof REMOVE_LABELS_MUTATION;
@@ -1294,7 +1315,7 @@ declare const queries_UPDATE_ITEM_FIELD_MUTATION: typeof UPDATE_ITEM_FIELD_MUTAT
1294
1315
  declare const queries_UPDATE_ITEM_STATUS_MUTATION: typeof UPDATE_ITEM_STATUS_MUTATION;
1295
1316
  declare const queries_VIEWER_QUERY: typeof VIEWER_QUERY;
1296
1317
  declare namespace queries {
1297
- export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
1318
+ export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_PR_AUTHORED_SEARCH_QUERY as PR_AUTHORED_SEARCH_QUERY, queries_PR_REVIEWS_SEARCH_QUERY as PR_REVIEWS_SEARCH_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
1298
1319
  }
1299
1320
 
1300
1321
  /**
package/dist/index.d.ts CHANGED
@@ -442,7 +442,7 @@ interface IssueActivity {
442
442
  * A single activity event on an issue
443
443
  */
444
444
  interface ActivityEvent {
445
- type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced';
445
+ type: 'comment' | 'assigned' | 'unassigned' | 'labeled' | 'unlabeled' | 'closed' | 'reopened' | 'referenced' | 'review_submitted' | 'review_requested' | 'pr_created' | 'pr_merged';
446
446
  actor: string;
447
447
  timestamp: string;
448
448
  details?: string;
@@ -683,13 +683,24 @@ declare class GitHubAPI {
683
683
  getIssueRelationships(repo: RepoInfo, issueNumber: number): Promise<IssueRelationships | null>;
684
684
  /**
685
685
  * Get recent activity across all project items since a given time.
686
- * Uses a two-pass approach for efficiency:
686
+ * Multi-pass approach:
687
687
  * Pass 1: Fetch all project items, filter by updatedAt client-side
688
688
  * Pass 2: Fetch timeline events only for items that changed
689
+ * Pass 3: Search for PRs reviewed by user (not captured in project items)
690
+ * Pass 4: Search for PRs authored by user (created/merged)
689
691
  */
690
692
  getRecentActivity(repo: RepoInfo, since: Date, options?: {
691
693
  mine?: boolean;
692
694
  }): Promise<IssueActivity[]>;
695
+ /**
696
+ * Search for PRs the user reviewed that aren't already in the activity list.
697
+ */
698
+ private fetchReviewedPRs;
699
+ /**
700
+ * Search for PRs the user authored that aren't already in the activity list.
701
+ * Captures PR creation and merges.
702
+ */
703
+ private fetchAuthoredPRs;
693
704
  /**
694
705
  * Fetch and normalize timeline events for a single issue/PR
695
706
  */
@@ -1255,7 +1266,15 @@ declare const ISSUE_WITH_PROJECT_ITEMS_QUERY = "\n query($owner: String!, $na
1255
1266
  * Query to get timeline events for an issue since a given time.
1256
1267
  * Used by the standup command to fetch specific activity details.
1257
1268
  */
1258
- declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n }\n }\n }\n";
1269
+ declare const ISSUE_TIMELINE_QUERY = "\n query($owner: String!, $name: String!, $number: Int!, $since: DateTime!) {\n repository(owner: $owner, name: $name) {\n issueOrPullRequest(number: $number) {\n ... on Issue {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n }\n }\n }\n ... on PullRequest {\n timelineItems(first: 100, since: $since) {\n nodes {\n __typename\n ... on IssueComment {\n author { login }\n createdAt\n body\n }\n ... on LabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on UnlabeledEvent {\n actor { login }\n createdAt\n label { name }\n }\n ... on AssignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on UnassignedEvent {\n actor { login }\n createdAt\n assignee { ... on User { login } }\n }\n ... on ClosedEvent {\n actor { login }\n createdAt\n }\n ... on ReopenedEvent {\n actor { login }\n createdAt\n }\n ... on CrossReferencedEvent {\n actor { login }\n createdAt\n source {\n __typename\n ... on PullRequest { number title url }\n ... on Issue { number title }\n }\n }\n ... on PullRequestReview {\n author { login }\n createdAt\n state\n }\n ... on ReviewRequestedEvent {\n actor { login }\n createdAt\n requestedReviewer {\n ... on User { login }\n }\n }\n }\n }\n }\n }\n }\n }\n";
1270
+ /**
1271
+ * Search for PRs reviewed by a user in a given repo since a date.
1272
+ */
1273
+ declare const PR_REVIEWS_SEARCH_QUERY = "\n query($searchQuery: String!) {\n search(query: $searchQuery, type: ISSUE, first: 50) {\n nodes {\n ... on PullRequest {\n number\n title\n url\n author { login }\n reviews(first: 20) {\n nodes {\n author { login }\n state\n submittedAt\n }\n }\n }\n }\n }\n }\n";
1274
+ /**
1275
+ * Search for PRs authored by a user in a given repo since a date.
1276
+ */
1277
+ declare const PR_AUTHORED_SEARCH_QUERY = "\n query($searchQuery: String!) {\n search(query: $searchQuery, type: ISSUE, first: 50) {\n nodes {\n ... on PullRequest {\n number\n title\n url\n state\n createdAt\n mergedAt\n mergedBy { login }\n }\n }\n }\n }\n";
1259
1278
  /**
1260
1279
  * Query to get issue relationships (parent and sub-issues)
1261
1280
  */
@@ -1281,6 +1300,8 @@ declare const queries_LABEL_EXISTS_QUERY: typeof LABEL_EXISTS_QUERY;
1281
1300
  declare const queries_PROJECT_FIELDS_QUERY: typeof PROJECT_FIELDS_QUERY;
1282
1301
  declare const queries_PROJECT_ITEMS_QUERY: typeof PROJECT_ITEMS_QUERY;
1283
1302
  declare const queries_PROJECT_VIEWS_QUERY: typeof PROJECT_VIEWS_QUERY;
1303
+ declare const queries_PR_AUTHORED_SEARCH_QUERY: typeof PR_AUTHORED_SEARCH_QUERY;
1304
+ declare const queries_PR_REVIEWS_SEARCH_QUERY: typeof PR_REVIEWS_SEARCH_QUERY;
1284
1305
  declare const queries_RECENT_ISSUES_QUERY: typeof RECENT_ISSUES_QUERY;
1285
1306
  declare const queries_REMOVE_BLOCKED_BY_MUTATION: typeof REMOVE_BLOCKED_BY_MUTATION;
1286
1307
  declare const queries_REMOVE_LABELS_MUTATION: typeof REMOVE_LABELS_MUTATION;
@@ -1294,7 +1315,7 @@ declare const queries_UPDATE_ITEM_FIELD_MUTATION: typeof UPDATE_ITEM_FIELD_MUTAT
1294
1315
  declare const queries_UPDATE_ITEM_STATUS_MUTATION: typeof UPDATE_ITEM_STATUS_MUTATION;
1295
1316
  declare const queries_VIEWER_QUERY: typeof VIEWER_QUERY;
1296
1317
  declare namespace queries {
1297
- export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
1318
+ export { queries_ADD_BLOCKED_BY_MUTATION as ADD_BLOCKED_BY_MUTATION, queries_ADD_COMMENT_MUTATION as ADD_COMMENT_MUTATION, queries_ADD_LABELS_MUTATION as ADD_LABELS_MUTATION, queries_ADD_SUB_ISSUE_MUTATION as ADD_SUB_ISSUE_MUTATION, queries_ADD_TO_PROJECT_MUTATION as ADD_TO_PROJECT_MUTATION, queries_COLLABORATORS_QUERY as COLLABORATORS_QUERY, queries_CREATE_ISSUE_MUTATION as CREATE_ISSUE_MUTATION, queries_ISSUES_WITH_LABEL_QUERY as ISSUES_WITH_LABEL_QUERY, queries_ISSUE_AND_LABEL_QUERY as ISSUE_AND_LABEL_QUERY, queries_ISSUE_DETAILS_QUERY as ISSUE_DETAILS_QUERY, queries_ISSUE_FOR_UPDATE_QUERY as ISSUE_FOR_UPDATE_QUERY, queries_ISSUE_NODE_ID_QUERY as ISSUE_NODE_ID_QUERY, queries_ISSUE_RELATIONSHIPS_QUERY as ISSUE_RELATIONSHIPS_QUERY, queries_ISSUE_TIMELINE_QUERY as ISSUE_TIMELINE_QUERY, queries_ISSUE_TYPES_QUERY as ISSUE_TYPES_QUERY, queries_ISSUE_WITH_PROJECT_ITEMS_QUERY as ISSUE_WITH_PROJECT_ITEMS_QUERY, queries_LABEL_EXISTS_QUERY as LABEL_EXISTS_QUERY, queries_PROJECT_FIELDS_QUERY as PROJECT_FIELDS_QUERY, queries_PROJECT_ITEMS_QUERY as PROJECT_ITEMS_QUERY, queries_PROJECT_VIEWS_QUERY as PROJECT_VIEWS_QUERY, queries_PR_AUTHORED_SEARCH_QUERY as PR_AUTHORED_SEARCH_QUERY, queries_PR_REVIEWS_SEARCH_QUERY as PR_REVIEWS_SEARCH_QUERY, queries_RECENT_ISSUES_QUERY as RECENT_ISSUES_QUERY, queries_REMOVE_BLOCKED_BY_MUTATION as REMOVE_BLOCKED_BY_MUTATION, queries_REMOVE_LABELS_MUTATION as REMOVE_LABELS_MUTATION, queries_REMOVE_SUB_ISSUE_MUTATION as REMOVE_SUB_ISSUE_MUTATION, queries_REPOSITORY_ID_QUERY as REPOSITORY_ID_QUERY, queries_REPOSITORY_PROJECTS_QUERY as REPOSITORY_PROJECTS_QUERY, queries_UPDATE_ISSUE_BODY_MUTATION as UPDATE_ISSUE_BODY_MUTATION, queries_UPDATE_ISSUE_MUTATION as UPDATE_ISSUE_MUTATION, queries_UPDATE_ISSUE_TYPE_MUTATION as UPDATE_ISSUE_TYPE_MUTATION, queries_UPDATE_ITEM_FIELD_MUTATION as UPDATE_ITEM_FIELD_MUTATION, queries_UPDATE_ITEM_STATUS_MUTATION as UPDATE_ITEM_STATUS_MUTATION, queries_VIEWER_QUERY as VIEWER_QUERY };
1298
1319
  }
1299
1320
 
1300
1321
  /**
package/dist/index.js CHANGED
@@ -30,6 +30,8 @@ __export(queries_exports, {
30
30
  PROJECT_FIELDS_QUERY: () => PROJECT_FIELDS_QUERY,
31
31
  PROJECT_ITEMS_QUERY: () => PROJECT_ITEMS_QUERY,
32
32
  PROJECT_VIEWS_QUERY: () => PROJECT_VIEWS_QUERY,
33
+ PR_AUTHORED_SEARCH_QUERY: () => PR_AUTHORED_SEARCH_QUERY,
34
+ PR_REVIEWS_SEARCH_QUERY: () => PR_REVIEWS_SEARCH_QUERY,
33
35
  RECENT_ISSUES_QUERY: () => RECENT_ISSUES_QUERY,
34
36
  REMOVE_BLOCKED_BY_MUTATION: () => REMOVE_BLOCKED_BY_MUTATION,
35
37
  REMOVE_LABELS_MUTATION: () => REMOVE_LABELS_MUTATION,
@@ -592,6 +594,39 @@ var ISSUE_TIMELINE_QUERY = `
592
594
  ... on Issue { number title }
593
595
  }
594
596
  }
597
+ ... on PullRequestReview {
598
+ author { login }
599
+ createdAt
600
+ state
601
+ }
602
+ ... on ReviewRequestedEvent {
603
+ actor { login }
604
+ createdAt
605
+ requestedReviewer {
606
+ ... on User { login }
607
+ }
608
+ }
609
+ }
610
+ }
611
+ }
612
+ }
613
+ }
614
+ }
615
+ `;
616
+ var PR_REVIEWS_SEARCH_QUERY = `
617
+ query($searchQuery: String!) {
618
+ search(query: $searchQuery, type: ISSUE, first: 50) {
619
+ nodes {
620
+ ... on PullRequest {
621
+ number
622
+ title
623
+ url
624
+ author { login }
625
+ reviews(first: 20) {
626
+ nodes {
627
+ author { login }
628
+ state
629
+ submittedAt
595
630
  }
596
631
  }
597
632
  }
@@ -599,6 +634,23 @@ var ISSUE_TIMELINE_QUERY = `
599
634
  }
600
635
  }
601
636
  `;
637
+ var PR_AUTHORED_SEARCH_QUERY = `
638
+ query($searchQuery: String!) {
639
+ search(query: $searchQuery, type: ISSUE, first: 50) {
640
+ nodes {
641
+ ... on PullRequest {
642
+ number
643
+ title
644
+ url
645
+ state
646
+ createdAt
647
+ mergedAt
648
+ mergedBy { login }
649
+ }
650
+ }
651
+ }
652
+ }
653
+ `;
602
654
  var ISSUE_RELATIONSHIPS_QUERY = `
603
655
  query($owner: String!, $name: String!, $number: Int!) {
604
656
  repository(owner: $owner, name: $name) {
@@ -1679,9 +1731,11 @@ var GitHubAPI = class {
1679
1731
  }
1680
1732
  /**
1681
1733
  * Get recent activity across all project items since a given time.
1682
- * Uses a two-pass approach for efficiency:
1734
+ * Multi-pass approach:
1683
1735
  * Pass 1: Fetch all project items, filter by updatedAt client-side
1684
1736
  * Pass 2: Fetch timeline events only for items that changed
1737
+ * Pass 3: Search for PRs reviewed by user (not captured in project items)
1738
+ * Pass 4: Search for PRs authored by user (created/merged)
1685
1739
  */
1686
1740
  async getRecentActivity(repo, since, options) {
1687
1741
  if (!this.graphqlWithAuth) throw new Error("Not authenticated");
@@ -1694,6 +1748,7 @@ var GitHubAPI = class {
1694
1748
  }
1695
1749
  const sinceMs = since.getTime();
1696
1750
  const sinceISO = since.toISOString();
1751
+ const sinceDate = sinceISO.split("T")[0];
1697
1752
  let recentItems = allItems.filter(
1698
1753
  (item) => item.updatedAt && new Date(item.updatedAt).getTime() >= sinceMs
1699
1754
  );
@@ -1743,6 +1798,33 @@ var GitHubAPI = class {
1743
1798
  }
1744
1799
  }
1745
1800
  }
1801
+ const activityNumbers = new Set(activities.map((a) => a.issue.number));
1802
+ if (this.username) {
1803
+ const reviewActivities = await this.fetchReviewedPRs(
1804
+ repo,
1805
+ this.username,
1806
+ sinceDate,
1807
+ sinceMs,
1808
+ activityNumbers
1809
+ );
1810
+ for (const a of reviewActivities) {
1811
+ activityNumbers.add(a.issue.number);
1812
+ activities.push(a);
1813
+ }
1814
+ }
1815
+ if (this.username) {
1816
+ const authoredActivities = await this.fetchAuthoredPRs(
1817
+ repo,
1818
+ this.username,
1819
+ sinceDate,
1820
+ sinceMs,
1821
+ activityNumbers
1822
+ );
1823
+ for (const a of authoredActivities) {
1824
+ activityNumbers.add(a.issue.number);
1825
+ activities.push(a);
1826
+ }
1827
+ }
1746
1828
  activities.sort((a, b) => {
1747
1829
  const aLatest = a.changes[a.changes.length - 1]?.timestamp || "";
1748
1830
  const bLatest = b.changes[b.changes.length - 1]?.timestamp || "";
@@ -1750,6 +1832,78 @@ var GitHubAPI = class {
1750
1832
  });
1751
1833
  return activities;
1752
1834
  }
1835
+ /**
1836
+ * Search for PRs the user reviewed that aren't already in the activity list.
1837
+ */
1838
+ async fetchReviewedPRs(repo, username, sinceDate, sinceMs, seen) {
1839
+ const searchQuery = `repo:${repo.owner}/${repo.name} reviewed-by:${username} updated:>=${sinceDate} is:pr`;
1840
+ const response = await this.graphqlWithRetry(
1841
+ PR_REVIEWS_SEARCH_QUERY,
1842
+ { searchQuery }
1843
+ );
1844
+ const activities = [];
1845
+ for (const pr of response.search.nodes) {
1846
+ if (seen.has(pr.number)) continue;
1847
+ const recentReviews = pr.reviews.nodes.filter(
1848
+ (r) => r.author?.login === username && new Date(r.submittedAt).getTime() >= sinceMs
1849
+ );
1850
+ if (recentReviews.length === 0) continue;
1851
+ const events = recentReviews.map((r) => {
1852
+ const stateLabel = r.state === "APPROVED" ? "Approved" : r.state === "CHANGES_REQUESTED" ? "Changes requested" : r.state === "COMMENTED" ? "Review comment" : r.state === "DISMISSED" ? "Review dismissed" : r.state;
1853
+ return {
1854
+ type: "review_submitted",
1855
+ actor: username,
1856
+ timestamp: r.submittedAt,
1857
+ details: stateLabel
1858
+ };
1859
+ });
1860
+ activities.push({
1861
+ issue: { number: pr.number, title: pr.title, url: pr.url },
1862
+ status: null,
1863
+ assignees: [],
1864
+ changes: events
1865
+ });
1866
+ }
1867
+ return activities;
1868
+ }
1869
+ /**
1870
+ * Search for PRs the user authored that aren't already in the activity list.
1871
+ * Captures PR creation and merges.
1872
+ */
1873
+ async fetchAuthoredPRs(repo, username, sinceDate, sinceMs, seen) {
1874
+ const searchQuery = `repo:${repo.owner}/${repo.name} author:${username} created:>=${sinceDate} is:pr`;
1875
+ const response = await this.graphqlWithRetry(
1876
+ PR_AUTHORED_SEARCH_QUERY,
1877
+ { searchQuery }
1878
+ );
1879
+ const activities = [];
1880
+ for (const pr of response.search.nodes) {
1881
+ if (seen.has(pr.number)) continue;
1882
+ const events = [];
1883
+ if (new Date(pr.createdAt).getTime() >= sinceMs) {
1884
+ events.push({
1885
+ type: "pr_created",
1886
+ actor: username,
1887
+ timestamp: pr.createdAt
1888
+ });
1889
+ }
1890
+ if (pr.mergedAt && new Date(pr.mergedAt).getTime() >= sinceMs) {
1891
+ events.push({
1892
+ type: "pr_merged",
1893
+ actor: pr.mergedBy?.login || username,
1894
+ timestamp: pr.mergedAt
1895
+ });
1896
+ }
1897
+ if (events.length === 0) continue;
1898
+ activities.push({
1899
+ issue: { number: pr.number, title: pr.title, url: pr.url },
1900
+ status: pr.state === "MERGED" ? "Merged" : pr.state === "OPEN" ? "Open" : "Closed",
1901
+ assignees: [username],
1902
+ changes: events
1903
+ });
1904
+ }
1905
+ return activities;
1906
+ }
1753
1907
  /**
1754
1908
  * Fetch and normalize timeline events for a single issue/PR
1755
1909
  */
@@ -1825,6 +1979,25 @@ var GitHubAPI = class {
1825
1979
  }
1826
1980
  break;
1827
1981
  }
1982
+ case "PullRequestReview": {
1983
+ const stateLabel = node.state === "APPROVED" ? "Approved" : node.state === "CHANGES_REQUESTED" ? "Changes requested" : node.state === "COMMENTED" ? "Review comment" : node.state === "DISMISSED" ? "Review dismissed" : node.state || "Reviewed";
1984
+ events.push({
1985
+ type: "review_submitted",
1986
+ actor,
1987
+ timestamp,
1988
+ details: stateLabel
1989
+ });
1990
+ break;
1991
+ }
1992
+ case "ReviewRequestedEvent": {
1993
+ events.push({
1994
+ type: "review_requested",
1995
+ actor,
1996
+ timestamp,
1997
+ details: node.requestedReviewer?.login
1998
+ });
1999
+ break;
2000
+ }
1828
2001
  }
1829
2002
  }
1830
2003
  return events;
@@ -3966,6 +4139,14 @@ function formatEventLine(event) {
3966
4139
  return `${arrow} Reopened by ${actor} (${timestamp})`;
3967
4140
  case "referenced":
3968
4141
  return `${arrow} ${event.details} linked by ${actor} (${timestamp})`;
4142
+ case "review_submitted":
4143
+ return `${arrow} ${event.details} by ${actor} (${timestamp})`;
4144
+ case "review_requested":
4145
+ return `${arrow} Review requested from ${event.details || "team"} by ${actor} (${timestamp})`;
4146
+ case "pr_created":
4147
+ return `${arrow} PR created by ${actor} (${timestamp})`;
4148
+ case "pr_merged":
4149
+ return `${arrow} PR merged by ${actor} (${timestamp})`;
3969
4150
  default:
3970
4151
  return `${arrow} ${event.type} by ${actor} (${timestamp})`;
3971
4152
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bretwardjames/ghp-core",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Shared core library for GitHub Projects tools",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",