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" # vibed-0fcp
priority = 5 title: Add justfiles for all projects with lint, check, build, build-release, and release recipes
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:29:17Z
updated_at: 2026-03-10T23:29:17Z
---
## Background ## 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. 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`). - 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. - 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. - 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" # vibed-wqsu
priority = 3 title: Add contact footer to all service front-ends
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:29:17Z
updated_at: 2026-03-10T23:29:17Z
---
## Background ## Background
The root `TODO.md` calls for a footer on every service front-end with contact info: 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/theme/index.hbs` (new — copy from mdbook default, add footer)
- `edu/book.toml` (may need `[output.html] theme = "theme"` entry) - `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, "superpowers@claude-plugins-official": true,
"plugin-dev@claude-plugins-official": true, "plugin-dev@claude-plugins-official": true,
"rust-analyzer-lsp@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>
## 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 ### Initialisation
```sh ```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 ### Core commands
```sh ```sh
# Create a new ticket (use --ftype md for a human-readable body) # Create a new bean
nbd create --title "Add OAuth login" --type feature --priority 7 --ftype md --json beans create --json "Add OAuth login" --type feature --priority high --status todo
# List all open tickets (sorted by priority) # List all beans
nbd list --json beans list --json
# Read a specific ticket # Show a specific bean
nbd read <id> --json beans show --json <id>
# Update a ticket # Update a bean
nbd update <id> --status in_progress --json beans update --json <id> --status in-progress
nbd update <id> --status done --json beans update --json <id> --status completed
``` ```
### Finding what to work on ### Finding what to work on
```sh ```sh
# All tickets that are unblocked and ready to start # All beans that are unblocked and ready to start
nbd ready --json beans list --json --ready
# The single highest-priority unblocked ticket # Filter by type or status
nbd next --json beans list --json --type bug --status todo
``` ```
### Workflow ### Workflow
1. **Before starting** — create a ticket: `nbd create --title "..." --ftype md --json` 1. **Before starting** — create a bean: `beans create --json "..." --type task --status todo`
2. **When starting** — mark it in progress: `nbd update <id> --status in_progress --json` 2. **When starting** — mark it in progress: `beans update --json <id> --status in-progress`
3. **When done** — mark it complete: `nbd update <id> --status done --json` 3. **When done** — mark it complete: `beans update --json <id> --status completed`
### Guidelines ### Guidelines
- **Always pass `--json`** to every command for structured, unambiguous output. - **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. - 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. - `--priority` choices: `critical`, `high`, `normal`, `low`, `deferred`.
- `--type` choices: `project`, `feature`, `task`, `bug`. - `--type` choices: `milestone`, `epic`, `feature`, `task`, `bug`.
- Use `--deps id1,id2` to express blockers — tickets that must be done first. - Use `--blocked-by <id>` to express blockers — beans that must be done first.
- Create tickets *before* starting non-trivial tasks, not after. - Create beans *before* starting non-trivial tasks, not after.
</task-tracking> </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)" # edu-0w1v
priority = 7 title: 'Markov exercise: Simulating a Random Walk (Rust)'
status = "archived" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-16fy
priority = 5 title: '§6 Recognizing Atoms: Integers, Booleans, Strings, Symbols'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §6 Recognizing Atoms: Integers, Booleans, Strings, Symbols — Stub to fill

@ -1,8 +1,11 @@
+++ ---
title = "Markov lesson: What Is a Markov Chain?" # edu-18qe
priority = 7 title: 'Markov lesson: What Is a Markov Chain?'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-1oh8
priority = 5 title: '§12 Exercise 5: Retrieval-Augmented Generation'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §12 Exercise 5 — Retrieval-Augmented Generation — Stub to fill
File: `edu/src/vector-db.md`, section `### 12. Exercise 5 — Retrieval-Augmented Generation` 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 ## 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" # edu-34co
priority = 7 title: 'Markov lesson: Applications and Further Reading'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-3sww
priority = 5 title: §11 Checking Special Forms
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §11 Checking Special Forms — Stub to fill ## §11 Checking Special Forms — Stub to fill

@ -1,8 +1,11 @@
+++ ---
title = "Markov exercise: N-gram Generalization (Rust)" # edu-4gok
priority = 7 title: 'Markov exercise: N-gram Generalization (Rust)'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-4kkb
priority = 5 title: §12 The C Runtime Preamble
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §12 The C Runtime Preamble — Stub to fill ## §12 The C Runtime Preamble — Stub to fill

@ -1,10 +1,13 @@
+++ ---
title = "edu: write chapter on shader programming" # edu-4u7w
priority = 3 title: 'edu: write chapter on shader programming'
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## Background ## Background
From `edu/TODO.md`: Hands-on: Shader programming. 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 ## File to create
- `edu/src/shaders.md` - `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" # edu-63ze
priority = 5 title: '§13 Generating C: Atoms and Expressions'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §13 Generating C: Atoms and Expressions — Stub to fill

@ -1,8 +1,11 @@
+++ ---
title = "Markov exercise: Bigram Text Generator (Rust)" # edu-6r70
priority = 7 title: 'Markov exercise: Bigram Text Generator (Rust)'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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)" # edu-7cp2
priority = 7 title: 'Markov exercise: Weather Model (Rust)'
status = "archived" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-91j2
priority = 5 title: vector-db
status = "done" status: completed
ticket_type = "project" type: epic
dependencies = ["21d9be", "584e0c", "99e1d9", "d9f850", "6ec5ff", "37cdd5", "081a55", "5674ce", "4c961f", "1ef9f4", "e8be9a", "5ed295"] 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 ## 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/`). 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 - **KNN query:** `vector_top_k('table', vector('[...]'), k)` table-valued function
- **Distance function:** `vector_distance_cos(a, b)` — 0 = identical, 2 = opposite - **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" # edu-9kuk
priority = 7 title: 'Markov lesson: Text Generation with Markov Chains'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-a1al
priority = 7 title: 'Markov lesson: Transition Probabilities and Matrices'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-al3r
priority = 3 title: 'edu: write chapter on co-op worker-owned business structure'
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background ## Background
From `edu/TODO.md`: write a chapter about how to structure a co-op profit-sharing worker-owned business. 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 ## 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" # edu-azf5
priority = 5 title: §2 MiniLisp Language Specification
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §2 MiniLisp Language Specification — Stub to fill ## §2 MiniLisp Language Specification — Stub to fill

@ -1,10 +1,31 @@
+++ ---
title = "Course: Writing a Lisp-to-C Compiler in Rust" # edu-b73b
priority = 5 title: 'Course: Writing a Lisp-to-C Compiler in Rust'
status = "done" status: completed
ticket_type = "project" type: epic
dependencies = ["e8da8b", "a93829", "3aeb62", "5835e9", "3dc36b", "685f5e", "a1a827", "b6c9ad", "a4c9f8", "d0b9f8", "6d40a7", "3e1250", "1eb794", "cbc6e3", "de82f1", "58b37a", "8fa47a", "1d16da"] 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 ## Course: Writing a Lisp-to-C Compiler in Rust

@ -1,10 +1,13 @@
+++ ---
title = "§9 Generating Embeddings in Rust" # edu-c98s
priority = 5 title: §9 Generating Embeddings in Rust
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §9 Generating Embeddings in Rust — Stub to fill ## §9 Generating Embeddings in Rust — Stub to fill
File: `edu/src/vector-db.md`, section `### 9. Generating Embeddings in Rust` 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. **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)" # edu-coqp
priority = 3 title: 'edu: write Machine Learning chapter (self-play game AI, Alpha Go Zero style)'
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background ## 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). 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 ## File to create
- `edu/src/ml-self-play.md` - `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" # edu-dgfl
priority = 5 title: '§11 Exercise 4: Recommendation Engine'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §11 Exercise 4 — Recommendation Engine — Stub to fill ## §11 Exercise 4 — Recommendation Engine — Stub to fill
File: `edu/src/vector-db.md`, section `### 11. Exercise 4 — Recommendation Engine` 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 ## 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" # edu-g1r5
priority = 5 title: §5 Setting Up the Project
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §5 Setting Up the Project — Stub to fill ## §5 Setting Up the Project — Stub to fill

@ -1,10 +1,13 @@
+++ ---
title = "§10 Exercise 3: Semantic Document Search" # edu-ga52
priority = 5 title: '§10 Exercise 3: Semantic Document Search'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §10 Exercise 3 — Semantic Document Search — Stub to fill
File: `edu/src/vector-db.md`, section `### 10. Exercise 3 — Semantic Document Search` 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 ## 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" # edu-h3yx
priority = 5 title: §10 Symbol Tables and Scope
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §10 Symbol Tables and Scope — Stub to fill ## §10 Symbol Tables and Scope — Stub to fill

@ -1,10 +1,13 @@
+++ ---
title = "§2 Embeddings" # edu-hvic
priority = 5 title: §2 Embeddings
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §2 Embeddings — Stub to fill ## §2 Embeddings — Stub to fill
File: `edu/src/vector-db.md`, section `### 2. Embeddings` 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. **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?" # edu-hvmi
priority = 5 title: §4 What Is a Vector Database?
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §4 What Is a Vector Database? — Stub to fill
File: `edu/src/vector-db.md`, section `### 4. What Is a Vector Database?` 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. - 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. - 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" # edu-ic66
priority = 5 title: §6 Setting Up Turso + sqlite-vec
status = "closed" status: scrapped
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §6 Setting Up Turso + sqlite-vec — ALREADY COMPLETE ## §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. 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()` - 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 a `F32_BLOB(3)` vector table
- Creating an HNSW index with `USING libsql_vector_idx(embedding)` - 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" # edu-jzvr
priority = 5 title: '§4 Introduction to nom: Parser Combinators'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §4 Introduction to nom: Parser Combinators — Stub to fill

@ -1,10 +1,13 @@
+++ ---
title = "§1 What Is a Vector?" # edu-mlut
priority = 5 title: §1 What Is a Vector?
status = "closed" status: scrapped
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## §1 What Is a Vector? — ALREADY COMPLETE ## §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. 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 - 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 - 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 - 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" # edu-mmbr
priority = 5 title: §8 Parsing Atoms with nom
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:02Z
updated_at: 2026-03-10T23:30:02Z
---
## §8 Parsing Atoms with nom — Stub to fill ## §8 Parsing Atoms with nom — Stub to fill

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

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

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

@ -1,10 +1,13 @@
+++ ---
title = "§8 Exercise 2: K-Nearest Neighbor Search" # edu-paqf
priority = 5 title: '§8 Exercise 2: K-Nearest Neighbor Search'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §8 Exercise 2 — K-Nearest Neighbor Search — Stub to fill
File: `edu/src/vector-db.md`, section `### 8. Exercise 2 — K-Nearest Neighbor Search` 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 ## 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" # edu-pdeo
priority = 5 title: '§7 Exercise 1: Storing and Retrieving Vectors'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §7 Exercise 1 — Storing and Retrieving Vectors — Stub to fill
File: `edu/src/vector-db.md`, section `### 7. Exercise 1 — Storing and Retrieving Vectors` 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 ## 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" # edu-pyue
priority = 5 title: '§14 Generating C: Definitions and Functions'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §14 Generating C: Definitions and Functions — Stub to fill

