k0-board 0.4.0 → 0.6.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 (77) hide show
  1. package/.claude/skills/k0-changelog/SKILL.md +2 -2
  2. package/.claude/skills/k0-discuss/SKILL.md +105 -0
  3. package/.claude/skills/k0-discuss/references/rounds.md +280 -0
  4. package/.claude/skills/k0-epic/SKILL.md +196 -0
  5. package/.claude/skills/k0-links/.claude-plugin/plugin.json +6 -0
  6. package/.claude/skills/k0-links/hooks/hooks.json +1 -0
  7. package/.claude/skills/k0-links/hooks/links.js +128 -0
  8. package/.claude/skills/k0-links/hooks/register.js +204 -0
  9. package/.claude/skills/k0-next/SKILL.md +82 -0
  10. package/.claude/skills/k0-order/SKILL.md +123 -0
  11. package/.claude/skills/k0-plan/SKILL.md +156 -0
  12. package/.claude/skills/k0-split/SKILL.md +169 -0
  13. package/.claude/skills/k0-story/SKILL.md +108 -0
  14. package/.claude/skills/k0-ultracode/SKILL.md +251 -0
  15. package/.claude/skills/k0-ultracode/references/agent-brief.md +71 -0
  16. package/.claude/skills/k0-ultracode/references/modes.md +49 -0
  17. package/.claude/skills/k0-verify/SKILL.md +219 -0
  18. package/.claude/skills/k0-whatsnew/SKILL.md +95 -0
  19. package/.claude/skills/k0-work/SKILL.md +212 -0
  20. package/CHANGELOG.md +426 -1
  21. package/LICENSE +83 -18
  22. package/README.md +1141 -119
  23. package/bin/k0-board.js +127 -12
  24. package/menubar/K0MenuBar.swift +35 -5
  25. package/package.json +14 -2
  26. package/platform/contract.js +30 -5
  27. package/platform/darwin/terminal.js +230 -56
  28. package/platform/index.js +2 -1
  29. package/platform/linux/index.js +3 -0
  30. package/platform/linux/tray.py +10 -10
  31. package/platform/shared/command.js +19 -3
  32. package/platform/shared/tmux.js +32 -14
  33. package/platform/win32/index.js +5 -2
  34. package/platform/win32/terminal.js +24 -8
  35. package/platform/win32/tray.ps1 +13 -13
  36. package/server/backlog.js +618 -0
  37. package/server/changelog.js +13 -13
  38. package/server/cloud.js +355 -0
  39. package/server/db.js +2117 -146
  40. package/server/files.js +60 -21
  41. package/server/git.js +53 -14
  42. package/server/idle.js +15 -13
  43. package/server/index.js +1341 -186
  44. package/server/launcher.js +122 -14
  45. package/server/machine.js +10 -1
  46. package/server/mirror.js +1069 -0
  47. package/server/prices.js +59 -0
  48. package/server/projects.js +57 -12
  49. package/server/servers.js +22 -1
  50. package/server/sessions.js +5 -5
  51. package/server/settings.js +25 -2
  52. package/server/sync.js +383 -0
  53. package/server/update.js +325 -0
  54. package/server/usage.js +642 -0
  55. package/server/watcher.js +67 -13
  56. package/server/worktree.js +600 -0
  57. package/server/writer.js +98 -26
  58. package/web/account.js +265 -0
  59. package/web/awake.js +62 -0
  60. package/web/base.css +97 -0
  61. package/web/board.css +396 -16
  62. package/web/board.js +1182 -152
  63. package/web/changelog.js +3 -3
  64. package/web/files.js +73 -16
  65. package/web/index.html +110 -12
  66. package/web/list.css +536 -0
  67. package/web/list.js +1015 -0
  68. package/web/mentions.js +27 -9
  69. package/web/recency.js +10 -10
  70. package/web/units.js +1 -1
  71. package/web/usage.css +169 -0
  72. package/web/usage.html +78 -0
  73. package/web/usage.js +447 -0
  74. package/web/view.js +22 -3
  75. package/web/whatsnew.css +211 -0
  76. package/web/whatsnew.html +49 -0
  77. package/web/whatsnew.js +339 -0
