Files
Vijay Janapa Reddi ece6eccf23 feat(vault): massive build — 630 drafts generated, 320 PASS promoted, paper 0.1.1
Phase 1 (analyzer):  top-priority cells: tinyml/parallelism (0/90),
                     tinyml/networking (2/90), mobile/parallelism (0/127),
                     edge/parallelism (12/152), global/L4-L6+ deeply empty.
Phase 2 (loop):      6 iterations, 50 of 80 API calls used, 630 drafts
                     generated (52% PASS / 19% NEEDS_FIX / 26% DROP /
                     ~6% unjudged). Saturation reason: same top-priority
                     cell two iterations in a row — converged. Top-priority
                     decay 2.25 → 2.14 → 2.03 → 1.93 → 1.83 plateaued;
                     generator cannot meaningfully shrink
                     tinyml/specification/L6+ further within current
                     prompt framing. Both halt conditions (gap-threshold
                     0.8, max-calls 80) had headroom; structural
                     convergence fired first. Loop defaults bumped:
                     max-iters 20 → 30, max-calls 60 → 80, batch 12 → 30,
                     calls/iter 3 → 4, judge chunk 15 → 25.
Phase 3 (quality):   Spot-read 4 PASS items + visuals across cloud/edge/
                     mobile/tinyml. All technically sound, math correct,
                     real hardware grounding (MI300X, Jetson Orin,
                     Cortex-M4 BLE), SVGs follow svg-style.md palette.
                     Systemic finding: generator emitted 462 drafts with
                     malformed competency_area values (60 distinct
                     patterns: zones-as-area, bloom-verbs-as-area,
                     underscore hallucinations, dash-form/slash-form
                     concatenations). Resolved by extending
                     fix_competency_areas.py REMAP table; re-run cleanup
                     mapped all 462 to canonical. Root cause —
                     generator skips Pydantic validation at write time —
                     flagged for follow-on fix; not blocking.
Phase 4 (promote):   320 PASS items promoted; bundle 9,224 → 9,544
                     published (exactly +320). Visual assets: 234 in
                     bundle, mirrored to staffml/public/.
Phase 5 (paper):     Cut 0.1.1 release (patch bump: content addition,
                     no schema change). release_hash 0350da5706e6.
                     macros.tex regenerated to 9,544/87 topics/
                     13 areas/11 zones; 4 figures rebuilt; paper.tex
                     zone counts updated (1,583/1,227/1,113 →
                     1,615/1,256/1,144). PDF compiles to 25 pages,
                     no LaTeX errors (citation warnings pre-existing).
Phase 6 (GUI):       All 8 Playwright tests pass on fresh dev server.
                     /practice HTML contains zero malformed area names
                     (down from 60 distinct pre-fix).
Phase 7 (manifest):  vault-manifest.json refreshed: questionCount
                     9224 → 9544, contentHash 539eb877f9cc → 0350da5706e6,
                     track + level distributions updated to match
                     0.1.1 corpus.

Loop run dir: interviews/vault/_validation_results/coverage_loop/20260425_150712
Deferred queue (next session): 120 NEEDS_FIX items carrying judge
fix_suggestions + 165 DROP items, plus the generator validate-at-write fix.

The runbook (vault/docs/MASSIVE_BUILD_RUNBOOK.md) is the methodology
this session followed; can be re-run on any future generation day.
2026-04-25 13:15:41 -04:00

216 lines
8.5 KiB
Python

#!/usr/bin/env python3
"""Phase 0 cleanup: remap malformed `competency_area` values to canonical.
The schema's `competency_area` field is documented as "one of 13 canonical
areas" but is enforced as a free-form string at the LinkML layer. This
left a hole that Gemini-generated questions slipped through: when asked
to populate the field, the model sometimes used the topic name
(`data-pipeline-engineering`) or the zone name (`evaluation`) instead.
This script fixes existing data. The companion change adds a LinkML
permissible_values enum so the same drift cannot reoccur.
Usage:
python3 fix_competency_areas.py --dry-run # preview
python3 fix_competency_areas.py # apply
"""
from __future__ import annotations
import argparse
import sys
from collections import Counter, defaultdict
from pathlib import Path
import yaml
VAULT_DIR = Path(__file__).resolve().parent.parent
QUESTIONS_DIR = VAULT_DIR / "questions"
CANONICAL = {
"deployment", "parallelism", "networking", "latency", "memory",
"compute", "data", "power", "precision", "reliability",
"optimization", "architecture", "cross-cutting",
}
# Best-effort remap from observed malformed values to canonical.
# Built from the audit on 2026-04-25; see GUI screenshot for the
# malformed values that surfaced as area-filter buttons.
REMAP = {
# Topic-name-as-area
"data-pipeline-engineering": "data",
"duty-cycling": "power",
"kv-cache-management": "architecture",
"memory-hierarchy-design": "memory",
"interconnect-topology": "networking",
"network-bandwidth-bottlenecks": "networking",
"pipeline-parallelism": "parallelism",
"queueing-theory": "latency",
"fault-tolerance-checkpointing": "reliability",
"quantization-fundamentals": "precision",
"communication-computation-overlap": "optimization",
"compute-cost-estimation": "compute",
"collective-communication": "networking",
# Zone-name-as-area (mistaken)
"diagnosis": "cross-cutting",
"evaluation": "cross-cutting",
"specification": "cross-cutting",
"realization": "cross-cutting",
# Slash-form (Gemini occasionally output `<track> / <topic>`)
# We remap by topic since the track is always the question's track field.
"edge / data-pipeline-engineering": "data",
"edge data-pipeline-engineering": "data",
"edge / network-bandwidth-bottlenecks": "networking",
"edge network-bandwidth-bottlenecks": "networking",
"edge / pipeline-parallelism": "parallelism",
"edge pipeline-parallelism": "parallelism",
"edge / queueing-theory": "latency",
"edge queueing-theory": "latency",
"mobile / memory-hierarchy-design": "memory",
"mobile memory-hierarchy-design": "memory",
"mobile / quantization-fundamentals": "precision",
"mobile quantization-fundamentals": "precision",
"tinyml / communication-computation-overlap": "optimization",
"tinyml communication-computation-overlap": "optimization",
"tinyml / compute-cost-estimation": "compute",
"tinyml compute-cost-estimation": "compute",
"tinyml / queueing-theory": "latency",
"tinyml queueing-theory": "latency",
"tinyml / memory-hierarchy-design": "memory",
"tinyml memory-hierarchy-design": "memory",
"mobile / duty-cycling": "power",
"mobile duty-cycling": "power",
"mobile / communication-computation-overlap": "optimization",
"mobile communication-computation-overlap": "optimization",
"edge / model-serving-infrastructure": "deployment",
"edge model-serving-infrastructure": "deployment",
# Standalone topic-name-as-area (more)
"model-serving-infrastructure": "deployment",
"distributed-training-economics": "cross-cutting",
"fluency": "cross-cutting", # zone leaked into area field
"mastery": "cross-cutting", # zone leaked into area field
# Bloom-verb-as-area (mistaken — bloom_level field leaked into area)
"implement": "cross-cutting",
"analyze": "cross-cutting",
"design": "cross-cutting",
# Underscore-form hallucinations (Gemini invented snake_case "areas")
"fault_tolerance": "reliability",
"power_management": "power",
"network_architecture": "networking",
"memory_management": "memory",
"memory_architecture": "memory",
"distributed_systems": "parallelism",
"performance_modeling": "optimization",
# Track-prefixed slash-form (more) — extend the existing slash-form table
"tinyml/queueing-theory": "latency",
"tinyml/fault-tolerance-checkpointing": "reliability",
"mobile/queueing-theory": "latency",
"mobile/quantization-fundamentals": "precision",
"mobile/fault-tolerance-checkpointing": "reliability",
"mobile/duty-cycling": "power",
"mobile/data-pipeline-engineering": "data",
"mobile/model-serving-infrastructure": "deployment",
"edge/queueing-theory": "latency",
"edge/compute-cost-estimation": "compute",
"edge/data-pipeline-engineering": "data",
"edge/communication-computation-overlap": "optimization",
"edge/fault-tolerance-checkpointing": "reliability",
# Track-prefixed dash-form ("<track> - <topic>") — new variant this run
"tinyml - duty-cycling": "power",
"tinyml - communication-computation-overlap": "optimization",
"tinyml - quantization-fundamentals": "precision",
"tinyml - model-serving-infrastructure": "deployment",
"tinyml - memory-hierarchy-design": "memory",
"edge - communication-computation-overlap": "optimization",
"edge - quantization-fundamentals": "precision",
"edge - queueing-theory": "latency",
"edge - memory-hierarchy-design": "memory",
"edge - fault-tolerance-checkpointing": "reliability",
"edge - model-serving-infrastructure": "deployment",
"mobile - duty-cycling": "power",
"mobile - data-pipeline-engineering": "data",
"cloud - queueing-theory": "latency",
"cloud - duty-cycling": "power",
"cloud - quantization-fundamentals": "precision",
"cloud - compute-cost-estimation": "compute",
# Capitalised / spaced variants (just in case)
"Data pipeline engineering": "data",
"Duty cycling": "power",
"Memory hierarchy design": "memory",
}
def survey() -> dict[str, list[Path]]:
"""Return malformed_value -> list of files using it."""
bad = defaultdict(list)
for p in QUESTIONS_DIR.glob("*/*.yaml"):
try:
d = yaml.safe_load(p.read_text(encoding="utf-8"))
except Exception:
continue
if not d:
continue
ca = d.get("competency_area")
if ca and ca not in CANONICAL:
bad[ca].append(p)
return bad
def apply_fix(bad: dict[str, list[Path]], dry_run: bool) -> tuple[int, list[str]]:
"""Apply REMAP. Returns (n_fixed, unmapped_values)."""
n_fixed = 0
unmapped = []
for malformed, paths in bad.items():
replacement = REMAP.get(malformed)
if not replacement:
# Try lower-case + dash form
normalized = malformed.lower().replace(" ", "-").replace("/", " / ").strip()
replacement = REMAP.get(normalized)
if not replacement:
unmapped.append(malformed)
continue
for p in paths:
if dry_run:
n_fixed += 1
continue
d = yaml.safe_load(p.read_text(encoding="utf-8"))
d["competency_area"] = replacement
p.write_text(
yaml.safe_dump(d, sort_keys=False, allow_unicode=True),
encoding="utf-8",
)
n_fixed += 1
return n_fixed, unmapped
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--dry-run", action="store_true")
args = parser.parse_args()
bad = survey()
print(f"Malformed `competency_area` values found: {len(bad)} distinct, "
f"{sum(len(ps) for ps in bad.values())} files affected.")
print()
print(f"{'Malformed value':<55} {'→ canonical':<15} {'count':>5}")
print("-" * 75)
for v in sorted(bad, key=lambda k: -len(bad[k])):
rep = REMAP.get(v) or REMAP.get(v.lower().replace(" ", "-").replace("/", " / ").strip()) or "?"
marker = "→" if rep != "?" else "✗"
print(f" {v:<53} {marker} {rep:<13} {len(bad[v]):>5}")
n, unmapped = apply_fix(bad, args.dry_run)
print()
print(f"{'Would fix' if args.dry_run else 'Fixed'}: {n} files")
if unmapped:
print(f"\n!! UNMAPPED values (no remap rule): {len(unmapped)}")
for v in unmapped:
print(f" {v!r}")
print("Add these to REMAP and re-run.")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())