phase: 94_ls_tree_drilldown
All green. Verification complete. **Phase 94 — `ls` drill-down tree: final verification pass (all 5 tasks were already complete; verified, nothing to fix)** - Verified `ls` 3-level tree (`app/rag/agent.py`): `ls()` sources + summaries, `ls(source)`/`ls(source/folder)` drill-down, 50-line file cap + grep-pointer note, NOT-A-FOLDER teaching refusal - Verified `folder_summaries` (migration 0017, model, `app/rag/folder_summaries.py` generator: `FOLDER_SUMMARY_MODE` marker, fail-soft per folder, ≥2-doc scope + prune) wired change-gated in both sync paths - Verified 10-turn fixture battery verdict recorded in `TOOL_CALLING_TESTING.md` §9 (2026-09-11): turbo PASS 19/19 contract, 98.7 s (−12.5…−13.2 % vs baseline); lite PASS 18/18, 43.6 s (+7.7 %) — accuracy at/above baseline, gate met - `uv run pytest --cov=app --cov-report=term-missing` → 1939 passed, 0 failed; TOTAL coverage **99 %** (folder_summaries.py 100 %) - `uv run ruff check .` → clean; `uv run pyright` → 0 errors, 0 warnings - E2E in isolation: `test_ls_tree_drilldown.py` 3 passed; `test_agent_document_tools` 4, `test_agent_unlimited_tools` 4, `test_harness_aligned_tools` 3, `test_search_tool` 3, `test_grep_regex_teaching` 2, `test_response_to_docs` 4 — all passed (read/grep contracts untouched) - Dedicated folder-summary tests (fail-soft, prune, both sync paths, migration): 46 passed - Completion criteria: all 6 met; working tree holds only phase-94 changes (commit left to harness per protocol) **Next pending phase:** `95_read_truncation_cap`
This commit is contained in:
@@ -63,6 +63,10 @@ Data model — see ``.agents/PLAN.md`` §Data Model:
|
||||
(``id = 1``); every column NULL = "use the
|
||||
default" (env value for the strings, the built-in
|
||||
palette for the colors — task 01).
|
||||
* ``folder_summaries`` — one row per folder with ≥ 2 documents:
|
||||
the sync-time ``lite`` summary the drill-down
|
||||
``ls`` shows next to each folder (phase 94;
|
||||
``folder_path = ""`` = the source root).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -446,3 +450,51 @@ class UiSettings(Base):
|
||||
accent_bg: Mapped[str | None] = mapped_column(String(7), nullable=True)
|
||||
accent_ink: Mapped[str | None] = mapped_column(String(7), nullable=True)
|
||||
accent_line: Mapped[str | None] = mapped_column(String(7), nullable=True)
|
||||
|
||||
|
||||
class FolderSummary(Base):
|
||||
"""One sync-time folder summary (phase 94, task 01).
|
||||
|
||||
``ls`` is a drill-down tree (phase 94, ``00_phase.md``): the top
|
||||
level lists the synced projects, each with its stored source-root
|
||||
summary; drilling into a source lists its folders, each with its
|
||||
stored folder summary. This table holds those summaries:
|
||||
|
||||
* PK ``(source, folder_path)`` — ``source`` mirrors
|
||||
``documents.source`` (String(120)); ``folder_path`` mirrors
|
||||
``documents.path`` (String(1000)) and is the source-relative
|
||||
folder prefix. ``folder_path = ""`` is the SOURCE ROOT — the
|
||||
top-level source summary (the whole source's recursive subtree).
|
||||
* Rows exist only for folders with ≥ 2 documents (recursive count
|
||||
— the same set the ``ls`` count rule counts): a
|
||||
single-document folder is fully described by its one file line,
|
||||
so no ``lite`` burn. After a changed sync, rows whose folder
|
||||
dropped below 2 documents are pruned (a pruned/renamed folder's
|
||||
summary would otherwise go stale); rows for folders that still
|
||||
have ≥ 2 documents persist (an unchanged folder's summary is
|
||||
still true). Both rules are generator policy (``app.rag.
|
||||
folder_summaries``), not schema constraints.
|
||||
* ``summary`` — the 1–3 sentence plain-text description the aipi
|
||||
``lite`` model wrote at sync time (``FOLDER_SUMMARY_MODE``,
|
||||
``app.rag.folder_summaries`` — change-gated and fail-soft like
|
||||
the KB overview: an old summary is better than none).
|
||||
|
||||
Chat turns only READ these rows (the agent's ``ls`` output, phase
|
||||
94 task 03) — generation happens at sync time only (task 02).
|
||||
"""
|
||||
|
||||
__tablename__ = "folder_summaries"
|
||||
|
||||
#: Mirrors ``documents.source`` (String(120)) — PK part 1.
|
||||
source: Mapped[str] = mapped_column(String(120), primary_key=True)
|
||||
#: Mirrors ``documents.path`` (String(1000)) — the source-relative
|
||||
#: folder prefix; ``""`` = the source root. PK part 2.
|
||||
folder_path: Mapped[str] = mapped_column(String(1000), primary_key=True)
|
||||
#: The lite-written 1–3 sentence description — never empty (the
|
||||
#: generator validates before storing, ``app.rag.folder_summaries``).
|
||||
summary: Mapped[str] = mapped_column(Text)
|
||||
#: Fresh UTC stamp on every upsert (the ``kb_overview.updated_at``
|
||||
#: precedent; the generator always sets it explicitly).
|
||||
updated_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user