Commit Graph
3849 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 489c415fd9 huskies: regen source-map.json 2026-07-16 13:19:20 +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 1a15347b02 huskies: merge 1165 refactor Upgrade matrix-sdk 0.17 to 0.18 2026-07-16 05:14:46 +00:00
Huskies Agent a4bf11dbc1 huskies: merge 1166 refactor Upgrade ed25519-dalek 2 to 3 2026-07-16 01:08:34 +00:00
Huskies Agent 182771192b huskies: merge 1168 refactor Upgrade tokio-tungstenite 0.29 to 0.30 2026-07-16 00:53:47 +00: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 ca05bd7224 huskies: merge 1164 refactor Lockfile refresh + sqlx alpha-to-stable 2026-07-16 00:13:38 +00:00
Huskies Agent aa977482db huskies: regen source-map.json 2026-07-16 00:03:44 +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 83f941b77e Revert /app/target binary fallback in entrypoint
Superseded: the running fleet was created by `new project` (no /app
mount), and the one-way upgrade path now replaces the binary at its
canonical install location (/opt/huskies/bin/huskies) directly, so the
entrypoint needs no fallback logic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019fHdm92yjvguPi2LiXfLB9
2026-07-15 16:28:32 +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
Huskies Agent 16d4294f08 huskies: regen source-map.json 2026-06-29 19:38:13 +00:00
Huskies Agent c733fb2bf9 huskies: merge 1162 refactor Update workspace Cargo.toml dependencies to latest compatible versions 2026-06-29 19:38:13 +00: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 8285a98f80 huskies: regen source-map.json 2026-05-20 01:18:59 +00: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 7be3bf1dbf huskies: regen source-map.json 2026-05-20 00:42:25 +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 a3ac09f8a3 huskies: regen source-map.json 2026-05-20 00:23:44 +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 0c207981e9 huskies: regen source-map.json 2026-05-19 23:54:05 +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 v0.13.0 2026-05-20 00:00:16 +01:00