kandown 0.27.0 → 0.28.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.28.0 — 2026-07-20 — "Agent Instruction Modes & CLI Reference"
4
+
5
+ - **Added**: **3 Base Agent Rule Modes (Verbose, Optimized, Caveman)** — redesigned the Agent instructions settings into 3 distinct rule density modes. Users can choose between **Verbose** (full reference guide), **Optimized** (concise, high-density structured rules tailored for LLMs), and **Caveman** (ultra-compact minimal token rules).
6
+ - **Added**: **Quick CLI Commands Reference in Agent Rules** — added a concise CLI cheatsheet table (`kandown work`, `kandown list`, `kandown show`, `kandown create`, `kandown move`, `kandown assign`, `kandown commit`) right at the top of base rules across all modes so AI agents immediately know the native CLI commands available to interact with the board.
7
+ - **Added**: **3-Step Numbered Layout for Agent Settings** — reorganized the Agent Instructions settings page into 3 clear numbered step cards: Step 1 (Base Rules mode & density), Step 2 (Project Guidelines stored in `.kandown/instructions.md`), and Step 3 (Live Board State data filters).
8
+ - **Added**: **Quick Preset Instruction Chips** — added 1-click template insertion chips (`📦 pnpm`, `🧪 Test rule`, `🌳 Git rule`, `⚡ Task log`) below the project instructions editor for adding repository rules instantly.
9
+ - **Added**: **Terminal-Style Sticky Live Preview Panel** — added an independent sticky preview panel on the right with window dot indicators, token estimation badge, layer legend badges (🟢 Step 1, 🟡 Step 2, 🔵 Step 3), 1-click Copy button, and real-time interactive color highlighting when hovering over options.
10
+
11
+ ## 0.27.1 — 2026-07-20 — "Auto-Updater & Daemon Process Upgrade"
12
+
13
+ - **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.
14
+ - **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.
15
+ - **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.
16
+
3
17
  ## 0.27.0 — 2026-07-20 — "Unified Views"
4
18
 
5
19
  - **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.
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
@@ -1559,18 +1575,32 @@ function priorityRank(p) {
1559
1575
  }
1560
1576
 
1561
1577
  const WORK_OUTPUT_SECTION_IDS = ['baseRules', 'projectInstructions', 'boardDigest'];
1562
- const CONCISE_AGENT_RULES = `# Kandown agent rules — concise
1578
+ const OPTIMIZED_AGENT_RULES = `# Kandown agent rules
1579
+
1580
+ ## CLI Commands
1581
+ - \`kandown list\` (list tasks) · \`kandown show <id>\` (view task)
1582
+ - \`kandown create "<title>"\` (create task) · \`kandown move <id> <status>\` (move task column)
1583
+ - \`kandown assign <id> <user>\` · \`kandown commit\` (commit board to git)
1563
1584
 
1585
+ ## Rules
1564
1586
  - Task state lives in project-root \`tasks/*.md\`; do not maintain a separate board index.
1565
1587
  - Before work, read the relevant task file and keep it updated while you progress.
1566
1588
  - Move tasks by editing frontmatter \`status:\`; complete work by setting \`status: Done\` and adding a markdown \`report:\` summary.
1567
1589
  - Update subtasks in-place: \`- [ ]\` → \`- [x]\`, with a short \`report:\` line for meaningful progress.
1568
1590
  - Board columns live in \`.kandown/kandown.json\` under \`board.columns\`; project instructions live in \`.kandown/instructions.md\`.
1569
1591
  - Never put Kandown task data inside \`.kandown/\`; tasks belong in \`./tasks/\`.`;
