Skip to content

Atlas step 3: CLI mode — one-shot commands at Python surface parity #5353

Closed

Description

@dezren39

Step 3 of the Atlas binary+service epic (#5350). Design of record: doc/2026-11-04T08-07-13Z_design_atlas_binary_service/ (§1, §4 atlas-search bin).

Scope

  • The atlas-search binary's one-shot mode at full Python surface parity: search and get-chunk subcommands, the Python's flags (--model / --vec-table / --embedder-equivalents where they still make sense, --trunc, --max-sensitivity, filters, --pool, --vector-backend, --backend turso|local, --text), JSON envelope output identical in shape to the Python's, and the human-readable --text rendering.
  • Standalone operation is the default and must be complete: embed the query in-process (step 1), talk to Turso or a local publish file directly (step 2). No daemon required, ever.
  • Token resolution for Turso identical to the Python's order: env, Bitwarden by name (turso.atlas-ro-token / turso.atlas-read-only-token / atlas-ro), turso CLI read-only mint with the 20 h cache.
  • --via-service / ATLAS_SEARCH_VIA=service: route through a running service (step 4) using atlas-proto; contract is prefer service, fall back to standalone loudly (a note in the envelope's notes), never a silent hang or failure. Until step 4 lands, via-service against no service exercises exactly that fallback path.
  • Degradation parity: with no model present, FTS-only search and get-chunk work; vector/hybrid fail loudly (design §4).

Dependencies: step 1 (embedder), step 2 (core).

Verification gate (exit criteria)

  • A flag-for-flag comparison run: a fixed battery of representative queries (filtered, ceiling-raised, FTS-only, get-chunk with neighbors, local-backend against a publish copy) produces envelopes matching the Python's (same results, same order, same rank_sources; scores within float formatting).
  • Cold one-shot latency measured and recorded on this issue vs the Python's ~35 s baseline (the embedder load is the expected win; report the real number either way).

Out of scope: serve mode (step 4), packaging/deploy (step 5), any default flip (step 6).

Activity

  1. added a commit that references this issue on Nov 4, 2026
  2. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Step 3 DONE — PR #5377 merged 9128ee816f281a48c3fc4504e3a67dd303dccc6f (API-verified).

    Built: the atlas-search binary crate (pkgs/atlas-search/crates/atlas-search) — search + get-chunk subcommands over atlas-core/atlas-embed at Python surface parity (flags, defaults, envelope, --text, exit codes: die-fatals exit 2, get-chunk not-found exit 1, backend/transport failures exit 1 with the message instead of a traceback). Standalone by default (Turso via the read-only token chain, or --backend local); the embedder loads lazily so FTS/get-chunk work with no model present and vector/hybrid fail loudly without one. --via-service implements prefer-with-loud-fallback now; the job-protocol client swaps in behind service::attempt in step 4. Declared divergences (in the PR body): --embedder fastembed / non-Snowflake --model fail loudly for vector/hybrid (atlas-embed is the Snowflake ST path only); clap help formatting; a test-only ATLAS_SEARCH_QVEC_FILE hook mirroring the fixture generator's monkeypatch.

    Gate results (laptop, rustup 1.99.0, sccache wrapper disabled via --config after it served a stale 1.98.1 rmeta — the step-1 trap, E0514):

    • Fixture parity: all 12 recorded search cases + both get-chunk cases through the compiled binary — envelopes equal AND stdout byte-equal to CPython's own json.dumps(indent=1, ensure_ascii=False) rendering (14/14). --text goldens generated by the Python's render_text itself, byte-equal. (This needed a CPython-compatible JSON writer: serde_json prints 0.000087 where CPython prints 8.7e-05, and 2-space pretty indent vs Python's 1.)
    • Live smoke (read-only production): 4 questions, top-10s (chunk ids, scores, rank_sources) identical to the deployed Python CLI on all 4. Cold one-shot: Rust 13.0–16.4s vs Python 17.2–25.6s in the same battery.
    • Via-service: --via-service → stderr warning (service at http://127.0.0.1:18760 unreachable (io: Connection refused (os error 111)); falling back to standalone) + the same note in the envelope; results identical to standalone.
    • Degradation: FTS + get-chunk succeed with no model env; vector without ORT exits 2 loudly; local backend exercised against the v2 publish copy.
    • cargo test --workspace (29 tests), clippy, fmt — clean.

    Notes for step 4/5 are in the PR body (transport seam; model/ORT resolution chain + the closure must carry libstdc++.so.6 + libz.so.1 — verified live with the venv ORT plus the store gcc-lib/zlib pair). Chaining to step 4 (#5354) per the run-to-completion instruction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions