kadence 0.5.0 → 0.7.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
@@ -2,6 +2,192 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.7.0] — 2026-09-25
6
+
7
+ **One question over everything written down — and three fixes that had to come
8
+ first.** `kadence search` answers "what do we know about X" across tasks,
9
+ decisions, notes and documents at once. Getting there meant admitting that the
10
+ commands an agent already calls were returning answers it could not use: one
11
+ that could be forged by a note, one that read the whole journal twice on every
12
+ call, and one that returned four thousand tasks into a window that truncates at
13
+ twenty-five thousand tokens.
14
+
15
+ ### ⚠️ Upgrading — three defaults changed
16
+
17
+ Nothing was renamed or removed from `kadence schema --json`, so `kadence/v1`
18
+ stands. What a caller gets **by default** changed in three places, and a script
19
+ that assumed otherwise needs one flag:
20
+
21
+ | Was | Is | To get the old answer |
22
+ |---|---|---|
23
+ | `task list --json` carried `history` | it does not | `--fields id,label,history` |
24
+ | list commands returned everything | one page of 100 | `--limit 0` |
25
+ | `prime --json` carried full note text | capped at 2000 characters | `kadence note list --json` |
26
+
27
+ `history` was never promised there — the schema has always placed it in
28
+ `task show` — but it was emitted, and Hyrum's Law says somebody depended on it.
29
+ It is 61% of that response at 4000 tasks, which put the command past the point
30
+ where an agent's tool output is silently cut in half.
31
+
32
+ ### Added — `kadence search`
33
+
34
+ - **One query, every kind of record.** Tasks with their descriptions,
35
+ acceptance criteria and comments; decisions with their reason and the
36
+ alternative they rejected; notes; documents cut at their headings. Most of
37
+ that was unreachable by any command before this: `task list --search` covered
38
+ 24% of the journal's prose and only tasks.
39
+ - **Lexical, not semantic, and measured rather than assumed.** BM25,
40
+ hand-rolled, no dependency, over the folded projection — so labels exist
41
+ (I7), a superseded decision does not answer as though it were current, and
42
+ search cannot disagree with `task show`. An embedding model is 200 MB and
43
+ seconds of cold start against a 200 ms budget and a promise to work offline;
44
+ on a vocabulary of `ULID`, `KAD-N` and `FlowEvent` it is also the weaker
45
+ method. 26 ms a query over 829 units; 158 ms end to end (DEC-26).
46
+ - **A hit is something you can cite.** The ULID, never the derived label; the
47
+ lines a document section came from; and a quoted span whose offsets land on
48
+ the quoted text, so an agent quotes the journal instead of paraphrasing it.
49
+ - **`coverage` — how much of the question a record actually holds**, 0 to 1,
50
+ weighted by how rare each word is. Where the first hit is right this is 1.00
51
+ at the median; where it is wrong, 0.62. Below 0.7 the human output says the
52
+ passage answers part of the question. The obvious signal — the gap to the
53
+ second hit — was measured and does not work: 0.10 against 0.08 (DEC-30).
54
+ - **An empty answer, said plainly.** Below the coverage floor the result is
55
+ nothing, and the message says the journal has no answer. A model handed
56
+ passages that merely look relevant fabricates more than one handed none, so
57
+ this is a feature and not a cop-out. Nine of ten questions about things this
58
+ journal has never discussed get silence.
59
+ - **Quality is held by a test, not by hope.** `test/search-relevance.test.ts`
60
+ runs 25 real questions against the repository's own journal and fails below
61
+ recall@3 of 0.64. Three ranking ideas were measured this release and two were
62
+ removed for making it worse (DEC-27, DEC-28).
63
+
64
+ ### Fixed — `prime` could be forged, and repainted your terminal
65
+
66
+ - **A note carrying newlines rendered as sections of its own**, and the
67
+ cheapest section to forge is the `Go deeper:` block `prime` ends with. The
68
+ length was capped; the shape was not. An escape sequence went further and
69
+ cleared the screen — `prime` runs from the `SessionStart` hook without being
70
+ asked.
71
+ - **`prime --json` was unbounded.** One 200 KB note made the session preamble
72
+ 200,728 bytes. Free text is now capped at 2000 characters with `bytes`
73
+ alongside, the signal `documentation` already gave (DEC-21).
74
+
75
+ ### Fixed — a warm command read the whole journal anyway
76
+
77
+ - **`loadState` called `readAll` on every command**, purely to count corrupted
78
+ and unknown events for a warning, after the snapshot had already answered.
79
+ A warm call read all 10,103 files; a cold one read every event twice.
80
+ 345 ms to 201 ms end to end at 10k events; 204 ms to 5 ms in process.
81
+ - **The fingerprint counts bytes as well as names**, so a file rewritten in
82
+ place invalidates the cache. That also means `git checkout .kadence/` — the
83
+ remedy the corruption warning itself recommends — finally invalidates the
84
+ cache it needed to, which it never did (DEC-22).
85
+ - Every performance guardrail measured `loadOrBuild`; the CLI calls
86
+ `loadState`. The bug lived in the gap between them. Both are measured now.
87
+
88
+ ### Fixed — list commands returned the whole board
89
+
90
+ - **One page of 100, with the real total and the offset beside it.**
91
+ `task list --json` was 1.3M tokens at 4000 tasks against the 25k at which an
92
+ agent's tool output is cut — silently, so the agent answers on a fraction
93
+ while believing it saw everything. Now 50 KB. `--limit 0` returns everything;
94
+ `--offset` walks (DEC-24).
95
+ - 100 rather than 200 because this repository's own tasks run 1100 bytes each,
96
+ where the ceiling is 93.
97
+
98
+ ### Changed
99
+
100
+ - Documentation moved into the journal: 65 documents, `DOC-2` through `DOC-66`,
101
+ as `doc.written` events. `docs/` stays on disk as the working draft and links
102
+ are rewritten to `DOC-N` on publication (DEC-25). The npm package is
103
+ unaffected — `.kadence/` is not in `files`.
104
+
105
+ ## [0.6.0] — 2026-09-23
106
+
107
+ **Documentation in the journal, and an honest answer when something goes
108
+ wrong.** Two halves of the same session. Documentation stops being a filename
109
+ someone has to know and becomes an entity an agent is handed — `DOC-N`, revised,
110
+ conflict-aware. And the three places where kadence told an agent something that
111
+ was not true — a claim it had already lost, a failure with no JSON, a flag
112
+ written twice — now answer straight. The second half came out of a contract
113
+ stress audit run against 0.5.0; the report is in
114
+ `docs/research/contract-stress-audit-2026-09.md`.
115
+
116
+ ### ⚠️ Upgrading — everyone updates before anyone runs `compact`
117
+
118
+ `compact` in 0.5.0 and earlier archives the events it can parse and then removes
119
+ the whole month directory, which **deletes `doc.*` events written by 0.6.0**.
120
+ An older kadence reads the journal fine; it just must not compact it. From this
121
+ release on, `compact` leaves alone any month holding an event it cannot read.
122
+ If someone compacted with an old binary, `git status` shows the deleted event
123
+ files — restore them, do not re-run.
124
+
125
+ ### Added — documentation is an entity
126
+
127
+ - **`kadence doc`** — `add`, `edit`, `show`, `list`, `link`. A document is
128
+ `DOC-N`, stored as `doc.written` revisions in the journal rather than as an
129
+ `.md` file beside it (ADR-014, superseding that part of ADR-010). Text comes
130
+ from `--body`, `--file` or `--stdin`; `--file` reads any path and keeps
131
+ nothing (DEC-15).
132
+ - **A revision names its parents.** Two people revising the same version leave a
133
+ conflict that is reported and settled by writing text — never a silent loss.
134
+ `doc edit` with no new text on a conflicted document is refused with
135
+ `conflicting_state`, because otherwise it would keep whichever version ULID
136
+ order happened to show and nobody would have read the other.
137
+ - **Agents reach documentation without a search term.** `task show --json`
138
+ carries `documentation[]` (label, title, bytes, `updatedAt`), `prime` names the
139
+ documentation of the work you hold, and `doc list --json` carries no bodies.
140
+ One body arrives only when you ask for it with `doc show`.
141
+ - **A body past 16 KiB is written with a warning, not refused.** Agents read long
142
+ inputs measurably worse; splitting is the author's call, not ours.
143
+ - **`KADENCE_ACTOR`** names the claimant (DEC-16). Without it, an agent in a
144
+ linked worktree claims as `email#<worktree>`. A person owns what their agents
145
+ hold; an agent owns only its own.
146
+ - **`task claim` reports what actually happened** — `claim: claimed |
147
+ already_yours | contested`, read back out of the journal after the write.
148
+ Additive to `kadence/v1`.
149
+
150
+ ### Changed
151
+
152
+ - **`prime` puts contested claims first in *Yours*,** each carrying `claimedBy`
153
+ and `contestedBy`, so an agent holding a task it no longer owns sees that
154
+ before it starts working. When every claim is the person's own agents, it says
155
+ so instead: *N of your agents collided — keep one, release the rest.*
156
+ - **`task doc` stays** for linking files that already exist; new writing goes to
157
+ `kadence doc`.
158
+ - **A repeated single-value flag keeps its last value** (DEC-18). Only
159
+ `--label`, `--add-label`, `--remove-label`, `--rejected` and `--doc`
160
+ accumulate. `--title a --title b` had been storing both and reporting success.
161
+
162
+ ### Fixed — the contract, where it was quiet
163
+
164
+ - **A parser failure answers in JSON.** An unknown flag, a missing value or an
165
+ extra argument is thrown by cac before any handler runs, and it used to reach
166
+ stderr as a bare sentence with nothing on stdout — the one failure `--json`
167
+ did not cover. It now goes through `failure()`: `invalid_argument` with
168
+ `received` and `allowed`, exit 2.
169
+ - **An unknown command no longer exits 0 with both streams empty,** and a bare
170
+ `kadence` prints help instead of nothing. An exception that is not a cac error
171
+ prints its stack and exits 1, rather than being mislabelled as usage.
172
+ - **`compact` no longer deletes events it cannot parse** along with their month
173
+ directory — see Upgrading.
174
+ - **`task doc` recorded a URL as the mangled path `https:/…`** and `task doc add`
175
+ created a directory named `https:` (KAD-33).
176
+ - **`--body -` was read as a missing value and `--body 007` became `7`.**
177
+ `--stdin` is its own flag now, and text flags are read raw from argv. Two text
178
+ sources at once are refused rather than one winning silently.
179
+ - **`doc link` returned a partial document;** it returns the full shape, pinned
180
+ in the schema contract.
181
+
182
+ ### Measured
183
+
184
+ - `claim` re-reads the journal after writing: ~121 ms median at 400 events,
185
+ against ~105 ms for a plain read. An agent without `KADENCE_ACTOR` pays one
186
+ git spawn (~10 ms) in `ready`, `prime` and `claim` to detect a linked
187
+ worktree.
188
+ - `ready` and `prime` now sit at the edge of the 200 ms budget as this
189
+ repository's own journal grows. Recorded as a note, not yet as a fix.
190
+
5
191
  ## [0.5.0] — 2026-09-16
