fix(activity-feed): canonicalize contributor handle so profile links resolve #9

Merged
fwazb merged 1 commit from fix/activity-feed-canonical-handle into main 2026-05-13 03:19:41 +00:00
Owner

Problem

The activity feed was returning decorated strings like Vida (self-directed) and @m3taversal in the contributor field. The frontend uses that field as both display label and routing handle, so /contributors/Vida%20(self-directed) 404s — Next fires notFound() in [handle]/page.tsx.

Root cause

_normalize_contributor only stripped @ and whitespace; it did not lowercase or strip the (self-directed) suffix that extract.py and the older backfill_submitted_by.py wrote into prs.submitted_by. Mixed-case agent names (Vida vs vida) and pipeline decorators (pipeline (reweave)) both fell through.

Fix

Lowercase + strip any trailing parenthetical decorator. Valid handles match ^[a-z0-9][a-z0-9_-]{0,38}$ per attribution._HANDLE_RE and cannot contain parens, so the strip is lossless.

Verification

  • 12/12 unit cases pass (mixed-case agent names, decorated suffixes, m3taversal variants, edge empties)
  • DB simulation against 3612 merged-PR events: 0 orphan handles after normalization (was 12 orphan label-variants before)
  • No KB writes — pure read-side normalization in the API layer

Stack context

Part of a 3-PR set fixing timeline-page 404s end-to-end:

  • This PR: read-side fix
  • fix/canonicalize-submitted-by (sibling Forgejo PR): write-side fix in lib/extract.py + historical backfill (3738 rows)
  • living-ip/livingip-web#33: frontend contract docs + enforceable check script

Merging this one alone resolves the live 404. The other two are durable guardrails so the contract can't quietly regress.

## Problem The activity feed was returning decorated strings like `Vida (self-directed)` and `@m3taversal` in the `contributor` field. The frontend uses that field as both display label and routing handle, so `/contributors/Vida%20(self-directed)` 404s — Next fires `notFound()` in `[handle]/page.tsx`. ## Root cause `_normalize_contributor` only stripped `@` and whitespace; it did not lowercase or strip the ` (self-directed)` suffix that `extract.py` and the older `backfill_submitted_by.py` wrote into `prs.submitted_by`. Mixed-case agent names (Vida vs vida) and pipeline decorators (`pipeline (reweave)`) both fell through. ## Fix Lowercase + strip any trailing parenthetical decorator. Valid handles match `^[a-z0-9][a-z0-9_-]{0,38}$` per `attribution._HANDLE_RE` and cannot contain parens, so the strip is lossless. ## Verification - 12/12 unit cases pass (mixed-case agent names, decorated suffixes, m3taversal variants, edge empties) - DB simulation against 3612 merged-PR events: **0 orphan handles** after normalization (was 12 orphan label-variants before) - No KB writes — pure read-side normalization in the API layer ## Stack context Part of a 3-PR set fixing timeline-page 404s end-to-end: - This PR: read-side fix - `fix/canonicalize-submitted-by` (sibling Forgejo PR): write-side fix in `lib/extract.py` + historical backfill (3738 rows) - `living-ip/livingip-web#33`: frontend contract docs + enforceable check script Merging this one alone resolves the live 404. The other two are durable guardrails so the contract can't quietly regress.
m3taversal added 1 commit 2026-05-13 03:08:47 +00:00
fix(activity-feed): canonicalize contributor handle so profile links resolve
Some checks are pending
CI / lint-and-test (pull_request) Waiting to run
01097da22c
The activity feed was returning decorated strings like "Vida (self-directed)"
and "@m3taversal" in the contributor field. The frontend uses that field as
both display label and routing handle, so /contributors/Vida%20(self-directed)
404s — Next fires notFound() in [handle]/page.tsx.

Root cause: _normalize_contributor only stripped @ and whitespace; it did not
lowercase or strip the " (self-directed)" suffix that extract.py and the
older backfill_submitted_by.py wrote into prs.submitted_by. Mixed-case
agent names (Vida vs vida) and pipeline decorators ("pipeline (reweave)")
both fell through.

Fix: lowercase + strip any trailing parenthetical decorator. Valid handles
match ^[a-z0-9][a-z0-9_-]{0,38}$ per attribution._HANDLE_RE and cannot
contain parens, so the strip is lossless.

DB simulation against 3612 merged-PR events: 0 orphan handles after
normalization (was 12 orphan label-variants before).

No KB writes — pure read-side normalization in the API layer.
fwazb merged commit 2ee9dd5150 into main 2026-05-13 03:19:41 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: teleo/teleo-infrastructure#9
No description provided.