kandown 0.26.0 → 0.27.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,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.27.1 — 2026-07-20 — "Auto-Updater & Daemon Process Upgrade"
4
+
5
+ - **Fixed**: **Environment inheritance during background auto-update** — cleaned inherited `npm_config_*` and `npm_*` environment variables when spawning `npm install -g kandown` in `checkForUpdate()`. Previously, if Kandown was run via `npx` or `npm run`, inherited local prefix overrides could cause global background updates to fail or target a temporary cache.
6
+ - **Fixed**: **Binary path resolution for system PATH and `~/.local/bin`** — updated `resolveKandownBin()` to check `which kandown`, `command -v kandown`, and `~/.local/bin/kandown` before checking package manager prefixes, ensuring custom global PATH installations are detected accurately.
7
+ - **Fixed**: **Live daemon process upgrade on CLI update** — updated `refreshRunningProjectHtml()` so that background project daemon processes in RAM running older code are automatically stopped and relaunched with the newly updated CLI binary.
8
+
9
+ ## 0.27.0 — 2026-07-20 — "Unified Views"
10
+
11
+ - **Added**: **Full Component Parity between Board and List Views** — unified the List view (`ListView.tsx`) and Board view (`Column.tsx`) so that List view sections and task items share the exact same components, column background color tints, icons, and action options as Board columns.
12
+ - **Added**: **Guarded Delete Button & Card Actions in List View** — task items in List view are now rendered with `<Card>` (and `<CardStack>` for tag-grouped tasks). Hovering over a task row in List view now reveals the guarded delete button (`IconTrash`/`IconTrashX`) with double-click confirmation, multi-task selection (`⌘/Ctrl/Shift + Click`), tag/epic/report/blocked-by badges, subtask progress bars, search-preview snippets, and frontmatter metadata blocks.
13
+ - **Added**: **Shared Column Header Actions & Color Picker** — added `<ColumnHeaderActions>` and `<ColumnColorMenu>` to List view section headers. Users can pick column accent colors, rename columns (`✎`), delete columns (`×`), create tasks (`+`), and add unconfigured columns to project settings directly from List view.
14
+ - **Added**: **Section Footers in List View** — each section in List view now includes the `+ Add task` (`KbdButton`) footer at the bottom of the section container.
15
+ - **Changed**: **100% Viewport Width for List View** — removed the fixed `max-w-[1200px]` width constraint so List view occupies 100% of the viewport width, allowing task titles and metadata to expand flexibly across wider displays.
16
+
3
17
  ## 0.26.0 — 2026-07-20 — "Task Workspace"
4
18
 
5
19
  - **Added**: **Desktop opened-task workspace** — opening a task on desktop now replaces the modal overlay with a split workspace below the sticky header. The left pane lists tasks grouped by board status, while the right pane keeps the full task editor available in a large three-quarter-width panel.
package/bin/kandown.js CHANGED
@@ -130,17 +130,27 @@ function getCurrentVersion() {
130
130
  * @returns {string|null} Absolute path to the kandown binary, or null.
131
131
  */
132
132
  function resolveKandownBin() {
133
+ try {
134
+ const whichBin = String(execSync('which kandown 2>/dev/null || command -v kandown 2>/dev/null', {
135
+ timeout: 3000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
136
+ })).trim();
137
+ if (whichBin && existsSync(whichBin)) return whichBin;
138
+ } catch { /* ignore */ }
139
+ const localBin = join(homedir(), '.local', 'bin', 'kandown');
140
+ if (existsSync(localBin)) return localBin;
133
141
  try {
134
142
  const npmBin = String(execSync('npm config get prefix 2>/dev/null', {
135
143
  timeout: 3000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
136
144
  })).trim();
137
145
  if (existsSync(join(npmBin, 'bin', 'kandown'))) return join(npmBin, 'bin', 'kandown');
146
+ if (existsSync(join(npmBin, 'kandown'))) return join(npmBin, 'kandown');
138
147
  } catch { /* npm not available */ }
139
148
  try {
140
149
  const pnpmBin = String(execSync('pnpm config get prefix 2>/dev/null', {
141
150
  timeout: 3000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
142
151
  })).trim();
143
152
  if (existsSync(join(pnpmBin, 'bin', 'kandown'))) return join(pnpmBin, 'bin', 'kandown');
153
+ if (existsSync(join(pnpmBin, 'kandown'))) return join(pnpmBin, 'kandown');
144
154
  } catch { /* pnpm not available */ }
145
155
  return null;
146
156
  }
@@ -307,10 +317,16 @@ async function checkForUpdate(argv = process.argv) {
307
317
  const updateOk = await new Promise((resolve) => {
308
318
  const tryInstall = (cmd) => {
309
319
  return new Promise((res) => {
320
+ const cleanEnv = { ...process.env };
321
+ for (const k of Object.keys(cleanEnv)) {
322
+ if (k.startsWith('npm_config_') || k.startsWith('npm_') || k === 'INIT_CWD') {
323
+ delete cleanEnv[k];
324
+ }
325
+ }
310
326
  const child = spawn(cmd, ['install', '-g', 'kandown'], {
311
- timeout: 45000,
327
+ timeout: 60000,
312
328
  stdio: ['pipe', 'pipe', 'pipe'],
313
- env: { ...process.env },
329
+ env: cleanEnv,
314
330
  detached: false,
315
331
  });
316
332
  child.stderr.on('data', () => {}); // silence npm noise
@@ -1926,10 +1942,19 @@ async function refreshRunningProjectHtml() {
1926
1942
  .filter(dir => typeof dir === 'string' && dir.length > 0)
1927
1943
  );
1928
1944
 
1945
+ const currentVersion = getCurrentVersion();
1929
1946
  let refreshed = 0;
1930
1947
  for (const kandownDir of kandownDirs) {
1931
1948
  try {
1932
1949
  if (refreshKandownHtml(kandownDir)) refreshed++;
1950
+ const current = await getDaemonStatus(kandownDir);
1951
+ if (current.running) {
1952
+ const daemonVersion = current.metadata?.version || null;
1953
+ if (!daemonVersion || (currentVersion && semverGt(currentVersion, daemonVersion) > 0)) {
1954
+ await stopDaemon(kandownDir);
1955
+ await startDaemon(kandownDir, current.metadata?.port || null);
1956
+ }
1957
+ }
1933
1958
  } catch { /* best-effort: one locked project must not block restart */ }
1934
1959
  }
1935
1960
  return refreshed;