diff --git a/04-ISSUES/353-an-agent-cannot-put-a-commit-on-the-forge/00-report.md b/04-ISSUES/353-an-agent-cannot-put-a-commit-on-the-forge/00-report.md new file mode 100644 index 00000000..f0ecaae1 --- /dev/null +++ b/04-ISSUES/353-an-agent-cannot-put-a-commit-on-the-forge/00-report.md @@ -0,0 +1,67 @@ +--- +status: open +opened: 2026-10-09 +located-in: [] +fixed-by: +amended-design: +--- + +# 353. An agent cannot put a commit on the forge + +## Symptom + +On 2026-10-09, in an agent session on the operator's laptop, local times: + +- An agent finished a change to this repository's connectivity design on a branch, committed it in a + worktree, and ran `merge-check.sh`; all four checks passed. +- `git push` was not possible: this repository's clone on the laptop has its push URL set to the literal + `DISABLED`. The laptop's clones of the mesh's code repositories push normally. Who set it, when, and + why is not recorded anywhere this session could find. +- The forge's tools have no verb that pushes a branch or makes a commit. `gitea_api` refused + `POST /repos/{owner}/{repo}/diffpatch`, the forge's endpoint that applies a patch to a branch: *not a + write gitea_api makes* ([ADR 0266](../../02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md)). +- The one file write `gitea_api` allows is the contents endpoint, which takes the **whole file**, + base64-encoded. The changed design document is about 90 KB, so the call would carry about 121 KB of + base64 that the agent must reproduce character for character. That is not a workable path. + +The change waits for the operator to push it by hand. This report waits for the same push. + +## Why it is an issue + +- **The mesh's own rule for a change cannot be followed by an agent.** Every change goes through a branch, + a pull request and a person's approval. An agent off the control node can make the branch locally and + open the pull request through `gitea_create_pull_request`, but it cannot put the commits between the two + on the forge. +- **Where no tool covers a need, none is worked around** ([ADR 0245](../../02-DECISIONS/0245-a-verb-says-what-it-replaces-and-the-agent-is-guarded-from-working-round-the-mesh.md)). + The only ways round are pushing to an explicit URL past the disabled one, or retyping a file as base64. + The first undoes a setting someone made on purpose. The second risks a commit that silently differs + from what was checked. +- **The control node already has an answer the laptop does not.** On the control node the agent account + holds a forge key of its own, so its pushes are its own (ADR 0266). An agent on any other machine has + no equivalent. + +## Other gaps in the forge's tools + +Found by listing the forge module's 37 tools on 2026-10-09. Only the first one blocks work. The others +can be done through `gitea_api`, which costs a raw call and a large answer each time. + +| Gap | Today | Checked | +|---|---|---| +| **No push, commit or patch on a branch** | blocked, as above | yes | +| **No commit history or compare** | `GET …/commits` through `gitea_api`: about 100 lines of JSON for one commit, its author and committer printed in full each time. `gitea_contains` answers only whether one commit contains another. | yes | +| **No reading a pull request's reviews or line comments** | `gitea_list_comments` returns the conversation only. Reviews and comments on lines need `GET …/pulls/{n}/reviews` through `gitea_api`. An agent asked to address review feedback does not see it unless it knows to ask there. No *approve* tool is right, since approval is a person's. | yes | +| **No creating a branch** | `POST …/branches` through `gitea_api` | no | +| **No editing an issue** — title, body, labels | only close and reopen exist | no | +| **No listing a directory** | `gitea_get_file` reads one file | no | +| **No code search across repositories** | none | no | + +*Checked* says whether this session called the raw endpoint and saw it answer. The rows marked *no* are +read from the tool list and the forge's API, not tried. + +## Open + +- Who disabled the push URL on the laptop's clone of this repository, and whether it was meant to keep + agents from pushing here or was a step in something else. +- Whether an agent off the control node should push with a forge key of its own, as on the control node, + or whether the forge module should take a commit as a patch and write it under the agent's account. + Either needs a decision record.