| name | report |
| description | Fires when producing a report or completion notice. Generates a report that includes the interlock verification section. |
Report Output Skill
Trigger
Fires at task completion, at interruption, or when the human asks "report it."
Where the Report Goes
The report for the design AI is written as an MD file.
In-conversation text does not count as "outputting a report."
Two-tier structure: dev log + canonical report:
- Upstream doc repo: canonical report (judgment-centric: design decisions, rumination, proposals). Readers: design AI / human decision-maker
- Working repo: dev log (fact-centric: diffs, commit unit). Readers: next-session CC / future maintainers
- When in doubt, write both (cross-navigate to maintain integrity)
Figure Plan (before writing — required)
Before writing the body, fire the diagram-craft skill, decide the figures via its trigger table, and declare them in frontmatter:
figures: [da-table, where-map]
figures: none
figures_reason: <one-line reason>
- Silently omitting figures is forbidden. Every declared kind must have a body counterpart (
--lint machine-checks declaration-reality match)
- The 4 cognitive-load-reduction anchors the reader looks at first: pending-decisions panel / current-location map (where-map) / DA table bars / out-of-scope ledger. Structuring decision material into these 4 anchors takes top priority
Readers and Purpose of This Report (required)
The report MUST start with the following section right after the frontmatter:
## Readers and Purpose of This Report
- **Who reads it**: <primary audience, in order of priority if multiple>
- **For what purpose**: <information the reader should obtain, why they should read it>
- **Next action**: <action expected from the reader after finishing the report>
Also recommended in frontmatter (machine-readable, optional):
audience: [<FILL: specify the primary reader role>]
purpose: <FILL: one-line summary>
expected_action: <FILL: one-line summary>
Skipping this section with "N/A" is forbidden. If the reader is unclear, revisit the design.
Conclusion Summary (required — right after Readers & Purpose)
Reports follow the order Readers & Purpose → Conclusion Summary → (pending-decisions / TOC = renderer-automatic) → Details. So the reader grasps the conclusion and its "good/bad direction" up front, always place it right after Readers & Purpose (md-render auto-hoists it):
## Conclusion Summary
- **OK** — <conclusion (has a measured verification PASS)>
- **CAVEAT** — <conclusion (works, but conditional / open issues)>
- **FAIL** — <conclusion (measured breakage / unresolved)>
- **INFO** — <conclusion (neutral / out of scope)>
- Content: a 1–5 line outcome (what the reader should now believe / do). Do not rephrase Readers & Purpose, duplicate the decision list, or pad it (it is not a second TOC).
- Status badge: a leading
**OK/FAIL/CAVEAT/INFO** is converted by md-render into a colored pill (OK=teal / FAIL=red / CAVEAT=amber / INFO=slate). Only bold that exactly matches the set is converted (**OK:**, **OK …** are not).
- ★No badge without grounds (honesty standard — most important): every badge states its grounds. OK = a measured verification PASS exists / FAIL = measured breakage or unresolved / CAVEAT = works but conditional, open issues / INFO = neutral, out of scope. A groundless "OK" is forbidden (a brake against the report drifting toward "looking good"). For mixed cases, reflect the principal outcome / risk (if the core failed, it is FAIL even if parts work; anti-gaming demotions like FAIL→CAVEAT are forbidden).
- Do not hand-write the pending-decisions list or TOC: the pending-decisions list is auto-generated by the renderer from
> [!DECISION] in the body, and the TOC from headings. The author writes only Readers & Purpose, Conclusion Summary, [!DECISION], Details, and Out-of-Scope (Pending). If a conclusion requires action, mirror it into [!DECISION] (Conclusion Summary = direction / [!DECISION] = decision & action).
- Exemption: pure descriptive memos / minutes / references etc. are exempt via frontmatter
conclusion_summary: none + conclusion_summary_reason: <reason> (same shape as figures: none; --lint checks it).
Interlock Verification Section (required)
Include the following checklist in the report:
## Interlock Verification
- rumination: fired / not fired (reason: )
- testable-impl: fired / not fired (reason: )
- investigation: fired / not fired (reason: )
- diagram-craft: fired / not fired (reason: )
- md2html --lint: exit 0 / not run (reason: )
- md2html --check: run / not applicable (reason: _index.md not updated, etc.)
If any "not fired" entry lacks a justified reason, stop the report and re-fire the missing skill.
Knowledge Accumulation Proposal (mandatory consideration)
Include the following in the report. Evaluate candidates; if none are needed, state why. Skipping this section with "N/A" is forbidden.
## Local Knowledge Proposal
- Candidates: (Is there any knowledge worth storing in rules/ or skills/?)
- Decision: adopt / not needed (reason: )
Allowed Syntax (closed set of 8)
Report MDs use only the 8 syntax kinds supported by the deterministic renderer (md-render).
No italics, strikethrough, images, footnotes, or raw HTML tags (using them merely degrades to literal display; no content is lost).
| # | Syntax | Use |
|---|
| 1 | YAML frontmatter (scalars + inline lists) | doc_id / revision / audience / where / status / figures |
| 2 | Headings H1–H4 | document title / §N / subsections |
| 3 | GFM tables | DA tables / pending ledger / comparisons |
| 4 | Fenced code (with info string; mermaid / svg special-cased) | code quotes / figure sources. SVG is converted by the renderer into a base64 data-URI img (scripts neutralized) |
| 5 | blockquote + [!DECISION] [!DA] admonitions | decision markers |
| 6 | Bullet / numbered lists (≤2 nesting levels) | enumerations |
| 7 | Horizontal rule --- | separators |
| 8 | Inline: code span / bold / link | emphasis / references |
Optional Tabs (frontmatter tabs: by-h2)
For long status reports, declare tabs: by-h2 in frontmatter to present the top-level body H2 sections as tabs (deterministic renderer extension — not a new syntax). Use it when the report has ≥2 such sections (e.g. purpose / history / now / next / open issues). The audience / decisions / TOC / pending panels and the lead stay outside the tabs; with JS disabled every section stays readable (fail-soft). Labels are the H2 heading text — number your headings if you want numbered tabs. See the md-render skill for details and the CSP note.
Comments & Reply Prompt (default on for reports)
Every report you render gets, by default, a per-topic comment box under each body H2 plus a one-click "reply prompt" generator (the user comments while reading → generate → copy → hand to a reviewer / CC). Requirements & notes:
- Include a stable
report_id (or doc_id) in frontmatter — comments key off it and are stored in the reader's localStorage (never written back into the MD/HTML). Without a stable id, comments are disabled.
- Give every body H2 a unique heading (identical headings share one sha1 anchor and merge comments;
--lint warns).
- Suppress with
comments: off (e.g. for dev logs / non-interactive docs).
- The renderer only produces the reply prompt (fixed-format, LLM-free) + copy button; writing the reply itself is out of scope. See the md-render skill for details.
Decision Marker Rules
| Requirement | How to write |
|---|
| Design decision points | > [!DECISION] <title> (auto-aggregated into the pending-decisions panel) |
| DA recommendation | > [!DA] <recommendation + one-sentence reason> (optional) |
| Current location (Where) | frontmatter where: A > B > C + ## Current Location section + where-map figure when needed |
| Out-of-scope accounting | fixed heading ## Out-of-Scope Proposals (Pending) + table |
Evaluation Axis Direction Rule (DA tables)
- When you have discretion over an axis direction, align it so that higher = positive, within the bounds of zero distortion (e.g. rephrase "cost" as "cost efficiency" when natural). The bar value color (high = magenta) then naturally matches goodness, speeding up reading
- Forbidden: distortion for the sake of alignment (forced reciprocals, unnatural indicators, data manipulation)
- Axes that are naturally "lower is better" stay as-is (bar colors are meaning-neutral position indicators; goodness is read from the header and numbers)
- Criterion: can it be aligned to "higher = better" naturally and without distortion? Yes → align / No → leave as-is
HTML Derivation and Renderer Procedure
The MD is canonical. HTML is derived (HTML ⊆ MD); reporting obligations are fulfilled by the MD alone.
- After saving the MD, generate HTML:
node ~/.claude/skills/md-render/md2html.cjs <report.md> <report.html> (in environments without md-render, skip HTML generation — the canonical MD suffices)
- Run
--lint <report.md> and confirm exit 0 (bidirectional machine check of figures declaration-reality match: declared→present and present→declared; on exit 1, fix and re-run)
- Run
--verify <report.md> for bidirectional verification (zero fabrication / omission)
- If
_index.md was updated, regenerate _index.html and confirm freshness with --check <_index.md> <_index.html>
- How to present the HTML follows the Presentation Rules below
Presentation Rules (operator-node detection + delivery)
Principle: no authoritative signal for the operator node exists. Machine detection is primary; when undecidable, always fall to the safe default (no auto-launch). Falling back to a default node is forbidden (eliminates the structure where omissions become misdelivery).
Operator-node detection (evaluate top-down; adopt the first tier that holds)
| Tier | Conditions (all AND) | Result |
|---|
| 1. Local interactive | SSH_CONNECTION/SSH_CLIENT/SSH_TTY all unset + TMUX/STY unset + execution node is a physically-seatable node | operator = execution node |
| 2. SSH tailnet | SSH_CONNECTION set + TMUX/STY unset + client IP resolves via tailscale whois to a physically-seatable node | operator = resolved node |
| 3. State file | first line of ~/.ccpit/operator-node is a seatable node name + mtime within 2 hours | operator = stated node |
| 4. Safe default | none of the above | operator unknown → no auto-launch; present URL + path only |
- Execution node =
currentProfile in ~/.ccpit/app-config.json (authoritative signal)
- The seatable-node set is defined per environment (headless servers and phones are excluded). Any resolution outside the set is treated as undecidable
SSH_CONNECTION inside tmux/screen can be stale — never use it to confirm the operator
- Operator-node designation via instruction frontmatter is abolished. Only an optional
allow_autolaunch: false (delivery policy) is accepted, which suppresses auto-launch even when the operator is confirmed. Omission is safe
- The state file is a human override for exceptional cases only (never demanded routinely; expiry invalidates it = forgetting decays to the safe side)
- Command snippets for detection/serving:
templates/present.md (verified commands only)
Delivery
| Detection result | Delivery |
|---|
| operator = execution node | Direct launch allowed (Windows Start-Process / macOS open / Linux desktop xdg-open). Auto-launch only for final deliverables; interim reports stay at file:// presentation |
| operator ≠ execution node (confirmed) | Tailscale serving: copy the HTML into a staging dir → local HTTP server bound to 127.0.0.1 only → tailscale serve --bg --http=80 <port> → present http://<exec-node tailnet name>.ts.net/<file> (include the cleanup procedure). After acknowledgment, always perform the 3-step cleanup (tailscale serve reset, stop the serving process, remove the staging dir) — resetting the proxy alone leaves staged leftovers re-exposable on the next serve |
| operator unknown (safe default) | No auto-launch. Present both the Tailscale URL and the file:// path |
tailscale funnel is absolutely forbidden (public internet exposure). Confirm "tailnet only" in the serve status output
- Never serve the repository directly (copy only the target files into staging)
Migration for Existing Reports (grandfather)
- The
figures declaration rule and the --lint figures checks apply only to reports newly written after this revision
- No retroactive linting or frontmatter retrofitting of existing reports (bulk lint application is forbidden)
- When regenerating HTML for an existing report, adding
figures is optional