kadence 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,96 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0] — 2026-09-08
4
+
5
+ The journal held what happened. It now holds **why** — and the reasoning cannot
6
+ quietly go stale, because superseding a decision is one event rather than two
7
+ edits somebody has to remember to make. Reasoning in
8
+ [ADR-010](docs/decisions/010-decisions-as-events.md).
9
+
10
+ ### Added
11
+
12
+ - **`kadence decision`** — why a choice was made, as an event next to the work.
13
+ `decision add "Use ULIDs" --why "Clocks disagree between machines" --rejected
14
+ "Auto-increment: collides across branches"`. `--why` is required; without it
15
+ the record is a changelog line.
16
+
17
+ Superseding is **one event**, not two edits. `--supersedes DEC-1` writes a
18
+ single record and the backward link is derived while folding, so the two
19
+ directions cannot fall out of step — the failure that makes a reversed
20
+ decision keep looking authoritative in file-based tools. `decision list`
21
+ returns what is still in force; `--all` adds the history.
22
+
23
+ Numbers are derived, so two branches can each record a decision and merge
24
+ without a conflict or a renumber. Both are covered by integration tests on
25
+ real git branches.
26
+
27
+ - **Documents linked to work** — `kadence task doc KAD-1 docs/design.md`, and
28
+ `--doc` on a decision. kadence does not store the document: it stays plain
29
+ markdown and git keeps versioning it. What git cannot say is that this file
30
+ explains this task, and that is the only thing recorded. A missing file is a
31
+ warning, not a refusal — it may arrive in a later commit.
32
+
33
+ Measured before building ([Probe D](docs/research/probe-d-docs-linkage.md)):
34
+ across five real questions, grep finds the answering document every time and
35
+ buries it among 10–35 candidates. The link saves the sifting, not the search.
36
+
37
+ - `task show --json` now carries `decisions` and `docs`; both are always arrays,
38
+ so an agent never has to branch on their absence.
39
+
40
+ A decision that supersedes another **inherits the task** it was about, unless
41
+ you name a different one. Without that, superseding quietly stripped a task of
42
+ its reasoning — the old decision dropped out of `task show` and the
43
+ replacement had never been attached. Found by installing the package and using
44
+ it, with 538 tests green.
45
+
46
+
47
+ - The files `init` writes into your repository now say what produced them:
48
+ `<!-- generated by kadence X.Y.Z — refresh with `kadence init` -->`. A context
49
+ file with no marker rots silently — a year on, nobody knows whether the
50
+ section is current or what put it there, and we write into other people's
51
+ repositories. Deliberately no date: it would rewrite the file on every new day
52
+ and fill diffs with noise, while the version changes exactly when the content
53
+ might have.
54
+
55
+ ## [0.2.2] — 2026-09-08
56
+
57
+ Two promises from 0.2.1 that the code did not keep, found by reading the
58
+ published package rather than the source.
59
+
60
+ ### Fixed
61
+
62
+ - **Most `--json` failures carried no `error.code`.** ADR-009 says every failure
63
+ has one; thirty-seven paths returned a bare sentence — most of `sprint`, all of
64
+ `template`, `board config`, and every "unknown action". An agent could tell
65
+ that something failed and nothing else. The existing tests compared the
66
+ published code list against the constant, so they could not see that the
67
+ commands were not using it; a new test now provokes twenty-seven real failures
68
+ and requires a code from the list on each.
69
+ - **`unknown_status` hinted at a command that does not exist.** It named
70
+ `kadence board statuses --json`; following it produced a second failure, which
71
+ itself had no code. The hint is now `kadence board config --json`, which
72
+ already returns the configured columns, and every hint the CLI can emit is
73
+ executed by a test that requires it to succeed.
74
+ - **`cac` was a runtime dependency that nothing loaded.** esbuild bundles it, so
75
+ the only external import in the published output is `blessed` — every install
76
+ downloaded 52 KB for nothing. Moved to `devDependencies`, with a test that
77
+ compares what the manifest declares against what the build actually imports.
78
+ This is the same shape as the 0.1.4 self-dependency bug.
79
+
80
+ ### Added
81
+
82
+ - Two error codes, additive within `kadence/v1`: `template_not_found`, and
83
+ `conflicting_state` for arguments that are understood but refused by the
84
+ current state — a closed sprint, one already started, one still open at close.
85
+ - `received` and `allowed` on the failures where they are knowable, including
86
+ the action lists behind "unknown action".
87
+
88
+ ### Changed
89
+
90
+ - The README's cost table said "29 KB, one runtime dependency". That is the
91
+ entry file. The published package is 37 KB packed, and an install puts 128 KB
92
+ of kadence and 1.8 MB of blessed on disk; the table now says so.
93
+
3
94
  ## [0.2.1] — 2026-09-08
4
95
 
5
96
  > Numbered 0.2.1 because 0.2.0 cannot be published under this name: a different
package/README.md CHANGED
@@ -183,6 +183,23 @@ a tenth of that with the fields an agent actually reads:
183
183
  kadence board --json --fields label,status,assignee
184
184
  ```
185
185
 
186
+ **And the part the code cannot hold — why:**
187
+
188
+ ```bash
189
+ kadence decision add "Use ULIDs" --why "Clocks disagree between machines" \
190
+ --rejected "Auto-increment: collides across branches" --task KAD-1
191
+ ```
192
+
193
+ When a decision stops being true you supersede it rather than edit it, and that
194
+ is **one event** — the backward link is derived, so the two directions cannot
195
+ fall out of step. In a file-based tool it is two edits, and teams reliably make
196
+ one; that is how a reversed decision keeps looking authoritative.
197
+ `decision list` returns what is still in force, `--all` adds the history, and
198
+ `task show --json` carries the decisions made about that task.
199
+
200
+ Documents stay plain markdown — `kadence task doc KAD-1 docs/design.md` records
201
+ only the link, which is the part git cannot express.
202
+
186
203
  Bulk works everywhere and is all or nothing: `kadence task move KAD-1,KAD-2 done`
187
204
  either moves both or changes nothing. A typo does not leave half a board.
188
205
 
@@ -192,7 +209,7 @@ either moves both or changes nothing. A typo does not leave half a board.
192
209
 
193
210
  | | |
194
211
  |---|---|
195
- | Install | 29 KB, one runtime dependency |
212
+ | Install | 38 KB packed — 132 KB of kadence, plus 1.8 MB of blessed |
196
213
  | Startup | 80 ms |
197
214
  | 10,000 events | 28 ms cold, 7 ms warm |
198
215
  | Journal on disk | 1.9 MB |
@@ -207,7 +224,7 @@ true.
207
224
 
208
225
  **Verified.** The merge thesis, on real git branches. Performance and size, by
209
226
  tests that fail if they regress. That the conflict problem exists in the wild —
210
- measured, not assumed. 428 tests, including an end-to-end run through the
227
+ measured, not assumed. 541 tests, including an end-to-end run through the
211
228
  installed binary.
212
229
 
213
230
  **Not verified.** That teams and their AI agents actually lose enough context to want
@@ -215,9 +232,8 @@ this. The bet rests on reasoning and on the industry naming the problem out
215
232
  loud — not on our own users. That research is
216
233
  [designed](docs/research/interview-script.md) and not yet run.
217
234
 
218
- **On the roadmap, not shipped.** `kadence decision` (record why, as its own event
219
- type) and the optional MCP package — the latter kept as a response to someone who
220
- cannot use the CLI, not as an inevitability.
235
+ **On the roadmap, not shipped.** The optional MCP package, kept as a response to
236
+ someone who cannot use the CLI rather than as an inevitability.
221
237
 
222
238
  `kadence context <task>` was dropped: we measured what `task show --json` already
223
239
  returns and it is the whole history of one piece of work, 948 bytes, constant.
@@ -250,8 +266,8 @@ revisit it: [docs/decisions/](docs/decisions/).
250
266
 
251
267
  ```bash
252
268
  npm install
