kandown 0.24.0 → 0.25.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.25.1 — 2026-07-20 — "Stale Daemon Refresh"
4
+
5
+ - **Fixed**: **Deep-link refreshes after existing daemon sessions** — Kandown now detects when a project daemon was started by an older CLI version and restarts it when the current CLI is newer. This matters because URL refresh handling for paths like `/058?p=suzu` lives in the daemon process itself; refreshing `kandown.html` alone cannot teach an already-running old daemon to serve task deep-link routes.
6
+ - **Fixed**: **Direct task URLs no longer require manual daemon restarts after updates** — running `kandown` or `kandown daemon start` now upgrades stale daemon processes automatically, so newly published routing behavior becomes active for existing projects without users needing to hunt for old PIDs.
7
+ - **Changed**: **Daemon reconnect behavior** — reconnecting to a same-project daemon still reuses compatible current/newer daemons, but older or unknown-version daemons are stopped and relaunched with the current CLI before returning the daemon URL.
8
+
9
+ ## 0.25.0 — 2026-07-20 — "Task Deep Links"
10
+
11
+ - **Added**: **Shareable task deep links** — opening a task drawer now updates the browser URL to a copy-pasteable route such as `/210?p=kandown`, where numeric task segments are normalized to Kandown task ids like `t210`. This makes it possible to send a direct link to a specific task instead of asking someone to find it manually on the board.
12
+ - **Added**: **Direct URL hydration for task drawers** — pasted links are parsed on web app startup and after browser navigation. Kandown now accepts the canonical `/210?p=kandown` format plus tolerant alternatives such as `/t210?p=kandown`, `?task=210`, and `?p=kandown/210`, then opens the matching drawer once the project is loaded.
13
+ - **Added**: **Browser history support for task navigation** — drawer open and close actions now synchronize with `pushState`/`replaceState`, and Kandown listens for `popstate` so browser Back and Forward switch between board-only and task-focused URLs instead of leaving stale drawer state behind.
14
+ - **Added**: **Copy URL action in the task drawer** — the opened task header now includes a lightweight Copy URL control that writes the absolute task link to the clipboard, with a toast fallback that displays the URL if clipboard access is denied.
15
+ - **Fixed**: **Daemon routing for deep links** — the local web daemon now serves the single-page app for safe one-segment task paths like `/210`, preventing direct task URLs from returning `404 Not found` before React has a chance to hydrate and open the drawer.
16
+ - **Changed**: **Project URL handling** — board/project URLs now go through shared URL helpers so project-only navigation keeps `/?p=<project>` while task navigation cleanly adds or removes the task path segment.
17
+ - **Changed**: **Board housekeeping** — completed Kandown task files were archived or removed from the active task set, new backlog tasks were added for upcoming archive/subtask/opened-task redesign work, and local board config/runtime ignore files were updated to match the current project workflow.
18
+
3
19
  ## 0.24.0 — 2026-07-20 — "Work Output Configurator"
4
20
 
5
21
  - **Added**: **`kandown work` Output Configurator** — added a new Settings panel under Agent configuration that lets each project control the markdown emitted by `kandown work`. Users can enable or disable the base rules, project instructions, and live board digest blocks without editing generated files by hand.
package/bin/kandown.js CHANGED
@@ -1987,7 +1987,21 @@ function releaseDaemonSpawnLock(lockPath) {
1987
1987
 
1988
1988
  async function startDaemon(kandownDir, preferredPort) {
1989
1989
  const current = await getDaemonStatus(kandownDir);
1990
- if (current.running) return current;
1990
+ if (current.running) {
1991
+ const currentVersion = getCurrentVersion();
1992
+ const daemonVersion = current.metadata?.version || null;
1993
+ // 📖 Deep-link routes and other daemon-owned behavior live in the long-running
1994
+ // daemon process, not in kandown.html. If the CLI updated while a daemon was
1995
+ // already running, reconnecting to the old process keeps old routing alive
1996
+ // (e.g. refreshing `/058?p=suzu` returned 404). Restart only when the local
1997
+ // CLI is newer; newer/dev daemons are left untouched.
1998
+ if (!daemonVersion || semverGt(currentVersion, daemonVersion) > 0) {
1999
+ warn(`Restarting daemon v${daemonVersion || 'unknown'} → v${currentVersion}...`);
2000
+ await stopDaemon(kandownDir);
2001
+ } else {
2002
+ return current;
2003
+ }
2004
+ }
1991
2005
 
1992
2006
  const lock = acquireDaemonSpawnLock(kandownDir);
1993
2007
  if (!lock) {
@@ -2726,6 +2740,15 @@ function serveStaticAsset(req, res, pathname) {
2726
2740
  return false;
2727
2741
  }
2728
2742
 
2743
+ function isTaskDeepLinkPath(pathname) {
2744
+ try {
2745
+ const cleaned = decodeURIComponent(pathname).replace(/^\/+|\/+$/g, '');
2746
+ return !!cleaned && !cleaned.includes('/') && !cleaned.includes('.') && /^[A-Za-z0-9_-]+$/.test(cleaned);
2747
+ } catch {
2748
+ return false;
2749
+ }
2750
+ }
2751
+
2729
2752
  function createServeServer(kandownDir) {
2730
2753
  try {
2731
2754
  const tasksDir = getTasksDir(kandownDir);
@@ -2750,6 +2773,7 @@ function createServeServer(kandownDir) {
2750
2773
  return handleApi(req, res, requestUrl, kandownDir);
2751
2774
  }
2752
2775
  if (serveStaticAsset(req, res, requestUrl.pathname)) return;
2776
+ if (req.method === 'GET' && isTaskDeepLinkPath(requestUrl.pathname)) return serveApp(res, kandownDir);
2753
2777
  return writeText(res, 404, 'Not found');
2754
2778
  });
2755
2779
  }