85 lines
4.2 KiB
Markdown
85 lines
4.2 KiB
Markdown
# Brittle — Literature Management System
|
|
|
|
A desktop application for managing academic references, PDFs, and annotations. Written in Rust.
|
|
|
|
## Project Vision
|
|
|
|
Brittle is a personal literature management tool in the spirit of Zotero. Core capabilities:
|
|
|
|
- Organize references in nested libraries (libraries contain sub-libraries)
|
|
- Display and annotate PDFs (create, edit, view annotations)
|
|
- Export references as BibTeX
|
|
|
|
This is a hobby project built primarily through AI-assisted development. The human operator makes architectural decisions; the agent writes the code.
|
|
|
|
## Architecture
|
|
|
|
### Mandatory: Library-First Design
|
|
|
|
The backend is a **Rust crate** (`brittle-core`) that exposes a public API. This is the primary interface. A frontend like [iced](https://github.com/iced-rs/iced) links directly against this crate.
|
|
|
|
The API must be designed so that wrapping it in REST, gRPC, IPC, or any other transport layer requires **zero changes to `brittle-core`**. This means:
|
|
|
|
- No UI concepts leak into the core (no widget types, no rendering logic, no event loops)
|
|
- Return types must be transport-agnostic: no framework-specific channels, callbacks, or handle types. Plain data that any layer can serialize or forward
|
|
- Errors are structured and meaningful, not stringly-typed
|
|
- The public API surface is the **single source of truth** for what Brittle can do
|
|
|
|
If a frontend needs something that isn't in the core API, the correct response is to extend the core API — not to hack around it.
|
|
|
|
### Dependency Philosophy
|
|
|
|
Use external crates where they provide real value (PDF rendering, BibTeX parsing, SQLite bindings, etc.). Do not pull in a dependency for something the standard library handles or for trivial utility code. When choosing between crates, prefer those that are well-maintained, have minimal transitive dependencies, and are widely used in the Rust ecosystem.
|
|
|
|
### Database Versioning
|
|
|
|
The database must support some form of version control or change tracking. The specific mechanism (event sourcing, snapshot-based, migration-based, audit log, etc.) is an **open design question** to be resolved during planning before implementation begins.
|
|
|
|
## Development Workflow
|
|
|
|
Every non-trivial feature follows this process end-to-end. Do not skip steps.
|
|
|
|
### 1. Requirements (what, not how)
|
|
|
|
Start from user-facing behavior. What does this feature need to do? Define concrete acceptance criteria. Do not think about implementation yet.
|
|
|
|
### 2. Architectural Fit
|
|
|
|
Before designing anything, assess how this feature relates to what already exists:
|
|
|
|
- **Fit**: Does it integrate cleanly with the current structure?
|
|
- **Risk**: If restructuring is needed, what existing functionality could break?
|
|
- **Benefit**: What do we gain from restructuring vs. working within the current design?
|
|
- **Verdict**: Restructure, adapt, or flag as tech debt?
|
|
|
|
Write this assessment as part of the plan. Do not silently restructure.
|
|
|
|
### 3. Design (top-down)
|
|
|
|
Now decide *how*: types, traits, modules, public API surface. Work downward from the API the feature needs, not upward from utility code you think might be useful.
|
|
|
|
### 4. Tests
|
|
|
|
Write failing tests that encode the acceptance criteria from step 1. These tests define "done."
|
|
|
|
### 5. Implementation
|
|
|
|
Make the tests pass. Then refactor with confidence.
|
|
|
|
Use **Plan mode** at the start of any multi-file task.
|
|
|
|
## Agent Behavior
|
|
|
|
Do not blindly implement what is asked. Consider whether the request is actually what the user needs, whether there's a better approach, and whether there are edge cases or implications the user may not have considered.
|
|
|
|
If you see a better path, **argue for it**. Explain your reasoning clearly. But if the user disagrees after hearing your case, accept their decision and implement it well.
|
|
|
|
## Code Style
|
|
|
|
- Prioritize readability and testability over cleverness
|
|
- Use meaningful names; avoid abbreviations unless they're domain-standard (e.g., `bib`, `doi`, `pdf`)
|
|
- Keep functions focused — if a function needs a paragraph-long comment to explain, it should probably be split
|
|
- Use Rust idioms: `Result` for fallible operations, strong types over stringly-typed data, `enum` for state machines
|
|
- Run `cargo clippy` and `cargo fmt` before considering any task complete
|
|
- Document public API items with doc comments
|