# A backlog and standards the agent can read

> Move a two-part spec into the issue tracker as two issues with a "blocked by" link that an agent reads through `gh`, then turn a finding that came up in two reviews into a line in a standards file or a check, and block on style only for a rule in the file or a failed check.

Page: https://schubergphilis.github.io/ai-training/coding-with-agents/backlog-and-standards/
License: CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/

In [the lesson on hooks and CI](https://schubergphilis.github.io/ai-training/coding-with-agents/ci-and-hooks/) two
team rules moved out of a brief and into the project, where every session
runs them. The plan for the next change is often still in one person's
notes or in a chat thread, and the review comments that keep coming back
are in old pull requests. A new agent session starts without them. In this
lesson we move both to
a place the agent reads by itself: the spec into the team's issue tracker,
and a repeated review finding into a standards file or a check.

The project is the nightly sales import from the earlier lessons:
`importer.py` adds up the exports of one night and converts every amount
to euros with the rates in `rates.json`. The team wants to import a past
night again with the rates of that night, and has a short spec for it.

## Put the spec in the tracker

An agent-reachable backlog is the team's specs and tickets, kept in its
tracker, where people and agents can both read and update them. The tracker
also records which ticket blocks which. A spec in a private note helps one
person. The same spec as an issue helps every person on the team and every
agent session, because each of them can find it, read it in full, and
report on it there.

The spec for the past nights has two parts, and the second needs the
first. The importer has to keep the rates of each night before it can
import a past night with them. So the spec becomes two issues, each with
its own "done when" list, and a link between them. GitHub calls the link
"blocked by" on one issue and "blocking" on the other, and it marks a
blocked issue with an icon in the issue list and on project boards
(Creating issue dependencies, GitHub documentation). The order is then in the
tracker, where the next reader sees it, and not only in the head of the
person who wrote the spec.

With the GitHub command-line tool, `gh`, the two issues are two commands.
The bodies are the two files `issue-rates.md` and `issue-rerun.md` in
`site/examples/coding-with-agents/backlog-and-standards/` of the course
repository. `--blocked-by` takes the number of the issue that must be
done first (Creating issue dependencies, GitHub documentation). The second command
below assumes the first issue got number 1. Put the number of your first
issue in its place if it differs.

```sh
gh issue create --title "Keep the rates of each night" --body-file issue-rates.md
gh issue create --title "Import a past night with its own rates" --body-file issue-rerun.md --blocked-by 1
```

If `gh issue create --help` doesn't list `--blocked-by`, your `gh` is
older than the feature. Update it, or set the link on the issue page in
the browser, under **Relationships** in the sidebar.

In another tracker, look for the same two parts, perhaps under other
names: a ticket with a body, and a link type for "this one waits for that
one".
Use the link type. A person reads a sentence in the body such as "do this
after the rates one", but only a link lets the tracker mark the issue as
blocked.

#### Checkpoint: What can a new session find on its own?

Which of these can a new agent session in the project use without anyone
pasting text into it? Select two.

Select exactly 2.

- The spec, written as an issue in the team's tracker
- The spec, kept in the notes app on the lead's laptop
- A "blocked by" link from the second issue to the first
- The order of the two parts, agreed in last week's call
- The spec you pasted in full into last week's session

## Let the agent read it from the command line

The agent reaches the tracker through the same command-line tool. The
vendor guide for Claude Code recommends command-line tools as the way to
work with outside services that costs the least context, names `gh` for
GitHub, and suggests that the agent read the `--help` of a tool it doesn't
know yet (Best practices for Claude Code, Claude Code documentation). These are the commands the agent
needs here:

```sh
gh issue list
gh issue view 2
gh issue view 2 --json blockedBy,blocking
```

`gh issue list` shows the open issues. `gh issue view` shows one issue in
full, and its output has a "Blocked by" row and a "Blocking" row when a
link is set. With `--json` and the fields `blockedBy` and `blocking`, the
same links come back as JSON (Creating issue dependencies, GitHub documentation).

The brief then names the tracker as the source of the work, and nobody
pastes the spec. The transcript below is illustrative and doesn't record a
specific model's words.

#### Prompt (illustrative, not a recorded transcript)

```text
The open issues in this repository are the backlog. Use `gh issue list`
and `gh issue view` to find the open issue that can start now, because
its blockers are closed or it has none. Tell me its number, its title,
and what it blocks. Don't change any issue yet.
```

#### Response

```text
The repository has two open issues. Issue 2, "Import a past night with its own
rates", is blocked by issue 1. Issue 1, "Keep the rates of each night",
has no blocker and blocks issue 2. So issue 1 is the one to start. Its
"done when" list asks for `rates/2026-09-14.json` to be read for that
night, and for a night without a rates file to be rejected.
```

The commands run with the credentials you give the tool. If those are your
own login, the agent has your rights in every repository you can reach. It
can close issues and change labels there. Give the agent only the rights
it needs. Reading issues and adding comments is enough for most work. If
your tracker lets you make a token with fewer rights, use one for the
agent. In Claude Code you can also run the session in Manual mode. Claude
Code then asks you before most shell commands, and you read each `gh`
command before it runs. From version 2.1.283, a session started in a
terminal starts in auto mode by default, so you choose Manual mode on
purpose with `claude --permission-mode default`
(Choose a permission mode, Claude Code documentation).

#### Checkpoint: The agent started the issue that has to wait

The agent says: "Issue 2 is open and nothing blocks it, so I am starting
there." You know issue 2 needs issue 1 first. What do you do?

- Tell the agent in this session that the rerun waits for the rates issue, and let it start again.
- Write the order of the two issues in your own notes, so that you can correct the agent next time.
- Set a "blocked by" link from the rerun issue to the rates issue, then ask the agent again.
- Tell the agent to always take the open issue with the lowest number, since it is usually the first.

## Write a repeated finding down once

Review comments have a second problem. A reviewer writes "use `Decimal` for
money, not `float`" on one pull request, and two weeks later writes the
same comment on the next one, for a change another session wrote. The
comment is in the old pull request, where no new session reads it. The
memory page for Claude Code names two moments to write a rule down that fit
here: the agent repeats a mistake, or a code review turns up a fact about
the project that the agent was missing (How Claude remembers your project, Claude Code documentation).

A standards file is the team's list of coding rules that no tool checks.
Human reviewers and agent reviewers read the same file, and check a change
against it. A short `STANDARDS.md` for the import could start like this:

```markdown
# Standards

Rules that no check enforces. Reviewers block a change that breaks one
of these, and mark every other style point as a suggestion.

## Errors

- An error message names the file it is about, and the row when there is one.
  For example: "nights/2026-09-15/store-03.csv, row 12: 5 fields, expected 4".
```

For an agent to read the file in every session, the project instructions
point at it. A line `@STANDARDS.md` in `CLAUDE.md` imports the file, and
Claude Code loads it at launch together with `CLAUDE.md` (How Claude remembers your project, Claude Code documentation).
A reviewer gets the same file through a link in the pull request template
or the review checklist.

Some findings don't need a line, because a script can find them. The
`float` comment is one. The [hooks and CI lesson](https://schubergphilis.github.io/ai-training/coding-with-agents/ci-and-hooks/)
showed how a rule that must hold every time becomes a hook or a CI step,
and a repeated finding can take the same path. This check flags every call
to `float(` in the files it is given. It is crude on purpose. When the code
one day needs a float for something other than money, make the check
narrower then.

#### Example: The finding as a check

The course's script copies the nightly import and `check_money.py` to a
temporary directory, runs the check the way a CI step would, and prints
its exit status. Run it from `site/examples/coding-with-agents/backlog-and-standards/`
in your clone of the course repository, and compare what you see with the
output below.

```sh
python3 run_check.py
```

Output:

```text
$ python3 check_money.py importer.py
importer.py:60: money as float, use decimal.Decimal: total = sum(float(amount) * rates[currency] for _, _, currency, amount in rows)
1 finding(s)
exit status 1
```

This example isn't graded. It is a command you run, with output the
course checks on every build.

The check exits with status 1, so as a step in the CI job it fails the
pull request until the amount goes through `Decimal`. Once the check is in
CI, delete the `float` line from the standards file if you wrote one there.
The check runs on every change, and the file stays a short list of the
rules that only a reader can check. That length matters for the agent too:
the memory page advises keeping `CLAUDE.md` under 200 lines, and an
imported file loads at launch and takes context the same way
(How Claude remembers your project, Claude Code documentation).

#### Checkpoint: Where does each finding go?

Match each review finding to what the team does with it.

Statements:

- A total that counts one row twice, found for the first time
- Error messages that don't name the file, found in a second review
- An amount converted with float(), found in a second review
- A reviewer would name a function differently, and no rule covers names

Options:

- Fix it in this change only
- A line in the standards file
- A check in the CI job
- A suggestion that doesn't block

## Block on the file, suggest the rest

The file also changes what a reviewer may block on. Google's code review
guide for reviewers says that on questions of style, the team's style
guide decides, and a style point the guide doesn't cover is the reviewer's
personal preference. It suggests a prefix such as "Nit:" for a small
improvement that the author doesn't have to make (Code Review Developer Guide, Google Engineering Practices Documentation).
The guide treats design as more than taste, and a bug or a design problem
can still block a change. For the conventions of the code, the standards
file is the team's style guide. A broken rule from the file, or a failed
check, blocks the change. Every other style point is a suggestion.

That gives an agent reviewer a clear brief. Ask it to review the diff
against `STANDARDS.md` and to mark a style finding as blocking only when
it names the rule it breaks. Ask it to write every other style point as a
"Nit:", and to block on a bug as usual.
When a reviewer, human or agent, blocks on taste, the author can no longer
tell the rules in the file from the preferences, and starts to treat both
as optional.

#### Checkpoint: A blocking finding with no rule behind it

The agent reviewer writes: "Blocking: rename `read_rows` to `parse_rows`."
No rule in the file covers names, and nothing else is wrong with the
change. What do you do?

- Rename the function as the reviewer asks, because the change shouldn't merge while a finding blocks it.
- Add a naming rule to the standards file now, so that the finding has a rule behind it and can block.
- Delete the finding from the review, because a point without a rule behind it isn't useful to the author.
- Treat it as a "Nit:" that the author can take or leave, and remind the reviewer to block on style only for a rule or a check.

#### Pitfall: The token that could do everything

A team gave its agent the lead's own login for the tracker, because it was
already set up on the machine. One afternoon someone asked the agent to
"tidy up the backlog". It closed thirty issues it judged to be stale,
including four that waited on a decision from a customer, and nobody saw
it happen until the next planning meeting. The agent needed to read issues
and add comments, and the login could close and delete them. Give the
agent credentials for what the task needs, and read every command that
changes the tracker before it runs.

## Exercise

Make a project from the course files and push it to a repository you can
delete. From the root of your clone of the course repository, run:

```sh
cp -R site/examples/coding-with-agents/observing-and-debugging/nightly ~/backlog-me
cp site/examples/coding-with-agents/backlog-and-standards/issue-rates.md site/examples/coding-with-agents/backlog-and-standards/issue-rerun.md site/examples/coding-with-agents/backlog-and-standards/check_money.py ~/backlog-me/
cd ~/backlog-me
git init --initial-branch=main
git add .
git commit -m "Nightly import with two issue bodies"
```

Create an empty private repository on GitHub that you can delete
afterwards, and push the copy to it, with the address GitHub shows for the
new repository in place of `<url>`. `gh auth status` tells you whether
`gh` is logged in.

```sh
cd ~/backlog-me
git remote add origin <url>
git push -u origin main
```

Create the two issues with the two `gh issue create` commands from this
lesson, the second one blocked by the first. Then start Claude Code inside
`~/backlog-me` in Manual mode with `claude --permission-mode default`, and
give it the brief from the transcript. Read each `gh` command before you
approve it. The brief asks for a report only, and `gh` runs with your own
login, which reaches every repository you can reach. So approve only
`gh issue list` and `gh issue view`, and refuse every other `gh` command
and any `git push`.

Then turn one finding into a rule. Take a finding that came up in two
reviews in your own team, or use the `float` finding from this lesson. If
no script can find it, write it as a line in a `STANDARDS.md` and add
`@STANDARDS.md` to a `CLAUDE.md`. If a script can find it, make it a check,
such as `python3 check_money.py importer.py` as a step in a CI job like the
one in the hooks and CI lesson. Commit the result on a branch and open a
pull request for it. Twenty minutes is enough for the issues and a line in
the standards file. The CI step takes longer, and it is extra.

A good result has two issues with a "blocked by" link between them, an
agent that named the rates issue as the one to start without anyone
pasting the spec, and one finding that is now a line in the standards
file or a check that fails on the mistake. Delete the repository when you
are done. Then answer one question: which review comment have you written
more than once this month, and where would it go?

Stretch: Then brief the agent to review its own next change against STANDARDS.md, to mark a style finding as blocking only when it names a line of the file, to write every other style point as a "Nit:", and to block on a bug as usual. Check that it does.

## Recap

1. An agent-reachable backlog keeps specs and tickets in the team's tracker, where people and agents both read them. A spec in a private note or a chat reaches nobody else.
2. Record the order of the work with the tracker's own links. GitHub marks an issue that is blocked by another, and `gh issue view` shows the links (Creating issue dependencies, GitHub documentation).
3. The agent reads the tracker through a command-line tool, which costs little context (Best practices for Claude Code, Claude Code documentation). Give it the rights the task needs, and read each command that changes the tracker before it runs.
4. When a review finding comes back, write it in the standards file that human and agent reviewers both read, and import that file into the project instructions (How Claude remembers your project, Claude Code documentation). When a script can find the mistake, make it a check and delete the line.
5. Reviewers block on a rule in the file, a failed check or a real defect, and mark other style points as suggestions (Code Review Developer Guide, Google Engineering Practices Documentation).

#### Habit

The next time you write a review comment you have written before, stop and add it to the standards file, or to a check, before you send the review.

## References

- Creating issue dependencies, GitHub documentation, https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-issue-dependencies
- Best practices for Claude Code, Claude Code documentation, https://code.claude.com/docs/en/best-practices
- Choose a permission mode, Claude Code documentation, https://code.claude.com/docs/en/permission-modes
- How Claude remembers your project, Claude Code documentation, https://code.claude.com/docs/en/memory
- Code Review Developer Guide, Google Engineering Practices Documentation, https://google.github.io/eng-practices/review/
