os-vault: add SessionStart git pull for multi-machine vault/memsearch freshness
Sync was push-only via SessionEnd (vault_sync.py/memsearch_sync.py); a second machine's copies could go stale. session_start.py now runs a fast-forward-only, 10s-timeout git pull for both repos before the staleness check — silent on success, quiet one-line stderr note on failure, never blocking session start. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Mb3V8NNzAuns7vgX9A2jU
This commit is contained in:
parent
c629959f37
commit
cc450c385b
|
|
@ -1,6 +1,6 @@
|
||||||
# cc-os implementation status & changelog
|
# cc-os implementation status & changelog
|
||||||
|
|
||||||
_Last updated: 2026-07-08. This is the append-only implementation-status record moved out of
|
_Last updated: 2026-07-10. This is the append-only implementation-status record moved out of
|
||||||
`CLAUDE.md` (2026-07-08, task B1 of
|
`CLAUDE.md` (2026-07-08, task B1 of
|
||||||
[system-prompt-profiles-tasks.md](plans/system-prompt-profiles-tasks.md)). CLAUDE.md keeps
|
[system-prompt-profiles-tasks.md](plans/system-prompt-profiles-tasks.md)). CLAUDE.md keeps
|
||||||
orientation only; when a build step completes, record it HERE (plus
|
orientation only; when a build step completes, record it HERE (plus
|
||||||
|
|
@ -113,15 +113,23 @@ drift — see "Editing a local plugin (cache refresh)" below. Investigation resu
|
||||||
caches (not manifest-naming issues) were the cause; slash command registration works
|
caches (not manifest-naming issues) were the cause; slash command registration works
|
||||||
correctly once caches are fresh.
|
correctly once caches are fresh.
|
||||||
|
|
||||||
**Remaining optional items:** SessionStart vault pull (multi-machine sync; push-only is the
|
**Multi-machine freshness closed (2026-07-10):** `session_start.py` gained a fast-forward-only
|
||||||
current design); additional project onboarding (one at a time, per ADR-013); bulk vault
|
`git pull` (`timeout 10 git pull --ff-only --quiet`) for both `cfg.vault_path` and
|
||||||
migration. All required build steps complete as of 2026-06-15.
|
`cfg.memsearch_dir`, run before the staleness check — silent on success, quiet one-line stderr
|
||||||
|
note on failure (offline machine), never blocking session start. Closes the push-only gap noted
|
||||||
|
below; mirrors the push style of `vault_sync.py`/`memsearch_sync.py` in the opposite direction.
|
||||||
|
|
||||||
|
**Remaining optional items:** additional project onboarding (one at a time, per ADR-013); bulk
|
||||||
|
vault migration. All required build steps complete as of 2026-06-15.
|
||||||
|
|
||||||
## Implemented components
|
## Implemented components
|
||||||
|
|
||||||
**Global os-vault plugin** — `cc-os/plugins/os-vault/` (git-tracked, 2026-06-12); symlinked
|
**Global os-vault plugin** — `cc-os/plugins/os-vault/` (git-tracked, 2026-06-12); symlinked
|
||||||
into `~/.claude/plugins/os-vault`
|
into `~/.claude/plugins/os-vault`
|
||||||
- Hooks: `hooks/` — `session_start.py`, `session_context.py` (project graph path only),
|
- Hooks: `hooks/` — `session_start.py` (SessionStart; staleness check + detached graph
|
||||||
|
rebuild, and, as of 2026-07-10, a fast-forward-only `git pull` for `cfg.vault_path` and
|
||||||
|
`cfg.memsearch_dir` before the staleness check — silent on success, quiet one-line stderr
|
||||||
|
note on failure, never blocking), `session_context.py` (project graph path only),
|
||||||
`post_tool_use_write.py`, `session_end.py` (vault journal), `memsearch_sync.py` (second
|
`post_tool_use_write.py`, `session_end.py` (vault journal), `memsearch_sync.py` (second
|
||||||
SessionEnd hook; memsearch auto-commit+push, 30s timeout), `vault_sync.py` (third
|
SessionEnd hook; memsearch auto-commit+push, 30s timeout), `vault_sync.py` (third
|
||||||
SessionEnd hook; vault auto-commit+push to forgejo.swansoncloud.com/jared/SecondBrain, 30s
|
SessionEnd hook; vault auto-commit+push to forgejo.swansoncloud.com/jared/SecondBrain, 30s
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,10 @@ pushes the vault to `forgejo.swansoncloud.com/jared/SecondBrain` on every sessio
|
||||||
daily journal note from `session_end.py` is included in the commit. Mirrors the
|
daily journal note from `session_end.py` is included in the commit. Mirrors the
|
||||||
`memsearch_sync.py` pattern; uses `cfg.vault_path`. Smoke-tested (exit 0) 2026-06-15.
|
`memsearch_sync.py` pattern; uses `cfg.vault_path`. Smoke-tested (exit 0) 2026-06-15.
|
||||||
|
|
||||||
**Remaining (optional):** SessionStart `git pull` for multi-machine freshness — push-only today.
|
**Multi-machine freshness — DONE (2026-07-10):** `session_start.py` now runs a fast-forward-only
|
||||||
|
`git pull` (`timeout 10`, `--ff-only --quiet`) against both `cfg.vault_path` and
|
||||||
|
`cfg.memsearch_dir` before the staleness check. Silent on success; a quiet one-line stderr note
|
||||||
|
on failure (offline machine, diverged history) that never blocks or delays session start.
|
||||||
|
|
||||||
**Do not sync** the Graphify `graphify-out/` directories, Milvus caches, or the Ollama
|
**Do not sync** the Graphify `graphify-out/` directories, Milvus caches, or the Ollama
|
||||||
models. Graphs are rebuilt per machine from the vault (the single source of truth).
|
models. Graphs are rebuilt per machine from the vault (the single source of truth).
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,25 @@ def _log(line):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _pull_repo(repo_dir):
|
||||||
|
"""Fast-forward-only pull for a sync'd repo. Silent on success; at most a
|
||||||
|
one-line stderr note on failure (offline machine must never block or
|
||||||
|
error out session start). Mirrors vault_sync.py / memsearch_sync.py push
|
||||||
|
style but in the opposite direction (Step 5b multi-machine freshness).
|
||||||
|
"""
|
||||||
|
if not os.path.isdir(os.path.join(repo_dir, ".git")):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
r = subprocess.run(
|
||||||
|
["timeout", "10", "git", "-C", repo_dir, "pull", "--ff-only", "--quiet", "origin", "main"],
|
||||||
|
stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, text=True,
|
||||||
|
)
|
||||||
|
if r.returncode != 0:
|
||||||
|
print(f"[session-start] pull skipped for {repo_dir} (offline or diverged)", file=sys.stderr)
|
||||||
|
except Exception:
|
||||||
|
print(f"[session-start] pull skipped for {repo_dir}", file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
def _needs_rebuild(stamp, stale_days):
|
def _needs_rebuild(stamp, stale_days):
|
||||||
if not os.path.exists(stamp):
|
if not os.path.exists(stamp):
|
||||||
return True
|
return True
|
||||||
|
|
@ -80,6 +99,9 @@ def main():
|
||||||
|
|
||||||
cfg = config_mod.load_config()
|
cfg = config_mod.load_config()
|
||||||
|
|
||||||
|
_pull_repo(cfg.vault_path)
|
||||||
|
_pull_repo(cfg.memsearch_dir)
|
||||||
|
|
||||||
_emit_usage_note()
|
_emit_usage_note()
|
||||||
|
|
||||||
if os.environ.get("OS_VAULT_SKIP_REBUILD"):
|
if os.environ.get("OS_VAULT_SKIP_REBUILD"):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue