# iqdb-index -- Roadmap
> Path from scaffold to a stable 1.0. Hard parts are front-loaded; each phase has hard exit criteria.
>
> **Anti-deferral rule:** no listed hard task moves to a later phase unless this file records the move and the reason.
---
## v0.1.0 -- Scaffold (DONE)
Compiles, CI green, structure correct, no domain logic.
- [x] Manifest, README, CHANGELOG, REPS, license, CI, lints in place.
- [x] API surface sketched in `docs/API.md`.
---
## v0.2.0 -- the `Index` trait + `IndexStats` + default batch impls (THE HARD PART, NOT DEFERRED) (DONE)
Split into `IndexCore` (object-safe operational surface) + `Index` (typed
construction) so the engine can hold `Box<dyn IndexCore>`. Default
`insert_batch` / `search_batch` / `is_empty` shims. `IndexStats` with an
allocation-free `extra` default.
Exit criteria:
- [x] Every public item has rustdoc + a runnable example.
- [x] Core invariants property-tested (ordering, deletion visibility, batch == loop, cardinality).
---
## v0.3.0 -- validate against `iqdb-flat`; refine the trait (DONE)
Cross-checked the surface against the live `iqdb-flat` (brute-force),
`iqdb-hnsw` (graph), and `iqdb-ivf` (clustered) implementations — each
implements `IndexCore` + `Index` verbatim with its own `Config`. Encoded a
consumer-simulation proving all three families fit and coexist behind
`Box<dyn IndexCore>` (§8). No trait change was required.
Exit criteria:
- [x] New surface tested (consumer-simulation across all three families).
- [x] Hot path: the crate is pure interface code with no hot path of its own (the default batch shims are O(n) dispatch wrappers); nothing to benchmark here. A consumer's search hot path is benchmarked in that consumer's crate.
---
## v0.4.0 -- async decision (sync default) + feature freeze (DONE)
Recorded the **synchronous-by-design** decision (no async trait, no `async`
feature, no `futures` dep) — async would break `IndexCore` object safety
without per-call future boxing, search is CPU-bound, and async belongs at the
engine boundary. Declared the feature set frozen at empty.
Exit criteria:
- [x] No `todo!`/`unimplemented!` (the crate has none; `#![forbid(unsafe_code)]`).
- [x] Feature freeze declared (empty feature set, recorded in API.md + CHANGELOG).
---
## v0.5.0 -- doc the deletion semantics per impl + API freeze
Exit criteria:
- [ ] Public API frozen (recorded here). `cargo audit` + `cargo deny` clean.
---
## v0.6.0 -> v0.9.x -- Alpha / Beta -> RC
- 0.6.x-0.7.x: integrate against real consumers; MINOR-compatible additions only.
- 0.8.x (beta): bug fixes; broader testing; final benchmarks.
- 0.9.x (rc): critical fixes + doc polish.
---
## v1.0.0 -- Stable
- [ ] Definition of Done (DIRECTIVES section 7) satisfied.
- [ ] Public API frozen until 2.0.
- [ ] Release note written; published to crates.io; tag pushed.
---
## Out of scope for 1.0
- Any concrete index -- those are separate crates.
- Async-only trait -- sync default with optional async wrapping.