253
- npm test # 428 tests
254
- npm run build # 29 KB bundle
269
+ npm test # 541 tests
270
+ npm run build # 35 KB bundle
255
271
  ```
256
272
 
257
273
  `CLAUDE.md` documents the invariants, the boundaries, and the decisions that
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ function re(e){return`<!-- generated by kadence ${e} \u2014 refresh with \`kadence init\` -->`}function Zt(e){return`${re(e)}
3
+ # kadence \u2014 for AI agents
4
+
5
+ This project's tasks live here as plain files. Read them directly, or through
6
+ the CLI. No server required.
7
+
8
+ ## Commands
9
+
10
+ kadence board --json the whole board
11
+ kadence task list --json all tasks
12
+ kadence task show KAD-42 --json one task with its history
13
+ kadence task add "title" -d "..." --type bug --estimate 3
14
+ kadence task move KAD-42 in_progress
15
+ kadence task assign KAD-42 you@example.com
16
+ kadence sprint status --json current sprint progress
17
+
18
+ ## JSON contract
19
+
20
+ Every \`--json\` response carries \`schema: "kadence/v1"\`. stdout holds JSON and
21
+ nothing else; warnings go to stderr. Exit codes: 0 success, 1 runtime error,
22
+ 2 bad arguments.
23
+
24
+ The contract itself is machine-readable \u2014 read it instead of guessing:
25
+
26
+ kadence schema --json
27
+
28
+ It lists every command, the fields you can rely on, and every error code. It
29
+ works outside a repository, so you can read it before \`init\`.
30
+
31
+ ## When something fails
32
+
33
+ A failed \`--json\` call carries \`error.code\` \u2014 branch on that, not on the
34
+ sentence. Where the valid set is knowable it also carries \`allowed\`:
35
+
36
+ { "ok": false,
37
+ "error": { "code": "unknown_status", "received": "shipped",
38
+ "allowed": ["backlog", "in_progress", "done"],
39
+ "hint": "kadence board statuses --json" } }
40
+
41
+ Statuses are configured per project, so \`allowed\` is the only reliable source \u2014
42
+ never assume the defaults. Retrying an identical command never helps: there is no
43
+ network and no lock, so the same input always fails the same way.
44
+
45
+ ## Working as an agent
46
+
47
+ Set \`KADENCE_SOURCE=agent\` so events record your authorship. Without it an
48
+ event is marked as human \u2014 we do not guess.
49
+
50
+ ## Why to ask rather than read the files
51
+
52
+ You cannot find a task by its label in the journal. \`KAD-3\` is derived while
53
+ folding and is never stored in an event, so \`grep -r "KAD-3" .kadence/events/\`
54
+ returns nothing. Folding the journal yourself is the only alternative to asking.
55
+
56
+ Asking is also cheaper, and stays cheap: \`task show --json\` is about 950 bytes
57
+ whether the project holds ten tasks or a thousand, while the journal behind it
58
+ grows past 500 KB.
59
+
60
+ \`board --json\` is the exception: it returns every task in full, which on a large
61
+ project is a lot of description you did not ask for. Narrow it:
62
+
63
+ kadence board --json --fields label,status,assignee
64
+ kadence task list --json --fields id,label,status
65
+
66
+ \`kadence schema --json\` lists every selectable field.
67
+
68
+ ## Recording why
69
+
70
+ The journal holds what happened. \`decision\` holds why, which the code and
71
+ \`git log\` never carry:
72
+
73
+ kadence decision add "Use ULIDs" --why "Clocks disagree between machines" \\
74
+ --rejected "Auto-increment: collides across branches" --task KAD-1
75
+
76
+ \`--why\` is required: without it the record is a changelog line. \`--rejected\` is
77
+ what stops the next agent proposing the thing that was already turned down.
78
+
79
+ When a decision stops being true, do not edit it \u2014 supersede it:
80
+
81
+ kadence decision add "Use signed tokens" --why "..." --supersedes DEC-1
82
+
83
+ One event writes both directions. \`decision list\` then returns only what is
84
+ still in force; pass \`--all\` when you need the history too. **Read the default,
85
+ not \`--all\`** \u2014 a reversed reason quoted as current is worse than no memory.
86
+
87
+ ## Documents
88
+
89
+ \`kadence task doc KAD-1 docs/design.md\` links a document to a task, and
90
+ \`task show --json\` returns the links. kadence does not store the document: it
91
+ stays plain markdown in the repository. The link is the part git cannot express.
92
+
93
+ ## What not to do
94
+
95
+ Do not hand-edit files under \`.kadence/events/\`: the journal is appended to,
96
+ never modified. To correct the state, add a new event through the CLI.
97
+ `}var se="<!-- kadence:begin -->",Z="<!-- kadence:end -->";function He(e){return`${se}
98
+ ${re(e)}
99
+ ## Project tasks \u2014 kadence
100
+
101
+ Tasks live in \`.kadence/\` as plain files. Read them directly or via the CLI:
102
+
103
+ kadence board --json the whole board
104
+ kadence task list --json all tasks
105
+ kadence task move KAD-1 done change state
106
+
107
+ kadence schema --json the contract: commands, fields, error codes
108
+ kadence decision list --json why the current choices were made
109
+
110
+ \`--json\` responses carry \`schema: "kadence/v1"\`; stdout is JSON only. A failure
111
+ carries \`error.code\` and, where knowable, \`allowed\`.
112
+ When acting as an agent, set \`KADENCE_SOURCE=agent\`.
113
+
114
+ Details: \`.kadence/README.md\`
115
+ ${Z}`}function Vt(e,n){let r=He(n);if(e===null||e.trim().length===0)return`${r}
116
+ `;let t=e.indexOf(se),s=e.indexOf(Z);if(t!==-1&&s!==-1&&s>t){let o=e.slice(0,t),a=e.slice(s+Z.length);return`${o}${r}${a}`}let i=e.endsWith(`
117
+ `)?`
118
+ `:`
119
+
120
+ `;return`${e}${i}${r}
121
+ `}var F=["id","label","title","description","type","priority","status","labels","assignee","reporter","sprint","loggedHours","parent","blockedBy","due","comments","estimate","history"],ie=["not_a_repository","not_initialised","no_git_identity","task_not_found","sprint_not_found","decision_not_found","unknown_status","unknown_type","unknown_priority","unknown_field","invalid_argument","template_not_found","conflicting_state"],We={not_a_repository:"There is no git repository here. kadence stores its journal inside one.",not_initialised:"The repository has no .kadence/ folder yet. Run `kadence init`.",no_git_identity:"Git has no user.email, so an event would have no author.",task_not_found:"No task carries that ULID or KAD-N label. Nothing was changed.",sprint_not_found:"No sprint carries that name or id.",decision_not_found:"No decision carries that ULID or DEC-N label.",unknown_status:"The status is not one of this project\u2019s columns. They are configurable, so read `allowed`.",unknown_type:"The task type is not one of the four kadence defines.",unknown_priority:"The priority is not one of the four kadence defines.",unknown_field:"A name given to --fields is not a task field. Read `allowed`.",invalid_argument:"An argument was missing or malformed; the command did nothing.",template_not_found:"No template carries that name.",conflicting_state:"The arguments were understood, but the current state does not allow it \u2014 a closed sprint, or one already started."};function zt(e){return{version:"kadence/v1",tool:{name:"kadence",version:e},stability:"Additive only: fields and error codes may be added, never renamed or removed within kadence/v1.",exitCodes:{0:"success",1:"runtime error \u2014 the command understood you and could not comply",2:"bad arguments \u2014 nothing was attempted"},output:{stdout:"With --json, JSON and nothing else.",stderr:"Warnings and human messages, never part of the contract."},env:{KADENCE_SOURCE:'Set to "agent" so events record agent authorship. Without it an event counts as human \u2014 we do not guess.',NO_COLOR:"Any value disables colour."},errors:ie.map(n=>({code:n,meaning:We[n]})),shapes:{task:{required:["id","label","title","status","type","priority","estimate","assignee","blockedBy","loggedHours"],selectable:[...F],notes:{id:"ULID. The identity of the task; KAD-N is a label derived while folding and is never stored.",history:"Present in `task show` only \u2014 the events that produced this state.",required:"What a full response carries. With --fields you get exactly what you asked for and nothing else."}},board:{required:["schema","ok","columns"]},decision:{required:["id","label","title","why","rejected","docs","supersedes","supersededBy"],notes:{why:"The reason. Required when recording \u2014 a decision without one is a changelog line.",supersededBy:"Derived while folding from a later decision carrying `supersedes`. Both directions come from one write, so they cannot fall out of step.",docs:"Repository-relative paths. kadence does not store the documents, only the link.",listing:"`decision list` hides superseded decisions unless --all is passed: a reversed reason presented as current is worse than no memory."}},error:{required:["code","message"],optional:["received","allowed","hint"],notes:{allowed:"Present when the valid set is knowable \u2014 statuses are project-configurable.",retryable:"Deliberately absent: no network, no lock, so a retry always fails identically."}}},commands:[{name:"schema",summary:"This contract. Works outside a repository."},{name:"init",summary:"Create .kadence/ and the agent instruction files."},{name:"board",summary:"The whole board, grouped by column. Every task in full \u2014 pass --fields on a large project.",flags:["--json","--fields"],json:!0},{name:"task list",summary:"All tasks, filterable.",flags:["--json","--fields"],json:!0},{name:"task show",summary:"One task with its comments and full history.",args:["ref"],json:!0},{name:"task add",summary:"Create a task.",args:["title"],json:!0},{name:"task move",summary:"Change status. Accepts several refs, all or nothing.",args:["refs","status"],json:!0},{name:"task assign",summary:"Assign or unassign.",args:["refs","who"],json:!0},{name:"task comment",summary:"Append a comment.",args:["ref","text"],json:!0},{name:"task edit",summary:"Change fields.",args:["refs"],json:!0},{name:"task log",summary:"Log hours.",args:["refs","hours"],json:!0},{name:"task block",summary:"Record a blocker.",args:["ref","blocker"],json:!0},{name:"decision add",summary:"Record why something was chosen, and what was turned down.",args:["title"],flags:["--why","--rejected","--task","--supersedes","--doc"],json:!0},{name:"decision list",summary:"Current decisions. Superseded ones need --all.",flags:["--all","--task"],json:!0},{name:"decision show",summary:"One decision in full.",args:["ref"],json:!0},{name:"task doc",summary:"Link a document to a task. The file stays plain markdown in the repo.",args:["ref","path"],json:!0},{name:"sprint status",summary:"Current sprint progress.",json:!0},{name:"sprint create",summary:"Start a sprint.",args:["name"],json:!0},{name:"sprint close",summary:"Close it and report velocity.",json:!0}]}}var G=["backlog","todo","in_progress","blocked","in_review","done","cancelled"],Qt="done",Ye="cancelled",N=["task","bug","story","epic"],A=["low","normal","high","urgent"];function ce(e){let n=[...e].sort((c,p)=>c.id<p.id?-1:c.id>p.id?1:0),r=new Map,t=new Map,s=new Map,i=new Map,o=null,a=[],d=[];for(let c of n){if(c.type==="decision.recorded"){let p=c.data??{},k=R=>typeof p[R]=="string"&&p[R].length>0?p[R]:null,$=k("title"),_=k("why");$!==null&&_!==null&&i.set(c.id,{id:c.id,label:"",title:$,why:_,rejected:k("rejected"),task:k("task"),docs:Array.isArray(p.docs)?p.docs.filter(R=>typeof R=="string"):[],supersedes:k("supersedes"),supersededBy:null,at:c.ts,by:c.actor});continue}if(c.type==="template.saved"){let p=typeof c.data?.name=="string"?c.data.name:null;p!==null&&s.set(p,{name:p,fields:c.data?.fields??{},author:c.actor});continue}if(c.type==="board.configured"){let p=c.data?.statuses;if(Array.isArray(p)){let k=p.filter($=>typeof $=="string"&&$.length>0);k.length>0&&(o=k)}continue}if(c.type==="template.deleted"){let p=typeof c.data?.name=="string"?c.data.name:null;p!==null&&s.delete(p);continue}oe(c,r,t,a,d)}let u=d.length>0,l=d;for(;l.length>0;){let c=[];for(let p of l)oe(p,r,t,a,c);if(c.length===l.length){l=c;break}l=c}if(u)for(let c of r.values())c.history.sort((p,k)=>p.id<k.id?-1:1);let f=[...r.values()].sort((c,p)=>c.id<p.id?-1:1);f.forEach((c,p)=>{c.label=`KAD-${p+1}`});let g=new Set(f.map(c=>c.id));for(let c of f)c.parent!==null&&!g.has(c.parent)&&(c.parent=null),c.blockedBy=c.blockedBy.filter(p=>g.has(p));let m=[...i.values()].sort((c,p)=>c.id<p.id?-1:1);m.forEach((c,p)=>{c.label=`DEC-${p+1}`});for(let c of m){if(c.supersedes===null)continue;let p=i.get(c.supersedes);p!==void 0&&(p.supersededBy=c.id)}for(let c of m)c.task!==null&&!g.has(c.task)&&(c.task=null);return{tasks:f,decisions:m,sprints:[...t.values()].sort((c,p)=>c.id<p.id?-1:1),statuses:o??[...G],orphanStatuses:[...new Set(f.map(c=>c.status).filter(c=>!(o??G).includes(c)))].sort(),templates:[...s.values()].sort((c,p)=>c.name.localeCompare(p.name)),cycles:Ge(f),pending:l,rejected:a}}function oe(e,n,r,t,s){let i=e.data??{};if(e.type==="task.created")return n.has(e.entity)||n.set(e.entity,{id:e.entity,label:"",title:typeof i.title=="string"?i.title:"(untitled)",description:v(i.description),type:ae(i.type),priority:de(i.priority),status:"backlog",labels:ue(i.labels),assignee:v(i.assignee),reporter:e.actor,sprint:null,parent:v(i.parent),blockedBy:[],due:v(i.due),comments:[],docs:[],estimate:typeof i.estimate=="number"?i.estimate:null,loggedHours:0,createdAt:e.ts,updatedAt:e.ts,history:[]}),V(n.get(e.entity),e),!0;if(e.type==="sprint.created")return r.has(e.entity)||r.set(e.entity,{id:e.entity,name:typeof i.name=="string"?i.name:"(untitled)",description:v(i.description),startDate:v(i.startDate),endDate:v(i.endDate),status:"planned",closedBy:null,taskIds:[]}),!0;if(e.type.startsWith("sprint.")){let a=r.get(e.entity);if(a===void 0)return s.push(e),!1;if(e.type==="sprint.started")return a.status==="planned"&&(a.status="active"),!0;if(e.type==="sprint.updated")return a.status==="closed"?(t.push(e),!0):(typeof i.name=="string"&&(a.name=i.name),i.description!==void 0&&(a.description=v(i.description)),i.startDate!==void 0&&(a.startDate=v(i.startDate)),i.endDate!==void 0&&(a.endDate=v(i.endDate)),!0);if(e.type==="sprint.closed")return a.closedBy===null?(a.status="closed",a.closedBy=e.id):t.push(e),!0;if(e.type==="sprint.cancelled")return a.status==="planned"?a.status="cancelled":t.push(e),!0;if(e.type==="sprint.task_added"){if(a.status==="closed")return t.push(e),!0;let d=typeof i.task=="string"?i.task:null;if(d===null)return!0;let u=n.get(d);return u===void 0?(s.push(e),!1):(u.sprint=a.id,a.taskIds.includes(d)||a.taskIds.push(d),V(u,e),!0)}return!0}let o=n.get(e.entity);if(o===void 0)return s.push(e),!1;if(e.type==="task.deleted")return n.delete(e.entity),!0;switch(e.type){case"task.moved":{let a=i.to;typeof a=="string"&&a.length>0&&(o.status=a);break}case"task.cancelled":o.status=Ye;break;case"task.reopened":o.status="in_progress";break;case"task.assigned":o.assignee=v(i.assignee);break;case"task.updated":typeof i.title=="string"&&(o.title=i.title),i.description!==void 0&&(o.description=v(i.description)),i.type!==void 0&&(o.type=ae(i.type)),i.priority!==void 0&&(o.priority=de(i.priority)),i.labels!==void 0&&(o.labels=ue(i.labels)),i.due!==void 0&&(o.due=v(i.due)),typeof i.estimate=="number"&&(o.estimate=i.estimate);break;case"task.parent_set":o.parent=v(i.parent);break;case"task.blocked_by_added":{let a=v(i.blocker);a!==null&&!o.blockedBy.includes(a)&&o.blockedBy.push(a);break}case"task.blocked_by_removed":{let a=v(i.blocker);a!==null&&(o.blockedBy=o.blockedBy.filter(d=>d!==a));break}case"task.doc_linked":{let a=v(i.path);a!==null&&!o.docs.includes(a)&&o.docs.push(a);break}case"task.time_logged":{let a=i.hours;typeof a=="number"&&Number.isFinite(a)&&(o.loggedHours=Math.max(0,o.loggedHours+a));break}case"task.commented":{let a=v(i.text);a!==null&&o.comments.push({id:e.id,author:e.actor,ts:e.ts,text:a});break}default:break}return V(o,e),!0}function V(e,n){e.history.push({id:n.id,type:n.type,actor:n.actor,ts:n.ts,data:n.data??{}}),n.ts>e.updatedAt&&(e.updatedAt=n.ts)}function v(e){return typeof e=="string"&&e.length>0?e:null}function ae(e){return N.includes(e)?e:"task"}function de(e){return A.includes(e)?e:"normal"}function ue(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"&&n.length>0):[]}function Ge(e){let n=new Map(e.map(i=>[i.id,i])),r=[],t=new Set,s=(i,o)=>{let a=new Map,d=(u,l)=>{let f=a.get(u);if(f==="done")return;if(f==="visiting"){let m=l.indexOf(u),c=l.slice(m),p=`${i}:${[...c].sort().join(",")}`;t.has(p)||(t.add(p),r.push({kind:i,path:[...c,u]}));return}a.set(u,"visiting");let g=n.get(u);if(g!==void 0)for(let m of o(g))d(m,[...l,u]);a.set(u,"done")};for(let u of e)d(u.id,[])};return s("parent",i=>i.parent===null?[]:[i.parent]),s("blocking",i=>i.blockedBy),r}var le={urgent:0,high:1,normal:2,low:3};function pe(e,n){return e!==null&&e.toLowerCase().includes(n)}function ge(e,n,r=new Date){let t=r.toISOString().slice(0,10),s=n.search?.toLowerCase();return e.filter(i=>{if(s!==void 0&&s.length>0){let o=i.comments.some(a=>a.text.toLowerCase().includes(s));if(!pe(i.title,s)&&!pe(i.description,s)&&!o)return!1}if(n.status!==void 0&&i.status!==n.status||n.type!==void 0&&i.type!==n.type||n.priority!==void 0&&i.priority!==n.priority)return!1;if(n.assignee!==void 0){let o=n.assignee.toLowerCase(),a=(i.assignee??"").toLowerCase();if(o==="none"?a!=="":a!==o)return!1}if(n.label!==void 0){let o=n.label.toLowerCase();if(!i.labels.some(a=>a.toLowerCase()===o))return!1}return!(n.sprint!==void 0&&i.sprint!==n.sprint||n.overdue===!0&&(i.due===null||i.due>=t)||n.dueBefore!==void 0&&(i.due===null||i.due>=n.dueBefore))})}function me(e,n){let r=[...e];switch(n){case"priority":return r.sort((t,s)=>le[t.priority]-le[s.priority]);case"due":return r.sort((t,s)=>fe(t.due,s.due,(i,o)=>i<o?-1:i>o?1:0));case"estimate":return r.sort((t,s)=>fe(t.estimate,s.estimate,(i,o)=>o-i));default:return r.sort((t,s)=>t.id<s.id?-1:t.id>s.id?1:0)}}function fe(e,n,r){return e===null&&n===null?0:e===null?1:n===null?-1:r(e,n)}function he(e){let n=[];return e.search!==void 0&&n.push(`search="${e.search}"`),e.status!==void 0&&n.push(`status=${e.status}`),e.type!==void 0&&n.push(`type=${e.type}`),e.priority!==void 0&&n.push(`priority=${e.priority}`),e.assignee!==void 0&&n.push(`assignee=${e.assignee}`),e.label!==void 0&&n.push(`label=${e.label}`),e.overdue===!0&&n.push("overdue"),e.dueBefore!==void 0&&n.push(`due before ${e.dueBefore}`),n.length===0?`No tasks yet.
122
+ Create the first one:
123
+ kadence task add "title"`:`No tasks match ${n.join(" and ")}.
124
+ Try fewer filters:
125
+ kadence task list`}var q=["created","priority","due","estimate"];function ke(e){return q.includes(e)}import{isAbsolute as jt,join as Rt,relative as Nt}from"node:path";import{execFileSync as qe}from"node:child_process";function ye(e,n){try{return qe("git",n,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function be(e){let n=ye(e,["rev-parse","--show-toplevel"]);return n===null||n.length===0?null:n}function we(e){let n=ye(e,["config","user.email"]);return n===null||n.length===0?null:n}import{mkdirSync as tt,readdirSync as nt,readFileSync as rt,renameSync as st,rmSync as an,writeFileSync as it}from"node:fs";import{join as O}from"node:path";var Ze=["task.created","task.moved","task.assigned","task.commented","task.updated","task.cancelled","task.reopened","task.deleted","task.parent_set","task.blocked_by_added","task.blocked_by_removed","task.time_logged","task.doc_linked","template.saved","template.deleted","board.configured","sprint.created","sprint.started","sprint.updated","sprint.closed","sprint.cancelled","sprint.task_added","decision.recorded"],Ve=new Set(Ze),ve=/^[0-9ABCDEFGHJKMNPQRSTVWXYZ]{26}$/,ze=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?(Z|[+-]\d{2}:\d{2})$/;function Xe(e){return typeof e=="string"&&Ve.has(e)}function Qe(e){if(typeof e!="object"||e===null)return["event"];let n=e,r=[];if((typeof n.id!="string"||!ve.test(n.id))&&r.push("id"),Xe(n.type)||r.push("type"),(typeof n.entity!="string"||!ve.test(n.entity))&&r.push("entity"),(typeof n.actor!="string"||n.actor.length===0)&&r.push("actor"),(typeof n.ts!="string"||!ze.test(n.ts)||Number.isNaN(Date.parse(n.ts)))&&r.push("ts"),n.source!=="human"&&n.source!=="agent"&&r.push("source"),n.data!==void 0&&(typeof n.data!="object"||n.data===null)&&r.push("data"),n.type==="decision.recorded"){let t=n.data??{};for(let s of["title","why"]){let i=t[s];(typeof i!="string"||i.trim().length===0)&&r.push(`data.${s}`)}}return r}function Se(e){let n=e.data?.description;if(typeof n!="string"||!n.includes(`
126
+ `))return JSON.stringify(e);let r={...e,data:{...e.data,description:n.split(`
127
+ `)}};return JSON.stringify(r,null,2)}function z(e){let n;try{n=JSON.parse(e)}catch(t){return{event:null,error:`unreadable JSON: ${t.message}`,unknownType:!1}}n=et(n);let r=Qe(n);return r.length===1&&r[0]==="type"?{event:null,error:null,unknownType:!0}:r.length>0?{event:null,error:`invalid fields: ${r.join(", ")}`,unknownType:!1}:{event:n,error:null,unknownType:!1}}function et(e){if(typeof e!="object"||e===null)return e;let n=e,r=n.data;if(typeof r!="object"||r===null)return e;let t=r.description;return Array.isArray(t)?{...n,data:{...r,description:t.filter(s=>typeof s=="string").join(`
128
+ `)}}:e}var ot=.2;function M(e){return O(e,".kadence")}function U(e){return O(M(e),"events")}function at(e){return O(U(e),"archive")}function dt(e){return e.slice(0,7)}function E(e,n){let r=O(U(e),dt(n.ts));tt(r,{recursive:!0});let t=O(r,`${n.id}.json`),s=O(r,`.${n.id}.tmp`);it(s,`${Se(n)}
129
+ `,"utf8"),st(s,t)}function B(e){let n=U(e),r=[],t=[],s=new Set,i=0,o=X(at(e)),a=new Set(o);for(let u of X(n)){let l;try{l=rt(u,"utf8")}catch{t.push(u);continue}if(a.has(u)){let g;try{g=JSON.parse(l)}catch{t.push(u);continue}if(!Array.isArray(g)){t.push(u);continue}for(let m of g){let c=z(JSON.stringify(m));c.unknownType?i++:c.error!==null||c.event===null?t.push(u):s.has(c.event.id)||(s.add(c.event.id),r.push(c.event))}continue}let f=z(l);if(f.unknownType){i++;continue}if(f.error!==null||f.event===null){t.push(u);continue}s.has(f.event.id)||(s.add(f.event.id),r.push(f.event))}r.sort((u,l)=>u.id<l.id?-1:u.id>l.id?1:0);let d=r.length+t.length;return{events:r,corrupted:t,unknownTypes:i,systemicCorruption:d>0&&t.length/d>ot}}function X(e){let n;try{n=nt(e,{withFileTypes:!0})}catch{return[]}let r=[];for(let t of n){let s=O(e,t.name);t.isDirectory()?r.push(...X(s)):t.name.endsWith(".json")&&r.push(s)}return r}import{randomFillSync as ut}from"node:crypto";var xe="0123456789ABCDEFGHJKMNPQRSTVWXYZ",ct=10,lt=16,$e=2**48-1;function pt(e){let n="",r=e;for(let t=ct-1;t>=0;t--)n=xe[r%32]+n,r=Math.floor(r/32);return n}function ft(e){let n="",r=0,t=0;for(let s of e){for(r=r<<8|s,t+=8;t>=5;)t-=5,n+=xe[r>>>t&31];r&=(1<<t)-1}return n.slice(0,lt)}function gt(e){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r<255){e[n]=r+1;return}e[n]=0}throw new Error("ULID: random space exhausted within a single millisecond")}function mt(){let e=-1,n=new Uint8Array(10);return function(t=Date.now()){if(!Number.isInteger(t)||t<0||t>$e)throw new RangeError(`ULID: time out of range 0..${$e}: ${t}`);return t>e?(e=t,ut(n)):gt(n),pt(e)+ft(n)}}var x=mt();import{readFileSync as ht,writeFileSync as kt,renameSync as yt,readdirSync as bt,mkdirSync as wt}from"node:fs";import{join as Ee}from"node:path";var Te="kadence-snapshot/1";function Ce(e){return Ee(M(e),"state.json")}function _e(e,n){let r=vt(U(e)),t=St(e);if(t!==null&&t.version===Te&&t.lastEventId===r.lastEventId&&t.eventCount===r.count)return{state:t.state,fromCache:!0,incomingEvents:0};let s=B(e),i=ce(s.events),o=t===null||n===void 0?0:xt(s.events,t,n);return $t(e,{version:Te,lastEventId:r.lastEventId,eventCount:r.count,state:i}),{state:i,fromCache:!1,incomingEvents:o}}function vt(e){let n="",r=0,t=s=>{let i;try{i=bt(s,{withFileTypes:!0})}catch{return}for(let o of i)if(o.isDirectory())t(Ee(s,o.name));else if(o.name.endsWith(".json")){r++;let a=o.name.slice(0,-5);a>n&&(n=a)}};return t(e),{lastEventId:n,count:r}}function St(e){try{let n=JSON.parse(ht(Ce(e),"utf8"));if(typeof n!="object"||n===null)return null;let r=n;return typeof r.version!="string"||typeof r.lastEventId!="string"||typeof r.eventCount!="number"||typeof r.state!="object"?null:r}catch{return null}}function $t(e,n){try{wt(M(e),{recursive:!0});let r=Ce(e),t=`${r}.tmp`;kt(t,JSON.stringify(n),"utf8"),yt(t,r)}catch{}}function xt(e,n,r){let t=0,s=0;for(let o of e)o.id<=n.lastEventId?t++:o.actor!==r&&s++;let i=Math.max(0,t-n.eventCount);return s+i}var T={dim:"\x1B[2m",bold:"\x1B[1m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",reset:"\x1B[0m"};function ee(e,n){return e.NO_COLOR!==void 0?!1:n}function D(e,n,r){return r?`${n}${e}${T.reset}`:e}var Tt={done:T.green,in_progress:T.blue,blocked:T.yellow,cancelled:T.dim},Et=72;function je(e,n=Et){let r=[...e];return r.length<=n?e:`${r.slice(0,n-1).join("")}\u2026`}function Q(e){return[...e].length}function De(e,n){let r=n-Q(e);return r>0?e+" ".repeat(r):e}function Re(e,n){if(e.length===0)return`No tasks yet.
130
+ Create the first one:
131
+ kadence task add "title"`;let r=Math.max(...e.map(s=>Q(s.label)),2),t=Math.max(...e.map(s=>Q(s.status)),6);return e.map(s=>{let i=D(De(s.label,r),T.bold,n),o=D(De(s.status,t),Tt[s.status]??T.dim,n),a=s.estimate===null?"":D(` (${s.estimate})`,T.dim,n);return`${i} ${o} ${je(s.title)}${a}`}).join(`
132
+ `)}function Ne(e){return e<=0?null:`Merged ${e} ${e===1?"change":"changes"} from another branch, no conflicts.`}var Ct={urgent:"!!",high:"!",normal:"",low:"v"},_t={bug:"BUG",story:"STORY",task:""};function Ae(e,n){let r=[D(e.label,T.bold,n)],t=Ct[e.priority];t!==""&&r.push(D(t,e.priority==="low"?T.dim:T.yellow,n));let s=_t[e.type]??"";s!==""&&r.push(D(s,T.dim,n)),r.push(je(e.title));let i=[];return e.assignee!==null&&i.push(`@${e.assignee.split("@")[0]}`),e.estimate!==null&&i.push(`${e.estimate}`),i.length>0&&r.push(D(`(${i.join(", ")})`,T.dim,n)),` ${r.join(" ")}`}function yn(e,n){if(Object.values(e).reduce((s,i)=>s+i.length,0)===0)return`No tasks yet.
133
+ Create the first one:
134
+ kadence task add "title"`;let t=[];for(let[s,i]of Object.entries(e)){if(i.length===0)continue;let o=i.reduce((d,u)=>d+(u.estimate??0),0),a=o>0?` \u2014 ${o}`:"";t.push(D(`${s} (${i.length}${a})`,T.bold,n),...i.map(d=>Ae(d,n)),"")}return t.join(`
135
+ `).trimEnd()}function Dt(e,n=new Date){let r=Date.parse(`${e}T00:00:00.000Z`),t=Date.parse(`${n.toISOString().slice(0,10)}T00:00:00.000Z`);if(Number.isNaN(r))return"";let s=Math.round((r-t)/864e5);return s<0?` (overdue by ${-s} day${s===-1?"":"s"})`:s===0?" (today)":s===1?" (tomorrow)":s<=7?` (in ${s} days)`:""}function Oe(e,n){if(e.length===0)return`No tasks yet.
136
+ Create the first one:
137
+ kadence task add "title"`;let r=new Set(e.map(a=>a.id)),t=new Map;for(let a of e){let d=a.parent!==null&&r.has(a.parent)?a.parent:null,u=t.get(d)??[];u.push(a),t.set(d,u)}let s=[],i=new Set,o=(a,d)=>{if(!(d>10))for(let u of t.get(a)??[]){if(i.has(u.id))continue;i.add(u.id);let l=" ".repeat(d),f=u.blockedBy.length>0?D(" [blocked]",T.yellow,n):"";s.push(`${l}${Ae(u,n).trimStart()}${f}`),o(u.id,d+1)}};return o(null,0),s.join(`
138
+ `)}function Pe(e){let n=[`${e.label} ${e.title}`,""];if(e.description!==null&&n.push(e.description,""),n.push(` Status: ${e.status}`),n.push(` Type: ${e.type}`),n.push(` Priority: ${e.priority}`),e.labels.length>0&&n.push(` Labels: ${e.labels.join(", ")}`),e.parent!==null&&n.push(` Parent: ${e.parent}`),e.blockedBy.length>0&&n.push(` Blocked by: ${e.blockedBy.length} task(s)`),n.push(` Assignee: ${e.assignee??"\u2014"}`),n.push(` Reporter: ${e.reporter}`),e.due!==null&&n.push(` Due: ${e.due}${Dt(e.due)}`),n.push(` Estimate: ${e.estimate??"\u2014"}`),e.comments.length>0){n.push("",` Comments (${e.comments.length}):`);for(let r of e.comments){n.push(` ${r.author} \xB7 ${r.ts.slice(0,10)}`);for(let t of r.text.split(`
139
+ `))n.push(` ${t}`)}}if(e.history.length>0){n.push("",` History (${e.history.length}):`);for(let r of e.history){let t=r.type==="task.moved"?` \u2192 ${String(r.data.to)}`:"";n.push(` ${r.ts.slice(0,16).replace("T"," ")} ${r.actor} ${r.type}${t}`)}}return n.join(`
140
+ `)}import{existsSync as Ie}from"node:fs";var jn=G;function h(e,n,r,t={}){return{ok:!1,exitCode:e,message:r,error:{code:n,message:r,...t}}}function j(e){return h(1,"task_not_found",`No task ${e}.
141
+ kadence task list`,{received:e,hint:"kadence task list --json"})}function L(e,n,r,t){return h(2,e,`Unknown ${n} "${r}".
142
+ Available: ${t.join(", ")}`,{received:r,allowed:t})}function b(e,n){let r=be(e);if(r===null)return h(1,"not_a_repository",`kadence lives inside a git repository, and there is none here.
143
+ Create one and try again:
144
+ git init`,{hint:"git init"});if(!Ie(M(r)))return h(1,"not_initialised",`No .kadence/ found here.
145
+ Run:
146
+ npx kadence init`,{hint:"kadence init"});let t=we(r);if(t===null)return h(1,"no_git_identity",`Git does not know who you are, so there is no author for the event.
147
+ Run:
148
+ git config user.email you@example.com`,{hint:"git config user.email you@example.com"});let s=n.KADENCE_SOURCE==="agent"?"agent":"human";return{root:r,actor:t,source:s}}function w(e){return"root"in e}function Rn(e,n,r,t={}){let s=b(e,n);if(!w(s))return s;let i=r.trim();if(i.length===0)return h(2,"invalid_argument","A task needs a title.",{hint:"kadence task list --json"});if(t.type!==void 0&&!N.includes(t.type))return L("unknown_type","type",t.type,N);if(t.priority!==void 0&&!A.includes(t.priority))return L("unknown_priority","priority",t.priority,A);let o;if(t.parent!==void 0){let{state:l}=y(s.root,s.actor),f=C(l,t.parent);if(f===void 0)return{...j(t.parent)};o=f.id}let a=x(),d={id:a,type:"task.created",entity:a,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{title:i,...t.description!==void 0?{description:t.description}:{},...t.type!==void 0?{type:t.type}:{},...t.priority!==void 0?{priority:t.priority}:{},...t.assignee!==void 0?{assignee:t.assignee}:{},...t.labels!==void 0&&t.labels.length>0?{labels:t.labels}:{},...t.due!==void 0?{due:t.due}:{},...o!==void 0?{parent:o}:{},...t.estimate!==void 0?{estimate:t.estimate}:{}}};E(s.root,d);let u=t.estimate===void 0?`
149
+ Without an estimate this task will not count towards velocity. Add --estimate.`:"";return{ok:!0,exitCode:0,message:`Created: ${i}${u}`,data:{schema:"kadence/v1",ok:!0,task:{id:a,title:i}}}}function y(e,n){let r=_e(e,n),t=B(e),s=[],i=Ne(r.incomingEvents);return i!==null&&s.push(i),t.systemicCorruption?s.push(`The journal is badly damaged: ${t.corrupted.length} of ${t.corrupted.length+t.events.length} events are unreadable. Try: git checkout .kadence/`):t.corrupted.length>0&&s.push(`Skipped ${t.corrupted.length} corrupted event(s).`),t.unknownTypes>0&&s.push(`Skipped ${t.unknownTypes} event(s) from a newer format. Update kadence.`),{state:r.state,warnings:s}}function C(e,n){let r=n.toUpperCase();return e.tasks.find(t=>t.id===r||t.label===r)}function Fe(e,n){return h(2,"unknown_status",`Unknown status "${e}".
150
+ Available: ${n.join(", ")}
151
+ kadence board config --statuses "todo,doing,done"`,{received:e,allowed:n,hint:"kadence board config --json"})}function Nn(e,n,r){let t=b(e,n);if(!w(t))return t;if(r.type!==void 0&&!N.includes(r.type))return L("unknown_type","type",r.type,N);if(r.priority!==void 0&&!A.includes(r.priority))return L("unknown_priority","priority",r.priority,A);let{fields:s,error:i}=At(r.fields);if(i!==null)return i;if(r.sort!==void 0&&!ke(r.sort))return{...h(2,"invalid_argument",`Unknown sort key "${r.sort}".
152
+ Available: ${q.join(", ")}`,{received:r.sort,allowed:q})};let{state:o,warnings:a}=y(t.root,t.actor);if(r.status!==void 0&&!o.statuses.includes(r.status))return Fe(r.status,o.statuses);let{sort:d,tree:u,...l}=r,f=ge(o.tasks,l),g=d===void 0?f:me(f,d);return g.length===0?{ok:!0,exitCode:0,warnings:a,message:he(l),data:{schema:"kadence/v1",ok:!0,tasks:[]}}:{ok:!0,exitCode:0,warnings:a,message:u===!0?Oe(g,ee(n,process.stdout.isTTY===!0)):Re(g,ee(n,process.stdout.isTTY===!0)),data:{schema:"kadence/v1",ok:!0,tasks:g.map(m=>Me(m,s)),cycles:o.cycles}}}function An(e,n,r,t){let s=b(e,n);if(!w(s))return s;let{state:i,warnings:o}=y(s.root,s.actor);if(!i.statuses.includes(t))return Fe(t,i.statuses);let{tasks:a,error:d}=P(i,r);if(d!==null)return d;let u=[],l=[],f="";for(let m of a){if(m.status===t){l.push(m);continue}let c=m.status;E(s.root,{id:x(),type:"task.moved",entity:m.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{from:c,to:t}}),u.push(m),a.length===1&&i.statuses.indexOf(t)-i.statuses.indexOf(c)>1&&(f=`
153
+ Moved straight from ${c} to ${t}, skipping the stages between.`)}if(u.length===0)return{ok:!0,exitCode:0,warnings:o,message:S("already there",l,`is already ${t}.`)};let g=l.length>0?`
154
+ ${l.length} already ${t}.`:"";return{ok:!0,exitCode:0,warnings:o,message:`${S("moved",u,`${u[0].status} \u2192 ${t}`)}${f}${g}`,data:{schema:"kadence/v1",ok:!0,moved:u.map(m=>({id:m.id,label:m.label,to:t}))}}}function At(e){if(e===void 0)return{fields:null,error:null};let n=e.split(",").map(t=>t.trim()).filter(t=>t.length>0);if(n.length===0)return{fields:null,error:h(2,"invalid_argument","--fields needs at least one field name.",{allowed:F})};let r=n.find(t=>!F.includes(t));return r!==void 0?{fields:null,error:h(2,"unknown_field",`Unknown field "${r}".
155
+ Available: ${F.join(", ")}`,{received:r,allowed:F})}:{fields:n,error:null}}function Me(e,n=null){let r=Ot(e);return n===null?r:Object.fromEntries(n.map(t=>[t,r[t]]))}function Ot(e){return{id:e.id,label:e.label,title:e.title,description:e.description,type:e.type,priority:e.priority,status:e.status,labels:e.labels,assignee:e.assignee,reporter:e.reporter,sprint:e.sprint,loggedHours:e.loggedHours,parent:e.parent,blockedBy:e.blockedBy,due:e.due,comments:e.comments,docs:e.docs,estimate:e.estimate,history:e.history}}function On(e,n,r,t){let s=b(e,n);if(!w(s))return s;let{state:i,warnings:o}=y(s.root,s.actor),{tasks:a,error:d}=P(i,r);if(d!==null)return d;let u=t.trim().toLowerCase()==="none"?null:t.trim(),l=a.filter(f=>f.assignee!==u);if(l.length===0)return{ok:!0,exitCode:0,warnings:o,message:u===null?S("already unassigned",a,"is already unassigned."):S("already assigned",a,`is already assigned to ${u}.`)};for(let f of l)E(s.root,{id:x(),type:"task.assigned",entity:f.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{assignee:u}});return{ok:!0,exitCode:0,warnings:o,message:u===null?S("unassigned",l,"unassigned."):S("assigned",l,`\u2192 ${u}`),data:{schema:"kadence/v1",ok:!0,assigned:l.map(f=>({id:f.id,label:f.label,assignee:u}))}}}function Pn(e,n,r){let t=b(e,n);if(!w(t))return t;let{state:s,warnings:i}=y(t.root,t.actor),o=C(s,r);if(o===void 0)return j(r);let a=s.decisions.filter(d=>d.task===o.id&&d.supersededBy===null).map(d=>({id:d.id,label:d.label,title:d.title,why:d.why,rejected:d.rejected,docs:d.docs}));return{ok:!0,exitCode:0,warnings:i,message:Pe(o),data:{schema:"kadence/v1",ok:!0,task:{...Me(o),decisions:a}}}}function In(e,n,r,t){let s=b(e,n);if(!w(s))return s;if(t.type!==void 0&&!N.includes(t.type))return L("unknown_type","type",t.type,N);if(t.priority!==void 0&&!A.includes(t.priority))return L("unknown_priority","priority",t.priority,A);if(t.due!==void 0&&t.due!==""&&!Pt(t.due))return{...h(2,"invalid_argument",`Due date must be YYYY-MM-DD, got "${t.due}".
156
+ kadence task edit KAD-1 --due 2026-09-30`,{received:t.due})};let{state:i,warnings:o}=y(s.root,s.actor),{tasks:a,error:d}=P(i,r);if(d!==null)return d;if(t.title!==void 0&&a.length>1)return{...h(2,"invalid_argument","A title can only be set on one task at a time.")};let u=[],l=new Set;for(let g of a){let m={},c=[];if(t.title!==void 0&&t.title!==g.title&&(m.title=t.title,c.push("title")),t.description!==void 0&&t.description!==(g.description??"")&&(m.description=t.description,c.push("description")),t.type!==void 0&&t.type!==g.type&&(m.type=t.type,c.push("type")),t.priority!==void 0&&t.priority!==g.priority&&(m.priority=t.priority,c.push("priority")),t.due!==void 0&&t.due!==(g.due??"")&&(m.due=t.due,c.push("due")),t.estimate!==void 0&&t.estimate!==g.estimate&&(m.estimate=t.estimate,c.push("estimate")),t.labels!==void 0&&t.labels.join(",")!==g.labels.join(",")&&(m.labels=t.labels,c.push("labels")),c.length!==0){E(s.root,{id:x(),type:"task.updated",entity:g.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:m}),u.push(g);for(let p of c)l.add(p)}}if(u.length===0)return{ok:!0,exitCode:0,warnings:o,message:S("unchanged",a,"nothing changed.")};let f=[...l].join(", ");return{ok:!0,exitCode:0,warnings:o,message:S("updated",u,`updated ${f}.`),data:{schema:"kadence/v1",ok:!0,updated:u.map(g=>({id:g.id,label:g.label})),changed:[...l]}}}function Pt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;let n=new Date(`${e}T00:00:00.000Z`);return!Number.isNaN(n.getTime())&&n.toISOString().slice(0,10)===e}function Fn(e,n,r){let t=b(e,n);if(!w(t))return t;let{state:s,warnings:i}=y(t.root,t.actor),{tasks:o,error:a}=P(s,r);if(a!==null)return a;let d=o.filter(u=>u.status!=="cancelled");if(d.length===0)return{ok:!0,exitCode:0,warnings:i,message:S("already cancelled",o,"is already cancelled.")};for(let u of d)E(t.root,{id:x(),type:"task.cancelled",entity:u.id,actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{}});return{ok:!0,exitCode:0,warnings:i,message:`${S("cancelled",d,"cancelled.")}
157
+ Cancelled work stays in history and does not count as missed.`,data:{schema:"kadence/v1",ok:!0,cancelled:d.map(u=>({id:u.id,label:u.label}))}}}function Mn(e,n,r){let t=b(e,n);if(!w(t))return t;let{state:s,warnings:i}=y(t.root,t.actor),{tasks:o,error:a}=P(s,r);if(a!==null)return a;for(let u of o)E(t.root,{id:x(),type:"task.deleted",entity:u.id,actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{title:u.title}});let d=o.length===1?`${o[0].label} deleted: "${o[0].title}".`:`${o.length} tasks deleted: ${o.map(u=>u.label).join(", ")}.`;return{ok:!0,exitCode:0,warnings:i,message:`${d}
158
+ The events stay in the journal \u2014 history is never rewritten.`,data:{schema:"kadence/v1",ok:!0,deleted:o.map(u=>({id:u.id,label:u.label}))}}}function Bn(e,n,r,t){let s=b(e,n);if(!w(s))return s;let i=t.trim();if(i.length===0)return h(2,"invalid_argument","A link needs a path.",{hint:"kadence task doc KAD-1 docs/design.md"});let{state:o,warnings:a}=y(s.root,s.actor),d=C(o,r);if(d===void 0)return j(r);let u=jt(i)?Nt(s.root,i):i.replace(/^\.\//,""),l=!Ie(Rt(s.root,u));return E(s.root,{id:x(),type:"task.doc_linked",entity:d.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{path:u}}),{ok:!0,exitCode:0,warnings:[...a,...l?[`No file at ${u} \u2014 the link is recorded anyway; it may arrive later.`]:[]],message:`${u} linked to ${d.label}.`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label},doc:u}}}function Ln(e,n,r,t){let s=b(e,n);if(!w(s))return s;let i=t.trim();if(i.length===0)return h(2,"invalid_argument","A comment needs text.",{received:r});let{state:o,warnings:a}=y(s.root,s.actor),d=C(o,r);return d===void 0?j(r):(E(s.root,{id:x(),type:"task.commented",entity:d.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{text:i}}),{ok:!0,exitCode:0,warnings:a,message:`Comment added to ${d.label}.`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label}}})}function P(e,n){let r=n.split(",").map(o=>o.trim()).filter(o=>o.length>0);if(r.length===0)return{tasks:[],error:h(2,"invalid_argument","No task given.")};let t=[],s=[];for(let o of r){let a=C(e,o);a===void 0?s.push(o):t.push(a)}return s.length>0?{tasks:[],error:h(1,"task_not_found",`No task ${s.join(", ")} \u2014 nothing was changed.
159
+ All ids must exist before a bulk change runs.
160
+ kadence task list`,{received:s.join(","),hint:"kadence task list --json"})}:{tasks:[...new Map(t.map(o=>[o.id,o])).values()],error:null}}function S(e,n,r){return n.length===1?`${n[0].label}: ${r}`:`${n.length} tasks ${e}: ${n.map(t=>t.label).join(", ")}`}function Kn(e,n,r,t){let s=b(e,n);if(!w(s))return s;let{state:i,warnings:o}=y(s.root,s.actor),{tasks:a,error:d}=P(i,r);if(d!==null)return d;let u=t.trim().toLowerCase()==="none",l=null;if(!u){let m=C(i,t);if(m===void 0)return j(t);if(a.some(c=>c.id===m.id))return h(2,"invalid_argument","A task cannot be its own parent.",{received:r});l=m.id}let f=a.filter(m=>m.parent!==l);if(f.length===0)return{ok:!0,exitCode:0,warnings:o,message:S("unchanged",a,"already there.")};for(let m of f)E(s.root,{id:x(),type:"task.parent_set",entity:m.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{parent:l}});let g=u?"detached":C(i,t).label;return{ok:!0,exitCode:0,warnings:[...o,...Be(s.root,s.actor)],message:u?S("detached",f,"detached from its parent."):S("moved",f,`\u2192 child of ${g}`),data:{schema:"kadence/v1",ok:!0,parent:l}}}function Jn(e,n,r,t,s){let i=b(e,n);if(!w(i))return i;let{state:o,warnings:a}=y(i.root,i.actor),{tasks:d,error:u}=P(o,r);if(u!==null)return u;let l=C(o,t);if(l===void 0)return j(t);if(d.some(g=>g.id===l.id))return h(2,"invalid_argument","A task cannot block itself.",{received:r});let f=d.filter(g=>s?g.blockedBy.includes(l.id):!g.blockedBy.includes(l.id));if(f.length===0)return{ok:!0,exitCode:0,warnings:a,message:S("unchanged",d,s?"was not blocked by it.":"is already blocked by it.")};for(let g of f)E(i.root,{id:x(),type:s?"task.blocked_by_removed":"task.blocked_by_added",entity:g.id,actor:i.actor,ts:new Date().toISOString(),source:i.source,data:{blocker:l.id}});return{ok:!0,exitCode:0,warnings:[...a,...Be(i.root,i.actor)],message:s?S("unblocked",f,`no longer blocked by ${l.label}.`):S("blocked",f,`blocked by ${l.label}.`),data:{schema:"kadence/v1",ok:!0,blocker:l.id}}}function Be(e,n){let{state:r}=y(e,n),t=new Map(r.tasks.map(s=>[s.id,s.label]));return r.cycles.map(s=>{let i=s.path.map(o=>t.get(o)??o).join(" \u2192 ");return`Dependency cycle (${s.kind}): ${i}. Both edges were kept \u2014 resolve it when you can.`})}function It(e){let n=/^(-?\d+(?:\.\d+)?)\s*(h|hours?|m|min|minutes?)?$/i.exec(e.trim());if(n===null)return null;let r=Number(n[1]);return!Number.isFinite(r)||r===0?null:(n[2]??"h").toLowerCase().startsWith("m")?r/60:r}function Un(e,n,r,t){let s=b(e,n);if(!w(s))return s;let i=It(t);if(i===null)return{...h(2,"invalid_argument",`Cannot read "${t}" as a duration.
161
+ Use hours or minutes:
162
+ kadence task log KAD-1 2h
163
+ kadence task log KAD-1 90m
164
+ kadence task log KAD-1 -30m to correct a mistake`,{received:t})};let{state:o,warnings:a}=y(s.root,s.actor),d=C(o,r);if(d===void 0)return j(r);E(s.root,{id:x(),type:"task.time_logged",entity:d.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{hours:i}});let u=Math.max(0,d.loggedHours+i),l=d.estimate===null?`
165
+ No estimate on this task, so there is nothing to compare against.`:"";return{ok:!0,exitCode:0,warnings:a,message:`${d.label}: ${u.toFixed(1)}h logged in total.${l}`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label,loggedHours:u}}}}import{spawnSync as Ft}from"node:child_process";import{mkdtempSync as Mt,readFileSync as Bt,rmSync as Lt,writeFileSync as Kt}from"node:fs";import{tmpdir as Jt}from"node:os";import{join as Le}from"node:path";var H="#";function Ut(e){return e.GIT_EDITOR??e.VISUAL??e.EDITOR??"vi"}function Zn(e,n,r){let t=Mt(Le(Jt(),"kadence-edit-")),s=Le(t,"KADENCE_EDITMSG.md"),i=["",`${H} ${r}`,`${H} Lines starting with '${H}' are ignored.`,`${H} Save an empty file to abort.`].join(`
166
+ `);try{Kt(s,`${n}${i}
167
+ `,"utf8");let o=Ut(e),a=Ft(o,[s],{stdio:"inherit",shell:!0});if(a.error!==void 0||a.status!==null&&a.status!==0)return{text:null,error:`Editor "${o}" exited without saving.
168
+ Set one explicitly:
169
+ export EDITOR=nano`};let u=Bt(s,"utf8").split(`
170
+ `).filter(l=>!l.startsWith(H)).join(`
171
+ `).trim();return{text:u.length===0?null:u,error:null}}catch(o){return{text:null,error:`Could not open an editor: ${o.message}`}}finally{Lt(t,{recursive:!0,force:!0})}}function Vn(e,n){return e.KADENCE_SOURCE==="agent"?!1:n}function te(e,n){let r=e.sprints.find(p=>p.id===n);if(r===void 0)return null;let t=e.tasks.filter(p=>p.sprint===n),s=t.filter(p=>p.status==="cancelled"),i=t.filter(p=>p.status!=="cancelled"),o=i.filter(p=>p.status==="done"),a=i.filter(p=>p.status!=="done"),d=W(i.map(p=>p.estimate??0)),u=W(o.map(p=>p.estimate??0)),l=o.filter(p=>p.estimate===null),f=o.map(Ht).filter(p=>p!==null),g=f.length>0?W(f):null,m=W(o.filter(p=>p.estimate!==null).map(p=>p.estimate)),c=g!==null&&m>0?g/m:null;return{id:r.id,name:r.name,status:r.status,committed:d,velocity:u,actualHours:g,hoursPerPoint:c,done:o,carriedOver:a,cancelled:s,unestimated:l,loggedHours:W(t.map(p=>p.loggedHours))}}function Ht(e){let n=e.history.find(s=>s.type==="task.moved"&&s.data.to==="in_progress"),r=[...e.history].reverse().find(s=>s.type==="task.moved"&&s.data.to==="done");if(n===void 0||r===void 0)return null;let t=Date.parse(r.ts)-Date.parse(n.ts);return t>0?t/36e5:null}function W(e){return e.reduce((n,r)=>n+r,0)}function Y(e){return new Date(e).toISOString().slice(0,10)}function Wt(e,n){let r=[];for(let t=Date.parse(`${e}T00:00:00.000Z`);t<=Date.parse(`${n}T00:00:00.000Z`);t+=864e5)r.push(Y(t));return r}function Ke(e,n,r,t=Y(Date.now())){let s=e.tasks.filter(k=>k.sprint===r.id&&k.status!=="cancelled"),i=new Map(s.map(k=>[k.id,k.estimate??0])),o=[...i.values()].reduce((k,$)=>k+$,0),a=n.filter(k=>i.has(k.entity));if(a.length===0)return null;let d=r.startDate??Y(a[0].ts),u=r.endDate??Y(a.at(-1).ts),l=r.status==="closed"||u<t?u:t;if(l<d)return null;let f=new Set,g=new Map;for(let k of a){let $=Y(k.ts);if($<d)continue;let _=k.type==="task.moved"?k.data?.to:void 0,R=i.get(k.entity)??0;_==="done"&&!f.has(k.entity)?(f.add(k.entity),g.set($,(g.get($)??0)+R)):_!==void 0&&_!=="done"&&f.has(k.entity)&&(f.delete(k.entity),g.set($,(g.get($)??0)-R))}let m=Wt(d,l),c=Math.max(m.length-1,1),p=o;return{sprintName:r.name,committed:o,finalRemaining:(r.status==="closed",null),days:m.map((k,$)=>{let _=g.get(k)??0;return p-=_,{date:k,remaining:Math.max(0,p),ideal:Math.max(0,o-o/c*$),completed:_}})}}function Je(e,n=40){if(e.committed===0)return`"${e.sprintName}": nothing to burn down \u2014 no estimated tasks.`;let r=[`"${e.sprintName}" \u2014 ${e.committed} points committed`,""];for(let s of e.days){let i=Math.round(s.remaining/e.committed*n),o=Math.round(s.ideal/e.committed*n),a=[];for(let l=0;l<n;l++)l===o&&l>=i?a.push("\u250A"):l<i?a.push(l===o?"\u2503":"\u2588"):a.push(" ");let d=s.remaining-s.ideal,u=Math.abs(d)<.5?"":d>0?` +${d.toFixed(0)}`:` ${d.toFixed(0)}`;r.push(`${s.date.slice(5)} ${a.join("")} ${String(s.remaining).padStart(3)}${u}`)}let t=e.days.at(-1);return t!==void 0&&(r.push(""),r.push(t.remaining===0?" All committed work is done.":` ${t.remaining} of ${e.committed} points remain.`+(t.remaining>t.ideal?" Behind the ideal line.":" On or ahead of the line."))),r.join(`
172
+ `)}function I(e){return e.sprints.find(n=>n.status==="active")}function Yt(e){return e.sprints.filter(n=>n.status==="planned")}function K(e,n){let r=n.trim().toLowerCase();return e.sprints.find(t=>t.name.toLowerCase()===r)}function J(e,n,r,t){E(e.root,{id:x(),type:n,entity:r,actor:e.actor,ts:new Date().toISOString(),source:e.source,data:t})}function or(e,n,r){let t=b(e,n);if(!w(t))return t;let s=r.trim();if(s.length===0)return h(2,"invalid_argument","A sprint needs a name.",{hint:"kadence sprint list --json"});let{state:i,warnings:o}=y(t.root,t.actor);if(K(i,s)!==void 0)return h(2,"invalid_argument",`Sprint "${s}" already exists.`,{received:s,hint:"kadence sprint list --json"});let a=I(i)!==void 0,d=x();return J(t,"sprint.created",d,{name:s}),a||J(t,"sprint.started",d,{}),{ok:!0,exitCode:0,warnings:o,message:a?`Sprint "${s}" planned.
173
+
174
+ kadence sprint add KAD-1 --sprint "${s}"
175
+ kadence sprint start "${s}"`:`Sprint "${s}" started.
176
+
177
+ kadence sprint add KAD-1
178
+ kadence sprint status`,data:{schema:"kadence/v1",ok:!0,sprint:{id:d,name:s,status:a?"planned":"active"}}}}function ar(e,n,r,t={}){let s=b(e,n);if(!w(s))return s;let{state:i,warnings:o}=y(s.root,s.actor),a=t.sprint===void 0?I(i):K(i,t.sprint);if(a===void 0)return t.sprint===void 0?{...h(1,"sprint_not_found",`No active sprint.
179
+ kadence sprint create "Sprint 1"`,{hint:"kadence sprint list --json"})}:h(1,"sprint_not_found",`No sprint named "${t.sprint}".
180
+ kadence sprint list`,{received:t.sprint,hint:"kadence sprint list --json"});if(a.status==="closed")return h(1,"conflicting_state",`Sprint "${a.name}" is closed \u2014 its velocity is not rewritten.`,{received:a.name});let d=C(i,r);if(d===void 0)return j(r);if(d.sprint===a.id)return{ok:!0,exitCode:0,warnings:o,message:`${d.label} is already in the sprint.`};J(s,"sprint.task_added",a.id,{task:d.id});let u=d.estimate===null?`
181
+ Without an estimate this task will not count towards velocity.`:"";return{ok:!0,exitCode:0,warnings:o,message:`${d.label} \u2192 "${a.name}"${u}`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label},sprint:a.id}}}function dr(e,n){let r=b(e,n);if(!w(r))return r;let{state:t,warnings:s}=y(r.root,r.actor),i=I(t);if(i===void 0)return{...h(1,"sprint_not_found",`No active sprint.
182
+ kadence sprint create "Sprint 1"`,{hint:"kadence sprint list --json"})};let o=te(t,i.id);J(r,"sprint.closed",i.id,{velocity:o.velocity});let a=[...s];return o.unestimated.length>0&&a.push(`${o.unestimated.length} completed task(s) without an estimate were left out of velocity: `+o.unestimated.map(d=>d.label).join(", ")),{ok:!0,exitCode:0,warnings:a,message:Gt(o),data:{schema:"kadence/v1",ok:!0,report:Ue(o)}}}function ur(e,n){let r=b(e,n);if(!w(r))return r;let{state:t,warnings:s}=y(r.root,r.actor),i=I(t);if(i===void 0)return{ok:!0,exitCode:0,warnings:s,message:`No active sprint.
183
+ kadence sprint create "Sprint 1"`,data:{schema:"kadence/v1",ok:!0,sprint:null}};let o=te(t,i.id),a=[`"${o.name}" \u2014 ${o.velocity} of ${o.committed} points`,"",...o.done.map(d=>` \u2713 ${d.label} ${d.title}`),...o.carriedOver.map(d=>` \xB7 ${d.label} ${d.title} (${d.status})`)];return{ok:!0,exitCode:0,warnings:s,message:a.join(`
184
+ `),data:{schema:"kadence/v1",ok:!0,report:Ue(o)}}}function Gt(e){let n=[`Sprint "${e.name}" closed.`,""];if(n.push(` Velocity: ${e.velocity} of ${e.committed} points`),e.hoursPerPoint!==null&&e.actualHours!==null&&e.actualHours>=1/60&&n.push(` Actual: ${ne(e.actualHours)} \u2014 ${ne(e.hoursPerPoint)} per point`),e.loggedHours>0&&n.push(` Logged: ${ne(e.loggedHours)} entered by hand`),e.carriedOver.length>0){n.push("",` Carried over (${e.carriedOver.length}):`);for(let r of e.carriedOver)n.push(` \xB7 ${r.label} ${r.title}`)}return e.cancelled.length>0&&n.push("",` Cancelled (${e.cancelled.length}) \u2014 not counted towards velocity`),n.join(`
185
+ `)}function ne(e){return e<1?`${Math.round(e*60)}m`:e<10?`${e.toFixed(1)}h`:`${Math.round(e)}h`}function Ue(e){return{id:e.id,name:e.name,status:e.status,velocity:e.velocity,committed:e.committed,actualHours:e.actualHours,hoursPerPoint:e.hoursPerPoint,done:e.done.map(n=>n.label),carriedOver:e.carriedOver.map(n=>n.label),cancelled:e.cancelled.map(n=>n.label),unestimated:e.unestimated.map(n=>n.label),loggedHours:e.loggedHours}}function cr(e,n,r){let t=b(e,n);if(!w(t))return t;let{state:s,warnings:i}=y(t.root,t.actor),o=I(s);if(o!==void 0)return{...h(1,"conflicting_state",`Sprint "${o.name}" is still active.
186
+ Close it so velocity can be computed:
187
+ kadence sprint close`,{received:o.name})};let a=Yt(s),d=r===void 0?a[0]:K(s,r);return d===void 0?{...h(1,"sprint_not_found",r===void 0?`No planned sprints.
188
+ kadence sprint create "Sprint 2"`:`No sprint named "${r}".
189
+ kadence sprint list`,{...r!==void 0?{received:r}:{},hint:"kadence sprint list --json"})}:d.status!=="planned"?h(1,"conflicting_state",`Sprint "${d.name}" is already ${d.status}.`,{received:d.name}):(J(t,"sprint.started",d.id,{}),{ok:!0,exitCode:0,warnings:i,message:`Sprint "${d.name}" started.
190
+
191
+ kadence sprint status`,data:{schema:"kadence/v1",ok:!0,sprint:{id:d.id,name:d.name}}})}function lr(e,n){let r=b(e,n);if(!w(r))return r;let{state:t,warnings:s}=y(r.root,r.actor);if(t.sprints.length===0)return{ok:!0,exitCode:0,warnings:s,message:`No sprints yet.
192
+ kadence sprint create "Sprint 1"`,data:{schema:"kadence/v1",ok:!0,sprints:[]}};let i=t.sprints.map(o=>{let a=t.tasks.filter(u=>u.sprint===o.id),d=a.reduce((u,l)=>u+(l.estimate??0),0);return{sprint:o,tasks:a,points:d}});return{ok:!0,exitCode:0,warnings:s,message:i.map(({sprint:o,tasks:a,points:d})=>{let u=o.status==="active"?"\u2192":" ",l=a.length===0?"":` ${a.length} tasks, ${d} points`;return`${u} ${o.name.padEnd(20)} ${o.status.padEnd(8)}${l}`}).join(`
193
+ `),data:{schema:"kadence/v1",ok:!0,sprints:i.map(({sprint:o,tasks:a,points:d})=>({id:o.id,name:o.name,status:o.status,taskIds:o.taskIds,taskCount:a.length,points:d}))}}}function qt(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;let n=new Date(`${e}T00:00:00.000Z`);return!Number.isNaN(n.getTime())&&n.toISOString().slice(0,10)===e}function pr(e,n,r,t){let s=b(e,n);if(!w(s))return s;for(let[g,m]of[["--start",t.startDate],["--end",t.endDate]])if(m!==void 0&&m!==""&&!qt(m))return{...h(2,"invalid_argument",`${g} must be YYYY-MM-DD, got "${m}".
194
+ kadence sprint edit --start 2026-09-01`,{received:m})};let{state:i,warnings:o}=y(s.root,s.actor),a=r===void 0?I(i):K(i,r);if(a===void 0)return{...h(1,"sprint_not_found",r===void 0?`No active sprint.
195
+ kadence sprint list`:`No sprint named "${r}".
196
+ kadence sprint list`,{...r!==void 0?{received:r}:{},hint:"kadence sprint list --json"})};if(a.status==="closed")return{...h(1,"conflicting_state",`Sprint "${a.name}" is closed \u2014 its record is not rewritten.`,{received:a.name})};if(t.name!==void 0&&t.name!==a.name&&K(i,t.name)!==void 0)return h(2,"invalid_argument",`Sprint "${t.name}" already exists.`,{received:t.name});let d=t.startDate??a.startDate??"",u=t.endDate??a.endDate??"";if(d!==""&&u!==""&&u<d)return{...h(2,"invalid_argument",`The end date (${u}) is before the start date (${d}).`,{received:u})};let l={},f=[];return t.name!==void 0&&t.name!==a.name&&(l.name=t.name,f.push("name")),t.description!==void 0&&t.description!==(a.description??"")&&(l.description=t.description,f.push("description")),t.startDate!==void 0&&t.startDate!==(a.startDate??"")&&(l.startDate=t.startDate,f.push("start")),t.endDate!==void 0&&t.endDate!==(a.endDate??"")&&(l.endDate=t.endDate,f.push("end")),f.length===0?{ok:!0,exitCode:0,warnings:o,message:`"${a.name}": nothing changed.`}:(J(s,"sprint.updated",a.id,l),{ok:!0,exitCode:0,warnings:o,message:`"${a.name}": updated ${f.join(", ")}.`,data:{schema:"kadence/v1",ok:!0,sprint:{id:a.id,changed:f}}})}function fr(e,n,r){let t=b(e,n);if(!w(t))return t;let{state:s,warnings:i}=y(t.root,t.actor),o=r===void 0?I(s):K(s,r);if(o===void 0)return{...h(1,"sprint_not_found",r===void 0?`No active sprint.
197
+ kadence sprint list`:`No sprint named "${r}".
198
+ kadence sprint list`,{...r!==void 0?{received:r}:{},hint:"kadence sprint list --json"})};let a=Ke(s,B(t.root).events,o);return a===null?{ok:!0,exitCode:0,warnings:i,message:`"${o.name}" has no tasks yet.
199
+ kadence sprint add KAD-1`,data:{schema:"kadence/v1",ok:!0,burndown:null}}:{ok:!0,exitCode:0,warnings:i,message:Je(a),data:{schema:"kadence/v1",ok:!0,burndown:a}}}export{be as a,M as b,U as c,E as d,Zt as e,Vt as f,zt as g,x as h,Qt as i,Ye as j,N as k,A as l,ee as m,yn as n,q as o,jn as p,h as q,j as r,b as s,w as t,Rn as u,y as v,C as w,Nn as x,An as y,At as z,Me as A,On as B,Pn as C,In as D,Fn as E,Mn as F,Bn as G,Ln as H,Kn as I,Jn as J,Un as K,Zn as L,Vn as M,or as N,ar as O,dr as P,ur as Q,cr as R,lr as S,pr as T,fr as U};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{A as u,C as S,D as k,G as x,H as C,I as h,K as y,L as E,M as A,N,Q as F,q as b,r as T,s as c,t as l,v as d,y as f}from"./chunk-JA73FCAN.js";async function $(r,e){let a=b(r,e);if(!T(a))return a;if(process.stdout.isTTY!==!0)return{ok:!1,exitCode:1,message:`The interactive board needs a terminal.
2
+ import{B as f,D as u,F as S,H as k,K as x,L as C,M as h,O as y,P as E,Q as A,R as N,U as F,s as b,t as T,u as c,v as l,y as d}from"./chunk-RINJ2CTH.js";async function $(r,e){let a=b(r,e);if(!T(a))return a;if(process.stdout.isTTY!==!0)return{ok:!1,exitCode:1,message:`The interactive board needs a terminal.
3
3
  For pipes and scripts use:
4
4
  kadence board --json`};let g;try{g=await import("./board-7RVHIQJQ.js")}catch(t){return{ok:!1,exitCode:1,message:`The interactive board could not start: ${t.message}
5
5
  The plain board always works:
package/dist/cli.js CHANGED
@@ -1,44 +1,54 @@
1
1
  #!/usr/bin/env node
2
- import{A as ne,B as se,C as ie,D as ae,E as re,F as oe,G as K,H as de,I as ce,J as le,K as ue,L as me,M as fe,N as pe,O as he,P as ge,Q as ke,a as F,b as L,c as E,d as C,e as U,f as q,g as Y,h as b,i as O,j as P,k as V,l as W,m as G,n as J,o as H,p as T,q as y,r as x,s as z,t as v,u as Q,v as X,w as Z,x as ee,y as te,z as j}from"./chunks/chunk-JA73FCAN.js";function N(n){return n==null?[]:Array.isArray(n)?n:[n]}function Ie(n,t,s,e){var i,a=n[t],r=~e.string.indexOf(t)?s==null||s===!0?"":String(s):typeof s=="boolean"?s:~e.boolean.indexOf(t)?s==="false"?!1:s==="true"||(n._.push((i=+s,i*0===0?i:s)),!!s):(i=+s,i*0===0?i:s);n[t]=a==null?r:Array.isArray(a)?a.concat(r):[a,r]}function Be(n,t){n=n||[],t=t||{};var s,e,i,a,r,d={_:[]},o=0,l=0,u=0,m=n.length;let k=t.alias!==void 0,p=t.unknown!==void 0,h=t.default!==void 0;if(t.alias=t.alias||{},t.string=N(t.string),t.boolean=N(t.boolean),k)for(s in t.alias)for(e=t.alias[s]=N(t.alias[s]),o=0;o<e.length;o++)(t.alias[e[o]]=e.concat(s)).splice(o,1);for(o=t.boolean.length;o-- >0;)for(e=t.alias[t.boolean[o]]||[],l=e.length;l-- >0;)t.boolean.push(e[l]);for(o=t.string.length;o-- >0;)for(e=t.alias[t.string[o]]||[],l=e.length;l-- >0;)t.string.push(e[l]);if(h){for(s in t.default)if(a=typeof t.default[s],e=t.alias[s]=t.alias[s]||[],t[a]!==void 0)for(t[a].push(s),o=0;o<e.length;o++)t[a].push(e[o])}let w=p?Object.keys(t.alias):[];for(o=0;o<m;o++){if(i=n[o],i==="--"){d._=d._.concat(n.slice(++o));break}for(l=0;l<i.length&&i.charCodeAt(l)===45;l++);if(l===0)d._.push(i);else if(i.substring(l,l+3)==="no-"){if(a=i.substring(l+3),p&&!~w.indexOf(a))return t.unknown(i);d[a]=!1}else{for(u=l+1;u<i.length&&i.charCodeAt(u)!==61;u++);for(a=i.substring(l,u),r=i.substring(++u)||o+1===m||(""+n[o+1]).charCodeAt(0)===45||n[++o],e=l===2?[a]:a,u=0;u<e.length;u++){if(a=e[u],p&&!~w.indexOf(a))return t.unknown("-".repeat(l)+a);Ie(d,a,u+1<e.length||r,t)}}}if(h)for(s in t.default)d[s]===void 0&&(d[s]=t.default[s]);if(k)for(s in d)for(e=t.alias[s]||[];e.length>0;)d[e.shift()]=d[s];return d}function xe(n){return n.replace(/[<[].+/,"").trim()}function Me(n){let t=/<([^>]+)>/g,s=/\[([^\]]+)\]/g,e=[],i=d=>{let o=!1,l=d[1];return l.startsWith("...")&&(l=l.slice(3),o=!0),{required:d[0].startsWith("<"),value:l,variadic:o}},a;for(;a=t.exec(n);)e.push(i(a));let r;for(;r=s.exec(n);)e.push(i(r));return e}function Fe(n){let t={alias:{},boolean:[]};for(let[s,e]of n.entries())e.names.length>1&&(t.alias[e.names[0]]=e.names.slice(1)),e.isBoolean&&(e.negated&&n.some((i,a)=>a!==s&&i.names.some(r=>e.names.includes(r))&&typeof i.required=="boolean")||t.boolean.push(e.names[0]));return t}function be(n){return n.sort((t,s)=>t.length>s.length?-1:1)[0]}function ye(n,t){return n.length>=t?n:`${n}${" ".repeat(t-n.length)}`}function Le(n){return n.replaceAll(/([a-z])-([a-z])/g,(t,s,e)=>s+e.toUpperCase())}function Ue(n,t,s){let e=n;for(let i=0;i<t.length;i++){let a=t[i];if(i===t.length-1){e[a]=s;return}if(e[a]==null){let r=+t[i+1]>-1;e[a]=r?[]:{}}e=e[a]}}function qe(n,t){for(let s of Object.keys(t)){let e=t[s];e.shouldTransform&&(n[s]=[n[s]].flat(),typeof e.transformFunction=="function"&&(n[s]=n[s].map(e.transformFunction)))}}function Ye(n){let t=/([^\\/]+)$/.exec(n);return t?t[1]:""}function ve(n){return n.split(".").map((t,s)=>s===0?Le(t):t).join(".")}var D=class extends Error{constructor(n){super(n),this.name="CACError",typeof Error.captureStackTrace!="function"&&(this.stack=new Error(n).stack)}},Pe=class{rawName;description;name;names;isBoolean;required;config;negated;constructor(n,t,s){this.rawName=n,this.description=t,this.config=Object.assign({},s),n=n.replaceAll(".*",""),this.negated=!1,this.names=xe(n).split(",").map(e=>{let i=e.trim().replace(/^-{1,2}/,"");return i.startsWith("no-")&&(this.negated=!0,i=i.replace(/^no-/,"")),ve(i)}).sort((e,i)=>e.length>i.length?1:-1),this.name=this.names.at(-1),this.negated&&this.config.default==null&&(this.config.default=!0),n.includes("<")?this.required=!0:n.includes("[")?this.required=!1:this.isBoolean=!0}},R,$;if(typeof process<"u"){let n;typeof Deno<"u"&&typeof Deno.version?.deno=="string"?n="deno":typeof Bun<"u"&&typeof Bun.version=="string"?n="bun":n="node",$=`${process.platform}-${process.arch} ${n}-${process.version}`,R=process.argv}else typeof navigator>"u"?$="unknown":$=`${navigator.platform} ${navigator.userAgent}`;var Ae=class{rawName;description;config;cli;options;aliasNames;name;args;commandAction;usageText;versionNumber;examples;helpCallback;globalCommand;constructor(n,t,s={},e){this.rawName=n,this.description=t,this.config=s,this.cli=e,this.options=[],this.aliasNames=[],this.name=xe(n),this.args=Me(n),this.examples=[]}usage(n){return this.usageText=n,this}allowUnknownOptions(){return this.config.allowUnknownOptions=!0,this}ignoreOptionDefaultValue(){return this.config.ignoreOptionDefaultValue=!0,this}version(n,t="-v, --version"){return this.versionNumber=n,this.option(t,"Display version number"),this}example(n){return this.examples.push(n),this}option(n,t,s){let e=new Pe(n,t,s);return this.options.push(e),this}alias(n){return this.aliasNames.push(n),this}action(n){return this.commandAction=n,this}isMatched(n){return this.name===n||this.aliasNames.includes(n)}get isDefaultCommand(){return this.name===""||this.aliasNames.includes("!")}get isGlobalCommand(){return this instanceof we}hasOption(n){return n=n.split(".")[0],this.options.find(t=>t.names.includes(n))}outputHelp(){let{name:n,commands:t}=this.cli,{versionNumber:s,options:e,helpCallback:i}=this.cli.globalCommand,a=[{body:`${n}${s?`/${s}`:""}`}];if(a.push({title:"Usage",body:` $ ${n} ${this.usageText||this.rawName}`}),(this.isGlobalCommand||this.isDefaultCommand)&&t.length>0){let d=be(t.map(o=>o.rawName));a.push({title:"Commands",body:t.map(o=>` ${ye(o.rawName,d.length)} ${o.description}`).join(`
3
- `)},{title:"For more info, run any command with the `--help` flag",body:t.map(o=>` $ ${n}${o.name===""?"":` ${o.name}`} --help`).join(`
4
- `)})}let r=this.isGlobalCommand?e:[...this.options,...e||[]];if(!this.isGlobalCommand&&!this.isDefaultCommand&&(r=r.filter(d=>d.name!=="version")),r.length>0){let d=be(r.map(o=>o.rawName));a.push({title:"Options",body:r.map(o=>` ${ye(o.rawName,d.length)} ${o.description} ${o.config.default===void 0?"":`(default: ${o.config.default})`}`).join(`
5
- `)})}this.examples.length>0&&a.push({title:"Examples",body:this.examples.map(d=>typeof d=="function"?d(n):d).join(`
6
- `)}),i&&(a=i(a)||a),console.info(a.map(d=>d.title?`${d.title}:
7
- ${d.body}`:d.body).join(`
2
+ import{A as re,B as oe,C as I,D as de,E as ce,F as le,G as ue,H as me,I as fe,J as pe,K as B,L as he,M as ge,N as ke,O as be,P as ye,Q as ve,R as we,S as Ae,T as xe,U as De,a as Y,b as V,c as O,d as C,e as J,f as G,g as H,h as x,i as N,j as z,k as Q,l as X,m as Z,n as ee,o as te,p as K,q as k,r as _,s as b,t as y,u as ne,v,w as R,x as se,y as ie,z as ae}from"./chunks/chunk-RINJ2CTH.js";function U(e){return e==null?[]:Array.isArray(e)?e:[e]}function ze(e,s,n,t){var i,a=e[s],r=~t.string.indexOf(s)?n==null||n===!0?"":String(n):typeof n=="boolean"?n:~t.boolean.indexOf(s)?n==="false"?!1:n==="true"||(e._.push((i=+n,i*0===0?i:n)),!!n):(i=+n,i*0===0?i:n);e[s]=a==null?r:Array.isArray(a)?a.concat(r):[a,r]}function Qe(e,s){e=e||[],s=s||{};var n,t,i,a,r,o={_:[]},c=0,l=0,u=0,m=e.length;let A=s.alias!==void 0,p=s.unknown!==void 0,h=s.default!==void 0;if(s.alias=s.alias||{},s.string=U(s.string),s.boolean=U(s.boolean),A)for(n in s.alias)for(t=s.alias[n]=U(s.alias[n]),c=0;c<t.length;c++)(s.alias[t[c]]=t.concat(n)).splice(c,1);for(c=s.boolean.length;c-- >0;)for(t=s.alias[s.boolean[c]]||[],l=t.length;l-- >0;)s.boolean.push(t[l]);for(c=s.string.length;c-- >0;)for(t=s.alias[s.string[c]]||[],l=t.length;l-- >0;)s.string.push(t[l]);if(h){for(n in s.default)if(a=typeof s.default[n],t=s.alias[n]=s.alias[n]||[],s[a]!==void 0)for(s[a].push(n),c=0;c<t.length;c++)s[a].push(t[c])}let D=p?Object.keys(s.alias):[];for(c=0;c<m;c++){if(i=e[c],i==="--"){o._=o._.concat(e.slice(++c));break}for(l=0;l<i.length&&i.charCodeAt(l)===45;l++);if(l===0)o._.push(i);else if(i.substring(l,l+3)==="no-"){if(a=i.substring(l+3),p&&!~D.indexOf(a))return s.unknown(i);o[a]=!1}else{for(u=l+1;u<i.length&&i.charCodeAt(u)!==61;u++);for(a=i.substring(l,u),r=i.substring(++u)||c+1===m||(""+e[c+1]).charCodeAt(0)===45||e[++c],t=l===2?[a]:a,u=0;u<t.length;u++){if(a=t[u],p&&!~D.indexOf(a))return s.unknown("-".repeat(l)+a);ze(o,a,u+1<t.length||r,s)}}}if(h)for(n in s.default)o[n]===void 0&&(o[n]=s.default[n]);if(A)for(n in o)for(t=s.alias[n]||[];t.length>0;)o[t.shift()]=o[n];return o}function $e(e){return e.replace(/[<[].+/,"").trim()}function Xe(e){let s=/<([^>]+)>/g,n=/\[([^\]]+)\]/g,t=[],i=o=>{let c=!1,l=o[1];return l.startsWith("...")&&(l=l.slice(3),c=!0),{required:o[0].startsWith("<"),value:l,variadic:c}},a;for(;a=s.exec(e);)t.push(i(a));let r;for(;r=n.exec(e);)t.push(i(r));return t}function Ze(e){let s={alias:{},boolean:[]};for(let[n,t]of e.entries())t.names.length>1&&(s.alias[t.names[0]]=t.names.slice(1)),t.isBoolean&&(t.negated&&e.some((i,a)=>a!==n&&i.names.some(r=>t.names.includes(r))&&typeof i.required=="boolean")||s.boolean.push(t.names[0]));return s}function Ce(e){return e.sort((s,n)=>s.length>n.length?-1:1)[0]}function Se(e,s){return e.length>=s?e:`${e}${" ".repeat(s-e.length)}`}function et(e){return e.replaceAll(/([a-z])-([a-z])/g,(s,n,t)=>n+t.toUpperCase())}function tt(e,s,n){let t=e;for(let i=0;i<s.length;i++){let a=s[i];if(i===s.length-1){t[a]=n;return}if(t[a]==null){let r=+s[i+1]>-1;t[a]=r?[]:{}}t=t[a]}}function nt(e,s){for(let n of Object.keys(s)){let t=s[n];t.shouldTransform&&(e[n]=[e[n]].flat(),typeof t.transformFunction=="function"&&(e[n]=e[n].map(t.transformFunction)))}}function st(e){let s=/([^\\/]+)$/.exec(e);return s?s[1]:""}function je(e){return e.split(".").map((s,n)=>n===0?et(s):s).join(".")}var j=class extends Error{constructor(e){super(e),this.name="CACError",typeof Error.captureStackTrace!="function"&&(this.stack=new Error(e).stack)}},it=class{rawName;description;name;names;isBoolean;required;config;negated;constructor(e,s,n){this.rawName=e,this.description=s,this.config=Object.assign({},n),e=e.replaceAll(".*",""),this.negated=!1,this.names=$e(e).split(",").map(t=>{let i=t.trim().replace(/^-{1,2}/,"");return i.startsWith("no-")&&(this.negated=!0,i=i.replace(/^no-/,"")),je(i)}).sort((t,i)=>t.length>i.length?1:-1),this.name=this.names.at(-1),this.negated&&this.config.default==null&&(this.config.default=!0),e.includes("<")?this.required=!0:e.includes("[")?this.required=!1:this.isBoolean=!0}},L,E;if(typeof process<"u"){let e;typeof Deno<"u"&&typeof Deno.version?.deno=="string"?e="deno":typeof Bun<"u"&&typeof Bun.version=="string"?e="bun":e="node",E=`${process.platform}-${process.arch} ${e}-${process.version}`,L=process.argv}else typeof navigator>"u"?E="unknown":E=`${navigator.platform} ${navigator.userAgent}`;var Ee=class{rawName;description;config;cli;options;aliasNames;name;args;commandAction;usageText;versionNumber;examples;helpCallback;globalCommand;constructor(e,s,n={},t){this.rawName=e,this.description=s,this.config=n,this.cli=t,this.options=[],this.aliasNames=[],this.name=$e(e),this.args=Xe(e),this.examples=[]}usage(e){return this.usageText=e,this}allowUnknownOptions(){return this.config.allowUnknownOptions=!0,this}ignoreOptionDefaultValue(){return this.config.ignoreOptionDefaultValue=!0,this}version(e,s="-v, --version"){return this.versionNumber=e,this.option(s,"Display version number"),this}example(e){return this.examples.push(e),this}option(e,s,n){let t=new it(e,s,n);return this.options.push(t),this}alias(e){return this.aliasNames.push(e),this}action(e){return this.commandAction=e,this}isMatched(e){return this.name===e||this.aliasNames.includes(e)}get isDefaultCommand(){return this.name===""||this.aliasNames.includes("!")}get isGlobalCommand(){return this instanceof Te}hasOption(e){return e=e.split(".")[0],this.options.find(s=>s.names.includes(e))}outputHelp(){let{name:e,commands:s}=this.cli,{versionNumber:n,options:t,helpCallback:i}=this.cli.globalCommand,a=[{body:`${e}${n?`/${n}`:""}`}];if(a.push({title:"Usage",body:` $ ${e} ${this.usageText||this.rawName}`}),(this.isGlobalCommand||this.isDefaultCommand)&&s.length>0){let o=Ce(s.map(c=>c.rawName));a.push({title:"Commands",body:s.map(c=>` ${Se(c.rawName,o.length)} ${c.description}`).join(`
3
+ `)},{title:"For more info, run any command with the `--help` flag",body:s.map(c=>` $ ${e}${c.name===""?"":` ${c.name}`} --help`).join(`
4
+ `)})}let r=this.isGlobalCommand?t:[...this.options,...t||[]];if(!this.isGlobalCommand&&!this.isDefaultCommand&&(r=r.filter(o=>o.name!=="version")),r.length>0){let o=Ce(r.map(c=>c.rawName));a.push({title:"Options",body:r.map(c=>` ${Se(c.rawName,o.length)} ${c.description} ${c.config.default===void 0?"":`(default: ${c.config.default})`}`).join(`
5
+ `)})}this.examples.length>0&&a.push({title:"Examples",body:this.examples.map(o=>typeof o=="function"?o(e):o).join(`
6
+ `)}),i&&(a=i(a)||a),console.info(a.map(o=>o.title?`${o.title}:
7
+ ${o.body}`:o.body).join(`
8
8
 
9
- `))}outputVersion(){let{name:n}=this.cli,{versionNumber:t}=this.cli.globalCommand;t&&console.info(`${n}/${t} ${$}`)}checkRequiredArgs(){let n=this.args.filter(t=>t.required).length;if(this.cli.args.length<n)throw new D(`missing required args for command \`${this.rawName}\``)}checkUnknownOptions(){let{options:n,globalCommand:t}=this.cli;if(!this.config.allowUnknownOptions){for(let s of Object.keys(n))if(s!=="--"&&!this.hasOption(s)&&!t.hasOption(s))throw new D(`Unknown option \`${s.length>1?`--${s}`:`-${s}`}\``)}}checkOptionValue(){let{options:n,globalCommand:t}=this.cli,s=[...t.options,...this.options];for(let e of s){let i=n[e.name.split(".")[0]];if(e.required){let a=s.some(r=>r.negated&&r.names.includes(e.name));if(i===!0||i===!1&&!a)throw new D(`option \`${e.rawName}\` value is missing`)}}}checkUnusedArgs(){let n=this.args.some(t=>t.variadic)?1/0:this.args.length;if(n<this.cli.args.length)throw new D(`Unused args: ${this.cli.args.slice(n).map(t=>`\`${t}\``).join(", ")}`)}},we=class extends Ae{constructor(n){super("@@global@@","",{},n)}},Ve=class extends EventTarget{name;commands;globalCommand;matchedCommand;matchedCommandName;rawArgs;args;options;showHelpOnExit;showVersionOnExit;constructor(n=""){super(),this.name=n,this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.globalCommand=new we(this),this.globalCommand.usage("<command> [options]")}usage(n){return this.globalCommand.usage(n),this}command(n,t,s){let e=new Ae(n,t||"",s,this);return e.globalCommand=this.globalCommand,this.commands.push(e),e}option(n,t,s){return this.globalCommand.option(n,t,s),this}help(n){return this.globalCommand.option("-h, --help","Display this message"),this.globalCommand.helpCallback=n,this.showHelpOnExit=!0,this}version(n,t="-v, --version"){return this.globalCommand.version(n,t),this.showVersionOnExit=!0,this}example(n){return this.globalCommand.example(n),this}outputHelp(){this.matchedCommand?this.matchedCommand.outputHelp():this.globalCommand.outputHelp()}outputVersion(){this.globalCommand.outputVersion()}setParsedInfo({args:n,options:t},s,e){return this.args=n,this.options=t,s&&(this.matchedCommand=s),e&&(this.matchedCommandName=e),this}unsetMatchedCommand(){this.matchedCommand=void 0,this.matchedCommandName=void 0}parse(n,{run:t=!0}={}){if(!n){if(!R)throw new Error("No argv provided and runtime process argv is not available.");n=R}this.rawArgs=n,this.name||(this.name=n[1]?Ye(n[1]):"cli");let s=!0;for(let i of this.commands){let a=this.mri(n.slice(2),i),r=a.args[0];if(i.isMatched(r)){s=!1;let d={...a,args:a.args.slice(1)};this.setParsedInfo(d,i,r),this.dispatchEvent(new CustomEvent(`command:${r}`,{detail:i}))}}if(s){for(let i of this.commands)if(i.isDefaultCommand){s=!1;let a=this.mri(n.slice(2),i);this.setParsedInfo(a,i),this.dispatchEvent(new CustomEvent("command:!",{detail:i}))}}if(s){let i=this.mri(n.slice(2));this.setParsedInfo(i)}this.options.help&&this.showHelpOnExit&&(this.outputHelp(),t=!1,this.unsetMatchedCommand()),this.options.version&&this.showVersionOnExit&&this.matchedCommandName==null&&(this.outputVersion(),t=!1,this.unsetMatchedCommand());let e={args:this.args,options:this.options};return t&&this.runMatchedCommand(),!this.matchedCommand&&this.args[0]&&this.dispatchEvent(new CustomEvent("command:*",{detail:this.args[0]})),e}mri(n,t){let s=[...this.globalCommand.options,...t?t.options:[]],e=Fe(s),i=[],a=n.indexOf("--");a!==-1&&(i=n.slice(a+1),n=n.slice(0,a));let r=Be(n,e);r=Object.keys(r).reduce((m,k)=>({...m,[ve(k)]:r[k]}),{_:[]});let d=r._,o={"--":i},l=t&&t.config.ignoreOptionDefaultValue?t.config.ignoreOptionDefaultValue:this.globalCommand.config.ignoreOptionDefaultValue,u=Object.create(null);for(let m of s){if(!l&&m.config.default!==void 0)for(let k of m.names)o[k]=m.config.default;Array.isArray(m.config.type)&&u[m.name]===void 0&&(u[m.name]=Object.create(null),u[m.name].shouldTransform=!0,u[m.name].transformFunction=m.config.type[0])}for(let m of Object.keys(r))m!=="_"&&(Ue(o,m.split("."),r[m]),qe(o,u));return{args:d,options:o}}runMatchedCommand(){let{args:n,options:t,matchedCommand:s}=this;if(!s||!s.commandAction)return;s.checkUnknownOptions(),s.checkOptionValue(),s.checkRequiredArgs(),s.checkUnusedArgs();let e=[];return s.args.forEach((i,a)=>{i.variadic?e.push(n.slice(a)):e.push(n[a])}),e.push(t),s.commandAction.apply(this,e)}},Ce=(n="")=>new Ve(n);import{existsSync as S,mkdirSync as We,readFileSync as $e,writeFileSync as _}from"node:fs";import{join as I}from"node:path";var De=".kadence/state.json",Ge=["AGENTS.md","CLAUDE.md"];function Se(n){let t=F(n);if(t===null)return{ok:!1,alreadyInitialized:!1,root:null,message:`kadence lives inside a git repository, and there is none here.
9
+ `))}outputVersion(){let{name:e}=this.cli,{versionNumber:s}=this.cli.globalCommand;s&&console.info(`${e}/${s} ${E}`)}checkRequiredArgs(){let e=this.args.filter(s=>s.required).length;if(this.cli.args.length<e)throw new j(`missing required args for command \`${this.rawName}\``)}checkUnknownOptions(){let{options:e,globalCommand:s}=this.cli;if(!this.config.allowUnknownOptions){for(let n of Object.keys(e))if(n!=="--"&&!this.hasOption(n)&&!s.hasOption(n))throw new j(`Unknown option \`${n.length>1?`--${n}`:`-${n}`}\``)}}checkOptionValue(){let{options:e,globalCommand:s}=this.cli,n=[...s.options,...this.options];for(let t of n){let i=e[t.name.split(".")[0]];if(t.required){let a=n.some(r=>r.negated&&r.names.includes(t.name));if(i===!0||i===!1&&!a)throw new j(`option \`${t.rawName}\` value is missing`)}}}checkUnusedArgs(){let e=this.args.some(s=>s.variadic)?1/0:this.args.length;if(e<this.cli.args.length)throw new j(`Unused args: ${this.cli.args.slice(e).map(s=>`\`${s}\``).join(", ")}`)}},Te=class extends Ee{constructor(e){super("@@global@@","",{},e)}},at=class extends EventTarget{name;commands;globalCommand;matchedCommand;matchedCommandName;rawArgs;args;options;showHelpOnExit;showVersionOnExit;constructor(e=""){super(),this.name=e,this.commands=[],this.rawArgs=[],this.args=[],this.options={},this.globalCommand=new Te(this),this.globalCommand.usage("<command> [options]")}usage(e){return this.globalCommand.usage(e),this}command(e,s,n){let t=new Ee(e,s||"",n,this);return t.globalCommand=this.globalCommand,this.commands.push(t),t}option(e,s,n){return this.globalCommand.option(e,s,n),this}help(e){return this.globalCommand.option("-h, --help","Display this message"),this.globalCommand.helpCallback=e,this.showHelpOnExit=!0,this}version(e,s="-v, --version"){return this.globalCommand.version(e,s),this.showVersionOnExit=!0,this}example(e){return this.globalCommand.example(e),this}outputHelp(){this.matchedCommand?this.matchedCommand.outputHelp():this.globalCommand.outputHelp()}outputVersion(){this.globalCommand.outputVersion()}setParsedInfo({args:e,options:s},n,t){return this.args=e,this.options=s,n&&(this.matchedCommand=n),t&&(this.matchedCommandName=t),this}unsetMatchedCommand(){this.matchedCommand=void 0,this.matchedCommandName=void 0}parse(e,{run:s=!0}={}){if(!e){if(!L)throw new Error("No argv provided and runtime process argv is not available.");e=L}this.rawArgs=e,this.name||(this.name=e[1]?st(e[1]):"cli");let n=!0;for(let i of this.commands){let a=this.mri(e.slice(2),i),r=a.args[0];if(i.isMatched(r)){n=!1;let o={...a,args:a.args.slice(1)};this.setParsedInfo(o,i,r),this.dispatchEvent(new CustomEvent(`command:${r}`,{detail:i}))}}if(n){for(let i of this.commands)if(i.isDefaultCommand){n=!1;let a=this.mri(e.slice(2),i);this.setParsedInfo(a,i),this.dispatchEvent(new CustomEvent("command:!",{detail:i}))}}if(n){let i=this.mri(e.slice(2));this.setParsedInfo(i)}this.options.help&&this.showHelpOnExit&&(this.outputHelp(),s=!1,this.unsetMatchedCommand()),this.options.version&&this.showVersionOnExit&&this.matchedCommandName==null&&(this.outputVersion(),s=!1,this.unsetMatchedCommand());let t={args:this.args,options:this.options};return s&&this.runMatchedCommand(),!this.matchedCommand&&this.args[0]&&this.dispatchEvent(new CustomEvent("command:*",{detail:this.args[0]})),t}mri(e,s){let n=[...this.globalCommand.options,...s?s.options:[]],t=Ze(n),i=[],a=e.indexOf("--");a!==-1&&(i=e.slice(a+1),e=e.slice(0,a));let r=Qe(e,t);r=Object.keys(r).reduce((m,A)=>({...m,[je(A)]:r[A]}),{_:[]});let o=r._,c={"--":i},l=s&&s.config.ignoreOptionDefaultValue?s.config.ignoreOptionDefaultValue:this.globalCommand.config.ignoreOptionDefaultValue,u=Object.create(null);for(let m of n){if(!l&&m.config.default!==void 0)for(let A of m.names)c[A]=m.config.default;Array.isArray(m.config.type)&&u[m.name]===void 0&&(u[m.name]=Object.create(null),u[m.name].shouldTransform=!0,u[m.name].transformFunction=m.config.type[0])}for(let m of Object.keys(r))m!=="_"&&(tt(c,m.split("."),r[m]),nt(c,u));return{args:o,options:c}}runMatchedCommand(){let{args:e,options:s,matchedCommand:n}=this;if(!n||!n.commandAction)return;n.checkUnknownOptions(),n.checkOptionValue(),n.checkRequiredArgs(),n.checkUnusedArgs();let t=[];return n.args.forEach((i,a)=>{i.variadic?t.push(e.slice(a)):t.push(e[a])}),t.push(s),n.commandAction.apply(this,t)}},Oe=(e="")=>new at(e);import{existsSync as T,mkdirSync as rt,readFileSync as Ke,writeFileSync as P}from"node:fs";import{join as F}from"node:path";var Ne=".kadence/state.json",ot=["AGENTS.md","CLAUDE.md"];function _e(e,s="dev"){let n=Y(e);if(n===null)return{ok:!1,alreadyInitialized:!1,root:null,message:`kadence lives inside a git repository, and there is none here.
10
10
  Create one and try again:
11
- git init`};let s=S(E(t));We(E(t),{recursive:!0}),Je(t);let e=I(L(t),"README.md");S(e)||_(e,U,"utf8");for(let i of Ge)He(t,i);return{ok:!0,alreadyInitialized:s,root:t,message:s?"kadence is already initialised.":`kadence is ready.
11
+ git init`};let t=T(O(n));rt(O(n),{recursive:!0}),dt(n);let i=F(V(n),"README.md");T(i)||P(i,J(s),"utf8");for(let a of ot)ct(n,a,s);return{ok:!0,alreadyInitialized:t,root:n,message:t?"kadence is already initialised.":`kadence is ready.
12
12
 
13
13
  kadence task add "first task"
14
14
  kadence board
15
15
 
16
- Files were created but not committed \u2014 that call is yours.`}}function Je(n){let t=I(n,".gitignore"),s="";if(S(t)&&(s=$e(t,"utf8")),s.includes(De))return;let e=s.length>0&&!s.endsWith(`
16
+ Files were created but not committed \u2014 that call is yours.`}}function dt(e){let s=F(e,".gitignore"),n="";if(T(s)&&(n=Ke(s,"utf8")),n.includes(Ne))return;let t=n.length>0&&!n.endsWith(`
17
17
  `)?`
18
- `:"";_(t,`${s}${e}${De}
19
- `,"utf8")}function He(n,t){let s=I(n,t),e=S(s)?$e(s,"utf8"):null,i=q(e);i!==e&&_(s,i,"utf8")}import{writeSync as Qe}from"node:fs";var B="cancelled";function Ee(n,t,s,e){let i=y(n,t);if(!x(i))return i;let{fields:a,error:r}=Z(e);if(r!==null)return r;let{state:d,warnings:o}=v(i.root,i.actor),l=d.tasks.filter(p=>p.status!==B);if(s.assignee!==void 0){let p=s.assignee.toLowerCase(),h=p==="me"?i.actor.toLowerCase():p;l=l.filter(w=>(w.assignee??"").toLowerCase()===h)}if(s.sprint==="active"){let p=d.sprints.find(h=>h.status==="active"||h.status==="planned");l=p===void 0?[]:l.filter(h=>h.sprint===p.id)}let u={};for(let p of d.statuses)p!==B&&(u[p]=l.filter(h=>h.status===p));let m=d.orphanStatuses.filter(p=>p!==B);for(let p of m)u[p]=l.filter(h=>h.status===p);let k=m.length>0?[`Statuses not in the board configuration: ${m.join(", ")}.
18
+ `:"";P(s,`${n}${t}${Ne}
19
+ `,"utf8")}function ct(e,s,n){let t=F(e,s),i=T(t)?Ke(t,"utf8"):null,a=G(i,n);a!==i&&P(t,a,"utf8")}import{existsSync as lt}from"node:fs";import{isAbsolute as ut,join as mt,relative as ft}from"node:path";function Re(e,s){let n=s.toUpperCase();return e.decisions.find(t=>t.id===n||t.label===n)}function Ie(e){return k(1,"decision_not_found",`No decision ${e}.
20
+ kadence decision list`,{received:e,hint:"kadence decision list --json"})}function Be(e,s,n,t){let i=b(e,s);if(!y(i))return i;let a=n.trim();if(a.length===0)return k(2,"invalid_argument","A decision needs a title.",{hint:'kadence decision add "Use ULIDs" --why "Clocks disagree between machines"'});let r=t.why?.trim()??"";if(r.length===0)return k(2,"invalid_argument",`A decision needs a reason.
21
+ --why "..."`,{received:a,hint:'kadence decision add "Use ULIDs" --why "Clocks disagree between machines"'});let{state:o,warnings:c}=v(i.root,i.actor),l;if(t.task!==void 0){let g=R(o,t.task);if(g===void 0)return _(t.task);l=g.id}let u;if(t.supersedes!==void 0){let g=Re(o,t.supersedes);if(g===void 0)return Ie(t.supersedes);u=g.id,l===void 0&&g.task!==null&&(l=g.task)}let m=(t.docs??[]).map(g=>ut(g)?ft(i.root,g):g.replace(/^\.\//,"")),p=m.filter(g=>!lt(mt(i.root,g))).map(g=>`No file at ${g} \u2014 the link is recorded anyway; it may arrive later.`),h=x();C(i.root,{id:h,type:"decision.recorded",entity:h,actor:i.actor,ts:new Date().toISOString(),source:i.source,data:{title:a,why:r,...t.rejected!==void 0?{rejected:t.rejected.trim()}:{},...l!==void 0?{task:l}:{},...u!==void 0?{supersedes:u}:{},...m.length>0?{docs:m}:{}}});let W=v(i.root,i.actor).state.decisions.find(g=>g.id===h)?.label??h,He=u===void 0?"":`
22
+ It replaces ${t.supersedes}, and both links were written by one event \u2014 neither side can go stale.`;return{ok:!0,exitCode:0,warnings:[...c,...p],message:`${W} recorded.${He}`,data:{schema:"kadence/v1",ok:!0,decision:{id:h,label:W,title:a}}}}function Ue(e,s,n){let t=b(e,s);if(!y(t))return t;let{state:i,warnings:a}=v(t.root,t.actor),r=i.decisions;if(n.task!==void 0){let o=R(i,n.task);if(o===void 0)return _(n.task);r=r.filter(c=>c.task===o.id)}return n.all!==!0&&(r=r.filter(o=>o.supersededBy===null)),{ok:!0,exitCode:0,warnings:a,message:pt(r,i),data:{schema:"kadence/v1",ok:!0,decisions:r.map(o=>Pe(o,i))}}}function Le(e,s,n){let t=b(e,s);if(!y(t))return t;let{state:i,warnings:a}=v(t.root,t.actor),r=Re(i,n);return r===void 0?Ie(n):{ok:!0,exitCode:0,warnings:a,message:ht(r,i),data:{schema:"kadence/v1",ok:!0,decision:Pe(r,i)}}}function S(e,s){return s===null?null:e.decisions.find(n=>n.id===s)?.label??e.tasks.find(n=>n.id===s)?.label??s}function Pe(e,s){return{id:e.id,label:e.label,title:e.title,why:e.why,rejected:e.rejected,task:S(s,e.task),docs:e.docs,supersedes:S(s,e.supersedes),supersededBy:S(s,e.supersededBy),superseded:e.supersededBy!==null,at:e.at,by:e.by}}function pt(e,s){return e.length===0?`No decisions recorded yet.
23
+ Record the first one:
24
+ kadence decision add "Use ULIDs" --why "Clocks disagree"`:e.map(n=>{let t=n.supersededBy===null?"":` (superseded by ${S(s,n.supersededBy)})`;return`${n.label} ${n.title}${t}`}).join(`
25
+ `)}function ht(e,s){let n=[`${e.label} ${e.title}`];return e.supersededBy!==null&&n.push("",`!! SUPERSEDED by ${S(s,e.supersededBy)} \u2014 this is no longer in force.`),n.push("",`Why: ${e.why}`),e.rejected!==null&&n.push(`Rejected: ${e.rejected}`),e.task!==null&&n.push(`Task: ${S(s,e.task)}`),e.docs.length>0&&n.push(`Docs: ${e.docs.join(", ")}`),e.supersedes!==null&&n.push(`Replaces: ${S(s,e.supersedes)}`),n.join(`
26
+ `)}import{writeSync as kt}from"node:fs";var M="cancelled";function Fe(e,s,n,t){let i=b(e,s);if(!y(i))return i;let{fields:a,error:r}=ae(t);if(r!==null)return r;let{state:o,warnings:c}=v(i.root,i.actor),l=o.tasks.filter(p=>p.status!==M);if(n.assignee!==void 0){let p=n.assignee.toLowerCase(),h=p==="me"?i.actor.toLowerCase():p;l=l.filter(D=>(D.assignee??"").toLowerCase()===h)}if(n.sprint==="active"){let p=o.sprints.find(h=>h.status==="active"||h.status==="planned");l=p===void 0?[]:l.filter(h=>h.sprint===p.id)}let u={};for(let p of o.statuses)p!==M&&(u[p]=l.filter(h=>h.status===p));let m=o.orphanStatuses.filter(p=>p!==M);for(let p of m)u[p]=l.filter(h=>h.status===p);let A=m.length>0?[`Statuses not in the board configuration: ${m.join(", ")}.
20
27
  Tasks there are still shown. Add the column or move them:
21
- kadence board config --statuses "..."`]:[];return{ok:!0,exitCode:0,warnings:[...o,...k],message:J(u,G(t,process.stdout.isTTY===!0)),data:{schema:"kadence/v1",ok:!0,columns:Object.fromEntries(Object.entries(u).map(([p,h])=>[p,h.map(w=>ee(w,a))]))}}}function Oe(n,t,s){let e=y(n,t);if(!x(e))return e;let{state:i,warnings:a}=v(e.root,e.actor);if(s===void 0)return{ok:!0,exitCode:0,warnings:a,message:`Board columns: ${i.statuses.join(", ")}
28
+ kadence board config --statuses "..."`]:[];return{ok:!0,exitCode:0,warnings:[...c,...A],message:ee(u,Z(s,process.stdout.isTTY===!0)),data:{schema:"kadence/v1",ok:!0,columns:Object.fromEntries(Object.entries(u).map(([p,h])=>[p,h.map(D=>re(D,a))]))}}}function Me(e,s,n){let t=b(e,s);if(!y(t))return t;let{state:i,warnings:a}=v(t.root,t.actor);if(n===void 0)return{ok:!0,exitCode:0,warnings:a,message:`Board columns: ${i.statuses.join(", ")}
22
29
 
23
30
  Change them with:
24
- kadence board config --statuses "todo,doing,review,done"`,data:{schema:"kadence/v1",ok:!0,statuses:i.statuses}};let r=s.split(",").map(l=>l.trim().toLowerCase().replace(/\s+/g,"_")).filter(l=>l.length>0);if(r.length===0)return{ok:!1,exitCode:2,message:"At least one status is required."};if(new Set(r).size!==r.length)return{ok:!1,exitCode:2,message:"The same status is listed twice."};if(!r.includes(O))return{ok:!1,exitCode:2,message:`The list must include "${O}" \u2014 velocity and burndown are computed from it.`};let d=i.tasks.filter(l=>!r.includes(l.status)&&l.status!==P);C(e.root,{id:b(),type:"board.configured",entity:b(),actor:e.actor,ts:new Date().toISOString(),source:e.source,data:{statuses:r}});let o=d.length>0?`
25
- ${d.length} task(s) remain in removed columns: ${[...new Set(d.map(l=>l.status))].join(", ")}. They are still listed.`:"";return{ok:!0,exitCode:0,warnings:a,message:`Board columns: ${r.join(", ")}${o}`,data:{schema:"kadence/v1",ok:!0,statuses:r}}}var ze=["description","type","priority","estimate","labels","assignee"];function Te(n,t,s,e){let i=y(n,t);if(!x(i))return i;let a=s.trim();if(a.length===0)return{ok:!1,exitCode:2,message:"A template needs a name."};let r={};for(let d of ze)e[d]!==void 0&&(r[d]=e[d]);return Object.keys(r).length===0?{ok:!1,exitCode:2,message:`A template needs at least one field.
26
- kadence template save bug --type bug --priority high --label triage`}:(C(i.root,{id:b(),type:"template.saved",entity:b(),actor:i.actor,ts:new Date().toISOString(),source:i.source,data:{name:a,fields:r}}),{ok:!0,exitCode:0,message:`Template "${a}" saved: ${Object.keys(r).join(", ")}.
27
- kadence task add "title" --template ${a}`,data:{schema:"kadence/v1",ok:!0,template:{name:a,fields:r}}})}function je(n,t){let s=y(n,t);if(!x(s))return s;let{state:e,warnings:i}=v(s.root,s.actor);return e.templates.length===0?{ok:!0,exitCode:0,warnings:i,message:`No templates yet.
28
- kadence template save bug --type bug --priority high`,data:{schema:"kadence/v1",ok:!0,templates:[]}}:{ok:!0,exitCode:0,warnings:i,message:e.templates.map(a=>{let r=Object.entries(a.fields).map(([d,o])=>`${d}=${Array.isArray(o)?o.join("/"):String(o)}`).join(" ");return` ${a.name.padEnd(14)} ${r}`}).join(`
29
- `),data:{schema:"kadence/v1",ok:!0,templates:e.templates}}}function Ke(n,t,s){let e=y(n,t);if(!x(e))return e;let{state:i,warnings:a}=v(e.root,e.actor);return i.templates.some(r=>r.name===s)?(C(e.root,{id:b(),type:"template.deleted",entity:b(),actor:e.actor,ts:new Date().toISOString(),source:e.source,data:{name:s}}),{ok:!0,exitCode:0,warnings:a,message:`Template "${s}" deleted.`}):{ok:!1,exitCode:1,message:`No template "${s}".
30
- kadence template list`}}function Ne(n,t,s){let e=y(n,t);if(!x(e))return{error:e};let{state:i}=v(e.root,e.actor),a=i.templates.find(r=>r.name===s);if(a===void 0){let r=i.templates.map(d=>d.name).join(", ");return{error:{ok:!1,exitCode:1,message:`No template "${s}".`+(r.length>0?`
31
- Available: ${r}`:`
32
- kadence template save ...`)}}}return{fields:a.fields}}function M(n,t){let s=Buffer.from(t,"utf8"),e=0;for(;e<s.length;)try{e+=Qe(n,s,e,s.length-e)}catch(i){if(i.code!=="EAGAIN")throw i}}var g=Ce("kadence");function c(n,t){for(let s of n.warnings??[])M(2,`${s}
33
- `);if(t){let s=n.data??{schema:"kadence/v1",ok:n.ok,...n.ok?{}:{error:n.error??{message:n.message}}};M(1,`${JSON.stringify(s)}
34
- `)}else M(n.ok?1:2,`${n.message}
35
- `);process.exit(n.exitCode)}function Re(n,t,s,e){if(n!==void 0)return n;ce(process.env,process.stdout.isTTY===!0)||c(f(`No terminal available for an editor.
31
+ kadence board config --statuses "todo,doing,review,done"`,data:{schema:"kadence/v1",ok:!0,statuses:i.statuses}};let r=n.split(",").map(l=>l.trim().toLowerCase().replace(/\s+/g,"_")).filter(l=>l.length>0);if(r.length===0)return k(2,"invalid_argument","At least one status is required.",{received:n});if(new Set(r).size!==r.length)return k(2,"invalid_argument","The same status is listed twice.",{received:n});if(!r.includes(N))return k(2,"invalid_argument",`The list must include "${N}" \u2014 velocity and burndown are computed from it.`,{received:n});let o=i.tasks.filter(l=>!r.includes(l.status)&&l.status!==z);C(t.root,{id:x(),type:"board.configured",entity:x(),actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{statuses:r}});let c=o.length>0?`
32
+ ${o.length} task(s) remain in removed columns: ${[...new Set(o.map(l=>l.status))].join(", ")}. They are still listed.`:"";return{ok:!0,exitCode:0,warnings:a,message:`Board columns: ${r.join(", ")}${c}`,data:{schema:"kadence/v1",ok:!0,statuses:r}}}var gt=["description","type","priority","estimate","labels","assignee"];function qe(e,s,n,t){let i=b(e,s);if(!y(i))return i;let a=n.trim();if(a.length===0)return k(2,"invalid_argument","A template needs a name.",{hint:"kadence template list --json"});let r={};for(let o of gt)t[o]!==void 0&&(r[o]=t[o]);return Object.keys(r).length===0?k(2,"invalid_argument",`A template needs at least one field.
33
+ kadence template save bug --type bug --priority high --label triage`,{received:n}):(C(i.root,{id:x(),type:"template.saved",entity:x(),actor:i.actor,ts:new Date().toISOString(),source:i.source,data:{name:a,fields:r}}),{ok:!0,exitCode:0,message:`Template "${a}" saved: ${Object.keys(r).join(", ")}.
34
+ kadence task add "title" --template ${a}`,data:{schema:"kadence/v1",ok:!0,template:{name:a,fields:r}}})}function We(e,s){let n=b(e,s);if(!y(n))return n;let{state:t,warnings:i}=v(n.root,n.actor);return t.templates.length===0?{ok:!0,exitCode:0,warnings:i,message:`No templates yet.
35
+ kadence template save bug --type bug --priority high`,data:{schema:"kadence/v1",ok:!0,templates:[]}}:{ok:!0,exitCode:0,warnings:i,message:t.templates.map(a=>{let r=Object.entries(a.fields).map(([o,c])=>`${o}=${Array.isArray(c)?c.join("/"):String(c)}`).join(" ");return` ${a.name.padEnd(14)} ${r}`}).join(`
36
+ `),data:{schema:"kadence/v1",ok:!0,templates:t.templates}}}function Ye(e,s,n){let t=b(e,s);if(!y(t))return t;let{state:i,warnings:a}=v(t.root,t.actor);return i.templates.some(r=>r.name===n)?(C(t.root,{id:x(),type:"template.deleted",entity:x(),actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{name:n}}),{ok:!0,exitCode:0,warnings:a,message:`Template "${n}" deleted.`}):k(1,"template_not_found",`No template "${n}".
37
+ kadence template list`,{received:n,hint:"kadence template list --json"})}function Ve(e,s,n){let t=b(e,s);if(!y(t))return{error:t};let{state:i}=v(t.root,t.actor),a=i.templates.find(r=>r.name===n);if(a===void 0){let r=i.templates.map(o=>o.name);return{error:k(1,"template_not_found",`No template "${n}".`+(r.length>0?`
38
+ Available: ${r.join(", ")}`:`
39
+ kadence template save ...`),{received:n,...r.length>0?{allowed:r}:{}})}}return{fields:a.fields}}function q(e,s){let n=Buffer.from(s,"utf8"),t=0;for(;t<n.length;)try{t+=kt(e,n,t,n.length-t)}catch(i){if(i.code!=="EAGAIN")throw i}}var w=Oe("kadence");function d(e,s){for(let n of e.warnings??[])q(2,`${n}
40
+ `);if(s){let n=e.data??{schema:"kadence/v1",ok:e.ok,...e.ok?{}:{error:e.error??{message:e.message}}};q(1,`${JSON.stringify(n)}
41
+ `)}else q(e.ok?1:2,`${e.message}
42
+ `);process.exit(e.exitCode)}function Je(e,s,n,t){if(e!==void 0)return e;ge(process.env,process.stdout.isTTY===!0)||d(f(`No terminal available for an editor.
36
43
  Pass the text directly:
37
- --description "..."`),e);let i=de(process.env,t,s);return i.error!==null&&c({ok:!1,exitCode:1,message:i.error},e),i.text===null&&c({ok:!0,exitCode:0,message:"Aborted \u2014 nothing changed."},e),i.text}function f(n){return{ok:!1,exitCode:2,message:n}}function Xe(n){let t=n.commands,s=n.errors;return`kadence/v1 \u2014 ${t.length} commands, ${s.length} error codes.
38
- ${n.stability}
44
+ --description "..."`),t);let i=he(process.env,s,n);return i.error!==null&&d({ok:!1,exitCode:1,message:i.error},t),i.text===null&&d({ok:!0,exitCode:0,message:"Aborted \u2014 nothing changed."},t),i.text}var bt=["add","list","show","edit","move","assign","comment","log","parent","block","unblock","cancel","delete"],yt=["create","add","edit","start","close","status","list","burndown"],vt=["save","list","delete"];function f(e,s={}){return k(2,"invalid_argument",e,s)}function wt(e){let s=e.commands,n=e.errors;return`kadence/v1 \u2014 ${s.length} commands, ${n.length} error codes.
45
+ ${e.stability}
39
46
 
40
47
  The machine-readable form is what agents read:
41
- kadence schema --json`}g.command("schema","The machine-readable --json contract, for agents").option("--json","Machine-readable output for agents").example(" kadence schema --json").action(n=>{let t=n.json===!0,s=Y("0.2.1");c({ok:!0,exitCode:0,message:Xe(s),data:{schema:"kadence/v1",ok:!0,contract:s}},t)});g.command("init","Set up kadence in this repository").example(" kadence init").action(()=>{let n=Se(process.cwd());c({ok:n.ok,message:n.message,exitCode:n.ok?0:1},!1)});g.command("task [action] [arg] [value]","Tasks: add | list | show | move | assign").option("--title <text>","New title (for edit)").option("-d, --description <text>","Full description; use quotes for multiple lines").option("--type <type>",`Type: ${V.join(" | ")}`).option("--priority <level>",`Priority: ${W.join(" | ")}`).option("-a, --assignee <who>","Assignee, e.g. dev@example.com").option("--label <name>","Label; repeat the flag for several").option("--estimate <points>","Estimate in points, a positive number").option("--due <date>","Due date, YYYY-MM-DD; empty string clears it").option("--status <status>",`Filter by status: ${T.join(" | ")}`).option("--search <text>","Search title, description and comments").option("--overdue","Only tasks past their due date").option("--due-before <date>","Only tasks due before YYYY-MM-DD").option("--sort <key>",`Sort by: ${H.join(" | ")}`).option("--tree","Show parent/child structure").option("--parent <task>",'Parent task, e.g. KAD-1 (use "none" to detach)').option("--template <name>","Pre-fill fields from a saved template").option("--fields <list>","JSON only: comma-separated task fields to return").option("--json","Machine-readable output for agents").example(' kadence task add "Fix login" -d "Broken since 2.3" --type bug --priority high --estimate 3').example(" kadence task list --status in_progress --sort priority").example(" kadence task list --search cookie --overdue").example(" kadence task list --assignee me --label auth").example(" kadence task list --tree").example(" kadence task list --json --fields id,label,status").example(" kadence task move KAD-1,KAD-2,KAD-3 done bulk: all or nothing").example(' kadence task add "Login form" --parent KAD-1 KAD-1 can be an epic').example(" kadence task parent KAD-2 KAD-1").example(" kadence task block KAD-2 KAD-1 KAD-2 waits for KAD-1").example(" kadence task unblock KAD-2 KAD-1").example(" kadence task log KAD-1 2h also 90m, or -30m to correct").example(' kadence task add "Crash on save" --template bug').example(" kadence task show KAD-1").example(" kadence task move KAD-1 done").example(" kadence task edit KAD-1 --priority urgent --due 2026-09-30").example(" kadence task edit KAD-1 opens $EDITOR for the description").example(' kadence task comment KAD-1 "Needs review"').example(' kadence task assign KAD-1 dev@example.com (use "none" to unassign)').example(" kadence task cancel KAD-1 keeps it in history").example(" kadence task delete KAD-1 drops it from the board").action((n,t,s,e)=>{let i=e.json===!0,a=process.cwd();switch(n===void 0&&c(f(`Which action?
48
+ kadence schema --json`}w.command("decision [action] [arg]","Decisions: add | list | show \u2014 the why behind the work").option("--why <text>","Why this was chosen. Required \u2014 without it this is a changelog line").option("--rejected <text>","The alternative that was turned down").option("--task <ref>","The task this decision came out of").option("--supersedes <ref>","The decision this one replaces").option("--doc <path>","A document that carries the detail; repeat for several").option("--all","Include superseded decisions, hidden by default").option("--json","Machine-readable output for agents").example(' kadence decision add "Use ULIDs" --why "Clocks disagree between machines"').example(' kadence decision add "Use Avro" --why "..." --supersedes DEC-1').example(" kadence decision list --json").action((e,s,n)=>{let t=n.json===!0,i=process.cwd(),a=n.doc===void 0?void 0:Array.isArray(n.doc)?n.doc:[n.doc];switch(e){case"add":s===void 0&&d(f(`A title is required:
49
+ kadence decision add "Use ULIDs" --why "..."`),t),d(Be(i,process.env,s,{...n.why!==void 0?{why:n.why}:{},...n.rejected!==void 0?{rejected:n.rejected}:{},...n.task!==void 0?{task:n.task}:{},...n.supersedes!==void 0?{supersedes:n.supersedes}:{},...a!==void 0?{docs:a}:{}}),t);break;case void 0:case"list":d(Ue(i,process.env,{...n.all===!0?{all:!0}:{},...n.task!==void 0?{task:n.task}:{}}),t);break;case"show":s===void 0&&d(f(`Which decision?
50
+ kadence decision show DEC-1`),t),d(Le(i,process.env,s),t);break;default:d(f(`Unknown action "${e}".
51
+ Available: add, list, show`),t)}});w.command("schema","The machine-readable --json contract, for agents").option("--json","Machine-readable output for agents").example(" kadence schema --json").action(e=>{let s=e.json===!0,n=H("0.3.0");d({ok:!0,exitCode:0,message:wt(n),data:{schema:"kadence/v1",ok:!0,contract:n}},s)});w.command("init","Set up kadence in this repository").example(" kadence init").action(()=>{let e=_e(process.cwd(),"0.3.0");d({ok:e.ok,message:e.message,exitCode:e.ok?0:1},!1)});w.command("task [action] [arg] [value]","Tasks: add | list | show | move | assign | doc").option("--title <text>","New title (for edit)").option("-d, --description <text>","Full description; use quotes for multiple lines").option("--type <type>",`Type: ${Q.join(" | ")}`).option("--priority <level>",`Priority: ${X.join(" | ")}`).option("-a, --assignee <who>","Assignee, e.g. dev@example.com").option("--label <name>","Label; repeat the flag for several").option("--estimate <points>","Estimate in points, a positive number").option("--due <date>","Due date, YYYY-MM-DD; empty string clears it").option("--status <status>",`Filter by status: ${K.join(" | ")}`).option("--search <text>","Search title, description and comments").option("--overdue","Only tasks past their due date").option("--due-before <date>","Only tasks due before YYYY-MM-DD").option("--sort <key>",`Sort by: ${te.join(" | ")}`).option("--tree","Show parent/child structure").option("--parent <task>",'Parent task, e.g. KAD-1 (use "none" to detach)').option("--template <name>","Pre-fill fields from a saved template").option("--fields <list>","JSON only: comma-separated task fields to return").option("--json","Machine-readable output for agents").example(' kadence task add "Fix login" -d "Broken since 2.3" --type bug --priority high --estimate 3').example(" kadence task list --status in_progress --sort priority").example(" kadence task list --search cookie --overdue").example(" kadence task list --assignee me --label auth").example(" kadence task list --tree").example(" kadence task list --json --fields id,label,status").example(" kadence task move KAD-1,KAD-2,KAD-3 done bulk: all or nothing").example(' kadence task add "Login form" --parent KAD-1 KAD-1 can be an epic').example(" kadence task parent KAD-2 KAD-1").example(" kadence task block KAD-2 KAD-1 KAD-2 waits for KAD-1").example(" kadence task unblock KAD-2 KAD-1").example(" kadence task log KAD-1 2h also 90m, or -30m to correct").example(' kadence task add "Crash on save" --template bug').example(" kadence task show KAD-1").example(" kadence task move KAD-1 done").example(" kadence task edit KAD-1 --priority urgent --due 2026-09-30").example(" kadence task edit KAD-1 opens $EDITOR for the description").example(' kadence task comment KAD-1 "Needs review"').example(' kadence task assign KAD-1 dev@example.com (use "none" to unassign)').example(" kadence task cancel KAD-1 keeps it in history").example(" kadence task delete KAD-1 drops it from the board").action((e,s,n,t)=>{let i=t.json===!0,a=process.cwd();switch(e===void 0&&d(f(`Which action?
42
52
  kadence task add "Fix login"
43
53
  kadence task list
44
54
  kadence task show KAD-1
@@ -47,44 +57,45 @@ The machine-readable form is what agents read:
47
57
  kadence task assign KAD-1 dev@example.com
48
58
  kadence task comment KAD-1 "text"
49
59
  kadence task cancel KAD-1
50
- kadence task delete KAD-1`),i),n){case"add":{t===void 0&&c(f(`A title is required:
51
- kadence task add "Fix login"`),i);let r=e.estimate===void 0?void 0:Number(e.estimate);r!==void 0&&(!Number.isFinite(r)||r<0)&&c(f(`Estimate must be a positive number, got "${e.estimate}".
52
- kadence task add "Fix login" --estimate 3`),i);let d={};if(e.template!==void 0){let l=Ne(a,process.env,e.template);"error"in l?c(l.error,i):d=l.fields}let o=e.label===void 0?void 0:Array.isArray(e.label)?e.label:[e.label];c(z(a,process.env,t,{...d,...e.description!==void 0?{description:e.description}:{},...e.type!==void 0?{type:e.type}:{},...e.priority!==void 0?{priority:e.priority}:{},...e.assignee!==void 0?{assignee:e.assignee}:{},...o!==void 0?{labels:o}:{},...e.due!==void 0?{due:e.due}:{},...e.parent!==void 0?{parent:e.parent}:{},...r!==void 0?{estimate:r}:{}}),i);break}case"log":(t===void 0||s===void 0)&&c(f(`A task and a duration are required:
60
+ kadence task delete KAD-1`),i),e){case"add":{s===void 0&&d(f(`A title is required:
61
+ kadence task add "Fix login"`),i);let r=t.estimate===void 0?void 0:Number(t.estimate);r!==void 0&&(!Number.isFinite(r)||r<0)&&d(f(`Estimate must be a positive number, got "${t.estimate}".
62
+ kadence task add "Fix login" --estimate 3`),i);let o={};if(t.template!==void 0){let l=Ve(a,process.env,t.template);"error"in l?d(l.error,i):o=l.fields}let c=t.label===void 0?void 0:Array.isArray(t.label)?t.label:[t.label];d(ne(a,process.env,s,{...o,...t.description!==void 0?{description:t.description}:{},...t.type!==void 0?{type:t.type}:{},...t.priority!==void 0?{priority:t.priority}:{},...t.assignee!==void 0?{assignee:t.assignee}:{},...c!==void 0?{labels:c}:{},...t.due!==void 0?{due:t.due}:{},...t.parent!==void 0?{parent:t.parent}:{},...r!==void 0?{estimate:r}:{}}),i);break}case"doc":(s===void 0||n===void 0)&&d(f(`A task and a path are required:
63
+ kadence task doc KAD-1 docs/design.md`),i),d(ue(a,process.env,s,n),i);break;case"log":(s===void 0||n===void 0)&&d(f(`A task and a duration are required:
53
64
  kadence task log KAD-1 2h
54
- kadence task log KAD-1 90m`),i),c(K(a,process.env,t,s),i);break;case"parent":(t===void 0||s===void 0)&&c(f(`A task and a parent are required:
65
+ kadence task log KAD-1 90m`),i),d(B(a,process.env,s,n),i);break;case"parent":(s===void 0||n===void 0)&&d(f(`A task and a parent are required:
55
66
  kadence task parent KAD-2 KAD-1
56
- kadence task parent KAD-2 none to detach`),i),c(re(a,process.env,t,s),i);break;case"block":case"unblock":(t===void 0||s===void 0)&&c(f(`A task and a blocker are required:
67
+ kadence task parent KAD-2 none to detach`),i),d(fe(a,process.env,s,n),i);break;case"block":case"unblock":(s===void 0||n===void 0)&&d(f(`A task and a blocker are required:
57
68
  kadence task block KAD-2 KAD-1 KAD-2 waits for KAD-1
58
- kadence task unblock KAD-2 KAD-1`),i),c(oe(a,process.env,t,s,n==="unblock"),i);break;case"edit":{t===void 0&&c(f(`Which task?
59
- kadence task edit KAD-1 --priority high`),i);let r=e.estimate===void 0?void 0:Number(e.estimate);r!==void 0&&(!Number.isFinite(r)||r<0)&&c(f(`Estimate must be a positive number, got "${e.estimate}".`),i);let d=e.label===void 0?void 0:Array.isArray(e.label)?e.label:[e.label],o=e.title!==void 0||e.description!==void 0||e.type!==void 0||e.priority!==void 0||e.due!==void 0||r!==void 0||d!==void 0||s!==void 0,l=e.description;if(!o){let u=j(a,process.env,t);u.ok||c(u,i);let m=u.data.task??{description:null};l=Re(void 0,m.description??"",`Editing the description of ${t}.`,i)}c(ne(a,process.env,t,{...e.title!==void 0?{title:e.title}:s!==void 0?{title:s}:{},...l!==void 0?{description:l}:{},...e.type!==void 0?{type:e.type}:{},...e.priority!==void 0?{priority:e.priority}:{},...e.due!==void 0?{due:e.due}:{},...r!==void 0?{estimate:r}:{},...d!==void 0?{labels:d}:{}}),i);break}case"comment":{t===void 0&&c(f(`Which task?
60
- kadence task comment KAD-1 "text"`),i);let r=Re(s,"",`Comment on ${t}.`,i);c(ae(a,process.env,t,r??""),i);break}case"cancel":t===void 0&&c(f(`Which task?
61
- kadence task cancel KAD-1`),i),c(se(a,process.env,t),i);break;case"delete":t===void 0&&c(f(`Which task?
62
- kadence task delete KAD-1`),i),c(ie(a,process.env,t),i);break;case"list":c(Q(a,process.env,{...e.status!==void 0?{status:e.status}:{},...e.search!==void 0?{search:e.search}:{},...e.type!==void 0?{type:e.type}:{},...e.priority!==void 0?{priority:e.priority}:{},...e.assignee!==void 0?{assignee:e.assignee}:{},...e.label!==void 0?{label:Array.isArray(e.label)?e.label.at(-1):e.label}:{},...e.overdue===!0?{overdue:!0}:{},...e.dueBefore!==void 0?{dueBefore:e.dueBefore}:{},...e.sort!==void 0?{sort:e.sort}:{},...e.tree===!0?{tree:!0}:{},...i&&e.fields!==void 0?{fields:e.fields}:{}}),i);break;case"show":t===void 0&&c(f(`Which task?
63
- kadence task show KAD-1`),i),c(j(a,process.env,t),i);break;case"move":(t===void 0||s===void 0)&&c(f(`A task and a target status are required:
69
+ kadence task unblock KAD-2 KAD-1`),i),d(pe(a,process.env,s,n,e==="unblock"),i);break;case"edit":{s===void 0&&d(f(`Which task?
70
+ kadence task edit KAD-1 --priority high`),i);let r=t.estimate===void 0?void 0:Number(t.estimate);r!==void 0&&(!Number.isFinite(r)||r<0)&&d(f(`Estimate must be a positive number, got "${t.estimate}".`),i);let o=t.label===void 0?void 0:Array.isArray(t.label)?t.label:[t.label],c=t.title!==void 0||t.description!==void 0||t.type!==void 0||t.priority!==void 0||t.due!==void 0||r!==void 0||o!==void 0||n!==void 0,l=t.description;if(!c){let u=I(a,process.env,s);u.ok||d(u,i);let m=u.data.task??{description:null};l=Je(void 0,m.description??"",`Editing the description of ${s}.`,i)}d(de(a,process.env,s,{...t.title!==void 0?{title:t.title}:n!==void 0?{title:n}:{},...l!==void 0?{description:l}:{},...t.type!==void 0?{type:t.type}:{},...t.priority!==void 0?{priority:t.priority}:{},...t.due!==void 0?{due:t.due}:{},...r!==void 0?{estimate:r}:{},...o!==void 0?{labels:o}:{}}),i);break}case"comment":{s===void 0&&d(f(`Which task?
71
+ kadence task comment KAD-1 "text"`),i);let r=Je(n,"",`Comment on ${s}.`,i);d(me(a,process.env,s,r??""),i);break}case"cancel":s===void 0&&d(f(`Which task?
72
+ kadence task cancel KAD-1`),i),d(ce(a,process.env,s),i);break;case"delete":s===void 0&&d(f(`Which task?
73
+ kadence task delete KAD-1`),i),d(le(a,process.env,s),i);break;case"list":d(se(a,process.env,{...t.status!==void 0?{status:t.status}:{},...t.search!==void 0?{search:t.search}:{},...t.type!==void 0?{type:t.type}:{},...t.priority!==void 0?{priority:t.priority}:{},...t.assignee!==void 0?{assignee:t.assignee}:{},...t.label!==void 0?{label:Array.isArray(t.label)?t.label.at(-1):t.label}:{},...t.overdue===!0?{overdue:!0}:{},...t.dueBefore!==void 0?{dueBefore:t.dueBefore}:{},...t.sort!==void 0?{sort:t.sort}:{},...t.tree===!0?{tree:!0}:{},...i&&t.fields!==void 0?{fields:t.fields}:{}}),i);break;case"show":s===void 0&&d(f(`Which task?
74
+ kadence task show KAD-1`),i),d(I(a,process.env,s),i);break;case"move":(s===void 0||n===void 0)&&d(f(`A task and a target status are required:
64
75
  kadence task move KAD-1 done
65
- Statuses: ${T.join(", ")}`),i),c(X(a,process.env,t,s),i);break;case"assign":(t===void 0||s===void 0)&&c(f(`A task and an assignee are required:
76
+ Statuses: ${K.join(", ")}`),i),d(ie(a,process.env,s,n),i);break;case"assign":(s===void 0||n===void 0)&&d(f(`A task and an assignee are required:
66
77
  kadence task assign KAD-1 dev@example.com
67
- kadence task assign KAD-1 none to unassign`),i),c(te(a,process.env,t,s),i);break;default:c(f(`Unknown action "${n}".
78
+ kadence task assign KAD-1 none to unassign`),i),d(oe(a,process.env,s,n),i);break;default:d(f(`Unknown action "${e}".
68
79
  Available: add, list, show, edit, move, assign, comment, log,
69
80
  parent, block, unblock, cancel, delete
70
- kadence task --help`),i)}});g.command("board [action]",'Kanban board in the terminal; "config" edits the columns').option("--fields <list>","JSON only: comma-separated task fields to return").option("--statuses <list>",'Comma-separated columns, e.g. "todo,doing,done"').option("-a, --assignee <who>",`Only this person's tasks; "me" means you`).option("--sprint","Only tasks in the active sprint").option("--json","Machine-readable output for agents").example(" kadence board").example(" kadence board --assignee me --sprint").example(" kadence board --json --fields label,status,assignee").example(" kadence board config").example(' kadence board config --statuses "todo,doing,review,done"').action((n,t)=>{n==="config"&&c(Oe(process.cwd(),process.env,t.statuses),t.json===!0),n!==void 0&&c(f(`Unknown action "${n}".
81
+ kadence task --help`,{received:e,allowed:bt}),i)}});w.command("board [action]",'Kanban board in the terminal; "config" edits the columns').option("--fields <list>","JSON only: comma-separated task fields to return").option("--statuses <list>",'Comma-separated columns, e.g. "todo,doing,done"').option("-a, --assignee <who>",`Only this person's tasks; "me" means you`).option("--sprint","Only tasks in the active sprint").option("--json","Machine-readable output for agents").example(" kadence board").example(" kadence board --assignee me --sprint").example(" kadence board --json --fields label,status,assignee").example(" kadence board config").example(' kadence board config --statuses "todo,doing,review,done"').action((e,s)=>{e==="config"&&d(Me(process.cwd(),process.env,s.statuses),s.json===!0),e!==void 0&&d(f(`Unknown action "${e}".
71
82
  Available: config
72
- kadence board --help`),t.json===!0),c(Ee(process.cwd(),process.env,{...t.assignee!==void 0?{assignee:t.assignee}:{},...t.sprint===!0?{sprint:"active"}:{}},t.json===!0?t.fields:void 0),t.json===!0)});g.command("sprint [action] [name]","Sprints: create | add | edit | start | close | status | list | burndown").option("--sprint <name>","Which sprint to add to; defaults to the active one").option("--name <name>","New name (for edit)").option("-d, --description <text>","Sprint description (for edit)").option("--start <date>","Start date, YYYY-MM-DD").option("--end <date>","End date, YYYY-MM-DD").option("--json","Machine-readable output for agents").example(' kadence sprint create "Sprint 1" first one starts right away').example(' kadence sprint create "Sprint 2" later ones are planned').example(' kadence sprint add KAD-1 --sprint "Sprint 2"').example(" kadence sprint start starts the next planned sprint").example(" kadence sprint edit --start 2026-09-01 --end 2026-09-14").example(' kadence sprint edit "Sprint 2" --name "Sprint 2: auth"').example(" kadence sprint burndown chart from the journal, any day").example(" kadence sprint close closes the active one, reports velocity").action((n,t,s)=>{let e=s.json===!0,i=process.cwd();switch(n===void 0&&c(f(`Which action?
83
+ kadence board --help`,{received:e,allowed:["config"]}),s.json===!0),d(Fe(process.cwd(),process.env,{...s.assignee!==void 0?{assignee:s.assignee}:{},...s.sprint===!0?{sprint:"active"}:{}},s.json===!0?s.fields:void 0),s.json===!0)});w.command("sprint [action] [name]","Sprints: create | add | edit | start | close | status | list | burndown").option("--sprint <name>","Which sprint to add to; defaults to the active one").option("--name <name>","New name (for edit)").option("-d, --description <text>","Sprint description (for edit)").option("--start <date>","Start date, YYYY-MM-DD").option("--end <date>","End date, YYYY-MM-DD").option("--json","Machine-readable output for agents").example(' kadence sprint create "Sprint 1" first one starts right away').example(' kadence sprint create "Sprint 2" later ones are planned').example(' kadence sprint add KAD-1 --sprint "Sprint 2"').example(" kadence sprint start starts the next planned sprint").example(" kadence sprint edit --start 2026-09-01 --end 2026-09-14").example(' kadence sprint edit "Sprint 2" --name "Sprint 2: auth"').example(" kadence sprint burndown chart from the journal, any day").example(" kadence sprint close closes the active one, reports velocity").action((e,s,n)=>{let t=n.json===!0,i=process.cwd();switch(e===void 0&&d(f(`Which action?
73
84
  kadence sprint create "Sprint 1"
74
85
  kadence sprint add KAD-1
75
86
  kadence sprint edit --start 2026-09-01
76
87
  kadence sprint start
77
88
  kadence sprint close
78
89
  kadence sprint status
79
- kadence sprint list`),e),n){case"create":t===void 0&&c(f(`A sprint name is required:
80
- kadence sprint create "Sprint 1"`),e),c(le(i,process.env,t),e);break;case"add":t===void 0&&c(f(`Which task?
90
+ kadence sprint list`),t),e){case"create":s===void 0&&d(f(`A sprint name is required:
91
+ kadence sprint create "Sprint 1"`),t),d(ke(i,process.env,s),t);break;case"add":s===void 0&&d(f(`Which task?
81
92
  kadence sprint add KAD-1
82
- kadence sprint add KAD-1 --sprint "Sprint 2"`),e),c(ue(i,process.env,t,s.sprint===void 0?{}:{sprint:s.sprint}),e);break;case"edit":c(ge(i,process.env,t,{...s.name!==void 0?{name:s.name}:{},...s.description!==void 0?{description:s.description}:{},...s.start!==void 0?{startDate:s.start}:{},...s.end!==void 0?{endDate:s.end}:{}}),e);break;case"start":c(pe(i,process.env,t),e);break;case"close":c(me(i,process.env),e);break;case"status":c(fe(i,process.env),e);break;case"list":c(he(i,process.env),e);break;case"burndown":c(ke(i,process.env,t),e);break;default:c(f(`Unknown action "${n}".
93
+ kadence sprint add KAD-1 --sprint "Sprint 2"`),t),d(be(i,process.env,s,n.sprint===void 0?{}:{sprint:n.sprint}),t);break;case"edit":d(xe(i,process.env,s,{...n.name!==void 0?{name:n.name}:{},...n.description!==void 0?{description:n.description}:{},...n.start!==void 0?{startDate:n.start}:{},...n.end!==void 0?{endDate:n.end}:{}}),t);break;case"start":d(we(i,process.env,s),t);break;case"close":d(ye(i,process.env),t);break;case"status":d(ve(i,process.env),t);break;case"list":d(Ae(i,process.env),t);break;case"burndown":d(De(i,process.env,s),t);break;default:d(f(`Unknown action "${e}".
83
94
  Available: create, add, edit, start, close, status, list, burndown
84
- kadence sprint --help`),e)}});g.command("template [action] [name]","Task templates: save | list | delete").option("-d, --description <text>","Default description").option("--type <type>","Default type").option("--priority <level>","Default priority").option("-a, --assignee <who>","Default assignee").option("--label <name>","Default label; repeat for several").option("--estimate <points>","Default estimate").option("--json","Machine-readable output for agents").example(" kadence template save bug --type bug --priority high --label triage").example(" kadence template list").action((n,t,s)=>{let e=s.json===!0,i=process.cwd();switch(n){case"save":{t===void 0&&c(f(`A template name is required:
85
- kadence template save bug --type bug`),e);let a=s.label===void 0?void 0:Array.isArray(s.label)?s.label:[s.label];c(Te(i,process.env,t,{...s.description!==void 0?{description:s.description}:{},...s.type!==void 0?{type:s.type}:{},...s.priority!==void 0?{priority:s.priority}:{},...s.assignee!==void 0?{assignee:s.assignee}:{},...a!==void 0?{labels:a}:{},...s.estimate!==void 0?{estimate:Number(s.estimate)}:{}}),e);break}case"list":case void 0:c(je(i,process.env),e);break;case"delete":t===void 0&&c(f(`Which template?
86
- kadence template delete bug`),e),c(Ke(i,process.env,t),e);break;default:c(f(`Unknown action "${n}".
87
- Available: save, list, delete`),e)}});g.command("ui","Interactive kanban board").alias("board:ui").example(" kadence ui").action(async()=>{let{runUi:n}=await import("./chunks/ui-ILZI767Q.js"),t=await n(process.cwd(),process.env);t.ok||c(t,!1)});g.help();g.version("0.2.1");var A=process.argv;if(A[2]==="task"&&A[3]==="log"&&A[4]!==void 0&&A[5]!==void 0){let n=K(process.cwd(),process.env,A[4],A[5]),t=A.includes("--json");c(n,t)}var _e=process.argv.findIndex((n,t)=>n.startsWith("-")&&/^-\d+(\.\d+)?$/.test(n)&&process.argv[t-1]==="--estimate");_e!==-1&&(process.stderr.write(`Estimate must be a positive number, got "${process.argv[_e]}".
95
+ kadence sprint --help`,{received:e,allowed:yt}),t)}});w.command("template [action] [name]","Task templates: save | list | delete").option("-d, --description <text>","Default description").option("--type <type>","Default type").option("--priority <level>","Default priority").option("-a, --assignee <who>","Default assignee").option("--label <name>","Default label; repeat for several").option("--estimate <points>","Default estimate").option("--json","Machine-readable output for agents").example(" kadence template save bug --type bug --priority high --label triage").example(" kadence template list").action((e,s,n)=>{let t=n.json===!0,i=process.cwd();switch(e){case"save":{s===void 0&&d(f(`A template name is required:
96
+ kadence template save bug --type bug`),t);let a=n.label===void 0?void 0:Array.isArray(n.label)?n.label:[n.label];d(qe(i,process.env,s,{...n.description!==void 0?{description:n.description}:{},...n.type!==void 0?{type:n.type}:{},...n.priority!==void 0?{priority:n.priority}:{},...n.assignee!==void 0?{assignee:n.assignee}:{},...a!==void 0?{labels:a}:{},...n.estimate!==void 0?{estimate:Number(n.estimate)}:{}}),t);break}case"list":case void 0:d(We(i,process.env),t);break;case"delete":s===void 0&&d(f(`Which template?
97
+ kadence template delete bug`),t),d(Ye(i,process.env,s),t);break;default:d(f(`Unknown action "${e}".
98
+ Available: save, list, delete`,{received:e,allowed:vt}),t)}});w.command("ui","Interactive kanban board").alias("board:ui").example(" kadence ui").action(async()=>{let{runUi:e}=await import("./chunks/ui-DYZ73OIR.js"),s=await e(process.cwd(),process.env);s.ok||d(s,!1)});w.help();w.version("0.3.0");var $=process.argv;if($[2]==="task"&&$[3]==="log"&&$[4]!==void 0&&$[5]!==void 0){let e=B(process.cwd(),process.env,$[4],$[5]),s=$.includes("--json");d(e,s)}var Ge=process.argv.findIndex((e,s)=>e.startsWith("-")&&/^-\d+(\.\d+)?$/.test(e)&&process.argv[s-1]==="--estimate");Ge!==-1&&(process.stderr.write(`Estimate must be a positive number, got "${process.argv[Ge]}".
88
99
  kadence task add "Fix login" --estimate 3
89
- `),process.exit(2));try{g.parse()}catch(n){process.stderr.write(`${n.message}
100
+ `),process.exit(2));try{w.parse()}catch(e){process.stderr.write(`${e.message}
90
101
  `),process.exit(2)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kadence",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Your team and your AI agents work from the same context: tasks, their full history and time as plain files in your git repository",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,12 +24,12 @@
24
24
  "prepublishOnly": "npm run typecheck && npm test && npm run build"
25
25
  },
26
26
  "dependencies": {
27
- "blessed": "^0.1.81",
28
- "cac": "^7.0.0"
27
+ "blessed": "^0.1.81"
29
28
  },
30
29
  "devDependencies": {
31
30
  "@types/blessed": "^0.1.27",
32
31
  "@types/node": "^22.0.0",
32
+ "cac": "^7.0.0",
33
33
  "esbuild": "^0.28.0",
34
34
  "typescript": "^5.6.0",
35
35
  "vitest": "^4.0.0"
@@ -1,172 +0,0 @@
1
- #!/usr/bin/env node
2
- var Wt=`# kadence \u2014 for AI agents
3
-
4
- This project's tasks live here as plain files. Read them directly, or through
5
- the CLI. No server required.
6
-
7
- ## Commands
8
-
9
- kadence board --json the whole board
10
- kadence task list --json all tasks
11
- kadence task show KAD-42 --json one task with its history
12
- kadence task add "title" -d "..." --type bug --estimate 3
13
- kadence task move KAD-42 in_progress
14
- kadence task assign KAD-42 you@example.com
15
- kadence sprint status --json current sprint progress
16
-
17
- ## JSON contract
18
-
19
- Every \`--json\` response carries \`schema: "kadence/v1"\`. stdout holds JSON and
20
- nothing else; warnings go to stderr. Exit codes: 0 success, 1 runtime error,
21
- 2 bad arguments.
22
-
23
- The contract itself is machine-readable \u2014 read it instead of guessing:
24
-
25
- kadence schema --json
26
-
27
- It lists every command, the fields you can rely on, and every error code. It
28
- works outside a repository, so you can read it before \`init\`.
29
-
30
- ## When something fails
31
-
32
- A failed \`--json\` call carries \`error.code\` \u2014 branch on that, not on the
33
- sentence. Where the valid set is knowable it also carries \`allowed\`:
34
-
35
- { "ok": false,
36
- "error": { "code": "unknown_status", "received": "shipped",
37
- "allowed": ["backlog", "in_progress", "done"],
38
- "hint": "kadence board statuses --json" } }
39
-
40
- Statuses are configured per project, so \`allowed\` is the only reliable source \u2014
41
- never assume the defaults. Retrying an identical command never helps: there is no
42
- network and no lock, so the same input always fails the same way.
43
-
44
- ## Working as an agent
45
-
46
- Set \`KADENCE_SOURCE=agent\` so events record your authorship. Without it an
47
- event is marked as human \u2014 we do not guess.
48
-
49
- ## Why to ask rather than read the files
50
-
51
- You cannot find a task by its label in the journal. \`KAD-3\` is derived while
52
- folding and is never stored in an event, so \`grep -r "KAD-3" .kadence/events/\`
53
- returns nothing. Folding the journal yourself is the only alternative to asking.
54
-
55
- Asking is also cheaper, and stays cheap: \`task show --json\` is about 950 bytes
56
- whether the project holds ten tasks or a thousand, while the journal behind it
57
- grows past 500 KB.
58
-
59
- \`board --json\` is the exception: it returns every task in full, which on a large
60
- project is a lot of description you did not ask for. Narrow it:
61
-
62
- kadence board --json --fields label,status,assignee
63
- kadence task list --json --fields id,label,status
64
-
65
- \`kadence schema --json\` lists every selectable field.
66
-
67
- ## What not to do
68
-
69
- Do not hand-edit files under \`.kadence/events/\`: the journal is appended to,
70
- never modified. To correct the state, add a new event through the CLI.
71
- `,se="<!-- kadence:begin -->",Z="<!-- kadence:end -->",G=`${se}
72
- ## Project tasks \u2014 kadence
73
-
74
- Tasks live in \`.kadence/\` as plain files. Read them directly or via the CLI:
75
-
76
- kadence board --json the whole board
77
- kadence task list --json all tasks
78
- kadence task move KAD-1 done change state
79
-
80
- kadence schema --json the contract: commands, fields, error codes
81
-
82
- \`--json\` responses carry \`schema: "kadence/v1"\`; stdout is JSON only. A failure
83
- carries \`error.code\` and, where knowable, \`allowed\`.
84
- When acting as an agent, set \`KADENCE_SOURCE=agent\`.
85
-
86
- Details: \`.kadence/README.md\`
87
- ${Z}`;function Yt(e){if(e===null||e.trim().length===0)return`${G}
88
- `;let n=e.indexOf(se),r=e.indexOf(Z);if(n!==-1&&r!==-1&&r>n){let s=e.slice(0,n),o=e.slice(r+Z.length);return`${s}${G}${o}`}let t=e.endsWith(`
89
- `)?`
90
- `:`
91
-
92
- `;return`${e}${t}${G}
93
- `}var I=["id","label","title","description","type","priority","status","labels","assignee","reporter","sprint","loggedHours","parent","blockedBy","due","comments","estimate","history"],oe=["not_a_repository","not_initialised","no_git_identity","task_not_found","sprint_not_found","unknown_status","unknown_type","unknown_priority","unknown_field","invalid_argument"],Ue={not_a_repository:"There is no git repository here. kadence stores its journal inside one.",not_initialised:"The repository has no .kadence/ folder yet. Run `kadence init`.",no_git_identity:"Git has no user.email, so an event would have no author.",task_not_found:"No task carries that ULID or KAD-N label. Nothing was changed.",sprint_not_found:"No sprint carries that name or id.",unknown_status:"The status is not one of this project\u2019s columns. They are configurable, so read `allowed`.",unknown_type:"The task type is not one of the four kadence defines.",unknown_priority:"The priority is not one of the four kadence defines.",unknown_field:"A name given to --fields is not a task field. Read `allowed`.",invalid_argument:"An argument was missing or malformed; the command did nothing."};function Gt(e){return{version:"kadence/v1",tool:{name:"kadence",version:e},stability:"Additive only: fields and error codes may be added, never renamed or removed within kadence/v1.",exitCodes:{0:"success",1:"runtime error \u2014 the command understood you and could not comply",2:"bad arguments \u2014 nothing was attempted"},output:{stdout:"With --json, JSON and nothing else.",stderr:"Warnings and human messages, never part of the contract."},env:{KADENCE_SOURCE:'Set to "agent" so events record agent authorship. Without it an event counts as human \u2014 we do not guess.',NO_COLOR:"Any value disables colour."},errors:oe.map(n=>({code:n,meaning:Ue[n]})),shapes:{task:{required:["id","label","title","status","type","priority","estimate","assignee","blockedBy","loggedHours"],selectable:[...I],notes:{id:"ULID. The identity of the task; KAD-N is a label derived while folding and is never stored.",history:"Present in `task show` only \u2014 the events that produced this state.",required:"What a full response carries. With --fields you get exactly what you asked for and nothing else."}},board:{required:["schema","ok","columns"]},error:{required:["code","message"],optional:["received","allowed","hint"],notes:{allowed:"Present when the valid set is knowable \u2014 statuses are project-configurable.",retryable:"Deliberately absent: no network, no lock, so a retry always fails identically."}}},commands:[{name:"schema",summary:"This contract. Works outside a repository."},{name:"init",summary:"Create .kadence/ and the agent instruction files."},{name:"board",summary:"The whole board, grouped by column. Every task in full \u2014 pass --fields on a large project.",flags:["--json","--fields"],json:!0},{name:"task list",summary:"All tasks, filterable.",flags:["--json","--fields"],json:!0},{name:"task show",summary:"One task with its comments and full history.",args:["ref"],json:!0},{name:"task add",summary:"Create a task.",args:["title"],json:!0},{name:"task move",summary:"Change status. Accepts several refs, all or nothing.",args:["refs","status"],json:!0},{name:"task assign",summary:"Assign or unassign.",args:["refs","who"],json:!0},{name:"task comment",summary:"Append a comment.",args:["ref","text"],json:!0},{name:"task edit",summary:"Change fields.",args:["refs"],json:!0},{name:"task log",summary:"Log hours.",args:["refs","hours"],json:!0},{name:"task block",summary:"Record a blocker.",args:["ref","blocker"],json:!0},{name:"sprint status",summary:"Current sprint progress.",json:!0},{name:"sprint create",summary:"Start a sprint.",args:["name"],json:!0},{name:"sprint close",summary:"Close it and report velocity.",json:!0}]}}var Y=["backlog","todo","in_progress","blocked","in_review","done","cancelled"],Vt="done",He="cancelled",R=["task","bug","story","epic"],j=["low","normal","high","urgent"];function le(e){let n=[...e].sort((l,p)=>l.id<p.id?-1:l.id>p.id?1:0),r=new Map,t=new Map,s=new Map,o=null,i=[],a=[];for(let l of n){if(l.type==="template.saved"){let p=typeof l.data?.name=="string"?l.data.name:null;p!==null&&s.set(p,{name:p,fields:l.data?.fields??{},author:l.actor});continue}if(l.type==="board.configured"){let p=l.data?.statuses;if(Array.isArray(p)){let m=p.filter(g=>typeof g=="string"&&g.length>0);m.length>0&&(o=m)}continue}if(l.type==="template.deleted"){let p=typeof l.data?.name=="string"?l.data.name:null;p!==null&&s.delete(p);continue}ie(l,r,t,i,a)}let d=a.length>0,u=a;for(;u.length>0;){let l=[];for(let p of u)ie(p,r,t,i,l);if(l.length===u.length){u=l;break}u=l}if(d)for(let l of r.values())l.history.sort((p,m)=>p.id<m.id?-1:1);let c=[...r.values()].sort((l,p)=>l.id<p.id?-1:1);c.forEach((l,p)=>{l.label=`KAD-${p+1}`});let f=new Set(c.map(l=>l.id));for(let l of c)l.parent!==null&&!f.has(l.parent)&&(l.parent=null),l.blockedBy=l.blockedBy.filter(p=>f.has(p));return{tasks:c,sprints:[...t.values()].sort((l,p)=>l.id<p.id?-1:1),statuses:o??[...Y],orphanStatuses:[...new Set(c.map(l=>l.status).filter(l=>!(o??Y).includes(l)))].sort(),templates:[...s.values()].sort((l,p)=>l.name.localeCompare(p.name)),cycles:We(c),pending:u,rejected:i}}function ie(e,n,r,t,s){let o=e.data??{};if(e.type==="task.created")return n.has(e.entity)||n.set(e.entity,{id:e.entity,label:"",title:typeof o.title=="string"?o.title:"(untitled)",description:v(o.description),type:ae(o.type),priority:de(o.priority),status:"backlog",labels:ue(o.labels),assignee:v(o.assignee),reporter:e.actor,sprint:null,parent:v(o.parent),blockedBy:[],due:v(o.due),comments:[],estimate:typeof o.estimate=="number"?o.estimate:null,loggedHours:0,createdAt:e.ts,updatedAt:e.ts,history:[]}),V(n.get(e.entity),e),!0;if(e.type==="sprint.created")return r.has(e.entity)||r.set(e.entity,{id:e.entity,name:typeof o.name=="string"?o.name:"(untitled)",description:v(o.description),startDate:v(o.startDate),endDate:v(o.endDate),status:"planned",closedBy:null,taskIds:[]}),!0;if(e.type.startsWith("sprint.")){let a=r.get(e.entity);if(a===void 0)return s.push(e),!1;if(e.type==="sprint.started")return a.status==="planned"&&(a.status="active"),!0;if(e.type==="sprint.updated")return a.status==="closed"?(t.push(e),!0):(typeof o.name=="string"&&(a.name=o.name),o.description!==void 0&&(a.description=v(o.description)),o.startDate!==void 0&&(a.startDate=v(o.startDate)),o.endDate!==void 0&&(a.endDate=v(o.endDate)),!0);if(e.type==="sprint.closed")return a.closedBy===null?(a.status="closed",a.closedBy=e.id):t.push(e),!0;if(e.type==="sprint.cancelled")return a.status==="planned"?a.status="cancelled":t.push(e),!0;if(e.type==="sprint.task_added"){if(a.status==="closed")return t.push(e),!0;let d=typeof o.task=="string"?o.task:null;if(d===null)return!0;let u=n.get(d);return u===void 0?(s.push(e),!1):(u.sprint=a.id,a.taskIds.includes(d)||a.taskIds.push(d),V(u,e),!0)}return!0}let i=n.get(e.entity);if(i===void 0)return s.push(e),!1;if(e.type==="task.deleted")return n.delete(e.entity),!0;switch(e.type){case"task.moved":{let a=o.to;typeof a=="string"&&a.length>0&&(i.status=a);break}case"task.cancelled":i.status=He;break;case"task.reopened":i.status="in_progress";break;case"task.assigned":i.assignee=v(o.assignee);break;case"task.updated":typeof o.title=="string"&&(i.title=o.title),o.description!==void 0&&(i.description=v(o.description)),o.type!==void 0&&(i.type=ae(o.type)),o.priority!==void 0&&(i.priority=de(o.priority)),o.labels!==void 0&&(i.labels=ue(o.labels)),o.due!==void 0&&(i.due=v(o.due)),typeof o.estimate=="number"&&(i.estimate=o.estimate);break;case"task.parent_set":i.parent=v(o.parent);break;case"task.blocked_by_added":{let a=v(o.blocker);a!==null&&!i.blockedBy.includes(a)&&i.blockedBy.push(a);break}case"task.blocked_by_removed":{let a=v(o.blocker);a!==null&&(i.blockedBy=i.blockedBy.filter(d=>d!==a));break}case"task.time_logged":{let a=o.hours;typeof a=="number"&&Number.isFinite(a)&&(i.loggedHours=Math.max(0,i.loggedHours+a));break}case"task.commented":{let a=v(o.text);a!==null&&i.comments.push({id:e.id,author:e.actor,ts:e.ts,text:a});break}default:break}return V(i,e),!0}function V(e,n){e.history.push({id:n.id,type:n.type,actor:n.actor,ts:n.ts,data:n.data??{}}),n.ts>e.updatedAt&&(e.updatedAt=n.ts)}function v(e){return typeof e=="string"&&e.length>0?e:null}function ae(e){return R.includes(e)?e:"task"}function de(e){return j.includes(e)?e:"normal"}function ue(e){return Array.isArray(e)?e.filter(n=>typeof n=="string"&&n.length>0):[]}function We(e){let n=new Map(e.map(o=>[o.id,o])),r=[],t=new Set,s=(o,i)=>{let a=new Map,d=(u,c)=>{let f=a.get(u);if(f==="done")return;if(f==="visiting"){let p=c.indexOf(u),m=c.slice(p),g=`${o}:${[...m].sort().join(",")}`;t.has(g)||(t.add(g),r.push({kind:o,path:[...m,u]}));return}a.set(u,"visiting");let l=n.get(u);if(l!==void 0)for(let p of i(l))d(p,[...c,u]);a.set(u,"done")};for(let u of e)d(u.id,[])};return s("parent",o=>o.parent===null?[]:[o.parent]),s("blocking",o=>o.blockedBy),r}var ce={urgent:0,high:1,normal:2,low:3};function pe(e,n){return e!==null&&e.toLowerCase().includes(n)}function ge(e,n,r=new Date){let t=r.toISOString().slice(0,10),s=n.search?.toLowerCase();return e.filter(o=>{if(s!==void 0&&s.length>0){let i=o.comments.some(a=>a.text.toLowerCase().includes(s));if(!pe(o.title,s)&&!pe(o.description,s)&&!i)return!1}if(n.status!==void 0&&o.status!==n.status||n.type!==void 0&&o.type!==n.type||n.priority!==void 0&&o.priority!==n.priority)return!1;if(n.assignee!==void 0){let i=n.assignee.toLowerCase(),a=(o.assignee??"").toLowerCase();if(i==="none"?a!=="":a!==i)return!1}if(n.label!==void 0){let i=n.label.toLowerCase();if(!o.labels.some(a=>a.toLowerCase()===i))return!1}return!(n.sprint!==void 0&&o.sprint!==n.sprint||n.overdue===!0&&(o.due===null||o.due>=t)||n.dueBefore!==void 0&&(o.due===null||o.due>=n.dueBefore))})}function me(e,n){let r=[...e];switch(n){case"priority":return r.sort((t,s)=>ce[t.priority]-ce[s.priority]);case"due":return r.sort((t,s)=>fe(t.due,s.due,(o,i)=>o<i?-1:o>i?1:0));case"estimate":return r.sort((t,s)=>fe(t.estimate,s.estimate,(o,i)=>i-o));default:return r.sort((t,s)=>t.id<s.id?-1:t.id>s.id?1:0)}}function fe(e,n,r){return e===null&&n===null?0:e===null?1:n===null?-1:r(e,n)}function ke(e){let n=[];return e.search!==void 0&&n.push(`search="${e.search}"`),e.status!==void 0&&n.push(`status=${e.status}`),e.type!==void 0&&n.push(`type=${e.type}`),e.priority!==void 0&&n.push(`priority=${e.priority}`),e.assignee!==void 0&&n.push(`assignee=${e.assignee}`),e.label!==void 0&&n.push(`label=${e.label}`),e.overdue===!0&&n.push("overdue"),e.dueBefore!==void 0&&n.push(`due before ${e.dueBefore}`),n.length===0?`No tasks yet.
94
- Create the first one:
95
- kadence task add "title"`:`No tasks match ${n.join(" and ")}.
96
- Try fewer filters:
97
- kadence task list`}var q=["created","priority","due","estimate"];function ye(e){return q.includes(e)}import{execFileSync as Ye}from"node:child_process";function he(e,n){try{return Ye("git",n,{cwd:e,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return null}}function be(e){let n=he(e,["rev-parse","--show-toplevel"]);return n===null||n.length===0?null:n}function ve(e){let n=he(e,["config","user.email"]);return n===null||n.length===0?null:n}import{mkdirSync as Qe,readdirSync as et,readFileSync as tt,renameSync as nt,rmSync as nn,writeFileSync as rt}from"node:fs";import{join as _}from"node:path";var Ge=["task.created","task.moved","task.assigned","task.commented","task.updated","task.cancelled","task.reopened","task.deleted","task.parent_set","task.blocked_by_added","task.blocked_by_removed","task.time_logged","template.saved","template.deleted","board.configured","sprint.created","sprint.started","sprint.updated","sprint.closed","sprint.cancelled","sprint.task_added"],Ze=new Set(Ge),we=/^[0-9ABCDEFGHJKMNPQRSTVWXYZ]{26}$/,Ve=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?(Z|[+-]\d{2}:\d{2})$/;function qe(e){return typeof e=="string"&&Ze.has(e)}function ze(e){if(typeof e!="object"||e===null)return["event"];let n=e,r=[];return(typeof n.id!="string"||!we.test(n.id))&&r.push("id"),qe(n.type)||r.push("type"),(typeof n.entity!="string"||!we.test(n.entity))&&r.push("entity"),(typeof n.actor!="string"||n.actor.length===0)&&r.push("actor"),(typeof n.ts!="string"||!Ve.test(n.ts)||Number.isNaN(Date.parse(n.ts)))&&r.push("ts"),n.source!=="human"&&n.source!=="agent"&&r.push("source"),n.data!==void 0&&(typeof n.data!="object"||n.data===null)&&r.push("data"),r}function Se(e){let n=e.data?.description;if(typeof n!="string"||!n.includes(`
98
- `))return JSON.stringify(e);let r={...e,data:{...e.data,description:n.split(`
99
- `)}};return JSON.stringify(r,null,2)}function z(e){let n;try{n=JSON.parse(e)}catch(t){return{event:null,error:`unreadable JSON: ${t.message}`,unknownType:!1}}n=Xe(n);let r=ze(n);return r.length===1&&r[0]==="type"?{event:null,error:null,unknownType:!0}:r.length>0?{event:null,error:`invalid fields: ${r.join(", ")}`,unknownType:!1}:{event:n,error:null,unknownType:!1}}function Xe(e){if(typeof e!="object"||e===null)return e;let n=e,r=n.data;if(typeof r!="object"||r===null)return e;let t=r.description;return Array.isArray(t)?{...n,data:{...r,description:t.filter(s=>typeof s=="string").join(`
100
- `)}}:e}var st=.2;function F(e){return _(e,".kadence")}function J(e){return _(F(e),"events")}function ot(e){return _(J(e),"archive")}function it(e){return e.slice(0,7)}function T(e,n){let r=_(J(e),it(n.ts));Qe(r,{recursive:!0});let t=_(r,`${n.id}.json`),s=_(r,`.${n.id}.tmp`);rt(s,`${Se(n)}
101
- `,"utf8"),nt(s,t)}function M(e){let n=J(e),r=[],t=[],s=new Set,o=0,i=X(ot(e)),a=new Set(i);for(let u of X(n)){let c;try{c=tt(u,"utf8")}catch{t.push(u);continue}if(a.has(u)){let l;try{l=JSON.parse(c)}catch{t.push(u);continue}if(!Array.isArray(l)){t.push(u);continue}for(let p of l){let m=z(JSON.stringify(p));m.unknownType?o++:m.error!==null||m.event===null?t.push(u):s.has(m.event.id)||(s.add(m.event.id),r.push(m.event))}continue}let f=z(c);if(f.unknownType){o++;continue}if(f.error!==null||f.event===null){t.push(u);continue}s.has(f.event.id)||(s.add(f.event.id),r.push(f.event))}r.sort((u,c)=>u.id<c.id?-1:u.id>c.id?1:0);let d=r.length+t.length;return{events:r,corrupted:t,unknownTypes:o,systemicCorruption:d>0&&t.length/d>st}}function X(e){let n;try{n=et(e,{withFileTypes:!0})}catch{return[]}let r=[];for(let t of n){let s=_(e,t.name);t.isDirectory()?r.push(...X(s)):t.name.endsWith(".json")&&r.push(s)}return r}import{randomFillSync as at}from"node:crypto";var Te="0123456789ABCDEFGHJKMNPQRSTVWXYZ",dt=10,ut=16,xe=2**48-1;function lt(e){let n="",r=e;for(let t=dt-1;t>=0;t--)n=Te[r%32]+n,r=Math.floor(r/32);return n}function ct(e){let n="",r=0,t=0;for(let s of e){for(r=r<<8|s,t+=8;t>=5;)t-=5,n+=Te[r>>>t&31];r&=(1<<t)-1}return n.slice(0,ut)}function pt(e){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r<255){e[n]=r+1;return}e[n]=0}throw new Error("ULID: random space exhausted within a single millisecond")}function ft(){let e=-1,n=new Uint8Array(10);return function(t=Date.now()){if(!Number.isInteger(t)||t<0||t>xe)throw new RangeError(`ULID: time out of range 0..${xe}: ${t}`);return t>e?(e=t,at(n)):pt(n),lt(e)+ct(n)}}var x=ft();import{readFileSync as gt,writeFileSync as mt,renameSync as kt,readdirSync as yt,mkdirSync as ht}from"node:fs";import{join as Ce}from"node:path";var $e="kadence-snapshot/1";function Ee(e){return Ce(F(e),"state.json")}function De(e,n){let r=bt(J(e)),t=vt(e);if(t!==null&&t.version===$e&&t.lastEventId===r.lastEventId&&t.eventCount===r.count)return{state:t.state,fromCache:!0,incomingEvents:0};let s=M(e),o=le(s.events),i=t===null||n===void 0?0:St(s.events,t,n);return wt(e,{version:$e,lastEventId:r.lastEventId,eventCount:r.count,state:o}),{state:o,fromCache:!1,incomingEvents:i}}function bt(e){let n="",r=0,t=s=>{let o;try{o=yt(s,{withFileTypes:!0})}catch{return}for(let i of o)if(i.isDirectory())t(Ce(s,i.name));else if(i.name.endsWith(".json")){r++;let a=i.name.slice(0,-5);a>n&&(n=a)}};return t(e),{lastEventId:n,count:r}}function vt(e){try{let n=JSON.parse(gt(Ee(e),"utf8"));if(typeof n!="object"||n===null)return null;let r=n;return typeof r.version!="string"||typeof r.lastEventId!="string"||typeof r.eventCount!="number"||typeof r.state!="object"?null:r}catch{return null}}function wt(e,n){try{ht(F(e),{recursive:!0});let r=Ee(e),t=`${r}.tmp`;mt(t,JSON.stringify(n),"utf8"),kt(t,r)}catch{}}function St(e,n,r){let t=0,s=0;for(let i of e)i.id<=n.lastEventId?t++:i.actor!==r&&s++;let o=Math.max(0,t-n.eventCount);return s+o}var S={dim:"\x1B[2m",bold:"\x1B[1m",green:"\x1B[32m",yellow:"\x1B[33m",blue:"\x1B[34m",reset:"\x1B[0m"};function ee(e,n){return e.NO_COLOR!==void 0?!1:n}function D(e,n,r){return r?`${n}${e}${S.reset}`:e}var xt={done:S.green,in_progress:S.blue,blocked:S.yellow,cancelled:S.dim},Tt=72;function je(e,n=Tt){let r=[...e];return r.length<=n?e:`${r.slice(0,n-1).join("")}\u2026`}function Q(e){return[...e].length}function Re(e,n){let r=n-Q(e);return r>0?e+" ".repeat(r):e}function _e(e,n){if(e.length===0)return`No tasks yet.
102
- Create the first one:
103
- kadence task add "title"`;let r=Math.max(...e.map(s=>Q(s.label)),2),t=Math.max(...e.map(s=>Q(s.status)),6);return e.map(s=>{let o=D(Re(s.label,r),S.bold,n),i=D(Re(s.status,t),xt[s.status]??S.dim,n),a=s.estimate===null?"":D(` (${s.estimate})`,S.dim,n);return`${o} ${i} ${je(s.title)}${a}`}).join(`
104
- `)}function Ne(e){return e<=0?null:`Merged ${e} ${e===1?"change":"changes"} from another branch, no conflicts.`}var $t={urgent:"!!",high:"!",normal:"",low:"v"},Ct={bug:"BUG",story:"STORY",task:""};function Ae(e,n){let r=[D(e.label,S.bold,n)],t=$t[e.priority];t!==""&&r.push(D(t,e.priority==="low"?S.dim:S.yellow,n));let s=Ct[e.type]??"";s!==""&&r.push(D(s,S.dim,n)),r.push(je(e.title));let o=[];return e.assignee!==null&&o.push(`@${e.assignee.split("@")[0]}`),e.estimate!==null&&o.push(`${e.estimate}`),o.length>0&&r.push(D(`(${o.join(", ")})`,S.dim,n)),` ${r.join(" ")}`}function gn(e,n){if(Object.values(e).reduce((s,o)=>s+o.length,0)===0)return`No tasks yet.
105
- Create the first one:
106
- kadence task add "title"`;let t=[];for(let[s,o]of Object.entries(e)){if(o.length===0)continue;let i=o.reduce((d,u)=>d+(u.estimate??0),0),a=i>0?` \u2014 ${i}`:"";t.push(D(`${s} (${o.length}${a})`,S.bold,n),...o.map(d=>Ae(d,n)),"")}return t.join(`
107
- `).trimEnd()}function Et(e,n=new Date){let r=Date.parse(`${e}T00:00:00.000Z`),t=Date.parse(`${n.toISOString().slice(0,10)}T00:00:00.000Z`);if(Number.isNaN(r))return"";let s=Math.round((r-t)/864e5);return s<0?` (overdue by ${-s} day${s===-1?"":"s"})`:s===0?" (today)":s===1?" (tomorrow)":s<=7?` (in ${s} days)`:""}function Oe(e,n){if(e.length===0)return`No tasks yet.
108
- Create the first one:
109
- kadence task add "title"`;let r=new Set(e.map(a=>a.id)),t=new Map;for(let a of e){let d=a.parent!==null&&r.has(a.parent)?a.parent:null,u=t.get(d)??[];u.push(a),t.set(d,u)}let s=[],o=new Set,i=(a,d)=>{if(!(d>10))for(let u of t.get(a)??[]){if(o.has(u.id))continue;o.add(u.id);let c=" ".repeat(d),f=u.blockedBy.length>0?D(" [blocked]",S.yellow,n):"";s.push(`${c}${Ae(u,n).trimStart()}${f}`),i(u.id,d+1)}};return i(null,0),s.join(`
110
- `)}function Pe(e){let n=[`${e.label} ${e.title}`,""];if(e.description!==null&&n.push(e.description,""),n.push(` Status: ${e.status}`),n.push(` Type: ${e.type}`),n.push(` Priority: ${e.priority}`),e.labels.length>0&&n.push(` Labels: ${e.labels.join(", ")}`),e.parent!==null&&n.push(` Parent: ${e.parent}`),e.blockedBy.length>0&&n.push(` Blocked by: ${e.blockedBy.length} task(s)`),n.push(` Assignee: ${e.assignee??"\u2014"}`),n.push(` Reporter: ${e.reporter}`),e.due!==null&&n.push(` Due: ${e.due}${Et(e.due)}`),n.push(` Estimate: ${e.estimate??"\u2014"}`),e.comments.length>0){n.push("",` Comments (${e.comments.length}):`);for(let r of e.comments){n.push(` ${r.author} \xB7 ${r.ts.slice(0,10)}`);for(let t of r.text.split(`
111
- `))n.push(` ${t}`)}}if(e.history.length>0){n.push("",` History (${e.history.length}):`);for(let r of e.history){let t=r.type==="task.moved"?` \u2192 ${String(r.data.to)}`:"";n.push(` ${r.ts.slice(0,16).replace("T"," ")} ${r.actor} ${r.type}${t}`)}}return n.join(`
112
- `)}import{existsSync as Dt}from"node:fs";var $n=Y;function $(e,n,r,t={}){return{ok:!1,exitCode:e,message:r,error:{code:n,message:r,...t}}}function N(e){return $(1,"task_not_found",`No task ${e}.
113
- kadence task list`,{received:e,hint:"kadence task list --json"})}function L(e,n,r,t){return $(2,e,`Unknown ${n} "${r}".
114
- Available: ${t.join(", ")}`,{received:r,allowed:t})}function h(e,n){let r=be(e);if(r===null)return $(1,"not_a_repository",`kadence lives inside a git repository, and there is none here.
115
- Create one and try again:
116
- git init`,{hint:"git init"});if(!Dt(F(r)))return $(1,"not_initialised",`No .kadence/ found here.
117
- Run:
118
- npx kadence init`,{hint:"kadence init"});let t=ve(r);if(t===null)return $(1,"no_git_identity",`Git does not know who you are, so there is no author for the event.
119
- Run:
120
- git config user.email you@example.com`,{hint:"git config user.email you@example.com"});let s=n.KADENCE_SOURCE==="agent"?"agent":"human";return{root:r,actor:t,source:s}}function b(e){return"root"in e}function Cn(e,n,r,t={}){let s=h(e,n);if(!b(s))return s;let o=r.trim();if(o.length===0)return{ok:!1,exitCode:2,message:"A task needs a title."};if(t.type!==void 0&&!R.includes(t.type))return L("unknown_type","type",t.type,R);if(t.priority!==void 0&&!j.includes(t.priority))return L("unknown_priority","priority",t.priority,j);let i;if(t.parent!==void 0){let{state:c}=k(s.root,s.actor),f=C(c,t.parent);if(f===void 0)return{ok:!1,exitCode:1,message:`No parent task ${t.parent}.
121
- kadence task list`};i=f.id}let a=x(),d={id:a,type:"task.created",entity:a,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{title:o,...t.description!==void 0?{description:t.description}:{},...t.type!==void 0?{type:t.type}:{},...t.priority!==void 0?{priority:t.priority}:{},...t.assignee!==void 0?{assignee:t.assignee}:{},...t.labels!==void 0&&t.labels.length>0?{labels:t.labels}:{},...t.due!==void 0?{due:t.due}:{},...i!==void 0?{parent:i}:{},...t.estimate!==void 0?{estimate:t.estimate}:{}}};T(s.root,d);let u=t.estimate===void 0?`
122
- Without an estimate this task will not count towards velocity. Add --estimate.`:"";return{ok:!0,exitCode:0,message:`Created: ${o}${u}`,data:{schema:"kadence/v1",ok:!0,task:{id:a,title:o}}}}function k(e,n){let r=De(e,n),t=M(e),s=[],o=Ne(r.incomingEvents);return o!==null&&s.push(o),t.systemicCorruption?s.push(`The journal is badly damaged: ${t.corrupted.length} of ${t.corrupted.length+t.events.length} events are unreadable. Try: git checkout .kadence/`):t.corrupted.length>0&&s.push(`Skipped ${t.corrupted.length} corrupted event(s).`),t.unknownTypes>0&&s.push(`Skipped ${t.unknownTypes} event(s) from a newer format. Update kadence.`),{state:r.state,warnings:s}}function C(e,n){let r=n.toUpperCase();return e.tasks.find(t=>t.id===r||t.label===r)}function Ie(e,n){return $(2,"unknown_status",`Unknown status "${e}".
123
- Available: ${n.join(", ")}
124
- kadence board config --statuses "todo,doing,done"`,{received:e,allowed:n,hint:"kadence board statuses --json"})}function En(e,n,r){let t=h(e,n);if(!b(t))return t;if(r.type!==void 0&&!R.includes(r.type))return L("unknown_type","type",r.type,R);if(r.priority!==void 0&&!j.includes(r.priority))return L("unknown_priority","priority",r.priority,j);let{fields:s,error:o}=Rt(r.fields);if(o!==null)return o;if(r.sort!==void 0&&!ye(r.sort))return{ok:!1,exitCode:2,message:`Unknown sort key "${r.sort}".
125
- Available: ${q.join(", ")}`};let{state:i,warnings:a}=k(t.root,t.actor);if(r.status!==void 0&&!i.statuses.includes(r.status))return Ie(r.status,i.statuses);let{sort:d,tree:u,...c}=r,f=ge(i.tasks,c),l=d===void 0?f:me(f,d);return l.length===0?{ok:!0,exitCode:0,warnings:a,message:ke(c),data:{schema:"kadence/v1",ok:!0,tasks:[]}}:{ok:!0,exitCode:0,warnings:a,message:u===!0?Oe(l,ee(n,process.stdout.isTTY===!0)):_e(l,ee(n,process.stdout.isTTY===!0)),data:{schema:"kadence/v1",ok:!0,tasks:l.map(p=>Fe(p,s)),cycles:i.cycles}}}function Dn(e,n,r,t){let s=h(e,n);if(!b(s))return s;let{state:o,warnings:i}=k(s.root,s.actor);if(!o.statuses.includes(t))return Ie(t,o.statuses);let{tasks:a,error:d}=A(o,r);if(d!==null)return d;let u=[],c=[],f="";for(let p of a){if(p.status===t){c.push(p);continue}let m=p.status;T(s.root,{id:x(),type:"task.moved",entity:p.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{from:m,to:t}}),u.push(p),a.length===1&&o.statuses.indexOf(t)-o.statuses.indexOf(m)>1&&(f=`
126
- Moved straight from ${m} to ${t}, skipping the stages between.`)}if(u.length===0)return{ok:!0,exitCode:0,warnings:i,message:w("already there",c,`is already ${t}.`)};let l=c.length>0?`
127
- ${c.length} already ${t}.`:"";return{ok:!0,exitCode:0,warnings:i,message:`${w("moved",u,`${u[0].status} \u2192 ${t}`)}${f}${l}`,data:{schema:"kadence/v1",ok:!0,moved:u.map(p=>({id:p.id,label:p.label,to:t}))}}}function Rt(e){if(e===void 0)return{fields:null,error:null};let n=e.split(",").map(t=>t.trim()).filter(t=>t.length>0);if(n.length===0)return{fields:null,error:$(2,"invalid_argument","--fields needs at least one field name.",{allowed:I})};let r=n.find(t=>!I.includes(t));return r!==void 0?{fields:null,error:$(2,"unknown_field",`Unknown field "${r}".
128
- Available: ${I.join(", ")}`,{received:r,allowed:I})}:{fields:n,error:null}}function Fe(e,n=null){let r=jt(e);return n===null?r:Object.fromEntries(n.map(t=>[t,r[t]]))}function jt(e){return{id:e.id,label:e.label,title:e.title,description:e.description,type:e.type,priority:e.priority,status:e.status,labels:e.labels,assignee:e.assignee,reporter:e.reporter,sprint:e.sprint,loggedHours:e.loggedHours,parent:e.parent,blockedBy:e.blockedBy,due:e.due,comments:e.comments,estimate:e.estimate,history:e.history}}function Rn(e,n,r,t){let s=h(e,n);if(!b(s))return s;let{state:o,warnings:i}=k(s.root,s.actor),{tasks:a,error:d}=A(o,r);if(d!==null)return d;let u=t.trim().toLowerCase()==="none"?null:t.trim(),c=a.filter(f=>f.assignee!==u);if(c.length===0)return{ok:!0,exitCode:0,warnings:i,message:u===null?w("already unassigned",a,"is already unassigned."):w("already assigned",a,`is already assigned to ${u}.`)};for(let f of c)T(s.root,{id:x(),type:"task.assigned",entity:f.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{assignee:u}});return{ok:!0,exitCode:0,warnings:i,message:u===null?w("unassigned",c,"unassigned."):w("assigned",c,`\u2192 ${u}`),data:{schema:"kadence/v1",ok:!0,assigned:c.map(f=>({id:f.id,label:f.label,assignee:u}))}}}function jn(e,n,r){let t=h(e,n);if(!b(t))return t;let{state:s,warnings:o}=k(t.root,t.actor),i=C(s,r);return i===void 0?N(r):{ok:!0,exitCode:0,warnings:o,message:Pe(i),data:{schema:"kadence/v1",ok:!0,task:Fe(i)}}}function _n(e,n,r,t){let s=h(e,n);if(!b(s))return s;if(t.type!==void 0&&!R.includes(t.type))return L("unknown_type","type",t.type,R);if(t.priority!==void 0&&!j.includes(t.priority))return L("unknown_priority","priority",t.priority,j);if(t.due!==void 0&&t.due!==""&&!_t(t.due))return{ok:!1,exitCode:2,message:`Due date must be YYYY-MM-DD, got "${t.due}".
129
- kadence task edit KAD-1 --due 2026-09-30`};let{state:o,warnings:i}=k(s.root,s.actor),{tasks:a,error:d}=A(o,r);if(d!==null)return d;if(t.title!==void 0&&a.length>1)return{ok:!1,exitCode:2,message:"A title can only be set on one task at a time."};let u=[],c=new Set;for(let l of a){let p={},m=[];if(t.title!==void 0&&t.title!==l.title&&(p.title=t.title,m.push("title")),t.description!==void 0&&t.description!==(l.description??"")&&(p.description=t.description,m.push("description")),t.type!==void 0&&t.type!==l.type&&(p.type=t.type,m.push("type")),t.priority!==void 0&&t.priority!==l.priority&&(p.priority=t.priority,m.push("priority")),t.due!==void 0&&t.due!==(l.due??"")&&(p.due=t.due,m.push("due")),t.estimate!==void 0&&t.estimate!==l.estimate&&(p.estimate=t.estimate,m.push("estimate")),t.labels!==void 0&&t.labels.join(",")!==l.labels.join(",")&&(p.labels=t.labels,m.push("labels")),m.length!==0){T(s.root,{id:x(),type:"task.updated",entity:l.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:p}),u.push(l);for(let g of m)c.add(g)}}if(u.length===0)return{ok:!0,exitCode:0,warnings:i,message:w("unchanged",a,"nothing changed.")};let f=[...c].join(", ");return{ok:!0,exitCode:0,warnings:i,message:w("updated",u,`updated ${f}.`),data:{schema:"kadence/v1",ok:!0,updated:u.map(l=>({id:l.id,label:l.label})),changed:[...c]}}}function _t(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;let n=new Date(`${e}T00:00:00.000Z`);return!Number.isNaN(n.getTime())&&n.toISOString().slice(0,10)===e}function Nn(e,n,r){let t=h(e,n);if(!b(t))return t;let{state:s,warnings:o}=k(t.root,t.actor),{tasks:i,error:a}=A(s,r);if(a!==null)return a;let d=i.filter(u=>u.status!=="cancelled");if(d.length===0)return{ok:!0,exitCode:0,warnings:o,message:w("already cancelled",i,"is already cancelled.")};for(let u of d)T(t.root,{id:x(),type:"task.cancelled",entity:u.id,actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{}});return{ok:!0,exitCode:0,warnings:o,message:`${w("cancelled",d,"cancelled.")}
130
- Cancelled work stays in history and does not count as missed.`,data:{schema:"kadence/v1",ok:!0,cancelled:d.map(u=>({id:u.id,label:u.label}))}}}function An(e,n,r){let t=h(e,n);if(!b(t))return t;let{state:s,warnings:o}=k(t.root,t.actor),{tasks:i,error:a}=A(s,r);if(a!==null)return a;for(let u of i)T(t.root,{id:x(),type:"task.deleted",entity:u.id,actor:t.actor,ts:new Date().toISOString(),source:t.source,data:{title:u.title}});let d=i.length===1?`${i[0].label} deleted: "${i[0].title}".`:`${i.length} tasks deleted: ${i.map(u=>u.label).join(", ")}.`;return{ok:!0,exitCode:0,warnings:o,message:`${d}
131
- The events stay in the journal \u2014 history is never rewritten.`,data:{schema:"kadence/v1",ok:!0,deleted:i.map(u=>({id:u.id,label:u.label}))}}}function On(e,n,r,t){let s=h(e,n);if(!b(s))return s;let o=t.trim();if(o.length===0)return{ok:!1,exitCode:2,message:"A comment needs text."};let{state:i,warnings:a}=k(s.root,s.actor),d=C(i,r);return d===void 0?N(r):(T(s.root,{id:x(),type:"task.commented",entity:d.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{text:o}}),{ok:!0,exitCode:0,warnings:a,message:`Comment added to ${d.label}.`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label}}})}function A(e,n){let r=n.split(",").map(i=>i.trim()).filter(i=>i.length>0);if(r.length===0)return{tasks:[],error:$(2,"invalid_argument","No task given.")};let t=[],s=[];for(let i of r){let a=C(e,i);a===void 0?s.push(i):t.push(a)}return s.length>0?{tasks:[],error:$(1,"task_not_found",`No task ${s.join(", ")} \u2014 nothing was changed.
132
- All ids must exist before a bulk change runs.
133
- kadence task list`,{received:s.join(","),hint:"kadence task list --json"})}:{tasks:[...new Map(t.map(i=>[i.id,i])).values()],error:null}}function w(e,n,r){return n.length===1?`${n[0].label}: ${r}`:`${n.length} tasks ${e}: ${n.map(t=>t.label).join(", ")}`}function Pn(e,n,r,t){let s=h(e,n);if(!b(s))return s;let{state:o,warnings:i}=k(s.root,s.actor),{tasks:a,error:d}=A(o,r);if(d!==null)return d;let u=t.trim().toLowerCase()==="none",c=null;if(!u){let p=C(o,t);if(p===void 0)return N(t);if(a.some(m=>m.id===p.id))return{ok:!1,exitCode:2,message:"A task cannot be its own parent."};c=p.id}let f=a.filter(p=>p.parent!==c);if(f.length===0)return{ok:!0,exitCode:0,warnings:i,message:w("unchanged",a,"already there.")};for(let p of f)T(s.root,{id:x(),type:"task.parent_set",entity:p.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{parent:c}});let l=u?"detached":C(o,t).label;return{ok:!0,exitCode:0,warnings:[...i,...Me(s.root,s.actor)],message:u?w("detached",f,"detached from its parent."):w("moved",f,`\u2192 child of ${l}`),data:{schema:"kadence/v1",ok:!0,parent:c}}}function In(e,n,r,t,s){let o=h(e,n);if(!b(o))return o;let{state:i,warnings:a}=k(o.root,o.actor),{tasks:d,error:u}=A(i,r);if(u!==null)return u;let c=C(i,t);if(c===void 0)return N(t);if(d.some(l=>l.id===c.id))return{ok:!1,exitCode:2,message:"A task cannot block itself."};let f=d.filter(l=>s?l.blockedBy.includes(c.id):!l.blockedBy.includes(c.id));if(f.length===0)return{ok:!0,exitCode:0,warnings:a,message:w("unchanged",d,s?"was not blocked by it.":"is already blocked by it.")};for(let l of f)T(o.root,{id:x(),type:s?"task.blocked_by_removed":"task.blocked_by_added",entity:l.id,actor:o.actor,ts:new Date().toISOString(),source:o.source,data:{blocker:c.id}});return{ok:!0,exitCode:0,warnings:[...a,...Me(o.root,o.actor)],message:s?w("unblocked",f,`no longer blocked by ${c.label}.`):w("blocked",f,`blocked by ${c.label}.`),data:{schema:"kadence/v1",ok:!0,blocker:c.id}}}function Me(e,n){let{state:r}=k(e,n),t=new Map(r.tasks.map(s=>[s.id,s.label]));return r.cycles.map(s=>{let o=s.path.map(i=>t.get(i)??i).join(" \u2192 ");return`Dependency cycle (${s.kind}): ${o}. Both edges were kept \u2014 resolve it when you can.`})}function Nt(e){let n=/^(-?\d+(?:\.\d+)?)\s*(h|hours?|m|min|minutes?)?$/i.exec(e.trim());if(n===null)return null;let r=Number(n[1]);return!Number.isFinite(r)||r===0?null:(n[2]??"h").toLowerCase().startsWith("m")?r/60:r}function Fn(e,n,r,t){let s=h(e,n);if(!b(s))return s;let o=Nt(t);if(o===null)return{ok:!1,exitCode:2,message:`Cannot read "${t}" as a duration.
134
- Use hours or minutes:
135
- kadence task log KAD-1 2h
136
- kadence task log KAD-1 90m
137
- kadence task log KAD-1 -30m to correct a mistake`};let{state:i,warnings:a}=k(s.root,s.actor),d=C(i,r);if(d===void 0)return N(r);T(s.root,{id:x(),type:"task.time_logged",entity:d.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{hours:o}});let u=Math.max(0,d.loggedHours+o),c=d.estimate===null?`
138
- No estimate on this task, so there is nothing to compare against.`:"";return{ok:!0,exitCode:0,warnings:a,message:`${d.label}: ${u.toFixed(1)}h logged in total.${c}`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label,loggedHours:u}}}}import{spawnSync as At}from"node:child_process";import{mkdtempSync as Ot,readFileSync as Pt,rmSync as It,writeFileSync as Ft}from"node:fs";import{tmpdir as Mt}from"node:os";import{join as Le}from"node:path";var U="#";function Lt(e){return e.GIT_EDITOR??e.VISUAL??e.EDITOR??"vi"}function Un(e,n,r){let t=Ot(Le(Mt(),"kadence-edit-")),s=Le(t,"KADENCE_EDITMSG.md"),o=["",`${U} ${r}`,`${U} Lines starting with '${U}' are ignored.`,`${U} Save an empty file to abort.`].join(`
139
- `);try{Ft(s,`${n}${o}
140
- `,"utf8");let i=Lt(e),a=At(i,[s],{stdio:"inherit",shell:!0});if(a.error!==void 0||a.status!==null&&a.status!==0)return{text:null,error:`Editor "${i}" exited without saving.
141
- Set one explicitly:
142
- export EDITOR=nano`};let u=Pt(s,"utf8").split(`
143
- `).filter(c=>!c.startsWith(U)).join(`
144
- `).trim();return{text:u.length===0?null:u,error:null}}catch(i){return{text:null,error:`Could not open an editor: ${i.message}`}}finally{It(t,{recursive:!0,force:!0})}}function Hn(e,n){return e.KADENCE_SOURCE==="agent"?!1:n}function te(e,n){let r=e.sprints.find(g=>g.id===n);if(r===void 0)return null;let t=e.tasks.filter(g=>g.sprint===n),s=t.filter(g=>g.status==="cancelled"),o=t.filter(g=>g.status!=="cancelled"),i=o.filter(g=>g.status==="done"),a=o.filter(g=>g.status!=="done"),d=H(o.map(g=>g.estimate??0)),u=H(i.map(g=>g.estimate??0)),c=i.filter(g=>g.estimate===null),f=i.map(Bt).filter(g=>g!==null),l=f.length>0?H(f):null,p=H(i.filter(g=>g.estimate!==null).map(g=>g.estimate)),m=l!==null&&p>0?l/p:null;return{id:r.id,name:r.name,status:r.status,committed:d,velocity:u,actualHours:l,hoursPerPoint:m,done:i,carriedOver:a,cancelled:s,unestimated:c,loggedHours:H(t.map(g=>g.loggedHours))}}function Bt(e){let n=e.history.find(s=>s.type==="task.moved"&&s.data.to==="in_progress"),r=[...e.history].reverse().find(s=>s.type==="task.moved"&&s.data.to==="done");if(n===void 0||r===void 0)return null;let t=Date.parse(r.ts)-Date.parse(n.ts);return t>0?t/36e5:null}function H(e){return e.reduce((n,r)=>n+r,0)}function W(e){return new Date(e).toISOString().slice(0,10)}function Kt(e,n){let r=[];for(let t=Date.parse(`${e}T00:00:00.000Z`);t<=Date.parse(`${n}T00:00:00.000Z`);t+=864e5)r.push(W(t));return r}function Be(e,n,r,t=W(Date.now())){let s=e.tasks.filter(y=>y.sprint===r.id&&y.status!=="cancelled"),o=new Map(s.map(y=>[y.id,y.estimate??0])),i=[...o.values()].reduce((y,E)=>y+E,0),a=n.filter(y=>o.has(y.entity));if(a.length===0)return null;let d=r.startDate??W(a[0].ts),u=r.endDate??W(a.at(-1).ts),c=r.status==="closed"||u<t?u:t;if(c<d)return null;let f=new Set,l=new Map;for(let y of a){let E=W(y.ts);if(E<d)continue;let P=y.type==="task.moved"?y.data?.to:void 0,re=o.get(y.entity)??0;P==="done"&&!f.has(y.entity)?(f.add(y.entity),l.set(E,(l.get(E)??0)+re)):P!==void 0&&P!=="done"&&f.has(y.entity)&&(f.delete(y.entity),l.set(E,(l.get(E)??0)-re))}let p=Kt(d,c),m=Math.max(p.length-1,1),g=i;return{sprintName:r.name,committed:i,finalRemaining:(r.status==="closed",null),days:p.map((y,E)=>{let P=l.get(y)??0;return g-=P,{date:y,remaining:Math.max(0,g),ideal:Math.max(0,i-i/m*E),completed:P}})}}function Ke(e,n=40){if(e.committed===0)return`"${e.sprintName}": nothing to burn down \u2014 no estimated tasks.`;let r=[`"${e.sprintName}" \u2014 ${e.committed} points committed`,""];for(let s of e.days){let o=Math.round(s.remaining/e.committed*n),i=Math.round(s.ideal/e.committed*n),a=[];for(let c=0;c<n;c++)c===i&&c>=o?a.push("\u250A"):c<o?a.push(c===i?"\u2503":"\u2588"):a.push(" ");let d=s.remaining-s.ideal,u=Math.abs(d)<.5?"":d>0?` +${d.toFixed(0)}`:` ${d.toFixed(0)}`;r.push(`${s.date.slice(5)} ${a.join("")} ${String(s.remaining).padStart(3)}${u}`)}let t=e.days.at(-1);return t!==void 0&&(r.push(""),r.push(t.remaining===0?" All committed work is done.":` ${t.remaining} of ${e.committed} points remain.`+(t.remaining>t.ideal?" Behind the ideal line.":" On or ahead of the line."))),r.join(`
145
- `)}function O(e){return e.sprints.find(n=>n.status==="active")}function Jt(e){return e.sprints.filter(n=>n.status==="planned")}function B(e,n){let r=n.trim().toLowerCase();return e.sprints.find(t=>t.name.toLowerCase()===r)}function K(e,n,r,t){T(e.root,{id:x(),type:n,entity:r,actor:e.actor,ts:new Date().toISOString(),source:e.source,data:t})}function er(e,n,r){let t=h(e,n);if(!b(t))return t;let s=r.trim();if(s.length===0)return{ok:!1,exitCode:2,message:"A sprint needs a name."};let{state:o,warnings:i}=k(t.root,t.actor);if(B(o,s)!==void 0)return{ok:!1,exitCode:2,message:`Sprint "${s}" already exists.`};let a=O(o)!==void 0,d=x();return K(t,"sprint.created",d,{name:s}),a||K(t,"sprint.started",d,{}),{ok:!0,exitCode:0,warnings:i,message:a?`Sprint "${s}" planned.
146
-
147
- kadence sprint add KAD-1 --sprint "${s}"
148
- kadence sprint start "${s}"`:`Sprint "${s}" started.
149
-
150
- kadence sprint add KAD-1
151
- kadence sprint status`,data:{schema:"kadence/v1",ok:!0,sprint:{id:d,name:s,status:a?"planned":"active"}}}}function tr(e,n,r,t={}){let s=h(e,n);if(!b(s))return s;let{state:o,warnings:i}=k(s.root,s.actor),a=t.sprint===void 0?O(o):B(o,t.sprint);if(a===void 0)return t.sprint===void 0?{ok:!1,exitCode:1,message:`No active sprint.
152
- kadence sprint create "Sprint 1"`}:{ok:!1,exitCode:1,message:`No sprint named "${t.sprint}".
153
- kadence sprint list`};if(a.status==="closed")return{ok:!1,exitCode:1,message:`Sprint "${a.name}" is closed \u2014 its velocity is not rewritten.`};let d=C(o,r);if(d===void 0)return N(r);if(d.sprint===a.id)return{ok:!0,exitCode:0,warnings:i,message:`${d.label} is already in the sprint.`};K(s,"sprint.task_added",a.id,{task:d.id});let u=d.estimate===null?`
154
- Without an estimate this task will not count towards velocity.`:"";return{ok:!0,exitCode:0,warnings:i,message:`${d.label} \u2192 "${a.name}"${u}`,data:{schema:"kadence/v1",ok:!0,task:{id:d.id,label:d.label},sprint:a.id}}}function nr(e,n){let r=h(e,n);if(!b(r))return r;let{state:t,warnings:s}=k(r.root,r.actor),o=O(t);if(o===void 0)return{ok:!1,exitCode:1,message:`No active sprint.
155
- kadence sprint create "Sprint 1"`};let i=te(t,o.id);K(r,"sprint.closed",o.id,{velocity:i.velocity});let a=[...s];return i.unestimated.length>0&&a.push(`${i.unestimated.length} completed task(s) without an estimate were left out of velocity: `+i.unestimated.map(d=>d.label).join(", ")),{ok:!0,exitCode:0,warnings:a,message:Ut(i),data:{schema:"kadence/v1",ok:!0,report:Je(i)}}}function rr(e,n){let r=h(e,n);if(!b(r))return r;let{state:t,warnings:s}=k(r.root,r.actor),o=O(t);if(o===void 0)return{ok:!0,exitCode:0,warnings:s,message:`No active sprint.
156
- kadence sprint create "Sprint 1"`,data:{schema:"kadence/v1",ok:!0,sprint:null}};let i=te(t,o.id),a=[`"${i.name}" \u2014 ${i.velocity} of ${i.committed} points`,"",...i.done.map(d=>` \u2713 ${d.label} ${d.title}`),...i.carriedOver.map(d=>` \xB7 ${d.label} ${d.title} (${d.status})`)];return{ok:!0,exitCode:0,warnings:s,message:a.join(`
157
- `),data:{schema:"kadence/v1",ok:!0,report:Je(i)}}}function Ut(e){let n=[`Sprint "${e.name}" closed.`,""];if(n.push(` Velocity: ${e.velocity} of ${e.committed} points`),e.hoursPerPoint!==null&&e.actualHours!==null&&e.actualHours>=1/60&&n.push(` Actual: ${ne(e.actualHours)} \u2014 ${ne(e.hoursPerPoint)} per point`),e.loggedHours>0&&n.push(` Logged: ${ne(e.loggedHours)} entered by hand`),e.carriedOver.length>0){n.push("",` Carried over (${e.carriedOver.length}):`);for(let r of e.carriedOver)n.push(` \xB7 ${r.label} ${r.title}`)}return e.cancelled.length>0&&n.push("",` Cancelled (${e.cancelled.length}) \u2014 not counted towards velocity`),n.join(`
158
- `)}function ne(e){return e<1?`${Math.round(e*60)}m`:e<10?`${e.toFixed(1)}h`:`${Math.round(e)}h`}function Je(e){return{id:e.id,name:e.name,status:e.status,velocity:e.velocity,committed:e.committed,actualHours:e.actualHours,hoursPerPoint:e.hoursPerPoint,done:e.done.map(n=>n.label),carriedOver:e.carriedOver.map(n=>n.label),cancelled:e.cancelled.map(n=>n.label),unestimated:e.unestimated.map(n=>n.label),loggedHours:e.loggedHours}}function sr(e,n,r){let t=h(e,n);if(!b(t))return t;let{state:s,warnings:o}=k(t.root,t.actor),i=O(s);if(i!==void 0)return{ok:!1,exitCode:1,message:`Sprint "${i.name}" is still active.
159
- Close it so velocity can be computed:
160
- kadence sprint close`};let a=Jt(s),d=r===void 0?a[0]:B(s,r);return d===void 0?{ok:!1,exitCode:1,message:r===void 0?`No planned sprints.
161
- kadence sprint create "Sprint 2"`:`No sprint named "${r}".
162
- kadence sprint list`}:d.status!=="planned"?{ok:!1,exitCode:1,message:`Sprint "${d.name}" is already ${d.status}.`}:(K(t,"sprint.started",d.id,{}),{ok:!0,exitCode:0,warnings:o,message:`Sprint "${d.name}" started.
163
-
164
- kadence sprint status`,data:{schema:"kadence/v1",ok:!0,sprint:{id:d.id,name:d.name}}})}function or(e,n){let r=h(e,n);if(!b(r))return r;let{state:t,warnings:s}=k(r.root,r.actor);if(t.sprints.length===0)return{ok:!0,exitCode:0,warnings:s,message:`No sprints yet.
165
- kadence sprint create "Sprint 1"`,data:{schema:"kadence/v1",ok:!0,sprints:[]}};let o=t.sprints.map(i=>{let a=t.tasks.filter(u=>u.sprint===i.id),d=a.reduce((u,c)=>u+(c.estimate??0),0);return{sprint:i,tasks:a,points:d}});return{ok:!0,exitCode:0,warnings:s,message:o.map(({sprint:i,tasks:a,points:d})=>{let u=i.status==="active"?"\u2192":" ",c=a.length===0?"":` ${a.length} tasks, ${d} points`;return`${u} ${i.name.padEnd(20)} ${i.status.padEnd(8)}${c}`}).join(`
166
- `),data:{schema:"kadence/v1",ok:!0,sprints:o.map(({sprint:i,tasks:a,points:d})=>({id:i.id,name:i.name,status:i.status,taskIds:i.taskIds,taskCount:a.length,points:d}))}}}function Ht(e){if(!/^\d{4}-\d{2}-\d{2}$/.test(e))return!1;let n=new Date(`${e}T00:00:00.000Z`);return!Number.isNaN(n.getTime())&&n.toISOString().slice(0,10)===e}function ir(e,n,r,t){let s=h(e,n);if(!b(s))return s;for(let[l,p]of[["--start",t.startDate],["--end",t.endDate]])if(p!==void 0&&p!==""&&!Ht(p))return{ok:!1,exitCode:2,message:`${l} must be YYYY-MM-DD, got "${p}".
167
- kadence sprint edit --start 2026-09-01`};let{state:o,warnings:i}=k(s.root,s.actor),a=r===void 0?O(o):B(o,r);if(a===void 0)return{ok:!1,exitCode:1,message:r===void 0?`No active sprint.
168
- kadence sprint list`:`No sprint named "${r}".
169
- kadence sprint list`};if(a.status==="closed")return{ok:!1,exitCode:1,message:`Sprint "${a.name}" is closed \u2014 its record is not rewritten.`};if(t.name!==void 0&&t.name!==a.name&&B(o,t.name)!==void 0)return{ok:!1,exitCode:2,message:`Sprint "${t.name}" already exists.`};let d=t.startDate??a.startDate??"",u=t.endDate??a.endDate??"";if(d!==""&&u!==""&&u<d)return{ok:!1,exitCode:2,message:`The end date (${u}) is before the start date (${d}).`};let c={},f=[];return t.name!==void 0&&t.name!==a.name&&(c.name=t.name,f.push("name")),t.description!==void 0&&t.description!==(a.description??"")&&(c.description=t.description,f.push("description")),t.startDate!==void 0&&t.startDate!==(a.startDate??"")&&(c.startDate=t.startDate,f.push("start")),t.endDate!==void 0&&t.endDate!==(a.endDate??"")&&(c.endDate=t.endDate,f.push("end")),f.length===0?{ok:!0,exitCode:0,warnings:i,message:`"${a.name}": nothing changed.`}:(K(s,"sprint.updated",a.id,c),{ok:!0,exitCode:0,warnings:i,message:`"${a.name}": updated ${f.join(", ")}.`,data:{schema:"kadence/v1",ok:!0,sprint:{id:a.id,changed:f}}})}function ar(e,n,r){let t=h(e,n);if(!b(t))return t;let{state:s,warnings:o}=k(t.root,t.actor),i=r===void 0?O(s):B(s,r);if(i===void 0)return{ok:!1,exitCode:1,message:r===void 0?`No active sprint.
170
- kadence sprint list`:`No sprint named "${r}".
171
- kadence sprint list`};let a=Be(s,M(t.root).events,i);return a===null?{ok:!0,exitCode:0,warnings:o,message:`"${i.name}" has no tasks yet.
172
- kadence sprint add KAD-1`,data:{schema:"kadence/v1",ok:!0,burndown:null}}:{ok:!0,exitCode:0,warnings:o,message:Ke(a),data:{schema:"kadence/v1",ok:!0,burndown:a}}}export{be as a,F as b,J as c,T as d,Wt as e,Yt as f,Gt as g,x as h,Vt as i,He as j,R as k,j as l,ee as m,gn as n,q as o,$n as p,h as q,b as r,Cn as s,k as t,En as u,Dn as v,Rt as w,Fe as x,Rn as y,jn as z,_n as A,Nn as B,An as C,On as D,Pn as E,In as F,Fn as G,Un as H,Hn as I,er as J,tr as K,nr as L,rr as M,sr as N,or as O,ir as P,ar as Q};