From 0c97e6eb32ac90bc90b4b81a3e71e8fac61224ac Mon Sep 17 00:00:00 2001 From: Liu Shiyu <104006363+liush2yuxjtu@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:45:44 +0800 Subject: [PATCH] Condense talk-html skill contract --- skills/talk-html/SKILL.md | 1090 ++++++++----------------------------- 1 file changed, 230 insertions(+), 860 deletions(-) diff --git a/skills/talk-html/SKILL.md b/skills/talk-html/SKILL.md index c9176da..eaa8389 100644 --- a/skills/talk-html/SKILL.md +++ b/skills/talk-html/SKILL.md @@ -1,956 +1,326 @@ --- name: talk-html -description: Invoke when the user wants a shareable HTML one-pager out of the current conversation, a writeup, or assembled context — recap, postmortem, retro, status board, transition letter, founder/exec update, decision log, or "send a link, not a chat scroll" artifact. The skill provides what raw HTML cannot: publish.sh uploads to a GitHub gist and returns the shareable URL; recall.sh + ~/.claude/talk-html/index.jsonl let the user grep past pages weeks later. zh-CN by default; embeds real screenshots/video/diff for non-static content, never hand-drawn mocks. Triggers: /talk-html, "make a page", "one-pager", "html version", "publish this", "shareable page", "gist link", "做成一页", "做个网页", "html 版本", "用 html 解释", "推到 gist". When the user names an audience for the page ("for ops", "for the CEO", "founder update", "send to data team"), trigger this — they want a recallable shareable artifact, not a stray HTML file. NOT for shipped UI, landing pages, React components, doc conversion, QA bug reports, or scripts. +description: >- + Invoke when the user wants a shareable HTML one-pager out of the current + conversation, a writeup, or assembled context: recap, postmortem, status + board, proposal, founder update, decision log, or "send a link, not a chat + scroll" artifact. zh-CN by default. The skill publishes via GitHub gist, + records recall metadata, and uses real screenshots/video/diff/command output + for proof. Triggers: /talk-html, make a page, one-pager, html version, + publish this, shareable page, gist link, 做成一页, 做个网页, html 版本, + 用 html 解释, 推到 gist. NOT for shipped UI, landing pages, React + components, doc conversion, QA bug reports, or scripts. --- # talk-html -Communicate in HTML, not chat. Local preview first, then gist-publish for permanence. **Output language is always Simplified Chinese.** - -> **Load-bearing principle — real content, not drawn demos.** Every page MUST be -> grounded in real sources. Before designing, dive deep into the relevant repo(s) -> and find the actual code, data, commands, routes, fixtures, screenshots, or -> generated artifacts that should drive the visual content. If the source you -> need does not exist yet and the user permits implementation work, build the -> smallest missing source with existing code paths and render *that*. Never -> substitute a hand-drawn mock, concept sketch, or fabricated UI for a missing -> run — the only exception is when the user explicitly asks for a mock or demo. -> And anything **non-static** — an interactive flow, a live/status board, an -> animation, a running UI — must be shown through a real embedded video or GIF, -> never a static screenshot or diagram standing in for motion. Source-grounding -> reaches *inside* the run: a real binary, built by the project's own pipeline -> and recorded honestly, is still a drawn mock if every number, status, and -> series it displays is a hardcoded literal. Real run + invented data is a mock -> wearing a real binary's clothes. §3.0, §3.0.1 and §3.1 below make this -> concrete and active. - -> **Source-of-truth guard — read this before any self-referential run.** The -> *only* canonical spec for this skill is `~/.agents/skills/talk-html/SKILL.md` -> (the symlink target that `~/.claude/skills/talk-html` and -> `~/.codex/skills/talk-html` load). Any `*/talk-html/SKILL.md` found *inside a -> project repo or a `.claude/worktrees/` checkout* is a **vendored copy**, not -> the spec — it may be stale or trimmed. When the page's topic is talk-html -> itself (redesign, diagnosis, "is it synced", proposal), the "dive into the -> relevant repo" rule above does **not** apply to this file: never treat a -> discovered in-repo `SKILL.md` as authoritative, and never re-propose rules -> that the canonical already contains. Preflight, every run: -> `bash ~/.agents/skills/talk-html/check-canon.sh --heal --all --quiet` — it -> prints the canonical sha256 and **collapses every vendored copy (persisted -> *and* transient `.claude/worktrees/` checkouts) back onto canonical in the -> same pass**. Only the latest canonical is ever ground truth: drift is -> overwritten, not merely reported, so a stale copy can never survive into a -> later run to be read as spec. - -## When to invoke - -- The current answer is structured enough that an HTML page beats a chat scroll (essay, recap, status board, proposal, letter). -- The user said "html version", "make a page", "publish this", "share this with X". -- The user wants to remember today's decision/insight in a recallable, linkable form. -- Another agent needs to hand a polished communication to a human user. - -If the topic is **a finished UI feature / production page** belonging to a real product, use `frontend-design` or `design-html` instead. `talk-html` is for ephemeral communication artifacts, not shipped product UI. +Communicate in HTML, not chat. Build a readable Chinese one-pager, preview it +locally, then publish a durable gist link unless the user explicitly opts out. + +This skill is a **contract**, not an eval recipe. It declares what the user +wants, what tools agents may use, what machine-readable outputs should exist, +and what tools can turn evidence into a human visual report. Agents choose +their own exploration path. + +## User Wants, Tools, Outputs + +| # | User wants | Tools agents can use to eval | Outputs readable to agents | Tools agents can use for human visual report | +|---|---|---|---|---| +| 1 | 分享页给人看,不是聊天记录搬运 | `talk-html`, `publish.sh`, `recall.sh`, browser, `curl` | `talk-html-meta`, `index.jsonl`, local/gist/raw/rendered URL, HTTP status | HTML/CSS, gist, htmlpreview, browser screenshot | +| 2 | 证据是真的,不要画假证明 | `verify-evidence.sh`, `talk-html-evidence`, `run-log`, source files, command logs | provenance JSON/comment, command exit code, artifact path/hash, source path | embedded screenshot, GIF, MP4, evidence caption | +| 3 | 证明必须匹配 claim | `git diff`, target CLI, test runner, browser tools, proof/source artifacts | diff, test output, command output, artifact type, reviewer/audience type | side-by-side diff, proof chain panel, status blocks | +| 4 | 不要强迫 Claude TUI | shell, CLI output, env checker, normal terminal recorder, Claude TUI when useful | redacted env report, command transcript, exit code, wrapper diff | readable terminal panel, short command replay, concise proof card | +| 5 | 如果用了 Claude TUI,就必须是真交互 | `tmux`, Claude Code TUI, `asciinema`, `ffmpeg`, terminal capture tools | TUI run log, prompt marker, response marker, frame list, recording path | TUI GIF/MP4, poster frame, prompt/response callout | +| 6 | 终端证据给人看,不给机器 scrollback | terminal recorder, `screencapture`, renderer, poster inspection tools | transcript file, frame metadata, recording metadata, clipped command output | large-font terminal visual, PASS/DENY highlight, collapsed raw evidence | +| 7 | 字体好看,中文正常,不要方块字 | font discovery tools, image renderer, screenshot/poster tools | font name, fallback list, poster path, render artifact path | SF Mono/SFNSMono + PingFang/Hiragino/Noto/Source Han rendered visual | +| 8 | 最终报告对人类清楚,对 agent 可追踪 | HTML file, metadata comment, evidence comment, index row, publish script | session id, slug, prompt summary, source list, generated timestamp | first-screen summary, visual evidence section, verification notes | + +Short form: + +- **User wants:** real, readable, claim-matched, shareable proof. +- **Agents get:** eval tools, provenance outputs, machine-readable metadata, + recording/rendering tools, and publishing tools. +- **Humans get:** a visual report with real screenshots/GIF/video, readable + terminal/TUI evidence, and no raw plumbing noise. +- **No fixed eval recipe:** agents explore, choose tools, and decide which proof + path fits the claim. + +## Non-Negotiable Contract + +- Output language is Simplified Chinese (`zh-CN`) unless the user explicitly + asks otherwise. File paths, commands, URLs, code, and technical identifiers + may stay in English. +- The page is grounded in real sources: code, data, commands, routes, fixtures, + screenshots, recordings, diffs, logs, tests, or generated artifacts. +- Do not invent a mock UI, fake dataset, fake command output, fake video, or + fake provenance unless the user explicitly asked for fiction/mockup. +- If a claim depends on motion or interaction, the human report needs real + visual evidence: GIF, MP4/WebM, screenshot sequence, terminal capture, or + poster frame from the real run. +- If Claude TUI appears as proof, the visual evidence shows a real user prompt + and Claude's visible response/permission/error state. A welcome screen or a + `claude -p` shell call is not a TUI interaction. +- Do not force Claude TUI for ordinary CLI/alias/script claims. Shell proof, + command output, env checks, and diffs are valid tools. +- Terminal/TUI visuals are for humans first: large type, stable framing, short + commands, clear PASS/DENY moments, no secret values, no internal job clutter, + no raw tmux plumbing as the main artifact. +- Terminal/TUI fonts must cover Chinese and box drawing. Prefer SF Mono/SFNSMono + plus PingFang SC, Hiragino Sans GB, Noto Sans CJK SC, or Source Han Sans. + Re-render if the poster shows `□`, `�`, missing glyph boxes, tiny text, or + ugly fallback fonts. +- Published pages must be portable. Primary evidence must work on the rendered + gist URL, not only on local `file://` paths. ## Workflow -### 0. Preflight — canonical self-heal (every run, enforcing) +### 0. Preflight -Before anything else, run the drift sentinel in **heal mode**: +For every run, heal local skill drift before reading or writing artifacts: ```bash bash ~/.agents/skills/talk-html/check-canon.sh --heal --all --quiet ``` -This is not a check that *reports* drift — it *erases* it. In one pass it -prints the canonical sha256 and overwrites **every** vendored copy (persisted -project mirrors **and** transient `.claude/worktrees/` checkouts) with -`~/.agents/skills/talk-html/SKILL.md`. After preflight, exactly one version of -this skill exists on disk: the latest canonical. There is no "two cases" and -no manual follow-up step — whatever the page's topic, the latest is the only -ground truth, enforced every run. +The canonical skill file is: -- **Topic is talk-html itself** (redesign / diagnosis / "is it synced" / - proposal): per the Source-of-truth guard, never read a discovered in-repo - `SKILL.md` as authoritative and never re-propose rules the canonical already - has. The auto-heal above guarantees any copy you might still glance at is - already byte-identical to canonical. -- **Any other topic**: the heal is cheap (a few `cp`s) and non-blocking — it - runs, the latest is enforced, the page proceeds. +```text +~/.agents/skills/talk-html/SKILL.md +``` -This step exists because the historical bad case was a /talk-html run "diving -into the relevant repo" and reading a stale vendored copy of this very file as -if it were the spec. Auto-heal makes that case **structurally impossible**: a -stale copy cannot survive a single preflight, so it can never be read as spec -in this run or any later one. +`~/.claude/skills/talk-html` and `~/.codex/skills/talk-html` should be treated +as loaded copies/symlinks. Repo-local `*/talk-html/SKILL.md` files are not +authoritative for self-referential talk-html work. -### 1. Resolve context +### 1. Resolve the Page -Identify what you are communicating. Look at: +Create: -- The user's last few messages. -- Files referenced in the conversation. -- If the user gave you a topic phrase, use that as the spine. +- `slug`: 3-5 kebab-case words. +- `prompt_summary`: one Chinese sentence, 200 chars max. +- `template`: `explainer`, `recap`, `status`, `pitch`, or `letter`. +- `audience`: who needs to understand the page. +- `core_claim`: the one sentence the first screen must make clear. -Synthesize a `slug` (3–5 kebab-case words) and a one-sentence `prompt_summary` (≤ 200 chars). +Use `status` for proof-of-work/status pages, `pitch` for persuasive proposals, +`recap` for decision logs, `letter` for personal memo, and `explainer` when in +doubt. -### 2. Pick a template +### 2. Gather Real Evidence -| Template | Use when | -|---|---| -| `explainer` (default) | Long-form essay / "explain X to Y". Editorial magazine style. | -| `recap` | Decision log: timeline + decisions + open questions. | -| `status` | What's done / in flight / blocked. Dashboard register. If it mirrors a live pipeline/board/run, that is non-static — §3.1 requires an embedded video/GIF of the real thing. | -| `pitch` | One-page proposal with a single CTA. | -| `letter` | Personal note / memo to a named recipient. | +Use the tools that fit the claim. Examples: -When in doubt: `explainer`. +- Code/change proof: `git diff`, test runner, build output, CI artifact. +- CLI/alias proof: target command, env checker, redacted transcript, exit code. +- Browser/UI proof: project build command, local server, Playwright/browser, + screenshots, GIF/MP4/WebM. +- Terminal/TUI proof: terminal recorder, `tmux`, `asciinema`, `ffmpeg`, + `screencapture`, poster renderer. +- Data proof: source files, fixtures, command output, generated data manifest, + hashes, `run-log`. +- Provenance proof: `talk-html-evidence`, `run-log.json`, source paths, command + logs, timestamps. -For `pitch` / `status` and any "show the boss / VC / customer" proof page, the -template only picks the skeleton — the page's job is to *convince a specific -reader*, so also apply **§3.2 (audience-first structure)** before writing. +The page should expose enough agent-readable material that another agent can +retrace the artifact without reading the chat scroll. ### 3. Write the HTML -Save to: `~/.agents/talk-html/-YYYYMMDD-HHMMSS.html` - -### 3.0 Source-ground the visual content - -Default to **real contents, not drawn demos**. Unless the user explicitly asks -for a mock, concept sketch, or fictional demo, the page must be grounded in -actual sources: - -- Dive into the relevant repo(s) before designing the page. Find the real - code, docs, commands, data files, routes, endpoints, screenshots, tests, - fixtures, or generated artifacts that should drive the visual content. -- If no suitable visual source exists yet and the user permits implementation - work, build the smallest missing source with existing code paths, then render - that real source. Do not replace missing product content with invented UI. -- If a page claims a terminal run, browser run, screenshot, GIF, chart, or - dashboard is real, create it from an actual command on the current machine. - Record the command, host, path, timestamp, and output artifact in the HTML. -- For tmux / Playwright evidence, a static illustration is not enough: start a - real tmux session, run the real server or command in it, drive it with real - Playwright, and use screenshots/video/GIF captured from that run. -- The final artifact should make clear which parts are source-backed and link - or name the exact source files/commands. Speculative product framing is fine - only when labeled as such and separated from verified evidence. - -Hard requirements: - -- **Language (load-bearing)**: All artifact content — title, lede, headings, body prose, captions, pull-quotes, CTA copy, footer text — **must be in Simplified Chinese (zh-CN)**. The only English allowed is: structural metadata (``), file paths, shell commands, code snippets, URLs, technical identifiers (slug, session id), and short inline tokens where a Chinese rendering would be confusing (e.g. `gh gist create`, `~/.agents/...`). Set `` and include ``. Avoid 中英夹杂 marketing speak ("我们 leverage best-of-breed solutions") — Chinese prose should read like a human wrote it. -- **Self-contained**: inline CSS, no external JS. Google Fonts via `` is allowed. JS is sanctioned in exactly **two** narrow places, both pure clipboard utilities, never general page scripting: - 1. the **audit pill** copy handlers — `copy id` and copy-`claude --resume` (§5); - 2. the **“继续修改” bar** prompt builder (§5.1) — reads one text input and writes one clipboard string. - Both are inline `onclick`/IIFE handlers with no network, no timers, and no DOM mutation beyond reading their own input. They are utility chrome, not page content, so they do **not** count as “non-static content” under §3.1 (the same carve-out the pill always had). Anything past these two — animation, `fetch`, frameworks, reveal logic — is out of bounds; a page that seems to need it is the wrong job for this skill (use `frontend-design`). -- **Editorial typography**: pair a Latin display/body family with **Noto Serif SC** (思源宋体) — the Chinese face must carry the body text, not fall through to a system default. Recommended pairings: Fraunces + Noto Serif SC, or Newsreader + Noto Serif SC. Name the typographic mood in one sentence (Chinese is fine); if you cannot, redo it. -- **Diagrams**: SVG. Diagram labels in Chinese (or technical English where labels reference real identifiers like `index.jsonl`). Reserve ASCII art for explicit "terminal" flavor sections only. -- **Reflow**: works on mobile (≤ 420 px). No fixed pixel heights that clip text. Chinese reflows differently from English — test the narrow viewport. -- **Motion**: respect `prefers-reduced-motion`. -- **No "AI SaaS landing page" aesthetic**: no centered hero gradient, no random emoji, no rainbow CTAs. -- **No emoji** unless the user asked for emoji. -- **Size**: < 200 KB unless content genuinely warrants more. -- **Published-page portability (load-bearing)**: anything that makes the local HTML "good" must also work in the gist/htmlpreview version. Do **not** rely on `file://` links, local relative asset paths, or local-only source links for primary evidence, images, demos, downloads, or "click to view" controls. For gist-published pages, embed critical media as `data:` URLs, include critical source/proof inline behind native clickable controls such as `
...`, or link to a real public HTTPS URL. A local URL such as `http://127.0.0.1:4177` may be included only as an optional "try it on this machine" control, never as the only copy of evidence or source. Before publishing, review every `` and ``: if a remote reader on `htmlpreview.github.io` cannot click or view it, fix it before `publish.sh`. - -A skeletal example with the required structural elements (meta comment, audit pill, footer link) lives at `templates/skeleton.html`. Read it once to learn the structural slots, then design the actual page fresh — do **not** copy the template's content or its visual style verbatim. - -### 3.0.1 The data inside the run must be real, too - -§3.0 grounds the *visual*; this grounds *what the visual says*. The two are -not the same thing, and the gap between them is the single most common way a -page is technically honest yet substantively fake: the program is real, the -recording is real, every value on screen is invented. - -A real run earns trust because it shows what the system *actually does with -real inputs*. A binary whose dashboard reads `status: "周环比 +12%"` from a -`const` table, or whose chart is `vec![3,5,4,6,8,…]` written by hand, does not -do that — it performs a screenshot the author drew, just rendered by a -compiler instead of a design tool. Recording it in a real PTY with honest -timestamps proves the *terminal* was real; it proves nothing about the claim -the reader takes away, which is the numbers. The reader cannot tell hardcoded -`+12%` from measured `+12%`; that is exactly why the burden is on the page. - -So before you record anything that displays data, ask the question §3.0 asks -of the visual, now of the values: **where does each number, status, label, and -series come from, and could a reader re-derive it from a source named on the -page?** Acceptable answers are a file the program reads, a command it runs, an -API it calls, a fixture committed to the repo, a real metric computed at run -time. Not acceptable: a literal in the source, a "仅作示意 / illustrative" -placeholder, a plausible-looking series with no origin. If the program does -not yet read a real source, §3.0 already told you the move — build the -smallest path that makes it read one (an env-pointed dir, a generated data -file stamped with the command + source path + timestamp, a real query), then -record *that*. Drive the real binary from real data; do not record the real -binary reciting fake data. - -When the real source genuinely cannot back a panel — there is no real -engagement metric, the input does not exist yet — that panel is a failed -artifact, and the **§3.1.1 decision tree governs it exactly as a failed build -does**: ① narrow the claim (drop the fabricated sparkline, or relabel it to -the real series you *do* have — file sizes, commit counts, test results); ② -rebuild it from the project's own real source; ③ if neither holds, render an -honest empty/"数据不可用" state and note it in 诚实边界; ④ if the whole page -has no real data behind it, block and report. A fabricated value is never an -exit, for the same reason a drawn mock never is — it is the precise thing the -load-bearing principle exists to forbid, and a compiler in the loop does not -launder it. - -The page must make the data's origin checkable: near the run, name the source -files / commands / fixtures the values came from, and put the exact -reproduction commands behind a `
` so a reader can run `wc`, `git -log`, `curl`, or the generator and land on the same numbers. "Real run" in -the verification caption means *real binary on real data*; if only the binary -was real, the caption must say so and the §3.1.1 narrowing applies. - -### 3.1 Non-static content → record a real video or GIF (no exceptions) - -§3.0 says visual content must be source-grounded. This step makes that **active, not aspirational**, and it is the rule the whole skill turns on: - -**If anything in the artifact is non-static, the page MUST embed a real video or GIF of it.** A static screenshot, an SVG diagram, or prose describing what "would" happen does not satisfy this — non-static content has to actually move on the page. You record it from a real run on this machine and embed the result; you do not draw it, mock it, or describe it. - -Recording does not launder data. A real PTY capture of a real binary that is displaying hardcoded `const` literals satisfies the *motion* requirement and still fails §3.0.1 — the run must be of the real binary **on real data**, not the real binary reciting placeholders. Before you record, confirm the values on screen trace to a source per §3.0.1; a recorded fake is no better than a drawn one, just more expensive to make. - -"Non-static" is deliberately broad. Apply the rule whenever *either* the subject you are communicating *or* the page you are building has any of: - -- a **UI, demo, dashboard, or terminal** — anything a reader would expect to *see running*; -- an **interactive feature** — a flow the user clicks / types / navigates through, a control that responds, a reveal that carries real content. This holds for interactivity in the *page itself*, too: this skill is JS-free by design so most pages genuinely are static and need no recording — but if you build a page whose value depends on interaction, that interaction still needs a moving capture for the reader who only ever sees a snapshot; -- a **status / live feature** — a `status`-template board, a progress register, a streaming build, anything whose worth is "what state is it in *right now*"; -- **motion** — an animation, a transition, an animated diagram, anything beyond decorative CSS. - -Static artifacts — a plain essay, a letter, a recap of past decisions with no live element — are unaffected. The rule only bites when something actually moves; when it does, the moving proof is non-negotiable. §3.2.1 turns this static-vs-motion call into a per-artifact lookup — which artifact types owe a moving capture, and which reviewer rejects the page without it. - -**Use the project's OWN existing build code. Never reinvent build logic.** The whole point: the artifact is trustworthy because it came out of the same pipeline the project actually ships. Find the project's existing entrypoint — `landing/build-static.sh`, `pnpm build`, `make site`, `next build`, a `justfile` target, a documented script in `README` / `CLAUDE.md` — and run *that* verbatim. If you cannot find an existing build path, that is a finding to report, not a license to write your own. - -The skill ships two helpers for the common "build → serve → drive a browser → GIF" case: - -- `record-to-gif.sh` — orchestrator. Runs the project's build command, serves the real output dir, drives Chromium across your routes, and emits an optimized self-contained GIF + base64 data-URI + poster frame + `run-log.json`. -- `record-playwright.mjs` — the generic Playwright driver it calls (also runnable standalone). +Save to: -```bash -# Full path — build with the project's own script, then record: -bash ~/.agents/skills/talk-html/record-to-gif.sh \ - --build-cmd 'bash landing/build-static.sh' \ # the project's EXISTING build entrypoint, verbatim - --build-cwd /path/to/repo \ - --serve-dir /path/to/repo/build/output/dir \ # the real artifact the build produced - --routes '["/","/page-a","/page-b"]' \ - --out "$CLAUDE_JOB_DIR/rec" --speed 1.6 --fps 10 --width 820 - -# Already-static artifact (no build step) — omit --build-cmd: -bash ~/.agents/skills/talk-html/record-to-gif.sh \ - --serve-dir /path/to/static/site --routes '["/"]' --out "$CLAUDE_JOB_DIR/rec" +```text +~/.agents/talk-html/-YYYYMMDD-HHMMSS.html ``` -On success it prints `KEY=VALUE` lines (`GIF=`, `GIF_B64=`, `POSTER=`, `POSTER_B64=`, `WEBM=`, `RUNLOG=`, `GIF_BYTES=`, `WEBM_BYTES=`). Embed the GIF as a `data:image/gif;base64,…` URL so it survives gist/htmlpreview (§ portability rule). Add a `prefers-reduced-motion` fallback to the poster frame. In the page, near the artifact, state plainly: the build command run, the host, the routes + their HTTP statuses (from `run-log.json`), and the recording timestamp — and offer the exact command chain behind a `
` so a reader can reproduce it. - -When the helper does not fit (native app, hardware, a flow Playwright can't drive), still record reality — `tmux` + `asciinema`, `screencapture`, an `ffmpeg` screen grab — and embed that. The rule is *real run, real capture, embedded*; the helper is just the fast path for web UIs. - -If recording genuinely cannot be done (no display, the build is broken, credentials unavailable), do **not** fabricate a visual. Say so on the page in plain Chinese, show whatever raw evidence you do have (build log, `run-log.json`, HTTP statuses), and label the section as un-recorded. The full decision is §3.1.1 — work it top to bottom. - -### 3.1.1 失败降级决策树 — when the supporting artifact fails to build - -§3.0/§3.1 assume the real run succeeds *and renders real data*. Often it -doesn't: the build is broken, the recorder crashes, a tool is missing on this -machine, the run produces garbage — **or it builds and records cleanly but its -panels are hardcoded literals (§3.0.1)**. That last case is the same failure, -not a lesser one: a run with no real data behind it is an unsupported -artifact, and it enters this tree exactly where a failed build does — most -often at ② (drive the real binary from the project's own real source) or ① -(narrow/relabel the panel to the real series you do have). The failure of a -supporting artifact is **never** a license to fabricate one — it is a fork with four ordered exits and one path that is -structurally walled off. The exits exist because the cheapest move under -pressure is "just draw something close enough", and that is exactly the move -this skill is built to make impossible. Work down the list; take the first -exit that holds, and stop there. - -**① 收窄结论 — narrow the conclusion.** Before reaching for any rebuild, ask -what the *real evidence you already have* can honestly support, and shrink the -claim to exactly that. A build log alone supports "the build step produced X, -log attached" — not "the pipeline runs end to end." The conclusion follows the -evidence; you never stretch the evidence to fit a conclusion you already wrote. -Most "missing artifact" situations resolve here: the page stays true, just -narrower. This exit is first because it is the only one that needs no new run — -if a smaller honest claim still does the job, the artifact was never required. - -**② 用现有 code path 补建 — rebuild via the project's own path.** If a -narrowed claim still needs a live artifact, produce it the way the project -itself does: its existing entrypoint (`landing/build-static.sh`, `pnpm build`, -`make site`, a documented script in `README` / `CLAUDE.md`), run verbatim, -rendering what that path really emits. This is the §3.1 "use the project's OWN -build code, never reinvent" rule applied as a *recovery* step, not just the -happy path. If there is **no** existing build path, that absence is itself a -finding for exit ④ — never a license to hand-write build logic so you can -manufacture a visual. A run is only trustworthy because it came out of the -pipeline the project actually ships; a bespoke build you wrote to pass your own -page is not evidence. - -**③ 诚实标注 gap — honestly label the gap.** If it cannot be recorded, do not -draw a stand-in. Say so on the page in plain Chinese, show the raw evidence you -*do* have (build log, `run-log.json`, HTTP statuses), and mark that section -explicitly as 未录制 / un-recorded. Per §3.2 this belongs in the collapsed -「诚实边界 / Verification notes」 block — preserved, not hidden. A page that -openly says "this part could not be recorded, here is the raw log" is honest -and shippable; one that draws the missing run is not, no matter how plausible -the drawing looks. - -**④ block 上报 — block and report.** If the core claim has *zero* real -evidence behind it — nothing to narrow to, no usable build path, no raw log, or -the originating session cannot be traced (Quality bar #6) — that is a build -defect, not a publish signal. Stop. State plainly what is missing and why the -page cannot stand, and surface it to whoever asked. Do not ship a hollow or -fabricated page to keep the flow moving: a blocked report is a correct outcome, -a fake page never is. Exit ④ is a real, expected ending, not a failure of the -skill. - -**The walled-off path — never an exit.** A hand-drawn mock, a concept sketch, -a fabricated UI, a static screenshot standing in for motion, **or a real -binary recorded while it recites hardcoded `const` data (§3.0.1)** is **not** -one of the four exits — it is precisely the move the load-bearing principle, -§3.0, §3.0.1, §3.1, and Quality bar #8 all exist to forbid. A compiler between -you and the fake values changes the cost of the lie, not its nature. The only time a drawn mock is -legitimate is when the user explicitly asked for one. Absent that explicit -request, "the artifact failed to build" routes ①→②→③→④ and never to a drawn -substitute; there is no fifth door. - -### 3.1.2 录制交互式 Claude Code CLI — a live-TUI pane is a composer, not a shell - -§3.1's `tmux` + `asciinema` fallback is the path you take to record an -interactive Claude Code (or any REPL/TUI) session — a real demo of the agent -being driven, denied, corrected. It has one trap that has already shipped a -broken proof, so it gets its own rule. - -The instant you launch `claude` in a pane, that pane stops being a shell. It is -now the **model's input composer**. Every later `tmux send-keys` to that pane -is a *user turn* — the model reads it and answers it. That includes -"narration" you only meant for the orchestrator or the viewer: a line like -`echo; echo '[team-sync] published rule'; tail -n1 store.jsonl | jq …` sent to -a still-live claude pane is **not** run by bash — it is typed into the composer -and submitted as the next prompt. On the recording it shows up as a real extra -user turn (a stray prompt starting with `echo`), visually indistinguishable -from a fabricated one. A demo whose entire claim is "these are exactly the N -real turns a human sent" is destroyed by an N+1th turn made of shell plumbing. -It is the §3.0 lie in a new costume: the capture is real, the turn count is -not — and the page is now asserting something false. - -The root cause is always the same: addressing panes by **position or timeline** -("then send the summary to the left pane") instead of by **state** ("is this -pane a bash prompt or a live TUI *right now*?"). Drive panes by state: - -- **Send a live-TUI pane only the inputs that are meant to be real model - turns** — the actual prompts, nothing else. Their count and content are the - exact thing the page is proving; treat every keystroke into that pane as - load-bearing evidence. -- **Route every narration / inspection / "show the artifact" line to a pane - that is still a bash shell.** A second pane whose own TUI hasn't launched yet - is ideal — it doubles as the natural place to show the hand-off. Otherwise - fully quit the TUI first: send its real exit, then *verify* the pane is back - at a shell prompt before sending any shell command — never assume the exit - landed. -- The real side effect (appending to a store, copying a file) is performed by - the orchestrator in the shell that runs the demo — **not** by typing a - command into a recorded pane. A command typed into a pane exists only for the - viewer, and only ever belongs in a pane that is genuinely a shell. - -**Preflight check — run it before recording, and again before you re-embed.** -For each pane that launches `claude`, every `send-keys … Enter` (or wrapper -like `send_prompt`/`send`) that targets that pane *after* its launch line must -be one of its intended real user turns. List them and confirm the count is -exactly right: +Required page properties: -```bash -# Every input sent to Alice's pane ($P0) AFTER claude launched must be one of -# her intended prompts. Read the list; the count must equal the turns the -# page claims (e.g. EXHIBIT A claims TWO). -awk '/launch_coder "\$P0"|claude .*\$P0/{after=1} - after && /send-keys -t "\$P0"|send(_prompt)? "\$P0"/{print NR": "$0}' demo/driver.sh -``` +- `` and ``. +- Inline CSS. No external JS. Google Fonts are allowed. +- JS only for the audit pill clipboard buttons and the "继续修改" prompt copy + button. +- Editorial typography with a real Chinese body face. Noto Serif SC is a safe + default; terminal panels may use SF Mono/SFNSMono plus CJK fallback. +- SVG for diagrams. No live Mermaid block. +- Mobile reflow at 420 px without clipped text. +- Motion respects `prefers-reduced-motion`. +- No emoji unless the user asked. +- No AI-SaaS hero-gradient filler. +- File under 200 KB unless real embedded media genuinely requires more. -A wrong count means the bug is in the **driver script**, not the recorder or -the encoder — re-recording without fixing the script just reproduces the bad -turn, and re-embedding ships it. After re-recording, watch the clip once at the -relevant moment and confirm the pane shows exactly the intended prompts: this -is the §3.1 "watch the capture, don't assume it worked" discipline applied to -turn count, and it is the last gate before the video becomes the proof. - -### 3.1.3 证据闸门 — the fail-closed finish gate (mechanical, not advisory) - -Everything above this line — §3.0, §3.0.1, §3.1, §3.1.1, Quality bar #8 — was -*prose*. Prose is reasoned with, and under deadline pressure a model reasons -its way around it: "close enough", "the motion looks real", "I'll note it -later". Nothing ever mechanically refused a fabricated video, so fabricated -videos shipped. - -This was measured, not assumed. A 36-clip human ground-truth set -(`~/.agents/mp4-eval/ground-truth.json`) was scored against a *motion*-based -probe. The probe agreed with the human on only **19/36** and **never once -returned FAIL** — clips with heavy motion (`YAVG` up to 195) were labelled -fake by the human because the *data on screen was invented*. The lesson is -exact: **you cannot gate "is this video real" on pixels.** Motion, sharpness, -duration, file size — all of it is the thing a real-binary-reciting-fake-data -recording sails through. The one property that is both load-bearing and -mechanically checkable is **provenance**: can a reader trace this motion -artifact back to a real command, host, data source, and time? - -So the anti-fake rule is now a **gate, run before §7 publish / before you -declare the page done**, not a paragraph you affirm: +Recommended page shape: -```bash -bash ~/.agents/skills/talk-html/verify-evidence.sh "$HTML_PATH" -``` +1. First screen: one-sentence claim + proof chain. +2. Evidence: real visual proof, diff, command output, or data source. +3. Agent-readable trail: metadata, provenance, logs, paths, hashes, URLs. +4. Human-readable explanation: short sections, no hype, no internal plumbing. +5. Verification notes: collapsed `
` for limitations/gaps. +6. Continue bar and footer. -It is fail-closed. A page that embeds a motion artifact (video / webm / -animated gif / `data:video`) PASSES only if one of these is true: - -- **inline provenance** — a `` - record near the artifact (all of `cmd`, `source`, `recorded_at` non-empty), - where `source` names the real file/command/fixture/metric the on-screen data - came from (this is the §3.0.1 claim, made checkable); -- **a co-located `run-log.json`** — what `record-to-gif.sh` already emits - (build cmd + routes/HTTP + timestamp); -- **a DECLARED un-recorded gap** — the §3.1.1 ③ honest exit: a - `data-evidence="unrecorded"` element plus a visible 未录制 / un-recorded - label. A *declared* gap is honest and ships; a *silent* gap is the lie. - -A page with no motion artifact is static and passes untouched (essays, -letters, recaps stay exempt). `publish.sh` runs this same gate as a hard -precondition and **refuses to upload** (exit non-zero, local file kept, no -prompt) when it fails — publishing is the act that turns a fabricated video -into a shared lie, so the publish path itself is where the refusal lives. - -A non-zero gate is **not** a signal to "fix the gate" or pass `--public` -harder. It is a §3.1.1 ④ block: state plainly what evidence is missing and -stop. The gate has the same four honest exits and the same one walled-off -path as §3.1.1 — embedding the artifact anyway, or hand-writing a -`talk-html-evidence` record for a run that did not happen, *is* the -fabrication this whole section exists to forbid. A passing gate is a floor, -not a certificate: it proves the run is traceable, the reader still judges -whether the traced run actually supports the claim. Which programmatic tools -produce that machine-checkable verdict, and the deterministic pass/fail -threshold, are tabulated per `artifact_type` in §3.2.1's -`proof-build-eval-matrix.csv` — the gate there feeds this one, it does not -replace it. - -### 3.1.4 Eval / bad-case pages that ask for videos must play video - -When a page explains expected evals, judge harnesses, bad-case coverage, probe -failures, Gate Rule mappings, or MP4/video artifact evaluation, and the user -asks for "videos", "playable videos", "attach videos", or equivalent, a static -table, screenshot, poster, or contact sheet is not enough. Every claimed bad -case, failed probe group, or `#Gate Rule {index}` cluster needs a visible -`