- Archive completed subtask files (PLAN, CODE_REVIEW, logs) to agent-task/archive - Add postgres_internal_test.go for internal storage tests - Update worker main.go, runtime, storage, and runner with iop agent run bridge - Expand test coverage in runtime_test.go, postgres_test.go, storage_test.go, runner_test.go - Update gito-control-plane notes and roadmap milestone
11 KiB
Gito Control Plane Contract Candidates
Transport Policy
- Internal runtime calls use proto-socket first.
- REST remains for health/readiness, provider callbacks, smoke/curl, and simple bootstrap endpoints.
- gRPC is excluded from the first design.
proto-socket Channels
| Channel | Purpose |
|---|---|
repo |
Register, inspect, and list managed repositories. |
workspace |
Lease, release, and inspect workspace slots. |
operation |
Create, cancel, inspect, and stream operations. |
git |
Request platformless Git operations. |
change_request |
Manage provider-neutral PR/MR operations. |
agent_shell |
Reserved/legacy shell scaffold metadata; canonical agent UI is ../agent-shell and backend/runtime is ../iop. |
event |
Subscribe to normalized events. |
proto-socket Action Registry Scaffold
The first proto-socket surface exposes channel/action registry metadata before
real command execution. Every listed action starts as placeholder until its
own Milestone wires storage, worker, or provider behavior.
| Channel | Placeholder actions |
|---|---|
repo |
register, get, list |
workspace |
lease, release, get |
operation |
create, cancel, get, stream |
git |
clone, fetch, status, diff, commit, push |
change_request |
open, update, list |
agent_shell |
heartbeat, dispatch, stream_logs remain placeholder-only until an explicit compatibility Milestone scopes them. |
event |
subscribe, list, ack |
REST Bootstrap Exceptions
REST may expose temporary repo bootstrap helpers for smoke/curl setup while the
proto-socket repo channel is still placeholder-only. Those helpers must stay
limited to bootstrap registration, lookup, and listing, and must use the same
Repo DTO fields documented below.
Agent Shell / IOP Boundary
../agent-shell is the product-agnostic Flutter package for agent interaction
UI and domain models. It is not the Gito backend. Hosts that use that package
should depend on it as agent_shell: path: ../agent-shell and route
agent runtime/backend behavior through the sibling ../iop project.
Gito's responsibility is the Git control plane boundary: repository registry, workspace leases, operations, revision events, durable event records, and provider-neutral Git results. IOP owns agent execution, shell command execution, model/runtime routing, command policy, cancellation, and log redaction source of truth. Gito may persist IOP results only after they are expressed as operation state, Git revision/diff, workspace lease state, or normalized event records. The IOP bridge below is the transport-independent contract candidate for this Milestone. It does not choose the concrete IOP CLI command, profile/model, stdin/input-file shape, or secret injection mechanism.
IOP Agent Run Bridge
Gito creates and owns an agent_run Operation, then hands execution intent to
IOP through an adapter boundary. Gito must not execute the IOP CLI or arbitrary
workspace commands directly. IOP may run through CLI, Edge, Node, or another
runtime, but Gito only records the result once it is expressed as operation
state, Git workspace evidence, or normalized event records.
AgentRunInput
| Field | Meaning |
|---|---|
operation_id |
Existing Gito operation id with type=agent_run. |
repo |
Repo snapshot containing id, remote_url, default_branch, and optional credential_ref; raw credential values are forbidden. |
branch |
Branch checked out in the leased workspace. |
workspace_path |
Absolute path of the leased workspace slot that IOP may use. |
instruction |
User or automation instruction text for the run. |
policy_context |
JSON object with Gito-known policy context, approvals, and allowed result actions; IOP remains source of truth for command policy decisions. See policy keys below. |
expected_revision |
Optional workspace HEAD before IOP starts, used later for revision diff checks. |
credential_refs |
Optional list or map of credential references. Values point to secrets outside tracked contracts and logs. |
policy_context Keys
Transport-independent keys Gito reads from policy_context. IOP may add its own keys; Gito ignores unknown ones.
| Key | Type | Meaning |
|---|---|---|
commit_push |
boolean | true to allow Gito to commit and push after a successful agent run. |
allowed_result_actions |
string array | Alternative form; presence of "commit_push" in the list enables commit and push. |
commit_message |
string | Commit message to use when commit/push is allowed. Defaults to "agent run result: <operation_id>". |
remote |
string | Git remote name for push. Defaults to "origin". |
branch |
string | Branch to push. Defaults to AgentRunInput.branch. |
Raw credential values must not appear in policy_context. When commit/push is allowed, Gito uses the credential environment already present in the workspace; it does not inject secrets from policy_context.
AgentRunState Mapping
| IOP run state | Gito operation lifecycle |
|---|---|
queued |
Operation exists as queued; IOP execution has not been accepted yet. |
running |
Operation moves to running; Gito may append operation.started and agent.run.started records. |
succeeded |
IOP reports successful execution. Gito marks succeeded only after the Git result confirmation step accepts workspace status and revision evidence. |
failed |
Operation moves to failed; Gito records sanitized failure context without raw logs or secrets. |
cancelled |
Operation moves to terminal cancelled; cancellation policy/event details belong to the command policy and cancellation Milestone. |
Structured IOP output is advisory. The success source of truth for this bridge is the Git workspace after the run: status, before/after revision, changed files, and any later commit/push result allowed by policy. When a policy-allowed push is completed, Gito triggers a revision scan to detect the newly updated revision and emit the corresponding branch update event. The results are recorded in the operation completion payload:
revision_scan_attempted(boolean):trueif a revision scan was triggered after a successful push.revision_event_matched(boolean):trueif the scanner matched the new revision and successfully generated/published the event.revision_event_id(string, optional): The ID of the generated revision event if matched.
If the scan fails, the operation moves to failed and a sanitized scan error message is recorded.
MVP: Forgejo Branch Event Flow
Forgejo branch event delivery is now a provided contract:
agent-contract/provided/gito-forgejo-branch-events-v1.md.
Read that contract when working on Forgejo webhook intake, branch.updated
events, event.subscribe, NomadCode branch event wakeups, or the
/callbacks/forgejo/push and /api/listeners/branches surfaces. This note keeps
only the proto-socket channel registry and DTO candidate overview.
Core DTO Candidates
Repo
| Field | Meaning |
|---|---|
id |
Stable Gito repo id. |
name |
Display name. |
remote_url |
Git remote URL. |
default_branch |
Default source-of-truth branch. |
workspace_root |
Local workspace root for slots. |
credential_ref |
Reference to credentials, never the raw secret. |
WorkspaceLease
| Field | Meaning |
|---|---|
id |
Lease id. |
repo_id |
Managed repo id. |
slot |
Zero-padded slot index. |
path |
Local workspace path. |
state |
available, leased, dirty, or error. |
expires_at |
Optional lease expiry. |
Operation
| Field | Meaning |
|---|---|
id |
Operation id. |
repo_id |
Target repo. |
type |
clone, fetch, commit, push, agent_run, etc. |
state |
queued, running, succeeded, failed, cancelled. |
idempotency_key |
Duplicate guard. |
created_by |
Actor id or system source. |
RevisionEvent
| Field | Meaning |
|---|---|
repo_id |
Target repo. |
branch |
Branch name. |
before |
Previous revision. |
after |
New revision. |
changed_files |
Changed file paths and change types. |
observed_at |
Observation timestamp. |
ChangeRequest
Provider-neutral abstraction for GitHub PR, GitLab MR, Gitea PR, and similar platform features.
| Field | Meaning |
|---|---|
provider |
github, gitlab, gitea, etc. |
external_id |
Provider PR/MR id. |
repo_id |
Target repo. |
source_branch |
Source branch. |
target_branch |
Target branch. |
state |
open, merged, closed, draft, etc. |
Normalized Events
Durable event records use a stable envelope:
| Field | Meaning |
|---|---|
id |
Stable event id generated by Gito. |
type |
Normalized event name from the table below. |
subject |
Entity anchor such as operation:<operation_id> or repo:<repo_id>. |
payload |
JSON object encoded as application/json; raw provider secrets and credential values are forbidden. |
created_at |
Time Gito recorded the event. |
| Event | Meaning |
|---|---|
repo.changed |
Repo registry changed. |
branch.updated |
Watched branch revision changed, initially from Forgejo push webhooks or future revision scans. |
workspace.leased |
Workspace lease acquired. |
workspace.released |
Workspace lease released. |
workspace.dirty |
Workspace has uncommitted changes. |
operation.started |
Operation execution started. |
operation.completed |
Operation succeeded. |
operation.failed |
Operation failed. |
agent.run.started |
Agent execution started. |
agent.run.completed |
Agent execution completed. |
change_request.opened |
PR/MR-like object opened. |
change_request.updated |
PR/MR-like object changed. |
change_request.merged |
PR/MR-like object merged. |
provider.webhook.received |
Provider webhook received. |
Operation Event Payloads
Operation lifecycle events are stored in the outbox as normalized event records
with subject=operation:<operation_id>.
| Event | Required payload fields |
|---|---|
operation.started |
operation_id, repo_id, type, state, started_at |
operation.completed |
operation_id, repo_id, type, state, completed_at |
operation.failed |
operation_id, repo_id, type, state, failed_at, optional error |
Outbox Storage Contract
- PostgreSQL is the source of truth for durable events.
- Stored payloads are JSON objects and map to
events.Event.Payloadwithevents.PayloadEncodingJSON. - Outbox readers list events in
(created_at, id)order. - Publish retry state belongs to the outbox store boundary; Redis, if added later, only accelerates fanout.
proto-socket Event Mapping
- Stored
typemaps to proto-socketactionon theeventchannel. - Stored
payloadmaps to the proto-socket envelopepayloadobject without provider secrets or credential values. event.subscribefilters by event name and optional payload fields such asrepo_idandbranch.event.listreturns recent event payloads for smoke/debug use.event.ackremains placeholder-only until a durable cursor or delivery acknowledgement Milestone explicitly scopes it.