Commit Graph

93 Commits

Author SHA1 Message Date
163a36fa08 ci: allow esbuild/@swc native build scripts under pnpm 10
Some checks failed
deploy / Build prerendered web (push) Failing after 2m10s
deploy / Deploy web to oolon (push) Has been skipped
deploy / Build api + worker (static musl) (push) Successful in 6m45s
deploy / Deploy moments-worker to frootmig (push) Successful in 58s
deploy / Deploy moments-api to nikola (push) Successful in 1m1s
The fedora-44 runner's pnpm 10 blocks dependency build scripts by default,
so `pnpm install` failed the web build with ERR_PNPM_IGNORED_BUILDS. esbuild
and @swc/core need their postinstall to place native binaries for vite; allow
them via pnpm.onlyBuiltDependencies, and explicitly ignore the harmless
react-vertical-timeline-component postinstall. Does not change the lockfile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7zF7Kf4JqDwa6M8Qgge9M
2026-06-25 13:35:00 +03:00
ed5acd9f4e ci: split build across rust + fedora runners, deploy on fedora-44
Some checks failed
deploy / Build api + worker (static musl) (push) Successful in 7m57s
deploy / Deploy moments-worker to frootmig (push) Successful in 1m1s
deploy / Deploy moments-api to nikola (push) Successful in 1m6s
deploy / Build prerendered web (push) Failing after 2m1s
deploy / Deploy web to oolon (push) Has been skipped
The `rust` runner image has cargo + musl but no node/pnpm, so the web build
(and the previous npm-install workaround) can't run there. The fedora runner
images bake in node + pnpm + rsync. Split the build:
- build-binaries on `rust`  (cargo musl + lint/test gate)
- build-web      on `fedora-44` (pnpm install + prerender, no install step)
Deploy jobs move to `fedora-44` (has rsync/ssh/pnpm/ca-trust) and depend on
the relevant build job.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7zF7Kf4JqDwa6M8Qgge9M
2026-06-25 13:19:57 +03:00
a7750def17 ci: install pnpm via npm (gongfoo rust image lacks corepack)
Some checks failed
deploy / Build api + worker + web (push) Waiting to run
deploy / Deploy moments-api to nikola (push) Has been cancelled
deploy / Deploy moments-worker to frootmig (push) Has been cancelled
deploy / Deploy web to oolon (push) Has been cancelled
The build job failed with `corepack: command not found`: Fedora's nodejs
package (gongfoo runner-rust image) ships node + npm but not corepack. The
job runs as root, so install pnpm globally via npm instead. Longer term,
bake pnpm into the runner image to drop this step.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7zF7Kf4JqDwa6M8Qgge9M
2026-06-25 13:13:59 +03:00
3761333ac4 fix: make the workspace pass the CI lint/test gate
Some checks failed
deploy / Build api + worker + web (push) Failing after 5m59s
deploy / Deploy moments-api to nikola (push) Has been skipped
deploy / Deploy moments-worker to frootmig (push) Has been skipped
deploy / Deploy web to oolon (push) Has been skipped
The new Gitea Actions build gate runs `cargo fmt --check`, `clippy -D warnings`,
and `cargo test` — stricter than the old deploy.sh, which only `cargo build`d.
That surfaced pre-existing drift that never compiled under the test/clippy
profile:

- apply rustfmt across the workspace (formatting only, no logic changes)
- moments-data: add the missing `prune_events` to the test-only `NoopWriter`
  stub (the EventWriter trait gained it with the blog-prune feature; a plain
  `cargo build` never compiles the `#[cfg(test)]` stub, so it went stale)
