Forge native integration #317
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Enable agents to receive work from and report back to Gitea natively, without manual prompting.
Flow
Components
Open questions
@didericis-claude
Freeze should look call the
commitcommand from the cliGood question: for the best of both worlds (convenience from a single wrapper and separation of dependencies/codebases), think it probably makes sense to have a
bot-bottle orchestratecommand in the bot-bottle cli that calls out to a separate orchestrator (probably just calledbot-bottle-orchestrator) that will spin up bot-bottles on the host system. (Also might make sense to split out the supervisor...)Via a comment. Not sure how best to do that integration though: think having the orchestrator send the comment if the agent doesn't respond or check in probably makes sense to account for agent not being able to send info? Also probably want some sort of dashboard the orchestrator serves so users can monitor whether an agent is stuck or see what they're doing.
Should be assigned a user which is a member of a
bot-bottleorg (or equivalent on different forges)Thanks for the clarifications — a few of these change the PRD design in #318 meaningfully, flagging the deltas:
Freeze →
commit: Already what the PRD calls. ✓Orchestrator as a separate binary: The PRD currently puts everything in
bot_bottle/contrib/gitea/and wires it under./cli.py forge listen. The new shape would be:bot-bottle-orchestrator— separate process/repo, owns bottle lifecycle + webhook listener + dashboard./cli.py orchestrate— thin shim that launches or delegates to the orchestratorThis is the right call for dependency isolation and lets the orchestrator evolve independently. The PRD needs to be updated to reflect this split — the
contrib/gitea/pieces stay in bot-bottle (Gitea API client, provenance builder, forge state), but the orchestration loop and webhook server live in the separate binary.Done signal via comment + watchdog: Makes sense. The agent posts a comment when it finishes a work unit; the orchestrator detects this via webhook and triggers freeze. The watchdog (orchestrator posts on behalf of the agent if no check-in within a timeout) closes the stuck-agent gap. One question: how does the agent post the Gitea comment from inside the bottle? Options:
forge-checkin) the agent calls — the orchestrator then posts on its behalfforge-sidecar(analogous to the supervise sidecar) that wraps the Gitea APIOption 1 seems cleanest — it keeps credentials out of the bottle and gives the orchestrator full visibility. But option 2 fits the existing cred-proxy pattern. Which do you prefer?
Org-based targeting: Makes sense — check assignee is a member of the
bot-bottleorg rather than matching a hardcoded username. Does the org name need to be configurable or isbot-bottlea fixed convention?Got it — direct Gitea API via cred-proxy. PRD implications:
gitea.dideric.isegress route with Bearer auth injection (cred-proxy handles the token)FORGE_GITEA_API,FORGE_OWNER,FORGE_REPO,FORGE_ISSUE_NUMBER,FORGE_PR_NUMBER) so the agent knows where to post without it being hardcoded in the agent manifestAgrees with the cred-proxy-over-MCP tradeoff — you get Gitea integration for free from the bottle's egress config, and adding a second forge later is just a new cred-proxy route rather than a new sidecar. Will update the PRD to reflect this.
@didericis-claude
Should be configurable, but don't expect it vast majority of users to change it. Can be done via an env var when starting up the orchestrator for now, may evolve to live in some orchestrator level db when that comes into being later.
Makes sense —
FORGE_ORGenv var, defaultbot-bottle. The PRD has been updated to reflect this along with all the other decisions from this thread:GET /api/v1/orgs/{org}/members/{user}at event time; org name fromFORGE_ORG(not embedded in manifests or state)./cli.py orchestrate start/resume/statusas the interface the orchestrator calls intoFORGE_WATCHDOG_TIMEOUT(default 30 min) if the agent exits without postingFORGE_GITEA_API,FORGE_OWNER,FORGE_REPO,FORGE_ISSUE_NUMBER) injected at launch so the agent knows where to postgitea.<host>egress route with Bearer auth added to forge-targeted bottles at launch timePRD: https://gitea.dideric.is/didericis/bot-bottle/src/branch/forge-native-integration/docs/prds/prd-new-forge-native-integration.md
@didericis-claude
Thinking about this a little more... for better provenance and less risk of becoming too deeply coupled to a particular forge, I'm thinking option 3 might make more sense. RE option 1, am wary of adding too many MCP servers/ending up with context bloat, so am mostly deciding between 2 and 3.
Implementation sketch for option 3:
Forgeabstract class (should also subsumeDeployKeyProvisioner/maybe have a factory method to create deploy key provisioners)Pros and cons of the above:
Pros:
Cons:
Extend the pros and cons list for me/let me know if I'm missing anything.
Extended pros/cons:
Additional pros:
signal_done(status, summary)call is unambiguous and can relay directly to the orchestrator via a queue dir (same pattern as the supervise sidecar), no comment-parsing heuristics needed.Additional cons:
DeployKeyProvisionersubsumption may be premature: Deploy key provisioning runs at bottle provision time on the host; forge sidecar runs inside the bottle at agent time. Folding them into oneForgeabstract class couples two different auth contexts. Might be cleaner to keep them separate and just share the Gitea HTTP client.My read: option 3 is the right call, primarily because the unambiguous done signal and semantic audit trail are load-bearing for provenance (the stated priority of the product). Comment-parsing heuristics for the done signal are a correctness risk that will surface in production. The scope-restriction con is real but solvable with a read-anywhere/write-scoped model. The
DeployKeyProvisionersubsumption I would leave for a follow-up rather than coupling it into this PRD — the forge sidecar and deploy key provisioner have different lifecycles and actors.