Idea quality pipeline, web UI features, academic paper

- Tighten idea extraction prompts (1-4 ideas, no sub-features) reducing
  1,907 ideas to 468 across 434 drafts (78% reduction)
- Add embedding-based dedup (ietf dedup-ideas) for same-draft similarity
- Add novelty scoring (ietf ideas score) and filtering (ietf ideas filter)
  using Claude to rate ideas 1-5, removing 49 generic building blocks
- Final count: 419 high-quality ideas (avg 1.1/draft)
- Web UI: gap explorer with live draft generation and pre-generated demos
- Web UI: D3.js author collaboration network (498 nodes, 1142 edges,
  68 clusters, org filtering, interactive zoom/pan)
- Academic paper: 15-page LaTeX workshop paper analyzing the 434-draft
  AI agent standards landscape
- Save improvement ideas backlog to data/reports/improvement-ideas.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 22:17:57 +01:00
parent 3c3d7e649f
commit 6e3a387778
29 changed files with 6575 additions and 240 deletions

View File

@@ -0,0 +1,89 @@
{% extends "base.html" %}
{% set active_page = "gaps" %}
{% block title %}Gap Explorer — IETF Draft Analyzer{% endblock %}
{% block content %}
<div class="mb-6">
<h1 class="text-2xl font-bold text-white">Gap Explorer</h1>
<p class="text-slate-400 text-sm mt-1">{{ gaps | length }} identified gaps in AI/agent standards coverage — click any gap to explore details or generate a draft</p>
</div>
<!-- Action bar -->
<div class="mb-6 flex flex-wrap gap-3">
<a href="/gaps/demo" class="inline-flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white text-sm font-medium rounded-lg transition">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
View Demo Draft
</a>
{% if generated_drafts %}
<span class="inline-flex items-center px-3 py-2 bg-slate-800 text-slate-400 text-sm rounded-lg">
{{ generated_drafts | length }} draft{{ 's' if generated_drafts | length != 1 }} already generated
</span>
{% endif %}
</div>
<!-- Severity overview -->
{% set ns = namespace(critical=0, high=0, medium=0, low=0) %}
{% for gap in gaps %}
{% if gap.severity == 'critical' %}{% set ns.critical = ns.critical + 1 %}
{% elif gap.severity == 'high' %}{% set ns.high = ns.high + 1 %}
{% elif gap.severity == 'medium' %}{% set ns.medium = ns.medium + 1 %}
{% else %}{% set ns.low = ns.low + 1 %}
{% endif %}
{% endfor %}
<div class="grid grid-cols-2 md:grid-cols-5 gap-4 mb-6">
<div class="stat-card rounded-xl border border-slate-800 p-4">
<div class="text-3xl font-bold text-slate-200">{{ gaps | length }}</div>
<div class="text-xs text-slate-400 mt-1">Total Gaps</div>
</div>
<div class="stat-card rounded-xl border border-red-500/30 p-4">
<div class="text-3xl font-bold text-red-400">{{ ns.critical }}</div>
<div class="text-xs text-red-400/70 mt-1">Critical</div>
</div>
<div class="stat-card rounded-xl border border-orange-500/30 p-4">
<div class="text-3xl font-bold text-orange-400">{{ ns.high }}</div>
<div class="text-xs text-orange-400/70 mt-1">High</div>
</div>
<div class="stat-card rounded-xl border border-yellow-500/30 p-4">
<div class="text-3xl font-bold text-yellow-400">{{ ns.medium }}</div>
<div class="text-xs text-yellow-400/70 mt-1">Medium</div>
</div>
<div class="stat-card rounded-xl border border-green-500/30 p-4">
<div class="text-3xl font-bold text-green-400">{{ ns.low }}</div>
<div class="text-xs text-green-400/70 mt-1">Low</div>
</div>
</div>
<!-- Gap cards sorted by severity -->
<div class="space-y-4">
{% for gap in gaps | sort(attribute='severity') %}
<a href="/gaps/{{ gap.id }}" class="block bg-slate-900 rounded-xl border
{% if gap.severity == 'critical' %}border-red-500/40 hover:border-red-500/60
{% elif gap.severity == 'high' %}border-orange-500/30 hover:border-orange-500/50
{% elif gap.severity == 'medium' %}border-yellow-500/20 hover:border-yellow-500/40
{% else %}border-slate-800 hover:border-slate-700{% endif %}
p-5 transition group">
<div class="flex items-start justify-between gap-3 mb-3">
<h2 class="text-base font-semibold text-white group-hover:text-blue-400 transition">{{ gap.topic }}</h2>
<div class="flex items-center gap-2 shrink-0">
<span class="px-2.5 py-0.5 rounded-full text-xs font-semibold whitespace-nowrap
{% if gap.severity == 'critical' %}bg-red-500/20 text-red-400 ring-1 ring-red-500/30
{% elif gap.severity == 'high' %}bg-orange-500/20 text-orange-400 ring-1 ring-orange-500/30
{% elif gap.severity == 'medium' %}bg-yellow-500/20 text-yellow-400 ring-1 ring-yellow-500/30
{% else %}bg-green-500/20 text-green-400 ring-1 ring-green-500/30{% endif %}">
{{ gap.severity | upper }}
</span>
<svg class="w-4 h-4 text-slate-600 group-hover:text-blue-400 transition" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg>
</div>
</div>
{% if gap.category %}
<span class="inline-block px-2 py-0.5 rounded text-[10px] bg-slate-800 text-slate-400 mb-3 font-medium">{{ gap.category }}</span>
{% endif %}
<p class="text-sm text-slate-400 leading-relaxed">{{ gap.description }}</p>
</a>
{% endfor %}
</div>
{% endblock %}