@monoes/monomindcli 1.9.17 → 1.10.1

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 (118) hide show
  1. package/.claude/commands/mastermind/_repeat.md +182 -39
  2. package/.claude/commands/mastermind/architect.md +17 -11
  3. package/.claude/commands/mastermind/brain.md +4 -0
  4. package/.claude/commands/mastermind/build.md +4 -0
  5. package/.claude/commands/mastermind/content.md +4 -0
  6. package/.claude/commands/mastermind/createorg.md +5 -3
  7. package/.claude/commands/mastermind/finance.md +4 -0
  8. package/.claude/commands/mastermind/idea.md +4 -0
  9. package/.claude/commands/mastermind/marketing.md +4 -0
  10. package/.claude/commands/mastermind/master.md +63 -37
  11. package/.claude/commands/mastermind/ops.md +4 -0
  12. package/.claude/commands/mastermind/release.md +4 -0
  13. package/.claude/commands/mastermind/research.md +4 -0
  14. package/.claude/commands/mastermind/review.md +4 -0
  15. package/.claude/commands/mastermind/runorg.md +5 -3
  16. package/.claude/commands/mastermind/sales.md +4 -0
  17. package/.claude/commands/mastermind/techport.md +9 -0
  18. package/.claude/commands/monomind/do.md +5 -1
  19. package/.claude/commands/monomind/idea.md +5 -1
  20. package/.claude/commands/monomind/improve.md +5 -1
  21. package/.claude/commands/monomind/repeat.md +85 -29
  22. package/.claude/commands/monomind/review.md +6 -2
  23. package/.claude/commands/monomind/understand.md +10 -8
  24. package/.claude/helpers/extras-registry.json +235 -235
  25. package/.claude/helpers/graphify-freshen.cjs +13 -1
  26. package/.claude/helpers/hook-handler.cjs +1 -1
  27. package/.claude/helpers/router.cjs +4 -1
  28. package/.claude/skills/mastermind/_protocol.md +28 -21
  29. package/.claude/skills/mastermind/access.md +236 -0
  30. package/.claude/skills/mastermind/activity.md +191 -0
  31. package/.claude/skills/mastermind/adapter-manager.md +259 -0
  32. package/.claude/skills/mastermind/adapters.md +204 -0
  33. package/.claude/skills/mastermind/agent-detail.md +242 -0
  34. package/.claude/skills/mastermind/agents.md +178 -0
  35. package/.claude/skills/mastermind/approval-detail.md +259 -0
  36. package/.claude/skills/mastermind/approve.md +181 -0
  37. package/.claude/skills/mastermind/architect.md +24 -8
  38. package/.claude/skills/mastermind/backup.md +197 -0
  39. package/.claude/skills/mastermind/bootstrap.md +190 -0
  40. package/.claude/skills/mastermind/budgets.md +237 -0
  41. package/.claude/skills/mastermind/companies.md +256 -0
  42. package/.claude/skills/mastermind/costs.md +151 -0
  43. package/.claude/skills/mastermind/createorg.md +23 -5
  44. package/.claude/skills/mastermind/diagnose.md +249 -0
  45. package/.claude/skills/mastermind/env.md +198 -0
  46. package/.claude/skills/mastermind/environments.md +250 -0
  47. package/.claude/skills/mastermind/export.md +324 -0
  48. package/.claude/skills/mastermind/goal-detail.md +255 -0
  49. package/.claude/skills/mastermind/goals.md +149 -0
  50. package/.claude/skills/mastermind/heartbeat.md +164 -0
  51. package/.claude/skills/mastermind/idea.md +250 -122
  52. package/.claude/skills/mastermind/import.md +281 -0
  53. package/.claude/skills/mastermind/inbox.md +214 -0
  54. package/.claude/skills/mastermind/instance-settings.md +315 -0
  55. package/.claude/skills/mastermind/instance.md +231 -0
  56. package/.claude/skills/mastermind/invite-landing.md +227 -0
  57. package/.claude/skills/mastermind/invites.md +254 -0
  58. package/.claude/skills/mastermind/issue-detail.md +291 -0
  59. package/.claude/skills/mastermind/issues.md +235 -0
  60. package/.claude/skills/mastermind/join-queue.md +170 -0
  61. package/.claude/skills/mastermind/liveness.md +392 -0
  62. package/.claude/skills/mastermind/memory.md +321 -0
  63. package/.claude/skills/mastermind/my-issues.md +146 -0
  64. package/.claude/skills/mastermind/new-agent.md +241 -0
  65. package/.claude/skills/mastermind/org-chart.md +207 -0
  66. package/.claude/skills/mastermind/org-settings.md +217 -0
  67. package/.claude/skills/mastermind/plan-to-tasks.md +136 -0
  68. package/.claude/skills/mastermind/plugin-manager.md +241 -0
  69. package/.claude/skills/mastermind/plugin-settings.md +273 -0
  70. package/.claude/skills/mastermind/plugins.md +190 -0
  71. package/.claude/skills/mastermind/profile.md +187 -0
  72. package/.claude/skills/mastermind/project-detail.md +249 -0
  73. package/.claude/skills/mastermind/project-workspace.md +244 -0
  74. package/.claude/skills/mastermind/projects.md +164 -0
  75. package/.claude/skills/mastermind/routine-detail.md +253 -0
  76. package/.claude/skills/mastermind/routines.md +202 -0
  77. package/.claude/skills/mastermind/runorg.md +74 -9
  78. package/.claude/skills/mastermind/search.md +186 -0
  79. package/.claude/skills/mastermind/secrets.md +199 -0
  80. package/.claude/skills/mastermind/skills.md +156 -0
  81. package/.claude/skills/mastermind/tasks.md +149 -0
  82. package/.claude/skills/mastermind/techport.md +5 -5
  83. package/.claude/skills/mastermind/threads.md +259 -0
  84. package/.claude/skills/mastermind/tree-control.md +250 -0
  85. package/.claude/skills/mastermind/wiki.md +314 -0
  86. package/.claude/skills/mastermind/workspace-detail.md +317 -0
  87. package/.claude/skills/mastermind/workspaces.md +261 -0
  88. package/.claude/skills/mastermind/worktree.md +187 -0
  89. package/dist/src/init/executor.js +8 -8
  90. package/dist/src/init/executor.js.map +1 -1
  91. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  92. package/dist/src/init/statusline-generator.js +12 -0
  93. package/dist/src/init/statusline-generator.js.map +1 -1
  94. package/dist/src/ui/.monomind/data/ranked-context.json +1 -1
  95. package/dist/src/ui/.monomind/loops/mastermind-review-1778664132789.json +16 -0
  96. package/dist/src/ui/.monomind/sessions/current.json +5 -5
  97. package/dist/src/ui/.monomind/sessions/session-1776778451399.json +15 -0
  98. package/dist/src/ui/dashboard.html +3030 -181
  99. package/dist/src/ui/data/mastermind-events.jsonl +8 -0
  100. package/dist/src/ui/data/mastermind-sessions.json +1 -0
  101. package/dist/src/ui/server.mjs +738 -0
  102. package/dist/tsconfig.tsbuildinfo +1 -1
  103. package/package.json +2 -2
  104. package/.claude/skills/.monomind/data/ranked-context.json +0 -5
  105. package/.claude/skills/.monomind/sessions/current.json +0 -13
  106. package/.claude/skills/.monomind/sessions/session-1777829336455.json +0 -15
  107. package/.claude/skills/.monomind/sessions/session-1777831614725.json +0 -15
  108. package/.claude/skills/.monomind/sessions/session-1777832095857.json +0 -15
  109. package/.claude/skills/.monomind/sessions/session-1777839814183.json +0 -15
  110. package/.claude/skills/.monomind/sessions/session-1777841847131.json +0 -15
  111. package/.claude/skills/.monomind/sessions/session-1777843309463.json +0 -15
  112. package/.claude/skills/.monomind/sessions/session-1777880867159.json +0 -15
  113. package/.claude/skills/.monomind/sessions/session-1777881884593.json +0 -15
  114. package/.claude/skills/.monomind/sessions/session-1777884090471.json +0 -15
  115. package/.claude/skills/.monomind/sessions/session-1777884808221.json +0 -15
  116. package/.claude/skills/.monomind/sessions/session-1777885672155.json +0 -15
  117. package/.claude/skills/.monomind/sessions/session-1777886852818.json +0 -15
  118. package/.claude/skills/.monomind/sessions/session-1777896532690.json +0 -15
