figdown 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EXPRESSING.md +119 -0
- package/LAYOUT-GUIDE.md +367 -0
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/README.zh-tw.md +185 -0
- package/SHOWCASE.md +421 -0
- package/dist/figdown.js +2239 -0
- package/dist/figdown.mjs +2231 -0
- package/examples/evpn-fabric.svg +54 -0
- package/examples/showcase/arp-resolution.svg +51 -0
- package/examples/showcase/ethernet-frame.svg +37 -0
- package/examples/showcase/l2-forwarding-logic.svg +42 -0
- package/examples/showcase/tcp-handshake.svg +56 -0
- package/examples/showcase/tcp-header.svg +47 -0
- package/examples/showcase/tcp-state-machine.svg +140 -0
- package/package.json +51 -0
- package/skill/figdown/build-svg.js +73 -0
- package/skill/figdown/figdown.html +3290 -0
package/SHOWCASE.md
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
# FigDown capability showcase — one source, two readers
|
|
2
|
+
|
|
3
|
+
A FigDown figure is a single `.fd` text: a human opens the rendered SVG and
|
|
4
|
+
*sees* it; an agent opens the same text and *reads* it — answering questions
|
|
5
|
+
about widths, bit positions, message order, and decision logic without a
|
|
6
|
+
pixel. These six classic networking figures each demonstrate one advantage as
|
|
7
|
+
an agent skill: the agent writes the `.fd` (not brittle ASCII art), the human
|
|
8
|
+
gets a clean SVG, and a second agent reads the text back to answer questions
|
|
9
|
+
that would otherwise need OCR. The sixth — the complete TCP state machine —
|
|
10
|
+
is the stress test: every state and every labelled transition of RFC 9293
|
|
11
|
+
Figure 5 on one canvas.
|
|
12
|
+
|
|
13
|
+
Each entry: the rendered SVG, the full `.fd`, one line on what the human sees,
|
|
14
|
+
and questions an agent answers **from the text alone**. Every colour and
|
|
15
|
+
dash is carried by a `class` whose label states its *meaning*; no meaning rides
|
|
16
|
+
on geometry (`tools/r25-check.js --strict`) or presentation.
|
|
17
|
+
|
|
18
|
+
Two of these figures — the TCP handshake and ARP resolution — are deliberately
|
|
19
|
+
**mixed documents**: a scene block *and* a `table` block in one `.fd`, composed
|
|
20
|
+
in document order (spec §8). This is the project's ruled answer for content the
|
|
21
|
+
scene genre cannot yet carry first-class (per-endpoint lifeline state; a local
|
|
22
|
+
cache transition): a second typed block carries it machine-readably, rather than
|
|
23
|
+
letting it ride on geometry or absence.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. TCP header — bit-exact machine-readable layout (`bitfield`)
|
|
28
|
+
|
|
29
|
+

