phase: 155_folder_summary_voice
Build and Push Containers / build-and-push-app (push) Successful in 2m25s
Build and Push Containers / build-and-push-db (push) Successful in 13s

All verification is complete — the whole project is 100% green. Final report:

**Phase 155 final verification pass — complete.**

**Verified (all tasks 01–04 done in `complete/`):**
- Instruction nudge in `app/rag/folder_summaries.py` (forbidden openers as the pin, 4 constraints preserved, docstring cites the phase)
- `scripts/regen_folder_summaries.py` (import_docs idiom, full mode, cron-safe summary line, fail-loud boot)
- Unit pins, integration suite, mock voice update, dedicated E2E suite

**Test / lint / coverage:**
- `uv run pytest --cov=app -q` → 100% passed (exit 0, zero failures); coverage **99%** on `app/` (>90% ✓)
- `uv run pytest tests/e2e/test_folder_summary_voice.py -v --no-cov` → **3 passed** in isolation
- `uv run ruff check .` → clean; `uv run pyright` → 0 errors, 0 warnings

**Completion criteria:**
1. Marker + header prefix byte-identical — ✅ (git vs HEAD + unit pins verbatim, green)
2. Regen script full regeneration — ✅ (live smoke: exit 0, `folders=… limit=7` summary line; misconfig boot → named stderr, exit 1; `updated_at`-advance/no-prune/canned-text semantics proven by the integration suite, green)
3. Sync path untouched — ✅ (0 diffs to `app/api/sync.py` / `app/rag/importer.py`; phase-127 pins green)
4. E2E stored + rendered without forbidden openers — ✅ (3/3, exact canned-string assertions + phase-127 regression guard)
5. Full suite green, E2E isolated green, ruff + pyright clean, coverage >90% — ✅
6. Atomic commit — deferred to the harness (working tree left intact per protocol)

**Documentation:** README.md and AGENTS.md reviewed in full — verified consistent, no changes needed (README already documents the new script in the update workflow; all `.env.example` vars documented; pages table matches routes; 17 colors = 9+8; no stale mock-voice references).

**Decisions:** No live-infrastructure changes (dev-DB read + a 0-row script smoke only). The `TODO.md` working-tree edit is the owner's own, left untouched.

**Next pending phase:** `156_table_ux_polish`.
This commit is contained in:
2026-10-04 16:32:50 -04:00
parent c275735db4
commit 742eef955b
37 changed files with 2396 additions and 46 deletions
+71 -4
View File
@@ -272,6 +272,40 @@ def test_system_prompt_has_marker_and_locked_instruction() -> None:
assert FOLDER_SUMMARY_MODE in system # the marker the E2E mock keys on
def test_instruction_pins_the_variety_nudge_and_preserved_constraints() -> None:
"""Phase 155 task 01: the locked instruction keeps the four phase-94
constraints (1–3 sentences; plain text; no markdown; no invention)
and ADDS the variety direction — the two forbidden openers are the
pin (an explicit NOT, not a mere mention)."""
# The four preserved constraints (phase 94 — unchanged).
for fragment in (
"1-3 sentence",
"plain-text",
"natural language",
"Do not use markdown",
"Do not invent anything that is not in the list",
):
assert fragment in FOLDER_SUMMARY_INSTRUCTION, fragment
# The variety direction (phase 155): the "varied, natural way"
# direction must survive the grammar polish.
assert "Open in a varied, natural way" in FOLDER_SUMMARY_INSTRUCTION
assert "state what the folder is for" in FOLDER_SUMMARY_INSTRUCTION
# The two forbidden openers, banned by an explicit NOT.
assert "Do NOT begin with" in FOLDER_SUMMARY_INSTRUCTION
assert "'This folder contains'" in FOLDER_SUMMARY_INSTRUCTION
assert "'The <folder name> folder contains'" in FOLDER_SUMMARY_INSTRUCTION
def test_marker_and_header_prefix_stay_byte_identical() -> None:
"""Phase 155 task 01: the E2E mock keys on ``FOLDER_SUMMARY_MODE``
and the ``FOLDER_HEADER_PREFIX`` line — the instruction nudge must
not touch them (the mock-contract pin).``SYSTEM_PROMPT`` keeps the
marker-first shape: the nudge lands AFTER the marker."""
assert FOLDER_SUMMARY_MODE == "FOLDER_SUMMARY_MODE"
assert FOLDER_HEADER_PREFIX == "Folder: "
assert SYSTEM_PROMPT.startswith("FOLDER_SUMMARY_MODE: ")
# ---------- build_folder_summary_prompt: user ----------
@@ -369,22 +403,55 @@ def test_mock_returns_canned_folder_summary_naming_the_folder() -> None:
marker in the system prompt and returns the canned one-liner naming
the folder from the ``Folder: …`` header — driven through the
GENERATOR's real prompt, so the two can never drift (the drill-down
E2E asserts on this exact template)."""
E2E asserts on this exact template). Phase 155 task 01: the canned
voice is the natural-opener ``Documentation for <folder>.``."""
system, user = build_folder_summary_prompt(
"Homelab", "deployments/ansible",
[("Homelab", "deployments/ansible/lab-inventory.md", "Lab Inventory", None)],
)
assert compose_answer(_mock_body(system, user)) == (
"Fixture folder summary for Homelab/deployments/ansible."
"Documentation for Homelab/deployments/ansible."
)
# The source-root row names the source itself.
system, user = build_folder_summary_prompt("Homelab", "",
[("Homelab", "top.md", "Top", None)])
assert compose_answer(_mock_body(system, user)) == (
"Fixture folder summary for Homelab."
"Documentation for Homelab."
)
def test_mock_canned_folder_reply_shape_and_determinism() -> None:
"""Phase 155 task 01: the canned folder reply is the new voice —
it NAMES the folder (from the ``Folder: …`` header), AVOIDS the
two forbidden openers, and is a PURE function of the request (the
determinism contract: two identical requests → identical replies).
"""
def reply_for(source: str, folder_path: str) -> str:
system, user = build_folder_summary_prompt(
source, folder_path, [(source, "x.md", "X", None)]
)
return compose_answer(_mock_body(system, user))
first = reply_for("Homelab", "deployments/ansible")
second = reply_for("Homelab", "deployments/ansible") # same request → same reply
assert first == second, "pure function of the request (determinism contract)"
assert "Homelab/deployments/ansible" in first, "the reply names the folder"
# The two forbidden openers (phase 155's pin), case-insensitively.
assert not first.lower().startswith("this folder contains"), (
"the formulaic opener must not survive the canned reply"
)
assert not first.lower().startswith(
"the homelab/deployments/ansible folder contains"
), "the named-folder formulaic opener must not survive either"
# A different folder yields a different (but same-shape) reply —
# still names its own folder, still neither forbidden opener.
root = reply_for("Homelab", "")
assert root != first, "the reply is a function of the request, not a constant"
assert "Homelab" in root
assert not root.lower().startswith("this folder contains")
assert not root.lower().startswith("the homelab folder contains")
def test_mock_folder_marker_is_not_shadowed_by_the_summary_branch() -> None:
"""``FOLDER_SUMMARY_MODE`` contains ``SUMMARY_MODE`` as a substring —
the mock must check the folder branch FIRST, or every folder call
@@ -394,7 +461,7 @@ def test_mock_folder_marker_is_not_shadowed_by_the_summary_branch() -> None:
)
assert "SUMMARY_MODE" in system # the shadowing hazard is real
answer = compose_answer(_mock_body(system, user))
assert answer == "Fixture folder summary for S/a."
assert answer == "Documentation for S/a."
assert not answer.startswith("This document covers")