review-fix(suppress-audit): skill_usage hub-lock walk, watchdog tick finally, session.create cwd — restore BASE exception semantics

This commit is contained in:
Teknium
2026-09-03 10:00:07 -07:00
parent 474eed838e
commit e7a0f4695b
3 changed files with 27 additions and 18 deletions
+6 -3
View File
@@ -295,11 +295,14 @@ async def _tick_socket_handler(reader: asyncio.StreamReader, writer: asyncio.Str
"""Answer a liveness ping with one byte; never raises. Runs on the gateway loop, so a reply
witnesses loop schedulability; the write is a socket-buffer copy (no fsync), immune to the
stalls that age the heartbeat."""
with contextlib.suppress(Exception):
try:
writer.write(b"1")
await writer.drain()
with contextlib.suppress(Exception):
writer.close()
except Exception:
pass
finally: # close even on CancelledError (BaseException), as on BASE
with contextlib.suppress(Exception):
writer.close()
def _sweep_stale_tick_sockets(own_path: Path) -> None:
+20 -14
View File
@@ -137,25 +137,31 @@ def _read_hub_installed_names() -> Set[str]:
"""Hub-installed names (``.hub/lock.json``) plus the frontmatter name of each in-tree ``install_path``."""
skills_dir = _skills_dir()
lock_path = skills_dir / ".hub" / "lock.json"
if not lock_path.exists():
return set()
# The whole walk sits under one handler (BASE semantics): an OSError anywhere — including the
# per-skill SKILL.md read — logs and yields an empty set rather than a partial one.
try:
# errors="replace": hub descriptions can carry Windows-1252 high bytes; a strict read raises
# UnicodeDecodeError (a ValueError, not caught below) and would 500 the whole /api/skills endpoint.
data = json.loads(lock_path.read_text(encoding="utf-8", errors="replace")) if lock_path.exists() else {}
except (OSError, json.JSONDecodeError) as e:
logger.debug("Failed to read hub lock file: %s", e)
return set()
installed = (data.get("installed") or {}) if isinstance(data, dict) else None
if not isinstance(installed, dict):
return set()
names = {str(k) for k in installed}
paths = (e.get("install_path") for e in installed.values() if isinstance(e, dict))
for install_path in (p for p in paths if isinstance(p, str) and p.strip()):
with suppress(OSError, ValueError): # ValueError: install_path escapes the skills dir
resolved = (skills_dir / install_path).resolve()
resolved.relative_to(skills_dir.resolve())
data = json.loads(lock_path.read_text(encoding="utf-8", errors="replace"))
installed = (data.get("installed") or {}) if isinstance(data, dict) else None
if not isinstance(installed, dict):
return set()
names = {str(k) for k in installed}
paths = (e.get("install_path") for e in installed.values() if isinstance(e, dict))
for install_path in (p for p in paths if isinstance(p, str) and p.strip()):
try: # ValueError: install_path escapes the skills dir
resolved = (skills_dir / install_path).resolve()
resolved.relative_to(skills_dir.resolve())
except (OSError, ValueError):
continue
if (resolved / "SKILL.md").exists():
names.add(_read_skill_name(resolved / "SKILL.md", fallback=resolved.name))
return names
return names
except (OSError, json.JSONDecodeError) as e:
logger.debug("Failed to read hub lock file: %s", e)
return set()
def _prune_builtins_enabled() -> bool:
+1 -1
View File
@@ -301,8 +301,8 @@ def _(rid, params: dict) -> dict:
parent_session_id = _str_param(params, "parent_session_id") or None
# Only an explicitly chosen existing workspace persists as cwd; the launch-dir fallback is "No workspace".
explicit_cwd = False
raw_cwd = _str_param(params, "cwd") # unguarded, as on BASE: only the path check is best-effort
with contextlib.suppress(Exception):
raw_cwd = _str_param(params, "cwd")
explicit_cwd = bool(raw_cwd) and os.path.isdir(os.path.abspath(os.path.expanduser(raw_cwd)))
_enable_gateway_prompts()
# ``profile`` (app-global remote mode): stored so the build and every turn re-bind HERMES_HOME.