215 lines
12 KiB
Markdown
215 lines
12 KiB
Markdown
# Plan: retire `oibot-agent` from the Tobserver change workflow
|
|
|
|
## Status
|
|
|
|
Implementation is in progress.
|
|
|
|
- The standalone catalog skill is implemented on `agent/tobserver-personal-agit` at commit `ce0f775` and published as [oibot/agent-skills PR #1](https://codeberg.org/oibot/agent-skills/pulls/1).
|
|
- AGit creation and a second linear push were verified against the same pull request without a write API token.
|
|
- Dotfiles are prepared to pin that catalog revision, load `create-skill` and `tobserver-change` in Pi, and package the bundled helper as `tobserver-agent`; Nix evaluation and the Home Manager build pass.
|
|
- The new configuration has not been activated, the Agent Skills PR has not been merged, and no bot credential has been revoked or deleted.
|
|
- Cutover is blocked until the user confirms Tobserver `main` protection in Codeberg and resolves or deliberately migrates the active legacy workspace at `/private/var/folders/5p/sj0yx8w92b51dzngrxn9gqz00000gn/T/tobserver-agent.d9wG9L` (`agent/add-bitcoin-pulse-module-wiring-20260723-130500-866d04`).
|
|
|
|
## Goal
|
|
|
|
Use the personal Codeberg account `oibot` for Tobserver change branches while preserving a human-only merge boundary:
|
|
|
|
- `main` accepts changes only through pull requests;
|
|
- direct, force, and deletion pushes to `main` are denied, including for `oibot`;
|
|
- the agent can create and update pull requests without a write-capable Codeberg API token;
|
|
- a human merges through the Codeberg web UI;
|
|
- the agent never accesses or deploys to the live Tobserver machine.
|
|
|
|
The trade-off is accepted: Codeberg will attribute both agent-created pull requests and human merges to `oibot`, so there is no account-level distinction or independently enforceable approval by a second user.
|
|
|
|
## Repository and distribution decision
|
|
|
|
The personal-only workflow will be implemented as a self-contained skill in the separate Agent Skills catalog rather than maintained as local skill and script copies in dotfiles.
|
|
|
|
- The canonical skill directory will be `~/Code/agent-skills/tobserver-change/`.
|
|
- The directory will contain `SKILL.md`, the `tobserver-agent` helper under `scripts/`, routing and execution evals, focused helper tests, and every reference or asset required to install, operate, validate, and recover the workflow.
|
|
- The helper script will have one canonical source in the skill directory. Dotfiles may package or wrap that bundled script to expose `tobserver-agent` on `PATH`, but must not retain a second editable copy.
|
|
- The completed Agent Skills change will be pushed as an `oibot` branch and reviewed through a pull request in `oibot/agent-skills`; do not push directly to protected `main`.
|
|
- Dotfiles will add the Agent Skills repository as a pinned, non-flake input and configure Pi to load both `create-skill` and `tobserver-change` from that input.
|
|
- The local `config/pi/skills/tobserver-change` copy and the upstream `anthropic-skills`/`skill-creator` input will be removed after Pi successfully loads the catalog's `tobserver-change` and `create-skill` skills.
|
|
- `flake.lock` will pin the reviewed Agent Skills revision so a future catalog push cannot silently change Pi's active instructions or helper.
|
|
- Existing local helper and skill files remain available during migration and are removed only after the catalog-backed installation passes local and end-to-end validation.
|
|
|
|
The intended order is: build and evaluate the standalone catalog skill, publish and review it, pin it in dotfiles, verify Pi and the packaged helper, complete the personal-only AGit cutover, and only then revoke or remove `oibot-agent` credentials.
|
|
|
|
## Security invariants
|
|
|
|
1. Protect `main` before changing credentials or helper behavior.
|
|
2. Do not place `oibot` on a direct-push or branch-protection bypass list.
|
|
3. Do not expose an `oibot` API token capable of merging pull requests or changing repository settings to the helper or agent.
|
|
4. Keep the existing workspace, branch-prefix, validation, secret, no-force-push, no-merge, and no-deployment checks.
|
|
5. Keep the current bot credentials available for rollback until the personal-only workflow completes an end-to-end test.
|
|
6. Do not delete keys, tokens, open pull requests, or active workspaces automatically.
|
|
|
|
## Preconditions and decisions
|
|
|
|
- [x] Confirm that independent Codeberg attribution and approval are no longer requirements.
|
|
- [x] Confirm that human merging will happen only in the Codeberg web UI.
|
|
- [x] Inspect existing open `oibot-agent` pull requests; the public API returned none.
|
|
- [x] Check `tobserver-agent status` and preserve the active legacy workspace recorded above.
|
|
- [x] Establish an isolated Agent Skills branch and preserve existing dotfiles commits and owner work.
|
|
|
|
## Phase 1: enforce the server-side merge boundary
|
|
|
|
In `oibot/Tobserver` repository settings, configure an exact protection rule for `main`:
|
|
|
|
- [ ] deny direct pushes for everyone, including repository owners;
|
|
- [ ] deny force pushes;
|
|
- [ ] deny branch deletion;
|
|
- [ ] require changes to arrive through pull requests;
|
|
- [ ] retain applicable status-check and conversation-resolution requirements;
|
|
- [ ] ensure there is no `oibot` push or bypass exception.
|
|
|
|
Verify the saved rule in the Codeberg UI. Do not probe Tobserver by attempting a push that could succeed if the rule is wrong. If a push-level test is desired, reproduce the rule in a disposable repository first.
|
|
|
|
**Gate:** do not continue until the UI confirms that `oibot` cannot directly update `main`.
|
|
|
|
## Phase 2: prove a tokenless pull-request path
|
|
|
|
Use Forgejo AGit over SSH so pull requests can be created without an API write token:
|
|
|
|
```sh
|
|
git push origin HEAD:refs/for/main/<topic> \
|
|
-o title="<title>" \
|
|
-o description="<description>"
|
|
```
|
|
|
|
Before refactoring the helper:
|
|
|
|
- [ ] confirm `oibot` authenticates through `git@codeberg.org` with the personal SSH key;
|
|
- [ ] confirm the public Codeberg API exposes the pull-request metadata needed by `revise` without authentication;
|
|
- [ ] determine the exact AGit representation of the topic, head ref, and pull-request URL;
|
|
- [ ] determine a robust multiline Markdown description encoding supported by Codeberg;
|
|
- [ ] create a clearly labeled AGit test pull request from an empty commit so it has no tree changes;
|
|
- [ ] push a second linear empty commit with the same topic and verify that it updates the same pull request without force-pushing;
|
|
- [ ] close the test pull request manually in Codeberg.
|
|
|
|
Do not merge the test pull request.
|
|
|
|
**Gate:** if AGit creation, URL discovery, or linear revision cannot be made reliable without a write-capable personal API token, stop and reconsider the account-removal design.
|
|
|
|
## Phase 3: refactor `tobserver-agent`
|
|
|
|
Target file: `~/Code/agent-skills/tobserver-change/scripts/tobserver-agent`
|
|
|
|
### Identity and credentials
|
|
|
|
- [ ] change the push URL from `git@codeberg-tobserver-agent:oibot/Tobserver.git` to the normal personal Codeberg SSH endpoint;
|
|
- [ ] retain an informational agent-specific commit author name;
|
|
- [ ] replace the bot noreply email with an agreed `oibot`-compatible address;
|
|
- [ ] remove bot Keychain account/service constants;
|
|
- [ ] remove write-token loading and temporary authorization-header handling;
|
|
- [ ] use unauthenticated HTTPS only for public read operations.
|
|
|
|
### Pull-request creation
|
|
|
|
- [ ] replace API `POST /pulls` creation with one AGit push;
|
|
- [ ] generate a unique, shell-safe AGit topic tied to the existing `agent/*` branch/workspace identity;
|
|
- [ ] pass the validated title and Markdown body without unsafe quoting, truncation, or accidental shell interpretation;
|
|
- [ ] capture and validate the returned pull-request URL under `https://codeberg.org/oibot/Tobserver/pulls/`;
|
|
- [ ] preserve the workspace when AGit submission or URL discovery fails.
|
|
|
|
### Pull-request revision
|
|
|
|
- [ ] replace the `oibot-agent` author assertion with checks appropriate to the new model: canonical repository, open state, `main` base, expected AGit topic/head, and helper-compatible history;
|
|
- [ ] fetch revision metadata without a write-capable token;
|
|
- [ ] push additional commits using the same AGit topic;
|
|
- [ ] preserve normal fast-forward/linear updates and continue to forbid force-push;
|
|
- [ ] verify that updating a pull request cannot create a duplicate PR silently.
|
|
|
|
### Existing safety checks
|
|
|
|
Retain and regression-test:
|
|
|
|
- [ ] helper-created temporary workspaces only;
|
|
- [ ] exact canonical fetch and push endpoints;
|
|
- [ ] `agent/*` local branch naming;
|
|
- [ ] refusal to work on `main`;
|
|
- [ ] no SOPS payload changes or plaintext secret access;
|
|
- [ ] Nix formatting, flake evaluation, derivation evaluation, Git whitespace, and Gitleaks checks;
|
|
- [ ] no merge, deployment, live-server access, force-push, remote branch deletion, or automatic failed-workspace cleanup.
|
|
|
|
## Phase 4: update the Tobserver skill and evaluations
|
|
|
|
Target files:
|
|
|
|
- `~/Code/agent-skills/tobserver-change/SKILL.md`
|
|
- `~/Code/agent-skills/tobserver-change/evals/evals.json`
|
|
|
|
Changes:
|
|
|
|
- [ ] remove the dedicated-bot compatibility requirement;
|
|
- [ ] replace the bot SSH alias with the normal Codeberg SSH endpoint;
|
|
- [ ] describe protected `main` plus human web merge as the approval boundary;
|
|
- [ ] state that the helper must not use a write-capable Codeberg API token;
|
|
- [ ] replace bot-owned PR revision checks with canonical AGit topic/head checks;
|
|
- [ ] retain the `agent/*`, no-force-push, no-merge, no-deploy, and recoverability constraints;
|
|
- [ ] update eval expectations that currently require `oibot-agent` ownership;
|
|
- [ ] add or revise an eval covering rejection of direct `main` pushes and API-based merge attempts.
|
|
|
|
## Phase 5: validate locally
|
|
|
|
- [x] run `bash -n tobserver-change/scripts/tobserver-agent` from the Agent Skills repository;
|
|
- [x] run focused helper tests for branch/topic restrictions, AGit metadata, push-option encoding, URL validation, and revision matching;
|
|
- [ ] test failure paths with mocked Git/HTTP commands so failed submission preserves the workspace;
|
|
- [ ] run the repository's Nix checks without deploying or building a Tobserver system closure;
|
|
- [x] inspect the Agent Skills diff for credentials, token remnants, unrelated edits, and stale bot assumptions;
|
|
- [ ] rerun the `tobserver-change` routing and representative workflow evaluations.
|
|
|
|
## Phase 6: end-to-end cutover test
|
|
|
|
With bot credentials still intact for rollback:
|
|
|
|
1. [ ] create a fresh helper workspace;
|
|
2. [ ] make an empty or harmless non-system test commit;
|
|
3. [ ] run all helper checks;
|
|
4. [ ] submit through AGit as `oibot`;
|
|
5. [ ] verify that one PR targets `main` and no direct `main` update occurred;
|
|
6. [ ] revise the same PR with one additional linear commit;
|
|
7. [ ] verify that no duplicate PR or force-push occurred;
|
|
8. [ ] close the test PR manually without merging;
|
|
9. [ ] verify failed and interrupted workspaces remain resumable.
|
|
|
|
**Gate:** retire the bot only after the complete create-and-revise workflow passes.
|
|
|
|
## Phase 7: retire bot credentials
|
|
|
|
Perform these as explicit human-approved cleanup steps:
|
|
|
|
- [ ] remove `codeberg-tobserver-agent` from `~/.ssh/config`;
|
|
- [ ] unload `~/.ssh/oibot-agent` from `ssh-agent`;
|
|
- [ ] revoke the bot API token in Codeberg;
|
|
- [ ] remove the bot token from macOS Keychain;
|
|
- [ ] remove the bot SSH key from Codeberg;
|
|
- [ ] remove `oibot-agent` repository access;
|
|
- [ ] archive or delete the bot account only after confirming it owns no required issues, PRs, repositories, or audit artifacts;
|
|
- [ ] delete local bot key files only with separate explicit confirmation and after any desired backup.
|
|
|
|
Do not rewrite historical commits or pull requests merely to remove the bot name.
|
|
|
|
## Rollback
|
|
|
|
Until Phase 7:
|
|
|
|
1. restore the previous helper push URL and bot token path;
|
|
2. restore the skill's bot-identity requirements;
|
|
3. use the preserved bot SSH alias and token;
|
|
4. resume preserved helper workspaces rather than recreating changes;
|
|
5. keep `main` protection in place throughout rollback.
|
|
|
|
After bot credentials are revoked, rollback requires issuing a new constrained credential or restoring the bot account deliberately; do not weaken `main` protection as a shortcut.
|
|
|
|
## Completion criteria
|
|
|
|
- `oibot` cannot directly, forcibly, or destructively update `main`.
|
|
- The helper creates and linearly updates a single PR through SSH/AGit.
|
|
- The helper and agent have no write-capable Codeberg API token.
|
|
- Only a human web action merges a PR.
|
|
- All existing local checks and secret boundaries still pass.
|
|
- No live Tobserver access or deployment occurred.
|
|
- Bot credentials and access are removed only after successful cutover and explicit approval.
|