mattrguerra/better-memory-pipelinemainPrivate on GitHub, published here in full

INSTALL.md

Language Markdown3.7 KB79 lines

docs/INSTALL.md

  1. # Installing better-memory
  2. One script (plus an optional second one) and one launchd job on a Mac, then a
  3. scheduled Cowork task for the distiller. Replace `CHANGEME` with the macOS username.
  4. ## The shape
  5. vaults -> gate.py (20:00, launchd) -> ~/cowork-staging/staging -> distiller (20:30, Cowork) -> Notion better-memory
  6. ## 1. Decide the walls first
  7. Open `gate.py` and read `_BASE_DENY_PREFIXES` and `DENY_COMPONENTS`. Every folder that
  8. must stay out of a database your phone reads has to be named there (prefixes are
  9. relative to a vault root and match case-insensitively; components match a folder name
  10. at any depth). Add any that are missing, and add a matching probe to the startup
  11. self-check in `main()` so the gate refuses to run if that wall ever stops blocking.
  12. This is the one review that matters. `EXTRA_DENY` (comma-separated prefixes) adds
  13. walls without editing the file.
  14. ## 2. Install the scripts
  15. mkdir -p ~/.local/bin/better-memory ~/cowork-staging
  16. cp gate.py content_gate.py scheduling/run-nightly.sh ~/.local/bin/better-memory/
  17. chmod +x ~/.local/bin/better-memory/*
  18. ## 3. Run it by hand against the live vaults
  19. VAULT_ROOTS="$HOME/Documents/vaults/workbench:$HOME/Documents/vaults/identity" \
  20. STAGING_DIR="$HOME/cowork-staging" \
  21. python3 ~/.local/bin/better-memory/gate.py
  22. You want one line: `gate: staged=N skipped=N framing-only=N scaffold-skipped=N total-staged=N -> <staging dir>`.
  23. Then check the walls held, naming your own walled folders:
  24. ls ~/cowork-staging/staging | grep -iE '_private|finance|journal' \
  25. && echo "WALL LEAK, STOP" || echo "walls holding"
  26. If the gate prints `DENYLIST FAILED to block ...`, that is it refusing to run because a
  27. wall is not blocking. Fix the denylist; do not force it. Run it a second time: it should
  28. stage 0.
  29. Point `VAULT_ROOTS` at the live vaults, never at a copy or a mirror that may be missing
  30. the very folders the walls exist for.
  31. ## 4. Schedule it
  32. Edit `scheduling/com.example.better-memory.plist` (replace every `CHANGEME`; confirm the
  33. `python3` path in `run-nightly.sh` matches `which python3`), and set `VAULT_ROOTS` in
  34. `run-nightly.sh`. Then:
  35. cp scheduling/com.example.better-memory.plist ~/Library/LaunchAgents/
  36. launchctl load ~/Library/LaunchAgents/com.example.better-memory.plist
  37. launchctl start com.example.better-memory
  38. cat ~/cowork-staging/better-memory.log
  39. It now runs nightly at 20:00. To stop it: `launchctl unload` the same plist.
  40. ## 5. The distiller
  41. 1. In Notion, create a database named `better-memory` with the properties in
  42. [`distiller/notion-schema.md`](../distiller/notion-schema.md), and seed the Tags
  43. vocabulary.
  44. 2. Authorize the Notion connector in Claude against that workspace. Click-through
  45. authorization; no token touches a vault or a script.
  46. 3. Install [`distiller/better-memory-nightly-distill`](../distiller/better-memory-nightly-distill/SKILL.md)
  47. as a skill, with the database's URL and data source ID filled in.
  48. 4. Create a Cowork scheduled task for 20:30 that runs the skill, bound to
  49. `~/cowork-staging/staging` only.
  50. 5. Keep the database read-only from every interactive session.
  51. ## The optional content gate
  52. `run-nightly.sh` runs `content_gate.py` after the path gate. It removes (or, with
  53. `BM_GATE_MODE=redact`, redacts) any staged file with `private: true`, `gate: block` or
  54. `visibility: private` in its frontmatter, and any line carrying `%% bm:private %%` or
  55. matching its patterns. It writes `gate-report.json` into staging listing every decision.
  56. It is a backstop for filing mistakes, not semantic privacy: a private thought in
  57. ordinary words, with no flag and no pattern, passes. Delete its lines from the wrapper
  58. to run the path gate alone.