phase: 184_sync_bounded_session
Build and Push Containers / build-and-push-app (push) Successful in 1m53s
Build and Push Containers / build-and-push-db (push) Successful in 13s

All gates green; no code changes were needed — the prior failure was a missing final report, not a test failure.

**Verified / implemented (phase 184 final pass)**
- All 4 tasks present in `.agents/phases/complete/184_sync_bounded_session/`; confirmed their output in the worktree: `sync_session_reset_files=200` / `sync_prune_batch=500` on `Settings` (+ non-negative validators), both `SettingMeta` rows under `"Import & sources"`, `.env.example` + `README.md` entries.
- `import_sources` expunges at **exactly two** sites (per-file loop top L972, source boundary L1012) — grep proves no third `expunge`/`expire_all` anywhere in `app/`; `app/db.py:30` untouched.
- `_prune` uses `load_only(id, source, path, is_image, image_path, page_count).order_by(Document.id)` + per-batch commits, with the phase-122/126 guards and `changed_paths` intact.

**Tests / lint / coverage (all 100% green)**
- `uv run pytest --cov=app --cov-report=term-missing` → **4506 passed**, `app/` TOTAL **99%** (>90%).
- `uv run pytest tests/integration/test_import_session_retention.py -v --no-cov` → **12 passed**.
- `uv run pytest tests/e2e/test_sync_session_reset.py -v --no-cov` → **4 passed in isolation**.
- Regression sweep of neighbouring sync suites (each isolated): `test_sync_changed_only` 3, `test_sync_summary_visibility` 3, `test_prune_cascade_cleanup` 3, `test_sync_git_freeze` 2 — all passed.
- `uv run ruff check .` → All checks passed. `uv run pyright` → 0 errors, 0 warnings.

**Completion criteria**
1. Settings + CATALOG + `.env.example` + README; `test_settings_catalog.py` → ✅ green
2. Retention test green with the post-fix bound and both measured numbers in the docstring (pre-fix 12-row monotone staircase / ≈265 MB extrapolated; post-fix ends at 0, add-path peak 14 vs 21→49) → ✅
3. Expunge only at the two documented-safe points; light-row batched prune with guards intact → ✅
4. Every existing importer/sync/removal test green with unchanged expectations → ✅
5. Full suite green, coverage >90%, ruff + pyright clean → ✅
6. Phase E2E green in isolation → ✅
7. README + AGENTS accurate/consistent → ✅
8. Atomic commit — left to the harness (I ran no git write commands).

**Documentation** — Full README (1886 lines) + AGENTS.md (189 lines) review: **verified consistent — no changes needed.** Programmatic cross-checks: every `Settings` field appears in `.env.example` and in the README config reference; every `.env.example` var is documented in that reference; every `tests/…` and `app/…` path cited in README/AGENTS exists; all 10 README page URLs are registered in `app/main.py`; documented E2E port vars (`E2E_APP_PORT_SYNCRESET[_ZERO]`) exist in the test. The only reference-var without a `Settings` field is `BOR_THEME`, which the README explicitly documents as retired (correct as written).

**Notable decisions/deviations** — None. No code, test, or doc edits were made this pass; changes remain entirely in the working tree for the harness to stage. `00_phase.md` still sits in `todo/` while tasks 01–04 are in `complete/` — harness-owned, so I left it untouched.

**Next pending phase:** `185_sync_defer_content_fast_path`.
This commit is contained in:
2026-10-15 23:19:27 -04:00
parent 7b5ea7c2ee
commit 065304b52f
40 changed files with 3512 additions and 13 deletions
+55
View File
@@ -906,3 +906,58 @@ def test_ui_customization_env_overrides(monkeypatch: pytest.MonkeyPatch) -> None
assert s.footer_text == "Powered by my own models"
monkeypatch.setenv("BOR_INPUT_PLACEHOLDER", "")
assert _settings().input_placeholder == "" # empty stands
# --- Sync session bounds (phase 184) ---
def test_sync_session_reset_files_default_and_env_override(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Phase 184 (LOCKED A3): the import walk releases its session every
``BOR_SYNC_SESSION_RESET_FILES`` files (default 200). ``0`` is accepted
and means NEVER release — the exact pre-phase-184 behaviour, the
operator's no-redeploy rollback."""
monkeypatch.delenv("BOR_SYNC_SESSION_RESET_FILES", raising=False)
assert _settings().sync_session_reset_files == 200
monkeypatch.setenv("BOR_SYNC_SESSION_RESET_FILES", "50")
assert _settings().sync_session_reset_files == 50
monkeypatch.setenv("BOR_SYNC_SESSION_RESET_FILES", "0")
assert _settings().sync_session_reset_files == 0
def test_sync_session_reset_files_rejects_negative(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""A negative cadence is a typo — a ``%`` against it never fires, so
startup refuses naming the field (the ``agent_max_rounds`` pattern,
phase 184)."""
monkeypatch.setenv("BOR_SYNC_SESSION_RESET_FILES", "-1")
with pytest.raises(ValidationError, match="sync_session_reset_files"):
_settings()
def test_sync_prune_batch_default_and_env_override(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Phase 184 (LOCKED A3): the prune commits every
``BOR_SYNC_PRUNE_BATCH`` deleted documents (default 500). ``0`` is
accepted and means ONE commit at the end of the whole prune — the
exact pre-phase-184 behaviour."""
monkeypatch.delenv("BOR_SYNC_PRUNE_BATCH", raising=False)
assert _settings().sync_prune_batch == 500
monkeypatch.setenv("BOR_SYNC_PRUNE_BATCH", "25")
assert _settings().sync_prune_batch == 25
monkeypatch.setenv("BOR_SYNC_PRUNE_BATCH", "0")
assert _settings().sync_prune_batch == 0
def test_sync_prune_batch_rejects_negative(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""A negative batch size is a typo — the batch comparison would never
fire, so startup refuses naming the field (the ``agent_max_rounds``
pattern, phase 184)."""
monkeypatch.setenv("BOR_SYNC_PRUNE_BATCH", "-1")
with pytest.raises(ValidationError, match="sync_prune_batch"):
_settings()