Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/operational-home-layout/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ config/startup-memory-budget primary-authoritative per-home startup-memory b
config/stow-pass-horizon optional presence flag opting this home in to /stow's default-off pass-count decay horizon; LOCAL, gitignored, and not inherited; see docs/configuration.md "Stow pass horizon"
config/herdr-presentation-spaces optional "off" opt-out from, or "on" opt-in to, Herdr's default-on disposable single-task visual projection, which is unconfigured-default-on only at or above a Herdr version floor; LOCAL, gitignored; inherited by secondmate homes; see docs/herdr-backend.md "Presentation spaces"
config/trace-context optional presence flag enabling default-off native W3C trace-context propagation to spawned agents; LOCAL, gitignored; inherited by secondmate homes; see docs/configuration.md "Trace context propagation" and docs/trace-context.md
config/lavish-axi-host optional one-line per-machine Lavish server address; LOCAL, gitignored, inherited by secondmate homes, and exported into every worker launch; see docs/configuration.md "Lavish server address" for opening versus polling
config/lavish-axi-host optional one-line per-machine Lavish server address; LOCAL, gitignored, not inherited by secondmate homes, and exported into every worker launch; see docs/configuration.md "Lavish server address" for opening versus polling
config/brief-include.md optional standing worker instructions appended verbatim as the last section of every ship and scout scaffold; LOCAL, gitignored, and not inherited; keep its text out of `## Firstmate spec`; see docs/configuration.md "Home brief include"
config/fleet-ledger optional presence flag opting this home in to the default-off fleet activity ledger state/fleet-ledger.jsonl that outside tools can follow; LOCAL, gitignored, and not inherited; see docs/fleet-ledger.md
config/turnend-churn-absorb optional presence flag opting this home into the default-off absorb of bare turn-end wakes on pane churn; LOCAL, gitignored, and not inherited; see docs/configuration.md "Turn-end pane-churn absorb"
Expand Down
4 changes: 1 addition & 3 deletions bin/fm-config-inherit-lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
# "off" preferences propagate as files. Primary
# config/trace-context is copied at the launch convergence point as part of the
# default-off W3C trace-context setup, while live convergence leaves it unchanged.
# Primary config/lavish-axi-host carries the one per-machine Lavish server address
# to every worker so a worker never starts a second server on another interface.
# The primary passes its frozen home-session decision into a newly launched
# Secondmate; see docs/trace-context.md.
# Primary config/claude-permission-mode is a captain-wide safety preference
Expand Down Expand Up @@ -79,7 +77,7 @@ FM_SHARED_CAPTAIN_MODE="444"
# The declared inheritable set (space-separated, config-dir-relative item paths).
# Extend here to inherit more of the primary's local config; override via the
# environment only in tests. Items must not contain whitespace.
FM_INHERITABLE_CONFIG="${FM_INHERITABLE_CONFIG:-crew-dispatch.json dispatch-never-send crew-harness backlog-backend backend herdr-presentation-spaces startup-memory-budget trace-context launch-env-allowlist claude-permission-mode lavish-axi-host keep-ai-trailers}"
FM_INHERITABLE_CONFIG="${FM_INHERITABLE_CONFIG:-crew-dispatch.json dispatch-never-send crew-harness backlog-backend backend herdr-presentation-spaces startup-memory-budget trace-context launch-env-allowlist claude-permission-mode keep-ai-trailers}"

# Items whose value is a home-SESSION enablement decision rather than durable
# local configuration. They are inherited at the launch convergence point, where
Expand Down
7 changes: 4 additions & 3 deletions bin/fm-spawn.sh
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,10 @@ case "$CLAUDE_PERMISSION_MODE" in
auto) CLAUDE_PERM_FLAG='--permission-mode auto' ;;
*) CLAUDE_PERM_FLAG='--dangerously-skip-permissions' ;;
esac
# config/lavish-axi-host is the primary-owned per-machine address for the
# shared Lavish server. Read it once per launch and refuse malformed values so
# every worker reaches the same server instead of starting a second one.
# config/lavish-axi-host is this home's own per-machine address for the
# shared Lavish server; it is never inherited from the primary. Read it once
# per launch and refuse malformed values so every worker reaches the same
# server instead of starting a second one.
if ! LAVISH_AXI_HOST_CONFIG_PRESENT=$(fm_config_source_present "$CONFIG/lavish-axi-host"); then
exit 1
fi
Expand Down
4 changes: 3 additions & 1 deletion docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,9 @@ A remote secondmate is launched on its host from its own home's configuration, s
## Lavish server address (config/lavish-axi-host)

The optional local, gitignored `config/lavish-axi-host` contains one non-empty address without whitespace for the per-machine Lavish server.
`fm-spawn.sh` exports that address into every new worker and relaunch for opening boards, and the file is inherited into secondmate homes through the primary-authoritative configuration contract.
`fm-spawn.sh` exports that home's address into every new worker and relaunch for opening boards.
Each secondmate home keeps its own per-machine value; the primary does not copy or overwrite it.
A home that already inherited the primary's address under the earlier inheritance contract keeps that copy until an operator rewrites or removes its `config/lavish-axi-host` once.

