Skip to content

Chorale: one room, one conductor — three ways the election could split - #151

Open
apirrone wants to merge 2 commits into
mainfrom
chorale-election
Open

Chorale: one room, one conductor — three ways the election could split#151
apirrone wants to merge 2 commits into
mainfrom
chorale-election

Conversation

@apirrone

Copy link
Copy Markdown
Contributor

Reported from a four-duck room, robotctl chorale typed by hand seconds apart: sometimes it worked, sometimes two songs at once, sometimes nothing at all. Three separate bugs, and the guess in the report — "what if two ducks start singing before the other two have seen them?" — was the first one exactly.

Two conductors never resolved. Nothing in conduct looked for a rival. Two ducks can pair off and start before either has seen the other two, who pair off and start their own piece — picked from their own clock, so not even the same song — and both performances then ran side by side to the end. Now a conductor that hears a lower-id duck conducting abandons its own performance and joins that one, so the room converges from any arrangement, by id, with nothing to negotiate and nothing to oscillate.

Deference had no timeout, which is the "nothing happens" case. The lowest id conducts — but the lowest id in one duck's view, and BLE discovery is neither simultaneous nor symmetric. The lowest duck can still be seeing nobody while everybody else sees it, and a duck alone does not sing: three ducks then defer, forever, to a duck that will never start. Deference is now a timer — one extra SETTLE per lower-id duck in view — so the second-lowest takes over if the lowest never starts, in id order rather than three ducks starting three pieces at once.

A follower outlived its conductor. It locks to one conductor by id and ignores every other beacon, which is what keeps a second piece from pulling it off the beat. The cost was that a conductor which stopped — yielded, or switched off — left its followers free-running to the end of a song nobody else was singing. Off the air or on the air and no longer singing now both mean: back to listening, and join whatever is actually being sung.

The regression test is the reported room rather than a unit: four ducks, staggered starts, and a visible predicate that keeps them in two islands long enough to each elect a conductor. It asserts the split really happens, then that it ends with one conductor, the lower of the two, and all four on one piece. Each fix was checked by disabling it — the sim reports two conductors without the yield, and [1, 2, 1, 1] pieces without the follower fix.

Reported from a four-duck room, `robotctl chorale` typed by hand seconds
apart: sometimes it worked, sometimes two songs at once, sometimes nothing
at all. Three separate bugs, and the guess in the report — "what if two
ducks start singing before the other two have seen them?" — was the first
one exactly.

**Two conductors never resolved.** Nothing in `conduct` looked for a rival.
Two ducks can pair off and start before either has seen the other two, who
pair off and start their own piece — picked from their own clock, so not
even the same song — and both performances then ran side by side to the end.
Now a conductor that hears a *lower-id* duck conducting abandons its own
performance and joins that one, so the room converges from any arrangement,
by id, with nothing to negotiate and nothing to oscillate.

**Deference had no timeout, which is the "nothing happens" case.** The
lowest id conducts — but the lowest id *in one duck's view*, and BLE
discovery is neither simultaneous nor symmetric. The lowest duck can still
be seeing nobody while everybody else sees it, and a duck alone does not
sing: three ducks then defer, forever, to a duck that will never start.
Deference is now a timer — one extra SETTLE per lower-id duck in view — so
the second-lowest takes over if the lowest never starts, in id order rather
than three ducks starting three pieces at once.

**A follower outlived its conductor.** It locks to one conductor by id and
ignores every other beacon, which is what keeps a second piece from pulling
it off the beat. The cost was that a conductor which stopped — yielded, or
switched off — left its followers free-running to the end of a song nobody
else was singing. Off the air or on the air and no longer singing now both
mean: back to listening, and join whatever is actually being sung.

The regression test is the reported room rather than a unit: four ducks,
staggered starts, and a `visible` predicate that keeps them in two islands
long enough to each elect a conductor. It asserts the split really happens,
then that it ends with one conductor, the lower of the two, and all four on
one piece. Each fix was checked by disabling it — the sim reports two
conductors without the yield, and `[1, 2, 1, 1]` pieces without the
follower fix.
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

Coverage

70.59% lines on this branch, against a floor of 72%.

Per-file
Filename                              Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
btd/src/adv.rs                             79                 0   100.00%           9                 0   100.00%          42                 0   100.00%           0                 0         -
btd/src/bluez.rs                          422               422     0.00%          32                32     0.00%         279               279     0.00%           0                 0         -
btd/src/chorale.rs                        346               246    28.90%          23                13    43.48%         230               171    25.65%           0                 0         -
btd/src/framing.rs                        217                 7    96.77%          17                 1    94.12%          97                 5    94.85%           0                 0         -
btd/src/gatt.rs                             3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
btd/src/link.rs                            13                 0   100.00%           1                 0   100.00%          17                 0   100.00%           0                 0         -
btd/src/main.rs                            77                77     0.00%          11                11     0.00%          77                77     0.00%           0                 0         -
btd/src/pairing.rs                        149                 2    98.66%          12                 1    91.67%          81                 1    98.77%           0                 0         -
btd/src/route.rs                          289                26    91.00%          24                 0   100.00%         269                 9    96.65%           0                 0         -
btd/src/session.rs                       1118                71    93.65%          66                 5    92.42%         649                41    93.68%           0                 0         -
btd/src/upstream.rs                       297                43    85.52%          29                 8    72.41%         184                25    86.41%           0                 0         -
configd/src/bluez.rs                      441               441     0.00%          78                78     0.00%         297               297     0.00%           0                 0         -
configd/src/identity.rs                   111                 5    95.50%          12                 1    91.67%          52                 3    94.23%           0                 0         -
configd/src/main.rs                       494               494     0.00%          38                38     0.00%         338               338     0.00%           0                 0         -
configd/src/net.rs                        246                12    95.12%          38                 2    94.74%         181                 4    97.79%           0                 0         -
configd/src/nm.rs                         271               213    21.40%          43                39     9.30%         171               120    29.82%           0                 0         -
configd/src/pad.rs                        301                12    96.01%          33                 2    93.94%         186                 8    95.70%           0                 0         -
configd/src/power.rs                       30                30     0.00%           6                 6     0.00%          28                28     0.00%           0                 0         -
configd/src/store.rs                      350                25    92.86%          28                 2    92.86%         173                 9    94.80%           0                 0         -
configd/src/units.rs                      119               119     0.00%          18                18     0.00%          83                83     0.00%           0                 0         -
duck-control/src/bus.rs                   408               299    26.72%          33                21    36.36%         276               203    26.45%           0                 0         -
duck-control/src/fall.rs                  173                 0   100.00%          15                 0   100.00%         108                 0   100.00%           0                 0         -
duck-control/src/imu.rs                   370                 8    97.84%          20                 0   100.00%         195                 5    97.44%           0                 0         -
duck-control/src/io.rs                    127                19    85.04%          20                 5    75.00%         115                17    85.22%           0                 0         -
duck-control/src/model.rs                 113                 1    99.12%          14                 0   100.00%          68                 0   100.00%           0                 0         -
duck-control/src/obs.rs                   260                 3    98.85%          23                 1    95.65%         174                 5    97.13%           0                 0         -
duck-control/src/policy.rs                347               239    31.12%          41                24    41.46%         229               150    34.50%           0                 0         -
duck-control/src/safety.rs                410                12    97.07%          31                 2    93.55%         274                 6    97.81%           0                 0         -
duck-detect/src/bin/duck-bench.rs         306               306     0.00%          16                16     0.00%         170               170     0.00%           0                 0         -
duck-detect/src/lib.rs                    512                10    98.05%          24                 0   100.00%         274                 6    97.81%           0                 0         -
duck-detect/src/onnx.rs                    96                96     0.00%           5                 5     0.00%          52                52     0.00%           0                 0         -
duck-detect/src/rknn.rs                   267               237    11.24%          15                11    26.67%         216               195     9.72%           0                 0         -
duck-ipc-proto/src/lib.rs                1828               159    91.30%         123                14    88.62%        1343                91    93.22%           0                 0         -
duckctl/src/main.rs                      1900               825    56.58%         120                41    65.83%        1169               508    56.54%           0                 0         -
kinematics/src/hand.rs                    373                 2    99.46%          21                 2    90.48%         172                 2    98.84%           0                 0         -
kinematics/src/head.rs                    381                 9    97.64%          20                 0   100.00%         188                 4    97.87%           0                 0         -
kinematics/src/lib.rs                     229                11    95.20%          19                 2    89.47%         115                 7    93.91%           0                 0         -
kinematics/src/math.rs                    171                 0   100.00%          16                 0   100.00%          79                 0   100.00%           0                 0         -
kinematics/src/mjcf.rs                    225                32    85.78%          17                 1    94.12%         132                15    88.64%           0                 0         -
kinematics/src/tof.rs                     338                20    94.08%          14                 1    92.86%         184                13    92.93%           0                 0         -
mediad/src/config.rs                       90                 5    94.44%           7                 1    85.71%          46                 4    91.30%           0                 0         -
mediad/src/detect.rs                      293               222    24.23%          13                 9    30.77%         200               145    27.50%           0                 0         -
mediad/src/exposure.rs                    412               161    60.92%          28                 8    71.43%         279               110    60.57%           0                 0         -
mediad/src/main.rs                        245               245     0.00%           7                 7     0.00%         158               158     0.00%           0                 0         -
mediad/src/pipeline.rs                    977               909     6.96%          62                56     9.68%         624               578     7.37%           0                 0         -
mediad/src/producer.rs                    161                33    79.50%          20                 5    75.00%         109                20    81.65%           0                 0         -
mediad/src/route.rs                       114                13    88.60%           8                 0   100.00%          85                 6    92.94%           0                 0         -
mediad/src/session.rs                     493                12    97.57%          30                 0   100.00%         290                 8    97.24%           0                 0         -
mediad/src/upstream.rs                    123                23    81.30%          10                 1    90.00%          82                17    79.27%           0                 0         -
mediad/src/web.rs                         112                26    76.79%          14                 4    71.43%          76                17    77.63%           0                 0         -
odometry/src/lib.rs                       321                 5    98.44%          22                 1    95.45%         192                 7    96.35%           0                 0         -
padd/src/main.rs                          446               446     0.00%           9                 9     0.00%         315               315     0.00%           0                 0         -
padd/src/tap.rs                           693               455    34.34%          42                25    40.48%         419               267    36.28%           0                 0         -
pet-detect/src/bin/detect.rs               61                61     0.00%           1                 1     0.00%          38                38     0.00%           0                 0         -
pet-detect/src/bin/features.rs             46                46     0.00%           2                 2     0.00%          20                20     0.00%           0                 0         -
pet-detect/src/lib.rs                     358               180    49.72%          27                13    51.85%         217               115    47.00%           0                 0         -
pet-detect/src/worker.rs                  293               293     0.00%          17                17     0.00%         223               223     0.00%           0                 0         -
robotctl/src/configure.rs                1720               345    79.94%          89                14    84.27%         849               216    74.56%           0                 0         -
robotctl/src/duck.rs                     1211               144    88.11%          63                 1    98.41%         604                47    92.22%           0                 0         -
robotctl/src/main.rs                     2996              1511    49.57%         176                84    52.27%        2165              1080    50.12%           0                 0         -
robotctl/src/monitor.rs                  4038               735    81.80%         213                35    83.57%        2529               468    81.49%           0                 0         -
robotctl/src/path_map.rs                  425                59    86.12%          24                 2    91.67%         223                36    83.86%           0                 0         -
robotd-params/src/lib.rs                  767                56    92.70%          64                 5    92.19%         586                39    93.34%           0                 0         -
robotd-params/src/registry.rs             178                10    94.38%          13                 2    84.62%         132                17    87.12%           0                 0         -
robotd/src/chorale.rs                    1729                36    97.92%          87                 4    95.40%        1028                24    97.67%           0                 0         -
robotd/src/control.rs                     297               260    12.46%          17                12    29.41%         257               210    18.29%           0                 0         -
robotd/src/intents.rs                     379                60    84.17%          38                 6    84.21%         276                39    85.87%           0                 0         -
robotd/src/main.rs                       4293              1371    68.06%         185                44    76.22%        2678               913    65.91%           0                 0         -
robotd/src/soc.rs                          47                25    46.81%           4                 1    75.00%          30                15    50.00%           0                 0         -
robotd/src/sound.rs                       968               688    28.93%          50                33    34.00%         565               416    26.37%           0                 0         -
robotd/src/theremin.rs                    472                71    84.96%          32                 6    81.25%         271                38    85.98%           0                 0         -
sounds/src/chorale/beat.rs                403                16    96.03%          26                 1    96.15%         246                12    95.12%           0                 0         -
sounds/src/chorale/midi.rs               1047                80    92.36%          44                 2    95.45%         581                43    92.60%           0                 0         -
sounds/src/chorale/mod.rs                1423                57    95.99%          83                 3    96.39%         812                41    94.95%           0                 0         -
sounds/src/chorale/text.rs                700                60    91.43%          41                12    70.73%         376                17    95.48%           0                 0         -
sounds/src/lib.rs                         162                30    81.48%          14                 6    57.14%          84                18    78.57%           0                 0         -
sounds/src/main.rs                        463               463     0.00%          20                20     0.00%         240               240     0.00%           0                 0         -
sounds/src/personality.rs                 174                 0   100.00%           6                 0   100.00%          84                 0   100.00%           0                 0         -
sounds/src/rng.rs                         173                 0   100.00%          18                 0   100.00%          96                 0   100.00%           0                 0         -
sounds/src/stream.rs                      719                 7    99.03%          46                 1    97.83%         420                 6    98.57%           0                 0         -
sounds/src/synth.rs                       353                 7    98.02%          29                 0   100.00%         197                 3    98.48%           0                 0         -
sounds/src/voices.rs                      679                 2    99.71%          26                 0   100.00%         353                 2    99.43%           0                 0         -
test-support/src/lib.rs                   272                 2    99.26%          22                 0   100.00%         167                 0   100.00%           0                 0         -
tof/src/lib.rs                             88                 0   100.00%           9                 0   100.00%          54                 0   100.00%           0                 0         -
tof/src/main.rs                           478               438     8.37%          23                18    21.74%         303               281     7.26%           0                 0         -
tof/src/sensor.rs                         230               148    35.65%          22                15    31.82%         163               114    30.06%           0                 0         -
tof/src/status.rs                          76                 2    97.37%           7                 1    85.71%          58                 1    98.28%           0                 0         -
updater/src/config.rs                     428                24    94.39%          37                 4    89.19%         349                17    95.13%           0                 0         -
updater/src/engine.rs                    2692               359    86.66%         184                20    89.13%        1729               208    87.97%           0                 0         -
updater/src/faults.rs                      69                 7    89.86%           7                 0   100.00%          51                 0   100.00%           0                 0         -
updater/src/fsutil.rs                     104                30    71.15%          10                 6    40.00%          51                24    52.94%           0                 0         -
updater/src/hooks.rs                      454                15    96.70%          37                 2    94.59%         382                12    96.86%           0                 0         -
updater/src/ipc.rs                        761               220    71.09%          60                16    73.33%         493               126    74.44%           0                 0         -
updater/src/journal.rs                    831                78    90.61%          57                10    82.46%         482                53    89.00%           0                 0         -
updater/src/lib.rs                         42                12    71.43%           4                 0   100.00%          32                12    62.50%           0                 0         -
updater/src/main.rs                       566               240    57.60%          37                13    64.86%         416               154    62.98%           0                 0         -
updater/src/manifest.rs                   159                 6    96.23%          16                 0   100.00%         110                 1    99.09%           0                 0         -
updater/src/orphan.rs                     288                 6    97.92%          25                 0   100.00%         181                 3    98.34%           0                 0         -
updater/src/preflight.rs                  380                14    96.32%          46                 3    93.48%         282                 9    96.81%           0                 0         -
updater/src/reconcile.rs                  292                15    94.86%          25                 3    88.00%         172                 5    97.09%           0                 0         -
updater/src/robot.rs                      212                20    90.57%          31                 4    87.10%         128                10    92.19%           0                 0         -
updater/src/source/github.rs              474               169    64.35%          51                26    49.02%         304                99    67.43%           0                 0         -
updater/src/source/hf_hub.rs              136                72    47.06%          20                12    40.00%          81                41    49.38%           0                 0         -
updater/src/source/http.rs                319                82    74.29%          29                11    62.07%         260                88    66.15%           0                 0         -
updater/src/source/local.rs               346                37    89.31%          36                 9    75.00%         192                26    86.46%           0                 0         -
updater/src/source/mod.rs                  39                30    23.08%           4                 2    50.00%          30                24    20.00%           0                 0         -
updater/src/spawn.rs                       94                13    86.17%           5                 0   100.00%          49                 4    91.84%           0                 0         -
updater/src/store.rs                      593                41    93.09%          43                 7    83.72%         271                42    84.50%           0                 0         -
updater/src/verify.rs                     786                95    87.91%          55                18    67.27%         424                75    82.31%           0                 0         -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                   56470             15936    71.78%        3755              1056    71.88%       35239             10364    70.59%           0                 0         -

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