phase: 152_sync_progress_image_pass
All criteria verified. The CLI path is hook-less (only `app/api/sync.py` passes the hook), and the byte-identity is pinned by `test_on_image_progress_none_run_is_byte_identical`. ## Final Report — Phase 152 final verification pass - **Verified (no new code needed):** `SyncStatus.images_done/images_total` + reset/clear rules in `app/api/sync.py`; `on_image_progress` threaded through the importer's three PDF vision spans with the continuous per-file counter; the `_image_hook` closure; `sources.js` `· image n/m` label part (box + title + aria). - **C1** status climbs 1→N + UI shows `· image n/m`: ✅ unit 3/15→15/15, integration 1/15→7/15, E2E 1/4→4/4 (title/aria ride the full string) - **C2** never frozen: ✅ E2E asserts ≥3 distinct positions, starting at 1, non-decreasing, ≤ total, reaching it - **C3** cleared at overview/summaries + all terminals; per-file reset via `_hook`; no stale position for image-less files: ✅ unit pins + E2E settle (image part gone in box/title/aria, endpoint 0/0) - **C4** `/api/sync/status` additive-only: ✅ full-dict pin passes (all pre-existing keys unchanged + the two new 0/0 keys) - **C5** hook-less caller byte-identical: ✅ CLI passes no hook; `test_on_image_progress_none_run_is_byte_identical` green - **C6** `uv run pytest`: **3526 passed, exit 0** (95s); dedicated E2E in isolation: **2 passed** (95s); `uv run ruff check . && uv run pyright`: **clean**; coverage: **99% on `app/` (>90% gate)** - Regression: all five neighbouring E2E suites green in isolation (progress_box 8, chunk_progress 2, label_mobile 4, pdf_support 6, image_documents 4) - **C7** atomic commit: left to the harness (no git index/history touched per rules) - **Docs:** README.md — sync-label paragraph already updated this phase, accurately; all `.env.example` vars documented; routes/commands verified — **no changes needed**. AGENTS.md — all references (PLAN, user_stories, test_smoke.py, .env.example, gpg config, .gitignore) verified — **no changes needed** - **Defects found in prior work:** none (one prior env-leak defect was already fixed inside this phase's task 04, conftest) - No live-infrastructure touched; no ntfy used. **Next pending phase:** none — `todo/` held only this phase
This commit is contained in:
@@ -127,6 +127,28 @@ setSyncProgress and pins the result mode behaviorally (a settle
|
||||
result line reveals the box, "" empties + hides it); the bare
|
||||
settle's row now shows the box LEFT ALONE (the settle label rides
|
||||
the button only — A2).
|
||||
|
||||
Phase 152 (task 03) adds the label's FOURTH part — the vision-image
|
||||
position: fmtSyncPhaseLabel's import fall-through gains "· image
|
||||
n/m" (rendered while images_total > 0 — a PDF's vision span is in
|
||||
flight; n the 1-based image about to be described, m the file's
|
||||
total images, ONE continuous counter across the PDF's three vision
|
||||
spans), the overview/summaries branches return image: "" (the
|
||||
position belongs to the import phase only — the status's image
|
||||
fields are cleared at those transitions, so the branches never read
|
||||
them), and the bare builder stays image-free (the upload label and
|
||||
the 202/409 click stay bare). setSyncLabel(mainText, countText =
|
||||
"", chunkText = "", running = false, imageText = "") appends the
|
||||
image part LAST to the composed full string — so the box, the
|
||||
button title, and the running aria-label all carry
|
||||
"Syncing… <file> (2/3) · chunk 14/38 · image 3/15". The image part
|
||||
gets NO span of its own (the running button is the spinner — its
|
||||
parts are hidden, phase 149): it rides ONLY the composed string,
|
||||
while the chunk part keeps its .sync-label-chunk span; the two
|
||||
positions are distinct and each disappears independently. The node
|
||||
harness gains the two in-flight image rows (both parts at once —
|
||||
the owner's stuck label — and the image-only pictorial PDF) and
|
||||
pins the composed full string byte-for-byte.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -298,8 +320,9 @@ def test_fmt_sync_label_returns_the_parts_contract() -> None:
|
||||
|
||||
def test_set_sync_label_is_the_single_parts_writer() -> None:
|
||||
"""setSyncLabel(mainText, countText = "", chunkText = "",
|
||||
running = false) — Phase 128 (task 01) + Phase 129 (task 04):
|
||||
the SINGLE point that writes #sync-label. The MAIN part gets
|
||||
running = false, imageText = "") — Phase 128 (task 01) + Phase
|
||||
129 (task 04) + Phase 152 (task 03): the SINGLE point that writes
|
||||
#sync-label. The MAIN part gets
|
||||
mainText (textContent only — the house rule, no HTML strings);
|
||||
the COUNT part gets countText when present (textContent +
|
||||
hidden=false — the "(n/m)" position is visible, NEVER clipped)
|
||||
@@ -309,11 +332,18 @@ def test_set_sync_label_is_the_single_parts_writer() -> None:
|
||||
hidden=true — the part renders only while a file's embed batch
|
||||
is in flight). Then the UNTRUNCATED full label — mainText +
|
||||
(countText ? " " + countText : "") + (chunkText ? " " + chunkText
|
||||
: "") — rides the button title (A4 — the screen reader hears the
|
||||
whole "Syncing… <file> (2/3) · chunk 14/38" there, and in the
|
||||
box — see below). Phase 149 (task 01): the fourth parameter
|
||||
: "") + (imageText ? " " + imageText : "") — rides the button
|
||||
title (A4 — the screen reader hears the
|
||||
whole "Syncing… <file> (2/3) · chunk 14/38 · image 3/15" there,
|
||||
and in the box — see below). The image part (phase 152) gets NO
|
||||
span of its own (the running button is the spinner — its parts
|
||||
are hidden, phase 149): it rides only the composed full string.
|
||||
Phase 149 (task 01): the fourth parameter
|
||||
`running` (the in-flight flag — the running entry passes true,
|
||||
the settle the default false). Phase 150 (task 02): while
|
||||
the settle the default false); phase 152 (task 03) adds the
|
||||
fifth — `imageText` (the bare builders and the non-running calls
|
||||
pass nothing, so it defaults "" and the part stays out of the
|
||||
string). Phase 150 (task 02): while
|
||||
running, the SAME full label goes into the detail box
|
||||
(#sync-progress — the SOLE aria-live region, the announcer the
|
||||
screen reader hears) through the single box writer
|
||||
@@ -324,10 +354,20 @@ def test_set_sync_label_is_the_single_parts_writer() -> None:
|
||||
running / the ship value "Sync sources" otherwise
|
||||
(overwrites/restores only — never removes)."""
|
||||
body = _fn(_js(), "setSyncLabel")
|
||||
assert (
|
||||
'function setSyncLabel(mainText, countText = "", chunkText = "", running = false)'
|
||||
in body
|
||||
), "phase 149: the in-flight flag is the fourth parameter"
|
||||
# the exact signature, byte-for-byte (concatenated — the literal
|
||||
# is 105 columns, over the line cap): main, count, chunk, the
|
||||
# phase-149 `running` flag (fourth), the phase-152 `imageText`
|
||||
# (fifth — the bare builders + non-running calls pass nothing,
|
||||
# so it defaults to the empty string).
|
||||
expected_sig = (
|
||||
'function setSyncLabel(mainText, countText = "", chunkText = "",'
|
||||
' running = false, imageText = "")'
|
||||
)
|
||||
assert expected_sig in body, (
|
||||
"phase 149: the in-flight flag is the fourth parameter; phase"
|
||||
" 152: the image part is the fifth, defaulting to the empty"
|
||||
" string (the part stays out of the composed full string)"
|
||||
)
|
||||
# the parts: textContent only (the house rule), null-guarded refs
|
||||
assert "syncLabelMain.textContent = mainText" in body
|
||||
assert "syncLabelCount.textContent = countText" in body
|
||||
@@ -353,8 +393,12 @@ def test_set_sync_label_is_the_single_parts_writer() -> None:
|
||||
"const full =\n"
|
||||
" mainText +\n"
|
||||
" (countText ? ` ${countText}` : \"\") +\n"
|
||||
" (chunkText ? ` ${chunkText}` : \"\");"
|
||||
) in body, ("the full label is main + ' ' + count + ' ' + chunk (spaces = the CSS gaps)")
|
||||
" (chunkText ? ` ${chunkText}` : \"\") +\n"
|
||||
" (imageText ? ` ${imageText}` : \"\");"
|
||||
) in body, (
|
||||
"the full label is main + ' ' + count + ' ' + chunk + ' ' +"
|
||||
" image — the image part LAST (spaces = the CSS gaps)"
|
||||
)
|
||||
i_full = body.find("const full")
|
||||
i_title = body.find("syncBtn.title = full")
|
||||
i_box = body.find("if (running) setSyncProgress(full);")
|
||||
@@ -375,7 +419,8 @@ def test_set_sync_label_is_the_single_parts_writer() -> None:
|
||||
|
||||
def test_fmt_sync_phase_label_is_the_exact_d2_parts_contract() -> None:
|
||||
"""fmtSyncPhaseLabel(status) — the SYNC job's phase-aware label
|
||||
(phase 98 task 02, D2; phase 128 task 01: the PARTS). "overview"
|
||||
(phase 98 task 02, D2; phase 128 task 01: the PARTS; phase 152
|
||||
task 03: the IMAGE part). "overview"
|
||||
→ main exactly "Writing KB overview…" (no folder, no count part);
|
||||
"summaries" → main "Summarizing folders… <current_summary>" +
|
||||
count "(n/m)" — the folder part (one leading space +
|
||||
@@ -385,7 +430,14 @@ def test_fmt_sync_phase_label_is_the_exact_d2_parts_contract() -> None:
|
||||
a total); anything else (the null prelude, "import") → the
|
||||
phase-64 fmtSyncLabel parts, byte-identical (same builder, same
|
||||
fields, same order). The UPLOAD job never enters here — its status
|
||||
has no phase (D2)."""
|
||||
has no phase (D2). Phase 152 (task 03): the import fall-through
|
||||
is the ONLY branch that reads the status's image fields — "·
|
||||
image n/m" renders while images_total > 0 (a PDF's vision span is
|
||||
in flight — n the 1-based image about to be described, m the
|
||||
file's total images) and hides at 0/0; the overview/summaries
|
||||
branches return image: "" and never read the fields (the position
|
||||
belongs to the import phase only — the runner clears it at those
|
||||
transitions)."""
|
||||
body = _fn(_js(), "fmtSyncPhaseLabel")
|
||||
assert "function fmtSyncPhaseLabel(status)" in body
|
||||
# "overview": the exact copy, no folder, no counts.
|
||||
@@ -421,14 +473,30 @@ def test_fmt_sync_phase_label_is_the_exact_d2_parts_contract() -> None:
|
||||
)
|
||||
assert "chunks_total" not in ov, "the overview branch never reads the chunk fields"
|
||||
assert "chunks_total" not in sum_, "the summaries branch never reads the chunk fields"
|
||||
# phase 152 (task 03): the overview/summaries labels carry NO
|
||||
# image part either (the position belongs to the import phase
|
||||
# only) and never read the status's image fields (the runner
|
||||
# clears them at those transitions).
|
||||
assert 'image: ""' in ov, "the overview label carries no image part"
|
||||
assert 'image: ""' in sum_, (
|
||||
"the summaries label carries no image part (its (n/m) is its position)"
|
||||
)
|
||||
assert "images_total" not in ov, "the overview branch never reads the image fields"
|
||||
assert "images_total" not in sum_, "the summaries branch never reads the image fields"
|
||||
# anything else (null prelude, "import"): byte-identical to today's
|
||||
# sync label — same builder, same fields, same order — plus the
|
||||
# phase-129 chunk part: "· chunk n/m" ONLY while chunks_total > 0
|
||||
# (a file's embed batch is in flight — n the 1-based first chunk
|
||||
# of the batch, m the file's total content chunks, batch
|
||||
# granularity), "" otherwise (0/0 before the first batch — the
|
||||
# part hides). The fall-through is the ONLY branch that reads the
|
||||
# status's chunk fields.
|
||||
# part hides) + the phase-152 image part: "· image n/m" ONLY
|
||||
# while images_total > 0 (a PDF's vision span is in flight — n
|
||||
# the 1-based image about to be described, m the file's total
|
||||
# images — ONE continuous counter across the PDF's three vision
|
||||
# spans), "" otherwise (0/0 — the part hides). The fall-through
|
||||
# is the ONLY branch that reads the status's chunk + image
|
||||
# fields, and the two parts are independent (both may show,
|
||||
# each disappears on its own 0/0).
|
||||
i_destr = body.find("const { main, count } = fmtSyncLabel(")
|
||||
assert -1 < i_destr < i_fall, "the fall-through destructures the phase-64 parts"
|
||||
fall = body[i_destr:]
|
||||
@@ -444,11 +512,22 @@ def test_fmt_sync_phase_label_is_the_exact_d2_parts_contract() -> None:
|
||||
i_guard = fall.find("status.chunks_total > 0")
|
||||
i_else = fall.find(": \"\";", i_guard)
|
||||
assert -1 < i_guard < i_else, "0/0 (before the first batch) → the empty chunk part"
|
||||
assert "return { main, count, chunk }" in fall
|
||||
# phase 152 (task 03): the image part — "· image n/m" ONLY while
|
||||
# images_total > 0, the exact template + the 0/0 → "" guard, and
|
||||
# the return gains the fourth part.
|
||||
assert "status.images_total > 0" in fall, (
|
||||
"the image part renders only while a vision span is in flight"
|
||||
)
|
||||
assert "`· image ${status.images_done}/${status.images_total}`" in fall
|
||||
i_iguard = fall.find("status.images_total > 0")
|
||||
i_ielse = fall.find(": \"\";", i_iguard)
|
||||
assert -1 < i_iguard < i_ielse, "0/0 (before the first image) → the empty image part"
|
||||
assert "return { main, count, chunk, image }" in fall
|
||||
# the bare builder (the upload job + the 202/409 click) returns NO
|
||||
# chunk part — those labels stay bare.
|
||||
# chunk OR image part — those labels stay bare.
|
||||
bare = _fn(_js(), "fmtSyncLabel")
|
||||
assert "chunk" not in bare, "fmtSyncLabel stays chunk-free (upload + the click stay bare)"
|
||||
assert "image" not in bare, "fmtSyncLabel stays image-free (upload + the click stay bare)"
|
||||
|
||||
|
||||
def test_enter_running_state_is_phase_aware_and_writes_the_parts() -> None:
|
||||
@@ -460,13 +539,16 @@ def test_enter_running_state_is_phase_aware_and_writes_the_parts() -> None:
|
||||
endpoint has no phase) and the 202/409 click keep the bare
|
||||
fmtSyncLabel parts, byte-identical. Phase 128 (task 01): the entry
|
||||
itself no longer writes the label — it hands the parts to the
|
||||
SINGLE writer (setSyncLabel(main, count, chunk) — phase 129:
|
||||
the chunk part destructures with a "" default), which lands the
|
||||
SINGLE writer (setSyncLabel(main, count, chunk, running, image) —
|
||||
phase 129: the chunk part destructures with a "" default, phase
|
||||
152: the image part does too), which lands the
|
||||
main part, the pinned count part (hidden when absent), the pinned
|
||||
chunk part (phase 129 — hidden when absent), and the FULL
|
||||
untruncated label on the button title + #sync-progress (A4 — set
|
||||
for EVERY running label; CSS ellipsizes the main part only).
|
||||
Phase 150 (task 02): the box write rides in the writer too
|
||||
for EVERY running label; CSS ellipsizes the main part only —
|
||||
phase 152: with the image part appended last when a PDF's vision
|
||||
span is in flight; it gets no span of its own). Phase 150 (task
|
||||
02): the box write rides in the writer too
|
||||
(setSyncLabel → setSyncProgress, running mode)."""
|
||||
body = _fn(_js(), "enterSyncRunningState")
|
||||
assert (
|
||||
@@ -487,13 +569,16 @@ def test_enter_running_state_is_phase_aware_and_writes_the_parts() -> None:
|
||||
# the parts are handed to the single writer (A4 lives in it) —
|
||||
# phase 129: the chunk part destructures with a "" default (the
|
||||
# bare builders — the upload job, the 202/409 click — return no
|
||||
# chunk part, so the part stays hidden there); phase 149: the
|
||||
# chunk part, so the part stays hidden there); phase 152: the
|
||||
# image part does too (it rides only the composed full string —
|
||||
# no span); phase 149: the
|
||||
# call passes `running = true` (the detail box reveals + the
|
||||
# full-label aria-label ride in the writer).
|
||||
assert "const { main, count, chunk = \"\" } =" in body, (
|
||||
"the chunk part destructures with the '' default (bare builders return none)"
|
||||
assert 'const { main, count, chunk = "", image = "" } =' in body, (
|
||||
"the chunk + image parts destructure with the '' defaults"
|
||||
" (bare builders return none)"
|
||||
)
|
||||
i_set = body.find("setSyncLabel(main, count, chunk, true)")
|
||||
i_set = body.find("setSyncLabel(main, count, chunk, true, image)")
|
||||
assert -1 < i_fall < i_set, "the parts are written after the split (running = true)"
|
||||
assert body.count("setSyncLabel(") == 1, "one writer call per entry"
|
||||
assert "syncBtn.title =" not in body, ("the title write lives in setSyncLabel (A4)")
|
||||
@@ -713,6 +798,25 @@ enterSyncRunningState("sync", "src/a/b.md", 2, 3, {
|
||||
current_chunk: 14, chunks_total: 38,
|
||||
});
|
||||
show("import-inflight");
|
||||
// 1b. Phase 152 (task 03): import, a PDF's vision span in flight
|
||||
// (the owner's stuck label — the last chunk position 125/126 is
|
||||
// STILL on the status + the climbing image position 3/15): the
|
||||
// composed full string carries BOTH parts (chunk keeps its span,
|
||||
// the image part rides the string only — no span):
|
||||
enterSyncRunningState("sync", "src/a/b.md", 2, 3, {
|
||||
phase: "import", current_file: "src/a/b.md", files_done: 2, files_total: 3,
|
||||
current_chunk: 125, chunks_total: 126, images_done: 3, images_total: 15,
|
||||
});
|
||||
show("import-image-span");
|
||||
// 1c. Phase 152 (task 03): import, a purely pictorial PDF (no text
|
||||
// chunks — the chunk position never left 0/0) in its vision
|
||||
// span: the image part shows ALONE (the chunk part stays hidden
|
||||
// + empty — the two parts are independent):
|
||||
enterSyncRunningState("sync", "src/a/b.md", 2, 3, {
|
||||
phase: "import", current_file: "src/a/b.md", files_done: 2, files_total: 3,
|
||||
current_chunk: 0, chunks_total: 0, images_done: 7, images_total: 7,
|
||||
});
|
||||
show("import-image-only");
|
||||
// 2. import before the first batch (0/0) — the chunk part hides:
|
||||
enterSyncRunningState("sync", "src/a/b.md", 2, 3, {
|
||||
phase: "import", current_file: "src/a/b.md", files_done: 2, files_total: 3,
|
||||
@@ -893,6 +997,96 @@ test-document-viewer pattern). The pinned "· chunk n/m" part (the
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
|
||||
def test_image_part_renders_only_in_the_import_phase_under_node() -> None:
|
||||
"""Phase 152 (task 03): behavioral check (node) of the REAL label
|
||||
path — the extracted fmtSyncPhaseLabel / setSyncLabel /
|
||||
enterSyncRunningState run against the stub element refs. The
|
||||
pinned "· image n/m" part (the task's fixture values):
|
||||
|
||||
* import, a PDF's vision span in flight (images_total 15 > 0)
|
||||
WITH the last chunk position still on the status (125/126):
|
||||
the composed full string carries BOTH parts — the box, the
|
||||
button title, and the running aria-label all read exactly
|
||||
"Syncing… src/a/b.md (2/3) · chunk 125/126 · image 3/15"
|
||||
(the owner's stuck label, now moving); the chunk part KEEPS
|
||||
its span ("· chunk 125/126" visible) and the image part gets
|
||||
NO span of its own (it rides the composed string only — the
|
||||
running button is the spinner, phase 149);
|
||||
* import, a purely pictorial PDF (the chunk position never left
|
||||
0/0) in its vision span: the image part shows ALONE —
|
||||
"Syncing… src/a/b.md (2/3) · image 7/7" — and the chunk part
|
||||
stays hidden + empty (the two parts are distinct and each
|
||||
disappears independently on its own 0/0);
|
||||
* every OTHER running state (the pre-batch import, the prelude,
|
||||
the 202/409 click, the upload run, the overview, the
|
||||
summaries — the status's image fields are 0/0 or cleared at
|
||||
those transitions) leaves the composed string image-free.
|
||||
|
||||
The box / Cancel-control / is-running contracts of the running
|
||||
state apply to the new rows exactly as to every other running
|
||||
state (the harness's other pins cover them per tag)."""
|
||||
rows = _chunk_harness_rows()
|
||||
by_tag = {row[0]: row for row in rows}
|
||||
# row = [tag, title, announcer (the box's text — the sole live
|
||||
# region, phase 150), main, count, countHidden, chunk,
|
||||
# chunkHidden, cancelHidden, cancelDisabled, progressText,
|
||||
# progressHidden, btnRunning, iconSpinning, ariaLabel]
|
||||
|
||||
# 1b. both parts at once — the composed full string, byte-for-byte
|
||||
# (the image part LAST, after the chunk part), on the box, the
|
||||
# title, and the running aria-label (A4) — the chunk span
|
||||
# keeps its own part.
|
||||
full = "Syncing… src/a/b.md (2/3) · chunk 125/126 · image 3/15"
|
||||
row = by_tag["import-image-span"]
|
||||
assert row[1] == full, row[1]
|
||||
assert row[2] == full, "the announcer (the box) hears the whole thing (A4)"
|
||||
assert row[14] == full, "the running button's accessible name is the full label"
|
||||
assert row[10] == full, "the detail box carries the EXACT full label"
|
||||
assert row[6] == "· chunk 125/126" and row[7] is False, (
|
||||
"the chunk part keeps its own span alongside the image part"
|
||||
)
|
||||
|
||||
# 1c. the image part alone (the chunk position never left 0/0 —
|
||||
# the two parts are independent).
|
||||
row = by_tag["import-image-only"]
|
||||
assert row[1] == "Syncing… src/a/b.md (2/3) · image 7/7", row[1]
|
||||
assert row[2] == row[1] and row[14] == row[1], row
|
||||
assert row[6] == "" and row[7] is True, (
|
||||
"the chunk part stays hidden + empty (its own 0/0)"
|
||||
)
|
||||
|
||||
# The pre-batch import (0/0 on BOTH positions) and every other
|
||||
# running state: the composed string is image-free (the part
|
||||
# hides on its own 0/0 — the overview/summaries transitions
|
||||
# clear the position server-side, the bare builders carry none).
|
||||
for tag, expected_title in (
|
||||
("import-inflight", "Syncing… src/a/b.md (2/3) · chunk 14/38"),
|
||||
("import-prebatch", "Syncing… src/a/b.md (2/3)"),
|
||||
("prelude", "Syncing…"),
|
||||
("click", "Syncing…"),
|
||||
("upload", "Importing"),
|
||||
("overview", "Writing KB overview…"),
|
||||
("summaries", "Summarizing folders… src/alpha (2/3)"),
|
||||
):
|
||||
row = by_tag[tag]
|
||||
assert row[1] == expected_title, (tag, row)
|
||||
assert "· image" not in row[1], (
|
||||
f"{tag}: the image part shows only while images_total > 0"
|
||||
)
|
||||
|
||||
# The running-state contracts apply to the new rows too: box
|
||||
# visible + is-running + spinning, the Cancel control shown +
|
||||
# enabled (a sync run in flight).
|
||||
for tag in ("import-image-span", "import-image-only"):
|
||||
row = by_tag[tag]
|
||||
assert row[11] is False, f"{tag}: the box must be visible while in flight"
|
||||
assert row[12] is True and row[13] is True, f"{tag}: is-running + spinning"
|
||||
assert row[8] is False and row[9] is False, (
|
||||
f"{tag}: the Cancel control is shown + enabled while a sync runs"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
|
||||
def test_progress_box_and_running_button_contract_under_node() -> None:
|
||||
"""Phase 149 (task 01) — the detail box + the icon-only running
|
||||
@@ -995,14 +1189,16 @@ def test_progress_box_and_running_button_contract_under_node() -> None:
|
||||
|
||||
|
||||
def test_every_other_state_passes_no_chunk_text() -> None:
|
||||
"""Source-level pin of the render-only-while-chunks_total>0
|
||||
contract: the import fall-through is the ONLY place in sources.js
|
||||
that reads the status's chunk fields (the summaries/overview
|
||||
branches and the bare builders never touch them), and every
|
||||
NON-running label emission passes no chunk text (the part hides):
|
||||
the settle/idle labels go through setSyncLabel(label) — the only
|
||||
running-flagged call site (phase 149: `running = true`) is the
|
||||
running entry."""
|
||||
"""Source-level pin of the render-only-while-chunks_total>0 +
|
||||
render-only-while-images_total>0 contracts: the import
|
||||
fall-through is the ONLY place in sources.js that reads the
|
||||
status's chunk OR image fields (the summaries/overview branches
|
||||
and the bare builders never touch them), and every
|
||||
NON-running label emission passes no chunk/image text (both
|
||||
parts hide): the settle/idle labels go through setSyncLabel(label)
|
||||
— the only running-flagged call site (phase 149: `running = true`)
|
||||
is the running entry (phase 152: passing the image part as its
|
||||
fifth argument)."""
|
||||
js = _js()
|
||||
body = _fn(js, "fmtSyncPhaseLabel")
|
||||
i_fall = body.find("fmtSyncLabel(")
|
||||
@@ -1010,12 +1206,21 @@ def test_every_other_state_passes_no_chunk_text() -> None:
|
||||
assert "chunks_total" not in pre and "current_chunk" not in pre, (
|
||||
"the overview/summaries branches never read the chunk fields"
|
||||
)
|
||||
assert "images_total" not in pre and "images_done" not in pre, (
|
||||
"the overview/summaries branches never read the image fields (phase 152)"
|
||||
)
|
||||
fall = body[i_fall:]
|
||||
assert "status.chunks_total" in fall and "status.current_chunk" in fall
|
||||
assert js.count("setSyncLabel(main, count, chunk, true)") == 1, (
|
||||
"the ONLY running-flagged call site is the running entry (phase 149)"
|
||||
assert "status.images_total" in fall and "status.images_done" in fall, (
|
||||
"the import fall-through is the ONLY reader of the image fields (phase 152)"
|
||||
)
|
||||
assert js.count("setSyncLabel(main, count, chunk, true, image)") == 1, (
|
||||
"the ONLY running-flagged call site is the running entry (phase 149"
|
||||
" — phase 152: with the image part)"
|
||||
)
|
||||
assert "setSyncLabel(label)" in js, (
|
||||
"the settle/idle labels stay two-arg (no chunk/image)"
|
||||
)
|
||||
assert "setSyncLabel(label)" in js, "the settle/idle labels stay two-arg (no chunk)"
|
||||
|
||||
|
||||
# ---------- the two-job tick (startSyncPolling) ----------
|
||||
|
||||
Reference in New Issue
Block a user