**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`.
62 lines
2.7 KiB
Python
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)
|