Skip to content

Roadmap

Daniel Boles edited this page Oct 29, 2026 · 1 revision

Mirrored from ROADMAP.md (content sha256 a6c839cbb224) by scripts/Sync-Wiki.ps1. Edit the source, not this page -- the next sync overwrites it.

BachelorPad+ Full-Product Roadmap

This is not an MVP roadmap. Each phase contributes to the full v1 target.

Status as of 2026-08-23. Three words, meaning three different things:

  • Done — the phase's work is finished.
  • Started — a real, tested slice exists and is reachable from the application. Not that the phase is finished.
  • Built, unwired — the library work exists and is tested, but nothing in the application calls it. Used where that is a deliberate decision rather than an unfinished job, and the reason is always recorded. No phase carries it any more, as of 2026-08-22. It is kept because the state is a real one and will recur, and because the count of phases in it — three, for four sessions — was this project's most useful single number while it was not zero.
# Phase Status Tasks Crates
1 Foundation and workspace Done 01-foundation bp-core, bp-config, bp-theme, bp-ui
2 Core editor Started 02-core-editor bp-buffer, bp-editor
3 File safety and recovery Done 03-file-safety bp-files, bp-history
4 Large-file engine Done 04-large-files bp-buffer
5 Format registry and parser framework Started 05-formats bp-formats
6 Structured formats Started 05-formats bp-data
7 Search engine Started 06-search bp-search
8 Semantic foundation and naming Started 07-semantic bp-semantic, bp-naming
9 Organization and related-note graph Started 07-semantic bp-storage
10 Semantic/hybrid search Not started, decided 07-semantic —
11 Clipboard system Started 08-clipboard bp-clipboard
12 Notebook/execution system Started 09-notebook bp-notebook, bp-execution
13 Research mode Started 10-research bp-research, bp-storage, bp-semantic
14 Security foundation Started 11-security bp-security
15 Encrypted .bpadx documents Started 11-security bp-crypto
16 Advanced security Started 11-security bp-secrets, bp-redaction, bp-audit, bp-integrity
17 Themes/personality/accessibility Started 12-themes-brand bp-theme
18 Windows/Linux platform integration Started 13-platform bp-platform
19 Hardening, fuzzing and benchmarks Started 14-hardening fuzz/ (standalone, and now gated)
20 Packaging, signing, release and upgrade testing Started 14-hardening —

Phase 2 gained thirteen menu rows on 2026-09-10 without anything being built (ADR-0080). Duplicate Line, Move Line Up/Down, the five date/time stamps and the five Markdown constructs were greyed in the build every user runs, on the claim that TextInput will not report its caret. It reports it, and had all along. The phase status does not change -- it was Started and remains so -- but the count of features that work in only one editor surface went from four to zero, which is the number ADR-0018 called the tax of carrying both views.

Whether the flag itself survives is D21, and it is deliberately not answered by that finding: what --editor-view still costs -- no CJK input, checked in Slint's source -- is unchanged, and retiring an editing surface is a larger decision than the discovery that made it askable.

Phase 20 started on 2026-08-23, and what it found is worth knowing before anybody sizes the rest of it. The inventory came first, as ADR-0048 recommends, and turned up four things in a product 1,972 passing tests deep: the binary could not say its own version, a mistyped flag was discarded in silence, every manifest claimed a licence the repository did not contain, and specs.md advertised three flags that did not exist -- one of which made bachelorpad --line 427 server.log try to open a file called 427.

All four are fixed (ADR-0054), and the artefact followed the same day: scripts/New-Release.ps1 builds, stages, archives and checksums both targets, and both archives have been extracted and run. Signing is deferred and self-signing refused outright (ADR-0055) -- so the archives are unsigned and say so, every run, in the same words.

Upgrade testing followed it: what_an_earlier_build_wrote.rs holds committed literals for the four files this product leaves on a disk -- config.toml, recent.toml, the security history and the recovery journal -- each of which had only write-then-read-back coverage, which is trap 7 exactly.

What is left of phase 20 is an icon and a .desktop file (a build-time resource, so a dependency ADR), and a decision about whether there is an installer at all.

Phase 10 was decided on 2026-08-23 without being started, which is a state this table needs a word for. D16 asked what should compute an embedding; the answer is all three sources as choices, with the profile as a ceiling and Cloud behind a per-use gesture (ADR-0056) -- and the axis carrying those three values had existed since ADR-0020. The phase is now three queue items rather than one large thing, listed in project/WORK_QUEUE.md, and the first of them needs neither provider to exist.

Two numbering schemes, reconciled

The phase numbers above are canonical — they are what specs.md and the ADRs refer to.

They are no longer what any menu row refers to. Until 2026-08-22 a greyed row read "not implemented yet (phase 19)" and the number pointed here; ADR-0048 removed every such row, so a phase number is now a planning device rather than something a user can see.

project/tasks/ uses fourteen directories rather than twenty, because several roadmap phases share a task folder (all three security phases live under 11-security, for example). The mapping is the Tasks column. The directories are deliberately not renumbered: they are a coarser grouping of the same plan, not a competing one, and renaming them would break every link that points at them for no gain.

Where the work actually is

Phases 1, 3 and 4 are complete. Every other phase now has a tested slice reachable in the product, and phases 9, 12 and 13 — the three that were "built with no way in" for four sessions — joined them across 2026-08-21/22.

No crate in this workspace is unreachable. That sentence has been the headline of this section since the fourth session, when it was three crates, 9,556 lines and 241 unit tests behind code no user could reach. bp-storage left under ADR-0037, bp-notebook and bp-execution under ADR-0043, and bp-research under ADR-0044.

