create-egregore 0.19.3 → 0.19.5
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 +3 -1
- package/lib/local.js +63 -6
- package/package.json +2 -2
- package/runtime/codex/.codex/hooks/search-hint.js +65 -0
- package/runtime/codex/.codex/hooks.json +13 -0
- package/runtime/codex/.codex/skills/deep-reflect/SKILL.md +14 -10
- package/runtime/codex/.codex/skills/minion/SKILL.md +25 -0
- package/runtime/codex/.codex/skills/scroll/SKILL.md +168 -0
- package/runtime/codex/.codex/skills/scroll/agents/openai.yaml +4 -0
- package/runtime/codex/.codex/skills/scroll/assets/shell.html +542 -0
- package/runtime/codex/.codex/skills/search/SKILL.md +56 -0
- package/runtime/codex/.codex/skills/session-view/SKILL.md +25 -0
- package/runtime/codex/.codex/skills/thread/SKILL.md +25 -0
- package/runtime/codex/.codex/skills/view/SKILL.md +147 -32
- package/runtime/codex/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/codex/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/codex/.codex/spec-manifest.json +3 -3
- package/runtime/codex/AGENTS.md +24 -3
- package/runtime/codex/bin/activity-data.sh +46 -4
- package/runtime/codex/bin/agent.sh +10 -2
- package/runtime/codex/bin/codex-install-skills.sh +1 -1
- package/runtime/codex/bin/codex-render-spec.mjs +18 -1
- package/runtime/codex/bin/codex-session-start.sh +1 -1
- package/runtime/codex/bin/codex-skill-render.mjs +13 -7
- package/runtime/codex/bin/codex-sync-skills.sh +4 -0
- package/runtime/codex/bin/graph-op.sh +56 -5
- package/runtime/codex/bin/graph.sh +36 -0
- package/runtime/codex/bin/handoff-run.sh +157 -7
- package/runtime/codex/bin/handoff-save-egregore.sh +6 -1
- package/runtime/codex/bin/index-handoff.sh +9 -3
- package/runtime/codex/bin/lib/context.sh +89 -17
- package/runtime/codex/bin/lib/dashboard-artifact.sh +1 -1
- package/runtime/codex/bin/lib/git-sync.sh +35 -9
- package/runtime/codex/bin/lib/greeting.sh +25 -3
- package/runtime/codex/bin/publish-artifact.sh +29 -1
- package/runtime/codex/manifest.json +16 -1
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
|
|
24
24
|
CTX_DIR=$(mktemp -d)
|
|
25
25
|
|
|
26
|
+
source "$SCRIPT_DIR/bin/lib/handoff-meta.sh" >/dev/null 2>/dev/null || true
|
|
27
|
+
|
|
26
28
|
# Time of day
|
|
27
29
|
HOUR=$(date +%H)
|
|
28
30
|
if [ "$HOUR" -lt 12 ]; then TIME_OF_DAY="morning"
|
|
@@ -177,6 +179,31 @@ fi
|
|
|
177
179
|
)
|
|
178
180
|
fi
|
|
179
181
|
|
|
182
|
+
# --- "Working on": latest session/handoff/wrap topic per person (file-based) ---
|
|
183
|
+
# Gives every team surface (greeting "around", dashboard) something legible in
|
|
184
|
+
# local mode, where git branches are usually empty for teammates.
|
|
185
|
+
_WM_TAB=$(printf '\t')
|
|
186
|
+
WORK_MAP=$(
|
|
187
|
+
{
|
|
188
|
+
for DIR in "$SCRIPT_DIR/memory/sessions" "$SCRIPT_DIR/memory/handoffs" "$SCRIPT_DIR/memory/wraps"; do
|
|
189
|
+
[ -d "$DIR" ] || continue
|
|
190
|
+
find -L "$DIR" -name '*.md' -not -name 'index*' -type f 2>/dev/null | xargs ls -t 2>/dev/null | head -30 | while read -r WFILE; do
|
|
191
|
+
[ -z "$WFILE" ] && continue
|
|
192
|
+
W_AUTH=$(grep -m1 '^\*\*Author\*\*:' "$WFILE" 2>/dev/null | sed 's/^\*\*Author\*\*:[[:space:]]*//')
|
|
193
|
+
W_DATE=$(grep -m1 '^\*\*Date\*\*:' "$WFILE" 2>/dev/null | sed 's/^\*\*Date\*\*:[[:space:]]*//')
|
|
194
|
+
W_TOPIC=$(grep -m1 '^# ' "$WFILE" 2>/dev/null | sed 's/^#[[:space:]]*//; s/^Session:[[:space:]]*//; s/^Handoff:[[:space:]]*//; s/^Wrap:[[:space:]]*//')
|
|
195
|
+
[ -z "$W_AUTH" ] && continue
|
|
196
|
+
[ -z "$W_TOPIC" ] && continue
|
|
197
|
+
printf '%s%s%s%s%s\n' "$W_AUTH" "$_WM_TAB" "$W_DATE" "$_WM_TAB" "$W_TOPIC"
|
|
198
|
+
done
|
|
199
|
+
done
|
|
200
|
+
} | sort -t"$_WM_TAB" -k1,1 -k2,2r | sort -t"$_WM_TAB" -k1,1 -u | while IFS="$_WM_TAB" read -r WM_NAME WM_DATE WM_TOPIC; do
|
|
201
|
+
[ -z "$WM_NAME" ] && continue
|
|
202
|
+
WM_LC=$(echo "$WM_NAME" | tr '[:upper:]' '[:lower:]')
|
|
203
|
+
printf '%s%s%s\n' "$WM_LC" "$_WM_TAB" "$WM_TOPIC"
|
|
204
|
+
done | jq -Rn --arg tab "$_WM_TAB" '[inputs | split($tab) | select(length>=2) | {(.[0]): (.[1] // "")}] | add // {}' 2>/dev/null || echo "{}"
|
|
205
|
+
)
|
|
206
|
+
|
|
180
207
|
# --- Relative time + epoch helpers (cross-platform) ---
|
|
181
208
|
NOW_EPOCH=$(date +%s)
|
|
182
209
|
|
|
@@ -270,8 +297,9 @@ fi
|
|
|
270
297
|
BRANCHES_JSON=$(echo "$BRANCHES_JSON" | jq --arg e "+${EXTRA} more" '[.[0:2][], $e]' 2>/dev/null || echo "$BRANCHES_JSON")
|
|
271
298
|
fi
|
|
272
299
|
|
|
273
|
-
|
|
274
|
-
|
|
300
|
+
WORK=$(echo "$WORK_MAP" | jq -r --arg n "$PNAME" '.[$n] // ""' 2>/dev/null)
|
|
301
|
+
ENTRY=$(jq -n --arg name "$PNAME" --arg seen "$LAST_SEEN_REL" --argjson sort "$LAST_SEEN_EPOCH" --argjson branches "$BRANCHES_JSON" --arg work "$WORK" \
|
|
302
|
+
'{name: $name, last_seen: $seen, last_seen_sort: $sort, branches: $branches, working_on: $work}')
|
|
275
303
|
$FIRST || PRESENCE="$PRESENCE,"
|
|
276
304
|
PRESENCE="$PRESENCE$ENTRY"
|
|
277
305
|
FIRST=false
|
|
@@ -320,18 +348,9 @@ fi
|
|
|
320
348
|
for AF in $ADDRESSED; do
|
|
321
349
|
[ -z "$AF" ] && continue
|
|
322
350
|
AF_NAME=$(basename "$AF" .md)
|
|
323
|
-
AF_AUTHOR=$(
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
fi
|
|
327
|
-
AF_TOPIC=$(sed -n 's/^# Handoff: *//p' "$AF" 2>/dev/null | head -1)
|
|
328
|
-
if [ -z "$AF_TOPIC" ]; then
|
|
329
|
-
AF_TOPIC=$(sed -n 's/^# *//p' "$AF" 2>/dev/null | head -1)
|
|
330
|
-
fi
|
|
331
|
-
AF_DATE=$(sed -n 's/^\*\*Date\*\*: *//p' "$AF" 2>/dev/null | head -1)
|
|
332
|
-
if [ -z "$AF_DATE" ]; then
|
|
333
|
-
AF_DATE=$(sed -n 's/^Date: *//p' "$AF" 2>/dev/null | head -1)
|
|
334
|
-
fi
|
|
351
|
+
AF_AUTHOR=$(eg_handoff_author "$AF")
|
|
352
|
+
AF_TOPIC=$(eg_handoff_topic "$AF")
|
|
353
|
+
AF_DATE=$(eg_handoff_date "$AF")
|
|
335
354
|
# Extract repo state table if present
|
|
336
355
|
AF_REPO_STATE="[]"
|
|
337
356
|
AF_REPO_TABLE=$(awk '/^## Repo State/{found=1; next} found && /^#/{exit} found && /^\|[^-]/ && !/^\| Repo/{print}' "$AF" 2>/dev/null || true)
|
|
@@ -352,9 +371,14 @@ fi
|
|
|
352
371
|
$FIRST || JSON="$JSON,"
|
|
353
372
|
$FIRST || RICH="$RICH,"
|
|
354
373
|
JSON="$JSON\"$AF_NAME\""
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
374
|
+
AF_ENTRY=$(jq -cn \
|
|
375
|
+
--arg name "$AF_NAME" \
|
|
376
|
+
--arg author "$AF_AUTHOR" \
|
|
377
|
+
--arg topic "$AF_TOPIC" \
|
|
378
|
+
--arg date "$AF_DATE" \
|
|
379
|
+
--argjson repoState "$AF_REPO_STATE" \
|
|
380
|
+
'{name:$name, author:$author, topic:$topic, date:$date, repoState:$repoState}' 2>/dev/null || echo "{}")
|
|
381
|
+
RICH="$RICH$AF_ENTRY"
|
|
358
382
|
FIRST=false
|
|
359
383
|
done
|
|
360
384
|
JSON="$JSON]"
|
|
@@ -364,6 +388,54 @@ fi
|
|
|
364
388
|
echo "$RICH" > "$CTX_DIR/addressed_rich"
|
|
365
389
|
) &
|
|
366
390
|
|
|
391
|
+
# 6.5. Pending questions addressed to user (background)
|
|
392
|
+
(
|
|
393
|
+
PENDING_JSON="[]"
|
|
394
|
+
QDIR="$SCRIPT_DIR/memory/knowledge/questions"
|
|
395
|
+
if [ -d "$QDIR" ]; then
|
|
396
|
+
# Match against the same identity variants used for handoffs (display name,
|
|
397
|
+
# github first-name, people-file name) so "to: oz" matches author "oguzhan".
|
|
398
|
+
_DISPLAY_Q=$(jq -r '.display_name // empty' "$STATE_FILE" 2>/dev/null)
|
|
399
|
+
_GH_NAME_Q=$(jq -r '.github_name // empty' "$STATE_FILE" 2>/dev/null)
|
|
400
|
+
_FIRST_NAME_Q=$(echo "$_GH_NAME_Q" | awk '{print tolower($1)}')
|
|
401
|
+
_PEOPLE_FILE_Q="$SCRIPT_DIR/memory/people/$(echo "$AUTHOR" | tr '[:upper:]' '[:lower:]').md"
|
|
402
|
+
_PEOPLE_NAME_Q=""
|
|
403
|
+
[ -f "$_PEOPLE_FILE_Q" ] && _PEOPLE_NAME_Q=$(sed -n 's/^# *//p' "$_PEOPLE_FILE_Q" 2>/dev/null | head -1 | awk '{print tolower($1)}')
|
|
404
|
+
|
|
405
|
+
LINES=""
|
|
406
|
+
for QF in "$QDIR"/*.md; do
|
|
407
|
+
[ -f "$QF" ] || continue
|
|
408
|
+
Q_TO=$(sed -n 's/^to:[[:space:]]*//p' "$QF" 2>/dev/null | head -1 | tr -d '"' | tr '[:upper:]' '[:lower:]' | awk '{print $1}')
|
|
409
|
+
[ -z "$Q_TO" ] && continue
|
|
410
|
+
_MATCH="false"
|
|
411
|
+
for _V in "$AUTHOR" "$_DISPLAY_Q" "$_FIRST_NAME_Q" "$_PEOPLE_NAME_Q"; do
|
|
412
|
+
[ -z "$_V" ] && continue
|
|
413
|
+
_V_LC=$(echo "$_V" | tr '[:upper:]' '[:lower:]')
|
|
414
|
+
[ "$Q_TO" = "$_V_LC" ] && _MATCH="true" && break
|
|
415
|
+
done
|
|
416
|
+
[ "$_MATCH" = "true" ] || continue
|
|
417
|
+
Q_STATUS=$(sed -n 's/^status:[[:space:]]*//p' "$QF" 2>/dev/null | head -1 | tr -d '"')
|
|
418
|
+
[ "$Q_STATUS" = "pending" ] || continue
|
|
419
|
+
Q_FROM=$(sed -n 's/^from:[[:space:]]*//p' "$QF" 2>/dev/null | head -1 | tr -d '"')
|
|
420
|
+
Q_TOPIC=$(sed -n 's/^topic:[[:space:]]*//p' "$QF" 2>/dev/null | head -1 | tr -d '"')
|
|
421
|
+
Q_HID=$(sed -n 's/^harvest_id:[[:space:]]*//p' "$QF" 2>/dev/null | head -1 | tr -d '"')
|
|
422
|
+
Q_REL="${QF#$SCRIPT_DIR/}"
|
|
423
|
+
LINE=$(jq -nc \
|
|
424
|
+
--arg from "$Q_FROM" \
|
|
425
|
+
--arg topic "$Q_TOPIC" \
|
|
426
|
+
--arg hid "$Q_HID" \
|
|
427
|
+
--arg file "$Q_REL" \
|
|
428
|
+
'{from:$from, topic:$topic, harvest_id:$hid, file:$file}' 2>/dev/null)
|
|
429
|
+
[ -n "$LINE" ] && LINES="$LINES$LINE
|
|
430
|
+
"
|
|
431
|
+
done
|
|
432
|
+
if [ -n "$LINES" ]; then
|
|
433
|
+
PENDING_JSON=$(echo "$LINES" | jq -sc '.' 2>/dev/null || echo "[]")
|
|
434
|
+
fi
|
|
435
|
+
fi
|
|
436
|
+
echo "$PENDING_JSON" > "$CTX_DIR/pending_questions"
|
|
437
|
+
) &
|
|
438
|
+
|
|
367
439
|
# 7. Graph health (background — zero added latency, runs in parallel)
|
|
368
440
|
(
|
|
369
441
|
if [ "$LOCAL_MODE" = "true" ]; then
|
|
@@ -90,7 +90,7 @@ mkdir -p /tmp
|
|
|
90
90
|
printf '## Team Activity\n\n'
|
|
91
91
|
printf '| Name | Last Seen | Working On |\n'
|
|
92
92
|
printf '|------|-----------|------------|\n'
|
|
93
|
-
echo "$_DB_TEAM_FILTERED" | jq -r '.[] | "| \(.name) | \(.last_seen) | \(
|
|
93
|
+
echo "$_DB_TEAM_FILTERED" | jq -r '.[] | ((.working_on // "")) as $w | (.branches // []) as $b | "| \(.name) | \(.last_seen) | \(if $w != "" then $w else ($b | join(", ")) end) |"' 2>/dev/null || true
|
|
94
94
|
printf '\n'
|
|
95
95
|
fi
|
|
96
96
|
fi
|
|
@@ -26,7 +26,20 @@ git config pull.rebase true 2>/dev/null || true
|
|
|
26
26
|
export GIT_HTTP_LOW_SPEED_LIMIT=1000 # abort if <1KB/s
|
|
27
27
|
export GIT_HTTP_LOW_SPEED_TIME=10 # for 10 seconds
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
# Attendant fast path: the ambient daemon (bin/attendant.sh) fetches origin,
|
|
30
|
+
# memory, and managed repos every few minutes. If its warm marker is fresh,
|
|
31
|
+
# refs are already up to date — skip the network fetches and launch on local
|
|
32
|
+
# ops only. Upstream fetch (framework update check) is not covered by the
|
|
33
|
+
# attendant and stays unconditional below.
|
|
34
|
+
_REFS_FRESH="false"
|
|
35
|
+
_ATT_SLUG=$(jq -r '.slug // "egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "egregore")
|
|
36
|
+
_ATT_MARKER="$HOME/.egregore/attendant/${_ATT_SLUG}-$(echo -n "$SCRIPT_DIR" | cksum | cut -d' ' -f1).warm-ts"
|
|
37
|
+
if [ -f "$_ATT_MARKER" ]; then
|
|
38
|
+
_ATT_AGE=$(( $(date +%s) - $(cat "$_ATT_MARKER" 2>/dev/null || echo 0) ))
|
|
39
|
+
[ "$_ATT_AGE" -lt 360 ] && _REFS_FRESH="true"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
[ "$_REFS_FRESH" != "true" ] && git fetch origin --quiet 2>/dev/null &
|
|
30
43
|
|
|
31
44
|
# Fetch upstream framework (for update check — non-blocking)
|
|
32
45
|
# Default: official egregore-core repo. Set upstream_url in egregore.json to override,
|
|
@@ -40,17 +53,19 @@ fi
|
|
|
40
53
|
|
|
41
54
|
# Sync memory in parallel (symlink or direct directory — both valid)
|
|
42
55
|
MEMORY_SYNCED="false"
|
|
43
|
-
if [ -d "$SCRIPT_DIR/memory/.git" ]; then
|
|
56
|
+
if [ -d "$SCRIPT_DIR/memory/.git" ] && [ "$_REFS_FRESH" != "true" ]; then
|
|
44
57
|
git -C "$SCRIPT_DIR/memory" fetch origin --quiet 2>/dev/null &
|
|
45
58
|
fi
|
|
46
59
|
|
|
47
60
|
# Fetch managed repos in parallel
|
|
48
61
|
MANAGED_REPOS=$(jq -r '(.repos[]? // empty) | if type == "object" then .name else . end' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
if [ "$_REFS_FRESH" != "true" ]; then
|
|
63
|
+
for REPO in $MANAGED_REPOS; do
|
|
64
|
+
if [ -d "$SCRIPT_DIR/../$REPO/.git" ]; then
|
|
65
|
+
git -C "$SCRIPT_DIR/../$REPO" fetch origin --quiet 2>/dev/null &
|
|
66
|
+
fi
|
|
67
|
+
done
|
|
68
|
+
fi
|
|
54
69
|
|
|
55
70
|
# Wait for all fetches
|
|
56
71
|
wait 2>/dev/null || true
|
|
@@ -93,6 +108,16 @@ else
|
|
|
93
108
|
HEALTH_GIT="fail"
|
|
94
109
|
fi
|
|
95
110
|
|
|
111
|
+
# --- Guarded staging -------------------------------------------------------
|
|
112
|
+
# git_add_guarded() lives in the shared lib so the /handoff auto-save uses the
|
|
113
|
+
# exact same logic. Fallback to plain `git add -A` if the lib can't be sourced,
|
|
114
|
+
# so an unattended auto-save never silently no-ops.
|
|
115
|
+
# shellcheck source=bin/lib/git-safe.sh
|
|
116
|
+
. "$SCRIPT_DIR/bin/lib/git-safe.sh" 2>/dev/null || true
|
|
117
|
+
if ! type git_add_guarded >/dev/null 2>&1; then
|
|
118
|
+
git_add_guarded() { git add -A 2>/dev/null || true; }
|
|
119
|
+
fi
|
|
120
|
+
|
|
96
121
|
# --- Setup develop (wrapped — failures set HEALTH_GIT but don't crash) ---
|
|
97
122
|
setup_develop() {
|
|
98
123
|
# Ensure develop branch exists locally
|
|
@@ -143,8 +168,9 @@ setup_develop() {
|
|
|
143
168
|
if [[ "$CURRENT_BRANCH" != "develop" ]]; then
|
|
144
169
|
# Check for uncommitted work (staged + unstaged + untracked in tracked dirs)
|
|
145
170
|
if [ -n "$(git status --porcelain 2>/dev/null | head -1)" ]; then
|
|
146
|
-
# Save uncommitted work so nothing is lost
|
|
147
|
-
|
|
171
|
+
# Save uncommitted work so nothing is lost (guarded: never auto-commit
|
|
172
|
+
# stray submodule pointers from sibling repos in the checkout)
|
|
173
|
+
git_add_guarded
|
|
148
174
|
git commit -m "Auto-save: uncommitted work from $CURRENT_BRANCH" --quiet 2>/dev/null || true
|
|
149
175
|
SAVED_BRANCH="$CURRENT_BRANCH"
|
|
150
176
|
fi
|
|
@@ -112,8 +112,26 @@ if [ "$ADDRESSED_COUNT" -gt 0 ] 2>/dev/null && [ "$ADDRESSED_COUNT" != "0" ]; th
|
|
|
112
112
|
done
|
|
113
113
|
fi
|
|
114
114
|
|
|
115
|
-
#
|
|
116
|
-
|
|
115
|
+
# Pending questions addressed to you (one summary line — /answer to engage)
|
|
116
|
+
PENDING_Q=$(cat "$CTX_DIR/pending_questions" 2>/dev/null || echo "[]")
|
|
117
|
+
PENDING_Q_COUNT=$(echo "$PENDING_Q" | jq 'length' 2>/dev/null || echo "0")
|
|
118
|
+
if [ "$PENDING_Q_COUNT" -gt 0 ] 2>/dev/null && [ "$PENDING_Q_COUNT" != "0" ]; then
|
|
119
|
+
PQ_SENDERS=$(echo "$PENDING_Q" | jq -r '[.[].from] | unique | join(", ")' 2>/dev/null)
|
|
120
|
+
if [ "$PENDING_Q_COUNT" = "1" ]; then
|
|
121
|
+
PQ_NOUN="question"
|
|
122
|
+
else
|
|
123
|
+
PQ_NOUN="questions"
|
|
124
|
+
fi
|
|
125
|
+
if [ -n "$PQ_SENDERS" ]; then
|
|
126
|
+
printf " ◐ %s pending %s from %s — /answer to engage\n" "$PENDING_Q_COUNT" "$PQ_NOUN" "$PQ_SENDERS"
|
|
127
|
+
else
|
|
128
|
+
printf " ◐ %s pending %s — /answer to engage\n" "$PENDING_Q_COUNT" "$PQ_NOUN"
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
131
|
+
|
|
132
|
+
# Fallback: last activity if no handoffs and no pending questions
|
|
133
|
+
if { [ "$ADDRESSED_COUNT" = "0" ] || [ -z "$ADDRESSED_COUNT" ]; } \
|
|
134
|
+
&& { [ "$PENDING_Q_COUNT" = "0" ] || [ -z "$PENDING_Q_COUNT" ]; }; then
|
|
117
135
|
LAST_ACTIVITY=$(cat "$CTX_DIR/activity" 2>/dev/null || echo "")
|
|
118
136
|
if [ -n "$LAST_ACTIVITY" ]; then
|
|
119
137
|
LA_TIME=$(echo "$LAST_ACTIVITY" | cut -d'|' -f1)
|
|
@@ -131,7 +149,7 @@ if [ "$TEAM_DATA_COUNT" -gt 0 ] 2>/dev/null && [ "$TEAM_DATA_COUNT" != "0" ]; th
|
|
|
131
149
|
echo " ◦ around"
|
|
132
150
|
# Presence roster with online/offline dots (hide inactive >3 days)
|
|
133
151
|
STALE_THRESHOLD=$((RECENCY_DAYS * 86400))
|
|
134
|
-
echo "$TEAM_DATA" | jq -r '.[] | "\(.name)\t\(.last_seen_sort)\t\(.last_seen)\t\(
|
|
152
|
+
echo "$TEAM_DATA" | jq -r '.[] | ((.working_on // "")) as $w | (.branches // []) as $b | "\(.name)\t\(.last_seen_sort)\t\(.last_seen)\t\(if $w != "" then $w else ($b | join(", ")) end)"' 2>/dev/null | while IFS=$'\t' read -r P_NAME P_EPOCH P_SEEN P_BRANCHES; do
|
|
135
153
|
[ -z "$P_NAME" ] && continue
|
|
136
154
|
# Skip if no recent activity (within recency window)
|
|
137
155
|
if [ "$P_EPOCH" -le 0 ] 2>/dev/null; then
|
|
@@ -256,6 +274,10 @@ if [ -n "${BOARD_URL:-}" ]; then
|
|
|
256
274
|
printf " ◆ %s (board)\n" "$BOARD_URL"
|
|
257
275
|
fi
|
|
258
276
|
|
|
277
|
+
if [ -n "${LOOM_DOCTOR_BRIEF:-}" ]; then
|
|
278
|
+
printf " %s\n" "$LOOM_DOCTOR_BRIEF"
|
|
279
|
+
fi
|
|
280
|
+
|
|
259
281
|
# Framework updates come through PRs to develop — no separate auto-update channel.
|
|
260
282
|
# The develop sync above already keeps framework files current.
|
|
261
283
|
# Use /update for manual upstream pulls when needed.
|
|
@@ -33,6 +33,7 @@ DESCRIPTION=""
|
|
|
33
33
|
ARTIFACT_ID=""
|
|
34
34
|
RAW_HTML=0
|
|
35
35
|
SKIP_REFERENCES=0
|
|
36
|
+
PAIR=""
|
|
36
37
|
|
|
37
38
|
while [[ $# -gt 0 ]]; do
|
|
38
39
|
case "$1" in
|
|
@@ -40,6 +41,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
40
41
|
--author) AUTHOR="$2"; shift 2 ;;
|
|
41
42
|
--description) DESCRIPTION="$2"; shift 2 ;;
|
|
42
43
|
--id) ARTIFACT_ID="$2"; shift 2 ;;
|
|
44
|
+
--pair) PAIR="$2"; shift 2 ;;
|
|
43
45
|
--raw-html) RAW_HTML=1; shift ;;
|
|
44
46
|
--no-references) SKIP_REFERENCES=1; shift ;;
|
|
45
47
|
*)
|
|
@@ -72,6 +74,7 @@ fi
|
|
|
72
74
|
if [ -f "$SCRIPT_DIR/.env" ]; then
|
|
73
75
|
EGREGORE_API_URL="${EGREGORE_API_URL:-$(grep '^EGREGORE_API_URL=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2- || true)}"
|
|
74
76
|
EGREGORE_API_KEY="${EGREGORE_API_KEY:-$(grep '^EGREGORE_API_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2- || true)}"
|
|
77
|
+
EGREGORE_USE_PUBLISHED="${EGREGORE_USE_PUBLISHED:-$(grep '^EGREGORE_USE_PUBLISHED=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2- || true)}"
|
|
75
78
|
fi
|
|
76
79
|
|
|
77
80
|
API_URL="${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG" 2>/dev/null)}"
|
|
@@ -79,6 +82,16 @@ API_KEY="${EGREGORE_API_KEY:-}"
|
|
|
79
82
|
ORG_SLUG="$(jq -r '.slug // empty' "$CONFIG" 2>/dev/null)"
|
|
80
83
|
VIEW_BASE="https://egregore.xyz/view"
|
|
81
84
|
|
|
85
|
+
# Resolve "use published renderer" from env first, then egregore.json. The
|
|
86
|
+
# env var lets individuals override per-shell; egregore.json lets an
|
|
87
|
+
# instance (e.g. the upstream dev repo) opt in for every teammate.
|
|
88
|
+
if [ -z "${EGREGORE_USE_PUBLISHED:-}" ]; then
|
|
89
|
+
CONFIG_USE_PUBLISHED="$(jq -r '.prefer_published_artifacts // empty' "$CONFIG" 2>/dev/null)"
|
|
90
|
+
if [ "$CONFIG_USE_PUBLISHED" = "true" ]; then
|
|
91
|
+
EGREGORE_USE_PUBLISHED=1
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
|
|
82
95
|
# Public relay for OSS share endpoint
|
|
83
96
|
RELAY_URL="https://egregore-production-55f2.up.railway.app"
|
|
84
97
|
|
|
@@ -98,13 +111,21 @@ else
|
|
|
98
111
|
if [ -n "$API_KEY" ] && [ -n "$ORG_SLUG" ]; then
|
|
99
112
|
RENDER_ARGS+=(--org-slug "$ORG_SLUG" --view-base "$VIEW_BASE")
|
|
100
113
|
fi
|
|
114
|
+
# Palette family (meridian default | agronomic | sovereign). Role-token driven,
|
|
115
|
+
# so it themes any composed artifact with no extra CSS.
|
|
116
|
+
if [ -n "$PAIR" ]; then
|
|
117
|
+
RENDER_ARGS+=(--pair "$PAIR")
|
|
118
|
+
fi
|
|
101
119
|
|
|
102
120
|
# Prefer the in-repo package copy when it's present AND its dependencies
|
|
103
121
|
# have been installed — that way local edits to packages/egregore-artifacts
|
|
104
122
|
# are exercised without waiting for an npm release. Fall back to the
|
|
105
123
|
# published `npx egregore-artifacts` otherwise.
|
|
124
|
+
# Set EGREGORE_USE_PUBLISHED=1 to force the npm-published renderer even
|
|
125
|
+
# when a local install is present — useful in the upstream dev repo to
|
|
126
|
+
# dogfood what teammates and OSS users actually run.
|
|
106
127
|
LOCAL_CLI="$SCRIPT_DIR/packages/egregore-artifacts/bin/cli.js"
|
|
107
|
-
if [ -f "$LOCAL_CLI" ] && [ -d "$SCRIPT_DIR/packages/egregore-artifacts/node_modules/react" ]; then
|
|
128
|
+
if [ "${EGREGORE_USE_PUBLISHED:-0}" != "1" ] && [ -f "$LOCAL_CLI" ] && [ -d "$SCRIPT_DIR/packages/egregore-artifacts/node_modules/react" ]; then
|
|
108
129
|
if ! node "$LOCAL_CLI" "${RENDER_ARGS[@]}" >/dev/null 2>&1; then
|
|
109
130
|
exit 0
|
|
110
131
|
fi
|
|
@@ -158,6 +179,13 @@ if [ -n "$RESPONSE" ]; then
|
|
|
158
179
|
URL=$(echo "$RESPONSE" | jq -r '.url // empty' 2>/dev/null)
|
|
159
180
|
if [ -n "$URL" ]; then
|
|
160
181
|
echo "$URL"
|
|
182
|
+
# Register in the local artifact registry (memory/artifacts/) so this hosted
|
|
183
|
+
# artifact is findable by CONTENT, not just name — grep/ls (Claude Code /
|
|
184
|
+
# Codex, OSS), and search + graph (paid). Never fatal to the publish.
|
|
185
|
+
bash "$SCRIPT_DIR/bin/artifact-register.sh" \
|
|
186
|
+
--id "$ARTIFACT_ID" --url "$URL" --type "$TYPE" --title "$TITLE" \
|
|
187
|
+
--author "$AUTHOR" --source "$FILE" --description "$DESCRIPTION" \
|
|
188
|
+
>/dev/null 2>&1 || true
|
|
161
189
|
fi
|
|
162
190
|
fi
|
|
163
191
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "egregore-runtime",
|
|
3
3
|
"policy": "public-safe subset derived from .syncignore; built by scripts/build-runtime-bundle.mjs",
|
|
4
|
-
"skillCount":
|
|
4
|
+
"skillCount": 56,
|
|
5
5
|
"skills": [
|
|
6
6
|
"activity",
|
|
7
7
|
"add",
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"issue",
|
|
30
30
|
"me",
|
|
31
31
|
"meeting",
|
|
32
|
+
"minion",
|
|
32
33
|
"note",
|
|
33
34
|
"onboarding",
|
|
34
35
|
"pr",
|
|
@@ -40,6 +41,9 @@
|
|
|
40
41
|
"reflect",
|
|
41
42
|
"review-pr",
|
|
42
43
|
"save",
|
|
44
|
+
"scroll",
|
|
45
|
+
"search",
|
|
46
|
+
"session-view",
|
|
43
47
|
"setup",
|
|
44
48
|
"summon",
|
|
45
49
|
"sync-repos",
|
|
@@ -47,6 +51,7 @@
|
|
|
47
51
|
"telemetry",
|
|
48
52
|
"test",
|
|
49
53
|
"the-spiral",
|
|
54
|
+
"thread",
|
|
50
55
|
"todo",
|
|
51
56
|
"tui-design",
|
|
52
57
|
"tutorial",
|
|
@@ -60,6 +65,7 @@
|
|
|
60
65
|
".codex/config.toml",
|
|
61
66
|
".codex/hooks.json",
|
|
62
67
|
".codex/hooks/branch-guard.js",
|
|
68
|
+
".codex/hooks/search-hint.js",
|
|
63
69
|
".codex/skills/activity/SKILL.md",
|
|
64
70
|
".codex/skills/add/SKILL.md",
|
|
65
71
|
".codex/skills/announce/SKILL.md",
|
|
@@ -86,6 +92,7 @@
|
|
|
86
92
|
".codex/skills/issue/SKILL.md",
|
|
87
93
|
".codex/skills/me/SKILL.md",
|
|
88
94
|
".codex/skills/meeting/SKILL.md",
|
|
95
|
+
".codex/skills/minion/SKILL.md",
|
|
89
96
|
".codex/skills/note/SKILL.md",
|
|
90
97
|
".codex/skills/onboarding/SKILL.md",
|
|
91
98
|
".codex/skills/pr/SKILL.md",
|
|
@@ -97,6 +104,11 @@
|
|
|
97
104
|
".codex/skills/reflect/SKILL.md",
|
|
98
105
|
".codex/skills/review-pr/SKILL.md",
|
|
99
106
|
".codex/skills/save/SKILL.md",
|
|
107
|
+
".codex/skills/scroll/SKILL.md",
|
|
108
|
+
".codex/skills/scroll/agents/openai.yaml",
|
|
109
|
+
".codex/skills/scroll/assets/shell.html",
|
|
110
|
+
".codex/skills/search/SKILL.md",
|
|
111
|
+
".codex/skills/session-view/SKILL.md",
|
|
100
112
|
".codex/skills/setup/SKILL.md",
|
|
101
113
|
".codex/skills/summon/SKILL.md",
|
|
102
114
|
".codex/skills/sync-repos/SKILL.md",
|
|
@@ -104,11 +116,14 @@
|
|
|
104
116
|
".codex/skills/telemetry/SKILL.md",
|
|
105
117
|
".codex/skills/test/SKILL.md",
|
|
106
118
|
".codex/skills/the-spiral/SKILL.md",
|
|
119
|
+
".codex/skills/thread/SKILL.md",
|
|
107
120
|
".codex/skills/todo/SKILL.md",
|
|
108
121
|
".codex/skills/tui-design/SKILL.md",
|
|
109
122
|
".codex/skills/tutorial/SKILL.md",
|
|
110
123
|
".codex/skills/update/SKILL.md",
|
|
111
124
|
".codex/skills/view/SKILL.md",
|
|
125
|
+
".codex/skills/view/agents/openai.yaml",
|
|
126
|
+
".codex/skills/view/assets/compose-scaffold.html",
|
|
112
127
|
".codex/skills/visual-explain/SKILL.md",
|
|
113
128
|
".codex/skills/wrap/SKILL.md",
|
|
114
129
|
".codex/spec-manifest.json",
|