phase: 105_hidden_folders_toggle
All completion criteria verified. Everything is green. **Phase 105 final verification pass — all criteria verified** - Verified the full implementation in the working tree: `git_sources.include_hidden` column + alembic `0019` (dev DB at head, column present), `iter_importable_files`/`import_sources` flag support with `str(root)`-keyed map used by both walk and progress pre-walk, `GitSourcePatchIn` rename with optional fields, sync/CLI pipeline wiring (OR-collision), and the per-row "Hidden" checkbox + tag + error line on the Sources page - Unit + integration: `uv run pytest` → exit 0 (2148 tests collected, all pass; this sandbox occasionally swallows pytest's final status line — exit codes verified) - Coverage: `uv run pytest --cov=app --cov-report=term-missing` → **TOTAL 99%** (3879 stmts, 15 miss) — >90% gate ✓ - Dedicated E2E: `uv run pytest tests/e2e/test_hidden_folders_toggle.py -v --no-cov` → **6 passed in 23.20s** (DB up, in isolation) - Regression E2E in isolation: `test_source_ignore_paths` 6 passed, `test_git_sources_admin` 6 passed, `test_local_directory_sources` 3 passed, `test_sync_button` 3 passed, `test_smoke` 3 passed - Lint/types: `uv run ruff check .` + `uv run pyright` → clean (0 errors/warnings) **Completion criteria:** (1) checkbox persists via PATCH 200 → "hidden on" tag + GET round-trips `include_hidden: true`; failure path reverts box + `role="alert"` canned message ✓; (2) flag OFF byte-identical (only `visible.md` indexed), ON indexes `.hidden/note.md` into the KB catalog, `EXCLUDED_DIRS` excluded both states ✓; (3) A2: flag OFF → `detail.pruned==1`, doc gone from catalog ✓; (4) PATCH bool-only/list-only/both/neither no-op, phase-89 fixed 422s unchanged, 404, anonymous 403 (incl. bool-only body) ✓; (5) env-fallback rows render no checkbox, WCAG-clean (aria-label, keyboard focus, visible label, text tag) ✓; (6) full gate green ✓; (7) commit left to the harness per instructions (no `git add`/`commit` run; phase files untouched). **Deviations:** none — no defects found; no code changes were needed on this pass. **Next pending phase:** `.agents/phases/todo/98_sync_summary_visibility`.
This commit is contained in:
+24
-12
@@ -469,12 +469,16 @@ class GitSourceIn(BaseModel):
|
||||
in the API layer, not the schema, so the A4 422 details stay fixed
|
||||
strings (the router's credential-safety discipline, applied for
|
||||
consistency).
|
||||
|
||||
``include_hidden`` (phase 105) is optional at create time (absent →
|
||||
stored ``False`` — A4).
|
||||
"""
|
||||
|
||||
kind: Literal["git", "local"] = "git"
|
||||
url: str | None = Field(default=None, min_length=1, max_length=500)
|
||||
path: str | None = Field(default=None, min_length=1, max_length=2000)
|
||||
ignore_paths: list[str] | None = Field(default=None)
|
||||
include_hidden: bool | None = Field(default=None)
|
||||
|
||||
@field_validator("url", mode="before")
|
||||
@classmethod
|
||||
@@ -497,12 +501,15 @@ class GitSourceOut(BaseModel):
|
||||
reports its path in ``url`` and the full row (``kind`` + ``path``)
|
||||
via ``GET``. ``ignore_paths`` (phase 89) is the stored, normalized
|
||||
list — non-null (a row created without it reports ``[]``).
|
||||
``include_hidden`` (phase 105) is the stored flag — a row created
|
||||
without it reports ``False`` (A4).
|
||||
"""
|
||||
|
||||
id: uuid.UUID | None
|
||||
url: str
|
||||
added_at: datetime | None
|
||||
ignore_paths: list[str]
|
||||
include_hidden: bool
|
||||
|
||||
|
||||
class GitSourceRow(BaseModel):
|
||||
@@ -516,7 +523,9 @@ class GitSourceRow(BaseModel):
|
||||
location column). ``id`` / ``added_at`` are nullable: env-fallback
|
||||
rows (table empty) carry neither. ``ignore_paths`` (phase 89) is the
|
||||
row's stored, normalized list — env-fallback rows (no DB row to
|
||||
store a list on) report ``[]``.
|
||||
store a list on) report ``[]``. ``include_hidden`` (phase 105) is
|
||||
the row's stored flag — env-fallback rows (no DB row to store a flag
|
||||
on) report ``False`` (the ``ignore_paths: []`` precedent).
|
||||
"""
|
||||
|
||||
id: uuid.UUID | None
|
||||
@@ -525,22 +534,25 @@ class GitSourceRow(BaseModel):
|
||||
path: str | None
|
||||
added_at: datetime | None
|
||||
ignore_paths: list[str]
|
||||
include_hidden: bool
|
||||
|
||||
|
||||
class GitSourceIgnoreIn(BaseModel):
|
||||
"""``PATCH /api/git-sources/{source_id}`` body (phase 89, A5).
|
||||
class GitSourcePatchIn(BaseModel):
|
||||
"""``PATCH /api/git-sources/{source_id}`` body (phase 89 A5;
|
||||
extended phase 105).
|
||||
|
||||
``ignore_paths`` is REQUIRED — the box's lines in REPLACE semantics:
|
||||
the body list (normalized + A4-validated in the API layer, with the
|
||||
fixed-detail 422s) becomes the row's whole list — an empty list
|
||||
clears all; an absent field is a 422 with the model's own detail.
|
||||
Entries are RAW box lines: normalization + the A4 limits are
|
||||
enforced in the API layer so the 422 details stay fixed strings
|
||||
(the router's credential-safety discipline, applied for
|
||||
consistency).
|
||||
Each field is independent and OPTIONAL: absent/None leaves the
|
||||
row's value unchanged; PRESENT applies. ``ignore_paths`` when
|
||||
present keeps the phase-89 A5 REPLACE semantics (the body list,
|
||||
normalized + A4-validated, becomes the row's whole list — empty
|
||||
list clears all; every pre-phase-105 client always sends the
|
||||
list, so their behavior is byte-identical). ``include_hidden``
|
||||
(phase 105) when present sets the stored flag. Both absent →
|
||||
200 no-op (the row is untouched).
|
||||
"""
|
||||
|
||||
ignore_paths: list[str]
|
||||
ignore_paths: list[str] | None = Field(default=None)
|
||||
include_hidden: bool | None = Field(default=None)
|
||||
|
||||
|
||||
class GitSourceList(BaseModel):
|
||||
|
||||
Reference in New Issue
Block a user