docs(backup): document seed-vs-runtime ignore architecture + add logs/ default
Confirmed (via @backup) the two-layer ignore model and wrote it down so it stops getting re-discovered: - BUILTIN_IGNORES (patterns.py) = the SEED that generates a new project's .backupignore at register; never consulted at backup time. - .backupignore (via load_spec) = the runtime source of truth. No static fallback exists, so the seed is safety-critical — an empty .backupignore backs up everything (.venv, node_modules, .git) and can crash the machine. Added a 'How Ignores Work' README section + code comments on BUILTIN_IGNORES and load_spec. Added logs/ to the seed so new projects exclude log dirs (prax .jsonl output) by default, not just *.log files, with a test. seedgo @backup 100%. td-27.
This commit is contained in:
@@ -64,6 +64,16 @@ PyPI version — not the changelog header.
|
||||
a step to audit every open todo against the actual system (`ls`/`find`/`git
|
||||
ls-files`/`grep`/`audit`) and close what's verifiably done — catching todos
|
||||
finished in a past session but never closed.
|
||||
- **Backup ignore architecture documented** — confirmed and written down the
|
||||
two-layer model so it stops getting re-discovered: `BUILTIN_IGNORES` is the
|
||||
**seed** that generates a new project's `.backupignore` at register and is
|
||||
never consulted at backup time; `.backupignore` (via `load_spec`) is the
|
||||
**runtime source of truth**. There's no static fallback, so the seed is
|
||||
safety-critical — an empty `.backupignore` backs up everything and can crash
|
||||
the machine. Added a "How Ignores Work" README section + code comments on
|
||||
`BUILTIN_IGNORES` and `load_spec`. Also added `logs/` to the seed so new
|
||||
projects exclude log directories (e.g. prax `.jsonl` output) by default, not
|
||||
just `*.log` files (td-27).
|
||||
|
||||
## [2026-06-23]
|
||||
|
||||
|
||||
@@ -105,15 +105,17 @@ The root `.gitignore` covers all three with a single `.backup/` entry.
|
||||
|
||||
---
|
||||
|
||||
## `.backupignore`
|
||||
## How Ignores Work
|
||||
|
||||
A true `.gitignore` for backups, using real pathspec/gitwildmatch semantics:
|
||||
- `#` comments, blank lines ignored
|
||||
- `!` negation (un-ignore a path)
|
||||
- Trailing `/` for directory-only matching
|
||||
- Last-match-wins ordering
|
||||
Two layers — seed and runtime:
|
||||
|
||||
Lives at the **project root** and is the single source of truth governing snapshot, versioned, Drive sync, and mirror-cleanup operations. Generated from `BUILTIN_IGNORES` in `handlers/ignore/patterns.py` during `register`. The `.backup/` directory is included in `BUILTIN_IGNORES`, so the store self-excludes from its own backups.
|
||||
1. **`BUILTIN_IGNORES`** (`handlers/ignore/patterns.py`) — the **seed**. Written into a new project's `.backupignore` at `register` time (`setup._build_backupignore()`). Never consulted at backup time.
|
||||
2. **`.backupignore`** — the **runtime source of truth**. `load_spec()` reads it on every backup; `BUILTIN_IGNORES` is not applied. True pathspec/gitwildmatch semantics: `#` comments, `!` negation, trailing `/` for dirs, last-match-wins.
|
||||
|
||||
There is no static fallback. The seed IS the safety mechanism — an empty or missing `.backupignore` means back up everything (`.venv`, `node_modules`, `.git`), which can crash the machine. Keep `BUILTIN_IGNORES` sane.
|
||||
|
||||
- To change defaults for **new** projects → edit `BUILTIN_IGNORES` in `patterns.py`
|
||||
- To change ignores for an **existing** project → edit its `.backupignore`
|
||||
|
||||
The repo-root `/.backupignore` ships intentionally as the curated default so users don't snapshot junk.
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ import pathspec
|
||||
from ..json import json_handler
|
||||
from ..path import builder
|
||||
|
||||
# Seed for new-project .backupignore (written at register by setup._build_backupignore).
|
||||
# NOT applied at backup time — runtime ignores come from .backupignore via load_spec().
|
||||
# Keep sane: empty seed = back up everything = crash.
|
||||
BUILTIN_IGNORES = [
|
||||
".backup/",
|
||||
".git/",
|
||||
@@ -40,6 +43,7 @@ BUILTIN_IGNORES = [
|
||||
"build/",
|
||||
"dist/",
|
||||
"*.log",
|
||||
"logs/",
|
||||
".ruff_cache/",
|
||||
".coverage",
|
||||
]
|
||||
@@ -48,6 +52,7 @@ BUILTIN_IGNORES = [
|
||||
def load_spec(project_root: str) -> pathspec.PathSpec:
|
||||
"""Load a PathSpec from .backupignore at the project root.
|
||||
|
||||
This is the runtime source of truth — BUILTIN_IGNORES is not consulted here.
|
||||
Reads raw lines — pathspec handles #comments, blanks, !negation,
|
||||
anchoring, dir-only trailing /, and last-match-wins natively.
|
||||
|
||||
|
||||
@@ -250,6 +250,10 @@ class TestSeedTemplate:
|
||||
"""Seed defaults include .coverage."""
|
||||
assert ".coverage" in BUILTIN_IGNORES
|
||||
|
||||
def test_builtin_has_logs_dir(self):
|
||||
"""Seed defaults exclude logs/ directories."""
|
||||
assert "logs/" in BUILTIN_IGNORES
|
||||
|
||||
def test_build_backupignore_content(self):
|
||||
"""Seed template includes ruff_cache, coverage, and pycache."""
|
||||
from aipass.backup.apps.handlers.project.setup import _build_backupignore
|
||||
|
||||
Reference in New Issue
Block a user