Command/backend/contract architecture; unify commands under commands/ - #53
Open
Seth Ockerman (OckermanSethGVSU) wants to merge 1 commit into
Open
Command/backend/contract architecture; unify commands under commands/#53Seth Ockerman (OckermanSethGVSU) wants to merge 1 commit into
Seth Ockerman (OckermanSethGVSU) wants to merge 1 commit into
Conversation
… commands/
Reorganize from a language-oriented layout (crates/, python/) to a
command-oriented one, and add a language-neutral backend contract system so
future nova-load / nova-storm backends can be added and conformance-checked
without touching the user-facing CLI. Qdrant behavior is unchanged.
Layout
- commands/ — every user-facing nova-* command (Rust and Python together):
nova-load, nova-storm : thin Rust SHIMS that read the backend selector from
the config and exec the backend, argv intact
nova-shim : shared shim front-controller lib (dedups the two
shims; dispatch logic defined once, cannot drift)
nova-contract : generic language-neutral conformance checker
nova-inspect : moved from crates/
nova-embed, nova-bf, nova-opt, nova-sweep, nova-dist : moved from python/
- backends/ — implementations behind command contracts:
nova-load/qdrant -> nova-load-qdrant (moved from crates/nova-load)
nova-storm/qdrant -> nova-storm-qdrant (moved from crates/nova-storm)
nova-{load,storm}/contracts/rust : shared Rust interface each Rust backend
implements (VectorStore / QueryTarget +
neutral types) — compile-time enforcement
- contracts/ — canonical language-neutral specs (v1.yaml) + docs
Two-layer contract enforcement
- Compile-time: a Rust backend depends on backends/<cmd>/contracts/rust and
implements the trait; a missing/mistyped method won't build.
- Runtime/cross-language: each backend advertises `capabilities --json`;
`nova contract check <backend-exe> --contract <yaml>` validates it against the
neutral spec (levels: shape | dry-run | live). Checks target backends, not shims.
Dispatch (UX preserved)
- `nova load ...` / `nova storm ...` unchanged. The shim reads only
vectorstore.type / target.type, maps qdrant -> nova-<cmd>-qdrant, and execs it
(process replacement — stdout/stderr/exit code pass straight through, incl.
storm's --json line). Unknown type -> exit 127 with an install hint.
Other
- capabilities --json added to both backends (kept in lockstep with the specs).
- Makefile: load/storm install shim + backend; add `contract`; `make test` runs
contract checks at dry-run level.
- CI + nova-dist updated to build/install both shim and backend on the fleet.
- backend package/binary renamed to nova-<cmd>-qdrant; lib names kept
(nova_load / nova_storm) so internal module paths are unchanged.
Tests: cargo test (87) green; contract checks pass; nova-bf (352p/1s) and
nova-sweep (36) pytest green; live Qdrant load->storm recall 1.0/1.0/1.0;
nova-embed and nova-bf exercised end-to-end locally.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reorganizes
supernovafrom a language-oriented layout (crates/,python/) to a command-oriented one, and introduces a language-neutral backend contract system so futurenova-load/nova-stormbackends (Milvus, Vespa, …) can be added and conformance-checked without touching the user-facing CLI. No new VDB backend is added here — current Qdrant behavior is unchanged and fully preserved.New layout
Two-layer contract enforcement
backends/<cmd>/contracts/rustand implements the shared trait (VectorStorefor load,QueryTargetfor storm, plus neutral types). A missing or mistyped method won't compile.capabilities --json;nova contract check <backend-exe> --contract <yaml>validates it against the neutral spec (--level shape | dry-run | live). This works for a backend in any language — it only ever talks to the executable. Checks target the backend, never the shim.Keep the three in lockstep when changing a contract: the Rust trait, the
v1.yaml, and each backend'scapabilities_json().Dispatch — UX preserved
nova load .../nova storm .../nova sweep ...are unchanged. The shim reads only the backend selector (vectorstore.type/target.type), mapsqdrant→nova-<cmd>-qdrant, andexecs it (process replacement — stdin/stdout/stderr and exit code/signals pass straight through, including storm's single--jsonsummary line). Unknown type → exit127with an install hint. The two shims share all logic vianova-shim, so they can't drift.Adding a future backend = new
backends/<cmd>/<name>/buildingnova-<cmd>-<name>, implement the trait, advertisecapabilities, passnova contract check. A config withtype: <name>then dispatches automatically — no shim change.Other changes
capabilities --jsonadded to both Qdrant backends (kept in lockstep with the specs).Makefile:make load/make storminstall both shim and backend; newmake contract;make testnow also runs contract checks atdry-runlevel.rust-binaries.yml) +nova-distupdated to build/install both the shim and the backend on fleet workers (a worker needs both).nova-<cmd>-qdrant; library crate names kept (nova_load/nova_storm) so internal module paths are unchanged. The neutralStoreError/TargetErrordrop their qdrant variant; qdrant errors convert at the trait boundary via.map_err(…::backend).README.md,AGENTS.md, and newcontracts/*/README.md+commands/README.md.Testing
cargo test: 87 pass (16 suites) — behavior preserved.nova contract checkagainst both backends: PASS (shape/dry-run/live); a negative case (load backend vs storm contract) correctly FAILs with exit 1.nova-bfpytest 352 passed, 1 skipped;nova-sweeppytest 36 passed;nova-embedhas no suite (pre-existing).nova-sweepfullload → reindex → storm --json → deleteorchestration → 2 rows, 0 errors.nova-embed(MiniLM-L6, CPU) andnova-bf(compute+merge, 54/54 self-match) exercised end-to-end locally;nova-inspectruns from its new path.Notes / risks
nova-embed/bf/opt/sweep/dist) andnova-inspectwere moved intocommands/too, so the layout is uniformly command-oriented.nova-optis a WIP tracked on another branch (only git-ignored artifacts in this checkout).nova-distand the CI release workflow were updated to produce/install both binaries, but the fleet path was not live-tested (AWS/SkyPilot) — the change is mechanical.novadispatcher (src/cli/) intentionally stays at the repo root (it's the zero-dep root package); it now also lists backends asnova load-qdrant/storm-qdrant, which is harmless and consistent with its zero-opinion design.🤖 Generated with Claude Code