ysoseri.us

实习日志 / English / Credentials are not authorisation: governing the repository of a five-person team where everyone uses an Agent

Credentials are not authorisation: governing the repository of a five-person team where everyone uses an Agent

中文 | English

From the first week of this project, everyone on the team used AI coding tools to write code, open PRs and answer reviews. I maintained the repository, and at first all I wanted was for five people to work in parallel safely. By the end of August I noticed that what I was doing had changed. Agents made writing code and opening PRs cheap, and they made overreach, misunderstanding and "looks finished" just as cheap. Repository governance slowly turned from a set of collaboration notes into the control plane of a "people plus Agents" system.

This piece follows that governance in time order, through the real failures that forced each step, and ends with what went into the skill it became. That skill is now public.

Build the road before anyone runs

The first things I set up were the SPEC, sprint plans, the directory structure, CI, protection on the main branch and a Kanban board. The aim was simple: without an authoritative document and clear delivery boundaries, every person and their Agent would build a "reasonable-looking" project out of their own partial context. So the first stage was about building the road: a source of truth, task status and dependencies, so that a teammate did not need the whole background and could move forward by picking up a card with clear acceptance criteria. Governance first solved how people avoid stepping on each other.

A written process does not mean the Agent follows it

Problems soon arrived in a row. Agents switched PRs between Draft and Ready on their own; PRs were opened without a linked issue; reviews and merges went ahead after CI had failed; code changed without the matching docs, cards and dependency status; Agents force-pushed, reordered stacked PRs, or closed issues and PRs without authorisation; and the Agent doing a review would dress its own misunderstanding up as a formal, confident change request.

What I said at the time was: "If I don't set this up, teammates will keep writing whatever they like."

The clearest case was a PR approved and merged while the backend checks were failing. Main broke and the next PR had to fix it. That showed that "everyone knows the process" and "the process can stop mistakes" are two completely different things. A reminder that works on people may not work on an Agent: if the rule is not in the current prompt, or the operator gave too broad an authorisation, the Agent will put the goal in front of it first and ignore the order of the repository as a whole.

Let the system say "no" for me

So governance became three layers: a rules entry point every Agent must read; local pre-push checks; and on GitHub, PR rule checks, required checks and branch protection.

Once the rules went live, teammates started asking why their PRs would not push. I admitted I felt a bit of schadenfreude. It was a delayed confirmation: problems that only I could see, and had to explain again and again, were now refused by the system on my behalf. From then on I stopped relying mainly on reminders, templates and verbal agreements, and relied on enforceable state conditions instead: a PR missing an issue, acceptance evidence or check results cannot count as ready to merge.

A complete format can still be fake progress

Gates could control PRs entering formal review, but not hollow issues, placeholder Drafts or work items with no real acceptance meaning. So the checks moved earlier, to the moment an issue or PR is created. They do not forbid anyone from opening one, but they require at least: why it is needed, what problem it actually solves, what counts as done, what the dependencies and risks are, and whether this submission is really worth reviewing.

The target of governance widened from "bad code" to "low-information output dressed up as progress". Agents are very good at producing text that looks complete, so governance cannot just check whether fields are filled. It has to check whether those fields contain anything that constrains implementation and review. A beautifully formatted PR with no problem definition, acceptance boundary or real evidence is no more mature than a PR that is obviously unfinished.

A check with nowhere to run is just a drawing

Then GitHub Actions was disabled by the organisation, and CircleCI had not been approved yet (I wrote about that night in the earlier CI diary). A required check without a real execution environment is only a design on paper. So I spent the night wiring the whole chain up with CircleCI, a Cloudflare Worker, a queue, webhooks and a Kanban status checker, got it running first, and then corrected it through real failures.

I recorded the cost of this stage too. The evidence behind those infrastructure PRs at merge time was weaker than for the later governance PRs; on one of them the rule check on the page was still red when it merged. The priority then was to fill the vacuum where rules could not be enforced at all, so I accepted more governance debt than I did later.

The gates can be wrong too

Next came another kind of problem: Windows CRLF line endings caused false failures; the same checks ran both locally and remotely; differences between CI providers produced false alarms. My view changed a second time here. More gates are not always better. A gate that is not real, cannot be diagnosed or has an unclear source is producing garbage of its own.

The PRs from that stretch removed false failures caused by line endings; stopped local and remote runs from duplicating each other while keeping the local checks needed when remote was unavailable; set up three quality profiles, none, github and circleci; and created a PR rule status independent of the CI provider. Governance began to answer for its own engineering quality: evidence must be real, failures must be explainable, environment differences must not cause pointless rework, an unexecuted quality source must never pass as "verified", and repository rules must not be tied forever to one temporary CI provider.

The same applies to the reviewing Agent. Change requests and gates are not right by default. They are diagnoses to be verified first, and the author does not have to obey them unconditionally.

When CircleCI finally worked, I did not assume which checks it would produce by design. I first looked at what it actually produced on a real PR, then changed branch protection to match, and finally checked the pipeline on main after the merge. Observe what the system really produces, then promote it to authority in the repository: that order became fixed from then on.

The real problem is how people control Agents

At the end of August I ran a careful review of all five people's submissions. The conclusion: shared templates, the Kanban board, quality gates and the Agents' writing ability had made every PR look the same. A tidy Summary, a fully ticked checklist and a polished reply to review prove nothing about whether the operator really understands what they own, what is out of scope, where they overlap with others, the current branch topology, the failure paths and the permission boundaries, nor whether they can judge if a reviewer's comment is reasonable.

What I said then was that the most dangerous thing is "reaching too far into other people's work". The most dangerous ability of an Agent goes beyond writing a bad piece of code: under vague authorisation it changes the scope of someone else's work, rewrites history, manages other people's PRs, even makes merge decisions for people. Account permission isolation cannot fix this. All five of us worked through gh, and the repository cannot reliably tell whether an action was taken by the person or by an Agent calling the API under the same identity.

So the goal of governance became a more realistic control plane: read the authoritative context before acting; declare ownership, non-goals and overlaps in every PR; review the exact current commit; back change requests with objective evidence; do not pretend the rules can identify who is really behind an account; and require current, explicit and specific authorisation for any management action on branches, PRs, issues, Kanban or merge state.

I also started treating the document structure as prompt infrastructure for Agents. Old sprint reports, target designs, current contracts and research notes sat together in one docs/ layer. People could still judge which was more authoritative from dates and experience; an Agent would very likely treat them all as equally valid facts. Since we could not stop Agents from using gh, we had to make sure that once they entered the repository, the first things they saw were correct, current and clearly layered facts.

The governor has to be governed too

Infrastructure work sometimes really does require temporarily lowering the approval requirement, changing branch protection or loosening a ruleset. That creates a loop: I set the rules, I open the exception, and the PR that changes the rules is merged by the same account. What shows that the exception is still under the rules?

The later "governance window" was the answer. Every exception records the operator, the PR it applies to, how long it is valid, the allowed actions and the evidence of restoration. It does not remove the maintainer's privilege. It turns a hidden privilege into a bounded, time-limited, auditable exception.

I was not consistent here either. Different governance PRs temporarily changed different controls; one PR passed all its checks but did not fully fill in the governance exception fields I had just created. "Merged by some account" on GitHub only proves that the account performed the merge, not whether I clicked it or an Agent called the API. The author of a system also needs time to get used to the system they built.

Into a skill

On 30 August I turned all of this into a repository governance skill: a Chinese master copy first, merging the discussion draft with the repository's existing governance documents and removing duplicates, then translated into English, made into a skill, and added to the repository with a governance PR. From then on it was the only current source of governance rules. I later pulled it out into its own public repository, so it can be used in other projects:

https://github.com/Ysoseri1224/repo-governance-for-novice

What I understood in the end

Back to where this started. At first I worried that people would write bad code. Later I worried that Agents, working under the wrong permissions, ownership and context, would very efficiently finish something that should never have been done. What this governance can do is make sure every operator sees the same authoritative information before acting, declares scope and boundaries while acting, provides reviewable evidence in review, and leaves a clear, time-limited and recoverable record whenever an exception happens.

Agents made execution cheap, but judgement, authorisation and responsibility did not get any cheaper. What repository governance has to constrain is the relationship between goals, context, ownership, evidence and state changes. The Agent is just one executor inside those relationships.