
Cover illustration: the CaseFlow browser is a conceptual application view. The companion lab supplies an integrated Rails API source app, not a working web interface.
GitHub Copilot for Rails Engineers · Part 01
The first half-hour in a new repository should produce a navigable architecture atlas, named unknowns and one useful next action.
A client asks: “Can we add status transitions to this Rails API this week?” You have never seen the codebase. GitHub Copilot can help you explore it, but an answer that sounds like Rails is not evidence that this particular application behaves that way. Our goal is a small, navigable architecture atlas: what the API exposes, how a request flows, what a status change might affect, and which claims still need a run. Copilot should discover and connect evidence; we should be able to challenge the resulting map.
We will use CaseFlow, a synthetic integrated Rails API source app. It is deliberately small enough to inspect and incomplete enough to expose an important habit: distinguish what source says, what a test asserts, and what a running system actually did. The companion materials contain the integrated app, the finished atlas under docs/architecture/, a deterministic declaration inventory, the Copilot prompt, Mermaid source and a workbook with answers. The atlas is a reviewed source map, not an observed production trace.
- 0-5 minPredict before you inspect
- 5-12 minGenerate an inventory and trace one path
- 12-20 minBuild an architecture atlas with Copilot
- 20-27 minAudit the atlas and run one check
- 27-30 minGive the client one bounded answer
Contents
- 0–5 minutes: predict before you inspect
- Early Copilot CLI check:
copilot init - 5–12 minutes: generate an inventory and trace one path
- 12–20 minutes: ask Copilot for an architecture atlas
- 20–27 minutes: audit the atlas and run one check
- 27–30 minutes: give the client one bounded answer
- Your 20–30 minute lab
- References and supporting materials
0–5 minutes: predict before you inspect
Write down your current hypothesis for POST /api/requests: what input is accepted, what gets saved and what comes back. Label every sentence prediction. This prevents your first impression or an AI suggestion from quietly turning into a fact.
The question is about one change, but its impact can cross more than one file. Predict whether an update endpoint, authorization check or background job already exists. Later, compare these predictions with a capability map and evidence register. GitHub’s codebase exploration guide shows how repository and file context can narrow a question. Its review guidance is equally relevant: inspect the answer against actual files. Here, the hypothesis is an investigation aid, not a delivery promise.
Early Copilot CLI check: copilot init
You’re right to try Copilot’s own repository onboarding early. From a terminal, copilot init (or /init in an interactive Copilot CLI session) analyzes the current project and creates or suggests changes to .github/copilot-instructions.md. It can surface build/test commands, high-level architecture and conventions. It is a draft of guidance for future sessions, not a verified request trace or a test run. Check every generated command and architectural claim against the repository. See the GitHub CLI command reference.
Our cumulative CaseFlow download already includes .github/copilot-instructions.md and AGENTS.md, so /init here sees existing guidance and may suggest improvements rather than producing an independent first map. Try it in a throwaway copy from the companion root (after installing and signing into Copilot CLI):
cp -R caseflow caseflow-init-trial
(cd caseflow-init-trial && copilot init)
diff -u caseflow/.github/copilot-instructions.md \
caseflow-init-trial/.github/copilot-instructions.md || true
Review any proposed change; keep the original caseflow/ untouched. Ask: which build/test command and which architecture claim can you cite in source, and which are only assumptions? Keep that comparison as a discovery artifact. In the next steps we trace the actual request path and build an evidence-backed atlas; Part 02 revisits the instruction file deliberately.
5–12 minutes: generate an inventory and trace one path
From the companion repository root, run:
ruby scripts/build_caseflow_inventory.rb
This generates docs/architecture/generated-inventory.md: a CaseFlow application guide with file:line declarations, Gemfile dependencies, the SQLite adapter, an architecture diagram, local setup and API examples. The extraction is reproducible and intentionally narrow. The diagram and runbook explain source-backed relationships; they do not execute Rails, discover every indirect dependency or assert that tests passed.
Start with caseflow/config/routes.rb:
namespace :api do
resources :requests, only: %i[index show create]
end
This declares a create route under /api. Rails routes dispatch incoming HTTP methods and paths to controller actions, as described in the Rails routing guide. The only: list matters: it does not declare an update route. Then inspect app/controllers/api/requests_controller.rb:
def create
request = ServiceRequest.new(request_params)
if request.save
render json: serialize(request), status: :created
else
render json: { errors: request.errors.full_messages }, status: :unprocessable_entity
end
end
def request_params
params.require(:request).permit(:title, :description)
end
The controller allows title and description from the request payload; status is not permitted there. Its private serialize method selects id, title, description, status, created_at and updated_at. There is no separate serializer file in this CaseFlow app. A reader who guesses “the serializer” from habit would be looking in the wrong place.
Next, the model constrains title presence, title length and status membership:
STATUSES = %w[open in_progress resolved].freeze
validates :title, presence: true, length: { maximum: 160 }
validates :status, inclusion: { in: STATUSES }
The migration declares a service_requests table with status defaulting to open. A migration describes a schema change applied during setup; it is not another method called for each POST. In a correctly migrated database, the default is a reasonable expectation for a new record created without an explicit status, but we still have to run the application before claiming to have observed it. See the Rails migration guide for the schema role of migrations.
The dotted link marks schema context, not an extra runtime step. The status labels describe the supplied controller branches; they are not a report of executed responses.
12–20 minutes: ask Copilot for an architecture atlas
Open caseflow/ as the VS Code workspace and give Copilot a change question: “Can a client resolve a request through this API?” Workspace search or its semantic index can find likely source; the generated inventory gives you explicit declarations to cross-check. Ask for four connected artifacts, rather than a prose summary:
Investigate this Rails workspace in read-only mode. The client asks whether
open → resolved is available. Produce: (1) a capability table with entry
points and source files; (2) a Mermaid flowchart TD for POST /api/requests,
with the migration as a dotted schema dependency; (3) a change-impact table
for API, data, tests, authorization and other effects; (4) an evidence
register classifying source, spec assertion, observation or unknown.
Suggest three checks that could falsify important assumptions. Cite exact
files and symbols. Do not invent an update action, a job or a passing test.
Compare the result with the reviewed docs/architecture/README.md, its generated inventory and docs/diagrams/request-path.mmd in the companion package. Check each path yourself. A citation is useful only if it points to a file that exists and supports that exact claim. Record a missing citation or a mistaken inference; correcting Copilot’s map is part of the exercise. In a client repository, keep sensitive data out of the prompt and follow the organization’s approved tooling rules.
What the atlas should reveal
| Atlas view | Source-backed finding | Important limit |
|---|---|---|
| Capabilities |
index, show, create are declared |
No update route in the supplied app |
| Request path | Create permits title and description; controller branches to 201 or 422
|
Branches are source expectations, not observed responses |
| Change impact | Model allows stored resolved
|
There is no transition contract or authorization policy here |
| Evidence register | Two request specs describe create behavior | Their presence does not prove they passed |
This is more useful than “I found a controller.” It links a client question to the API surface, persisted state, verification and missing decisions. The reviewed atlas is included in the companion package under docs/architecture/.
20–27 minutes: audit the atlas and run one check
Audit every diagram edge and table row against the cited file. A search result, a plausible Rails convention and an agent-generated link are leads; each still needs verification. The included request spec has two cases: a valid title expecting a 201 response, an open status and one stored record; and a missing title expecting 422 with no record. Those are assertions in source, not reported pass results. The companion includes an integrated Rails API source app, but has no resolved lockfile or installed dependencies here; we have not executed its specs in the authoring environment.
On a Mac with compatible Ruby and Bundler installed, follow caseflow/README.md in the companion materials. Use the integrated caseflow/ app, install dependencies, and record the actual output of:
bundle install
bin/rails db:prepare
bundle exec rspec spec/requests/api/requests_spec.rb
If setup fails, keep the first useful error. A blocker is evidence. Do not replace it with a hypothetical green test run. If it succeeds, send a synthetic HTTP request and capture the actual response before promoting the expected behavior to observed behavior.
| Statement | Evidence now | Classification |
|---|---|---|
Route includes create but no update
|
config/routes.rb |
Source fact |
Controller permits title, description
|
RequestsController#request_params |
Source fact |
Migration declares default open
|
Migration source | Schema fact; runtime effect pending |
Valid request returns 201 in this environment |
Spec assertion only | Unverified until execution |
Client can transition to resolved
|
No route/action or test supplied | Unsupported |
27–30 minutes: give the client one bounded answer
The useful answer is a shareable atlas, not “Copilot says the endpoint works.” Alongside the map, tell the client: “The source defines creation with title and description, title and status validations, and a schema default of open. The supplied specs cover valid creation and missing title, but I have not run them in this environment. I do not see an update route. The next safe step is to boot the integrated app, record the focused spec result, then scope a status-transition contract and tests.”
The atlas supports a short engagement: a visible inventory, a diagram of the current path, a change-impact table, a named uncertainty and a testable next issue. It also gives a stakeholder a clear boundary between discovery and implementation.
Your 20–30 minute lab
- Make three predictions in a local
ENVIRONMENT.mdusing the template (caseflow/ENVIRONMENT.template.md). - In a throwaway copy, try
copilot initfrom the CaseFlow directory. Compare any proposed instructions withconfig/routes.rb,Gemfile, the existing specs and the original instructions; record one supported claim and one unknown. Keep the packaged app unchanged. - Generate the inventory; ask Copilot for four atlas views. Compare them with
docs/architecture/README.mdand the five files indocs/labs/01-codebase-diagnosis.md. Mark every unsupported edge. - Attempt the focused spec; record the versions, command, actual outcome or first blocker.
- Explain why a model that lists
resolveddoes not prove a client can perform a status transition. Deliver the corrected capability table, request diagram, change-impact table and one bounded issue.
Retrieval question: What evidence would let you change “the source suggests 201” to “I observed 201,” and why does a passing spec not prove the entire API is production ready?
Next in the series: we will refine the context we give Copilot—repository guidance, instructions and tool boundaries—and test how the atlas changes. The reviewed atlas, generator, Mermaid source and workbook are in the companion package.
References and supporting materials
Finding the prompt after download: extract the support ZIP and open github-copilot-rails-labs/prompts/01-trace-request.md to read the full prompt. For Copilot Chat, open github-copilot-rails-labs/caseflow/ as the VS Code workspace; the executable file is .github/prompts/01-trace-request.prompt.md. Invoke /01-trace-request. On macOS, Finder may hide the .github directory (press Command-Shift-Period to show hidden files). The companion also contains the complete three-prompt catalog in github-copilot-rails-labs/prompts/.
-
Read or download the Part 01 Copilot prompt: a standalone text copy. To run it as a VS Code prompt file, use the matching
.prompt.mdinside the support ZIP undergithub-copilot-rails-labs/caseflow/.github/prompts/. - Download the CaseFlow companion package: the complete post in Markdown, integrated Rails API app, study workbook with exercises and answers, field lab, atlas, reproducible inventory, Copilot prompt, Mermaid source and validation status. The integrated app still requires installing dependencies and its request specs remain unexecuted in this authoring environment.
- VS Code Docs: Working with agents in an unfamiliar codebase.
- VS Code Docs: How Copilot understands your workspace.
-
Part 01
copilot initdiscovery exercise: optional read-and-verify worksheet, also packaged underparts/01-first-30-minutes/copilot-init-lab.md. -
GitHub Docs: Copilot CLI project initialization (
copilot init). - GitHub Docs: Using GitHub Copilot to explore a codebase.
- GitHub Docs: Review AI-generated code.
- Rails Guides: Routing from the Outside In.
- Rails Guides: Active Record Migrations.