Rhizamonitor
live

Run

Web UI server

done ship-change

Steps

  1. build/builddone57m 32s

    Nov 5 22:12 · 6 of 6 leaves passed

  2. build/renderdone2s

    Nov 5 22:12 · exit 0

  3. build/checkdone7s

    Nov 5 22:13 · exit 0

  4. review/codedone11s

    Nov 5 22:13 · exit 0

  5. review/reviewdone24m 54s

    Nov 5 22:38 · 5 of 5 checks passed

  6. review/renderdone2s

    Nov 5 22:38 · exit 0

  7. render-prdone2s

    Nov 5 22:38 · exit 0

  8. open-prdone7s

    Nov 5 22:38 · exit 0

  9. wait-prdone46m 45s

    Nov 5 23:25 · held after 92 checks

  10. pr-greendone0s

    Nov 5 23:25 · exit 0

  11. signoffdone0s

    Nov 5 23:25 · approved by rule autonomous

  12. rebasefail12s

    Nov 5 23:25 · exit 1 rhiza: git push --force-with-lease=refs/heads/cs/web-ui-server:89ac6e80d9bd29aef4a1f14e2485bfdc768d43b9 origin HEAD:refs/heads/cs/web-ui-server: remote: fatal error in commit_refs To github.com:dphaener/rhiza.git ! [remote rejected] HEAD -> cs/web-ui-server (failure) error: failed to push some refs to 'github.com:dphaener/rhiza.git'

  13. rebasedone1m 16s

    Nov 5 23:26 · exit 0

  14. wait-rebaseddone15m 26s

    Nov 5 23:42 · held after 31 checks

  15. rebased-greendone0s

    Nov 5 23:42 · exit 0

  16. landdone14s

    Nov 5 23:42 · exit 0

  17. wait-landeddone25m 12s

    Nov 6 00:07 · held after 49 checks

  18. landed-greendone1s

    Nov 6 00:07 · exit 0

  19. rebase-mergedone1s

    Nov 6 00:07 · exit 0

  20. wait-rebased-mergedone1s

    Nov 6 00:07 · held after 1 checks

  21. rebased-merge-greendone1s

    Nov 6 00:07 · exit 0

  22. mergedone6s

    Nov 6 00:07 · exit 0

  23. wait-maindone1s

    Nov 6 00:07 · held after 1 checks

  24. main-greendone1s

    Nov 6 00:07 · exit 0

  25. close-outdone5s

    Nov 6 00:07 · exit 0

  26. shipdone8s

    Nov 6 00:07 · exit 0

Review

compliance passed

No findings.

