Commit Graph

125 Commits

Author SHA1 Message Date
dave fc5481dbe4 huskies: merge 1093 bug Chat dispatcher spawns one Timmy per inbound message — needs coalesce window + per-session serial lock 2026-05-15 12:03:09 +00:00
dave 56179d712e huskies: merge 1078 2026-05-15 01:32:29 +00:00
dave c66016394b huskies: merge 1063 2026-05-14 21:53:56 +00:00
dave 595777f366 huskies: merge 1054 2026-05-14 18:53:07 +00:00
dave 8faf19f3ab huskies: merge 1034 2026-05-14 14:02:21 +00:00
Timmy 8625b9a7fc fix: rust 1.95.0 clippy lints and matrix-sdk 0.17 API changes
Toolchain bump surfaced new lints (derivable_impls,
unnecessary_unwrap, unnecessary_sort_by, while_let_loop,
collapsible_match, unnecessary_option_map_or_else, cmp_owned)
across bft-json-crdt and huskies-server. All fixed mechanically.

Cargo.toml: dropped the no-longer-existing `rustls-tls` matrix-sdk
feature, then chased through the 0.17 API breakage:
- Relation::Reply is now a tuple variant wrapping Reply, not a
  struct variant with `in_reply_to`
- UserIdentifier::UserIdOrLocalpart removed — use
  UserIdentifier::Matrix(MatrixUserIdentifier::new(..))
- SendMessageLikeEventResult no longer exposes event_id directly;
  it's now on the inner `response` field

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 14:48:49 +01:00
dave c353c0a6be huskies: merge 1033 2026-05-14 13:08:43 +00:00
dave c7a7cb4281 huskies: merge 997 2026-05-14 11:06:27 +00:00
dave 4e007bb770 huskies: merge 1009 2026-05-13 22:55:05 +00:00
dave 580480094e huskies: merge 984 2026-05-13 16:47:51 +00:00
dave 184c214c34 huskies: merge 962 2026-05-13 12:05:01 +00:00
dave 8b53e20ca9 huskies: merge 961 2026-05-13 11:27:21 +00:00
dave 396a47d7c2 huskies: merge 957 2026-05-13 10:07:49 +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 7ca5339450 huskies: merge 944 2026-05-13 05:07:28 +00:00
dave 12ae7ec8bb huskies: merge 936 2026-05-12 21:48:39 +00:00
Timmy 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
Timmy 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
dave f9f16d6a14 huskies: merge 925 2026-05-12 18:33:13 +00:00
dave 03a99b3cf1 huskies: merge 927 2026-05-12 17:55:12 +00:00
Timmy 9eb5116f7e wip(929): stage 2 — migrate chat/transport/matrix/* off yaml_legacy
delete.rs, start.rs, assign.rs all looked up the story name by reading
the content from disk/store and parsing the front matter. Replaced with
`crdt_state::read_item(&story_id).and_then(|w| w.name())`. Each callsite's
fallback chain ("CRDT → content store → filesystem") still locates the
story_id; only the name extraction moved off YAML.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 18:45:25 +01:00
dave 9be438e6d3 huskies: merge 865 2026-05-08 14:29:06 +00:00
dave 61cf7684de huskies: merge 864 2026-04-30 22:27:51 +00:00
dave 1251b869a6 style: cargo fmt on today's new code (883/884/886/opus-pin)
The mergemaster gates run rustfmt and rejected 864's merge because
several files I added/touched in master today had not been fmt'd.
Six files affected, mostly trivial line-wrapping nits. Fixes the
formatting gate for the next 864 merge attempt.
2026-04-30 22:15:37 +00:00
dave 7ac3fc2e3e feat(884): persistent perm_rx lock-holder for Matrix bot
Before: handle_message.rs acquired services.perm_rx only while processing
one chat message and dropped it on chat_fut completion. The moment the
bot wasn't actively responding, prompt_permission auto-denied any spawned
coder bash call as "no interactive session" — making unattended coder
work impossible.

Now: a permission_listener task is spawned at bot startup and holds
perm_rx for the bot's lifetime. Permission requests are forwarded to
the first configured Matrix room, replies resolved by the existing
on_room_message handler via pending_perm_replies. Per-message acquire is
gone from handle_message.rs (chat_fut just awaits cleanly).

- New module: chat/transport/matrix/bot/permission_listener.rs.
- Wired into run_bot before BotContext construction; bot_sent_event_ids
  is hoisted out so the listener and the rest of the bot share it.
- handle_message.rs no longer touches perm_rx.
- diagnostics/permission.rs comment updated to reflect the new reality.
- Regression test asserts the listener forwards a PermissionForward to
  the target room and records the pending reply key — exactly the path
  that was broken when no chat_fut was in flight.

Discord/Slack/WhatsApp transports still acquire perm_rx per message
(commands.rs:368 / commands/llm.rs:83 / commands/llm.rs:82). They are
not the active transport in this deployment so their per-message acquire
remains dormant; the same listener pattern should be applied to them as
follow-up work in 884 phase 2.
2026-04-30 13:53:46 +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 e56bd2d834 huskies: merge 877 2026-04-29 22:10:47 +00:00
dave db526bbdb2 huskies: merge 876 2026-04-29 21:20:29 +00:00
dave c0801c3894 huskies: merge 875 2026-04-29 18:44:50 +00:00
dave fc86774618 huskies: merge 857 2026-04-29 17:45:51 +00:00
dave c84786364a huskies: merge 874 2026-04-29 17:00:28 +00:00
dave 7f8467b068 huskies: merge 871 2026-04-29 15:45:54 +00:00
dave 59b626d3ba huskies: merge 824 2026-04-29 13:42:58 +00:00
dave 11d111360d huskies: merge 858 2026-04-29 10:47:18 +00:00
dave 39bdbbd095 huskies: merge 809 2026-04-29 00:06:42 +00:00
dave ab01a62bd1 huskies: merge 808 2026-04-28 23:18:57 +00:00
dave 97b9eaa39d huskies: merge 807 2026-04-28 20:56:17 +00:00
dave d0b7db6765 huskies: merge 785 2026-04-28 15:59:50 +00:00
dave b7db6d6aae huskies: merge 775 2026-04-28 12:25:59 +00:00
dave 0d14fffe1c huskies: merge 762 2026-04-28 01:31:16 +00:00
dave 63d5a500de huskies: merge 670_refactor_hoist_chat_history_persistence_into_a_shared_module_replaces_658 2026-04-27 20:09:44 +00:00
dave 4b64bc614f huskies: merge 726_story_notify_chat_transports_when_oauth_account_swaps_or_all_accounts_are_exhausted 2026-04-27 18:44:47 +00:00
dave 272a592a4d huskies: merge 735_story_attach_statuseventbuffer_to_each_agent_session_scoped_per_project_reset_on_restart 2026-04-27 18:06:11 +00:00
dave 4a0f57478c huskies: merge 671_refactor_migrate_pipeline_state_consumers_from_string_comparisons_to_typed_pipelinestage_enum 2026-04-27 16:39:39 +00:00
dave 65d2fb210c huskies: merge 655_bug_matrix_bot_spawns_its_own_timerstore_instead_of_using_shared_appcontext_timer_store 2026-04-27 11:32:51 +00:00
dave 144f07f412 huskies: merge 644_story_chat_transport_consumers_slack_discord_whatsapp_matrix_for_the_unified_status_broadcaster 2026-04-27 11:22:52 +00:00
dave 75533225e4 fix: commit minor fmt residue blocking mergemaster cherry-picks
Master had 8 uncommitted single-line whitespace changes (blank-line trimming
in test mod headers, etc.) left over from a previous mergemaster cargo-fmt
run that didn't get committed. Each subsequent merge attempt hit:

  cherry-pick failed: 'Your local changes to the following files would be
  overwritten by merge. Please commit your changes or stash them.'

So merges had been silently un-mergeable for the last several rounds —
mergemaster correctly reported the issue but had no way to fix master's
own state from inside the merge_workspace.

Files affected (all whitespace-only):
- chat/transport/matrix/bot/messages/{handle_message,on_room_message}.rs
- chat/transport/slack/commands/{llm,mod}.rs
- http/mcp/agent_tools/worktree.rs
- http/workflow/story_ops/{create,criterion,update}.rs

cargo clippy --all-targets -- -D warnings: clean
cargo fmt --all --check: clean
2636 tests pass.
2026-04-27 11:17:31 +00:00