|
|
30
|
+
|
|
31
|
+
```figdown
|
|
32
|
+
figdown 0.1 bitfield
|
|
33
|
+
title TCP Header
|
|
34
|
+
|
|
35
|
+
bitfield tcp "TCP Header (RFC 9293)" unit=32 numbering=msb0
|
|
36
|
+
|
|
37
|
+
field "Source Port" 16
|
|
38
|
+
field "Destination Port" 16
|
|
39
|
+
field "Sequence Number" 32
|
|
40
|
+
field "Acknowledgment Number" 32
|
|
41
|
+
field "Data Offset" 4 note="header length in 32-bit words; min 5 (=20 bytes), max 15 (=60 bytes)"
|
|
42
|
+
field Reserved 4 note="must be zero"
|
|
43
|
+
field CWR 1
|
|
44
|
+
field ECE 1
|
|
45
|
+
field URG 1
|
|
46
|
+
field ACK 1
|
|
47
|
+
field PSH 1
|
|
48
|
+
field RST 1
|
|
49
|
+
field SYN 1 color=#fee2e2
|
|
50
|
+
field FIN 1 color=#fee2e2
|
|
51
|
+
field Window 16 note="receive window size in bytes (subject to window scaling option)"
|
|
52
|
+
field Checksum 16
|
|
53
|
+
field "Urgent Pointer" 16
|
|
54
|
+
field Options 32 optional note="present iff Data Offset > 5; padded to a 32-bit boundary"
|
|
55
|
+
field Data * note="variable-length payload; length from the IP datagram, not the TCP header"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Human sees:** the RFC-style header — a 32-bit ruler, every field to width,
|
|
59
|
+
the eight flags as individual bit cells, Options dashed (optional).
|
|
60
|
+
|
|
61
|
+
**An agent answers from the text alone:**
|
|
62
|
+
|
|
63
|
+
- *Q: Which bits carry the window size?* A: bits 112–127 — the sum of preceding
|
|
64
|
+
widths (96 for rows 1–3, then Data Offset 4 + Reserved 4 + eight 1-bit flags)
|
|
65
|
+
places `Window` next. Derived from field order/width, not the drawing.
|
|
66
|
+
- *Q: Is SYN one bit or a byte?* A: one bit (`field SYN 1`); each of the eight
|
|
67
|
+
flags is a distinct, individually addressable 1-bit field.
|
|
68
|
+
- *Q: When are Options present; what is the minimum header length?* A: present
|
|
69
|
+
iff Data Offset > 5 (`optional` + note); minimum header = 5 × 32-bit words =
|
|
70
|
+
20 bytes (Data Offset note).
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## 2. TCP three-way handshake — labelled directed exchange (`topology`)
|
|
75
|
+
|
|
76
|
+

|
|
77
|
+
|
|
78
|
+
```figdown
|
|
79
|
+
figdown 0.1 topology
|
|
80
|
+
title TCP Three-Way Handshake
|
|
81
|
+
|
|
82
|
+
class setup "Connection-setup segment — carries SYN and/or ACK control flags" color=#2563eb
|
|
83
|
+
class data "Segment that also carries application data (piggybacked on the ACK)" color=#16a34a
|
|
84
|
+
|
|
85
|
+
node client "Client (active open)"
|
|
86
|
+
node server "Server (passive open, LISTEN)"
|
|
87
|
+
|
|
88
|
+
flow right
|
|
89
|
+
|
|
90
|
+
edge client -[1: SYN seq=x]-> server class=setup
|
|
91
|
+
edge server -[2: SYN,ACK seq=y ack=x+1]-> client class=setup
|
|
92
|
+
edge client -[3: ACK ack=y+1 (+ data)]-> server class=data
|
|
93
|
+
|
|
94
|
+
table state "Endpoint state after each segment (RFC 9293 §3.3.2 state names)"
|
|
95
|
+
| Segment | Client state | Server state |
|
|
96
|
+
|--------------------|-----------------------|---------------------------|
|
|
97
|
+
| start | CLOSED | LISTEN |
|
|
98
|
+
| 1: SYN → | SYN-SENT | SYN-RECEIVED on receipt |
|
|
99
|
+
| 2: SYN,ACK ← | ESTABLISHED on receipt| SYN-RECEIVED |
|
|
100
|
+
| 3: ACK → | ESTABLISHED | ESTABLISHED on receipt |
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This is a **mixed document**: a `topology` scene *and* a `table` in one `.fd`,
|
|
104
|
+
composed in document order (spec §8). The canonical RFC 9293 figure carries the
|
|
105
|
+
per-endpoint state on the lifelines; the topology genre has no lifeline-state
|
|
106
|
+
construct, so the companion table carries those states machine-readably —
|
|
107
|
+
composition is the ruled interim until the sequence genre lands.
|
|
108
|
+
|
|
109
|
+
**Human sees:** two endpoints and three numbered segments — SYN out, SYN-ACK
|
|
110
|
+
back, ACK (with piggybacked data) out — with a state table below tracking each
|
|
111
|
+
endpoint's TCP state segment by segment.
|
|
112
|
+
|
|
113
|
+
**An agent answers from the text alone:**
|
|
114
|
+
|
|
115
|
+
- *Q: Which flags are set in segment 2?* A: SYN and ACK — from label `2: SYN,ACK`.
|
|
116
|
+
- *Q: Which segment carries data, in which direction?* A: segment 3,
|
|
117
|
+
client → server — the only `data`-classed edge; its operator gives direction.
|
|
118
|
+
- *Q: What ack number does the client send last?* A: `ack=y+1`, acknowledging
|
|
119
|
+
the server's SYN — from the segment-3 label.
|
|
120
|
+
- *Q: What state is the server in after receiving segment 1?* A: SYN-RECEIVED —
|
|
121
|
+
row 2 of the state table (`1: SYN →`, Server state). Answerable only because
|
|
122
|
+
the companion table carries the RFC 9293 lifeline states.
|
|
123
|
+
|
|
124
|
+
> **Honest limit (stated in the source):** message *order* rides on the 1/2/3
|
|
125
|
+
> label ordinals, not a first-class construct — R37 does not treat numbering as
|
|
126
|
+
> semantics. The v0.2 sequence genre (OQ-S18) closes this; see
|
|
127
|
+
> [EXPRESSING.md](EXPRESSING.md), "strict message ordering".
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 3. L2 switch forwarding decision — protocol logic, readable (`flowchart`)
|
|
132
|
+
|
|
133
|
+

