1 Reference
mitosis edited this page 2026-07-29 08:11:35 -05:00

Every enumerable fact of the platform in one place: labels, URL shapes, MCP tools, dispatcher env vars, deeplinks, the flow API, the coldstart gate, and the system repos. For narrative, start at Home.

Labels

Applied on issues and PRs in Forgejo. The dispatcher auto-creates agent-work, agent-working, and ultracode on every repo it manages.

Label Effect
agent-work The queue. Apply to any issue (or open PR) — an agent builds it and opens a PR with a live preview. The label IS the queue: blocked issues keep it until dispatchable.
agent-working Pipeline state — the agent swaps this on when it claims the work; the dispatcher owns its removal.
plan-org Arming label. Apply to the 🌱 Plan this org seed issue in an org's _plan repo to launch the planner.
plat/org-brief Marks the org's seed/brief issue in _plan (prevents duplicate seeds).
plat/domain-claim Marks a repo's custom-domain DNS-challenge issue.
ultracode Operator harness: spawns a Fable orchestrator on the issue. Gated on the label-applying actor being in PLAT_OPERATORS — non-operators applying it do nothing.
blocked:unarmed / blocked:merge-gate / blocked:pr-stuck Operator convention (hand-applied): queryable block-cause taxonomy during interventions.

Validator verdict vocabulary (posted as one PR comment): ✅ Ship it / ⚠️ Ship with nits (both auto-merge) / ❌ Blockers found (rework, bounded at 2 rounds) / ❌ Untestable (infra failure, no rework).

URL shapes

Surface Shape
Git / control plane https://git.espoautos.com
MCP endpoint https://mcp.espoautos.com/mcp (Streamable HTTP)
Grafana https://grafana.espoautos.com (present where the observability stack is deployed)
App (prod) https://<app>-<org>.espoautos.com
App (PR preview) https://pr-<N>-<app>-<org>.espoautos.com
Org landing site https://www-<org>.espoautos.com
Custom domain (BYOD) <app>.<your-domain> once the domain is registered to the org in domains.yaml
Workload namespace <org>--<app>--<env>, env in prod | dev | pr-<N>
Release tag git tag v<semver>; image/chart/APP_VERSION carry the bare semver
Preview version 0.0.0-pr.<N>.<sha7> — sha-suffixed so every push rolls
URN (cross-app reference) urn:<owner>:<name>:<entity>:<id>

MCP tools (37)

Full tour with connection recipes in Connect Your Agent.

App lifecycle

Tool Key params One-liner
create_app owner, name, description?, database?, bucket?, allowedHosts?, domain?, migrate?, consumes? Full synchronous provisioning: repo from template, CI creds, TLS'd URL, OAuth, optional Postgres/S3. Org-owned only; idempotent. Prod stays dormant until first release.
generate_app owner, name, description, database? Repo-only seed; the crew picks it up within ~a minute and ships v1 from the description. database:false = pure consumer (no-db topic, no Postgres). Not idempotent (409 = pick another name).
release_app owner, name, version, notes?, wait_for_ci? Cuts a release at main HEAD; pins the prod chart tag in one gitops commit. Dev auto-rolls (semver:>=0.0.0); prod only moves here.
list_apps Every deployed app (names/urls/status). Ungated.
get_app_status owner, name, env HelmRelease/Deployment/pod health + last 5 Warning events.
tail_logs owner, name, env, lines?, since?, grep?, previous? One-shot log snapshot from every pod in the env.
update_app_content owner, name, path, content, message?, branch? Single-file whole-content commit (prefer commit_files for multi-file).
rotate_oauth_app owner, name Destructive: recreates the Forgejo OAuth app + BETTER_AUTH_SECRET; every active user session invalidated.
delete_app owner, name, force_repo? Removes the gitops overlay + namespaces (prod/dev). Repo kept unless force_repo:true.

Code & collaboration