@ -1,8 +1,22 @@
+++ ---
title = "markov" # edu-svom
priority = 7 title: markov
status = "done" status: completed
ticket_type = "project" type: epic
dependencies = ["fbf323", "738be2", "44ebe7", "257a2a", "64826a", "92a829", "74be50", "1f995a", "68ee16", "5994a6"] priority: high
+++ created_at: 2026-03-10T23:30:02Z
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 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" # edu-twtl
priority = 5 title: §3 Vector Similarity
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §3 Vector Similarity — Stub to fill ## §3 Vector Similarity — Stub to fill
File: `edu/src/vector-db.md`, section `### 3. Vector Similarity` 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. **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" # edu-tx54
priority = 5 title: Deploy edu mdbook to Cloudflare Pages at vibebooks.elijah.run
status = "done" status: completed
ticket_type = "project" type: epic
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## Background ## Background
From `edu/TODO.md`: 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/` - `tofu validate && tofu plan` from `edu/infra/`
- `mdbook build` from `edu/` — builds without errors - `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" # edu-tzzh
priority = 5 title: §9 Parsing S-Expressions and Special Forms
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §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" # edu-u2w7
priority = 3 title: 'edu: write chapter on creating and training a simple LLM'
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:00Z
updated_at: 2026-03-10T23:30:00Z
---
## Background ## Background
From `edu/TODO.md`: Hands-on: Creating and training a simple LLM. 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 ## File to create
- `edu/src/llm-from-scratch.md` - `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" # edu-unus
priority = 5 title: '§15 Generating C: Control Flow and Sequencing'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §15 Generating C: Control Flow and Sequencing — Stub to fill

@ -1,8 +1,11 @@
+++ ---
title = "Markov lesson: Stationary Distributions" # edu-urpp
priority = 7 title: 'Markov lesson: Stationary Distributions'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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" # edu-uz3e
priority = 5 title: '§5 Under the Hood: ANN Algorithms'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §5 Under the Hood: ANN Algorithms — Stub to fill
File: `edu/src/vector-db.md`, section `### 5. Under the Hood: ANN Algorithms` 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) | | Insert | Incremental | Batch (requires training) |
| Memory | Higher (graph edges) | Lower | | Memory | Higher (graph edges) | Lower |
| Recall@10 at defaults | ~0.95+ | ~0.90+ (depends on nprobe) | | 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" # edu-v0ud
priority = 5 title: §17 Testing the Compiler
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:01Z
updated_at: 2026-03-10T23:30:01Z
---
## §17 Testing the Compiler — Stub to fill ## §17 Testing the Compiler — Stub to fill

@ -1,10 +1,12 @@
+++ ---
title = "§18 What's Next: Extensions and Further Reading" # edu-y4e6
priority = 5 title: '§18 What''s Next: Extensions and Further Reading'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 ## §18 What's Next: Extensions and Further Reading — Stub to fill

@ -1,10 +1,12 @@
+++ ---
title = "§1 Introduction: What We're Building" # edu-ylb8
priority = 5 title: '§1 Introduction: What We''re Building'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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 Introduction: What We're Building — Stub to fill

@ -1,8 +1,11 @@
+++ ---
title = "Markov lesson: States and Transitions" # edu-zjy1
priority = 7 title: 'Markov lesson: States and Transitions'
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: high
+++ created_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 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) # Serve locally with live reload (default: http://localhost:3000)
mdbook serve mdbook serve
# Enter the Nix dev shell (provides mdbook + nbd) # Enter the Nix dev shell (provides mdbook + beans)
nix develop nix develop
# or automatically via direnv: cd into the directory # 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. 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> </conventions>

