Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .alfonso/release-notes/next-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Semantic search: when Synapse announces a timed embedding-model pause (`lane_paused`), indexing waits it out and resumes where it stopped instead of failing or re-embedding finished work, without holding build slots or locks. Searches meanwhile use keyword search with "Semantic search unavailable: the embedding model is paused; using keyword search only.", and health shows the semantic index as paused until the announced time.
- edit: multi-item `edits[]` and line-range edits now work on existing files whose paths contain glob characters, such as Next.js `app/[id]/page.tsx`, instead of being refused as glob targets; real globs behave as before. Thanks for the report (#486).
- gh shim (manifest 19): `gh workflow disable` and `gh workflow enable` run under the operator bypass, like `run cancel`, and are refused as undeclared on older manifests.
- Backups: the daemon writes its ENGRAM backup catalog (`engram-catalog.json` in the storage root) at startup, so a fresh machine is covered without a hand-written file. It declares only what exists right now: `aft.db` (captured page by page) and the trusted-filter project list as device-local, and undo history, checkpoints, background task output, logs, diagnostics, caches and generated shims as excluded from backup. Undo history keeps its earlier entry ids, so ENGRAM records the switch to excluded on the same entries, and an id stays with its folder across restarts. The catalog is written only when the storage folder is named `aft`, since ENGRAM looks nowhere else.

## Sandbox profiles

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"slice_class": "engine_unwired",
"targeted_mechanism": "none",
"kind": "harness",
"fixtures": [
"crates/aft/tests/integration/tool_call_parity_test.rs"
],
"fenced_files": [
"crates/aft/src/lib.rs"
],
"note": "The only fenced change is a module declaration in lib.rs for the startup backup catalog writer (engram_catalog.rs), which runs once at daemon startup and touches no search code. Ranking and routing are unchanged; benchmark rows must remain byte-identical."
}
38 changes: 38 additions & 0 deletions crates/aft/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2937,8 +2937,19 @@ impl App {
}
}

let created = !path.exists();
let conn = Arc::new(Mutex::new(crate::db::open_with_mode(path, mode)?));
*slot = Some((key, Arc::clone(&conn)));
drop(slot);
if created {
// The startup catalog cannot declare a database that does not
// exist yet, so on a fresh machine it would stay undeclared until
// the next restart. Describe the storage root again now that it
// has one.
if let Some(storage_root) = path.parent() {
crate::engram_catalog::refresh_catalog(storage_root);
}
}
Ok(conn)
}

Expand Down Expand Up @@ -17715,6 +17726,33 @@ mod shared_db_tests {
&ctx_two.db().expect("second context database")
));
}

/// On a fresh machine the startup catalog runs before `aft.db` exists, so
/// creating the database must declare it without waiting for a restart.
#[test]
fn creating_the_database_declares_it_in_the_engram_catalog() {
let parent = tempdir().expect("storage parent");
let storage = parent.path().join("aft");
std::fs::create_dir(&storage).unwrap();
crate::engram_catalog::refresh_catalog(&storage);
let catalog = storage.join("engram-catalog.json");
let declares_db = || {
let value: serde_json::Value =
serde_json::from_slice(&std::fs::read(&catalog).unwrap()).unwrap();
value["entries"]
.as_array()
.unwrap()
.iter()
.any(|entry| entry["entry_id"] == "aft/db")
};
assert!(!declares_db(), "no database yet, so no aft/db entry");

let app = App::default_shared();
app.open_db(&storage.join("aft.db"))
.expect("create database");

assert!(declares_db(), "the new database is declared at once");
}
}

#[cfg(test)]
Expand Down
Loading
Loading