Tool Key params One-liner
read_repo owner, name, path?, ref? File content or directory listing.
commit_files owner, name, files[], message, branch? Many files, one commit; auto-creates missing branches; no-content = delete.
create_pr owner, name, title, head, base?, body? Idempotent — 409 returns the existing open PR.
list_prs owner, name, number?, state?, limit? Lean list, or full PR (incl. mergeable) with number.
merge_pr owner, name, number, method? Merge/rebase/squash; 405 errors teach the fix.
create_issue owner, name, title, body?, labels?, assignees?, milestone? Label NAMES auto-resolved to ids.
list_issues owner, name, number?, state?, labels?, limit? With number includes full comment thread.
comment owner, name, number, body Works on issues AND PRs (shared numbering).
update_issue owner, name, number, state?, title?, body?, milestone? The closing tool; milestone: 0 clears, omitted preserves.
create_milestone owner, name, title, description?, due_on? Returns {id}; attach via create_issue(milestone: id).
add_issue_dependency owner, name, index, dep_index, dep_owner?, dep_name? Declares blocked-by (cross-repo supported); live transitive-cycle guard, fail-closed.
lint_dependency_graph owner, name? Org-wide graph audit: cycles, orphaned consumers, duplicate providers, silos, dead blockers + health.
get_contract owner, name Integration contract for another app: OpenAPI URL, typed client, m2m audience, scopes, forbidden-to-table entities.

CI & data

Tool Key params One-liner
get_build owner, name, ref? Actions run status for a ref; failure attaches a runner-log tail.
retry_build owner, name, ref, workflow? Re-triggers via workflow-dispatch; refuses pull_request-only workflows (push an empty commit for previews).
query_db owner, name, sql, env?, max_rows?, allow_write? SQL against the app's own Postgres as the non-superuser app role; read-only unless allow_write:true.

Workflows, domains, admin

Tool One-liner
list_workflows / run_workflow / get_workflow_status / tail_workflow_logs Platform workflow service, owner-membership gated. cancel_workflow is a stub today.
add_domain(owner, domain) Returns the DNS TXT challenge to publish; safe to re-run.
verify_domain(owner, domain) Live DNS check; registers <domain> → <owner> in domains.yaml.
set_app_domain(owner, name, domain) Per-app custom-domain override (Ingress, cert, auth URL, OAuth redirect).
set_org_domain(owner, domain, name?) Org default: apps resolve to <name>.<domain>.
admin_revoke_user_access(login, reason?, ttl_hours?) Admin-only deny-list kill switch (default 24h).
mint_agent_token(owner, name?, ttlSec?) Admin-only run-scoped token; omit name for an org-scoped planner token.
mint_agent_ctx_token(owner, name, ttlSec?) Admin-only, requires PLAT_AGENT_CTX_RBAC=1; short-lived read-only Kubernetes token for one app namespace.

Dispatcher env vars (operator surface)

Set on the agents deployment (plat/gitopsplatform/agents/helmrelease.yaml). Flow semantics in Steering the Fleet.

Var Default Meaning
PLAT_TOKEN (required) Forgejo admin PAT; never reaches agent runs (per-run deploy keys + scoped MCP tokens instead).
CLAUDE_CODE_OAUTH_TOKEN / ANTHROPIC_API_KEY Claude credential; without one the dispatcher is bookkeeping-only.
FORGEJO_BASE http://localhost:3000 Forgejo API base.
FORGEJO_SSH forgejo-ssh.forgejo.svc.cluster.local:22 SSH endpoint agents push through.
MCP_URL http://localhost:8080/mcp Platform MCP server.
APPS_DOMAIN plat.local Domain for all app/preview/www hosts.
WEBHOOK_PORT / WEBHOOK_URL 9909 / http://host.k3d.internal:9909/hook Operator-API port; webhook target registered in Forgejo.
WEBHOOK_SECRET "" HMAC secret for webhooks AND the operator API; empty = verification off.
WORKDIR ~/.plat-agents State, run logs, spend.jsonl.
BUILDER_MODEL / WORKER_MODEL / REVIEWER_MODEL / ORCHESTRATOR_MODEL opus / sonnet / sonnet / fable Model per role.
WORKER_MAX_TURNS 200 Worker turn budget.
MAX_CONCURRENT 2 Global concurrent-run slots.
PLAT_OPERATORS "" Comma-separated logins allowed to wield ultracode.
PLANNER_MODE armed armed | auto (plan orgs on sight) | off.
PLAN_REPO / PLAN_LABEL _plan / plan-org Seed repo + arming label.
AUTO_RELEASE / AUTO_MERGE_ISSUE_PRS 1 / 1 Auto-release after merge; auto-merge validated issue PRs.
SWEEP_INTERVAL_MS / HEARTBEAT_INTERVAL_MS 60s / 3m Reconcile sweep + live-progress cadence.
IDLE_TIMEOUT_MS / ABSOLUTE_MAX_MS / REVIEWER_ABSOLUTE_MAX_MS 10m / 24h / 40m Run watchdogs.
QA_FORGEJO_USER / QA_FORGEJO_PASS "" Validator's browser login (empty = auth untestable).
ORG_MAX_INFLIGHT_PER_ORG 2 Per-org concurrency — the steady-state pacer.
ORG_SPEND_CEILING_USD / ORG_SPEND_WINDOW_MS 0 / 1h Per-org soft budget (0 = off); hold, self-healing.
ORG_BREAKER_USD / ORG_BREAKER_WINDOW_MS / ORG_BREAKER_COOLDOWN_MS 0 / 5m / 15m Tight-window kill switch + cooldown.
ORG_DAILY_CAP_USD / ORG_MIN_GAP_MS 0 / 120s Emergency budget lid; min gap between run starts.
GLOBAL_SESSION_USD / GLOBAL_SESSION_WINDOW_MS / GLOBAL_WEEKLY_USD / GLOBAL_HOURLY_USD 0 / 5h / 0 / 0 Global governor: fleet shares of the one subscription.
PROVIDER_FAIL_THRESHOLD / PROVIDER_STARTUP_FAIL_MS / PROVIDER_BASE_BACKOFF_MS / PROVIDER_MAX_BACKOFF_MS 3 / 8s / 5m / 60m Provider-backoff tuning (crew-wide pause on credential/limit signatures).
FLEET_REPO / FLEET_ISSUE / FLEET_CADENCE_MS / FLEET_SNAPSHOT_MS plat/fleet / 1 / 6h / 5m 🛰 fleet-status issue location + cadences.
EPISODE_LOG_REPO / EPISODE_LOG_ISSUE plat/fleet / 2 Episode-digest feed (empty repo disables episode auto-close).
ULTRACODE_LABEL ultracode Operator-harness label name.
AGENT_SUDO_IMPERSONATION 0 1 = agent Forgejo writes attributed to the triggering user via admin Sudo.
Intent URL
Sign up https://git.espoautos.com/user/sign_up
Generate a PAT https://git.espoautos.com/user/settings/applications
New issue, prefilled https://git.espoautos.com/<org>/<app>/issues/new?title=Add+CSV+export&body=Users+need+CSV+export.
New issue via template https://git.espoautos.com/<org>/<app>/issues/new?template=agent-task.md — templates may pre-apply labels
Issue template chooser https://git.espoautos.com/<org>/<app>/issues/new/choose
New repo from template https://git.espoautos.com/repo/create?template_id=<id-of-plat/_app-template>&org=<numeric-org-uid>
Create an org https://git.espoautos.com/org/create (no prefill params — the description you type is the product brief)
App secrets https://git.espoautos.com/<org>/<app>/settings/actions/secrets
App variables (PLAT_DEV) https://git.espoautos.com/<org>/<app>/settings/actions/variables
Org team page https://git.espoautos.com/org/<org>/teams/<team>
The app template https://git.espoautos.com/plat/_app-template

Supported issues/new query params: title, body, milestone (numeric id), project (numeric id), template. labels is not a supported param — pre-set labels only via an issue template file (labels: [agent-work] front-matter). repo/create supports exactly org and template_id; name/description cannot be prefilled.

