diff options
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 411 |
1 files changed, 201 insertions, 210 deletions
@@ -150,29 +150,6 @@ Filed as a VERIFY because the capture asks for a conversation rather than describing a defect. What is the clock avoiding being dragged by, and is the avoidance the bug or the intended behaviour? -** CANCELLED [#B] agent-text relay reports success for a message that went nowhere :bug: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:CREATED: [2026-08-19 Wed] -:LAST_REVIEWED: 2026-08-19 -:END: - -Not a defect. rulesets refuted it with measurements and I reproduced theirs -before accepting: on velox, whose account store is empty, -=signal-cli -a +15550000000 send= exits 1 with "User +15550000000 is not -registered", and =ssh 100.71.182.1 'exit 7'= returns 7, so a non-zero code -propagates faithfully back through the relay. The loop's -=[ "$rc" -eq 0 ] && break= therefore advances to the next host exactly as -intended. signal-cli fails closed. - -I filed this off a conditional in their handoff — ".emacs.d raised a case -neither of you tested ... *if* signal-cli send exits zero against an empty -account store" — and turned the "if" into a graded [#B] with a =:blocked:= tag -on another project, without running the one command that settles it. The -machine that proves it was in front of me the whole time. Their ask is fair and -I am recording it rather than the outcome alone: verify before filing a defect -against someone else's work, especially one carrying a blocking tag. - ** TODO [#C] A failed hostname lookup takes seven seconds :bug: :PROPERTIES: :CREATED: [2026-08-19 Wed] @@ -201,154 +178,6 @@ Grading: Minor severity (nothing behaves wrong, it just waits) x some users sometimes (every failed lookup, which is occasional rather than constant) = P3 = [#C]. -** DONE [#B] Clock/DNS bootstrap deadlock — recovery needs a second device :bug:velox: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:CREATED: [2026-08-19 Wed] -:LAST_REVIEWED: 2026-08-19 -:END: - -The installer wrote both halves of a deadlock. =configure_dns= pins -=DNSOverTLS=yes= with =DNSSEC=yes=, and both validate against the wall clock; -the chrony step enables chronyd without writing a config, so the machine runs -Arch's stock one whose only source is =pool 2.arch.pool.ntp.org= — a hostname. -Boot with a wrong clock and DoT certificate validation fails, so nothing -resolves; chrony then cannot resolve its pool, so the clock stays wrong. -Neither side moves. It caught velox on the road 2026-08-19 and had to be -diagnosed from a phone. - -Fixed at the root: the installer now writes -=/etc/chrony.d/10-bootstrap-ip-ntp.conf= with two IP-addressed Cloudflare -sources and points stock chrony.conf at the drop-in. An address needs no DNS -and carries no certificate, so the escape hatch holds whatever broke the clock. -velox has the same drop-in applied live, verified with =chronyc -n sources= -(=162.159.200.1= selected) and =timedatectl= reporting synchronized. - -What is left here is the part I could not verify: the decisive test is a full -power-down and cold boot, confirming the clock corrects itself untouched. See -the manual-testing entry. Until that runs, the fix is sound by construction -rather than demonstrated. - -Grading: Critical severity (total loss of network — no DNS means no egress, and -recovery needs a second device) x some users sometimes (only machines that boot -with a wrong clock, which is any RTC fault, BIOS reset, or drained cell) = P2 = -[#B]. Graded on the being-in-it, not the getting-into-it: once the machine is in -this state it is fully offline with no local path out. - -*** 2026-08-19 Wed @ 12:25:00 -0700 Reproduced it, and the mechanism was not what either of us said -I wound velox's clock back 27 days with chronyd stopped and watched it fail. -Resolution died outright, and plain UDP/53 to 1.1.1.1 kept answering throughout -— the discriminator the doctor keys on, confirmed live rather than reasoned. - -The cause is DNSSEC, not DNS-over-TLS. resolved logged =signature-expired= -against the root DNSKEY and every DS beneath it. The DoT handshake to -=1.1.1.1:853= verified clean at that same clock, and the Cloudflare certificate -runs Dec 2025 to Dec 2026, so it was never outside its window. An RRSIG window -is days to weeks and a certificate is good for a year, so a skew that breaks -DNSSEC normally leaves DoT untouched. The phone session blamed the certificate -and I carried that forward into the first commit; both were wrong. - -=DNSSEC=allow-downgrade= does not rescue it either, which matters because it is -the obvious reach and it is what ratio runs. resolved downgrades when a server -lacks DNSSEC support, and a signature-window failure is a validation failure, so -no downgrade fires. Six retries over eighteen seconds plus -=resolvectl reset-server-features=, all dead. I briefly believed otherwise off a -test whose success was a cache hit (=Data from: cache network=). - -So ratio was exposed after all, and I have given it the same drop-in. Its -=162.159.200.1= is selected and its clock is synchronized. - -The fix itself is verified end to end: with the clock wound back and no DNS at -all, chronyd reached the IP-addressed source and stepped the clock from -2026-07-23 straight back to 2026-08-19. That is the whole claim, demonstrated -rather than argued. - -Also settled: the clock landed on 2026-07-23 because that is systemd 261.2's -build date to the minute (=/usr/lib/systemd/systemd=, 10:43:59), and systemd -advances a garbage RTC to its own build epoch at boot. Not timesyncd's -last-good-sync timestamp, which cannot be it — timesyncd is disabled here. That -also confirms the RTC really was reading earlier than that, so the coin cell -stays the prime suspect. - -*** 2026-08-19 Wed @ 10:12:00 -0700 Root fix, doctor verdict, and taxonomy entry landed -The installer carries the drop-in; =post-rebuild-check= grew a sixth check that -fails a machine whose every NTP source is a hostname; the net failure taxonomy -gained the mode in its DNS layer plus a cluster 5 triage line, and its existing -egress-layer clock entry now says outright that its remedy does not apply when -DoT or DNSSEC is on. - -The doctor half is in dotfiles: =classify.py= reached "DNS not resolving → net -repair dns-test" here, which cannot help, because every public resolver fails -the same clock-sensitive validation — so the doctor sent you round a loop. It -now emits a =clock-dns= row ahead of the generic DNS verdict. Detection is -deliberately DNS-free: a local =timedatectl= read for sync state, and a bypass -query addressed by IP over plain UDP/53 to tell "resolved is refusing to -validate" apart from "DNS is genuinely dead". - -** DONE [#C] DNSSEC strictness on the travelling laptop :velox: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:CREATED: [2026-08-19 Wed] -:LAST_REVIEWED: 2026-08-19 -:END: - -Craig chose =allow-downgrade= everywhere. Applied to velox, ratio, and the -installer, and ratio's =DNSOverTLS= tightened from =opportunistic= to =yes= in -the same pass, so all three now agree: encrypted DNS always, validation -best-effort. - -The reasoning that settled it: the deadlock is fixed by the IP-addressed NTP -source, and =allow-downgrade= was measured not to help with it at all. What -=allow-downgrade= does buy is the venue-resolver case the taxonomy documents, -where =yes= turns a resolver that mangles DNSSEC records into no answer at all. -That is a hotel and airport problem, so it is velox's problem, and the -encryption is the half worth being strict about. - -** CANCELLED [#C] Branch network policy on laptop vs desktop in the installer :feature: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:CREATED: [2026-08-19 Wed] -:LAST_REVIEWED: 2026-08-19 -:END: - -Cancelled because the decision above emptied it. All three motivating cases now -want the same value on every machine: =DNSSEC=allow-downgrade=, a stable -per-network wifi MAC, and an IP-addressed NTP source. A branch with nothing to -put on either side is machinery built for a divergence that does not exist, and -it would be the kind of scaffolding that rots unread. - -Worth keeping the observation, which is the part with a shelf life: when a -network default does need to differ by machine class, the test already exists. -=ls /sys/class/power_supply/BAT*= is what =prune_waybar_battery=, the ppd mask, -and the TLP config all key on. Reopen this then rather than building it now. - -** DONE [#C] Automate the clock/DNS deadlock repair in the net doctor :feature: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:CREATED: [2026-08-19 Wed] -:LAST_REVIEWED: 2026-08-19 -:END: - -Shipped as the =clock-ip-ntp= repair, and the verdict is =fixable= rather than -terminal. Both open questions got answered by driving a real deadlock instead of -reasoning about it: =chronyc add server= returns =200 OK= against a running -chronyd, and =makestep= needs a sample to land, so it took four calls and about -eight seconds rather than working on the first. The repair retries accordingly. - -Verified end to end on velox against a genuine deadlock (wrong clock, chronyd -running with only an unresolvable hostname source, DNS dead): the repair -corrected the clock in 6.1 seconds and DNS came back. - -The live run also caught a defect no unit test would have. The doctor reported -"Saved password for SpectrumSetup-3C was rejected" — because -=_recent_auth_failure= greps =journalctl --since -5min=, and a clock weeks off -windows onto a different incident's entries. It would have sent Craig to -re-enter a password that was never wrong. Fixed twice over: the journal half is -now skipped when the clock is untrustworthy, and the clock verdict is ordered -above the auth verdict, since everything below it reasons over timestamps that -only mean something once the clock is right. Airplane mode and hard rfkill stay -above, being physical states the clock has no bearing on. - ** TODO [#A] Reseat velox input-cover ribbon — phantom power button :bug:velox:hardware: DEADLINE: <2026-08-14 Fri> :PROPERTIES: @@ -1139,42 +968,6 @@ Handoff from home (2026-07-25), originally combining the 2026-06-07 stale-compos 2. On =Upgrade= of =fontconfig=, =freetype2=, or =harfbuzz=, run =/usr/bin/fc-cache -f= after the transaction. The fontconfig 2.17→2.18 cache-format change left stale cache-9 files that crashed Qt6 apps in =FcCharSetHasChar= until the system font cache was rebuilt. Acceptance: hook files are source-controlled and installed by archsetup; package/operation/action fields are asserted from the generated hook text; the reminder is print-only and exits successfully; the font hook runs only after successful matching upgrades and invokes the absolute =fc-cache= path. Validate with the fast installer tests plus a disposable pacman-hook parser/install check when practical. -** DONE [#D] net-scenarios harness times out under back-to-back suite runs :test:tooling: -CLOSED: [2026-08-19 Wed] -:PROPERTIES: -:LAST_REVIEWED: 2026-07-24 -:END: -=tests/net-scenarios/test_run_net_scenarios.py= errored on all 5 tests twice during round 12, each time =subprocess.TimeoutExpired= after its 20s budget on =scripts/testing/run-net-scenarios.sh --target root@fake-vm=. Both occurrences were in =make test-unit= runs launched immediately after a previous full run. It then passed 6 runs in a row (3 on a pristine tree, 3 with the round-12 change), and standalone it finishes in 0.09s, so this is not a regression from any code change. - -The harness stubs =ssh=, =rsync= and =jq= onto =PATH=, so nothing should touch the network at all — which is what makes a 20s timeout suspicious rather than merely slow. Worth reproducing under load before deciding whether the fix is a larger timeout or a real hang in the script. Evidence logs from the round: =/tmp/tu.log= and =/tmp/tu2.log= (tmpfs, gone after reboot). - -Not graded on the bug matrix: it is test infrastructure, not the shipped codebase. - -*** 2026-08-08 Sat @ 05:05:00 -0500 Recurred under concurrent load, same signature -All 5 tests hit the 20s TimeoutExpired again during a =make test-unit= run -that overlapped two review subagents running their own suites on the box. -Standalone immediately after: 0.095s, all pass; the following quiet-machine -full run was clean. Confirms the load-sensitivity read — reproduce under -deliberate load before choosing between a bigger budget and a real hang. - - -*** 2026-08-19 Wed @ 14:50:00 -0700 Root-caused and fixed: inherited stdin, not load -Not load, and not the network. The harness stubs ssh as =cat >/dev/null=, which -drains stdin to EOF. With no explicit stdin the stub inherits whatever the test -runner had, so it returned instantly when stdin was redirected and blocked -forever when it was a terminal or a live pipe. All five tests then burned their -20-second budget. - -That is why it looked like a load effect: a run launched immediately after -another inherited a different stdin than a standalone invocation. A/B measured -today — =make test-unit </dev/null= exits 0, the same target with an open pipe -on stdin hangs on all five. The note above guessed at "a larger timeout or a -real hang in the script" and it was neither. - -Fixed by pinning =stdin=subprocess.DEVNULL= in =run_script=. Verified both ways: -the previously-failing open-pipe case and the redirected case both pass in -0.08s, and a full =make test-unit= under a live pipe is clean across 50 suites. - ** VERIFY Should coredump entries group as one journal-digest row per binary? :maint: :PROPERTIES: :LAST_REVIEWED: 2026-07-24 @@ -3069,9 +2862,6 @@ The maintenance console's coredump metric flagged telega-server on ratio (8 core * Archsetup Resolved -** DONE [#B] Absorb the clock-panel project into the dotfiles :feature:waybar:dotfiles: -CLOSED: [2026-07-18 Sat] -Absorbed into =~/.dotfiles= (commit 3fab11d): package =clock/src/clock/= (renamed from clock_panel), the six PNG watchface layers packaged inside the module at =clock/src/clock/assets/=, a stowed =clock-panel= shell shim (LD_PRELOADs gtk4-layer-shell), waybar left-click now =clock-panel toggle= with the absolute path dropped, tests converted pytest→unittest into =tests/clock/= plus an asset-load guard. Kept the layer-shell overlay and the socket toggle. The standalone repo is archived (ARCHIVED.md), kept for its design history. Verified live: the bar click renders the polished watchface. ** DONE [#A] Velox boot recovery — no kernel in BE :bug:velox:zfs: CLOSED: [2026-07-19 Sun] Recovered. Velox boots linux-lts 6.18.38 and is back on the tailnet (up 1d+, /boot holds initramfs-linux-lts.img). The pre-pacman ZFS snapshot rollback restored the kernel from the ZBM recovery shell. @@ -4431,3 +4221,204 @@ CLOSED: [2026-08-08 Sat] Killed at the 2026-08-08 task review: an undated annual intention that never fired — pain points get surfaced organically as they bite. Once-yearly systematic inventory of known deficiencies and friction points in current toolset +** CANCELLED [#B] agent-text relay reports success for a message that went nowhere :bug: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:CREATED: [2026-08-19 Wed] +:LAST_REVIEWED: 2026-08-19 +:END: + +Not a defect. rulesets refuted it with measurements and I reproduced theirs +before accepting: on velox, whose account store is empty, +=signal-cli -a +15550000000 send= exits 1 with "User +15550000000 is not +registered", and =ssh 100.71.182.1 'exit 7'= returns 7, so a non-zero code +propagates faithfully back through the relay. The loop's +=[ "$rc" -eq 0 ] && break= therefore advances to the next host exactly as +intended. signal-cli fails closed. + +I filed this off a conditional in their handoff — ".emacs.d raised a case +neither of you tested ... *if* signal-cli send exits zero against an empty +account store" — and turned the "if" into a graded [#B] with a =:blocked:= tag +on another project, without running the one command that settles it. The +machine that proves it was in front of me the whole time. Their ask is fair and +I am recording it rather than the outcome alone: verify before filing a defect +against someone else's work, especially one carrying a blocking tag. +** DONE [#B] Clock/DNS bootstrap deadlock — recovery needs a second device :bug:velox: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:CREATED: [2026-08-19 Wed] +:LAST_REVIEWED: 2026-08-19 +:END: + +The installer wrote both halves of a deadlock. =configure_dns= pins +=DNSOverTLS=yes= with =DNSSEC=yes=, and both validate against the wall clock; +the chrony step enables chronyd without writing a config, so the machine runs +Arch's stock one whose only source is =pool 2.arch.pool.ntp.org= — a hostname. +Boot with a wrong clock and DoT certificate validation fails, so nothing +resolves; chrony then cannot resolve its pool, so the clock stays wrong. +Neither side moves. It caught velox on the road 2026-08-19 and had to be +diagnosed from a phone. + +Fixed at the root: the installer now writes +=/etc/chrony.d/10-bootstrap-ip-ntp.conf= with two IP-addressed Cloudflare +sources and points stock chrony.conf at the drop-in. An address needs no DNS +and carries no certificate, so the escape hatch holds whatever broke the clock. +velox has the same drop-in applied live, verified with =chronyc -n sources= +(=162.159.200.1= selected) and =timedatectl= reporting synchronized. + +What is left here is the part I could not verify: the decisive test is a full +power-down and cold boot, confirming the clock corrects itself untouched. See +the manual-testing entry. Until that runs, the fix is sound by construction +rather than demonstrated. + +Grading: Critical severity (total loss of network — no DNS means no egress, and +recovery needs a second device) x some users sometimes (only machines that boot +with a wrong clock, which is any RTC fault, BIOS reset, or drained cell) = P2 = +[#B]. Graded on the being-in-it, not the getting-into-it: once the machine is in +this state it is fully offline with no local path out. + +*** 2026-08-19 Wed @ 12:25:00 -0700 Reproduced it, and the mechanism was not what either of us said +I wound velox's clock back 27 days with chronyd stopped and watched it fail. +Resolution died outright, and plain UDP/53 to 1.1.1.1 kept answering throughout +— the discriminator the doctor keys on, confirmed live rather than reasoned. + +The cause is DNSSEC, not DNS-over-TLS. resolved logged =signature-expired= +against the root DNSKEY and every DS beneath it. The DoT handshake to +=1.1.1.1:853= verified clean at that same clock, and the Cloudflare certificate +runs Dec 2025 to Dec 2026, so it was never outside its window. An RRSIG window +is days to weeks and a certificate is good for a year, so a skew that breaks +DNSSEC normally leaves DoT untouched. The phone session blamed the certificate +and I carried that forward into the first commit; both were wrong. + +=DNSSEC=allow-downgrade= does not rescue it either, which matters because it is +the obvious reach and it is what ratio runs. resolved downgrades when a server +lacks DNSSEC support, and a signature-window failure is a validation failure, so +no downgrade fires. Six retries over eighteen seconds plus +=resolvectl reset-server-features=, all dead. I briefly believed otherwise off a +test whose success was a cache hit (=Data from: cache network=). + +So ratio was exposed after all, and I have given it the same drop-in. Its +=162.159.200.1= is selected and its clock is synchronized. + +The fix itself is verified end to end: with the clock wound back and no DNS at +all, chronyd reached the IP-addressed source and stepped the clock from +2026-07-23 straight back to 2026-08-19. That is the whole claim, demonstrated +rather than argued. + +Also settled: the clock landed on 2026-07-23 because that is systemd 261.2's +build date to the minute (=/usr/lib/systemd/systemd=, 10:43:59), and systemd +advances a garbage RTC to its own build epoch at boot. Not timesyncd's +last-good-sync timestamp, which cannot be it — timesyncd is disabled here. That +also confirms the RTC really was reading earlier than that, so the coin cell +stays the prime suspect. + +*** 2026-08-19 Wed @ 10:12:00 -0700 Root fix, doctor verdict, and taxonomy entry landed +The installer carries the drop-in; =post-rebuild-check= grew a sixth check that +fails a machine whose every NTP source is a hostname; the net failure taxonomy +gained the mode in its DNS layer plus a cluster 5 triage line, and its existing +egress-layer clock entry now says outright that its remedy does not apply when +DoT or DNSSEC is on. + +The doctor half is in dotfiles: =classify.py= reached "DNS not resolving → net +repair dns-test" here, which cannot help, because every public resolver fails +the same clock-sensitive validation — so the doctor sent you round a loop. It +now emits a =clock-dns= row ahead of the generic DNS verdict. Detection is +deliberately DNS-free: a local =timedatectl= read for sync state, and a bypass +query addressed by IP over plain UDP/53 to tell "resolved is refusing to +validate" apart from "DNS is genuinely dead". +** DONE [#C] DNSSEC strictness on the travelling laptop :velox: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:CREATED: [2026-08-19 Wed] +:LAST_REVIEWED: 2026-08-19 +:END: + +Craig chose =allow-downgrade= everywhere. Applied to velox, ratio, and the +installer, and ratio's =DNSOverTLS= tightened from =opportunistic= to =yes= in +the same pass, so all three now agree: encrypted DNS always, validation +best-effort. + +The reasoning that settled it: the deadlock is fixed by the IP-addressed NTP +source, and =allow-downgrade= was measured not to help with it at all. What +=allow-downgrade= does buy is the venue-resolver case the taxonomy documents, +where =yes= turns a resolver that mangles DNSSEC records into no answer at all. +That is a hotel and airport problem, so it is velox's problem, and the +encryption is the half worth being strict about. +** CANCELLED [#C] Branch network policy on laptop vs desktop in the installer :feature: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:CREATED: [2026-08-19 Wed] +:LAST_REVIEWED: 2026-08-19 +:END: + +Cancelled because the decision above emptied it. All three motivating cases now +want the same value on every machine: =DNSSEC=allow-downgrade=, a stable +per-network wifi MAC, and an IP-addressed NTP source. A branch with nothing to +put on either side is machinery built for a divergence that does not exist, and +it would be the kind of scaffolding that rots unread. + +Worth keeping the observation, which is the part with a shelf life: when a +network default does need to differ by machine class, the test already exists. +=ls /sys/class/power_supply/BAT*= is what =prune_waybar_battery=, the ppd mask, +and the TLP config all key on. Reopen this then rather than building it now. +** DONE [#C] Automate the clock/DNS deadlock repair in the net doctor :feature: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:CREATED: [2026-08-19 Wed] +:LAST_REVIEWED: 2026-08-19 +:END: + +Shipped as the =clock-ip-ntp= repair, and the verdict is =fixable= rather than +terminal. Both open questions got answered by driving a real deadlock instead of +reasoning about it: =chronyc add server= returns =200 OK= against a running +chronyd, and =makestep= needs a sample to land, so it took four calls and about +eight seconds rather than working on the first. The repair retries accordingly. + +Verified end to end on velox against a genuine deadlock (wrong clock, chronyd +running with only an unresolvable hostname source, DNS dead): the repair +corrected the clock in 6.1 seconds and DNS came back. + +The live run also caught a defect no unit test would have. The doctor reported +"Saved password for SpectrumSetup-3C was rejected" — because +=_recent_auth_failure= greps =journalctl --since -5min=, and a clock weeks off +windows onto a different incident's entries. It would have sent Craig to +re-enter a password that was never wrong. Fixed twice over: the journal half is +now skipped when the clock is untrustworthy, and the clock verdict is ordered +above the auth verdict, since everything below it reasons over timestamps that +only mean something once the clock is right. Airplane mode and hard rfkill stay +above, being physical states the clock has no bearing on. +** DONE [#D] net-scenarios harness times out under back-to-back suite runs :test:tooling: +CLOSED: [2026-08-19 Wed] +:PROPERTIES: +:LAST_REVIEWED: 2026-07-24 +:END: +=tests/net-scenarios/test_run_net_scenarios.py= errored on all 5 tests twice during round 12, each time =subprocess.TimeoutExpired= after its 20s budget on =scripts/testing/run-net-scenarios.sh --target root@fake-vm=. Both occurrences were in =make test-unit= runs launched immediately after a previous full run. It then passed 6 runs in a row (3 on a pristine tree, 3 with the round-12 change), and standalone it finishes in 0.09s, so this is not a regression from any code change. + +The harness stubs =ssh=, =rsync= and =jq= onto =PATH=, so nothing should touch the network at all — which is what makes a 20s timeout suspicious rather than merely slow. Worth reproducing under load before deciding whether the fix is a larger timeout or a real hang in the script. Evidence logs from the round: =/tmp/tu.log= and =/tmp/tu2.log= (tmpfs, gone after reboot). + +Not graded on the bug matrix: it is test infrastructure, not the shipped codebase. + +*** 2026-08-08 Sat @ 05:05:00 -0500 Recurred under concurrent load, same signature +All 5 tests hit the 20s TimeoutExpired again during a =make test-unit= run +that overlapped two review subagents running their own suites on the box. +Standalone immediately after: 0.095s, all pass; the following quiet-machine +full run was clean. Confirms the load-sensitivity read — reproduce under +deliberate load before choosing between a bigger budget and a real hang. + + +*** 2026-08-19 Wed @ 14:50:00 -0700 Root-caused and fixed: inherited stdin, not load +Not load, and not the network. The harness stubs ssh as =cat >/dev/null=, which +drains stdin to EOF. With no explicit stdin the stub inherits whatever the test +runner had, so it returned instantly when stdin was redirected and blocked +forever when it was a terminal or a live pipe. All five tests then burned their +20-second budget. + +That is why it looked like a load effect: a run launched immediately after +another inherited a different stdin than a standalone invocation. A/B measured +today — =make test-unit </dev/null= exits 0, the same target with an open pipe +on stdin hangs on all five. The note above guessed at "a larger timeout or a +real hang in the script" and it was neither. + +Fixed by pinning =stdin=subprocess.DEVNULL= in =run_script=. Verified both ways: +the previously-failing open-pipe case and the redirected case both pass in +0.08s, and a full =make test-unit= under a live pipe is clean across 50 suites. |
