chore: migrate task tracking from nbd to beans

Replace all .nbd/ ticket stores with .beans/ directories across the
mono-repo (root, edu, nbd, quotesdb). Field mappings: status todo→todo,
in_progress→in-progress, done→completed, closed→scrapped,
archived→completed, backlog→draft; priority numeric→label; type
project→epic. All dependency relationships preserved via --blocked-by.

Add scripts/migrate-nbd-to-beans.sh for reproducible future migrations.

Update CLAUDE.md task-tracking sections (root, edu, nbd, quotesdb) to
reference beans commands instead of nbd commands.

Counts: root 2, edu 48, nbd 38, quotesdb 121 beans created; 0 failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
Elijah Voigt 3 months ago
parent 01d30b45c2
commit 2dd808cdd3

@ -0,0 +1,6 @@
beans:
path: .beans
prefix: vibed-
id_length: 4
default_status: todo
default_type: task

@ -1,10 +1,13 @@
+++
title = "Add justfiles for all projects with lint, check, build, build-release, and release recipes"
priority = 5
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# vibed-0fcp
title: Add justfiles for all projects with lint, check, build, build-release, and release recipes
status: todo
type: task
priority: normal
created_at: 2026-03-10T23:29:17Z
updated_at: 2026-03-10T23:29:17Z
---
## Background
The root `TODO.md` calls for each project in the mono-repo to have a `justfile` with standard recipe names so that any contributor can run the same commands regardless of project type. `just` is a command runner similar to Make but with cleaner syntax.
@ -63,4 +66,4 @@ Not every project needs every recipe; stub missing ones with an error or a no-op
- Recipe names must be consistent across all projects (`lint`, `check`, `build`, `build-release`, `release`).
- Commands are run from the directory containing the `justfile`, so paths are relative to the project directory.
- Add a comment above each recipe explaining what it does.
- Check whether the `just` package is already in each project's Nix dev shell (`flake.nix`); add it if missing.
- Check whether the `just` package is already in each project's Nix dev shell (`flake.nix`); add it if missing.

@ -1,10 +1,13 @@
+++
title = "Add contact footer to all service front-ends"
priority = 3
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# vibed-wqsu
title: Add contact footer to all service front-ends
status: todo
type: task
priority: low
created_at: 2026-03-10T23:29:17Z
updated_at: 2026-03-10T23:29:17Z
---
## Background
The root `TODO.md` calls for a footer on every service front-end with contact info:
@ -61,4 +64,4 @@ Simplest option: add `footer.html` fragment via `[output.html] additional-js` ha
- `edu/theme/index.hbs` (new — copy from mdbook default, add footer)
- `edu/book.toml` (may need `[output.html] theme = "theme"` entry)
- `quotesdb/ui/src/components/footer.rs` (new) or similar
- `quotesdb/ui/src/components/footer.rs` (new) or similar

@ -3,5 +3,13 @@
"superpowers@claude-plugins-official": true,
"plugin-dev@claude-plugins-official": true,
"rust-analyzer-lsp@claude-plugins-official": true
},
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "beans prime" }] }
],
"PreCompact": [
{ "hooks": [{ "type": "command", "command": "beans prime" }] }
]
}
}

@ -327,59 +327,60 @@ Covers:
<task-tracking>
## Task Tracking with nbd
**IMPORTANT**: before you do anything else, run the `beans prime` command and heed its output.
`nbd` is a CLI tool for managing work tickets, designed for agent workflows.
## Task Tracking with beans
`beans` is a CLI tool for managing work tickets (called "beans"), designed for agent workflows.
### Initialisation
```sh
nbd init
beans init
```
Run once in the project root. Creates `.nbd/tickets/`. Safe to run multiple times.
Run once in the project root. Creates `.beans/`. Safe to run multiple times.
### Core commands
```sh
# Create a new ticket (use --ftype md for a human-readable body)
nbd create --title "Add OAuth login" --type feature --priority 7 --ftype md --json
# Create a new bean
beans create --json "Add OAuth login" --type feature --priority high --status todo
# List all open tickets (sorted by priority)
nbd list --json
# List all beans
beans list --json
# Read a specific ticket
nbd read <id> --json
# Show a specific bean
beans show --json <id>
# Update a ticket
nbd update <id> --status in_progress --json
nbd update <id> --status done --json
# Update a bean
beans update --json <id> --status in-progress
beans update --json <id> --status completed
```
### Finding what to work on
```sh
# All tickets that are unblocked and ready to start
nbd ready --json
# All beans that are unblocked and ready to start
beans list --json --ready
# The single highest-priority unblocked ticket
nbd next --json
# Filter by type or status
beans list --json --type bug --status todo
```
### Workflow
1. **Before starting** — create a ticket: `nbd create --title "..." --ftype md --json`
2. **When starting** — mark it in progress: `nbd update <id> --status in_progress --json`
3. **When done** — mark it complete: `nbd update <id> --status done --json`
1. **Before starting** — create a bean: `beans create --json "..." --type task --status todo`
2. **When starting** — mark it in progress: `beans update --json <id> --status in-progress`
3. **When done** — mark it complete: `beans update --json <id> --status completed`
### Guidelines
- **Always pass `--json`** to every command for structured, unambiguous output.
- **Always pass `--ftype md`** when creating tickets — markdown format keeps the body human-readable.
- Use `jq` to parse and transform JSON output when needed.
- Priority scale 010: use **79** for bugs, **5** for normal tasks, **3** for nice-to-haves.
- `--type` choices: `project`, `feature`, `task`, `bug`.
- Use `--deps id1,id2` to express blockers — tickets that must be done first.
- Create tickets *before* starting non-trivial tasks, not after.
- `--priority` choices: `critical`, `high`, `normal`, `low`, `deferred`.
- `--type` choices: `milestone`, `epic`, `feature`, `task`, `bug`.
- Use `--blocked-by <id>` to express blockers — beans that must be done first.
- Create beans *before* starting non-trivial tasks, not after.
</task-tracking>

@ -0,0 +1,6 @@
beans:
path: .beans
prefix: edu-
id_length: 4
default_status: todo
default_type: task

@ -1,8 +1,11 @@
+++
title = "Markov exercise: Simulating a Random Walk (Rust)"
priority = 7
status = "archived"
ticket_type = "task"
dependencies = []
+++
Write Section 5 of edu/markov.md: Exercise 2 — Simulating a Random Walk\n\nLearning objectives:\n- Model a countably-finite state space (bounded integers) in Rust\n- Implement reflecting boundary conditions\n- Aggregate results from many trials into a histogram\n\nContent to produce:\n- Setup instructions (reuse or extend Exercise 1 project)\n- Step-by-step hints:\n 1. Define RandomWalk with min, max, prob_right fields\n 2. Implement step with boundary reflection (clamp or reverse)\n 3. Implement histogram by running simulate() many times\n 4. Print histogram as ASCII bar chart\n 5. Observe convergence toward uniform (symmetric walk) or skewed (asymmetric)\n- Full reference solution\n\nTarget: replace the stub in edu/markov.md §5
---
# edu-0w1v
title: 'Markov exercise: Simulating a Random Walk (Rust)'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 5 of edu/markov.md: Exercise 2 — Simulating a Random Walk\n\nLearning objectives:\n- Model a countably-finite state space (bounded integers) in Rust\n- Implement reflecting boundary conditions\n- Aggregate results from many trials into a histogram\n\nContent to produce:\n- Setup instructions (reuse or extend Exercise 1 project)\n- Step-by-step hints:\n 1. Define RandomWalk with min, max, prob_right fields\n 2. Implement step with boundary reflection (clamp or reverse)\n 3. Implement histogram by running simulate() many times\n 4. Print histogram as ASCII bar chart\n 5. Observe convergence toward uniform (symmetric walk) or skewed (asymmetric)\n- Full reference solution\n\nTarget: replace the stub in edu/markov.md §5

@ -1,10 +1,12 @@
+++
title = "§6 Recognizing Atoms: Integers, Booleans, Strings, Symbols"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-16fy
title: '§6 Recognizing Atoms: Integers, Booleans, Strings, Symbols'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §6 Recognizing Atoms: Integers, Booleans, Strings, Symbols — Stub to fill

@ -1,8 +1,11 @@
+++
title = "Markov lesson: What Is a Markov Chain?"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 1 of edu/markov.md: 'What Is a Markov Chain?'\n\nLearning objectives:\n- Define the Markov property (memorylessness)\n- Give 34 concrete real-world examples (weather, board games, web surfing, genetics)\n- Explain why the Markov property is a useful modelling assumption\n- Introduce the notation P(Xₙ₊₁ = s | X₀, …, Xₙ) = P(Xₙ₊₁ = s | Xₙ)\n\nContent to produce:\n- 35 paragraphs of prose\n- At least one illustrative example worked through informally\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §1
---
# edu-18qe
title: 'Markov lesson: What Is a Markov Chain?'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
Write Section 1 of edu/markov.md: 'What Is a Markov Chain?'\n\nLearning objectives:\n- Define the Markov property (memorylessness)\n- Give 34 concrete real-world examples (weather, board games, web surfing, genetics)\n- Explain why the Markov property is a useful modelling assumption\n- Introduce the notation P(Xₙ₊₁ = s | X₀, …, Xₙ) = P(Xₙ₊₁ = s | Xₙ)\n\nContent to produce:\n- 35 paragraphs of prose\n- At least one illustrative example worked through informally\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §1

@ -1,10 +1,13 @@
+++
title = "§12 Exercise 5: Retrieval-Augmented Generation"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-1oh8
title: '§12 Exercise 5: Retrieval-Augmented Generation'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §12 Exercise 5 — Retrieval-Augmented Generation — Stub to fill
File: `edu/src/vector-db.md`, section `### 12. Exercise 5 — Retrieval-Augmented Generation`
@ -87,4 +90,4 @@ Print the retrieved passages first (so the reader can see what context was used)
## Reference solution
Full `main.rs` inside `<details>`. Keep `retrieve`, `build_prompt`, and `call_llm` as clearly named separate functions. The `main` function should be a thin orchestrator.
Full `main.rs` inside `<details>`. Keep `retrieve`, `build_prompt`, and `call_llm` as clearly named separate functions. The `main` function should be a thin orchestrator.

@ -1,8 +1,11 @@
+++
title = "Markov lesson: Applications and Further Reading"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 10 of edu/markov.md: 'Applications and Further Reading'\n\nLearning objectives:\n- Survey real-world applications: PageRank, MCMC, HMMs, RL, bioinformatics\n- Give a 23 sentence description of each application and how Markov chains appear\n- Point to concrete next steps for learners who want to go deeper\n\nContent to produce:\n- Application survey (57 topics, each 23 sentences)\n- Annotated reading list:\n * 'Introduction to Probability' (Blitzstein & Hwang) — free PDF\n * 'Markov Chains' (Norris) — rigorous treatment\n * Sutton & Barto 'Reinforcement Learning' — RL connection\n * The Metropolis-Hastings algorithm article on Wikipedia\n- Rust ecosystem pointers (crates for probabilistic modelling)\n\nTarget: replace the stub in edu/markov.md §10
---
# edu-34co
title: 'Markov lesson: Applications and Further Reading'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 10 of edu/markov.md: 'Applications and Further Reading'\n\nLearning objectives:\n- Survey real-world applications: PageRank, MCMC, HMMs, RL, bioinformatics\n- Give a 23 sentence description of each application and how Markov chains appear\n- Point to concrete next steps for learners who want to go deeper\n\nContent to produce:\n- Application survey (57 topics, each 23 sentences)\n- Annotated reading list:\n * 'Introduction to Probability' (Blitzstein & Hwang) — free PDF\n * 'Markov Chains' (Norris) — rigorous treatment\n * Sutton & Barto 'Reinforcement Learning' — RL connection\n * The Metropolis-Hastings algorithm article on Wikipedia\n- Rust ecosystem pointers (crates for probabilistic modelling)\n\nTarget: replace the stub in edu/markov.md §10

@ -1,10 +1,12 @@
+++
title = "§11 Checking Special Forms"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-3sww
title: §11 Checking Special Forms
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §11 Checking Special Forms — Stub to fill

@ -1,8 +1,11 @@
+++
title = "Markov exercise: N-gram Generalization (Rust)"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 8 of edu/markov.md: Exercise 4 — N-gram Generalization\n\nLearning objectives:\n- Generalize from bigrams to arbitrary-order n-gram chains\n- Use Vec<String> as a HashMap key (or a joined string)\n- Empirically compare output quality for n = 1, 2, 3, 4\n\nContent to produce:\n- Setup instructions (extend Exercise 3 project)\n- Step-by-step hints:\n 1. Modify train to use a sliding window of n words as the key\n 2. Modify generate to maintain a deque/window of the last n words\n 3. Run on the same corpus with n = 1, 2, 3, 4 and print 50 words each\n 4. Discuss observations: when does it start memorising the corpus?\n- Full reference solution\n- Stretch goal: implement character-level n-grams instead of word-level\n\nTarget: replace the stub in edu/markov.md §8
---
# edu-4gok
title: 'Markov exercise: N-gram Generalization (Rust)'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
Write Section 8 of edu/markov.md: Exercise 4 — N-gram Generalization\n\nLearning objectives:\n- Generalize from bigrams to arbitrary-order n-gram chains\n- Use Vec<String> as a HashMap key (or a joined string)\n- Empirically compare output quality for n = 1, 2, 3, 4\n\nContent to produce:\n- Setup instructions (extend Exercise 3 project)\n- Step-by-step hints:\n 1. Modify train to use a sliding window of n words as the key\n 2. Modify generate to maintain a deque/window of the last n words\n 3. Run on the same corpus with n = 1, 2, 3, 4 and print 50 words each\n 4. Discuss observations: when does it start memorising the corpus?\n- Full reference solution\n- Stretch goal: implement character-level n-grams instead of word-level\n\nTarget: replace the stub in edu/markov.md §8

@ -1,10 +1,12 @@
+++
title = "§12 The C Runtime Preamble"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-4kkb
title: §12 The C Runtime Preamble
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §12 The C Runtime Preamble — Stub to fill

@ -1,10 +1,13 @@
+++
title = "edu: write chapter on shader programming"
priority = 3
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# edu-4u7w
title: 'edu: write chapter on shader programming'
status: todo
type: task
priority: low
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## Background
From `edu/TODO.md`: Hands-on: Shader programming.
@ -46,4 +49,4 @@ A practical introduction to GPU shaders, written with Rust as the host language.
## File to create
- `edu/src/shaders.md`
- Add to `edu/src/SUMMARY.md` under a `# Graphics` section
- Add to `edu/src/SUMMARY.md` under a `# Graphics` section

@ -1,10 +1,12 @@
+++
title = "§13 Generating C: Atoms and Expressions"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-63ze
title: '§13 Generating C: Atoms and Expressions'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §13 Generating C: Atoms and Expressions — Stub to fill

@ -1,8 +1,11 @@
+++
title = "Markov exercise: Bigram Text Generator (Rust)"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 7 of edu/markov.md: Exercise 3 — Bigram Text Generator\n\nLearning objectives:\n- Build a HashMap-based transition table from a text corpus\n- Implement weighted random sampling over successor words\n- Generate and print novel word sequences from a seed\n\nContent to produce:\n- Setup instructions (new Cargo project or extend previous, add rand crate)\n- Step-by-step hints:\n 1. Tokenize corpus into words (split_whitespace)\n 2. Build BigramModel::train by iterating consecutive word pairs\n 3. Implement weighted sampling in generate (accumulate weights, compare to rng draw)\n 4. Handle end-of-chain gracefully (seed word not in model)\n 5. Try with a public-domain text (e.g., Project Gutenberg excerpt)\n- Full reference solution\n\nTarget: replace the stub in edu/markov.md §7
---
# edu-6r70
title: 'Markov exercise: Bigram Text Generator (Rust)'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 7 of edu/markov.md: Exercise 3 — Bigram Text Generator\n\nLearning objectives:\n- Build a HashMap-based transition table from a text corpus\n- Implement weighted random sampling over successor words\n- Generate and print novel word sequences from a seed\n\nContent to produce:\n- Setup instructions (new Cargo project or extend previous, add rand crate)\n- Step-by-step hints:\n 1. Tokenize corpus into words (split_whitespace)\n 2. Build BigramModel::train by iterating consecutive word pairs\n 3. Implement weighted sampling in generate (accumulate weights, compare to rng draw)\n 4. Handle end-of-chain gracefully (seed word not in model)\n 5. Try with a public-domain text (e.g., Project Gutenberg excerpt)\n- Full reference solution\n\nTarget: replace the stub in edu/markov.md §7

@ -1,8 +1,11 @@
+++
title = "Markov exercise: Weather Model (Rust)"
priority = 7
status = "archived"
ticket_type = "task"
dependencies = []
+++
Write Section 4 of edu/markov.md: Exercise 1 — Weather Model\n\nLearning objectives:\n- Translate a transition matrix into a Rust struct\n- Use a weighted random draw to implement a single Markov step\n- Run a simulation and print or collect the resulting sequence\n\nContent to produce:\n- Setup instructions (new Cargo project, add rand crate)\n- Step-by-step hints:\n 1. Define the Weather enum and index conversion\n 2. Implement WeatherChain::step using rand::Rng::gen::<f64>()\n 3. Implement WeatherChain::simulate as a loop collecting states\n 4. Run with transition matrix [[0.8, 0.2], [0.4, 0.6]] from Sunny\n 5. Count sunny vs rainy days and compare to stationary distribution\n- Full reference solution (collapsed or at end)\n\nTarget: replace the stub in edu/markov.md §4
---
# edu-7cp2
title: 'Markov exercise: Weather Model (Rust)'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
Write Section 4 of edu/markov.md: Exercise 1 — Weather Model\n\nLearning objectives:\n- Translate a transition matrix into a Rust struct\n- Use a weighted random draw to implement a single Markov step\n- Run a simulation and print or collect the resulting sequence\n\nContent to produce:\n- Setup instructions (new Cargo project, add rand crate)\n- Step-by-step hints:\n 1. Define the Weather enum and index conversion\n 2. Implement WeatherChain::step using rand::Rng::gen::<f64>()\n 3. Implement WeatherChain::simulate as a loop collecting states\n 4. Run with transition matrix [[0.8, 0.2], [0.4, 0.6]] from Sunny\n 5. Count sunny vs rainy days and compare to stationary distribution\n- Full reference solution (collapsed or at end)\n\nTarget: replace the stub in edu/markov.md §4

