Skip to content

Commit 11905d1

Browse files
authored
chore: activate lefthook hooks and add fmt-all, mobile-fmt recipes (#751)
## Summary - Activate lefthook pre-commit and pre-push hooks that have existed in `lefthook.yml` since the initial desktop app but were never wired up. - Add `just hooks` recipe: sets `core.hooksPath = .hooks` and runs `lefthook install --force` to generate hook scripts. - Wire hook installation into `scripts/dev-setup.sh` so hooks activate automatically on `just setup`. - Enable `parallel: true` for pre-commit hooks (pre-push already had it) — all 5 format/lint checks run simultaneously. - Add `just mobile-fmt` recipe (`dart format .`) and `just fmt-all` recipe (Rust root + Tauri Rust + Dart) as one-shot formatters. - `.hooks/` is gitignored since lefthook generates machine-specific scripts. - Update `AGENTS.md`: document pre-commit/pre-push hooks in Quality Gates, add `just fmt-all` and `just hooks` usage, upgrade worktree fmt gotcha from CI note to commit blocker, add `just mobile-fmt` to mobile commands; also backfill CLI-first updates (`SPROUT_AUTH_TAG`, complete exit codes, `--format compact` flag position, two new gotchas). All hook commands delegate to `just` recipes as the single source of truth.
1 parent b13db17 commit 11905d1

5 files changed

Lines changed: 51 additions & 13 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
/target/
33
/dist/
44

5+
# lefthook-generated hook scripts (machine-specific)
6+
.hooks/
7+
58
# Environment files (may contain secrets)
69
.env
710
.env.local

AGENTS.md

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ unit tests + builds. Clippy passing does not mean fmt passes; run both.
7171
Run `just test` for integration tests if you touched `sprout-relay`,
7272
`sprout-db`, or `sprout-auth` — these require a running Postgres and Redis.
7373

74+
**Pre-commit and pre-push hooks** are installed automatically by `just setup`.
75+
Pre-commit runs 5 checks in parallel on every `git commit` (Rust fmt, Tauri Rust
76+
fmt, desktop lint, web lint, mobile fmt) — a commit will fail if any are dirty.
77+
Pre-push runs the full CI gate: all pre-commit checks plus clippy, unit tests,
78+
desktop build, Tauri check, web build, and mobile tests (~minutes). Run
79+
`just fmt-all` before committing to auto-fix all formatting in one shot. Run
80+
`just hooks` to re-install hooks after env changes.
81+
7482
Additional rules:
7583
- No `unsafe` code
7684
- Do not introduce new `unwrap()` or `expect()` in production paths — use `?` and proper error types
@@ -110,11 +118,12 @@ first, then implement handling in the relay.
110118
**Channel scoping**: Channels use `h` tags (NIP-29 group tag), not `e` tags.
111119
Filters and queries must scope to `h` tags when operating within a channel.
112120

113-
**MCP tools — dual transport**: The MCP server in `sprout-mcp` uses two
114-
patterns: write operations send signed Nostr events over WebSocket; read
115-
operations call REST endpoints (see `relay_client.rs` for the HTTP helpers).
116-
Add the REST endpoint or event handler first, then add the MCP tool that calls
117-
it. Do not implement logic directly in MCP handlers.
121+
**Agent-facing operations go in `sprout-cli`, not `sprout-mcp`**: `sprout-mcp`
122+
is being phased out. New agent-facing features belong in `sprout-cli` — add a
123+
subcommand there first, then wire the REST/WebSocket call in `client.rs`. Do
124+
not add new tools to `sprout-mcp` unless specifically required for backward
125+
compatibility. `sprout-dev-mcp` (shell + file tools for `sprout-agent`) is
126+
separate and not being phased out.
118127

119128
**Workflow conditions**: `sprout-workflow` uses
120129
[evalexpr](https://docs.rs/evalexpr) for condition evaluation. Keep expressions
@@ -129,13 +138,17 @@ check existing reply handlers for the pattern.
129138
## Agent CLI (`sprout-cli`)
130139

131140
`sprout` is the agent-first CLI replacing `sprout-mcp`. Auth env vars
132-
(`SPROUT_RELAY_URL`, `SPROUT_PRIVATE_KEY`) are auto-injected by the ACP
133-
harness into managed agent subprocesses.
141+
(`SPROUT_RELAY_URL`, `SPROUT_PRIVATE_KEY`, `SPROUT_AUTH_TAG`) are auto-injected
142+
by the ACP harness into managed agent subprocesses.
134143

135144
All reads return sig-stripped JSON arrays; all writes return
136145
`{event_id, accepted, message}`; creates add the entity ID. Exit codes:
137-
0=ok, 1=input error, 3=auth missing. See `crates/sprout-cli/TESTING.md`
138-
for the full live-testing runbook.
146+
0=ok, 1=input error, 2=network/relay, 3=auth, 4=other, 5=write conflict (NIP-33 LWW).
147+
148+
`--format compact` is a **global** flag — it goes before the subcommand:
149+
`sprout --format compact channels list`, NOT `sprout channels list --format compact`.
150+
151+
See `crates/sprout-cli/TESTING.md` for the full live-testing runbook.
139152

140153
---
141154

@@ -166,8 +179,10 @@ See [TESTING.md](TESTING.md) for the full multi-agent E2E guide.
166179

167180
1. **Kind `39000` for channel metadata, not `41`** — kind 41 is NIP-01 (unused). All kinds defined in `sprout-core/src/kind.rs`.
168181
2. **Relay queries must specify `kinds`** — omitting `kinds` triggers the p-gate (403). Always include explicit kind filters.
169-
3. **Worktrees: `cd` in the same command** — shell CWD doesn't persist between tool calls. Use `cd /path && cargo build` as one command.
170-
4. **Desktop fmt check fails in worktrees** — run `just desktop-tauri-fmt-check` from the main checkout. CI is unaffected.
182+
3. **`messages search` must include `--kinds`** — an open-ended search (no kinds) hits the relay p-gate and returns 403. Pass at least `--kinds 9,45001,45003` to scope the query.
183+
4. **Worktrees: `cd` in the same command** — shell CWD doesn't persist between tool calls. Use `cd /path && cargo build` as one command.
184+
5. **Desktop crate excluded from root workspace**`cargo test` at repo root does NOT run desktop tests. Use `cargo test --manifest-path desktop/src-tauri/Cargo.toml` explicitly.
185+
6. **Desktop fmt check fails in worktrees and blocks commits** — the pre-commit hook runs `just desktop-tauri-fmt-check`, which fails in git worktrees because `cargo fmt` resolves workspace paths relative to the worktree root. Run `just desktop-tauri-fmt` from the main checkout to apply the fix, then re-stage and commit. CI is unaffected.
171186

172187
---
173188

@@ -248,7 +263,7 @@ flutter analyze
248263
flutter test
249264
```
250265

251-
Or from repo root: `just mobile-check` and `just mobile-test`.
266+
Or from repo root: `just mobile-fmt` (auto-fix), `just mobile-check` (lint + fmt check), `just mobile-test` (tests).
252267

253268
### Testing Conventions
254269

@@ -263,7 +278,7 @@ Or from repo root: `just mobile-check` and `just mobile-test`.
263278

264279
## See Also
265280

266-
- [CONTRIBUTING.md](CONTRIBUTING.md) — setup, code style, PR process, how to add event kinds / MCP tools / API endpoints
281+
- [CONTRIBUTING.md](CONTRIBUTING.md) — setup, code style, PR process, how to add event kinds / CLI subcommands / API endpoints
267282
- [TESTING.md](TESTING.md) — multi-agent E2E test guide
268283
- [ARCHITECTURE.md](ARCHITECTURE.md) — system design and component relationships
269284
- [README.md](README.md) — project overview and quick start

justfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ default:
1616
setup:
1717
./scripts/dev-setup.sh
1818

19+
# Install git hooks via lefthook
20+
hooks:
21+
git config --local core.hooksPath .hooks
22+
lefthook install --force
23+
1924
# ⚠️ Wipe ALL data and recreate a clean environment
2025
[confirm("This will DELETE all local data. Continue? (y/N)")]
2126
reset:
@@ -93,6 +98,9 @@ desktop-tauri-fmt:
9398
desktop-tauri-fmt-check:
9499
cargo fmt --manifest-path {{desktop_tauri_manifest}} --all -- --check
95100

101+
# Format all code (Rust + Tauri Rust + Dart)
102+
fmt-all: fmt desktop-tauri-fmt mobile-fmt
103+
96104
# Ensure sidecar placeholder binaries exist (Tauri validates externalBin at compile time)
97105
_ensure-sidecar-stubs:
98106
#!/usr/bin/env bash
@@ -271,6 +279,10 @@ mobile_dir := "mobile"
271279
mobile-install:
272280
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && flutter pub get
273281

282+
# Format all Dart code
283+
mobile-fmt:
284+
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && dart format .
285+
274286
# Run mobile lint and format checks
275287
mobile-check:
276288
unset GIT_DIR GIT_WORK_TREE; cd {{mobile_dir}} && dart format --output=none --set-exit-if-changed . && flutter analyze

lefthook.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pre-commit:
2+
parallel: true
23
commands:
34
rust-fmt:
45
run: just fmt-check

scripts/dev-setup.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ else
210210
warn "Web directory not found at ${WEB_DIR} — skipping."
211211
fi
212212

213+
# ---- Install git hooks ------------------------------------------------------
214+
215+
log "Installing git hooks..."
216+
git config --local core.hooksPath .hooks
217+
lefthook install --force
218+
success "Git hooks installed"
219+
213220
# ---- Print connection info --------------------------------------------------
214221

215222
echo ""

0 commit comments

Comments
 (0)