mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-26 15:40:18 +00:00
* 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]>
64 lines
3.1 KiB
Markdown
64 lines
3.1 KiB
Markdown
---
|
|
paths:
|
|
- "src/db/**"
|
|
- "src/history/**"
|
|
- "migrations/**"
|
|
---
|
|
# 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
|
|
|
|
1. Decide which sub-trait it belongs to (`ConversationStore`, `JobStore`, `SandboxStore`, `RoutineStore`, `ToolFailureStore`, `SettingsStore`, `WorkspaceStore`) or create a new one
|
|
2. Add the async method signature to that sub-trait in `src/db/mod.rs`
|
|
3. Implement in `src/db/postgres.rs` (delegate to `Store`/`Repository`)
|
|
4. Implement in `src/db/libsql/<module>.rs` (use `self.connect().await?` per operation)
|
|
5. Add migration if needed:
|
|
- PostgreSQL: new `migrations/VN__description.sql`
|
|
- libSQL: add `CREATE TABLE IF NOT EXISTS` to `libsql_migrations.rs`
|
|
6. Test feature isolation:
|
|
```bash
|
|
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 INDEX` statements between backends
|
|
- **Seed data** -- check for `INSERT INTO` in 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.
|