@ -1,10 +1,26 @@
+++
title = "vector-db"
priority = 5
status = "done"
ticket_type = "project"
dependencies = ["21d9be", "584e0c", "99e1d9", "d9f850", "6ec5ff", "37cdd5", "081a55", "5674ce", "4c961f", "1ef9f4", "e8be9a", "5ed295"]
+++
---
# edu-91j2
title: vector-db
status: completed
type: epic
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:04Z
blocked_by:
- edu-mlut
- edu-hvic
- edu-twtl
- edu-hvmi
- edu-uz3e
- edu-ic66
- edu-pdeo
- edu-paqf
- edu-c98s
- edu-ga52
- edu-dgfl
- edu-1oh8
---
## Project: Vector Database Self-Guided Course
This is the top-level project ticket for `edu/src/vector-db.md` — a self-guided mdbook course on vector databases in the **Vibed Learning** site (`edu/`).
@ -47,4 +63,4 @@ The course is modelled on `edu/src/markov.md`. It teaches vector databases throu
- **KNN query:** `vector_top_k('table', vector('[...]'), k)` table-valued function
- **Distance function:** `vector_distance_cos(a, b)` — 0 = identical, 2 = opposite
This project ticket closes when all 12 section tickets are done and `mdbook build` passes.
This project ticket closes when all 12 section tickets are done and `mdbook build` passes.

@ -1,8 +1,11 @@
+++
title = "Markov lesson: Text Generation with Markov Chains"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 6 of edu/markov.md: 'Text Generation with Markov Chains'\n\nLearning objectives:\n- Explain how words (or characters) become states in a text Markov chain\n- Define bigrams and how they form a transition table from a corpus\n- Discuss why generated text sounds locally plausible but globally incoherent\n- Introduce the concept of order-n chains and the tradeoff between coherence and novelty\n\nContent to produce:\n- 35 paragraphs of prose\n- A short worked bigram example from a 2-sentence sample text (show the table)\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §6
---
# edu-9kuk
title: 'Markov lesson: Text Generation with Markov Chains'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 6 of edu/markov.md: 'Text Generation with Markov Chains'\n\nLearning objectives:\n- Explain how words (or characters) become states in a text Markov chain\n- Define bigrams and how they form a transition table from a corpus\n- Discuss why generated text sounds locally plausible but globally incoherent\n- Introduce the concept of order-n chains and the tradeoff between coherence and novelty\n\nContent to produce:\n- 35 paragraphs of prose\n- A short worked bigram example from a 2-sentence sample text (show the table)\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §6

@ -1,8 +1,11 @@
+++
title = "Markov lesson: Transition Probabilities and Matrices"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 3 of edu/markov.md: 'Transition Probabilities and Matrices'\n\nLearning objectives:\n- Formally define the transition matrix P where P[i][j] = P(next=j | current=i)\n- Explain the stochastic matrix constraint: all rows sum to 1, all entries ≥ 0\n- Show how to compute the distribution after k steps: π₀ Pᵏ\n- Work through a 2×2 weather-model example by hand\n\nContent to produce:\n- 35 paragraphs of prose\n- A worked numeric example (2-state weather chain)\n- LaTeX-style or plain-text matrix notation\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §3
---
# edu-a1al
title: 'Markov lesson: Transition Probabilities and Matrices'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
Write Section 3 of edu/markov.md: 'Transition Probabilities and Matrices'\n\nLearning objectives:\n- Formally define the transition matrix P where P[i][j] = P(next=j | current=i)\n- Explain the stochastic matrix constraint: all rows sum to 1, all entries ≥ 0\n- Show how to compute the distribution after k steps: π₀ Pᵏ\n- Work through a 2×2 weather-model example by hand\n\nContent to produce:\n- 35 paragraphs of prose\n- A worked numeric example (2-state weather chain)\n- LaTeX-style or plain-text matrix notation\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §3

@ -1,10 +1,13 @@
+++
title = "edu: write chapter on co-op worker-owned business structure"
priority = 3
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# edu-al3r
title: 'edu: write chapter on co-op worker-owned business structure'
status: todo
type: task
priority: low
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background
From `edu/TODO.md`: write a chapter about how to structure a co-op profit-sharing worker-owned business.
@ -28,4 +31,4 @@ This is a conceptual/informational chapter, not a Rust hands-on. It fits natural
## Notes
This chapter is explicitly not intended to be authoritative legal or financial advice — add the standard AI-generated disclaimer.
This chapter is explicitly not intended to be authoritative legal or financial advice — add the standard AI-generated disclaimer.

@ -1,10 +1,12 @@
+++
title = "§2 MiniLisp Language Specification"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-azf5
title: §2 MiniLisp Language Specification
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §2 MiniLisp Language Specification — Stub to fill

@ -1,10 +1,31 @@
+++
title = "Course: Writing a Lisp-to-C Compiler in Rust"
priority = 5
status = "done"
ticket_type = "project"
dependencies = ["e8da8b", "a93829", "3aeb62", "5835e9", "3dc36b", "685f5e", "a1a827", "b6c9ad", "a4c9f8", "d0b9f8", "6d40a7", "3e1250", "1eb794", "cbc6e3", "de82f1", "58b37a", "8fa47a", "1d16da"]
+++
---
# edu-b73b
title: 'Course: Writing a Lisp-to-C Compiler in Rust'
status: completed
type: epic
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:03Z
blocked_by:
- edu-ylb8
- edu-azf5
- edu-n9ap
- edu-jzvr
- edu-g1r5
- edu-16fy
- edu-n7zb
- edu-mmbr
- edu-tzzh
- edu-h3yx
- edu-3sww
- edu-4kkb
- edu-63ze
- edu-pyue
- edu-unus
- edu-nc61
- edu-v0ud
- edu-y4e6
---
## Course: Writing a Lisp-to-C Compiler in Rust

@ -1,10 +1,13 @@
+++
title = "§9 Generating Embeddings in Rust"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-c98s
title: §9 Generating Embeddings in Rust
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §9 Generating Embeddings in Rust — Stub to fill
File: `edu/src/vector-db.md`, section `### 9. Generating Embeddings in Rust`
@ -60,4 +63,4 @@ Show a minimal async function that POSTs to the embeddings endpoint and returns
**Choosing between them.** Recommend fastembed for §10§12 because: no API key, no network dependency, deterministic results (important for exercises), sub-100ms per batch on CPU. Use the HTTP approach when you need a specific production-grade model or have one already deployed.
**Dimensionality note.** The `F32_BLOB(d)` column type must match the model's output dimension exactly — you cannot mix dimensions. Change the DDL from the toy `F32_BLOB(3)` used in §6§8 to `F32_BLOB(384)` for BGE-Small, `F32_BLOB(768)` for all-MiniLM-L6-v2, or `F32_BLOB(1536)` for OpenAI text-embedding-3-small. The index must also be dropped and recreated if you change the dimension.
**Dimensionality note.** The `F32_BLOB(d)` column type must match the model's output dimension exactly — you cannot mix dimensions. Change the DDL from the toy `F32_BLOB(3)` used in §6§8 to `F32_BLOB(384)` for BGE-Small, `F32_BLOB(768)` for all-MiniLM-L6-v2, or `F32_BLOB(1536)` for OpenAI text-embedding-3-small. The index must also be dropped and recreated if you change the dimension.

@ -1,10 +1,13 @@
+++
title = "edu: write Machine Learning chapter (self-play game AI, Alpha Go Zero style)"
priority = 3
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# edu-coqp
title: 'edu: write Machine Learning chapter (self-play game AI, Alpha Go Zero style)'
status: todo
type: task
priority: low
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background
From `edu/TODO.md`: Hands-on: Machine Learning; training a computer to play a game by playing against itself (a-la Alpha Go Zero).
@ -40,4 +43,4 @@ A self-play reinforcement learning course. The practical focus is implementing a
## File to create
- `edu/src/ml-self-play.md`
- Add to `edu/src/SUMMARY.md` under a `# Machine Learning` section
- Add to `edu/src/SUMMARY.md` under a `# Machine Learning` section

@ -1,10 +1,13 @@
+++
title = "§11 Exercise 4: Recommendation Engine"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-dgfl
title: '§11 Exercise 4: Recommendation Engine'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §11 Exercise 4 — Recommendation Engine — Stub to fill
File: `edu/src/vector-db.md`, section `### 11. Exercise 4 — Recommendation Engine`
@ -68,4 +71,4 @@ Output format: `"Customers who liked Laptop also liked: Mechanical Keyboard (0.0
## Reference solution
Full `main.rs` inside `<details>`. The `recommend` function should be clearly separated from the setup boilerplate. The recommendation query pattern (SELECT embedding → feed as query to vector_top_k) is the key technique to highlight.
Full `main.rs` inside `<details>`. The `recommend` function should be clearly separated from the setup boilerplate. The recommendation query pattern (SELECT embedding → feed as query to vector_top_k) is the key technique to highlight.

@ -1,10 +1,12 @@
+++
title = "§5 Setting Up the Project"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-g1r5
title: §5 Setting Up the Project
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §5 Setting Up the Project — Stub to fill

@ -1,10 +1,13 @@
+++
title = "§10 Exercise 3: Semantic Document Search"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-ga52
title: '§10 Exercise 3: Semantic Document Search'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §10 Exercise 3 — Semantic Document Search — Stub to fill
File: `edu/src/vector-db.md`, section `### 10. Exercise 3 — Semantic Document Search`
@ -77,4 +80,4 @@ Print results ranked by distance with the passage text.
## Reference solution
Full self-contained `main.rs` inside `<details>`: creates table, embeds and inserts all 15 passages, runs three queries, prints results.
Full self-contained `main.rs` inside `<details>`: creates table, embeds and inserts all 15 passages, runs three queries, prints results.

@ -1,10 +1,12 @@
+++
title = "§10 Symbol Tables and Scope"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-h3yx
title: §10 Symbol Tables and Scope
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §10 Symbol Tables and Scope — Stub to fill

@ -1,10 +1,13 @@
+++
title = "§2 Embeddings"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-hvic
title: §2 Embeddings
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §2 Embeddings — Stub to fill
File: `edu/src/vector-db.md`, section `### 2. Embeddings`
@ -34,4 +37,4 @@ This is a **reading lesson** — no Rust code. Target 400700 words. Follow th
**Practical dimensionalities.** 384 (MiniLM, fast, ~130MB), 768 (BERT-base, sentence-transformers default), 1536 (OpenAI text-embedding-3-small), 3072 (text-embedding-3-large). Larger is not always better — depends on task and dataset.
**Embeddings for non-text data.** Brief mention: CLIP produces image embeddings comparable to text embeddings in the same space (enabling text-to-image search). Product embeddings can be learned from purchase co-occurrence. The vector database stores float arrays regardless of modality.
**Embeddings for non-text data.** Brief mention: CLIP produces image embeddings comparable to text embeddings in the same space (enabling text-to-image search). Product embeddings can be learned from purchase co-occurrence. The vector database stores float arrays regardless of modality.

@ -1,10 +1,13 @@
+++
title = "§4 What Is a Vector Database?"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-hvmi
title: §4 What Is a Vector Database?
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §4 What Is a Vector Database? — Stub to fill
File: `edu/src/vector-db.md`, section `### 4. What Is a Vector Database?`
@ -43,4 +46,4 @@ This is a **reading lesson** — no Rust code. Target 500700 words. Bold lead
- Index build time: one-time cost paid before serving queries.
- Memory footprint: HNSW stores graph edges in RAM; this limits how large the index can grow on a single machine.
**Where sqlite-vec / Turso fits.** sqlite-vec is appropriate for embedded applications, local development, and small-to-medium corpora (up to a few million vectors). Dedicated cloud vector databases (Pinecone, Qdrant, Weaviate) handle larger scale and add features like multi-tenancy, filtering, and distributed search.
**Where sqlite-vec / Turso fits.** sqlite-vec is appropriate for embedded applications, local development, and small-to-medium corpora (up to a few million vectors). Dedicated cloud vector databases (Pinecone, Qdrant, Weaviate) handle larger scale and add features like multi-tenancy, filtering, and distributed search.

@ -1,10 +1,13 @@
+++
title = "§6 Setting Up Turso + sqlite-vec"
priority = 5
status = "closed"
ticket_type = "task"
dependencies = []
+++
---
# edu-ic66
title: §6 Setting Up Turso + sqlite-vec
status: scrapped
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §6 Setting Up Turso + sqlite-vec — ALREADY COMPLETE
This section is fully written in `edu/src/vector-db.md` under `### 6. Setting Up`. No further content work is needed. Mark this ticket done.
@ -18,4 +21,4 @@ This section is fully written in `edu/src/vector-db.md` under `### 6. Setting Up
- Reference table of all sqlite-vec constructs used in later exercises: `F32_BLOB(d)`, `vector()`, `vector_extract()`, `vector_distance_cos()`, `libsql_vector_idx`, `vector_top_k()`
- Creating a `F32_BLOB(3)` vector table
- Creating an HNSW index with `USING libsql_vector_idx(embedding)`
- Complete working `main.rs` listing — produces "SQLite version: x.y.z" and "Database ready."
- Complete working `main.rs` listing — produces "SQLite version: x.y.z" and "Database ready."

@ -1,10 +1,12 @@
+++
title = "§4 Introduction to nom: Parser Combinators"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-jzvr
title: '§4 Introduction to nom: Parser Combinators'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §4 Introduction to nom: Parser Combinators — Stub to fill

@ -1,10 +1,13 @@
+++
title = "§1 What Is a Vector?"
priority = 5
status = "closed"
ticket_type = "task"
dependencies = []
+++
---
# edu-mlut
title: §1 What Is a Vector?
status: scrapped
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §1 What Is a Vector? — ALREADY COMPLETE
This section is fully written in `edu/src/vector-db.md` under `### 1. What Is a Vector?`. No further content work is needed. Mark this ticket done.
@ -15,4 +18,4 @@ This section is fully written in `edu/src/vector-db.md` under `### 1. What Is a
- Geometric intuition in 2D and 3D: magnitude (`‖v‖ = √(Σ vᵢ²)`), direction, orthogonality via dot product
- High-dimensional spaces: the curse of dimensionality, normalisation onto the unit hypersphere, dimensions are not individually interpretable features
- Vectors as representations: the key insight that similarity in meaning corresponds to proximity in vector space — the basis of everything that follows
- Notation used throughout the course: **v**, `v[i]`, `‖v‖`, *d* for dimension, *n* for number of stored vectors
- Notation used throughout the course: **v**, `v[i]`, `‖v‖`, *d* for dimension, *n* for number of stored vectors

@ -1,10 +1,12 @@
+++
title = "§8 Parsing Atoms with nom"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-mmbr
title: §8 Parsing Atoms with nom
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §8 Parsing Atoms with nom — Stub to fill

@ -1,10 +1,12 @@
+++
title = "§7 The Abstract Syntax Tree"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-n7zb
title: §7 The Abstract Syntax Tree
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §7 The Abstract Syntax Tree — Stub to fill

@ -1,10 +1,12 @@
+++
title = "§3 Compiler Architecture: The Pipeline"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-n9ap
title: '§3 Compiler Architecture: The Pipeline'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §3 Compiler Architecture: The Pipeline — Stub to fill

@ -1,10 +1,12 @@
+++
title = "§16 The Compilation Pipeline"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-nc61
title: §16 The Compilation Pipeline
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §16 The Compilation Pipeline — Stub to fill

@ -1,10 +1,13 @@
+++
title = "§8 Exercise 2: K-Nearest Neighbor Search"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-paqf
title: '§8 Exercise 2: K-Nearest Neighbor Search'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §8 Exercise 2 — K-Nearest Neighbor Search — Stub to fill
File: `edu/src/vector-db.md`, section `### 8. Exercise 2 — K-Nearest Neighbor Search`
@ -62,4 +65,4 @@ Query: [0.85, 0.15, 0.25]
## Reference solution
Full `main.rs` inside `<details><summary>Show full solution</summary>`. The solution should re-run setup from §7 (create table, insert data) then run the three KNN queries.
Full `main.rs` inside `<details><summary>Show full solution</summary>`. The solution should re-run setup from §7 (create table, insert data) then run the three KNN queries.

@ -1,10 +1,13 @@
+++
title = "§7 Exercise 1: Storing and Retrieving Vectors"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-pdeo
title: '§7 Exercise 1: Storing and Retrieving Vectors'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:29:59Z
updated_at: 2026-03-10T23:29:59Z
---
## §7 Exercise 1 — Storing and Retrieving Vectors — Stub to fill
File: `edu/src/vector-db.md`, section `### 7. Exercise 1 — Storing and Retrieving Vectors`
@ -71,4 +74,4 @@ SELECT id, label, vector_extract(embedding) FROM items ORDER BY id
## Cargo.toml additions
Add `serde_json = "1"` for JSON array parsing.
Add `serde_json = "1"` for JSON array parsing.

@ -1,10 +1,12 @@
+++
title = "§14 Generating C: Definitions and Functions"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-pyue
title: '§14 Generating C: Definitions and Functions'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §14 Generating C: Definitions and Functions — Stub to fill

@ -1,8 +1,22 @@
+++
title = "markov"
priority = 7
status = "done"
ticket_type = "project"
dependencies = ["fbf323", "738be2", "44ebe7", "257a2a", "64826a", "92a829", "74be50", "1f995a", "68ee16", "5994a6"]
+++
Self-guided Markov chain course in edu/markov.md.\n\nThe course outline lives in edu/markov.md. Each of the 10 section tickets must be completed to flesh out all stubs before this project is done.\n\nSections:\n1. fbf323 — What Is a Markov Chain?\n2. 738be2 — States and Transitions\n3. 44ebe7 — Transition Probabilities and Matrices\n4. 257a2a — Exercise 1: Weather Model (Rust)\n5. 64826a — Exercise 2: Random Walk (Rust)\n6. 92a829 — Text Generation with Markov Chains\n7. 74be50 — Exercise 3: Bigram Text Generator (Rust)\n8. 1f995a — Exercise 4: N-gram Generalization (Rust)\n9. 68ee16 — Stationary Distributions\n10. 5994a6 — Applications and Further Reading
---
# edu-svom
title: markov
status: completed
type: epic
priority: high
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:04Z
blocked_by:
- edu-18qe
- edu-zjy1
- edu-a1al
- edu-7cp2
- edu-0w1v
- edu-9kuk
- edu-6r70
- edu-4gok
- edu-urpp
- edu-34co
---
Self-guided Markov chain course in edu/markov.md.\n\nThe course outline lives in edu/markov.md. Each of the 10 section tickets must be completed to flesh out all stubs before this project is done.\n\nSections:\n1. fbf323 — What Is a Markov Chain?\n2. 738be2 — States and Transitions\n3. 44ebe7 — Transition Probabilities and Matrices\n4. 257a2a — Exercise 1: Weather Model (Rust)\n5. 64826a — Exercise 2: Random Walk (Rust)\n6. 92a829 — Text Generation with Markov Chains\n7. 74be50 — Exercise 3: Bigram Text Generator (Rust)\n8. 1f995a — Exercise 4: N-gram Generalization (Rust)\n9. 68ee16 — Stationary Distributions\n10. 5994a6 — Applications and Further Reading

@ -1,10 +1,13 @@
+++
title = "§3 Vector Similarity"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-twtl
title: §3 Vector Similarity
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §3 Vector Similarity — Stub to fill
File: `edu/src/vector-db.md`, section `### 3. Vector Similarity`
@ -34,4 +37,4 @@ This is a **reading lesson with inline math** — no Rust code. Target 400600
**When to use each.** Text and sentence embeddings: cosine (or dot product if model outputs unit vectors, which many do). Follow the model card's recommendation when specified. Low-dimensional geometric features: L2.
**Worked example.** Use vectors a = [1, 0, 1] and b = [1, 1, 0]. Compute all three by hand and show the arithmetic step by step. Cosine similarity = 0.5, L2 distance ≈ 1.414, dot product = 1. This concretises the formulas before the reader sees them in SQL queries.
**Worked example.** Use vectors a = [1, 0, 1] and b = [1, 1, 0]. Compute all three by hand and show the arithmetic step by step. Cosine similarity = 0.5, L2 distance ≈ 1.414, dot product = 1. This concretises the formulas before the reader sees them in SQL queries.

@ -1,10 +1,13 @@
+++
title = "Deploy edu mdbook to Cloudflare Pages at vibebooks.elijah.run"
priority = 5
status = "done"
ticket_type = "project"
dependencies = []
+++
---
# edu-tx54
title: Deploy edu mdbook to Cloudflare Pages at vibebooks.elijah.run
status: completed
type: epic
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background
From `edu/TODO.md`:
@ -71,4 +74,4 @@ Add a `release` recipe to `edu/justfile` (see justfiles ticket) that triggers th
- `tofu validate && tofu plan` from `edu/infra/`
- `mdbook build` from `edu/` — builds without errors
- After deploy: `curl -I https://vibebooks.elijah.run` returns 200
- After deploy: `curl -I https://vibebooks.elijah.run` returns 200

@ -1,10 +1,12 @@
+++
title = "§9 Parsing S-Expressions and Special Forms"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-tzzh
title: §9 Parsing S-Expressions and Special Forms
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §9 Parsing S-Expressions and Special Forms — Stub to fill

@ -1,10 +1,13 @@
+++
title = "edu: write chapter on creating and training a simple LLM"
priority = 3
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# edu-u2w7
title: 'edu: write chapter on creating and training a simple LLM'
status: todo
type: task
priority: low
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## Background
From `edu/TODO.md`: Hands-on: Creating and training a simple LLM.
@ -44,4 +47,4 @@ A practical course on building a small language model from scratch in Rust, cove
## File to create
- `edu/src/llm-from-scratch.md`
- Add to `edu/src/SUMMARY.md` under the `# Machine Learning` section
- Add to `edu/src/SUMMARY.md` under the `# Machine Learning` section

@ -1,10 +1,12 @@
+++
title = "§15 Generating C: Control Flow and Sequencing"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-unus
title: '§15 Generating C: Control Flow and Sequencing'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §15 Generating C: Control Flow and Sequencing — Stub to fill

@ -1,8 +1,11 @@
+++
title = "Markov lesson: Stationary Distributions"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 9 of edu/markov.md: 'Stationary Distributions'\n\nLearning objectives:\n- Define stationary distribution π: πP = π, Σπᵢ = 1\n- Explain existence and uniqueness conditions: irreducibility and aperiodicity\n- Show how to compute π analytically for a 2-state chain\n- Introduce power iteration as a numerical method\n- Connect to the long-run frequency interpretation from the simulation in Exercise 1\n\nContent to produce:\n- 46 paragraphs of prose\n- Worked 2×2 example: solve πP = π by hand\n- Power iteration pseudocode or brief Rust sketch\n\nTarget: replace the stub in edu/markov.md §9
---
# edu-urpp
title: 'Markov lesson: Stationary Distributions'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 9 of edu/markov.md: 'Stationary Distributions'\n\nLearning objectives:\n- Define stationary distribution π: πP = π, Σπᵢ = 1\n- Explain existence and uniqueness conditions: irreducibility and aperiodicity\n- Show how to compute π analytically for a 2-state chain\n- Introduce power iteration as a numerical method\n- Connect to the long-run frequency interpretation from the simulation in Exercise 1\n\nContent to produce:\n- 46 paragraphs of prose\n- Worked 2×2 example: solve πP = π by hand\n- Power iteration pseudocode or brief Rust sketch\n\nTarget: replace the stub in edu/markov.md §9

@ -1,10 +1,13 @@
+++
title = "§5 Under the Hood: ANN Algorithms"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-uz3e
title: '§5 Under the Hood: ANN Algorithms'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §5 Under the Hood: ANN Algorithms — Stub to fill
File: `edu/src/vector-db.md`, section `### 5. Under the Hood: ANN Algorithms`
@ -58,4 +61,4 @@ IVFFlat requires a training step before data can be inserted. Incremental insert
| Insert | Incremental | Batch (requires training) |
| Memory | Higher (graph edges) | Lower |
| Recall@10 at defaults | ~0.95+ | ~0.90+ (depends on nprobe) |
| Used by | sqlite-vec, Qdrant, Weaviate | pgvector, Faiss |
| Used by | sqlite-vec, Qdrant, Weaviate | pgvector, Faiss |

@ -1,10 +1,12 @@
+++
title = "§17 Testing the Compiler"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-v0ud
title: §17 Testing the Compiler
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §17 Testing the Compiler — Stub to fill

@ -1,10 +1,12 @@
+++
title = "§18 What's Next: Extensions and Further Reading"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-y4e6
title: '§18 What''s Next: Extensions and Further Reading'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §18 What's Next: Extensions and Further Reading — Stub to fill

@ -1,10 +1,12 @@
+++
title = "§1 Introduction: What We're Building"
priority = 5
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# edu-ylb8
title: '§1 Introduction: What We''re Building'
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §1 Introduction: What We're Building — Stub to fill

@ -1,8 +1,11 @@
+++
title = "Markov lesson: States and Transitions"
priority = 7
status = "done"
ticket_type = "task"
dependencies = []
+++
Write Section 2 of edu/markov.md: 'States and Transitions'\n\nLearning objectives:\n- Define state space (finite vs countably infinite)\n- Define a transition as a directed edge between states with an associated probability\n- Introduce state-transition diagrams and how to draw them\n- Distinguish absorbing states, transient states, and recurrent states at an intuitive level\n\nContent to produce:\n- 35 paragraphs of prose\n- A hand-drawn-style ASCII or described state-transition diagram for the weather example\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §2
---
# edu-zjy1
title: 'Markov lesson: States and Transitions'
status: completed
type: task
priority: high
created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
Write Section 2 of edu/markov.md: 'States and Transitions'\n\nLearning objectives:\n- Define state space (finite vs countably infinite)\n- Define a transition as a directed edge between states with an associated probability\n- Introduce state-transition diagrams and how to draw them\n- Distinguish absorbing states, transient states, and recurrent states at an intuitive level\n\nContent to produce:\n- 35 paragraphs of prose\n- A hand-drawn-style ASCII or described state-transition diagram for the weather example\n- No code in this section\n\nTarget: replace the stub in edu/markov.md §2

@ -1 +0,0 @@
cache.db

@ -25,7 +25,7 @@ mdbook build
# Serve locally with live reload (default: http://localhost:3000)
mdbook serve
# Enter the Nix dev shell (provides mdbook + nbd)
# Enter the Nix dev shell (provides mdbook + beans)
nix develop
# or automatically via direnv: cd into the directory
```
@ -52,6 +52,6 @@ Scope for commit messages: `edu` (e.g., `docs(edu): write §3 transition matrice
Ticket IDs appear in commit messages in `[<id>]` format.
Stub sections in content are marked with 🚧 and reference an nbd ticket — fill in content and close the ticket when complete.
Stub sections in content are marked with 🚧 and reference a beans ticket — fill in content and close the ticket when complete.
</conventions>

@ -55,6 +55,9 @@
# NBD task management
nbd.packages.${system}.nbd
# Task management
pkgs.beans
# MCP servers
pkgs.nodejs

@ -0,0 +1,6 @@
beans:
path: .beans
prefix: nbd-
id_length: 4
default_status: todo
default_type: task

@ -1,10 +1,15 @@
+++
title = "Add nbd next subcommand"
priority = 7
status = "done"
ticket_type = "feature"
dependencies = ["887344"]
+++
---
# nbd-08jg
title: Add nbd next subcommand
status: completed
type: feature
priority: high
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-p9na
---
## Summary
Add `nbd next` subcommand that selects the single highest-priority ticket that is
@ -176,4 +181,4 @@ cargo run -- next --json
(Create bug priority 8, task priority 9: with filter, should return the bug.)
- `nbd next --json` returns a JSON object with a `"next"` key containing all ticket fields
including `"id"`.
- `nbd next --filter priority=99 --json` returns `{"next": null}` (no ticket has priority 99).
- `nbd next --filter priority=99 --json` returns `{"next": null}` (no ticket has priority 99).

@ -1,10 +1,15 @@
+++
title = "ASCII graph rendering in display.rs"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = ["9c9ebe"]
+++
---
# nbd-17dp
title: ASCII graph rendering in display.rs
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-csdh
---
Add `format_graph` and `print_graph` to `src/display.rs` to render a ticket dependency DAG as an ASCII tree.
## Motivation
@ -65,4 +70,4 @@ pub fn print_subtree(graph: &TicketGraph, root_id: &str)
- `format_graph` on a two-ticket chain shows the child indented with `└──`.
- `format_graph` with a branching parent shows `├──` for all but the last child and `└──` for the last.
- `format_subtree` only shows the specified root's subtree.
- A cycle in the graph does not cause infinite recursion; the repeated node is labelled `[cycle]`.
- A cycle in the graph does not cause infinite recursion; the repeated node is labelled `[cycle]`.

