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/gitops → platform/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. |
Deeplink patterns (this Forgejo)
| 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). |
For everyone
Experience
Operate
Under the hood
Grow
This wiki ships inside plat/mitosis (wiki/) — edit it there, not here. Grown by the platform it describes.