@dosx/agent-memory 0.0.13

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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +142 -0
  3. package/bin/agent-memory.js +496 -0
  4. package/hooks/README.md +292 -0
  5. package/hooks/agent-memory-hooks/agent-memory-common.sh +1020 -0
  6. package/hooks/agent-memory-hooks/agent-memory-session.sh +98 -0
  7. package/hooks/agent-memory-hooks/agent-memory-sync.sh +147 -0
  8. package/hooks/claude-code/settings.json +51 -0
  9. package/hooks/codex/config.toml.snippet +38 -0
  10. package/hooks/codex/hooks.json +51 -0
  11. package/hooks/copilot/agent-memory.json +34 -0
  12. package/hooks/cursor/hooks.json +36 -0
  13. package/hooks/gemini/settings.json +50 -0
  14. package/hooks/git/pre-commit +45 -0
  15. package/hooks/install-hooks.sh +358 -0
  16. package/hooks/opencode/agent-memory.ts +320 -0
  17. package/package.json +22 -0
  18. package/skills/agent-memory/SKILL.md +185 -0
  19. package/skills/agent-memory/references/agent-block.md +115 -0
  20. package/skills/agent-memory/references/bootstrap.md +84 -0
  21. package/skills/agent-memory/references/init.md +211 -0
  22. package/skills/agent-memory/references/install-hooks.md +113 -0
  23. package/skills/agent-memory/references/lint.md +113 -0
  24. package/skills/agent-memory/references/sync.md +120 -0
  25. package/skills/agent-memory/references/update.md +145 -0
  26. package/skills/agent-memory/vendor/README.md +132 -0
  27. package/skills/agent-memory/vendor/UPDATE.md +369 -0
  28. package/skills/agent-memory/vendor/memory/active-work/TEMPLATE.md +33 -0
  29. package/skills/agent-memory/vendor/memory/current.md +34 -0
  30. package/skills/agent-memory/vendor/memory/decisions.md +30 -0
  31. package/skills/agent-memory/vendor/memory/index.md +55 -0
  32. package/skills/agent-memory/vendor/memory/instructions.md +340 -0
  33. package/skills/agent-memory/vendor/memory/log.md +38 -0
