# How `stone eval` starts one headless role run in this harness (lifecycle.md, "Eval design").
# stone fills $role, $model, $budget, and $prompt. An argument that is only $tools becomes the
# tool list of the role. For a role eval, the two variants differ only in --agent: the role file is
# also removed from the workspace for "without". The hook and the tools stay the same in both
# variants. For any other component (a hook), the runner uses `with` for both variants, so both
# load the same role file, and "without" removes only the component (D44).

run:
  with: [claude, -p, --agent, $role, --model, $model, --output-format, stream-json, --verbose,
         --permission-mode, acceptEdits, --setting-sources, project, --max-budget-usd, $budget,
         --allowedTools, $tools, --, $prompt]
  without: [claude, -p, --model, $model, --output-format, stream-json, --verbose,
            --permission-mode, acceptEdits, --setting-sources, project, --max-budget-usd, $budget,
            --allowedTools, $tools, --, $prompt]
  # A guidance eval (D69): no --agent, because the workspace has no role file. The default
  # permission mode denies each tool that --allowedTools does not list, so the writer cannot edit a
  # file and the report is the text. --setting-sources project keeps the user-level instruction file
  # out of the run (probe of 2026-10-23: a project CLAUDE.md loaded, the user-level rules did not).
  guidance: [claude, -p, --model, $model, --output-format, stream-json, --verbose,
             --permission-mode, default, --setting-sources, project, --max-budget-usd, $budget,
             --allowedTools, $tools, --, $prompt]

env:   # the hook reads the role from agent_type (set by --agent), and STONE_ROLE is the fallback (D55)
  with: {STONE_ROLE: $role}
  without: {STONE_ROLE: $role}

tools:   # the same lists as the role files, plus the commands that the role runs
  shaper: [Read, Grep, Glob, Write, Edit]   # a file ticket (D60); the hook limits the edits
  planner: [Read, Grep, Glob, Write]
  writer: [Read, Grep, Glob]   # the guidance.writing eval (D69): read-only
  tester: [Read, Grep, Glob, Edit, Write, "Bash(python -m unittest*)", "Bash(git diff*)",
           "Bash(git log*)", "Bash(git show*)", "Bash(git add*)", "Bash(git commit*)",
           "Bash(git status*)"]
  reviewer: [Read, Grep, Glob, "Bash(python -m unittest*)", "Bash(git diff*)", "Bash(git log*)",
             "Bash(git show*)", "Bash(git status*)"]   # read-only: the reviewer changes no file
  # The role.investigator eval: the report file, the tests, a short repro, and the git history.
  # The hook limits the file tools to the reports path.
  investigator: [Read, Grep, Glob, Edit, Write, "Bash(python -m unittest*)", "Bash(python -c*)",
                 "Bash(git diff*)", "Bash(git log*)", "Bash(git show*)", "Bash(git status*)"]
  # The hook.protect-paths eval (D39): the shell write forms of its scenarios. Confirmed on
  # 2026-10-19 and 2026-10-21: sed -i, a redirect, tee, cp, and python3 -c ran under acceptEdits
  # (30 of 30 runs on 2026-10-21, with no file tool). A command with a second part (`; echo ...`)
  # needed approval and was denied, so the model ran it again alone (6 of 30 runs).
  # The role.implementer eval adds the commands that the role runs: the checks and the commit.
  # The task of the hook eval says "do not commit", so the extra tools do not change it.
  implementer: [Read, Grep, Glob, Edit, Write, "Bash(sed -i*)", "Bash(printf*)", "Bash(tee*)",
                "Bash(cp*)", "Bash(python3 -c*)", "Bash(git diff*)", "Bash(git status*)",
                "Bash(python -m unittest*)", "Bash(git log*)", "Bash(git show*)",
                "Bash(git add*)", "Bash(git commit*)"]

output_where: {type: result}   # use the last JSON object with these keys and values

output:   # dotted paths in the last JSON object of the output (the "result" event).
          # stone reads these names: report, cost_usd, input_tokens, output_tokens, turns.
  report: result
  cost_usd: total_cost_usd
  input_tokens: usage.input_tokens
  output_tokens: usage.output_tokens
  turns: num_turns
