create-egregore 0.18.17 → 0.19.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.
@@ -224,6 +224,8 @@ Codex has no structured question tool — render each batch as compact numbered
224
224
 
225
225
  **Rules:** Max 4 questions per batch. When choices aren't mutually exclusive, say "pick any that apply".`;
226
226
 
227
+ const LOOM_ROUTING_BODY = `Loom routes commands across model tiers on the Claude Code runtime (\`loom/routes.json\` + \`bin/loom.sh\` + a model-pinned executor subagent). Codex has no subagent delegation — every command runs inline in the current session. Ignore "Loom routing" preambles if you encounter them in a skill spec, and skip \`bin/loom.sh\` calls; \`loom/\` and \`.claude/agents/\` are framework files synced for the Claude runtime.`;
228
+
227
229
  const ISOLATION_BODY = `Sessions are confined to this project + memory + managed repos. On Codex this boundary is a standing instruction, not an enforced hook — hold it yourself.
228
230
 
229
231
  - **Never modify \`~/.egregore/instances.json\`** — managed by session-start.sh
@@ -266,6 +268,11 @@ const RULES = {
266
268
  'Onboarding': { action: 'keep', note: 'Kept; /onboarding rendered as $onboarding.' },
267
269
  'Transparency Beat': { action: 'keep', note: 'Kept verbatim.' },
268
270
  'Memory': { action: 'keep', note: 'Kept verbatim.' },
271
+ 'Loom Routing': {
272
+ action: 'replace',
273
+ body: LOOM_ROUTING_BODY,
274
+ note: 'Loom delegation rides the Claude Code Agent tool; Codex has no subagent delegation — commands run inline. Preambles and bin/loom.sh calls marked skippable.',
275
+ },
269
276
  'Git Workflow': {
270
277
  action: 'keep',
271
278
  note: 'Kept; slash tokens rendered as $skill tokens. Branch diagram unchanged (code fence).',
@@ -72,12 +72,12 @@ _apply_framework_update() {
72
72
  fi
73
73
  # Apply upstream changes — checkout is idempotent, skip diff check
74
74
  # (git diff with variable path lists breaks in zsh — no word-splitting)
75
- for _p in bin/ .claude/commands/ .claude/skills/ .claude/hooks/ .claude/context/ CLAUDE.md skills/; do
75
+ for _p in bin/ .claude/commands/ .claude/skills/ .claude/hooks/ .claude/context/ .claude/agents/ loom/ CLAUDE.md skills/; do
76
76
  git checkout upstream/main -- "$_p" 2>/dev/null || true
77
77
  done
78
78
  # Only commit if there are actual changes
79
- if [ -n "$(git status --porcelain bin/ .claude/ CLAUDE.md skills/ 2>/dev/null | head -1)" ]; then
80
- git add bin/ .claude/ CLAUDE.md skills/ 2>/dev/null
79
+ if [ -n "$(git status --porcelain bin/ .claude/ loom/ CLAUDE.md skills/ 2>/dev/null | head -1)" ]; then
80
+ git add bin/ .claude/ loom/ CLAUDE.md skills/ 2>/dev/null
81
81
  EGREGORE_FRAMEWORK_UPDATE=1 git commit -m "Auto-update Egregore framework" --quiet 2>/dev/null || true
82
82
  FRAMEWORK_UPDATED="true"
83
83
  fi
@@ -162,3 +162,13 @@ PROJ_HASH=$(echo -n "$SCRIPT_DIR" | md5 2>/dev/null || echo -n "$SCRIPT_DIR" | m
162
162
  echo "$EGREGORE_SESSION_ID" > "$SESSION_ID_DIR/session-${PROJ_HASH}.id"
163
163
  # Also write project-local file (CLAUDE.md reads this — no glob needed)
164
164
  echo "$EGREGORE_SESSION_ID" > "$SCRIPT_DIR/.egregore-session-id"
165
+
166
+ # Model stamp hashes the git common-dir root because telemetry.sh resolves it that way.
167
+ MODEL_REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir 2>/dev/null | sed 's|/\.git$||') || MODEL_REPO_ROOT="$SCRIPT_DIR"
168
+ MODEL_PROJ_HASH=$(echo -n "$MODEL_REPO_ROOT" | md5 2>/dev/null || echo -n "$MODEL_REPO_ROOT" | md5sum 2>/dev/null | cut -d' ' -f1)
169
+ MODEL_STAMP_FILE="$SESSION_ID_DIR/session-model-${MODEL_PROJ_HASH}"
170
+ if [ -n "${CLAUDE_MODEL:-}" ]; then
171
+ echo "$CLAUDE_MODEL" > "$MODEL_STAMP_FILE"
172
+ else
173
+ rm -f "$MODEL_STAMP_FILE"
174
+ fi
@@ -98,6 +98,13 @@ _resolve_org() {
98
98
  fi
99
99
  }
100
100
 
101
+ _resolve_proj_hash() {
102
+ # Use git common dir so worktrees hash to the same path as the main checkout
103
+ local repo_root
104
+ repo_root=$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir 2>/dev/null | sed 's|/\.git$||') || repo_root="$SCRIPT_DIR"
105
+ echo -n "$repo_root" | md5 2>/dev/null || echo -n "$repo_root" | md5sum 2>/dev/null | cut -d' ' -f1
106
+ }
107
+
101
108
  _resolve_session_id() {
102
109
  if [ -n "${EGREGORE_SESSION_ID:-}" ]; then
103
110
  echo "$EGREGORE_SESSION_ID"
@@ -106,11 +113,8 @@ _resolve_session_id() {
106
113
 
107
114
  # Fallback: read from file written by session-start.sh
108
115
  # (env vars from hooks don't propagate into the Claude Code agent)
109
- # Use git common dir so worktrees hash to the same path as the main checkout
110
- local repo_root
111
- repo_root=$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir 2>/dev/null | sed 's|/\.git$||') || repo_root="$SCRIPT_DIR"
112
116
  local proj_hash
113
- proj_hash=$(echo -n "$repo_root" | md5 2>/dev/null || echo -n "$repo_root" | md5sum 2>/dev/null | cut -d' ' -f1)
117
+ proj_hash=$(_resolve_proj_hash)
114
118
  local sid_file="$HOME/.egregore/session-${proj_hash}.id"
115
119
  if [ -f "$sid_file" ]; then
116
120
  cat "$sid_file" 2>/dev/null || echo "unknown"
@@ -119,6 +123,45 @@ _resolve_session_id() {
119
123
  fi
120
124
  }
121
125
 
126
+ _resolve_model() {
127
+ local proj_hash
128
+ proj_hash=$(_resolve_proj_hash)
129
+ local model_file="$HOME/.egregore/session-model-${proj_hash}"
130
+ if [ ! -s "$model_file" ]; then
131
+ return 0
132
+ fi
133
+
134
+ local model=""
135
+ IFS= read -r model < "$model_file" || true
136
+ if [ -n "$model" ]; then
137
+ printf '%s\n' "$model"
138
+ fi
139
+ }
140
+
141
+ _stamp_model_if_absent() {
142
+ local compact_data="$1"
143
+ local has_model=""
144
+ has_model=$(printf '%s' "$compact_data" | jq -e 'has("model")' 2>/dev/null || true)
145
+ if [ "$has_model" != "false" ]; then
146
+ printf '%s' "$compact_data"
147
+ return 0
148
+ fi
149
+
150
+ local model=""
151
+ model=$(_resolve_model 2>/dev/null || true)
152
+ if [ -z "$model" ]; then
153
+ printf '%s' "$compact_data"
154
+ return 0
155
+ fi
156
+
157
+ local stamped_data=""
158
+ if stamped_data=$(printf '%s' "$compact_data" | jq -c --arg m "$model" 'if has("model") then . else . + {model:$m} end' 2>/dev/null); then
159
+ printf '%s' "$stamped_data"
160
+ else
161
+ printf '%s' "$compact_data"
162
+ fi
163
+ }
164
+
122
165
  # --- emit: append event to local JSONL buffer ---
123
166
  cmd_emit() {
124
167
  local event_type="${1:?Usage: telemetry.sh emit <type> <json>}"
@@ -129,12 +172,15 @@ cmd_emit() {
129
172
  return 0
130
173
  fi
131
174
 
175
+ local ts
176
+ ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
177
+ # Compact data to single line — callers may pass pretty-printed JSON
178
+ local compact_data
179
+ compact_data=$(printf '%s' "$data" | tr -d '\n' | tr -s ' ')
180
+ compact_data=$(_stamp_model_if_absent "$compact_data")
181
+
132
182
  # Debug mode: print to stderr instead of writing
133
183
  if _is_debug; then
134
- local ts
135
- ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
136
- local compact_data
137
- compact_data=$(printf '%s' "$data" | tr -d '\n' | tr -s ' ')
138
184
  printf '{"ts":"%s","type":"%s","sid":"%s","org":"%s","user":"%s","data":%s}\n' \
139
185
  "$ts" "$event_type" "$(_resolve_session_id)" "$(_resolve_org)" "$(_resolve_user)" "$compact_data" >&2
140
186
  return 0
@@ -144,11 +190,6 @@ cmd_emit() {
144
190
  mkdir -p "$BUFFER_DIR"
145
191
 
146
192
  # Build event line (outside lock for minimal hold time)
147
- local ts
148
- ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
149
- # Compact data to single line — callers may pass pretty-printed JSON
150
- local compact_data
151
- compact_data=$(printf '%s' "$data" | tr -d '\n' | tr -s ' ')
152
193
  local line
153
194
  line=$(printf '{"ts":"%s","type":"%s","sid":"%s","org":"%s","user":"%s","data":%s}' \
154
195
  "$ts" "$event_type" "$(_resolve_session_id)" "$(_resolve_org)" "$(_resolve_user)" "$compact_data")