create-egregore 0.20.1 → 0.20.2

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.
Files changed (48) hide show
  1. package/assets/egregore-launcher.js +57 -14
  2. package/lib/local.js +4 -20
  3. package/lib/setup.js +0 -2
  4. package/package.json +2 -2
  5. package/runtime/codex/.codex/spec-manifest.json +3 -3
  6. package/runtime/codex/AGENTS.md +23 -9
  7. package/runtime/codex/bin/agent.sh +15 -3
  8. package/runtime/codex/bin/codex-render-spec.mjs +5 -3
  9. package/runtime/codex/bin/contribute-guard.sh +79 -0
  10. package/runtime/codex/bin/handoff-save-egregore.sh +1 -1
  11. package/runtime/codex/bin/lib/git-sync.sh +16 -0
  12. package/runtime/codex/bin/lib/greeting.sh +2 -2
  13. package/runtime/codex/bin/search.sh +46 -4
  14. package/runtime/codex/bin/session-autosave.sh +6 -1
  15. package/runtime/codex/bin/settings.sh +62 -3
  16. package/runtime/codex/bin/worktree-create.sh +4 -1
  17. package/runtime/codex/manifest.json +1 -0
  18. package/runtime/pi/.codex/spec-manifest.json +3 -3
  19. package/runtime/pi/.pi/APPEND_SYSTEM.md +23 -9
  20. package/runtime/pi/.pi/spec-manifest.json +2 -2
  21. package/runtime/pi/AGENTS.md +23 -9
  22. package/runtime/pi/bin/agent.sh +15 -3
  23. package/runtime/pi/bin/codex-render-spec.mjs +5 -3
  24. package/runtime/pi/bin/contribute-guard.sh +79 -0
  25. package/runtime/pi/bin/handoff-save-egregore.sh +1 -1
  26. package/runtime/pi/bin/lib/git-sync.sh +16 -0
  27. package/runtime/pi/bin/lib/greeting.sh +2 -2
  28. package/runtime/pi/bin/search.sh +46 -4
  29. package/runtime/pi/bin/session-autosave.sh +6 -1
  30. package/runtime/pi/bin/settings.sh +62 -3
  31. package/runtime/pi/bin/worktree-create.sh +4 -1
  32. package/runtime/pi/manifest.json +1 -0
  33. package/runtime/prime/.codex/spec-manifest.json +3 -3
  34. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +24 -10
  35. package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
  36. package/runtime/prime/AGENTS.md +23 -9
  37. package/runtime/prime/bin/agent.sh +15 -3
  38. package/runtime/prime/bin/codex-render-spec.mjs +5 -3
  39. package/runtime/prime/bin/contribute-guard.sh +79 -0
  40. package/runtime/prime/bin/handoff-save-egregore.sh +1 -1
  41. package/runtime/prime/bin/lib/git-sync.sh +16 -0
  42. package/runtime/prime/bin/lib/greeting.sh +2 -2
  43. package/runtime/prime/bin/prime-render-spec.mjs +1 -1
  44. package/runtime/prime/bin/search.sh +46 -4
  45. package/runtime/prime/bin/session-autosave.sh +6 -1
  46. package/runtime/prime/bin/settings.sh +62 -3
  47. package/runtime/prime/bin/worktree-create.sh +4 -1
  48. package/runtime/prime/manifest.json +1 -0
