create-egregore 0.19.33 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/egregore-launcher.js +118 -13
- package/bin/cli.js +19 -3
- package/lib/connect-runtime.js +4 -2
- package/lib/local.js +15 -1
- package/lib/prime-runtime.js +208 -0
- package/lib/setup.js +45 -3
- package/package.json +4 -3
- package/runtime/codex/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/spec-manifest.json +3 -3
- package/runtime/codex/AGENTS.md +11 -4
- package/runtime/codex/bin/activity-data.sh +4 -8
- package/runtime/codex/bin/attendant.sh +13 -0
- package/runtime/codex/bin/autosave.sh +27 -1
- package/runtime/codex/bin/codex-render-spec.mjs +6 -0
- package/runtime/codex/bin/codex-session-start.sh +3 -1
- package/runtime/codex/bin/graph-batch.sh +25 -6
- package/runtime/codex/bin/graph-op.sh +5 -4
- package/runtime/codex/bin/graph.sh +31 -5
- package/runtime/codex/bin/ingest.py +81 -5
- package/runtime/codex/bin/lib/context.sh +26 -1
- package/runtime/codex/bin/lib/greeting.sh +4 -1
- package/runtime/codex/bin/lib/worktree-links.sh +25 -0
- package/runtime/codex/manifest.json +7 -1
- package/runtime/pi/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/spec-manifest.json +3 -3
- package/runtime/pi/.pi/APPEND_SYSTEM.md +3 -2
- package/runtime/pi/.pi/extensions/egregore.ts +17 -6
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +11 -4
- package/runtime/pi/bin/activity-data.sh +4 -8
- package/runtime/pi/bin/attendant.sh +13 -0
- package/runtime/pi/bin/autosave.sh +27 -1
- package/runtime/pi/bin/codex-render-spec.mjs +6 -0
- package/runtime/pi/bin/codex-session-start.sh +3 -1
- package/runtime/pi/bin/graph-batch.sh +25 -6
- package/runtime/pi/bin/graph-op.sh +5 -4
- package/runtime/pi/bin/graph.sh +31 -5
- package/runtime/pi/bin/ingest.py +81 -5
- package/runtime/pi/bin/lib/context.sh +26 -1
- package/runtime/pi/bin/lib/greeting.sh +4 -1
- package/runtime/pi/bin/lib/worktree-links.sh +25 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +138 -1
- package/runtime/pi/bin/pi-product-workflows.mjs +35 -7
- package/runtime/pi/manifest.json +7 -1
- package/runtime/prime/.claude/context/notification-consent.md +66 -0
- package/runtime/prime/.codex/config.toml +17 -0
- package/runtime/prime/.codex/hooks/branch-guard.js +461 -0
- package/runtime/prime/.codex/hooks/search-hint.js +67 -0
- package/runtime/prime/.codex/hooks.json +30 -0
- package/runtime/prime/.codex/skills/activity/SKILL.md +82 -0
- package/runtime/prime/.codex/skills/announce/SKILL.md +67 -0
- package/runtime/prime/.codex/skills/archive/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/branch/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/checkup/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/commit/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/contribute/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/create-skill/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dark-mode/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/prime/.codex/skills/deep-reflect/SKILL.md +109 -0
- package/runtime/prime/.codex/skills/delete-user/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/emissary/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/handoff/SKILL.md +166 -0
- package/runtime/prime/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
- package/runtime/prime/.codex/skills/harvest/SKILL.md +131 -0
- package/runtime/prime/.codex/skills/ingest/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/invite/SKILL.md +44 -0
- package/runtime/prime/.codex/skills/issue/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/me/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/meeting/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/note/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/onboarding/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/pr/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/pull/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/push/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/quest/SKILL.md +80 -0
- package/runtime/prime/.codex/skills/reflect/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/review-pr/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/save/SKILL.md +125 -0
- package/runtime/prime/.codex/skills/slack-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/summon/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/sync-repos/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telegram-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telemetry/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/test/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/prime/.codex/skills/tui-design/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/tutorial/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/update/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/view/SKILL.md +156 -0
- package/runtime/prime/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/prime/.codex/skills/visual-explain/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/wrap/SKILL.md +58 -0
- package/runtime/prime/.codex/spec-manifest.json +132 -0
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +393 -0
- package/runtime/prime/.prime/agent/extensions/egregore.ts +460 -0
- package/runtime/prime/.prime/agent/settings.json +4 -0
- package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +34 -0
- package/runtime/prime/.prime/agent/skills/egregore/pyproject.toml +13 -0
- package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +156 -0
- package/runtime/prime/.prime/agent/spec-manifest.json +12 -0
- package/runtime/prime/AGENTS.md +489 -0
- package/runtime/prime/bin/activity-data.sh +238 -0
- package/runtime/prime/bin/agent.sh +775 -0
- package/runtime/prime/bin/attendant.sh +707 -0
- package/runtime/prime/bin/autosave.sh +112 -0
- package/runtime/prime/bin/capture-reconcile.sh +69 -0
- package/runtime/prime/bin/capture-run.sh +341 -0
- package/runtime/prime/bin/codex-install-skills.sh +78 -0
- package/runtime/prime/bin/codex-render-spec.mjs +440 -0
- package/runtime/prime/bin/codex-session-start.sh +265 -0
- package/runtime/prime/bin/codex-skill-render.mjs +347 -0
- package/runtime/prime/bin/codex-sync-skills.sh +232 -0
- package/runtime/prime/bin/connect-refresh.sh +33 -0
- package/runtime/prime/bin/dashboard-data.sh +178 -0
- package/runtime/prime/bin/graph-batch.sh +79 -0
- package/runtime/prime/bin/graph-op.sh +1102 -0
- package/runtime/prime/bin/graph-wal.sh +229 -0
- package/runtime/prime/bin/graph.sh +223 -0
- package/runtime/prime/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/prime/bin/handoff-run.sh +671 -0
- package/runtime/prime/bin/handoff-save-egregore.sh +212 -0
- package/runtime/prime/bin/index-handoff.sh +322 -0
- package/runtime/prime/bin/ingest-graph.sh +80 -0
- package/runtime/prime/bin/ingest-surface.html +495 -0
- package/runtime/prime/bin/ingest.py +756 -0
- package/runtime/prime/bin/ingest.sh +279 -0
- package/runtime/prime/bin/ingest_graph.py +856 -0
- package/runtime/prime/bin/ingest_surface.py +544 -0
- package/runtime/prime/bin/lib/artifact-id.sh +46 -0
- package/runtime/prime/bin/lib/config.sh +116 -0
- package/runtime/prime/bin/lib/context.sh +621 -0
- package/runtime/prime/bin/lib/dashboard-artifact.sh +242 -0
- package/runtime/prime/bin/lib/ensure-develop.sh +183 -0
- package/runtime/prime/bin/lib/git-sync.sh +406 -0
- package/runtime/prime/bin/lib/greeting.sh +519 -0
- package/runtime/prime/bin/lib/hash.sh +13 -0
- package/runtime/prime/bin/lib/identity.sh +213 -0
- package/runtime/prime/bin/lib/metrics.sh +374 -0
- package/runtime/prime/bin/lib/noncode.sh +31 -0
- package/runtime/prime/bin/lib/permissions.sh +106 -0
- package/runtime/prime/bin/lib/time.sh +56 -0
- package/runtime/prime/bin/lib/worktree-links.sh +79 -0
- package/runtime/prime/bin/notify.sh +636 -0
- package/runtime/prime/bin/person.py +630 -0
- package/runtime/prime/bin/person.sh +448 -0
- package/runtime/prime/bin/pi-branch-policy.mjs +312 -0
- package/runtime/prime/bin/pi-product-workflows.mjs +394 -0
- package/runtime/prime/bin/prime-render-spec.mjs +123 -0
- package/runtime/prime/bin/prime-session-start.sh +24 -0
- package/runtime/prime/bin/publish-artifact.sh +271 -0
- package/runtime/prime/bin/publish-references.sh +144 -0
- package/runtime/prime/bin/repo-state.sh +96 -0
- package/runtime/prime/bin/search.sh +240 -0
- package/runtime/prime/bin/session-autosave.sh +209 -0
- package/runtime/prime/bin/session-log.sh +199 -0
- package/runtime/prime/bin/settings.sh +304 -0
- package/runtime/prime/bin/telemetry.sh +391 -0
- package/runtime/prime/bin/worktree-create.sh +128 -0
- package/runtime/prime/bin/worktree-remove.sh +50 -0
- package/runtime/prime/bin/worktree.sh +198 -0
- package/runtime/prime/manifest.json +178 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
5
|
+
CLAUDE_DIR="$SCRIPT_DIR/.claude/skills"
|
|
6
|
+
CODEX_DIR="$SCRIPT_DIR/.codex/skills"
|
|
7
|
+
CHECK=0
|
|
8
|
+
|
|
9
|
+
NATIVE_SKILLS=(
|
|
10
|
+
activity
|
|
11
|
+
handoff
|
|
12
|
+
wrap
|
|
13
|
+
announce
|
|
14
|
+
harvest
|
|
15
|
+
the-spiral
|
|
16
|
+
dashboard
|
|
17
|
+
deep-reflect
|
|
18
|
+
quest
|
|
19
|
+
invite
|
|
20
|
+
ask
|
|
21
|
+
save
|
|
22
|
+
search
|
|
23
|
+
view
|
|
24
|
+
scroll
|
|
25
|
+
plate
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
STRUCTURED_UX_SKILLS=(
|
|
29
|
+
activity
|
|
30
|
+
dashboard
|
|
31
|
+
handoff
|
|
32
|
+
wrap
|
|
33
|
+
todo
|
|
34
|
+
quest
|
|
35
|
+
project
|
|
36
|
+
issue
|
|
37
|
+
test
|
|
38
|
+
qa
|
|
39
|
+
checkup
|
|
40
|
+
infra
|
|
41
|
+
graph-maintain
|
|
42
|
+
telemetry-admin
|
|
43
|
+
waitlist
|
|
44
|
+
hosting
|
|
45
|
+
review-pr
|
|
46
|
+
triage
|
|
47
|
+
eval
|
|
48
|
+
eval-multiagent
|
|
49
|
+
summon
|
|
50
|
+
reflect
|
|
51
|
+
deep-reflect
|
|
52
|
+
archive
|
|
53
|
+
meeting
|
|
54
|
+
ingest-user-interview
|
|
55
|
+
harvest
|
|
56
|
+
tutorial
|
|
57
|
+
onboarding
|
|
58
|
+
emissary
|
|
59
|
+
launch-site
|
|
60
|
+
view
|
|
61
|
+
scroll
|
|
62
|
+
visual-explain
|
|
63
|
+
tui-design
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
GENERATED_MARKER='generated-by: bin/codex-sync-skills.sh'
|
|
67
|
+
|
|
68
|
+
while [ $# -gt 0 ]; do
|
|
69
|
+
case "$1" in
|
|
70
|
+
--check) CHECK=1; shift ;;
|
|
71
|
+
--help|-h)
|
|
72
|
+
echo "usage: bin/codex-sync-skills.sh [--check]"
|
|
73
|
+
exit 0
|
|
74
|
+
;;
|
|
75
|
+
*) echo "unknown option: $1" >&2; exit 2 ;;
|
|
76
|
+
esac
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
is_native() {
|
|
80
|
+
local name="$1"
|
|
81
|
+
local native
|
|
82
|
+
for native in "${NATIVE_SKILLS[@]}"; do
|
|
83
|
+
[ "$name" = "$native" ] && return 0
|
|
84
|
+
done
|
|
85
|
+
return 1
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
is_structured_ux() {
|
|
89
|
+
local name="$1"
|
|
90
|
+
local structured
|
|
91
|
+
for structured in "${STRUCTURED_UX_SKILLS[@]}"; do
|
|
92
|
+
[ "$name" = "$structured" ] && return 0
|
|
93
|
+
done
|
|
94
|
+
return 1
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
skill_description() {
|
|
98
|
+
local file="$1"
|
|
99
|
+
awk '
|
|
100
|
+
NR == 1 && $0 == "---" { in_fm = 1; next }
|
|
101
|
+
in_fm && $0 == "---" { exit }
|
|
102
|
+
in_fm && /^description:/ {
|
|
103
|
+
sub(/^description:[[:space:]]*/, "")
|
|
104
|
+
gsub(/^"|"$/, "")
|
|
105
|
+
print
|
|
106
|
+
exit
|
|
107
|
+
}
|
|
108
|
+
' "$file"
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
yaml_single_quote() {
|
|
112
|
+
local value="$1"
|
|
113
|
+
printf "'%s'" "$(printf '%s' "$value" | sed "s/'/''/g")"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
render_adapter() {
|
|
117
|
+
local name="$1"
|
|
118
|
+
local source="$2"
|
|
119
|
+
local description="$3"
|
|
120
|
+
local structured="$4"
|
|
121
|
+
[ -n "$description" ] || description="Fallback Codex adapter for the Egregore ${name} workflow."
|
|
122
|
+
local description_yaml
|
|
123
|
+
description_yaml="$(yaml_single_quote "$description")"
|
|
124
|
+
cat <<EOF
|
|
125
|
+
---
|
|
126
|
+
name: ${name}
|
|
127
|
+
description: ${description_yaml}
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
<!-- ${GENERATED_MARKER} -->
|
|
131
|
+
|
|
132
|
+
# Egregore ${name} Adapter
|
|
133
|
+
|
|
134
|
+
This is fallback coverage for a long-tail Egregore workflow that has not been
|
|
135
|
+
ported to a hand-written Codex-native skill yet.
|
|
136
|
+
|
|
137
|
+
Use the project shell and filesystem directly. Do not invoke Claude Code
|
|
138
|
+
commands. Translate interactive choices to structured Codex question tooling
|
|
139
|
+
when it is available; otherwise render compact numbered choices with an
|
|
140
|
+
\`Other:\` option and wait for the user.
|
|
141
|
+
|
|
142
|
+
EOF
|
|
143
|
+
if [ "$structured" = "1" ]; then
|
|
144
|
+
cat <<EOF
|
|
145
|
+
## Structured UX parity
|
|
146
|
+
|
|
147
|
+
This workflow has a Claude skill with user-visible structured output. After
|
|
148
|
+
reading \`${source}\`, reproduce the same visible UX in Codex:
|
|
149
|
+
|
|
150
|
+
- Preserve TUI boxes, markdown tables, rich cards, browser artifact rendering,
|
|
151
|
+
exact confirmation blocks, and "no preamble" rules from the source skill.
|
|
152
|
+
- Use the source skill's frame width, section order, labels, status footer,
|
|
153
|
+
and examples as the contract for the final response.
|
|
154
|
+
- Never replace a required box/table/card/artifact view with a prose summary
|
|
155
|
+
unless the user explicitly asks for a summary.
|
|
156
|
+
- When the source says to output a TUI box directly, paste that box as the
|
|
157
|
+
visible response, preferably in a \`text\` fenced block.
|
|
158
|
+
- Never show raw JSON, raw command output, or unformatted script output when
|
|
159
|
+
the source skill requires formatted status or rendered output.
|
|
160
|
+
|
|
161
|
+
EOF
|
|
162
|
+
fi
|
|
163
|
+
cat <<EOF
|
|
164
|
+
1. Read \`${source}\` for the workflow details.
|
|
165
|
+
2. Run the referenced \`bin/\` scripts directly from Codex.
|
|
166
|
+
3. Treat graph and publish steps as best-effort unless that workflow explicitly
|
|
167
|
+
says they are required.
|
|
168
|
+
4. For every external notification, follow
|
|
169
|
+
\`.claude/context/notification-consent.md\`: plan without sending, then show
|
|
170
|
+
a separate exact Send / Edit / Cancel checkpoint. Never infer notification
|
|
171
|
+
consent from the workflow request or a batch approval.
|
|
172
|
+
5. Keep local-mode behavior filesystem-first and avoid graph or notification
|
|
173
|
+
calls when \`egregore.json\` declares \`"mode": "local"\`.
|
|
174
|
+
6. Never call the deprecated \`egregore-handoff\` CLI for Egregore project
|
|
175
|
+
handoffs.
|
|
176
|
+
EOF
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
[ -d "$CLAUDE_DIR" ] || { echo "missing Claude skills directory: $CLAUDE_DIR" >&2; exit 1; }
|
|
180
|
+
mkdir -p "$CODEX_DIR"
|
|
181
|
+
|
|
182
|
+
changed=0
|
|
183
|
+
native_present=0
|
|
184
|
+
adapter_present=0
|
|
185
|
+
|
|
186
|
+
for native in "${NATIVE_SKILLS[@]}"; do
|
|
187
|
+
if [ -f "$CODEX_DIR/$native/SKILL.md" ]; then
|
|
188
|
+
native_present=$((native_present + 1))
|
|
189
|
+
else
|
|
190
|
+
echo "missing native Codex skill: $native" >&2
|
|
191
|
+
changed=1
|
|
192
|
+
fi
|
|
193
|
+
done
|
|
194
|
+
|
|
195
|
+
while IFS= read -r source_file; do
|
|
196
|
+
name="$(basename "$(dirname "$source_file")")"
|
|
197
|
+
is_native "$name" && continue
|
|
198
|
+
|
|
199
|
+
target_dir="$CODEX_DIR/$name"
|
|
200
|
+
target_file="$target_dir/SKILL.md"
|
|
201
|
+
if [ -f "$target_file" ] && ! grep -q "$GENERATED_MARKER" "$target_file" 2>/dev/null; then
|
|
202
|
+
continue
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
description="$(skill_description "$source_file")"
|
|
206
|
+
rel_source=".claude/skills/$name/SKILL.md"
|
|
207
|
+
structured=0
|
|
208
|
+
is_structured_ux "$name" && structured=1
|
|
209
|
+
tmp="$(mktemp -t codex-skill-adapter-XXXXXX)"
|
|
210
|
+
render_adapter "$name" "$rel_source" "$description" "$structured" > "$tmp"
|
|
211
|
+
|
|
212
|
+
if [ ! -f "$target_file" ] || ! cmp -s "$tmp" "$target_file"; then
|
|
213
|
+
changed=1
|
|
214
|
+
if [ "$CHECK" = "1" ]; then
|
|
215
|
+
echo "adapter out of date: $name"
|
|
216
|
+
else
|
|
217
|
+
mkdir -p "$target_dir"
|
|
218
|
+
cp "$tmp" "$target_file"
|
|
219
|
+
echo "generated adapter: $name"
|
|
220
|
+
fi
|
|
221
|
+
fi
|
|
222
|
+
rm -f "$tmp"
|
|
223
|
+
done < <(find "$CLAUDE_DIR" -mindepth 2 -maxdepth 2 -name SKILL.md | sort)
|
|
224
|
+
|
|
225
|
+
adapter_present="$({ grep -rl "$GENERATED_MARKER" "$CODEX_DIR"/*/SKILL.md 2>/dev/null || true; } | wc -l | tr -d ' ')"
|
|
226
|
+
|
|
227
|
+
if [ "$CHECK" = "1" ] && [ "$changed" -ne 0 ]; then
|
|
228
|
+
echo "codex skills out of sync (native: $native_present/${#NATIVE_SKILLS[@]}, adapters: $adapter_present)" >&2
|
|
229
|
+
exit 1
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
echo "codex skills synced (native: $native_present/${#NATIVE_SKILLS[@]}, adapters: $adapter_present)"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Refresh the Connect runtime overlay (skills served by the org's API) for
|
|
3
|
+
# this instance. Fired fire-and-forget from session start on every runtime;
|
|
4
|
+
# local-mode instances exit immediately and nothing here may block or break
|
|
5
|
+
# a session. New Connect features appear without re-running the launcher.
|
|
6
|
+
set -u
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
10
|
+
cd "$ROOT" || exit 0
|
|
11
|
+
|
|
12
|
+
# Connected instances only — resolved the same way the runtime does.
|
|
13
|
+
MODE=$(jq -r '.mode // empty' egregore.json 2>/dev/null)
|
|
14
|
+
API_URL=$(jq -r '.api_url // empty' egregore.json 2>/dev/null)
|
|
15
|
+
if [ "$MODE" != "connected" ] && [ -z "$API_URL" ]; then
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
LOG_DIR="$ROOT/.egregore"
|
|
20
|
+
mkdir -p "$LOG_DIR" 2>/dev/null || true
|
|
21
|
+
LOG="$LOG_DIR/connect-refresh.log"
|
|
22
|
+
|
|
23
|
+
# The refresh logic lives in the installed create-egregore tooling (client
|
|
24
|
+
# instances do not carry packages/ in their tree). --prefer-offline keeps the
|
|
25
|
+
# common case fast; the first run may fetch the package once.
|
|
26
|
+
{
|
|
27
|
+
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] connect refresh"
|
|
28
|
+
npx --yes --prefer-offline create-egregore --refresh-connect 2>&1
|
|
29
|
+
} >>"$LOG" 2>&1 || true
|
|
30
|
+
|
|
31
|
+
# Keep the log bounded.
|
|
32
|
+
tail -n 200 "$LOG" >"$LOG.tmp" 2>/dev/null && mv "$LOG.tmp" "$LOG" 2>/dev/null || true
|
|
33
|
+
exit 0
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Fetches personal dashboard data: single API call + parallel git ops.
|
|
3
|
+
# Usage: bash bin/dashboard-data.sh [username] [time_range]
|
|
4
|
+
# Returns a single JSON object with all query results.
|
|
5
|
+
#
|
|
6
|
+
# time_range: P1D (today), P7D (week, default), P30D (month), P365D (all)
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
10
|
+
TMPDIR=$(mktemp -d)
|
|
11
|
+
trap "rm -rf $TMPDIR" EXIT
|
|
12
|
+
|
|
13
|
+
# --- Read config ---
|
|
14
|
+
API_URL=$(jq -r '.api_url // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
|
|
15
|
+
API_KEY=$(grep '^EGREGORE_API_KEY=' "$SCRIPT_DIR/.env" 2>/dev/null | cut -d'=' -f2- || true)
|
|
16
|
+
ORG=$(jq -r '.org_name // "Egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || echo "Egregore")
|
|
17
|
+
DATE=$(date '+%b %d')
|
|
18
|
+
|
|
19
|
+
# --- Detect user ---
|
|
20
|
+
GH_USER="${1:-}"
|
|
21
|
+
if [ -z "$GH_USER" ]; then
|
|
22
|
+
STATE_FILE="$SCRIPT_DIR/.egregore-state.json"
|
|
23
|
+
if [ -f "$STATE_FILE" ]; then
|
|
24
|
+
GH_USER=$(jq -r '.github_username // empty' "$STATE_FILE" 2>/dev/null)
|
|
25
|
+
fi
|
|
26
|
+
if [ -z "$GH_USER" ]; then
|
|
27
|
+
GH_USER=$(git -C "$SCRIPT_DIR" config user.name 2>/dev/null || echo "unknown")
|
|
28
|
+
fi
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# --- Time range (default P7D) ---
|
|
32
|
+
TIME_RANGE="${2:-P7D}"
|
|
33
|
+
|
|
34
|
+
# --- Read current session ID (client-side fallback for WAL-not-yet-drained) ---
|
|
35
|
+
PROJ_HASH=$(echo -n "$SCRIPT_DIR" | md5 2>/dev/null || echo -n "$SCRIPT_DIR" | md5sum 2>/dev/null | cut -d' ' -f1)
|
|
36
|
+
SESSION_ID=$(cat "$HOME/.egregore/session-${PROJ_HASH}.id" 2>/dev/null || echo "")
|
|
37
|
+
|
|
38
|
+
# --- Fire API call + git ops in parallel ---
|
|
39
|
+
|
|
40
|
+
# Graph data: single API call (all queries run server-side)
|
|
41
|
+
(
|
|
42
|
+
GRAPH_STATUS="offline"
|
|
43
|
+
GRAPH_REASON=""
|
|
44
|
+
if [ -z "$API_URL" ] || [ -z "$API_KEY" ]; then
|
|
45
|
+
GRAPH_REASON="missing_config"
|
|
46
|
+
else
|
|
47
|
+
# Keep curl's transport status separate from %{http_code}; otherwise a
|
|
48
|
+
# failed request can concatenate 000 + fallback text and look like an
|
|
49
|
+
# unexpected API response.
|
|
50
|
+
CURL_STATUS=0
|
|
51
|
+
HTTP_CODE=$(curl -s -o "$TMPDIR/dashboard_raw.json" -w "%{http_code}" \
|
|
52
|
+
"${API_URL}/api/personal/dashboard?github_username=$(printf '%s' "$GH_USER" | jq -sRr @uri)&time_range=$(printf '%s' "$TIME_RANGE" | jq -sRr @uri)&session_id=$(printf '%s' "$SESSION_ID" | jq -sRr @uri)" \
|
|
53
|
+
-H "Authorization: Bearer $API_KEY" \
|
|
54
|
+
--connect-timeout 5 --max-time 15 2>/dev/null) || CURL_STATUS=$?
|
|
55
|
+
|
|
56
|
+
if [ "$CURL_STATUS" -ne 0 ] || [ "$HTTP_CODE" = "000" ] || ! [[ "$HTTP_CODE" =~ ^[0-9][0-9][0-9]$ ]]; then
|
|
57
|
+
GRAPH_REASON="unreachable"
|
|
58
|
+
elif [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "403" ]; then
|
|
59
|
+
GRAPH_REASON="auth_error"
|
|
60
|
+
elif [ "$HTTP_CODE" -ge 500 ] 2>/dev/null; then
|
|
61
|
+
GRAPH_REASON="server_error"
|
|
62
|
+
elif [ -s "$TMPDIR/dashboard_raw.json" ] && jq -e '.me' "$TMPDIR/dashboard_raw.json" >/dev/null 2>&1; then
|
|
63
|
+
cp "$TMPDIR/dashboard_raw.json" "$TMPDIR/dashboard.json"
|
|
64
|
+
GRAPH_STATUS="connected"
|
|
65
|
+
else
|
|
66
|
+
GRAPH_REASON="invalid_response"
|
|
67
|
+
fi
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# If not connected, write status-only response
|
|
71
|
+
if [ "$GRAPH_STATUS" != "connected" ]; then
|
|
72
|
+
jq -n --arg status "$GRAPH_STATUS" --arg reason "$GRAPH_REASON" \
|
|
73
|
+
'{graph_status: $status, graph_reason: $reason}' > "$TMPDIR/dashboard.json"
|
|
74
|
+
else
|
|
75
|
+
jq --arg status "$GRAPH_STATUS" '. + {graph_status: $status}' \
|
|
76
|
+
"$TMPDIR/dashboard.json" > "$TMPDIR/dashboard_merged.json" \
|
|
77
|
+
&& mv "$TMPDIR/dashboard_merged.json" "$TMPDIR/dashboard.json"
|
|
78
|
+
fi
|
|
79
|
+
) &
|
|
80
|
+
API_PID=$!
|
|
81
|
+
|
|
82
|
+
# Git: branch + dirty status (parallel, stays client-side)
|
|
83
|
+
(
|
|
84
|
+
CURRENT=$(git -C "$SCRIPT_DIR" branch --show-current 2>/dev/null || echo "unknown")
|
|
85
|
+
DIRTY="false"
|
|
86
|
+
if [ -n "$(git -C "$SCRIPT_DIR" status --porcelain 2>/dev/null | head -1)" ]; then
|
|
87
|
+
DIRTY="true"
|
|
88
|
+
fi
|
|
89
|
+
jq -n --arg branch "$CURRENT" --argjson dirty "$DIRTY" \
|
|
90
|
+
'{branch: $branch, dirty: $dirty}' > "$TMPDIR/git.json"
|
|
91
|
+
) &
|
|
92
|
+
GIT_PID=$!
|
|
93
|
+
|
|
94
|
+
# Local sessions: parse memory files when graph is offline (parallel)
|
|
95
|
+
(
|
|
96
|
+
GH_LC=$(echo "$GH_USER" | tr '[:upper:]' '[:lower:]')
|
|
97
|
+
DISPLAY_LC=""
|
|
98
|
+
if [ -f "$SCRIPT_DIR/.egregore-state.json" ]; then
|
|
99
|
+
DISPLAY_LC=$(jq -r '.display_name // empty' "$SCRIPT_DIR/.egregore-state.json" 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Compute cutoff date from time range
|
|
103
|
+
case "$TIME_RANGE" in
|
|
104
|
+
P1D) CUTOFF=$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d '1 day ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
105
|
+
P7D) CUTOFF=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
106
|
+
P30D) CUTOFF=$(date -v-30d +%Y-%m-%d 2>/dev/null || date -d '30 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
107
|
+
P365D) CUTOFF="2000-01-01" ;;
|
|
108
|
+
*) CUTOFF=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null || echo "2000-01-01") ;;
|
|
109
|
+
esac
|
|
110
|
+
|
|
111
|
+
# Scan sessions, wraps, and handoffs for this user
|
|
112
|
+
for DIR in "$SCRIPT_DIR/memory/sessions" "$SCRIPT_DIR/memory/wraps" "$SCRIPT_DIR/memory/handoffs"; do
|
|
113
|
+
[ -d "$DIR" ] || continue
|
|
114
|
+
TYPE=$(basename "$DIR")
|
|
115
|
+
find -L "$DIR" -name '*.md' -not -name 'index*' -type f 2>/dev/null | xargs ls -t 2>/dev/null | head -20 | while read -r MFILE; do
|
|
116
|
+
[ -z "$MFILE" ] && continue
|
|
117
|
+
M_AUTH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Author\*\*:' | sed 's/^\*\*Author\*\*:[[:space:]]*//' || true)
|
|
118
|
+
[ -z "$M_AUTH" ] && continue
|
|
119
|
+
M_AUTH_LC=$(echo "$M_AUTH" | tr '[:upper:]' '[:lower:]')
|
|
120
|
+
# Filter to this user only
|
|
121
|
+
[ "$M_AUTH_LC" != "$GH_LC" ] && { [ -z "$DISPLAY_LC" ] || [ "$M_AUTH_LC" != "$DISPLAY_LC" ]; } && continue
|
|
122
|
+
M_DATE=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Date\*\*:' | sed 's/^\*\*Date\*\*:[[:space:]]*//' || true)
|
|
123
|
+
M_DAY="${M_DATE%%T*}"
|
|
124
|
+
[ -n "$M_DAY" ] && [ "$M_DAY" \< "$CUTOFF" ] && continue
|
|
125
|
+
M_BRANCH=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Branch\*\*:' | sed 's/^\*\*Branch\*\*:[[:space:]]*//' || true)
|
|
126
|
+
M_DURATION=$(head -10 "$MFILE" 2>/dev/null | grep -m1 '^\*\*Duration\*\*:' | sed 's/^\*\*Duration\*\*:[[:space:]]*//' || true)
|
|
127
|
+
M_TOPIC=$(head -3 "$MFILE" 2>/dev/null | grep -m1 '^# ' | sed 's/^# [^:]*:[[:space:]]*//' || true)
|
|
128
|
+
echo "${M_DATE}|${M_TOPIC}|${M_BRANCH}|${M_DURATION}|${TYPE}"
|
|
129
|
+
done
|
|
130
|
+
done | jq -Rn '
|
|
131
|
+
[inputs | split("|") |
|
|
132
|
+
{date: .[0], topic: .[1], branch: .[2], duration: .[3], type: .[4]}
|
|
133
|
+
] | sort_by(.date) | reverse | {
|
|
134
|
+
sessions: .,
|
|
135
|
+
session_count: length
|
|
136
|
+
}
|
|
137
|
+
' 2>/dev/null > "$TMPDIR/local_sessions.json" || echo '{"sessions":[],"session_count":0}' > "$TMPDIR/local_sessions.json"
|
|
138
|
+
) &
|
|
139
|
+
LOCAL_PID=$!
|
|
140
|
+
|
|
141
|
+
# --- Wait for all ---
|
|
142
|
+
wait $API_PID $GIT_PID $LOCAL_PID 2>/dev/null || true
|
|
143
|
+
|
|
144
|
+
# --- Read results ---
|
|
145
|
+
GIT_INFO=$(cat "$TMPDIR/git.json" 2>/dev/null || echo '{"branch":"unknown","dirty":false}')
|
|
146
|
+
BRANCH=$(echo "$GIT_INFO" | jq -r '.branch' 2>/dev/null || echo "unknown")
|
|
147
|
+
LOCAL_SESSIONS=$(cat "$TMPDIR/local_sessions.json" 2>/dev/null || echo '{"sessions":[],"session_count":0}')
|
|
148
|
+
echo "$LOCAL_SESSIONS" | jq . >/dev/null 2>&1 || LOCAL_SESSIONS='{"sessions":[],"session_count":0}'
|
|
149
|
+
|
|
150
|
+
# --- Client-side current session fallback ---
|
|
151
|
+
# If the graph returned no current_session (WAL hasn't drained yet),
|
|
152
|
+
# inject one from the local session ID file so the TUI always renders it.
|
|
153
|
+
DASHBOARD=$(cat "$TMPDIR/dashboard.json" 2>/dev/null || echo '{"graph_status":"offline"}')
|
|
154
|
+
CS_ID=$(echo "$DASHBOARD" | jq -r '.current_session.id // empty' 2>/dev/null)
|
|
155
|
+
if [ -z "$CS_ID" ] && [ -n "$SESSION_ID" ]; then
|
|
156
|
+
DASHBOARD=$(echo "$DASHBOARD" | jq \
|
|
157
|
+
--arg sid "$SESSION_ID" \
|
|
158
|
+
--arg branch "$BRANCH" \
|
|
159
|
+
'.current_session = {id: $sid, status: "active", topic: null, branch: $branch}' 2>/dev/null || echo "$DASHBOARD")
|
|
160
|
+
fi
|
|
161
|
+
|
|
162
|
+
# --- Derive time range label ---
|
|
163
|
+
case "$TIME_RANGE" in
|
|
164
|
+
P1D) RANGE_LABEL="today" ;;
|
|
165
|
+
P7D) RANGE_LABEL="last 7 days" ;;
|
|
166
|
+
P30D) RANGE_LABEL="last 30 days" ;;
|
|
167
|
+
P365D) RANGE_LABEL="all time" ;;
|
|
168
|
+
*) RANGE_LABEL="last 7 days" ;;
|
|
169
|
+
esac
|
|
170
|
+
|
|
171
|
+
# --- Merge server response + local data ---
|
|
172
|
+
echo "$DASHBOARD" | jq \
|
|
173
|
+
--arg org "$ORG" \
|
|
174
|
+
--arg date "$DATE" \
|
|
175
|
+
--arg range_label "$RANGE_LABEL" \
|
|
176
|
+
--argjson git "$GIT_INFO" \
|
|
177
|
+
--argjson local_sessions "$LOCAL_SESSIONS" \
|
|
178
|
+
'. + {org: $org, date: $date, range_label: $range_label, git: $git, local_sessions: $local_sessions}'
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Execute multiple Cypher queries in a single HTTP call.
|
|
5
|
+
# Usage: graph-batch.sh '<json array of {statement, parameters} objects>'
|
|
6
|
+
#
|
|
7
|
+
# Example:
|
|
8
|
+
# graph-batch.sh '[{"statement":"MATCH (p:Person) RETURN p.name"},{"statement":"MATCH (q:Quest) RETURN q.id"}]'
|
|
9
|
+
#
|
|
10
|
+
# Returns: {"results": [{...}, {...}]}
|
|
11
|
+
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
13
|
+
CONFIG="$SCRIPT_DIR/egregore.json"
|
|
14
|
+
|
|
15
|
+
if [ ! -f "$CONFIG" ]; then
|
|
16
|
+
echo "Error: egregore.json not found. Run onboarding first." >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# --- Local mode gate: bail immediately ---
|
|
21
|
+
_MODE=$(jq -r '.mode // "connected"' "$CONFIG" 2>/dev/null)
|
|
22
|
+
if [ "$_MODE" = "local" ]; then
|
|
23
|
+
echo '{"results":[]}'
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Load specific variables from .env if it exists (safe extraction, no arbitrary code execution).
|
|
28
|
+
# A worktree missing its .env symlink resolves through worktree-links.sh, which
|
|
29
|
+
# self-heals the link and falls back to the main checkout's .env.
|
|
30
|
+
_ENV_FILE="$SCRIPT_DIR/.env"
|
|
31
|
+
if [ ! -f "$_ENV_FILE" ] && [ -f "$SCRIPT_DIR/bin/lib/worktree-links.sh" ]; then
|
|
32
|
+
# shellcheck source=bin/lib/worktree-links.sh
|
|
33
|
+
source "$SCRIPT_DIR/bin/lib/worktree-links.sh" 2>/dev/null || true
|
|
34
|
+
_ENV_FILE="$(egregore_env_file "$SCRIPT_DIR" 2>/dev/null || true)"
|
|
35
|
+
fi
|
|
36
|
+
if [ -n "$_ENV_FILE" ] && [ -f "$_ENV_FILE" ]; then
|
|
37
|
+
EGREGORE_API_URL="${EGREGORE_API_URL:-$(grep '^EGREGORE_API_URL=' "$_ENV_FILE" 2>/dev/null | cut -d'=' -f2- || true)}"
|
|
38
|
+
EGREGORE_API_KEY="${EGREGORE_API_KEY:-$(grep '^EGREGORE_API_KEY=' "$_ENV_FILE" 2>/dev/null | cut -d'=' -f2- || true)}"
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
API_URL="${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG")}"
|
|
42
|
+
API_KEY="${EGREGORE_API_KEY:-}"
|
|
43
|
+
|
|
44
|
+
if [ -z "$API_URL" ]; then
|
|
45
|
+
# === OFFLINE MODE: no api_url configured (OSS/unconfigured) ===
|
|
46
|
+
echo '{"results":[]}'
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
if [ -z "$API_KEY" ]; then
|
|
51
|
+
# api_url is configured but no key was found — the local-mode gate exited
|
|
52
|
+
# above, so the org expects a live graph. Faking empty results here hides a
|
|
53
|
+
# missing .env (e.g. a worktree without its symlink) from every caller.
|
|
54
|
+
{
|
|
55
|
+
echo "Error: api_url is configured but EGREGORE_API_KEY is empty (looked in: ${_ENV_FILE:-$SCRIPT_DIR/.env})."
|
|
56
|
+
echo " If this is a worktree, its .env symlink may be missing. Run /env to configure."
|
|
57
|
+
} >&2
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
QUERIES_JSON="${1:?Usage: graph-batch.sh '<json array of queries>'}"
|
|
62
|
+
|
|
63
|
+
# Wrap the array into the batch request format
|
|
64
|
+
BODY=$(jq -n --argjson queries "$QUERIES_JSON" '{queries: $queries}')
|
|
65
|
+
|
|
66
|
+
RESPONSE=$(curl -s -X POST "${API_URL}/api/graph/batch" \
|
|
67
|
+
-H "Authorization: Bearer $API_KEY" \
|
|
68
|
+
-H "Content-Type: application/json" \
|
|
69
|
+
-d "$BODY" \
|
|
70
|
+
--max-time 60)
|
|
71
|
+
|
|
72
|
+
# Check for HTTP-level errors
|
|
73
|
+
if echo "$RESPONSE" | jq -e '.detail' >/dev/null 2>&1; then
|
|
74
|
+
echo "API error:" >&2
|
|
75
|
+
echo "$RESPONSE" | jq '.detail' >&2
|
|
76
|
+
exit 1
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
echo "$RESPONSE"
|