create-egregore 0.21.0-runtime-mvp.18 → 0.21.0-runtime-mvp.19

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // egregore-launcher-version: 0.21.0-runtime-mvp.18
2
+ // egregore-launcher-version: 0.21.0-runtime-mvp.19
3
3
  //
4
4
  // egregore — launch and browse Egregore instances from your terminal.
5
5
  // Installed by create-egregore. Reads ~/.egregore/instances.json.
@@ -35,7 +35,7 @@ const crypto = require("node:crypto");
35
35
  const { spawnSync, spawn } = require("node:child_process");
36
36
  const readline = require("node:readline");
37
37
 
38
- const VERSION = "0.21.0-runtime-mvp.18";
38
+ const VERSION = "0.21.0-runtime-mvp.19";
39
39
  const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
40
40
  const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
41
41
  const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.21.0-runtime-mvp.18",
3
+ "version": "0.21.0-runtime-mvp.19",
4
4
  "description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env bash
2
+ # memory-read-guard.sh — PreToolUse hook for Read and Bash.
3
+ #
4
+ # After a Runtime retrieval, memory sources are opened through the private
5
+ # evidence packet — `bash bin/search.sh open <path> --context-packet` — and
6
+ # never dumped into the transcript with cat/sed/head/tail or the Read tool.
7
+ # Instructions alone did not hold (2026-09-03: three `sed -n 1,140p` dumps of
8
+ # memory files right after a clean search), so this hook enforces it.
9
+ #
10
+ # Scope: a retrieval episode. The guard engages only while this session's
11
+ # evidence packet is fresh (written within the last EGREGORE_RETRIEVAL_WINDOW_MIN
12
+ # minutes, default 15). Outside an episode — editing a decision record, a skill
13
+ # reading memory, ordinary work — memory reads are untouched. Edit and Write
14
+ # are never the guard's business. Searching memory with grep passes.
15
+ #
16
+ # Exit 0 = allow, exit 2 = block (reason on stderr). Any unexpected failure
17
+ # falls through to allow; the hook must never block by crashing.
18
+ set -u
19
+
20
+ PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(cd "$(dirname "$0")/../.." && pwd)}"
21
+ [ -d "$PROJECT_DIR" ] || exit 0
22
+ INPUT=$(cat 2>/dev/null) || exit 0
23
+ TOOL=$(printf '%s' "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
24
+ case "$TOOL" in Bash|Read) ;; *) exit 0 ;; esac
25
+
26
+ # --- Retrieval episode: this session's packet exists and is fresh ---------
27
+ SESSION=$(cat "$PROJECT_DIR/.egregore-session-id" 2>/dev/null | tr -cd 'A-Za-z0-9_.-')
28
+ [ -n "$SESSION" ] || exit 0
29
+ PACKET="${TMPDIR:-/tmp}/egregore-retrieval-context/$SESSION.context"
30
+ [ -f "$PACKET" ] || exit 0
31
+ WINDOW_MIN="${EGREGORE_RETRIEVAL_WINDOW_MIN:-15}"
32
+ [ -n "$(find "$PACKET" -mmin "-$WINDOW_MIN" 2>/dev/null)" ] || exit 0
33
+
34
+ _block() {
35
+ printf 'Egregore: memory sources are opened through the private evidence packet, not printed into the transcript.\n' >&2
36
+ printf 'Run, one file per call:\n bash bin/search.sh open %s --context-packet\n' "$1" >&2
37
+ printf 'Searching with grep is fine; dumping a file with cat/sed/head/tail or the Read tool is not.\n' >&2
38
+ exit 2
39
+ }
40
+
41
+ if [ "$TOOL" = "Read" ]; then
42
+ FILE=$(printf '%s' "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
43
+ [ -n "$FILE" ] || exit 0
44
+ case "$FILE" in
45
+ "$PROJECT_DIR"/memory/*) _block "memory/${FILE#"$PROJECT_DIR"/memory/}" ;;
46
+ memory/*) _block "$FILE" ;;
47
+ esac
48
+ # The memory symlink's target (the sibling memory repository) counts too.
49
+ MEM_REAL=$(readlink -f "$PROJECT_DIR/memory" 2>/dev/null || true)
50
+ if [ -n "$MEM_REAL" ]; then
51
+ case "$FILE" in "$MEM_REAL"/*) _block "memory/${FILE#"$MEM_REAL"/}" ;; esac
52
+ fi
53
+ exit 0
54
+ fi
55
+
56
+ # --- Bash: a raw reader applied to a memory path -------------------------
57
+ CMD=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
58
+ [ -n "$CMD" ] || exit 0
59
+ case "$CMD" in *bin/search.sh*) exit 0 ;; esac
60
+ MEM_PATH=$(printf '%s' "$CMD" | grep -oE 'memory/[A-Za-z0-9_./@:+-]+' | head -1)
61
+ [ -n "$MEM_PATH" ] || exit 0
62
+ if printf '%s' "$CMD" | grep -qE '(^|[;&|(][[:space:]]*)(cat|sed|head|tail|less|more|awk|bat|nl)([[:space:]]|$)'; then
63
+ _block "$MEM_PATH"
64
+ fi
65
+ exit 0
@@ -56,6 +56,15 @@
56
56
  }
57
57
  ]
58
58
  },
59
+ {
60
+ "matcher": "Read|Bash",
61
+ "hooks": [
62
+ {
63
+ "type": "command",
64
+ "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/memory-read-guard.sh"
65
+ }
66
+ ]
67
+ },
59
68
  {
60
69
  "matcher": "Edit|Write|Bash|EnterWorktree|EnterPlanMode",
61
70
  "hooks": [
@@ -62,6 +62,7 @@
62
62
  ".claude/hooks/branch-guard.sh",
63
63
  ".claude/hooks/card-context.sh",
64
64
  ".claude/hooks/emissary-detect.sh",
65
+ ".claude/hooks/memory-read-guard.sh",
65
66
  ".claude/hooks/memory-refresh.sh",
66
67
  ".claude/hooks/onboarding-guard.sh",
67
68
  ".claude/hooks/retrieval-context.sh",