Gitmoot v0.9.0
An email can now start a pipeline and hand it the message — end to end, declared in one YAML file, with the Activepieces glue generated and owned by gitmoot so you never open a flow-builder UI. Alongside it: a one-command Activepieces bootstrap, a production wave for pipelines (skipped decisions, intra-stage progress, PR-bound reviews, opt-in self-merge, data-writing produce stages), a kernel-enforced Landlock write sandbox, and a self-balancing memory hierarchy. Everything additive; existing setups behave identically unless you opt in.
What's new since v0.8.8
Email-triggered pipelines, end to end (#851, #861, #863)
name: triage-email
repo: owner/repo
trigger:
kind: email
map: {subject: subject, sender: from_address, body: text}
stages:
- id: route
cmd: 'echo "got: $GITMOOT_TRIGGER_SUBJECT"'
- id: triage
agent: lead
prompt: Read the trigger payload and decide what to do.
needs: [route]
- One-command Activepieces bootstrap (#851).
gitmoot activepieces setup --yesstarts Activepieces + Postgres + Redis in Docker, spawns the token-authed gitmoot bridge, creates the admin account, installs the published@gitmoot/piece-gitmootfrom npm, wires the bridge connection, and imports two starter flows.connect gmailcreates a live-validated IMAP connection from the CLI (wrong app password fails immediately with the provider's error);--with-smtp, non-Gmail hosts, and test servers are flags away. - Declarative triggers — the AP UI becomes invisible (#861). A
trigger: {kind: email}block on a pipeline makespipeline add --enablegenerate, import, metadata-stamp, and publish an ownedgitmoot: <name>flow via the Activepieces API. Ownership is durable (stored flow id + metadata, never name adoption);pipeline bind-triggerrepairs — including recreating a flow deleted in the AP UI; disable is fail-closed (the bridge rejects runs of disabled pipelines even when AP is unreachable); removing the trigger block cleans up the stale flow. - Run inputs — the email reaches your stages (#863). The bridge accepts a bounded string payload (64 KiB body, ≤32 entries, ≤48 KiB decoded; duplicate JSON keys rejected at any nesting — unescape-aware), snapshots it immutably on the run, and exposes it two ways: shell stages get
GITMOOT_TRIGGER_<KEY>environment variables delivered viaexecve(payload can never reach shell source text), and every agent stage's prompt is prefixed with a fencedUNTRUSTEDtrigger block (fence sized from post-truncation values so payload backticks can't escape).trigger.mapcompiles a closed selector set (subject,from_address,text,message_id,date) into the generated flow — raw expressions are never accepted. A newallow_triggered_writesdouble-key mirrorsallow_scheduled_writes: email content cannot silently drive write-capable stages. Companion piece release:@gitmoot/piece-gitmoot0.1.4 (optionalpayloadobject; 0.1.3 flows and older bridges interoperate unchanged). - Local flow execution actually works now. The embedded stack sets
AP_INTERNAL_URL, fixing a bug where every flow run on asetupstack died withINTERNAL_ERROR(engine self-calls hit the host-only published port); trigger poll cadence became configurable. Setup/down polish (#858):downwarns instead of stranding the bridge,--stop-bridgestops only the verified process it spawned, failed template imports are retryable, and prompts never hang in scripts.
Pipelines: the production wave (#819, #821, #823, #839, #826, #829)
- First-class
skippeddecision (#819) — a no-op stage advances the line instead of parking the run. - Intra-stage progress (#821) — elapsed + last-activity for long-running stages, bridged into the dashboard funnel (#841).
- PR-bound reviews (#823) —
source:binds a review stage to the PR its implement stage opened:[implement] → [review the PR] → [gate]is first-class, with a report-only guard. merge: auto(#839) — an opt-in, double-keyed gate mode that lets a pipeline merge its own PR when the gate is green.producestages (#826) — agents that write data, never a PR: declared writable paths, acheck:QA loop with bounded retries, token rollup; codex-first, now with Landlock-backed claude/kimi support (#840).- Wedge fix (#829) — implement stages no longer stall on non-
implementedsuccess decisions.
Landlock launch sandbox (#840)
Kernel-enforced write confinement for produce-stage agents: the launched runtime can only write its declared paths, enforced by the kernel rather than prompt discipline. Off unless the stage declares writes.
Memory: self-balancing knowledge (#838, #837, #827)
- Auto-balanced cluster hierarchy (#838) — recursive agglomerative clustering with bounded fan-out keeps the Knowledge view legible as facts grow.
- Brick-splitting groomer (#837) — oversized memories split losslessly at seams, automatically.
- Fact-to-fact wiki-link edges (#827) —
[[links]]between facts become first-class graph edges (the fact-galaxy server half).
Coordination & dashboard (#852, #866, #862, #836)
- External-coordinator job grouping (#852) — jobs driven by an outside coordinator (like a Claude Code session) group under one workflow with a journal and a memory hook.
- Workflow visibility (#866, #862) — galaxy hubs, a run strip, and a
/workflowsforest + journal view, with the server halves to feed them. - Checkout self-healing (#836) — registration guard plus self-heal for dangling checkouts.
Docs for all of the above are live on the site (Gmail + pipelines workflows, bridge payload reference, llms.txt/llms-full.txt regenerated). Upgrade is a drop-in binary replacement: gitmoot update.