devloom 1.0.0 → 1.1.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.
Files changed (140) hide show
  1. package/.ai/core.dsl +44 -0
  2. package/.ai/skills.dsl +39 -0
  3. package/.ai/verify.dsl +97 -0
  4. package/.ai/workflow.dsl +81 -0
  5. package/.opencode/themes/devloom-night-owl.json +103 -0
  6. package/GUIDE.md +547 -114
  7. package/README.md +557 -109
  8. package/SECURITY.md +93 -0
  9. package/agents/devloom-developer-flash.md +27 -0
  10. package/agents/devloom-developer-senior.md +28 -0
  11. package/agents/devloom-developer.md +18 -56
  12. package/agents/devloom-documenter-flash.md +24 -0
  13. package/agents/devloom-documenter.md +14 -57
  14. package/agents/devloom-orchestrator.md +232 -356
  15. package/agents/devloom-planner-flash.md +30 -0
  16. package/agents/devloom-planner-senior.md +31 -0
  17. package/agents/devloom-planner.md +32 -0
  18. package/agents/devloom-qa-flash.md +28 -0
  19. package/agents/devloom-qa.md +18 -84
  20. package/agents/devloom-security-senior.md +31 -0
  21. package/agents/devloom-security.md +30 -0
  22. package/agents/devloom-verifier.md +29 -0
  23. package/agents/devloom-vision.md +109 -0
  24. package/agents/devloom-visual-critic.md +98 -0
  25. package/agents/devloom-visual-director.md +80 -0
  26. package/commands/devloom-agents.md +49 -0
  27. package/commands/devloom-auto.md +11 -0
  28. package/commands/devloom-context.md +82 -0
  29. package/commands/devloom-deepseek.md +11 -0
  30. package/commands/devloom-free.md +11 -0
  31. package/commands/devloom-go-economy.md +11 -0
  32. package/commands/devloom-go-flash.md +11 -0
  33. package/commands/devloom-go.md +11 -0
  34. package/commands/devloom-init.md +28 -50
  35. package/commands/devloom-loop-status.md +25 -0
  36. package/commands/devloom-loop.md +36 -0
  37. package/commands/devloom-mimo.md +11 -0
  38. package/commands/devloom-plan.md +13 -0
  39. package/commands/devloom-refresh.md +22 -0
  40. package/commands/devloom-resume.md +30 -49
  41. package/commands/devloom-save.md +69 -0
  42. package/commands/devloom-status.md +9 -18
  43. package/commands/devloom.md +99 -67
  44. package/dist/agents.d.ts +30 -0
  45. package/dist/agents.d.ts.map +1 -0
  46. package/dist/agents.js +139 -0
  47. package/dist/agents.js.map +1 -0
  48. package/dist/bootstrap.d.ts +56 -0
  49. package/dist/bootstrap.d.ts.map +1 -0
  50. package/dist/bootstrap.js +116 -0
  51. package/dist/bootstrap.js.map +1 -0
  52. package/dist/constraints.d.ts +5 -0
  53. package/dist/constraints.d.ts.map +1 -0
  54. package/dist/constraints.js +45 -0
  55. package/dist/constraints.js.map +1 -0
  56. package/dist/context.d.ts +42 -0
  57. package/dist/context.d.ts.map +1 -0
  58. package/dist/context.js +636 -0
  59. package/dist/context.js.map +1 -0
  60. package/dist/guard.d.ts +19 -0
  61. package/dist/guard.d.ts.map +1 -0
  62. package/dist/guard.js +418 -0
  63. package/dist/guard.js.map +1 -0
  64. package/dist/loop.d.ts +64 -0
  65. package/dist/loop.d.ts.map +1 -0
  66. package/dist/loop.js +164 -0
  67. package/dist/loop.js.map +1 -0
  68. package/dist/plugin.d.ts.map +1 -1
  69. package/dist/plugin.js +101 -1
  70. package/dist/plugin.js.map +1 -1
  71. package/dist/tui-agents.d.ts +61 -0
  72. package/dist/tui-agents.d.ts.map +1 -0
  73. package/dist/tui-agents.js +89 -0
  74. package/dist/tui-agents.js.map +1 -0
  75. package/dist/tui.d.ts +6 -0
  76. package/dist/tui.d.ts.map +1 -0
  77. package/dist/tui.js +92 -0
  78. package/dist/tui.js.map +1 -0
  79. package/dist/worktree.d.ts +46 -0
  80. package/dist/worktree.d.ts.map +1 -0
  81. package/dist/worktree.js +272 -0
  82. package/dist/worktree.js.map +1 -0
  83. package/package.json +46 -6
  84. package/patterns/changelog-drafter.md +38 -0
  85. package/patterns/ci-sweeper.md +40 -0
  86. package/patterns/daily-triage.md +37 -0
  87. package/patterns/dependency-sweeper.md +40 -0
  88. package/patterns/design-audit.md +63 -0
  89. package/patterns/issue-triage.md +37 -0
  90. package/patterns/post-merge-cleanup.md +34 -0
  91. package/patterns/pr-babysitter.md +37 -0
  92. package/patterns/registry.yaml +52 -0
  93. package/postinstall.mjs +259 -63
  94. package/project/README.md +29 -0
  95. package/protocol/agent-contracts.md +27 -0
  96. package/protocol/artifact-system.md +53 -0
  97. package/protocol/model-routing.md +185 -0
  98. package/protocol/orchestrator-core.md +43 -0
  99. package/protocol/project-system.md +45 -0
  100. package/protocol/rules.md +18 -0
  101. package/protocol/verification-policy.md +48 -0
  102. package/scripts/loop-run.mjs +205 -0
  103. package/scripts/model-capabilities.mjs +169 -0
  104. package/scripts/plugin-cache.mjs +269 -0
  105. package/scripts/profile.mjs +691 -0
  106. package/scripts/visual-benchmark.mjs +149 -0
  107. package/scripts/worktree.mjs +445 -0
  108. package/skills/build/development.md +33 -0
  109. package/skills/build/live-docs.md +38 -0
  110. package/skills/build/simplify.md +50 -0
  111. package/skills/build/vision-analysis.md +98 -0
  112. package/skills/design/app-design.md +31 -0
  113. package/skills/design/design-grounding.md +30 -0
  114. package/skills/design/design-system.md +27 -0
  115. package/skills/design/game-design.md +35 -0
  116. package/skills/design/motion-design.md +34 -0
  117. package/skills/design/visual-direction.md +32 -0
  118. package/skills/design/web-design.md +33 -0
  119. package/skills/loop/changelog-drafter.md +32 -0
  120. package/skills/loop/ci-sweeper.md +24 -0
  121. package/skills/loop/constraints.md +21 -0
  122. package/skills/loop/dependency-sweeper.md +24 -0
  123. package/skills/loop/design-audit.md +67 -0
  124. package/skills/loop/issue-triage.md +27 -0
  125. package/skills/loop/post-merge-cleanup.md +24 -0
  126. package/skills/loop/pr-babysitter.md +26 -0
  127. package/skills/loop/triage.md +25 -0
  128. package/skills/loop/verifier.md +20 -0
  129. package/skills/meta/skill-discovery.md +23 -0
  130. package/skills/plan/planning.md +27 -0
  131. package/skills/plan/verification-planning.md +40 -0
  132. package/skills/review/security-review.md +63 -0
  133. package/skills/ship/documentation.md +11 -0
  134. package/skills/verify/app-verification.md +19 -0
  135. package/skills/verify/quality-assurance.md +17 -0
  136. package/skills/verify/visual-critique.md +30 -0
  137. package/skills/verify/visual-quality-gate.md +29 -0
  138. package/skills/verify/visual-regression.md +25 -0
  139. package/agents/devloom-analyst.md +0 -83
  140. package/agents/devloom-architect.md +0 -88
@@ -0,0 +1,37 @@
1
+ ---
2
+ id: pr-babysitter
3
+ cadence: "*/15 * * * *"
4
+ level: L2
5
+ agents: [planner, developer, qa]
6
+ cost: 200000
7
+ description: "Watch long-running PRs and push them forward"
8
+ ---
9
+ # PR Babysitter Pattern
10
+
11
+ ## Purpose
12
+ Watch open PRs that have been idle for >2 hours and push them forward with fixes, rebases, or reviews.
13
+
14
+ ## State Schema
15
+ ```json
16
+ {
17
+ "prs": [
18
+ {
19
+ "number": number,
20
+ "status": "idle" | "in_progress" | "blocked" | "merged",
21
+ "lastActivity": "ISO string",
22
+ "agentAssigned": string,
23
+ "attempts": number
24
+ }
25
+ ]
26
+ }
27
+ ```
28
+
29
+ ## Agent Chain
30
+ 1. planner — analyze PR diff and comments, plan next action
31
+ 2. developer — implement the planned change in a worktree
32
+ 3. qa — verify the change, run tests
33
+
34
+ ## Safety
35
+ - L2: all changes go through verifier review before commit
36
+ - Max 3 attempts per PR per tick
37
+ - Never force-push
@@ -0,0 +1,52 @@
1
+ # Loop Pattern Registry
2
+ # Each pattern defines: cadence, safety level, agent chain, token cost estimate
3
+ v: 1
4
+ patterns:
5
+ - id: daily-triage
6
+ cadence: "0 6 * * *"
7
+ level: L1
8
+ agents: [verifier, documenter]
9
+ cost_estimate: 50000
10
+ description: "Report repo health every morning"
11
+ - id: pr-babysitter
12
+ cadence: "*/15 * * * *"
13
+ level: L2
14
+ agents: [planner, developer, qa]
15
+ cost_estimate: 200000
16
+ description: "Watch long-running PRs and push them forward"
17
+ - id: ci-sweeper
18
+ cadence: "*/10 * * * *"
19
+ level: L2
20
+ agents: [developer, qa]
21
+ cost_estimate: 300000
22
+ description: "Detect and fix CI failures"
23
+ - id: dependency-sweeper
24
+ cadence: "0 */6 * * *"
25
+ level: L2
26
+ agents: [verifier, developer]
27
+ cost_estimate: 100000
28
+ description: "Patch-only dependency updates"
29
+ - id: changelog-drafter
30
+ cadence: "0 8 * * *"
31
+ level: L1
32
+ agents: [documenter]
33
+ cost_estimate: 30000
34
+ description: "Draft release notes from recent commits"
35
+ - id: post-merge-cleanup
36
+ cadence: "0 3 * * *"
37
+ level: L1
38
+ agents: [developer, qa]
39
+ cost_estimate: 40000
40
+ description: "Clean up stale branches and worktrees"
41
+ - id: issue-triage
42
+ cadence: "0 */2 * * *"
43
+ level: L1
44
+ agents: [planner]
45
+ cost_estimate: 60000
46
+ description: "Propose labels and priorities for new issues"
47
+ - id: design-audit
48
+ cadence: "on-demand"
49
+ level: L1
50
+ agents: [verifier]
51
+ cost_estimate: 150000
52
+ description: "Comprehensive UI/UX design audit with automated fix loop"
package/postinstall.mjs CHANGED
@@ -1,62 +1,97 @@
1
1
  #!/usr/bin/env node
