Hmbown/CodeWhale · error
fleet task '{}' is write-capable but declares no workspace.w
Error message
fleet task '{}' is write-capable but declares no workspace.writable_paths or metadata.coordination_contracts What it means
The worker's effective runtime profile allows writes (permissions.write = true, possibly derived from a parent profile or the role's default), but the task declares neither `workspace.writable_paths` nor `metadata.coordination_contracts`. The fleet refuses write-capable tasks with no declared write surface: there would be no bounded, auditable place for the worker to write or coordinate. This check sits in the sub-agent worker spec builder (crates/tui/src/fleet/worker_runtime.rs) before any launch manifest is minted.
Source
Thrown at crates/tui/src/fleet/worker_runtime.rs:241
requested_runtime.provider = explicit_fleet_provider_id(agent_profile);
if let Some(reasoning_effort) = effective_fleet_reasoning_effort(agent_profile) {
requested_runtime.reasoning_effort = Some(reasoning_effort);
}
if let Some(agent_profile) = agent_profile
&& let Some(profile_depth) = agent_profile.profile.delegation.max_spawn_depth
{
requested_runtime.max_spawn_depth = requested_runtime.max_spawn_depth.min(profile_depth);
}
let runtime_profile = parent_runtime_profile
.map(|parent| parent.derive_child(&requested_runtime))
.unwrap_or(requested_runtime);
let writable_roots = fleet_write_roots(task_spec)?;
let coordination_contracts = fleet_coordination_contracts(task_spec)?;
if runtime_profile.permissions.write
&& writable_roots.is_empty()
&& coordination_contracts.is_empty()
{
bail!(
"fleet task '{}' is write-capable but declares no workspace.writable_paths or metadata.coordination_contracts",
task_spec.id
);
}
let session_name = format!("fleet-{}-{}", worker_id, task_spec.id);
let launch_manifest = ChildLaunchManifest {
owner_session: run_id.to_string(),
child_id: worker_id.to_string(),
profile: runtime_profile.clone(),
prompt: objective.clone(),
cwd: Some(workspace.display().to_string()),
worktree: worker_workspace_is_isolated(coordination_workspace, workspace),
writable_roots,
writable_files: Vec::new(),
coordination_contracts,
expected_artifact: None,
token_budget: task_spec
.budgetView on GitHub (pinned to 0c42157ee5)
Solutions
- Add `writable_paths` under `[workspace]` listing the repo-relative roots the task may write (e.g. "src", ".codewhale/fleet").
- If the task coordinates through contracts instead, add `metadata.coordination_contracts = ["..."]` (array of short strings).
- If the task genuinely needs no writes, switch it to a read-only role/profile so permissions.write is false.
Example fix
# before [[tasks]] id = "refactor-core" role = "implementer" # no workspace.writable_paths, no coordination_contracts # after [[tasks]] id = "refactor-core" role = "implementer" [workspace] writable_paths = ["src"]
Defensive patterns
Strategy: validation
Validate before calling
fn write_scope_declared(task: &FleetTaskSpec) -> bool {
let writable = task.workspace.as_ref().is_some_and(|w| !w.writable_paths.is_empty());
let contracts = task
.metadata
.get("coordination_contracts")
.and_then(|v| v.as_array())
.is_some_and(|a| !a.is_empty());
writable || contracts
} Prevention
- Treat 'write-capable role' as implying 'must declare writable_paths' in every task template.
- Lint specs: if role is an implementer/writer type, require a non-empty workspace.writable_paths.
- Keep read-only review tasks on read-only roles so the check never engages.
When it happens
Trigger: A task using a write-capable role/agent type with only `workspace.readonly_paths` set; a parent runtime profile with write=true derived into the child while the task omits both fields; metadata present but missing the `coordination_contracts` key.
Common situations: Copying a read-only task template and flipping the role to an implementer type without adding write scoping; assuming role defaults count as a declared scope — they do not.
Related errors
- persistent allow rules must be scoped to a workspace
- persistent command allow rules must use exact matching
- persistent allow rules must match an exact command or path
- persistent command allow rules must not be empty
- persistent path allow rules must stay within the workspace
AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20).
Data as JSON: /api/errors/8fc8dda201bcdc34.
Report an issue: GitHub.