@@ -29,6 +29,48 @@ SLUG=$(jq -r '.slug // "egregore"' "$SCRIPT_DIR/egregore.json" 2>/dev/null || ec
29
29
  COLLECTION="${SLUG}-memory"
30
30
  MEM_PATH="$(readlink -f "$SCRIPT_DIR/memory" 2>/dev/null || true)"
31
31
 
32
+ # qmd 2.5.x may render --full-path results as absolute `**file:**` paths,
33
+ # while older output uses qmd:// URIs. Normalize both to the canonical
34
+ # memory/... form users can open from an Egregore checkout, and parse both
35
+ # forms when counting hits or attaching graph state.
36
+ _normalize_file_paths() {
37
+ local line absolute_prefix uri_prefix
38
+ absolute_prefix="**file:** \`$MEM_PATH/"
39
+ uri_prefix="**file:** \`qmd://${COLLECTION}/"
40
+ while IFS= read -r line || [ -n "$line" ]; do
41
+ if [[ "$line" == "$absolute_prefix"* ]]; then
42
+ printf '**file:** `memory/%s\n' "${line#"$absolute_prefix"}"
43
+ elif [[ "$line" == "$uri_prefix"* ]]; then
44
+ printf '**file:** `memory/%s\n' "${line#"$uri_prefix"}"
45
+ else
46
+ printf '%s\n' "$line"
47
+ fi
48
+ done
49
+ }
50
+
51
+ _result_paths() {
52
+ local line path canonical_prefix absolute_prefix uri_prefix
53
+ canonical_prefix="**file:** \`memory/"
54
+ absolute_prefix="**file:** \`$MEM_PATH/"
55
+ uri_prefix="**file:** \`qmd://${COLLECTION}/"
56
+ while IFS= read -r line || [ -n "$line" ]; do
57
+ path=""
58
+ if [[ "$line" == "$canonical_prefix"* ]]; then
59
+ path="${line#"$canonical_prefix"}"
60
+ elif [[ "$line" == "$absolute_prefix"* ]]; then
61
+ path="${line#"$absolute_prefix"}"
62
+ elif [[ "$line" == "$uri_prefix"* ]]; then
63
+ path="${line#"$uri_prefix"}"
64
+ elif [[ "$line" == *"qmd://${COLLECTION}/"* ]]; then
65
+ path="${line#*"qmd://${COLLECTION}/"}"
66
+ fi
67
+ path="${path%%\`*}"
68
+ case "$path" in
69
+ *.md*) printf '%s\n' "${path%%.md*}.md" ;;
70
+ esac
71
+ done | sort -u
72
+ }
73
+
32
74
  QMD_VERSION="2.5.3" # pinned — bump deliberately, never float @latest
33
75
 