@@ -26,6 +26,9 @@ import { ps, psJson, psq } from './powershell.js'
26
26
  const WT = () => which('wt')
27
27
  const POWERSHELL_BIN = () => which('pwsh') || which('powershell')
28
28
 
29
+ /** How much of the work area a window takes unless the mode asks for more. */
30
+ const COVERAGE = 0.86
31
+
29
32
  /** The user32 declarations every window operation here needs, added once per PowerShell run. */
30
33
  const USER32 = `
31
34
  Add-Type -Namespace K0 -Name Win -MemberDefinition @'
@@ -66,7 +69,7 @@ export async function open({ command, title }) {
66
69
 
67
70
  /**
68
71
  * Windows Terminal owns its tab titles and does not take instructions about them from
69
- * outside, so a card renamed after its session started keeps the old name in the title bar
72
+ * outside, so a story renamed after its session started keeps the old name in the title bar
70
73
  * until the session is restarted. Reported as unavailable rather than failing silently.
71
74
  */
72
75
  export async function setTitle() {
@@ -74,7 +77,7 @@ export async function setTitle() {
74
77
  }
75
78
 
76
79
  export async function focus(handle) {
77
- if (!handle) return { ok: false, error: 'This card has no terminal window of its own' }
80
+ if (!handle) return { ok: false, error: 'This story has no terminal window of its own' }
78
81
  const found = await psJson(
79
82
  `${USER32}
80
83
  $p = ${findWindow(handle)}
@@ -86,14 +89,14 @@ export async function focus(handle) {
86
89
  return found?.ok ? { ok: true } : { ok: false, error: 'That window is gone' }
87
90
  }
88
91
 
