Files
brain-of-reese/tests/e2e/sync_helpers.py
T
ducoterra c054b47df5
Build and Push Containers / build-and-push-app (push) Successful in 1m47s
Build and Push Containers / build-and-push-db (push) Successful in 13s
phase: 187_sync_peak_memory_line
**Phase 187 — final verification pass: all criteria met, repo 100% green.**

Verified (all four tasks already in `complete/`)
- `app/core/memory.py`: `rss_mb` / `rss_peak_mb` / `cgroup_peak_mb` / `fmt_mb`, pure stdlib, never-raise, **100%** coverage, 24 branch tests.
- Lifecycle lines append-only: `sync: started … rss_mb=`, all three terminals `… rss_mb= rss_peak_mb=` (failed = sanitized one-liner beside the surviving `logger.exception`), `import: summary … rss_mb=`; prefixes byte-identical.
- `GET /api/sync/status`: additive `rss_mb`/`rss_peak_mb` (`int|null`), keyed off the ONE `_sample_rss` (run start, phase transitions, forced terminals, 5 s-throttled hook), `peak >= current` invariant, anonymous 403.
- `sources.js` `fmtSyncPeakClause`: ` · peak <N> MB` trailing the counts line / "Sync cancelled", nothing when null, no new control/live region.

Gates (exact commands)
- `uv run pytest --cov=app --cov-report=term-missing` → **4570 passed**, TOTAL **99%**, `app/api/sync.py` **100%**, `app/core/memory.py` **100%**
- `uv run ruff check .` → clean · `uv run pyright` → **0 errors**
- `uv run pytest tests/e2e/test_sync_peak_memory_visible.py -v --no-cov` → **5 passed in isolation** (ran twice)
- All 27 touched E2E families re-run **in isolation**, all green (progress_box 8, cancel 3, status_freshness 4, summary_visibility 3, sync_button 3, session_reset 4, git_freeze 2, git_log_stream_dates 5, PDF/image suites, …)

Completion criteria: every checkbox ✅ except the commit + phase-dir move, which belong to the harness.

Documentation
- README reviewed in full (pages, commands, config tables cross-checked against `app/config.py` — 85 env rows, all defaults match; phase-187 ops section, greps, process-vs-cgroup caveat): consistent, no changes needed.
- `AGENTS.md`: **fixed one pre-existing inconsistency** — rule 6 claimed the no-CDN test covers "the index page"; it actually parametrizes 10 pages (all but `/doc-edit.html`).

Notable
- Two failures early in the pass were self-inflicted by running the E2E module concurrently with the full suite on the shared Postgres (TRUNCATE deadlock + one order-dependent `test_overview` flake); both vanish under the documented serial isolation — no code defect, no change made.
- **PLAN §9 still needs the owner's reconciliation** (phase 187 adds the sync memory fields + two status keys; PLAN is never agent-edited — AGENTS rule 10 carries the spec). `TODO.md` holds an unrelated owner note, left untouched.

Next pending phase: `188_chunks_hnsw_index`.
2026-10-16 15:22:51 -04:00

62 lines
2.7 KiB
Python

"""Shared sync-result-line helpers (phase 187, task 03).
The Sources page's sync result line — the ``fmtSyncResult`` counts line
and the neutral ``"Sync cancelled"`` line the ``#sync-progress`` box
speaks — now trails the run's PEAK-MEMORY clause (`` · peak 1936 MB``),
sourced from ``GET /api/sync/status``'s additive ``rss_peak_mb`` /
``rss_mb`` pair (the 2026-10-15 incident: "how much RAM did that sync
use?" used to mean reading ``systemd`` unit-teardown lines off three
boots; now it is on the page that started the run and in the log).
The clause is per-run DATA, so the suites that pin the OWNER-VISIBLE
counts pin the counts plus an OPTIONAL clause:
* :func:`counts_line` — a Playwright-ready pattern: the exact expected
line, with `` · peak <N> MB`` allowed at the end (and the whole line
anchored, so a mutated counts line still fails);
* :func:`strip_peak_clause` — for the suites that compare two runs' or
two apps' lines byte-for-byte: the memory number belongs to the
process, not to the KB, so it is not part of a byte-identity contract.
A NULL pair renders NOTHING (``fmtSyncPeakClause``), which is why the
clause is optional rather than required: an idle app, a status that
predates phase 187, and the upload job all settle without it.
"""
from __future__ import annotations
import re
#: The clause sources.js appends (``fmtSyncPeakClause``), as a regex —
#: optional, because a null peak/current pair appends the empty string.
PEAK_CLAUSE = r"(?: · peak \d+ MB)?"
#: The same clause, for a substitution (``strip_peak_clause``): anchored
#: at end of line, so nothing else is ever stripped.
_PEAK_CLAUSE_TAIL = re.compile(r" · peak \d+ MB$")
def counts_line(expected: str | re.Pattern[str]) -> re.Pattern[str]:
"""Match the EXACT ``expected`` sync result line, clause included or
not — the pin a suite writes when it cares about the counts, not
about the number of megabytes the run happened to reach.
``expected`` is either the literal line (escaped, so the ``·`` and
the digits mean exactly what they say) or a suite's own shape
pattern (its anchors are dropped and re-applied around the optional
clause, so ``^3 added$`` becomes ``^3 added(?: · peak \\d+ MB)?$``).
"""
if isinstance(expected, re.Pattern):
body = expected.pattern
if body.startswith("^"):
body = body[1:]
if body.endswith("$"):
body = body[:-1]
return re.compile(rf"^{body}{PEAK_CLAUSE}$")
return re.compile(rf"^{re.escape(expected)}{PEAK_CLAUSE}$")
def strip_peak_clause(text: str) -> str:
"""``text`` without its trailing peak clause (if any) — the
byte-identity comparison's view of the line."""
return _PEAK_CLAUSE_TAIL.sub("", text)