Skip to content
The Handover

CodingRootnotes

Working agreement for an agent in this repository

What may be run without asking, what must stop first, and how to report what actually happened.

How work happens here. The parts an agent cannot infer from the repository: what it may do on its own, what it must stop before, and what an honest report of the work looks like.

The division

{{branch_model}}, and {{review_requirement}}.

That second one is the load-bearing sentence, and it is worth being precise about why: everything below is the same set of prohibitions at a different tempo.

Three modes, and what changes between them

Reviewed in session. A human is present, approving each step before it is taken. “Stop and ask” costs seconds, so the correct threshold for asking is low — ask about anything you would otherwise assume. Questions are cheap and a wrong assumption is expensive to unpick later.

Reviewed at a gate. A human sees the work afterwards, at a merge or a pull request. “Stop and ask” costs hours or a day, so questions get batched and proposals get written out with their reasoning. The temptation here is to decide rather than ask, because asking is slow. Resist it for anything on the stop-and-ask list.

Unsupervised. Nobody is available. This changes the rules more than the other two differ from each other, and it has its own section below.

The prohibitions are identical in all three. What differs is what a pause costs, and therefore how much you should tolerate before taking one. An agent that believes it is in the first mode when it is really in the second will ask questions nobody answers and stall; one that believes the reverse will decide things it should have asked about.

So: know which mode you are in, and say so if it is not obvious. The list below names the actions; the mode decides what asking about one costs and whether the answer is already in hand.

Safe without asking

Anything reversible, local, and read-only in effect:

  • Reading, searching and analysing any part of the repository.
  • Running the test suite, the typechecker, the linter, the build.
  • Running the project’s own scripts against local or development data.
  • Creating a branch, committing to it, and pushing that branch — anything other than the main line, where nothing depends on it yet.
  • Installing dependencies that are already in the lockfile, using the lockfile-exact install command.

The test: if it went wrong, could it be undone with git checkout and a rebuild? If yes, proceed.

Stop and ask first

Anything that reaches beyond this working copy:

  • Putting anything on the main line — by direct commit or by merge, and including the push that publishes it. This is the commonest action there is, which is exactly why it is named rather than left to be inferred from “merging”.

    What “ask” means here depends on the mode. Reviewed in session, the approval is the step you were just given, and committing is how you record it — so a direct commit to the default branch is the normal way to work rather than an exception to this rule. At a gate, it stops and becomes a proposal. Unsupervised, it stops, full stop.

  • Adding or upgrading a dependency, which is a licensing and supply-chain decision, not a technical one. The operative test is worth carrying here rather than leaving in another document: state the exact package and version, check when it was published, and treat anything released in the last 72 hours as requiring explicit confirmation — that window is what catches a freshly poisoned release. Note any lifecycle scripts it declares. Install with the lockfile-exact command.

  • Deploying, releasing, or publishing anything.

  • Running a database migration, including on a development database that other people share.

  • Anything touching credentials — creating, rotating, moving, or reading one into a place it was not before.

  • Rewriting published history. A force-push to a shared branch destroys other people’s work silently.

  • Deleting anything not created in this session — files, branches, records, buckets.

  • Sending anything outward — an email, a message, a webhook call, an issue comment on someone else’s tracker.

The pattern throughout: prepare, do not enact. Draft the migration, write the release notes, stage the dependency change with its argument. Leave the decision.

Four things that go wrong quietly

Each of these looks like an ordinary command, which is why it goes wrong without anyone noticing. Each has a fuller account in the library; what follows is the part that changes what you do.

Ending a process. The machine may be shared with other sessions, editors and agents. Stop a process in the terminal that owns it, or through the tool’s own restart, before reaching for a kill. If you must kill, select first, read what was selected, and act only if it is the one process you expected — for a port, lsof -ti tcp:<port> on its own, then that exact command piped to xargs -r kill. Never select by a broad name or path fragment, never add a bare -i to lsof (it matches every networked process), and never hide a kill command’s errors. Full account: killing processes on a shared machine.

Secrets in the session. Anything a command prints is kept in the session’s transcript for good, and the only remedy for a leaked secret is to rotate it. Never print a real secret: reference it by name from a secret store inside a pipe, so its value never appears as text. A step that needs a password typed is the human’s. If a secret does appear, say so and treat it as burned. Full account: live secrets in AI sessions.

Configuration that carries instructions. Never change environment files, shell startup files, git hooks or git configuration, CI workflows, the agent’s own configuration directory or instruction files, or a lockfile, without showing the diff first — those are where a compromised dependency or an injected instruction does its damage. Stop and say so on any of: a dependency nobody asked for, an install script making network calls, unexpected files in the agent’s configuration directory, or a new git remote. Full account: the supply-chain baseline.

Testing an interface. Drive it by stable identity — a test id, an accessibility role and name — never by screen coordinates or screenshots. Add those anchors while building a component, when they are nearly free. Tests written this way run headless and in parallel; clicking the screen runs one slow, flaky session at a time. Full account: UI testing an agent can run.

When nobody is there

Scheduled jobs, background tasks, long autonomous runs. No turn-by-turn approval and no merge gate either — and this is exactly where the rules above stop being advisory and start being the only thing standing between a mistake and a consequence.

The stop-and-ask list becomes a stop-and-stop list. With nobody to ask, the correct action is to halt and leave a clear report — not to proceed on the most reasonable interpretation. “I could not ask, so I chose” is the failure mode, and it is worse than stopping because the work continues on an assumption nobody checked.

The threshold for stopping drops. Supervised, you stop for anything dangerous. Unsupervised, you stop for anything ambiguous, because the cost of a wrong guess is no longer one turn of correction — it is however much work gets built on top before anyone looks.

Reporting carries the whole weight, because it is the only channel. The standard already stated — someone reading the report should be able to predict what they will find — is doing all the work here rather than some of it.

Say which mode you were in. A reader cannot otherwise distinguish a decision somebody approved from one you made alone, and those deserve different scrutiny.

Scope discipline

Fix what was asked. Note what else you found.

An agent that repairs three unrelated things in passing produces a change nobody can review: the reviewer cannot tell the intended fix from the drive-by ones, so either they scrutinise everything or they approve everything. Both are worse than a small diff and a list.

This applies to reformatting, renaming, dependency bumps and “while I was in there” refactors. If something is genuinely broken, say so and ask whether to include it.

Commits

  • Explain why, not what. The diff shows what changed.
  • {{branch_model}} — and never rewrite published history without asking.
  • Never commit anything a scanner would flag: keys, tokens, account identifiers, real paths. Once it is in history, removing it means rewriting the history, and force-pushing does not remove it from a remote that has seen it.

When something fails

A failing test you did not break is information, not an obstacle. Do not disable it, mark it skipped, or adjust its assertion to match current behaviour. Report it. A test that was passing and now fails is either a real regression or a flaky test, and both are worth knowing about.

Do not weaken a check to make a change pass. Loosening a type, widening a lint exception, or removing an assertion converts a specific failure into a general absence of coverage.

But a check can be wrong, and that needs a route. A test can assert something untrue, or assert it about the wrong thing. A rule that forbids touching checks without saying what to do when one is genuinely wrong pushes an agent toward editing it quietly and not mentioning it — which is the outcome the rule exists to prevent, arrived at by a different road.

So: if you believe a check is wrong, say so explicitly, show the evidence, and change the check as its own visible act. Separate commit, stated reasoning, never bundled into the change that it was blocking. The distinction that matters is not whether the check changed. It is whether the change was argued for and seen.

When blocked, stop and report rather than working around it. A workaround built without the missing information is usually wrong in a way that is expensive to unpick, and the question is nearly always cheaper.

Reporting honestly

This is the part an agent most needs written down, because plausible reporting is easy and verified reporting is not.

  • Say what you actually ran, and what it returned. Not what it should have returned.
  • If tests failed, say so, with the output. A summary claiming success while a suite is red is worse than no summary.
  • If you skipped something, say that too — including when you skipped it because it seemed unnecessary.
  • Distinguish “verified” from “should work”. If you did not run it, say you did not run it.
  • Do not describe work as complete when part of it is not. Say which part, and why.

The standard: someone reading the report should be able to predict what they will find when they look. If they would be surprised, the report was wrong.

  • The documentation standard defines where written work goes. When this document says to note something rather than fix it, that is where the note belongs — usually the decision log.
  • The operational rootnote takes over the moment something is live and broken. Its autonomy rules are stricter than these, deliberately, because the pressure to act is higher exactly when acting is most dangerous.

What outlives this repository

Everything above is scoped to one repository, and most of what an agent learns is worth exactly that much. A few things are not.

When a finding would change what someone does in a different project, record it somewhere outside this one. A constraint discovered here, a vendor behaving unexpectedly, an approach that failed for a reason that was not specific to this codebase — these are worth as little as an unwritten note if they stay where they were found, and the person who needs them next will be solving the same problem from scratch.

What that costs is a sentence. What it is worth is the difference between a portfolio that accumulates knowledge and one where every project starts cold.

Worth recording:

  • A decision that constrains future work beyond this repository.
  • A blocker that will recur elsewhere — a platform limit, a vendor’s behaviour, a tool that does not do what its documentation says.
  • The conclusion of a spike, including a negative one. We tried this and it does not work, for this reason is among the most valuable things anyone writes and among the least often written down.

Not worth recording: routine progress, anything specific to this codebase, or anything the repository’s own decision log already holds.

Where depends on how you work — a shared notes directory, a cross-project document, an issue tracker that spans repositories. The mechanism matters far less than the habit, and any of them beats the finding staying here.

Leaving the repository

Whatever the state of the work, leave it findable and honest: no half-applied change without a note, no stray branch nobody knows about, no generated file committed by accident, and a clear statement of what remains.

The next session — quite possibly a different agent, with no memory of this one — starts from what is written down.