Study guides / CCAR-P / Domain 7

Developer Productivity & Operational Enablement · Lesson 2 of 3

7.2 - AI-Assisted Developer Workflows

Choose between plan mode and direct execution, close the feedback loop with verification, place review and CI automation correctly, and report productivity gains without over-claiming.

Improving a developer workflow with an agent is four decisions: how much to plan before Claude edits, what check lets the loop close without a human, where independent review and CI automation sit, and how you will know any of it helped. The Claude Code best-practices guide builds most of its advice on one constraint: the context window fills quickly and quality degrades as it fills. That is the lens for the trade-offs below.

Plan mode versus direct execution

Plan mode makes Claude research and propose without editing your source: it reads files, runs exploratory commands and writes a plan, and edits stay blocked until you approve. Enter it with Shift+Tab, claude --permission-mode plan, or a /plan prefix on one prompt. Approving the plan leaves plan mode so Claude starts editing. The built-in Explore and Plan subagents are read-only and keep their reading in a separate context window, so discovery output does not crowd the session (Explore also skips your CLAUDE.md files).

The decision criterion is ambiguity and blast radius, not difficulty. Plan when the approach is uncertain, the change spans several files, or the code is unfamiliar. Skip planning when you could describe the diff in one sentence: a typo, a log line, a rename, or a hard bug whose stack trace already names one function. A useful hybrid for larger features is to have Claude interview you, write a spec to a file, then start a fresh session to implement it, so the implementation runs on clean context. The cost of planning is time and tokens; the cost of skipping it is solving the wrong problem across many files.

Plan mode is a workflow, not a security boundary

In plan mode Claude is instructed not to edit, and edits are blocked pending approval, but the permissions docs note that in interactive terminal sessions where bypass permissions is available Claude Code does not enforce those blocks. If read-only behaviour must be guaranteed, use permission rules or the dontAsk mode, not plan mode alone.

Iterative refinement: close the loop, then pick the technique

Give Claude a check it can run: tests, a build exit code, a linter, a script that diffs output against a fixture, or a screenshot comparison. Without one, “looks done” is the only signal and you become the verification loop. The strength of the gate is a design choice: ask in the prompt, set a session-long /goal condition, run the check from a Stop hook that blocks the turn from ending until it passes, or use a separate verifier so the agent doing the work is not the one grading it. Ask for evidence (test output, the command and its result) rather than an assertion.

Then match the technique to the failure mode:

Manage context actively. After two failed corrections on the same issue, /clear and restart with a sharper prompt instead of stacking corrections on a polluted context; use /rewind to undo; send investigations to subagents.

Code review and CI: choose the layer, then harden it

For a scripted claude -p gate: pass -p so the run is non-interactive; use --output-format json with --json-schema and read the structured_output field; scope permissions with --allowedTools or --permission-mode dontAsk; cap work with --max-turns; and branch on the exit code. --bare skips hooks, MCP servers, plugins and CLAUDE.md for reproducible runs (you then pass context with flags such as --append-system-prompt-file). Without it, a -p run executes the hooks in the project's .claude/settings.json and connects its .mcp.json servers even in a folder you never trusted, which matters when a pipeline checks out an untrusted branch.

Review only helps if it is independent. A reviewer in a fresh context sees the diff and your criteria, not the reasoning that produced the change; telling it to flag only correctness or stated-requirement gaps stops it inventing findings to please you. For repeat runs, pass prior findings and ask for new or still-open issues only, so developers are not shown the same comments on every push.

Measuring productivity honestly

The Teams and Enterprise analytics dashboard reports adoption (daily users, sessions), lines of code accepted, suggestion accept rate and, once GitHub is connected, PRs with Claude Code and PRs per user. Anthropic's own notes describe these as deliberately conservative: attribution matches merged-PR lines against session activity in a window from 21 days before to 2 days after the merge, ignores generated files, and does not credit code a developer substantially rewrote. Accepted lines do not track later deletion. Per-invocation cost figures (total_cost_usd in JSON output, the claude_code.cost.usage metric) are client-side estimates that can differ from the bill.

Treat those as activity and adoption signals. Judge value with outcome metrics you already trust (lead time, review turnaround, change failure rate and other DORA measures), compared against a baseline captured before rollout or against a comparable team. Track the cost side too: reviewer time, rework, escaped defects, token spend. Be wary of leaderboards, which reward volume; and report ranges and caveats rather than a single ROI number.

Common exam distractor

“Lines accepted rose 40%, so productivity rose 40%” is the wrong inference. Accepted lines and PR counts measure activity, not delivered value, and the attribution is an estimate. The defensible answer pairs adoption metrics with outcome and quality metrics against a baseline, and states the limits.

Exam traps

Practice question

A pipeline step runs claude -p to implement a change and a later step in the same job runs claude -p --continue to review it. Reviews keep approving changes that later fail in QA for the same class of defect. Which change is most likely to improve review quality?

  • A Append 'be extremely critical and assume there are bugs' to the review prompt and raise --max-turns so the reviewer has room to dig.

    A stricter tone does not remove the underlying problem: the reviewer still holds the generator's reasoning. More turns only adds cost.

  • B Run the review as a fresh invocation given only the diff and acceptance criteria, with tests as a gate before it. Correct

    A fresh context evaluates the change without the generator's rationale, and stating criteria plus running tests gives the reviewer something concrete to check against. This matches the writer/reviewer pattern in the best-practices guide.

  • C Keep --continue so the reviewer has the full context of why each decision was made and can check the code against that rationale.

    That shared context is exactly what makes self-review weak; the reviewer is inclined to accept decisions it already justified.

  • D Switch the review step to plan mode so Claude cannot edit files while reviewing and only reports what it finds.

    Plan mode controls whether Claude edits, not how independent its judgement is. The problem is bias from shared context, not unwanted edits.

Build exercise: Build and evaluate an AI-assisted delivery workflow

Advanced · 90 minutes

You'll practice:

  1. List eight tasks from a real backlog. For each, write plan or direct with a one-sentence reason. Run two of each in Claude Code and record corrections needed, elapsed time and whether you had to /clear.

    It converts the ambiguity criterion into evidence from your own codebase instead of a slogan.

    You should see: A table of eight tasks with your prediction and measured effort. At least one prediction should be wrong or borderline, and you should write down why.

    Hints
    1. For each task, could you describe the diff in one sentence? Does it touch one file or many? Is the approach already decided?
    2. Use claude --permission-mode plan for planned tasks and a normal session for direct ones. Count each correction after Claude's first attempt.
    3. Example rows: rename a config key (direct, one-sentence diff); replace a date library across 30 files (plan, then a fresh session to execute); fix a null dereference at a known line (direct); split a module (plan, uncertain boundaries).
  2. Pick a feature. Write its failing tests first, then ask Claude to implement it and report the test output as evidence. Add a Stop hook that runs the test command and keeps the turn open until it passes. Read the hooks reference to confirm the blocking convention for the Stop event before you write it.

    A check Claude can run, enforced deterministically, lets you walk away from the session. Reading the reference avoids guessing a hook contract.

    You should see: Claude iterates on failures until the suite passes, and the hook prevents the run from ending while tests are red. Your notes say what happens if the tests are flaky.

    Hints
    1. What is the difference between asking Claude to run tests and making the run impossible to finish until they pass?
    2. Put the hook under the hooks key in .claude/settings.json, script the test run, and return the blocking signal documented for the Stop event. Remember the docs say Claude Code overrides the hook after a number of consecutive blocks.
    3. Sketch: hooks -> Stop -> a command that runs your test script; on failure it prints the failing summary to stderr and returns the documented blocking exit status. Confirm the exact convention in the hooks reference before relying on it.
  3. Write a CI script that reviews the current branch diff with claude --bare -p, returns findings that match a JSON schema, is limited to read-only tools and a turn cap, and fails the job when a high-severity finding exists. Use a review-criteria.md file for the instructions.

    This is the hardened shape of a scripted gate: reproducible, machine-parseable, least-privilege and bounded.

    You should see: The script prints JSON containing a structured_output field; jq exits non-zero when a high-severity finding exists; the run is non-interactive and finishes within the turn cap. ANTHROPIC_API_KEY comes from the environment or a secret, never from the file.

    Hints
    1. Which flag makes the run non-interactive, and which flag returns schema-conforming data in the JSON envelope?
    2. Pipe git diff into claude -p, use --append-system-prompt-file for your criteria (bare mode does not load CLAUDE.md), --allowedTools to permit only reads, --max-turns to bound work, and jq -e on structured_output for the exit status.
    3. SCHEMA='{"type":"object","properties":{"findings":{"type":"array","items":{"type":"object","properties":{"file":{"type":"string"},"line":{"type":"integer"},"severity":{"type":"string"},"message":{"type":"string"}},"required":["file","severity","message"]}}},"required":["findings"]}'
      git diff origin/main...HEAD | claude --bare -p 'Review this diff for correctness bugs only.' --append-system-prompt-file review-criteria.md --allowedTools 'Read' --max-turns 5 --output-format json --json-schema "$SCHEMA" > out.json
      jq -e '[.structured_output.findings[] | select(.severity=="high")] | length == 0' out.json
  4. Add incremental behaviour: save each run's findings as a CI artifact, feed them into the next run's prompt, and instruct the reviewer to report only new or still-open issues. Compare the output against a same-session self-review of the same diff.

    Repeated identical comments teach developers to ignore the bot, and self-review shows how much independence matters.

    You should see: The second run omits findings you already fixed or explicitly accepted, and the independent review surfaces at least one issue the self-review missed (or you record that it did not).

    Hints
    1. What information does the second run lack that would let it avoid repeats?
    2. Store the JSON output, prepend it to the prompt with an instruction to list only new or unresolved items, and run the self-review with --continue for comparison.
    3. PREV=$(cat previous-findings.json 2>/dev/null || echo '{}') and include it in the prompt text: 'Previous findings: '"$PREV"'. Report only new issues or ones still present.' Then cp out.json previous-findings.json.
  5. Write review criteria as a REVIEW.md-style file: what counts as blocking, a cap on minor comments, paths to skip, and two repository-specific checks. Use it as your --append-system-prompt-file in step 3. Run the local /code-review on the same diff and compare noise and coverage.

    Review quality is mostly calibration. Note that REVIEW.md itself is read by managed Code Review, not by the local /code-review command, so your script must pass the criteria explicitly.

    You should see: A short criteria file that changes the findings in a visible way (fewer style nits, the two repo checks appearing), plus a short comparison of local, scripted and (if available) managed review output.

    Hints
    1. Which findings would you be unhappy to see on every PR, and which would you always want?
    2. Define severity in terms of production impact, cap minor items, list generated paths to ignore, and add checks such as 'new API routes have an integration test'.
    3. Sections: What blocking means here; Cap the minor comments at five; Do not report generated code or lockfiles; Always check: new routes have integration tests, log lines contain no user identifiers.
  6. Draft a measurement plan for rolling this workflow out to a team: four outcome metrics, two guardrail metrics, the baseline period, the comparison group, and a paragraph explaining what the analytics dashboard can and cannot tell you.

    Architects are asked to justify the investment. An honest plan separates adoption from outcomes and anticipates gaming.

    You should see: A plan that uses dashboard adoption data as context only, measures lead time or review turnaround and defect escape against a baseline, includes a guardrail such as rework or incident rate, and states how estimates and attribution limits will be reported.

    Hints
    1. If lines accepted doubled but incident rate also doubled, what would you conclude?
    2. Pick metrics your organisation already trusts (DORA-style delivery measures, defect escape), capture two to four weeks of baseline, and compare against a similar team not yet using the workflow.
    3. Outline: outcomes = lead time, review turnaround, change failure rate, defect escape; guardrails = rework rate, review load per PR; adoption context = daily users and PRs with Claude Code; caveats = attribution window and rewritten code are excluded, cost figures are estimates.

Sources