Once a board exists, the process-event adapter derives the polling address from that board's own saved Lavish session instead; its header owns the lookup contract.
When the file is absent, worker launches do not add a board address and retain the existing ambient-environment behavior.
Expand Down
19 changes: 17 additions & 2 deletions tests/fm-secondmate-harness.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -380,20 +380,26 @@ test_propagate_lib() {
[ -d "$dest/crew-harness" ] || fail "failed absence mirror removed the wrong path"
rm -rf "$dest/crew-harness"

# 5. secondmate-harness is never inherited; backend still is
# 5. secondmate-harness and the per-machine Lavish address are never inherited; backend still is
printf 'grok\n' > "$src/secondmate-harness"
printf 'primary.example\n' > "$src/lavish-axi-host"
printf '{"default":{"harness":"codex"}}\n' > "$src/crew-dispatch.json"
printf 'codex\n' > "$src/crew-harness"
printf 'manual\n' > "$src/backlog-backend"
printf 'herdr\n' > "$src/backend"
rm -rf "$d/home2"
mkdir -p "$d/home2/config" "$d/home2/state"
printf 'secondmate.example\n' > "$d/home2/config/lavish-axi-host"
propagate_inheritable_config "$src" "$d/home2/config"
[ -e "$d/home2/config/secondmate-harness" ] && fail "secondmate-harness was inherited (must not be)"
[ "$(cat "$d/home2/config/lavish-axi-host")" = secondmate.example ] || fail "per-machine Lavish address was overwritten"
[ "$(cat "$d/home2/config/crew-dispatch.json")" = '{"default":{"harness":"codex"}}' ] || fail "crew-dispatch.json not propagated alongside"
[ "$(cat "$d/home2/config/crew-harness")" = codex ] || fail "crew-harness not propagated alongside"
[ "$(cat "$d/home2/config/backlog-backend")" = manual ] || fail "backlog-backend not propagated alongside"
[ "$(cat "$d/home2/config/backend")" = herdr ] || fail "backend not propagated alongside"
rm -f "$d/home2/config/lavish-axi-host"
propagate_inheritable_config "$src" "$d/home2/config"
[ ! -e "$d/home2/config/lavish-axi-host" ] || fail "primary Lavish address was copied into a home without its own value"

# 6. nothing to propagate -> destination dir is never created (a true no-op)
rm -rf "$d/src3" "$d/dest3"
Expand Down Expand Up @@ -1044,7 +1050,7 @@ new_world() {
[ "$dispatch_ignore" = no ] || printf 'config/crew-dispatch.json\n'
printf 'config/crew-harness\nconfig/secondmate-harness\nconfig/backlog-backend\n'
printf 'config/backend\nconfig/herdr-presentation-spaces\nconfig/startup-memory-budget\n'
printf 'config/claude-permission-mode\n'
printf 'config/claude-permission-mode\nconfig/lavish-axi-host\n'
} > "$w/main/.gitignore"
printf 'v1\n' > "$w/main/AGENTS.md"
printf 'r1\n' > "$w/main/README.md"
Expand Down Expand Up @@ -1302,6 +1308,8 @@ test_bootstrap_sweep_propagates_and_reconverges() {
printf 'tmux\n' > "$w/home/config/backend"
: > "$w/home/config/trace-context"
printf 'grok\n' > "$w/home/config/secondmate-harness"
mkdir -p "$w/sm/config"
printf 'secondmate.example\n' > "$w/sm/config/lavish-axi-host"
run_bootstrap "$w" >/dev/null
[ "$(cat "$w/sm/config/crew-harness" 2>/dev/null)" = codex ] \
|| fail "sweep: crew-harness not pushed into the live home"
Expand All @@ -1315,12 +1323,15 @@ test_bootstrap_sweep_propagates_and_reconverges() {
|| fail "sweep: trace-context changed a legacy live home before relaunch"
[ -e "$w/sm/config/secondmate-harness" ] \
&& fail "sweep: secondmate-harness was inherited (must not be)"
[ "$(cat "$w/sm/config/lavish-axi-host")" = secondmate.example ] \
|| fail "sweep: secondmate's per-machine Lavish address was removed"

# Re-converge: primary changes inherited config values; the home follows on the next sweep.
printf '{"default":{"harness":"claude"}}\n' > "$w/home/config/crew-dispatch.json"
printf 'claude\n' > "$w/home/config/crew-harness"
printf 'tasks-axi\n' > "$w/home/config/backlog-backend"
printf 'zellij\n' > "$w/home/config/backend"
printf 'primary.example\n' > "$w/home/config/lavish-axi-host"
run_bootstrap "$w" >/dev/null
[ "$(cat "$w/sm/config/crew-harness" 2>/dev/null)" = claude ] \
|| fail "sweep: home did not re-converge to the primary's new crew-harness"
Expand All @@ -1330,6 +1341,8 @@ test_bootstrap_sweep_propagates_and_reconverges() {
|| fail "sweep: home did not re-converge to the primary's new backlog-backend"
[ "$(cat "$w/sm/config/backend" 2>/dev/null)" = zellij ] \
|| fail "sweep: home did not re-converge to the primary's new backend"
[ "$(cat "$w/sm/config/lavish-axi-host")" = secondmate.example ] \
|| fail "sweep: primary Lavish address overwrote the secondmate's value"

# Mirror absence: primary clears inherited config; the home's copies are removed.
rm -f "$w/home/config/crew-dispatch.json" "$w/home/config/crew-harness" \
Expand All @@ -1343,6 +1356,8 @@ test_bootstrap_sweep_propagates_and_reconverges() {
&& fail "sweep: home backlog-backend not removed after the primary cleared it"
[ -e "$w/sm/config/backend" ] \
&& fail "sweep: home backend not removed after the primary cleared it"
[ "$(cat "$w/sm/config/lavish-axi-host")" = secondmate.example ] \
|| fail "sweep: secondmate's per-machine Lavish address changed"
pass "B7 bootstrap sweep pushes, re-converges, and mirrors absence; never inherits secondmate-harness"
}

Expand Down
Loading