@@ -0,0 +1,314 @@
1
+ ---
2
+ name: mastermind-wiki
3
+ description: Mastermind wiki — org-scoped knowledge base with ingest, query, maintain, lint, and distill operations. Stores durable synthesis in .monomind/orgs/<org>/wiki/ with page citations, raw sources, and change log. Port of Paperclip's LLM Wiki plugin skills adapted for mastermind orgs.
4
+ type: domain-skill
5
+ default_mode: auto
6
+ ---
7
+
8
+ # Mastermind Wiki
9
+
10
+ This skill is invoked by `mastermind:wiki` or directly via `/mastermind:wiki`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org whose wiki to operate on (required)
18
+ - `action`: query | ingest | list | maintain | lint | distill | page
19
+ - `question`: question or search term (required for query)
20
+ - `source`: path or URL to ingest (required for ingest)
21
+ - `page_slug`: wiki page slug to read/write (required for page)
22
+ - `content`: content to write to a page (required for page write)
23
+ - `caller`: command | master
24
+
25
+ ---
26
+
27
+ ## Wiki Structure
28
+
29
+ ```
30
+ .monomind/orgs/<org>/wiki/
31
+ index.md ← navigation hub; must be kept current
32
+ log.md ← append-only change log
33
+ concepts/ ← concepts, definitions, architectural decisions
34
+ projects/ ← per-project knowledge (standup.md + index.md)
35
+ synthesis/ ← synthesized answers filed from queries
36
+ raw/ ← raw source material (never modified after ingest)
37
+ ```
38
+
39
+ **Invariants:**
40
+ - Raw sources in `raw/` are NEVER modified after ingest
41
+ - Every durable page write must append a `log.md` entry
42
+ - `index.md` must be updated when pages are added or removed
43
+ - Answers cite wiki pages or raw sources inline, not in footnote blocks
44
+
45
+ ---
46
+
47
+ ## Step 0 — Brain Load (standalone only)
48
+
49
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
50
+
51
+ ---
52
+
53
+ ## Step 1 — Resolve Wiki Root
54
+
55
+ ```bash
56
+ orgFile=".monomind/orgs/${org_name}.json"
57
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
58
+
59
+ wikiRoot=".monomind/orgs/${org_name}/wiki"
60
+ mkdir -p "$wikiRoot/concepts" "$wikiRoot/projects" "$wikiRoot/synthesis" "$wikiRoot/raw"
61
+
62
+ if [ ! -f "$wikiRoot/index.md" ]; then
63
+ cat > "$wikiRoot/index.md" << EOF
64
+ # Wiki — ${org_name}
65
+
66
+ This is the org knowledge base. Navigate by category or search with \`/mastermind:wiki --action query\`.
67
+
68
+ ## Concepts
69
+ (none yet)
70
+
71
+ ## Projects
72
+ (none yet)
73
+
74
+ ## Synthesis
75
+ (none yet)
76
+ EOF
77
+ fi
78
+
79
+ [ ! -f "$wikiRoot/log.md" ] && echo "# Wiki Log — ${org_name}" > "$wikiRoot/log.md"
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Step 2 — Execute Action
85
+
86
+ ### query (default)
87
+
88
+ Answer a question from what the wiki contains, with citations.
89
+
90
+ ```bash
91
+ [ -z "$question" ] && { echo "ERROR: --question required."; exit 1; }
92
+ echo "WIKI QUERY — ${org_name}"
93
+ echo "Q: $question"
94
+ echo "────────────────────────────────────────────────────────"
95
+
96
+ python3 - "$wikiRoot" "$question" <<'PYEOF'
97
+ import os, sys, re
98
+ root, query = sys.argv[1], sys.argv[2].lower()
99
+ hits = []
100
+
101
+ def scan_dir(d, prefix):
102
+ if not os.path.isdir(d): return
103
+ for fname in os.listdir(d):
104
+ if not fname.endswith(".md"): continue
105
+ fpath = os.path.join(d, fname)
106
+ try:
107
+ text = open(fpath).read()
108
+ if query in text.lower():
109
+ snippet = ""
110
+ for line in text.split("\n"):
111
+ if query in line.lower():
112
+ snippet = line.strip()[:120]
113
+ break
114
+ hits.append((prefix + "/" + fname, snippet))
115
+ except: pass
116
+
117
+ scan_dir(os.path.join(root, "concepts"), "concepts")
118
+ scan_dir(os.path.join(root, "synthesis"), "synthesis")
119
+ scan_dir(os.path.join(root, "projects"), "projects")
120
+ scan_dir(os.path.join(root, "raw"), "raw")
121
+
122
+ if not hits:
123
+ print(" No wiki pages match that query.")
124
+ print(" Use --action ingest to add source material, or --action distill to synthesize from org data.")
125
+ else:
126
+ print(f" {len(hits)} page(s) match:")
127
+ for path, snippet in hits[:10]:
128
+ print(f"\n [[{path}]]")
129
+ if snippet: print(f" → {snippet}")
130
+ PYEOF
131
+ ```
132
+
133
+ ### list
134
+
135
+ Show all wiki pages.
136
+
137
+ ```bash
138
+ echo "WIKI INDEX — ${org_name}"
139
+ echo "────────────────────────────────────────────────────────"
140
+ cat "$wikiRoot/index.md"
141
+ echo ""
142
+ echo " Raw sources: $(ls $wikiRoot/raw/ 2>/dev/null | wc -l) file(s)"
143
+ ```
144
+
145
+ ### ingest
146
+
147
+ Add a raw source file to the wiki. Raw sources are immutable after ingest.
148
+
149
+ ```bash
150
+ [ -z "$source" ] && { echo "ERROR: --source required (path to file)."; exit 1; }
151
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
152
+ srcBase=$(basename "$source")
153
+ dstPath="$wikiRoot/raw/$srcBase"
154
+
155
+ if [ -f "$dstPath" ]; then
156
+ echo " Already ingested: $srcBase"
157
+ else
158
+ cp "$source" "$dstPath" && echo " Ingested: $srcBase → $wikiRoot/raw/"
159
+ echo "$(date -u +%Y-%m-%d) | ingest | raw/$srcBase" >> "$wikiRoot/log.md"
160
+ fi
161
+ echo " To synthesize a page from this source, use: /mastermind:wiki --action distill --source $srcBase"
162
+ ```
163
+
164
+ ### page
165
+
166
+ Read or write a specific wiki page.
167
+
168
+ ```bash
169
+ [ -z "$page_slug" ] && { echo "ERROR: --page-slug required."; exit 1; }
170
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
171
+
172
+ if [ -n "$content" ]; then
173
+ # Write/update
174
+ pageDir="$wikiRoot/$(dirname $page_slug)"
175
+ mkdir -p "$pageDir"
176
+ pagePath="$wikiRoot/${page_slug}.md"
177
+ echo "$content" > "$pagePath"
178
+ echo "$(date -u +%Y-%m-%d) | update | ${page_slug}" >> "$wikiRoot/log.md"
179
+ echo " Page written: $pagePath"
180
+ echo " Remember to update index.md if this is a new page."
181
+ else
182
+ # Read
183
+ pagePath="$wikiRoot/${page_slug}.md"
184
+ if [ -f "$pagePath" ]; then
185
+ cat "$pagePath"
186
+ else
187
+ echo " Page not found: $page_slug"
188
+ echo " Available pages:"
189
+ find "$wikiRoot" -name "*.md" ! -name "index.md" ! -name "log.md" | sed "s|$wikiRoot/||"
190
+ fi
191
+ fi
192
+ ```
193
+
194
+ ### distill
195
+
196
+ Synthesize a wiki page from raw sources and org data. The AI synthesizes based on context, writes the page, and logs it.
197
+
198
+ ```bash
199
+ [ -z "$page_slug" ] && { echo "ERROR: --page-slug required."; exit 1; }
200
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
201
+ pagePath="$wikiRoot/${page_slug}.md"
202
+
203
+ echo "WIKI DISTILL — ${org_name}"
204
+ echo "Target: ${page_slug}"
205
+ echo "────────────────────────────────────────────────────────"
206
+
207
+ if [ -n "$source" ] && [ -f "$wikiRoot/raw/$source" ]; then
208
+ echo "Source: $wikiRoot/raw/$source"
209
+ cat "$wikiRoot/raw/$source"
210
+ fi
211
+
212
+ echo ""
213
+ echo " Use the above source material to write a synthesis page at $pagePath."
214
+ echo " The page should: answer the most important questions, cite raw/ sources inline,"
215
+ echo " use a terse factual voice, and avoid summarizing what is already obvious."
216
+ echo " After writing, update index.md to link to the new page and append a distill log entry."
217
+ ```
218
+
219
+ ### maintain
220
+
221
+ Check wiki health: stale pages, missing index links, unreferenced raw sources.
222
+
223
+ ```bash
224
+ echo "WIKI HEALTH — ${org_name}"
225
+ echo "────────────────────────────────────────────────────────"
226
+
227
+ python3 - "$wikiRoot" <<'PYEOF'
228
+ import os, sys
229
+ root = sys.argv[1]
230
+
231
+ pages = []
232
+ for subdir in ["concepts","projects","synthesis"]:
233
+ d = os.path.join(root, subdir)
234
+ if not os.path.isdir(d): continue
235
+ for f in os.listdir(d):
236
+ if f.endswith(".md"): pages.append(f"{subdir}/{f}")
237
+
238
+ raw_sources = os.listdir(os.path.join(root,"raw")) if os.path.isdir(os.path.join(root,"raw")) else []
239
+
240
+ # Check index.md links
241
+ index_text = open(os.path.join(root,"index.md")).read() if os.path.exists(os.path.join(root,"index.md")) else ""
242
+ missing_links = [p for p in pages if p not in index_text]
243
+ orphan_raw = [r for r in raw_sources if r not in index_text and not any(r in open(os.path.join(root,p)).read() for p in pages if os.path.exists(os.path.join(root,p)))]
244
+
245
+ print(f" Pages: {len(pages)}")
246
+ print(f" Raw sources: {len(raw_sources)}")
247
+ print()
248
+ if missing_links:
249
+ print(f" ⚠ {len(missing_links)} page(s) not in index.md:")
250
+ for p in missing_links: print(f" · {p}")
251
+ else:
252
+ print(" ✓ All pages listed in index.md")
253
+ if orphan_raw:
254
+ print(f"\n ⚠ {len(orphan_raw)} raw source(s) not referenced by any page:")
255
+ for r in orphan_raw: print(f" · raw/{r}")
256
+ else:
257
+ print(" ✓ All raw sources referenced")
258
+ PYEOF
259
+ ```
260
+
261
+ ### lint
262
+
263
+ Validate page formatting: headers, citations, no broken links.
264
+
265
+ ```bash
266
+ echo "WIKI LINT — ${org_name}"
267
+ echo "────────────────────────────────────────────────────────"
268
+
269
+ python3 - "$wikiRoot" <<'PYEOF'
270
+ import os, sys, re
271
+ root = sys.argv[1]
272
+ issues = []
273
+
274
+ for subdir in ["concepts","projects","synthesis"]:
275
+ d = os.path.join(root, subdir)
276
+ if not os.path.isdir(d): continue
277
+ for fname in os.listdir(d):
278
+ if not fname.endswith(".md"): continue
279
+ fpath = os.path.join(d, fname)
280
+ text = open(fpath).read()
281
+ path = f"{subdir}/{fname}"
282
+ if not text.strip().startswith("#"):
283
+ issues.append(f" {path}: missing H1 title")
284
+ wikilinks = re.findall(r'\[\[([^\]]+)\]\]', text)
285
+ for wl in wikilinks:
286
+ candidate = os.path.join(root, wl.lstrip("/"))
287
+ if not os.path.exists(candidate) and not os.path.exists(candidate+".md"):
288
+ issues.append(f" {path}: broken wiki-link [[{wl}]]")
289
+
290
+ if not issues:
291
+ print(" ✓ No lint issues found.")
292
+ else:
293
+ print(f" {len(issues)} issue(s):")
294
+ for i in issues: print(i)
295
+ PYEOF
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Step 3 — Return Output
301
+
302
+ ```yaml
303
+ domain: ops
304
+ status: complete
305
+ action: <action>
306
+ org_name: <org_name>
307
+ wiki_root: .monomind/orgs/<org_name>/wiki/
308
+ ```
309
+
310
+ ---
311
+
312
+ ## Step 4 — Brain Write (standalone only)
313
+
314
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: mastermind-workspace-detail
3
+ description: Mastermind workspace-detail — deep per-execution-workspace inspection and runtime control. Manage services, provision/teardown/cleanup commands, linked issues and routines, runtime logs, and configuration for a single execution workspace.
4
+ type: domain-skill
5
+ default_mode: confirm
6
+ ---
7
+
8
+ # Mastermind Workspace Detail
9
+
10
+ This skill is invoked by `mastermind:workspace-detail` or directly via `/mastermind:workspace-detail`.
11
+
12
+ ---
13
+
14
+ ## Inputs
15
+
16
+ - `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
17
+ - `org_name`: org the workspace belongs to (required)
18
+ - `workspace_id`: execution workspace id (required)
19
+ - `action`: show | services | provision | teardown | cleanup | runtime-logs | issues | routines | config
20
+ - `provision_command`: shell command to provision the workspace (for config action)
21
+ - `teardown_command`: shell command to tear down the workspace (for config action)
22
+ - `cleanup_command`: shell command for workspace cleanup (for config action)
23
+ - `cwd`: working directory override (for config action)
24
+ - `repo_url`: repository URL (for config action)
25
+ - `base_ref`: git base ref/branch (for config action)
26
+ - `branch_name`: branch name for the workspace (for config action)
27
+ - `log_lines`: number of runtime log lines to show (default 50)
28
+ - `caller`: command | master
29
+
30
+ ---
31
+
32
+ ## Workspace Tabs (mirrors ExecutionWorkspaceDetail.tsx)
33
+
34
+ | Tab | Description |
35
+ |-----|-------------|
36
+ | `services` | Running service processes in this workspace |
37
+ | `configuration` | Provision/teardown/cleanup commands, repo, branch, cwd |
38
+ | `runtime_logs` | Live or recent runtime logs from workspace processes |
39
+ | `issues` | Issues currently assigned to or running in this workspace |
40
+ | `routines` | Routines with workspace-specific variable bindings |
41
+
42
+ ---
43
+
44
+ ## Step 0 — Brain Load (standalone only)
45
+
46
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
47
+
48
+ ---
49
+
50
+ ## Step 1 — Load Workspace Data
51
+
52
+ ```bash
53
+ orgFile=".monomind/orgs/${org_name}.json"
54
+ [ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
55
+
56
+ wsFile=".monomind/orgs/${org_name}-workspaces.json"
57
+ [ ! -f "$wsFile" ] && { echo "ERROR: No workspaces file for org '$org_name'. Create workspaces via /mastermind:workspaces."; exit 1; }
58
+
59
+ wsDef=$(jq -r --arg id "$workspace_id" '.workspaces[] | select(.id == $id)' "$wsFile")
60
+ [ -z "$wsDef" ] && { echo "ERROR: Workspace '$workspace_id' not found in org '$org_name'."; exit 1; }
61
+
62
+ issuesFile=".monomind/orgs/${org_name}-issues.json"
63
+ routinesFile=".monomind/orgs/${org_name}-routines.json"
64
+ logFile=".monomind/orgs/${org_name}-workspace-logs/${workspace_id}.log"
65
+ ```
66
+
67
+ ---
68
+
69
+ ## Step 2 — Execute Action
70
+
71
+ ### show (default)
72
+
73
+ ```bash
74
+ echo "EXECUTION WORKSPACE — $workspace_id @ $org_name"
75
+ echo "────────────────────────────────────────────────────────"
76
+
77
+ echo "$wsDef" | jq -r '
78
+ " ID: \(.id)",
79
+ " Project: \(.project_id // "(none)")",
80
+ " Agent: \(.agent_id // "(unassigned)")",
81
+ " Status: \(.status // "unknown")",
82
+ " Branch: \(.branch // "?")",
83
+ " Base ref: \(.base_ref // "?")",
84
+ " Repo URL: \(.repo_url // "(local)")",
85
+ " CWD: \(.cwd // .worktree_path // "(none)")",
86
+ " Created: \(.createdAt // "-")",
87
+ " Last active: \(.lastActiveAt // "-")"
88
+ '
89
+
90
+ # Services
91
+ svcCount=$(echo "$wsDef" | jq -r '(.services // []) | length')
92
+ echo ""
93
+ echo " Services running: $svcCount"
94
+ echo "$wsDef" | jq -r '(.services // [])[] | " · \(.)"'
95
+
96
+ # Config summary
97
+ hasProvision=$(echo "$wsDef" | jq -r 'if .config.provisionCommand then "yes" else "no" end')
98
+ hasTeardown=$(echo "$wsDef" | jq -r 'if .config.teardownCommand then "yes" else "no" end')
99
+ echo ""
100
+ echo " Provision cmd: $hasProvision"
101
+ echo " Teardown cmd: $hasTeardown"
102
+ ```
103
+
104
+ ### services
105
+
106
+ ```bash
107
+ echo "SERVICES — $workspace_id"
108
+ echo "────────────────────────────────────────────────────────"
109
+
110
+ services=$(echo "$wsDef" | jq -r '(.services // [])[]')
111
+ if [ -z "$services" ]; then
112
+ echo " No services running."
113
+ else
114
+ echo "$wsDef" | jq -r '.services // [] | to_entries[] |
115
+ " [\(.key)] \(.value)"' 2>/dev/null || \
116
+ echo "$wsDef" | jq -r '(.services // [])[] | " · \(.)"'
117
+ fi
118
+
119
+ echo ""
120
+ echo " Workspace path: $(echo "$wsDef" | jq -r '.worktree_path // "(none)"')"
121
+ echo " Status: $(echo "$wsDef" | jq -r '.status // "unknown"')"
122
+ ```
123
+
124
+ ### provision
125
+
126
+ ```bash
127
+ echo "PROVISION — $workspace_id"
128
+ echo "────────────────────────────────────────────────────────"
129
+
130
+ provCmd=$(echo "$wsDef" | jq -r '.config.provisionCommand // ""')
131
+ wsPath=$(echo "$wsDef" | jq -r '.worktree_path // .cwd // ""')
132
+
133
+ if [ -z "$provCmd" ]; then
134
+ echo " No provision command configured."
135
+ echo " Set one: --action config --provision-command 'npm install && npm run build'"
136
+ else
137
+ echo " Command: $provCmd"
138
+ echo " CWD: $wsPath"
139
+ echo ""
140
+ echo " To run: cd '$wsPath' && $provCmd"
141
+ echo ""
142
+ if [ -d "$wsPath" ] && [ -n "$provCmd" ]; then
143
+ echo " Executing provision command…"
144
+ (cd "$wsPath" && eval "$provCmd") && {
145
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
146
+ tmp="${wsFile}.tmp"
147
+ jq --arg id "$workspace_id" --arg ts "$ts" \
148
+ '.workspaces = [.workspaces[] | if .id == $id then .last_provisioned = $ts else . end]' \
149
+ "$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
150
+ echo " Provision complete."
151
+ } || echo " Provision command exited with error."
152
+ else
153
+ [ -z "$wsPath" ] && echo " ERROR: No worktree_path set — cannot execute provision command automatically."
154
+ fi
155
+ fi
156
+ ```
157
+
158
+ ### teardown
159
+
160
+ ```bash
161
+ echo "TEARDOWN — $workspace_id"
162
+ echo "────────────────────────────────────────────────────────"
163
+
164
+ tdCmd=$(echo "$wsDef" | jq -r '.config.teardownCommand // ""')
165
+ wsPath=$(echo "$wsDef" | jq -r '.worktree_path // .cwd // ""')
166
+
167
+ if [ -z "$tdCmd" ]; then
168
+ echo " No teardown command configured."
169
+ else
170
+ echo " Command: $tdCmd"
171
+ echo " CWD: $wsPath"
172
+ if [ -d "$wsPath" ]; then
173
+ echo " Executing teardown command…"
174
+ (cd "$wsPath" && eval "$tdCmd") && echo " Teardown complete." || echo " Teardown command exited with error."
175
+ fi
176
+ fi
177
+ ```
178
+
179
+ ### cleanup
180
+
181
+ ```bash
182
+ echo "CLEANUP — $workspace_id"
183
+ echo "────────────────────────────────────────────────────────"
184
+
185
+ cleanCmd=$(echo "$wsDef" | jq -r '.config.cleanupCommand // ""')
186
+ wsPath=$(echo "$wsDef" | jq -r '.worktree_path // .cwd // ""')
187
+
188
+ if [ -z "$cleanCmd" ]; then
189
+ echo " No cleanup command configured."
190
+ else
191
+ echo " Command: $cleanCmd"
192
+ if [ -d "$wsPath" ]; then
193
+ (cd "$wsPath" && eval "$cleanCmd") && echo " Cleanup complete." || echo " Cleanup exited with error."
194
+ fi
195
+ fi
196
+ ```
197
+
198
+ ### runtime-logs
199
+
200
+ ```bash
201
+ lines=${log_lines:-50}
202
+ echo "RUNTIME LOGS — $workspace_id (last $lines lines)"
203
+ echo "────────────────────────────────────────────────────────"
204
+
205
+ if [ -f "$logFile" ]; then
206
+ tail -${lines} "$logFile"
207
+ else
208
+ # Try workspace path stderr/stdout logs
209
+ wsPath=$(echo "$wsDef" | jq -r '.worktree_path // ""')
210
+ found=false
211
+ for logPath in "${wsPath}/.monomind/runtime.log" "${wsPath}/logs/runtime.log" "${wsPath}/output.log"; do
212
+ if [ -f "$logPath" ]; then
213
+ tail -${lines} "$logPath"
214
+ found=true
215
+ break
216
+ fi
217
+ done
218
+ "$found" || echo " No runtime logs found. Logs are written to .monomind/workspace-logs/$workspace_id.log during runs."
219
+ fi
220
+ ```
221
+
222
+ ### issues
223
+
224
+ ```bash
225
+ echo "ISSUES — workspace: $workspace_id"
226
+ echo "────────────────────────────────────────────────────────"
227
+ printf "%-24s %-12s %-10s %s\n" "ID" "STATUS" "PRIORITY" "TITLE"
228
+ echo "────────────────────────────────────────────────────────"
229
+
230
+ if [ ! -f "$issuesFile" ]; then
231
+ echo " No issues file found."
232
+ else
233
+ jq -r --arg wid "$workspace_id" '.issues[] |
234
+ select(.workspace_id == $wid or (.assigned_workspace == $wid)) |
235
+ [.id, (.status // "open"), (.priority // "medium"), (.title // "(no title)")] | @tsv' \
236
+ "$issuesFile" | while IFS=$'\t' read -r id st pri title; do
237
+ printf "%-24s %-12s %-10s %s\n" "$id" "$st" "$pri" "$title"
238
+ done || echo " No issues assigned to this workspace."
239
+ fi
240
+ ```
241
+
242
+ ### routines
243
+
244
+ ```bash
245
+ echo "ROUTINES — workspace: $workspace_id"
246
+ echo "────────────────────────────────────────────────────────"
247
+
248
+ if [ ! -f "$routinesFile" ]; then
249
+ echo " No routines file found."
250
+ else
251
+ # Show routines that have workspace-specific variable bindings
252
+ jq -r --arg wid "$workspace_id" \
253
+ '.routines[] | select((.variables // {}) | to_entries[] | .key | startswith("WS_") or contains("workspace")) |
254
+ "\(.id) \(.name // "(no name)") vars: \((.variables // {}) | keys | join(", "))"' \
255
+ "$routinesFile" 2>/dev/null || echo " No routines with workspace-specific variables."
256
+ fi
257
+
258
+ echo ""
259
+ echo "To run a routine with workspace vars: /mastermind:routine-detail --org $org_name --routine-id <id> --action variables"
260
+ ```
261
+
262
+ ### config
263
+
264
+ ```bash
265
+ echo "WORKSPACE CONFIG — $workspace_id"
266
+ echo "────────────────────────────────────────────────────────"
267
+
268
+ if [ -n "$provision_command" ] || [ -n "$teardown_command" ] || [ -n "$cleanup_command" ] || \
269
+ [ -n "$cwd" ] || [ -n "$repo_url" ] || [ -n "$base_ref" ] || [ -n "$branch_name" ]; then
270
+
271
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
272
+ tmp="${wsFile}.tmp"
273
+ jq --arg id "$workspace_id" \
274
+ --arg prov "${provision_command:-}" \
275
+ --arg td "${teardown_command:-}" \
276
+ --arg clean "${cleanup_command:-}" \
277
+ --arg cwd_ "${cwd:-}" \
278
+ --arg repo "${repo_url:-}" \
279
+ --arg base "${base_ref:-}" \
280
+ --arg branch "${branch_name:-}" \
281
+ --arg ts "$ts" \
282
+ '.workspaces = [.workspaces[] | if .id == $id then
283
+ if .config == null then .config = {} else . end |
284
+ (if $prov != "" then .config.provisionCommand = $prov else . end) |
285
+ (if $td != "" then .config.teardownCommand = $td else . end) |
286
+ (if $clean != "" then .config.cleanupCommand = $clean else . end) |
287
+ (if $cwd_ != "" then .cwd = $cwd_ else . end) |
288
+ (if $repo != "" then .repo_url = $repo else . end) |
289
+ (if $base != "" then .base_ref = $base else . end) |
290
+ (if $branch != "" then .branch = $branch else . end) |
291
+ .lastActiveAt = $ts
292
+ else . end]' \
293
+ "$wsFile" > "$tmp" && mv "$tmp" "$wsFile"
294
+ echo "Config updated for workspace '$workspace_id'."
295
+ else
296
+ echo "$wsDef" | jq '{id, project_id, agent_id, status, branch, base_ref, repo_url, cwd, config}'
297
+ fi
298
+ ```
299
+
300
+ ---
301
+
302
+ ## Step 3 — Return Output
303
+
304
+ ```yaml
305
+ domain: ops
306
+ status: complete
307
+ action: <action>
308
+ org: <org_name>
309
+ workspace_id: <workspace_id>
310
+ workspace_status: <status>
311
+ ```
312
+
313
+ ---
314
+
315
+ ## Step 4 — Brain Write (standalone only)
316
+
317
+ If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.