perf(skills): optimize sleeps and modularize duplication with multi-agent consensus PASS

- OP-1: Implement reactive _wait_session_gone in lib.sh and stop_session.sh with set -e || true guard
- OP-2: Event-driven MQTT subscribe handshake with sub_pid liveness in delegate-job
- OP-3: Replace CPU time.sleep(0.5) spin with threading.Event wait in reconcile.sh
- OP-4: Define mam_tmux dispatcher targeting resolved _REAL_TMUX_PATH to prevent recursion
- OP-6 & OP-7: Add token variables and bash version source check in lib.sh
- Integrate approved optimization plan and PASS review reports from all agents
This commit is contained in:
2026-07-11 10:08:41 +09:00
parent 25de01eaad
commit 7eeb4b709a
11 changed files with 1148 additions and 24 deletions
+33 -14
View File
@@ -14,10 +14,18 @@
# HARD RULE: the agent-sessions.yaml file is only ever written through
# atomic_dump_yaml. Never `open(yaml_path, 'w')` anywhere else.
if [ -z "${BASH_VERSION:-}" ]; then
echo "ERROR: lib.sh must be executed/sourced from bash (foreign shell detected)" >&2
return 1 2>/dev/null || exit 1
fi
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE_ROOT="$(cd "$SKILL_DIR/../.." && pwd)"
AGENT_SESSIONS_YAML="${AGENT_SESSIONS_YAML:-$WORKSPACE_ROOT/.mam/agent-sessions.yaml}"
# Central TUI dialog and readiness validation tokens (OP-6)
_MAM_DIALOG_TOKENS='Do you trust the files|Yes, proceed|No, exit|Allow this|Press Enter to continue|browser to authenticate|Use arrow keys|Esc to cancel'
_MAM_READY_TOKENS_CLAUDE='Anthropic|Assistant|Chat|Welcome|projects'
# Workspace-relative defaults with environment overrides (Phase Z)
HOME_DIR="${HOME_DIR:-$HOME}"
CLAUDE_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$HOME/.claude/projects}"
@@ -86,13 +94,18 @@ EOF
fi
}
mam_tmux() {
_resolve_real_tmux_path
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
"$_REAL_TMUX_PATH" -L "$TMUX_SERVER_NAME" "$@"
else
"$_REAL_TMUX_PATH" "$@"
fi
}
_tmux() {
_init_tmux_isolation
if [ -z "${TMUX_SERVER_NAME:-}" ] || [ "$TMUX_SERVER_NAME" = "default" ]; then
"$_REAL_TMUX_PATH" "$@"
else
"$_REAL_TMUX_PATH" -L "$TMUX_SERVER_NAME" "$@"
fi
mam_tmux "$@"
}
tmux() {
@@ -1055,7 +1068,7 @@ wait_for_tui_ready() {
if [ -n "$content" ]; then
case "$agent" in
claude)
if echo "$content" | grep -E -q "Anthropic|Assistant|Chat|Welcome|projects" 2>/dev/null; then
if echo "$content" | grep -E -q "$_MAM_READY_TOKENS_CLAUDE" 2>/dev/null; then
echo "✅ Claude TUI detected ready."
return 0
fi
@@ -1103,11 +1116,7 @@ inject_instructions() {
# Server-aware tmux (same isolation rule as inject_instructions).
_sks_tmux() {
if [ -n "${TMUX_SERVER_NAME:-}" ] && [ "$TMUX_SERVER_NAME" != "default" ]; then
tmux -L "$TMUX_SERVER_NAME" "$@"
else
tmux "$@"
fi
mam_tmux "$@"
}
_pane_capture() { _sks_tmux capture-pane -p -t "$1" 2>/dev/null || echo ""; }
@@ -1116,6 +1125,17 @@ _pane_capture() { _sks_tmux capture-pane -p -t "$1" 2>/dev/null || echo ""; }
# blank rows; window on non-blank lines or top-anchored dialogs are invisible.
_pane_tail() { _pane_capture "$1" | grep -v '^[[:space:]]*$' | tail -n "${2:-20}"; }
# _wait_session_gone <sess> [max_sec=5]
# Reactive loop to wait until a tmux session goes away (happy path returns early).
_wait_session_gone() {
local sess="$1" max="${2:-5}" i
for ((i = 0; i < max * 4; i++)); do
_sks_tmux has-session -t "$sess" 2>/dev/null || return 0
sleep 0.25
done
return 1
}
# _pane_quiescent <sess> [tries=20] [interval=0.5]
# Renderer settled = two consecutive identical non-empty captures.
# Defeats RC-A (Blessed/Ink renderer bottleneck) without a magic fixed sleep.
@@ -1135,8 +1155,7 @@ _pane_quiescent() {
# only (dialogs render near the input area; conversation text above must not
# trigger this). Tokens must NOT appear on normal idle prompt screens.
_pane_dialog_open() {
_pane_tail "$1" 20 | grep -Eq \
'Do you trust the files|Yes, proceed|No, exit|Allow this|Press Enter to continue|browser to authenticate|Use arrow keys|Esc to cancel'
_pane_tail "$1" 20 | grep -Eq "$_MAM_DIALOG_TOKENS"
}
# send_keys_safe <sess> <text> [job_id]
@@ -1202,7 +1221,7 @@ handle_startup_dialogs() {
_sks_tmux send-keys -t "$sess" Down
sleep 0.3
_sks_tmux send-keys -t "$sess" Enter
elif printf '%s\n' "$pane" | grep -Eq 'Anthropic|Assistant|Chat|Welcome|projects'; then
elif printf '%s\n' "$pane" | grep -Eq "$_MAM_READY_TOKENS_CLAUDE"; then
return 0
fi
sleep 2
@@ -116,7 +116,23 @@ cmd_submit() {
>"$logf" 2>&1 &
local sub_pid=$!
echo "subscriber pid: $sub_pid (log: $logf)"
sleep 1 # give the subscriber time to CONNACK + SUBSCRIBE before the agent runs
# Wait for the subscriber to CONNACK + SUBSCRIBE (reactive handshake)
local sub_ready=0
for ((i = 0; i < 25; i++)); do
if kill -0 "$sub_pid" 2>/dev/null; then
if grep -q '^SUBSCRIBED ' "$logf" 2>/dev/null; then
sub_ready=1
break
fi
else
echo "ERROR: subscriber died early (pid=$sub_pid, check $logf)" >&2
exit 1
fi
sleep 0.2
done
if [ "$sub_ready" -ne 1 ]; then
echo "WARNING: subscriber subscribe handshake timed out — falling back to proceed" >&2
fi
# 3) run the agent (or print the command for dry-run / missing binary)
local pub="$PY $SCRIPT_DIR/scripts/publish_event.py --registry-dir $REGISTRY_DIR --job $JOB_ID"
@@ -202,7 +218,23 @@ Task: $PROMPT"
>"$logf" 2>&1 &
local sub_pid=$!
echo "subscriber pid: $sub_pid (log: $logf)"
sleep 1
# Wait for the subscriber to CONNACK + SUBSCRIBE (reactive handshake)
local sub_ready=0
for ((i = 0; i < 25; i++)); do
if kill -0 "$sub_pid" 2>/dev/null; then
if grep -q '^SUBSCRIBED ' "$logf" 2>/dev/null; then
sub_ready=1
break
fi
else
echo "ERROR: subscriber died early (pid=$sub_pid, check $logf)" >&2
exit 1
fi
sleep 0.2
done
if [ "$sub_ready" -ne 1 ]; then
echo "WARNING: subscriber subscribe handshake timed out — falling back to proceed" >&2
fi
# Format instruction block
local pub="$PY $SCRIPT_DIR/scripts/publish_event.py --registry-dir $REGISTRY_DIR --job $JOB_ID"
@@ -185,8 +185,13 @@ def main(argv=None) -> int:
if rc != 0:
logger.warning("broker disconnected (rc=%s); will retry reconnect", reason_code)
def on_subscribe(_c, _u, mid, granted_qos, _props=None):
for topic in subscribed_topics:
print(f"SUBSCRIBED {topic}", flush=True)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.on_subscribe = on_subscribe
client.reconnect_delay_set(min_delay=1, max_delay=16)
mqtt_common.with_retry(
lambda: client.connect(config.host, config.port, config.keepalive),
@@ -239,17 +239,29 @@ if not state['connected']:
client.loop_stop()
sys.exit(3)
import threading
stop_event = threading.Event()
start = time.time()
try:
while True:
now = time.time()
if timeout and (now - start) >= timeout:
print(f"MQTT Monitor: --timeout {timeout}s reached, exiting", flush=True)
wall_left = (timeout - (now - start)) if timeout else None
idle_left = (idle_timeout - (now - state['last_msg'])) if idle_timeout else None
next_timeout = 5.0
if wall_left is not None:
next_timeout = min(next_timeout, wall_left)
if idle_left is not None:
next_timeout = min(next_timeout, idle_left)
if next_timeout <= 0:
if wall_left is not None and wall_left <= 0:
print(f"MQTT Monitor: --timeout {timeout}s reached, exiting", flush=True)
else:
print(f"MQTT Monitor: --idle-timeout {idle_timeout}s reached, exiting", flush=True)
break
if idle_timeout and (now - state['last_msg']) >= idle_timeout:
print(f"MQTT Monitor: --idle-timeout {idle_timeout}s reached, exiting", flush=True)
break
time.sleep(0.5)
stop_event.wait(timeout=next_timeout)
finally:
client.loop_stop()
try:
@@ -190,14 +190,14 @@ graceful_stop() {
esac
echo "graceful: send-keys '$exitkey' to $SESSION_NAME"
send_keys_safe "$SESSION_NAME" "$exitkey" "stop$$" || echo "graceful: safe delivery failed (rc=$?) — falling back to kill chain"
sleep 3
_wait_session_gone "$SESSION_NAME" 5 || true
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "graceful: exited cleanly"
return 0
fi
echo "graceful: still alive → kill-session (SIGTERM)"
tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
sleep 5
_wait_session_gone "$SESSION_NAME" 8 || true
if ! tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
echo "graceful: terminated after kill-session"
return 0