|
|
134
|
+
|
|
135
|
+
```figdown
|
|
136
|
+
figdown 0.1 flowchart
|
|
137
|
+
title L2 Switch Forwarding Decision
|
|
138
|
+
|
|
139
|
+
class forward "Forward — send the frame out the single learned egress port" color=#16a34a
|
|
140
|
+
class flood "Flood — send out every port in the VLAN except the ingress port" color=#2563eb
|
|
141
|
+
class filter "Filter — discard; destination is out the same port it arrived on" color=#dc2626
|
|
142
|
+
|
|
143
|
+
boundary wire "from ingress port"
|
|
144
|
+
|
|
145
|
+
node learn "Learn source MAC:\nupdate MAC table\n(SA -> ingress port)"
|
|
146
|
+
node lookup "Look up destination MAC\nin MAC table"
|
|
147
|
+
node hit "Entry found?" shape=diamond
|
|
148
|
+
node same "Egress port ==\ningress port?" shape=diamond
|
|
149
|
+
node fwd "Forward out\nlearned port" shape=rounded class=forward
|
|
150
|
+
node fld "Flood to all ports\nin VLAN except ingress" shape=rounded class=flood
|
|
151
|
+
node flt "Filter (drop):\nsame-port destination" shape=rounded class=filter
|
|
152
|
+
|
|
153
|
+
flow down
|
|
154
|
+
|
|
155
|
+
edge wire -> learn
|
|
156
|
+
edge learn -> lookup
|
|
157
|
+
edge lookup -> hit
|
|
158
|
+
edge hit -[no]-> fld
|
|
159
|
+
edge hit -[yes]-> same
|
|
160
|
+
edge same -[yes]-> flt
|
|
161
|
+
edge same -[no]-> fwd
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Human sees:** a frame from the ingress port → source-MAC learning →
|
|
165
|
+
destination lookup → two decisions branching into three colour-coded outcomes.
|
|
166
|
+
|
|
167
|
+
**An agent answers from the text alone:**
|
|
168
|
+
|
|
169
|
+
- *Q: When does the switch flood?* A: on a lookup miss — `hit -[no]-> fld`, and
|
|
170
|
+
`fld` is the `flood` outcome (unknown-unicast and broadcast both take it).
|
|
171
|
+
- *Q: A hit whose destination is behind the ingress port?* A: filtered
|
|
172
|
+
(dropped) — `same -[yes]-> flt`, class `filter`.
|
|
173
|
+
- *Q: Does learning happen before or after lookup?* A: before — the chain is
|
|
174
|
+
`wire -> learn -> lookup`.
|
|
175
|
+
|
|
176
|
+
Closed-world: the three `class`-marked terminals are the *only* outcomes; there
|
|
177
|
+
is no unstated fourth path.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 4. Ethernet II frame — byte order carried by syntax (`table`)
|
|
182
|
+
|
|
183
|
+

|
|
184
|
+
|
|
185
|
+
```figdown
|
|
186
|
+
figdown 0.1 table
|
|
187
|
+
title Ethernet II Frame — Untagged vs 802.1Q Tagged
|
|
188
|
+
|
|
189
|
+
class tag "802.1Q VLAN tag (4 bytes), inserted after Source MAC; absent in an untagged frame" color=#dbeafe
|
|
190
|
+
|
|
191
|
+
table eth "Ethernet II frame — column order = wire order (byte counts in the second header tier)"
|
|
192
|
+
| Variant | Destination MAC | Source MAC | 802.1Q Tag | EtherType | Payload | FCS |
|
|
193
|
+
| (frame) | (6 bytes) | (6 bytes) | (4 bytes) | (2 bytes) | (46-1500 bytes) | (4 bytes) |
|
|
194
|
+
|----------|-----------------|------------|-------------|-----------|-----------------|-----------|
|
|
195
|
+
| Untagged | DA | SA | (none) | Type | Data | CRC-32 |
|
|
196
|
+
| Tagged | DA | SA | TPID 0x8100 + PCP/DEI/VID | Type | Data | CRC-32 |
|
|
197
|
+
colw 90 auto auto auto auto auto auto
|
|
198
|
+
cell 1,4 class=tag
|
|
199
|
+
cell 2,4 class=tag
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Human sees:** the frame in wire order left-to-right, two variants (untagged /
|
|
203
|
+
802.1Q-tagged), the tag column highlighted at its insertion point.
|
|
204
|
+
|
|
205
|
+
**An agent answers from the text alone:**
|
|
206
|
+
|
|
207
|
+
- *Q: What field follows Source MAC on a tagged frame?* A: the 802.1Q Tag
|
|
208
|
+
(column 4, `class=tag`) — column order is wire order.
|
|
209
|
+
- *Q: How many bytes does the tag add?* A: 4 (header tier `(4 bytes)` + class
|
|
210
|
+
label).
|
|
211
|
+
- *Q: Untagged vs tagged?* A: the tag column is `(none)` vs
|
|
212
|
+
`TPID 0x8100 + PCP/DEI/VID` — absent, not zeroed (class label).
|
|
213
|
+
|
|
214
|
+
The OQ-S24 sanctioned pattern: a byte-unit packet is a single-row `table`, so
|
|
215
|
+
byte order lives in cell order (strip test survives), not a bit ruler.
|
|
216
|
+
|
|
217
|
+
**One fact this figure cannot draw:** the FCS (CRC-32) is computed over
|
|
218
|
+
Destination MAC through Payload inclusive — a coverage span across a
|
|
219
|
+
*contiguous run of columns*. FigDown has no construct to annotate such a span
|
|
220
|
+
(curly-brace grouping over a contiguous cell range is **OQ-S16**, v0.2), so the
|
|
221
|
+
fact is stated in the `.fd` source comment and here in prose, never on geometry.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 5. ARP resolution — boundary + class discipline (`topology`)
|
|
226
|
+
|
|
227
|
+

