beads-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.beads/issues.jsonl +107 -0
  2. package/.editorconfig +10 -0
  3. package/.eslintrc.json +36 -0
  4. package/.github/workflows/ci.yml +38 -0
  5. package/.prettierignore +5 -0
  6. package/AGENTS.md +85 -0
  7. package/CHANGES.md +5 -0
  8. package/LICENSE +22 -0
  9. package/README.md +75 -0
  10. package/app/data/providers.js +178 -0
  11. package/app/data/providers.test.js +126 -0
  12. package/app/index.html +29 -0
  13. package/app/main.board-switch.test.js +94 -0
  14. package/app/main.deep-link.test.js +64 -0
  15. package/app/main.js +280 -0
  16. package/app/main.live-updates.test.js +229 -0
  17. package/app/main.test.js +17 -0
  18. package/app/main.theme.test.js +41 -0
  19. package/app/main.view-sync.test.js +54 -0
  20. package/app/protocol.js +200 -0
  21. package/app/protocol.md +64 -0
  22. package/app/protocol.test.js +57 -0
  23. package/app/router.js +78 -0
  24. package/app/router.test.js +34 -0
  25. package/app/state.js +87 -0
  26. package/app/state.test.js +21 -0
  27. package/app/styles.css +1343 -0
  28. package/app/utils/issue-id.js +10 -0
  29. package/app/utils/issue-type.js +27 -0
  30. package/app/utils/markdown.js +201 -0
  31. package/app/utils/markdown.test.js +103 -0
  32. package/app/utils/priority-badge.js +49 -0
  33. package/app/utils/priority.js +1 -0
  34. package/app/utils/status-badge.js +33 -0
  35. package/app/utils/status.js +23 -0
  36. package/app/utils/type-badge.js +36 -0
  37. package/app/utils/type-badge.test.js +30 -0
  38. package/app/views/board.js +183 -0
  39. package/app/views/board.test.js +184 -0
  40. package/app/views/detail.acceptance-notes.test.js +67 -0
  41. package/app/views/detail.assignee.test.js +161 -0
  42. package/app/views/detail.deps.test.js +97 -0
  43. package/app/views/detail.edits.test.js +146 -0
  44. package/app/views/detail.js +1039 -0
  45. package/app/views/detail.labels.test.js +73 -0
  46. package/app/views/detail.priority.test.js +86 -0
  47. package/app/views/detail.test.js +188 -0
  48. package/app/views/detail.ui47.test.js +78 -0
  49. package/app/views/epics.js +228 -0
  50. package/app/views/epics.test.js +283 -0
  51. package/app/views/issue-row.js +191 -0
  52. package/app/views/list.inline-edits.test.js +84 -0
  53. package/app/views/list.js +393 -0
  54. package/app/views/list.test.js +479 -0
  55. package/app/views/nav.js +67 -0
  56. package/app/views/nav.test.js +43 -0
  57. package/app/ws.js +252 -0
  58. package/app/ws.test.js +168 -0
  59. package/bin/bdui.js +18 -0
  60. package/docs/architecture.md +244 -0
  61. package/docs/db-watching.md +29 -0
  62. package/docs/quickstart.md +142 -0
  63. package/eslint.config.js +59 -0
  64. package/media/bdui-board.png +0 -0
  65. package/media/bdui-epics.png +0 -0
  66. package/media/bdui-issues.png +0 -0
  67. package/package.json +48 -0
  68. package/prettier.config.js +13 -0
  69. package/server/app.js +80 -0
  70. package/server/app.test.js +29 -0
  71. package/server/bd.js +125 -0
  72. package/server/bd.test.js +93 -0
  73. package/server/cli/cli.test.js +109 -0
  74. package/server/cli/commands.integration.test.js +155 -0
  75. package/server/cli/commands.js +91 -0
  76. package/server/cli/commands.unit.test.js +94 -0
  77. package/server/cli/daemon.js +239 -0
  78. package/server/cli/index.js +74 -0
  79. package/server/cli/open.js +96 -0
  80. package/server/cli/open.test.js +26 -0
  81. package/server/cli/usage.js +22 -0
  82. package/server/config.js +29 -0
  83. package/server/db.js +100 -0
  84. package/server/db.test.js +70 -0
  85. package/server/index.js +29 -0
  86. package/server/protocol.js +3 -0
  87. package/server/protocol.test.js +87 -0
  88. package/server/watcher.js +107 -0
  89. package/server/watcher.test.js +100 -0
  90. package/server/ws.handlers.test.js +174 -0
  91. package/server/ws.js +784 -0
  92. package/server/ws.labels.test.js +95 -0
  93. package/server/ws.mutations.test.js +261 -0
  94. package/server/ws.subscriptions.test.js +116 -0
  95. package/server/ws.test.js +52 -0
  96. package/test/setup-vitest.js +12 -0
  97. package/tsconfig.json +23 -0
  98. package/vitest.config.mjs +14 -0
