Non-default graphs were second-class citizens — timers only maintained the default graph, git sync ignored named graphs, there was no way to create a graph without editing config manually, cross-graph edge errors were confusing, and utility scripts were hardcoded to the default graph. - Add `graph-create` CLI command + `create_graph()` in common.py, with custom path registration written to the default graph's _config.json - Add `scripts/maintain-all-graphs.sh` to loop decay/core/embed/reflect over all discovered graphs; update systemd services to call it - Refactor `memory-git-sync.sh` into sync_repo() function that iterates default + all named graphs with .git directories - Improve cross-graph edge ValueError to explain the same-graph constraint - Add --graph flag to edge-proposer.py and session_memory.py - Update systemd/README.md with portable paths and new architecture Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
104 lines
4.2 KiB
Bash
Executable File
104 lines
4.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# Commit and push cognitive memory changes to Gitea.
|
|
#
|
|
# Syncs the default graph and any named graphs whose directory is a git repo.
|
|
# Called daily by cognitive-memory-daily.service after decay/core runs.
|
|
# Safe to run multiple times — only commits when there are actual changes.
|
|
#
|
|
# Default graph: COGNITIVE_MEMORY_DIR > XDG_DATA_HOME > ~/.local/share/cognitive-memory
|
|
# Named graphs: ~/.local/share/cognitive-memory-graphs/<name>/ (any with .git/)
|
|
#
|
|
# Location: ~/.claude/skills/cognitive-memory/scripts/memory-git-sync.sh
|
|
|
|
set -uo pipefail
|
|
# Note: -e intentionally omitted at the top level so that one graph's failure
|
|
# does not prevent the remaining graphs from being synced. Each function call
|
|
# is checked explicitly.
|
|
|
|
# ── resolve directories ────────────────────────────────────────────────────────
|
|
|
|
MEMORY_DIR="${COGNITIVE_MEMORY_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/cognitive-memory}"
|
|
|
|
# Named graphs live in a sibling directory: cognitive-memory-graphs/<name>/
|
|
GRAPHS_BASE_DIR="${MEMORY_DIR%cognitive-memory}cognitive-memory-graphs"
|
|
|
|
# ── sync function ──────────────────────────────────────────────────────────────
|
|
# sync_repo <dir> <label>
|
|
# Commits and pushes any pending changes in the given git repo directory.
|
|
# Returns 0 on success or "nothing to commit", non-zero on error.
|
|
sync_repo() {
|
|
local dir="$1"
|
|
local label="$2"
|
|
|
|
# Directory must exist and be a git repo
|
|
if [ ! -d "$dir/.git" ]; then
|
|
echo "memory-git-sync [$label]: not a git repo, skipping"
|
|
return 0
|
|
fi
|
|
|
|
(
|
|
# Run everything inside a subshell so cd is scoped and set -e is safe
|
|
set -euo pipefail
|
|
cd "$dir"
|
|
|
|
# Nothing to commit?
|
|
if git diff --quiet && git diff --cached --quiet \
|
|
&& [ -z "$(git ls-files --others --exclude-standard)" ]; then
|
|
echo "memory-git-sync [$label]: no changes to commit"
|
|
exit 0
|
|
fi
|
|
|
|
# Stage all changes (.gitignore handles exclusions)
|
|
git add -A
|
|
|
|
# Build a descriptive commit message
|
|
ADDED=$(git diff --cached --name-only --diff-filter=A | wc -l)
|
|
MODIFIED=$(git diff --cached --name-only --diff-filter=M | wc -l)
|
|
DELETED=$(git diff --cached --name-only --diff-filter=D | wc -l)
|
|
EDGES=$(git diff --cached --name-only --diff-filter=ACM | grep -c '^graph/edges/' || true)
|
|
|
|
MSG="daily sync: ${ADDED} added, ${MODIFIED} modified, ${DELETED} deleted"
|
|
if [ "$EDGES" -gt 0 ]; then
|
|
MSG="$MSG (${EDGES} edges)"
|
|
fi
|
|
|
|
git commit -m "$MSG" --no-gpg-sign 2>/dev/null || {
|
|
echo "memory-git-sync [$label]: commit failed (pre-commit hook?)"
|
|
exit 1
|
|
}
|
|
|
|
git push origin main 2>/dev/null || {
|
|
echo "memory-git-sync [$label]: push failed"
|
|
exit 1
|
|
}
|
|
|
|
echo "memory-git-sync [$label]: pushed to origin/main"
|
|
)
|
|
}
|
|
|
|
# ── sync default graph ─────────────────────────────────────────────────────────
|
|
|
|
ERRORS=0
|
|
|
|
sync_repo "$MEMORY_DIR" "default" || ERRORS=$((ERRORS + 1))
|
|
|
|
# ── sync named graphs ──────────────────────────────────────────────────────────
|
|
# Iterate subdirectories of GRAPHS_BASE_DIR; skip non-git directories silently.
|
|
|
|
if [ -d "$GRAPHS_BASE_DIR" ]; then
|
|
for graph_dir in "$GRAPHS_BASE_DIR"/*/; do
|
|
# glob may yield literal "*/'" if directory is empty
|
|
[ -d "$graph_dir" ] || continue
|
|
|
|
graph_name="$(basename "$graph_dir")"
|
|
sync_repo "$graph_dir" "$graph_name" || ERRORS=$((ERRORS + 1))
|
|
done
|
|
fi
|
|
|
|
# ── exit status ───────────────────────────────────────────────────────────────
|
|
|
|
if [ "$ERRORS" -gt 0 ]; then
|
|
echo "memory-git-sync: completed with $ERRORS error(s)"
|
|
exit 1
|
|
fi
|