|
|
228
|
+
|
|
229
|
+
```figdown
|
|
230
|
+
figdown 0.1 topology
|
|
231
|
+
title ARP Resolution
|
|
232
|
+
|
|
233
|
+
class bcast "Broadcast — delivered to every host on the LAN (dst MAC ff:ff:ff:ff:ff:ff)" color=#dc2626 style=dashed
|
|
234
|
+
class ucast "Unicast — delivered only to the requester (dst MAC = A's MAC)" color=#16a34a
|
|
235
|
+
|
|
236
|
+
node a "Host A\nwants MAC for B's IP"
|
|
237
|
+
node b "Host B\nowns the target IP"
|
|
238
|
+
|
|
239
|
+
boundary lan "rest of the LAN\n(hosts C, D, ...)"
|
|
240
|
+
|
|
241
|
+
flow right
|
|
242
|
+
|
|
243
|
+
edge a -[1: who-has B? (broadcast)]-> b class=bcast
|
|
244
|
+
edge a -[1: heard, ignored]-> lan class=bcast
|
|
245
|
+
edge b -[2: B is at aa:bb:cc:... A caches it]-> a class=ucast
|
|
246
|
+
|
|
247
|
+
table cache "Host A's ARP cache — before and after the exchange"
|
|
248
|
+
| Moment | Entry |
|
|
249
|
+
|--------------------|-----------------------------------------|
|
|
250
|
+
| before the exchange| (no entry for B's IP) |
|
|
251
|
+
| after segment 2 | B's IP → aa:bb:cc:... , learned from the reply |
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
This too is a **mixed document** (scene + table in one `.fd`, document order):
|
|
255
|
+
the cache *transition* is the figure's actual outcome, but it is a local state
|
|
256
|
+
change on A rather than a message, so the companion table carries the
|
|
257
|
+
before/after cache state machine-readably.
|
|
258
|
+
|
|
259
|
+
**Human sees:** A broadcasts who-has (reaching B; the rest of the LAN hears it
|
|
260
|
+
and ignores it), B replies by unicast and A caches the binding — broadcast
|
|
261
|
+
dashed-red, unicast green, "rest of the LAN" an open boundary — with a cache
|
|
262
|
+
table below showing the before/after state. The cache update is a local action
|
|
263
|
+
on A, not a message, so it rides on the reply label, the cache table, and this
|
|
264
|
+
prose rather than on an edge of its own.
|
|
265
|
+
|
|
266
|
+
**An agent answers from the text alone:**
|
|
267
|
+
|
|
268
|
+
- *Q: Broadcast or unicast request, and how do you know?* A: broadcast — the
|
|
269
|
+
request edges are `class=bcast` ("delivered to every host … dst MAC ff:…ff").
|
|
270
|
+
The dashed red is only presentation; the meaning is the class label.
|
|
271
|
+
- *Q: Who receives the reply, and what does A do with it?* A: only Host A —
|
|
272
|
+
reply edge `class=ucast`, directed `b -> a`; the label states A caches the
|
|
273
|
+
IP → MAC binding on receipt.
|
|
274
|
+
- *Q: Is "rest of the LAN" a participating host?* A: no — a `boundary`, stating
|
|
275
|
+
only that the broadcast crosses the figure's edge.
|
|
276
|
+
- *Q: What does A's cache hold before the exchange?* A: nothing — row 1 of the
|
|
277
|
+
cache table (`before the exchange` → `(no entry for B's IP)`). Answerable only
|
|
278
|
+
because the companion table carries the before-state explicitly.
|
|
279
|
+
|
|
280
|
+
> **Honest limit:** step order (1/2) rides on label ordinals, pending the v0.2
|
|
281
|
+
> sequence genre (OQ-S18).
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## 6. TCP connection state machine — every state, every transition (`flowchart`)
|
|
286
|
+
|
|
287
|
+

|
|
288
|
+
|
|
289
|
+
```figdown
|
|
290
|
+
figdown 0.1 flowchart
|
|
291
|
+
title TCP Connection State Machine (RFC 9293, Figure 5)
|
|
292
|
+
|
|
293
|
+
class states "A node IS a TCP state (RFC 9293 §3.3.2); the two CLOSED nodes are one state — no node-identity construct yet (OQ-S26)" color=#eef2ff
|
|
294
|
+
class setup "Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)" color=#2563eb
|
|
295
|
+
class client "Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED" color=#dc2626
|
|
296
|
+
class server "Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED" color=#16a34a
|
|
297
|
+
class rare "Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)" color=#9333ea style=dashed
|
|
298
|
+
|
|
299
|
+
node closed "CLOSED" shape=rounded class=states
|
|
300
|
+
node listen "LISTEN" shape=rounded class=states
|
|
301
|
+
node synsent "SYN-SENT" shape=rounded class=states
|
|
302
|
+
node synrcvd "SYN-RECEIVED" shape=rounded class=states
|
|
303
|
+
node estab "ESTABLISHED" shape=rounded class=states
|
|
304
|
+
node fw1 "FIN-WAIT-1" shape=rounded class=states
|
|
305
|
+
node fw2 "FIN-WAIT-2" shape=rounded class=states
|
|
306
|
+
node closing "CLOSING" shape=rounded class=states
|
|
307
|
+
node closewait "CLOSE-WAIT" shape=rounded class=states
|
|
308
|
+
node lastack "LAST-ACK" shape=rounded class=states
|
|
309
|
+
node timewait "TIME-WAIT" shape=rounded class=states
|
|
310
|
+
node closed2 "CLOSED" shape=rounded class=states
|
|
311
|
+
|
|
312
|
+
flow down
|
|
313
|
+
|
|
314
|
+
edge closed -[passive OPEN / create TCB]-> listen class=setup
|
|
315
|
+
edge closed -[active OPEN / create TCB, snd SYN]-> synsent class=setup
|
|
316
|
+
edge listen -[SEND / snd SYN]-> synsent class=setup
|
|
317
|
+
edge listen -[rcv SYN / snd SYN,ACK]-> synrcvd class=setup
|
|
318
|
+
edge synsent -[rcv SYN / snd SYN,ACK]-> synrcvd class=rare
|
|
319
|
+
edge synsent -[rcv SYN,ACK / snd ACK]-> estab class=setup
|
|
320
|
+
edge synrcvd -[rcv ACK of SYN / x]-> estab class=setup
|
|
321
|
+
|
|
322
|
+
edge listen -[CLOSE / delete TCB]-> closed class=rare
|
|
323
|
+
edge synsent -[CLOSE / delete TCB]-> closed class=rare
|
|
324
|
+
edge synrcvd -[rcv RST (note 1) / x]-> listen class=rare
|
|
325
|
+
|
|
326
|
+
edge synrcvd -[CLOSE / snd FIN]-> fw1 class=client
|
|
327
|
+
edge estab -[CLOSE / snd FIN]-> fw1 class=client
|
|
328
|
+
edge fw1 -[rcv ACK of FIN / x]-> fw2 class=client
|
|
329
|
+
edge fw1 -[rcv FIN / snd ACK]-> closing class=client
|
|
330
|
+
edge fw1 -[rcv FIN,ACK / snd ACK]-> timewait class=rare
|
|
331
|
+
edge fw2 -[rcv FIN / snd ACK]-> timewait class=client
|
|
332
|
+
edge closing -[rcv ACK of FIN / x]-> timewait class=client
|
|
333
|
+
edge timewait -[Timeout=2MSL / delete TCB]-> closed2 class=client
|
|
334
|
+
|
|
335
|
+
edge estab -[rcv FIN / snd ACK]-> closewait class=server
|
|
336
|
+
edge closewait -[CLOSE / snd FIN]-> lastack class=server
|
|
337
|
+
edge lastack -[rcv ACK of FIN / x]-> closed2 class=server
|
|
338
|
+
|
|
339
|
+
render
|
|
340
|
+
pin closed at=394,20
|
|
341
|
+
pin listen at=394,150
|
|
342
|
+
pin synrcvd at=152,280
|
|
343
|
+
pin synsent at=607,280
|
|
344
|
+
pin estab at=376,410
|
|
345
|
+
pin fw1 at=159,540
|
|
346
|
+
pin closewait at=600,540
|
|
347
|
+
pin fw2 at=159,670
|
|
348
|
+
pin closing at=311,670
|
|
349
|
+
pin lastack at=607,670
|
|
350
|
+
pin timewait at=304,800
|
|
351
|
+
pin closed2 at=614,800
|
|
352
|
+
route closed -> synsent via=790,38;790,298
|
|
353
|
+
route listen -> closed via=300,105
|
|
354
|
+
route synsent -> closed via=640,120
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
The `pin`/`route` block reproduces the canonical Figure 5 arrangement so a
|
|
358
|
+
reader who knows the RFC diagram recognises it — but it is **presentation
|
|
359
|
+
only** (`r25-check --strict` passes): strip every line after `render` and all
|
|
360
|
+
11 states, all 21 transitions and their `event / action` labels survive on the
|
|
361
|
+
`node`/`edge`/`class` lines. All meaning is in the edges; the pins are layout.
|
|
362
|
+
|
|
363
|
+
**Human sees:** the whole RFC 9293 state diagram — CLOSED at top, the SYN pair
|
|
364
|
+
flanking, ESTABLISHED centred, the active-close column falling left and the
|
|
365
|
+
passive-close column right — four colour-coded transition families (blue setup,
|
|
366
|
+
red active-close, green passive-close, purple rare/simultaneous dashed), every
|
|
367
|
+
arrow carrying its `event / action`.
|
|
368
|
+
|
|
369
|
+
**An agent answers from the text alone:**
|
|
370
|
+
|
|
371
|
+
- *Q: What event takes ESTABLISHED to CLOSE-WAIT, and what does the endpoint
|
|
372
|
+
send?* A: `rcv FIN / snd ACK` — one edge label
|
|
373
|
+
(`edge estab -[rcv FIN / snd ACK]-> closewait`).
|
|
374
|
+
- *Q: From FIN-WAIT-1, how many ways lead to TIME-WAIT and under what
|
|
375
|
+
conditions?* A: two. Directly, `rcv FIN,ACK / snd ACK` (the RFC Note-2
|
|
376
|
+
transition, `fw1 -> timewait`); and via FIN-WAIT-2, `rcv ACK of FIN / x` then
|
|
377
|
+
`rcv FIN / snd ACK` (`fw1 -> fw2 -> timewait`). A third path runs via CLOSING
|
|
378
|
+
(`rcv FIN / snd ACK` then `rcv ACK of FIN / x`). All read off the edges.
|
|
379
|
+
- *Q: How long does TIME-WAIT last and what happens after?* A: `Timeout=2MSL`,
|
|
380
|
+
then `delete TCB` → CLOSED (`timewait -[Timeout=2MSL / delete TCB]-> closed2`).
|
|
381
|
+
- *Q: Which transitions belong to the typical server (passive-close) path?*
|
|
382
|
+
A: the three `class=server` edges — `ESTABLISHED → CLOSE-WAIT`,
|
|
383
|
+
`CLOSE-WAIT → LAST-ACK`, `LAST-ACK → CLOSED` — enumerated by querying the
|
|
384
|
+
class, whose label spells the path out.
|
|
385
|
+
|
|
386
|
+
> **Honest limit (stated in the source):** a node *is* a state is not yet a
|
|
387
|
+
> machine-declarable fact — FigDown has no state genre (the R49 §6 candidate),
|
|
388
|
+
> so "this node is a protocol state" rides on the `states` class label, interim.
|
|
389
|
+
> And CLOSED is drawn **twice** (top origin, bottom terminus) because FigDown
|
|
390
|
+
> has no node-identity/alias construct (**OQ-S26**): the two `closed`/`closed2`
|
|
391
|
+
> nodes are declared one state only by the shared class label, not machine-
|
|
392
|
+
> readably. Everything else — all 11 states, all 21 labelled transitions
|
|
393
|
+
> including the one the canonical figure omits in its own Note 2 — the edges
|
|
394
|
+
> carry in full.
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## The honest limits, in one paragraph
|
|
399
|
+
|
|
400
|
+
Two figures depend on a convention the language does not yet make first-class:
|
|
401
|
+
**message/step ordering** in the handshake and ARP is carried by numbering edge
|
|
402
|
+
labels `1:`/`2:`/`3:`, which R37 treats as naming, not semantics — the v0.2
|
|
403
|
+
sequence genre (OQ-S18) will fix it, and the sources say so. Relatedly, the RFC
|
|
404
|
+
9293 handshake carries **per-endpoint lifeline state** (LISTEN, SYN-SENT, …)
|
|
405
|
+
that the topology genre has no construct for; the companion state table carries
|
|
406
|
+
it as composition (a ruled interim, again pending the sequence genre, OQ-S18).
|
|
407
|
+
The Ethernet frame uses the **OQ-S24** byte-unit workaround (single-row `table`,
|
|
408
|
+
not `bitfield`) so byte order rides on cell order, and one of its facts — the
|
|
409
|
+
FCS **coverage span** over a contiguous run of columns (DA through Payload) —
|
|
410
|
+
has no annotation construct yet (**OQ-S16**), so it rides on a source comment
|
|
411
|
+
and prose. The TCP state machine meets two more: **state-ness is not first-class**
|
|
412
|
+
— a node *is* a state carries as the `states` class label until the state genre
|
|
413
|
+
lands (the R49 §6 candidate) — and CLOSED is drawn **twice** because FigDown has
|
|
414
|
+
no **node-identity/alias** construct (**OQ-S26**) to declare two nodes the same
|
|
415
|
+
entity; the shared class label asserts it instead. Every state and every labelled
|
|
416
|
+
transition still rides on an edge, so those two are the *only* facts the figure
|
|
417
|
+
cannot carry that the canonical drawing implies. All are documented in
|
|
418
|
+
[EXPRESSING.md](EXPRESSING.md)'s "Known limits".
|
|
419
|
+
That a figure format states its own limits — and that a reading agent recovers
|
|
420
|
+
exactly what the text declares and nothing the geometry merely implies — is the
|
|
421
|
+
claim these figures make.
|