Commit Graph
1169 Commits
Author SHA1 Message Date
Huskies Agent 0ac68afa4c huskies: merge 1173 story Identity-aware fleet checks: cryptographic node identity in upgrade and health probes 2026-07-16 13:26:03 +00:00
Huskies Agent 18b065f77a huskies: merge 1163 story Replace perm_rx lock-as-presence-signal with a permission router 2026-07-16 13:19:20 +00:00
Huskies Agent 6f8a8ffd87 huskies: merge 1175 bug Flaky tests intermittently fail merge gates 2026-07-16 13:03:05 +00:00
TimmyandClaude Fable 5 6a1ee8377d docs: update stale libsqlite3-sys pin comment for sqlx 0.9 stable
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:46:26 +01:00
Huskies Agent a464febdcb huskies: merge 1174 story Gateway startup announcement reports version and model 2026-07-16 10:11:55 +00:00
Huskies Agent 8ae2eaaad3 huskies: merge 1160 bug Chat bot crash-loops on poisoned Claude Code session resume 2026-07-16 09:51:44 +00:00
Huskies Agent 23f2934e1f huskies: merge 1172 story Add Docker log rotation to project container launch args 2026-07-16 09:44:48 +00:00
Huskies Agent 69df921856 huskies: merge 1170 bug Full tokio runtime stall after unblock → merge auto-assign 2026-07-16 09:10:46 +00:00
TimmyandClaude Fable 5 f73689cfd8 Fix CRDT self-deadlock: read_llm_session re-locked the state mutex
read_llm_session acquired the CRDT_STATE mutex, then called
extract_llm_session_view while holding the guard — which called
our_node_id(), which locks the same non-reentrant std::sync::Mutex.
The thread deadlocks itself and parks forever HOLDING the lock; every
other CRDT user then queues behind it. With light traffic that's a
partial wedge (MCP `show`/content reads hang while /health stays
green); during a CRDT-write burst (unblock → auto-assign) enough
tasks pile up to pin every tokio worker: liveness heartbeat stops,
/health dies, full sled freeze. Root cause of bug 1170's repeated
sled freezes, confirmed by live gdb capture: thread parked in
lock_contended at presence::our_node_id ← read_llm_session ←
event_matches_persona, with all other threads queued on CRDT reads.

Fix: extract_llm_session_view now takes local_sled_id as a parameter;
read_llm_session computes it from the guard it already holds. The
trigger path (event_matches_persona on persona-subscribed WS events)
explains the raciness — it needs a chat/persona event racing a
pipeline transition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-16 09:46:36 +01:00
Huskies Agent 0a53c1ff0a huskies: merge 1167 refactor Upgrade garde 0.22 to 0.23 2026-07-16 00:38:34 +00:00
Huskies Agent e67eff17ad huskies: merge 1158 story Reject boilerplate user stories at save time 2026-07-16 00:03:44 +00:00
TimmyandClaude Fable 5 6cceec9c26 Disable CRDT debug logging in default features — fixes runtime stalls
logging-list/logging-json were in bft-json-crdt's default feature set,
so every production build printed multi-KB debug dumps on every CRDT
op — executed INSIDE the global CRDT_STATE mutex. A stdout write that
stalls while holding that lock blocks every task touching the CRDT
(tick loop, watchers, MCP, RPC), each one pinning an OS worker thread
until the tokio pool is exhausted: liveness heartbeat stops, /health
dies, zero CPU. This is the mechanism behind bug 1170 (two full-sled
freezes on huskies-server, both seconds after a CRDT write burst, the
second insert's dump truncated mid-print in the log).

The features remain available for CRDT debugging via explicit opt-in.

Also fixes a latent race in persist_tx_send_success_emits_no_warn:
it counted [crdt_persist] warns in the process-global log buffer,
which parallel tests also write to; the debug prints had been acting
as an accidental serializer. Now filters for its own story id.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 18:37:47 +01:00
TimmyandClaude Fable 5 be0c88c801 Pre-check binary writability before accepting an upgrade request
/api/upgrade now verifies the target can be replaced (create + remove
the swap's tmp file) before returning 202. A sled that cannot write
its own binary — e.g. a container predating the /opt/huskies/bin
layout — fails phase 1 of `upgrade all` loudly instead of returning
202, staying healthy, and silently remaining on the old version, which
is exactly what happened on the first fleet deploy.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 17:53:56 +01:00
TimmyandClaude Fable 5 ba0a38d403 Fix WS deadlock: never block on perm_rx in the chat handler
Since story 884 the Matrix permission listener (and the sled uplink,
when configured) hold services.perm_rx for the process lifetime. The
WS chat handler's blocking `lock().await` on that same mutex therefore
parked the entire WS connection loop forever on StartChat: chat_fut was
never polled, RPC frames on the socket were never answered, and
everything queued behind the dispatcher's serial session lock —
wedging /mcp and /rpc while /health stayed green.

Use try_lock instead: if another task already owns permission routing,
run the chat without the local permission-forwarding select arm (a
pending future keeps the select shape unchanged).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 17:17:24 +01:00
TimmyandClaude Fable 5 01b24ff2ae Drop the drain check from upgrade — agent death is routine
Agents die all the time; the pipeline's retry machinery re-queues
their work. Skipping busy sleds just created version skew and manual
retries for no real protection. `upgrade all` now sweeps every sled
unconditionally.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:54:55 +01:00
TimmyandClaude Fable 5 f39c4b7c4b Remove all alternate update paths — fleet redeploy is release + upgrade all
Killed:
- rebuild_and_restart (in-container cargo self-compile): the MCP tool,
  the `rebuild` chat command in all four transports, the web-ui bot
  command, and the underlying function. This was the path that caused
  the exec() deadlocks.
- upgrade_sled gateway MCP tool: second entry point to sled upgrades,
  defaulted to serving the gateway's own macOS binary to Linux sleds.
- GET /api/huskies-binary (both sled and gateway route trees): served
  current_exe(), wrong platform when the gateway is macOS. Superseded
  by /api/artifacts/ which now also serves on the gateway route tree.
- `huskies upgrade` CLI subcommand and --source flag: third way of
  doing the same download-and-replace. Escape hatch for a bricked sled
  is `docker cp` + restart.

Kept, distinct jobs: `project-rebuild` (container/image updates),
`rebuild gateway` + script/local-release (gateway self-update).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:46:11 +01:00
TimmyandClaude Fable 5 e8253a06b7 Add release chat command — build sled binary and publish artifact
Finds the registered project carrying the huskies source tree, runs
`cargo build --release` inside its container (dedicated
CARGO_TARGET_DIR=target/sled-release so container builds stop
clobbering host target/release), then atomically publishes the binary
to ~/.huskies/artifacts/ with a .hash sidecar for convergence checks.

Full fleet redeploy is now chat-only: `release` then `upgrade all` —
no laptop access needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:27:32 +01:00
TimmyandClaude Fable 5 18ba57a7b0 Add upgrade all chat command with drain check and convergence verify
- `upgrade all` sweeps every registered sled in sequence, streaming
  per-sled phase markers and reporting a summary.
- Binary source is now the gateway's own artifact store via
  host.docker.internal (was: unresolvable `gateway` hostname serving
  the gateway's macOS binary to Linux sleds — would have bricked them).
- Sleds with active claude processes are skipped, never killed.
- After reconnect, /api/version git_hash is compared against the
  published artifact's .hash sidecar; divergence is reported loudly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:22:11 +01:00
TimmyandClaude Fable 5 07b9e1605d Serve sled binary artifacts from ~/.huskies/artifacts/
GET /api/artifacts/:filename with filename validation (no path
components, no dotfiles). Sleds only ever download binaries from their
own gateway; this endpoint is where the gateway serves them from,
replacing the current_exe()-based /api/huskies-binary which serves the
gateway's own (macOS) binary — wrong platform for Linux sleds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:12:00 +01:00
TimmyandClaude Fable 5 4d22171d16 Install sled binary in huskies-owned dir so upgrades work without root
/opt/huskies/bin/huskies (chowned to the huskies user) with a symlink
from /usr/local/bin/huskies. Atomic replace needs write permission on
the directory for the tmp-write + rename, which root-owned
/usr/local/bin can't provide to the server process.

resolve_target_path() now prefers /opt/huskies/bin/huskies over
current_exe(), which can point at a stale location (e.g.
/workspace/target/release/huskies after a historical in-container
rebuild) that the entrypoint would never launch after a restart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:06:31 +01:00
TimmyandClaude Fable 5 a1ae532c6e Add /api/version endpoint for upgrade convergence checks
Reports crate version + compile-time BUILD_GIT_HASH as JSON. The
gateway will poll this after `upgrade all` to verify each sled is
actually running the published artifact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:03:49 +01:00
Timmy 2a7db16a77 Fixed exec bug 2026-07-15 14:55:27 +01:00
TimmyandClaude Opus 4.6 549e0349d7 Fix rebuild_and_restart in Docker project containers
CARGO_MANIFEST_DIR is baked at image build time as /app/server, but
project containers (Dockerfile.base) don't copy /app — the source is
bind-mounted at /workspace instead. Fall back to project_root when
the compile-time path doesn't exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-07-14 18:42:55 +01:00
Timmy 4c965c73b2 Added CRDT snapshotting 2026-06-29 20:11:52 +01:00
Timmy 3342d129c2 Unreachable container times out gracefully 2026-06-29 19:22:47 +01:00
Timmy 32646c6256 Catching a docker rm problem 2026-06-29 18:27:50 +01:00
Timmy 0a0ab65908 Adding doc comments. 2026-06-29 17:02:17 +01:00
Timmy feb35ddd10 Converted all external tool calling to async 2026-06-29 16:59:54 +01:00
Timmy 75f41088b1 Dealing with bot failures 2026-06-29 15:34:14 +01:00
Timmy b662a7da95 Stack detection fix 2026-06-29 13:14:06 +01:00
Timmy 146205c83b Added docs comment 2026-06-29 12:45:25 +01:00
Timmy 705f5bcc89 Adding show story mcp 2026-06-29 12:42:45 +01:00
dave 2fb935e726 huskies: merge 1156 story Periodic liveness tick so runtime freezes have a precise timestamp 2026-05-20 01:18:59 +00:00
dave 2a5359051e huskies: merge 1154 story Extend gateway_health with a relay-working signal — is each sled actually delivering events? 2026-05-20 00:42:24 +00:00
dave 846b3e1b4c huskies: merge 1153 story huskies projects chat command — list every registered project with port and status 2026-05-20 00:23:44 +00:00
dave e7456d3391 huskies: merge 1155 story Bracket logging around install_pre_commit_hook to diagnose bug 1151 freezes 2026-05-19 23:54:05 +00:00
Timmy 5bca1f6cec Bump version to 0.13.0 2026-05-20 00:00:16 +01:00
dave 9a286315a3 huskies: merge 1149 story huskies health chat command — surface gateway, sled, matrix, creds, and build-hash status 2026-05-19 20:11:55 +00:00
dave 5d0801854c huskies: merge 1146 story Matrix bot auto-recovers from M_UNKNOWN_TOKEN by re-logging in from bot.toml password 2026-05-19 19:40:53 +00:00
dave 2593b36072 huskies: merge 1148 story Per-sled upgrade chat command using huskies upgrade (1138), serial-locked 2026-05-19 18:39:40 +00:00
dave be7bdf8304 huskies: merge 1147 story One-active-gateway invariant via pidfile+flock — prevent double-gateway during restarts 2026-05-19 18:34:41 +00:00
dave 918f18c200 huskies: merge 1151 bug install_pre_commit_hook blocks the tokio executor — sync std::process::Command::output() in an async path stalls worktree-create-sub 2026-05-19 18:19:58 +00:00
dave de638603cd huskies: merge 1144 story Gateway trampoline-restart: detached helper survives the gateway's own death 2026-05-19 18:13:26 +00:00
dave 9a5b6f4d92 huskies: merge 1152 story Set HUSKIES_GATEWAY_URL on every sled container so 1136's relay actually spawns 2026-05-19 17:55:37 +00:00
dave f8ff63af0e huskies: merge 1142 story Force coder agents through MCP-validated Edit/Write/Bash to prevent writes to master worktree 2026-05-18 16:57:58 +00:00
dave fb4e52dd09 huskies: merge 1143 story Decouple LLM environmental awareness from chat transport — persona-keyed sessions and a real-time event subscription 2026-05-18 16:52:45 +00:00
dave b1dec36e1c huskies: merge 1140 story One-shot project-rebuild chat command: rebuild image, swap container, reconnect, preserve state 2026-05-18 14:55:31 +00:00
dave 95c0aafb68 huskies: merge 1141 story Convert work-item type between spike/story/bug/refactor (or at least spike→story) 2026-05-18 14:50:00 +00:00
dave 55badc1e08 huskies: merge 1139 story Per-project Dockerfile fragment so agents can extend their own sled image 2026-05-18 13:54:44 +00:00
dave 0ec5c05de8 huskies: merge 1138 story In-container huskies self-update — huskies upgrade pulls a fresh binary without docker rebuild 2026-05-18 13:33:50 +00:00