Work Types
research→backlog-writer→dev→qa→acceptance pathway.
The Rensei SDLC pipeline decomposes software work into five canonical stages. Each stage runs a focused agent with a defined purpose, a budget cap, and a handoff contract - ensuring that agents stay on-task and that humans stay informed at every transition.
The five stages
The stage vocabulary is platform-owned. Stage IDs appear in CloudEvent types (com.rensei.stage.<id>.start / .complete), in workflow YAML (spec.lifecycle.<id>), and in stage-trigger logs. Renaming a canonical stage ID is a breaking change.
research
Investigate the problem, prior art, options, and constraints. Produces a research brief. Emits NO code.
backlog-writer
Convert the research brief into a well-formed, sized, dependency-aware backlog item. Emits NO code.
development
Implement the backlog item end-to-end: code, tests, docs. Decides internally whether to spawn sub-agents.
qa
Validate the implementation against acceptance criteria. Produces a QA report; may run smoke tests and exploratory checks.
acceptance
Final human-aligned sign-off. Confirms the work meets original intent before the issue closes.
There is also a refinement stage that activates when QA or acceptance fails - it reads failure history, clarifies corrective requirements, and routes the issue back to the appropriate state.
Stage defaults and budgets
Each stage has a default budget the dispatcher enforces when no per-workflow override is present:
| Stage | Max duration | Max sub-agents | Max tokens | Work type |
|---|---|---|---|---|
research | 30 min | 5 | 200,000 | research |
backlog-writer | 15 min | 2 | 80,000 | backlog-writing |
development | 4 hr | 8 | 1,500,000 | development |
qa | 1 hr | 4 | 400,000 | qa |
acceptance | 30 min | 1 | 60,000 | acceptance |
refinement | 30 min | 3 | 160,000 | other |
Budget overrides are per-lifecycle-config, not per-template. Custom workflows can declare different maxDurationSeconds, maxSubAgents, and maxTokens per stage in their spec.lifecycle block.
The workType field
Every dispatch leaf in the SDLC template stamps a workType on the dispatched session. The routing engine uses this for model selection, capability gating, and analytics aggregation:
# Example agent dispatch leaf config (development role)
workType: development| Role | workType value |
|---|---|
| research | research |
| backlog-writer | backlog-writing |
| development | development |
| qa | qa |
| acceptance | acceptance |
| refinement | other |
The workType is also the primary dimension in the Routing Intelligence Thompson Sampling posteriors - the platform learns which model + provider combination yields the best outcome per workType over time.
Pathway flow
The canonical pathway through the pipeline maps tracker state transitions to stage activations:
Each arrow represents an agent dispatch followed by an automatic issue-state transition at session completion. The Linear branch uses linear.issue.advance; the GitHub Issues branch uses github_issues.label.replace.
The research and backlog-writer distinction
Research and backlog-writer are the two stages that explicitly produce no code. This is a hard invariant:
- Research agents investigate; they may read files, search the web, consult the architecture corpus, and write a structured brief into the issue. They do not open PRs or modify source files.
- Backlog-writer agents refine; they turn the brief into a well-formed, sized, acceptance-criteria-complete backlog item. They do not implement anything.
This separation prevents premature implementation from polluting the planning record and ensures the development agent starts with a clear, human-reviewable brief.
If you bypass the research or backlog-writer stages by pushing an issue directly to Backlog, the development agent dispatches without a research brief. The agent will attempt the task anyway but may produce lower-quality output due to the missing context.
The @-mention routing shortcut
The Linear branch includes a keyword-routing chain (rensei.text.strip_mentions → rensei.text.keyword_prefix) that inspects the first word of an @-mention body to choose between dispatching a research or backlog-writer agent directly:
@rensei research <problem description> → dispatches research agent
@rensei backlog <brief> → dispatches backlog-writer agentAny other first word falls through to the default status-driven path.
Condition nodes that gate dispatch
Several linear.issue.predicate nodes guard dispatch along the pathway. Common checks in the default template:
| Check | Purpose |
|---|---|
is_terminal | Skip exit-handler processing for already-closed issues |
project_allowed | Ensure the issue belongs to a project the workflow is subscribed to |
assignee_is_human | Skip dispatch when the issue has a human assignee (anti-loop guard) |
status_equals | Match the specific tracker status before routing to a stage |
See Condition Nodes for the full linear.issue.predicate configuration reference.
Capability injection per stage
The capability matrix is wired at the foundational node level - capabilities flow to dispatch leaves through multi-target edges from the shared capability.* foundational nodes. At dispatch time, the platform resolves each CapabilityRef into a live subsystem:
| Capability | Resolved to |
|---|---|
memory (scope: project) | Project-scoped observation store; read at session start, written on completion |
architecture (corpusConfigs: [{repo}]) | Architecture intelligence corpus for the issue's repo |
code-intel (repo) | Code-intelligence index (symbol search, repo map) for the issue's repo |
The repo field in architecture and code-intel refs uses ={{ trigger.data.repo }} - this is a runtime expression resolved from the inbound CloudEvent, not a static string.
Extending the stage vocabulary
The stage registry supports runtime extension for marketplace templates. Custom stage IDs must match ^[a-z][a-z0-9-]{0,63}$ and are registered by calling registerStage(). Extension-registered stages cannot override canonical IDs.
Canonical stage IDs are reserved and stable. You cannot rename research, backlog-writer, development, qa, acceptance, or refinement - doing so would break CloudEvent routing, lifecycle config parsing, and the analytics aggregation layer.
Lifecycle config reference
The spec.lifecycle block in a workflow YAML maps stage IDs to tracker state transitions. A minimal custom lifecycle that adds a security-review extension stage between development and QA:
spec:
lifecycle:
research:
trigger:
event: issue.transitioned
when: { to: "Icebox" }
exit:
transition_to: "Triage"
backlog-writer:
trigger:
event: issue.transitioned
when: { to: "Triage" }
exit:
transition_to: "Backlog"
development:
trigger:
event: issue.transitioned
when: { to: "Backlog" }
exit:
transition_to: "In Security Review"
on_fail: "Rejected"
qa:
trigger:
event: issue.transitioned
when: { to: "Finished" }
exit:
transition_to: "Delivered"
on_fail: "Rejected"
acceptance:
trigger:
event: issue.transitioned
when: { to: "Delivered" }
exit:
transition_to: "Accepted"
on_fail: "Rejected"The on_fail field is optional. When omitted, a failed stage does not auto-transition the issue - the human is expected to decide next steps.
For the full spec.lifecycle schema see Lifecycle Config.