deciduous 0.13.15

Decision graph tooling for AI-assisted development. Track every goal, decision, and outcome. Survive context loss. Query your reasoning.
Documentation
# Deciduous Cleanup Strategy

## The Case for Simplification

The Elixir rewrite (Decidulixir) achieves **full CRUD + traversal + CLI in ~4,800 LOC** vs Deciduous's **25,384 LOC**. While language differences account for some of this, the rewrite exposed that a huge amount of Rust code serves features that are either:

1. **Redundant** — two competing systems for the same thing
2. **Unused in practice** — built speculatively, never adopted
3. **Over-engineered** — 1,300 LOC for what could be 100
4. **Belongs elsewhere** — not core to decision graphs

## Codebase Inventory (Current State)

| File | LOC | Category | Verdict |
|------|-----|----------|---------|
| `main.rs` | 5,080 | Core | **Split** — monolith, needs decomposition |
| `db.rs` | 3,561 | Core | **Simplify** — god-object, too many responsibilities |
| `opencode.rs` | 3,651 | Integration | **Keep** — actively used |
| `init/templates.rs` | 2,762 | Tooling | **Slim down** — massive embedded strings |
| `init/mod.rs` | 1,184 | Tooling | **Simplify** — multi-tool init is over-complex |
| `serve.rs` | 1,232 | Core | Keep (web viewer is valuable) |
| `events.rs` | 967 | Sync | Keep (preferred sync mechanism) |
| `export.rs` | 942 | Core | Keep |
| `roadmap.rs` | 692 | Feature | **Evaluate** — is this used? |
| `github.rs` | 641 | Feature | **Evaluate** — coupled to roadmap |
| `diff.rs` | 607 | Sync | **Delete** — superseded by events.rs |
| `hooks.rs` | 501 | Tooling | **Simplify** — over-engineered |
| `archaeology.rs` | 461 | Feature | Keep |
| `pulse.rs` | 428 | Feature | Keep |
| `changelog.rs` | 391 | Tooling | Keep (small, useful) |
| `config.rs` | 382 | Core | Keep |
| `narratives.rs` | 252 | Feature | Keep |
| `schema.rs` | 218 | Core | Keep |
| `lib.rs` | 95 | Core | Keep |
| `git_guard/` | 1,337 | Tooling | **Delete or gut** — massive over-engineering |

## What the Elixir Rewrite Taught Us

### 1. PostgreSQL eliminated entire subsystems

The single biggest lesson: by using a shared database instead of per-user SQLite files, Decidulixir **never needed** sync, diff, events, or patch systems. While Deciduous must keep SQLite (it's a CLI tool), the **dual sync system** (events.rs AND diff.rs) is pure waste.

### 2. The god-object `db.rs` pattern doesn't scale

Rust's `db.rs` is a 3,561-line god-object with every database operation. Decidulixir decomposes this into focused modules: `Graph` context (32 lines), `Queries` (60 lines), `Traversal` (70 lines), `Metadata` (40 lines). The Rust version should follow this pattern.

### 3. OpenCode integration is dead weight

`opencode.rs` is 3,651 lines — the **second largest file** — generating templates for a tool that appears to have minimal adoption. This is 14% of the entire codebase for an optional integration nobody asked for.

### 4. Git Guard is a 1,337-line solution to a non-problem

Claude Code and other AI tools already have built-in protections against dangerous git operations. The git_guard subsystem with its own config format, rules engine, hook handlers, and logging system is massive over-engineering. A simple 50-line shell script could do 90% of this.

### 5. Init/templates could be external files

2,762 lines of `templates.rs` is raw string constants embedded in the binary. These could be external template files, reducing binary bloat and making them easier to maintain.

### 6. `main.rs` at 5,080 lines is unmaintainable

All command dispatch, argument parsing, and execution logic in one file. The Elixir version uses a clean `Command` behaviour pattern where each command is its own module.

## Proposed Issue Breakdown

### Phase 1: Delete Dead Code (Immediate wins, ~2,000 LOC removed)

#### Issue 1: Remove legacy diff/patch sync system (`diff.rs`)
- **Delete**: `src/diff.rs` (607 LOC)
- **Modify**: `main.rs` — remove `diff` subcommand
- **Modify**: `db.rs` — remove diff-related queries if any
- **Risk**: Low — events.rs is the preferred approach
- **Estimated savings**: ~700 LOC

#### Issue 2: Remove or radically simplify git_guard
- **Delete**: `src/git_guard/` (1,337 LOC)
- **Replace with**: Simple shell-script-based check (or nothing — Claude Code has its own protections)
- **Modify**: `main.rs` — remove `git-guard` subcommand
- **Risk**: Low — redundant with AI tool built-in protections
- **Estimated savings**: ~1,300 LOC

### Phase 2: Decompose Monoliths (~0 LOC change, major maintainability win)

#### Issue 3: Split `main.rs` into command modules
- Extract each subcommand into its own module under `src/commands/`
- Keep `main.rs` as thin dispatcher (~200 lines)
- Follow Decidulixir's `Command` behaviour pattern
- **Pattern**:
  ```
  src/commands/
  ├── mod.rs          # Command trait + dispatch
  ├── add.rs          # add subcommand
  ├── link.rs         # link subcommand
  ├── nodes.rs        # nodes subcommand
  ├── serve.rs        # serve subcommand
  └── ...
  ```
- **Risk**: Medium — lots of code movement, but no logic changes
- **Estimated impact**: main.rs goes from 5,080 → ~200 lines

#### Issue 4: Decompose `db.rs` into focused modules
- Split into: `db/nodes.rs`, `db/edges.rs`, `db/queries.rs`, `db/sessions.rs`, `db/documents.rs`, `db/roadmap.rs`, `db/themes.rs`
- Keep `db/mod.rs` as connection pool + shared types
- **Risk**: Medium — many internal references to refactor
- **Estimated impact**: db.rs goes from 3,561 → focused 200-400 line modules

### Phase 3: Simplify Init System (~1,500 LOC removed)

#### Issue 5: Externalize templates
- Move embedded template strings from `init/templates.rs` to `data/templates/`
- Load at build time via `include_str!()` or at runtime
- Remove Windsurf integration templates (does anyone use this?)
- **Risk**: Low — same behavior, just organized differently
- **Estimated savings**: ~1,500 LOC from templates.rs, cleaner maintenance

#### Issue 6: Simplify init — remove Windsurf, keep Claude Code + OpenCode
- Remove Windsurf integration templates and detection
- Keep Claude Code and OpenCode init paths
- Simplify `init/mod.rs` from 1,184 → ~600 lines
- **Risk**: Low — Windsurf integration appears unused
- **Estimated savings**: ~500 LOC

### Phase 4: Evaluate Feature Scope

#### Issue 7: Evaluate roadmap sync (`roadmap.rs` + `github.rs`)
- **Question**: Is anyone using `deciduous roadmap sync`?
- If no: delete both files (1,333 LOC)
- If yes: consider extracting to separate tool/plugin
- Related database tables: `roadmap_items`, `github_issue_cache`
- **Risk**: Needs user research first
- **Estimated savings**: 0 or 1,333 LOC

#### Issue 8: Simplify hooks system
- `hooks.rs` (501 LOC) manages Claude Code hook installation
- The version-check hook runs a shell script that calls `deciduous check-update`
- Could be simplified to a single `deciduous init-hooks` command
- **Risk**: Low
- **Estimated savings**: ~300 LOC

### Phase 5: Web Viewer Modernization

#### Issue 9: Evaluate removing `pages_viewer.html`
- Two embedded HTML files: `viewer.html` (390 KB) and `pages_viewer.html` (666 KB)
- Are both needed? Can GitHub Pages use the same viewer?
- **Risk**: Low — investigation first
- **Estimated savings**: 666 KB from binary

## Impact Summary

| Phase | Issues | Est. LOC Removed | Est. LOC Remaining |
|-------|--------|------------------|-------------------|
| Current ||| 25,384 |
| Phase 1 | #1-2 | ~2,000 | ~23,384 |
| Phase 2 | #3-4 | 0 (restructure) | ~23,384 |
| Phase 3 | #5-6 | ~2,000 | ~21,384 |
| Phase 4 | #7-8 | 300-1,633 | ~19,751-21,084 |
| Phase 5 | #9 | binary size only ||

**Best case: 25,384 → ~19,751 LOC (22% reduction)** while keeping all actively-used functionality. The restructuring in Phase 2 is the biggest maintainability win despite no LOC change.

## Guiding Principles

1. **Delete before simplify** — removing code is always better than refactoring it
2. **One sync system** — events.rs won; diff.rs dies
3. **Two integration targets** — Claude Code + OpenCode; Windsurf dies
4. **Decompose monoliths** — no file over 500 lines
5. **External over embedded** — templates belong in files, not strings
6. **Core vs plugin** — decision graphs are core; roadmap sync is a plugin

## Decision Graph Nodes from Decidulixir

Key decisions recorded in the Decidulixir decision graph that informed this analysis:

- **Node 12**: "PostgreSQL eliminates need for offline sync" — the #1 simplification
- **Node 13**: "User decided these features not needed in rewrite" — explicit feature cuts
- **Node 14**: "Leverage Elixir ecosystem strengths" — framework > hand-rolled
- **Node 153**: "Rewrite CLI: drop Logger-based Formatter, use IO output, config hash pattern" — CLI was completely rewritten after initial attempt proved broken

These decisions validate that the complexity in Deciduous was accidental, not essential.