kadence 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +111 -11
- package/README.md +16 -11
- package/dist/chunks/chunk-MOXGQLKI.js +251 -0
- package/dist/chunks/{ui-OTWFK76P.js → ui-O7JSS6KE.js} +1 -1
- package/dist/cli.js +142 -129
- package/package.json +1 -1
- package/dist/chunks/chunk-J7QEHKDW.js +0 -248
package/dist/cli.js
CHANGED
|
@@ -1,41 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{$ as
|
|
2
|
+
import{$ as Gt,A,B,C as jt,D as Dt,E as Tt,F as Rt,G as Et,H as Fe,I as Ot,J as Nt,K as Mt,L as _t,M as Pt,N as It,O as Lt,P as Wt,Q as Bt,R as Kt,S as Ft,T as Ut,U as Ht,V as Ue,W as ne,X as zt,Y as Yt,Z as Jt,_ as qt,a as lt,aa as Vt,ba as Zt,ca as Qt,da as Xt,e as ct,ea as en,f as Be,fa as tn,g as M,ga as nn,h as ut,ha as sn,i as mt,ia as on,j as ft,k as pt,l as ht,m as gt,n as E,o as z,p as Y,q as ve,r as yt,s as $t,t as Ke,u as b,v as W,w as C,x as Se,y as j,z as Ct}from"./chunks/chunk-MOXGQLKI.js";import{b as I,c as L,d as kt,e as bt,g as wt,h as ce,j as vt,k as xt,o as ue,p as te,q as xe,r as St,s as At}from"./chunks/chunk-CR5YON2J.js";function He(e){return e==null?[]:Array.isArray(e)?e:[e]}function Ws(e,n,t,o){var s,r=e[n],i=~o.string.indexOf(n)?t==null||t===!0?"":String(t):typeof t=="boolean"?t:~o.boolean.indexOf(n)?t==="false"?!1:t==="true"||(e._.push((s=+t,s*0===0?s:t)),!!t):(s=+t,s*0===0?s:t);e[n]=r==null?i:Array.isArray(r)?r.concat(i):[r,i]}function Bs(e,n){e=e||[],n=n||{};var t,o,s,r,i,a={_:[]},d=0,l=0,c=0,u=e.length;let m=n.alias!==void 0,g=n.unknown!==void 0,f=n.default!==void 0;if(n.alias=n.alias||{},n.string=He(n.string),n.boolean=He(n.boolean),m)for(t in n.alias)for(o=n.alias[t]=He(n.alias[t]),d=0;d<o.length;d++)(n.alias[o[d]]=o.concat(t)).splice(d,1);for(d=n.boolean.length;d-- >0;)for(o=n.alias[n.boolean[d]]||[],l=o.length;l-- >0;)n.boolean.push(o[l]);for(d=n.string.length;d-- >0;)for(o=n.alias[n.string[d]]||[],l=o.length;l-- >0;)n.string.push(o[l]);if(f){for(t in n.default)if(r=typeof n.default[t],o=n.alias[t]=n.alias[t]||[],n[r]!==void 0)for(n[r].push(t),d=0;d<o.length;d++)n[r].push(o[d])}let S=g?Object.keys(n.alias):[];for(d=0;d<u;d++){if(s=e[d],s==="--"){a._=a._.concat(e.slice(++d));break}for(l=0;l<s.length&&s.charCodeAt(l)===45;l++);if(l===0)a._.push(s);else if(s.substring(l,l+3)==="no-"){if(r=s.substring(l+3),g&&!~S.indexOf(r))return n.unknown(s);a[r]=!1}else{for(c=l+1;c<s.length&&s.charCodeAt(c)!==61;c++);for(r=s.substring(l,c),i=s.substring(++c)||d+1===u||(""+e[d+1]).charCodeAt(0)===45||e[++d],o=l===2?[r]:r,c=0;c<o.length;c++){if(r=o[c],g&&!~S.indexOf(r))return n.unknown("-".repeat(l)+r);Ws(a,r,c+1<o.length||i,n)}}}if(f)for(t in n.default)a[t]===void 0&&(a[t]=n.default[t]);if(m)for(t in a)for(o=n.alias[t]||[];o.length>0;)a[o.shift()]=a[t];return a}function dn(e){return e.replace(/[<[].+/,"").trim()}function Ks(e){let n=/<([^>]+)>/g,t=/\[([^\]]+)\]/g,o=[],s=a=>{let d=!1,l=a[1];return l.startsWith("...")&&(l=l.slice(3),d=!0),{required:a[0].startsWith("<"),value:l,variadic:d}},r;for(;r=n.exec(e);)o.push(s(r));let i;for(;i=t.exec(e);)o.push(s(i));return o}function Fs(e){let n={alias:{},boolean:[]};for(let[t,o]of e.entries())o.names.length>1&&(n.alias[o.names[0]]=o.names.slice(1)),o.isBoolean&&(o.negated&&e.some((s,r)=>r!==t&&s.names.some(i=>o.names.includes(i))&&typeof s.required=="boolean")||n.boolean.push(o.names[0]));return n}function rn(e){return e.sort((n,t)=>n.length>t.length?-1:1)[0]}function an(e,n){return e.length>=n?e:`${e}${" ".repeat(n-e.length)}`}function Us(e){return e.replaceAll(/([a-z])-([a-z])/g,(n,t,o)=>t+o.toUpperCase())}function Hs(e,n,t){let o=e;for(let s=0;s<n.length;s++){let r=n[s];if(s===n.length-1){o[r]=t;return}if(o[r]==null){let i=+n[s+1]>-1;o[r]=i?[]:{}}o=o[r]}}function zs(e,n){for(let t of Object.keys(n)){let o=n[t];o.shouldTransform&&(e[t]=[e[t]].flat(),typeof o.transformFunction=="function"&&(e[t]=e[t].map(o.transformFunction)))}}function Ys(e){let n=/([^\\/]+)$/.exec(e);return n?n[1]:""}function ln(e){return e.split(".").map((n,t)=>t===0?Us(n):n).join(".")}var Ae=class extends Error{constructor(e){super(e),this.name="CACError",typeof Error.captureStackTrace!="function"&&(this.stack=new Error(e).stack)}},Js=class{rawName;description;name;names;isBoolean;required;config;negated;constructor(e,n,t){this.rawName=e,this.description=n,this.config=Object.assign({},t),e=e.replaceAll(".*",""),this.negated=!1,this.names=dn(e).split(",").map(o=>{let s=o.trim().replace(/^-{1,2}/,"");return s.startsWith("no-")&&(this.negated=!0,s=s.replace(/^no-/,"")),ln(s)}).sort((o,s)=>o.length>s.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}},ze,Ce;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",Ce=`${process.platform}-${process.arch} ${e}-${process.version}`,ze=process.argv}else typeof navigator>"u"?Ce="unknown":Ce=`${navigator.platform} ${navigator.userAgent}`;var cn=class{rawName;description;config;cli;options;aliasNames;name;args;commandAction;usageText;versionNumber;examples;helpCallback;globalCommand;constructor(e,n,t={},o){this.rawName=e,this.description=n,this.config=t,this.cli=o,this.options=[],this.aliasNames=[],this.name=dn(e),this.args=Ks(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,n="-v, --version"){return this.versionNumber=e,this.option(n,"Display version number"),this}example(e){return this.examples.push(e),this}option(e,n,t){let o=new Js(e,n,t);return this.options.push(o),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 un}hasOption(e){return e=e.split(".")[0],this.options.find(n=>n.names.includes(e))}outputHelp(){let{name:e,commands:n}=this.cli,{versionNumber:t,options:o,helpCallback:s}=this.cli.globalCommand,r=[{body:`${e}${t?`/${t}`:""}`}];if(r.push({title:"Usage",body:` $ ${e} ${this.usageText||this.rawName}`}),(this.isGlobalCommand||this.isDefaultCommand)&&n.length>0){let a=rn(n.map(d=>d.rawName));r.push({title:"Commands",body:n.map(d=>` ${an(d.rawName,a.length)} ${d.description}`).join(`
|
|
3
3
|
`)},{title:"For more info, run any command with the `--help` flag",body:n.map(d=>` $ ${e}${d.name===""?"":` ${d.name}`} --help`).join(`
|
|
4
|
-
`)})}let i=this.isGlobalCommand?o:[...this.options,...o||[]];if(!this.isGlobalCommand&&!this.isDefaultCommand&&(i=i.filter(a=>a.name!=="version")),i.length>0){let a=
|
|
4
|
+
`)})}let i=this.isGlobalCommand?o:[...this.options,...o||[]];if(!this.isGlobalCommand&&!this.isDefaultCommand&&(i=i.filter(a=>a.name!=="version")),i.length>0){let a=rn(i.map(d=>d.rawName));r.push({title:"Options",body:i.map(d=>` ${an(d.rawName,a.length)} ${d.description} ${d.config.default===void 0?"":`(default: ${d.config.default})`}`).join(`
|
|
5
5
|
`)})}this.examples.length>0&&r.push({title:"Examples",body:this.examples.map(a=>typeof a=="function"?a(e):a).join(`
|
|
6
6
|
`)}),s&&(r=s(r)||r),console.info(r.map(a=>a.title?`${a.title}:
|
|
7
7
|
${a.body}`:a.body).join(`
|
|
8
8
|
|
|
9
|
-
`))}outputVersion(){let{name:e}=this.cli,{versionNumber:n}=this.cli.globalCommand;n&&console.info(`${e}/${n} ${
|
|
9
|
+
`))}outputVersion(){let{name:e}=this.cli,{versionNumber:n}=this.cli.globalCommand;n&&console.info(`${e}/${n} ${Ce}`)}checkRequiredArgs(){let e=this.args.filter(n=>n.required).length;if(this.cli.args.length<e)throw new Ae(`missing required args for command \`${this.rawName}\``)}checkUnknownOptions(){let{options:e,globalCommand:n}=this.cli;if(!this.config.allowUnknownOptions){for(let t of Object.keys(e))if(t!=="--"&&!this.hasOption(t)&&!n.hasOption(t))throw new Ae(`Unknown option \`${t.length>1?`--${t}`:`-${t}`}\``)}}checkOptionValue(){let{options:e,globalCommand:n}=this.cli,t=[...n.options,...this.options];for(let o of t){let s=e[o.name.split(".")[0]];if(o.required){let r=t.some(i=>i.negated&&i.names.includes(o.name));if(s===!0||s===!1&&!r)throw new Ae(`option \`${o.rawName}\` value is missing`)}}}checkUnusedArgs(){let e=this.args.some(n=>n.variadic)?1/0:this.args.length;if(e<this.cli.args.length)throw new Ae(`Unused args: ${this.cli.args.slice(e).map(n=>`\`${n}\``).join(", ")}`)}},un=class extends cn{constructor(e){super("@@global@@","",{},e)}},qs=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 un(this),this.globalCommand.usage("<command> [options]")}usage(e){return this.globalCommand.usage(e),this}command(e,n,t){let o=new cn(e,n||"",t,this);return o.globalCommand=this.globalCommand,this.commands.push(o),o}option(e,n,t){return this.globalCommand.option(e,n,t),this}help(e){return this.globalCommand.option("-h, --help","Display this message"),this.globalCommand.helpCallback=e,this.showHelpOnExit=!0,this}version(e,n="-v, --version"){return this.globalCommand.version(e,n),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:n},t,o){return this.args=e,this.options=n,t&&(this.matchedCommand=t),o&&(this.matchedCommandName=o),this}unsetMatchedCommand(){this.matchedCommand=void 0,this.matchedCommandName=void 0}parse(e,{run:n=!0}={}){if(!e){if(!ze)throw new Error("No argv provided and runtime process argv is not available.");e=ze}this.rawArgs=e,this.name||(this.name=e[1]?Ys(e[1]):"cli");let t=!0;for(let s of this.commands){let r=this.mri(e.slice(2),s),i=r.args[0];if(s.isMatched(i)){t=!1;let a={...r,args:r.args.slice(1)};this.setParsedInfo(a,s,i),this.dispatchEvent(new CustomEvent(`command:${i}`,{detail:s}))}}if(t){for(let s of this.commands)if(s.isDefaultCommand){t=!1;let r=this.mri(e.slice(2),s);this.setParsedInfo(r,s),this.dispatchEvent(new CustomEvent("command:!",{detail:s}))}}if(t){let s=this.mri(e.slice(2));this.setParsedInfo(s)}this.options.help&&this.showHelpOnExit&&(this.outputHelp(),n=!1,this.unsetMatchedCommand()),this.options.version&&this.showVersionOnExit&&this.matchedCommandName==null&&(this.outputVersion(),n=!1,this.unsetMatchedCommand());let o={args:this.args,options:this.options};return n&&this.runMatchedCommand(),!this.matchedCommand&&this.args[0]&&this.dispatchEvent(new CustomEvent("command:*",{detail:this.args[0]})),o}mri(e,n){let t=[...this.globalCommand.options,...n?n.options:[]],o=Fs(t),s=[],r=e.indexOf("--");r!==-1&&(s=e.slice(r+1),e=e.slice(0,r));let i=Bs(e,o);i=Object.keys(i).reduce((u,m)=>({...u,[ln(m)]:i[m]}),{_:[]});let a=i._,d={"--":s},l=n&&n.config.ignoreOptionDefaultValue?n.config.ignoreOptionDefaultValue:this.globalCommand.config.ignoreOptionDefaultValue,c=Object.create(null);for(let u of t){if(!l&&u.config.default!==void 0)for(let m of u.names)d[m]=u.config.default;Array.isArray(u.config.type)&&c[u.name]===void 0&&(c[u.name]=Object.create(null),c[u.name].shouldTransform=!0,c[u.name].transformFunction=u.config.type[0])}for(let u of Object.keys(i))u!=="_"&&(Hs(d,u.split("."),i[u]),zs(d,c));return{args:a,options:d}}runMatchedCommand(){let{args:e,options:n,matchedCommand:t}=this;if(!t||!t.commandAction)return;t.checkUnknownOptions(),t.checkOptionValue(),t.checkRequiredArgs(),t.checkUnusedArgs();let o=[];return t.args.forEach((s,r)=>{s.variadic?o.push(e.slice(r)):o.push(e[r])}),o.push(n),t.commandAction.apply(this,o)}},mn=(e="")=>new qs(e);import{existsSync as Z,mkdirSync as gn,readFileSync as De,writeFileSync as me}from"node:fs";import{join as Q}from"node:path";var fn=".kadence/state.json",Gs=["AGENTS.md","CLAUDE.md"];function kn(e,n="dev",t={}){let o=lt(e);if(o===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=
|
|
11
|
+
git init`};let s=Z(Be(o));gn(Be(o),{recursive:!0}),Zs(o);let r=Q(ct(o),"README.md");Z(r)||me(r,pt(n),"utf8");for(let l of Gs)Qs(o,l,n);let i=t.hooks===!0?`
|
|
12
12
|
|
|
13
|
-
${
|
|
13
|
+
${Vs(o)}`:"",a=t.hooks!==!0&&Z(Q(o,".claude"))&&!hn(o)?`
|
|
14
14
|
|
|
15
|
-
kadence init --hooks adds prime at session start.`:"",d=[".kadence/","AGENTS.md","CLAUDE.md"];return t.hooks===!0&&
|
|
15
|
+
kadence init --hooks adds prime at session start.`:"",d=[".kadence/","AGENTS.md","CLAUDE.md"];return t.hooks===!0&&hn(o)&&d.push(".claude/settings.json"),{ok:!0,alreadyInitialized:s,root:o,message:s?`kadence is already initialised.${i}${a}`:`kadence is ready.
|
|
16
16
|
|
|
17
17
|
kadence task add "first task"
|
|
18
18
|
kadence decision add "What we chose" --why "Why we chose it"
|
|
19
19
|
kadence board
|
|
20
20
|
|
|
21
21
|
Commit ${d.join(", ")} so a teammate's agent finds them.
|
|
22
|
-
Files were created but not committed \u2014 that call is yours.`+i+a}}var
|
|
23
|
-
kadence init --hooks`}}let s=o.hooks??{},r=Array.isArray(s.SessionStart)?s.SessionStart:[],i=r.flatMap(d=>(Array.isArray(d.hooks)?d.hooks:[]).filter(l=>typeof l.command=="string"&&
|
|
24
|
-
`,"utf8"),`Updated the SessionStart hook in ${t}: it now prints an install hint where kadence is missing.`}let a=r.find(d=>d.matcher===
|
|
25
|
-
`,"utf8"),`Added a SessionStart hook to ${t}: every session now starts with \`kadence prime\`.`}function
|
|
22
|
+
Files were created but not committed \u2014 that call is yours.`+i+a}}var je="if command -v kadence >/dev/null 2>&1; then kadence prime; else echo 'kadence is not installed on this machine: ask the human to run npm install -g kadence. The team journal is in .kadence/.'; fi",bn=["kadence prime",je],pn="startup";function Vs(e){let n=Q(e,".claude"),t=Q(n,"settings.json"),o={};if(Z(t)){let d=De(t,"utf8");try{let l=JSON.parse(d);if(typeof l!="object"||l===null||Array.isArray(l))throw new Error("not an object");o=l}catch{return`${t} is not valid JSON, so the hook was not added. Fix it and run:
|
|
23
|
+
kadence init --hooks`}}let s=o.hooks??{},r=Array.isArray(s.SessionStart)?s.SessionStart:[],i=r.flatMap(d=>(Array.isArray(d.hooks)?d.hooks:[]).filter(l=>typeof l.command=="string"&&bn.includes(l.command)));if(i.some(d=>d.command===je))return`The SessionStart hook is already in ${t}.`;if(i.length>0){for(let d of i)d.command=je;return me(t,`${JSON.stringify(o,null,2)}
|
|
24
|
+
`,"utf8"),`Updated the SessionStart hook in ${t}: it now prints an install hint where kadence is missing.`}let a=r.find(d=>d.matcher===pn);return a===void 0&&(a={matcher:pn,hooks:[]},r.push(a)),Array.isArray(a.hooks)||(a.hooks=[]),a.hooks.push({type:"command",command:je,timeout:60}),s.SessionStart=r,o.hooks=s,gn(n,{recursive:!0}),me(t,`${JSON.stringify(o,null,2)}
|
|
25
|
+
`,"utf8"),`Added a SessionStart hook to ${t}: every session now starts with \`kadence prime\`.`}function hn(e){let n=Q(e,".claude","settings.json");if(!Z(n))return!1;try{let o=JSON.parse(De(n,"utf8"))?.hooks?.SessionStart;return Array.isArray(o)?o.some(s=>Array.isArray(s?.hooks)&&s.hooks.some(r=>typeof r?.command=="string"&&bn.includes(r.command))):!1}catch{return!1}}function Zs(e){let n=Q(e,".gitignore"),t="";if(Z(n)&&(t=De(n,"utf8")),t.includes(fn))return;let o=t.length>0&&!t.endsWith(`
|
|
26
26
|
`)?`
|
|
27
|
-
`:"";
|
|
28
|
-
`,"utf8")}function
|
|
29
|
-
kadence task claim ${
|
|
30
|
-
`),data:{schema:"kadence/v1",ok:!0,tasks:
|
|
31
|
-
`),
|
|
27
|
+
`:"";me(n,`${t}${o}${fn}
|
|
28
|
+
`,"utf8")}function Qs(e,n,t){let o=Q(e,n),s=Z(o)?De(o,"utf8"):null,r=ht(s,t);r!==s&&me(o,r,"utf8")}function Xs(e){return{label:e.label,title:e.title,priority:e.priority,estimate:e.estimate,labels:e.labels,claimedBy:e.claimedBy,contestedBy:e.contestedBy}}function yn(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i={statuses:s.statuses,started:s.started},a=xe(s.tasks,{viewer:Se(o,n),...i,...t.assignee===void 0?{}:{assignee:t.assignee}}),d=z(a,t.limit,t.offset),l=d.shown;if(l.length===0)return{ok:!0,exitCode:0,warnings:r,message:St(s.tasks,o.actor,t.assignee,i),data:{schema:"kadence/v1",ok:!0,tasks:[],tasksTotal:d.total,tasksOffset:d.offset}};let c=ve(n,process.stdout.isTTY===!0),u=l.map(m=>{let g=m.contestedBy.length>0?` [contested: ${m.contestedBy.join(", ")}]`:"";return`${yt(m,c)}${g}`});return{ok:!0,exitCode:0,warnings:r,message:[...u,Y(d,"kadence ready"),"",`Take the first one:
|
|
29
|
+
kadence task claim ${l[0].label}`].filter(m=>m!==null).join(`
|
|
30
|
+
`),data:{schema:"kadence/v1",ok:!0,tasks:l.map(Xs),tasksTotal:d.total,tasksOffset:d.offset}}}var se=["task","decision","note","doc","sprint","milestone"];var eo=new Set(["a","an","and","are","as","at","be","but","by","can","did","do","does","for","from","had","has","have","how","i","if","in","is","it","its","of","on","or","our","so","than","that","the","their","them","then","there","these","they","this","to","was","we","were","what","when","where","which","who","why","will","with","would","you","your"]),to=.2,no=.35,so=new RegExp("\\p{Cc}","gu");function Te(e){return e.toLowerCase().match(/[\p{L}\p{N}][\p{L}\p{N}_.-]*/gu)??[]}function Sn(e){return e.replace(so," ").replace(/\s+/gu," ").trim()}function oo(e,n){let t=e.split(`
|
|
31
|
+
`),o=[],s=n,r=[],i=1,a=d=>{let l=r.join(`
|
|
32
|
+
`).trim();l.length>0&&o.push({heading:s,text:l,from:i,to:d})};for(let d=0;d<t.length;d++){let l=/^(#{1,6})\s+(.*)$/.exec(t[d]);l!==null?(a(d),s=l[2].trim(),r=[],i=d+1):r.push(t[d])}return a(t.length),o}function ro(e){let n=[];for(let t of e.tasks){let o=[t.title,t.description??"",...t.criteria.map(s=>s.text),...t.comments.map(s=>s.text)];n.push({kind:"task",id:t.id,label:t.label,title:t.title,heading:t.title,subject:"",text:o.filter(s=>s.length>0).join(`
|
|
33
|
+
`),lines:null,at:t.history[0]?.ts??"",by:t.reporter,superseded:!1})}for(let t of e.decisions)n.push({kind:"decision",id:t.id,label:t.label,title:t.title,heading:t.title,subject:"",text:[t.title,t.why,t.rejected??""].filter(o=>o.length>0).join(`
|
|
34
|
+
`),lines:null,at:t.at,by:t.by,superseded:t.supersededBy!==null});for(let t of e.notes)n.push({kind:"note",id:t.id,label:null,title:Sn(t.text).slice(0,60),heading:"",subject:"",text:t.text,lines:null,at:t.at,by:t.by,superseded:!1});for(let t of e.documents)for(let o of oo(t.body,t.title))n.push({kind:"doc",id:t.id,label:t.label,title:t.title,heading:o.heading,subject:t.title,text:`${o.heading}
|
|
35
|
+
${o.text}`,lines:{from:o.from,to:o.to},at:t.updatedAt,by:t.updatedBy,superseded:!1});for(let t of e.sprints)n.push({kind:"sprint",id:t.id,label:null,title:t.name,heading:t.name,subject:"",text:[t.name,t.description??""].filter(o=>o.length>0).join(`
|
|
36
|
+
`),lines:null,at:"",by:"",superseded:!1});for(let t of e.milestones)n.push({kind:"milestone",id:t.id,label:t.label,title:t.name,heading:t.name,subject:"",text:t.name,lines:null,at:"",by:"",superseded:!1});return n}var $n=1.2,wn=.45,vn=3,xn=2;function io(e,n){let t=new Map,o=new Array(e.length),s=new Float64Array(e.length),r=0;for(let i=0;i<e.length;i++){let a=new Map,d=0;for(let l of Te(e[i].heading))d+=vn,n.has(l)&&a.set(l,(a.get(l)??0)+vn);for(let l of Te(e[i].subject))d+=xn,n.has(l)&&a.set(l,(a.get(l)??0)+xn);for(let l of Te(e[i].text))d+=1,n.has(l)&&a.set(l,(a.get(l)??0)+1);for(let l of a.keys())t.set(l,(t.get(l)??0)+1);o[i]=a,s[i]=d,r+=d}return{df:t,frequency:o,length:s,average:e.length===0?1:r/e.length,count:e.length}}function ao(e){let t=Te(e).filter(o=>!eo.has(o));return t.length>0?t:[]}function lo(e,n){let t=Sn(e),o=t.toLowerCase(),s=-1;for(let a of n){let d=o.indexOf(a);d>=0&&(s<0||d<s)&&(s=d)}if(s<0)return{text:t.slice(0,180),start:0,end:Math.min(180,t.length)};let r=Math.max(0,s-Math.floor(180/3)),i=Math.min(t.length,r+180);if(r>0){let a=t.indexOf(" ",r);a>=0&&a<s&&(r=a+1)}if(i<t.length){let a=t.lastIndexOf(" ",i);a>r&&(i=a)}return{text:t.slice(r,i),start:r,end:i}}function co(e,n){let t=io(e,n),o=a=>{let d=t.df.get(a)??0;return Math.log(1+(t.count-d+.5)/(d+.5))},s=new Map([...n].map(a=>[a,o(a)])),r=0;for(let a of s.values())r+=a;let i=new Map;for(let a=0;a<e.length;a++){let d=t.frequency[a];if(d.size===0)continue;let l=1-wn+wn*(t.length[a]/t.average),c=0,u=0;for(let[m,g]of d){let f=s.get(m);c+=f*(g*($n+1))/(g+$n*l),u+=f}u>=r*no&&i.set(a,{score:c,coverage:r===0?1:u/r})}return i}function An(e,n,t={}){let o=ao(n);if(o.length===0)return[];let s=t.kinds===void 0?null:new Set(t.kinds),r=ro(e).filter(u=>(s===null||s.has(u.kind))&&(t.all===!0||!u.superseded));if(r.length===0)return[];let i=new Set(o),a=co(r,i);if(a.size===0)return[];let d=[...a.entries()].sort((u,m)=>m[1].score!==u[1].score?m[1].score-u[1].score:r[u[0]].id<r[m[0]].id?-1:1),l=d[0][1].score,c=t.limit??5;return d.filter(([,u])=>u.score>=l*to).slice(0,c).map(([u,{score:m,coverage:g}])=>{let f=r[u];return{kind:f.kind,id:f.id,label:f.label,title:f.title,score:Math.round(m*100)/100,coverage:Math.round(g*100)/100,span:lo(f.text,o),lines:f.lines,at:f.at,by:f.by}})}function uo(e){if(e===void 0)return{kinds:null,error:null};let n=e.split(",").map(o=>o.trim().toLowerCase()).filter(o=>o.length>0),t=n.find(o=>!se.includes(o));return t!==void 0?{kinds:null,error:b(2,"invalid_argument",`Unknown kind "${t}".
|
|
37
|
+
Available: ${se.join(", ")}`,{received:t,allowed:se})}:{kinds:n,error:null}}function jn(e){let n=e.label??e.id;return e.lines===null?n:`${n}:${e.lines.from}-${e.lines.to}`}function mo(e,n){let t=Math.max(...e.map(r=>jn(r).length)),o=e.flatMap(r=>[`${jn(r).padEnd(t)} [${r.kind}] ${r.title}`+(r.coverage<.7?" \xB7 answers part of the question":""),`${" ".repeat(t)} ${r.span.text}`,""]),s=e[0].coverage<.7;return[`${e.length} result${e.length===1?"":"s"} for "${n}"`,"",...o,...s?["None of these holds the whole question \u2014 each answers part of it.","Treat them as places to look, not as the answer.",""]:[],"Read one in full:"," kadence task show KAD-1 \xB7 kadence decision show DEC-1 \xB7 kadence doc show DOC-1"].join(`
|
|
38
|
+
`)}function fo(e,n){return[`Nothing in the journal matches "${e}".`,"",n?"That is with --kind narrowing the search. Try it without.":"Either it was never written down, or it is written in other words.","Record it once you know:",' kadence note "\u2026" \xB7 kadence decision add "\u2026" --why "\u2026"'].join(`
|
|
39
|
+
`)}function Dn(e,n,t,o={}){let s=C(e,n);if(!j(s))return s;if(t===void 0||t.trim().length===0)return b(2,"invalid_argument",`What are you looking for?
|
|
40
|
+
kadence search "why are events append-only"`);let{kinds:r,error:i}=uo(o.kind);if(i!==null)return i;let{state:a,warnings:d}=A(s.root,s.actor),l=An(a,t,{...r===null?{}:{kinds:r},...o.limit===void 0?{}:{limit:o.limit},...o.all===!0?{all:!0}:{}});return{ok:!0,exitCode:0,warnings:d,message:l.length===0?fo(t,r!==null):mo(l,t),data:{schema:"kadence/v1",ok:!0,query:t,hits:l,hitsTotal:l.length}}}var po=864e5;function Ye(e){return e.history[e.history.length-1]?.ts??e.createdAt}function fe(e,n){let t=Math.floor((n.getTime()-Date.parse(e))/po);return t>0?t:0}function ho(e){for(let n=e.history.length-1;n>=0;n--){let t=e.history[n];if(t.id===e.claimedEventId)return!1;if(t.type==="task.moved")return!0}return!1}function go(e,n,t,o,s,r){let i=[],a=e.blockedBy.filter(l=>o.has(l));if(a.length>0&&i.push({kind:"dead_blocker",blockers:a.map(l=>t.get(l)??l)}),!ce(n,e))return i;let d=fe(Ye(e),s);if(d>=r&&i.push({kind:"stalled",days:d}),e.assignee===null&&e.claimedBy===null){let l=wt(e,n.started,n.statuses,n.startedChanges),c=l===null?d:fe(l,s);c>=r&&i.push({kind:"unowned",days:c})}if(e.claimedBy!==null&&e.claimedAt!==null&&!ho(e)){let l=fe(e.claimedAt,s);l>=r&&i.push({kind:"stale_claim",days:l,who:e.claimedBy})}return i}function oe(e){switch(e.kind){case"stalled":return`stalled ${String(e.days)}d`;case"unowned":return`unowned ${String(e.days)}d`;case"stale_claim":return`claimed ${String(e.days)}d ago by ${e.who??"someone"}, never moved`;case"dead_blocker":return`blocked by ${(e.blockers??[]).join(", ")}, already done`}}function Re(e,n=new Date,t=7){let o=e.tasks.filter(d=>!te(d)),s=new Set(e.tasks.filter(te).map(d=>d.id)),r=new Map(e.tasks.map(d=>[d.id,d.label])),i=[];for(let d of o){let l=go(d,e,r,s,n,t);l.length!==0&&i.push({label:d.label,title:d.title,status:d.status,priority:d.priority,assignee:d.assignee,idleDays:fe(Ye(d),n),signals:l})}let a=new Map(e.tasks.map((d,l)=>[d.label,l]));return i.sort((d,l)=>l.idleDays!==d.idleDays?l.idleDays-d.idleDays:(a.get(d.label)??0)-(a.get(l.label)??0)),{threshold:t,started:e.started,asOf:n.toISOString().slice(0,10),rows:i,notes:i.length>0?[]:ko(e,o,n,t)}}function ko(e,n,t,o){let s=n.filter(i=>ce(e,i));if(s.length===0)return[`Nothing to report: there is no work in progress past \`${e.started}\`.`];let r=Math.min(...s.map(i=>fe(Ye(i),t)));return[`Nothing to report: ${String(s.length)} task${s.length===1?"":"s"} in progress, none silent or ownerless for ${String(o)} days (the quietest was touched ${String(r)} day(s) ago).`]}function Tn(e,n){return n===null?null:e.tasks.find(t=>t.id===n)?.label??null}var bo=5,yo=5,$o=5,wo=3,vo=3,xo=7,Rn=60,En=2e3,So='record why: kadence decision add "\u2026" --why "\u2026"',On=["kadence ready what can be started now","kadence task show KAD-1 one task in full, with its decisions","kadence decision list the reasons behind the work","kadence board the whole board"],Ao=new RegExp("\\p{Cc}","gu");function Ee(e){let n=e.replace(Ao," ").replace(/\s+/gu," ").trim(),t=[...n];return t.length>Rn?`${t.slice(0,Rn-1).join("")}\u2026`:n}function pe(e){let n=[...e];return n.length>En?`${n.slice(0,En-1).join("")}\u2026`:e}function Co(e,n){if(e===null)return null;let t=Date.parse(`${e}T00:00:00.000Z`);if(Number.isNaN(t))return null;let o=Date.parse(`${n.toISOString().slice(0,10)}T00:00:00.000Z`);return Math.round((t-o)/864e5)}function jo(e,n,t){return e.tasks.filter(o=>ue(o.claimedBy,n)||o.contestedBy.some(s=>ue(s,n))||o.assignee===t&&o.status===e.started)}function Do(e,n){if(e.contestedBy.length===0)return"";let t=[e.claimedBy,...e.contestedBy];if(!n.includes("#")&&t.every(o=>ue(o,n))){let o=t.every(s=>s!==n);return` [contested: ${t.length} of your ${o?"agents":"claims"} collided \u2014 keep one, release the rest]`}return ue(e.claimedBy,n)?` [contested: also claimed by ${e.contestedBy.join(", ")}]`:` [contested: ${e.claimedBy??"nobody"} holds it \u2014 talk before starting]`}function Nn(e,n,t,o=new Date){let s=C(e,n);if(!j(s))return s;let{state:r,warnings:i}=A(s.root,s.actor),a=r.sprints.find(y=>y.status==="active"),d=a===void 0?null:Co(a.endDate,o),l=Se(s,n),c=jo(r,l,s.actor),u=[...c].reverse().sort((y,N)=>+(N.contestedBy.length>0)-+(y.contestedBy.length>0)).slice(0,bo),m=xe(r.tasks,{viewer:l,statuses:r.statuses,started:r.started}),g=Re(r,o,xo).rows,f=g.slice(0,vo),S=r.decisions.filter(y=>y.supersededBy===null).slice(-yo).reverse().map(y=>({label:y.label,title:pe(y.title)})),$=r.notes.slice(-$o).reverse().map(y=>({text:pe(y.text),bytes:Buffer.byteLength(y.text,"utf8"),by:y.by,task:Tn(r,y.task)})),x=new Set(c.map(y=>y.id)),k=r.documents.flatMap(y=>{let N=y.tasks.find(_=>x.has(_));return N===void 0?[]:[{label:y.label,title:pe(y.title),task:Tn(r,N),bytes:Buffer.byteLength(y.body,"utf8")}]}),D=k.slice(0,wo),R=[];a!==void 0&&R.push(`Sprint: ${a.name}${d===null?"":`, ${d} day(s) left`}`,"");let q=c.length>u.length?`${u.length} of ${c.length}`:`${u.length}`;R.push(c.length===0?"Nothing claimed by you.":`Yours (${q}):`);for(let y of u)R.push(` ${y.label} ${y.status} ${Ee(y.title)}${Do(y,l)}`);if(D.length>0){let y=k.length>D.length?`${D.length} of ${k.length}`:`${D.length}`;R.push("",`Documentation for your work (${y}): (kadence doc show DOC-N)`);for(let N of D)R.push(` ${N.label} ${Ee(N.title)} (${N.task})`)}if(R.push("",`Ready to start: ${m.length} (kadence ready)`),f.length>0){let y=g.length>f.length?`${f.length} of ${g.length}`:`${f.length}`;R.push("",`Nobody is moving (${y}): (kadence report attention)`);for(let N of f)R.push(` ${N.label} ${N.signals.map(oe).join(" \xB7 ")}`)}if(S.length>0){R.push("","Decisions in force:");for(let y of S)R.push(` ${y.label} ${Ee(y.title)}`)}else R.push("",So);if($.length>0){R.push("","Recent notes:");for(let y of $)R.push(` ${y.task===null?"":`${y.task} `}${Ee(y.text)}`)}R.push("","Go deeper:");for(let y of On)R.push(` ${y}`);return{ok:!0,exitCode:0,warnings:i,message:R.join(`
|
|
41
|
+
`),data:{schema:"kadence/v1",ok:!0,sprint:a===void 0?null:{name:pe(a.name),endDate:a.endDate,daysLeft:d},mine:u.map(y=>({label:y.label,title:pe(y.title),status:y.status,claimedBy:y.claimedBy,contestedBy:y.contestedBy})),mineTotal:c.length,documentation:D,documentationTotal:k.length,ready:m.length,attention:f,attentionTotal:g.length,decisions:S,notes:$,commands:On}}}var To=3;function Mn(e,n){let t=new Map;for(let o of e)t.set(n(o),(t.get(n(o))??0)+1);return[...t.entries()].sort((o,s)=>s[1]-o[1]||(o[0]<s[0]?-1:1))}function Ro(e){return e.sprints.filter(n=>n.status==="closed").sort((n,t)=>(n.closedBy??"")<(t.closedBy??"")?1:-1).slice(0,To).map(n=>{let t=ne(e,n.id);return{name:n.name,velocity:t?.velocity??0}})}function _n(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=s.tasks.filter(f=>f.status!==I&&f.status!==L),a=new Set(s.tasks.filter(f=>f.status===I||f.status===L).map(f=>f.id)),d=Mn(s.tasks,f=>f.status),l=Mn(i,f=>f.assignee??"unassigned"),c=i.filter(f=>f.blockedBy.some(S=>!a.has(S))),u=s.tasks.filter(f=>f.contestedBy.length>0),m=Ro(s);if(s.tasks.length===0)return{ok:!0,exitCode:0,warnings:r,message:`No tasks yet.
|
|
32
42
|
Create the first one:
|
|
33
|
-
kadence task add "title"`,data:{schema:"kadence/v1",ok:!0,tasks:0,open:0,byStatus:[],byAssignee:[],blocked:[],contested:[],velocity:[]}};let g=[];g.push(`${s.tasks.length} tasks, ${i.length} open`),g.push("","By status:");for(let[
|
|
34
|
-
`),data:{schema:"kadence/v1",ok:!0,tasks:s.tasks.length,open:i.length,byStatus:d.map(([
|
|
35
|
-
Nothing was written. Drop --dry-run to do it.`,data:{schema:"kadence/v1",ok:!0,keepFrom:i,archivedMonths:a.months.map(c=>c.month),archivedEvents:a.events,dryRun:!0}};let l=
|
|
36
|
-
`:"",m=l.skipped.every(
|
|
43
|
+
kadence task add "title"`,data:{schema:"kadence/v1",ok:!0,tasks:0,open:0,byStatus:[],byAssignee:[],blocked:[],contested:[],velocity:[]}};let g=[];g.push(`${s.tasks.length} tasks, ${i.length} open`),g.push("","By status:");for(let[f,S]of d)g.push(` ${S} ${f}`);if(l.length>0){g.push("","Open work by assignee:");for(let[f,S]of l)g.push(` ${S} ${f}`)}if(c.length>0&&g.push("",`Blocked (${c.length}): ${c.map(f=>f.label).join(", ")}`),u.length>0&&g.push("",`Contested (${u.length}): ${u.map(f=>f.label).join(", ")}`),m.length>0){g.push("","Velocity of the last closed sprints:");for(let f of m)g.push(` ${f.velocity} points ${f.name}`)}return{ok:!0,exitCode:0,warnings:r,message:g.join(`
|
|
44
|
+
`),data:{schema:"kadence/v1",ok:!0,tasks:s.tasks.length,open:i.length,byStatus:d.map(([f,S])=>({status:f,count:S})),byAssignee:l.map(([f,S])=>({assignee:f,count:S})),blocked:c.map(f=>f.label),contested:u.map(f=>f.label),velocity:m}}}var Eo=2;function Oo(e,n){let t=e.getUTCFullYear(),o=e.getUTCMonth();return new Date(Date.UTC(t,o-(n-1),1)).toISOString().slice(0,7)}function Pn(e,n,t,o=new Date){let s=C(e,n);if(!j(s))return s;let r=t.keepMonths??Eo;if(!Number.isInteger(r)||r<1){let c=t.keepMonthsRaw??String(r);return b(2,"invalid_argument",`--keep-months must be a whole number of at least 1, got "${c}".`,{received:c,hint:"kadence compact --keep-months 3"})}let i=Oo(o,r),a=mt(s.root,i);if(a.months.length===0)return{ok:!0,exitCode:0,message:`Nothing to archive: every event is from ${i} or later, which --keep-months ${r} keeps as separate files.`,data:{schema:"kadence/v1",ok:!0,keepFrom:i,archivedMonths:[],archivedEvents:0,dryRun:t.dryRun===!0}};let d=a.months.map(c=>`${c.month} (${c.events} event${c.events===1?"":"s"})`).join(", ");if(t.dryRun===!0)return{ok:!0,exitCode:0,message:`Would archive ${a.events} event${a.events===1?"":"s"} from ${d}, keeping ${i} onward as separate files.
|
|
45
|
+
Nothing was written. Drop --dry-run to do it.`,data:{schema:"kadence/v1",ok:!0,keepFrom:i,archivedMonths:a.months.map(c=>c.month),archivedEvents:a.events,dryRun:!0}};let l=ft(s.root,i);if(l.skipped.length>0){let c=l.skipped.map(f=>f.replace(`${s.root}/`,"")).join(", "),u=l.archivedMonths.length>0?`Archived ${l.archivedMonths.join(", ")} first; those are done.
|
|
46
|
+
`:"",m=l.skipped.every(f=>!f.endsWith(".json")),g=m?"It holds events this version cannot read \u2014 most often written by a newer kadence. Update kadence and run this again.":"The archive holds every event compacted before it \u2014 restore the file from git, or move it aside if you accept losing what it held, then run this again.";return b(1,"conflicting_state",`${u}Could not read ${c}, so ${l.skipped.length===1?"that month was":"those months were"} left alone. Nothing was deleted. ${g}`,{received:c,hint:m?"npm install -g kadence":"git checkout -- .kadence/events/archive/"})}return{ok:!0,exitCode:0,message:`Archived ${l.archivedEvents} event${l.archivedEvents===1?"":"s"} from ${d} into .kadence/events/archive/, keeping ${i} onward as separate files.
|
|
37
47
|
An archived month is one file. Compact on one branch and merge it before compacting on another; the events themselves are unchanged, only where they live.
|
|
38
|
-
Nothing was committed \u2014 that call is yours.`,data:{schema:"kadence/v1",ok:!0,keepFrom:i,archivedMonths:l.archivedMonths,archivedEvents:l.archivedEvents,dryRun:!1}}}function
|
|
48
|
+
Nothing was committed \u2014 that call is yours.`,data:{schema:"kadence/v1",ok:!0,keepFrom:i,archivedMonths:l.archivedMonths,archivedEvents:l.archivedEvents,dryRun:!1}}}function In(e,n=new Date){let t=e.tasks.filter(d=>!te(d)),o=new Set(e.tasks.filter(d=>!te(d)).map(d=>d.id)),s=new Map;for(let d of t){let l=d.assignee,c=s.get(l);c===void 0?s.set(l,[d]):c.push(d)}let r=[...s.entries()].map(([d,l])=>({assignee:d,open:l.length,openPoints:l.reduce((c,u)=>c+(u.estimate??0),0),inProgress:l.filter(c=>ce(e,c)).length,blocked:l.filter(c=>c.blockedBy.some(u=>o.has(u))).length,unestimated:l.filter(c=>c.estimate===null).length})).sort((d,l)=>l.openPoints-d.openPoints||l.open-d.open),i=[];r.length===0&&i.push("Nothing open.");let a=r.reduce((d,l)=>d+l.unestimated,0);return a>0&&i.push(`${a} open task${a===1?"":"s"} carry no estimate, so the points understate the work by an unknown amount.`),{asOf:n.toISOString().slice(0,10),started:e.started,rows:r,notes:i}}function v(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}var F=`
|
|
39
49
|
:root {
|
|
40
50
|
color-scheme: light dark;
|
|
41
51
|
--bg: #ffffff; --fg: #1a1a1a; --muted: #6b6b6b; --line: #e2e2e2;
|
|
@@ -109,21 +119,21 @@ summary { color: var(--muted); font-size: .82rem; cursor: pointer; }
|
|
|
109
119
|
summary::marker { color: var(--line); }
|
|
110
120
|
tr.critical td:first-child { border-left: 3px solid var(--critical); }
|
|
111
121
|
`;function H(e,n,t){return["<!doctype html>",'<html lang="en">',"<head>",'<meta charset="utf-8">','<meta name="viewport" content="width=device-width, initial-scale=1">',`<title>${v(e)}</title>`,`<style>${n}</style>`,"</head>","<body>","<main>",...t,"</main>","</body>","</html>",""].join(`
|
|
112
|
-
`)}function E(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function f(e){return Number.isFinite(e)?String(Math.round(e*100)/100):"0"}function ce(e){if(!Number.isFinite(e)||e<=0)return 1;let n=Math.floor(Math.log10(e)),t=Math.pow(10,n),o=e/t;return(o<=1?1:o<=2?2:o<=5?5:10)*t}function no(e,n,t,o){let s=Math.min(4,t/2,o);return o<=0?"":`M${f(e)},${f(n+o)}L${f(e)},${f(n+s)}Q${f(e)},${f(n)} ${f(e+s)},${f(n)}L${f(e+t-s)},${f(n)}Q${f(e+t)},${f(n)} ${f(e+t)},${f(n+s)}L${f(e+t)},${f(n+o)}Z`}function so(e,n,t,o){let s=Math.min(4,o/2,t);return t<=0?"":`M${f(e)},${f(n)}L${f(e+t-s)},${f(n)}Q${f(e+t)},${f(n)} ${f(e+t)},${f(n+s)}L${f(e+t)},${f(n+o-s)}Q${f(e+t)},${f(n+o)} ${f(e+t-s)},${f(n+o)}L${f(e)},${f(n+o)}Z`}function ue(e,n,t,o){return`<svg class="viz" viewBox="0 0 ${e} ${n}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${E(t)}"><title>${E(t)}</title>${o}</svg>`}function Fe(e){let t=e.height??220,o={top:12,right:14,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.labels.length),a=s/i,d=ce(Math.max(0,...e.series.flatMap(x=>x.values))),l=x=>o.top+r-x/d*r,c=[];for(let x of[0,d/2,d])c.push(`<line class="grid" x1="${o.left}" y1="${f(l(x))}" x2="${f(760-o.right)}" y2="${f(l(x))}"/>`,`<text class="tick" x="${o.left-6}" y="${f(l(x)+3.5)}" text-anchor="end">${f(x)}</text>`);let u=2,m=(a-8-u*(e.series.length-1))/e.series.length,g=Math.min(24,Math.max(2,m)),h=g*e.series.length+u*(e.series.length-1);e.series.forEach((x,S)=>{e.labels.forEach((M,T)=>{let Y=x.values[T]??0,$=r-(l(Y)-o.top);if($<=0)return;let N=o.left+T*a+(a-h)/2+S*(g+u);c.push(`<path d="${no(N,l(Y),g,$)}" fill="var(${x.color})"><title>${E(M)} \xB7 ${E(x.name)}: ${Y} ${E(e.unit)}</title></path>`)})});let k=e.labels.length>8;e.labels.forEach((x,S)=>{let M=S===0||S===e.labels.length-1;if(!(k&&!M)){if(k){let T=S===0?o.left:760-o.right;c.push(`<text class="tick" x="${f(T)}" y="${f(t-10)}" text-anchor="${S===0?"start":"end"}">${E(x)}</text>`);return}c.push(`<text class="tick" x="${f(o.left+S*a+a/2)}" y="${f(t-10)}" text-anchor="middle">${E(x)}</text>`)}});let b=`${e.series.map(x=>x.name).join(" and ")} per period, in ${e.unit}.`;return ue(760,t,b,c.join(""))}function vn(e){let t=e.height??240,o={top:12,right:104,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.dates.length),a=b=>i===1?o.left+s/2:o.left+b/(i-1)*s,d=e.dates.map((b,x)=>e.bands.reduce((S,M)=>S+(M.values[x]??0),0)),l=ce(Math.max(0,...d)),c=b=>o.top+r-b/l*r,u=[];for(let b of[0,l/2,l])u.push(`<line class="grid" x1="${o.left}" y1="${f(c(b))}" x2="${f(760-o.right)}" y2="${f(c(b))}"/>`,`<text class="tick" x="${o.left-6}" y="${f(c(b)+3.5)}" text-anchor="end">${f(b)}</text>`);let m=e.dates.map(()=>0),g=[...e.bands].reverse(),h=[];for(let b of g){let x=[...m];e.dates.forEach((N,_)=>{m[_]=(m[_]??0)+(b.values[_]??0)});let S=e.dates.map((N,_)=>`${f(a(_))},${f(c(m[_]??0))}`),M=e.dates.map((N,_)=>`${f(a(_))},${f(c(x[_]??0))}`).reverse();if(i===1){let N=Math.min(24,s),_=c(x[0]??0)-c(m[0]??0);_>0&&u.push(`<rect x="${f(a(0)-N/2)}" y="${f(c(m[0]??0))}" width="${f(N)}" height="${f(_)}" fill="var(${b.color})"><title>${E(b.name)}: ${b.values[0]??0}</title></rect>`);continue}u.push(`<path d="M${S.join("L")}L${M.join("L")}Z" fill="var(${b.color})" fill-opacity="0.9"><title>${E(b.name)}</title></path>`,`<polyline class="seam" points="${S.join(" ")}"/>`);let T=e.dates.length-1,Y=c(m[T]??0),$=c(x[T]??0);h.push({name:b.name,y:(Y+$)/2,height:$-Y})}let k=Number.NEGATIVE_INFINITY;for(let b of[...h].sort((x,S)=>x.y-S.y))b.height<10||b.y-k<13||(k=b.y,u.push(`<text class="tick" x="${f(760-o.right+10)}" y="${f(b.y+3.5)}">${E(b.name)}</text>`));return e.dates.forEach((b,x)=>{(x===0||x===e.dates.length-1)&&u.push(`<text class="tick" x="${f(a(x))}" y="${f(t-10)}" text-anchor="${x===0?"start":"end"}">${E(b)}</text>`)}),ue(760,t,`Tasks per column per day, ${e.bands.map(b=>b.name).join(", ")}.`,u.join(""))}function Ae(e){let o={top:8,right:52,bottom:26,left:92},s=o.top+o.bottom+Math.max(1,e.rows.length)*26,r=760-o.left-o.right,i=ce(Math.max(e.reference?.value??0,...e.rows.map(l=>l.value))),a=l=>o.left+l/i*r,d=[];return d.push(`<line class="grid" x1="${o.left}" y1="${o.top}" x2="${o.left}" y2="${f(s-o.bottom)}"/>`),e.rows.forEach((l,c)=>{let u=o.top+c*26,m=Math.min(14,16),g=a(l.value)-o.left,h=l.critical===!0?"var(--critical)":"var(--s1)";d.push(`<text class="tick mono" x="${o.left-8}" y="${f(u+m/2+8)}" text-anchor="end">${E(l.name)}</text>`,`<path d="${so(o.left,u+5,Math.max(g,1),m)}" fill="${h}"><title>${E(l.name)}: ${l.value} ${E(e.unit)}${l.note===void 0?"":` \xB7 ${E(l.note)}`}</title></path>`,`<text class="tick" x="${f(a(l.value)+6)}" y="${f(u+m/2+8)}">${l.value}</text>`)}),e.reference!==void 0&&e.reference.value>0&&d.push(`<line class="reference" x1="${f(a(e.reference.value))}" y1="${o.top}" x2="${f(a(e.reference.value))}" y2="${f(s-o.bottom+4)}"/>`,`<text class="tick" x="${f(a(e.reference.value))}" y="${f(s-10)}" text-anchor="middle">${E(e.reference.label)}</text>`),ue(760,s,`${e.rows.length} rows, in ${e.unit}.`,d.join(""))}function xn(e,n){let s={top:10,right:20,bottom:26,left:92},r=s.top+s.bottom+Math.max(1,e.length)*44,i=760-s.left-s.right,a=ce(Math.max(1,...e.map(c=>c.p95))),d=c=>s.left+c/a*i,l=[];for(let c of[0,a/2,a])l.push(`<line class="grid" x1="${f(d(c))}" y1="${s.top}" x2="${f(d(c))}" y2="${f(r-s.bottom+2)}"/>`,`<text class="tick" x="${f(d(c))}" y="${f(r-10)}" text-anchor="middle">${f(c)}</text>`);return e.forEach((c,u)=>{let m=s.top+u*44+22-4;l.push(`<text class="tick" x="${s.left-8}" y="${f(m+4)}" text-anchor="end">${E(c.name)}</text>`,`<line class="range" x1="${f(d(c.p50))}" y1="${f(m)}" x2="${f(d(c.p95))}" y2="${f(m)}"/>`);for(let[g,h,k]of[["p50",c.p50,4.5],["p85",c.p85,6],["p95",c.p95,4.5]])l.push(`<circle class="dot" cx="${f(d(h))}" cy="${f(m)}" r="${k}"><title>${E(c.name)} ${g}: ${h} ${E(n)} (n=${c.n})</title></circle>`);l.push(`<text class="tick" x="${f(d(c.p85))}" y="${f(m-12)}" text-anchor="middle">p85 = ${c.p85}</text>`)}),ue(760,r,`p50, p85 and p95 per measure, in ${n}.`,l.join(""))}function Sn(e){let t=e.height??230,o={top:12,right:60,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.labels.length),a=u=>i===1?o.left+s/2:o.left+u/(i-1)*s,d=ce(Math.max(0,...e.series.flatMap(u=>u.values))),l=u=>o.top+r-u/d*r,c=[];for(let u of[0,d/2,d])c.push(`<line class="grid" x1="${o.left}" y1="${f(l(u))}" x2="${f(760-o.right)}" y2="${f(l(u))}"/>`,`<text class="tick" x="${o.left-6}" y="${f(l(u)+3.5)}" text-anchor="end">${f(u)}</text>`);for(let u of e.series){let m=u.values.map((b,x)=>`${f(a(x))},${f(l(b))}`).join("L"),g=u.reference===!0;c.push(`<path class="line${g?" reference-line":""}" d="M${m}" ${g?"":`stroke="var(${u.color})"`}><title>${E(u.name)}, ${E(e.unit)}</title></path>`);let h=u.values.length-1,k=u.values[h];!g&&k!==void 0&&c.push(`<circle class="dot" cx="${f(a(h))}" cy="${f(l(k))}" r="4.5" fill="var(${u.color})"/>`,`<text class="tick" x="${f(a(h)+9)}" y="${f(l(k)+3.5)}">${k}</text>`)}return e.labels.forEach((u,m)=>{m!==0&&m!==e.labels.length-1||c.push(`<text class="tick" x="${f(a(m))}" y="${f(t-10)}" text-anchor="${m===0?"start":"end"}">${E(u)}</text>`)}),ue(760,t,`${e.series.map(u=>u.name).join(" against ")}, in ${e.unit}.`,c.join(""))}var me=["--s1","--s2","--s3","--s4","--s5","--s6","--s7","--s8"];function ne(e,n){return`<p class="stamp">${e.map(v).join(" ")} A file, not a page: nothing here is live, and regenerating it is <code>${v(n)}</code>.</p>`}function P(e,n,t,o=!1){return`<div class="tile${o?" critical":""}"><div class="label">${v(e)}</div><div class="value">${v(n)}</div><div class="sub">${v(t)}</div></div>`}function je(e){return'<div class="legend">'+e.map(n=>`<span><i style="background:var(${n.color})"></i>${v(n.name)}</span>`).join("")+"</div>"}function J(e,n){return`<figure class="figure">${e}<figcaption>${v(n)}</figcaption></figure>`}function q(e,n){return`<div class="rows"><table><tr>${e.map(o=>`<th${o.num===!0?' class="num"':""}>${v(o.head)}</th>`).join("")}</tr>${n.join("")}</table></div>`}function pe(e){return e.length===0?"":e.map(n=>`<p class="empty">${v(n)}</p>`).join("")}function z(e){return`<footer>${v(e)} Folded from the event journal by kadence. No server, no network.</footer>`}function se(e){return`${e.toISOString().slice(0,16).replace("T"," ")} UTC`}function Cn(e,n=new Date){let t=[];t.push("<h1>Flow</h1>"),t.push(ne([`${e.window.from} to ${e.window.to} UTC, ${e.window.days} calendar days.`,`Work counts as started at "${e.started}".`,`Generated ${se(n)}.`],"kadence report flow --html"));let o=e.cycleTime===null?"\u2014":String(e.cycleTime.p85);t.push('<div class="tiles">',P("In progress now",String(e.wip),"tasks past the started boundary"),P("Finished",String(e.finished),`in ${e.window.days} calendar days`),P("Cycle time p85",o,e.cycleTime===null?"nothing finished yet":`calendar days, n=${e.cycleTime.n}`),P("Blocked",String(e.blocked.days),e.blocked.tasks===0?"no blocked time in the window":`days across ${e.blocked.tasks} task(s)`,e.blocked.tasks>0),"</div>"),e.sle!==null&&t.push(`<p class="callout">${v(e.sle)}</p>`);let r=[{name:"Cycle time",p:e.cycleTime},{name:"Lead time",p:e.leadTime},{name:"Response time",p:e.responseTime}].filter(i=>i.p!==null);if(t.push("<h2>How long work takes</h2>"),r.length===0?t.push('<p class="empty">Nothing has finished in this window, so there is nothing to measure.</p>'):(t.push(J(xn(r.map(i=>({name:i.name,p50:i.p.p50,p85:i.p.p85,p95:i.p.p95,n:i.p.n})),"calendar days"),"p50, p85 and p95 in calendar days. Percentiles, never a mean \u2014 the tail is the part worth managing.")),t.push(q([{head:"Measure"},{head:"p50",num:!0},{head:"p85",num:!0},{head:"p95",num:!0},{head:"n",num:!0}],r.map(i=>`<tr><td>${v(i.name)}</td><td class="num">${i.p.p50}</td><td class="num">${i.p.p85}</td><td class="num">${i.p.p95}</td><td class="num">${i.p.n}</td></tr>`)))),t.push("<h2>Created and finished, per week</h2>"),e.perWeek.length===0)t.push('<p class="empty">No weeks in this window carry either.</p>');else{let i=[{name:"Created",color:"--s2",values:e.perWeek.map(a=>a.created)},{name:"Finished",color:"--s1",values:e.perWeek.map(a=>a.finished)}];t.push(je(i.map(a=>({name:a.name,color:a.color})))),t.push(J(Fe({labels:e.perWeek.map(a=>a.week),series:i,unit:"tasks"}),"One band per week, labelled by its Monday. More created than finished, week after week, is a queue growing.")),t.push("<details><summary>Every week as rows</summary>",q([{head:"Week of"},{head:"Created",num:!0},{head:"Finished",num:!0}],e.perWeek.map(a=>`<tr><td>${v(a.week)}</td><td class="num">${a.created}</td><td class="num">${a.finished}</td></tr>`)),"</details>")}if(t.push("<h2>Aging work in progress</h2>"),e.aging.length===0)t.push('<p class="empty">Nothing is in progress.</p>');else{let i=e.aging.slice(0,15);t.push(J(Ae({rows:i.map(a=>({name:a.label,value:a.ageDays,critical:a.overP85,note:`${a.status} \xB7 ${a.title}`})),unit:"calendar days",...e.cycleTime===null?{}:{reference:{value:e.cycleTime.p85,label:`p85 = ${e.cycleTime.p85} d`}}}),e.cycleTime===null?"Age in calendar days, oldest first.":"Age in calendar days, oldest first. The line is the p85 cycle time: work to its right has already taken longer than 85% of what finished.")),t.push(q([{head:"Task"},{head:"Age",num:!0},{head:"Status"},{head:"Title"}],i.map(a=>`<tr class="${a.overP85?"critical":""}"><td>${v(a.label)}</td><td class="num">${a.ageDays}</td><td>${v(a.status)}</td><td>${v(a.title)}${a.overP85?' <span class="pill danger">older than p85</span>':""}</td></tr>`))),e.aging.length>i.length&&t.push(`<p class="empty">\u2026 and ${e.aging.length-i.length} more. The --json response carries every row.</p>`)}return t.push(pe(e.notes)),t.push(z(`${e.finished} finished, ${e.wip} in progress.`)),H("kadence flow",K+U,t)}function An(e,n=new Date){let t=[];if(t.push("<h1>Cumulative flow</h1>"),t.push(ne([`${e.window.from} to ${e.window.to} UTC, ${e.window.days} calendar days.`,"Tasks per column at the end of each day.",`Generated ${se(n)}.`],"kadence report cfd --html")),e.statuses.length===0||e.days.length===0)return t.push('<p class="empty">No columns to draw yet.</p>'),t.push(z("Nothing in the window.")),H("kadence cumulative flow",K+U,t);let o=e.statuses.slice(0,me.length),s=e.statuses.slice(me.length),r=o.map((a,d)=>({name:a,color:me[d],values:e.days.map(l=>l.counts[a]??0)}));s.length>0&&r.push({name:`Other (${s.length} columns)`,color:me[me.length-1],values:e.days.map(a=>s.reduce((d,l)=>d+(a.counts[l]??0),0))}),t.push(je(r.map(a=>({name:a.name,color:a.color})))),t.push(J(vn({dates:e.days.map(a=>a.date),bands:r}),"Bands stack in board order, finished work at the baseline. A band that widens is a queue; the height between two lines is the work sitting in that column."));let i=[{head:"Date"},...r.map(a=>({head:a.name,num:!0}))];return t.push("<details><summary>Every day as rows</summary>",q(i,e.days.map(a=>{let d=o.map(c=>`<td class="num">${a.counts[c]??0}</td>`).join(""),l=s.length===0?"":`<td class="num">${s.reduce((c,u)=>c+(a.counts[u]??0),0)}</td>`;return`<tr><td>${v(a.date)}</td>${d}${l}</tr>`})),"</details>"),t.push(z(`${e.days.length} days, ${e.statuses.length} columns.`)),H("kadence cumulative flow",K+U,t)}function jn(e,n=new Date){let t=[];if(t.push("<h1>Attention</h1>"),t.push(ne([`As of ${e.asOf} UTC.`,`Work past "${e.started}" that nobody is moving \u2014 silent or ownerless for ${e.threshold} days or more, or blocked by work that is already done.`,`Generated ${se(n)}.`],"kadence report attention --html")),t.push('<div class="tiles">',P("Needs attention",String(e.rows.length),e.rows.length===0?"nothing is stuck":"of the work in flight",e.rows.length>0),P("Threshold",`${e.threshold} d`,"silence before a task counts as stalled"),"</div>"),e.rows.length===0)t.push('<p class="empty">Nothing is stalled, unowned, claimed and forgotten, or waiting on work that is already done.</p>');else{let o=e.rows.slice(0,20);t.push(J(Ae({rows:o.map(s=>({name:s.label,value:s.idleDays,critical:s.idleDays>=e.threshold*2,note:`${s.status} \xB7 ${s.title}`})),unit:"days of silence",reference:{value:e.threshold,label:`${e.threshold} d`}}),`Days since the task last moved. The line is the ${e.threshold}-day threshold; everything here is already past it, and a bar turns critical past twice it.`)),t.push(q([{head:"Task"},{head:"Idle",num:!0},{head:"Status"},{head:"Why it is here"}],o.map(s=>`<tr class="${s.idleDays>=e.threshold*2?"critical":""}"><td>${v(s.label)}</td><td class="num">${s.idleDays}</td><td>${v(s.status)}</td><td>${v(s.title)}<div class="sub">${v(s.signals.map(te).join(" \xB7 "))}</div></td></tr>`))),e.rows.length>o.length&&t.push(`<p class="empty">\u2026 and ${e.rows.length-o.length} more. The --json response carries every row.</p>`)}return t.push(pe(e.notes)),t.push(z(`${e.rows.length} needing attention.`)),H("kadence attention",K+U,t)}function Dn(e,n=new Date){let t=[];if(t.push("<h1>Burndown</h1>"),t.push(ne([`${v(e.sprintName)}: ${e.committed} points committed.`,e.finalRemaining===null?"The sprint is still open, so the last day is today rather than the end.":`Closed with ${e.finalRemaining} point(s) unfinished.`,`Generated ${se(n)}.`],"kadence report burndown --html")),e.committed===0||e.days.length===0)return t.push('<p class="empty">Nothing to burn down: no task in this sprint carries an estimate.</p>'),t.push(z(`${e.sprintName}, ${e.days.length} days.`)),H("kadence burndown",K+U,t);let o=e.days[e.days.length-1],s=o.remaining<=o.ideal;return t.push('<div class="tiles">',P("Committed",String(e.committed),"points taken into the sprint"),P("Remaining",String(o.remaining),`of ${e.committed}, on ${o.date}`,!s),P("Against the ideal",`${s?"\u2212":"+"}${Math.abs(Math.round(o.remaining-o.ideal))}`,s?"points ahead of an even burn":"points behind an even burn",!s),"</div>"),t.push(je([{name:"Remaining",color:"--s1"},{name:"An even burn",color:"--muted"}])),t.push(J(Sn({labels:e.days.map(r=>r.date),series:[{name:"An even burn",color:"--muted",values:e.days.map(r=>Math.round(r.ideal*10)/10),reference:!0},{name:"Remaining",color:"--s1",values:e.days.map(r=>r.remaining)}],unit:"points"}),"Points still open at the end of each day. The muted line is where a perfectly even burn would have been \u2014 an expectation, not a measurement.")),t.push("<details><summary>Every day as rows</summary>",q([{head:"Date"},{head:"Remaining",num:!0},{head:"Even burn",num:!0},{head:"Finished that day",num:!0}],e.days.map(r=>`<tr><td>${v(r.date)}</td><td class="num">${r.remaining}</td><td class="num">${Math.round(r.ideal*10)/10}</td><td class="num">${r.completed}</td></tr>`)),"</details>"),t.push(z(`${e.sprintName}, ${e.days.length} days, ${e.committed} points.`)),H("kadence burndown",K+U,t)}function Tn(e,n=new Date){let t=[];if(t.push("<h1>Velocity</h1>"),t.push(ne(["Points taken into a sprint against points finished, oldest first.",`Generated ${se(n)}.`],"kadence report velocity --html")),e.rows.length===0)return t.push('<p class="empty">No closed sprint yet. Velocity is what a finished sprint leaves behind.</p>'),t.push(pe(e.notes)),t.push(z("No sprints closed.")),H("kadence velocity",K+U,t);t.push('<div class="tiles">',P("Finished",`${e.low}\u2013${e.high}`,`points per sprint, median ${e.median}`),P("Sprints",String(e.rows.length),"closed and counted"),"</div>");let o=[{name:"Committed",color:"--s2",values:e.rows.map(s=>s.committed)},{name:"Finished",color:"--s1",values:e.rows.map(s=>s.velocity)}];return t.push(je(o.map(s=>({name:s.name,color:s.color})))),t.push(J(Fe({labels:e.rows.map(s=>s.name),series:o,unit:"points"}),"A committed column taller than its finished one, sprint after sprint, is a team taking in more than it can deliver \u2014 not a team that is slow.")),t.push(q([{head:"Sprint"},{head:"Committed",num:!0},{head:"Finished",num:!0},{head:"Carried over",num:!0}],e.rows.map(s=>`<tr><td>${v(s.name)}</td><td class="num">${s.committed}</td><td class="num">${s.velocity}</td><td class="num">${s.carriedOver}</td></tr>`))),t.push(pe(e.notes)),t.push(z(`${e.rows.length} closed sprint(s).`)),H("kadence velocity",K+U,t)}function Rn(e,n=new Date){let t=[];if(t.push("<h1>Workload</h1>"),t.push(ne([`Open work by owner, as of ${e.asOf} UTC.`,`Work counts as in progress at "${e.started}".`,`Generated ${se(n)}.`],"kadence report workload --html")),e.rows.length===0)return t.push('<p class="empty">Nothing open.</p>'),t.push(z("Nothing open.")),H("kadence workload",K+U,t);let o=i=>i===null?"unassigned":i.split("@")[0]??i,s=e.rows.reduce((i,a)=>i+a.openPoints,0),r=e.rows.find(i=>i.assignee===null);return t.push('<div class="tiles">',P("Open points",String(s),`across ${e.rows.length} owner(s)`),P("Unassigned",String(r?.openPoints??0),r===void 0?"everything has an owner":`points over ${r.open} task(s)`,r!==void 0&&r.openPoints>s/2),"</div>"),t.push(J(Ae({rows:e.rows.map(i=>({name:o(i.assignee),value:i.openPoints,critical:i.assignee===null,note:`${i.open} open, ${i.inProgress} in progress${i.blocked>0?`, ${i.blocked} blocked`:""}`})),unit:"open points"}),"Open points per owner. The unassigned row is drawn in the critical colour and named in the table: work nobody owns is what this report exists to surface.")),t.push(q([{head:"Owner"},{head:"Open",num:!0},{head:"Points",num:!0},{head:"In progress",num:!0},{head:"Blocked",num:!0}],e.rows.map(i=>`<tr class="${i.assignee===null?"critical":""}"><td>${v(i.assignee??"(unassigned)")}</td><td class="num">${i.open}</td><td class="num">${i.openPoints}</td><td class="num">${i.inProgress}</td><td class="num">${i.blocked}</td></tr>`))),t.push(pe(e.notes)),t.push(z(`${s} open points.`)),H("kadence workload",K+U,t)}import{mkdirSync as oo,writeFileSync as ro}from"node:fs";import{dirname as io}from"node:path";function De(e,n,t,o,s){let r=Tt(e,n??t,s);if("exitCode"in r)return r;oo(io(r.full),{recursive:!0});try{ro(r.full,o,"utf8")}catch(i){return y(1,"conflicting_state",`Could not write ${r.full}: ${i.code??"unknown error"}.`,{received:r.rel,hint:s})}return{path:r.full,bytes:Buffer.byteLength(o)}}var Te=["flow","cfd","attention","burndown","velocity","workload"],He=[{name:"flow",answers:"How long work takes, how much is in flight, and what is aging."},{name:"cfd",answers:"Where work piles up: tasks per column at the end of each day."},{name:"attention",answers:"Work in flight that nobody is moving, and why."},{name:"burndown",answers:"Whether a sprint is on track against an even burn."},{name:"velocity",answers:"Committed against completed, sprint by sprint, as a range."},{name:"workload",answers:"Who is carrying what right now, unassigned work included."}],En={team:["attention","flow","cfd"],sprint:["burndown","velocity","workload"]};function Nn(e){let n=He.find(t=>t.name===e);return` ${n.name.padEnd(10)} ${n.answers}`}var Ke=["flow","cfd","attention"],Mn=30,ao=7,On=730;function lo(e,n=Mn){if(e===void 0)return n;let t=/^(\d+)\s*d?$/i.exec(e.trim()),o=t===null?NaN:Number(t[1]);return!Number.isInteger(o)||o<1||o>On?y(2,"invalid_argument",`--since takes a number of days from 1 to ${On}, like 30d, got "${e}".`,{received:e,hint:"kadence report flow --since 30d"}):o}function Ue(e,n){return e===null?"no data":`p50 ${e.p50} \xB7 p85 ${e.p85} \xB7 p95 ${e.p95} ${n} (n=${e.n})`}function co(e){let n=[];if(n.push(`Flow, ${e.window.from} to ${e.window.to} UTC (${e.window.days} calendar days). Work starts at "${e.started}".`),n.push(""),n.push(` In progress now: ${e.wip}`),n.push(` Finished: ${e.finished}`),n.push(` Cycle time: ${Ue(e.cycleTime,"days")}`),n.push(` Lead time: ${Ue(e.leadTime,"days")}`),n.push(` Response time: ${Ue(e.responseTime,"days")}`),e.blocked.tasks>0&&n.push(` Blocked: ${e.blocked.tasks} task(s), ${e.blocked.days} days in total`),e.sle!==null&&n.push("",` ${e.sle}`),e.perWeek.some(t=>t.finished>0||t.created>0)){n.push(""," Week Created Finished");for(let t of e.perWeek)n.push(` ${t.week} ${String(t.created).padStart(7)} ${String(t.finished).padStart(8)}`)}if(e.aging.length>0){n.push(""," Aging work in progress (oldest first):");for(let t of e.aging.slice(0,10)){let o=t.overP85?" \u2190 older than p85":"";n.push(` ${t.label} ${String(t.ageDays).padStart(5)} d ${t.status} ${t.title}${o}`)}e.aging.length>10&&n.push(` \u2026 and ${e.aging.length-10} more`)}if(e.notes.length>0){n.push("");for(let t of e.notes)n.push(` ${t}`)}return n.join(`
|
|
113
|
-
`)}function
|
|
114
|
-
`)}function
|
|
115
|
-
`)}function
|
|
122
|
+
`)}function O(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function h(e){return Number.isFinite(e)?String(Math.round(e*100)/100):"0"}function he(e){if(!Number.isFinite(e)||e<=0)return 1;let n=Math.floor(Math.log10(e)),t=Math.pow(10,n),o=e/t;return(o<=1?1:o<=2?2:o<=5?5:10)*t}function No(e,n,t,o){let s=Math.min(4,t/2,o);return o<=0?"":`M${h(e)},${h(n+o)}L${h(e)},${h(n+s)}Q${h(e)},${h(n)} ${h(e+s)},${h(n)}L${h(e+t-s)},${h(n)}Q${h(e+t)},${h(n)} ${h(e+t)},${h(n+s)}L${h(e+t)},${h(n+o)}Z`}function Mo(e,n,t,o){let s=Math.min(4,o/2,t);return t<=0?"":`M${h(e)},${h(n)}L${h(e+t-s)},${h(n)}Q${h(e+t)},${h(n)} ${h(e+t)},${h(n+s)}L${h(e+t)},${h(n+o-s)}Q${h(e+t)},${h(n+o)} ${h(e+t-s)},${h(n+o)}L${h(e)},${h(n+o)}Z`}function ge(e,n,t,o){return`<svg class="viz" viewBox="0 0 ${e} ${n}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${O(t)}"><title>${O(t)}</title>${o}</svg>`}function Je(e){let t=e.height??220,o={top:12,right:14,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.labels.length),a=s/i,d=he(Math.max(0,...e.series.flatMap(x=>x.values))),l=x=>o.top+r-x/d*r,c=[];for(let x of[0,d/2,d])c.push(`<line class="grid" x1="${o.left}" y1="${h(l(x))}" x2="${h(760-o.right)}" y2="${h(l(x))}"/>`,`<text class="tick" x="${o.left-6}" y="${h(l(x)+3.5)}" text-anchor="end">${h(x)}</text>`);let u=2,m=(a-8-u*(e.series.length-1))/e.series.length,g=Math.min(24,Math.max(2,m)),f=g*e.series.length+u*(e.series.length-1);e.series.forEach((x,k)=>{e.labels.forEach((D,R)=>{let q=x.values[R]??0,y=r-(l(q)-o.top);if(y<=0)return;let N=o.left+R*a+(a-f)/2+k*(g+u);c.push(`<path d="${No(N,l(q),g,y)}" fill="var(${x.color})"><title>${O(D)} \xB7 ${O(x.name)}: ${q} ${O(e.unit)}</title></path>`)})});let S=e.labels.length>8;e.labels.forEach((x,k)=>{let D=k===0||k===e.labels.length-1;if(!(S&&!D)){if(S){let R=k===0?o.left:760-o.right;c.push(`<text class="tick" x="${h(R)}" y="${h(t-10)}" text-anchor="${k===0?"start":"end"}">${O(x)}</text>`);return}c.push(`<text class="tick" x="${h(o.left+k*a+a/2)}" y="${h(t-10)}" text-anchor="middle">${O(x)}</text>`)}});let $=`${e.series.map(x=>x.name).join(" and ")} per period, in ${e.unit}.`;return ge(760,t,$,c.join(""))}function Ln(e){let t=e.height??240,o={top:12,right:104,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.dates.length),a=$=>i===1?o.left+s/2:o.left+$/(i-1)*s,d=e.dates.map(($,x)=>e.bands.reduce((k,D)=>k+(D.values[x]??0),0)),l=he(Math.max(0,...d)),c=$=>o.top+r-$/l*r,u=[];for(let $ of[0,l/2,l])u.push(`<line class="grid" x1="${o.left}" y1="${h(c($))}" x2="${h(760-o.right)}" y2="${h(c($))}"/>`,`<text class="tick" x="${o.left-6}" y="${h(c($)+3.5)}" text-anchor="end">${h($)}</text>`);let m=e.dates.map(()=>0),g=[...e.bands].reverse(),f=[];for(let $ of g){let x=[...m];e.dates.forEach((N,_)=>{m[_]=(m[_]??0)+($.values[_]??0)});let k=e.dates.map((N,_)=>`${h(a(_))},${h(c(m[_]??0))}`),D=e.dates.map((N,_)=>`${h(a(_))},${h(c(x[_]??0))}`).reverse();if(i===1){let N=Math.min(24,s),_=c(x[0]??0)-c(m[0]??0);_>0&&u.push(`<rect x="${h(a(0)-N/2)}" y="${h(c(m[0]??0))}" width="${h(N)}" height="${h(_)}" fill="var(${$.color})"><title>${O($.name)}: ${$.values[0]??0}</title></rect>`);continue}u.push(`<path d="M${k.join("L")}L${D.join("L")}Z" fill="var(${$.color})" fill-opacity="0.9"><title>${O($.name)}</title></path>`,`<polyline class="seam" points="${k.join(" ")}"/>`);let R=e.dates.length-1,q=c(m[R]??0),y=c(x[R]??0);f.push({name:$.name,y:(q+y)/2,height:y-q})}let S=Number.NEGATIVE_INFINITY;for(let $ of[...f].sort((x,k)=>x.y-k.y))$.height<10||$.y-S<13||(S=$.y,u.push(`<text class="tick" x="${h(760-o.right+10)}" y="${h($.y+3.5)}">${O($.name)}</text>`));return e.dates.forEach(($,x)=>{(x===0||x===e.dates.length-1)&&u.push(`<text class="tick" x="${h(a(x))}" y="${h(t-10)}" text-anchor="${x===0?"start":"end"}">${O($)}</text>`)}),ge(760,t,`Tasks per column per day, ${e.bands.map($=>$.name).join(", ")}.`,u.join(""))}function Oe(e){let o={top:8,right:52,bottom:26,left:92},s=o.top+o.bottom+Math.max(1,e.rows.length)*26,r=760-o.left-o.right,i=he(Math.max(e.reference?.value??0,...e.rows.map(l=>l.value))),a=l=>o.left+l/i*r,d=[];return d.push(`<line class="grid" x1="${o.left}" y1="${o.top}" x2="${o.left}" y2="${h(s-o.bottom)}"/>`),e.rows.forEach((l,c)=>{let u=o.top+c*26,m=Math.min(14,16),g=a(l.value)-o.left,f=l.critical===!0?"var(--critical)":"var(--s1)";d.push(`<text class="tick mono" x="${o.left-8}" y="${h(u+m/2+8)}" text-anchor="end">${O(l.name)}</text>`,`<path d="${Mo(o.left,u+5,Math.max(g,1),m)}" fill="${f}"><title>${O(l.name)}: ${l.value} ${O(e.unit)}${l.note===void 0?"":` \xB7 ${O(l.note)}`}</title></path>`,`<text class="tick" x="${h(a(l.value)+6)}" y="${h(u+m/2+8)}">${l.value}</text>`)}),e.reference!==void 0&&e.reference.value>0&&d.push(`<line class="reference" x1="${h(a(e.reference.value))}" y1="${o.top}" x2="${h(a(e.reference.value))}" y2="${h(s-o.bottom+4)}"/>`,`<text class="tick" x="${h(a(e.reference.value))}" y="${h(s-10)}" text-anchor="middle">${O(e.reference.label)}</text>`),ge(760,s,`${e.rows.length} rows, in ${e.unit}.`,d.join(""))}function Wn(e,n){let s={top:10,right:20,bottom:26,left:92},r=s.top+s.bottom+Math.max(1,e.length)*44,i=760-s.left-s.right,a=he(Math.max(1,...e.map(c=>c.p95))),d=c=>s.left+c/a*i,l=[];for(let c of[0,a/2,a])l.push(`<line class="grid" x1="${h(d(c))}" y1="${s.top}" x2="${h(d(c))}" y2="${h(r-s.bottom+2)}"/>`,`<text class="tick" x="${h(d(c))}" y="${h(r-10)}" text-anchor="middle">${h(c)}</text>`);return e.forEach((c,u)=>{let m=s.top+u*44+22-4;l.push(`<text class="tick" x="${s.left-8}" y="${h(m+4)}" text-anchor="end">${O(c.name)}</text>`,`<line class="range" x1="${h(d(c.p50))}" y1="${h(m)}" x2="${h(d(c.p95))}" y2="${h(m)}"/>`);for(let[g,f,S]of[["p50",c.p50,4.5],["p85",c.p85,6],["p95",c.p95,4.5]])l.push(`<circle class="dot" cx="${h(d(f))}" cy="${h(m)}" r="${S}"><title>${O(c.name)} ${g}: ${f} ${O(n)} (n=${c.n})</title></circle>`);l.push(`<text class="tick" x="${h(d(c.p85))}" y="${h(m-12)}" text-anchor="middle">p85 = ${c.p85}</text>`)}),ge(760,r,`p50, p85 and p95 per measure, in ${n}.`,l.join(""))}function Bn(e){let t=e.height??230,o={top:12,right:60,bottom:30,left:38},s=760-o.left-o.right,r=t-o.top-o.bottom,i=Math.max(1,e.labels.length),a=u=>i===1?o.left+s/2:o.left+u/(i-1)*s,d=he(Math.max(0,...e.series.flatMap(u=>u.values))),l=u=>o.top+r-u/d*r,c=[];for(let u of[0,d/2,d])c.push(`<line class="grid" x1="${o.left}" y1="${h(l(u))}" x2="${h(760-o.right)}" y2="${h(l(u))}"/>`,`<text class="tick" x="${o.left-6}" y="${h(l(u)+3.5)}" text-anchor="end">${h(u)}</text>`);for(let u of e.series){let m=u.values.map(($,x)=>`${h(a(x))},${h(l($))}`).join("L"),g=u.reference===!0;c.push(`<path class="line${g?" reference-line":""}" d="M${m}" ${g?"":`stroke="var(${u.color})"`}><title>${O(u.name)}, ${O(e.unit)}</title></path>`);let f=u.values.length-1,S=u.values[f];!g&&S!==void 0&&c.push(`<circle class="dot" cx="${h(a(f))}" cy="${h(l(S))}" r="4.5" fill="var(${u.color})"/>`,`<text class="tick" x="${h(a(f)+9)}" y="${h(l(S)+3.5)}">${S}</text>`)}return e.labels.forEach((u,m)=>{m!==0&&m!==e.labels.length-1||c.push(`<text class="tick" x="${h(a(m))}" y="${h(t-10)}" text-anchor="${m===0?"start":"end"}">${O(u)}</text>`)}),ge(760,t,`${e.series.map(u=>u.name).join(" against ")}, in ${e.unit}.`,c.join(""))}var ke=["--s1","--s2","--s3","--s4","--s5","--s6","--s7","--s8"];function re(e,n){return`<p class="stamp">${e.map(v).join(" ")} A file, not a page: nothing here is live, and regenerating it is <code>${v(n)}</code>.</p>`}function P(e,n,t,o=!1){return`<div class="tile${o?" critical":""}"><div class="label">${v(e)}</div><div class="value">${v(n)}</div><div class="sub">${v(t)}</div></div>`}function Ne(e){return'<div class="legend">'+e.map(n=>`<span><i style="background:var(${n.color})"></i>${v(n.name)}</span>`).join("")+"</div>"}function G(e,n){return`<figure class="figure">${e}<figcaption>${v(n)}</figcaption></figure>`}function V(e,n){return`<div class="rows"><table><tr>${e.map(o=>`<th${o.num===!0?' class="num"':""}>${v(o.head)}</th>`).join("")}</tr>${n.join("")}</table></div>`}function be(e){return e.length===0?"":e.map(n=>`<p class="empty">${v(n)}</p>`).join("")}function J(e){return`<footer>${v(e)} Folded from the event journal by kadence. No server, no network.</footer>`}function ie(e){return`${e.toISOString().slice(0,16).replace("T"," ")} UTC`}function Kn(e,n=new Date){let t=[];t.push("<h1>Flow</h1>"),t.push(re([`${e.window.from} to ${e.window.to} UTC, ${e.window.days} calendar days.`,`Work counts as started at "${e.started}".`,`Generated ${ie(n)}.`],"kadence report flow --html"));let o=e.cycleTime===null?"\u2014":String(e.cycleTime.p85);t.push('<div class="tiles">',P("In progress now",String(e.wip),"tasks past the started boundary"),P("Finished",String(e.finished),`in ${e.window.days} calendar days`),P("Cycle time p85",o,e.cycleTime===null?"nothing finished yet":`calendar days, n=${e.cycleTime.n}`),P("Blocked",String(e.blocked.days),e.blocked.tasks===0?"no blocked time in the window":`days across ${e.blocked.tasks} task(s)`,e.blocked.tasks>0),"</div>"),e.sle!==null&&t.push(`<p class="callout">${v(e.sle)}</p>`);let r=[{name:"Cycle time",p:e.cycleTime},{name:"Lead time",p:e.leadTime},{name:"Response time",p:e.responseTime}].filter(i=>i.p!==null);if(t.push("<h2>How long work takes</h2>"),r.length===0?t.push('<p class="empty">Nothing has finished in this window, so there is nothing to measure.</p>'):(t.push(G(Wn(r.map(i=>({name:i.name,p50:i.p.p50,p85:i.p.p85,p95:i.p.p95,n:i.p.n})),"calendar days"),"p50, p85 and p95 in calendar days. Percentiles, never a mean \u2014 the tail is the part worth managing.")),t.push(V([{head:"Measure"},{head:"p50",num:!0},{head:"p85",num:!0},{head:"p95",num:!0},{head:"n",num:!0}],r.map(i=>`<tr><td>${v(i.name)}</td><td class="num">${i.p.p50}</td><td class="num">${i.p.p85}</td><td class="num">${i.p.p95}</td><td class="num">${i.p.n}</td></tr>`)))),t.push("<h2>Created and finished, per week</h2>"),e.perWeek.length===0)t.push('<p class="empty">No weeks in this window carry either.</p>');else{let i=[{name:"Created",color:"--s2",values:e.perWeek.map(a=>a.created)},{name:"Finished",color:"--s1",values:e.perWeek.map(a=>a.finished)}];t.push(Ne(i.map(a=>({name:a.name,color:a.color})))),t.push(G(Je({labels:e.perWeek.map(a=>a.week),series:i,unit:"tasks"}),"One band per week, labelled by its Monday. More created than finished, week after week, is a queue growing.")),t.push("<details><summary>Every week as rows</summary>",V([{head:"Week of"},{head:"Created",num:!0},{head:"Finished",num:!0}],e.perWeek.map(a=>`<tr><td>${v(a.week)}</td><td class="num">${a.created}</td><td class="num">${a.finished}</td></tr>`)),"</details>")}if(t.push("<h2>Aging work in progress</h2>"),e.aging.length===0)t.push('<p class="empty">Nothing is in progress.</p>');else{let i=e.aging.slice(0,15);t.push(G(Oe({rows:i.map(a=>({name:a.label,value:a.ageDays,critical:a.overP85,note:`${a.status} \xB7 ${a.title}`})),unit:"calendar days",...e.cycleTime===null?{}:{reference:{value:e.cycleTime.p85,label:`p85 = ${e.cycleTime.p85} d`}}}),e.cycleTime===null?"Age in calendar days, oldest first.":"Age in calendar days, oldest first. The line is the p85 cycle time: work to its right has already taken longer than 85% of what finished.")),t.push(V([{head:"Task"},{head:"Age",num:!0},{head:"Status"},{head:"Title"}],i.map(a=>`<tr class="${a.overP85?"critical":""}"><td>${v(a.label)}</td><td class="num">${a.ageDays}</td><td>${v(a.status)}</td><td>${v(a.title)}${a.overP85?' <span class="pill danger">older than p85</span>':""}</td></tr>`))),e.aging.length>i.length&&t.push(`<p class="empty">\u2026 and ${e.aging.length-i.length} more. The --json response carries every row.</p>`)}return t.push(be(e.notes)),t.push(J(`${e.finished} finished, ${e.wip} in progress.`)),H("kadence flow",F+U,t)}function Fn(e,n=new Date){let t=[];if(t.push("<h1>Cumulative flow</h1>"),t.push(re([`${e.window.from} to ${e.window.to} UTC, ${e.window.days} calendar days.`,"Tasks per column at the end of each day.",`Generated ${ie(n)}.`],"kadence report cfd --html")),e.statuses.length===0||e.days.length===0)return t.push('<p class="empty">No columns to draw yet.</p>'),t.push(J("Nothing in the window.")),H("kadence cumulative flow",F+U,t);let o=e.statuses.slice(0,ke.length),s=e.statuses.slice(ke.length),r=o.map((a,d)=>({name:a,color:ke[d],values:e.days.map(l=>l.counts[a]??0)}));s.length>0&&r.push({name:`Other (${s.length} columns)`,color:ke[ke.length-1],values:e.days.map(a=>s.reduce((d,l)=>d+(a.counts[l]??0),0))}),t.push(Ne(r.map(a=>({name:a.name,color:a.color})))),t.push(G(Ln({dates:e.days.map(a=>a.date),bands:r}),"Bands stack in board order, finished work at the baseline. A band that widens is a queue; the height between two lines is the work sitting in that column."));let i=[{head:"Date"},...r.map(a=>({head:a.name,num:!0}))];return t.push("<details><summary>Every day as rows</summary>",V(i,e.days.map(a=>{let d=o.map(c=>`<td class="num">${a.counts[c]??0}</td>`).join(""),l=s.length===0?"":`<td class="num">${s.reduce((c,u)=>c+(a.counts[u]??0),0)}</td>`;return`<tr><td>${v(a.date)}</td>${d}${l}</tr>`})),"</details>"),t.push(J(`${e.days.length} days, ${e.statuses.length} columns.`)),H("kadence cumulative flow",F+U,t)}function Un(e,n=new Date){let t=[];if(t.push("<h1>Attention</h1>"),t.push(re([`As of ${e.asOf} UTC.`,`Work past "${e.started}" that nobody is moving \u2014 silent or ownerless for ${e.threshold} days or more, or blocked by work that is already done.`,`Generated ${ie(n)}.`],"kadence report attention --html")),t.push('<div class="tiles">',P("Needs attention",String(e.rows.length),e.rows.length===0?"nothing is stuck":"of the work in flight",e.rows.length>0),P("Threshold",`${e.threshold} d`,"silence before a task counts as stalled"),"</div>"),e.rows.length===0)t.push('<p class="empty">Nothing is stalled, unowned, claimed and forgotten, or waiting on work that is already done.</p>');else{let o=e.rows.slice(0,20);t.push(G(Oe({rows:o.map(s=>({name:s.label,value:s.idleDays,critical:s.idleDays>=e.threshold*2,note:`${s.status} \xB7 ${s.title}`})),unit:"days of silence",reference:{value:e.threshold,label:`${e.threshold} d`}}),`Days since the task last moved. The line is the ${e.threshold}-day threshold; everything here is already past it, and a bar turns critical past twice it.`)),t.push(V([{head:"Task"},{head:"Idle",num:!0},{head:"Status"},{head:"Why it is here"}],o.map(s=>`<tr class="${s.idleDays>=e.threshold*2?"critical":""}"><td>${v(s.label)}</td><td class="num">${s.idleDays}</td><td>${v(s.status)}</td><td>${v(s.title)}<div class="sub">${v(s.signals.map(oe).join(" \xB7 "))}</div></td></tr>`))),e.rows.length>o.length&&t.push(`<p class="empty">\u2026 and ${e.rows.length-o.length} more. The --json response carries every row.</p>`)}return t.push(be(e.notes)),t.push(J(`${e.rows.length} needing attention.`)),H("kadence attention",F+U,t)}function Hn(e,n=new Date){let t=[];if(t.push("<h1>Burndown</h1>"),t.push(re([`${v(e.sprintName)}: ${e.committed} points committed.`,e.finalRemaining===null?"The sprint is still open, so the last day is today rather than the end.":`Closed with ${e.finalRemaining} point(s) unfinished.`,`Generated ${ie(n)}.`],"kadence report burndown --html")),e.committed===0||e.days.length===0)return t.push('<p class="empty">Nothing to burn down: no task in this sprint carries an estimate.</p>'),t.push(J(`${e.sprintName}, ${e.days.length} days.`)),H("kadence burndown",F+U,t);let o=e.days[e.days.length-1],s=o.remaining<=o.ideal;return t.push('<div class="tiles">',P("Committed",String(e.committed),"points taken into the sprint"),P("Remaining",String(o.remaining),`of ${e.committed}, on ${o.date}`,!s),P("Against the ideal",`${s?"\u2212":"+"}${Math.abs(Math.round(o.remaining-o.ideal))}`,s?"points ahead of an even burn":"points behind an even burn",!s),"</div>"),t.push(Ne([{name:"Remaining",color:"--s1"},{name:"An even burn",color:"--muted"}])),t.push(G(Bn({labels:e.days.map(r=>r.date),series:[{name:"An even burn",color:"--muted",values:e.days.map(r=>Math.round(r.ideal*10)/10),reference:!0},{name:"Remaining",color:"--s1",values:e.days.map(r=>r.remaining)}],unit:"points"}),"Points still open at the end of each day. The muted line is where a perfectly even burn would have been \u2014 an expectation, not a measurement.")),t.push("<details><summary>Every day as rows</summary>",V([{head:"Date"},{head:"Remaining",num:!0},{head:"Even burn",num:!0},{head:"Finished that day",num:!0}],e.days.map(r=>`<tr><td>${v(r.date)}</td><td class="num">${r.remaining}</td><td class="num">${Math.round(r.ideal*10)/10}</td><td class="num">${r.completed}</td></tr>`)),"</details>"),t.push(J(`${e.sprintName}, ${e.days.length} days, ${e.committed} points.`)),H("kadence burndown",F+U,t)}function zn(e,n=new Date){let t=[];if(t.push("<h1>Velocity</h1>"),t.push(re(["Points taken into a sprint against points finished, oldest first.",`Generated ${ie(n)}.`],"kadence report velocity --html")),e.rows.length===0)return t.push('<p class="empty">No closed sprint yet. Velocity is what a finished sprint leaves behind.</p>'),t.push(be(e.notes)),t.push(J("No sprints closed.")),H("kadence velocity",F+U,t);t.push('<div class="tiles">',P("Finished",`${e.low}\u2013${e.high}`,`points per sprint, median ${e.median}`),P("Sprints",String(e.rows.length),"closed and counted"),"</div>");let o=[{name:"Committed",color:"--s2",values:e.rows.map(s=>s.committed)},{name:"Finished",color:"--s1",values:e.rows.map(s=>s.velocity)}];return t.push(Ne(o.map(s=>({name:s.name,color:s.color})))),t.push(G(Je({labels:e.rows.map(s=>s.name),series:o,unit:"points"}),"A committed column taller than its finished one, sprint after sprint, is a team taking in more than it can deliver \u2014 not a team that is slow.")),t.push(V([{head:"Sprint"},{head:"Committed",num:!0},{head:"Finished",num:!0},{head:"Carried over",num:!0}],e.rows.map(s=>`<tr><td>${v(s.name)}</td><td class="num">${s.committed}</td><td class="num">${s.velocity}</td><td class="num">${s.carriedOver}</td></tr>`))),t.push(be(e.notes)),t.push(J(`${e.rows.length} closed sprint(s).`)),H("kadence velocity",F+U,t)}function Yn(e,n=new Date){let t=[];if(t.push("<h1>Workload</h1>"),t.push(re([`Open work by owner, as of ${e.asOf} UTC.`,`Work counts as in progress at "${e.started}".`,`Generated ${ie(n)}.`],"kadence report workload --html")),e.rows.length===0)return t.push('<p class="empty">Nothing open.</p>'),t.push(J("Nothing open.")),H("kadence workload",F+U,t);let o=i=>i===null?"unassigned":i.split("@")[0]??i,s=e.rows.reduce((i,a)=>i+a.openPoints,0),r=e.rows.find(i=>i.assignee===null);return t.push('<div class="tiles">',P("Open points",String(s),`across ${e.rows.length} owner(s)`),P("Unassigned",String(r?.openPoints??0),r===void 0?"everything has an owner":`points over ${r.open} task(s)`,r!==void 0&&r.openPoints>s/2),"</div>"),t.push(G(Oe({rows:e.rows.map(i=>({name:o(i.assignee),value:i.openPoints,critical:i.assignee===null,note:`${i.open} open, ${i.inProgress} in progress${i.blocked>0?`, ${i.blocked} blocked`:""}`})),unit:"open points"}),"Open points per owner. The unassigned row is drawn in the critical colour and named in the table: work nobody owns is what this report exists to surface.")),t.push(V([{head:"Owner"},{head:"Open",num:!0},{head:"Points",num:!0},{head:"In progress",num:!0},{head:"Blocked",num:!0}],e.rows.map(i=>`<tr class="${i.assignee===null?"critical":""}"><td>${v(i.assignee??"(unassigned)")}</td><td class="num">${i.open}</td><td class="num">${i.openPoints}</td><td class="num">${i.inProgress}</td><td class="num">${i.blocked}</td></tr>`))),t.push(be(e.notes)),t.push(J(`${s} open points.`)),H("kadence workload",F+U,t)}import{mkdirSync as _o,writeFileSync as Po}from"node:fs";import{dirname as Io}from"node:path";function Me(e,n,t,o,s){let r=_t(e,n??t,s);if("exitCode"in r)return r;_o(Io(r.full),{recursive:!0});try{Po(r.full,o,"utf8")}catch(i){return b(1,"conflicting_state",`Could not write ${r.full}: ${i.code??"unknown error"}.`,{received:r.rel,hint:s})}return{path:r.full,bytes:Buffer.byteLength(o)}}var _e=["flow","cfd","attention","burndown","velocity","workload"],Ve=[{name:"flow",answers:"How long work takes, how much is in flight, and what is aging."},{name:"cfd",answers:"Where work piles up: tasks per column at the end of each day."},{name:"attention",answers:"Work in flight that nobody is moving, and why."},{name:"burndown",answers:"Whether a sprint is on track against an even burn."},{name:"velocity",answers:"Committed against completed, sprint by sprint, as a range."},{name:"workload",answers:"Who is carrying what right now, unassigned work included."}],Jn={team:["attention","flow","cfd"],sprint:["burndown","velocity","workload"]};function qn(e){let n=Ve.find(t=>t.name===e);return` ${n.name.padEnd(10)} ${n.answers}`}var qe=["flow","cfd","attention"],Vn=30,Lo=7,Gn=730;function Wo(e,n=Vn){if(e===void 0)return n;let t=/^(\d+)\s*d?$/i.exec(e.trim()),o=t===null?NaN:Number(t[1]);return!Number.isInteger(o)||o<1||o>Gn?b(2,"invalid_argument",`--since takes a number of days from 1 to ${Gn}, like 30d, got "${e}".`,{received:e,hint:"kadence report flow --since 30d"}):o}function Ge(e,n){return e===null?"no data":`p50 ${e.p50} \xB7 p85 ${e.p85} \xB7 p95 ${e.p95} ${n} (n=${e.n})`}function Bo(e){let n=[];if(n.push(`Flow, ${e.window.from} to ${e.window.to} UTC (${e.window.days} calendar days). Work starts at "${e.started}".`),n.push(""),n.push(` In progress now: ${e.wip}`),n.push(` Finished: ${e.finished}`),n.push(` Cycle time: ${Ge(e.cycleTime,"days")}`),n.push(` Lead time: ${Ge(e.leadTime,"days")}`),n.push(` Response time: ${Ge(e.responseTime,"days")}`),e.blocked.tasks>0&&n.push(` Blocked: ${e.blocked.tasks} task(s), ${e.blocked.days} days in total`),e.sle!==null&&n.push("",` ${e.sle}`),e.perWeek.some(t=>t.finished>0||t.created>0)){n.push(""," Week Created Finished");for(let t of e.perWeek)n.push(` ${t.week} ${String(t.created).padStart(7)} ${String(t.finished).padStart(8)}`)}if(e.aging.length>0){n.push(""," Aging work in progress (oldest first):");for(let t of e.aging.slice(0,10)){let o=t.overP85?" \u2190 older than p85":"";n.push(` ${t.label} ${String(t.ageDays).padStart(5)} d ${t.status} ${t.title}${o}`)}e.aging.length>10&&n.push(` \u2026 and ${e.aging.length-10} more`)}if(e.notes.length>0){n.push("");for(let t of e.notes)n.push(` ${t}`)}return n.join(`
|
|
123
|
+
`)}function Ko(e){let n=[];n.push(`Cumulative flow, ${e.window.from} to ${e.window.to} UTC. Tasks per column at the end of each day.`),n.push("");let t=e.statuses,o=Math.max(6,...t.map(r=>r.length));n.push(` ${"date".padEnd(10)} ${t.map(r=>r.padStart(o)).join(" ")}`);let s=e.days.filter((r,i)=>i%7===0||i===e.days.length-1);for(let r of s)n.push(` ${r.date} ${t.map(i=>String(r.counts[i]??0).padStart(o)).join(" ")}`);return s.length<e.days.length&&n.push("",` ${e.days.length} days in the window; one row per week shown. --json carries every day.`),n.join(`
|
|
124
|
+
`)}function Fo(e){let n=[];if(n.push(`Attention, as of ${e.asOf} UTC. Work past "${e.started}" that nobody is moving \u2014 silent or ownerless for ${e.threshold} days or more, or blocked by work that is already done.`),e.rows.length>0){n.push("");for(let t of e.rows.slice(0,15))n.push(` ${t.label} ${String(t.idleDays).padStart(4)} d ${t.title}`),n.push(` ${t.signals.map(oe).join(" \xB7 ")}`);e.rows.length>15&&n.push(` \u2026 and ${e.rows.length-15} more`)}if(e.notes.length>0){n.push("");for(let t of e.notes)n.push(` ${t}`)}return n.join(`
|
|
125
|
+
`)}function Uo(e){let n=[];if(n.push("Velocity, oldest first. Points taken into a sprint against points finished."),e.rows.length===0){n.push(""," No closed sprint yet.");for(let o of e.notes)n.push(` ${o}`);return n.join(`
|
|
116
126
|
`)}n.push("");let t=Math.max(8,...e.rows.map(o=>o.name.length));n.push(` ${"Sprint".padEnd(t)} Committed Finished Carried`);for(let o of e.rows)n.push(` ${o.name.padEnd(t)} ${String(o.committed).padStart(9)} ${String(o.velocity).padStart(8)} ${String(o.carriedOver).padStart(7)}`);n.push("",` Finished: ${e.low} to ${e.high} points, median ${e.median}, over ${e.rows.length} sprint(s).`);for(let o of e.notes)n.push(` ${o}`);return n.join(`
|
|
117
|
-
`)}function
|
|
127
|
+
`)}function Ho(e){let n=[];if(n.push(`Open work by owner, as of ${e.asOf} UTC. Work counts as in progress at "${e.started}".`),e.rows.length===0)return n.push(""," Nothing open."),n.join(`
|
|
118
128
|
`);n.push("");let t=s=>s??"(unassigned)",o=Math.max(10,...e.rows.map(s=>t(s.assignee).length));n.push(` ${"Owner".padEnd(o)} Open Points Doing Blocked`);for(let s of e.rows)n.push(` ${t(s.assignee).padEnd(o)} ${String(s.open).padStart(4)} ${String(s.openPoints).padStart(6)} ${String(s.inProgress).padStart(5)} ${String(s.blocked).padStart(7)}`);e.notes.length>0&&n.push("");for(let s of e.notes)n.push(` ${s}`);return n.join(`
|
|
119
|
-
`)}function
|
|
120
|
-
`),data:{schema:"kadence/v1",ok:!0,reports:
|
|
121
|
-
`),{...t===void 0?{}:{received:t},allowed:
|
|
122
|
-
It applies to ${
|
|
123
|
-
kadence sprint add KAD-1`,data:{schema:"kadence/v1",ok:!0,report:t,burndown:null}};l={data:{burndown:m},message:
|
|
124
|
-
Open it from disk \u2014 there is no server, and the page makes no requests.`,data:{schema:"kadence/v1",ok:!0,report:t,format:"html",path:c.path,bytes:c.bytes}}}return{ok:!0,exitCode:0,warnings:d,message:l.message,data:{schema:"kadence/v1",ok:!0,report:t,...l.data}}}import{existsSync as
|
|
129
|
+
`)}function Zn(e,n,t,o,s=new Date){if(o.list===!0)return{ok:!0,exitCode:0,warnings:[],message:["Reports, each a fold over the journal:","",...Jn.team.map(qn),"","Sprint and team:",...Jn.sprint.map(qn),"","Each takes --json, and --html to write it as a page with charts."," kadence report flow --html"].join(`
|
|
130
|
+
`),data:{schema:"kadence/v1",ok:!0,reports:Ve}};if(t===void 0||!_e.includes(t))return b(2,"invalid_argument",["Which report?",...Ve.map(c=>` kadence report ${c.name.padEnd(10)} ${c.answers}`)].join(`
|
|
131
|
+
`),{...t===void 0?{}:{received:t},allowed:_e,hint:"kadence report flow"});if(o.since!==void 0&&!qe.includes(t))return b(2,"invalid_argument",`--since is a window, and ${t} does not have one.
|
|
132
|
+
It applies to ${qe.join(", ")}.`,{received:o.since,allowed:qe,hint:`kadence report ${t}`});if(o.sprint!==void 0&&t!=="burndown")return b(2,"invalid_argument",`--sprint applies to burndown, not to ${t}.`,{received:o.sprint,hint:'kadence report burndown --sprint "Sprint 3"'});let r=Wo(o.since,t==="attention"?Lo:Vn);if(typeof r!="number")return r;let i=C(e,n);if(!j(i))return i;let{state:a,warnings:d}=A(i.root,i.actor),l;if(t==="attention"){let c=Re(a,s,r);l={data:c,message:Fo(c),html:()=>Un(c,s)}}else if(t==="cfd"){let c=xt(a,s,r);l={data:c,message:Ko(c),html:()=>Fn(c,s)}}else if(t==="burndown"){let c=tn(i.root,a,o.sprint);if("exitCode"in c)return c;let{sprint:u,chart:m}=c;if(m===null)return{ok:!0,exitCode:0,warnings:d,message:`"${u.name}" has no tasks yet.
|
|
133
|
+
kadence sprint add KAD-1`,data:{schema:"kadence/v1",ok:!0,report:t,burndown:null}};l={data:{burndown:m},message:Jt(m),html:()=>Hn(m,s)}}else if(t==="velocity"){let c=zt(a);l={data:c,message:Uo(c),html:()=>zn(c,s)}}else if(t==="workload"){let c=In(a,s);l={data:c,message:Ho(c),html:()=>Yn(c,s)}}else{let c=vt(a,s,r);l={data:c,message:Bo(c),html:()=>Kn(c,s)}}if(o.html===!0){let c=Me(i.root,o.file,`kadence-${t}.html`,l.html(),`kadence report ${t} --html --file docs/${t}.html`);return"exitCode"in c?c:{ok:!0,exitCode:0,warnings:d,message:`Wrote ${c.path}.
|
|
134
|
+
Open it from disk \u2014 there is no server, and the page makes no requests.`,data:{schema:"kadence/v1",ok:!0,report:t,format:"html",path:c.path,bytes:c.bytes}}}return{ok:!0,exitCode:0,warnings:d,message:l.message,data:{schema:"kadence/v1",ok:!0,report:t,...l.data}}}import{existsSync as zo,mkdirSync as Yo,readFileSync as Jo,writeFileSync as qo}from"node:fs";import{homedir as Go}from"node:os";import{dirname as Qn,join as Ze}from"node:path";var Pe="# kadence completion",ae=["zsh","bash","fish"];function Vo(e){return ae.includes(e)}var Qe=[["init","Set up kadence in this repository"],["prime","Everything a session needs before it starts"],["ready","What can be started right now"],["task","Tasks: add, list, show, move, claim, ac"],["board","Kanban board in the terminal"],["sprint","Sprints: create, start, close, status"],["milestone","Milestones: create, add, list, close"],["decision","Decisions: add, list, show"],["note","Record something learned"],["stats","Where the project stands"],["template","Task templates: save, list, delete"],["schema","The machine-readable --json contract"],["completion","Shell completion"],["ui","The interactive board"]],Xe=["add","list","show","edit","move","assign","comment","log","parent","block","unblock","claim","release","ac","doc","cancel","delete"];function Zo(e){let n=Qe.map(([t])=>t).join(" ");return e==="fish"?`${[`${Pe} for fish`,"complete -c kadence -f",...Qe.map(([o,s])=>`complete -c kadence -n "not __fish_seen_subcommand_from ${n}" -a ${o} -d '${s.replace(/'/g,"")}'`),`complete -c kadence -n "__fish_seen_subcommand_from task" -a "${Xe.join(" ")}"`,"complete -c kadence -l json -d 'Machine-readable output for agents'"].join(`
|
|
125
135
|
`)}
|
|
126
|
-
`:e==="bash"?`${
|
|
136
|
+
`:e==="bash"?`${Pe} for bash
|
|
127
137
|
_kadence() {
|
|
128
138
|
local cur prev
|
|
129
139
|
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
@@ -134,7 +144,7 @@ _kadence() {
|
|
|
134
144
|
return
|
|
135
145
|
fi
|
|
136
146
|
case "$prev" in
|
|
137
|
-
task) COMPREPLY=( $(compgen -W "${
|
|
147
|
+
task) COMPREPLY=( $(compgen -W "${Xe.join(" ")}" -- "$cur") ) ;;
|
|
138
148
|
sprint) COMPREPLY=( $(compgen -W "create add edit start close status list burndown" -- "$cur") ) ;;
|
|
139
149
|
milestone) COMPREPLY=( $(compgen -W "create add list close" -- "$cur") ) ;;
|
|
140
150
|
decision) COMPREPLY=( $(compgen -W "add list show" -- "$cur") ) ;;
|
|
@@ -144,12 +154,12 @@ _kadence() {
|
|
|
144
154
|
}
|
|
145
155
|
complete -F _kadence kadence
|
|
146
156
|
`:`#compdef kadence
|
|
147
|
-
${
|
|
157
|
+
${Pe} for zsh
|
|
148
158
|
|
|
149
159
|
_kadence() {
|
|
150
160
|
local -a commands
|
|
151
161
|
commands=(
|
|
152
|
-
${
|
|
162
|
+
${Qe.map(([t,o])=>` '${t}:${o.replace(/'/g,"")}'`).join(`
|
|
153
163
|
`)}
|
|
154
164
|
)
|
|
155
165
|
|
|
@@ -159,7 +169,7 @@ ${Ye.map(([t,o])=>` '${t}:${o.replace(/'/g,"")}'`).join(`
|
|
|
159
169
|
fi
|
|
160
170
|
|
|
161
171
|
case "\${words[2]}" in
|
|
162
|
-
task) _values 'action' ${
|
|
172
|
+
task) _values 'action' ${Xe.join(" ")} ;;
|
|
163
173
|
sprint) _values 'action' create add edit start close status list burndown ;;
|
|
164
174
|
milestone) _values 'action' create add list close ;;
|
|
165
175
|
decision) _values 'action' add list show ;;
|
|
@@ -169,49 +179,51 @@ ${Ye.map(([t,o])=>` '${t}:${o.replace(/'/g,"")}'`).join(`
|
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
_kadence "$@"
|
|
172
|
-
`}function
|
|
182
|
+
`}function Qo(e,n){return e==="fish"?Ze(n,".config","fish","completions","kadence.fish"):e==="bash"?Ze(n,".local","share","bash-completion","completions","kadence"):Ze(n,".zsh","completions","_kadence")}function Xo(e){let n=e.SHELL??"";for(let t of ae)if(n.endsWith(`/${t}`)||n===t)return t;return null}function Xn(e,n){let t;if(n.shell!==void 0){if(!Vo(n.shell))return b(2,"invalid_argument",`kadence has no completion for "${n.shell}".`,{received:n.shell,allowed:ae,hint:"kadence completion install --shell zsh"});t=n.shell}else{let i=Xo(e);if(i===null)return b(2,"invalid_argument",`Could not tell which shell you use from $SHELL.
|
|
173
183
|
Name it:
|
|
174
|
-
kadence completion install --shell zsh`,{allowed:
|
|
184
|
+
kadence completion install --shell zsh`,{allowed:ae,hint:"kadence completion install --shell zsh"});t=i}let o=Zo(t);if(n.install!==!0||n.isTty===!1)return{ok:!0,exitCode:0,message:o,data:{schema:"kadence/v1",ok:!0,shell:t,script:o}};let s=Qo(t,n.home??Go());if(zo(s)){let i=Jo(s,"utf8");if(i===o)return{ok:!0,exitCode:0,message:`Completion for ${t} is already installed at ${s}.`,data:{schema:"kadence/v1",ok:!0,shell:t,path:s,written:!1}};if(!i.includes(Pe)&&n.force!==!0)return b(1,"conflicting_state",`${s} exists and was not written by kadence.
|
|
175
185
|
Nothing was changed. Look at it, then either move it or run:
|
|
176
|
-
kadence completion install --shell ${t} --force`,{received:s,hint:`kadence completion install --shell ${t} --force`})}
|
|
186
|
+
kadence completion install --shell ${t} --force`,{received:s,hint:`kadence completion install --shell ${t} --force`})}Yo(Qn(s),{recursive:!0}),qo(s,o,"utf8");let r=t==="zsh"?`
|
|
177
187
|
zsh loads completions from fpath, which is yours to set. Add to ~/.zshrc:
|
|
178
|
-
fpath=(${
|
|
188
|
+
fpath=(${Qn(s)} $fpath)
|
|
179
189
|
autoload -Uz compinit && compinit`:`
|
|
180
|
-
Open a new shell, or reload it, and it will be picked up.`;return{ok:!0,exitCode:0,message:`Wrote ${t} completion to ${s}.${r}`,data:{schema:"kadence/v1",ok:!0,shell:t,path:s,written:!0}}}var
|
|
190
|
+
Open a new shell, or reload it, and it will be picked up.`;return{ok:!0,exitCode:0,message:`Wrote ${t} completion to ${s}.${r}`,data:{schema:"kadence/v1",ok:!0,shell:t,path:s,written:!0}}}var es=`A note records something learned. When there was a choice and something was
|
|
181
191
|
turned down, record it as a decision instead:
|
|
182
|
-
kadence decision add "title" --why "reason"`;function
|
|
192
|
+
kadence decision add "title" --why "reason"`;function er(e,n){return{id:e.id,text:e.text,task:n(e.task),at:e.at,by:e.by,source:e.source}}function ts(e,n,t,o){let s=C(e,n);if(!j(s))return s;let r=t.trim();if(r.length===0)return b(2,"invalid_argument",`A note needs text.
|
|
183
193
|
|
|
184
|
-
${
|
|
194
|
+
${es}`,{hint:'kadence note "Tests need a git identity"'});let{state:i,warnings:a}=A(s.root,s.actor),d=null,l=null;if(o.task!==void 0&&o.task.trim().length>0){let m=B(i,o.task);if(m===void 0)return W(o.task);d=m.id,l=m.label}let c=E();M(s.root,{id:c,type:"note.recorded",entity:c,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:d===null?{text:r}:{text:r,task:d}});let u=l===null?"":` on ${l}`;return{ok:!0,exitCode:0,warnings:a,message:`Note recorded${u}.`,data:{schema:"kadence/v1",ok:!0,note:{id:c,text:r,task:l}}}}function ns(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=s.notes;if(t.task!==void 0&&t.task.trim().length>0){let u=B(s,t.task);if(u===void 0)return W(t.task);i=i.filter(m=>m.task===u.id)}let a=[...i].reverse(),d=z(a,t.limit,t.offset),l=d.shown;if(l.length===0)return{ok:!0,exitCode:0,warnings:r,message:`No notes yet.
|
|
185
195
|
Record the first one:
|
|
186
196
|
kadence note "text"
|
|
187
197
|
|
|
188
|
-
${
|
|
189
|
-
`),
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
kadence doc
|
|
193
|
-
kadence doc
|
|
194
|
-
`),data:{schema:"kadence/v1",ok:!0,document:
|
|
198
|
+
${es}`,data:{schema:"kadence/v1",ok:!0,notes:[],notesTotal:d.total,notesOffset:d.offset}};let c=tr(s);return{ok:!0,exitCode:0,warnings:r,message:[l.map(u=>nr(u,c)).join(`
|
|
199
|
+
`),Y(d,"kadence note list")].filter(u=>u!==null).join(`
|
|
200
|
+
`),data:{schema:"kadence/v1",ok:!0,notes:l.map(u=>er(u,c)),notesTotal:d.total,notesOffset:d.offset}}}function tr(e){return n=>n===null?null:e.tasks.find(t=>t.id===n)?.label??null}function nr(e,n){let t=n(e.task),o=t===null?"":` ${t}`,s=e.source==="agent"?` ${e.by} [agent]`:` ${e.by}`;return`${e.at.slice(0,10)}${o}${s}
|
|
201
|
+
${e.text}`}import{existsSync as sr,readFileSync as or,statSync as rr}from"node:fs";import{resolve as ir}from"node:path";var ar=16*1024;function de(e,n){let t=n.trim().toUpperCase();return e.documents.find(o=>o.id===t||o.label===t)}function et(e){return b(1,"doc_not_found",`No document ${e}.
|
|
202
|
+
kadence doc list`,{received:e,hint:"kadence doc list --json"})}var Ie=e=>Buffer.byteLength(e,"utf8");function ss(e,n,t){if([n.body,n.file,n.stdin].filter(s=>s!==void 0).length>1)return b(2,"invalid_argument","Give the text one way: --body, --file or --stdin.",{hint:t});if(n.stdin!==void 0)return n.stdin;if(n.file!==void 0){let s=ir(e,n.file);return!sr(s)||!rr(s).isFile()?b(2,"invalid_argument",`No file at ${n.file} to read the text from.`,{received:n.file,hint:t}):or(s,"utf8")}return n.body}function os(e){return Ie(e)>ar?[`This document is ${Math.round(Ie(e)/1024)} KiB, past 16 KiB. Agents read long documents worse; one document per topic keeps what they read short.`]:[]}function ye(e,n){return{id:e.id,label:e.label,title:e.title,bytes:Ie(e.body),revisions:e.revisions,tasks:e.tasks.map(n).filter(t=>t!==null),updatedAt:e.updatedAt,updatedBy:e.updatedBy,source:e.source,conflicted:e.conflicts.length>0}}function dr(e,n){return{...ye(e,n),body:e.body,revision:e.revision,createdAt:e.createdAt,createdBy:e.createdBy,conflicts:e.conflicts}}function $e(e){let n=new Map(e.tasks.map(t=>[t.id,t.label]));return t=>n.get(t)??null}function rs(e,n,t,o){let s=C(e,n);if(!j(s))return s;let r='kadence doc add "Auth" --body "How login works."',i=t.trim();if(i.length===0)return b(2,"invalid_argument","A document needs a title.",{hint:r});let a=ss(e,o,r);if(typeof a=="object")return a;if(a===void 0||a.trim().length===0)return b(2,"invalid_argument",'A document needs text: --body "\u2026", --file <path>, or --stdin.',{hint:r});let{state:d,warnings:l}=A(s.root,s.actor),c=null;if(o.task!==void 0&&o.task.trim().length>0){let $=B(d,o.task);if($===void 0)return W(o.task);c=$.id}let u=E(),m=new Date().toISOString();M(s.root,{id:u,type:"doc.written",entity:u,actor:s.actor,ts:m,source:s.source,data:{title:i,body:a,parents:[]}}),c!==null&&M(s.root,{id:E(),type:"doc.linked",entity:u,actor:s.actor,ts:m,source:s.source,data:{task:c}});let g=A(s.root,s.actor).state,f=de(g,u),S=$e(g);return{ok:!0,exitCode:0,warnings:[...l,...os(a)],message:`${f.label} written: ${f.title}
|
|
203
|
+
kadence doc show ${f.label}`,data:{schema:"kadence/v1",ok:!0,document:ye(f,S)}}}function is(e,n,t,o){let s=C(e,n);if(!j(s))return s;let{state:r,warnings:i}=A(s.root,s.actor),a=de(r,t);if(a===void 0)return et(t);let d=`kadence doc edit ${a.label} --body "\u2026"`,l=ss(e,o,d);if(typeof l=="object")return l;if(l!==void 0&&l.trim().length===0)return b(2,"invalid_argument","A document cannot be emptied; its history would still hold every word.",{hint:d});if(a.conflicts.length>0&&l===void 0)return b(1,"conflicting_state",`${a.label} has ${a.conflicts.length+1} versions written on top of the same one. Read them (kadence doc show ${a.label} --json, under conflicts), then write the merged text:
|
|
204
|
+
kadence doc edit ${a.label} --file merged.txt`,{received:t,hint:`kadence doc show ${a.label} --json`});let c=o.title?.trim()||a.title,u=l??a.body;if(c===a.title&&u===a.body&&a.conflicts.length===0)return b(2,"invalid_argument",`Nothing to change: ${a.label} already reads that way.`,{received:t,hint:d});let m=[...a.conflicts.map($=>$.revision),a.revision];M(s.root,{id:E(),type:"doc.written",entity:a.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{title:c,body:u,parents:m}});let g=A(s.root,s.actor).state,f=de(g,a.id),S=a.conflicts.length>0?` The ${a.conflicts.length+1} competing versions are now one.`:"";return{ok:!0,exitCode:0,warnings:[...i,...os(u)],message:`${f.label} revised (${f.revisions} revisions; earlier ones stay in the journal).${S}`,data:{schema:"kadence/v1",ok:!0,document:ye(f,$e(g))}}}function as(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=de(s,t);if(i===void 0)return et(t);let a=$e(s),d=i.tasks.map(a).filter(u=>u!==null),l=[`${i.label} ${i.title}`,` ${i.revisions} revision${i.revisions===1?"":"s"}, last ${i.updatedAt.slice(0,10)} by ${i.updatedBy}${i.source==="agent"?" [agent]":""}`,...d.length>0?[` Explains: ${d.join(", ")}`]:[],"",i.body],c=i.conflicts.length===0?[]:[`${i.label} has ${i.conflicts.length+1} versions written on top of the same one. Shown: the latest. Also written: ${i.conflicts.map(u=>`${u.at.slice(0,10)} by ${u.by}`).join("; ")} (in --json under conflicts). Write the merged text with kadence doc edit ${i.label} --file <path> to settle it.`];return{ok:!0,exitCode:0,warnings:[...r,...c],message:l.join(`
|
|
205
|
+
`),data:{schema:"kadence/v1",ok:!0,document:dr(i,a)}}}function ds(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=s.documents;if(t.task!==void 0&&t.task.trim().length>0){let c=B(s,t.task);if(c===void 0)return W(t.task);i=i.filter(u=>u.tasks.includes(c.id))}let a=$e(s);if(i.length===0)return{ok:!0,exitCode:0,warnings:r,message:`No documentation yet.
|
|
195
206
|
Write the first one:
|
|
196
|
-
kadence doc add "Auth" --body "How login works." --task KAD-1`,data:{schema:"kadence/v1",ok:!0,documents:[]}};let d=Math.max(...
|
|
197
|
-
`),data:{schema:"kadence/v1",ok:!0,documents:
|
|
207
|
+
kadence doc add "Auth" --body "How login works." --task KAD-1`,data:{schema:"kadence/v1",ok:!0,documents:[],documentsTotal:0,documentsOffset:0}};let d=z(i,t.limit,t.offset),l=Math.max(...d.shown.map(c=>c.label.length));return{ok:!0,exitCode:0,warnings:r,message:d.shown.map(c=>{let u=c.tasks.map(a).filter(f=>f!==null),m=`${Math.max(1,Math.round(Ie(c.body)/1024))} KiB`,g=c.conflicts.length>0?" [conflict]":"";return`${c.label.padEnd(l)} ${c.title} (${m}${u.length>0?`, ${u.join(" ")}`:""})${g}`}).join(`
|
|
208
|
+
`).concat(Y(d,"kadence doc list")??""),data:{schema:"kadence/v1",ok:!0,documents:d.shown.map(c=>ye(c,a)),documentsTotal:d.total,documentsOffset:d.offset}}}function ls(e,n,t,o){let s=C(e,n);if(!j(s))return s;let{state:r,warnings:i}=A(s.root,s.actor),a=de(r,t);if(a===void 0)return et(t);let d=B(r,o);if(d===void 0)return W(o);let l=!a.tasks.includes(d.id);l&&M(s.root,{id:E(),type:"doc.linked",entity:a.id,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{task:d.id}});let c=l?A(s.root,s.actor).state:r;return{ok:!0,exitCode:0,warnings:i,message:`${a.label} explains ${d.label}. It now arrives with kadence task show ${d.label}.`,data:{schema:"kadence/v1",ok:!0,document:ye(de(c,a.id),$e(c)),task:{id:d.id,label:d.label}}}}import{readFileSync as Rr}from"node:fs";var lr=/^\d{4}-\d{2}-\d{2}$/;function tt(e,n){let t=String(n).trim(),o=t.toUpperCase();return e.milestones.find(s=>s.id===o||s.label===o||s.name.toLowerCase()===t.toLowerCase())}function cs(e,n){let t=e.milestones.map(o=>`${o.label} ${o.name}`);return b(1,"milestone_not_found",t.length===0?`No milestone "${n}".
|
|
198
209
|
Create one:
|
|
199
210
|
kadence milestone create "1.0"`:`No milestone "${n}".
|
|
200
|
-
Available: ${t.join(", ")}`,{received:n,hint:"kadence milestone list --json"})}function
|
|
201
|
-
${a} task(s) are still open; closing does not move them.`:""),data:{schema:"kadence/v1",ok:!0,milestone:{id:i.id,label:i.label,name:i.name,donePoints:i.donePoints,totalPoints:i.totalPoints}}}}function
|
|
211
|
+
Available: ${t.join(", ")}`,{received:n,hint:"kadence milestone list --json"})}function nt(e,n,t,o){M(e.root,{id:E(),type:n,entity:t,actor:e.actor,ts:new Date().toISOString(),source:e.source,data:o})}function us(e,n,t,o){let s=C(e,n);if(!j(s))return s;let r=t.trim();if(r.length===0)return b(2,"invalid_argument","A milestone needs a name.",{hint:'kadence milestone create "1.0"'});if(o.due!==void 0&&!lr.test(o.due))return b(2,"invalid_argument",`"${o.due}" is not a date. Use YYYY-MM-DD.`,{received:o.due,hint:'kadence milestone create "1.0" --due 2026-12-01'});let{state:i,warnings:a}=A(s.root,s.actor),d=tt(i,r),l=d===void 0?[]:[`A milestone named ${d.name} already exists as ${d.label}. Both stay in the journal \u2014 reference them by label to be unambiguous.`],c=E();nt(s,"milestone.created",c,{name:r,...o.due===void 0?{}:{due:o.due}});let u=`MS-${i.milestones.filter(m=>m.id<c).length+1}`;return{ok:!0,exitCode:0,warnings:[...a,...l],message:`${u} ${r}${o.due===void 0?"":` \u2014 due ${o.due}`}`,data:{schema:"kadence/v1",ok:!0,milestone:{id:c,label:u,name:r,due:o.due??null}}}}function ms(e,n,t,o){let s=C(e,n);if(!j(s))return s;let{state:r,warnings:i}=A(s.root,s.actor),a=B(r,t);if(a===void 0)return W(t);let d=tt(r,o);if(d===void 0)return cs(r,o);if(a.milestone===d.id)return{ok:!0,exitCode:0,warnings:i,message:`${a.label} is already in ${d.label} ${d.name}.`,data:{schema:"kadence/v1",ok:!0,task:{id:a.id,label:a.label}}};let l=a.milestone===null?null:r.milestones.find(c=>c.id===a.milestone);return nt(s,"milestone.task_added",d.id,{task:a.id}),{ok:!0,exitCode:0,warnings:i,message:l==null?`${a.label} \u2192 ${d.label} ${d.name}`:`${a.label}: ${l.label} ${l.name} \u2192 ${d.label} ${d.name}`,data:{schema:"kadence/v1",ok:!0,task:{id:a.id,label:a.label},milestone:{id:d.id,label:d.label,name:d.name},...l==null?{}:{previous:l.label}}}}function fs(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=tt(s,t);if(i===void 0)return cs(s,t);if(i.status==="closed")return{ok:!0,exitCode:0,warnings:r,message:`${i.label} ${i.name} is already closed.`,data:{schema:"kadence/v1",ok:!0,milestone:{id:i.id,label:i.label}}};nt(o,"milestone.closed",i.id,{});let a=i.totalTasks-i.doneTasks;return{ok:!0,exitCode:0,warnings:r,message:`${i.label} ${i.name} closed at ${i.donePoints}/${i.totalPoints} points.`+(a>0?`
|
|
212
|
+
${a} task(s) are still open; closing does not move them.`:""),data:{schema:"kadence/v1",ok:!0,milestone:{id:i.id,label:i.label,name:i.name,donePoints:i.donePoints,totalPoints:i.totalPoints}}}}function ps(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=t.all===!0?s.milestones:s.milestones.filter(a=>a.status==="open");return i.length===0?{ok:!0,exitCode:0,warnings:r,message:s.milestones.length===0?`No milestones yet.
|
|
202
213
|
Create one:
|
|
203
214
|
kadence milestone create "1.0"`:`Every milestone is closed.
|
|
204
215
|
See them all:
|
|
205
|
-
kadence milestone list --all`,data:{schema:"kadence/v1",ok:!0,milestones:[]}}:{ok:!0,exitCode:0,warnings:r,message:i.map(
|
|
206
|
-
`),data:{schema:"kadence/v1",ok:!0,milestones:i.map(
|
|
207
|
-
${o} ${n}% ${e.donePoints}/${e.totalPoints} points, ${e.doneTasks}/${e.totalTasks} tasks`}import{existsSync as
|
|
208
|
-
kadence decision list`,{received:e,hint:"kadence decision list --json"})}function
|
|
209
|
-
--why "..."`,{received:r,hint:'kadence decision add "Use ULIDs" --why "Clocks disagree between machines"'});let{state:a,warnings:d}=
|
|
210
|
-
It replaces ${o.supersedes}, and both links were written by one event \u2014 neither side can go stale.`;return{ok:!0,exitCode:0,warnings:[...d,...g],message:`${
|
|
216
|
+
kadence milestone list --all`,data:{schema:"kadence/v1",ok:!0,milestones:[]}}:{ok:!0,exitCode:0,warnings:r,message:i.map(ur).join(`
|
|
217
|
+
`),data:{schema:"kadence/v1",ok:!0,milestones:i.map(cr)}}}function cr(e){return{id:e.id,label:e.label,name:e.name,due:e.due,status:e.status,doneTasks:e.doneTasks,totalTasks:e.totalTasks,donePoints:e.donePoints,totalPoints:e.totalPoints}}function ur(e){let n=e.totalPoints===0?0:Math.round(e.donePoints/e.totalPoints*100),t=Math.round(n/10),o=`${"#".repeat(t)}${".".repeat(10-t)}`,s=e.due===null?"":` due ${e.due}`,r=e.status==="closed"?" [closed]":"";return`${e.label} ${e.name}${s}${r}
|
|
218
|
+
${o} ${n}% ${e.donePoints}/${e.totalPoints} points, ${e.doneTasks}/${e.totalTasks} tasks`}import{existsSync as mr}from"node:fs";import{isAbsolute as fr,join as pr,relative as hr}from"node:path";function hs(e,n){let t=n.toUpperCase();return e.decisions.find(o=>o.id===t||o.label===t)}function gs(e){return b(1,"decision_not_found",`No decision ${e}.
|
|
219
|
+
kadence decision list`,{received:e,hint:"kadence decision list --json"})}function ks(e,n,t,o){let s=C(e,n);if(!j(s))return s;let r=t.trim();if(r.length===0)return b(2,"invalid_argument","A decision needs a title.",{hint:'kadence decision add "Use ULIDs" --why "Clocks disagree between machines"'});let i=o.why?.trim()??"";if(i.length===0)return b(2,"invalid_argument",`A decision needs a reason.
|
|
220
|
+
--why "..."`,{received:r,hint:'kadence decision add "Use ULIDs" --why "Clocks disagree between machines"'});let{state:a,warnings:d}=A(s.root,s.actor),l;if(o.task!==void 0){let k=B(a,o.task);if(k===void 0)return W(o.task);l=k.id}let c;if(o.supersedes!==void 0){let k=hs(a,o.supersedes);if(k===void 0)return gs(o.supersedes);c=k.id,l===void 0&&k.task!==null&&(l=k.task)}let u=(o.docs??[]).map(k=>fr(k)?hr(s.root,k):k.replace(/^\.\//,"")),g=u.filter(k=>!mr(pr(s.root,k))).map(k=>`No file at ${k} \u2014 the link is recorded anyway; it may arrive later.`),f=E();M(s.root,{id:f,type:"decision.recorded",entity:f,actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{title:r,why:i,...o.rejected!==void 0?{rejected:o.rejected.trim()}:{},...l!==void 0?{task:l}:{},...c!==void 0?{supersedes:c}:{},...u.length>0?{docs:u}:{}}});let $=A(s.root,s.actor).state.decisions.find(k=>k.id===f)?.label??f,x=c===void 0?"":`
|
|
221
|
+
It replaces ${o.supersedes}, and both links were written by one event \u2014 neither side can go stale.`;return{ok:!0,exitCode:0,warnings:[...d,...g],message:`${$} recorded.${x}`,data:{schema:"kadence/v1",ok:!0,decision:{id:f,label:$,title:r}}}}function bs(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=s.decisions;if(t.task!==void 0){let d=B(s,t.task);if(d===void 0)return W(t.task);i=i.filter(l=>l.task===d.id)}t.all!==!0&&(i=i.filter(d=>d.supersededBy===null));let a=z(i,t.limit,t.offset);return{ok:!0,exitCode:0,warnings:r,message:[gr(a.shown,s),Y(a,"kadence decision list")].filter(d=>d!==null).join(`
|
|
222
|
+
`),data:{schema:"kadence/v1",ok:!0,decisions:a.shown.map(d=>$s(d,s)),decisionsTotal:a.total,decisionsOffset:a.offset}}}function ys(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor),i=hs(s,t);return i===void 0?gs(t):{ok:!0,exitCode:0,warnings:r,message:kr(i,s),data:{schema:"kadence/v1",ok:!0,decision:$s(i,s)}}}function X(e,n){return n===null?null:e.decisions.find(t=>t.id===n)?.label??e.tasks.find(t=>t.id===n)?.label??n}function $s(e,n){return{id:e.id,label:e.label,title:e.title,why:e.why,rejected:e.rejected,task:X(n,e.task),docs:e.docs,supersedes:X(n,e.supersedes),supersededBy:X(n,e.supersededBy),superseded:e.supersededBy!==null,at:e.at,by:e.by,source:e.source}}function gr(e,n){return e.length===0?`No decisions recorded yet.
|
|
211
223
|
Record the first one:
|
|
212
|
-
kadence decision add "Use ULIDs" --why "Clocks disagree"`:e.map(t=>{let o=t.supersededBy===null?"":` (superseded by ${
|
|
213
|
-
`)}function
|
|
214
|
-
`)}import{writeSync as
|
|
224
|
+
kadence decision add "Use ULIDs" --why "Clocks disagree"`:e.map(t=>{let o=t.supersededBy===null?"":` (superseded by ${X(n,t.supersededBy)})`,s=t.source==="agent"?" [agent]":"";return`${t.label} ${t.title}${o}${s}`}).join(`
|
|
225
|
+
`)}function kr(e,n){let t=[`${e.label} ${e.title}`];return e.supersededBy!==null&&t.push("",`!! SUPERSEDED by ${X(n,e.supersededBy)} \u2014 this is no longer in force.`),t.push("",`Why: ${e.why}`),e.rejected!==null&&t.push(`Rejected: ${e.rejected}`),e.task!==null&&t.push(`Task: ${X(n,e.task)}`),e.docs.length>0&&t.push(`Docs: ${e.docs.join(", ")}`),t.push(`By: ${e.by}${e.source==="agent"?" (agent)":""}`),e.supersedes!==null&&t.push(`Replaces: ${X(n,e.supersedes)}`),t.join(`
|
|
226
|
+
`)}import{writeSync as Er}from"node:fs";import{existsSync as wr,readFileSync as vr,writeFileSync as xr}from"node:fs";import{join as Sr}from"node:path";var br=`
|
|
215
227
|
:root {
|
|
216
228
|
color-scheme: light dark;
|
|
217
229
|
--bg: #ffffff; --fg: #1a1a1a; --muted: #6b6b6b; --line: #e2e2e2;
|
|
@@ -264,67 +276,68 @@ th { color: var(--muted); font-weight: 600; font-size: .78rem; text-transform: u
|
|
|
264
276
|
.criteria li.checked { color: var(--done); }
|
|
265
277
|
.empty { color: var(--muted); }
|
|
266
278
|
footer { margin-top: 2.5rem; color: var(--muted); font-size: .8rem; border-top: 1px solid var(--line); padding-top: .75rem; }
|
|
267
|
-
`;function
|
|
268
|
-
`)}var
|
|
279
|
+
`;function ws(e,n,t=""){let o=n===0?0:Math.round(e/n*100);return`<div class="bar ${t}"><span style="width:${o}%"></span></div>`}function yr(e,n){let t=[];if(e.contestedBy.length>0?t.push(`<span class="pill danger">contested: ${v(e.contestedBy.join(", "))}</span>`):e.claimedBy!==null&&t.push(`<span class="pill">claimed ${v(e.claimedBy)}</span>`),e.blockedBy.length>0&&t.push(`<span class="pill danger">blocked by ${e.blockedBy.length}</span>`),e.criteria.length>0){let a=e.criteria.filter(l=>l.checked).length,d=a===e.criteria.length?"pill":"pill warn";t.push(`<span class="${d}">${a}/${e.criteria.length} criteria</span>`)}let o=e.milestone===null?null:n.milestones.find(a=>a.id===e.milestone)?.name??null;o!==null&&t.push(`<span class="pill">${v(o)}</span>`);let s=[e.assignee===null?"":v(e.assignee),e.estimate===null?"":`${e.estimate} pts`,e.due===null?"":`due ${v(e.due)}`].filter(a=>a.length>0),r=e.criteria.length===0?"":`<ul class="criteria">${e.criteria.map(a=>`<li class="${a.checked?"checked":""}">${a.checked?"\u2611":"\u2610"} ${v(a.text)}</li>`).join("")}</ul>`;return[`<div class="card ${e.contestedBy.length>0?"contested":e.blockedBy.length>0?"blocked":v(e.status)}">`,`<span class="label">${v(e.label)}</span>`,`<span class="title">${v(e.title)}</span>`,t.length>0?t.join(""):"",r,s.length>0?`<div class="meta">${s.join(" \xB7 ")}</div>`:"","</div>"].join("")}function vs(e,n=null,t=new Date){let o=t.toISOString().slice(0,16).replace("T"," "),s=[];s.push("<h1>Board</h1>"),s.push(`<p class="stamp">Snapshot of <code>.kadence/</code> at ${v(o)} UTC. A file, not a page: nothing here is live, and regenerating it is <code>kadence board export --html</code>.</p>`);let r=e.tasks.length>0;r||s.push('<p class="empty">No tasks yet. Create the first one with <code>kadence task add "title"</code>.</p>');{let a=e.sprints.find(l=>l.status==="active");if(r&&a!==void 0){let l=ne(e,a.id);if(s.push(`<h2>Sprint: ${v(a.name)}</h2>`),l!==null&&(s.push(ws(l.velocity,l.committed,"done")),s.push(`<p class="stamp">${l.velocity} of ${l.committed} points done, ${l.carriedOver.length} carrying over.</p>`)),n!==null&&n.committed>0&&n.days.length>0){s.push("<h2>Burndown</h2>"),s.push('<div class="chart">');for(let c of n.days){let u=Math.round(c.remaining/n.committed*100),m=Math.round(c.ideal/n.committed*100);s.push(`<div><span class="day">${v(c.date.slice(5))}</span><span class="track"><span class="bar"><span style="width:${u}%"></span></span></span><span class="day">${c.remaining} / ${m}%</span></div>`)}s.push("</div>")}}if(e.milestones.length>0){s.push("<h2>Milestones</h2>"),s.push("<table><tr><th>Milestone</th><th>Due</th><th>Progress</th><th>Points</th><th>Tasks</th></tr>");for(let l of e.milestones)s.push(`<tr><td>${v(l.name)}${l.status==="closed"?' <span class="pill">closed</span>':""}</td><td>${v(l.due??"")}</td><td>${ws(l.donePoints,l.totalPoints)}</td><td>${l.donePoints}/${l.totalPoints}</td><td>${l.doneTasks}/${l.totalTasks}</td></tr>`);s.push("</table>")}if(r){s.push("<h2>Tasks</h2>"),s.push('<div class="columns">');let l=[...e.statuses,...e.orphanStatuses];for(let c of l){let u=e.tasks.filter(m=>m.status===c);if(!(u.length===0&&c===L)){s.push('<div class="column">'),s.push(`<h3>${v(c)} (${u.length})</h3>`),u.length===0&&s.push('<p class="empty">\u2014</p>');for(let m of u)s.push(yr(m,e));s.push("</div>")}}s.push("</div>")}let d=e.decisions.filter(l=>l.supersededBy===null);if(d.length>0){s.push("<h2>Decisions in force</h2>");for(let l of d)s.push('<div class="decision">'),s.push(`<strong>${v(l.label)} ${v(l.title)}</strong>`),s.push(`<div class="why">Why: ${v(l.why)}</div>`),l.rejected!==null&&s.push(`<div class="why">Rejected: ${v(l.rejected)}</div>`),s.push("</div>")}}let i=e.tasks.filter(a=>a.status!==I&&a.status!==L);return s.push(`<footer>${e.tasks.length} tasks, ${i.length} open. Generated by kadence from the event journal. No server, no network.</footer>`),["<!doctype html>",'<html lang="en">',"<head>",'<meta charset="utf-8">','<meta name="viewport" content="width=device-width, initial-scale=1">',"<title>kadence board</title>",`<style>${br}</style>`,"</head>","<body>","<main>",...s,"</main>","</body>","</html>",""].join(`
|
|
280
|
+
`)}var xs="<!-- kadence:board:begin -->",st="<!-- kadence:board:end -->";function K(e){return e.replace(/\|/g,"\\|").replace(/\n+/g," ").replace(/kadence:board:(begin|end)/g,"kadence:board:\u200B$1")}function Ss(e,n,t=20){if(n===0)return`${"\u2591".repeat(t)} 0%`;let o=Math.round(e/n*100),s=Math.round(o/100*t);return`${"\u2588".repeat(s)}${"\u2591".repeat(t-s)} ${o}%`}function $r(e,n){let t=e.criteria.length===0?"":`${e.criteria.filter(s=>s.checked).length}/${e.criteria.length}`,o=e.milestone===null?"":n.find(s=>s.id===e.milestone)?.name??"";return`| ${K(e.label)} | ${K(e.title)} | ${K(e.status)} | ${K(e.priority)} | ${e.estimate??""} | ${K(e.assignee??"")} | ${t} | ${K(o)} |`}function ot(e,n=new Date){let t=["# Board"],o=n.toISOString().slice(0,16).replace("T"," ");t.push("",`Snapshot of \`.kadence/\` at ${o} UTC. Regenerate with \`kadence board export --md\`.`);let s=e.tasks.length>0,r=e.sprints.find(d=>d.status==="active");if(s&&r!==void 0){let d=ne(e,r.id);t.push("",`## Sprint: ${K(r.name)}`),d!==null&&(t.push(""),t.push(`${Ss(d.velocity,d.committed)} \u2014 ${d.velocity} of ${d.committed} points`))}if(e.milestones.length>0){t.push("","## Milestones","","| Milestone | Due | Progress | Points | Tasks |","|---|---|---|---|---|");for(let d of e.milestones)t.push(`| ${K(d.name)}${d.status==="closed"?" (closed)":""} | ${K(d.due??"")} | ${Ss(d.donePoints,d.totalPoints,10)} | ${d.donePoints}/${d.totalPoints} | ${d.doneTasks}/${d.totalTasks} |`)}if(s){t.push("","## Tasks","","| Task | Title | Status | Priority | Points | Assignee | Criteria | Milestone |","|---|---|---|---|---|---|---|---|");let d=new Map(e.statuses.map((c,u)=>[c,u])),l=[...e.tasks].sort((c,u)=>(d.get(c.status)??99)-(d.get(u.status)??99)||(c.id<u.id?-1:1));for(let c of l)t.push($r(c,e.milestones))}else t.push("","No tasks yet.","",' kadence task add "first task"');let i=e.decisions.filter(d=>d.supersededBy===null);if(i.length>0){t.push("","## Decisions in force");for(let d of i)t.push("",`**${d.label} ${K(d.title)}**`,"",`Why: ${K(d.why)}`),d.rejected!==null&&t.push("",`Rejected: ${K(d.rejected)}`)}let a=e.tasks.filter(d=>d.status!==I&&d.status!==L);return t.push("",`${e.tasks.length} tasks, ${a.length} open.`),`${t.join(`
|
|
269
281
|
`)}
|
|
270
|
-
`}function
|
|
282
|
+
`}function As(e,n){let t=`${xs}
|
|
271
283
|
${n.trimEnd()}
|
|
272
|
-
${
|
|
284
|
+
${st}`,o=e.indexOf(xs),s=o===-1?-1:e.indexOf(st,o);if(o!==-1&&s!==-1&&s>o)return`${e.slice(0,o)}${t}${e.slice(s+st.length)}`;let r=e.endsWith(`
|
|
273
285
|
`)?"":`
|
|
274
286
|
`;return`${e}${r}
|
|
275
287
|
${t}
|
|
276
|
-
`}var
|
|
288
|
+
`}var rt="cancelled",Ar=["id","label","title","status","type","priority","estimate","assignee","claimedBy","contestedBy","blockedBy","sprint","milestone","due"];function js(e,n,t,o,s=!1){let r=C(e,n);if(!j(r))return r;let{fields:i,error:a}=Tt(o);if(a!==null)return a;let d=i??(s?[...Ar]:null),{state:l,warnings:c}=A(r.root,r.actor),u=l.tasks.filter(k=>k.status!==rt);if(t.assignee!==void 0){let k=t.assignee.toLowerCase(),D=k==="me"?r.actor.toLowerCase():k;u=u.filter(R=>(R.assignee??"").toLowerCase()===D)}if(t.sprint==="active"){let k=l.sprints.find(D=>D.status==="active"||D.status==="planned");u=k===void 0?[]:u.filter(D=>D.sprint===k.id)}let m={};for(let k of l.statuses)k!==rt&&(m[k]=u.filter(D=>D.status===k));let g=l.orphanStatuses.filter(k=>k!==rt);for(let k of g)m[k]=u.filter(D=>D.status===k);let f=g.length>0?[`Statuses not in the board configuration: ${g.join(", ")}.
|
|
277
289
|
Tasks there are still shown. Add the column or move them:
|
|
278
|
-
kadence board config --statuses "..."`]:[]
|
|
290
|
+
kadence board config --statuses "..."`]:[],S=Object.entries(m).flatMap(([k,D])=>D.map(R=>({column:k,task:R}))),$=z(S,t.limit,t.offset),x={};for(let k of Object.keys(m))x[k]=[];for(let{column:k,task:D}of $.shown)x[k].push(D);return{ok:!0,exitCode:0,warnings:[...c,...f],message:[$t(x,ve(n,process.stdout.isTTY===!0)),Y($,"kadence board")].filter(k=>k!==null).join(`
|
|
291
|
+
`),data:{schema:"kadence/v1",ok:!0,columns:Object.fromEntries(Object.entries(x).map(([k,D])=>[k,D.map(R=>Rt(R,d,l))])),tasksTotal:$.total,tasksOffset:$.offset}}}function Ds(e,n,t,o,s){let r=C(e,n);if(!j(r))return r;let{state:i,warnings:a}=A(r.root,r.actor);if(t===void 0&&o===void 0&&s===void 0){let m=i.dod.length===0?"Definition of done: not set":`Definition of done: ${i.dod.join(", ")}`;return{ok:!0,exitCode:0,warnings:[...a,...Cs(i.statuses,i.started)],message:`Board columns: ${i.statuses.join(", ")}
|
|
279
292
|
Started: ${i.started} (cycle time and actual hours count from here)
|
|
280
293
|
${m}
|
|
281
294
|
|
|
282
295
|
Change them with:
|
|
283
296
|
kadence board config --statuses "todo,doing,review,done"
|
|
284
297
|
kadence board config --started doing
|
|
285
|
-
kadence board config --dod "tests green,docs updated"`,data:{schema:"kadence/v1",ok:!0,statuses:i.statuses,dod:i.dod,started:i.started}}}if(t===void 0&&o===void 0&&s!==void 0){let m=
|
|
286
|
-
Cycle time, work item age and a sprint's actual hours are measured from this column.`,data:{schema:"kadence/v1",ok:!0,started:g}})}if(t===void 0){let m;if(s!==void 0){let
|
|
298
|
+
kadence board config --dod "tests green,docs updated"`,data:{schema:"kadence/v1",ok:!0,statuses:i.statuses,dod:i.dod,started:i.started}}}if(t===void 0&&o===void 0&&s!==void 0){let m=it(s,i.statuses);if(typeof m!="string")return m;let g=m;return g===i.started?{ok:!0,exitCode:0,warnings:a,message:`Work already counts as started at "${g}".`,data:{schema:"kadence/v1",ok:!0,started:g}}:(M(r.root,{id:E(),type:"board.configured",entity:E(),actor:r.actor,ts:new Date().toISOString(),source:r.source,data:{started:g}}),{ok:!0,exitCode:0,warnings:a,message:`Work counts as started at "${g}".
|
|
299
|
+
Cycle time, work item age and a sprint's actual hours are measured from this column.`,data:{schema:"kadence/v1",ok:!0,started:g}})}if(t===void 0){let m;if(s!==void 0){let f=it(s,i.statuses);if(typeof f!="string")return f;m=f}let g=o.split(",").map(f=>f.trim()).filter(f=>f.length>0);return g.length===i.dod.length&&g.every((f,S)=>f===i.dod[S])?{ok:!0,exitCode:0,warnings:a,message:g.length===0?"There is already no definition of done.":`Definition of done is already: ${g.join(", ")}`,data:{schema:"kadence/v1",ok:!0,dod:g}}:(M(r.root,{id:E(),type:"board.configured",entity:E(),actor:r.actor,ts:new Date().toISOString(),source:r.source,data:{dod:g,...m===void 0?{}:{started:m}}}),{ok:!0,exitCode:0,warnings:a,message:(g.length===0?"Definition of done cleared. New tasks start with no criteria.":`Definition of done: ${g.join(", ")}
|
|
287
300
|
New tasks start with these criteria. Tasks that already exist keep theirs.`)+(m===void 0?"":`
|
|
288
|
-
Work counts as started at "${m}".`),data:{schema:"kadence/v1",ok:!0,dod:g,...m===void 0?{}:{started:m}}})}let d=t.split(",").map(m=>m.trim().toLowerCase().replace(/\s+/g,"_")).filter(m=>m.length>0);if(d.length===0)return
|
|
289
|
-
${l.length} task(s) remain in removed columns: ${[...new Set(l.map(m=>m.status))].join(", ")}. They are still listed.`:"";return{ok:!0,exitCode:0,warnings:[...a,...
|
|
290
|
-
Work counts as started at "${c}".`),data:{schema:"kadence/v1",ok:!0,statuses:d}}}var
|
|
301
|
+
Work counts as started at "${m}".`),data:{schema:"kadence/v1",ok:!0,dod:g,...m===void 0?{}:{started:m}}})}let d=t.split(",").map(m=>m.trim().toLowerCase().replace(/\s+/g,"_")).filter(m=>m.length>0);if(d.length===0)return b(2,"invalid_argument","At least one status is required.",{received:t});if(new Set(d).size!==d.length)return b(2,"invalid_argument","The same status is listed twice.",{received:t});if(!d.includes(I))return b(2,"invalid_argument",`The list must include "${I}" \u2014 velocity and burndown are computed from it.`,{received:t});let l=i.tasks.filter(m=>!d.includes(m.status)&&m.status!==L),c;if(s!==void 0){let m=it(s,d);if(typeof m!="string")return m;c=m}M(r.root,{id:E(),type:"board.configured",entity:E(),actor:r.actor,ts:new Date().toISOString(),source:r.source,data:{statuses:d,...o===void 0?{}:{dod:o.split(",").map(m=>m.trim()).filter(m=>m.length>0)},...c===void 0?{}:{started:c}}});let u=l.length>0?`
|
|
302
|
+
${l.length} task(s) remain in removed columns: ${[...new Set(l.map(m=>m.status))].join(", ")}. They are still listed.`:"";return{ok:!0,exitCode:0,warnings:[...a,...Cs(d,c??i.started)],message:`Board columns: ${d.join(", ")}${u}`+(c===void 0?"":`
|
|
303
|
+
Work counts as started at "${c}".`),data:{schema:"kadence/v1",ok:!0,statuses:d}}}var Cr="kadence-board.html",jr="kadence-board.md";function Ts(e,n,t){let o=C(e,n);if(!j(o))return o;if(t.html!==!0&&t.md!==!0)return b(2,"invalid_argument",`Which format?
|
|
291
304
|
kadence board export --html
|
|
292
|
-
kadence board export --md`,{hint:"kadence board export --html"});if(t.html===!0&&t.md===!0)return
|
|
305
|
+
kadence board export --md`,{hint:"kadence board export --html"});if(t.html===!0&&t.md===!0)return b(2,"invalid_argument","One format at a time: --html or --md.",{hint:"kadence board export --html"});if(t.readme===!0&&t.html===!0)return b(2,"invalid_argument","--readme writes markdown. Use --md with it.",{hint:"kadence board export --md --readme"});let{state:s,warnings:r}=A(o.root,o.actor);if(t.md===!0&&t.readme===!0){if(t.file!==void 0)return b(2,"invalid_argument","--readme writes into README.md, so --file has nowhere to go.",{received:t.file,hint:"kadence board export --md --file docs/board.md"});let l=Sr(o.root,"README.md");if(!wr(l))return b(1,"conflicting_state",`There is no README.md here to update.
|
|
293
306
|
Write the board to a file instead:
|
|
294
|
-
kadence board export --md`,{hint:"kadence board export --md"});let c=
|
|
295
|
-
It is a snapshot: rerun this after the board changes.`,data:{schema:"kadence/v1",ok:!0,format:"md",path:l,section:!0,bytes:Buffer.byteLength(c)}}}let i=t.html===!0?
|
|
296
|
-
`+(t.html===!0?"Open it from disk \u2014 there is no server, and the page makes no requests.":"A snapshot for a README or a pull request."),data:{schema:"kadence/v1",ok:!0,format:t.html===!0?"html":"md",path:d,section:!1,bytes:a.bytes}}}function
|
|
297
|
-
kadence board config --started ${e[1]??e[0]??"doing"}`]}function
|
|
298
|
-
Available: ${n.join(", ")}`,{received:e,allowed:n,hint:"kadence board config --json"})}var
|
|
299
|
-
kadence template save bug --type bug --priority high --label triage`,{received:t}):(
|
|
300
|
-
kadence task add "title" --template ${r}`,data:{schema:"kadence/v1",ok:!0,template:{name:r,fields:i}}})}function
|
|
307
|
+
kadence board export --md`,{hint:"kadence board export --md"});let c=As(vr(l,"utf8"),ot(s));return xr(l,c,"utf8"),{ok:!0,exitCode:0,warnings:r,message:`Board section updated in ${l}.
|
|
308
|
+
It is a snapshot: rerun this after the board changes.`,data:{schema:"kadence/v1",ok:!0,format:"md",path:l,section:!0,bytes:Buffer.byteLength(c)}}}let i=t.html===!0?vs(s,Dr(o.root,s)):ot(s),a=Me(o.root,t.file,t.html===!0?Cr:jr,i,"kadence board export --html --file docs/board.html");if("exitCode"in a)return a;let d=a.path;return{ok:!0,exitCode:0,warnings:r,message:`Wrote ${d}.
|
|
309
|
+
`+(t.html===!0?"Open it from disk \u2014 there is no server, and the page makes no requests.":"A snapshot for a README or a pull request."),data:{schema:"kadence/v1",ok:!0,format:t.html===!0?"html":"md",path:d,section:!1,bytes:a.bytes}}}function Dr(e,n){let t=n.sprints.find(o=>o.status==="active");return t===void 0?null:Yt(n,ut(e).events,t)}function Cs(e,n){return e.includes(n)?[]:[`Work is set to start at "${n}", which is not one of the columns any more. Cycle time and actual hours will be empty until it is:
|
|
310
|
+
kadence board config --started ${e[1]??e[0]??"doing"}`]}function it(e,n){let t=e.trim().toLowerCase().replace(/\s+/g,"_");return t===I||t===L?b(2,"invalid_argument",`Work cannot start at "${t}" \u2014 that is where it ends. Cycle time would always be zero.`,{received:e,allowed:n.filter(o=>o!==I&&o!==L)}):n.includes(t)?t:b(2,"unknown_status",`"${e}" is not one of this board's columns.
|
|
311
|
+
Available: ${n.join(", ")}`,{received:e,allowed:n,hint:"kadence board config --json"})}var Tr=["description","type","priority","estimate","labels","assignee"];function Rs(e,n,t,o){let s=C(e,n);if(!j(s))return s;let r=t.trim();if(r.length===0)return b(2,"invalid_argument","A template needs a name.",{hint:"kadence template list --json"});let i={};for(let a of Tr)o[a]!==void 0&&(i[a]=o[a]);return Object.keys(i).length===0?b(2,"invalid_argument",`A template needs at least one field.
|
|
312
|
+
kadence template save bug --type bug --priority high --label triage`,{received:t}):(M(s.root,{id:E(),type:"template.saved",entity:E(),actor:s.actor,ts:new Date().toISOString(),source:s.source,data:{name:r,fields:i}}),{ok:!0,exitCode:0,message:`Template "${r}" saved: ${Object.keys(i).join(", ")}.
|
|
313
|
+
kadence task add "title" --template ${r}`,data:{schema:"kadence/v1",ok:!0,template:{name:r,fields:i}}})}function Es(e,n){let t=C(e,n);if(!j(t))return t;let{state:o,warnings:s}=A(t.root,t.actor);return o.templates.length===0?{ok:!0,exitCode:0,warnings:s,message:`No templates yet.
|
|
301
314
|
kadence template save bug --type bug --priority high`,data:{schema:"kadence/v1",ok:!0,templates:[]}}:{ok:!0,exitCode:0,warnings:s,message:o.templates.map(r=>{let i=Object.entries(r.fields).map(([a,d])=>`${a}=${Array.isArray(d)?d.join("/"):String(d)}`).join(" ");return` ${r.name.padEnd(14)} ${i}`}).join(`
|
|
302
|
-
`),data:{schema:"kadence/v1",ok:!0,templates:o.templates}}}function
|
|
303
|
-
kadence template list`,{received:t,hint:"kadence template list --json"})}function
|
|
315
|
+
`),data:{schema:"kadence/v1",ok:!0,templates:o.templates}}}function Os(e,n,t){let o=C(e,n);if(!j(o))return o;let{state:s,warnings:r}=A(o.root,o.actor);return s.templates.some(i=>i.name===t)?(M(o.root,{id:E(),type:"template.deleted",entity:E(),actor:o.actor,ts:new Date().toISOString(),source:o.source,data:{name:t}}),{ok:!0,exitCode:0,warnings:r,message:`Template "${t}" deleted.`}):b(1,"template_not_found",`No template "${t}".
|
|
316
|
+
kadence template list`,{received:t,hint:"kadence template list --json"})}function Ns(e,n,t){let o=C(e,n);if(!j(o))return{error:o};let{state:s}=A(o.root,o.actor),r=s.templates.find(i=>i.name===t);if(r===void 0){let i=s.templates.map(a=>a.name);return{error:b(1,"template_not_found",`No template "${t}".`+(i.length>0?`
|
|
304
317
|
Available: ${i.join(", ")}`:`
|
|
305
|
-
kadence template save ...`),{received:t,...i.length>0?{allowed:i}:{}})}}return{fields:r.fields}}function
|
|
306
|
-
`);if(n){let t=e.data??{schema:"kadence/v1",ok:e.ok,...e.ok?{}:{error:e.error??{message:e.message}}};
|
|
307
|
-
`)}else
|
|
308
|
-
`);process.exit(e.exitCode)}function
|
|
318
|
+
kadence template save ...`),{received:t,...i.length>0?{allowed:i}:{}})}}return{fields:r.fields}}function we(e){return Array.isArray(e)?e.at(-1)??"":e}function Or(e){return Array.isArray(e)?e.join("; "):e}function Le(e,n){let t=Buffer.from(n,"utf8"),o=0;for(;o<t.length;)try{o+=Er(e,t,o,t.length-o)}catch(s){if(s.code!=="EAGAIN")throw s}}var T=mn("kadence");function p(e,n){for(let t of e.warnings??[])Le(2,`${t}
|
|
319
|
+
`);if(n){let t=e.data??{schema:"kadence/v1",ok:e.ok,...e.ok?{}:{error:e.error??{message:e.message}}};Le(1,`${JSON.stringify(t)}
|
|
320
|
+
`)}else Le(e.ok?1:2,`${e.message}
|
|
321
|
+
`);process.exit(e.exitCode)}function Ms(e,n,t,o){if(e!==void 0)return e;on(process.env,process.stdout.isTTY===!0)||p(w(`No terminal available for an editor.
|
|
309
322
|
Pass the text directly:
|
|
310
|
-
--description "..."`),o);let s=
|
|
323
|
+
--description "..."`),o);let s=sn(process.env,n,t);return s.error!==null&&p({ok:!1,exitCode:1,message:s.error},o),s.text===null&&p({ok:!0,exitCode:0,message:"Aborted \u2014 nothing changed."},o),s.text}function Nr(e,n=process.argv){let t,o=`--${e}`;for(let s=0;s<n.length;s++){let r=n[s];r===o?t=n[s+1]:r.startsWith(`${o}=`)&&(t=r.slice(o.length+1))}return t}function We(e,n=process.argv){let t=`--${e}`;for(let o=0;o<n.length;o++){let s=n[o];if(s===t)return n[o+1];if(s.startsWith(`${t}=`))return s.slice(t.length+1)}}var Mr=["add","list","show","edit","move","assign","comment","log","parent","block","unblock","claim","release","ac","doc","cancel","delete"],_r=["create","add","edit","start","close","status","list","burndown"],Pr=["save","list","delete"],Ir=["create","add","list","close"],Lr=["add","list","show"],_s=["add","edit","show","list","link"];function le(e){let n={};for(let t of["limit","offset"]){let o=e[t];if(o===void 0)continue;let s=Number(o);if(!Number.isInteger(s)||s<0)return{error:w(`--${t} must be a whole number of 0 or more, got "${o}".`,{received:o})};n[t]=s}return{...n,error:null}}function w(e,n={}){return b(2,"invalid_argument",e,n)}function Wr(e){let n=e.commands,t=e.errors;return`kadence/v1 \u2014 ${n.length} commands, ${t.length} error codes.
|
|
311
324
|
${e.stability}
|
|
312
325
|
|
|
313
326
|
The machine-readable form is what agents read:
|
|
314
|
-
kadence schema --json`}
|
|
315
|
-
kadence milestone create "1.0"`),o),p(
|
|
316
|
-
kadence milestone add KAD-1 --milestone 1.0`),o),p(
|
|
317
|
-
kadence milestone close 1.0`),o),p(
|
|
327
|
+
kadence schema --json`}T.command("milestone [action] [arg]","Milestones: create | add | list | close \u2014 grouping by outcome").option("--due <date>","Target date, YYYY-MM-DD").option("--milestone <ref>","Which milestone, by MS-N or name").option("--all","Include closed milestones, hidden by default").option("--json","Machine-readable output for agents").example(' kadence milestone create "1.0" --due 2026-12-01').example(" kadence milestone add KAD-1 --milestone 1.0").example(" kadence milestone list --json").example(" kadence milestone close 1.0").action((e,n,t)=>{let o=t.json===!0,s=process.cwd();switch(e){case"create":n===void 0&&p(w(`A milestone needs a name:
|
|
328
|
+
kadence milestone create "1.0"`),o),p(us(s,process.env,n,t.due===void 0?{}:{due:We("due")??String(t.due)}),o);break;case"add":(n===void 0||t.milestone===void 0)&&p(w(`A task and a milestone are required:
|
|
329
|
+
kadence milestone add KAD-1 --milestone 1.0`),o),p(ms(s,process.env,n,We("milestone")??String(t.milestone)),o);break;case"close":n===void 0&&p(w(`Which milestone?
|
|
330
|
+
kadence milestone close 1.0`),o),p(fs(s,process.env,n),o);break;case"list":case void 0:p(ps(s,process.env,{...t.all===!0?{all:!0}:{},json:o}),o);break;default:p(w(`Unknown milestone action "${e}".`,{received:e,allowed:Ir}),o)}});T.command("note [text]","Record something learned; `note list` reads them back").option("--task <ref>","The task it came out of").option("--limit <n>","At most this many, newest first; 0 for all of them").option("--offset <n>","list: start the page here").option("--json","Machine-readable output for agents").example(' kadence note "Tests need a git identity"').example(' kadence note "The redirect drops the cookie" --task KAD-1').example(" kadence note list --limit 5").action((e,n)=>{let t=n.json===!0,o=process.cwd(),s=le(n);if(s.error!==null&&p(s.error,t),e==="list"){p(ns(o,process.env,{...n.task===void 0?{}:{task:n.task},...s.limit!==void 0?{limit:s.limit}:{},...s.offset!==void 0?{offset:s.offset}:{},json:t}),t);return}e===void 0&&p(w(`A note needs text:
|
|
318
331
|
kadence note "Tests need a git identity"
|
|
319
|
-
kadence note list`),t),p(
|
|
320
|
-
kadence decision add "Use ULIDs" --why "..."`),o),p(
|
|
321
|
-
kadence decision show DEC-1`),o),p(
|
|
322
|
-
Available: add, list, show`,{...e===void 0?{}:{received:e},allowed:
|
|
323
|
-
kadence doc add "Auth" --body "How login works."`),s),p(
|
|
324
|
-
kadence doc edit DOC-1 --body "\u2026"`),s),p(
|
|
325
|
-
kadence doc show DOC-1`),s),p(
|
|
326
|
-
kadence doc link DOC-1 KAD-2`),s),p(
|
|
327
|
-
Available: ${
|
|
332
|
+
kadence note list`),t),p(ts(o,process.env,e,n.task===void 0?{}:{task:n.task}),t)});T.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("--limit <n>","list: at most this many decisions; 0 for all of them").option("--offset <n>","list: start the page here").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,n,t)=>{let o=t.json===!0,s=process.cwd(),r=le(t);r.error!==null&&p(r.error,o);let i=t.doc===void 0?void 0:Array.isArray(t.doc)?t.doc:[t.doc];switch(e){case"add":n===void 0&&p(w(`A title is required:
|
|
333
|
+
kadence decision add "Use ULIDs" --why "..."`),o),p(ks(s,process.env,n,{...t.why!==void 0?{why:we(t.why)}:{},...t.rejected!==void 0?{rejected:Or(t.rejected)}:{},...t.task!==void 0?{task:we(t.task)}:{},...t.supersedes!==void 0?{supersedes:we(t.supersedes)}:{},...i!==void 0?{docs:i}:{}}),o);break;case void 0:case"list":p(bs(s,process.env,{...r.limit!==void 0?{limit:r.limit}:{},...r.offset!==void 0?{offset:r.offset}:{},...t.all===!0?{all:!0}:{},...t.task!==void 0?{task:we(t.task)}:{}}),o);break;case"show":n===void 0&&p(w(`Which decision?
|
|
334
|
+
kadence decision show DEC-1`),o),p(ys(s,process.env,n),o);break;default:p(w(`Unknown action "${e}".
|
|
335
|
+
Available: add, list, show`,{...e===void 0?{}:{received:e},allowed:Lr}),o)}});T.command("doc [action] [arg] [arg2]","Documentation: add | edit | show | list | link \u2014 kept in the journal, not in files").option("--body <text>","The text").option("--stdin","Read the text from standard input \u2014 for text too long for an argument").option("--file <path>","Read the text from a file; the file is not kept or linked").option("--title <text>","A new title, for edit").option("--task <ref>","The task this explains (add), or narrow the list to one task").option("--limit <n>","list: at most this many documents; 0 for all of them").option("--offset <n>","list: start the page here").option("--json","Machine-readable output for agents").example(' kadence doc add "Auth" --body "How login works." --task KAD-1').example(" kadence doc edit DOC-1 --file draft.txt").example(" kadence doc show DOC-1 --json").example(" kadence doc link DOC-1 KAD-2").action((e,n,t,o)=>{let s=o.json===!0,r=process.cwd(),i=le(o);i.error!==null&&p(i.error,s);let a=(g,f)=>f===void 0?void 0:Nr(g)??String(we(f)),d=a("body",o.body),l=a("file",o.file),c=a("task",o.task),u=a("title",o.title),m={...d!==void 0?{body:d}:{},...l!==void 0?{file:l}:{},...o.stdin===!0?{stdin:Rr(0,"utf8")}:{}};switch(e){case"add":n===void 0&&p(w(`A document needs a title:
|
|
336
|
+
kadence doc add "Auth" --body "How login works."`),s),p(rs(r,process.env,String(n),{...m,...c!==void 0?{task:c}:{}}),s);break;case"edit":n===void 0&&p(w(`Which document?
|
|
337
|
+
kadence doc edit DOC-1 --body "\u2026"`),s),p(is(r,process.env,String(n),{...m,...u!==void 0?{title:u}:{}}),s);break;case"show":n===void 0&&p(w(`Which document?
|
|
338
|
+
kadence doc show DOC-1`),s),p(as(r,process.env,String(n)),s);break;case void 0:case"list":p(ds(r,process.env,{...c!==void 0?{task:c}:{},...i.limit!==void 0?{limit:i.limit}:{},...i.offset!==void 0?{offset:i.offset}:{}}),s);break;case"link":(n===void 0||t===void 0)&&p(w(`A link needs a document and a task:
|
|
339
|
+
kadence doc link DOC-1 KAD-2`),s),p(ls(r,process.env,String(n),String(t)),s);break;default:p(w(`Unknown action "${e}".
|
|
340
|
+
Available: ${_s.join(", ")}`,{received:e,allowed:_s}),s)}});T.command("schema","The machine-readable --json contract, for agents").option("--json","Machine-readable output for agents").example(" kadence schema --json").action(e=>{let n=e.json===!0,t=gt("0.7.0");p({ok:!0,exitCode:0,message:Wr(t),data:{schema:"kadence/v1",ok:!0,contract:t}},n)});T.command("prime","Everything a session needs before it starts. Short by design").option("--json","Machine-readable output for agents").example(" kadence prime").example(" kadence prime --json").action(e=>{p(Nn(process.cwd(),process.env,{json:e.json===!0}),e.json===!0)});T.command("ready","What can be started right now: open, unblocked, unclaimed").option("-a, --assignee <who>",'Only this person; "me" for yourself').option("--limit <n>","At most this many tasks").option("--json","Machine-readable output for agents").example(" kadence ready").example(" kadence ready --assignee me --json").action(e=>{let n=le(e);n.error!==null&&p(n.error,e.json===!0),p(yn(process.cwd(),process.env,{...e.assignee===void 0?{}:{assignee:e.assignee},...n.limit!==void 0?{limit:n.limit}:{},...n.offset!==void 0?{offset:n.offset}:{},json:e.json===!0}),e.json===!0)});T.command("search <query>","Find it across tasks, decisions, notes and documents").option("--kind <list>",`Narrow to: ${se.join(" | ")}; comma-separated`).option("--limit <n>","At most this many passages").option("--all","Include superseded decisions, left out by default").option("--json","Machine-readable output for agents").example(' kadence search "why are events append-only"').example(' kadence search "cookie redirect" --kind task,note').example(' kadence search "ordering between machines" --json').action((e,n)=>{let t=n.json===!0,o=n.limit===void 0?void 0:Number(n.limit);o!==void 0&&(!Number.isInteger(o)||o<1)&&p(w(`--limit must be a whole number of 1 or more, got "${n.limit}".`),t),p(Dn(process.cwd(),process.env,e,{...n.kind===void 0?{}:{kind:n.kind},...o===void 0?{}:{limit:o},...n.all===!0?{all:!0}:{},json:t}),t)});T.command("stats","Where the project stands: counts, blockers, contested claims, velocity").option("--json","Machine-readable output for agents").example(" kadence stats").action(e=>{p(_n(process.cwd(),process.env,{json:e.json===!0}),e.json===!0)});T.command("report [name]",`Reports folded from the journal: ${_e.join(" | ")}`).option("--list","Name every report and what each one answers").option("--since <days>","flow, cfd, attention: window ending today, in calendar days (default 30d)").option("--sprint <name>","burndown: a sprint by name, rather than the active one").option("--html","Write one self-contained page instead of printing; charts included, no network").option("--file <path>","html: where to write it (default kadence-<report>.html)").option("--json","Machine-readable output for agents").example(" kadence report --list every report, and what it answers").example(" kadence report flow cycle time, throughput, aging work").example(" kadence report flow --since 90d").example(" kadence report cfd tasks per column, per day").example(" kadence report attention work in flight that nobody is moving").example(" kadence report burndown the active sprint against an even burn").example(" kadence report velocity committed against finished, sprint by sprint").example(" kadence report workload who is carrying what right now").example(" kadence report flow --html the same numbers as a page, with charts").example(" kadence report cfd --html --file docs/cfd.html").action((e,n)=>{p(Zn(process.cwd(),process.env,e,{...n.since===void 0?{}:{since:We("since")??String(n.since)},...n.list===!0?{list:!0}:{},...n.sprint===void 0?{}:{sprint:String(n.sprint)},...n.html===!0?{html:!0}:{},...n.file===void 0?{}:{file:String(n.file)},json:n.json===!0}),n.json===!0)});T.command("compact","Fold old months into one file each; cold start on a long journal drops from ~200 ms to ~20 ms").option("--keep-months <n>","Months to keep as separate files, counting this one (default 2)").option("--dry-run","Say what would be archived and write nothing").option("--json","Machine-readable output for agents").example(" kadence compact --dry-run").example(" kadence compact --keep-months 3").action(e=>{let n=We("keep-months"),t=e.keepMonths===void 0?void 0:Number(n??e.keepMonths);p(Pn(process.cwd(),process.env,{...t===void 0?{}:{keepMonths:t,keepMonthsRaw:n??String(e.keepMonths)},...e.dryRun===!0?{dryRun:!0}:{},json:e.json===!0}),e.json===!0)});T.command("completion [action]",'Shell completion; "install" writes it where your shell looks').option("--shell <name>",`Shell: ${ae.join(" | ")}; detected from $SHELL by default`).option("--force","Overwrite a completion file kadence did not write").option("--json","Machine-readable output for agents").example(" kadence completion print the script").example(" kadence completion install --shell zsh").action((e,n)=>{let t=n.json===!0;e!==void 0&&e!=="install"&&p(w(`Unknown completion action "${e}".`,{received:e,allowed:["install"]}),t),p(Xn(process.env,{...n.shell===void 0?{}:{shell:n.shell},...e==="install"?{install:!0}:{},...n.force===!0?{force:!0}:{},isTty:process.stdout.isTTY===!0}),t)});T.command("init","Set up kadence in this repository").option("--hooks","Also add a SessionStart hook running `kadence prime` to .claude/settings.json").example(" kadence init").example(" kadence init --hooks").action(e=>{let n=kn(process.cwd(),"0.7.0",{hooks:e.hooks===!0});p({ok:n.ok,message:n.message,exitCode:n.ok?0:1},!1)});T.command("task [action] [arg] [value] [extra]","Tasks: add | list | show | move | assign | ac | doc").option("--title <text>","New title (for edit)").option("-d, --description <text>","Full description; use quotes for multiple lines").option("--type <type>",`Type: ${kt.join(" | ")}`).option("--priority <level>",`Priority: ${bt.join(" | ")}`).option("-a, --assignee <who>","Assignee, e.g. dev@example.com").option("--label <name>","Label; repeat the flag for several. On edit, the set becomes exactly this").option("--add-label <name>","Add one label, leaving the rest; repeat for several").option("--remove-label <name>","Remove one label, leaving the rest; repeat 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: ${Ke.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: ${At.join(" | ")}`).option("--tree","Show parent/child structure").option("--branch","Only the work this branch introduced").option("--base <name>","What --branch compares against; main by default").option("--parent <task>",'Parent task, e.g. KAD-1 (use "none" to detach)').option("--template <name>","Pre-fill fields from a saved template").option("--no-dod","Skip the board's definition of done for this task").option("--fields <list>","JSON only: comma-separated task fields to return").option("--limit <n>","list: at most this many; 0 for all of them").option("--offset <n>","list: start the page here; use with --limit").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 --branch what this branch is about").example(" kadence task list --branch --base release/1.0").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 claim take the top of `kadence ready`").example(" kadence task claim KAD-1").example(" kadence task release KAD-1").example(' kadence task ac add KAD-1 "tests green"').example(" kadence task ac check KAD-1 1").example(" kadence task ac list KAD-1").example(" kadence task doc add KAD-1 docs/design.md create it and link it").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,n,t,o,s)=>{let r=s.json===!0,i=process.cwd();switch(e===void 0&&p(w(`Which action?
|
|
328
341
|
kadence task add "Fix login"
|
|
329
342
|
kadence task list
|
|
330
343
|
kadence task show KAD-1
|
|
@@ -335,36 +348,36 @@ Available: ${ys.join(", ")}`,{received:e,allowed:ys}),s)}});D.command("schema","
|
|
|
335
348
|
kadence task cancel KAD-1
|
|
336
349
|
kadence task delete KAD-1`),r),e){case"add":{n===void 0&&p(w(`A title is required:
|
|
337
350
|
kadence task add "Fix login"`),r);let a=s.estimate===void 0?void 0:Number(s.estimate);a!==void 0&&(!Number.isFinite(a)||a<0)&&p(w(`Estimate must be a positive number, got "${s.estimate}".
|
|
338
|
-
kadence task add "Fix login" --estimate 3`),r);let d={};if(s.template!==void 0){let c=
|
|
351
|
+
kadence task add "Fix login" --estimate 3`),r);let d={};if(s.template!==void 0){let c=Ns(i,process.env,s.template);"error"in c?p(c.error,r):d=c.fields}let l=s.label===void 0?void 0:Array.isArray(s.label)?s.label:[s.label];p(Ct(i,process.env,n,{...d,...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}:{},...l!==void 0?{labels:l}:{},...s.due!==void 0?{due:s.due}:{},...s.parent!==void 0?{parent:s.parent}:{},...a!==void 0?{estimate:a}:{},...s.dod===!1?{noDod:!0}:{}}),r);break}case"doc":{let a=n==="add",d=a?t:n,l=a?o:t;(d===void 0||l===void 0)&&p(w(`A task and a path are required:
|
|
339
352
|
kadence task doc KAD-1 docs/design.md link an existing file
|
|
340
|
-
kadence task doc add KAD-1 docs/design.md create it and link it`),r),p(
|
|
353
|
+
kadence task doc add KAD-1 docs/design.md create it and link it`),r),p(Pt(i,process.env,d,l,a),r);break}case"log":(n===void 0||t===void 0)&&p(w(`A task and a duration are required:
|
|
341
354
|
kadence task log KAD-1 2h
|
|
342
|
-
kadence task log KAD-1 90m`),r),p(
|
|
355
|
+
kadence task log KAD-1 90m`),r),p(Ue(i,process.env,n,t),r);break;case"parent":(n===void 0||t===void 0)&&p(w(`A task and a parent are required:
|
|
343
356
|
kadence task parent KAD-2 KAD-1
|
|
344
|
-
kadence task parent KAD-2 none to detach`),r),p(
|
|
357
|
+
kadence task parent KAD-2 none to detach`),r),p(Ut(i,process.env,n,t),r);break;case"ac":{if((n===void 0||t===void 0)&&p(w(`An action and a task are required:
|
|
345
358
|
kadence task ac add KAD-1 "tests green"
|
|
346
359
|
kadence task ac check KAD-1 1
|
|
347
360
|
kadence task ac uncheck KAD-1 1
|
|
348
|
-
kadence task ac list KAD-1`,{...n===void 0?{}:{received:n},allowed:["add","check","uncheck","list"]}),r),n==="list"){p(
|
|
361
|
+
kadence task ac list KAD-1`,{...n===void 0?{}:{received:n},allowed:["add","check","uncheck","list"]}),r),n==="list"){p(Kt(i,process.env,t),r);break}if(o===void 0&&p(w(n==="add"?`The criterion text is missing:
|
|
349
362
|
kadence task ac add ${t} "tests green"`:`Which criterion?
|
|
350
|
-
kadence task ac ${n} ${t} 1`,{received:n}),r),n==="add"){p(
|
|
351
|
-
kadence task release KAD-1`),r),p(
|
|
363
|
+
kadence task ac ${n} ${t} 1`,{received:n}),r),n==="add"){p(Wt(i,process.env,t,o),r);break}if(n==="check"||n==="uncheck"){p(Bt(i,process.env,t,o,n==="uncheck"),r);break}p(w(`Unknown criteria action "${n}".`,{received:n,allowed:["add","check","uncheck","list"]}),r);break}case"claim":p(It(i,process.env,n,s.assignee===void 0?{}:{assignee:s.assignee}),r);break;case"release":n===void 0&&p(w(`Which task?
|
|
364
|
+
kadence task release KAD-1`),r),p(Lt(i,process.env,n),r);break;case"block":case"unblock":(n===void 0||t===void 0)&&p(w(`A task and a blocker are required:
|
|
352
365
|
kadence task block KAD-2 KAD-1 KAD-2 waits for KAD-1
|
|
353
|
-
kadence task unblock KAD-2 KAD-1`),r),p(
|
|
354
|
-
kadence task edit KAD-1 --priority high`),r);let a=s.estimate===void 0?void 0:Number(s.estimate);a!==void 0&&(!Number.isFinite(a)||a<0)&&p(w(`Estimate must be a positive number, got "${s.estimate}".`),r);let d=
|
|
355
|
-
kadence task comment KAD-1 "text"`),r);let a=
|
|
356
|
-
kadence task cancel KAD-1`),r),p(
|
|
357
|
-
kadence task delete KAD-1`),r),p(
|
|
358
|
-
kadence task show KAD-1`),r),p(
|
|
366
|
+
kadence task unblock KAD-2 KAD-1`),r),p(Ht(i,process.env,n,t,e==="unblock"),r);break;case"edit":{n===void 0&&p(w(`Which task?
|
|
367
|
+
kadence task edit KAD-1 --priority high`),r);let a=s.estimate===void 0?void 0:Number(s.estimate);a!==void 0&&(!Number.isFinite(a)||a<0)&&p(w(`Estimate must be a positive number, got "${s.estimate}".`),r);let d=f=>f===void 0?void 0:Array.isArray(f)?f:[f],l=d(s.label),c=d(s.addLabel),u=d(s.removeLabel),m=s.title!==void 0||s.description!==void 0||s.type!==void 0||s.priority!==void 0||s.due!==void 0||a!==void 0||l!==void 0||c!==void 0||u!==void 0||t!==void 0,g=s.description;if(!m){let f=Fe(i,process.env,n);f.ok||p(f,r);let S=f.data.task??{description:null};g=Ms(void 0,S.description??"",`Editing the description of ${n}.`,r)}p(Ot(i,process.env,n,{...s.title!==void 0?{title:s.title}:t!==void 0?{title:t}:{},...g!==void 0?{description:g}:{},...s.type!==void 0?{type:s.type}:{},...s.priority!==void 0?{priority:s.priority}:{},...s.due!==void 0?{due:s.due}:{},...a!==void 0?{estimate:a}:{},...l!==void 0?{labels:l}:{},...c!==void 0?{addLabels:c}:{},...u!==void 0?{removeLabels:u}:{}}),r);break}case"comment":{n===void 0&&p(w(`Which task?
|
|
368
|
+
kadence task comment KAD-1 "text"`),r);let a=Ms(t,"",`Comment on ${n}.`,r);p(Ft(i,process.env,n,a??""),r);break}case"cancel":n===void 0&&p(w(`Which task?
|
|
369
|
+
kadence task cancel KAD-1`),r),p(Nt(i,process.env,n),r);break;case"delete":n===void 0&&p(w(`Which task?
|
|
370
|
+
kadence task delete KAD-1`),r),p(Mt(i,process.env,n),r);break;case"list":{let a=le(s);a.error!==null&&p(a.error,r),p(jt(i,process.env,{...a.limit!==void 0?{limit:a.limit}:{},...a.offset!==void 0?{offset:a.offset}:{},...s.status!==void 0?{status:s.status}:{},...s.search!==void 0?{search:s.search}:{},...s.type!==void 0?{type:s.type}:{},...s.priority!==void 0?{priority:s.priority}:{},...s.assignee!==void 0?{assignee:s.assignee}:{},...s.label!==void 0?{label:Array.isArray(s.label)?s.label.at(-1):s.label}:{},...s.overdue===!0?{overdue:!0}:{},...s.dueBefore!==void 0?{dueBefore:s.dueBefore}:{},...s.sort!==void 0?{sort:s.sort}:{},...s.tree===!0?{tree:!0}:{},...s.branch===!0?{branch:!0}:{},...s.base!==void 0?{base:s.base}:{},...r&&s.fields!==void 0?{fields:s.fields}:{}}),r);break}case"show":n===void 0&&p(w(`Which task?
|
|
371
|
+
kadence task show KAD-1`),r),p(Fe(i,process.env,n),r);break;case"move":(n===void 0||t===void 0)&&p(w(`A task and a target status are required:
|
|
359
372
|
kadence task move KAD-1 done
|
|
360
|
-
Statuses: ${
|
|
373
|
+
Statuses: ${Ke.join(", ")}`),r),p(Dt(i,process.env,n,t),r);break;case"assign":(n===void 0||t===void 0)&&p(w(`A task and an assignee are required:
|
|
361
374
|
kadence task assign KAD-1 dev@example.com
|
|
362
|
-
kadence task assign KAD-1 none to unassign`),r),p(
|
|
375
|
+
kadence task assign KAD-1 none to unassign`),r),p(Et(i,process.env,n,t),r);break;default:p(w(`Unknown action "${e}".
|
|
363
376
|
Available: add, list, show, edit, move, assign, comment, log,
|
|
364
377
|
parent, block, unblock, cancel, delete
|
|
365
|
-
kadence task --help`,{received:e,allowed:
|
|
378
|
+
kadence task --help`,{received:e,allowed:Mr}),r)}});T.command("board [action]",'Kanban board in the terminal; "config" edits it, "export" writes a snapshot').option("--fields <list>","JSON only: comma-separated task fields to return").option("--statuses <list>",'Comma-separated columns, e.g. "todo,doing,done"').option("--dod <list>",'Criteria every new task starts with, e.g. "tests green,docs updated"').option("--started <status>","The column where work counts as started; cycle time is measured from it").option("--summary","JSON only: column state without history or comments").option("--html","export: one self-contained HTML file, no server and no network").option("--md","export: markdown for a README or a pull request").option("--readme","export: update the section between markers in README.md").option("--file <path>","export: where to write it").option("-a, --assignee <who>",`Only this person's tasks; "me" means you`).option("--sprint","Only tasks in the active sprint").option("--limit <n>","At most this many tasks across the board; 0 for all of them").option("--offset <n>","Start the page here, counted across the columns").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 --json --summary the state, without the history").example(" kadence board config").example(' kadence board config --statuses "todo,doing,review,done"').example(' kadence board config --dod "tests green,docs updated"').example(" kadence board config --started doing where cycle time starts counting").example(" kadence board export --html").example(" kadence board export --md --readme").action((e,n)=>{let t=le(n);if(t.error!==null&&p(t.error,n.json===!0),e==="export"){p(Ts(process.cwd(),process.env,{...n.html===!0?{html:!0}:{},...n.md===!0?{md:!0}:{},...n.readme===!0?{readme:!0}:{},...n.file===void 0?{}:{file:n.file}}),n.json===!0);return}e==="config"&&p(Ds(process.cwd(),process.env,n.statuses,n.dod,n.started),n.json===!0),e!==void 0&&p(w(`Unknown action "${e}".
|
|
366
379
|
Available: config, export
|
|
367
|
-
kadence board --help`,{received:e,allowed:["config","export"]}),n.json===!0),p(
|
|
380
|
+
kadence board --help`,{received:e,allowed:["config","export"]}),n.json===!0),p(js(process.cwd(),process.env,{...n.assignee!==void 0?{assignee:n.assignee}:{},...n.sprint===!0?{sprint:"active"}:{},...t.limit!==void 0?{limit:t.limit}:{},...t.offset!==void 0?{offset:t.offset}:{}},n.json===!0?n.fields:void 0,n.json===!0&&n.summary===!0),n.json===!0)});T.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,n,t)=>{let o=t.json===!0,s=process.cwd();switch(e===void 0&&p(w(`Which action?
|
|
368
381
|
kadence sprint create "Sprint 1"
|
|
369
382
|
kadence sprint add KAD-1
|
|
370
383
|
kadence sprint edit --start 2026-09-01
|
|
@@ -372,17 +385,17 @@ Available: config, export
|
|
|
372
385
|
kadence sprint close
|
|
373
386
|
kadence sprint status
|
|
374
387
|
kadence sprint list`),o),e){case"create":n===void 0&&p(w(`A sprint name is required:
|
|
375
|
-
kadence sprint create "Sprint 1"`),o),p(
|
|
388
|
+
kadence sprint create "Sprint 1"`),o),p(qt(s,process.env,n),o);break;case"add":n===void 0&&p(w(`Which task?
|
|
376
389
|
kadence sprint add KAD-1
|
|
377
|
-
kadence sprint add KAD-1 --sprint "Sprint 2"`),o),p(
|
|
390
|
+
kadence sprint add KAD-1 --sprint "Sprint 2"`),o),p(Gt(s,process.env,n,t.sprint===void 0?{}:{sprint:t.sprint}),o);break;case"edit":p(en(s,process.env,n,{...t.name!==void 0?{name:t.name}:{},...t.description!==void 0?{description:t.description}:{},...t.start!==void 0?{startDate:t.start}:{},...t.end!==void 0?{endDate:t.end}:{}}),o);break;case"start":p(Qt(s,process.env,n),o);break;case"close":p(Vt(s,process.env),o);break;case"status":p(Zt(s,process.env),o);break;case"list":p(Xt(s,process.env),o);break;case"burndown":p(nn(s,process.env,n),o);break;default:p(w(`Unknown action "${e}".
|
|
378
391
|
Available: create, add, edit, start, close, status, list, burndown
|
|
379
|
-
kadence sprint --help`,{received:e,allowed:
|
|
380
|
-
kadence template save bug --type bug`),o);let r=t.label===void 0?void 0:Array.isArray(t.label)?t.label:[t.label];p(
|
|
381
|
-
kadence template delete bug`),o),p(
|
|
382
|
-
Available: save, list, delete`,{received:e,allowed:
|
|
383
|
-
kadence task add "Fix login" --estimate 3`,{received:process.argv[
|
|
384
|
-
`),process.exit(1));let n=
|
|
392
|
+
kadence sprint --help`,{received:e,allowed:_r}),o)}});T.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,n,t)=>{let o=t.json===!0,s=process.cwd();switch(e){case"save":{n===void 0&&p(w(`A template name is required:
|
|
393
|
+
kadence template save bug --type bug`),o);let r=t.label===void 0?void 0:Array.isArray(t.label)?t.label:[t.label];p(Rs(s,process.env,n,{...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}:{},...r!==void 0?{labels:r}:{},...t.estimate!==void 0?{estimate:Number(t.estimate)}:{}}),o);break}case"list":case void 0:p(Es(s,process.env),o);break;case"delete":n===void 0&&p(w(`Which template?
|
|
394
|
+
kadence template delete bug`),o),p(Os(s,process.env,n),o);break;default:p(w(`Unknown action "${e}".
|
|
395
|
+
Available: save, list, delete`,{received:e,allowed:Pr}),o)}});T.command("ui","Interactive kanban board").alias("board:ui").example(" kadence ui").action(async()=>{let{runUi:e}=await import("./chunks/ui-O7JSS6KE.js"),n=await e(process.cwd(),process.env);n.ok||p(n,!1)});var Ps=["init","prime","ready","task","decision","note","doc","board","ui","schema","sprint","milestone","template","report","stats","compact","completion"],Is=e=>{let n=Ps.indexOf(e);return n===-1?Ps.length:n};T.commands.sort((e,n)=>Is(e.name)-Is(n.name));T.help();T.version("0.7.0");var ee=process.argv;if(ee[2]==="task"&&ee[3]==="log"&&ee[4]!==void 0&&ee[5]!==void 0){let e=Ue(process.cwd(),process.env,ee[4],ee[5]),n=ee.includes("--json");p(e,n)}var dt=process.argv.slice(2).includes("--json"),at=process.argv.findIndex((e,n)=>e.startsWith("-")&&/^-\d+(\.\d+)?$/.test(e)&&process.argv[n-1]==="--estimate");at!==-1&&p(w(`Estimate must be a positive number, got "${process.argv[at]}".
|
|
396
|
+
kadence task add "Fix login" --estimate 3`,{received:process.argv[at]}),dt);var Br=new Set(["label","addLabel","removeLabel","rejected","doc"]);function Kr(e){for(let[n,t]of Object.entries(e))n==="--"||Br.has(n)||!Array.isArray(t)||(e[n]=t.at(-1))}function Ls(e){e.name!=="CACError"&&(Le(2,`${e.stack??e.message}
|
|
397
|
+
`),process.exit(1));let n=T.matchedCommandName,t=/Unknown option `([^`]+)`/.exec(e.message)?.[1],o=n===void 0?"kadence --help":`kadence ${n} --help`;p(w(`${e.message}.
|
|
385
398
|
See what it takes:
|
|
386
|
-
${o}`,t===void 0?{}:{received:t}),
|
|
399
|
+
${o}`,t===void 0?{}:{received:t}),dt)}try{T.parse(process.argv,{run:!1});let e=T.options.help===!0||T.options.version===!0;if(T.matchedCommand===void 0&&!e){let t=T.args[0];t===void 0&&(T.outputHelp(),process.exit(0)),p(w(`Unknown command "${String(t)}".
|
|
387
400
|
See all commands:
|
|
388
|
-
kadence --help`,{received:String(t),allowed:
|
|
401
|
+
kadence --help`,{received:String(t),allowed:T.commands.map(o=>o.name)}),dt)}Kr(T.options);let n=T.runMatchedCommand();n instanceof Promise&&n.catch(t=>Ls(t))}catch(e){Ls(e)}
|