diff --git a/backlog.md b/backlog.md index 192509e..80bae74 100644 --- a/backlog.md +++ b/backlog.md @@ -110,13 +110,65 @@ einer klar darunter. Vier Punkte sagen: der Normalfall ist ein Abstand um 16 s, und der Ausreißer bei 26,6 s ist der, der das Fenster zumacht. Die Deckung bleibt ein Rest, kein Versprechen — #453 unverändert offen. -### Offen +### Nachtrag `a60f44c` — die erhöhte Reißleine hat sich in achteinhalb Minuten bezahlt + +Der Merge dieses Eintrags lief in eine `e2e` von **38:30** — grün, und damit +wieder ein neues Maximum. Die von mir veröffentlichte Obergrenze war heute +Nacht **zweimal** zu klein: 17:38, überholt von 34:57, überholt von 38:30. + +**Das ist der Beleg für die Reißleine, und er ist knapp.** Der Zeuge lief um +01:19:26 an, mit `WITNESS_MAX_SEC=2700`: -- **Dependabot ist leer.** Die nächste Einheit kommt aus Rangfolge (b), der - nächsten Phase ab Stufe I. -- **#453** offen, vier Datenpunkte. -- **#304** hat aus dieser Nacht **keine** neue Evidenz: vier bezeugte Tausche, - alle sauber. +| | | +|---|---| +| Zeugenstart | 01:19:26Z | +| alte Reißleine (1 800 s) wäre ausgelaufen | **01:49:26Z** | +| `deploy` | 01:57:53Z → 01:58:15Z | +| Zeugenende | 01:58:45Z, nach **2 359 s** | + +**Achteinhalb Minuten** zwischen der alten Grenze und dem Tausch. Mit 1 800 s +wäre diese Messung verloren gewesen — derselbe Ausgang wie bei #439, nur aus +einem anderen Grund: dort lag die Runner-Warteschlange davor, hier ist die +`e2e` selbst länger als die Reißleine. + +**Die Lehre ist nicht die Spanne, sondern das Misstrauen gegen sie.** Eine aus +Stichproben geschätzte Obergrenze ist in einer einzigen Nacht zweimal überholt +worden. +Richtig ist: **sofort bei `in_progress` starten** und die Reißleine **großzügig** +setzen, weil ein zu früher Start nichts kostet und ein zu kurzes Fenster die +ganze Messung. + +| Tausch | `main` | `ops.lastDeploy.at` | `startedAt` (10 × gezählt) | Versatz | Zeuge je Pfad | +|---|---|---|---|---|---| +| — | `a60f44c` | 01:58:13Z | 01:58:28,779Z | **+15,8 s** | **2 359 × 200** | + +Null Nicht-200, 9 s ohne Stichprobe. `v0.47.2-15-ga60f44c`, p95 **67,8 ms**. +Die Identität wurde zehnmal gelesen und war zehnmal gleich — nach dem Fund von +oben wird hier nicht mehr einmal gelesen. + +**#453, fünfter Datenpunkt:** Abstand Zwilling → endgültiger Prozess 13,8 s, +Deckung danach **16,2 s**. Damit deckt dieses Fenster die bekannten +#304-Abstände (+12 s, +12,9 s) ab. Vier von fünf tun das; der Ausreißer bleibt +`3b990e5` mit 3,4 s. + +### Offen — und warum die Schleife hier hält + +- **I1 · Boot-Sequenz** ist die nächste Einheit und **geplant**, aber nicht + begonnen. Sie hängt an drei Entscheidungen, die mir nicht gehören: + **(1)** sechs neue `--d-boot-*`-Tokens in `tokens.css` — die Offsets + (80/340/640/1040/1200/2400) dürfen nicht als `animation-delay` hart im CSS + stehen, `tools/check-tokens.sh:80` fängt das, und seine Meldung nennt die + neun bestehenden Dauern. `--d-decode: 540ms` **existiert** und ist genau die + Decode-Dauer des Blattes. + **(2)** Lenis und GSAP ScrollTrigger für **I2** — zwei neue Abhängigkeiten + gegen #237 (143 KB von 150 KB), und der Plan nennt I2 ausdrücklich *ein* + Integrationsproblem. + **(3)** Die **Ambient-Ebene** steht in der Spec-Tabelle des Blattes + (1900 ms, opacity .06), der Build-Plan schiebt sie nach **I3, nach Launch**. + Zwei Quellen, ein Widerspruch. +- **#453** offen, fünf Datenpunkte. +- **#304**: fünf bezeugte Tausche in dieser Nacht, **alle sauber**, keine neue + Evidenz. --- @@ -581,12 +633,13 @@ Mal im Ruhezustand, **nie im Tausch**: | **#455** (Fenster ohne Deploy) | **1 800** | **0** | kein Tausch im Fenster | | **#455 `944a1e4`** | **339** | **0** | — | | **#450 `592da9d`** | **1 087** | **0** | — | +| **#456 `a60f44c`** | **2 359** | **0** | — | -Also **6 Ausfälle auf rund 35 440 Anfragen**, in fünf von zweiundzwanzig Läufen +Also **6 Ausfälle auf rund 37 800 Anfragen**, in fünf von dreiundzwanzig Läufen — die sieben Zeilen der Oktober-Welle vom 14./15.10. sind **alle** null. Die -längste ausfallfreie Einzelzeile bleibt #332 mit 3 558; neu ist, dass **elf** -Tausch-Läufe hintereinander keinen zeigen — die drei Fenster ohne Deploy -zählen in dieser Reihe nicht mit. +längste ausfallfreie Einzelzeile bleibt #332 mit 3 558, dicht gefolgt von +`a60f44c` mit 2 359; neu ist, dass **zwölf** Tausch-Läufe hintereinander +keinen zeigen — die drei Fenster ohne Deploy zählen in dieser Reihe nicht mit. Das Eskalationskriterium der Zählung ist unverändert nicht erfüllt: ein Issue wäre es, wenn ein Lauf **zwei** Ausfälle auf **einem** Pfad zeigt oder einer in den Tausch fällt. Hier ist es einer, auf einem Pfad, 18 Minuten vom Tausch entfernt diff --git a/tools/bundle-size.sh b/tools/bundle-size.sh index de086f7..6c12277 100755 --- a/tools/bundle-size.sh +++ b/tools/bundle-size.sh @@ -54,7 +54,24 @@ done # ---------------------------------------------------------------- the build printf ' building (this is not cached, on purpose)\n' -( cd "$web" && rm -rf .next && NEXT_TELEMETRY_DISABLED=1 npm run build >/dev/null 2>&1 ) \ + +# THE CLEAN AND THE BUILD ARE TWO COMMANDS BECAUSE THEY FAIL FOR TWO REASONS. +# `rm -rf .next && npm run build` reported the build's reason for both: `make +# dev` runs its container as root, so what it leaves in .next/dev is root-owned, +# `rm` cannot unlink it, and the run ended on "npm run build failed" for a build +# that had never started. Two hundred lines of Permission denied sat above the +# message, and the message pointed at the wrong half. #323, four times over. +if ! rm_err=$( cd "$web" && rm -rf .next 2>&1 ); then + printf ' ✗ %s\n' "could not remove $next — the build never started" + printf '%s\n' "$rm_err" | head -3 | sed 's/^/ /' + say "the dev container writes .next/dev as root. Remove it from a container" + say "of the same origin — not with sudo:" + say " docker run --rm --user 0:0 -v \"\$PWD/web/.next:/x\" \\" + say " timseil-dev-web:latest sh -c 'rm -rf /x/dev'" + exit 1 +fi + +( cd "$web" && NEXT_TELEMETRY_DISABLED=1 npm run build >/dev/null 2>&1 ) \ || die "npm run build failed — run it yourself to see why" # `/` never has a document of its own: proxy.ts rewrites it onto `/en`, because diff --git a/tools/selftest.sh b/tools/selftest.sh index 71fff8b..0b8f35f 100755 --- a/tools/selftest.sh +++ b/tools/selftest.sh @@ -77,7 +77,8 @@ cp "$root/tools/check-repo.sh" "$root/tools/check-todo.sh" "$root/tools/check-no "$root/tools/prune-registry.sh" "$root/tools/witness.sh" \ "$root/tools/rollout.sh" "$root/tools/release.sh" \ "$root/tools/check-rollout.sh" "$root/tools/check-tokens.sh" \ - "$root/tools/check-vuln.sh" "$root/tools/check-pr-title.sh" "$tmp/tools/" + "$root/tools/check-vuln.sh" "$root/tools/check-pr-title.sh" \ + "$root/tools/bundle-size.sh" "$tmp/tools/" cp "$root/.cosign-image" "$tmp/" cp "$root/.githooks/pre-commit" "$root/.githooks/commit-msg" "$root/.githooks/pre-push" "$tmp/.githooks/" cp "$root/Makefile" "$tmp/" @@ -2020,6 +2021,23 @@ rm -f w.out kill "$NOOP_PID" 2>/dev/null rm -rf noop +# BUNDLE SIZE BLAMED THE BUILD FOR THE CLEAN'S FAILURE — #323, a quarter of an +# hour four times over. An unwritable directory is the refusal `rm` gives on the +# root-owned files `make dev` leaves, without needing a container to make one. +# +# SKIPPED AS ROOT: root ignores the mode bits, so the rm would succeed and the +# case would go red for a missing package.json instead. +if [ "$(id -u)" -ne 0 ]; then + mkdir -p bs/web/node_modules bs/web/.next/dev + : > bs/web/.next/dev/chunk.js + chmod 500 bs/web/.next/dev + refuses "bundle-size names the clean, not the build, when .next cannot go" \ + "the build never started" tools/bundle-size.sh bs + # `cleanup` is `rm -rf "$tmp"` and would trip over this same mode. + chmod 700 bs/web/.next/dev + rm -rf bs +fi + # THE REFUSALS, and this is the incident that bought them. On 2026-08-30 at 21:28 # the deploy of 28a2c63 was rolled back and the log said "the site is down". The # site was serving that very build, and at 21:37 it answered 200 everywhere. What