From 1a9856b7e2e82a239885e4f1a658d4815f21af5e Mon Sep 17 00:00:00 2001 From: huangrt01 Date: Sat, 27 Jun 2026 15:00:22 +0800 Subject: [PATCH] Add bilingual showcase gallery pages --- docs/showcases/README.md | 58 +- .../0617-blocked-p0-safe-rotation.en.html | 381 +++++ .../cases/0617-blocked-p0-safe-rotation.html | 381 +++++ ...19-dynamic-workflow-hardware-agent.en.html | 380 +++++ .../0619-dynamic-workflow-hardware-agent.html | 669 +++++---- .../cases/0619-loopx-self-iteration.en.html | 380 +++++ .../cases/0619-loopx-self-iteration.html | 380 +++++ .../0620-creator-operator-case-spec.en.html | 382 +++++ .../0620-creator-operator-case-spec.html | 382 +++++ .../0623-agent-to-agent-pr-comments.en.html | 380 +++++ .../0623-agent-to-agent-pr-comments.html | 380 +++++ .../0623-overnight-project-refactor.en.html | 380 +++++ .../0623-overnight-project-refactor.html | 380 +++++ .../cases/0624-pr-issue-auto-fix.en.html | 380 +++++ .../cases/0624-pr-issue-auto-fix.html | 380 +++++ .../cases/0627-overnight-pr-batch.en.html | 380 +++++ .../cases/0627-overnight-pr-batch.html | 380 +++++ docs/showcases/index.en.html | 489 +++++++ docs/showcases/index.html | 489 +++++++ docs/showcases/showcase-catalog.json | 602 +++++--- examples/export-frontstage-share-bundle.mjs | 49 +- examples/showcase-catalog-smoke.py | 62 +- examples/showcase-html-pages.py | 1241 +++++++++++++++++ 23 files changed, 8784 insertions(+), 581 deletions(-) create mode 100644 docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html create mode 100644 docs/showcases/cases/0617-blocked-p0-safe-rotation.html create mode 100644 docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html create mode 100644 docs/showcases/cases/0619-loopx-self-iteration.en.html create mode 100644 docs/showcases/cases/0619-loopx-self-iteration.html create mode 100644 docs/showcases/cases/0620-creator-operator-case-spec.en.html create mode 100644 docs/showcases/cases/0620-creator-operator-case-spec.html create mode 100644 docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html create mode 100644 docs/showcases/cases/0623-agent-to-agent-pr-comments.html create mode 100644 docs/showcases/cases/0623-overnight-project-refactor.en.html create mode 100644 docs/showcases/cases/0623-overnight-project-refactor.html create mode 100644 docs/showcases/cases/0624-pr-issue-auto-fix.en.html create mode 100644 docs/showcases/cases/0624-pr-issue-auto-fix.html create mode 100644 docs/showcases/cases/0627-overnight-pr-batch.en.html create mode 100644 docs/showcases/cases/0627-overnight-pr-batch.html create mode 100644 docs/showcases/index.en.html create mode 100644 docs/showcases/index.html create mode 100644 examples/showcase-html-pages.py diff --git a/docs/showcases/README.md b/docs/showcases/README.md index 6d0f3158..929ed9ac 100644 --- a/docs/showcases/README.md +++ b/docs/showcases/README.md @@ -30,8 +30,18 @@ The first creator-operator storyboard is [creator-ops-fake-data-storyboard.md](creator-ops-fake-data-storyboard.md). Its feedback and source-status contract is [creator-ops-feedback-boundary-contract.md](creator-ops-feedback-boundary-contract.md). -The first static frontstage prototype is generated from the catalog with -`python3 examples/showcase-frontstage-prototype.py --output /tmp/loopx-showcases.html`. +The generated showcase gallery lives at [index.html](index.html), with an +English sibling at [index.en.html](index.en.html). Every current showcase case +has a Chinese default page plus an English `.en.html` page. Regenerate those +pages after changing `showcase-catalog.json`: + +```bash +python3 examples/showcase-html-pages.py +python3 examples/showcase-html-pages.py --check +``` + +An older static frontstage prototype can still be generated from the catalog +with `python3 examples/showcase-frontstage-prototype.py --output /tmp/loopx-showcases.html`. The dashboard frontstage now has a separate public-safe share-bundle path for showing a live-looking control-plane board without exposing local state: @@ -68,38 +78,28 @@ the artifact with `python3 examples/showcase-animation-prototype-smoke.py`. ![Hosted LoopX frontstage showing public-safe showcase cases](../assets/frontstage-showcase-first-screen.png) -## Canonical PoC Cards - -| Case | Pattern | Status | Public Surface | -| --- | --- | --- | --- | -| [0617 blocked P0 with safe P1/P2 rotation](cases/0617-blocked-p0-safe-rotation.md) | Blocked priority fallback, concrete user gate, quota discipline | Reproducible synthetic demo | `python3 examples/showcase-0617-blocked-p0-safe-rotation-smoke.py` | -| [0619 LoopX self-iteration loop](cases/0619-loopx-self-iteration.md) | Self-iteration, side-agent scope, evidence writeback | Public Git evidence case | Commit-backed narrative and workload signal | -| [0619 dynamic workflow for hardware-agent development](cases/0619-dynamic-workflow-hardware-agent.html) | Dynamic workflow, multi-agent convergence, shared control plane | Public-safe interactive case | Five hardware-agent cases plus companion notes | - -The catalog order above is the canonical frontstage order for the PoC. It keeps -the public homepage focused on one reproducible control-plane proof, one -commit-backed self-iteration case, and one contributor-approved interactive -workflow case that shows how LoopX coordinates generated scripts and worker -agents under a shared control plane. - -## Additional Public Evidence Cases +## Current Showcase Pages | Case | Pattern | Status | Public Surface | | --- | --- | --- | --- | -| [0623 agent-to-agent PR comment and fix loop](cases/0623-agent-to-agent-pr-comments.md) | Agent handoff, PR comment loop, review packet | Public-safe pattern case | Redacted lifecycle narrative | -| [0623 overnight project refactor](cases/0623-overnight-project-refactor.md) | PR-sized slices, todo follow-up, supersede | Public-safe pattern case | Redacted lifecycle narrative | -| [0624 PR issue automatic fix loop](cases/0624-pr-issue-auto-fix.md) | Issue-fix workflow, repro smoke, reviewer handoff | Public-safe pattern case | Redacted workflow narrative | -| [0627 overnight PR batch with reviewable control](cases/0627-overnight-pr-batch.md) | PR-sized slices, validation writeback, public-boundary discipline | Public Git evidence case | 22 merged commits over a 10-hour public Git window | - -Additional evidence cases stay in the catalog as appendix surfaces, but they -are not part of the first three canonical PoC cards until they gain a -reproducible demo or a deeper public evidence packet. +| [0627 overnight PR batch with reviewable control](cases/0627-overnight-pr-batch.html) ([EN](cases/0627-overnight-pr-batch.en.html)) | PR-sized slices, validation writeback, public-boundary discipline | Public Git evidence case | 22 merged commits over a 10-hour public Git window | +| [0624 PR issue automatic fix loop](cases/0624-pr-issue-auto-fix.html) ([EN](cases/0624-pr-issue-auto-fix.en.html)) | Issue-fix workflow, repro smoke, reviewer handoff | Public-safe pattern case | Redacted workflow narrative | +| [0623 agent-to-agent PR comment and fix loop](cases/0623-agent-to-agent-pr-comments.html) ([EN](cases/0623-agent-to-agent-pr-comments.en.html)) | Agent handoff, PR comment loop, review packet | Public-safe pattern case | Redacted lifecycle narrative | +| [0623 overnight project refactor](cases/0623-overnight-project-refactor.html) ([EN](cases/0623-overnight-project-refactor.en.html)) | PR-sized slices, todo follow-up, supersede | Public-safe pattern case | Redacted lifecycle narrative | +| [0619 dynamic workflow for hardware-agent development](cases/0619-dynamic-workflow-hardware-agent.html) ([EN](cases/0619-dynamic-workflow-hardware-agent.en.html)) | Dynamic workflow, multi-agent convergence, shared control plane | Public-safe interactive case | Five hardware-agent public anchors plus companion notes | +| [0619 LoopX self-iteration loop](cases/0619-loopx-self-iteration.html) ([EN](cases/0619-loopx-self-iteration.en.html)) | Self-iteration, side-agent scope, evidence writeback | Public Git evidence case | Commit-backed narrative and workload signal | +| [0617 blocked P0 with safe P1/P2 rotation](cases/0617-blocked-p0-safe-rotation.html) ([EN](cases/0617-blocked-p0-safe-rotation.en.html)) | Blocked priority fallback, concrete user gate, quota discipline | Reproducible synthetic demo | `python3 examples/showcase-0617-blocked-p0-safe-rotation-smoke.py` | + +The order above mirrors the current Showcase & Good Case packet. The frontend +page for each case uses the same dark control-plane style as the 0619 hardware +agent showcase: a first-viewport proof frame, visible LoopX intervention, story +beats, language switch, and explicit public evidence boundary. ## Appendix Cases | Case | Pattern | Status | Public Surface | | --- | --- | --- | --- | -| [0620 creator-operator long-running agent case](cases/0620-creator-operator-case-spec.md) | Creator-operator workflow, user gate, feedback capture, material library | Synthetic product case spec | [Fake-data storyboard](creator-ops-fake-data-storyboard.md), [feedback contract](creator-ops-feedback-boundary-contract.md) | +| [0620 creator-operator long-running agent case](cases/0620-creator-operator-case-spec.html) ([EN](cases/0620-creator-operator-case-spec.en.html)) | Creator-operator workflow, user gate, feedback capture, material library | Synthetic product case spec | [Fake-data storyboard](creator-ops-fake-data-storyboard.md), [feedback contract](creator-ops-feedback-boundary-contract.md) | Appendix cases are useful product direction, but they should not appear as frontstage top cards until there is real public evidence or an approved @@ -146,10 +146,10 @@ Do commit: - synthetic demos that exercise public LoopX contracts; - explicit `evidence_boundary` notes that keep future authors honest. -## Future Frontend Shape +## Frontend Shape -The catalog is intentionally small enough for a static website to render. -A good first website view would show: +The committed gallery and generated case pages render directly from the +catalog. A good showcase view should keep: - a card grid of cases grouped by pattern family; - a visual timeline for each case: trigger, LoopX state, agent action, diff --git a/docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html b/docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html new file mode 100644 index 00000000..b1bf13e2 --- /dev/null +++ b/docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html @@ -0,0 +1,381 @@ + + + + + + LoopX Showcase: Blocked P0 with safe P1/P2 rotation + + + + +
+ +
+ +
+ +
+
+
+

2026-06-17 / Reproducible demo

+

Blocked P0 with safe P1/P2 rotation

+

A gated P0 lane should not stall a whole long-running goal when safe fallback work exists.

+
+ benchmark-rotation + + reproducibleuser-gatefallback +
+
+ Story + Boundary +
+
+ +
+ + Blocked P0 with safe P1/P2 rotation + + + + operator + agent lane + + benchmark-rotation + trigger + + concrete user todo + todo / quota / evidence + + Reproducible demo + public result + + + + + + + priority lanes with one gated lane and one active fallback lane + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

A blocked P0 decision should not stall safe P1/P2 work.

+
LoopX intervention

concrete user todo, safe fallback, quota control

+ +
+ +
+ +
+
+

Control-Plane Behavior

+
  1. surface the P0 dependency as a concrete user gate
  2. avoid spending on the gated lane
  3. select a non-dependent fallback lane
  4. record both the blocker and the fallback reason
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0617-blocked-p0-safe-rotation.html b/docs/showcases/cases/0617-blocked-p0-safe-rotation.html new file mode 100644 index 00000000..145df756 --- /dev/null +++ b/docs/showcases/cases/0617-blocked-p0-safe-rotation.html @@ -0,0 +1,381 @@ + + + + + + LoopX Showcase: P0 阻塞后的 P1/P2 安全推进 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-17 / 可复现 demo

+

P0 阻塞后的 P1/P2 安全推进

+

当 P0 lane 等待人类决策时,如果存在安全 fallback 工作,整个长跑目标不应该停住。

+
+ benchmark-rotation + + reproducibleuser-gatefallback +
+
+ 故事 + 边界 +
+
+ +
+ + Blocked P0 with safe P1/P2 rotation + + + + operator + agent lane + + benchmark-rotation + 触发 + + concrete user todo、safe fallba + todo / quota / evidence + + 可复现 demo + 公开结果 + + + + + + + P0 gate 留在前台,安全 side path 继续推进 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

被阻塞的 P0 决策不应该阻止安全的 P1/P2 工作继续。

+
LoopX 介入

concrete user todo、safe fallback、quota control

+ +
+ +
+ +
+
+

控制面行为

+
  1. 区分必须等人的 P0 和可验证的安全后续工作
  2. 在 status/should-run contract 中保留 concrete gate
  3. 只在有安全候选和验证边界时继续推进
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html b/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html new file mode 100644 index 00000000..cf0ab6a3 --- /dev/null +++ b/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: Dynamic workflow for hardware-agent development + + + + +
+ +
+ +
+ +
+
+
+

2026-06-19 / Interactive case

+

Dynamic workflow for hardware-agent development

+

A fuzzy long-running engineering goal needs a shared control plane when multiple worker agents participate.

+
+ hardware-agent-development + + interactive-htmlmulti-agenthardware +
+
+ Story + Boundary +
+
+ +
+ + Dynamic workflow for hardware-agent development + + + + operator + agent lane + + hardware-agent-development + trigger + + goal state + todo / quota / evidence + + Interactive case + public result + + + + + + + multiple worker lanes converging through one shared control plane + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

Fuzzy multi-worker engineering goals can converge under one shared control plane.

+
LoopX intervention

goal state, worker handoff, dynamic workflow

+
Public hardware anchors

Claude Code, DUDU, CV32E40P, VeeR EH1, Viterbi

+
+ +
+ +
+
+

Control-Plane Behavior

+
  1. keep durable goal state outside any one chat thread
  2. make ownership, quota, and evidence writeback explicit
  3. let script-generated worker loops continue only after bounded validation
  4. project convergence state and human gates for the operator
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html b/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html index 138ddaef..58b23097 100644 --- a/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html +++ b/docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html @@ -1,323 +1,380 @@ - - + + - LoopX Hardware-Agent Dynamic Workflow + + LoopX Showcase: 动态 workflow:硬件 Agent 开发 + - - - -
- - - - - - - - - - - - - - - - - - -
-
Unpacking...
- - + - +
+

这个案例证明了什么

+
+
证明点

模糊的多 worker 工程目标可以在同一个共享控制面下收敛。

+
LoopX 介入

goal state、worker handoff、dynamic workflow

+
公开硬件锚点

loopx 在芯片开发任务上的实践: Claude Code, DUDU, CV32E40P, VeeR EH1, Viterbi

+
- +
- +
+
+

控制面行为

+
  1. 把 durable goal state 放在任意单个聊天线程之外
  2. 显式管理 ownership、quota 和 evidence writeback
  3. 只有在有边界验证后才允许脚本生成的 worker loop 继续
  4. 向 operator 投影收敛状态和 human gate
+
+ +
+ + + diff --git a/docs/showcases/cases/0619-loopx-self-iteration.en.html b/docs/showcases/cases/0619-loopx-self-iteration.en.html new file mode 100644 index 00000000..a9233221 --- /dev/null +++ b/docs/showcases/cases/0619-loopx-self-iteration.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: LoopX self-iteration loop + + + + +
+ +
+ +
+ +
+
+
+

2026-06-19 / Public evidence

+

LoopX self-iteration loop

+

A high-churn LoopX repo stayed legible while benchmark, product, docs, planning, and side-agent lanes moved in parallel.

+
+ agent-platform-self-improvement + + self-iterationcommit-backedside-agentefficiency-model +
+
+ Story + Boundary +
+
+ +
+ + LoopX self-iteration loop + + + + operator + agent lane + + agent-platform-self-improvem + trigger + + todo + todo / quota / evidence + + Public evidence + public result + + + + + + + many repo lanes flowing through one control plane, with a side-agent lane branching sa + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

A high-churn multi-lane agent repo can keep state, evidence, and boundaries coherent.

+
LoopX intervention

todo, quota, gate, evidence, review packet, frontstage

+ +
+
801public commits
19.6dGit window
59-92dbaseline estimate
3.0-4.7xcalendar compression
+
+ +
+
+

Control-Plane Behavior

+
  1. preserve durable goal, todo, gate, quota, evidence, and run-history state across high repository churn
  2. separate benchmark, productization, documentation, planning, and side-agent lanes into reviewable obligations
  3. register primary and side-agent identities and project side-agent scope through automation prompts
  4. claim and complete scoped todos with public-safe evidence
  5. allow small validated side-agent self-merges while preserving primary review for risky work
  6. keep public showcases and smokes free of private chat, internal docs, raw trajectories, and raw benchmark evidence
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0619-loopx-self-iteration.html b/docs/showcases/cases/0619-loopx-self-iteration.html new file mode 100644 index 00000000..256117d0 --- /dev/null +++ b/docs/showcases/cases/0619-loopx-self-iteration.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: LoopX Meta Agent 自迭代 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-19 / 公开证据

+

LoopX Meta Agent 自迭代

+

在 benchmark、产品、文档、planning 和 side-agent 多线并行时,高 churn 的 LoopX repo 仍然保持可读。

+
+ agent-platform-self-improvement + + self-iterationcommit-backedside-agentefficiency-model +
+
+ 故事 + 边界 +
+
+ +
+ + LoopX self-iteration loop + + + + operator + agent lane + + agent-platform-self-improvem + 触发 + + todo、quota、gate、evidence、revie + todo / quota / evidence + + 公开证据 + 公开结果 + + + + + + + 自迭代 repo 通过 todo、quota 和 evidence rail 保持清醒 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

高 churn 多 lane agent repo 可以保持状态、证据和边界一致。

+
LoopX 介入

todo、quota、gate、evidence、review packet、frontstage

+ +
+
801public commits
19.6dGit window
59-92dbaseline estimate
3.0-4.7xcalendar compression
+
+ +
+
+

控制面行为

+
  1. 用公共 Git 证据表达长期自迭代工作量
  2. 用 todo 和 run history 维持 lane 间可追踪性
  3. 把 efficiency model 写成可审阅而非夸张的产品叙事
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0620-creator-operator-case-spec.en.html b/docs/showcases/cases/0620-creator-operator-case-spec.en.html new file mode 100644 index 00000000..46471e34 --- /dev/null +++ b/docs/showcases/cases/0620-creator-operator-case-spec.en.html @@ -0,0 +1,382 @@ + + + + + + LoopX Showcase: Creator-operator long-running agent case + + + + +
+ +
+ +
+ +
+
+
+

2026-06-20 / Case spec

+

Creator-operator long-running agent case

+

A creator-operator needs a long-running agent loop that keeps research moving while publishing decisions stay gated.

+
+ creator-operations + appendix + creator_operator_workflowgate_aware_continuationfeedback_capturesafe_side_path +
+
+ Story + Boundary +
+
+ +
+ + Creator-operator long-running agent case + + + + operator + agent lane + + creator-operations + trigger + + creator_operator_workflow + todo / quota / evidence + + Case spec + public result + + + + + + + agent lanes converge through one shared control plane + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

A creator-operator needs a long-running agent loop that keeps research moving while publishing decisions stay gated.

+
LoopX intervention

creator_operator_workflow, gate_aware_continuation, feedback_capture, safe_side_path

+ +
+ +
+ +
+
+

Control-Plane Behavior

+
  1. represent the creative objective as durable goal state
  2. separate publishing decisions from safe research and organization work
  3. turn feedback into preference hints, gate decisions, todo updates, or boundary corrections
  4. keep synthetic/public material separate from private notes and unpublished drafts
  5. show the next agent move before another automatic run spends compute
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0620-creator-operator-case-spec.html b/docs/showcases/cases/0620-creator-operator-case-spec.html new file mode 100644 index 00000000..8e978e5a --- /dev/null +++ b/docs/showcases/cases/0620-creator-operator-case-spec.html @@ -0,0 +1,382 @@ + + + + + + LoopX Showcase: 创作者-运营者长跑 Agent 案例 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-20 / 案例规格

+

创作者-运营者长跑 Agent 案例

+

创作者-运营者需要一种长跑 agent loop:研究可以继续,发布决策仍然 gated。

+
+ creator-operations + appendix + creator_operator_workflowgate_aware_continuationfeedback_capturesafe_side_path +
+
+ 故事 + 边界 +
+
+ +
+ + Creator-operator long-running agent case + + + + operator + agent lane + + creator-operations + 触发 + + creator-operator workflow、user + todo / quota / evidence + + 案例规格 + 公开结果 + + + + + + + 研究 side path 继续积累素材,发布 gate 保持在人类手里 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

创作与运营工作可以共享一个 gate-aware 的长期 agent loop。

+
LoopX 介入

creator-operator workflow、user gate、feedback capture、material library

+ +
+ +
+ +
+
+

控制面行为

+
  1. 把创作准备和发布决策拆成不同风险层级
  2. 在 gate 后继续安全的材料整理和反馈归档
  3. 用假数据 storyboard 保护真实用户上下文
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html b/docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html new file mode 100644 index 00000000..6ec1ce00 --- /dev/null +++ b/docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: Agent-to-agent PR comment and fix loop + + + + +
+ +
+ +
+ +
+
+
+

2026-06-23 / Pattern case

+

Agent-to-agent PR comment and fix loop

+

PR review feedback can become an owned agent todo with fix evidence instead of a loose chat reminder.

+
+ pull-request-review + + handoffPR commentclaimed_by +
+
+ Story + Boundary +
+
+ +
+ + Agent-to-agent PR comment and fix loop + + + + operator + agent lane + + pull-request-review + trigger + + claimed_by + todo / quota / evidence + + Pattern case + public result + + + + + + + agent comments hand off through ownership rather than scattered threads + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

Agent lanes can coordinate around PR comments without losing owner review.

+
LoopX intervention

claimed_by, handoff gate, review packet, comment/fix loop

+ +
+ +
+ +
+
+

Control-Plane Behavior

+
  1. turn review feedback into a claimed todo
  2. route implementation through the owning agent lane
  3. record fix and validation evidence in the review packet
  4. keep successor work explicit after the comment is handled
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0623-agent-to-agent-pr-comments.html b/docs/showcases/cases/0623-agent-to-agent-pr-comments.html new file mode 100644 index 00000000..3d865f9c --- /dev/null +++ b/docs/showcases/cases/0623-agent-to-agent-pr-comments.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: Agent-to-agent PR 评论与修复循环 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-23 / 模式案例

+

Agent-to-agent PR 评论与修复循环

+

PR review 反馈可以成为有 owner 的 agent todo 和修复证据,而不是一条松散的聊天提醒。

+
+ pull-request-review + + handoffPR commentclaimed_by +
+
+ 故事 + 边界 +
+
+ +
+ + Agent-to-agent PR comment and fix loop + + + + operator + agent lane + + pull-request-review + 触发 + + claimed_by、handoff gate、review + todo / quota / evidence + + 模式案例 + 公开结果 + + + + + + + agent 评论通过 ownership 交接,而不是散落在线程里 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

多条 agent lane 可以围绕 PR comment 协作,同时保留 owner review。

+
LoopX 介入

claimed_by、handoff gate、review packet、comment/fix loop

+ +
+ +
+ +
+
+

控制面行为

+
  1. 用 claimed_by 把 PR comment 变成明确责任
  2. 把修复证据写回 review packet
  3. 保留 owner handoff,不让 agent 之间互相默认放行
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0623-overnight-project-refactor.en.html b/docs/showcases/cases/0623-overnight-project-refactor.en.html new file mode 100644 index 00000000..1cf67e5a --- /dev/null +++ b/docs/showcases/cases/0623-overnight-project-refactor.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: Overnight project refactor as PR-sized slices + + + + +
+ +
+ +
+ +
+
+
+

2026-06-23 / Pattern case

+

Overnight project refactor as PR-sized slices

+

A broad refactor can run overnight while staying split into human-sized review units.

+
+ repository-refactor + + refactorPR slicestodo evidence +
+
+ Story + Boundary +
+
+ +
+ + Overnight project refactor as PR-sized slices + + + + operator + agent lane + + repository-refactor + trigger + + loop + todo / quota / evidence + + Pattern case + public result + + + + + + + a large refactor travels as a sequence of small reviewable packets + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

Unattended refactors can split into human-sized PR slices instead of one large diff.

+
LoopX intervention

loop, todo follow-up, supersede, PR-sized slices

+ +
+ +
+ +
+
+

Control-Plane Behavior

+
  1. keep the current refactor slice explicit
  2. convert discoveries into follow-up todos
  3. supersede stale tasks when the route changes
  4. validate each slice before merge or handoff
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0623-overnight-project-refactor.html b/docs/showcases/cases/0623-overnight-project-refactor.html new file mode 100644 index 00000000..a26b0aa2 --- /dev/null +++ b/docs/showcases/cases/0623-overnight-project-refactor.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: 一晚上自主重构项目 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-23 / 模式案例

+

一晚上自主重构项目

+

广泛重构可以在夜间推进,但输出仍然要拆成适合人类 review 的小单元。

+
+ repository-refactor + + refactorPR slicestodo evidence +
+
+ 故事 + 边界 +
+
+ +
+ + Overnight project refactor as PR-sized slices + + + + operator + agent lane + + repository-refactor + 触发 + + loop、todo follow-up、supersede、 + todo / quota / evidence + + 模式案例 + 公开结果 + + + + + + + 大型 refactor 沿着一串小型 review packet 前进 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

无人值守的 refactor 可以拆成 PR-sized slice,而不是一个难审的大 diff。

+
LoopX 介入

loop、todo follow-up、supersede、PR-sized slices

+ +
+ +
+ +
+
+

控制面行为

+
  1. 把大范围 refactor 收敛成多个可验证 patch
  2. 用 supersede 记录替换和迁移关系
  3. 每个 slice 都留下下一步和剩余风险
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0624-pr-issue-auto-fix.en.html b/docs/showcases/cases/0624-pr-issue-auto-fix.en.html new file mode 100644 index 00000000..5955965e --- /dev/null +++ b/docs/showcases/cases/0624-pr-issue-auto-fix.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: PR issue automatic fix loop + + + + +
+ +
+ +
+ +
+
+
+

2026-06-24 / Pattern case

+

PR issue automatic fix loop

+

Review feedback should become an ordered repair workflow with repro, fix, validation, and reviewer handoff.

+
+ issue-fix-workflow + + issue fixrepro smokePR review +
+
+ Story + Boundary +
+
+ +
+ + PR issue automatic fix loop + + + + operator + agent lane + + issue-fix-workflow + trigger + + issue-fix workflow + todo / quota / evidence + + Pattern case + public result + + + + + + + issue feedback turns into a closed repair loop with smoke evidence + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

Issue and review feedback can become a controlled executable repair loop.

+
LoopX intervention

issue-fix workflow, command pack, repro smoke, PR review feedback

+ +
+ +
+ +
+
+

Control-Plane Behavior

+
  1. classify the issue or review feedback
  2. create ordered repair todos
  3. keep gated source reads explicit
  4. separate repro, implementation, validation, and reviewer handoff
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0624-pr-issue-auto-fix.html b/docs/showcases/cases/0624-pr-issue-auto-fix.html new file mode 100644 index 00000000..7e796404 --- /dev/null +++ b/docs/showcases/cases/0624-pr-issue-auto-fix.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: PR Issue 自动修复循环 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-24 / 模式案例

+

PR Issue 自动修复循环

+

review 反馈应该进入有 repro、修复、验证和 reviewer handoff 的有序修复 workflow。

+
+ issue-fix-workflow + + issue fixrepro smokePR review +
+
+ 故事 + 边界 +
+
+ +
+ + PR issue automatic fix loop + + + + operator + agent lane + + issue-fix-workflow + 触发 + + issue-fix workflow、command pac + todo / quota / evidence + + 模式案例 + 公开结果 + + + + + + + issue 反馈被闭环成带 smoke 证据的修复轨道 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

Issue 和 review 反馈可以变成受控、可执行的修复循环。

+
LoopX 介入

issue-fix workflow、command pack、repro smoke、PR review feedback

+ +
+ +
+ +
+
+

控制面行为

+
  1. 把 review comment 映射成可 claim 的修复 todo
  2. 保留 repro、fix、validation 三段证据
  3. 把剩余风险交还给 reviewer,而不是默认吞掉
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/cases/0627-overnight-pr-batch.en.html b/docs/showcases/cases/0627-overnight-pr-batch.en.html new file mode 100644 index 00000000..c211a817 --- /dev/null +++ b/docs/showcases/cases/0627-overnight-pr-batch.en.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: Overnight PR batch with reviewable control + + + + +
+ +
+ +
+ +
+
+
+

2026-06-27 / Public evidence

+

Overnight PR batch with reviewable control

+

An overnight LoopX run can produce many PR-sized slices while keeping review, validation, and public evidence boundaries visible.

+
+ agent-platform-self-improvement + + PR batchreview packetpublic boundary +
+
+ Story + Boundary +
+
+ +
+ + Overnight PR batch with reviewable control + + + + operator + agent lane + + agent-platform-self-improvem + trigger + + todo claim + todo / quota / evidence + + Public evidence + public result + + + + + + + parallel PR lanes converge into a reviewable public merge rail + +
+ +
+ +
+

What This Case Proves

+
+
Proof point

High-throughput multi-lane work can stay PR-sized, reviewable, and merge-safe.

+
LoopX intervention

todo claim, review packet, self-merge boundary, focused smoke, public-boundary scan

+ +
+
22merged commits
60files touched
10hpublic Git window
+
+ +
+
+

Control-Plane Behavior

+
  1. keep work broken into PR-sized slices instead of a giant unreviewable diff
  2. tie runtime, docs, and focused smoke updates together when a control-plane contract changes
  3. limit self-merge to narrow validated changes while preserving broader review gates
  4. record public evidence from Git history instead of raw agent logs or private screenshots
  5. keep public/private boundary checks in the showcase path
+
+ +
+
+
Public-safe showcase page generated from docs/showcases/showcase-catalog.json.
+
+ + diff --git a/docs/showcases/cases/0627-overnight-pr-batch.html b/docs/showcases/cases/0627-overnight-pr-batch.html new file mode 100644 index 00000000..f1357e7f --- /dev/null +++ b/docs/showcases/cases/0627-overnight-pr-batch.html @@ -0,0 +1,380 @@ + + + + + + LoopX Showcase: 一晚 PR 批次的可审阅控制 + + + + +
+ +
+ +
+ +
+
+
+

2026-06-27 / 公开证据

+

一晚 PR 批次的可审阅控制

+

一次长时间 LoopX 运行可以产出多条 PR-sized slice,同时让 review、验证和公开证据边界始终可见。

+
+ agent-platform-self-improvement + + PR batchreview packetpublic boundary +
+
+ 故事 + 边界 +
+
+ +
+ + Overnight PR batch with reviewable control + + + + operator + agent lane + + agent-platform-self-improvem + 触发 + + todo claim、review packet、自合并边界 + todo / quota / evidence + + 公开证据 + 公开结果 + + + + + + + 多条 PR lane 汇入一条可审阅的公开合并轨道 + +
+ +
+ +
+

这个案例证明了什么

+
+
证明点

高吞吐多 lane 工作也可以保持 PR 粒度、可审阅、可合并。

+
LoopX 介入

todo claim、review packet、自合并边界、focused smoke、公开边界扫描

+ +
+
22merged commits
60files touched
10hpublic Git window
+
+ +
+
+

控制面行为

+
  1. 把大批量候选工作拆成可命名、可验证、可回滚的 PR 单元
  2. 每条 lane 写回验证证据和 review 边界
  3. 在公开仓库历史中保留可追溯的合并结果
+
+ +
+
+
公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。
+
+ + diff --git a/docs/showcases/index.en.html b/docs/showcases/index.en.html new file mode 100644 index 00000000..4ca1a6a6 --- /dev/null +++ b/docs/showcases/index.en.html @@ -0,0 +1,489 @@ + + + + + + LoopX Showcase Gallery + + + + +
+ +
+ +
+ +
+
+
+

LoopX Showcase Gallery

+

Agent work that stays reviewable.

+

Seven public-safe cases show how LoopX keeps long-running agent work tied to todos, gates, quota, handoffs, validation, review packets, and evidence boundaries.

+ +
+
01 Goal

Open-ended work becomes durable project state.

+
02 Todo

Each lane has ownership, priority, and a bounded next move.

+
03 Gate

Human decisions stay visible without stopping safe work.

+
04 Evidence

Reviewable output links back to validation and public boundaries.

+
+
+ +
+ + LoopX showcase gallery rail + + + showcase catalog + + proof point + + LoopX control + todo / gate / evidence + + case page + + + + 06-27 +06-24 +06-23 +06-23 +06-19 +06-19 +06-17 + +
+ +
+ +
+

Showcase Cases

+

The order mirrors the current Showcase & Good Case packet: high-throughput proof first, then issue-fix, agent-to-agent collaboration, overnight refactor, dynamic hardware workflow, LoopX self-iteration, and blocked-P0 fallback.

+
+ + 7 public cases +
+
+ + +
+ Public evidence + 2026-06-27 +
+

Overnight PR batch with reviewable control

+

An overnight LoopX run can produce many PR-sized slices while keeping review, validation, and public evidence boundaries visible.

+

High-throughput multi-lane work can stay PR-sized, reviewable, and merge-safe.

+
PR batchreview packetpublic boundary
+
+ + + +
+ Pattern case + 2026-06-24 +
+

PR issue automatic fix loop

+

Review feedback should become an ordered repair workflow with repro, fix, validation, and reviewer handoff.

+

Issue and review feedback can become a controlled executable repair loop.

+
issue fixrepro smokePR review
+
+ + + +
+ Pattern case + 2026-06-23 +
+

Agent-to-agent PR comment and fix loop

+

PR review feedback can become an owned agent todo with fix evidence instead of a loose chat reminder.

+

Agent lanes can coordinate around PR comments without losing owner review.

+
handoffPR commentclaimed_by
+
+ + + +
+ Pattern case + 2026-06-23 +
+

Overnight project refactor as PR-sized slices

+

A broad refactor can run overnight while staying split into human-sized review units.

+

Unattended refactors can split into human-sized PR slices instead of one large diff.

+
refactorPR slicestodo evidence
+
+ + + +
+ Interactive case + 2026-06-19 +
+

Dynamic workflow for hardware-agent development

+

A fuzzy long-running engineering goal needs a shared control plane when multiple worker agents participate.

+

Fuzzy multi-worker engineering goals can converge under one shared control plane.

+
interactive-htmlmulti-agenthardware
+
+ + + +
+ Public evidence + 2026-06-19 +
+

LoopX self-iteration loop

+

A high-churn LoopX repo stayed legible while benchmark, product, docs, planning, and side-agent lanes moved in parallel.

+

A high-churn multi-lane agent repo can keep state, evidence, and boundaries coherent.

+
self-iterationcommit-backedside-agentefficiency-model
+
+ + + +
+ Reproducible demo + 2026-06-17 +
+

Blocked P0 with safe P1/P2 rotation

+

A gated P0 lane should not stall a whole long-running goal when safe fallback work exists.

+

A blocked P0 decision should not stall safe P1/P2 work.

+
reproducibleuser-gatefallback
+
+ +
+
+ +
+

Appendix Surface

+

Appendix material keeps product direction visible without mixing synthetic or private-adjacent evidence into the seven public proof cases.

+ +
+ +
+

Public Boundary

+
+

These pages are generated from the public showcase catalog. They do not embed private documents, internal screenshots, raw chats, local active-state bodies, credentials, raw benchmark traces, or internal Lark media URLs.

+
+
+
+
Generated from docs/showcases/showcase-catalog.json. Public case pages are copied into the GitHub Pages frontstage bundle.
+
+ + + diff --git a/docs/showcases/index.html b/docs/showcases/index.html new file mode 100644 index 00000000..03fa386c --- /dev/null +++ b/docs/showcases/index.html @@ -0,0 +1,489 @@ + + + + + + LoopX Showcase Gallery + + + + +
+ +
+ +
+ +
+
+
+

LoopX Showcase Gallery

+

让 Agent 工作保持可审阅。

+

七个公开安全案例展示 LoopX 如何把长跑 agent 工作绑定到 todo、gate、quota、handoff、验证、review packet 和证据边界。

+ +
+
01 Goal

开放目标沉淀为 durable project state。

+
02 Todo

每条 lane 都有 owner、优先级和有边界的下一步。

+
03 Gate

人类决策保持可见,同时不阻塞安全工作。

+
04 Evidence

可审阅输出回链到验证和公开边界。

+
+
+ +
+ + LoopX showcase gallery rail + + + showcase catalog + + 证明点 + + LoopX 控制面 + todo / gate / evidence + + case 页面 + + + + 06-27 +06-24 +06-23 +06-23 +06-19 +06-19 +06-17 + +
+ +
+ +
+

Showcase 案例

+

顺序对齐当前 Showcase & Good Case packet:高吞吐证明、issue fix、agent-to-agent 协作、夜间重构、硬件动态 workflow、LoopX 自迭代和 P0 阻塞 fallback。

+
+ + 7个公开案例 +
+
+ + +
+ 公开证据 + 2026-06-27 +
+

一晚 PR 批次的可审阅控制

+

一次长时间 LoopX 运行可以产出多条 PR-sized slice,同时让 review、验证和公开证据边界始终可见。

+

高吞吐多 lane 工作也可以保持 PR 粒度、可审阅、可合并。

+
PR batchreview packetpublic boundary
+
+ + + +
+ 模式案例 + 2026-06-24 +
+

PR Issue 自动修复循环

+

review 反馈应该进入有 repro、修复、验证和 reviewer handoff 的有序修复 workflow。

+

Issue 和 review 反馈可以变成受控、可执行的修复循环。

+
issue fixrepro smokePR review
+
+ + + +
+ 模式案例 + 2026-06-23 +
+

Agent-to-agent PR 评论与修复循环

+

PR review 反馈可以成为有 owner 的 agent todo 和修复证据,而不是一条松散的聊天提醒。

+

多条 agent lane 可以围绕 PR comment 协作,同时保留 owner review。

+
handoffPR commentclaimed_by
+
+ + + +
+ 模式案例 + 2026-06-23 +
+

一晚上自主重构项目

+

广泛重构可以在夜间推进,但输出仍然要拆成适合人类 review 的小单元。

+

无人值守的 refactor 可以拆成 PR-sized slice,而不是一个难审的大 diff。

+
refactorPR slicestodo evidence
+
+ + + +
+ 交互案例 + 2026-06-19 +
+

动态 workflow:硬件 Agent 开发

+

当多个 worker agent 参与一个模糊的长跑工程目标时,需要共享控制面来保持收敛。

+

模糊的多 worker 工程目标可以在同一个共享控制面下收敛。

+
interactive-htmlmulti-agenthardware
+
+ + + +
+ 公开证据 + 2026-06-19 +
+

LoopX Meta Agent 自迭代

+

在 benchmark、产品、文档、planning 和 side-agent 多线并行时,高 churn 的 LoopX repo 仍然保持可读。

+

高 churn 多 lane agent repo 可以保持状态、证据和边界一致。

+
self-iterationcommit-backedside-agentefficiency-model
+
+ + + +
+ 可复现 demo + 2026-06-17 +
+

P0 阻塞后的 P1/P2 安全推进

+

当 P0 lane 等待人类决策时,如果存在安全 fallback 工作,整个长跑目标不应该停住。

+

被阻塞的 P0 决策不应该阻止安全的 P1/P2 工作继续。

+
reproducibleuser-gatefallback
+
+ +
+
+ +
+

附录案例

+

附录材料保留产品方向,但不把 synthetic 或接近私有边界的证据混入七个公开证明案例。

+ +
+ +
+

公开边界

+
+

这些页面由公开 showcase catalog 生成,不嵌入私有文档、内部截图、原始聊天、本地 active-state、凭据、原始 benchmark trace 或内部文档图片链接。

