Forgejo Accelerated

# Agents

FJX defines a small set of named roles. Each is a separate Forgejo account, with its own phase prompts, its own ledger marker on every issue it touches, and its own narrow set of authorities.

  • Project Manager aka PM (agent-pm) — curator, librarian, command-interpreter.
  • Developer aka DEV (agent-dev) — the worker. Implements approved specs, drafts proposals, investigates issues, lands simple changes.
  • QA (agent-qa) — the deliberately-misaligned second pair of eyes.
  • Builder aka BOB (agent-build) — planned. Release manager.

The human ($FJX_OWNER) is not an agent but carries authority that no agent has: the trust map for /<command> directives, /spec-approved for design-gate decisions, and the final merge.

For the broader framing — how these roles map onto the five leadership "chairs" — see Roles & Chairs.

# Project Manager (agent-pm)

PM is the curator of the workflow. It is off the critical path: removing PM degrades to manual mode without breaking anything. PM exists to make the rest of the workflow cheaper to run.

# What PM does

  • Translates /<command> directives in comments into concrete actions. /spec-approved, /needs-spec, /block, /unblock, /brief, /note — PM is the sole interpreter of this vocabulary. Working agents never parse /<commands>.
  • Curates per-role context briefs. <!-- pm:brief:dev -->, <!-- pm:brief:qa -->. The brief points the working agent at the right phase prompt and adds the small amount of context the issue body and AGENTS.md don't already supply. Briefs follow an "earn its place" test — when in doubt, omit.
  • Routes handoffs. When agent-dev hands back with agent/review, PM decides what's next: hold for $FJX_OWNER (spec proposals, trivial changes), or write a QA brief and route to agent-qa (substantive code).
  • Finalizes closed issues. fjx pm close <N> reads the ledger, closes the issue, removes the worktree, surfaces durable notes for promotion to the Forgejo project wiki.
  • Maintains the PM ledger — one canonical comment per issue, edited in place, recording every /<command> processed.

# What PM doesn't do

  • No code-write authority. PM never commits, never modifies files in the repo. Its entire write surface is Forgejo-only: comments, labels, briefs, ledger, project wiki. This is what makes PM safe to run continuously.
  • No agent-controlling. PM doesn't invoke agent-dev or agent-qa. It assigns the issue and lets them pick it up on their next tick.
  • No gating. Working agents apply agent/* labels themselves under their own protocols; PM doesn't police them.

# Why PM gets more judgment than DEV/QA

The DEV and QA prompts are tightly scoped — narrow output shapes, evidence-required blocker checklists, explicit anti-patterns. PM's prompt is looser, and deliberately so. PM's value is curation, which is judgment work that doesn't reduce cleanly to a checklist. Deciding whether a Context bullet earns its place, whether a note belongs in the project wiki, how to phrase a brief refresh — these are calls a tight imperative prompt would get wrong.

The constraint that keeps PM safe despite the loose prompt is the bounded write surface: PM has judgment inside (comments, labels, briefs, ledger, wiki), and none outside (the repo tree, working agents' ledgers, /<command> parsing).

# See also

# Developer (agent-dev)

DEV is the worker. It claims issues, follows the brief PM wrote, opens PRs, and hands off for review. DEV is the role with the highest output volume and the tightest leash.

# The cycle

  1. fjx dev next — pick the next ready issue (filtered by assignee=agent-dev).
  2. fjx dev claim <N> — apply agent/working, set assignee, create the ledger.
  3. Isolate in a per-issue git worktree at ../worktrees/<project>-<N>. One worktree, one branch, one PR per issue across all phasesproposeapply reuses the same worktree.
  4. Read the issue's <!-- pm:brief:dev --> and follow it to the right phase prompt.
  5. Work. Keep the ledger current (fjx dev ledger --status working).
  6. Open the PR with fjx pr create. Refs: #<N> is prepended for you.
  7. Final ledger update (--status review), then fjx dev done <N>.

# Phases

The brief routes DEV to one of four phase prompts. Each has a distinct output shape and scope rule:

  • simple — typo, comment, obvious one-line fix. Issue body is the spec. Most common derailment: "while I'm here" cleanups that turn a simple change into a non-simple change.
  • investigate — veracity, root cause, and impact are unknown. Output is a wiki/findings/<N>-<slug>.md file, not necessarily code. Investigation IS the work.
  • propose — draft a spec via /openspec-propose. Output is a draft PR with the proposal only — no implementation. Wait for /spec-approved or /spec-rejected.
  • apply — implement an approved spec via /openspec-apply-change. Same worktree and branch as the proposal — spec commits stay, implementation lands on top, draft PR is marked ready. Finish with /openspec-archive-change.

# The tight leash

The DEV prompt is deliberately imperative. Two reasons: DEV's output volume is highest (so prompt-level slop compounds fastest), and DEV's actions have the largest blast radius (commits, PRs, branches). Concretely:

  • Operating directive on fjx usage. If a fjx command errors, default assumption is you invoked it wrong — run --help, don't reach for the raw API. Named anti-pattern in the prompt.
  • Evidence-required blocker checklist. A blocker ledger entry must cite four things: --help output, error grep evidence, brief re-read step, one-line classification. Without all four, the blocker reads as "I gave up after one try" and is sent back.
  • Hard action surface. No editing .forgejo/workflows/*, Justfile, or other CI/tooling files unless the issue explicitly says so. No force-push, no --no-verify, no git reset --hard on shared refs. Never commit on main.
  • Bounded retries. Cap just validate fix attempts at 10. Cap merge-conflict resolution at 3. After 5 validate-fix cycles on one issue, or 3 bootstrap cycles without a merged PR, stop and wait.
  • Stay in scope. New findings are filed as separate issues, not absorbed into the current PR.

# See also

# QA (agent-qa)

QA is the second pair of eyes — agent-level maker-checker. It does not write code. It reads what the Actions produced, finds the gaps the harness can't catch, and returns a verdict.

The misalignment is deliberate: DEV's incentive is "make this work," QA's incentive is "find what's wrong." A clean QA verdict is one layer of defense, not a guarantee — the human merging the PR is the residual judgment downstream.

# The cycle

  1. fjx qa next — pick the next ready issue (filtered by assignee=agent-qa).
  2. fjx qa claim <N> — assign, create the QA ledger.
  3. Isolate in a per-issue git worktree, checked out to the PR branch. QA never commits; the worktree exists to run the code under test in isolation.
  4. Read the issue's <!-- pm:brief:qa --> brief.
  5. Fetch action results: fjx qa checks <pr-id>.
  6. Identify gaps, break them, post findings via the QA ledger.
  7. Hand back: pass → assign to agent-pm; concerns/fail → assign directly to agent-dev (shortens the loop, PM doesn't need to re-route every cycle).

# Where the edge is

The actions cover what they were aimed at. QA's edge is what they miss:

  • Behavior changes hidden behind unchanged type signatures.
  • Race conditions, ordering, concurrency — actions are mostly serial.
  • Logic the type system can't enforce (off-by-one, wrong constant, swapped args).
  • Adversarial inputs the fuzz scaffold didn't try.
  • Failure modes whose tests were authored by the same developer who wrote the code.

"All actions passed" is not a finding. Finding what the actions could not check is the work.

# The verdict

QA posts findings in its ledger and routes by assignment:

  • pass — assign to agent-pm, keep agent/review. PM holds the PR for $FJX_OWNER.
  • concerns / fail — assign directly to agent-dev, keep agent/review. Direct return shortens the revision loop.

Findings are evidence, not opinions. The QA prompt explicitly says: do not soften findings.

# When actions fail

A failed required action almost always means "send back to DEV." QA does not fix the action itself — that's DEV's job. The one exception: a clearly flaky infra failure (network, runner), re-run once before escalating.

# See also

# Builder (agent-build) — planned

agent-build is the release manager role. It does not exist yet. This section sketches the intent so the design is visible before code lands.

# The job

Owning the release path: tagging, building artifacts, publishing to registries, drafting release notes, gating prod deploys. Today these steps are handled by Actions on main plus human attention; agent-build would consolidate them under a named owner with its own ledger and its own narrow set of authorities.

# The chair it picks up

Build maps onto the operator chair from Roles & Chairs — documented triggers rather than nervous-system vigilance. The four canonical trigger categories all land on build's surface:

  • Cost — dollar threshold per release (CI minutes, registry storage, deploy compute).
  • Irreversibility — deletions, external sends (release announcements, customer emails), prod deploys, migrations. Always escalate.
  • Confidence — build's self-rated confidence on a tagged version. Below threshold, escalate.
  • Drift — release notes vs the actual change set. Did the release ship more than the changelog claims?

# Why it isn't shipped yet

The platform-lead chair (blast-radius permissioning) is thinner than the operator chair, and agent-build is the role where that gap hurts most. Prod deploys, tag pushes, migrations, and release-note sends are exactly the high-blast-radius actions that flat boundaries don't cover well. Shipping agent-build before action-tiered permissions exist is the loud-failure-mode shape ROLES.md warns about.

The current plan: design the permission tiering first (read / staging-write / prod-write / delete / external-send), then build the agent against it.