diff --git a/README.md b/README.md index cc4de1bb..3a2275bb 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,11 @@ It turns rough workflows, transcripts, prompts, notes, and runbooks into reusabl - a front-loaded intent dialogue that starts from the user's real work, desired outcome, and quality bar - an automatic GitHub benchmark scan that pulls the top three public repositories first, extracts borrow or avoid patterns, and then asks whether the user has references worth learning from - a generated visual HTML overview for each newly initialized skill -- a compact HTML review viewer for first-pass human review +- a side-by-side HTML review studio for first-pass human review - three high-value next iteration directions after the first package is created - a lightweight feedback log that does not require a full promotion cycle - a baseline compare report for with-skill vs baseline review -- an archetype-aware quickstart that steers new packages toward scaffold, production, library, or governed fits +- a conversation-style, archetype-aware quickstart that steers new packages toward scaffold, production, library, or governed fits - neutral source metadata plus client-specific adapters - governance, promotion, and portability checks built into the default flow diff --git a/docs/README.fr-FR.md b/docs/README.fr-FR.md index 486a2b90..851c4937 100644 --- a/docs/README.fr-FR.md +++ b/docs/README.fr-FR.md @@ -17,7 +17,7 @@ Il transforme des workflows bruts, des transcripts, des prompts, des notes et de - un review viewer HTML compact pour accélérer la première revue humaine - un feedback log léger pour éviter de lancer tout le flux de promotion à chaque tour - un rapport with-skill vs baseline pour visualiser rapidement le gain incrémental -- un quickstart sensible aux archetypes pour orienter un nouveau skill vers scaffold, production, library ou governed +- un quickstart conversationnel, sensible aux archetypes, pour orienter un nouveau skill vers scaffold, production, library ou governed - des métadonnées sources neutres et des adaptateurs spécifiques au client - des contrôles de gouvernance, de promotion et de portabilité intégrés au flux standard diff --git a/docs/README.ja-JP.md b/docs/README.ja-JP.md index a538a8a4..002242e8 100644 --- a/docs/README.ja-JP.md +++ b/docs/README.ja-JP.md @@ -17,7 +17,7 @@ - 初回の人間レビューを助ける、コンパクトな HTML review viewer - 毎回フル promotion flow を通さずに使える軽量 feedback log - 増分価値をすばやく確認できる with-skill vs baseline 比較レポート -- scaffold / production / library / governed を案内する archetype-aware quickstart +- 会話型 discovery flow として scaffold / production / library / governed を案内する archetype-aware quickstart - 中立的なソースメタデータとクライアント別アダプタ - ガバナンス、昇格判定、portability チェックを標準フローに内蔵 diff --git a/docs/README.ru-RU.md b/docs/README.ru-RU.md index e9fab5ad..98360468 100644 --- a/docs/README.ru-RU.md +++ b/docs/README.ru-RU.md @@ -17,7 +17,7 @@ - компактным HTML review viewer для быстрой первой ручной оценки - легким feedback log, чтобы не запускать полный promotion flow на каждом цикле - отчетом with-skill vs baseline для быстрого сравнения инкрементальной пользы -- archetype-aware quickstart, который помогает выбрать scaffold, production, library или governed форму +- conversation-style archetype-aware quickstart, который ведет пользователя как discovery flow и помогает выбрать scaffold, production, library или governed форму - нейтральными исходными метаданными и клиентскими адаптерами - встроенными проверками governance, promotion и portability в стандартном потоке diff --git a/docs/README.zh-CN.md b/docs/README.zh-CN.md index 6248edf1..60984110 100644 --- a/docs/README.zh-CN.md +++ b/docs/README.zh-CN.md @@ -17,7 +17,7 @@ - 提供一个紧凑的 HTML review viewer,方便第一次人工理解和评审 - 提供一个轻量 feedback log,不必每次都走完整 promotion 流程 - 提供一个 with-skill vs baseline 的对比报告,便于快速看增量收益 -- 提供一个 archetype-aware 的 quickstart,引导新 skill 落到 scaffold、production、library 或 governed 的合适形态 +- 提供一个更像对话发现流程的 archetype-aware quickstart,引导新 skill 落到 scaffold、production、library 或 governed 的合适形态 - 中性的源元数据以及面向不同客户端的适配层 - 内建的治理、晋升和 portability 检查 diff --git a/reports/context_budget.json b/reports/context_budget.json index 8519419f..f0537f09 100644 --- a/reports/context_budget.json +++ b/reports/context_budget.json @@ -6,9 +6,9 @@ "context_budget_tier": "production", "context_budget_limit": 1000, "skill_body_tokens": 824, - "other_text_tokens": 274311, + "other_text_tokens": 276100, "estimated_initial_load_tokens": 1000, - "estimated_total_text_tokens": 275135, + "estimated_total_text_tokens": 276924, "relevant_file_count": 165, "unused_resource_dirs": [], "quality_signal_points": 140, diff --git a/scripts/render_review_viewer.py b/scripts/render_review_viewer.py index 3e81c4c4..6ee72a72 100644 --- a/scripts/render_review_viewer.py +++ b/scripts/render_review_viewer.py @@ -2,6 +2,7 @@ import argparse import html import json +import re from pathlib import Path from render_intent_dialogue import render_intent_dialogue @@ -132,6 +133,67 @@ def benchmark_cards(benchmark: dict) -> list[dict]: return cards +def split_sentences(text: str) -> list[str]: + if not text: + return [] + parts = [item.strip() for item in re.split(r"(?<=[.!?])\s+", " ".join(text.split())) if item.strip()] + return parts + + +def metric_delta(current: int | float, baseline: int | float) -> str: + delta = current - baseline + if delta == 0: + return "0" + return f"{delta:+}" + + +def variant_diff_cards(compare: dict) -> list[dict]: + baseline = compare.get("baseline", {}) + current = compare.get("current_candidate", {}) + winner = compare.get("winner", {}) + variants = [ + ("Baseline", baseline), + ("Current", current), + (f"Winner — {winner.get('label', 'Winner')}", winner), + ] + baseline_sentences = split_sentences(baseline.get("description", "")) + baseline_set = set(baseline_sentences) + baseline_dev = baseline.get("dev", {}).get("total_errors", 0) + baseline_holdout = baseline.get("holdout", {}).get("total_errors", 0) + cards = [] + seen = set() + for label, payload in variants: + if not payload: + continue + unique_key = (payload.get("description"), payload.get("strategy"), label) + if unique_key in seen: + continue + seen.add(unique_key) + description = payload.get("description", "") + sentences = split_sentences(description) + sentence_set = set(sentences) + added = [item for item in sentences if item not in baseline_set][:3] + removed = [item for item in baseline_sentences if item not in sentence_set][:2] + dev_errors = payload.get("dev", {}).get("total_errors", 0) + holdout_errors = payload.get("holdout", {}).get("total_errors", 0) + cards.append( + { + "label": label, + "strategy": payload.get("strategy", "existing"), + "description": description, + "tokens": payload.get("estimated_tokens", 0), + "dev_errors": dev_errors, + "holdout_errors": holdout_errors, + "token_delta": metric_delta(payload.get("estimated_tokens", 0), baseline.get("estimated_tokens", 0)), + "dev_delta": metric_delta(dev_errors, baseline_dev), + "holdout_delta": metric_delta(holdout_errors, baseline_holdout), + "added": added if label != "Baseline" else baseline_sentences[:3], + "removed": removed, + } + ) + return cards + + def render_html(report: dict) -> str: overview = report["overview"] intent = report["intent"] @@ -146,6 +208,7 @@ def render_html(report: dict) -> str: architecture = architecture_steps(overview) compare_table_rows = compare_rows(compare) benchmark_rows = benchmark_cards(benchmark) + variant_cards = variant_diff_cards(compare) strength_items = "".join(f"
No GitHub benchmark scan has been attached to this package yet.
" + variant_diff_html = "" + if variant_cards: + variant_diff_html = "".join( + ( + "{html.escape(item['description'])}
" + "Adds relative to baseline
" + + ( + "No added cues.
" + ) + + "Drops from baseline
" + + ( + "No dropped cues.
" + ) + + "No description optimization compare payload is attached yet.
" + return f""" @@ -365,6 +460,12 @@ def render_html(report: dict) -> str: gap: 16px; margin-top: 16px; }} + .variant-grid {{ + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 16px; + margin-top: 16px; + }} .direction-card {{ padding: 18px; }} @@ -376,6 +477,48 @@ def render_html(report: dict) -> str: color: var(--muted); font-size: 13px; }} + .variant-card {{ + border: 1px solid var(--line); + background: var(--white); + padding: 18px; + }} + .variant-head {{ + display: flex; + justify-content: space-between; + gap: 12px; + align-items: baseline; + }} + .variant-head span {{ + color: var(--muted); + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.06em; + }} + .variant-description {{ + margin: 14px 0; + padding-left: 14px; + border-left: 2px solid var(--line); + color: var(--text); + }} + .variant-metrics {{ + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 14px; + }} + .variant-metrics span {{ + border: 1px solid var(--line); + background: var(--soft); + padding: 6px 10px; + font-size: 12px; + }} + .variant-cues p {{ + margin: 8px 0 6px; + }} + .variant-cues ul {{ + margin: 0 0 12px; + padding-left: 18px; + }} table {{ width: 100%; border-collapse: collapse; @@ -395,7 +538,7 @@ def render_html(report: dict) -> str: color: var(--muted); }} @media (max-width: 1000px) {{ - .arch-grid, .direction-grid, .grid {{ + .arch-grid, .direction-grid, .variant-grid, .grid {{ grid-template-columns: 1fr; }} }} @@ -453,6 +596,11 @@ def render_html(report: dict) -> str: +