Flow API (dispatcher operator surface)

HTTP on the agents service, port 9909. Auth = HMAC-SHA256 over the raw body with WEBHOOK_SECRET (X-Hub-Signature-256: sha256=<hex>); no secret configured = verification off. Wrappers: the plat-flow CLI (signs in-cluster) and Grafana's session-gated /flow-api prefix on https://grafana.espoautos.com (Grafana session is the credential).

Route Methods Does
/hook POST Forgejo webhook receiver (HMAC-verified before parse).
/metrics GET Prometheus exposition (unauthenticated, ClusterIP-only).
/healthz GET {ok, activeRuns, queued, providerBackoffSec, globalPaused}.
/fleet GET JSON fleet snapshot (same data as the 🛰 issue).
/governor GET/POST/DELETE Read / override / clear the global governor (hourlyUsd, sessionUsd, weeklyUsd).
/pause POST/DELETE Global pause set/clear (finishing reviewers still ship).
/provider/backoff DELETE Clear crew-wide provider backoff.
/flow/<org> GET/POST/DELETE Read / merge / clear a per-org override (numeric flow knobs + boolean paused).
/flow/<org>/cooldown DELETE Clear an org's tripped-breaker cooldown.

plat-flow CLI verbs: fleet | get <org> | set <org> '<json>' | clear <org> | clear-cooldown <org> | pause | resume | clear-backoff.

Coldstart gate assertions

scripts/coldstart-assert.sh [--e2e] <kube-context> <domain> — the one acceptance gate for a germinated platform; CI and humans run the same script. Details in Grow Your Own Platform.

Assertion Passes when
A1 All Flux Kustomizations Ready (>=10, incl. kyverno + kyverno-policies); >=12 Kyverno ClusterPolicies.
A2 Exactly ONE Forgejo system webhook (probed by ID — the list endpoint lies).
A3 Dispatcher restart leaves exactly one hook; log contains system webhook verified.
A4 HTTP→HTTPS redirect matrix correct in-cluster; traefik logs free of missing-middleware errors.
A5 Registry mirror alive: forwarder pod Running, node listens on 127.0.0.1:31100, crictl pull through the mirror succeeds.
A6 deploy/agents + deploy/mcp Available.
A7 Fork genealogy: the daughter's plat/mitosis records an original_url with real parent history (tier-strict when FORK_TIER is set).
E1 A Claude credential is sealed in plat-agents-secrets.
E2 Canary repo generated from _app-template (the description IS the spec).
E3 A PR with head branch prime opens within 900s.
E4 The prime PR auto-merges (builder → preview → verdict → merge), no human.
E5 Prod serves 200 in-cluster at <app>-<owner>.<domain>.
E6 Zero preview liveness unconfirmed fallback lines.
E7 Builder-finish → reviewer-queued gap < 120s.
E8 Prod namespace carries plat.sh/app, >=1 ResourceQuota, >=3 NetworkPolicies.

The repos of the platform

Repo Role
plat/gitops The declarative substrate: every platform component and app overlay; Flux converges the cluster on it.
plat/mcp The platform MCP server: 37 tools, OAuth/PAT auth, /ci/preview + /ci/sync-env provisioning endpoints.
plat/agents The dispatcher: build crew (builder/worker/reviewer/planner/migrator/orchestrator), flow control, fleet status.
plat/_app-template The app seed: Bun + Fastify + TypeBox stack, five CI workflows, feature flags, Helm chart.
plat/ci-runner Toolchain image for the isolated CI runner pool (runs-on: isolated).
plat/ci-builder Legacy CI toolchain image; current isolated-vintage seeds pin no ci-builder tags.
plat/mitosis Reproduction: nix run .#up, seed + germinate, the coldstart gate — and this wiki (wiki/).
plat/hello Minimal seeded app repo carried in every seed.
plat/workflows The platform workflow service behind the *_workflow MCP tools.
plat/flow Flow Deck console (parent-side; not carried in the seed — lean daughters run without it).