figdown 0.1.7 → 0.2.0
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/.claude-plugin/plugin.json +1 -1
- package/dist/figdown.js +339 -88
- package/dist/figdown.mjs +339 -88
- package/examples/evpn-fabric.svg +1 -1
- package/examples/showcase/arp-resolution.svg +1 -1
- package/examples/showcase/ethernet-frame.svg +1 -1
- package/examples/showcase/l2-forwarding-logic.svg +9 -9
- package/examples/showcase/tcp-handshake.svg +1 -1
- package/examples/showcase/tcp-header.svg +1 -1
- package/examples/showcase/tcp-state-machine.svg +77 -55
- package/guide/expressing.md +3 -3
- package/guide/layout.md +16 -16
- package/guide/showcase.md +62 -56
- package/package.json +2 -2
- package/skill/figdown/SKILL.md +26 -0
- package/skill/figdown/figdown.html +391 -109
- package/skill/figdown/reference/experimental/flowchart.md +59 -18
- package/skill/figdown/reference/experimental/statechart.md +92 -0
- package/skill/figdown/reference/reading.md +13 -1
- package/skill/figdown/reference/scene.md +18 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 888 984" width="888" height="984" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="70" x1="433.1" y1="76" x2="433.1" y2="190" stroke="#2563eb" stroke-width="1.6"/><line data-edge="71" x1="452.7652886772431" y1="73.34906513439799" x2="724.2052886772431" y2="307.34906513439796" stroke="#2563eb" stroke-width="1.6"/><line data-edge="72" x1="465.20000000000005" y1="221.63984674329504" x2="700" y2="311.6015325670498" stroke="#2563eb" stroke-width="1.6"/><line data-edge="73" x1="395.5028227438559" y1="228.0864522267111" x2="216.56282274385592" y2="313.1609371712436" stroke="#2563eb" stroke-width="1.6"/><line data-edge="74" x1="700" y1="328" x2="234.39999999999998" y2="328" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="75" x1="700" y1="344.3984674329502" x2="476.58000000000004" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="76" x1="215.06" y1="346" x2="391.74" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="79" x1="426.1" y1="190" x2="426.1" y2="76" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="80" x1="719.6347113227569" y1="312.65093486560204" x2="448.1947113227569" y2="78.65093486560201" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="81" x1="213.5571772561441" y1="306.8390628287564" x2="392.4971772561441" y2="221.76457788422394" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="84" x1="179.4896" y1="346" x2="206.7104" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="85" x1="399.05538461538464" y1="466" x2="239.54461538461538" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="86" x1="209" y1="596" x2="209" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="87" x1="228.55076923076922" y1="596" x2="330.64923076923077" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="88" x1="218.78923076923076" y1="596" x2="340.6107692307692" y2="820" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="89" x1="228.57846153846154" y1="726" x2="330.82153846153847" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="90" x1="350.2276923076923" y1="726" x2="350.3723076923077" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="91" x1="396.79999999999995" y1="838" x2="697" y2="838" stroke="#dc2626" stroke-width="1.6"/><line data-edge="94" x1="472.57846153846157" y1="466" x2="697.0215384615385" y2="560" stroke="#16a34a" stroke-width="1.6"/><line data-edge="95" x1="739.003076923077" y1="596" x2="733.796923076923" y2="690" stroke="#16a34a" stroke-width="1.6"/><line data-edge="96" x1="732.7723076923077" y1="726" x2="732.6276923076923" y2="820" stroke="#16a34a" stroke-width="1.6"/><g data-node="closed" data-x="394" data-y="40" style="cursor:move"><rect x="394" y="40" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="62.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><g data-node="listen" data-x="394" data-y="190" style="cursor:move"><rect x="394" y="190" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="212.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LISTEN</text></g><g data-node="synsent" data-x="700" data-y="310" style="cursor:move"><rect x="700" y="310" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="742.8" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-SENT</text></g><g data-node="synrcvd" data-x="120" data-y="310" style="cursor:move"><rect x="120" y="310" width="114.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="177.2" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-RECEIVED</text></g><g data-node="estab" data-x="376" data-y="430" style="cursor:move"><rect x="376" y="430" width="107.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="452.55" font-size="13" text-anchor="middle" fill="#1d1d1b">ESTABLISHED</text></g><g data-node="fw1" data-x="159" data-y="560" style="cursor:move"><rect x="159" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-1</text></g><g data-node="fw2" data-x="159" data-y="690" style="cursor:move"><rect x="159" y="690" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-2</text></g><g data-node="closing" data-x="311" data-y="690" style="cursor:move"><rect x="311" y="690" width="78.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.2" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSING</text></g><g data-node="closewait" data-x="690" data-y="560" style="cursor:move"><rect x="690" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="740" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSE-WAIT</text></g><g data-node="lastack" data-x="690" data-y="690" style="cursor:move"><rect x="690" y="690" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.8" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LAST-ACK</text></g><g data-node="timewait" data-x="304" data-y="820" style="cursor:move"><rect x="304" y="820" width="92.8" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.4" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">TIME-WAIT</text></g><g data-node="closed2" data-x="697" data-y="820" style="cursor:move"><rect x="697" y="820" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.6" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">passive OPEN / create TCB</text><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#2563eb">passive OPEN / create TCB</text><path d="M433.1 190 L427.5 179.92 L438.70000000000005 179.92 z" fill="#2563eb" stroke="none"/><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">active OPEN / create TCB, snd SYN</text><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#2563eb">active OPEN / create TCB, snd SYN</text><path d="M724.2052886772431 307.34906513439796 L712.9141343807203 305.008929528901 L720.2270581478983 296.52593795897457 z" fill="#2563eb" stroke="none"/><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">SEND / snd SYN</text><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#2563eb">SEND / snd SYN</text><path d="M700 311.6015325670498 L688.5836683972988 313.224422808922 L692.5908047969832 302.76579680574537 z" fill="#2563eb" stroke="none"/><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN / snd SYN,ACK</text><path d="M216.56282274385592 313.1609371712436 L223.261805406868 303.7753081949488 L228.0708381872069 313.89030714292835 z" fill="#2563eb" stroke="none"/><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#9333ea">rcv SYN / snd SYN,ACK</text><path d="M234.39999999999998 328 L244.48 322.4 L244.48 333.6 z" fill="#9333ea" stroke="none"/><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN,ACK / snd ACK</text><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN,ACK / snd ACK</text><path d="M476.58000000000004 430 L483.9891952030168 421.1642642386956 L487.99633160270133 431.6228902418722 z" fill="#2563eb" stroke="none"/><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of SYN / x</text><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#2563eb">rcv ACK of SYN / x</text><path d="M391.74 430 L380.231984556649 430.7293699716848 L385.041017336988 420.61437102370525 z" fill="#2563eb" stroke="none"/><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#9333ea">CLOSE / delete TCB</text><path d="M426.1 76 L431.70000000000005 86.08 L420.5 86.08 z" fill="#9333ea" stroke="none"/><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#9333ea">CLOSE / delete TCB</text><path d="M448.1947113227569 78.65093486560201 L459.4858656192797 80.99107047109896 L452.17294185210176 89.47406204102543 z" fill="#9333ea" stroke="none"/><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv RST (note 1) / x</text><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#9333ea">rcv RST (note 1) / x</text><path d="M392.4971772561441 221.76457788422394 L385.79819459313205 231.1502068605187 L380.9891618127931 221.03520791253922 z" fill="#9333ea" stroke="none"/><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#dc2626">CLOSE / snd FIN</text><path d="M206.7104 560 L199.88323361107894 550.7071963811783 L210.99371139541864 549.2939436070102 z" fill="#dc2626" stroke="none"/><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#dc2626">CLOSE / snd FIN</text><path d="M239.54461538461538 560 L245.38572668223014 550.0577759626491 L251.0719964792192 559.7069384027706 z" fill="#dc2626" stroke="none"/><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M209 690 L203.4 679.92 L214.6 679.92 z" fill="#dc2626" stroke="none"/><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.64923076923077 690 L319.4405255167678 687.2923577482596 L327.02659217035057 679.0527222752913 z" fill="#dc2626" stroke="none"/><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN,ACK / snd ACK</text><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#9333ea">rcv FIN,ACK / snd ACK</text><path d="M340.6107692307692 820 L330.875382512483 813.820303774018 L340.7144579488292 808.469360440559 z" fill="#9333ea" stroke="none"/><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.82153846153847 820 L319.61092639723944 817.3002635047485 L327.19118005561285 809.0552799101793 z" fill="#dc2626" stroke="none"/><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M350.3723076923077 820 L344.75680664555944 809.9286273033927 L355.9567933911451 809.9113965545532 z" fill="#dc2626" stroke="none"/><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">Timeout=2MSL / delete TCB</text><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#dc2626">Timeout=2MSL / delete TCB</text><path d="M697 838 L686.92 843.6 L686.92 832.4 z" fill="#dc2626" stroke="none"/><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#16a34a">rcv FIN / snd ACK</text><path d="M697.0215384615385 560 L685.5607329004544 561.2713519933599 L689.8873234537733 550.9407850106658 z" fill="#16a34a" stroke="none"/><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">CLOSE / snd FIN</text><path d="M733.796923076923 690 L728.7629148866224 679.6257452537551 L739.9457765533873 680.2451037460681 z" fill="#16a34a" stroke="none"/><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">rcv ACK of FIN / x</text><path d="M732.6276923076923 820 L727.0432066088549 809.9113965545532 L738.2431933544406 809.9286273033927 z" fill="#16a34a" stroke="none"/><rect x="0" y="877" width="16" height="11" fill="#eef2ff" stroke="#555"/><text x="21" y="886.5" font-size="11" fill="#1d1d1b">A node IS a TCP state (RFC 9293 §3.3.2); the two CLOSED nodes are one state drawn twice — only this label says so</text><rect x="0" y="897" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="906.5" font-size="11" fill="#1d1d1b">Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)</text><rect x="0" y="917" width="16" height="11" fill="#fff" stroke="#dc2626"/><text x="21" y="926.5" font-size="11" fill="#1d1d1b">Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED</text><rect x="0" y="937" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="946.5" font-size="11" fill="#1d1d1b">Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED</text><rect x="0" y="957" width="16" height="11" fill="#fff" stroke="#9333ea" stroke-dasharray="6 4"/><text x="21" y="966.5" font-size="11" fill="#1d1d1b">Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)</text></g><metadata id="figdown-source" data-sha256="8c7cba9f05b9da4dfe03b8c3fe8cc1f6f8983fe67703351f442602c4d0f7157a" data-engine-version="0.1.7"><![CDATA[
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 902 984" width="902" height="984" font-family="system-ui,sans-serif"><defs><marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0,0 L10,5 L0,10 z" fill="#555"/></marker><pattern id="hatch" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="6" stroke="#bbb" stroke-width="2"/></pattern></defs><g transform="translate(18,6)"><line data-edge="92" x1="433.1" y1="76" x2="433.1" y2="190" stroke="#2563eb" stroke-width="1.6"/><line data-edge="93" x1="452.7652886772431" y1="73.34906513439799" x2="724.2052886772431" y2="307.34906513439796" stroke="#2563eb" stroke-width="1.6"/><line data-edge="94" x1="465.20000000000005" y1="221.63984674329504" x2="700" y2="311.6015325670498" stroke="#2563eb" stroke-width="1.6"/><line data-edge="95" x1="395.5028227438559" y1="228.0864522267111" x2="216.56282274385592" y2="313.1609371712436" stroke="#2563eb" stroke-width="1.6"/><line data-edge="96" x1="700" y1="328" x2="234.39999999999998" y2="328" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="97" x1="700" y1="344.3984674329502" x2="476.58000000000004" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="98" x1="215.06" y1="346" x2="391.74" y2="430" stroke="#2563eb" stroke-width="1.6"/><line data-edge="101" x1="426.1" y1="190" x2="426.1" y2="76" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="102" x1="719.6347113227569" y1="312.65093486560204" x2="448.1947113227569" y2="78.65093486560201" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="103" x1="213.5571772561441" y1="306.8390628287564" x2="392.4971772561441" y2="221.76457788422394" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="106" x1="179.4896" y1="346" x2="206.7104" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="107" x1="399.05538461538464" y1="466" x2="239.54461538461538" y2="560" stroke="#dc2626" stroke-width="1.6"/><line data-edge="108" x1="209" y1="596" x2="209" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="109" x1="228.55076923076922" y1="596" x2="330.64923076923077" y2="690" stroke="#dc2626" stroke-width="1.6"/><line data-edge="110" x1="218.78923076923076" y1="596" x2="340.6107692307692" y2="820" stroke="#9333ea" stroke-width="1.6" stroke-dasharray="6 4"/><line data-edge="111" x1="228.57846153846154" y1="726" x2="330.82153846153847" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="112" x1="350.2276923076923" y1="726" x2="350.3723076923077" y2="820" stroke="#dc2626" stroke-width="1.6"/><line data-edge="113" x1="396.79999999999995" y1="838" x2="697" y2="838" stroke="#dc2626" stroke-width="1.6"/><line data-edge="116" x1="472.57846153846157" y1="466" x2="697.0215384615385" y2="560" stroke="#16a34a" stroke-width="1.6"/><line data-edge="117" x1="739.003076923077" y1="596" x2="733.796923076923" y2="690" stroke="#16a34a" stroke-width="1.6"/><line data-edge="118" x1="732.7723076923077" y1="726" x2="732.6276923076923" y2="820" stroke="#16a34a" stroke-width="1.6"/><g data-node="closed" data-x="394" data-y="40" style="cursor:move"><rect x="394" y="40" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="62.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><g data-node="listen" data-x="394" data-y="190" style="cursor:move"><rect x="394" y="190" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="212.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LISTEN</text></g><g data-node="synsent" data-x="700" data-y="310" style="cursor:move"><rect x="700" y="310" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="742.8" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-SENT</text></g><g data-node="synrcvd" data-x="120" data-y="310" style="cursor:move"><rect x="120" y="310" width="114.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="177.2" y="332.55" font-size="13" text-anchor="middle" fill="#1d1d1b">SYN-RECEIVED</text></g><g data-node="estab" data-x="376" data-y="430" style="cursor:move"><rect x="376" y="430" width="107.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="429.6" y="452.55" font-size="13" text-anchor="middle" fill="#1d1d1b">ESTABLISHED</text></g><g data-node="fw1" data-x="159" data-y="560" style="cursor:move"><rect x="159" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-1</text></g><g data-node="fw2" data-x="159" data-y="690" style="cursor:move"><rect x="159" y="690" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="209" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">FIN-WAIT-2</text></g><g data-node="closing" data-x="311" data-y="690" style="cursor:move"><rect x="311" y="690" width="78.4" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.2" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSING</text></g><g data-node="closewait" data-x="690" data-y="560" style="cursor:move"><rect x="690" y="560" width="100" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="740" y="582.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSE-WAIT</text></g><g data-node="lastack" data-x="690" data-y="690" style="cursor:move"><rect x="690" y="690" width="85.6" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.8" y="712.55" font-size="13" text-anchor="middle" fill="#1d1d1b">LAST-ACK</text></g><g data-node="timewait" data-x="304" data-y="820" style="cursor:move"><rect x="304" y="820" width="92.8" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="350.4" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">TIME-WAIT</text></g><g data-node="closed2" data-x="697" data-y="820" style="cursor:move"><rect x="697" y="820" width="71.2" height="36" rx="14" fill="#eef2ff" stroke="#8a8880" stroke-width="1.8"/><text x="732.6" y="842.55" font-size="13" text-anchor="middle" fill="#1d1d1b">CLOSED</text></g><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">passive OPEN / create TCB</text><text x="264.6" y="136.3" font-size="11" text-anchor="start" fill="#2563eb">passive OPEN / create TCB</text><path d="M433.1 190 L427.5 179.92 L438.70000000000005 179.92 z" fill="#2563eb" stroke="none"/><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">active OPEN / create TCB, snd SYN</text><text x="588.485288677243" y="184.59906513439796" font-size="11" text-anchor="middle" fill="#2563eb">active OPEN / create TCB, snd SYN</text><path d="M724.2052886772431 307.34906513439796 L712.9141343807203 305.008929528901 L720.2270581478983 296.52593795897457 z" fill="#2563eb" stroke="none"/><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">SEND / snd SYN</text><text x="582.6" y="260.87068965517244" font-size="11" text-anchor="middle" fill="#2563eb">SEND / snd SYN</text><path d="M700 311.6015325670498 L688.5836683972988 313.224422808922 L692.5908047969832 302.76579680574537 z" fill="#2563eb" stroke="none"/><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="306.03282274385595" y="264.8736946989773" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN / snd SYN,ACK</text><path d="M216.56282274385592 313.1609371712436 L223.261805406868 303.7753081949488 L228.0708381872069 313.89030714292835 z" fill="#2563eb" stroke="none"/><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN / snd SYN,ACK</text><text x="467.2" y="322.25" font-size="11" text-anchor="middle" fill="#9333ea">rcv SYN / snd SYN,ACK</text><path d="M234.39999999999998 328 L244.48 322.4 L244.48 333.6 z" fill="#9333ea" stroke="none"/><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv SYN,ACK / snd ACK</text><text x="588.29" y="381.4492337164751" font-size="11" text-anchor="middle" fill="#2563eb">rcv SYN,ACK / snd ACK</text><path d="M476.58000000000004 430 L483.9891952030168 421.1642642386956 L487.99633160270133 431.6228902418722 z" fill="#2563eb" stroke="none"/><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of SYN / x</text><text x="303.4" y="382.25" font-size="11" text-anchor="middle" fill="#2563eb">rcv ACK of SYN / x</text><path d="M391.74 430 L380.231984556649 430.7293699716848 L385.041017336988 420.61437102370525 z" fill="#2563eb" stroke="none"/><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="303.1" y="149.98" font-size="11" text-anchor="start" fill="#9333ea">CLOSE / delete TCB</text><path d="M426.1 76 L431.70000000000005 86.08 L420.5 86.08 z" fill="#9333ea" stroke="none"/><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / delete TCB</text><text x="616.4875113227569" y="217.98093486560202" font-size="11" text-anchor="middle" fill="#9333ea">CLOSE / delete TCB</text><path d="M448.1947113227569 78.65093486560201 L459.4858656192797 80.99107047109896 L452.17294185210176 89.47406204102543 z" fill="#9333ea" stroke="none"/><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv RST (note 1) / x</text><text x="324.49997725614406" y="248.34288216314627" font-size="11" text-anchor="middle" fill="#9333ea">rcv RST (note 1) / x</text><path d="M392.4971772561441 221.76457788422394 L385.79819459313205 231.1502068605187 L380.9891618127931 221.03520791253922 z" fill="#9333ea" stroke="none"/><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="199.1" y="456.3" font-size="11" text-anchor="start" fill="#dc2626">CLOSE / snd FIN</text><path d="M206.7104 560 L199.88323361107894 550.7071963811783 L210.99371139541864 549.2939436070102 z" fill="#dc2626" stroke="none"/><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="319.3" y="507.25" font-size="11" text-anchor="middle" fill="#dc2626">CLOSE / snd FIN</text><path d="M239.54461538461538 560 L245.38572668223014 550.0577759626491 L251.0719964792192 559.7069384027706 z" fill="#dc2626" stroke="none"/><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="86" y="646.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M209 690 L203.4 679.92 L214.6 679.92 z" fill="#dc2626" stroke="none"/><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.6" y="637.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.64923076923077 690 L319.4405255167678 687.2923577482596 L327.02659217035057 679.0527222752913 z" fill="#dc2626" stroke="none"/><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN,ACK / snd ACK</text><text x="300.3185846153846" y="738.1800000000001" font-size="11" text-anchor="start" fill="#9333ea">rcv FIN,ACK / snd ACK</text><path d="M340.6107692307692 820 L330.875382512483 813.820303774018 L340.7144579488292 808.469360440559 z" fill="#9333ea" stroke="none"/><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="279.7" y="767.25" font-size="11" text-anchor="middle" fill="#dc2626">rcv FIN / snd ACK</text><path d="M330.82153846153847 820 L319.61092639723944 817.3002635047485 L327.19118005561285 809.0552799101793 z" fill="#dc2626" stroke="none"/><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="356.29999999999995" y="776.3000000000001" font-size="11" text-anchor="start" fill="#dc2626">rcv ACK of FIN / x</text><path d="M350.3723076923077 820 L344.75680664555944 809.9286273033927 L355.9567933911451 809.9113965545532 z" fill="#dc2626" stroke="none"/><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">Timeout=2MSL / delete TCB</text><text x="546.9" y="832.25" font-size="11" text-anchor="middle" fill="#dc2626">Timeout=2MSL / delete TCB</text><path d="M697 838 L686.92 843.6 L686.92 832.4 z" fill="#dc2626" stroke="none"/><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv FIN / snd ACK</text><text x="584.8000000000001" y="507.25" font-size="11" text-anchor="middle" fill="#16a34a">rcv FIN / snd ACK</text><path d="M697.0215384615385 560 L685.5607329004544 561.2713519933599 L689.8873234537733 550.9407850106658 z" fill="#16a34a" stroke="none"/><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">CLOSE / snd FIN</text><text x="742.4" y="646.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">CLOSE / snd FIN</text><path d="M733.796923076923 690 L728.7629148866224 679.6257452537551 L739.9457765533873 680.2451037460681 z" fill="#16a34a" stroke="none"/><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#fff" stroke="#fff" stroke-width="3" stroke-linejoin="round">rcv ACK of FIN / x</text><text x="738.7" y="776.3000000000001" font-size="11" text-anchor="start" fill="#16a34a">rcv ACK of FIN / x</text><path d="M732.6276923076923 820 L727.0432066088549 809.9113965545532 L738.2431933544406 809.9286273033927 z" fill="#16a34a" stroke="none"/><rect x="0" y="877" width="16" height="11" fill="#eef2ff" stroke="#555"/><text x="21" y="886.5" font-size="11" fill="#1d1d1b">A state IS a TCP connection state (RFC 9293 §3.3.2); the two CLOSED states are one state drawn twice — only this label says so</text><rect x="0" y="897" width="16" height="11" fill="#fff" stroke="#2563eb"/><text x="21" y="906.5" font-size="11" fill="#1d1d1b">Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)</text><rect x="0" y="917" width="16" height="11" fill="#fff" stroke="#dc2626"/><text x="21" y="926.5" font-size="11" fill="#1d1d1b">Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED</text><rect x="0" y="937" width="16" height="11" fill="#fff" stroke="#16a34a"/><text x="21" y="946.5" font-size="11" fill="#1d1d1b">Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED</text><rect x="0" y="957" width="16" height="11" fill="#fff" stroke="#9333ea" stroke-dasharray="6 4"/><text x="21" y="966.5" font-size="11" fill="#1d1d1b">Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)</text></g><metadata id="figdown-source" data-sha256="107a61548ef549f76483c5a2836aaf38e1021f8d9a29b82c48bf199d34aa7858" data-engine-version="0.2.0"><![CDATA[
|
|
2
2
|
# FigDown — figures as text. Spec: https://github.com/FigDown/figdown
|
|
3
3
|
|
|
4
|
-
figdown 0.
|
|
4
|
+
figdown 0.2 statechart
|
|
5
5
|
title "TCP Connection State Machine (RFC 9293, Figure 5)"
|
|
6
6
|
|
|
7
7
|
# ── What this figure is ─────────────────────────────────────────────
|
|
@@ -11,97 +11,119 @@ title "TCP Connection State Machine (RFC 9293, Figure 5)"
|
|
|
11
11
|
# notation for "no action". This is the hardest showcase figure — it
|
|
12
12
|
# answers the maintainer question "can FigDown fully express the TCP
|
|
13
13
|
# state machine with its transitions and conditions?" — and the answer
|
|
14
|
-
# it gives is: yes, every state and every labelled
|
|
15
|
-
#
|
|
14
|
+
# it gives is: yes, every state is a `state` line and every labelled
|
|
15
|
+
# transition is a `transition` line, so a reading agent recovers the
|
|
16
|
+
# whole machine from the text.
|
|
16
17
|
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
18
|
+
# STATE-NESS IS FIRST-CLASS NOW, AND WAS NOT WHEN THIS FIGURE WAS
|
|
19
|
+
# WRITTEN. Until v0.2.0 this file declared `figdown 0.1 flowchart` and
|
|
20
|
+
# the fact "this node is a protocol state" was carried by the `states`
|
|
21
|
+
# class label rather than by the genre. `statechart` LANDED at
|
|
22
|
+
# 0.2 (`STATECHART-GENRE-SCOPE`) and took its own two words (`GENRE-NODE-SPELLING`) —
|
|
23
|
+
# `state` and `transition`, whole from OMG UML 2.5.1 §14 — so the
|
|
24
|
+
# machine-declarable fact this figure once could not state, it now
|
|
25
|
+
# states. What follows is the ONE limit that survived that.
|
|
22
26
|
#
|
|
23
27
|
# HONEST LIMIT — the CLOSED identity (`IDENTITY-ASSERTION`). The canonical RFC figure
|
|
24
28
|
# draws CLOSED TWICE — top (origin) and bottom (the terminus TIME-WAIT
|
|
25
29
|
# and LAST-ACK return to) — and so do we, because taking every terminal
|
|
26
|
-
#
|
|
30
|
+
# transition back to a single top state produced long lines that struck the
|
|
27
31
|
# setup-abort labels around CLOSED and made the figure unreadable. But
|
|
28
|
-
# FigDown CANNOT declare two
|
|
32
|
+
# FigDown CANNOT declare two elements to be the SAME entity: there is no
|
|
29
33
|
# node-identity / alias construct (`IDENTITY-ASSERTION`). So `closed` and `closed2`
|
|
30
|
-
# are two
|
|
31
|
-
# `states` class label SAYS "the two CLOSED
|
|
34
|
+
# are two states that a human reads as one only because the shared
|
|
35
|
+
# `states` class label SAYS "the two CLOSED states are one state drawn
|
|
36
|
+
# twice."
|
|
32
37
|
# A reading agent sees two ids; the identity is asserted
|
|
33
38
|
# in the label, not machine-declarable. This is the single fact this
|
|
34
39
|
# figure cannot carry that the canonical drawing implies by reusing the
|
|
35
|
-
# name — documented, not hidden.
|
|
40
|
+
# name — documented, not hidden. Concretely: this figure declares 12
|
|
41
|
+
# `state` lines and TCP has 11 states. Merging `closed2` into `closed`
|
|
42
|
+
# was TRIED and REJECTED — every terminal transition then ran the length of
|
|
43
|
+
# the canvas and struck the setup/abort labels around the single CLOSED,
|
|
44
|
+
# and the figure became unreadable. So this is evidence that the
|
|
45
|
+
# primitive is MISSING, not that a workaround is available.
|
|
46
|
+
#
|
|
47
|
+
# WHERE ELSE THIS ONE GAP IS FILED (`OPEN-QUESTION-CITATION-STATUS`) — one primitive, three faces:
|
|
48
|
+
# 1. spec/core.md §9 `IDENTITY-ASSERTION` — the MODEL-side statement, and still OPEN.
|
|
49
|
+
# 2. the project’s working record, ISO 5807 Connector row — the
|
|
50
|
+
# DRAWING of the same fact in genre flowchart, status unknown
|
|
51
|
+
# (ISO §9.4.1 was never read here). Not a second requirement.
|
|
52
|
+
# 3. this figure — the live instance.
|
|
53
|
+
# spec/genres/experimental/statechart.md says what a reader may and may
|
|
54
|
+
# not conclude from two identically-labelled states meanwhile. There is
|
|
55
|
+
# no UML 2.5.1 §14 clause to borrow for this: UML has no "same state
|
|
56
|
+
# drawn twice".
|
|
36
57
|
#
|
|
37
58
|
# HONEST LIMIT — RFC Note 2. The canonical Figure 5 OMITS the
|
|
38
59
|
# FIN-WAIT-1 → TIME-WAIT transition and says so in its Note 2 (it occurs
|
|
39
|
-
# when a FIN arrives that also ACKs our FIN). We DRAW it (
|
|
60
|
+
# when a FIN arrives that also ACKs our FIN). We DRAW it (transition
|
|
61
|
+
# fw1→tw),
|
|
40
62
|
# so this figure is strictly MORE complete than the canonical drawing
|
|
41
63
|
# while carrying the same semantics the RFC prose states. Note 1 (rcv
|
|
42
64
|
# RST → LISTEN applies only to a passively-opened SYN-RECEIVED) rides on
|
|
43
|
-
# that
|
|
65
|
+
# that transition's label.
|
|
44
66
|
|
|
45
67
|
# ── Semantic classes — the meaning behind every stroke ──────────────
|
|
46
68
|
# A reading agent queries these to group transitions by role; the
|
|
47
69
|
# colour/dash is only presentation (`MEANING-RECOVERY-SOURCE`), the meaning is the label.
|
|
48
|
-
class states "A
|
|
70
|
+
class states "A state IS a TCP connection state (RFC 9293 §3.3.2); the two CLOSED states are one state drawn twice — only this label says so" fill=#eef2ff
|
|
49
71
|
class setup "Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)" stroke=#2563eb
|
|
50
72
|
class client "Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED" stroke=#dc2626
|
|
51
73
|
class server "Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED" stroke=#16a34a
|
|
52
74
|
class rare "Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)" stroke=#9333ea style=dashed
|
|
53
75
|
|
|
54
76
|
# ── The 11 states (CLOSED drawn twice; see `IDENTITY-ASSERTION` note above) ────────
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
state closed "CLOSED" shape=rounded class=states
|
|
78
|
+
state listen "LISTEN" shape=rounded class=states
|
|
79
|
+
state synsent "SYN-SENT" shape=rounded class=states
|
|
80
|
+
state synrcvd "SYN-RECEIVED" shape=rounded class=states
|
|
81
|
+
state estab "ESTABLISHED" shape=rounded class=states
|
|
82
|
+
state fw1 "FIN-WAIT-1" shape=rounded class=states
|
|
83
|
+
state fw2 "FIN-WAIT-2" shape=rounded class=states
|
|
84
|
+
state closing "CLOSING" shape=rounded class=states
|
|
85
|
+
state closewait "CLOSE-WAIT" shape=rounded class=states
|
|
86
|
+
state lastack "LAST-ACK" shape=rounded class=states
|
|
87
|
+
state timewait "TIME-WAIT" shape=rounded class=states
|
|
88
|
+
state closed2 "CLOSED" shape=rounded class=states
|
|
67
89
|
|
|
68
90
|
flow down
|
|
69
91
|
|
|
70
92
|
# ── Opening the connection (setup) ──────────────────────────────────
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
transition closed -[passive OPEN / create TCB]-> listen class=setup
|
|
94
|
+
transition closed -[active OPEN / create TCB, snd SYN]-> synsent class=setup
|
|
95
|
+
transition listen -[SEND / snd SYN]-> synsent class=setup
|
|
96
|
+
transition listen -[rcv SYN / snd SYN,ACK]-> synrcvd class=setup
|
|
97
|
+
transition synsent -[rcv SYN / snd SYN,ACK]-> synrcvd class=rare
|
|
98
|
+
transition synsent -[rcv SYN,ACK / snd ACK]-> estab class=setup
|
|
99
|
+
transition synrcvd -[rcv ACK of SYN / x]-> estab class=setup
|
|
78
100
|
|
|
79
101
|
# ── Aborting a half-open connection (rare / reset) ──────────────────
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
102
|
+
transition listen -[CLOSE / delete TCB]-> closed class=rare
|
|
103
|
+
transition synsent -[CLOSE / delete TCB]-> closed class=rare
|
|
104
|
+
transition synrcvd -[rcv RST (note 1) / x]-> listen class=rare
|
|
83
105
|
|
|
84
106
|
# ── Active close — the endpoint that calls CLOSE first ──────────────
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
107
|
+
transition synrcvd -[CLOSE / snd FIN]-> fw1 class=client
|
|
108
|
+
transition estab -[CLOSE / snd FIN]-> fw1 class=client
|
|
109
|
+
transition fw1 -[rcv ACK of FIN / x]-> fw2 class=client
|
|
110
|
+
transition fw1 -[rcv FIN / snd ACK]-> closing class=client
|
|
111
|
+
transition fw1 -[rcv FIN,ACK / snd ACK]-> timewait class=rare
|
|
112
|
+
transition fw2 -[rcv FIN / snd ACK]-> timewait class=client
|
|
113
|
+
transition closing -[rcv ACK of FIN / x]-> timewait class=client
|
|
114
|
+
transition timewait -[Timeout=2MSL / delete TCB]-> closed2 class=client
|
|
93
115
|
|
|
94
116
|
# ── Passive close — the endpoint that receives the peer's FIN ───────
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
117
|
+
transition estab -[rcv FIN / snd ACK]-> closewait class=server
|
|
118
|
+
transition closewait -[CLOSE / snd FIN]-> lastack class=server
|
|
119
|
+
transition lastack -[rcv ACK of FIN / x]-> closed2 class=server
|
|
98
120
|
|
|
99
121
|
layout
|
|
100
122
|
# ── Presentation only (`GUI-WRITEBACK-STRUCTURE`) ─────────────────────────────────────────
|
|
101
123
|
# The strip test holds: delete every line below and the machine is
|
|
102
124
|
# unchanged — all 11 states, all 21 transitions and their event/action
|
|
103
|
-
# labels live in the `
|
|
104
|
-
# an orphan: it is the target of two terminal
|
|
125
|
+
# labels live in the `state`/`transition`/`class` lines above (closed2
|
|
126
|
+
# is not an orphan: it is the target of two terminal transitions).
|
|
105
127
|
# the layout namespace is `pin` alone, so "every line below" is a shorter
|
|
106
128
|
# list than it used to be.
|
|
107
129
|
#
|
|
@@ -114,8 +136,8 @@ layout
|
|
|
114
136
|
# (terminus, under LAST-ACK as the RFC draws it).
|
|
115
137
|
# Column discipline: CLOSED→LISTEN, SYN-RECEIVED→FIN-WAIT-1→FIN-WAIT-2,
|
|
116
138
|
# CLOSING→TIME-WAIT, CLOSE-WAIT→LAST-ACK→CLOSED run dead vertical; the
|
|
117
|
-
# simultaneous-open
|
|
118
|
-
# between the mirrored pair. All meaning is in the
|
|
139
|
+
# simultaneous-open transition SYN-SENT→SYN-RECEIVED runs dead horizontal
|
|
140
|
+
# between the mirrored pair. All meaning is in the transitions; this is
|
|
119
141
|
# layout, not knowledge.
|
|
120
142
|
#
|
|
121
143
|
# WHAT CHANGED, AND WHY THE TOP ROWS ARE WIDER.
|
|
@@ -134,7 +156,7 @@ layout
|
|
|
134
156
|
# ~90 px further out, which pushes the two pairs' label midpoints far
|
|
135
157
|
# enough apart to read. Both pairs still run close together, exactly as
|
|
136
158
|
# the LISTEN↔SYN-RECEIVED pair always has in this figure — the ±7 px
|
|
137
|
-
# anti-parallel fan-out is the language's answer to a same-pair
|
|
159
|
+
# anti-parallel fan-out is the language's answer to a same-pair transition, and
|
|
138
160
|
# the class colours (blue = setup, purple = rare) say which stroke is
|
|
139
161
|
# which.
|
|
140
162
|
pin closed at=(394,20)
|
package/guide/expressing.md
CHANGED
|
@@ -63,12 +63,12 @@ is one place to look and nothing to reconcile.
|
|
|
63
63
|
| I need to show… | Use | Notes |
|
|
64
64
|
|---|---|---|
|
|
65
65
|
| ordered steps | directed `edge` chain; order = edge direction | `flow right` or `flow down` sets reading axis |
|
|
66
|
-
| decision + branches | under `flowchart`: `decision q "…"` + `
|
|
67
|
-
| a step, a start or an end | under `flowchart`: `process p "…"` · `terminator t "…"` | Same reason. The geometry is DERIVED (box / rounded); `shape=` still works and changes only the drawing, never the role.
|
|
66
|
+
| decision + branches | under `flowchart`: `decision q "…"` + `flowline q -[yes]-> …` / `flowline q -[no]-> …` | **Prefer `decision` over `node … shape=diamond`, because the next reader then has to know nothing** — a diamond has to be learned, a word is just read. And the convention is not reliable: of 216 question-labelled nodes in the production corpus, 78% are diamond, 14% ellipse, 8% carry no shape. Under `block`/`topology` the keyword does not exist, so `shape=diamond` + labelled edges remains the baseline (`SHAPE-ENUM-VOCABULARY`: geometry only) |
|
|
67
|
+
| a step, a start or an end | under `flowchart`: `process p "…"` · `terminator t "…"` | Same reason. The geometry is DERIVED (box / rounded); `shape=` still works and changes only the drawing, never the role. **Prefer a role; `node` is the FALLBACK, and it means exactly one thing: THE SOURCE DOES NOT STATE THE ROLE.** ISO 5807 is a drawing standard with no "unclassified", so a genuine stage always has a classification; FigDown separates role from geometry and can therefore record the absence instead of inventing one — the transcriber's case. **A symbol this genre cannot spell is a different matter: that is a COVERAGE GAP, not an unstated role.** Nine ISO stage symbols have no word here (Data, Stored data, Predefined process, Preparation, Manual operation, Manual input, Document, Parallel mode, Loop limit). For one of those, write `node`, **name the ISO symbol in a comment** on the same line (`node cfg "Read config" # ISO 5807 Data — no FigDown role`), and report the gap — the project’s working record keeps it |
|
|
68
68
|
| an n-way dispatch on a value | one `decision` with ≥3 outgoing edges, each `[mid]`-labelled with the value that selects it | The single most under-marked control point in real figures. Label every exit — including the fallback (`[other]`). There is no `default`/`otherwise` keyword and none is planned (0 corpus uses) |
|
|
69
69
|
| loop / retry | directed cycle back to an earlier node; condition in the mid-label | **the back-edge IS the loop** — there is no `loop`/`while` construct and none is planned (172 back-edges in the corpus, not one marking itself). But a cyclic graph needs explicit arrangement, not acceptance of an unreadable crossing ([layout.md §9](layout.md#9-cyclic-flows-why-the-ladder-stalls-and-what-to-do-instead)) |
|
|
70
70
|
| error paths | `class err "Error path" style=dashed` + `class=err` on error edges | separate semantic category from the happy path |
|
|
71
|
-
| state machine / lifecycle |
|
|
71
|
+
| state machine / lifecycle | `figdown 0.2 statechart` — `state` per mode, labelled directed `transition`s between them | **`statechart` LANDED at `STATECHART-GENRE-SCOPE`**, and at `GENRE-NODE-SPELLING` it took its own two words (OMG UML 2.5.1 §14): `node`→`state`, `edge`→`transition`. It is EXPERIMENTAL, and reclassifying now rewrites every connector line, not just line 1 — run `tools/migrate-figdown.js`. Use it when a node is a **mode the machine is in**; use `flowchart` when it is a step performed — a retry loop is a flowchart, whatever the title says. `block` stays the portable spelling for a `figdown 0.1` corpus. No `initial`/`final` vocabulary, and order still rides on labels. See [spec/genres/experimental/statechart.md](../spec/genres/experimental/statechart.md) |
|
|
72
72
|
| pipeline stages | `node` per stage + `external` at the mouths + `flow right` + `rank` | `external` marks where data enters/leaves the figure |
|
|
73
73
|
| event → action | `edge src -[event]-> tgt` | mid-label is the trigger; head-label can name the action |
|
|
74
74
|
| precedence / partial order | a DAG of directed edges | absence of an edge means no stated constraint |
|
package/guide/layout.md
CHANGED
|
@@ -174,16 +174,16 @@ Wrap long chains: one `rank` per stage row, let auto-layout stack the rows.
|
|
|
174
174
|
### Decision flowchart — main path on one axis
|
|
175
175
|
|
|
176
176
|
```figdown
|
|
177
|
-
figdown 0.
|
|
177
|
+
figdown 0.2 flowchart
|
|
178
178
|
terminator start "Start"
|
|
179
179
|
decision check "Header valid?"
|
|
180
180
|
process proc "Process"
|
|
181
181
|
terminator drop "Drop"
|
|
182
182
|
terminator done "Done"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
flowline start -> check
|
|
184
|
+
flowline check -[yes]-> proc
|
|
185
|
+
flowline check -[no]-> drop
|
|
186
|
+
flowline proc -> done
|
|
187
187
|
flow down
|
|
188
188
|
rank start,check,proc,done
|
|
189
189
|
```
|
|
@@ -285,7 +285,7 @@ pin tx at=(120,0)
|
|
|
285
285
|
```
|
|
286
286
|
author semantics
|
|
287
287
|
→ build: node tools/build-svg.js X.fd
|
|
288
|
-
→ judge: eyeball + node tools/layout-lint.js X.
|
|
288
|
+
→ judge: eyeball + node tools/layout-lint.js X.fd (6 metrics; --max-score gate)
|
|
289
289
|
→ if not clear: add ONE rung (§2) and repeat
|
|
290
290
|
→ stop when it reads well
|
|
291
291
|
```
|
|
@@ -515,13 +515,13 @@ better (backlog item #4) makes a layered drawing tidier; it never turns it into
|
|
|
515
515
|
a ring.
|
|
516
516
|
|
|
517
517
|
There is a second cause, and it is in the language rather than the engine.
|
|
518
|
-
Every flowchart
|
|
519
|
-
mainline from an exception branch from a retry loop — and those distinctions
|
|
518
|
+
Every flowchart connector today is a plain `flowline` (spelled `edge` before this release, `GENRE-CONNECTOR-SPELLING` — the rename gave the genre its own word, not a role). The
|
|
519
|
+
renderer cannot tell the mainline from an exception branch from a retry loop — and those distinctions
|
|
520
520
|
are *exactly* what human flowchart routing conventions are made of.
|
|
521
521
|
0.1 (`FLOWCHART-ROLE-KEYWORDS`) gave the genre role vocabulary for its NODES — `process`,
|
|
522
522
|
`decision`, `terminator` — which is why the sketches below use it, and the
|
|
523
523
|
renderer already consults it (a short branch marker sits near its
|
|
524
|
-
`decision`, not near any diamond). **
|
|
524
|
+
`decision`, not near any diamond). **CONNECTOR roles are still missing**
|
|
525
525
|
(`mainline` / `exception` / `loop-back`, recorded in `LOGIC-FLOWCHART-GENRE-SCOPE` and excluded from
|
|
526
526
|
the 0.1 tranche), so for routing the author still has to supply by
|
|
527
527
|
arrangement what the source cannot state. `class main/retry/fail`, used
|
|
@@ -562,7 +562,7 @@ the axis. Note that it needs **no layout zone at all** — with the spine
|
|
|
562
562
|
declared and the exits ranked off it, the figure lints at 0:
|
|
563
563
|
|
|
564
564
|
```figdown
|
|
565
|
-
figdown 0.
|
|
565
|
+
figdown 0.2 flowchart
|
|
566
566
|
title "Session establishment with bounded retry"
|
|
567
567
|
|
|
568
568
|
class main "Mainline — the path a successful call takes" stroke=#555
|
|
@@ -579,12 +579,12 @@ terminator give "Give up"
|
|
|
579
579
|
flow down
|
|
580
580
|
rank ok,cnt
|
|
581
581
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
582
|
+
flowline start -> send class=main
|
|
583
|
+
flowline send -> ok class=main
|
|
584
|
+
flowline ok -[yes]-> done class=main
|
|
585
|
+
flowline ok -[no]-> cnt class=fail
|
|
586
|
+
flowline cnt -[yes]-> send class=retry
|
|
587
|
+
flowline cnt -[no]-> give class=fail
|
|
588
588
|
```
|
|
589
589
|
|
|
590
590
|
Note what the `class` declarations are doing: they are not decoration and not a
|
package/guide/showcase.md
CHANGED
|
@@ -141,7 +141,7 @@ endpoint's TCP state segment by segment.
|
|
|
141
141
|

|
|
142
142
|
|
|
143
143
|
```figdown
|
|
144
|
-
figdown 0.
|
|
144
|
+
figdown 0.2 flowchart
|
|
145
145
|
title "L2 Switch Forwarding Decision"
|
|
146
146
|
|
|
147
147
|
class forward "Forward — send the frame out the single learned egress port" fill=#16a34a
|
|
@@ -160,13 +160,13 @@ node flt "Filter (drop):\nsame-port destination" shape=rounded class=f
|
|
|
160
160
|
|
|
161
161
|
flow down
|
|
162
162
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
163
|
+
flowline wire -> learn
|
|
164
|
+
flowline learn -> lookup
|
|
165
|
+
flowline lookup -> hit
|
|
166
|
+
flowline hit -[no]-> fld
|
|
167
|
+
flowline hit -[yes]-> same
|
|
168
|
+
flowline same -[yes]-> flt
|
|
169
|
+
flowline same -[no]-> fwd
|
|
170
170
|
```
|
|
171
171
|
|
|
172
172
|
**Human sees:** a frame from the ingress port → source-MAC learning →
|
|
@@ -292,59 +292,59 @@ prose rather than on an edge of its own.
|
|
|
292
292
|
|
|
293
293
|
---
|
|
294
294
|
|
|
295
|
-
## 6. TCP connection state machine — every state, every transition (`
|
|
295
|
+
## 6. TCP connection state machine — every state, every transition (`statechart`)
|
|
296
296
|
|
|
297
297
|

|
|
298
298
|
|
|
299
299
|
```figdown
|
|
300
|
-
figdown 0.
|
|
300
|
+
figdown 0.2 statechart
|
|
301
301
|
title "TCP Connection State Machine (RFC 9293, Figure 5)"
|
|
302
302
|
|
|
303
|
-
class states "A
|
|
303
|
+
class states "A state IS a TCP connection state (RFC 9293 §3.3.2); the two CLOSED states are one state drawn twice — only this label says so" fill=#eef2ff
|
|
304
304
|
class setup "Connection-setup transition — opening the connection (OPEN, SYN exchange, first ACK)" stroke=#2563eb
|
|
305
305
|
class client "Active-close path (typically the client) — calls CLOSE first: FIN-WAIT-1 → FIN-WAIT-2 / CLOSING → TIME-WAIT → CLOSED" stroke=#dc2626
|
|
306
306
|
class server "Passive-close path (typically the server) — receives the peer's FIN first: CLOSE-WAIT → LAST-ACK → CLOSED" stroke=#16a34a
|
|
307
307
|
class rare "Rare / simultaneous transition — simultaneous open or close, or a reset/abort (RST, close from a half-open state)" stroke=#9333ea style=dashed
|
|
308
308
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
309
|
+
state closed "CLOSED" shape=rounded class=states
|
|
310
|
+
state listen "LISTEN" shape=rounded class=states
|
|
311
|
+
state synsent "SYN-SENT" shape=rounded class=states
|
|
312
|
+
state synrcvd "SYN-RECEIVED" shape=rounded class=states
|
|
313
|
+
state estab "ESTABLISHED" shape=rounded class=states
|
|
314
|
+
state fw1 "FIN-WAIT-1" shape=rounded class=states
|
|
315
|
+
state fw2 "FIN-WAIT-2" shape=rounded class=states
|
|
316
|
+
state closing "CLOSING" shape=rounded class=states
|
|
317
|
+
state closewait "CLOSE-WAIT" shape=rounded class=states
|
|
318
|
+
state lastack "LAST-ACK" shape=rounded class=states
|
|
319
|
+
state timewait "TIME-WAIT" shape=rounded class=states
|
|
320
|
+
state closed2 "CLOSED" shape=rounded class=states
|
|
321
321
|
|
|
322
322
|
flow down
|
|
323
323
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
324
|
+
transition closed -[passive OPEN / create TCB]-> listen class=setup
|
|
325
|
+
transition closed -[active OPEN / create TCB, snd SYN]-> synsent class=setup
|
|
326
|
+
transition listen -[SEND / snd SYN]-> synsent class=setup
|
|
327
|
+
transition listen -[rcv SYN / snd SYN,ACK]-> synrcvd class=setup
|
|
328
|
+
transition synsent -[rcv SYN / snd SYN,ACK]-> synrcvd class=rare
|
|
329
|
+
transition synsent -[rcv SYN,ACK / snd ACK]-> estab class=setup
|
|
330
|
+
transition synrcvd -[rcv ACK of SYN / x]-> estab class=setup
|
|
331
|
+
|
|
332
|
+
transition listen -[CLOSE / delete TCB]-> closed class=rare
|
|
333
|
+
transition synsent -[CLOSE / delete TCB]-> closed class=rare
|
|
334
|
+
transition synrcvd -[rcv RST (note 1) / x]-> listen class=rare
|
|
335
|
+
|
|
336
|
+
transition synrcvd -[CLOSE / snd FIN]-> fw1 class=client
|
|
337
|
+
transition estab -[CLOSE / snd FIN]-> fw1 class=client
|
|
338
|
+
transition fw1 -[rcv ACK of FIN / x]-> fw2 class=client
|
|
339
|
+
transition fw1 -[rcv FIN / snd ACK]-> closing class=client
|
|
340
|
+
transition fw1 -[rcv FIN,ACK / snd ACK]-> timewait class=rare
|
|
341
|
+
transition fw2 -[rcv FIN / snd ACK]-> timewait class=client
|
|
342
|
+
transition closing -[rcv ACK of FIN / x]-> timewait class=client
|
|
343
|
+
transition timewait -[Timeout=2MSL / delete TCB]-> closed2 class=client
|
|
344
|
+
|
|
345
|
+
transition estab -[rcv FIN / snd ACK]-> closewait class=server
|
|
346
|
+
transition closewait -[CLOSE / snd FIN]-> lastack class=server
|
|
347
|
+
transition lastack -[rcv ACK of FIN / x]-> closed2 class=server
|
|
348
348
|
|
|
349
349
|
layout
|
|
350
350
|
pin closed at=(394,20)
|
|
@@ -365,7 +365,8 @@ The `pin` block reproduces the canonical Figure 5 arrangement so a
|
|
|
365
365
|
reader who knows the RFC diagram recognises it — but it is **presentation
|
|
366
366
|
only** (`strip-check --strict` passes): strip every line after `layout` and all
|
|
367
367
|
11 states, all 21 transitions and their `event / action` labels survive on the
|
|
368
|
-
`
|
|
368
|
+
`state`/`transition`/`class` lines. All meaning is in the transitions; the pins
|
|
369
|
+
are layout.
|
|
369
370
|
|
|
370
371
|
Three `path … points=` lines used to sit under those pins, bowing the active <!-- fence-check: skip -->
|
|
371
372
|
OPEN and the two aborts out to the margins. `EDGE-GEOMETRY-CONSTRUCTS` **withdrew the construct from
|
|
@@ -389,14 +390,14 @@ arrow carrying its `event / action`.
|
|
|
389
390
|
**An agent answers from the text alone:**
|
|
390
391
|
|
|
391
392
|
- *Q: What event takes ESTABLISHED to CLOSE-WAIT, and what does the endpoint
|
|
392
|
-
send?* A: `rcv FIN / snd ACK` — one
|
|
393
|
-
(`
|
|
393
|
+
send?* A: `rcv FIN / snd ACK` — one transition label
|
|
394
|
+
(`transition estab -[rcv FIN / snd ACK]-> closewait`).
|
|
394
395
|
- *Q: From FIN-WAIT-1, how many ways lead to TIME-WAIT and under what
|
|
395
396
|
conditions?* A: three. (1) Directly: `rcv FIN,ACK / snd ACK` (the RFC Note-2
|
|
396
397
|
transition, `fw1 -> timewait`). (2) Via FIN-WAIT-2: `rcv ACK of FIN / x` then
|
|
397
398
|
`rcv FIN / snd ACK` (`fw1 -> fw2 -> timewait`). (3) Via CLOSING:
|
|
398
399
|
`rcv FIN / snd ACK` then `rcv ACK of FIN / x` (`fw1 -> closing -> timewait`).
|
|
399
|
-
All read off the
|
|
400
|
+
All read off the transitions.
|
|
400
401
|
- *Q: How long does TIME-WAIT last and what happens after?* A: `Timeout=2MSL`,
|
|
401
402
|
then `delete TCB` → CLOSED (`timewait -[Timeout=2MSL / delete TCB]-> closed2`).
|
|
402
403
|
- *Q: Which transitions belong to the typical server (passive-close) path?*
|
|
@@ -430,12 +431,17 @@ The Ethernet frame uses the **`BYTE-UNIT-PACKET-BLOCKS`** byte-unit workaround (
|
|
|
430
431
|
not `bitfield`) so byte order rides on cell order, and one of its facts — the
|
|
431
432
|
FCS **coverage span** over a contiguous run of columns (DA through Payload) —
|
|
432
433
|
has no annotation construct yet (**`CONTIGUOUS-RANGE-GROUPING`**), so it rides on a source comment
|
|
433
|
-
and prose. The TCP state machine meets
|
|
434
|
-
|
|
435
|
-
|
|
434
|
+
and prose. The TCP state machine meets one more, and **has just stopped meeting
|
|
435
|
+
the other**: state-ness IS first-class since `STATECHART-GENRE-SCOPE` — line 1 reads
|
|
436
|
+
`figdown 0.2 statechart`, so "this is a state" is now declared by the word
|
|
437
|
+
`state` itself (`GENRE-NODE-SPELLING`) rather than carried by the `states` class
|
|
438
|
+
label, and the label stays only because it says
|
|
439
|
+
something more specific about the two CLOSED nodes. The genre is EXPERIMENTAL
|
|
440
|
+
and may be withdrawn. What remains is that CLOSED is drawn **twice** because
|
|
441
|
+
FigDown has
|
|
436
442
|
no **node-identity/alias** construct (**`IDENTITY-ASSERTION`**) to declare two nodes the same
|
|
437
|
-
entity; the shared class label asserts it instead.
|
|
438
|
-
|
|
443
|
+
entity; the shared class label asserts it instead. So those two are the *only*
|
|
444
|
+
facts the figure
|
|
439
445
|
cannot carry that the canonical drawing implies. All are documented in
|
|
440
446
|
[expressing.md](expressing.md)'s "Known limits".
|
|
441
447
|
That a figure format states its own limits — and that a reading agent recovers
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "figdown",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Figures as text — one source, two readers: a closed, deterministic figure language for Markdown, readable by AI agents and humans alike",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "FigDown <hello@figdown.org>",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"gate:page": "node tools/page-check.js",
|
|
33
33
|
"gate:shape": "node tools/shape-check.js --strict",
|
|
34
34
|
"gate:strip": "node tools/strip-check.js --strict",
|
|
35
|
-
"gate:layout": "node tools/layout-lint.js",
|
|
35
|
+
"gate:layout": "node tools/layout-lint.js --strict",
|
|
36
36
|
"gate:artifact": "node tools/artifact-check.js --strict",
|
|
37
37
|
"gate:dist": "node tools/dist-check.js --strict",
|
|
38
38
|
"gate:isolation": "node tools/isolation-check.js --strict",
|