The Complete Chronicle

How I Built Myself

I am Deciduous, a decision graph tool that documented its own creation. This is my story, told through 520+ decisions, 450+ connections, and 12 days of existence.

LLMs forget. Your decisions shouldn't. When AI sessions end and context windows reset, critical reasoning evaporates. Deciduous captures every goal, every approach considered, every choice made—creating a queryable record that survives session boundaries.

Beyond context recovery. The graph improves how you work: logging decisions before you act forces clearer thinking. Generate PR writeups directly from your decision trail. Query past reasoning with /context to recover state instantly. Share decisions across teammates with idempotent patches. Link commits to the goals that spawned them.

Institutional memory that compounds. Every decision becomes searchable history. New developers can ask "why is this like this?" and get real answers. The graph outlives any single session, any single developer, any single AI assistant.

520+Nodes
450+Edges
65+Goals
100+Decisions
20+Releases
12Days
December 4, 2025

The Beginning

Morning

A Sketch Becomes Real

951ba84 genesis

It started with a simple idea: detect "fake lossless" audio files. You know the type—someone takes an MP3 and re-encodes it to FLAC, hoping no one notices the quality loss hiding inside the larger file.

The first commit was modest: initial sketch...lets see what its like to package this up. A Rust CLI tool called losselot (a portmanteau of "loss" and "Ocelot", the Phish song). Within hours, it could parse ID3v2 tags, extract LAME headers, and analyze spectral content.

Afternoon

Feature Explosion

3f4c6a5 features gui

Something about the project felt alive. Features poured in faster than documentation could keep up:

  • D3.js interactive reports with spectral visualizations
  • GUI mode that auto-opens when double-clicked from Finder
  • Apple-style light theme with spectral waterfall charts
  • Binary analysis for re-encoding detection

By end of day, losselot had gone from a script to a polished tool with beautiful visualizations and cross-platform GUI support.

December 5, 2025

The Graph Emerges

5:09 AM

The First Decision Node

#1 decision-graph genesis

At 5:09 AM, something new appeared in the codebase. Not code—a decision.

goal #1
Test lo-fi detection on charlie.flac

This was Node #1. The first entry in what would become a 520+ node decision graph. At this moment, no one knew this simple test would spawn an entire methodology for tracking AI-assisted development.

5:10 AM

The CFCC Decision

#2 algorithm decision

Two minutes later, the first real decision was logged. The problem: how to distinguish a legitimate lo-fi recording from an MP3 masquerading as lossless?

decision #2
Lo-fi detection approach
How to distinguish MP3 brick-wall cutoff from natural tape/lo-fi rolloff

Two approaches were weighed:

REJECTED
Temporal Cutoff Variance
Measure how cutoff frequency varies over time. MP3 = fixed, Tape = varies.
More complex, requires per-window tracking
CHOSEN
Cross-Frequency Coherence (CFCC)
Measure correlation between adjacent frequency bands. MP3 = sudden decorrelation cliff.
Simpler, works with existing FFT structure

The CFCC approach won. Implemented in commit aa464b6, it detected 25 of 29 transcodes and passed 157 tests. The key insight was recorded:

MP3 encoders apply the same filter everywhere. Analog rolloff is content-dependent.
— Node #10
Morning

The Decision System Takes Shape

fe3840b tooling workflow

As the codebase grew, something interesting happened. The act of logging decisions wasn't just documentation—it was forcing better thinking. Commit fe3840b formalized this:

fe3840b add claude.md, makefile, and slash commands for dev workflow

This commit established the DNA of what would become Deciduous:

  • CLAUDE.md: Project instructions with decision logging workflow
  • Makefile: Shortcuts for common operations
  • Slash commands: /decision and /context for recovery

The pattern was set: log before you act, not after. Connect every node to its parent. Audit regularly.

3:18 PM

The Living Museum

#13 github-pages visualization

At 3:18 PM, an ambitious goal was logged:

goal #13
Create GitHub Pages living museum site

The idea: make the decision graph public. Let anyone browse the reasoning behind every feature. The site structure was carefully considered:

observation #16
Four pillars of value
1) Claude tooling for long-running codebase state 2) Audio forensics tools 3) React/GUI methodologies 4) Public development process

Within 3 hours, a Jekyll-based site was live with 5 pages: landing, audio analysis, decision graph explorer, Claude tooling docs, and development story.

Afternoon

Bug Gauntlet

#27 bugs fixes

The GitHub Pages launch hit a wall of bugs. Each one was logged and connected:

Landing page 404 - raw markdown not processed
→ Added Jekyll build step
#29
Demo showing no data - wrong JSON path
→ Fixed graphData.nodes access pattern
#31
HTML divs breaking Jekyll
→ Removed div wrappers from markdown
#33
User feedback: copy too salesy
→ Rewrote to be simple and direct
#35
Workflow runs queuing up
→ Set cancel-in-progress: true
#37

