Skip to content

v0.28.2 — a resource port's connections on two sides branch on their own - #357

Merged
MerciHanrim merged 3 commits into
mainfrom
fix/fan-key-by-face
Oct 15, 2026
Merged

MerciHanrim merged 3 commits into
mainfrom
fix/fan-key-by-face

Conversation

@MerciHanrim

@MerciHanrim MerciHanrim commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

v0.28.2 — a resource port's connections on two sides branch on their own

The router grouped a port's connections into one fan by node and handle id only, so an out leaving a node's bottom face and one leaving its right face shared branch points and excused each other's stub (Coffee's green wholesale line had a needless S-jog from it). Share notes 50 and 54 hold the investigation, the experiments and every same-view capture. Three commits, each verified as it was done.

1. The rule (5364fca, src/store/routeMap.ts)

A new fanKey decides, per FAN:

  • fan membership (branch points, first legs): for a RESOURCE port the node, the handle id and the face — two sides are two stubs in two places, two fans; a STATE port keeps one fan across its sides, as before;
  • the sibling relation while routing: a sibling's route is cut at the shared stub (not charged there) and offered as lanes, anything else is an ordinary obstacle — so two resource lines on two sides of one handle no longer excuse each other's stub; and the fanOverlaps check.

endKey still decides, per handle: the port use behind "no label on a shared stub", a route's exemption from its own ports' reserved stubs, and the parallel sets. A resource in and out are never one fan. docs/edge-routing.md §ER14.3 says which connections form one fan and what each key decides.

Why state ports are not included. Grouping every port by side was measured first: it fixes Coffee the same way but makes three lines harder to follow on the gacha banner Template. Reverting one port at a time showed all three are one thing — an arriving and a leaving state connection meeting one side of a node at one point, which the old cross-side fans happened to push apart. That meeting is a separate, later unit. A general cost for running beside another line was tried for it and rejected (it fixed none cleanly, broke Coffee's roasted-bean fan, slowed MMO routing about 60 %).

Why the sibling relation follows the fan. Measured on 32 small synthetic diagrams with one handle used on two sides: 29 draw the same either way; in the 3 hard ones (an in fed from straight left into its top side and from straight above into its left side) treating the two as siblings let one hook round the corner across the other — 2–3 crossings; as ordinary routes, 1. None worse.

2. What draws differently

Every bundled example dumped in the browser: Coffee roastery operations flow 1 route (e_green_wholesale, straight now), 3-zone gacha banner comparison 5 (e_pickup_3, 4, 5, 9, 14: same-view close-ups judged three easier to follow, two no real difference), every other example unchanged; the router's fan diagnostics 0 / 0.

3. Tests

src/store/routeMap.fanKey.test.ts (9), through a test-only seam __planFans (not on the dev bridge; absent from the production build): resource ports by face, state ports across faces, in / out never one fan, and the three hard cases (one crossing). Mutations: the face dropped from the resource key fails the two resource-by-face tests, the face added to the state key fails the state test, the sibling relation on endKey fails the three hard cases.

4. Baseline (0e84f70) and release (b5e2bdf)

  • One screenshot baseline changed, as expected: forced-active-resource-coffee-z05.png (29 px, the straightened Coffee line), regenerated from the final code; byte-identical to the reviewed "actual".
  • 0.28.2: .changes/fan-key-by-face.json (user-facing), three What's new lines in 18 languages (resource connections on two sides branch separately in some diagrams; six automatic routes in two bundled Templates change, named by each locale's own Template names; state connections unchanged), CHANGELOG v0.28.2, README Latest. Release date 2026-10-15, to be checked on the merge day.
  • The translation contract tests pass: evidence of the catalogs' structure and terms, not a review of how the lines read. The English and Korean lines were reviewed; the other 16 had no native-speaker review.

Verification, by head

Head What ran Result
b5e2bdf PR CI, run 38667880094 success: checks, e2e shards 1–6, production bundle, PWA
b5e2bdf Full local e2e, --workers=1 --retries=0 2 191 passed, 0 failed, 10 skipped (47.9 min)
b5e2bdf dist config, then pwa config, run separately 16 passed; 19 passed
b5e2bdf Unit (vitest, full); tsc; lint; check:change-declaration, check:i18n, check:i18n-surface, check:control-bytes, check:isolate-arguments, check:locale-lists, check:functional-glyphs, check:e2e-shards, check:snapshot-policy 3 586 passed, 1 skipped; lint 0 errors; all pass
0e84f70 forced-colors-edge-tell.spec.ts without updating 19 passed

An earlier full run on b5e2bdf stopped at test 272 of 2 201 with no failure reported, when the session restarted; it is not a result and was rerun from the start (above).

Separate, later units

The arriving / leaving state connections at one point of one side (Pity top, Roll — forced, owed bottom on the gacha banner) — why the state half of the face rule waits. Seen while measuring, main too: after undo / redo React Flow keeps a connection's selected mark without the Inspector's selection; starting to draw a connection on the gacha banner costs about 0.2 s (636 face handles mount).

Share notes 50 and 54. The router grouped a port's connections into one
fan by node and handle id only, so an `out` leaving the bottom face and
one leaving the right face shared branch points and excused each other's
stub (Coffee's `e_green_wholesale` had a needless S-jog from it).

A new `fanKey` (`src/store/routeMap.ts`) decides, per fan:
- fan membership (branch points, first legs): for a RESOURCE port the node,
  the handle id and the face; a STATE port keeps one fan across its faces,
  as before;
- the sibling relation while routing: a sibling's route is cut at the
  shared stub and offered as lanes, anything else is an ordinary obstacle —
  so two resource lines on two faces of one handle no longer excuse each
  other's stub; and the `fanOverlaps` check.
`endKey` still decides, per handle: the port use count behind "no label on
a shared stub", the own-port exemption from the reserved stubs, and the
parallel sets. A resource `in` and `out` are never one fan.

Why only resource ports: grouping state ports by face too (measured)
fixes Coffee but makes three readability regressions on the gacha banner
Template, all one cause — an arriving and a leaving state connection on
one face at one anchor, which the old cross-face fans happened to push
apart. That collision is a separate unit. A general cost for running
beside a line was tried and rejected (it fixed none cleanly, broke
Coffee's roasted-bean fan and slowed MMO routing about 60 %).

Drawing, every bundled example dumped in the browser: Coffee 1 route
changes (`e_green_wholesale`, straight now), the gacha banner 5
(`e_pickup_3`, `4`, `5`, `9`, `14`; same-view close-ups: three better, two
no real difference), every other example unchanged. 32 small synthetic
mixed-face diagrams: the sibling rule by fan draws 29 the same and cuts
crossings in the three hard ones.

Tests: `routeMap.fanKey.test.ts` (9) through a test-only seam
`__planFans` (not on the dev bridge, absent from the production build):
resource ports by face, state ports across faces, `in` / `out` never one
fan, and the three hard cases (one crossing; they fail with the sibling
relation on `endKey`). `docs/edge-routing.md` §ER14.3 says which
connections form one fan and what each key decides.

Checks: tsc, lint, full vitest (3 586 passed, 1 skipped). Screenshot
specs: one baseline differs, as expected — `forced-active-resource-coffee-
z05.png`, 29 px, the straightened Coffee line; not updated here.
…tened green wholesale line

`forced-active-resource-coffee-z05.png` regenerated from the final code of
the previous commit, the only baseline its screenshot specs changed (29 px,
0.01 %): Coffee's `e_green_wholesale` now goes straight down from Green
bean stock's bottom face instead of an S-jog. The new image is
byte-identical to the "actual" of the earlier failing run that was
reviewed. `forced-colors-edge-tell.spec.ts`: 19 passed without updating.
…ranch on their own

- package.json / package-lock.json 0.28.2; `.changes/fan-key-by-face.json`
  (user-facing, `release:0.28.2`), date 2026-10-15, to be checked on the
  merge day.
- What's new 0.28.2, three lines in 18 languages (Lumi's wording,
  2026-10-15): resource connections that use one port from different sides
  branch separately, reducing detours in some diagrams; six automatic
  routes in two bundled Templates change, named by each locale's own
  Template names; state connections are unchanged. The side / port /
  resource / state words follow each locale's UI. es-ES = es-419 and
  pt-PT = pt-BR, written neutrally; French avoids the punctuation its
  spacing rule governs. Locale count pins follow (catalog 1141, runtime
  1363); es-419 and vi declare the Latin `gacha` / `banner` of the Template
  name in the new line; the e2e release list pins 0.28.2.
- CHANGELOG v0.28.2; README Latest v0.28.2 (v0.28.1 kept as a section,
  v0.26.2 moved into the CHANGELOG list).

The translation contract tests pass: evidence of the catalogs' structure
and terms, not a review of how the lines read; no native-speaker review.
Checks: tsc, lint, full vitest (3 586 passed, 1 skipped), change
declaration, i18n, i18n surface, control bytes, isolate arguments, locale
lists, functional glyphs, e2e shards, snapshot policy.
@MerciHanrim
MerciHanrim merged commit b11ff65 into main Oct 15, 2026
11 checks passed
@MerciHanrim
MerciHanrim deleted the fix/fan-key-by-face branch October 15, 2026 02:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant