phase: 106_document_dates
Build and Push Containers / build-and-push-app (push) Successful in 4m35s
Build and Push Containers / build-and-push-db (push) Successful in 14s

Everything is verified green. Final report:

**Phase 106 — Document dates (final verification pass; all 10 tasks already complete)**

- Verified all phase artifacts: alembic `0020` (dev DB at `0020`), `doc_dates.py`, git `file_commit_dates`, importer `doc_dates_by_root`/`dates_updated`, both entry-point wirings, date APIs + tree `created_at`/`updated_at`, LLM surfaces (prompt block, `read` line 2, appended `ls` field), `apply_recency_boost` in `retrieve()`, UI columns/badge, admin editor, mock-LLM regex — all present and correct; no defects found, no fixes needed.
- `uv run pytest --cov=app --cov-report=term-missing` → **2299 passed, TOTAL 99%** (>90% ✓)
- `uv run pytest tests/e2e/test_document_dates.py -v --no-cov` → **6/6 passed** in isolation (DB up)
- 12 regression E2E suites (retrieval_quality, whole_document_context, agent_document_tools, ls_tree_drilldown, read_truncation_cap, kb_tree, kb_tree_nav, document_viewer, edit_summaries, import_documents, sync_button, hidden_folders_toggle, smoke) → **all green in isolation**
- `uv run ruff check .` → clean; `uv run pyright` → **0 errors, 0 warnings**

**Completion criteria:** 1) non-null `created_at` + 0020 upgrade/downgrade on dev DB ✓ (real-Alembic integration tests) 2) sync refresh/older/manual-persists/content-reset/no sources_meta bump ✓ 3) zip/tar mtime + future→today ✓ 4) LLM date surfaces + cross-check ✓ 5) UI Created/Updated/badge positions ✓ 6) admin editor set+revert round-trip ✓ 7) old-correct-beats-new-similar (defaults & boost-off) + near-tie + `BOR_RECENCY_BOOST=0` byte-identical ✓ 8) full gate ✓ 9) commit/phase-move — left to harness per instructions.

