Files
brain-of-reese/.agents/phases/todo/193_sync_remaining_count/00_phase.md
T
ducoterra 47456a44df chore(agent): phase roadmap from TODO.md, 4 phases (190-193)
Convert the four open TODO items into executable phases (append mode,
starting at 190 after the completed 189):

  190_app_name_settings_fix  - the Settings-panel app name wins over the
      Theme tab; the three brand strings stripped from the Theme tab
      (colors-only); live brand re-apply on save, no reload
  191_source_name_labels_tags - source_labels table + admin API + Sources
      page editor; the separate bounded source_name_hit_bonus retrieval
      boost; label surfacing in the <document> blocks and KB overview
  192_verbatim_inline_midturn - an additive verbatim_block SSE frame at
      the show_text success moment; in-place mid-turn fence hydration;
      the done/restore per-locator dedupe; the done frame, record key,
      restore and shared page stay byte-identical
  193_sync_remaining_count - the running sync/upload label counts down:
      "N remaining" (N = total - done), hidden at the final file; the
      chunk/image/summaries/terminal parts untouched

TODO.md is cleared (its items now live in .agents/phases/todo/).

LLM-Generated: true
2026-10-17 19:35:55 -04:00

6.8 KiB
Raw Blame History

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)

  1. The running label counts UP. frontend/assets/sources.js fmtSyncLabel (L1053–1058): the import phase and the upload job render count = 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.
  2. The data already exists. SyncStatus.files_done / files_total (the phase-64 payload — the running label's only inputs) carry everything: N = total − done is a subtraction, no server change, no new field, no new poll. The #sync-progress line (the phase-152 A4: the untruncated full label rides the button title + #sync-progress via setSyncLabel) gets the new part through the SAME builder — nothing to change there.
  3. 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, fmtSyncPhaseLabel L1089+) 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's count becomes total > 0 && total - done > 0 ? ${total - done} remaining : "" — the owner-confirmed shape (ASSUMPTION A1, confirmed 2026-10-18):
    • N remaining shows while N ≥ 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's files_total is 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 the N remaining one).
  • 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.py IMPORT_FULL_RE L226 + the docstring L93/L213; test_sync_upload_progress.py L653/L667/L850).

ASSUMPTIONS (owner-confirmed 2026-10-18)

  • A1: N remaining while N ≥ 1, hidden at N == 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), the counts_line helper (the terminal result line — UNTOUCHED); app/schemas.py SyncStatus (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 (the counts_line terminal pins — unedited).

Tasks

  1. 01_remaining_label.md — the fmtSyncLabel count part becomes N remaining (the D1 spec), the docstring update, the JS marker pin.
  2. 02_update_pinned_e2e.md — the running-label count pins retarget to the new part (the D2 list); the full suite green.
  3. 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 > 0 guard, the plain-integer shape, the total > 0 guard 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_line pins 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.md and AGENTS.md in 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 the N remaining one; 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 while N ≥ 1, hidden at N == 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_line pins green unedited); the #sync-progress line carries the new part through the same builder (the A4 pin).
  • test suite green, coverage >90%; uv run ruff check . && uv run pyright clean.
  • 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.