- moments-api: `.max().min()` -> `.clamp()`, and build `usvg::Options` with
  struct-update syntax instead of post-Default field assignment

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7zF7Kf4JqDwa6M8Qgge9M
2026-06-25 13:00:40 +03:00
1b753f991f feat: prerender every route + Gitea Actions deploy
Some checks failed
deploy / Build api + worker + web (push) Failing after 53s
deploy / Deploy moments-api to nikola (push) Has been skipped
deploy / Deploy moments-worker to frootmig (push) Has been skipped
deploy / Deploy web to oolon (push) Has been skipped
Make the site fully prerendered so a plain curl returns complete content
for every route (crawlers / AI screening tools see real text, not an empty
#root), while humans keep full client interactivity.

Prerender:
- Build-time per-route render: prefetch data, renderToString, inline the
  dehydrated react-query cache as window.__RQ_STATE__; client hydrateRoots
  and refetches live (activity stays fresh; crawlers get the baked snapshot).
- New entry-server.tsx + prerender/{prefetch,routes,meta}.ts + run-prerender.mjs;
  shared lib/ranges.ts keeps SSR and client query keys identical.
- pnpm build now: tsc -b -> vite client build -> ssr build -> prerender.
- API base absolute at build (VITE_API_BASE), relative /api/v1 in the browser.
- CSS imports moved to the client entry so the tree imports under Node.
- schema.org Person + Occupation JSON-LD and per-route title/description/og.
- UTC + explicit field widths on shared date formatting so SSR and client
  hydration match byte-for-byte (fixes hydration mismatch on /activity).
- Strip non-text gist content from the CV fetch (1MB -> 25KB gzipped page).

Deploy (Gitea Actions, replaces script/deploy.sh):
- deploy.yml: on push to main, lint/test gate, build api+worker as static
  musl binaries (pure-rustls, no glibc skew) + prerendered web, deploy each
  over SSH as gitea_ci with scoped sudo.
- refresh.yml: daily cron re-bakes only the web snapshot so gist/activity
  edits propagate without a push or bouncing the api/worker.
- script/infra-setup.sh + asset/sudoers.d/{api,worker,web}-host.conf for
  one-time per-host provisioning. Secrets: RSYNC_SSH_KEY, QUERY_GITHUB_TOKEN,
  QUERY_GITEA_TOKEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7zF7Kf4JqDwa6M8Qgge9M
2026-06-25 12:53:46 +03:00
70b4b265c3 style(blog): scale down in-content post headings
markdown section headings (## etc.) rendered at bootstrap defaults,
making them as large as the post title. size .blog-post h1-h4 down to
1.4/1.25/1.1/1rem so sections read as subordinate to the title.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 10:15:46 +03:00
908ab33bd2 style(blog): smaller list headers, readable date color
list-view post titles were h3 at the bootstrap default, large enough
to wrap; size them to 1.4rem. dates used bootstrap's text-muted, whose
dark grey contrasts poorly on the dark background — replace with a
blog-date class matching the site's opacity-based muted-text pattern,
on the list and the detail page.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-13 10:14:02 +03:00
37c44906bb feat(blog): prune posts removed or renamed upstream
the blog repo is the source of truth for the full set of posts, but
upserts alone never delete: removing a file or changing a slug or
filename left the old row serving forever. each poll now reconciles —
after upserting the current tree, events under source='blog' whose id
is not in the parsed set are deleted via a new EventWriter::prune_events
port. nothing is lost: git still has every post, and restoring or
fixing a file re-ingests it on the next tip change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:56:54 +03:00
cd3dc2d82d fix(ui): add @types/node for process.env in vite.config
tsc -b type-checks vite.config.ts during the production build (pnpm
lint does not), and the API_PROXY_TARGET override added there needs
node types for `process`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:48:26 +03:00
88ce993df3 feat(blog): add markdown blog sourced from a gitea repo
posts are markdown files with yaml frontmatter (title, slug, date;
optional draft/public) in the grenade/blog repo. the worker's new
BlogSource polls the repo — one branch-tip request when nothing
changed — and upserts posts into events with source='blog' and
occurred_at from the frontmatter date, so imported posts keep their
original publish dates and backfill the contribution graph.

- new /v1/blog and /v1/blog/{slug} endpoints over the existing
  EventReader port; drafts stay hidden via the public gate
- new /blog and /blog/:slug routes, nav link, activity-feed entry
  with post icon and filter toggle; relative image srcs resolve to
  gitea raw urls
- shared Markdown component extracted from ProjectPage
- vite proxy target overridable via API_PROXY_TARGET for local dev

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 22:44:56 +03:00
2821548e6e feat(ui): add avg-by-hour panel to dashboard stats
Complements the existing avg-by-weekday chart with its orthogonal
partner: which hour of the day the user typically commits. The api
buckets events by EXTRACT(hour FROM occurred_at AT TIME ZONE $tz) so
the chart matches the clock the user sees rather than UTC; the UI
passes the browser's resolved IANA timezone. Renders as 24 mini-bars
below the weekday chart with labels every 4 hours and per-bar
tooltips showing the average events/day at that hour.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 16:34:17 +03:00
72eeb547af chore(deploy): self-heal /tmp perms before staging
frootmig periodically has its /tmp reset from the standard sticky-
world-writable 1777 to root-owned 0755 (cause not yet pinned down),
which breaks the unprivileged rsync of the deploy stage dir and
surfaces as a cryptic "Permission denied" plus a follow-on install
failure. Stat /tmp before each rsync and, if the mode is off, sudo
chmod it back to 1777 — visible in the deploy log so it's obvious
which host keeps drifting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:59:06 +03:00
86411bb88e fix(worker): dedup gitea events from overlapping user and org feeds
Gitea writes one Action row per interested user-context. A push to an
org repo by user U produces two rows — one with user_id=U, one with
user_id=org — differing only in `id` and `user_id`. Polling both the
user feed and org feeds (which we do, and need to, since neither alone
catches every cross-namespace event) surfaced both rows; the
`gitea:{action_row_id}` id gave them distinct ids, so the upsert dedup
never fired and ~38% of events on org-repo project pages rendered
twice. Switch to a content-derived id keyed on (op_type, act_user_id,
repo_id, ref_name, comment_id, created) so the two rows collide on
upsert, and add a migration that re-keys existing rows to the same
formula while collapsing the duplicates already in the table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 07:53:43 +03:00
acb061baca chore(deploy): build rust binaries in a podman container
Workstation runs Fedora 44 (glibc 2.43); servers are still on F42 and
F43. A native release build produces ELFs the older glibc can't load
(GLIBC_2.43 not found), and the api/worker units fail-loop on every
deploy. Build inside docker.io/library/rust:1-bookworm (glibc 2.36)
so the artifacts are forward-compatible with every Fedora target.
Output goes to target/deploy/ to keep separate from native dev
builds, and the cargo registry/git index are cached in named podman
volumes so subsequent builds are incremental. podman is a hard
requirement; no docker fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:05:13 +03:00
8a7177a54a feat(ui): render GFM and embedded HTML in project READMEs
ReactMarkdown was running with no plugins, so README headers full of
raw <div align=center>, tables, <details>/<summary>, and other GFM
markup rendered as escaped text. Wire in remark-gfm for tables and
GFM features, rehype-raw for embedded HTML, and rehype-sanitize with
an extended schema that permits README-typical tags and attributes
(align, target, width/height, picture/source, etc.) while still
blocking script/iframe/object — READMEs come from external repos so
they need adversarial-input handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:05:05 +03:00
818a535903 feat(worker): capture commits on non-default branches and forks
The ingestion paths each had a gap that let non-default-branch work
slip through: /search/commits silently excludes forks, the per-repo
REST commit scan only walked the default branch, and the user events
feed ages out after 90 days. Catch them by enumerating branches per
repo and scanning each (with per-branch state cursors so a brand-new
branch isn't cut off by the default branch's cursor), pre-filtering
branches via a GraphQL HEAD-author check so big upstream forks like
azure-docs don't trigger hundreds of wasted REST calls, treating
GitHub's HTTP 500 on author-filtered empty branches as "no commits"
rather than a server error, and adding fork:true to the search query.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:04:58 +03:00
9a8c0955b5 chore: phrasing 2026-05-12 13:20:11 +03:00
25eab2d795 feat: add robots.txt allowing all crawlers including social bots
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:49:55 +03:00
2130032d46 chore: update Cargo.lock for fontdb dependency
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:35:08 +03:00
92a66422ab feat(ui): add meta description, og:locale, and og:site_name
Adds the standard HTML meta description (for SEO), og:locale, and
og:site_name tags flagged by Open Graph validators.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:32:33 +03:00
94b6fbe42d feat(ui): add og:logo meta tag pointing to 512px icon
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:29:40 +03:00
048646a7c1 feat(ui): add og:url meta tag for canonical URL
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:27:47 +03:00
1f2fea3427 fix: load system fonts for OG image text rendering
usvg's default Options creates an empty fontdb, so no fonts are found
for text rendering regardless of what's installed. Load system fonts
into a fontdb::Database and set the default font family to Noto Sans.

Also picks up a formatting change to index.html from a linter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:17:17 +03:00
d539892b70 fix: scale OG contribution graph to fill 1200x630 canvas
Compute cell size from available width so the graph fills the canvas
instead of rendering at a fixed small size. Scale year labels
proportionally. Position headline and subtitle at the top with the
graph centered in the remaining space.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:11:05 +03:00
a57682e610 feat: improve OG image and meta tags for social sharing
- Resize OG image from ~676x216 to 1200x630 (recommended size)
- Add "rob thijssen" headline text overlay to the OG image
- Center the contribution graph within the canvas
- Expand og:title to 55 chars and og:description to 148 chars
  to meet social platform optimal lengths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:08:29 +03:00
22c80fd7af feat(ui): transpose weekday averages to vertical bar chart
Show days on the X axis and volume on the Y axis, replacing the
horizontal bar layout with vertical bars for a more natural
time-series reading direction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 16:02:30 +03:00
8b5656ef26 fix: specify sans-serif font in OG image SVG text elements
The SVG text elements had no font-family, causing usvg to default to
Times New Roman which isn't installed on the server. Specifying
sans-serif uses the system default and silences the warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:56:24 +03:00
dd1de38b2f feat(ui): show more languages in top languages chart
Increase from 10 to 14 rows so languages visible in the contribution
graph (e.g. Svelte, C++) also appear in the legend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:52:33 +03:00
283b2126c0 feat(ui): color contribution graph circles by dominant language
Replace fixed green palette with per-period dominant language colors.
Each circle's hue reflects the language with the most commits for that
day (last-year graph) or month (all-time graph), with opacity scaled
by volume quartile. Language data comes from the existing language
daily counts endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:50:19 +03:00
e8dcb5fcaf feat(ui): show private activity count on timeline when no public events
When viewing a date range with zero public activities, the status line
now shows the count of private contributions (derived from daily counts
which include private repos). Helps explain gaps in the public timeline.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:41:22 +03:00
b41e8c330a feat: include private repo contributions in graph metrics
Aggregate graph endpoints (daily counts, language daily counts, source
summaries, OG image) now include private repository activity. These
endpoints only expose numeric counts — no commit messages, repo names,
or other metadata — so private details remain hidden. The activity
timeline continues to serve only public events.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:35:22 +03:00
f386e0b574 feat(ui): reshape all-time graph and add dashboard stats panels
Transpose AllTimeGraph to show years on X axis and months on Y axis
instead of year-per-row with weekly columns. Add TopLanguages bar chart
(all-time code volume by language) and ContributionStats panel (current
and longest streaks, busiest day, active days, weekday averages) in a
three-column row matching the project card grid.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-11 15:27:39 +03:00
111a2af573 feat(ui): language distribution bar on project cards
Extract LanguageBar into a shared component used by both DashPage
(compact, bar only) and ProjectPage (full, with percentage labels).
Remove redundant forge source text from project cards since the
forge icon already indicates it.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 07:13:41 +03:00
6f30a61184 feat(ui): smooth language stream graph with Catmull-Rom splines
Replace straight line segments with cubic bezier curves using
Catmull-Rom to bezier conversion (tension 0.5) for a smoother
stream graph visualization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 07:02:50 +03:00
14643273c0 fix: weight language graph by repo language proportions
Each commit was counted once per language in the repo regardless of
that language's share, so Shell (present in many repos as small
deploy scripts) appeared larger than Rust. Now weights each commit
by the language's byte proportion in the repo (e.g. a commit to a
95% Rust / 5% Shell repo contributes 0.95 to Rust, 0.05 to Shell).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 06:59:47 +03:00
ee93429317 feat: language stream graph on dashboard
Full-stack feature showing programming languages by commit activity
as a stream graph on the dashboard.

Backend:
- migration: repo_languages table (source, repo, language, bytes, color)
- worker: fetch language breakdowns via GitHub GraphQL (batched,
  20 repos/request) and Gitea REST API during poll cycles
- API: GET /v1/languages/daily (daily commit counts per language),
  GET /v1/languages/repos (all stored repo language data)
- fix timezone bug in daily_counts and language_daily_counts: the
  PostgreSQL server timezone (Europe/Sofia, UTC+3) shifted day
  boundaries, miscounting events near midnight. Now uses explicit
  UTC boundaries in generate_series JOINs.
- use per-source CASE for repo name extraction in language query
  to match gitea payload structure (repo.full_name vs repo.name)
- Gitea languages use GitHub colors via COALESCE fallback

Frontend:
- LanguageStreamGraph component: pure SVG stream graph, weekly
  buckets, centered baseline, top 8 languages + Other, GitHub
  canonical language colors, legend with color dots
- DashPage/ProjectPage: fetch repo languages once via new endpoint
  instead of per-repo forge proxy calls (eliminates 200+ GitHub
  API calls and 403 rate limit errors)
- removed fetchLanguages forge proxy wrapper (dead code)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 06:27:59 +03:00
c66aaeb268 feat: discover contributed repos via GitHub GraphQL API
The REST /user/repos endpoint only returns repos where the user is
owner, collaborator, or org member. Repos contributed to via PRs
(e.g. polkadot-js/api, zed-industries/zed) were never discovered
and their commits were missing from moments.

