Explorar el Código

HANDOFF.md: mark Phase 13 shipped

Maintenance rule (§14). Moves Phase 13 from Upcoming → Shipped with
its SHA (b027c5d), drops the planning-body from §9 Upcoming (which is
now empty), resets the §12 resume prompt to "1–13 shipped, nothing
scheduled," and appends b027c5d plus the previously-missed 815e232
("note 5-dot Arbeitstage indicator follow-up") to the §13 git history
block so it matches `git log`.

No §3 directory refresh (no new files — pure edits to show.php,
sprint-planner.js, input.css, ACCEPTANCE.md). Test count unchanged at
88 / 208; §11 already reflects that.

No code changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
achiappa hace 2 semanas
padre
commit
d0fdf53e37
Se han modificado 1 ficheros con 28 adiciones y 129 borrados
  1. 28 129
      HANDOFF.md

+ 28 - 129
HANDOFF.md

@@ -269,130 +269,27 @@ with a `BOOTSTRAP_ADMIN` audit row.
       `active_days`; `max_working_days` in the body is rejected. Migration
       002 backfills legacy rows (half-days round up, clamped to 0..5).
       +14 tests, 88 total (was 74).
+- [x] **Phase 13 — Focus filter + Reset in the task list** (`b027c5d`):
+      new `[data-focus-select]` in the task-list toolbar picks one sprint
+      worker; `applyFilters()` grows a fourth AND predicate hiding rows
+      whose `[data-assign][data-sw-id="{focus}"]` is not > 0, and a new
+      `applyFocusColumnVisibility()` tags every sw column that is
+      all-zero across the remaining visible rows with `.focus-auto-hidden`
+      (a one-line utility added to `assets/css/input.css` — does NOT
+      touch `hiddenCols`, so clearing focus restores the user's manual
+      Columns picks). `[data-reset-filters]` wipes search, prio,
+      ownerFilterSet, focusWorker, and hiddenCols in one click and
+      re-hides itself. All state lives in `localStorage`
+      (`sp:{sprintId}:focusWorker` joins the existing namespace). Pure
+      client-side; no schema, route, or audit changes. Tests unchanged
+      at 88 (the phase is 100% JS over existing HTML, same pattern as
+      Phase 10).
 
 ### Upcoming
 
