phase: 157_chat_chip_cap
Build and Push Containers / build-and-push-app (push) Successful in 2m19s
Build and Push Containers / build-and-push-db (push) Successful in 11s

All verification is green. Final report:

**Phase 157 — final verification pass (all 3 tasks already complete in `complete/`)**

- Verified the implemented work matches the design: `CHIP_CAP = 90` constant + display-only cap in `renderChips` (`slice(0,90).trimEnd() + "…"`), `title`/`aria-label`/click payload byte-unchanged; unit pins (89/90/91 letter & space, full-text invariant, short-string guard, Maybe-try single-path guard); phase-104 E2E updated to the cap contract
- Full suite `uv run pytest --cov=app --cov-report=term-missing`: **3578 passed**, app/ coverage **99%** (>90% ✓)
- `uv run ruff check .` clean; `uv run pyright`: 0 errors
- Dedicated E2E `uv run pytest tests/e2e/test_chat_chip_cap.py -v --no-cov`: **4/4 passed** in isolation (DB up)
- Cross-phase regression: phase-104 E2E 6/6, phase 05/80/103 chip suite 8/8 (seed chips <90 chars — cap is a no-op, assertions hold)
- Criteria: ≤91-char capped display ✓ (byte-for-byte pin) · click submits FULL 120-char question (user bubble) ✓ · `title` + clipped-case `aria-label` carry full text ✓ (375px viewport) · <90-char byte-identical ✓ (unit + live DOM) · commit: deferred to the harness (per harness protocol, overrides AGENTS.md rule 8 for this pass)
- Documentation: README.md reviewed in full — every `.env.example` var documented, all referenced scripts/pages/commands verified against the tree, the phase's chip-cap note is in the Chat section; AGENTS.md verified (commands, test files, layout-rule citations — phase 157 adds no new layout principle) → **verified consistent, no changes needed**
- No live-infrastructure changes were required or made
- Next pending phase: **158_thinking_timeline**
This commit is contained in:
2026-10-04 22:18:31 -04:00
parent 1513981c1c
commit 3f752fb77f
21 changed files with 1423 additions and 45 deletions
+13 -2
View File
@@ -1289,6 +1289,14 @@ function submitSuggestion(text) {
composer.requestSubmit();
}
/* Phase 157 (owner-locked 2026-10-03, A1): the chip display cap — a
* chip's DISPLAYED text never exceeds CHIP_CAP characters (the `…`
* brings a capped chip to at most CAP+1). The cap is the PRIMARY
* length guard; the phase-104 single-line CSS clip stays the
* secondary. Display-only: the title / aria-label / click payload
* keep the FULL text (the phase-104 contract, extended). */
const CHIP_CAP = 90;
function renderChips(container, items, { onSelect } = {}) {
// Replace only previous chips; keep any other children (e.g. the
// visually-hidden group label inside a "maybe-try" row).
@@ -1300,10 +1308,13 @@ function renderChips(container, items, { onSelect } = {}) {
btn.type = "button";
btn.className = "suggestion-chip";
btn.setAttribute("role", "listitem");
btn.textContent = text;
btn.textContent =
text.length > CHIP_CAP ? text.slice(0, CHIP_CAP).trimEnd() + "…" : text;
// phase 104 (owner 2026-09-12): the single-line chip clips long
// questions — `title` is the hover reveal, `aria-label` the
// clipped-case accessible name (the source-chip pattern).
// clipped-case accessible name (the source-chip pattern);
// phase 157 (owner 2026-10-03, A1): the CHIP_CAP display cap is
// the PRIMARY guard — the CSS clip is the secondary.
btn.title = text;
btn.addEventListener("click", () => {
submitSuggestion(text);