quality passed

  • minor Handler never checks the Host header, so the loopback server is open to DNS rebinding: a page the owner visits can rebind its name to 127.0.0.1 and read /api/* (model, inbox, run summaries) and /events. Refusing a Host other than 127.0.0.1:<port> or localhost:<port> would close it. internal/web/web.go:79
  • minor When the port is taken, Manager.Apply fails and the daemon prints the same error to stderr on every poll, which floods the daemon log with no change in state. Reporting only on a change of error would avoid it. internal/api/daemon.go:170
  • minor common() runs gitCommonDir (a git rev-parse exec) on each call. The run, log, inbox and daemon sources each call it on every 1s tick for every open /events connection, so each open tab spawns about four git processes a second. The common dir does not change and could be resolved once. internal/api/web_events.go:25
  • nit http.Server has no ReadHeaderTimeout or ReadTimeout (go vet's G112 class). It is loopback only, but a stalled client holds a goroutine forever. internal/web/web.go:117
  • nit DiskLowInboxIDs is exported production API that exists only so the web test can name an event ID. internal/api/web_events.go:142
  • nit The app.js line in the file tree is no longer aligned with its sibling entries' comment column, and the old static/js/ path is gone without saying that app.js now sits at static/ root. internal/web/README.md:10

qa passed

  • nit Hands-on, the served layout's nav links to /runs and /roadmap, which the running daemon answers 404 (only / is a page in this change set). This is fine if later change sets add those pages, but until then every page shows two dead links. internal/web/templates/layout.html:20

scope passed

No findings.

model passed

  • minor The leaf says every non-GET method is refused, but ReadOnlyHandler (and Handler's GET patterns, which Go also matches for HEAD) answer HEAD too. HEAD is harmless and changes nothing, but the statement should say GET and HEAD, or the code should refuse HEAD, so the model matches the code. internal/api/web_api.go:22

Log

log · tail
- rebase-merge (visit 1): pass, then wait-rebased-merge: exit 0
- wait-rebased-merge (visit 1): pass, then rebased-merge-green: held after 1 checks
- rebased-merge-green (visit 1): pass, then merge: exit 0
- merge (visit 1): pass, then wait-main: exit 0
- wait-main (visit 1): pass, then main-green: held after 1 checks
- main-green (visit 1): pass, then close-out: exit 0
- close-out (visit 1): pass, then ship: exit 0
- ship (visit 1): pass, then end: exit 0

## Leaves

- web-serve-loopback (step build/build): passed: attempt 2: verifier passed
  - attempt 1 builder, session f65a0c51-271e-49a5-9462-01a1ad9129aa: pass (said done)
  - attempt 1 verifier, session 22f6fe1b-faed-4934-8ad8-01a1ad9524df: fail (verifier found 2 problem(s))
  - attempt 2 builder, session dc576494-f776-49f5-8bed-01a1ad99f20f: pass (said done)
  - attempt 2 verifier, session e101ac60-f0b6-4196-86ca-01a1ada5ab4b: pass (Evidence written by the verifier)
  - attempt 1 finding f1: TestDaemonWebListenerFollowsPort (internal/api/daemon_web_test.go:40) is racy and flaky. runDaemonTicks calls between(i) right after the daemon goroutine receives tick i, so the test sets `port` while that same poll reads it through ctx.Git. Nothing orders the write before the read. `go test -trimpath -race -count=3 ./internal/api -run TestDaemonWeb` reported 'race detected during execution of test' and failed with events [start 127.0.0.1:7787 start 127.0.0.1:8080 start 127.0.0.1:7787] wanted, [start 127.0.0.1:7787 start 127.0.0.1:7787] got: a poll saw a later value than the one meant for it, so the 8080 move was never driven. The successive-poll check of the acceptance (7787, 8080, off, 7787) is therefore not reliably exercised. Fix: set the port for poll i before sending tick i (e.g. a ticker or Git fake that synchronises the value with the poll) and guard the shared state.
  - attempt 1 finding f2: The daemon-level poll test never checks that the listener is stopped at off: webFake.closed is set but never asserted. Only starts are recorded, so the 'stops' point of the acceptance ('checks it starts, moves, stops and restarts the listener at each poll') is inferred from a later restart, not checked at the off poll. Read in internal/api/daemon_web_test.go. Assert the fake from the 8080 start is closed after the off poll, and that no listener is open then.
- web-api-read-only (step build/build): passed: attempt 1: verifier passed
  - attempt 1 builder, session da8c5550-a298-4fda-b144-01a1ad9554f7: pass (said done)
  - attempt 1 verifier, session cd471593-c0a6-4de3-bdcb-01a1ad99cc4d: pass (Evidence written by the verifier)
- web-events-stream (step build/build): passed: attempt 2: verifier passed
  - attempt 1 builder, session 99a5df12-8319-45e5-abf0-01a1ada5deb1: pass (said done)
  - attempt 1 verifier, session e7d86230-6b20-467f-a219-01a1ada9bd58: fail (verifier found 1 problem(s))
  - attempt 2 builder, session 9ac9efb5-68af-41c6-892b-01a1adb121d4: pass (said done)
  - attempt 2 verifier, session 7d5e40c8-e4a0-438c-b56f-01a1adbcab8f: pass (Evidence written by the verifier)
  - attempt 1 finding f1: Appending a log entry to an existing change set sends no change event, so the stream misses a change set that moves (propose/accept) or lands. WebEventSources' EventChange source fingerprints .rhiza/log with dirFingerprints(dirs=true), which records each change-set directory as "x" and ignores its contents (internal/api/web_events.go). Every move or landing appends a new entry file to the change set's existing directory, e.g. .rhiza/log/01M6PFEXSHWC6TR4F3GFKHV09R holds its accept entry. TestEventsNameWhatChanged passes only because its log entry goes into a brand-new change-set directory. How I ran it: I added a probe test through go test -overlay, leaving the tree unedited. It writes a.json into .rhiza/log/01ZZ.../, reads the change source, writes b.json into the same directory and reads again. Both reads give fingerprint "x", so no event would be sent (go test -trimpath -count=1 -overlay ... -run TestProbe ./internal/web/ FAILs). Fix: fingerprint each change-set directory by its entries (count, names or newest mtime), and add a test case that appends an entry to an existing change set and expects event: change for that change set's ID.
- web-templates-embedded (step build/build): passed: attempt 1: verifier passed
  - attempt 1 builder, session 866c8140-adc4-41b3-aeb6-01a1ada9f254: pass (said done)
  - attempt 1 verifier, session 58d0f11f-618a-4e27-a5b7-01a1adab895e: pass (Evidence written by the verifier)
- web-live-sections (step build/build): passed: attempt 1: verifier passed
  - attempt 1 builder, session 61332dea-b9ae-43af-915e-01a1adabb908: pass (said done)
  - attempt 1 verifier, session 1840efdb-9199-49fa-be9f-01a1adad733d: pass (Evidence written by the verifier)
- web-url-in-daemon-status (step build/build): passed: attempt 1: verifier passed
  - attempt 1 builder, session 0b6cc426-7a44-4fee-8319-01a1adada134: pass (said done)
  - attempt 1 verifier, session fee64b7b-f4b9-42c5-ade8-01a1adb0f3b8: pass (Evidence written by the verifier)

## Checks

- compliance (step review/review): passed after 1 cycle
  - cycle 1: passed, check session 8dcbd2ad-71af-41a2-8975-01a1adc60d01 pass (said done)
  - round 1 (cycle 1): no findings
- quality (step review/review): passed after 1 cycle
  - cycle 1: passed, check session ed98a322-b9d9-4bb1-8f95-01a1adc63a1a pass (said done)
  - round 1 (cycle 1): 6 findings, 0 confirmed
    - f1 minor at internal/web/web.go:79 on web-serve-loopback: Handler never checks the Host header, so the loopback server is open to DNS rebinding: a page the owner visits can rebind its name to 127.0.0.1 and read /api/* (model, inbox, run summaries) and /events. Refusing a Host other than 127.0.0.1:<port> or localhost:<port> would close it.
    - f2 minor at internal/api/daemon.go:170 on web-serve-loopback: When the port is taken, Manager.Apply fails and the daemon prints the same error to stderr on every poll, which floods the daemon log with no change in state. Reporting only on a change of error would avoid it.
    - f3 minor at internal/api/web_events.go:25 on web-events-stream: common() runs gitCommonDir (a git rev-parse exec) on each call. The run, log, inbox and daemon sources each call it on every 1s tick for every open /events connection, so each open tab spawns about four git processes a second. The common dir does not change and could be resolved once.
    - f4 nit at internal/web/web.go:117 on web-serve-loopback: http.Server has no ReadHeaderTimeout or ReadTimeout (go vet's G112 class). It is loopback only, but a stalled client holds a goroutine forever.
    - f5 nit at internal/api/web_events.go:142 on web-events-stream: DiskLowInboxIDs is exported production API that exists only so the web test can name an event ID.
    - f6 nit at internal/web/README.md:10 on web-templates-embedded: The app.js line in the file tree is no longer aligned with its sibling entries' comment column, and the old static/js/ path is gone without saying that app.js now sits at static/ root.
- qa (step review/review): passed after 1 cycle
  - cycle 1: passed, check session e4071629-5ccf-4cbd-a7c3-01a1adc66bbd pass (said done)
  - round 1 (cycle 1): 1 finding, 0 confirmed
    - f1 nit at internal/web/templates/layout.html:20 on web-templates-embedded: Hands-on, the served layout's nav links to /runs and /roadmap, which the running daemon answers 404 (only / is a page in this change set). This is fine if later change sets add those pages, but until then every page shows two dead links.
- scope (step review/review): passed after 1 cycle
  - cycle 1: passed, check session 8b91a242-5b90-4109-9bc2-01a1adc69fe8 pass (said done)
  - round 1 (cycle 1): no findings
- model (step review/review): passed after 1 cycle
  - cycle 1: passed, check session 61323590-b559-4ded-b10a-01a1adc6e212 pass (said done)
  - round 1 (cycle 1): 1 finding, 0 confirmed
    - f1 minor at internal/api/web_api.go:22 on web-api-read-only: The leaf says every non-GET method is refused, but ReadOnlyHandler (and Handler's GET patterns, which Go also matches for HEAD) answer HEAD too. HEAD is harmless and changes nothing, but the statement should say GET and HEAD, or the code should refuse HEAD, so the model matches the code.

## Code checks

- step review/code: pass

## Sign-offs

- signoff (visit 1): approved by rule autonomous

## Retries

- 2026-11-05T23:26:28Z retried at rebase, after: step "rebase" ended with outcome "fail"

## Sessions

- build/build, session f65a0c51-271e-49a5-9462-01a1ad9129aa: tokens input 38, output 11338, cache creation 53399, cache read 1281213; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 22f6fe1b-faed-4934-8ad8-01a1ad9524df: tokens input 26, output 4618, cache creation 42903, cache read 711528; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session da8c5550-a298-4fda-b144-01a1ad9554f7: tokens input 34, output 12043, cache creation 67556, cache read 1275365; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session cd471593-c0a6-4de3-bdcb-01a1ad99cc4d: tokens input 26, output 3784, cache creation 35908, cache read 733369; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session dc576494-f776-49f5-8bed-01a1ad99f20f: tokens input 34, output 8166, cache creation 42832, cache read 966324; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session e101ac60-f0b6-4196-86ca-01a1ada5ab4b: tokens input 16, output 3306, cache creation 36459, cache read 436115; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 99a5df12-8319-45e5-abf0-01a1ada5deb1: tokens input 30, output 12405, cache creation 53996, cache read 982515; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session e7d86230-6b20-467f-a219-01a1ada9bd58: tokens input 14, output 3384, cache creation 31909, cache read 359933; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 866c8140-adc4-41b3-aeb6-01a1ada9f254: tokens input 14, output 3637, cache creation 35315, cache read 359893; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 58d0f11f-618a-4e27-a5b7-01a1adab895e: tokens input 14, output 2117, cache creation 28553, cache read 353121; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 61332dea-b9ae-43af-915e-01a1adabb908: tokens input 12, output 5624, cache creation 38762, cache read 310487; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 1840efdb-9199-49fa-be9f-01a1adad733d: tokens input 12, output 2022, cache creation 29387, cache read 299179; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 0b6cc426-7a44-4fee-8319-01a1adada134: tokens input 18, output 3035, cache creation 36590, cache read 491055; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session fee64b7b-f4b9-42c5-ade8-01a1adb0f3b8: tokens input 40, output 4570, cache creation 36002, cache read 1014518; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 9ac9efb5-68af-41c6-892b-01a1adb121d4: tokens input 32, output 4073, cache creation 38369, cache read 866978; helper tokens input 0, output 0, cache creation 0, cache read 0
- build/build, session 7d5e40c8-e4a0-438c-b56f-01a1adbcab8f: tokens input 18, output 2614, cache creation 32586, cache read 475168; helper tokens input 0, output 0, cache creation 0, cache read 0
- review/review, session 8dcbd2ad-71af-41a2-8975-01a1adc60d01: tokens input 20, output 3655, cache creation 55956, cache read 680074; helper tokens input 0, output 0, cache creation 0, cache read 0
- review/review, session ed98a322-b9d9-4bb1-8f95-01a1adc63a1a: tokens input 28, output 7236, cache creation 75026, cache read 1026998; helper tokens input 0, output 0, cache creation 0, cache read 0
- review/review, session e4071629-5ccf-4cbd-a7c3-01a1adc66bbd: tokens input 66, output 19778, cache creation 63669, cache read 2461302; helper tokens input 0, output 0, cache creation 0, cache read 0
- review/review, session 8b91a242-5b90-4109-9bc2-01a1adc69fe8: tokens input 16, output 2160, cache creation 43193, cache read 476320; helper tokens input 0, output 0, cache creation 0, cache read 0
- review/review, session 61323590-b559-4ded-b10a-01a1adc6e212: tokens input 24, output 4747, cache creation 64981, cache read 904510; helper tokens input 0, output 0, cache creation 0, cache read 0

Totals: tokens input 532, output 124312, cache creation 943351, cache read 16465965; helper tokens input 0, output 0, cache creation 0, cache read 0