Fix child startup readiness and ordered provider tools

Wait for shell bootstrap before dispatching child prompts, serialize provider preprocessing, and make permission callbacks idempotent. Restrict task lists to concrete multistep plans and stop inferring completion from tool activity.

Update regression fixtures and resolve existing lint and test-layout failures. Verified formatting, both presubmit Clippy commands, and 354 targeted nextest tests.
This commit is contained in:
2026-09-09 13:55:34 -05:00
parent 4b703c019f
commit 1845b9e20e
41 changed files with 1097 additions and 895 deletions
@@ -386,7 +386,6 @@ impl CodebaseIndex {
repository: ModelHandle<Repository>,
store_client: Arc<dyn StoreClient>,
embedding_config: EmbeddingConfig,
max_files_repo_limit: usize,
embedding_generation_batch_size: usize,
ctx: &mut ModelContext<Self>,
) -> Self {
@@ -398,7 +397,7 @@ impl CodebaseIndex {
ctx,
);
if let Err(err) = index.build_and_sync_from_repository_root(max_files_repo_limit, ctx) {
if let Err(err) = index.build_and_sync_from_repository_root(ctx) {
safe_error!(
safe: ("Failed to build index: {err:?}"),
full: ("Failed to build index at root {}: {err:?}", index.repo_path.display())
@@ -803,7 +802,6 @@ impl CodebaseIndex {
#[cfg(feature = "local_fs")]
fn build_and_sync_from_repository_root(
&mut self,
max_files_repo_limit: usize,
ctx: &mut ModelContext<'_, Self>,
) -> Result<(), Error> {
let repo_path = self.repo_path.clone();
@@ -1127,13 +1125,9 @@ impl CodebaseIndex {
/// Performs a full reparse of the merkle tree, followed by a full server sync. This force evicts the
/// existing merkle tree state.
#[cfg(feature = "local_fs")]
pub(super) fn full_sync_index(
&mut self,
max_files_repo_limit: usize,
ctx: &mut ModelContext<Self>,
) -> Result<(), Error> {
pub(super) fn full_sync_index(&mut self, ctx: &mut ModelContext<Self>) -> Result<(), Error> {
self.update_tree_sync_state(TreeSourceSyncState::unsynced(), ctx);
self.build_and_sync_from_repository_root(max_files_repo_limit, ctx)
self.build_and_sync_from_repository_root(ctx)
}
/// Attempt to perform a full SERVER sync on the current index. We only proceed with the sync if there is
@@ -1328,7 +1322,6 @@ impl CodebaseIndex {
#[cfg(not(feature = "local_fs"))]
pub fn build_and_sync_from_repository_root(
&mut self,
_max_num_files_limit: usize,
_ctx: &mut ModelContext<'_, Self>,
) -> Result<(), Error> {
Err(Error::UnsupportedPlatform)
@@ -1705,7 +1698,6 @@ impl CodebaseIndex {
store_client: Arc<dyn StoreClient>,
embedding_config: EmbeddingConfig,
snapshot_bytes: Vec<u8>,
max_files_repo_limit: usize,
embedding_generation_batch_size: usize,
ctx: &mut ModelContext<Self>,
) -> Result<Self, Error> {
@@ -1716,7 +1708,7 @@ impl CodebaseIndex {
embedding_generation_batch_size,
ctx,
);
index.rebuild_and_sync_from_snapshot(snapshot_bytes, max_files_repo_limit, ctx);
index.rebuild_and_sync_from_snapshot(snapshot_bytes, ctx);
Ok(index)
}
@@ -1724,7 +1716,6 @@ impl CodebaseIndex {
fn rebuild_and_sync_from_snapshot(
&mut self,
snapshot_bytes: Vec<u8>,
max_files_repo_limit: usize,
ctx: &mut ModelContext<'_, Self>,
) {
let repo_metadata = RepoMetadata {
@@ -1756,7 +1747,6 @@ impl CodebaseIndex {
let (changed_files, gitignores) = Self::diff_filesystem_with_tree(
repo_path.clone(),
&tree,
max_files_repo_limit,
)
.map_err(SnapshotLoadError::DiffFailed)?;
@@ -1922,7 +1912,6 @@ impl CodebaseIndex {
fn diff_filesystem_with_tree(
repo_path: PathBuf,
tree: &MerkleTree,
max_files_repo_limit: usize,
) -> Result<(ChangedFiles, Vec<Gitignore>), Error> {
let mut gitignores = Self::construct_initial_ignores(&repo_path);
@@ -723,7 +723,7 @@ impl CodebaseIndexManager {
))
) {
index.update(_ctx, |code_index, ctx| {
let _ = code_index.full_sync_index(self.max_files_repo_limit, ctx);
let _ = code_index.full_sync_index(ctx);
});
}
}
@@ -940,7 +940,6 @@ impl CodebaseIndexManager {
let index = Self::build_and_sync_codebase_index_internal(
self.store_client.clone(),
handle,
self.max_files_repo_limit,
self.embedding_generation_batch_size,
#[cfg(feature = "local_fs")]
snapshot_storage,
@@ -967,7 +966,6 @@ impl CodebaseIndexManager {
fn build_and_sync_codebase_index_internal(
store_client: Arc<dyn StoreClient>,
repository: ModelHandle<Repository>,
max_files_repo_limit: usize,
embedding_generation_batch_size: usize,
#[cfg(feature = "local_fs")] snapshot_storage: Option<SnapshotStorage>,
ctx: &mut ModelContext<Self>,
@@ -991,7 +989,6 @@ impl CodebaseIndexManager {
store_client.clone(),
snapshot_storage.path(),
repository.clone(),
max_files_repo_limit,
embedding_generation_batch_size,
ctx,
) {
@@ -1020,7 +1017,6 @@ impl CodebaseIndexManager {
repository,
store_client,
EmbeddingConfig::default(),
max_files_repo_limit,
embedding_generation_batch_size,
ctx,
)
@@ -1185,7 +1181,7 @@ impl CodebaseIndexManager {
};
codebase_index.update(ctx, |index, ctx| {
let _ = index.full_sync_index(self.max_files_repo_limit, ctx);
let _ = index.full_sync_index(ctx);
})
}
@@ -157,7 +157,6 @@ pub(super) fn read_snapshot(
store_client: Arc<dyn StoreClient>,
snapshot_dir: &Path,
repository: ModelHandle<Repository>,
max_files_repo_limit: usize,
embedding_generation_batch_size: usize,
ctx: &mut ModelContext<CodebaseIndex>,
) -> anyhow::Result<CodebaseIndex> {
@@ -171,7 +170,6 @@ pub(super) fn read_snapshot(
store_client.clone(),
EmbeddingConfig::default(),
snapshot_bytes,
max_files_repo_limit,
embedding_generation_batch_size,
ctx,
);
@@ -674,6 +674,7 @@ async fn acquire_repository_lock(storage_root: &Path, root_path: &Path) -> Resul
.read(true)
.write(true)
.create(true)
.truncate(false)
.open(&lock_path)
.with_context(|| format!("Failed to open local index lock {}", lock_path.display()))?;
loop {