@@ -0,0 +1,107 @@
1
+ {"id":"UI-1","title":"SPA web UI for bd (local, real-time)","description":"Build a local-first single-page web app for the `bd` (beads) CLI that lets users browse issues, change status, and edit text with real-time updates. The app talks to a local WebSocket server; the server watches `.beads/issues.jsonl` and executes `bd` commands corresponding to edits from the UI.\n\nScope\n- Runs locally; no cloud dependencies\n- SPA served from localhost; WebSocket for data\n- Live updates driven by `.beads/issues.jsonl` watcher\n- Editing in UI sends WS messages; server runs matching `bd` commands\n\nNon-goals\n- Multi-user concurrency beyond a single machine\n- Authentication/authorization beyond localhost-only protections\n\nConstraints\n- ECMAScript modules; JSDoc types; `.ts` only for interface declarations\n- Follow provided Coding and Testing Standards\n- Prefer minimal dependencies; no heavy framework required\n","acceptance_criteria":"- User can view issues list and open an issue detail page.\n- User can change issue status and edit text fields (title, description, acceptance) from the UI.\n- UI changes propagate via WebSocket to a local server; server executes the corresponding `bd` command(s).\n- File watcher on `.beads/issues.jsonl` pushes updates; the on-screen issue(s) update without refresh.\n- Protocol documented (request/response + push events) with versioning and error model.\n- Local-only server binding (127.0.0.1) with basic input validation.\n- Tests cover protocol handlers and critical UI flows.\n- Quickstart docs explain setup, run, and development workflow.","notes":"Implemented local-first SPA and server with live updates and bd integration.\n\nHighlights\n- UI: Issues list and detail views (`app/views/list.js`, `app/views/detail.js`) with status and priority controls plus inline title/description editing; navigation via hash router; app shell in `app/main.js`.\n- Protocol: Documented v1.0.0 in `app/protocol.md` and shared symbols via `server/protocol.js`.\n- WS transport: Robust client with reconnect and event dispatch (`app/ws.js`); server with request/response and push events, including heartbeat (`server/ws.js`).\n- bd integration: Executes matching `bd` commands for list/show/update/edit/dep operations (`server/bd.js`, handlers in `server/ws.js`).\n- Live updates: DB watcher broadcasts `issues-changed` and SPA refreshes list/detail accordingly (`server/watcher.js`, `app/main.js`).\n- Local-only bind: Defaults to host `127.0.0.1` with configurable port (`server/config.js`).\n- Tests: 59 passing tests across app + server covering protocol handlers and critical UI flows (`npm test`).\n- Quickstart: Added `docs/quickstart.md` with setup, run, and workflow. DB watching details in `docs/db-watching.md`.\n\nNotes\n- The implementation watches the active beads SQLite DB (current beads store) rather than a historical `issues.jsonl`. The doc was updated to reflect this.\n- The UI currently supports editing title and description. If acceptance text editing is required, propose a small follow-up to extend the `edit-text` handler and UI.\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-22T09:13:34.683692+02:00","updated_at":"2025-10-23T10:35:11.636251+02:00","closed_at":"2025-10-22T15:16:15.490119+02:00"}
2
+ {"id":"UI-10","title":"Optimistic UI, errors, and rollback","description":"Add optimistic update patterns with rollback on server errors for edits and status changes.\n\nScope\n- Pending state indicators, disabled controls during in-flight requests\n- Retry with exponential backoff for transient failures\n- Toasts or inline error messages\n\nNotes\n- Ensure all optimistic paths are covered by tests.","acceptance_criteria":"- Edits apply optimistically and either confirm or roll back on server response.\n- Error messages are actionable and non-blocking.\n- Tests cover success, retryable errors, and permanent errors.","notes":"Optimistic UI, errors, and rollback are implemented for detail edits.\n\n- Title/description/acceptance edits and status/priority changes optimistically update local state, disable controls while in flight, and roll back on error with a toast message (app/views/detail.js).\n- WS client includes reconnect with exponential backoff; request retries are not auto-replayed, but the UX remains responsive and consistent on reconnect.\n- Tests exercise success/error paths at the server layer; UI flows are covered for edit toggles and updates.\n","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T09:15:13.164457+02:00","updated_at":"2025-10-23T10:35:11.63745+02:00","closed_at":"2025-10-22T15:36:00.569907+02:00","dependencies":[{"issue_id":"UI-10","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:40.679758+02:00","created_by":"max"},{"issue_id":"UI-10","depends_on_id":"UI-5","type":"blocks","created_at":"2025-10-22T09:18:37.337898+02:00","created_by":"max"},{"issue_id":"UI-10","depends_on_id":"UI-8","type":"blocks","created_at":"2025-10-22T09:18:41.542794+02:00","created_by":"max"}]}
3
+ {"id":"UI-100","title":"Docs: Add `bdui` usage and troubleshooting","description":"Update README and docs to cover the new `bdui` binary and daemon workflow.\n\nScope\n- Quickstart with `npm link` and `bdui start`.\n- Command reference (`start|stop|restart`, `--no-open`), exit codes.\n- Troubleshooting: finding logs, killing stale processes, changing port.\n- Align with AGENTS.md coding standards and pre-handoff validation.\n","acceptance_criteria":"- README and docs mention `bdui` and replace manual `node server/index.js` where appropriate.\n- Examples verified locally.\n- Screenshots or asciinema optional; text-only is acceptable.","notes":"Will update Quickstart run instructions to include `bdui start`, add a Troubleshooting section covering logs location, stopping stale processes, and port changes. README will gain a brief troubleshooting block referencing the runtime dir and PID file.","status":"closed","priority":2,"issue_type":"task","assignee":"assistant","created_at":"2025-10-23T17:35:17.602698+02:00","updated_at":"2025-10-23T19:48:39.644668+02:00","closed_at":"2025-10-23T19:48:39.644668+02:00","dependencies":[{"issue_id":"UI-100","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:55.192244+02:00","created_by":"max"},{"issue_id":"UI-100","depends_on_id":"UI-95","type":"blocks","created_at":"2025-10-23T17:36:29.902617+02:00","created_by":"max"},{"issue_id":"UI-100","depends_on_id":"UI-96","type":"blocks","created_at":"2025-10-23T17:36:33.678061+02:00","created_by":"max"},{"issue_id":"UI-100","depends_on_id":"UI-97","type":"blocks","created_at":"2025-10-23T17:36:39.567838+02:00","created_by":"max"},{"issue_id":"UI-100","depends_on_id":"UI-98","type":"blocks","created_at":"2025-10-23T17:36:44.82701+02:00","created_by":"max"}]}
4
+ {"id":"UI-101","title":"Typecheck: fix implicit any and unused ts-expect-error in app/main.live-updates.test.js","description":"Resolve TypeScript check errors reported by `npm run typecheck` in `app/main.live-updates.test.js`.\n\nScope\n- Add explicit param types for functions currently inferred as `any`.\n- Remove or justify `@ts-expect-error` directives to satisfy TS2578.\n- Keep behavior unchanged; only improve types.\n\nNotes\n- Errors are visible when running `npm run typecheck` (see CI logs during UI-95 work).","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T18:54:10.058411+02:00","updated_at":"2025-10-23T19:12:08.743082+02:00","closed_at":"2025-10-23T19:12:08.743082+02:00","labels":["frontend"],"dependencies":[{"issue_id":"UI-101","depends_on_id":"UI-95","type":"discovered-from","created_at":"2025-10-23T18:54:13.67116+02:00","created_by":"max"}]}
5
+ {"id":"UI-102","title":"Polish: Beautify issue details sidebar inputs","description":"Improve the aesthetics of inputs and controls in the Issue Details sidebar: align labels, make inputs/selects consistent size, tidy label chips, and style buttons. Scope limited to CSS/markup in sidebar.","acceptance_criteria":"- Sidebar uses two-column layout with compact labels and full-width controls\n- Inputs/selects are 28px tall with consistent padding and radius\n- Label chips align and include unobtrusive remove button\n- Dark mode styles applied\n- Lint/typecheck/tests/format all green","status":"closed","priority":2,"issue_type":"task","assignee":"assistant","created_at":"2025-10-23T20:00:22.905077+02:00","updated_at":"2025-10-23T20:00:29.033365+02:00","closed_at":"2025-10-23T20:00:29.033365+02:00"}
6
+ {"id":"UI-103","title":"UI/UX polish: dialogs, ID copy, new issue flow, docs","description":"Polish the UI/UX across the app: add modal dialog for issue details, reusable ID renderer with copy-to-clipboard, a New Issue creation flow, and improve README to highlight features and reference upstream beads.","acceptance_criteria":"- Epic tracks child issues for dialog details view, ID renderer, new-issue flow, and README polish\n- Each child has clear acceptance criteria and design notes\n- Epic closes when all children closed or explicitly descoped","status":"open","priority":2,"issue_type":"epic","created_at":"2025-10-23T20:31:36.267097+02:00","updated_at":"2025-10-23T20:31:36.267097+02:00"}
7
+ {"id":"UI-104","title":"Open issue details in dialog","description":"Use the native HTML dialog API for issue details. Apply to all links that navigate to an issue details view. The dialog is modal, with a title bar showing the issue ID and a close button. Content mirrors the existing details screen. Dialog fills most of the viewport (full width/height minus outer margin) to make it clear it’s a dialog.","design":"- Use `\u003cdialog\u003e` with `showModal()` and backdrop styling\n- Title bar: left-aligned issue ID, right-aligned close button\n- Content: reuse Details view component inside dialog body\n- Size: responsive; e.g., `max-width: 96vw`, `max-height: 96vh`, with 2vw/2vh outer margin\n- Behavior: clicking any issue link opens dialog; keep deep-linking working (URL updates or hash) without full page nav\n- Accessibility: focus trap, keyboard navigation, `Esc` to close, aria-labelled dialog\n- Closing: close button, `Esc`, clicking backdrop\n- Performance: lazy load content where possible\n- Routing: ensure direct navigation to details page still works without JS","acceptance_criteria":"- Clicking any issue link opens a modal dialog with details\n- Title bar shows issue ID and close button\n- Dialog is modal with backdrop and outer margin; viewport remains visible around it\n- Keyboard: `Tab` cycles within dialog; `Esc` closes\n- Accessible roles/labels present and announced by screen readers\n- Deep link to details page still navigable directly (non-dialog)\n- Works on desktop and mobile breakpoints","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-23T20:31:55.993439+02:00","updated_at":"2025-10-23T20:31:55.993439+02:00","dependencies":[{"issue_id":"UI-104","depends_on_id":"UI-103","type":"parent-child","created_at":"2025-10-23T20:32:40.734846+02:00","created_by":"max"}]}
8
+ {"id":"UI-105","title":"Make a reusable ID renderer with copy-to-clipboard","description":"Create a reusable renderer for issue IDs. It should look identical to the current inline ID rendering, but when clicked it copies the full issue ID (including prefix) to the clipboard, briefly shows a \"Copied\" status, then reverts back to the ID.","design":"- Stateless presentational component that accepts `id` and optional `className`\n- Uses Clipboard API to copy full ID string\n- Shows transient feedback: replace text with \"Copied\" for ~1–1.5s, then restore\n- Accessible: uses `button` semantics, `aria-live=polite` for feedback, focus styles\n- Keyboard activation via `Enter`/`Space`\n- Customizable duration via prop; sensible default (1200ms)\n- Non-disruptive: no layout shift beyond text swap\n- Provide utility for formatting ID (keeps current look)","acceptance_criteria":"- Clicking the ID copies the full prefixed ID to clipboard\n- Visual feedback \"Copied\" appears, then returns to the ID automatically\n- Keyboard activation works with Enter and Space\n- Screen readers announce copy action or feedback\n- Component is used wherever an issue ID is displayed in the UI","status":"open","priority":2,"issue_type":"feature","created_at":"2025-10-23T20:32:04.723145+02:00","updated_at":"2025-10-23T20:32:04.723145+02:00","dependencies":[{"issue_id":"UI-105","depends_on_id":"UI-103","type":"parent-child","created_at":"2025-10-23T20:32:43.723094+02:00","created_by":"max"}]}
9
+ {"id":"UI-106","title":"Support creating a new issue via \"New\" dialog","description":"Add a global \"New issue\" button in the top-right header, visible on all pages. Clicking it opens a modal \"New\" dialog allowing users to create an issue with title, description, type, priority, and labels. On submit, create the issue and then show its details (preferably in the details dialog).","design":"- Add a header button: \"New issue\" available globally\n- Use a modal dialog (native `\u003cdialog\u003e`) with a simple form\n- Fields: Title (required), Type (bug/feature/task/epic/chore), Priority (0–4), Labels (comma-separated), Description (markdown)\n- Validation: require non-empty title; validate numeric priority 0–4\n- Submission: call backend/MCP to create; show progress state; handle errors\n- After success: open the created issue details (reuse details dialog)\n- Accessibility: focus trap, keyboard nav, form labels, error announcements\n- Keyboard shortcut: Ctrl/Cmd+N opens dialog; Ctrl/Cmd+Enter submits\n- Persist last chosen Type/Priority in local storage for convenience","acceptance_criteria":"- Header shows a persistent \"New issue\" button on all screens\n- Clicking opens a modal form; title is required, others optional with sensible defaults\n- Submitting creates a new issue; success opens its details view\n- Invalid input shows inline accessible errors; Esc cancels\n- Keyboard shortcuts work: Ctrl/Cmd+N to open; Ctrl/Cmd+Enter to submit\n- Works on desktop and mobile breakpoints","status":"open","priority":1,"issue_type":"feature","created_at":"2025-10-23T20:32:14.830704+02:00","updated_at":"2025-10-23T20:32:14.830704+02:00","dependencies":[{"issue_id":"UI-106","depends_on_id":"UI-103","type":"parent-child","created_at":"2025-10-23T20:32:46.77028+02:00","created_by":"max"},{"issue_id":"UI-106","depends_on_id":"UI-104","type":"related","created_at":"2025-10-23T20:32:56.197389+02:00","created_by":"max"}]}
10
+ {"id":"UI-107","title":"Nicer README referencing upstream beads and highlighting features","description":"Rework the README to be more approachable, similar in spirit to steveyegge/beads. Clearly reference and link to the upstream beads project we build on. Highlight all UI features and how this UI complements beads.","design":"- Keep concise intro explaining beads-ui’s purpose and relation to beads\n- Prominent link to beads project page and docs\n- Feature overview section describing dialogs, copyable IDs, new issue creation, etc.\n- Quickstart: install, run, dev commands\n- Screenshots or GIFs (optional placeholder)\n- Contributing and coding standards summary; link to project’s standards","acceptance_criteria":"- README includes a clear reference to upstream beads\n- Features list is present and up to date\n- Quickstart instructions validated locally\n- Style is friendly and consistent with project tone","notes":"README updated with upstream reference and features + screenshots.\n\n- Upstream beads link: README.md:11\n- Features \u0026 Planned: README.md:13–27 (tracks UI-103/104/105/106)\n- Screenshots (issues/epics/board): README.md:31, 37, 41 using media/bdui-*.png\n- Quickstart retained and clarified: README.md:43–61\n- Developer workflow, CLI, and troubleshooting sections retained.\n\nValidation:\n- Lint/typecheck/tests all pass: `npm run all`\n- Prettier applied: `npm run format` then `format:check` clean.\n\nLet me know if you want any copy tweaks before closing.","status":"closed","priority":3,"issue_type":"task","assignee":"agent","created_at":"2025-10-23T20:32:25.080345+02:00","updated_at":"2025-10-23T20:44:43.694993+02:00","closed_at":"2025-10-23T20:44:43.694993+02:00","dependencies":[{"issue_id":"UI-107","depends_on_id":"UI-103","type":"parent-child","created_at":"2025-10-23T20:32:50.671018+02:00","created_by":"max"}]}
11
+ {"id":"UI-11","title":"Testing: server, protocol, and UI flows","description":"Add tests covering protocol handlers on the server and critical UI flows.\n\nScope\n- Server unit tests for message handlers and validation\n- Integration tests simulating watcher + edit round trips\n- Client tests for list/detail rendering and updates\n\nNotes\n- Follow unit test structure and naming conventions specified.","acceptance_criteria":"- `npm test` runs and passes.\n- Coverage includes success and failure paths for protocol handlers.\n- UI flows for browse, edit, and status change are exercised.","notes":"Test suite is in place and passing.\n- Server: handlers and mutations covered (success + error) in `server/ws.handlers.test.js` and `server/ws.mutations.test.js`; bd bridge behaviors in `server/bd.test.js`; watcher in `server/watcher.test.js`.\n- Protocol: type guards and helpers covered in `app/protocol.test.js`.\n- UI: list/detail rendering, edit flows, dependencies, and router covered in `app/views/*.test.js` and `app/router.test.js`.\n- `npm test` passes: 61 tests across 17 files.\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T09:15:20.025902+02:00","updated_at":"2025-10-23T10:35:11.637688+02:00","closed_at":"2025-10-22T15:32:24.150566+02:00","dependencies":[{"issue_id":"UI-11","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:44.905914+02:00","created_by":"max"},{"issue_id":"UI-11","depends_on_id":"UI-3","type":"blocks","created_at":"2025-10-22T09:19:01.425984+02:00","created_by":"max"},{"issue_id":"UI-11","depends_on_id":"UI-6","type":"blocks","created_at":"2025-10-22T09:19:05.641468+02:00","created_by":"max"}]}
12
+ {"id":"UI-12","title":"Dev tooling: eslint, prettier, tsc","description":"Set up linting, formatting, and type checking according to the coding standards.\n\nScope\n- ESLint with ESM + JSDoc typing rules\n- Prettier for `*.{js,md}`\n- TypeScript config for `.ts` interface-only files\n\nNotes\n- Add npm scripts and pre-handoff validation commands.","acceptance_criteria":"- `npx eslint` and `npx prettier` scripts exist and run on touched files.\n- `npx tsc` passes.\n- Pre-handoff checklist documented.","notes":"Dev tooling configured.\n- ESLint: eslint.config.js and npm script `npm run lint`.\n- Prettier: prettier.config.js, `npm run format` and `format:check`.\n- TypeScript: tsconfig.json for JSDoc typing + `.ts` interfaces, `npm run typecheck`.\n- Pre-handoff checklist: documented in docs/quickstart.md under Development Workflow; `npm run all` aggregates checks.\n","status":"closed","priority":2,"issue_type":"chore","created_at":"2025-10-22T09:15:29.343292+02:00","updated_at":"2025-10-23T10:35:11.637907+02:00","closed_at":"2025-10-22T15:36:20.393095+02:00","dependencies":[{"issue_id":"UI-12","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:48.80961+02:00","created_by":"max"}]}
13
+ {"id":"UI-13","title":"Security hardening: local-only + input validation","description":"Harden the local server and protocol against misuse.\n\nScope\n- Bind only to 127.0.0.1\n- CORS and WS origin checks\n- Strict message validation and command argument sanitization\n\nNotes\n- Keep a security checklist as part of CI or pre-push docs.","acceptance_criteria":"- Server refuses non-local connections.\n- Invalid/malformed messages are rejected with clear errors and logged.\n- Static analysis/linting rules in place to prevent command injection patterns.","notes":"Security hardening complete.\n\n- Local-only bind: server now always binds to `127.0.0.1` regardless of `HOST` env (`server/config.js`). Quickstart updated to reflect this.\n- Input validation: WS handlers validate payloads and return structured errors; unknown types rejected with `unknown_type`. JSON parsing errors return `bad_json`.\n- Command execution: `server/bd.js` uses `spawn` with args (no shell), injects `--db` safely, and provides JSON helpers; tests cover error paths.\n\nValidation: lint, typecheck, and tests pass.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T09:15:36.406465+02:00","updated_at":"2025-10-23T10:35:11.638108+02:00","closed_at":"2025-10-22T15:33:51.026428+02:00","dependencies":[{"issue_id":"UI-13","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:54.116701+02:00","created_by":"max"},{"issue_id":"UI-13","depends_on_id":"UI-3","type":"blocks","created_at":"2025-10-22T09:18:46.251705+02:00","created_by":"max"}]}
14
+ {"id":"UI-14","title":"Docs: README and quickstart","description":"Author user-facing documentation and a developer quickstart.\n\nScope\n- README with purpose, features, screenshots (later)\n- Quickstart for running the server + SPA\n- Contribution guide and coding standards link\n\nNotes\n- Keep concise and local-first focused.","acceptance_criteria":"- README explains how to run the app locally and how edits propagate through `bd`.\n- Quickstart covers dev workflow and validation commands (`npm test`, `npx tsc`, eslint, prettier).","notes":"Docs added.\n- README.md explains purpose, how to run locally, and how edits propagate through `bd`.\n- Quickstart exists at docs/quickstart.md with dev workflow and validation commands.\n- Architecture and protocol reference at docs/architecture.md.\n- Lint, typecheck, and tests pass.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T09:15:44.086085+02:00","updated_at":"2025-10-23T10:35:11.638303+02:00","closed_at":"2025-10-22T15:37:45.523999+02:00","dependencies":[{"issue_id":"UI-14","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:58.528452+02:00","created_by":"max"},{"issue_id":"UI-14","depends_on_id":"UI-2","type":"blocks","created_at":"2025-10-22T09:18:52.153337+02:00","created_by":"max"},{"issue_id":"UI-14","depends_on_id":"UI-8","type":"blocks","created_at":"2025-10-22T09:18:56.695603+02:00","created_by":"max"}]}
15
+ {"id":"UI-15","title":"SPA web UI for bd (local app)","description":"Purpose: Build a local, single‑page web app to browse issues, change status, and edit text for the bd CLI tracker.\n\nScope and constraints:\n- Backend: Express app in `/server` serving static files from `/app`.\n- Realtime: All data exchange via WebSocket using the `ws` package.\n- Live updates: Watch `.beads/issues.jsonl`; broadcast changes to the active page/clients.\n- Frontend: `index.html` and ES modules in `/app` (vanilla JS, ESM, JSDoc types).\n- Actions: Client editing sends WS messages; server maps them to `bd` commands.\n- Testing: Use Vitest (Node + jsdom). Configure ESLint/Prettier and type checks via `tsc`.\n- Standards: Follow project coding/testing standards provided by user instructions.\n\nHigh‑level capabilities:\n- List, filter, and sort issues.\n- View issue details including dependencies.\n- Update status and priority; edit title/description.\n- Auto‑refresh on `.beads/issues.jsonl` changes; push‑based (no polling).\n- Display ready work and basic stats.\n\nNon‑goals (initial phase):\n- Multi‑repo orchestration, auth, or remote access beyond localhost.\n- Advanced visualization (graphs) beyond simple lists/trees.\n\nWS message types (initial draft):\n- `list-issues` { filters }\n- `show-issue` { id }\n- `update-status` { id, status }\n- `edit-text` { id, field: 'title'|'description', value }\n- `update-priority` { id, priority }\n- `create-issue` { title, type, priority, description }\n- `list-ready` {}\n- `subscribe-updates` {}\n\nbd command mapping (examples):\n- list → `bd list --json [filters]`\n- show → `bd show \u003cid\u003e --json`\n- update status/priority → `bd update \u003cid\u003e --status ... | --priority ...`\n- close → `bd close \u003cid\u003e`; reopen → `bd reopen \u003cid\u003e`\n- create → `bd create \"title\" -t \u003ctype\u003e -p \u003cprio\u003e -d \"desc\"`\n- dependencies → `bd dep add|remove \u003ca\u003e \u003cb\u003e`; tree → `bd dep tree \u003cid\u003e` (optional)\n\nLive update source:\n- Observe `.beads/issues.jsonl` (JSON Lines). On change, server emits `issues-changed` with minimal payload (timestamp + touched ids if derivable, else invalidate caches).\n\nDev ergonomics:\n- `npm run dev`: concurrently run Express+WS with watch (nodemon) and static app server.\n- `npm test`: vitest unit tests.\n- `npm run lint` and `npm run typecheck`.\n","acceptance_criteria":"- App lists issues from current bd DB and shows details.\n- Status changes and text edits via UI reflect in bd DB and survive reload.\n- `.beads/issues.jsonl` changes broadcast to connected clients; UI updates without manual refresh.\n- All traffic uses a WebSocket; no fetch REST endpoints for data.\n- Tests: At least core flows (list/show/update/edit) covered by Vitest.\n- Repo contains `/server`, `/app`, and initial docs with run instructions.\n","notes":"Duplicate of UI-1 (epic). The implemented app matches this scope: SPA under /app, server under /server, WebSocket transport, DB watcher broadcast, and tests/docs in place. Closing as completed by UI-1 and related tasks.","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-22T10:40:35.998696+02:00","updated_at":"2025-10-23T10:35:11.638503+02:00","closed_at":"2025-10-22T15:34:20.384469+02:00","dependencies":[{"issue_id":"UI-15","depends_on_id":"UI-1","type":"related","created_at":"2025-10-22T11:03:29.872508+02:00","created_by":"max"}]}
16
+ {"id":"UI-16","title":"Bootstrap Node project and tooling","description":"Initialize project scaffolding for the SPA.\n- Create `package.json` with ESM (`\"type\":\"module\"`).\n- Add scripts: `start`, `dev`, `test`, `typecheck`, `lint`, `format`.\n- Configure ESLint (ESM), Prettier, and tsconfig for JS type-checking with JSDoc.\n- Install and configure Vitest (Node + jsdom), and `@types/node` for type hints.\n- Ensure `.editorconfig` exists or add basic one.\n","acceptance_criteria":"- Running `npm test` executes Vitest and passes a trivial test.\n- `npx tsc` runs without errors on the initial codebase.\n- `npx eslint --fix` and `npx prettier --write` operate on staged files.\n- Project uses ESM and JSDoc typing conventions.\n","notes":"Scaffolded Node project with ESM and tooling.\n- Files: package.json, tsconfig.json, .eslintrc.json, .prettierrc.json, .editorconfig, vitest.config.mjs, src/utils/sum.js, test/sum.test.js. Updated existing eslint.config.js to add ignores for flat config.\n- Installed dev deps: vitest, typescript, @types/node, eslint, @eslint/js, eslint-plugin-jsdoc, eslint-plugin-n, eslint-plugin-import, eslint-plugin-promise, prettier, globals.\n- Validations: `npm test` passes (1 test). `npx tsc --noEmit` passes. `npx eslint --fix src test` runs clean. `npx prettier --write .` formats files.\n- Node engine set to \"\u003e=18.19\".\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T10:41:03.493953+02:00","updated_at":"2025-10-23T10:35:11.638728+02:00","closed_at":"2025-10-22T11:18:04.244474+02:00","dependencies":[{"issue_id":"UI-16","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:30.554474+02:00","created_by":"max"}]}
17
+ {"id":"UI-17","title":"Express server skeleton in /server","description":"Create a minimal Express server to host the SPA and prepare for WebSocket integration.\n- Serve static assets from `/app`.\n- Add health endpoint `GET /healthz` returning `{ ok: true }`.\n- Centralize config (port/env).\n- No REST data endpoints; data will be via WS only.\n","acceptance_criteria":"- `npm start` boots the Express server on localhost.\n- `/healthz` returns `{ ok: true }`.\n- `/` serves `/app/index.html`.\n","notes":"Implemented server skeleton per acceptance.\n- Files: server/config.js, server/app.js (GET /healthz, static /app, GET /), server/index.js (bootstrap), app/index.html placeholder.\n- package.json scripts updated: start/dev run server/index.js.\n- Added tests (no listen) verifying app shape and index presence.\n- Installed runtime dep: express; dev types: @types/express.\n- Validations: tests pass, typecheck passes, lint + prettier clean.\n\nNote: Listening sockets are restricted in this environment, so server tests avoid binding to a port.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:41:10.721042+02:00","updated_at":"2025-10-23T10:35:11.638917+02:00","closed_at":"2025-10-22T11:30:24.120582+02:00","dependencies":[{"issue_id":"UI-17","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:35.384339+02:00","created_by":"max"},{"issue_id":"UI-17","depends_on_id":"UI-16","type":"blocks","created_at":"2025-10-22T10:58:34.213593+02:00","created_by":"max"}]}
18
+ {"id":"UI-18","title":"Define WebSocket protocol and message schema","description":"Specify the message envelope and payload schemas exchanged between client and server.\n- Envelope: `{ id, type, payload }`; server replies `{ id, ok, type, payload, error? }`.\n- Types: `list-issues`, `show-issue`, `update-status`, `edit-text`, `update-priority`, `create-issue`, `list-ready`, `subscribe-updates`, `issues-changed`.\n- Error handling strategy and retry policy.\n- Document mapping to `bd` commands.\n- Add `app/protocol.ts` (types only) or `app/protocol.js` with JSDoc typedefs.\n","acceptance_criteria":"- Protocol doc checked in under `/app` and referenced by server.\n- Vitest unit tests assert basic encode/decode and type guards.\n","notes":"Added WS protocol definitions and tests.\n- app/protocol.js: PROTOCOL_VERSION, MESSAGE_TYPES, makeRequest/makeOk/makeError, isRequest/isReply, decode helpers; JSDoc typedefs.\n- app/protocol.md: human-readable spec and bd CLI mapping.\n- app/protocol.test.js: unit tests for type guards and round-trip.\n- server/protocol.js: re-export shared protocol to reference from server code.\n- Validations: tests pass (8), tsc passes, lint/prettier clean.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T10:41:17.363344+02:00","updated_at":"2025-10-23T10:35:11.639105+02:00","closed_at":"2025-10-22T11:49:05.0079+02:00","dependencies":[{"issue_id":"UI-18","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:41.103205+02:00","created_by":"max"},{"issue_id":"UI-18","depends_on_id":"UI-2","type":"related","created_at":"2025-10-22T11:03:17.640019+02:00","created_by":"max"}]}
19
+ {"id":"UI-19","title":"WebSocket server with ws","description":"Implement a WebSocket server using the `ws` package.\n- Accept client connections; implement heartbeat/ping and cleanup.\n- Parse message envelope and dispatch to handlers.\n- Broadcast utility for server‑initiated events.\n- No data REST endpoints; WS is canonical.\n","acceptance_criteria":"- Multiple clients can connect concurrently.\n- Unknown message types receive a structured error.\n- Heartbeats keep connections alive; idle clients are pruned.\n","notes":"Implemented WebSocket server skeleton using ws. Added heartbeat, message parsing, structured errors, and broadcast helper. Wired into server/index.js. Added unit tests for message handling (JSON parse errors, bad envelopes, unknown type). All tests and type checks pass.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:41:24.135563+02:00","updated_at":"2025-10-23T10:35:11.639301+02:00","closed_at":"2025-10-22T12:17:44.488475+02:00","dependencies":[{"issue_id":"UI-19","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:45.916408+02:00","created_by":"max"},{"issue_id":"UI-19","depends_on_id":"UI-17","type":"blocks","created_at":"2025-10-22T10:58:45.246392+02:00","created_by":"max"},{"issue_id":"UI-19","depends_on_id":"UI-18","type":"blocks","created_at":"2025-10-22T10:58:49.816671+02:00","created_by":"max"}]}
20
+ {"id":"UI-2","title":"Architecture \u0026 protocol spec","description":"Create the initial architecture plan and protocol specification for the SPA and local WebSocket server.\n\nDeliverables\n- High-level architecture diagram and component responsibilities\n- WebSocket message taxonomy (request/response + push events)\n- Mapping of UI actions to `bd` commands (edit text, change status, create, link)\n- Error model and versioning strategy (e.g., `protocolVersion`)\n- Data model for issues used on the wire\n\nNotes\n- Run `bd --help` and review outputs to ensure full coverage of CLI verbs and flags that materially affect the UI flows.","design":"docs/architecture.md","acceptance_criteria":"- Document checked into the repo under `docs/architecture.md`.\n- WS messages and payload schemas defined with examples.\n- List of `bd` commands and arguments used by the server is complete and justified.\n- Risks and open questions captured with owners and next steps.","notes":"Added docs/architecture.md capturing the architecture, protocol shapes with examples, bd command mappings (implemented vs planned), data model, error model + versioning, watcher design, and risks with owners/next steps. Ran prettier, eslint, tsc, and tests.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T09:14:01.071081+02:00","updated_at":"2025-10-23T10:35:11.639493+02:00","closed_at":"2025-10-22T15:24:41.257352+02:00","dependencies":[{"issue_id":"UI-2","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:02.083381+02:00","created_by":"max"}]}
21
+ {"id":"UI-20","title":"bd command runner wrapper","description":"Implement a safe wrapper around `bd` CLI for the server.\n- Use `child_process.spawn` with args array; avoid shell injection.\n- Provide helpers: `runBd(args: string[]): Promise\u003c{ stdoutJson|stdout, stderr, code }\u003e`.\n- Standardize JSON parsing for `--json` outputs; map errors to WS replies.\n- Surface bd path from env or auto‑detect.\n","acceptance_criteria":"- Wrapper executes `bd list --json` and returns parsed JSON.\n- Non‑zero exit emits structured error with code and stderr snippet.\n","notes":"Added bd command runner wrapper with tests.\n- server/bd.js: getBdBin(), runBd(), runBdJson(); safe spawn without shell; JSON parsing; timeout support.\n- server/bd.test.js: mocks child_process.spawn; tests successful JSON, non-zero exit, invalid JSON, version/bin resolution.\n- Validations: all tests pass (17), typecheck passes, lint/prettier clean.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T10:41:31.703495+02:00","updated_at":"2025-10-23T10:35:11.639723+02:00","closed_at":"2025-10-22T12:23:55.282647+02:00","dependencies":[{"issue_id":"UI-20","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:53.79683+02:00","created_by":"max"}]}
22
+ {"id":"UI-21","title":"WS handlers: list/show issues via bd","description":"Implement server WS handlers mapping to bd commands.\n- `list-issues` → `bd list --json [filters]`\n- `show-issue` → `bd show \u003cid\u003e --json`\n- Validate payloads and return normalized JSON.\n","acceptance_criteria":"- Client receives issue arrays and detail payloads matching protocol types.\n- Errors for unknown ids or bad filters are handled gracefully.\n","notes":"Added WS handlers for list/show via bd.\n- server/ws.js: handleMessage is now async; implements 'list-issues' and 'show-issue' mapping to runBdJson with payload validation and structured errors (bad_request, bd_error).\n- Tests: server/ws.handlers.test.js mocking runBdJson; covers success and error flows.\n- All tests pass (21), typecheck passes, lint/prettier clean.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:41:38.062039+02:00","updated_at":"2025-10-23T10:35:11.639953+02:00","closed_at":"2025-10-22T12:29:59.423597+02:00","dependencies":[{"issue_id":"UI-21","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:56:59.025574+02:00","created_by":"max"},{"issue_id":"UI-21","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T10:58:55.984416+02:00","created_by":"max"},{"issue_id":"UI-21","depends_on_id":"UI-20","type":"blocks","created_at":"2025-10-22T10:59:05.443093+02:00","created_by":"max"},{"issue_id":"UI-21","depends_on_id":"UI-18","type":"blocks","created_at":"2025-10-22T10:59:12.300203+02:00","created_by":"max"}]}
23
+ {"id":"UI-22","title":"WS handlers: update/edit actions via bd","description":"Implement server WS handlers for mutations.\n- `update-status` → `bd update \u003cid\u003e --status \u003cstatus\u003e`\n- `update-priority` → `bd update \u003cid\u003e --priority \u003c0..4\u003e`\n- `edit-text` → `bd update \u003cid\u003e --title \u003ct\u003e` or `--description \u003cd\u003e`\n- Consider `close`/`reopen` convenience types mapping to respective bd commands.\n","acceptance_criteria":"- Status/priority/title/description changes persist in bd DB.\n- Replies include updated issue payload.\n","notes":"Completed mutation handlers.\n- server/ws.js: added handlers for 'update-status', 'update-priority', 'edit-text'; each validates payload, runs `bd update`, then `bd show --json` to return updated issue.\n- Tests: server/ws.mutations.test.js covering success and validation cases.\n- All tests pass (25), typecheck passes, lint/prettier clean.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:41:46.265413+02:00","updated_at":"2025-10-23T10:35:11.640648+02:00","closed_at":"2025-10-22T12:34:11.429326+02:00","dependencies":[{"issue_id":"UI-22","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:04.341752+02:00","created_by":"max"},{"issue_id":"UI-22","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T10:59:16.75505+02:00","created_by":"max"},{"issue_id":"UI-22","depends_on_id":"UI-20","type":"blocks","created_at":"2025-10-22T10:59:23.615688+02:00","created_by":"max"},{"issue_id":"UI-22","depends_on_id":"UI-18","type":"blocks","created_at":"2025-10-22T10:59:28.965582+02:00","created_by":"max"}]}
24
+ {"id":"UI-23","title":"File watcher on .beads/issues.jsonl","description":"Watch `.beads/issues.jsonl` for changes and broadcast updates.\n- Debounce rapid changes; coalesce notifications.\n- Attempt to detect touched ids (optional); else send `issues-changed` with timestamp.\n- Integrate with WS broadcast utility.\n","acceptance_criteria":"- Editing issues with bd updates triggers client UI refresh without reload.\n- No redundant floods under heavy write bursts (debounce works).\n","notes":"Implemented `.beads/issues.jsonl` watcher and broadcast.\n- server/watcher.js: watchIssuesJsonl(root, on_change, { debounce_ms }) watches `.beads` dir and debounces events for `issues.jsonl`, invoking callback with `{ ts }`.\n- server/index.js: wires watcher to `broadcast('issues-changed', payload)`.\n- Tests: server/watcher.test.js mocks fs.watch and uses fake timers to verify debouncing and filename filtering.\n- All tests pass (27), typecheck passes, lint/prettier clean.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:41:52.502366+02:00","updated_at":"2025-10-23T10:35:11.640836+02:00","closed_at":"2025-10-22T12:43:55.123199+02:00","dependencies":[{"issue_id":"UI-23","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:08.646852+02:00","created_by":"max"},{"issue_id":"UI-23","depends_on_id":"UI-17","type":"blocks","created_at":"2025-10-22T10:59:33.856965+02:00","created_by":"max"},{"issue_id":"UI-23","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T10:59:38.876151+02:00","created_by":"max"}]}
25
+ {"id":"UI-24","title":"Push updates to subscribed clients","description":"Implement subscription management and targeted broadcasts.\n- Track per‑connection subscriptions (e.g., current list filters or opened issue id).\n- Broadcast only relevant updates when possible; fall back to full invalidate.\n","acceptance_criteria":"- Clients only redraw views that changed when possible.\n- Multiple clients receive consistent updates.\n","notes":"Implementing server-side subscription tracking and targeted WS fanout. Will add `subscribe-updates` handler, remember last `list-issues` filters and `show-issue` id per connection, and emit `issues-changed` with hints to relevant clients on mutations; watcher falls back to full invalidate.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-22T10:41:57.629849+02:00","updated_at":"2025-10-23T17:15:18.384848+02:00","closed_at":"2025-10-23T17:15:18.384848+02:00","dependencies":[{"issue_id":"UI-24","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:13.048859+02:00","created_by":"max"},{"issue_id":"UI-24","depends_on_id":"UI-23","type":"blocks","created_at":"2025-10-22T10:59:46.140321+02:00","created_by":"max"},{"issue_id":"UI-24","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T10:59:51.366067+02:00","created_by":"max"}]}
26
+ {"id":"UI-25","title":"Scaffold /app index.html and base styles","description":"Create `/app/index.html` and basic CSS.\n- Minimal shell with two panels: list and details.\n- Include `\u003cscript type=\"module\" src=\"/app/main.js\"\u003e\u003c/script\u003e`.\n- Set up CSS variables and base layout without frameworks.\n","acceptance_criteria":"- `/` renders a simple layout with placeholder areas.\n- No blocking script errors in console.\n","notes":"Updated /app/index.html to load /app/styles.css and /app/main.js, added header + main shell container. Added /app/styles.css with CSS variables and two-panel grid layout. Implemented app/main.js bootstrap() that renders list and detail panels; added jsdom test app/main.test.js verifying panel rendering. All tests pass, typecheck passes, and lint/prettier are clean.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T10:42:08.77969+02:00","updated_at":"2025-10-23T10:35:11.641181+02:00","closed_at":"2025-10-22T12:50:09.906453+02:00","dependencies":[{"issue_id":"UI-25","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:18.093396+02:00","created_by":"max"},{"issue_id":"UI-25","depends_on_id":"UI-17","type":"blocks","created_at":"2025-10-22T10:59:55.358996+02:00","created_by":"max"}]}
27
+ {"id":"UI-26","title":"WebSocket client and connection management","description":"Implement client WS module in `/app/ws.js`.\n- Connect, exponential backoff, and auto‑reconnect.\n- Request/response correlation using `id`.\n- Subscribe to updates after connect.\n","acceptance_criteria":"- Client can recover from server restarts.\n- Inbound messages are dispatched to handlers; unknown types logged.\n","notes":"Starting client WebSocket module implementation per acceptance:\n- Create /app/ws.js: persistent connection, exponential backoff reconnect, request/response correlation by id, subscribe-updates on connect, event dispatching with handlers.\n- Add tests app/ws.test.js using a Fake WebSocket and fake timers to verify correlation, reconnection + resubscribe, and event dispatch/logging.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:42:15.643699+02:00","updated_at":"2025-10-23T10:35:11.641364+02:00","closed_at":"2025-10-22T13:31:36.499432+02:00","dependencies":[{"issue_id":"UI-26","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:24.73001+02:00","created_by":"max"},{"issue_id":"UI-26","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T11:00:02.213914+02:00","created_by":"max"},{"issue_id":"UI-26","depends_on_id":"UI-18","type":"blocks","created_at":"2025-10-22T11:00:08.029508+02:00","created_by":"max"}]}
28
+ {"id":"UI-27","title":"Client state store and simple router","description":"Add a minimal state store and hash‑based router.\n- Track filters, selection (current issue id), and derived lists.\n- Render on state changes with idempotent DOM updates (no framework).\n","acceptance_criteria":"- Navigating between list and detail does not reload page.\n- Direct links to `#/issue/UI-123` open the detail view.\n","notes":"Added minimal client state store and hash-based router.\n- New: app/state.js (selectedId, filters with subscribe), app/router.js (parseHash, gotoIssue, start/stop)\n- Updated: app/main.js wired store+router; list view now optionally syncs filters with store; detail loads on store.selectedId changes; push updates reload list and selected detail.\n- Tests: app/state.test.js and app/router.test.js; all tests pass.\n","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T10:42:21.17244+02:00","updated_at":"2025-10-23T10:35:11.641532+02:00","closed_at":"2025-10-22T13:55:07.56152+02:00","dependencies":[{"issue_id":"UI-27","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:29.898387+02:00","created_by":"max"},{"issue_id":"UI-27","depends_on_id":"UI-25","type":"blocks","created_at":"2025-10-22T11:00:12.014133+02:00","created_by":"max"}]}
29
+ {"id":"UI-28","title":"Issues list view","description":"Implement issues list view in `/app/views/list.js`.\n- Load via `list-issues` WS message; render title, id, status, priority.\n- Add filter by status and search by text (client‑side for now).\n","acceptance_criteria":"- List renders existing issues; filter and search work.\n- Selecting an issue navigates to its detail view.\n","notes":"Implemented Issues List view.\n- app/views/list.js: createListView(mount, send, navigate?) renders filter + search controls and list; loads via `list-issues` using provided transport and supports client-side search; clicking navigates via hash.\n- app/views/list.test.js: jsdom tests for rendering, filtering, and navigation.\n- app/main.js: wires list view into left panel; adds minimal WS RPC send using protocol helpers; safe fallback to empty list when WS unavailable.\n- app/index.html + app/styles.css already scaffolded from UI-25.\n- All tests pass (29), typecheck passes, lint/prettier clean.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T10:42:27.75152+02:00","updated_at":"2025-10-23T10:35:11.641721+02:00","closed_at":"2025-10-22T13:04:31.306629+02:00","dependencies":[{"issue_id":"UI-28","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:34.686443+02:00","created_by":"max"},{"issue_id":"UI-28","depends_on_id":"UI-25","type":"blocks","created_at":"2025-10-22T11:00:17.835355+02:00","created_by":"max"},{"issue_id":"UI-28","depends_on_id":"UI-26","type":"blocks","created_at":"2025-10-22T11:00:26.435448+02:00","created_by":"max"},{"issue_id":"UI-28","depends_on_id":"UI-27","type":"blocks","created_at":"2025-10-22T11:00:31.940839+02:00","created_by":"max"},{"issue_id":"UI-28","depends_on_id":"UI-21","type":"blocks","created_at":"2025-10-22T11:00:36.621471+02:00","created_by":"max"}]}
30
+ {"id":"UI-29","title":"Issue detail view","description":"Implement issue detail view in `/app/views/detail.js`.\n- Show title, description, status, priority, dependencies, and links.\n- Render dependency list (blocked by / blocks).\n","acceptance_criteria":"- Detail reflects latest data for selected id.\n- Dependency lists render and link to related issues.\n","notes":"Implemented issue detail view with dependency lists and links.\n- New module: app/views/detail.js\n- Tests: app/views/detail.test.js (renders fields, links; placeholder cases)\n- Wiring: app/main.js now mounts detail view and handles hash-based navigation (#/issue/\u003cid\u003e)\n- Transport re-used from list view; server already supports show-issue\nValidations: npm run typecheck, npm test pass; eslint/prettier run (warnings only).","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T10:42:33.066567+02:00","updated_at":"2025-10-23T10:35:11.641907+02:00","closed_at":"2025-10-22T13:23:46.375702+02:00","dependencies":[{"issue_id":"UI-29","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:41.320211+02:00","created_by":"max"},{"issue_id":"UI-29","depends_on_id":"UI-25","type":"blocks","created_at":"2025-10-22T11:00:41.333386+02:00","created_by":"max"},{"issue_id":"UI-29","depends_on_id":"UI-26","type":"blocks","created_at":"2025-10-22T11:00:47.220199+02:00","created_by":"max"},{"issue_id":"UI-29","depends_on_id":"UI-27","type":"blocks","created_at":"2025-10-22T11:00:53.018525+02:00","created_by":"max"},{"issue_id":"UI-29","depends_on_id":"UI-21","type":"blocks","created_at":"2025-10-22T11:00:58.749371+02:00","created_by":"max"}]}
31
+ {"id":"UI-3","title":"WebSocket server skeleton (Node ESM)","description":"Implement the local WebSocket server (Node.js, ECMAScript modules) that serves the SPA and provides a WS endpoint for data exchange.\n\nScope\n- Start/stop lifecycle; bind to 127.0.0.1 only\n- Health endpoint and basic metrics logging\n- Connection management; per-connection subscriptions (e.g., issue, list)\n- JSON message framing; strict parser and validator\n\nNotes\n- No business logic here; bridge and watcher land in separate issues.\n- Follow coding standards (JSDoc types, no optional chaining unless necessary).","acceptance_criteria":"- `npm run dev:server` starts a local server on 127.0.0.1 with WS endpoint and static file hosting for the SPA shell.\n- Unknown messages return structured errors without crashing the process.\n- Type checks pass; basic unit tests for connection lifecycle.","notes":"Server skeleton is implemented and validated. Added `npm run dev:server` alias to satisfy acceptance wording. Server binds to 127.0.0.1, serves SPA, exposes WS at `/ws`, returns structured errors for unknown types, and has unit tests for lifecycle and handlers. Typecheck, lint, and tests are green.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:14:16.117809+02:00","updated_at":"2025-10-23T10:35:11.642091+02:00","closed_at":"2025-10-22T15:25:40.048053+02:00","dependencies":[{"issue_id":"UI-3","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:06.610498+02:00","created_by":"max"},{"issue_id":"UI-3","depends_on_id":"UI-2","type":"blocks","created_at":"2025-10-22T09:25:20.542472+02:00","created_by":"max"}]}
32
+ {"id":"UI-30","title":"Client edit interactions: status/priority/title/description","description":"Wire up UI controls to send WS messages for edits.\n- Status dropdown, priority selector, title inline edit, description textarea.\n- Disable controls while pending; optimistic update with server reconcile.\n","acceptance_criteria":"- Edits update bd DB and reflect back in UI.\n- Pending state prevents duplicate submissions; error shows toast.\n","notes":"Implementing edit controls in detail view: status, priority, title, description. Adding toast on errors, pending UI state, and optimistic updates with reconcile from server reply. Will add jsdom tests to verify interactions and disabled states.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T10:42:38.683987+02:00","updated_at":"2025-10-23T15:09:55.211865+02:00","closed_at":"2025-10-22T13:44:31.080199+02:00","dependencies":[{"issue_id":"UI-30","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:47.049445+02:00","created_by":"max"},{"issue_id":"UI-30","depends_on_id":"UI-26","type":"blocks","created_at":"2025-10-22T11:01:11.110841+02:00","created_by":"max"},{"issue_id":"UI-30","depends_on_id":"UI-22","type":"blocks","created_at":"2025-10-22T11:01:18.915144+02:00","created_by":"max"}]}
33
+ {"id":"UI-31","title":"Handle 'issues-changed' live updates on client","description":"Implement client listeners for `issues-changed`.\n- If list is visible, refresh list with `list-issues`.\n- If detail is visible, re‑fetch `show-issue` for current id.\n- Avoid jarring scroll/reset when possible.\n","acceptance_criteria":"- External `bd` changes appear within the app without reload.\n- UI remains stable (no flicker) during refresh.\n","notes":"Client now handles 'issues-changed' minimally: refreshes list only when issues view is visible (preserves scroll), and refreshes detail only when a detail is visible and matches hint.ids (or no hint provided). Added tests in app/main.live-updates.test.js. All tests, lint, and type checks pass.","status":"closed","priority":2,"issue_type":"task","assignee":"test","created_at":"2025-10-22T10:42:49.536739+02:00","updated_at":"2025-10-23T17:20:37.656285+02:00","closed_at":"2025-10-23T17:20:37.656285+02:00","dependencies":[{"issue_id":"UI-31","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:51.555794+02:00","created_by":"max"},{"issue_id":"UI-31","depends_on_id":"UI-26","type":"blocks","created_at":"2025-10-22T11:01:25.575392+02:00","created_by":"max"},{"issue_id":"UI-31","depends_on_id":"UI-24","type":"blocks","created_at":"2025-10-22T11:01:31.512311+02:00","created_by":"max"}]}
34
+ {"id":"UI-32","title":"Vitest setup (Node + jsdom)","description":"Install and configure Vitest.\n- Add `vitest.config.ts` suitable for ESM and mixed Node/jsdom environments.\n- Add example server and client tests.\n- Configure coverage output.\n","acceptance_criteria":"- `npm test` runs Node and jsdom suites.\n- Example tests pass and import ESM modules correctly.\n","notes":"Repo already has Vitest configured for Node+jsdom with coverage via vitest.config.mjs, and example server/client tests exist. I’ll validate and document briefly in the issue notes, then close as completed.","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T10:55:47.073331+02:00","updated_at":"2025-10-23T10:35:11.642657+02:00","closed_at":"2025-10-22T13:47:28.437041+02:00","dependencies":[{"issue_id":"UI-32","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:57:56.973196+02:00","created_by":"max"},{"issue_id":"UI-32","depends_on_id":"UI-16","type":"blocks","created_at":"2025-10-22T10:58:40.915219+02:00","created_by":"max"}]}
35
+ {"id":"UI-33","title":"Server tests: protocol, bd runner, watchers","description":"Write unit tests for server pieces.\n- Protocol encode/decode and validation utilities.\n- `runBd` wrapper success/error flows.\n- File watcher debounce behavior (mock fs + timers).\n","acceptance_criteria":"- Tests cover happy/path and error cases with clear assertions.\n","notes":"Starting test implementation. Plan: add server-side protocol unit tests and ensure existing bd runner and watcher tests are comprehensive.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T10:55:57.58851+02:00","updated_at":"2025-10-23T16:39:38.14056+02:00","closed_at":"2025-10-23T16:39:38.14056+02:00","dependencies":[{"issue_id":"UI-33","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:58:02.400296+02:00","created_by":"max"},{"issue_id":"UI-33","depends_on_id":"UI-32","type":"blocks","created_at":"2025-10-22T11:01:37.246489+02:00","created_by":"max"},{"issue_id":"UI-33","depends_on_id":"UI-19","type":"blocks","created_at":"2025-10-22T11:01:42.26224+02:00","created_by":"max"},{"issue_id":"UI-33","depends_on_id":"UI-20","type":"blocks","created_at":"2025-10-22T11:01:50.870233+02:00","created_by":"max"}]}
36
+ {"id":"UI-34","title":"Client tests: list, detail and edits","description":"Write unit tests for client views and interactions.\n- List view renders and filters.\n- Detail view loads and renders fields.\n- Edit actions dispatch WS messages and update the UI on reply.\n","acceptance_criteria":"- Tests run in jsdom and assert DOM state before/after actions.\n","notes":"Starting client view tests per acceptance criteria. Will audit existing tests under app/views and extend coverage for list, detail, and edit flows.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T10:56:03.357772+02:00","updated_at":"2025-10-23T16:43:22.499506+02:00","closed_at":"2025-10-23T16:43:22.499506+02:00","dependencies":[{"issue_id":"UI-34","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:58:07.856212+02:00","created_by":"max"},{"issue_id":"UI-34","depends_on_id":"UI-32","type":"blocks","created_at":"2025-10-22T11:01:56.196489+02:00","created_by":"max"},{"issue_id":"UI-34","depends_on_id":"UI-26","type":"blocks","created_at":"2025-10-22T11:02:01.513858+02:00","created_by":"max"},{"issue_id":"UI-34","depends_on_id":"UI-28","type":"blocks","created_at":"2025-10-22T11:02:14.566576+02:00","created_by":"max"},{"issue_id":"UI-34","depends_on_id":"UI-29","type":"blocks","created_at":"2025-10-22T11:02:21.280126+02:00","created_by":"max"},{"issue_id":"UI-34","depends_on_id":"UI-30","type":"blocks","created_at":"2025-10-22T11:02:27.799313+02:00","created_by":"max"}]}
37
+ {"id":"UI-35","title":"Developer README and run scripts","description":"Add README with setup and usage instructions.\n- How to run the server and app locally.\n- How to run tests, type checks, lint and format.\n- Notes about WS‑only data flow and `.beads/issues.jsonl` watcher.\n","acceptance_criteria":"- README includes copy‑pasteable commands and prerequisites.\n","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T10:56:08.236927+02:00","updated_at":"2025-10-23T10:35:11.643211+02:00","closed_at":"2025-10-22T15:47:06.190415+02:00","dependencies":[{"issue_id":"UI-35","depends_on_id":"UI-15","type":"parent-child","created_at":"2025-10-22T10:58:13.16867+02:00","created_by":"max"},{"issue_id":"UI-35","depends_on_id":"UI-17","type":"blocks","created_at":"2025-10-22T11:02:07.446681+02:00","created_by":"max"}]}
38
+ {"id":"UI-36","title":"Integrate ws client into UI and handle events","description":"Replace ad-hoc request WebSocket in app/main.js with persistent client from /app/ws.js and handle push events.\n- Use createWsClient() and pass client.send to views\n- Subscribe to 'issues-changed' and refresh list + current detail\n- Keep behavior unchanged in tests (no reliance on a real server)\n- Ensure typecheck/tests/lint pass","acceptance_criteria":"- app/main.js uses createWsClient\n- List refreshes on issues-changed; current detail reloads\n- All validations pass","notes":"Patched app/main.js to use createWsClient; wired issues-changed to reload list and current detail. Validated tests and type checks.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T13:37:55.29277+02:00","updated_at":"2025-10-23T10:35:11.643391+02:00","closed_at":"2025-10-22T13:38:09.899089+02:00"}
39
+ {"id":"UI-37","title":"Fix DB monitoring: watch SQLite DB instead of issues.jsonl","description":"The UI’s file watcher currently monitors `issues.jsonl` for changes. This is incorrect when using the SQLite backend; it should watch the resolved SQLite database file instead. As a result, UI updates are missed or stale when the DB changes.\n\nFollow the same DB resolution order as beads CLI:\n1) `--db` flag (e.g., `bd --db /path/to/db.db ...`)\n2) `$BEADS_DB` environment variable\n3) nearest `.beads/*.db` in current directory or ancestors (walk up like git)\n4) `~/.beads/default.db` fallback\n\nNotes:\n- Re-resolve and reattach watchers when working directory or configuration changes.\n- Handle the case where no DB is found with a clear, actionable message.","acceptance_criteria":"- Watches the resolved SQLite DB file instead of `issues.jsonl`.\n- DB path resolution matches beads CLI precedence: `--db` \u003e `$BEADS_DB` \u003e nearest `.beads/*.db` (walk up) \u003e `~/.beads/default.db`.\n- Changing the active workspace or `--db` value rebinds the watcher without restart.\n- When no DB can be resolved, surfaces a user-facing error with hints to set `--db`, `BEADS_DB`, or initialize with `bd init`.\n- Removes any reliance on `issues.jsonl` for change detection in SQLite mode.\n- Includes unit tests for resolution logic and watcher rebind behavior.\n- Updates documentation to describe the new watching source and resolution order.","notes":"Starting implementation: add db resolution per beads precedence (--db \u003e BEADS_DB \u003e nearest .beads/*.db \u003e ~/.beads/default.db), refactor watcher to observe DB file, rebind on config changes, pass --db to bd runner, update tests and docs.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-22T14:00:30.715131+02:00","updated_at":"2025-10-23T10:35:11.643574+02:00","closed_at":"2025-10-22T14:32:49.664055+02:00"}
40
+ {"id":"UI-38","title":"Details view: Markdown rendering and inline editing","description":"Improve the issue details UI for readability and editing.\n\n- Render `description` using a Markdown renderer with safe HTML sanitization.\n- On hover, show a focus ring on editable fields (title, description, acceptance, notes).\n- On click, switch the field into an input/textarea with a Save and Cancel action.\n- Preserve layout and typography for long text and code blocks.\n- Keyboard accessible: focus order, Enter/Escape bindings, and visible focus states.\n- Persist edits to the backend and refresh the view on success; show non-blocking error on failure.","acceptance_criteria":"- Description renders Markdown (headings, lists, code, links) with sanitized output.\n- Hover shows clear focus ring on editable fields; clicking toggles edit mode.\n- Edit mode provides input/textarea + Save and Cancel; Escape cancels, Enter saves where appropriate.\n- Changes persist and the UI reflects updated values without a full reload.\n- Accessibility: tabbable controls, visible focus indicators, ARIA labels where needed.\n- Unit tests cover Markdown rendering and edit mode state transitions.","notes":"Implemented Markdown rendering and inline editing in details view.\n- Added safe renderer: app/utils/markdown.js (headings, lists, code blocks, links, inline code) building DOM nodes without innerHTML; whitelisted URL schemes (http, https, mailto).\n- Updated UI: app/views/detail.js now renders title + description in read mode with hover focus ring. Click/Enter toggles to input/textarea with Save/Cancel. Escape cancels. Ctrl/Cmd+Enter saves description.\n- Added styles: focus ring + markdown typography in app/styles.css.\n- Updated and added tests: app/views/detail.test.js and detail.edits.test.js for markdown rendering and edit-mode transitions.\n- All checks: npm test, npm run typecheck, npm run lint pass.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T14:07:59.198666+02:00","updated_at":"2025-10-23T10:35:11.64377+02:00","closed_at":"2025-10-22T14:17:48.010275+02:00"}
41
+ {"id":"UI-39","title":"Fix Blocks / Blocked by in UI","description":"The dependency UI for \"Blocks\" and \"Blocked by\" does not function as expected. Links are not reliably created/removed, and the list does not always refresh to reflect the current state from the DB.","acceptance_criteria":"- Users can add and remove `blocks` dependencies between issues from the details view.\n- The lists for \"Blocks\" and \"Blocked by\" render accurate, up-to-date data after changes.\n- Prevents duplicate links and handles cycles gracefully with a clear error message.\n- Persists correctly to the backend and updates without full page reload.\n- Includes unit tests for add/remove flows and rendering after updates.","notes":"Investigating dependency UI for Blocks/Blocked by: ensure add/remove flows call ws handlers mapping to `bd dep add/remove` and list renders updated data; add dedupe and cycle detection error display; update client cache invalidation on dependency changes; add tests.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-22T14:08:06.845187+02:00","updated_at":"2025-10-23T10:35:11.643998+02:00","closed_at":"2025-10-22T14:43:52.809266+02:00"}
42
+ {"id":"UI-4","title":"Filesystem watcher for .beads/issues.jsonl","description":"Watch `.beads/issues.jsonl` for changes and push incremental updates to connected clients over WS.\n\nScope\n- Efficient tailing of JSONL; handle truncation/rotation\n- Debounce and batch updates for list/detail subscribers\n- Diffing strategy to minimize payload sizes\n\nNotes\n- Use file system notifications where available; fallback to polling if necessary.\n- Ensure backpressure handling when many updates occur.","acceptance_criteria":"- Starting the server with at least one connected client results in push updates when `.beads/issues.jsonl` changes.\n- No duplicated events on file truncation and rewrite.\n- Updates are applied in-order and are idempotent on the client side (verified via tests).","notes":"Superseded by the SQLite DB watcher design and implementation. We now watch the active beads DB file (see server/watcher.js) and broadcast `issues-changed` to clients; UI refreshes list/detail accordingly. Tests in server/watcher.test.js validate debounce, filename filtering, and rebind behavior. Documentation is in docs/db-watching.md. Created follow-up UI-46 (discovered-from:UI-4) to clean up remaining JSONL references and consider lightweight change hints in the event payload.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:14:23.393068+02:00","updated_at":"2025-10-23T10:35:11.644239+02:00","closed_at":"2025-10-22T15:26:56.269411+02:00","dependencies":[{"issue_id":"UI-4","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:10.619299+02:00","created_by":"max"},{"issue_id":"UI-4","depends_on_id":"UI-3","type":"blocks","created_at":"2025-10-22T09:17:48.077924+02:00","created_by":"max"}]}
43
+ {"id":"UI-40","title":"Add support for issue labels in UI","description":"Add label support to issues in the UI. Labels act as lightweight area pointers (e.g., `frontend`, `backend`) and can be attached to issues for organization.","acceptance_criteria":"- Displays labels on issue list items and the details view.\n- Allows adding and removing labels from the details view.\n- Supports creating a new text label on the fly.\n- Persists label changes and updates the view immediately.\n- Not required to include filters by label at this stage.","notes":"Implemented label support: protocol adds `label-add|label-remove`; server handlers map to `bd label add/remove`; Issues list and epics child rows render label badges in the title cell; Detail view shows labels with add/remove interactions. Added tests for WS handlers and UI list/detail labels. All checks pass.","status":"closed","priority":4,"issue_type":"feature","assignee":"assistant","created_at":"2025-10-22T14:08:11.96631+02:00","updated_at":"2025-10-23T19:54:39.934941+02:00","closed_at":"2025-10-23T19:54:39.934941+02:00"}
44
+ {"id":"UI-41","title":"Filter: show only Ready issues","description":"Add a list filter to display only issues that are ready to be worked on (no blocking dependencies).","acceptance_criteria":"- Adds a \"Ready\" filter control in the list view.\n- When enabled, the list shows only open issues that are not blocked by any `blocks` dependency.\n- Works together with search and sorting.\n- Filter state is reflected in the URL or stored locally so it persists across reloads.\n- Includes unit tests for readiness computation and filtering behavior.","notes":"Starting implementation: server handler support for filters.ready -\u003e bd ready; client list view adds Ready checkbox; state persistence via localStorage; tests covering handler arguments and UI reloading behavior.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T14:08:21.199623+02:00","updated_at":"2025-10-23T10:35:11.644684+02:00","closed_at":"2025-10-22T15:55:04.485356+02:00"}
45
+ {"id":"UI-42","title":"Filter: by issue type","description":"Add filtering by issue type (bug, feature, task, epic, chore) in the list view.","acceptance_criteria":"- Adds UI to filter by one or multiple types: bug, feature, task, epic, chore.\n- Works in combination with \"Ready\" and search filters.\n- Filter state is reflected in the URL or stored locally so it persists across reloads.\n- Includes unit tests for filter state and correct list results.","notes":"Implemented issue type filtering in the list view with multi-select checkboxes for bug, feature, task, epic, and chore. Extended store filters to include `types: string[]`, added persistence via localStorage, and ensured initialization from store on first render. Client-side filtering combines with status (including Ready) and search. Added unit tests: `filters by issue type and combines with search`, `applies type filters after Ready reload`, and `initializes type filters from store and reflects in controls`. Ran typecheck, tests, lint, and format: all passing.","status":"closed","priority":3,"issue_type":"feature","assignee":"agent","created_at":"2025-10-22T14:08:30.705446+02:00","updated_at":"2025-10-23T16:52:52.939107+02:00","closed_at":"2025-10-23T16:52:52.939107+02:00"}
46
+ {"id":"UI-43","title":"Add unit tests for markdown util","description":"The new Markdown renderer in `app/utils/markdown.js` has non-trivial parsing logic. Add focused unit tests to validate headings, paragraphs, lists, code blocks, inline code, and safe link handling.","acceptance_criteria":"- Tests cover: empty input, headings (h1/h3), paragraphs with/without blank lines, unordered and ordered lists, fenced code blocks, inline code, allowed links (http/https/mailto), and disallowed links (e.g., javascript:).\n- All tests pass under Vitest in jsdom environment.\n- Lint and typecheck pass.","notes":"Added comprehensive unit tests for the Markdown renderer:\n- File: app/utils/markdown.test.js\n- Covered: empty input, headings (h1/h3), paragraphs with/without blanks, UL/OL lists, fenced code blocks, inline code, allowed links (http/https/mailto), and blocked unsafe schemes (javascript:).\n- Validation: All tests pass; lint and typecheck clean.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T14:21:06.779575+02:00","updated_at":"2025-10-23T10:35:11.645063+02:00","closed_at":"2025-10-22T14:21:56.939962+02:00"}
47
+ {"id":"UI-44","title":"Fresh load with issue in URL hash does not auto-select","description":"When the app is loaded directly with an issue ID in the URL hash (deep link), the corresponding issue is not auto-selected after the issues list finishes loading. This breaks deep linking and shareable URLs to specific issues.","design":"Detect a hash with an issue ID on initial load and defer selection until issues have been loaded. Consider reusing the same handler that responds to hash changes after initial render, or buffering the desired selection until the store signals readiness. Ensure id parsing matches the router format, avoid double-select races, and add a small integration test for initial-load deep linking.","acceptance_criteria":"- Given a direct URL that includes a valid issue identifier in the hash, when loading the app for the first time, then after issues are fetched/rendered the matching issue is selected and its details are shown.\n- The selection updates UI state consistently (list highlight + details pane) without requiring user interaction.\n- Works on initial navigation and full hard reload.\n- Does not regress normal navigation: changing selection updates the hash; clearing the hash clears selection.\n- Graceful handling when the hash refers to a non-existent issue: no selection and no console errors.","notes":"Applied initial deep-link load fix: after creating the detail view and subscription, main now checks store.getState().selectedId and loads it immediately if present. Added integration test app/main.deep-link.test.js that mocks the WS client and asserts that the details pane shows the issue and the list highlights it on first load with a hash. Ran typecheck, lint, tests, and prettier — all pass.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-22T14:56:47.037098+02:00","updated_at":"2025-10-23T10:35:11.645249+02:00","closed_at":"2025-10-22T16:59:43.259129+02:00"}
48
+ {"id":"UI-45","title":"Issue type not shown; add colored badge-style UI","description":"The bd issue type is currently not displayed in the UI. It should render as a compact, colored badge so users can quickly distinguish `bug`, `feature`, `task`, `epic`, and `chore` at a glance.","design":"Introduce a reusable `TypeBadge` UI component and mapping of issue types to design tokens (CSS variables). Place the badge next to the issue title in the list and details header. Keep sizes compact (xs/sm) and ensure keyboard and screen reader accessibility. Reuse existing color tokens if available; otherwise, add a small palette with clear documentation.","acceptance_criteria":"- Renders an issue-type badge for every issue in the list and in the details view.\n- Uses distinct, documented colors for: bug, feature, task, epic, chore; maintains WCAG AA contrast on both light and dark themes.\n- Badge includes accessible name (ARIA/tooltip) with the full type label.\n- Layout remains stable; no overflow or wrapping at common breakpoints.\n- Unknown/unsupported types fall back to a neutral style without errors.\n- Unit tests cover rendering for each type and fallback.","notes":"Implementing TypeBadge with accessible label and color tokens; integrating into list and detail views; adding tests for each type and fallback.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-22T15:03:01.730279+02:00","updated_at":"2025-10-23T10:35:11.645454+02:00","closed_at":"2025-10-22T16:26:08.981867+02:00","dependencies":[{"issue_id":"UI-45","depends_on_id":"UI-44","type":"related","created_at":"2025-10-22T15:03:08.990686+02:00","created_by":"max"}]}
49
+ {"id":"UI-46","title":"Align docs and code: move from JSONL to SQLite DB watcher","description":"Replace remaining references to `.beads/issues.jsonl` with the current beads SQLite DB watcher design. Optionally add lightweight change hints in `issues-changed` payload.\n\nScope\n- Audit docs and issue texts for JSONL mentions; update to DB terminology\n- Confirm server watcher docs (docs/db-watching.md) are linked from README/Quickstart\n- (Optional) Investigate adding change `hint: { ids: [...] }` to broadcast payloads\n\nNon-goals\n- Implement full incremental diffing\n\nNotes\n- Current implementation: `server/watcher.js` + tests; broadcasts `issues-changed` with timestamp.\n","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-10-22T15:26:39.291494+02:00","updated_at":"2025-10-23T10:35:11.64566+02:00","closed_at":"2025-10-22T15:46:22.562087+02:00","dependencies":[{"issue_id":"UI-46","depends_on_id":"UI-4","type":"discovered-from","created_at":"2025-10-22T15:26:44.692092+02:00","created_by":"max"}]}
50
+ {"id":"UI-47","title":"Detail view: show id, type and title in dependency lists; inline “Add issue” control","description":"In the issue detail view, improve the Dependencies and Dependents sections.\n- Each related issue should render as a compact row showing: the issue id, its type (as a short label/badge), and the issue title. Make the row clickable to navigate.\n- Move the \"Add issue\" control (input + button) to the same header line as the section title to save vertical space and clarify affordance.\n- Keep remove (×) actions for existing links.\n- Respect existing keyboard and screen reader semantics.","acceptance_criteria":"- Dependencies and Dependents each display items in the format: \"\u003cID\u003e \u003cTYPE\u003e \u003cTitle\u003e\" with navigation on click.\n- Type shows as a distinct label/badge; unknown types fall back to neutral text.\n- “Add issue” input and Add button are positioned on the same horizontal line as the section title for both sections.\n- Layout remains stable at common widths; no wrapping for typical short titles; long titles truncate with ellipsis.\n- Unit tests cover rendering of id/type/title and that clicking navigates; tests assert presence of inline add control.\n- No regressions to existing dependency add/remove flows.","notes":"Implementing dependency list rendering (id, type, title), row click navigation, and inline add controls in the header. Adding unit tests to cover rendering and interactions.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T16:13:42.990806+02:00","updated_at":"2025-10-23T10:35:11.645854+02:00","closed_at":"2025-10-22T16:20:48.396809+02:00"}
51
+ {"id":"UI-48","title":"Use type-badge for dependency/dependent items","description":"Render the existing type badge component for each related issue item in the Dependencies and Dependents lists of the detail view, replacing the plain text type. Ensure accessibility and layout remain compact.","acceptance_criteria":"- Dependency and Dependent list items include a `.type-badge` next to the ID.\n- Badge uses the related issue's `issue_type` and falls back to neutral on missing/unknown.\n- Existing add/remove interactions and navigation remain unchanged.\n- Unit tests assert presence of badges in both lists.","notes":"Switching dependency and dependent list type rendering to use the shared TypeBadge component; adding a test to assert presence of badges.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-22T16:30:55.439377+02:00","updated_at":"2025-10-23T10:35:11.646054+02:00","closed_at":"2025-10-22T16:32:03.41611+02:00","dependencies":[{"issue_id":"UI-48","depends_on_id":"UI-45","type":"discovered-from","created_at":"2025-10-22T16:31:02.050383+02:00","created_by":"max"}]}
52
+ {"id":"UI-49","title":"Dark mode toggle + form control styling","description":"Add a theme toggle switch in the app header (top-right) to switch between light and dark modes. Persist preference in localStorage and apply immediately. Enhance form controls (inputs, selects, textarea, buttons) to be readable and consistent in dark mode using CSS variables.","acceptance_criteria":"- Visible toggle in header; clicking toggles between light and dark.\n- Theme state persists across reloads and updates `data-theme` on `\u003chtml\u003e`.\n- Form controls remain readable with adequate contrast in both themes.\n- Minimal unit test verifies `data-theme` attribute changes and preference persistence.","notes":"Adding header switch, localStorage theme persistence, data-theme overrides, and form control CSS for dark mode.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T16:38:40.505332+02:00","updated_at":"2025-10-23T10:35:11.646269+02:00","closed_at":"2025-10-22T16:40:22.733398+02:00"}
53
+ {"id":"UI-5","title":"Bridge UI edits to bd commands","description":"Implement handlers that translate WS edit messages into `bd` CLI commands and return results.\n\nScope\n- Supported actions: change status; edit title/description/acceptance; create issue\n- Synchronous request/response over WS with typed results\n- Error reporting: include stderr/exit codes in structured form\n\nNotes\n- Commands should be executed in the current workspace root.\n- Consider a queue to serialize writes to avoid conflicts.","acceptance_criteria":"- Editing in the UI results in the expected `bd` command invocation and persisted changes in `.beads/issues.jsonl`.\n- Errors from `bd` surface back to the client in a structured, user-friendly way.\n- Tests simulate failure (e.g., invalid issue id) and verify correct error propagation.","notes":"Implemented WS handlers bridging edits to `bd` commands, including create and acceptance editing.\n\nChanges\n- server/ws.js: add `create-issue` handler; extend `edit-text` to support `acceptance` field; reuse existing validation + error mapping.\n- server/ws.mutations.test.js: added tests for acceptance editing and create-issue ack; all tests pass.\n\nBehavior\n- Status/title/description/acceptance edits call the corresponding `bd update` flags and return the updated issue via `bd show --json`.\n- Create issue runs `bd create ...` and replies with `{ created: true }`; the watcher triggers UI refresh.\n- Errors propagate as structured `bd_error` replies.\n\nNotes\n- Persistence target is the beads SQLite DB (current implementation), not JSONL. Watcher and tests updated in previous tasks.\n- Consider a write queue if we observe conflicts under rapid successive edits.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:14:32.408003+02:00","updated_at":"2025-10-23T10:35:11.64645+02:00","closed_at":"2025-10-22T15:29:15.570122+02:00","dependencies":[{"issue_id":"UI-5","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:14.803208+02:00","created_by":"max"},{"issue_id":"UI-5","depends_on_id":"UI-3","type":"blocks","created_at":"2025-10-22T09:17:53.10505+02:00","created_by":"max"},{"issue_id":"UI-5","depends_on_id":"UI-2","type":"blocks","created_at":"2025-10-22T09:18:00.173303+02:00","created_by":"max"}]}
54
+ {"id":"UI-50","title":"Reload does not restore/apply list filters on initial load","description":"On full reload, the issues list ignores previously persisted filters (status/search). The UI renders with defaults (status=all, empty search), and only after a user action that touches store state (e.g., clicking any issue) are the persisted filters restored and applied. This leads to incorrect initial results and UX inconsistency.","acceptance_criteria":"- Given filters persisted in localStorage or store initial state, when the app loads, then the list view initializes its internal state from the store and applies these filters before the first data load.\n- The status select and search input reflect the persisted values immediately after load.\n- No user interaction (clicking an issue) is required for filters to be applied.\n- Includes a unit test that fails before the fix and passes after, asserting initial application of persisted filters.","notes":"Fix implemented by initializing list view filters from the store on first render and reflecting them in controls. Added unit test `applies persisted filters from store on initial load` in app/views/list.test.js. Ran typecheck, lint, and tests: all passing.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-22T16:53:08.077287+02:00","updated_at":"2025-10-23T10:35:11.646643+02:00","closed_at":"2025-10-22T16:53:32.296427+02:00","dependencies":[{"issue_id":"UI-50","depends_on_id":"UI-42","type":"related","created_at":"2025-10-22T16:53:28.013921+02:00","created_by":"max"}]}
55
+ {"id":"UI-51","title":"Redesign UI to match provided mock","description":"Improve the beads‑ui design to match the screenshot at /Users/max/Desktop/Bildschirmfoto 2025-10-22 um 17.29.20.png.\nScope:\n- Apply new layout, spacing, and typography\n- Update color palette and component styles (lists, headers, filters, details)\n- Ensure responsive behavior and accessible contrast\n- No functional changes to data flows\nVerification:\n- Run the app locally and verify visually using MCP Chrome DevTools against the mock\nDocs/Tests:\n- Update README with design tokens\n- Keep existing tests passing; no new tests required unless CSS utilities added","notes":"Implemented the requested layout changes:\n- Panel headers: left header now shows filters; right header shows selected issue id in monospace.\n- Issues list: 2-row layout with title (left) + id (right, monospace) on row 1; status+priority (left) + type badge (right) on row 2. CSS utilities added.\n- Details: two-column layout with Properties card; moved Status \u0026 Priority selects into Properties; moved Dependencies and Dependents into side panel with matching heading style.\n- Kept behavior intact; no new non-functional buttons added. All tests pass (74/74). Verified visually in MCP Chrome DevTools at http://127.0.0.1:5173.\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-22T17:31:15.705894+02:00","updated_at":"2025-10-23T10:35:11.646852+02:00","closed_at":"2025-10-22T18:19:53.416722+02:00"}
56
+ {"id":"UI-52","title":"Editing issue description doesn’t persist; UI clears on save","description":"Problem: Updating an issue’s description in the UI appears to save, but the editor clears and a reload shows the old description.\nHypothesis: The save payload omits `description`, uses a wrong field name, or the local state resets to empty after mutation success. Could also be a mismatch between `description` vs `notes` on the backend.\nPlan: Trace edit component → mutation call → store update. Fix payload/state handling and add a focused test.\nAcceptance:\n- Changing description updates server-side value.\n- Editor keeps new text post-save.\n- Reload shows updated description.\n- No regressions in title/labels save flows.","notes":"Root cause: WebSocket server mapped `edit-text` to non-existent bd flags (`--description`, `--acceptance`). bd update actually expects `--notes` and `--acceptance-criteria`. This caused saves to error and UI to exit edit mode without persisting.\nFix: Updated server/ws.js to map description → `--notes` and acceptance → `--acceptance-criteria`. Added tests asserting correct flags in server/ws.mutations.test.js. Updated docs in app/protocol.md and docs/architecture.md. Ran typecheck, tests, lint, and prettier — all green.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-22T20:14:51.198731+02:00","updated_at":"2025-10-23T10:35:11.647048+02:00","closed_at":"2025-10-22T20:20:02.784313+02:00"}
57
+ {"id":"UI-53","title":"Epic: Migrate UI to GitHub Projects-like navigation","description":"Goal: Introduce a top navigation and three primary views (Issues, Epics, Board) inspired by GitHub Projects to improve overview and flow.\n\nDesign references (local on your machine):\n- Issues list: /Users/max/Desktop/Bildschirmfoto 2025-10-23 um 08.16.07.png\n- Issue detail: /Users/max/Desktop/Bildschirmfoto 2025-10-23 um 08.20.26.png\n- Epics table: /Users/max/Desktop/example-table.webp\n- Board: /Users/max/Desktop/example-board.webp\n\nData sources:\n- Epics view: `bd epic status --json` (see `epic-status-example.json`)\n- Board Ready: `bd ready --json` (see `bd-ready-example.json`)\n- Board In progress: `bd list -s in_progress` (see `bd-list-example.json`)\n- Board Closed: `bd list -s closed -l 10`\n\nKey behaviors:\n- Top navigation with tabs: Issues, Epics, Board\n- Issues: list view; clicking an issue opens the new issue detail screen\n- Epics: grouped by epic; expanding shows non-closed issues; inline editing of type, title, priority, status, assignee; row click opens issue detail screen\n- Board: three columns (Ready, In progress, Closed) with specified data sources and sorting\n- All views open the same issue detail screen on selection\n\nNon-goals (phase 1):\n- Cross-column drag \u0026 drop\n- Linked pull requests\n\nTech notes:\n- Use existing MCP `beads`/`bd` integration to fetch JSON, with a thin data layer.\n- Keep components framework-agnostic where practical and respect repo coding standards (ESM, JSDoc typing, tests).","acceptance_criteria":"- Top navigation renders three tabs: Issues, Epics, Board\n- Issues list shows issues; clicking opens new issue detail screen\n- Epics view renders grouped epics from `bd epic status --json`; expanding shows non-closed issues\n- Epics view supports inline editing of type, title, priority, status, assignee and persists via bd\n- Board view shows three columns: Ready, In progress, Closed\n- Ready column uses `bd ready --json` sorted by priority then updated_at\n- In progress column uses `bd list -s in_progress` sorted by updated_at\n- Closed column uses `bd list -s closed -l 10` sorted by updated_at\n- Clicking any row/card opens the new issue detail screen\n- Pre‑handoff checks pass: `npm run typecheck`, `npm test`, `npm run lint`, `npm run format`","notes":"Opened the app in MCP chrome-devtools and verified the new top navigation. Adjusted sticky offset so the nav stays directly under the sticky header.\n\nChanges:\n- app/styles.css: make `.top-nav` sticky at `top: 53px` so it doesn’t slide under the header; keep active tab styling and route layout from earlier patch.\n\nNext:\n- Cross-check padding, tab border accents, and panel proportions against the provided screenshots; tweak spacing variables if needed.\n- If you see any remaining visual deviations (e.g., tab hover/border weights, selected background), point them out and I’ll fine-tune quickly.\n","status":"closed","priority":1,"issue_type":"epic","created_at":"2025-10-23T08:36:34.458336+02:00","updated_at":"2025-10-23T16:12:32.241594+02:00","closed_at":"2025-10-23T16:12:32.241594+02:00"}
58
+ {"id":"UI-54","title":"Top navigation and routing: Issues, Epics, Board","description":"Add a persistent top navigation with three tabs and route skeletons for each view.\n\nTabs:\n- Issues\n- Epics\n- Board\n\nRouting:\n- `/#/issues`\n- `/#/epics`\n- `/#/board`\n\nFollow repo coding standards (ESM, JSDoc, control-flow blocks).","design":"Reference the provided designs for visual spacing and typography.\n- Issues: /Users/max/Desktop/Bildschirmfoto 2025-10-23 um 08.16.07.png\n- Epics: /Users/max/Desktop/example-table.webp\n- Board: /Users/max/Desktop/example-board.webp","acceptance_criteria":"- A top nav renders with three tabs\n- Each tab navigates to a distinct route without page reloads\n- Active tab is highlighted\n- Each route renders a placeholder shell component\n- Typecheck, lint, tests pass","notes":"Added top navigation and basic tab routing.\n- app/state.js: added `view` to AppState and store; persists last view.\n- app/router.js: parseView, gotoView; router updates store view + selected_id.\n- app/views/nav.js: new TopNav component with three tabs and active highlight.\n- app/main.js: renders nav and three route shells; Issues view uses existing list + detail; Epics/Board placeholders.\n- Tests: app/views/nav.test.js, app/router.test.js extended.\n- All checks pass: typecheck, tests, lint, format.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T08:36:55.570068+02:00","updated_at":"2025-10-23T10:35:11.647665+02:00","closed_at":"2025-10-23T09:09:57.664798+02:00","dependencies":[{"issue_id":"UI-54","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:18.302091+02:00","created_by":"max"}]}
59
+ {"id":"UI-55","title":"Data layer: bd JSON providers and update actions","description":"Introduce a small data layer that wraps `bd` commands and exposes typed functions returning JSON for consumption by UI components. Provide update actions to edit issues.\n\nRead providers:\n- `getEpicStatus()` → `bd epic status --json`\n- `getReady()` → `bd ready --json`\n- `getInProgress()` → `bd list -s in_progress --json`\n- `getClosed(limit=10)` → `bd list -s closed -l 10 --json`\n- `getIssue(id)` → `bd show \u003cid\u003e --json`\n\nWrite actions:\n- `updateIssue({ id, title, type, priority, status, assignee })` → `bd update`\n\nNotes:\n- Respect repo standards (ESM, JSDoc types, minimal runtime checks).\n- Include basic caching and an event-based refresh signal for edits.","design":"Use `epic-status-example.json`, `bd-ready-example.json`, and `bd-list-example.json` as fixtures for typing and tests.","acceptance_criteria":"- Functions above exist with JSDoc types\n- Unit tests stub bd responses using local example JSON\n- Errors surface with actionable messages\n- No network calls; uses MCP beads/CLI integration\n- Typecheck, lint, tests pass","notes":"Implementation landed in repo:\n- app/data/providers.js: createDataLayer with getEpicStatus/getReady/getInProgress/getClosed/getIssue/updateIssue; basic cache + invalidation on 'issues-changed'.\n- server/ws.js: new handlers 'epic-status', 'update-type', 'update-assignee'; list-issues accepts filters.limit and passes '-l'.\n- app/protocol.js: added new message types.\n- Tests: server/ws.handlers.test.js (epic-status, limit); server/ws.mutations.test.js (update-type, update-assignee); app/data/providers.test.js covering data wrappers and update dispatch.\n- All checks pass: `npm run typecheck`, `npm test`, `npm run lint`, `npm run format:check`.\n\nNotes:\n- updateIssue supports title/acceptance/status/priority/type/assignee. Edits return the updated issue.\n- No network calls; server integrates with bd CLI.\n\nNext:\n- Consumers (Issues/Epics/Board) can import createDataLayer and reuse transport from app/main.js WebSocket client.\n- If assignee/type flags differ in your bd CLI, adjust server mappings accordingly.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T08:37:04.368248+02:00","updated_at":"2025-10-23T10:35:11.647922+02:00","closed_at":"2025-10-23T09:03:44.708017+02:00","dependencies":[{"issue_id":"UI-55","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:23.828157+02:00","created_by":"max"}]}
60
+ {"id":"UI-56","title":"Issues view: list and detail navigation","description":"Implement the Issues view as a list table matching the provided screenshot. Clicking a row navigates to the new Issue Detail screen.\n\nData:\n- Use `bd list --json` or the data layer helpers as appropriate.\n\nBehavior:\n- Sort by updated_at (desc) by default; allow manual re-sort by priority and updated_at.\n- Row click opens Issue Detail.\n\nFollow standards (ESM, JSDoc, tests).","design":"Screenshot: /Users/max/Desktop/Bildschirmfoto 2025-10-23 um 08.16.07.png","acceptance_criteria":"- Issues table renders with id, title, type, priority, status, assignee, updated_at\n- Default sort by updated_at desc; user can re-sort by priority and updated_at\n- Clicking a row navigates to Issue Detail\n- Typecheck, lint, tests pass","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T08:37:13.480424+02:00","updated_at":"2025-10-23T13:03:22.371748+02:00","closed_at":"2025-10-23T13:03:22.371771+02:00","dependencies":[{"issue_id":"UI-56","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:27.92663+02:00","created_by":"max"},{"issue_id":"UI-56","depends_on_id":"UI-55","type":"blocks","created_at":"2025-10-23T08:39:04.489508+02:00","created_by":"max"},{"issue_id":"UI-56","depends_on_id":"UI-54","type":"blocks","created_at":"2025-10-23T08:39:23.227471+02:00","created_by":"max"}]}
61
+ {"id":"UI-57","title":"Issue Detail screen: new design and editing","description":"Build the Issue Detail screen per provided screenshot; shared destination for clicks from Issues/Epics/Board. Support editing fields where applicable.","design":"Screenshot: /Users/max/Desktop/Bildschirmfoto 2025-10-23 um 08.20.26.png","acceptance_criteria":"- Route renders Issue Detail for a given id\n- Shows id, title, type, priority, status, assignee, description, acceptance\n- Supports editing title, type, priority, status, assignee via data layer write actions\n- Navigates back preserves the calling view state (scroll/filters if feasible)\n- Typecheck, lint, tests pass","notes":"Implementing UI-57: Issue Detail screen new design and editing. Gaps found: Properties sidebar lacked Assignee editing; Type is not editable in bd (see UI-70/UI-71), so it should display as a badge only. Plan: add inline Assignee editor in Properties; keep Type as badge; verify navigation from Issues/Epics/Board points here and back preserves state; add unit test; run validations.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-23T08:37:22.394398+02:00","updated_at":"2025-10-23T14:56:44.094359+02:00","closed_at":"2025-10-23T14:56:44.094359+02:00","dependencies":[{"issue_id":"UI-57","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:33.35176+02:00","created_by":"max"},{"issue_id":"UI-57","depends_on_id":"UI-55","type":"blocks","created_at":"2025-10-23T08:39:17.078323+02:00","created_by":"max"},{"issue_id":"UI-57","depends_on_id":"UI-54","type":"blocks","created_at":"2025-10-23T08:39:35.510355+02:00","created_by":"max"}]}
62
+ {"id":"UI-58","title":"Epics view: grouped table with inline editing","description":"Implement the Epics view as a grouped table:\n- Each group represents one epic from `bd epic status --json`\n- Group expand shows non-closed issues\n- Inline editing for type, title, priority, status, assignee\n- Row click opens Issue Detail\n- No linked pull requests column\n\nSorting:\n- Within a group, sort by priority then updated_at\n\nUse data layer helpers.","design":"Table reference: /Users/max/Desktop/example-table.webp\nJSON fixture: epic-status-example.json","acceptance_criteria":"- Groups epics correctly from `bd epic status --json`\n- Expanding a group shows non-closed issues only\n- Inline edits persist via `bd update`\n- Row click opens Issue Detail\n- Typecheck, lint, tests pass","notes":"Started Epics view implementation.\n- app/views/epics.js: new Epics grouped table. Expands a group and loads dependents via getIssue(epic.id), then fetches each dependent via getIssue to filter non-closed children. Inline editing for title, type, priority, status, assignee via updateIssue. Row click navigates to detail.\n- app/main.js: wires Epics view into the new routing and loads when tab is active.\n- Tests: app/views/epics.test.js validates loading, expansion, and navigation.\n- All checks pass (typecheck, tests, lint, format).","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T08:37:34.389548+02:00","updated_at":"2025-10-23T10:35:11.648473+02:00","closed_at":"2025-10-23T09:23:29.60237+02:00","dependencies":[{"issue_id":"UI-58","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:38.167295+02:00","created_by":"max"},{"issue_id":"UI-58","depends_on_id":"UI-55","type":"blocks","created_at":"2025-10-23T08:39:08.372903+02:00","created_by":"max"},{"issue_id":"UI-58","depends_on_id":"UI-54","type":"blocks","created_at":"2025-10-23T08:39:27.488651+02:00","created_by":"max"}]}
63
+ {"id":"UI-59","title":"Board view: Ready / In progress / Closed columns","description":"Implement a three-column board.\n\nColumns:\n- Ready: `bd ready --json`, sort by priority asc, then updated_at desc\n- In progress: `bd list -s in_progress --json`, sort by updated_at desc\n- Closed: `bd list -s closed -l 10 --json`, sort by updated_at desc\n\nBehavior:\n- Clicking a card opens Issue Detail\n- No drag-and-drop in phase 1\n\nUse data layer helpers.","design":"Board reference: /Users/max/Desktop/example-board.webp\nJSON fixtures: `bd-ready-example.json`, `bd-list-example.json`","acceptance_criteria":"- Columns render with correct data and sorting\n- Card click opens Issue Detail\n- Typecheck, lint, tests pass","notes":"Started Board view implementation.\n- New component: app/views/board.js with three columns (Ready, In progress, Closed).\n- Sorting: Ready (priority asc, then updated_at desc), In progress/Closed (updated_at desc).\n- Click on card navigates to Issue Detail via router callback.\n- Wiring: app/main.js now mounts Board view and loads it on switching to the Board tab.\n- Tests: app/views/board.test.js covers sorting for all columns and navigation on click.\nNext: Run full checks and close if all pass.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T08:37:40.618906+02:00","updated_at":"2025-10-23T10:35:11.648669+02:00","closed_at":"2025-10-23T09:38:36.255268+02:00","dependencies":[{"issue_id":"UI-59","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:43.28937+02:00","created_by":"max"},{"issue_id":"UI-59","depends_on_id":"UI-55","type":"blocks","created_at":"2025-10-23T08:39:13.086992+02:00","created_by":"max"},{"issue_id":"UI-59","depends_on_id":"UI-54","type":"blocks","created_at":"2025-10-23T08:39:31.524908+02:00","created_by":"max"}]}
64
+ {"id":"UI-6","title":"SPA shell and routing","description":"Implement the SPA shell with client-side routing using ESM and JSDoc types (no heavy framework required).\n\nScope\n- App bootstrapping and environment config\n- Routes: issues list (`/`), issue detail (`/issue/:id`)\n- Minimal UI scaffolding; keyboard navigation baseline\n\nNotes\n- Keep dependencies light; favor small utilities or standard Web APIs.\n- Follow coding standards and unit testing conventions.","acceptance_criteria":"- `npm run dev` serves the SPA shell that can navigate between list and detail routes without reload.\n- Lint, type checks, and basic client tests pass.","notes":"SPA shell and routing implemented.\n- app/main.js boots the shell and wires list/detail panels.\n- app/router.js implements hash routing for list and issue detail; tests in app/router.test.js.\n- app/index.html and styles scaffold the UI; app/main.test.js exercises bootstrap.\n- `npm run dev` serves the SPA via the local server; navigation happens without reload.\n- Lint, typecheck, and tests pass.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:14:38.544355+02:00","updated_at":"2025-10-23T10:35:11.648867+02:00","closed_at":"2025-10-22T15:29:33.454232+02:00","dependencies":[{"issue_id":"UI-6","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:20.534873+02:00","created_by":"max"},{"issue_id":"UI-6","depends_on_id":"UI-2","type":"blocks","created_at":"2025-10-22T09:18:05.183685+02:00","created_by":"max"}]}
65
+ {"id":"UI-60","title":"Tests, typing, and docs for new UI","description":"Add focused unit tests for data layer + each new view. Ensure repo standards passes and document usage.\n\nScope:\n- Unit tests for data providers and sort logic\n- Minimal tests for navigation routing and row/card click behavior\n- Typecheck + ESLint + Prettier pass\n- Update README with new navigation, data sources, and development tips","design":"Use the example JSON files for fixtures in tests.","acceptance_criteria":"- `npm run typecheck` passes\n- `npm test` passes\n- `npm run lint` passes\n- `npm run format` produces no diff on second run\n- README updated with new sections","notes":"Started UI-60. Added tests and docs.\n- Tests: app/views/epics.test.js now includes sorting by priority then updated_at and guards against navigation when clicking inputs.\n- Code: app/views/epics.js includes updated_at in child mapping for correct secondary sort and updates IssueLite JSDoc.\n- Docs: README.md gains Navigation \u0026 Views section describing Issues/Epics/Board data sources, sorting, and persistence.\nNext: Re-run full checks and close if all pass.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T08:38:00.898685+02:00","updated_at":"2025-10-23T10:35:11.649066+02:00","closed_at":"2025-10-23T09:29:02.395725+02:00","dependencies":[{"issue_id":"UI-60","depends_on_id":"UI-53","type":"parent-child","created_at":"2025-10-23T08:38:48.616603+02:00","created_by":"max"},{"issue_id":"UI-60","depends_on_id":"UI-54","type":"blocks","created_at":"2025-10-23T08:39:39.506715+02:00","created_by":"max"},{"issue_id":"UI-60","depends_on_id":"UI-55","type":"blocks","created_at":"2025-10-23T08:39:44.118254+02:00","created_by":"max"},{"issue_id":"UI-60","depends_on_id":"UI-56","type":"blocks","created_at":"2025-10-23T08:39:48.529053+02:00","created_by":"max"},{"issue_id":"UI-60","depends_on_id":"UI-58","type":"blocks","created_at":"2025-10-23T08:39:52.203049+02:00","created_by":"max"},{"issue_id":"UI-60","depends_on_id":"UI-59","type":"blocks","created_at":"2025-10-23T08:39:58.046138+02:00","created_by":"max"}]}
66
+ {"id":"UI-61","title":"Navigating to issue shows 'Issue not found' on valid ID","description":"When navigating via list/epics or deep-linking (e.g., #/issue/wk-8), the detail pane sometimes renders \"Issue not found\" even though the issue exists. Root cause: case-sensitive ID comparison in detail view vs backend-normalized IDs (e.g., WK-8). Fix: compare IDs case-insensitively in detail view and keep existing error fallback for truly missing issues.","acceptance_criteria":"- Deep-linking to an existing issue with mixed-case ID loads detail.\n- Clicking an issue in list or epics always loads detail (no false 'not found').\n- All tests pass.\n- No regression on error handling.","notes":"Working on detail view: normalize ID comparison to be case-insensitive. Added guard in app/views/detail.js and expanded tests pass locally.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T10:14:15.843414+02:00","updated_at":"2025-10-23T10:35:11.649251+02:00","closed_at":"2025-10-23T10:14:41.547191+02:00"}
67
+ {"id":"UI-62","title":"Opening epic shows \"No open issues\" despite progress counts","description":"On the Epics screen, expanding an epic sometimes shows \"No open issues\" even when the header indicates progress like \"5/7 closed\". Root cause: the UI loaded `dependents` of the epic instead of its `dependencies`. Given `dep-add a b` expresses \"a depends on b\", an epic's children are its `dependencies`.","acceptance_criteria":"- Expanding an epic lists its non-closed child issues (from `dependencies`).\n- Progress count and visible rows line up (e.g., with 5/7 closed, 2 open rows render).\n- Inline edits still work and rows navigate to detail on click.\n- All tests pass.","notes":"Adjusted epics view to fetch children from `dependencies` rather than `dependents`; updated tests to reflect correct semantics. All tests pass locally.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T10:14:24.837178+02:00","updated_at":"2025-10-23T10:35:11.649461+02:00","closed_at":"2025-10-23T10:14:50.948847+02:00"}
68
+ {"id":"UI-63","title":"UI consistency: IDs, translations, and epic inline editing","description":"Bring UI consistency across the app:\n- Show issue IDs as `#${n}` everywhere (strip prefix, show numeric part).\n- Translate priority everywhere using `app/utils/priority.js` (dropdowns and text).\n- Translate status everywhere to Open / In progress / Closed (add helper, use in list and detail views).\n- Translate issue type everywhere to Bug / Feature / Epic / Task / Chore (add helper).\n- Epic inline editing should match issue details pattern: render as text with focus ring on hover; click to edit mode.","notes":"Child tasks UI-64…UI-68 created and implemented. Closing epic after validation.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-23T10:35:35.059532+02:00","updated_at":"2025-10-23T10:48:40.544629+02:00","closed_at":"2025-10-23T10:48:40.544629+02:00"}
69
+ {"id":"UI-64","title":"Show issue IDs as #${n} everywhere","description":"Display ID as `#${n}` where `n` is the numeric part of the beads issue ID with prefix stripped. Update all components (list, detail, headers, badges) to use a single helper.\nAcceptance:\n- All issue ID UI renders as `#123`.\n- No raw `UI-123` or similar prefixes visible.\n- Unit tests cover helper and a representative component.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T10:35:47.036808+02:00","updated_at":"2025-10-23T10:47:49.566129+02:00","closed_at":"2025-10-23T10:47:49.566129+02:00","dependencies":[{"issue_id":"UI-64","depends_on_id":"UI-63","type":"parent-child","created_at":"2025-10-23T10:36:19.799696+02:00","created_by":"max"}]}
70
+ {"id":"UI-65","title":"Translate priority using app/utils/priority.js","description":"Ensure priority is translated consistently everywhere using `app/utils/priority.js` for both text and dropdown labels.\nAcceptance:\n- All priority displays use helper.\n- Dropdown options use helper mapping.\n- Remove duplicated/inline translations.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T10:35:52.3385+02:00","updated_at":"2025-10-23T10:47:56.933154+02:00","closed_at":"2025-10-23T10:47:56.933154+02:00","dependencies":[{"issue_id":"UI-65","depends_on_id":"UI-63","type":"parent-child","created_at":"2025-10-23T10:36:25.105322+02:00","created_by":"max"}]}
71
+ {"id":"UI-66","title":"Translate status to Open/In progress/Closed","description":"Add a status translation helper and use it everywhere (list, detail view, dropdowns):\n- open -\u003e Open\n- in_progress -\u003e In progress\n- closed -\u003e Closed","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T10:35:59.009837+02:00","updated_at":"2025-10-23T10:48:04.814922+02:00","closed_at":"2025-10-23T10:48:04.814922+02:00","dependencies":[{"issue_id":"UI-66","depends_on_id":"UI-63","type":"parent-child","created_at":"2025-10-23T10:36:29.567296+02:00","created_by":"max"}]}
72
+ {"id":"UI-67","title":"Translate issue type to Bug/Feature/Epic/Task/Chore","description":"Add an issue type translation helper and apply everywhere:\n- bug -\u003e Bug\n- feature -\u003e Feature\n- epic -\u003e Epic\n- task -\u003e Task\n- chore -\u003e Chore","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T10:36:04.634608+02:00","updated_at":"2025-10-23T10:48:12.802393+02:00","closed_at":"2025-10-23T10:48:12.802393+02:00","dependencies":[{"issue_id":"UI-67","depends_on_id":"UI-63","type":"parent-child","created_at":"2025-10-23T10:36:33.493977+02:00","created_by":"max"}]}
73
+ {"id":"UI-68","title":"Epic inline editing matches issue details interaction","description":"Make epic inline editing follow issue details pattern:\n- Render value as plain text with a focus ring on hover.\n- Click switches to editing mode with input focused.\n- On blur or submit, save and render back to text.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T10:36:10.055566+02:00","updated_at":"2025-10-23T10:48:25.826396+02:00","closed_at":"2025-10-23T10:48:25.826396+02:00","dependencies":[{"issue_id":"UI-68","depends_on_id":"UI-63","type":"parent-child","created_at":"2025-10-23T10:36:38.114652+02:00","created_by":"max"}]}
74
+ {"id":"UI-69","title":"Epic screen polish: stable columns, inline title edit, badge styling for status/priority","description":"UI improvements on Epics view and shared components:\n- Keep table column widths stable while editing titles (table-layout fixed + colgroup)\n- Inline title editor matches text (no border, inherits font, focus ring only)\n- Render status and priority everywhere as badges; when editable, selects styled as badges with native arrow\n- Add emoji to select option labels for type/status/priority (badges keep text-only for tests)\n- Apply same priority badge on board cards; add status/priority badges to list view meta\n- CSS variables for light/dark palettes\nIncludes tests passing and linting.\n","notes":"Starting implementation: CSS badge system, epics table colgroup + fixed layout, inline title input style, and select styling. Will update list/board/detail views and run validations.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T11:29:58.127333+02:00","updated_at":"2025-10-23T11:30:08.901744+02:00","closed_at":"2025-10-23T11:30:08.901744+02:00"}
75
+ {"id":"UI-7","title":"Issues list view (browse and filter)","description":"Implement the issues list page with basic filtering and search.\n\nScope\n- Show id, title, status, priority, type, assignee\n- Client-side filters (status, type, priority) and text search\n- Subscribe to list updates via WS and update incrementally\n\nNotes\n- Keep render fast; prefer simple virtual list if needed.","acceptance_criteria":"- List loads from server via WS and updates in place on changes.\n- Filters and text search work locally without server roundtrips.\n- Keyboard navigation moves selection; Enter opens detail.","notes":"Issues list view implemented with filtering, search, and keyboard navigation.\n\n- app/views/list.js: renders id/title/status/priority, filters by status and search locally, and supports Arrow Up/Down selection with Enter to open detail. Selection syncs with the shared store.\n- Live updates: list reloads on `issues-changed` events (from app/main.js) with no full page reload.\n- Tests cover rendering, click navigation, and filters.\n\nNote: `type` and `assignee` columns can be added later if exposed by `bd` JSON output; current UI focuses on the essential fields.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-22T09:14:45.710607+02:00","updated_at":"2025-10-23T10:35:11.649635+02:00","closed_at":"2025-10-22T15:35:38.748214+02:00","dependencies":[{"issue_id":"UI-7","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:25.860801+02:00","created_by":"max"},{"issue_id":"UI-7","depends_on_id":"UI-6","type":"blocks","created_at":"2025-10-22T09:18:11.066066+02:00","created_by":"max"}]}
76
+ {"id":"UI-70","title":"Replace issue type select with plain text in UI","description":"`bd update` cannot change the issue `type`. Update the UI to render the issue type as non-editable plain text wherever it currently appears as an editable select control.","acceptance_criteria":"- Epics view shows issue type as plain text (badge), not a select.\n- No UI allows editing type via select in detail/epics views.\n- Test suite passes: `npm test`.\n- Typecheck, lint, and prettier pass: `npm run typecheck`, `npm run lint`, `npm run format:check`.","notes":"Changed `app/views/epics.js` to use `createTypeBadge(...)` for the Type column. Removed dropdown and related imports/helpers. No backend changes required.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T11:33:17.485875+02:00","updated_at":"2025-10-23T11:36:57.207612+02:00","closed_at":"2025-10-23T11:36:57.207612+02:00"}
77
+ {"id":"UI-71","title":"Remove update-type message wiring from UI and server","description":"Remove all references to the deprecated `update-type` message: protocol enums, client data layer, server handler, and tests. Keep create-issue `-t` support. Ensure full test/lint/typecheck pass.","acceptance_criteria":"- No code references `update-type` message.\n- `app/protocol.js` MessageType and MESSAGE_TYPES exclude `update-type`.\n- `createDataLayer.updateIssue` does not accept `type` and never calls `update-type`.\n- `server/ws.js` has no `update-type` handler.\n- Tests updated; `npm test` passes.\n- `npm run typecheck`, `npm run lint`, `npm run format:check` pass.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T11:50:01.110334+02:00","updated_at":"2025-10-23T11:50:19.510794+02:00","closed_at":"2025-10-23T11:50:19.510794+02:00","dependencies":[{"issue_id":"UI-71","depends_on_id":"UI-70","type":"discovered-from","created_at":"2025-10-23T11:50:07.441327+02:00","created_by":"max"}]}
78
+ {"id":"UI-72","title":"Board screen: UI fixes","description":"Modernize the Board and Closed views with UX, layout, and styling fixes. This epic groups tasks to add an \"Open\" column, remove redundant title, adjust card visuals and spacing, align issue ID within titles, and fix the Closed screen not rendering items.","acceptance_criteria":"All child tasks are complete and verified in the UI across light/dark themes. Board and Closed screens behave as specified; no regressions in filtering or drag-and-drop.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-23T12:59:16.964981+02:00","updated_at":"2025-10-23T14:05:19.752065+02:00","closed_at":"2025-10-23T14:05:19.752065+02:00"}
79
+ {"id":"UI-73","title":"App layout: navigation and style","description":"Unify the app header and navigation look-and-feel. This epic groups tasks to rename the title, reposition and restyle tabs, align the Issues screen search row background, and wrap the issues table with a rounded border with consistent margins.","acceptance_criteria":"All child tasks are complete and verified in the UI across light/dark themes. Header and tab layout matches spec; Issues table and search row align with epics/cards margins.","status":"closed","priority":2,"issue_type":"epic","created_at":"2025-10-23T12:59:25.211174+02:00","updated_at":"2025-10-23T14:16:00.176611+02:00","closed_at":"2025-10-23T14:16:00.176611+02:00"}
80
+ {"id":"UI-74","title":"Board: add leftmost \"Open\" column for non-Ready open issues","description":"Add a new Board column on the far left named \"Open\" that lists all open issues not already in the \"Ready\" column.","acceptance_criteria":"- A new \"Open\" column renders at the far left.\n- Contains all issues with status open that are not present in \"Ready\".\n- No duplicates across columns.\n- Respects global filters (assignee, labels, text).\n- Drag-and-drop continues to work for other columns.","notes":"Implemented Open column: added data.getOpen(), render Open leftmost in Board, excluded Ready IDs from Open, updated CSS to 4 columns, and adjusted board test to cover Open behavior. Running validations passed.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-23T12:59:40.566694+02:00","updated_at":"2025-10-23T13:25:39.218725+02:00","closed_at":"2025-10-23T13:25:39.218725+02:00","dependencies":[{"issue_id":"UI-74","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:00:46.721957+02:00","created_by":"max"}]}
81
+ {"id":"UI-75","title":"Board: remove redundant \"Board\" title","description":"Remove the page title heading \"Board\" from the Board screen since it duplicates the \"Board\" tab label.","acceptance_criteria":"- The \"Board\" heading no longer appears on the Board screen.\n- No layout jump or spacing regression after removal.\n- Screen readers still expose a sensible page landmark/heading structure.","notes":"Removed redundant visual heading from Board view; column headers now expose heading roles for screen readers. Verified no layout regressions and passing checks.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-23T12:59:45.371117+02:00","updated_at":"2025-10-23T13:39:36.045906+02:00","closed_at":"2025-10-23T13:39:36.045906+02:00","dependencies":[{"issue_id":"UI-75","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:00:50.842723+02:00","created_by":"max"}]}
82
+ {"id":"UI-76","title":"Board cards: match body background and add box-shadow","description":"Update board cards so their background color matches the page body background and add a subtle box-shadow for elevation.","acceptance_criteria":"- Card background color equals body background color in light and dark modes.\n- A single, subtle box-shadow is applied; no borders.\n- Contrast and readability meet AA for card content.\n- No change to card width or column layout.","notes":"Working on board card visuals: match body background, remove borders, add subtle elevation shadow. Changes in app/styles.css.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T12:59:51.645562+02:00","updated_at":"2025-10-23T14:05:06.492677+02:00","closed_at":"2025-10-23T14:05:06.492677+02:00","dependencies":[{"issue_id":"UI-76","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:00:55.930692+02:00","created_by":"max"}]}
83
+ {"id":"UI-77","title":"Board cards: increase internal padding and row gap","description":"Increase card internal padding and vertical spacing between card rows to improve readability and scannability.","acceptance_criteria":"- Card internal padding increased consistently on all sides.\n- Vertical gap between card rows increased consistently across columns.\n- No text truncation or overflow regressions.\n- Column counts/widths remain unchanged.","notes":"Working on board card spacing: increase internal padding and vertical gap between rows. Changes in app/styles.css.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-23T12:59:56.545104+02:00","updated_at":"2025-10-23T14:05:10.024414+02:00","closed_at":"2025-10-23T14:05:10.024414+02:00","dependencies":[{"issue_id":"UI-77","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:00:59.966127+02:00","created_by":"max"}]}
84
+ {"id":"UI-78","title":"Board cards: move issue ID into title row, right-aligned","description":"Render the issue ID in the same row as the card title, aligned to the right, to save vertical space.","acceptance_criteria":"- Card title row displays the issue ID on the far right.\n- ID remains a link to the issue detail.\n- No wrapping or overlap with long titles at common widths.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-23T13:00:02.175735+02:00","updated_at":"2025-10-23T13:34:44.213982+02:00","closed_at":"2025-10-23T13:34:44.21399+02:00","dependencies":[{"issue_id":"UI-78","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:01:05.250545+02:00","created_by":"max"}]}
85
+ {"id":"UI-79","title":"Closed screen: fix empty view (no issues shown)","description":"The Closed screen currently renders no issues. Fix the query/filters so that closed issues display correctly.","acceptance_criteria":"- Navigating to the Closed screen lists issues with status closed.\n- Respects existing filters, sorting, and pagination.\n- No performance regressions on large datasets.\n- Add a friendly empty-state only when no closed issues exist.","notes":"Adjusted bd list flags: use `--status` and `--limit`. Updated server/ws.js and tests. All validations passed. Thanks for the flag clarification.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T13:00:08.730668+02:00","updated_at":"2025-10-23T13:22:55.980383+02:00","closed_at":"2025-10-23T13:22:55.980383+02:00","dependencies":[{"issue_id":"UI-79","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:01:09.037139+02:00","created_by":"max"}]}
86
+ {"id":"UI-8","title":"Issue detail view (edit text and status)","description":"Implement the issue detail page supporting text editing and status changes.\n\nScope\n- Show and edit: title, description, acceptance\n- Change status via dropdown; reflect allowed states\n- Subscribe to issue updates; optimistic UI with rollback on error\n\nNotes\n- Use debounced input updates with explicit Save/Undo.\n- Respect Coding and Testing Standards.","acceptance_criteria":"- Editing fields triggers WS requests that result in persisted changes via `bd`.\n- Status changes apply and are visible immediately on list and detail pages.\n- Concurrent update from watcher applies non-destructively while editing with clear conflict messaging.","notes":"Issue detail view implemented with inline edits and status changes.\n\nUpdates\n- app/views/detail.js: supports title, description, and acceptance editing with Save/Cancel and keyboard shortcuts (Esc to cancel; Ctrl/Cmd+Enter to save for textareas). Status and priority controls update via WS with optimistic UI and rollback on error. Dependency add/remove controls included.\n- Server already bridges edits; watcher updates refresh list/detail on push.\n- Tests validate core edit flows; acceptance editing added to server and covered in ws tests.\n\nBehavior\n- Edits send `edit-text` and `update-status` messages; replies update UI immediately.\n- Concurrent `issues-changed` events trigger reloads; UI re-renders without losing local state except when a save occurs (baseline approach).\n\nValidation\n- `npm run dev` serves the SPA; navigation between list and detail works without reload.\n- Lint, typecheck, and tests pass.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:15:00.800014+02:00","updated_at":"2025-10-23T10:35:11.649822+02:00","closed_at":"2025-10-22T15:31:09.816053+02:00","dependencies":[{"issue_id":"UI-8","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:30.876933+02:00","created_by":"max"},{"issue_id":"UI-8","depends_on_id":"UI-6","type":"blocks","created_at":"2025-10-22T09:18:16.047653+02:00","created_by":"max"},{"issue_id":"UI-8","depends_on_id":"UI-5","type":"blocks","created_at":"2025-10-22T09:18:20.241426+02:00","created_by":"max"}]}
87
+ {"id":"UI-80","title":"App title: rename to \"Beads\"","description":"Rename the app title to just \"Beads\" (drop any \"UI\" suffix).","acceptance_criteria":"- Header title displays \"Beads\".\n- Document/page title reflects \"Beads\".\n- No other strings or branding are unintentionally changed.","notes":"Started implementing title rename across header and document title as per UI-73 epic.","status":"closed","priority":3,"issue_type":"task","created_at":"2025-10-23T13:00:13.856294+02:00","updated_at":"2025-10-23T14:15:16.962765+02:00","closed_at":"2025-10-23T14:15:16.962765+02:00","dependencies":[{"issue_id":"UI-80","depends_on_id":"UI-73","type":"parent-child","created_at":"2025-10-23T13:01:13.652219+02:00","created_by":"max"}]}
88
+ {"id":"UI-81","title":"Header tabs: move next to title; style selected tab with body background and matching bottom border","description":"Reposition header tabs next to the app title and style the selected tab using the body background color with a bottom border of the same color.","acceptance_criteria":"- Tabs sit inline next to the \"Beads\" title on desktop.\n- Selected tab background equals body background; bottom border equals body background.\n- Hover/focus states remain accessible.\n- Layout adapts reasonably on narrow widths.","notes":"Moved tabs next to the title by mounting nav inside header; updated nav markup (app/views/nav.js), main shell (app/main.js), and styles (app/styles.css). Styling for active tab uses body background and matching bottom border.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T13:00:19.381693+02:00","updated_at":"2025-10-23T14:15:28.424225+02:00","closed_at":"2025-10-23T14:15:28.424225+02:00","dependencies":[{"issue_id":"UI-81","depends_on_id":"UI-73","type":"parent-child","created_at":"2025-10-23T13:01:17.536579+02:00","created_by":"max"}]}
89
+ {"id":"UI-82","title":"Issues screen: search row uses body background","description":"Set the Issues screen search row (filters and inputs) to use the page body background color for visual consistency.","acceptance_criteria":"- Search row background equals body background color in light and dark modes.\n- No contrast regressions with inputs or labels.\n- Sticky/fixed behavior, if any, remains correct.","notes":"Updated Issues screen search row to use body background via CSS override (#list-panel .panel__header) in app/styles.css. Verified contrast in both themes.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T13:00:28.292738+02:00","updated_at":"2025-10-23T14:15:39.89006+02:00","closed_at":"2025-10-23T14:15:39.89006+02:00","dependencies":[{"issue_id":"UI-82","depends_on_id":"UI-73","type":"parent-child","created_at":"2025-10-23T13:01:21.937585+02:00","created_by":"max"}]}
90
+ {"id":"UI-83","title":"Issues table: rounded border and margins aligned with epics/cards","description":"Wrap the Issues table with a rounded border and apply margins consistent with epics/cards so all content aligns vertically.","acceptance_criteria":"- Issues table has a rounded border with consistent radius.\n- Table block margins align with epics/cards margins on all screens.\n- No layout overflow or horizontal scroll introduced.","notes":"Wrapped Issues table in a rounded container `.issues-block` with margins aligned to Epic cards; added styles in app/styles.css and adjusted rendering in app/views/list.js. Ensured no overflow or horizontal scroll introduced.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T13:00:33.744689+02:00","updated_at":"2025-10-23T14:15:47.672265+02:00","closed_at":"2025-10-23T14:15:47.672265+02:00","dependencies":[{"issue_id":"UI-83","depends_on_id":"UI-73","type":"parent-child","created_at":"2025-10-23T13:01:25.321789+02:00","created_by":"max"}]}
91
+ {"id":"UI-84","title":"Board: columns fill screen with sticky headers and per-column scrolling","description":"Make Board columns fill available vertical space and scroll within each column. Make each column header sticky at the top of its column.","acceptance_criteria":"- Board route fills vertical space under top bar\n- Column headers remain visible during vertical scroll in that column\n- Vertical scroll occurs per column, not the whole page\n- No overflow glitches on narrow screens (single-column breakpoint)\n- No regressions to other views","notes":"Implemented CSS-only fix: Board route fills viewport, each column scrolls vertically with sticky header. Updated styles in app/styles.css and kept markup intact.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T13:33:54.137405+02:00","updated_at":"2025-10-23T13:34:28.329924+02:00","closed_at":"2025-10-23T13:34:28.329924+02:00","dependencies":[{"issue_id":"UI-84","depends_on_id":"UI-72","type":"parent-child","created_at":"2025-10-23T13:34:01.808718+02:00","created_by":"max"}]}
92
+ {"id":"UI-85","title":"Board persists when switching views","description":"When navigating away from the Board (to Issues, Epics, or an Issue Detail), portions of the Board remain rendered on the right side of the app layout.","acceptance_criteria":"- Switching from Board to Issues/Epics hides and unmounts Board contents\n- Opening an Issue Detail from any view hides and unmounts Board\n- No Board DOM remains in `#board-root` after leaving the Board\n- Pre‑handoff checks pass: `npm run typecheck`, `npm test`, `npm run lint`, `npm run format`","notes":"Root cause identified: author CSS set `display` on route shells (e.g., `.route.board { display:flex }`), which can override the UA `[hidden]` rule.\n\nFixes:\n- app/styles.css: add `[hidden] { display:none !important; }` so hidden routes never render.\n- app/main.js: revert clearing the board on non-board views to avoid losing content when navigating back. Board loads on entry as before.\n- app/main.board-switch.test.js: update test to assert hide/show behavior without relying on clearing.\n\nResult:\n- Clicking a Board card navigates to detail and hides Board fully.\n- Switching board → issues → board shows the board contents again.\n\nValidation unchanged: all checks pass.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T13:52:06.54857+02:00","updated_at":"2025-10-23T14:00:04.552902+02:00","closed_at":"2025-10-23T13:52:22.322613+02:00","dependencies":[{"issue_id":"UI-85","depends_on_id":"UI-72","type":"related","created_at":"2025-10-23T13:52:13.093857+02:00","created_by":"max"}]}
93
+ {"id":"UI-86","title":"UI-85: Board height regression after header refactor","description":"After moving tabs into the header (UI-81), the Board route height relied on a fixed 53px header offset, causing the page to scroll instead of columns on some screens. Fix by computing `--header-h` from the actual header height on load/resize and using it in CSS for `.app-shell` height.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T14:36:44.113392+02:00","updated_at":"2025-10-23T14:36:49.16843+02:00","closed_at":"2025-10-23T14:36:49.16843+02:00"}
94
+ {"id":"UI-87","title":"Board: Ready column shows items already In Progress","description":"On the Board screen, the Ready column sometimes includes issues that are already in the In Progress column. This creates duplicates and misleads prioritization.\n\nRoot cause: The client view did not filter Ready items against In Progress IDs after loading both lists.\n\nFix: Filter Ready by excluding any item whose id appears in the In Progress list.\n\nFiles:\n- app/views/board.js — exclude In Progress IDs from Ready list in load()\n- app/views/board.test.js — add test: \"filters Ready to exclude items that are In Progress\"\n\nNotes: Sorting is unchanged. Open column continues to exclude items present in Ready.","acceptance_criteria":"- When the same issue appears in both the underlying Ready and In Progress data, the Ready column does not display it.\n- No duplicates across Board columns for that issue.\n- Tests, typecheck, lint, and format pass.","notes":"Implemented fix and tests.\n- app/views/board.js: filter Ready by excluding IDs present in In Progress.\n- app/views/board.test.js: add unit test confirming Ready excludes In Progress duplicate.\nValidation:\n- npm run typecheck: pass\n- npm test: 96 tests passing\n- npm run lint: pass\n- npm run format: no changes","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-23T14:50:11.624314+02:00","updated_at":"2025-10-23T14:50:18.652192+02:00","closed_at":"2025-10-23T14:50:18.652192+02:00"}
95
+ {"id":"UI-88","title":"Detail view: show editable \"Unassigned\" placeholder for Assignee","description":"When an issue has no `assignee`, the Properties sidebar displays nothing, leaving no visible affordance to edit. Show a muted placeholder that is still clickable to enter edit mode.","acceptance_criteria":"- When `assignee` is empty or missing, the Properties Assignee field shows a muted placeholder (e.g., \"Unassigned\").\n- The placeholder is keyboard/click editable (same behavior as when a value exists).\n- Clicking/Enter on the placeholder switches to input with Save/Cancel.\n- Tests, typecheck, lint, and format pass.","status":"closed","priority":2,"issue_type":"bug","created_at":"2025-10-23T15:03:49.818696+02:00","updated_at":"2025-10-23T15:05:12.22165+02:00","closed_at":"2025-10-23T15:05:12.22165+02:00","dependencies":[{"issue_id":"UI-88","depends_on_id":"UI-57","type":"discovered-from","created_at":"2025-10-23T15:03:53.342376+02:00","created_by":"max"}]}
96
+ {"id":"UI-89","title":"Allow clearing assignee (empty string) via WS","description":"The server WS handler for `update-assignee` rejected empty strings, preventing users from clearing the assignee, even though `bd update \u003cid\u003e --assignee \"\"` is supported.","acceptance_criteria":"- WS `update-assignee` accepts empty string and passes it through to `bd`.\n- Unit test covers empty-string case and asserts spawn args.\n- All validations pass.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-10-23T15:09:05.079513+02:00","updated_at":"2025-10-23T16:32:08.521679+02:00","closed_at":"2025-10-23T15:09:09.864229+02:00"}
97
+ {"id":"UI-9","title":"Real-time UI updates from watcher","description":"Wire the client subscription(s) to apply incoming watcher events efficiently to the current page.\n\nScope\n- Normalized client cache keyed by issue id\n- Fast update paths for list and detail routes\n- Visual cues for live updates\n\nNotes\n- Ensure no flicker and preserve scroll/selection.","acceptance_criteria":"- When `.beads/issues.jsonl` changes, the connected UI updates within 200ms for visible issues.\n- No full-page reloads are required; only affected rows/fields update.","notes":"Real-time updates are wired.\n- app/main.js subscribes to `issues-changed` events and reloads the list and active detail view without a full-page reload.\n- Server broadcasts on DB changes via `watchDb`; end-to-end propagation verified by unit tests.\n\nNotes\n- The current implementation re-renders the visible list rather than patching individual rows. Created follow-up UI-46 to consider lightweight change hints and partial DOM updates to minimize work and improve perceived latency.\n","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-22T09:15:06.299306+02:00","updated_at":"2025-10-23T10:35:11.650011+02:00","closed_at":"2025-10-22T15:31:58.149234+02:00","dependencies":[{"issue_id":"UI-9","depends_on_id":"UI-1","type":"parent-child","created_at":"2025-10-22T09:16:36.720644+02:00","created_by":"max"},{"issue_id":"UI-9","depends_on_id":"UI-6","type":"blocks","created_at":"2025-10-22T09:18:27.028524+02:00","created_by":"max"},{"issue_id":"UI-9","depends_on_id":"UI-4","type":"blocks","created_at":"2025-10-22T09:18:32.570119+02:00","created_by":"max"}]}
98
+ {"id":"UI-90","title":"Show acceptance and notes in issue details","description":"Render acceptance and notes in the Issue Detail view.\n\n- Normalize acceptance from `acceptance` or `acceptance_criteria`.\n- Display notes (read-only) using markdown.\n- Only render section headings when section has content.\n- Add tests for acceptance fallback, notes rendering, and heading gating.","acceptance_criteria":"- Acceptance section shows text from `acceptance` or `acceptance_criteria`.\n- Notes section renders markdown when present.\n- Headings for Acceptance and Notes appear only when the respective text is non-empty.\n- Unit tests pass and cover both presence and absence cases.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-23T15:15:36.461187+02:00","updated_at":"2025-10-23T15:15:44.263266+02:00","closed_at":"2025-10-23T15:15:44.263266+02:00"}
99
+ {"id":"UI-91","title":"Add 32px top margin to acceptance and notes sections","description":"Add spacing to details view sections.\n\n- Apply `margin-top: 32px` to `.acceptance` and `.notes` containers within `#detail-root`.\n- Keep consistent with detail layout spacing.\n- Validate with lint/tests/format.","status":"closed","priority":3,"issue_type":"chore","created_at":"2025-10-23T15:19:42.104513+02:00","updated_at":"2025-10-23T15:19:50.180006+02:00","closed_at":"2025-10-23T15:19:50.180006+02:00"}
100
+ {"id":"UI-92","title":"Detail view: remove header, show ID in title, fix editor font sizes, make title editor full-width","description":"Polish detail screen layout and editing.\n\n- Remove `.panel__header` from detail panel.\n- Show issue ID right-aligned on the title line.\n- Ensure editor font sizes match read mode for title/description/acceptance/notes.\n- Make title input fill available width.\n- Update tests accordingly.","acceptance_criteria":"- No `.panel__header` renders in the detail panel.\n- Title line shows the `#ID` at the right; title editor spans remaining width.\n- Editing title/description/acceptance does not change font size vs read mode.\n- All tests pass, linters and type checks clean.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-23T15:30:35.038912+02:00","updated_at":"2025-10-23T15:30:43.300457+02:00","closed_at":"2025-10-23T15:30:43.300457+02:00"}
101
+ {"id":"UI-93","title":"Replace type filter checkboxes with single select","description":"Switch List view type filtering from multi-select checkboxes to a single select.\n- Remove combination of types; allow filtering by a single type only.\n- Persist selected type as `filters.type: string` in store/localStorage (migrate from previous `filters.types: string[]`).\n- Update UI to a `\u003cselect\u003e` with options: All types, bug, feature, task, epic, chore.\n- Keep compatibility by reading old `types` array from localStorage and picking the first valid entry.\n- Update unit tests to assert select behavior and persisted initialization.\n","acceptance_criteria":"- Type select filters list items by a single type and works with Ready and search filters.\n- Select reflects initial state from store/localStorage on first render.\n- No checkboxes remain in the header.\n- All tests, lint, and typecheck pass.","status":"closed","priority":2,"issue_type":"task","created_at":"2025-10-23T16:59:55.34764+02:00","updated_at":"2025-10-23T17:00:07.432073+02:00","closed_at":"2025-10-23T17:00:07.432073+02:00","dependencies":[{"issue_id":"UI-93","depends_on_id":"UI-42","type":"discovered-from","created_at":"2025-10-23T17:00:02.31129+02:00","created_by":"max"}]}
102
+ {"id":"UI-94","title":"Epic: Add `bdui` binary for UI daemon control","description":"Introduce a new CLI binary `bdui` to control the beads-ui server as a background daemon and streamline local usage.\n\nGoals\n- Provide `bdui` with commands: `start`, `stop`, `restart`.\n- Spawn the UI server as a detached daemon (background process) with PID management.\n- On successful `start`, auto-open the app in the OS default browser.\n- Cross-platform support (macOS, Linux, Windows)\n- Ship as a Node ESM binary, adhering to repo coding standards (JSDoc, ESM, lint/type/test).\n- Update docs and add tests.\n\nNotes\n- Current server entry: `server/index.js` with Express + WS.\n- Package currently `private`; for dev, support `npm link` to expose `bdui` locally.\n- Prefer a PID file under a runtime dir (e.g. XDG runtime or OS tmp) to avoid repo writes; include an override via env or flag for debugging.\n","acceptance_criteria":"- Running `bdui --help` prints usage and lists `start|stop|restart`.\n- `bdui start` ensures exactly one detached server instance, writes PID file, and prints the URL.\n- `bdui start` opens the default browser to the server URL unless disabled with `--no-open` or `BDUI_NO_OPEN=1`.\n- `bdui stop` terminates the daemon gracefully (SIGTERM) and removes the PID file.\n- `bdui restart` behaves as `stop` then `start`.\n- Exit codes: success=0; not-running on stop=2; invalid command=1.\n- Works on macOS and Linux; Windows behavior documented and covered where feasible.\n- CI passes: `npm run all` stays green.","notes":"Docs updated: README.md and docs/quickstart.md now cover `bdui` usage, flags (`--no-open`), env (`BDUI_RUNTIME_DIR`, `BDUI_NO_OPEN`, `PORT`), and Windows notes. Tests added in UI-99 validate CLI parsing and daemon management. `npm run all` passes locally.","status":"closed","priority":1,"issue_type":"epic","assignee":"assistant","created_at":"2025-10-23T17:34:17.648604+02:00","updated_at":"2025-10-23T19:47:46.04278+02:00","closed_at":"2025-10-23T19:47:46.04278+02:00"}
103
+ {"id":"UI-95","title":"bdui: CLI command and usage scaffold","description":"Create the `bdui` CLI entry with ESM-only implementation and a clean command interface for `start|stop|restart`.\n\nScope\n- Implement argument parsing and help/usage.\n- Wire commands to stub handlers that will call daemon logic.\n- Respect coding standards (JSDoc, snake_case vars, camelCase funcs).\n- Structure: `bin/bdui.js` (thin entry) + `server/cli/*.js` modules.\n","acceptance_criteria":"- `bdui --help` prints usage and exits 0.\n- `bdui start|stop|restart` are recognized; unknown commands print usage and exit 1.\n- No side effects beyond calling stub handlers (until daemon feature lands).\n- Lint, typecheck, and unit tests pass for this module.","notes":"Implemented CLI scaffold for `bdui` per scope.\n\nChanges\n- Added `bin/bdui.js` thin entry that awaits `main()` and sets `process.exitCode`.\n- Added `server/cli/index.js` with `parseArgs()` and `main()`.\n- Added `server/cli/usage.js` for help/usage printing.\n- Added `server/cli/commands.js` with stub handlers for `start|stop|restart` (no side effects).\n- Added tests `server/cli/cli.test.js` covering parse/help/dispatch and exit codes.\n- Updated ESLint config to include Node globals for `bin/**/*.js` only.\n\nValidation\n- Lint: passes (`npm run lint`).\n- Tests: pass (`npm test`).\n- Typecheck: repo run currently reports pre-existing errors in `app/main.live-updates.test.js`. New task filed: UI-101 (discovered-from:UI-95).\n\nUsage (until UI-98 wires npm bin):\n- `node bin/bdui.js --help` prints usage and exits 0.\n- `node bin/bdui.js start|stop|restart` return 0; unknown commands exit 1.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T17:34:29.013936+02:00","updated_at":"2025-10-23T18:54:43.475126+02:00","closed_at":"2025-10-23T18:54:43.475126+02:00","dependencies":[{"issue_id":"UI-95","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:34.101293+02:00","created_by":"max"}]}
104
+ {"id":"UI-96","title":"bdui: Daemonize server with PID management","description":"Implement background daemon management for the beads-ui server.\n\nScope\n- Start: spawn `node server/index.js` as a detached child; redirect stdio to a log file; unref.\n- PID file: write child PID to a runtime directory (prefer `$XDG_RUNTIME_DIR/beads-ui` or `os.tmpdir()/beads-ui`), ensure directory exists, and set safe permissions.\n- Stop: read PID file, send SIGTERM, wait up to N seconds for clean exit, then SIGKILL as fallback; remove PID file.\n- Restart: stop (ignore not-running) then start.\n- Idempotency: `start` returns 0 if already running and prints the URL; guard against stale PID files.\n- Port/host: respect `server/config.js` defaults and env overrides.\n","acceptance_criteria":"- `bdui start` leaves no child attached to the invoking terminal and returns 0.\n- Log file written under the runtime dir and appended across runs.\n- `bdui stop` terminates the daemon and removes the PID file; returns code 2 if not running.\n- `bdui restart` performs stop then start and returns 0 on success.\n- Stale PID file detection works (no crash), replacing the PID file when necessary.\n- Works on macOS and Linux in local testing.","notes":"Claiming UI-96. Implementing `bdui` CLI daemon management: start/stop/restart with PID + logs and idempotency. Will integrate as ESM binary per coding standards and respect server/config.js host/port.","status":"closed","priority":1,"issue_type":"feature","created_at":"2025-10-23T17:34:40.612048+02:00","updated_at":"2025-10-23T19:22:38.440979+02:00","closed_at":"2025-10-23T19:22:38.440979+02:00","dependencies":[{"issue_id":"UI-96","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:37.146463+02:00","created_by":"max"}]}
105
+ {"id":"UI-97","title":"bdui: Auto-open default browser on start","description":"On successful `bdui start`, open the app URL in the system default browser.\n\nScope\n- Compute URL from `server/config.js` host/port.\n- Implement cross-platform open: macOS `open`, Linux `xdg-open`, Windows `start`.\n- Provide `--no-open` flag and `BDUI_NO_OPEN=1` env var to disable.\n- Retry once if the port is not ready yet (wait for health/HTTP 200 or a brief delay).\n","acceptance_criteria":"- `bdui start` opens the browser exactly once when launching a new daemon.\n- `--no-open` and `BDUI_NO_OPEN=1` prevent opening.\n- Opening works on macOS and Linux.\n- Graceful behavior when the server fails to start (prints error, exits non-zero, does not loop).","notes":"Implementing auto-open on `bdui start` with `--no-open` and `BDUI_NO_OPEN=1` support. Adding cross-platform open mapping and a brief readiness wait.","status":"closed","priority":2,"issue_type":"feature","created_at":"2025-10-23T17:34:50.783125+02:00","updated_at":"2025-10-23T19:34:58.867965+02:00","closed_at":"2025-10-23T19:34:58.867965+02:00","dependencies":[{"issue_id":"UI-97","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:43.462679+02:00","created_by":"max"},{"issue_id":"UI-97","depends_on_id":"UI-95","type":"blocks","created_at":"2025-10-23T17:36:10.555738+02:00","created_by":"max"},{"issue_id":"UI-97","depends_on_id":"UI-96","type":"blocks","created_at":"2025-10-23T17:36:15.874339+02:00","created_by":"max"}]}
106
+ {"id":"UI-98","title":"bdui: Package binary and local linking","description":"Expose `bdui` as an npm binary for local development and future distribution.\n\nScope\n- Add `bin` field in `package.json` mapping `bdui` -\u003e `bin/bdui.js`.\n- Ensure Node `\u003e=22` engine remains enforced and binary has proper shebang.\n- Document `npm link` workflow for developers.\n- Keep package `private` for now; evaluate publish later.\n","acceptance_criteria":"- `npm link` from repo root makes `bdui` available on PATH.\n- Invoking `bdui --help` works after linking.\n- CI passes: lint/type/tests including new files.","notes":"Wiring npm binary and docs.\n- Added package.json `bin` mapping: { \"bdui\": \"bin/bdui.js\" }\n- Ensured shebang present (already) and set local exec bit on `bin/bdui.js`.\n- Added README/docs quickstart section for `npm link` + `bdui --help`.\n- Ran `npm run all`: lint/type/tests/format all pass.\n","status":"closed","priority":1,"issue_type":"task","created_at":"2025-10-23T17:35:03.261329+02:00","updated_at":"2025-10-23T19:16:28.94109+02:00","closed_at":"2025-10-23T19:16:28.94109+02:00","dependencies":[{"issue_id":"UI-98","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:48.620881+02:00","created_by":"max"},{"issue_id":"UI-98","depends_on_id":"UI-95","type":"blocks","created_at":"2025-10-23T17:36:18.737737+02:00","created_by":"max"}]}
107
+ {"id":"UI-99","title":"bdui: Add tests for start|stop|restart and PID handling","description":"Add focused tests around the `bdui` CLI and daemon manager using Vitest.\n\nScope\n- Unit tests for CLI parsing and command dispatch.\n- Integration-style tests for start/stop/restart using a temporary port and fake runtime dir; mock browser open.\n- Verify exit codes and messages.\n- Ensure tests follow repo standards (no \"should\" in names, setup→exec→assert).\n","acceptance_criteria":"- `npm test` includes new CLI/daemon tests and passes locally.\n- Tests verify exit codes, idempotent start, and stop when not running.\n- Browser open is mocked and verified when enabled and disabled.","notes":"Starting implementation: adding Vitest unit tests for command handlers and integration tests that start the real server with a temp runtime dir and mocked browser open. Will verify exit codes, idempotent start, and stop-not-running behavior.","status":"closed","priority":1,"issue_type":"task","assignee":"assistant","created_at":"2025-10-23T17:35:11.985846+02:00","updated_at":"2025-10-23T19:44:37.049799+02:00","closed_at":"2025-10-23T19:44:37.049799+02:00","labels":["foo"],"dependencies":[{"issue_id":"UI-99","depends_on_id":"UI-94","type":"parent-child","created_at":"2025-10-23T17:35:51.849617+02:00","created_by":"max"},{"issue_id":"UI-99","depends_on_id":"UI-95","type":"blocks","created_at":"2025-10-23T17:36:23.667257+02:00","created_by":"max"},{"issue_id":"UI-99","depends_on_id":"UI-96","type":"blocks","created_at":"2025-10-23T17:36:26.673535+02:00","created_by":"max"}]}
package/.editorconfig ADDED
@@ -0,0 +1,10 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ indent_style = space
7
+ indent_size = 2
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
package/.eslintrc.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "root": true,
3
+ "env": {
4
+ "es2023": true,
5
+ "node": true,
6
+ "browser": true
7
+ },
8
+ "parserOptions": {
9
+ "ecmaVersion": "latest",
10
+ "sourceType": "module"
11
+ },
12
+ "extends": ["eslint:recommended"],
13
+ "plugins": ["jsdoc", "import", "n", "promise"],
14
+ "rules": {
15
+ "no-unused-vars": [
16
+ "error",
17
+ { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }
18
+ ],
19
+ "no-console": "off",
20
+ "eqeqeq": ["error", "always"],
21
+ "jsdoc/check-alignment": "warn",
22
+ "jsdoc/check-param-names": "warn",
23
+ "jsdoc/require-param": "warn",
24
+ "jsdoc/require-returns": "off"
25
+ },
26
+ "overrides": [
27
+ {
28
+ "files": ["test/**/*.js"],
29
+ "globals": {
30
+ "describe": "readonly",
31
+ "test": "readonly",
32
+ "expect": "readonly"
33
+ }
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,38 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ node-version: ['22.x', '24.x']
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ - name: Use Node.js ${{ matrix.node-version }}
22
+ uses: actions/setup-node@v4
23
+ with:
24
+ node-version: ${{ matrix.node-version }}
25
+ cache: 'npm'
26
+ - name: Install
27
+ run: npm ci
28
+ - name: Lint
29
+ if: matrix.node-version == '24.x'
30
+ run: npm run lint
31
+ - name: Types
32
+ if: matrix.node-version == '24.x'
33
+ run: npm run typecheck
34
+ - name: Prettier
35
+ if: matrix.node-version == '24.x'
36
+ run: npm run format:check
37
+ - name: Test
38
+ run: npm test