6
192
 
7
193
  **The second author.** kadence was built for a team, and until now its first
@@ -232,7 +418,7 @@ command was renamed, and `--json` responses gain keys rather than losing them.
232
418
  - **`kadence task claim` / `task release`** — take a task, or give it back.
233
419
  `claim` with no argument takes the top of `ready`, which is one step instead
234
420
  of two. There is **no lock**, and the message says so: two machines can each
235
- claim before either pushes. See [ADR-011](docs/decisions/011-claims-as-events.md).
421
+ claim before either pushes. See ADR-011.
236
422
  - **`kadence note "text" [--task KAD-1]`** and `note list` — something learned
237
423
  that was never a choice. Deliberately not a decision: no `--why`, no
238
424
  `supersedes`, no number. The help says when to reach for `decision add`
@@ -268,7 +454,7 @@ command was renamed, and `--json` responses gain keys rather than losing them.
268
454
  events fold differently depending on where they were written. A detached HEAD
269
455
  and an unknown base both fail by name rather than reporting no work.
270
456
  The measurement that justified the flag, including what would make it wrong,
271
- is in [branch-context-2026-09.md](docs/research/branch-context-2026-09.md).
457
+ is in branch-context-2026-09.md.
272
458
  - **Acceptance criteria** — `task ac add|check|uncheck|list`. The number is a
273
459
  position in the folded list, assigned like `KAD-N` and never stored, so two
274
460
  branches can each add a criterion and merge without renumbering. Moving a task
@@ -309,7 +495,7 @@ command was renamed, and `--json` responses gain keys rather than losing them.
309
495
 
310
496
  What the neighbours call reports is, here, a fold over timestamps the journal
311
497
  already carries. The reasoning, the sources and the verdict per report are in
312
- [reports-discovery-2026-09.md](docs/research/reports-discovery-2026-09.md).
498
+ reports-discovery-2026-09.md.
313
499
  Velocity and cycle time stay out of the headline; they are a consequence, served
314
500
  to the person who asks.
315
501
 
@@ -340,7 +526,7 @@ to the person who asks.
340
526
 
341
527
  Each of these was a standing "no". Each is now tried in the shape that survives
342
528
  the three constraints, and each has a kill condition written before the code, in
343
- [feature-adoption-2026-09.md](docs/product/feature-adoption-2026-09.md).
529
+ feature-adoption-2026-09.md.
344
530
 
345
531
  - **`kadence board export --html`** — the board, the sprint, the burndown,
346
532
  milestones and decisions in force, as **one self-contained file**. No script
@@ -358,7 +544,7 @@ the three constraints, and each has a kill condition written before the code, in
358
544
  trusts. A marker in the issue body makes a second publish an edit rather than
359
545
  a duplicate, and the issue itself says that edits made there are overwritten.
360
546
  Nothing is ever read back. See
361
- [ADR-012](docs/decisions/012-network-only-in-packages.md), written before the
547
+ ADR-012, written before the
362
548
  code. Every test runs against a recorded `gh`, never the real one.
363
549
  - **`kadence task doc add KAD-1 docs/design.md`** — creates the file from a
364
550
  four-line template and records the link in one call. It never overwrites: a
@@ -389,7 +575,7 @@ the three constraints, and each has a kill condition written before the code, in
389
575
  adding different labels merged without a conflict and one label vanished with
390
576
  no warning. Not a merge failure — a fold storing *state* in an event, the
391
577
  exact mistake the product exists to avoid. Reasoning in
392
- [ADR-013](docs/decisions/013-labels-as-deltas.md).
578
+ ADR-013.
393
579
  - **`labels` in `ready --json`**, the seventh field, and in the guaranteed set.
394
580
 
395
581
  Source for this slice: a tech lead's feedback of 2026-09-10 — drift comes not
@@ -576,7 +762,7 @@ is additive within `kadence/v1`, which the contract permits at any version.
576
762
  The journal held what happened. It now holds **why** — and the reasoning cannot
577
763
  quietly go stale, because superseding a decision is one event rather than two
578
764
  edits somebody has to remember to make. Reasoning in
579
- [ADR-010](docs/decisions/010-decisions-as-events.md).
765
+ ADR-010.
580
766
 
581
767
  ### Added
582
768
 
@@ -601,7 +787,7 @@ edits somebody has to remember to make. Reasoning in
601
787
  explains this task, and that is the only thing recorded. A missing file is a
602
788
  warning, not a refusal — it may arrive in a later commit.
603
789
 
604
- Measured before building ([Probe D](docs/research/probe-d-docs-linkage.md)):
790
+ Measured before building (Probe D):
605
791
  across five real questions, grep finds the answering document every time and
606
792
  buries it among 10–35 candidates. The link saves the sifting, not the search.
607
793
 
@@ -672,8 +858,8 @@ published package rather than the source.
672
858
  The agent contract, made real. `schema: "kadence/v1"` used to be a version
673
859
  string that nothing checked; now the contract is published, the failures are
674
860
  machine-readable, and the responses can be narrowed to what an agent actually
675
- reads. Reasoning in [ADR-009](docs/decisions/009-the-agent-contract.md),
676
- measurements in [Probe C](docs/research/probe-c-agent-cost.md).
861
+ reads. Reasoning in ADR-009,
862
+ measurements in Probe C.
677
863
 
678
864
  ### Added
679
865
 
@@ -744,7 +930,7 @@ asked for.
744
930
  - Developer tooling (`.claude/`, `.serena/`) is no longer committed: 381 files
745
931
  and 3.8 MB of it, against 94 files of actual product. What belongs in git and
746
932
  what does not is written down in
747
- [ADR-007](docs/decisions/007-what-goes-into-git.md), and `.gitignore` now
933
+ ADR-007, and `.gitignore` now
748
934
  also covers `.env`, coverage output and editor leftovers.
749
935
 
750
936
  ## [0.1.3] — 2026-09-03
package/README.md CHANGED
@@ -56,7 +56,7 @@ reads the same thing as JSON.
56
56
  **And it stays one call.** That answer stays under a kilobyte whether the project
57
57
  holds ten tasks or a thousand — while the journal behind it grows from 5 KB to
58
58
  528 KB. The cost of asking does not grow with the history that makes the answer
59
- worth having. [Measured](docs/research/probe-c-agent-cost.md) at 948 bytes in
59
+ worth having. Measured at 948 bytes in
60
60
  0.2; 982 bytes at 0.4, after claims and acceptance criteria joined every record.
61
61
 
62
62
  ## Why events and not files
@@ -102,7 +102,9 @@ merged in every order. Zero conflicts, every author preserved, identical final
102
102
  state. That is an [integration test](test/integration/merge.test.ts), not a
103
103
  claim.
104
104
 
105
- Full data: [probe-a-results.md](docs/research/probe-a-results.md).
105
+ The measurement itself is a working paper and is not published (see
106
+ `.gitignore`); the mechanism it measures is proved here by
107
+ `test/integration/merge.test.ts`.
106
108
 
107
109
  ---
108
110
 
@@ -187,7 +189,7 @@ kadence task list --branch
187
189
 
188
190
  Nothing is stored for that: which tasks belong to a branch lives in git's
189
191
  history and is read when you ask. It narrows the answer between three and
190
- twenty times, [measured](docs/research/branch-context-2026-09.md) on real board
192
+ twenty times, measured on real board
191
193
  sizes.
192
194
 
193
195
  ### Also in the box
@@ -198,8 +200,8 @@ columns, reports folded from the same journal (`report flow`, `cfd`,
198
200
  `attention`; burndown, velocity and workload are in the repository and not yet
199
201
  on npm), a self-contained HTML or Markdown export, `compact` for long journals,
200
202
  and shell completion. None of it is required, and none of it is the point —
201
- it is what the journal happens to know. Commands and caveats:
202
- [docs/reports.md](docs/reports.md), and `--help` on each command.
203
+ it is what the journal happens to know. `--help` on each command is the
204
+ reference, and `kadence doc list` is what the journal knows about itself.
203
205
 
204
206
  ### Removing kadence
205
207
 
@@ -257,7 +259,7 @@ documentation can tell an agent what yours are.
257
259
 
258
260
  There is no MCP wrapper, and one gets built only as an **optional package**, when
259
261
  someone who cannot run a CLI asks for it: it costs about 700 tokens a session
260
- over the CLI path — [we measured it](docs/research/probe-c-agent-cost.md), and it
262
+ over the CLI path — we measured it, and it
261
263
  is not the saving the industry benchmarks suggest — it would be a second way to
262
264
  say the same thing, and it would not work for agents that have no MCP client at
263
265
  all.
@@ -292,9 +294,23 @@ no number, and `prime` shows the latest:
292
294
  kadence note "The staging clock runs 40 s behind" --task KAD-1
293
295
  ```
294
296
 
295
- Documents stay plain markdown — `kadence task doc add KAD-1 docs/design.md`
296
- records only the link, which is the part git cannot express. If the file does
297
- not exist it is created from a template; an existing one is never overwritten.
297
+ **Documentation lives in the journal too.** How something works now, revised as
298
+ it changes — an entity, `DOC-N`, not a filename an agent has to guess:
299
+
300
+ ```bash
301
+ kadence doc add "How auth works" --file notes/auth.md --task KAD-1
302
+ kadence doc show DOC-1 --json
303
+ ```
304
+
305
+ A revision names the revisions it was written on top of, so two people editing
306
+ the same version leave a conflict that is reported and settled by writing text,
307
+ never a silent overwrite. Agents are handed it without searching: `task show`
308
+ carries `documentation[]` and `prime` names the documentation of the work you
309
+ hold — both without bodies, so the body arrives only when asked for.
310
+
311
+ A markdown file that already exists is still linked, not swallowed:
312
+ `kadence task doc add KAD-1 docs/design.md` records the link, which is the part
313
+ git cannot express.
298
314
 
299
315
  Bulk works everywhere and is all or nothing: `kadence task move KAD-1,KAD-2 done`
300
316
  either moves both or changes nothing. A typo does not leave half a board.
@@ -320,16 +336,16 @@ true.
320
336
 
321
337
  **Verified.** The merge thesis, on real git branches. Performance and size, by
322
338
  tests that fail if they regress. That the conflict problem exists in the wild —
323
- measured, not assumed. 998 tests in the repository today, including an
339
+ measured, not assumed. 1060 tests in the repository today, including an
324
340
  end-to-end run through the installed binary.
325
341
 
326
342
  **Not verified.** That teams and their AI agents actually lose enough context to want
327
343
  this. The bet rests on reasoning and on the industry naming the problem out
328
344
  loud — not on our own users. That research, Probe B, is
329
- [designed](docs/research/interview-script.md) and not yet run: as of
330
- 2026-09-16, [zero conversations](docs/research/probe-b-results.md) and no
331
- external users. [The strategy](docs/product/strategy.md) says what happens next
332
- and on which dates.
345
+ designed and not yet run: as of
346
+ 2026-09-16, zero conversations and no external users. What happens next, and
347
+ on which dates, is recorded in this repository's own journal — `kadence
348
+ decision list` and `kadence note list`.
333
349
 
334
350
  **Not built, on purpose.** An MCP package — only if someone who cannot run a CLI
335
351
  asks for it, not as an inevitability.
@@ -368,13 +384,16 @@ branches writing at once produce two different files, and git merges them
368
384
  without a conflict by construction.
369
385
 
370
386
  Design decisions, each recording what was measured and what would make us
371
- revisit it: [docs/decisions/](docs/decisions/).
387
+ revisit it, are in the journal that ships with this repository — `kadence
388
+ decision list`, or `kadence decision show DEC-3` for one in full. The longer
389
+ write-ups behind them are working papers and are kept out of git on purpose;
390
+ the decision, its reason and the alternatives that lost are in the events.
372
391
 
373
392
  ## Contributing
374
393
 
375
394
  ```bash
376
395
  npm install
377
- npm test # 998 tests; builds dist/cli.js first
396
+ npm test # 1060 tests; builds dist/cli.js first
378
397
  npm run typecheck
379
398
  npm run build # one 111 KB bundle, blessed kept external (82 KB at 0.4.1)
