Canonical config for the /monthly-dedupe autonomous sweep. The skill (samaguiar1982-cpu/sail-skills -> skills/monthly-dedupe/SKILL.md) reads this page first; .credentials/vault.env is fallback only. Change a value here and the next run picks it up. No drift.

Scan scope

SCAN_ROOTS = ~/Downloads, ~/Documents, ~/Desktop, home-root loose files
EXCLUDES   = Library, .git, node_modules, Parallels, Repos, Codex, SAIL-Logs, go, sam-wp, printing-press, iCloud Drive (Archive) variants
MIN_FILE_KB = 100

Safety thresholds (circuit breakers)

MAX_RECLAIM_GB    = 5     # over this in one run -> escalate, trash nothing, ask Sam
MAX_FILES         = 500   # over this many files -> escalate
MAX_AMBIGUOUS      = 25    # more than this many no-clear-canonical groups -> escalate
MIN_FILE_AGE_DAYS = 7     # never touch files newer than this
AUTO_PURGE_AFTER_DAYS = 0  # 0 = never auto-empty Trash (destructive; leave 0 unless Sam opts in)

Notifications

TEAMS_SUCCESS_PING = on   # one-line Teams summary on success (3A); alerts-only if off
SAM_IMESSAGE = 502-991-2491   # primary alert + iMessage target
SAM_IMESSAGE_ALT = csamaguiar@gmail.com, samaguiar1982@gmail.com   # alternate Apple ID / iMessage handles
SAM_TEAMS_ID = <PENDING: Sam's Microsoft 365 / Teams UPN - can be resolved via Graph if desired>

Note: iMessage target is set (cell 502-991-2491, with two alternate Apple ID handles). Teams DM target still needs Sam's Microsoft 365 UPN; until set, the Teams ping logs its text in the export instead of sending and the run flags it in self-audit. iMessage alerts are fully live.

Paths and IDs

DEDUPE_SCRIPT_PATH = sail-skills repo (referenced from GitHub, not pinned to a machine path)
REPORT_DIR    = ~/Documents/   (dedupe-report-YYYY-MM-DD.json)
MANIFEST_DIR  = ~/Documents/   (dedupe-manifest-YYYY-MM-DD.json + restore-YYYY-MM-DD.sh)
SAIL_KB_DATA_SOURCE = 13d5d9db-4588-41bc-afa9-45ce9e23e56c

Behavior summary

Move-to-Trash only (reversible). Rollback manifest + restore script every run. Verify-before-move re-hash. One canonical copy survives per group via the deterministic selection chain in the skill. Emptying Trash stays manual unless AUTO_PURGE_AFTER_DAYS is raised.