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.
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.
Something about the project felt alive. Features poured in faster than documentation could keep up:
By end of day, losselot had gone from a script to a polished tool with beautiful visualizations and cross-platform GUI support.
At 5:09 AM, something new appeared in the codebase. Not code—a decision.
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.
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?
Two approaches were weighed:
The CFCC approach won. Implemented in commit aa464b6, it detected
25 of 29 transcodes and passed 157 tests. The key insight was recorded:
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:
This commit established the DNA of what would become Deciduous:
/decision and /context for recoveryThe pattern was set: log before you act, not after. Connect every node to its parent. Audit regularly.
At 3:18 PM, an ambitious goal was logged:
The idea: make the decision graph public. Let anyone browse the reasoning behind every feature. The site structure was carefully considered:
Within 3 hours, a Jekyll-based site was live with 5 pages: landing, audio analysis, decision graph explorer, Claude tooling docs, and development story.
The GitHub Pages launch hit a wall of bugs. Each one was logged and connected:
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.
The server-side analyzer was powerful, but limiting. Node #19 captured the vision:
A breakthrough observation changed the implementation:
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.
With 55+ nodes in the graph, navigation became unwieldy. Decision #55 introduced structure:
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.
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:
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:
Commit 0b74ffe marks the moment Deciduous became its own entity:
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.
Within hours of extraction, Deciduous was published:
Anyone could now install the tool that was tracking its own development. The snake had eaten its tail.
With the graph growing rapidly, better ways to explore it were needed. Three experimental "spelunking" pages were built in parallel:
All three were merged for side-by-side comparison. The user could choose how to explore the same underlying data.
Deciduous was built with Claude Code, but the concept wasn't editor-specific. Node #128 tracked the expansion:
Windsurf (the Cascade editor) uses different conventions:
.windsurf/rules/rules.md for workspace rulesAGENTS.md for agent instructionsThe research was thorough:
By v0.4.0, both editors were fully supported. The vision: one decision graph, any AI assistant.
Real projects have branches. Decisions made on feature-auth shouldn't
pollute the view when working on feature-payments. Node #155:
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:
A fundamental challenge emerged: how do multiple users share decisions?
The naive approach—sharing the SQLite database—wouldn't work. Different machines would have different auto-increment IDs. Five approaches were considered:
Research into jj (Jujutsu)—a next-generation version control system—proved transformative:
This insight directly shaped the chosen architecture:
The implementation added two new columns: change_id (UUID) on nodes,
and from_change_id/to_change_id on edges. The workflow:
The key property: idempotent application. Same patch applied twice produces no duplicates. Teams could safely merge each other's patches through git PRs.
The web viewer was powerful, but developers live in the terminal. A 55-node chain of development began with:
The architecture decision was critical:
What followed was an intense burst of development. Features arrived in waves:
User feedback arrived with urgency:
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:
The theme switched from InspiredGitHub to base16-mocha.dark (Node #249). The TUI was becoming genuinely pleasant to use.
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.
The TUI had grown to over 1,000 lines in app.rs. Rapid feature
development had accumulated debt. Node #285 launched a cleanup:
The audit was sobering:
The solution: separate pure functions (state transformations) from side effects (I/O, git commands). Three new modules emerged:
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 47 writeln!().unwrap() calls in export.rs were a panic risk.
The solution: infallible macros:
The maintenance PR landed with zero panic risks remaining.
A persistent bug pattern emerged: the Rust backend and TypeScript frontend had separate type definitions. They drifted. Node #320:
The solution: ts-rs, a library that generates TypeScript types from
Rust structs. Add #[derive(TS)] to a struct, and TypeScript definitions
appear automatically:
Generation alone wasn't enough—drift could return if developers forgot to regenerate. The solution: automation at every level:
Type drift was solved at the source. The problem simply cannot recur.
December 12th saw a flurry of releases as features and fixes landed:
A 9-phase implementation began. The goal: connect ROADMAP.md items to GitHub Issues to decision graph outcomes. Node #476:
The phases unfolded systematically:
The key architectural decisions shaped the user experience:
As of this writing, the decision graph contains:
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.
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.
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.
Every decision mentioned in this story can be browsed interactively.