dotfiles/docs/plans/retire-oibot-agent.md
2026-07-24 20:30:06 +07:00

12 KiB

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.
  • 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

  • Confirm that independent Codeberg attribution and approval are no longer requirements.
  • Confirm that human merging will happen only in the Codeberg web UI.
  • Inspect existing open oibot-agent pull requests; the public API returned none.
  • Check tobserver-agent status and preserve the active legacy workspace recorded above.
  • 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:

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

  • run bash -n tobserver-change/scripts/tobserver-agent from the Agent Skills repository;
  • 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;
  • 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.