opencode-telos
v2.0.0
Published
OpenCode Telos - Spec-Driven Development plugin with Knowledge Graph enforcement
Maintainers
Readme
OPENCODE TELOS
A Spec-Driven Development (SDD) plugin for OpenCode. It turns the development environment into a conversational system based on a Knowledge Graph, where the specification always comes before the code.
What it does
- Conversational discovery: analyzes your briefing, detects what is missing and asks questions with selection menus (via the OpenCode
questiontool) - Knowledge Graph: keeps a semantic graph as the source of truth for the project
- Configurable tech stack: detects mentioned technologies, uses the AI's knowledge for stacks not supported by templates
- @ references: reads
.mdfiles to extract stack specifications - Code generation: generates code for supported stacks (Express+React+SQLite) or uses AI for arbitrary stacks
- SDD-first enforcement: blocks code modifications that did not go through the specification
- Change management: every change becomes a trackable Change node in the graph
- Impact analysis: traverses the graph to show what will be affected
- Drift detection: detects when the code deviated from the specification
- Web dashboard: real-time 3D graph visualization with 3d-force-graph
- Constitution: defines mandatory, optional and preferred principles for the project
- Promise tracking: tracks specification promises and detects violations
- Quality scoring: calculates a quality score (0-100%) with trend
- Anti-pattern detection: identifies god nodes, circular dependencies, speculation
- AST clone detection: detects duplicated code in the project
- Contradiction detection: identifies conflicting requirements and rules
- Test coverage tracking: measures test coverage by requirement
- Config drift detection: detects inconsistencies in configs
- Session handoff: generates a state package to continue work
- Workflow export: exports the SDD state as a structured report
- Shell hooks: installs Git hooks for SDD integration
- Brownfield scanning: analyzes existing projects for integration
- CI/CD Integration: generates GitHub Actions, GitLab CI, Jenkins, Docker, CircleCI, Azure DevOps, AWS CodePipeline, Travis CI, NPM Publish, Docker Compose, Maven (Java), Python (pip), Go (GoReleaser) with SDD validation
- Multi-developer Sync: Git-based synchronization with conflict detection and resolution
- Rollback: 3 rollback layers (git → snapshot → backup)
- Permissions: role-based access control (admin, architect, developer, viewer) with GitHub/GitLab authentication
- Enterprise Workflows: automated workflows for enterprise scenarios:
- Bug Fixing: workflow with automatic approval
- Hotfix/Emergency: enforcement bypass + retrospective documentation
- Refactoring: dependency verification + mandatory tests
- Deprecation: migration plan + notifications
- Data Migration: migration scripts + rollback
- A/B Testing: experiments with variants
- Feature Flags: rollout control
- Multi-tenancy: data isolation
- Onboarding: guide for new developers
- Security Audit: automated security audit
- Scalability Analysis: scalability analysis
- Compliance: regulatory validation (GDPR, HIPAA, SOC2)
- Monitoring: metrics and alert configuration
- Incident Management: incident management
- SLA Tracking: service level agreement tracking
- Cost Management: cost estimation
- Documentation: documentation generation
- Knowledge Transfer: knowledge transfer
- Disaster Recovery: disaster recovery plan
Prerequisites
Installation
Option 1: Via OpenCode CLI (recommended)
opencode plugin add opencode-telosThis installs the plugin automatically in your OpenCode.
Option 2: Via npm
npm install -g opencode-telosThen add it to your opencode.json:
{
"plugin": ["opencode-telos"]
}Option 3: Local plugin
Clone or copy the plugin folder into an accessible directory:
git clone https://github.com/JudahAragao/opencode-telos.git ~/.config/opencode/plugins/opencode-telosThen add it to your opencode.json:
{
"plugin": ["~/.config/opencode/plugins/opencode-telos"]
}Option 4: Project-local plugin
Copy the opencode-telos folder into your project:
cp -r /path/to/opencode-telos ./opencode-telosThen add it to your opencode.json:
{
"plugin": ["./opencode-telos"]
}How the interaction works
SDD toggle (on/off)
The plugin can be enabled or disabled at any time. The plugin registers a
command hub on the command.execute.before hook: a single sdd command
that routes to deterministic subcommands (executed by the plugin, without
depending on the LLM to perform the action):
| Command | Subcommand | Effect |
|---|---|---|
| /sdd | panel / help | Shows the panel with the available subcommands |
| /sdd on | on / enable | Enables SDD enforcement (every change requires a spec) |
| /sdd off | off / disable | Disables enforcement (you can code freely) |
| /sdd status | status | Shows the current toggle state |
| /sdd renew | renew | Renews the validity window of the active workflow, keeping the same Change |
| /sdd viz | viz / viz start | Starts the Knowledge Graph dashboard (3D, real time) in the background |
| /sdd viz stop | viz stop | Stops the dashboard |
| /sdd viz status | viz status | Shows the dashboard URL |
| /sdd tasks | tasks | Lists the Kanban task board |
| /sdd tasks integrate | tasks integrate | Shows the AI integration plan for tasks pending integration |
| /sdd tasks board | tasks board | Opens the dashboard on the Kanban board |
| /sdd tasks change <TASK-ID> | tasks change <id> | Opens the SDD Change that authorizes the code of a task (--approve approves it) |
| /sdd cache_reset | cache_reset | Clears caches without killing the session |
/sdd-viz and /sdd:viz are accepted as the same command as /sdd viz.
The dashboard listens on 127.0.0.1:7331 (override with SDD_DASHBOARD_PORT),
falls back to a free port when 7331 is taken, and is stopped when the OpenCode
process exits — it is an in-process server, not a detached daemon.
Note: because slash
/commands in OpenCode are prompt commands by definition, invoking them makes OpenCode also trigger an LLM turn after thecommand.execute.beforehook. The deterministic action itself (enable/disable) is performed by the hook without depending on the model; the extra turn is an inherent behavior of the OpenCode command flow.
Recommended way (no LLM turn): the same operations are available as tools/MCP, called by the agent deterministically:
| Tool | Effect |
|---|---|
| sdd.toggle | Enables/disables enforcement |
| sdd.toggle_status | Shows the current toggle state |
When disabled:
- The SDD system prompt is not injected
- There is no enforcement on writes/edits
- The agent can modify code directly
When enabled:
- Mandatory SDD-first workflow
- Spec before code
- Change nodes for every modification
The toggle state is persisted in .sdd/enabled inside the project.
Step 1: Describe the project
Open OpenCode in your project folder and describe what you want to create:
I want to create a task management system.
Each user will have their own tasks with title, description and status.The plugin automatically:
- Detects that SDD is not initialized
- Runs
sdd.discoveranalyzing your briefing - Detects: entities (user, task), domain (task_management)
- Detects mentioned technologies (none yet)
- Returns structured questions for the
questiontool
Step 2: Answer with selection menus
OpenCode displays a menu for each missing question:
? Which framework will be used on the frontend?
> React
Vue.js
Angular
Svelte
Next.js
[Type your own answer]? Which framework will be used on the backend?
> Express
Fastify
NestJS
Django
FastAPI
[Type your own answer]? Which database will be used?
> SQLite
PostgreSQL
MySQL
MongoDB
[Type your own answer]? How will users log in to the system?
> Email + Password
Google OAuth
JWT
No authentication
[Type your own answer]? How should deletions work in the system?
> Hard delete (permanent)
Soft delete (reversible)You select an option or type your own answer. The plugin updates the Knowledge Graph automatically.
Step 3: Specify the stack via .md files (optional)
If you prefer to define the stack in a file, create a .md and reference it with @:
I want a task system. @tech.mdWhere tech.md contains:
## Stack
- Frontend: Next.js + Tailwind
- Backend: FastAPI (Python)
- Database: PostgreSQL
- Auth: ClerkThe plugin reads the file, detects the technologies and does not ask about them.
Step 4: Generate the code
Once the specification is sufficient:
Generate the project codeThe plugin:
- If the stack has built-in templates (Express+React+SQLite): generates the files automatically
- If the stack is different: returns a detailed specification and the AI generates the code using its knowledge of your chosen technologies
Step 5: Modify features
Add a priority field to tasks with LOW, MEDIUM and HIGH valuesThe plugin forces the SDD workflow:
sdd.enforce→ classifies as "add_functionality"- Creates a Change node (e.g. CHG-001)
- Analyzes impact: Task entity, API, tests
- Updates the specification
- Validates the SDD
- Regenerates the affected code
- Completes the Change
Step 6: Architectural changes
Change the database from SQLite to PostgreSQLThe plugin blocks and asks for explicit approval before proceeding.
Step 7: Check drift
Check if there is any drift in the projectThe plugin compares the graph with the code and reports divergences.
Complete the specification manually
If you think the AI did not ask all the questions, you can:
Validate what is missing:
Validate the SDD and tell me what is missing in the specThe agent runs sdd.validate and lists errors/warnings (e.g. entity without fields, requirement without task).
Run discovery again:
Analyze the current SDD and ask all the missing questionsThe agent inspects the graph with sdd.inspect, identifies gaps, and asks questions via question.
Check completeness before generating:
Check if the spec is complete before generating codeAdd entities/rules manually:
Add a Tenant entity with fields id (uuid), name (string), created_at (timestamp)The agent runs sdd.graph_mutation(action="add_node") directly.
Add a relationship:
Create a relationship: Tenant contains UserQuery the current state:
Show the current SDD stateThe agent runs sdd.inspect showing stats, nodes by type and status distribution.
Kanban task board
The dashboard exposes a Kanban view over the existing task nodes — no
schema change. Columns are derived from the task status:
| Column | Status |
|---|---|
| Backlog | DRAFT, PROPOSED, todo |
| Ready | ready, APPROVED |
| In Progress | in_progress, IMPLEMENTING, VERIFYING |
| Blocked | blocked, BLOCKED, CONFLICT, FAILED, DRIFTED |
| Done | completed, COMPLETED, IMPLEMENTED, VERIFIED, DEPRECATED, ROLLED_BACK |
Open it with /sdd viz (or /sdd tasks board) and switch to the Kanban tab:
- Create manually: the “+ Nova task” button writes a
tasknode to the graph immediately (statustodo, linked to the project root so it is never an orphan). The task keepsmetadata.integration_status: "pending". - Edit / drag: moving a card updates the node status; editing content marks the task as pending integration again.
- AI integration: when the SDD agent session is active, saving a card asks
the agent to run
sdd.integrate_tasks, linking the task to itsfeature/requirement(implements), tests (tested_by) and dependencies. Without an active session the task simply stays pending and the agent picks it up on the next turn (the system prompt surfaces the pending count) —/sdd tasks integrateprints the plan at any time.
Persistence goes through the same repository as the SDD tools, so the board
works for both YAML and SQLite backends. Mutating routes reject cross-origin
requests and non-loopback Host headers.
Filtering, search and sorting
The toolbar at the top of the Kanban lets you:
- Search by free text (matches task id, name, description, goal, files and linked node names).
- Filter by link status: all / linked / unlinked / specific node type (feature, requirement, entity, test).
- Filter by integration: all / pending / manual / integrated.
- Filter by priority: all / critical / high / medium / low.
- Filter by column: all / Backlog / Ready / In Progress / Blocked / Done.
- Sort by: column (default), priority, name, updated, created, links, integration.
- Toggle ascending/descending order.
All filter state is persisted in localStorage and survives page reloads. The
Limpar button resets everything. The server-side API also accepts query
params (GET /api/tasks?q=...&priority=high&sort=name&order=desc) for external
consumers.
Each card shows a colored priority badge and, when a Change has been opened,
a CHG-xxx · STATUS badge.
From task to code: the SDD Change
A task is only a work item — the write hook refuses any Write/Edit that is
not covered by an APPROVED change node. So an integrated task opens its
own Change, and that Change is what unlocks code generation:
mark_integrated(or the card's Abrir Change SDD button,POST /api/tasks/:id/change, or/sdd tasks change <TASK-ID>) creates achangenode through the standardcreateChangepath — impact analysis, approval level,affected_files/affected_teststaken fromtask.metadata.files,implementation_tasks: [task.id], andchange → affects → <spec nodes linked to the task>.- The link is recorded both ways (
change.affects → taskandtask.metadata.change_id/change_status), so the card shows aCHG-xxx · STATUSbadge and the topbar counts the Changes awaiting approval. - AUTO-level Changes with a complete file scope are approved immediately;
REVIEW/APPROVALones stay in draft and the modal offers Aprovar + gerar código ({ "approve": true }) or/sdd tasks change <TASK-ID> --approve. A Change withoutaffected_filescannot be approved — the write hook would reject every file — so the blocker is reported instead. - Once approved, the agent is handed
buildChangeImplementationPrompt(...): implement the code covered by that Change, run the tests and finish withsdd.complete_change. Without an active session nothing is lost: the next turn surfaces the tasks whose Change still needs approval, and the same steps are available as tools.
The bridge is idempotent — calling it twice returns the same Change — and never writes source code itself.
| Tool | Description |
|---|---|
| sdd.integrate_tasks | Kanban bridge: list tasks pending integration, create/update/remove tasks, mark_integrated (which opens the Change) and open_change/approve_change to drive the code authorisation |
Available tools
Graph initialization and management
| Tool | Description |
|---|---|
| sdd.initialize | Initializes SDD for the project |
| sdd.toggle | Enables/disables SDD enforcement (write) |
| sdd.toggle_status | Shows the current toggle state (read-only) |
Navigation and search
| Tool | Description |
|---|---|
| sdd.inspect | Shows the current state of the graph |
| sdd.query_graph | Searches nodes by text, type or ID |
| sdd.get_context | Context pack for a node |
| sdd.analyze_impact | Impact analysis via traversal |
Node listing/counting/status filtering, traversal and path finding live in the composite tools below (
sdd.graph_query,sdd.traverse).
Graph building
| Tool | Description |
|---|---|
| sdd.build_graph | Builds a complete Knowledge Graph from a briefing (entities, features, requirements, relationships). The primary tool for bootstrapping a specification: prefers an analysis_json with the agent's structured analysis. |
| sdd.auto_link_tests | Links orphan tests to requirements by name/import analysis (tested_by), optionally as a dry run |
| sdd.infer_relationships | Rebuilds graph traceability: infers the missing semantic edges (requirement --specifies--> feature, endpoint/file --implements--> feature, endpoint --operates_on--> entity, task/change --belongs_to--> milestone), normalizes redundant inverse pairs and creates milestone nodes. Idempotent; dry_run previews the edges |
| sdd.milestone | Manages release milestones and reports traceability per release: create, list, add, remove, assign, close, report. The report shows the release scope, task progress and gaps (requirements without tests, features without implementation, endpoints/files without a feature) |
Composite tools
The router groups related tools into composite tools that accept an action parameter. They are the single canonical path for these capabilities: the original standalone tools (sdd.add_node, sdd.analyze_complexity, sdd.create_snapshot, ...) were removed from the catalog and are no longer registered or announced. A residual call to an old name is rejected with a redirect to the canonical form.
| Tool | Actions |
|---|---|
| sdd.graph_mutation | add_node, update_node, remove_node, add_relationship, remove_relationship |
| sdd.graph_query | count_nodes, get_nodes_by_status, list_nodes |
| sdd.traverse | outgoing, incoming, both, subgraph, find_path |
| sdd.permissions | set_role, check, audit, config, save_config, role, approval |
| sdd.snapshot | create, rollback, history, list |
| sdd.sync | status, pull, push, conflicts, merge |
| sdd.graph_admin | health, health_detail, prune, cache, conventions, learn |
| sdd.code_quality | complexity, metrics, smells, dependencies, usage, dead_code, remove_dead_code, parse_symbols, plan_implementation, analyze_codebase |
| sdd.enterprise | migration, experiment, flag, tenant, security_audit, scalability, compliance, monitoring, dashboard, incident, sla, cost, docs, onboarding, knowledge_transfer, disaster_recovery, config_drift, workflow_export |
| sdd.drift_whitelist | add, remove, list |
Workflow chains
Encapsulated multi-step workflows executed as a single tool call (each step uses the SDD tools under the hood):
| Tool | What it does |
|---|---|
| sdd.workflow_new_feature | enforce → build_graph → validate → approve → generate → verify → complete |
| sdd.workflow_bug_fix | enforce → validate → approve → generate → verify → complete |
| sdd.workflow_hotfix | emergency hotfix (no enforcement) + retrospective documentation |
| sdd.workflow_refactor | enforce → validate → analyze impact → complete |
| sdd.workflow_full_cycle | full cycle via sdd.full_cycle |
Discovery and briefing
| Tool | Description |
|---|---|
| sdd.discover | Analyzes briefing, returns questions for the question tool |
| sdd.update_from_answers | Updates the graph with answers |
Change management
| Tool | Description |
|---|---|
| sdd.create_change | Creates a Change with approval gates (refuses to create one without affected_files) |
| sdd.approve_change | Approves a change (refuses a Change with no declared scope) |
| sdd.verify_implementation | Runs the declared scripts + the requirement→test evidence, and binds the report to the Change's files |
| sdd.complete_change | Marks a change as complete, only when every gate passes |
| sdd.renew_workflow | Renews the active workflow window, keeping the same Change and its verification report |
| sdd.pending_changes | Lists pending changes |
| sdd.fail_change | Marks a change as FAILED with a reason |
| sdd.change_history | Shows the changes history ordered by creation |
| sdd.impact_report | Generates a detailed impact report for a change (affected nodes, files, new/modified/removed) |
Completion gate (trava B)
sdd.complete_change only completes a Change when all of these hold:
- the executable verification passed — or was explicitly waived with
acknowledge_no_scripts=truein a project that declares no script; - the requirement→test evidence holds, or the Change declares
no_requirement_impact=true; - no verification check failed;
- the project fingerprint still matches (any code/config change invalidates the report);
- the declared
affected_filesstill exist with the same content hashes (verifyScopedFiles); - the Change references at least one node that exists in the graph (spec evidence).
force=true remains an explicit, audited override — it is not a shortcut. The blocked message lists exactly which condition failed.
Workflow window
An active workflow is valid for 30 minutes (SDD_WORKFLOW_TTL_MS overrides it).
When it expires mid-task, sdd.renew_workflow (or /sdd renew) extends the window
for the same Change, preserving the verification report. Calling sdd.enforce
again would create a new Change and orphan the previous one.
Validation and quality
| Tool | Description |
|---|---|
| sdd.validate | Validates SDD integrity |
| sdd.constitution | Manages the project constitution (principles) |
| sdd.quality | Calculates the quality score with trend |
| sdd.contradictions | Detects contradictions in the graph |
Migrations
| Tool | Description |
|---|---|
| sdd.check_migrations | Checks if SDD data needs migration (graph.yaml vs graph.db, missing fields) |
| sdd.run_migrations | Executes all pending SDD migrations |
| sdd.migrate_storage | Migrates storage between YAML and SQLite backends |
Drift detection
| Tool | Description |
|---|---|
| sdd.detect_drift | Detects specification ↔ code drift |
| sdd.drift_signals | Detects advanced drift signals (mutant duplicates, architecture violations, pattern fragmentation) |
Patterns and anti-patterns
| Tool | Description |
|---|---|
| sdd.anti_patterns | Detects anti-patterns in the graph |
| sdd.clone_detection | Detects duplicated code in the project |
Code and generation
| Tool | Description |
|---|---|
| sdd.generate_code | Generates code (templates or via AI for arbitrary stacks) |
| sdd.enforce | Enforces the SDD-first workflow |
| sdd.enforce_rules | Shows the enforcement rules |
| sdd.full_cycle | Full cycle: enforce → validate → generate → sync |
Verification
| Tool | Description |
|---|---|
| sdd.verify_implementation | Runs the project-declared verification scripts (lint, typecheck, test, build, etc.) plus the requirement→test evidence for the Change. A report is required before completing the Change. |
Analysis
| Tool | Description |
|---|---|
| sdd.drift_signals | Detects advanced drift signals (mutant duplicates, architecture violations, pattern fragmentation) |
| sdd.brownfield_scan | Analyzes an existing project for integration |
Code quality analysis, codebase intelligence, sync, rollback and permissions are composite tools (
sdd.code_quality,sdd.sync,sdd.snapshot,sdd.permissions).
Enterprise workflows
| Tool | Description | Approval level |
|---|---|---|
| sdd.bug_fix | Full bug fix workflow | AUTO |
| sdd.hotfix | Retrospective hotfix documentation | POST_HOC |
| sdd.refactoring | Refactoring with dependency verification | REVIEW |
| sdd.deprecate | Deprecation with migration plan | APPROVAL |
Migrations, experiments, feature flags, multi-tenancy, monitoring, dashboards, incidents, SLAs, docs, onboarding, knowledge transfer, disaster recovery, config drift and workflow export are actions of
sdd.enterprise.
Documentation and knowledge
| Tool | Description |
|---|---|
| sdd.session_handoff | Generates a session handoff package |
Cost and CI/CD
| Tool | Description |
|---|---|
| sdd.generate_cicd | Generates CI/CD config (platform: github, gitlab, jenkins, docker, or all) |
Infrastructure
| Tool | Description |
|---|---|
| sdd.install_hooks | Installs Git hooks for SDD |
| sdd.brownfield_scan | Analyzes an existing project |
| sdd.start_dashboard | Starts the web server with 3D graph visualization |
| sdd.mcp_server_info | MCP server information |
| sdd.handle_mcp_tool | Processes a tool via the MCP protocol |
| sdd.telemetry | Shows local performance, estimated token, and cache telemetry (nothing leaves the machine) |
| sdd.record_feedback | Records a local human correction for an extracted fact/classification |
Promises
| Tool | Description |
|---|---|
| sdd.promises | Tracks specification promises |
| sdd.coverage | Measures test coverage by requirement |
Tech stack and code generation
Stacks with built-in templates
The plugin generates code automatically for:
| Layer | Technologies | |---|---| | Frontend | React + React Router + custom hooks | | Backend | Express or Fastify + REST routes + controllers + services + repositories | | Database | SQLite, PostgreSQL or MySQL (via native drivers) + SQL schema | | Tests | Bun test | | Types | Shared TypeScript |
Arbitrary stacks (via AI)
For any other combination (Django, FastAPI, Rails, Go, etc.):
- The plugin detects the stack from the graph
- If it is not in the built-in template set, it returns a spec prompt
- The spec prompt lists entities, endpoints and business rules extracted from the graph
- The AI generates the complete code using its knowledge of your chosen technologies
- You can specify the stack via the briefing (
FastAPI with PostgreSQL) or via a@tech.mdfile
Automatic detection
The plugin automatically detects in the briefing:
- Frontend: React, Vue, Angular, Svelte, Next.js, Nuxt, Tailwind, shadcn/ui, etc.
- Backend: Express, Fastify, NestJS, Django, FastAPI, Flask, Rails, Laravel, Spring Boot, Go, Rust, etc.
- Database: PostgreSQL, MySQL, SQLite, MongoDB, Redis, Supabase, Firebase, Turso, etc.
- Auth: JWT, Google/GitHub OAuth, Clerk, Auth0, NextAuth, session/cookie, etc.
- Language: TypeScript, JavaScript, Python, Go, Rust, Java, Ruby
- Tests: Jest, Vitest, Bun test, Cypress, Playwright, pytest, RSpec
Technologies that have already been mentioned are not asked again.
Supported node types
| Type | Description |
|---|---|
| project | The project |
| domain | Functional domain |
| feature | Feature |
| requirement | Requirement |
| business_rule | Business rule |
| actor | External user/system |
| entity | Domain entity |
| value_object | Value object |
| flow | Flow |
| use_case | Use case |
| architecture_component | Architectural component |
| module | Module |
| api | API interface |
| endpoint | HTTP endpoint |
| database | Database |
| table | Table |
| field | Field |
| task | Implementation task |
| test | Test |
| file | Code file |
| symbol | Function, class, interface |
| change | System change |
| decision | Architectural decision (ADR) |
| constraint | Constraint |
| assumption | Recorded assumption |
| constitution | Project principles (must/should/may) |
Relationship types
contains, depends_on, requires, implements, implemented_by,
satisfied_by, affects, modifies, creates, deletes, uses,
calls, persists_to, exposes, tested_by, tests, derived_from,
contradicts, supersedes, replaces, blocked_by, belongs_to,
owned_by, triggered_by, flows_to, deprecates, migrates_to,
experimented_by, flagged_by, validates, influences, constrains,
applies_to, owned_by_tenant, monitored_by, alerted_by,
incident_in, sla_for, definesEnforcement flow
Every modification must follow it. The hook blocks programmatically any Write/Edit to source files that does not have an approved Change node:
USER: "Add X"
↓
Write/Edit intercepted by the hook
↓
Hook checks: source file? SDD initialized? Approved Change covering this file?
↓
If there is NO approved Change → ERROR: operation blocked
↓
The agent is forced to follow the SDD workflow:
↓
sdd.enforce → classifies the change
↓
sdd.discover → collects missing information
↓
question → selection menus for the user
↓
sdd.update_from_answers → updates the graph
↓
sdd.create_change → creates a Change node (needs affected_files)
↓
sdd.approve_change → approves the Change
↓
Write/Edit → operation released by the hook for files covered by the Change
↓
sdd.generate_code → generates/updates code
↓
sdd.verify_implementation → scripts + requirement→test evidence + file hashes
↓
sdd.complete_change → completes only when every gate passes
(if the 30-min window expires: sdd.renew_workflow keeps the same Change)What is blocked: any write operation on .ts, .tsx, .js, .jsx, .py, .go, .rs, .java, .rb, .vue, .svelte files (outside node_modules, .sdd/, dist/, build/, .git/, .opencode/, and unfollowed files like package.json, tsconfig.json, .env).
What is NOT blocked: config files (package.json, tsconfig.json), .env, .sdd/ files, files outside the project.
What happens when blocked: the agent receives an error message describing exactly what it needs to do (enforce → approve → retry).
Completing a Change (verification gate)
sdd.complete_change only completes a Change when all of these hold (unless you explicitly force=true, which is an audited override, not a shortcut):
- the executable verification passed —
sdd.verify_implementationran the project-declared scripts AND the requirement→test evidence for the Change, and all passed; - the requirement→test evidence holds — at least one
tested_bylink exists for each affected requirement, or the Change declaresno_requirement_impact=true; - no verification check failed — every
format:check,lint,typecheck,test,build,ci,diff, etc. that the project declares must pass (skipped optional tests do not count as a failure); - the fingerprint still matches — no code or configuration file changed after verification;
- the declared
affected_filesstill match — each file declared by the Change exists and has the same content hash captured at verification (verifyScopedFiles); - spec evidence exists — the Change references at least one node that actually exists in the graph, or declares
no_requirement_impact=true.
The blocked message lists exactly which condition failed, so the agent knows what to fix.
What is a "verification script" and when does a project not have one?
sdd.verify_implementation does NOT invent a command. It derives the check from the project:
- reads
package.jsonscripts and runs the ones it understands:format:check,format,lint,typecheck,check,verify,build,compile,test,ci; - also looks for common manifests:
Cargo.toml(cargo check/test),go.mod(go test),pyproject.toml/pytest.ini/tox.ini(python compile/test),pom.xml/gradle/Makefile; - runs
git diff --checkwhen there is a.gitrepo.
A project "does not have a verification script" when none of those is declared — for example, a straight Node/TS repo that only has start/dev scripts and no test or lint target, or a minimal project that was not configured with any verification script at all.
In that case sdd.verify_implementation returns:
## Executable Verification: BLOCKED
- SKIPPED: project verification — No supported project verification manifest or script was declared
No executable verification script was available; configure project scripts before completing the Change.So a project without a verification script is blocked by default — that is the intended behavior, because the gate is supposed to require evidence, not guess.
How can a project still complete when it has no script?
That is the G4 case. Instead of silently forcing the Change, the workflow now uses an auditable waiver:
- run
sdd.verify_implementationwithacknowledge_no_scripts=trueand optionallywaiver_reason(e.g. "docs-only change, no test runner declared"); - the report is saved with
verification_waived: trueand the recorded reason; sdd.complete_changethen accepts that report as a valid completion.
Use this only when you understand what is missing — it is the explicit path from "I must provide a script" to "I am recording why there is no script and I still want to complete". It does not remove the other gates: the requirement→test evidence, fingerprint and file hashes still apply.
What about changes that do not write code?
For changes that do not affect a file (documentation only, graph-only updates, metadata changes), declaring an artificial file to satisfy the gate is not the right move. Instead:
- declare
affected_files: []withacknowledge_no_files=truewhen creating the Change (private, audited — the write hook stays blocked for that Change because there is nothing to cover); - declare
no_requirement_impact=truewhen the change truly alters no specified behaviour; - complete only if the remaining gates still make sense.
That combination is the intended path for graph-only/documentation-only changes: it records the decision that no script and no spec-trace were required, instead of forcing a Change into a verification model that does not fit it.
Authentication and roles
How roles work
The permissions system works on 3 levels:
1. Remote Detection (automatic)
- The plugin automatically detects the remote repository (GitHub/GitLab)
- If detected, it uses the API to check the user's permissions
- If not detected or no token → everyone has admin access
2. Available roles
| Role | Permissions |
|---|---|
| admin | Everything: create, approve, modify constitution, rollback, manage permissions |
| architect | Create/approve features/requirements, approve architecture, decisions |
| developer | Create/approve features/requirements |
| viewer | View only |
3. Automatic fallback
- No remote repository → everyone is admin
- No auth token → everyone is admin
- Invalid token → fallback to admin
- User not found on remote → checks local role
Token configuration
GitHub:
export GITHUB_TOKEN=ghp_yourtokenhereGitLab:
export GITLAB_TOKEN=glpat-yourtokenhereThe token needs collaborator-read permissions:
- GitHub:
reposcope - GitLab:
read_apiscope
Check status
sdd.remote_statusShows whether the remote is configured and whether the token is present.
Usage example
# Check a user's permission
sdd.permissions(action: "check", user: "joao", permission: "approve_architecture")
# Set a role manually (local)
sdd.permissions(action: "set_role", user: "maria", role: "architect")
# Check remote status
sdd.remote_statusEnterprise workflows
The plugin automatically detects enterprise scenarios and suggests specific workflows:
Automatic detection
When you type something like:
- "Fix the login bug" → Detects bug fix and suggests
sdd.bug_fix - "Emergency: system is down" → Detects hotfix and disables enforcement
- "Refactor the auth module" → Detects refactoring and suggests
sdd.refactoring - "Deprecate the /api/v1 route" → Detects deprecation and suggests
sdd.deprecate - "Migrate the users table data" → Detects migration and suggests
sdd.enterprise(action="migration") - "Create an A/B experiment" → Detects A/B testing and suggests
sdd.enterprise(action="experiment") - "Add a feature flag" → Detects feature flag and suggests
sdd.enterprise(action="flag") - "Add multi-tenancy to the system" → Detects multi-tenancy and suggests
sdd.enterprise(action="tenant") - "Onboarding for a new dev" → Detects onboarding and suggests
sdd.enterprise(action="onboarding") - "Run a security audit" → Detects security and suggests
sdd.enterprise(action="security_audit") - "Analyze scalability" → Detects scalability and suggests
sdd.enterprise(action="scalability") - "Check GDPR compliance" → Detects compliance and suggests
sdd.enterprise(action="compliance") - "Set up monitoring" → Detects monitoring and suggests
sdd.enterprise(action="monitoring") - "Report an incident" → Detects incident and suggests
sdd.enterprise(action="incident") - "Create a 99.9% SLA" → Detects SLA and suggests
sdd.enterprise(action="sla") - "Estimate costs" → Detects cost and suggests
sdd.enterprise(action="cost") - "Generate documentation" → Detects documentation and suggests
sdd.enterprise(action="docs") - "Knowledge transfer" → Detects knowledge and suggests
sdd.enterprise(action="knowledge_transfer") - "Disaster recovery plan" → Detects disaster and suggests
sdd.enterprise(action="disaster_recovery")
Available tools
| Tool | Description | Approval level |
|---|---|---|
| sdd.bug_fix | Full bug fix workflow | AUTO |
| sdd.hotfix | Retrospective hotfix documentation | POST_HOC |
| sdd.refactoring | Refactoring with dependency verification | REVIEW |
| sdd.deprecate | Deprecation with migration plan | APPROVAL |
| sdd.enterprise | migration, experiment, flag, tenant, security_audit, scalability, compliance, monitoring, dashboard, incident, sla, cost, docs, onboarding, knowledge_transfer, disaster_recovery, config_drift, workflow_export | per action |
Usage examples
# Bug fix (automatic approval)
sdd.bug_fix(description: "Login returns 500", files: ["src/auth.ts"], severity: "high")
# Hotfix (emergency)
# 1. Enforcement is disabled automatically
# 2. Apply the fix
# 3. Document retroactively:
sdd.hotfix(description: "System is down", files: ["src/server.ts"], urgency: "critical")
# Refactoring
sdd.refactoring(target: "auth", description: "Extract validation", type: "extract", files: ["src/auth.ts"])
# Deprecation
sdd.deprecate(target: "/api/v1/users", removal_date: "2025-12-31", endpoints: ["/api/v1/users"])
# Migration
sdd.enterprise(action: "migration", source: "users_v1", target: "users_v2", description: "Add email field")
# A/B Testing
sdd.enterprise(action: "experiment",
hypothesis: "New button increases conversion",
variants: [
{ name: "control", description: "Blue button", traffic_percentage: 50 },
{ name: "variant", description: "Green button", traffic_percentage: 50 }
],
metric: "conversion_rate",
duration: 14
)
# Feature Flag
sdd.enterprise(action: "flag", name: "new_dashboard", description: "New dashboard", rollout: 10)
# Multi-tenancy
sdd.enterprise(action: "tenant", name: "acme_corp", type: "shared_database", isolation: "row")
# Onboarding
sdd.enterprise(action: "onboarding", developer_name: "John")
# Security Audit
sdd.enterprise(action: "security_audit")
# Scalability Analysis
sdd.enterprise(action: "scalability")
# Compliance
sdd.enterprise(action: "compliance", standard: "GDPR")
sdd.enterprise(action: "compliance", standard: "LGPD")
# Monitoring
sdd.enterprise(action: "monitoring")
# Incident Management
sdd.enterprise(action: "incident", title: "System is down", severity: "SEV1", impact: "All users affected")
# SLA
sdd.enterprise(action: "sla", name: "Uptime", metric: "availability", target: 99.9, period: "monthly")
# Cost Estimation
sdd.enterprise(action: "cost")
# Documentation
sdd.enterprise(action: "docs", type: "api")
# Knowledge Transfer
sdd.enterprise(action: "knowledge_transfer")
# Disaster Recovery
sdd.enterprise(action: "disaster_recovery")
# Dashboard Generation
sdd.enterprise(action: "dashboard", type: "overview")Project structure
src/
├ index.ts # Plugin entry point (synchronous init — no HTTP await)
├ version.ts # PLUGIN_VERSION + GRAPH_SCHEMA_VERSION (generated by scripts/sync-version.cjs)
├ server-entry.ts # "./server" subpath with utilities (createMcpServer, dashboard, analyzeCodebase)
├ sdd/
│ ├── domain/types.ts # Node types + relationships + graphs
│ ├── graph/ # Knowledge Graph CRUD and navigation
│ │ ├── index.ts # In-memory graph indices (byId, byType, byStatus, inverted)
│ │ ├── engine.ts # Engines / integrity
│ │ ├── traverse.ts # BFS, impact analysis, pathfinding
│ │ ├── integrity.ts / integrity-guard.ts / pruner.ts
│ ├── persistence/ # Storage backends
│ │ ├── yaml.ts # YAML repositories + snapshots
│ │ ├── sqlite.ts # SQLite backend (1000+ nodes)
│ │ └── repository.ts # Repository abstraction
│ ├── discovery/ # Briefing analysis + questions
│ │ ├── briefing.ts # Briefing analysis
│ │ ├── briefing-analyzer.ts # Tech stack detection
│ │ ├── adaptive.ts # Adaptive discovery
│ │ └── graph-builder.ts # Graph construction
│ ├── changes/manager.ts # Change management + approval gates
│ ├── validation/ # Structural/semantic validation
│ │ ├── validator.ts # Main validator
│ │ ├── smart-validator.ts # Smart per-subsystem validation
│ │ ├── executable.ts / coverage-index.ts
│ ├── drift/ # Drift detection
│ │ ├── detector.ts # Spec ↔ code drift
│ │ ├── signals.ts # Advanced drift signals
│ │ └── exclusion.ts # Drift whitelist
│ ├── enforcement/interceptor.ts # Enforces the SDD-first workflow
│ │ └── workflow-tracker.ts # Per-session workflow tracking
│ ├── codegen/generator.ts # Built-in templates + spec prompt for AI
│ ├── toggle/state.ts # SDD enforcement on/off
│ ├── cache/ # Cache (memory + persistent + lock)
│ │ ├── manager.ts / atomic.ts / fingerprint.ts / snapshot-store.ts
│ ├── constitution/validator.ts # Principle validation
│ ├── promises/ # Promise tracking
│ │ ├── tracker.ts / classifier.ts
│ ├── quality/scorer.ts # Quality score with trend
│ ├── session/handoff.ts # Session handoff
│ ├── patterns/ # Anti-pattern detection
│ │ ├── anti-patterns.ts / ast-clones.ts / contradictions.ts / config-drift.ts / learner.ts
│ ├── coverage/tracker.ts # Test coverage
│ ├── workflow/exporter.ts # Workflow export
│ ├── brownfield/scanner.ts # Existing project analysis
│ ├── cicd/generators.ts # CI/CD generation (GitHub, GitLab, Jenkins, Docker)
│ ├── sync/git-sync.ts # Git sync + conflicts
│ ├── rollback/manager.ts # 3-layer rollback (git → snapshot → backup)
│ ├── permissions/access.ts # Access control + audit
│ ├── migrations/ # SDD migrations
│ │ ├── fixes.ts / index.ts / migration-runner.ts
│ ├── code-quality/ # Code quality
│ │ ├── complexity.ts / metrics.ts / smells.ts / dependencies.ts
│ │ ├── symbol-parser.ts / usage-tracker.ts / import-analyzer.ts / conventions.ts / utils.ts
│ ├── security/paths.ts # Project path assertion (rejects traversal, symlink escapes)
│ ├── workflows/ # Enterprise workflows
│ │ ├── bug-fix.ts / hotfix.ts / refactoring.ts / deprecation.ts / data-migration.ts
│ │ ├── ab-testing.ts / feature-flags.ts / multi-tenancy.ts / onboarding.ts
│ ├── analysis/ # Audits
│ │ ├── security.ts / scalability.ts / compliance.ts
│ ├── monitoring/ # Monitoring
│ │ ├── setup.ts / telemetry.ts
│ ├── incidents/manager.ts # Incident management
│ ├── sla/tracker.ts # SLA tracking
│ ├── cost/estimator.ts # Cost estimation
│ ├── documentation/generator.ts # Documentation generation
│ ├── knowledge/transfer.ts # Knowledge transfer
│ ├── disaster/recovery.ts # Disaster recovery plan
│ ├── tasks/board.ts # Kanban board domain over `task` nodes
│ ├── tasks/change-bridge.ts # Task → SDD Change bridge (code authorisation)
│ ├── transactions/manager.ts # Logical transactions
│ ├── project-dir.ts # Project directory resolution (rejects "/")
│ └── log.ts # Plugin debug log
├ opencode/
│ ├── tools.ts # Tools for the agent
│ ├── hooks.ts # OpenCode hooks (including cache restore with try/catch)
│ ├── command.ts # "sdd" command hub (command.execute.before)
│ ├── system-prompt.ts # SDD instructions + question tool integration
│ ├── shell-hooks.ts # Git hooks for SDD
│ ├── router/ # Semantic tool routing
│ │ ├── index.ts / categories.ts / intent-classifier.ts / state-gate.ts
│ │ ├── tool-registry.ts / tool-taxonomy.ts / tools-composite.ts
│ │ ├── graph-state-snapshot.ts / embeddings.ts
│ └── workflows/ # Opencode workflow executor
│ ├── index.ts / chains.ts / executor.ts / tools-workflow.ts / types.ts
├ mcp/
│ └── server.ts # MCP server
├ code-intelligence/
│ ├── analyzer.ts # Code analysis
│ └── ast/ # AST (tree-sitter + fallback)
│ ├── index.ts / cache.ts / common.ts / component.ts / fallback.ts / ir.ts / metrics.ts
│ └── registry.ts / tree-sitter.ts / typescript.ts
└ server/
├── server.ts # Web dashboard (API + UI)
├── tasks-api.ts # Kanban task API (create/update/move/delete/change)
├── dashboard-context.ts # Dashboard ↔ agent bridge (integration + code prompts)
├── ui/
│ └── kanban-view.ts # Kanban style, modal and script
└── events.ts # Dashboard events.sdd/ structure
When initialized, the plugin creates:
.sdd/
├ graph.yaml # The complete Knowledge Graph
├ enabled # Toggle state (JSON: {enabled, changed_at})
├ nodes/ # Individual nodes (future)
├ relationships/ # Relationships (future)
├ changes/ # Change history
├ snapshots/ # State snapshots
└ transactions/ # Logical transactionsDevelopment
# Install dependencies
bun install
# Verify types
bun run typecheck
# Compile (generates dist/)
bun run build
# Lint (noUnusedLocals/noUnusedParameters)
bun run lint
# Run tests
bun testLicense
MIT
