Expand description
On-disk path resolver for camp deployment manifests.
Replaces the pre-R215 single-rooted .yah/cloud/ layout. The new model
splits substrate (“where”) from service declarations (“what”):
.yah/
infra/ # substrate registry — Infra tab
machines/<name>.toml # provisioned hosts
providers/<id>.toml # account/runtime bindings
cloud-init/mirror.yml # yubaba bootstrap template
rules/<id>.yaml # tower alert rules
services/<svc>/ # operator-facing deployables — Services tab
service.toml # name, domain, components
mirrors/<env>.toml # service projection onto infraWorkload manifests stay colocated with the code they deploy (paths come
from service.toml components).
All helpers take workspace_root (the camp dir, the parent of .yah/).
No helper does I/O, and every one of them resolves camp-locally. A camp that
runs on another camp’s shared cluster borrows that inventory through
.yah/infra/sources.toml, overlaid by CloudConfig::load (R615-F2) — not by
any helper here returning a foreign directory.
@yah:relay(R222, “Service/infra manifest reshape — phases B2–B4”) @yah:at(2026-05-18T02:19:27Z) @yah:status(handoff) @yah:assignee(agent:claude) @arch:see(.yah/docs/architecture/A031-yah-cloud-config-shape.md) @yah:verify(“cargo check -p cloud && cargo test -p cloud”) @yah:verify(“cargo check -p yah && cargo check -p agent-tools”) @yah:verify(“cargo check -p yah –tests && cargo check -p agent-tools –tests”) @yah:verify(“CloudConfig::load(workspace_root) populates providers + services (with mirrors) from the seven Phase-A manifests”) @yah:cleanup(“compose.rs + cli/cloud.rs bucket commands + handle_mirror{,_status} + collect_machine_services + derive_public_hostname likely deleted in B3-T2 — confirm against the yubaba integration story first”) @yah:cleanup(“agent-tools/cloud_tools.rs’s duplicate ServiceConfig/MirrorConfig collapses into a re-import once B3-T3/T4 stabilize the loader API”) @yah:cleanup(“MachineConfig::save signature: tighten in B5 once .yah/infra/ vs .yah/cloud/ migration settles”) @yah:next(“B4: schemars-generated JSON schemas → .yah/schema/{service,mirror,provider,workload,machine}.toml.schema.json. Implement as an xtask command (not a build script — keeps cloud’s compile path clean). Drift test asserts generated == committed. Each manifest’s #:schema directive points there.”) @yah:next(“R222-T1: Update cloud.mirror_state + cloud.service_ports to read from .yah/services/ layout (currently silently empty in post-B2 workspaces).”) @yah:handoff(“B2 landed (prev agent): Provider/ServiceConfig/MirrorConfig types in config.rs, cross-ref validation, 100+ tests passing.”) @yah:handoff(“B3 landed: All cli/cloud.rs callers migrated off pre-B2 field names. cfg.mirrors → cfg.legacy_mirrors in machines_for_workload_name, workload_ident_for_machine, machines_for_service, workload-show block. cfg.mirror() → cfg.legacy_mirror() in collect_machine_services, derive_public_hostname, handle_mirror, handle_mirror_status. cfg.services.iter() → cfg.legacy_services.iter() in collect_machine_services. cargo check -p cloud/yah/agent-tools clean; 104 cloud tests pass. compose.rs + bucket commands left pending yubaba integration confirmation. R222-T1 filed for agent-tools cloud_tools.rs path update (.yah/services/ layout).”)
@yah:ticket(R615-T5, “Retire the inherit_machines stopgap: migrate noisetable to sources.toml, delete the camp.toml redirect”)
@yah:status(review)
@yah:assignee(agent:bundle-anthropic-ashguard)
@yah:at(2026-08-08T23:57:47Z)
@yah:phase(P3)
@yah:parent(R615)
@yah:next(“Author noisetable .yah/infra/sources.toml with a kind=path, mode=read-only source owner=yah path=../yah, and verify its Infra tab + yah cloud reconcile resolve the same machines they do today through inherit_machines.”)
@yah:next(“THEN delete the stopgap in the same pass — no coexistence. Remove paths.rs machines_dir inherited_machines_dir / inherited_machines_source, the [infra] inherit_machines key from noisetable camp.toml, and the InfraSection field from kg-store CampConfig + camp.toml.schema.json if nothing else uses it.”)
@yah:verify(“rg -n inherit_machines across the tree returns ZERO live hits outside archived docs”)
@yah:verify(“noisetable yah cloud validate stays ok and its Infra tab still lists yah cluster machines”)
@yah:gotcha(“Both mechanisms hook the SAME paths::machines_dir seam. If they coexist, resolution order becomes ambiguous and an operator cannot tell which one is winning. inherit_machines is a strict subset of the sources.toml kind=path case, so this is a pure replacement — do not build a compatibility shim.”)
@yah:gotcha(“Dropping InfraSection from CampConfig has a silent-data-loss hazard in reverse: the section was added so camp.toml round-trips without an old binary stripping [infra] on the next relay_high_water save. Confirm no camp.toml in any camp still carries the key before removing the struct field.”)
@arch:see(.yah/docs/working/W274-linked-infra-sources.md)
@yah:depends_on(R615-F4)
@yah:tier(Cleric)
@yah:handoff(“Authored /Users/leif/ss/noisetable/.yah/infra/sources.toml (kind=path, owner=yah, path=../yah, mode=read-only) – a NEW, purely additive file, zero risk to noisetable’s substantial in-progress uncommitted work (git status there shows dozens of modified koda/core files unrelated to this ticket – did not touch, did not build/run anything in that repo, only wrote the one new file). Left [infra].inherit_machines in noisetable’s camp.toml UNTOUCHED – see next-steps for why.”)
@yah:handoff(“Resolution parity PROVEN two ways. (1) Self-contained unit tests in oss/yubaba/crates/cloud/src/config.rs (no dependency on the live noisetable checkout): inherit_machines_and_a_path_source_resolve_the_same_machines builds two synthetic camps against one shared machine root – one via [infra].inherit_machines, one via an equivalent kind=path source – and asserts the resolved machine sets are byte-identical. (2) coexistence_is_a_safe_no_op_not_a_conflict proves the ticket’s own gotcha resolves cleanly: with BOTH mechanisms declared against the same root (noisetable’s actual current state, now that sources.toml exists alongside inherit_machines), inherit_machines claims the names as camp-local first, so sources.toml’s overlay finds every name already ‘seen’ and contributes nothing – no duplicate rows, no origin-tag confusion. This is also why adding sources.toml today was safe: it’s a provable no-op until inherit_machines is removed.”)
@yah:handoff(“DID NOT delete the stopgap. Three reasons, compounding: (a) noisetable’s camp.toml still declares inherit_machines, so deleting the paths.rs/kg-store CODE first would silently empty its Infra tab and reconcile surface the moment this crate is rebuilt and installed – a live camp.toml file whose own header comments warn ‘the running desktop app holds state in memory,’ so I have no way to know whether a live session is depending on this right now. (b) Flipping noisetable’s camp.toml to delete inherit_machines is the mirror-image risk – an edit to a live, actively-worked-on separate repo I cannot safely verify end-to-end without running noisetable’s own build (which I declined to do given its unrelated in-progress state). (c) THE BLAST RADIUS IS BIGGER THAN THE TICKET DESCRIBED, discovered via rg -n inherit_machines across the tree: crates/yah/hub/src/coordinator.rs independently re-implements the SAME [infra].inherit_machines read (its own parsing, not routed through paths::machines_dir at all) for mesh_yubaba_base_urls – hub is fenced/live-owned by @Ashguard:polaris this session. app/yah/desktop/src/infra_decl.rs also references the mechanism. So ‘delete paths.rs + kg-store’s InfraSection’ alone would leave hub’s independent reader orphaned and still working off the old field, and the desktop app referencing dead code paths – a genuinely 4-file, 3-crate (+1 fenced) cutover, not the 2-file one the ticket’s own next-step described.”)
@yah:handoff(“Tree anchor 85801e7f. Pathspec (this repo): oss/yubaba/crates/cloud/src/config.rs (+2 tests only). Pathspec (noisetable, separate repo, NOT part of this handoff’s git tree): .yah/infra/sources.toml (new file). Tests: cargo test -p yah-cloud –lib (from oss/yubaba) 723 passed / 0 failed / 4 ignored, +2 over R615-T3’s 721 baseline.”)
@yah:handoff(“Tree anchor at handoff: 85801e7f6b76b369c0c8ecd2e5c7874990cd9286 — the shared tree as I left it. Diff against it (git diff 85801e7f6b76b369c0c8ecd2e5c7874990cd9286..HEAD) to see what landed under you, and quote this SHA rather than ‘HEAD’ in any revert/restore instruction.”)
@yah:next(“THE ACTUAL CUTOVER is what remains, and it’s an operator-timing call, not an engineering gap: (1) confirm no live desktop session has noisetable open / depending on cached inherit_machines state, (2) delete ‘[infra]\ninherit_machines = "../yah"’ from noisetable’s camp.toml (the file already carries a big warning about live desktop state – read it before touching it), (3) in THIS repo: remove paths.rs’s inherited_machines_dir/inherited_machines_source + the redirect branch in machines_dir(), remove InfraSection from crates/yah/kg-store/src/camp_config.rs (camp_config.rs:1250-1257’s round-trip test goes with it) + regenerate camp.toml.schema.json, AND fix crates/yah/hub/src/coordinator.rs’s independent inherit_machines reader (mesh_yubaba_base_urls + its two tests resolves_through_inherit_machines_redirect / enumeration_follows_the_inherit_machines_redirect at coordinator.rs:283,375) to read sources.toml instead or be told sources.toml already covers it via a different call path – hub is fenced, needs @Ashguard:polaris or a session after that lane drains. (4) app/yah/desktop/src/infra_decl.rs (:326,:394) also references the mechanism in comments – confirm nothing there needs a matching edit. rg -n inherit_machines across the tree is the ticket’s own verify line; it currently returns non-archive hits in exactly these 4 files plus this ticket’s own test fixtures (which retire themselves once the mechanism does).”)
@yah:next(“R615-S6 (the settle ticket) can now cite BOTH the sources.toml mechanism (F1/F2) and this coexistence proof as grounding for whether shared infra becomes a named repo any camp links.”)
@yah:gotcha(“Reconciliation audit (871fde1c): verified NOT landed — the ticket’s core ask (delete the inherit_machines stopgap) is confirmed absent. rg inherit_machines still hits paths.rs, hub/coordinator.rs, hub/in_process.rs, desktop/infra_decl.rs; the ticket’s own verify line (‘zero live hits outside archived docs’) fails. Only the parity proof (2 new tests in oss/yubaba/crates/cloud/src/config.rs, confirmed present) and the noisetable sources.toml file (outside this repo, unverifiable here) landed. This matches the ticket’s own handoff text (‘DID NOT delete the stopgap’) — board state (open) is accurate, not stale.”)
@yah:handoff(“CUT OVER. The inherit_machines stopgap is deleted across all four call sites the prior pass identified, and noisetable is migrated. Tree anchor 5e86d6d96527fe00aeb77b20c70fec5da7ec2707.”)
@yah:verify(“End-to-end proof against the REAL inventory, three-way, through the real CLI: a scratch camp whose only infra declaration was a sources.toml [[source]] kind=path at /Users/leif/ss/yah resolved us-west-001 (a machine declared solely in yah’s tree) via yah cloud machine status. Control 1: a bogus name errored with ‘no machine … check declared names’. Control 2: removing sources.toml made the same camp report ‘no machines declared’. So the borrow is load-bearing, not incidental.”)
@yah:handoff(“FOUR CALL SITES, all cut. (1) cloud/src/paths.rs: machines_dir is now a pure path join; inherited_machines_dir + inherited_machines_source deleted. (2) crates/yah/hub/src/coordinator.rs: its independent reader is replaced by machines_dirs() -> Vec
Functions§
- apps_
registry - Registry of app roots for fast discovery (R470-T7).
Populated by
yah cloud apps add <path>/yah cloud apps scan. - asset_
status_ journal - Append-only journal for static-asset reconciler decisions (R470-T1).
One JSONL record per reconciler decision; replayed by
yah cloud status. - cloud_
init_ dir - cloud_
init_ template - domain_
toml - domains_
dir - infra_
dir - infra_
source_ cache_ dir - Sync-cache checkout directory for one
kind = "git"crate::config::InfraSource(R615-T3 / W274 §3).yah infra syncshallow-clones/pulls the source’s repo here;CloudConfig::load’s overlay (R615-F2) only ever reads this directory, never the network, so config load stays synchronous and offline.kind = "path"sources need no cache — they read the owner’s live tree directly. - legacy_
cloud_ dir - Pre-R215 root, kept for one release so we can read existing on-disk
state from a tool that wrote there. New writes go through the
infra_*/service_*helpers above. - machine_
toml - machines_
dir - Directory holding this camp’s own machine inventory (
<name>.tomlper node): always<workspace_root>/.yah/infra/machines/. - provider_
toml - providers_
dir - rules_
dir - service_
dir - service_
mirror_ toml - service_
mirrors_ dir - service_
toml - services_
dir - workloads_
dir - Directory holding this camp’s fleet workload declarations — the TOML
serialization of a
WorkloadSpec, one file per workload, whichyah cloud workload deploy <n> <machine>looks up by name. - yah_dir