Skip to content

Intent drift on shell tool: model plans exec_command but hook enforces Bash (register-and-retry loop) #49

Description

@Harihara04sudhan

Problem

On Codex, a first tool use triggers a frustrating register-and-retry loop:

  1. Agent reads a file -> PreToolUse blocks: `ArmorCodex intent mismatch: parameters not allowed for Bash`
  2. Agent registers a plan with `action: "exec_command"` (Codex's API tool name)
  3. PreToolUse blocks: `ArmorIQ intent drift: tool not in plan (Bash)` -- because Codex reports the shell tool as `Bash` at the hook layer, and `normalizeToolName` only lowercases, so `exec_command != bash`
  4. Agent re-registers with `action: "Bash"` -> finally allowed

This wastes turns and makes the plugin feel like it's fighting the user.

Root cause

  • plugins/armorcodex/scripts/lib/common.mjs normalizeToolName only trims+lowercases; no alias between Codex's shell tool names (exec_command/shell/local_shell/unified_exec) and Bash.
  • The register_intent_plan directive (engine.mjs) says "action = tool name" without telling the model the canonical names, so it guesses exec_command.

Fix

  • Alias the Codex shell family to bash in normalizeToolName so a plan declaring any of them matches the actual Bash tool call (and policy rules for bash cover the shell family).
  • Make the register_intent_plan directive name the canonical tools (Bash for shell, apply_patch for edits, exact MCP tool name), and tell the agent to register all tools up front with metadata.inputs: {}.
  • Tests in tests/tool-alias.test.mjs.

Refs

Part of the ArmorCodex parity work (#41). Fix on branch feat/armor-policy-parity.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions