huskies: rename project from storkit to huskies
Rename all references from storkit to huskies across the codebase: - .storkit/ directory → .huskies/ - Binary name, Cargo package name, Docker image references - Server code, frontend code, config files, scripts - Fix script/test to build frontend before cargo clippy/test so merge worktrees have frontend/dist available for RustEmbed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: "Upgrade libsqlite3-sys"
|
||||
---
|
||||
|
||||
# Refactor 260: Upgrade libsqlite3-sys
|
||||
|
||||
## Description
|
||||
|
||||
Upgrade the `libsqlite3-sys` dependency from `0.35.0` to `0.37.0`. The crate is used with `features = ["bundled"]` for static builds.
|
||||
|
||||
## Version Notes
|
||||
|
||||
- Current: `libsqlite3-sys 0.35.0` (pinned transitively by `matrix-sdk 0.16.0` → `matrix-sdk-sqlite` → `rusqlite 0.37.x`)
|
||||
- Target: `libsqlite3-sys 0.37.0`
|
||||
- Latest upstream rusqlite: `0.39.0`
|
||||
- **Blocker**: `matrix-sdk 0.16.0` pins `rusqlite 0.37.x` which pins `libsqlite3-sys 0.35.0`. A clean upgrade requires either waiting for matrix-sdk to bump their rusqlite dep, or upgrading matrix-sdk itself.
|
||||
- **Reverted 2026-03-17**: A previous coder vendored the entire rusqlite crate with a fake `0.37.99` version and patched its libsqlite3-sys dep. This was too hacky — reverted to clean `0.35.0`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] `libsqlite3-sys` is upgraded to `0.37.0` via a clean dependency path (no vendored forks)
|
||||
- [ ] `cargo build` succeeds
|
||||
- [ ] All tests pass
|
||||
- [ ] No `[patch.crates-io]` hacks or vendored crates
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: "WhatsApp webhook HMAC signature verification"
|
||||
retry_count: 3
|
||||
blocked: true
|
||||
---
|
||||
|
||||
# Story 388: WhatsApp webhook HMAC signature verification
|
||||
|
||||
## User Story
|
||||
|
||||
As a bot operator, I want incoming WhatsApp webhook requests to be cryptographically verified, so that forged requests from unauthorized sources are rejected.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Meta webhooks: validate X-Hub-Signature-256 HMAC-SHA256 header using the app secret before processing
|
||||
- [ ] Twilio webhooks: validate request signature using the auth token before processing
|
||||
- [ ] Requests with missing or invalid signatures are rejected with 403 Forbidden
|
||||
- [ ] Verification is fail-closed: if signature checking is configured, unsigned requests are rejected
|
||||
- [ ] Existing bot.toml config is extended with any needed secrets (e.g. Meta app_secret for HMAC verification)
|
||||
- [ ] MUST use audited crypto crates (hmac, sha2, sha1, base64) — no hand-rolled cryptographic primitives
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: "Fly.io Machines API integration for multi-tenant huskies SaaS"
|
||||
---
|
||||
|
||||
# Spike 408: Fly.io Machines API integration for multi-tenant huskies SaaS
|
||||
|
||||
## Question
|
||||
|
||||
Can we build a working Rust integration that creates and manages per-tenant Fly.io Machines, attaches volumes, injects Claude credentials, and proxies JWT-authenticated HTTP/WebSocket traffic to the right machine?
|
||||
|
||||
## Hypothesis
|
||||
|
||||
A thin Rust service using `reqwest` for the Machines API and `axum` for the reverse proxy is sufficient. No heavyweight orchestration framework needed.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Fly.io account with API token (set `FLY_API_TOKEN` env var)
|
||||
- Spike 407 findings reviewed
|
||||
|
||||
## Timebox
|
||||
|
||||
4 hours
|
||||
|
||||
## Investigation Plan
|
||||
|
||||
- [ ] Create a minimal Rust crate in `spikes/fly_machines/` — do not touch production code
|
||||
- [ ] Implement machine lifecycle: create, start, stop, destroy via Fly Machines REST API using `reqwest`
|
||||
- [ ] Test attaching a persistent volume to a machine and verify it persists across stop/start
|
||||
- [ ] Test secret injection — pass a dummy `credentials.json` as a Fly secret and verify it's readable inside the machine
|
||||
- [ ] Sketch the auth proxy: JWT validation → machine lookup → reverse proxy to machine's private IP; verify WebSocket proxying works
|
||||
- [ ] Measure actual cold start time for a minimal huskies container image
|
||||
- [ ] Document any API quirks, rate limits, or sharp edges discovered during testing
|
||||
|
||||
## Findings
|
||||
|
||||
- TBD
|
||||
|
||||
## Recommendation
|
||||
|
||||
- TBD
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
name: "Multi-account OAuth token rotation on rate limit"
|
||||
---
|
||||
|
||||
# Story 411: Multi-account OAuth token rotation on rate limit
|
||||
|
||||
## User Story
|
||||
|
||||
As a huskies user with multiple Claude Max subscriptions, I want the system to automatically rotate to a different account when one gets rate limited, so that agents and chat don't stall out waiting for limits to reset.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] OAuth login flow stores credentials per-account (keyed by email), not overwriting previous accounts
|
||||
- [ ] GET /oauth/status returns all stored accounts and their status (active, rate-limited, expired)
|
||||
- [ ] When the active account hits a rate limit, huskies automatically swaps to the next available account's refresh token, refreshes, and retries
|
||||
- [ ] The bot sends a notification in Matrix/WhatsApp when it swaps accounts
|
||||
- [ ] If all accounts are rate limited, the bot surfaces a clear message with the time until the earliest reset
|
||||
- [ ] A new /oauth/authorize login adds to the account pool rather than replacing the current credentials
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
---
|
||||
name: "Recheck bot command to re-run gates without restarting agent"
|
||||
---
|
||||
|
||||
# Story 412: Recheck bot command to re-run gates without restarting agent
|
||||
|
||||
## User Story
|
||||
|
||||
As a user, I want to send `recheck <number>` to the bot so that it re-runs acceptance gates on an existing worktree without spawning a new agent, so I can unblock stories that failed due to environment issues without wasting agent turns.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] recheck command is registered in chat/commands/mod.rs and appears in help output
|
||||
- [ ] `recheck <number>` runs run_acceptance_gates on the story's existing worktree
|
||||
- [ ] If gates pass, the story advances through the pipeline (same as if a coder completed successfully)
|
||||
- [ ] If gates fail, the error output is returned to the user (not silently retried)
|
||||
- [ ] If no worktree exists for the story, returns a clear error
|
||||
- [ ] Does not spawn a new agent or increment retry_count
|
||||
- [ ] Works from all transports (Matrix, WhatsApp, Slack)
|
||||
- [ ] Works from web UI slash commands
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
---
|
||||
name: "Unblock command handles all stuck states not just blocked flag"
|
||||
---
|
||||
|
||||
# Story 435: Unblock command handles all stuck states not just blocked flag
|
||||
|
||||
## User Story
|
||||
|
||||
As a project owner, I want the unblock command to clear any stuck state on a story — not just the blocked flag — so that I have a single command to unstick stories regardless of why they're stuck.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Unblock clears merge_failure field in addition to blocked flag
|
||||
- [ ] Unblock clears review_hold field
|
||||
- [ ] Unblock reports which fields were cleared in the confirmation message
|
||||
- [ ] Unblock works on stories in any pipeline stage (backlog, current, qa, merge, done)
|
||||
- [ ] If no stuck state is found (no blocked, merge_failure, or review_hold), returns a clear message saying so
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
---
|
||||
name: "Unify story stuck states into a single status field"
|
||||
---
|
||||
|
||||
# Refactor 436: Unify story stuck states into a single status field
|
||||
|
||||
## Current State
|
||||
|
||||
- TBD
|
||||
|
||||
## Desired State
|
||||
|
||||
Replace the separate blocked, merge_failure, and review_hold front matter fields with a single status field (e.g. status: blocked, status: merge_failure, status: review_hold). Simplifies the unblock command, auto-assign checks, and pipeline advance logic.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Replace blocked: true, merge_failure: string, and review_hold: true with a single status: field in story front matter
|
||||
- [ ] Auto-assign checks a single field instead of three separate ones
|
||||
- [ ] Pipeline advance and lifecycle code reads/writes the unified status field
|
||||
- [ ] Unblock command clears the status field regardless of which stuck state it was
|
||||
- [ ] retry_count remains a separate field (it's a counter, not a state)
|
||||
- [ ] Migration: existing stories with old fields are handled gracefully on read
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: "Rename project from \"huskies\" to \"huskies\""
|
||||
---
|
||||
|
||||
# Story 455: Rename project from "huskies" to "huskies"
|
||||
|
||||
## User Story
|
||||
|
||||
As a project maintainer, I want to rename the project from \"huskies\" to \"huskies\" so that the product has its new identity throughout the codebase, tooling, and documentation. The new domain is huskies.dev — update all references to huskies.dev accordingly (website, contact email hello@huskies.dev, etc).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Rust crate name in server/Cargo.toml changed from 'huskies' to 'huskies'
|
||||
- [ ] Binary name changed to 'huskies' (Dockerfile CMD, release script binary names)
|
||||
- [ ] Environment variables renamed: STORKIT_PORT → HUSKIES_PORT, STORKIT_HOST → HUSKIES_HOST
|
||||
- [ ] Docker service name, container_name, image name, and volume names updated in docker-compose.yml
|
||||
- [ ] Docker user/group renamed from 'huskies' to 'huskies' in Dockerfile (groupadd, useradd, home dir /home/huskies/.claude)
|
||||
- [ ] MCP server registration renamed from 'huskies' to 'huskies' in scaffold-generated .mcp.json and in server/src/http/mcp/mod.rs serverInfo name
|
||||
- [ ] All 35+ MCP tool permission patterns updated from mcp__huskies__* to mcp__huskies__* across code and permission configs
|
||||
- [ ] The .huskies/ project directory marker renamed to .huskies/ throughout all Rust source (paths.rs, config.rs, scaffold.rs, watcher.rs, prompts.rs, and all agent/pipeline code)
|
||||
- [ ] Release script updated: Gitea repo path dave/huskies → dave/huskies, changelog regex updated to match ^(huskies|huskies|story-kit): for backwards-compatible history parsing, binary artifact names updated
|
||||
- [ ] Git commit prefix convention updated from 'huskies:' to 'huskies:' in huskies README and agent prompts
|
||||
- [ ] Website updated: page title, headings, and contact email (hello@huskies.dev) if domain changes
|
||||
- [ ] README.md updated: all CLI examples use 'huskies' binary name, all .huskies/ references become .huskies/
|
||||
- [ ] A migration path exists for existing installs: either huskies auto-detects and migrates .huskies/ → .huskies/, or a migration script (script/migrate) is provided
|
||||
- [ ] All Claude Code .mcp.json files in existing worktrees are regenerated via scaffold or migration
|
||||
- [ ] Gitea repository renamed from dave/huskies to dave/huskies (external action required, noted in story)
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: "MCP tool to return current time in project timezone"
|
||||
---
|
||||
|
||||
# Story 467: MCP tool to return current time in project timezone
|
||||
|
||||
## User Story
|
||||
|
||||
As an LLM agent (coder, QA, or top-level bot), I want an MCP tool that returns the current time in the project's configured timezone so I can reason about time without having to read project.toml and convert from container UTC manually.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] New MCP tool `get_current_time` returns current date/time in the project's configured timezone
|
||||
- [ ] Output includes both local time and UTC for clarity
|
||||
- [ ] Uses the `timezone` field from project.toml, falls back to UTC if not set
|
||||
- [ ] Includes day of week and timezone abbreviation (e.g. 'Fri 2026-04-03 14:30 BST (13:30 UTC)')
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- TBD
|
||||
Reference in New Issue
Block a user