phase: 167_api_payload_diet
All gates green. Final report: **Verified (phase 167 final pass — all 6 tasks already in `complete/`)** - Live re-measure of the headline criterion on the **1,000-doc live-replica corpus** (restored `data/bor_live_kb_replica.dump.sql` into a scratch DB `bor_audit`, alembic 0011→0027, dropped after; the shared dev DB was never touched): `GET /api/docs/tree` default depth=1 = **8,474 identity → 1,128 B with `Content-Encoding: gzip`** (< 40 KB bar; ~2 MB defect fixed), repeat load **304 / 0 bytes**; depth=8 265,147→23,515; node drill 20,844→1,065; `/api/docs` 246,366→45,104; `/api/documents/content` 892,124→60,776 (`LOOK`, accepted-with-why). Reproduces `AUDIT.md` to within 1 byte. - Transport contracts proven live: `POST /api/chat` **no** `Content-Encoding` + frames arriving live + budget line `… enc=identity duration_ms=7380 stream=1`; HTML still `no-cache` with the `?v=` rewrite (and gzipped); A20 headers on 200 **and** 304; ETag identical across identity/gzip; `depth=0|9|abc`→422; anonymous tree/node→403; unknown folder/source→404 `unknown node`. **Gates (all 100% green)** - `uv run pytest` → **3980 passed**; `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (`compression.py`, `http_cache.py`, `response_budget.py` 100%; `api/docs.py` 99%, one defensive dedupe line). - `uv run ruff check .` → All checks passed; `uv run pyright` → 0 errors. - Phase + regression E2E **in isolation** (`--junitxml`, exit codes): `test_kb_tree_lazy_load` 11, `test_kb_tree` 8, `test_kb_tree_nav` 4, `test_navbar_refresh` 7, `test_document_dates` 6, `test_git_source_dates` 4, `test_sync_summary_visibility` 3, `test_table_ux_polish` 6, `test_sources_midstream_bug` 6, `test_ls_tree_drilldown` 3, `test_smoke` 3 — **0 failures/errors** (the earlier `-q -q` run had simply suppressed pytest's summary line). **Documentation** — README.md + AGENTS.md reviewed in full (1,436 / 80 lines): - Fixed (pre-existing, phase-167-exposed): README *Caching & deploys* claimed "One Starlette middleware (`app/core/caching.py`) applies the rule" while the section now describes three transport layers → rewritten to name caching/compression/http_cache, the real outermost→innermost order, and why `bytes=` is uncompressed. - AGENTS.md rule 5 (UI Structure Check) gained the phase-167 clause: a lazily-drilled level keeps the current level rendered, its in-flight `role="status"` / `role="alert"`+Retry row lives in the same bounded scroll panel, and stat cards read server `totals` (never a walk of a depth-limited tree). - Cross-checked and consistent: every `BOR_*` in `.env.example` is in the README table, every `Settings` field is documented, all 15 README-cited API routes exist in the app, no stale "one fetch / drill client-side" claim remains anywhere. **Notable decisions / deviations** - `compression.py` adds a documented `_RebufferSmallResponses` seam beyond the D1 sketch (the caching layer's `BaseHTTPMiddleware` re-framing otherwise defeats Starlette's `minimum_size` exemption and inflates tiny responses) — integration-pinned, math still Starlette's. - A node-route **404 = vanished folder → honest reset to top level** (per `00_phase.md` D4/D6), not task-06's "alert + Retry"; 500 shows alert+Retry with the level preserved — both pinned, nothing weakened. - Retrieval battery not measurable (shared E2E DB holds no corpus), but `git diff --name-only -- app/rag` is empty, so retrieval is unchanged by construction. `AUDIT.md` left byte-identical (it lives under `todo/`, off-limits to this pass); no git index/history commands run. **Next pending phase:** none — `167_api_payload_diet` is the only entry in `.agents/phases/todo/`; the harness moves it to `complete/` and commits.
This commit is contained in:
+282
-45
@@ -5,10 +5,13 @@ The RAG (Knowledge base) view lists the catalog the way the agent's
|
||||
top, then per level the subfolders (recursive count + the STORED
|
||||
description) and the level's files (the ``#docs-table`` — phase 106,
|
||||
task 08, D8, added the Created column BEFORE Indexed, making it the
|
||||
6-column contract). The view's catalog load is now
|
||||
``loadTree()``: ONE fetch of ``GET /api/docs/tree`` (the full recursive
|
||||
tree in a single payload — task 02), then client-side drill navigation
|
||||
(no per-level fetch, no URL change).
|
||||
6-column contract). The view's catalog load is ``loadTree()``: ONE
|
||||
fetch of ``GET /api/docs/tree?depth=1`` (sources + one level + the
|
||||
server's ``totals``) plus ONE ``GET /api/docs/tree/node`` fetch per
|
||||
not-yet-loaded level — phase 167 (task 04, LOCKED A3 — the TODO L5
|
||||
2 MB payload fix) SUPERSEDED the phase-97 "one full-tree fetch, drill
|
||||
purely client-side" contract; the drill UX (breadcrumb, no URL change)
|
||||
is unchanged.
|
||||
|
||||
This module pins the source-level contract (the house pattern of
|
||||
``tests/unit/test_sync_button.py`` — read the frontend files as text,
|
||||
@@ -24,8 +27,14 @@ suite, task 06):
|
||||
``#stat-cards`` and BEFORE the file table (now the 6-column
|
||||
Source | Path | Title | Chunks | Created | Indexed head — phase 106
|
||||
(task 08, D8) added the Created column BEFORE Indexed);
|
||||
* the exact ``/api/docs/tree`` fetch (and the flat ``/api/docs`` fetch
|
||||
is gone from the view module);
|
||||
* the exact ``/api/docs/tree?depth=1`` load fetch + the single
|
||||
``/api/docs/tree/node`` drill fetch (the flat ``/api/docs`` fetch is
|
||||
gone from the view module), the level cache (declared once, cleared
|
||||
by every load, consulted by ``needsLevelFetch``, written only after a
|
||||
200), the §7.4 drill states (in-flight ``aria-busy``/``aria-disabled``
|
||||
+ one ``role="status"`` row, ``role="alert"`` failure with a real
|
||||
Retry ``<button>``, the node 404 → top-level reset, the race token
|
||||
extended to the drill), and the ``totals``-first stat cards;
|
||||
* the drill state (``current`` / ``kbTree``), the state transitions
|
||||
(source row click, folder row click, breadcrumb up, top reset), and
|
||||
the aria-current last segment;
|
||||
@@ -239,18 +248,25 @@ def test_rag_view_ships_the_tree_skeleton_in_order() -> None:
|
||||
assert f">{column}</th>" in doc_head.group(1), f"#docs-table head must keep {column!r}"
|
||||
|
||||
|
||||
# ---------- the tree load: the ONE fetch + the race token ----------
|
||||
# ---------- the tree load: the depth-1 fetch, the node fetch, the token ----------
|
||||
|
||||
|
||||
def test_sources_js_fetches_the_tree_endpoint_only() -> None:
|
||||
"""The catalog load is `loadTree()`: ONE fetch of the tree endpoint.
|
||||
The flat `GET /api/docs` fetch is GONE from the view module (the
|
||||
endpoint itself stays — the API surface is untouched, task 02)."""
|
||||
"""Phase 167 (task 04, A3 — supersedes the phase-97 "ONE full-tree
|
||||
fetch, zero per-level fetches" pin): the catalog load is ONE
|
||||
`fetch("/api/docs/tree?depth=1")` and the drill has exactly ONE
|
||||
node-fetch call site (`fetch("/api/docs/tree/node?…`, reached only
|
||||
through fetchLevel). The flat `GET /api/docs` fetch stays GONE from
|
||||
the view module (the endpoint itself stays — task 02)."""
|
||||
js = _js()
|
||||
assert 'fetch("/api/docs/tree")' in js, "the load must fetch /api/docs/tree"
|
||||
assert js.count('fetch("/api/docs/tree")') == 1, (
|
||||
"the tree is the view's SINGLE catalog fetch (zero per-level fetches)"
|
||||
code = _code(js)
|
||||
assert code.count('fetch("/api/docs/tree?depth=1")') == 1, (
|
||||
"the load is ONE depth=1 request (the 2 MB first-payload fix)"
|
||||
)
|
||||
assert code.count('fetch("/api/docs/tree/node?') == 1, (
|
||||
"exactly ONE per-level fetch call site — every drill routes through it"
|
||||
)
|
||||
assert 'fetch("/api/docs/tree")' not in js, "the depth-less load URL is gone"
|
||||
assert 'fetch("/api/docs")' not in js, "the flat /api/docs fetch must be gone"
|
||||
|
||||
|
||||
@@ -301,8 +317,9 @@ def test_source_row_click_drills_into_the_source_root() -> None:
|
||||
body = js[js.find("function makeSourceRow(") : js.find("function makeFolderRow(")]
|
||||
assert 'link.className = "folder-link"' in body, "the source row uses the row drill link"
|
||||
assert "link.textContent = s.name" in body
|
||||
assert "goTo({ source: s.name, folder: \"\" })" in body, (
|
||||
"a source row drills to the source ROOT (folder \"\")"
|
||||
assert "goTo({ source: s.name, folder: \"\" }, link)" in body, (
|
||||
"a source row drills to the source ROOT (folder \"\") — the link "
|
||||
"rides the phase-167 in-flight state"
|
||||
)
|
||||
assert "countTd.textContent = String(s.documents)" in body, "the recursive count"
|
||||
assert 'makeDescCell(s, s.name, "", s.name)' in body, (
|
||||
@@ -326,8 +343,9 @@ def test_folder_row_click_drills_into_the_folder() -> None:
|
||||
"the label is the last segment (the breadcrumb language)"
|
||||
)
|
||||
assert "link.title = current.source + \"/\" + f.path" in body, "full path on hover"
|
||||
assert "goTo({ source: current.source, folder: f.path })" in body, (
|
||||
"a folder row drills to that folder"
|
||||
assert "goTo({ source: current.source, folder: f.path }, link)" in body, (
|
||||
"a folder row drills to that folder — the link rides the "
|
||||
"phase-167 in-flight state"
|
||||
)
|
||||
assert "countTd.textContent = String(f.documents)" in body
|
||||
assert (
|
||||
@@ -370,19 +388,24 @@ def test_breadcrumb_links_go_up_and_the_top_reset() -> None:
|
||||
|
||||
def test_drill_navigation_pushes_state_only_entries() -> None:
|
||||
"""Phase 99 (task 02, D2): every user-initiated drill is a history
|
||||
entry — ``goTo`` is the push variant of ``applyTarget``: when the
|
||||
target DIFFERS from the current level (a re-click of the current
|
||||
row/segment pushes NO duplicate entry), it FIRST records a
|
||||
STATE-ONLY entry — ``history.pushState({ view: "rag", kb: target },
|
||||
"")`` — the second arg is ``""`` and there is no third (the URL
|
||||
stays the shell's pathname: no new route, the phase-76 deep-link
|
||||
surface is untouched) — then sets ``current`` + re-renders. The
|
||||
drill still never fetches (the tree is in memory) and the module
|
||||
never ``replaceState``s."""
|
||||
entry — ``applyTarget(target, push)``: when the target DIFFERS
|
||||
from the current level (a re-click of the current row/segment
|
||||
pushes NO duplicate entry), it FIRST records a STATE-ONLY entry —
|
||||
``history.pushState({ view: "rag", kb: target }, "")`` — the second
|
||||
arg is ``""`` and there is no third (the URL stays the shell's
|
||||
pathname: no new route, the phase-76 deep-link surface is
|
||||
untouched) — then sets ``current`` + re-renders. The module never
|
||||
``replaceState``s. Phase 167 (task 04, A3 — supersedes the "the
|
||||
drill never fetches" pin): ``goTo`` hands the target to
|
||||
``enterFolder`` with ``push=true``, so the push lands only when the
|
||||
level is IN HAND (a failed drill records nothing) — ``applyTarget``
|
||||
and ``goTo`` themselves stay fetch-free; the drill's only fetch
|
||||
lives in ``fetchLevel`` (pinned below)."""
|
||||
js = _js()
|
||||
start = js.find("function applyTarget(")
|
||||
assert start != -1, "applyTarget must exist (the two-step drill)"
|
||||
body = js[start : js.find("function makeSourceRow(")]
|
||||
assert js.find("function applyTarget(") != -1, (
|
||||
"applyTarget must exist (the two-step drill)"
|
||||
)
|
||||
body = _fn(js, "applyTarget")
|
||||
gate_i = body.find(
|
||||
"if (push && (target.source !== current.source || target.folder !== current.folder)) {"
|
||||
)
|
||||
@@ -394,14 +417,191 @@ def test_drill_navigation_pushes_state_only_entries() -> None:
|
||||
)
|
||||
# STATE-ONLY: exactly ONE pushState call site — the "" second arg,
|
||||
# no third (no URL change).
|
||||
assert _code(body).count("pushState") == 1, (
|
||||
assert _code(js).count("pushState") == 1, (
|
||||
"ONE pushState call site — the state-only drill entry"
|
||||
)
|
||||
assert "replaceState" not in _code(js), "no replaceState anywhere in the module"
|
||||
# goTo is the push variant — every drill call site keeps calling it.
|
||||
go = body[body.find("function goTo(") :]
|
||||
assert "applyTarget(target, true)" in go, "goTo pushes (the user-initiated drill)"
|
||||
assert "fetch(" not in body, "the drill never fetches (client-side only)"
|
||||
go = _fn(js, "goTo")
|
||||
assert "enterFolder(target, link, true)" in go, (
|
||||
"goTo pushes (the user-initiated drill, phase 167 via enterFolder)"
|
||||
)
|
||||
assert "fetch(" not in _code(body), "applyTarget stays a pure state transition"
|
||||
assert "fetch(" not in _code(go), "goTo delegates the fetch to enterFolder only"
|
||||
|
||||
|
||||
# ---------- phase 167 (task 04): the lazy drill (cache, states, reset) ----------
|
||||
|
||||
|
||||
def test_level_cache_declared_cleared_and_consulted() -> None:
|
||||
"""The level cache (phase 167, D4): ONE module-scoped Map keyed
|
||||
`source + "/" + folder`; EVERY successful load clears it (a refresh
|
||||
invalidates every drilled level — the sync/upload/re-show call
|
||||
sites keep working unchanged) BEFORE the never-stale reset (the
|
||||
reset re-derives known-ness from the NEW tree); `needsLevelFetch`
|
||||
consults it (the second visit to a folder is free — zero network);
|
||||
the write sits behind the ok gate (only a 200 caches, never the
|
||||
404/failure arms) and follows the merge (children ride the node
|
||||
before the level is marked loaded)."""
|
||||
js = _js()
|
||||
assert js.count("const levelCache = new Map();") == 1, (
|
||||
"ONE module-scoped level cache"
|
||||
)
|
||||
load = _fn(js, "loadTree")
|
||||
clear_i = load.find("levelCache.clear();")
|
||||
reset_i = load.find("resetVanishedLocation();")
|
||||
assert 0 < clear_i < reset_i, "clear the cache BEFORE the reset (new tree)"
|
||||
needs = _fn(js, "needsLevelFetch")
|
||||
assert "node.truncated === true" in needs, "only a TRUNCATED node needs a fetch"
|
||||
assert "levelCache.has(" in needs, "a cached level never refetches"
|
||||
fetch = _fn(js, "fetchLevel")
|
||||
merge_i = fetch.find("Object.assign(targetNode, merged);")
|
||||
set_i = fetch.find('levelCache.set(target.source + "/" + target.folder, true);')
|
||||
ok_gate = fetch.find("if (response === null || !response.ok) {")
|
||||
vanish_i = fetch.find("if (vanished) {")
|
||||
assert -1 < vanish_i < ok_gate < merge_i < set_i, (
|
||||
"404 arm → ok gate → merge → cache: only a 200 caches, after the merge"
|
||||
)
|
||||
|
||||
|
||||
def test_drill_race_token_extends_to_the_node_fetch() -> None:
|
||||
"""Phase 79 carried over (task 04): fetchLevel captures the
|
||||
loadSeq token (plus a navSeq bumped by every applyTarget) and a
|
||||
response may only paint while NEITHER a newer load NOR a newer
|
||||
navigation happened — pinned twice (after the fetch, after the
|
||||
json read). A new loadTree invalidates the in-flight drill the
|
||||
moment it starts, and rehydrates the user's own truncated level
|
||||
through the node route BEFORE it paints (a refresh never shows a
|
||||
half-empty level)."""
|
||||
js = _js()
|
||||
fetch = _fn(js, "fetchLevel")
|
||||
assert "const my = loadSeq;" in fetch, "the phase-79 token extends to the drill"
|
||||
assert "const nav = navSeq;" in fetch, "a navigation invalidates the drill too"
|
||||
assert fetch.count("if (my !== loadSeq || nav !== navSeq) return false;") == 2, (
|
||||
"a stale drill response never paints (checked after the fetch and the json)"
|
||||
)
|
||||
load = _fn(js, "loadTree")
|
||||
assert load.find("drillPending = null;") < load.find("await fetch"), (
|
||||
"a new load invalidates the in-flight drill immediately"
|
||||
)
|
||||
assert "if (needsLevelFetch(currentLevelNode(), current.source)) {" in load, (
|
||||
"the user's own truncated level is REHYDRATED through the node route"
|
||||
)
|
||||
assert "let navSeq = 0;" in js
|
||||
# …and the ADOPTED navigation (popstate) rehydrates the same way:
|
||||
# a forward/back entry can point at a level the client has not
|
||||
# fetched since the last load (ensureCurrentLevel, after the adopt).
|
||||
pop = js[js.find('window.addEventListener("popstate"') :]
|
||||
pop = pop[: pop.find("});")]
|
||||
adopt_i = pop.find("applyTarget(kb, false)")
|
||||
ensure_i = pop.find("ensureCurrentLevel();")
|
||||
assert -1 < adopt_i < ensure_i, "adopt the entry, THEN rehydrate its level"
|
||||
ensure = _fn(js, "ensureCurrentLevel")
|
||||
assert "if (drillPending) return;" in ensure
|
||||
assert "if (needsLevelFetch(currentLevelNode(), current.source)) {" in ensure
|
||||
|
||||
|
||||
def test_drill_pending_guards_and_aria_inflight_state() -> None:
|
||||
"""§7.4 in-flight: enterFolder early-returns while a drill is
|
||||
pending (a double click cannot start a second fetch), sets the
|
||||
drillPending state BEFORE awaiting fetchLevel, and applies the
|
||||
target only once the level is in hand. fetchLevel marks the
|
||||
clicked link aria-busy + aria-disabled BEFORE the fetch and clears
|
||||
both on every settle path (the control never stays disabled — the
|
||||
failure path re-enables)."""
|
||||
js = _js()
|
||||
enter = _fn(js, "enterFolder")
|
||||
guard_i = enter.find("if (drillPending) return;")
|
||||
pending_i = enter.find(
|
||||
"drillPending = { source: target.source, folder: target.folder };"
|
||||
)
|
||||
fetch_i = enter.find("await fetchLevel(target, node, link)")
|
||||
apply_i = enter.find("applyTarget(target, push);")
|
||||
assert -1 < guard_i < pending_i < fetch_i < apply_i, (
|
||||
"guard → in-flight state → fetch → apply (only when the level is in hand)"
|
||||
)
|
||||
fetch = _fn(js, "fetchLevel")
|
||||
busy_i = fetch.find('link.setAttribute("aria-busy", "true")')
|
||||
disabled_i = fetch.find('link.setAttribute("aria-disabled", "true")')
|
||||
call_i = fetch.find("response = await fetch(")
|
||||
clear_busy = fetch.find('link.removeAttribute("aria-busy")')
|
||||
clear_disabled = fetch.find('link.removeAttribute("aria-disabled")')
|
||||
assert -1 < busy_i < call_i and -1 < disabled_i < call_i, (
|
||||
"the busy state rides the row link BEFORE the fetch"
|
||||
)
|
||||
assert call_i < clear_busy and call_i < clear_disabled, (
|
||||
"every settle path re-enables the control (§7.4)"
|
||||
)
|
||||
|
||||
|
||||
def test_drill_inflight_status_and_failure_alert_rows() -> None:
|
||||
"""The ONE in-flight row of the folders panel (phase 167, D4): the
|
||||
loading row is a role="status" "Loading <folder>…" line while the
|
||||
level the user is LEAVING stays rendered; the failure row is a
|
||||
role="alert" "Couldn't load <folder> — " line with a REAL
|
||||
<button type="button">Retry</button> whose click re-runs the SAME
|
||||
enterFolder fetch. Neither builder calls renderLevel (the current
|
||||
level never blanks); both clear the previous drill row first (ONE
|
||||
row at a time) and textContent only (the house rule)."""
|
||||
js = _js()
|
||||
loading = _fn(js, "showDrillLoading")
|
||||
assert "clearDrillRow();" in loading
|
||||
assert 'note.setAttribute("role", "status");' in loading
|
||||
assert 'note.textContent = "Loading " + name + "…"' in loading
|
||||
assert 'row.className = "kb-level-loading"' in loading
|
||||
assert "foldersTbody.appendChild(row)" in loading, "the row lives in the folders panel"
|
||||
assert "renderLevel" not in _code(loading), "the leaving level stays rendered"
|
||||
fail = _fn(js, "showDrillFailure")
|
||||
assert "clearDrillRow();" in fail
|
||||
assert 'note.setAttribute("role", "alert");' in fail
|
||||
assert '"Couldn\'t load " + target.folder.split("/").pop() + " — "' in fail
|
||||
assert 'retry.type = "button";' in fail, "Retry is a REAL button"
|
||||
assert 'retry.textContent = "Retry";' in fail
|
||||
assert (
|
||||
"retry.addEventListener(\"click\", () => enterFolder(target, link, true));" in fail
|
||||
), "Retry re-runs the SAME drill fetch"
|
||||
assert "renderLevel" not in _code(fail), "the failure keeps the current level rendered"
|
||||
clear = _fn(js, "clearDrillRow")
|
||||
assert "drillRowEl.remove();" in clear and "drillRowEl = null;" in clear
|
||||
|
||||
|
||||
def test_vanished_node_resets_to_the_top_level() -> None:
|
||||
"""The node route's 404 IS the "the folder vanished" signal (task
|
||||
04, D4): the drill resets `current` to the TOP level and re-renders
|
||||
(no stale breadcrumb), caches NOTHING for the failed level, and
|
||||
never applies the vanished target (enterFolder returns on false).
|
||||
A network/non-OK failure takes the alert arm instead — the current
|
||||
level stays rendered (pinned above)."""
|
||||
js = _js()
|
||||
fetch = _fn(js, "fetchLevel")
|
||||
assert "response.status === 404" in fetch, "the 404 is detected"
|
||||
vanish = fetch[fetch.find("if (vanished) {") : fetch.find(
|
||||
"if (response === null || !response.ok) {"
|
||||
)]
|
||||
assert "current = { source: null, folder: null };" in vanish, (
|
||||
"the 404 resets to the top level (the phase-97 never-stale contract)"
|
||||
)
|
||||
assert "renderLevel();" in vanish, "the reset renders — no stale breadcrumb"
|
||||
assert "return false;" in vanish, "the vanished target is never applied"
|
||||
assert "levelCache" not in vanish, "the failing level is NOT cached"
|
||||
enter = _fn(js, "enterFolder")
|
||||
assert "if (!loaded) return;" in enter, "enterFolder applies only on a real merge"
|
||||
|
||||
|
||||
def test_module_docstring_documents_the_lazy_drill() -> None:
|
||||
"""The house per-phase module-note convention: the Phase 167
|
||||
(task 04) section records the depth-1 load, the per-level node
|
||||
fetch + cache, the §7.4 drill states, the extended race token, the
|
||||
404 reset and the totals-first stat cards — citing TODO L5."""
|
||||
js = _js()
|
||||
header = js[: js.find("import { fetchIsAdmin }")]
|
||||
assert "Phase 167 (task 04, D4/A3" in header
|
||||
assert "TODO L5" in header, "the 2 MB payload defect is documented"
|
||||
assert "LAZY DRILL" in header
|
||||
assert "/api/docs/tree?depth=1" in header
|
||||
assert "levelCache" in header
|
||||
assert "loadSeq token EXTENDS" in header, "the race-token narrative stays accurate"
|
||||
assert "folderKnownIn" in header, "the existence-rule change is documented"
|
||||
|
||||
|
||||
# ---------- the level rendering ----------
|
||||
@@ -507,12 +707,39 @@ def test_render_clears_both_row_containers_before_filling() -> None:
|
||||
assert clear_docs < body.find(append), f"{append} must come after the clears"
|
||||
|
||||
|
||||
# ---------- the stat cards: the whole-tree walk ----------
|
||||
# ---------- the stat cards: server totals, walk as the fallback ----------
|
||||
|
||||
|
||||
def test_stat_cards_prefer_the_server_totals() -> None:
|
||||
"""Phase 167 (task 04, D2/D4): a depth-limited tree CANNOT be
|
||||
summed client-side, so treeStats() reads the server's `totals`
|
||||
(documents / chunks / last_indexed) FIRST; the phase-97 recursive
|
||||
walk stays only as the defensive no-`totals` fallback (a tree
|
||||
served by a pre-phase process — the no-crash path). The stat-card
|
||||
rendering (String(st.docs)/String(st.totalChunks)/fmtDate(st.last)
|
||||
with the "–" null idiom) is UNCHANGED."""
|
||||
js = _js()
|
||||
body = _fn(js, "treeStats")
|
||||
totals_i = body.find("const totals = kbTree.totals;")
|
||||
guard_i = body.find('if (totals && typeof totals === "object") {')
|
||||
docs_i = body.find("docs: totals.documents,")
|
||||
chunks_i = body.find("totalChunks: totals.chunks,")
|
||||
last_i = body.find('last: totals.last_indexed || "",')
|
||||
walk_i = body.find("const walk = (node) => {")
|
||||
assert -1 < totals_i < guard_i < docs_i < chunks_i < last_i < walk_i, (
|
||||
"totals first, the recursive walk ONLY as the no-totals fallback"
|
||||
)
|
||||
render = js[js.find("function renderLevel(") : js.find("function renderEmpty(")]
|
||||
assert "const st = treeStats();" in render
|
||||
assert 'st.last ? fmtDate(st.last) : "–"' in render, (
|
||||
"the exact fmtDate formatting call is unchanged at every level"
|
||||
)
|
||||
|
||||
|
||||
def test_stat_cards_walk_the_whole_tree() -> None:
|
||||
"""The KB-wide stat cards walk the WHOLE tree (every file node at
|
||||
any depth): document count, chunks sum, max indexed_at (fmtDate
|
||||
"""The no-`totals` fallback walk (phase 97, kept defensive since
|
||||
phase 167): walk the WHOLE held tree (every file node at any
|
||||
depth): document count, chunks sum, max indexed_at (fmtDate
|
||||
reuse) — the values identical to the former flat walk. A
|
||||
0-document registered source contributes nothing (and still lists
|
||||
its row — the ls invariant)."""
|
||||
@@ -577,21 +804,30 @@ def test_module_docstring_documents_the_semantic_change() -> None:
|
||||
|
||||
def test_reset_to_top_when_the_location_vanished() -> None:
|
||||
"""PLAN §7.4: after a re-fetch, if the current source is no longer
|
||||
in the tree (unregistered/pruned) OR the current folder no longer
|
||||
exists under it, `current` RESETS to the top level BEFORE rendering
|
||||
— no stale breadcrumb, no stale block. The folder existence check
|
||||
mirrors the phase-94 rule: some indexed path starts with
|
||||
`folder + "/"` (the source root — \"\" — always exists)."""
|
||||
in the tree (unregistered/pruned) OR the current folder is no
|
||||
longer KNOWN under it, `current` RESETS to the top level BEFORE
|
||||
rendering — no stale breadcrumb, no stale block. Phase 167 (task
|
||||
04, D4): the phase-94 full-tree path-prefix walk becomes
|
||||
folderKnownIn — a folder is known iff its WHOLE ancestor chain
|
||||
exists in the levels the client HOLDS (the depth-1 tree + the
|
||||
drilled-and-merged levels; a broken chain — gone OR simply not
|
||||
loaded that deep — resets honestly; the node route's 404 is the
|
||||
drill path's own vanished-signal, pinned separately)."""
|
||||
js = _js()
|
||||
body = js[js.find("function resetVanishedLocation()") : js.find("function folderExistsIn(")]
|
||||
body = _fn(js, "resetVanishedLocation")
|
||||
assert "if (current.source === null) return;" in body, "the top level never vanishes"
|
||||
assert "kbTree.sources.find((s) => s.name === current.source)" in body
|
||||
assert body.count("current = { source: null, folder: null };") == 2, (
|
||||
"both vanishing arms reset to the top level"
|
||||
)
|
||||
exists = js[js.find("function folderExistsIn(") : js.find("function currentLevelNode(")]
|
||||
assert 'if (folderPath === "") return true;' in exists, "the source root always exists"
|
||||
assert "p.startsWith(folderPath + \"/\")" in exists, "the phase-94 existence rule"
|
||||
assert "folderKnownIn(src, current.folder)" in body, (
|
||||
"the reset consults KNOWN-ness (the held levels), never a full-tree walk"
|
||||
)
|
||||
known = _fn(js, "folderKnownIn")
|
||||
assert 'if (folderPath === "") return true;' in known, "the source root always exists"
|
||||
assert "if (!next) return false;" in known, "a broken ancestor chain is not known"
|
||||
assert "collect" not in _code(known), "the recursive path-collection walk is gone"
|
||||
assert "folderExistsIn" not in js, "the old full-tree existence walker is gone"
|
||||
# The reset runs on the success path of the load, before the render
|
||||
# (pinned in the load-order test — here: it is defined and called).
|
||||
assert "resetVanishedLocation();" in js[js.find("async function loadTree()"):]
|
||||
@@ -736,6 +972,7 @@ def test_styles_carry_the_tree_classes_with_no_new_hue() -> None:
|
||||
".kb-crumb-current",
|
||||
".kb-crumb-sep",
|
||||
".kb-level",
|
||||
".kb-level-loading",
|
||||
".kb-folders-table",
|
||||
".folder-link",
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user