What actually unblocked the last three was not effort. Each had been sized as a mode -- a large, unscoped thing -- and each turned out to be waiting on a question rather than on work: phase 12 on what a notebook is for (ADR-0043), phase 13 on whether two decisions were a contradiction (ADR-0044), and phase 9 on presentation (ADR-0037). Research mode's last five planned rows went the same way one session later, in the opposite direction (ADR-0046).

The lesson from all four -- "undecided reads like large", and its mirror -- is in DECISIONS.md, which is the one home for a lesson. It is named here rather than retold because it decides whether a phase can be estimated at all, which is this file's subject.

Phase 4 is finished, including the piece it deliberately left out. Find over a document served from disk shipped under ADR-0042 — a resumable scan rather than a threaded one, measured on a 213.5 MiB log: searching 86% while it ran, then 1 of 1 at line 4,800,001. Ctrl+End and a total line count remain refusals with reasons rather than gaps.

Cross-crate tests found seven defects, and all seven are fixed. Until the fourth session every test in the repository tested one crate. Eleven files of cross-crate tests found that bp-search and bp-buffer disagree about what a line is, that bp-formats identified a pretty-printed JSON array as JSON Lines, that the encoder deciding encodings and line endings was pub(crate) inside the shell where no library test could reach it, that YAML had no way in, that bp-notebook runs a cell whose language it could not map through the kernel's interpreter, that bp-files never applies the extended-length path prefix -- and, worst of the seven, that bp-naming would generate a filename Windows treats as a device. That last one is now fixed: the sanitiser tests the stem before the first dot, the way Win32 does, so con.txt becomes con File.txt rather than a save that reports success while writing to the console -- and bp-files refuses such a name outright, which closes the route sanitising never covered, the name a user types into a Save dialog. The last of the seven was a decision rather than a defect and is now ADR-0029: a line break in this product is or and nothing else. There is no #[ignore]d test left anywhere in the tree. DECISIONS.md has the evidence for each.

Phase 4's measurements, kept because they are the claim. The open path classifies from metadata before a byte is read, and all three classes have somewhere to go: an ordinary document opens as it always did, a large one opens and edits with its size in the status bar, and a huge one is served from disk as the reader scrolls (ADR-0030). A few lines of text peaked at 31.3 MiB and a 192 MiB log at 32.1 MiB — a document 240 times the size costs 0.8 MiB more.

It draws in the custom surface in every build, not only under --editor-view, because TextInput owns its own text and cannot be handed a window of a file it does not have. The flag is now precisely a statement about which surface edits a document the rope holds.

Two things in that phase are deliberately not built and each is a refusal with a reason rather than a gap: Ctrl+End and a total line count. Both need the whole file indexed, which for these documents means reading two gigabytes to answer one question while the window is frozen. Find is no longer on that list: ADR-0042 built it, and it is resumable for exactly the reason those two are refused — a window must not be frozen while a file is read.

Two whole-file reads also came off the open path. bp_crypto::is_bpadx needs six bytes and was being handed the entire file, which bp_files::load then read again.

Phase 19's harnesses are inside the gate now, which they were not. fuzz/ declares its own [workspace], so every --workspace command in Invoke-LocalCI.ps1 walked straight past it: five harnesses feeding hostile input to bp-crypto, bp-data, bp-files, bp-formats and bp-notebook, formatted, linted and run by nobody, while this table called the phase Started on the strength of them. Two stages now run them, on both legs, and they are green -- 42 tests, one #[ignore]d for cost with the reason on it. The gate is about two and a half minutes per leg longer, which is what that assurance costs.

The item that gated three sessions is no longer gating. The rope is the editor's storage, bp-editor owns caret, motion, undo and the line operations, and a custom editor view exists behind --editor-view (ADR-0018). Phase 4's large-file work is unblocked either way, because the storage question is settled independently of which view draws.

The parity question is settled, and not in the view's favour. Word wrap is done: a document line can occupy several visual rows, Up and Down move by row, and scrolling is anchored to a line and a row within it. Input-method composition cannot be done at all on Slint 1.17.1 — FocusScope rejects UpdateComposition and CommitComposition and exposes no callback for either, and TextInput is the only item in the toolkit that consumes them. Without it CJK entry does not work, so --editor-view stays opt-in and the default stays TextInput. project/WORK_QUEUE.md records the evidence.

Signing shipped, and with it the last row that was greyed for a missing decision rather than a missing prerequisite. ADR-0031 puts the Ed25519 signing key inside the .bpadx envelope, sealed under a passphrase, which closes the Windows/Linux asymmetry ADR-0026 measured and could not fix. Sign Document acts; Verify Signature already did.

Security profiles (phase 14) are wired. ADR-0020 defines what each of Standard, Private, Confidential and Maximum permits across seven axes, and the named profiles are checked to be monotonic — each at least as restrictive as the one before, on every axis. All three dependants now read the policy: the recovery journal refuses rather than writing plaintext (and deletes what a looser profile already wrote), clipboard history stops recording and is cleared, and bp-storage's record_document drops the title under PathOnly and records nothing under Disabled. The Security menu sets the profile and states what it permits; the status bar shows anything other than the default.

Two limits are deliberate and visible. Profiles requiring an encrypted journal cannot be honoured until bp-crypto (phase 15), so recovery is refused rather than downgraded — the menu says "off until encryption ships". And bp-storage is still not called by the application: that is ADR-0019's product decision, which the profile model makes revisitable rather than reversible by hand.

Clone this wiki locally