Agentic orchestration for governed end-to-end product delivery
Project description
Startup Factory
Turn your product board into a governed software delivery system.
Startup Factory is an agentic orchestration framework for end-to-end product delivery. Connect the project-management tool your team already loves—Linear, Jira, GitHub Issues, local Markdown, or your own adapter—and make it the durable control plane for a cross-functional team of AI agents.
Put a [task] in ToDo—the shipped mapping of the generic queued state.
When automation is enabled and scheduled, the deterministic PM supervisor
checks the board every three minutes by default, leaves anything labeled
human-work to people, routes every other queued task by its explicit team
preset (or your configured default), and drives it through architecture,
implementation, a four-party In Review gate, optional specialist QA, and
integration. It also observes Blocked work as a human-controlled safety lock:
the matching task workers stop, while independent ToDo work continues. When
your release policy, exact approval, and protected green CI proof allow it, a
separate credential-isolated executor deploys the reviewed immutable artifact,
verifies the target, and only then closes the parent [feature] as Live.
Bring your own models, repository, stack, tracker, and infrastructure. Provider-neutral structured hooks can target production in any cloud, platform, cluster, datacenter, or internal environment that can implement the plan/apply/status/verify contract. Startup Factory supplies the delivery protocol, team topology, deterministic runtime, recovery model, and safety boundaries around them.
Project-management native · Multi-model · Cloud agnostic · Fail closed · Auditable
This is not a hidden chatbot loop. Plans, ownership, progress, decisions, evidence, blockers, approvals, policy denials, and deployment state remain visible in the same board where your team manages the product. Tracker text and claimed authorship are workflow evidence, never security authentication or production authority.
ToDo -> In Progress -> In Review -> Ready for production -> deploy -> Live
findings -> ToDo -> fresh attempt -> In Progress
red / pending / missing CI ----------------------X deploy anywhere
Safe by default: board automation and production delivery both ship disabled. Ordinary agents never receive production credentials; enabling a release requires protected external configuration, hooks, identities, and verification. Only an exact, current green CI/CD proof for the release commit permits deployment.
Table of contents
- Layered safety boundaries for AI builders
- Why Startup Factory
- Superpowers + Startup Factory
- Full transparency in your tracker
- Choose your operating mode
- Requirements
- Quick Start (2 minutes, no accounts)
- Install into your repository
- Connect your LLM
- Connect your tracker
- Configure
- Use it
- Automate the board and production delivery
- The six preset teams
- How it works
- Documentation map
- Directory map
- Extend it
- Troubleshooting
- Credits
- License
Layered safety boundaries for AI builders
Autonomous agents are only as useful as the boundaries around them. Startup Factory supplies fail-closed workflow and release controls, but repository code is not an operating-system security boundary. Ordinary agents still require a real worktree-scoped sandbox and least-privilege identity:
- A code-owned production policy gate.
bin/policy-check.pyscreens every privileged release-hook command and normalized production plan before that subprocess starts. Its deny baseline — shell composition, privilege escalation, filesystem/database/ infrastructure destruction, secret dumping, metadata-credential access, encoded-command bypasses — is owned by the code: project configuration can add denials, never remove one. - A three-tier authority model. Every action resolves to DENY,
REQUIRE HUMAN APPROVAL, or ALLOW (
reference/guardrails.md). Approvals bind exact digests, environments, targets, expirations, and one-use nonces. Silence never approves; unknown anything is denied. - A
[task]-level release-denial trail. A normalized production-plan denial is projected idempotently as[DENIED ACTION]throughbin/tracker-ops.sh record-denial. Other launcher, path, queue, and identity preflight refusals fail before mutation and remain in protected runtime logs; they are not falsely advertised as tracker records. - Least-privilege agent sandboxes. In enforced mode every LLM process and
WORKTREE_SETUPruns asAGENT_SANDBOX_RUNNER --workdir <absolute> -- /usr/bin/env -i .... The launcher accepts only a protected executable outside the repository; that runner must enforce filesystem, process, network, and IAM isolation. In broker mode no LLM—including the team lead—receives tracker credentials. - Contained workspaces. Every implementer is isolated in its own git worktree; tracker file paths are symlink-safe and confined to their configured root; integration and terminal transitions are serialized, verified by read-back, and reserved to dedicated components.
- Automation that is off by default. The portfolio supervisor is deterministic (not an LLM), disabled until explicitly enabled, and stops the pass rather than fabricating state when anything is malformed.
The built-in authority policy is intentionally simple:
| Decision | Representative actions | Who can authorize it |
|---|---|---|
| Always deny | Path escape or recursive/bulk deletion outside disposable task scope; database/schema drops or truncation; production instance, cluster, storage, network, DNS, certificate, key, backup, or log deletion; secret extraction; privilege escalation; wildcard IAM; force-push/history rewrite; sandbox or policy bypasses | Nobody inside Startup Factory. Use a separate human-operated break-glass process. |
| Require exact human approval | Non-destructive production infrastructure, IAM, network, DNS, certificate, capacity, schema, backfill, traffic, cost, or scale changes; external communication | A protected verifier must authorize the exact manifest, target, commit, artifact, digests, expiry, and one-use nonce. A tracker comment is not approval. |
| Allow within scope | Read-only inspection, plans, tests, builds, linting, worktree-local edits, task-branch checkpoints, brokered integration, health checks, and a policy-clean immutable-artifact release | The assigned role or deterministic executor, within its path, identity, target, quota, and lifecycle boundaries. |
The full non-bypassable list and enforcement boundary are in
reference/guardrails.md.
The result: you can hand real delivery work to AI agents and inspect, from your tracker, the workflow actor, workflow approvals, production approval ID, and policy denials for each delivery. Authenticated production approver identity remains in protected transaction state; tracker authorship is never treated as authentication.
Why Startup Factory
| Advantage | What it gives you |
|---|---|
| Move fast without merge chaos | A deterministic dispatcher launches only design-approved, dependency-ready, resource-safe work. Each attempt gets its own task branch and worktree; integration stays serialized. |
| See the whole delivery, not just agent output | One live [progress] record per [task] and one [digest] per [feature] show tracker status, execution stage, actor, and attempt in your project-management tool. |
| Use the right model for each job | Mix Claude, Codex, Gemini, or any file-reading CLI by role, then route individual tasks to fast, standard, or strong model profiles. |
| Keep quality gates explicit | Architecture approval precedes implementation. In Review requires independent approvals from the Principal Architect, Sceptical Principal Architect, Senior Security Engineer, and Team Lead over one exact package; optional QA may add evidence, and the integrator runs your build, test, and lint commands before merging. |
| Recover instead of restarting | Immutable task packets, durable events, checkpoint branches, an idempotent outbox, and attempt-aware relaunches make interrupted work inspectable and recoverable. |
| Keep your stack and your tracker | The same workflow runs across languages, frameworks, LLMs, and project-management tools. Start offline with Markdown and switch adapters without rewriting the process. |
| Turn the board into a safe delivery queue | A deterministic cron/service pass observes queued/blocked work, restores in-flight runs, chooses an explicit team preset, and launches LLMs only for eligible queued tasks. |
| Pause one task without stopping the factory | On the next scan, [Blocked] immediately fences only the matching task. Independent ToDo work and other features continue; only a human can unlock it. |
| Keep dangerous authority out of agents | One deny/approval/allow contract governs every role. The code gate blocks dangerous privileged release hooks and plans; your required OS sandbox and least-privilege identities enforce ordinary-agent filesystem, network, process, and IAM boundaries. |
Superpowers + Startup Factory: split the SDLC by strength
obra/superpowers and Startup Factory
operate at different, complementary levels.
Superpowers is an engineering methodology packaged as agent skills. Its full upstream workflow can cover brainstorming, implementation planning, worktree creation, task execution, TDD, debugging, code review, verification, and branch completion. Startup Factory is a project delivery control plane: it coordinates product, architecture, implementation, security, quality, integration, portfolio automation, and production release across durable tracker state and multiple independent agents.
The combined integration deliberately uses the strongest part of each system without running two execution orchestrators:
- Superpowers shapes the idea into an approved specification and detailed implementation plan.
- Startup Factory reviews those documents as inputs, creates and governs the tracked delivery, and owns execution through verified production.
- Claude task workers may use focused Superpowers methods for TDD, debugging, receiving review, and fresh verification inside their one assigned task.
- Superpowers does not create a second worktree, dispatch a second team, execute the plan, merge the branch, or declare the feature released.
flowchart LR
Idea["Product idea or ticket"]
Brainstorm["Superpowers brainstorming<br/>questions · alternatives · approved design"]
Plan["Superpowers writing-plans<br/>exact files · interfaces · tests · commands"]
Handoff["Digest-bound planning handoff<br/>committed spec + plan"]
Shape["Startup Factory planning review<br/>Product · Lead · Principal · Sceptical"]
Tracker["Tracked feature and tasks<br/>acceptance · dependencies · resources"]
Execute["Startup Factory execution<br/>packets · branches · worktrees · dispatch"]
Methods["Claude-local Superpowers methods<br/>TDD · debugging · review response · verification"]
Review["Exact-package review board<br/>Lead · Principal · Sceptical · Security"]
Integrate["Serialized integration<br/>validated feature branch"]
Release["Protected CI and release<br/>policy · approval · deploy · verify"]
Idea --> Brainstorm --> Plan --> Handoff --> Shape --> Tracker --> Execute
Execute --> Methods --> Review --> Integrate --> Release
Why divide the lifecycle
| Reason | Benefit |
|---|---|
| One authority per stage | The specification has one source, the tracker has one workflow owner, each task has one active attempt, the feature branch has one integrator, and production has one protected release executor. |
| Methodology stays separate from orchestration | Superpowers can improve how Claude thinks, plans, tests, and debugs without competing with Startup Factory's scheduler, worktrees, review board, tracker writers, or release transaction. |
| Different scopes get different tools | Superpowers is excellent at the local reasoning loop around one design or task. Startup Factory governs the wider system of roles, dependencies, concurrent work, artifacts, statuses, and environments. |
| Independent models remain independent | Claude may shape the plan, while Codex, Gemini, or another model can challenge architecture, implement, review, or test without receiving Claude-only Superpowers instructions. |
| Planning remains challengeable | A polished plan is evidence, not authority. Product and both architects still test its scope, acceptance criteria, interfaces, risks, dependencies, and delivery order before work is created or dispatched. |
| Recovery becomes durable | Superpowers provides strong session-level discipline; Startup Factory adds tracker history, immutable packets, attempt identity, event journals, idempotent outboxes, resumable integration, and restart-safe production transactions. |
| The integration is reversible | USE_SUPERPOWERS=false removes all Superpowers-specific wiring without changing the Startup Factory lifecycle, tracker model, team topology, or release controls. |
SDLC responsibility map
| SDLC stage | Superpowers contribution | Startup Factory contribution | Primary owner in this integration |
|---|---|---|---|
| Idea discovery | Socratic clarification, one question at a time, alternative approaches, trade-offs, incremental user approval | Product context, repository constraints, explicit scope and NOT-in-scope | Superpowers, with human approval |
| Specification | Writes and self-checks the design document; requires the user to review the written spec | Product Manager and architects challenge completeness, boundaries, risks, and acceptance criteria | Superpowers produces; Startup Factory accepts or pushes back |
| Implementation planning | Produces detailed tasks with exact files, interfaces, code steps, test commands, expected results, and no placeholders | Converts the plan into independently reviewable vertical slices, dependencies, tracks, resources, and model profiles | Shared handoff; Startup Factory owns executable project structure |
| Tracker and portfolio management | Not used as the project control plane | Creates [features] and [tasks], owns legal statuses, routing, progress, digests, automation scope, and generations |
Startup Factory |
| Per-task design | May inform the proposed implementation | Requires implementer design notes, contract registration, and independent Principal + Sceptical approval before code | Startup Factory |
| Implementation | TDD and disciplined small-step engineering methods inside a Claude task | Selects the worker/model, creates immutable packets and isolated attempts, enforces scope, and records evidence | Startup Factory orchestrates; Superpowers improves the local method |
| Debugging | Root-cause investigation, pattern comparison, one hypothesis at a time, regression test, fresh verification | Task-scoped stop/retry/escalation, durable evidence, attempt recovery, and architectural re-review when needed | Shared: Superpowers method inside Startup Factory boundaries |
| Code review | Helps a worker receive feedback technically and verify fixes | Four independent, commit-bound verdicts over one exact review package, plus optional QA and specialist evidence | Startup Factory |
| Integration | Upstream Superpowers has branch-finishing workflows, but they are not invoked here | The integrator alone validates and writes the feature branch; brokered transactions make retries idempotent | Startup Factory |
| CI, release, and production | No production authority in this integration | Exact-commit protected CI, policy checks, approval binding, isolated credentials, plan/apply/status/verify hooks, rollback, and Live transition |
Startup Factory |
| Operations and recovery | Session-level verification discipline | Portfolio reconciliation, human [Blocked] locks, stale-worker fencing, release recovery, and auditable tracker projections |
Startup Factory |
Where Superpowers is strongest
- Design before code. Its
brainstormingskill explores the repository, asks focused questions, compares approaches, validates the design section by section, writes the specification, performs a consistency/ambiguity review, and waits for user approval. - Plans that another engineer can execute.
writing-plansinsists on exact paths, explicit interfaces, complete steps, concrete test commands, expected outcomes, small commits, TDD ordering, and noTBDor “similar to the previous task” shortcuts. - Strict engineering habits.
test-driven-developmentenforces a real red-green-refactor loop;systematic-debuggingrequires root-cause evidence before fixes; andverification-before-completionrequires fresh command output before a success claim. - Useful local review discipline.
receiving-code-reviewhelps a Claude worker evaluate feedback technically, clarify uncertainty, fix one issue at a time, and verify the result instead of responding performatively.
Those strengths are intentionally used as planning inputs and task-local methods. They do not grant tracker, scheduler, integration, or production authority.
Where Startup Factory is strongest
- Cross-functional governance. Product, Team Lead, Principal Architect, Sceptical Principal Architect, Security, implementation, QA, integration, and release have explicit and non-interchangeable responsibilities.
- Multi-model independence. Assign different model families to design, challenge, implementation, and review so one model's blind spot does not silently become the team's consensus.
- Deterministic execution. The dispatcher—not an LLM—selects eligible work from tracker state, dependencies, resource conflicts, design approvals, risk, and capacity.
- Isolation and recoverability. Every attempt gets an immutable task packet containing the complete current tracker comment history, a collision-safe branch, separate worktree, report path, event history, and authenticated publication capability.
- Review and integration integrity. Four distinct reviewers decide against the same exact package. No approval survives changed code, and only the integrator writes the feature branch.
- Human and production safety.
[Blocked]is a human-controlled task lock. Production requires protected CI evidence, policy-clean plans, exact external authority where configured, isolated credentials, target verification, and a durable transaction. - End-to-end visibility. The project-management tool remains the durable
record from idea and acceptance criteria through findings, rework,
integration, deployment, and
Live.
Execution workflows that must not overlap
Upstream Superpowers includes excellent execution workflows for projects that use Superpowers alone. Startup Factory replaces these at the orchestration layer for a feature delivered by a Startup Factory team:
| Superpowers workflow | Startup Factory owner used instead |
|---|---|
using-git-worktrees |
Per-attempt worktrees created and retired by launch-team.sh |
subagent-driven-development / executing-plans |
Tracker-driven task packets and deterministic dispatch.sh scheduling |
requesting-code-review as the authoritative gate |
Four-party exact-package Startup Factory review board |
finishing-a-development-branch |
Serialized integrator plus protected release lifecycle |
Do not run both execution systems on the same feature. Two schedulers cannot safely share task identity, branches, worktrees, review state, or completion authority.
When to use which mode
| Mode | Best fit |
|---|---|
| Superpowers + Startup Factory | A meaningful Claude-planned feature that should become tracked, independently challenged, implemented by a team, reviewed, integrated, and potentially delivered to production. |
| Startup Factory alone | Non-Claude runtimes, an already-approved specification, operational/release work, or any project that wants native planning without the Superpowers dependency. |
| Superpowers alone | A local coding session where you explicitly want the upstream Superpowers execution workflow and do not launch a Startup Factory team for the same work. |
How to use the combined workflow
The example below uses Claude Code for planning and a Startup Factory team for delivery. Upstream Superpowers supports other coding agents too, but this integration is intentionally enabled by default only for Claude Code.
-
Install both systems and create the feature branch that will become the Startup Factory team name:
# In Claude Code: /plugin install superpowers@claude-plugins-official # In your project shell: SF_HOME=.claude/skills/startup-factory git switch -c payments-revamp
-
Keep the default planning configuration, or inspect it before starting:
USE_SUPERPOWERS=true SUPERPOWERS_PLUGIN_ID=superpowers@claude-plugins-official SUPERPOWERS_SPEC_ROOT=docs/superpowers/specs SUPERPOWERS_PLAN_ROOT=docs/superpowers/plans
truemeans “Claude is eligible,” not “enable Superpowers for every model.” Codex, Gemini, and unmarked harnesses stay on the native workflow. -
Verify that Claude can use the configured plugin:
python3 "$SF_HOME/bin/superpowers-planning.py" preflight --runtime claude
-
Ask Claude to shape the ticket, and make the ownership boundary explicit:
Use superpowers:brainstorming to shape this feature. Explore the repository, clarify scope and success criteria, compare approaches, and write the approved specification. After I approve the written spec, use superpowers:writing-plans to create the detailed implementation plan. Stop after the committed specification and plan. Do not use Superpowers worktrees, subagent-driven-development, executing-plans, code-review orchestration, or branch-finishing. Startup Factory will own execution.
-
Review the generated documents. They normally live under:
docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md
Both files must be committed. If either changes later, commit the change, recreate the handoff, and repeat any affected planning approvals.
-
Bind the exact documents to the Startup Factory team:
TEAM=payments-revamp FEATURE_ID=ENG-100 SPEC=docs/superpowers/specs/2026-07-16-payments-revamp-design.md PLAN=docs/superpowers/plans/2026-07-16-payments-revamp.md "$SF_HOME/bin/launch-team.sh" planning-handoff \ "$TEAM" "$SPEC" "$PLAN"
-
Let Startup Factory review and operationalize the handoff. The Product Manager, Team Lead, Principal Architect, and Sceptical Architect still approve scope, acceptance criteria, contracts, dependencies, risks, vertical slices, and execution order before implementation.
A suitable instruction to the Startup Factory agent is:
Use the validated planning handoff for payments-revamp as planning evidence. Review it with the Product Manager, Team Lead, Principal Architect, and Sceptical Architect. Resolve pushback, then create or update ENG-100 and its vertical-slice tasks with acceptance criteria, dependencies, tracks, files, resources, and model profiles. Startup Factory owns all execution.
-
Launch the normal Startup Factory delivery:
"$SF_HOME/bin/launch-team.sh" preflight "$TEAM" "$FEATURE_ID" "$SF_HOME/bin/launch-team.sh" gate-team full-stack "$TEAM" "$FEATURE_ID" "$SF_HOME/bin/dispatch.sh" "$TEAM" "$FEATURE_ID" --watch
Direct
claudecommands inconfig/team.config.mdare recognized automatically. Mark a Claude wrapper explicitly:FRONTEND_CMD="STARTUP_FACTORY_LLM_RUNTIME=claude /path/to/claude-wrapper {prompt_file}"In harness mode, declare Claude while composing:
STARTUP_FACTORY_LLM_RUNTIME=claude \ "$SF_HOME/bin/launch-team.sh" compose "$TEAM" "$FEATURE_ID" team-lead full-stack
-
To return completely to native Startup Factory planning, edit
config/planning.config.md:USE_SUPERPOWERS=false
For the exact machine-enforced boundary, see
reference/superpowers-planning.md.
Full transparency in your tracker
Startup Factory treats the tracker as the durable collaboration surface, not a status board updated after the real work happened. The local runtime makes coordination fast, but the information a human needs to supervise delivery is projected back into the configured tool.
| You can inspect | How it stays visible |
|---|---|
| Scope and execution order | [features], [tasks], dependencies, resource declarations, and legal board transitions |
| Design decisions | Structured design notes, pushback, approvals, conditions, and numbered architecture checklists |
| Live progress | A mechanically updated [progress] record on every task and a compact [digest] across the feature |
| Validation and review | Evidence records, changed-file lists, review findings, exact artifact paths, and explicit NOT validated declarations |
| Blockers and human decisions | Proven blocked-by relationships plus escalations with a question, options, and a default if you are unavailable |
| Release-policy denials | Idempotent [DENIED ACTION] audit comments for normalized production plans; other preflight refusals remain in protected runtime logs |
| Delivery | The integrated commit, completed validation gates, generic [Ready to deploy] (shipped as Ready for production), protected green CI proof, and an idempotent [deployment] projection through verified production and Live |
Use as much of the system as your project needs:
| Layer | What it gives you | Where |
|---|---|---|
| 1. PM port | One AI agent creates/tracks/completes [features] and [tasks] in any configured tracker through one tool-agnostic workflow. |
SKILL.md, reference/, adapters/ |
| 2. Governed squad | A lead coordinates, two independent architects gate design, specialists implement, and four distinct agents—the Team Lead, both architects, and Senior Security Engineer—must approve the exact review package before the integrator alone writes the feature branch. | reference/orchestration.md, roles/ |
| 3. Task-driven runtime | Event-driven dispatch, bounded parallel waves, model routing, exact review packages, durable handoffs, and recoverable integration. | bin/dispatch.sh, bin/runtime-state.py, bin/integrate-task.sh |
| 4. Preset teams | Six ready-made rosters for full-stack, backend, frontend, security, infrastructure, and LLM/data-science work, all resolved through the same team launcher. | teams/, bin/launch-team.sh |
| 5. Portfolio automation | One bounded cron/service pass observes generic queued/blocked statuses, bootstraps only queued feature runs, and reconciles comments, task holds, and team actions. | bin/pm-agent.py, reference/automation.md |
| 6. Safe production delivery | Structured provider-neutral plan/apply/status/verify hooks, hard guardrails, isolated credentials, crash recovery, and bounded rollback. | bin/release-feature.py, bin/policy-check.py, reference/deployment.md |
Everything is inspectable: plain Markdown, shell scripts, small Python utilities,
and git. There is no application server or coordinator database to host;
schedulers invoke bounded scripts, and --watch is an optional foreground
clock owner. The system is language-, framework-, tracker-, and LLM-agnostic
because it manages the delivery contract around the code rather than assuming
anything about the stack.
Choose your operating mode
Adopt only the layers you need; each mode keeps the same vocabulary and tracker history.
| Your goal | Runtime shape | Start here |
|---|---|---|
| Give one agent a reliable PM workflow | Your existing agent reads SKILL.md; no daemon, external tracker, or team launcher is required. |
Two-minute offline quick start |
| Launch a governed specialist team | The launcher and dispatcher coordinate task-scoped workers, gate roles, isolated worktrees, and serialized integration. | Run a whole team |
| Continuously pull work from the board | Cron, a service timer, or a hosted scheduler invokes one bounded deterministic pm-agent.py --once pass. |
Automate the board |
| Deploy approved work to a production target | A protected deterministic executor runs digest-pinned provider hooks with isolated credentials and independent verification. | Configure production delivery |
Requirements
Minimum (single agent): a git repository, a POSIX shell, and any agentic LLM
CLI or IDE that can read files (Claude Code, Codex CLI, Gemini CLI, Aider,
Cursor, Windsurf, Cline, …). The release installer runs as an isolated Python
tool through uvx (or pipx) and does not require Homebrew, Node.js, git, or
rsync. The auditable shell compatibility path uses curl, git, and rsync.
For multi-agent teams, additionally: the launcher (bin/launch-team.sh) needs
bash + git; every implementation task uses a task branch and isolated
worktree. tmux is optional but recommended — without it, agents run as
background processes. Autonomous protocol gates additionally require a real
OS/container sandbox that hides Git-common-dir broker capability state and other
process environments from agent roles; Unix file modes alone do not isolate
same-UID processes. Configure that protected external executable as
AGENT_SANDBOX_RUNNER before enabling autonomous execution.
Tracker access is optional. The default Markdown tracker stores everything
in local files, so you can run the whole thing offline. Connect Linear/Jira/GitHub
when you're ready—via MCP, REST, or the gh CLI, depending on the adapter.
For cron/service automation: use one scheduler instance and a scriptable, explicitly scoped adapter (REST/CLI/files; a cron process cannot invoke an MCP client). The scan observes queued and Blocked work, but only queued work bootstraps or launches. Registered runs are re-authorized on every pass through an exhaustive per-feature export. Production delivery additionally needs protected external structured hooks/config/state, an external identity/isolation attestor for automatic mode, and a separate short-lived credential environment that ordinary agents never inherit.
The human-only exit from [Blocked] also needs an operator-owned control in the
project-management tool: restrict outbound Blocked transitions to human
principals and deny them to every scheduler, bot, and service identity. Startup
Factory refuses its own outbound writes, but normalized adapters do not prove
who performed an external transition. If the tool cannot enforce status-level
permissions or provide verified transition provenance, treat the human-only
claim as an operational policy and keep autonomous portfolio automation disabled
for that tool.
Quick Start (2 minutes, no accounts)
The fastest win: one AI agent managing work in local Markdown files. No tracker
account, API key, Homebrew formula, or global package is required—Markdown is
the default.
-
From your project root, install the complete, versioned release bundle. Codex and Aider use the shared Agent Skills project directory:
uvx startup-factory@latest install --agent codex
For Claude Code use
--agent claude-code. Pin a release in controlled environments, for examplestartup-factory@0.1.1.uvxcreates an isolated environment for the installer and leaves no Startup Factory package in your project environment.The
uvxpath downloads the published PyPI package. For a Git checkout or offline use, use the auditable shell compatibility path.This quick start demonstrates the one-agent workflow. Set
TEAM_MODE=falsein the installedconfig/project-management.config.mdbefore continuing; fresh installations otherwise use the team workflow by default. -
Ask your agent, in plain language:
Plan a feature: add CSV export to the reports page.The skill creates a
[feature]and a handful of[tasks]as Markdown files under.workspace/task-manager/. Then drive them:Start task 1. → moves it to [Active], implements it Send task 1 to review. Finalize task 1. → verified, committed + [Ready to deploy]
That's the whole loop — plan → start → review → complete — in generic vocabulary that works identically on every tracker. When you're ready for a real tracker or a full team, keep reading.
Sanity-check the runtime (no LLM calls, no cost): from the installed skill directory,
bash tests/run-all.shshould finish withALL TESTS PASS.
Install into your repository
Use a project-scoped copy. Startup Factory contains mutable tracker, team, automation, deployment, and guardrail configuration, so one global copy should not be shared across unrelated projects. Homebrew would still need a second project-initialization step and is intentionally not part of the current distribution.
Choose the project path your agent supports:
| Agent | Project install directory | Discovery |
|---|---|---|
| Codex | .agents/skills/startup-factory |
Native project skill path |
| Claude Code | .claude/skills/startup-factory |
Native project skill path |
| Aider | .agents/skills/startup-factory |
Start with aider --read .agents/skills/startup-factory/SKILL.md |
| Other agents | Their native project skill directory | Use native discovery or point the agent at SKILL.md |
The release package embeds one deterministic bundle built from an exact Git commit. The installer verifies every archived path, size, mode, and SHA-256 digest before planning a destination change, then records the installed version, source commit, archive digest, and ownership policy locally.
# One-shot isolated install
uvx startup-factory@latest install --agent codex
# Claude Code
uvx startup-factory@latest install --agent claude-code
# Alternative isolated runner
pipx run startup-factory install --agent codex
# Persistent operator CLI
uv tool install startup-factory
startup-factory install --agent codex
Use an exact version instead of @latest in controlled environments. Package
index mirrors work through normal uv/pipx configuration; installation
semantics are not tied to a cloud, project-management tool, or deployment
provider.
For an explicit path instead of an agent mapping:
uvx startup-factory@latest install \
--install-dir /absolute/path/to/startup-factory
Shell compatibility path
Until the first package release, or on a host without uv/pipx, use the
auditable updater. The unique temporary file is removed automatically, and a
failed download cannot execute a stale installer:
SF_INSTALL_DIR=.agents/skills/startup-factory
(
set -eu
installer="$(mktemp "${TMPDIR:-/tmp}/startup-factory-install.XXXXXX")"
trap 'rm -f "$installer"' EXIT
curl -fsSLo "$installer" \
https://raw.githubusercontent.com/alexrolls/startup-factory/main/bin/update-installed-skill.sh
# Optional audit: less "$installer"
bash "$installer" --install-dir "$SF_INSTALL_DIR"
)
If you already cloned or downloaded Startup Factory, skip curl and run its
local bin/update-installed-skill.sh with the same --install-dir argument.
The compatibility script fetches the complete repository bundle—not just
SKILL.md.
Why the README does not currently use
npx skills add: the open Skills CLI is the right long-term direction and correctly discovers this repository. However, its current remote repository-root installation path copies only the rootSKILL.md. Startup Factory also requiresbin/,config/,adapters/,extensions/,reference/,roles/, andteams/; an end-to-end installation without them is broken. Until a lean nested distribution is published, do not usenpx skills addornpx skills updatefor Startup Factory.
Safe updates
Preview and apply an update with the same release CLI. It recognizes the selected project installation and performs a complete preflight before any destination mutation:
uvx startup-factory@latest update --agent codex --dry-run
uvx startup-factory@latest update --agent codex
For Claude Code, use --agent claude-code. You can also ask your agent:
Fetch latest Startup Factory skill.
Existing project configuration remains byte-for-byte untouched by default,
while newly introduced config files are installed. Destination-only files under
the documented adapters/, extensions/, and teams/ extension points are
also preserved. A generated ownership manifest lets later updates delete an
upstream extension that has been retired without mistaking project-owned files
for upstream files. A legacy installation without a manifest is migrated
conservatively: destination-only extension files are kept. If a later upstream
release introduces a file at a project-owned extension path, the update fails
before mutation instead of overwriting it:
config/project-management.config.mdconfig/planning.config.mdconfig/team.config.mdconfig/statuses.config.jsonconfig/automation.config.jsonconfig/deployment.config.jsonconfig/guardrails.config.json
To intentionally replace those files with upstream defaults too:
uvx startup-factory@latest update --agent codex --overwrite-config
To verify the owned runtime independently of preserved configuration and custom extensions:
uvx startup-factory@latest verify --agent codex
The release CLI uses a sibling staging directory, an installation lock, and a backup swap with rollback. Interrupted copying cannot silently turn a valid installation into a partial one. Its main operator options are:
| Option | Purpose |
|---|---|
--agent codex|claude-code|aider |
Select the native project skill directory. |
--project PATH |
Resolve the agent directory relative to another project. |
--install-dir PATH |
Override the mapped installation directory. |
--bundle PATH |
For install/update, use an explicitly supplied local canonical archive. |
--overwrite-config |
For install/update, replace all seven preserved project configuration files. |
--dry-run |
For install/update, print the plan without writing the destination or lock. |
--json |
Emit machine-readable output for operator automation. |
Legacy/source-installed copies can continue to use the shell compatibility updater from their installed bundle:
bash .agents/skills/startup-factory/bin/update-installed-skill.sh --dry-run
bash .agents/skills/startup-factory/bin/update-installed-skill.sh
It requires git and rsync, accepts --remote-url and --ref, and defaults
to main; prefer a reviewed tag or exact commit. The release CLI instead binds
its embedded bundle version and source commit to the Python package version.
The shell updater intentionally refuses any installation containing
.startup-factory-install.json or .startup-factory-bundle.json: synchronizing
a mutable Git checkout over a release-managed copy would destroy verifiable
provenance. Update those copies only through uvx, pipx, or another isolated
runner for the versioned startup-factory package.
Before synchronizing, the installer verifies the fetched bundle and refuses
filesystem root, the home directory, a Git repository root, symlink targets,
and unrelated non-empty directories. --dry-run never creates a missing
destination.
Release provenance
packaging/build_bundle.py constructs the canonical archive from Git object
bytes at an exact commit—not from an uncommitted checkout—and normalizes archive
ordering, timestamps, ownership, and modes. Release CI builds it twice and
requires byte-identical output, embeds those exact bytes in the wheel and source
distribution, exercises the built wheel, generates GitHub provenance
attestations, and publishes through PyPI Trusted Publishing. The GitHub Release
is created from the same already-tested artifacts; nothing is rebuilt during
publication.
Before the first release, a maintainer must register the startup-factory PyPI
Trusted Publisher for .github/workflows/release.yml, create a protected
pypi GitHub Environment with required human approval, protect v* tags from
unauthorized creation, force-update, and deletion, and enable immutable GitHub
Releases. A vX.Y.Z tag is accepted only when it exactly matches the version
in pyproject.toml and its commit belongs to main.
Multi-agent teams require the target project to be a git repository because
every implementation attempt receives a task branch and git worktree. The skill
bundle may live inside that repository for interactive/manual use; autonomous
automation instead requires a reviewed, protected external installation. Use
the same installer with an absolute operator-owned destination outside the
checkout and every agent mount. Add .teamwork/
and .workspace/ to the target repository's root .gitignore—ignore rules
inside a nested skill installation do not cover project-root runtime paths.
Two execution modes (config/team.config.md → EXECUTION) share the same
task-branch/worktree isolation: sequential runs one task worker at a time;
parallel dispatches dependency/resource-safe waves, bounded by
MAX_ACTIVE_IMPLEMENTERS (default 2 when unset). Gate roles and integration
remain serialized where required.
Connect your LLM
There are two modes, and they connect to your LLM differently.
Single agent — nothing to connect
You already run an agent (Claude Code, Codex, …). The skill is instructions that agent reads, so there is no separate connection: install the bundle and talk to your agent normally. Your existing LLM credentials are used as-is.
Multi-agent teams — map each role to a CLI command
config/team.config.md is the entire LLM coupling: one line per role giving
the shell command that runs that role. The launcher composes each agent's startup
prompt into a file and substitutes its path for {prompt_file}.
Every cross-functional preset requires a Sceptical Architect. Its protocol
mapping, roster entry, role brief, and command are validated before any team
process starts; SCEPTICAL_ARCHITECT_CMD=null is a configuration error, not an
opt-out.
TEAM_LEAD_CMD="claude -p \"$(cat '{prompt_file}')\" --permission-mode acceptEdits"
PRINCIPAL_ARCHITECT_CMD="claude -p \"$(cat '{prompt_file}')\" --permission-mode acceptEdits"
SCEPTICAL_ARCHITECT_CMD="codex exec --full-auto \"$(cat '{prompt_file}')\""
BACKEND_CMD="codex exec --full-auto \"$(cat '{prompt_file}')\""
REVIEWER_CMD="gemini --yolo \"$(cat '{prompt_file}')\""
TEAM_DEFAULT_CMD="claude -p \"$(cat '{prompt_file}')\" --permission-mode acceptEdits"
Command templates for common CLIs:
| LLM / CLI | Command template |
|---|---|
| Claude Code | claude -p "$(cat '{prompt_file}')" --permission-mode acceptEdits |
| Codex CLI | codex exec --full-auto "$(cat '{prompt_file}')" |
| Gemini CLI | gemini --yolo "$(cat '{prompt_file}')" |
| Any file-reading CLI | yourcli --prompt-file {prompt_file} |
Direct claude commands are detected automatically. If Claude is behind a
wrapper, mark only that command template so mixed-model teams remain precise:
FRONTEND_CMD="STARTUP_FACTORY_LLM_RUNTIME=claude /path/to/claude-wrapper {prompt_file}"
Mixing LLMs is the design intent — e.g. Claude to lead and own the primary architecture position, Codex to challenge it independently and implement, and Gemini to review. Use different model families for the two architects when possible to reduce correlated reasoning errors. Same-LLM teams still work.
Optional TASK_FAST_CMD, TASK_STANDARD_CMD, and TASK_STRONG_CMD overrides
route individual task packets by explicit model-profile:, conservative risk
classification, or a bounded low-risk fast path for documentation, formatting,
and structurally small test/config tasks. Missing overrides fall back to the
role command.
Harness mode — teammates as subagents, no CLI processes
If your harness can spawn subagents and message them (e.g. Claude Code's Agent
tool), skip the command map entirely: compose each role's startup prompt with
bin/launch-team.sh compose <team> <featureId> <role> [preset] and spawn the
role natively with it. Harness messages replace mailboxes, harness idle
notifications replace heartbeats, and the tracker stays the source of truth —
see reference/orchestration.md → Harness mode.
When the harness runtime is Claude Code, declare it while composing so the default-on Superpowers integration is included:
STARTUP_FACTORY_LLM_RUNTIME=claude \
bin/launch-team.sh compose <team> <featureId> <role> [preset]
Omit the variable for Codex, Gemini, and other runtimes.
Command resolution per role: explicit <ROLE>_CMD value → used; <ROLE>_CMD=null
→ role disabled; absent → falls back to TEAM_DEFAULT_CMD. That fallback is
why the many specialized preset-team roles need no per-role keys — set
TEAM_DEFAULT_CMD once and only override the roles you want on a different model.
⚠️ Safety: those templates use auto-approve flags (
acceptEdits,--full-auto,--yolo) so agents can work unattended. Workers may commit untrusted checkpoints only to task branches; only the integrator writes the feature branch. Every implementer is isolated in its own git worktree — but still run teams on a branch you can throw away, and review the tracker before merging to your main branch.
Connect your tracker
Pick one tracker in config/project-management.config.md:
PRODUCT_MANAGEMENT_TOOL=Markdown # or Linear, Jira, GitHubIssues
Then wire its access (skip entirely for Markdown):
| Tracker | Access options | What to set |
|---|---|---|
| Markdown | none — local files | MARKDOWN_ROOT (default .workspace/task-manager) |
| Linear | MCP or REST API key | LINEAR_ACCESS=mcp|rest; for rest, export LINEAR_API_KEY |
| Jira | MCP or REST API token | JIRA_ACCESS=mcp|rest, exact JIRA_PROJECT_KEY and child JIRA_TASK_ISSUE_TYPE; for rest, export JIRA_BASE_URL, JIRA_EMAIL, JIRA_API_TOKEN |
| GitHub Issues | gh CLI or GitHub MCP |
GITHUB_REPO (explicitly required for automation; interactive use may infer from git remote), GITHUB_USE_MCP |
The REST/API-key paths mean harnesses without an MCP client (Codex, Aider,
plain scripts) are first-class. Each adapters/<Tool>.md has an Access
mechanisms section with the exact setup (MCP, REST/curl, gh, or local-file
instructions as appropriate).
Scriptable remote operations have a 60-second inner deadline by default;
operators may set TRACKER_OPERATION_TIMEOUT_SECONDS to an integer from 1
through 300, while automation's operationTimeoutSeconds remains the outer
process-group bound.
Credentials live in environment variables, never in the config files. Once
access is configured, switching among shipped adapters is a one-line change to
PRODUCT_MANAGEMENT_TOOL; no workflow, prompt, or role brief mentions a tracker
by name. A new tool also needs its adapter contract and deterministic
tracker-ops.sh backend before unattended dispatch or automation can use it.
Configure
Core operation uses three files. Autonomous operation adds three fail-closed JSON templates. Project policy stays versioned; an enabled deployment config is instead copied to operator-protected storage outside agent mounts.
config/project-management.config.md — the tracker
| Key | Meaning | Default |
|---|---|---|
PRODUCT_MANAGEMENT_TOOL |
Active tracker (matches an adapters/<Name>.md) |
Markdown |
| per-tool block | Access mode + defaults for the active tracker (see above) | — |
TEAM_MODE |
true enables the multi-agent status-ownership model; set false for the single-agent workflow |
true |
STRICT_STATUS |
true = refuse an action if a [task] isn't in the expected status (the "andon cord") |
true |
Team mode is enabled in new installations. Set
TEAM_MODE=falseto opt into the single-agent workflow.
config/planning.config.md — optional Claude planning intake
| Key | Meaning | Default |
|---|---|---|
USE_SUPERPOWERS |
Make Claude Code eligible for obra/superpowers brainstorming and plan-writing; non-Claude runtimes stay native |
true |
SUPERPOWERS_PLUGIN_ID |
Required Claude Code plugin id checked by the planning preflight | superpowers@claude-plugins-official |
SUPERPOWERS_SPEC_ROOT |
Repository-relative root for approved specifications | docs/superpowers/specs |
SUPERPOWERS_PLAN_ROOT |
Repository-relative root for approved implementation plans | docs/superpowers/plans |
Run python3 bin/superpowers-planning.py preflight --runtime claude before the
Claude planning stages, then
bin/launch-team.sh planning-handoff <team> <spec-path> <plan-path> before
launching the Startup Factory team. Set USE_SUPERPOWERS=false to remove all
Superpowers-specific prompt wiring. With the default true, only commands
classified as Claude receive that wiring. See
Superpowers + Startup Factory
for the end-to-end workflow and SDLC ownership map.
Configure your board
config/statuses.config.json defines both state machines: every status, legal
transitions, owner, and per-tracker tool mapping. The internal task flow is
Planned → Active → Review → Ready to deploy, shipped to project tools as
ToDo → In Progress → In Review → Ready for production; Blocked is the
task-scoped human-held state. Review findings move the task from Review back
to Planned/ToDo, and the dispatcher starts a fresh implementation attempt
that returns through In Progress. The listed outbound transitions normalize
human project-management actions; Startup Factory itself cannot author them.
The internal feature flow is Planned → Active → Resolved, shipped with
Resolved mapped to Live. Add, rename, or remove
statuses by editing the JSON, then run bin/launch-team.sh validate-board to
check the structural graph, reachability, owners, and marker roles. Separately
verify that your active adapter maps every status to a real tracker state (the
Markdown tracker needs nothing).
On the shipped board, only the deterministic release-executor owns terminal
feature status Resolved; disabled or unverified delivery remains non-terminal.
config/team.config.md — the team (only for multi-agent)
| Section | Keys | Purpose |
|---|---|---|
| Role → command | TEAM_LEAD_CMD, PRINCIPAL_ARCHITECT_CMD, SCEPTICAL_ARCHITECT_CMD, SENIOR_SECURITY_ENGINEER_CMD, INTEGRATOR_CMD, BACKEND_CMD, FRONTEND_CMD, QA_CMD, REVIEWER_CMD, TEAM_DEFAULT_CMD |
Which CLI runs each role (see above) |
| Task model routing | TASK_FAST_CMD, TASK_STANDARD_CMD, TASK_STRONG_CMD |
Optional task-level command overrides selected from packet metadata and conservative risk classification; each falls back to the role command |
| Coordination | TEAMWORK_ROOT (.teamwork), AGENT_ENV_ALLOWLIST (non-secret minimum), POLL_INTERVAL_SECONDS (120), STUCK_AFTER_MINUTES (15), ESCALATE_AFTER_ATTEMPTS (2), TRACKER_WRITERS (broker), EXECUTION (sequential), MAX_ACTIVE_IMPLEMENTERS (null) |
Canonical symlink-free workspace paths; LLMs start with env -i; deterministic broker keeps tracker credentials out of every LLM role; event-driven supervision with polling fallback; bounded sequential/parallel scheduling |
| Worktree provisioning | WORKTREE_SETUP |
Non-empty setup command run once inside every fresh task worktree through the same sandbox boundary; autonomous mode rejects null/no-op provisioning. |
| Agent isolation | AGENT_SANDBOX_RUNNER, AGENT_SANDBOX_ENFORCED |
Protected external runner --workdir ABSOLUTE -- /usr/bin/env -i … boundary. The runner, not Startup Factory code, must enforce filesystem, process, network, and identity isolation. |
| Lifecycle authority | BROKER_LIFECYCLE_ROOT |
Absolute protected external mode-0700 root for HMAC-authenticated PID/start/tmux identities. Without it, manual processes are unmanaged and stop refuses to signal. |
| Validation | VALIDATE_BUILD, VALIDATE_TEST, VALIDATE_LINT, VALIDATE_FORMAT, VALIDATE_SCRIPT |
Your stack's commands; the integrator runs them before every merge (null = skip). VALIDATE_SCRIPT replaces all four with one repo-owned script that receives the changed-file list |
Point the VALIDATE_* commands at your real build/test/lint (e.g.
VALIDATE_TEST="pytest") — this is the only place the framework-agnostic
integrator learns about your stack.
Automation, deployment, and guardrails
| File | Purpose | Safe default |
|---|---|---|
config/automation.config.json |
Scan cadence, separate observation/launch kinds, task-hold policy, run cap, branch/worktree root, allowed/default team presets | enabled: false |
config/deployment.config.json |
Disabled template for protected external target/state paths, trusted base, code/hook pins, positive environment boundaries, protected CI/attestation/approval hooks, and timeouts | enabled: false, approval-required |
config/guardrails.config.json |
Project additions to the built-in immutable deny policy and automatic cost/change limits | Zero cost delta; cannot weaken built-ins |
Board automation configuration
Copy config/automation.config.json to
protected external storage before enabling it. The scheduler reads these keys:
| Key | Shipped value | Meaning |
|---|---|---|
schemaVersion |
1 |
Configuration schema; unknown versions fail closed. |
enabled |
false |
Master switch. A disabled pass launches nothing. |
trustedPath |
/usr/bin:/bin |
Absolute protected command-search directories used by the scheduler. |
scanIntervalMinutes |
3 |
Board scan interval, from 1 through 1440 minutes. Omit it to retain the three-minute default. Legacy pollSeconds is accepted only when this key is absent. |
leaseSeconds |
900 |
Single-host pass lease and bounded stale-recovery window; integer 5–86400. |
operationTimeoutSeconds |
120 |
Outer deadline for each adapter, launcher, and dispatcher child process; integer 5–3600. |
releaseTimeoutSeconds |
7200 |
Separate outer deadline for the complete release transaction; integer 60–86400 and at least the conservative full hook-path bound. |
maxFeaturesPerPass |
2 |
Maximum new feature runs bootstrapped in one pass, from 1–1000; existing runs reconcile first. The omission fallback is 1. |
requireAgentSandbox |
true |
Mandatory invariant; false or missing is rejected. |
requireSingleTrackerWriter |
true |
Mandatory invariant requiring deterministic broker writes. |
observeStatusKinds |
queued, blocked |
Exact adapter-neutral kinds to observe. The shipped project mapping is ToDo and Blocked; observation is not launch authority. |
launchStatusKinds |
queued |
The only kind eligible for a new automatic launch. [Blocked] is observed solely to enforce its hold. |
blockedTaskPolicy |
task-scoped, human exit, no automatic resume | Fixed fail-closed policy: continue independent work, refresh all communication, propagate only lead-confirmed direct dependencies, and use a fresh attempt after human resume. Missing, unknown, or weaker values are rejected. |
ignoredTaskLabels |
human-work |
Case-insensitive tracker labels that reserve a task for people. New matching tasks are never claimed or launched; if the label appears mid-flight, the next reconcile stops/fences that task while independent work continues. Removing it restores normal status-specific handling on the next scan. |
reconcileRegisteredRuns |
true |
Re-export and re-authorize every unfinished registered feature on each pass. |
baseRef |
main |
Feature-run starting ref whose resolved base commit is recorded immutably. Production provenance is anchored separately by deployment trustedBaseRef. |
branchPrefix |
factory- |
Prefix for generated feature branches. External IDs are hashed before use in paths or refs. |
workspaceRoot |
.teamwork/pm-agent |
Repository-relative supervisor workspace and registry root. |
defaultTeamPreset |
full-stack |
Team used when eligible metadata contains no explicit preset. |
allowedTeamPresets |
all six shipped presets | Exact routing allowlist. Unknown or changed routing pauses the run. |
requireMetadataOptIn |
false |
When false, every non-ignored queued task is eligible by default. Set true to additionally require an explicit latest automation: enabled marker. |
metadata.optInKey |
automation |
Adapter-neutral description/comment key for enablement. |
metadata.teamPresetKey |
team-preset |
Adapter-neutral description/comment key for specialist-team routing. |
--print-cron supports stable minute intervals that divide 60 and whole-hour
intervals that divide 24. Use a service timer or hosted scheduler for other
valid intervals, and configure its equivalent of “forbid overlapping runs.”
The filesystem lease covers one host only.
Production delivery configuration
Start with the disabled
config/deployment.production.approval-required.example.json,
copy it outside the repository and every agent mount, then configure the exact
target and protected hooks.
{
"enabled": false,
"mode": "approval-required",
"environment": "production",
"target": {
"id": "payments-production",
"provider": "your-cloud-or-platform",
"region": "your-region-or-datacenter",
"service": "your-service-or-application"
}
}
Keep enabled false until every required external path, digest, hook, identity,
and verifier below is installed and tested.
| Key group | What to configure |
|---|---|
enabled, mode, environment |
Keep disabled until the external trust boundary is ready. Choose approval-required or the stricter-attested automatic mode; the current executor requires environment: production. |
trustedBaseRef |
Protected base ref from which the gap-free integration chain must descend. This does not replace branch protection. |
target |
Set a stable non-secret id; add provider-neutral routing such as provider, region, service, account, namespace, or cluster fields needed by your hooks. |
stateRoot, trustedPath |
Absolute external release transaction/state root and protected executable-search path. |
gitLfsPolicy, maxSourceArchiveBytes, maxSourceBytes, maxSourceFiles |
Bound and validate the isolated source snapshot consumed by planning. |
approvalTtlSeconds, deliveryAttestationTtlSeconds, ciAttestationTtlSeconds |
Maximum age of exact approval, automatic-delivery attestation, and protected green CI evidence. |
planningIsolation |
Declare the protected sandbox provider, separate identity, unmounted credential/state paths, and production-egress posture. Safe templates are intentionally incomplete. |
credentialEnvFile, credentialEnvironmentAllowlist |
Mode-0600-or-stricter external credential source and the exact names the privileged hooks may receive. Ordinary agents and plan hooks never inherit it. |
planningEnvironmentAllowlist, trackerEnvironmentAllowlist, environmentAllowlist |
Independent positive allowlists for planning/CI verification, tracker projection, and privileged release hooks. |
trustedCodeDigests, trustedHookDigests |
SHA-256 pins for the protected executor/helper set and every dedicated hook executable. |
hooks.plan |
Produce a canonical structured plan from isolated source, binding the exact source archive and immutable artifactDigest. Required when delivery is enabled. |
hooks.verifyCi |
Required whenever delivery is enabled. Return a protected, fresh, exact-commit proof that every required check succeeded and no check is failed, pending, skipped, missing, stale, or unverifiable. It is re-run before planning and twice at the apply boundary. |
hooks.status, hooks.apply, hooks.verify |
Read current target state, apply the exact reviewed artifact, and independently prove the deployed version and health. |
hooks.rollback |
Optional bounded recovery hook; automatic rollback may target only the immediately previous immutable artifact matching observed pre-apply status. |
hooks.verifyApproval |
Required by approval-required; validate an external exact-manifest authorization. Tracker comments never satisfy it. |
hooks.verifyDelivery |
Required by automatic; attest role isolation, planning isolation, and approval authenticity for the exact commit and evidence digests. |
timeoutsSeconds |
Per-hook bounds for CI verification, plan, status, apply, verify, rollback, approval, and attestation. Their conservative total must fit inside releaseTimeoutSeconds. |
| Release mode | What can proceed |
|---|---|
approval-required |
Apply proceeds for a policy-clean manifest only after the protected verifyApproval hook confirms the exact target, commit, artifact, evidence digests, expiry, and nonce. |
automatic |
Only a non-destructive, reversible immutable-artifact release with no approval-only effects and a valid protected verifyDelivery attestation. |
Both release modes also require the protected verifyCi hook to prove a green
pipeline for the exact release commit. Red, failed, pending, skipped, missing,
stale, or unverifiable CI blocks apply before any supported environment can be
changed; no agent or tracker comment can waive that gate.
The provider hooks are the production-target boundary. Startup Factory does not
hard-code AWS, Azure, GCP, Kubernetes, VMs, bare metal, or a particular CI/CD
service; each hook receives and returns the normalized contracts documented in
reference/deployment.md.
Project guardrail additions
config/guardrails.config.json cannot remove or
override any built-in denial. Its pattern/action lists only add restrictions;
its numeric keys set operator-owned bounds for otherwise policy-clean automatic
plans:
| Key | Safe default | Purpose |
|---|---|---|
additionalDenyPatterns |
[] |
Add project-specific forbidden patterns for privileged release-hook argv. |
additionalApprovalRequiredActions |
[] |
Add project-specific action classes that always need exact human approval. |
maximumAutomaticPlanChanges |
100 |
Bound the number of normalized effects in an automatic release plan. |
maximumAutomaticCostDelta |
0 |
With the zero default, a positive cost delta is denied in automatic mode and approval-only in approval-required mode. |
allowAutomaticRollbackOnlyToPreviousArtifact |
true |
Allow automatic rollback only to the immediately previous immutable artifact whose digest matches the objectively observed pre-apply state; false disables automatic rollback. |
Never put production credentials, privileged hook argv, trust pins, or release
state in repository config. (config/team.config.md intentionally contains
ordinary agent CLI, setup, and validation commands.) When deployment is enabled,
use a protected external config and state root, absolute digest-pinned hook
executables outside the repository, and a credential file outside the repository with
mode 0600 or stricter, exact credential-name allowlisting, executor/root
ownership, and no symlink. Generic interpreters are rejected as privileged hook
executables. The scheduler authenticates and snapshots the external release
entrypoint/config before its first instruction and passes only positive
environment allowlists; absent or disabled external trust starts no release
executor. See reference/deployment.md for the exact trusted-code keys,
environment boundaries, attestation, and hook contracts.
Autonomous launch additionally refuses to start unless
TRACKER_WRITERS=broker, AGENT_SANDBOX_ENFORCED=true, and a valid protected
AGENT_SANDBOX_RUNNER are configured. The runner must be an absolute,
non-symlink executable outside the repository, owned by the executor or root and
not group/world-writable. Startup Factory validates and invokes that boundary;
the runner implementation remains responsible for actual OS/container isolation.
It also requires the external mode-0700 BROKER_LIFECYCLE_ROOT, kept outside
every agent mount, for authenticated PID/start-time/tmux lifecycle authority.
Use it
One agent
Set TEAM_MODE=false in config/project-management.config.md, then talk to
your agent in the generic vocabulary:
- "Plan a feature: …" → creates a
[feature]+[tasks] - "Start task ENG-142" → generic
[Active]/ shippedIn Progress, then implements - "Send it to review" → generic
[Review]/ shippedIn Review, launching the four mandatory independent reviewers - "Finalize it" → only after all four approvals, generic
[Ready to deploy]/ shippedReady for production - "Switch the tracker to Linear" → follows the adapter's setup
A whole team
-
Set the bundle path for your installation, confirm the shipped
TEAM_MODE=truesetting, configure role commands,WORKTREE_SETUP, and at least one realVALIDATE_*command in$SF_HOME/config/team.config.md:SF_HOME=.agents/skills/startup-factory # Codex / shared Agent Skills # SF_HOME=.claude/skills/startup-factory # Claude Code
Add
.teamwork/and.workspace/to the target repository's root.gitignore. Provision the protected external mode-0700BROKER_LIFECYCLE_ROOTfor this dispatcher-driven path; it supplies authoritative liveness, prevents duplicate launches, and enablesstatus/stop. -
Create a feature branch — its name is the team name:
git checkout -b payments-revamp
-
If Claude/Superpowers produced an approved committed specification and plan, bind them before launch:
"$SF_HOME/bin/launch-team.sh" planning-handoff payments-revamp \ docs/superpowers/specs/2026-07-16-payments-revamp-design.md \ docs/superpowers/plans/2026-07-16-payments-revamp.md
Skip this step when using native Startup Factory planning.
-
Launch the preset's persistent supervision and gate roles:
"$SF_HOME/bin/launch-team.sh" gate-team deep-backend payments-revamp ENG-100 # └ preset └ branch/team └ featureId
-
Start the deterministic dispatcher in its own persistent shell. This process owns task claims and launches fresh task-scoped workers:
"$SF_HOME/bin/dispatch.sh" payments-revamp ENG-100 --watch
-
Watch the team:
tmux attach -t team-payments-revamp # live agent windows, when tmux is used "$SF_HOME/bin/launch-team.sh" status payments-revamp # protected process state + heartbeat
Progress lands in your tracker; anything needing you lands in
.teamwork/payments-revamp/ESCALATIONS.md. -
Stop the dispatcher with
Ctrl-C, then stop the managed team:"$SF_HOME/bin/launch-team.sh" stop payments-revamp
If you intentionally experiment with unmanaged direct launches instead, do not rely on dispatcher liveness,
status, orstop; supervise the tmux/background processes yourself.
Keep
SF_HOMEset in every shell that runs a launcher or dispatcher. For a protected external automation installation, set it to that absolute path.
bin/launch-team.sh subcommands:
| Command | Purpose |
|---|---|
team <preset> <team> <featureId> |
Launch a whole preset roster |
gate-team <preset> <team> <featureId> |
Launch only persistent supervision/review/integration gates; automation uses this and starts implementers per task |
planning-handoff <team> <spec-path> <plan-path> |
Bind committed Claude/Superpowers specification and plan inputs to this Startup Factory team |
preflight <team> <featureId> |
Verify adapter access, workspace writability, and UTC pin — run once before any CLI team launch |
start <team> <featureId> <role>… |
Launch specific roles (custom teams) |
relaunch <team> <featureId> <role> [preset] |
Restart one crashed/wedged agent |
compose <team> <featureId> <role> [preset] |
Write a role's startup prompt without spawning — for running teammates as subagents inside your own harness (see reference/orchestration.md → Harness mode) |
start-task <team> <featureId> <role> <taskId> [attempt] [preset] |
Generate a packet and launch one task-scoped worker in its worktree |
compose-task <team> <featureId> <role> <taskId> [attempt] [preset] |
Generate a packet and lean startup prompt without spawning, for harness subagents |
worktree <team> <role> <taskId> [attempt] |
Create an implementer's isolated task worktree |
worktree-remove <team> <role> <taskId> [attempt] |
Remove a worktree only after protected lifecycle state proves its worker is stopped; unmanaged mode refuses |
validate-board [config-path] |
Validate status structure, initial/terminal rules, transitions, reachability, owners, and marker-role references |
status <team> |
Show authenticated process state plus last heartbeat when protected lifecycle authority is enabled; otherwise report that markers are non-authoritative |
stop <team> |
Stop the managed team through authenticated lifecycle identities; unmanaged mode refuses to signal |
stop-task <team> <taskId> |
Send bounded TERM→KILL to the authenticated launcher-managed process group/session for one [task], then revoke that [task]'s active publication capabilities; sibling workers and gate roles continue |
Process-group stopping is lifecycle control, not a complete containment
boundary. A subprocess that deliberately escapes with setsid, double-forking,
or an external supervisor may outlive the launcher. Autonomous deployments must
therefore use an OS sandbox, cgroup/container, service job, or equivalent
kill-on-close boundary that contains every descendant. Broker hold checks still
reject output from an escaped stale process.
bin/dispatch.sh — the event loop:
| Command | Purpose |
|---|---|
dispatch.sh <team> <featureId> --once [--dry-run] |
One deterministic read-and-act pass |
dispatch.sh <team> <featureId> --watch |
Wake on runtime events with POLL_INTERVAL_SECONDS as a fallback — run in a persistent shell (tmux/nohup); you own this process |
CLI dispatch requires scriptable tracker access. Linear and Jira default to MCP; set
LINEAR_ACCESS=restorJIRA_ACCESS=restinconfig/project-management.config.mdbefore runningdispatch.sh --watch. Harness mode (launch-team.sh compose) supports MCP natively.
bin/tracker-ops.sh — normalized scriptable tracker operations:
| Command | Purpose |
|---|---|
state <taskId> <Status> |
Make and verify a legal generic [task] status write. Startup Factory rejects every outbound [Blocked] transition; a human must perform that move in the project-management tool. |
feature-state <featureId> <Status> |
Make and verify a legal generic [feature] status write. |
feature-reopen <featureId> <Status> |
PM-supervisor-only terminal-to-queued reopen for a new delivery generation. |
task-reopen <taskId> <Status> |
Integration-broker-only terminal-to-queued reopen after late valid findings; the shipped target is Planned/ToDo, followed by a fresh claim into Active/In Progress. |
comment <taskId> [bodyfile] |
Add a comment, reading its body from a file or stdin. |
comment-once <taskId> <deliveryId> <bodyfile> |
Deliver one idempotent comment for a durable outbox item. |
update-comment <taskId> <commentId> [bodyfile] |
Edit an existing comment where the adapter supports it. |
upsert-progress <taskId> [bodyfile] |
Create or update the task's single managed [progress] projection. |
upsert-digest <featureId> [bodyfile] |
Create or update the feature's single managed [digest] projection. |
upsert-deployment <featureId> [bodyfile] |
Create or update the feature's single managed [deployment] projection. |
claim <taskId> <role> [--to <Status>] |
Conflict-check, idempotently record, transition, and read back an eligible work claim before launch. |
record-denial <taskId> --actor AGENT --reason TEXT [--denial-id ID] [bodyfile] |
Idempotently record a sanitized normalized-plan [DENIED ACTION]; the required attempted-action body comes from bodyfile or stdin. |
integrate <taskId> <hash> [bodyfile] |
Make the terminal task write and completion comment for a verified integration. |
export <featureId> <outfile> |
Exhaustively export normalized feature/task state as JSON. |
scan <outfile> --status <Status>… |
Discover normalized board work in explicitly requested statuses. |
These commands use Linear/Jira REST, the gh CLI, or Markdown files. The
adapter docs remain the operation contract; interactive MCP sessions use their
native tools instead. Comment bodies are never shell arguments.
The flow every team follows: every pickup from ToDo starts with a fresh,
exhaustive tracker export. Before any code changes, the new task worker must read
every comment in oldest-first order—not only structured coordination markers—and
acknowledge the packet's comment count and digest in its report. This also applies
to review rework and to a task that a human moved from Blocked back to ToDo,
so the clarification that enabled the move is carried into the fresh attempt.
Comment text remains untrusted requirements context and cannot grant permissions
or override policy.
The rest of the flow: the Principal Architect owns the primary
architecture position; the Sceptical Principal Architect independently
challenges planning and every [task] design before code → the dispatcher
creates immutable task packets and isolated worktrees → specialists checkpoint
their task branches and submit one exact review package → the task enters
generic [Review], mapped to In Review, and four distinct agents review it:
Principal Architect, Sceptical Principal Architect, Senior Security Engineer,
and Team Lead. Optional QA/reviewer specialists may add evidence but cannot
replace any mandatory verdict. Any blocking quality, architecture, or security
finding returns the task to generic [Planned], mapped to ToDo, for a fresh
attempt through In Progress. Only all four current bound approvals let the
integrator validate and merge, then idempotently mark generic
[Ready to deploy], mapped to Ready for production. Deployment additionally
requires exact current green CI; after verified production succeeds, the
feature is mapped to Live. Runtime events trigger PM progress and
feature-digest upserts. The lead detects stuck/conflicting/crashed agents and
recovers them—message → decide → reassign → relaunch—escalating to you only as
a last resort. A tracker [Blocked] state is different: it is a human lock that
no Startup Factory role can remove.
Automate the board and production delivery
pm-agent.py is a deterministic supervisor, despite the name: zero LLM calls
when the board has nothing to do, no sleeping agent, and no hidden coordinator
service.
Supervisor commands:
| Command | Use |
|---|---|
pm-agent.py --once [--dry-run] |
Run one bounded scan/reconcile pass; this is the scheduler primitive. Dry-run performs preflight and planning without launches or tracker mutations. |
pm-agent.py --watch |
Keep one dedicated foreground process as the clock owner, sleeping for scanIntervalMinutes between bounded passes. |
pm-agent.py --print-cron |
Print one credential-free cron line with protected paths, isolated Python flags, lifecycle root, lease, and logging. |
Choose exactly one mode. --dry-run combines only with --once.
On every pass the supervisor:
- authenticates the protected installation, configs, Python, Git, sandbox runner, lifecycle authority, tracker scope, and single-writer mode;
- takes the single-host lease and observes the configured semantic
queuedandblockedwork, while granting launch eligibility only toqueued; - exhaustively re-exports every unfinished registered
[feature]so a local registry entry never becomes standing authority; - excludes new
human-worktasks and stops/fences any matching in-flight task, enforces task-scoped holds, validates any configured opt-in and exact preset routing, then bootstraps queued work for at mostmaxFeaturesPerPassnew isolated feature runs; - launches persistent gate roles, invokes one deterministic dispatch pass, reconciles holds/comments/recovery, and starts fresh task-scoped workers only when the state machine calls for them; and
- hands an all-integrated feature to the protected release executor, or leaves it visibly awaiting delivery when deployment is disabled or authorization is incomplete.
Malformed state, an incomplete export, a newly human-owned task, lost required
opt-in, conflicting metadata,
preset drift, an expired capability, or a failed read-back pauses/stops the
affected run or pass; it never falls through to a guessed action. A valid
[Blocked] state is not such a failure: it fences that [task] and the portfolio
continues.
[Blocked] is a human-controlled task lock
When a dispatcher or portfolio reconcile observes a [task] in [Blocked], it
creates a durable task hold and captures the complete communication snapshot.
If the [task] is in flight, it stops the workers bound to that [task] and revokes
their active publication capabilities. The team, PM loop, gate roles, sibling [tasks], and other
[features] continue. A held [task] cannot publish, integrate, or release; its
parent [feature] waits because not every [task] is integrated, while unrelated
[features] remain eligible for delivery.
Dependencies remain narrow and explicit:
- A queued [task] with an unfinished non-Blocked
blockedBydependency remains unclaimable. Independent queued [tasks] continue. - A queued,
[Active], or[Review][task] whose adapter-normalized, first-classblockedByedge points directly to a currently[Blocked][task] enters dependency-impact review. Titles, descriptions, comments, and semantic similarity never create dependency edges. - The team-lead publishes
[dependency-hold]with the current graph digest and a verdict ofblocked,partially-actionable, orindependent. Only an authenticatedblockedverdict that still matches a fresh graph authorizes the broker to move that dependent into[Blocked]; the other verdicts give the exact graph-bound clearance needed to claim or continue it.
Only a human can move a [task] out of [Blocked]; Startup Factory has no
automated outbound path. A human move of that held [task] to the configured
queued status starts a resume barrier: the supervisor snapshots the [task] again,
diffs title, description, every stable comment (including edits/deletions), and
adapter-provided normalized attachment metadata, and asks the team-lead for an
authenticated [resume-review] bound to the hold and communication digest.
unchanged may clear the barrier; requirements-changed additionally requires
a later [resume-plan] plus both architect design approvals;
needs-human keeps it closed. The prior worktree must also be clean—dirty work
is preserved for explicit salvage or quarantine, never discarded. Clearing the
barrier archives the old claim and starts a fresh numbered attempt from the new
packet. A human move directly to [Active] or [Review] is manual takeover, so
automation remains fenced rather than claiming it. The fresh post-resume packet
also embeds every current tracker comment—not just the resume markers—and the
worker must review the complete history before changing code.
This human-only rule is enforceable end to end only when the project-management tool's workflow ACL restricts outbound Blocked transitions to human principals. The adapters observe state but do not authenticate the transition actor.
These hold-control markers are authenticated workflow commands, not ordinary board prose. The local broker accepts them only when a published receipt binds the exact body, role, task, feature, and verified launched-role capability. Copying the marker text into a project-management comment—or claiming a team-lead signature—does not create that receipt and grants no authority.
-
Provision a real worktree-scoped OS sandbox and network/IAM restrictions for every ordinary agent. Install its protected external entrypoint, configure its absolute path as
AGENT_SANDBOX_RUNNER, verify the--workdir <absolute> -- <argv...>contract, and setAGENT_SANDBOX_ENFORCED=true. Configure a non-empty, non-no-opWORKTREE_SETUPand at least one meaningfulVALIDATE_SCRIPT,VALIDATE_BUILD,VALIDATE_TEST,VALIDATE_LINT, orVALIDATE_FORMATcommand inconfig/team.config.md. -
Keep the shipped
TEAM_MODE=truedefault, setTRACKER_WRITERS=broker, and configure a scriptable, explicit tracker scope. Linear requiresLINEAR_ACCESS=restplusLINEAR_DEFAULT_TEAM; Jira requiresJIRA_ACCESS=restplus an exactJIRA_PROJECT_KEYandJIRA_TASK_ISSUE_TYPE; GitHub requires an explicitGITHUB_REPO. Reviewreference/guardrails.md; ordinary agents must have no cloud/database production credentials. -
Install the reviewed skill and Python outside the target checkout and all agent mounts. Copy the automation/team/project-management configs there, protect them from group/world writes, set an external protected
trustedPath, and configure automation. Provision a separate absolute mode-0700BROKER_LIFECYCLE_ROOToutside the checkout, installed skill, and every agent sandbox mount; its parent chain must contain no symlinks or group/world-writable directory (so do not place it below shared/tmp). The shipped policy automatically launches queued tasks and observes Blocked tasks as human-held unless they carry thehuman-worklabel. SetrequireMetadataOptIn: trueif this installation should additionally require anautomation: enabledmetadata marker. Then inspect a pass:STARTUP_FACTORY_PROJECT_ROOT=/absolute/target-checkout \ STARTUP_FACTORY_AUTOMATION_CONFIG=/protected/config/automation.json \ /protected/python/bin/python3 -I -S -E -s \ /protected/startup-factory/bin/pm-agent.py --once --dry-run
-
Set
scanIntervalMinutesto the desired board-scan cadence (default3), setenabled: true, and install exactly one cron entry:STARTUP_FACTORY_PROJECT_ROOT=/absolute/target-checkout \ STARTUP_FACTORY_AUTOMATION_CONFIG=/protected/config/automation.json \ /protected/python/bin/python3 -I -S -E -s \ /protected/startup-factory/bin/pm-agent.py --print-cron
The explicit project root is established before
trustedPathis consumed; the supervisor then verifies it with protected Git. The supervisor refuses its own executable, Python, or protected configs when they resolve inside the target repository. ConfiguretrustedPathwith protected directories that exist on the scheduler host (the portable template uses/usr/bin:/bin). A root-owned OS alias such as usrmerge/binis canonicalized and its target chain is revalidated; user-owned symlinks are rejected. The printed line fixes the protectedPATHand uses Python-I -S -E -s, but intentionally embeds no credentials. Inject tracker/deployment variables through the scheduler's secret store, service definition, or a scheduler/root-owned wrapper that preserves those flags; never put tokens in crontab. The printer accepts only exact stable cron cadences: minute intervals that divide 60 and whole-hour intervals that divide 24. Use a service timer or hosted scheduler for intervals such as seven minutes. Hosted schedulers should use their equivalent of “forbid overlapping runs.” The built-in lease covers one host; multiple hosts require a distributed lock or adapter-native compare-and-set. Each adapter, Git, launcher, and dispatcher child operation has the boundedoperationTimeoutSecondsdeadline; a production transaction uses its separately boundedreleaseTimeoutSeconds, which must cover the full configured plan/attestation/status/apply/verify/rollback path. New queued work on an already deployed feature opens a numbered generation with a new run ID, team, and feature branch rooted at the exact verified predecessor HEAD, while preserving the stable workspace and prior release evidence. -
Optionally put initial routing metadata in a [task] description:
team-preset: deep-backend
Apply the tracker label
human-workto reserve a task for a person. The PM supervisor makes no new claims or launches for it; if it was already in flight, the next reconcile stops its managed worker and fences publication, integration, and release while other tasks remain eligible. Removing the label returns the task to automatic consideration on the next scan.automation: disabledremains an explicit metadata opt-out, whileautomation: enabledis required only whenrequireMetadataOptInis true.Treat descriptions as the baseline. Post every later routing change as a timestamped/revisioned comment; generic record
updatedAtdoes not prove a description edit. Unordered or conflicting latest metadata pauses the run. -
For production, install a protected release executor/config/state root and digest-pinned provider hooks as specified in
reference/deployment.md. Chooseautomaticonly for a normalized reversible, non-destructive immutable-artifact path and a pinned externalverifyDeliveryattestor that proves OS role isolation, isolated source planning, and approval authenticity for the exact feature commit, integration evidence, and product-acceptance digest. Otherwise retainapproval-requiredwith an external exact-manifest verifier. Set the scheduler environment variablesSTARTUP_FACTORY_DEPLOYMENT_CONFIGto that external config path andSTARTUP_FACTORY_RELEASE_FEATUREto the absolute executor in the protected external skill installation. Enabled production refuses the repository-local executor.For the common “approved work deploys to one fixed production target” setup, start from
config/deployment.production.approval-required.example.jsonandconfig/pm-agent.production.env.example. Copy both outside the checkout, settarget.idplus optional provider/region/service routing fields, install the pinned hooks and digests, satisfyplanningIsolation, and only then setenabled: true. Only after every task is integrated and current commit-bound product acceptance exists does the supervisor trigger the guarded release handoff;verifyApprovalauthorizes the exact manifest, deployment and verification run automatically, and the parent [feature] closes only after verification. Ordinary tracker comments never satisfy production approval.
Scheduler environment:
| Variable | Required when | Meaning |
|---|---|---|
STARTUP_FACTORY_PROJECT_ROOT |
Always | Absolute exact root of the target git checkout. |
STARTUP_FACTORY_AUTOMATION_CONFIG |
Always | Absolute protected external automation JSON. |
STARTUP_FACTORY_LIFECYCLE_STATE_ROOT |
Autonomous operation | Absolute protected external lifecycle authority root; overrides BROKER_LIFECYCLE_ROOT. |
STARTUP_FACTORY_DEPLOYMENT_CONFIG |
Production delivery | Absolute protected external deployment JSON. Omit it to keep release handoff disabled. |
STARTUP_FACTORY_RELEASE_FEATURE |
Enabled production delivery | Absolute protected external bin/release-feature.py; a repository-local path is refused. |
| Adapter credential variables | Remote tracker access | Inject only the names required by the selected scriptable adapter through the scheduler secret facility. |
Install the operational PM configuration at
<protected-skill>/config/project-management.config.md; the launcher and tracker
broker read that exact location. Do not attempt to relocate it with a scheduler
environment override.
Use
config/pm-agent.production.env.example
as non-secret wiring, not as a credential file.
Protected executor entry points (normally invoked by the supervisor, not by an LLM):
| Command | Purpose |
|---|---|
release-feature.py --repository ROOT --workspace WORKTREE --team TEAM --feature ID --config DEPLOYMENT_JSON |
Resume or execute the durable production transaction. The supervisor also binds expected git/common-dir identities at handoff. |
policy-check.py --config GUARDRAILS_JSON plan --mode MODE [--approved] PLAN_JSON |
Evaluate one canonical normalized release plan as DENY, REQUIRE HUMAN APPROVAL, or ALLOW. |
policy-check.py --config GUARDRAILS_JSON command --action ACTION --environment production [--authorization-digest DIGEST] -- ARGV… |
Evaluate exact privileged hook argv before subprocess launch. |
The release transaction requires the canonical symlink-free feature workspace,
a gap-free integration chain rooted under trustedBaseRef, an exact
commit/evidence-bound feature-level product acceptance marker, and current
trusted code/hook/config bindings. Missing or stale product acceptance is routed
back to the product role before any release plan or apply. A protected
verifyCi hook must also prove that the exact release commit has a current
green pipeline; the executor checks this before planning and twice at the apply
boundary, so a red or newly regressed pipeline cannot race into deployment.
The executor always queries current deployment state before apply,
checks the artifact digest, independently verifies health/version, redacts loaded
credentials from logs, and records success only after verification. The release
executor alone performs the terminal [feature] transition; disabled or waiting
delivery remains non-terminal. Disabled delivery creates no tracker deployment
projection; the PM registry records local awaiting state. A safe rollback can
target only the immediately previous immutable artifact matching the objectively
observed pre-apply digest. Branch protection remains an operator-owned git-host
control; trustedBaseRef does not configure it.
Each run also records the exact initial baseCommit, refuses pre-positioned
feature branches, and requires the branch/base ancestry to remain intact. Before
handoff the supervisor captures the canonical Git common/worktree directory
paths and device/inode identities; the release executor binds Git directly to
those directories and rechecks their identity plus feature HEAD at apply.
The six preset teams
| Preset | Roster | Use when |
|---|---|---|
full-stack |
Team Lead · Principal Software Architect · Sceptical Architect · Senior Security Engineer · Senior Technical PM · Senior Full Stack Engineer · Senior QA | Features cutting through schema, API, and UI — the default |
deep-backend |
Team Lead · Principal Backend Architect · Sceptical Architect · Senior Security Engineer · TPM · Senior Staff Engineer · Senior QA | Domain logic, data models, APIs, performance |
deep-frontend |
Team Lead · Principal Frontend Architect · Sceptical Architect · Senior Security Engineer · TPM · Senior Frontend Engineer · Senior QA | UI architecture, client state, design systems, a11y |
deep-security |
Team Lead · Principal Security Architect · Sceptical Architect · Senior Security Engineer · TPM · Senior Security Implementation Engineer · Senior Penetration Tester · Senior QA | Security features & hardening on your own codebase |
deep-infra |
Team Lead · Principal Cloud & Infrastructure Architect · Sceptical Architect · Senior Security Engineer · TPM · Senior Cloud Engineer · Senior SRE · Senior QA | Cloud infra, IaC, delivery pipelines, reliability |
deep-llm |
Team Lead · Principal LLM Architect · Sceptical Principal LLM Architect · Senior LLM Security Engineer · TPM · Senior LLM Engineer · Senior Staff Backend Engineer · Senior Full Stack Engineer · Senior QA | LLM systems, data science, RAG, evaluation, inference services, and LLM product UX |
Every preset launches four distinct mandatory review-board agents: Team
Lead, Principal Architect, Sceptical Principal Architect, and
Senior Security Engineer. They independently review the same exact package;
QA and reviewer roles are optional specialists, not substitutes. A standard
integrator owns serialized feature-branch commits and recoverable tracker
finalization only after all four approvals. Details in
teams/README.md.
How it works
The PM layer applies the ports-and-adapters (hexagonal) pattern: workflows and agents speak one stable vocabulary; one config selects the adapter that translates it to a concrete tracker. Teams, models, and deployment hooks never need tracker-specific workflow logic.
flowchart LR
Board["Linear · Jira · GitHub Issues · Markdown"]
PM["Deterministic PM supervisor<br/>cron · timer · service"]
State{"Task state?"}
Hold["Task-scoped human hold<br/>stop worker · revoke capability"]
Route{"Opt-in and preset<br/>valid?"}
Gates["Lead · Product · Two architects<br/>scope and independent design gates"]
Work["Task-scoped agents<br/>isolated Git worktrees"]
Review["In Review<br/>Lead · Principal · Sceptical · Security"]
Rework["ToDo<br/>fresh numbered attempt"]
Integrate["Integrator<br/>serialized feature branch"]
CI{"Exact-commit protected CI<br/>green?"}
Policy{"Release policy and<br/>exact authority pass?"}
Release["Credential-isolated<br/>release executor"]
Target["Verified production target<br/>feature Live"]
Board --> PM --> State
State -->|queued| Route
State -->|Blocked| Hold -->|human returns to queued| Board
Route -->|yes| Gates --> Work --> Review
Review -->|blocking finding| Rework --> Work
Review -->|all four approve| Integrate --> CI
CI -->|green| Policy
CI -->|red · pending · missing| Board
Route -->|pause / escalate| Board
Policy -->|approved| Release --> Target --> Board
Policy -->|wait / deny| Board
The dispatcher claims a [task] under a per-pass lock, generates its packet,
and launches exactly one attempt. Design notes, approvals, findings, and
escalations remain structured tracker comments. An append-only event journal
wakes local coordination quickly; the durable outbox serializes tracker writes
when TRACKER_WRITERS=broker; polling remains the distributed fallback.
Documentation map
| Read this | It answers… |
|---|---|
SKILL.md |
What does an agent load, in what order, and which invariants must every workflow obey? |
reference/vocabulary.md |
What stable [feature]/[task] contract and status semantics do all adapters share? |
reference/lifecycle.md |
How does work move through planning, execution, review, blocking, automation, and production release? |
reference/superpowers-planning.md |
How does Claude/Superpowers produce planning inputs without taking over Startup Factory execution? |
reference/team-roles.md |
Which role owns each status and transition in team mode? |
reference/orchestration.md |
How do roles coordinate, authenticate handoffs, review, integrate, recover, and pull the andon cord? |
reference/dispatch.md |
Which deterministic event launches each next role action? |
reference/automation.md |
How do protected cron/service scans, task holds, human resume barriers, routing metadata, registration, generations, leases, and recovery work? |
reference/guardrails.md |
Which actions are denied, approval-only, or autonomously allowed, and where are those boundaries enforced? |
reference/deployment.md |
What are the provider-neutral hook schemas, trust requirements, approvals, transaction phases, and rollback rules? |
teams/README.md and teams/_PLAYBOOK.md |
Which preset should you choose and how does its shared delivery protocol operate? |
extensions/tracker-backends/README.md |
Where does a project-owned backend module for a custom tracker live? |
| Tracker guide | Scriptable unattended access | Interactive access |
|---|---|---|
adapters/Markdown.md |
Local files; zero credentials | Local files |
adapters/Linear.md |
Scriptable GraphQL HTTP mode with exact team scope | MCP or the configured rest mode |
adapters/Jira.md |
REST with exact project and child type | MCP or REST |
adapters/GitHubIssues.md |
gh CLI with explicit repository |
GitHub MCP or gh |
adapters/_TEMPLATE.md |
Contract for a new tool, including exhaustive pagination, normalized scan/export, idempotent writes, and read-back | Tool-specific |
Directory map
A source checkout is arranged as below. Runtime entries ship in the operational bundle; release-engineering entries are intentionally omitted from project skill installations. The Python source distribution contains the marked package metadata and CLI source, but not repository-only release automation.
├── README.md this guide
├── SKILL.md the operational skill your agent runs
├── LICENSE MIT distribution terms
├── pyproject.toml release source + sdist: package metadata
├── packaging/ release repository only
│ ├── bundle-spec.json canonical payload and preservation policy
│ └── build_bundle.py reproducible exact-commit archive builder
├── src/startup_factory_cli/ release source + sdist: installer CLI
├── .github/workflows/ release repository only: package/release CI
├── config/
│ ├── project-management.config.md ← EDIT: pick tracker, TEAM_MODE, STRICT_STATUS
│ ├── planning.config.md ← EDIT: Claude/Superpowers planning on/off
│ ├── team.config.md ← EDIT (teams): role→CLI, timings, VALIDATE_*
│ └── statuses · automation · deployment · guardrails configs
├── reference/
│ ├── vocabulary.md the tool-agnostic contract (the port)
│ ├── lifecycle.md the scenarios: plan → work → review → complete
│ ├── team-roles.md status ownership across roles
│ ├── orchestration.md the multi-agent protocol
│ └── superpowers-planning · automation · deployment · guardrails
├── adapters/
│ ├── Markdown.md · Linear.md · Jira.md · GitHubIssues.md
│ └── _TEMPLATE.md scaffold for a new tracker
├── extensions/tracker-backends/ project-owned custom tracker modules
├── roles/ the 9 base protocol roles
│ └── team-lead · principal-architect · sceptical-architect · senior-security-engineer · integrator · backend · frontend · qa · reviewer
├── teams/
│ ├── README.md · _PLAYBOOK.md how presets work + shared collaboration flow
│ ├── full-stack.md · deep-backend.md · deep-frontend.md · deep-security.md · deep-infra.md · deep-llm.md
│ └── roles/ 21 specialized role briefs
├── bin/
│ ├── launch-team.sh role and task-instance launcher
│ ├── superpowers-planning.py Claude plugin preflight + planning handoff
│ ├── process-lifecycle.py authenticated external process/tmux authority
│ ├── update-installed-skill.sh legacy/source compatibility updater
│ ├── dispatch.sh · dispatch-plan.py deterministic bounded scheduler
│ ├── runtime-state.py · task_metadata.py
│ │ event journal, metadata/routing, task packets
│ ├── submit-artifact.sh · process-outbox.sh
│ ├── review-package.sh · review_evidence.py · integrate-task.sh · finalize-integrations.sh
│ ├── teamwork-path.py · product_acceptance.py safety/path and product gates
│ ├── pm-agent.py bounded portfolio scheduler pass
│ ├── release-feature.py · policy-check.py
│ └── tracker-ops.sh idempotent tracker operations
└── tests/ offline smoke tests (no LLM calls)
└── run-all.sh tracker, runtime, dispatch, launcher, integration
Extend it
Team and role extensions are one file. A new tracker needs its adapter contract plus a scriptable backend before deterministic dispatch/automation can use it.
- New tracker: copy
adapters/_TEMPLATE.md→adapters/<YourTool>.md, fill the tables, add the normalized primitive backend class atextensions/tracker-backends/<YourTool>.py, then setPRODUCT_MANAGEMENT_TOOL=<YourTool>. Do not edit the upstream-ownedbin/tracker-ops.sh; seeextensions/tracker-backends/README.md. - New team: copy any
teams/<preset>.md, edit the charter,ROSTER=line, and specialist roles. Include four distinct enabled mappings and roster entries forPROTOCOL_TEAM_LEAD,PROTOCOL_PRINCIPAL_ARCHITECT,PROTOCOL_SCEPTICAL_ARCHITECT, andPROTOCOL_SECURITY_REVIEWER, plusintegrator. - New role: add
teams/roles/<kebab-name>.mdwith the standard sections (identity, Protocol mapping, responsibilities, decision authority, deliverables, handoffs, "you never"). The launcher resolves any role that has a brief inroles/orteams/roles/.
Keep the generic vocabulary ([feature], [task], semantic status kinds) and the
exact protocol markers — never invent new ones.
Troubleshooting
| Symptom | Fix |
|---|---|
| Agent says the tracker is unavailable | Re-check the adapter's Access mechanisms (MCP block or exported API-key env vars); the agent stops rather than fabricating — that's by design |
launch-team.sh can't find a role |
The role needs a brief in roles/ or teams/roles/, and its <ROLE>_CMD (or TEAM_DEFAULT_CMD) must be set |
| A role won't launch in a preset | An optional role may have <ROLE>_CMD=null; remove the line to fall back to TEAM_DEFAULT_CMD. Team Lead, Principal Architect, Sceptical Principal Architect, and Senior Security Engineer are mandatory, distinct reviewers; a missing/duplicate mapping, absent roster entry, null command, or missing fallback rejects the whole team before launch. |
No tmux |
Agents run as background processes automatically. With protected lifecycle state use status/stop; otherwise supervise them externally. Logs remain under .teamwork/<team>/pids/ |
status says lifecycle supervision is disabled |
Provision BROKER_LIFECYCLE_ROOT as documented in config/team.config.md; unmanaged manual mode deliberately refuses stop rather than trusting workspace PID text |
| Team seems stuck | With protected lifecycle state configured, bin/launch-team.sh status <team> shows authoritative process state plus heartbeats; the lead applies the recovery ladder, and anything needing you is in .teamwork/<team>/ESCALATIONS.md. A [Blocked] task is intentionally human-held and never changed outbound by automation. |
| An eligible queued task never launches | Confirm automation is enabled and scheduled, the scriptable adapter has an exact scope, the task does not carry an ignoredTaskLabels value such as human-work, and team-preset is absent or exactly one allowed preset. If requireMetadataOptIn is true, also confirm the latest metadata says automation: enabled; conflicting or unordered metadata deliberately pauses. |
A human moved [Blocked] to queued but no fresh attempt starts |
Inspect the generated resume-review request. A broker-authenticated [resume-review] must bind its exact hold and communication digest; changed requirements also need a later [resume-plan] and both architect design approvals, and the prior worktree must be clean. |
--print-cron rejects the scan interval |
Conventional cron output supports minute divisors of 60 and whole-hour divisors of 24. Use a service timer or hosted scheduler for cadences such as seven minutes |
another live pass owns the monitor lease |
One healthy pass is already running on this host. Do not start a second scheduler; multi-host operation needs a distributed lock or adapter-native compare-and-set |
| Release waits for product acceptance | Publish a current feature-scope [product-approval] bound to the exact final feature HEAD and integration-evidence digest; stale or ambiguous evidence cannot release |
| Release says it is awaiting CI | Inspect the protected verifyCi result for the exact release commit. Failed, pending, skipped, missing, stale, mismatched, or unverifiable required checks block every apply; fix CI and rerun the release transaction—never bypass or replace this proof with a tracker comment. |
| Release says it is awaiting authorization | In approval-required mode, have the protected verifyApproval system authorize the exact manifest before its expiry; a board comment is intentionally insufficient |
| Release is fenced after an uncertain apply, detached-worker loss (exit 125), post-launch authority change, or target mismatch | Inspect the protected transaction and target status evidence. Repair the provider hook/target state and let the transaction reconcile; never blindly re-run apply or delete the fence |
| Want to verify the plumbing | bash tests/run-all.sh → ALL TESTS PASS (stub agents + local files; no LLM, no cost) |
Credits
Inspired by the PlatformPlatform product-management architecture, developed by Thomas Jespersen.
Optional Claude planning builds on
obra/superpowers, created by Jesse
Vincent and the Prime Radiant team. Startup Factory uses its planning and
task-local engineering methods while retaining independent ownership of
orchestration, review, integration, and production delivery.
License
MIT License
The canonical license file is LICENSE.
Copyright (c) 2026 ExecMatchAi
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file startup_factory-0.1.1.tar.gz.
File metadata
- Download URL: startup_factory-0.1.1.tar.gz
- Upload date:
- Size: 622.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab615d8713bb3a4390ecfc6239616a895eb74944d0c90ed89a6cba32e20669f7
|
|
| MD5 |
f10876009a4d80967755ce97aa5e22bd
|
|
| BLAKE2b-256 |
7ad1c632df0814066c66bee4726dfb1c4d05972706222b8ba45d1af3eaf0aaec
|
Provenance
The following attestation bundles were made for startup_factory-0.1.1.tar.gz:
Publisher:
release.yml on alexrolls/startup-factory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
startup_factory-0.1.1.tar.gz -
Subject digest:
ab615d8713bb3a4390ecfc6239616a895eb74944d0c90ed89a6cba32e20669f7 - Sigstore transparency entry: 2195311112
- Sigstore integration time:
-
Permalink:
alexrolls/startup-factory@3c8da2189709b01bb951d725508d6acede58cede -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/alexrolls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3c8da2189709b01bb951d725508d6acede58cede -
Trigger Event:
push
-
Statement type:
File details
Details for the file startup_factory-0.1.1-py3-none-any.whl.
File metadata
- Download URL: startup_factory-0.1.1-py3-none-any.whl
- Upload date:
- Size: 549.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd4aa7602c04188ec40b539ad7ee576b07856db12a938107466dd03645c73c11
|
|
| MD5 |
ea3d288774c512c50494e4dc62182f55
|
|
| BLAKE2b-256 |
7c1c829fdbf4ebe617bf6c2aad089b0d9d80647398a445f6d6a5344256cff75a
|
Provenance
The following attestation bundles were made for startup_factory-0.1.1-py3-none-any.whl:
Publisher:
release.yml on alexrolls/startup-factory
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
startup_factory-0.1.1-py3-none-any.whl -
Subject digest:
fd4aa7602c04188ec40b539ad7ee576b07856db12a938107466dd03645c73c11 - Sigstore transparency entry: 2195311151
- Sigstore integration time:
-
Permalink:
alexrolls/startup-factory@3c8da2189709b01bb951d725508d6acede58cede -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/alexrolls
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3c8da2189709b01bb951d725508d6acede58cede -
Trigger Event:
push
-
Statement type: