ci: mark nightly tree-commits once the tree is published, not daemon-tested
Takes back #25933: only its request-nightly-next.test.sh case "a marker carrying the old os field must still promote". Nightly promotion no longer reads daemon-tests.json at all, so the case has nothing left to test. The marker's other readers (cmux-tui-point-channel.sh, tree-commit-marker.sh daemon-tested) still check only that it exists, as #25933 made them.
Leo, 2026-10-23: "we want no smoke tests. No smoke tests, okay? Or at least, like, you know, previously we had the daemon with a smoke test literally block the entire nightly release, right? Like, that's unacceptable."
Problem
NEXT nightly promotion only takes a commit with a tree-commit marker (files.cmux.com/cmux-tui/tree-commits/<sha>.json). The marker writer's tree_ready asked for the tree's daemon tests too, and mark-tree-commits waited on publish-tree-tested.
On 2026-10-28, run 40651931144 (cfd8a475) built and published its tree, but its cmux_next_ daemon tests job failed fetching Zig packages, an infra download failure. No marker was written for any of the last 60 feat-cmux-next commits, and a launch-crash fix (1daea603) was held off the nightly feed for over 4 hours.
Change
The marker now means "the tree is built, published and verified".
scripts/cmux-next/tree-commit-marker.sh:tree_readyispin-cmux-tui.sh verify-keyalone (sha256, source.json and the publishing commit's attested manifest agree). Thedaemon-testedsubcommand stays. The header contract says what changed and why.scripts/cmux-next/request-nightly-next.sh: drops step 1b, its owndaemon-testedcheck. Without this, the 30-minute tick (which runs each commit's own copy of this script) would still refuse every commit whose daemon tests did not pass..github/workflows/cmux-tui-artifacts.yml:mark-tree-commitsneedspublish-treeinstead ofpublish-tree-tested, and runs when the publish succeeded or was skipped (a tree already published, or one another run owns). A failed publish marks nothing. The script still verifies every tree itself, so it never marks an unpublished one.- Unchanged: the daemon tests still run after the publish and report as before.
publish-tree-testedstill writesdaemon-tests.jsonon a pass, andpoint-feat-channel(the acpmux feat-cmux-next channel) still follows only daemon-tested trees.
Comments on main that still say "daemon-tested" (scripts/ci/promote-nightly-next.mjs, nightly-next-tick.yml, scripts/ci/nightly_next_feed_watch.py) are left alone here. Main's promote guard only reads the marker, so its behaviour follows this change without a main PR.
Risk
A tree whose daemon tests really fail can now reach Nightly. The existing nightly-next-rollback.yml covers it today.
Follow-up: roll the nightly feed back automatically on a real (non-infra) daemon-test failure, through nightly-next-rollback.yml. Not in this PR.
Validation
Red on the base scripts and workflow, green on this head (run locally):
bash scripts/cmux-next/tests/request-nightly-next.test.sh: a published tree with nodaemon-tests.jsonis promoted,tree-readyanswers ready for it, the writer marks it, and the writer still refuses an unpublished tree. Base fails with "a published tree without its daemon-tests marker must be promoted".python3 tests/test_cmux_tui_feat_publish_order.py:mark-tree-commitsneeds no daemon tests and runs on a feat-cmux-next push or dispatch while they are still queued, and not when the publish failed.test_tree_publish_and_nightly_promotion_do_not_wait_for_daemon_testsintests/test_tui_publish_workflow_security.py.
Also green: tests/test_cmux_tui_daemon_tests_gate.py, tests/test_cmux_next_checks_workflow.py (160 tests), tests/test_cmux_tui_lane_daemon_tests.py, tests/test_cmux_tui_owner_wait_defers.py, tests/test_cmux_tui_point_channel.py, tests/test_ci_production_secrets_protected_env.py. actionlint shows one SC2034 warning at line 1506, the same as on base.
Observed / Not run
Ran the files above with python3 and bash. I did not run the workflow itself. After merge, one cmux-tui-artifacts.yml dispatch on feat-cmux-next backfills the markers.
Changelog
none
Agent session: agent session
š¤ Generated with Claude Code