Intent
Why this exists
Root daemon: one daemon on the root builds every registered project round-robin under one machine-wide run cap and usage governor, with machine settings in the root config and project settings in each repo, under one service
Leaves
8 leaves, 8 with evidence
- has evidence
The root daemon keeps one usage governor for the machine: run drivers of every project record usage-limit hits in the root's state folder, and the governor's hold stops new runs in all projects at once.
Acceptanceinternal/daemon usage tests: a limit hit recorded by one project's driver holds starts in a second project, and the hold lifts for both at the reset time. - has evidence
rhiza daemon runs on the root, never on a single repo: run anywhere under the root it resolves the root and holds one lock in the root's state folder (<root>/.rhiza-root/), so a second daemon on the same root refuses to start, and outside a root it exits 2 with next rhiza root init.
Acceptanceinternal/daemon lock tests: a second lock on the same root fails, from a project dir and from the root alike; a testscript gets exit 2 with the next from rhiza daemon in $NOROOT, outside any root; the existing daemon scripts (daemon-settings, daemon-pause, daemon-event-hook, daemon-repo-session, stage-autonomy) pass unedited under the root testscripts-run-under-root gives them. - has evidence
Each poll of the root daemon reads every registered, initialised project and starts its ship-change runs, plan requests and resumes as the per-repo daemon did, in that project's own checkout and journal; a project that is not initialised is skipped and daemon status says so.
AcceptanceDaemon tests with a root of two initialised projects and one bare checkout start a ready change set in each initialised project and record the bare one as skipped, not initialised. - has evidence
The root daemon fills the machine-wide maxRuns round-robin across projects, each turn taking that project's next ready change set in its own roadmap order, and never runs more of a project's change sets at once than its optional per-project max.
Acceptanceinternal/daemon pick tests: with maxRuns 3 and projects A (3 ready), B (2 ready) and C (1 ready), the picks are A1, B1, C1; with A's per-project max 1 and maxRuns 4, A gets one slot and the rest go to B and C. - has evidence
rhiza daemon settings lists every setting with its scope, machine (from rhiza.toml: maxRuns, usage budget and reserve, minFree, trimGoCache, web host and port, selfUpdate, permissionMode, paused) or project (from that repo's git config: autonomy per stage, project paused, per-project maxRuns, deploy check), and rhiza daemon set writes each key to its scope, taking --project or the current project for project keys. The hook commands rhiza.eventCommand and rhiza.notifyCommand are project settings: the root daemon runs a project's event command for that project's lifecycle moves and its notify command for that project's inbox, each read from that project's git config.
AcceptanceA testscript sets a machine key and a project key, finds the first in rhiza.toml and the second in that repo's git config, sees both in daemon settings --json with their scope and source, sees rhiza.daemon.trimGoCache listed with machine scope, and gets exit 2 for a project key set at the root with no --project; a daemon test with two projects, each with its own rhiza.eventCommand, runs each project's command only for that project's moves. - has evidence
rhiza daemon install writes and enables one systemd user unit for the root (rhiza-root.service, working directory the root), and rhiza daemon start, stop, status and uninstall act on the root's daemon from anywhere under the root.
AcceptanceA testscript with a fake systemctl on PATH runs daemon install from inside a project and finds one unit whose WorkingDirectory is the root, then start, stop and uninstall call systemctl on that unit. - has evidence
With selfUpdate on, the root daemon keeps itself current from the project rhiza.toml names as self_update_project: it fast-forwards that project's main checkout and runs make update there when origin/main moves, as today's self-update does; with none named it never self-updates.
Acceptanceinternal/daemon selfupdate tests: with self_update_project set, the fake git and make run in that project's checkout; unset, neither runs. - has evidence
Every Rex tab the root daemon's runs open (agent tabs; plan-request runs and run drivers start headless) opens in its project's fixed Rex session, rhiza-<project>, where <project> is the name the project is registered under in rhiza.toml (its folder, or project add --name), not the checkout's folder; the daemon creates each session on its Rex server when missing and passes it as REX_SESSION to every run driver it starts for that project, and rhiza inbox open and run open use the same registered name to find a run's panes.
AcceptanceA testscript runs rhiza daemon --once on a root with two projects, one added with --name other than its folder, against a fake Rex with REX_SESSION unset: it creates rhiza-<name> once for each project missing from rex session ls, each run driver it starts carries REX_SESSION=rhiza-<registered name>, with the sessions present it creates none, and rhiza run open for the renamed project's run targets rhiza-<registered name>.
Relations
Serves and depends on
- Serves
- Rhiza manages and builds several projects on one machine from one root directory: projects are registered under the root, one root daemon builds them all under one run cap and one usage budget, the CLI, web UI and TUI apps show every project and each on its own, and this VM runs rhiza and nebari that way. One root daemon builds every registered project's ready change sets, sharing run slots round-robin under one machine-wide cap and one usage governor, with machine settings in the root and project settings in each repo.
- Depends on
- —
Runs
1 runs
- ship-change rundone—
History
Lifecycle
- Proposed
- Accepted
- Landed