5 Commits
Author SHA1 Message Date
Jamie Pineandcapy-ai-staging[bot] e4b4cb71f5 Capture time and place in listings and search, read from the image facet on both backends (#3151)
* Capture time and place in listings and search, read from the image facet on both backends

search.files sorts by CapturedAt and filters by a CapturedAt range and
has_location; files.directory_listing sorts by datetaken; the media
listing's datetaken reads the facet. The store joins facet_image into
every entry read, guarded by the row's content hash, and the arena path
reads the facet from the store ahead of its sort and filter, so both
backends hand the same File to one predicate and one order (R8 row 19,
new row 29). File.image_media_data is filled from the facet on every
path; the inspector shows the capture time and the coordinates; Date
Taken is in every explorer view's sort menu.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* search.media judges the capture filters on its rows and leaves replicas out under them; a directory listing reads facets ahead of the sort only for a capture order

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* search.media judges a replica's rows under a capture filter as search.files does instead of dropping the partition

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-09 10:30:21 +00:00
Jamie Pineandcapy-ai-staging[bot] 2d781bf4b1 Rebuild a drive's arena from its source stores when the snapshot is missing or quarantined (#3139)
* Rebuild a drive's arena from its source stores when the snapshot is missing or quarantined

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Store rebuild runs off the request path and skips a partition a restore already filled

Every reader on a drive funnels through the restore gate, so the fill now
runs on its own task: the gate resolves as soon as it starts, roots stay in
progress until they land and listings serve the store meanwhile. A partition
rebuild_quiesced already filled resolves as restored without a second read.
The fill reads a rebuild-only select without the content join: 18.9 s for a
1.01M-record store in release, from 33.1 s.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* A browse beneath a source being filled serves the store instead of clearing the subtree

is_under_indexing is the ancestor-aware check: a store fill or recursive
walk over a root covers everything beneath it, and a browse dispatched into
that tree ran clear_for_reindex over what the fill had already placed. The
acceptance test lists a subdirectory during the fill and the deepest one
after it. REBUILD_PAGE moved above the fill's doc block.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Scope the mid-fill store answer to roots being filled from a store

indexing_in_progress also holds walk roots, whose stores cannot promise an
answer beneath them, so the prefix gate reads a separate filling_from_store
set and falls through to the ordinary dispatch when the store has no row.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-08 13:35:37 +00:00
Jamie Pineandcapy-ai-staging[bot] f9d89c1d71 R4 arena compaction: reuse vacated slots, compact inflated arenas, snapshot live nodes only (#3138)
* R4 arena compaction: reuse vacated slots, compact inflated arenas, snapshot live nodes only

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* R4 arena compaction: reuse vacated slots, compact inflated arenas, snapshot live nodes only

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Arena: removing a directory takes its subtree so no parent link survives slot reuse

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Arena: rename moves a subtree under its new path instead of dropping it

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Arena::rename: keep the moved entry's own path spelled as given

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-08 09:45:09 +00:00
Jamie Pineandcapy-ai-staging[bot] e58507a1ec R8 fixes F1, F2, F3, F5: salvage repair, snapshot quarantine, refused watch state, nested-store search duplicates (#3114)
* Store: unsettle a salvaged-away row so the next observation rewrites it

R8 row 3 (F1). When a batch loses a row to a database failure the ledger
kept the binding it made before the commit, so the next walk resolved the
same file Unchanged and the row stayed missing for as long as its size and
mtime held. commit now takes the ledger and unsettles each row it could not
land: the uuid keeps its path, the size and mtime evidence is cleared, and
the next observation resolves Changed and writes the whole row under the
identity the arena already holds. Un-ignores
a_repeat_observation_repairs_a_failed_write.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Snapshot: move an unreadable artifact aside instead of deleting it

R8 row 10 (F2). load_snapshot_impl removed a snapshot it could not read,
decode, or accept the version of, so the artifact was gone before anyone
could inspect it. It now moves to <name>.corrupt-<unix seconds> beside the
slot with a WARN naming both paths; the slot is clear for the next save and
no launch parses it again. Un-ignores an_invalid_snapshot_is_retained_for_diagnosis,
which now asserts the bytes survive at the aside path.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Watcher: register a root only after the OS accepts, report and retry refusals

R8 row 11 (F3). watch_root registered the root with the volume index before
subscribing at the OS, so a refused subscription left the root in
watched_paths and is_watched and core.index_status reported a watch that did
not exist. The OS subscription now comes first; a refusal is recorded on the
volume index with its reason, surfaces as IndexStatus::refused_watches (and
in sd index status), and is retried every watch_retry_interval (30 s) while
the service runs. A retry the OS accepts moves the root to watched_paths.
Un-ignores a_refused_watch_is_not_reported_active and extends it with the
status report and the reconciling retry. Regenerates ts-client types.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Search: answer a file under nested sources once from the stores

R8 row 25 (F5). With an outer and an inner source both walked, the file
under the inner root sits in both stores, and after a restart with no
snapshot search_every_index queried each store in turn and returned it
twice. The store loop now reads sources innermost first and drops a hit
whose local path an earlier partition (an inner store or a drive's arena)
already answered, before it is counted, so total_found stays the number of
distinct files. Un-ignores a_file_under_nested_sources_is_one_hit_from_the_stores.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Docs: R8 rows 3, 10, 11 and 25 fixed; row 17 remains the R4 brief

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Review: one retained corrupt snapshot, full-arena dedupe seed, reset clears refusals

A recurring load failure no longer retains an artifact per launch: when a
.corrupt-* sibling exists the slot is removed instead, keeping the oldest
copy as the mismatched-root path does. The store de-duplication seed is
collected from each arena's full match set before the page window narrows
it, so total_found stays exact beyond the page. clear_all forgets refused
watches along with the watched paths.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-07 05:02:25 +00:00
Jamie Pineandcapy-ai-staging[bot] 179adcf6d5 R8: source runtime acceptance matrix as CI tests (#3113)
* R8: source runtime acceptance matrix as CI tests

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Drop the regenerated Tauri linux schema; unrelated build churn

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* Run the R8 suites as their own core_tests job

The integration job took 63 min cold on Blacksmith with the three suites
added; its original suites alone run close to the hour. An acceptance
group in xtask keeps each job under the cap and lets the two run in
parallel.

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

* PROJECT_STATUS: baseline follows the merged tree

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai-staging[bot] <305915985+capy-ai-staging[bot]@users.noreply.github.com>
2026-10-07 04:04:07 +00:00