feat(web): personal board — private tasks beside the work board - #75
Open
tym83 wants to merge 4 commits into
Open
feat(web): personal board — private tasks beside the work board#75tym83 wants to merge 4 commits into
tym83 wants to merge 4 commits into
Conversation
Attach your own private GitHub Project as a personal board: - Me view splits into Work and Personal panes (narrow screens switch panes with a clamped ‹ › bar); the personal pane is an embedded MeBoard (zone bands + stats, no duplicated toolbar/notes chrome). - Team view gains an owner-only virtual Personal chip that repoints the whole team machinery (grid, sprint, carry-over, weekly plan) at the personal project's no-team group — personal tasks get real sprints. - Privacy needs no server work: every GitHub call already runs under the requesting user's token and the board cache is gated per login, so a private personal project is invisible to everyone else. The pointer to it is a per-login localStorage preference and never leaves the client. - Implementation is two instances of the board machinery (useBoardData, extracted verbatim from App): each board owns its state, scoped watch socket and server address, so mutations, notes and logs route to the right project by construction. Server, API and MCP: zero changes. - A failing personal board degrades to a dismissible warning and never takes down the work board; attaching the work board itself is refused; view-as never shows a personal pane. Design: docs/design/personal-board.md; behaviour rows P1-P8 in docs/design/behavior-matrix.md. Frontend: typecheck clean, 33 vitest cases pass (8 new); Go: untouched, full test suite passes. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: tym83 <6355522@gmail.com>
- BLOCKER: lock-board mode disabled the guarantee, not the feature — the server pins every request to the locked project, so a 'personal' board would silently BE the shared work project and private cards would land where the whole team reads them. Everything personal is now gated on !lockBoard through one tested helper (personalPaneVisible): no button, no load, no pane, no chip. Design doc told the opposite; fixed. - Same-project guard now covers both directions: the dialog refused attaching the work board, but loading the personal project AS the work board created two instances over one project (doubled cards, cross-routed mutations). doLoad now detaches the pointer with a visible warning. - Column-order localStorage is board-scoped (legacy global key read as fallback): a shuffle on the personal team view no longer overwrites the work board's hand-picked column order. - Pane arrows go through the tested prevPane/nextPane transitions; the pane/chip gate is a pure tested helper (P2/P2a/P7 rows are now pinned by tests, matching the matrix's Test column convention). - reset() clears the queue badge and its debounce timer (no phantom pending counter after detach); a personal card's detail never falls back to the work board and is closed on detach; component reloads clear their error banner again (pre-refactor contract). - Docs: lock-board paragraph rewritten to the truth, stale tag/route test claims removed, behavior-matrix P-rows get the Test column. 37 vitest cases pass (4 new), typecheck clean, SPA builds, Go untouched. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: tym83 <6355522@gmail.com>
Found by live end-to-end testing (attach tym83/1, then repoint to a nonexistent #99): the load effect reset state only on detach, so a FAILED load of a new pointer left the previous board alive — the pane kept rendering (and would keep mutating) the old project while the toolbar already named the new one. Reset first on every pointer change, and drop a stale error from a superseded load via an effect-scoped cancel flag. Also verified live in the same session: same-project guard (both directions), card creation routed to the personal project only (checked via gh item-list on both projects), personal team mode (grid, carry-over, weekly plan against the personal project), the ≤820px pane switcher, and the broken-pointer warning leaving the work board untouched. The 61px horizontal overflow seen on narrow screens reproduces on main's plain Me board with any card — pre-existing, out of scope here. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: tym83 <6355522@gmail.com>
Two more real bugs from the deep re-verification pass: - Both MeBoard instances bound global keydown handlers: with the dual Me view an ArrowDown moved selection in BOTH panes and Shift+Arrow reordered cards on BOTH projects at once. The embedded pane no longer binds global keys (mouse/touch only), and the work pane ignores keys while hidden by the narrow-mode switcher (offsetParent check) — so a hardware keyboard on a phone cannot drive the invisible pane either. Verified live: ArrowDown selects in the work pane only. - useBoardData.load() now carries a generation: reset() and any newer load() orphan an in-flight load's eventual result. Previously a SLOW successful load resolving after detach resurrected the detached board's state and its watch socket (the a9bd071 cancel flag covered only the error path); a repoint A->B with A's response arriving last could land A's board under B's pointer. Also verified this round: per-instance DndContext means a drag can never cross panes/projects; TeamBoard conditional slots genuinely remount (no state leakage between work/personal instances); StrictMode double-invoke of the doLoad pointer-updater is idempotent. Behavior matrix: P9, P10. Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: tym83 <6355522@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Attach your own private GitHub Project as a personal board next to the work board. Personal cards get the full aeman experience — zones, sprints, carry-over, the weekly plan — while staying invisible to everyone else.
What
Why
The Me view is a day plan; real days mix work and personal tasks, but personal tasks must not live on a shared project. A second, user-owned private project gives them a home with zero server changes.
How it holds together
useBoardDataand instantiated per board — each owns its state, scoped watch socket and server address, so mutations, notes and logs route to the right project by construction. Server, REST API and MCP: zero changes (Go diff is empty).personalPaneVisible); a server-side@me-style allowance is a possible follow-up.Testing
go test ./...green, full Hugo-less SPA build embedded and exercised.gh project item-liston both), personal team mode with carry-over and weekly plan, the narrow-mode switcher, broken-pointer degradation, keyboard isolation between panes.docs/design/personal-board.md; behaviour rows P1–P10 indocs/design/behavior-matrix.md.Residual notes