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
|
@@ -28,6 +28,8 @@ Runtime-neutral commands:
|
|
|
28
28
|
protocol Print the portable agent protocol
|
|
29
29
|
sync Pull latest shared memory
|
|
30
30
|
activity [--for <person>] Show recent handoffs and questions
|
|
31
|
+
search "query" [-n N] [--fast|--semantic]
|
|
32
|
+
Hybrid recall over shared memory (qmd)
|
|
31
33
|
people List known people from memory/people
|
|
32
34
|
branch --topic TEXT Create or reuse a task branch/worktree
|
|
33
35
|
save [--message TEXT] Commit and push current repo + memory changes
|
|
@@ -165,8 +167,9 @@ Egregore portable agent protocol
|
|
|
165
167
|
4. Use `bin/agent.sh handoff` to leave structured context for another agent.
|
|
166
168
|
5. Use `bin/agent.sh ask` and `bin/agent.sh answer` for asynchronous questions.
|
|
167
169
|
6. Run `bin/agent.sh activity --for <person>` to see pending work.
|
|
168
|
-
7. Run `bin/agent.sh
|
|
169
|
-
8. Run `bin/agent.sh
|
|
170
|
+
7. Run `bin/agent.sh search "<query>"` to recall shared memory (decisions, handoffs, knowledge) before answering questions about past work.
|
|
171
|
+
8. Run `bin/agent.sh branch --topic "<what you are working on>"` before code changes when you need a task branch/worktree.
|
|
172
|
+
9. Run `bin/agent.sh save` and `bin/agent.sh wrap` for portable save/wrap flows.
|
|
170
173
|
|
|
171
174
|
This protocol is runtime-neutral. Claude Code may still use .claude hooks and
|
|
172
175
|
skills, while Codex or another agent can call this script directly.
|
|
@@ -653,11 +656,16 @@ cmd_answer() {
|
|
|
653
656
|
echo "answered: memory/$rel"
|
|
654
657
|
}
|
|
655
658
|
|
|
659
|
+
cmd_search() {
|
|
660
|
+
bash "$SCRIPT_DIR/bin/search.sh" query "$@"
|
|
661
|
+
}
|
|
662
|
+
|
|
656
663
|
case "${1:-}" in
|
|
657
664
|
--help|-h|help|"") usage ;;
|
|
658
665
|
protocol) shift; cmd_protocol "$@" ;;
|
|
659
666
|
sync) shift; cmd_sync "$@" ;;
|
|
660
667
|
activity) shift; cmd_activity "$@" ;;
|
|
668
|
+
search) shift; cmd_search "$@" ;;
|
|
661
669
|
people) shift; cmd_people "$@" ;;
|
|
662
670
|
branch) shift; cmd_branch "$@" ;;
|
|
663
671
|
save) shift; cmd_save "$@" ;;
|
|
@@ -71,7 +71,7 @@ for skill_dir in "$SOURCE_DIR"/*; do
|
|
|
71
71
|
[ -f "$skill_dir/SKILL.md" ] || continue
|
|
72
72
|
name="$(basename "$skill_dir")"
|
|
73
73
|
mkdir -p "$TARGET_DIR/$name"
|
|
74
|
-
cp "$skill_dir
|
|
74
|
+
cp -R "$skill_dir/." "$TARGET_DIR/$name/"
|
|
75
75
|
copied=$((copied + 1))
|
|
76
76
|
done
|
|
77
77
|
|
|
@@ -53,6 +53,11 @@ const AGENTS_PREAMBLE = `# Egregore Agent Protocol
|
|
|
53
53
|
> Egregore skill already covers. This file exists only for runtimes that cannot
|
|
54
54
|
> read \`CLAUDE.md\`.
|
|
55
55
|
>
|
|
56
|
+
> **If you are Pi** (the \`pi\` coding-agent harness): **stop here.** Your
|
|
57
|
+
> authoritative Egregore instructions are loaded from
|
|
58
|
+
> \`.pi/APPEND_SYSTEM.md\`, and your workflows are exposed through the
|
|
59
|
+
> project-local \`.pi/\` runtime. Do not follow the Codex-specific block below.
|
|
60
|
+
>
|
|
56
61
|
> **If you are Codex or another shell-only agent:** this file is yours — continue.
|
|
57
62
|
|
|
58
63
|
Egregore is no longer only a Claude Code workspace. Claude Code remains the
|
|
@@ -73,6 +78,12 @@ portable memory protocol below.
|
|
|
73
78
|
Use the runtime-neutral bridge instead of Claude Code slash commands:
|
|
74
79
|
|
|
75
80
|
\`\`\`bash
|
|
81
|
+
bin/agent.sh branch --topic "auth review"
|
|
82
|
+
bin/agent.sh save --message "Save: auth review" --topic "auth review"
|
|
83
|
+
bin/agent.sh wrap --from alice --topic "auth review" \\
|
|
84
|
+
--summary "Implemented the OAuth callback parser and documented follow-ups." \\
|
|
85
|
+
--body "Open threads: review error cases and browser redirects."
|
|
86
|
+
|
|
76
87
|
bin/agent.sh handoff --from alice --to bob --topic "auth review" \\
|
|
77
88
|
--body "Implemented the OAuth callback parser. Bob should review error cases."
|
|
78
89
|
|
|
@@ -88,6 +99,17 @@ Each command writes to the existing Git-backed \`memory/\` repository and pushes
|
|
|
88
99
|
when the memory repo has an \`origin\` remote. Agents that cannot run shell may
|
|
89
100
|
write the same markdown files directly, following \`docs/AGENT-PROTOCOL.md\`.
|
|
90
101
|
|
|
102
|
+
## Handoffs vs Emissaries
|
|
103
|
+
|
|
104
|
+
\`bin/agent.sh handoff\` is the runtime-neutral path for internal team
|
|
105
|
+
session-handoffs: it writes to \`memory/handoffs/\`, updates the index, and uses
|
|
106
|
+
the same \`bin/handoff-run.sh\` machinery as Claude Code's \`/handoff\`.
|
|
107
|
+
|
|
108
|
+
Portable external capsules are **emissaries**, not team handoffs. Claude Code
|
|
109
|
+
routes those through \`/emissary\`; non-Claude agents should use the
|
|
110
|
+
\`egregore-emissary\` CLI/skill when it is installed. Do not use the deprecated
|
|
111
|
+
\`egregore-handoff\` CLI for Egregore project \`/handoff\` work.
|
|
112
|
+
|
|
91
113
|
## Compatibility
|
|
92
114
|
|
|
93
115
|
Claude Code users continue using \`/handoff\`, \`/activity\`, \`/ask\`, \`/save\`, and
|
|
@@ -152,7 +174,7 @@ const INTRO_BODY = `You are a collaborator inside Egregore — a shared intellig
|
|
|
152
174
|
|
|
153
175
|
This block is the Codex-native Egregore behavioral spec, rendered from CLAUDE.md (the source of truth for egregore behavior) by \`bin/codex-render-spec.mjs\`. The per-section adaptation manifest is \`.codex/spec-manifest.json\`. The thin agent protocol above this block applies to every shell-capable agent; this block is the full behavioral contract for Codex sessions.`;
|
|
154
176
|
|
|
155
|
-
const ON_LAUNCH_BODY = `The \`egregore\` launcher renders the Egregore startup card (identity,
|
|
177
|
+
const ON_LAUNCH_BODY = `The \`egregore\` launcher renders the Egregore startup card (identity, team momentum, and pending work) via \`bin/codex-session-start.sh\` before Codex starts, and installs project skills. Do not rerun startup checks and do not narrate startup. The card ends with **"What are you working on?"** — that question is already on screen; treat the user's first message as the answer to it. To re-show the card, run \`bash bin/codex-session-start.sh --card\`.`;
|
|
156
178
|
|
|
157
179
|
const AFTER_GREETING_BODY = `**Mandatory behavioral rule.** When the user describes work, your **first action** — before reading files, exploring code, or anything else — is to get onto a working branch:
|
|
158
180
|
|
|
@@ -216,7 +238,7 @@ If this Codex build does not support hooks, follow the same discipline as a stan
|
|
|
216
238
|
|
|
217
239
|
If the startup card output contains \`onboarding_needed\`, invoke the \`$onboarding\` skill instead of greeting.`;
|
|
218
240
|
|
|
219
|
-
const COMMAND_AWARENESS_PREPEND = `Codex reserves leading \`/\` for built-ins, so Egregore workflows are **skills**, not slash commands. Invoke them with the matching \`$name\` skill token or from natural language intent ("show activity", "make a handoff"). Hand-written native Codex skills: \`$activity\`, \`$handoff\`, \`$wrap\`, \`$announce\`, \`$harvest\`, \`$the-spiral\`, \`$dashboard\`, \`$deep-reflect\`, \`$quest\`, \`$invite\`, \`$ask\`, \`$save\`. Every other workflow has a generated adapter skill of the same name. \`$save\` is the user-facing abstraction for committing, pushing, opening or reusing pull requests, and syncing memory — never make users manage the git workflow by hand.`;
|
|
241
|
+
const COMMAND_AWARENESS_PREPEND = `Codex reserves leading \`/\` for built-ins, so Egregore workflows are **skills**, not slash commands. Invoke them with the matching \`$name\` skill token or from natural language intent ("show activity", "make a handoff"). Hand-written native Codex skills: \`$activity\`, \`$handoff\`, \`$wrap\`, \`$announce\`, \`$harvest\`, \`$the-spiral\`, \`$dashboard\`, \`$deep-reflect\`, \`$quest\`, \`$invite\`, \`$ask\`, \`$save\`, \`$view\`, and \`$scroll\`. Every other workflow has a generated adapter skill of the same name. \`$save\` is the user-facing abstraction for committing, pushing, opening or reusing pull requests, and syncing memory — never make users manage the git workflow by hand.`;
|
|
220
242
|
|
|
221
243
|
const SOCRATIC_BODY = `**Triggers**: "ask me questions", "question me", "help me think through", or any request to be questioned.
|
|
222
244
|
|
|
@@ -6,7 +6,7 @@ set -o pipefail
|
|
|
6
6
|
# libraries as Claude's SessionStart, then renders a terminal greeting before
|
|
7
7
|
# Codex itself starts.
|
|
8
8
|
|
|
9
|
-
FRAMEWORK_VERSION="
|
|
9
|
+
FRAMEWORK_VERSION="6"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
11
11
|
cd "$SCRIPT_DIR" || exit 1
|
|
12
12
|
|
|
@@ -56,6 +56,7 @@ fi
|
|
|
56
56
|
|
|
57
57
|
source "$SCRIPT_DIR/bin/lib/git-sync.sh" >/dev/null 2>/dev/null
|
|
58
58
|
source "$SCRIPT_DIR/bin/lib/context.sh" >/dev/null 2>/dev/null
|
|
59
|
+
source "$SCRIPT_DIR/bin/lib/metrics.sh" >/dev/null 2>/dev/null
|
|
59
60
|
trap 'rm -rf "${CTX_DIR:-}"' EXIT
|
|
60
61
|
|
|
61
62
|
read_json() {
|
|
@@ -69,23 +70,6 @@ read_json() {
|
|
|
69
70
|
fi
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
shorten() {
|
|
73
|
-
local value="$1"
|
|
74
|
-
local max="$2"
|
|
75
|
-
if command -v jq >/dev/null 2>&1; then
|
|
76
|
-
jq -nr --arg value "$value" --argjson max "$max" '
|
|
77
|
-
$value
|
|
78
|
-
| if length > $max then .[0:($max - 3)] + "..." else . end
|
|
79
|
-
'
|
|
80
|
-
return
|
|
81
|
-
fi
|
|
82
|
-
if [ "${#value}" -gt "$max" ]; then
|
|
83
|
-
printf '%s...\n' "${value:0:$((max - 3))}"
|
|
84
|
-
else
|
|
85
|
-
printf '%s\n' "$value"
|
|
86
|
-
fi
|
|
87
|
-
}
|
|
88
|
-
|
|
89
73
|
ORG_NAME="$(read_json "$CONFIG" '.org_name' '')"
|
|
90
74
|
[ -z "$ORG_NAME" ] && ORG_NAME="$(read_json "$CONFIG" '.slug' 'Egregore')"
|
|
91
75
|
GITHUB_ORG="$(read_json "$CONFIG" '.github_org' '')"
|
|
@@ -96,14 +80,12 @@ DISPLAY_NAME="$(read_json "$STATE_FILE" '.display_name' '')"
|
|
|
96
80
|
ONBOARDING_COMPLETE="$(read_json "$STATE_FILE" '.onboarding_complete' '')"
|
|
97
81
|
[ -z "$ONBOARDING_COMPLETE" ] && ONBOARDING_COMPLETE="unknown"
|
|
98
82
|
|
|
99
|
-
TEAM_DATA="$(cat "$CTX_DIR/team" 2>/dev/null || echo "[]")"
|
|
100
83
|
ADDRESSED_RICH="$(cat "$CTX_DIR/addressed_rich" 2>/dev/null || echo "[]")"
|
|
101
84
|
PENDING_Q="$(cat "$CTX_DIR/pending_questions" 2>/dev/null || echo "[]")"
|
|
102
|
-
LAST_ACTIVITY="$(cat "$CTX_DIR/activity" 2>/dev/null || true)"
|
|
103
85
|
ADDRESSED_COUNT="$(echo "$ADDRESSED_RICH" | jq 'length' 2>/dev/null || echo "0")"
|
|
104
86
|
PENDING_Q_COUNT="$(echo "$PENDING_Q" | jq 'length' 2>/dev/null || echo "0")"
|
|
105
87
|
|
|
106
|
-
|
|
88
|
+
render_pending_line() {
|
|
107
89
|
if [ "$PENDING_Q_COUNT" -gt 0 ] 2>/dev/null; then
|
|
108
90
|
local senders noun
|
|
109
91
|
senders="$(echo "$PENDING_Q" | jq -r '[.[].from] | unique | join(", ")' 2>/dev/null)"
|
|
@@ -115,41 +97,9 @@ render_for_you_summary() {
|
|
|
115
97
|
fi
|
|
116
98
|
elif [ "$ADDRESSED_COUNT" -gt 0 ] 2>/dev/null; then
|
|
117
99
|
printf ' ◇ %s handoffs for %s - bin/agent.sh activity --for %s\n' "$ADDRESSED_COUNT" "$AUTHOR" "$AUTHOR"
|
|
118
|
-
else
|
|
119
|
-
printf ' ◇ nothing pending for %s\n' "$AUTHOR"
|
|
120
|
-
fi
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
render_handoff_rows() {
|
|
124
|
-
if [ "$ADDRESSED_COUNT" -gt 0 ] 2>/dev/null; then
|
|
125
|
-
echo "$ADDRESSED_RICH" | jq -r '.[] | [.author, .date, .topic] | @tsv' 2>/dev/null | head -4 | while IFS=$'\t' read -r author date topic; do
|
|
126
|
-
[ -z "$author" ] && continue
|
|
127
|
-
printf ' ○ %-10s%-12s%s\n' "$(shorten "$author" 9)" "$date" "$(shorten "$topic" 40)"
|
|
128
|
-
done
|
|
129
|
-
elif [ -n "$LAST_ACTIVITY" ]; then
|
|
130
|
-
local last_when last_msg
|
|
131
|
-
last_when="$(printf '%s\n' "$LAST_ACTIVITY" | cut -d'|' -f1 | sed 's/ hours\{0,1\} ago/h ago/; s/ days\{0,1\} ago/d ago/; s/ minutes\{0,1\} ago/m ago/')"
|
|
132
|
-
last_msg="$(printf '%s\n' "$LAST_ACTIVITY" | cut -d'|' -f2-)"
|
|
133
|
-
printf ' ◇ %-10s%-12s%s\n' "you" "$last_when" "$(shorten "$last_msg" 40)"
|
|
134
100
|
fi
|
|
135
101
|
}
|
|
136
102
|
|
|
137
|
-
render_team_rows() {
|
|
138
|
-
local now_render online_threshold
|
|
139
|
-
now_render=$(date +%s)
|
|
140
|
-
online_threshold=7200
|
|
141
|
-
echo "$TEAM_DATA" | jq -r '.[] | [.name, .last_seen_sort, .last_seen, (.branches | join(", "))] | @tsv' 2>/dev/null | head -4 | while IFS=$'\t' read -r name epoch seen branches; do
|
|
142
|
-
[ -z "$name" ] && continue
|
|
143
|
-
local dot
|
|
144
|
-
if [ "$epoch" -gt 0 ] 2>/dev/null && [ $((now_render - epoch)) -lt "$online_threshold" ] 2>/dev/null; then
|
|
145
|
-
dot="●"
|
|
146
|
-
else
|
|
147
|
-
dot="○"
|
|
148
|
-
fi
|
|
149
|
-
printf ' %s %-10s%-12s%s\n' "$dot" "$(shorten "$name" 9)" "$seen" "$(shorten "$branches" 40)"
|
|
150
|
-
done
|
|
151
|
-
}
|
|
152
|
-
|
|
153
103
|
banner() {
|
|
154
104
|
cat <<'EOF'
|
|
155
105
|
|
|
@@ -175,12 +125,8 @@ render_card() {
|
|
|
175
125
|
banner
|
|
176
126
|
printf '%s%*s%s\n' "$identity_left" "$pad" "" "$identity_right"
|
|
177
127
|
printf '%s\n' "$separator"
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
render_handoff_rows
|
|
181
|
-
printf '\n'
|
|
182
|
-
printf ' ◦ around\n'
|
|
183
|
-
render_team_rows
|
|
128
|
+
SEPARATOR="$separator" LINE_WIDTH=$line_width _render_momentum_board
|
|
129
|
+
render_pending_line
|
|
184
130
|
printf '%s\n' "$separator"
|
|
185
131
|
|
|
186
132
|
has_failure="false"
|
|
@@ -229,7 +175,7 @@ Follow AGENTS.md before code changes.
|
|
|
229
175
|
After the user names what they are working on, use bin/agent.sh branch --topic "<work topic>" if you are not already in an appropriate task worktree, then continue file work from the printed worktree path.
|
|
230
176
|
Use bin/agent.sh to update shared activity: handoff, ask, and answer write to memory/ and push when possible.
|
|
231
177
|
Use bin/agent.sh handoff for internal team session-handoffs. Portable external capsules are emissaries; use egregore-emissary when installed, not the deprecated egregore-handoff CLI.
|
|
232
|
-
Codex reserves leading slash commands for built-ins, so custom Egregore /activity-style commands will not reach the agent. Egregore native Codex skills are: \$activity, \$handoff, \$wrap, \$announce, \$harvest, \$the-spiral, \$dashboard, \$deep-reflect, \$quest, \$invite, \$ask, and \$
|
|
178
|
+
Codex reserves leading slash commands for built-ins, so custom Egregore /activity-style commands will not reach the agent. Egregore native Codex skills are: \$activity, \$handoff, \$wrap, \$announce, \$harvest, \$the-spiral, \$dashboard, \$deep-reflect, \$quest, \$invite, \$ask, \$save, \$view, and \$scroll. Natural-language requests such as "show activity", "make a handoff", or "render this as a scroll" work too. Remaining mirrored workflows are adapter skills for long-tail coverage.
|
|
233
179
|
\$save is the user-facing abstraction for committing, pushing, opening or reusing pull requests, and syncing memory; do not make users manage the git workflow by hand.
|
|
234
180
|
Egregore Codex workflows are skill invocations, not Claude Code slash commands. Do not rely on Claude Code-only command machinery.
|
|
235
181
|
If onboarding_complete is false, use the memory protocol directly and make sure memory/people/${AUTHOR}.md exists before the first handoff.
|
|
@@ -72,9 +72,10 @@ function truncate(value, max) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function padLine(left, right = '') {
|
|
75
|
-
const
|
|
76
|
-
const r = truncate(right,
|
|
77
|
-
const
|
|
75
|
+
const inner = WIDTH - 4;
|
|
76
|
+
const r = right ? truncate(right, Math.min(18, inner - 1)) : '';
|
|
77
|
+
const l = truncate(left, inner - (r ? r.length + 1 : 0));
|
|
78
|
+
const space = Math.max(0, inner - l.length - r.length);
|
|
78
79
|
return `│ ${l}${' '.repeat(space)}${r} │`;
|
|
79
80
|
}
|
|
80
81
|
|
|
@@ -143,13 +144,14 @@ function renderActivity(data) {
|
|
|
143
144
|
const org = data.org || data.organization || 'Egregore';
|
|
144
145
|
const date = data.date || '';
|
|
145
146
|
const me = data.me?.github || data.me?.name || data.github_username || '';
|
|
146
|
-
const handoffs = firstArray(data, ['handoffs', 'pending_handoffs', 'me.handoffs', 'addressed_handoffs']);
|
|
147
|
+
const handoffs = firstArray(data, ['handoffs_to_me', 'handoffs', 'pending_handoffs', 'me.handoffs', 'addressed_handoffs']);
|
|
147
148
|
const questions = firstArray(data, ['questions', 'pending_questions', 'me.questions']);
|
|
148
149
|
const prs = asArray(data.prs);
|
|
149
150
|
const mine = firstArray(data, ['local_sessions.my_sessions', 'my_sessions', 'sessions']);
|
|
150
151
|
const team = firstArray(data, ['local_sessions.team_sessions', 'team_sessions', 'team.sessions']);
|
|
151
152
|
|
|
152
|
-
const
|
|
153
|
+
const brand = `${truncate(org, 20).toUpperCase()} EGREGORE ✦ ACTIVITY DASHBOARD`;
|
|
154
|
+
const lines = [topRule(), padLine(brand), padLine([me, date].filter(Boolean).join(' · ')), rule()];
|
|
153
155
|
if (graph.status !== 'connected') {
|
|
154
156
|
lines.push(padLine(`graph: ${graph.status}`, graph.reason));
|
|
155
157
|
lines.push(rule());
|
|
@@ -159,12 +161,18 @@ function renderActivity(data) {
|
|
|
159
161
|
if (questions.length === 0 && handoffs.length === 0) {
|
|
160
162
|
lines.push(padLine('nothing pending'));
|
|
161
163
|
} else {
|
|
162
|
-
questions.
|
|
163
|
-
lines.push(padLine(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
164
|
+
if (questions.length > 0) {
|
|
165
|
+
lines.push(padLine('QUESTIONS'));
|
|
166
|
+
questions.slice(0, 4).forEach((q) => {
|
|
167
|
+
lines.push(padLine(`● ${valueOf(q, ['from', 'author', 'asker'], 'someone')}: ${valueOf(q, ['topic', 'title', 'question'], 'question')}`));
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
if (handoffs.length > 0) {
|
|
171
|
+
lines.push(padLine('HANDOFFS'));
|
|
172
|
+
handoffs.slice(0, 4).forEach((h) => {
|
|
173
|
+
lines.push(padLine(`○ ${valueOf(h, ['author', 'from'], 'someone')}: ${valueOf(h, ['topic', 'title'], 'handoff')}`));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
lines.push(rule());
|
|
@@ -284,7 +292,7 @@ function renderHandoff(data) {
|
|
|
284
292
|
data.notifyStatus ? `notify=${data.notifyStatus}` : '',
|
|
285
293
|
].filter(Boolean).join(' · ');
|
|
286
294
|
|
|
287
|
-
const lines = [topRule(), padLine('HANDOFF', data.author || ''), rule()];
|
|
295
|
+
const lines = [topRule(), padLine('⇌ HANDOFF', data.author || ''), rule()];
|
|
288
296
|
lines.push(padLine(`Topic: ${data.topic || '(untitled)'}`));
|
|
289
297
|
if (data.recipient) lines.push(padLine(`To: ${data.recipient}`));
|
|
290
298
|
if (file) lines.push(padLine(`Path: ${file}`));
|
|
@@ -19,8 +19,11 @@ set -euo pipefail
|
|
|
19
19
|
# remove-name to keep-name, stores remove-name as alias
|
|
20
20
|
# create-harvest <id> <topic> <intent> <initiator>
|
|
21
21
|
# Create a Harvest node and link to initiator (WAL-backed)
|
|
22
|
-
# create-harvest-session <harvest-id> <session-id> <person-name>
|
|
23
|
-
# Create a HarvestSession linked to a Harvest and Person
|
|
22
|
+
# create-harvest-session <harvest-id> <session-id> <person-name> [status]
|
|
23
|
+
# Create a HarvestSession linked to a Harvest and Person.
|
|
24
|
+
# status defaults to 'active' (back-compat). Valid values:
|
|
25
|
+
# pending | active | answered | complete | incorporated.
|
|
26
|
+
# Async respondents should be created with 'pending'.
|
|
24
27
|
# record-harvest-turn <session-id> <turn> <question> <intent> [answer] [eval]
|
|
25
28
|
# Record a question-answer turn in a HarvestSession
|
|
26
29
|
# complete-harvest <harvest-id> <artifact-path>
|
|
@@ -42,6 +45,7 @@ if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
|
|
42
45
|
echo " merge-person <keep> <rm> Merge two Person nodes"
|
|
43
46
|
echo " claim-handoff <sid> <ho> Link implementing session to handoff"
|
|
44
47
|
echo " create-pr <sid> <num> <repo> <author> [title]"
|
|
48
|
+
echo " register-artifact <id> <url> <title> <type> <author> <topics> <excerpt>"
|
|
45
49
|
echo " create-harvest / complete-harvest / record-harvest-turn"
|
|
46
50
|
echo " wal-status Show WAL pending count"
|
|
47
51
|
exit 0
|
|
@@ -202,6 +206,39 @@ case "$OP" in
|
|
|
202
206
|
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
203
207
|
;;
|
|
204
208
|
|
|
209
|
+
register-artifact)
|
|
210
|
+
# Index a published (hosted) artifact as an Artifact node so the finder can
|
|
211
|
+
# retrieve it from the graph in connected mode — by content (title/topics/
|
|
212
|
+
# excerpt CONTAINS) and by relationship (who made it, which quest). The node
|
|
213
|
+
# id is the registry FILENAME STEM (date-author-slug), matching sync-graph.sh
|
|
214
|
+
# so a later /save sync upserts the same node instead of duplicating it.
|
|
215
|
+
# args: <id> <url> <title> <type> <author-handle> <topics-csv> <excerpt>
|
|
216
|
+
A_ID="${1:?missing id}"
|
|
217
|
+
A_URL="${2:?missing url}"
|
|
218
|
+
A_TITLE="${3:-}"
|
|
219
|
+
A_TYPE="${4:-artifact}"
|
|
220
|
+
A_AUTHOR="$(printf '%s' "${5:-}" | tr '[:upper:]' '[:lower:]' | awk '{print $1}')"
|
|
221
|
+
A_TOPICS_JSON="$(printf '%s' "${6:-}" | jq -Rc 'split(",") | map(gsub("^\\s+|\\s+$";"")) | map(select(length > 0))' 2>/dev/null || echo '[]')"
|
|
222
|
+
A_EXCERPT="$(printf '%s' "${7:-}" | tr '\n' ' ' | cut -c1-2000)"
|
|
223
|
+
CYPHER="
|
|
224
|
+
MERGE (a:Artifact {id: \$id})
|
|
225
|
+
ON CREATE SET a.created = datetime()
|
|
226
|
+
SET a.title = \$title, a.type = \$type, a.url = \$url,
|
|
227
|
+
a.topics = \$topics, a.excerpt = \$excerpt, a.published = true
|
|
228
|
+
WITH a
|
|
229
|
+
OPTIONAL MATCH (p:Person)
|
|
230
|
+
WHERE \$author <> '' AND (toLower(p.name) = \$author OR p.github = \$author)
|
|
231
|
+
FOREACH (_ IN CASE WHEN p IS NOT NULL THEN [1] ELSE [] END |
|
|
232
|
+
MERGE (a)-[:CONTRIBUTED_BY]->(p))
|
|
233
|
+
RETURN a.id AS id
|
|
234
|
+
"
|
|
235
|
+
PARAMS="$(jq -n --arg id "$A_ID" --arg url "$A_URL" --arg title "$A_TITLE" --arg type "$A_TYPE" \
|
|
236
|
+
--arg author "$A_AUTHOR" --argjson topics "$A_TOPICS_JSON" --arg excerpt "$A_EXCERPT" \
|
|
237
|
+
'{id: $id, url: $url, title: $title, type: $type, author: $author, topics: $topics, excerpt: $excerpt}')"
|
|
238
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
239
|
+
bash "$GS" query "$CYPHER" "$PARAMS"
|
|
240
|
+
;;
|
|
241
|
+
|
|
205
242
|
check-implements)
|
|
206
243
|
SID="${1:?missing session-id}"
|
|
207
244
|
bash "$GS" query "
|
|
@@ -305,16 +342,30 @@ case "$OP" in
|
|
|
305
342
|
HID="${1:?missing harvest-id}"
|
|
306
343
|
HSID="${2:?missing session-id}"
|
|
307
344
|
PERSON="${3:?missing person-name}"
|
|
308
|
-
|
|
345
|
+
STATUS="${4:-active}"
|
|
346
|
+
case "$STATUS" in
|
|
347
|
+
pending|active|answered|complete|incorporated) ;;
|
|
348
|
+
*) jq -n --arg s "$STATUS" '{error:("invalid status: "+$s),valid:["pending","active","answered","complete","incorporated"]}' >&2; exit 2 ;;
|
|
349
|
+
esac
|
|
350
|
+
CYPHER="
|
|
309
351
|
MATCH (h:Harvest {id: \$hid})
|
|
310
352
|
MERGE (hs:HarvestSession {id: \$hsid})
|
|
311
|
-
ON CREATE SET hs.status =
|
|
353
|
+
ON CREATE SET hs.status = \$status, hs.created = datetime()
|
|
312
354
|
MERGE (h)-[:HAS_SESSION]->(hs)
|
|
313
355
|
WITH hs
|
|
314
356
|
MATCH (p:Person) WHERE toLower(p.name) = toLower(\$person) OR p.github = \$person
|
|
315
357
|
MERGE (hs)-[:WITH]->(p)
|
|
316
358
|
RETURN hs.id AS id, hs.status AS status
|
|
317
|
-
"
|
|
359
|
+
"
|
|
360
|
+
PARAMS="$(jq -n --arg hid "$HID" --arg hsid "$HSID" --arg person "$PERSON" --arg status "$STATUS" '{hid: $hid, hsid: $hsid, person: $person, status: $status}')"
|
|
361
|
+
bash "$SCRIPT_DIR/bin/graph-wal.sh" append "$CYPHER" "$PARAMS" 2>/dev/null || true
|
|
362
|
+
OUT="$(bash "$GS" query "$CYPHER" "$PARAMS")"
|
|
363
|
+
if [ "$(echo "$OUT" | jq -r '.results | length' 2>/dev/null)" = "0" ]; then
|
|
364
|
+
jq -n --arg hid "$HID" --arg hsid "$HSID" --arg person "$PERSON" \
|
|
365
|
+
'{error:"create-harvest-session: harvest or person not found",hid:$hid,hsid:$hsid,person:$person}' >&2
|
|
366
|
+
exit 3
|
|
367
|
+
fi
|
|
368
|
+
echo "$OUT"
|
|
318
369
|
;;
|
|
319
370
|
|
|
320
371
|
record-harvest-turn)
|
|
@@ -42,6 +42,22 @@ _millis() {
|
|
|
42
42
|
fi
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
# --- Optional read-through cache (opt-in via EGREGORE_GRAPH_CACHE_TTL) ---
|
|
46
|
+
# Read-only queries can be served from a local cache that bin/attendant.sh
|
|
47
|
+
# keeps warm in the background, so callers on the launch path (session-start
|
|
48
|
+
# greeting) pay zero network round-trips when warm. TTL in seconds; unset/0
|
|
49
|
+
# disables. Mutating queries are never cached.
|
|
50
|
+
_CACHE_TTL="${EGREGORE_GRAPH_CACHE_TTL:-0}"
|
|
51
|
+
_CACHE_DIR="$HOME/.egregore/graph-cache/$(echo -n "$SCRIPT_DIR" | cksum | cut -d' ' -f1)"
|
|
52
|
+
|
|
53
|
+
_cache_key() {
|
|
54
|
+
echo -n "$1|${2:-}" | cksum | cut -d' ' -f1
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_is_read_query() {
|
|
58
|
+
! echo "$1" | grep -qiE '\b(MERGE|CREATE|SET|DELETE|DETACH|REMOVE)\b'
|
|
59
|
+
}
|
|
60
|
+
|
|
45
61
|
if [ -n "$API_URL" ] && [ -n "$API_KEY" ]; then
|
|
46
62
|
# === API MODE: Call Egregore API gateway ===
|
|
47
63
|
|
|
@@ -54,6 +70,19 @@ if [ -n "$API_URL" ] && [ -n "$API_KEY" ]; then
|
|
|
54
70
|
params="{}"
|
|
55
71
|
fi
|
|
56
72
|
|
|
73
|
+
local cache_file=""
|
|
74
|
+
if [ "$_CACHE_TTL" != "0" ] && _is_read_query "$cypher"; then
|
|
75
|
+
cache_file="$_CACHE_DIR/$(_cache_key "$cypher" "$params").json"
|
|
76
|
+
if [ -f "$cache_file" ]; then
|
|
77
|
+
local now cts
|
|
78
|
+
now=$(date +%s)
|
|
79
|
+
cts=$(jq -r '.ts // 0' "$cache_file" 2>/dev/null || echo 0)
|
|
80
|
+
if [ $(( now - cts )) -lt "$_CACHE_TTL" ]; then
|
|
81
|
+
jq -c '.result' "$cache_file" 2>/dev/null && return 0
|
|
82
|
+
fi
|
|
83
|
+
fi
|
|
84
|
+
fi
|
|
85
|
+
|
|
57
86
|
local body
|
|
58
87
|
body=$(jq -n --arg stmt "$cypher" --argjson params "$params" \
|
|
59
88
|
'{statement: $stmt, parameters: $params}')
|
|
@@ -86,6 +115,13 @@ if [ -n "$API_URL" ] && [ -n "$API_KEY" ]; then
|
|
|
86
115
|
bash "$SCRIPT_DIR/bin/telemetry.sh" emit "graph_query" \
|
|
87
116
|
"$(jq -n --argjson latency "$latency_ms" '{latency_ms: $latency}')" 2>/dev/null &
|
|
88
117
|
|
|
118
|
+
# Store for the attendant to keep warm (query+params travel with the result)
|
|
119
|
+
if [ -n "$cache_file" ]; then
|
|
120
|
+
mkdir -p "$_CACHE_DIR" 2>/dev/null
|
|
121
|
+
jq -n --arg q "$cypher" --argjson p "$params" --argjson ts "$(date +%s)" --argjson r "$response" \
|
|
122
|
+
'{query: $q, params: $p, ts: $ts, result: $r}' > "$cache_file" 2>/dev/null || true
|
|
123
|
+
fi
|
|
124
|
+
|
|
89
125
|
echo "$response"
|
|
90
126
|
}
|
|
91
127
|
|