**Phase 193 — final verification pass: all gates green.**
- **Verified (all 3 tasks already complete in `complete/193_sync_remaining_count/`):** `fmtSyncLabel`'s count part is `total > 0 && total - done > 0 ? \`${total - done} remaining\` : ""` (plain int, hidden at `N==0`, `total===0` → no part); docstrings updated; chunk/image/summaries parts + `counts_line` terminal + `app/` byte-untouched (`git diff --stat`: no `app/` files).
- **Completion criteria:** `N remaining` shape + marker pins ✅ · upload shares the builder (E2E upload arm) ✅ · chunk/image/summaries pins green ✅ · terminal `counts_line` green unedited + A4 title/`#sync-progress` pin ✅ · suite green, coverage 99% ✅ · lint/types clean ✅ · commit + `todo/→complete/` left to the harness (no git index/history commands run).
- `uv run pytest -q --cov=app --cov-report=term-missing` → **exit 0**, junit: **4792 tests, 0 failures/errors/skipped**, `TOTAL 7181 16 → 99%` (>90%)
- `uv run pytest tests/e2e/test_sync_remaining_count.py -v --no-cov` → **3 passed** (isolated, 53 s)
- Isolated `--no-cov` sweep of the 14 sync-lineage suites (label_mobile, upload_progress, chunk_progress, image_progress, progress_box, summary_visibility, archive_upload_sources, status_freshness, upload_no_scan, peak_memory_visible, session_reset, fast_path_deferred_content, git_freeze, smoke) → **14/14 exit 0**
- `uv run ruff check .` → All checks passed · `uv run pyright` → **0 errors**
- **Docs:** README.md reviewed in full (all 2408 lines) + AGENTS.md. Fixed 2 inconsistencies: the sync running-label clause claimed the upload label shows the count — now states it shares the ONE builder/shape but reports no counts since phase 90 (renders bare); phase-190's "the other ~72 rows" → "the other 83 rows of the panel's 86-row catalogue" (mechanically: 86 CATALOG rows, 84 overridable). `N remaining` already in the sync paragraph; task-01's `(n/m)` examples gone. AGENTS.md verified consistent (no clause names the running count part → unchanged per the phase's "do not add if absent"). Mechanically re-verified: all 86 `BOR_*` settings documented + defaults match, `.env.example` 88 vars covered, 0 broken README anchors, all cited file paths exist, 17 palette colors, migrations head `0030`, pages/shell routes, ports 8123/8901, E2E port allocations (new suite's 8211/8914 unique).
- **Notable:** task 02's documented deviation stands — `files_done` is the importer's 1-based *current* file, so the phase doc's `[1-4]` range is unreachable; count-bearing frames are `1 … N−1` (pinned). Pre-existing, untouched: `E2E_APP_PORT_TOOLBUDGET`/`SAVEDOC` both 8129 and `SYNCUP`/`SYCNCEL` both 8133 — harmless under the one-suite-at-a-time rule.
- **Next pending phase:** none — `193_sync_remaining_count` is the last entry in `.agents/phases/todo/`.
6.8 KiB
6.8 KiB
Phase 193 — The sync label counts DOWN: "N remaining"
Source: TODO.md L6 — "The sync status should show how many files are left to sync, not how many files out of the total."
Story: n/a (owner directive)
Depends on: none functionally (builds on the completed phase-64/98/128/129/152 sync-label lineage).
Evidence (diagnosed from the code, read this not the chat)
- The running label counts UP.
frontend/assets/sources.jsfmtSyncLabel(L1053–1058): the import phase and the upload job rendercount = total > 0 ?(${done}/${total}): ""—Syncing… notes/a.md (1234/27000). The owner wants the distance to the end, not the position in the whole:25766 remaining. - The data already exists.
SyncStatus.files_done/files_total(the phase-64 payload — the running label's only inputs) carry everything:N = total − doneis a subtraction, no server change, no new field, no new poll. The#sync-progressline (the phase-152 A4: the untruncated full label rides the button title +#sync-progressviasetSyncLabel) gets the new part through the SAME builder — nothing to change there. - The other count parts are different animals — they stay.
· chunk n/m(phase 129 — one file's embed batch),· image n/m(phase 152 — one PDF's vision span), and the summaries phase's(n/m)(phase 98 — the FOLDER position, always emitted,fmtSyncPhaseLabelL1089+) are per-file / per-folder position parts, not "files of the total". The terminal result line (counts_line— "N added · M updated …") is a different surface and is untouched.
Design (shared by all tasks — the executor reads this, not the chat)
- D1 — the part (task 01).
fmtSyncLabel'scountbecomestotal > 0 && total - done > 0 ?${total - done} remaining: ""— the owner-confirmed shape (ASSUMPTION A1, confirmed 2026-10-18):N remainingshows whileN ≥ 1; at the final file (N == 0) the part is HIDDEN — the main part names the file in flight, and a "0 remaining" next to the last file's name is the stale-looking edge the owner's complaint is about;- plain integer (no thousands separator — the existing count part is plain; the house label style);
- the POSITION is unchanged (main → count → chunk → image — the phase-128 parts rework order);
- the UPLOAD job shares the builder and the format (owner-confirmed A2 —
Importing <file> N remaining; the upload'sfiles_totalis the pre-walk count, the phase-98 contract — the same subtraction semantics); total === 0(the pre-walk null total, the phase-64 contract) → no count part (unchanged);- the chunk / image parts and the summaries-phase folder position are UNTOUCHED (byte-identical);
- the docstring (L1044–1058 region) is updated to the new part (the phase-64/98 lineage paragraph keeps its history, the
(done/total)description becomes theN remainingone).
- D2 — the pinned suites move (task 02). The running-label count pins retarget to the new part; the terminal-line pins stay unedited. The definitive list is found by
grep -rn "Syncing…\|Importing" tests/e2e/*.py | grep -E "\\\\d|/\{N|[0-9]+\)"at execution time (the known pins:test_sync_label_mobile.pyIMPORT_FULL_REL226 + the docstring L93/L213;test_sync_upload_progress.pyL653/L667/L850).
ASSUMPTIONS (owner-confirmed 2026-10-18)
- A1:
N remainingwhileN ≥ 1, hidden atN == 0(the final file — the main part names it). - A2: the upload job shares the format (one builder, one shape).
Context
frontend/assets/sources.js—fmtSyncLabel(L1053–1058),fmtSyncPhaseLabel(L1089+, the phase-aware wrapper: overview / summaries / import),setSyncLabel(the A4 full-label placement — the button title +#sync-progress), thecounts_linehelper (the terminal result line — UNTOUCHED);app/schemas.pySyncStatus(files_done/files_total— the payload, UNTOUCHED);app/api/sync.py(the status endpoint — UNTOUCHED).tests/e2e/test_sync_label_mobile.py,tests/e2e/test_sync_upload_progress.py,tests/e2e/test_sync_chunk_progress.py,tests/e2e/test_sync_summary_visibility.py(the phase-64/98/128/129/152 label suites — the count-part pins; the chunk/image/summaries pins stay),tests/e2e/test_sync_git_freeze.py+test_sync_session_reset.py+test_fast_path_deferred_content.py(thecounts_lineterminal pins — unedited).
Tasks
01_remaining_label.md— thefmtSyncLabelcount part becomesN remaining(the D1 spec), the docstring update, the JS marker pin.02_update_pinned_e2e.md— the running-label count pins retarget to the new part (the D2 list); the full suite green.03_e2e_and_gates.md— the phase's own suite (the count-down through the real UI), the full gates, the docs pass, the atomic commit.
Testing & Quality
- Unit (JS marker pin): the new count expression (
total - done > 0guard, the plain-integer shape, thetotal > 0guard kept, the upload kind sharing the builder — the marker names the expression). - E2E (regression, task 02): the retargeted count pins + the chunk / image / summaries pins green; the terminal
counts_linepins green UNEDITED. - E2E (phase, AGENTS rule 4, task 03):
tests/e2e/test_sync_remaining_count.py, run in isolation — the count-down arm (the part decreases across polls; hidden at the final file; the chunk part coexists), the upload arm (the shared format). - Coverage: >90% on
app/(unchanged — the task is frontend; the app-side gate stays green). - Lint/types:
uv run ruff check . && uv run pyright.
Documentation & Consistency
- Final pass reviews
README.mdandAGENTS.mdin their entirety against the post-phase app and fixes every inconsistency found, pre-existing ones included. README.md: the sync section's running-label description (the(done/total)example, if present) becomes theN remainingone;AGENTS.md— the phase-64 sync-label clause (if it names the count part) gains the new shape (task 03 — verify, do not add if absent).
Completion Criteria
- the running file-count part is
N remaining(N = total − done, plain, shown whileN ≥ 1, hidden atN == 0,total === 0→ no part) — the marker pin + the E2E count-down arm. - the upload label uses the same shape (the E2E upload arm); the chunk / image / summaries parts are byte-identical (the unedited pins green).
- the terminal result line is byte-identical (the
counts_linepins green unedited); the#sync-progressline carries the new part through the same builder (the A4 pin). - test suite green, coverage >90%;
uv run ruff check . && uv run pyrightclean. - no behavior change in completed phases (the server, the payload, the phases of the run all untouched — the change is the one label part).
- one atomic Conventional Commits commit with
--no-gpg-sign.