Skill Tracer
Skills › Archify › archify › explainer-authoring.md

explainer-authoring.md

274 lines · archify/references/explainer-authoring.md at a406594

Open on GitHub

Most marks come from matching words in the file, so treat them as pointers.

1# Explainer authoring
2
3An explainer turns an answer with a conclusion and some structure (an explanation, comparison, decision, diagnosis, review or plan) into one page. The page leads with the conclusion and shows the reasoning as panels: diagrams, tables, steps and short text. When to make one, and the opt-in modes, are in the Skill under “Choose the artifact”. A request to draw a system uses a native diagram type.
4
5This guide is the complete draft language. Write the draft from it directly.
6

Explainer authoring

An explainer turns an answer with a conclusion and some structure (an explanation, comparison, decision, diagnosis, review or plan) into one page. The page leads with the conclusion and shows the reasoning as panels: diagrams, tables, steps and short text. When to make one, and the opt-in modes, are in the Skill under “Choose the artifact”. A request to draw a system uses a native diagram type.

This guide is the complete draft language. Write the draft from it directly.

Raw lines 1 to 6
7## Draft
8
9Write one Markdown file, `candidate.archify.md`. The first paragraph after the title is the direct conclusion. A flat list immediately after it gives up to four reasons. Each `##` heading starts a panel.
11```md
12# Why does the first HTTPS visit take an extra round trip? {#tls-first-visit}
14The browser and server must agree on keys before any request is sent: **one extra round trip** with TLS 1.3.
16- The browser sends its key share in the first message, so one round trip is enough.[](source:rfc8446)
17- The server replies with its key share, then its certificate, already encrypted.
18- A returning browser can resume and send data immediately.
20@answer scope="TLS 1.3 · first visit · no proxy"
21@meta locale=en
22@source rfc8446 title="RFC 8446: TLS 1.3" url=https://www.rfc-editor.org/rfc/rfc8446
24## What is exchanged before the first request? {#handshake}
26@sequence id=handshake-flow title="TLS 1.3 full handshake"
27| actor browser | Browser | frontend |
28| actor server | Server | backend |
29| browser | server | ClientHello + key share |
30| server | browser | ServerHello + key share | return |
31| server | browser | Certificate + Finished (encrypted) | return |
32| browser | server | Finished + GET / | emphasis |
33| server | browser | 200 OK | return |
35@steps id=handshake-steps
36| hello | ClientHello | Offers cipher suites and a key share. | handshake-flow | browser |
37| reply | ServerHello | Picks a suite and sends its key share; the certificate follows encrypted. | handshake-flow | server |
38| done | Finished | Both sides confirm the keys; the request rides along. | handshake-flow | browser |
40## How does TLS 1.3 compare with 1.2? {#versions}
42| Criterion | TLS 1.2 | TLS 1.3 |
43| --- | --- | --- |
44| Round trips before data | Two {caution:Slower} | One {good:Faster} |
45| Resumed connection | One | Zero {good:0-RTT} |
46```
48Deliver it with the command under [Delivery](#delivery).

Draft

Write one Markdown file, candidate.archify.md. The first paragraph after the title is the direct conclusion. A flat list immediately after it gives up to four reasons. Each ## heading starts a panel.

# Why does the first HTTPS visit take an extra round trip? {#tls-first-visit}

The browser and server must agree on keys before any request is sent: **one extra round trip** with TLS 1.3.

- The browser sends its key share in the first message, so one round trip is enough.[](source:rfc8446)
- The server replies with its key share, then its certificate, already encrypted.
- A returning browser can resume and send data immediately.

@answer scope="TLS 1.3 · first visit · no proxy"
@meta locale=en
@source rfc8446 title="RFC 8446: TLS 1.3" url=https://www.rfc-editor.org/rfc/rfc8446

## What is exchanged before the first request? {#handshake}

@sequence id=handshake-flow title="TLS 1.3 full handshake"
| actor browser | Browser | frontend |
| actor server | Server | backend |
| browser | server | ClientHello + key share |
| server | browser | ServerHello + key share | return |
| server | browser | Certificate + Finished (encrypted) | return |
| browser | server | Finished + GET / | emphasis |
| server | browser | 200 OK | return |

@steps id=handshake-steps
| hello | ClientHello | Offers cipher suites and a key share. | handshake-flow | browser |
| reply | ServerHello | Picks a suite and sends its key share; the certificate follows encrypted. | handshake-flow | server |
| done | Finished | Both sides confirm the keys; the request rides along. | handshake-flow | browser |

## How does TLS 1.3 compare with 1.2? {#versions}

| Criterion | TLS 1.2 | TLS 1.3 |
| --- | --- | --- |
| Round trips before data | Two {caution:Slower} | One {good:Faster} |
| Resumed connection | One | Zero {good:0-RTT} |

Deliver it with the command under Delivery.

Raw lines 7 to 49
50### Rules that keep a draft valid
52- IDs are unique across the whole document: panels, blocks, diagrams and steps share one namespace. Give a block an `id` only when a step, link or patch targets it; omit it on callouts, facts and lists. Name a diagram after its content (`handshake-flow`), not after its panel (`handshake`).
53- Prose is plain text. Wrap file paths, globs, `<placeholders>`, operators and code in backticks: a bare `<`, `>` or `*` in prose fails as HTML or emphasis. Inline code is shown literally.
54- Directive rows are pipe rows, one per line, each with the documented number of cells: `| first | second |`. Write a literal pipe inside a cell as `\|`. A blank line or the next `##` or `@` line ends the rows.
55- Directive arguments are `key=value`; quote values with spaces using double quotes and JSON escaping.
56- Draw native diagrams with the compact rows below. Inline JSON specs are for exceptional cases only.
57- Nested lists, raw HTML and other Markdown extensions fail with a located diagnostic that names the line, component and a repair example.

Rules that keep a draft valid

  • IDs are unique across the whole document: panels, blocks, diagrams and steps share one namespace. Give a block an id only when a step, link or patch targets it; omit it on callouts, facts and lists. Name a diagram after its content (handshake-flow), not after its panel (handshake).
  • Prose is plain text. Wrap file paths, globs, <placeholders>, operators and code in backticks: a bare <, > or * in prose fails as HTML or emphasis. Inline code is shown literally.
  • Directive rows are pipe rows, one per line, each with the documented number of cells: | first | second |. Write a literal pipe inside a cell as \|. A blank line or the next ## or @ line ends the rows.
  • Directive arguments are key=value; quote values with spaces using double quotes and JSON escaping.
  • Draw native diagrams with the compact rows below. Inline JSON specs are for exceptional cases only.
  • Nested lists, raw HTML and other Markdown extensions fail with a located diagnostic that names the line, component and a repair example.
Raw lines 50 to 58
59## Choose the form by the shape of the information
61A diagram replaces the paragraph that would describe it. When the answer involves relationships, a flow, an exchange over time, a hierarchy, a history or a data model, draw it. A typical page has the conclusion, one diagram and one or two tables or step lists.
63| Shape of the information | Form |
64| --- | --- |
65| Messages between parties in order: protocols, request paths | `@sequence` |
66| A process with steps and branches: triage, rollout, approval | `@workflow` |
67| Parts of a system and how they connect | `@architecture` |
68| A hierarchy: directories, modules, taxonomies | `@tree` |
69| Events over time: incidents, releases | `@timeline` |
70| Entities with fields and relationships | `@erd` |
71| Options compared on several criteria | Markdown table with `{good:…}`, `{caution:…}`, `{bad:…}` cells |
72| Ordered actions, checks or stages | `@steps` |
73| Things the reader must do or verify | Task list, `- [ ] item` |
74| A warning, open question or key caveat | `@callout` |
75| A few labelled facts | `@facts` |
76| Numbers compared across items or over time, shares of a whole, a 2×2 priority, flows of quantity | ```` ```mermaid ```` chart fence |
77| One number against a limit | `@metric` |
78| Code that exists in a repository | `@code` |
79| A change to code | `@diff` or a ```` ```diff ```` fence |
80| A command, config or code that does not exist yet | Plain fence |
82Steps that walk through a diagram belong in the diagram's panel: the page reads them beside it, each step lighting its part, and the reader can step through them. Title each step with the label of the node it points at, so the text and the diagram match at a glance; the detail column says what to do there.
84A small answer gets a small page: the conclusion plus one or two panels. A how-it-works, diagnosis or checklist question usually needs three to five.

Choose the form by the shape of the information

A diagram replaces the paragraph that would describe it. When the answer involves relationships, a flow, an exchange over time, a hierarchy, a history or a data model, draw it. A typical page has the conclusion, one diagram and one or two tables or step lists.

Shape of the informationForm
Messages between parties in order: protocols, request paths@sequence
A process with steps and branches: triage, rollout, approval@workflow
Parts of a system and how they connect@architecture
A hierarchy: directories, modules, taxonomies@tree
Events over time: incidents, releases@timeline
Entities with fields and relationships@erd
Options compared on several criteriaMarkdown table with {good:…}, {caution:…}, {bad:…} cells
Ordered actions, checks or stages@steps
Things the reader must do or verifyTask list, - [ ] item
A warning, open question or key caveat@callout
A few labelled facts@facts
Numbers compared across items or over time, shares of a whole, a 2×2 priority, flows of quantity` `mermaid ``` chart fence
One number against a limit@metric
Code that exists in a repository@code
A change to code@diff or a ``` `diff ``` fence
A command, config or code that does not exist yetPlain fence

Steps that walk through a diagram belong in the diagram's panel: the page reads them beside it, each step lighting its part, and the reader can step through them. Title each step with the label of the node it points at, so the text and the diagram match at a glance; the detail column says what to do there.

A small answer gets a small page: the conclusion plus one or two panels. A how-it-works, diagnosis or checklist question usually needs three to five.

Raw lines 59 to 85
86## Writing
88Write for a reader who will act on the page and may check it. Use the user's language.
90- The conclusion is read first; every panel after it supports, qualifies or applies it. Stop once nothing is left to support.
91- Cover what the reader needs to act on the answer: the mechanism behind the conclusion, how to check it, and the cases where it does not hold. The next question a careful reader would ask gets a panel, a table row or a line in scope; a fact the reader could get wrong without it is not optional.
92- Each panel takes one question and each sentence makes one claim. A claim a table or diagram already shows is not restated; the text adds its reason or exception.
93- Keep one term per thing across the title, panels, diagram labels and table headers, and prefer the reader's own term. The page links a name in the text to the node with that label, so a reader can point at it in the diagram.
94- Give results with their evidence: a number with its unit, a file position, a source. When a value is unknown or estimated, say so in scope.
95- Cite a `@source` for each claim the reader cannot check alone: protocol details, thresholds, benchmark figures, API behaviour. A rule of thumb without a source is labelled as one, or left out.
96- Recompute every derived number before delivery and show the arithmetic once: “990 of 1000 requests at 80 ms → P99 = 80 ms; 11 slow → P99 = 600 ms.” Totals in tables add up.
97- Phrase an action as an imperative with its trigger in front: “If the migration reports a schema mismatch, roll it back before retrying.”
98- When the reader must act or verify, end with a checklist panel: `- [ ] item`, one concrete check per item. Readers tick items on the page.
100English: short sentences (under about 25 words), common words (use, before, to, because), active voice with a named actor.
102中文:短句,每句不超过约 50 字;动词直接用(检查、决定,而不是进行检查、做出决定);一句话里的“的”不超过两个;数字后写清边界(超过 3 次、不超过 1 秒);用具体结果代替套话(赋能、全方位、至关重要)。

Writing

Write for a reader who will act on the page and may check it. Use the user's language.

  • The conclusion is read first; every panel after it supports, qualifies or applies it. Stop once nothing is left to support.
  • Cover what the reader needs to act on the answer: the mechanism behind the conclusion, how to check it, and the cases where it does not hold. The next question a careful reader would ask gets a panel, a table row or a line in scope; a fact the reader could get wrong without it is not optional.
  • Each panel takes one question and each sentence makes one claim. A claim a table or diagram already shows is not restated; the text adds its reason or exception.
  • Keep one term per thing across the title, panels, diagram labels and table headers, and prefer the reader's own term. The page links a name in the text to the node with that label, so a reader can point at it in the diagram.
  • Give results with their evidence: a number with its unit, a file position, a source. When a value is unknown or estimated, say so in scope.
  • Cite a @source for each claim the reader cannot check alone: protocol details, thresholds, benchmark figures, API behaviour. A rule of thumb without a source is labelled as one, or left out.
  • Recompute every derived number before delivery and show the arithmetic once: “990 of 1000 requests at 80 ms → P99 = 80 ms; 11 slow → P99 = 600 ms.” Totals in tables add up.
  • Phrase an action as an imperative with its trigger in front: “If the migration reports a schema mismatch, roll it back before retrying.”
  • When the reader must act or verify, end with a checklist panel: - [ ] item, one concrete check per item. Readers tick items on the page.

English: short sentences (under about 25 words), common words (use, before, to, because), active voice with a named actor.

中文:短句,每句不超过约 50 字;动词直接用(检查、决定,而不是进行检查、做出决定);一句话里的“的”不超过两个;数字后写清边界(超过 3 次、不超过 1 秒);用具体结果代替套话(赋能、全方位、至关重要)。

Raw lines 86 to 103
104## Compact native diagrams
106Write `@<type> id=<diagram-id> title="..."` followed by pipe rows. Each compiles to a full native Archify diagram, with native validation and layout, and opens in the full Viewer from the page. A document holds up to four native diagrams.
108Any node, actor or entity row may end with a `source:<id>` cell naming a declared `@source`; hovering that node shows the source, and for a repository file its pinned lines, so a code diagram doubles as a code tour.
110Node and participant types: `frontend`, `backend`, `database`, `cloud`, `security`, `messagebus`, `external` (default `backend`). Edge and message variants: `default`, `emphasis`, `security`, `dashed`; sequences also accept `return`. IDs start with a letter and use letters, digits, `-` and `_`.
112**`@sequence`**: declare actors, then messages in order.
114```md
115@sequence id=cache-read title="Cache miss"
116| actor api | Order API | backend |
117| actor redis | Redis | database |
118| api | redis | GET order:42 |
119| redis | api | nil | return |
120```
122Actor rows: `actor <id> | label | type`. Message rows: `from | to | label | variant?`, where `from` and `to` are actor IDs or labels. A `phase | label` row opens a labelled band over the messages after it, up to the next phase: `phase | TCP handshake (1 RTT)`.
124**`@workflow`** and **`@architecture`**: nodes, then edges. Placement follows the edges from left to right, starting with nodes that have no incoming edge.
126```md
127@workflow id=triage title="Latency triage"
128| alert | Alert fires | external |
129| split | Check percentiles | backend |
130| trace | Compare slow traces | backend |
131| fix | Fix the cause | backend |
132| alert > split | |
133| split > trace | tail only |
134| trace > fix | cause found | emphasis |
135```
137Node rows: `id | label | type?`. Edge rows: `from > to | label? | variant?`. Nodes widen to fit their labels, so a node label names the step in a few words (up to about 10 Chinese characters or 4 English words) and `@steps` carries the detail. Keep edge labels to one or two words. A node label ending in `?` is drawn as a decision; label its outgoing edges with the answers (`yes`, `no`, `是`, `否`).
139Group the steps of a process into phases: declare `lane <id> | label` rows, then give each workflow node its phase as a fourth cell. Up to six nodes draw as one row with the phase labels above it; a longer process wraps into one row per phase.
141```md
142@workflow id=p99-flow title="P99 triage"
143| lane confirm | Confirm the symptom |
144| lane locate | Locate the cause |
145| alert | P99 up, mean flat | external | confirm |
146| window | Align window and percentiles | backend | confirm |
147| sample | Sample slow requests | backend | locate |
148| fix | Fix and verify | backend | locate |
149| alert > window | |
150| window > sample | tail grew |
151| sample > fix | cause | emphasis |
152```
154Architecture allows twelve columns. Use `@architecture` for components that talk to each other and `@workflow` for steps a reader follows.
156**`@tree`**: one row per node, `id | label | parent`; the root's parent is `-`.
158```md
159@tree id=package-layout title="Package layout"
160| root | archify | - |
161| bin | bin | root |
162| explainer | explainer | root |
163```
165**`@timeline`**: optional lane rows, then events, `id | ISO time with offset | title | lane? | kind?`. Kinds: `default`, `change`, `alert`, `action`, `recovery`.
167```md
168@timeline id=incident title="Checkout incident"
169| lane ops | Operations |
170| deploy | 2026-10-01T10:00:00+08:00 | Deploy v2 | ops | change |
171| alarm | 2026-10-01T10:12:00+08:00 | Error rate alarm | ops | alert |
172```
174Shorthand timelines are labelled illustrative and display their times in UTC.
176**`@erd`**: entities, fields, then relationships.
178```md
179@erd id=order-model title="Orders"
180| entity user | User |
181| entity order | Order |
182| user.id | bigint | pk |
183| order.id | bigint | pk |
184| order.user_id | bigint | fk | user.id |
185| order > user | many:one | placed by |
186```
188Field rows: `entity.field | type | keys? | references?`, keys `pk`, `fk`, `uk` comma-separated. Relationship rows: `from > to | one:one|one:many|many:one|many:many | label?`.
190Other native types (`dataflow`, `lifecycle`, `class`, `waterfall`) and diagrams that need explicit geometry use a same-directory spec file: `@diagram dataflow source=events.dataflow.json`, written with the Skill's native authoring workflow.

Compact native diagrams

Write @<type> id=<diagram-id> title="..." followed by pipe rows. Each compiles to a full native Archify diagram, with native validation and layout, and opens in the full Viewer from the page. A document holds up to four native diagrams.

Any node, actor or entity row may end with a source:<id> cell naming a declared @source; hovering that node shows the source, and for a repository file its pinned lines, so a code diagram doubles as a code tour.

Node and participant types: frontend, backend, database, cloud, security, messagebus, external (default backend). Edge and message variants: default, emphasis, security, dashed; sequences also accept return. IDs start with a letter and use letters, digits, - and _.

**@sequence**: declare actors, then messages in order.

@sequence id=cache-read title="Cache miss"
| actor api | Order API | backend |
| actor redis | Redis | database |
| api | redis | GET order:42 |
| redis | api | nil | return |

Actor rows: actor <id> | label | type. Message rows: from | to | label | variant?, where from and to are actor IDs or labels. A phase | label row opens a labelled band over the messages after it, up to the next phase: phase | TCP handshake (1 RTT).

**@workflow and @architecture**: nodes, then edges. Placement follows the edges from left to right, starting with nodes that have no incoming edge.

@workflow id=triage title="Latency triage"
| alert | Alert fires | external |
| split | Check percentiles | backend |
| trace | Compare slow traces | backend |
| fix | Fix the cause | backend |
| alert > split | |
| split > trace | tail only |
| trace > fix | cause found | emphasis |

Node rows: id | label | type?. Edge rows: from > to | label? | variant?. Nodes widen to fit their labels, so a node label names the step in a few words (up to about 10 Chinese characters or 4 English words) and @steps carries the detail. Keep edge labels to one or two words. A node label ending in ? is drawn as a decision; label its outgoing edges with the answers (yes, no, 是, 否).

Group the steps of a process into phases: declare lane <id> | label rows, then give each workflow node its phase as a fourth cell. Up to six nodes draw as one row with the phase labels above it; a longer process wraps into one row per phase.

@workflow id=p99-flow title="P99 triage"
| lane confirm | Confirm the symptom |
| lane locate | Locate the cause |
| alert | P99 up, mean flat | external | confirm |
| window | Align window and percentiles | backend | confirm |
| sample | Sample slow requests | backend | locate |
| fix | Fix and verify | backend | locate |
| alert > window | |
| window > sample | tail grew |
| sample > fix | cause | emphasis |

Architecture allows twelve columns. Use @architecture for components that talk to each other and @workflow for steps a reader follows.

**@tree**: one row per node, id | label | parent; the root's parent is -.

@tree id=package-layout title="Package layout"
| root | archify | - |
| bin | bin | root |
| explainer | explainer | root |

**@timeline**: optional lane rows, then events, id | ISO time with offset | title | lane? | kind?. Kinds: default, change, alert, action, recovery.

@timeline id=incident title="Checkout incident"
| lane ops | Operations |
| deploy | 2026-10-01T10:00:00+08:00 | Deploy v2 | ops | change |
| alarm | 2026-10-01T10:12:00+08:00 | Error rate alarm | ops | alert |

Shorthand timelines are labelled illustrative and display their times in UTC.

**@erd**: entities, fields, then relationships.

@erd id=order-model title="Orders"
| entity user | User |
| entity order | Order |
| user.id | bigint | pk |
| order.id | bigint | pk |
| order.user_id | bigint | fk | user.id |
| order > user | many:one | placed by |

Field rows: entity.field | type | keys? | references?, keys pk, fk, uk comma-separated. Relationship rows: from > to | one:one|one:many|many:one|many:many | label?.

Other native types (dataflow, lifecycle, class, waterfall) and diagrams that need explicit geometry use a same-directory spec file: @diagram dataflow source=events.dataflow.json, written with the Skill's native authoring workflow.

Raw lines 104 to 191
192## Charts
194A ```` ```mermaid ```` fence draws a chart from numbers: `pie`, `xychart-beta` (bar and line), `quadrantChart`, `sankey-beta`, `radar-beta` or `venn-beta`. The page renders it to static SVG in the page theme. An optional `title="..."` becomes the caption.
196````md
197```mermaid title="Latency before and after the release (ms)"
198xychart-beta
199 x-axis ["Mean", "P50", "P99"]
200 y-axis "ms" 0 --> 700
201 bar "Before" [80, 75, 80]
202 bar "After" [88, 76, 600]
203```
204````
206Name each series (`bar "Before" [...]`) so the chart gets a legend. Bars show their values, and a pie legend shows each value with its share. Use `xychart-beta horizontal` for ranked items or long category names. When numbers carry the point, such as one value jumping while others stay flat, a before/after or a share, chart them so the contrast is seen at a glance; a table under the chart adds only the words each number needs. Put the contrast in one chart, such as mean, P50 and P99 before and after.
208When the numbers are in a CSV or JSON file next to the draft, chart the file instead of copying its values: `@chart type=bar|line|pie data=latency.csv x=day y=p50,p99 unit=ms title="..."`. `x` names the label column and `y` one value column per series (a pie uses the first). CSV needs a header row; JSON is an array of objects. The file is read and frozen at delivery, up to 60 rows (12 for a pie). A blank value is an error, not zero: fill it in, or leave the row out and say so in the caption.
210A chart states where its numbers come from the same way text does: measured, from a source, estimated or illustrative, in its caption or in scope. Quote every label that contains spaces or non-ASCII text. Flowcharts, sequences, class, ER, state, timeline and mind-map Mermaid use the native shorthand above, which Archify validates and lets readers explore.

Charts

A ``` `mermaid fence draws a chart from numbers: pie, xychart-beta (bar and line), quadrantChart, sankey-beta, radar-beta or venn-beta. The page renders it to static SVG in the page theme. An optional title="..."` becomes the caption.

xychart-beta x-axis ["Mean", "P50", "P99"] y-axis "ms" 0 --> 700 bar "Before" [80, 75, 80] bar "After" [88, 76, 600]

Name each series (bar "Before" [...]) so the chart gets a legend. Bars show their values, and a pie legend shows each value with its share. Use xychart-beta horizontal for ranked items or long category names. When numbers carry the point, such as one value jumping while others stay flat, a before/after or a share, chart them so the contrast is seen at a glance; a table under the chart adds only the words each number needs. Put the contrast in one chart, such as mean, P50 and P99 before and after.

When the numbers are in a CSV or JSON file next to the draft, chart the file instead of copying its values: @chart type=bar|line|pie data=latency.csv x=day y=p50,p99 unit=ms title="...". x names the label column and y one value column per series (a pie uses the first). CSV needs a header row; JSON is an array of objects. The file is read and frozen at delivery, up to 60 rows (12 for a pie). A blank value is an error, not zero: fill it in, or leave the row out and say so in the caption.

A chart states where its numbers come from the same way text does: measured, from a source, estimated or illustrative, in its caption or in scope. Quote every label that contains spaces or non-ASCII text. Flowcharts, sequences, class, ER, state, timeline and mind-map Mermaid use the native shorthand above, which Archify validates and lets readers explore.

Raw lines 192 to 211
212## Directive reference
214| Directive | Header arguments | Rows |
215| --- | --- | --- |
216| `@answer` | `scope="..."` | none |
217| `@meta` | `locale` (`en`, `zh-CN`, `zh-TW`, `es`, `ko`, `ar`), `quality_profile`, `style` (`clean`, `editorial`, `product`, `swiss`; readers can switch), `repo_url`, `repo_revision` | none |
218| `@source <id>` | `title`, `url`, or `path` with `lines=start:end` | none |
219| `@steps` | `id` | `id | title | detail? | diagram-id? | node? | from~to? | edge-ids?` (node and route are exclusive) |
220| `@callout` | `id`, `level=note|warning|open-question`, `title` | one cell per row; rows join into paragraphs |
221| `@facts` | `id` | `label | value` |
222| `@metric` | `id`, `label`, `value`, `limit`, `unit`, `note`, `typical=true` | none; `value` or `limit` required |
223| `@comparison` | `id`, `columns="A,B"`, `label` | `criterion | cell per option` |
224| `@prose` | `id`, `text` | one cell per row |
225| `@list` | `id`, `ordered=true` | one cell per row |
226| `@code` | `id`, `source=<source-id>`, `language` | none |
227| `@diff` | `id`, `caption` | a following ```` ```diff ```` fence |
228| `@image` | `id`, `path`, `alt`, `caption` | none |
229| `@chart` | `type` (`bar`, `line`, `pie`), `data` (`.csv` or `.json`), `x`, `y`, `unit`, `title`, `id` | none |
230| `@<diagram type>` | `id`, `title`, `changes` | compact rows above |
231| `@diagram <type>` | `id`, `source`, `title` | none |
233Plain paragraphs, flat lists and Markdown tables need no directive. A table's first header cell labels the row column; comparison cells may end with `{good:Label}`, `{caution:Label}` or `{bad:Label}`, and row labels with `{#row-id}`. Mark only the cells that decide the comparison, usually one or two per row; a badge in every cell reads as noise.
235A plain fence (```` ```bash title="Run the tests" ````) is a literal snippet with a copy button. `@code` obtains a real excerpt from the source's Git commit and line range; it accepts no authored code text. `@image` embeds a contained local PNG, JPEG, GIF or WebP.

Directive reference

DirectiveHeader argumentsRows
@answerscope="..."none
@metalocale (en, zh-CN, zh-TW, es, ko, ar), quality_profile, style (clean, editorial, product, swiss; readers can switch), repo_url, repo_revisionnone
@source <id>title, url, or path with lines=start:endnone
@stepsid`idtitledetail?diagram-id?node?from~to?edge-ids?` (node and route are exclusive)
@calloutid, `level=notewarningopen-question, title`one cell per row; rows join into paragraphs
@factsid`labelvalue`
@metricid, label, value, limit, unit, note, typical=truenone; value or limit required
@comparisonid, columns="A,B", label`criterioncell per option`
@proseid, textone cell per row
@listid, ordered=trueone cell per row
@codeid, source=<source-id>, languagenone
@diffid, captiona following ``` `diff ``` fence
@imageid, path, alt, captionnone
@charttype (bar, line, pie), data (.csv or .json), x, y, unit, title, idnone
@<diagram type>id, title, changescompact rows above
@diagram <type>id, source, titlenone

Plain paragraphs, flat lists and Markdown tables need no directive. A table's first header cell labels the row column; comparison cells may end with {good:Label}, {caution:Label} or {bad:Label}, and row labels with {#row-id}. Mark only the cells that decide the comparison, usually one or two per row; a badge in every cell reads as noise.

A plain fence (``` `bash title="Run the tests" ) is a literal snippet with a copy button. @code obtains a real excerpt from the source's Git commit and line range; it accepts no authored code text. @image` embeds a contained local PNG, JPEG, GIF or WebP.

Raw lines 212 to 236
237## Inline links and sources
239`**bold**`, inline code and safe HTTP(S) links are supported. `[Redis](node:cache-read.redis)` and `[path](route:cache-read.api~redis)` open the native Viewer at existing targets. `[details](block:next)` jumps within the page.
241`[reference text](source:docs)` renders the text followed by a numbered superscript; `[](source:docs)` renders only the superscript. Numbers follow first appearance; uncited sources follow in declaration order. The footer lists titles with URLs or repository positions.
243```md
244@source router title="Request handler" path=src/router.js lines=10:30
245@code source=router language=js
246```
248Pass `--repo-root /path/to/repository` for code excerpts. With it, every cited repository source with a line range also shows its pinned lines when the reader hovers the citation; a source that cannot be verified stays a plain reference. The tool resolves origin and HEAD, or accepts `@meta repo_url=... repo_revision=<full-commit>`. The commit, path and line range must exist; working-tree edits cannot replace committed bytes.
250`[5 ms](typical:Description of the value)` becomes a static footnote, including in print.

Inline links and sources

**bold**, inline code and safe HTTP(S) links are supported. [Redis](node:cache-read.redis) and [path](route:cache-read.api~redis) open the native Viewer at existing targets. [details](block:next) jumps within the page.

[reference text](source:docs) renders the text followed by a numbered superscript; [](source:docs) renders only the superscript. Numbers follow first appearance; uncited sources follow in declaration order. The footer lists titles with URLs or repository positions.

@source router title="Request handler" path=src/router.js lines=10:30
@code source=router language=js

Pass --repo-root /path/to/repository for code excerpts. With it, every cited repository source with a line range also shows its pinned lines when the reader hovers the citation; a source that cannot be verified stays a plain reference. The tool resolves origin and HEAD, or accepts @meta repo_url=... repo_revision=<full-commit>. The commit, path and line range must exist; working-tree edits cannot replace committed bytes.

[5 ms](typical:Description of the value) becomes a static footnote, including in print.

Raw lines 237 to 251
252## Panels and layout
254Prefer a specific question as each panel title. `{#id}` gives a stable ID for links and panel replacement; `{#id span=7}` fixes a width of 1–12 columns. Omit spans: the page measures each panel and plans the board, keeping source order with the conclusion top-left, giving each diagram enough width for readable labels, and keeping tables and code from clipping. Without JavaScript, below 1100 px and in print, static widths apply.

Panels and layout

Prefer a specific question as each panel title. {#id} gives a stable ID for links and panel replacement; {#id span=7} fixes a width of 1–12 columns. Omit spans: the page measures each panel and plans the board, keeping source order with the conclusion top-left, giving each diagram enough width for readable labels, and keeping tables and code from clipping. Without JavaScript, below 1100 px and in print, static widths apply.

Raw lines 252 to 255
256## Delivery
258```sh
259node archify/bin/archify.mjs finalize explainer candidate.archify.md answer.html --json
260```
262After a pass, reply in two or three lines: the conclusion, then a Markdown link to the page with a descriptive title. Do not list gates. When the user asked for this page and no `[archify explainer: ...]` rules line is in context, end with the one-line mode offer from the Skill's Output section.
264Add `--repo-root <path>` when the draft uses `@code`. Finalize validates, atomically delivers and checks the HTML; it does not launch a browser, and its receipt records the browser gate as not run. A failure names the line, component, reason and a repair example; fix the draft and rerun to the same output path.
266Writing warnings apply the [Writing](#writing) rules: sentences over 50 Chinese units or 28 English words, paragraphs over four sentences or 120 units, chained “的”, light verbs, set phrases, openers and sign-offs, unbounded quantities, “以上/以下/以内” after a number, long English words with a common equivalent, qualifiers such as “示例”, “未实测” or “illustrative” outside scope, a mostly bold conclusion and a scope over 50 units. Each warning names the matched text and a repair; fix it when the repair keeps the meaning. `--writing warn|strict|off` sets the severity.

Delivery

node archify/bin/archify.mjs finalize explainer candidate.archify.md answer.html --json

After a pass, reply in two or three lines: the conclusion, then a Markdown link to the page with a descriptive title. Do not list gates. When the user asked for this page and no [archify explainer: ...] rules line is in context, end with the one-line mode offer from the Skill's Output section.

Add --repo-root <path> when the draft uses @code. Finalize validates, atomically delivers and checks the HTML; it does not launch a browser, and its receipt records the browser gate as not run. A failure names the line, component, reason and a repair example; fix the draft and rerun to the same output path.

Writing warnings apply the Writing rules: sentences over 50 Chinese units or 28 English words, paragraphs over four sentences or 120 units, chained “的”, light verbs, set phrases, openers and sign-offs, unbounded quantities, “以上/以下/以内” after a number, long English words with a common equivalent, qualifiers such as “示例”, “未实测” or “illustrative” outside scope, a mostly bold conclusion and a scope over 50 units. Each warning names the matched text and a repair; fix it when the repair keeps the meaning. --writing warn|strict|off sets the severity.

Raw lines 256 to 267
Runs code bin/archify.mjs :259
268## Panel replacement
270```sh
271node archify/bin/archify.mjs patch explainer answer.html next replacement.md revised.html --json
272```
274The replacement holds one `##` panel with the same stable ID; untouched content and frozen assets are preserved. Rerun finalize on the full draft when changing shared sources, the conclusion or document-wide structure.

Panel replacement

node archify/bin/archify.mjs patch explainer answer.html next replacement.md revised.html --json

The replacement holds one ## panel with the same stable ID; untouched content and frozen assets are preserved. Rerun finalize on the full draft when changing shared sources, the conclusion or document-wide structure.

Raw lines 268 to 274
Runs code bin/archify.mjs :271