34
76
  _qmd() {
@@ -104,7 +146,7 @@ _enrich() {
104
146
  local results paths params out
105
147
  results=$(cat)
106
148
  echo "$results"
107
- paths=$(echo "$results" | grep -o "qmd://${COLLECTION}/[^: ]*\.md" | sed "s|qmd://${COLLECTION}/||" | sort -u)
149
+ paths=$(printf '%s\n' "$results" | _result_paths)
108
150
  [ -z "$paths" ] && return 0
109
151
  params=$(printf '%s\n' "$paths" | jq -R . | jq -sc '{paths: .}')
110
152
  out=$(bash "$SCRIPT_DIR/bin/graph.sh" query "UNWIND \$paths AS fp
@@ -167,7 +209,7 @@ cmd_query() {
167
209
  local t0 out label
168
210
  t0=$(date +%s)
169
211
  if [ "$mode" != "search" ]; then
170
- out=$(_qmd "$mode" "$q" -c "$COLLECTION" -n "$n" --format md --full-path "${all[@]}" 2>/dev/null | _clean)
212
+ out=$(_qmd "$mode" "$q" -c "$COLLECTION" -n "$n" --format md --full-path "${all[@]}" 2>/dev/null | _clean | _normalize_file_paths)
171
213
  if [ -n "$out" ] && [ "$out" != "No results found." ]; then
172
214
  [ "$mode" = "query" ] && label="hybrid" || label="semantic"
173
215
  _banner_and_emit "$label" "$t0" "$emit" "$q" "$out"
@@ -176,7 +218,7 @@ cmd_query() {
176
218
  echo "_(hybrid/semantic returned nothing — showing keyword results. If this persists, run: bash bin/search.sh reindex --embed)_"
177
219
  echo ""
178
220
  fi
179
- out=$(_qmd search "$q" -c "$COLLECTION" -n "$n" --format md --full-path "${all[@]}" | _clean)
221
+ out=$(_qmd search "$q" -c "$COLLECTION" -n "$n" --format md --full-path "${all[@]}" | _clean | _normalize_file_paths)
180
222
  _banner_and_emit "keyword" "$t0" "$emit" "$q" "$out"
181
223
  }
182
224
 
@@ -189,7 +231,7 @@ cmd_query() {
189
231
  _banner_and_emit() {
190
232
  local label="$1" t0="$2" emit="$3" q="$4" out="$5"
191
233
  local hits dur modef product surface plural=""
192
- hits=$(printf '%s\n' "$out" | grep -c '^qmd://' 2>/dev/null | tr -d ' ')
234
+ hits=$(printf '%s\n' "$out" | _result_paths | wc -l | tr -d ' ')
193
235
  dur=$(( $(date +%s) - t0 ))
194
236
  modef="$label"
195
237
  product="Egregore"
@@ -85,7 +85,12 @@ git rev-parse --git-dir >/dev/null 2>&1 || exit 0
85
85
  DIR_HASH=$( { md5sum <<<"$DIR" 2>/dev/null || md5 -q -s "$DIR" 2>/dev/null || echo default; } | cut -c1-8 )
86
86
  STAMP="/tmp/.egregore-autosave-${DIR_HASH}"
87
87
  if [ "$DEBOUNCE" -gt 0 ] && [ -f "$STAMP" ]; then
88
- LAST=$(stat -f %m "$STAMP" 2>/dev/null || stat -c %Y "$STAMP" 2>/dev/null || echo 0)
88
+ if stat -c %Y "$STAMP" >/dev/null 2>&1; then
89
+ LAST=$(stat -c %Y "$STAMP")
90
+ else
91
+ LAST=$(stat -f %m "$STAMP" 2>/dev/null || echo 0)
92
+ fi
93
+ case "$LAST" in ""|*[!0-9]*) LAST=0 ;; esac
89
94
  [ $(( $(date +%s) - LAST )) -lt "$DEBOUNCE" ] && exit 0
90
95
  fi
91
96
  touch "$STAMP" 2>/dev/null || true
@@ -3,14 +3,16 @@ set -euo pipefail
3
3
 
4
4
  # settings.sh — deterministic config verbs for an Egregore instance.
5
5
  #
6
- # Edits egregore.json atomically. No agent, no network, no session. Idempotent:
7
- # re-adding an existing item is a no-op success; removing a missing one is too.
6
+ # Edits egregore.json atomically. No agent, no session. Idempotent: re-adding
7
+ # an existing item is a no-op success; removing a missing one is too. Switching
8
+ # to staged releases is the one networked verb: it creates origin/develop first.
8
9
  # This is the deterministic core the launcher settings screen (and slash
9
10
  # commands) call — the reliability lives here, the surfaces are thin callers.
10
11
  #
11
12
  # Usage:
12
13
  # settings.sh hosting status|on|off
13
14
  # settings.sh relay status|on|off
15
+ # settings.sh workflow status|simple|staged
14
16
  # settings.sh repo list | add <name> [description] | remove <name>
15
17
  # settings.sh admin list | add <github-handle> | remove <github-handle>
16
18
  # settings.sh dump # full settings snapshot as JSON (for the launcher)
@@ -53,6 +55,7 @@ settings.sh — Egregore instance settings
53
55
 
54
56
  settings.sh hosting status|on|off
55
57
  settings.sh relay status|on|off
58
+ settings.sh workflow status|simple|staged
56
59
  settings.sh repo list | add <name> [description] | remove <name>
57
60
  settings.sh admin list | add <github-handle> | remove <github-handle>
58
61
  settings.sh people list | add <github-handle> | remove <github-handle>
@@ -114,6 +117,54 @@ cmd_relay() {
114
117
  esac
115
118
  }
116
119
 
120
+ cmd_workflow() {
121
+ local action="${1:-status}"
122
+ local base
123
+ base="$(jq -r 'if has("base_branch") then .base_branch else "develop" end' "$CONFIG" 2>/dev/null)"
124
+ case "$action" in
125
+ status)
126
+ local workflow="custom"
127
+ [ "$base" = "main" ] && workflow="simple"
128
+ [ "$base" = "develop" ] && workflow="staged"
129
+ if [ "$JSON" = 1 ]; then
130
+ jq -n --arg workflow "$workflow" --arg base_branch "$base" \
131
+ '{domain:"workflow", workflow:$workflow, base_branch:$base_branch}'
132
+ elif [ "$workflow" = "simple" ]; then
133
+ echo "Git workflow: SIMPLE — pull requests target main"
134
+ elif [ "$workflow" = "staged" ]; then
135
+ echo "Git workflow: STAGED — pull requests target develop; releases promote to main"
136
+ else
137
+ echo "Git workflow: CUSTOM — pull requests target $base"
138
+ fi
139
+ ;;
140
+ simple)
141
+ if [ "$base" != "main" ]; then
142
+ git -C "$SCRIPT_DIR" rev-parse --git-dir >/dev/null 2>&1 \
143
+ || _die "cannot switch workflow: $SCRIPT_DIR is not a Git repository" 1
144
+ git -C "$SCRIPT_DIR" ls-remote --exit-code --heads origin main >/dev/null 2>&1 \
145
+ || _die "cannot switch workflow: origin/main does not exist or could not be reached" 1
146
+ _save '.base_branch = "main"'
147
+ fi
148
+ echo "Git workflow: SIMPLE — pull requests now target main"
149
+ ;;
150
+ staged)
151
+ if [ "$base" != "develop" ]; then
152
+ git -C "$SCRIPT_DIR" rev-parse --git-dir >/dev/null 2>&1 \
153
+ || _die "cannot switch workflow: $SCRIPT_DIR is not a Git repository" 1
154
+ bash "$SCRIPT_DIR/bin/lib/ensure-develop.sh" "$SCRIPT_DIR" >/dev/null \
155
+ || _die "could not create develop; workflow is unchanged" 1
156
+ git -C "$SCRIPT_DIR" ls-remote --exit-code --heads origin develop >/dev/null 2>&1 \
157
+ || _die "could not verify origin/develop; workflow is unchanged" 1
158
+ _save '.base_branch = "develop"'
159
+ elif ! jq -e 'has("base_branch")' "$CONFIG" >/dev/null 2>&1; then
160
+ _save '.base_branch = "develop"'
161
+ fi
162
+ echo "Git workflow: STAGED — pull requests now target develop; releases promote to main"
163
+ ;;
164
+ *) _die "usage: settings.sh workflow status|simple|staged" 1 ;;
165
+ esac
166
+ }
167
+
117
168
  cmd_repo() {
118
169
  local action="${1:-list}"; shift || true
119
170
  case "$action" in
@@ -273,6 +324,13 @@ cmd_dump() {
273
324
  slug: .slug,
274
325
  hosting: (.features.publishing != false),
275
326
  public_relay: (.features.public_relay == true),
327
+ workflow: (
328
+ if ((if has("base_branch") then .base_branch else "develop" end) == "main") then "simple"
329
+ elif ((if has("base_branch") then .base_branch else "develop" end) == "develop") then "staged"
330
+ else "custom"
331
+ end
332
+ ),
333
+ base_branch: (if has("base_branch") then .base_branch else "develop" end),
276
334
  repos: [.repos[]? | if type=="object" then . else {name:.} end],
277
335
  admins: (.admins // []),
278
336
  people: $people
@@ -295,10 +353,11 @@ DOMAIN="${1:-}"; shift || true
295
353
  case "$DOMAIN" in
296
354
  hosting) cmd_hosting "$@" ;;
297
355
  relay) cmd_relay "$@" ;;
356
+ workflow) cmd_workflow "$@" ;;
298
357
  repo) cmd_repo "$@" ;;