@ -1,10 +1,13 @@
+++
title = "nbd claude-md command"
priority = 6
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-2i1e
title: nbd claude-md command
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
Add `nbd claude-md` subcommand that prints a ready-to-paste CLAUDE.md snippet for adopting `nbd` in any project. The snippet content is maintained as a source file and baked into the binary at compile time via `include_str!`.
## Motivation
@ -65,4 +68,4 @@ Integration tests (`tests/integration.rs`):
- `src/claude_md_snippet.md` — new file; the canonical snippet content
- `src/main.rs``include_str!` constant, `ClaudeMd` command variant and handler
- `tests/integration.rs` — integration tests
- `README.md` — mention `nbd claude-md` in the Usage section
- `README.md` — mention `nbd claude-md` in the Usage section

@ -1,10 +1,15 @@
+++
title = "Exclude done tickets from nbd list by default"
priority = 7
status = "done"
ticket_type = "feature"
dependencies = ["887344"]
+++
---
# nbd-4w8z
title: Exclude done tickets from nbd list by default
status: completed
type: feature
priority: high
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-p9na
---
## Summary
Change `nbd list` to hide `done` tickets by default. Users must explicitly opt in
@ -130,4 +135,4 @@ nbd list --json
- `src/filter.rs``matches_status`, `matches_except_status` methods
- `src/tests.rs` — unit tests for new filter methods
- `tests/integration.rs` — new tests, update any affected existing tests
- `README.md` — updated usage section
- `README.md` — updated usage section

@ -1,10 +1,15 @@
+++
title = "Tests for nbd graph command"
priority = 5
status = "done"
ticket_type = "task"
dependencies = ["9ad11f"]
+++
---
# nbd-56ho
title: Tests for nbd graph command
status: completed
type: task
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-d9dh
---
Add comprehensive unit and integration tests for the `nbd graph` command introduced across tickets `9c9ebe`, `e14172`, and `9ad11f`.
## Unit tests (src/tests.rs)
@ -87,4 +92,4 @@ test_graph_partial_id
## Files touched
- `src/tests.rs` — unit tests for `TicketGraph` and `format_graph` / `format_subtree`
- `tests/integration.rs` — CLI-level integration tests
- `tests/integration.rs` — CLI-level integration tests

@ -1,10 +1,13 @@
+++
title = "Print tickets in markdown format instead of key-value table"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-6j0q
title: Print tickets in markdown format instead of key-value table
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Goal
When a ticket is printed to stdout (e.g. by `nbd read`, `nbd create`, `nbd archive`, `nbd next`, `nbd update` without `--json`), it should be rendered as markdown with TOML frontmatter — the same format used by `--ftype md` files on disk — rather than the current key-value table.
@ -94,4 +97,4 @@ cargo run -- create --title "Test ticket" --body "Some body text" --priority 7 -
# dependencies = []
# +++
# Some body text
```
```

@ -1,10 +1,13 @@
+++
title = "Add backlog status to tickets"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-7cab
title: Add backlog status to tickets
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal
Add a `backlog` status variant so tickets can be created without immediately surfacing in the active work queue. Tickets in `backlog` are created but intentionally deferred; they should not appear in `nbd list`, `nbd ready`, or `nbd next` by default.
@ -77,4 +80,4 @@ cargo run -- create --title "Backlog item" --status backlog --json
cargo run -- list --json # should NOT appear
cargo run -- list --all --json # should appear
cargo run -- ready --json # should NOT appear
```
```

@ -1,10 +1,13 @@
+++
title = "Add status convenience sub-commands (open, start, complete, close)"
priority = 5
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-8yn8
title: Add status convenience sub-commands (open, start, complete, close)
status: todo
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem
`nbd update <id> --status <x>` is verbose for the most common lifecycle transitions. `nbd archive` already exists as a top-level convenience — the same pattern should apply to all transitions.
@ -45,4 +48,4 @@ Wire up in `dispatch()` following the same pattern as `Commands::Archive`.
**`tests/integration.rs`**
Add integration tests for each command analogous to the existing archive test.
Add integration tests for each command analogous to the existing archive test.

@ -1,10 +1,13 @@
+++
title = "nbd init command"
priority = 7
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-95l6
title: nbd init command
status: completed
type: feature
priority: high
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
Add an explicit `nbd init` subcommand that creates `.nbd/tickets/` in the current working directory, analogous to `git init`.
## Motivation
@ -30,4 +33,4 @@ Currently users must run `mkdir -p .nbd/tickets` manually before first use. This
## Files touched
- `src/main.rs` — new `Init` variant and `cmd_init` handler
- `tests/integration.rs` — new integration tests
- `README.md` — update Initialise section
- `README.md` — update Initialise section

@ -1,10 +1,13 @@
+++
title = "Add list status sub-commands (list todo, list backlog, etc.)"
priority = 4
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-9mxu
title: Add list status sub-commands (list todo, list backlog, etc.)
status: todo
type: feature
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
Filtering by status requires the verbose `--filter status=X`. Common patterns like listing only backlog or only completed tickets should have ergonomic shortcuts.
@ -46,4 +49,4 @@ If both `status` and `--filter status=...` are given, merge them (OR behaviour w
**`tests/integration.rs`**
Add tests for each status shorthand.
Add tests for each status shorthand.

@ -1,10 +1,13 @@
+++
title = "Add .nbd/config.toml for per-project defaults"
priority = 5
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-9vrn
title: Add .nbd/config.toml for per-project defaults
status: todo
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
All defaults (output format, file type, default status) are hard-coded in the CLI. Users in a project that always uses `--json` or always creates `md`-format tickets must pass these flags repeatedly. A per-project config file would let them set these once.
@ -70,4 +73,4 @@ After creating the tickets directory, write `.nbd/config.toml` with default valu
## Dependencies
None. Can be implemented independently of other tickets.
None. Can be implemented independently of other tickets.

@ -1,10 +1,13 @@
+++
title = "Add graph computation module (src/graph.rs)"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-csdh
title: Add graph computation module (src/graph.rs)
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
Implement `src/graph.rs` — a module that builds a directed dependency graph from a flat list of tickets and provides the data structures needed by the ASCII renderer and JSON output.
## Motivation
@ -73,4 +76,4 @@ No new crates needed. If `IndexMap` insertion-order is useful, `indexmap` can be
- `roots` returns only tickets with no in-graph dependencies.
- `subtree` returns the correct set of IDs for a linear chain.
- `subtree` does not infinite-loop when the data contains a cycle.
- `to_json_value` contains all expected IDs in `nodes` and all edges in `edges`.
- `to_json_value` contains all expected IDs in `nodes` and all edges in `edges`.

@ -1,10 +1,16 @@
+++
title = "Add 'nbd graph' CLI subcommand"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = ["9c9ebe", "e14172"]
+++
---
# nbd-d9dh
title: Add 'nbd graph' CLI subcommand
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-csdh
- nbd-17dp
---
Wire up the `graph` subcommand in `src/main.rs` to expose the ASCII dependency graph and JSON output.
## Motivation
@ -87,4 +93,4 @@ Same shape as full graph but only including nodes and edges reachable from `<id>
## Depends on
- `9c9ebe` — graph computation module
- `e14172` — ASCII rendering functions
- `e14172` — ASCII rendering functions

@ -1,10 +1,13 @@
+++
title = "nbd update diff output"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-fgwx
title: nbd update diff output
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
Show a git-diff-style +/- summary of what changed when `nbd update` is run without `--json`.
## Motivation
@ -50,4 +53,4 @@ Integration test:
- `src/display.rs``format_diff`, `print_diff`
- `src/main.rs``cmd_update` uses `print_diff`
- `src/tests.rs` — unit tests for `format_diff`
- `tests/integration.rs` — integration tests
- `tests/integration.rs` — integration tests

@ -1,10 +1,13 @@
+++
title = "Update claude-md snippet to show --json on all commands"
priority = 4
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# nbd-flbj
title: Update claude-md snippet to show --json on all commands
status: completed
type: task
priority: low
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal
The `nbd claude-md` command emits `src/claude_md_snippet.md` verbatim. The current snippet shows core commands without `--json`, contradicting the guideline at the bottom that says to always pass it.
@ -48,4 +51,4 @@ The `nbd ready` and `nbd next` sections should also include `--json`.
cargo run -- claude-md | grep -c '\-\-json'
```
The count should go up after the change. All existing tests should still pass.
The count should go up after the change. All existing tests should still pass.

@ -1,10 +1,13 @@
+++
title = "nbd ready command"
priority = 7
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-i0fc
title: nbd ready command
status: completed
type: feature
priority: high
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
Add `nbd ready` subcommand that lists tickets which are actionable right now: not yet done and with all dependencies completed.
## Motivation
@ -38,4 +41,4 @@ Unit-style integration tests:
## Files touched
- `src/main.rs` — new `Ready` variant and `cmd_ready` handler
- `tests/integration.rs` — new integration tests
- `tests/integration.rs` — new integration tests

@ -1,10 +1,13 @@
+++
title = "Split archive/closed: archive=done, closed=cancelled"
priority = 6
status = "done"
ticket_type = "bug"
dependencies = []
+++
---
# nbd-jc1v
title: 'Split archive/closed: archive=done, closed=cancelled'
status: completed
type: bug
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem
Currently `nbd archive` sets a ticket's status to `closed`. This conflates two distinct intents:
@ -85,4 +88,4 @@ cargo run -- create --title "Test archive" --json | jq -r '.id' | xargs -I{} car
# → status should be "archived"
cargo run -- create --title "Cancelled ticket" --json | jq -r '.id' | xargs -I{} cargo run -- update {} --status closed --json
# → status should be "closed"
```
```

@ -1,10 +1,13 @@
+++
title = "Scope nbd next and nbd ready by dependency subtree"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-kq6o
title: Scope nbd next and nbd ready by dependency subtree
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Summary
Add an optional positional `<id>` argument to `nbd next` and `nbd ready` that scopes
@ -99,4 +102,4 @@ Add integration tests (using `tempdir`):
```sh
cargo fmt && cargo check && cargo clippy && cargo test
```
```

@ -1,10 +1,13 @@
+++
title = "Fix graph orientation: show goals at root, prerequisites as leaves"
priority = 7
status = "done"
ticket_type = "bug"
dependencies = []
+++
---
# nbd-l38k
title: 'Fix graph orientation: show goals at root, prerequisites as leaves'
status: completed
type: bug
priority: high
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
The dependency graph is inverted. Currently:
@ -42,4 +45,4 @@ The edge semantics paragraph should be updated: "A is a dependency of B" means A
### Tests
Update any graph-related tests in `src/tests.rs` and `tests/integration.rs` that assert the current (inverted) traversal order.
Update any graph-related tests in `src/tests.rs` and `tests/integration.rs` that assert the current (inverted) traversal order.

@ -1,10 +1,15 @@
+++
title = "Fix nbd graph <id>: show ancestry path through ticket, not just subtree"
priority = 6
status = "todo"
ticket_type = "bug"
dependencies = ["668150"]
+++
---
# nbd-lins
title: 'Fix nbd graph <id>: show ancestry path through ticket, not just subtree'
status: todo
type: bug
priority: normal
created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:31Z
blocked_by:
- nbd-l38k
---
## Problem
Currently `nbd graph <id>` renders the subtree **below** the given ticket via dependent edges (tickets blocked by it). After the graph orientation fix (see ticket 668150), `nbd graph <id>` will render the dependency subtree **below** the given ticket.
@ -54,4 +59,4 @@ In `src/main.rs`:
Add integration tests in `tests/integration.rs`:
- Create tickets A, B, C, D, E with A depending on B/C/D, and B depending on E
- Assert `nbd graph B` output contains A and E but not C and D
- Assert `nbd graph B` output contains A and E but not C and D

@ -1,10 +1,13 @@
+++
title = "nbd init: add cache.db to .nbd/.gitignore"
priority = 5
status = "todo"
ticket_type = "task"
dependencies = []
+++
---
# nbd-m9q2
title: 'nbd init: add cache.db to .nbd/.gitignore'
status: todo
type: task
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
`.nbd/cache.db` is a Turso/libsql SQLite cache file created automatically by `list_tickets_cached`. It should never be committed to git. Currently `nbd init` does not create a `.gitignore` to exclude it.
@ -30,4 +33,4 @@ The JSON output for `--json` should include a `gitignore` key indicating the pat
**`tests/integration.rs`**
Add a test that runs `nbd init` and asserts `.nbd/.gitignore` contains `cache.db`. Run `nbd init` a second time and assert the file is unchanged (idempotent).
Add a test that runs `nbd init` and asserts `.nbd/.gitignore` contains `cache.db`. Run `nbd init` a second time and assert the file is unchanged (idempotent).

@ -1,10 +1,13 @@
+++
title = "Add --xml output format that wraps each ticket section in XML tags"
priority = 4
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-mkkm
title: Add --xml output format that wraps each ticket section in XML tags
status: todo
type: feature
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Background
From `nbd/TODO.md`:
@ -101,4 +104,4 @@ All commands that support `--json` should also support `--xml`:
- `nbd migrate`
- `nbd graph` (the JSON graph format has a defined structure; XML should mirror it)
- `nbd claude-md` (wrap snippet in `<snippet>` tag)
- `nbd init` (wrap root path in `<init>`)
- `nbd init` (wrap root path in `<init>`)

@ -1,10 +1,13 @@
+++
title = "Investigate: user-configurable type and status strings with lifecycle phases"
priority = 3
status = "backlog"
ticket_type = "task"
dependencies = []
+++
---
# nbd-n2xz
title: 'Investigate: user-configurable type and status strings with lifecycle phases'
status: draft
type: task
priority: low
created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:29Z
---
## Problem
`type` and `status` are currently hard-coded Rust enums. Users cannot add custom values (e.g., `status = "review"` or `type = "spike"`) without modifying the codebase. But certain status values (`done`, `archived`, `closed`) have special semantics (excluded from `list`/`ready`/`next`; counted as resolved for deps). Making these extensible requires a design that lets users declare which values are "pre-work", "in-work", and "post-work".
@ -45,4 +48,4 @@ Allow `type` to be any string. Keep built-in types (`project`, `feature`, `task`
## Expected output
Create one or more follow-up tickets with a concrete implementation plan and migration strategy.
Create one or more follow-up tickets with a concrete implementation plan and migration strategy.

@ -1,10 +1,13 @@
+++
title = "Add --version flag with X.Y.Z+GitSha format"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-no88
title: Add --version flag with X.Y.Z+GitSha format
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal
Add a `--version` / `-V` flag to `nbd` that prints the version in the format:
@ -123,4 +126,4 @@ fn version_flag_exits_zero_with_semver() {
cargo fmt && cargo check && cargo clippy && cargo test
cargo run -- --version
# Expected output: nbd 0.1.0+<sha>
```
```

@ -1,10 +1,13 @@
+++
title = "Remove id field from ticket JSON body"
priority = 9
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# nbd-o3k8
title: Remove id field from ticket JSON body
status: completed
type: task
priority: critical
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
The ticket ID is already encoded in the filename (`a3f9c2.json`). Storing it redundantly inside the JSON body creates a potential consistency hazard (the two could disagree) and wastes space. The filename should be the sole source of truth for the ID.
## Motivation
@ -77,4 +80,4 @@ Integration tests (`tests/integration.rs`):
- `src/ticket.rs` — add `#[serde(skip)]` to `id`
- `src/store.rs``read_ticket` and `list_tickets` inject id from filename
- `src/tests.rs` — update and add unit tests
- `tests/integration.rs` — add assertion that written files lack `"id"` key
- `tests/integration.rs` — add assertion that written files lack `"id"` key

@ -1,10 +1,13 @@
+++
title = "Turso cache for list performance"
priority = 3
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-oziy
title: Turso cache for list performance
status: completed
type: feature
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
Add a Turso (libsql) cache in `.nbd/cache.db` to accelerate `nbd list` and `nbd ready` for large ticket stores.
## Motivation
@ -64,4 +67,4 @@ Fall back to `list_tickets` on any cache error.
cargo fmt && cargo check && cargo clippy && cargo test
cargo run -- list # should create .nbd/cache.db on first run
cargo run -- list # second run uses cache
```
```

@ -1,10 +1,15 @@
+++
title = "Wire --filter flag into list, ready, and migrate commands"
priority = 8
status = "done"
ticket_type = "feature"
dependencies = ["c2a024"]
+++
---
# nbd-p9na
title: Wire --filter flag into list, ready, and migrate commands
status: completed
type: feature
priority: critical
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-zz62
---
## Summary
Add `--filter KEY=VALUE` (repeatable) to the `list`, `ready`, and `migrate` CLI commands.
@ -147,4 +152,4 @@ JSON format: add `"skipped": N` key to the existing object.
**error cases:**
- `--filter` with unknown key exits non-zero.
- `--filter` with no `=` exits non-zero.
- `--filter` with no `=` exits non-zero.

@ -1,10 +1,13 @@
+++
title = "nbd archive command and Closed status"
priority = 6
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-pq2x
title: nbd archive command and Closed status
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:29Z
---
Add `Status::Closed` (serialised as `"closed"`) and a convenience `nbd archive <id>` command that sets it.
## Motivation
@ -47,4 +50,4 @@ Add `Status::Closed` (serialised as `"closed"`) and a convenience `nbd archive <
- `src/display.rs``status_str` update
- `src/tests.rs` — unit tests
- `tests/integration.rs` — integration tests
- `README.md` — document archive and --all
- `README.md` — document archive and --all

@ -1,10 +1,15 @@
+++
title = "nbd migrate command"
priority = 9
status = "done"
ticket_type = "feature"
dependencies = ["d1634a"]
+++
---
# nbd-q2d1
title: nbd migrate command
status: completed
type: feature
priority: critical
created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:31Z
blocked_by:
- nbd-o3k8
---
Add `nbd migrate` to bring all ticket files on disk into conformance with the current schema. This is the standard mechanism for handling any schema change — field removals, field additions, renames, or type changes.
## Motivation
@ -108,4 +113,4 @@ Integration tests (`tests/integration.rs`):
- `src/display.rs``print_migrate_report`
- `src/tests.rs` — unit tests
- `tests/integration.rs` — integration tests
- `README.md` — document `nbd migrate`
- `README.md` — document `nbd migrate`

@ -1,10 +1,13 @@
+++
title = "Add next <type> filtered sub-commands (next bug, next feature, next task)"
priority = 4
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-ql0c
title: Add next <type> filtered sub-commands (next bug, next feature, next task)
status: todo
type: feature
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
`nbd next --filter type=bug` is verbose. When an engineer wants the highest-priority ready bug, they should be able to say `nbd next bug`.
@ -41,4 +44,4 @@ Explicit `--filter type=...` values are ORed with the positional shorthand, cons
**`tests/integration.rs`**
Add tests verifying that `next bug` returns only bug-type ready tickets and that `next` with no argument still works as before.
Add tests verifying that `next bug` returns only bug-type ready tickets and that `next` with no argument still works as before.

@ -1,10 +1,13 @@
+++
title = "Partial ID matching"
priority = 8
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-rulc
title: Partial ID matching
status: completed
type: feature
priority: critical
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
Allow `nbd read`, `nbd update`, and dependency resolution to accept a prefix of a ticket ID (e.g. `nbd read a3f` resolves to `a3f9c2`).
## Motivation
@ -40,4 +43,4 @@ Integration tests in `tests/integration.rs`:
- `src/store.rs` — new `resolve_id` function
- `src/main.rs``cmd_read`, `cmd_update`, `validate_deps` use `resolve_id`
- `src/tests.rs` — unit tests
- `tests/integration.rs` — integration tests
- `tests/integration.rs` — integration tests

@ -1,10 +1,13 @@
+++
title = "Multiple file format support (md, toml, jsonb)"
priority = 5
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-s16w
title: Multiple file format support (md, toml, jsonb)
status: completed
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
Add `--ftype` flag to `create` and `update` to write tickets in markdown, TOML, or binary JSON (CBOR) in addition to the existing JSON format. Format is detected from file extension on read.
## Motivation
@ -81,4 +84,4 @@ Long-form body text goes here. Supports full markdown.
- `src/tests.rs` — format roundtrip tests
- `tests/integration.rs` — format integration tests
- `README.md` — document `--ftype`
- `docs/ARCHITECTURE.md` — update storage layout section
- `docs/ARCHITECTURE.md` — update storage layout section

@ -1,10 +1,13 @@
+++
title = "Investigate: filtering tickets by project / stream of work"
priority = 3
status = "backlog"
ticket_type = "task"
dependencies = []
+++
---
# nbd-urlz
title: 'Investigate: filtering tickets by project / stream of work'
status: draft
type: task
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
When multiple streams of work coexist (e.g., refactoring vs. new feature), there is no way to select tickets for one stream only. `nbd next` and `nbd list` operate across all tickets.
@ -28,4 +31,4 @@ Investigate by:
## Expected output
Create one or more follow-up tickets with a concrete implementation plan, or close this ticket with a rationale if the existing tools are sufficient.
Create one or more follow-up tickets with a concrete implementation plan, or close this ticket with a rationale if the existing tools are sufficient.

@ -1,10 +1,13 @@
+++
title = "Nix flake for nbd"
priority = 4
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# nbd-wbf7
title: Nix flake for nbd
status: completed
type: task
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
Add `nbd/flake.nix` so that `nbd` can be consumed as a Nix package and used as a CLI tool in other projects in the mono-repo.
## Motivation
@ -35,4 +38,4 @@ The `buildRustPackage` derivation requires a `cargoHash` (or `cargoSha256`). Use
## Files touched
- `nbd/flake.nix` — new file
- `README.md` — add `nix run` usage section
- `README.md` — add `nix run` usage section

@ -1,10 +1,13 @@
+++
title = 'VERSION file: compile into binary via include_str\! and add nbd version subcommand'
priority = 5
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-wi74
title: '''VERSION file: compile into binary via include_str\! and add nbd version subcommand'''
status: todo
type: feature
priority: normal
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem
The current version string is assembled in `main.rs` from `CARGO_PKG_VERSION` (Cargo.toml) and `GIT_SHORT_SHA` (build.rs). There is no `nbd version` subcommand — only `--version`. And the `/work` skill does not bump any version on completion.
@ -73,4 +76,4 @@ The skill should read `VERSION`, parse the semver, increment the appropriate com
- `nbd/build.rs` (update: emit `NBD_VERSION`)
- `nbd/src/main.rs` (update: use `NBD_VERSION`, add `Version` subcommand)
- `nbd/Cargo.toml` (keep version in sync with `VERSION` file)
- `.claude/skills/work/SKILL.md` (update: add version-bump step)
- `.claude/skills/work/SKILL.md` (update: add version-bump step)

@ -1,10 +1,13 @@
+++
title = "Change graph cycle marker from [cycle] to *"
priority = 3
status = "done"
ticket_type = "task"
dependencies = []
+++
---
# nbd-y4nv
title: Change graph cycle marker from [cycle] to *
status: completed
type: task
priority: low
created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Goal
When `nbd graph` renders a node that has already been visited (a node appearing in multiple branches of the tree), it currently labels the repeat occurrence as `[cycle]`. This label is misleading — the node isn't truly in a cycle, it's simply appearing twice in the tree because it's depended on from multiple places. Change the marker to `*` to indicate "this ticket appears elsewhere in the tree".
@ -55,4 +58,4 @@ cargo fmt && cargo check && cargo clippy && cargo test
cargo run -- graph
```
Any test that checks for `[cycle]` in graph output needs updating to expect `*` instead.
Any test that checks for `[cycle]` in graph output needs updating to expect `*` instead.

@ -1,10 +1,13 @@
+++
title = "Add triage status: new default for tickets lacking implementation detail"
priority = 6
status = "todo"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-yh0v
title: 'Add triage status: new default for tickets lacking implementation detail'
status: todo
type: feature
priority: normal
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem
New tickets are created with `status=todo`, implying they are ready to work on. But many tickets need further research or implementation details before work can begin. The TODO describes a `triage` status for exactly this case — tickets that need an LLM or human to fill in details before they become `todo`.
@ -79,4 +82,4 @@ Add unit tests:
- `nbd next` does not include `triage` tickets.
- `nbd list` does not include `triage` tickets by default.
- `nbd list --filter status=triage` shows only triage tickets.
- `nbd list --all` includes `triage` tickets.
- `nbd list --all` includes `triage` tickets.

@ -1,10 +1,13 @@
+++
title = "Implement TicketFilter module with glob matching"
priority = 8
status = "done"
ticket_type = "feature"
dependencies = []
+++
---
# nbd-zz62
title: Implement TicketFilter module with glob matching
status: completed
type: feature
priority: critical
created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Summary
Add a `src/filter.rs` module implementing `TicketFilter`, which parses and applies
@ -129,4 +132,4 @@ The module is `pub(crate)`.
- `TicketFilter::matches` — same key OR correctly (either matches).
- `TicketFilter::matches` — empty filter matches everything.
- `TicketFilter::is_empty` — true when no filters, false when any filter set.
- `TicketFilter::has_status_filter` — true iff status vec is non-empty.
- `TicketFilter::has_status_filter` — true iff status vec is non-empty.

@ -1 +0,0 @@
cache.db

@ -1,8 +0,0 @@
{
"title": "Test archive",
"body": "",
"priority": 5,
"status": "archived",
"dependencies": [],
"ticket_type": "task"
}

@ -1,8 +0,0 @@
{
"title": "Test ticket",
"body": "Some body text",
"priority": 7,
"status": "done",
"dependencies": [],
"ticket_type": "bug"
}

@ -114,77 +114,61 @@ nbd graph [<id>] [--filter KEY=VALUE ...] [--json]
<task-tracking>
## Task Tracking with nbd
## Task Tracking with beans
Use `nbd` to track tasks for work on this project. Since the binary is not
installed, always invoke via `cargo run` from the `nbd/` directory:
Use `beans` to track tasks for work on this project.
```sh
cargo run -- <subcommand> [flags]
```
The `.nbd/` directory at the project root is the ticket store. If it does not
exist yet, initialise it first:
```sh
cargo run -- init
beans init # run once; creates .beans/
```
### Workflow
Always pass `--json` to every command.
Use `jq` to parse and transform the JSON output if necessary.
Always pass `--json` to every command. Use `jq` to parse output when needed.
**Before starting work:** Create a ticket for the task. Use `--ftype md` so the body is stored as human-readable markdown.
**Before starting work:** Create a bean.
```sh
cargo run -- create --title "Add partial ID matching" --type feature --priority 7 --ftype md --json
beans create --json "Add partial ID matching" --type feature --priority high --status todo
```
**When starting a task:** Update its status.
```sh
cargo run -- update <id> --status in_progress --json
beans update --json <id> --status in-progress
```
**When done:** Mark it complete.
```sh
cargo run -- update <id> --status done --json
```
**To get the single best ticket to work on next:**
```sh
cargo run -- next --json
beans update --json <id> --status completed
```
**To see all tickets that are unblocked and ready to start:**
**To see all beans ready to start:**
```sh
cargo run -- ready --json
beans list --json --ready
```
**To see all tickets:**
**To see all beans:**
```sh
cargo run -- list --json
beans list --json
```
**To read a specific ticket:**
**To view a specific bean:**
```sh
cargo run -- read <id> --json
beans show --json <id>
```
### Guidelines
- **Always use `--json`.** It gives structured, unambiguous output on every command.
- **Always use `--ftype md`** when creating tickets. Markdown format keeps the body human-readable in the file browser.
- Create tickets *before* starting non-trivial tasks, not after.
- Use `--deps id1,id2` to express blockers — tickets that must be done first.
- `--priority` follows 010: use 79 for bugs, 5 for normal tasks, 3 for nice-to-haves.
- `--type` choices: `project`, `feature`, `task`, `bug`.
- Create beans *before* starting non-trivial tasks, not after.
- Use `--blocked-by <id>` to express blockers — beans that must be done first.
- `--priority` choices: `critical`, `high`, `normal`, `low`, `deferred`.
- `--type` choices: `milestone`, `epic`, `feature`, `task`, `bug`.
</task-tracking>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save