← back to Ventura Corridor
iter 172: /api/magazine/similar/:id — pg_trgm word_similarity over first 480 chars; surfaces editorial-body templating beyond headline-level
317fdcfc39e70ef911a2b4b551997e756e9e86b8 · 2026-05-06 20:19:05 -0700 · SteveStudio2
Files touched
Diff
commit 317fdcfc39e70ef911a2b4b551997e756e9e86b8
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 6 20:19:05 2026 -0700
iter 172: /api/magazine/similar/:id — pg_trgm word_similarity over first 480 chars; surfaces editorial-body templating beyond headline-level
---
src/server/index.ts | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/src/server/index.ts b/src/server/index.ts
index 2876f1e..4d430a9 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1934,6 +1934,43 @@ app.get('/api/magazine/random', async (req, res) => {
}
});
+// Editorial similarity — finds features whose bodies most resemble the given feature.
+// Uses pg_trgm word_similarity over the first 480 chars (avoids huge cross-products).
+// Use case: detect when qwen3 reuses similar sentence structure across features
+// (deeper signal than exact-duplicate or trigram detection).
+app.get('/api/magazine/similar/:id', async (req, res) => {
+ try {
+ const id = parseInt(req.params.id, 10);
+ const limit = Math.min(20, Math.max(1, parseInt(String(req.query.limit || 5), 10) || 5));
+ if (!Number.isFinite(id)) return res.status(400).json({ error: 'bad id' });
+ const seed = await query(`SELECT editorial, headline FROM magazine_features WHERE id = $1`, [id]);
+ if (seed.rowCount === 0) return res.status(404).json({ error: 'feature not found' });
+ const seedText = String(seed.rows[0].editorial || '').slice(0, 480);
+ if (!seedText) return res.json({ id, neighbors: [] });
+
+ const r = await query(`
+ SELECT mf.id, mf.headline, mf.subhead, mf.category_tag, mf.status,
+ b.name AS biz_name,
+ round(similarity(LEFT(mf.editorial, 480), $2)::numeric, 3) AS similarity
+ FROM magazine_features mf
+ JOIN businesses b ON b.id = mf.business_id
+ WHERE mf.id != $1
+ AND mf.editorial IS NOT NULL
+ AND length(mf.editorial) > 100
+ ORDER BY LEFT(mf.editorial, 480) <-> $2 ASC
+ LIMIT $3
+ `, [id, seedText, limit]);
+
+ res.json({
+ id,
+ seed_headline: seed.rows[0].headline,
+ neighbors: r.rows.map((n: any) => ({ ...n, permalink: `/magazine/${n.id}` })),
+ });
+ } catch (e: any) {
+ res.status(500).json({ error: e.message });
+ }
+});
+
// Calendar — features generated/published per day for the last N days.
// Powers /calendar.html GitHub-style heatmap.
app.get('/api/magazine/calendar', async (req, res) => {
← a55be3f iter 171: SESSION_LOG_2026-05-06.md — 40-iter overnight debr
·
back to Ventura Corridor
·
iter 173: auto-dedupe now also catches trigram-templated hea 88857c9 →