phase: 154_sync_status_freshness
Build and Push Containers / build-and-push-app (push) Successful in 2m26s
Build and Push Containers / build-and-push-db (push) Successful in 16s

All 4 task files exist in `complete/`, and only `00_phase.md` remains in `todo/`. This is the final verification pass. I'll read through the task files and check the current state of the code.
This commit is contained in:
2026-10-04 14:24:33 -04:00
parent 966c4b0540
commit c275735db4
36 changed files with 2526 additions and 99 deletions
+425 -18
View File
@@ -149,6 +149,46 @@ 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.
Phase 154 (task 02) extends the Sources-page upload line with the
COMPLETION STAMP (the phase's date-qualified freshness): the settled
line reads "Uploaded <name> (<stamp>) — press Sync sources to import
it." (the fresh 202 settle, the page-local name) or the nameless
"Uploaded <stamp> — press Sync sources to import it." (the boot
re-render — the stamp comes from the SERVER payload, so the line is
self-dating even with the name unknown); a running / legacy / partial
payload without timestamps renders the byte-identical pre-phase-154
strings (the nameful / nameless "Uploaded … — press Sync sources to
import it." lines). The stamp is PRECOMPUTED by the page-local
fmtUploadStamp(status) (the per-page duplication idiom — the same A1
date-qualifier as sources.js's fmtSyncTime, duplicated, not shared;
the rule's boundary set is pinned in test_sync_button.py on a fixed
clock): it reads status.finished_at first (the success state always
has it on the server), falls back to status.started_at (a defensive
guard — a corrupt finished_at degrades to the started_at stamp rather
than to no stamp), and yields "" when both are absent or every ISO is
unparseable. Both render sites — the poll's success settle and the
boot re-attach — pass fmtUploadStamp(status) as the third argument;
the NO server change (the /upload/status payload is untouched —
started_at / finished_at already shipped, phase 64).
Phase 154 (task 03) pins the BYTE-IDENTITY of the no-stamp fallbacks
against the VERBATIM pre-phase-154 strings: the old 2-arg
fmtUploadResult (git history) is pinned in this file as a reference
implementation (the name renamed, the body byte-for-byte) and run
side by side with the real 3-arg function under node — the no-stamp
(nameful / nameless) outputs + the legacy 2-arg call are asserted
byte-identical to the reference's output, and the reference's
output to the verbatim old line strings (assertable, not assumed).
Clock-free: `when` is a precomputed argument, so the no-stamp
shapes need no clock at all. The /upload/status full-dict pin
(tests/integration/test_git_sources_upload.py, the phase-64
precedent) stays UNCHANGED — this phase adds no server keys (the
app/ no-touch regression guard). The qualifier's byte-identity
(same-day + fallbacks vs the verbatim pre-phase fmtSyncTime) is
pinned in test_sync_button.py on the shared fixed clock; the four
shapes and the fmtUploadStamp behavior (finished / started /
missing / garbage) ride the task-02 pins below.
"""
from __future__ import annotations
@@ -1639,23 +1679,42 @@ def test_processing_state_is_bare_for_the_whole_run() -> None:
def test_fmt_upload_result_is_the_ready_for_sync_line() -> None:
"""Phase 90 (A2/A3): the result line reads the no-count
{"message": "uploaded"} detail and renders "Uploaded <name> —
press Sync sources to import it." (the name from the accepted
202); without a name (a reload re-render, the 409 re-attach) it
renders the nameless variant; the old sync-style count keys
"""Phase 90 (A2/A3) extended by Phase 154 (task 02): the result
line reads the no-count {"message": "uploaded"} detail and renders
the ready-for-sync line in the FOUR phase-154 shapes —
"Uploaded <name> (<stamp>) — press Sync sources to import it." (the
name + the completion stamp), "Uploaded <name> — press Sync sources
to import it." (name, no stamp — BYTE-IDENTICAL to the pre-phase
string), "Uploaded <stamp> — press Sync sources to import it." (no
name + stamp — the boot re-render, self-dating with the name
unknown), "Uploaded — press Sync sources to import it." (no name,
no stamp — BYTE-IDENTICAL to the pre-phase string; the running /
legacy / partial payload). The non-uploaded detail keeps the
unchanged "The upload finished."; the old sync-style count keys
(added / updated / unchanged / pruned) are no longer read at all.
The 202 branch records the safe name (lastUploadName); the poll's
settle and the boot re-attach both render the line from
(detail, lastUploadName); the button's idle label is "Upload"."""
settle and the boot re-attach both render the line from (detail,
lastUploadName, fmtUploadStamp(status)); the button's idle label
is "Upload"."""
js = _gjs()
body = _gfn(js, "fmtUploadResult")
assert "function fmtUploadResult(detail, name)" in body
assert 'detail.message === "uploaded"' in body
assert "Uploaded ${name} — press Sync sources to import it." in body
assert "Uploaded — press Sync sources to import it." in body, (
"the nameless variant (reload / 409 re-attach)"
assert "function fmtUploadResult(detail, name, when)" in body, (
"phase 154: the precomputed completion stamp is the third parameter"
)
assert 'detail.message === "uploaded"' in body
# The four shapes (name×stamp, name×no-stamp, no-name×stamp,
# no-name×no-stamp).
assert "Uploaded ${name} (${when}) — press Sync sources to import it." in body
assert "Uploaded ${name} — press Sync sources to import it." in body, (
"the no-stamp nameful variant — byte-identical to pre-phase"
)
assert "Uploaded ${when} — press Sync sources to import it." in body, (
"the nameless + stamp variant (the boot re-render — self-dating)"
)
assert "Uploaded — press Sync sources to import it." in body, (
"the nameless no-stamp variant — byte-identical to pre-phase"
)
assert '"The upload finished."' in body, ("the non-uploaded branch is unchanged")
for key in ("added", "updated", "unchanged", "pruned"):
assert key not in body, f"the sync-style count {key!r} is gone"
# The 202 branch records the safe name for the settled line.
@@ -1664,9 +1723,19 @@ def test_fmt_upload_result_is_the_ready_for_sync_line() -> None:
i409 = sub.find("r.status === 409")
assert "lastUploadName = name" in sub[i202:i409]
assert "let lastUploadName = null" in js, "page-local (null after a reload)"
# Both render sites pass (detail, lastUploadName).
assert "fmtUploadResult(detail, lastUploadName)" in _utick(js)
assert "fmtUploadResult(status.detail, lastUploadName)" in _gfn(js, "initUploadStatus")
# Both render sites pass (…, lastUploadName, fmtUploadStamp(status)).
tick = _utick(js)
assert re.search(
r"uploadResult\.textContent = fmtUploadResult\(\s*detail,\s*"
r"lastUploadName,\s*fmtUploadStamp\(status\)\s*\)",
tick,
), "the poll's success settle passes the completion stamp (phase 154)"
init = _gfn(js, "initUploadStatus")
assert re.search(
r"uploadResult\.textContent = fmtUploadResult\(\s*status\.detail,\s*"
r"lastUploadName,\s*fmtUploadStamp\(status\)\s*\)",
init,
), "the boot re-attach passes the completion stamp (phase 154)"
# The button's idle label (static + the poll's restores).
restore = _gfn(js, "restoreUploadButton")
assert 'uploadBtn.textContent = "Upload"' in restore
@@ -1751,7 +1820,7 @@ def test_upload_polling_decision_tree() -> None:
# next-step announce + reload, NO toast.
ok = tick[i_ok:i_fail]
for line in (
"fmtUploadResult(detail, lastUploadName)",
"fmtUploadResult(",
"uploadResult.hidden = false",
'announce("Archive uploaded — press Sync sources to import it.")',
'uploadFileInput.value = ""',
@@ -1759,6 +1828,11 @@ def test_upload_polling_decision_tree() -> None:
"loadSources()",
):
assert line in ok, f"the success settle must carry {line!r}"
assert re.search(
r"uploadResult\.textContent = fmtUploadResult\(\s*detail,\s*"
r"lastUploadName,\s*fmtUploadStamp\(status\)\s*\)",
ok,
), "the success settle passes the completion stamp (phase 154)"
assert "showUploadToast" not in tick, "no toast in the poll — it fired at the 202 (A2)"
# failed: the sanitized error banner + reload.
fail = tick[i_fail:]
@@ -1815,8 +1889,14 @@ def test_boot_reattach_branches() -> None:
assert "uploadError" not in run and "showUploadToast" not in run
ok = body[i_ok:i_fail]
# The last result line — the nameless variant after a reload
# (lastUploadName is null: the safe name was page-local, phase 90).
assert "fmtUploadResult(status.detail, lastUploadName)" in ok
# (lastUploadName is null: the safe name was page-local, phase 90),
# self-dating through the completion stamp (phase 154 — the stamp
# comes from the server payload).
assert re.search(
r"uploadResult\.textContent = fmtUploadResult\(\s*status\.detail,\s*"
r"lastUploadName,\s*fmtUploadStamp\(status\)\s*\)",
ok,
), "the boot re-attach passes the completion stamp (phase 154)"
assert "uploadResult.hidden = false" in ok
assert "announce(" not in ok, "no announce at boot (A2)"
assert "showUploadToast" not in ok, "no toast at boot (A2)"
@@ -1860,3 +1940,330 @@ def test_git_sources_html_comment_documents_the_202_contract() -> None:
assert "Phase 90" in comment, "the unpack-only rework is documented"
assert "UNPACK + REGISTER ONLY" in comment
assert "Sync sources" in comment, "the result line points at the RAG page's button"
# =====================================================================
# Phase 154 (task 02) — the Sources upload line's completion stamp
# =====================================================================
def test_fmt_upload_stamp_is_the_duplicated_qualifier() -> None:
"""Phase 154 (task 02): ``fmtUploadStamp(status)`` — the page-local
DUPLICATE of sources.js's ``fmtSyncTime`` date-qualifier (the
per-page duplication idiom — not shared). It reads
``status.finished_at`` first (the success state always has it on
the server), falls back to ``status.started_at`` (the defensive
guard — a corrupt ``finished_at`` degrades to the ``started_at``
stamp rather than to no stamp), and yields ``""`` when both are
missing/absent or every ISO is unparseable (the byte-identical
pre-phase-154 fallback). The qualifier is the SAME A1 structure as
the phase-154 task-01 pin in test_sync_button.py — local calendar
dates, ``HH:MM`` same day, ``M/D, h:MM AM/PM`` same year,
``M/D/YYYY, h:MM AM/PM`` across years, the 12-hour form WITHOUT a
leading zero on the hour, month/day without leading zeros — cited
in sources.js, not restated. The ``status || {}`` guard defends a
missing status object."""
js = _gjs()
body = _gfn(js, "fmtUploadStamp")
assert "function fmtUploadStamp(status)" in body
assert "const s = status || {};" in body, (
"defensive: a missing / null status object yields ''"
)
assert "s.finished_at" in body and "s.started_at" in body
i_fin = body.find("s.finished_at")
i_st = body.find("s.started_at")
assert -1 < i_fin < i_st, "finished_at is read first — the started_at fallback"
assert "if (!iso) continue;" in body, (
"absent / null timestamps are skipped (the fallback reads)"
)
assert "if (!Number.isNaN(t.getTime()))" in body, (
"an unparseable ISO is skipped — a corrupt finished_at degrades"
" to started_at, '' when neither parses"
)
assert 'if (d === null) return "";' in body, (
"both absent (or unparseable) → '' — the byte-identical pre-"
"phase-154 fallback"
)
# The duplicated A1 qualifier (cited in sources.js's fmtSyncTime,
# not restated) — the same structure as the task-01 pin.
assert "const now = new Date();" in body, "'now' is the page's clock"
assert (
"d.getFullYear() === now.getFullYear() &&" in body
and "d.getMonth() === now.getMonth()" in body
and "d.getDate() === now.getDate()" in body
), "same local calendar day as now → HH:MM (byte-identical to pre-phase)"
assert "d.getHours() % 12 || 12" in body, (
"12-hour WITHOUT leading zero on the hour (the 12 o'clock edge)"
)
assert '"AM"' in body and '"PM"' in body, "the AM/PM family"
assert "pad(d.getMinutes())" in body, "MM zero-padded in every form"
assert "`${d.getMonth() + 1}/${d.getDate()}`" in body, (
"M/D, no leading zeros (same year, different day)"
)
assert "`${d.getMonth() + 1}/${d.getDate()}/${d.getFullYear()}`" in body, (
"M/D/YYYY across years"
)
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_upload_result_four_shapes_under_node() -> None:
"""Phase 154 (task 02): the REAL git-sources.js ``fmtUploadResult``
under node — the four shapes, ``when`` PRECOMPUTED by the caller
(so the shape itself is clock-free):
* name + stamp: ``Uploaded docs.zip (21:14) — press Sync sources
to import it.`` (the fresh 202 settle, the page-local name);
* name, no stamp (``""``): ``Uploaded docs.zip — press Sync
sources to import it.`` — BYTE-IDENTICAL to the pre-phase-154
string (the running / legacy / partial payload);
* no name + stamp: ``Uploaded 10/2, 3:14 PM — press Sync sources
to import it.`` (the boot re-render — self-dating with the name
unknown);
* no name, no stamp (``""``): ``Uploaded — press Sync sources to
import it.`` — BYTE-IDENTICAL to the pre-phase-154 string;
* a legacy 2-arg call (``when`` undefined) renders the pre-phase
nameful string (the fallback is falsy-driven);
* the non-``uploaded`` detail and a missing detail keep the
unchanged ``The upload finished.``."""
js = _gjs()
fn = _gfn(js, "fmtUploadResult")
script = (
fn
+ "\n"
'const S = { message: "uploaded" };\n'
'const O = { message: "other" };\n'
"console.log(JSON.stringify([\n"
' fmtUploadResult(S, "docs.zip", "21:14"),\n'
' fmtUploadResult(S, "docs.zip", ""),\n'
' fmtUploadResult(S, null, "10/2, 3:14 PM"),\n'
' fmtUploadResult(S, null, ""),\n'
' fmtUploadResult(S, "docs.zip"),\n'
' fmtUploadResult(O, "docs.zip", "21:14"),\n'
" fmtUploadResult(null, \"docs.zip\", \"21:14\"),\n"
"]));\n"
)
rows = json.loads(_run_node(script))
assert rows == [
"Uploaded docs.zip (21:14) — press Sync sources to import it.",
# byte-identical to pre-phase (the no-stamp nameful variant):
"Uploaded docs.zip — press Sync sources to import it.",
"Uploaded 10/2, 3:14 PM — press Sync sources to import it.",
# byte-identical to pre-phase (the no-stamp nameless variant):
"Uploaded — press Sync sources to import it.",
# the legacy 2-arg call (when undefined → falsy → pre-phase):
"Uploaded docs.zip — press Sync sources to import it.",
"The upload finished.",
"The upload finished.",
], rows
# =====================================================================
# Phase 154 (task 03) — the byte-identity pins (the pre-phase
# strings, pinned verbatim — assertable, not assumed)
# =====================================================================
#: The pre-phase-154 fmtUploadResult, pinned VERBATIM from git
#: history (the 2-arg no-count formatter — the phase-90 contract
#: pre-stamp). Only the function NAME is renamed (so the real + the
#: reference run side by side under node); the body is the old code
#: byte-for-byte — the two old line strings + "The upload finished."
#: live in this constant, so the byte-identity below is assertable,
#: not assumed.
PRE_PHASE_FMT_UPLOAD_RESULT_JS = """
function prePhaseUploadResult(detail, name) {
if (detail && detail.message === "uploaded") {
return name
? `Uploaded ${name} — press Sync sources to import it.`
: "Uploaded — press Sync sources to import it.";
}
return "The upload finished.";
}
"""
#: The two pre-phase-154 result-line strings, pinned verbatim as
#: constants (the byte-identity targets — the task-03 completion
#: criterion). The nameful one is the old template instantiated with
#: the test's input name.
PRE_PHASE_UPLOAD_LINE_NAMEFUL = "Uploaded docs.zip — press Sync sources to import it."
PRE_PHASE_UPLOAD_LINE_NAMELESS = "Uploaded — press Sync sources to import it."
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_upload_result_no_stamp_is_byte_identical_to_pre_phase() -> None:
"""Phase 154 (task 03): the two BYTE-IDENTITY fallbacks — the
REAL 3-arg ``fmtUploadResult`` and the VERBATIM pre-phase 2-arg
formatter (pinned above) run side by side under node (clock-free
— ``when`` is precomputed):
* name + ``when === ""`` → the pre-phase nameful string,
byte-identical (the running / legacy / partial payload);
* no name + ``when === ""`` → the pre-phase nameless string,
byte-identical (the same payload, the name unknown);
* the legacy 2-arg call (``when`` undefined → falsy) renders the
SAME two byte-identical strings (the old call shape is
unchanged in output);
* the non-``uploaded`` detail (and a missing detail) keep
``The upload finished.`` on BOTH sides (the branch the phase
never touched).
The reference implementation's own output is asserted against the
verbatim old strings FIRST (a self-check on the pinned constant —
a typo in the pinned function fails here, not silently), so the
real-vs-reference identity is an assertion against the verbatim
pre-phase strings (the completion criterion), not an
assumption."""
# Source-level self-check: the pinned constant carries the old
# strings verbatim (both line templates + the non-uploaded
# branch).
assert (
"return name\n"
" ? `Uploaded ${name} — press Sync sources to import it.`\n"
' : "Uploaded — press Sync sources to import it.";'
in PRE_PHASE_FMT_UPLOAD_RESULT_JS
), "the old nameful + nameless line templates are pinned verbatim"
assert '"The upload finished."' in PRE_PHASE_FMT_UPLOAD_RESULT_JS, (
"the non-uploaded branch is pinned verbatim"
)
fn = _gfn(_gjs(), "fmtUploadResult")
script = (
fn
+ "\n"
+ PRE_PHASE_FMT_UPLOAD_RESULT_JS
+ "\n"
'const S = { message: "uploaded" };\n'
'const O = { message: "other" };\n'
"console.log(JSON.stringify({\n"
" REAL: [\n"
' fmtUploadResult(S, "docs.zip", ""),\n'
" fmtUploadResult(S, null, \"\"),\n"
' fmtUploadResult(S, "docs.zip"),\n' # legacy 2-arg call
" fmtUploadResult(S, null),\n" # legacy 2-arg call
' fmtUploadResult(O, "docs.zip", "21:14"),\n'
' fmtUploadResult(null, "docs.zip", "21:14"),\n'
" ],\n"
" PRE: [\n"
' prePhaseUploadResult(S, "docs.zip"),\n'
" prePhaseUploadResult(S, null),\n"
' prePhaseUploadResult(O, "docs.zip"),\n'
' prePhaseUploadResult(null, "docs.zip"),\n'
" ]\n"
"}));\n"
)
rows = json.loads(_run_node(script))
# 1. the pinned reference reproduces the verbatim old strings
# (self-check on the constant — assertable, not assumed).
assert rows["PRE"] == [
PRE_PHASE_UPLOAD_LINE_NAMEFUL,
PRE_PHASE_UPLOAD_LINE_NAMELESS,
"The upload finished.",
"The upload finished.",
], rows
# 2. the no-stamp + legacy shapes are byte-identical to the
# reference (i.e. to the verbatim old strings).
assert rows["REAL"][:4] == [
PRE_PHASE_UPLOAD_LINE_NAMEFUL, # name + when === ""
PRE_PHASE_UPLOAD_LINE_NAMELESS, # no name + when === ""
PRE_PHASE_UPLOAD_LINE_NAMEFUL, # legacy 2-arg call
PRE_PHASE_UPLOAD_LINE_NAMELESS, # legacy 2-arg call
], rows
assert rows["REAL"][0] == rows["PRE"][0], (
"the nameful no-stamp shape is byte-identical to pre-phase"
)
assert rows["REAL"][1] == rows["PRE"][1], (
"the nameless no-stamp shape is byte-identical to pre-phase"
)
# 3. the non-uploaded branch is unchanged on both sides.
assert rows["REAL"][4] == rows["PRE"][2] == "The upload finished."
assert rows["REAL"][5] == rows["PRE"][3] == "The upload finished."
#: Phase 154 (task 02): the fixed clock for the stamp's boundary set —
#: the SAME fixed now as test_sync_button.py's task-01 pin (Oct 3,
#: 2026, 18:30 LOCAL). The test body never calls `new Date()` for its
#: own timing: the fake clock is installed in the driver (global Date
#: patched BEFORE the call — `new Date()` → the fixed now,
#: `new Date(iso)` → the real parse), and every ISO is
#: designator-less (local) so the comparison is
#: timezone-independent.
_UPLOAD_STAMP_NOW_JS = "new RealDate(2026, 9, 3, 18, 30, 0)"
def _upload_stamp_driver(fn_src: str, expr: str) -> str:
"""Run `expr` under node with the REAL git-sources.js function +
the fake clock (the idiom: the Date patch precedes the call)."""
driver = (
f"{fn_src}\n"
"const RealDate = Date;\n"
f"const NOW = {_UPLOAD_STAMP_NOW_JS};\n"
"globalThis.Date = function (...args) {\n"
" return args.length === 0 ? NOW : new RealDate(...args);\n"
"};\n"
f"{expr}\n"
)
proc = subprocess.run(
["node", "-e", driver], capture_output=True, text=True, timeout=60
)
assert proc.returncode == 0, f"node failed: {proc.stderr}"
return proc.stdout
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_upload_stamp_behavior_fixed_clock() -> None:
"""Phase 154 (task 02): the REAL git-sources.js
``fmtUploadStamp`` under node (fake clock, the fixed now Oct 3
2026 18:30 local — the same clock as test_sync_button.py's
task-01 pin): finished wins over started; started when finished is
missing/null; ``""`` when both are absent (or the status object is
missing — the defensive guard); a garbage ISO → ``""`` with no
fallback (and a corrupt finished_at degrades to the started_at
stamp when a started_at is present — the defensive guard); the A1
date-qualifier's boundary set (same day ``HH:MM`` — the audit's
own ``21:14`` case + the end-of-day edge; yesterday
``M/D, h:MM AM/PM`` with the ``12:05 AM`` edge; last year
``M/D/YYYY, h:MM AM/PM``). The wall clock never appears in an
assertion."""
fn = _gfn(_gjs(), "fmtUploadStamp")
def _lit(status: object) -> str:
if status is None:
return "null"
assert isinstance(status, dict)
parts = []
for k, v in status.items():
if v is None:
parts.append(f"{k}: null")
else:
parts.append(f'{k}: "{v}"')
return "{" + ", ".join(parts) + "}"
# (status, expected) — the expected strings are the pins.
cases = [
(
{"finished_at": "2026-10-03T16:06:00", "started_at": "2026-10-03T16:05:00"},
"16:06", # finished wins over started
),
({"started_at": "2026-10-02T15:14:00"}, "10/2, 3:14 PM"), # no finished → started
(
{"finished_at": None, "started_at": "2025-10-03T21:12:00"},
"10/3/2025, 9:12 PM", # null finished → started, last year
),
({"finished_at": "garbage"}, ""), # unparseable, no fallback
(
{"finished_at": "garbage", "started_at": "2026-10-03T16:06:00"},
"16:06", # corrupt finished degrades to the started_at stamp
),
({"finished_at": None, "started_at": None}, ""), # both absent
({}, ""), # both missing
(None, ""), # the status object itself missing (the guard)
({"finished_at": "2026-10-02T00:05:00"}, "10/2, 12:05 AM"), # 12:05 AM edge
({"finished_at": "2026-10-03T23:59:00"}, "23:59"), # same day, end-of-day
]
driver_expr = (
"const CASES = [" + ", ".join(_lit(s) for s, _ in cases) + "];\n"
"const STAMPS = CASES.map((c) => fmtUploadStamp(c));\n"
"console.log(JSON.stringify(STAMPS));"
)
out = json.loads(_upload_stamp_driver(fn, driver_expr))
assert out == [expected for _, expected in cases], out
+316
View File
@@ -164,8 +164,11 @@ tests/unit/test_frontend_sync_upload.py's node check).
from __future__ import annotations
import asyncio
import json
import logging
import re
import shutil
import subprocess
import threading
import time
from collections.abc import Callable, Iterator, Sequence
@@ -198,6 +201,8 @@ RETIRED_ID = "-".join(("sync", "result")) # built at runtime: 3.12+ folds
# adjacent/"+" constant strings at compile time, which would leave the
# retired name in the .pyc — the phase gate greps even the bytecode.
HAVE_NODE = shutil.which("node") is not None
def _text(path: Path) -> str:
assert path.is_file(), f"missing frontend file: {path}"
@@ -563,6 +568,10 @@ def test_sources_js_terminal_states() -> None:
success = _body(js, "applySyncSuccess")
assert '"Synced"' in success and "fmtSyncTime(status.finished_at)" in success
assert 'settleSyncButton(time ? `Synced ${time}` : "Synced")' in success, (
"the settle string — phase 154: the qualified stamp rides the SAME"
" shape (the qualifier lives inside the formatter)"
)
failure = _body(js, "applySyncFailure")
assert 'settleSyncButton("Sync sources")' in failure # retry-ready
@@ -578,6 +587,313 @@ def test_sources_js_terminal_states() -> None:
time = _body(js, "fmtSyncTime")
assert "getHours()" in time and "getMinutes()" in time, "local HH:MM of finished_at"
assert 'if (Number.isNaN(d.getTime())) return "";' in time, (
"the parse guard is UNCHANGED — unparseable ISO → "" (the bare"
" 'Synced' settle)"
)
# Phase 154 (task 01): the DATE-QUALIFIER (A1 rule — the LOCAL
# calendar dates, the page's clock; the table dates' family).
assert "const now = new Date();" in time, "'now' is the page's clock"
assert (
"d.getFullYear() === now.getFullYear() &&" in time
and "d.getMonth() === now.getMonth()" in time
and "d.getDate() === now.getDate()" in time
), "same local calendar day as now → HH:MM (byte-identical to pre-phase)"
assert "d.getHours() % 12 || 12" in time, (
"12-hour WITHOUT leading zero on the hour (the 12 o'clock edge)"
)
assert '"AM"' in time and '"PM"' in time, "the AM/PM family"
assert "pad(d.getMinutes())" in time, "MM zero-padded in every form"
assert "`${d.getMonth() + 1}/${d.getDate()}`" in time, (
"M/D, no leading zeros (same year, different day)"
)
assert "`${d.getMonth() + 1}/${d.getDate()}/${d.getFullYear()}`" in time, (
"M/D/YYYY across years"
)
# Phase 154 (task 01) — the date-qualifier's boundary set, behavioral
# under node with a FIXED clock. The test body never calls `new
# Date()` for its own timing: the fake clock is installed in the
# driver (global Date patched BEFORE the call — `new Date()` → the
# fixed now, `new Date(iso)` → the real parse), and every ISO is
# designator-less (local) so the comparison is timezone-independent.
# The fixed now is Oct 3, 2026, 18:30 LOCAL.
_STAMP_NOW_JS = "new RealDate(2026, 9, 3, 18, 30, 0)"
def _stamp_driver(fn_src: str, expr: str) -> str:
"""Run `expr` under node with the REAL sources.js function + the
fake clock (the idiom: the Date patch precedes the call)."""
driver = (
f"{fn_src}\n"
"const RealDate = Date;\n"
f"const NOW = {_STAMP_NOW_JS};\n"
"globalThis.Date = function (...args) {\n"
" return args.length === 0 ? NOW : new RealDate(...args);\n"
"};\n"
f"{expr}\n"
)
proc = subprocess.run(
["node", "-e", driver], capture_output=True, text=True, timeout=60
)
assert proc.returncode == 0, f"node failed: {proc.stderr}"
return proc.stdout
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_sources_js_fmt_sync_time_qualifier_boundaries_fixed_clock() -> None:
"""The REAL sources.js ``fmtSyncTime`` under node (fake clock, the
fixed now Oct 3 2026 18:30 local) — the A1 boundary set:
same-day → ``HH:MM`` (byte-identical to the pre-phase output —
the audit's own ``16:06`` case, plus the midnight / end-of-day
edges); yesterday (same year) → ``M/D, h:MM AM/PM`` (no leading
zero on the hour — ``3:14 PM``; the ``12:05 AM`` / ``12:07 PM``
o'clock edges); last-year same M/D → ``M/D/YYYY, h:MM AM/PM``;
garbage / missing ISO → ``""`` (the guard unchanged).
The ``null`` edge (``new Date(null)`` IS the epoch — parseable,
the guard unchanged) is pinned TZ-independently: ``null`` and the
epoch ISO render identically (same instant), in the dated + year
form (1969 ≠ the fixed 2026). The wall clock never appears in an
assertion."""
fn = _body(_text(SOURCES_JS), "fmtSyncTime")
# (iso, expected) — the expected strings are the pins.
cases = [
("2026-10-03T16:06:00", "16:06"), # same day — the audit case
("2026-10-03T00:05:00", "00:05"), # same day, midnight edge
("2026-10-03T23:59:00", "23:59"), # same day, end-of-day edge
("2026-10-02T15:14:00", "10/2, 3:14 PM"), # yesterday, no zero hour
("2026-10-02T00:05:00", "10/2, 12:05 AM"), # yesterday, 12:05 AM edge
("2026-10-02T12:07:00", "10/2, 12:07 PM"), # yesterday, noon edge
("2026-10-02T23:58:00", "10/2, 11:58 PM"), # yesterday, PM minutes
("2025-10-03T21:12:00", "10/3/2025, 9:12 PM"), # last year, same M/D
("2025-01-03T09:12:00", "1/3/2025, 9:12 AM"), # last year, month 1
("garbage", ""), # unparseable → the pre-phase fallback
("", ""), # empty → the pre-phase fallback
("undefined", ""), # missing ISO (the app-restart case) → ""
]
iso_literals = []
for iso, _ in cases:
if iso == "undefined":
iso_literals.append("undefined")
else:
iso_literals.append(f'"{iso}"')
driver_expr = (
"const CASES = [" + ", ".join(iso_literals) + "];\n"
"const STAMPS = CASES.map((c) => fmtSyncTime(c));\n"
"const EPOCH = [fmtSyncTime(null), fmtSyncTime(new RealDate(0).toISOString())];\n"
"console.log(JSON.stringify({ STAMPS, EPOCH }));"
)
out = json.loads(_stamp_driver(fn, driver_expr))
assert out["STAMPS"] == [expected for _, expected in cases], out
assert out["EPOCH"][0] == out["EPOCH"][1], (
"null and the epoch ISO render identically (the same instant —"
" the guard is unchanged: new Date(null) IS the epoch)"
)
assert re.fullmatch(
r"\d{1,2}/\d{1,2}/\d{4}, \d{1,2}:\d{2} (AM|PM)", out["EPOCH"][0]
), "the epoch takes the M/D/YYYY, h:MM AM/PM form (1969 ≠ the fixed year)"
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_sources_js_synced_settle_string_qualifies_the_stamp() -> None:
"""The ``applySyncSuccess`` settle string (the pinned shape
``time ? `Synced ${time}` : "Synced"`` — the qualifier lives
INSIDE the formatter, the shape is unchanged) under node with the
fixed clock: a same-day ``finished_at`` settles as
``Synced 16:06`` (byte-identical to pre-phase), a non-same-day
one settles as ``Synced 10/2, 3:14 PM`` (the date-qualified
badge — the phase's ask), and an unparseable/missing ISO settles
as the bare ``Synced`` (the existing fallback). The ``null`` edge
pins identically to the boundary test (the epoch — the pre-phase
rendered ``Synced 00:00`` there)."""
fn = _body(_text(SOURCES_JS), "fmtSyncTime")
settle = (
"const settle = (iso) => {\n"
" const t = fmtSyncTime(iso);\n"
" return t ? `Synced ${t}` : \"Synced\";\n"
"};\n"
)
iso_literals = [
'"2026-10-03T16:06:00"', # same day
'"2026-10-02T15:14:00"', # yesterday
'"2025-10-03T21:12:00"', # last year
'"garbage"', # unparseable
"undefined", # missing ISO
]
driver_expr = (
settle
+ "const CASES = [" + ", ".join(iso_literals) + "];\n"
+ "const SETTLES = CASES.map(settle);\n"
+ "const EPOCH = [settle(null), settle(new RealDate(0).toISOString())];\n"
+ "console.log(JSON.stringify({ SETTLES, EPOCH }));"
)
out = json.loads(_stamp_driver(fn, driver_expr))
assert out["SETTLES"] == [
"Synced 16:06", # same day — byte-identical to pre-phase
"Synced 10/2, 3:14 PM", # yesterday — date-qualified
"Synced 10/3/2025, 9:12 PM", # last year — date + year
"Synced", # garbage — the bare fallback
"Synced", # missing ISO — the bare fallback
], out
assert out["EPOCH"][0] == out["EPOCH"][1], (
"settle(null) and the epoch ISO settle identically (the guard"
" unchanged)"
)
assert out["EPOCH"][0].startswith("Synced "), (
"the epoch settles with a stamp (new Date(null) is parseable"
" — the pre-phase rendered 'Synced 00:00' there)"
)
# Phase 154 (task 03) — the qualifier's BYTE-IDENTITY: the pre-phase
# fmtSyncTime, pinned VERBATIM from git history (the phase-154
# pre-state — the time-only formatter). Only the function NAME is
# renamed (so the real + the reference run side by side under node);
# the body is the old code byte-for-byte — the old strings (the
# `HH:MM` return + the `""` guard) live in this constant, so the
# byte-identity below is assertable, not assumed. The reference is
# clock-free (it reads no `now` — only the ISO's local time), but
# the same fixed-clock driver (the task-01 boundary set's clock) is
# used, so the real function's same-day comparison runs on the fixed
# now exactly as in the boundary test.
PRE_PHASE_FMT_SYNC_TIME_JS = """
function prePhaseSyncTime(iso) {
const d = new Date(iso);
if (Number.isNaN(d.getTime())) return "";
const pad = (n) => String(n).padStart(2, "0");
return `${pad(d.getHours())}:${pad(d.getMinutes())}`;
}
"""
@pytest.mark.skipif(not HAVE_NODE, reason="node not available")
def test_sources_js_fmt_sync_time_same_day_is_byte_identical_to_pre_phase() -> None:
"""Phase 154 (task 03): the REAL sources.js ``fmtSyncTime`` and
the VERBATIM pre-phase formatter (pinned above) run side by side
under node with the fixed clock (Oct 3 2026 18:30 local — the
task-01 boundary set's clock):
* the pinned reference's own output is asserted against the
verbatim old strings FIRST (a self-check on the constant — a
typo in the pinned function fails here, not silently);
* EVERY same-day ISO renders BYTE-IDENTICALLY to the pre-phase
output (the old ``HH:MM`` — the audit's ``16:06`` case, the
midnight / end-of-day edges), and its settle string is
byte-identical to the pre-phase settle (``"Synced " + HH:MM``
— a same-day badge never moved);
* EVERY unparseable/missing ISO (``garbage`` / ``""`` /
``undefined``) renders byte-identically to the pre-phase
``""`` (the guard unchanged);
* the NON-same-day ISOs (yesterday + last year + the
``null``/epoch edge — the epoch's local time is a different
day AND a different year, so the qualified form applies; its
value is TZ-dependent, so it is pinned by SHAPE: the
``M/D/YYYY, h:MM AM/PM`` family vs the old ``HH:MM``) are the
pinned DIVERGENT set — the qualified form is byte-different
from the pre-phase time-only string (the phase's change lives
exactly there).
The wall clock never appears in an assertion."""
# Source-level self-check: the pinned constant carries the old
# strings verbatim (the `HH:MM` return + the parse guard).
assert (
"return `${pad(d.getHours())}:${pad(d.getMinutes())}`;"
in PRE_PHASE_FMT_SYNC_TIME_JS
), "the old HH:MM return is pinned verbatim"
assert (
'if (Number.isNaN(d.getTime())) return "";' in PRE_PHASE_FMT_SYNC_TIME_JS
), "the old parse guard is pinned verbatim"
fn = _body(_text(SOURCES_JS), "fmtSyncTime")
# (js literal, category) — category: same / fallback / diverge.
cases = [
('"2026-10-03T16:06:00"', "same"), # the audit case
('"2026-10-03T00:05:00"', "same"), # midnight edge
('"2026-10-03T23:59:00"', "same"), # end-of-day edge
('"garbage"', "fallback"),
('""', "fallback"), # empty ISO
("undefined", "fallback"), # missing ISO (the app-restart case)
("null", "diverge"), # the epoch edge — shape-pinned (TZ-dependent)
('"2026-10-02T15:14:00"', "diverge"), # yesterday
('"2026-10-02T00:05:00"', "diverge"),
('"2026-10-02T12:07:00"', "diverge"),
('"2026-10-02T23:58:00"', "diverge"),
('"2025-10-03T21:12:00"', "diverge"), # last year
('"2025-01-03T09:12:00"', "diverge"),
]
# The verbatim old strings (the pre-phase output — pinned here so
# the identity is assertable); the null/epoch value is
# TZ-dependent, so its old string is pinned by shape, not value.
old = {
'"2026-10-03T16:06:00"': "16:06",
'"2026-10-03T00:05:00"': "00:05",
'"2026-10-03T23:59:00"': "23:59",
'"garbage"': "",
'""': "",
"undefined": "",
}
driver_expr = (
"const CASES = [" + ", ".join(lit for lit, _ in cases) + "];\n"
"const PRE = CASES.map((c) => prePhaseSyncTime(c));\n"
"const REAL = CASES.map((c) => fmtSyncTime(c));\n"
"const settle = (f) => (iso) => {\n"
" const t = f(iso);\n"
" return t ? `Synced ${t}` : \"Synced\";\n"
"};\n"
"const PRE_SETTLE = CASES.map((c) => settle(prePhaseSyncTime)(c));\n"
"const REAL_SETTLE = CASES.map((c) => settle(fmtSyncTime)(c));\n"
"console.log(JSON.stringify({ PRE, REAL, PRE_SETTLE, REAL_SETTLE }));"
)
out = json.loads(
_stamp_driver(fn + "\n" + PRE_PHASE_FMT_SYNC_TIME_JS, driver_expr)
)
# 1. the pinned reference reproduces the verbatim old strings
# (self-check on the constant — assertable, not assumed).
for i, (lit, _cat) in enumerate(cases):
if lit in old:
assert out["PRE"][i] == old[lit], (
f"the pre-phase reference for {lit} must be the verbatim old"
f" string {old[lit]!r} — got {out['PRE'][i]!r} (a typo in the"
" pinned constant?"
)
null_i = [lit for lit, _ in cases].index("null")
assert re.fullmatch(r"\d{2}:\d{2}", out["PRE"][null_i]), (
"the null/epoch edge takes the old HH:MM shape on the reference"
" side (the pre-phase is time-only — the value is TZ-dependent,"
" the shape is not)"
)
assert out["PRE_SETTLE"][null_i] == "Synced " + out["PRE"][null_i] # old settle
assert re.fullmatch(
r"\d{1,2}/\d{1,2}/\d{4}, \d{1,2}:\d{2} (AM|PM)", out["REAL"][null_i]
), (
"the null/epoch edge takes the M/D/YYYY, h:MM AM/PM shape on the"
" real side (the epoch is a different day + year — the qualified"
" form; the value is TZ-dependent, the shape is not)"
)
assert out["REAL_SETTLE"][null_i].startswith("Synced ")
# 2. the audit case's settle is byte-identical to pre-phase.
audit_i = [lit for lit, _ in cases].index('"2026-10-03T16:06:00"')
assert out["REAL_SETTLE"][audit_i] == "Synced 16:06", (
"the same-day settle is byte-identical to the pre-phase string"
)
# 3. same-day + fallbacks: byte-identical to the reference, settle
# included; the divergent set: byte-different (the qualified form).
for i, (lit, cat) in enumerate(cases):
if cat == "diverge":
assert out["REAL"][i] != out["PRE"][i], (
f"{lit} must DIFFER from the pre-phase form (the qualified"
f" branch) — got {out['REAL'][i]!r} == {out['PRE'][i]!r}"
)
assert out["REAL_SETTLE"][i] != out["PRE_SETTLE"][i]
else:
assert out["REAL"][i] == out["PRE"][i], (
f"{lit} must be byte-identical to the pre-phase output"
f" (category {cat}) — got {out['REAL'][i]!r} vs"
f" {out['PRE'][i]!r}"
)
assert out["REAL_SETTLE"][i] == out["PRE_SETTLE"][i]
def test_sources_js_failed_error_is_sanitized() -> None: