Repository navigation
fix(figc4.4, figc4.5): DL-FLOW-OFF acts on the not-busy branch, and the busy arms stage N(r) (#43) - #109
Draft
M0LTE wants to merge 3 commits into
Draft
fix(figc4.4, figc4.5): DL-FLOW-OFF acts on the not-busy branch, and the busy arms stage N(r) (#43)#109M0LTE wants to merge 3 commits into
M0LTE wants to merge 3 commits into
Conversation
…rms stage N(r) (#43) The Connected DL-FLOW-OFF column asked "Own Receiver Busy?" and hung "Set Own Receiver Busy, RNR Response, Clear Acknowledge Pending" off the Yes arm, the No arm returning straight to the state, so a not-busy station could never enter the busy condition through DL-FLOW-OFF, which is the primitive's whole purpose (5.3 "temporarily suspend the flow of incoming information"; 6.4.10 "Whenever a TNC enters a busy condition, it indicates this by sending an RNR response at the next opportunity"). The mirror DL-FLOW-ON column acts on its Yes (busy) arm and is untouched. See #43. - DataLink_Connected.graphml: the Yes and No labels on edges e46 and e50 are swapped. Two new "N(r) <- V(r)" processing boxes: n182 before RNR Response on the DL-FLOW-OFF arm and n183 before RR Command on the DL-FLOW-ON busy arm (ax25sdl explorer note H3: every other RR/RNR emission on the page stages N(r) first and the interpreter treats an unstaged emission as a machine error, so the arm had to become executable in the same change that makes it reachable). e47/e54 retargeted to the new boxes, e211/e212 continue to the emissions. The boxes below each insertion, the shared "3 Connected" terminal and the second bend point of the two decision-to-state edges move down by 90 (one box plus the column's 30 gap), so every original gap is preserved; no node overlaps or edge/box crossings introduced (checked mechanically against main). - connected.sdl.yaml regenerated by the Packet.Sdl.Transcribe walker: still 68 transitions / 39 decisions; t05_dl_flow_off_request_yes and _no swap meaning (the walker's suffix follows the edge label), and t05_..._no, t06_dl_flow_on_request_yes_yes and _yes_no gain the "N(r) := V(r)" step. - connected.citations.yaml re-keyed (the two t05 entries swap keys) and annotated: CORRECTION APPLIED (#43) header, ERRATUM (#43) notes on both t05 arms and the H3 note on both t06 busy arms, with the evidence (ax25sdl explorer calibration row #43, golden trace dl-flow-off-sets-busy, packet.net quirk Ax25Spec43DlFlowOffEntersBusy, the direwolf and linbpq negative evidence); the legacy-id mapping table gains a note. - connected.g.mmd + DataLink_Connected.svg regenerated. Totality lint clean (8051 feasible valuations, 0 holes, 0 overlaps). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qyx5dT8rmRTb8szT4SpEQ
…rms stage N(r) (#43) Timer Recovery carries the same pair of flow-control columns as figc4.4, with the emissions written out as "RNR Response (F = 0)" and "RR Command (P = 0)". Same correction as the figc4.4 commit, kept separate so the two figures can be reviewed and reverted independently. - DataLink_TimerRecovery.graphml: Yes/No labels on e33 and e43 swapped; new "N(r) <- V(r)" boxes n244 (before RNR Response (F = 0)) and n245 (before RR Command (P = 0)); e35/e36 retargeted, e274/e275 continue to the emissions. Boxes below each insertion, the shared "4 Timer Recovery" terminal and the second bend point of the two decision-to-state edges move down by 95.62 (one box plus this column's 35.6 gap), preserving every original gap; no node overlaps or edge/box crossings introduced (checked mechanically against main). - timer_recovery.sdl.yaml regenerated: still 92 transitions / 47 decisions; t05_dl_flow_off_request_yes and _no swap meaning; t05_..._no, t06_dl_flow_on_request_yes_yes and _yes_no gain the "N(r) := V(r)" step. - timer_recovery.citations.yaml: the t05 entry re-keyed to _no and annotated (ERRATUM (#43)); a t05_..._yes entry added for the now-empty arm; H3 note on t06_..._yes_no and a new t06_..._yes_yes entry carrying it; CORRECTION APPLIED (#43) header. - timer_recovery.g.mmd + DataLink_TimerRecovery.svg regenerated (the srej-received viewport is untouched). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qyx5dT8rmRTb8szT4SpEQ
…r) staging (#43) "Changes from Version 2.2" table: row appended for the Figure C4.4 / C4.5 DL-FLOW-OFF decision (actions now on the not-busy arm) and the "N(r) := V(r)" box inserted before the RNR and RR emissions on the flow-control busy arms. No prose change: 5.3 defines DL-FLOW-OFF as suspending the flow of incoming information and 6.4.10 already says a TNC entering the busy condition sends an RNR response at the next opportunity. Refs #43. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qyx5dT8rmRTb8szT4SpEQ
SVG figure changes (
|
| what | change | |
|---|---|---|
| + | node | N(r) <- V(r) |
| + | node | N(r) <- V(r) |
| + | edge | Clear Own Receiver Busy → N(r) <- V(r) |
| + | edge | N(r) <- V(r) → RNR Response |
| + | edge | N(r) <- V(r) → RR Command |
| + | edge | Set Own Receiver Busy → N(r) <- V(r) |
| − | edge | Clear Own Receiver Busy → RR Command |
| − | edge | Set Own Receiver Busy → RNR Response |
spec-sdl/v2.2-errata/data-link/svg/DataLink_TimerRecovery.svg
nodes 241→243, edges 272→274, labels 113→113
| what | change | |
|---|---|---|
| + | node | N(r) <- V(r) |
| + | node | N(r) <- V(r) |
| + | edge | Clear Own Receiver Busy → N(r) <- V(r) |
| + | edge | N(r) <- V(r) → RNR Response (F = 0) |
| + | edge | N(r) <- V(r) → RR Command (P = 0) |
| + | edge | Set Own Receiver Busy → N(r) <- V(r) |
| − | edge | Clear Own Receiver Busy → RR Command (P = 0) |
| − | edge | Set Own Receiver Busy → RNR Response (F = 0) |
Interactive viewers — swipe, onion-skin, blink, and a clickable change list that zooms to each change — are attached to this run as the svg-figure-diff artifact: download, unzip, open the HTML.
Locally: python3 tools/svgdiff/svg_diff.py main HEAD --all --merge-base
M0LTE
marked this pull request as draft
September 10, 2026 22:52
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #43. Stacked on PR #107 (#47): base is
fix/47-timer-recovery-drain-incrementbecause both touch figc4.5; retarget tomainonce #107 merges (the three commits here are the only delta).What changed (both figc4.4 Connected and figc4.5 Timer Recovery).
N(r) <- V(r)processing box is inserted immediately before "RNR Response" on the DL-FLOW-OFF action arm and immediately before "RR Command" on the DL-FLOW-ON busy arm, on both pages, matching how every other RR/RNR emission on these pages stages N(r) first (Transmit Enquiry and Enquiry Response on figc4.7, the I-frame arms). Per ax25sdldocs/explorer.md"Novel findings" H3, the interpreter treats an emission without a staged N(r) as a machine error, so the arm had to become executable in the same change that makes it reachable; every implementation sends N(r) = V(r) on that RNR.Layout: the boxes below each insertion, the shared terminal state and the second bend point of the two decision-to-state edges move down by one box plus the column's existing gap (90 on figc4.4, 95.62 on figc4.5), so every original gap is preserved. Checked mechanically against main: no node overlaps and no edge/box crossings introduced on either page.
Why. §5.3 defines DL-FLOW-OFF.Request as "temporarily suspend the flow of incoming information"; §6.4.10: "Whenever a TNC enters a busy condition, it indicates this by sending an RNR response at the next opportunity." The figure gated the busy entry on already being busy, contradicting its own primitive, and the DL-FLOW-ON symmetry (act only when there is a busy condition to clear) says FLOW-OFF must act on not-busy. The prose already states the behaviour, so the v2.3 draft only gains a "Changes from Version 2.2" table row.
Evidence (#93 rule 1: the fix flips its evidence).
docs/explorer.md, current tables): Connected seed, A sends 2, B's layer 3 turns flow off after its first delivery, no faults; the busy-tracks-flow invariant fires at 3 steps with B takingt05_dl_flow_off_request_no(the empty not-busy arm) and staying not-busy and silent; with that check off, flow-off delivery fires at 5 (B deliversa1upward with flow off). TestsDefect43_*inCalibrationTests.cs, includingDefect43_Note_The_Busy_Arms_Emit_RNR_And_RR_Without_N_r_Stagingfor H3.traces/dl-flow-off-sets-busy.trace.yaml(expected_failureon figc4.4 DL-FLOW-OFF: Set-Own-Receiver-Busy/RNR on the wrong branch — a not-busy station can never enter busy via DL-FLOW-OFF #43): Connected, not busy,DL_FLOW_OFF_requestshould leaveown_receiver_busy: trueand emit an RNR response carrying V(r).Ax25Spec43DlFlowOffEntersBusy(src/Packet.Ax25/Session/Ax25SessionQuirks.cs, default on): inverts theown_receiver_busyguard forDL_FLOW_OFF_requestonly.src/ax25_link.c: "dl_flow_off - not implemented", "we currently don't have a way to set own_receiver_busy") nor linbpq exposes the primitive. The fix rests on the prose, the figure's self-contradiction and the FLOW-ON symmetry.Regeneration.
connected.sdl.yamlandtimer_recovery.sdl.yamlregenerated with the Packet.Sdl.Transcribe walker at the pinned tooling ref (68/39 and 92/47 transitions/decisions, unchanged counts). Because the walker's suffix follows the edge label,t05_dl_flow_off_request_yesand_noswap meaning on both pages (_nonow carries the actions,_yesis the no-op);t05_..._no,t06_dl_flow_on_request_yes_yesand_yes_nogain theN(r) := V(r)step. Both*.citations.yamlsidecars are re-keyed accordingly (every key still names a transition; checked) and annotated with CORRECTION APPLIED (#43) headers, ERRATUM (#43) notes on both t05 arms and the H3 note on both t06 busy arms. Mermaid and SVG regenerated; totality lint clean (8051 feasible valuations, 0 holes, 0 overlaps).svgdiff (
python3 tools/svgdiff/svg_diff.py fix/47-timer-recovery-drain-increment fix/43-dl-flow-off-branch --all --merge-base --format markdown):spec-sdl/v2.2-errata/data-link/svg/DataLink_Connected.svgnodes 182→184, edges 211→213, labels 73→73
N(r) <- V(r)N(r) <- V(r)Clear Own Receiver Busy → N(r) <- V(r)N(r) <- V(r) → RNR ResponseN(r) <- V(r) → RR CommandSet Own Receiver Busy → N(r) <- V(r)Clear Own Receiver Busy → RR CommandSet Own Receiver Busy → RNR Responsespec-sdl/v2.2-errata/data-link/svg/DataLink_TimerRecovery.svgnodes 241→243, edges 272→274, labels 113→113
N(r) <- V(r)N(r) <- V(r)Clear Own Receiver Busy → N(r) <- V(r)N(r) <- V(r) → RNR Response (F = 0)N(r) <- V(r) → RR Command (P = 0)Set Own Receiver Busy → N(r) <- V(r)Clear Own Receiver Busy → RR Command (P = 0)Set Own Receiver Busy → RNR Response (F = 0)Note that svgdiff's edge signature does not carry the edge label, so the Yes/No swap is invisible to it (label counts 73 to 73 and 113 to 113 because both words still exist). The graphml multiset diff against the base branch (source label, edge label, target label) shows the swap explicitly, and nothing else:
ax25sdl follow-up: remove the expected_failure marker from traces/dl-flow-off-sets-busy.trace.yaml, turn the #43 explorer calibration row clean, delete the tables-43fixed fixture once the pin lands.
🤖 Generated with Claude Code
https://claude.ai/code/session_014qyx5dT8rmRTb8szT4SpEQ
Status (paused on Tom's order, 2026-09-10). Everything for #43 is finished and pushed: both graphml edits (label swap + N(r) staging box on figc4.4 and figc4.5), yaml/mermaid/SVG regeneration, both sidecars re-keyed and annotated, draft-doc row. Nothing is half done. CI does not fire on a PR whose base is not
main, so instead: (a) the transcribe drift was checked locally with the pinned ax25sdl tooling refff5bc7d(no drift), (b) a fresh render matches the committed SVGs, (c)ci.ymlwas dispatched by hand on this branch (run 34539506948) andsvg-figure-difffor this PR (run 34539508708, success). To resume: once #107 merges,gh pr edit 109 --base main, which also makes the normal PR checks run. Worktree:/home/tf/ax25spec-wt/fix43.