Spec-Driven Development Workflow
This is the architecture reference — see Getting Started for setup and your first change, and End-to-End Walkthrough for a complete concrete example.
Overview
This workspace uses a spec-driven development workflow that combines:
- OpenSpec — Structured specifications alongside code
- Tracking issues on Codeberg / Gitea / Forgejo (primary, under the
Conductionorg as of 2026-05-29) or GitHub (secondary/fallback) — visual progress tracking via per-repo project boards or kanban - Spec verification — Automated review of code against specifications
Platform note. Conduction is migrating from github.com/ConductionNL/* to codeberg.org/Conduction/*. Skills and Hydra-pipeline scripts auto-detect the per-repo platform from git remote get-url origin; opsx-* skills create tracking issues on whichever host the target repo lives. The migration is bidirectional — every operation also supports GitHub fallback so the system can revert if needed.
The key insight: specs are written once, then broken into small JSON tasks that each point back to a specific spec section. This means AI coding loops can work with minimal context (just the task + its spec ref) instead of loading entire spec documents.
Architecture
All specs and changes live in their primary app repository (submodule). Skills and shared config (schemas, company-wide ADRs) live in the hydra repo inside apps-extra. Developer documentation lives in the .github repo (~/.github).
apps-extra/ # Workspace root
├── project.md # Generic guidelines (all projects)
├── hydra/ # Automation, skills & shared config
│ ├── .claude/
│ │ └── skills/ # OpenSpec skills (opsx-new, opsx-ff, etc.)
│ └── openspec/
│ ├── architecture/ # Company-wide ADRs
│ └── schemas/conduction/ # Shared workflow schema
│
├── openregister/ # FOUNDATION REPO
│ ├── project.md # Project description & context
│ └── openspec/
│ ├── config.yaml # Project config
│ ├── specs/ # Domain + shared specs
│ │ ├── nextcloud-app/ # Shared: NC app conventions
│ │ ├── api-patterns/ # Shared: API conventions
│ │ ├── docker/ # Shared: Docker environment
│ │ ├── release-workflows/ # Shared: Release workflows
│ │ └── ... # Domain specs (registers, schemas, etc.)
│ └── changes/ # Active changes
│ └── add-feature-x/
│ ├── proposal.md # Why & what
│ ├── discovery.md # Research output (optional — uncertain approach)
│ ├── contract.md # API contract (optional — cross-project APIs)
│ ├── specs/ # Delta specs (ADDED/MODIFIED/REMOVED)
│ ├── design.md # How (technical approach)
│ ├── migration.md # DB migration plan (optional — schema changes)
│ ├── test-plan.md # Test cases pre-defined from specs (optional)
│ ├── tasks.md # Implementation checklist
│ ├── plan.json # Task tracking JSON (generated by /opsx-plan-to-issues)
│ └── review.md # Verification report (generated)
│
├── opencatalogi/ # Same openspec/ pattern per app
│ ├── project.md
│ └── openspec/
Primary spec ownership:
openregister(foundation) —nextcloud-app/,api-patterns/,docker/,release-workflows/nldesign—nl-design/pipelinq—pipeline/,pipeline-views/
The Full Flow
Legacy app? This flow assumes the app is spec-first — methods carry
@spectags that/opsx-verifywalks at review time. Apps that predate the convention (ADR-003) need a one-time retrofit pass before normal feature work. See the Retrofit Playbook.
Phase 1: Spec Building
Start by defining what you're building. This creates structured, reviewable specifications.
/opsx-new add-woo-search
This creates openspec/changes/add-woo-search/ with metadata. Then either:
Fast-forward (all at once):
/opsx-ff
Creates proposal → specs → design → tasks in dependency order.
Or incrementally:
/opsx-continue # Creates proposal
/opsx-continue # Creates specs
/opsx-continue # Creates design
/opsx-continue # Creates tasks
Review the artifacts. This is your chance to refine requirements before any code is written. The core artifacts form a dependency chain:
proposal → specs → design → tasks
(why) (what) (how) (steps)
Four optional artifacts can be inserted when needed:
proposal → discovery → specs (use when approach or NC API availability is uncertain)
proposal → contract → specs (use when change introduces API consumed by other projects)
design → migration → tasks (use when change introduces DB/schema changes)
specs → test-plan → tasks (use to pre-define test cases before implementation)
test-plan and test scenarios: A test-plan.md maps spec scenarios to named test cases (TC-1, TC-2, …) before any code is written — it answers "what does done look like?" After implementation, TCs that represent ongoing regression value should be promoted to reusable test scenarios via /test-scenario-create. Those TS-NNN-slug.md files persist after the change is archived and are automatically picked up by /test-counsel, /test-app, and /test-persona-*.
Phase 2: Plan to Tracking Issues
Once specs are reviewed and approved, convert them to trackable work items:
/opsx-plan-to-issues
This command:
- Parses
tasks.mdinto structured JSON - Creates a tracking issue (epic) on the per-repo platform (Codeberg primary, GitHub fallback, GitLab alternative) with a full task checklist
- Creates individual issues per task, each containing:
- Task description
- Acceptance criteria (from spec scenarios)
- Spec reference (link to the relevant spec section)
- Files likely affected
- Labels:
openspec,<change-name>
- Saves
plan.jsonwith all issue numbers linked
Why tracking issues?
- Visual kanban board (per-repo on Codeberg; Codeberg has no cross-repo board yet — see Codeberg Community #694)
- Progress visible to the whole team
- Each issue links back to specs for traceability
- Can be managed independently of Claude sessions
Phase 3: Implementation
Start the focused implementation loop:
/opsx-apply
Automated alternative — /opsx-apply-loop (experimental):
Runs Phases 3 → 4 → 5 in one hands-off command inside an isolated Docker container:
/opsx-apply-loop project add-sla-tracking
/opsx-apply-loop # asks which app + change
The loop runs /opsx-apply → /opsx-verify up to 5 times per app, optionally followed by targeted single-agent tests (max 3 test iterations), then archives when verify is clean and handles git commit and per-platform issue sync on the host. Use this when you want to walk away and let Claude work through the full cycle automatically. Requires a container authentication token — the Docker container cannot use interactive OAuth. Set CLAUDE_CODE_AUTH_TOKEN (preferred — free, uses your subscription) or ANTHROPIC_API_KEY (fallback — costs money) in your ~/.bashrc. See Getting Started — Container authentication for step-by-step setup.
Each iteration of the loop:
- Reads plan.json — finds the next pending task
- Reads ONLY the referenced spec section — via
spec_refpointer - Implements the task — following acceptance criteria, including:
- Backend logic (service/controller)
- UI so users can actually use the feature (Vue component, page, dialog)
- Tests: unit tests (PHPUnit), API tests (Newman/Postman), browser tests (Playwright MCP)
- Runs tests — unit tests, Newman tests, and browser verification MUST pass before marking complete
- Updates progress — marks task done in plan.json and tasks.md
- Closes the tracking issue — with a summary comment (Codeberg/GitHub/GitLab depending on the per-repo platform)
- Moves to the next task — or stops if all done
Why this works:
- Minimal context per iteration (just the task + its spec section)
- No "amnesia" — plan.json tracks state across sessions
- Visual progress — tracking issues close as work completes
- Resumable — if interrupted, picks up where it left off
- Tests catch regressions immediately — before moving to the next task
Phase 4: Review
After all tasks are complete, verify the implementation:
/opsx-verify
This command:
- Reads ALL spec requirements (ADDED/MODIFIED/REMOVED)
- Checks each against the actual implementation
- Cross-references with shared specs (NC conventions, API patterns, etc.)
- Categorizes findings:
- CRITICAL — Must fix (spec requirement not met)
- WARNING — Should fix (partial compliance)
- SUGGESTION — Nice to have
- Generates
review.mdin the change directory - Creates a tracking issue (on the per-repo platform — Codeberg primary, GitHub fallback) if CRITICAL/WARNING findings exist
Phase 5: Archive
Once review passes:
/opsx-archive
This:
- Merges delta specs into the app's
openspec/specs/directory - Moves the change to
openspec/changes/archive/YYYY-MM-DD-<name>/ - Creates or updates
CHANGELOG.mdwith the completed tasks as versioned entries - Preserves full audit trail
The plan.json Format
{
"change": "add-woo-search",
"project": "opencatalogi",
"repo": "Conduction/opencatalogi",
"created": "2026-02-14T12:00:00Z",
"tracking_issue": 42,
"tasks": [
{
"id": 1,
"title": "Add search API endpoint",
"description": "Create /api/woo/search endpoint with query parameter support",
"github_issue": 43,
"status": "pending",
"spec_ref": "openspec/specs/search/spec.md#requirement-search-api",
"acceptance_criteria": [
"GIVEN a search query WHEN GET /api/woo/search?q=test THEN returns matching publications",
"GIVEN no results WHEN searching THEN returns empty array with 200"
],
"files_likely_affected": [
"lib/Controller/SearchController.php",
"lib/Service/SearchService.php"
],
"labels": ["openspec", "add-woo-search"]
}
]
}
Key design decisions:
spec_refusesfile#anchorformat so the AI can read just that sectionacceptance_criteriaare extracted from spec scenarios, ready for verificationfiles_likely_affectedscopes the search space for implementationgithub_issueenables automatic close on completionstatustracks progress across sessions (pending→in_progress→completed)
Spec Writing Guide
See writing-specs.md for the complete guide — RFC 2119 keywords, Gherkin scenario format, delta spec operations (ADDED/MODIFIED/REMOVED/RENAMED), and common mistakes to avoid.
Commands Reference
| Command | Phase | Description |
|---|---|---|
/opsx-new <name> | Spec | Start a new change |
/opsx-ff | Spec | Fast-forward all artifacts |
/opsx-continue | Spec | Create next artifact |
/opsx-plan-to-issues | Plan | Tasks → JSON + tracking issues (per-repo platform — Codeberg primary, GitHub fallback) |
/opsx-apply | Implement | Implement tasks from plan.json |
/opsx-verify | Review | Verify implementation against specs |
/opsx-archive | Archive | Complete and preserve change |
Team Role Commands
Specialist agents representing different roles on the development team. Useful for getting a focused perspective on a change — architecture review, QA, product sign-off, etc.
| Command | Role | Focus |
|---|---|---|
/team-architect | Architect | API design, data models, cross-app dependencies |
/team-backend | Backend Developer | PHP implementation, entities, services, tests |
/team-frontend | Frontend Developer | Vue components, state management, UX |
/team-po | Product Owner | Business value, acceptance criteria, priority |
/team-qa | QA Engineer | Test coverage, edge cases, regression risk |
/team-reviewer | Code Reviewer | Standards, conventions, security, code quality |
/team-sm | Scrum Master | Progress tracking, blockers, sprint health |
Usage:
/team-architect # review the API design for the active change
/team-qa # get QA perspective on test coverage
Model for /team-architect: Checked at run time — stops if on Haiku. Asks which model to use and explains how to switch if the choice differs from the active model. Opus recommended — best multi-framework reasoning across NLGov, BIO2/NIS2, WCAG, Haven, AVG/GDPR. Sonnet not recommended — may miss nuances in complex compliance scenarios.
Tips
- Start small: Try the flow on a small feature first to build muscle memory
- Review specs before coding: The spec review is the most valuable step — catch issues before writing code
- Keep tasks small: Each task should be completable in one focused iteration (15-30 min of work)
- Use shared specs: Reference cross-project specs in your delta specs to avoid reinventing patterns
- Trust the JSON: The plan.json is your source of truth during implementation — it survives context window resets
- The tracking issue is your dashboard: Use the per-repo project board (Codeberg primary, GitHub Projects on legacy repos) to visualize progress across multiple changes and projects. Codeberg has no cross-repo board yet — per-repo only.