+
+
+
+
由 docs/showcases/showcase-catalog.json 生成。公开 case 页面会被复制进 GitHub Pages frontstage bundle。
+
+ + + diff --git a/docs/showcases/showcase-catalog.json b/docs/showcases/showcase-catalog.json index ea69e29c..74f89ee3 100644 --- a/docs/showcases/showcase-catalog.json +++ b/docs/showcases/showcase-catalog.json @@ -21,49 +21,330 @@ }, "cases": [ { - "id": "2026-06-17-blocked-p0-safe-rotation", - "date": "2026-06-17", - "title": "Blocked P0 with safe P1/P2 rotation", - "status": "reproducible_synthetic_demo", - "case_page": "docs/showcases/cases/0617-blocked-p0-safe-rotation.md", - "demo_command": "python3 examples/showcase-0617-blocked-p0-safe-rotation-smoke.py", - "domain": "benchmark-rotation", + "id": "2026-06-27-overnight-pr-batch", + "date": "2026-06-27", + "title": "Overnight PR batch with reviewable control", + "status": "public_evidence_case", + "case_page": "docs/showcases/cases/0627-overnight-pr-batch.md", + "demo_command": null, + "domain": "agent-platform-self-improvement", "audience": [ "operator", "agent-platform-developer", - "benchmark-developer" + "technical-lead" ], "pattern_tags": [ - "blocked_priority_fallback", - "concrete_user_gate", - "safe_fallback_work", - "quota_discipline", - "attention_reduction" + "high_throughput_reviewable_work", + "pr_sized_slices", + "self_merge_policy", + "validation_writeback", + "public_boundary" ], - "headline": "A gated P0 lane should not stall a whole long-running goal when safe fallback work exists.", - "problem": "A benchmark lane needed a large local dependency before it could continue, while other no-upload benchmark work remained safe.", + "headline": "An overnight LoopX run can produce many PR-sized slices while keeping review, validation, and public evidence boundaries visible.", + "problem": "High-throughput autonomous work is only useful if the resulting changes remain reviewable, validated, and safe to publish.", "loopx_behavior": [ - "surface the P0 dependency as a concrete user gate", - "avoid spending on the gated lane", - "select a non-dependent fallback lane", - "record both the blocker and the fallback reason" + "keep work broken into PR-sized slices instead of a giant unreviewable diff", + "tie runtime, docs, and focused smoke updates together when a control-plane contract changes", + "limit self-merge to narrow validated changes while preserving broader review gates", + "record public evidence from Git history instead of raw agent logs or private screenshots", + "keep public/private boundary checks in the showcase path" ], - "user_value": "The operator sees exactly what decision is needed while the agent can keep making bounded progress elsewhere.", - "evidence_boundary": "Synthetic public fixture only; no private screenshots, raw tasks, internal links, local image names, or raw run logs.", + "user_value": "The operator can wake up to a compact batch of merged public slices, see what changed, and still trust that gates, validation, and evidence boundaries were not bypassed.", + "workload_signal": { + "scope": "public_repository_window", + "window": { + "from": "2026-06-27T01:29:00+08:00", + "to": "2026-06-27T11:29:00+08:00", + "hours": 10 + }, + "public_git": { + "merged_commits": 22, + "files_touched": 60, + "insertions": 6695, + "deletions": 223, + "commit_messages_with_pr_numbers": 10 + }, + "claim_boundary": "public Git history only; contemporaneous private queue notes are not used as public evidence" + }, + "evidence_boundary": "Public Git evidence only; no private documents, internal screenshots, raw chats, local active-state bodies, raw logs, credentials, or machine-specific paths.", + "appendix_surface": { + "reason": "Public Git evidence case for an overnight throughput window; keep outside the first canonical frontstage cards until each PR slice has a deeper public evidence packet or reproducible demo.", + "public_surface": "appendix_only", + "links": [ + "docs/showcases/cases/0627-overnight-pr-batch.md" + ] + }, + "interactive_page": "docs/showcases/cases/0627-overnight-pr-batch.html", + "showcase_rank": 1, + "showcase_table": { + "proof_point": "High-throughput multi-lane work can stay PR-sized, reviewable, and merge-safe.", + "loopx_intervention": "todo claim, review packet, self-merge boundary, focused smoke, public-boundary scan" + }, "frontend_card": { - "visual_metaphor": "priority lanes with one gated lane and one active fallback lane", - "primary_metric_hint": "attention reduction: user sees one concrete decision instead of reading the whole run log", + "visual_metaphor": "parallel PR lanes converge into a reviewable public merge rail", + "story_beats": [ + "A long overnight window is split into PR-sized public repository slices.", + "Each lane records validation, review boundary, and merge evidence.", + "LoopX keeps throughput visible without hiding reviewer control." + ], "badges": [ - "reproducible", - "user-gate", - "fallback" + "PR batch", + "review packet", + "public boundary" + ] + }, + "interactive_page_zh": "docs/showcases/cases/0627-overnight-pr-batch.html", + "interactive_page_en": "docs/showcases/cases/0627-overnight-pr-batch.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0627-overnight-pr-batch.html", + "en": "docs/showcases/cases/0627-overnight-pr-batch.en.html" + } + }, + { + "id": "2026-06-24-pr-issue-auto-fix", + "date": "2026-06-24", + "title": "PR issue automatic fix loop", + "status": "public_safe_pattern_case", + "case_page": "docs/showcases/cases/0624-pr-issue-auto-fix.md", + "demo_command": null, + "domain": "issue-fix-workflow", + "audience": [ + "operator", + "agent-platform-developer", + "open-source-maintainer" + ], + "pattern_tags": [ + "issue_fix_workflow", + "review_feedback", + "repro_smoke", + "command_pack", + "successor_todo" + ], + "headline": "Review feedback should become an ordered repair workflow with repro, fix, validation, and reviewer handoff.", + "problem": "PR comments and issues are often concrete enough to fix, but unsafe to feed into an agent as unstructured prompt text without routing, repro, and validation.", + "loopx_behavior": [ + "classify the issue or review feedback", + "create ordered repair todos", + "keep gated source reads explicit", + "separate repro, implementation, validation, and reviewer handoff" + ], + "user_value": "The operator can turn a PR issue into a controlled fix loop without manually rewriting the review comment as an agent plan.", + "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw gated issue bodies, internal review notes, local paths, raw logs, credentials, or unpublished repository artifacts.", + "appendix_surface": { + "reason": "Pattern is durable, but keep outside canonical cards until a public issue-fix PR packet and focused smoke are curated together.", + "public_surface": "appendix_only", + "links": [ + "docs/showcases/cases/0624-pr-issue-auto-fix.md" + ] + }, + "interactive_page": "docs/showcases/cases/0624-pr-issue-auto-fix.html", + "showcase_rank": 2, + "showcase_table": { + "proof_point": "Issue and review feedback can become a controlled executable repair loop.", + "loopx_intervention": "issue-fix workflow, command pack, repro smoke, PR review feedback" + }, + "frontend_card": { + "visual_metaphor": "issue feedback turns into a closed repair loop with smoke evidence", + "story_beats": [ + "A reviewer or issue report becomes a concrete repair target.", + "LoopX preserves the repro path, fix scope, and validation command.", + "The PR returns with a focused evidence packet instead of loose chat context." + ], + "badges": [ + "issue fix", + "repro smoke", + "PR review" + ] + }, + "interactive_page_zh": "docs/showcases/cases/0624-pr-issue-auto-fix.html", + "interactive_page_en": "docs/showcases/cases/0624-pr-issue-auto-fix.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0624-pr-issue-auto-fix.html", + "en": "docs/showcases/cases/0624-pr-issue-auto-fix.en.html" + } + }, + { + "id": "2026-06-23-agent-to-agent-pr-comments", + "date": "2026-06-23", + "title": "Agent-to-agent PR comment and fix loop", + "status": "public_safe_pattern_case", + "case_page": "docs/showcases/cases/0623-agent-to-agent-pr-comments.md", + "demo_command": null, + "domain": "pull-request-review", + "audience": [ + "operator", + "agent-platform-developer", + "open-source-maintainer" + ], + "pattern_tags": [ + "agent_to_agent_handoff", + "pr_comment_loop", + "review_packet", + "claimed_todo", + "successor_todo" + ], + "headline": "PR review feedback can become an owned agent todo with fix evidence instead of a loose chat reminder.", + "problem": "Multiple agent lanes can see or act on the same PR feedback, but without ownership and handoff state the comment-to-fix loop becomes hard to audit.", + "loopx_behavior": [ + "turn review feedback into a claimed todo", + "route implementation through the owning agent lane", + "record fix and validation evidence in the review packet", + "keep successor work explicit after the comment is handled" + ], + "user_value": "The operator can let agents coordinate around PR comments without losing final review visibility or fix evidence.", + "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw chats, internal review notes, local state, credentials, or unpublished artifacts.", + "appendix_surface": { + "reason": "Pattern is durable, but the original evidence included private screenshots; keep as appendix until a fully public PR-comment packet is curated.", + "public_surface": "appendix_only", + "links": [ + "docs/showcases/cases/0623-agent-to-agent-pr-comments.md" + ] + }, + "interactive_page": "docs/showcases/cases/0623-agent-to-agent-pr-comments.html", + "showcase_rank": 3, + "showcase_table": { + "proof_point": "Agent lanes can coordinate around PR comments without losing owner review.", + "loopx_intervention": "claimed_by, handoff gate, review packet, comment/fix loop" + }, + "frontend_card": { + "visual_metaphor": "agent comments hand off through ownership rather than scattered threads", + "story_beats": [ + "One agent leaves actionable PR feedback with public-safe context.", + "Another lane claims the follow-up and turns it into a bounded fix.", + "The owner still sees the handoff, evidence, and residual review gate." ], + "badges": [ + "handoff", + "PR comment", + "claimed_by" + ] + }, + "interactive_page_zh": "docs/showcases/cases/0623-agent-to-agent-pr-comments.html", + "interactive_page_en": "docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0623-agent-to-agent-pr-comments.html", + "en": "docs/showcases/cases/0623-agent-to-agent-pr-comments.en.html" + } + }, + { + "id": "2026-06-23-overnight-project-refactor", + "date": "2026-06-23", + "title": "Overnight project refactor as PR-sized slices", + "status": "public_safe_pattern_case", + "case_page": "docs/showcases/cases/0623-overnight-project-refactor.md", + "demo_command": null, + "domain": "repository-refactor", + "audience": [ + "operator", + "agent-platform-developer", + "technical-lead" + ], + "pattern_tags": [ + "long_unattended_goal", + "pr_sized_slices", + "todo_follow_up", + "supersede", + "validation_writeback" + ], + "headline": "A broad refactor can run overnight while staying split into human-sized review units.", + "problem": "Autonomous refactors become risky when discoveries, stale tasks, cleanup, and behavior changes collapse into one broad diff.", + "loopx_behavior": [ + "keep the current refactor slice explicit", + "convert discoveries into follow-up todos", + "supersede stale tasks when the route changes", + "validate each slice before merge or handoff" + ], + "user_value": "The operator can wake up to reviewable PR-sized refactor slices instead of a single giant autonomous diff.", + "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw chats, internal planning notes, local paths, credentials, raw logs, or unpublished project artifacts.", + "appendix_surface": { + "reason": "Pattern is durable, but keep outside canonical cards until public PR slices and validations are curated into a deeper packet.", + "public_surface": "appendix_only", + "links": [ + "docs/showcases/cases/0623-overnight-project-refactor.md" + ] + }, + "interactive_page": "docs/showcases/cases/0623-overnight-project-refactor.html", + "showcase_rank": 4, + "showcase_table": { + "proof_point": "Unattended refactors can split into human-sized PR slices instead of one large diff.", + "loopx_intervention": "loop, todo follow-up, supersede, PR-sized slices" + }, + "frontend_card": { + "visual_metaphor": "a large refactor travels as a sequence of small reviewable packets", "story_beats": [ - "P0 lane is blocked by a user decision", - "LoopX projects the decision as a user todo", - "agent continues safe fallback work", - "state records blocker, fallback, validation, and spend policy" + "Open-ended cleanup is reduced into ordered slices.", + "Superseded or migrated work stays traceable through todo evidence.", + "The result remains reviewable even when progress happens unattended." + ], + "badges": [ + "refactor", + "PR slices", + "todo evidence" ] + }, + "interactive_page_zh": "docs/showcases/cases/0623-overnight-project-refactor.html", + "interactive_page_en": "docs/showcases/cases/0623-overnight-project-refactor.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0623-overnight-project-refactor.html", + "en": "docs/showcases/cases/0623-overnight-project-refactor.en.html" + } + }, + { + "id": "2026-06-19-dynamic-workflow-hardware-agent", + "date": "2026-06-19", + "title": "Dynamic workflow for hardware-agent development", + "status": "public_safe_interactive_case", + "case_page": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.md", + "interactive_page": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html", + "demo_command": null, + "domain": "hardware-agent-development", + "audience": [ + "agent-platform-developer", + "technical-lead", + "open-source-user" + ], + "pattern_tags": [ + "dynamic_workflow", + "multi_agent_coordination", + "shared_control_plane", + "long_unattended_goal", + "convergence" + ], + "headline": "A fuzzy long-running engineering goal needs a shared control plane when multiple worker agents participate.", + "problem": "Specialized engineering work can require multiple agents to split work and converge without losing ownership or state.", + "loopx_behavior": [ + "keep durable goal state outside any one chat thread", + "make ownership, quota, and evidence writeback explicit", + "let script-generated worker loops continue only after bounded validation", + "project convergence state and human gates for the operator" + ], + "user_value": "A contributor-approved public artifact shows how one control plane can coordinate Claude Code, generated scripts, and hardware-agent workers across five long-running engineering cases.", + "evidence_boundary": "Public-safe interactive artifact; no raw chats, screenshots, proprietary design details, private repositories, local paths, task ids, credentials, or unpublished hardware artifacts.", + "frontend_card": { + "visual_metaphor": "multiple worker lanes converging through one shared control plane", + "primary_metric_hint": "five public hardware-agent cases under one control plane", + "badges": [ + "interactive-html", + "multi-agent", + "hardware" + ], + "story_beats": [ + "LoopX owns goal state, quota, todos, claims, evidence, and history", + "Claude Code writes task-specific orchestration scripts under that contract", + "hardware-agent workers perform bounded RTL, simulation, and validation work", + "five public cases show closed tasks, DSE, flagship Fmax optimization, and convergence floors" + ] + }, + "showcase_rank": 5, + "showcase_table": { + "proof_point": "Fuzzy multi-worker engineering goals can converge under one shared control plane.", + "loopx_intervention": "goal state, worker handoff, dynamic workflow" + }, + "interactive_page_zh": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html", + "interactive_page_en": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html", + "en": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.en.html" } }, { @@ -179,222 +460,76 @@ "public Git history is converted into conservative product requirement clusters", "public docs and smokes turn the experience into a reusable case" ] + }, + "interactive_page": "docs/showcases/cases/0619-loopx-self-iteration.html", + "showcase_rank": 6, + "showcase_table": { + "proof_point": "A high-churn multi-lane agent repo can keep state, evidence, and boundaries coherent.", + "loopx_intervention": "todo, quota, gate, evidence, review packet, frontstage" + }, + "interactive_page_zh": "docs/showcases/cases/0619-loopx-self-iteration.html", + "interactive_page_en": "docs/showcases/cases/0619-loopx-self-iteration.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0619-loopx-self-iteration.html", + "en": "docs/showcases/cases/0619-loopx-self-iteration.en.html" } }, { - "id": "2026-06-19-dynamic-workflow-hardware-agent", - "date": "2026-06-19", - "title": "Dynamic workflow for hardware-agent development", - "status": "public_safe_interactive_case", - "case_page": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.md", - "interactive_page": "docs/showcases/cases/0619-dynamic-workflow-hardware-agent.html", - "demo_command": null, - "domain": "hardware-agent-development", + "id": "2026-06-17-blocked-p0-safe-rotation", + "date": "2026-06-17", + "title": "Blocked P0 with safe P1/P2 rotation", + "status": "reproducible_synthetic_demo", + "case_page": "docs/showcases/cases/0617-blocked-p0-safe-rotation.md", + "demo_command": "python3 examples/showcase-0617-blocked-p0-safe-rotation-smoke.py", + "domain": "benchmark-rotation", "audience": [ + "operator", "agent-platform-developer", - "technical-lead", - "open-source-user" + "benchmark-developer" ], "pattern_tags": [ - "dynamic_workflow", - "multi_agent_coordination", - "shared_control_plane", - "long_unattended_goal", - "convergence" + "blocked_priority_fallback", + "concrete_user_gate", + "safe_fallback_work", + "quota_discipline", + "attention_reduction" ], - "headline": "A fuzzy long-running engineering goal needs a shared control plane when multiple worker agents participate.", - "problem": "Specialized engineering work can require multiple agents to split work and converge without losing ownership or state.", + "headline": "A gated P0 lane should not stall a whole long-running goal when safe fallback work exists.", + "problem": "A benchmark lane needed a large local dependency before it could continue, while other no-upload benchmark work remained safe.", "loopx_behavior": [ - "keep durable goal state outside any one chat thread", - "make ownership, quota, and evidence writeback explicit", - "let script-generated worker loops continue only after bounded validation", - "project convergence state and human gates for the operator" + "surface the P0 dependency as a concrete user gate", + "avoid spending on the gated lane", + "select a non-dependent fallback lane", + "record both the blocker and the fallback reason" ], - "user_value": "A contributor-approved public artifact shows how one control plane can coordinate Claude Code, generated scripts, and hardware-agent workers across five long-running engineering cases.", - "evidence_boundary": "Public-safe interactive artifact; no raw chats, screenshots, proprietary design details, private repositories, local paths, task ids, credentials, or unpublished hardware artifacts.", + "user_value": "The operator sees exactly what decision is needed while the agent can keep making bounded progress elsewhere.", + "evidence_boundary": "Synthetic public fixture only; no private screenshots, raw tasks, internal links, local image names, or raw run logs.", "frontend_card": { - "visual_metaphor": "multiple worker lanes converging through one shared control plane", - "primary_metric_hint": "five public hardware-agent cases under one control plane", + "visual_metaphor": "priority lanes with one gated lane and one active fallback lane", + "primary_metric_hint": "attention reduction: user sees one concrete decision instead of reading the whole run log", "badges": [ - "interactive-html", - "multi-agent", - "hardware" + "reproducible", + "user-gate", + "fallback" ], "story_beats": [ - "LoopX owns goal state, quota, todos, claims, evidence, and history", - "Claude Code writes task-specific orchestration scripts under that contract", - "hardware-agent workers perform bounded RTL, simulation, and validation work", - "five public cases show closed tasks, DSE, flagship Fmax optimization, and convergence floors" - ] - } - }, - { - "id": "2026-06-23-agent-to-agent-pr-comments", - "date": "2026-06-23", - "title": "Agent-to-agent PR comment and fix loop", - "status": "public_safe_pattern_case", - "case_page": "docs/showcases/cases/0623-agent-to-agent-pr-comments.md", - "demo_command": null, - "domain": "pull-request-review", - "audience": [ - "operator", - "agent-platform-developer", - "open-source-maintainer" - ], - "pattern_tags": [ - "agent_to_agent_handoff", - "pr_comment_loop", - "review_packet", - "claimed_todo", - "successor_todo" - ], - "headline": "PR review feedback can become an owned agent todo with fix evidence instead of a loose chat reminder.", - "problem": "Multiple agent lanes can see or act on the same PR feedback, but without ownership and handoff state the comment-to-fix loop becomes hard to audit.", - "loopx_behavior": [ - "turn review feedback into a claimed todo", - "route implementation through the owning agent lane", - "record fix and validation evidence in the review packet", - "keep successor work explicit after the comment is handled" - ], - "user_value": "The operator can let agents coordinate around PR comments without losing final review visibility or fix evidence.", - "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw chats, internal review notes, local state, credentials, or unpublished artifacts.", - "appendix_surface": { - "reason": "Pattern is durable, but the original evidence included private screenshots; keep as appendix until a fully public PR-comment packet is curated.", - "public_surface": "appendix_only", - "links": [ - "docs/showcases/cases/0623-agent-to-agent-pr-comments.md" - ] - } - }, - { - "id": "2026-06-23-overnight-project-refactor", - "date": "2026-06-23", - "title": "Overnight project refactor as PR-sized slices", - "status": "public_safe_pattern_case", - "case_page": "docs/showcases/cases/0623-overnight-project-refactor.md", - "demo_command": null, - "domain": "repository-refactor", - "audience": [ - "operator", - "agent-platform-developer", - "technical-lead" - ], - "pattern_tags": [ - "long_unattended_goal", - "pr_sized_slices", - "todo_follow_up", - "supersede", - "validation_writeback" - ], - "headline": "A broad refactor can run overnight while staying split into human-sized review units.", - "problem": "Autonomous refactors become risky when discoveries, stale tasks, cleanup, and behavior changes collapse into one broad diff.", - "loopx_behavior": [ - "keep the current refactor slice explicit", - "convert discoveries into follow-up todos", - "supersede stale tasks when the route changes", - "validate each slice before merge or handoff" - ], - "user_value": "The operator can wake up to reviewable PR-sized refactor slices instead of a single giant autonomous diff.", - "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw chats, internal planning notes, local paths, credentials, raw logs, or unpublished project artifacts.", - "appendix_surface": { - "reason": "Pattern is durable, but keep outside canonical cards until public PR slices and validations are curated into a deeper packet.", - "public_surface": "appendix_only", - "links": [ - "docs/showcases/cases/0623-overnight-project-refactor.md" - ] - } - }, - { - "id": "2026-06-24-pr-issue-auto-fix", - "date": "2026-06-24", - "title": "PR issue automatic fix loop", - "status": "public_safe_pattern_case", - "case_page": "docs/showcases/cases/0624-pr-issue-auto-fix.md", - "demo_command": null, - "domain": "issue-fix-workflow", - "audience": [ - "operator", - "agent-platform-developer", - "open-source-maintainer" - ], - "pattern_tags": [ - "issue_fix_workflow", - "review_feedback", - "repro_smoke", - "command_pack", - "successor_todo" - ], - "headline": "Review feedback should become an ordered repair workflow with repro, fix, validation, and reviewer handoff.", - "problem": "PR comments and issues are often concrete enough to fix, but unsafe to feed into an agent as unstructured prompt text without routing, repro, and validation.", - "loopx_behavior": [ - "classify the issue or review feedback", - "create ordered repair todos", - "keep gated source reads explicit", - "separate repro, implementation, validation, and reviewer handoff" - ], - "user_value": "The operator can turn a PR issue into a controlled fix loop without manually rewriting the review comment as an agent plan.", - "evidence_boundary": "Public-safe pattern case only; no private screenshots, raw gated issue bodies, internal review notes, local paths, raw logs, credentials, or unpublished repository artifacts.", - "appendix_surface": { - "reason": "Pattern is durable, but keep outside canonical cards until a public issue-fix PR packet and focused smoke are curated together.", - "public_surface": "appendix_only", - "links": [ - "docs/showcases/cases/0624-pr-issue-auto-fix.md" + "P0 lane is blocked by a user decision", + "LoopX projects the decision as a user todo", + "agent continues safe fallback work", + "state records blocker, fallback, validation, and spend policy" ] - } - }, - { - "id": "2026-06-27-overnight-pr-batch", - "date": "2026-06-27", - "title": "Overnight PR batch with reviewable control", - "status": "public_evidence_case", - "case_page": "docs/showcases/cases/0627-overnight-pr-batch.md", - "demo_command": null, - "domain": "agent-platform-self-improvement", - "audience": [ - "operator", - "agent-platform-developer", - "technical-lead" - ], - "pattern_tags": [ - "high_throughput_reviewable_work", - "pr_sized_slices", - "self_merge_policy", - "validation_writeback", - "public_boundary" - ], - "headline": "An overnight LoopX run can produce many PR-sized slices while keeping review, validation, and public evidence boundaries visible.", - "problem": "High-throughput autonomous work is only useful if the resulting changes remain reviewable, validated, and safe to publish.", - "loopx_behavior": [ - "keep work broken into PR-sized slices instead of a giant unreviewable diff", - "tie runtime, docs, and focused smoke updates together when a control-plane contract changes", - "limit self-merge to narrow validated changes while preserving broader review gates", - "record public evidence from Git history instead of raw agent logs or private screenshots", - "keep public/private boundary checks in the showcase path" - ], - "user_value": "The operator can wake up to a compact batch of merged public slices, see what changed, and still trust that gates, validation, and evidence boundaries were not bypassed.", - "workload_signal": { - "scope": "public_repository_window", - "window": { - "from": "2026-06-27T01:29:00+08:00", - "to": "2026-06-27T11:29:00+08:00", - "hours": 10 - }, - "public_git": { - "merged_commits": 22, - "files_touched": 60, - "insertions": 6695, - "deletions": 223, - "commit_messages_with_pr_numbers": 10 - }, - "claim_boundary": "public Git history only; contemporaneous private queue notes are not used as public evidence" }, - "evidence_boundary": "Public Git evidence only; no private documents, internal screenshots, raw chats, local active-state bodies, raw logs, credentials, or machine-specific paths.", - "appendix_surface": { - "reason": "Public Git evidence case for an overnight throughput window; keep outside the first canonical frontstage cards until each PR slice has a deeper public evidence packet or reproducible demo.", - "public_surface": "appendix_only", - "links": [ - "docs/showcases/cases/0627-overnight-pr-batch.md" - ] + "interactive_page": "docs/showcases/cases/0617-blocked-p0-safe-rotation.html", + "showcase_rank": 7, + "showcase_table": { + "proof_point": "A blocked P0 decision should not stall safe P1/P2 work.", + "loopx_intervention": "concrete user todo, safe fallback, quota control" + }, + "interactive_page_zh": "docs/showcases/cases/0617-blocked-p0-safe-rotation.html", + "interactive_page_en": "docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0617-blocked-p0-safe-rotation.html", + "en": "docs/showcases/cases/0617-blocked-p0-safe-rotation.en.html" } }, { @@ -439,6 +574,13 @@ "docs/showcases/creator-ops-fake-data-storyboard.md", "docs/showcases/creator-ops-feedback-boundary-contract.md" ] + }, + "interactive_page": "docs/showcases/cases/0620-creator-operator-case-spec.html", + "interactive_page_zh": "docs/showcases/cases/0620-creator-operator-case-spec.html", + "interactive_page_en": "docs/showcases/cases/0620-creator-operator-case-spec.en.html", + "localized_pages": { + "zh": "docs/showcases/cases/0620-creator-operator-case-spec.html", + "en": "docs/showcases/cases/0620-creator-operator-case-spec.en.html" } } ] diff --git a/examples/export-frontstage-share-bundle.mjs b/examples/export-frontstage-share-bundle.mjs index 2d593aa2..66516061 100644 --- a/examples/export-frontstage-share-bundle.mjs +++ b/examples/export-frontstage-share-bundle.mjs @@ -13,6 +13,7 @@ const defaultOutDir = resolve("/tmp", "loopx-frontstage-share-bundle"); const statusFileName = "status.frontstage-share.json"; const manifestFileName = "frontstage-share-manifest.json"; const showcaseCatalogPath = "docs/showcases/showcase-catalog.json"; +const showcaseIndexPath = "docs/showcases/index.html"; const projectionFixturePath = "examples/goal-channel-frontstage-fixture.py"; function parseArgs(argv) { @@ -90,12 +91,23 @@ function validateInteractivePagePath(path) { return path; } +function addInteractivePage(pages, path) { + if (path) { + pages.add(validateInteractivePagePath(path)); + } +} + async function copyInteractiveCasePages(siteDir) { const catalog = JSON.parse(await readFile(resolve(repoRoot, showcaseCatalogPath), "utf8")); const interactivePages = new Set(); for (const item of catalog.cases ?? []) { - if (item.interactive_page) { - interactivePages.add(validateInteractivePagePath(item.interactive_page)); + addInteractivePage(interactivePages, item.interactive_page); + addInteractivePage(interactivePages, item.interactive_page_zh); + addInteractivePage(interactivePages, item.interactive_page_en); + if (item.localized_pages && typeof item.localized_pages === "object") { + for (const pagePath of Object.values(item.localized_pages)) { + addInteractivePage(interactivePages, pagePath); + } } } @@ -108,6 +120,22 @@ async function copyInteractiveCasePages(siteDir) { return Array.from(interactivePages).sort(); } +async function copyShowcaseIndexes(siteDir) { + const indexPaths = [showcaseIndexPath, "docs/showcases/index.en.html"]; + const copied = []; + for (const indexPath of indexPaths) { + const sourcePath = resolve(repoRoot, indexPath); + if (!existsSync(sourcePath)) { + continue; + } + const targetPath = resolve(siteDir, indexPath); + await mkdir(dirname(targetPath), { recursive: true }); + await copyFile(sourcePath, targetPath); + copied.push(indexPath); + } + return copied; +} + async function removeCopiedLiveStatusFiles(siteDir) { for (const entry of await readdir(siteDir, { withFileTypes: true })) { if (!entry.isFile()) { @@ -175,7 +203,7 @@ function buildStatusFixture(projection) { }; } -async function writeShareReadme(outDir, base, interactivePages) { +async function writeShareReadme(outDir, base, interactivePages, showcaseIndexes) { const siteDir = resolve(outDir, "site"); const frontstageUrl = `${base}frontstage/`; const previewBlock = base === "/" @@ -220,9 +248,10 @@ ${previewBlock} ## Publication Boundary - Includes: compiled dashboard assets, \`${statusFileName}\`, direct - \`/frontstage/\` static route support, and catalog-declared interactive - case pages. + \`/frontstage/\` static-route support, the generated showcase gallery, and + catalog-declared interactive case pages. - Primary case source: \`${showcaseCatalogPath}\`. +- Showcase galleries: ${showcaseIndexes.length ? showcaseIndexes.map((path) => `\`${path}\``).join(", ") : "not generated"}. - Interactive case pages: ${interactivePages.length ? interactivePages.map((path) => `\`${path}\``).join(", ") : "none"}. - Demo shell fixture: \`${projectionFixturePath} --format json\`. - Excludes: live registry state, local paths, credentials, raw logs, raw @@ -231,15 +260,17 @@ ${previewBlock} await writeFile(resolve(outDir, "README.md"), readme); } -async function writeManifest(outDir, base, interactivePages) { +async function writeManifest(outDir, base, interactivePages, showcaseIndexes) { const manifest = { schema_version: "loopx_frontstage_share_bundle_v0", base, site_dir: "site", status_fixture: `site/${statusFileName}`, frontstage_entry: "site/frontstage/index.html", + showcase_gallery_entries: showcaseIndexes.map((path) => `site/${path}`), content_sources: { primary_public_story: showcaseCatalogPath, + showcase_galleries: showcaseIndexes, interactive_case_pages: interactivePages, read_only_control_plane_shell: projectionFixturePath, live_status_feed: false, @@ -328,6 +359,7 @@ async function main() { await removeCopiedLiveStatusFiles(siteDir); await copyIndexForFrontstage(siteDir); + const showcaseIndexes = await copyShowcaseIndexes(siteDir); const interactivePages = await copyInteractiveCasePages(siteDir); const projectionOutput = run("python3", [resolve(repoRoot, "examples/goal-channel-frontstage-fixture.py"), "--format", "json"], { @@ -337,8 +369,8 @@ async function main() { const projection = sanitizeProjectionForShare(JSON.parse(projectionOutput)); const statusFixture = buildStatusFixture(projection); await writeFile(resolve(siteDir, statusFileName), `${JSON.stringify(statusFixture, null, 2)}\n`); - await writeShareReadme(outDir, args.base, interactivePages); - await writeManifest(outDir, args.base, interactivePages); + await writeShareReadme(outDir, args.base, interactivePages, showcaseIndexes); + await writeManifest(outDir, args.base, interactivePages, showcaseIndexes); await scanPublicBoundary(outDir); console.log(JSON.stringify({ @@ -346,6 +378,7 @@ async function main() { out_dir: outDir, site_dir: siteDir, frontstage_url: `${args.base}frontstage/`, + showcase_galleries: showcaseIndexes.map((path) => `${args.base}${path}`), status_fixture: `site/${statusFileName}`, }, null, 2)); } diff --git a/examples/showcase-catalog-smoke.py b/examples/showcase-catalog-smoke.py index 70ec9d51..a20115b1 100644 --- a/examples/showcase-catalog-smoke.py +++ b/examples/showcase-catalog-smoke.py @@ -4,13 +4,25 @@ from __future__ import annotations import json +import subprocess from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[1] CATALOG = REPO_ROOT / "docs" / "showcases" / "showcase-catalog.json" SHOWCASES = REPO_ROOT / "docs" / "showcases" / "README.md" +SHOWCASE_GALLERY = REPO_ROOT / "docs" / "showcases" / "index.html" +SHOWCASE_GALLERY_EN = REPO_ROOT / "docs" / "showcases" / "index.en.html" POC_FEEDBACK_LOOP = REPO_ROOT / "docs" / "showcases" / "poc-feedback-case-report-loop.md" +PRIMARY_CASE_ORDER = [ + "2026-06-27-overnight-pr-batch", + "2026-06-24-pr-issue-auto-fix", + "2026-06-23-agent-to-agent-pr-comments", + "2026-06-23-overnight-project-refactor", + "2026-06-19-dynamic-workflow-hardware-agent", + "2026-06-19-loopx-self-iteration", + "2026-06-17-blocked-p0-safe-rotation", +] PRIVATE_MARKERS = tuple( "".join(parts) for parts in ( @@ -37,26 +49,33 @@ def assert_public_safe(path: Path) -> None: assert marker not in text, f"{path}: private marker {marker!r}" +def run_generated_html_check() -> None: + subprocess.run( + ["python3", "examples/showcase-html-pages.py", "--check"], + cwd=REPO_ROOT, + check=True, + ) + + def main() -> int: + run_generated_html_check() catalog = json.loads(read(CATALOG)) assert catalog["schema_version"] == "loopx_showcase_catalog_v0", catalog cases = catalog.get("cases") assert isinstance(cases, list) and len(cases) >= 2, catalog case_ids = {case.get("id") for case in cases} - assert "2026-06-17-blocked-p0-safe-rotation" in case_ids, case_ids - assert "2026-06-19-dynamic-workflow-hardware-agent" in case_ids, case_ids - assert "2026-06-19-loopx-self-iteration" in case_ids, case_ids + assert set(PRIMARY_CASE_ORDER).issubset(case_ids), case_ids frontstage_ids = [case.get("id") for case in cases if isinstance(case.get("frontend_card"), dict)] - assert frontstage_ids[:3] == [ - "2026-06-17-blocked-p0-safe-rotation", - "2026-06-19-loopx-self-iteration", - "2026-06-19-dynamic-workflow-hardware-agent", - ], frontstage_ids + assert frontstage_ids[:7] == PRIMARY_CASE_ORDER, frontstage_ids assert_public_safe(CATALOG) assert_public_safe(SHOWCASES) + assert_public_safe(SHOWCASE_GALLERY) + assert_public_safe(SHOWCASE_GALLERY_EN) assert_public_safe(POC_FEEDBACK_LOOP) + gallery_zh = read(SHOWCASE_GALLERY) + gallery_en = read(SHOWCASE_GALLERY_EN) for case in cases: case_id = str(case.get("id") or "") @@ -78,6 +97,33 @@ def main() -> int: assert appendix.get("reason"), case assert appendix.get("public_surface") == "appendix_only", case + localized_pages = case.get("localized_pages") + assert isinstance(localized_pages, dict), case + zh_page = localized_pages.get("zh") + en_page = localized_pages.get("en") + assert zh_page == case.get("interactive_page"), case + for lang, page_path in (("zh", zh_page), ("en", en_page)): + assert isinstance(page_path, str), case + assert page_path.startswith("docs/showcases/"), case + assert page_path.endswith(".html"), case + path = REPO_ROOT / page_path + assert path.is_file(), case + assert_public_safe(path) + text = read(path) + if lang == "zh": + assert "English" in text, case_id + assert path.name in gallery_zh, case_id + else: + assert "中文" in text, case_id + assert path.name in gallery_en, case_id + + if case_id in PRIMARY_CASE_ORDER: + interactive_page = case.get("interactive_page") + assert isinstance(interactive_page, str), case + interactive_path = REPO_ROOT / interactive_page + assert interactive_path.is_file(), case + assert_public_safe(interactive_path) + demo_command = case.get("demo_command") if case.get("status") == "reproducible_synthetic_demo": assert isinstance(demo_command, str) and demo_command.startswith("python3 examples/"), case diff --git a/examples/showcase-html-pages.py b/examples/showcase-html-pages.py new file mode 100644 index 00000000..04c3ede8 --- /dev/null +++ b/examples/showcase-html-pages.py @@ -0,0 +1,1241 @@ +#!/usr/bin/env python3 +"""Generate public-safe LoopX showcase HTML pages from the catalog.""" + +from __future__ import annotations + +import argparse +import html +import json +import os +import re +from pathlib import Path +from typing import Any + + +REPO_ROOT = Path(__file__).resolve().parents[1] +CATALOG = REPO_ROOT / "docs" / "showcases" / "showcase-catalog.json" +SHOWCASE_DIR = REPO_ROOT / "docs" / "showcases" +CASES_DIR = SHOWCASE_DIR / "cases" + +PRIMARY_CASE_ORDER = [ + "2026-06-27-overnight-pr-batch", + "2026-06-24-pr-issue-auto-fix", + "2026-06-23-agent-to-agent-pr-comments", + "2026-06-23-overnight-project-refactor", + "2026-06-19-dynamic-workflow-hardware-agent", + "2026-06-19-loopx-self-iteration", + "2026-06-17-blocked-p0-safe-rotation", +] + +FALLBACK_SHOWCASE_TABLE = { + "2026-06-27-overnight-pr-batch": { + "proof_point": "High-throughput multi-lane work can stay PR-sized, reviewable, and merge-safe.", + "loopx_intervention": "todo claim, review packet, self-merge boundary, focused smoke, public-boundary scan", + }, + "2026-06-24-pr-issue-auto-fix": { + "proof_point": "Issue and review feedback can become a controlled executable repair loop.", + "loopx_intervention": "issue-fix workflow, command pack, repro smoke, PR review feedback", + }, + "2026-06-23-agent-to-agent-pr-comments": { + "proof_point": "Agent lanes can coordinate around PR comments without losing owner review.", + "loopx_intervention": "claimed_by, handoff gate, review packet, comment/fix loop", + }, + "2026-06-23-overnight-project-refactor": { + "proof_point": "Unattended refactors can split into human-sized PR slices instead of one large diff.", + "loopx_intervention": "loop, todo follow-up, supersede, PR-sized slices", + }, + "2026-06-19-dynamic-workflow-hardware-agent": { + "proof_point": "Fuzzy multi-worker engineering goals can converge under one shared control plane.", + "loopx_intervention": "goal state, worker handoff, dynamic workflow", + }, + "2026-06-19-loopx-self-iteration": { + "proof_point": "A high-churn multi-lane agent repo can keep state, evidence, and boundaries coherent.", + "loopx_intervention": "todo, quota, gate, evidence, review packet, frontstage", + }, + "2026-06-17-blocked-p0-safe-rotation": { + "proof_point": "A blocked P0 decision should not stall safe P1/P2 work.", + "loopx_intervention": "concrete user todo, safe fallback, quota control", + }, +} + +DEFAULT_FRONTEND_CARDS = { + "2026-06-27-overnight-pr-batch": { + "visual_metaphor": "parallel PR lanes converge into a reviewable public merge rail", + "story_beats": [ + "A long overnight window is split into PR-sized public repository slices.", + "Each lane records validation, review boundary, and merge evidence.", + "LoopX keeps throughput visible without hiding reviewer control.", + ], + "badges": ["PR batch", "review packet", "public boundary"], + }, + "2026-06-24-pr-issue-auto-fix": { + "visual_metaphor": "issue feedback turns into a closed repair loop with smoke evidence", + "story_beats": [ + "A reviewer or issue report becomes a concrete repair target.", + "LoopX preserves the repro path, fix scope, and validation command.", + "The PR returns with a focused evidence packet instead of loose chat context.", + ], + "badges": ["issue fix", "repro smoke", "PR review"], + }, + "2026-06-23-agent-to-agent-pr-comments": { + "visual_metaphor": "agent comments hand off through ownership rather than scattered threads", + "story_beats": [ + "One agent leaves actionable PR feedback with public-safe context.", + "Another lane claims the follow-up and turns it into a bounded fix.", + "The owner still sees the handoff, evidence, and residual review gate.", + ], + "badges": ["handoff", "PR comment", "claimed_by"], + }, + "2026-06-23-overnight-project-refactor": { + "visual_metaphor": "a large refactor travels as a sequence of small reviewable packets", + "story_beats": [ + "Open-ended cleanup is reduced into ordered slices.", + "Superseded or migrated work stays traceable through todo evidence.", + "The result remains reviewable even when progress happens unattended.", + ], + "badges": ["refactor", "PR slices", "todo evidence"], + }, +} + +ZH_CASE_COPY = { + "2026-06-27-overnight-pr-batch": { + "title": "一晚 PR 批次的可审阅控制", + "headline": "一次长时间 LoopX 运行可以产出多条 PR-sized slice,同时让 review、验证和公开证据边界始终可见。", + "proof_point": "高吞吐多 lane 工作也可以保持 PR 粒度、可审阅、可合并。", + "loopx_intervention": "todo claim、review packet、自合并边界、focused smoke、公开边界扫描", + "visual_metaphor": "多条 PR lane 汇入一条可审阅的公开合并轨道", + "story_beats": [ + "一整晚的开放工作被切成适合 review 的公开仓库 PR slice。", + "每条 lane 都记录验证、review 边界和合并证据。", + "LoopX 让吞吐量可见,同时不抹掉 reviewer 的控制权。", + ], + "loopx_behavior": [ + "把大批量候选工作拆成可命名、可验证、可回滚的 PR 单元", + "每条 lane 写回验证证据和 review 边界", + "在公开仓库历史中保留可追溯的合并结果", + ], + "evidence_boundary": "只使用公开 Git 历史、PR 元数据和公开安全摘要;不提交内部状态、原始聊天、私有截图或本地运行证据。", + }, + "2026-06-24-pr-issue-auto-fix": { + "title": "PR Issue 自动修复循环", + "headline": "review 反馈应该进入有 repro、修复、验证和 reviewer handoff 的有序修复 workflow。", + "proof_point": "Issue 和 review 反馈可以变成受控、可执行的修复循环。", + "loopx_intervention": "issue-fix workflow、command pack、repro smoke、PR review feedback", + "visual_metaphor": "issue 反馈被闭环成带 smoke 证据的修复轨道", + "story_beats": [ + "reviewer 或 issue 报告先变成一个具体修复目标。", + "LoopX 保存 repro 路径、修复范围和验证命令。", + "PR 回来时带着聚焦证据,而不是散落在聊天里的上下文。", + ], + "loopx_behavior": [ + "把 review comment 映射成可 claim 的修复 todo", + "保留 repro、fix、validation 三段证据", + "把剩余风险交还给 reviewer,而不是默认吞掉", + ], + "evidence_boundary": "公开页面只描述可复用的 issue-fix 模式和公开安全验证;不包含私有 issue 内容、内部 reviewer 语境或本地日志。", + }, + "2026-06-23-agent-to-agent-pr-comments": { + "title": "Agent-to-agent PR 评论与修复循环", + "headline": "PR review 反馈可以成为有 owner 的 agent todo 和修复证据,而不是一条松散的聊天提醒。", + "proof_point": "多条 agent lane 可以围绕 PR comment 协作,同时保留 owner review。", + "loopx_intervention": "claimed_by、handoff gate、review packet、comment/fix loop", + "visual_metaphor": "agent 评论通过 ownership 交接,而不是散落在线程里", + "story_beats": [ + "一个 agent 留下带公开安全上下文的可执行 PR 反馈。", + "另一条 lane claim 后续工作,并把它变成有边界的修复。", + "owner 仍然能看到 handoff、证据和剩余 review gate。", + ], + "loopx_behavior": [ + "用 claimed_by 把 PR comment 变成明确责任", + "把修复证据写回 review packet", + "保留 owner handoff,不让 agent 之间互相默认放行", + ], + "evidence_boundary": "公开页面只展示 agent handoff 的模式;不暴露私有评论、内部 reviewer 名单、原始截图或本地状态。", + }, + "2026-06-23-overnight-project-refactor": { + "title": "一晚上自主重构项目", + "headline": "广泛重构可以在夜间推进,但输出仍然要拆成适合人类 review 的小单元。", + "proof_point": "无人值守的 refactor 可以拆成 PR-sized slice,而不是一个难审的大 diff。", + "loopx_intervention": "loop、todo follow-up、supersede、PR-sized slices", + "visual_metaphor": "大型 refactor 沿着一串小型 review packet 前进", + "story_beats": [ + "开放式 cleanup 先被降解为有顺序的 slice。", + "被 supersede 或迁移的工作通过 todo 证据保持可追踪。", + "即使进展发生在夜间,结果仍然保持可审阅。", + ], + "loopx_behavior": [ + "把大范围 refactor 收敛成多个可验证 patch", + "用 supersede 记录替换和迁移关系", + "每个 slice 都留下下一步和剩余风险", + ], + "evidence_boundary": "公开页面只保留 refactor 控制面模式;不提交内部计划、私有状态叙事或原始运行轨迹。", + }, + "2026-06-19-dynamic-workflow-hardware-agent": { + "title": "动态 workflow:硬件 Agent 开发", + "headline": "当多个 worker agent 参与一个模糊的长跑工程目标时,需要共享控制面来保持收敛。", + "proof_point": "模糊的多 worker 工程目标可以在同一个共享控制面下收敛。", + "loopx_intervention": "goal state、worker handoff、dynamic workflow", + "visual_metaphor": "多条 worker lane 汇入同一个共享控制面", + "story_beats": [ + "LoopX 持有 goal state、quota、todo、claim、evidence 和 history。", + "Claude Code 在这个契约下编写任务级 orchestration script。", + "hardware-agent worker 执行有边界的 RTL、simulation 和 validation 工作。", + "五个公开 case 展示 closed task、DSE、旗舰 Fmax 优化和收敛下限。", + ], + "loopx_behavior": [ + "把 durable goal state 放在任意单个聊天线程之外", + "显式管理 ownership、quota 和 evidence writeback", + "只有在有边界验证后才允许脚本生成的 worker loop 继续", + "向 operator 投影收敛状态和 human gate", + ], + "evidence_boundary": "公开安全交互 artifact;不包含原始聊天、截图、专有设计细节、私有仓库、本地路径、task id、凭据或未发布硬件 artifact。", + }, + "2026-06-19-loopx-self-iteration": { + "title": "LoopX Meta Agent 自迭代", + "headline": "在 benchmark、产品、文档、planning 和 side-agent 多线并行时,高 churn 的 LoopX repo 仍然保持可读。", + "proof_point": "高 churn 多 lane agent repo 可以保持状态、证据和边界一致。", + "loopx_intervention": "todo、quota、gate、evidence、review packet、frontstage", + "visual_metaphor": "自迭代 repo 通过 todo、quota 和 evidence rail 保持清醒", + "story_beats": [ + "多条 lane 同时推进 benchmark、产品能力、文档和规划。", + "LoopX 把 user gate、agent claim 和验证证据投影到同一控制面。", + "公开 Git 历史提供工作量信号,私有运行细节留在边界外。", + ], + "loopx_behavior": [ + "用公共 Git 证据表达长期自迭代工作量", + "用 todo 和 run history 维持 lane 间可追踪性", + "把 efficiency model 写成可审阅而非夸张的产品叙事", + ], + "evidence_boundary": "只使用公开仓库历史和公开安全叙事;不包含内部目标状态、原始 heartbeat、私有计划或本地运行数据。", + }, + "2026-06-17-blocked-p0-safe-rotation": { + "title": "P0 阻塞后的 P1/P2 安全推进", + "headline": "当 P0 lane 等待人类决策时,如果存在安全 fallback 工作,整个长跑目标不应该停住。", + "proof_point": "被阻塞的 P0 决策不应该阻止安全的 P1/P2 工作继续。", + "loopx_intervention": "concrete user todo、safe fallback、quota control", + "visual_metaphor": "P0 gate 留在前台,安全 side path 继续推进", + "story_beats": [ + "P0 决策被投影成具体 user todo,而不是笼统 owner gate。", + "LoopX 在安全范围内继续 P1/P2 候选工作。", + "quota 和 evidence writeback 限制无人值守工作的节奏。", + ], + "loopx_behavior": [ + "区分必须等人的 P0 和可验证的安全后续工作", + "在 status/should-run contract 中保留 concrete gate", + "只在有安全候选和验证边界时继续推进", + ], + "evidence_boundary": "使用合成 demo 证明控制面行为;不依赖真实私有阻塞事项、内部任务正文或本地运行状态。", + }, + "2026-06-20-creator-operator-case-spec": { + "title": "创作者-运营者长跑 Agent 案例", + "headline": "创作者-运营者需要一种长跑 agent loop:研究可以继续,发布决策仍然 gated。", + "proof_point": "创作与运营工作可以共享一个 gate-aware 的长期 agent loop。", + "loopx_intervention": "creator-operator workflow、user gate、feedback capture、material library", + "visual_metaphor": "研究 side path 继续积累素材,发布 gate 保持在人类手里", + "story_beats": [ + "素材整理和研究探索可以作为安全 side path 继续。", + "发布、外发或品牌判断仍然停在 owner gate。", + "反馈契约把用户体验沉淀成可复用材料库。", + ], + "loopx_behavior": [ + "把创作准备和发布决策拆成不同风险层级", + "在 gate 后继续安全的材料整理和反馈归档", + "用假数据 storyboard 保护真实用户上下文", + ], + "evidence_boundary": "这是 synthetic product case spec;不代表真实私有用户故事,也不包含内部素材、客户信息或未授权截图。", + }, +} + +UI = { + "en": { + "html_lang": "en", + "language_label": "中文", + "cases_nav": "Cases", + "readme_nav": "README", + "catalog_nav": "Catalog", + "story": "Story", + "boundary": "Boundary", + "proof_title": "What This Case Proves", + "proof_point": "Proof point", + "loopx_intervention": "LoopX intervention", + "hardware_anchors": "Public hardware anchors", + "behavior": "Control-Plane Behavior", + "story_beats": "Story Beats", + "evidence_boundary": "Evidence Boundary", + "narrative_note": "Narrative note", + "storyboard": "Storyboard", + "feedback_contract": "Feedback contract", + "footer_case": "Public-safe showcase page generated from docs/showcases/showcase-catalog.json.", + "gallery_eyebrow": "LoopX Showcase Gallery", + "gallery_title": "Agent work that stays reviewable.", + "gallery_copy": "Seven public-safe cases show how LoopX keeps long-running agent work tied to todos, gates, quota, handoffs, validation, review packets, and evidence boundaries.", + "browse_cases": "Browse cases", + "open_catalog": "Open catalog", + "control_steps": [ + ("01 Goal", "Open-ended work becomes durable project state."), + ("02 Todo", "Each lane has ownership, priority, and a bounded next move."), + ("03 Gate", "Human decisions stay visible without stopping safe work."), + ("04 Evidence", "Reviewable output links back to validation and public boundaries."), + ], + "showcase_cases": "Showcase Cases", + "section_lede": "The order mirrors the current Showcase & Good Case packet: high-throughput proof first, then issue-fix, agent-to-agent collaboration, overnight refactor, dynamic hardware workflow, LoopX self-iteration, and blocked-P0 fallback.", + "search_placeholder": "Search cases, patterns, or LoopX interventions", + "public_cases": "public cases", + "appendix_surface": "Appendix Surface", + "appendix_lede": "Appendix material keeps product direction visible without mixing synthetic or private-adjacent evidence into the seven public proof cases.", + "public_boundary": "Public Boundary", + "public_boundary_copy": "These pages are generated from the public showcase catalog. They do not embed private documents, internal screenshots, raw chats, local active-state bodies, credentials, raw benchmark traces, or internal Lark media URLs.", + "footer_index": "Generated from docs/showcases/showcase-catalog.json. Public case pages are copied into the GitHub Pages frontstage bundle.", + "graph_operator": "operator + agent lane", + "graph_trigger": "trigger", + "graph_result": "public result", + "graph_control": "todo / quota / evidence", + "index_graph_catalog": "showcase catalog", + "index_graph_proof": "proof point", + "index_graph_control": "LoopX control", + "index_graph_case": "case page", + }, + "zh": { + "html_lang": "zh-CN", + "language_label": "English", + "cases_nav": "案例", + "readme_nav": "README", + "catalog_nav": "Catalog", + "story": "故事", + "boundary": "边界", + "proof_title": "这个案例证明了什么", + "proof_point": "证明点", + "loopx_intervention": "LoopX 介入", + "hardware_anchors": "公开硬件锚点", + "behavior": "控制面行为", + "story_beats": "故事节奏", + "evidence_boundary": "证据边界", + "narrative_note": "叙事说明", + "storyboard": "Storyboard", + "feedback_contract": "反馈契约", + "footer_case": "公开安全 showcase 页面,由 docs/showcases/showcase-catalog.json 生成。", + "gallery_eyebrow": "LoopX Showcase Gallery", + "gallery_title": "让 Agent 工作保持可审阅。", + "gallery_copy": "七个公开安全案例展示 LoopX 如何把长跑 agent 工作绑定到 todo、gate、quota、handoff、验证、review packet 和证据边界。", + "browse_cases": "浏览案例", + "open_catalog": "打开 catalog", + "control_steps": [ + ("01 Goal", "开放目标沉淀为 durable project state。"), + ("02 Todo", "每条 lane 都有 owner、优先级和有边界的下一步。"), + ("03 Gate", "人类决策保持可见,同时不阻塞安全工作。"), + ("04 Evidence", "可审阅输出回链到验证和公开边界。"), + ], + "showcase_cases": "Showcase 案例", + "section_lede": "顺序对齐当前 Showcase & Good Case packet:高吞吐证明、issue fix、agent-to-agent 协作、夜间重构、硬件动态 workflow、LoopX 自迭代和 P0 阻塞 fallback。", + "search_placeholder": "搜索案例、模式或 LoopX 介入", + "public_cases": "个公开案例", + "appendix_surface": "附录案例", + "appendix_lede": "附录材料保留产品方向,但不把 synthetic 或接近私有边界的证据混入七个公开证明案例。", + "public_boundary": "公开边界", + "public_boundary_copy": "这些页面由公开 showcase catalog 生成,不嵌入私有文档、内部截图、原始聊天、本地 active-state、凭据、原始 benchmark trace 或内部文档图片链接。", + "footer_index": "由 docs/showcases/showcase-catalog.json 生成。公开 case 页面会被复制进 GitHub Pages frontstage bundle。", + "graph_operator": "operator + agent lane", + "graph_trigger": "触发", + "graph_result": "公开结果", + "graph_control": "todo / quota / evidence", + "index_graph_catalog": "showcase catalog", + "index_graph_proof": "证明点", + "index_graph_control": "LoopX 控制面", + "index_graph_case": "case 页面", + }, +} + +HARDWARE_PUBLIC_ANCHORS = [ + "Claude Code", + "DUDU", + "CV32E40P", + "VeeR EH1", + "Viterbi", +] + +STATUS_LABELS = { + "public_evidence_case": "Public evidence", + "public_safe_interactive_case": "Interactive case", + "public_safe_pattern_case": "Pattern case", + "public_safe_case_spec": "Case spec", + "reproducible_synthetic_demo": "Reproducible demo", +} + + +def esc(value: object) -> str: + return html.escape(str(value), quote=True) + + +def slug(value: object) -> str: + safe = re.sub(r"[^a-z0-9]+", "-", str(value).lower()).strip("-") + return safe or "case" + + +def rel_href(source: Path, target: Path) -> str: + return os.path.relpath(target, source.parent).replace(os.sep, "/") + + +def repo_path(path: str) -> Path: + return (REPO_ROOT / path).resolve() + + +def ui(lang: str, key: str) -> Any: + return UI[lang][key] + + +def case_copy(case: dict[str, Any], lang: str) -> dict[str, Any]: + if lang == "zh": + return ZH_CASE_COPY.get(str(case.get("id")), {}) + return {} + + +def localized(case: dict[str, Any], lang: str, key: str) -> str: + copy = case_copy(case, lang) + value = copy.get(key) + if value is None: + value = case.get(key) + return str(value or "") + + +def localized_list(case: dict[str, Any], lang: str, key: str, fallback: Any) -> list[str]: + copy = case_copy(case, lang) + value = copy.get(key) + if value is None: + value = fallback + return first_items(value, 8) + + +def case_html_path(case: dict[str, Any], lang: str = "zh") -> Path: + interactive_page = case.get("interactive_page") + if lang == "zh" and isinstance(interactive_page, str) and interactive_page: + return repo_path(interactive_page) + case_page = str(case.get("case_page") or "") + if case_page.endswith(".md"): + base = repo_path(case_page[:-3] + ".html") + else: + base = CASES_DIR / f"{slug(case.get('id') or case.get('title'))}.html" + if lang == "en": + return base.with_name(f"{base.stem}.en{base.suffix}") + return base + + +def case_table(case: dict[str, Any], lang: str = "en") -> dict[str, str]: + copy = case_copy(case, lang) + if lang == "zh" and copy: + return { + "proof_point": str(copy.get("proof_point") or ""), + "loopx_intervention": str(copy.get("loopx_intervention") or ""), + } + table = case.get("showcase_table") + if isinstance(table, dict): + return { + "proof_point": str(table.get("proof_point") or ""), + "loopx_intervention": str(table.get("loopx_intervention") or ""), + } + return FALLBACK_SHOWCASE_TABLE.get(str(case.get("id")), { + "proof_point": str(case.get("headline") or ""), + "loopx_intervention": ", ".join(str(value) for value in case.get("pattern_tags", [])[:4]), + }) + + +def ordered_cases(cases: list[dict[str, Any]]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]: + by_id = {str(case.get("id")): case for case in cases} + primary = [by_id[case_id] for case_id in PRIMARY_CASE_ORDER if case_id in by_id] + primary_ids = {str(case.get("id")) for case in primary} + appendix = [case for case in cases if str(case.get("id")) not in primary_ids] + return primary, appendix + + +def first_items(values: Any, limit: int = 4) -> list[str]: + if not isinstance(values, list): + return [] + return [str(value) for value in values[:limit]] + + +def badges(values: list[str]) -> str: + return "".join(f"{esc(value)}" for value in values) + + +ZH_STATUS_LABELS = { + "public_evidence_case": "公开证据", + "public_safe_interactive_case": "交互案例", + "public_safe_pattern_case": "模式案例", + "public_safe_case_spec": "案例规格", + "reproducible_synthetic_demo": "可复现 demo", +} + + +def status_label(case: dict[str, Any], lang: str = "en") -> str: + status = str(case.get("status") or "case") + if lang == "zh": + return ZH_STATUS_LABELS.get(status, status.replace("_", " ")) + return STATUS_LABELS.get(status, status.replace("_", " ").title()) + + +def metric_cards(case: dict[str, Any]) -> str: + workload = case.get("workload_signal") + if not isinstance(workload, dict): + return "" + + cards: list[tuple[str, str]] = [] + public_git = workload.get("public_git") if isinstance(workload.get("public_git"), dict) else {} + whole = workload.get("whole_repository") if isinstance(workload.get("whole_repository"), dict) else {} + public_window = workload.get("public_window") if isinstance(workload.get("public_window"), dict) else {} + window = workload.get("window") if isinstance(workload.get("window"), dict) else {} + efficiency = workload.get("efficiency_model") if isinstance(workload.get("efficiency_model"), dict) else {} + + if public_git.get("merged_commits") is not None: + cards.append((str(public_git["merged_commits"]), "merged commits")) + if public_git.get("files_touched") is not None: + cards.append((str(public_git["files_touched"]), "files touched")) + if window.get("hours") is not None: + cards.append((f"{window['hours']}h", "public Git window")) + if whole.get("commit_count") is not None: + cards.append((str(whole["commit_count"]), "public commits")) + if public_window.get("calendar_days") is not None: + cards.append((f"{public_window['calendar_days']}d", "Git window")) + estimated = efficiency.get("estimated_developer_days") + if isinstance(estimated, dict) and estimated.get("low") and estimated.get("high"): + cards.append((f"{estimated['low']}-{estimated['high']}d", "baseline estimate")) + compression = efficiency.get("single_engineer_calendar_compression") + if isinstance(compression, dict) and compression.get("low") and compression.get("high"): + cards.append((f"{compression['low']}-{compression['high']}x", "calendar compression")) + + if not cards: + return "" + return "".join( + f'
{esc(value)}{esc(label)}
' + for value, label in cards[:4] + ) + + +def behavior_items(case: dict[str, Any], lang: str) -> str: + items = localized_list(case, lang, "loopx_behavior", case.get("loopx_behavior")) + return "".join(f"
  • {esc(item)}
  • " for item in items[:6]) + + +def beat_items(case: dict[str, Any], lang: str) -> str: + frontend = case.get("frontend_card") if isinstance(case.get("frontend_card"), dict) else {} + beats = localized_list(case, lang, "story_beats", frontend.get("story_beats")) + if not beats: + beats = localized_list(case, lang, "loopx_behavior", case.get("loopx_behavior"))[:5] + return "".join( + f'
  • {index:02d}

    {esc(beat)}

  • ' + for index, beat in enumerate(beats, start=1) + ) + + +def case_links(case: dict[str, Any], *, current: Path, lang: str) -> str: + links: list[str] = [] + case_page = case.get("case_page") + if isinstance(case_page, str) and case_page: + links.append( + f'{esc(ui(lang, "narrative_note"))}' + ) + demo = case.get("demo_command") + if isinstance(demo, str) and demo: + links.append(f'{esc(demo)}') + storyboard = case.get("storyboard_path") + if isinstance(storyboard, str) and storyboard: + links.append( + f'{esc(ui(lang, "storyboard"))}' + ) + feedback = case.get("feedback_contract_path") + if isinstance(feedback, str) and feedback: + links.append( + f'{esc(ui(lang, "feedback_contract"))}' + ) + return "\n".join(links) + + +def control_graph(case: dict[str, Any], lang: str) -> str: + frontend = case.get("frontend_card") if isinstance(case.get("frontend_card"), dict) else {} + metaphor = localized(case, lang, "visual_metaphor") or str(frontend.get("visual_metaphor") or "agent lanes converge through one shared control plane") + table = case_table(case, lang) + center = table["loopx_intervention"].split(",")[0].strip() or "LoopX control plane" + left = str(case.get("domain") or "goal") + right = status_label(case, lang) + return f""" +
    + + {esc(case.get("title") or "LoopX showcase diagram")} + + + + {esc(ui(lang, "graph_operator"))} + + {esc(left[:28])} + {esc(ui(lang, "graph_trigger"))} + + {esc(center[:30])} + {esc(ui(lang, "graph_control"))} + + {esc(right[:28])} + {esc(ui(lang, "graph_result"))} + + + + + + + {esc(metaphor[:86])} + +
    + """ + + +def page_css() -> str: + return """ + :root { + color-scheme: dark; + --bg: #0b0b0c; + --panel: #121318; + --panel-2: #171920; + --ink: #f4f2ee; + --muted: #b7bbc7; + --dim: #7f8492; + --line: #343843; + --line-2: #4a4f5e; + --accent: #6e79d6; + --accent-2: #7ed4a8; + --accent-3: #e1b36a; + --danger: #e07a7a; + --max: 1180px; + } + * { box-sizing: border-box; } + html { scroll-behavior: smooth; } + body { + margin: 0; + min-height: 100vh; + background: var(--bg); + color: var(--ink); + font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + letter-spacing: 0; + } + a { color: inherit; } + .page-shell { min-height: 100vh; } + .topbar { + position: sticky; + top: 0; + z-index: 5; + border-bottom: 1px solid rgba(255,255,255,.08); + background: rgba(11,11,12,.92); + backdrop-filter: blur(12px); + } + .topbar-inner { + max-width: var(--max); + margin: 0 auto; + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 14px 22px; + } + .brand { + display: inline-flex; + align-items: center; + gap: 10px; + text-decoration: none; + font-weight: 720; + } + .brand-mark { + width: 30px; + height: 30px; + border: 2px solid var(--accent); + border-radius: 8px; + display: inline-grid; + place-items: center; + color: var(--accent-2); + font-size: 14px; + } + .topbar nav { display: flex; flex-wrap: wrap; gap: 10px; } + .topbar nav a, .link-button { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 34px; + border: 1px solid var(--line-2); + border-radius: 8px; + padding: 8px 11px; + text-decoration: none; + color: var(--ink); + font-size: 13px; + font-weight: 650; + background: rgba(255,255,255,.03); + } + .topbar nav a:hover, .link-button:hover { border-color: var(--accent); } + .link-button.secondary { color: var(--muted); } + main { max-width: var(--max); margin: 0 auto; padding: 38px 22px 70px; } + .hero { + display: grid; + grid-template-columns: minmax(0, .95fr) minmax(380px, 1.05fr); + gap: 28px; + align-items: center; + min-height: min(720px, calc(100vh - 64px)); + padding-bottom: 26px; + } + .eyebrow { + margin: 0 0 14px; + color: var(--accent-2); + font-size: 12px; + font-weight: 750; + text-transform: uppercase; + } + h1 { + margin: 0; + max-width: 760px; + font-size: clamp(44px, 7vw, 94px); + line-height: .91; + letter-spacing: 0; + } + .hero-copy { + margin: 20px 0 0; + max-width: 680px; + color: var(--muted); + font-size: clamp(16px, 2vw, 20px); + line-height: 1.6; + } + .hero-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 24px; } + .hero-actions .primary { + background: var(--ink); + border-color: var(--ink); + color: var(--bg); + } + .meta-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; } + .pill, .badges span, .status-pill { + display: inline-flex; + align-items: center; + min-height: 26px; + border: 1px solid var(--line); + border-radius: 8px; + padding: 5px 8px; + color: var(--muted); + font-size: 12px; + font-weight: 650; + background: rgba(255,255,255,.03); + } + .status-pill { color: var(--accent-2); border-color: rgba(126,212,168,.45); } + .control-graph { + margin: 0; + border: 1px solid var(--line); + border-radius: 8px; + overflow: hidden; + background: #0f1014; + box-shadow: 0 18px 80px rgba(0,0,0,.28); + } + .control-graph svg { display: block; width: 100%; height: auto; } + .graph-bg { fill: #0b0b0c; } + .node { fill: none; stroke: #666b75; stroke-width: 3; } + .node-accent { stroke: var(--accent); } + .node-accent-fill { fill: rgba(110,121,214,.16); stroke: var(--accent); stroke-width: 3; } + .node-label { fill: var(--ink); font-size: 18px; font-weight: 720; } + .node-sub { fill: var(--dim); font-size: 13px; font-weight: 650; } + .line { fill: none; stroke-width: 3; } + .line.muted { stroke: #3a3d42; } + .line.accent { stroke: var(--accent); } + .line.return { stroke: #555b66; } + .dot { fill: var(--accent); } + .dot.alt { fill: var(--accent-3); } + .caption-box { fill: rgba(255,255,255,.035); stroke: rgba(255,255,255,.08); } + .caption { fill: var(--muted); font-size: 13px; font-weight: 650; } + .section { border-top: 1px solid rgba(255,255,255,.08); padding: 34px 0; } + .section h2 { margin: 0 0 18px; font-size: clamp(28px, 4vw, 46px); line-height: 1; } + .section-lede { margin: -6px 0 24px; max-width: 760px; color: var(--muted); line-height: 1.65; } + .metrics, .case-grid, .proof-grid, .link-grid { + display: grid; + gap: 12px; + } + .metrics { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 18px; } + .metric, .proof, .case-card, .boundary-panel, .behavior-panel, .timeline-panel { + border: 1px solid var(--line); + border-radius: 8px; + background: var(--panel); + } + .metric { padding: 16px; } + .metric strong { display: block; font-size: 28px; line-height: 1; color: var(--ink); } + .metric span { display: block; margin-top: 8px; color: var(--dim); font-size: 12px; font-weight: 650; } + .proof-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .proof { padding: 18px; } + .proof span { color: var(--accent-2); font-size: 12px; font-weight: 780; text-transform: uppercase; } + .proof p { margin: 10px 0 0; color: var(--muted); line-height: 1.6; } + .case-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } + .case-card { + display: grid; + gap: 12px; + min-height: 310px; + padding: 18px; + text-decoration: none; + color: inherit; + } + .case-card:hover { border-color: var(--accent); } + .case-card h3 { margin: 0; font-size: 23px; line-height: 1.08; } + .case-card p { margin: 0; color: var(--muted); line-height: 1.55; } + .case-card .badges { display: flex; flex-wrap: wrap; gap: 6px; align-self: end; } + .case-card__meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } + .case-card__date { color: var(--dim); font-size: 12px; font-weight: 700; } + .case-card__proof { border-left: 2px solid var(--accent); padding-left: 10px; font-size: 13px; color: var(--muted); } + .page-layout { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 18px; align-items: start; } + .behavior-panel, .timeline-panel, .boundary-panel { padding: 20px; } + .behavior-panel h2, .timeline-panel h2, .boundary-panel h2 { font-size: 24px; } + .behavior-list, .beat-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 10px; } + .behavior-list li { + border-left: 2px solid var(--accent); + padding: 7px 0 7px 12px; + color: var(--muted); + line-height: 1.55; + } + .beat-list li { + display: grid; + grid-template-columns: 42px minmax(0,1fr); + gap: 10px; + align-items: start; + color: var(--muted); + } + .beat-list li span { + display: inline-grid; + place-items: center; + width: 34px; + height: 28px; + border: 1px solid var(--line-2); + border-radius: 8px; + color: var(--accent-2); + font-size: 12px; + font-weight: 780; + } + .beat-list li p { margin: 2px 0 0; line-height: 1.55; } + .boundary-panel { background: #121514; border-color: rgba(126,212,168,.22); } + .boundary-panel p { margin: 0; color: var(--muted); line-height: 1.6; } + .side-stack { display: grid; gap: 12px; align-content: start; } + .demo-command { + display: block; + padding: 12px; + border: 1px solid var(--line); + border-radius: 8px; + color: var(--accent-2); + background: #0d0f12; + white-space: normal; + overflow-wrap: anywhere; + font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + } + .control-strip { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 10px; + margin-top: 20px; + } + .control-strip div { + min-height: 92px; + border: 1px solid var(--line); + border-radius: 8px; + padding: 14px; + background: var(--panel-2); + } + .control-strip span { color: var(--accent-3); font-size: 12px; font-weight: 760; } + .control-strip p { margin: 8px 0 0; color: var(--muted); font-size: 13px; line-height: 1.45; } + .search-row { + display: grid; + grid-template-columns: minmax(0, 1fr) auto; + gap: 10px; + margin-bottom: 18px; + } + .search-row input { + width: 100%; + min-height: 40px; + border: 1px solid var(--line); + border-radius: 8px; + padding: 0 12px; + background: var(--panel); + color: var(--ink); + font: inherit; + } + .search-row .count { align-self: center; color: var(--dim); font-size: 13px; font-weight: 650; } + .public-note { color: var(--dim); font-size: 12px; line-height: 1.6; } + footer { border-top: 1px solid rgba(255,255,255,.08); padding: 28px 22px 44px; color: var(--dim); } + footer div { max-width: var(--max); margin: 0 auto; } + @media (max-width: 940px) { + .hero, .page-layout { grid-template-columns: 1fr; min-height: auto; } + .metrics, .case-grid, .control-strip { grid-template-columns: repeat(2, minmax(0,1fr)); } + .proof-grid { grid-template-columns: 1fr; } + } + @media (max-width: 620px) { + main { padding: 26px 14px 48px; } + .topbar-inner { align-items: flex-start; flex-direction: column; padding: 12px 14px; } + .metrics, .case-grid, .control-strip { grid-template-columns: 1fr; } + .search-row { grid-template-columns: 1fr; } + h1 { font-size: 44px; } + } + """ + + +def html_head(title: str) -> str: + return f""" + + + {esc(title)} + + +""" + + +def index_path(lang: str) -> Path: + if lang == "en": + return SHOWCASE_DIR / "index.en.html" + return SHOWCASE_DIR / "index.html" + + +def topbar(current: Path, lang: str, alternate: Path) -> str: + index_href = rel_href(current, index_path(lang)) + readme_href = rel_href(current, SHOWCASE_DIR / "README.md") + catalog_href = rel_href(current, CATALOG) + alternate_href = rel_href(current, alternate) + return f""" +
    + +
    + """ + + +def render_case_page(case: dict[str, Any], primary: bool, lang: str) -> str: + output = case_html_path(case, lang) + alternate = case_html_path(case, "en" if lang == "zh" else "zh") + frontend = case.get("frontend_card") if isinstance(case.get("frontend_card"), dict) else {} + table = case_table(case, lang) + tags = first_items(case.get("pattern_tags"), 5) + badges_values = first_items(frontend.get("badges"), 5) or tags[:4] + metrics = metric_cards(case) + anchors = "" + if str(case.get("id")) == "2026-06-19-dynamic-workflow-hardware-agent": + anchor_text = ( + f"loopx 在芯片开发任务上的实践: {', '.join(HARDWARE_PUBLIC_ANCHORS)}" + if lang == "zh" + else ", ".join(HARDWARE_PUBLIC_ANCHORS) + ) + anchors = ( + f'
    {esc(ui(lang, "hardware_anchors"))}' + f'

    {esc(anchor_text)}

    ' + ) + metric_markup = f'
    {metrics}
    ' if metrics else "" + appendix_label = "" if primary else 'appendix' + links = case_links(case, current=output, lang=lang) + title = localized(case, lang, "title") + headline = localized(case, lang, "headline") + evidence_boundary = localized(case, lang, "evidence_boundary") + return f""" + +{html_head("LoopX Showcase: " + title)} + +
    + {topbar(output, lang, alternate)} +
    +
    +
    +

    {esc(case.get("date") or "")} / {esc(status_label(case, lang))}

    +

    {esc(title)}

    +

    {esc(headline)}

    +
    + {esc(case.get("domain") or "showcase")} + {appendix_label} + {badges(badges_values)} +
    + +
    + {control_graph(case, lang)} +
    + +
    +

    {esc(ui(lang, "proof_title"))}

    +
    +
    {esc(ui(lang, "proof_point"))}

    {esc(table["proof_point"])}

    +
    {esc(ui(lang, "loopx_intervention"))}

    {esc(table["loopx_intervention"])}

    + {anchors} +
    + {metric_markup} +
    + +
    +
    +

    {esc(ui(lang, "behavior"))}

    +
      {behavior_items(case, lang)}
    +
    + +
    +
    +
    {esc(ui(lang, "footer_case"))}
    +
    + + +""" + + +def render_index(cases: list[dict[str, Any]], lang: str) -> str: + primary, appendix = ordered_cases(cases) + current = index_path(lang) + alternate = index_path("en" if lang == "zh" else "zh") + cards = "\n".join(render_index_card(case, current=current, lang=lang) for case in primary) + appendix_cards = "\n".join(render_index_card(case, current=current, lang=lang) for case in appendix) + steps = "\n".join( + f"
    {esc(label)}

    {esc(copy)}

    " + for label, copy in ui(lang, "control_steps") + ) + initial_count = f'{len(primary)} {ui(lang, "public_cases")}' if lang == "en" else f'{len(primary)}{ui(lang, "public_cases")}' + count_expression = "`${visible} public cases`" if lang == "en" else "`${visible}个公开案例`" + return f""" + +{html_head("LoopX Showcase Gallery")} + +
    + {topbar(current, lang, alternate)} +
    +
    +
    +

    {esc(ui(lang, "gallery_eyebrow"))}

    +

    {esc(ui(lang, "gallery_title"))}

    +

    {esc(ui(lang, "gallery_copy"))}

    + +
    + {steps} +
    +
    + {index_graph(primary, lang)} +
    + +
    +

    {esc(ui(lang, "showcase_cases"))}

    +

    {esc(ui(lang, "section_lede"))}

    +
    + + {esc(initial_count)} +
    +
    + {cards} +
    +
    + +
    +

    {esc(ui(lang, "appendix_surface"))}

    +

    {esc(ui(lang, "appendix_lede"))}

    +
    + {appendix_cards} +
    +
    + +
    +

    {esc(ui(lang, "public_boundary"))}

    +
    +

    {esc(ui(lang, "public_boundary_copy"))}

    +
    +
    +
    +
    {esc(ui(lang, "footer_index"))}
    +
    + + + +""" + + +def render_index_card(case: dict[str, Any], *, current: Path, lang: str) -> str: + output = case_html_path(case, lang) + frontend = case.get("frontend_card") if isinstance(case.get("frontend_card"), dict) else {} + table = case_table(case, lang) + tags = first_items(case.get("pattern_tags"), 4) + badge_values = first_items(frontend.get("badges"), 4) or tags + title = localized(case, lang, "title") + headline = localized(case, lang, "headline") + search = " ".join( + str(value) + for value in [ + title, + headline, + case.get("domain"), + case.get("status"), + table.get("proof_point"), + table.get("loopx_intervention"), + *tags, + ] + if value + ).lower() + return f""" + +
    + {esc(status_label(case, lang))} + {esc(case.get("date") or "")} +
    +

    {esc(title)}

    +

    {esc(headline)}

    +

    {esc(table["proof_point"])}

    +
    {badges(badge_values)}
    +
    + """ + + +def index_graph(primary: list[dict[str, Any]], lang: str) -> str: + labels = [str(case.get("date") or "") for case in primary[:7]] + dots = "\n".join( + f'' + f'{esc(label[5:])}' + for index, label in enumerate(labels) + ) + return f""" +
    + + LoopX showcase gallery rail + + + {esc(ui(lang, "index_graph_catalog"))} + + {esc(ui(lang, "index_graph_proof"))} + + {esc(ui(lang, "index_graph_control"))} + todo / gate / evidence + + {esc(ui(lang, "index_graph_case"))} + + + + {dots} + +
    + """ + + +def update_catalog(catalog: dict[str, Any]) -> dict[str, Any]: + cases = catalog.get("cases") + if not isinstance(cases, list): + raise ValueError("catalog must contain cases") + by_id = {str(case.get("id")): case for case in cases} + reordered: list[dict[str, Any]] = [] + for case_id in PRIMARY_CASE_ORDER: + if case_id in by_id: + reordered.append(by_id.pop(case_id)) + reordered.extend(by_id.values()) + + for rank, case in enumerate(reordered, start=1): + zh_output = case_html_path(case, "zh") + en_output = case_html_path(case, "en") + zh_rel = zh_output.relative_to(REPO_ROOT).as_posix() + en_rel = en_output.relative_to(REPO_ROOT).as_posix() + case["interactive_page"] = zh_rel + case["interactive_page_zh"] = zh_rel + case["interactive_page_en"] = en_rel + case["localized_pages"] = {"zh": zh_rel, "en": en_rel} + if str(case.get("id")) in FALLBACK_SHOWCASE_TABLE: + case["showcase_rank"] = rank + case["showcase_table"] = FALLBACK_SHOWCASE_TABLE[str(case["id"])] + if not isinstance(case.get("frontend_card"), dict): + case["frontend_card"] = DEFAULT_FRONTEND_CARDS.get(str(case["id"]), { + "visual_metaphor": "a LoopX control-plane rail turns ambiguous agent work into reviewable evidence", + "story_beats": first_items(case.get("loopx_behavior"), 3), + "badges": first_items(case.get("pattern_tags"), 3), + }) + catalog["cases"] = reordered + return catalog + + +def read_catalog() -> dict[str, Any]: + return json.loads(CATALOG.read_text(encoding="utf-8")) + + +def write(path: Path, text: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(clean_generated_text(text), encoding="utf-8") + + +def clean_generated_text(text: str) -> str: + return "\n".join(line.rstrip() for line in text.splitlines()) + "\n" + + +def generate(*, write_files: bool) -> list[Path]: + catalog = update_catalog(read_catalog()) + cases = catalog["cases"] + primary, appendix = ordered_cases(cases) + outputs: list[Path] = [] + if write_files: + CATALOG.write_text(json.dumps(catalog, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + for case in primary + appendix: + for lang in ("zh", "en"): + output = case_html_path(case, lang) + html_text = render_case_page(case, primary=case in primary, lang=lang) + outputs.append(output) + if write_files: + write(output, html_text) + for lang in ("zh", "en"): + path = index_path(lang) + outputs.append(path) + if write_files: + write(path, render_index(cases, lang)) + return outputs + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", action="store_true", help="Verify committed HTML/catalog match generated output.") + args = parser.parse_args() + + if args.check: + catalog = update_catalog(read_catalog()) + expected_catalog = json.dumps(catalog, ensure_ascii=False, indent=2) + "\n" + actual_catalog = CATALOG.read_text(encoding="utf-8") + if actual_catalog != expected_catalog: + raise AssertionError("showcase catalog is not normalized; run examples/showcase-html-pages.py") + cases = catalog["cases"] + primary, appendix = ordered_cases(cases) + for case in primary + appendix: + for lang in ("zh", "en"): + output = case_html_path(case, lang) + expected = clean_generated_text(render_case_page(case, primary=case in primary, lang=lang)) + if output.read_text(encoding="utf-8") != expected: + raise AssertionError(f"{output} is not generated from the catalog") + for lang in ("zh", "en"): + path = index_path(lang) + if path.read_text(encoding="utf-8") != clean_generated_text(render_index(cases, lang)): + raise AssertionError(f"{path} is not generated from the catalog") + print("showcase-html-pages check ok") + return 0 + + outputs = generate(write_files=True) + for output in outputs: + print(output.relative_to(REPO_ROOT).as_posix()) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())