Commit Graph
173 Commits
Author SHA1 Message Date
Huskies Agent 9c61dfa595 huskies: merge 1219 story Add runtime artifacts to the default project scaffold .gitignore 2026-07-18 13:50:49 +00:00
Huskies Agent 71f3fa09c4 huskies: merge 1211 story Deterministic crash notification when the agent PTY dies mid-turn 2026-07-18 11:00:28 +00:00
Huskies Agent 80efb7fcfc huskies: merge 1201 story Chat notification when a new work item is filed 2026-07-17 19:43:27 +00:00
Huskies Agent c1523e8acf huskies: merge 1200 story Low-disk warning: the fleet tells the operator before the disk takes it down 2026-07-17 19:25:52 +00:00
Huskies Agent 0f4b0c9536 huskies: merge 1185 story Bounded auto-retry for GatesFailed merges before requiring human intervention 2026-07-17 12:11:27 +00:00
Huskies Agent a4e2d4bc25 huskies: merge 1177 bug project.toml scaffold puts top-level keys after [[component]] so uncommenting them silently no-ops 2026-07-16 16:13:17 +00:00
dave e82602db77 huskies: merge 1086 story Pipeline+Status split — Step C: migrate auto-assign, subscribers, and lifecycle transitions to read Pipeline + Status 2026-05-15 08:26:39 +00:00
dave f9b140add9 huskies: merge 1073 2026-05-15 00:37:01 +00:00
dave d4db96f709 huskies: merge 1070 2026-05-15 00:20:29 +00:00
dave bb6a6063e8 huskies: merge 1066 2026-05-14 23:45:53 +00:00
dave c7a7cb4281 huskies: merge 997 2026-05-14 11:06:27 +00:00
dave e3f5875b8e huskies: merge 1019 2026-05-14 08:52:38 +00:00
dave 13ab97a615 huskies: merge 1010 2026-05-14 08:12:56 +00:00
dave 29e800da21 huskies: merge 1016 2026-05-13 23:51:07 +00:00
dave 4e007bb770 huskies: merge 1009 2026-05-13 22:55:05 +00:00
dave caed894db9 huskies: merge 988 2026-05-13 17:28:52 +00:00
dave 580480094e huskies: merge 984 2026-05-13 16:47:51 +00:00
dave 77dc09668c huskies: merge 960 2026-05-13 13:24:15 +00:00
dave 4a8ed4348b huskies: merge 950 2026-05-13 08:46:22 +00:00
dave a7840ea4b0 huskies: merge 946 2026-05-13 08:00:49 +00:00
dave 9ce5a8df0c huskies: merge 945 2026-05-13 06:09:34 +00:00
dave 9ccbdff19f huskies: merge 952 2026-05-13 05:43:22 +00:00
TimmyandClaude Opus 4.7 d78dd9e8f9 feat(934): typed Stage enum replaces directory-string state model
The state machine's `Stage` enum becomes the source of truth for pipeline
state. Six stages of work land together:

  1. Clean wire vocabulary (`coding`, `merge`, `merge_failure`, ...) replaces
     legacy directory-style strings (`2_current`, `4_merge`, ...) on the wire.
     `Stage::from_dir` accepted both during deployment; new writes always
     emit the clean form via `stage_dir_name`. Lexicographic `dir >= "5_done"`
     checks in lifecycle.rs become typed `matches!` checks since the new
     vocabulary doesn't sort in pipeline order.
  2. `crdt_state::write_item` takes typed `&Stage`, serialising via
     `stage_dir_name` at the CRDT boundary. `#[cfg(test)] write_item_str`
     parses legacy strings for test fixtures.
  3. `WorkItem::stage()` returns typed `crdt_state::Stage`; `stage_str()`
     is gone from the public API. Projection dispatches on the typed enum.
  4. `frozen` becomes an orthogonal CRDT register. `Stage::Frozen` and
     `PipelineEvent::Freeze`/`Unfreeze` are removed; `transition_to_frozen`/
     `unfrozen` set the flag directly without touching the stage register.
  5. Watcher sweep and `tool_update_story`'s `blocked` setter route through
     `apply_transition` so the typed transition table validates every
     stage change. `update_story` gains a `frozen` field for symmetry.
  6. One-shot startup migration rewrites pre-934 directory-style stage
     registers (and sets `frozen=true` on items previously at `7_frozen`).
     `Stage::from_dir` drops legacy aliases. The db boundary keeps a small
     normaliser so callers with legacy strings (MCP, tests) still work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 22:31:59 +01:00
TimmyandClaude Opus 4.7 69d91d7707 feat(929): delete db/yaml_legacy.rs entirely — CRDT is the sole source of truth
Final 929 sweep: every YAML-shaped helper is gone. No production code
parses or writes YAML front matter anywhere.

Surface removed:
- db/yaml_legacy.rs (FrontMatter/StoryMetadata structs, parse_front_matter,
  set_front_matter_field, yaml_residue marker) — file deleted.
- ItemMeta::from_yaml — deleted; callers pass typed ItemMeta::named(...) or
  ItemMeta::default() and use typed CRDT setters (set_depends_on,
  set_blocked, set_retry_count, set_agent, set_qa_mode, set_review_hold,
  set_item_type, set_epic, set_mergemaster_attempted) for the rest.
- write_coverage_baseline_to_story_file + read_coverage_percent_from_json —
  the coverage_baseline YAML field was write-only (nothing read it back);
  removed along with its caller in agent_tools/lifecycle.rs.
- update_story_in_file's generic `front_matter` HashMap parameter —
  tool_update_story now intercepts every known field name and routes it
  to a typed CRDT setter; unknown keys are rejected with an explicit error
  pointing at the typed setters. The function only takes user_story /
  description sections now.
- All 117 ItemMeta::from_yaml callsites migrated. Where tests previously
  passed a YAML-shaped content blob and relied on the helper to extract
  name/depends_on/blocked/agent/qa, they now pass:
    write_item_with_content(id, stage, content, ItemMeta::named("Foo"))
    crate::crdt_state::set_depends_on(id, &[...])    // when needed
    crate::crdt_state::set_blocked(id, true)         // when needed
    crate::crdt_state::set_agent(id, Some("..."))    // when needed
- write_story_content + write_story_file (test helper) now take an
  explicit `name: Option<&str>` instead of parsing it from content.
- db::ops::move_item_stage stopped re-parsing YAML on every stage
  transition; metadata is read straight from the CRDT view when mirroring
  the row into SQLite.

New CRDT setters added for symmetry:
- crdt_state::set_name (mirrors set_agent — explicit name updates).

cargo fmt --check, clippy --all-targets -- -D warnings, and the
2830-test suite all pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:55:25 +01:00
TimmyandClaude Opus 4.7 7660a460a5 wip(929): stage 9 — drop FS-archived-deps scan; story_tools/story/create.rs reads CRDT
io/watcher and io/watcher/sweep were already CRDT-only — the watcher only
watches .huskies/{project,agents}.toml, work-item events come from CRDT
subscribe — so the remaining FS shadow reader was the bug-503 archived-dep
warning in story_tools/story/create.rs (via check_archived_deps_from_list,
which scanned .huskies/work/6_archived/). Migrate that call to the
CRDT-direct `dep_is_archived_crdt`. Drop the now-unused helper and the
four dead imports in bug/spike/refactor/criteria.rs that referenced it.

io/story_metadata/deps.rs is reduced to a module-level comment pointing
callers at the crdt_state helpers; nothing in io/ now scans the FS shadow
tree.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 19:25:47 +01:00
TimmyandClaude Opus 4.7 6e704a33b7 wip(929): stage 5 — drop FS-based dep checks and qa-mode parser from io/story_metadata
Migrate the last three callers of the FS-scanning dependency helpers to the
CRDT-direct equivalents and delete the dead helpers:

- agents/pool/auto_assign/story_checks.rs: has_unmet_dependencies and
  check_archived_dependencies now wrap check_unmet_deps_crdt /
  check_archived_deps_crdt directly. Tests rewritten to seed the CRDT.
- http/mcp/story_tools/story/update.rs: bug-503 archived-dep warning now
  reads from CRDT instead of scanning 6_archived.
- agents/pool/pipeline/advance/helpers.rs: resolve_qa_mode_from_store is
  CRDT-only (the FS fallback for content-store-empty stories is gone).
- io/story_metadata/parser.rs: resolve_qa_mode_from_content removed.
- io/story_metadata/deps.rs: check_unmet_deps and dep_is_done deleted,
  along with the unused check_unmet_deps_from_list helper.
- io/story_metadata/mod.rs: re-exports trimmed accordingly.