89
- export async function relayout(handles) {
92
+ export async function relayout(handles, { coverage = COVERAGE } = {}) {
90
93
  let touched = 0
91
94
  for (const handle of handles || []) {
92
95
  const ok = await psJson(
93
96
  `${USER32}
94
97
  Add-Type -AssemblyName System.Windows.Forms -ErrorAction SilentlyContinue
95
98
  $area = [System.Windows.Forms.Screen]::PrimaryScreen.WorkingArea
96
- $w = [int]($area.Width * 0.86); $h = [int]($area.Height * 0.86)
99
+ $w = [int]($area.Width * ${coverage}); $h = [int]($area.Height * ${coverage})
97
100
  $x = $area.X + [int](($area.Width - $w) / 2); $y = $area.Y + [int](($area.Height - $h) / 2)
98
101
  $p = ${findWindow(handle)}
99
102
  if ($p) { [K0.Win]::MoveWindow($p.MainWindowHandle, $x, $y, $w, $h, $true) | Out-Null; @{ ok = $true } }
@@ -105,10 +108,13 @@ export async function relayout(handles) {
105
108
  return { touched }
106
109
  }
107
110
 
108
- /** Font size lives in the terminal's own profile, which k0 will not rewrite. */
109
- export async function setFont() {
110
- return { touched: 0 }
111
- }
111
+ /**
112
+ * What the mode asks for, as far as this platform can give it: the window takes its share of
113
+ * the screen. The font size lives in the terminal's own profile, which k0 will not rewrite —
114
+ * so here driving mode makes the windows bigger and leaves the text alone, which is what the
115
+ * `terminal.font` capability has always said.
116
+ */
117
+ export const applyMode = (handles, { coverage } = {}) => relayout(handles, { coverage })
112
118
 
113
119
  export async function defaultFontSize() {
114
120
  return 12
@@ -198,12 +204,22 @@ export async function close({ handle, pid }) {
198
204
  return { closed: !!res?.ok }
199
205
  }
200
206
 
207
+ /**
208
+ * Not here: a command is only worth typing into a live session once the screen says the input
209
+ * box is free and, afterwards, that the line came out right — and Windows gives no way to read
210
+ * the screen (see the top of this file). A live session keeps its name until it ends.
211
+ */
212
+ export async function command() {
213
+ return { sent: false, why: 'k0 cannot read a terminal on Windows, so it will not type into one blind' }
214
+ }
215
+
201
216
  export const capabilities = () => ({
202
217
  windows: !!POWERSHELL_BIN(),
203
218
  font: false,
204
219
  readScreen: false,
205
220
  pasteWithoutSending: !!POWERSHELL_BIN(),
206
221
  title: false,
222
+ commands: false,
207
223
  })
208
224
 
209
225
  export { powershellCommand as buildCommand } from '../shared/command.js'
@@ -75,12 +75,12 @@ $menu = New-Object System.Windows.Forms.ContextMenuStrip
75
75
  $notify.ContextMenuStrip = $menu
76
76
 
77
77
  # Clicking the balloon brings that session's terminal up front, which is the whole point of being
78
- # told. Windows shows one balloon at a time and replaces it rather than queueing, so the card the
78
+ # told. Windows shows one balloon at a time and replaces it rather than queueing, so the story the
79
79
  # click belongs to is always the last one announced — there is nothing else it could be.
80
80
  $script:LastNotified = $null
81
81
  $notify.Add_BalloonTipClicked({
82
82
  if ($null -ne $script:LastNotified) {
83
- Invoke-K0 "/api/card/$($script:LastNotified)/focus" @{} | Out-Null
83
+ Invoke-K0 "/api/story/$($script:LastNotified)/focus" @{} | Out-Null
84
84
  }
85
85
  }) | Out-Null
86
86
 
@@ -100,10 +100,10 @@ function Update-K0Menu($Waiting, [bool]$Down) {
100
100
  } elseif (-not $Waiting -or $Waiting.Count -eq 0) {
101
101
  Add-K0Item 'Nothing waiting for you' $null $false | Out-Null
102
102
  } else {
103
- foreach ($card in $Waiting) {
104
- $label = "$($Labels[$card.status]) - $($card.title)"
105
- $id = $card.id
106
- Add-K0Item $label ([System.EventHandler]{ Invoke-K0 "/api/card/$id/focus" @{} | Out-Null }.GetNewClosure()) | Out-Null
103
+ foreach ($story in $Waiting) {
104
+ $label = "$($Labels[$story.status]) - $($story.title)"
105
+ $id = $story.id
106
+ Add-K0Item $label ([System.EventHandler]{ Invoke-K0 "/api/story/$id/focus" @{} | Out-Null }.GetNewClosure()) | Out-Null
107
107
  }
108
108
  }
109
109
 
@@ -126,17 +126,17 @@ function Update-K0Menu($Waiting, [bool]$Down) {
126
126
  }) | Out-Null
127
127
  }
128
128
 
129
- # Notify about cards that have just started waiting, not about every one on every pass.
129
+ # Notify about stories that have just started waiting, not about every one on every pass.
130
130
  function Show-K0Notifications($Waiting) {
131
131
  $now = @{}
132
- foreach ($card in $Waiting) { $now["$($card.id):$($card.status)"] = $true }
132
+ foreach ($story in $Waiting) { $now["$($story.id):$($story.status)"] = $true }
133
133
  if (-not $script:FirstPass) {
134
- foreach ($card in $Waiting) {
135
- $key = "$($card.id):$($card.status)"
134
+ foreach ($story in $Waiting) {
135
+ $key = "$($story.id):$($story.status)"
136
136
  if (-not $script:Seen.ContainsKey($key)) {
137
- $script:LastNotified = $card.id
138
- $notify.BalloonTipTitle = $Labels[$card.status]
139
- $notify.BalloonTipText = $card.title
137
+ $script:LastNotified = $story.id
138
+ $notify.BalloonTipTitle = $Labels[$story.status]
139
+ $notify.BalloonTipText = $story.title
140
140
  $notify.ShowBalloonTip(4000)
141
141
  }
142
142
  }