No description
  • Go 94.5%
  • Go Template 2.5%
  • Shell 1.5%
  • Python 1.2%
  • Dockerfile 0.3%
Find a file
Ryan Grippeling c5b9f89c2f
All checks were successful
On Source Change / checks (push) Successful in 2m25s
On Source Change / Semantic Release (push) Successful in 53s
ci: retire the pin comment that outlived the pin
77a5f3c moved this ref to v1.2.0 but left the comment above it saying
"TEMPORARY PIN — flip back to @main once webgrip/workflows PR #40 is merged"
and, at the end, "prefer a merged-to-main SHA the moment #40 lands". #40 has
landed and the ref is already a tag on main, so both instructions now point
the next reader at work that is done — and one of them, flipping to @main,
would undo it.

Says instead what the ref costs and what it bought. v1.2.0 moved the
composite 135/126 lines against v1.1.0, but ploeg felt none of that: it was
already on ee06ca5, PR #40's tip, and the composite is byte-identical between
the two. The repin bought immutability, not behaviour.

Keeps the failure story, because it is the reason for the shape: a SHA pin is
only as immutable as the branch it hangs off, and it fails in a way local
checks cannot see — 2c5c68c9 still resolved from a workstation and still
fetched over SSH after it had stopped being reachable from any server ref.

`ci:` on purpose — not releasable, so this does not cut an rc.18 identical to
rc.17. The release job still runs and still resolves the ref, which is the
part worth proving.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 09:27:12 +02:00
.forgejo/workflows ci: retire the pin comment that outlived the pin 2026-08-09 09:27:12 +02:00
.openhands/skills/team-silver docs: AGENTS.md + team-silver repo skill — make the repo factory-workable 2026-07-24 16:40:27 +02:00
cmd fix(shiftengine,worker,litellm): close the loop the reviews were falling out of 2026-07-31 06:50:43 +02:00
docs docs(research): correct the rc.15 claim — it published; the release job is what broke 2026-08-09 07:56:45 +02:00
internal/ledger docs: make docs/adrs the only ledger, and gate it in go test 2026-07-29 10:26:59 +02:00
openspec fix(shiftengine,store): a failed writing Run re-opens its Round 2026-08-08 15:23:19 +02:00
ops chore(release): v0.2.0-rc.17 [skip ci] 2026-08-09 07:18:25 +00:00
pkg fix(shiftengine,store): a failed writing Run re-opens its Round 2026-08-08 15:23:19 +02:00
scripts docs(ci): name the helm-version trap in the golden check's own advice 2026-08-08 08:00:39 +02:00
.gitignore feat: run forensics survive pod/job cleanup — node+pod identity in logs+checkpoints, failure-reason taxonomy, VIK-586 fix 2026-07-28 17:24:21 +00:00
.releaserc.cjs fix(release): drop the yq appVersion prepareCmd — the shared config bumps both keys 2026-07-27 05:46:30 +02:00
AGENTS.md docs(agents): record the multi-session staging discipline 2026-07-29 17:14:02 +02:00
CHANGELOG.md chore(release): v0.2.0-rc.17 [skip ci] 2026-08-09 07:18:25 +00:00
go.mod feat(config): routing and roster as a file, and push rights minted per Run 2026-07-29 21:00:26 +02:00
go.sum feat(config): routing and roster as a file, and push rights minted per Run 2026-07-29 21:00:26 +02:00
LICENSE feat: bootstrap Ploeg — dispatch plane for ephemeral agent crews 2026-07-21 20:07:17 +02:00
mise.toml docs: make docs/adrs the only ledger, and gate it in go test 2026-07-29 10:26:59 +02:00
package.json ci(release): drop the local semantic-release toolchain — the shared config pins it 2026-07-26 10:05:58 +02:00
README.md docs: update README status — executors ship in the chart 2026-07-29 05:38:28 +02:00
renovate.json ci: Forgejo Actions Go pipeline + Renovate org preset 2026-07-21 20:16:15 +02:00

Ploeg

Assign a ticket on your own board and Ploeg spins up an ephemeral team of AI agents on your Kubernetes cluster that works it, opens a pull request, reports the outcome, and disappears — every run leased, audited, and crash-safe, with no lock-in on tracker, forge, or agent harness.

An open-source, self-hostable dispatch plane. Bring your own board, forge, and agent harness.

Ploeg is Dutch for a work crew or shift. Teams of specialist agents pick up a ticket, work it, report an outcome, and disappear.

Status: pre-alpha. Ploeg is being extracted from a running autonomous-agent setup (a "dark factory": agents working a ticket board unattended on a homelab Kubernetes cluster). The dispatch core and both executors (KEDA ScaledJob and a KEDA-free CronJob) ship in the chart — opt-in via executor.enabled — and dispatch the originating factory today; a local prototype runs the same core over Docker Compose (see below). Provider write-backs, a Forgejo forge provider, and team manifests are still to come. Watch, don't install.

What Ploeg is

  • A dispatch plane, not a board. Your tracker (Vikunja, Jira, GitHub Issues, …) stays the source of truth for what to do. Ploeg owns how work gets executed: assignment events in, ephemeral agent runs out.
  • Event-driven, never polling. Assigning a ticket fires a webhook; Ploeg spawns a Kubernetes Job for it. No heartbeat crons burning tokens to discover there is no work.
  • Ephemeral by design. Every run is a Job that starts, produces a structured outcome, and dies. Durable state lives in Postgres (work items, leases, checkpoints, outcomes, audit) and in git (branches, PRs) — never in a long-lived agent process.
  • Leased, not labeled. Claims are rows with a TTL renewed by the running Job. A crashed pod releases its ticket mechanically; nothing depends on an agent behaving well at death.
  • Teams of specialists. A work item is claimed by a team — a declarative manifest of specialist roles (implementer, reviewer on a different model family, tester) — not by a single agent identity.
  • Audited end to end. Every mutation, lease, run, and outcome is a Postgres row. Grafana dashboards ship as code.

What Ploeg is not

  • Not another kanban UI. The market has plenty; Ploeg has none.
  • Not a persistent-agent platform (see kagent) or model serving.
  • Not a promise of every integration. Ploeg ships a small, stable provider SPI and two reference providers (Vikunja tracker, Forgejo forge). Further providers are community-owned.

Architecture (v0 sketch)

tracker webhook ─┐                        ┌─> KEDA ScaledJob (per team) ─> agent Job (ephemeral)
forge webhook  ──┼─> ploegd ─> Postgres ──┤        │ lease renewal · checkpoints
                 │   (ingest,  (work items,        └─> outcome report ─> ploegd ─> tracker/forge writeback
                 │    SPI)      leases, runs,
                 └─────────────  audit)  ──────> Grafana (dashboards as code)
  • ploegd — single Go binary: webhook ingest, provider SPI, lease manager, outcome ingestion.
  • Executor — KEDA ScaledJob with the Postgres scaler is the flagship default; executors are pluggable behind the run-API contract (docs/contracts/executor.md) — a KEDA-free CronJob executor ships in the same chart (executor.type).
  • Harness contract — an agent container receives a TaskSpec, must emit an OutcomeReport (schemas). Harness adapters live behind pkg/harness.Adapter: openhands (default), exec (any binary), claude-code — selected per team, along with the agent image, via the team's harness block.

Try the prototype

docker compose -f ops/local/docker-compose.yml up -d --build
ops/local/demo.sh

The demo plays both tracker and agent: a signed Vikunja webhook queues a work item, a claim leases it (FOR UPDATE SKIP LOCKED + TTL lease), checkpoint and outcome complete it, and the audit trail records every step as a Postgres row. Crash-safety is real: claim an item, report nothing, and the sweeper releases the lease and re-queues the item when the TTL expires.

Roadmap

  1. Extraction — core service, Vikunja + Forgejo providers, one harness adapter, audit + dashboards. Exit criterion: the originating dark factory runs on Ploeg in production.
  2. Teams & follow-ups — team manifests, checkpoint/resume, PR-feedback ingestion routed to the owning team, a dry-run grooming worker.
  3. On demonstrated pull — GitHub provider, CRD/operator graduation, agent-sandbox runtimes, further providers by contribution.

License

Apache-2.0