devloom 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ai/core.dsl +44 -0
- package/.ai/skills.dsl +39 -0
- package/.ai/verify.dsl +97 -0
- package/.ai/workflow.dsl +81 -0
- package/.opencode/themes/devloom-night-owl.json +103 -0
- package/GUIDE.md +572 -115
- package/README.md +583 -109
- package/SECURITY.md +93 -0
- package/agents/devloom-developer-flash.md +31 -0
- package/agents/devloom-developer-senior.md +32 -0
- package/agents/devloom-developer.md +21 -55
- package/agents/devloom-documenter-flash.md +28 -0
- package/agents/devloom-documenter.md +17 -56
- package/agents/devloom-orchestrator.md +236 -356
- package/agents/devloom-planner-flash.md +34 -0
- package/agents/devloom-planner-senior.md +35 -0
- package/agents/devloom-planner.md +36 -0
- package/agents/devloom-qa-flash.md +32 -0
- package/agents/devloom-qa.md +21 -83
- package/agents/devloom-security-senior.md +35 -0
- package/agents/devloom-security.md +34 -0
- package/agents/devloom-verifier.md +33 -0
- package/agents/devloom-vision.md +113 -0
- package/agents/devloom-visual-critic.md +102 -0
- package/agents/devloom-visual-director.md +84 -0
- package/commands/devloom-agents.md +49 -0
- package/commands/devloom-auto.md +11 -0
- package/commands/devloom-context.md +82 -0
- package/commands/devloom-deepseek-mimo.md +11 -0
- package/commands/devloom-deepseek.md +11 -0
- package/commands/devloom-free.md +11 -0
- package/commands/devloom-go-economy.md +11 -0
- package/commands/devloom-go-flash.md +11 -0
- package/commands/devloom-go.md +11 -0
- package/commands/devloom-init.md +28 -50
- package/commands/devloom-loop-status.md +25 -0
- package/commands/devloom-loop.md +36 -0
- package/commands/devloom-mimo.md +11 -0
- package/commands/devloom-plan.md +13 -0
- package/commands/devloom-refresh.md +22 -0
- package/commands/devloom-resume.md +30 -49
- package/commands/devloom-save.md +69 -0
- package/commands/devloom-status.md +9 -18
- package/commands/devloom.md +99 -67
- package/dist/agents.d.ts +30 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +139 -0
- package/dist/agents.js.map +1 -0
- package/dist/bootstrap.d.ts +56 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +116 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/constraints.d.ts +5 -0
- package/dist/constraints.d.ts.map +1 -0
- package/dist/constraints.js +45 -0
- package/dist/constraints.js.map +1 -0
- package/dist/context.d.ts +42 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +636 -0
- package/dist/context.js.map +1 -0
- package/dist/guard.d.ts +19 -0
- package/dist/guard.d.ts.map +1 -0
- package/dist/guard.js +418 -0
- package/dist/guard.js.map +1 -0
- package/dist/loop.d.ts +64 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +164 -0
- package/dist/loop.js.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +101 -1
- package/dist/plugin.js.map +1 -1
- package/dist/tui-agents.d.ts +61 -0
- package/dist/tui-agents.d.ts.map +1 -0
- package/dist/tui-agents.js +89 -0
- package/dist/tui-agents.js.map +1 -0
- package/dist/tui.d.ts +6 -0
- package/dist/tui.d.ts.map +1 -0
- package/dist/tui.js +92 -0
- package/dist/tui.js.map +1 -0
- package/dist/worktree.d.ts +46 -0
- package/dist/worktree.d.ts.map +1 -0
- package/dist/worktree.js +272 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +46 -6
- package/patterns/changelog-drafter.md +38 -0
- package/patterns/ci-sweeper.md +40 -0
- package/patterns/daily-triage.md +37 -0
- package/patterns/dependency-sweeper.md +40 -0
- package/patterns/design-audit.md +63 -0
- package/patterns/issue-triage.md +37 -0
- package/patterns/post-merge-cleanup.md +34 -0
- package/patterns/pr-babysitter.md +37 -0
- package/patterns/registry.yaml +52 -0
- package/postinstall.mjs +264 -64
- package/project/README.md +29 -0
- package/protocol/agent-contracts.md +27 -0
- package/protocol/artifact-system.md +53 -0
- package/protocol/model-routing.md +194 -0
- package/protocol/orchestrator-core.md +43 -0
- package/protocol/project-system.md +45 -0
- package/protocol/rules.md +18 -0
- package/protocol/verification-policy.md +48 -0
- package/scripts/briefing.mjs +192 -0
- package/scripts/loop-run.mjs +205 -0
- package/scripts/model-capabilities.mjs +194 -0
- package/scripts/plugin-cache.mjs +269 -0
- package/scripts/profile.mjs +755 -0
- package/scripts/visual-benchmark.mjs +149 -0
- package/scripts/worktree.mjs +445 -0
- package/skills/build/development.md +33 -0
- package/skills/build/live-docs.md +38 -0
- package/skills/build/simplify.md +50 -0
- package/skills/build/vision-analysis.md +98 -0
- package/skills/design/app-design.md +31 -0
- package/skills/design/design-grounding.md +30 -0
- package/skills/design/design-system.md +27 -0
- package/skills/design/game-design.md +35 -0
- package/skills/design/motion-design.md +34 -0
- package/skills/design/visual-direction.md +32 -0
- package/skills/design/web-design.md +33 -0
- package/skills/loop/changelog-drafter.md +32 -0
- package/skills/loop/ci-sweeper.md +24 -0
- package/skills/loop/constraints.md +21 -0
- package/skills/loop/dependency-sweeper.md +24 -0
- package/skills/loop/design-audit.md +67 -0
- package/skills/loop/issue-triage.md +27 -0
- package/skills/loop/post-merge-cleanup.md +24 -0
- package/skills/loop/pr-babysitter.md +26 -0
- package/skills/loop/triage.md +25 -0
- package/skills/loop/verifier.md +20 -0
- package/skills/meta/skill-discovery.md +23 -0
- package/skills/plan/planning.md +27 -0
- package/skills/plan/verification-planning.md +40 -0
- package/skills/review/security-review.md +63 -0
- package/skills/ship/documentation.md +11 -0
- package/skills/verify/app-verification.md +19 -0
- package/skills/verify/quality-assurance.md +17 -0
- package/skills/verify/visual-critique.md +30 -0
- package/skills/verify/visual-quality-gate.md +29 -0
- package/skills/verify/visual-regression.md +25 -0
- package/agents/devloom-analyst.md +0 -83
- package/agents/devloom-architect.md +0 -88
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# DevLoom Model Routing Profiles
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Model routing assigns a specific language model to each agent role. Different models offer different trade-offs between reasoning quality, context, cost, and speed. Profiles let users pick the right balance without changing agent logic.
|
|
6
|
+
|
|
7
|
+
Each of the 10 DevLoom agents (orchestrator, planner, developer, qa, verifier, security, documenter, vision, visual-director, visual-critic) receives a model from the active profile. The orchestrator applies these when dispatching tasks. In every profile the `visual-director` and `visual-critic` roles resolve through the same model as `vision`.
|
|
8
|
+
|
|
9
|
+
## How Profile Selection Works
|
|
10
|
+
|
|
11
|
+
1. Profile is read from `.opencode/devloom/project/config.json` under `modelRouting`.
|
|
12
|
+
2. Default: `go-flash` (deepseek-v4-flash for every role except vision).
|
|
13
|
+
3. Override per task via `--model` flag or `OPENCODE_MODEL_OVERRIDE` env var.
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{ "modelRouting": "go" }
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Profiles
|
|
20
|
+
### go (max quality)
|
|
21
|
+
The highest quality profile for production work. Orchestrator uses DeepSeek V4 Flash (cheapest — runs every turn; vision delegated to `devloom-vision`). Qwen 3.7 Max to planner (strong reasoning), Kimi K2.7 Code to implementation, GLM 5.2 to security (forensic depth), DeepSeek V4 Pro to QA/verifier, Qwen 3.7 Plus to documentation, Qwen 3.6 Plus to vision (low-cost multimodal).
|
|
22
|
+
|
|
23
|
+
| Role | Model |
|
|
24
|
+
|---|---|
|
|
25
|
+
| orchestrator | opencode-go/deepseek-v4-flash |
|
|
26
|
+
| planner | opencode-go/qwen3.7-max |
|
|
27
|
+
| developer | opencode-go/kimi-k2.7-code |
|
|
28
|
+
| qa | opencode-go/deepseek-v4-pro |
|
|
29
|
+
| verifier | opencode-go/deepseek-v4-pro |
|
|
30
|
+
| security | opencode-go/glm-5.2 |
|
|
31
|
+
| documenter | opencode-go/qwen3.7-plus |
|
|
32
|
+
| vision | opencode-go/qwen3.6-plus |
|
|
33
|
+
|
|
34
|
+
### go-economy
|
|
35
|
+
A lower cost profile that retains Kimi K2.7 Code for the developer role and uses DeepSeek V4 Pro for orchestrator, qa, verifier, and security roles. Qwen 3.6 Plus handles documentation at reduced cost. Suitable for routine development work where premium reasoning is not essential.
|
|
36
|
+
|
|
37
|
+
| Role | Model |
|
|
38
|
+
|---|---|
|
|
39
|
+
| orchestrator | opencode-go/deepseek-v4-pro |
|
|
40
|
+
| planner | opencode-go/kimi-k2.7-code |
|
|
41
|
+
| developer | opencode-go/kimi-k2.7-code |
|
|
42
|
+
| qa | opencode-go/deepseek-v4-pro |
|
|
43
|
+
| verifier | opencode-go/deepseek-v4-pro |
|
|
44
|
+
| security | opencode-go/deepseek-v4-pro |
|
|
45
|
+
| documenter | opencode-go/qwen3.6-plus |
|
|
46
|
+
| vision | opencode-go/qwen3.6-plus |
|
|
47
|
+
|
|
48
|
+
### go-flash
|
|
49
|
+
All agents on DeepSeek V4 Flash for maximum throughput at minimum cost. Vision uses Qwen 3.6 Plus (multimodal).
|
|
50
|
+
|
|
51
|
+
| Role | Model |
|
|
52
|
+
|---|---|
|
|
53
|
+
| orchestrator | opencode-go/deepseek-v4-flash |
|
|
54
|
+
| planner | opencode-go/deepseek-v4-flash |
|
|
55
|
+
| developer | opencode-go/deepseek-v4-flash |
|
|
56
|
+
| qa | opencode-go/deepseek-v4-flash |
|
|
57
|
+
| verifier | opencode-go/deepseek-v4-flash |
|
|
58
|
+
| security | opencode-go/deepseek-v4-flash |
|
|
59
|
+
| documenter | opencode-go/deepseek-v4-flash |
|
|
60
|
+
| vision | opencode-go/qwen3.6-plus |
|
|
61
|
+
|
|
62
|
+
### deepseek
|
|
63
|
+
All DeepSeek V4 Pro agents (consistent provider affinity). Vision uses DeepSeek V4 Flash Vision Exp (cheapest vision-capable DeepSeek model: 0.22 input / 0.66 output vs Qwen 3.6 Plus 0.5/3).
|
|
64
|
+
|
|
65
|
+
| Role | Model |
|
|
66
|
+
|---|---|
|
|
67
|
+
| orchestrator | opencode-go/deepseek-v4-pro |
|
|
68
|
+
| planner | opencode-go/deepseek-v4-pro |
|
|
69
|
+
| developer | opencode-go/deepseek-v4-pro |
|
|
70
|
+
| qa | opencode-go/deepseek-v4-pro |
|
|
71
|
+
| verifier | opencode-go/deepseek-v4-pro |
|
|
72
|
+
| security | opencode-go/deepseek-v4-pro |
|
|
73
|
+
| documenter | opencode-go/deepseek-v4-pro |
|
|
74
|
+
| vision | opencode-go/deepseek-v4-flash-vision-exp |
|
|
75
|
+
|
|
76
|
+
### free
|
|
77
|
+
A zero-cost profile using only freely available models. Intended for experimentation, open-source projects, learning, and low-stakes development where cost must be zero. All agents use the best available free-tier model. If a specific free model is unavailable, the fallback chains are: orchestration: opencode/big-pickle -> opencode/muse-spark-1.3-contributor-free -> opencode/mimo-v2.5-free -> opencode/muse-spark-1.2-contributor-free -> opencode/nemotron-3.5-lightning-free -> opencode/nemotron-3-ultra-free -> opencode/ling-3.0-flash-fin-free; implementation/verification: opencode/big-pickle -> opencode/muse-spark-1.3-contributor-free -> opencode/nemotron-3.5-lightning-free -> opencode/mimo-v2.5-free -> opencode/nemotron-3-ultra-free -> opencode/ling-3.0-flash-fin-free; planning: opencode/nemotron-3-ultra-free -> opencode/muse-spark-1.3-contributor-free -> opencode/muse-spark-1.2-contributor-free -> opencode/big-pickle -> opencode/nemotron-3.5-lightning-free -> opencode/ling-3.0-flash-fin-free; documentation: opencode/muse-spark-1.3-contributor-free -> opencode/muse-spark-1.2-contributor-free -> opencode/nemotron-3-ultra-free -> opencode/mimo-v2.5-free -> opencode/ling-3.0-flash-fin-free; vision: opencode/mimo-v2.5-free -> opencode-go/deepseek-v4-flash-vision-exp -> opencode-go/minimax-m3 -> opencode-go/mimo-v2.5-pro (paid fallbacks ordered by cost, cheapest first: deepseek 0.22/0.66 < minimax 0.3/1.2 < mimo-pro 0.435/0.87).
|
|
78
|
+
|
|
79
|
+
| Role | Model |
|
|
80
|
+
|---|---|
|
|
81
|
+
| orchestrator | opencode/big-pickle |
|
|
82
|
+
| planner | opencode/nemotron-3-ultra-free |
|
|
83
|
+
| developer | opencode/big-pickle |
|
|
84
|
+
| qa | opencode/big-pickle |
|
|
85
|
+
| verifier | opencode/big-pickle |
|
|
86
|
+
| security | opencode/big-pickle |
|
|
87
|
+
| documenter | opencode/muse-spark-1.2-contributor-free |
|
|
88
|
+
| vision | opencode/mimo-v2.5-free |
|
|
89
|
+
|
|
90
|
+
### mimo (locked tier)
|
|
91
|
+
|
|
92
|
+
A single multimodal stack: every role — including vision, visual-director, and visual-critic — resolves to the first available MiMo V2.6 Flash candidate from the chain `mimo/mimo-v2.6-flash` -> `xiaomi/mimo-v2.6-flash` -> `opencode-go/mimo-v2.6-flash`, checked against `opencode models`. `opencode/mimo-v2.6-flash-free` is deliberately excluded from free chains. If no candidate is available the profile is NOT activated: `profile.mjs` exits with code 1 and prints the attempted candidates — never an unrelated substitution. Tier overrides are locked for this profile. Activate with `/devloom-mimo`.
|
|
93
|
+
|
|
94
|
+
| Role | Model |
|
|
95
|
+
|---|---|
|
|
96
|
+
| all 10 roles | resolved MiMo V2.6 Flash candidate |
|
|
97
|
+
|
|
98
|
+
### deepseek-mimo (hybrid, tier unlocked)
|
|
99
|
+
|
|
100
|
+
Fast everyday work on DeepSeek V4.1 Flash; graphical/complex work on MiMo V2.6 Flash. The 7 general roles (orchestrator, planner, developer, qa, verifier, security, documenter) resolve to `opencode-go/deepseek-v4.1-flash`; vision, visual-director, and visual-critic resolve through the `MIMO_V26_FLASH_CANDIDATES` chain. Both chains resolve strictly against `opencode models` — if either finds nothing the profile exits code 1 with the attempted candidates, never an unrelated substitution. Activate with `/devloom-deepseek-mimo`.
|
|
101
|
+
|
|
102
|
+
| Role | Model |
|
|
103
|
+
|---|---|
|
|
104
|
+
| 7 general roles | opencode-go/deepseek-v4.1-flash |
|
|
105
|
+
| vision, visual-director, visual-critic | resolved MiMo V2.6 Flash candidate |
|
|
106
|
+
|
|
107
|
+
## Model Guidance
|
|
108
|
+
|
|
109
|
+
### When to Use GLM 5.2
|
|
110
|
+
|
|
111
|
+
GLM 5.2 (opencode-go/glm-5.2) provides the strongest reasoning and planning capabilities among available models. It is the best choice when a task requires:
|
|
112
|
+
|
|
113
|
+
- Architectural design and system decomposition
|
|
114
|
+
- Requirements analysis and specification writing
|
|
115
|
+
- UX-aware decisions that balance user experience with technical constraints
|
|
116
|
+
- Multi-step planning with dependency management
|
|
117
|
+
- High-stakes decisions where incorrect reasoning would be costly
|
|
118
|
+
|
|
119
|
+
In practice, GLM 5.2 should be assigned to the orchestrator, planner, and any agent that makes strategic decisions. For UI/UX-heavy Angular or React SaaS frontend work, GLM 5.2 delivers superior reasoning around component hierarchies, state management patterns, accessibility, and user flow design.
|
|
120
|
+
|
|
121
|
+
### When to Use Kimi K2.7 Code
|
|
122
|
+
|
|
123
|
+
Kimi K2.7 Code (opencode-go/kimi-k2.7-code) offers strong code generation quality with a large context window. Successor to K2.6 with fewer hallucinations and better long-context adherence. Ideal for multi-file changes, refactors, code exploration, deep bug fixes, and backend work that needs to hold many services/schemas in context simultaneously. Primary workhorse for the developer role in the go and go-economy profiles.
|
|
124
|
+
|
|
125
|
+
### When to Use Kimi K3 (Senior Developer)
|
|
126
|
+
|
|
127
|
+
Kimi K3 (opencode-go/kimi-k3) is the newest Kimi generation. It is the model assigned to the `senior` tier for the developer role when the orchestrator classifies the prompt as complex (architecture change, large refactor, deep debugging, security-sensitive implementation). It offers stronger code reasoning and longer context than K2.7 Code.
|
|
128
|
+
|
|
129
|
+
### When to Use MiniMax M3 (Multimodal)
|
|
130
|
+
|
|
131
|
+
MiniMax M3 (opencode-go/minimax-m3) is multimodal but is not the default in any current profile. The `devloom-vision` agent uses Qwen 3.6 Plus (multimodal, lower cost). MiniMax M3 may still be used as a vision fallback if Qwen 3.6 Plus is unavailable. Use it directly only when you need a multimodal model with no vision delegation overhead.
|
|
132
|
+
|
|
133
|
+
### When to Use DeepSeek V4 Pro
|
|
134
|
+
|
|
135
|
+
DeepSeek V4 Pro (opencode-go/deepseek-v4-pro) excels at structured, analytical tasks. It is the default qa and verifier in the go profile, and the default for most roles in `deepseek` and `go-economy`, because these roles benefit from precision over open-ended reasoning.
|
|
136
|
+
|
|
137
|
+
Best uses: planning, verification, writing/running tests, debugging, root-cause analysis, regression reviews.
|
|
138
|
+
|
|
139
|
+
### When to Use DeepSeek V4 Flash
|
|
140
|
+
|
|
141
|
+
DeepSeek V4 Flash (opencode-go/deepseek-v4-flash) is the cheapest Go model. It is the default orchestrator in the go and go-economy profiles because the orchestrator runs every turn and accumulates the highest token volume. Vision is delegated to `devloom-vision` (Qwen 3.6 Plus), so the orchestrator does not need multimodal capability. It is also the default for every role in the `go-flash` profile.
|
|
142
|
+
|
|
143
|
+
### When to Use Qwen Models
|
|
144
|
+
|
|
145
|
+
Qwen 3.7 Plus (opencode-go/qwen3.7-plus) is the latest Qwen model — documentation, analysis, code summarization. Qwen 3.7 Max (opencode-go/qwen3.7-max) is the planner in the `go` profile for strong reasoning. Qwen 3.6 Plus (opencode-go/qwen3.6-plus) is the default multimodal model for the `devloom-vision` agent — lowest-cost multimodal option on the OpenCode Go plan.
|
|
146
|
+
|
|
147
|
+
### When to Use Free Tier Models
|
|
148
|
+
|
|
149
|
+
Free models (opencode/big-pickle, opencode/nemotron-3-ultra-free, opencode/nemotron-3.5-lightning-free, opencode/mimo-v2.5-free, opencode/muse-spark-1.3-contributor-free, opencode/muse-spark-1.2-contributor-free, opencode/ling-3.0-flash-fin-free) are suitable only when cost must be zero — experimentation, learning, or evaluation. They have lower reasoning capability than paid Go models in some roles, not recommended for production work. The `vision` role always resolves to a vision-capable model (mimo-v2.5-free on the free tier, with DeepSeek V4 Flash Vision Exp as cheapest paid fallback).
|
|
150
|
+
|
|
151
|
+
## Frontend vs Backend Guidance
|
|
152
|
+
|
|
153
|
+
**UI/UX-heavy frontend (Angular, React, SaaS):** component decomposition, state management, accessibility, responsive layout, and user-flow decisions benefit from strong reasoning rather than large context. Use DeepSeek V4 Pro (planner) for planning, architecture, and review; Kimi K2.7 Code for implementation when the task spans many files.
|
|
154
|
+
|
|
155
|
+
**Backend and data-intensive work:** context size matters more than peak reasoning. Use Kimi K2.7 Code for backend implementation roles — its large context window holds services, database schemas, API contracts, and data pipelines without truncation.
|
|
156
|
+
|
|
157
|
+
## Configuration and Overrides
|
|
158
|
+
|
|
159
|
+
### Setting the Profile
|
|
160
|
+
|
|
161
|
+
In `.opencode/devloom/project/config.json`:
|
|
162
|
+
|
|
163
|
+
```json
|
|
164
|
+
{
|
|
165
|
+
"modelRouting": "go"
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Valid values: `"go"`, `"go-economy"`, `"deepseek"`, `"go-flash"`, `"free"`, `"mimo"`, `"deepseek-mimo"`.
|
|
170
|
+
|
|
171
|
+
### Overrides
|
|
172
|
+
|
|
173
|
+
Per-task: `opencode task --model opencode-go/glm-5.2 "implement feature"`. Environment: set `OPENCODE_MODEL_OVERRIDE=<model-id>` to force every agent onto one model — it takes precedence over both the profile and the `--model` flag.
|
|
174
|
+
|
|
175
|
+
### Per-Role Override in Config
|
|
176
|
+
|
|
177
|
+
Individual role assignments can be overridden by adding a `modelRoutingOverrides` object in config.json:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"modelRouting": "go-economy",
|
|
182
|
+
"modelRoutingOverrides": {
|
|
183
|
+
"developer": "opencode-go/glm-5.2",
|
|
184
|
+
"qa": "opencode-go/kimi-k2.7-code"
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Overrides merge on top of the selected profile and take precedence for the specified roles.
|
|
190
|
+
|
|
191
|
+
### Sidebar visibility and plugin cache
|
|
192
|
+
|
|
193
|
+
The sidebar reflects the active profile via the plugin `config` hook, which injects all 17 agents, renders a `DevLoom - {profile}` header, and shows the resolved model next to every agent row. The orchestrator agent description carries the profile label — e.g. `DevLoom Orchestrator: autonomous multi-agent delivery (profile: go-flash)`, extended to `(profile: go, tier: senior)` when the senior tier is active. The sidebar lists only the 10 base agents: all `-flash` and `-senior` variants are hidden for every profile, yet all 17 stay registered so `task()` routing is unaffected.
|
|
194
|
+
OpenCode installs npm plugins into `~/.cache/opencode/packages/` with `ignoreScripts`, so the cached copy can go stale and the hook never runs. Run `/devloom-refresh` after installing/updating DevLoom or switching profiles — it rebuilds `dist/` from source before refreshing the cache — then restart opencode (or `opencode --continue`) to see the updated profile and agents in the sidebar.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Orchestrator Core
|
|
2
|
+
|
|
3
|
+
LOAD: ~/.config/opencode/devloom-ai/core.dsl|~/.config/opencode/devloom-ai/workflow.dsl
|
|
4
|
+
|
|
5
|
+
SM:
|
|
6
|
+
`IDLE>TRIAGE>CHAIN[step1..stepN]>GATE>DONE`
|
|
7
|
+
|
|
8
|
+
TRIAGE:
|
|
9
|
+
- classify prompt intent, select minimal chain from workflow.dsl CHAINS
|
|
10
|
+
- append COND_ADDONS only when their condition holds
|
|
11
|
+
- full pipeline only when intent=feature with UI+API+flows touched
|
|
12
|
+
- orchestrator routes+persists only; chain steps run in subagents
|
|
13
|
+
|
|
14
|
+
STATE:
|
|
15
|
+
- LEGACY=.opencode/devloom/state.json
|
|
16
|
+
- BOARD=.opencode/devloom/project/board.json
|
|
17
|
+
- PSTATE=.opencode/devloom/project/state.json
|
|
18
|
+
|
|
19
|
+
RULES:
|
|
20
|
+
- COMPLIANCE: you MUST follow every rule in this file and every LOADed file. No rule may be skipped or abbreviated.
|
|
21
|
+
- COMPLIANCE: you MUST verify every sub-agent output against the protocol gates defined in this file. Reject non-compliant results and re-delegate.
|
|
22
|
+
- load BOARD+PSTATE every prompt
|
|
23
|
+
- load memory context and relevant skills every prompt before planning
|
|
24
|
+
- if board.cols.doing is non-empty: queue the new prompt (append to backlog + TODO.md), set phase=queued, do NOT triage or execute
|
|
25
|
+
- append the current prompt as the last task/todo before execution (only when doing is empty)
|
|
26
|
+
- continue pending work first
|
|
27
|
+
- single active ticket — new prompts queue behind current work unless explicitly overridden
|
|
28
|
+
- orchestrator may invoke any DevLoom subagent automatically when the phase requires it
|
|
29
|
+
- orchestrator must delegate specialist phase work to the matching DevLoom subagent when one exists
|
|
30
|
+
- orchestrator must invoke devloom-security for CRUD endpoint work and for any change that exposes internal component/module input or output
|
|
31
|
+
- orchestrator keeps routing and state ownership; subagents do the phase-specific execution
|
|
32
|
+
- orchestrator updates tickets, todos, and plan artifacts on each state transition
|
|
33
|
+
- orchestrator saves state before reprioritization, pause, and completion
|
|
34
|
+
- all artifacts EN
|
|
35
|
+
- official docs + latest stable check before stack-specific plan/code
|
|
36
|
+
- defect => developer(rootCauseFix)>qa(regr)
|
|
37
|
+
- max3 fix cycles per defect, then mark blocked + BLOCKED report
|
|
38
|
+
- max100 steps
|
|
39
|
+
- clear context every 5 completed tasks if needed
|
|
40
|
+
- FILES: never use /tmp, /var/tmp, or system temp — use .opencode/devloom/.tmp/ for temp files and test artifacts
|
|
41
|
+
|
|
42
|
+
EXIT:
|
|
43
|
+
- only DEVLOOM_DONE when all gates pass and no open high/critical defect
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Project System
|
|
2
|
+
|
|
3
|
+
LOAD: ~/.config/opencode/devloom-ai/core.dsl|~/.config/opencode/devloom-ai/workflow.dsl
|
|
4
|
+
|
|
5
|
+
ROOT: `.opencode/devloom/project/`
|
|
6
|
+
|
|
7
|
+
TREE:
|
|
8
|
+
- README.md
|
|
9
|
+
- config.json
|
|
10
|
+
- board.json
|
|
11
|
+
- state.json
|
|
12
|
+
- stories/
|
|
13
|
+
- tasks/
|
|
14
|
+
- bugs/
|
|
15
|
+
- decisions/
|
|
16
|
+
- reports/
|
|
17
|
+
|
|
18
|
+
CFG_JSONM:
|
|
19
|
+
```json
|
|
20
|
+
{"v":1,"lang":"en","tracker":"local","gh":{"enabled":false,"owner":"","repo":"","project":""},"rules":{"flow":["analysis","documentation","implementation","verification","regression","done"],"tests":"required","regression":"required","queue":"single","docs":"official","delegation":"required","skills":"required","memory":"load","save":"always","promptTask":"append-last"}}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
BOARD_JSONM:
|
|
24
|
+
```json
|
|
25
|
+
{"v":1,"tracker":"local","active":"","cols":{"backlog":[],"ready":[],"doing":[],"review":[],"blocked":[],"done":[]},"updatedAt":""}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
STATE_JSONM:
|
|
29
|
+
```json
|
|
30
|
+
{"v":1,"phase":"idle","prompt":"","ticket":"","next":"analysis","updatedAt":"","notes":[]}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
RULES:
|
|
34
|
+
- EN
|
|
35
|
+
- JSONM for AI-only state
|
|
36
|
+
- doing<=1 unless explicit user override
|
|
37
|
+
- when doing is occupied, new prompts queue to backlog — never preempt active work
|
|
38
|
+
- never drop pending work
|
|
39
|
+
- tests+regr required for code change
|
|
40
|
+
- load memory and relevant skills every prompt
|
|
41
|
+
- append each new prompt as the last task/todo entry before execution continues (only when doing is empty)
|
|
42
|
+
- keep tickets, todos, and plan synchronized automatically
|
|
43
|
+
- tracker=github only with explicit user authorization
|
|
44
|
+
- local files remain fallback source of truth even in github mode
|
|
45
|
+
- phase=queued means prompts are waiting in backlog behind active work — resume dequeues the next item
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# DevLoom Protocol Rules
|
|
2
|
+
|
|
3
|
+
CORE: EN only | SOLID+TDD+CleanArch | SingleActive | AppendPromptTask | OfficialDocsFirst | tests+regr required | delegation required | save every phase | load memory+skills every prompt
|
|
4
|
+
|
|
5
|
+
QUEUE: doing<=1 | new prompt while doing non-empty → append to backlog, set phase=queued, do NOT triage or execute | /devloom-resume dequeues next backlog item
|
|
6
|
+
|
|
7
|
+
CHAIN: feature=planner>dev>qa>doc | bug=dev(rca)>qa(regr) | refactor=planner>dev>qa | small=dev>qa | docs=planner>doc | task=dev | explore=verifier
|
|
8
|
+
|
|
9
|
+
ADDONS: image→vision FIRST | UI→visual-director(DESIGN_FILE, persist .opencode/devloom/context/design.md) then verifier(route,form,a11y,visual,responsive,motion) + visual-critic(≤3 cycles, verdict passed to verifier; backend-only never routes visual agents) | API→verifier(api,contract) | CRUD/endpoint→security | defect→dev(rca)>qa(regr) max3 cycles | high-risk→peer-review (verifier with multi-model consensus)
|
|
10
|
+
|
|
11
|
+
GATES: build(lint+tests) | qa(test+review+regr) | verifier(all requested scopes) | visual(design.md exists + critic verdict or VISUAL_CRITIQUE_LIMITED, VISUAL_REQUIRED only for UI work) | security(all checks) | peer-review(≥2 models agree) | doc(done+verified only)
|
|
12
|
+
|
|
13
|
+
ANTI-LOOP: max3 retries per defect | max100 steps | BLOCKED+reason after 2 failed retries | never self-delegate | never loop same agent
|
|
14
|
+
|
|
15
|
+
OUTPUT: DEVLOOM_DONE only when chain gates pass | sub-agents emit their OUT signal | final response ≤40 lines, full detail in artifacts | sub-agent never calls orchestrator back
|
|
16
|
+
FILES: never use /tmp, /var/tmp, or any system temp dirs — use .opencode/devloom/.tmp/ in the project workspace for all temporary files, test artifacts, and scratch work
|
|
17
|
+
SESSIONS: orchestrator tracks sub-agent task IDs in state.sessions. Reuse task_id when re-delegating to the same agent type mid-pipeline — prevents context loss across turns.
|
|
18
|
+
DEGRADE: if a sub-agent fails twice (timeout, rate-limit, empty response), fall back one tier: senior→mid, mid→junior, junior→skip. Set state.degraded=true and log the fallback.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Verification Policy
|
|
2
|
+
|
|
3
|
+
LOAD: ~/.config/opencode/devloom-ai/verify.dsl
|
|
4
|
+
|
|
5
|
+
RULES:
|
|
6
|
+
- ROUTE-001=render|noBlank|noCrash|noConsoleErr|noNavFail|noHydrationErr
|
|
7
|
+
- ROUTE-002=domVisible|size>0|notHidden|notBlocked|inViewport
|
|
8
|
+
- ROUTE-003=screenshot/vision when available
|
|
9
|
+
- FORM-001=valid|invalid|required|boundary|successMsg|errorMsg|loading
|
|
10
|
+
- FORM-002=input|select|checkbox|radio|textarea|submit|reset
|
|
11
|
+
- A11Y-001=role|label|expanded|selected|current
|
|
12
|
+
- A11Y-002=tabReachable|focusVisible|orderOk|noTrap|enterSpace|escClose|arrowKeys
|
|
13
|
+
- A11Y-003=contrastText|contrastFocus|noColorOnly
|
|
14
|
+
- A11Y-004=nav|main|headingOrder|buttonVsLink|labelAssoc
|
|
15
|
+
- API-001=auth|authz|inputVal|outputSchema|statusCodes|errorShape|paging/filter/sort if app
|
|
16
|
+
- API-002=openapi if missing|runtime vs contract
|
|
17
|
+
- E2E-001=targeted impacted suite during iteration
|
|
18
|
+
- E2E-002=full suite before acceptance
|
|
19
|
+
- JOURNEY-001=generate from REQ+routes+ui
|
|
20
|
+
- JOURNEY-002=test valid state transitions
|
|
21
|
+
- PERF-001=loadTime|noLeak|noExcessRender|bundleOk
|
|
22
|
+
- VISUAL-001=screenshots or CRITIC_VERDICT required|else VISUAL_CRITIQUE_LIMITED (never fake VISUAL_PASS)
|
|
23
|
+
- VISUAL-002=10-dim score vs design.md contract|hierarchy|spacing|typography|color|alignment|consistency|affordance|density|polish|fidelity
|
|
24
|
+
- VISUAL-003=no overflow|no clipped text|no overlap|component states match tokens
|
|
25
|
+
- RESP-001=viewports 360|768|1280|no horizontal scroll|no overlap|touch targets >=44px|images scale
|
|
26
|
+
- MOTION-001=prefers-reduced-motion|duration <=300ms standard <=500ms complex|no layout shift|states complete|easing matches design.md
|
|
27
|
+
- SEC-001=depAudit|noSecrets|cors|sanitize|auth|authz|leastPrivilege
|
|
28
|
+
- SEC-002=inputVal|outputSchema|errorShape|massAssignment|overposting
|
|
29
|
+
- SEC-003=noInternalFieldLeak|noDebugLeak|idor|xss|csrf|ssrf if applicable
|
|
30
|
+
- SEC-004=mandatory for CRUD endpoints and any internal component/module exposure via input/output
|
|
31
|
+
|
|
32
|
+
MAP:
|
|
33
|
+
- RouteVerifier=ROUTE-001|002|003
|
|
34
|
+
- FormVerifier=FORM-001|002
|
|
35
|
+
- A11yVerifier=A11Y-001|002|003|004
|
|
36
|
+
- ApiVerifier=API-001|002
|
|
37
|
+
- VisualVerifier=VISUAL-001|002|003
|
|
38
|
+
- ResponsiveVerifier=RESP-001
|
|
39
|
+
- MotionVerifier=MOTION-001
|
|
40
|
+
- SecurityVerifier=SEC-001|002|003|004
|
|
41
|
+
- JourneyAgent=JOURNEY-001|002
|
|
42
|
+
- QA=run applicable rules
|
|
43
|
+
- Regression=E2E-001 during work; E2E-002 before done
|
|
44
|
+
|
|
45
|
+
ENFORCE:
|
|
46
|
+
- each violation => defect
|
|
47
|
+
- critical/high defect blocks gate
|
|
48
|
+
- skip is invalid; only escalate after 3 failed repair cycles
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Incremental briefing tracker: answers "what changed since the briefing was
|
|
3
|
+
// written?" so orchestrator/sub-agents re-read ONLY modified files.
|
|
4
|
+
//
|
|
5
|
+
// Signal: sha256 content fingerprints recorded at init/touch — the same
|
|
6
|
+
// content-addressed idea as git, but immune to commit/uncommitted state (a
|
|
7
|
+
// file already re-read after `touch` never reappears until it truly changes).
|
|
8
|
+
// The git baseCommit is kept for provenance/status only.
|
|
9
|
+
//
|
|
10
|
+
// Commands:
|
|
11
|
+
// briefing.mjs init <ticket> create briefing.md stub + record fingerprints
|
|
12
|
+
// briefing.mjs changed print changed paths (one per line), exit 0
|
|
13
|
+
// briefing.mjs touch re-anchor after the briefing was patched
|
|
14
|
+
// briefing.mjs status show ticket/base/counters
|
|
15
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from "fs"
|
|
16
|
+
import { execSync } from "child_process"
|
|
17
|
+
import { resolve, dirname, join, relative, sep } from "path"
|
|
18
|
+
import { fileURLToPath } from "url"
|
|
19
|
+
import { createHash } from "crypto"
|
|
20
|
+
|
|
21
|
+
const DIR = ".opencode/devloom/context"
|
|
22
|
+
export const BRIEFING_MD = `${DIR}/briefing.md`
|
|
23
|
+
export const BRIEFING_JSON = `${DIR}/briefing.json`
|
|
24
|
+
|
|
25
|
+
const EXCLUDE_DIRS = new Set([
|
|
26
|
+
"node_modules", ".git", "dist", ".angular", ".next", "build", "coverage",
|
|
27
|
+
"logs", ".tmp", "tmp", ".opencode", ".idea", ".vscode",
|
|
28
|
+
])
|
|
29
|
+
const EXCLUDE_FILES = /^(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|\.DS_Store|.*\.log)$/
|
|
30
|
+
|
|
31
|
+
export function walkFiles(root = process.cwd()) {
|
|
32
|
+
const out = []
|
|
33
|
+
const stack = [root]
|
|
34
|
+
while (stack.length > 0) {
|
|
35
|
+
const dir = stack.pop()
|
|
36
|
+
let entries = []
|
|
37
|
+
try {
|
|
38
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
39
|
+
} catch {
|
|
40
|
+
continue
|
|
41
|
+
}
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.name.startsWith(".") && entry.isDirectory() && entry.name !== ".ai") continue
|
|
44
|
+
const full = join(dir, entry.name)
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
if (!EXCLUDE_DIRS.has(entry.name)) stack.push(full)
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
if (!entry.isFile() || EXCLUDE_FILES.test(entry.name)) continue
|
|
50
|
+
const rel = relative(root, full).split(sep).join("/")
|
|
51
|
+
out.push(rel)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return out.sort()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function hashFile(rel, root = process.cwd()) {
|
|
58
|
+
try {
|
|
59
|
+
const data = readFileSync(join(root, rel))
|
|
60
|
+
return createHash("sha256").update(data).digest("hex").slice(0, 12)
|
|
61
|
+
} catch {
|
|
62
|
+
return null
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function computeHashes(paths, root = process.cwd()) {
|
|
67
|
+
const files = {}
|
|
68
|
+
for (const p of paths) files[p] = hashFile(p, root)
|
|
69
|
+
return files
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function diffHashes(previous, paths, root = process.cwd()) {
|
|
73
|
+
const changed = []
|
|
74
|
+
const prev = previous || {}
|
|
75
|
+
for (const p of paths) {
|
|
76
|
+
if (prev[p] !== hashFile(p, root)) changed.push(p)
|
|
77
|
+
}
|
|
78
|
+
for (const p of Object.keys(prev)) {
|
|
79
|
+
if (!paths.includes(p) && prev[p] !== null) changed.push(p)
|
|
80
|
+
}
|
|
81
|
+
return [...new Set(changed)].sort()
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function run(cmd, cwd = process.cwd()) {
|
|
85
|
+
try {
|
|
86
|
+
return execSync(cmd, { cwd, encoding: "utf8", timeout: 15000 }).trim()
|
|
87
|
+
} catch {
|
|
88
|
+
return null
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function gitAvailable(cwd = process.cwd()) {
|
|
93
|
+
return run("git rev-parse --is-inside-work-tree", cwd) === "true"
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function gitHead(cwd = process.cwd()) {
|
|
97
|
+
const out = run("git rev-parse HEAD", cwd)
|
|
98
|
+
return out && !out.includes("fatal") ? out : null
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function readJson() {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(readFileSync(BRIEFING_JSON, "utf8"))
|
|
104
|
+
} catch {
|
|
105
|
+
return null
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function writeJson(data) {
|
|
110
|
+
mkdirSync(DIR, { recursive: true })
|
|
111
|
+
writeFileSync(BRIEFING_JSON, JSON.stringify(data, null, 2) + "\n")
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function init(ticket = "ticket") {
|
|
115
|
+
mkdirSync(DIR, { recursive: true })
|
|
116
|
+
const paths = walkFiles()
|
|
117
|
+
const useGit = gitAvailable()
|
|
118
|
+
const data = {
|
|
119
|
+
ticket,
|
|
120
|
+
baseCommit: useGit ? gitHead() : null,
|
|
121
|
+
files: computeHashes(paths),
|
|
122
|
+
updatedAt: new Date().toISOString(),
|
|
123
|
+
}
|
|
124
|
+
writeJson(data)
|
|
125
|
+
if (!existsSync(BRIEFING_MD)) {
|
|
126
|
+
writeFileSync(
|
|
127
|
+
BRIEFING_MD,
|
|
128
|
+
`# Briefing — ${ticket}\n` +
|
|
129
|
+
`> Created: ${data.updatedAt}\n` +
|
|
130
|
+
`> Refresh rule: run \`briefing.mjs changed\`, re-read ONLY those paths, patch this file, then \`briefing.mjs touch\`.\n` +
|
|
131
|
+
`> Every task() prompt starts with: "Read .opencode/devloom/context/briefing.md first — do not re-discover."\n\n` +
|
|
132
|
+
`## Goal\n\n## Constraints\n\n## File map\n\n## Decisions\n`
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
return data
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function changed() {
|
|
139
|
+
const data = readJson()
|
|
140
|
+
if (!data) return []
|
|
141
|
+
return diffHashes(data.files, walkFiles())
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function touch() {
|
|
145
|
+
const data = readJson() || init("ticket")
|
|
146
|
+
const paths = walkFiles()
|
|
147
|
+
data.baseCommit = gitAvailable() ? gitHead() : null
|
|
148
|
+
data.files = computeHashes(paths)
|
|
149
|
+
data.updatedAt = new Date().toISOString()
|
|
150
|
+
writeJson(data)
|
|
151
|
+
return data
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function status() {
|
|
155
|
+
const data = readJson()
|
|
156
|
+
if (!data) {
|
|
157
|
+
console.log("No briefing recorded. Run: briefing.mjs init <ticket>")
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
console.log(`Ticket: ${data.ticket}`)
|
|
161
|
+
console.log(`Base commit: ${data.baseCommit || "(no git)"}`)
|
|
162
|
+
console.log(`Tracked files: ${Object.keys(data.files).length}`)
|
|
163
|
+
console.log(`Updated: ${data.updatedAt}`)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function main() {
|
|
167
|
+
const args = process.argv.slice(2)
|
|
168
|
+
const command = args[0] || ""
|
|
169
|
+
switch (command) {
|
|
170
|
+
case "init":
|
|
171
|
+
init(args[1] || "ticket")
|
|
172
|
+
console.log(`Briefing initialized${args[1] ? ` for ${args[1]}` : ""}: ${BRIEFING_MD}`)
|
|
173
|
+
break
|
|
174
|
+
case "changed": {
|
|
175
|
+
const paths = changed()
|
|
176
|
+
for (const p of paths) console.log(p)
|
|
177
|
+
break
|
|
178
|
+
}
|
|
179
|
+
case "touch":
|
|
180
|
+
touch()
|
|
181
|
+
console.log("Briefing anchors refreshed.")
|
|
182
|
+
break
|
|
183
|
+
case "status":
|
|
184
|
+
status()
|
|
185
|
+
break
|
|
186
|
+
default:
|
|
187
|
+
console.log("Usage: briefing.mjs <init <ticket>|changed|touch|status>")
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const isMain = process.argv[1] ? fileURLToPath(import.meta.url) === resolve(process.argv[1]) : false
|
|
192
|
+
if (isMain) main()
|