Daily Activity: automated end-of-day GitHub + Slack summary log#28
Open
therzka wants to merge 25 commits into
Open
Daily Activity: automated end-of-day GitHub + Slack summary log#28therzka wants to merge 25 commits into
therzka wants to merge 25 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prevents a fully-failed org from being masked by another org's empty-success result, which would clobber a good log block. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…k the daily log Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…PI route; cap hourly retries The API route's in-flight guard was module-local and never actually shared with the scheduler, so a scheduled run and a manual trigger for the same date could still race and clobber each other's write. Move the guard (keyed by date) into generateDailyActivity() itself so every caller coalesces on it. Also cap the scheduler's retry-on-failure to 3 attempts per day so a persistent failure doesn't re-run the Slack call and git commit every hour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A single-slot guard could be overwritten by a concurrent call for a different date, causing it to stop protecting the original date's still-running generation. A small Map keyed by date fixes this while staying simple. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The daily-activity API call can take up to ~5 minutes. If the user navigates to a different day while it's in flight, the server has already written the correct day's log; skip the client-side merge/save if currentDate no longer matches the date the request was made for, so we never write mixed-day content back to disk. Also clear any pending debounced autosave before the merge-save so a stale autosave can't land afterward and overwrite the merged content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…alue The prior fix compared currentDate against itself within the same async closure (always false — currentDate is a plain const frozen at click time, so the guard never fired). Track the live date in a ref, updated via effect, and compare against that instead so mid-request navigation is actually detected. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The copilot-slack-mcp plugin approach was unreliable: the SDK session sometimes lacked slack_* tools entirely, and even when nominally available, the model failed to find real public Slack activity that existed on the test day (#world-cup-2026 messages were missed). Replace the LLM-driven search with a deterministic call to `gh slack api get search.messages -f query="from:me on:<date>"`, filtered client-side to public channels and to messages whose timestamp genuinely falls on the target date (America/Los_Angeles). The AI model is now only used to summarize the already-gathered facts per channel, not to search for them, which is both faster and far more accurate. Also: - Show each commit's message as a sub-bullet in the GitHub section (previously only the SHA link was shown, grouped per repo) - Fix missing blank line after the "_Summary_" heading - Add SLACK_TEAM env var (falls back to first GITHUB_ORG entry) and update README prerequisites/env docs to describe the gh-slack setup instead of the abandoned copilot-slack-mcp plugin Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mirrors the logging already done in the catch block for install/exec failures, so a mis-scoped token or expired auth is distinguishable from genuinely having no Slack activity that day. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ity key Final full-branch review caught two issues: Critical: GitHub's search date qualifiers (created:, author-date:) are always interpreted in UTC, but the app's "date" is always a PT calendar day. Passing the bare PT date string into these UTC-interpreted qualifiers silently misattributed GitHub activity created roughly 4-8pm PT onward to the wrong day - exactly the window most likely to contain real work by the time the evening auto-trigger runs. Fixed by computing the explicit UTC instant range for the PT calendar day (handling both PST/PDT offsets) and using GitHub's range query syntax (created:start..end) instead. Also fixed the same bug in fetchAgentActivity's date comparison, which naively sliced a UTC ISO timestamp instead of converting it to the PT calendar date. Minor: DAILY_ACTIVITY_KEY was duplicated as two independent string literals (client and server) to avoid pulling server-only deps into the client bundle. Moved it into the existing shared, dependency-free constants.ts module instead, so both sides can never drift out of sync on the managed-block marker. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per user feedback: the per-channel Slack summary now has a blank line between each channel's entry for readability, and each entry links back to that channel's first matching message so you can jump to the original context. Post-processed deterministically after the model's response rather than relying on prompt instructions, since models don't reliably keep blank lines/links in free-form output. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…erges
Replace the three Search-API-based queries (issues created, PRs created,
commits authored) with a single call to GitHub's per-user Events API
(`GET /users/{username}/events`), which captures far more of "my GitHub
activity": issues/PRs opened and closed, PRs merged, PR reviews given
(approved / requested changes / commented), and comments left on issues
and PRs — not just things I created.
Important correctness fix during implementation: the org-scoped events
endpoint (`/users/{username}/events/orgs/{org}`) initially used for this
turned out to be the user's *organization dashboard* feed — i.e. other
org members' activity, not events performed by this user (verified
empirically: 0/100 sampled events had actor.login matching the
authenticated user). Switched to the plain `/users/{username}/events`
endpoint, which correctly scopes to the authenticated user's own
actions, then filter results client-side to configured orgs
(GITHUB_ORG) and ignored repos.
Also added:
- Defensive handling for GitHub's ~300-event/3-page hard cap on this
endpoint: pagination now stops gracefully (keeping partial results)
instead of raising an uncaught error, and surfaces a visible
"⚠️ ... may be missing" note in the log if the cap was hit before
confirming full day coverage, rather than silently showing "no
activity".
- PushEvent-based commit collection, deduped by SHA and filtered to
`distinct: true` commits to avoid double-counting on force-pushes.
Updated `renderGitHubList` to render all the new activity types
(reviews grouped with human-readable state labels, comments grouped
by repo like commits already were), and updated README/CHANGELOG to
describe the expanded scope.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Code review caught that the previous condition (status===422 && page>1) would swallow a 422 as young as page 2, which per the code's own stated intent should instead propagate as a hard failure (auth error, etc.). GitHub's ~300-event cap on this endpoint is only reachable once page 4+ is requested with per_page=100. Gate the swallow condition on having already fetched >= 300 events (computed from page/PAGE_SIZE, so it stays correct if PAGE_SIZE ever changes) instead of a hardcoded page number. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
therzka
force-pushed
the
feature/daily-activity-log
branch
from
July 1, 2026 22:30
d5dc1b6 to
7ad0cf3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an automated "Daily Activity" feature that appends an idempotent markdown block to each day's work log, combining:
GET /users/{username}/events), filtered to configured orgs and ignored repos, with a visible warning if GitHub's ~300-event pagination cap is hit before the full day is confirmed covered.gh-slack), with blank-line separation between channels and a permalink back to each channel's activity.Triggering:
dailyActivityHour), with an in-flight guard to avoid duplicate/overlapping runs.Notable fixes along the way
gh-slackAPI call, keeping AI only for summarization (not tool use).Test Plan
npm run build(includes TypeScript type check) passes cleannpm run lintpasses clean