check_archived_deps_from_list survives because story-creation still calls
it before the CRDT entry exists (used from story_tools/story/create.rs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 19:14:54 +01:00
dave 148ce37beb huskies: merge 891 2026-05-12 17:09:01 +00:00
TimmyandClaude Opus 4.7 cd12cb5e2c fix: Bash(:*) is invalid; use unconstrained Bash instead
Claude Code rejects "Bash(:*)" with "Prefix cannot be empty before :*" —
the rule is silently skipped, which since 5b48f0d0 left no Bash entry
in the allowlist at all. Every coder agent's Bash call has been
auto-denying since that commit landed (~840 of 1.4k denials in the sled
log).

The canonical form for "allow all bash commands" is the tool name alone:
"Bash" (no parens). Apply it in three places that 5b48f0d0 touched:
  - .claude/settings.json (project root, inherited by new worktrees)
  - server/src/io/fs/scaffold/templates.rs (huskies init template)
  - server/src/io/fs/scaffold/tests.rs (assertion now checks "Bash")

The gateway settings.json at ~/Desktop/huskies/.claude/settings.json and
the four live worktrees (810, 888, 890, 894) were also corrected — not
in this commit since they live outside the repo.

Surfaced via /doctor; reported with rule "Invalid permission rule
Bash(:*) was skipped: Prefix cannot be empty before :*".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:46:34 +01:00
dave 9be438e6d3 huskies: merge 865 2026-05-08 14:29:06 +00:00
TimmyandClaude Opus 4.7 5b48f0d051 fix(897): broaden Bash allowlist to wildcard to stop coders stalling on uncommon commands
The per-command allowlist (Bash(cargo:*), Bash(git:*), …) misses any tool
a coder agent reaches for outside the curated set — ./script/*, make, curl,
jq, docker, test, [, etc. Each miss hits prompt_permission, which auto-denies
on the sled because no listener holds perm_rx (the matrix bot lives in the
gateway). 1,377 such denies in the sled log over the past week, accounting
for most of the recent throughput slowdown.

Replace the curated list with a single Bash(:*) wildcard in:
  - .claude/settings.json (project root, picked up on git worktree add)
  - server/src/io/fs/scaffold/templates.rs (used only by huskies init when
    no .claude/settings.json already exists)

Update scaffold/tests.rs to assert the wildcard rather than a fixed set
of patterns; the per-command gate offered no real safety in this trusted
single-user deployment, since the prompt was never going to reach a human
anyway (that's the bug).

Stopgap until story 898 lands the proper sled→gateway permission
forwarding — at which point the wildcard can be narrowed back if desired.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 15:14:03 +01:00
dave 61cf7684de huskies: merge 864 2026-04-30 22:27:51 +00:00
dave 0e4a970e3a fix(883): canonical Bash(:*) syntax in scaffold settings template
Claude Code 2.1.123+ honours wildcard Bash allowlist patterns only in
the canonical form `Bash(cmd:*)`. The space form `Bash(cmd *)` falls
through to prompt_permission and gets auto-denied in agent mode,
breaking spawned coders.

- Rewrite all `Bash(cmd *)` patterns in STORY_KIT_CLAUDE_SETTINGS to
  the colon form.
- Replace separate `Bash(cargo build:*)` / `Bash(cargo check:*)` with
  a single `Bash(cargo:*)`.
- Add commonly-needed patterns: python3, node, npm, which, sed, awk,
  rg, diff, sort, uniq.
- Patch the live project-root .claude/settings.json so the running
  system picks up the fix immediately (rebuilt scaffolds will match).
- Add regression test asserting no `Bash(... *)` patterns survive and
  required common commands are present.
2026-04-30 13:44:51 +00:00
TimmyandClaude Opus 4.7 3a9ff5e740 fix(mcp): restore HTTP /mcp endpoint after 855 regression
855 deleted the HTTP /mcp route and pointed agents at ws://...crdt-sync,
but Claude Code's .mcp.json doesn't speak ws:// and the rendezvous WS
never had MCP method handlers wired up — so every spawned Claude Code
agent (gateway-routed and local) booted with zero huskies tools and
died on --permission-prompt-tool=mcp__huskies__prompt_permission.

Restore mcp_post_handler / mcp_get_handler / handle_initialize, re-add
the /mcp route, and revert all three .mcp.json writers to emit
http://localhost:{port}/mcp with explicit "type": "http". Reuses the
already-extracted gateway::jsonrpc types and the surviving
dispatch_tool_call / list_tools surfaces — net add ~140 lines.

Federation work is unaffected: /crdt-sync continues to do CRDT sync,
which is what it was actually doing. MCP-over-WebSocket for cross-LAN
agents was never wired up by 855 and can be done as a proper follow-up
with a regression test that boots a real claude and verifies tool
registration.

Verified end-to-end: /mcp initialize, tools/list (74 tools incl.
prompt_permission), and tools/call all respond correctly from inside
the rebuilt container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 14:03:16 +01:00
dave a796bd933f huskies: merge 879 2026-04-30 00:26:35 +00:00
dave 1d86202abb huskies: merge 868 2026-04-29 23:34:24 +00:00
dave 9a3f60d5d3 huskies: merge 866 2026-04-29 22:47:53 +00:00
dave a49f668b5a huskies: merge 867 2026-04-29 22:17:08 +00:00
dave 7e2f122d36 huskies: merge 880 2026-04-29 21:46:12 +00:00
dave 4d24b5b661 huskies: merge 855 2026-04-29 21:41:03 +00:00
dave a7b1572693 huskies: merge 856 2026-04-29 21:34:58 +00:00
dave 39013be535 huskies: merge 846 2026-04-29 18:24:11 +00:00
dave fc86774618 huskies: merge 857 2026-04-29 17:45:51 +00:00
dave 2655288412 huskies: merge 870 2026-04-29 15:26:57 +00:00
dave f3e4d5d072 huskies: merge 869 2026-04-29 14:58:11 +00:00
dave 11d111360d huskies: merge 858 2026-04-29 10:47:18 +00:00
dave 4ed1fb5110 huskies: merge 854 2026-04-29 09:29:32 +00:00
dave 30dd4b3a0a huskies: merge 796 2026-04-28 16:34:10 +00:00
dave c1a50eab8e huskies: merge 790 2026-04-28 15:16:01 +00:00
dave 36ca8d5e3b huskies: merge 827 2026-04-28 13:01:48 +00:00
dave 3d986a733b huskies: merge 763 2026-04-28 09:42:59 +00:00