Files
obsidian-wiki/scripts/daily-update.sh
T
nac 777607dc29 chore(repo): establish project baseline
Track the source-of-truth code, skills, bootstrap rules, docs, and packaging files before adding new features.

Exclude local vault config, generated skill mirrors, temporary exports, virtual environments, and business data files from version control.

Validation: inspected staged file list and git ignored status before commit.
2026-07-05 11:03:40 +00:00

115 lines
3.2 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Daily wiki index update — called by launchd or directly.
# Checks if any history sources are stale and writes vault-scoped state files
# that the shell prompt reads on terminal open.
#
# Config resolution order (mirrors llm-wiki/SKILL.md protocol):
# 1. Walk up from CWD looking for .env with OBSIDIAN_VAULT_PATH
# 2. Fall back to ~/.obsidian-wiki/config
# 3. Exit with error if neither found
_find_config() {
local dir="$PWD"
while [[ "$dir" != "$HOME" && "$dir" != "/" ]]; do
if [[ -f "$dir/.env" ]] && grep -q "OBSIDIAN_VAULT_PATH" "$dir/.env" 2>/dev/null; then
echo "$dir/.env"
return
fi
dir="$(dirname "$dir")"
done
if [[ -f "$HOME/.obsidian-wiki/config" ]]; then
echo "$HOME/.obsidian-wiki/config"
return
fi
echo ""
}
CONFIG_FILE="$(_find_config)"
if [[ -z "$CONFIG_FILE" ]]; then
echo "[wiki-daily] No config found. Run wiki-setup to initialize your wiki." >&2
exit 1
fi
# shellcheck source=/dev/null
source "$CONFIG_FILE"
if [[ -z "${OBSIDIAN_VAULT_PATH:-}" ]]; then
echo "[wiki-daily] OBSIDIAN_VAULT_PATH not set in $CONFIG_FILE — skipping" >&2
exit 1
fi
# Vault-scoped state dir (supports multiple vaults independently)
VAULT_ID=$(echo "$OBSIDIAN_VAULT_PATH" | md5sum 2>/dev/null | cut -c1-8 || \
md5 -q - <<< "$OBSIDIAN_VAULT_PATH" 2>/dev/null | cut -c1-8 || \
echo "default")
STATE_DIR="$HOME/.obsidian-wiki/state/$VAULT_ID"
mkdir -p "$STATE_DIR"
# Write vault path so wiki-notify.sh can find this state dir
echo "$OBSIDIAN_VAULT_PATH" > "$STATE_DIR/.vault_path"
MANIFEST="$OBSIDIAN_VAULT_PATH/.manifest.json"
# Count sources modified after last ingest
stale_count=0
if [[ -f "$MANIFEST" ]]; then
last_updated=$(python3 -c "
import json, sys
try:
d = json.load(open('$MANIFEST'))
print(d.get('last_updated',''))
except:
print('')
" 2>/dev/null || echo "")
if [[ -n "$last_updated" ]]; then
stale_count=$(MANIFEST="$MANIFEST" OBSIDIAN_VAULT_PATH="$OBSIDIAN_VAULT_PATH" python3 - <<'PYEOF'
import json, os, sys
from datetime import datetime, timezone
manifest_path = os.environ["MANIFEST"]
try:
with open(manifest_path) as f:
manifest = json.load(f)
except Exception:
print(0)
sys.exit()
last_updated_str = manifest.get("last_updated", "")
try:
last_updated = datetime.fromisoformat(last_updated_str.replace("Z", "+00:00"))
except Exception:
print(0)
sys.exit()
vault_path = os.environ.get("OBSIDIAN_VAULT_PATH", "")
stale = 0
for path, meta in manifest.get("sources", {}).items():
expanded = os.path.expanduser(path)
if not os.path.isabs(expanded) and vault_path:
expanded = os.path.join(vault_path, expanded)
if os.path.exists(expanded):
mtime = datetime.fromtimestamp(os.path.getmtime(expanded), tz=timezone.utc)
if mtime > last_updated:
stale += 1
print(stale)
PYEOF
)
fi
fi
# Write vault-scoped state
NOW=$(date +%s)
echo "$NOW" > "$STATE_DIR/.last_update"
echo "$stale_count" > "$STATE_DIR/.pending_delta"
if [[ "$stale_count" -gt 0 ]]; then
echo "[wiki-daily] $stale_count source(s) have new content since last ingest. State: $STATE_DIR"
else
echo "[wiki-daily] Wiki is up to date. State: $STATE_DIR"
fi