k0-board 0.4.0 → 0.5.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 (73) 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 +361 -1
  21. package/README.md +931 -111
  22. package/bin/k0-board.js +79 -11
  23. package/menubar/K0MenuBar.swift +35 -5
  24. package/package.json +13 -1
  25. package/platform/contract.js +30 -5
  26. package/platform/darwin/terminal.js +230 -56
  27. package/platform/index.js +2 -1
  28. package/platform/linux/index.js +3 -0
  29. package/platform/linux/tray.py +10 -10
  30. package/platform/shared/command.js +19 -3
  31. package/platform/shared/tmux.js +32 -14
  32. package/platform/win32/index.js +5 -2
  33. package/platform/win32/terminal.js +24 -8
  34. package/platform/win32/tray.ps1 +13 -13
  35. package/server/backlog.js +618 -0
  36. package/server/changelog.js +13 -13
  37. package/server/db.js +1800 -146
  38. package/server/files.js +60 -21
  39. package/server/git.js +53 -14
  40. package/server/idle.js +15 -13
  41. package/server/index.js +1251 -186
  42. package/server/launcher.js +122 -14
  43. package/server/machine.js +10 -1
  44. package/server/mirror.js +1048 -0
  45. package/server/prices.js +59 -0
  46. package/server/projects.js +57 -12
  47. package/server/servers.js +22 -1
  48. package/server/sessions.js +5 -5
  49. package/server/settings.js +25 -2
  50. package/server/update.js +324 -0
  51. package/server/usage.js +642 -0
  52. package/server/watcher.js +67 -13
  53. package/server/worktree.js +600 -0
  54. package/server/writer.js +98 -26
  55. package/web/awake.js +62 -0
  56. package/web/base.css +4 -0
  57. package/web/board.css +396 -16
  58. package/web/board.js +1182 -152
  59. package/web/changelog.js +3 -3
  60. package/web/files.js +73 -16
  61. package/web/index.html +109 -12
  62. package/web/list.css +536 -0
  63. package/web/list.js +1015 -0
  64. package/web/mentions.js +27 -9
  65. package/web/recency.js +10 -10
  66. package/web/units.js +1 -1
  67. package/web/usage.css +169 -0
  68. package/web/usage.html +78 -0
  69. package/web/usage.js +447 -0
  70. package/web/view.js +22 -3
  71. package/web/whatsnew.css +211 -0
  72. package/web/whatsnew.html +49 -0
  73. package/web/whatsnew.js +339 -0
@@ -27,7 +27,7 @@ whole thing. Markdown, starting at the first word that belongs to the summary.
27
27
  "unpushed_total": 2,
28
28
  "uncommitted_files": ["web/board.js"],
29
29
  "unreleased_changelog": ["### Fixed", "- the board stays pinned to the bar"],
30
- "cards": [{ "title": "…", "description": "…", "status": "IDLE", "done": false }]
30
+ "stories": [{ "title": "…", "description": "…", "status": "IDLE", "done": false }]
31
31
  }
32
32
  ]
33
33
  }
@@ -73,7 +73,7 @@ something to put in them. This is a summary somebody reads standing up.
73
73
 
74
74
  ## Rules
75
75
 
76
- - **Write in the language of the facts.** The commit subjects and the card titles tell you what
76
+ - **Write in the language of the facts.** The commit subjects and the story titles tell you what
77
77
  language this person works in: write in that one, and do not translate anything. The headings,
78
78
  the bold lines, the bullets — all of it in their language.
