Skip to content

atlas staging tier: versioned schema, registry, aggregator with merge-on-close promotion into three-level core #5669

Open

Description

@dezren39

Implementation of §4 of the Scaler-era data architecture revision (design doc PR #5667, doc/2026-11-04T21-27-34Z_design_atlas_scaler_revision/).

Scope:

  • atlas_stage v1 schema DDL (items, chunks_raw, notes, kv, _schema_version) + one provisioning tool that creates a staging DB per work unit (queue task / session / epic / notes batch) and applies the schema.
  • Registry (internal core tier): unit id → staging DB, owner, sensitivity level, state (open/closing/merged), schema version. (Design §6 proposes the registry be born as a TursoDB --tursodb pilot DB once the account toggle is enabled — sequencing note, not a blocker for the libSQL version.)
  • Aggregator (fleet serve role, laptop): on unit close, embed new chunks with the resident Snowflake model, promote survivors into core in bounded batches (≤500 rows/txn), write the merge manifest (unit id, rows in/promoted, content hash), bump the core snapshot id per batch (consumed by the §3 result cache), branch the staging DB as archive, deregister. Partial periodic promotion for long-lived units (epics).
  • Core stores per design: exactly three physical sensitivity levels (public / internal-default / secret — separate DBs + credentials); within a level, scan stores per corpus + one content store per level; reclassification = verified mechanical row move (counts + hash) with a manifest log entry.
  • Session-close extraction hook as the canonical staging producer (sessions write staging only; core never sees session-rate writes).

Acceptance: an end-to-end demo unit (one session) flows staging → close → promotion → searchable in core with correct ceiling behavior per level; a reclassification move round-trips counts/hashes; promotion never holds a core writer > seconds (batch bound enforced); core DDL only via maintenance path. PBT/MBT per the testing doctrine (schema-version invariants, manifest hash oracle).

Design: #5667 §4 (+ §5 sizing, §6 pilot). Parent context: hatch-personal#21.

Acceptance criteria

  • atlas_stage v1 schema DDL exists (items, chunks_raw, notes, kv, _schema_version) and one provisioning tool creates a per-unit staging DB and applies it.
  • Internal registry records unit id -> staging DB, owner, sensitivity level, state (open/closing/merged), and schema version, and is the lookup the aggregator uses.
  • Aggregator promotion on unit close embeds new chunks, promotes survivors into core in bounded batches (<=500 rows/txn), writes a merge manifest (unit id, rows in/promoted, content hash), and bumps the core snapshot id per batch.
  • Long-lived units (epics) get partial periodic promotion; closed units are branched as archive and deregistered.
  • Behaviour matches design PR docs: Scaler-era Atlas/Turso data architecture revision #5667 section 4; deviations are recorded on this issue.

Activity

  1. added
    priority/normalOrdinary priority (the default)
    effort/lLarge: multi-day or open-ended; expect staged check-ins
    source/humanFiled directly by a human
    meta/enrichedIntake review done: acceptance criteria, links, and normalized labels added
    on Nov 4, 2026
  2. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Intake review

    Intake by fleet monitor (repo-fleet-monitor), 2026-11-04 run.

  3. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    Drew approvals recorded (2026-11-04 ~17:10 CST):

    1. TursoDB preview pilot — APPROVED and executed. The turso CLI (v1.0.34) supports db create --tursodb, so no dashboard toggle was needed. Two empty Turso-type pilot DBs now exist in group great-star-lord, labeled as pilots, no data migrated:
    2. Shared INTERNAL-tier embedding-cache DB — CONFIRMED by Drew ("yes, all of these things"), per revision §3.1. The pilot above is its first instance (TursoDB-type).
    3. Shadow-cost spike — TOP PRIORITY per Drew. Results are landing on dezren39/hatch-personal#20 and as a comment on PR docs: Scaler-era Atlas/Turso data architecture revision #5667 (headline: the 160,576 B/row is the index's honest fixed cost — 52× raw vector + 832 B — measured identical on fresh DBs; what production got wrong is the wedged/orphaned index state, not the size).

    Engine note for this issue's staging design: production atlas is confirmed libSQL (sqld) by three independent signals (turso db show Type=SQLite + libsql:// URL + sqlite_version() 3.47.0, vs Type=Turso + turso:// + 3.50.4 on the pilots). TursoDB exists in this org only for DBs created with --tursodb.

  4. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Core-tier shard restore — executed 2026-11-04 (per Drew's stop-and-redirect ruling, 18:24 CST)

    The in-flight index rewrite was stopped (precondition verified here: laptop atlas-index-rewrite.service inactive; hosted shadow frozen at 28,760 across two reads ~5 min apart) and the corpus was restored into fresh shards. Production atlas was only ever read — untouched.

    Engine + creation route (Drew ruling 18:28 CST: all new DBs are TursoDB)

    • Standing creation route, identified from turso-cli source (CreateDatabaseV3Body.use_tursodb) and verified empirically: POST https://api.turso.tech/v3/organizations/{org-UUID}/databases with {"name": ..., "group_id": ..., "use_tursodb": true}. The path org must be the org UUID — the slug returns "organization not found".
    • Gate probe (atlas-tursodb-probe, created via the API route): turso db show Type=Turso, sqlite_version() = 3.50.4 (libSQL = 3.47.0), F32_BLOB(768) accepted, vector_distance_cos scan top-10 identical to production on the same 200 real chunks.
    • Scan path everywhere: plain SQL exact-cosine scan over vec F32_BLOB(768), fan-out + merge. No libsql_vector_idx (TursoDB rejects the syntax; scan-over-shards is the design regardless). TursoDB's metric set for future corpora: cosine, dot product, L2, Jaccard — this corpus is cosine by design (source index metadata).
    • Deviation recorded: FTS5 is unavailable on TursoDB ("Virtual tables are not supported in MVCC mode"), so the new scan stores carry no chunks_fts. Keyword search stays on the libSQL monolith until the consumer work decides the FTS answer (see atlas core consumer wiring: fleet atlas-search fan-out over the TursoDB shard core (tier ceilings, merge, --expand hydration) #5755).

    Shard map (tier → topic → shards; sessions atomic; ≤4,800 chunks/shard per §5.2)

    Source: hosted atlas, 107,639 chunks = 107,639 vectors (all 3,072 B; 0 missing/orphan). Sensitivity → tier: secret-bearing → secret; personal + local-only → internal (default); public = none in this corpus.

    Shard(s) Chunks
    atlas-core-internal-work-engineering-01..06 4,435 ×4, 4,434 ×2
    atlas-core-internal-personal-admin-01..04 4,360 ×3, 4,359
    atlas-core-internal-agent-tooling-01..04 3,866 ×4
    atlas-core-internal-models-and-plans-01..02 4,551 ×2
    atlas-core-internal-infra-nix-01..02 4,094 ×2
    atlas-core-internal-home-lab-01..02 4,070, 4,069
    atlas-core-internal-fleet-repos-01..03 3,458, 3,457 ×2
    atlas-core-internal-people-pets-01 4,502
    atlas-core-internal-security-01 3,489
    atlas-core-internal-media-01 1,607
    atlas-core-internal-cloudflare-01 1,250
    atlas-core-internal-misc-01 (finances+health+travel+unlabeled) 841
    atlas-core-secret-main-01 638

    Plus per-level content stores (§4.2): atlas-core-internal-content (sessions 18,235; messages 70,987) and atlas-core-secret-content (sessions 90; messages 564). (The content message load needed one idempotent resume: the first pass dropped at 84% on a transport disconnect — RemoteDisconnected escaping the HTTP client's retry filter — and a targeted second pass inserted only the missing ids to the exact counts above. Scan-shard loads were unaffected.) Every scan shard carries chunks + vec with DDL identical to source, plus an atlas_manifest self-description. Secret chunks exist only in the two secret DBs.

    Verification (all independent of the loader's own counts)

    • Per-shard chunk/vec counts == map expectations, 29/29 exact. Tier sums: internal 107,001, secret 638, total 107,639.
    • Per-tier content-hash reconciliation: sorted-set SHA-256 of all content_hashes, source vs shards — internal MATCH, secret MATCH (no chunk lost, duplicated, or mis-tiered).
    • Vector bytes: 60/60 random spot-checks byte-identical to source.
    • Parity (held-out real queries, query chunk excluded): merged fan-out top-10 == production exact-scan top-10 on 5/5 internal queries and 2/2 secret queries (an early "False" on secret was a LIMIT artifact in the test harness — fan-out fetched top-10 including the excluded query row; corrected run: identical ids, identical order, max distance delta 8e-7).
    • Latency (sandbox → us-east-1 HTTPS, network-inclusive, per-shard top-10 scan): 1.1–1.9 s at 3.5–4.5k rows — above the §5.2 libSQL-based budget; flagged for the consumer work (atlas core consumer wiring: fleet atlas-search fan-out over the TursoDB shard core (tier ceilings, merge, --expand hydration) #5755: re-measure from the laptop path; §5.5 replicas are the lever).

    Corrections to the restore packet's premises (verified, second-sourced)

    • The laptop local DB contributes zero chunks: its chunk content-hash set is identical to hosted (same sorted-set SHA-256). The "2,226 local-only + 90 secret-bearing laptop chunks" were hosted session counts; at chunk level everything already lived in the hosted source of record (6,941 local-only + 638 secret-bearing chunks, all restored above). The laptop DB holds no vectors/labels; its extra messages belong to unchunked sessions and are referenced by no chunk.

    Leftovers

  5. added
    queue/queuedHas a queued task in the Supabase agent queue
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Nov 5, 2026
  6. developing-today commented on Nov 5, 2026

    @developing-today
    Contributor

    🤖 Agent note · handed off

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 5, 2026
  8. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 5, 2026
  9. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  10. dezren39 commented on Nov 5, 2026

    @dezren39
    MemberAuthor

    Queue triage — task 10103

    Verdict: #5669 remains open and is not already implemented. GitHub REST confirms issue #5669 is open; the all-state PR search found no PR for it. Design PR #5667 merged at 7ddc3c0. I fast-forwarded the primary clone (already current) and checked main at b830347.

    Current code evidence: main has pkgs/atlas-search and pkgs/fleet, but no atlas_stage schema, staging registry, merge manifest, or promotion worker implementation. The fleet README describes fleet serve search as the remaining serve-role stub; fleet's current role registry has queue-broker, secrets-broker, and search, but no aggregate role.

    Scoped implementation path and order:

    1. Settle the module/role boundary between the staging schema/provisioner and the fleet service; keep this separate from the adjacent search-consumer work.
    2. Add the versioned atlas_stage v1 schema and a single per-unit provisioning path; begin with schema-version invariants.
    3. Add the internal registry mapping unit id to staging DB, owner, sensitivity, state, and schema version.
    4. Add the closing-unit aggregation path: embed, promote in batches of at most 500 rows/transaction, write a content-hash merge manifest, and bump the core snapshot per batch.
    5. Archive and deregister closed units, add partial promotions for long-lived epics, then wire the session/task close producers and end-to-end/reclassification checks.

    Ordering dependency: the schema/provisioner slice can start immediately. Before the aggregator slice, choose whether it is a new fleet serve aggregate role or is hosted under the existing search serve role; the current role registry has no aggregate entry. The required sequencing is now recorded here. This is an enhancement, so reproduction is not applicable; no repository code changed in this triage.

    🤖 Agent note · triaged

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

Metadata

Metadata

Assignees

Labels

effort/lLarge: multi-day or open-ended; expect staged check-inskind/enhancementmeta/enrichedIntake review done: acceptance criteria, links, and normalized labels addedpriority/normalOrdinary priority (the default)source/humanFiled directly by a humantask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions