@monoes/monomindcli 1.9.17 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/mastermind/_repeat.md +182 -39
- package/.claude/commands/mastermind/architect.md +17 -11
- package/.claude/commands/mastermind/brain.md +4 -0
- package/.claude/commands/mastermind/build.md +4 -0
- package/.claude/commands/mastermind/content.md +4 -0
- package/.claude/commands/mastermind/createorg.md +5 -3
- package/.claude/commands/mastermind/finance.md +4 -0
- package/.claude/commands/mastermind/idea.md +4 -0
- package/.claude/commands/mastermind/marketing.md +4 -0
- package/.claude/commands/mastermind/master.md +63 -37
- package/.claude/commands/mastermind/ops.md +4 -0
- package/.claude/commands/mastermind/release.md +4 -0
- package/.claude/commands/mastermind/research.md +4 -0
- package/.claude/commands/mastermind/review.md +4 -0
- package/.claude/commands/mastermind/runorg.md +5 -3
- package/.claude/commands/mastermind/sales.md +4 -0
- package/.claude/commands/mastermind/techport.md +9 -0
- package/.claude/commands/monomind/do.md +5 -1
- package/.claude/commands/monomind/idea.md +5 -1
- package/.claude/commands/monomind/improve.md +5 -1
- package/.claude/commands/monomind/repeat.md +85 -29
- package/.claude/commands/monomind/review.md +6 -2
- package/.claude/commands/monomind/understand.md +10 -8
- package/.claude/helpers/extras-registry.json +235 -235
- package/.claude/helpers/graphify-freshen.cjs +13 -1
- package/.claude/helpers/hook-handler.cjs +1 -1
- package/.claude/helpers/router.cjs +4 -1
- package/.claude/skills/mastermind/_protocol.md +28 -21
- package/.claude/skills/mastermind/access.md +236 -0
- package/.claude/skills/mastermind/activity.md +191 -0
- package/.claude/skills/mastermind/adapter-manager.md +259 -0
- package/.claude/skills/mastermind/adapters.md +204 -0
- package/.claude/skills/mastermind/agent-detail.md +242 -0
- package/.claude/skills/mastermind/agents.md +178 -0
- package/.claude/skills/mastermind/approval-detail.md +259 -0
- package/.claude/skills/mastermind/approve.md +181 -0
- package/.claude/skills/mastermind/architect.md +24 -8
- package/.claude/skills/mastermind/backup.md +197 -0
- package/.claude/skills/mastermind/bootstrap.md +190 -0
- package/.claude/skills/mastermind/budgets.md +237 -0
- package/.claude/skills/mastermind/companies.md +256 -0
- package/.claude/skills/mastermind/costs.md +151 -0
- package/.claude/skills/mastermind/createorg.md +23 -5
- package/.claude/skills/mastermind/diagnose.md +249 -0
- package/.claude/skills/mastermind/env.md +198 -0
- package/.claude/skills/mastermind/environments.md +250 -0
- package/.claude/skills/mastermind/export.md +324 -0
- package/.claude/skills/mastermind/goal-detail.md +255 -0
- package/.claude/skills/mastermind/goals.md +149 -0
- package/.claude/skills/mastermind/heartbeat.md +164 -0
- package/.claude/skills/mastermind/idea.md +250 -122
- package/.claude/skills/mastermind/import.md +281 -0
- package/.claude/skills/mastermind/inbox.md +214 -0
- package/.claude/skills/mastermind/instance-settings.md +315 -0
- package/.claude/skills/mastermind/instance.md +231 -0
- package/.claude/skills/mastermind/invite-landing.md +227 -0
- package/.claude/skills/mastermind/invites.md +254 -0
- package/.claude/skills/mastermind/issue-detail.md +291 -0
- package/.claude/skills/mastermind/issues.md +235 -0
- package/.claude/skills/mastermind/join-queue.md +170 -0
- package/.claude/skills/mastermind/liveness.md +392 -0
- package/.claude/skills/mastermind/memory.md +321 -0
- package/.claude/skills/mastermind/my-issues.md +146 -0
- package/.claude/skills/mastermind/new-agent.md +241 -0
- package/.claude/skills/mastermind/org-chart.md +207 -0
- package/.claude/skills/mastermind/org-settings.md +217 -0
- package/.claude/skills/mastermind/plan-to-tasks.md +136 -0
- package/.claude/skills/mastermind/plugin-manager.md +241 -0
- package/.claude/skills/mastermind/plugin-settings.md +273 -0
- package/.claude/skills/mastermind/plugins.md +190 -0
- package/.claude/skills/mastermind/profile.md +187 -0
- package/.claude/skills/mastermind/project-detail.md +249 -0
- package/.claude/skills/mastermind/project-workspace.md +244 -0
- package/.claude/skills/mastermind/projects.md +164 -0
- package/.claude/skills/mastermind/routine-detail.md +253 -0
- package/.claude/skills/mastermind/routines.md +202 -0
- package/.claude/skills/mastermind/runorg.md +74 -9
- package/.claude/skills/mastermind/search.md +186 -0
- package/.claude/skills/mastermind/secrets.md +199 -0
- package/.claude/skills/mastermind/skills.md +156 -0
- package/.claude/skills/mastermind/tasks.md +149 -0
- package/.claude/skills/mastermind/techport.md +5 -5
- package/.claude/skills/mastermind/threads.md +259 -0
- package/.claude/skills/mastermind/tree-control.md +250 -0
- package/.claude/skills/mastermind/wiki.md +314 -0
- package/.claude/skills/mastermind/workspace-detail.md +317 -0
- package/.claude/skills/mastermind/workspaces.md +261 -0
- package/.claude/skills/mastermind/worktree.md +187 -0
- package/dist/src/init/executor.js +8 -8
- package/dist/src/init/executor.js.map +1 -1
- package/dist/src/init/statusline-generator.d.ts.map +1 -1
- package/dist/src/init/statusline-generator.js +12 -0
- package/dist/src/init/statusline-generator.js.map +1 -1
- package/dist/src/ui/.monomind/data/ranked-context.json +1 -1
- package/dist/src/ui/.monomind/loops/mastermind-review-1778664132789.json +16 -0
- package/dist/src/ui/.monomind/sessions/current.json +5 -5
- package/dist/src/ui/.monomind/sessions/session-1776778451399.json +15 -0
- package/dist/src/ui/dashboard.html +3030 -181
- package/dist/src/ui/data/mastermind-events.jsonl +8 -0
- package/dist/src/ui/data/mastermind-sessions.json +1 -0
- package/dist/src/ui/server.mjs +738 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/.claude/skills/.monomind/data/ranked-context.json +0 -5
- package/.claude/skills/.monomind/sessions/current.json +0 -13
- package/.claude/skills/.monomind/sessions/session-1777829336455.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777831614725.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777832095857.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777839814183.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777841847131.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777843309463.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777880867159.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777881884593.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884090471.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777884808221.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777885672155.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777886852818.json +0 -15
- package/.claude/skills/.monomind/sessions/session-1777896532690.json +0 -15
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-memory
|
|
3
|
+
description: Mastermind memory — org-scoped persistent memory using PARA method (Projects, Areas, Resources, Archives). Ingest facts, recall context, maintain knowledge graph, run weekly synthesis. Reads from .monomind/orgs/<org>-memory/ directory. Port of Paperclip's para-memory-files skill for org-level context.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind Memory
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:memory` or directly via `/mastermind:memory`.
|
|
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 memory to operate on (required)
|
|
18
|
+
- `action`: ingest | recall | query | update | forget | synthesize | decay | list
|
|
19
|
+
- `topic`: topic or entity name (required for ingest/recall/update/forget)
|
|
20
|
+
- `layer`: knowledge | daily | tacit (default: knowledge)
|
|
21
|
+
- `category`: projects | areas | resources | archives (for layer=knowledge; default: resources)
|
|
22
|
+
- `content`: fact or note body (required for ingest/update)
|
|
23
|
+
- `caller`: command | master
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Memory Architecture (PARA)
|
|
28
|
+
|
|
29
|
+
Three layers, mirrored to `.monomind/orgs/<org_name>-memory/`:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
.monomind/orgs/<org>-memory/
|
|
33
|
+
knowledge/ ← Layer 1: PARA knowledge graph
|
|
34
|
+
projects/<topic>/
|
|
35
|
+
summary.md
|
|
36
|
+
items.yaml
|
|
37
|
+
areas/<topic>/
|
|
38
|
+
summary.md
|
|
39
|
+
items.yaml
|
|
40
|
+
resources/<topic>/
|
|
41
|
+
summary.md
|
|
42
|
+
items.yaml
|
|
43
|
+
archives/<topic>/
|
|
44
|
+
summary.md
|
|
45
|
+
items.yaml
|
|
46
|
+
index.md
|
|
47
|
+
daily/ ← Layer 2: Raw timeline (YYYY-MM-DD.md)
|
|
48
|
+
tacit.md ← Layer 3: Org operating patterns
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**PARA rules:**
|
|
52
|
+
- **projects** — active work with a goal/deadline; archive when complete
|
|
53
|
+
- **areas** — ongoing responsibilities, no end date
|
|
54
|
+
- **resources** — reference material, topics of interest
|
|
55
|
+
- **archives** — inactive items from any category
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Step 0 — Brain Load (standalone only)
|
|
60
|
+
|
|
61
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Step 1 — Resolve Memory Root
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
memRoot=".monomind/orgs/${org_name}-memory"
|
|
69
|
+
mkdir -p "$memRoot/knowledge/projects" "$memRoot/knowledge/areas" \
|
|
70
|
+
"$memRoot/knowledge/resources" "$memRoot/knowledge/archives" \
|
|
71
|
+
"$memRoot/daily"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Step 2 — Execute Action
|
|
77
|
+
|
|
78
|
+
### ingest (default for new facts)
|
|
79
|
+
|
|
80
|
+
Store a durable fact in Layer 1 (knowledge graph) or Layer 2 (daily note).
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
84
|
+
day=$(date -u +%Y-%m-%d)
|
|
85
|
+
layer="${layer:-knowledge}"
|
|
86
|
+
category="${category:-resources}"
|
|
87
|
+
topicSlug=$(echo "${topic:-general}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
88
|
+
|
|
89
|
+
if [ "$layer" = "daily" ]; then
|
|
90
|
+
dailyFile="$memRoot/daily/${day}.md"
|
|
91
|
+
[ ! -f "$dailyFile" ] && echo "# Daily Notes — ${day}" > "$dailyFile"
|
|
92
|
+
echo "" >> "$dailyFile"
|
|
93
|
+
echo "## [${ts}] ${topic:-note}" >> "$dailyFile"
|
|
94
|
+
echo "${content}" >> "$dailyFile"
|
|
95
|
+
echo " [daily] Appended to $dailyFile"
|
|
96
|
+
elif [ "$layer" = "tacit" ]; then
|
|
97
|
+
[ ! -f "$memRoot/tacit.md" ] && echo "# Org Operating Patterns — ${org_name}" > "$memRoot/tacit.md"
|
|
98
|
+
echo "" >> "$memRoot/tacit.md"
|
|
99
|
+
echo "## ${topic}" >> "$memRoot/tacit.md"
|
|
100
|
+
echo "${content}" >> "$memRoot/tacit.md"
|
|
101
|
+
echo " [tacit] Pattern saved."
|
|
102
|
+
else
|
|
103
|
+
# Layer 1: knowledge graph
|
|
104
|
+
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
105
|
+
mkdir -p "$entityDir"
|
|
106
|
+
factId="fact-$(python3 -c 'import time; print(int(time.time()*1000))')"
|
|
107
|
+
python3 - "$entityDir/items.yaml" "$factId" "${topic}" "${content}" "$ts" <<'PYEOF'
|
|
108
|
+
import sys, yaml, os
|
|
109
|
+
path, fid, topic, body, ts = sys.argv[1:]
|
|
110
|
+
facts = []
|
|
111
|
+
if os.path.exists(path):
|
|
112
|
+
try:
|
|
113
|
+
with open(path) as f:
|
|
114
|
+
loaded = yaml.safe_load(f)
|
|
115
|
+
if isinstance(loaded, list): facts = loaded
|
|
116
|
+
except: pass
|
|
117
|
+
facts.append({"id": fid, "topic": topic, "body": body, "createdAt": ts, "status": "active"})
|
|
118
|
+
with open(path, "w") as f:
|
|
119
|
+
yaml.dump(facts, f, default_flow_style=False, allow_unicode=True)
|
|
120
|
+
print(f" Fact saved: {fid} → {path}")
|
|
121
|
+
PYEOF
|
|
122
|
+
fi
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### recall / query
|
|
126
|
+
|
|
127
|
+
Search org memory across all layers for a topic or keyword.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
q="${topic:-${content}}"
|
|
131
|
+
echo "MEMORY RECALL — ${org_name}"
|
|
132
|
+
echo "Query: $q"
|
|
133
|
+
echo "────────────────────────────────────────────────────────"
|
|
134
|
+
|
|
135
|
+
python3 - "$memRoot" "$q" <<'PYEOF'
|
|
136
|
+
import os, sys, yaml, re
|
|
137
|
+
root, query = sys.argv[1], sys.argv[2].lower()
|
|
138
|
+
results = []
|
|
139
|
+
|
|
140
|
+
# Layer 1: scan items.yaml files
|
|
141
|
+
kg = os.path.join(root, "knowledge")
|
|
142
|
+
for cat in ["projects","areas","resources","archives"]:
|
|
143
|
+
cpath = os.path.join(kg, cat)
|
|
144
|
+
if not os.path.isdir(cpath): continue
|
|
145
|
+
for topic in os.listdir(cpath):
|
|
146
|
+
ypath = os.path.join(cpath, topic, "items.yaml")
|
|
147
|
+
if not os.path.exists(ypath): continue
|
|
148
|
+
try:
|
|
149
|
+
facts = yaml.safe_load(open(ypath)) or []
|
|
150
|
+
for f in facts:
|
|
151
|
+
if f.get("status") == "superseded": continue
|
|
152
|
+
body = str(f.get("body","")).lower()
|
|
153
|
+
ftopic = str(f.get("topic","")).lower()
|
|
154
|
+
if query in body or query in ftopic or query in topic.lower():
|
|
155
|
+
results.append(("knowledge/"+cat+"/"+topic, f.get("createdAt","?")[:10], f.get("body","")[:120]))
|
|
156
|
+
except: pass
|
|
157
|
+
|
|
158
|
+
# Layer 2: daily notes
|
|
159
|
+
daily_dir = os.path.join(root, "daily")
|
|
160
|
+
if os.path.isdir(daily_dir):
|
|
161
|
+
for fname in sorted(os.listdir(daily_dir), reverse=True)[:30]:
|
|
162
|
+
try:
|
|
163
|
+
text = open(os.path.join(daily_dir, fname)).read().lower()
|
|
164
|
+
if query in text:
|
|
165
|
+
results.append(("daily/"+fname, fname[:10], "(match in daily notes)"))
|
|
166
|
+
except: pass
|
|
167
|
+
|
|
168
|
+
# Layer 3: tacit
|
|
169
|
+
tacit = os.path.join(root, "tacit.md")
|
|
170
|
+
if os.path.exists(tacit):
|
|
171
|
+
text = open(tacit).read().lower()
|
|
172
|
+
if query in text:
|
|
173
|
+
results.append(("tacit.md", "", "(match in org patterns)"))
|
|
174
|
+
|
|
175
|
+
if not results:
|
|
176
|
+
print(" No matches found.")
|
|
177
|
+
else:
|
|
178
|
+
print(f" {len(results)} result(s):")
|
|
179
|
+
for path, date, body in results[:20]:
|
|
180
|
+
print(f"\n [{date}] {path}")
|
|
181
|
+
print(f" {body[:100]}{'...' if len(body)>100 else ''}")
|
|
182
|
+
PYEOF
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### list
|
|
186
|
+
|
|
187
|
+
List all entities in the knowledge graph.
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
echo "KNOWLEDGE GRAPH — ${org_name}"
|
|
191
|
+
echo "────────────────────────────────────────────────────────"
|
|
192
|
+
|
|
193
|
+
python3 - "$memRoot/knowledge" <<'PYEOF'
|
|
194
|
+
import os, sys, yaml
|
|
195
|
+
kg = sys.argv[1]
|
|
196
|
+
total = 0
|
|
197
|
+
for cat in ["projects","areas","resources","archives"]:
|
|
198
|
+
cpath = os.path.join(kg, cat)
|
|
199
|
+
if not os.path.isdir(cpath): continue
|
|
200
|
+
topics = [d for d in os.listdir(cpath) if os.path.isdir(os.path.join(cpath,d))]
|
|
201
|
+
if not topics: continue
|
|
202
|
+
print(f"\n {cat.upper()} ({len(topics)})")
|
|
203
|
+
for t in sorted(topics):
|
|
204
|
+
ypath = os.path.join(cpath, t, "items.yaml")
|
|
205
|
+
count = 0
|
|
206
|
+
try:
|
|
207
|
+
facts = yaml.safe_load(open(ypath)) or []
|
|
208
|
+
count = len([f for f in facts if f.get("status") != "superseded"])
|
|
209
|
+
except: pass
|
|
210
|
+
print(f" · {t} ({count} facts)")
|
|
211
|
+
total += len(topics)
|
|
212
|
+
print(f"\n Total entities: {total}")
|
|
213
|
+
PYEOF
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### forget
|
|
217
|
+
|
|
218
|
+
Mark a fact as superseded (never delete — supersede).
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
topicSlug=$(echo "${topic}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
222
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
223
|
+
category="${category:-resources}"
|
|
224
|
+
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
225
|
+
ypath="$entityDir/items.yaml"
|
|
226
|
+
|
|
227
|
+
python3 - "$ypath" "$ts" "${content:-forgot}" <<'PYEOF'
|
|
228
|
+
import sys, yaml, os
|
|
229
|
+
path, ts, reason = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
230
|
+
if not os.path.exists(path):
|
|
231
|
+
print(" No facts found for this entity.")
|
|
232
|
+
sys.exit(0)
|
|
233
|
+
facts = yaml.safe_load(open(path)) or []
|
|
234
|
+
active = [f for f in facts if f.get("status") == "active"]
|
|
235
|
+
for f in active:
|
|
236
|
+
f["status"] = "superseded"
|
|
237
|
+
f["supersededAt"] = ts
|
|
238
|
+
f["supersededReason"] = reason
|
|
239
|
+
with open(path, "w") as out:
|
|
240
|
+
yaml.dump(facts, out, default_flow_style=False, allow_unicode=True)
|
|
241
|
+
print(f" {len(active)} fact(s) superseded in {path}")
|
|
242
|
+
PYEOF
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### synthesize
|
|
246
|
+
|
|
247
|
+
Rebuild summary.md for an entity from its active facts.
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
topicSlug=$(echo "${topic}" | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | tr -cd 'a-z0-9-')
|
|
251
|
+
category="${category:-resources}"
|
|
252
|
+
entityDir="$memRoot/knowledge/${category}/${topicSlug}"
|
|
253
|
+
ypath="$entityDir/items.yaml"
|
|
254
|
+
[ ! -f "$ypath" ] && { echo " No facts found for '${topic}'."; exit 0; }
|
|
255
|
+
|
|
256
|
+
python3 - "$ypath" "$entityDir/summary.md" "${topic}" <<'PYEOF'
|
|
257
|
+
import sys, yaml
|
|
258
|
+
ypath, sumpath, topic = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
259
|
+
facts = [f for f in (yaml.safe_load(open(ypath)) or []) if f.get("status") == "active"]
|
|
260
|
+
lines = [f"# {topic}", "", f"{len(facts)} active fact(s):", ""]
|
|
261
|
+
for f in facts:
|
|
262
|
+
date = str(f.get("createdAt","?"))[:10]
|
|
263
|
+
lines.append(f"- [{date}] {f.get('body','')}")
|
|
264
|
+
open(sumpath, "w").write("\n".join(lines) + "\n")
|
|
265
|
+
print(f" Summary rebuilt: {sumpath}")
|
|
266
|
+
PYEOF
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### decay
|
|
270
|
+
|
|
271
|
+
Archive entities with no facts updated in the last 90 days.
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
275
|
+
|
|
276
|
+
python3 - "$memRoot/knowledge" "$ts" <<'PYEOF'
|
|
277
|
+
import os, sys, yaml, shutil
|
|
278
|
+
from datetime import datetime, timedelta
|
|
279
|
+
kg, ts = sys.argv[1], sys.argv[2]
|
|
280
|
+
cutoff = datetime.utcnow() - timedelta(days=90)
|
|
281
|
+
archived = 0
|
|
282
|
+
for cat in ["projects","areas","resources"]:
|
|
283
|
+
cpath = os.path.join(kg, cat)
|
|
284
|
+
if not os.path.isdir(cpath): continue
|
|
285
|
+
for topic in os.listdir(cpath):
|
|
286
|
+
ypath = os.path.join(cpath, topic, "items.yaml")
|
|
287
|
+
if not os.path.exists(ypath): continue
|
|
288
|
+
try:
|
|
289
|
+
facts = yaml.safe_load(open(ypath)) or []
|
|
290
|
+
active = [f for f in facts if f.get("status") == "active"]
|
|
291
|
+
if not active: continue
|
|
292
|
+
last = max(f.get("createdAt","")[:19] for f in active)
|
|
293
|
+
dt = datetime.fromisoformat(last)
|
|
294
|
+
if dt < cutoff:
|
|
295
|
+
dst = os.path.join(kg, "archives", topic)
|
|
296
|
+
shutil.move(os.path.join(cpath, topic), dst)
|
|
297
|
+
archived += 1
|
|
298
|
+
print(f" Archived: {cat}/{topic} (last active: {last[:10]})")
|
|
299
|
+
except: pass
|
|
300
|
+
print(f"\n Decay complete: {archived} entity/entities moved to archives.")
|
|
301
|
+
PYEOF
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Step 3 — Return Output
|
|
307
|
+
|
|
308
|
+
```yaml
|
|
309
|
+
domain: ops
|
|
310
|
+
status: complete
|
|
311
|
+
action: <action>
|
|
312
|
+
org_name: <org_name>
|
|
313
|
+
layer: <layer>
|
|
314
|
+
topic: <topic>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## Step 4 — Brain Write (standalone only)
|
|
320
|
+
|
|
321
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mastermind-my-issues
|
|
3
|
+
description: Mastermind my-issues — filtered issue queue scoped to the current operator or a specific assignee. Lists open and in-progress issues, supports self-assign and unassign. Mirrors MyIssues.tsx.
|
|
4
|
+
type: domain-skill
|
|
5
|
+
default_mode: auto
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Mastermind My Issues
|
|
9
|
+
|
|
10
|
+
This skill is invoked by `mastermind:my-issues` or directly via `/mastermind:my-issues`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Inputs
|
|
15
|
+
|
|
16
|
+
- `brain_context`: BRAIN CONTEXT block (injected by command, or loaded below if standalone)
|
|
17
|
+
- `org_name`: org to query issues from (required)
|
|
18
|
+
- `action`: list | assign-self | unassign | close
|
|
19
|
+
- `assignee_id`: user/agent id to filter by (default: local-operator)
|
|
20
|
+
- `issue_id`: issue id (required for assign-self / unassign / close)
|
|
21
|
+
- `status_filter`: open | in_progress | all (default: open+in_progress)
|
|
22
|
+
- `caller`: command | master
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Step 0 — Brain Load (standalone only)
|
|
27
|
+
|
|
28
|
+
If `caller` is not "command", load brain context following _protocol.md Brain Load Procedure with namespace: `ops`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Step 1 — Load Issues
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
orgFile=".monomind/orgs/${org_name}.json"
|
|
36
|
+
[ ! -f "$orgFile" ] && { echo "ERROR: Org '${org_name}' not found."; exit 1; }
|
|
37
|
+
|
|
38
|
+
issuesFile=".monomind/orgs/${org_name}-issues.json"
|
|
39
|
+
[ ! -f "$issuesFile" ] && { echo "No issues found for org '${org_name}'."; exit 0; }
|
|
40
|
+
|
|
41
|
+
assigneeFilter="${assignee_id:-local-operator}"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Step 2 — Execute Action
|
|
47
|
+
|
|
48
|
+
### list (default)
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
statusFilter="${status_filter:-active}"
|
|
52
|
+
echo "MY ISSUES — org: $org_name assignee: $assigneeFilter"
|
|
53
|
+
echo "────────────────────────────────────────────────────────"
|
|
54
|
+
printf "%-24s %-12s %-10s %s\n" "ID" "STATUS" "PRIORITY" "TITLE"
|
|
55
|
+
echo "────────────────────────────────────────────────────────"
|
|
56
|
+
|
|
57
|
+
jq -r --arg uid "$assigneeFilter" --arg sf "$statusFilter" '
|
|
58
|
+
.issues[] |
|
|
59
|
+
select(
|
|
60
|
+
(.assigneeId == $uid or .assigned_to == $uid) and
|
|
61
|
+
(if $sf == "active" then (.status == "open" or .status == "in_progress")
|
|
62
|
+
elif $sf == "all" then true
|
|
63
|
+
else .status == $sf
|
|
64
|
+
end)
|
|
65
|
+
) |
|
|
66
|
+
[.id, (.status // "open"), (.priority // "medium"), (.title // "(no title)")] | @tsv
|
|
67
|
+
' "$issuesFile" | while IFS=$'\t' read -r id st pri title; do
|
|
68
|
+
printf "%-24s %-12s %-10s %s\n" "$id" "$st" "$pri" "$title"
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
total=$(jq -r --arg uid "$assigneeFilter" \
|
|
72
|
+
'[.issues[] | select(.assigneeId == $uid or .assigned_to == $uid)] | length' \
|
|
73
|
+
"$issuesFile")
|
|
74
|
+
echo ""
|
|
75
|
+
echo "Total assigned: $total"
|
|
76
|
+
[ "$total" -eq 0 ] && echo " No issues assigned to '$assigneeFilter'. To assign: --action assign-self --issue-id <id>"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### assign-self
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
[ -z "$issue_id" ] && { echo "ERROR: --issue-id required."; exit 1; }
|
|
83
|
+
|
|
84
|
+
exists=$(jq -r --arg id "$issue_id" '[.issues[] | select(.id == $id)] | length' "$issuesFile")
|
|
85
|
+
[ "$exists" -eq 0 ] && { echo "ERROR: Issue '$issue_id' not found."; exit 1; }
|
|
86
|
+
|
|
87
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
88
|
+
tmp="${issuesFile}.tmp"
|
|
89
|
+
jq --arg id "$issue_id" --arg uid "$assigneeFilter" --arg ts "$ts" \
|
|
90
|
+
'.issues = [.issues[] | if .id == $id then
|
|
91
|
+
.assigneeId = $uid | .lastActivityAt = $ts
|
|
92
|
+
else . end]' \
|
|
93
|
+
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
94
|
+
|
|
95
|
+
echo "Issue '$issue_id' assigned to '$assigneeFilter'."
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### unassign
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
[ -z "$issue_id" ] && { echo "ERROR: --issue-id required."; exit 1; }
|
|
102
|
+
|
|
103
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
104
|
+
tmp="${issuesFile}.tmp"
|
|
105
|
+
jq --arg id "$issue_id" --arg ts "$ts" \
|
|
106
|
+
'.issues = [.issues[] | if .id == $id then
|
|
107
|
+
.assigneeId = null | .lastActivityAt = $ts
|
|
108
|
+
else . end]' \
|
|
109
|
+
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
110
|
+
|
|
111
|
+
echo "Issue '$issue_id' unassigned."
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### close
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
[ -z "$issue_id" ] && { echo "ERROR: --issue-id required."; exit 1; }
|
|
118
|
+
|
|
119
|
+
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
120
|
+
tmp="${issuesFile}.tmp"
|
|
121
|
+
jq --arg id "$issue_id" --arg ts "$ts" \
|
|
122
|
+
'.issues = [.issues[] | if .id == $id then
|
|
123
|
+
.status = "done" | .closedAt = $ts | .lastActivityAt = $ts
|
|
124
|
+
else . end]' \
|
|
125
|
+
"$issuesFile" > "$tmp" && mv "$tmp" "$issuesFile"
|
|
126
|
+
|
|
127
|
+
echo "Issue '$issue_id' closed (status: done)."
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Step 3 — Return Output
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
domain: ops
|
|
136
|
+
status: complete
|
|
137
|
+
action: <action>
|
|
138
|
+
org: <org_name>
|
|
139
|
+
assignee: <assignee_id>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Step 4 — Brain Write (standalone only)
|
|
145
|
+
|
|
146
|
+
If `caller` is not "command", follow _protocol.md Brain Write Procedure for domain `ops`.
|