kaizen-agent 1.8.1 → 1.9.1
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/README.md +10 -0
- package/cli/build-web.ts +27 -0
- package/cli/install.ts +6 -4
- package/cli/notes.test.ts +221 -0
- package/cli/notes.ts +139 -0
- package/cli/web.ts +59 -4
- package/package.json +12 -2
- package/web/board.html +27 -1
- package/web/notebook.js +36 -0
- package/web/notebook.ts +696 -0
- package/web/notes-lib.ts +135 -0
- package/web/notes.html +214 -0
package/web/board.html
CHANGED
|
@@ -166,6 +166,8 @@ aside .foot{padding:16px 24px;border-top:1px solid var(--line);display:flex;gap:
|
|
|
166
166
|
aside .foot:empty{display:none}
|
|
167
167
|
.md h3{font-size:12px;text-transform:uppercase;letter-spacing:.08em;color:var(--dim);margin:20px 0 8px}.md h3:first-child{margin-top:0}
|
|
168
168
|
.md p{margin:0 0 10px;max-width:62ch}.md ol,.md ul{display:block;padding:0 0 0 1.4em;margin:0 0 10px;list-style:revert}.md li{margin:3px 0}
|
|
169
|
+
.md .lnk a{color:var(--accent);text-underline-offset:3px}
|
|
170
|
+
.md .hit{outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--r-s);transition:outline-color .6s}
|
|
169
171
|
.md li.tk{list-style:none;margin-left:-1.4em}.md li.tk label{display:flex;gap:8px;align-items:baseline}.md li.tk input{flex:none;margin:0;accent-color:var(--accent);position:relative;top:2px;cursor:default}.md li.rej{color:var(--dim);text-decoration:line-through}
|
|
170
172
|
.md pre{background:var(--bg);border:1px solid var(--line);border-radius:var(--r-s);padding:10px 12px;overflow-x:auto;margin:0 0 10px;font:12px/1.5 var(--mono)}
|
|
171
173
|
.md h1,.md h2{font-size:15px;font-weight:600;margin:20px 0 8px}.md h1:first-child,.md h2:first-child{margin-top:0}.md code{font:12px var(--mono);background:var(--bg);padding:1px 5px;border-radius:var(--r-s)}.md table{border-collapse:collapse;font-size:12px;margin:0 0 10px}.md td,.md th{border:1px solid var(--line);padding:4px 8px;text-align:left}.md hr{border:0;border-top:1px solid var(--line);margin:14px 0}
|
|
@@ -207,6 +209,7 @@ aside .foot:empty{display:none}
|
|
|
207
209
|
<symbol id="i-mic" viewBox="0 0 24 24"><rect x="9" y="3" width="6" height="11" rx="3"/><path d="M5 11a7 7 0 0 0 14 0M12 18v3M9 21h6"/></symbol>
|
|
208
210
|
<symbol id="i-pen" viewBox="0 0 24 24"><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z"/></symbol>
|
|
209
211
|
<symbol id="i-x" viewBox="0 0 24 24"><path d="M18 6L6 18M6 6l12 12"/></symbol>
|
|
212
|
+
<symbol id="i-note" viewBox="0 0 24 24"><path d="M6 3h9l4 4v14H6z"/><path d="M14 3v5h5M9 13h6M9 17h6"/></symbol>
|
|
210
213
|
<symbol id="i-trash" viewBox="0 0 24 24"><path d="M3 6h18M8 6V4h8v2M6 6l1 14h10l1-14M10 11v6M14 11v6"/></symbol>
|
|
211
214
|
<symbol id="i-close" viewBox="0 0 24 24"><path d="M18 6L6 18M6 6l12 12"/></symbol>
|
|
212
215
|
<symbol id="i-more" viewBox="0 0 24 24"><circle cx="5" cy="12" r="1.2" fill="currentColor"/><circle cx="12" cy="12" r="1.2" fill="currentColor"/><circle cx="19" cy="12" r="1.2" fill="currentColor"/></symbol>
|
|
@@ -235,6 +238,7 @@ aside .foot:empty{display:none}
|
|
|
235
238
|
<div class="combo" id="combo"><button class="sel" id="proj" aria-label="project" aria-haspopup="listbox" aria-expanded="false"></button><div class="menu-pop" id="projpop" hidden><input class="sel" id="projq" aria-label="Search projects" placeholder="Search projects…" spellcheck="false" autocomplete="off"><div id="projs" role="listbox"></div></div></div>
|
|
236
239
|
<span class="sp"></span>
|
|
237
240
|
<button class="btn pri" id="newtop">New idea</button>
|
|
241
|
+
<a class="ib" href="/notebook" title="Notebook" aria-label="Notebook"><svg><use href="#i-note"/></svg></a>
|
|
238
242
|
<button class="ib" id="sources" title="Request sources" aria-label="Request sources"><svg><use href="#i-link"/></svg></button>
|
|
239
243
|
<button class="ib" id="settings" title="Settings" aria-label="Settings"><svg><use href="#i-gear"/></svg></button>
|
|
240
244
|
</div>
|
|
@@ -534,6 +538,10 @@ async function openRun(c,refresh,again){
|
|
|
534
538
|
chat(c,doc,ro);}
|
|
535
539
|
else $("pbody").innerHTML=doc?md(doc,k==="backlog"):`<p style="color:var(--dim)">No ${({request:"request",plan:"plan",impl:"work report",preview:"preview",review:"review",backlog:"backlog"})[k]} yet.</p>`;
|
|
536
540
|
if(k==="review")fixForm(c);
|
|
541
|
+
// The notebook's notes that link here, each opening that note: above the run's own notes.
|
|
542
|
+
if(k==="notes"&&runDoc.linkedFrom&&runDoc.linkedFrom.length)$("pbody").insertAdjacentHTML("afterbegin",`<h3>Linked from notes</h3><ul class="lnk">${runDoc.linkedFrom.map(n=>`<li><a href="/notebook?dir=${encodeURIComponent(c.state)}&note=${encodeURIComponent(n)}">${esc(n)}</a></li>`).join("")}</ul>`);
|
|
543
|
+
// Only the panel the link asked for: another card opened meanwhile drops the mark.
|
|
544
|
+
if(hit&&!refresh){if(hit.k===key(c))mark(hit);else hit=null}
|
|
537
545
|
const foot=$("pfoot");
|
|
538
546
|
// A refresh while the commit is being confirmed would wipe the message.
|
|
539
547
|
if(refresh&&foot.querySelector(".inl,[data-busy]"))return;
|
|
@@ -543,6 +551,24 @@ async function openRun(c,refresh,again){
|
|
|
543
551
|
else if(c.status==="done"||c.status==="abandoned")foot.innerHTML=arch;
|
|
544
552
|
else foot.innerHTML=`${arch}<button class="btn ghost" data-a="ab">Abandon run</button>`;
|
|
545
553
|
foot.querySelectorAll("[data-a]").forEach(b=>b.onclick=()=>{const a=b.dataset.a;if(a==="archive"||a==="restore"){toggleArchive(c,a==="archive");return}if(a==="push"){commitPush(c,"",b);return}if(a==="commit"){confirmCommit(c);return}close();mode="reject";modeKey=key(c);render()})}
|
|
554
|
+
// A link from a note (?run= or ?idea=, with dir, tab, item) opens that card's panel;
|
|
555
|
+
// a finding or backlog item named is scrolled to and marked. Found by its text, since
|
|
556
|
+
// the rendered list does not carry the numbers.
|
|
557
|
+
let hit=null;
|
|
558
|
+
function deep(){const p=new URLSearchParams(location.search),d=p.get("dir"),id=p.get("run"),idea=p.get("idea");if(!id&&idea===null)return;
|
|
559
|
+
history.replaceState(null,"",location.pathname+"?all=1");
|
|
560
|
+
const c=S.cards.find(x=>x.state===d&&(id?x.kind==="run"&&x.id===id:x.kind==="idea"&&x.text===idea));
|
|
561
|
+
if(!c){toast(id?"That run is not on this board":"That idea is not on this board");return}
|
|
562
|
+
const m=/^(finding|backlog)-(\d+)$/.exec(p.get("item")||"");
|
|
563
|
+
// An item's tab is its own when the link does not name one.
|
|
564
|
+
const t=["request","notes","plan","work","preview","review","backlog"].indexOf(p.get("tab")||(m?(m[1]==="finding"?"review":"backlog"):""));tab=t<0?0:t;hit=m?{type:m[1],n:+m[2],k:key(c)}:null;open(c)}
|
|
565
|
+
// What md() leaves of a line as text: no backticks or stars, a link reduced to its words.
|
|
566
|
+
function mark(h){hit=null;const flat=t=>String(t).replace(/!?\[([^\]]*)\]\([^)\s]+\)/g,"$1").replace(/[`*]/g,"").replace(/\s+/g," ").trim();
|
|
567
|
+
const b=[...(runDoc.backlog||"").matchAll(/^\s*-\s*(?:open|done|rejected):\s*(.*)$/gm)];
|
|
568
|
+
const text=h.type==="finding"?(runDoc.findings||[]).find(f=>f.n===h.n)?.text:b[h.n-1]?.[1];
|
|
569
|
+
if(!text){toast("That item is not in this run");return}
|
|
570
|
+
const want=flat(text).slice(0,60),el=[...$("pbody").querySelectorAll("li,p")].find(e=>flat(e.textContent).includes(want));
|
|
571
|
+
if(!el)return;el.scrollIntoView({block:"center"});el.classList.add("hit");setTimeout(()=>el.classList.remove("hit"),2400)}
|
|
546
572
|
// Fix picked findings, under the review: open ones ticked, closed ones listed but settled.
|
|
547
573
|
// Unticked numbers live outside the form, which every refresh rebuilds. A finding is one
|
|
548
574
|
// line, so md() gives one paragraph; its wrapper is dropped to sit inline in the label.
|
|
@@ -713,7 +739,7 @@ function listen(){const es=new EventSource("/events");es.onmessage=ev=>{if(ev.da
|
|
|
713
739
|
(async()=>{let d;try{d=localStorage.getItem("kz-proj")}catch(e){}
|
|
714
740
|
if(d&&!urlAll)try{if((await fetch("/cd",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({dir:d})})).ok)all=false;else keep()}catch(e){}
|
|
715
741
|
try{const f=JSON.parse(sessionStorage.getItem("kz-form"));if(f)[mode,modeKey]=f}catch(e){}
|
|
716
|
-
load();listen()})();
|
|
742
|
+
load().then(deep);listen()})();
|
|
717
743
|
</script>
|
|
718
744
|
</body>
|
|
719
745
|
</html>
|