Maintenance Factory
A useful “dark factory” is not an agent with a large prompt and unlimited authority. It is a small-work queue with explicit promotion, isolated execution, bounded retries, and production evidence.
Flow-Next supplies the lifecycle engines:
- Pilot selects one blessed item and advances one build stage.
- Land owns the PR after Pilot reports
DEFERRED_TO_LAND. - Tracker Sync lets Linear, Jira, GitHub, or GitLab provide the promotion signal.
- Worktree Kit supplies isolated checkouts.
The queue policy on this page is an orchestration pattern above those primitives, not a dark-factory command or a promise that Flow-Next understands your deployment topology. Your prompt, scheduler, and repository rules define scope, concurrency, release, and production verification.
The operating model
Section titled “The operating model”flowchart LR
A["Backlog item"] --> B{"Human-blessed?"}
B -- "No" --> A
B -- "ready=true or exact tracker state" --> C{"Workable maintenance spec?"}
C -- "Thin or consequentially ambiguous" --> D["Park with exact question"]
C -- "Yes" --> E["Claim + isolated worktree"]
E --> F["Pilot: one stage per tick"]
F --> G{"PILOT_VERDICT"}
G -- "ADVANCED" --> F
G -- "ASKED / NEEDS_HUMAN" --> D
G -- "DEFERRED_TO_LAND" --> H["Land: CI, review, merge, release"]
H --> I{"Runtime-affecting?"}
I -- "No" --> J["Tracker reconciliation + closeout"]
I -- "Yes" --> K["Approved deployment path + per-target verification"]
K --> J
The important boundaries:
- Promotion is human-owned. A local
ready=trueor the exact configuredtracker.readyStateis the blessing. The operator may read that signal; it never promotes an unblessed item itself. - Fitness is narrower than readiness. A promoted ticket can still be too thin to execute. Require a clear goal, boundaries, acceptance criteria, verification, dependencies, and no unresolved consequential ambiguity.
- The maintenance lane is deliberately boring. Bug fixes, regressions, bounded UI/UX improvements, docs, reliability, tests, and maintenance qualify. New product features, major architecture, broad migrations, new schemas or connectors, destructive operations, and product-policy decisions do not.
- Isolation is per item. Keep one registered
.worktrees/<spec-branch>/checkout for the item’s full lifecycle. Every state-changing Pilot, test, QA, PR, and Land action runs there. (Since 4.1.0 this composes fully: pilot’splan/plan-reviewstages run inside a secondary worktree instead of demanding the default branch.) - Readiness is not a concurrency lock. Before claiming, inspect active claims, registered worktrees, open branches and PRs, dependencies, and changed-file overlap against fresh
origin/main. - Production completion is project-defined. Land follows repository release instructions; your operator adds the guarded deployment and live-verification steps for every required target. Documentation-only changes do not invent a runtime rollout.
Promotion and parking
Section titled “Promotion and parking”Set the tracker state once:
flowctl config set tracker.readyState "Ready for Dev"Use the exact workflow-state or status name configured for the project. Linear and Jira readiness is state-based; GitHub and GitLab readiness is label-based. Tracker-connected projects treat the tracker as authoritative: pull-side reconciliation projects that signal onto the local spec’s ready flag.
Valid intake shapes:
- Flow spec only, with
ready=true. - Tracker issue only, in the exact promoted lane.
- Linked tracker issue and Flow spec.
Tracker-only work is valid intake, not executable work: backlog mode parks it with a request to capture or interview a Flow spec rather than treating issue prose as an implementation contract. Planning is not a prerequisite for promotion. Pilot can plan and run plan review once a self-contained Flow spec exists. A self-contained specification is the prerequisite for execution.
When a promoted item lacks enough authority, park it with one exact question:
Should retries stop after the third failure or continue until the 30-second deadline?
Do not ask:
Can you clarify the requirements?
Backlog mode records these as durable async questions and emits PILOT_VERDICT=ASKED. The queue can continue with independent items while that one waits.
Isolation and overlap
Section titled “Isolation and overlap”Fetch before selection and conflict assessment:
git fetch --prune origingit worktree list --porcelainflowctl listgh pr list --state open --json number,headRefName,baseRefName,urlFor the selected spec:
- Resolve its canonical branch name.
- Reuse its registered worktree if one already exists.
- Otherwise create
.worktrees/<canonical-branch>/from freshorigin/main. - Run the whole lifecycle from that path.
Treat overlap as unsafe when concurrent work would require either agent to guess merge order, duplicate a shared contract change, or repeatedly rebase across an actively changing area. Record a machine-readable defer reason, preserve readiness, and reconsider after the conflicting branch merges.
A practical defer record needs at least:
{ "spec": "fn-42", "kind": "overlap", "conflicts_with": "fn-39", "surfaces": ["src/billing/contract.ts", "api/invoices"], "reconsider_after": "fn-39 merged to origin/main"}Do not turn temporary overlap into a human escalation. Do escalate a semantic merge conflict: autonomous conflict resolution is safe only when ownership and integration order are mechanically obvious.
Copy-paste goal
Section titled “Copy-paste goal”Adapt the bracketed project details. Keep the scope and authority clauses; delete deployment language only when the repository truly has no runtime.
/goal Drain the blessed maintenance queue to production completion.
Eligible intake:- Bug fixes, regressions, bounded UI/UX improvements, documentation, maintenance, reliability, and test improvements.- Exclude new product features, major architecture changes, broad migrations, new connectors or production schemas, consequential product-policy choices, destructive data operations, and work that materially expands a spec.- Promote only when a Flow spec has ready=true or its tracker issue is in the exact configured tracker.readyState. Never promote an unblessed item.- Accept Flow-only, tracker-only, and linked items as queue intake. Park a tracker-only item for capture/interview; never execute directly from issue prose. Planning may happen in Pilot once a Flow spec exists.- Before execution require a self-contained specification: clear goal, boundaries, acceptance criteria, verification, dependencies, and no unresolved consequential ambiguity. Park thin items with one exact human question.
Isolation and selection:- On every wake, fetch origin before selecting work or assessing overlap.- Before claiming, inspect active Flow claims, registered worktrees, open branches and PRs, dependencies, and changed-file overlap against origin/main.- Before state-changing work, create or reuse the spec's registered worktree at .worktrees/<canonical-branch>, based on fresh origin/main.- Run every Pilot stage, test, QA pass, PR update, and Land remediation for the spec from that worktree. Keep it for the entire lifecycle.- Defer materially overlapping work with a machine-readable reason. Preserve its readiness and reconsider after the conflicting branch merges. Never guess through semantic conflicts or modify another agent's checkout.
Execution:1. Select one eligible independent item read-only.2. In its worktree, invoke /flow-next:pilot --backlog --spec <spec-id>.3. Repeat one Pilot stage at a time while it reports ADVANCED.4. On PILOT_VERDICT=DEFERRED_TO_LAND, invoke /flow-next:land from the same worktree.5. Continue Pilot and Land until the item reaches a terminal outcome.6. Keep processing other independent items while one waits on a human, dependency, review, CI, or overlap.
Release and verification:- Land owns bounded CI repair, review remediation, current-head gates, merge, release, and the repository's documented closeout.- For runtime-affecting changes, use only the project's approved operator path and identities. Preflight the exact project and mode before cloud actions.- Deploy the same release to [TARGETS]. Verify each target independently: supported public URL, release/version parity, interface or schema conformance, health, and spec-specific behavior.- Report sparse or unavailable tenant data honestly; do not silently omit a target or turn absence of sample data into a false failure.- Documentation-only changes still require PR, CI, merge, and release closeout, but no invented runtime deployment.- Preserve tenant isolation and repository data-safety rules. Never delete, truncate, drop, recreate, weaken authorization, expose credentials, or widen scope without explicit human approval.
Cadence:- During a wake, continue immediately while useful state-changing work exists.- When all remaining work awaits CI, review, another agent, a dependency, the Land patience window, or human input, end the cycle. Wake about once per hour.- Do not continuously poll or repeatedly report unchanged state.- Reconsider parked and overlap-deferred items only on an hourly wake or after a known conflicting merge.
Stop and request human intervention only for:- unclear or expanding scope; ineligible new-feature work;- missing acceptance or verification authority;- unresolved consequential UX, product, security, privacy, tenancy, schema, migration, retention, or destructive-operation decisions;- missing operator authorization or failed project preflight;- semantic merge conflicts; exhausted bounded CI or review remediation;- production verification that cannot safely roll forward or back;- any Pilot or Land NEEDS_HUMAN verdict.
Completion:- Stop permanently only after Pilot and Land both report NO_WORK on two consecutive hourly wakes, unless new eligible work appears.- Require every resulting PR merged, required release/deployment complete, runtime changes verified on every target, and Flow/tracker state reconciled.- Final report: each item, PR, merge/release id, tests, deployment targets, live-verification evidence, and every parked human question.This prompt intentionally contains more policy than command syntax. Pilot and Land already know how to advance their stages. The queue controller’s job is to decide what may enter, where it may run, when it must wait, and what counts as production proof.
Headless hourly controller
Section titled “Headless hourly controller”/goal is convenient in an interactive host. The same policy can be run by launchd, cron, a CI scheduler, or an internal control plane that starts one fresh headless session per wake.
Store the adapted goal in a reviewed repository file such as:
.flow/automation/maintenance-queue.mdKeep the goal body intact; the runners below strip the interactive /goal prefix from its first line and replace it with a one-wake instruction. Then choose one runner. Run it from a trusted repository with Flow-Next installed and the required GitHub/tracker/cloud credentials already provisioned.
Claude Code
Section titled “Claude Code”repo_root="/srv/acme-app"prompt_file="$repo_root/.flow/automation/maintenance-queue.md"run_log="$repo_root/.flow/tmp/maintenance-$(date -u +%Y%m%dT%H%M%SZ).jsonl"factory_prompt="$( { printf '%s\n\n' "Run one maintenance-factory wake cycle."; sed '1s|^/goal ||' "$prompt_file"; } )"
cd "$repo_root" &&claude -p "$factory_prompt" \ --output-format stream-json \ --verbose \ --permission-mode acceptEdits \ --max-budget-usd 25 \ </dev/null | tee "$run_log"repo_root="/srv/acme-app"prompt_file="$repo_root/.flow/automation/maintenance-queue.md"run_id="$(date -u +%Y%m%dT%H%M%SZ)"run_log="$repo_root/.flow/tmp/maintenance-$run_id.jsonl"final_log="$repo_root/.flow/tmp/maintenance-$run_id.final.txt"factory_prompt="$( { printf '%s\n\n' "Run one maintenance-factory wake cycle."; sed '1s|^/goal ||' "$prompt_file"; } )"
codex exec \ -C "$repo_root" \ --sandbox workspace-write \ --json \ --output-last-message "$final_log" \ "$factory_prompt" \ </dev/null | tee "$run_log"Equivalent headless entry points — Cursor agents, Factory Droid automation, a Kubernetes job, or an internal scheduler — work if they can load the project rules and Flow-Next skills, mutate only the intended workspace, and return a durable transcript.
Prefer one fresh wake-cycle process over a shell process that sleeps forever:
- The external scheduler owns the hourly cadence and retry policy.
- Each run has a hard budget and an inspectable exit.
- Credentials can be short-lived.
- A crashed agent does not become a silent immortal poller.
- The two-consecutive-
NO_WORKcounter can live in small scheduler state rather than model memory.
Do not pass secrets in the prompt or command line. Inject them through the runner’s secret store or provisioned operator identity. A headless host still needs the same repository lock, exact worktree ownership, and cloud preflight as an interactive run.
Jira or Linear as the front door
Section titled “Jira or Linear as the front door”The board can be the factory’s human console:
- Configure
tracker.readyStateto an exact state such asReady for Dev. - Keep unapproved work outside that state.
- Move a bounded, self-contained maintenance issue into it to bless execution.
- Let backlog-mode Pilot union tracker-only, Flow-only, and linked items.
- Let async questions and lifecycle updates reconcile back to the issue.
For Jira, the promoted lane is queried using the configured status name. For Linear, the workflow-state name is matched exactly after normalization. No separate “agent ready” score should infer promotion from priority, labels, assignee, or prose.
An external scheduler may use Jira, Linear, GitHub Actions, or another queue to wake the controller, but it should not duplicate Flow-Next’s stage machine. Feed the same reviewed maintenance goal to the host, let Pilot and Land emit their verdicts, and store the transcript plus release evidence as the run receipt.
What to measure
Section titled “What to measure”A factory that only counts merged PRs will optimize for easy PRs. Track:
- promoted → first action latency;
- time parked and the exact missing authority;
ASKED,BLOCKED, andNEEDS_HUMANrates by cause;- overlap-defer time;
- first-pass CI and review success;
- bounded remediation exhaustion;
- merge → release → per-target verification latency;
- production-verification failures and rollback/roll-forward outcomes;
- items reopened after “completion.”
The useful unit is not agent activity. It is a blessed maintenance item closed with current-head review, reproducible tests, release identity, and live proof.