{"record":{"id":"d07daae4d295c257","repo":"Hmbown/CodeWhale","slug":"search-remains-available","errorCode":null,"errorMessage":"search remains available","messagePattern":"search remains available","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/subagent/tests.rs","lineNumber":8031,"sourceCode":"    runtime.worker_profile.denied_tools.push(\"Web\".to_string());\n    let registry = SubAgentToolRegistry::new(\n        runtime,\n        FleetRole::Scout,\n        None,\n        crate::tools::todo::new_shared_todo_list(),\n        crate::tools::plan::new_shared_plan_state(),\n    );\n    let catalog = registry.deferred_catalog_for_model(&FleetRole::Scout);\n    let mut surface = SubAgentToolSurface::new(catalog, &[\"Web\".to_string()]);\n    assert!(!model_tool_names(model_request_tools(&mut surface)).contains(\"Web\"));\n    let searched = execute_surface_tool(\n        &registry,\n        &mut surface,\n        TOOL_SEARCH_NAME,\n        json!({\"query\": \"web\", \"match\": \"regex\"}),\n    )\n    .await\n    .expect(\"search remains available\");\n    assert!(!searched.contains(\"\\\"tool_name\\\":\\\"Web\\\"\"));\n    assert!(surface.hydrate(\"Web\").is_err());\n}\n\nfn synthetic_deferred_tool(name: &str, description_bytes: usize) -> Tool {\n    Tool {\n        tool_type: Some(\"function\".to_string()),\n        name: name.to_string(),\n        description: \"x\".repeat(description_bytes),\n        input_schema: json!({\"type\": \"object\", \"properties\": {}}),\n        allowed_callers: None,\n        defer_loading: Some(true),\n        input_examples: None,\n        strict: None,\n        cache_control: None,\n    }\n}\n","sourceCodeStart":8013,"sourceCodeEnd":8049,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/subagent/tests.rs#L8013-L8049","documentation":"A `.expect(\"search remains available\")` panic: the tool_search tool failed to execute when the test verifies it stays reachable after other tools are evicted/deferred. tool_search is supposed to remain hydrated at all times so the model can rediscover deferred tools; its failure breaks that guarantee.","triggerScenarios":"execute_surface_tool(&registry, &mut surface, TOOL_SEARCH_NAME, json!({\"query\":\"web\",\"match\":\"regex\"})) returns Err in crates/tui/src/tools/subagent/tests.rs:8031, typically because the surface treated tool_search as deferable and evicted it, or its execution errored after hydration changes.","commonSituations":"Tightening the deferred-tool LRU so tool_search itself is evicted; changing SubAgentToolSurface::new to warm only a fixed list that omits tool_search; renaming TOOL_SEARCH_NAME.","solutions":["Inspect the Err from the failing call to see whether the tool is missing or execution failed.","Ensure tool_search is always kept eager/warm and never counted against the deferred cache cap.","Re-run with the warm list including TOOL_SEARCH_NAME to confirm eviction is the cause.","Check that surface.hydrate(\"Web\") failing afterwards is intended and unrelated to search availability."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Before executing, ensure tool_search is warm/eager on the surface\nlet warm = surface.warm_names();\nassert!(warm.iter().any(|n| n == TOOL_SEARCH_NAME), \"tool_search was evicted or never warmed\");","typeGuard":null,"tryCatchPattern":"if let Err(e) = execute_surface_tool(&registry, &mut surface, TOOL_SEARCH_NAME, &args).await {\n    panic!(\"search must remain available after eviction changes: {e}\");\n}","preventionTips":["Exclude tool_search from the deferred LRU cap accounting by construction, not by test.","Add an invariant check that hydration never evicts tool_search.","Keep warm lists derived from constants rather than positional filters.","Re-run eviction tests whenever the deferred cache cap changes."],"tags":["rust","test-panic","tool-search","deferred-tools"],"backgroundTag":"tool-execution-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T10:30:35.592Z"}