fix(skills): resolve headless layout overflow, reconcile SKILLS_DIR scope, and prompt-injection fast-path gating (B-19)

This commit is contained in:
2026-08-23 17:49:45 +09:00
parent f133e52863
commit 82eecfda24
5 changed files with 262 additions and 13 deletions
+12 -8
View File
@@ -446,7 +446,10 @@ try:
if anchor:
w = anchor.get('width', 0)
h = anchor.get('height', 0)
if w // 2 >= min_cols:
if w <= 0 or h <= 0:
# Headless or detached session with unmeasured/zero dimensions
print('right')
elif w // 2 >= min_cols:
print('right')
elif h // 2 >= min_rows:
print('down')
@@ -1632,13 +1635,6 @@ _pane_dialog_open() {
send_keys_safe() {
local sess="$1" text="$2" job_id="${3:-adhoc}"
local agent_target
agent_target=$(_sanitize_herdr_agent_name "$sess")
# Native herdr 0.8+ fast path: agent prompt handles atomic text + enter submission
if _sks_herdr agent prompt "$agent_target" "$text" >/dev/null 2>&1 || _sks_herdr agent prompt "$sess" "$text" >/dev/null 2>&1; then
return 0
fi
local marker pre_submit deadline try
# Verification token: last 24 *characters* (not bytes — `tail -c` can split a
# multi-byte UTF-8 char, e.g. Korean, producing a marker that can never match
@@ -1668,6 +1664,14 @@ send_keys_safe() {
sleep 2
done
local agent_target
agent_target=$(_sanitize_herdr_agent_name "$sess")
# Native herdr 0.8+ fast path: agent prompt handles atomic text + enter submission
# Gated behind quiescence and dialog checks; returns 0 on RPC success to prevent duplicate input
if _sks_herdr agent prompt "$agent_target" "$text" >/dev/null 2>&1 || _sks_herdr agent prompt "$sess" "$text" >/dev/null 2>&1; then
return 0
fi
local sks_buf="sks_${sess}_${job_id}_$$_${RANDOM}_$(date +%s%N 2>/dev/null || date +%s)"
_sks_herdr set-buffer -b "$sks_buf" "$text"
_sks_herdr paste-buffer -b "$sks_buf" -t "$sess"
@@ -325,6 +325,11 @@ from lib_py.verify_session import verify_session_uuid, workspace_key
yaml_path = os.environ['YAML_PATH']
home = os.environ['HOME_DIR']
skills_dir = os.environ.get('SKILLS_DIR', '')
if not skills_dir:
_ws_root = os.environ.get('WORKSPACE_ROOT')
if not _ws_root:
_ws_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../..'))
skills_dir = os.path.join(_ws_root, '.agents/skills')
claude_project_dir = os.environ.get('CLAUDE_PROJECT_DIR', f"{home}/.claude/projects")
now_iso = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
@@ -806,7 +811,7 @@ if not actions:
PYEOF
if [ "$DRY_RUN" = "1" ]; then
printf '%s' "$RECON_SRC" | LIB_SH="$LIB_SH" env_python "$AGENT_SESSIONS_YAML"
printf '%s' "$RECON_SRC" | SKILLS_DIR="$SKILLS_DIR" LIB_SH="$LIB_SH" env_python "$AGENT_SESSIONS_YAML"
else
printf '%s' "$RECON_SRC" | LIB_SH="$LIB_SH" atomic_dump_yaml "$AGENT_SESSIONS_YAML"
printf '%s' "$RECON_SRC" | SKILLS_DIR="$SKILLS_DIR" LIB_SH="$LIB_SH" atomic_dump_yaml "$AGENT_SESSIONS_YAML"
fi