-- [ ] **Phase 13 — "Focus" filter in the task list**
-
-      **Problem.** With more than a handful of workers on a sprint, the
-      task list is wide and noisy for someone who only cares about what
-      *they* (or one specific teammate) are on the hook for. Today you
-      can filter by owner, but "owner" is not the same as "has time
-      assigned" — a task owned by Alice can still have Bob doing 3 days
-      of the work. Scanning a 12-worker grid for Bob's non-zero cells is
-      exactly what the computer should do.
-
-      **Goal.** Add a **Focus** control to the task-list toolbar. Pick
-      one sprint worker; the list then shows only tasks where that
-      worker's assignment is > 0, and any worker column that is zero for
-      every remaining visible task collapses away. A **Reset filters**
-      button next to it clears the search, priority filter, owner
-      multi-select, focus worker, and any manually-hidden columns in one
-      click. All state is purely client-side — no API changes.
-
-      **Scope (plan).**
-
-      1. **Toolbar (`views/sprints/show.php`).**
-         - Between the existing `[data-owner-filter-root]` and
-           `[data-columns-root]`, insert a `[data-focus-filter-root]`
-           block: a `<select data-focus-select>` with `<option value="">
-           All workers</option>` + one `<option value="{sw_id}">{name}
-           </option>` per sprint worker. Styled to match the other
-           toolbar controls.
-         - At the far left of the toolbar row, add a
-           `<button data-reset-filters>` (subtle, border-only, "Reset"
-           label). Visible only when any filter is active (managed by
-           the same logic that computes filter state below).
-         - No schema or controller changes — this is pure view + JS.
-
-      2. **JS filter state (`public/assets/js/sprint-planner.js`).**
-         - New localStorage key: `sp:{sprintId}:focusWorker`, string
-           value (sw_id or "").
-         - Hydrate on boot, reflect into `<select data-focus-select>`.
-         - On `change`: persist, then call `applyFilters()`.
-         - `applyFilters()` grows a fourth AND clause: if focus is set
-           and the row's `[data-assign][data-sw-id="{focus}"]` input has
-           value ≤ 0, hide the row. Use the same zero-tolerance the
-           capacity math uses (`Number(v) > 0`, not `!== 0`, so 0.0 is
-           treated as empty).
-
-      3. **Derived column auto-hide (new function,
-         `applyFocusColumnVisibility()`).**
-         - Called at the end of `applyFilters()` when focus is active.
-         - For each sprint worker's column `sw-{id}`:
-           - If any visible task row has `[data-assign][data-sw-id="{id}"]`
-             > 0 → keep the column as-is (respect the user's manual
-             visibility from the Columns dropdown).
-           - Otherwise → add a transient CSS class `focus-auto-hidden`
-             to every `[data-col="sw-{id}"]` cell/header (don't touch
-             the user's `hiddenCols` set, so turning focus off restores
-             their pick).
-         - When focus is cleared, strip every `.focus-auto-hidden` and
-           let `applyColumnVisibility()` re-run.
-         - Define `.focus-auto-hidden { display: none; }` in
-           `assets/css/input.css` (one line; Tailwind's `@layer
-           utilities` section, or inline in the view — former keeps the
-           vendored CSS path consistent).
-
-      4. **Reset button.**
-         - On click: clear `[data-task-search]`, reset
-           `[data-prio-filter]` to `""`, empty `ownerFilterSet` (and
-           persist), clear `focusWorker` (and persist), and empty
-           `hiddenCols` (and persist), then call the existing update
-           functions (`updateOwnerFilterUi`, `applyColumnVisibility`,
-           `applyFilters`). One code path, no reloads.
-         - Visibility rule: show the button when any of
-           `{search, prio, ownerFilterSet.size, focusWorker,
-           hiddenCols.size}` is non-empty. Re-evaluate after every
-           filter change.
-
-      5. **Edge cases / behaviour.**
-         - **Focus + owner + search all active** → AND. The existing
-           `applyFilters` ordering is fine; focus is just another
-           predicate per row.
-         - **Focused worker has no assigned tasks** → row list is empty,
-           every sw column is all-zero, so every sw column collapses.
-           The existing `[data-task-empty-filter]` banner covers the
-           empty-rows case — test that it shows, not the "No tasks yet"
-           banner.
-         - **New task created while focus is on** → `buildTaskRow` adds
-           a row with zero assignments, so the focus filter will hide
-           it immediately. Acceptable (user can clear focus to see it),
-           but a small UX surprise — call it out in the commit message.
-         - **Worker removed from sprint** → the reorder-then-reload
-           (§10) already covers this; focus just reads from the refreshed
-           DOM.
-         - **Archived sprints** → read-only, but the focus/reset
-           controls are pure UI, so they still work for viewers.
-
-      6. **Tests.** No new PHPUnit — this phase is 100% client-side JS
-         over existing HTML. Manual acceptance:
-           (a) pick a worker with assignments → only their tasks show
-               and only columns with non-zero cells for those tasks
-               remain;
-           (b) pick a worker with no assignments → empty-filter banner,
-               all sw columns collapsed;
-           (c) stack with search + prio + owner filters → all four AND;
-           (d) hit Reset → everything clears, Reset button vanishes.
-         Add these to [ACCEPTANCE.md](ACCEPTANCE.md) in the same commit
-         so the §10 manual walkthrough stays truthful.
-
-      **Out of scope.**
-      - Server-side enforcement of the filter. The API does not gate
-        which tasks a user can see — sprint membership already grants
-        read access to the whole sprint, and focus is a personal lens
-        over that.
-      - Multi-worker focus. Sticking to one worker at a time keeps the
-        UI + column-collapse rule simple. Multi-focus would muddy "what
-        counts as a relevant column" and nobody has asked for it.
-      - Persisting the Reset click as an audit event. Pure UI state, no
-        data mutation, no audit row.
-
-      **Spec alignment.**
-      - §3 / §4 / §5: unchanged — no schema or domain changes.
-      - §6 Routes: unchanged — no new endpoints.
-      - §7 Audit: unchanged — no mutations.
-      - §11: phpunit count stays 88 (no new tests).
+Nothing scheduled. Residual follow-ups are in §10; the main outstanding
+item is a human-run walkthrough of [ACCEPTANCE.md](ACCEPTANCE.md)
+(now covering Phases 1–13) in a running container.
 
 ## 10. Residual known gaps / deferred items
 
@@ -449,14 +346,14 @@ vendor/bin/phpunit
 Tell Claude:
 
 > Working on `/Users/achiappa/Development/claude_code_private/sprint_planer_web`.
-> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–12 are
-> shipped (see §9); Phase 13 ("Focus" filter + reset in the task list)
-> is planned but not implemented — the scope is in §9 under Upcoming.
-> Other outstanding items are in §10 (mostly a manual acceptance
-> walkthrough in the running container). If I ask you to work Phase 13,
-> follow the maintenance rule in §14 — commit code, then commit a
-> HANDOFF.md update separately that moves the entry from Upcoming →
-> Shipped with its SHA.
+> Read `HANDOFF.md`, the git log, and `ACCEPTANCE.md`. Phases 1–13 are
+> shipped (see §9) and §9 Upcoming is empty — no scheduled work.
+> Outstanding items are in §10 (mostly a human-run acceptance
+> walkthrough in the running container). If you plan to take on a new
+> phase, append its plan to §9 Upcoming first; when it ships, follow
+> the maintenance rule in §14 — commit code, then commit a HANDOFF.md
+> update separately that moves the entry from Upcoming → Shipped with
+> its SHA.
 
 Claude should verify what's described here against actual repo state
 before acting — nothing here is load-bearing once it grows stale.
@@ -464,6 +361,8 @@ before acting — nothing here is load-bearing once it grows stale.
 ## 13. Git history (as of this handoff)
 
 ```
+b027c5d Phase 13: Focus filter + Reset in the task list
+815e232 HANDOFF.md: note 5-dot Arbeitstage indicator follow-up
 1aca417 Sprint view Arbeitstage: 5-dot weekday indicator instead of a number
 59eb1d7 HANDOFF.md: mark Phase 12 shipped
 a634582 Phase 12: per-week weekday selection (Mo–Fr) drives Arbeitstage