@@ -0,0 +1,98 @@
1
+ #!/bin/bash
2
+ # agent-memory sessionStart / NewSession hook — inject context + deterministic
3
+ # memory refresh. Captures session_id from harness stdin JSON when provided.
4
+ # On new session: refresh current.md In progress from active-work/ + log state.
5
+ # No-op when .agents/memory/ is absent.
6
+ #
7
+ # Set AGENT_MEMORY_HOST: cursor | claude | codex | copilot | opencode | gemini
8
+
9
+ set -u
10
+
11
+ host="${AGENT_MEMORY_HOST:-}"
12
+
13
+ script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
14
+ _common_sh="$script_dir/agent-memory-common.sh"
15
+ if [ ! -f "$_common_sh" ]; then
16
+ printf 'agent-memory: missing agent-memory-common.sh beside %s; install all three hooks/agent-memory-hooks/*.sh together (see hooks/README.md)\n' \
17
+ "$(basename -- "$0")" >&2
18
+ exit 0
19
+ fi
20
+ # shellcheck source=agent-memory-common.sh
21
+ . "$_common_sh"
22
+
23
+ agent_memory_init_context || exit 0
24
+
25
+ [ -d "$memory" ] || exit 0
26
+
27
+ session_id=$(resolve_session_id "$hook_stdin_session_id" 0)
28
+ [ -n "$session_id" ] || write_state current_session_id ""
29
+ persist_session_id "$session_id"
30
+ reset_logged_files_if_session_changed "$session_id" sessionStart
31
+
32
+ # New session: ensure active-work, log heading, current.md in-progress list.
33
+ if command -v git >/dev/null 2>&1 && git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1; then
34
+ refresh_branch_cache
35
+ aw=$(ensure_active_work)
36
+ update_task_stub "$aw"
37
+ ensure_session_log_heading "$session_id" sessionStart
38
+ refresh_current_in_progress
39
+ fi
40
+
41
+ msg="Agent Memory (.agents/memory/). Before tasks: read instructions.md, index.md, current.md, and your branch active-work file. As you work: refine active-work Task/Progress, append semantic bullets under the current session heading in log.md, and record every architecture/design decision in decisions.md. Hooks keep Touched files, log file-bullets, and current.md In progress synced — you own task meaning, log type/summary, and decisions.md. Run /agent-memory sync at checkpoints (end of task, before commit/compaction)."
42
+
43
+ json_escape() {
44
+ local s=$1
45
+ s=${s//\\/\\\\}
46
+ s=${s//\"/\\\"}
47
+ s=${s//$'\n'/\\n}
48
+ s=${s//$'\r'/\\r}
49
+ s=${s//$'\t'/\\t}
50
+ printf '%s' "$s"
51
+ }
52
+
53
+ case "$host" in
54
+ cursor)
55
+ if [ -n "$session_id" ]; then
56
+ printf '{"env":{"AGENT_MEMORY_SESSION_ID":"%s"},"additional_context":"%s"}\n' \
57
+ "$(json_escape "$session_id")" "$(json_escape "$msg")"
58
+ else
59
+ printf '{"additional_context":"%s"}\n' "$(json_escape "$msg")"
60
+ fi
61
+ ;;
62
+ claude)
63
+ if [ -n "$session_id" ]; then
64
+ printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"},"env":{"AGENT_MEMORY_SESSION_ID":"%s"}}\n' \
65
+ "$(json_escape "$msg")" "$(json_escape "$session_id")"
66
+ else
67
+ printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":"%s"}}\n' \
68
+ "$(json_escape "$msg")"
69
+ fi
70
+ ;;
71
+ codex)
72
+ [ -n "$session_id" ] && export AGENT_MEMORY_SESSION_ID="$session_id"
73
+ printf '%s\n' "$msg"
74
+ ;;
75
+ copilot)
76
+ if [ -n "$session_id" ]; then
77
+ printf '{"additionalContext":"%s","env":{"AGENT_MEMORY_SESSION_ID":"%s"}}\n' \
78
+ "$(json_escape "$msg")" "$(json_escape "$session_id")"
79
+ else
80
+ printf '{"additionalContext":"%s"}\n' "$(json_escape "$msg")"
81
+ fi
82
+ ;;
83
+ opencode)
84
+ [ -n "$session_id" ] && export AGENT_MEMORY_SESSION_ID="$session_id"
85
+ printf '%s\n' "$msg"
86
+ ;;
87
+ gemini)
88
+ # Gemini CLI requires strict JSON-only stdout for hooks (no stray text).
89
+ # We return the memory guidance as context. The deterministic work
90
+ # (heading, current.md, etc.) happens as side effects before this output.
91
+ printf '{"context":"%s"}\n' "$(json_escape "$msg")"
92
+ ;;
93
+ *)
94
+ [ -n "$session_id" ] && export AGENT_MEMORY_SESSION_ID="$session_id"
95
+ printf '%s\n' "$msg"
96
+ ;;
97
+ esac
98
+ exit 0
@@ -0,0 +1,147 @@
1
+ #!/bin/bash
2
+ # agent-memory deterministic checkpoint (all harnesses).
3
+ #
4
+ # Evidence-backed updates from git + session ID — no LLM, no invented semantics.
5
+ # Maintains: active-work (Touched files, Task stub), log.md (session heading +
6
+ # file-change bullets on full checkpoints). current.md is refreshed on sessionStart only.
7
+ #
8
+ # Reads harness stdin JSON when present (session_id, cwd, tool_name,
9
+ # tool_input.file_path / tool_input.path / file_path — Claude, Cursor, Copilot,
10
+ # Codex, Gemini). Session ID also from AGENT_MEMORY_SESSION_ID env or state.
11
+ #
12
+ # Set AGENT_MEMORY_EVENT (any host naming):
13
+ # postToolUse | PostToolUse | AfterTool | afterFileEdit
14
+ # — accumulate touched paths from stdin (git-free; no log.md bullets)
15
+ # afterAgentResponse | Stop | agentStop | AfterAgent — end of turn; full git
16
+ # reconciliation (session-cumulative Touched files, log bullets)
17
+ # preCompact | PreCompact | precommit | PreCompress — before compaction or
18
+ # git commit; same as afterAgentResponse
19
+ #
20
+ # Git runs only at afterAgentResponse/preCompact (+ sessionStart in session.sh);
21
+ # postToolUse/afterFileEdit use the branch cache and stdin file path only.
22
+ #
23
+ # Install per host — see hooks/README.md.
24
+
25
+ set -u
26
+
27
+ script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
28
+ _common_sh="$script_dir/agent-memory-common.sh"
29
+ if [ ! -f "$_common_sh" ]; then
30
+ printf 'agent-memory: missing agent-memory-common.sh beside %s; install all three hooks/agent-memory-hooks/*.sh together (see hooks/README.md)\n' \
31
+ "$(basename -- "$0")" >&2
32
+ exit 0
33
+ fi
34
+ # shellcheck source=agent-memory-common.sh
35
+ . "$_common_sh"
36
+
37
+ raw_event="${AGENT_MEMORY_EVENT:-afterAgentResponse}"
38
+ case "$raw_event" in
39
+ postToolUse|PostToolUse|posttool|AfterTool|aftertool|afterFileEdit|afterfileedit)
40
+ event=postToolUse
41
+ ;;
42
+ afterAgentResponse|Stop|stop|agentStop|afterresponse|AfterAgent|afteragent)
43
+ event=afterAgentResponse
44
+ ;;
45
+ preCompact|PreCompact|precompact|precommit|PreCompress|precompress)
46
+ event=preCompact
47
+ ;;
48
+ *) event=afterAgentResponse ;;
49
+ esac
50
+
51
+ agent_memory_init_context || exit 0
52
+
53
+ [ -d "$memory" ] || exit 0
54
+ command -v git >/dev/null 2>&1 || exit 0
55
+ git -C "$cwd" rev-parse --git-dir >/dev/null 2>&1 || exit 0
56
+
57
+ # Normalize harness file path to a repo-relative path, or return non-zero to skip.
58
+ normalize_repo_rel_path() {
59
+ local rel=$1
60
+ case "$rel" in
61
+ *$'\n'* | *$'\r'* | *$'\x1e'*) return 1 ;;
62
+ esac
63
+ case "$rel" in
64
+ "$cwd"/*) rel=${rel#"$cwd"/} ;;
65
+ /*) return 1 ;;
66
+ esac
67
+ case "$rel" in
68
+ .agents/memory/*) return 1 ;;
69
+ esac
70
+ case "/$rel/" in
71
+ */../*) return 1 ;;
72
+ esac
73
+ [ -n "$rel" ] || return 1
74
+ printf '%s' "$rel"
75
+ }
76
+
77
+ case "$event" in
78
+ postToolUse)
79
+ agent_memory_include_commit_files=0
80
+ [ -n "$hook_stdin_tool_file" ] || exit 0
81
+ run_posttool_checkpoint "$hook_stdin_tool_file"
82
+ exit 0
83
+ ;;
84
+ esac
85
+
86
+ session_id=$(resolve_session_id "$hook_stdin_session_id")
87
+ log_session_id=$(normalize_session_id_for_checkpoint "$session_id")
88
+ persist_session_id "$session_id"
89
+
90
+ mark_head_processed() {
91
+ local current_head
92
+ current_head=$(git -C "$cwd" rev-parse HEAD 2>/dev/null || true)
93
+ [ -n "$current_head" ] || return 0
94
+ write_state last_processed_head "$current_head"
95
+ }
96
+
97
+ # Git-free: merge stdin path into session touched set; no log.md bullets.
98
+ run_posttool_checkpoint() {
99
+ local rel=$1 aw accumulated
100
+ rel=$(normalize_repo_rel_path "$rel") || return 0
101
+ accumulated=$(read_state session_touched_files "")
102
+ file_already_logged "$rel" "$accumulated" && return 0
103
+ aw=$(ensure_active_work)
104
+ add_touched_file "$aw" "$rel"
105
+ update_task_stub "$aw"
106
+ }
107
+
108
+ run_full_checkpoint() {
109
+ local list_file=$1 aw resolved_sid filtered_tmp
110
+ aw=$(ensure_active_work)
111
+ update_task_stub "$aw"
112
+ resolved_sid=$(ensure_log_heading_for_checkpoint "$log_session_id")
113
+ if [ -s "$list_file" ]; then
114
+ filtered_tmp=$(mktemp)
115
+ while IFS= read -r f || [ -n "$f" ]; do
116
+ [ -n "$f" ] || continue
117
+ f=$(normalize_repo_rel_path "$f") || continue
118
+ printf '%s\n' "$f" >>"$filtered_tmp"
119
+ done <"$list_file"
120
+ if [ -s "$filtered_tmp" ]; then
121
+ update_touched_files "$aw" "$filtered_tmp"
122
+ append_log_file_bullets "$resolved_sid" "$filtered_tmp"
123
+ else
124
+ write_active_work_touched_from_session "$aw"
125
+ fi
126
+ rm -f "$filtered_tmp"
127
+ else
128
+ write_active_work_touched_from_session "$aw"
129
+ fi
130
+ }
131
+
132
+ case "$event" in
133
+ afterAgentResponse|preCompact)
134
+ agent_memory_include_commit_files=1
135
+ refresh_branch_cache
136
+ list_tmp=$(mktemp)
137
+ list_non_memory_changes >"$list_tmp"
138
+ run_full_checkpoint "$list_tmp"
139
+ rm -f "$list_tmp"
140
+ mark_head_processed
141
+ ;;
142
+ *)
143
+ exit 0
144
+ ;;
145
+ esac
146
+
147
+ exit 0
@@ -0,0 +1,51 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "*",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "AGENT_MEMORY_HOST=claude .claude/hooks/agent-memory-session.sh",
10
+ "timeout": 5
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "PostToolUse": [
16
+ {
17
+ "matcher": "Write|Edit|Bash",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "AGENT_MEMORY_EVENT=PostToolUse .claude/hooks/agent-memory-sync.sh",
22
+ "timeout": 15
23
+ }
24
+ ]
25
+ }
26
+ ],
27
+ "Stop": [
28
+ {
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "AGENT_MEMORY_EVENT=Stop .claude/hooks/agent-memory-sync.sh",
33
+ "timeout": 15
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "PreCompact": [
39
+ {
40
+ "matcher": "auto|manual",
41
+ "hooks": [
42
+ {
43
+ "type": "command",
44
+ "command": "AGENT_MEMORY_EVENT=PreCompact .claude/hooks/agent-memory-sync.sh",
45
+ "timeout": 15
46
+ }
47
+ ]
48
+ }
49
+ ]
50
+ }
51
+ }
@@ -0,0 +1,38 @@
1
+ # Codex hooks can live in a sidecar hooks.json (see hooks.json) OR inline in
2
+ # config.toml under [hooks]. Inline form (project: .codex/config.toml):
3
+ #
4
+ # [features]
5
+ # hooks = true # enabled by default
6
+ #
7
+ # Copy hooks/agent-memory-hooks/agent-memory-sync.sh and agent-memory-session.sh to
8
+ # .codex/hooks/ first (see hooks/README.md).
9
+ #
10
+ # [[hooks.SessionStart]]
11
+ # matcher = "startup|resume"
12
+ # [[hooks.SessionStart.hooks]]
13
+ # type = "command"
14
+ # command = ["sh", "-c", "AGENT_MEMORY_HOST=codex .codex/hooks/agent-memory-session.sh"]
15
+ # timeout = 5
16
+ #
17
+ # [[hooks.PostToolUse]]
18
+ # matcher = "Bash|apply_patch"
19
+ # [[hooks.PostToolUse.hooks]]
20
+ # type = "command"
21
+ # command = ["sh", "-c", "AGENT_MEMORY_EVENT=PostToolUse .codex/hooks/agent-memory-sync.sh"]
22
+ # timeout = 15
23
+ #
24
+ # [[hooks.Stop]]
25
+ # [[hooks.Stop.hooks]]
26
+ # type = "command"
27
+ # command = ["sh", "-c", "AGENT_MEMORY_EVENT=Stop .codex/hooks/agent-memory-sync.sh"]
28
+ # timeout = 15
29
+ #
30
+ # [[hooks.PreCompact]]
31
+ # matcher = "auto|manual"
32
+ # [[hooks.PreCompact.hooks]]
33
+ # type = "command"
34
+ # command = ["sh", "-c", "AGENT_MEMORY_EVENT=PreCompact .codex/hooks/agent-memory-sync.sh"]
35
+ # timeout = 15
36
+ #
37
+ # After adding project hooks, run `/hooks` in the Codex TUI to trust them.
38
+ # Codex hooks are disabled on Windows.
@@ -0,0 +1,51 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "AGENT_MEMORY_HOST=codex .codex/hooks/agent-memory-session.sh",
10
+ "timeout": 5
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "PostToolUse": [
16
+ {
17
+ "matcher": "Bash|apply_patch",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "AGENT_MEMORY_EVENT=PostToolUse .codex/hooks/agent-memory-sync.sh",
22
+ "timeout": 15
23
+ }
24
+ ]
25
+ }
26
+ ],
27
+ "Stop": [
28
+ {
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "AGENT_MEMORY_EVENT=Stop .codex/hooks/agent-memory-sync.sh",
33
+ "timeout": 15
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "PreCompact": [
39
+ {
40
+ "matcher": "auto|manual",
41
+ "hooks": [
42
+ {
43
+ "type": "command",
44
+ "command": "AGENT_MEMORY_EVENT=PreCompact .codex/hooks/agent-memory-sync.sh",
45
+ "timeout": 15
46
+ }
47
+ ]
48
+ }
49
+ ]
50
+ }
51
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ "version": 1,
3
+ "hooks": {
4
+ "sessionStart": [
5
+ {
6
+ "type": "command",
7
+ "bash": "AGENT_MEMORY_HOST=copilot .github/hooks/agent-memory-session.sh",
8
+ "timeoutSec": 5
9
+ }
10
+ ],
11
+ "postToolUse": [
12
+ {
13
+ "type": "command",
14
+ "bash": "AGENT_MEMORY_EVENT=postToolUse .github/hooks/agent-memory-sync.sh",
15
+ "matcher": "bash|edit|write|apply_patch",
16
+ "timeoutSec": 15
17
+ }
18
+ ],
19
+ "agentStop": [
20
+ {
21
+ "type": "command",
22
+ "bash": "AGENT_MEMORY_EVENT=agentStop .github/hooks/agent-memory-sync.sh",
23
+ "timeoutSec": 15
24
+ }
25
+ ],
26
+ "preCompact": [
27
+ {
28
+ "type": "command",
29
+ "bash": "AGENT_MEMORY_EVENT=preCompact .github/hooks/agent-memory-sync.sh",
30
+ "timeoutSec": 15
31
+ }
32
+ ]
33
+ }
34
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": 1,
3
+ "hooks": {
4
+ "sessionStart": [
5
+ {
6
+ "command": "AGENT_MEMORY_HOST=cursor .cursor/hooks/agent-memory-session.sh",
7
+ "timeout": 5
8
+ }
9
+ ],
10
+ "postToolUse": [
11
+ {
12
+ "command": "AGENT_MEMORY_EVENT=postToolUse .cursor/hooks/agent-memory-sync.sh",
13
+ "matcher": "Write|Shell",
14
+ "timeout": 15
15
+ }
16
+ ],
17
+ "afterFileEdit": [
18
+ {
19
+ "command": "AGENT_MEMORY_EVENT=afterFileEdit .cursor/hooks/agent-memory-sync.sh",
20
+ "timeout": 15
21
+ }
22
+ ],
23
+ "afterAgentResponse": [
24
+ {
25
+ "command": "AGENT_MEMORY_EVENT=afterAgentResponse .cursor/hooks/agent-memory-sync.sh",
26
+ "timeout": 15
27
+ }
28
+ ],
29
+ "preCompact": [
30
+ {
31
+ "command": "AGENT_MEMORY_EVENT=preCompact .cursor/hooks/agent-memory-sync.sh",
32
+ "timeout": 15
33
+ }
34
+ ]
35
+ }
36
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "*",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "AGENT_MEMORY_HOST=gemini .gemini/hooks/agent-memory-session.sh",
10
+ "timeout": 5000
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "AfterTool": [
16
+ {
17
+ "matcher": "write_file|edit|shell|bash|apply_patch",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "AGENT_MEMORY_EVENT=AfterTool .gemini/hooks/agent-memory-sync.sh",
22
+ "timeout": 15000
23
+ }
24
+ ]
25
+ }
26
+ ],
27
+ "AfterAgent": [
28
+ {
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "AGENT_MEMORY_EVENT=AfterAgent .gemini/hooks/agent-memory-sync.sh",
33
+ "timeout": 15000
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "PreCompress": [
39
+ {
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "AGENT_MEMORY_EVENT=PreCompress .gemini/hooks/agent-memory-sync.sh",
44
+ "timeout": 15000
45
+ }
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,45 @@
1
+ #!/bin/sh
2
+ # agent-memory git pre-commit hook (host-agnostic).
3
+ #
4
+ # Runs the deterministic sync script when co-installed, then reminds when
5
+ # staged work has no .agents/memory/ change (semantic fields may still need
6
+ # /agent-memory sync). Never blocks the commit. Fails open.
7
+ #
8
+ # Install:
9
+ # cp hooks/git/pre-commit .git/hooks/pre-commit
10
+ # cp hooks/agent-memory-hooks/agent-memory-*.sh .git/hooks/
11
+ # chmod +x .git/hooks/pre-commit .git/hooks/agent-memory-*.sh
12
+
13
+ # GIT_PREFIX is the subdirectory where the user ran `git commit`, not the repo
14
+ # root — never use it as PROJECT_DIR (would skip memory when committing from src/).
15
+ cwd=$(git rev-parse --show-toplevel 2>/dev/null) || exit 0
16
+ [ -d "$cwd/.agents/memory" ] || exit 0
17
+
18
+ hook_dir=$(dirname "$0")
19
+ if [ -x "$hook_dir/agent-memory-sync.sh" ]; then
20
+ AGENT_MEMORY_EVENT=precommit AGENT_MEMORY_PROJECT_DIR="$cwd" "$hook_dir/agent-memory-sync.sh" || true
21
+ fi
22
+
23
+ staged=$(git diff --cached --name-only 2>/dev/null | grep -v '^\.agents/memory/' || true)
24
+ [ -n "$staged" ] || exit 0
25
+
26
+ # Branch sanitization must mirror common.sh:sanitize_branch so the reminder
27
+ # path matches the file ensure_active_work writes. (This hook is /bin/sh and
28
+ # does not source common.sh, so the logic is duplicated by necessity.)
29
+ branch=$(git branch --show-current 2>/dev/null)
30
+ branch=$(printf '%s' "$branch" | tr -c 'A-Za-z0-9._-' '-')
31
+ [ -n "$branch" ] || branch="local"
32
+
33
+ memory_staged=$(git diff --cached --name-only 2>/dev/null | grep '^\.agents/memory/' || true)
34
+
35
+ if [ -z "$memory_staged" ]; then
36
+ cat <<EOF
37
+
38
+ [agent-memory] Staged work on branch '$branch' but no .agents/memory/ change in this commit.
39
+ Hooks updated Touched files from git; review task/progress in
40
+ \`.agents/memory/active-work/$branch.md\` and run \`/agent-memory sync\` if needed.
41
+ (This is a reminder, not a block — the commit will proceed.)
42
+
43
+ EOF
44
+ fi
45
+ exit 0