- **Notable:** recency default tuned 0.001 → **0.0007** (task 07 step 5 explicitly permits; measured margins recorded in `test_recency_boost.py` docstring).
- **Next pending phase:** none — `todo/` holds only this phase.
This commit is contained in:
2026-09-13 19:28:05 -04:00
parent cec819743d
commit ee3efb28c9
113 changed files with 8228 additions and 344 deletions
+153 -10
View File
@@ -1937,7 +1937,9 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
directory's STORED description — the surface-panel language of the
phase-93 page heads), and #folders-table (the ONE folders/sources
table — the .docs-table language; .kb-folders-table only re-styles
the 2nd/3rd column cells). Phase-08 tokens only — NO new hue
the 2nd/4th column cells — phase 106 (task 08, D8) moved
Description from 3rd to 4th, the Updated column taking 3rd). Phase-08
tokens only — NO new hue
(the phase-92 monochrome invariant): brand-ink on surface 9.0:1,
ink 13.8:1, ink-soft 5.1:1 (every pair AA). :focus-visible via the
global 3px outline rule; row targets keep the .docs-table cell
@@ -1981,7 +1983,12 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
.kb-level p { margin: 0; color: var(--ink-soft); } /* 5.1:1 on --surface */
.kb-folders-table { min-width: 480px; }
.kb-folders-table td:nth-child(2) { font-family: var(--font); font-size: inherit; max-width: none; }
.kb-folders-table td:nth-child(3) {
/* Phase 106 (task 08, D8): the Updated column sits at 3rd (BETWEEN
Documents and Description) — it takes the .docs-table cell defaults
(nowrap text, the table ink: var(--ink) on the wrap's --surface —
13.8:1, the pair recorded at :root). NO new CSS: the one-line clamp
below follows the Description cell, which moved to 4th. */
.kb-folders-table td:nth-child(4) {
white-space: nowrap; /* phase 99 (D1): one line — the clamp's budget is the column width */
min-width: 18rem;
max-width: 44rem;
@@ -3637,10 +3644,11 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
overflow: hidden;
text-overflow: ellipsis;
}
/* Meta row: source badge · format badge · mono path · indexed · chunks.
Phase 12/34: it may clip, but it must NEVER wrap — the meta stays on
one line in the titlebar row (the row is content-sized, so a wrap
would grow it). */
/* Meta row: source badge · format badge · mono path · created ·
indexed · chunks (phase 106 (task 08, D8) added created BEFORE
indexed). Phase 12/34: it may clip, but it must NEVER wrap — the
meta stays on one line in the titlebar row (the row is content-
sized, so a wrap would grow it). */
.doc-meta {
display: flex;
flex-wrap: nowrap;
@@ -3682,6 +3690,13 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
min-width: 6rem;
}
.doc-chunks { font-family: var(--mono); }
/* Phase 106 (task 08, D8): the Created badge — the SAME family as the
Indexed one (no own look: the meta row's text, var(--ink-soft) on
the titlebar's --surface — 5.1:1, the pair recorded at :root; the
modal's .doc-modal-meta row records the same pair). The explicit
declaration pins the inherited value: a themed --ink-soft moves the
badge with the row (byte-identical rendering). */
.doc-created { color: var(--ink-soft); /* 5.1:1 on --surface */ }
.doc-shell {
display: flex;
@@ -3856,6 +3871,133 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
}
.doc-summary-status:empty { margin-top: 0; }
/* Date edit affordance (phase 106, task 09 — D7, admin-only): the
"Edit date" text button after the Created badge (the
.doc-summary-edit family — one pill style for both inline
editors) and the editor box that swaps in for the button IN the
.doc-meta row: the native type=date input, Save / Cancel, the
muted underlined "Revert to sync" clear affordance (the phase-57
"clear = explicit" contrast), a role=status live line, and a
role=alert error line (the .git-source-error err pair). The meta
row may clip (nowrap) on the page, so the box wraps ITS children
internally (the modal's .doc-modal-meta already wraps). The
global 3px :focus-visible outline rule applies — no per-control
rule (the phase-105 checkbox idiom). :disabled = opacity +
cursor: wait (the .git-source-remove:disabled idiom — one PATCH
at a time). Contrast (verified, house style): button / Cancel /
revert / status ride the row's ink-soft on --surface (5.1:1, AA);
the input is ink on --bg (16.7:1, AA); Save is the solid brand
pill (--bg on --brand = 5.2:1, AA); the error line is the err
pair (9.1:1 on --err-bg, AA). Anonymous / token holders never see
any of it — the wiring is admin-gated (docAdminReady in
document.js), so the public badge row stays byte-for-byte the
task-08 shape. */
.doc-date-edit {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0.15rem 0.7rem;
border: 1px solid var(--line);
border-radius: 999px;
background: transparent;
color: var(--ink-soft); /* 5.1:1 on --surface (AA) */
font: inherit;
font-weight: 600;
font-size: 0.78rem;
letter-spacing: 0.02em;
cursor: pointer;
}
.doc-date-edit:hover { background: var(--brand-soft); color: var(--brand-ink); border-color: var(--brand); }
.doc-date-edit[hidden] { display: none; } /* the hidden attr must beat the display above */
.doc-date-editor {
display: inline-flex;
flex-wrap: wrap;
align-items: center;
gap: 0.35rem;
min-width: 0;
max-width: 100%;
}
.doc-date-input {
padding: 0.15rem 0.4rem;
border: 1px solid var(--line);
border-radius: var(--radius-sm);
background: var(--bg);
color: var(--ink); /* 16.7:1 on --bg (AA) */
font: inherit;
font-size: 0.78rem;
font-family: var(--mono);
}
.doc-date-save {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0.15rem 0.7rem;
border: 0;
border-radius: 999px;
background: var(--brand);
color: var(--bg); /* --bg on --brand = 5.2:1 (AA) */
font: inherit;
font-weight: 600;
font-size: 0.78rem;
cursor: pointer;
}
.doc-date-save:hover { background: var(--brand-hover); } /* the house hover lightening */
.doc-date-cancel {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0.15rem 0.7rem;
border: 1px solid var(--line);
border-radius: 999px;
background: transparent;
color: var(--ink-soft); /* 5.1:1 on --surface (AA) */
font: inherit;
font-weight: 600;
font-size: 0.78rem;
cursor: pointer;
}
.doc-date-cancel:hover { background: var(--err-bg); color: var(--err-ink); border-color: var(--err-line); }
.doc-date-revert {
display: inline-flex;
align-items: center;
min-height: 24px;
padding: 0.15rem 0.2rem;
border: 0;
background: transparent;
color: var(--ink-soft); /* 5.1:1 on --surface (AA) — the muted marker */
font: inherit;
font-size: 0.78rem;
text-decoration: underline;
cursor: pointer;
}
.doc-date-revert:hover { color: var(--ink); } /* 14.5:1 on --surface (AA) */
.doc-date-save:disabled,
.doc-date-cancel:disabled,
.doc-date-revert:disabled,
.doc-date-input:disabled {
opacity: 0.5;
cursor: wait; /* one PATCH at a time (the .git-source-remove:disabled idiom) */
}
.doc-date-status {
font-size: 0.78rem;
color: var(--ink-soft); /* 5.1:1 on --surface (AA) */
}
.doc-date-error {
flex-basis: 100%; /* drops onto its own row under the controls */
min-width: 0;
max-width: 100%;
overflow-wrap: anywhere; /* a long server detail never overflows the box */
font-size: 0.78rem;
font-weight: 600;
background: var(--err-bg);
color: var(--err-ink); /* 9.1:1 on --err-bg (AA — the .git-source-error pair) */
border: 1px solid var(--err-line);
border-radius: var(--radius-sm);
padding: 0.1rem 0.5rem;
}
.doc-date-status:empty, .doc-date-error:empty { display: none; } /* an empty live line takes no space */
/* Raw (non-markdown) formats: full-width mono pre, horizontal scroll. */
.doc-raw {
width: 100%;
@@ -4039,10 +4181,11 @@ details.thinking .thinking-text ul { margin: 0 0 0.5rem; }
.doc-modal-close svg { width: 18px; height: 18px; display: block; }
/* Meta row: the SAME badge classes as the viewer's .doc-meta (source
badge · format badge · mono path · indexed · chunks — no duplicate
badge styling here); unlike the fixed-height header bar it may WRAP,
so nothing clips. aria-live="polite" on the element announces the
load → meta swap (phase-10 a11y contract, modal variant). */
badge · format badge · mono path · created · indexed · chunks — no
duplicate badge styling here); unlike the fixed-height header bar it
may WRAP, so nothing clips. aria-live="polite" on the element
announces the load → meta swap (phase-10 a11y contract, modal
variant). */
.doc-modal-meta {
flex-shrink: 0;
display: flex;