299
358
  admin) cmd_admin "$@" ;;
300
359
  people) cmd_people "$@" ;;
301
360
  dump) cmd_dump ;;
302
361
  ""|-h|--help|help) usage 0 ;;
303
- *) _die "unknown settings domain: '$DOMAIN' (try: hosting, relay, repo, admin, people, dump)" 1 ;;
362
+ *) _die "unknown settings domain: '$DOMAIN' (try: hosting, relay, workflow, repo, admin, people, dump)" 1 ;;
304
363
  esac
@@ -48,7 +48,10 @@ git -C "$REPO_ROOT" fetch origin "$BASE_BRANCH" --quiet 2>/dev/null || true
48
48
 
49
49
  # --- Create branch (idempotent — skip if exists) ---
50
50
  if ! git -C "$REPO_ROOT" show-ref --verify --quiet "refs/heads/$BRANCH" 2>/dev/null; then
51
- git -C "$REPO_ROOT" branch "$BRANCH" "origin/$BASE_BRANCH" >/dev/null 2>&1 || {
51
+ # A task branch starts at the integration branch but must never track it.
52
+ # Otherwise `git push` can target origin/$BASE_BRANCH (especially when the
53
+ # user's push.default is `upstream`) before the first explicit task push.
54
+ git -C "$REPO_ROOT" branch --no-track "$BRANCH" "origin/$BASE_BRANCH" >/dev/null 2>&1 || {
52
55
  echo "Error: failed to create branch $BRANCH" >&2
53
56
  exit 1
54
57
  }
@@ -129,6 +129,7 @@
129
129
  "bin/codex-skill-render.mjs",
130
130
  "bin/codex-sync-skills.sh",
131
131
  "bin/connect-refresh.sh",
132
+ "bin/contribute-guard.sh",
132
133
  "bin/dashboard-data.sh",
133
134
  "bin/graph-batch.sh",
134
135
  "bin/graph-op.sh",