Now supplements /user/repos with a GraphQL
repositoriesContributedTo query, which returns all repos the user
has committed to, opened issues/PRs on, or reviewed — with cursor-
based pagination and no result cap.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 05:38:57 +03:00
2a20b47a29 fix: resolve clippy redundant_closure warning in moments-api
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 05:04:18 +03:00
f77a8ab48f fix: use since cursor in github-repo polls to prevent missed commits
After initial backfill, scan_repo was fetching only page 1 (100 most
recent commits) per repo. If more than 100 commits landed between
7-day polls, older ones in that window were permanently missed.

Now stores the newest commit date in poller_state.last_modified and
passes it as &since= on subsequent polls, with full pagination, so
only genuinely new commits are fetched but none are skipped.

On first poll after deploy, last_modified is NULL so no since filter
is applied — triggering a full re-backfill that catches any
previously missed commits.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 05:03:41 +03:00
1679153c43 docs: add CLAUDE.md and ignore .zed/
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-06 04:43:00 +03:00
0aa53d30db docs: rewrite readme to reflect current architecture
Cover all data sources (github events/search/repo, gitea with org
discovery, hg revset queries, bugzilla), frontend routes (dash with
contribution graphs, activity timeline with timespan filtering,
project detail with readme/languages, cv), api endpoints including
forge proxy and og image, environment variables, and deployment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:52:25 +03:00
cd833b18f1 fix(ui): demote repos with >= 10k commits to end of dashboard
Automated/bulk-commit repos score -1 so they sort last regardless
of recency or volume.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:48:52 +03:00
293d112c18 fix: fall back to _repo in commit reshape for github-repo events
The commit presentation layer only checked repository.full_name,
missing commits ingested by github_repo which store the repo name
in _repo instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:44:31 +03:00
ef1e84a41b feat(ui): link forge icon to repo on project page
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:42:04 +03:00
f8c13b5e21 fix: icon colors for dark backgrounds 2026-05-05 18:40:29 +03:00
abc90c8da0 feat(ui): forge icon on project page header
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:30:13 +03:00
d46a0e3777 fix: add _repo fallback to events repo filter for github-repo commits
The events query's COALESCE for github source was missing _repo,
so per-repo commit events from github_repo had no repo match and
project pages showed 0 activities.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:28:32 +03:00
642209068a feat(ui): forge icons on repo cards (github, gitea, mozilla)
Add SVG icons for each forge before the repo name on dashboard cards.
Icons sourced from user-provided SVGs in ui/public/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:24:47 +03:00
c1e964de06 feat(ui): show all repos on dashboard instead of top 24
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 18:09:34 +03:00
45fd45f5da fix: stamp _repo into github-repo commit payloads for project attribution
The /repos/{owner}/{repo}/commits endpoint doesn't include repo info
in its response. Without _repo in the payload, these commits were
invisible to the projects query. Add _repo to parse_commit and include
it in the COALESCE chain for github source repo extraction.

After deploy, reset github-repo poller state to re-ingest with _repo:
  DELETE FROM poller_state WHERE source LIKE 'github-repo%';

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-05 17:59:31 +03:00