* refactor: restructure CLAUDE.md into modular rules and add pr-shepherd command Trim CLAUDE.md from 710 lines to 92 by moving detailed guidance into path-scoped `.claude/rules/` files that load on demand. Add a new `/pr-shepherd` command that consolidates the full PR lifecycle (review, fix, quality gate, CI fix loop, merge) into one workflow. Changes: - CLAUDE.md: keep only essentials (build commands, code style, architecture, module specs, config reference, debugging) - .claude/rules/review-discipline.md: 15+ review rules, scoped to src/**/*.rs - .claude/rules/database.md: dual-backend rules with SQL dialect translation table, scoped to src/db/** and migrations/** - .claude/rules/safety-and-sandbox.md: safety layer and sandbox rules, scoped to src/safety/**, src/sandbox/**, src/secrets/** - .claude/rules/testing.md: test tiers and patterns, scoped to src/** and tests/** - .claude/rules/tools.md: tool architecture and implementation pattern, scoped to src/tools/** and tools-src/** - .claude/commands/pr-shepherd.md: 7-phase PR lifecycle command that subsumes review-pr, respond-pr, ship, and manual CI fix loops [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address review feedback on CLAUDE.md restructure - Restore project structure tree in CLAUDE.md (zmanian blocking) - Create .claude/rules/skills.md with trust model, SKILL.md format, selection pipeline, and skill tools (zmanian blocking) - Restore configuration section with key env vars (zmanian medium) - Restore "Adding a New Channel" guide (zmanian medium) - Add heartbeat mention to Workspace & Memory section (zmanian low) - Fix pr-shepherd: replace `git add -A` with specific file staging (zmanian) - Fix pr-shepherd: ask user for merge strategy instead of hardcoding --squash (zmanian) - Fix pr-shepherd: replace `--watch` with polling + 10min timeout (zmanian) - Fix testing.md: "skipped if DB is unreachable" not "expected to fail" (Copilot) [skip-regression-check] Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address review comments on PR #750 - Narrow `crate::` import rule: `super::` is fine in tests and intra-module refs - Fix capabilities file naming: `<name>.capabilities.json` sidecar, not bare `capabilities.json` - Update mechanical verification checklist to match narrowed import rule Co-Authored-By: Claude Opus 4.6 <[email protected]> * refactor: move Bedrock docs from CLAUDE.md to src/llm/CLAUDE.md Bedrock provider details (auth, config, feature flag) belong in the LLM module spec, not the top-level guide. Added file map entry, provider table row, and dedicated section in src/llm/CLAUDE.md. Co-Authored-By: Claude Opus 4.6 <[email protected]> * refactor: move env var config block out of CLAUDE.md Replace 20-line config block with one-liner pointing to .env.example and src/llm/CLAUDE.md. Config details are only needed during deployment, not everyday coding. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: use gh pr checkout for fork-safe PR checkout in pr-shepherd Replaces git fetch/checkout with gh pr checkout {number} which handles both same-repo and fork-based PRs automatically. Co-Authored-By: Claude Opus 4.6 <[email protected]> * fix: address Copilot review round 5 on PR #750 - Add gh pr list and gh pr checkout to pr-shepherd allowed-tools - Align crate:: import rule in pr-shepherd with updated CLAUDE.md guidance - Fix vector type in database.md: BLOB (flexible dims), not F32_BLOB(1536) - Update MCP limitation: stdio/HTTP/Unix transports exist, no streaming Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]>
3.1 KiB
paths
| paths | |||
|---|---|---|---|
|
Database Rules
Dual-backend persistence: PostgreSQL + libSQL/Turso. All new persistence features must support both backends.
See src/db/CLAUDE.md for full schema, dialect differences, and libSQL limitations.
Adding a New Operation
- Decide which sub-trait it belongs to (
ConversationStore,JobStore,SandboxStore,RoutineStore,ToolFailureStore,SettingsStore,WorkspaceStore) or create a new one - Add the async method signature to that sub-trait in
src/db/mod.rs - Implement in
src/db/postgres.rs(delegate toStore/Repository) - Implement in
src/db/libsql/<module>.rs(useself.connect().await?per operation) - Add migration if needed:
- PostgreSQL: new
migrations/VN__description.sql - libSQL: add
CREATE TABLE IF NOT EXISTStolibsql_migrations.rs
- PostgreSQL: new
- Test feature isolation:
cargo check # postgres (default) cargo check --no-default-features --features libsql # libsql only cargo check --all-features # both
SQL Dialect Translation Checklist
When writing SQL for both backends, translate these types:
| PostgreSQL | libSQL |
|---|---|
UUID |
TEXT |
TIMESTAMPTZ |
TEXT (ISO-8601, write with fmt_ts(), read with get_ts()) |
JSONB |
TEXT (JSON string) |
BOOLEAN |
INTEGER (0/1 -- use get_i64(row, idx) != 0 to read) |
NUMERIC |
TEXT (preserves rust_decimal precision) |
TEXT[] |
TEXT (JSON-encoded array) |
VECTOR |
BLOB (flexible dimensions; vector index dropped, brute-force search fallback) |
jsonb_set(col, '{key}', val) |
json_patch(col, '{"key": val}') -- replaces top-level keys entirely, cannot do partial nested updates |
DEFAULT NOW() |
DEFAULT (datetime('now')) |
tsvector + ts_rank_cd |
FTS5 virtual table + sync triggers |
Schema Translation Beyond DDL
Don't just translate CREATE TABLE. Also check:
- Indexes -- diff
CREATE INDEXstatements between backends - Seed data -- check for
INSERT INTOin migrations (e.g.,leak_detection_patterns) - Triggers -- PostgreSQL functions vs SQLite triggers (no stored procs in SQLite)
Transaction Safety
Multi-step operations (INSERT+INSERT, UPDATE+DELETE, read-modify-write) MUST be wrapped in a transaction. Ask: "If this crashes between step N and N+1, is the database consistent?" If not, wrap in a transaction. Applies to both backends.
libSQL Connection Model
LibSqlBackend::connect() creates a fresh connection per operation with PRAGMA busy_timeout = 5000. This is intentional -- no pool exists. Never hold connections open across await points. Satellite stores (LibSqlSecretsStore, LibSqlWasmToolStore) receive Arc<LibSqlDatabase> via shared_db() and call .connect() themselves -- never pass a live Connection.
Fix the Pattern, Not the Instance
When fixing a bug in one backend's SQL, always grep for the same pattern in the other. A fix to postgres.rs that doesn't also fix libsql/jobs.rs is half a fix. Same applies to satellite stores.