create-egregore 0.19.5 → 0.19.7
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/assets/egregore-launcher.js +411 -25
- package/bin/cli.js +34 -20
- package/lib/local.js +21 -5
- package/lib/pi-runtime.js +186 -0
- package/lib/setup.js +56 -11
- package/lib/ui.js +1 -1
- package/package.json +7 -5
- package/runtime/codex/.codex/spec-manifest.json +1 -1
- package/runtime/codex/AGENTS.md +7 -2
- package/runtime/codex/bin/codex-render-spec.mjs +6 -1
- package/runtime/codex/bin/codex-session-start.sh +5 -59
- package/runtime/codex/bin/codex-skill-render.mjs +7 -5
- package/runtime/codex/bin/lib/context.sh +8 -1
- package/runtime/codex/bin/lib/greeting.sh +12 -108
- package/runtime/codex/bin/lib/metrics.sh +374 -0
- package/runtime/codex/bin/publish-artifact.sh +14 -0
- package/runtime/codex/bin/settings.sh +274 -0
- package/runtime/codex/manifest.json +2 -0
- package/runtime/pi/.codex/config.toml +15 -0
- package/runtime/pi/.codex/hooks/branch-guard.js +242 -0
- package/runtime/pi/.codex/hooks/search-hint.js +65 -0
- package/runtime/pi/.codex/hooks.json +30 -0
- package/runtime/pi/.codex/skills/activity/SKILL.md +70 -0
- package/runtime/pi/.codex/skills/add/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/announce/SKILL.md +54 -0
- package/runtime/pi/.codex/skills/answer/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/archive/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/ask/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/branch/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/checkup/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/commit/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/contribute/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dark-mode/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/deep-reflect/SKILL.md +74 -0
- package/runtime/pi/.codex/skills/delete-user/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/emissary/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/env/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/handoff/SKILL.md +67 -0
- package/runtime/pi/.codex/skills/harvest/SKILL.md +107 -0
- package/runtime/pi/.codex/skills/ingest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-google/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/invite/SKILL.md +40 -0
- package/runtime/pi/.codex/skills/issue/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/me/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/meeting/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/minion/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/note/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/onboarding/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pr/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/project/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pull/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/push/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/quest/SKILL.md +77 -0
- package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/reflect/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/review-pr/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/save/SKILL.md +62 -0
- package/runtime/pi/.codex/skills/scroll/SKILL.md +168 -0
- package/runtime/pi/.codex/skills/scroll/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/scroll/assets/shell.html +542 -0
- package/runtime/pi/.codex/skills/search/SKILL.md +56 -0
- package/runtime/pi/.codex/skills/session-view/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/setup/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/summon/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/sync-repos/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telemetry/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/test/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/pi/.codex/skills/thread/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/todo/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tui-design/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tutorial/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/update/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/view/SKILL.md +156 -0
- package/runtime/pi/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/pi/.codex/skills/visual-explain/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/wrap/SKILL.md +55 -0
- package/runtime/pi/.codex/spec-manifest.json +114 -0
- package/runtime/pi/.pi/APPEND_SYSTEM.md +255 -0
- package/runtime/pi/.pi/extensions/egregore.ts +324 -0
- package/runtime/pi/.pi/settings.json +6 -0
- package/runtime/pi/.pi/spec-manifest.json +12 -0
- package/runtime/pi/AGENTS.md +350 -0
- package/runtime/pi/bin/activity-data.sh +242 -0
- package/runtime/pi/bin/agent.sh +677 -0
- package/runtime/pi/bin/codex-install-skills.sh +78 -0
- package/runtime/pi/bin/codex-render-spec.mjs +394 -0
- package/runtime/pi/bin/codex-session-start.sh +188 -0
- package/runtime/pi/bin/codex-skill-render.mjs +323 -0
- package/runtime/pi/bin/codex-sync-skills.sh +227 -0
- package/runtime/pi/bin/dashboard-data.sh +178 -0
- package/runtime/pi/bin/graph-batch.sh +60 -0
- package/runtime/pi/bin/graph-op.sh +431 -0
- package/runtime/pi/bin/graph-wal.sh +228 -0
- package/runtime/pi/bin/graph.sh +177 -0
- package/runtime/pi/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/pi/bin/handoff-run.sh +581 -0
- package/runtime/pi/bin/handoff-save-egregore.sh +136 -0
- package/runtime/pi/bin/index-handoff.sh +312 -0
- package/runtime/pi/bin/lib/artifact-id.sh +46 -0
- package/runtime/pi/bin/lib/config.sh +71 -0
- package/runtime/pi/bin/lib/context.sh +542 -0
- package/runtime/pi/bin/lib/dashboard-artifact.sh +142 -0
- package/runtime/pi/bin/lib/ensure-develop.sh +183 -0
- package/runtime/pi/bin/lib/git-sync.sh +288 -0
- package/runtime/pi/bin/lib/greeting.sh +340 -0
- package/runtime/pi/bin/lib/hash.sh +13 -0
- package/runtime/pi/bin/lib/identity.sh +174 -0
- package/runtime/pi/bin/lib/metrics.sh +374 -0
- package/runtime/pi/bin/lib/permissions.sh +106 -0
- package/runtime/pi/bin/lib/time.sh +56 -0
- package/runtime/pi/bin/lib/worktree-links.sh +54 -0
- package/runtime/pi/bin/notify.sh +207 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +15 -0
- package/runtime/pi/bin/pi-product-workflows.mjs +324 -0
- package/runtime/pi/bin/pi-render-spec.mjs +114 -0
- package/runtime/pi/bin/pi-session-start.sh +24 -0
- package/runtime/pi/bin/publish-artifact.sh +201 -0
- package/runtime/pi/bin/publish-references.sh +144 -0
- package/runtime/pi/bin/repo-state.sh +99 -0
- package/runtime/pi/bin/telemetry.sh +391 -0
- package/runtime/pi/bin/worktree-create.sh +118 -0
- package/runtime/pi/bin/worktree-remove.sh +50 -0
- package/runtime/pi/bin/worktree.sh +198 -0
- package/runtime/pi/manifest.json +176 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# greeting.sh — Greeting output renderer for session-start.sh
|
|
3
|
+
#
|
|
4
|
+
# Renders the full session greeting:
|
|
5
|
+
# - ASCII art banner
|
|
6
|
+
# - Identity line (org/repo + user + branch)
|
|
7
|
+
# - Momentum board (sessions, commits, handoffs, knowledge)
|
|
8
|
+
# - Pending questions signal
|
|
9
|
+
# - Health footer
|
|
10
|
+
# - Alias migration
|
|
11
|
+
# - Session context JSON (hidden, for Claude)
|
|
12
|
+
# - Soul file inclusion
|
|
13
|
+
# - Telemetry emit
|
|
14
|
+
# - First session welcome
|
|
15
|
+
#
|
|
16
|
+
# Inputs: SCRIPT_DIR, STATE_FILE, CONFIG, CTX_DIR, BRANCH, COMMITS_AHEAD,
|
|
17
|
+
# AUTHOR, LOCAL_MODE, MEMORY_SYNCED, REPOS_STATUS, SAVED_BRANCH,
|
|
18
|
+
# HEALTH_*, FRAMEWORK_VERSION, TIME_OF_DAY, EGREGORE_SESSION_ID,
|
|
19
|
+
# FIRST_SESSION, DISPLAY_NAME_STATE, DASHBOARD_URL
|
|
20
|
+
|
|
21
|
+
# --- Output greeting for Claude to display ---
|
|
22
|
+
cat << 'GREETING'
|
|
23
|
+
|
|
24
|
+
███████╗ ██████╗ ██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗
|
|
25
|
+
██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝ ██╔═══██╗██╔══██╗██╔════╝
|
|
26
|
+
█████╗ ██║ ███╗██████╔╝█████╗ ██║ ███╗██║ ██║██████╔╝█████╗
|
|
27
|
+
██╔══╝ ██║ ██║██╔══██╗██╔══╝ ██║ ██║██║ ██║██╔══██╗██╔══╝
|
|
28
|
+
███████╗╚██████╔╝██║ ██║███████╗╚██████╔╝╚██████╔╝██║ ██║███████╗
|
|
29
|
+
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
|
|
30
|
+
|
|
31
|
+
GREETING
|
|
32
|
+
|
|
33
|
+
# --- Ornamented status ---
|
|
34
|
+
REPO_NAME=$(jq -r '.repo_name // "egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
35
|
+
GITHUB_ORG_DISPLAY=$(jq -r '.github_org // ""' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
36
|
+
ORG_NAME=$(jq -r '.org_name // ""' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
37
|
+
|
|
38
|
+
DISPLAY_NAME=""
|
|
39
|
+
if [ -f "$STATE_FILE" ]; then
|
|
40
|
+
DISPLAY_NAME=$(jq -r '.display_name // .name // empty' "$STATE_FILE" 2>/dev/null)
|
|
41
|
+
fi
|
|
42
|
+
GREETING_NAME="${DISPLAY_NAME:-$AUTHOR}"
|
|
43
|
+
|
|
44
|
+
# --- Line 1: Org/Repo + User + Branch (primary info) ---
|
|
45
|
+
SEPARATOR=" ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄"
|
|
46
|
+
|
|
47
|
+
# Build identity line: Org/repo on left, user + branch on right
|
|
48
|
+
if [ "$LOCAL_MODE" = "true" ]; then
|
|
49
|
+
IDENTITY_LEFT=" Egregore"
|
|
50
|
+
else
|
|
51
|
+
IDENTITY_LEFT=" ${GITHUB_ORG_DISPLAY}/${REPO_NAME}"
|
|
52
|
+
fi
|
|
53
|
+
BRANCH_COMPACT="$BRANCH"
|
|
54
|
+
if [ "$COMMITS_AHEAD" -gt 0 ] 2>/dev/null; then
|
|
55
|
+
BRANCH_COMPACT="${BRANCH} · ${COMMITS_AHEAD}↑"
|
|
56
|
+
fi
|
|
57
|
+
IDENTITY_RIGHT="${GREETING_NAME} · ${BRANCH_COMPACT}"
|
|
58
|
+
LINE_WIDTH=67
|
|
59
|
+
ID_LEFT_LEN=${#IDENTITY_LEFT}
|
|
60
|
+
ID_RIGHT_LEN=${#IDENTITY_RIGHT}
|
|
61
|
+
ID_PADDING=$((LINE_WIDTH - ID_LEFT_LEN - ID_RIGHT_LEN))
|
|
62
|
+
if [ "$ID_PADDING" -lt 1 ]; then ID_PADDING=1; fi
|
|
63
|
+
printf "\n%s%*s%s\n" "$IDENTITY_LEFT" "$ID_PADDING" "" "$IDENTITY_RIGHT"
|
|
64
|
+
echo "$SEPARATOR"
|
|
65
|
+
|
|
66
|
+
# --- Momentum board ---
|
|
67
|
+
source "$SCRIPT_DIR/bin/lib/metrics.sh"
|
|
68
|
+
_render_momentum_board
|
|
69
|
+
|
|
70
|
+
# Pending questions addressed to you (one summary line — /answer to engage)
|
|
71
|
+
PENDING_Q=$(cat "$CTX_DIR/pending_questions" 2>/dev/null || echo "[]")
|
|
72
|
+
PENDING_Q_COUNT=$(echo "$PENDING_Q" | jq 'length' 2>/dev/null || echo "0")
|
|
73
|
+
if [ "$PENDING_Q_COUNT" -gt 0 ] 2>/dev/null && [ "$PENDING_Q_COUNT" != "0" ]; then
|
|
74
|
+
PQ_SENDERS=$(echo "$PENDING_Q" | jq -r '[.[].from] | unique | join(", ")' 2>/dev/null)
|
|
75
|
+
if [ "$PENDING_Q_COUNT" = "1" ]; then
|
|
76
|
+
PQ_NOUN="question"
|
|
77
|
+
else
|
|
78
|
+
PQ_NOUN="questions"
|
|
79
|
+
fi
|
|
80
|
+
if [ -n "$PQ_SENDERS" ]; then
|
|
81
|
+
printf " ◐ %s pending %s from %s — /answer to engage\n" "$PENDING_Q_COUNT" "$PQ_NOUN" "$PQ_SENDERS"
|
|
82
|
+
else
|
|
83
|
+
printf " ◐ %s pending %s — /answer to engage\n" "$PENDING_Q_COUNT" "$PQ_NOUN"
|
|
84
|
+
fi
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# Show auto-save notice if work was committed from a previous branch
|
|
88
|
+
if [ -n "$SAVED_BRANCH" ]; then
|
|
89
|
+
echo " ✓ Auto-saved uncommitted work on $SAVED_BRANCH"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# --- Footer: health + repos + memory (tertiary) ---
|
|
93
|
+
echo "$SEPARATOR"
|
|
94
|
+
|
|
95
|
+
# Build compact footer line
|
|
96
|
+
if [ "$LOCAL_MODE" = "true" ]; then
|
|
97
|
+
# Local mode: only check github + git, skip api-key/graph/telegram
|
|
98
|
+
HAS_FAILURE="false"
|
|
99
|
+
FAILED_SERVICES=""
|
|
100
|
+
for pair in "github:$HEALTH_GITHUB" "git:$HEALTH_GIT"; do
|
|
101
|
+
svc="${pair%%:*}"
|
|
102
|
+
svc_status="${pair#*:}"
|
|
103
|
+
if [ "$svc_status" = "fail" ]; then
|
|
104
|
+
HAS_FAILURE="true"
|
|
105
|
+
FAILED_SERVICES="${FAILED_SERVICES} ${svc} ✗"
|
|
106
|
+
fi
|
|
107
|
+
done
|
|
108
|
+
|
|
109
|
+
if [ "$HAS_FAILURE" = "true" ]; then
|
|
110
|
+
echo " ⚠${FAILED_SERVICES} — run /checkup"
|
|
111
|
+
else
|
|
112
|
+
if [ "${FRAMEWORK_UPDATED:-false}" = "true" ]; then
|
|
113
|
+
printf " ◆ updated\n"
|
|
114
|
+
else
|
|
115
|
+
printf " ✓ ready\n"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Managed repos on separate line
|
|
119
|
+
if [ -n "$REPOS_STATUS" ]; then
|
|
120
|
+
REPOS_COMPACT=$(printf '%s' "$REPOS_STATUS" | sed 's/^ ◇ //;s/^[[:space:]]*//' | paste -sd' ' - | sed 's/[[:space:]]*$//')
|
|
121
|
+
if [ -n "$REPOS_COMPACT" ]; then
|
|
122
|
+
printf " %s\n" "$REPOS_COMPACT"
|
|
123
|
+
fi
|
|
124
|
+
fi
|
|
125
|
+
fi
|
|
126
|
+
else
|
|
127
|
+
# Connected mode: check all services
|
|
128
|
+
HAS_FAILURE="false"
|
|
129
|
+
FAILED_SERVICES=""
|
|
130
|
+
for pair in "github:$HEALTH_GITHUB" "git:$HEALTH_GIT" "api-key:$HEALTH_APIKEY" "graph:$HEALTH_GRAPH" "telegram:$HEALTH_TELEGRAM"; do
|
|
131
|
+
svc="${pair%%:*}"
|
|
132
|
+
svc_status="${pair#*:}"
|
|
133
|
+
if [ "$svc_status" = "fail" ]; then
|
|
134
|
+
HAS_FAILURE="true"
|
|
135
|
+
FAILED_SERVICES="${FAILED_SERVICES} ${svc} ✗"
|
|
136
|
+
fi
|
|
137
|
+
done
|
|
138
|
+
|
|
139
|
+
if [ "$HAS_FAILURE" = "true" ]; then
|
|
140
|
+
echo " ⚠${FAILED_SERVICES} — run /checkup"
|
|
141
|
+
else
|
|
142
|
+
# Compact footer: ready + memory on one line, repos on next if present
|
|
143
|
+
FOOTER_LEFT=" ✓ ready"
|
|
144
|
+
FOOTER_RIGHT=""
|
|
145
|
+
if [ "$MEMORY_SYNCED" = "true" ]; then
|
|
146
|
+
FOOTER_RIGHT="◆ memory synced"
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
FL_LEN=${#FOOTER_LEFT}
|
|
150
|
+
FR_LEN=${#FOOTER_RIGHT}
|
|
151
|
+
F_PAD=$((LINE_WIDTH - FL_LEN - FR_LEN))
|
|
152
|
+
if [ "$F_PAD" -lt 1 ]; then F_PAD=1; fi
|
|
153
|
+
printf "%s%*s%s\n" "$FOOTER_LEFT" "$F_PAD" "" "$FOOTER_RIGHT"
|
|
154
|
+
|
|
155
|
+
# Managed repos on separate line (avoids line overflow)
|
|
156
|
+
if [ -n "$REPOS_STATUS" ]; then
|
|
157
|
+
REPOS_COMPACT=$(printf '%s' "$REPOS_STATUS" | sed 's/^ ◇ //;s/^[[:space:]]*//' | paste -sd' ' - | sed 's/[[:space:]]*$//')
|
|
158
|
+
if [ -n "$REPOS_COMPACT" ]; then
|
|
159
|
+
printf " %s\n" "$REPOS_COMPACT"
|
|
160
|
+
fi
|
|
161
|
+
fi
|
|
162
|
+
fi
|
|
163
|
+
fi
|
|
164
|
+
|
|
165
|
+
# Dashboard link (OSC 8 hyperlink — clickable text in supported terminals)
|
|
166
|
+
if [ -n "${DASHBOARD_URL:-}" ]; then
|
|
167
|
+
printf " ◆ %s\n" "$DASHBOARD_URL"
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
if [ -n "${BOARD_URL:-}" ]; then
|
|
171
|
+
printf " ◆ %s (board)\n" "$BOARD_URL"
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
if [ -n "${LOOM_DOCTOR_BRIEF:-}" ]; then
|
|
175
|
+
printf " %s\n" "$LOOM_DOCTOR_BRIEF"
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# Framework updates come through PRs to develop — no separate auto-update channel.
|
|
179
|
+
# The develop sync above already keeps framework files current.
|
|
180
|
+
# Use /update for manual upstream pulls when needed.
|
|
181
|
+
|
|
182
|
+
# --- One-time migration: fix aliases to use 'claude "start"' ---
|
|
183
|
+
# v1: 'claude start' → 'claude' (cross-instance bug)
|
|
184
|
+
# v2: 'claude' → 'claude "start"' (blank prompt — auto-sends first message)
|
|
185
|
+
ALIAS_VERSION=$(jq -r '.alias_version // 0' "$STATE_FILE" 2>/dev/null || echo "0")
|
|
186
|
+
if [ "$ALIAS_VERSION" -lt 2 ] 2>/dev/null; then
|
|
187
|
+
for profile in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile"; do
|
|
188
|
+
if [ -f "$profile" ] && grep -q "$SCRIPT_DIR" "$profile" 2>/dev/null; then
|
|
189
|
+
# Replace any egregore alias pointing to this directory with the correct command
|
|
190
|
+
# Handles: && claude start, && claude, && claude "start" (idempotent)
|
|
191
|
+
sed -i.bak "s|&& claude start|\\&\\& claude \"start\"|g; s|&& claude'|\\&\\& claude \"start\"'|g" "$profile" 2>/dev/null && rm -f "${profile}.bak" || true
|
|
192
|
+
fi
|
|
193
|
+
done
|
|
194
|
+
if [ -f "$STATE_FILE" ] && jq . "$STATE_FILE" >/dev/null 2>&1; then
|
|
195
|
+
jq '. + {"alias_fixed": true, "alias_version": 2}' "$STATE_FILE" > "$STATE_FILE.tmp" && mv "$STATE_FILE.tmp" "$STATE_FILE"
|
|
196
|
+
fi
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
echo ""
|
|
200
|
+
|
|
201
|
+
# --- Session context (hidden, for Claude) ---
|
|
202
|
+
CONTEXT_HANDOFFS=$(cat "$CTX_DIR/handoffs" 2>/dev/null || echo "[]")
|
|
203
|
+
CONTEXT_ADDRESSED=$(cat "$CTX_DIR/addressed" 2>/dev/null || echo "[]")
|
|
204
|
+
CONTEXT_QUESTS=$(cat "$CTX_DIR/quests" 2>/dev/null || echo "[]")
|
|
205
|
+
CONTEXT_ACTIVITY=$(cat "$CTX_DIR/activity" 2>/dev/null || echo "")
|
|
206
|
+
CONTEXT_TEAM=$(cat "$CTX_DIR/team" 2>/dev/null || echo "[]")
|
|
207
|
+
CONTEXT_SOUL=$(cat "$CTX_DIR/soul_summary" 2>/dev/null || echo "")
|
|
208
|
+
CONTEXT_LIFECYCLE=$(cat "$CTX_DIR/lifecycle" 2>/dev/null || echo '{"merged_prs":[],"implemented_handoffs":[]}')
|
|
209
|
+
CONTEXT_PULSE=$(cat "$CTX_DIR/pulse_brief" 2>/dev/null || echo '{}')
|
|
210
|
+
if [ -f "$CTX_DIR/metrics" ]; then
|
|
211
|
+
CONTEXT_METRICS=$(jq -c . "$CTX_DIR/metrics" 2>/dev/null || echo "{}")
|
|
212
|
+
[ -n "$CONTEXT_METRICS" ] || CONTEXT_METRICS="{}"
|
|
213
|
+
else
|
|
214
|
+
CONTEXT_METRICS="{}"
|
|
215
|
+
fi
|
|
216
|
+
|
|
217
|
+
# --- Write compact subagent context cache (reuses already-gathered data) ---
|
|
218
|
+
SUBAGENT_CTX="/tmp/egregore-subagent-ctx-${EGREGORE_SESSION_ID}.txt"
|
|
219
|
+
(
|
|
220
|
+
SA_ORG_NAME=$(jq -r '.org_name // "Unknown"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "Unknown")
|
|
221
|
+
SA_GITHUB_ORG=$(jq -r '.github_org // "unknown"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "unknown")
|
|
222
|
+
|
|
223
|
+
# Format quests list
|
|
224
|
+
SA_QUESTS="none"
|
|
225
|
+
if [ "$CONTEXT_QUESTS" != "[]" ]; then
|
|
226
|
+
SA_QUESTS=$(echo "$CONTEXT_QUESTS" | jq -r '.[]' 2>/dev/null | paste -sd', ' - 2>/dev/null || echo "none")
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
# Format recent handoffs
|
|
230
|
+
SA_HANDOFFS="none"
|
|
231
|
+
if [ "$CONTEXT_HANDOFFS" != "[]" ]; then
|
|
232
|
+
SA_HANDOFFS=$(echo "$CONTEXT_HANDOFFS" | jq -r '.[] | .name' 2>/dev/null | head -5 | paste -sd', ' - 2>/dev/null || echo "none")
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
cat > "$SUBAGENT_CTX" << SAEOF
|
|
236
|
+
<!-- egregore-context
|
|
237
|
+
Organization: $SA_ORG_NAME (github: $SA_GITHUB_ORG)
|
|
238
|
+
Session: $BRANCH — ${EGREGORE_SESSION_ID}
|
|
239
|
+
Active quests: $SA_QUESTS
|
|
240
|
+
Recent handoffs: $SA_HANDOFFS
|
|
241
|
+
Memory: memory/ is a symlink to shared knowledge base. Use bin/graph.sh for Neo4j queries.
|
|
242
|
+
-->
|
|
243
|
+
SAEOF
|
|
244
|
+
) 2>/dev/null || true
|
|
245
|
+
|
|
246
|
+
cat << CTXEOF
|
|
247
|
+
|
|
248
|
+
<!-- session-context
|
|
249
|
+
{
|
|
250
|
+
"framework_version": "$FRAMEWORK_VERSION",
|
|
251
|
+
"time_of_day": "$TIME_OF_DAY",
|
|
252
|
+
"dashboard_url": "${DASHBOARD_URL:-}",
|
|
253
|
+
"recent_handoffs": $CONTEXT_HANDOFFS,
|
|
254
|
+
"addressed_to_user": $CONTEXT_ADDRESSED,
|
|
255
|
+
"quests": $CONTEXT_QUESTS,
|
|
256
|
+
"last_user_activity": "$CONTEXT_ACTIVITY",
|
|
257
|
+
"team_recent_memory": $CONTEXT_TEAM,
|
|
258
|
+
"soul_self_summary": "$CONTEXT_SOUL",
|
|
259
|
+
"lifecycle": $CONTEXT_LIFECYCLE,
|
|
260
|
+
"momentum": $CONTEXT_METRICS,
|
|
261
|
+
"pulse": $CONTEXT_PULSE
|
|
262
|
+
}
|
|
263
|
+
-->
|
|
264
|
+
CTXEOF
|
|
265
|
+
|
|
266
|
+
# Include soul file if present
|
|
267
|
+
if [ -f "$SCRIPT_DIR/egregore.md" ]; then
|
|
268
|
+
echo ""
|
|
269
|
+
echo "<!-- egregore-soul"
|
|
270
|
+
cat "$SCRIPT_DIR/egregore.md"
|
|
271
|
+
echo "-->"
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
# Include latest soul reflection if present
|
|
275
|
+
if [ -d "$SCRIPT_DIR/memory/soul" ]; then
|
|
276
|
+
LATEST_REFLECTION=$(ls -t "$SCRIPT_DIR/memory/soul/"*.md 2>/dev/null | head -1 || true)
|
|
277
|
+
if [ -n "$LATEST_REFLECTION" ]; then
|
|
278
|
+
echo "<!-- latest-reflection"
|
|
279
|
+
cat "$LATEST_REFLECTION"
|
|
280
|
+
echo "-->"
|
|
281
|
+
fi
|
|
282
|
+
fi
|
|
283
|
+
|
|
284
|
+
# --- Flush leftover telemetry from previous session (background) ---
|
|
285
|
+
# If the previous session exited without a clean flush (terminal closed,
|
|
286
|
+
# crash, kill -9), events are still in the local buffer. Drain them now.
|
|
287
|
+
bash "$SCRIPT_DIR/bin/telemetry.sh" flush 2>/dev/null &
|
|
288
|
+
|
|
289
|
+
# --- Emit session_start telemetry (background, non-blocking) ---
|
|
290
|
+
bash "$SCRIPT_DIR/bin/telemetry.sh" emit "session_start" \
|
|
291
|
+
"$(jq -n --arg branch "$BRANCH" '{branch: $branch}')" 2>/dev/null &
|
|
292
|
+
|
|
293
|
+
# --- Health check-in (background, non-blocking) ---
|
|
294
|
+
bash "$SCRIPT_DIR/bin/startup-check.sh" >/dev/null 2>&1 &
|
|
295
|
+
|
|
296
|
+
# --- Warm npx cache for egregore-artifacts (background, throttled) ---
|
|
297
|
+
# publish-artifact.sh spawns `npx egregore-artifacts` — first run in a
|
|
298
|
+
# fresh npx cache pays a 5-10s npm download. Warmup is throttled to
|
|
299
|
+
# once per hour via a marker file so we don't storm npm when a user
|
|
300
|
+
# opens many tabs, and don't start runaway retry loops when offline.
|
|
301
|
+
_WARM_TS_FILE="$HOME/.cache/egregore/npx-warm-ts"
|
|
302
|
+
mkdir -p "$(dirname "$_WARM_TS_FILE")" 2>/dev/null
|
|
303
|
+
_WARM_LAST=$(cat "$_WARM_TS_FILE" 2>/dev/null || echo 0)
|
|
304
|
+
_WARM_NOW=$(date +%s)
|
|
305
|
+
if [ $(( _WARM_NOW - _WARM_LAST )) -gt 3600 ]; then
|
|
306
|
+
(npx -y egregore-artifacts@latest --help >/dev/null 2>&1 \
|
|
307
|
+
&& echo "$_WARM_NOW" > "$_WARM_TS_FILE" &) >/dev/null 2>&1
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
# Clean up temp files
|
|
311
|
+
rm -rf "$CTX_DIR"
|
|
312
|
+
|
|
313
|
+
# --- First session welcome ---
|
|
314
|
+
if [ -z "$FIRST_SESSION" ] && [ -f "$STATE_FILE" ]; then
|
|
315
|
+
FIRST_SESSION=$(jq -r '.first_session // false' "$STATE_FILE" 2>/dev/null)
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
if [ "$FIRST_SESSION" = "true" ]; then
|
|
319
|
+
echo ""
|
|
320
|
+
echo " Welcome! This is your first session."
|
|
321
|
+
echo ""
|
|
322
|
+
echo "IMPORTANT: Display the above greeting exactly as-is (ASCII art + ornamented status). Then ask the user if they'd like a quick onboarding tour (run /onboarding), or if they want to jump straight in."
|
|
323
|
+
# Clear the flag so it only shows once
|
|
324
|
+
jq '.first_session = false' "$STATE_FILE" > "$STATE_FILE.tmp" && mv "$STATE_FILE.tmp" "$STATE_FILE"
|
|
325
|
+
else
|
|
326
|
+
# --- Tutorial tip (if onboarding done but tutorial not) ---
|
|
327
|
+
TUTORIAL_COMPLETE="true"
|
|
328
|
+
if [ -f "$STATE_FILE" ]; then
|
|
329
|
+
TUTORIAL_COMPLETE=$(jq -r '.tutorial_complete // false' "$STATE_FILE" 2>/dev/null || echo "true")
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
if [ "$TUTORIAL_COMPLETE" != "true" ]; then
|
|
333
|
+
echo " Tip: Run /tutorial to learn the core loop."
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
echo ""
|
|
337
|
+
echo "IMPORTANT: Display the above greeting to the user exactly as-is (preserve the ASCII art formatting and ornamented status) on their first message. Then ask: What are you working on?"
|
|
338
|
+
echo ""
|
|
339
|
+
echo "BRANCH RULE: When the user responds with what they're working on, your FIRST action is to create a working branch: git fetch origin develop --quiet && git checkout -b dev/{author}/{topic-slug} origin/develop. Do this BEFORE any other work. Derive the topic slug from their description. If they ask a pure question with no work intent, skip branching."
|
|
340
|
+
fi
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cross-platform hash helpers — sourced by scripts that need hashing.
|
|
3
|
+
|
|
4
|
+
# Compute MD5 hash of a string (macOS + Linux compatible)
|
|
5
|
+
_md5() {
|
|
6
|
+
local input="$1"
|
|
7
|
+
echo -n "$input" | md5 2>/dev/null || echo -n "$input" | md5sum 2>/dev/null | cut -d' ' -f1
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
# Compute project hash (used for per-instance file isolation)
|
|
11
|
+
_proj_hash() {
|
|
12
|
+
_md5 "${SCRIPT_DIR:-$PWD}"
|
|
13
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# identity.sh — User identity resolution for session-start.sh
|
|
3
|
+
#
|
|
4
|
+
# Resolves the current user's identity through multiple fallback layers:
|
|
5
|
+
# 1. .egregore-state.json github_username (stored during setup)
|
|
6
|
+
# 2. GitHub API auto-detect via GITHUB_TOKEN
|
|
7
|
+
# 3. Graph person lookup (existing team member on new machine)
|
|
8
|
+
# 4. Global git config user.name (last resort)
|
|
9
|
+
#
|
|
10
|
+
# Inputs: STATE_FILE, ENV_FILE, SCRIPT_DIR, HEALTH_GITHUB
|
|
11
|
+
# Outputs: AUTHOR, DISPLAY_NAME_STATE, FIRST_SESSION, HEALTH_GITHUB,
|
|
12
|
+
# EGREGORE_USER, EGREGORE_ORG, EGREGORE_SESSION_ID
|
|
13
|
+
# Writes .egregore-session-id and ~/.egregore/session-*.id
|
|
14
|
+
|
|
15
|
+
STORED_USERNAME=""
|
|
16
|
+
FIRST_SESSION=""
|
|
17
|
+
AUTHOR=""
|
|
18
|
+
if [ -f "$STATE_FILE" ]; then
|
|
19
|
+
STORED_USERNAME=$(jq -r '.github_username // empty' "$STATE_FILE" 2>/dev/null)
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
DISPLAY_NAME_STATE=""
|
|
23
|
+
if [ -f "$STATE_FILE" ]; then
|
|
24
|
+
DISPLAY_NAME_STATE=$(jq -r '.display_name // empty' "$STATE_FILE" 2>/dev/null)
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
if [ -n "$STORED_USERNAME" ]; then
|
|
28
|
+
# Identity stored during setup — use it and ensure repo-local git config matches
|
|
29
|
+
AUTHOR="$STORED_USERNAME"
|
|
30
|
+
HEALTH_GITHUB="ok"
|
|
31
|
+
CURRENT_LOCAL=$(git config --local user.name 2>/dev/null || echo "")
|
|
32
|
+
if [ "$CURRENT_LOCAL" != "$STORED_USERNAME" ]; then
|
|
33
|
+
STORED_NAME=$(jq -r '.github_name // empty' "$STATE_FILE" 2>/dev/null)
|
|
34
|
+
git config user.name "${STORED_NAME:-$STORED_USERNAME}" 2>/dev/null || true
|
|
35
|
+
git config user.email "${STORED_USERNAME}@users.noreply.github.com" 2>/dev/null || true
|
|
36
|
+
fi
|
|
37
|
+
else
|
|
38
|
+
# No stored identity — try GitHub API to auto-detect (self-healing for pre-fix installs)
|
|
39
|
+
if [ -f "$ENV_FILE" ]; then
|
|
40
|
+
GH_TOKEN=$(grep '^GITHUB_TOKEN=' "$ENV_FILE" 2>/dev/null | cut -d'=' -f2-)
|
|
41
|
+
if [ -n "$GH_TOKEN" ]; then
|
|
42
|
+
GH_USER_JSON=$(curl -s -H "Authorization: token $GH_TOKEN" https://api.github.com/user --max-time 5 2>/dev/null || echo "")
|
|
43
|
+
GH_LOGIN=$(echo "$GH_USER_JSON" | jq -r '.login // empty' 2>/dev/null)
|
|
44
|
+
GH_NAME=$(echo "$GH_USER_JSON" | jq -r '.name // empty' 2>/dev/null)
|
|
45
|
+
if [ -n "$GH_LOGIN" ]; then
|
|
46
|
+
AUTHOR="$GH_LOGIN"
|
|
47
|
+
HEALTH_GITHUB="ok"
|
|
48
|
+
# Set repo-local config and save to state for next time
|
|
49
|
+
git config user.name "${GH_NAME:-$GH_LOGIN}" 2>/dev/null || true
|
|
50
|
+
git config user.email "${GH_LOGIN}@users.noreply.github.com" 2>/dev/null || true
|
|
51
|
+
# Save to state file so we don't need API call next time
|
|
52
|
+
# Include onboarding_complete + name so it doesn't re-trigger onboarding
|
|
53
|
+
# Determine if founder or joiner: if github_username != github_org, they're a joiner
|
|
54
|
+
GITHUB_ORG_CFG=$(jq -r '.github_org // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
55
|
+
if [ -n "$GITHUB_ORG_CFG" ] && [ "$GH_LOGIN" != "$GITHUB_ORG_CFG" ]; then
|
|
56
|
+
USAGE_TYPE="joiner_group"
|
|
57
|
+
else
|
|
58
|
+
USAGE_TYPE="founder_group"
|
|
59
|
+
fi
|
|
60
|
+
if [ -f "$STATE_FILE" ]; then
|
|
61
|
+
# Existing state file — update identity but preserve onboarding status
|
|
62
|
+
HAS_ONBOARDING=$(jq -r '.onboarding_complete // "unset"' "$STATE_FILE" 2>/dev/null)
|
|
63
|
+
if [ "$HAS_ONBOARDING" = "unset" ]; then
|
|
64
|
+
# State file exists but no onboarding flag — set to false to trigger it
|
|
65
|
+
jq --arg u "$GH_LOGIN" --arg n "${GH_NAME:-$GH_LOGIN}" --arg ut "$USAGE_TYPE" \
|
|
66
|
+
'.github_username = $u | .github_name = $n | .name = $n | .onboarding_complete = false | .usage_type = $ut' "$STATE_FILE" > "$STATE_FILE.tmp" \
|
|
67
|
+
&& mv "$STATE_FILE.tmp" "$STATE_FILE"
|
|
68
|
+
else
|
|
69
|
+
jq --arg u "$GH_LOGIN" --arg n "${GH_NAME:-$GH_LOGIN}" --arg ut "$USAGE_TYPE" \
|
|
70
|
+
'.github_username = $u | .github_name = $n | .name = $n | .usage_type = $ut' "$STATE_FILE" > "$STATE_FILE.tmp" \
|
|
71
|
+
&& mv "$STATE_FILE.tmp" "$STATE_FILE"
|
|
72
|
+
fi
|
|
73
|
+
FIRST_SESSION="false"
|
|
74
|
+
else
|
|
75
|
+
# No state file — check graph to see if this person already exists
|
|
76
|
+
# (handles fresh clone / new machine for existing team members)
|
|
77
|
+
GRAPH_PERSON=""
|
|
78
|
+
GRAPH_DISPLAY_NAME=""
|
|
79
|
+
GRAPH_PERSON=$(bash "$SCRIPT_DIR/bin/graph.sh" query \
|
|
80
|
+
"MATCH (p:Person {github: \$github}) RETURN p.name AS name" \
|
|
81
|
+
"$(jq -n --arg github "$GH_LOGIN" '{github: $github}')" 2>/dev/null || echo "")
|
|
82
|
+
if echo "$GRAPH_PERSON" | jq -e '.values | length > 0' &>/dev/null; then
|
|
83
|
+
GRAPH_DISPLAY_NAME=$(echo "$GRAPH_PERSON" | jq -r '.values[0][0] // empty' 2>/dev/null)
|
|
84
|
+
# Existing team member — skip onboarding
|
|
85
|
+
cat > "$STATE_FILE" << STATEEOF
|
|
86
|
+
{
|
|
87
|
+
"github_username": "$GH_LOGIN",
|
|
88
|
+
"github_name": "${GH_NAME:-$GH_LOGIN}",
|
|
89
|
+
"name": "${GRAPH_DISPLAY_NAME:-${GH_NAME:-$GH_LOGIN}}",
|
|
90
|
+
"display_name": "${GRAPH_DISPLAY_NAME:-}",
|
|
91
|
+
"onboarding_complete": true,
|
|
92
|
+
"usage_type": "$USAGE_TYPE",
|
|
93
|
+
"session_tracking": true,
|
|
94
|
+
"transcript_sharing": true,
|
|
95
|
+
"telemetry": true,
|
|
96
|
+
"contact_preference": "all",
|
|
97
|
+
"telemetry_noticed": true
|
|
98
|
+
}
|
|
99
|
+
STATEEOF
|
|
100
|
+
FIRST_SESSION="false"
|
|
101
|
+
else
|
|
102
|
+
# Genuinely new user — trigger onboarding
|
|
103
|
+
cat > "$STATE_FILE" << STATEEOF
|
|
104
|
+
{
|
|
105
|
+
"github_username": "$GH_LOGIN",
|
|
106
|
+
"github_name": "${GH_NAME:-$GH_LOGIN}",
|
|
107
|
+
"name": "${GH_NAME:-$GH_LOGIN}",
|
|
108
|
+
"onboarding_complete": false,
|
|
109
|
+
"usage_type": "$USAGE_TYPE",
|
|
110
|
+
"first_session": true
|
|
111
|
+
}
|
|
112
|
+
STATEEOF
|
|
113
|
+
FIRST_SESSION="true"
|
|
114
|
+
fi
|
|
115
|
+
fi
|
|
116
|
+
fi
|
|
117
|
+
fi
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
# Final fallback: git config user.name (global or local)
|
|
121
|
+
if [ -z "$AUTHOR" ]; then
|
|
122
|
+
FULLNAME=$(git config user.name 2>/dev/null || echo "")
|
|
123
|
+
AUTHOR=$(echo "$FULLNAME" | tr '[:upper:]' '[:lower:]' | cut -d' ' -f1)
|
|
124
|
+
fi
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
if [ -z "$AUTHOR" ]; then
|
|
128
|
+
AUTHOR="unknown"
|
|
129
|
+
HEALTH_GITHUB="fail"
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
# --- Validate gh CLI identity matches git identity ---
|
|
133
|
+
# The gh CLI has its own auth (keyring) separate from .env GITHUB_TOKEN.
|
|
134
|
+
# If they diverge, PRs get created under the wrong account.
|
|
135
|
+
if command -v gh &>/dev/null; then
|
|
136
|
+
GH_CLI_USER=$(gh api user --jq '.login' 2>/dev/null || true)
|
|
137
|
+
if [ -n "$GH_CLI_USER" ] && [ -n "$AUTHOR" ] && [ "$AUTHOR" != "unknown" ]; then
|
|
138
|
+
AUTHOR_LC=$(echo "$AUTHOR" | tr '[:upper:]' '[:lower:]')
|
|
139
|
+
GH_CLI_LC=$(echo "$GH_CLI_USER" | tr '[:upper:]' '[:lower:]')
|
|
140
|
+
if [ "$AUTHOR_LC" != "$GH_CLI_LC" ]; then
|
|
141
|
+
echo ""
|
|
142
|
+
echo "WARNING: Identity mismatch detected."
|
|
143
|
+
echo " Git identity (.env): $AUTHOR"
|
|
144
|
+
echo " gh CLI (active): $GH_CLI_USER"
|
|
145
|
+
echo " PRs will be created as '$GH_CLI_USER', not '$AUTHOR'."
|
|
146
|
+
echo " Fix: gh auth switch --user $AUTHOR"
|
|
147
|
+
echo ""
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# --- Export telemetry identity env vars ---
|
|
153
|
+
export EGREGORE_USER="$AUTHOR"
|
|
154
|
+
export EGREGORE_ORG="$(jq -r '.slug // .github_org // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null || true)"
|
|
155
|
+
export EGREGORE_SESSION_ID="$(date -u +%Y%m%dT%H%M%S)-${AUTHOR}-$$"
|
|
156
|
+
|
|
157
|
+
# Persist session ID to file so telemetry.sh can read it
|
|
158
|
+
# (env vars from hooks don't propagate into the Claude Code agent)
|
|
159
|
+
SESSION_ID_DIR="$HOME/.egregore"
|
|
160
|
+
mkdir -p "$SESSION_ID_DIR"
|
|
161
|
+
PROJ_HASH=$(echo -n "$SCRIPT_DIR" | md5 2>/dev/null || echo -n "$SCRIPT_DIR" | md5sum 2>/dev/null | cut -d' ' -f1)
|
|
162
|
+
echo "$EGREGORE_SESSION_ID" > "$SESSION_ID_DIR/session-${PROJ_HASH}.id"
|
|
163
|
+
# Also write project-local file (CLAUDE.md reads this — no glob needed)
|
|
164
|
+
echo "$EGREGORE_SESSION_ID" > "$SCRIPT_DIR/.egregore-session-id"
|
|
165
|
+
|
|
166
|
+
# Model stamp hashes the git common-dir root because telemetry.sh resolves it that way.
|
|
167
|
+
MODEL_REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir 2>/dev/null | sed 's|/\.git$||') || MODEL_REPO_ROOT="$SCRIPT_DIR"
|
|
168
|
+
MODEL_PROJ_HASH=$(echo -n "$MODEL_REPO_ROOT" | md5 2>/dev/null || echo -n "$MODEL_REPO_ROOT" | md5sum 2>/dev/null | cut -d' ' -f1)
|
|
169
|
+
MODEL_STAMP_FILE="$SESSION_ID_DIR/session-model-${MODEL_PROJ_HASH}"
|
|
170
|
+
if [ -n "${CLAUDE_MODEL:-}" ]; then
|
|
171
|
+
echo "$CLAUDE_MODEL" > "$MODEL_STAMP_FILE"
|
|
172
|
+
else
|
|
173
|
+
rm -f "$MODEL_STAMP_FILE"
|
|
174
|
+
fi
|