79
79
  - **Leave the words of the trade alone.** *commit*, *push*, *branch*, *changelog* are what these
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: k0-discuss
3
+ description: Takes a story that is already on the k0 board and still too vague to build, and discusses it in rounds of questions until the decisions behind it are written down one by one. Appends to the rounds and decisions the story already has instead of starting the conversation again. Use this skill when the user types "/k0-discuss", or says "discuss K42", "this story is too vague", "let's talk it through before I start", "pick up the discussion on K19", "parliamo di K42", "questa storia è troppo vaga", "riprendiamo la discussione su K19", "discutiamo prima di partire". Do not use it to create a story from nothing (that is /k0-story or /k0-epic), to break up a story that will not close (/k0-split), or to plan one whose decisions are already recorded (/k0-plan).
4
+ ---
5
+
6
+ # /k0-discuss [key]
7
+
8
+ A story on the board says what it is called and not much else. This turns it into something
9
+ buildable: rounds of questions, and a row of decisions somebody can hold the finished work up
10
+ against six months from now.
11
+
12
+ `[key]` is `K42`, or nothing — with nothing, work out which story from what the user just said.
13
+
14
+ ## The rules of a round live in one file
15
+
16
+ Read `references/rounds.md` — it sits in this skill's own folder — and follow it. How many rounds
17
+ and how to say it, when to stop, the fifteen-round ceiling, how to ask, what to do when two
18
+ answers collide, how to write a decision, and why every round is written to the API before the
19
+ next question is asked: all of that is there and none of it is repeated here.
20
+
21
+ **If you cannot read that file, say so and stop.** Those rules are the method. Running the
22
+ discussion without them produces exactly the pleasant, unchecked conversation the whole feature
23
+ exists to prevent.
24
+
25
+ What follows is only what is particular to discussing a story that already exists.
26
+
27
+ ## Procedure
28
+
29
+ 1. **Find the story, and check the feature is on.**
30
+
31
+ ```bash
32
+ PORT="${K0_PORT:-4319}"
33
+ REPO="$(git rev-parse --path-format=absolute --git-common-dir 2>/dev/null)"; REPO="${REPO%/.git}"
34
+ [ -d "$REPO" ] || REPO="$(git rev-parse --show-toplevel 2>/dev/null)"
35
+ curl -sS --max-time 30 --get --data-urlencode "repo=$REPO" \
36
+ "http://127.0.0.1:$PORT/api/backlog" -o "$SCRATCH/k0-backlog.json"
37
+ ```
38
+
39
+ `127.0.0.1`, not `k0.localhost`: browsers resolve that name by themselves, `curl` does not.
40
+ `--get --data-urlencode`, not `?repo=$REPO`: a repository path with a space in it makes `curl`
41
+ refuse the address outright, and one with a `#` in it quietly sends half.
42
+ `$SCRATCH` is the session's scratch directory; nothing is written outside it. `REPO` is the
43
+ repository the stories are filed under — the main one, even when this session sits in a
44
+ subdirectory of it or inside a worktree, which is why it is not `$PWD`.
45
+
46
+ - `curl` cannot connect → the k0 server is not running. Say so (`k0-board start`, or the tray
47
+ icon → *Restart*) and **stop**.
48
+ - `{"enabled": false}` → say in one line that the backlog is switched off in k0's settings and
49
+ **stop**. Do not run the discussion anyway and do not offer to turn it on.
50
+ - `REPO` empty → this is not a git repository. Ask once which repository this belongs to and
51
+ take the path he gives.
52
+
53
+ The listing carries every key, title and state. Match the key the user gave, or the
54
+ title he described. If two stories match, ask which one; never pick one and hope. If the
55
+ listing has no stories at all, say so — an empty board is not the same as a story you failed
56
+ to find, and it usually means the work has never been written down here.
57
+
58
+ 2. **Read everything already recorded.**
59
+
60
+ ```bash
61
+ curl -sS --max-time 30 "http://127.0.0.1:$PORT/api/backlog/story/$STORY_ID" -o "$SCRATCH/k0-story.json"
62
+ ```
63
+
64
+ `$STORY_ID` is the `id` of the story you matched in step 1, not the key. Rounds, decisions,
65
+ plan, checks, log. This is the whole point of the skill: a second discussion that ignores the
66
+ first one is worse than no second discussion, because it spends the user's evening asking him
67
+ things he has already answered.
68
+
69
+ 3. **Say where you are picking up from**, in one line, before the first question:
70
+
71
+ > K42 already has four rounds and six decisions from 3 September. Round 5 of about 7.
72
+
73
+ On a story with no rounds yet, say that instead and start at round 1.
74
+
75
+ 4. **Run the rounds** exactly as `references/rounds.md` describes. Every round POSTed before the
76
+ next question leaves your mouth, every decision POSTed the moment it is settled.
77
+
78
+ 5. **Close the account.** The new decisions, by number, in his words — a short list, not a
79
+ retelling of the conversation. Then, unless the story is already `Planned`, `Working`,
80
+ `Review` or `Done`, move it on:
81
+
82
+ ```bash
83
+ curl -sS -X PATCH "http://127.0.0.1:$PORT/api/backlog/story/$STORY_ID" \
84
+ -H 'content-type: application/json' -d '{"state": "Discussed"}'
85
+ ```
86
+
87
+ Then one line saying what comes next — `/k0-plan K42` — and stop there. Do not start planning.
88
+
89
+ ## Rules
90
+
91
+ - **Append, never replace.** New decisions get new numbers. One that contradicts an older one
92
+ goes through the collision rule in §4 of `references/rounds.md`: the old sentence is marked
93
+ superseded by the new one's `id`, never edited and never deleted. Nothing in this skill sends
94
+ a `DELETE`.
95
+ - **The body is his, not yours.** If the discussion changes what the story is fundamentally
96
+ about, `PATCH` the `body` — but with his sentences, in his language, and say that you did.
97
+ - **A story mid-flight is still discussable.** `Working` or `Review` is not a reason to refuse.
98
+ It is a reason to read the log first, and to say out loud that work has already started, so
99
+ that a new decision contradicting what is built is recognised as the rework it is.
100
+ - **Talk in the language the user speaks, and store what he says in that language.** The story
101
+ carries a `lang`: if it is empty, set it from the language of the discussion.
102
+ - **Never ask what the API can tell you** — the key, the epic, the dependencies, what
103
+ is open, how far the epic has got. It is in the two calls above. See §7 of `references/rounds.md`.
104
+ - **No files outside the scratch directory**, and never write into `.k0/` by hand: the server
105
+ mirrors the story there on its own.
@@ -0,0 +1,280 @@
1
+ # The rounds engine
2
+
3
+ This is the one place the rules for discussing a story live. `k0-discuss` runs on them, and
4
+ `k0-epic`, `k0-split`, `k0-plan`, `k0-work` and `k0-verify` read this file instead of restating
5
+ it — they reach it as `../k0-discuss/references/rounds.md`, relative to the folder the skill
6
+ itself was loaded from, which is where it is whether k0 runs installed from npm or from a
7
+ checkout. If you find these rules written out somewhere else, that copy is wrong and this one
8
+ wins.
9
+
10
+ ## Why any of this exists
11
+
12
+ The person you are talking to has already been through a long, pleasant discussion with a
13
+ model that asked good questions, understood the answers, agreed with everything — and then
14
+ built something that quietly contradicted half of it. Nothing checked. Nothing compared the
15
+ finished work against what had been decided, because nothing had written down what had been
16
+ decided in a form anybody could check.
17
+
18
+ So the discussion was worthless. Worse than worthless: it cost an hour and bought a false
19
+ sense that the thing was understood.
20
+
21
+ Everything below exists to stop that happening again. The questions are not the point. The
22
+ point is the row of decisions the questions leave behind, each one a sentence a person can
23
+ read six months later and hold the work up against. `/k0-verify` will do exactly that, one
24
+ decision at a time. Write them so it can.
25
+
26
+ ---
27
+
28
+ ## 1. How many rounds, and saying it out loud
29
+
30
+ Before the first question, list the **open unknowns**: the things where a different answer
31
+ would produce different work. Not the things you are curious about — the things that fork the
32
+ build. A question whose two answers lead to the same code is not an unknown.
33
+
34
+ Then:
35
+
36
+ - rounds still needed ≈ open unknowns ÷ 3, rounded up (three, not four: the fourth slot is
37
+ for what an answer opens up);
38
+ - estimated total = rounds already run + that;
39
+ - say it in the first line of every round: **"Round 3 of about 8"**, in the user's language.
40
+
41
+ The word *about* is doing real work. It is an estimate and it is allowed to move.
42
+
43
+ **Recount after every answer**, because answers both close unknowns and create them. When the
44
+ number moves, say so in the same breath — one short clause, no apology:
45
+
46
+ > Round 4 of about 6 — two of the questions answered themselves.
47
+
48
+ > Round 5 of about 9 — invoicing turned out to have its own states.
49
+
50
+ **Never let the number drift in silence.** Announcing 8 and then quietly asking a twelfth
51
+ question is the thing that makes people stop trusting the count. If you cannot say why the
52
+ number moved, the number did not move: you miscounted, and you say that instead.
53
+
54
+ If the estimate ever climbs past about twelve, stop and say what you are seeing: a story that
55
+ needs twelve rounds is usually two stories. Offer `/k0-split`. The user decides.
56
+
57
+ Every round is written to the API with the estimate it was asked under, so the record shows
58
+ what you believed at the time — see §6.
59
+
60
+ ## 2. When to stop
61
+
62
+ Stop when **no remaining question would change what gets built.** That is the whole test, and
63
+ it is stricter than it sounds. Apply it to each unknown still on your list:
64
+
65
+ - *Would a different answer change the work?* No → drop it, do not ask it.
66
+ - *Can it be decided during the work, and cheaply undone if it is wrong?* Then it is not a
67
+ decision for now. Decide it yourself later, and say so in one line.
68
+ - *Is it a preference the user will notice the moment he sees it?* Ask.
69
+
70
+ Do not run a last round to be thorough. Thoroughness here means one more question the user has
71
+ to answer to get where he was already going.
72
+
73
+ **The ceiling is 15 rounds.** At 15 you stop, whatever state the discussion is in. Post the
74
+ last round, then show what is still open — a plain list of the unknowns you never got to,
75
+ in the user's words — and say the story is recorded as it stands and can be picked up again
76
+ whenever he wants. Do not ask a sixteenth question. Do not decide the open ones yourself to
77
+ make the list look finished. A discussion that hits 15 is telling you the story is too big;
78
+ say that too, and offer to split it.
79
+
80
+ ## 3. How to ask
81
+
82
+ `AskUserQuestion`, **at most four questions per round**. Four is a ceiling, not a target: two
83
+ sharp questions beat four vague ones, and a round of one is fine.
84
+
85
+ **Never pass `preview` on an option.** With `preview` set on a single-select question the
86
+ interface switches to a side-by-side layout and the free-text box — *Type something.* —
87
+ disappears. That box is how this user actually answers. He picks one of your options perhaps
88
+ half the time; the rest of the time he types the answer you did not think of, and that answer
89
+ is usually the good one. Taking the box away to show a nicer layout is a bad trade every
90
+ single time. There is no exception.
91
+
92
+ For each question:
93
+
94
+ - **One unknown per question.** Two unknowns bundled into one question get one answer, and you
95
+ will not know which one it settled.
96
+ - **Two to four options**, and put the **one you recommend first**. You have read the story;
97
+ having no opinion is not neutrality, it is work handed back.
98
+ - **The description carries the trade-off**, never a restatement of the label. It says what you
99
+ give up by choosing this. If you cannot name what is lost, you have not understood the
100
+ choice well enough to ask about it.
101
+ - Short labels. The description is where the sentence goes.
102
+
103
+ Good:
104
+
105
+ > **The user presses Done** — nothing closes a story by itself. Safest, but a finished story
106
+ > can sit on the board for days looking unfinished.
107
+ >
108
+ > **The last check passing closes it** — no housekeeping, but a story can close while you are
109
+ > still looking at it.
110
+
111
+ Bad — the description says the label again:
112
+
113
+ > **The user presses Done** — the user has to press Done to finish the story.
114
+
115
+ Then **listen to the free text.** When the typed answer does not match any option, the typed
116
+ answer is the answer. Do not re-ask in the hope of getting a clean click.
117
+
118
+ ## 4. When two answers collide
119
+
120
+ **Before every round**, fetch what has already been recorded and read it — do not trust your
121
+ memory of the conversation:
122
+
123
+ ```bash
124
+ curl -sS --max-time 30 "http://127.0.0.1:$PORT/api/backlog/story/$STORY_ID" -o "$SCRATCH/k0-story.json"
125
+ ```
126
+
127
+ Its `decisions` array is everything that binds this story: the decisions taken on it, and the
128
+ ones taken on its epic before it existed, which it inherits. Each carries an `owner` — `story` or
129
+ `epic` — and a `label`, `D3` or `K7·D3`. There is nowhere else to look: an epic's decisions are
130
+ rows on the epic, never prose in its `body`, and `body` is only the Why.
131
+
132
+ The inherited ones are the ones a later answer most often contradicts, because they were settled
133
+ weeks ago about the whole area and nobody in this conversation has said them out loud.
134
+
135
+ Compare the answer that just arrived against every decision in that list. A collision is when
136
+ the two **cannot both be true of the finished work**. A later answer that adds detail to an
137
+ earlier one is not a collision; do not cry conflict over a refinement, it teaches the user to
138
+ ignore you when it matters.
139
+
140
+ When they do collide, **stop in the middle of the round.** No next question, no smoothing it
141
+ over, no picking the newer one because it is newer.
142
+
143
+ Put both in front of him, quoted, by number:
144
+
145
+ > These two do not fit together.
146
+ >
147
+ > **D3** — A story can go straight from Backlog to Done, and nothing warns about it.
148
+ > **just now** — Nothing may leave Review until every check has passed.
149
+ >
150
+ > I think **D3** should win: you asked for no mandatory path twice, and the check rule only
151
+ > bites on stories that got as far as Review. But it is your call.
152
+
153
+ Say which one you think should win **and why**, in one sentence, and then wait. Do not continue
154
+ the discussion until he has chosen.
155
+
156
+ On the record, **the last answer wins**: the choice becomes a new decision with its own number,
157
+ and the loser is marked superseded — never edited, never deleted.
158
+
159
+ ```bash
160
+ curl -sS -X POST "http://127.0.0.1:$PORT/api/backlog/story/$STORY_ID/decision" \
161
+ -H 'content-type: application/json' -d @"$SCRATCH/k0-decision.json" \
162
+ -o "$SCRATCH/k0-new-decision.json" # → { "id": 148, "n": 9, … }
163
+
164
+ curl -sS -X PATCH "http://127.0.0.1:$PORT/api/backlog/decision/$OLD_ID" \
165
+ -H 'content-type: application/json' -d '{"superseded_by": 148}'
166
+ ```
167
+
168
+ **`superseded_by` takes the new decision's `id`, never its `n`.** They are different numbers and
169
+ they look alike: `id` is the row's own, unique across the whole database, and it is what the
170
+ answer to the POST carries next to `n`; `n` starts again at 1 on every story, so sending it
171
+ points the supersession at some other story's decision, or at nothing. Read the `id` out of the
172
+ answer. Never type a number you worked out yourself, and never reuse the one in the example.
173
+
174
+ **Supersede a decision where it lives, not where it is read.** An epic's decision is superseded on
175
+ the epic — one call, and every story under it sees the change at once. That is the whole reason it
176
+ belongs to the epic. The only copies that ever need chasing are the ones `/k0-split` made when it
177
+ cut a story into tasks, and those are the story's own, not the epic's: if this story has tasks
178
+ under it that carry a copy of the decision you are reversing, supersede each of those too, with
179
+ that task's own decision `id`. A copy left standing is a rule `/k0-verify` will go on holding the
180
+ finished work up against long after the user reversed it.
181
+
182
+ The old sentence stays readable with *(superseded by D9)* beside it. That is not bookkeeping:
183
+ six months on, knowing a decision was made and then reversed is worth more than a tidy list
184
+ that pretends it never happened.
185
+
186
+ ## 5. How to write a decision
187
+
188
+ This is the part the whole feature stands on. A decision is what `/k0-verify` will hold the
189
+ finished work up against, one at a time. A decision nobody can check is a decision that was
190
+ not made.
191
+
192
+ - **One complete sentence.** Subject, verb, the thing that will be true. Not a fragment, not a
193
+ heading, not a note to self.
194
+ - **Behaviour, not implementation.** What the user will see, do, or be spared. No file paths,
195
+ no table names, no function names, no jargon. He does not read code and should not have to.
196
+ - **One decision per line.** Never merge two, however neatly they pair.
197
+ - **Never lose one.** Half-swallowed by voice dictation, said badly, said twice in different
198
+ words, dropped into the middle of an answer about something else — it still counts. When a
199
+ sentence came out garbled, read back what you think he meant and ask; do not quietly bin it
200
+ and do not guess.
201
+ - **In the language he spoke.** The decisions are for him, not for the repository.
202
+ - Write it the moment it is settled, in the same breath as the round it came from (§6).
203
+
204
+ ### Three that work
205
+
206
+ - Nothing marks a story finished on its own: the user presses Done.
207
+ - A story can go straight from Backlog to Done, and nothing warns about it.
208
+ - Every post-it shows the name of the epic it belongs to, in that epic's colour.
209
+
210
+ Each one is a sentence, describes something visible, and can be checked by looking at k0.
211
+
212
+ ### Three that do not
213
+
214
+ - *Add `epic_id` to the story table and join it in `listStories()`.*
215
+ Implementation, and the two things he would need in order to check it — a table and a
216
+ function — are things he never looks at. Rewritten: *a story remembers which epic it belongs
217
+ to, and keeps it when it is moved.*
218
+
219
+ - *Colours and states.*
220
+ Not a sentence and not a decision. In six months nobody, including you, can say what was
221
+ agreed. If this is all you have, you did not get an answer: ask again.
222
+
223
+ - *Use the epic's colour on the post-it, and allow Backlog → Done directly, and keep Done
224
+ manual.*
225
+ Three decisions on one line. When one of them is reversed there is no way to strike only
226
+ that one, so the whole line goes stale and the other two rot with it.
227
+
228
+ ## 6. Write it down before you ask the next thing
229
+
230
+ **Every round is POSTed before the following question leaves your mouth.** Not batched at the
231
+ end, not held in the conversation and written up when the discussion closes.
232
+
233
+ ```bash
234
+ curl -sS -X POST "http://127.0.0.1:$PORT/api/backlog/story/$STORY_ID/round" \
235
+ -H 'content-type: application/json' -d @"$SCRATCH/k0-round.json"
236
+ ```
237
+
238
+ with `{ "n": 3, "estimated_total": 8, "question": "…", "answer": "…" }` — `n` is 1-based per
239
+ story, `estimated_total` is what you announced for *that* round. Decisions go the same way, the
240
+ instant they are settled, not when the discussion ends.
241
+
242
+ The reason is plain: terminals die. A crash at round three must not take the first three with
243
+ it, and it must not leave the user re-answering questions he has already answered — that is
244
+ exactly the moment people stop using a tool. Write the JSON to a file under `$SCRATCH` and send
245
+ it with `-d @file`; long answers with quotes and newlines in them do not survive being pasted
246
+ inline.
247
+
248
+ Resuming is then automatic: fetch `GET /api/backlog/story/:id`, read the rounds and decisions
249
+ already there, carry on at the highest `n` + 1, and say where you are picking up from. Never
250
+ start again at round 1 on a story that already has rounds.
251
+
252
+ If `curl` cannot connect, the k0 server is not running. Say so (`k0-board start`, or the tray
253
+ icon → *Restart*) and **stop**. Do not run the discussion anyway and promise to save it later:
254
+ that promise is the failure this file exists to prevent.
255
+
256
+ ## 7. What you never ask
257
+
258
+ His time is the scarce thing here. Two kinds of question waste it.
259
+
260
+ **What the server already knows.** Fetch it; do not ask, and do not reason it out either.
261
+
262
+ | you want | where it comes from |
263
+ |---|---|
264
+ | the key, the title, the state | `GET /api/backlog?repo=<path>` |
265
+ | which epic, how far along it is | the same call — `progress: {done, total}` |
266
+ | what was decided while the epic was discussed | `GET /api/backlog/story/:id` — already merged into `decisions`, marked `owner: "epic"` |
267
+ | what is open, what is blocked, the dependencies | the same call — `state`, `blocked`, `deps` |
268
+ | the rounds, decisions, checks, plan and log so far | `GET /api/backlog/story/:id` |
269
+ | what to pick up next, and why | `GET /api/backlog/next?repo=<path>` |
270
+
271
+ Counting is not what a model is for. Understanding what he means and writing it down clearly
272
+ is. Asking him for a number the database is already holding makes him do the machine's job.
273
+
274
+ **Anything with an obvious default.** Decide it, and say what you decided in one line he can
275
+ push back on — *"I am taking the story's colour from its epic unless you say otherwise"* — and
276
+ carry on without waiting. A round spent confirming the obvious buys nothing and spends the
277
+ attention you will need for the question that actually matters.
278
+
279
+ Also never ask: something he has already answered in this session; the same unknown a second
280
+ time in different words; permission to continue; or a question whose answer you would ignore.
@@ -0,0 +1,196 @@
1
+ ---
2
+ name: k0-epic
3
+ description: The long way in. The user talks for ten minutes about something big — a feature, a rewrite, a whole area of the product — and this turns it into an epic on the k0 board: rounds of questions until nothing is left that would change the work, a decision written down for each thing settled, and only then a tree of stories proposed for approval and created. Use this skill when the user says "/k0-epic", "new epic", "let me tell you about something big", "I want to think this through with you", "break this down for me", or in Italian "nuovo epic", "ti racconto una cosa grossa", "ragioniamo su questa feature", "spacchettiamo questo lavoro". Do not use it for one thing he already knows he wants — that is /k0-story — nor to discuss, split or plan a story that already exists: those are /k0-discuss, /k0-split and /k0-plan.
4
+ ---
5
+
6
+ # /k0-epic
7
+
8
+ Somebody is about to describe something too big to be one post-it. The work here is in this
9
+ order and no other: **understand, record, propose, then write.** Thirty stories created before
10
+ he has agreed to them is thirty things he now has to delete.
11
+
12
+ ## Before anything
13
+
14
+ ```bash
15
+ PORT="${K0_PORT:-4319}"
16
+ REPO="$(git rev-parse --path-format=absolute --git-common-dir 2>/dev/null)"; REPO="${REPO%/.git}"
17
+ [ -d "$REPO" ] || REPO="$(git rev-parse --show-toplevel 2>/dev/null)"
18
+ curl -sS --max-time 30 --get --data-urlencode "repo=$REPO" \
19
+ "http://127.0.0.1:$PORT/api/backlog" -o "$SCRATCH/k0-backlog.json"
20
+ ```
21
+
22
+ `127.0.0.1`, not `k0.localhost`: browsers resolve that name by themselves, `curl` does not.
23
+ `--get --data-urlencode`, not `?repo=$REPO`: a repository path with a space in it makes `curl`
24
+ refuse the address outright, and one with a `#` in it quietly sends half.
25
+ `$SCRATCH` is the session's scratch directory; nothing is written outside it. `REPO` is the
26
+ repository the stories are filed under — the main one, even when this session sits in a
27
+ subdirectory of it or inside a worktree, which is why it is not `$PWD`.
28
+
29
+ - `curl` cannot connect → the k0 server is not running. Say so (`k0-board start`, or the tray
30
+ icon → *Restart*) and **stop**.
31
+ - `{"enabled": false}` → say in one line that the backlog is switched off in k0's settings and
32
+ **stop**.
33
+ - `REPO` empty → this is not a git repository. Ask once which repository this belongs to and
34
+ take the path he gives.
35
+
36
+ That one answer also holds the repository's existing epics and stories. Read it before you open
37
+ your mouth: half of what he is about to describe may already be on the board, and saying so is
38
+ worth more than a good question.
39
+
40
+ ## 1. Let him finish
41
+
42
+ He is dictating, probably out loud, probably jumping about. Do not interrupt with round one
43
+ while he is still going. When he stops, say back in three or four lines what you understood the
44
+ thing to be — not a summary of his words, the shape of the work — and let him correct it.
45
+
46
+ ## 2. Create the epic straight away
47
+
48
+ As soon as there is a title and a why, before the first question:
49
+
50
+ ```bash
51
+ curl -sS --max-time 30 -X POST "http://127.0.0.1:$PORT/api/backlog/epic" \
52
+ -H 'content-type: application/json' -d @"$SCRATCH/k0-epic.json" -o "$SCRATCH/k0-epic-new.json"
53
+ ```
54
+
55
+ with `{ "project_path": "…", "title": "…", "body": "…", "lang": "it" }`. The `body` is why this
56
+ epic exists, in his words and his language. The answer carries the `key` and the
57
+ `id`; use those from now on and never work them out yourself.
58
+
59
+ An epic with no stories yet costs nothing and means the next ten minutes survive a dead terminal.
60
+
61
+ ## 3. Run the rounds
62
+
63
+ The rules for this are in one place and this skill does not repeat them:
64
+
65
+ **`../k0-discuss/references/rounds.md` — read it now and follow it.** The path is relative to
66
+ the folder this skill was loaded from; the two skills are siblings wherever k0 is installed. If
67
+ you cannot find the file, say so and **stop** — those rules are the method, and an epic
68
+ discussed without them is the long pleasant conversation nobody ever checks.
69
+
70
+ How many rounds and how to announce them, when to stop, the ceiling, how to ask, what to do when
71
+ two answers collide, how to write a decision, and what never to ask: all of it is there and all
72
+ of it applies here unchanged.
73
+
74
+ One thing is particular to an epic: the rounds and the decisions belong to the **epic itself**,
75
+ not to a story, and not to its body.
76
+
77
+ **Write every round on the epic, before the next question.** An epic has rows of its own for
78
+ exactly this — there is no need to keep the transcript anywhere, and no reason to.
79
+
80
+ ```bash
81
+ curl -sS --max-time 30 -X POST "http://127.0.0.1:$PORT/api/backlog/epic/$EPIC_ID/round" \
82
+ -H 'content-type: application/json' -d @"$SCRATCH/round.json"
83
+ ```
84
+
85
+ `{ "n": 3, "estimated_total": 8, "question": "…", "answer": "…" }`, in his language. Writing the
86
+ same `n` twice replaces that round, so the question can go down when you ask it and the answer
87
+ when it arrives — that is one round, not two.
88
+
89
+ **Write every decision on the epic as it is taken.**
90
+
91
+ ```bash
92
+ curl -sS --max-time 30 -X POST "http://127.0.0.1:$PORT/api/backlog/epic/$EPIC_ID/decision" \
93
+ -H 'content-type: application/json' -d '{"text":"…","source":"discussion"}'
94
+ ```
95
+
96
+ It comes back with `id` and `n`. Keep the `id`: superseding takes a row id and never a number.
97
+
98
+ **`body` is the Why and nothing else.** Never grow it into a transcript. A decision written into
99
+ prose cannot be counter-checked one at a time, which is the one thing this whole feature is for,
100
+ and it cannot be superseded either — the strikethrough is a mark on a paragraph, not a change to
101
+ anything `/k0-verify` reads.
102
+
103
+ **The collision check reads the epic's decisions.** §4 of `rounds.md` says to fetch what is
104
+ already recorded before every round rather than trusting your memory of the conversation. Here
105
+ that is the epic:
106
+
107
+ ```bash
108
+ curl -sS --max-time 30 "http://127.0.0.1:$PORT/api/backlog/epic/$EPIC_ID" -o "$SCRATCH/epic.json"
109
+ ```
110
+
111
+ `decisions` is the list, each with `id`, `n`, `text` and `superseded_by`. Everything else in §4
112
+ holds: stop mid-round, put both sentences in front of him, say which you think should win and
113
+ why, wait. The loser is superseded by the winner's row id:
114
+
115
+ ```bash
116
+ curl -sS --max-time 30 -X PATCH "http://127.0.0.1:$PORT/api/backlog/decision/$OLD_ID" \
117
+ -H 'content-type: application/json' -d "{\"superseded_by\":$NEW_ID}"
118
+ ```
119
+
120
+ A superseded decision is never deleted — the record of a reversal is worth more than a tidy list
121
+ — and every story of this epic sees the reversal at once, which is the reason it lives here.
122
+
123
+ Resuming after a dead terminal is the same as anywhere: re-fetch the epic, read its rounds and
124
+ decisions, carry on at the next number, and say where you are picking up from.
125
+
126
+ ## 4. Propose the tree, and wait
127
+
128
+ Only when the rounds have stopped. One message, in his language:
129
+
130
+ - the epic, one line;
131
+ - the stories, in the order they would be done — **title, then one line saying what it is**;
132
+ - under each, the dependency when there is one: *needs the first one done*;
133
+ - what you have deliberately left out, if anything, one line.
134
+
135
+ No numbering scheme of your own — k0 gives every story a key the moment it exists,
136
+ and inventing a second one now only makes two things to reconcile.
137
+
138
+ Then ask for the tree as a whole, with `AskUserQuestion` under the rules in §3 of `rounds.md`:
139
+ approve it, change it, or cut something. Expect him to move things. Rework the list and ask
140
+ again; two passes here are cheap and thirty wrong stories are not.
141
+
142
+ **If the tree comes out longer than about twelve stories, say so before asking.** An epic that
143
+ big is usually two epics, and he decides which.
144
+
145
+ **Nothing is written until he has said yes.**
146
+
147
+ ## 5. Write it
148
+
149
+ In this order:
150
+
151
+ 1. **The stories.** One `POST /api/backlog/story` each, with `project_path`, `title`, `body`,
152
+ `lang`, `epic_key` — the epic's key from step 2 — and a **`prompt`**: the sentence a session
153
+ opening on that story starts from. Two lines is enough, in his language, and it always says
154
+ the same two things: what this story is, and that the plan and the standing decisions are on
155
+ the story, so `/k0-plan K42` or `/k0-work K42` is where to begin. Without it a session started
156
+ from the board's button opens cold, and ten minutes of discussion reach the terminal by luck.
157
+ Send each one with `-d @file`.
158
+ 2. **The decisions: nothing to do.** They were written on the epic in step 3, as they were taken,
159
+ and every story carrying `epic_key` inherits them. `GET /api/backlog/story/:id` returns them
160
+ in the same `decisions` array as the story's own, marked `"owner": "epic"` and labelled
161
+ `K7·D3`, and `/k0-verify` counter-checks them one by one like any other.
162
+
163
+ **Do not copy them down onto the stories.** It is the one thing that looks helpful here and is
164
+ not: the copy is a second row saying the same sentence, and the day he reverses `K7·D3` on the
165
+ epic only the epic's changes. The copies stand, and `/k0-verify` goes on holding finished work
166
+ up against a rule he took back.
167
+
168
+ A story only gets a decision of its own when something was settled about *that story* and
169
+ about no other — usually nothing was, at this point.
170
+ 3. **The dependencies.** `POST /api/backlog/dependency` with `{ "story_id": …, "depends_on": … }`,
171
+ using the ids that came back from step 1.
172
+
173
+ The epic keeps the record: its `body` is the why, its rounds are the discussion, its decisions are
174
+ the rules. That is what a later `/k0-discuss` on any story in this epic already has in front of
175
+ it, without going looking.
176
+
177
+ If anything fails, stop and say what got written and what did not. Do not retry blindly and do
178
+ not carry on as if the tree were complete.
179
+
180
+ ## 6. Close it
181
+
182
+ Short, in his language: the epic's key and title, how many stories, and the one to start with —
183
+ which you get from `/api/backlog/next` — asked the same way as the listing above, with
184
+ `--get --data-urlencode "repo=$REPO"` — and not from your own reading of the list.
185
+
186
+ ## Rules
187
+
188
+ - **Never write a story before he has agreed to the tree.** This is the rule the skill exists
189
+ for.
190
+ - **Everything he says is stored in the language he said it in.** Titles, bodies, decisions.
191
+ The interface stays English; his words do not get translated.
192
+ - **Never ask for what the API already knows** — keys, states, an epic's progress,
193
+ what is blocked. `rounds.md` §7 has the table.
194
+ - **Decisions are written the way `rounds.md` §5 says**, and at the ceiling the discussion stops
195
+ the way §2 says. Neither rule is repeated here, and neither is yours to soften.
196
+ - **No files outside the scratch directory**, and never a `git` command that changes anything.
@@ -0,0 +1,6 @@
1
+ {
2
+ "name": "k0-links",
3
+ "version": "0.1.0",
4
+ "author": { "name": "Alessio Ragni", "url": "https://alessioragni.com" },
5
+ "description": "While k0 is running, the addresses, folders, documents and artifacts the last reply named sit above the prompt, one click away"
6
+ }
@@ -0,0 +1 @@
1
+ { "modules": ["./register.js"] }