Skip to content

bug(rovodev): per-tool permissions emitted at toolPermissions.<tool> instead of toolPermissions.tools.<tool>, so they never apply #2422

Description

@dyoshikawa

Summary

rulesync writes Rovo Dev per-tool permission levels one level too shallowtoolPermissions.<tool> instead of the documented toolPermissions.tools.<tool> — so generated permissions never take effect and a real user config round-trips to nothing. Three smaller MCP/checks drifts follow from the same pass.

Release / version situation

Rovo Dev updates independently of the Atlassian CLI package, and Atlassian does not publish per-build Rovo Dev release notes on a public page. The ACLI changelog was last updated 2026-03-25 and states "Rovo Dev can now be updated independently of Atlassian CLI"; in-product release notes are only reachable via the /changelog slash command. developer.atlassian.com/cloud/acli/release-notes/ and /cloud/acli/reference/rovodev/ both 404.

Therefore the baseline below is the current state of the living support docs, not a versioned changelog. All upstream claims were verified against Atlassian's live support docs (fetched raw with curl and converted to text; the pages are server-rendered, so there was no SPA problem).

Verified upstream surface (2026-07-26)

toolPermissions:
  # Default permission for tools not explicitly listed (default: "ask")
  default: "ask"
  tools:
    create_file: "ask"
    delete_file: "ask"
    move_file: "ask"
    find_and_replace_code: "ask"
    open_files: "allow"
    expand_code_chunks: "allow"
    expand_folder: "allow"
    grep: "allow"
    createTechnicalPlan: "allow"
    getJiraIssue: "allow"
    createJiraIssue: "ask"
    updateJiraIssue: "ask"
    getConfluencePage: "allow"
    createConfluencePage: "ask"
    updateConfluencePage: "ask"
  bash:
    default: "ask"
    commands:
      - command: "ls.*"
        permission: "allow"
    runInSandbox: false        # macOS only, internal users
  allowedExternalPaths: []

Both use tools in Rovo Dev CLI and manage Rovo Dev CLI settings agree that per-tool levels live under toolPermissions.tools.*.

Gaps

1. permissions — wrong YAML depth (toolPermissions.<tool> instead of toolPermissions.tools.<tool>)

  • Upstream: per-tool levels are nested under toolPermissions.tools (see the block above; both docs pages agree). toolPermissions.default is the documented catch-all for tools not listed.
  • rulesync: src/features/permissions/rovodev-permissions.ts writes per-tool levels directly under toolPermissions (toolPermissions[toolKey] = action), and rovodev-permissions.test.ts asserts tp.open_files / tp.create_file at that depth. bash and allowedExternalPaths are at the right depth; only the per-tool block is wrong. Import (toRulesyncPermissions) reads the same wrong depth, so a real user config round-trips to nothing.
  • Also unmapped: toolPermissions.default, and the documented planning/Atlassian tool keys (createTechnicalPlan, getJiraIssue, createJiraIssue, updateJiraIssue, getConfluencePage, createConfluencePage, updateConfluencePage), which are dropped on import.

2. checks — .rovodev/.review-agent.md unsupported

  • Upstream: .rovodev/.review-agent.md in the repository root holds custom PR-review instructions for Rovo Dev code reviews (Bitbucket/GitHub) — set custom instructions for code reviews.
  • rulesync: unsupported. pnpm run dev generate --targets rovodev --features "*" --dry-run prints Target 'rovodev' does not support the feature 'checks'. Skipping.; only amp and hermesagent are registered in src/features/checks/checks-processor.ts. Rovo Dev's repository-level PR-review instruction file is exactly the single-file review-instruction shape rulesync's checks feature already targets elsewhere.

3. mcp — canonical type is never translated to Rovo Dev's transport

  • Upstream: ~/.rovodev/mcp.json holds mcpServers, and the documented per-server keys are command, args, env, url, headers, transport (stdio | http | sse), and enable_instructions.
  • rulesync: RovodevMcp.fromRulesyncMcp writes rulesyncMcp.getMcpServers() verbatim (src/features/mcp/rovodev-mcp.ts). Canonical rulesync configs use type (see this repo's own .rulesync/mcp.json: "type": "http"), while Rovo Dev documents transport. The kilo/roo/goose/amp/codexcli adapters already normalize this.

4. mcp — disabled servers are not honoured

  • Upstream: Rovo Dev disables servers through mcp.disabledMcpServers in ~/.rovodev/config.yml, not via a field in mcp.json. The mcp: block also carries mcpConfigPath and allowedMcpServers.
  • rulesync: passes canonical disabled: true through into mcp.json, where Rovo Dev ignores it — so a server the user disabled in rulesync still loads.

5. hooks — still unsupported, still blocked on an undocumented schema

  • Upstream: /hooks ("Manage event hook configurations") is listed in the official command reference, and the eventHooks section of ~/.rovodev/config.yml is referenced by the Atlassian blog (2026-01-26) — but the literal YAML schema is still unpublished, and the settings reference page has no eventHooks section at all.
  • rulesync: unsupported; there is no src/features/hooks/rovodev-hooks.ts and the dry-run prints the skip message. Same blocker recorded on closed Follow up Rovo Dev upstream updates: event hooks (eventHooks in ~/.rovodev/config.yml) #1986; re-verified today, nothing has changed upstream. No action possible yet — recorded so the next sweep does not re-derive it.

Proposed Follow-up

  1. Nest generated per-tool levels under toolPermissions.tools, read from there on import (optionally tolerating the legacy flat shape rulesync previously emitted), and map a rulesync-wide catch-all onto toolPermissions.default. Add the planning/Atlassian tool keys to the known-tool set. Priority item — current output is inert.
  2. Add a RovodevCheck adapter rendering rulesync checks into .rovodev/.review-agent.md (project scope only — the file is repo-root by definition).
  3. Emit transport from canonical type/transport (mapping localstdio, streamable-httphttp, dropping or warning on ws, which Rovo Dev does not support) and convert back on import.
  4. Translate disabled: true into mcp.disabledMcpServers in the global config.yml (the permissions adapter already merges into that file and preserves other keys), and read it back on import.
  5. Hooks: no action until Atlassian publishes the eventHooks schema.

Not gaps / rejected

  • Project-scope MCP or permissions. The Bitbucket "Rovo Dev: Advanced agentic configuration" page shows a project .rovodev/config.yml, but only when it is explicitly referenced (agents.<name>.config.path in Pipelines, or acli rovodev run --config-file). The CLI does not auto-discover a project config, so rulesync's global-only gating stays correct.
  • rules — memory is ~/.rovodev/AGENTS.md, project AGENTS.md / AGENTS.local.md, with parent-dir lookup; matches rulesync.
  • skills.rovodev/skills/<name>/ or .agents/skills/<name>/; user ~/.rovodev/skills/ or ~/.agents/skills/; frontmatter name, description, allowed-tools, license, compatibility, metadata — all covered by src/features/skills/rovodev-skill.ts.
  • subagents.rovodev/subagents/, ~/.rovodev/subagents/, frontmatter name/description/tools; extra keys round-trip through the rulesync rovodev key.
  • commands (saved prompts).rovodev/prompts.yml (name/description/content_file) plus markdown content resolved relative to prompts.yml, matching what rovodev-command.ts emits.
  • Shared .agents/skills alternative-root ownership — the same alternativeSkillRoots pattern used by augmentcode/vibe/opencode; not a Rovo Dev-specific gap.

Open questions / unconfirmed

  • The eventHooks YAML schema (key names, event list, handler shape) — no primary source (gap 5).
  • Whether Rovo Dev silently accepts type as an alias for transport in mcp.json — undocumented. Gap 3 stands either way, since transport is the documented key.
  • Whether a powershell permission block exists alongside bash: the tools page mentions PowerShell execution and console.toolResultVisibility lists a powershell tool, but no toolPermissions.powershell is documented.
  • The settings page's mcpConfigPath default string is inconsistent with the MCP page — it says ~/.rovodev/mcp_config.json while the MCP page's own mcpConfigPath example is ~/.rovodev/mcp.json. rulesync targets mcp.json, matching the MCP page.
  • The exact date/version when .rovodev/.review-agent.md and the toolPermissions.tools nesting were introduced — Atlassian publishes no dated changelog for these pages.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghigh prioritymaintainer-scrapRough notes for AI implementation. Not for human eyes.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions