@monoes/monomindcli 2.10.9 → 2.10.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/mastermind/brain.md +14 -14
- package/.claude/commands/mastermind/help.md +2 -2
- package/.claude/commands/mastermind/master.md +24 -19
- package/.claude/commands/mastermind/memory.md +8 -8
- package/.claude/commands/mastermind/monoswarm.md +4 -4
- package/.claude/commands/mastermind.md +7 -7
- package/.claude/commands/truth/start.md +3 -3
- package/.claude/settings.json +0 -4
- package/.claude/skills/mastermind/SKILL.md +7 -16
- package/.claude/skills/mastermind/references/antigravity-tools.md +0 -62
- package/.claude/skills/mastermind/references/claude-code-tools.md +0 -52
- package/.claude/skills/mastermind/references/codex-tools.md +0 -66
- package/.claude/skills/mastermind/references/copilot-tools.md +0 -51
- package/.claude/skills/mastermind/references/gemini-tools.md +0 -65
- package/.claude/skills/mastermind/references/pi-tools.md +0 -30
- package/.claude/skills/mastermind-createorg/SKILL.md +3 -1
- package/.claude/skills/mastermind-debug/SKILL.md +3 -277
- package/.claude/skills/mastermind-design/SKILL.md +2 -0
- package/.claude/skills/mastermind-execute/SKILL.md +59 -103
- package/.claude/skills/mastermind-idea/SKILL.md +9 -2
- package/.claude/skills/mastermind-intake/SKILL.md +31 -7
- package/.claude/skills/mastermind-issue-detail/SKILL.md +70 -16
- package/.claude/skills/mastermind-issues/SKILL.md +111 -16
- package/.claude/skills/mastermind-liveness/SKILL.md +96 -26
- package/.claude/skills/mastermind-memory/SKILL.md +0 -316
- package/.claude/skills/mastermind-my-issues/SKILL.md +40 -8
- package/.claude/skills/mastermind-org/SKILL.md +1 -12
- package/.claude/skills/mastermind-plan/SKILL.md +7 -228
- package/.claude/skills/mastermind-plan-to-tasks/SKILL.md +132 -24
- package/.claude/skills/mastermind-protocol/SKILL.md +33 -22
- package/.claude/skills/mastermind-research/SKILL.md +0 -163
- package/.claude/skills/mastermind-review/SKILL.md +0 -228
- package/.claude/skills/mastermind-runorg/SKILL.md +22 -3
- package/.claude/skills/mastermind-skill-builder/SKILL.md +1 -1
- package/.claude/skills/mastermind-tasks/SKILL.md +5 -0
- package/.claude/skills/mastermind-techport/SKILL.md +1 -1
- package/.claude/skills/performance-analysis/SKILL.md +1 -1
- package/.claude/skills/verification-quality/SKILL.md +2 -3
- package/README.md +2 -2
- package/dist/src/commands/agent-exec.d.ts +2 -0
- package/dist/src/commands/agent-exec.d.ts.map +1 -1
- package/dist/src/commands/agent-exec.js +16 -0
- package/dist/src/commands/agent-exec.js.map +1 -1
- package/dist/src/commands/doc.js +2 -2
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/commands/doctor-project-checks.d.ts.map +1 -1
- package/dist/src/commands/doctor-project-checks.js +20 -1
- package/dist/src/commands/doctor-project-checks.js.map +1 -1
- package/dist/src/commands/init-wizard.d.ts.map +1 -1
- package/dist/src/commands/init-wizard.js +6 -0
- package/dist/src/commands/init-wizard.js.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/commands/init.js +12 -2
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/monograph.d.ts.map +1 -1
- package/dist/src/commands/monograph.js +11 -4
- package/dist/src/commands/monograph.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts +2 -0
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +115 -6
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts +26 -0
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +186 -28
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/init/codex-generator.d.ts +5 -0
- package/dist/src/init/codex-generator.d.ts.map +1 -1
- package/dist/src/init/codex-generator.js +12 -3
- package/dist/src/init/codex-generator.js.map +1 -1
- package/dist/src/init/executor.d.ts.map +1 -1
- package/dist/src/init/executor.js +10 -9
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +0 -5
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/init/write-codex.d.ts.map +1 -1
- package/dist/src/init/write-codex.js +6 -5
- package/dist/src/init/write-codex.js.map +1 -1
- package/dist/src/knowledge/document-pipeline.d.ts +5 -0
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +32 -16
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.d.ts +9 -0
- package/dist/src/mcp-tools/hooks-routing.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-routing.js +12 -1
- package/dist/src/mcp-tools/hooks-routing.js.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/knowledge-tools.js +105 -13
- package/dist/src/mcp-tools/knowledge-tools.js.map +1 -1
- package/dist/src/mcp-tools/memory-tools.d.ts +13 -0
- package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/memory-tools.js +257 -31
- package/dist/src/mcp-tools/memory-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/health-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/health-tools.js +99 -42
- package/dist/src/mcp-tools/monograph/health-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/impact-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/impact-tools.js +123 -51
- package/dist/src/mcp-tools/monograph/impact-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/query-tools.js +113 -96
- package/dist/src/mcp-tools/monograph/query-tools.js.map +1 -1
- package/dist/src/mcp-tools/monograph/shared.d.ts +37 -4
- package/dist/src/mcp-tools/monograph/shared.d.ts.map +1 -1
- package/dist/src/mcp-tools/monograph/shared.js +75 -56
- package/dist/src/mcp-tools/monograph/shared.js.map +1 -1
- package/dist/src/memory/embedding-operations.d.ts.map +1 -1
- package/dist/src/memory/embedding-operations.js +9 -4
- package/dist/src/memory/embedding-operations.js.map +1 -1
- package/dist/src/memory/memory-bridge.d.ts +60 -1
- package/dist/src/memory/memory-bridge.d.ts.map +1 -1
- package/dist/src/memory/memory-bridge.js +185 -42
- package/dist/src/memory/memory-bridge.js.map +1 -1
- package/dist/src/memory/memory-kg.d.ts +495 -28
- package/dist/src/memory/memory-kg.d.ts.map +1 -1
- package/dist/src/memory/memory-kg.js +2186 -251
- package/dist/src/memory/memory-kg.js.map +1 -1
- package/dist/src/memory/query-router.d.ts +51 -0
- package/dist/src/memory/query-router.d.ts.map +1 -1
- package/dist/src/memory/query-router.js +38 -2
- package/dist/src/memory/query-router.js.map +1 -1
- package/dist/src/orgrt/agent-exec.d.ts +14 -0
- package/dist/src/orgrt/agent-exec.d.ts.map +1 -1
- package/dist/src/orgrt/agent-exec.js +88 -4
- package/dist/src/orgrt/agent-exec.js.map +1 -1
- package/dist/src/orgrt/agent-runner.d.ts +26 -1
- package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
- package/dist/src/orgrt/agent-runner.js +73 -22
- package/dist/src/orgrt/agent-runner.js.map +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
- package/dist/src/orgrt/antigravity-runner.js +36 -19
- package/dist/src/orgrt/antigravity-runner.js.map +1 -1
- package/dist/src/orgrt/approvals.d.ts +26 -2
- package/dist/src/orgrt/approvals.d.ts.map +1 -1
- package/dist/src/orgrt/approvals.js +67 -7
- package/dist/src/orgrt/approvals.js.map +1 -1
- package/dist/src/orgrt/broker.d.ts +21 -2
- package/dist/src/orgrt/broker.d.ts.map +1 -1
- package/dist/src/orgrt/broker.js +56 -8
- package/dist/src/orgrt/broker.js.map +1 -1
- package/dist/src/orgrt/bus.d.ts +8 -0
- package/dist/src/orgrt/bus.d.ts.map +1 -1
- package/dist/src/orgrt/bus.js +27 -0
- package/dist/src/orgrt/bus.js.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint-ops.js +15 -5
- package/dist/src/orgrt/checkpoint-ops.js.map +1 -1
- package/dist/src/orgrt/checkpoint.d.ts +42 -4
- package/dist/src/orgrt/checkpoint.d.ts.map +1 -1
- package/dist/src/orgrt/checkpoint.js +75 -4
- package/dist/src/orgrt/checkpoint.js.map +1 -1
- package/dist/src/orgrt/codex-runner.d.ts +1 -1
- package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
- package/dist/src/orgrt/codex-runner.js +50 -23
- package/dist/src/orgrt/codex-runner.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts +24 -2
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
- package/dist/src/orgrt/copilot-runner.js +257 -157
- package/dist/src/orgrt/copilot-runner.js.map +1 -1
- package/dist/src/orgrt/cross-org.d.ts +10 -3
- package/dist/src/orgrt/cross-org.d.ts.map +1 -1
- package/dist/src/orgrt/cross-org.js +225 -10
- package/dist/src/orgrt/cross-org.js.map +1 -1
- package/dist/src/orgrt/crush-runner.d.ts +22 -2
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
- package/dist/src/orgrt/crush-runner.js +227 -120
- package/dist/src/orgrt/crush-runner.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +77 -7
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +989 -385
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +2 -2
- package/dist/src/orgrt/decisions.d.ts.map +1 -1
- package/dist/src/orgrt/decisions.js +90 -18
- package/dist/src/orgrt/decisions.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts +29 -3
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
- package/dist/src/orgrt/grok-runner.js +286 -150
- package/dist/src/orgrt/grok-runner.js.map +1 -1
- package/dist/src/orgrt/kimicode-runner.d.ts +5 -5
- package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +53 -32
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/mailbox.d.ts +15 -0
- package/dist/src/orgrt/mailbox.d.ts.map +1 -1
- package/dist/src/orgrt/mailbox.js +29 -1
- package/dist/src/orgrt/mailbox.js.map +1 -1
- package/dist/src/orgrt/migrate.d.ts.map +1 -1
- package/dist/src/orgrt/migrate.js +8 -5
- package/dist/src/orgrt/migrate.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +29 -3
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/org-memory.d.ts +19 -3
- package/dist/src/orgrt/org-memory.d.ts.map +1 -1
- package/dist/src/orgrt/org-memory.js +110 -38
- package/dist/src/orgrt/org-memory.js.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts +3 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.js +35 -3
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/pi-runner.d.ts +25 -2
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-runner.js +271 -152
- package/dist/src/orgrt/pi-runner.js.map +1 -1
- package/dist/src/orgrt/policy.d.ts +1 -0
- package/dist/src/orgrt/policy.d.ts.map +1 -1
- package/dist/src/orgrt/policy.js +199 -39
- package/dist/src/orgrt/policy.js.map +1 -1
- package/dist/src/orgrt/provider.d.ts +4 -0
- package/dist/src/orgrt/provider.d.ts.map +1 -1
- package/dist/src/orgrt/provider.js +16 -0
- package/dist/src/orgrt/provider.js.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts +3 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.js +35 -3
- package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/qwen-runner.d.ts +30 -3
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-runner.js +282 -142
- package/dist/src/orgrt/qwen-runner.js.map +1 -1
- package/dist/src/orgrt/role-slot.d.ts +88 -0
- package/dist/src/orgrt/role-slot.d.ts.map +1 -0
- package/dist/src/orgrt/role-slot.js +133 -0
- package/dist/src/orgrt/role-slot.js.map +1 -0
- package/dist/src/orgrt/runtime-options.d.ts +17 -0
- package/dist/src/orgrt/runtime-options.d.ts.map +1 -0
- package/dist/src/orgrt/runtime-options.js +32 -0
- package/dist/src/orgrt/runtime-options.js.map +1 -0
- package/dist/src/orgrt/scheduler-integration.d.ts +11 -0
- package/dist/src/orgrt/scheduler-integration.d.ts.map +1 -1
- package/dist/src/orgrt/scheduler-integration.js +75 -17
- package/dist/src/orgrt/scheduler-integration.js.map +1 -1
- package/dist/src/orgrt/scheduler.d.ts +4 -0
- package/dist/src/orgrt/scheduler.d.ts.map +1 -1
- package/dist/src/orgrt/scheduler.js +7 -1
- package/dist/src/orgrt/scheduler.js.map +1 -1
- package/dist/src/orgrt/server.d.ts +8 -3
- package/dist/src/orgrt/server.d.ts.map +1 -1
- package/dist/src/orgrt/server.js +48 -13
- package/dist/src/orgrt/server.js.map +1 -1
- package/dist/src/orgrt/session.d.ts +26 -2
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +99 -5
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/task-dag.d.ts +5 -0
- package/dist/src/orgrt/task-dag.d.ts.map +1 -1
- package/dist/src/orgrt/task-dag.js +41 -0
- package/dist/src/orgrt/task-dag.js.map +1 -1
- package/dist/src/orgrt/test-loop.js +2 -2
- package/dist/src/orgrt/test-loop.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +14 -2
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +15 -1
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/orgrt/vercel-runner.d.ts.map +1 -1
- package/dist/src/orgrt/vercel-runner.js +4 -0
- package/dist/src/orgrt/vercel-runner.js.map +1 -1
- package/dist/src/ui/routes-org.mjs +27 -7
- package/dist/src/ui/server.mjs +82 -48
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/dist/src/ui/data/mastermind-sessions.json +0 -1
|
@@ -64,6 +64,38 @@ issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
|
64
64
|
stateFile=".monomind/orgs/${org_name}-state.json"
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
Normalize any legacy records written by a pre-2.10 version of these skills. Idempotent — safe to run on every load. Guarded because this skill tolerates a missing issues file.
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
[ -f "$issuesFile" ] && python3 - "$issuesFile" <<'PYEOF'
|
|
71
|
+
import json, sys
|
|
72
|
+
path = sys.argv[1]
|
|
73
|
+
data = json.load(open(path))
|
|
74
|
+
RENAME = {
|
|
75
|
+
"assignee_id": "assigneeId", "assigned_to": "assigneeId",
|
|
76
|
+
"created_at": "createdAt", "updated_at": "updatedAt",
|
|
77
|
+
"closed_at": "closedAt", "project_id": "projectId",
|
|
78
|
+
"parent_id": "parentId", "recovery_status": "recoveryStatus",
|
|
79
|
+
"lastActivityAt": "updatedAt",
|
|
80
|
+
}
|
|
81
|
+
changed = False
|
|
82
|
+
for iss in data.get("issues", []):
|
|
83
|
+
for old, new in RENAME.items():
|
|
84
|
+
if old in iss:
|
|
85
|
+
iss.setdefault(new, iss.pop(old))
|
|
86
|
+
iss.pop(old, None)
|
|
87
|
+
changed = True
|
|
88
|
+
if iss.get("status") == "open":
|
|
89
|
+
iss["status"] = "todo"
|
|
90
|
+
changed = True
|
|
91
|
+
if changed:
|
|
92
|
+
tmp = path + ".tmp"
|
|
93
|
+
with open(tmp, "w") as f:
|
|
94
|
+
json.dump(data, f, indent=2)
|
|
95
|
+
import os; os.replace(tmp, path)
|
|
96
|
+
PYEOF
|
|
97
|
+
```
|
|
98
|
+
|
|
67
99
|
---
|
|
68
100
|
|
|
69
101
|
## Step 2 — Execute Action
|
|
@@ -108,35 +140,44 @@ now = datetime.utcnow()
|
|
|
108
140
|
|
|
109
141
|
for iss in issues:
|
|
110
142
|
status = iss.get("status","")
|
|
111
|
-
|
|
143
|
+
iid = iss.get("id","?")
|
|
144
|
+
title = (iss.get("title") or "?")[:50]
|
|
145
|
+
|
|
146
|
+
if status in terminal_statuses:
|
|
147
|
+
continue
|
|
148
|
+
if status not in non_terminal_statuses:
|
|
149
|
+
# Silently skipping an unknown status is how issues become invisible.
|
|
150
|
+
warnings.append((iid, title, status, f"unknown status '{status}' — outside the canonical vocabulary"))
|
|
112
151
|
continue
|
|
113
152
|
|
|
114
|
-
aId = iss.get("assigneeAgentId")
|
|
153
|
+
aId = iss.get("assigneeAgentId")
|
|
115
154
|
uId = iss.get("assigneeUserId")
|
|
116
|
-
iid = iss.get("id","?")
|
|
117
|
-
title = iss.get("title","?")[:50]
|
|
118
155
|
|
|
119
|
-
#
|
|
156
|
+
# Human-owned: the next move belongs to a person, not an execution path.
|
|
120
157
|
if uId and not aId:
|
|
121
158
|
healthy.append((iid, title, status, "user-owned"))
|
|
122
159
|
continue
|
|
123
160
|
|
|
124
|
-
# Evaluate liveness
|
|
125
161
|
paths = []
|
|
126
162
|
|
|
127
163
|
run_id = iss.get("executionRunId") or iss.get("checkoutRunId")
|
|
128
164
|
if run_id and run_id in active_runs:
|
|
129
165
|
paths.append("active-run")
|
|
130
166
|
|
|
167
|
+
resolved_ids = {i.get("id") for i in issues if i.get("status") in terminal_statuses}
|
|
131
168
|
blockers = iss.get("blockedByIssueIds") or []
|
|
132
|
-
if status == "blocked"
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
169
|
+
if status == "blocked":
|
|
170
|
+
if blockers:
|
|
171
|
+
unresolved = [b for b in blockers if b not in resolved_ids]
|
|
172
|
+
if unresolved:
|
|
173
|
+
paths.append(f"blocked-by:{','.join(unresolved[:2])}")
|
|
174
|
+
else:
|
|
175
|
+
warnings.append((iid, title, status, "all blockers resolved but issue still blocked"))
|
|
176
|
+
elif not iss.get("recoveryActions"):
|
|
177
|
+
# Liveness Contract: blocked requires a named dependency or an
|
|
178
|
+
# explicit human decision. This issue records neither.
|
|
179
|
+
stalled.append((iid, title, status, "blocked with no blockedByIssueIds and no recovery action"))
|
|
180
|
+
continue
|
|
140
181
|
|
|
141
182
|
if iss.get("executionPolicy", {}).get("monitor", {}).get("nextCheckAt"):
|
|
142
183
|
paths.append("monitor")
|
|
@@ -150,7 +191,10 @@ for iss in issues:
|
|
|
150
191
|
if iss.get("currentParticipant"):
|
|
151
192
|
paths.append("participant")
|
|
152
193
|
|
|
153
|
-
|
|
194
|
+
if status == "in_review" and not (iss.get("reviewerId") or iss.get("currentParticipant")):
|
|
195
|
+
stalled.append((iid, title, status, "in_review with no named reviewer"))
|
|
196
|
+
continue
|
|
197
|
+
|
|
154
198
|
if status == "in_progress" and aId and not paths:
|
|
155
199
|
updated = iss.get("updatedAt","")
|
|
156
200
|
if updated:
|
|
@@ -159,16 +203,19 @@ for iss in issues:
|
|
|
159
203
|
if age > timedelta(hours=2):
|
|
160
204
|
stalled.append((iid, title, status, f"in_progress {int(age.total_seconds()//3600)}h with no active path"))
|
|
161
205
|
continue
|
|
162
|
-
except:
|
|
206
|
+
except Exception:
|
|
207
|
+
pass
|
|
163
208
|
stalled.append((iid, title, status, "in_progress with no active execution path"))
|
|
164
209
|
continue
|
|
165
210
|
|
|
166
|
-
if
|
|
167
|
-
warnings.append((iid, title, status, "todo assigned to agent — may need wakeup"))
|
|
168
|
-
elif paths:
|
|
211
|
+
if paths:
|
|
169
212
|
healthy.append((iid, title, status, " + ".join(paths)))
|
|
213
|
+
elif not aId:
|
|
214
|
+
warnings.append((iid, title, status, "no assignee — nothing will pick this up"))
|
|
215
|
+
elif status == "todo":
|
|
216
|
+
warnings.append((iid, title, status, "todo assigned to agent — may need wakeup"))
|
|
170
217
|
else:
|
|
171
|
-
|
|
218
|
+
stalled.append((iid, title, status, f"{status} with an agent assignee but no execution path"))
|
|
172
219
|
|
|
173
220
|
print(f" ✓ Healthy: {len(healthy)}")
|
|
174
221
|
if healthy:
|
|
@@ -206,7 +253,7 @@ Claim an issue for execution by an agent run. Sets `checkoutRunId` and `executio
|
|
|
206
253
|
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
207
254
|
|
|
208
255
|
python3 - "$issuesFile" "$issue_id" "$agent_id" "$run_id" "$ts" <<'PYEOF'
|
|
209
|
-
import json, sys
|
|
256
|
+
import json, os, sys
|
|
210
257
|
|
|
211
258
|
path, iid, agentId, runId, ts = sys.argv[1:]
|
|
212
259
|
data = json.load(open(path))
|
|
@@ -224,6 +271,7 @@ for iss in issues:
|
|
|
224
271
|
iss["executionRunId"] = runId
|
|
225
272
|
iss["assigneeId"] = agentId
|
|
226
273
|
iss["assigneeAgentId"]= agentId
|
|
274
|
+
iss["assigneeUserId"] = None
|
|
227
275
|
iss["status"] = "in_progress"
|
|
228
276
|
iss["checkedOutAt"] = ts
|
|
229
277
|
iss["updatedAt"] = ts
|
|
@@ -237,9 +285,16 @@ if not found:
|
|
|
237
285
|
sys.exit(1)
|
|
238
286
|
|
|
239
287
|
data["issues"] = issues
|
|
240
|
-
|
|
288
|
+
tmp = path + ".tmp"
|
|
289
|
+
with open(tmp, "w") as f:
|
|
241
290
|
json.dump(data, f, indent=2)
|
|
291
|
+
os.replace(tmp, path)
|
|
242
292
|
PYEOF
|
|
293
|
+
|
|
294
|
+
activityFile=".monomind/orgs/${org_name}-activity.jsonl"
|
|
295
|
+
jq -cn --arg iid "$issue_id" --arg ts "$ts" --arg st "in_progress" --arg ag "$agent_id" --arg sm "checkout $issue_id" \
|
|
296
|
+
'{issue_id:$iid, ts:$ts, status:$st, tokens:null, agent:$ag, type:"checkout", summary:$sm}' \
|
|
297
|
+
>> "$activityFile"
|
|
243
298
|
```
|
|
244
299
|
|
|
245
300
|
### release
|
|
@@ -269,13 +324,21 @@ for iss in issues:
|
|
|
269
324
|
print(f" RELEASED: Checkout cleared for issue {iid}")
|
|
270
325
|
print(f" Status remains: {iss.get('status','?')} — update separately if needed.")
|
|
271
326
|
data["issues"] = issues
|
|
272
|
-
|
|
327
|
+
tmp = path + ".tmp"
|
|
328
|
+
with open(tmp, "w") as f:
|
|
273
329
|
json.dump(data, f, indent=2)
|
|
330
|
+
os.replace(tmp, path)
|
|
274
331
|
sys.exit(0)
|
|
275
332
|
|
|
276
333
|
print(f" ERROR: Issue '{iid}' not found.")
|
|
277
334
|
sys.exit(1)
|
|
278
335
|
PYEOF
|
|
336
|
+
|
|
337
|
+
activityFile=".monomind/orgs/${org_name}-activity.jsonl"
|
|
338
|
+
currentStatus=$(jq -r --arg id "$issue_id" '(.issues // [])[] | select(.id == $id) | .status // "todo"' "$issuesFile")
|
|
339
|
+
jq -cn --arg iid "$issue_id" --arg ts "$ts" --arg st "$currentStatus" --arg ag "${agent_id:-operator}" --arg sm "release $issue_id" \
|
|
340
|
+
'{issue_id:$iid, ts:$ts, status:$st, tokens:null, agent:$ag, type:"release", summary:$sm}' \
|
|
341
|
+
>> "$activityFile"
|
|
279
342
|
```
|
|
280
343
|
|
|
281
344
|
### wakeup
|
|
@@ -296,7 +359,7 @@ if not iss:
|
|
|
296
359
|
print(f" ERROR: Issue '{iid}' not found.")
|
|
297
360
|
sys.exit(1)
|
|
298
361
|
|
|
299
|
-
checkout_agent = iss.get("assigneeAgentId") or
|
|
362
|
+
checkout_agent = iss.get("assigneeAgentId") or ""
|
|
300
363
|
checkout_run = iss.get("checkoutRunId","")
|
|
301
364
|
|
|
302
365
|
# Port of Paperclip's shouldWakeAssigneeOnCheckout logic
|
|
@@ -338,7 +401,7 @@ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
338
401
|
recoveryId="recovery-$(python3 -c 'import time; print(int(time.time()*1000))')"
|
|
339
402
|
|
|
340
403
|
python3 - "$issuesFile" "$issue_id" "$recoveryId" "${agent_id:-operator}" "$reason" "$ts" <<'PYEOF'
|
|
341
|
-
import json, sys
|
|
404
|
+
import json, os, sys
|
|
342
405
|
|
|
343
406
|
path, iid, rid, owner, cause, ts = sys.argv[1:]
|
|
344
407
|
data = json.load(open(path))
|
|
@@ -359,8 +422,10 @@ for iss in issues:
|
|
|
359
422
|
iss["status"] = "blocked"
|
|
360
423
|
iss["updatedAt"] = ts
|
|
361
424
|
data["issues"] = issues
|
|
362
|
-
|
|
425
|
+
tmp = path + ".tmp"
|
|
426
|
+
with open(tmp, "w") as f:
|
|
363
427
|
json.dump(data, f, indent=2)
|
|
428
|
+
os.replace(tmp, path)
|
|
364
429
|
print(f" RECOVERY ACTION FILED: {rid}")
|
|
365
430
|
print(f" Issue {iid} → status: blocked (pending recovery)")
|
|
366
431
|
print(f" Owner: {owner}")
|
|
@@ -371,6 +436,11 @@ for iss in issues:
|
|
|
371
436
|
print(f" ERROR: Issue '{iid}' not found.")
|
|
372
437
|
sys.exit(1)
|
|
373
438
|
PYEOF
|
|
439
|
+
|
|
440
|
+
activityFile=".monomind/orgs/${org_name}-activity.jsonl"
|
|
441
|
+
jq -cn --arg iid "$issue_id" --arg ts "$ts" --arg st "blocked" --arg ag "${agent_id:-operator}" --arg sm "recover $issue_id" \
|
|
442
|
+
'{issue_id:$iid, ts:$ts, status:$st, tokens:null, agent:$ag, type:"recover", summary:$sm}' \
|
|
443
|
+
>> "$activityFile"
|
|
374
444
|
```
|
|
375
445
|
|
|
376
446
|
---
|
|
@@ -319,319 +319,3 @@ topic: <topic>
|
|
|
319
319
|
## Step 4 — Brain Write (standalone only)
|
|
320
320
|
|
|
321
321
|
If `caller` is not "command", follow mastermind-protocol/SKILL.md Brain Write Procedure for domain `ops`.
|
|
322
|
-
# monomind:start skills:claude:mastermind-memory
|
|
323
|
-
# Mastermind Memory
|
|
324
|
-
|
|
325
|
-
This skill is invoked by `mastermind:memory` or directly via `/mastermind:memory`.
|
|
326
|
-
|
|
327
|
-
---
|
|
328
|
-
|
|
329
|
-
## Inputs
|
|
330
|
-
|
|
331
|
-
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
332
|
-
- `org_name`: org whose memory to operate on (required)
|
|
333
|
-
- `action`: ingest | recall | query | update | forget | synthesize | decay | list
|
|
334
|
-
- `topic`: topic or entity name (required for ingest/recall/update/forget)
|
|
335
|
-
- `layer`: knowledge | daily | tacit (default: knowledge)
|
|
336
|
-
- `category`: projects | areas | resources | archives (for layer=knowledge; default: resources)
|
|
337
|
-
- `content`: fact or note body (required for ingest/update)
|
|
338
|
-
- `caller`: command | master
|
|
339
|
-
|
|
340
|
-
---
|
|
341
|
-
|
|
342
|
-
## Memory Architecture (PARA)
|
|
343
|
-
|
|
344
|
-
Three layers, mirrored to `.monomind/orgs/<org_name>-memory/`:
|
|
345
|
-
|
|
346
|
-
```
|
|
347
|
-
.monomind/orgs/<org>-memory/
|
|
348
|
-
knowledge/ ← Layer 1: PARA knowledge graph
|
|
349
|
-
projects/<topic>/
|
|
350
|
-
summary.md
|
|
351
|
-
items.yaml
|
|
352
|
-
areas/<topic>/
|
|
353
|
-
summary.md
|
|
354
|
-
items.yaml
|
|
355
|
-
resources/<topic>/
|
|
356
|
-
summary.md
|
|
357
|
-
items.yaml
|
|
358
|
-
archives/<topic>/
|
|
359
|
-
summary.md
|
|
360
|
-
items.yaml
|
|
361
|
-
index.md
|
|
362
|
-
daily/ ← Layer 2: Raw timeline (YYYY-MM-DD.md)
|
|
363
|
-
tacit.md ← Layer 3: Org operating patterns
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
**PARA rules:**
|
|
367
|
-
- **projects** — active work with a goal/deadline; archive when complete
|
|
368
|
-
- **areas** — ongoing responsibilities, no end date
|
|
369
|
-
- **resources** — reference material, topics of interest
|
|
370
|
-
- **archives** — inactive items from any category
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
## Step 0 — Brain Load (standalone only)
|
|
375
|
-
|
|
376
|
-
If `caller` is not "command", load brain context following mastermind-protocol/SKILL.md Brain Load Procedure with namespace: `ops`.
|
|
377
|
-
|
|
378
|
-
---
|
|
379
|
-
|
|
380
|
-
## Step 1 — Resolve Memory Root
|
|
381
|
-
|
|
382
|
-
```bash
|
|
383
|
-
memRoot=".monomind/orgs/${org_name}-memory"
|
|
384
|
-
mkdir -p "$memRoot/knowledge/projects" "$memRoot/knowledge/areas" \
|
|
385
|
-
"$memRoot/knowledge/resources" "$memRoot/knowledge/archives" \
|
|
386
|
-
"$memRoot/daily"
|
|
387
|
-
```
|
|
388
|
-
|
|
389
|
-
---
|
|
390
|
-
|
|
391
|
-
## Step 2 — Execute Action
|
|
392
|
-
|
|
393
|
-
### ingest (default for new facts)
|
|
394
|
-
|
|
395
|
-
Store a durable fact in Layer 1 (knowledge graph) or Layer 2 (daily note).
|
|
396
|
-
|
|
397
|
-
```bash
|
|
398
|
-
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
399
|
-
day=$(date -u +%Y-%m-%d)
|
|
400
|
-
layer="${layer:-knowledge}"
|
|
401
|
-
category="${category:-resources}"
|
|
402
|
-
topicSlug=$(echo "${topic:-general}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
403
|
-
|
|
404
|
-
if [ "$layer" = "daily" ]; then
|
|
405
|
-
dailyFile="$memRoot/daily/${day}.md"
|
|
406
|
-
[ ! -f "$dailyFile" ] && echo "# Daily Notes — ${day}" > "$dailyFile"
|
|
407
|
-
echo "" >> "$dailyFile"
|
|
408
|
-
echo "## [${ts}] ${topic:-note}" >> "$dailyFile"
|
|
409
|
-
echo "${content}" >> "$dailyFile"
|
|
410
|
-
echo " [daily] Appended to $dailyFile"
|
|
411
|
-
elif [ "$layer" = "tacit" ]; then
|
|
412
|
-
[ ! -f "$memRoot/tacit.md" ] && echo "# Org Operating Patterns — ${org_name}" > "$memRoot/tacit.md"
|
|
413
|
-
echo "" >> "$memRoot/tacit.md"
|
|
414
|
-
echo "## ${topic}" >> "$memRoot/tacit.md"
|
|
415
|
-
echo "${content}" >> "$memRoot/tacit.md"
|
|
416
|
-
echo " [tacit] Pattern saved."
|
|
417
|
-
else
|
|
418
|
-
# Layer 1: knowledge graph
|
|
419
|
-
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
420
|
-
mkdir -p "$entityDir"
|
|
421
|
-
factId="fact-$(python3 -c 'import time; print(int(time.time()*1000))')"
|
|
422
|
-
python3 - "$entityDir/items.yaml" "$factId" "${topic}" "${content}" "$ts" <<'PYEOF'
|
|
423
|
-
import sys, yaml, os
|
|
424
|
-
path, fid, topic, body, ts = sys.argv[1:]
|
|
425
|
-
facts = []
|
|
426
|
-
if os.path.exists(path):
|
|
427
|
-
try:
|
|
428
|
-
with open(path) as f:
|
|
429
|
-
loaded = yaml.safe_load(f)
|
|
430
|
-
if isinstance(loaded, list): facts = loaded
|
|
431
|
-
except: pass
|
|
432
|
-
facts.append({"id": fid, "topic": topic, "body": body, "createdAt": ts, "status": "active"})
|
|
433
|
-
with open(path, "w") as f:
|
|
434
|
-
yaml.dump(facts, f, default_flow_style=False, allow_unicode=True)
|
|
435
|
-
print(f" Fact saved: {fid} → {path}")
|
|
436
|
-
PYEOF
|
|
437
|
-
fi
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
### recall / query
|
|
441
|
-
|
|
442
|
-
Search org memory across all layers for a topic or keyword.
|
|
443
|
-
|
|
444
|
-
```bash
|
|
445
|
-
q="${topic:-${content}}"
|
|
446
|
-
echo "MEMORY RECALL — ${org_name}"
|
|
447
|
-
echo "Query: $q"
|
|
448
|
-
echo "────────────────────────────────────────────────────────"
|
|
449
|
-
|
|
450
|
-
python3 - "$memRoot" "$q" <<'PYEOF'
|
|
451
|
-
import os, sys, yaml, re
|
|
452
|
-
root, query = sys.argv[1], sys.argv[2].lower()
|
|
453
|
-
results = []
|
|
454
|
-
|
|
455
|
-
# Layer 1: scan items.yaml files
|
|
456
|
-
kg = os.path.join(root, "knowledge")
|
|
457
|
-
for cat in ["projects","areas","resources","archives"]:
|
|
458
|
-
cpath = os.path.join(kg, cat)
|
|
459
|
-
if not os.path.isdir(cpath): continue
|
|
460
|
-
for topic in os.listdir(cpath):
|
|
461
|
-
ypath = os.path.join(cpath, topic, "items.yaml")
|
|
462
|
-
if not os.path.exists(ypath): continue
|
|
463
|
-
try:
|
|
464
|
-
facts = yaml.safe_load(open(ypath)) or []
|
|
465
|
-
for f in facts:
|
|
466
|
-
if f.get("status") == "superseded": continue
|
|
467
|
-
body = str(f.get("body","")).lower()
|
|
468
|
-
ftopic = str(f.get("topic","")).lower()
|
|
469
|
-
if query in body or query in ftopic or query in topic.lower():
|
|
470
|
-
results.append(("knowledge/"+cat+"/"+topic, f.get("createdAt","?")[:10], f.get("body","")[:120]))
|
|
471
|
-
except: pass
|
|
472
|
-
|
|
473
|
-
# Layer 2: daily notes
|
|
474
|
-
daily_dir = os.path.join(root, "daily")
|
|
475
|
-
if os.path.isdir(daily_dir):
|
|
476
|
-
for fname in sorted(os.listdir(daily_dir), reverse=True)[:30]:
|
|
477
|
-
try:
|
|
478
|
-
text = open(os.path.join(daily_dir, fname)).read().lower()
|
|
479
|
-
if query in text:
|
|
480
|
-
results.append(("daily/"+fname, fname[:10], "(match in daily notes)"))
|
|
481
|
-
except: pass
|
|
482
|
-
|
|
483
|
-
# Layer 3: tacit
|
|
484
|
-
tacit = os.path.join(root, "tacit.md")
|
|
485
|
-
if os.path.exists(tacit):
|
|
486
|
-
text = open(tacit).read().lower()
|
|
487
|
-
if query in text:
|
|
488
|
-
results.append(("tacit.md", "", "(match in org patterns)"))
|
|
489
|
-
|
|
490
|
-
if not results:
|
|
491
|
-
print(" No matches found.")
|
|
492
|
-
else:
|
|
493
|
-
print(f" {len(results)} result(s):")
|
|
494
|
-
for path, date, body in results[:20]:
|
|
495
|
-
print(f"\n [{date}] {path}")
|
|
496
|
-
print(f" {body[:100]}{'...' if len(body)>100 else ''}")
|
|
497
|
-
PYEOF
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
### list
|
|
501
|
-
|
|
502
|
-
List all entities in the knowledge graph.
|
|
503
|
-
|
|
504
|
-
```bash
|
|
505
|
-
echo "KNOWLEDGE GRAPH — ${org_name}"
|
|
506
|
-
echo "────────────────────────────────────────────────────────"
|
|
507
|
-
|
|
508
|
-
python3 - "$memRoot/knowledge" <<'PYEOF'
|
|
509
|
-
import os, sys, yaml
|
|
510
|
-
kg = sys.argv[1]
|
|
511
|
-
total = 0
|
|
512
|
-
for cat in ["projects","areas","resources","archives"]:
|
|
513
|
-
cpath = os.path.join(kg, cat)
|
|
514
|
-
if not os.path.isdir(cpath): continue
|
|
515
|
-
topics = [d for d in os.listdir(cpath) if os.path.isdir(os.path.join(cpath,d))]
|
|
516
|
-
if not topics: continue
|
|
517
|
-
print(f"\n {cat.upper()} ({len(topics)})")
|
|
518
|
-
for t in sorted(topics):
|
|
519
|
-
ypath = os.path.join(cpath, t, "items.yaml")
|
|
520
|
-
count = 0
|
|
521
|
-
try:
|
|
522
|
-
facts = yaml.safe_load(open(ypath)) or []
|
|
523
|
-
count = len([f for f in facts if f.get("status") != "superseded"])
|
|
524
|
-
except: pass
|
|
525
|
-
print(f" · {t} ({count} facts)")
|
|
526
|
-
total += len(topics)
|
|
527
|
-
print(f"\n Total entities: {total}")
|
|
528
|
-
PYEOF
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
### forget
|
|
532
|
-
|
|
533
|
-
Mark a fact as superseded (never delete — supersede).
|
|
534
|
-
|
|
535
|
-
```bash
|
|
536
|
-
topicSlug=$(echo "${topic}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
537
|
-
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
538
|
-
category="${category:-resources}"
|
|
539
|
-
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
540
|
-
ypath="$entityDir/items.yaml"
|
|
541
|
-
|
|
542
|
-
python3 - "$ypath" "$ts" "${content:-forgot}" <<'PYEOF'
|
|
543
|
-
import sys, yaml, os
|
|
544
|
-
path, ts, reason = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
545
|
-
if not os.path.exists(path):
|
|
546
|
-
print(" No facts found for this entity.")
|
|
547
|
-
sys.exit(0)
|
|
548
|
-
facts = yaml.safe_load(open(path)) or []
|
|
549
|
-
active = [f for f in facts if f.get("status") == "active"]
|
|
550
|
-
for f in active:
|
|
551
|
-
f["status"] = "superseded"
|
|
552
|
-
f["supersededAt"] = ts
|
|
553
|
-
f["supersededReason"] = reason
|
|
554
|
-
with open(path, "w") as out:
|
|
555
|
-
yaml.dump(facts, out, default_flow_style=False, allow_unicode=True)
|
|
556
|
-
print(f" {len(active)} fact(s) superseded in {path}")
|
|
557
|
-
PYEOF
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
### synthesize
|
|
561
|
-
|
|
562
|
-
Rebuild summary.md for an entity from its active facts.
|
|
563
|
-
|
|
564
|
-
```bash
|
|
565
|
-
topicSlug=$(echo "${topic}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
566
|
-
category="${category:-resources}"
|
|
567
|
-
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
568
|
-
ypath="$entityDir/items.yaml"
|
|
569
|
-
[ ! -f "$ypath" ] && { echo " No facts found for '${topic}'."; exit 0; }
|
|
570
|
-
|
|
571
|
-
python3 - "$ypath" "$entityDir/summary.md" "${topic}" <<'PYEOF'
|
|
572
|
-
import sys, yaml
|
|
573
|
-
ypath, sumpath, topic = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
574
|
-
facts = [f for f in (yaml.safe_load(open(ypath)) or []) if f.get("status") == "active"]
|
|
575
|
-
lines = [f"# {topic}", "", f"{len(facts)} active fact(s):", ""]
|
|
576
|
-
for f in facts:
|
|
577
|
-
date = str(f.get("createdAt","?"))[:10]
|
|
578
|
-
lines.append(f"- [{date}] {f.get('body','')}")
|
|
579
|
-
open(sumpath, "w").write("\n".join(lines) + "\n")
|
|
580
|
-
print(f" Summary rebuilt: {sumpath}")
|
|
581
|
-
PYEOF
|
|
582
|
-
```
|
|
583
|
-
|
|
584
|
-
### decay
|
|
585
|
-
|
|
586
|
-
Archive entities with no facts updated in the last 90 days.
|
|
587
|
-
|
|
588
|
-
```bash
|
|
589
|
-
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
590
|
-
|
|
591
|
-
python3 - "$memRoot/knowledge" "$ts" <<'PYEOF'
|
|
592
|
-
import os, sys, yaml, shutil
|
|
593
|
-
from datetime import datetime, timedelta
|
|
594
|
-
kg, ts = sys.argv[1], sys.argv[2]
|
|
595
|
-
cutoff = datetime.utcnow() - timedelta(days=90)
|
|
596
|
-
archived = 0
|
|
597
|
-
for cat in ["projects","areas","resources"]:
|
|
598
|
-
cpath = os.path.join(kg, cat)
|
|
599
|
-
if not os.path.isdir(cpath): continue
|
|
600
|
-
for topic in os.listdir(cpath):
|
|
601
|
-
ypath = os.path.join(cpath, topic, "items.yaml")
|
|
602
|
-
if not os.path.exists(ypath): continue
|
|
603
|
-
try:
|
|
604
|
-
facts = yaml.safe_load(open(ypath)) or []
|
|
605
|
-
active = [f for f in facts if f.get("status") == "active"]
|
|
606
|
-
if not active: continue
|
|
607
|
-
last = max(f.get("createdAt","")[:19] for f in active)
|
|
608
|
-
dt = datetime.fromisoformat(last)
|
|
609
|
-
if dt < cutoff:
|
|
610
|
-
dst = os.path.join(kg, "archives", topic)
|
|
611
|
-
shutil.move(os.path.join(cpath, topic), dst)
|
|
612
|
-
archived += 1
|
|
613
|
-
print(f" Archived: {cat}/{topic} (last active: {last[:10]})")
|
|
614
|
-
except: pass
|
|
615
|
-
print(f"\n Decay complete: {archived} entity/entities moved to archives.")
|
|
616
|
-
PYEOF
|
|
617
|
-
```
|
|
618
|
-
|
|
619
|
-
---
|
|
620
|
-
|
|
621
|
-
## Step 3 — Return Output
|
|
622
|
-
|
|
623
|
-
```yaml
|
|
624
|
-
domain: ops
|
|
625
|
-
status: complete
|
|
626
|
-
action: <action>
|
|
627
|
-
org_name: <org_name>
|
|
628
|
-
layer: <layer>
|
|
629
|
-
topic: <topic>
|
|
630
|
-
```
|
|
631
|
-
|
|
632
|
-
---
|
|
633
|
-
|
|
634
|
-
## Step 4 — Brain Write (standalone only)
|
|
635
|
-
|
|
636
|
-
If `caller` is not "command", follow mastermind-protocol/SKILL.md Brain Write Procedure for domain `ops`.
|
|
637
|
-
# monomind:end skills:claude:mastermind-memory
|
|
@@ -18,7 +18,7 @@ This skill is invoked by `mastermind:my-issues` or directly via `/mastermind:my-
|
|
|
18
18
|
- `action`: list | assign-self | unassign | close
|
|
19
19
|
- `assignee_id`: user/agent id to filter by (default: local-operator)
|
|
20
20
|
- `issue_id`: issue id (required for assign-self / unassign / close)
|
|
21
|
-
- `status_filter`:
|
|
21
|
+
- `status_filter`: active | todo | in_progress | blocked | in_review | done | cancelled | all (default: active = todo+in_progress)
|
|
22
22
|
- `caller`: command | master
|
|
23
23
|
|
|
24
24
|
---
|
|
@@ -41,6 +41,38 @@ issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
|
41
41
|
assigneeFilter="${assignee_id:-local-operator}"
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
Normalize any legacy records written by a pre-2.10 version of these skills. Idempotent — safe to run on every load.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 - "$issuesFile" <<'PYEOF'
|
|
48
|
+
import json, sys
|
|
49
|
+
path = sys.argv[1]
|
|
50
|
+
data = json.load(open(path))
|
|
51
|
+
RENAME = {
|
|
52
|
+
"assignee_id": "assigneeId", "assigned_to": "assigneeId",
|
|
53
|
+
"created_at": "createdAt", "updated_at": "updatedAt",
|
|
54
|
+
"closed_at": "closedAt", "project_id": "projectId",
|
|
55
|
+
"parent_id": "parentId", "recovery_status": "recoveryStatus",
|
|
56
|
+
"lastActivityAt": "updatedAt",
|
|
57
|
+
}
|
|
58
|
+
changed = False
|
|
59
|
+
for iss in data.get("issues", []):
|
|
60
|
+
for old, new in RENAME.items():
|
|
61
|
+
if old in iss:
|
|
62
|
+
iss.setdefault(new, iss.pop(old))
|
|
63
|
+
iss.pop(old, None)
|
|
64
|
+
changed = True
|
|
65
|
+
if iss.get("status") == "open":
|
|
66
|
+
iss["status"] = "todo"
|
|
67
|
+
changed = True
|
|
68
|
+
if changed:
|
|
69
|
+
tmp = path + ".tmp"
|
|
70
|
+
with open(tmp, "w") as f:
|
|
71
|
+
json.dump(data, f, indent=2)
|
|
72
|
+
import os; os.replace(tmp, path)
|
|
73
|
+
PYEOF
|
|
74
|
+
```
|
|
75
|
+
|
|
44
76
|
---
|
|
45
77
|
|
|
46
78
|
## Step 2 — Execute Action
|
|
@@ -57,19 +89,19 @@ echo "────────────────────────
|
|
|
57
89
|
jq -r --arg uid "$assigneeFilter" --arg sf "$statusFilter" '
|
|
58
90
|
(.issues // [])[] |
|
|
59
91
|
select(
|
|
60
|
-
(.assigneeId == $uid
|
|
61
|
-
(if $sf == "active" then (.status == "
|
|
92
|
+
(.assigneeId == $uid) and
|
|
93
|
+
(if $sf == "active" then (.status == "todo" or .status == "in_progress")
|
|
62
94
|
elif $sf == "all" then true
|
|
63
95
|
else .status == $sf
|
|
64
96
|
end)
|
|
65
97
|
) |
|
|
66
|
-
[.id, (.status // "
|
|
98
|
+
[.id, (.status // "todo"), (.priority // "medium"), (.title // "(no title)")] | @tsv
|
|
67
99
|
' "$issuesFile" | while IFS=$'\t' read -r id st pri title; do
|
|
68
100
|
printf "%-24s %-12s %-10s %s\n" "$id" "$st" "$pri" "$title"
|
|
69
101
|
done
|
|
70
102
|
|
|
71
103
|
total=$(jq -r --arg uid "$assigneeFilter" \
|
|
72
|
-
'[(.issues // [])[] | select(.assigneeId == $uid
|
|
104
|
+
'[(.issues // [])[] | select(.assigneeId == $uid)] | length' \
|
|
73
105
|
"$issuesFile")
|
|
74
106
|
echo ""
|
|
75
107
|
echo "Total assigned: $total"
|
|
@@ -88,7 +120,7 @@ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
88
120
|
tmp="${issuesFile}.tmp"
|
|
89
121
|
jq --arg id "$issue_id" --arg uid "$assigneeFilter" --arg ts "$ts" \
|
|
90
122
|
'.issues = [(.issues // [])[] | if .id == $id then
|
|
91
|
-
.assigneeId = $uid | .
|
|
123
|
+
.assigneeId = $uid | .assigneeUserId = $uid | .assigneeAgentId = null | .updatedAt = $ts
|
|
92
124
|
else . end]' \
|
|
93
125
|
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
94
126
|
|
|
@@ -104,7 +136,7 @@ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
104
136
|
tmp="${issuesFile}.tmp"
|
|
105
137
|
jq --arg id "$issue_id" --arg ts "$ts" \
|
|
106
138
|
'.issues = [(.issues // [])[] | if .id == $id then
|
|
107
|
-
.assigneeId = null | .
|
|
139
|
+
.assigneeId = null | .assigneeUserId = null | .assigneeAgentId = null | .updatedAt = $ts
|
|
108
140
|
else . end]' \
|
|
109
141
|
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
110
142
|
|
|
@@ -120,7 +152,7 @@ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
|
120
152
|
tmp="${issuesFile}.tmp"
|
|
121
153
|
jq --arg id "$issue_id" --arg ts "$ts" \
|
|
122
154
|
'.issues = [(.issues // [])[] | if .id == $id then
|
|
123
|
-
.status = "done" | .closedAt = $ts | .
|
|
155
|
+
.status = "done" | .closedAt = $ts | .updatedAt = $ts
|
|
124
156
|
else . end]' \
|
|
125
157
|
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
126
158
|
|
|
@@ -14,16 +14,5 @@ Use the `monomind org` commands as the portable organization control surface.
|
|
|
14
14
|
- Stop a running organization with `monomind org stop <name>`.
|
|
15
15
|
|
|
16
16
|
Before changing organization configuration, inspect its current status and preserve the user's explicit goal, budget, and safety constraints. Use the platform's native task and agent interfaces when available; otherwise keep the CLI as the functional source of truth.
|
|
17
|
-
# monomind:start skills:claude:mastermind-org
|
|
18
|
-
# Mastermind Organization
|
|
19
|
-
|
|
20
|
-
Use the `monomind org` commands as the portable organization control surface.
|
|
21
|
-
|
|
22
|
-
- Create or configure an organization with `monomind org create` or the platform's organization workflow.
|
|
23
|
-
- Run an organization once with `monomind org run <name>`.
|
|
24
|
-
- Host scheduled organizations with `monomind org serve`.
|
|
25
|
-
- Inspect status with `monomind org status [name]` and validate configuration with `monomind org validate [name]`.
|
|
26
|
-
- Stop a running organization with `monomind org stop <name>`.
|
|
27
17
|
|
|
28
|
-
|
|
29
|
-
# monomind:end skills:claude:mastermind-org
|
|
18
|
+
The org runtime does not read `<org>-issues.json`. Work is driven by the org definition's roles and goal plus an optional `--task` string.
|