Execution Gates
Gates are checkpoints where Trinity pauses the pipeline and asks for your input. They keep you in control of decisions that the agent can't (or shouldn't) make on its own.
How Gates Work
When an agent or the coordinator detects a situation that needs human judgment, it raises a gate. The job transitions to waiting_gate, a notification appears on the Run page and in the sidebar task indicator, and the pipeline won't advance until you respond.
Gates are tied to an entity (either a story or a release). Each gate carries a typed payload describing what triggered it — the same structure powers both the UI and the feedback pipeline.
Gate Types
The full set of gate types (from the JobGateType enum):
Deviation Approval (deviation_approval)
Payload: The agent's analysis, the proposed alternative, and the reasoning for the substitution.
- Approve — accept the substitution; the implementer uses the alternative
- Reject — keep the original technology; the implementer proceeds as planned
Missing Assets (missing_assets)
Payload: One card per declared need, each with a purpose line and a prose description of what the story expects.
- Save & Continue — upload real assets to those cards, then the story replans with the new assets in hand
- Use Placeholders — explicit opt-in. Trinity threads this choice back into the analyst as a feedback directive so it doesn't redeclare the same need on replan. The post-checkpoint placeholder audit remains the safety net.
Skip globally: toggle skipAssetCheck in project settings or globally. The flag is resolved up front and threaded into the analyst prompt so the analyst never declares when you've opted out.
Checkpoint + Release Placeholder Audits
Quality checkpoints run a full-worktree placeholder scan in addition to the analyst-plan pre-flight. Two regex families are independent:
- Images (
skipCheckpointAssetAudit/skipReleaseAssetAudit) — catches shippedplaceholder.svg,picsum.photos, Lorem ipsum, etc. - Contacts (
skipCheckpointBusinessDetailsAudit/skipReleaseBusinessDetailsAudit) — catchesexample.comemails,555-*phones,John Doe,Your Company, stale copyright years.
Findings surface as entries on the quality checkpoint gate — each with file:line refs.
Agent triage: when the scan finds anything, an agent classifies each match as leak (blocks), fixture / docs (info, non-blocking), or false_positive (dropped). For leaks, the agent also suggests a replacement using the project's uploaded assets + business details. If the agent itself fails, raw scan warnings surface unchanged.
Custom excludes: placeholderAuditExcludes (project / team / global) is a list of glob patterns added to the hard-coded base list (node_modules/, **/__tests__/**, etc.). A .trinityignore file at the worktree root is also honoured (gitignore syntax).
On-demand scrub: Project Settings → Audit Codebase runs the same scan at any time — informational, nothing blocks.
Missing Business Details (missing_business_details)
Payload: Which fields are missing + why the story needs them.
- Fill in details in Project Settings → Business, then resume
- Skip — proceed without business details
Skip globally: toggle skipBusinessDetailsCheck in project settings or globally.
Missing Secret (missing_secret)
Payload: Each missing key — the service it belongs to, the env var name it's injected as, and why the story needs it.
- Save & Resume — enter the values directly in the gate dialog, one masked field per key. Trinity saves them encrypted to your secrets, then resumes the run with the keys injected into the agent's environment.
This is a blocking gate with no skip: the analyst pauses at the tool call and the run waits right here until you provide the keys (or the hold window elapses, after which the gate resumes through the normal flow). You provide the secrets inline — there's no "go to Project Settings and come back."
Waiting for Key Grant (waiting_key_grant)
Payload: The key_names with visible-but-undecryptable rows, and the team whose grant is pending (when the scope is a team).
- Check again — the only action. Once a key holder approves the grant from another device, click this; the run re-runs its decryptability check and clears when the key has landed (or re-arms the same gate if it hasn't).
Service Setup Required (service_setup_required)
- Worker pre-flight — before the analyst phase even runs, Trinity scans the project's stack for rows marked
needs_keysand checks whether each one has a secret bound. Any gap fires the gate with the full list of services to set up. - Agent signal — any pipeline phase can raise the gate mid-execution via the
signal_service_requiredtool when it discovers a service the worker pre-flight didn't catch (e.g. an internal SDK that needs a project ID).
Payload: List of missing_services[] — each with the service name, target binding, and (for agent signals) the agent's goal and blockingReason.
- Configure — run the inline setup runner. Trinity launches the relevant playbook (e.g.
gh auth login, paste-from-dashboard) pre-bound to the right target. Captured values flow into the secrets store and any config files materialize to disk before the story resumes. - Skip — proceed without configuring (the agent owns the failure mode from here)
The setup runner is the same UI you've seen in Project Settings → Stack → Setup — pty-driven CLI, capture forms for tokens, paste prompts for values the CLI prints at the end.
External Dependencies (external_deps)
Payload: List of external deps (name, description) and a human-readable explanation.
- Diagnose — complete the external action, then open the chat to describe what you provisioned or configured. Your report threads back to the agent and the story resumes.
Story Blocked (story_blocked)
Payload: Which agent phase escalated, a prose explanation of what's stuck, and (optionally) the list of approaches the agent already tried — so you know what not to suggest.
- Diagnose — open a diagnostic chat to investigate the blocker; submitting your guidance re-enters the story through the feedback pipeline.
- Cut story — give up and mark the story Failed. The recorded cause reflects which agent was stuck: an audit-phase escalation records audit criticals; any other phase records retries exhausted.
There is no skip — diagnose the blocker or cut the story.
Story Failed (story_failed)
A structural failure (a report-missing run or an agent timeout) parks here after a single attempt rather than burning the full retry budget — re-running the same prompt just re-hangs, so there's no point exhausting retries first. The gate's header says so ("This story failed on its first attempt").
Payload: The coarse failure cause phrased for humans (e.g. "ran out of retries", "produced no implementation"), a short reason, and — when present — the verbatim implement-phase diagnostic (the actual hang/crash message).
- Diagnose — open a diagnostic chat to co-investigate the failure; submitting your guidance re-runs the story through the feedback pipeline. This is the recovery path.
- Cut story — give up and mark the story Failed, carrying through the recorded cause so the failure reads the same as why it originally failed.
There is no skip — recover via Diagnose or cut the story. The full blast-radius failure dossier is already filed for the architect when the story parks here, so a resolution proposal is usually waiting either way.
Repository Access (git_write_access)
Payload: Every managed repo you can't push to, each with its host and whether the block was confirmed. The repos the story's targets actually touch are called out to sharpen the message, but they never loosen the gate.
- Check again — runs a fresh read-only re-probe. It resolves to access confirmed, still blocked, or "couldn't verify — the host didn't answer."
- Request access — notifies the project owner that you need write access to the listed repos (an entry in their activity inbox).
- Start story / Start anyway — always available, because it's the appeal: starting runs the story through to its push, which is the real test — a successful push overturns a stale negative, a genuine block re-confirms it. After a clearing re-check the button reads Start story; otherwise Start anyway.
PR Review (pr_review)
Payload: PR URLs + repo names (multi-repo projects get one entry per repo).
- Approve — continue the merge chain
- Provide feedback — re-run the feedback pipeline against your review comments
- Skip — cancel this leg of the merge
Quality Checkpoint Approval (quality_checkpoint_approval)
Payload: Audit findings, fixes applied, any remaining issues.
- Approve — marks the checkpoint passed
- Skip — acknowledges unresolved issues and continues
- Provide feedback — re-enter the feedback pipeline
Merge Conflict (merge_conflict)
Payload: Which repo, branch, and base branch are conflicting. Shown alongside a "resolve locally" hint.
- I resolved it — retry — re-run the merge after you pushed a manual conflict resolution
- Diagnose — open a chat to investigate the conflict; submitting your fix plan retries the merge with that plan threaded into the conflict-resolver agent's prompt as authoritative guidance
- Cut story — give up on the story and mark it Failed
External PR Closed (external_pr_closed)
Payload: PR URL, branch, and repo — so you can see what was closed.
- Recreate PR — re-open a fresh PR with the same branch and keep going
- Diagnose — open a chat to investigate before deciding; submitting from the chat recreates the PR
- Cut story — give up on the story and mark it Failed
Partial Merge Failed (partial_merge_failed)
Payload: Which repos succeeded vs. failed, with error details per failed repo.
- Retry Failed — re-attempt the merge for just the failed repos; already-merged repos are untouched
- Cut story — give up and mark the whole story Failed. Repos that already merged keep their code on the branch, but the story blocks dependents until you fix or cut it — it never reads "merged" with a repo's work missing.
This gate is specific to polyrepo projects — a single unresolved conflict (with nothing merged yet) raises merge_conflict instead.
Re-auth Required (reauth_required)
Payload: The account and host that need re-authentication, which op failed and on which repo, and a fix hint. The gate is tied to either a story (a story job's git op) or a release (a release-finalize push).
- I've re-authenticated — resume — confirms you re-authenticated the credential out-of-band; Trinity re-runs only the failed op (re-push, re-open the PR, or re-merge), never the whole story or release
- The give-up action depends on the entity:
- Cut story (story jobs) — marks the story Failed. A story that can't push didn't land — it isn't skipped, and it blocks dependents until you fix or cut it.
- Skip this step (release runs) — records the release as
partially_released; repos that were already tagged persist.
Commit Email Needed (commit_email_required)
Payload: The host the author email is missing for, which op was blocked (push, PR open, or merge) and on which repo, and a fix hint. Tied to either a story or a release-finalize commit/tag.
- Set commit email & resume — set a verified commit email for the host directly in the gate. The field prefills a suggestion from your account, validates against your verified addresses on that host (only verified emails are accepted), and offers one-tap chips. Once set, Trinity re-runs only the parked op.
- The give-up action depends on the entity:
- Cut story (story jobs) — marks the story Failed.
- Skip this step (release runs) — ships as
partially_released.
You can also set this ahead of time: each connected account carries a commit email you can set in the connect flow or override per account in Settings — see Signing In → Commit email per account.
Tool Not Installed (tool_missing)
Payload: Which binary is missing and its install recipe, plus the underlying error for diagnostics.
- I've installed it — resume — confirm you installed the tool (via the inline recipe or on your own); Trinity re-runs the pipeline.
- Cut story — give up and mark the story Failed.
Cutting a Story
The failure gates (merge_conflict, partial_merge_failed, external_pr_closed, reauth_required, commit_email_required, tool_missing, story_blocked, story_failed) share Cut story as their give-up action (on release runs, reauth_required and commit_email_required offer Skip this step instead). Cutting is honest failure, not deletion:
- The story is marked Failed with a cause that records the obstacle — see the cause table in Stories → Failed Stories. Nothing is deleted: branches, PRs, and repos that already merged keep their code.
- A failed story blocks its dependents until it's resolved, so the plan never builds on work that silently went missing.
- Cutting files a failure dossier for the architect — the cause and reason, the attempt count, the gate's details, the latest conflict-resolution findings, and which stories are now stuck — and the architect immediately drafts a resolution proposal from it (retry, reshape, or delete). By the time you open the failed story, a reviewable way forward is usually waiting.
The same dossier is filed when a story fails without a gate (retry exhaustion, an implement run that produced no changes), so every failure — cut or automatic — carries the same paths to resolution. How loudly a failure surfaces depends on what it blocks — see Running → Failed Stories on the Run Page.
Gate Feedback
Instead of a binary approve/skip, every gate supports a feedback response that re-enters the story (or release) through the feedback pipeline:
- Triage — the agent classifies what you're asking for
- Analyst — re-reads the codebase with your feedback as context
- Implementer — makes changes (no commit)
- Audit loop — Auditor passes over the new changes
- Documenter — commits, updates the PR, walks the merge chain
This is the sanctioned way to iterate on agent output without editing code yourself. It's the same shape for story gates and release gates.
Attachments
When you provide feedback, you can attach files:
- Screenshots of desired behavior
- Updated wireframes or specs
- API contracts or documentation
- Anything the agent might need to reason about
Attachments are scoped to the gate and cleaned up when the gate resolves (approve / skip / merge). They're not mixed into project assets.
Gate Reentry
Every gate tracks how many times it's been re-entered via gate_reentry_count. Visible on the gate card — useful for spotting stories that keep bouncing back through feedback without converging. If a story hits a high reentry count, that's usually a sign the problem needs manual intervention or a restructured plan.
Best Practices
- Respond promptly — gates block the pipeline, and dependent stories stall behind them
- Prefer feedback over skip — the feedback pipeline can fix most issues without you editing code
- Be specific — "Make the button blue" beats "This doesn't look right"; include screenshots when layout matters
- Use skip judiciously — bypassing a gate (skipping a checkpoint, a merge leg, or release notes) can leave downstream work brittle; the gate exists for a reason
- Audit skipped gates — check the activity feed to see which gates you skipped and why