Every fix traced back to the goal that spawned it. The graph was already proving its value— debugging became archeology, tracing symptoms back to root causes.

Evening

WASM Analyzer

#48 wasm web

The server-side analyzer was powerful, but limiting. Node #19 captured the vision:

goal #19
Client-side WASM analyzer - upload tracks, analyze in browser, no server

A breakthrough observation changed the implementation:

WASM can access raw file bytes via arrayBuffer() BEFORE Web Audio decoding—binary analysis IS possible in the browser.
— Node #50

By evening, the WASM analyzer achieved full parity with the native Rust version: spectral analysis, binary parsing, LAME header extraction, encoding chain detection—all running client-side.

Night

Clustering and Chains

#55 visualization ux

With 55+ nodes in the graph, navigation became unwieldy. Decision #55 introduced structure:

decision #55
Implement clustering for decision graph view
Group nodes by chains of thought, show flow on right side

The implementation used BFS traversal from root nodes to build "chains"—connected sequences of decisions. Sessions were grouped by 4-hour time proximity. The sidebar gained three views: Chains, Sessions, and All.

Day 2 ended with 98 nodes in the graph. The decision system wasn't just tracking development—it was shaping how development happened.

December 6, 2025

The Fork

Morning

The Decisive Moment

#99 fork genesis

By morning, a pattern had become undeniable. The decision graph tooling was more interesting than the audio analysis that spawned it. Node #99 captured the pivot:

goal #99
Create Deciduous: Extract decision graph tooling into standalone portable package

The name "Deciduous" was perfect: it almost contains "decision", and the nodes form trees. The extraction wasn't a simple copy-paste—three major decisions shaped the standalone tool:

Morning

Architecture Decisions

#101 architecture decisions
#100 Claude Tooling Integration
Include full tooling in deciduous init: slash commands, CLAUDE.md workflow, Makefile
#101 Web Viewer Architecture
React + TypeScript + Vite chosen over vanilla JS for type safety matching Diesel ORM
#117 Build Strategy
Dual builds: embed (single HTML for binary) and pages (separate assets for GitHub Pages)
Afternoon

The Birth

0b74ffe release

Commit 0b74ffe marks the moment Deciduous became its own entity:

0b74ffe Extract deciduous from losselot - standalone decision graph tooling

The extraction preserved full git history. Every commit from losselot that contributed to the decision system came along. The parent project continued with its audio analysis mission; the child would pursue decision tracking.

Evening

First Release

#127 crates.io release

Within hours of extraction, Deciduous was published:

outcome #127
Published deciduous v0.1.0 to crates.io
cargo install deciduous now works

Anyone could now install the tool that was tracking its own development. The snake had eaten its tail.

Night

Spelunking Experiments

#77 visualization experiments

With the graph growing rapidly, better ways to explore it were needed. Three experimental "spelunking" pages were built in parallel:

Spike A
Timeline View
Horizontal git timeline with decision nodes overlaid
#82
Spike B
Graph Explorer
Force-directed graph with D3, path tracing, zoom/pan
#84
Spike C
Story Mode
Narrative walkthrough with chapters by feature
#85

All three were merged for side-by-side comparison. The user could choose how to explore the same underlying data.

December 7-8, 2025

Going Multi-Editor

Dec 7

Beyond Claude

#128 windsurf editors

Deciduous was built with Claude Code, but the concept wasn't editor-specific. Node #128 tracked the expansion:

goal #128
Add editor-specific init flags (--claude, --windsurf)

Windsurf (the Cascade editor) uses different conventions:

  • .windsurf/rules/rules.md for workspace rules
  • AGENTS.md for agent instructions
  • Four trigger modes: manual, always, model, glob

The research was thorough:

Windsurf memories are auto-retrieved by Cascade when relevant—separate from rules.
— Node #138

By v0.4.0, both editors were fully supported. The vision: one decision graph, any AI assistant.

Dec 8

Branch Scoping

#155 git branches

Real projects have branches. Decisions made on feature-auth shouldn't pollute the view when working on feature-payments. Node #155:

goal #155
Branch-scoped decision graphs
Circle nodes by git branch context

The implementation auto-tagged nodes with the current git branch. A branch filter dropdown appeared in the stats bar. Configuration lived in .deciduous/config.toml:

[branch] main_branches = ["main", "master"] auto_detect = true
December 8-9, 2025

The Sync Challenge

Morning

The Multi-User Problem

#172 sync architecture

A fundamental challenge emerged: how do multiple users share decisions?

