← back to Ventura Corridor
feat(coverage): "tonight on the corridor" glance footer
e4ee322a324ea1e2d643114cd25116b5fa6e4b2b · 2026-05-08 01:12:23 -0700 · SteveStudio2
One-line session summary at the bottom of /coverage.html showing
commits / insertion lines / news articles+biz / ideas accepted/total.
Reads /api/session-stats which aggregates git log + news_items +
ideas.jsonl in a single endpoint (60s cache).
Visible at the dramatic black-and-gold footer panel below all the
existing analytics sections so Steve sees the run scorecard at the
end of the page without scrolling out into other tools.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M public/coverage.htmlM src/server/index.ts
Diff
commit e4ee322a324ea1e2d643114cd25116b5fa6e4b2b
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Fri May 8 01:12:23 2026 -0700
feat(coverage): "tonight on the corridor" glance footer
One-line session summary at the bottom of /coverage.html showing
commits / insertion lines / news articles+biz / ideas accepted/total.
Reads /api/session-stats which aggregates git log + news_items +
ideas.jsonl in a single endpoint (60s cache).
Visible at the dramatic black-and-gold footer panel below all the
existing analytics sections so Steve sees the run scorecard at the
end of the page without scrolling out into other tools.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/coverage.html | 17 ++++++++++++++++
src/server/index.ts | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+)
diff --git a/public/coverage.html b/public/coverage.html
index d58b097..b86b5da 100644
--- a/public/coverage.html
+++ b/public/coverage.html
@@ -119,6 +119,11 @@ main{padding:32px;max-width:1200px;margin:0 auto}
<div id="news-board"></div>
</div>
+<div id="session-glance" style="margin-top:48px;padding:18px 22px;background:linear-gradient(180deg,var(--noir-rise),#0a0a0c);border:2px solid var(--metal);border-radius:6px;font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--cream);text-align:center;letter-spacing:.06em">
+ <span style="color:var(--metal);font-size:10px;letter-spacing:.32em;text-transform:uppercase">— tonight on the corridor —</span>
+ <div id="glance-line" style="margin-top:10px;color:var(--metal-glow);font-size:14px">loading…</div>
+</div>
+
</main>
<script>
function escHtml(s) { return String(s ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); }
@@ -238,6 +243,18 @@ async function load() {
}
} catch (e) { /* skip */ }
+ // Session at a glance — one-liner summary for the night
+ try {
+ const s = await fetch('/api/session-stats').then(r => r.json());
+ const parts = [
+ `${s.commits} commits`,
+ `${s.insertions.toLocaleString()} lines`,
+ `${s.news_total} articles · ${s.news_biz} biz`,
+ `${s.ideas_accepted}/${s.ideas_accepted + s.ideas_rejected} ideas accepted`
+ ];
+ document.getElementById('glance-line').innerHTML = parts.join(' · ');
+ } catch(e) {}
+
// News scrape calendar — 90-day heatmap above the heatmap section
try {
const cal = await fetch('/api/news/by-day').then(r => r.json());
diff --git a/src/server/index.ts b/src/server/index.ts
index bfdf3bb..78ef0d2 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -5146,6 +5146,62 @@ app.get('/api/news/archive', async (_req, res) => {
// entries. Pure read; idea-loop owns its own writes.
// Idea-loop stats: accept/reject totals + breakdown by type. Useful to spot
// "is the panel too generous" (>50% accept) or "too harsh" (<5% accept).
+// Session-at-a-glance — single endpoint that aggregates "what was tonight"
+// for the coverage page footer. Reads git log for commit count + LoC,
+// news_items for content state, idea-loop jsonl for creative state.
+app.get('/api/session-stats', async (_req, res) => {
+ try {
+ const fs = await import('node:fs/promises');
+ const path = await import('node:path');
+ const { exec } = await import('node:child_process');
+ const execP = (cmd: string) => new Promise<string>((resolve) => {
+ exec(cmd, { cwd: process.cwd(), encoding: 'utf8', timeout: 4000 }, (_e, out) => resolve(out || ''));
+ });
+
+ // Tonight = since the news pipeline started (7594bb3, ~6 hours ago)
+ const SESSION_BASE = '7594bb3';
+ const commitCount = parseInt((await execP(`git rev-list --count ${SESSION_BASE}..HEAD 2>/dev/null`)).trim(), 10) || 0;
+ const shortStat = (await execP(`git diff ${SESSION_BASE}..HEAD --shortstat 2>/dev/null`)).trim();
+ const insMatch = shortStat.match(/(\d+) insertion/);
+ const insertions = insMatch ? parseInt(insMatch[1], 10) : 0;
+
+ // News + biz counts
+ const newsR = await query(`
+ SELECT
+ COUNT(*)::int AS news_total,
+ COUNT(DISTINCT business_id)::int AS news_biz,
+ COUNT(*) FILTER (WHERE summary IS NOT NULL)::int AS summarized
+ FROM news_items
+ `);
+
+ // Ideas
+ const home = process.env.HOME || require('os').homedir() || '';
+ let ideasAccepted = 0, ideasRejected = 0;
+ try {
+ const a = await fs.readFile(path.join(home, '.claude', 'skills', 'idea-loop', 'data', 'ideas.jsonl'), 'utf8');
+ ideasAccepted = a.split(/\r?\n/).filter(Boolean).length;
+ } catch {}
+ try {
+ const r = await fs.readFile(path.join(home, '.claude', 'skills', 'idea-loop', 'data', 'rejects.jsonl'), 'utf8');
+ ideasRejected = r.split(/\r?\n/).filter(Boolean).length;
+ } catch {}
+
+ res.set('Cache-Control', 'public, max-age=60');
+ res.json({
+ commits: commitCount,
+ insertions,
+ news_total: newsR.rows[0]?.news_total || 0,
+ news_biz: newsR.rows[0]?.news_biz || 0,
+ summarized: newsR.rows[0]?.summarized || 0,
+ ideas_accepted: ideasAccepted,
+ ideas_rejected: ideasRejected,
+ session_base: SESSION_BASE
+ });
+ } catch (e: any) {
+ res.status(500).json({ error: e.message });
+ }
+});
+
app.get('/api/ideas/stats', async (_req, res) => {
try {
const fs = await import('node:fs/promises');
← be002e1 fix(coverage): wire JS for rejects drawer (was empty since t
·
back to Ventura Corridor
·
feat(coverage): expose ideas_rejected on homepage strip alon b552dfe →