create-egregore 0.19.3 → 0.19.6
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 +410 -26
- package/bin/cli.js +34 -20
- package/lib/local.js +84 -11
- package/lib/pi-runtime.js +186 -0
- package/lib/setup.js +56 -11
- package/lib/ui.js +1 -1
- package/package.json +8 -6
- 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 +4 -4
- package/runtime/codex/AGENTS.md +31 -5
- 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 +24 -2
- package/runtime/codex/bin/codex-session-start.sh +6 -60
- package/runtime/codex/bin/codex-skill-render.mjs +20 -12
- 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 +97 -18
- 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 +30 -104
- package/runtime/codex/bin/lib/metrics.sh +374 -0
- package/runtime/codex/bin/publish-artifact.sh +43 -1
- package/runtime/codex/bin/settings.sh +274 -0
- package/runtime/codex/manifest.json +18 -1
- 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,142 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# dashboard-artifact.sh — Generate a session dashboard artifact with a shareable URL
|
|
3
|
+
#
|
|
4
|
+
# Runs after context.sh (all $CTX_DIR/* files populated), before greeting.sh.
|
|
5
|
+
# Compiles gathered context into a markdown document, generates HTML via
|
|
6
|
+
# egregore-artifacts, publishes it, and exports DASHBOARD_URL for greeting.sh.
|
|
7
|
+
#
|
|
8
|
+
# Inputs: SCRIPT_DIR, CTX_DIR, AUTHOR, GREETING_NAME, LOCAL_MODE,
|
|
9
|
+
# EGREGORE_SESSION_ID, FIRST_SESSION
|
|
10
|
+
# Outputs: DASHBOARD_URL (exported for greeting.sh)
|
|
11
|
+
|
|
12
|
+
DASHBOARD_URL=""
|
|
13
|
+
|
|
14
|
+
# Skip conditions: first session, onboarding incomplete, no session ID
|
|
15
|
+
if [ "${FIRST_SESSION:-false}" = "true" ]; then
|
|
16
|
+
return 0 2>/dev/null || exit 0
|
|
17
|
+
fi
|
|
18
|
+
if [ -z "${EGREGORE_SESSION_ID:-}" ]; then
|
|
19
|
+
return 0 2>/dev/null || exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
# --- Read gathered context ---
|
|
23
|
+
_DB_ADDRESSED=$(cat "$CTX_DIR/addressed_rich" 2>/dev/null || echo "[]")
|
|
24
|
+
_DB_ADDR_COUNT=$(echo "$_DB_ADDRESSED" | jq 'length' 2>/dev/null || echo "0")
|
|
25
|
+
_DB_QUESTS=$(cat "$CTX_DIR/quests" 2>/dev/null || echo "[]")
|
|
26
|
+
_DB_QUEST_COUNT=$(echo "$_DB_QUESTS" | jq 'length' 2>/dev/null || echo "0")
|
|
27
|
+
_DB_TEAM=$(cat "$CTX_DIR/team" 2>/dev/null || echo "[]")
|
|
28
|
+
_DB_TEAM_COUNT=$(echo "$_DB_TEAM" | jq 'length' 2>/dev/null || echo "0")
|
|
29
|
+
_DB_LIFECYCLE=$(cat "$CTX_DIR/lifecycle" 2>/dev/null || echo '{}')
|
|
30
|
+
_DB_MERGED_COUNT=$(echo "$_DB_LIFECYCLE" | jq '.merged_prs.values // [] | length' 2>/dev/null || echo "0")
|
|
31
|
+
_DB_IMPL_COUNT=$(echo "$_DB_LIFECYCLE" | jq '.implemented_handoffs.values // [] | length' 2>/dev/null || echo "0")
|
|
32
|
+
_DB_PULSE=$(cat "$CTX_DIR/pulse_brief" 2>/dev/null || echo '{}')
|
|
33
|
+
_DB_PULSE_BRIEF=$(echo "$_DB_PULSE" | jq -r '.brief // empty' 2>/dev/null || true)
|
|
34
|
+
|
|
35
|
+
# Skip if all context is empty — nothing worth showing
|
|
36
|
+
_DB_HAS_CONTENT="false"
|
|
37
|
+
if [ "$_DB_ADDR_COUNT" -gt 0 ] 2>/dev/null; then _DB_HAS_CONTENT="true"; fi
|
|
38
|
+
if [ "$_DB_QUEST_COUNT" -gt 0 ] 2>/dev/null; then _DB_HAS_CONTENT="true"; fi
|
|
39
|
+
if [ "$_DB_TEAM_COUNT" -gt 0 ] 2>/dev/null; then _DB_HAS_CONTENT="true"; fi
|
|
40
|
+
if [ "$_DB_MERGED_COUNT" -gt 0 ] 2>/dev/null; then _DB_HAS_CONTENT="true"; fi
|
|
41
|
+
if [ "$_DB_IMPL_COUNT" -gt 0 ] 2>/dev/null; then _DB_HAS_CONTENT="true"; fi
|
|
42
|
+
|
|
43
|
+
if [ "$_DB_HAS_CONTENT" = "false" ]; then
|
|
44
|
+
return 0 2>/dev/null || exit 0
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
# --- Compile markdown ---
|
|
48
|
+
_DB_DATE=$(date +%Y-%m-%d)
|
|
49
|
+
_DB_ORG=$(jq -r '.org_name // "Egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "Egregore")
|
|
50
|
+
_DB_MD="/tmp/egregore-dashboard-${EGREGORE_SESSION_ID}.md"
|
|
51
|
+
mkdir -p /tmp
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
printf '# Session Dashboard — %s\n\n' "$_DB_ORG"
|
|
55
|
+
|
|
56
|
+
# --- Pulse Brief (first — sets the tone) ---
|
|
57
|
+
if [ -n "$_DB_PULSE_BRIEF" ]; then
|
|
58
|
+
printf '## Pulse\n\n'
|
|
59
|
+
printf '✦ %s\n\n' "$_DB_PULSE_BRIEF"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# --- Handoffs & Asks (dense format matching terminal TUI) ---
|
|
63
|
+
if [ "$_DB_ADDR_COUNT" -gt 0 ] 2>/dev/null; then
|
|
64
|
+
printf '## Handoffs & Asks\n\n'
|
|
65
|
+
_DB_NOW_SEC=$(date +%s)
|
|
66
|
+
echo "$_DB_ADDRESSED" | jq -r '.[] | "\(.author // "unknown")\t\(.topic // "Untitled")\t\(.date // "--")"' 2>/dev/null | while IFS=$'\t' read -r _HF_AUTHOR _HF_TOPIC _HF_DATE; do
|
|
67
|
+
[ -z "$_HF_AUTHOR" ] && continue
|
|
68
|
+
# Compute relative time
|
|
69
|
+
_HF_DATE_ONLY="${_HF_DATE%%T*}"
|
|
70
|
+
_HF_EPOCH=$(date -j -f "%Y-%m-%d" "$_HF_DATE_ONLY" +%s 2>/dev/null || \
|
|
71
|
+
date -d "$_HF_DATE_ONLY" +%s 2>/dev/null || echo "0")
|
|
72
|
+
_HF_DAYS=$(( (_DB_NOW_SEC - _HF_EPOCH) / 86400 ))
|
|
73
|
+
if [ "$_HF_DAYS" -le 0 ] 2>/dev/null; then _HF_AGO="today"
|
|
74
|
+
elif [ "$_HF_DAYS" -eq 1 ] 2>/dev/null; then _HF_AGO="yesterday"
|
|
75
|
+
else _HF_AGO="${_HF_DAYS}d ago"
|
|
76
|
+
fi
|
|
77
|
+
_HF_NAME_LC=$(printf '%s' "$_HF_AUTHOR" | awk '{print tolower($1)}')
|
|
78
|
+
printf '● %s → you: %s (%s)\n\n' "$_HF_NAME_LC" "$_HF_TOPIC" "$_HF_AGO"
|
|
79
|
+
done
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# --- Team Activity (right after handoffs, recent only) ---
|
|
83
|
+
if [ "$_DB_TEAM_COUNT" -gt 0 ] 2>/dev/null; then
|
|
84
|
+
_DB_NOW=$(date +%s)
|
|
85
|
+
_DB_RECENCY=$((7 * 86400))
|
|
86
|
+
_DB_TEAM_FILTERED=$(echo "$_DB_TEAM" | jq --argjson now "$_DB_NOW" --argjson window "$_DB_RECENCY" \
|
|
87
|
+
'[.[] | select(.last_seen_sort > 0 and ($now - .last_seen_sort) < $window)]' 2>/dev/null || echo "[]")
|
|
88
|
+
_DB_TEAM_FCOUNT=$(echo "$_DB_TEAM_FILTERED" | jq 'length' 2>/dev/null || echo "0")
|
|
89
|
+
if [ "$_DB_TEAM_FCOUNT" -gt 0 ] 2>/dev/null; then
|
|
90
|
+
printf '## Team Activity\n\n'
|
|
91
|
+
printf '| Name | Last Seen | Working On |\n'
|
|
92
|
+
printf '|------|-----------|------------|\n'
|
|
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
|
+
printf '\n'
|
|
95
|
+
fi
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
# --- What Changed ---
|
|
99
|
+
if [ "$_DB_MERGED_COUNT" -gt 0 ] 2>/dev/null || [ "$_DB_IMPL_COUNT" -gt 0 ] 2>/dev/null; then
|
|
100
|
+
printf '## What Changed\n\n'
|
|
101
|
+
if [ "$_DB_MERGED_COUNT" -gt 0 ] 2>/dev/null; then
|
|
102
|
+
echo "$_DB_LIFECYCLE" | jq -r '.merged_prs.values[]? | "- ✓ PR #\(.[0]) \(.[2] // .[1] // "")"' 2>/dev/null || true
|
|
103
|
+
fi
|
|
104
|
+
if [ "$_DB_IMPL_COUNT" -gt 0 ] 2>/dev/null; then
|
|
105
|
+
echo "$_DB_LIFECYCLE" | jq -r '.implemented_handoffs.values[]? | "- ✓ \(.[1] // "someone") worked on: \(.[0] // "handoff")"' 2>/dev/null || true
|
|
106
|
+
fi
|
|
107
|
+
printf '\n'
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# --- Active Quests (bottom — reference, exclude meta entries) ---
|
|
111
|
+
if [ "$_DB_QUEST_COUNT" -gt 0 ] 2>/dev/null; then
|
|
112
|
+
_DB_QUESTS_FILTERED=$(echo "$_DB_QUESTS" | jq '[.[] | select(. != "_template" and . != "index")][:10]' 2>/dev/null || echo "[]")
|
|
113
|
+
_DB_QF_COUNT=$(echo "$_DB_QUESTS_FILTERED" | jq 'length' 2>/dev/null || echo "0")
|
|
114
|
+
if [ "$_DB_QF_COUNT" -gt 0 ] 2>/dev/null; then
|
|
115
|
+
printf '## Active Quests\n\n'
|
|
116
|
+
echo "$_DB_QUESTS_FILTERED" | jq -r '.[] | "- \(.)"' 2>/dev/null || true
|
|
117
|
+
printf '\n'
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
} > "$_DB_MD" 2>/dev/null
|
|
122
|
+
|
|
123
|
+
# --- Publish markdown → HTML → hosted URL ---
|
|
124
|
+
# publish-artifact.sh handles HTML generation internally (npx egregore-artifacts)
|
|
125
|
+
# then uploads. Don't pre-generate HTML — that causes double-wrapping.
|
|
126
|
+
# https:// URLs are universally cmd+clickable across all terminal emulators.
|
|
127
|
+
# publish-artifact.sh may output npx progress lines before the URL — extract just the URL
|
|
128
|
+
_DB_PUBLISH_OUT=$(bash "$SCRIPT_DIR/bin/publish-artifact.sh" document "$_DB_MD" \
|
|
129
|
+
--title "Session Dashboard" \
|
|
130
|
+
--author "${GREETING_NAME:-$AUTHOR}" 2>/dev/null || true)
|
|
131
|
+
DASHBOARD_URL=$(echo "$_DB_PUBLISH_OUT" | grep -o 'https://[^ ]*' | tail -1)
|
|
132
|
+
|
|
133
|
+
# Fallback: generate HTML locally and use file:// URL (offline, no API key, etc.)
|
|
134
|
+
if [ -z "$DASHBOARD_URL" ]; then
|
|
135
|
+
_DB_HTML="/tmp/egregore-artifacts/dashboard-${EGREGORE_SESSION_ID}.html"
|
|
136
|
+
mkdir -p /tmp/egregore-artifacts
|
|
137
|
+
if npx egregore-artifacts@latest document "$_DB_MD" --output "$_DB_HTML" --no-open >/dev/null 2>&1 && [ -f "$_DB_HTML" ]; then
|
|
138
|
+
DASHBOARD_URL="file://${_DB_HTML}"
|
|
139
|
+
fi
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
rm -f "$_DB_MD"
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ensure-develop.sh — Ensure a repository has a develop branch.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# bash bin/lib/ensure-develop.sh <repo-path>
|
|
6
|
+
# bash bin/lib/ensure-develop.sh <repo-path> --report
|
|
7
|
+
#
|
|
8
|
+
# Behavior:
|
|
9
|
+
# 1. Detects the repo's default branch (main, master, or HEAD)
|
|
10
|
+
# 2. Checks if develop exists locally and/or on origin
|
|
11
|
+
# 3. If missing, creates develop from the default branch and pushes it
|
|
12
|
+
#
|
|
13
|
+
# Flags:
|
|
14
|
+
# --report Print a JSON report of the repo's branching model instead of
|
|
15
|
+
# creating develop. Used by create-egregore to analyze existing repos.
|
|
16
|
+
#
|
|
17
|
+
# Exit codes:
|
|
18
|
+
# 0 — develop exists (already existed or was just created)
|
|
19
|
+
# 1 — could not create develop (no default branch, not a git repo, push failed)
|
|
20
|
+
#
|
|
21
|
+
# Output (on success, without --report):
|
|
22
|
+
# created:<default_branch> — develop was created from <default_branch>
|
|
23
|
+
# exists — develop already existed
|
|
24
|
+
#
|
|
25
|
+
# Output (with --report):
|
|
26
|
+
# JSON object with branching analysis
|
|
27
|
+
|
|
28
|
+
set -o pipefail
|
|
29
|
+
|
|
30
|
+
REPO_PATH="${1:-.}"
|
|
31
|
+
FLAG="${2:-}"
|
|
32
|
+
|
|
33
|
+
if [ ! -d "$REPO_PATH/.git" ] && [ ! -f "$REPO_PATH/.git" ]; then
|
|
34
|
+
echo "error:not_a_git_repo" >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
# ── Detect default branch ──────────────────────────────────────────
|
|
39
|
+
# Priority: what origin/HEAD points to > main > master > first branch found
|
|
40
|
+
detect_default_branch() {
|
|
41
|
+
local repo="$1"
|
|
42
|
+
|
|
43
|
+
# 1. Check origin/HEAD (set by GitHub on clone)
|
|
44
|
+
local origin_head
|
|
45
|
+
origin_head=$(git -C "$repo" symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||')
|
|
46
|
+
if [ -n "$origin_head" ] && git -C "$repo" show-ref --verify --quiet "refs/remotes/origin/$origin_head" 2>/dev/null; then
|
|
47
|
+
echo "$origin_head"
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# 2. Check common names on remote
|
|
52
|
+
for branch in main master; do
|
|
53
|
+
if git -C "$repo" show-ref --verify --quiet "refs/remotes/origin/$branch" 2>/dev/null; then
|
|
54
|
+
echo "$branch"
|
|
55
|
+
return 0
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# 3. Check local branches (repo might not have a remote yet)
|
|
60
|
+
for branch in main master; do
|
|
61
|
+
if git -C "$repo" show-ref --verify --quiet "refs/heads/$branch" 2>/dev/null; then
|
|
62
|
+
echo "$branch"
|
|
63
|
+
return 0
|
|
64
|
+
fi
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
# 4. Fall back to whatever HEAD points to
|
|
68
|
+
local head_branch
|
|
69
|
+
head_branch=$(git -C "$repo" branch --show-current 2>/dev/null)
|
|
70
|
+
if [ -n "$head_branch" ] && [ "$head_branch" != "develop" ]; then
|
|
71
|
+
echo "$head_branch"
|
|
72
|
+
return 0
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
return 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# ── Report mode ─────────────────────────────────────────────────────
|
|
79
|
+
if [ "$FLAG" = "--report" ]; then
|
|
80
|
+
default_branch=$(detect_default_branch "$REPO_PATH" 2>/dev/null || echo "")
|
|
81
|
+
has_develop_local="false"
|
|
82
|
+
has_develop_remote="false"
|
|
83
|
+
git -C "$REPO_PATH" show-ref --verify --quiet refs/heads/develop 2>/dev/null && has_develop_local="true"
|
|
84
|
+
git -C "$REPO_PATH" show-ref --verify --quiet refs/remotes/origin/develop 2>/dev/null && has_develop_remote="true"
|
|
85
|
+
|
|
86
|
+
# Count remote branches (excluding HEAD)
|
|
87
|
+
branch_count=$(git -C "$REPO_PATH" branch -r 2>/dev/null | grep -cv 'HEAD' 2>/dev/null || echo "0")
|
|
88
|
+
[ -z "$branch_count" ] && branch_count=0
|
|
89
|
+
|
|
90
|
+
# List remote branch names (excluding origin/HEAD, max 20)
|
|
91
|
+
_branch_list=$(git -C "$REPO_PATH" branch -r --format='%(refname:short)' 2>/dev/null \
|
|
92
|
+
| grep -v 'origin/HEAD' \
|
|
93
|
+
| sed 's|^origin/||' \
|
|
94
|
+
| head -20)
|
|
95
|
+
if [ -n "$_branch_list" ]; then
|
|
96
|
+
branches=$(echo "$_branch_list" | jq -R . | jq -s .)
|
|
97
|
+
else
|
|
98
|
+
branches="[]"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Detect active contributors from branch names (dev/author/... pattern)
|
|
102
|
+
_contrib_list=$(git -C "$REPO_PATH" branch -r --format='%(refname:short)' 2>/dev/null \
|
|
103
|
+
| grep -E '^origin/dev/' \
|
|
104
|
+
| sed 's|^origin/dev/||; s|/.*||' \
|
|
105
|
+
| sort -u)
|
|
106
|
+
if [ -n "$_contrib_list" ]; then
|
|
107
|
+
contributors=$(echo "$_contrib_list" | jq -R . | jq -s .)
|
|
108
|
+
else
|
|
109
|
+
contributors="[]"
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
jq -n \
|
|
113
|
+
--arg default_branch "$default_branch" \
|
|
114
|
+
--argjson has_develop_local "$has_develop_local" \
|
|
115
|
+
--argjson has_develop_remote "$has_develop_remote" \
|
|
116
|
+
--argjson branch_count "$branch_count" \
|
|
117
|
+
--argjson branches "$branches" \
|
|
118
|
+
--argjson contributors "$contributors" \
|
|
119
|
+
'{
|
|
120
|
+
default_branch: $default_branch,
|
|
121
|
+
has_develop_local: $has_develop_local,
|
|
122
|
+
has_develop_remote: $has_develop_remote,
|
|
123
|
+
branch_count: $branch_count,
|
|
124
|
+
branches: $branches,
|
|
125
|
+
contributors: $contributors,
|
|
126
|
+
needs_develop: (($has_develop_remote | not) and ($has_develop_local | not))
|
|
127
|
+
}'
|
|
128
|
+
exit 0
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
# ── Ensure develop exists ──────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
# Already exists on remote?
|
|
134
|
+
if git -C "$REPO_PATH" show-ref --verify --quiet refs/remotes/origin/develop 2>/dev/null; then
|
|
135
|
+
# Ensure local tracking branch exists too
|
|
136
|
+
if ! git -C "$REPO_PATH" show-ref --verify --quiet refs/heads/develop 2>/dev/null; then
|
|
137
|
+
git -C "$REPO_PATH" branch develop origin/develop --quiet 2>/dev/null || true
|
|
138
|
+
fi
|
|
139
|
+
echo "exists"
|
|
140
|
+
exit 0
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Already exists locally but not on remote? Push it.
|
|
144
|
+
if git -C "$REPO_PATH" show-ref --verify --quiet refs/heads/develop 2>/dev/null; then
|
|
145
|
+
if git -C "$REPO_PATH" push -u origin develop --quiet 2>/dev/null; then
|
|
146
|
+
echo "exists"
|
|
147
|
+
exit 0
|
|
148
|
+
fi
|
|
149
|
+
# Push failed but local exists — still usable
|
|
150
|
+
echo "exists:local_only"
|
|
151
|
+
exit 0
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# Need to create develop from default branch
|
|
155
|
+
DEFAULT_BRANCH=$(detect_default_branch "$REPO_PATH")
|
|
156
|
+
if [ -z "$DEFAULT_BRANCH" ]; then
|
|
157
|
+
echo "error:no_default_branch" >&2
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Create develop from the default branch
|
|
162
|
+
# Prefer remote ref if available (more up-to-date after fetch)
|
|
163
|
+
if git -C "$REPO_PATH" show-ref --verify --quiet "refs/remotes/origin/$DEFAULT_BRANCH" 2>/dev/null; then
|
|
164
|
+
git -C "$REPO_PATH" branch develop "origin/$DEFAULT_BRANCH" --quiet 2>/dev/null
|
|
165
|
+
else
|
|
166
|
+
git -C "$REPO_PATH" branch develop "$DEFAULT_BRANCH" --quiet 2>/dev/null
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
if [ $? -ne 0 ]; then
|
|
170
|
+
echo "error:branch_create_failed" >&2
|
|
171
|
+
exit 1
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
# Push to remote
|
|
175
|
+
if git -C "$REPO_PATH" push -u origin develop --quiet 2>/dev/null; then
|
|
176
|
+
echo "created:$DEFAULT_BRANCH"
|
|
177
|
+
exit 0
|
|
178
|
+
else
|
|
179
|
+
# Push failed — develop exists locally but not on remote
|
|
180
|
+
# This is still usable; session-start.sh will retry the push
|
|
181
|
+
echo "created:$DEFAULT_BRANCH:local_only"
|
|
182
|
+
exit 0
|
|
183
|
+
fi
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
# shellcheck shell=bash
|
|
2
|
+
# git-sync.sh — Git synchronization for session-start.sh
|
|
3
|
+
#
|
|
4
|
+
# Handles all git operations during session startup:
|
|
5
|
+
# - Pull rebase configuration
|
|
6
|
+
# - Parallel fetches (origin, upstream, memory, managed repos)
|
|
7
|
+
# - Worktree orphan cleanup
|
|
8
|
+
# - Git health check
|
|
9
|
+
# - Develop branch setup + sync
|
|
10
|
+
# - Memory sync
|
|
11
|
+
# - Managed repos sync
|
|
12
|
+
#
|
|
13
|
+
# Inputs: SCRIPT_DIR, IS_WORKTREE, MAIN_PROJECT_DIR, STATE_FILE, ENV_FILE,
|
|
14
|
+
# HEALTH_GIT, MANAGED_REPOS (not yet set — read from config here)
|
|
15
|
+
# Outputs: HEALTH_GIT, DEVELOP_SYNCED, COMMITS_AHEAD, ACTION, SAVED_BRANCH,
|
|
16
|
+
# BRANCH, MEMORY_SYNCED, REPOS_STATUS, MANAGED_REPOS, CURRENT_BRANCH,
|
|
17
|
+
# FRAMEWORK_UPDATED
|
|
18
|
+
|
|
19
|
+
FRAMEWORK_UPDATED="false"
|
|
20
|
+
|
|
21
|
+
# --- Ensure pull.rebase is set (prevents "divergent branches" errors) ---
|
|
22
|
+
git config pull.rebase true 2>/dev/null || true
|
|
23
|
+
|
|
24
|
+
# --- Fetch all remotes in parallel ---
|
|
25
|
+
# Set git transfer timeout so hangs don't block startup indefinitely.
|
|
26
|
+
export GIT_HTTP_LOW_SPEED_LIMIT=1000 # abort if <1KB/s
|
|
27
|
+
export GIT_HTTP_LOW_SPEED_TIME=10 # for 10 seconds
|
|
28
|
+
|
|
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 &
|
|
43
|
+
|
|
44
|
+
# Fetch upstream framework (for update check — non-blocking)
|
|
45
|
+
# Default: official egregore-core repo. Set upstream_url in egregore.json to override,
|
|
46
|
+
# or set it to "none" to disable (e.g., in the dev repo where this IS the source).
|
|
47
|
+
_UPSTREAM_URL=$(jq -r '.upstream_url // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
48
|
+
[ -z "$_UPSTREAM_URL" ] && _UPSTREAM_URL="https://github.com/egregore-labs/egregore.git"
|
|
49
|
+
if [ "$_UPSTREAM_URL" != "none" ]; then
|
|
50
|
+
git remote add upstream "$_UPSTREAM_URL" 2>/dev/null || true
|
|
51
|
+
git fetch upstream main --quiet 2>/dev/null &
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Sync memory in parallel (symlink or direct directory — both valid)
|
|
55
|
+
MEMORY_SYNCED="false"
|
|
56
|
+
if [ -d "$SCRIPT_DIR/memory/.git" ] && [ "$_REFS_FRESH" != "true" ]; then
|
|
57
|
+
git -C "$SCRIPT_DIR/memory" fetch origin --quiet 2>/dev/null &
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# Fetch managed repos in parallel
|
|
61
|
+
MANAGED_REPOS=$(jq -r '(.repos[]? // empty) | if type == "object" then .name else . end' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
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
|
|
69
|
+
|
|
70
|
+
# Wait for all fetches
|
|
71
|
+
wait 2>/dev/null || true
|
|
72
|
+
|
|
73
|
+
# --- Auto-update framework from upstream (deferred) ---
|
|
74
|
+
# Moved AFTER setup_develop() so framework commits land on develop, not on
|
|
75
|
+
# working branches. See _apply_framework_update() below.
|
|
76
|
+
_AUTO_UPDATE=$(jq -r '.auto_update // true' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
77
|
+
|
|
78
|
+
_apply_framework_update() {
|
|
79
|
+
# Applies framework paths from upstream to the CURRENT branch (must be develop).
|
|
80
|
+
# Disable with "auto_update": false in egregore.json.
|
|
81
|
+
# Dev repos (upstream_url: "none") skip this entirely.
|
|
82
|
+
if [ "$_UPSTREAM_URL" = "none" ] || [ "$_AUTO_UPDATE" = "false" ]; then
|
|
83
|
+
return 0
|
|
84
|
+
fi
|
|
85
|
+
if ! git show-ref --verify --quiet refs/remotes/upstream/main 2>/dev/null; then
|
|
86
|
+
return 0
|
|
87
|
+
fi
|
|
88
|
+
# Apply upstream changes — checkout is idempotent, skip diff check
|
|
89
|
+
# (git diff with variable path lists breaks in zsh — no word-splitting)
|
|
90
|
+
for _p in bin/ .claude/commands/ .claude/skills/ .claude/hooks/ .claude/context/ .claude/agents/ loom/ CLAUDE.md skills/; do
|
|
91
|
+
git checkout upstream/main -- "$_p" 2>/dev/null || true
|
|
92
|
+
done
|
|
93
|
+
# Only commit if there are actual changes
|
|
94
|
+
if [ -n "$(git status --porcelain bin/ .claude/ loom/ CLAUDE.md skills/ 2>/dev/null | head -1)" ]; then
|
|
95
|
+
git add bin/ .claude/ loom/ CLAUDE.md skills/ 2>/dev/null
|
|
96
|
+
EGREGORE_FRAMEWORK_UPDATE=1 git commit -m "Auto-update Egregore framework" --quiet 2>/dev/null || true
|
|
97
|
+
FRAMEWORK_UPDATED="true"
|
|
98
|
+
fi
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# --- Worktree prune (just clean git's internal list, don't delete anything) ---
|
|
102
|
+
git worktree prune 2>/dev/null || true
|
|
103
|
+
|
|
104
|
+
# --- Git health check ---
|
|
105
|
+
if git show-ref --verify --quiet refs/remotes/origin/develop 2>/dev/null; then
|
|
106
|
+
HEALTH_GIT="ok"
|
|
107
|
+
else
|
|
108
|
+
HEALTH_GIT="fail"
|
|
109
|
+
fi
|
|
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
|
+
|
|
121
|
+
# --- Setup develop (wrapped — failures set HEALTH_GIT but don't crash) ---
|
|
122
|
+
setup_develop() {
|
|
123
|
+
# Ensure develop branch exists locally
|
|
124
|
+
if ! git show-ref --verify --quiet refs/heads/develop 2>/dev/null; then
|
|
125
|
+
if git show-ref --verify --quiet refs/remotes/origin/develop 2>/dev/null; then
|
|
126
|
+
git checkout -b develop origin/develop --quiet 2>/dev/null
|
|
127
|
+
else
|
|
128
|
+
# No develop on remote either — create from main
|
|
129
|
+
git checkout -b develop --quiet 2>/dev/null
|
|
130
|
+
git push -u origin develop --quiet 2>/dev/null
|
|
131
|
+
fi
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# Sync develop (without checkout — safe for concurrent sessions)
|
|
135
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
136
|
+
|
|
137
|
+
# Update local develop ref from remote without switching branches
|
|
138
|
+
# Use fetch + force-update to handle divergence (e.g., from auto-update commits)
|
|
139
|
+
git fetch origin develop --quiet 2>/dev/null || true
|
|
140
|
+
if [[ "$CURRENT_BRANCH" != "develop" ]]; then
|
|
141
|
+
# Safe to force-update when not checked out
|
|
142
|
+
git branch -f develop origin/develop 2>/dev/null || true
|
|
143
|
+
else
|
|
144
|
+
# On develop — try ff merge, fall back to reset only if no unpushed work
|
|
145
|
+
git merge --ff-only origin/develop --quiet 2>/dev/null || {
|
|
146
|
+
# Only reset if there are no unpushed commits on develop
|
|
147
|
+
LOCAL_AHEAD=$(git rev-list origin/develop..develop --count 2>/dev/null || echo "0")
|
|
148
|
+
if [ "$LOCAL_AHEAD" = "0" ]; then
|
|
149
|
+
git reset --hard origin/develop --quiet 2>/dev/null || true
|
|
150
|
+
fi
|
|
151
|
+
}
|
|
152
|
+
fi
|
|
153
|
+
DEVELOP_SYNCED="true"
|
|
154
|
+
|
|
155
|
+
# Count commits on develop ahead of main
|
|
156
|
+
COMMITS_AHEAD=0
|
|
157
|
+
if git show-ref --verify --quiet refs/remotes/origin/main 2>/dev/null; then
|
|
158
|
+
COMMITS_AHEAD=$(git rev-list origin/main..develop --count 2>/dev/null || echo "0")
|
|
159
|
+
fi
|
|
160
|
+
|
|
161
|
+
# Always start from develop
|
|
162
|
+
# Every session begins on develop. Claude creates a fresh topic branch
|
|
163
|
+
# (dev/{author}/{topic-slug}) when the user says what they're working on.
|
|
164
|
+
# If we're on a working branch with uncommitted work, save it first.
|
|
165
|
+
ACTION="ready"
|
|
166
|
+
SAVED_BRANCH=""
|
|
167
|
+
|
|
168
|
+
if [[ "$CURRENT_BRANCH" != "develop" ]]; then
|
|
169
|
+
# Check for uncommitted work (staged + unstaged + untracked in tracked dirs)
|
|
170
|
+
if [ -n "$(git status --porcelain 2>/dev/null | head -1)" ]; then
|
|
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
|
|
174
|
+
git commit -m "Auto-save: uncommitted work from $CURRENT_BRANCH" --quiet 2>/dev/null || true
|
|
175
|
+
SAVED_BRANCH="$CURRENT_BRANCH"
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# Push the branch if it has unpushed commits (so work is never only local)
|
|
179
|
+
if [[ "$CURRENT_BRANCH" == dev/* ]] || [[ "$CURRENT_BRANCH" == feature/* ]] || [[ "$CURRENT_BRANCH" == bugfix/* ]]; then
|
|
180
|
+
LOCAL_HEAD=$(git rev-parse HEAD 2>/dev/null || echo "")
|
|
181
|
+
REMOTE_HEAD=$(git rev-parse "origin/$CURRENT_BRANCH" 2>/dev/null || echo "none")
|
|
182
|
+
if [ "$LOCAL_HEAD" != "$REMOTE_HEAD" ]; then
|
|
183
|
+
git push origin "$CURRENT_BRANCH" --quiet 2>/dev/null || true
|
|
184
|
+
fi
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
# Switch to develop (already updated by fetch origin develop:develop above)
|
|
188
|
+
git checkout develop --quiet 2>/dev/null || true
|
|
189
|
+
else
|
|
190
|
+
# Already on develop — fetch couldn't update it (checked-out branch), so pull
|
|
191
|
+
git merge --ff-only origin/develop --quiet 2>/dev/null || true
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
BRANCH="develop"
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# Initialize defaults used by setup_develop
|
|
198
|
+
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null || echo "")
|
|
199
|
+
DEVELOP_SYNCED="false"
|
|
200
|
+
COMMITS_AHEAD=0
|
|
201
|
+
ACTION="ready"
|
|
202
|
+
SAVED_BRANCH=""
|
|
203
|
+
BRANCH="${CURRENT_BRANCH:-develop}"
|
|
204
|
+
|
|
205
|
+
if [ "$IS_WORKTREE" = "true" ]; then
|
|
206
|
+
# Inside a worktree — skip develop checkout and framework update.
|
|
207
|
+
# Worktrees are isolated working copies; framework updates belong on develop.
|
|
208
|
+
BRANCH=$(git branch --show-current 2>/dev/null || echo "?")
|
|
209
|
+
DEVELOP_SYNCED="true"
|
|
210
|
+
|
|
211
|
+
# --- Worktree branch health check ---
|
|
212
|
+
# Detect if the branch was already merged into develop (e.g., PR merged
|
|
213
|
+
# but worktree not cleaned up). This prevents working on a stale branch
|
|
214
|
+
# whose commits are already in develop.
|
|
215
|
+
WORKTREE_STALE="false"
|
|
216
|
+
if [ "$BRANCH" != "?" ] && [ "$BRANCH" != "develop" ] && [ "$BRANCH" != "main" ]; then
|
|
217
|
+
# Check if remote branch still exists
|
|
218
|
+
if ! git ls-remote --heads origin "$BRANCH" 2>/dev/null | grep -q "$BRANCH"; then
|
|
219
|
+
# Remote branch gone — check if it was merged into develop
|
|
220
|
+
if git branch -r --merged origin/develop 2>/dev/null | grep -q "origin/$BRANCH" 2>/dev/null || \
|
|
221
|
+
git merge-base --is-ancestor HEAD origin/develop 2>/dev/null; then
|
|
222
|
+
WORKTREE_STALE="merged"
|
|
223
|
+
else
|
|
224
|
+
WORKTREE_STALE="remote_deleted"
|
|
225
|
+
fi
|
|
226
|
+
fi
|
|
227
|
+
fi
|
|
228
|
+
|
|
229
|
+
if [ "$WORKTREE_STALE" = "merged" ]; then
|
|
230
|
+
echo ""
|
|
231
|
+
echo "WARNING: Branch '$BRANCH' was already merged into develop."
|
|
232
|
+
echo "This worktree is stale — your work here is already in develop."
|
|
233
|
+
echo "Start a new session in the main project to get a fresh branch."
|
|
234
|
+
echo ""
|
|
235
|
+
HEALTH_GIT="fail"
|
|
236
|
+
elif [ "$WORKTREE_STALE" = "remote_deleted" ]; then
|
|
237
|
+
echo ""
|
|
238
|
+
echo "WARNING: Remote branch '$BRANCH' was deleted but NOT merged into develop."
|
|
239
|
+
echo "This worktree may contain unique local commits. Check before discarding:"
|
|
240
|
+
echo " git log origin/develop..HEAD --oneline"
|
|
241
|
+
echo ""
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
# Use main project's .env and state if ours are missing
|
|
245
|
+
if [ ! -f "$SCRIPT_DIR/.env" ] && [ -f "$MAIN_PROJECT_DIR/.env" ]; then
|
|
246
|
+
export ENV_FILE="$MAIN_PROJECT_DIR/.env"
|
|
247
|
+
fi
|
|
248
|
+
elif ! setup_develop 2>/dev/null; then
|
|
249
|
+
HEALTH_GIT="fail"
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
# Apply framework update now — we're on develop (or worktree skipped above)
|
|
253
|
+
if [ "$IS_WORKTREE" != "true" ]; then
|
|
254
|
+
_apply_framework_update 2>/dev/null || true
|
|
255
|
+
fi
|
|
256
|
+
|
|
257
|
+
# --- Sync memory (symlink or direct directory — both valid) ---
|
|
258
|
+
if [ -d "$SCRIPT_DIR/memory/.git" ]; then
|
|
259
|
+
MEM_LOCAL=$(git -C "$SCRIPT_DIR/memory" rev-parse HEAD 2>/dev/null || echo "")
|
|
260
|
+
MEM_REMOTE=$(git -C "$SCRIPT_DIR/memory" rev-parse origin/main 2>/dev/null || echo "")
|
|
261
|
+
if [ -n "$MEM_LOCAL" ] && [ -n "$MEM_REMOTE" ] && [ "$MEM_LOCAL" != "$MEM_REMOTE" ]; then
|
|
262
|
+
git -C "$SCRIPT_DIR/memory" pull origin main --quiet 2>/dev/null || true
|
|
263
|
+
fi
|
|
264
|
+
MEMORY_SYNCED="true"
|
|
265
|
+
fi
|
|
266
|
+
|
|
267
|
+
# --- Sync managed repos ---
|
|
268
|
+
REPOS_STATUS=""
|
|
269
|
+
for REPO in $MANAGED_REPOS; do
|
|
270
|
+
REPO_DIR="$SCRIPT_DIR/../$REPO"
|
|
271
|
+
if [ -d "$REPO_DIR/.git" ]; then
|
|
272
|
+
# Resolve base branch for this repo (from egregore.json or auto-detect)
|
|
273
|
+
REPO_BASE=$(_get_base_branch "$REPO")
|
|
274
|
+
# Sync base branch with remote (if not checked out)
|
|
275
|
+
R_BRANCH=$(git -C "$REPO_DIR" branch --show-current 2>/dev/null || echo "?")
|
|
276
|
+
if [ "$R_BRANCH" != "$REPO_BASE" ]; then
|
|
277
|
+
git -C "$REPO_DIR" branch -f "$REPO_BASE" "origin/$REPO_BASE" --quiet 2>/dev/null || true
|
|
278
|
+
else
|
|
279
|
+
git -C "$REPO_DIR" merge --ff-only "origin/$REPO_BASE" --quiet 2>/dev/null || true
|
|
280
|
+
fi
|
|
281
|
+
# Collect status
|
|
282
|
+
R_DIRTY=""
|
|
283
|
+
if [ -n "$(git -C "$REPO_DIR" status --porcelain 2>/dev/null | head -1)" ]; then
|
|
284
|
+
R_DIRTY=" *"
|
|
285
|
+
fi
|
|
286
|
+
REPOS_STATUS="${REPOS_STATUS} ◇ ${REPO}: ${R_BRANCH}${R_DIRTY}\n"
|
|
287
|
+
fi
|
|
288
|
+
done
|