create-egregore 0.19.32 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/assets/egregore-launcher.js +118 -13
  2. package/bin/cli.js +48 -3
  3. package/lib/connect-runtime.js +4 -2
  4. package/lib/local.js +15 -1
  5. package/lib/prime-runtime.js +208 -0
  6. package/lib/setup.js +45 -3
  7. package/package.json +5 -4
  8. package/runtime/codex/.codex/skills/ingest-notion/SKILL.md +29 -0
  9. package/runtime/codex/.codex/skills/notion-connect/SKILL.md +29 -0
  10. package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
  11. package/runtime/codex/.codex/spec-manifest.json +3 -3
  12. package/runtime/codex/AGENTS.md +11 -4
  13. package/runtime/codex/bin/activity-data.sh +4 -8
  14. package/runtime/codex/bin/attendant.sh +13 -0
  15. package/runtime/codex/bin/autosave.sh +27 -1
  16. package/runtime/codex/bin/codex-render-spec.mjs +6 -0
  17. package/runtime/codex/bin/codex-session-start.sh +8 -1
  18. package/runtime/codex/bin/connect-refresh.sh +33 -0
  19. package/runtime/codex/bin/graph-batch.sh +25 -6
  20. package/runtime/codex/bin/graph-op.sh +5 -4
  21. package/runtime/codex/bin/graph.sh +31 -5
  22. package/runtime/codex/bin/ingest.py +81 -5
  23. package/runtime/codex/bin/lib/context.sh +26 -1
  24. package/runtime/codex/bin/lib/greeting.sh +4 -1
  25. package/runtime/codex/bin/lib/worktree-links.sh +25 -0
  26. package/runtime/codex/manifest.json +8 -1
  27. package/runtime/pi/.codex/skills/ingest-notion/SKILL.md +29 -0
  28. package/runtime/pi/.codex/skills/notion-connect/SKILL.md +29 -0
  29. package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
  30. package/runtime/pi/.codex/spec-manifest.json +3 -3
  31. package/runtime/pi/.pi/APPEND_SYSTEM.md +3 -2
  32. package/runtime/pi/.pi/extensions/egregore.ts +17 -6
  33. package/runtime/pi/.pi/spec-manifest.json +2 -2
  34. package/runtime/pi/AGENTS.md +11 -4
  35. package/runtime/pi/bin/activity-data.sh +4 -8
  36. package/runtime/pi/bin/attendant.sh +13 -0
  37. package/runtime/pi/bin/autosave.sh +27 -1
  38. package/runtime/pi/bin/codex-render-spec.mjs +6 -0
  39. package/runtime/pi/bin/codex-session-start.sh +8 -1
  40. package/runtime/pi/bin/connect-refresh.sh +33 -0
  41. package/runtime/pi/bin/graph-batch.sh +25 -6
  42. package/runtime/pi/bin/graph-op.sh +5 -4
  43. package/runtime/pi/bin/graph.sh +31 -5
  44. package/runtime/pi/bin/ingest.py +81 -5
  45. package/runtime/pi/bin/lib/context.sh +26 -1
  46. package/runtime/pi/bin/lib/greeting.sh +4 -1
  47. package/runtime/pi/bin/lib/worktree-links.sh +25 -0
  48. package/runtime/pi/bin/pi-branch-policy.mjs +138 -1
  49. package/runtime/pi/bin/pi-product-workflows.mjs +35 -7
  50. package/runtime/pi/manifest.json +8 -1
  51. package/runtime/prime/.claude/context/notification-consent.md +66 -0
  52. package/runtime/prime/.codex/config.toml +17 -0
  53. package/runtime/prime/.codex/hooks/branch-guard.js +461 -0
  54. package/runtime/prime/.codex/hooks/search-hint.js +67 -0
  55. package/runtime/prime/.codex/hooks.json +30 -0
  56. package/runtime/prime/.codex/skills/activity/SKILL.md +82 -0
  57. package/runtime/prime/.codex/skills/announce/SKILL.md +67 -0
  58. package/runtime/prime/.codex/skills/archive/SKILL.md +45 -0
  59. package/runtime/prime/.codex/skills/branch/SKILL.md +29 -0
  60. package/runtime/prime/.codex/skills/checkup/SKILL.md +45 -0
  61. package/runtime/prime/.codex/skills/commit/SKILL.md +29 -0
  62. package/runtime/prime/.codex/skills/contribute/SKILL.md +29 -0
  63. package/runtime/prime/.codex/skills/create-skill/SKILL.md +29 -0
  64. package/runtime/prime/.codex/skills/dark-mode/SKILL.md +29 -0
  65. package/runtime/prime/.codex/skills/dashboard/SKILL.md +59 -0
  66. package/runtime/prime/.codex/skills/deep-reflect/SKILL.md +109 -0
  67. package/runtime/prime/.codex/skills/delete-user/SKILL.md +29 -0
  68. package/runtime/prime/.codex/skills/emissary/SKILL.md +45 -0
  69. package/runtime/prime/.codex/skills/handoff/SKILL.md +166 -0
  70. package/runtime/prime/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  71. package/runtime/prime/.codex/skills/harvest/SKILL.md +131 -0
  72. package/runtime/prime/.codex/skills/ingest/SKILL.md +29 -0
  73. package/runtime/prime/.codex/skills/ingest-notion/SKILL.md +29 -0
  74. package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +45 -0
  75. package/runtime/prime/.codex/skills/invite/SKILL.md +44 -0
  76. package/runtime/prime/.codex/skills/issue/SKILL.md +45 -0
  77. package/runtime/prime/.codex/skills/me/SKILL.md +29 -0
  78. package/runtime/prime/.codex/skills/meeting/SKILL.md +45 -0
  79. package/runtime/prime/.codex/skills/note/SKILL.md +29 -0
  80. package/runtime/prime/.codex/skills/notion-connect/SKILL.md +29 -0
  81. package/runtime/prime/.codex/skills/onboarding/SKILL.md +45 -0
  82. package/runtime/prime/.codex/skills/pr/SKILL.md +29 -0
  83. package/runtime/prime/.codex/skills/pull/SKILL.md +29 -0
  84. package/runtime/prime/.codex/skills/push/SKILL.md +29 -0
  85. package/runtime/prime/.codex/skills/quest/SKILL.md +80 -0
  86. package/runtime/prime/.codex/skills/reflect/SKILL.md +45 -0
  87. package/runtime/prime/.codex/skills/review-pr/SKILL.md +45 -0
  88. package/runtime/prime/.codex/skills/save/SKILL.md +125 -0
  89. package/runtime/prime/.codex/skills/slack-connect/SKILL.md +29 -0
  90. package/runtime/prime/.codex/skills/summon/SKILL.md +45 -0
  91. package/runtime/prime/.codex/skills/sync-repos/SKILL.md +29 -0
  92. package/runtime/prime/.codex/skills/teams-connect/SKILL.md +29 -0
  93. package/runtime/prime/.codex/skills/telegram-connect/SKILL.md +29 -0
  94. package/runtime/prime/.codex/skills/telemetry/SKILL.md +29 -0
  95. package/runtime/prime/.codex/skills/test/SKILL.md +45 -0
  96. package/runtime/prime/.codex/skills/the-spiral/SKILL.md +84 -0
  97. package/runtime/prime/.codex/skills/tui-design/SKILL.md +45 -0
  98. package/runtime/prime/.codex/skills/tutorial/SKILL.md +45 -0
  99. package/runtime/prime/.codex/skills/update/SKILL.md +29 -0
  100. package/runtime/prime/.codex/skills/view/SKILL.md +156 -0
  101. package/runtime/prime/.codex/skills/view/agents/openai.yaml +4 -0
  102. package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +221 -0
  103. package/runtime/prime/.codex/skills/visual-explain/SKILL.md +45 -0
  104. package/runtime/prime/.codex/skills/wrap/SKILL.md +58 -0
  105. package/runtime/prime/.codex/spec-manifest.json +132 -0
  106. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +393 -0
  107. package/runtime/prime/.prime/agent/extensions/egregore.ts +460 -0
  108. package/runtime/prime/.prime/agent/settings.json +4 -0
  109. package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +34 -0
  110. package/runtime/prime/.prime/agent/skills/egregore/pyproject.toml +13 -0
  111. package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +156 -0
  112. package/runtime/prime/.prime/agent/spec-manifest.json +12 -0
  113. package/runtime/prime/AGENTS.md +489 -0
  114. package/runtime/prime/bin/activity-data.sh +238 -0
  115. package/runtime/prime/bin/agent.sh +775 -0
  116. package/runtime/prime/bin/attendant.sh +707 -0
  117. package/runtime/prime/bin/autosave.sh +112 -0
  118. package/runtime/prime/bin/capture-reconcile.sh +69 -0
  119. package/runtime/prime/bin/capture-run.sh +341 -0
  120. package/runtime/prime/bin/codex-install-skills.sh +78 -0
  121. package/runtime/prime/bin/codex-render-spec.mjs +440 -0
  122. package/runtime/prime/bin/codex-session-start.sh +265 -0
  123. package/runtime/prime/bin/codex-skill-render.mjs +347 -0
  124. package/runtime/prime/bin/codex-sync-skills.sh +232 -0
  125. package/runtime/prime/bin/connect-refresh.sh +33 -0
  126. package/runtime/prime/bin/dashboard-data.sh +178 -0
  127. package/runtime/prime/bin/graph-batch.sh +79 -0
  128. package/runtime/prime/bin/graph-op.sh +1102 -0
  129. package/runtime/prime/bin/graph-wal.sh +229 -0
  130. package/runtime/prime/bin/graph.sh +223 -0
  131. package/runtime/prime/bin/handoff-pr-backfill.sh +86 -0
  132. package/runtime/prime/bin/handoff-run.sh +671 -0
  133. package/runtime/prime/bin/handoff-save-egregore.sh +212 -0
  134. package/runtime/prime/bin/index-handoff.sh +322 -0
  135. package/runtime/prime/bin/ingest-graph.sh +80 -0
  136. package/runtime/prime/bin/ingest-surface.html +495 -0
  137. package/runtime/prime/bin/ingest.py +756 -0
  138. package/runtime/prime/bin/ingest.sh +279 -0
  139. package/runtime/prime/bin/ingest_graph.py +856 -0
  140. package/runtime/prime/bin/ingest_surface.py +544 -0
  141. package/runtime/prime/bin/lib/artifact-id.sh +46 -0
  142. package/runtime/prime/bin/lib/config.sh +116 -0
  143. package/runtime/prime/bin/lib/context.sh +621 -0
  144. package/runtime/prime/bin/lib/dashboard-artifact.sh +242 -0
  145. package/runtime/prime/bin/lib/ensure-develop.sh +183 -0
  146. package/runtime/prime/bin/lib/git-sync.sh +406 -0
  147. package/runtime/prime/bin/lib/greeting.sh +519 -0
  148. package/runtime/prime/bin/lib/hash.sh +13 -0
  149. package/runtime/prime/bin/lib/identity.sh +213 -0
  150. package/runtime/prime/bin/lib/metrics.sh +374 -0
  151. package/runtime/prime/bin/lib/noncode.sh +31 -0
  152. package/runtime/prime/bin/lib/permissions.sh +106 -0
  153. package/runtime/prime/bin/lib/time.sh +56 -0
  154. package/runtime/prime/bin/lib/worktree-links.sh +79 -0
  155. package/runtime/prime/bin/notify.sh +636 -0
  156. package/runtime/prime/bin/person.py +630 -0
  157. package/runtime/prime/bin/person.sh +448 -0
  158. package/runtime/prime/bin/pi-branch-policy.mjs +312 -0
  159. package/runtime/prime/bin/pi-product-workflows.mjs +394 -0
  160. package/runtime/prime/bin/prime-render-spec.mjs +123 -0
  161. package/runtime/prime/bin/prime-session-start.sh +24 -0
  162. package/runtime/prime/bin/publish-artifact.sh +271 -0
  163. package/runtime/prime/bin/publish-references.sh +144 -0
  164. package/runtime/prime/bin/repo-state.sh +96 -0
  165. package/runtime/prime/bin/search.sh +240 -0
  166. package/runtime/prime/bin/session-autosave.sh +209 -0
  167. package/runtime/prime/bin/session-log.sh +199 -0
  168. package/runtime/prime/bin/settings.sh +304 -0
  169. package/runtime/prime/bin/telemetry.sh +391 -0
  170. package/runtime/prime/bin/worktree-create.sh +128 -0
  171. package/runtime/prime/bin/worktree-remove.sh +50 -0
  172. package/runtime/prime/bin/worktree.sh +198 -0
  173. package/runtime/prime/manifest.json +178 -0
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env bash
2
+ # Fetches all activity dashboard data: single API call + parallel git/disk ops.
3
+ # Usage: bash bin/activity-data.sh [username]
4
+ # Returns a single JSON object with all query results.
5
+
6
+ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
7
+ TMPDIR=$(mktemp -d)
8
+ trap "rm -rf $TMPDIR" EXIT
9
+
10
+ # --- Read config ---
11
+ API_URL=$(jq -r '.api_url // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
12
+ API_KEY="${EGREGORE_API_KEY:-$(grep '^EGREGORE_API_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2-)}"
13
+ ORG=$(jq -r '.org_name // "Egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "Egregore")
14
+ DATE=$(date '+%b %d')
15
+
16
+ source "$SCRIPT_DIR/bin/lib/handoff-meta.sh" >/dev/null 2>/dev/null || true
17
+
18
+ # --- Detect user ---
19
+ GH_USER="${1:-}"
20
+ if [ -z "$GH_USER" ]; then
21
+ STATE_FILE="$SCRIPT_DIR/.egregore-state.json"
22
+ if [ -f "$STATE_FILE" ]; then
23
+ GH_USER=$(jq -r '.github_username // empty' "$STATE_FILE" 2>/dev/null)
24
+ fi
25
+ if [ -z "$GH_USER" ]; then
26
+ GH_USER=$(git -C "$SCRIPT_DIR" config user.name 2>/dev/null || echo "unknown")
27
+ fi
28
+ fi
29
+
30
+ EMPTY='{"fields":[],"values":[]}'
31
+
32
+ # --- Fire API call + git/disk ops in parallel ---
33
+
34
+ # Graph data: single API call (all queries run server-side)
35
+ (
36
+ GRAPH_STATUS="offline"
37
+ GRAPH_REASON=""
38
+ if [ -z "$API_URL" ] || [ -z "$API_KEY" ]; then
39
+ GRAPH_REASON="missing_config"
40
+ else
41
+ # Store HTTP status code alongside response body. curl already emits 000
42
+ # on transport failure; keep the exit status separate so it cannot become
43
+ # 000000 and fall through as an invalid JSON response.
44
+ CURL_STATUS=0
45
+ HTTP_CODE=$(curl -s -o "$TMPDIR/activity_raw.json" -w "%{http_code}" \
46
+ "${API_URL}/api/activity/dashboard?github_username=$(printf '%s' "$GH_USER" | jq -sRr @uri)" \
47
+ -H "Authorization: Bearer $API_KEY" \
48
+ --connect-timeout 5 --max-time 15 2>/dev/null) || CURL_STATUS=$?
49
+
50
+ if [ "$CURL_STATUS" -ne 0 ] || [ "$HTTP_CODE" = "000" ] || ! [[ "$HTTP_CODE" =~ ^[0-9][0-9][0-9]$ ]]; then
51
+ GRAPH_REASON="unreachable"
52
+ elif [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
53
+ GRAPH_REASON="auth_error"
54
+ elif [ "$HTTP_CODE" -ge 500 ] 2>/dev/null; then
55
+ GRAPH_REASON="server_error"
56
+ elif [ -s "$TMPDIR/activity_raw.json" ] && jq -e '.me' "$TMPDIR/activity_raw.json" >/dev/null 2>&1; then
57
+ cp "$TMPDIR/activity_raw.json" "$TMPDIR/activity.json"
58
+ GRAPH_STATUS="connected"
59
+ else
60
+ GRAPH_REASON="invalid_response"
61
+ fi
62
+ fi
63
+
64
+ # If not connected, write status-only response
65
+ if [ "$GRAPH_STATUS" != "connected" ]; then
66
+ jq -n --arg status "$GRAPH_STATUS" --arg reason "$GRAPH_REASON" \
67
+ '{graph_status: $status, graph_reason: $reason}' > "$TMPDIR/activity.json"
68
+ else
69
+ # Inject graph_status into successful response
70
+ jq --arg status "$GRAPH_STATUS" '. + {graph_status: $status}' \
71
+ "$TMPDIR/activity.json" > "$TMPDIR/activity_merged.json" \
72
+ && mv "$TMPDIR/activity_merged.json" "$TMPDIR/activity.json"
73
+ fi
74
+ ) &
75
+ API_PID=$!
76
+
77
+ # Git/disk: runs in parallel (stays client-side)
78
+ (
79
+ # Refresh remote refs only. A data read must never mutate the working
80
+ # branch: the rebase this block used to run rewrote users' task branches as
81
+ # a side effect of /activity (observed rewinding a pushed branch mid-session).
82
+ # Workspace sync belongs to agent.sh sync / the session-start path.
83
+ git -C "$SCRIPT_DIR" fetch origin --quiet 2>/dev/null || true
84
+
85
+ # Memory sync
86
+ if [ -d "$SCRIPT_DIR/memory/.git" ] || [ -L "$SCRIPT_DIR/memory" ]; then
87
+ git -C "$SCRIPT_DIR/memory" fetch origin main --quiet 2>/dev/null || true
88
+ LOCAL=$(git -C "$SCRIPT_DIR/memory" rev-parse HEAD 2>/dev/null || echo "")
89
+ REMOTE=$(git -C "$SCRIPT_DIR/memory" rev-parse origin/main 2>/dev/null || echo "")
90
+ if [ -n "$LOCAL" ] && [ -n "$REMOTE" ] && [ "$LOCAL" != "$REMOTE" ]; then
91
+ git -C "$SCRIPT_DIR/memory" pull origin main --quiet 2>/dev/null || true
92
+ fi
93
+ fi
94
+
95
+ # PRs
96
+ PRS=$(cd "$SCRIPT_DIR" && gh pr list --base develop --state open --json number,title,author 2>/dev/null || echo "[]")
97
+ echo "$PRS" > "$TMPDIR/prs.json"
98
+
99
+ # Disk cross-reference
100
+ MONTH=$(date +%Y-%m)
101
+ TODAY=$(date +%d)
102
+ YESTERDAY=$(date -v-1d +%d 2>/dev/null || date -d 'yesterday' +%d 2>/dev/null || echo "00")
103
+ HANDOFFS=$(ls -1 "$SCRIPT_DIR/memory/handoffs/$MONTH/" 2>/dev/null | grep "^${TODAY}-\|^${YESTERDAY}-" 2>/dev/null | head -10 || echo "")
104
+ echo "$HANDOFFS" > "$TMPDIR/disk_handoffs.txt"
105
+
106
+ DECISIONS=$(ls -1t "$SCRIPT_DIR/memory/knowledge/decisions/" 2>/dev/null | head -5 || echo "")
107
+ echo "$DECISIONS" > "$TMPDIR/disk_decisions.txt"
108
+ ) &
109
+ GIT_PID=$!
110
+
111
+ # Local sessions: parse memory files when graph is offline (parallel)
112
+ (
113
+ GH_LC=$(echo "$GH_USER" | tr '[:upper:]' '[:lower:]')
114
+ DISPLAY_LC=""
115
+ if [ -f "$SCRIPT_DIR/.egregore-state.json" ]; then
116
+ DISPLAY_LC=$(jq -r '.display_name // empty' "$SCRIPT_DIR/.egregore-state.json" 2>/dev/null | tr '[:upper:]' '[:lower:]')
117
+ fi
118
+
119
+ CUTOFF=$(date -v-14d +%Y-%m-%d 2>/dev/null || date -d '14 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01")
120
+ MY="[]"
121
+ TEAM="[]"
122
+
123
+ # Scan sessions, wraps, and handoffs
124
+ ALL_ENTRIES=""
125
+ for DIR in "$SCRIPT_DIR/memory/sessions" "$SCRIPT_DIR/memory/wraps" "$SCRIPT_DIR/memory/handoffs"; do
126
+ [ -d "$DIR" ] || continue
127
+ TYPE=$(basename "$DIR")
128
+ find -L "$DIR" -name '*.md' -not -name 'index*' -type f 2>/dev/null | xargs ls -t 2>/dev/null | head -20 | while read -r MFILE; do
129
+ [ -z "$MFILE" ] && continue
130
+ M_AUTH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Author\*\*:' | sed 's/^\*\*Author\*\*:[[:space:]]*//')
131
+ M_DATE=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Date\*\*:' | sed 's/^\*\*Date\*\*:[[:space:]]*//')
132
+ M_BRANCH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Branch\*\*:' | sed 's/^\*\*Branch\*\*:[[:space:]]*//')
133
+ M_DURATION=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Duration\*\*:' | sed 's/^\*\*Duration\*\*:[[:space:]]*//')
134
+ M_TOPIC=$(head -3 "$MFILE" 2>/dev/null | grep -m1 '^# ' | sed 's/^# [^:]*:[[:space:]]*//')
135
+ [ -z "$M_AUTH" ] && continue
136
+ # Date filter
137
+ M_DAY="${M_DATE%%T*}"
138
+ [ -n "$M_DAY" ] && [ "$M_DAY" \< "$CUTOFF" ] && continue
139
+ echo "${M_AUTH}|${M_DATE}|${M_BRANCH}|${M_TOPIC}|${M_DURATION}|${TYPE}"
140
+ done
141
+ done | jq -Rn --arg gh "$GH_LC" --arg dn "$DISPLAY_LC" '
142
+ [inputs | split("|") |
143
+ {author: .[0], date: .[1], branch: .[2], topic: .[3], duration: .[4], type: .[5]}
144
+ ] | {
145
+ my_sessions: [.[] | select((.author | ascii_downcase) == $gh or (.author | ascii_downcase) == $dn) | select($dn != "" or (.author | ascii_downcase) == $gh)],
146
+ team_sessions: [.[] | select((.author | ascii_downcase) != $gh and (if $dn != "" then (.author | ascii_downcase) != $dn else true end))]
147
+ }
148
+ ' 2>/dev/null > "$TMPDIR/local_sessions.json" || echo '{"my_sessions":[],"team_sessions":[]}' > "$TMPDIR/local_sessions.json"
149
+ ) &
150
+ LOCAL_PID=$!
151
+
152
+ # --- Wait for all ---
153
+ wait $API_PID $GIT_PID $LOCAL_PID 2>/dev/null || true
154
+
155
+ # --- Read results ---
156
+ PRS=$(cat "$TMPDIR/prs.json" 2>/dev/null || echo "[]")
157
+ echo "$PRS" | jq . >/dev/null 2>&1 || PRS="[]"
158
+
159
+ # Resolve PR author GitHub logins -> egregore display names. `gh pr list` returns
160
+ # the raw github login (e.g. "alice-gh"); without this it leaks into activity
161
+ # instead of the person's display name ("Alice"). Map via the graph when connected;
162
+ # fall back to the github profile name, then the login. Author becomes a string.
163
+ if [ -n "$PRS" ] && [ "$PRS" != "[]" ]; then
164
+ AUTHOR_MAP='{}'
165
+ if [ -n "$API_URL" ] && [ -n "$API_KEY" ]; then
166
+ MAP_RAW=$(bash "$SCRIPT_DIR/bin/graph.sh" query \
167
+ "MATCH (p:Person) WHERE p.github IS NOT NULL RETURN p.github AS gh, p.name AS name" 2>/dev/null)
168
+ AUTHOR_MAP=$(printf '%s' "$MAP_RAW" | jq -c \
169
+ 'reduce (.values[]?) as $v ({}; .[($v[0]|ascii_downcase)] = $v[1])' 2>/dev/null || echo '{}')
170
+ fi
171
+ PRS=$(printf '%s' "$PRS" | jq -c --argjson map "$AUTHOR_MAP" '
172
+ map(
173
+ (if (.author|type)=="object" then .author else {login: (.author|tostring), name: null} end) as $a
174
+ | .author = ([$map[(($a.login // "") | ascii_downcase)], $a.name, $a.login]
175
+ | map(select(. != null and . != "")) | first // "unknown")
176
+ )' 2>/dev/null || printf '%s' "$PRS")
177
+ fi
178
+ DISK_HANDOFFS=$(cat "$TMPDIR/disk_handoffs.txt" 2>/dev/null || echo "")
179
+ DISK_DECISIONS=$(cat "$TMPDIR/disk_decisions.txt" 2>/dev/null || echo "")
180
+ LOCAL_SESSIONS=$(cat "$TMPDIR/local_sessions.json" 2>/dev/null || echo '{"my_sessions":[],"team_sessions":[]}')
181
+ echo "$LOCAL_SESSIONS" | jq . >/dev/null 2>&1 || LOCAL_SESSIONS='{"my_sessions":[],"team_sessions":[]}'
182
+
183
+ handoff_metadata_map() {
184
+ local json="$1"
185
+
186
+ if ! declare -F eg_handoff_metadata_json >/dev/null 2>&1; then
187
+ echo "{}"
188
+ return
189
+ fi
190
+
191
+ printf '%s\n' "$json" | jq -r '
192
+ [(.handoffs_to_me[]?.filePath // empty), (.all_handoffs[]?.filePath // empty)]
193
+ | map(select(. != ""))
194
+ | unique[]
195
+ ' 2>/dev/null | while IFS= read -r rel; do
196
+ [ -z "$rel" ] && continue
197
+ file="$SCRIPT_DIR/memory/$rel"
198
+ [ -f "$file" ] || continue
199
+ eg_handoff_metadata_json "$file" | jq -c --arg rel "$rel" '{key:$rel, value:{author:.author, topic:.topic, date:.date}}'
200
+ done | jq -sc 'map({(.key): .value}) | add // {}' 2>/dev/null || echo "{}"
201
+ }
202
+
203
+ # --- Merge server response + local git/disk data ---
204
+ FINAL_JSON=$(jq -n \
205
+ --arg org "$ORG" \
206
+ --arg date "$DATE" \
207
+ --slurpfile activity "$TMPDIR/activity.json" \
208
+ --argjson prs "$PRS" \
209
+ --arg disk_handoffs "$DISK_HANDOFFS" \
210
+ --arg disk_decisions "$DISK_DECISIONS" \
211
+ --argjson local_sessions "$LOCAL_SESSIONS" \
212
+ '$activity[0] + {
213
+ org: $org,
214
+ date: $date,
215
+ prs: $prs,
216
+ disk: {handoffs: $disk_handoffs, decisions: $disk_decisions},
217
+ local_sessions: $local_sessions
218
+ }')
219
+
220
+ HANDOFF_META="$(handoff_metadata_map "$FINAL_JSON")"
221
+ [ -z "$HANDOFF_META" ] && HANDOFF_META="{}"
222
+
223
+ printf '%s\n' "$FINAL_JSON" | jq --argjson handoff_meta "$HANDOFF_META" '
224
+ def enrich_handoff_sender:
225
+ (.filePath // "") as $file
226
+ | if $file != "" and ($handoff_meta[$file] // null) != null then
227
+ ($handoff_meta[$file] // {}) as $meta
228
+ | .author = ($meta.author // .author)
229
+ | .from = ($meta.author // .from)
230
+ | .topic = (.topic // $meta.topic)
231
+ | .date = (.date // $meta.date)
232
+ else
233
+ .
234
+ end;
235
+
236
+ .handoffs_to_me = ((.handoffs_to_me // []) | map(enrich_handoff_sender))
237
+ | .all_handoffs = ((.all_handoffs // []) | map(enrich_handoff_sender))
238
+ '