@monoes/monomindcli 1.11.7 → 1.11.9

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 (222) hide show
  1. package/.claude/agents/github/issue-tracker.md +5 -5
  2. package/.claude/agents/github/pr-manager.md +5 -5
  3. package/.claude/agents/github/release-manager.md +3 -3
  4. package/.claude/agents/github/repo-architect.md +3 -3
  5. package/.claude/agents/github/swarm-issue.md +1 -1
  6. package/.claude/agents/github/sync-coordinator.md +1 -1
  7. package/.claude/agents/github/workflow-automation.md +1 -1
  8. package/.claude/commands/github/repo-architect.md +1 -1
  9. package/.claude/commands/github/sync-coordinator.md +1 -1
  10. package/.claude/commands/mastermind/createorg.md +4 -1
  11. package/.claude/commands/mastermind/help.md +2 -2
  12. package/.claude/commands/mastermind/orgs.md +21 -0
  13. package/.claude/commands/mastermind/orgstatus.md +59 -0
  14. package/.claude/commands/mastermind/runorg.md +4 -2
  15. package/.claude/commands/mastermind/stoporg.md +78 -0
  16. package/.claude/commands/mastermind/swarm.md +1 -1
  17. package/.claude/helpers/handlers/gates-handler.cjs +135 -0
  18. package/.claude/helpers/handlers/task-handler.cjs +7 -3
  19. package/.claude/helpers/hook-handler.cjs +11 -2
  20. package/.claude/helpers/intelligence.cjs +87 -0
  21. package/.claude/helpers/learning-service.mjs +60 -0
  22. package/.claude/helpers/memory.cjs +69 -0
  23. package/.claude/helpers/router.cjs +68 -0
  24. package/.claude/helpers/session.cjs +63 -0
  25. package/.claude/helpers/utils/monograph.cjs +4 -2
  26. package/.claude/helpers/utils/telemetry.cjs +3 -2
  27. package/.claude/skills/agentic-jujutsu/SKILL.md +1 -1
  28. package/.claude/skills/hive-mind-advanced/SKILL.md +4 -4
  29. package/.claude/skills/mastermind/_agent-select.md +2 -2
  30. package/.claude/skills/mastermind/access.md +11 -11
  31. package/.claude/skills/mastermind/adapter-manager.md +13 -13
  32. package/.claude/skills/mastermind/adapters.md +7 -7
  33. package/.claude/skills/mastermind/agent-detail.md +1 -1
  34. package/.claude/skills/mastermind/agents.md +5 -5
  35. package/.claude/skills/mastermind/approval-detail.md +6 -6
  36. package/.claude/skills/mastermind/approve.md +9 -10
  37. package/.claude/skills/mastermind/backup.md +2 -2
  38. package/.claude/skills/mastermind/bootstrap.md +2 -2
  39. package/.claude/skills/mastermind/companies.md +7 -7
  40. package/.claude/skills/mastermind/createorg.md +213 -8
  41. package/.claude/skills/mastermind/diagnose.md +4 -4
  42. package/.claude/skills/mastermind/env.md +1 -1
  43. package/.claude/skills/mastermind/environments.md +8 -8
  44. package/.claude/skills/mastermind/export.md +12 -3
  45. package/.claude/skills/mastermind/goal-detail.md +9 -9
  46. package/.claude/skills/mastermind/goals.md +4 -4
  47. package/.claude/skills/mastermind/heartbeat.md +1 -1
  48. package/.claude/skills/mastermind/idea.md +4 -4
  49. package/.claude/skills/mastermind/import.md +8 -8
  50. package/.claude/skills/mastermind/inbox.md +4 -4
  51. package/.claude/skills/mastermind/instance-settings.md +9 -9
  52. package/.claude/skills/mastermind/instance.md +9 -7
  53. package/.claude/skills/mastermind/invite-landing.md +5 -5
  54. package/.claude/skills/mastermind/invites.md +12 -12
  55. package/.claude/skills/mastermind/issue-detail.md +8 -8
  56. package/.claude/skills/mastermind/monitor.md +11 -11
  57. package/.claude/skills/mastermind/my-issues.md +6 -6
  58. package/.claude/skills/mastermind/new-agent.md +4 -4
  59. package/.claude/skills/mastermind/org-chart.md +8 -6
  60. package/.claude/skills/mastermind/org-settings.md +58 -21
  61. package/.claude/skills/mastermind/orgs.md +98 -0
  62. package/.claude/skills/mastermind/orgstatus.md +194 -0
  63. package/.claude/skills/mastermind/plan-to-tasks.md +1 -1
  64. package/.claude/skills/mastermind/plugin-manager.md +12 -12
  65. package/.claude/skills/mastermind/plugin-settings.md +5 -5
  66. package/.claude/skills/mastermind/plugins.md +5 -5
  67. package/.claude/skills/mastermind/profile.md +2 -2
  68. package/.claude/skills/mastermind/project-detail.md +12 -12
  69. package/.claude/skills/mastermind/project-workspace.md +4 -4
  70. package/.claude/skills/mastermind/projects.md +4 -4
  71. package/.claude/skills/mastermind/review.md +50 -0
  72. package/.claude/skills/mastermind/routine-detail.md +3 -3
  73. package/.claude/skills/mastermind/routines.md +7 -6
  74. package/.claude/skills/mastermind/runorg.md +178 -8
  75. package/.claude/skills/mastermind/search.md +6 -6
  76. package/.claude/skills/mastermind/secrets.md +6 -6
  77. package/.claude/skills/mastermind/skills.md +4 -4
  78. package/.claude/skills/mastermind/stoporg.md +138 -0
  79. package/.claude/skills/mastermind/workspace-detail.md +5 -5
  80. package/.claude/skills/mastermind/workspaces.md +9 -9
  81. package/.claude/skills/performance-analysis/SKILL.md +3 -3
  82. package/.claude/skills/sparc-methodology/SKILL.md +2 -2
  83. package/.claude/skills/swarm-advanced/SKILL.md +4 -4
  84. package/README.md +129 -376
  85. package/dist/src/agents/registry-builder.d.ts +27 -1
  86. package/dist/src/agents/registry-builder.d.ts.map +1 -1
  87. package/dist/src/agents/registry-builder.js +2 -2
  88. package/dist/src/agents/registry-builder.js.map +1 -1
  89. package/dist/src/commands/agent.d.ts.map +1 -1
  90. package/dist/src/commands/agent.js +4 -9
  91. package/dist/src/commands/agent.js.map +1 -1
  92. package/dist/src/commands/analyze.d.ts +1 -1
  93. package/dist/src/commands/analyze.js +1 -1
  94. package/dist/src/commands/claims.d.ts +1 -1
  95. package/dist/src/commands/claims.js +2 -2
  96. package/dist/src/commands/claims.js.map +1 -1
  97. package/dist/src/commands/cleanup.d.ts +1 -1
  98. package/dist/src/commands/cleanup.js +1 -1
  99. package/dist/src/commands/completions.d.ts +1 -1
  100. package/dist/src/commands/completions.js +1 -1
  101. package/dist/src/commands/deployment.d.ts +1 -1
  102. package/dist/src/commands/deployment.js +2 -2
  103. package/dist/src/commands/deployment.js.map +1 -1
  104. package/dist/src/commands/doctor.d.ts +1 -1
  105. package/dist/src/commands/doctor.d.ts.map +1 -1
  106. package/dist/src/commands/doctor.js +69 -4
  107. package/dist/src/commands/doctor.js.map +1 -1
  108. package/dist/src/commands/guidance.d.ts.map +1 -1
  109. package/dist/src/commands/guidance.js +129 -0
  110. package/dist/src/commands/guidance.js.map +1 -1
  111. package/dist/src/commands/index.d.ts.map +1 -1
  112. package/dist/src/commands/index.js +4 -0
  113. package/dist/src/commands/index.js.map +1 -1
  114. package/dist/src/commands/init.d.ts.map +1 -1
  115. package/dist/src/commands/init.js +18 -0
  116. package/dist/src/commands/init.js.map +1 -1
  117. package/dist/src/commands/monovector/import.d.ts +1 -1
  118. package/dist/src/commands/monovector/import.js +1 -1
  119. package/dist/src/commands/monovector/index.d.ts +1 -1
  120. package/dist/src/commands/monovector/index.js +1 -1
  121. package/dist/src/commands/monovector/setup.d.ts +1 -1
  122. package/dist/src/commands/monovector/setup.js +2 -2
  123. package/dist/src/commands/neural.d.ts +1 -1
  124. package/dist/src/commands/neural.js +2 -2
  125. package/dist/src/commands/neural.js.map +1 -1
  126. package/dist/src/commands/performance.d.ts +1 -1
  127. package/dist/src/commands/performance.js +2 -2
  128. package/dist/src/commands/performance.js.map +1 -1
  129. package/dist/src/commands/platforms.d.ts +1 -1
  130. package/dist/src/commands/platforms.js +1 -1
  131. package/dist/src/commands/plugins.d.ts +1 -1
  132. package/dist/src/commands/plugins.d.ts.map +1 -1
  133. package/dist/src/commands/plugins.js +2 -4
  134. package/dist/src/commands/plugins.js.map +1 -1
  135. package/dist/src/commands/providers.d.ts +1 -1
  136. package/dist/src/commands/providers.js +2 -2
  137. package/dist/src/commands/providers.js.map +1 -1
  138. package/dist/src/commands/route.d.ts +1 -1
  139. package/dist/src/commands/route.d.ts.map +1 -1
  140. package/dist/src/commands/route.js +5 -11
  141. package/dist/src/commands/route.js.map +1 -1
  142. package/dist/src/commands/security.d.ts +1 -1
  143. package/dist/src/commands/security.d.ts.map +1 -1
  144. package/dist/src/commands/security.js +140 -91
  145. package/dist/src/commands/security.js.map +1 -1
  146. package/dist/src/dlq/dlq-replayer.d.ts +7 -1
  147. package/dist/src/dlq/dlq-replayer.d.ts.map +1 -1
  148. package/dist/src/dlq/dlq-replayer.js.map +1 -1
  149. package/dist/src/index.d.ts +1 -1
  150. package/dist/src/index.d.ts.map +1 -1
  151. package/dist/src/index.js +10 -26
  152. package/dist/src/index.js.map +1 -1
  153. package/dist/src/init/claudemd-generator.js +2 -2
  154. package/dist/src/init/claudemd-generator.js.map +1 -1
  155. package/dist/src/init/executor.js +3 -3
  156. package/dist/src/init/settings-generator.js +2 -2
  157. package/dist/src/init/settings-generator.js.map +1 -1
  158. package/dist/src/mcp-client.d.ts +5 -0
  159. package/dist/src/mcp-client.d.ts.map +1 -1
  160. package/dist/src/mcp-client.js +7 -0
  161. package/dist/src/mcp-client.js.map +1 -1
  162. package/dist/src/mcp-server.d.ts.map +1 -1
  163. package/dist/src/mcp-server.js +17 -1
  164. package/dist/src/mcp-server.js.map +1 -1
  165. package/dist/src/mcp-tools/a2a-tools.js +6 -6
  166. package/dist/src/mcp-tools/a2a-tools.js.map +1 -1
  167. package/dist/src/mcp-tools/auto-install.d.ts +2 -2
  168. package/dist/src/mcp-tools/auto-install.js +1 -1
  169. package/dist/src/mcp-tools/auto-install.js.map +1 -1
  170. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  171. package/dist/src/mcp-tools/hive-mind-tools.js +1 -52
  172. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  173. package/dist/src/mcp-tools/index.d.ts +4 -0
  174. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  175. package/dist/src/mcp-tools/index.js +4 -0
  176. package/dist/src/mcp-tools/index.js.map +1 -1
  177. package/dist/src/mcp-tools/monograph-compat.d.ts.map +1 -1
  178. package/dist/src/mcp-tools/monograph-compat.js +1 -2
  179. package/dist/src/mcp-tools/monograph-compat.js.map +1 -1
  180. package/dist/src/mcp-tools/monograph-tools.d.ts.map +1 -1
  181. package/dist/src/mcp-tools/monograph-tools.js +107 -5
  182. package/dist/src/mcp-tools/monograph-tools.js.map +1 -1
  183. package/dist/src/mcp-tools/security-tools.d.ts +6 -6
  184. package/dist/src/mcp-tools/security-tools.d.ts.map +1 -1
  185. package/dist/src/mcp-tools/security-tools.js +48 -61
  186. package/dist/src/mcp-tools/security-tools.js.map +1 -1
  187. package/dist/src/memory/memory-bridge.d.ts +0 -1
  188. package/dist/src/memory/memory-bridge.d.ts.map +1 -1
  189. package/dist/src/memory/memory-bridge.js +232 -57
  190. package/dist/src/memory/memory-bridge.js.map +1 -1
  191. package/dist/src/memory/memory-initializer.d.ts.map +1 -1
  192. package/dist/src/memory/memory-initializer.js +3 -32
  193. package/dist/src/memory/memory-initializer.js.map +1 -1
  194. package/dist/src/plugins/store/discovery.d.ts.map +1 -1
  195. package/dist/src/plugins/store/discovery.js +0 -69
  196. package/dist/src/plugins/store/discovery.js.map +1 -1
  197. package/dist/src/routing/embed-worker.d.ts +2 -0
  198. package/dist/src/routing/embed-worker.d.ts.map +1 -0
  199. package/dist/src/routing/embed-worker.js +55 -0
  200. package/dist/src/routing/embed-worker.js.map +1 -0
  201. package/dist/src/routing/embedder.d.ts +31 -0
  202. package/dist/src/routing/embedder.d.ts.map +1 -0
  203. package/dist/src/routing/embedder.js +0 -0
  204. package/dist/src/routing/embedder.js.map +1 -0
  205. package/dist/src/routing/llm-caller.d.ts +1 -1
  206. package/dist/src/routing/llm-caller.d.ts.map +1 -1
  207. package/dist/src/routing/llm-caller.js +18 -3
  208. package/dist/src/routing/llm-caller.js.map +1 -1
  209. package/dist/src/routing/route-layer-factory.d.ts +9 -0
  210. package/dist/src/routing/route-layer-factory.d.ts.map +1 -0
  211. package/dist/src/routing/route-layer-factory.js +151 -0
  212. package/dist/src/routing/route-layer-factory.js.map +1 -0
  213. package/dist/src/services/worker-daemon.d.ts.map +1 -1
  214. package/dist/src/services/worker-daemon.js +0 -1
  215. package/dist/src/services/worker-daemon.js.map +1 -1
  216. package/dist/src/suggest.d.ts +1 -1
  217. package/dist/src/suggest.js +1 -1
  218. package/dist/src/ui/server.mjs +5 -2
  219. package/dist/tsconfig.tsbuildinfo +1 -1
  220. package/package.json +9 -10
  221. package/scripts/publish-registry.ts +0 -2
  222. package/scripts/understand-analyze.mjs +1 -1
@@ -65,9 +65,9 @@ echo "INVITES — org: $org_name"
65
65
  echo "────────────────────────────────────────────────────────"
66
66
 
67
67
  # Active invites (pending in join_requests with type=invite)
68
- activeInvites=$(jq '[.join_requests[] | select(.type == "invite" and .status == "pending")] | length' "$membersFile")
68
+ activeInvites=$(jq '[(.join_requests // [])[] | select(.type == "invite" and .status == "pending")] | length' "$membersFile")
69
69
  totalMembers=$(jq '.members | length' "$membersFile")
70
- pendingJoins=$(jq '[.join_requests[] | select(.type != "invite" and .status == "pending_approval")] | length' "$membersFile")
70
+ pendingJoins=$(jq '[(.join_requests // [])[] | select(.type != "invite" and .status == "pending_approval")] | length' "$membersFile")
71
71
 
72
72
  echo " Members: $totalMembers"
73
73
  echo " Pending invites: $activeInvites"
@@ -78,7 +78,7 @@ if [ "$activeInvites" -gt 0 ]; then
78
78
  echo "ACTIVE INVITES"
79
79
  printf " %-28s %-10s %-20s %s\n" "TOKEN" "ROLE" "CREATED" "URL"
80
80
  echo " ────────────────────────────────────────────────────────"
81
- jq -r '.join_requests[] | select(.type == "invite" and .status == "pending") |
81
+ jq -r '(.join_requests // [])[] | select(.type == "invite" and .status == "pending") |
82
82
  [.token, (.role // "operator"), (.createdAt // "-"), (.inviteUrl // "-")] | @tsv' \
83
83
  "$membersFile" | while IFS=$'\t' read -r tok role ts url; do
84
84
  printf " %-28s %-10s %-20s %s\n" "${tok:0:24}…" "$role" "$ts" "${url:0:40}…"
@@ -126,14 +126,14 @@ echo "To copy URL hint: --action copy-url --invite-id $token"
126
126
 
127
127
  # Find the invite
128
128
  inviteExists=$(jq -r --arg id "$invite_id" \
129
- '[.join_requests[] | select((.id == $id or .token == $id) and .type == "invite")] | length' \
129
+ '[(.join_requests // [])[] | select((.id == $id or .token == $id) and .type == "invite")] | length' \
130
130
  "$membersFile")
131
131
  [ "$inviteExists" -eq 0 ] && { echo "ERROR: Invite '$invite_id' not found or already resolved."; exit 1; }
132
132
 
133
133
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
134
134
  tmp="${membersFile}.tmp"
135
135
  jq --arg id "$invite_id" --arg ts "$ts" \
136
- '.join_requests = [.join_requests[] | if (.id == $id or .token == $id) then
136
+ '.join_requests = [(.join_requests // [])[] | if (.id == $id or .token == $id) then
137
137
  .status = "revoked" | .resolvedAt = $ts
138
138
  else . end]' \
139
139
  "$membersFile" > "$tmp" && mv "$tmp" "$membersFile"
@@ -148,7 +148,7 @@ echo " Revoked at: $ts"
148
148
  [ -z "$invite_id" ] && { echo "ERROR: --invite-id required."; exit 1; }
149
149
 
150
150
  inviteUrl=$(jq -r --arg id "$invite_id" \
151
- '.join_requests[] | select(.id == $id or .token == $id) | .inviteUrl // ""' \
151
+ '(.join_requests // [])[] | select(.id == $id or .token == $id) | .inviteUrl // ""' \
152
152
  "$membersFile")
153
153
  [ -z "$inviteUrl" ] && { echo "ERROR: Invite '$invite_id' not found."; exit 1; }
154
154
 
@@ -172,7 +172,7 @@ echo " Filter: status=$statusFilter type=$typeFilter"
172
172
  echo "────────────────────────────────────────────────────────"
173
173
 
174
174
  jq -r --arg st "$statusFilter" --arg type "$typeFilter" '
175
- .join_requests[] |
175
+ (.join_requests // [])[] |
176
176
  select(
177
177
  (.status == $st) and
178
178
  (.type != "invite") and
@@ -190,7 +190,7 @@ jq -r --arg st "$statusFilter" --arg type "$typeFilter" '
190
190
  echo " → reject: --action reject-join --request-id $id"
191
191
  done
192
192
 
193
- total=$(jq --arg st "$statusFilter" '[.join_requests[] | select(.status == $st and .type != "invite")] | length' "$membersFile")
193
+ total=$(jq --arg st "$statusFilter" '[(.join_requests // [])[] | select(.status == $st and .type != "invite")] | length' "$membersFile")
194
194
  [ "$total" -eq 0 ] && echo " No join requests with status='$statusFilter'."
195
195
  echo ""
196
196
  echo "Total ($statusFilter): $total"
@@ -202,13 +202,13 @@ echo "Total ($statusFilter): $total"
202
202
  [ -z "$request_id" ] && { echo "ERROR: --request-id required."; exit 1; }
203
203
 
204
204
  reqRole=$(jq -r --arg id "$request_id" \
205
- '.join_requests[] | select(.id == $id) | .role // "viewer"' "$membersFile")
205
+ '(.join_requests // [])[] | select(.id == $id) | .role // "viewer"' "$membersFile")
206
206
  [ -z "$reqRole" ] && { echo "ERROR: Request '$request_id' not found."; exit 1; }
207
207
 
208
208
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
209
209
  tmp="${membersFile}.tmp"
210
210
  jq --arg id "$request_id" --arg role "$reqRole" --arg ts "$ts" \
211
- '.join_requests = [.join_requests[] | if .id == $id then .status = "approved" | .resolvedAt = $ts else . end] |
211
+ '.join_requests = [(.join_requests // [])[] | if .id == $id then .status = "approved" | .resolvedAt = $ts else . end] |
212
212
  .members += [{"id":$id,"role":$role,"status":"active","grants":[],"joinedAt":$ts}]' \
213
213
  "$membersFile" > "$tmp" && mv "$tmp" "$membersFile"
214
214
 
@@ -222,13 +222,13 @@ echo " Member added. View members: /mastermind:access --org $org_name --action
222
222
  ```bash
223
223
  [ -z "$request_id" ] && { echo "ERROR: --request-id required."; exit 1; }
224
224
 
225
- exists=$(jq -r --arg id "$request_id" '[.join_requests[] | select(.id == $id)] | length' "$membersFile")
225
+ exists=$(jq -r --arg id "$request_id" '[(.join_requests // [])[] | select(.id == $id)] | length' "$membersFile")
226
226
  [ "$exists" -eq 0 ] && { echo "ERROR: Request '$request_id' not found."; exit 1; }
227
227
 
228
228
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
229
229
  tmp="${membersFile}.tmp"
230
230
  jq --arg id "$request_id" --arg ts "$ts" \
231
- '.join_requests = [.join_requests[] | if .id == $id then .status = "rejected" | .resolvedAt = $ts else . end]' \
231
+ '.join_requests = [(.join_requests // [])[] | if .id == $id then .status = "rejected" | .resolvedAt = $ts else . end]' \
232
232
  "$membersFile" > "$tmp" && mv "$tmp" "$membersFile"
233
233
 
234
234
  echo "Join request '$request_id' rejected."
@@ -54,7 +54,7 @@ orgFile=".monomind/orgs/${org_name}.json"
54
54
  issuesFile=".monomind/orgs/${org_name}-issues.json"
55
55
  [ ! -f "$issuesFile" ] && { echo "ERROR: No issues file for org '$org_name'. Create tasks via /mastermind:tasks."; exit 1; }
56
56
 
57
- issueDef=$(jq -r --arg id "$issue_id" '.issues[] | select(.id == $id or .slug == $id)' "$issuesFile")
57
+ issueDef=$(jq -r --arg id "$issue_id" '(.issues // [])[] | select(.id == $id or .slug == $id)' "$issuesFile")
58
58
  [ -z "$issueDef" ] && { echo "ERROR: Issue '$issue_id' not found in org '$org_name'."; exit 1; }
59
59
 
60
60
  resolvedId=$(echo "$issueDef" | jq -r '.id')
@@ -86,7 +86,7 @@ echo "$issueDef" | jq -r '
86
86
  '
87
87
 
88
88
  # Sub-issues
89
- subCount=$(jq --arg pid "$resolvedId" '[.issues[] | select(.parent_id == $pid)] | length' "$issuesFile" 2>/dev/null || echo 0)
89
+ subCount=$(jq --arg pid "$resolvedId" '[(.issues // [])[] | select(.parent_id == $pid)] | length' "$issuesFile" 2>/dev/null || echo 0)
90
90
  echo " Sub-issues: $subCount"
91
91
 
92
92
  # Attachments
@@ -169,7 +169,7 @@ printf "%-24s %-12s %-10s %s\n" "ID" "STATUS" "PRIORITY" "TITLE"
169
169
  echo "────────────────────────────────────────────────────────"
170
170
 
171
171
  count=0
172
- jq -r --arg pid "$resolvedId" '.issues[] | select(.parent_id == $pid) |
172
+ jq -r --arg pid "$resolvedId" '(.issues // [])[] | select(.parent_id == $pid) |
173
173
  [.id, (.status // "open"), (.priority // "medium"), (.title // "(no title)")] | @tsv' \
174
174
  "$issuesFile" 2>/dev/null | while IFS=$'\t' read -r id st pri title; do
175
175
  printf "%-24s %-12s %-10s %s\n" "$id" "$st" "$pri" "$title"
@@ -215,13 +215,13 @@ echo " Time: $ts"
215
215
  [ -z "$assignee_id" ] && { echo "ERROR: --assignee-id required."; exit 1; }
216
216
 
217
217
  # Validate agent exists in org
218
- exists=$(jq --arg id "$assignee_id" '[.roles[] | select(.id == $id)] | length' "$orgFile")
218
+ exists=$(jq --arg id "$assignee_id" '[(.roles // [])[] | select(.id == $id)] | length' "$orgFile")
219
219
  [ "$exists" -eq 0 ] && echo "WARNING: Agent '$assignee_id' not found in org '$org_name'. Assigning anyway."
220
220
 
221
221
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
222
222
  tmp="${issuesFile}.tmp"
223
223
  jq --arg id "$resolvedId" --arg ag "$assignee_id" --arg ts "$ts" \
224
- '.issues = [.issues[] | if .id == $id then .assignee_id = $ag | .updated_at = $ts else . end]' \
224
+ '.issues = [(.issues // [])[] | if .id == $id then .assignee_id = $ag | .updated_at = $ts else . end]' \
225
225
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
226
226
 
227
227
  echo "Issue '$issue_id' assigned to '$assignee_id'."
@@ -233,7 +233,7 @@ echo "Issue '$issue_id' assigned to '$assignee_id'."
233
233
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
234
234
  tmp="${issuesFile}.tmp"
235
235
  jq --arg id "$resolvedId" --arg ts "$ts" \
236
- '.issues = [.issues[] | if .id == $id then .status = "done" | .updated_at = $ts | .closed_at = $ts else . end]' \
236
+ '.issues = [(.issues // [])[] | if .id == $id then .status = "done" | .updated_at = $ts | .closed_at = $ts else . end]' \
237
237
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
238
238
  echo "Issue '$issue_id' → done (closed at $ts)."
239
239
  ```
@@ -244,7 +244,7 @@ echo "Issue '$issue_id' → done (closed at $ts)."
244
244
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
245
245
  tmp="${issuesFile}.tmp"
246
246
  jq --arg id "$resolvedId" --arg ts "$ts" \
247
- '.issues = [.issues[] | if .id == $id then .status = "open" | .updated_at = $ts | .closed_at = null else . end]' \
247
+ '.issues = [(.issues // [])[] | if .id == $id then .status = "open" | .updated_at = $ts | .closed_at = null else . end]' \
248
248
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
249
249
  echo "Issue '$issue_id' → reopened."
250
250
  ```
@@ -262,7 +262,7 @@ newStatus=$([ "$recovery_action" = "accept" ] && echo "in_progress" || echo "can
262
262
 
263
263
  tmp="${issuesFile}.tmp"
264
264
  jq --arg id "$resolvedId" --arg st "$newStatus" --arg ts "$ts" --arg ra "$recovery_action" \
265
- '.issues = [.issues[] | if .id == $id then
265
+ '.issues = [(.issues // [])[] | if .id == $id then
266
266
  .status = $st | .recovery_status = $ra | .updated_at = $ts
267
267
  else . end]' \
268
268
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
@@ -59,7 +59,7 @@ for f in "$MONITOR_DIR"/*.json; do
59
59
  [ -f "$f" ] || continue
60
60
  jq -r '
61
61
  "[\(.name)] status=\(.status // "active") interval=\(.poll_interval)s agent=\(.agent_type)
62
- sources: \([.sources[].type] | join(", "))
62
+ sources: \([(.sources // [])[].type] | join(", "))
63
63
  last_tick: \(.last_tick // "never") tasks_done: \(.stats.done // 0) tasks_failed: \(.stats.failed // 0)"
64
64
  ' "$f"
65
65
  echo ""
@@ -162,7 +162,7 @@ jq -r '
162
162
  "Sources (\(.sources | length)):"
163
163
  ' "$cfg"
164
164
 
165
- jq -r '.sources[] | " [\(.type)] \(.filter | to_entries | map("\(.key)=\(.value)") | join(" "))"' "$cfg"
165
+ jq -r '(.sources // [])[] | " [\(.type)] \(.filter | to_entries | map("\(.key)=\(.value)") | join(" "))"' "$cfg"
166
166
 
167
167
  if [ -f "$state_file" ]; then
168
168
  in_flight=$(jq '.in_flight // [] | length' "$state_file" 2>/dev/null || echo 0)
@@ -320,7 +320,7 @@ state_file="$MONITOR_DIR/${name}-state.json"
320
320
  # Load config
321
321
  [ ! -f "$cfg" ] && echo "Monitor '$name' not found — loop terminated." && exit 0
322
322
 
323
- monitor_status=$(jq -r '.status' "$cfg")
323
+ monitor_status=$(jq -r '.status // "active"' "$cfg")
324
324
  [ "$monitor_status" = "stopped" ] && echo "Monitor '$name' stopped — loop terminated." && exit 0
325
325
  [ "$monitor_status" = "paused" ] && echo "Monitor '$name' paused — will not reschedule." && exit 0
326
326
 
@@ -353,7 +353,7 @@ If a previous task failed but has retry_count < 3, it remains in `in_flight` wit
353
353
 
354
354
  ```bash
355
355
  retry_task=$(jq -c '
356
- .in_flight[] as $t |
356
+ (.in_flight // [])[] as $t |
357
357
  (.processed_ids[($t.source_type + ":" + $t.external_id)].status // "") |
358
358
  if . == "retry_pending" then $t else empty end' "$state_file" | head -1)
359
359
  ```
@@ -405,7 +405,7 @@ if [ -z "$retry_task" ]; then
405
405
  # === Linear adapter (below) ===
406
406
  ```
407
407
 
408
- > The `case` block continues through all adapters. After the Filesystem adapter closes its inner loop and `fi`, add `esac` → `done < <(jq -c '.sources[]' "$cfg")` → `fi` (closing the `if [ -z "$retry_task" ]` guard). After the outer `fi`, check `$task_claimed` to decide whether to run the "After claim" section.
408
+ > The `case` block continues through all adapters. After the Filesystem adapter closes its inner loop and `fi`, add `esac` → `done < <(jq -c '(.sources // [])[]' "$cfg")` → `fi` (closing the `if [ -z "$retry_task" ]` guard). After the outer `fi`, check `$task_claimed` to decide whether to run the "After claim" section.
409
409
 
410
410
  ---
411
411
 
@@ -733,7 +733,7 @@ done <<< "$tasks" # close per-file while loop (reached only if no file was cla
733
733
  fi # close 'if [ ! -d "$folder" ]' else block
734
734
  ;; # end filesystem case branch
735
735
  esac
736
- done < <(jq -c '.sources[]' "$cfg")
736
+ done < <(jq -c '(.sources // [])[]' "$cfg")
737
737
  fi # close 'if [ -z "$retry_task" ]' guard
738
738
  # After: if $task_claimed=true, proceed to "After claim"; otherwise skip to Step 5
739
739
  ```
@@ -950,7 +950,7 @@ jq --arg key "${task_source_type}:${task_external_id}" \
950
950
  --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
951
951
  '(.processed_ids[$key].status = "done") |
952
952
  (.processed_ids[$key].done_at = $ts) |
953
- (.in_flight = [.in_flight[] | select(.external_id != $eid or .source_type != $stype)])' \
953
+ (.in_flight = [(.in_flight // [])[] | select(.external_id != $eid or .source_type != $stype)])' \
954
954
  "$state_file" > "$tmp" && mv "$tmp" "$state_file"
955
955
 
956
956
  tmp="${cfg}.tmp"
@@ -991,7 +991,7 @@ if [ "$retry_count" -lt 3 ]; then
991
991
  '(.processed_ids[$key].retry_count = $r) |
992
992
  (.processed_ids[$key].last_failure = $ts) |
993
993
  (.processed_ids[$key].status = "retry_pending") |
994
- (.in_flight = [.in_flight[] |
994
+ (.in_flight = [(.in_flight // [])[] |
995
995
  if (.external_id == $eid and .source_type == $stype)
996
996
  then .retry_count = $r | .last_failure = $ts
997
997
  else . end])' \
@@ -1064,7 +1064,7 @@ Last attempt: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
1064
1064
  --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
1065
1065
  '(.processed_ids[$key].status = "failed") |
1066
1066
  (.processed_ids[$key].failed_at = $ts) |
1067
- (.in_flight = [.in_flight[] | select(.external_id != $eid or .source_type != $stype)])' \
1067
+ (.in_flight = [(.in_flight // [])[] | select(.external_id != $eid or .source_type != $stype)])' \
1068
1068
  "$state_file" > "$tmp" && mv "$tmp" "$state_file"
1069
1069
 
1070
1070
  tmp="${cfg}.tmp"
@@ -1137,7 +1137,7 @@ If `caller` is not "command", follow `_protocol.md` Brain Write Procedure for do
1137
1137
  {
1138
1138
  "type": "github",
1139
1139
  "filter": {
1140
- "repo": "nokhodian/monomind",
1140
+ "repo": "monoes/monomind",
1141
1141
  "assignee": "nokhodian",
1142
1142
  "labels": ["ai-agent"],
1143
1143
  "state": "open",
@@ -1214,7 +1214,7 @@ If `caller` is not "command", follow `_protocol.md` Brain Write Procedure for do
1214
1214
  ```bash
1215
1215
  # Create a monitor watching GitHub issues assigned to you
1216
1216
  /mastermind:monitor --action start --name dev-watcher \
1217
- --source github --project nokhodian/monomind --user nokhodian \
1217
+ --source github --project monoes/monomind --user nokhodian \
1218
1218
  --label ai-agent --agent coder --interval 120
1219
1219
 
1220
1220
  # Add a Linear source to an existing monitor
@@ -55,7 +55,7 @@ printf "%-24s %-12s %-10s %s\n" "ID" "STATUS" "PRIORITY" "TITLE"
55
55
  echo "────────────────────────────────────────────────────────"
56
56
 
57
57
  jq -r --arg uid "$assigneeFilter" --arg sf "$statusFilter" '
58
- .issues[] |
58
+ (.issues // [])[] |
59
59
  select(
60
60
  (.assigneeId == $uid or .assigned_to == $uid) and
61
61
  (if $sf == "active" then (.status == "open" or .status == "in_progress")
@@ -69,7 +69,7 @@ jq -r --arg uid "$assigneeFilter" --arg sf "$statusFilter" '
69
69
  done
70
70
 
71
71
  total=$(jq -r --arg uid "$assigneeFilter" \
72
- '[.issues[] | select(.assigneeId == $uid or .assigned_to == $uid)] | length' \
72
+ '[(.issues // [])[] | select(.assigneeId == $uid or .assigned_to == $uid)] | length' \
73
73
  "$issuesFile")
74
74
  echo ""
75
75
  echo "Total assigned: $total"
@@ -81,13 +81,13 @@ echo "Total assigned: $total"
81
81
  ```bash
82
82
  [ -z "$issue_id" ] && { echo "ERROR: --issue-id required."; exit 1; }
83
83
 
84
- exists=$(jq -r --arg id "$issue_id" '[.issues[] | select(.id == $id)] | length' "$issuesFile")
84
+ exists=$(jq -r --arg id "$issue_id" '[(.issues // [])[] | select(.id == $id)] | length' "$issuesFile")
85
85
  [ "$exists" -eq 0 ] && { echo "ERROR: Issue '$issue_id' not found."; exit 1; }
86
86
 
87
87
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
88
88
  tmp="${issuesFile}.tmp"
89
89
  jq --arg id "$issue_id" --arg uid "$assigneeFilter" --arg ts "$ts" \
90
- '.issues = [.issues[] | if .id == $id then
90
+ '.issues = [(.issues // [])[] | if .id == $id then
91
91
  .assigneeId = $uid | .lastActivityAt = $ts
92
92
  else . end]' \
93
93
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
@@ -103,7 +103,7 @@ echo "Issue '$issue_id' assigned to '$assigneeFilter'."
103
103
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
104
104
  tmp="${issuesFile}.tmp"
105
105
  jq --arg id "$issue_id" --arg ts "$ts" \
106
- '.issues = [.issues[] | if .id == $id then
106
+ '.issues = [(.issues // [])[] | if .id == $id then
107
107
  .assigneeId = null | .lastActivityAt = $ts
108
108
  else . end]' \
109
109
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
@@ -119,7 +119,7 @@ echo "Issue '$issue_id' unassigned."
119
119
  ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
120
120
  tmp="${issuesFile}.tmp"
121
121
  jq --arg id "$issue_id" --arg ts "$ts" \
122
- '.issues = [.issues[] | if .id == $id then
122
+ '.issues = [(.issues // [])[] | if .id == $id then
123
123
  .status = "done" | .closedAt = $ts | .lastActivityAt = $ts
124
124
  else . end]' \
125
125
  "$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
@@ -91,7 +91,7 @@ echo "CURRENT ROLES IN ORG: $org_name"
91
91
  echo "────────────────────────────────────────────────────────"
92
92
  printf "%-22s %-20s %-14s %s\n" "ID" "TITLE" "ADAPTER" "REPORTS TO"
93
93
  echo "────────────────────────────────────────────────────────"
94
- jq -r '.roles[] |
94
+ jq -r '(.roles // [])[] |
95
95
  [.id, (.title // "-"), (.adapter.type // "claude-local"), (.reports_to // "(root)")] | @tsv' \
96
96
  "$orgFile" | while IFS=$'\t' read -r id title adapter rt; do
97
97
  printf "%-22s %-20s %-14s %s\n" "$id" "$title" "$adapter" "$rt"
@@ -165,13 +165,13 @@ if [ -z "$agent_id" ]; then
165
165
  fi
166
166
 
167
167
  # Check for duplicate id
168
- duplicate=$(jq -r --arg id "$agent_id" '[.roles[] | select(.id == $id)] | length' "$orgFile")
168
+ duplicate=$(jq -r --arg id "$agent_id" '[(.roles // [])[] | select(.id == $id)] | length' "$orgFile")
169
169
  [ "$duplicate" -gt 0 ] && { echo "ERROR: Agent id '$agent_id' already exists in org '$org_name'. Use --agent-id to specify a unique id."; exit 1; }
170
170
 
171
171
  # Validate reports_to if set
172
172
  if [ -n "$reports_to" ]; then
173
- parentExists=$(jq -r --arg pid "$reports_to" '[.roles[] | select(.id == $pid)] | length' "$orgFile")
174
- [ "$parentExists" -eq 0 ] && echo "WARNING: Parent agent '$reports_to' not found in org. Setting anyway."
173
+ parentExists=$(jq -r --arg pid "$reports_to" '[(.roles // [])[] | select(.id == $pid)] | length' "$orgFile")
174
+ [ "$parentExists" -eq 0 ] && { echo "ERROR: Parent agent '$reports_to' not found in org '${org_name}'. Check the agent ID with /mastermind:org-chart --org ${org_name}."; exit 1; }
175
175
  fi
176
176
 
177
177
  # Build skills array
@@ -97,9 +97,9 @@ def render(nodes, prefix="", depth=0):
97
97
  child_prefix = prefix + (" " if is_last else "│ ")
98
98
  rid = r.get("id", "?")
99
99
  title = r.get("title", rid)
100
- adapter = r.get("adapter", {})
101
- atype = adapter.get("type", "?") if isinstance(adapter, dict) else str(adapter)
100
+ adapter = r.get("adapter_config", r.get("adapter", {}))
102
101
  model = adapter.get("model", "") if isinstance(adapter, dict) else ""
102
+ atype = model.split("-")[0] if model else "?"
103
103
  hb_status = "♡" if rid not in hb or not hb[rid] else "♥"
104
104
  gov = r.get("governance") or ""
105
105
  gov_str = f" [{gov}]" if gov else ""
@@ -135,7 +135,8 @@ printf "%-24s %-20s %-16s %-20s %s\n" "ID" "TITLE" "ADAPTER" "MODEL" "REPORTS TO
135
135
  echo "────────────────────────────────────────────────────────"
136
136
 
137
137
  echo "$roles" | jq -r '.[] |
138
- [.id, (.title // "-"), (.adapter.type // "?"), (.adapter.model // "-"),
138
+ (((.adapter_config.model // .adapter.model) // "") | split("-") | .[0] | if . == "" then "?" else . end) as $atype |
139
+ [.id, (.title // "-"), $atype, ((.adapter_config.model // .adapter.model) // "-"),
139
140
  (.reports_to // "(root)")] | @tsv' | \
140
141
  while IFS=$'\t' read -r id title adapter model rt; do
141
142
  printf "%-24s %-20s %-16s %-20s %s\n" "$id" "$title" "$adapter" "$model" "$rt"
@@ -157,13 +158,14 @@ echo "────────────────────────
157
158
 
158
159
  ql=$(echo "$query" | tr '[:upper:]' '[:lower:]')
159
160
  echo "$roles" | jq -r --arg q "$ql" '.[] |
161
+ (((.adapter_config.model // .adapter.model) // "") | split("-") | .[0] | if . == "" then "?" else . end) as $atype |
160
162
  select(
161
163
  (.id | ascii_downcase | contains($q)) or
162
164
  (.title // "" | ascii_downcase | contains($q)) or
163
- (.adapter.type // "" | ascii_downcase | contains($q)) or
164
- (.adapter.model // "" | ascii_downcase | contains($q))
165
+ ((.adapter_config.model // .adapter.model) // "" | ascii_downcase | contains($q)) or
166
+ (.agent_type // "" | ascii_downcase | contains($q))
165
167
  ) |
166
- [.id, (.title // "-"), (.adapter.type // "?"), (.reports_to // "(root)")] | @tsv' | \
168
+ [.id, (.title // "-"), $atype, (.reports_to // "(root)")] | @tsv' | \
167
169
  while IFS=$'\t' read -r id title adapter rt; do
168
170
  printf "%-24s %-20s %-16s %s\n" "$id" "$title" "$adapter" "$rt"
169
171
  done
@@ -75,8 +75,30 @@ tmp="${orgFile}.tmp"
75
75
 
76
76
  case "$field" in
77
77
  name)
78
+ # Validate new name slug
79
+ echo "$value" | grep -qE '^[a-z0-9][a-z0-9-]{0,63}$' || { echo "ERROR: name must match ^[a-z0-9][a-z0-9-]{0,63}$"; exit 1; }
80
+ newOrgFile=".monomind/orgs/${value}.json"
81
+ [ -f "$newOrgFile" ] && { echo "ERROR: An org named '${value}' already exists."; exit 1; }
82
+ # Update the name field inside the JSON
78
83
  jq --arg v "$value" '.name = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
79
- echo "Updated: name $value"
84
+ # Rename the main config file
85
+ mv "$orgFile" "$newOrgFile"
86
+ # Rename all side-car data files
87
+ for suffix in -state -goals -routines -approvals -activity -issues -members -projects -workspaces -worktrees -environments -plugins -adapters -threads -budgets -project-workspaces -approval-comments -bootstrap -secrets; do
88
+ old_file=".monomind/orgs/${org_name}${suffix}.json"
89
+ [ -f "$old_file" ] && mv "$old_file" ".monomind/orgs/${value}${suffix}.json" || true
90
+ old_jsonl=".monomind/orgs/${org_name}${suffix}.jsonl"
91
+ [ -f "$old_jsonl" ] && mv "$old_jsonl" ".monomind/orgs/${value}${suffix}.jsonl" || true
92
+ done
93
+ # Rename loop prompt file if present (scheduled orgs)
94
+ old_loop=".monomind/loops/${org_name}.md"
95
+ [ -f "$old_loop" ] && mv "$old_loop" ".monomind/loops/${value}.md" || true
96
+ # Rename stop file if present
97
+ old_stop=".monomind/orgs/.stops/${org_name}.stop"
98
+ [ -f "$old_stop" ] && mv "$old_stop" ".monomind/orgs/.stops/${value}.stop" || true
99
+ echo "Renamed org '${org_name}' → '${value}'"
100
+ org_name="$value"
101
+ orgFile="$newOrgFile"
80
102
  ;;
81
103
  goal)
82
104
  jq --arg v "$value" '.goal = $v' "$orgFile" > "$tmp" && mv "$tmp" "$orgFile"
@@ -143,19 +165,24 @@ mkdir -p ".monomind/exports"
143
165
  timestamp=$(date +%Y%m%d-%H%M%S)
144
166
  outPath="${export_path:-.monomind/exports/${org_name}-${timestamp}.json}"
145
167
 
168
+ # Pre-read optional side-car files (--slurpfile aborts jq when the file is missing)
169
+ goals_json=$([ -f ".monomind/orgs/${org_name}-goals.json" ] && jq -c '.' ".monomind/orgs/${org_name}-goals.json" || echo 'null')
170
+ routines_json=$([ -f ".monomind/orgs/${org_name}-routines.json" ] && jq -c '.' ".monomind/orgs/${org_name}-routines.json" || echo 'null')
171
+ projects_json=$([ -f ".monomind/orgs/${org_name}-projects.json" ] && jq -c '.' ".monomind/orgs/${org_name}-projects.json" || echo 'null')
172
+
146
173
  # Merge all org data files into one export bundle
147
174
  jq -n \
148
175
  --slurpfile config "$orgFile" \
149
- --slurpfile goals ".monomind/orgs/${org_name}-goals.json" 2>/dev/null \
150
- --slurpfile routines ".monomind/orgs/${org_name}-routines.json" 2>/dev/null \
151
- --slurpfile projects ".monomind/orgs/${org_name}-projects.json" 2>/dev/null \
176
+ --argjson goals "$goals_json" \
177
+ --argjson routines "$routines_json" \
178
+ --argjson projects "$projects_json" \
152
179
  '{
153
180
  exported_at: (now|todate),
154
181
  format_version: "1.0",
155
182
  config: ($config[0] // {}),
156
- goals: ($goals[0].goals // []),
157
- routines: ($routines[0].routines // []),
158
- projects: ($projects[0].projects // [])
183
+ goals: ($goals.goals // []),
184
+ routines: ($routines.routines // []),
185
+ projects: ($projects.projects // [])
159
186
  }' > "$outPath"
160
187
 
161
188
  echo "Exported: $outPath"
@@ -178,20 +205,30 @@ importedName=$(jq -r '.config.name // .config.org_name // "unnamed"' "$import_pa
178
205
  targetOrg="${org_name:-$importedName}"
179
206
  mkdir -p ".monomind/orgs"
180
207
 
181
- # Write config
182
- jq '.config' "$import_path" > ".monomind/orgs/${targetOrg}.json"
183
-
184
- # Write goals if present
185
- goalsData=$(jq '.goals // []' "$import_path")
186
- [ "$goalsData" != "[]" ] && echo "{\"goals\":$goalsData}" > ".monomind/orgs/${targetOrg}-goals.json"
187
-
188
- # Write routines if present
189
- routinesData=$(jq '.routines // []' "$import_path")
190
- [ "$routinesData" != "[]" ] && echo "{\"routines\":$routinesData}" > ".monomind/orgs/${targetOrg}-routines.json"
191
-
192
- # Write projects if present
193
- projectsData=$(jq '.projects // []' "$import_path")
194
- [ "$projectsData" != "[]" ] && echo "{\"projects\":$projectsData}" > ".monomind/orgs/${targetOrg}-projects.json"
208
+ # Write config — update the name field to match targetOrg (in case file was exported under a different name)
209
+ tmpConfig=".monomind/orgs/${targetOrg}.json.tmp"
210
+ jq --arg n "$targetOrg" '.config | .name = $n' "$import_path" > "$tmpConfig" && mv "$tmpConfig" ".monomind/orgs/${targetOrg}.json" || { rm -f "$tmpConfig"; echo "ERROR: Failed to write org config from import."; exit 1; }
211
+
212
+ # Write goals if present (atomic write)
213
+ goalsData=$(jq -c '.goals // []' "$import_path" 2>/dev/null || echo '[]')
214
+ if [ "$goalsData" != "[]" ]; then
215
+ tmp=".monomind/orgs/${targetOrg}-goals.json.tmp"
216
+ jq -n --argjson data "$goalsData" '{"goals":$data}' > "$tmp" && mv "$tmp" ".monomind/orgs/${targetOrg}-goals.json" || rm -f "$tmp"
217
+ fi
218
+
219
+ # Write routines if present (atomic write)
220
+ routinesData=$(jq -c '.routines // []' "$import_path" 2>/dev/null || echo '[]')
221
+ if [ "$routinesData" != "[]" ]; then
222
+ tmp=".monomind/orgs/${targetOrg}-routines.json.tmp"
223
+ jq -n --argjson data "$routinesData" '{"routines":$data}' > "$tmp" && mv "$tmp" ".monomind/orgs/${targetOrg}-routines.json" || rm -f "$tmp"
224
+ fi
225
+
226
+ # Write projects if present (atomic write)
227
+ projectsData=$(jq -c '.projects // []' "$import_path" 2>/dev/null || echo '[]')
228
+ if [ "$projectsData" != "[]" ]; then
229
+ tmp=".monomind/orgs/${targetOrg}-projects.json.tmp"
230
+ jq -n --argjson data "$projectsData" '{"projects":$data}' > "$tmp" && mv "$tmp" ".monomind/orgs/${targetOrg}-projects.json" || rm -f "$tmp"
231
+ fi
195
232
 
196
233
  echo "Imported org '${targetOrg}' from ${import_path}"
197
234
  echo "Agents: $(jq '.config.roles | length' "$import_path")"
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: mastermind-orgs
3
+ description: Mastermind orgs — list all saved orgs with their status, schedule, and last/next run times. Shows stopped/active/paused state for scheduled orgs.
4
+ type: domain-skill
5
+ default_mode: auto
6
+ ---
7
+
8
+ # Mastermind Orgs
9
+
10
+ This skill is invoked by `mastermind:orgs` or directly via `/mastermind:orgs`.
11
+
12
+ Lists all saved orgs from `.monomind/orgs/*.json`.
13
+
14
+ ---
15
+
16
+ ## Inputs
17
+
18
+ - `caller`: command | master (controls whether brain load runs here)
19
+
20
+ ---
21
+
22
+ ## Step 0 — Brain Load (standalone only)
23
+
24
+ If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
25
+
26
+ ---
27
+
28
+ ## Step 1 — List Orgs
29
+
30
+ ```bash
31
+ orgsDir=".monomind/orgs"
32
+ orgFiles=$(ls "$orgsDir"/*.json 2>/dev/null | grep -vE -- '-approvals|-state|-activity|-goals|-routines|-projects|-members|-issues|-workspaces|-worktrees|-environments|-plugins|-adapters|-bootstrap|-threads|-budgets|-project-workspaces|-approval-comments')
33
+
34
+ if [ -z "$orgFiles" ]; then
35
+ echo "No saved orgs found."
36
+ echo "Create one: /mastermind:createorg <goal>"
37
+ exit 0
38
+ fi
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Step 2 — Render Org Table
44
+
45
+ For each org file (skip state/approvals files), extract and display:
46
+
47
+ ```bash
48
+ echo ""
49
+ printf "%-28s %-10s %-12s %-22s %-22s\n" "ORG" "STATUS" "SCHEDULE" "LAST RUN" "NEXT RUN"
50
+ printf "%-28s %-10s %-12s %-22s %-22s\n" "---" "------" "--------" "--------" "--------"
51
+
52
+ for f in $orgFiles; do
53
+ name=$(jq -r '.name // "(unnamed)"' "$f" 2>/dev/null)
54
+ goal=$(jq -r '.goal // ""' "$f" 2>/dev/null | cut -c1-55)
55
+ status=$(jq -r '.status // "—"' "$f" 2>/dev/null)
56
+ interval=$(jq -r 'if .loop.poll_interval_minutes then "\(.loop.poll_interval_minutes)m" else "manual" end' "$f" 2>/dev/null)
57
+ last_run=$(jq -r '.loop.last_run // "—"' "$f" 2>/dev/null | sed 's/T/ /;s/Z//')
58
+ next_run=$(jq -r '.loop.next_run // "—"' "$f" 2>/dev/null | sed 's/T/ /;s/Z//')
59
+
60
+ # Status indicator — distinguish non-scheduled (manual) from scheduled loop states
61
+ if [ "$interval" = "manual" ]; then
62
+ indicator="■ persistent"
63
+ else
64
+ case "$status" in
65
+ active) indicator="● active" ;;
66
+ stopped) indicator="○ stopped" ;;
67
+ paused) indicator="⏸ paused" ;;
68
+ *) indicator="— unknown" ;;
69
+ esac
70
+ fi
71
+
72
+ printf "%-28s %-10s %-12s %-22s %-22s\n" "$name" "$indicator" "$interval" "$last_run" "$next_run"
73
+ echo " └ $goal"
74
+ echo ""
75
+ done
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Step 3 — Show Summary and Commands
81
+
82
+ ```
83
+ COMMANDS
84
+ ────────
85
+ /mastermind:orgstatus --org <name> Detailed status, last runs, activity
86
+ /mastermind:runorg --org <name> Start (or restart) a scheduled org
87
+ /mastermind:stoporg --org <name> Stop a running scheduled org
88
+ /mastermind:createorg <goal> Create a new org
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Step 4 — Return Output
94
+
95
+ ```yaml
96
+ domain: ops
97
+ status: complete
98
+ ```