
An agent’s patch is a proposal, not proof. Give Copilot a bounded Rails task, then inspect the diff, negative tests and unresolved policy before approving the change.
GitHub Copilot for Rails Engineers · Part 03
A Rails agent can edit a route and controller in minutes. The hard part is deciding which behavior it was authorized to add, how a reviewer can verify it, and what remains unknown. In Part 01, we mapped CaseFlow: resolved is a legal model value, but there is no update endpoint. In Part 02, we taught Copilot to cite that boundary. Here we turn the question into an issue, a candidate diff and a review worksheet.
The companion package includes the full baseline Rails API, the issue, an agent prompt, an applicable patch, four proposed request specs, the review worksheet and a study workbook with answers. No GitHub issue or PR has been opened in this educational repository. The patch is a local review artifact; Ruby/RSpec and HTTP calls have not been executed in this authoring environment.
Contents
- First, make the issue decidable
- Give the agent a bounded task
- Inspect the patch as a reviewer
- Separate test assertions from results
- Turn review into a PR decision
- Your 35-minute lab
- References and supporting materials
First, make the issue decidable {:#issue}
“Let users update status” hides unanswered questions: which user, which transitions, what happens on an invalid state, and which unrelated fields can change? A good issue turns that uncertainty into acceptance criteria. For this synthetic exercise, we propose PATCH /api/requests/:id/resolve, accepting only open → resolved and requiring an operator token stored server-side in CASEFLOW_OPERATOR_TOKEN. This token models an operator capability for the lab; it is not a customer-approved production identity system. Missing configuration or missing/incorrect credentials should fail closed. A real engagement would settle actors, authorization, rotation, audit trail and concurrent requests before deployment.
| Requested case | Expected from candidate source and proposed specs | What remains unobserved |
|---|---|---|
| Open + valid token |
200, serialized resolved, persisted change |
Focused RSpec and manual response |
| Missing/wrong token |
401, original state retained |
Focused negative spec run |
Already in_progress
|
409, clear error, state retained |
Focused negative spec run |
| Client tries arbitrary status | No generic update action; resolve never accepts status from payload | Route audit and unexpected-input probe |
The full issue in the package distinguishes the lab decision from unknown production policy. Keep that distinction in a client conversation: a reviewer can evaluate the code against this issue, while still withholding deployment approval.
Give the agent a bounded task {:#agent}
GitHub’s Copilot cloud agent quickstart describes assigning an issue and reviewing the resulting pull request. On your Mac, you can also use VS Code agent mode with the packaged task prompt. Both routes depend on repository access and feature availability. This package has no GitHub remote for the CaseFlow lab, so nothing here claims the cloud agent opened a PR.
Ask for plan → change → focused tests → diff summary → review, in that order. Give the agent exact context: the issue, config/routes.rb, app/controllers/api/requests_controller.rb, app/models/service_request.rb, and spec/requests/api/requests_spec.rb. Open caseflow/ as the workspace root so its .github/ instructions are in scope. One useful instruction from the packaged prompt is:
Implement only the issue's scope. Report the exact files changed,
negative cases, tests you actually ran, and any blocker.
Do not invent a passing CI run or treat the lab token as a production policy.
The review stage cannot be delegated away. GitHub’s guide to reviewing agent output tells reviewers to inspect changes and test results before merging. It also documents conditions under which workflows for agent-authored PRs need explicit approval; check the actual Actions state instead of assuming that a badge ran automatically.
The green PR node means a document with recorded evidence, not a merged or production-safe feature. The test branch can land in a blocker. That branch is as important as the happy path.
Inspect the patch as a reviewer {:#diff}
A local candidate patch in parts/03-issue-to-pr/candidate.patch proposes exactly three changed files: route, controller and request spec. From the companion root, inspect before applying:
git apply --check parts/03-issue-to-pr/candidate.patch
git apply --stat parts/03-issue-to-pr/candidate.patch
git apply parts/03-issue-to-pr/candidate.patch
The support ZIP contains the complete baseline caseflow/ Rails app. The patch is an optional change to that app; keep a clean copy if you want to repeat the exercise. git apply --check passed on the packaged baseline at authoring time; that check says only that the patch fits, not that the Rails feature works.
The route patch declares a single member action, without exposing general update:
resources :requests, only: %i[index show create] do
patch :resolve, on: :member
end
The controller’s proposed guard reads the token from the environment, refuses empty configuration, and compares supplied credentials using Rails’ secure comparison utility. Its resolve action looks up the request, rejects non-open state, then writes resolved explicitly. It does not permit params[:status]. Rails documents HTTP token authentication; the candidate uses that mechanism as an educational boundary, not as a finished authorization design.
Review questions are concrete. Does the token guard run before the database lookup? If the environment variable is unset, could the endpoint become public? Can a client transition in_progress? Could a second concurrent request race between the state check and the write? What does a missing ID return on your actual Rails configuration? The candidate handles the first three in source, but lacks a focused unset-token spec and does not settle concurrency, audit or missing-ID behavior. Those are findings, not silent assumptions.
Separate test assertions from results {:#verify}
The candidate adds four request examples: valid token and open request, no token, wrong token, and valid token with in_progress. Each asserts the expected status and persistence. Apply the patch, then from caseflow/ run:
bundle install
RAILS_ENV=test bin/rails db:prepare
bundle exec rspec spec/requests/api/requests_spec.rb
Log the versions, command, exit code and output in your private ENVIRONMENT.md; the app README explains initial setup. A green output in one local environment would support this specific candidate, not a production guarantee. If Bundler or SQLite blocks setup, record the first error. The verified baseline still contains only the original route and specs until you apply the patch.
For an optional manual probe, start the patched server with a synthetic, locally set value, then use an existing request ID returned by POST. Do not commit the token or paste a real secret into the issue:
CASEFLOW_OPERATOR_TOKEN=synthetic-operator-token bin/rails server
curl -i -X PATCH http://localhost:3000/api/requests/1/resolve \
-H 'Authorization: Bearer synthetic-operator-token'
curl -i -X PATCH http://localhost:3000/api/requests/1/resolve
Replace 1 with the actual created ID. Expected source branches are a successful transition and a 401 for a missing token. They are not captured responses. Confirm whether your Rails version accepts the chosen token header and inspect the actual JSON and database state. For a real service, use HTTPS and a reviewed credential and authorization design.
Turn review into a PR decision {:#review}
The packaged PR-REVIEW.md is a review worksheet, not a fabricated PR. It requests exact results, highlights the single shared operator token as a production decision, and asks for an unset-token case and concurrency discussion. A useful draft PR description states the scope, links the issue, gives the focused command and its actual result, lists remaining unknowns and asks for a reviewer decision. If tests have not run, “pending due to environment blocker” is the correct entry.
In a consultative engagement, the client receives a bounded answer: “We have a candidate patch with a narrow endpoint and explicit rejection cases. We cannot recommend deployment until your authorization rule is defined and we have real test and review evidence.” The agent accelerated the diff; the review made it accountable.
Your 35-minute lab {:#lab}
- Read
parts/03-issue-to-pr/ISSUE.md. Mark the synthetic operator-token assumption and write one different production authorization question. - Ask Copilot to plan and propose the change using
prompts/03-agent-issue-to-pr.md. Record paths and tests it proposes before seeing the packaged candidate patch. - Inspect
candidate.patch; apply it to a clean copy withgit apply --check, then compare your agent’s diff to the candidate. Flag extra migrations, mass-assigned status or invented policy classes. - Run focused RSpec where possible, record its exact output, then inspect the positive and negative branches. Do not call a static
git applyresult a passed test. - Complete
PR-REVIEW.mdand the study workbook. Make one explicit review decision: change requested, evidence pending or acceptable for this lab; distinguish each from production approval.
Acceptance criterion: a reviewer can inspect every changed path, tie each acceptance case to an assertion or observed run, and identify the unresolved customer authorization decision.
References and supporting materials {:#references}
- Download Part 03 package: this article’s Markdown, integrated baseline Rails app, candidate patch, issue, agent prompt, review worksheet, workbook with answers, editable Mermaid and visual masters.
- GitHub Docs: Copilot on GitHub quickstart
- GitHub Docs: review Copilot output
- GitHub Docs: Copilot code review
- Rails Guides: HTTP token authentication