@ -55,6 +55,9 @@
# NBD task management # NBD task management
nbd.packages.${system}.nbd nbd.packages.${system}.nbd
# Task management
pkgs.beans
# MCP servers # MCP servers
pkgs.nodejs 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" # nbd-08jg
priority = 7 title: Add nbd next subcommand
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["887344"] priority: high
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-p9na
---
## Summary ## Summary
Add `nbd next` subcommand that selects the single highest-priority ticket that is 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.) (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 - `nbd next --json` returns a JSON object with a `"next"` key containing all ticket fields
including `"id"`. 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" # nbd-17dp
priority = 5 title: ASCII graph rendering in display.rs
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["9c9ebe"] 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. Add `format_graph` and `print_graph` to `src/display.rs` to render a ticket dependency DAG as an ASCII tree.
## Motivation ## 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` 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_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. - `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" # nbd-2i1e
priority = 6 title: nbd claude-md command
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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!`. 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 ## Motivation
@ -65,4 +68,4 @@ Integration tests (`tests/integration.rs`):
- `src/claude_md_snippet.md` — new file; the canonical snippet content - `src/claude_md_snippet.md` — new file; the canonical snippet content
- `src/main.rs``include_str!` constant, `ClaudeMd` command variant and handler - `src/main.rs``include_str!` constant, `ClaudeMd` command variant and handler
- `tests/integration.rs` — integration tests - `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" # nbd-4w8z
priority = 7 title: Exclude done tickets from nbd list by default
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["887344"] priority: high
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-p9na
---
## Summary ## Summary
Change `nbd list` to hide `done` tickets by default. Users must explicitly opt in 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/filter.rs``matches_status`, `matches_except_status` methods
- `src/tests.rs` — unit tests for new filter methods - `src/tests.rs` — unit tests for new filter methods
- `tests/integration.rs` — new tests, update any affected existing tests - `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" # nbd-56ho
priority = 5 title: Tests for nbd graph command
status = "done" status: completed
ticket_type = "task" type: task
dependencies = ["9ad11f"] 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`. Add comprehensive unit and integration tests for the `nbd graph` command introduced across tickets `9c9ebe`, `e14172`, and `9ad11f`.
## Unit tests (src/tests.rs) ## Unit tests (src/tests.rs)
@ -87,4 +92,4 @@ test_graph_partial_id
## Files touched ## Files touched
- `src/tests.rs` — unit tests for `TicketGraph` and `format_graph` / `format_subtree` - `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" # nbd-6j0q
priority = 5 title: Print tickets in markdown format instead of key-value table
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Goal ## 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. 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 = [] # dependencies = []
# +++ # +++
# Some body text # Some body text
``` ```

@ -1,10 +1,13 @@
+++ ---
title = "Add backlog status to tickets" # nbd-7cab
priority = 5 title: Add backlog status to tickets
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal ## 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. 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 --json # should NOT appear
cargo run -- list --all --json # should appear cargo run -- list --all --json # should appear
cargo run -- ready --json # should NOT appear cargo run -- ready --json # should NOT appear
``` ```

@ -1,10 +1,13 @@
+++ ---
title = "Add status convenience sub-commands (open, start, complete, close)" # nbd-8yn8
priority = 5 title: Add status convenience sub-commands (open, start, complete, close)
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem ## 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. `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`** **`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" # nbd-95l6
priority = 7 title: nbd init command
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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`. Add an explicit `nbd init` subcommand that creates `.nbd/tickets/` in the current working directory, analogous to `git init`.
## Motivation ## Motivation
@ -30,4 +33,4 @@ Currently users must run `mkdir -p .nbd/tickets` manually before first use. This
## Files touched ## Files touched
- `src/main.rs` — new `Init` variant and `cmd_init` handler - `src/main.rs` — new `Init` variant and `cmd_init` handler
- `tests/integration.rs` — new integration tests - `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.)" # nbd-9mxu
priority = 4 title: Add list status sub-commands (list todo, list backlog, etc.)
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## Problem
Filtering by status requires the verbose `--filter status=X`. Common patterns like listing only backlog or only completed tickets should have ergonomic shortcuts. 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`** **`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" # nbd-9vrn
priority = 5 title: Add .nbd/config.toml for per-project defaults
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## 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. 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 ## 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)" # nbd-csdh
priority = 5 title: Add graph computation module (src/graph.rs)
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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. 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 ## 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. - `roots` returns only tickets with no in-graph dependencies.
- `subtree` returns the correct set of IDs for a linear chain. - `subtree` returns the correct set of IDs for a linear chain.
- `subtree` does not infinite-loop when the data contains a cycle. - `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" # nbd-d9dh
priority = 5 title: Add 'nbd graph' CLI subcommand
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["9c9ebe", "e14172"] 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. Wire up the `graph` subcommand in `src/main.rs` to expose the ASCII dependency graph and JSON output.
## Motivation ## Motivation
@ -87,4 +93,4 @@ Same shape as full graph but only including nodes and edges reachable from `<id>
## Depends on ## Depends on
- `9c9ebe` — graph computation module - `9c9ebe` — graph computation module
- `e14172` — ASCII rendering functions - `e14172` — ASCII rendering functions

