← back to build-pages
api: canonAuthor() collapses 'SteveStudio2'/'Steve Abrams'/etc into 'Steve' — authors[] no longer fragmented
c7c77634f5e9571ff168b562c58c61a86f12a0c2 · 2026-05-13 19:05:51 -0700 · SteveStudio2
Files touched
Diff
commit c7c77634f5e9571ff168b562c58c61a86f12a0c2
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 19:05:51 2026 -0700
api: canonAuthor() collapses 'SteveStudio2'/'Steve Abrams'/etc into 'Steve' — authors[] no longer fragmented
---
server.js | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/server.js b/server.js
index 2f944ed..6ed9f3e 100644
--- a/server.js
+++ b/server.js
@@ -787,6 +787,22 @@ for (const facet of ['agents', 'skills']) {
// /api/recent — most recent N commits across the entire fleet, merged + sorted
// by date desc. Powers a "today across the fleet" rail. Shares the bundle
// cache so it's free after the first warm.
+// Normalize git author strings. Steve commits as "SteveStudio2", "Steve",
+// "Steve Abrams" — same person, different .gitconfig values on different
+// machines. Map these to a canonical name so the authors[] tally doesn't
+// fragment. Extensible — add more aliases here as new people come in.
+const AUTHOR_ALIASES = {
+ 'stevestudio2': 'Steve',
+ 'steve abrams': 'Steve',
+ 'steveabrams': 'Steve',
+ 'steve@designerwallcoverings.com': 'Steve',
+};
+function canonAuthor(name) {
+ if (!name) return 'unknown';
+ const key = name.toLowerCase().trim();
+ return AUTHOR_ALIASES[key] || name;
+}
+
// Parse a ?since= query value into a unix ms cutoff (or 0 = no filter).
// Accepts 24h, 7d, 30m, or an ISO date prefix (YYYY-MM-DD…). Returns 0 for
// missing/malformed input so callers can use the result as a min-Date filter
@@ -1073,8 +1089,13 @@ app.get('/api/projects/:slug', async (req, res, next) => {
const first = bundle.commits[bundle.commits.length - 1];
const last = bundle.commits[0];
// Author breakdown — who landed how many commits on this project.
+ // Aliases collapsed via canonAuthor() so multiple git-config names map to
+ // one person.
const authorTallies = new Map();
- for (const c of bundle.commits) authorTallies.set(c.author, (authorTallies.get(c.author) || 0) + 1);
+ for (const c of bundle.commits) {
+ const a = canonAuthor(c.author);
+ authorTallies.set(a, (authorTallies.get(a) || 0) + 1);
+ }
const authors = [...authorTallies.entries()]
.map(([name, count]) => ({ name, count }))
.sort((a, b) => b.count - a.count);
← 4acf48a api: /api/projects/:slug now includes authors[] breakdown
·
back to build-pages
·
api/fleet/authors + Authors chip rail on /p/:slug — uses can b806ffd →