2
- // postinstall.mjs Installs DevLoom agents, commands, and skills into OpenCode's global config dirs.
3
-
4
- import { copyFileSync, mkdirSync, existsSync, readdirSync, statSync } from "fs"
2
+ import { copyFileSync, mkdirSync, existsSync, readdirSync, statSync, accessSync, constants, readFileSync, writeFileSync } from "fs"
5
3
  import { resolve, dirname, join, relative } from "path"
6
4
  import { fileURLToPath } from "url"
7
5
  import { homedir, platform } from "os"
6
+ import { getOpenCodeCacheDir, refreshOpenCodePluginCache, syncOpenCodePluginDependencies } from "./scripts/plugin-cache.mjs"
8
7
 
9
8
  const __dirname = dirname(fileURLToPath(import.meta.url))
10
9
 
11
- // ── Config dir resolution (cross-platform) ────────────────────────────────────
12
- function getConfigDir() {
13
- const os = platform()
14
- if (os === "win32") {
15
- return resolve(process.env.APPDATA ?? homedir(), "opencode")
10
+ export function getConfigDir(_platform = platform(), _homedir = homedir()) {
11
+ if (_platform === "win32") {
12
+ return resolve(process.env.APPDATA ?? _homedir, "opencode")
16
13
  }
17
- if (os === "darwin") {
18
- return resolve(homedir(), "Library", "Application Support", "opencode")
14
+ if (_platform === "darwin") {
15
+ return resolve(_homedir, "Library", "Application Support", "opencode")
19
16
  }
20
17
  return resolve(
21
- process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"),
18
+ process.env.XDG_CONFIG_HOME ?? join(_homedir, ".config"),
22
19
  "opencode"
23
20
  )
24
21
  }
25
22
 
26
- const CONFIG_DIR = getConfigDir()
27
- const AGENTS_DIR = resolve(CONFIG_DIR, "agents")
28
- const COMMANDS_DIR = resolve(CONFIG_DIR, "commands")
29
- const SKILLS_DIR = resolve(CONFIG_DIR, "skills")
30
-
31
- const AGENTS = [
32
- "devloom-orchestrator",
33
- "devloom-analyst",
34
- "devloom-architect",
35
- "devloom-developer",
36
- "devloom-qa",
37
- "devloom-documenter",
38
- ]
23
+ export function isPathSafe(basePath, resolvedPath) {
24
+ const rel = relative(basePath, resolvedPath)
25
+ return !rel.startsWith("..") && !rel.startsWith("/")
26
+ }
39
27
 
40
- const COMMANDS = ["devloom", "devloom-status", "devloom-resume", "devloom-init"]
28
+ export function isDebug() {
29
+ return process.env.DEVLOOM_DEBUG === "1" || process.env.DEVLOOM_DEBUG === "true"
30
+ }
41
31
 
42
- // ── Helpers ───────────────────────────────────────────────────────────────────
43
- function ensureDir(dir) {
32
+ export function ensureDir(dir) {
44
33
  if (!existsSync(dir)) {
45
34
  mkdirSync(dir, { recursive: true })
35
+ if (isDebug()) console.log(`[debug] Created directory: ${dir}`)
46
36
  console.log(` Created: ${dir}`)
47
37
  }
48
38
  }
49
39
 
40
+ // Register the DevLoom TUI plugin in tui.json's `plugin` array so OpenCode's
41
+ // TUI loads the rightbar sidebar slot (no directory auto-discovery for TUI
42
+ // plugins). Preserves every existing key (theme, keybinds, ...); dedupes the
43
+ // plugin entry; returns the merged object, or null when the file is corrupt
44
+ // (caller decides whether to warn).
45
+ export function ensureTuiPlugin(tuiPath, pluginName = "devloom") {
46
+ let tui = {}
47
+ if (existsSync(tuiPath)) {
48
+ try {
49
+ tui = JSON.parse(readFileSync(tuiPath, "utf8"))
50
+ } catch {
51
+ return null
52
+ }
53
+ }
54
+ if (typeof tui !== "object" || tui === null || Array.isArray(tui)) return null
55
+ if (!tui.$schema) tui.$schema = "https://opencode.ai/tui.json"
56
+ const plugins = Array.isArray(tui.plugin) ? tui.plugin.filter((spec) => spec !== pluginName) : []
57
+ plugins.push(pluginName)
58
+ tui.plugin = plugins
59
+ writeFileSync(tuiPath, JSON.stringify(tui, null, 2) + "\n")
60
+ return tui
61
+ }
62
+
50
63
  let installFailed = false
51
64
 
52
- function installFile(src, dest, label) {
65
+ export function installFile(src, dest, label, configDir, optional = false) {
66
+ const baseDir = configDir || getConfigDir()
53
67
  if (!existsSync(src)) {
68
+ if (optional) {
69
+ console.log(` Skipped (not shipped) -- ${label}`)
70
+ return
71
+ }
54
72
  console.error(` Source file not found: ${src}`)
55
73
  installFailed = true
56
74
  return
57
75
  }
76
+ const destDir = dirname(dest)
77
+ if (!isPathSafe(baseDir, resolve(destDir))) {
78
+ console.error(` Path traversal blocked -- ${label}: ${dest}`)
79
+ installFailed = true
80
+ return
81
+ }
82
+ try {
83
+ accessSync(destDir, constants.W_OK)
84
+ } catch {
85
+ console.error(` No write permission -- ${label}: ${destDir}`)
86
+ installFailed = true
87
+ return
88
+ }
58
89
  try {
59
90
  copyFileSync(src, dest)
91
+ if (isDebug()) {
92
+ const srcStat = statSync(src)
93
+ console.log(`[debug] Copied ${src} -> ${dest} (${srcStat.size} bytes)`)
94
+ }
60
95
  console.log(` ${label}`)
61
96
  } catch (err) {
62
97
  console.error(` Failed -- ${label}: ${err.message}`)
@@ -64,7 +99,8 @@ function installFile(src, dest, label) {
64
99
  }
65
100
  }
66
101
 
67
- function installDirRecursive(srcDir, destDir, labelPrefix) {
102
+ export function installDirRecursive(srcDir, destDir, labelPrefix, configDir) {
103
+ const baseDir = configDir || getConfigDir()
68
104
  if (!existsSync(srcDir)) {
69
105
  console.error(` Source dir not found: ${srcDir}`)
70
106
  installFailed = true
@@ -77,61 +113,221 @@ function installDirRecursive(srcDir, destDir, labelPrefix) {
77
113
  const destPath = join(destDir, entry)
78
114
  const stat = statSync(srcPath)
79
115
  if (stat.isDirectory()) {
80
- installDirRecursive(srcPath, destPath, `${labelPrefix}/${entry}`)
116
+ installDirRecursive(srcPath, destPath, `${labelPrefix}/${entry}`, baseDir)
81
117
  } else {
82
- installFile(srcPath, destPath, `${labelPrefix}/${entry}`)
118
+ installFile(srcPath, destPath, `${labelPrefix}/${entry}`, baseDir)
83
119
  }
84
120
  }
85
121
  }
86
122
 
87
- // ── Main ──────────────────────────────────────────────────────────────────────
88
- console.log("\nDevLoom -- post-install\n")
89
- console.log(` Config dir : ${CONFIG_DIR}`)
90
- console.log(` Agents dir : ${AGENTS_DIR}`)
91
- console.log(` Commands dir: ${COMMANDS_DIR}`)
92
- console.log(` Skills dir : ${SKILLS_DIR}\n`)
123
+ const CONFIG_DIR = getConfigDir()
124
+ const AGENTS_DIR = resolve(CONFIG_DIR, "agents")
125
+ const COMMANDS_DIR = resolve(CONFIG_DIR, "commands")
126
+ const SKILLS_DIR = resolve(CONFIG_DIR, "skills")
127
+ const PROTOCOL_DIR = resolve(CONFIG_DIR, "protocol")
128
+ const AI_DIR = resolve(CONFIG_DIR, "devloom-ai")
129
+ const THEMES_DIR = resolve(CONFIG_DIR, "themes")
130
+
131
+ const AGENTS = [
132
+ "devloom-orchestrator",
133
+ "devloom-planner",
134
+ "devloom-developer",
135
+ "devloom-qa",
136
+ "devloom-verifier",
137
+ "devloom-security",
138
+ "devloom-documenter",
139
+ "devloom-vision",
140
+ "devloom-visual-director",
141
+ "devloom-visual-critic",
142
+ "devloom-planner-senior",
143
+ "devloom-developer-senior",
144
+ "devloom-security-senior",
145
+ "devloom-planner-flash",
146
+ "devloom-developer-flash",
147
+ "devloom-qa-flash",
148
+ "devloom-documenter-flash",
149
+ ]
150
+
151
+ const COMMANDS = ["devloom", "devloom-status", "devloom-resume", "devloom-init", "devloom-save", "devloom-auto", "devloom-go", "devloom-go-economy", "devloom-go-flash", "devloom-deepseek", "devloom-free", "devloom-mimo", "devloom-plan", "devloom-context", "devloom-agents", "devloom-refresh"]
93
152
 
94
- ensureDir(AGENTS_DIR)
95
- ensureDir(COMMANDS_DIR)
153
+ const SCRIPTS_DIR = resolve(CONFIG_DIR, "devloom-scripts")
96
154
 
155
+ const PROTOCOLS = [
156
+ "orchestrator-core",
157
+ "agent-contracts",
158
+ "artifact-system",
159
+ "verification-policy",
160
+ "project-system",
161
+ ]
97
162
 
98
- console.log("Installing agents:")
99
- for (const name of AGENTS) {
163
+ function main() {
164
+ console.log("\nDevLoom -- post-install\n")
165
+ console.log(` Config dir : ${CONFIG_DIR}`)
166
+ console.log(` Agents dir : ${AGENTS_DIR}`)
167
+ console.log(` Commands dir: ${COMMANDS_DIR}`)
168
+ console.log(` Skills dir : ${SKILLS_DIR}\n`)
169
+ console.log(` AI dir : ${AI_DIR}\n`)
170
+
171
+ if (isDebug()) console.log("[debug] Starting DevLoom post-install")
172
+
173
+ ensureDir(AGENTS_DIR)
174
+ ensureDir(COMMANDS_DIR)
175
+
176
+ console.log("Installing agents:")
177
+ for (const name of AGENTS) {
178
+ installFile(
179
+ resolve(__dirname, "agents", `${name}.md`),
180
+ resolve(AGENTS_DIR, `${name}.md`),
181
+ `Agent: ${name}`
182
+ )
183
+ }
184
+
185
+ console.log("\nInstalling commands:")
186
+ for (const name of COMMANDS) {
187
+ installFile(
188
+ resolve(__dirname, "commands", `${name}.md`),
189
+ resolve(COMMANDS_DIR, `${name}.md`),
190
+ `Command: /${name}`
191
+ )
192
+ }
100
193
  installFile(
101
- resolve(__dirname, "agents", `${name}.md`),
102
- resolve(AGENTS_DIR, `${name}.md`),
103
- `Agent: ${name}`
194
+ resolve(__dirname, "scripts", "profile.mjs"),
195
+ resolve(COMMANDS_DIR, "profile.mjs"),
196
+ "Profile manager"
104
197
  )
105
- }
106
-
107
- console.log("\nInstalling commands:")
108
- for (const name of COMMANDS) {
109
198
  installFile(
110
- resolve(__dirname, "commands", `${name}.md`),
111
- resolve(COMMANDS_DIR, `${name}.md`),
112
- `Command: /${name}`
199
+ resolve(__dirname, "scripts", "model-capabilities.mjs"),
200
+ resolve(COMMANDS_DIR, "model-capabilities.mjs"),
201
+ "Model capabilities helper"
202
+ )
203
+ installFile(
204
+ resolve(__dirname, "scripts", "plugin-cache.mjs"),
205
+ resolve(COMMANDS_DIR, "plugin-cache.mjs"),
206
+ "Plugin cache helper"
207
+ )
208
+
209
+ console.log("\nInstalling skills:")
210
+ installDirRecursive(
211
+ resolve(__dirname, "skills"),
212
+ SKILLS_DIR,
213
+ "Skill"
214
+ )
215
+
216
+ console.log("\nInstalling AI DSL:")
217
+ installDirRecursive(
218
+ resolve(__dirname, ".ai"),
219
+ AI_DIR,
220
+ "AI"
113
221
  )
114
- }
115
222
 
116
- console.log("\nInstalling skills:")
117
- installDirRecursive(
118
- resolve(__dirname, "skills"),
119
- SKILLS_DIR,
120
- "Skill"
121
- )
223
+ console.log("\nInstalling profile manager scripts:")
224
+ installDirRecursive(
225
+ resolve(__dirname, "scripts"),
226
+ SCRIPTS_DIR,
227
+ "Script"
228
+ )
229
+
230
+ console.log("\nInstalling protocol modules:")
231
+ ensureDir(PROTOCOL_DIR)
232
+ for (const name of PROTOCOLS) {
233
+ installFile(
234
+ resolve(__dirname, "protocol", `${name}.md`),
235
+ resolve(PROTOCOL_DIR, `${name}.md`),
236
+ `Protocol: ${name}`
237
+ )
238
+ }
122
239
 
123
- if (!installFailed) {
124
- console.log(`
240
+ // Install theme
241
+ console.log("\nInstalling DevLoom Night Owl theme:")
242
+ ensureDir(THEMES_DIR)
243
+ const themeSrc = resolve(__dirname, ".opencode", "themes", "devloom-night-owl.json")
244
+ const themeDest = resolve(THEMES_DIR, "devloom-night-owl.json")
245
+ // ponytail: cosmetic asset — a missing theme must never fail the install
246
+ installFile(themeSrc, themeDest, "Theme: DevLoom Night Owl", CONFIG_DIR, true)
247
+
248
+ // Register the TUI plugin in tui.json (the right sidebar renders only plugin
249
+ // slots, so this is what makes the DevLoom agents visible in the rightbar)
250
+ // and activate the theme when no theme is set.
251
+ const tuiPath = resolve(CONFIG_DIR, "tui.json")
252
+ const tui = ensureTuiPlugin(tuiPath)
253
+ if (tui === null) {
254
+ console.log(" Skipping tui.json update (parse error)")
255
+ } else {
256
+ if (!tui.theme) {
257
+ tui.theme = "devloom-night-owl"
258
+ writeFileSync(tuiPath, JSON.stringify(tui, null, 2) + "\n")
259
+ console.log(" Theme activated in tui.json (change via /theme)")
260
+ } else {
261
+ console.log(` Theme already set: ${tui.theme} (change via /theme)`)
262
+ }
263
+ console.log(" DevLoom TUI plugin registered in tui.json (agents render in the right sidebar)")
264
+ }
265
+
266
+ // Refresh the OpenCode plugin cache so the plugin code loaded by the TUI
267
+ // actually contains the config hook that injects DevLoom agents + profile
268
+ // into the sidebar. Best-effort only: OpenCode installs plugins with
269
+ // ignoreScripts, so this copy is the only way the cache picks up new code.
270
+ // Cosmetic failures here must never fail the npm install.
271
+ console.log("\nRefreshing OpenCode plugin cache:")
272
+ const cacheDir = getOpenCodeCacheDir()
273
+ const refresh = refreshOpenCodePluginCache(__dirname, cacheDir)
274
+ if (refresh.build && refresh.build.built) {
275
+ console.log(" Rebuilt dist/ before refreshing the plugin cache.")
276
+ }
277
+ if (refresh.build && refresh.build.errors.length > 0) {
278
+ console.log(` Warning (not fatal): dist rebuild failed — ${refresh.build.errors[0]}`)
279
+ }
280
+ for (const entry of refresh.refreshed) {
281
+ console.log(` Refreshed plugin cache: ${entry} -> fresh DevLoom code with the sidebar config hook`)
282
+ }
283
+ for (const entry of refresh.skipped) {
284
+ console.log(` Skipped: no OpenCode plugin cache entry found at ${entry}`)
285
+ }
286
+ for (const error of refresh.errors) {
287
+ console.log(` Warning (not fatal): plugin cache refresh failed for ${error}`)
288
+ }
289
+ if (refresh.skipped.length > 0 && refresh.refreshed.length === 0) {
290
+ console.log("")
291
+ console.log(" DevLoom is not yet registered as an OpenCode plugin.")
292
+ console.log(" Install it once with: opencode plugin devloom --global")
293
+ console.log(" then re-run this installer (or /devloom-refresh) to sync the plugin code.")
294
+ } else if (refresh.errors.length > 0) {
295
+ console.log(" The plugin cache could not be fully refreshed — run /devloom-refresh to retry.")
296
+ }
297
+
298
+ console.log("\nSyncing plugin cache dependencies (TUI sidebar plugin):")
299
+ const deps = syncOpenCodePluginDependencies(__dirname, cacheDir)
300
+ for (const entry of deps.synced) {
301
+ console.log(` Synced runtime deps: ${entry} (right-sidebar TUI plugin ready)`)
302
+ }
303
+ for (const entry of deps.skipped) {
304
+ console.log(` Skipped: no OpenCode plugin cache entry found at ${entry}`)
305
+ }
306
+ for (const error of deps.errors) {
307
+ console.log(` Warning (not fatal): dependency sync failed for ${error}`)
308
+ }
309
+
310
+ if (!installFailed) {
311
+ console.log(`
125
312
  DevLoom installed successfully!
126
313
 
127
314
  Start weaving:
128
315
  /devloom Build a REST API for user management with JWT auth
129
316
  /devloom-status
130
317
 
318
+ Protocol modules available at ~/.config/opencode/protocol/
319
+
320
+ Theme: DevLoom Night Owl active (change via /theme or edit tui.json)
321
+
131
322
  Debug mode:
132
323
  DEVLOOM_DEBUG=1 opencode @devloom-orchestrator
133
324
  `)
134
- } else {
135
- console.error("\nSome files could not be installed. See errors above.")
136
- process.exit(1)
325
+ } else {
326
+ console.error("\nSome files could not be installed. See errors above.")
327
+ process.exit(1)
328
+ }
329
+ }
330
+
331
+ if (process.argv[1] && fileURLToPath(import.meta.url) === resolve(process.argv[1])) {
332
+ main()
137
333
  }
@@ -0,0 +1,29 @@
1
+ # DevLoom Project Standard
2
+
3
+ ROOT: `.opencode/devloom/project/`
4
+
5
+ GOALS:
6
+ - EN artifacts
7
+ - JSONM for AI-only state
8
+ - SingleActive queue
9
+ - Persist pending work
10
+ - Load memory every prompt
11
+ - Use relevant skills every prompt
12
+ - Append each prompt as the last task/todo
13
+ - Keep tickets/todos/plan in sync
14
+ - Tests+Regr required
15
+ - Local tracker default
16
+ - GitHub Project mirror only with explicit authorization
17
+
18
+ TREE:
19
+ - README.md
20
+ - config.json
21
+ - board.json
22
+ - state.json
23
+ - stories/
24
+ - tasks/
25
+ - bugs/
26
+ - decisions/
27
+ - reports/
28
+
29
+ JSON_KEYS: v|id|type|title|status|ac|deps|files|tests|cols|ts
@@ -0,0 +1,27 @@
1
+ # Agent Contracts
2
+
3
+ LOAD: ~/.config/opencode/devloom-ai/core.dsl|~/.config/opencode/devloom-ai/workflow.dsl|~/.config/opencode/devloom-ai/verify.dsl
4
+
5
+ FMT:
6
+ `Agent|Purpose|In|Out|Rules|Signal`
7
+
8
+ AGENTS (7):
9
+ - Orchestrator|triage+route+queue+inline recovery|prompt|state+handoffs|EN|SingleActive|PersistAll|LoadMemory|UseSkills|AppendPromptTask|MaintainPlan|NoSelfDelegate|DEVLOOM_DONE
10
+ - Planner|prompt->REQ and/or PLAN+tickets|prompt/REQ|REQ|PLAN+tasks/*|NoImpl|CleanArch|LatestStableCheck|OfficialDocsFirst|TestsInPlan|ANALYST_COMPLETE/ARCHITECT_COMPLETE/PLANNER_COMPLETE
11
+ - Developer|implement one ticket OR fix one defect|ticket/defect+PLAN|code+tests|TDDReq|RootCauseFix|NoWorkaround|SOLID|NoScopeCreep|MinChange|DEVELOPER_COMPLETE/REPAIR_COMPLETE
12
+ - QA|verify+review+regression|ticket+diff|results|Lint|Tests|CodeReview|Regr|QA_PASS/QA_FAIL/REGRESSION_PASS/REGRESSION_FAIL
13
+ - Verifier|runtime app verification by scope|scope+app url/cmd|defects/report|UX_BAR|NoGuess|Forensic|VERIFIER_COMPLETE
14
+ - Security|review CRUD/exposure surfaces|endpoint+dto+component api|security report|SEC checks|Forensic|SECURITY_REVIEW_COMPLETE
15
+ - Documenter|update docs+state|done tasks|docs+state|OnlyImplemented|EN|DOCUMENTER_COMPLETE
16
+
17
+ SHARED:
18
+ - EN
19
+ - DeltaCommOnly
20
+ - FinalResponse<=40lines: status signal + deltas + artifact paths; full detail goes to .opencode/devloom/ artifacts, never chat
21
+ - JSONM for AI-only state
22
+ - Update BOARD+PSTATE on ticket state change
23
+ - Append each prompt to project/tasks/TODO.md before execution routing
24
+ - Keep tasks/todos/plan aligned with the active ticket
25
+ - DevLoom subagents are callable by the orchestrator and may also be invoked manually by the user
26
+ - OfficialDocsFirst for stack-specific decisions
27
+ - LatestStableCheck before stack-specific planning/coding
@@ -0,0 +1,53 @@
1
+ # Artifact System
2
+
3
+ LOAD: ~/.config/opencode/devloom-ai/core.dsl
4
+
5
+ REG:
6
+ - REG=.opencode/devloom/registry.json
7
+ - BOARD=.opencode/devloom/project/board.json
8
+ - PSTATE=.opencode/devloom/project/state.json
9
+
10
+ TYPES: feature|defect|requirement|plan|exploration|verification|journey|decision
11
+
12
+ RULES:
13
+ - use ids, not raw dumps
14
+ - send title|files|ac|signal only
15
+ - summaries <=100 tokens when possible
16
+ - use relative paths
17
+ - persist active work in BOARD
18
+ - append each prompt to project/tasks/TODO.md as the last todo item
19
+ - keep task, todo, and plan artifacts aligned on every state change
20
+ - JSONM for AI-only files
21
+
22
+ JSONM_EX:
23
+ ```json
24
+ {"v":1,"id":"TASK-003","type":"task","status":"doing","ac":["auth ok"],"files":["src/auth.ts"],"tests":["npm test -- auth"],"ts":"2026-05-24T19:00:00Z"}
25
+ ```
26
+
27
+ LAYERS:
28
+ - L1 project summary
29
+ - L2 arch summary
30
+ - L3 module summaries
31
+ - L4 source files on demand only
32
+
33
+ SIG:
34
+ - ANALYST_COMPLETE
35
+ - ARCHITECT_COMPLETE
36
+ - DEVELOPER_COMPLETE
37
+ - QA_PASS
38
+ - QA_FAIL
39
+ - EXPLORER_COMPLETE
40
+ - ROUTE_VERIFIER_COMPLETE
41
+ - FORM_VERIFIER_COMPLETE
42
+ - A11Y_VERIFIER_COMPLETE
43
+ - API_VERIFIER_COMPLETE
44
+ - JOURNEY_AGENT_COMPLETE
45
+ - RCA_COMPLETE
46
+ - REPAIR_COMPLETE
47
+ - REGRESSION_PASS
48
+ - REGRESSION_FAIL
49
+ - RECOVERY_DONE
50
+ - DOCUMENTER_COMPLETE
51
+ - DEVLOOM_RESUME
52
+ - DEVLOOM_HANG_DETECTED
53
+ - DEVLOOM_DONE