coread-explainer — Co-Reading Explainer (Audited)
This skill has two layers. How to draw uses the anatomy kit (isometric camera, four-level shading, framed cards, components). What this skill provides is the discipline and mechanism on top of that: read only frozen data, recompute numbers, display limitations on every screen, keep a ledger of what can / cannot be said, and turn questions from the figure into cards and answer them. The figure is a surface for "aligning human understanding with the AI's readout" — it is not decoration. If even a single number cannot be traced back to its source, the credibility of the entire figure is compromised.
The first reference is an entry with multiple revisions (v1–v5). The reference entry can be obtained from the gallery DOI (10.5281/zenodo.23992312, the concept DOI for all versions). When in doubt, read its NOTES, CLAIMS, and README.
0. Decide Before Starting (Write a BRIEF)
Every request for a figure must first be captured in a BRIEF (specification). Without a BRIEF, the creator will read outside the material, place numbers by hand, and decide the evaluation criteria themselves. What to write in the BRIEF:
- Verbatim request (the requester's exact words with date).
- Reader and final evaluation (default is three; replace for different readers):
- E1 editor: The figure and text are faithful to the paper (or report) and do not claim what the paper does not claim. Suitable quality for a paper figure or appendix.
- E2 video creator: A 1920×1080 shot and script alone can produce a 1–2 minute scene. The core is visible in the first 10 seconds.
- E4 "Because of this instrument, this reading appeared": Positive controls, gates (eligibility judgment), and that changing bands or conditions changes the reading, is visible as a chain of evidence in the shot.
- If the reader is replaced, write the acceptance test for that reader (e.g., for students: three questions to answer after seeing the figure, and the criteria for correct answers). Just leaving the E1 / E2 / E4 names is not a valid measure for a student-oriented figure.
- List of materials (absolute paths, read only these) and what not to read (other creators' folders, judgments, memory).
- Verification values (a few numbers the execution layer reads from the data). If they don't match, the data is correct.
- Location (
entry_<card>_vN/, do not overwrite the previous version's folder) and scratch (a separate subdirectory per creator). - Time limit (minutes) and what to return (≤ 10 lines: files, number of states, captures, verification results, the point you are least confident about).
→ Template: references/brief-template.md.
1. Data Contract
- Only read frozen card outputs: JSON, npz, figure PNGs. A card = PREREG (question, universe, controls, judgment, what is not claimed) + script + output (provenance = commit, dirty, md5). Do not show numbers from outside the card in the figure.
- Do not import or execute the experiment's script (an unguarded aggregation script in
main, when merely imported, can rewrite frozen results). Only read data files. - Numbers are produced by scripts from data. Do not copy numbers by hand into HTML or scripts. Recompute each number via two or more independent paths (e.g., Python asserts in the pack / page JS / kernel side /
check_claims.pyanchors = file, key, expected value). If a verification value disagrees, treat the data as correct and notify the requester. - Fences for truncated values: Ranks truncated at an upper bound (e.g., below rank 1000 = 1001) are drawn in mist / uniform color, and described / referred to as "submerged" or "suppressed," never as "low". Align the truncation order (truncate then median, or median then truncate) with the card's documentation and implementation; if even-count medians disagree, disclose it.
- Values from ineligible bands or conditions may be shown only as a comparison side with a "not audited" label. Do not draw null as "absent."
- Rows from the same seed or same prompt family are not counted independently (specify the counting method, e.g., "three different scenes").
- A RESULT reading (L3) is not data. Before copying a RESULT statement into the figure, verify that the statement is supported by the data numbers. Example of confusion: "Most of the top positions are preview and echo" — this is correct as a proportion per position, but in absolute numbers the baseline position occupied 80% of the cases. If unsupported, do not include the statement in the figure; move it to the "cannot say" category in the ledger and ask the RESULT authors to correct it.
- Growing files (logs, daily records) must be passed as a frozen copy: write the line range and md5 in the BRIEF, and the creator reads only that range. This prevents later-added records (e.g., evaluation answers) from mixing into the material.
→ Details and pitfalls: references/data-contract.md.
2. What to Produce (One Entry Folder)
entry_<card>_vN/
build.mjs Assembles ESM / CSS for pages and widget from the kit (do not edit HTML by hand)
pack_*.py Data → figure pack (asserts form the first recomputation path)
data.mjs / live.js Page state machine and rendering (second recomputation path)
i18n.js ja / en strings
*_widget.py/.js/.css anywidget (traits: state, row, t, layer, band, lang, theme, etc.)
demo_marimo.py demo_jupyter.ipynb
check_claims.py make_check.py run_*.sh Inspections (§5)
captures/ Captures (§6)
CLAIMS.md NOTES.md README.md SCRIPT_yukkuri.md
(Internal layers are separate files: *_layer.js / *.css / README_internal.md — §8)
- Sections and states: Make the figure walk through states (0, 1, 2, …) and group them into sections (e.g., scene → audit → main scene → co-reading cycle → ledger). Place section buttons above the state number sequence (press to go to the first state of the section). Place section and state buttons above the heading (at the top of the page) (
.sh-nav, sticky at the top of the screen on pages): if placed below, headings of varying lengths cause the buttons to shift vertically between states, and the user loses track after clicking (Requester Oct 28 evening: "When I press a button, I lose it because the page height changes — put it on top without vertical movement"; before fixing, the button moved ≥ 900 px between states). Include an inspection: "The top edge of the band is the same in all states." After renumbering, output a list (state number → heading) and verify it yourself (the renumbering script's double shift has actually happened). - Do not wrap the widget in an iframe. Figure operations must reach Python, and Python must be able to write to the state (bidirectional). Support both marimo and JupyterLab.
- Build produces 4 pages (dark / light × ja / en).
→ Implementation template: references/implementation.md (skeleton based on the reference entry). Minimal template in assets/ (a skeleton that runs through build, inspection, and capture with synthetic data: config.json is the single source of state / section / frame numbers / run_checks.sh / list_headings.py / _smoke/ with runtime evidence). Start new figures by copying from here.
3. Language Discipline (Ledger: Can Say / Reading / Cannot Say)
The ledger is the final section of the figure. Each entry has a source (file and key):
- Can say (L1): A copy of a data value, a frozen judgment.
- Reading (L3): State whose reading it is (execution layer / creator) and label it "accept/reject is human." If the phrasing is meant to be replaced by the requester, label it as such.
- Cannot say: State explicitly in a declarative sentence (e.g., "It does not say that …"). Do not use small caveats or "maybe" to end. At minimum: mechanism / identification (things the adjudication kept as juxtaposed are not called the same thing) / quantity judgments (difference smaller than error band) / readings outside the instrument's validity domain / unread side (e.g., prompt side) / extrapolating "only" from one example / counting non-independent rows as independent.
Words not to use in the text and script: "the model thought / hesitated / realized / knew / actually understood", "we saw the AI's mind", "detected a lie" and similar exaggerations. The figure should state that lens rankings are lens readouts, not a map of the model's internals.
Display the limitation label on every screen of a section (one line below the frame + an identity badge at top-right): validity domain, description only, no identification, unread side, n. Limitations not shown in the capture do not exist. But before applying limitations, verify they truly apply to the data on that screen. Do not blindly copy examples from references/wording.md to all sections. Example: "All positions are outside the instrument's fit domain" — verify per-row positions (in a reference entry, rows under one condition were outside, but under another condition the prompt was short and they were inside). If the applicable range varies within a section, split the labels per row.
→ Examples and prohibited terms: references/wording.md.
4. Visualization Patterns (Effective in v1–v5)
- Entry is a scene: The first section is a single shot of "what happened in that moment" (e.g., intermediate tokens hover over a prompt before the answer is written, the answer board is still empty). The audit of numbers comes afterward.
- 3D isometric axes: Horizontal = position (tokens being written), Vertical = layer, Depth = instrument rank (front = rank 1, logarithmic, ranks beyond the upper bound are mist). Control bands are slabs; outside the band is gray ("outside control, for reference").
- Show success and failure side-by-side: Place two 3D figures in a single projection, a single camera, with a common scale. Rotating one rotates both. Video: left/right; desk/phone: stacked vertically (to preserve the smallest characters on the card).
- Declare the alignment method: For two rows with different outputs, state where they are aligned (branch point, pivot word, column head) and if the distance from the alignment point to the pivot word differs, write "+1 token / +3 token". Show small multiples aligned by distance (aligned at pivot position k).
- Draw zero-length parts as frames: A part present in only one row (e.g., "thinking column token / 0 token") should have a frame of the same width on both sides, with one side being a dotted empty frame. Blank space alone looks like a rendering error and invites criticism.
- Preview and echo: If the instrument ranks upcoming or just-written words high, mark positions F / E with distinct markers, and show them separately from quiet positions.
- Do not fill in what data does not have: If data is only aggregated and lacks per-row positions, label the entry scene as "schematic (not an actual row)." Do not draw intermediate states not in the record (e.g., between 3 machines → 1 machine, do not insert 2 machines or a sequence of gradual disappearance). For intervals between records (e.g., every 2 minutes), write times outside as "somewhere in this interval" with a width.
- Decide names in one place: Names for positions, rows, and surfaces (e.g., "branch point," "aligned position") go in a helper or config, so that all screen strings call the same thing by the same name. Add an inspection (§5) to scan for old names.
- One color, one meaning: Preserve colors that already have meaning (e.g., orange = He/Hi pair, blue = apex pair); do not add new colors. When adding colors only for non-data decoration (e.g., internal layer analogies), use a dataviz validator to check against existing colors: normal ΔE ≥ 15, CVD ΔE ≥ 8, on both dark and light backgrounds. Do not use third-party characters, images, or external fonts.
5. Inspections (Pass All Before Capturing)
- Console clean (4 pages, desk, phone, video, reduced motion, marimo, JupyterLab). Warnings from unrelated extensions are recorded and distinguished.
- Robust: Zero exceptions across all states × all rows × several layers.
- Number verification: All
check_claims.pyanchors (file, key, expected value) match, none missing. Verification values N / N. - Section buttons: Real clicks land on the first state of each section; check selected appearance, hash, and label (ja / en) match.
- Font size: Measure minimum px of labels per capture frame (guideline: video ≥ 10 px, desk ≥ 10 px, phone ≥ 9.5 px). An unreadable label is as good as absent.
- Overflow: Zero characters extending outside the viewBox.
- Public filter: Zero occurrences of internal terms (§8) in main files (count with grep).
- Name scan: Scan text of all states × ja / en pages for zero occurrences of old names and prohibited terms. Also perform a positive control for the scan itself (detection of a deliberately mixed old phrase in a page).
- Note about tools: Phone label minimum px reached 9.5 px only after narrowing the viewBox to enlarge text and converting the kit's four-corner text to vertical columns (the template's initial value was 2.7 px).
?video=1hides section buttons, so click testing is done on desk and phone views.
→ references/checks-and-captures.md.
6. Captures and Script
- 1920 × 1080 (for video, exactly that size) + desk (dark / light) + phone for each state. For "moment" states, include two frames (e.g., position 24 → 25).
SCRIPT_yukkuri.md: Dialogue (A = listener / B = explainer) ≤ 150 seconds, each line with a cue for which state to show, first 10 seconds showing the scene. Do not use real character names or images.
7. Co-Reading Cycle (The Main Use of This Figure)
When a viewer asks a question (e.g., "Where does He emerge from?"), turn it into a card and answer it. Procedure: 0. Confirm the question's wording: Check if the question refers to a unique position / row / word in the figure. If names are inconsistent (e.g., the same position is called "branch point" in one screen and "one step before the branch point" in another), ask the questioner a single question to clarify before reading numbers, and also fix the name inconsistency in the figure.
- Propose candidates (reading, L3): Two or three explanations that could answer the question. Mark each with three labels: (a) depends on the instrument (lens) or not / (b) the quantity is in persist (preserved data) / requires a new forward / requires new generation ("not in persist" does not mean the quantity does not exist — e.g., the rank of the model's own output exists at every position, but only the written token's rank was saved) / (c) touches the paper's constraints (e.g., do not connect predicates to layers outside the control band). Order: "does not depend on lens, in persist" candidates first, then those needing forward, then those depending on lens. Remove candidates that touch constraints.
- Freeze the card first: Put PREREG (question, universe, controls = including positive controls, phrasing of reading, what is not claimed, disclosure of what was seen beforehand) and script in one commit; allow
--fireonly when not dirty. Freeze before seeing values. - Read → RESULT: Numbers are copies of output (L1), reading is L3; what is not claimed remains as in PREREG.
- Stop if a control fails: Stop without writing figure data, diagnose the cause within the text side only, fix, and re-freeze as a new card (do not change the card definition after execution). Example: character decoding at token boundaries broke multi-byte characters into U+FFFD, shifting positions and text → control C2 caught it → new card using byte alignment. Record this as a real example of why AI readings also need controls.
- Insert as a state in the figure: "Figure → human question → AI candidates → freeze card and read → answer and cannot-say → next question."
→ references/coread-loop.md (card template, control philosophy).
8. Internal Layers (Analogies, In-Group Language)
If you want to include in-group analogies (e.g., internal names, mascots) in the figure, put them in a hidden layer: place them in separate files (*_layer.js / *.css / README_internal.md); the main body only "reads if present, does nothing if absent." Toggle via a hidden command (key sequence) + URL flag + widget trait. Default off, only on Japanese pages; on English pages, do nothing. When the layer is on, display "internal layer, not for external distribution" at top-right. Include an inspection that main files contain zero in-group terms (to prevent the figure from being excluded from the public bundle). Draw analogies yourself; explicitly state "cannot say" even within the layer so that the analogy is not read as a claim about mechanism.
9. Review and Versioning
- Separate storage per version (
_v1…_vN); do not overwrite previous versions. For minor fixes, usevN.1, vN.2 …and write in NOTES "what was fixed, who pointed it out." - Review: A cold reader from a different model family than the creator receives only the judgment criteria file, captures, and CLAIMS / NOTES / README (no mutual judgments, no hint of the creator's identity). The yardstick is E1 / E2 / E4 (+ E3 as reference). Criteria template:
references/judging.md.
10. Publication (When Accompanying a Paper)
- Show the live page via GitHub Pages (static site). Freeze a release of the same repo with a Zenodo DOI (Zenodo does not render HTML, but the bundle can be opened via
file://). Write both in the paper. - Remove internal layers (§8) from the public bundle. Retain the Anatomy MIT notice (Copyright (c) 2026 Ryan) in the README and at the bottom of pages.
- Include this SKILL.md itself in the bundle: even if full reproduction is impossible, it shows the procedure (prompts) used to create the figure.
- Include md5 in MANIFEST. →
references/publishing.md.