v0.3.0: Gap-to-Draft pipeline, Living Standards Observatory, blog series
Gap-to-Draft Pipeline (ietf pipeline): - Context builder assembles ideas, RFC foundations, similar drafts, ecosystem vision - Generator produces outlines + sections using rich context with Claude - Quality gates: novelty (embedding similarity), references, format, self-rating - Family coordinator generates 5-draft ecosystem (AEM/ATD/HITL/AEPB/APAE) - I-D formatter with proper headers, references, 72-char wrapping Living Standards Observatory (ietf observatory): - Source abstraction with IETF + W3C fetchers - 7-step update pipeline: snapshot, fetch, analyze, embed, ideas, gaps, record - Static GitHub Pages dashboard (explorer, gap tracker, timeline) - Weekly CI/CD automation via GitHub Actions Also includes: - 361 drafts (expanded from 260 with 6 new keywords), 403 authors, 1,262 ideas, 12 gaps - Blog series (8 posts planned), reports, arXiv paper figures - Agent team infrastructure (CLAUDE.md, scripts, dev journal) - 5 new DB tables, schema migration, ~15 new query methods Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
110
docs/index.html
Normal file
110
docs/index.html
Normal file
@@ -0,0 +1,110 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Living Standards Observatory</title>
|
||||
<link rel="stylesheet" href="assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="container">
|
||||
<h1>Living Standards Observatory</h1>
|
||||
<nav>
|
||||
<a href="index.html" class="active">Dashboard</a>
|
||||
<a href="observatory/explorer.html">Explorer</a>
|
||||
<a href="observatory/gaps.html">Gaps</a>
|
||||
<a href="observatory/timeline.html">Timeline</a>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
<div class="cards" id="metricsCards">
|
||||
<div class="card"><div class="label">Total Documents</div><div class="value" id="totalDocs">--</div><div class="sub" id="sourceSub"></div></div>
|
||||
<div class="card"><div class="label">Standards Bodies</div><div class="value" id="sourceCount">--</div><div class="sub">Active sources</div></div>
|
||||
<div class="card"><div class="label">Open Gaps</div><div class="value" id="gapCount">--</div><div class="sub">Identified coverage gaps</div></div>
|
||||
<div class="card"><div class="label">Ideas Extracted</div><div class="value" id="ideaCount">--</div><div class="sub">Technical contributions</div></div>
|
||||
<div class="card"><div class="label">Authors Tracked</div><div class="value" id="authorCount">--</div><div class="sub">Individual contributors</div></div>
|
||||
<div class="card"><div class="label">Last Update</div><div class="value" id="lastUpdate" style="font-size:1rem">--</div><div class="sub" id="updateSub"></div></div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-header">Top Rated Documents</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr><th>Score</th><th>Document</th><th>Source</th><th>Date</th><th>Categories</th></tr>
|
||||
</thead>
|
||||
<tbody id="topDrafts"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-header">Critical & High Severity Gaps</div>
|
||||
<div id="gapsList" style="padding: 16px;"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function escHtml(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }
|
||||
function scoreBadge(s) {
|
||||
const cls = s >= 4.0 ? 'score-high' : s >= 3.0 ? 'score-mid' : 'score-low';
|
||||
return '<span class="score-badge ' + cls + '">' + s.toFixed(1) + '</span>';
|
||||
}
|
||||
|
||||
async function init() {
|
||||
const [obs, drafts, gaps] = await Promise.all([
|
||||
fetch('data/observatory.json').then(r => r.json()),
|
||||
fetch('data/drafts.json').then(r => r.json()),
|
||||
fetch('data/gaps.json').then(r => r.json()),
|
||||
]);
|
||||
|
||||
// Metrics
|
||||
document.getElementById('totalDocs').textContent = obs.total_docs;
|
||||
const srcNames = Object.keys(obs.sources || {});
|
||||
document.getElementById('sourceCount').textContent = srcNames.length || 1;
|
||||
document.getElementById('sourceSub').textContent = srcNames.map(s => s.toUpperCase() + ': ' + (obs.sources[s] || 0)).join(' | ') || '';
|
||||
document.getElementById('gapCount').textContent = obs.gaps_count;
|
||||
document.getElementById('ideaCount').textContent = obs.ideas;
|
||||
document.getElementById('authorCount').textContent = obs.authors;
|
||||
if (obs.last_update) {
|
||||
document.getElementById('lastUpdate').textContent = obs.last_update.substring(0, 10);
|
||||
}
|
||||
|
||||
// Top drafts
|
||||
const top = drafts.sort((a, b) => b.score - a.score).slice(0, 15);
|
||||
const tbody = document.getElementById('topDrafts');
|
||||
top.forEach(d => {
|
||||
const tr = document.createElement('tr');
|
||||
const srcClass = 'source-' + (d.source || 'ietf');
|
||||
tr.innerHTML =
|
||||
'<td>' + scoreBadge(d.score) + '</td>' +
|
||||
'<td><a href="' + escHtml(d.url) + '" target="_blank">' + escHtml(d.name) + '</a><br><span class="dim">' + escHtml(d.title.substring(0,80)) + '</span></td>' +
|
||||
'<td><span class="source-badge ' + srcClass + '">' + (d.source || 'ietf').toUpperCase() + '</span></td>' +
|
||||
'<td class="dim">' + d.date + '</td>' +
|
||||
'<td>' + d.categories.map(c => '<span class="cat-badge">' + escHtml(c) + '</span>').join('') + '</td>';
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
// Gaps
|
||||
const gapsList = document.getElementById('gapsList');
|
||||
const critical = (gaps.current || []).filter(g => g.severity === 'critical' || g.severity === 'high');
|
||||
if (critical.length === 0) {
|
||||
gapsList.innerHTML = '<p class="dim">No critical or high severity gaps found.</p>';
|
||||
} else {
|
||||
critical.forEach(g => {
|
||||
const cls = g.severity === 'critical' ? 'critical' : 'high';
|
||||
gapsList.innerHTML +=
|
||||
'<div class="gap-card ' + cls + '">' +
|
||||
'<h3>' + escHtml(g.topic) + '</h3>' +
|
||||
'<p>' + escHtml(g.description) + '</p>' +
|
||||
'<div class="meta"><span class="sev-' + g.severity + '">' + g.severity.toUpperCase() + '</span> · ' + escHtml(g.category || '') + '</div>' +
|
||||
'</div>';
|
||||
});
|
||||
}
|
||||
}
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user