380
399
  ```
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{p as G}from"./chunk-CDGGOWGY.js";import S from"blessed";var c={border:"gray",borderFocus:"cyan",headerFg:"white",headerBg:"blue",selectedFg:"black",selectedBg:"cyan",dim:"gray",hint:"gray",warn:"yellow",danger:"red"},he={backlog:"gray",todo:"white",in_progress:"blue",doing:"blue",blocked:"red",in_review:"magenta",review:"magenta",done:"green",shipped:"green"};function ne(n){return he[n]??"white"}var pe={urgent:"\u203C",high:"\u2191",normal:" ",low:"\u2193"},me={urgent:"red",high:"yellow",normal:"white",low:"gray"},ye={bug:"\u2716",story:"\u25C6",epic:"\u2B22",task:"\xB7"};function k(n,s){return`{${s}-fg}${n}{/}`}function W(n,s){let d=k(pe[n.priority],me[n.priority]),p=k(ye[n.type]??"\xB7","gray"),h=k(n.label,"cyan"),g=[];n.blockedBy.length>0&&g.push(k("\u2298","red")),n.contestedBy.length>0?g.push(k("\u2691","magenta")):n.claimedBy!==null&&g.push(k("\u2713","green"));let E=n.criteria.filter(O=>!O.checked).length;if(E>0?g.push(k(`${n.criteria.length-E}/${n.criteria.length}`,"yellow")):n.criteria.length>0&&g.push(k("\u2611","green")),n.comments.length>0&&g.push(k("\u{1F4AC}","gray")),n.due!==null){let O=n.due<new Date().toISOString().slice(0,10);g.push(k(O?"\u23F0":"\u{1F4C5}",O?"red":"gray"))}let C=[n.assignee!==null?k(`@${n.assignee.split("@")[0]}`,"gray"):"",n.estimate!==null?k(String(n.estimate),"yellow"):"",g.join("")].filter(O=>O.length>0).join(" "),m=`${Y(d)}${Y(p)} ${Y(h)} `,b=C.length>0?` ${Y(C)}`:"",T=Math.max(4,s-m.length-b.length),F=[...n.title],q=F.length>T?`${F.slice(0,T-1).join("")}\u2026`:n.title;return`${d}${p} ${h} ${q}${C.length>0?` ${C}`:""}`}function z(n,s){return s?`{cyan-bg}{black-fg}${Y(n)}{/}`:` ${n}`}function J(n,s,d,p=12){let h=`${n.padEnd(p)} ${s}`;return d?`{cyan-bg}{black-fg}\u25B8 ${h}{/}`:` ${h}`}function Y(n){return n.replace(/\{[^}]*\}/g,"")}var re=["\u2190\u2192\u2191\u2193 move","enter details","[ ] shift","m status","a assign","c comment","e edit","n new","s sprint","/ filter","R ready","b branch","M milestone","C claim","? help","q quit (Ctrl-C forces)"].join(" ");function se(n){let s=[],d=!1;function p(){d=!0,setImmediate(()=>{d=!1})}return{dispatch(h){if(d)return;let g=s[s.length-1];g!==void 0?g(h):n(h)},push(h){s.push(h),p();let g=!1;return()=>{if(g)return;g=!0;let E=s.lastIndexOf(h);E!==-1&&s.splice(E,1),p()}},isDialogOpen:()=>s.length>0,depth:()=>s.length}}function oe(n){if(n.ch==="")return!1;let s=n.ch.charCodeAt(0);return s<32||s===127}var be=["up","down","pageup","pagedown","home","end"],ie=["escape","q"];function Q(n){return be.includes(n.name)}function le(n){return ie.includes(n.name)||ie.includes(n.ch)}function _(n,s,d){return d===0?0:(n+s+d)%d}var ae="cancelled",we="done";function ve(n){let s=[`${n.open} open`,`${n.ready} ready`,`${n.decisions} ${n.decisions===1?"decision":"decisions"} in force`,...n.points===null?[]:[`${n.points} points`]];return`kadence ${n.sprint===null?"":`${n.sprint} `}${s.join(" \xB7 ")}${n.filterNote}`}function Ie(n){let s=S.screen({smartCSR:!0,title:"kadence",fullUnicode:!0,mouse:!0}),{state:d}=n.reload(),p=n.branchEventIds(),h="",g=!1,E=!1,C="",m=[],b=0,T=se(t=>ge(t));function F(t=0){try{s.destroy()}catch{}process.exit(t)}process.on("SIGINT",()=>F(0)),process.on("SIGTERM",()=>F(0)),s.program.on("keypress",(t,r)=>{let i={ch:t??"",name:r?.name??""};(i.name==="C-c"||i.ch==="")&&F(0),!(oe(i)&&i.name!=="enter"&&i.name!=="escape")&&T.dispatch(i)});let q=S.box({parent:s,top:0,height:1,width:"100%",tags:!0,style:{fg:c.headerFg,bg:c.headerBg}}),O=S.box({parent:s,bottom:0,height:1,width:"100%",tags:!0,content:` ${re}`,style:{fg:c.hint}}),V=S.box({parent:s,bottom:1,height:1,width:"100%",tags:!0,style:{fg:c.warn}});function w(t,r=c.warn){V.setContent(` ${t}`),V.style.fg=r,s.render()}function A(){let t=d.statuses.filter(i=>i!==ae),r=d.orphanStatuses.filter(i=>i!==ae);return[...t,...r]}function de(t){let r=h.toLowerCase(),i=g?new Set(G(d.tasks,{viewer:n.actor,statuses:d.statuses,started:d.started}).map(a=>a.id)):null,e=E&&!("reason"in p)?p:null,o=e===null?null:a=>e.ids.has(a.id)||a.history.some(l=>e.ids.has(l.id)),u=C===""?null:d.milestones.find(a=>a.label===C)?.id??null;return d.tasks.filter(a=>a.status===t&&(i===null||i.has(a.id))&&(o===null||o(a))&&(u===null||a.milestone===u)&&(r===""||a.title.toLowerCase().includes(r)||(a.assignee??"").toLowerCase().includes(r)||a.labels.some(l=>l.toLowerCase().includes(r))))}function X(){for(let i of m)i.box.destroy();m=[];let t=A(),r=Math.max(Math.floor(100/Math.max(t.length,1)),12);t.forEach((i,e)=>{let o=S.box({parent:s,top:1,left:`${e*r}%`,width:`${r}%`,bottom:2,label:` ${i} `,border:{type:"line"},style:{border:{fg:c.border},label:{fg:ne(i)}}}),u=S.list({parent:o,top:0,left:0,right:0,bottom:0,keys:!1,mouse:!1,interactive:!1,tags:!0,scrollable:!0,style:{selected:{fg:c.selectedFg,bg:c.selectedBg},item:{fg:"white"}}});m.push({status:i,box:o,list:u,tasks:[],cursor:0})})}function y(t=!1){t&&(d=n.reload().state,p=n.branchEventIds()),m.length!==A().length&&X();let r=0,i=0,e=!1;m.forEach((l,N)=>{l.tasks=de(l.status),l.status!==we&&(r+=l.tasks.length,i+=l.tasks.reduce((R,M)=>R+(M.estimate??0),0)),l.tasks.some(R=>R.estimate!==null)&&(e=!0);let U=l.box.width-4;l.cursor=Math.min(l.cursor,Math.max(0,l.tasks.length-1)),l.list.setItems(l.tasks.map((R,M)=>z(W(R,U),N===b&&M===l.cursor)));let L=l.tasks.reduce((R,M)=>R+(M.estimate??0),0);l.box.setLabel(` ${l.status} (${l.tasks.length}${L>0?`, ${L}`:""}) `),l.box.style.border.fg=N===b?c.borderFocus:c.border});let o=d.sprints.find(l=>l.status==="active"),u=(h===""?"":` filter: "${h}"`)+(g?" ready only":"")+(E&&!("reason"in p)?` branch: ${p.name}`:"")+(C===""?"":` milestone: ${C}`),a=G(d.tasks,{viewer:n.actor,statuses:d.statuses,started:d.started}).length;q.setContent(` ${ve({sprint:o===void 0?null:o.name,open:r,ready:a,decisions:d.decisions.filter(l=>l.supersededBy===null).length,points:e?i:null,filterNote:u})}`),d.cycles.length>0&&w(`${d.cycles.length} dependency cycle(s) \u2014 see kadence task list`,c.danger),s.render()}function I(){let t=m[b];return t?.tasks[t.cursor]}function Z(){m.forEach((t,r)=>{let i=t.box.width-4;t.list.setItems(t.tasks.map((e,o)=>z(W(e,i),r===b&&o===t.cursor))),t.box.style.border.fg=r===b?c.borderFocus:c.border}),s.render()}function x(t){t!==null?w(t,c.warn):w(""),y(!0)}function K(t,r,i){let e=T.push(()=>{}),o=S.prompt({parent:s,top:"center",left:"center",width:"60%",height:7,border:{type:"line"},style:{border:{fg:c.borderFocus}},keys:!0,mouse:!0});o.input(t,r,(u,a)=>{o.destroy(),e(),s.render(),typeof a=="string"&&i(a.trim())})}function ue(t){let r=S.box({parent:s,top:"center",left:"center",width:"75%",height:"80%",border:{type:"line"},label:` ${t.label} `,style:{border:{fg:c.borderFocus}},tags:!0,keys:!0,mouse:!0}),i=[{key:"title",label:"title",value:()=>t.title,hint:"Title:"},{key:"description",label:"description",value:()=>(t.description??"\u2014").split(`
2
+ import{q as G}from"./chunk-CR5YON2J.js";import S from"blessed";var c={border:"gray",borderFocus:"cyan",headerFg:"white",headerBg:"blue",selectedFg:"black",selectedBg:"cyan",dim:"gray",hint:"gray",warn:"yellow",danger:"red"},he={backlog:"gray",todo:"white",in_progress:"blue",doing:"blue",blocked:"red",in_review:"magenta",review:"magenta",done:"green",shipped:"green"};function ne(n){return he[n]??"white"}var pe={urgent:"\u203C",high:"\u2191",normal:" ",low:"\u2193"},me={urgent:"red",high:"yellow",normal:"white",low:"gray"},ye={bug:"\u2716",story:"\u25C6",epic:"\u2B22",task:"\xB7"};function k(n,s){return`{${s}-fg}${n}{/}`}function W(n,s){let d=k(pe[n.priority],me[n.priority]),p=k(ye[n.type]??"\xB7","gray"),h=k(n.label,"cyan"),g=[];n.blockedBy.length>0&&g.push(k("\u2298","red")),n.contestedBy.length>0?g.push(k("\u2691","magenta")):n.claimedBy!==null&&g.push(k("\u2713","green"));let E=n.criteria.filter(O=>!O.checked).length;if(E>0?g.push(k(`${n.criteria.length-E}/${n.criteria.length}`,"yellow")):n.criteria.length>0&&g.push(k("\u2611","green")),n.comments.length>0&&g.push(k("\u{1F4AC}","gray")),n.due!==null){let O=n.due<new Date().toISOString().slice(0,10);g.push(k(O?"\u23F0":"\u{1F4C5}",O?"red":"gray"))}let C=[n.assignee!==null?k(`@${n.assignee.split("@")[0]}`,"gray"):"",n.estimate!==null?k(String(n.estimate),"yellow"):"",g.join("")].filter(O=>O.length>0).join(" "),m=`${Y(d)}${Y(p)} ${Y(h)} `,b=C.length>0?` ${Y(C)}`:"",T=Math.max(4,s-m.length-b.length),F=[...n.title],q=F.length>T?`${F.slice(0,T-1).join("")}\u2026`:n.title;return`${d}${p} ${h} ${q}${C.length>0?` ${C}`:""}`}function z(n,s){return s?`{cyan-bg}{black-fg}${Y(n)}{/}`:` ${n}`}function J(n,s,d,p=12){let h=`${n.padEnd(p)} ${s}`;return d?`{cyan-bg}{black-fg}\u25B8 ${h}{/}`:` ${h}`}function Y(n){return n.replace(/\{[^}]*\}/g,"")}var re=["\u2190\u2192\u2191\u2193 move","enter details","[ ] shift","m status","a assign","c comment","e edit","n new","s sprint","/ filter","R ready","b branch","M milestone","C claim","? help","q quit (Ctrl-C forces)"].join(" ");function se(n){let s=[],d=!1;function p(){d=!0,setImmediate(()=>{d=!1})}return{dispatch(h){if(d)return;let g=s[s.length-1];g!==void 0?g(h):n(h)},push(h){s.push(h),p();let g=!1;return()=>{if(g)return;g=!0;let E=s.lastIndexOf(h);E!==-1&&s.splice(E,1),p()}},isDialogOpen:()=>s.length>0,depth:()=>s.length}}function oe(n){if(n.ch==="")return!1;let s=n.ch.charCodeAt(0);return s<32||s===127}var be=["up","down","pageup","pagedown","home","end"],ie=["escape","q"];function Q(n){return be.includes(n.name)}function le(n){return ie.includes(n.name)||ie.includes(n.ch)}function _(n,s,d){return d===0?0:(n+s+d)%d}var ae="cancelled",we="done";function ve(n){let s=[`${n.open} open`,`${n.ready} ready`,`${n.decisions} ${n.decisions===1?"decision":"decisions"} in force`,...n.points===null?[]:[`${n.points} points`]];return`kadence ${n.sprint===null?"":`${n.sprint} `}${s.join(" \xB7 ")}${n.filterNote}`}function Ie(n){let s=S.screen({smartCSR:!0,title:"kadence",fullUnicode:!0,mouse:!0}),{state:d}=n.reload(),p=n.branchEventIds(),h="",g=!1,E=!1,C="",m=[],b=0,T=se(t=>ge(t));function F(t=0){try{s.destroy()}catch{}process.exit(t)}process.on("SIGINT",()=>F(0)),process.on("SIGTERM",()=>F(0)),s.program.on("keypress",(t,r)=>{let i={ch:t??"",name:r?.name??""};(i.name==="C-c"||i.ch==="")&&F(0),!(oe(i)&&i.name!=="enter"&&i.name!=="escape")&&T.dispatch(i)});let q=S.box({parent:s,top:0,height:1,width:"100%",tags:!0,style:{fg:c.headerFg,bg:c.headerBg}}),O=S.box({parent:s,bottom:0,height:1,width:"100%",tags:!0,content:` ${re}`,style:{fg:c.hint}}),V=S.box({parent:s,bottom:1,height:1,width:"100%",tags:!0,style:{fg:c.warn}});function w(t,r=c.warn){V.setContent(` ${t}`),V.style.fg=r,s.render()}function A(){let t=d.statuses.filter(i=>i!==ae),r=d.orphanStatuses.filter(i=>i!==ae);return[...t,...r]}function de(t){let r=h.toLowerCase(),i=g?new Set(G(d.tasks,{viewer:n.actor,statuses:d.statuses,started:d.started}).map(a=>a.id)):null,e=E&&!("reason"in p)?p:null,o=e===null?null:a=>e.ids.has(a.id)||a.history.some(l=>e.ids.has(l.id)),u=C===""?null:d.milestones.find(a=>a.label===C)?.id??null;return d.tasks.filter(a=>a.status===t&&(i===null||i.has(a.id))&&(o===null||o(a))&&(u===null||a.milestone===u)&&(r===""||a.title.toLowerCase().includes(r)||(a.assignee??"").toLowerCase().includes(r)||a.labels.some(l=>l.toLowerCase().includes(r))))}function X(){for(let i of m)i.box.destroy();m=[];let t=A(),r=Math.max(Math.floor(100/Math.max(t.length,1)),12);t.forEach((i,e)=>{let o=S.box({parent:s,top:1,left:`${e*r}%`,width:`${r}%`,bottom:2,label:` ${i} `,border:{type:"line"},style:{border:{fg:c.border},label:{fg:ne(i)}}}),u=S.list({parent:o,top:0,left:0,right:0,bottom:0,keys:!1,mouse:!1,interactive:!1,tags:!0,scrollable:!0,style:{selected:{fg:c.selectedFg,bg:c.selectedBg},item:{fg:"white"}}});m.push({status:i,box:o,list:u,tasks:[],cursor:0})})}function y(t=!1){t&&(d=n.reload().state,p=n.branchEventIds()),m.length!==A().length&&X();let r=0,i=0,e=!1;m.forEach((l,N)=>{l.tasks=de(l.status),l.status!==we&&(r+=l.tasks.length,i+=l.tasks.reduce((R,M)=>R+(M.estimate??0),0)),l.tasks.some(R=>R.estimate!==null)&&(e=!0);let U=l.box.width-4;l.cursor=Math.min(l.cursor,Math.max(0,l.tasks.length-1)),l.list.setItems(l.tasks.map((R,M)=>z(W(R,U),N===b&&M===l.cursor)));let L=l.tasks.reduce((R,M)=>R+(M.estimate??0),0);l.box.setLabel(` ${l.status} (${l.tasks.length}${L>0?`, ${L}`:""}) `),l.box.style.border.fg=N===b?c.borderFocus:c.border});let o=d.sprints.find(l=>l.status==="active"),u=(h===""?"":` filter: "${h}"`)+(g?" ready only":"")+(E&&!("reason"in p)?` branch: ${p.name}`:"")+(C===""?"":` milestone: ${C}`),a=G(d.tasks,{viewer:n.actor,statuses:d.statuses,started:d.started}).length;q.setContent(` ${ve({sprint:o===void 0?null:o.name,open:r,ready:a,decisions:d.decisions.filter(l=>l.supersededBy===null).length,points:e?i:null,filterNote:u})}`),d.cycles.length>0&&w(`${d.cycles.length} dependency cycle(s) \u2014 see kadence task list`,c.danger),s.render()}function I(){let t=m[b];return t?.tasks[t.cursor]}function Z(){m.forEach((t,r)=>{let i=t.box.width-4;t.list.setItems(t.tasks.map((e,o)=>z(W(e,i),r===b&&o===t.cursor))),t.box.style.border.fg=r===b?c.borderFocus:c.border}),s.render()}function x(t){t!==null?w(t,c.warn):w(""),y(!0)}function K(t,r,i){let e=T.push(()=>{}),o=S.prompt({parent:s,top:"center",left:"center",width:"60%",height:7,border:{type:"line"},style:{border:{fg:c.borderFocus}},keys:!0,mouse:!0});o.input(t,r,(u,a)=>{o.destroy(),e(),s.render(),typeof a=="string"&&i(a.trim())})}function ue(t){let r=S.box({parent:s,top:"center",left:"center",width:"75%",height:"80%",border:{type:"line"},label:` ${t.label} `,style:{border:{fg:c.borderFocus}},tags:!0,keys:!0,mouse:!0}),i=[{key:"title",label:"title",value:()=>t.title,hint:"Title:"},{key:"description",label:"description",value:()=>(t.description??"\u2014").split(`
3
3
  `)[0]??"\u2014",hint:"Description (one line here, e for $EDITOR):"},{key:"status",label:"status",value:()=>t.status,hint:`Status (${A().join(", ")}):`},{key:"type",label:"type",value:()=>t.type,hint:"Type (task, bug, story, epic):"},{key:"priority",label:"priority",value:()=>t.priority,hint:"Priority (low, normal, high, urgent):"},{key:"assignee",label:"assignee",value:()=>t.assignee??"\u2014",hint:'Assignee (or "none"):'},{key:"estimate",label:"estimate",value:()=>t.estimate===null?"\u2014":String(t.estimate),hint:"Estimate in points:"},{key:"due",label:"due",value:()=>t.due??"\u2014",hint:"Due date YYYY-MM-DD (empty clears):"},{key:"labels",label:"labels",value:()=>t.labels.length>0?t.labels.join(", "):"\u2014",hint:"Labels, comma separated:"}],e=()=>[...i.map((v,f)=>({kind:"field",index:f})),...t.criteria.map(v=>({kind:"criterion",n:v.n}))],o=S.list({parent:r,top:0,left:1,right:1,height:i.length+t.criteria.length,keys:!1,mouse:!1,interactive:!1,tags:!0,style:{selected:{fg:c.selectedFg,bg:c.selectedBg}}}),u=0,a=S.box({parent:r,top:i.length+t.criteria.length+1,left:1,right:1,bottom:0,tags:!0,scrollable:!0});function l(){o.setItems(e().map((f,B)=>f.kind==="field"?J(i[f.index].label,i[f.index].value(),B===u):J(` ${f.n}.`,`[${t.criteria.find($=>$.n===f.n)?.checked===!0?"x":" "}] ${t.criteria.find($=>$.n===f.n)?.text??""}`,B===u)));let v=[t.blockedBy.length>0?`{red-fg}blocked by ${t.blockedBy.length} task(s){/}`:"",t.parent!==null?"{gray-fg}has a parent{/}":"",t.loggedHours>0?`{gray-fg}logged ${t.loggedHours.toFixed(1)}h{/}`:"","",t.description!==null&&t.description.includes(`
4
4
  `)?`{gray-fg}${t.description.split(`
5
5
  `).slice(1).join(`
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ var F=["backlog","todo","in_progress","blocked","in_review","done","cancelled"],x="done",S="cancelled",$="in_progress",Y="backlog",ot=["task","bug","story","epic"],at=["low","normal","high","urgent"];function lt(t){let e=m(t.data?.title),s=t.data?.body,u=t.data?.parents;return e===null||typeof s!="string"||s.trim().length===0||!Array.isArray(u)?null:{title:e,body:s,parents:u.filter(l=>typeof l=="string")}}function dt(t,e,s){let u=[];for(let[l,a]of t){let r=a.filter((c,h)=>a.findIndex(k=>k.id===c.id)===h).map(c=>({e:c,r:lt(c)})).filter(c=>c.r!==null);if(r.length===0)continue;let d=new Set(r.flatMap(c=>c.r.parents)),i=r.filter(c=>!d.has(c.e.id));i.length===0&&(i=[r[r.length-1]]);let f=i[i.length-1],y=r[0];u.push({id:l,label:"",title:f.r.title,body:f.r.body,tasks:(e.get(l)??[]).filter(c=>s.has(c)),revision:f.e.id,revisions:r.length,conflicts:i.slice(0,-1).map(c=>({revision:c.e.id,title:c.r.title,body:c.r.body,at:c.e.ts,by:c.e.actor,source:c.e.source})),createdAt:y.e.ts,createdBy:y.e.actor,updatedAt:f.e.ts,updatedBy:f.e.actor,source:f.e.source})}return u.sort((l,a)=>l.id<a.id?-1:1),u.forEach((l,a)=>{l.label=`DOC-${a+1}`}),u}function L(t,e){for(let s=t.length-1;s>=0;s--)if(t[s].id<e)return t[s].started;return $}function wt(t){let e=[...t].sort((n,o)=>n.id<o.id?-1:n.id>o.id?1:0),s=new Map,u=new Map,l=new Map,a=new Map,p=new Map,r=[],d=new Map,i=new Map,f=null,y=[],c={started:$,changes:[]},h=[],k=[];for(let n of e)n.type==="task.created"?z(s,n):n.type==="sprint.created"?G(u,n):n.type==="milestone.created"&&J(l,n);for(let n of e){if(n.type==="decision.recorded"){let o=n.data??{},g=A=>typeof o[A]=="string"&&o[A].length>0?o[A]:null,b=g("title"),v=g("why");b!==null&&v!==null&&p.set(n.id,{id:n.id,label:"",title:b,why:v,rejected:g("rejected"),task:g("task"),docs:Array.isArray(o.docs)?o.docs.filter(A=>typeof A=="string"):[],supersedes:g("supersedes"),supersededBy:null,at:n.ts,by:n.actor,source:n.source});continue}if(n.type==="note.recorded"){let o=m(n.data?.text);o!==null&&r.push({id:n.id,text:o,task:m(n.data?.task),at:n.ts,by:n.actor,source:n.source});continue}if(n.type==="doc.written"){let o=d.get(n.entity)??[];o.push(n),d.set(n.entity,o);continue}if(n.type==="doc.linked"){let o=m(n.data?.task);if(o!==null){let g=i.get(n.entity)??[];g.includes(o)||g.push(o),i.set(n.entity,g)}continue}if(n.type==="template.saved"){let o=typeof n.data?.name=="string"?n.data.name:null;o!==null&&a.set(o,{name:o,fields:n.data?.fields??{},author:n.actor});continue}if(n.type==="board.configured"){let o=n.data?.statuses;if(Array.isArray(o)){let v=o.filter(A=>typeof A=="string"&&A.length>0);v.length>0&&(f=v)}let g=n.data?.dod;Array.isArray(g)&&(y=g.filter(v=>typeof v=="string"&&v.length>0));let b=m(n.data?.started);b!==null&&(c.started=b,c.changes.push({id:n.id,started:b}));continue}if(n.type==="template.deleted"){let o=typeof n.data?.name=="string"?n.data.name:null;o!==null&&a.delete(o);continue}ut(n,s,u,l,h,k,c)}let w=k,T=[...s.values()].sort((n,o)=>n.id<o.id?-1:1);T.forEach((n,o)=>{n.label=`KAD-${o+1}`,ft(n),n.criteria.sort((g,b)=>g.id<b.id?-1:1),n.criteria.forEach((g,b)=>{g.n=b+1}),ct(n)});let M=new Set(T.map(n=>n.id));for(let n of T)n.parent!==null&&!M.has(n.parent)&&(n.parent=null),n.blockedBy=n.blockedBy.filter(o=>M.has(o));let B=[...p.values()].sort((n,o)=>n.id<o.id?-1:1);B.forEach((n,o)=>{n.label=`DEC-${o+1}`});for(let n of B){if(n.supersedes===null)continue;let o=p.get(n.supersedes);o!==void 0&&(o.supersededBy=n.id)}let C=[...l.values()].sort((n,o)=>n.id<o.id?-1:1);C.forEach((n,o)=>{n.label=`MS-${o+1}`});let R=new Map;for(let n of T){if(n.milestone===null||!l.has(n.milestone))continue;let o=R.get(n.milestone)??[];o.push(n.id),R.set(n.milestone,o)}for(let n of C){n.taskIds=R.get(n.id)??[];let o=n.taskIds.map(g=>s.get(g)).filter(g=>g!==void 0);n.totalTasks=o.length,n.doneTasks=o.filter(g=>g.status===x).length,n.totalPoints=o.reduce((g,b)=>g+(b.estimate??0),0),n.donePoints=o.filter(g=>g.status===x).reduce((g,b)=>g+(b.estimate??0),0)}for(let n of B)n.task!==null&&!M.has(n.task)&&(n.task=null);for(let n of r)n.task!==null&&!M.has(n.task)&&(n.task=null);let K=dt(d,i,M);return{tasks:T,decisions:B,documents:K,milestones:C,notes:r,sprints:[...u.values()].sort((n,o)=>n.id<o.id?-1:1),statuses:f??[...F],dod:y,started:c.started,startedChanges:[...c.changes],orphanStatuses:[...new Set(T.map(n=>n.status).filter(n=>!(f??F).includes(n)))].sort(),templates:[...a.values()].sort((n,o)=>n.name.localeCompare(o.name)),cycles:pt(T),pending:w,rejected:h}}function z(t,e){if(t.has(e.entity))return;let s=e.data??{};t.set(e.entity,{id:e.entity,label:"",title:typeof s.title=="string"?s.title:"(untitled)",description:m(s.description),type:Q(s.type),priority:V(s.priority),status:Y,labels:X(s.labels),assignee:m(s.assignee),reporter:e.actor,sprint:null,milestone:null,parent:m(s.parent),blockedBy:[],due:m(s.due),claimedBy:null,claimedAt:null,claimedEventId:null,contestedBy:[],criteria:[],comments:[],docs:[],estimate:typeof s.estimate=="number"?s.estimate:null,loggedHours:0,createdAt:e.ts,updatedAt:e.ts,history:[]})}function G(t,e){if(t.has(e.entity))return;let s=e.data??{};t.set(e.entity,{id:e.entity,name:typeof s.name=="string"?s.name:"(untitled)",description:m(s.description),startDate:m(s.startDate),endDate:m(s.endDate),status:"planned",closedBy:null,taskIds:[]})}function J(t,e){if(t.has(e.entity))return;let s=e.data??{};t.set(e.entity,{id:e.entity,label:"",name:typeof s.name=="string"?s.name:"(untitled)",due:m(s.due),status:"open",closedBy:null,taskIds:[],donePoints:0,totalPoints:0,doneTasks:0,totalTasks:0})}function ut(t,e,s,u,l,a,p){let r=t.data??{};if(t.type==="milestone.created")return J(u,t),!0;if(t.type==="milestone.task_added"){let i=m(r.task);if(i===null)return!0;let f=e.get(i);return f===void 0?(a.push(t),!1):(f.milestone=t.entity,!0)}if(t.type==="milestone.closed"){let i=u.get(t.entity);return i===void 0?(a.push(t),!1):(i.closedBy===null?(i.status="closed",i.closedBy=t.id):l.push(t),!0)}if(t.type==="task.created")return z(e,t),H(e.get(t.entity),t),!0;if(t.type==="sprint.created")return G(s,t),!0;if(t.type.startsWith("sprint.")){let i=s.get(t.entity);if(i===void 0)return a.push(t),!1;if(t.type==="sprint.started")return i.status==="planned"&&(i.status="active"),!0;if(t.type==="sprint.updated")return i.status==="closed"?(l.push(t),!0):(typeof r.name=="string"&&(i.name=r.name),r.description!==void 0&&(i.description=m(r.description)),r.startDate!==void 0&&(i.startDate=m(r.startDate)),r.endDate!==void 0&&(i.endDate=m(r.endDate)),!0);if(t.type==="sprint.closed")return i.closedBy===null?(i.status="closed",i.closedBy=t.id):l.push(t),!0;if(t.type==="sprint.cancelled")return i.status==="planned"?i.status="cancelled":l.push(t),!0;if(t.type==="sprint.task_added"){if(i.status==="closed")return l.push(t),!0;let f=typeof r.task=="string"?r.task:null;if(f===null)return!0;let y=e.get(f);return y===void 0?(a.push(t),!1):(y.sprint=i.id,i.taskIds.includes(f)||i.taskIds.push(f),H(y,t),!0)}return!0}let d=e.get(t.entity);if(d===void 0)return a.push(t),!1;if(t.type==="task.deleted")return e.delete(t.entity),!0;switch(t.type){case"task.moved":{let i=r.to;typeof i=="string"&&i.length>0&&(d.status=i);break}case"task.cancelled":d.status=S;break;case"task.reopened":d.status=L(p.changes,t.id);break;case"task.assigned":d.assignee=m(r.assignee);break;case"task.updated":typeof r.title=="string"&&(d.title=r.title),r.description!==void 0&&(d.description=m(r.description)),r.type!==void 0&&(d.type=Q(r.type)),r.priority!==void 0&&(d.priority=V(r.priority)),r.labels!==void 0&&(d.labels=X(r.labels)),r.due!==void 0&&(d.due=m(r.due)),typeof r.estimate=="number"&&(d.estimate=r.estimate);break;case"task.parent_set":d.parent=m(r.parent);break;case"task.blocked_by_added":{let i=m(r.blocker);i!==null&&!d.blockedBy.includes(i)&&d.blockedBy.push(i);break}case"task.blocked_by_removed":{let i=m(r.blocker);i!==null&&(d.blockedBy=d.blockedBy.filter(f=>f!==i));break}case"task.label_added":{let i=m(r.label);i!==null&&!d.labels.includes(i)&&d.labels.push(i);break}case"task.label_removed":{let i=m(r.label);i!==null&&(d.labels=d.labels.filter(f=>f!==i));break}case"task.criterion_added":{let i=m(r.text);i!==null&&d.criteria.push({id:t.id,n:0,text:i,checked:!1,checkedBy:null});break}case"task.criterion_checked":case"task.criterion_unchecked":break;case"task.doc_linked":{let i=m(r.path);i!==null&&!d.docs.includes(i)&&d.docs.push(i);break}case"task.time_logged":{let i=r.hours;typeof i=="number"&&Number.isFinite(i)&&(d.loggedHours=Math.max(0,d.loggedHours+i));break}case"task.commented":{let i=m(r.text);i!==null&&d.comments.push({id:t.id,author:t.actor,ts:t.ts,text:i,source:t.source});break}default:break}return H(d,t),!0}function ct(t){let e=new Map(t.criteria.map(s=>[s.id,s]));for(let s of t.criteria)s.checked=!1,s.checkedBy=null;for(let s of t.history){if(s.type!=="task.criterion_checked"&&s.type!=="task.criterion_unchecked")continue;let u=m(s.data.criterion),l=u===null?void 0:e.get(u);if(l===void 0)continue;let a=s.type==="task.criterion_checked";l.checked=a,l.checkedBy=a?s.actor:null}}function ft(t){let e=null,s=null,u=null,l=[],a=()=>{e=null,s=null,u=null,l=[]};for(let p of t.history)if(p.type==="task.claimed"){let r=m(p.data.by)??p.actor;e===null?(e=r,s=p.ts,u=p.id):r!==e&&!l.includes(r)&&l.push(r)}else if(p.type==="task.released"){let r=m(p.data.by)??p.actor;e===r?a():l=l.filter(d=>d!==r)}else(p.type==="task.cancelled"||p.type==="task.moved"&&p.data.to===x)&&a();t.claimedBy=e,t.claimedAt=s,t.claimedEventId=u,t.contestedBy=l}function H(t,e){t.history.push({id:e.id,type:e.type,actor:e.actor,ts:e.ts,source:e.source,data:e.data??{}}),e.ts>t.updatedAt&&(t.updatedAt=e.ts)}function m(t){return typeof t=="string"&&t.length>0?t:null}function Q(t){return ot.includes(t)?t:"task"}function V(t){return at.includes(t)?t:"normal"}function X(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"&&e.length>0):[]}function pt(t){let e=new Map(t.map(a=>[a.id,a])),s=[],u=new Set,l=(a,p)=>{let r=new Map,d=(i,f)=>{let y=r.get(i);if(y==="done")return;if(y==="visiting"){let h=f.indexOf(i),k=f.slice(h),w=`${a}:${[...k].sort().join(",")}`;u.has(w)||(u.add(w),s.push({kind:a,path:[...k,i]}));return}r.set(i,"visiting");let c=e.get(i);if(c!==void 0)for(let h of p(c))d(h,[...f,i]);r.set(i,"done")};for(let i of t)d(i.id,[])};return l("parent",a=>a.parent===null?[]:[a.parent]),l("blocking",a=>a.blockedBy),s}var D=864e5;function P(t){return new Date(t).toISOString().slice(0,10)}function E(t){return Date.parse(`${t}T00:00:00.000Z`)}function gt(t){let e=new Date(E(t)),s=(e.getUTCDay()+6)%7;return P(e.getTime()-s*D)}function et(t,e){let s=P(t.getTime());return{from:P(E(s)-(e-1)*D),to:s,days:e}}function tt(t,e){let s=t.slice(0,10);return s>=e.from&&s<=e.to}function N(t,e){if(t.length===0)return 0;let s=Math.max(1,Math.ceil(e*t.length));return t[s-1]}var I=t=>Math.round(t*10)/10;function q(t){if(t.length===0)return null;let e=[...t].sort((s,u)=>s-u);return{shown:{n:e.length,p50:I(N(e,.5)),p85:I(N(e,.85)),p95:I(N(e,.95))},rawP85:N(e,.85)}}function j(t,e){let s=t.indexOf(e);return s===-1?null:new Set(t.slice(0,s))}function Z(t,e,s=[],u=[]){let l=j(s,e),a=r=>r===x||r===S?!1:l===null?r===e:r===e||!l.has(r);return t.history.find(r=>r.type==="task.reopened"?a(L(u,r.id)):r.type==="task.moved"&&typeof r.data.to=="string"&&a(r.data.to))?.ts??null}function yt(t,e){if(e.status===x||e.status===S)return!1;let s=j(t.statuses,t.started);return s===null?e.status===t.started:s.has(e.status)?!1:Z(e,t.started,t.statuses,t.startedChanges)!==null}function _(t){if(t.status!==x)return null;for(let e=t.history.length-1;e>=0;e--){let s=t.history[e];if(s.type==="task.moved"&&s.data.to===x)return s.ts}return null}function ht(t){if(t.status!==S)return null;for(let e=t.history.length-1;e>=0;e--){let s=t.history[e];if(s.type==="task.cancelled"||s.type==="task.moved"&&s.data.to===S)return s.ts}return null}function O(t,e){return Math.max(0,(Date.parse(e)-Date.parse(t))/D)}function mt(t,e,s,u){let l=_(t)??ht(t),a=l===null?u:Date.parse(l),p=[],r=new Map;for(let h of t.history){let k=typeof h.data.blocker=="string"?h.data.blocker:null;if(k!==null){if(h.type==="task.blocked_by_added")r.has(k)||r.set(k,Date.parse(h.ts));else if(h.type==="task.blocked_by_removed"){let w=r.get(k);w!==void 0&&(p.push([w,Math.min(Date.parse(h.ts),a)]),r.delete(k))}}}for(let[h,k]of r){let w=Math.min(e.get(h)??u,a);p.push([k,Math.max(k,w)])}let d=E(s.from),i=E(s.to)+D,f=p.map(([h,k])=>[Math.max(h,d),Math.min(k,i)]).filter(([h,k])=>k>h).sort((h,k)=>h[0]-k[0]),y=0,c=null;for(let[h,k]of f)c===null||h>c[1]?(c!==null&&(y+=c[1]-c[0]),c=[h,k]):k>c[1]&&(c[1]=k);return c!==null&&(y+=c[1]-c[0]),y/D}function St(t,e=new Date,s=30){let u=et(e,s),l=e.getTime(),a=[],p=t.tasks.filter(n=>n.status!==S),r=p.filter(n=>{let o=_(n);return o!==null&&tt(o,u)}),d=[],i=[],f=[];for(let n of r){let o=_(n),g=Z(n,t.started,t.statuses,t.startedChanges);i.push(O(n.createdAt,o)),g!==null&&(d.push(O(g,o)),f.push(O(n.createdAt,g)))}let y=q(d),c=y?.shown??null,h=p.filter(n=>yt(t,n)),k=h.map(n=>{let o=O(Z(n,t.started,t.statuses,t.startedChanges),e.toISOString());return{label:n.label,title:n.title,status:n.status,ageDays:I(o),overP85:y!==null&&o>y.rawP85}}).sort((n,o)=>o.ageDays-n.ageDays),w=new Map,T=n=>{let o=gt(n),g=w.get(o);return g===void 0&&(g={week:o,finished:0,created:0},w.set(o,g)),g};for(let n=E(u.from);n<=E(u.to);n+=D)T(P(n));for(let n of r)T(_(n).slice(0,10)).finished+=1;for(let n of p)tt(n.createdAt,u)&&(T(n.createdAt.slice(0,10)).created+=1);let M=[...w.values()].sort((n,o)=>n.week<o.week?-1:1),B=new Map;for(let n of t.tasks){let o=_(n);o!==null&&B.set(n.id,Date.parse(o))}let C=0,R=0;for(let n of p){let o=mt(n,B,u,l);o>0&&(C+=1,R+=o)}t.tasks.length===0?a.push("No tasks yet."):(h.length===0&&r.length===0&&a.push(`Nothing has crossed "${t.started}" yet. If work starts in another column, say so: kadence board config --started <status>`),r.length===0?a.push(`Nothing finished between ${u.from} and ${u.to}; cycle time needs finished work.`):d.length===0&&a.push(`${r.length} item(s) finished without ever entering "${t.started}", so there is no cycle time to measure.`),t.statuses.includes(t.started)||a.push(`"${t.started}" is not one of the board's columns; set one with kadence board config --started.`));let K=c===null?null:`${c.n<10?`From ${c.n} finished items (a small sample): `:""}85% of finished items took ${c.p85} calendar days or less.`;return{window:u,started:t.started,unit:"calendar days",wip:h.length,finished:r.length,perWeek:M,cycleTime:c,leadTime:q(i)?.shown??null,responseTime:q(f)?.shown??null,sle:K,aging:k,blocked:{tasks:C,days:I(R)},notes:a}}function vt(t,e=new Date,s=30){let u=et(e,s),l=[...t.statuses];for(let d of t.tasks)l.includes(d.status)||l.push(d.status);let a=Y;!l.includes(a)&&t.tasks.length>0&&l.unshift(a);let p=t.tasks.map(d=>{let i=[];for(let f of d.history)f.type==="task.moved"&&typeof f.data.to=="string"?i.push({at:Date.parse(f.ts),status:f.data.to}):f.type==="task.cancelled"?i.push({at:Date.parse(f.ts),status:S}):f.type==="task.reopened"&&i.push({at:Date.parse(f.ts),status:L(t.startedChanges,f.id)});return{createdAt:Date.parse(d.createdAt),changes:i,next:0,status:a}}),r=[];for(let d=E(u.from);d<=E(u.to);d+=D){let i=d+D,f={};for(let y of l)f[y]=0;for(let y of p){for(;y.next<y.changes.length&&y.changes[y.next].at<i;)y.status=y.changes[y.next].status,y.next+=1;y.createdAt>=i||(f[y.status]=(f[y.status]??0)+1)}r.push({date:P(d),counts:f})}return{window:u,statuses:l,days:r}}var W={urgent:0,high:1,normal:2,low:3};function nt(t,e){return t!==null&&t.toLowerCase().includes(e)}function Mt(t,e,s=new Date){let u=s.toISOString().slice(0,10),l=e.search?.toLowerCase();return t.filter(a=>{if(l!==void 0&&l.length>0){let p=a.comments.some(r=>r.text.toLowerCase().includes(l));if(!nt(a.title,l)&&!nt(a.description,l)&&!p)return!1}if(e.status!==void 0&&a.status!==e.status||e.type!==void 0&&a.type!==e.type||e.priority!==void 0&&a.priority!==e.priority)return!1;if(e.assignee!==void 0){let p=e.assignee.toLowerCase(),r=(a.assignee??"").toLowerCase();if(p==="none"?r!=="":r!==p)return!1}if(e.label!==void 0){let p=e.label.toLowerCase();if(!a.labels.some(r=>r.toLowerCase()===p))return!1}return!(e.sprint!==void 0&&a.sprint!==e.sprint||e.overdue===!0&&(a.due===null||a.due>=u)||e.dueBefore!==void 0&&(a.due===null||a.due>=e.dueBefore))})}function Bt(t,e){let s=[...t];switch(e){case"priority":return s.sort((u,l)=>W[u.priority]-W[l.priority]);case"due":return s.sort((u,l)=>st(u.due,l.due,(a,p)=>a<p?-1:a>p?1:0));case"estimate":return s.sort((u,l)=>st(u.estimate,l.estimate,(a,p)=>p-a));default:return s.sort((u,l)=>u.id<l.id?-1:u.id>l.id?1:0)}}function st(t,e,s){return t===null&&e===null?0:t===null?1:e===null?-1:s(t,e)}function Ct(t){let e=[];return t.search!==void 0&&e.push(`search="${t.search}"`),t.status!==void 0&&e.push(`status=${t.status}`),t.type!==void 0&&e.push(`type=${t.type}`),t.priority!==void 0&&e.push(`priority=${t.priority}`),t.assignee!==void 0&&e.push(`assignee=${t.assignee}`),t.label!==void 0&&e.push(`label=${t.label}`),t.overdue===!0&&e.push("overdue"),t.dueBefore!==void 0&&e.push(`due before ${t.dueBefore}`),e.length===0?`No tasks yet.
3
+ Create the first one:
4
+ kadence task add "title"`:`No tasks match ${e.join(" and ")}.
5
+ Try fewer filters:
6
+ kadence task list`}function rt(t,e){return t===null||e===null?!1:t===e?!0:!e.includes("#")&&t.startsWith(`${e}#`)}function kt(t){let e=t.indexOf("#");return e===-1?t:t.slice(0,e)}function it(t){return j(t.statuses??F,t.started??$)}function U(t){return t.status===x||t.status===S}function Rt(t,e={}){let s=e.viewer??null,u=new Set(t.filter(U).map(r=>r.id)),l=e.assignee==="me"?s===null?null:kt(s):e.assignee??null,a=it(e);return t.filter(r=>{if(U(r)||a!==null&&!a.has(r.status)||r.blockedBy.some(d=>!u.has(d))||r.claimedBy!==null&&!rt(r.claimedBy,s)&&r.contestedBy.length===0)return!1;if(l!==null){if(l==="none")return r.assignee===null;if(r.assignee!==l)return!1}return!0}).sort((r,d)=>W[r.priority]-W[d.priority]||(r.id<d.id?-1:1))}function _t(t,e,s,u={}){if(t.length===0)return`No tasks yet.
7
+ Create the first one:
8
+ kadence task add "title"`;let l=t.filter(c=>!U(c));if(l.length===0)return"Nothing ready: every task is done or cancelled.";let a=new Set(t.filter(U).map(c=>c.id)),p=it(u),r=p===null?0:l.filter(c=>!p.has(c.status)).length,d=l.filter(c=>c.blockedBy.some(h=>!a.has(h))).length,i=l.filter(c=>c.claimedBy!==null&&!rt(c.claimedBy,e)&&c.contestedBy.length===0).length,f=[];return r>0&&f.push(`${r} already started`),d>0&&f.push(`${d} blocked`),i>0&&f.push(`${i} claimed by someone else`),s!==void 0&&f.push(`filtered to assignee=${s}`),`Nothing ready${f.length>0?` (${f.join(", ")})`:""}.
9
+ See the whole board:
10
+ kadence task list`}var bt=["created","priority","due","estimate"];function It(t){return bt.includes(t)}export{F as a,x as b,S as c,ot as d,at as e,wt as f,Z as g,yt as h,_ as i,St as j,vt as k,Mt as l,Bt as m,Ct as n,rt as o,U as p,Rt as q,_t as r,bt as s,It as t};