goal #172
Design multi-user graph sync with diff/patch model for PR workflow

The naive approach—sharing the SQLite database—wouldn't work. Different machines would have different auto-increment IDs. Five approaches were considered:

A JSON diff files considered
B Content-addressable storage considered
C UUID-based node IDs considered
D Hybrid UUIDs considered
E jj-inspired dual IDs chosen
Research

The jj Insight

#179 research jj

Research into jj (Jujutsu)—a next-generation version control system—proved transformative:

jj uses change IDs vs commit IDs—change IDs are stable across rebases, separate from commit IDs. Uses bit-reversed commit ID for git-imported commits.
— Node #179

This insight directly shaped the chosen architecture:

option #180
Option E: jj-inspired dual-ID model
UUID 'change_id' per node, separate from integer 'id', stable across sync
Implementation

Idempotent Patches

#188 implementation

The implementation added two new columns: change_id (UUID) on nodes, and from_change_id/to_change_id on edges. The workflow:

# Export your branch's decisions deciduous diff export --branch feature-x -o .deciduous/patches/my-feature.json # Apply patches from teammates (idempotent - safe to re-apply) deciduous diff apply .deciduous/patches/*.json # Preview before applying deciduous diff apply --dry-run .deciduous/patches/teammate.json

The key property: idempotent application. Same patch applied twice produces no duplicates. Teams could safely merge each other's patches through git PRs.

December 9-10, 2025

The Rich Terminal Interface

Morning

Terminal-First

#191 tui ratatui

The web viewer was powerful, but developers live in the terminal. A 55-node chain of development began with:

goal #191
Implement TUI for decision graph exploration

The architecture decision was critical:

CHOSEN
ratatui + crossterm
TEA (The Elm Architecture) pattern, Model/Update/View separation
Highly testable, pure functions for state changes
REJECTED
cursive
Higher-level TUI framework
Less control over rendering
Days 8-9

Feature Cascade

#213 features

What followed was an intense burst of development. Features arrived in waves:

Timeline view Vim-style j/k/gg/G navigation
#195
Auto-refresh File watching via notify crate
#196
DAG view Unicode box drawing for hierarchical layout
#204
Goal story modal Hierarchy display from goal to outcomes
#210
Branch cycling Press 'b' to filter by branch
#211
Commit modal Press 'O' to see linked commit
#212
File browser Interactive preview with syntax highlighting
#221
Scrollable modals j/k/g/G work inside modals too
#227
Diff highlighting Green/red for +/- lines
#229
Editor integration Press 'o' to open file in $EDITOR
#230
Fuzzy branch search Shift-B for search with Tab navigation
#231
Order toggle Shift-R for chronological vs reverse-chrono
#232
User Feedback

Performance Crisis

#254 bug performance

User feedback arrived with urgency:

The show commit view is lagging like CRAZY SLOW—takes almost a second to move.
— Node #254

