Hmbown/CodeWhale · error

read-only roles may revise their private working notes

Error message

read-only roles may revise their private working notes

What it means

This panic comes from `.expect("read-only roles may revise their private working notes")` on `registry.execute("agent_read_only", "todo_write", ...)` in crates/tui/src/tools/subagent/tests.rs:8528. It asserts the contract that read-only Fleet roles can still write to their own private todo list even though other write tools are denied. If the registry's read-only deny list incorrectly blocks `todo_write`, the tool returns an error and the expect panics.

Solutions

  1. Check the read-only role's tool catalog/deny list construction and ensure `todo_write` is explicitly permitted for read-only roles.
  2. Confirm the tool name string "todo_write" matches the registered tool identifier (grep the registry catalog).
  3. Verify the registry was built with the intended `ToolContext` and auto-approve settings so the write isn't rejected for approval reasons.
  4. Run the test with the registry construction logged (tool list) to see whether todo_write is present in the child's catalog.

Example fix

// before: blanket deny of all write-suffixed tools for read-only roles
let denied = tools.iter().filter(|t| t.name().ends_with("write"));
// after: exempt the private working notes surface
let denied = tools.iter()
    .filter(|t| t.name().ends_with("write") && t.name() != "todo_write");
Defensive patterns

Strategy: validation

Validate before calling

// before relying on a role's catalog, assert the surface:
fn expects_tool(registry: &SubAgentToolRegistry, tool: &str) -> bool {
    registry.catalog_names().any(|n| n == tool)
}
assert!(expects_tool(&registry, "todo_write"), "read-only roles must keep todo_write");

Type guard

fn is_private_notes_tool(tool: &str) -> bool {
    matches!(tool, "todo_write" | "todo_read")
}

Try / catch

match registry.execute("agent_read_only", "todo_write", payload).await {
    Ok(out) => assert_eq!(out, expected),
    Err(e) => panic!("todo_write denied for read-only role: {e:?} — check the deny-list exemption"),
}

Prevention

When it happens

Trigger: Executing `todo_write` against an `agent_read_only` SubAgentToolRegistry whose deny-list/allow-list construction no longer exempts the private todo tool — e.g. after tightening role permissions, changing the tool name, or seeding a deny list that includes todo_write.

Common situations: Refactoring the permission allowlist for read-only roles, renaming the todo tool, or adding a new write-protection layer that sweeps in the private notes surface; also seen when tests forget to enable the agent tool surface options.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/83af6868276b79b2. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tools/subagent/tests.rs:8528

            assert!(
                registry.is_tool_allowed("image_ocr"),
                "{role:?} must allow image_ocr"
            );
            assert!(
                !registry.role_blocks_unhardened_process_tool("image_ocr"),
                "{role:?} must not hide proven read-only tool image_ocr"
            );
        }

        // Private working notes are writable; workspace writes are not.
        registry
            .execute(
                "agent_read_only",
                "todo_write",
                json!({"todos": [{"content": "inspect issue evidence", "status": "in_progress"}]}),
            )
            .await
            .expect("read-only roles may revise their private working notes");
        assert_eq!(
            todo_contents(&todo_list).await,
            vec!["inspect issue evidence"],
            "the bounded notes write lands only in this child's todo list"
        );
        assert!(
            registry
                .envelope_refusal(
                    "File",
                    &json!({"action": "write", "path": "src/lib.rs", "content": "nope"})
                )
                .is_some(),
            "agent-owned notes must not widen workspace writes"
        );
    }
}

#[tokio::test]

View on GitHub (pinned to 433685b202)