@ -1,10 +1,13 @@
+++ ---
title = "nbd update diff output" # nbd-fgwx
priority = 5 title: nbd update diff output
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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`. Show a git-diff-style +/- summary of what changed when `nbd update` is run without `--json`.
## Motivation ## Motivation
@ -50,4 +53,4 @@ Integration test:
- `src/display.rs``format_diff`, `print_diff` - `src/display.rs``format_diff`, `print_diff`
- `src/main.rs``cmd_update` uses `print_diff` - `src/main.rs``cmd_update` uses `print_diff`
- `src/tests.rs` — unit tests for `format_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" # nbd-flbj
priority = 4 title: Update claude-md snippet to show --json on all commands
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal ## 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. 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' 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" # nbd-i0fc
priority = 7 title: nbd ready command
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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. Add `nbd ready` subcommand that lists tickets which are actionable right now: not yet done and with all dependencies completed.
## Motivation ## Motivation
@ -38,4 +41,4 @@ Unit-style integration tests:
## Files touched ## Files touched
- `src/main.rs` — new `Ready` variant and `cmd_ready` handler - `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" # nbd-jc1v
priority = 6 title: 'Split archive/closed: archive=done, closed=cancelled'
status = "done" status: completed
ticket_type = "bug" type: bug
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem ## Problem
Currently `nbd archive` sets a ticket's status to `closed`. This conflates two distinct intents: 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" # → status should be "archived"
cargo run -- create --title "Cancelled ticket" --json | jq -r '.id' | xargs -I{} cargo run -- update {} --status closed --json cargo run -- create --title "Cancelled ticket" --json | jq -r '.id' | xargs -I{} cargo run -- update {} --status closed --json
# → status should be "closed" # → status should be "closed"
``` ```

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

@ -1,10 +1,13 @@
+++ ---
title = "Fix graph orientation: show goals at root, prerequisites as leaves" # nbd-l38k
priority = 7 title: 'Fix graph orientation: show goals at root, prerequisites as leaves'
status = "done" status: completed
ticket_type = "bug" type: bug
dependencies = [] priority: high
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## Problem
The dependency graph is inverted. Currently: 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 ### 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" # nbd-lins
priority = 6 title: 'Fix nbd graph <id>: show ancestry path through ticket, not just subtree'
status = "todo" status: todo
ticket_type = "bug" type: bug
dependencies = ["668150"] priority: normal
+++ created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:31Z
blocked_by:
- nbd-l38k
---
## Problem ## 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. 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`: 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 - 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" # nbd-m9q2
priority = 5 title: 'nbd init: add cache.db to .nbd/.gitignore'
status = "todo" status: todo
ticket_type = "task" type: task
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## 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. `.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`** **`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" # nbd-mkkm
priority = 4 title: Add --xml output format that wraps each ticket section in XML tags
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Background ## Background
From `nbd/TODO.md`: From `nbd/TODO.md`:
@ -101,4 +104,4 @@ All commands that support `--json` should also support `--xml`:
- `nbd migrate` - `nbd migrate`
- `nbd graph` (the JSON graph format has a defined structure; XML should mirror it) - `nbd graph` (the JSON graph format has a defined structure; XML should mirror it)
- `nbd claude-md` (wrap snippet in `<snippet>` tag) - `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" # nbd-n2xz
priority = 3 title: 'Investigate: user-configurable type and status strings with lifecycle phases'
status = "backlog" status: draft
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:29Z
updated_at: 2026-03-10T23:30:29Z
---
## Problem ## 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". `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 ## 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" # nbd-no88
priority = 5 title: Add --version flag with X.Y.Z+GitSha format
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Goal ## Goal
Add a `--version` / `-V` flag to `nbd` that prints the version in the format: 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 fmt && cargo check && cargo clippy && cargo test
cargo run -- --version cargo run -- --version
# Expected output: nbd 0.1.0+<sha> # Expected output: nbd 0.1.0+<sha>
``` ```

@ -1,10 +1,13 @@
+++ ---
title = "Remove id field from ticket JSON body" # nbd-o3k8
priority = 9 title: Remove id field from ticket JSON body
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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. 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 ## Motivation
@ -77,4 +80,4 @@ Integration tests (`tests/integration.rs`):
- `src/ticket.rs` — add `#[serde(skip)]` to `id` - `src/ticket.rs` — add `#[serde(skip)]` to `id`
- `src/store.rs``read_ticket` and `list_tickets` inject id from filename - `src/store.rs``read_ticket` and `list_tickets` inject id from filename
- `src/tests.rs` — update and add unit tests - `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" # nbd-oziy
priority = 3 title: Turso cache for list performance
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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. Add a Turso (libsql) cache in `.nbd/cache.db` to accelerate `nbd list` and `nbd ready` for large ticket stores.
## Motivation ## Motivation
@ -64,4 +67,4 @@ Fall back to `list_tickets` on any cache error.
cargo fmt && cargo check && cargo clippy && cargo test cargo fmt && cargo check && cargo clippy && cargo test
cargo run -- list # should create .nbd/cache.db on first run cargo run -- list # should create .nbd/cache.db on first run
cargo run -- list # second run uses cache cargo run -- list # second run uses cache
``` ```

@ -1,10 +1,15 @@
+++ ---
title = "Wire --filter flag into list, ready, and migrate commands" # nbd-p9na
priority = 8 title: Wire --filter flag into list, ready, and migrate commands
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["c2a024"] priority: critical
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:32Z
blocked_by:
- nbd-zz62
---
## Summary ## Summary
Add `--filter KEY=VALUE` (repeatable) to the `list`, `ready`, and `migrate` CLI commands. 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:** **error cases:**
- `--filter` with unknown key exits non-zero. - `--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" # nbd-pq2x
priority = 6 title: nbd archive command and Closed status
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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. Add `Status::Closed` (serialised as `"closed"`) and a convenience `nbd archive <id>` command that sets it.
## Motivation ## Motivation
@ -47,4 +50,4 @@ Add `Status::Closed` (serialised as `"closed"`) and a convenience `nbd archive <
- `src/display.rs``status_str` update - `src/display.rs``status_str` update
- `src/tests.rs` — unit tests - `src/tests.rs` — unit tests
- `tests/integration.rs` — integration 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" # nbd-q2d1
priority = 9 title: nbd migrate command
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = ["d1634a"] 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. 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 ## Motivation
@ -108,4 +113,4 @@ Integration tests (`tests/integration.rs`):
- `src/display.rs``print_migrate_report` - `src/display.rs``print_migrate_report`
- `src/tests.rs` — unit tests - `src/tests.rs` — unit tests
- `tests/integration.rs` — integration 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)" # nbd-ql0c
priority = 4 title: Add next <type> filtered sub-commands (next bug, next feature, next task)
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## 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`. `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`** **`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" # nbd-rulc
priority = 8 title: Partial ID matching
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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`). 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 ## Motivation
@ -40,4 +43,4 @@ Integration tests in `tests/integration.rs`:
- `src/store.rs` — new `resolve_id` function - `src/store.rs` — new `resolve_id` function
- `src/main.rs``cmd_read`, `cmd_update`, `validate_deps` use `resolve_id` - `src/main.rs``cmd_read`, `cmd_update`, `validate_deps` use `resolve_id`
- `src/tests.rs` — unit tests - `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)" # nbd-s16w
priority = 5 title: Multiple file format support (md, toml, jsonb)
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] 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. 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 ## Motivation
@ -81,4 +84,4 @@ Long-form body text goes here. Supports full markdown.
- `src/tests.rs` — format roundtrip tests - `src/tests.rs` — format roundtrip tests
- `tests/integration.rs` — format integration tests - `tests/integration.rs` — format integration tests
- `README.md` — document `--ftype` - `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" # nbd-urlz
priority = 3 title: 'Investigate: filtering tickets by project / stream of work'
status = "backlog" status: draft
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## 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. 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 ## 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" # nbd-wbf7
priority = 4 title: Nix flake for nbd
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] 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. 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 ## Motivation
@ -35,4 +38,4 @@ The `buildRustPackage` derivation requires a `cargoHash` (or `cargoSha256`). Use
## Files touched ## Files touched
- `nbd/flake.nix` — new file - `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' # nbd-wi74
priority = 5 title: '''VERSION file: compile into binary via include_str\! and add nbd version subcommand'''
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Problem ## 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. 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/build.rs` (update: emit `NBD_VERSION`)
- `nbd/src/main.rs` (update: use `NBD_VERSION`, add `Version` subcommand) - `nbd/src/main.rs` (update: use `NBD_VERSION`, add `Version` subcommand)
- `nbd/Cargo.toml` (keep version in sync with `VERSION` file) - `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 *" # nbd-y4nv
priority = 3 title: Change graph cycle marker from [cycle] to *
status = "done" status: completed
ticket_type = "task" type: task
dependencies = [] priority: low
+++ created_at: 2026-03-10T23:30:30Z
updated_at: 2026-03-10T23:30:30Z
---
## Goal ## 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". 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 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" # nbd-yh0v
priority = 6 title: 'Add triage status: new default for tickets lacking implementation detail'
status = "todo" status: todo
ticket_type = "feature" type: feature
dependencies = [] priority: normal
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Problem ## 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`. 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 next` does not include `triage` tickets.
- `nbd list` does not include `triage` tickets by default. - `nbd list` does not include `triage` tickets by default.
- `nbd list --filter status=triage` shows only triage tickets. - `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" # nbd-zz62
priority = 8 title: Implement TicketFilter module with glob matching
status = "done" status: completed
ticket_type = "feature" type: feature
dependencies = [] priority: critical
+++ created_at: 2026-03-10T23:30:31Z
updated_at: 2026-03-10T23:30:31Z
---
## Summary ## Summary
Add a `src/filter.rs` module implementing `TicketFilter`, which parses and applies 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` — same key OR correctly (either matches).
- `TicketFilter::matches` — empty filter matches everything. - `TicketFilter::matches` — empty filter matches everything.
- `TicketFilter::is_empty` — true when no filters, false when any filter set. - `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>
## Task Tracking with nbd ## Task Tracking with beans
Use `nbd` to track tasks for work on this project. Since the binary is not Use `beans` to track tasks for work on this project.
installed, always invoke via `cargo run` from the `nbd/` directory:
```sh ```sh
cargo run -- <subcommand> [flags] beans init # run once; creates .beans/
```
The `.nbd/` directory at the project root is the ticket store. If it does not
exist yet, initialise it first:
```sh
cargo run -- init
``` ```
### Workflow ### Workflow
Always pass `--json` to every command. Always pass `--json` to every command. Use `jq` to parse output when needed.
Use `jq` to parse and transform the JSON output if necessary.
**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 ```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. **When starting a task:** Update its status.
```sh ```sh
cargo run -- update <id> --status in_progress --json beans update --json <id> --status in-progress
``` ```
**When done:** Mark it complete. **When done:** Mark it complete.
```sh ```sh
cargo run -- update <id> --status done --json beans update --json <id> --status completed
```
**To get the single best ticket to work on next:**
```sh
cargo run -- next --json
``` ```
**To see all tickets that are unblocked and ready to start:** **To see all beans ready to start:**
```sh ```sh
cargo run -- ready --json beans list --json --ready
``` ```
**To see all tickets:** **To see all beans:**
```sh ```sh
cargo run -- list --json beans list --json
``` ```
**To read a specific ticket:** **To view a specific bean:**
```sh ```sh
cargo run -- read <id> --json beans show --json <id>
``` ```
### Guidelines ### Guidelines
- **Always use `--json`.** It gives structured, unambiguous output on every command. - **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 beans *before* starting non-trivial tasks, not after.
- Create tickets *before* starting non-trivial tasks, not after. - Use `--blocked-by <id>` to express blockers — beans that must be done first.
- Use `--deps id1,id2` to express blockers — tickets that must be done first. - `--priority` choices: `critical`, `high`, `normal`, `low`, `deferred`.
- `--priority` follows 010: use 79 for bugs, 5 for normal tasks, 3 for nice-to-haves. - `--type` choices: `milestone`, `epic`, `feature`, `task`, `bug`.
- `--type` choices: `project`, `feature`, `task`, `bug`.
</task-tracking> </task-tracking>

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

Loading…
Cancel
Save