1592
+
1593
+ const CAVEMAN_AGENT_RULES = `# Kandown agent rules
1594
+
1595
+ CLI: kandown list | kandown show <id> | kandown create "<title>" | kandown move <id> <status> | kandown assign <id> <user> | kandown commit
1596
+ RULES: TASKS IN ./tasks/*.md. READ TASK BEFORE WORK. UPDATE SUBTASKS - [ ] -> - [x] + REPORT. MOVE: EDIT status:. DONE: status: Done + report:.`;
1597
+
1598
+ const CONCISE_AGENT_RULES = OPTIMIZED_AGENT_RULES;
1599
+
1570
1600
  const DEFAULT_WORK_OUTPUT = {
1571
1601
  mode: 'blocks',
1572
1602
  includeBaseRules: true,
1573
- baseRulesMode: 'full',
1603
+ baseRulesMode: 'verbose',
1574
1604
  includeProjectInstructions: true,
1575
1605
  includeBoardDigest: true,
1576
1606
  sectionOrder: WORK_OUTPUT_SECTION_IDS,
@@ -1596,11 +1626,13 @@ function normalizeWorkOutputConfig(config) {
1596
1626
  ? raw.sectionOrder.filter(id => WORK_OUTPUT_SECTION_IDS.includes(id))
1597
1627
  : DEFAULT_WORK_OUTPUT.sectionOrder;
1598
1628
  const order = sectionOrder.length > 0 ? sectionOrder : DEFAULT_WORK_OUTPUT.sectionOrder;
1629
+ const validBaseModes = ['verbose', 'optimized', 'caveman', 'full', 'concise'];
1630
+ const baseMode = validBaseModes.includes(raw.baseRulesMode) ? raw.baseRulesMode : DEFAULT_WORK_OUTPUT.baseRulesMode;
1599
1631
  return {
1600
1632
  ...DEFAULT_WORK_OUTPUT,
1601
1633
  ...raw,
1602
1634
  mode: raw.mode === 'raw' ? 'raw' : 'blocks',
1603
- baseRulesMode: raw.baseRulesMode === 'concise' ? 'concise' : 'full',
1635
+ baseRulesMode: baseMode,
1604
1636
  sectionOrder: order,
1605
1637
  rawTemplate: typeof raw.rawTemplate === 'string' && raw.rawTemplate.trim()
1606
1638
  ? raw.rawTemplate
@@ -1609,8 +1641,9 @@ function normalizeWorkOutputConfig(config) {
1609
1641
  };
1610
1642
  }
1611
1643
 
1612
- function readBaseAgentRules(mode = 'full') {
1613
- if (mode === 'concise') return CONCISE_AGENT_RULES;
1644
+ function readBaseAgentRules(mode = 'verbose') {
1645
+ if (mode === 'caveman') return CAVEMAN_AGENT_RULES;
1646
+ if (mode === 'optimized' || mode === 'concise') return OPTIMIZED_AGENT_RULES;
1614
1647
  try {
1615
1648
  return readFileSync(join(PKG_ROOT, 'templates', 'AGENT_KANDOWN.md'), 'utf8').trim();
1616
1649
  } catch (e) {
@@ -1926,10 +1959,19 @@ async function refreshRunningProjectHtml() {
1926
1959
  .filter(dir => typeof dir === 'string' && dir.length > 0)
1927
1960
  );
1928
1961
 
1962
+ const currentVersion = getCurrentVersion();
1929
1963
  let refreshed = 0;
1930
1964
  for (const kandownDir of kandownDirs) {
1931
1965
  try {
1932
1966
  if (refreshKandownHtml(kandownDir)) refreshed++;
1967
+ const current = await getDaemonStatus(kandownDir);
1968
+ if (current.running) {
1969
+ const daemonVersion = current.metadata?.version || null;
1970
+ if (!daemonVersion || (currentVersion && semverGt(currentVersion, daemonVersion) > 0)) {
1971
+ await stopDaemon(kandownDir);
1972
+ await startDaemon(kandownDir, current.metadata?.port || null);
1973
+ }
1974
+ }
1933
1975
  } catch { /* best-effort: one locked project must not block restart */ }
1934
1976
  }
1935
1977
  return refreshed;