Skip to content
Merged
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
3 changes: 3 additions & 0 deletions .agents/skills/bootstrap-diagnostics/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ When any diagnostic needs captain attention, report the plain consequence and re
Publication is deliberately best-effort, so it cannot change another session-start, spawn, teardown, or watcher-poll result, and the watcher runs it detached so a slow attempt cannot delay the liveness beacon.
Read the named record for the recorded reasons, then reproduce with a direct `bin/fm-home-summary-refresh.sh` (no `--best-effort`, which is what keeps the failure quiet) so the refresh error reaches you.
A recorded deadline means the complete refresh did not finish inside `FM_HOME_SUMMARY_TIMEOUT`, so inspect lock acquisition and producer completion before validation or publication, and fix the blocked phase rather than raising this load-bearing bound.
- `LAVISH_REGISTRY_WARNING: <counts>; ... run bin/fm-lavish-audit.sh audit` - the historical Lavish registry has reached 50 open rows, or its read-only audit could not complete.
Run the named audit, preserve every ambiguous or actively owned review, and never treat registry-row count as live-connection count.
Bootstrap never prunes sessions.

- `BOOTSTRAP_INFO: closed the backlog item for <id> after interrupted cleanup; its endpoint or local copy may remain and should be reconciled` - replay closed the item, but the durable transition says physical cleanup was interrupted.
Verify process reaping, the local-copy return, and endpoint closure, then reconcile any surviving resource.
Expand Down
9 changes: 8 additions & 1 deletion .agents/skills/process-event-sources/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ Use the adapter, not the generic runner, for a real source.
For a Lavish review artifact produced by a worker (a live investigating scout should host its own loop and author revisions):

```sh
bin/fm-procevent-lavish.sh arm <artifact.html>
bin/fm-procevent-lavish.sh arm <artifact.html> --task-id <task-id>
```

The adapter records the task's Lavish ownership ledger as part of arming.
The fleet bearings board is home-owned and uses `--task-id home`.
Use `bin/fm-lavish-session.sh safe-park <task-id> <worktree-artifact.html> <durable-artifact.html>` when a review must outlive its worktree; that command owns the copy, re-serve, binding transfer, live verification, and superseded-session end sequence.
Use `bin/fm-procevent-lavish.sh retire-and-end <task-id> <artifact.html>` only when the durable review's owning lifecycle has reached its terminal event.
That operation preflights the durable end guard before retiring the source, then verifies the end.
Plain `retire` remains the correct narrow operation for a listener replacement that must leave the review open.

When a source carries captain answers to captain-held tasks, bind it BEFORE arming it, so it can never produce an answer that has nowhere to go:

```sh
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
projects/
state/
data/
data/*
!data/fm-lavish-session-prune-f1/
data/fm-lavish-session-prune-f1/*
scratchpad*
.no-mistakes/
.lavish/
Expand Down
17 changes: 14 additions & 3 deletions bin/fm-bearings-board.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ set -eu
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FM_ROOT="${FM_ROOT_OVERRIDE:-$(cd "$SCRIPT_DIR/.." && pwd)}"
FM_HOME="${FM_HOME:-$FM_ROOT}"
LAVISH_STATE_FILE="${FM_LAVISH_STATE_FILE:-${LAVISH_AXI_STATE_DIR:-$HOME/.lavish-axi}/state.json}"

TEMPLATE="${FM_BEARINGS_BOARD_TEMPLATE:-$SCRIPT_DIR/../.agents/skills/bearings/assets/board-template.html}"
PLACEHOLDER='__FM_BEARINGS_BOARD_DATA__'
Expand All @@ -66,7 +67,13 @@ fail() {
exit 1
}

# shellcheck source=bin/fm-lavish-lib.sh
. "$SCRIPT_DIR/fm-lavish-lib.sh"
LAVISH_STATE_DIR=$(fm_lavish_state_dir "$LAVISH_STATE_FILE") \
|| fail "FM_LAVISH_STATE_FILE must be an absolute Lavish state.json path"

board_path() { printf '%s/.lavish/bearings-board.html\n' "$FM_HOME"; }
lavish_cli() { LAVISH_AXI_STATE_DIR="$LAVISH_STATE_DIR" command lavish-axi "$@"; }

validate_payload() { # <data.json>
jq -e --arg schema "$BOARD_SCHEMA" '
Expand Down Expand Up @@ -137,7 +144,7 @@ validate_payload() { # <data.json>
}

command_build() {
local data=${1-} board json tmp sid extracted
local data=${1-} board json tmp sid extracted state_override
[ "$#" -eq 1 ] || { usage >&2; exit 2; }
command -v jq >/dev/null 2>&1 || fail "jq is required"
[ -f "$data" ] || fail "board data does not exist: $data"
Expand Down Expand Up @@ -178,7 +185,7 @@ command_build() {
printf 'board: %s\n' "$board"

command -v lavish-axi >/dev/null 2>&1 || fail "lavish-axi is not installed"
lavish-axi "$board" || fail "cannot establish the board Lavish session"
lavish_cli "$board" || fail "cannot establish the board Lavish session"
printf 'served: %s\n' "$board"

sid=$("$SCRIPT_DIR/fm-procevent-lavish.sh" source-id "$board") \
Expand All @@ -188,9 +195,13 @@ command_build() {
printf 'bound: %s\n' "$sid"

if "$SCRIPT_DIR/fm-procevent.sh" list | awk 'NR > 1 { print $1 }' | grep -Fxq "$sid"; then
state_override=${FM_STATE_OVERRIDE:-$FM_HOME/state}
FM_HOME="$FM_HOME" FM_STATE_OVERRIDE="$state_override" \
"$SCRIPT_DIR/fm-lavish-session.sh" register-auto "$board" home >/dev/null \
|| fail "cannot refresh the board Lavish ownership ledger"
printf 'already-armed: %s\n' "$sid"
else
"$SCRIPT_DIR/fm-procevent-lavish.sh" arm "$board" >/dev/null \
"$SCRIPT_DIR/fm-procevent-lavish.sh" arm "$board" --task-id home >/dev/null \
|| fail "cannot arm the board as a process-event source"
printf 'armed: %s\n' "$sid"
fi
Expand Down
23 changes: 23 additions & 0 deletions bin/fm-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,29 @@ detect_local_config() {
echo "BOOTSTRAP_INFO: tasks-axi available"
fi
detect_home_summary_publication
detect_lavish_registry
}

# Lavish's registry is historical state, not a live-connection count.
# This read-only startup diagnostic stays silent below the 20-session target,
# reports a non-actionable fact from 20 through 49, and emits one actionable
# warning from 50 upward.
detect_lavish_registry() {
local lavish_state summary open
lavish_state="${FM_LAVISH_STATE_FILE:-${LAVISH_AXI_STATE_DIR:-$HOME/.lavish-axi}/state.json}"
[ -f "$lavish_state" ] && [ ! -L "$lavish_state" ] || return 0
summary=$(FM_HOME="$FM_HOME" FM_LAVISH_STATE_FILE="$lavish_state" \
"$SCRIPT_DIR/fm-lavish-audit.sh" summary 2>/dev/null) || {
echo "LAVISH_REGISTRY_WARNING: registry audit failed; run bin/fm-lavish-audit.sh audit"
return 0
}
open=$(printf '%s\n' "$summary" | sed -n 's/.* registry rows: .* open=\([0-9][0-9]*\).*/\1/p')
case "$open" in ''|*[!0-9]*) echo "LAVISH_REGISTRY_WARNING: registry count was unreadable; run bin/fm-lavish-audit.sh audit"; return 0 ;; esac
if [ "$open" -ge 50 ]; then
printf 'LAVISH_REGISTRY_WARNING: %s; these are historical registry rows, not live connections; run bin/fm-lavish-audit.sh audit\n' "$summary"
elif [ "$open" -ge 20 ]; then
printf 'BOOTSTRAP_INFO: %s; these are historical registry rows, not live connections\n' "$summary"
fi
}

# This home's ledger publication is deliberately best-effort: every lifecycle
Expand Down
Loading
Loading