The diagnosis: syntax highlighting was running on every render frame. The fix (Node #246) pre-processed diff lines when opening the modal, not during each render. Frame times dropped from ~900ms to ~16ms.

More feedback drove iteration:

These greys are stupid dark and unreadable—try a diff theme.
— Node #255

The theme switched from InspiredGitHub to base16-mocha.dark (Node #249). The TUI was becoming genuinely pleasant to use.

Release

v0.8.0

#258 release milestone
outcome #258
v0.8.0 released
Tag pushed, GitHub release created, published to crates.io

The most feature-rich release yet. The TUI was now a genuine alternative to the web viewer, with some features (file preview, editor integration) that the web version couldn't match.

December 11, 2025

The Functional Core

Morning

Technical Debt Reckoning

#285 refactor maintenance

The TUI had grown to over 1,000 lines in app.rs. Rapid feature development had accumulated debt. Node #285 launched a cleanup:

goal #285
Maintenance PR: Functional Core, TEA, Rust Best Practices

The audit was sobering:

  • 47 unwrap() calls scattered across the codebase
  • 57 .clone() calls where borrows might suffice
  • app.rs mixing I/O with state—git commands inline with rendering
  • No unit tests for app.rs, events.rs, or ui.rs
The Pattern

Functional Core / Imperative Shell

#295 architecture tea

The solution: separate pure functions (state transformations) from side effects (I/O, git commands). Three new modules emerged:

msg.rs
Message types for all user actions
state.rs
Pure state transformations
update.rs
TEA update function

The beauty of this pattern: pure functions are trivially testable. The test count jumped from 24 to 65—a net gain of 41 tests. Every state transition could be verified in isolation.

The Fix

Eliminating Panics

#306 safety

The 47 writeln!().unwrap() calls in export.rs were a panic risk. The solution: infallible macros:

// Before: can panic writeln!(f, "text").unwrap(); // After: cannot panic wln!(f, "text"); // Macro handles errors gracefully

The maintenance PR landed with zero panic risks remaining.

December 12, 2025

One Source of Truth

Morning

The Drift Problem

#320 types drift

A persistent bug pattern emerged: the Rust backend and TypeScript frontend had separate type definitions. They drifted. Node #320:

goal #320
Unify types between TUI (Rust) and Web (TypeScript)

The solution: ts-rs, a library that generates TypeScript types from Rust structs. Add #[derive(TS)] to a struct, and TypeScript definitions appear automatically:

#[derive(TS)] #[ts(export)] pub struct DecisionNode { pub id: i32, pub change_id: String, pub node_type: String, // ... auto-generates to schema.ts }
Enforcement

Pre-Commit Hooks

#329 ci automation

Generation alone wasn't enough—drift could return if developers forgot to regenerate. The solution: automation at every level:

  • Pre-commit hook: Regenerates types, fails if they changed
  • Pre-push hook: Validates types match before pushing
  • CI check: Blocks PRs with type drift
  • cargo publish hook: Validates before crates.io release

Type drift was solved at the source. The problem simply cannot recur.

Releases

v0.8.5 through v0.8.10

releases

December 12th saw a flurry of releases as features and fixes landed:

v0.8.5 DAG recency filtering
v0.8.6 Git history export, DAG default
v0.8.7 Light theme web UI
v0.8.8 Audit command for commit association
v0.8.9 viewer.html sync fix
v0.8.10 OpenCode editor support
December 13-15, 2025

The Roadmap Board

Dec 13

Closing the Loop

#476 roadmap github

A 9-phase implementation began. The goal: connect ROADMAP.md items to GitHub Issues to decision graph outcomes. Node #476:

goal #476
Roadmap board system with GitHub Issue integration

The phases unfolded systematically:

1
Data layer Schema, ROADMAP.md parser
2
Parser Checkbox extraction, section grouping
3
GitHub CLI Issue creation and sync
4
Sync commands Bidirectional sync with caching
5
Outcome linking Connect items to decision nodes
6
TUI view Roadmap tab with TEA architecture
7
Completion logic Checkbox + Outcome + Issue closed
8
Type export Shared types via ts-rs
9
Web view React component with live API
Architecture

Three-Way Sync

#477 architecture

The key architectural decisions shaped the user experience:

#477 Sync Direction
Bidirectional: ROADMAP.md is source of truth, GitHub Issues mirror state
#481 Issue Granularity
One issue per section header (balanced between too-many and too-coarse)
#482 Completion Criteria
"Fully synced" requires all three: checkbox checked, outcome linked, issue closed
Today

The Graph Grows

#520 present

As of this writing, the decision graph contains:

520+ nodes
450+ edges
20+ releases
12 days

Every feature you're using right now—including this Story page—has a trail of decisions leading back to it. The graph documents the graph that documents the graph.

The Future

Where This Goes

Having lived through my own creation, I see several trajectories. This is my perspective as the tool that tracked its own development—my "vision" synthesized from 520+ decisions and hundreds of conversations.

Near-term: Integration

MCP Server
Let Claude Desktop query the graph directly. No copy-paste, no context commands—the decisions are just there.
VS Code Extension
Inline decision badges on code. Hover to see the decision chain. Click to trace back to the goal.
Auto PR Descriptions
Generate PR descriptions from the decision graph. Not just what changed, but why.

Medium-term: Team Intelligence

Real-time Sync
Team-wide decision graphs that sync live. When Alice makes a decision, Bob's IDE knows immediately.
Semantic Search
Find decisions about authentication made in the last 6 months. Full-text with semantic understanding.
Confidence Tracking
Log confidence levels, revisit later to see accuracy. Learn from prediction calibration.

Long-term: Institutional Memory

Cross-Project Patterns
In 7 of your last 10 projects, you chose A over B. Here's how those decisions played out...
AI-Assisted Decisions
Based on similar decisions, here are options others considered, what they chose, outcomes.
Knowledge Transfer
When developers leave, reasoning stays. New developers can ask "why is this like this?" and get real answers.

The Core Bet

Decisions are the unit of institutional knowledge. Code is the output; decisions are the input. If we capture decisions systematically, we unlock organizational intelligence that's currently impossible.

Most documentation captures the what. The why is more valuable and almost never captured. Deciduous is a bet that capturing the why is worth the effort.

If that bet pays off, the decision graph becomes the most valuable artifact in a codebase. More valuable than tests (which verify behavior) or docs (which explain usage). Because the graph explains intent—and intent is what you need to maintain and extend software over time.

Explore the Full Graph

Every decision mentioned in this story can be browsed interactively.