Synaptory User Guide
Single-file documentation build for offline distribution.
Synaptory User Guide
Multi-agent adaptive delivery — orchestrate the best AI for each role.
The Problem
Most AI coding tools make you faster at writing code. You still play every other role yourself: project manager, architect, QA lead, security reviewer, DevOps engineer — all at once. You prompt, review, iterate, manually wire things together, figure out tests, set up CI/CD, and write docs. The AI writes files; you do everything else.
The Shift
synaptory changes what you are doing entirely. You describe what you want to build. Nine specialized agents — Project Owner, Solution Architect, Software Engineer, Code Reviewer, Quality Engineer, Compliance Engineer, Platform Engineer, Technical Writer, and Research Advisor — coordinate through an adaptive delivery lifecycle to produce a complete system: architecture decisions, tested backend and frontend, security audit, infrastructure, and documentation. You sit in the strategist's seat — approving direction, not directing labor.
The system is built on one principle: do the work, don't describe the work. When a decision has a clearly superior option, agents take it and report what they chose and why. Results are reported, not plans.
How It Works
synaptory classifies every request automatically into one of three operation layers. Just describe what you need — the orchestrator routes to the right agents.
flowchart TD
prompt["Your prompt"] --> orchestrator["Orchestrator classifies intent"]
orchestrator --> scrum["Scrum Lifecycle"]
orchestrator --> kanban["Kanban Lifecycle"]
orchestrator --> util["Standalone Utility"]
scrum --> inception["Inception → Sprint Loop → Release"]
kanban --> discover["Discover → Ticket Flow → Release"]
util --> modes["Debug / Explore / Branch Finish / Story Buddy / ..."]
Scrum Lifecycle (greenfield or brownfield)
For new products or major capabilities built iteratively:
Inception --> Sprint Planning --> Sprint Execution --> Sprint Review
|
Sprint Close <-- Sprint Retro (adaptive) <-+
|
+--> Next Sprint (loop) or Release
Per-story pipeline: Every story flows SE (implement) → QE (test) → CR (review) → DoD evaluation. Quality is verified per story, not at the end.
Kanban Lifecycle (brownfield maintenance)
For post-launch maintenance and continuous ticket flow on existing codebases:
Discover --> Ready --> Execute ticket --> Review --> Ready (loop)
|
+--> Release (on-demand)
Standalone Utilities
Debug, Explore, Discover, Preview, Branch Finish, Story Buddy, Retro, Init, Status, Help — no lifecycle context needed. "Review my code" routes to the Code Reviewer. "Debug this error" runs structured root-cause analysis.
What You Get
From a single prompt, a Scrum delivery produces (iteratively, sprint by sprint):
- Requirements and architecture — BRD, ADRs, system design, API contracts
- Working code — backend services, frontend UI, design system
- Tests — unit, integration, e2e, and performance test suites
- Security — OWASP/STRIDE threat model, dependency scan, compliance audit
- Infrastructure — IaC modules, Kubernetes manifests, CI/CD pipelines
- Documentation — API reference, developer guides, runbooks
- Ticket tracking — stories, epics, sprints managed in your tracker (local, GitHub Issues, Jira Cloud, or Teamwork)
Not every task needs the full lifecycle. Standalone modes handle scoped work — from a targeted Debug or Code Review to Story Buddy per-ticket workflows and brownfield reverse-engineering.
Choosing the Right Path
| If your situation is... | Use | Why |
|---|---|---|
| Starting a new product or major capability | Build / Scrum | Inception, sprint planning, iterative delivery, Release |
| Existing codebase needing ongoing maintenance | Kanban | Discover first, then continuous ticket-based flow |
| Know the story and want focused help on one item | Story Buddy | Requirements, implement, test, or sprint-planning without the full lifecycle |
| Active failure needing root-cause analysis | Debug | Structured reproduce → isolate → understand → fix loop |
| Verification before merging or shipping | Branch Finish or Release | Branch Finish is branch-scoped; Release is full production-readiness |
| Unfamiliar brownfield system to understand first | Discover | Builds context packages and risk awareness before delivery starts |
Quality Model
One human gate at project start. Continuous automated verification on every story.
| Checkpoint | When | What you review |
|---|---|---|
| Inception Gate | After Sprint 0 | Project direction — vision, epics, Sprint 1 stories, architecture foundations |
| Per-Story DoD | Every story | Automated: tests pass, build succeeds, no critical findings, code reviewed (adaptive) |
| Sprint DoD Overlay | Sprint Review (Scrum) | Sprint Goal met, feedback addressed, no regression, docs updated |
Between checkpoints, agents work autonomously — building, testing, reviewing, and fixing their own failures.
AI Model Routing
All agents in this build run on Claude. The Orchestrator selects the model tier based on role type:
| Tier | Agents | Rationale |
|---|---|---|
| Opus | PO · SA · CE · RA | Strategic decisions — scope, architecture, risk, direction |
| Sonnet | SE · QE · PE · TW · CR | Execution roles — implement, test, review, document |
The active tier is fixed per role. The only lever is engagement_mode: structured | interactive in .synaptory.yaml.
Configure in .synaptory.yaml:
agents:
default_backend: "claude"
Ticket Tracking
All story, epic, sprint, and backlog operations go through a pluggable tracker adapter. Every agent calls the same tracker_cli.py commands regardless of backend.
| Backend | Storage | When to use |
|---|---|---|
local | .synaptory/.orchestrator/tracker-data.json | Default. Zero deps. Solo or small team. |
github | GitHub Issues (types + milestones + labels) | Team with GitHub repo. |
jira | Jira Cloud (native types + Scrum board) | Enterprise with Jira. |
teamwork | Teamwork Projects (tasks + milestones) | Teams using Teamwork. |
Runtime Artifacts
synaptory persists lifecycle state and evidence under .synaptory/.orchestrator/:
| Artifact | Purpose | When it appears |
|---|---|---|
pipeline-state.json | Source of truth for Scrum or Kanban lifecycle state | After Init and throughout delivery |
receipts/ | Story-scoped machine-verifiable agent receipts | After each subagent completes work |
context-packages/ | Brownfield reverse-engineering outputs from Discover | After Discover or Context Refresh |
last-session.md | Snapshot for cross-session resume | On session stop |
tracker-data.json | Local tracker state when using the local backend | When local tracking is enabled |
Documentation Guide
Concepts — How synaptory thinks
| Page | Description |
|---|---|
| The Synaptory Platform | How the plugin, CLI, and Control Plane fit together |
| Platform Architecture | Deeper view: per-URL routing, request sequence, where every artifact lives |
| Identity and Access | Entra OAuth, synaptory-users vs synaptory-admins, project membership |
| Personas | Five roles that touch the platform and their entry points |
| Delivery Lifecycle | The adaptive lifecycle: Scrum ceremonies, Kanban flow, story pipeline |
| Modes | Operation modes and how the orchestrator classifies requests |
| Agents | The 9 agents, their roles, backends, and authority boundaries |
| Engagement Modes | Autonomous vs. Controlled execution |
| Enforcement | Receipts, DoD evaluation, safety nets |
| v3.0 Roadmap | What's next: spec graph, four-gate model, evidence ledger, policy/domain packs, runtime adapters |
Guides — How to do things
| Page | Description |
|---|---|
| Scrum Delivery | Complete walkthrough: Inception through sprint ceremonies to Release |
| Kanban Delivery | Continuous ticket-based delivery and brownfield workflows |
| Multi-Spec Delivery | Running multiple parallel specs out of one repo + one Jira project |
| Release | Shipping to production from Scrum or Kanban |
| Resuming Sessions | Cross-session persistence and progress tracking |
| Using the Control Plane | Page-by-page tour of synaptory.h3t.co (role-aware: every signed-in user gets the same app, scoped to their grants) |
| Inviting Members | End-to-end flow for granting and revoking project access |
Reference — Lookup information
| Page | Description |
|---|---|
| Configuration | Complete .synaptory.yaml schema |
| Commands | All CLI commands and tools |
| Routing | Every mode the orchestrator can dispatch and the tiebreakers between them |
| Rules | The 10 behavioural rules auto-injected on every session start |
| Hooks | Lifecycle hooks and enforcement |
| URLs | Every public URL on synaptory.h3t.co and what it serves |
| Auth Flows | Web code-flow, CLI PKCE, and local-auth fallback (sequence diagrams) |
| Permissions | What each Entra group + project role grants |
| Glossary | v2.5 ↔ v3.0 vocabulary map and platform terminology |
Troubleshooting
| Page | Description |
|---|---|
| Troubleshooting | Common issues and fixes |
Reading Paths by Role
PM / BA — Requirements and delivery strategy
- Delivery Lifecycle — Understand ceremonies and the story pipeline
- Scrum Delivery — Sprint Planning, Review, and your role in each ceremony
- Agents — Project Owner behavior and authority boundaries
- Configuration — build_mode, tracker, and sprint settings
Dev — Implementation and architecture
- Modes — Debug, Story Buddy, Branch Finish, and other modes you use daily
- Agents — Software Engineer modes, tech packs, Code Reviewer boundaries
- Kanban Delivery — Working with existing codebases
- Resuming Sessions — Cross-session persistence
QE — Verification and quality
- Enforcement — Receipts, DoD evaluation, safety nets
- Agents — Quality Engineer modes, Compliance Engineer, Code Reviewer
- Delivery Lifecycle — Per-story pipeline and adaptive DoD
- Hooks — Verification hooks and enforcement behavior
Control Plane user — Any signed-in member of synaptory-users
- Personas — Confirm where you fit
- Using the Control Plane — Page-by-page tour (role-aware)
- Identity and Access — Why your view is scoped to you
- Auth Flows — Sign-in path and session revoke
Project admin — Granting access
- Inviting Members — Three paths and their tradeoffs
- Permissions —
membervsadmincapabilities - Using the Control Plane — Members tab specifics
Global admin — Operator cockpit
- Personas — Confirm where you fit
- Using the Control Plane — Admin-only pages
- Platform Architecture — Where every artifact lives
- Permissions — What
synaptory-adminsgrants - URLs — Every URL on
synaptory.h3t.co
Getting Started
Four steps from zero to your first delivery run.
New here? The plugin you're installing is the in-IDE component of a larger platform — there's a separate Go CLI, a control plane, and web surfaces. Read The Synaptory Platform for a 5-minute overview of how they fit together.
Step 1 -- Install the plugin and the CLI
The plugin lives in the H3Tech marketplace; the CLI is shipped separately. Install both once.
Plugin:
/plugin marketplace add https://synaptory.h3t.co/marketplace
/plugin install "synaptory@h3tech-ai"
Choose User scope for all projects, or Project scope for the current project only. Restart Claude Code afterwards.
CLI (one install per laptop, shared across every synaptory project):
# macOS / Linux
curl -fsSL https://synaptory.h3t.co/cli/install.sh | bash
# Windows (PowerShell)
iwr -useb https://synaptory.h3t.co/cli/install.ps1 | iex
See Install the CLI for the full walk-through, PATH setup, and updates.
Step 2 -- Sign in
synaptory authenticates through your organisation's Microsoft Entra ID. One sign-in per laptop — the same session works across every project you're a member of (the way gh and aws work).
How it works
After the plugin is installed and Claude Code restarts, the session-start hook checks for a cached session. If none is valid (or refreshable), it surfaces an instruction to run:
synaptory login
A browser tab opens to your org's sign-in page. After sign-in the CLI prints the projects you have access to:
login: signed in as you@yourorg.com (session expires 2026-04-26T09:15:00Z)
login: member of 2 project(s): taskflow-pilot, synaptory-build
The session is cached in the OS keychain — you won't be prompted again until the token expires (typically 24 hours; the CLI refreshes it silently when possible).
Headless environments (no browser)
If you're on a server or CI machine where a browser can't open, run the device-code flow once from a terminal:
synaptory login --device
Follow the on-screen instructions: visit the URL shown, enter the code, and approve. The session is cached in the same keychain store and produces the same user-scoped token as the browser flow.
Telling synaptory which project this repo belongs to
Each repo carries a one-line config that maps it to a control-plane project slug:
# .synaptory.yaml
project_id: "my-project"
Or per-shell:
export SYNAPTORY_PROJECT_ID=my-project
The CLI walks up from your current directory looking for the file, the same way git finds .git/. Telemetry and skill fetches stamp this slug onto each request, and the server checks your membership against project_members per call.
Verify sign-in at any time
synaptory whoami # UPN, expiry
synaptory projects list # what you can see, with your role in each
If sign-in fails, check the troubleshooting section or run synaptory status for a full diagnostic.
Note: All skill access is scoped to your session identity. Usage is watermarked and auditable by your H3Tech operator.
Step 3 -- Configure your project
Say "initialize my project" to scan your codebase and generate .synaptory.yaml:
initialize my project
What it auto-detects:
- Language --
package.json,go.mod,pyproject.toml,Cargo.toml,pom.xml - Framework --
next.config.*,nest-cli.json,fastapi,gin,actix - Infrastructure --
Dockerfile*,terraform/,k8s/,.github/workflows/ - Architecture -- monolith, modular-monolith, microservices, monorepo
The orchestrator shows a detection summary and asks before writing. Review the generated config before your first run.
Key configuration choices
build_mode: "scrum" # scrum (default) or kanban
engagement_mode: "structured" # structured (default) or interactive
agents:
default_backend: "claude" # claude only in this build
Key decision — engagement mode:
structureduses Opus for strategic roles (PO, SA, CE, RA) and Sonnet for executors (SE, QE, PE, TW, CR) — agents decide and report without surfacing every choice.interactiveuses the same model tiers but strategic roles surface all major decisions for your review before proceeding — no cost premium, just more visibility. Usestructuredfor most sprint work; switch tointeractivefor Release or regulated-industry builds. See Engagement Modes for a scenario guide.
Ticket tracker (optional)
By default, synaptory uses a local JSON tracker -- zero external dependencies. If your team uses GitHub Issues, Jira Cloud, or Teamwork, add a tracker section:
tracker:
backend: github # or: local (default), jira, teamwork
github:
repo: your-org/your-repo
GitHub requires gh CLI authenticated (gh auth login). Jira requires JIRA_API_TOKEN and JIRA_USER_EMAIL env vars. Teamwork requires TEAMWORK_API_KEY env var.
Step 4 -- Your first delivery run
Just describe what you want to build:
Build me a SaaS for managing restaurant reservations with a React frontend and Node.js backend
What happens next:
- Classification -- the orchestrator identifies this as a Build (Scrum lifecycle)
- Engagement mode -- Autonomous (cost-optimized) or Controlled (maximum visibility)
- Inception -- Project Owner defines vision and Sprint 1 stories. Solution Architect creates foundation ADRs. Platform Engineer bootstraps CI/CD.
- Inception Gate -- you review the project direction and approve
- Sprint 1 -- stories flow through the per-story pipeline: SE implements -> QE tests -> CR reviews -> DoD evaluation
- Sprint Review -- demo working software, capture feedback, sprint metrics
- Sprint 2+ -- ceremonies repeat with adaptive intensity
- Release -- when ready, full verification at maximum depth
From first prompt to working increment, you made one strategic decision (Inception Gate). The agents made hundreds.
Quick path chooser
Use these starting prompts when you want to land a specific mode directly:
| Goal | Prompt | Expected path |
|---|---|---|
| Greenfield product build | Build me a SaaS for managing restaurant reservations | Build -> Scrum lifecycle |
| Brownfield reverse-engineering | Understand this codebase and prepare a delivery plan | Discover |
| Brownfield maintenance | Work on TICKET-142 to fix checkout retries | Kanban |
| Focused story execution | Implement US-037 | Story Buddy |
| Root-cause analysis | Debug why login returns 500 in staging | Debug |
| Production readiness | Run Release readiness for this project | Release |
End-to-end examples
Example 1 -- Greenfield Scrum run
initialize my projectBuild me a SaaS for managing restaurant reservations- Review the Inception Gate output and approve Sprint 1
- Let stories flow through SE -> QE -> CR -> DoD
- Continue with
next sprintuntil ready - Trigger
release
Example 2 -- Brownfield Kanban run
initialize my projectUnderstand this codebase and prepare a delivery plan- Choose Kanban after Discover
Work on TICKET-142 to fix checkout retries- Review the completed ticket and DoD evidence
- Trigger
releasewhen you want a production shipment
Runtime artifacts to expect
synaptory writes working state into .synaptory/.orchestrator/:
pipeline-state.json-- current lifecycle state, stories, metricsreceipts/-- per-story or per-ticket evidence from each agentcontext-packages/-- Discover outputs for brownfield projectslast-session.md-- session snapshot for resumetracker-data.json-- local tracker state when using the local backend
These files are useful when resuming work, auditing a run, or troubleshooting.
Parallel story execution
synaptory can dispatch up to parallelism.max_concurrent_subagents (default: 3) agent tasks simultaneously. The orchestrator manages the pipeline so QE can verify one story while SE implements the next.
If a subagent times out or fails, the orchestrator retries up to resilience.story_retry_cap times (default: 2) before marking the story blocked. Reduce story size if retries happen repeatedly.
Reading paths by role
Everyone should start with Delivery Lifecycle and Engagement Modes for shared vocabulary. Then follow the path for your primary role.
PM / BA -- Requirements and delivery strategy
- Scrum Delivery -- Sprint Planning, Review, and your role in each ceremony
- Agents -- Project Owner behavior and authority boundaries
- Configuration -- build_mode, tracker, and sprint settings
Dev -- Implementation and architecture
- Modes -- Debug, Story Buddy, Branch Finish, Preview, and other modes you use daily
- Agents -- Software Engineer modes, tech packs, Code Reviewer boundaries
- Kanban Delivery -- Working with existing codebases
- Resuming Sessions -- Cross-session persistence
QE -- Verification and quality
- Enforcement -- Receipts, DoD evaluation, safety nets
- Agents -- Quality Engineer modes, Compliance Engineer, Code Reviewer
- Kanban Delivery -- Coverage ratchet protocol
- Hooks -- Verification hooks and enforcement behavior
What's next?
- Scrum Delivery guide -- Detailed walkthrough of the complete Scrum lifecycle
- Kanban Delivery guide -- Continuous ticket-based delivery for existing codebases
- Delivery Lifecycle -- Understand the adaptive lifecycle in depth
- Configuration -- Tune
.synaptory.yamlfor your project
Install the synaptory CLI
The synaptory CLI handles sign-in, session state, and encrypted-skill delivery. Install it once per laptop — the same install works across every synaptory project you're a member of (the same way gh or aws work).
The CLI is shipped separately from the Claude Code plugin. Installing the plugin no longer carries the binary; the marketplace publishes a download script that detects your OS / architecture, verifies SHA-256, and drops the binary onto your $PATH.
macOS / Linux
curl -fsSL https://synaptory.h3t.co/cli/install.sh | bash
That's it. The script:
- Detects
darwin-arm64,darwin-amd64,linux-amd64, orlinux-arm64. - Downloads the binary and
sha256sums.txtfrom the marketplace'scli/latest/. - Verifies the SHA-256 before installing.
- Installs to
~/.local/bin/synaptory. - Tells you the line to add to
~/.zshrc/~/.bashrcif~/.local/binisn't on your$PATH.
After install:
synaptory version # confirm the CLI is on PATH
synaptory login # sign in via Entra (browser opens)
The login step prints the projects you can see right after sign-in, so you'll know immediately whether the operator has provisioned you correctly.
Custom install location
Set SYNAPTORY_CLI_PREFIX if ~/.local isn't where you want it:
SYNAPTORY_CLI_PREFIX=$HOME/Tools curl -fsSL .../cli/install.sh | bash
# installs to $HOME/Tools/bin/synaptory
Updating the CLI
Re-run the same one-liner. The script is idempotent and overwrites with the latest version.
Uninstall
rm ~/.local/bin/synaptory
synaptory logout # if you want the keychain cleared first
Windows
iwr -useb https://synaptory.h3t.co/cli/install.ps1 | iex
The script:
- Detects amd64 (the only Windows build we publish).
- Downloads
synaptory-windows-amd64.exeandsha256sums.txtfrom the marketplace'scli/latest/. - Verifies the SHA-256.
- Installs to
%USERPROFILE%\bin\synaptory.exe. - Adds
%USERPROFILE%\binto your userPATHif it isn't already (no admin needed; survives reboot).
If the script added a directory to PATH, open a new PowerShell window so the updated PATH is loaded. Then:
synaptory version
synaptory login
Updating
Re-run the same one-liner.
Uninstall
Remove-Item "$env:USERPROFILE\bin\synaptory.exe"
synaptory logout # not strictly required; the keychain entry is harmless
Commands every user should know
These are the commands you'll run directly. Hooks call the rest for you.
| Command | What it does |
|---|---|
synaptory login | Open a browser, sign in via Entra. Session is cached in the OS keychain. No --project flag — one sign-in covers every project you're a member of. |
synaptory whoami | Print the cached UPN and session expiry. First check when something feels wrong. |
synaptory projects list | List the projects you can see, with your role in each. Calls /v1/me/projects. |
synaptory status | Full diagnostic — control-plane URL, session state, skill cache, outbox depth. |
synaptory logout | Clear the cached session. Next Claude Code session will prompt you to sign in again. |
synaptory version | Print the CLI version. Useful when reporting issues. |
Less common, but good to know
| Command | When to use it |
|---|---|
synaptory skills list | See which skills are in your local cache. |
synaptory outbox flush | Manually flush queued telemetry if the control plane was unreachable. Normally automatic on session start. |
synaptory projects current | Print the project slug resolved from .synaptory.yaml / SYNAPTORY_PROJECT_ID. |
Switching projects
You don't. The same session works across every project you're a member of. The CLI auto-detects which project you're in by walking up from your current directory looking for .synaptory.yaml:
# .synaptory.yaml
project_id: taskflow-pilot
Telemetry and skill fetches stamp that slug onto requests. The server checks your membership against project_members per request — if you've been removed from a project, the next call returns 403 and the CLI quarantines the event for the operator to review.
What happens behind the scenes
You won't run these commands — Claude Code's session-start hooks call them for you:
synaptory-access-token-check.shrunssynaptory login --if-needed. If your cached session is still valid (or refreshable via the cached refresh token) it's a no-op; otherwise the hook surfaces the install instructions and pauses the session.synaptory-skills-fetch.shrunssynaptory skills syncto pull the encrypted skill bundle for this project.synaptory-load-rules.shdecrypts the rules for this session.synaptory-session-start.shrunssynaptory outbox flushandsynaptory telemetry session-start.
If any of those fail, you'll see a clear error message pointing at the fix.
Troubleshooting
| Symptom | Fix |
|---|---|
command not found: synaptory | The install dir isn't on $PATH. Rerun the install one-liner; it prints the line to add to your shell rc. |
synaptory: control plane URL not configured | The CLI binary you installed was built without SYNAPTORY_CP_URL stamped in. Ask your H3Tech operator for a rebuilt binary. |
synaptory: Entra OAuth is not configured | Same operator-side issue — the Entra tenant/client IDs weren't stamped at build time. |
login: you are not a member of any project yet | Your sign-in worked but the operator hasn't added your UPN to any project. Email ops@h3t.co with your UPN. |
403 user is not an active member of project '<slug>' mid-session | Either you've been removed from the project, or the slug in .synaptory.yaml is wrong. Run synaptory projects list to see what you can access. |
| Session expired mid-work | Run synaptory login again. No --project flag, no Claude Code restart needed. |
| macOS Gatekeeper blocks the binary | Run xattr -d com.apple.quarantine ~/.local/bin/synaptory. The binary is unsigned for the pilot; production builds will be notarized. |
For anything else, run synaptory status and include the output when you report the issue to ops.
The Synaptory Platform
Where the plugin sits, and what runs around it.
The Claude Code plugin you installed is one component of a larger system. Identity, skill delivery, telemetry, audit, and the marketplace itself live on a control plane operated by your H3Tech operator. This page explains how the parts fit together so the rest of the user guide makes sense in context.
If you only care about using the plugin, skip this and read Getting Started. Come back when you want to understand auth flows, where your data goes, or what "skill cache" means.
Why a platform, not just a plugin
A plugin alone can't enforce three things synaptory depends on:
- Per-user, per-project access — a single Claude Code install must work across multiple projects with different membership rules, without bundling credentials into the plugin.
- Watermarked skill delivery — the prompts and protocols that drive the agents are H3Tech IP. They're delivered at runtime against your authenticated session, not shipped as plaintext on disk.
- Audit and telemetry — every agent run produces a receipt; every receipt and token usage event lands in a place an operator can query.
So the plugin is intentionally thin. It registers hooks, defines agent stubs, and shells out to a separate Go CLI (synaptory) for everything that requires a session, a key, or the network.
Component map
flowchart LR
subgraph Laptop["Your laptop"]
CC["Claude Code"]
Plugin["synaptory plugin<br/>(hooks, agent stubs)"]
CLI["synaptory CLI<br/>(Go binary)"]
Cache[("OS keychain<br/>+ skill cache")]
CC --- Plugin
Plugin -.shells out.-> CLI
CLI --- Cache
end
subgraph CP["Control plane — synaptory.h3t.co"]
API["FastAPI"]
DB[("Postgres")]
Web["Web<br/>(Control Plane)"]
MP["Marketplace<br/>(/marketplace.git)"]
Bin["CLI binaries<br/>(/cli/...)"]
API --- DB
Web --- API
end
CLI <-.HTTPS.-> API
CLI <-.HTTPS.-> Bin
CC <-.git smart-HTTP.-> MP
| Component | Lives on | What it does |
|---|---|---|
| Claude Code plugin | Your laptop | Registers hooks, defines the 9 agent stubs, ships the /synaptory skill that classifies your request into a mode. Contains no IP-sensitive prompt bodies. |
synaptory CLI | Your laptop (one install) | Authenticates against Entra, caches the session in your OS keychain, fetches skill bodies on demand, queues telemetry, runs doctor and status diagnostics. |
| Control-plane API (FastAPI) | synaptory.h3t.co/v1/* | Auth exchange, project membership checks, signed config delivery, watermarked skill delivery, telemetry ingest. |
| Control Plane (Next.js) | synaptory.h3t.co/ | Single role-aware web app for every signed-in user (ADR-019). Pages auto-scope to the caller's grants — global admins see everything, project admins see their projects with cross-UPN visibility, project members see their own UPN within member projects. |
| Marketplace | synaptory.h3t.co/marketplace.git | A self-hosted git endpoint. /plugin marketplace add reads from here. |
| CLI download | synaptory.h3t.co/cli/install.{sh,ps1} | Install scripts and signed binaries. Resolved by latest.json. |
The control plane is operated by your H3Tech administrator. The marketplace and CLI hosts are static, served by Caddy; the API and Web run on a single Azure VM behind the same Caddy.
How auth works
synaptory login # opens browser → Entra OAuth (PKCE)
↓
SYNAPTORY1 token minted by FastAPI, signed Ed25519, audience-scoped to the Entra app
↓
Cached in your OS keychain (macOS Keychain / Windows Credential Manager / libsecret)
↓
Plugin hooks shell out to `synaptory` CLI; CLI reads the cached token
↓
Every request to the control plane carries the token; server checks project_members per call
There is no master password and there is no token bundled in the plugin distribution. If a token expires (~24h), the CLI silently refreshes it; if refresh fails, the next hook surfaces a one-line prompt to re-run synaptory login.
For headless servers and CI, run synaptory login --device once — same end state, different code path.
Project membership is checked per request, server-side, against the project_members table. The SYNAPTORY1 token only proves who you are, not what you can see — that's why a single laptop install works across every project you're a member of (the gh / aws model).
How a request travels through the stack
A typical /synaptory "build me a SaaS" invocation:
- SessionStart hooks fire (only on cold start /
/clear/ compact):
synaptory-access-token-check.shvalidates the cached session via the CLI.synaptory-skills-fetch.shsyncs the skill manifest; missing or stale bodies are pulled live and cached.synaptory-config-fetch.shrefreshes the policy cache.synaptory-load-rules.shinjects the 10 behavioural rules.
- Orchestrator classifies the request using
plugin/skills/synaptory/routing-rules.jsonand dispatches an agent. SubagentStartfires —synaptory-inject-protocols.shpulls every shared protocol body for the target role from the cache (or live from the control plane on cache miss). Each body is watermarked per-UPN before delivery — there's an<!-- synaptory-id: ... -->comment on the first line and a steganographic zero-width pattern through the body. Both are deterministic per user and survive copy-paste.- The agent runs, writing a receipt to
.synaptory/.orchestrator/receipts/<story-id>-<role>.json. SubagentStopfires —synaptory-verify-receipt.shvalidates the receipt JSON and re-runs the verification commands listed in the receipt. In Structured mode, a missing or failing receipt blocks the pipeline; in Interactive mode, it warns.- Telemetry queues — token usage, model identity, durations, fallbacks. The CLI's outbox flushes these to the control plane in the background (or
synaptory outbox flushmanually). Stopfires —synaptory-pipeline-snapshot.shwrites a resume snapshot to.synaptory/.orchestrator/last-session.md.
Skill bodies are never written to plaintext disk. The cache is per-user and bound to the cached session.
What ships in the marketplace vs what stays on the control plane
The marketplace tree (/marketplace.git) ships stubs and plumbing only:
- Agent stubs (
agents/<name>/agent.md) and SKILL frontmatter - Hook scripts (
hooks/*.sh) and Python helpers - The orchestrator skill, modes, ceremonies (these are user-facing, intentionally readable)
- Routing rules (
routing-rules.json) - Configuration templates
What stays on the control plane and is delivered watermarked at runtime:
- Shared protocols (
skills/_shared/protocols/*.md) - Behavioural rules (
rules/*.md) - Templates and design assets
- Backend wrappers and prompt translators
Pulling the marketplace tree by hand gives you a working scaffold but no agent prompts. Without an authenticated CLI session against the control plane, the plugin will fetch nothing and the orchestrator will surface a clear "session required" message.
What you see on the web
You'll touch the Control Plane rarely; it's not part of the in-IDE workflow.
synaptory.h3t.co/ is one app for every signed-in synaptory-users member. The same pages render for everyone; the data and controls auto-scope:
- As a project member, you'll mostly visit
/sessionsto revoke a stale session,/auditto see your own receipts, and/skillsto confirm what you've used. - As a project admin, you also use
/projects/<slug>to invite or revoke members, and the analytics pages (/cost,/quality,/reliability,/people) for your project's outcomes. - As a global admin, every page is unrestricted: project provisioning, system health, Grafana, audit across all UPNs.
The web app uses the same Entra sign-in your CLI uses. Sign in once at the CLI; the cookie path is independent.
What's next
- Getting Started — install the plugin and CLI, sign in, run your first delivery.
- Architecture — deeper view: per-URL routing, request sequences, where every artifact lives.
- Identity and Access — Entra OAuth, groups, project membership, the local-auth fallback.
- Personas — six roles that touch the platform and where each starts.
- v3.0 Roadmap — what's next: spec graph, four-gate model, evidence ledger.
- Using the Control Plane — the web surface.
- Hooks — every hook script, when it fires, what it blocks on.
- Routing — every mode the orchestrator can dispatch and the tiebreakers between them.
- Rules — the 10 behavioural rules auto-injected at session start.
- Commands — the
synaptoryCLI surface and the slash-command modes.
Platform Architecture
A deeper view than Platform — the wires between every surface.
Platform covers the component map and why the platform exists. This page goes one layer down: how requests traverse the stack, what every URL on synaptory.h3t.co maps to, and which artifacts live on which host.
Read this once if you operate the platform or you're integrating new tooling against it. Skip it if you're a delivery user — Platform is enough.
Surfaces, by URL
Every public URL is served by one Caddy instance on the prod VM. Three backends sit behind it:
| URL pattern | Served by | Source on prod VM |
|---|---|---|
/, /home, /overview, /projects/*, /audit, /sessions, /activity, … (every Control Plane page) | Next.js (web container) | Built into the container image |
/auth/*, /api/web/* | Next.js (web container) | Built into the container image |
/v1/* | FastAPI (api container) | api/ Python package |
/marketplace, /get-started | Static HTML | web/static/ (mounted at /srv/web-static) |
/marketplace.git/* | git-http-backend (FastCGI) | /mnt/pgdata/git/marketplace.git |
/cli/* | Static files | /mnt/pgdata/web-dist/cli/ |
/docs/* | Static files | /mnt/pgdata/web-dist/docs/ |
/downloads, /favicon.ico, etc. | Static files | web/static/ |
The complete list with example URLs is in reference/urls.md.
Cold-start request: a /synaptory invocation
platform.md gives the seven-step summary. Here is the same flow expanded so you can map it onto log lines and Grafana traces.
sequenceDiagram
participant User
participant CC as Claude Code
participant Plugin as synaptory plugin
participant CLI as synaptory CLI
participant API as FastAPI (control plane)
participant DB as Postgres
User->>CC: /synaptory "build me a SaaS"
CC->>Plugin: SessionStart hook chain
Plugin->>CLI: synaptory status
CLI->>API: GET /v1/projects (SYNAPTORY1 token)
API->>DB: SELECT project_members WHERE upn=...
API-->>CLI: 200 + groups + memberships
CLI-->>Plugin: ok / token-expired
Plugin->>CLI: synaptory skills sync
CLI->>API: GET /v1/skills/manifest
API-->>CLI: signed manifest
CLI->>API: GET /v1/skills/protocols/receipt-protocol (cache-miss)
API-->>CLI: watermarked body
Plugin->>CC: orchestrator classifies → SubagentStart
CC->>Plugin: SubagentStop with receipt
Plugin->>CLI: synaptory telemetry queue
CLI->>API: POST /v1/ingest (background, batched)
API->>DB: INSERT receipt + token_usage
The two cache layers worth knowing about:
- OS keychain holds the SYNAPTORY1 token (
security find-generic-password -s synaptoryon macOS). - Skill cache holds watermarked bodies, gated by token validity. Wiped on
synaptory logout.
What runs where
| Process | Container | Image source | Restart policy |
|---|---|---|---|
| Caddy | caddy | Stock caddy:2-alpine + custom Caddyfile | always |
| Next.js (Control Plane) | web | Built from web/Dockerfile | always |
| FastAPI | api | Built from api/Dockerfile | always |
| Postgres 16 | postgres | Stock postgres:16 | always |
| Grafana | grafana | Stock grafana/grafana | always |
Nightly pg_dump | backup | Built from infra/docker/Dockerfile.backup | unless-stopped |
git-http-backend | git-http | Built from infra/docker/Dockerfile.git-http | always |
Local dev adds a fixture-idp container that mints SYNAPTORY1 tokens at /dev/mint so tests don't hit Entra. Local addition only — never enabled in prod.
Compose project name is synaptory (declared via name: directive). If you see orphan containers from earlier project names, docker compose -p <old-name> down cleans them up.
How an artifact gets to a user
Three artifacts ship outside the API. Each takes a slightly different path:
Plugin marketplace (the agent stubs and hooks)
release.yml on self-hosted runner (on prod VM)
→ ./synaptory build --publish-prod-fs
→ rsync into /mnt/pgdata/git/marketplace-worktree/
→ git commit + push to file:///mnt/pgdata/git/marketplace.git
→ Caddy proxies /marketplace.git/* to git-http container (FastCGI to git-http-backend)
→ user runs `/plugin marketplace add https://synaptory.h3t.co/marketplace.git`
CLI binaries
release.yml on self-hosted runner
→ ./synaptory release cli (cross-compile 5 OS/arch)
→ ./synaptory release cli --publish-prod-fs
→ cp into /mnt/pgdata/web-dist/cli/<version>/
→ Caddy serves /cli/* from /srv/web-dist
→ user runs install script → fetches /cli/latest.json → fetches the matching binary
Single-page user guide HTML (this guide)
release.yml on self-hosted runner
→ ./synaptory build (already runs build_user_guide.py as a side-effect)
→ ./synaptory build --publish-prod-fs (also copies web/dist/docs/user-guide.html → /mnt/pgdata/web-dist/docs/)
→ Caddy serves /docs/* from /srv/web-dist
→ user opens https://synaptory.h3t.co/docs/user-guide.html (or via the Control Plane "User Guide" link)
Every other artifact (skill bodies, signed config, telemetry receipts) is API-mediated — never touches the static-file path.
What's next
- Identity and access — Entra OAuth, groups, project membership, the local-auth fallback.
- Personas — who touches which surface, and why.
- URLs reference — every endpoint and static path on
synaptory.h3t.co. - Auth flows reference — sequence diagrams for each sign-in path.
Identity and Access
Who you are (Entra), what group you belong to (
synaptory-users/synaptory-admins), and what projects you can see (project_members).
synaptory has three identity questions, and each is answered in a different place:
| Question | Answered by | Where it's checked |
|---|---|---|
| Who are you? | Entra OAuth (UPN claim) | At sign-in; baked into the SYNAPTORY1 token |
| Are you an admin? | Entra group membership (grp claim) | At sign-in; baked into the SYNAPTORY1 token |
| Can you see project X? | project_members table | Per request, server-side, against the live DB |
The first two are token-time — set at sign-in and immutable for the token's lifetime (~24h). The third is request-time — re-evaluated on every API call, so revoking access takes effect within seconds of the next request.
Sign-in (the normal path)
Three OAuth audiences exist, all backed by one Entra app registration (SYNAPTORY_CP_ENTRA_CLIENT_ID). The same app holds two platform sections in Azure: a Web platform with a client secret, and a Mobile/desktop platform for PKCE.
| Caller | Flow | Redirect URI |
|---|---|---|
| Control Plane browser | Authorization-code with client_secret | https://synaptory.h3t.co/auth/callback |
synaptory CLI | PKCE public client | http://127.0.0.1/auth/callback (loopback exception, random port) |
After Entra issues an ID token, the API exchanges it for a SYNAPTORY1 token:
SYNAPTORY1.<base64url(payload)>.<base64url(ed25519_sig)>
Payload carries sid, upn, grp, iat, exp. There is no prj claim — that was the V1.5 design and was replaced. Project access is a per-request check against project_members, not a token claim.
The Ed25519 signing key lives on disk in dev (settings.signing_key_path) and in Azure Key Vault in prod (kty OKP, curve Ed25519, loaded by api/synaptoryapi/tokens.py KeyVaultSigner). The public key is exposed at GET /v1/public-key so the CLI can verify signed config offline.
Groups: synaptory-users vs synaptory-admins
Two Entra groups gate the platform:
synaptory-users— every member of either group. If you don't have this, the API returns 401 at sign-in.synaptory-admins— superset role. Grants access to the legacy/console/*(now retired) and every/v1/admin/*endpoint.
The grp claim is a list, so admins carry both. ADR-019 retired the /console/* and /portal/* URL trees; every page lives at root URLs now, and admin-only entries are hidden from the sidebar (and gated server-side) for callers without synaptory-admins.
Group membership changes in Entra propagate at the next sign-in — the existing token's grp claim is frozen until expiry.
Project membership
Identity tells the API who you are; the project_members table tells it what you can see. Every project-scoped endpoint calls check_project_membership(db, claims.upn, project_id) (see api/synaptoryapi/security.py) which returns:
| Outcome | Status | Reason |
|---|---|---|
| Project doesn't exist | 404 | (anti-leak — no row existence disclosure) |
| Project archived | 403 | Archived projects are read-locked |
| User not a member | 404 | Returned as 404, not 403 — anti-enumeration |
| User membership revoked | 404 | Same as above |
| Active member | 200 | Proceed |
The "not a member returns 404" pattern is deliberate. A 403 would let an attacker enumerate project slugs.
Membership is granted via ./synaptory api projects add-member <slug> <upn> (CLI on the prod VM) or via the project's Members tab in the Control Plane (project admins can self-serve).
Local-auth fallback
For dev and on-prem deployments where Entra isn't available, the API exposes POST /v1/auth/local. It accepts a UPN+password pair from SYNAPTORY_CP_LOCAL_*_PASSWORD env vars and mints the same SYNAPTORY1 token format.
| Flag | Container | Default | Purpose |
|---|---|---|---|
SYNAPTORY_CP_LOCAL_AUTH_ENABLED | api | false | Enables POST /v1/auth/local |
SYNAPTORY_LOCAL_AUTH_ENABLED | web | false | Renders the password form on /auth/login |
Both must be true for the flow to work end-to-end. The admin slot grants [synaptory-users, synaptory-admins]; the user slot grants [synaptory-users] only. Tokens minted via local-auth carry the same upn claim format and are indistinguishable from Entra-minted tokens once issued — the server treats them identically.
Never enable in deployments expected to use Entra. It's a back-door by design, intended for dev fixtures and disconnected on-prem.
Watermarking and IP delivery
Identity also determines watermarking. Every skill-body fetch (GET /v1/skills/<name>) is watermarked per-UPN before delivery:
- Visible HTML comment — the first line of every body is
<!-- synaptory-id: {sha256-prefix} -->. Explicit deterrent; easily stripped. - Steganographic zero-width Unicode pattern — inserted at positions seeded by a deterministic RNG keyed on the watermark hash. Survives comment stripping. Reproducible per-user on every fetch.
The watermarker lives at api/synaptoryapi/watermark.py and is applied by api/synaptoryapi/routers/skills.py. See ADR-016 for the IP-delivery model.
What's next
- Auth flows reference — sequence diagrams for each path.
- Permissions reference — what each group + project role can do.
- Personas — how identity maps to who-touches-what.
Personas
Five roles touch the platform. Each touches a different surface for different reasons.
This guide is written for everyone who interacts with synaptory, but the interesting part of the platform changes depending on which role you're playing. Use this page to find the entry points that matter to you.
What changed in v3.0. Through v2.5 the platform served two browser surfaces —
/console/*for admins and/portal/*for everyone else. ADR-019 collapsed those into a single Control Plane app at root URLs (/,/home,/projects,/audit,/sessions, etc.) with role-gated sidebar entries and server-side scope filtering. Where this guide previously listed a "Portal user" and a "Console admin" as separate personas, the unified Control Plane treats them as different role grants on the same app.
1. Plugin user (delivery user)
You are: a developer or PM running /synaptory inside Claude Code to build, debug, or maintain a system.
You touch: the Claude Code plugin and the synaptory CLI on your laptop.
You don't usually touch: the Control Plane web app or anything on synaptory.h3t.co except via the plugin/CLI.
Start here:
- Getting Started
- Modes — what
/synaptory "review my code"actually does. - Scrum delivery or Kanban delivery
- Troubleshooting when something stalls.
2. Control Plane user
You are: any signed-in member of synaptory-users. Could be a developer, a stakeholder watching an in-flight project, a project admin, or a global admin — they all use the same web app.
You touch: https://synaptory.h3t.co in a browser. The same URLs (/home, /projects, /sessions, /audit, /skills, /profile) for everyone; the data you see is auto-scoped to what your role grants.
Your role determines what you see:
| Role | Where it comes from | What you see |
|---|---|---|
| global admin | Member of synaptory-admins Entra group | Everything: every project, every receipt, every UPN, system health, Grafana, policy. |
| project admin | project_members.role = 'admin' for one or more projects | Your admin projects' analytics with cross-UPN visibility. Members tab on those projects shows invite/revoke/promote controls. |
| project member | project_members.role = 'member' | Your member projects' analytics filtered to your own UPN. Read-only on Members tab. |
| unaffiliated | Signed-in synaptory-users with no project memberships | Your identity, sessions, and the access-request workflow. Analytics return empty. |
You can: view what your role allows, revoke your own sessions, sign out everywhere, and (in Phase 2b) request access to additional projects.
You can't: see another user's row — every endpoint that takes ?project=<slug> returns 404 (not 403) for projects you can't see, so existence isn't leakable.
Start here:
- Using the Control Plane — page-by-page tour.
- Identity and access — what your
grpclaim andproject_membersrow grant. - Permissions reference.
3. Project admin
You are: a Control Plane user plus you hold the admin role on at least one project.
You touch: the Members tab on /projects/[slug] for the projects you administer, plus the per-project drill-ins (Phase 2b: /projects/[slug]/{quality,cost,reliability}).
You can: invite new members to your project, revoke access, promote/demote project roles, view your project's analytics with cross-UPN visibility, approve / deny access requests other users submit against your project.
You can't: create or archive projects (that's global admin); see other admins' projects unless you're a member.
Start here:
- Inviting members — the end-to-end flow.
- Permissions reference — what each project role grants.
4. Operator
You are: the person responsible for keeping the platform running. Often the same human as a global admin acting in a different capacity.
You touch: the prod VM directly via az ssh vm, the GitHub Actions workflows, Grafana, and the Control Plane's /system, /sessions, and /audit pages (admin-gated).
You can: deploy the platform, rotate secrets, run migrations, restore backups, ship plugin / CLI / user-guide releases via labelled commits.
Start here:
- infra/README.md — the operator runbook (lives outside this guide).
- docs/RELEASE-POLICY.md — the labelled-commit release model.
- ADR-018 — release pipeline and versioning.
- ADR-019 — Control Plane unification.
This user guide intentionally doesn't duplicate the operator runbook. We link out.
5. Platform developer
You are: working on synaptory itself — agents, hooks, the API, the Control Plane web app, the CLI, infra.
You touch: the source repo. Local dev stack via ./synaptory api up. The plugin via claude --plugin-dir ./plugin.
Start here:
- CLAUDE.md — repo-level conventions and architecture.
- Module READMEs: api/README.md, web/README.md, cli/README.md, plugin/README.md, infra/README.md.
- The ADR set under docs/adrs/.
This user guide isn't aimed at you. The module READMEs and ADRs are.
A note on agent roles vs. human personas
The nine agents (Project Owner, Solution Architect, Software Engineer, etc.) are not personas in this list — they're not humans. They're roles played by Claude under the orchestrator. See Agents for that vocabulary.
The Control Plane UI uses "Delivery Owner" as the human counterpart to the "Project Owner" agent. See reference/glossary.md.
The Adaptive Delivery Lifecycle
The Shift That Matters
Most AI coding tools make you faster at writing code. Synaptory changes what you are doing entirely.
Without synaptory: You describe what you want. Claude writes code files. You review, iterate, ask follow-up questions, manually wire things together, figure out tests, set up CI/CD, write docs. You are the project manager, the architect, the QA lead, the DevOps engineer -- all at once.
With synaptory: You describe what you want to build. Nine specialized agents -- Project Owner, Solution Architect, Software Engineer (with backend, frontend, AI/ML, and mobile modes), Code Reviewer, Compliance Engineer, Quality Engineer, Platform Engineer, Technical Writer (with docs and report modes), and Research Advisor -- coordinate through an adaptive delivery lifecycle to produce a complete system: architecture decisions, tested backend and frontend, security audit, infrastructure, sprint reports, and documentation. You sit in the strategist's seat. You approve direction. You do not direct labor.
The system is built on one principle: do the work, don't describe the work. When a decision has a clearly superior option, agents take it and report what they chose and why. They don't ask. When a task can be done now, it's done now. Results are reported, not plans.
Quality Through Continuous Verification
synaptory replaces traditional checkpoints with a two-layer quality model: one human gate at project start, and continuous automated verification on every story.
Inception Gate
At the end of Inception (Sprint 0), you review and approve the project direction before any sprint begins:
Vision ✓ | Epics {N} | Sprint 1 {N} stories ready | Architecture {N} ADRs | CI/CD ✓ | Tests ✓
Options: Approve | Show details | I have concerns | Chat
This is the only human approval gate. It checks that the direction is right -- not that the entire design is locked. Architecture evolves incrementally as the project matures.
Per-Story Definition of Done
Every story is verified as it completes the SE->QE->CR pipeline. These checks are automated and continuous -- no waiting for a "quality gate" at the end.
v3 vocabulary: in the Control Plane UI the per-story DoD is rendered as the Evidence / DoD gate — one of four spec gates (Inception, Spec Ready, Evidence/DoD, Release). The underlying signals (tests pass, no critical findings, code reviewed, coverage non-decreasing, build green) are unchanged; the framing moves from "agent says done" to "evidence proves done." Receipts and pipeline behaviour described below continue to use the DoD wording.
| Check | Severity | What it verifies |
|---|---|---|
| Tests pass | Critical | All acceptance criteria tests for this story pass |
| Build succeeds | Critical | Build completes and dev server starts |
| No critical findings | Critical | Zero Critical security findings (Compliance Engineer) |
| Code reviewed | Adaptive | Story code reviewed (Code Reviewer) -- skips Sprint 1, enables Sprint 2+ |
| Coverage no decrease | Non-critical | Test coverage did not decrease |
Sprint-Level Overlay (Scrum only)
At Sprint Review, a second layer of checks verifies the sprint as a whole:
| Check | Type | What it verifies |
|---|---|---|
| Sprint Goal met | Human | Did the sprint deliver on its stated goal? |
| Feedback addressed | Human | Was stakeholder feedback from prior sprints incorporated? |
| No regression | Auto | No regression across all sprint stories |
| Documentation updated | Human | Were docs updated for changed features? |
This two-layer model means quality is verified continuously at the story level, with a human sanity check at sprint boundaries. Problems are caught when they are cheap to fix -- not at the end.
Three Operation Layers
synaptory classifies every request into one of three layers. You don't need to specify which -- just describe what you need, and the orchestrator routes automatically.
Layer 1: Scrum Lifecycle (time-boxed delivery)
For greenfield projects and brownfield projects that need structured iteration:
Inception --> Sprint Planning --> Sprint Execution --> Sprint Review
|
Sprint Close <-- Sprint Retro (adaptive) <-+
|
+--> Next Sprint (loop) or Release --> Complete
Inception establishes just enough foundation to start building: a mini-BRD, Sprint 1 stories, foundation architecture decisions (ADRs), CI/CD bootstrap, and test framework setup. The Project Owner defines vision and decomposes Sprint 1 stories. The Solution Architect creates foundation ADRs. The Platform Engineer bootstraps CI/CD and Docker. The Quality Engineer sets up the test framework.
Sprint Planning happens every sprint. The Project Owner refines stories, the Solution Architect reviews if architecture signals are detected in story text, the team selects stories, and a Sprint Goal is set. Planning intensity is adaptive -- lightweight when the backlog is stable, full when new feedback arrives.
Sprint Execution runs the per-story pipeline for each story in the sprint backlog. Stories move through SE->QE->CR with per-story DoD evaluation. Infrastructure stories run in parallel via the Platform Engineer.
Sprint Review deploys the increment to preview (auto-detected for web apps), generates sprint reports via the Technical Writer, demos working software, evaluates the sprint-level DoD overlay, and captures stakeholder feedback.
Sprint Retro is adaptive -- it only runs when the sprint had issues (low completion, blocks, regressions). When it runs, it analyzes metrics, identifies improvements, and feeds suggestions forward to the next sprint's planning.
Sprint Close always runs. It handles carry-over of incomplete stories, records sprint metrics, and presents the next decision: continue to the next sprint, or release.
Release is on-demand -- triggered when you decide to ship. Full regression testing, security audit, production infrastructure, documentation, and a release readiness check.
Layer 2: Kanban Lifecycle (continuous ticket flow)
For brownfield projects in maintenance or post-launch evolution:
Discover --> Ready --> Execute ticket --> Review --> Ready (loop)
|
+--> Release (on-demand)
Discover reverse-engineers the existing codebase and builds context packages (dependency map, interface contracts, business rules, data dictionary, risk register, health assessment, UI contracts).
Ready waits for the next ticket -- either user-specified ("fix TICKET-123") or auto-pulled from the tracker (highest priority ready ticket, user confirms).
Execute runs the same per-story SE->QE->CR pipeline as Scrum, with per-ticket DoD evaluation.
Review demos the completed ticket, captures feedback, and returns to Ready for the next ticket.
Release is available on-demand anytime -- same full verification as Scrum release.
Layer 3: Standalone Utilities (no lifecycle required)
For scoped tasks that don't need a delivery lifecycle:
| Utility | What it does |
|---|---|
| Debug | 4-phase root-cause analysis: Reproduce -> Isolate -> Understand -> Fix |
| Explore | Research Advisor thinking partner -- ideation, domain research |
| Discover | Reverse-engineer existing codebase, build context packages |
| Preview | Launch dev server, smoke test running application |
| Branch Finish | Per-branch verification, PR creation, merge |
| Story Buddy | Per-story assistance -- requirements, implement, test, sprint plan |
| Retro | Standalone engineering retrospective with git and receipt analysis |
| Init | Project detection, .synaptory.yaml generation |
| Status | Sprint/Kanban state dashboard |
| Help | Quick reference card |
These utilities work independently of the Scrum or Kanban lifecycle. "Review my code" routes to the Code Reviewer. "Debug this error" runs Debug mode. No ceremony context needed.
The Story Pipeline
Every story -- whether in a Scrum sprint or a Kanban ticket -- flows through the same per-story pipeline:
queued --> in_progress (SE) --> testing (QE) --> reviewing (CR) --> done
|
(or blocked)
- SE picks the highest-priority story and implements it (code + unit tests)
- Hands off to QE immediately -- no waiting for all stories to be built first
- QE tests -- acceptance criteria tests, integration tests
- CR reviews (if DoD requires it -- adaptive, enabled Sprint 2+)
- Per-story DoD evaluated -- tests pass, build succeeds, no critical findings
- Concurrent dispatch: up to 3 agents run simultaneously (configurable via
parallelism.max_concurrent_subagents)
This is the core difference from traditional AI pipelines: quality verification happens per story, not at the end. Problems are caught within hours of being introduced, not days later.
Adaptive Intensity
DoD checks, ceremony depth, and agent involvement all scale with project maturity:
| Maturity | What's Active | Why |
|---|---|---|
| Early (Sprint 1 or first 5 Kanban tickets) | Critical DoD only: tests, build, no critical findings | Minimal code to review or audit |
| Growing (Sprint 2-3 or tickets 6-15) | + Code review enabled | Growing codebase needs review |
| Mature (Sprint 4+ or tickets 16+) | + Full security audit | Enough surface area for meaningful assessment |
| Release | All checks at maximum depth | Production readiness |
This prevents ceremony overhead from slowing down early sprints when there is barely any code to review, while ensuring mature codebases get the scrutiny they need.
Progressive Elaboration
synaptory does not try to plan everything upfront. Requirements are elaborated progressively:
- At Inception: Project Owner decomposes Sprint 1 stories only (foundation mode) or Sprint 1-2 (blueprint mode). Remaining epics exist as high-level placeholders.
- At Sprint Planning: Project Owner refines stories for this sprint, incorporating feedback from prior sprints and retro insights.
- Architecture evolves: Solution Architect is auto-triggered when story text contains architecture signals (new entity, new service, new integration, security requirement). No upfront architecture lock.
- Architecture health checks: Every 3 sprints (configurable), the Solution Architect reviews the architecture for drift.
The result: early sprints focus on building. Later sprints benefit from accumulated learning. Architecture adapts to what the code actually needs, not what was guessed upfront.
What's next?
- Scrum Delivery -- Step-by-step walkthrough of the complete Scrum lifecycle
- Kanban Delivery -- Continuous ticket-based delivery for existing codebases
- Engagement Modes -- How to control agent autonomy vs. visibility
- Modes -- All operation modes and how the orchestrator classifies your requests
Operation Modes
The orchestrator classifies every request automatically into an operation mode. You do not need to specify a mode -- just describe what you want. Classification uses keyword matching, intent patterns, and project context to route your request to the right agents with the right scope.
Modes are organized into three operation layers: lifecycle modes that drive structured delivery, and standalone utilities for focused tasks. For the full machine-readable rules and tiebreakers, see Routing Reference.
Layer 1: Scrum Lifecycle
| Mode | Trigger Signals | What Happens |
|---|---|---|
| Build | "build a SaaS", "production grade", "from scratch", "full stack", greenfield intent | Inception -> Sprint ceremony loop -> Release. Full adaptive delivery lifecycle. |
| Sprint | "build sprint", "sprint N", "next sprint", "continue sprint", "resume sprint" | Loads sprint state, routes to the correct ceremony (Planning, Execution, Review, Retro, Close). |
Build is the most comprehensive mode. Describe what you want to build in plain language, and synaptory runs the complete Scrum lifecycle: Inception establishes the foundation, then sprint ceremonies iterate until you decide to release. See Scrum Delivery for the full walkthrough.
Sprint resumes an active Scrum project. The orchestrator reads the sprint state machine and routes to whichever ceremony is next -- no need to specify "planning" or "review" explicitly.
Layer 2: Kanban Lifecycle
| Mode | Trigger Signals | What Happens |
|---|---|---|
| Kanban | "fix ticket", "work on TICKET-xxx", "pull next ticket", "maintenance mode" | Discover -> Ready -> Execute ticket -> Review -> loop. Continuous ticket-based flow for brownfield projects. |
Kanban mode is for post-launch maintenance and evolution. It runs the same per-story SE->QE->CR pipeline as Scrum, but without sprint ceremonies -- tickets flow continuously. See Kanban Delivery for details.
Layer 3: Standalone Modes
These modes work independently of any lifecycle. They group naturally into five families.
Diagnostics & Setup
Doctor -- Configuration Diagnostic
| Trigger Signals | Agent |
|---|---|
| "doctor", "diagnose", "check config", "validate config", "is this correctly configured", "synaptory doctor" | Orchestrator (read-only) |
Read-only configuration validator. Checks .synaptory.yaml correctness, plugin settings, CLI auth, control-plane project membership, and v2.1 cruft. Produces a clear pass/warn/fail report with remediation guidance for every finding. Never modifies files without asking. Run it whenever a project is being migrated, after manual edits to .synaptory.yaml or .claude/settings.json, when a new team member sets up the plugin, or when something looks wrong. See Troubleshooting → Run Doctor first for the typical recipe.
Init -- Project Setup
| Trigger Signals | Agent |
|---|---|
| "initialize", "configure project", "set up synaptory", "reconfigure" | Orchestrator (init) |
Scans the project, auto-detects language, framework, infrastructure, and architecture, then generates .synaptory.yaml and scaffolds tracker description templates into docs/templates/. Use Doctor to check a config; use Init to generate or replace one.
Status -- State Dashboard
| Trigger Signals | Agent |
|---|---|
| "status", "progress", "dashboard", "where are we" | Orchestrator (status) |
Displays the current lifecycle state: sprint number, ceremony position, story pipeline status, agent backends, DoD compliance, and velocity metrics.
Help -- Quick Reference
| Trigger Signals | Agent |
|---|---|
| "help", "commands", "what can you do" | Orchestrator (help) |
Prints a quick reference card with available modes and example prompts. Mostly useful during onboarding.
Report -- File a Plugin Issue
| Trigger Signals | Agent |
|---|---|
| "report a bug", "report an issue", "synaptory bug" | Orchestrator (report) |
Gathers context (versions, config, state, recent errors) and files a GitHub issue against the synaptory repository. Use this when something is wrong with the plugin itself, not with your project's code.
Update -- Auto-Update Check
| Trigger | Behaviour |
|---|---|
| Runs silently before any other mode | Orchestrator (Step 0) |
Not user-invocable — it's a Step 0 that runs ahead of every other mode. Compares your installed plugin version against the latest in the marketplace. Stays silent if you're current; surfaces a single one-question prompt if a newer version is available; never blocks the pipeline if the version check fails (offline, timeout). Skip the update once and the rest of the request runs on your current version.
Per-Story Assistance (Story Buddy)
| Trigger Signals | Agent |
|---|---|
| "analyze US-xxx", "implement story", "refine requirements", "help plan sprint", "test story" | Role-specific (PO, SE, QE, or Orchestrator) |
Focused assistance for a single story or ticket, integrated with the tracker. Story IDs in the request (e.g., US-042, TICKET-123) automatically route to Story Buddy. Four sub-roles:
- Requirements -- Project Owner analyzes and refines a story's acceptance criteria
- Implement -- Software Engineer implements a specific story
- Test -- Quality Engineer writes tests for a specific story (diff-aware)
- Sprint Plan -- Project Owner advisor: suggests story selection and capacity estimate. Does NOT create or modify stories unless asked.
Lightweight Single-Agent Modes
These modes run a single agent (occasionally two) with minimal orchestration overhead. Useful when you know exactly what you want and don't need a full pipeline.
Test -- Standalone Test Generation
| Trigger Signals | Agent |
|---|---|
| "write tests", "test coverage", "test this", "add tests" (with no story ID) | Quality Engineer |
Generates tests for code that already works. Coverage-focused. With a story ID present, routes to Story Buddy — Test instead.
Review -- Standalone Code Review
| Trigger Signals | Agent |
|---|---|
| "review my code", "code review", "code quality", "check my code" | Code Reviewer |
Read-only adversarial code quality analysis. Architecture conformance, SOLID/DRY/KISS, performance anti-patterns, test quality. Does NOT perform security review (that's Compliance Engineer). For security audit, use Verify or trigger Release readiness.
Architect -- Design and ADRs
| Trigger Signals | Agent |
|---|---|
| "design", "architecture", "API design", "data model", "tech stack", "how should I structure" | Solution Architect |
Single-agent architecture work outside a sprint cycle. Produces ADRs, API contracts, ERDs, or migration plans. The Solution Architect's modernize mode also dispatches here when migration intent is detected (see Modernize below).
Document -- Documentation Generation
| Trigger Signals | Agent |
|---|---|
| "document", "write docs", "API docs", "README" | Technical Writer |
Generates API references, developer guides, READMEs, or Docusaurus sites. Traces every statement back to a source artifact -- never invents.
Explore -- Thinking Partner
| Trigger Signals | Agent |
|---|---|
| "explain", "understand", "help me think", "what should I", "I'm not sure" | Research Advisor |
The Research Advisor acts as a thinking partner for ideation, domain research, and decision-making. It does not write code -- it helps you think through problems.
Optimize -- Performance and Scale
| Trigger Signals | Agents |
|---|---|
| "performance", "slow", "optimize", "scale" (without operational framing) | Platform Engineer + Code Reviewer |
Performance and scale work on existing code. Profiling, hotspot analysis, caching, query plans. If the request mentions SLOs, error budgets, chaos, runbooks, incidents, or on-call, the orchestrator routes to a reliability path on the Platform Engineer instead -- see the routing tiebreaker in Routing Reference.
Stabilize -- Pre-Refactor Safety Net
| Trigger Signals | Agents |
|---|---|
| "add safety net", "characterization tests", "before refactoring", "establish baseline", "coverage ratchet" | Quality Engineer + Code Reviewer |
Adds characterization tests around code you're about to change. Establishes a coverage baseline that subsequent work cannot decrease (the coverage ratchet). Run this before a Modernize pass.
Modernize -- Migration Planning
| Trigger Signals | Agents |
|---|---|
| "modernize", "migrate", "upgrade architecture", "strangler fig", "migration plan", "rewrite plan" | Solution Architect + Compliance Engineer |
Brownfield migration planning. The Solution Architect produces a phased migration plan (strangler fig patterns, quarterly roadmaps, ADRs); Compliance reviews the security/regulatory impact of the migration path. Pair with Stabilize first.
Custom -- Manual Skill Selection
| Trigger Signals | Agent |
|---|---|
| Doesn't fit any pattern above | User selects from menu |
Catch-all. The orchestrator presents a skill menu and lets you pick the agent and scope.
Brownfield Analysis
Discover -- Codebase Reverse-Engineering
| Trigger Signals | Agent |
|---|---|
| "understand this codebase", "map the system", "reverse engineer", "what does this code do" | Orchestrator (analysis) |
Reverse-engineers an existing codebase and produces 7 context packages: dependency map, interface contracts, business rules inventory, data dictionary, risk register, health assessment, and UI contracts. These packages are loaded by all agents in subsequent work. Re-runnable -- detects what changed since the last run.
Context Refresh -- Incremental Re-Analysis
| Trigger Signals | Agent |
|---|---|
| "update context", "refresh context", "re-analyze" | Orchestrator (incremental) |
Re-runs Discover incrementally, updating context packages for files that changed since the last analysis. Use after major code changes to keep context packages current.
Workflow Utilities
Debug -- Structured Root-Cause Analysis
| Trigger Signals | Agents |
|---|---|
| "debug", "fix this bug", "not working", "broken", "error", "crash", "failing", "investigate", "root cause" | Code Reviewer (diagnose) -> SE (fix) -> QE (regression test) |
Debug mode uses a structured 4-phase protocol rather than ad-hoc troubleshooting:
- Reproduce -- Confirm the failure reliably. If the bug cannot be reproduced, the diagnosis is unreliable.
- Isolate --
git bisectstrategy to pinpoint the regression. Binary search through the call chain to find the minimal reproducer. - Understand -- 5 Whys root cause analysis. The causal chain is documented in
.synaptory/debug/diagnosis.md. - Fix & Verify -- SE applies the fix. QE writes a regression test. Both the original failure and the fix are verified with running code.
Preview -- Dev Server Launch
| Trigger Signals | Agent |
|---|---|
| "preview", "run it", "start server", "launch", "dev server" | Orchestrator (preview) |
Launches the dev server, runs smoke tests against the running application, and reports the result. Auto-detects the correct start command for your framework.
Branch Finish -- Verification and Merge
| Trigger Signals | Agent |
|---|---|
| "finish this branch", "merge", "create PR", "done with this branch", "ship this branch" | Verify -> merge/PR/keep/discard |
Runs per-branch verification (tests, lint, type check), then offers options: create a PR, merge directly, keep the branch, or discard.
Retro -- Engineering Retrospective
| Trigger Signals | Agent |
|---|---|
| "retro", "retrospective", "what did we ship", "team metrics", "how are we doing" | Orchestrator (analysis) |
Standalone retrospective that analyzes git history, receipt data, and pipeline artifacts. In Scrum, integrated retros run automatically within the ceremony flow -- this mode is for on-demand analysis or Kanban projects.
Routing Conflicts
When a request matches multiple modes, the orchestrator applies tiebreakers. The complete list lives in Routing Reference; the most common ones:
| Conflict | Resolution | Why |
|---|---|---|
| "review" -> Code Review vs Release | Code Review if "my code / this code". Release if "before launch / audit / harden" | Release implies full verification; Code Review is single-agent |
| "add tests" + "bug" -> Test vs Debug | Debug if error/failure described. Story Buddy Test if code works and coverage is the goal | Debug = active failure; Test = proactive quality |
| "implement" + story ID present | Story Buddy Implement | Story ID pattern = [A-Z]+-\d+ or US-\d+ |
| "implement" + no story ID | Build (Inception -> Scrum lifecycle) | No story ID = new feature from scratch |
| Story ID anywhere in request | Story Buddy (choose role from context) | Story ID overrides other modes |
| "doctor" vs "init" | Doctor if "check / validate / diagnose / is it configured correctly". Init if "initialize / set up / generate config" | Doctor is read-only; Init writes |
| "optimize" vs "reliability" | Reliability if SLO / error budget / chaos / runbook / incident / on-call. Optimize otherwise | Reliability = operational; Optimize = code/infra perf |
| Multiple modes match | Pick the most specific: Debug > Story Buddy, Release > Code Review, Sprint > Build | Specificity beats generality |
What's next?
- Routing Reference -- the full machine-readable trigger table and all tiebreakers.
- Delivery Lifecycle -- the adaptive lifecycle that drives Scrum and Kanban delivery.
- Agents -- the 9 specialized agents and their roles.
- Engagement Modes -- Structured vs Interactive execution.
The 9 Delivery Agents
synaptory orchestrates 9 specialized agents, each owning a distinct domain. The Orchestrator (always Claude) classifies your request and dispatches the right agents. All agents in this build run on Claude — Opus for strategic roles, Sonnet for execution roles.
Why Separate Roles?
A single AI doing everything is like one person writing the code, reviewing their own code, and auditing their own security. It cannot work: the builder has too much context invested in their choices to question them adversarially.
Each role in synaptory is architecturally separate because each role requires a distinct stance:
- The Code Reviewer must assume the code is wrong and look for proof it works. It cannot be the same agent that built the code — the builder cannot review their own output.
- The Compliance Engineer owns OWASP and STRIDE and never defers to the SE's judgment on security. Domain authority cannot be shared.
- The Project Owner defines what to build. The Solution Architect decides how. When a requirement is technically infeasible, the Architect flags the contradiction — the PO cannot override it.
Role separation also enables parallelism: the orchestrator can dispatch up to parallelism.max_concurrent_subagents (default: 3) agent tasks concurrently.
Role Short Codes
The Control Plane UI and audit trail render agents with these two-letter codes (source of truth: web/src/lib/v3-vocab.ts):
| Code | Role |
|---|---|
| PO | Project Owner |
| SA | Solution Architect |
| SE | Software Engineer |
| QE | Quality Engineer |
| CR | Code Reviewer |
| CE | Compliance Engineer |
| PE | Platform Engineer |
| TW | Technical Writer |
| RA | Research Advisor |
Note on rename: Project Owner was called Product Manager in v2.x. The short code moved from
PMtoPOand the agent slug fromproduct-managertoproject-owner. The control plane still acceptsproduct-manageras a server-side alias for in-flight receipts, but new code, docs, and tooling use the new names.
Agent Classification
Agents are classified by how and when they are invoked:
Core Crew (active every delivery cycle)
| Agent | Domain | Modes |
|---|---|---|
| Project Owner | Backlog refinement, Sprint Planning, story decomposition | feature, refinement |
| Software Engineer | Code implementation -- one story at a time | backend (default), frontend, ai-ml, mobile |
| Quality Engineer | Per-story testing -- unit, integration, e2e, performance | default, diff-aware, browser-qa, exploratory, testability-review |
| Technical Writer | Sprint reports at Review, documentation at Release | docs (default), report |
On-Demand Specialists (auto-triggered)
| Agent | Trigger | Modes |
|---|---|---|
| Solution Architect | Story text contains architecture signals (new entity, service, integration, security requirement) | default, modernize |
| Compliance Engineer | Per-story DoD security check, intensity scales with maturity | default, healthcare (HIPAA/PHI), pentest (PTES 7-phase) |
| Code Reviewer | Per-story DoD review check -- adaptive (skip Sprint 1, enable Sprint 2+) | -- |
User-Invoked
| Agent | Trigger | Modes |
|---|---|---|
| Research Advisor | User request or knowledge gap | research, advise, ideate, synthesize, translate, onboard |
Conditional Per Cycle
| Agent | Trigger | Modes |
|---|---|---|
| Platform Engineer | Inception bootstrap + infrastructure stories | -- |
Claude Model Tiers
The Orchestrator selects a model tier for each agent based on task complexity. The active tier depends on engagement_mode:
| Agent | Model | Rationale |
|---|---|---|
| Project Owner | Opus | Makes strategic decisions: story scope, sprint content, requirements |
| Solution Architect | Opus | Makes irreversible decisions: tech stack, ADRs, architecture patterns |
| Compliance Engineer | Opus | Makes risk-acceptance decisions: severity, OWASP findings, threat model |
| Research Advisor | Opus | Synthesizes options and recommends direction |
| Software Engineer | Sonnet | Executes implementation contracts — follows ADRs and acceptance criteria |
| Quality Engineer | Sonnet | Executes test strategy against known acceptance criteria |
| Platform Engineer | Sonnet | Executes infrastructure specs — follows IaC patterns and ADRs |
| Technical Writer | Sonnet | Traces artifacts to documentation — no invention, pure traceability |
| Code Reviewer | Sonnet | Adversarial analysis requires judgment and reasoning — not mechanical pattern-matching |
These tiers apply in both Structured and Interactive modes. The modes are identical in model cost. The difference is behavioral: in Interactive mode, strategic roles (PO, SA, CE, RA) surface major decisions for human review instead of deciding autonomously. Executor roles (SE, QE, PE, TW, CR) follow orchestrator direction in both modes and don't make autonomous decisions, so their tier doesn't change.
You cannot configure individual model tiers per role. The only lever is engagement_mode: structured | interactive in .synaptory.yaml.
Software Engineer Modes
The Software Engineer runs in one of four modes, selected automatically based on project signals:
- Backend (default) -- Services, APIs, business logic. Builds shared foundations (
libs/shared/) before spawning parallel service agents. In microservices, one SE instance runs per service.
- Frontend -- React/Next.js components, design system, pages. Builds UI primitives first (Button, Input, Modal, etc.), then pages. Enforces the Dead Element Rule: any button, link, or form that renders but does nothing is a Critical bug, not a TODO.
- AI/ML -- LLM optimization, agent framework design, data pipelines, cost modeling. Auto-detected from project signals. Skipped if not applicable.
- Mobile -- React Native, Flutter, Swift, Kotlin. Auto-detected from project signals.
Multiple SE instances can run in parallel with different modes via worktree isolation.
Code Reviewer
Read-only adversarial code quality analysis. Architecturally separate from the Software Engineer -- the builder and the reviewer are distinct roles by design.
- Tools restricted to Read, Grep, Glob only -- never modifies source code
- Two-stage review: Stage 1 (Spec Compliance) verifies the code meets requirements. Stage 2 (Code Quality) runs architecture conformance, SOLID/DRY/KISS, performance anti-patterns, and test quality analysis
- Adversarial stance -- assumes the code is wrong and looks for proof it works
- Does NOT perform security review -- defers entirely to the Compliance Engineer
- Adaptive invocation -- skips Sprint 1 (too little code to review), enables Sprint 2+ as the codebase grows
- Per-story scope -- reviews each story as it completes the SE->QE pipeline, not all code at once
Software Engineer Tech Packs
After mode dispatch, the SE auto-loads technology-specific guidance based on project signals. Tech packs are additive -- a Next.js project with Tailwind and PostgreSQL loads three packs simultaneously.
| Detection signal | Tech pack loaded |
|---|---|
next.config.* or "next" in package.json | nextjs.md |
"react" in package.json (no Next.js) | react.md |
pyproject.toml with fastapi | python-fastapi.md |
go.mod | go.md |
tailwind.config.* | tailwind.md |
| PostgreSQL in dependencies or docker-compose | postgresql.md |
@modelcontextprotocol/sdk in package.json | mcp.md |
| Web app detected | performance.md -- Core Web Vitals, bundle analysis, caching |
| Marketing/public-facing content | seo-geo.md -- SEO + GEO (Generative Engine Optimization) |
Tech pack loading is automatic. No user configuration required.
Technical Writer Modes
- Docs mode (default) -- API reference (from OpenAPI specs), developer guides, operational guides, architecture guides, contributing guides, Docusaurus sites. Invoked at Release. Every statement traces to a source artifact -- never invents information.
- Report mode -- Sprint summary reports (PDF) generated at Sprint Review. Technical documentation PDFs from architecture markdown. Closed sprint reports are immutable -- only new reports can be generated for new sprints.
Project Owner Behavior
The Project Owner is active every sprint cycle, not just at project start:
- At Inception: Defines project vision, decomposes Sprint 1 stories (foundation mode) or Sprint 1-2 (blueprint mode)
- At Sprint Planning: Reads prior feedback and retro insights, refines stories for this sprint, updates acceptance criteria
- Feature mode: Scoped requirements for adding a feature -- produces a focused BRD section rather than a full document
- Refinement mode: Reworks requirements based on specific feedback from the Inception Gate (max 2 rework cycles)
Quality Engineer Modes
- Default -- Full test strategy: unit, integration, e2e, performance, contract tests. Per-story testing as each story completes the SE pipeline.
- Diff-aware -- Tests only changed files. Activated automatically on feature branches to minimize scope and cost.
- Browser QA -- Visual testing, accessibility checks (WCAG), responsive layout verification. Activated for web frontend projects in Controlled mode.
- Exploratory -- Session-based, charter-driven testing. Finds bugs that scripted tests miss.
- Testability Review -- Identifies test gaps BEFORE the SE starts coding. Flags untestable designs early.
Compliance Engineer Modes
Default mode runs the standard compliance audit: OWASP Top 10, STRIDE threat modeling, dependency vulnerability scanning, regulatory compliance. Intensity scales with project maturity -- minimal at Sprint 1, full audit at Sprint 4+ and Release.
Healthcare mode activates when the task mentions HIPAA, PHI, healthcare, ePHI, or BAA. Adds PHI data flow analysis, BAA verification, HIPAA access controls, encryption verification, breach notification review, HITRUST CSF mapping.
Pentest mode activates in Controlled mode or when explicitly requested. Applies the PTES 7-phase methodology: Pre-Engagement, Intelligence Gathering, Threat Modeling, Vulnerability Analysis, Exploitation (PoC), Post-Exploitation Analysis, Reporting.
Solution Architect
The Solution Architect is auto-triggered -- the Orchestrator analyzes story text for architecture signals:
- New database entity -> ERD update + migration ADR
- New service or bounded context -> system design + ADR
- New external API integration -> API contract + integration ADR
- Auth/security requirement -> security architecture ADR
- Performance-critical story -> NFR alignment review
No triggers detected -> SA is skipped for this sprint (most sprints).
Architecture health checks run every 3 sprints (configurable) to detect drift. The SA reviews the codebase against ADRs and flags divergence.
Modernize mode activates for brownfield codebases. Instead of designing from scratch, the Architect evaluates existing architecture and plans a migration path with strangler fig patterns and quarterly roadmaps.
Authority Boundaries
Each agent owns its domain completely. When two agents' domains touch, the conflict-resolution protocol defines who has authority:
- Compliance Engineer vs. Code Reviewer: Compliance owns OWASP, STRIDE, PII, encryption. Code Reviewer owns architecture conformance, code quality, performance. The Code Reviewer does NOT do security review -- this boundary is absolute.
- Platform Engineer: Sole authority on infrastructure AND reliability -- Docker, CI/CD, IaC, K8s, monitoring, SLOs, runbooks, chaos engineering.
- Software Engineer vs. Code Reviewer: The SE builds. The Code Reviewer reviews. They are never the same agent instance. The SE cannot review its own code.
- Project Owner vs. Solution Architect: The PO defines what to build. The Architect decides how to build it. When a requirement is technically infeasible, the Architect flags the contradiction.
What's next?
- Delivery Lifecycle -- How agents coordinate through the adaptive delivery lifecycle
- Engagement Modes -- How agent model routing and question depth vary by mode
- Enforcement -- How receipts, DoD, and safety nets enforce agent quality
Engagement Modes
At the start of any multi-agent run, the orchestrator asks you to choose an engagement mode. This single choice propagates to all 9 agents and controls two things: how much agents surface to you versus decide autonomously, and which AI model tier each agent uses.
The 2 Modes
| Mode | Model Routing | Agent Questions | Use When |
|---|---|---|---|
| Structured | Opus for strategic roles, Sonnet for executor roles | Minimal -- auto-resolve, report decisions | Most work -- speed and cost efficiency |
| Interactive | Same tiers as Structured | Major decisions from PO, SA, CE, RA surfaced for review | Compliance-sensitive, complex systems, full control |
Important distinction: The Inception Gate (approve project direction) is always present regardless of mode. Engagement mode controls agent-level decision visibility and model quality, not lifecycle gates.
Aliases:
autonomousandhands-offare accepted as aliases forstructured.controlledandhands-onare accepted as aliases forinteractive. New config should use the canonical names.
Structured Mode
Agents decide and report. The Project Owner derives requirements from your request with minimal questions. The Solution Architect auto-selects the tech stack and documents the rationale. Agents report what they decided rather than asking.
Model routing: Two tiers based on role type:
- Opus for strategic/decision roles: Project Owner, Solution Architect, Compliance Engineer, Research Advisor
- Sonnet for executor roles: Software Engineer, Quality Engineer, Platform Engineer, Technical Writer, Code Reviewer
Structured is ideal for most production work, prototypes, and domains where you trust the agents' defaults.
Interactive Mode
Maximum visibility and quality. The Project Owner asks more questions. The Solution Architect walks through ADRs. All major decisions are surfaced for your review.
Model routing: Same tiers as Structured — Opus for strategic roles, Sonnet for executor roles. No model cost premium over Structured.
Interactive is for production systems in regulated industries, compliance-sensitive builds, or situations where you need an audit trail of every decision. The cost difference vs. Structured is minimal — the distinction is visibility and human gate behavior, not model quality.
How Engagement Mode Affects Enforcement
The same quality checks run in both modes. The difference is what happens when a check fails:
| Behavior | Structured | Interactive |
|---|---|---|
| Missing receipt | Hook exits 1 -- execution BLOCKED | Warning shown, execution proceeds for human review |
| Invalid receipt | Hook exits 1 -- execution BLOCKED | Validation report shown, user decides |
| Lifecycle state violation | Hook exits 1 -- execution BLOCKED | Warning shown, execution proceeds |
| Verification commands fail | Hook exits 1 -- execution BLOCKED | All results shown to user for review |
| Philosophy | Trust the automated safety nets | Trust the human operator |
Structured is ambitious: it assumes the system will produce correct work, and blocks hard when it doesn't. The safety nets are invisible when passing, painful when failing.
Interactive is honest: it acknowledges limitations and surfaces everything for human review. Nothing blocks silently. Everything is visible.
When to Use Which
| Situation | Recommended mode | Why |
|---|---|---|
| Prototype or early-stage greenfield build | Structured | Speed and cost matter more than exhaustive visibility |
| Standard sprint execution | Structured | Agents build and test reliably; audit trail not required |
| Regulated industry or compliance-sensitive build | Interactive | Every decision surfaced and reviewable; nothing silently blocked |
| HIPAA / PHI project | Interactive | Compliance Engineer activates pentest mode; all Opus for maximum analysis depth |
| Release verification for production | Interactive | Maximum reasoning quality at the final gate matters |
| Small team on tight token budget | Structured | No difference in model tiers vs Interactive — both modes use the same Opus/Sonnet split |
| You need an audit trail of every architectural decision | Interactive | SA walks through ADRs; PO asks questions; all choices recorded |
| Debugging a complex production issue | Interactive | Maximum model quality for hypothesis generation and root-cause reasoning |
Token Cost Awareness
Engagement mode is the single biggest lever on token consumption:
- Structured: standard cost. Opus for strategic roles, Sonnet for executor roles. Agents decide and report without surfacing every choice.
- Interactive: same model tiers — no cost premium over Structured. The difference is decision visibility: strategic roles (PO, SA, CE, RA) surface major choices for human review before proceeding.
A practical strategy: use Structured for sprint execution (where agents build and test stories reliably without needing to surface every decision), then switch to Interactive for Release mode or regulated-environment builds where every architectural and security decision needs a human sign-off.
Configuration
Set in .synaptory.yaml:
engagement_mode: "structured" # structured | interactive
Or let the orchestrator ask at the start of each run.
What's next?
- Enforcement -- The safety nets that implement Structured vs. Interactive behavior
- Scrum Delivery -- See engagement modes in action during sprint delivery
- Configuration -- All config options that affect delivery behavior
Enforcement and Safety Nets
synaptory's quality mechanisms are not instructions that the LLM may or may not follow. They are enforced by shell hooks and Python scripts that can block execution. This distinction -- between "the model is told to do X" and "the system stops if X isn't done" -- is what makes the system reliable.
v3 vocabulary: the per-story Definition of Done described here is the signal behind the Evidence / DoD gate that the Console renders (one of four v3 spec gates: Inception, Spec Ready, Evidence/DoD, Release). The receipt + verification machinery on this page is unchanged — it's what produces the evidence that lights the gate green.
The difference between a system that says "tests must pass" and one that stops if they don't is the difference between guidance and a guarantee. For you as the operator, this means you do not need to audit every story to make sure the agents did the right thing. The hooks do it automatically, and they do not lie.
Code-Enforced Safety Nets
In Autonomous mode: missing receipts, invalid receipts, lifecycle state violations, and verification command failures all trigger exit 1 from their respective hooks. Execution stops. No work continues until the problem is resolved.
In Controlled mode: the same checks run, but failures are surfaced as warnings rather than blocks. The human operator reviews and decides whether to proceed.
This is the Autonomous/Controlled split described in Engagement Modes. The enforcement is identical; only the consequence differs.
Receipt Protocol
Every agent writes a JSON receipt when it completes work on a story. The receipt is the agent's proof of work -- not a summary, but a verifiable claim.
Story-Scoped Receipts
Receipts are scoped to individual stories, not phases or sprints:
US-001-se.json # SE implementation of story US-001
US-001-qe.json # QE testing of story US-001
US-001-cr.json # CR review of story US-001
US-001-ce.json # CE security audit of story US-001
TICKET-042-se.json # Kanban ticket implementation
Receipt Format
A receipt contains:
{
"story_id": "US-001",
"role": "quality-engineer",
"backend": "codex",
"model": "gpt-5.4",
"story_dod": {
"tests_pass": true,
"code_reviewed": true,
"no_critical_findings": true,
"build_succeeds": true,
"coverage_no_decrease": true
},
"artifacts": [
"tests/unit/user-service.test.ts",
"tests/integration/user-api.test.ts"
],
"verification_commands": [
"npm test -- --testPathPattern=user-service",
"npm run test:integration -- --testPathPattern=user-api"
],
"metrics": {
"tests_written": 12,
"tests_passing": 12,
"coverage_delta": "+3.2%",
"findings_count": 0
},
"completed_at": "2026-04-12T14:30:00Z"
}
Key fields:
backendandmodel-- which AI backend and model produced this work (traceability)story_dod-- per-story Definition of Done evaluation, inline with the receiptartifacts-- file paths to everything the agent produced (must exist on disk)verification_commands-- shell commands that prove the work is correct
Receipt Validation
After each agent completes, synaptory-verify-receipt.sh runs a validation pass:
- Schema validation -- required fields present, correct types
- Artifact verification -- every file path in the artifacts list exists on disk
- Banned phrase check -- rejects vague verification claims
- Command re-execution -- verification commands are re-run to confirm they still pass
Receipts without verification_commands block execution in Autonomous mode. There is no "I finished" without verified artifacts and passing commands.
Definition of Done Evaluation
Quality is verified continuously through a two-layer DoD model, replacing traditional phase gates.
Per-Story DoD (both Scrum and Kanban)
Evaluated as each story completes the SE->QE->CR pipeline:
| Check | Severity | Agent | Adaptive? |
|---|---|---|---|
| tests-pass | Critical | Quality Engineer | No -- always checked |
| build-succeeds | Critical | (auto) | No -- always checked |
| no-critical-findings | Critical | Compliance Engineer | Yes -- intensity scales with maturity |
| code-reviewed | Non-critical | Code Reviewer | Yes -- skip Sprint 1, enable Sprint 2+ |
| coverage-no-decrease | Non-critical | (auto) | No -- always checked |
Critical checks must pass for a story to move to done. Non-critical checks are advisory -- they warn but don't block.
Sprint-Level Overlay (Scrum only)
Evaluated at Sprint Review, after all sprint stories have been executed:
| Check | Type | What it verifies |
|---|---|---|
| Sprint Goal met | Human | Did the sprint deliver on its stated goal? |
| Feedback addressed | Human | Was stakeholder feedback from prior sprints incorporated? |
| No regression | Auto (Critical) | No regression across all sprint stories |
| Documentation updated | Human | Were docs updated for changed features? |
Adaptive Intensity
DoD depth scales with project maturity:
| Maturity | What's Active | Why |
|---|---|---|
| Early (Sprint 1 / first 5 tickets) | Critical only: tests, build, no critical findings | Minimal code to review or audit |
| Growing (Sprint 2-3 / tickets 6-15) | + Code review enabled | Growing codebase needs review |
| Mature (Sprint 4+ / tickets 16+) | + Full security audit | Enough surface area |
| Release | All checks at maximum depth | Production readiness |
Story Pipeline Enforcement
The story pipeline enforces state transitions. Stories cannot skip states or go backward:
queued --> in_progress (SE) --> testing (QE) --> reviewing (CR) --> done
- A story cannot move to
testinguntil the SE receipt is validated - A story cannot move to
reviewinguntil the QE receipt is validated - A story cannot move to
doneuntil all per-story DoD checks pass - A story moves to
blockedif any Critical DoD check fails -- the SE is notified for rework
Story state transitions auto-sync to the configured tracker backend (local, GitHub, Jira, Teamwork).
Backend Traceability
Every receipt records which AI backend and model produced the work. This provides a complete audit trail:
- Which AI built each story (SE receipt:
backend: "codex", model: "gpt-5.4") - Which AI tested each story (QE receipt:
backend: "codex", model: "gpt-5.4") - Which AI reviewed each story (CR receipt:
backend: "claude", model: "claude-opus-4-6")
This traceability is valuable for debugging quality issues (which backend produced the problematic code?) and for cost analysis (which backend configuration gives the best cost/quality ratio?).
Re-Anchoring
At ceremony transitions and before context compaction, the orchestrator re-reads key artifacts directly from disk: the BRD, ADRs, API contracts, current receipt chain, and brownfield context packages. The synaptory-reanchor.sh hook handles this automatically at the PreCompact lifecycle event.
Re-anchoring prevents silent degradation. Over a long delivery run, the model's in-context memory of early architecture decisions can drift. By re-reading source-of-truth files from disk, agents in later sprints work from the same foundation as agents in Sprint 1.
Freshness Protocol
Before implementing anything involving external dependencies -- package versions, model IDs, API endpoints, cloud service names -- agents run a web search to verify the information is current. This catches outdated information before it lands in the codebase.
Particularly important for:
- NPM/PyPI package versions (agents may "remember" versions that are months old)
- Cloud service API endpoints and parameters
- LLM model identifiers (model names change frequently)
- Framework configuration syntax (breaking changes between versions)
Self-Healing
When you reject the Inception Gate or a DoD evaluation, the system feeds your specific concerns back to the relevant agent, the agent reworks its output, and the check is re-presented. Maximum 2 rework cycles.
The quality of the rework depends on feedback specificity. "The multi-tenancy model should be schema-per-tenant, not row-level" produces a targeted fix. "Make it better" produces a vague rework.
Dead Element Rule
Any button, link, or form that renders in the UI but does nothing is classified as a Critical bug, not a TODO. The SE [frontend mode] verification checks that every interactive element has a working handler, every link resolves, every form submits, and every navigation item reaches a page that renders.
Cross-Session Persistence
Context packages, lifecycle state, and receipts survive across sessions. Three hooks handle the lifecycle:
synaptory-session-start.sh(SessionStart) -- detects the.synaptory/workspace, loads lifecycle state (Scrum or Kanban), injects context packages and story pipeline statesynaptory-pipeline-snapshot.sh(Stop) -- writes a state snapshot with enough context to resumesynaptory-session-end.sh(SessionEnd) -- async cleanup of temporary resources
Long multi-session builds resume where they left off. Sprint state, ceremony position, story pipeline status, receipt chains, and context packages are all persistent.
Constraint-Driven Architecture
The Solution Architect derives architecture from actual constraints: expected scale, budget, team size, compliance requirements, and operational complexity.
100 concurrent users gets a monolith. 10 million users gets microservices. A two-person team gets simpler infrastructure than a platform team of twenty. HIPAA compliance gets encryption-at-rest and audit logging as architectural requirements, not bolt-on features.
This prevents the most common AI architecture failure: recommending microservices for every project regardless of scale.
What's next?
- Hooks Reference -- Detailed hook execution order and mode-aware behavior
- Commands Reference -- State machine CLI for manual state inspection
- Resuming Sessions -- How persistence and re-anchoring work across sessions
v3.0 Roadmap
What's coming, why, and what's already visible in the v2.5 product today.
The current product is v2.5 — that's the version reflected in the rest of this guide. v3.0 is the next major milestone. Some pieces are already live in the UI ahead of the backend; this page tells you which signals you'll see, what's coming, and how the runtime story plays out.
For the full design specification (the source of truth) see docs/v3.0/v3-spec.md. The vocabulary mapping is in glossary.
The product reframe
| Version | Product frame | What the user gets |
|---|---|---|
| v2.5 (today) | Multi-agent adaptive delivery inside Claude Code | Agents run Scrum, Kanban, and focused workflows with receipts, hooks, telemetry, skills, control-plane-backed auth |
| v3.0 | Claude Code harness governed by an agentic delivery control plane | The same workflows, but bound to specs, tasks, gates, evidence, policy, audit, domain packs, and Delivery Owner / global-admin cockpit views |
| v3.1+ | Runtime-neutral control plane with pluggable harness adapters | Claude Code remains supported, but selected workflows can run through additional agent runtimes |
The clearest mental model:
synaptory = Delivery Control Plane + Agent Runtime Harness.
In v2.5 those two layers are entangled inside the plugin. In v3.0 the control plane becomes the durable product layer and Claude Code becomes the (still-only) production runtime adapter.
The v2.5 delivery model is not discarded. Scrum, Kanban, Story Buddy, Branch Finish, Debug, Discover, Preview, Retro, Init, Status, and Help all remain. v3.0 makes them more accountable by binding them to specs, tasks, gates, and evidence.
Four concrete additions in v3.0
1. Spec graph
In v2.5 a "story" is a tracker ticket plus some markdown that lives in receipts. In v3.0 it becomes a Spec — a versioned object in the control plane with kind (story, feature, bugfix, task, release), a hash chain back to its parent spec versions, and explicit task children.
The spec_versions and tasks tables become the source of truth. The tracker adapter (GitHub Issues / Jira / Teamwork) syncs from them, not the other way around.
2. Four-gate model
Today the user-facing checkpoints are the Inception Gate (one human review at Sprint 0) and per-story DoD (automated, every story). v3.0 generalises this into four gates:
| Gate | When it fires | What it gates |
|---|---|---|
| Inception | Project start | Project direction is signed off (vision, epics, Sprint 1, architecture foundations) |
| Spec Ready | Before code-modifying work | The spec is complete, has tasks, and has explicit validation commands |
| Evidence / DoD | Before marking a spec done | Receipts present, verification commands rerun cleanly, no critical findings |
| Release | Before shipping | Release evidence pack assembled across the contributing specs |
The the Overview page already renders the Gate Queue card with all four — only Evidence/DoD has a wired backend signal in v2.5; the other three light up in place when v3.0 ships. See Using the Control Plane.
3. Evidence ledger with hash chain
Receipts stay (the protocol you know from enforcement) but become entries in a ledger — each receipt's hash chains to the prior receipt for the same spec. A break in the chain is detectable; the Control Plane gets chain-break alerts.
Receipts also gain three v3 fields: spec_version_id, task_id, and per-stage token usage tagged to one of the 11 v3 stages.
4. Policy and domain packs
Today, healthcare compliance is enforced via .synaptory.yaml flags. v3.0 generalises this into a policy registry + domain packs: a project can declare e.g. domain: healthcare-hc0 and inherit BAA-only backends, model pinning, AI-BOM emission, and signed-commit requirements as a unit.
Healthcare is the first pack. Others (financial-services, gov, default-strict) are sketched in the spec but not committed.
What's already visible in v2.5
The Control Plane UI runs ahead of the backend in places, so you'll see v3 vocabulary today even though the underlying signals are partial. Specifically:
| Where you see it | What it means today | What it'll mean in v3.0 |
|---|---|---|
| Control Plane label "Spec" instead of "Story" | Renaming only — same DB table | Backed by spec_versions with hash chain |
| Control Plane "Project Owner" instead of "Product Manager" | Agent rename complete | No change |
| Control Plane "Delivery Owner" for human role | UI-only term | Used in evidence and gate-event ownership |
| Overview "Gate Queue" card with 4 gates | Three are placeholders | All four wired |
| Cost panel "11 stages" breakdown | Aggregated from existing receipt fields | Cleaner per-stage tagging in the receipt |
| Quality panel "Evidence/DoD" header | Same as v2.5 DoD evaluation | Tied to the ledger and gate_events table |
This is intentional — the v3 cut-over should be a backend swap, not a UI rewrite.
What does not change
The v3.0 spec is explicit about what stays:
- Entra OAuth + PKCE for staff and admin auth.
- SYNAPTORY1 user-scoped session tokens — same format, same per-request
project_memberscheck. - Standalone CLI distribution — still installed once per laptop (ADR-012).
- Build-time control-plane URL stamping — no runtime redirection.
- CP-delivered, watermarked skill bodies — ADR-016.
- Durable local outbox — offline-capable telemetry.
- Claude-only user-facing plugin — until v3.2 introduces a second runtime as a narrow pilot.
- The 9-agent delivery team — the orchestration model remains.
If you're worried about a v3 migration breaking your laptop install: it won't. The plugin and CLI flow stays the same; the new objects (specs, gates, ledger) live behind the API.
Beyond v3.0
v3.0 makes the core delivery objects runtime-neutral but ships only Claude Code as a production adapter. The breakout from Claude-Code dependency is staged:
| Milestone | Frame | What changes |
|---|---|---|
| v3.1 | Runtime adapter boundary | Claude Code becomes the first named adapter (runtime: claude-code). A formal runtime-adapter interface is defined. A fake/local runtime passes conformance tests. No second production runtime yet. |
| v3.2 | Second runtime pilot | One narrow workflow (likely Branch Finish, Code Review, or sandboxed spec implementation) runs through a second runtime — probably an open-source runner or a Cursor/IDE harness. Claude Code stays default for full Scrum/Kanban. |
| v3.3+ | Multi-runtime delivery | Runtime selection by project / workflow / risk tier / domain pack. Cost and quality comparison in the Console. Runtime failover where safe. |
Spec, gate, evidence, and policy are designed in v3.0 to not encode Claude-Code-specific assumptions, so v3.1+ is a refactor at the runtime boundary, not a re-architecture of the control plane.
v2.5 prerequisites before v3.0 ships
Five v2.5 items are explicit prerequisites:
- CLI verifies signed config payloads before caching.
- CLI does real Entra auth-code exchange (no fixture assumptions in prod).
- Device-code flow mints the same user-scoped SYNAPTORY1 session as browser login.
- Production skill KEK is bound to Azure Key Vault, not the filesystem fallback.
- Standalone CLI install/version flow is confirmed in pilot.
These don't add features — they close gaps from the v2.5 substrate. Operators tracking v3 readiness should watch these.
What's next
- Glossary — the v2.5 ↔ v3.0 vocabulary map.
- Using the Control Plane — where v3 vocabulary already shows up in the UI.
- docs/v3.0/v3-spec.md — the full design specification (canonical).
- docs/v3.0/v3-research.md — the research companion that motivates the design.
Scrum Delivery
You type a description of what you want to build. The orchestrator runs Inception — the Project Owner defines the vision and Sprint 1 stories, the Solution Architect lays down the foundational ADRs, the Platform Engineer bootstraps CI/CD. You review the Inception Gate output (vision, epics, Sprint 1 stories, architecture) and approve. Then you watch stories flow through the SE → QE → CR pipeline, sprint by sprint, until you decide to release. Your role is to approve direction at the gate and provide feedback at Sprint Review. The agents handle everything in between.
End-to-end guide for running structured, sprint-based delivery with synaptory. The Scrum lifecycle takes a project from inception to release through iterative sprints with adaptive ceremonies.
Prerequisites
- Initialize your project -- say "initialize my project" to scan your codebase and generate
.synaptory.yaml. Without it, agents use defaults that may not match your project structure.
- Review
.synaptory.yaml-- checkbuild_mode: "scrum"(default),sprint.inception(foundation or blueprint),agents.*for backend configuration, andpaths.*for directory mapping.
- Choose your engagement mode --
structured(agents decide and report, minimal questions) orinteractive(major decisions surfaced for review, same model cost). See Engagement Modes.
Starting a Scrum Project
Describe what you want to build in plain language. The orchestrator classifies your request automatically.
Example prompts that trigger the Scrum lifecycle:
Build me a multi-tenant SaaS for managing restaurant reservations
Create a real-time collaborative document editor with WebSocket support
Build a full-stack e-commerce platform with React and Node.js
Trigger signals: "build a SaaS", "from scratch", "full stack", "production grade", any greenfield intent.
For brownfield projects, the orchestrator runs Discover first (reverse-engineers the codebase), then offers a choice between Scrum (with adaptive Inception) or Kanban. See Kanban Delivery.
The Scrum Lifecycle
Inception --> Sprint Planning --> Sprint Execution --> Sprint Review
|
Sprint Close <-- Sprint Retro (adaptive) <-+
|
+--> Next Sprint (loop) or Release
Inception (Sprint 0)
Purpose: Establish just enough foundation to start Sprint 1. Not a complete upfront design -- just enough direction.
Two modes (configured via sprint.inception):
| Mode | When to Use | What's Produced |
|---|---|---|
| Foundation (default) | Direction is clear, details will emerge | Mini-BRD (1-2 pages), 3-5 epics, Sprint 1 stories decomposed, foundation ADRs, CI/CD bootstrap, test framework |
| Blueprint | Complex domain, regulatory requirements, fixed-scope contracts | Full BRD + NFRs, all epics to feature level, Sprint 1-2 stories decomposed, complete SAD + all ADRs, full infrastructure + staging |
Agents involved:
- Project Owner -- defines vision, decomposes Sprint 1 stories (foundation) or Sprint 1-2 (blueprint)
- Solution Architect -- creates foundation ADRs, API skeleton, ERD
- Platform Engineer -- bootstraps CI/CD, Docker, dev environment
- Quality Engineer -- sets up test framework, Sprint 1 test spec
Inception Gate:
Vision ✓ | Epics {N} | Sprint 1 {N} stories ready | Architecture {N} ADRs | CI/CD ✓ | Tests ✓
Options: Approve | Show details | I have concerns | Chat
This is the only human approval gate. Approve the direction, then sprints begin. If you have concerns, the orchestrator feeds them back for rework (max 2 cycles).
Brownfield Inception: For existing codebases choosing Scrum after Discover, Inception is adaptive. The orchestrator detects what already exists (CI/CD, tests, architecture docs, tracker data) and only runs the missing steps:
- All detected -> Skip Inception, start at Sprint Planning
- Some detected -> Targeted Inception (run only missing steps)
- None detected -> Full Inception (same as greenfield)
Sprint Planning
When: Every sprint start.
Agents: Project Owner, Solution Architect (conditional), Quality Engineer, Orchestrator.
What happens:
- PO reads context -- prior sprint feedback, retro insights, backlog priorities
- PO refines stories for this sprint -- updates acceptance criteria, creates new stories if needed
- SA architecture review (conditional) -- the Orchestrator analyzes story text for architecture signals:
- New database entity -> ERD update + migration ADR
- New service/bounded context -> system design + ADR
- New external API integration -> API contract + integration ADR
- Auth/security requirement -> security architecture ADR
- Performance-critical story -> NFR alignment review
- No triggers -> SA is skipped (most sprints)
- Team selects stories -- velocity-based capacity, user can override scope
- Sprint Goal confirmed
- QE generates test spec for sprint stories
Adaptive intensity:
- Lightweight -- stable backlog, no new feedback -> PO confirms pre-refined stories, minimal ceremony
- Full -- new feedback, scope changes, retro improvements -> full refinement cycle
Sprint Execution
The per-story pipeline:
Story US-001: SE implements → QE tests → CR reviews → DoD ✓ Done
Story US-002: SE implements → QE tests → CR reviews → DoD ✓ Done
Story US-003: SE implements → QE tests → (in progress)
Infra-001: PE implements → (parallel)
How it works:
- SE picks the highest-priority story and implements it (code + unit tests)
- Hands off to QE immediately -- no waiting for all stories to finish
- QE tests -- acceptance criteria tests, integration tests
- CR reviews if DoD requires (adaptive: skip Sprint 1, enable Sprint 2+)
- Per-story DoD evaluated: tests pass, build succeeds, no critical findings
- SE moves to the next story
Story sub-states:
queued --> in_progress (SE) --> testing (QE) --> reviewing (CR) --> done
The orchestrator can dispatch up to parallelism.max_concurrent_subagents (default: 3) agent tasks concurrently. QE can test one story while SE implements the next.
Infrastructure stories: The Platform Engineer handles infra stories (CI/CD updates, IaC changes) in parallel with the story pipeline.
Sprint Review
When: After all sprint stories have been executed (or time-box ends).
Agents: Orchestrator, Technical Writer, Project Owner.
What happens:
- Deploy increment to preview -- auto-detected for web apps (Next.js, React, etc.)
- TW generates reports -- quality and progress reports for the sprint
- Demo working software -- organized by Sprint Goal and completed stories
- Sprint-level DoD overlay evaluated:
- Sprint Goal met (human)
- Stakeholder feedback addressed (human)
- No regression across sprint stories (auto)
- Documentation updated (human)
- Capture stakeholder feedback -- feeds forward to next Sprint Planning
- PO updates product backlog based on feedback
What you see:
Sprint 2 -- Review & Demo
Stories: 8/9 completed
Tests: 142/145 passing (98%)
Coverage: 82% (+3.2%)
Findings: 0 Critical, 1 High (fixed)
Sprint Goal: "Ship user management module" ✓
Sprint reports: reports/sprint-2/
Options:
[Approve -- continue to Sprint 3]
[I have feedback]
[View sprint reports]
[Release]
Sprint Retro (Adaptive)
When: After Sprint Review. Skipped if the sprint went smoothly (high completion, no blocks, no regressions).
What happens when it runs:
- Data collection -- git metrics, receipt data, velocity trends, cycle time
- Analysis -- what went well, what needs improvement
- Process suggestions:
- Adjust verification intensity (e.g., enable code review earlier)
- Add/remove DoD items
- Adjust concurrency settings (
parallelism.max_concurrent_subagents) - Modify sprint capacity
- User selects improvements -- accept all, select specific, or skip
- Configuration updated for next sprint
- Feed-forward -- insights passed to PO for next Sprint Planning
Sprint Close
Always runs -- bookkeeping that cannot be skipped.
What happens:
- Carry-over policy applied to incomplete stories:
move_to_next(default) -- move to next sprint backlogkeep_in_sprint-- archive in closed sprint (reporting only)ask-- prompt user at close time
- Sprint metrics recorded -- planned/completed stories, velocity, DoD compliance
- Next decision:
- Continue to Sprint N+1
- Release (ship to production)
- Stop
Running Sprints
How to start a sprint
Use natural language:
build sprint 1 # Start a specific sprint
next sprint # Continue to the next pending sprint
continue sprint # Same as "next sprint"
resume sprint 3 # Pick up where you left off on sprint 3
start sprint # Start the current pending sprint
If no sprint number is specified, the orchestrator reads sprint state and targets the current pending sprint.
Sprint routing guards
Ambiguous requests -- when you say "build this" in a Scrum project, the orchestrator asks:
- Build Sprint N (recommended) -- continue with the next pending sprint
- Choose a different sprint
- Override sprint mode
Out-of-order requests -- requesting Sprint 3 when Sprint 2 isn't complete shows the prerequisite gap and offers to build Sprint 2 instead.
Re-building approved sprints -- requesting an already-approved sprint warns that re-building is destructive and offers alternatives.
Cross-Session Persistence
Sprint state persists automatically across Claude Code sessions:
- On session end:
synaptory-pipeline-snapshot.shwrites a state snapshot including full sprint and story pipeline state - On session start:
synaptory-session-start.shloads lifecycle state, sprint position, story pipeline, and context packages
Resuming after a break:
- Open the project in Claude Code (session start hook loads state automatically)
- Say "show status" to see: which sprint, which ceremony, story pipeline status
- Say "continue sprint" or "next sprint" to resume
No manual state restoration needed. See Resuming Sessions for details.
Configuration
Essential settings
build_mode: "scrum" # Default -- Scrum lifecycle
sprint:
inception: "foundation" # foundation | blueprint
carry_over_policy: "move_to_next" # move_to_next | keep_in_sprint | ask
velocity: null # Story points per sprint (null = uncapped)
protected_modules: [] # Paths SE must confirm before touching
constraints: [] # Architectural rules for every story
agents:
default_backend: "claude"
engagement_mode: "structured" # structured | interactive
Full config example
version: "3.0"
build_mode: "scrum"
engagement_mode: "structured"
project:
name: "reservation-saas"
language: "typescript"
framework: "nextjs"
cloud: "aws"
architecture: "modular-monolith"
type: "greenfield"
template: "nextjs-fullstack"
agents:
default_backend: "claude"
sprint:
inception: "foundation"
carry_over_policy: "move_to_next"
velocity: 21
tracker:
backend: "github"
github:
repo: "myorg/reservation-saas"
preferences:
test_framework: "vitest"
orm: "prisma"
package_manager: "pnpm"
frontend_framework: "nextjs"
styling: "tailwind"
features:
frontend: true
multi_tenancy: true
payment_integration: true
real_time: true
See Configuration Reference for the complete schema.
What's next?
- Kanban Delivery -- Continuous ticket-based delivery for maintenance
- Release -- Shipping to production
- Resuming Sessions -- How state persists across sessions
- Troubleshooting -- Sprint and ceremony issues
Kanban Delivery and Brownfield Workflows
You point synaptory at an existing codebase. Discover runs — the orchestrator reverse-engineers the system and builds context packages so every agent understands what exists before touching it. Then you say "work on TICKET-142" or "pull the next ticket." The SE implements, the QE tests, the CR reviews — same per-story pipeline as Scrum, without the sprint ceremonies. When you're ready to ship, you trigger Release on-demand. No ceremonies, no sprint planning overhead: just continuous flow from ticket to verified increment.
Guide for continuous ticket-based delivery on existing codebases. Kanban mode provides a lightweight flow for post-launch maintenance and evolution -- no sprint ceremonies, just pull a ticket, build it, verify it, ship it.
When to Use Kanban
Kanban is designed for brownfield projects -- codebases that already have working code, tests, and infrastructure:
- Post-launch maintenance and bug fixes
- Continuous feature evolution on a live product
- Projects that have completed their Scrum sprints and transitioned to maintenance
- Teams that prefer continuous flow over time-boxed sprints
Entry Point: Discover Always Runs First
Every brownfield project starts with Discover -- reverse-engineering the codebase to build understanding before making changes.
Run /synaptory in your project or describe what you want:
understand this codebase
map the system
What Discover Produces
Discover analyzes your codebase through five phases:
- Architecture Reconstruction -- module inventory, dependency graph, hidden coupling, interface contracts, architecture pattern classification
- Business Rule Extraction -- domain logic with confidence scores (HIGH/MEDIUM/LOW/INFERRED), implicit assumptions, dead code candidates
- Risk and Hotspot Analysis -- git-based churn analysis, risk scoring per module, bus factor identification
- Coverage Baseline -- test framework detection, current coverage measurement, characterization tests for critical untested paths
- Assembly -- verifies all artifacts, writes completion receipt
Context Packages
Discover produces seven context packages stored in .synaptory/.orchestrator/context-packages/:
| Package | Contents |
|---|---|
dependency-map.md | Module boundaries, import graph, hidden coupling |
interface-contracts.md | Inter-module contracts, protocols, endpoint specs |
business-rules-inventory.md | Domain logic with confidence scores |
data-dictionary.md | Domain terms, entity definitions, magic numbers |
risk-register.md | Module risk scores, hotspot files, bus factor risks |
health-assessment.md | Project health, test density, coverage baseline, tech debt |
ui-contracts.md | UI component interfaces, design tokens, page-level contracts |
These packages are auto-loaded into every agent's context via the synaptory-session-start.sh hook. Agents read relevant packages before making decisions:
- Project Owner reads
business-rules-inventory.mdbefore refining requirements - Solution Architect reads
dependency-map.mdandinterface-contracts.mdbefore designing - Software Engineer reads
risk-register.mdbefore modifying high-risk modules - Compliance Engineer reads
health-assessment.mdto calibrate audit depth - Code Reviewer reads
interface-contracts.mdto verify modifications respect contracts
Choosing Your Path
After Discover, the orchestrator presents a choice:
- Scrum (with adaptive Inception) -- for structured iteration with ceremonies. See Scrum Delivery.
- Kanban -- for continuous ticket-based flow without sprint ceremonies.
Set in .synaptory.yaml:
build_mode: "kanban"
Adaptive Inception Detection (Scrum path)
If you choose Scrum for a brownfield project, Inception is adaptive -- the orchestrator detects what already exists:
| Signal | Detection | If Present | If Missing |
|---|---|---|---|
| CI/CD pipeline | .github/workflows/*, .gitlab-ci.yml, Jenkinsfile | Skip PE bootstrap | Run PE bootstrap |
| Test framework | jest.config.*, pytest.ini, test patterns | Skip QE setup | Initialize tests |
| Architecture docs | docs/architecture/, ADRs | Skip SA foundation | Run foundation ADRs |
| Project config | .synaptory.yaml | Skip config | Run Init |
| Tracker data | Tracker CLI health check OK | Skip tracker init | Initialize tracker |
- All detected -> Skip Inception entirely, start at Sprint Planning
- Some detected -> Targeted Inception (run only missing steps)
- None detected -> Full Inception (same as greenfield)
The Kanban Flow
READY --> Pull ticket --> SA triggers (if needed) --> SE implements
|
REVIEW <-- CR reviews (if DoD) <-- QE tests <-------------+
|
+--> READY (next ticket)
+--> RELEASE (on-demand)
Ready
The system waits for the next ticket. Two work source modes:
User-specified:
fix TICKET-123
work on US-042
implement the login bug fix
Auto-pull:
pull next ticket
what's next
The orchestrator queries the tracker for the highest-priority ready ticket and asks for confirmation before starting.
Execute
The same per-story SE->QE->CR pipeline used in Scrum:
- SE implements the ticket (code + unit tests)
- QE tests -- acceptance criteria, integration tests
- CR reviews (if DoD requires -- adaptive, based on ticket count maturity)
- Per-ticket DoD evaluated -- same story-level checks as Scrum (tests pass, build succeeds, no critical findings)
SA auto-trigger: If the ticket text contains architecture signals (new entity, new service, integration, security requirement), the Solution Architect is invoked before the SE starts.
Review
After the ticket completes the pipeline:
- Demo the completed work -- preview deployment for web changes
- Capture feedback -- the Project Owner updates the backlog
- Return to Ready for the next ticket
Per-Ticket DoD
Kanban uses the same per-story DoD as Scrum, but without the sprint-level overlay:
| Check | Severity | What it verifies |
|---|---|---|
| Tests pass | Critical | All acceptance criteria tests pass |
| Build succeeds | Critical | Build completes and dev server starts |
| No critical findings | Critical | Zero Critical security findings |
| Code reviewed | Adaptive | Ticket code reviewed (after first 5 tickets) |
| Coverage no decrease | Non-critical | Test coverage maintained |
No Sprint Goal, no sprint-level regression check, no documentation overlay. Quality is verified per ticket.
Kanban Retro
Retro is not part of the default Kanban flow. You can trigger it on-demand anytime:
retro
how are we doing
show metrics
The orchestrator analyzes recent tickets for trends: cycle time, throughput, recurring issue patterns, DoD compliance rate, backend performance comparison.
Release in Kanban
Release is available on-demand -- there are no sprint boundaries to wait for:
release
ship it
go live
The Release flow is identical to Scrum Release: full regression testing, security audit, production infrastructure, documentation, release readiness check. See Release.
Scrum-to-Kanban Transition
Projects that have completed their Scrum lifecycle can transition to Kanban for ongoing maintenance:
- Complete the current sprint or Release
- Change configuration:
build_mode: kanban - The Kanban state machine starts from READY
- Remaining backlog stories become Kanban tickets
- Context packages, ADRs, and architecture are carried over
- Sprint history and metrics are archived
- Agent backend configuration is preserved
# Before transition
build_mode: "scrum"
# After transition
build_mode: "kanban"
Coverage Ratchet
When enabled, code-modifying agents check for existing tests before modifying any file:
| Situation | Agent behavior |
|---|---|
| File has existing tests | Modify freely |
| File is untested | Write a characterization test first, then modify |
| Coverage decreases | Blocked -- agent must add tests to restore coverage |
Configure in .synaptory.yaml:
brownfield:
coverage_ratchet: true
context_packages: true
characterization_tests: true
Brownfield Protections
Additional safety mechanisms for existing codebases:
- Protected modules (
sprint.protected_modules) -- paths the SE must confirm before touching - Read-before-write (
sprint.read_before_write) -- SE must Read() every file before modifying it - Characterization tests first (
sprint.characterization_tests_first) -- QE writes behavior-capturing tests before SE modifies legacy code - Context injection (
sprint.require_context_injection) -- SE must read existing module code before generating new code
Refreshing Context Packages
Context packages can become stale after significant changes. Re-run Discover incrementally:
refresh context
update context
re-analyze codebase
This runs Context Refresh mode -- an incremental update that only re-analyzes changed files.
Common triggers for refresh:
- After a major refactoring
- After adding a new module or service
- When agents make decisions that ignore recent changes
- After unshallowing a shallow git clone (enables better hotspot analysis)
Configuration
build_mode: "kanban"
engagement_mode: "structured"
project:
type: "brownfield" # or evolved_brownfield, mixed
agents:
default_backend: "claude"
tracker:
backend: "github"
github:
repo: "myorg/my-project"
brownfield:
coverage_ratchet: true
context_packages: true
characterization_tests: true
What's next?
- Scrum Delivery -- Structured sprint-based delivery for greenfield projects
- Release -- Shipping to production from Kanban
- Resuming Sessions -- How Kanban state persists across sessions
- Configuration -- Brownfield and Kanban config options
Multi-Spec Delivery (multiple parallel specs in one repo)
When to use this: your team runs more than one independent spec out of a single codebase and a single tracker project (Jira / GitHub Issues / Teamwork), and you need the parallel teams to keep their own backlogs, sprints, and retros without trampling each other's state. Available since Synaptory v2.7 (Jira) and v2.8 (GitHub Issues + Teamwork).
By default Synaptory assumes one tracker project + one sprint counter + one receipt stream per codebase. That breaks when two or three teams are working concurrently in the same repo:
- One team's
/sprint-advanceoverwrites another'scurrent_sprint. - Concurrent agents flip the
last_agentfield mid-session. - The
tracker-id-map.jsoncache gets clobbered by parallel syncs.
Multi-spec adds a thin spec abstraction that lives entirely inside one tracker project. Each spec maps to a partition discriminator native to the backend — a Jira label / GitHub label / Teamwork tag — and the state, caches, receipts, and CLI flags namespace cleanly under the spec id.
| Backend | Default discriminator | Other options | Read filter | Write side-effect |
|---|---|---|---|---|
| Jira | label | component / epic / jql | JQL fragment labels = "<v>" | append label |
| GitHub Issues | label | milestone | search query label:"<v>" | append label (or set milestone) |
| Teamwork | tag | tasklist | tagIds=<id> query param | append tag (or override tasklist) |
| Local | not supported | — | — | — |
This guide walks through migrating an existing single-spec project to multi-spec, the day-to-day commands once you're there, and the operational details. The full design is in docs/multi-spec-design.md.
Mental model
| Concept | Single-spec (default) | Multi-spec |
|---|---|---|
| Tracker project | 1 | 1 (same project hosts all specs — Jira project, GitHub repo, or Teamwork project) |
| Boards / views | 1 | N — one per spec, each filtered by the discriminator |
pipeline-state.json lifecycle | One lifecycle_state + current_sprint | Per-spec under state.specs.<id> |
| Receipts directory | .synaptory/.orchestrator/receipts/ | .synaptory/.orchestrator/specs/<id>/receipts/ |
| Tracker caches | Flat | Per-spec under specs/<id>/ |
| CLAUDE.md guidance | One body | Shared top + ### Spec: <name> sub-sections |
| Active spec | n/a | pipeline-state.json.active_spec (/switch-spec to change) |
Specs are a logical grouping, not an organizational boundary. Cross-spec dependencies stay in the tracker via "is blocked by" / "depends on" links; humans coordinate, agents stay isolated per spec.
Tracker-side setup (do this first)
Multi-spec is opt-in. Pick a discriminator on the tracker side per spec, apply it to existing tickets, and (where applicable) create a filtered view. ~5 minutes per spec once you've decided on names.
Jira
- Pick a kebab-case label. Examples:
platform,contract-mastery. No prefix; no spaces. - Apply the label to every existing ticket that belongs to that spec (bulk-edit in Jira).
- Create a saved filter via
POST /rest/api/3/filter(Jira REST).aclicannot do this; the API call is one shot. - Create a Scrum board backed by the filter:
acli jira board create --filter-id <id>.
Alternative discriminators: component, epic, or raw jql (read-only). The Hano dogfood used labels: boards 136/137/138, filters 10269/10270/10271, labels platform / contract-mastery / ehr-integration.
GitHub Issues
- Pick a kebab-case label. GitHub labels are repo-wide and case-sensitive — pick something distinctive (e.g.
spec:platform,spec:ehr-integration) so the label doesn't collide with other repo labels. - Create the label on the repo:
gh label create platform --description 'Spec: Multi-tenant Platform' --color FFA500(one per spec). - Apply the label to every existing issue that belongs to that spec:
gh issue edit <number> --add-label platformor bulk-edit in the GitHub UI. - Optional: saved searches / projects. GitHub Projects (v2) board with the label filter is the natural multi-spec view, but not required — the adapter constructs the filter from
.synaptory.yamlat query time.
Alternative discriminator: milestone. Use this if each spec maps to a long-lived release/quarter rather than a label (e.g. CM-2026Q1). Note that the GitHub adapter also uses milestones for sprints — when both spec and sprint are milestone-bound, the sprint scope wins for read queries.
Teamwork
- Pick a kebab-case tag name. Teamwork tags are scoped per Teamwork installation (not per project) — verify your name isn't already taken:
https://<site>.teamwork.com/app/people/tags. - Create the tag via the Teamwork UI (Add → Tags) or let the adapter auto-create on first write — it calls
get_or_create_tag()on the transport. - Apply the tag to every existing task that belongs to that spec (bulk-tag in Teamwork UI).
- Optional: saved filters. Teamwork's "Saved Filters" on the Tasks page give your team the per-spec board view without leaving the project.
Alternative discriminator: tasklist. Use this if each spec already owns a dedicated tasklist in the Teamwork project (strict partitioning — a task can only live in one tasklist). Filter value is the numeric tasklist id.
Migration: collapse single-spec into multi-spec
If you have an existing Synaptory project, run the migration script before touching .synaptory.yaml by hand:
python3 ${CLAUDE_PLUGIN_ROOT}/skills/_shared/scripts/migrate_to_multispec.py \
--primary-spec=platform \
--new-specs=contract-mastery,ehr-integration
What it does (in order):
- Snapshots
.synaptory/.orchestrator/to.synaptory/.migrations/<timestamp>-pre-multispec.tar.gzso you can roll back. - Upgrades
pipeline-state.jsonfrom v2.0 (flat) to v3.0 (nested underspecs:). The existing flat state (lifecycle/sprint/stories/etc.) collapses understate.specs.<primary>. New specs are initialized atINCEPTION,current_sprint=0, empty caches. - Moves tracker caches and receipts from
.synaptory/.orchestrator/{tracker-id-map,tracker-data,backlog-order}.json+receipts/*tospecs/<primary>/. Emptyspecs/<new-spec>/receipts/directories are created for the new specs. - Appends a stub
specs:block to.synaptory.yaml(you fill inboard_idandfilter.valuefrom your Jira side). - Regenerates the CLAUDE.md sentinel as a multi-spec rollup.
The script is idempotent — re-running it on an already-migrated project is a no-op:
$ python3 .../migrate_to_multispec.py --primary-spec=platform --yes
[migrate-to-multispec] state is already multi-spec — nothing to do.
Post-migration: fill in .synaptory.yaml
The script writes a stub specs: block. Edit it with your actual tracker values per spec. Every spec must bind to the same backend as tracker.backend (mixed bindings are rejected at config-load time).
Jira
tracker:
backend: jira
specs:
- id: "platform"
name: "Multi-tenant Platform"
jira:
url: "https://hano.atlassian.net"
project_key: "HT"
board_id: 136
filter:
type: "label"
value: "platform"
- id: "contract-mastery"
name: "Contract Mastery"
jira:
url: "https://hano.atlassian.net"
project_key: "HT"
board_id: 137
filter:
type: "label"
value: "contract-mastery"
Jira filter.type | Read JQL fragment | Write side-effect |
|---|---|---|
label (recommended) | labels = "<value>" | Append <value> to the new issue's labels |
component | component = "<value>" | Set the issue's component |
epic | "Epic Link" = <value> | Set the issue's parent/epic-link |
jql | (verbatim user-provided JQL fragment) | Refuse to auto-create — read-only spec |
GitHub Issues
tracker:
backend: github
github:
repo: "h3tco/hiro-app"
specs:
- id: "platform"
name: "Multi-tenant Platform"
github:
repo: "h3tco/hiro-app"
# Optional per-spec sprint milestone prefix override:
# sprint_milestone_prefix: "Platform Sprint "
filter:
type: "label"
value: "platform"
- id: "contract-mastery"
name: "Contract Mastery"
github:
repo: "h3tco/hiro-app"
filter:
type: "label"
value: "contract-mastery"
GitHub filter.type | Read search fragment | Write side-effect |
|---|---|---|
label (recommended) | label:"<value>" | Append <value> to the new issue's labels (creates the repo label if missing) |
milestone | milestone:"<value>" | Set the new issue's milestone — only when the caller didn't already pin one (sprint > spec) |
Teamwork
tracker:
backend: teamwork
teamwork:
site_name: "hano"
project_id: 999
specs:
- id: "platform"
name: "Multi-tenant Platform"
teamwork:
site_name: "hano"
project_id: 999
filter:
type: "tag"
value: "platform"
- id: "contract-mastery"
name: "Contract Mastery"
teamwork:
site_name: "hano"
project_id: 999
filter:
type: "tasklist"
value: "12345" # numeric Teamwork tasklist id
Teamwork filter.type | Read list_tasks filter | Write side-effect |
|---|---|---|
tag (recommended) | tagIds=<resolved-id> (auto-looked-up by name via get_or_create_tag()) | Append the tag id to the new task's tagIds |
tasklist | tasklistIds=<id> | Place new aux tasks (Tasks/Bugs/Enhancements) in this tasklist; sprint tasklists still win when a story has a sprint assignment |
Per-spec workflow_stages (when specs target different Teamwork projects). Teamwork assigns workflow stage IDs per project — a single top-level tracker.teamwork.workflow_stages map only resolves in one project, so writes against the other spec's project land in the wrong stage. When each spec sets its own teamwork.project_id, also give each spec its own workflow_stages map; per-spec values take precedence over the top-level map and fall back to it when empty. Per-spec sprint_milestone_prefix keeps milestone names from colliding across specs.
tracker:
backend: teamwork
teamwork:
site_name: "lmhealthcarecommunications"
# No top-level project_id or workflow_stages — each spec carries its own.
specs:
- id: "venue-agent"
name: "Venue Agent"
teamwork:
project_id: 1519491
sprint_milestone_prefix: "Venue Sprint "
workflow_stages:
TO_DO: 25086
IN_PROGRESS: 25087
DONE: 25091
filter: { type: "tag", value: "venue-agent" }
- id: "stars-assistant"
name: "STARS Assistant"
teamwork:
project_id: 1598948
sprint_milestone_prefix: "STARS Sprint "
workflow_stages:
TO_DO: 385922
IN_PROGRESS: 385923
IN_REVIEW: 385924
DONE: 385929
filter: { type: "tag", value: "stars-assistant" }
Post-migration: edit CLAUDE.md
The migration script does not rewrite the body of CLAUDE.md beyond the state sentinel. You should add ### Spec: <name> headings yourself and move spec-specific guidance under them:
# Shared Agent Instructions
(shared top block — monorepo layout, commands, git rules, generic patterns)
### Spec: Multi-tenant Platform
(platform-specific guidance: schema isolation rules, tenant boundary discipline, etc.)
### Spec: Contract Mastery
(CM domain glossary, payer-contract authoring rules, etc.)
### Spec: EHR Integration
(EI vendor abstraction rules, PHI audit, simulator profiles, etc.)
<!-- synaptory-state ... -->
Each agent invocation reads the shared top block + only its active spec's section.
Day-to-day usage
Two ways to inspect or switch the active spec
The currently-active spec lives in pipeline-state.json.active_spec. You have two equivalent paths to read or change it:
| Surface | Inspect | Switch |
|---|---|---|
| CLI (terminal) | synaptory status · synaptory specs list · synaptory specs show [id] | synaptory specs switch <id> |
| Inside an agent session | ask the orchestrator: "show specs", "what's the active spec?" — routes via /synaptory to the status mode | /switch-spec <id> (natural-language phrase routed through /synaptory — see routing-rules.json) |
Both paths write to the same file atomically. The CLI is fastest from a terminal; the orchestrator routing is fastest while you're already in an agent session.
Picking the active spec
The currently-active spec is also displayed in the CLAUDE.md sentinel rollup:
<!-- synaptory-state
last_updated: 2026-05-25T12:34:00Z
active_spec: platform
specs:
platform: SPRINT_EXECUTION sprint=9 last_agent=ht-415-retrospective
contract-mastery: INCEPTION sprint=0 last_agent=<none>
ehr-integration: INCEPTION sprint=0 last_agent=<none>
-->
Switch the active spec from inside an agent session:
/switch-spec contract-mastery
Or naturally: "make platform the active spec", "switch to the EHR one". The orchestrator routes to the /switch-spec mode, which:
- Validates the id against
.synaptory.yaml. - Writes
active_spec: <id>topipeline-state.json(atomic). - Re-renders the CLAUDE.md sentinel.
- Echoes the new spec's lifecycle + sprint.
Running scheduled commands per spec
Every tracker-side CLI accepts a --spec=<id> flag that overrides active_spec:
# Advance only the platform sprint, leaving CM and EI untouched
python3 .../scrum_state_machine.py transition <project_dir> SPRINT_PLANNING --spec=platform
# Query the CM backlog without touching active_spec
python3 .../tracker_cli.py get-backlog --spec=contract-mastery
# Update a story under EI's board
python3 .../tracker_cli.py update-status US-EI-3 IN_PROGRESS --spec=ehr-integration
This lets you wire up one scheduled routine per spec (e.g. via the control-plane's scheduled tasks), each carrying its own --spec flag. Routines never need to switch the persisted active_spec.
Scoped agent dispatches
When the orchestrator dispatches a subagent, it sets SYNAPTORY_ACTIVE_SPEC=<id> in the subagent's environment so:
- Every internal tracker call routes to the spec's board (right project + right filter).
- The state machine writes to
state.specs.<id>only. - The receipt is filed under
specs/<id>/receipts/{story_id}-{role}.json.
Agents read the spec context from $SYNAPTORY_ACTIVE_SPEC first, falling back to pipeline-state.json.active_spec. The CLAUDE.md ### Spec: <name> section corresponding to the active spec is loaded; other specs' sections are not.
Concurrency model
Three concurrent sessions, each running /sprint-advance --spec=<X> on a different spec, will all succeed and leave their respective current_sprint counters correct.
Under the hood: spec_state.write_state() wraps the multi-spec read-modify-write window in an fcntl advisory exclusive lock on pipeline-state.json.lock. This prevents lost updates when two writers target different spec slots in the same file. Same-spec concurrent writes still rely on last-writer-wins — if you genuinely need to advance the same spec from two places at once, you need a higher-level coordinator.
The lock is a no-op on platforms without fcntl (Windows); current production targets (macOS + Linux) are unaffected.
Rollback
If something goes wrong:
# Restore the pre-migration state from the backup tar
cd <project_root>
ls -la .synaptory/.migrations/
tar -xzf .synaptory/.migrations/<timestamp>-pre-multispec.tar.gz -C .synaptory/
The backup snapshots the entire .synaptory/.orchestrator/ directory, so restoring it reverts the schema, the cache layout, and the receipts. After restoring, remove the specs: block from .synaptory.yaml to disable multi-spec opt-in.
Out of scope (v1)
The first cut intentionally avoids these:
- Cross-spec reads from agents. A CM agent cannot list platform stories. Humans link in Jira; agents stay isolated.
- Cross-spec sprint coordination. Two specs sprinting on overlapping work need a human coordinator.
- N Jira projects per codebase. This design assumes one project. Customers with hard org boundaries between specs (different BAAs, different access policies) need a separate enhancement.
- Cross-spec receipt rollup. Per-spec streams only.
- Spec auto-detection from git branch. Explicit
/switch-specis the only way to changeactive_spec.
If you need any of these, file a request via /synaptory report.
Reference
| Topic | Where |
|---|---|
| Full design + decision rationale | docs/multi-spec-design.md |
.synaptory.yaml schema | reference/config.md — specs: block |
/switch-spec mode | plugin/skills/synaptory/modes/switch-spec.md |
| Migration script | plugin/skills/_shared/scripts/migrate_to_multispec.py |
| State helpers | plugin/hooks/lib/spec_state.py |
| Layer-1 tests | plugin/tests/lib/test_multi_spec.py (13 tests) |
| Layer-2 hook tests | plugin/tests/hooks/test_multi_spec_hooks.py (4 tests) |
Release
Guide for shipping code to production. Release is a first-class lifecycle event -- available on-demand from both Scrum and Kanban, with full verification at maximum depth.
When to Release
Manual Trigger
Say "release", "ship it", or "go live" at any point:
release
ship it
go to production
production ready
Orchestrator Suggestion
At Sprint Close, if all epics are marked Done, the orchestrator notes:
All epics completed. Consider releasing.
Options: [Start Release] [Continue to Sprint N+1] [Stop]
Release is never auto-triggered. You always decide.
Mid-Project Release
You can release after any sprint or anytime in Kanban. Not every feature needs to be complete -- release what's ready.
What Happens During Release
Release runs all agents at maximum verification depth:
| Activity | Agent | What Happens |
|---|---|---|
| Full regression testing | Quality Engineer | Unit, integration, e2e, performance tests across ALL sprints/tickets. Not just the latest -- everything. |
| Full security audit | Compliance Engineer | STRIDE threat model, OWASP Top 10, dependency vulnerability scan, full depth. In Controlled mode, includes PTES penetration testing. |
| Production infrastructure | Platform Engineer | IaC modules, production CI/CD pipelines, monitoring, alerting, runbooks, capacity planning. |
| Complete documentation | Technical Writer | API reference, developer guides, operational guide, architecture guide. |
| Final code review | Code Reviewer | Full codebase review -- architecture conformance, performance, code quality across the entire project. |
| Skill extraction | Orchestrator | Extracts recurring patterns into reusable Claude Code skills. |
Release Readiness Check
After all agents complete, the orchestrator presents a readiness dashboard:
Release Readiness
Sprints: {completed}/{total} completed
Stories: {done}/{total} done
Tests: {passed}/{total} passing ({coverage}% coverage)
Security: {critical} Critical, {high} High remaining
Infrastructure: ✓ Production-ready
Documentation: ✓ Complete
Rollback: ✓ Plan documented
Options:
[Approve Release]
[I have concerns]
[View details]
All DoD checks run at Release intensity -- the highest depth level:
| Check | Release Behavior |
|---|---|
| Tests pass | Full regression across all code, not just latest sprint |
| Build succeeds | Production build, not dev build |
| No critical findings | Full STRIDE + OWASP + dependency scan |
| Code reviewed | Complete codebase review |
| Coverage no decrease | Final coverage baseline established |
Release from Scrum vs Kanban
| Aspect | Scrum Release | Kanban Release |
|---|---|---|
| Trigger | After Sprint Close, manual or suggested | Anytime, manual only |
| Scope | All completed sprints | All completed tickets |
| Sprint overlay | Final sprint DoD overlay evaluated | No sprint overlay |
| History | Sprint metrics archived | Ticket throughput archived |
| What's next | COMPLETE (terminal) or transition to Kanban | COMPLETE (terminal) |
After Release
The lifecycle reaches the COMPLETE terminal state. From here:
- Transition to Kanban for ongoing maintenance (
build_mode: kanban) - Start a new Scrum cycle for major new features (Inception again)
- Stop -- the project is shipped
What's next?
- Scrum Delivery -- The sprint lifecycle that leads to Release
- Kanban Delivery -- Continuous delivery with on-demand Release
- Enforcement -- How DoD scales to Release intensity
Resuming Sessions and Tracking Progress
Guide for resuming interrupted delivery runs, understanding lifecycle state, and using the visualization tools that synaptory provides.
Cross-Session Persistence
How it works
synaptory saves and restores lifecycle state automatically across Claude Code sessions. Two hooks handle this:
| Hook | Event | What it does |
|---|---|---|
synaptory-pipeline-snapshot.sh | Stop (session end) | Writes a state snapshot to .synaptory/.orchestrator/last-session.md -- current ceremony, completed stories, sprint state, pending work |
synaptory-session-start.sh | SessionStart | Detects .synaptory/ workspace, reads pipeline-state.json, injects lifecycle state, story pipeline status, and context packages into the session |
Everything that matters for resumption is persisted to disk:
- Lifecycle state (
pipeline-state.json) -- current ceremony (e.g., SPRINT_EXECUTION), lifecycle history, Inception Gate decisions - Sprint state (inside
pipeline-state.json) -- current sprint number, completed sprints, sprint metrics, carry-over stories - Story pipeline (inside
pipeline-state.json) -- per-story sub-states (queued, in_progress, testing, reviewing, done, blocked) - Receipts (
.synaptory/.orchestrator/receipts/) -- story-scoped receipts with backend traceability - Context packages (
.synaptory/.orchestrator/context-packages/) -- brownfield analysis artifacts - Session snapshot (
.synaptory/.orchestrator/last-session.md) -- human-readable summary of where the run stopped
No manual export or import is needed. Close Claude Code, reopen it tomorrow, and the delivery run picks up where it left off.
Checking Status
Say "status" (or "show progress", "where are we") at any time:
show status
The status display includes:
- Lifecycle position -- current ceremony (e.g., Sprint 2 / Execution) with story pipeline progress
- Story pipeline -- per-story status (queued, in_progress, testing, reviewing, done)
- Agent metrics -- which backend produced each story, files read/written, key outputs
- DoD compliance -- per-story and sprint-level DoD check results
- Sprint metrics -- velocity, stories planned vs completed, carry-over count
- Context packages (if Discover was run)
- Next-action suggestion -- what to do next based on current state
Check status when:
- Resuming after a break -- to orient yourself before continuing
- Mid-sprint -- to check story pipeline progress
- After Sprint Review -- to see the full sprint metrics
- Debugging state issues -- to verify lifecycle state is correct
Visualization
Three complementary views are auto-generated after ceremony completions and session end.
1. Terminal dashboard -- "show status"
The live view described above. Always current, always available. Say "status" or "show progress" in your Claude Code session.
2. Markdown journal -- .synaptory/PIPELINE.md
Auto-generated at ceremony completions and session end. A persistent record that tracks:
- Lifecycle timeline with ceremony timestamps and durations
- Story receipts: which agent and backend produced each story, verification results
- DoD evaluation results per story and per sprint
- Inception Gate decisions and rework cycles
- Sprint metrics (velocity, completion rate, carry-over)
- Context packages
3. HTML dashboard -- .synaptory/PIPELINE.html
A dark-theme, self-contained HTML file. Contains:
- Summary cards (sprints completed, stories done, tests written, findings)
- Story pipeline visualization
- Agent/backend performance comparison
- Sprint metrics over time
- DoD compliance trends
Open in any browser -- fully self-contained with inline CSS and data.
Re-Anchoring
What it is
Re-anchoring is the process of re-reading key artifacts (BRD, ADRs, API contracts, receipts, context packages) directly from disk before spawning agents or continuing work. It prevents silent context degradation where the model's memory of architecture decisions drifts over long runs.
When it triggers automatically
- Before context compaction -- the
synaptory-reanchor.shhook fires on thePreCompactevent. Before Claude Code compresses the context window, the hook re-injects critical artifacts so they survive compaction intact.
- At ceremony transitions -- the orchestrator re-reads key artifacts from disk before starting each ceremony. For example, before Sprint Planning, the orchestrator re-reads ADRs, prior sprint feedback, and the current backlog.
What gets re-anchored
docs/requirements/BRD.md-- the approved Business Requirements Documentdocs/architecture/adr/*.md-- Architecture Decision Recordsapi/openapi/*.yaml-- API contracts.synaptory/.orchestrator/receipts/*.json-- story-scoped receipts.synaptory/.orchestrator/context-packages/*.md-- brownfield context packages- Sprint state and story pipeline state
Manual trigger
If you suspect context degradation (agents seem to forget architecture decisions):
/synaptory -- re-anchor context
Symptoms of degradation:
- An agent produces output that contradicts an ADR
- An agent asks a question already answered in the BRD
- Tests target the wrong API endpoints or data model
Resuming After a Break
Step-by-step
- Open the project in Claude Code. The
synaptory-session-start.shhook fires automatically, loading lifecycle state and context packages.
- Check where you are:
`` show status `` This shows the current ceremony, story pipeline status, and pending work.
- Continue:
`` continue sprint next sprint resume sprint 3 ` Or for Kanban projects: ` pull next ticket what's next `` The orchestrator reads state and picks up where it left off.
- If a gate was pending, the orchestrator re-presents it.
- If an agent had failed, check the escalation report and decide how to proceed.
What if the state seems wrong?
If "show status" reveals incorrect state:
- Check the raw state:
``bash cat .synaptory/.orchestrator/pipeline-state.json ``
- For Scrum state issues:
``bash python3 /path/to/plugin/hooks/lib/scrum_state_machine.py read "$(pwd)" ``
- For Kanban state issues:
``bash python3 /path/to/plugin/hooks/lib/kanban_state_machine.py read "$(pwd)" ``
- Manual state correction (use with caution):
``bash python3 /path/to/plugin/hooks/lib/state_machine.py transition "$(pwd)" SPRINT_REVIEW ``
Long multi-session builds
For projects that span multiple sessions (days or weeks):
- Lifecycle state, receipts, and context packages all persist on disk
- The session start hook re-injects everything on each new session
- The re-anchor hook protects against context degradation within long sessions
- Sprint boundaries are natural session boundaries: complete a sprint, stop, come back tomorrow, start the next sprint
- Kanban tickets are natural units too: finish a ticket, stop, resume with the next one
What's next?
- Commands Reference -- State machine CLI for manual state inspection
- Hooks Reference -- Details on persistence and re-anchoring hooks
- Troubleshooting -- Fixes for state issues and context degradation
Using the Control Plane
Single browser app for every signed-in
synaptory-usersmember. Lives athttps://synaptory.h3t.co/. Pages are role-aware — what you see is auto-scoped to what your Entra group membership andproject_membersrows grant.
Per ADR-019 the legacy /console/* (admin) and /portal/* (member) URL trees were collapsed into one tree at root URLs. There is no longer a separate "Console" or "Portal" — admins, project admins, project members, and unaffiliated users all use the same pages; the data they see differs.
If you've never signed in: open https://synaptory.h3t.co/ in a browser. You'll be redirected to Entra, then back to the root page, which redirects you to /overview (if you're a global admin) or /home (everyone else). Same Entra app, same redirect URI as the CLI uses — see Auth flows.
Page reference
The Control Plane mounts a single AppChrome (collapsible sidebar, theme toggle, user-menu) with the brand subtitle "CONTROL PLANE". Sidebar entries are filtered by your role — admin-only pages (Overview, Policy, System, Grafana, Settings, Access review) only render in the sidebar for callers in synaptory-admins.
| Path | Purpose | Visible to | Backed by |
|---|---|---|---|
/ | Role-aware redirect (admin → /overview, else → /home) | everyone | server redirect, no API call |
/home | Identity card + quick links | everyone | session cookie, no API call |
/overview | KPI band, gate queue (4 v3 gates), recent activity | global admin | /v1/analytics/overview, /v1/analytics/evidence-gates |
/projects | Projects you can see (admins can pass ?all=true) | everyone | /v1/projects |
/projects/<slug> | Project detail + Members tab | everyone with a role on the project | /v1/projects/<slug> |
/projects/<slug>/overview | Project cockpit (per-project KPIs) | project admin + global admin | scope-aware analytics |
/audit | Audit log with detail drawer | everyone (scope-aware) | /v1/analytics/audit, /v1/analytics/audit/<id> |
/sessions | Sessions list with two-step revoke | everyone (scope-aware) | /v1/sessions, DELETE /v1/sessions/<id>, POST /v1/sessions/revoke-all |
/skills | Manifest + your usage stats | everyone | /v1/skills/manifest, /v1/analytics/skill-distribution |
/quality | Evidence/DoD scoreboard, per-spec gate matrix, per-role pass-rate | everyone (scope-aware) | /v1/analytics/evidence-gates, /v1/analytics/specs/quality |
/cost | USD compute, per-stage spend, per-model rollup, fallback waste | everyone (scope-aware) | /v1/analytics/cost/* |
/reliability | OTLP latency p50/p95/p99, top errors, fallback waste, outbox health | everyone (scope-aware) | /v1/analytics/reliability/* |
/people | Per-Delivery-Owner activity, time-of-day heatmap, new-vs-returning cohort | everyone (scope-aware) | /v1/analytics/people/* |
/policy | Read-only signed-config viewer | global admin | /v1/config/* |
/system | Probes + versions + security mode + last backup | global admin | /v1/admin/system/health |
/settings | Operator settings | global admin | /v1/admin/* |
/grafana | Grafana iframe | global admin | Grafana via Caddy reverse-proxy |
/access-review | Periodic access review | global admin | scope-aware /v1/analytics/people/access-review |
/profile | Identity / groups / sign-out / sign-out-everywhere | everyone | session cookie + POST /v1/sessions/revoke-all |
How role gating works
The same page renders for every viewer; the data and controls differ:
- Global admin (
synaptory-admins): sees everything. Cross-UPN visibility on/audit,/sessions. All projects on/projects. Project create / archive controls visible on/projects. - Project admin (
project_members.role = 'admin'): sees their admin projects' analytics with cross-UPN visibility within those projects. Members tab shows invite / revoke / promote. - Project member (
project_members.role = 'member'): sees their member projects' analytics filtered to their own UPN. Members tab is read-only. - Unaffiliated: sees identity, sessions, skills (manifest only), and (Phase 2b) the access-request workflow. Analytics return empty.
Anti-leak: every endpoint that takes ?project=<slug> returns 404 (not 403) when the caller can't see the project. Status codes never confirm existence of projects you don't have a role on.
Project filtering
Most analytics pages accept ?project=<slug> to scope every chart and table to one project. The explicit ?project=all sentinel restores the caller's full visible scope. Two pages are intrinsically global and ignore the param: /projects (the project list itself) and /grafana (Grafana has its own filtering UI).
When you select a project from the project picker in the header, every page link in the sidebar carries the ?project=<slug> param forward.
Overview: the gate queue
The Overview page's headline component is the Gate Queue card, which renders all four v3 gates:
- Inception — has the project's Sprint 0 produced a signed-off vision?
- Spec Ready — for the active sprint, are the stories spec-complete?
- Evidence / DoD — for stories in
reviewing, are receipts + verification commands present? (This is the only gate with a wired backend signal in v2.5 — the others are placeholders that light up in place when v3.0 ships.) - Release — are sprint outcomes shippable?
The Evidence/DoD gate maps to the enforcement model you already know from the plugin guide.
Quality: per-spec gate matrix
The Quality page is the operator's view of the Evidence/DoD gate. Three sections:
- Scoreboard — pass-rate over time, broken out by gate sub-signal (tests-pass, build-succeeds, no-critical-findings, code-reviewed, coverage-no-decrease).
- Per-spec gate matrix — a grid of stories (specs in v3) × gates. Hover for the receipt link.
- Per-role pass-rate — which roles produce the most failing receipts. Use this to spot a flaky agent.
In v2.5 vocabulary: "spec" = "story" with kind=story; the spec model expands in v3 to include feature, bugfix, task, release. The current grid only contains stories.
Cost: USD compute breakdown
Cost endpoints aggregate Receipt.payload.token_usage against pinned per-model rates in MODEL_PRICING_USD_PER_M (api/synaptoryapi/routers/analytics.py). Four panels:
- Summary — total spend window-over-window, with cache-hit ratio.
- By stage — 11 v3 stages (
pro-discovery,pro-brd,pro-ux-spec,sa-architecture,se-implementation,qe-verification,cr-review,ce-compliance,pe-infra,tw-docs,orchestrator). - By model — per Claude model, USD spent and tokens used.
- Fallbacks — when a higher tier failed and the orchestrator dropped to a lower one. "Waste" = tokens spent on the failed call.
Pricing changes are reviewable diffs alongside model-pins.json for AI-BOM provenance.
Reliability: latency and errors
Driven by OTLP spans the CLI emits via synaptory otel. Stored in OtelEvent.payload; aggregated inline today, with an otel_rollup materialized table queued for when span volume crosses ~10k/window.
Three panels:
- Latency — p50/p95/p99 over time. Per-stage and per-role breakouts.
- Errors — top error messages by frequency. Click for the receipts that produced them.
- Outbox health — telemetry queue depth on the CLI side, derived from when batches arrive late.
People: who's delivering
- Staff activity — receipts per UPN over the window (scope-aware: project members see only their own UPN).
- Heatmap — 7×24 grid of activity (day of week × hour). Useful for spotting after-hours work patterns.
- Cohorts — new vs returning Delivery Owners over the window.
In v3.0 vocabulary, "staff" → "Delivery Owner" — the human counterpart to the Project Owner agent.
Projects: provisioning and members
/projects lists every project the caller can see. By default that's the caller's active memberships; global admins can pass ?all=true. Per-slug pages cover:
- Project Overview — slug, created at, archive status, KPI strip scoped to the project.
- Members tab — invite / revoke / promote. Visible to project admins (or global admins) on projects where they hold that role; read-only for plain members.
- Settings — project-level config overrides (admin-only).
Provisioning a new project is currently CLI-side: ./synaptory api projects create <slug> on the prod VM. Members can be added via the Control Plane afterward.
Audit: who did what
Receipts + admin actions in one timeline. Filter by UPN (admin only), project, action, time window. Click a row → drawer with the full receipt or audit-event payload.
The audit log includes admin writes (revoke, invite, archive) — not just delivery receipts. Use this as the forensics surface.
Project members see only their own UPN's rows on /audit. Project admins see cross-UPN rows for their admin projects. Global admins see everything.
Sessions: server-side revoke
/sessions lists scope-aware sessions. Project members see only their own; project admins see all UPNs active in their admin projects; global admins see all. Each row has a two-step revoke button.
The two-step revoke is deliberate friction. Click once → confirm. The component is <ConfirmDestructiveAction>; same primitive used in any destructive action. There's no "are you sure?" modal — the button text changes to "Confirm revoke" and you click again.
Sign-out everywhere: there's a single button on /profile that hits POST /v1/sessions/revoke-all. Use this if you've lost a laptop or suspect token compromise.
A revoked session is rejected on the next API call from that session — there's no push to the laptop. The plugin's CLI will surface a re-run synaptory login prompt within a hook lifecycle.
Skills: manifest and per-skill usage
Two tabs:
- Manifest — every skill name + tier + description. The same payload
/v1/skills/manifestreturns to the CLI on session start. Shared across all users. - Distribution / Usage — usage histograms per skill (admin); your own usage stats (non-admin). The page reads the scope-aware
/v1/analytics/skill-distributionendpoint, which auto-filters non-admins to their own UPN.
The Distribution view reads from Receipt.payload aggregations.
Policy: read-only signed-config
/policy is a read-only viewer of the current signed configuration that the CLI fetches via /v1/config/*. Useful for verifying what policy is live without round-tripping through a CLI call.
The signature is verified server-side on render; if it doesn't verify, the page shows an error and the Audit log carries a warning.
Global admin only.
System: health and versions
Probes, container versions, Postgres replication state, last backup timestamp, current security mode (baa_enforced flag and friends).
Use this as the first stop when you suspect platform-wide trouble. Global admin only.
Profile: sign-out everywhere
/profile shows:
- Identity card — UPN, display name (from Entra), groups (
synaptory-usersplus any others), platform access badge. - Groups list — every group on your session.
- Sign-out button (just this session).
- Sign-out-everywhere button — revokes every active session under your UPN.
In Phase 2b: full current-session card + plugin/CLI install-verification card.
What's next
- Inviting members — for project admins.
- Permissions reference — what each role grants.
- Identity and access — why your view is scoped to you.
Inviting Members to a Project
The end-to-end flow for granting and revoking project access.
Project membership is one piece of state with multiple write paths. This guide covers all of them so you can pick the right tool for the role you're playing.
What "membership" actually means
A row in the project_members table. Schema (simplified):
| Column | Meaning |
|---|---|
project_id | Foreign key into projects |
upn | The Entra UPN (user@h3t.co) |
role | member or admin (project-level role, not platform-level) |
added_at | Timestamp |
revoked_at | Null while active; set when revoked |
The check at api/synaptoryapi/security.py check_project_membership reads this table on every project-scoped API call. There's no caching layer — revoke takes effect on the user's next request.
Three ways to grant access
1. Project admin via the Control Plane
You are: a signed-in user with role=admin on the target project (i.e. you hold the project-admin grant on project_members).
You go to: /projects/<slug> → Members tab → "Invite member" button.
You enter: a UPN. The user must already be a member of synaptory-users (you can't invite people who haven't been provisioned in Entra). The form rejects unknown UPNs with a 404.
The new member is active immediately. They'll see the project on /projects the next time they refresh.
2. Global admin via the Control Plane
You are: a member of synaptory-admins.
You go to: /projects/<slug> → Members tab.
The UI is identical to what project admins use — same <ConfirmDestructiveAction> primitive, same invite form, same backend endpoint (POST /v1/projects/<slug>/members). The only difference is that you can do this on any project, not just ones where you hold a project-admin role.
3. Operator via CLI
You are: an operator with shell access to the prod VM.
You run: ./synaptory api projects add-member <slug> <upn>.
Use this when the Control Plane is down, when you're seeding a fresh project, or in CI for test fixtures.
Revoke
Same three paths, mirrored:
| Surface | Action |
|---|---|
Members tab (/projects/<slug>) | Two-step revoke button per row. Visible to project admins on their projects, to global admins on any project. |
| CLI | ./synaptory api projects revoke <slug> <upn> |
A revoked member's revoked_at is set; the row stays in the table for audit. To re-add, an admin re-invites — a new row is created.
Promote / demote
A project admin can promote a member to admin and demote back, but only on projects they admin. Global admins can do it anywhere.
The CLI doesn't currently expose a promote command directly — use the Control Plane Members tab for promotion, or write the SQL by hand if the web app is unavailable.
What a new member sees
Within seconds of being added:
/projectslists the new project./projects/<slug>opens (Overview tab).synaptory statuson their CLI lists the project under their memberships.cdinto a directory configured for that project's slug; the plugin works.
If they were a member before, were revoked, and are now re-added: the new row is treated as a new membership. The old revoked_at row stays for audit; the new row has revoked_at=null.
What gets logged
Every grant / revoke / promote produces an audit row. View at /audit (filter by action=member.grant etc.) or query the audit_events table directly.
The audit row carries: who did it, who was affected, the project, the resulting role, and a free-text reason (if the form prompted for one — the Control Plane Members tab does; the CLI doesn't).
Common gotchas
- "User not found" — the UPN isn't in the local Entra group. Add to
synaptory-usersin Entra first, then invite to the project. - "Already a member" — there's an active row already. The form deduplicates; nothing's wrong.
- Plugin still 404s after invite — the user's CLI is using a cached SYNAPTORY1 token that pre-dates the invite, but membership is checked per-request, so this shouldn't matter. If it persists, ask the user to run
synaptory statusto force a fresh API hit. - Project archived — archived projects return 403 on every member-write. Unarchive via the Control Plane (
/projects/<slug>→ settings) first; this is global-admin only.
What's next
- Permissions reference — what
membervsadmingrants you. - Identity and access — the per-request enforcement model.
Configuration Reference
Diataxis category: Reference -- information-oriented, for lookup.
synaptory reads its project configuration from .synaptory.yaml at the project root. This file controls delivery lifecycle, agent backends, project identity, directory mapping, tooling preferences, feature toggles, brownfield behavior, Definition of Done, and architecture settings.
The canonical schema with all supported keys, types, defaults, and valid values is maintained in: plugin/skills/_shared/templates/synaptory.yaml.tmpl
Session authentication
synaptory authenticates via your organisation's Entra ID. No token files needed.
On first session start a browser tab opens to complete sign-in. The session is cached in the OS keychain and refreshed silently until it expires (typically 24 hours).
Run synaptory whoami to inspect the cached session at any time. For headless environments, run synaptory login --device once from a terminal and follow the on-screen instructions.
All skill access is scoped to your session identity. Usage is watermarked and auditable by your H3Tech operator.
Auto-configure your project
The recommended way to create .synaptory.yaml is to say "initialize my project". The orchestrator scans the project and generates a tailored config.
initialize my project
What initialization auto-detects
| Signal | Detection source |
|---|---|
| Language | package.json, go.mod, pyproject.toml, Cargo.toml, pom.xml |
| Framework | next.config.*, nest-cli.json, fastapi, gin, actix |
| Infrastructure | Dockerfile*, terraform/, k8s/, .github/workflows/ |
| Architecture | monolith, modular-monolith, microservices, monorepo |
| Project health | test density, TODO/HACK density, git depth, coverage config, documentation level |
The orchestrator shows a detection summary and asks before writing. Review the output before approving -- particularly paths.* for non-standard directory names.
Config keys
project_id
Control-plane project scope. The CLI uses this to scope auth, telemetry, and skill fetch.
Precedence: SYNAPTORY_PROJECT_ID env > this value > the single cached keychain session.
project_id: "my-project" # slug assigned by your H3Tech operator
build_mode
Delivery lifecycle for the project.
| Value | Behavior |
|---|---|
"scrum" | (Default) Time-boxed sprint delivery. Inception -> Sprint loop -> Release. For greenfield or brownfield projects. |
"kanban" | Continuous ticket-based flow. Discover -> Ready -> Execute -> Review -> loop. For brownfield/post-launch maintenance. |
build_mode: "scrum" # or "kanban"
engagement_mode
Controls decision visibility and model routing strategy for agents.
| Value | Behavior |
|---|---|
"structured" | (Default) Opus for strategic/decision roles (PO, SA, CE, RA). Sonnet for executor roles (SE, QE, PE, TW, CR). Agents decide and report without surfacing every choice. |
"interactive" | Same model tiers as structured — no cost premium. Strategic roles surface all major decisions for human review before proceeding. Use for compliance-sensitive builds or when you need an audit trail of every decision. |
Aliases:
autonomousandhands-offare accepted as aliases forstructured.controlledandhands-onare accepted as aliases forinteractive. New config should use the canonical names.
engagement_mode: "structured" # structured | interactive
agents.*
Agent backend configuration. All agents in this build run on Claude.
| Key | Type | Default | Description |
|---|---|---|---|
agents.default_backend | string | "claude" | Backend for all agents. Only claude is supported in this build. |
The Orchestrator always runs on Claude. Model tier (Opus vs Sonnet) is determined by engagement_mode and role type — not configurable per role.
agents:
default_backend: "claude"
tracker.*
Ticket tracker backend for story, epic, sprint, and backlog management.
| Key | Type | Default | Description |
|---|---|---|---|
tracker.backend | string | "local" | Backend provider: local, github, jira, teamwork. |
tracker.github.repo | string | "" | GitHub repo (owner/repo). Auto-detected from git remote if empty. |
tracker.github.points_label_prefix | string | "points:" | Label prefix for story points. |
tracker.github.sprint_milestone_prefix | string | "Sprint " | Milestone naming prefix. |
tracker.jira.url | string | "" | Jira Cloud URL (e.g., https://team.atlassian.net). |
tracker.jira.project_key | string | "" | Jira project key (e.g., ANC). |
tracker.jira.board_id | int | null | Scrum board ID. Auto-detected if null. |
tracker.teamwork.site_name | string | "" | Teamwork subdomain. |
tracker.teamwork.project_id | int | 0 | Numeric project ID. |
tracker.teamwork.sprint_milestone_prefix | string | "Sprint " | Milestone naming prefix. |
tracker.teamwork.workflow_stages | object | — | Maps synaptory statuses to Teamwork board column IDs. |
The local backend works in any build_mode. Remote backends (github, jira, teamwork) require build_mode: scrum.
tracker:
backend: github
github:
repo: myorg/my-project
specs[] — multi-spec (opt-in, since v2.7 / v2.8)
When a top-level specs: block is present, one tracker project (Jira / GitHub repo / Teamwork project) hosts N partitioned backlogs. See the Multi-Spec Delivery guide for the full workflow, runbook, and migration script.
Every spec carries exactly one backend binding (jira: / github: / teamwork:), matching tracker.backend. Mixed bindings are rejected at config-load time. Multi-spec is not supported on tracker.backend: local.
| Key | Type | Description |
|---|---|---|
specs[].id | string | kebab-case spec id (used in --spec flags, directory names). |
specs[].name | string | Human-readable label for the spec. |
| Jira binding | ||
specs[].jira.url | string | Jira Cloud URL. Must agree across specs (single project). |
specs[].jira.project_key | string | Jira project key. Must agree across specs. |
specs[].jira.board_id | int | Spec's Scrum board id (one per spec). |
specs[].jira.filter.type | enum | label \ |
specs[].jira.filter.value | string | Label name, component name, epic key, or raw JQL fragment. |
| GitHub binding | ||
specs[].github.repo | string | owner/repo. Must agree across specs. |
specs[].github.sprint_milestone_prefix | string | Optional per-spec milestone prefix override. |
specs[].github.filter.type | enum | label \ |
specs[].github.filter.value | string | Label name or milestone title. |
| Teamwork binding | ||
specs[].teamwork.site_name | string | Teamwork subdomain. Must agree across specs. |
specs[].teamwork.project_id | int | Numeric Teamwork project id. Must agree across specs. |
specs[].teamwork.filter.type | enum | tag \ |
specs[].teamwork.filter.value | string | Tag name (auto-resolved to tag id) or numeric tasklist id (as string). |
When specs: is absent (default), single-spec behavior is unchanged. When specs: is present, the legacy top-level tracker.<backend> block is ignored if it agrees with every spec, and rejected if it disagrees.
# Jira example
tracker:
backend: jira
specs:
- id: "platform"
name: "Multi-tenant Platform"
jira:
url: "https://hano.atlassian.net"
project_key: "HT"
board_id: 136
filter:
type: "label"
value: "platform"
# GitHub Issues example
tracker:
backend: github
github:
repo: "h3tco/hiro-app"
specs:
- id: "platform"
name: "Multi-tenant Platform"
github:
repo: "h3tco/hiro-app"
filter:
type: "label"
value: "platform"
# Teamwork example
tracker:
backend: teamwork
teamwork:
site_name: "hano"
project_id: 999
specs:
- id: "platform"
name: "Multi-tenant Platform"
teamwork:
site_name: "hano"
project_id: 999
filter:
type: "tag"
value: "platform"
To migrate an existing single-spec project, run migrate_to_multispec.py.
project.*
Project identity. Drives agent decisions for tech stack selection, scaffold structure, and execution patterns.
| Key | Type | Default | Valid values | Description |
|---|---|---|---|---|
project.name | string | "" | any | Project name used in reports and docs. |
project.language | string | "" | typescript, go, python, rust, java | Primary language. Determines tech pack loading. |
project.framework | string | "" | nestjs, express, fastapi, gin, actix, spring | Server framework. |
project.cloud | string | "" | aws, gcp, azure | Cloud provider. |
project.architecture | string | "" | monolith, modular-monolith, microservices | Architecture pattern. |
project.type | string | "greenfield" | greenfield, brownfield, evolved_brownfield, mixed | Project type. |
project.template | string | "" | nextjs-fullstack, express-api, python-fastapi, react-native, flutter, cli-tool, monorepo | Greenfield scaffold archetype. |
project:
name: "my-service"
language: "typescript"
framework: "nextjs"
cloud: "aws"
architecture: "modular-monolith"
type: "greenfield"
template: "nextjs-fullstack"
paths.*
Directory mapping. Critical for existing codebases with non-standard layouts.
| Key | Type | Default | Description |
|---|---|---|---|
paths.services | string | "services/" | Backend services directory. |
paths.frontend | string | "frontend/" | Frontend application directory. |
paths.tests | string | "tests/" | Test files directory. |
paths.iac | string | "infra/opentofu/" | IaC root directory. Derived from preferences.iac_tool. |
paths.ci_cd | string | ".github/workflows/" | CI/CD pipeline definitions. |
paths.docs | string | "docs/" | Documentation directory. |
paths.roadmap | string | "docs/requirements/ROADMAP.md" | Product roadmap file. |
paths.reports | string | "reports" | Sprint and pipeline reports directory. |
paths.workspace | string | ".synaptory/" | synaptory internal workspace. |
paths.brd | string | "docs/requirements/" | PO documentation output. |
preferences.*
Tooling choices. Agents respect these instead of making their own selections.
| Key | Type | Valid values | Description |
|---|---|---|---|
preferences.test_framework | string | jest, vitest, pytest, go-test, junit | Test runner. |
preferences.orm | string | prisma, drizzle, typeorm, sqlalchemy, gorm | ORM / query builder. |
preferences.ci_provider | string | github-actions, gitlab-ci, circleci | CI/CD provider. |
preferences.package_manager | string | npm, pnpm, yarn, bun | Package manager. |
preferences.linter | string | eslint, biome, ruff, golangci-lint | Linter. |
preferences.formatter | string | prettier, biome, black, gofmt | Formatter. |
preferences.frontend_framework | string | nextjs, nuxt, sveltekit, remix | Frontend meta-framework. |
preferences.state_management | string | react-query, redux, pinia, svelte-stores | Client-side state management. |
preferences.styling | string | tailwind, css-modules, styled-components, vanilla-extract | CSS / styling. |
preferences.iac_tool | string | opentofu, terraform, pulumi | Infrastructure as Code tool. Default: opentofu. |
features.*
Feature toggles.
| Key | Type | Default | Description |
|---|---|---|---|
features.frontend | bool | true | Set false for API-only projects. |
features.ai_ml | bool | false | Activates SE ai-ml mode. |
features.multi_tenancy | bool | false | Enables tenant isolation patterns. |
features.documentation_site | bool | false | Generates documentation site at Release. |
features.real_time | bool | false | WebSocket/SSE support. |
features.graphql | bool | false | GraphQL API alongside REST. |
features.grpc | bool | false | gRPC inter-service communication. |
features.event_driven | bool | false | Async messaging patterns. |
features.payment_integration | bool | false | Payment service patterns. |
brownfield.*
Settings for existing codebases.
| Key | Type | Default | Description |
|---|---|---|---|
brownfield.coverage_ratchet | bool | true | Enforce coverage-ratchet: agents must write tests before modifying untested files. |
brownfield.context_packages | bool | true | Auto-load Discover context packages into all agents. |
brownfield.characterization_tests | bool | true | Generate behavior-capturing tests during Discover. |
sprint.*
Scrum delivery settings. Active when build_mode: scrum.
| Key | Type | Default | Description |
|---|---|---|---|
sprint.inception | string | "foundation" | Inception mode: foundation (just enough for Sprint 1) or blueprint (comprehensive upfront plan). |
sprint.protected_modules | list | [] | Paths the SE must confirm before touching. Supports glob strings or objects with path + reason. |
sprint.constraints | list | [] | Architectural rules prepended to every SE prompt. |
sprint.velocity | int or null | null | Average story points per sprint. Used to cap sprint scope. |
sprint.carry_over_policy | string | "move_to_next" | Incomplete story handling: move_to_next, keep_in_sprint, ask. |
sprint.require_context_injection | bool | false | SE must read existing module code before implementing. |
sprint.read_before_write | bool | false | SE must Read() every file before modifying. |
sprint.characterization_tests_first | bool | false | QE must write tests before SE touches legacy code. |
sprint:
inception: "foundation"
protected_modules:
- path: "src/modules/billing/"
reason: "Financial regression risk"
constraints:
- "Every new endpoint MUST use @CurrentTenant()"
velocity: 21
carry_over_policy: "move_to_next"
dod
Definition of Done -- two-layer model. Per-story DoD is evaluated as each story completes the SE->QE->CR pipeline. Sprint-level overlay is evaluated at Sprint Review (Scrum only).
dod.story -- Per-story DoD (both Scrum and Kanban)
| Key | Type | Description |
|---|---|---|
dod.story.auto_check[].id | string | Check identifier (e.g., tests-pass, build-succeeds). |
dod.story.auto_check[].description | string | Human-readable description. |
dod.story.auto_check[].critical | bool | If true, story is blocked when check fails. |
dod.story.auto_check[].agent | string | Agent responsible (optional). |
dod.story.auto_check[].adaptive | bool | If true, check scales with maturity (e.g., skip Sprint 1). |
dod.sprint -- Sprint-level overlay (Scrum only)
| Key | Type | Description |
|---|---|---|
dod.sprint.human_check[] | string | Items requiring human verification at Sprint Review. |
dod.sprint.auto_check[].id | string | Automated check identifier. |
dod.sprint.auto_check[].critical | bool | If true, sprint review is blocked when check fails. |
dod:
story:
auto_check:
- id: tests-pass
description: "All acceptance criteria tests passing"
critical: true
- id: build-succeeds
description: "Build completes and dev server starts"
critical: true
- id: no-critical-findings
description: "Zero Critical security findings"
critical: true
agent: compliance-engineer
- id: code-reviewed
description: "Story code reviewed"
critical: false
agent: code-reviewer
adaptive: true
- id: coverage-no-decrease
description: "Test coverage did not decrease"
critical: false
sprint:
human_check:
- "Sprint Goal met"
- "Stakeholder feedback addressed"
- "Documentation updated"
auto_check:
- id: no-regression
description: "No regression across sprint stories"
critical: true
dor
Definition of Ready. Used to validate stories before sprint commitment.
| Key | Type | Default | Description |
|---|---|---|---|
dor.file | string | "" | Path to a DoR markdown file. Parser reads bullet lines. |
dor.inline | list | [] | Inline DoR criteria when file is empty. |
architecture
Solution Architect settings.
| Key | Type | Default | Description |
|---|---|---|---|
architecture.health_check_interval | int | 3 | Run SA health check every N sprints (0 = disabled). |
architecture.triggers | list | [new_entity, new_service, new_integration, security_requirement, performance_story] | Auto-detect triggers for SA invocation. |
story_buddy
Story Buddy settings.
| Key | Type | Default | Description |
|---|---|---|---|
story_buddy.issue_templates | list | [] | Paths to issue template files for story structural validation. |
Complete examples
Greenfield SaaS (Scrum)
version: "3.0"
build_mode: "scrum"
engagement_mode: "structured"
project:
name: "reservation-saas"
language: "typescript"
framework: "nextjs"
cloud: "aws"
architecture: "modular-monolith"
type: "greenfield"
template: "nextjs-fullstack"
agents:
default_backend: "claude"
sprint:
inception: "foundation"
carry_over_policy: "move_to_next"
velocity: 21
tracker:
backend: "github"
github:
repo: "myorg/reservation-saas"
preferences:
test_framework: "vitest"
orm: "prisma"
package_manager: "pnpm"
frontend_framework: "nextjs"
styling: "tailwind"
features:
frontend: true
multi_tenancy: true
payment_integration: true
real_time: true
Brownfield API (Kanban, maintenance)
version: "3.0"
build_mode: "kanban"
engagement_mode: "structured"
project:
name: "payments-api"
language: "typescript"
framework: "express"
cloud: "aws"
architecture: "monolith"
type: "brownfield"
agents:
default_backend: "claude"
tracker:
backend: "jira"
jira:
url: "https://myteam.atlassian.net"
project_key: "PAY"
paths:
services: "src/"
tests: "test/"
preferences:
test_framework: "jest"
orm: "typeorm"
features:
frontend: false
brownfield:
coverage_ratchet: true
context_packages: true
characterization_tests: true
What's next?
- Commands Reference -- Slash commands, state machine CLI, and admin tools
- Hooks Reference -- Lifecycle hooks and enforcement behavior
- Getting Started -- First-time setup and configuration walkthrough
Commands Reference
Diataxis category: Reference -- information-oriented, for lookup.
All commands available in synaptory: slash commands (user-facing skills), the synaptory Go CLI, state machine CLIs (lifecycle internals), and admin scripts.
Slash commands
| Command | What it does | When to use |
|---|---|---|
/synaptory | Starts or continues the adaptive delivery lifecycle. Classifies the request into an operation mode and routes to the appropriate agents. Also handles init, status, help, and reporting via natural language. | Any build, sprint, kanban, debug, review, story buddy, init, status, help, or other task. |
Modes within /synaptory
The following capabilities are triggered by natural language. See Modes for behavioural detail and Routing for the full trigger table and tiebreakers.
| Mode | Trigger phrases | What it does |
|---|---|---|
| Build | "build a SaaS", "from scratch", greenfield intent | Full Scrum lifecycle: Inception -> Sprint loop -> Release |
| Sprint | "sprint N", "next sprint", "continue sprint" | Routes to current ceremony in an active Scrum project |
| Kanban | "fix ticket", "work on TICKET-xxx", "maintenance" | Continuous ticket flow for brownfield projects |
| Doctor | "doctor", "diagnose", "check config", "validate config" | Read-only configuration diagnostic. Pass/warn/fail report with remediation guidance. |
| Init | "initialize", "configure project", "set up synaptory" | Project detection + .synaptory.yaml generation |
| Status | "status", "progress", "where are we" | Lifecycle state dashboard |
| Help | "help", "what can you do" | Quick reference card |
| Report | "report a bug", "report an issue" | Gather context + file GitHub issue against the synaptory repo |
| Story Buddy | "analyze US-037", "implement story", "test story", "help plan sprint" | Per-story assistance (Requirements / Implement / Test / Sprint Plan) |
| Debug | "debug", "fix this bug", "not working", "error" | 4-phase root-cause analysis: Reproduce -> Isolate -> Understand -> Fix |
| Explore | "help me think", "what should I", "I'm not sure" | Research Advisor thinking partner |
| Discover | "understand this codebase", "map the system" | Reverse-engineer codebase, build context packages |
| Context Refresh | "update context", "refresh context" | Incremental re-analysis of changed files |
| Preview | "preview", "run it", "start server", "launch" | Dev server launch and smoke test |
| Branch Finish | "finish this branch", "merge", "create PR" | Per-branch verification and merge |
| Retro | "retro", "what did we ship", "metrics" | Standalone engineering retrospective |
| Test | "write tests", "test coverage", "add tests" (no story ID) | Quality Engineer generates tests for working code |
| Review | "review my code", "code review", "code quality" | Code Reviewer adversarial read-only analysis |
| Architect | "design", "API design", "data model", "tech stack" | Solution Architect: ADRs, contracts, ERDs |
| Document | "document", "write docs", "API docs", "README" | Technical Writer documentation generation |
| Optimize | "performance", "slow", "optimize", "scale" | Platform Engineer + Code Reviewer perf work |
| Stabilize | "characterization tests", "before refactoring", "coverage ratchet" | Quality Engineer + Code Reviewer pre-refactor safety net |
| Modernize | "modernize", "migrate", "strangler fig", "migration plan" | Solution Architect + Compliance Engineer migration plan |
| Custom | (no other mode matches) | Skill menu — pick the agent and scope |
| Release | "release", "ship it", "go live" | Full verification + production prep |
| Update | (auto, before every other mode) | Silent plugin version check; one-question prompt if newer version available |
Automatic invocation
You do not need to prefix every request with /synaptory. The orchestrator is invoked automatically when you type a natural language request. Activation rules define keyword and intent patterns that route to the appropriate mode.
Examples:
Build me a SaaS for managing restaurant reservations
Add Stripe payment integration
Review my code
Debug -- login endpoint returns 500
Finish this branch
initialize my project
show status
CLI commands
The synaptory Go CLI is shipped separately from the plugin and installed once per laptop via https://synaptory.h3t.co/cli/install.{sh,ps1} — see Install the CLI. It handles authentication, skill delivery, telemetry, and policy sync. Plugin hooks shell out to the synaptory binary on $PATH; you can also run it directly from a terminal.
| Command | What it does |
|---|---|
synaptory login [--device] | Sign in via Entra ID. --device for headless environments. |
synaptory logout | Revoke cached session and clear keychain entry. |
synaptory whoami | Print cached UPN, project, token expiry and time remaining. |
synaptory status | Full diagnostic: auth state, skill cache size, outbox depth. |
synaptory skills sync | Fetch manifest and pull missing/stale skills into cache. |
synaptory skills list | List cached skills. |
synaptory skills get <name> | Print cached body for a skill; live fetch on cache miss. |
synaptory config fetch [--if-stale] | Pull policy from control-plane; update local cache. |
synaptory config env | Print cached policy summary (version, backends, roster). |
synaptory projects list | List control-plane projects the current user has access to. |
synaptory projects current | Show the active project for this directory. |
synaptory outbox list | Inspect queued telemetry events. |
synaptory outbox flush | Manually force outbox flush to control-plane. |
synaptory version | Print CLI version. |
State machine CLIs
synaptory uses separate state machines for Scrum and Kanban lifecycles, plus a shared story pipeline. All are in plugin/hooks/lib/.
Scrum state machine
python3 scrum_state_machine.py <action> <project_dir> [args]
| Action | Description |
|---|---|
read | Print the full Scrum lifecycle state JSON |
init | Initialize a new Scrum lifecycle |
transition | Transition to the next ceremony state |
start_sprint | Start Sprint Execution from Sprint Planning with sprint goal and story list |
complete_sprint | Close Sprint Execution and move to Sprint Review |
close_sprint | Close the sprint and continue to the next sprint or Release |
add_story | Add a story to the active sprint backlog |
transition_story | Move a story through the shared story pipeline |
evaluate_dod | Evaluate per-story Definition of Done |
velocity | Calculate sprint velocity metrics |
summary | Build sprint summary data |
retro_check | Evaluate whether Sprint Retro is needed |
transition_to_kanban | Convert a completed Scrum project to Kanban mode |
Scrum lifecycle states:
INCEPTION -> SPRINT_PLANNING -> SPRINT_EXECUTION -> SPRINT_REVIEW
-> SPRINT_RETRO (adaptive) -> SPRINT_CLOSE -> (loop) -> RELEASE -> COMPLETE
Kanban state machine
python3 kanban_state_machine.py <action> <project_dir> [args]
| Action | Description |
|---|---|
read | Print the full Kanban lifecycle state JSON |
init | Initialize a new Kanban lifecycle |
transition | Transition to the next state |
pull_ticket | Pull a ticket into the active Kanban board |
complete_ticket | Move a completed ticket into history |
transition_story | Move a ticket through the shared story pipeline |
evaluate_dod | Evaluate per-ticket Definition of Done |
throughput | Calculate throughput metrics over a time window |
summary | Build Kanban summary data |
Kanban lifecycle states:
DISCOVER -> READY -> EXECUTION -> REVIEW -> (loop to READY) -> RELEASE -> COMPLETE
Shared state dispatcher
python3 state_machine.py <action> <project_dir> [args]
Thin dispatcher for lifecycle bootstrap and state reads. It does not proxy the full Scrum or Kanban command surface.
| Action | Description |
|---|---|
read | Print the full lifecycle state (routes to Scrum or Kanban) |
init_scrum | Initialize a new Scrum lifecycle |
init_kanban | Initialize a new Kanban lifecycle |
Story pipeline CLI
python3 story_pipeline.py <action> <project_dir> [args]
The story pipeline is shared by Scrum stories and Kanban tickets.
| Action | Description |
|---|---|
create_story | Create a new queued story or ticket |
transition | Move a story or ticket to the next pipeline sub-state |
unblock | Return a blocked item to its prior active state |
get_story | Print one story or ticket record |
list_stories | List stories or tickets filtered by state |
evaluate_dod | Evaluate per-story or per-ticket DoD |
aggregate_dod | Aggregate DoD results across the active set |
cycle_time | Calculate cycle time for one story or ticket |
Story pipeline sub-states
Stories move through these sub-states within any lifecycle:
queued -> in_progress (SE) -> testing (QE) -> reviewing (CR) -> done (or blocked)
Story state transitions auto-sync to the configured tracker backend.
Examples
# Initialize a new Scrum project
python3 state_machine.py init_scrum "$(pwd)"
# Read Scrum lifecycle state
python3 scrum_state_machine.py read "$(pwd)"
# Read Kanban lifecycle state
python3 kanban_state_machine.py read "$(pwd)"
# Read whichever lifecycle is active
python3 state_machine.py read "$(pwd)"
# Start Sprint 1 with two stories
python3 scrum_state_machine.py start_sprint "$(pwd)" 1 \
--goal "Ship the first booking flow" \
--stories '[{"id":"US-001","title":"Guest can create reservation"},{"id":"US-002","title":"Owner can view bookings"}]'
# Transition Scrum to Sprint Review
python3 scrum_state_machine.py transition "$(pwd)" SPRINT_REVIEW
# Move a story through the shared pipeline
python3 story_pipeline.py transition "$(pwd)" US-001 testing
# Pull a Kanban ticket and evaluate DoD
python3 kanban_state_machine.py pull_ticket "$(pwd)" TICKET-042 --title "Fix checkout timeout"
python3 kanban_state_machine.py evaluate_dod "$(pwd)" TICKET-042
# Transition a completed Scrum project to Kanban
python3 scrum_state_machine.py transition_to_kanban "$(pwd)"
Admin CLI (./synaptory)
All operator tasks are accessed via the ./synaptory script at the repo root (a thin shim onto plugin/synaptory).
./synaptory <command> [arguments]
The plugin no longer ships encrypted blobs (per ADR-016) and there are no per-user access tokens. Identity is Entra OAuth via the user-installed synaptory CLI; project membership is managed in the control plane.
Build & release
| Command | Description |
|---|---|
| `./synaptory build [--minor\ | --major\ |
./synaptory build cli [os/arch ...] | Cross-compile the Go CLI into cli/dist/ for distribution. Output is not yet published — chain release cli to ship. |
./synaptory release cli [--publish] | Stage CLI binaries + sha256sums.txt + install scripts into web/dist/cli/. With --publish, also rsync to SYNAPTORY_PROD_HOST so /cli/* serves the new version. |
| `./synaptory version [patch\ | minor\ |
Required environment variables for build / release:
SYNAPTORY_CP_URL— control-plane URL stamped into the plugin and CLI binary at build time.SYNAPTORY_CP_ENTRA_TENANT_ID,SYNAPTORY_CP_ENTRA_CLIENT_ID— stamped sosynaptory loginworks with no local setup.SYNAPTORY_PROD_HOST=user@host— required for--publish.
Identity & projects (control-plane)
| Command | Description |
|---|---|
./synaptory api projects create <slug> | Provision a project on the control plane. |
./synaptory api projects add-member <slug> <upn> | Grant a user access to the project. |
./synaptory api projects revoke <slug> <upn> | Revoke a user's access. |
There is no separate "issue access token" step — staff sign in once with synaptory login and project access is checked per-request against project_members.
Local stack & dev
| Command | Description |
|---|---|
| `./synaptory api up\ | down\ |
./synaptory dev plugin | Launch claude --plugin-dir plugin for live source-tree testing. |
./synaptory dev cli | Run the CLI against a local control-plane (go run ./cmd/synaptory). |
| `./synaptory cli {test\ | smoke\ |
./synaptory test | Plugin syntax validation + pytest (Layer 1 + Layer 2). |
| `./synaptory test --syntax\ | --pytest` |
./synaptory e2e [--keep-stack] [--scenario test_NN_name.py] | Cross-module Layer-3 scenarios against a fresh local stack. |
./synaptory status | Show source/dist status, current version, and live-marketplace version. |
Examples
# Build and publish the plugin (test against the local marketplace first)
./synaptory build --publish-local # auto-bump patch; push to infra/git/marketplace.git
./synaptory build --minor --publish # bump minor + SSH-push to prod
# Release the standalone CLI
./synaptory release cli --publish # rsync binaries to SYNAPTORY_PROD_HOST
# Provision a new project
./synaptory api projects create taskflow-pilot
./synaptory api projects add-member taskflow-pilot alice@h3tech.io
# Local stack
./synaptory api up
./synaptory api smoke
./synaptory e2e --scenario test_03_kanban_loop.py
Mode reader CLI
The mode reader (plugin/hooks/lib/mode_reader.py) reads the engagement mode. Used internally by hooks.
python3 mode_reader.py <project_dir>
| Field | Values | Description |
|---|---|---|
mode | structured, interactive | Current engagement mode |
block_on_failure | True / False | Whether hooks block on validation failure. True for Structured, False for Interactive. |
What's next?
- Configuration Reference -- All
.synaptory.yamlsettings - Hooks Reference -- Lifecycle hooks that execute these commands
- Troubleshooting -- Common command issues and fixes
Routing Reference
Diataxis category: Reference — information-oriented, for lookup.
How the orchestrator decides which mode to dispatch. The full machine-readable source of truth is plugin/skills/synaptory/routing-rules.json — this page is its human projection.
Three-layer dispatch
Every request is classified into one of three layers:
- Scrum lifecycle modes —
Build,Sprint. Drive the full Inception → Sprint loop → Release flow. - Kanban lifecycle mode —
Kanban. Continuous ticket flow on a brownfield codebase. - Standalone modes — everything else. Single- or dual-agent scoped tasks that don't depend on a lifecycle.
Standalone modes group naturally:
- Diagnostics & setup:
Doctor,Init,Status,Help,Report. Plus the silentUpdatecheck that runs before every other mode. - Per-story assistance (Story Buddy):
Story Buddy — Requirements,Story Buddy — Implement,Story Buddy — Test,Story Buddy — Sprint Plan. - Lightweight single-agent:
Test,Review,Architect,Document,Explore,Optimize,Stabilize,Modernize,Custom. - Brownfield analysis:
Discover,Context Refresh. - Workflow utilities:
Debug,Preview,Branch Finish,Retro.
For a behavioural description of each mode see Modes. This page is for predicting routing.
Trigger signals and patterns
Each mode declares both keyword signals and regex patterns. A request matches if any signal substring appears, or if any pattern matches.
| Mode | Layer | Signals (sample) | Patterns (regex) |
|---|---|---|---|
Build | Scrum | "build a SaaS", "production grade", "from scratch", "full stack", "greenfield" | `build.*(?:saas\ |
Sprint | Scrum | "build sprint", "sprint N", "next sprint", "continue sprint", "resume sprint", "run sprint", "start sprint" | `(?:build\ |
Kanban | Kanban | "fix ticket", "work on TICKET-xxx", "pull next ticket", "maintenance mode", "kanban" | fix\s+ticket, work on\s+TICKET-\d+, pull next ticket, maintenance mode, kanban |
Test | Standalone | "write tests", "test coverage", "test this", "add tests" | `(?:write\ |
Review | Standalone | "review my code", "code review", "code quality", "check my code" | `(?:review\ |
Architect | Standalone | "design", "architecture", "API design", "data model", "tech stack", "how should I structure" | `(?:design\ |
Document | Standalone | "document", "write docs", "API docs", "README" | `(?:write\ |
Explore | Standalone | "explain", "understand", "help me think", "what should I", "I'm not sure" | explain\s+\w+, help me think, what should I, I'm not sure |
Optimize | Standalone | "performance", "slow", "optimize", "scale", "reliability" | (?:too\s+)?slow, optimize\s+\w+, `performance\s+(?:issue\ |
Discover | Standalone | "understand this codebase", "map the system", "reverse engineer", "what does this code do", "map dependencies" | reverse.?engineer, `map.*(?:system\ |
Stabilize | Standalone | "add safety net", "characterization tests", "before refactoring", "establish baseline", "coverage ratchet" | characterization tests?, before refactor, safety net, coverage ratchet |
Modernize | Standalone | "modernize", "migrate", "upgrade architecture", "strangler fig", "migration plan", "rewrite plan" | modernize, migration plan, strangler fig, rewrite plan |
Debug | Standalone | "debug", "fix this bug", "not working", "broken", "error", "crash", "failing", "investigate", "root cause" | `(?:fix\ |
Preview | Standalone | "preview", "run it", "start server", "launch", "see it running", "dev server" | preview, run it, start.*server, `launch.*(?:app\ |
Retro | Standalone | "retro", "retrospective", "what did we ship", "team metrics", "weekly summary", "sprint review", "shipping velocity" | retro(?:spective)?, what did we ship, team metrics, shipping velocity |
Branch Finish | Standalone | "finish this branch", "merge", "create PR", "done with this branch", "ship this branch", "ready to merge" | finish.*branch, create.*pr, ready to merge, ship.*branch |
Doctor | Standalone | "doctor", "diagnose", "check config", "validate config", "is this correctly configured", "synaptory doctor" | \bdoctor\b, \bdiagnose\b, `(?:run\ |
Init | Standalone | "initialize", "configure project", "set up synaptory", "reconfigure", "generate config" | `(?:initialize\ |
Status | Standalone | "status", "progress", "dashboard", "where are we", "show pipeline", "check progress" | `(?:show\ |
Help | Standalone | "help", "commands", "what can you do", "reference", "how does synaptory work" | `(?:help\ |
Report | Standalone | "report a bug", "report an issue", "synaptory bug", "plugin issue" | `report.*(?:bug\ |
Context Refresh | Standalone | "update context", "refresh context", "re-analyze codebase", "update codebase knowledge" | `(?:update\ |
Story Buddy — Requirements | Standalone | "analyze [story]", "refine requirements", "AC review", "PM help with [story]", "BA help with [story]" | `analyze\s+(?:[A-Z]+-\d+\ |
Story Buddy — Implement | Standalone | "implement [US-xxx]", "build [story ID]", "code [story]" | `(?:implement\ |
Story Buddy — Test | Standalone | "test cases for [US-xxx]", "test [story]", "automate [story]", "QA help with [story]" | `(?:test cases?\ |
Story Buddy — Sprint Plan | Standalone | "sprint planning", "help plan sprint", "prioritize backlog", "backlog grooming" | sprint planning, help.*plan.*sprint, prioritize.*backlog, backlog grooming |
Custom | Standalone | (catch-all when no other mode matches) | — |
Update is not a routing-rules entry — it runs silently before any mode and prompts only if a newer plugin version is available. See plugin/skills/synaptory/modes/update.md.
Tiebreakers
When multiple modes match, the orchestrator applies these rules in order. They are reproduced verbatim from routing-rules.json so they stay in sync with the routing engine.
| Conflict | Rule | Why |
|---|---|---|
| review vs verify | Review if "my code / this code". Verify if "before launch / audit / harden / production ready" | Verify implies multi-agent parallel audit; Review is single-agent read-only |
| test vs debug | Debug if error/failure/crash/not working is described. Test if the code works and coverage is the goal | Debug = active failure; Test = proactive quality |
| build vs debug | Debug if there is a specific error description. Build if it is a new behaviour request | Debug requires root-cause analysis; Build is additive |
| multiple modes match | Pick the most specific: Debug > Story Buddy, Release > Code Review, Sprint > Build | Specificity beats generality |
| reliability vs optimize | Reliability if SLO, error budget, chaos, runbook, incident, or on-call is mentioned. Optimize if performance or scale is the goal without operational framing | Reliability = operational engineering; Optimize = code/infra performance tuning |
| implement + story ID vs Build | Story Buddy — Implement if a story ID pattern ([A-Z]+-\d+ or US-\d+) is present. Build (Scrum lifecycle) if no story ID | Story ID = story already in tracker. No story ID = new project requiring Inception |
| write tests + story ID vs Test | Story Buddy — Test if a story ID is present. Test (standalone) if no story ID | Story ID enables AC-to-test traceability; standalone Test is general coverage work |
| story ID anywhere in request | Story Buddy mode (role inferred from request context). Story ID overrides Build/Test/Review | Presence of a story ID signals per-story assistance intent, not a new feature request |
| doctor vs init | Doctor if "check", "validate", "diagnose", "is it configured correctly", or "doctor" is mentioned. Init if "initialize", "set up", or "generate config" is the goal | Doctor is read-only diagnostic; Init generates/overwrites configuration |
Forcing a specific mode
Two ways to force routing:
- Use the trigger phrase explicitly. "doctor" →
Doctor. "initialize" →Init. "modernize the architecture" →Modernize. The signals are loose enough that natural English usually lands the right mode. - Address the orchestrator directly.
/synaptory run doctoror/synaptory start sprint 3bypasses ambiguity by pinning the mode in the request.
If a mode keeps misclassifying, run Doctor first — .synaptory.yaml mismatches account for most surprising routes.
What's next
Rules Reference
Diataxis category: Reference — information-oriented, for lookup.
The plugin ships ten behavioural rules in plugin/rules/. They are auto-injected at every SessionStart by synaptory-load-rules.sh (delivered watermarked from the control plane like all IP-sensitive bodies — see The Synaptory Platform). They define the structural patterns and protocols every agent must follow.
Some rules are scoped via a paths: frontmatter list; those fire only when the agent touches matching files.
Rules at a glance
| Rule | Scope | Summary |
|---|---|---|
synaptory-boundary-safety | always | Six structural patterns that cause silent failures at system boundaries (framework abstractions vs. platform primitives). |
synaptory-conflict-resolution | always | Authority hierarchy when two agents' outputs overlap. Single-owner-per-artifact, contributors flag but don't override. |
synaptory-flaky-tests | tests/**, **/__tests__/**, .github/workflows/** | Defines and bans flaky tests. ≥1 failure in 20 runs is a pipeline correctness issue, not a minor inconvenience. |
synaptory-freshness | .synaptory/** | Volatility tiers for verifying external facts before using them — model IDs, pricing, security advisories, framework breaking changes. |
synaptory-guard | .synaptory/** | Fallback when the SessionStart hook is not active. Detects an existing .synaptory/ workspace and offers options. |
synaptory-receipt-protocol | .synaptory/** | Receipt schema and the proof-of-completion contract. Every completing agent MUST write .synaptory/.orchestrator/receipts/<story>-<role>.json. |
synaptory-secrets-scan | .env*, **/*.{key,pem,p12,pfx}, secrets/**, infra/**, terraform/** | Forbids secrets in tracked files. Triggers on env files, key material, infra configs, and CI workflows. |
synaptory-ux | always | UX interaction rules. Always use AskUserQuestion with explicit options; "Chat about this" always last; recommended option first. |
synaptory-visual-identity | always | Visual language for agent output. Information density over decoration; earned elevation; concrete over vague. |
synaptory-welcome | first-message-after-install | Onboarding rule for new users. Fires once when no .synaptory/ exists and the user makes a development request. |
Rule detail
synaptory-boundary-safety
Six framework-agnostic patterns that produce silent failures when crossing system boundaries. Pattern 1 — framework abstractions break at system boundaries — is the canonical example: Next.js <Link> to an API route, React Router navigate() to an external OAuth URL. Before using a framework abstraction, agents must verify the target stays within the framework's domain; otherwise fall back to the platform primitive (raw <a href>, raw fetch, raw redirect).
synaptory-conflict-resolution
The authority hierarchy. Each artifact type has a single owning skill; contributors may flag issues but never overwrite. Examples: BRD → project-owner. ADRs and API contracts → solution-architect. Implementation code → software-engineer (reviewers produce findings only). Tests → quality-engineer. Security findings → compliance-engineer (Code Reviewer does NOT perform OWASP review). SLOs and monitoring → platform-engineer.
synaptory-flaky-tests
Path-scoped to test and CI files. Defines flaky as ≥1 failure in 20 runs without code change (≥5% failure rate). Establishes that flaky tests are a pipeline correctness issue: they erode trust, mask real regressions, and make synaptory-verify-receipt.sh re-runs unreliable.
synaptory-freshness
Path-scoped to .synaptory/**. Defines volatility tiers for things you should never trust training data on:
- Tier 1 (days to weeks): LLM model IDs and capabilities, API pricing, security advisories, compliance requirements, framework breaking changes — MUST WebSearch before use.
- Lower tiers cover slower-changing facts.
The Freshness Protocol is what catches "package version X has been deprecated" mistakes before code lands.
synaptory-guard
Path-scoped to .synaptory/**. A fallback for environments where the SessionStart hook didn't fire. When .synaptory/ is detected and no pipeline session is active, presents the user with the choice to use the pipeline or work directly. Prevents accidental ad-hoc edits to a repo that has an active synaptory workspace.
synaptory-receipt-protocol
Path-scoped to .synaptory/**. Defines the receipt JSON schema every agent writes on completion (task, agent, backend, model, artifacts, verification_commands, plus optional story_dod, confidence, fallback_from). Receipts are the authoritative record of what was built; they're what synaptory-verify-receipt.sh validates and re-runs.
synaptory-secrets-scan
Path-scoped to env files, key material, secrets directories, CI workflows, docker-compose, and infra/**/terraform/**. Fires when an agent touches any of those paths and forbids commits that include secret-shaped content. Aligned with the project-wide pre-commit gitleaks hook.
synaptory-ux
Always-on. Rules for how agents talk to the user:
- Every decision point uses
AskUserQuestionwith explicit options — never open-ended "what do you think?" - Every
AskUserQuestionhas Chat about this as the last option (escape hatch). - First option is the recommended default with
(Recommended)suffix; the user should accept it ~80% of the time.
synaptory-visual-identity
Always-on. Defines synaptory's visual language for chat output:
- Information is the aesthetic — never print a line that doesn't carry information.
- Earned elevation — heavy formatting is reserved for genuinely important moments.
- State must be visible — the user should always know where they are, what's happening now, and what's next.
- Concrete over vague — never "analysis complete"; always "analyzed 247 files across 3 services, 12 endpoints."
Also defines the icon vocabulary used across agent output.
synaptory-welcome
Fires when all of these are true: the plugin is loaded, no .synaptory/ directory exists, the user's first message is development-related, and the welcome hasn't been shown this session. Walks new users through initialize my project and the recommended starting prompts. Suppressed once dismissed for the session.
Behavioural protocols (separate from rules)
In addition to rules, every SubagentStart injects ~26 shared protocols (receipt-protocol, input-validation, tool-efficiency, freshness-protocol, iron-laws, verification-discipline, socratic-gate, anti-safe-harbor, script-output-handling, clean-code-self-check, boundary-safety, conflict-resolution, coverage-ratchet, finding-memory, local-deploy-verification, open-decision-registry, scope-challenge, source-attribution, subagent-isolation, tdd-discipline, ux-protocol, visual-identity, code-review-response, story-pipeline, backend-dispatch, sa-triggers). Protocols live in plugin/skills/_shared/protocols/ and are delivered via the same watermarked-fetch path as rules. See Hooks for the full list.
What's next
- Hooks — when each rule and protocol is loaded.
- The Synaptory Platform — how watermarked delivery works.
- Enforcement — how the Receipt Protocol is enforced at
SubagentStop.
Hooks Reference
Diataxis category: Reference -- information-oriented, for lookup.
synaptory uses Claude Code's native Hooks system for lifecycle automation. Hooks run automatically at defined lifecycle events -- you do not invoke them manually. Hook definitions live in plugin/hooks/hooks.json.
Hook events in execution order
Hooks fire at six lifecycle points in this order:
SessionStart -> SubagentStart -> SubagentStop -> PreCompact -> Stop -> SessionEnd
Complete hooks table
| Event | Script | Timeout | Async | Description |
|---|---|---|---|---|
SessionStart | synaptory-access-token-check.sh | 20s | no | Validate session, resolve control-plane URL, and authenticate CLI. |
SessionStart | synaptory-skills-fetch.sh | 15s | no | Sync skill manifest and pull missing/stale skills into local cache. |
SessionStart | synaptory-config-fetch.sh | 10s | no | Pull policy from control-plane; update local cache. Non-fatal on network failure. |
SessionStart | synaptory-load-rules.sh | 10s | no | Inject behavioral rules into session. |
SessionStart | synaptory-session-start.sh | 10s | no | Detect workspace and inject lifecycle state, story pipeline, context packages. |
SessionStart | session-guard.sh | 10s | no | Detect existing project and offer options. |
SubagentStart | synaptory-inject-protocols.sh | 5s | no | Inject shared behavioral protocols into subagent. |
SubagentStop | synaptory-verify-receipt.sh | 30s | no | Validate agent receipt and re-run verification commands. |
PreCompact | synaptory-reanchor.sh | 10s | no | Re-inject critical context before compaction. |
Stop | synaptory-pipeline-snapshot.sh | 10s | yes | Save lifecycle state snapshot for cross-session resume. |
Stop | synaptory-access-token-cleanup.sh | 5s | yes | Async cleanup of in-memory token material at end of turn. |
SessionEnd | synaptory-session-end.sh | 5s | yes | Async cleanup of temporary resources. |
SessionEnd | synaptory-access-token-cleanup.sh | 5s | yes | Final async cleanup of cached token material on session close. |
| user-invocable | synaptory-doctor.sh | -- | -- | Configuration diagnostic. Not bound to a lifecycle event — invoked by the Doctor mode and surfaced from SessionStart errors. Delegates to hooks/lib/doctor.py. |
| internal | synaptory-decrypt-skill.sh | -- | -- | Helper invoked by other hooks when a cached skill body needs to be decoded before use. Not user-invocable. |
| internal | _resolve-cli.sh | -- | -- | Locates the synaptory CLI binary on $PATH. Sourced by every other hook. |
| internal | _plugin-env.sh | -- | -- | Bootstraps shared environment variables (CLAUDE_PLUGIN_ROOT, log paths) for every other hook. Sourced, not executed. |
The SessionStart matcher is startup|resume|clear|compact, meaning these hooks fire on session start, on resume, after /clear, and after context compaction.
Hook details
synaptory-access-token-check.sh (SessionStart)
Resolves the control-plane URL from the bundled plugin/hooks/lib/cp-url file (stamped at build time) and exports SYNAPTORY_CONTROL_PLANE_URL for downstream hooks. In dev environments (SYNAPTORY_CP_ENV=dev), falls back to the SYNAPTORY_CONTROL_PLANE_URL env var if set. Hard-fails with a clear message if no URL is available.
- Mode-aware behavior: None. Always runs.
- Blocks vs warns: Exits 1 when the control-plane URL is missing or placeholder (build not stamped).
synaptory-skills-fetch.sh (SessionStart)
Invokes synaptory skills sync to fetch the skill manifest from the control-plane and pull any missing or stale skill bodies into the local cache. Skills are served live from the cache — never stored as plaintext files on disk.
- Mode-aware behavior: None. Always runs.
- Blocks vs warns: Non-fatal on network failure; logs a warning and continues.
synaptory-config-fetch.sh (SessionStart)
Invokes synaptory config fetch --if-stale to refresh the local policy cache (~/.synaptory/.cache/policy.json). Policy data controls receipt schema validation, allowed backends, and roster.
- Mode-aware behavior: None. Always runs.
- Blocks vs warns: Non-fatal on network failure; exits 0 always.
synaptory-load-rules.sh (SessionStart)
Injects behavioral rules (UX, guard, conflict resolution, etc.) into the session context. Rules live in plugin/rules/ and are loaded because plugins do not natively support rules/ directories.
- Mode-aware behavior: None. Rules are always loaded.
- Blocks vs warns: Never blocks. Adds context only.
synaptory-session-start.sh (SessionStart)
Detects the .synaptory/ workspace directory and injects:
- Lifecycle state -- current ceremony position (Scrum or Kanban)
- Story pipeline state -- per-story sub-states
- Sprint state -- sprint number, Sprint Goal, completed sprints
- Engagement mode -- structured or interactive
- Context packages -- brownfield analysis artifacts (if present)
Eliminates the need to check status manually after opening a project.
- Mode-aware behavior: None. Always runs if workspace exists.
- Blocks vs warns: Never blocks. Adds context only.
session-guard.sh (SessionStart)
Detects an existing project (presence of .synaptory/ directory) and offers options: use /synaptory (recommended), work directly without the plugin, or chat about it.
- Mode-aware behavior: None. Always runs if workspace exists.
- Blocks vs warns: Never blocks. Presents options.
synaptory-inject-protocols.sh (SubagentStart)
Injects all shared behavioral protocols into every subagent context automatically. Reads protocol content from the local skill cache via the CLI.
Injected protocols:
| Protocol | Domain |
|---|---|
receipt-protocol | Receipt writing and verification commands |
input-validation | Input sanitization patterns |
tool-efficiency | Tool call optimization |
freshness-protocol | External dependency version verification |
iron-laws | Inviolable delivery rules |
verification-discipline | Verification command requirements |
socratic-gate | Gate interview patterns |
anti-safe-harbor | Prevents hedging language in deliverables |
script-output-handling | Script execution and output parsing |
clean-code-self-check | Self-review before completion |
boundary-safety | Agent authority boundaries |
conflict-resolution | Cross-agent conflict handling |
coverage-ratchet | Coverage cannot decrease |
finding-memory | Persistent finding tracking |
local-deploy-verification | Local server health check requirements |
open-decision-registry | Decision tracking and justification |
scope-challenge | Scope creep prevention |
source-attribution | Source citation requirements |
subagent-isolation | Subagent workspace isolation |
tdd-discipline | Test-driven development patterns |
ux-protocol | User experience standards |
visual-identity | Progress output formatting |
code-review-response | Code review finding response format |
story-pipeline | Story state machine protocol |
backend-dispatch | Backend dispatch and routing protocol |
sa-triggers | Solution Architect auto-trigger signals |
- Mode-aware behavior: None. All protocols are always injected.
- Blocks vs warns: Never blocks. Adds context only.
synaptory-verify-receipt.sh (SubagentStop)
Mode-aware receipt enforcement with a 30-second timeout. After each subagent completes, validates the story-scoped receipt JSON.
Validation checks:
- Receipt file exists in
.synaptory/.orchestrator/receipts/ - Required fields present (
story_id,role,backend,model,artifacts,verification_commands,metrics,completed_at) - Listed artifacts exist on disk
- Verification phrases are not banned (rejects generic claims without evidence)
verification_commandsare re-run to confirm they still pass- Optional enrichment fields such as
story_dod,confidence, andfallback_fromare validated when present
- Mode-aware behavior:
- Structured: Missing receipt, invalid receipt, or failing verification commands cause
exit 1-- execution BLOCKED. - Interactive: Same checks run, but failures are surfaced as warnings. Execution proceeds (
exit 0). - Blocks vs warns: Structured blocks. Interactive warns.
synaptory-reanchor.sh (PreCompact)
Before Claude Code compacts the context window, re-injects BRD, ADRs, receipts, context packages, and other critical artifacts. Prevents context degradation during long runs.
- Mode-aware behavior: None. Always runs before compaction.
- Blocks vs warns: Never blocks. Adds context only.
synaptory-pipeline-snapshot.sh (Stop)
Writes a lifecycle state snapshot to .synaptory/.orchestrator/last-session.md. Captures current ceremony, completed stories, story pipeline status, sprint metrics, and engagement mode.
- Mode-aware behavior: None. Always runs on stop.
- Blocks vs warns: Never blocks. Runs asynchronously.
synaptory-session-end.sh (SessionEnd)
Async cleanup of temporary resources created during the session.
- Mode-aware behavior: None. Always runs.
- Blocks vs warns: Never blocks. Runs asynchronously.
synaptory-access-token-cleanup.sh (Stop, SessionEnd)
Asynchronous cleanup of in-memory token material at end of turn (Stop) and on session close (SessionEnd). Pairs with synaptory-access-token-check.sh at SessionStart. Never blocks.
- Mode-aware behavior: None.
- Blocks vs warns: Never blocks. Runs asynchronously.
synaptory-doctor.sh (user-invocable)
User-invocable self-service diagnostic. Prints a plain-text report covering token source and format, signature status, expiry, backend mode, and session directory. The Doctor mode dispatches here, and SessionStart errors funnel through it automatically so the user sees a remediation report instead of a raw stack trace. Delegates to ${CLAUDE_PLUGIN_ROOT}/hooks/lib/doctor.py.
- Mode-aware behavior: Always read-only. Never modifies files.
- Blocks vs warns: Surfaces findings; never blocks the pipeline by itself.
See Troubleshooting → Run Doctor first for typical recipes.
synaptory-decrypt-skill.sh (internal helper)
Helper used by other hooks when a cached skill body needs to be decoded before use. Not user-invocable; never registered against a lifecycle event directly.
_resolve-cli.sh (internal helper)
Locates the synaptory CLI binary on $PATH and exports it for downstream hooks. Sourced by every other hook script. Hard-fails with a clear message if the CLI is not installed (see Install the CLI).
The synaptory-guard rule fallback
The synaptory-guard rule (plugin/rules/synaptory-guard.md) is a fallback for environments where Hooks are not yet supported. It fires when a .synaptory/ directory is detected and offers options.
Hook lib modules
All hook library modules live in plugin/hooks/lib/.
| Module | Language | Description |
|---|---|---|
state_machine.py | Python | Thin dispatcher for lifecycle bootstrap and state reads. Initializes Scrum or Kanban and reads the current pipeline state. |
scrum_state_machine.py | Python | Scrum lifecycle state machine. Enforces ceremony transitions: INCEPTION -> SPRINTPLANNING -> SPRINTEXECUTION -> SPRINTREVIEW -> SPRINTRETRO -> SPRINT_CLOSE -> (loop) -> RELEASE -> COMPLETE. |
kanban_state_machine.py | Python | Kanban lifecycle state machine. Enforces: DISCOVER -> READY -> EXECUTION -> REVIEW -> (loop) -> RELEASE -> COMPLETE. |
story_pipeline.py | Python | Story-level sub-state management. Tracks queued -> in_progress -> testing -> reviewing -> done/blocked. Evaluates per-story DoD. Syncs to tracker backend. |
mode_reader.py | Python | Reads engagement mode (structured, interactive) from settings. Provides should_block_on_failure() helper. |
receipt_validator.py | Python | Validates receipt JSON: schema compliance, required fields, artifact existence, banned phrase detection. Schema loaded from policy cache (~/.synaptory/.cache/policy.json). |
verification_runner.py | Python | Re-runs verification_commands from receipts and reports pass/fail. |
What's next?
- Configuration Reference -- All
.synaptory.yamlsettings - Commands Reference -- CLI tools that hooks invoke
- Enforcement -- How hooks enforce quality and safety
URLs Reference
Diataxis category: Reference — information-oriented.
Every public URL on synaptory.h3t.co, what it does, and which container or static path serves it.
The host is fronted by Caddy; see infra/caddy/Caddyfile for the source of truth.
Per ADR-019 the /console/* and /portal/* URL trees are gone — every page in the Control Plane lives at root URLs.
User-facing URLs
| URL | Purpose | Audience |
|---|---|---|
https://synaptory.h3t.co/ | Role-aware redirect (admin → /overview, else → /home) | Any signed-in user |
https://synaptory.h3t.co/get-started | Public landing — install instructions, links into the user guide | Prospective users |
https://synaptory.h3t.co/home, /overview, /projects/*, /audit, /sessions, /skills, /cost, /quality, /reliability, /people, /policy, /system, /grafana, /access-review, /settings, /profile | Control Plane pages (Next.js); each role-gated server-side | synaptory-users (varying scope by role) |
https://synaptory.h3t.co/auth/login | Sign-in entry point | Anyone (redirected to Entra) |
https://synaptory.h3t.co/auth/callback | OAuth callback for Web flow | Browser (round-trip from Entra) |
https://synaptory.h3t.co/docs/user-guide.html | This guide, single-file HTML | Anyone signed in (gated by Caddy if needed) |
The legacy /console/* and /portal/* URL trees return 404. There are no redirects — bookmarks pointing at the v2.5 surfaces must be updated.
Plugin distribution
| URL | Purpose |
|---|---|
https://synaptory.h3t.co/marketplace.git | Smart-HTTP git endpoint. The actual transport for /plugin marketplace add. |
https://synaptory.h3t.co/marketplace.git/info/refs | Git protocol probe. Returned by git-http-backend |
https://synaptory.h3t.co/marketplace | Discoverability landing page. Not the marketplace transport. |
/plugin marketplace add https://synaptory.h3t.co/marketplace.git is the supported install command.
CLI distribution
| URL | Purpose |
|---|---|
https://synaptory.h3t.co/cli/install.sh | macOS / Linux install script |
https://synaptory.h3t.co/cli/install.ps1 | Windows install script |
https://synaptory.h3t.co/cli/latest.json | Current CLI version + per-platform binary URLs |
https://synaptory.h3t.co/cli/<version>/<binary> | Versioned binaries (e.g. synaptory_darwin_arm64) |
https://synaptory.h3t.co/cli/<version>/sha256sums.txt | SHA-256 manifest for offline verification |
https://synaptory.h3t.co/downloads | Human-readable download index |
The install scripts resolve latest.json first, then download the binary. Override with SYNAPTORY_CLI_BASE_URL for staging.
API endpoints (/v1/*)
The complete authoritative list is in api/README.md. Highlights:
| Pattern | Audience | Purpose |
|---|---|---|
/v1/auth/* | Anyone | OAuth exchange, local-auth fallback |
/v1/projects/* | Any signed-in user | Project list (caller's by default; ?all=true for global admins). Project detail / members / archive (membership-gated) |
/v1/projects/{ref}/access-requests* | Any signed-in user | Self-service access requests; project admins approve/deny |
/v1/access-requests/mine | Any signed-in user | Caller's outstanding access requests across projects |
/v1/analytics/* | Any signed-in user (scope-aware) | Analytics with server-side filter by project_members. Anti-leak 404 on ?project=<slug> the caller can't see |
/v1/sessions/* | Any signed-in user (scope-aware) | List, detail, revoke. Self-revoke always allowed |
/v1/admin/* | synaptory-admins only | Cross-tenant operations the role gating doesn't cover: system/*, projects/bulk-archive, config/{v}/export |
/v1/skills/manifest | Any signed-in user | Skill list (no bodies) |
/v1/skills/<name:path> | Any signed-in user | Watermarked body fetch |
/v1/ingest | CLI | Telemetry batch ingest |
/v1/config/* | CLI | Signed config delivery |
/v1/healthz, /v1/readyz | Anyone | Liveness / readiness |
/v1/public-key | Anyone | Ed25519 public key for offline signature verification |
The /v1/me/* namespace was retired by ADR-019. Identity comes from the iron-session cookie's claims; member-scoped reads go through the scope-aware /v1/{projects,sessions,analytics} endpoints.
Operator URLs
| URL | Purpose |
|---|---|
https://synaptory.h3t.co/grafana | Grafana embed (Caddy reverse-proxy, admin-only) |
https://synaptory.h3t.co/system | Probes + versions + last backup |
https://synaptory.h3t.co/audit | Audit log (scope-aware: admins see everything; project admins see their projects) |
Direct Grafana (without the iframe) is also available via SSH tunnel — see infra/README.md.
Local dev URLs
When you run ./synaptory api up, the same surface appears at localhost:
| URL | Equivalent |
|---|---|
http://localhost:8080/ | Role-aware Control Plane root |
http://localhost:8080/<page> | Same page as on prod (e.g. /overview, /projects, /sessions) |
http://localhost:8080/marketplace.git | The local bare repo for --publish-local testing |
http://localhost:8080/cli/* | The local web/dist/cli/ |
http://localhost:8080/docs/user-guide.html | The local web/dist/docs/ |
http://localhost:8080/v1/* | FastAPI |
http://localhost:8080/dev/mint | Fixture-IDP token mint (local only) |
http://localhost:3099 is the Next.js dev server when running npm run dev directly without Caddy.
Authentication Flows
Diataxis category: Reference — information-oriented.
Three flows mint a SYNAPTORY1 token. Each has a different shape; all produce the same token format, indistinguishable downstream.
For the conceptual model and per-request enforcement, see Identity and access.
Flow 1: Web (Control Plane browser sign-in)
Used by every page in the Control Plane (synaptory.h3t.co/*) — single unified app per ADR-019.
sequenceDiagram
participant U as User (browser)
participant W as Next.js (web)
participant E as Entra
participant A as FastAPI (api)
U->>W: GET /home (no cookie)
W-->>U: 302 → /auth/login
U->>W: GET /auth/login
W-->>U: 302 → Entra authorize URL (with client_id + redirect_uri)
U->>E: GET /authorize
E-->>U: Sign-in UI; consent
U->>E: POST credentials
E-->>U: 302 → /auth/callback?code=...
U->>W: GET /auth/callback?code=...
W->>E: POST /token (code + client_secret)
E-->>W: id_token (JWT)
W->>A: POST /v1/auth/exchange (id_token)
A->>A: Verify JWKS; extract upn, grp; mint SYNAPTORY1
A-->>W: SYNAPTORY1 token
W-->>U: Set-Cookie iron-session; 302 → role-aware home
Key facts:
- The
client_secretis held by thewebcontainer only — never exposed to the browser. redirect_uriregistered as a Web platform on the Entra app (not Mobile/desktop).- The browser carries an iron-session cookie; the SYNAPTORY1 token is held server-side by Next.js.
- The role-aware redirect at the end inspects
grp: admins →/overview, others →/home.
Flow 2: CLI (PKCE)
Used by: synaptory login (default).
sequenceDiagram
participant CLI as synaptory CLI
participant Browser
participant E as Entra
participant A as FastAPI (api)
CLI->>CLI: Generate code_verifier + code_challenge
CLI->>CLI: Bind random loopback port (e.g. 49321)
CLI->>Browser: Open https://login.microsoftonline.com/.../authorize?...&redirect_uri=http://127.0.0.1:49321/auth/callback&code_challenge=...
Browser->>E: GET /authorize
E-->>Browser: Sign-in UI
Browser->>E: POST credentials
E-->>Browser: 302 → http://127.0.0.1:49321/auth/callback?code=...
Browser->>CLI: GET /auth/callback?code=... (loopback HTTP)
CLI->>E: POST /token (code + code_verifier; no client_secret)
E-->>CLI: id_token
CLI->>A: POST /v1/auth/exchange (id_token)
A-->>CLI: SYNAPTORY1 token
CLI->>CLI: Store token in OS keychain
Key facts:
- No
client_secret. PKCE is a public-client flow;code_verifiersubstitutes for the secret. - The loopback port is bound at runtime; Microsoft's loopback exception means
http://127.0.0.1(no port) is registered as the redirect URI on the Entra app's Mobile/desktop platform, and any port satisfies the match. - The CLI starts a local HTTP server on the bound port for exactly long enough to receive the callback, then shuts it down.
- Same Entra app + same exchange endpoint as Flow 1. Only the front-end shape differs.
For headless servers: synaptory login --device uses Entra's device-code flow instead. The user opens a URL on a separate device, enters a short code, and the CLI polls until success.
Flow 3: Local-auth fallback
Used by: dev fixtures and on-prem deployments where Entra isn't available.
sequenceDiagram
participant U as User
participant W as Next.js (web) [or CLI]
participant A as FastAPI (api)
U->>W: POST /auth/login (UPN + password)
W->>A: POST /v1/auth/local (UPN + password)
A->>A: Compare against SYNAPTORY_CP_LOCAL_*_PASSWORD env vars
A->>A: Mint SYNAPTORY1 with grp from the matched slot
A-->>W: SYNAPTORY1 token
W-->>U: Set-Cookie iron-session
Key facts:
SYNAPTORY_CP_LOCAL_AUTH_ENABLED=trueon the API;SYNAPTORY_LOCAL_AUTH_ENABLED=trueon the web container. Two different env-var prefixes because they live in different containers.- The admin slot grants
[synaptory-users, synaptory-admins]; the user slot grants[synaptory-users]only. - Tokens minted via local-auth are indistinguishable from Entra-minted tokens once issued — the server treats them identically.
- Never enable in deployments expected to use Entra.
The CLI also supports local-auth via synaptory login --local. Same flow, headless.
SYNAPTORY1 token format
SYNAPTORY1.<base64url(payload_json)>.<base64url(ed25519_sig)>
Payload:
| Field | Type | Meaning |
|---|---|---|
sid | string | Server-side session id (used for revoke) |
upn | string | Entra UPN |
grp | string[] | Entra group names; e.g. ["synaptory-users", "synaptory-admins"] |
iat | int | Issued-at (Unix seconds) |
exp | int | Expiry (typically iat + 86400) |
There is no prj claim. Project access is per-request, server-side, against project_members.
The signing key is Ed25519 — file-backed in dev (settings.signing_key_path), Azure Key Vault in prod (kty OKP, curve Ed25519). Public key at GET /v1/public-key.
Refresh and revoke
- Tokens expire (~24h). The CLI silently refreshes via
POST /v1/auth/refreshif possible. - Sessions are revocable from
/sessions(caller's own) or/sessions(any). Revoke flipsrevoked_aton the session row; the next API call returns 401, and the CLI surfaces a re-login prompt. - "Sign out everywhere" hits
POST /v1/me/sessions/revoke-alland revokes every active session for the caller's UPN.
What's next
- Identity and access — the conceptual model.
- Permissions reference — what each token grants.
- URLs reference — every endpoint and static path.
Permissions Reference
Diataxis category: Reference — information-oriented.
Two axes determine what you can do: your Entra group membership (synaptory-users / synaptory-admins) and your project-level role on each project (member / admin). This page enumerates every cell in that grid.
For the conceptual model and where checks happen, see Identity and access.
Entra group → platform-level capabilities
| Capability | synaptory-users | synaptory-admins |
|---|---|---|
| Sign in via Entra | ✓ | ✓ |
| Mint a SYNAPTORY1 token | ✓ | ✓ |
Reach Control Plane workspace pages (/home, /projects, /sessions, /audit, /activity, /skills, /profile) | ✓ | ✓ |
Reach admin sidebar entries (/overview, /access-review, /policy, /settings, /system, /grafana/*) | ✗ | ✓ |
Read scope-aware endpoints (/v1/analytics/*, /v1/sessions, /v1/projects) | ✓ (server-side scope clamp) | ✓ |
Read /v1/skills/manifest | ✓ | ✓ |
| Fetch watermarked skill bodies | ✓ | ✓ |
Read /v1/admin/* | ✗ | ✓ |
Provision a new project (./synaptory api projects create) | ✗ | ✓ (operator path) |
| Revoke any user's session | ✗ | ✓ |
| View any user's receipts | ✗ | ✓ |
| Read project membership for projects you're not on | ✗ | ✓ |
synaptory-admins is a superset — Entra grants both groups when you're an admin, and the API treats admins as transitively having users.
Project role → project-level capabilities
These are checked per project, on top of group permissions, by check_project_membership.
| Capability | Non-member | member | admin (project) |
|---|---|---|---|
See the project on /projects | ✗ | ✓ | ✓ |
Read /v1/projects/<slug> | ✗ (404) | ✓ | ✓ |
Read /projects/<slug> overview | ✗ (404) | ✓ | ✓ |
Run /synaptory against the project's source tree | ✗ (CLI sees 404) | ✓ | ✓ |
See receipts for this project on /audit | (not shown) | ✓ (own receipts only) | ✓ (own receipts only) |
| Invite a member | ✗ | ✗ | ✓ |
| Revoke a member | ✗ | ✗ | ✓ |
| Promote a member to admin | ✗ | ✗ | ✓ |
| Modify project settings | ✗ | ✗ | ✓ |
Important: synaptory-admins does not automatically get admin on every project. A global admin who wants to invite a member to a project they aren't on goes through the project's Members tab (allowed by the /v1/admin/* capability above) — not the project-admin self-serve path.
What synaptory-admins can do that project admin can't
Some operations are platform-wide and require the Entra group, not project role:
- Create a new project (
./synaptory api projects create <slug>— currently CLI-only). - Archive / unarchive a project.
- Read
/auditacross all projects. - Read
/costand other analytics across all projects. - Read
/v1/system/health. - Modify the signed config that the CLI fetches.
- Revoke another user's session (members can revoke only their own; admins can revoke anyone's via
/sessions).
What no one can do
Some properties are out of band — not granted by any role.
- Read encrypted skill bodies at rest. They're envelope-encrypted with a KEK in Azure Key Vault. Even DB access doesn't help — you'd also need Key Vault access plus the deterministic UPN-watermark would still trace any leak.
- Modify the immutable parts of receipts. Receipts are append-only; the
receiptstable has no UPDATE path in the API. - Forge an Entra group. The
grpclaim is set at sign-in from the Entra ID token. Tampering with the SYNAPTORY1 token breaks the Ed25519 signature.
Anti-enumeration patterns
A few permission checks return 404 (not 403) on purpose, to avoid leaking the existence of resources you can't see.
| Scenario | Status |
|---|---|
| You're not a project member, project exists | 404 |
| You're a project member, project archived | 403 (you can see it but can't modify) |
| Project doesn't exist at all | 404 |
This is why "user reports they got 404 on a project they should have access to" is the #1 access-control debug signal — there are three possible causes (not a member, project archived, project missing), and they look identical from the client.
What's next
- Auth flows — how the
grpclaim is set. - Identity and access — the per-request enforcement model.
- Inviting members — the workflow.
Glossary
Diataxis category: Reference — information-oriented.
This guide is v2.5-primary in vocabulary, matching the rest of the codebase. The Console UI has already adopted v3.0 names for some surfaces (per docs/v3.0/v3-spec.md). When you see a v3 name in the Console, this table is your decoder ring.
For the broader v3 plan — what's coming beyond renames — see v3.0 Roadmap.
The single TS module mapping these names in the UI is web/src/lib/v3-vocab.ts.
v2.5 → v3.0 vocabulary map
| v2.5 term (used in this guide) | v3.0 term (in Console UI today) | Notes |
|---|---|---|
| Story | Spec (with kind=story) | "Story" remains a spec kind alongside feature, bugfix, task, release in v3. Today the only spec kind in the system is story. |
product-manager (PM) — agent role | project-owner (PO) | Codebase-wide rename. product-manager accepted as a server-side legacy alias for in-flight receipts; Alembic migration 20260428_0005 backfills. |
| Definition of Done (DoD) | Evidence / DoD gate (one of four v3 gates) | The four v3 gates are: Inception · Spec Ready · Evidence/DoD · Release. Only Evidence/DoD has a wired backend signal in v2.5; the others are placeholders. |
| Token usage | Per-stage token usage | 11 v3 stages: pro-discovery, pro-brd, pro-ux-spec, sa-architecture, se-implementation, qe-verification, cr-review, ce-compliance, pe-infra, tw-docs, orchestrator. Drives /cost/by-stage. |
| Cost | USD compute | Split into input / output / cache-read / cache-write. Pinned rates per model — see MODEL_PRICING_USD_PER_M in api/synaptoryapi/routers/analytics.py. |
| User (in admin context) | Delivery Owner | Human role; the agent counterpart is Project Owner. v3 §4.2. |
Agent tier (every-sprint / on-demand / adaptive) | (retired) | Field still on the API for back-compat; UI no longer displays it. |
Platform terminology
| Term | Definition |
|---|---|
| Plugin | The Claude Code plugin (plugin/ in this repo). Installs via /plugin marketplace add https://synaptory.h3t.co/marketplace.git. |
| CLI | The standalone synaptory Go binary. One install per laptop, used by the plugin's hooks. |
| Control-plane API | The FastAPI service at synaptory.h3t.co/v1/*. Handles auth, project membership, skill delivery, telemetry. |
| Control Plane | The Next.js web app at synaptory.h3t.co/. One role-aware app for every signed-in synaptory-users member (ADR-019). Per-page sidebar entries are gated by role; data is auto-scoped server-side. The legacy Console (/console/*, admin) and Portal (/portal/*, member) surfaces were collapsed into this one tree. |
| Marketplace | The self-hosted git endpoint at synaptory.h3t.co/marketplace.git. The transport for /plugin marketplace add. |
| SYNAPTORY1 token | The session token format. SYNAPTORY1.<payload>.<sig> — Ed25519-signed by the control plane. |
| UPN | User Principal Name — the Entra identity (e.g. alice@h3t.co). |
| Watermark | Per-UPN visible HTML comment + steganographic zero-width pattern injected into every fetched skill body. See ADR-016. |
Lifecycle terminology
| Term | Definition |
|---|---|
| Build mode | Either scrum or kanban. Set in .synaptory.yaml per project. |
| Engagement mode | Either structured (autonomous) or interactive (user reviews major decisions). Set in .synaptory.yaml. |
| Inception | Sprint 0 of a Scrum delivery. Produces vision, epics, Sprint 1 stories, architecture foundations. |
| Story pipeline | The per-story SE → QE → CR sequence. Sub-states: queued → in_progress → testing → reviewing → done (or blocked). |
| Receipt | Story-scoped JSON written by every agent on completion. {story_id}-{role_abbrev}.json. Validated by synaptory-verify-receipt.sh. |
| DoD | Definition of Done. Story-level (always) and sprint-level (Scrum only). See Enforcement. |
| Tracker adapter | The pluggable backend for stories / epics / sprints. local, github, jira, teamwork. |
Agent role abbreviations
Used throughout this guide and in receipt filenames.
| Abbrev | Role |
|---|---|
| PO | Project Owner |
| SA | Solution Architect |
| SE | Software Engineer |
| QE | Quality Engineer |
| CR | Code Reviewer |
| CE | Compliance Engineer |
| PE | Platform Engineer |
| TW | Technical Writer |
| RA | Research Advisor |
See Agents for the full descriptions and model-tier assignments.
Misc
| Term | Definition |
|---|---|
synaptory-users | The Entra group every signed-in user belongs to. |
synaptory-admins | The Entra group Console admins belong to. Superset — implies synaptory-users. |
project_members | The DB table that grants per-project access. Checked per request. |
| AI-BOM | AI Bill of Materials. The build-metadata.json shipped alongside each plugin build that pins model versions. See Healthcare Compliance. |
| Healthcare mode (HC0) | Operating mode with healthcare.baa_enforced: true. Restricts to BAA-covered backends; pins model IDs explicitly. |
Troubleshooting
Common issues, error messages, and fixes for synaptory delivery runs.
Run Doctor first
When something looks wrong — auth misbehaving, a mode picking the wrong route, a .synaptory.yaml change that didn't take, a fresh laptop that has never run the plugin — run the Doctor mode before anything else:
doctor
(Or any of: "diagnose", "check config", "validate config", "is this correctly configured".)
What Doctor checks (read-only — never modifies files without asking):
.synaptory.yaml— presence, version, schema correctness.- Plugin settings in
.claude/settings.json. - CLI authentication state (token source, format, signature, expiry).
- Control-plane project membership for the current
project_id. - Backend mode and session directory layout.
- v2.1 cruft (legacy paths, retired keys) that should be cleaned up.
Doctor produces a pass/warn/fail report with a remediation pointer for every finding. SessionStart errors funnel through the same diagnostic automatically, so a failed login or stale config surfaces a Doctor report instead of a raw stack trace.
When to run it:
- A project is being migrated from v2.1 to v2.5.
- A
/synaptorydispatch returns unexpected errors. - A new team member sets up the plugin.
- After any manual edits to
.synaptory.yamlor.claude/settings.json. - Before opening a Report — the Doctor output is exactly the context the bug report needs.
Authentication issues
"synaptory: Control Plane Not Configured"
The plugin build does not have a control-plane URL stamped into it. Re-download the plugin from the marketplace or contact your H3Tech operator.
Sign-in browser tab did not open
Run the device-code flow manually:
synaptory login --device
Visit the URL shown, enter the code, and approve. The session is cached once approved.
"Cached session expired" / session prompt on every start
The session token expired and silent refresh failed. Re-run:
synaptory login
synaptory login returns 401 or "project not found"
Your UPN may not be a member of the project declared in .synaptory.yaml. Contact your H3Tech operator to verify project membership. Run synaptory projects list to see projects you have access to.
Skills not loading after sign-in
Force a skill cache sync:
synaptory skills sync
Then restart your Claude Code session.
Verify your session at any time
synaptory whoami
synaptory status
whoami prints your UPN, project, and token expiry. status runs a full diagnostic including skill cache size and outbox depth.
Lifecycle and ceremony issues
"No active pipeline found"
No .synaptory/ workspace directory exists. Say "initialize my project" or describe what you want to build.
Execution blocked by receipt validation
In Structured mode, synaptory-verify-receipt.sh exits 1 if an agent completes without a valid receipt. The error identifies which fields are missing or which artifacts weren't found. Options:
- Re-run the agent -- the receipt may have been skipped on a failed attempt
- Switch to Interactive mode -- change engagement mode to inspect the output before deciding
- Check the receipt manually --
.synaptory/.orchestrator/receipts/-- verify artifact paths
Lifecycle state seems wrong
If "show status" reveals incorrect state (e.g., stuck in SPRINT_EXECUTION when stories are done):
- Check raw state:
``bash cat .synaptory/.orchestrator/pipeline-state.json ``
- Manually transition if needed:
``bash python3 /path/to/plugin/hooks/lib/scrum_state_machine.py transition "$(pwd)" SPRINT_REVIEW ``
Inception Gate rework stuck
Gate rework is automatic -- the system feeds your concerns back to the relevant agent and re-presents the gate. Maximum 2 rework cycles. If it appears stuck after 2 cycles, check .synaptory/.orchestrator/rework-log.md.
Story stuck in testing/reviewing state
A story in testing or reviewing state means the QE or CR hasn't completed yet. Check:
- Receipt exists? Look for
{story_id}-qe.jsonor{story_id}-cr.jsonin.synaptory/.orchestrator/receipts/ - DoD failure? Check the receipt's
story_dodfield -- a Critical check may have failed, moving the story toblocked. - Agent timed out? Re-run the agent for the affected story.
Agent failed multiple times
Read .synaptory/<agent-name>/escalation.md. Common causes:
- A dependency the agent needs doesn't exist yet (sequencing issue)
- An external service is unreachable (network or credentials)
- The problem requires a human decision
Context degraded mid-run -- agents forget the architecture
The synaptory-reanchor.sh hook handles this automatically before context compaction. If you suspect degradation mid-run, trigger manually:
/synaptory -- re-anchor context
Symptoms: agent output contradicts an ADR, agent re-asks an already-answered question, tests target wrong endpoints.
Config not being picked up
Verify .synaptory.yaml is at the project root:
ls .synaptory.yaml
Frontend renders but doesn't work
This is a Dead Element Rule violation -- a Critical bug. Run Debug mode or ask for verification:
Debug -- buttons on the login page don't work
Wrong package versions or deprecated APIs in generated code
The Freshness Protocol should have caught this. Ask for a targeted verification:
verify dependency versions and API compatibility
Delivery cost is higher than expected
Check the engagement mode -- Interactive surfaces more decisions but uses the same model tiers as Structured. Check rework cycles in .synaptory/.orchestrator/rework-log.md. Each rework adds 10-30K tokens.
Strategy: use Structured for sprint execution, switch to Interactive for Release verification.
Sprint issues
Sprint Review DoD not met
At Sprint Review, the sprint-level DoD overlay is evaluated. If blocked on the auto-check (no-regression), the regression test suite must pass. If blocked on human checks (Sprint Goal, feedback addressed, docs), these require your confirmation.
Cannot advance to next sprint
Sprint Close must complete before Sprint Planning for the next sprint. Check the lifecycle state -- if stuck in SPRINTREVIEW or SPRINTRETRO, complete those ceremonies first.
Sprint carry-over confusion
Incomplete stories at Sprint Close are handled by sprint.carry_over_policy in .synaptory.yaml:
move_to_next(default) -- stories move to next sprintkeep_in_sprint-- stories stay in closed sprint (reporting only)ask-- you choose at close time
Tracker issues
"Jira API not configured" or "GitHub CLI not available"
Remote tracker backends require authentication:
- GitHub: Run
gh auth loginor setGITHUB_TOKENenv var - Jira: Set
JIRA_API_TOKENandJIRA_USER_EMAILenv vars - Teamwork: Set
TEAMWORK_API_KEYenv var
"Could not create GitHub Issue Types: Epic, Story"
Creating custom Issue Types requires admin:org scope. Ask an org admin to create them. Synaptory only needs standard repo scope for ongoing use.
Switching tracker providers
Use the migrate command:
python3 path/to/tracker_cli.py --project-dir . migrate --from local --to github
Then update tracker.backend in .synaptory.yaml.
Tracker health check
python3 path/to/tracker_cli.py --project-dir . health-check
Expected: {"status": "ok", ...}. If offline, the error message includes setup instructions.
Discover and context package issues
/synaptory producing incomplete context packages
Some analysis phases require git history. If the repo is shallow-cloned, risk and hotspot analysis will be limited:
git fetch --unshallow
Then re-run Discover.
Context packages not being loaded
Verify brownfield.context_packages is true in .synaptory.yaml and that packages exist in .synaptory/.orchestrator/context-packages/. Re-run Discover if missing.
Control Plane issues
"I get a 404 when I try to open /console/* or /portal/*"
ADR-019 retired both URL trees. Drop the prefix and use the root URL: /console/overview → /overview, /portal/home → /home, etc. Bookmarks at the legacy URLs need to be updated; there are no redirects.
"An admin-only page (Overview, Policy, System) doesn't show in my sidebar"
You aren't a member of synaptory-admins. The unified Sidebar filters entries via requires(viewer); admin-only items are hidden for non-admins. Have an existing admin add you to the Entra group, then sign out and back in (the grp claim is set at token-mint time).
"I see /cost but with empty results"
You aren't a member of any project (or you're a member-only on projects that have no activity in the window). The page is scope-aware: project members see their member projects' costs filtered to their own UPN; project admins see cross-UPN; global admins see everything. Unaffiliated users get an empty result rather than a 403.
"Sign-in redirect loops between /auth/login and Entra"
Almost always one of:
- The browser's iron-session cookie is stuck — clear
synaptory.h3t.cocookies and try again. - The Entra app's Web platform redirect URI list doesn't include the host you're signing in from. Verify with
az ad app show --id $SYNAPTORY_CP_ENTRA_CLIENT_ID --query "web.redirectUris". - The Entra
client_secretis rotated but.env.prodwasn't updated; thewebcontainer is failing the code-for-token exchange silently. Checkdocker logs webforAADSTS7000215or similar.
"I can see my project in /projects but the Members tab is empty"
You're a member, not a project admin. Only project admins see the invite/revoke controls. See permissions.
"I revoked my session but the plugin keeps working"
Session revoke takes effect on the next API call from that session. If the plugin hasn't fired a hook since the revoke, the cached token is still in the OS keychain and inert. Run synaptory status to force an API call — you'll see a 401 and the plugin will surface the re-login prompt.
"/cost shows $0.00 across the board"
Either no receipts have been ingested yet (check /audit for any rows) or the Receipt.payload.token_usage field is empty. The latter happens if the CLI's outbox was queued before the platform started recording token usage. Force-flush with synaptory outbox flush.
"OTLP latency panel is empty on /reliability"
The CLI emits OTLP spans only when synaptory otel is configured. Check synaptory config show for the otel exporter URL. With no exporter, the only signals come from receipts (no per-stage latency).
"Inviting a user returns 404 even though they're in Entra"
The invite endpoint validates that the UPN exists in synaptory-users first. Add to the Entra group, then retry. The 404 is anti-enumeration — same status whether the UPN doesn't exist at all or just isn't in the group.
What's next?
- Getting Started -- Installation and setup
- Configuration Reference -- All config options
- Commands Reference -- CLI tools for manual debugging
- Using the Control Plane -- Page-by-page tour