gito/packages/contracts/notes/gito-control-plane.md
toki 90f927612e feat(m-iop-agent-run-bridge): complete commit push policy and revision scan event subtasks
- 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
2026-06-16 22:24:23 +09:00

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): true if a revision scan was triggered after a successful push.
  • revision_event_matched (boolean): true if 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.Payload with events.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 type maps to proto-socket action on the event channel.
  • Stored payload maps to the proto-socket envelope payload object without provider secrets or credential values.
  • event.subscribe filters by event name and optional payload fields such as repo_id and branch.
  • event.list returns recent event payloads for smoke/debug use.
  • event.ack remains placeholder-only until a durable cursor or delivery acknowledgement Milestone explicitly scopes it.