@vpxa/aikit 0.1.179 → 0.1.181

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.
@@ -13,7 +13,7 @@ import{mkdir as e,readFile as t,readdir as n,rm as r,stat as i,writeFile as a}fr
13
13
  `),n.push(`| Pattern | Confidence | Count |`),n.push(`|---------|-----------|-------|`);for(let t of e.patterns)n.push(`| ${t.name} | ${t.confidence} | ${t.count} |`)}else t===`normal`&&n.push(`\n**Patterns:** ${e.patterns.map(e=>e.name).join(`, `)}`);return n.join(`
14
14
  `)}const ct=/^[a-zA-Z0-9_./\-~^@{}]+$/;function lt(e){let{from:t,to:n=`HEAD`,format:r=`grouped`,includeBreaking:i=!0,cwd:a=process.cwd()}=e;if(!ct.test(t))throw Error(`Invalid git ref: ${t}`);if(!ct.test(n))throw Error(`Invalid git ref: ${n}`);let o;try{o=C(`git`,[`log`,`${t}..${n}`,`--format=%H%s%b%an%ai`],{cwd:a,encoding:`utf8`,maxBuffer:10*1024*1024,timeout:3e4})}catch{throw Error(`Git log failed. Ensure "${t}" and "${n}" are valid refs.`)}let s=o.split(``).map(e=>e.trim()).filter(Boolean).map(e=>{let[t=``,n=``,r=``,i=``,a=``]=e.split(``),o=n.match(/^(\w+)(?:\(([^)]*)\))?(!)?:\s*(.+)/);return{hash:t.slice(0,8),type:o?.[1]??`other`,scope:o?.[2]??``,subject:o?.[4]??n,body:r.trim(),author:i.trim(),date:a.trim().split(` `)[0],breaking:!!(o?.[3]||/BREAKING[\s-]CHANGE/i.test(r))}}),c={},l=0;for(let e of s)c[e.type]=(c[e.type]??0)+1,e.breaking&&l++;return{entries:s,markdown:ut(s,r,i),stats:{total:s.length,breaking:l,types:c}}}function ut(e,t,n){let r=[`# Changelog`,``];if(n){let t=e.filter(e=>e.breaking);if(t.length>0){r.push(`## Breaking Changes`,``);for(let e of t)r.push(`- ${e.subject} (${e.hash})`);r.push(``)}}if(t===`grouped`){let t={};for(let n of e)t[n.type]||(t[n.type]=[]),t[n.type].push(n);let n=[`feat`,`fix`,`refactor`,`perf`,`test`,`docs`,`chore`],i={feat:`Features`,fix:`Bug Fixes`,refactor:`Refactoring`,perf:`Performance`,test:`Tests`,docs:`Documentation`,chore:`Chores`,other:`Other`};for(let e of[...n,...Object.keys(t).filter(e=>!n.includes(e))])if(t[e]?.length){r.push(`## ${i[e]??e}`,``);for(let n of t[e]){let e=n.scope?`**${n.scope}:** `:``;r.push(`- ${e}${n.subject} (${n.hash})`)}r.push(``)}}else if(t===`chronological`)for(let t of e){let e=t.scope?`(${t.scope}) `:``;r.push(`- \`${t.date}\` ${t.type}: ${e}${t.subject} (${t.hash})`)}else{let t={};for(let n of e){let e=n.scope||`general`;t[e]||(t[e]=[]),t[e].push(n)}for(let[e,n]of Object.entries(t)){r.push(`## ${e}`,``);for(let e of n)r.push(`- ${e.type}: ${e.subject} (${e.hash})`);r.push(``)}}return r.join(`
15
15
  `)}const dt=/^[a-z0-9][a-z0-9-]*$/,ft=new Map;function pt(e){let t=f(e),n=ft.get(t);if(n!==void 0)return n;try{return C(`git`,[`rev-parse`,`--git-dir`],{cwd:t,timeout:1e4,encoding:`utf8`}),ft.set(t,!0),!0}catch{return ft.set(t,!1),!1}}function mt(e,t,n,r){try{return C(`git`,e,{cwd:t,timeout:1e4,input:n,encoding:`utf8`,stdio:[`pipe`,`pipe`,`pipe`]}).trim()}catch(t){r||console.warn(`Git operation failed (${e.join(` `)}): ${t instanceof Error?t.message:String(t)}`);return}}function ht(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``).slice(0,60)||`untitled`}function gt(e,t,n,r,i){let a=mt([`hash-object`,`-w`,`--stdin`],i,n);if(!a)return;let o=mt([`mktree`],i,`100644 blob ${a}\t${t}\n`);if(!o)return;let s=mt([`rev-parse`,e],i,void 0,!0),c=[`commit-tree`,o];s&&c.push(`-p`,s),c.push(`-m`,r);let l=mt(c,i);if(l)return mt([`update-ref`,e,l],i)===void 0?void 0:l}function _t(){ft.clear()}const vt=new Set;function yt(e){let t=ht(e);return t===`untitled`?`checkpoint`:t}function bt(e={}){let t=e.cwd??process.cwd();return f(e.stateDir??V(t),`checkpoints`)}function xt(e){return`${e}.bak`}function St(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function Ct(e,t,n){if(typeof e!=`string`||e.length<1||e.length>120)throw Error(`Checkpoint label must be 1-120 characters.`);if(!St(t))throw Error(`Checkpoint data must be a JSON-serializable object.`);let r;try{r=JSON.stringify(t)}catch{throw Error(`Checkpoint data must be a JSON-serializable object.`)}if(Buffer.byteLength(r,`utf8`)>5e5)throw Error(`Checkpoint data must be 500KB or less when serialized.`);if(n?.notes!==void 0&&Buffer.byteLength(n.notes,`utf8`)>1e4)throw Error(`Checkpoint notes must be 10KB or less.`);return r}function wt(e,t){try{let t=JSON.parse(e);if(!St(t))throw Error(`Checkpoint data must deserialize to an object.`);return t}catch(e){console.warn(`Corrupt checkpoint payload ${t}: ${e instanceof Error?e.message:String(e)}`);return}}function Tt(e){let t=wt(e.data,e.id);if(t)return{id:e.id,label:e.label,createdAt:e.createdAt,data:t,...e.notes?{notes:e.notes}:{}}}function Et(e){return{id:e.id,label:e.label,createdAt:e.createdAt,...e.notes?{notes:e.notes}:{}}}function Dt(e,t={}){let n=bt(t);if(vt.has(n)||!M(n)){vt.add(n);return}try{let t=F(n).filter(e=>e.endsWith(`.json`));for(let r of t){let t=f(n,r);try{let n=P(t,`utf-8`),i=JSON.parse(n),a=typeof i.id==`string`&&i.id.length>0?i.id:o(r,`.json`);if(typeof i.label!=`string`)throw Error(`Missing checkpoint label.`);if(!St(i.data))throw Error(`Checkpoint data must be a JSON object.`);let s=Ct(i.label,i.data,{notes:i.notes});e.checkpointSave(a,i.label,s,i.notes)}catch(e){console.warn(`Legacy checkpoint import failed for ${t}: ${e instanceof Error?e.message:String(e)}`)}}let r=xt(n);M(r)&&L(r,{recursive:!0,force:!0}),I(n,r),vt.add(n)}catch(e){console.warn(`Legacy checkpoint import failed for ${n}: ${e instanceof Error?e.message:String(e)}`)}}function Ot(e,t,n,r){Dt(e,{cwd:r?.cwd});let i=Ct(t,n,{notes:r?.notes}),a=`${Date.now()}-${yt(t)}`;e.checkpointSave(a,t,i,r?.notes);let o=kt(e,a,{cwd:r?.cwd});if(!o)throw Error(`Failed to load saved checkpoint "${a}".`);return o}function kt(e,t,n={}){Dt(e,n);let r=e.checkpointLoad(t);if(r)return Tt(r)}function At(e,t={}){return Dt(e,t),e.checkpointList(t.label,t.limit).map(Et)}function jt(e,t={}){Dt(e,t);let n=e.checkpointLatest(t.label);if(n)return Tt(n)}function Mt(e,t,n,r={}){Dt(e,r);let i=e.checkpointDiff(t,n);if(!i)return;let a=wt(i.from,t),o=wt(i.to,n);if(!a||!o)return;let s=new Set(Object.keys(a)),c=new Set(Object.keys(o));return{fromId:t,toId:n,added:[...c].filter(e=>!s.has(e)),removed:[...s].filter(e=>!c.has(e)),modified:[...s].filter(e=>c.has(e)).filter(e=>JSON.stringify(a[e])!==JSON.stringify(o[e]))}}function Nt(e,t,n){return Dt(e,{cwd:n?.cwd}),e.checkpointHistory(t,n?.limit??20).map(Et)}function Pt(e,t){Dt(e,{cwd:t?.cwd});let n=t?.keepLast??10,r=t?.dryRun??!0,i=t?.maxAgeDays===void 0?void 0:Date.now()-t.maxAgeDays*864e5,a=t?.label?yt(t.label):void 0,o=t?.label?e.checkpointHistory(t.label):e.checkpointList(),s=new Map;for(let e of o){let t=yt(e.label);if(a&&t!==a)continue;let n=s.get(t);n?n.push(e):s.set(t,[e])}let c=[],l=0;for(let e of s.values())e.forEach((e,t)=>{let r=Date.parse(e.createdAt);if(t<n&&!(i!==void 0&&!Number.isNaN(r)&&r<i)){l+=1;return}c.push(e.id)});if(!r)for(let t of c)e.checkpointDelete(t);return{deleted:c.length,kept:l,labels:[...s.keys()],deletedIds:c}}const Ft=[`.ts`,`.tsx`,`.js`,`.jsx`],It=new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,B.state]);function Lt(e){return e.replace(/\\/g,`/`)}function Rt(e){return e.replace(/[.+^${}()|[\]\\]/g,`\\$&`)}function zt(e,t){let n=Lt(e),r=Lt(t).trim();if(!r)return!1;let i=Rt(r).replace(/\*\*/g,`::DOUBLE_STAR::`).replace(/\*/g,`[^/]*`).replace(/\?/g,`[^/]`).replace(/::DOUBLE_STAR::/g,`.*`);return RegExp(`^${i}$`).test(n)}function Bt(e,t,n){return t.some(t=>zt(e,t)?!0:n?zt(`${e}/`,t):!1)}async function Vt(e,t,r){let a=[],o=t.map(e=>e.toLowerCase());async function s(t){let l=await n(t);for(let n of l){if(It.has(n))continue;let l=u(t,n),f=await i(l),p=Lt(d(e,l));if(f.isDirectory()){Bt(p,r,!0)||await s(l);continue}Bt(p,r,!1)||o.includes(c(n).toLowerCase())&&a.push(l)}}return await s(e),a.sort((e,t)=>e.localeCompare(t)),a}const Ht=B.restorePoints;function Ut(){let e=u(process.cwd(),Ht);return M(e)||N(e,{recursive:!0}),e}function Wt(e,t,n){let r=Ut(),i=`${Date.now()}-${e}`,a={id:i,timestamp:new Date().toISOString(),operation:e,files:t,description:n};z(u(r,`${i}.json`),`${JSON.stringify(a,null,2)}\n`,`utf-8`);let o=F(r).filter(e=>e.endsWith(`.json`)).sort();for(;o.length>50;){let e=o.shift();if(!e)break;try{re(u(r,e))}catch{}}return i}function Gt(){let e=u(process.cwd(),Ht);return M(e)?F(e).filter(e=>e.endsWith(`.json`)).sort().reverse().map(t=>{try{return JSON.parse(P(u(e,t),`utf-8`))}catch(n){return console.debug(`Skipping corrupt restore point ${u(e,t)}: ${n instanceof Error?n.message:String(n)}`),null}}).filter(e=>e!==null):[]}async function Kt(e){let t=u(u(process.cwd(),Ht),`${e}.json`);if(!M(t))throw Error(`Restore point not found: ${e}`);let n=JSON.parse(P(t,`utf-8`)),r=[];for(let e of n.files){let t=s(e.path);M(t)||N(t,{recursive:!0}),await a(e.path,e.content,`utf-8`),r.push(e.path)}return r}function qt(e){return e.replace(/\\/g,`/`)}async function Jt(e){let{rootPath:n,rules:r,extensions:i=Ft,exclude:o=[],dryRun:s=!1}=e,c=r.map(e=>({...e,regex:new RegExp(e.pattern,`g`)})),l=await Vt(n,i,o),u=[],f=new Set,p=0,m=[];for(let e of l){let r=qt(d(n,e)),i=await t(e,`utf-8`),o=i.split(/\r?\n/),l=!1;for(let[e,t]of c.entries())if(!(t.fileFilter&&!zt(r,t.fileFilter)))for(let n=0;n<o.length;n++){let i=o[n];t.regex.lastIndex=0;let a=i.replace(t.regex,t.replacement);i!==a&&(o[n]=a,l=!0,f.add(e),u.push({rule:t.description,path:r,line:n+1,before:i,after:a}))}l&&(p+=1,s||(m.push({path:e,content:i}),await a(e,o.join(`
16
- `),`utf-8`)))}return!s&&m.length>0&&Wt(`codemod`,m,`codemod: ${r.length} rules, ${p} files`),{changes:u,rulesApplied:f.size,filesModified:p,dryRun:s}}const Yt=new se({max:200,ttl:1e3*60*30});function Xt(e){return H(`sha256`).update(e).digest(`hex`).slice(0,16)}function Zt(e,t){let n=Xt(t),r=Yt.get(e);if(Yt.set(e,{hash:n,text:t,timestamp:Date.now()}),!r||r.hash===n)return{text:r?.hash===n?`[No changes since last read]`:t,isDelta:r?.hash===n,hash:n};let i=oe(e,e,r.text,t,`previous`,`current`,{context:3});return i.length>=t.length*.8?{text:t,isDelta:!1,hash:n}:{text:i,isDelta:!0,hash:n}}const Qt=.6;function $t(e){if(!e||e.length===0)return 0;let t=ce(e),n=e.length;return n===0?0:Math.min(t.length/n,Qt)/Qt}function en(e){if(e.length===0)return[];let t=new Map,n=[];for(let r of e){let e=ce(r);n.push(e);for(let n of e)t.set(n,(t.get(n)??0)+1)}let r=[];for(let i=0;i<e.length;i++){let a=e[i],o=n[i];if(!a||o.length===0){r.push(0);continue}let s=Math.min(o.length/a.length,Qt)/Qt,c=0;for(let e of o)(t.get(e)??0)===1&&c++;let l=c/o.length,u=.6*s+.4*l;r.push(Math.min(u,1))}return r}function tn(e){if(!e||e.length===0)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0,r=e.length;for(let e of t.values()){let t=e/r;t>0&&(n-=t*Math.log2(t))}return Math.min(n/6.6,1)}function nn(e){try{return $t(e)}catch{return tn(e)}}function rn(e,t=15){try{let n=F(s(e),{withFileTypes:!0});if(n.length===0)return``;let r=n.slice(0,t).map(e=>e.isDirectory()?`${e.name}/`:e.name),i=n.length>t?`, … (${n.length} total)`:``;return` Available in directory: ${r.join(`, `)}${i}`}catch{return``}}async function an(e,n){let{query:r,maxChars:a=3e3,minScore:o=.3,segmentation:s=`paragraph`}=n,c=n.tokenBudget?n.tokenBudget*4:a,l;if(n.text)l=n.text;else if(n.path){let e;try{e=await i(n.path)}catch(e){let t=e.code;if(t===`ENOENT`){let e=rn(n.path);throw Error(`File not found: ${n.path}. Check the path and try again.${e}`)}throw t===`EACCES`||t===`EPERM`?Error(`Permission denied reading ${n.path}. The file exists but is not accessible.`):e}if(e.isDirectory())throw Error(`Path is a directory: ${n.path}. compact requires a file path, not a directory. Use analyze({ aspect: "structure", path }) or find to explore directories.`);if(e.size>1e7)throw Error(`File too large (${(e.size/1e6).toFixed(1)}MB). compact supports files up to 10MB. Consider splitting or using search instead.`);l=n.cache?(await n.cache.get(n.path)).content:await t(n.path,`utf-8`)}else throw Error(`Either "text" or "path" must be provided`);if(n.mode===`delta`&&n.path){let e=Zt(n.path,l);if(e.isDelta)return{text:e.text,originalChars:l.length,compressedChars:e.text.length,ratio:e.text.length/l.length,segmentsKept:1,segmentsTotal:1}}if(l.length<=c)return{text:l,originalChars:l.length,compressedChars:l.length,ratio:1,segmentsKept:1,segmentsTotal:1};let u=Xe(l,s);if(u.length===0)return{text:``,originalChars:l.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};let d=await e.embed(r);if(d.length===0){let e=l.slice(0,c);return{text:`/* warning: embeddings unavailable — returning unscored text */\n${e}`,originalChars:l.length,compressedChars:e.length,ratio:e.length/l.length,segmentsKept:u.length,segmentsTotal:u.length}}let f=en(u),p=[];for(let t=0;t<u.length;t++){let n=.85*et(d,await e.embed(u[t]))+.15*(f[t]??0);p.push({text:u[t],score:n,index:t})}let m=p.filter(e=>e.score>=o).sort((e,t)=>t.score-e.score),h=[],g=0;for(let e of m){if(g+e.text.length>c){g===0&&(h.push({...e,text:e.text.slice(0,c)}),g=c);break}h.push(e),g+=e.text.length+2}let _=tt(h.sort((e,t)=>t.score-e.score)).map(e=>e.text).join(`
16
+ `),`utf-8`)))}return!s&&m.length>0&&Wt(`codemod`,m,`codemod: ${r.length} rules, ${p} files`),{changes:u,rulesApplied:f.size,filesModified:p,dryRun:s}}const Yt=new se({max:200,ttl:1e3*60*30});function Xt(e){return H(`sha256`).update(e).digest(`hex`).slice(0,16)}function Zt(e,t){let n=Xt(t),r=Yt.get(e);if(Yt.set(e,{hash:n,text:t,timestamp:Date.now()}),!r||r.hash===n)return{text:r?.hash===n?`[No changes since last read]`:t,isDelta:r?.hash===n,hash:n};let i=oe(e,e,r.text,t,`previous`,`current`,{context:3});return i.length>=t.length*.8?{text:t,isDelta:!1,hash:n}:{text:i,isDelta:!0,hash:n}}const Qt=.6;function $t(e){if(!e||e.length===0)return 0;let t=ce(e),n=e.length;return n===0?0:Math.min(t.length/n,Qt)/Qt}function en(e){if(e.length===0)return[];let t=new Map,n=[];for(let r of e){let e=ce(r);n.push(e);for(let n of e)t.set(n,(t.get(n)??0)+1)}let r=[];for(let i=0;i<e.length;i++){let a=e[i],o=n[i];if(!a||o.length===0){r.push(0);continue}let s=Math.min(o.length/a.length,Qt)/Qt,c=0;for(let e of o)(t.get(e)??0)===1&&c++;let l=c/o.length,u=.6*s+.4*l;r.push(Math.min(u,1))}return r}function tn(e){if(!e||e.length===0)return 0;let t=new Map;for(let n of e)t.set(n,(t.get(n)??0)+1);let n=0,r=e.length;for(let e of t.values()){let t=e/r;t>0&&(n-=t*Math.log2(t))}return Math.min(n/6.6,1)}function nn(e){try{return $t(e)}catch{return tn(e)}}function rn(e,t=15){try{let n=F(s(e),{withFileTypes:!0});if(n.length===0)return``;let r=n.slice(0,t).map(e=>e.isDirectory()?`${e.name}/`:e.name),i=n.length>t?`, … (${n.length} total)`:``;return` Available in directory: ${r.join(`, `)}${i}`}catch{return``}}async function an(e,n){let{query:r,maxChars:a=3e3,minScore:o=.3,segmentation:s=`paragraph`}=n,c=n.tokenBudget?n.tokenBudget*4:a,l;if(n.text)l=n.text;else if(n.path){let e;try{e=await i(n.path)}catch(e){let t=e.code;if(t===`ENOENT`){let e=rn(n.path);throw Error(`File not found: ${n.path}. Check the path and try again.${e}`)}throw t===`EACCES`||t===`EPERM`?Error(`Permission denied reading ${n.path}. The file exists but is not accessible.`):e}if(e.isDirectory())throw Error(`Path is a directory: ${n.path}. compact requires a file path, not a directory. Use analyze({ aspect: "structure", path }) or find to explore directories.`);if(e.size>1e7)throw Error(`File too large (${(e.size/1e6).toFixed(1)}MB). compact supports files up to 10MB. Consider splitting or using search instead.`);l=n.cache?(await n.cache.get(n.path)).content:await t(n.path,`utf-8`)}else throw Error(`Either "text" or "path" must be provided`);if(n.mode===`delta`&&n.path){let e=Zt(n.path,l);if(e.isDelta)return{text:e.text,originalChars:l.length,compressedChars:e.text.length,ratio:e.text.length/l.length,segmentsKept:1,segmentsTotal:1}}if(l.length<=c)return{text:l,originalChars:l.length,compressedChars:l.length,ratio:1,segmentsKept:1,segmentsTotal:1};let u=Xe(l,s);if(u.length===0)return{text:``,originalChars:l.length,compressedChars:0,ratio:0,segmentsKept:0,segmentsTotal:0};let d;try{d=await e.embed(r)}catch{d=new Float32Array}if(d.length===0){let e=l.slice(0,c);return{text:`/* warning: embeddings unavailable — returning unscored text */\n${e}`,originalChars:l.length,compressedChars:e.length,ratio:e.length/l.length,segmentsKept:u.length,segmentsTotal:u.length}}let f=en(u),p=[];for(let t=0;t<u.length;t++){let n=await e.embed(u[t]),r=.85*et(d,n)+.15*(f[t]??0);p.push({text:u[t],score:r,index:t})}let m=p.filter(e=>e.score>=o).sort((e,t)=>t.score-e.score),h=[],g=0;for(let e of m){if(g+e.text.length>c){g===0&&(h.push({...e,text:e.text.slice(0,c)}),g=c);break}h.push(e),g+=e.text.length+2}let _=tt(h.sort((e,t)=>t.score-e.score)).map(e=>e.text).join(`
17
17
 
18
18
  `);return{text:_,originalChars:l.length,compressedChars:_.length,ratio:_.length/l.length,segmentsKept:h.length,segmentsTotal:u.length}}const on=/\b(error|fatal|exception|failed|failure|fail|passed|warn|warning|panic|abort|timeout|critical)\b/i,sn=[];function cn(e){sn.push(e),sn.sort((e,t)=>t.priority-e.priority)}function ln(e){for(let t of e)cn(t)}function un(){return sn}function dn(e){return/^(diff --git|commit [0-9a-f]{7,40}|On branch |Your branch )/m.test(e)?`git`:/^\s*[MADRCU?!]{1,2}\s+\S/m.test(e)&&/^##\s/m.test(e)?`git-status`:/^(npm (warn|ERR!|notice)|added \d+ packages?|up to date)/m.test(e)?`npm`:/^(Packages|Progress):/m.test(e)||/pnpm/.test(e)?`pnpm`:/✓|✗|PASS|FAIL|Tests?\s+\d+\s+(passed|failed)/m.test(e)||/^(PASS|FAIL)\s+\S/m.test(e)?`test-runner`:/^(error TS\d+|warning TS\d+|\S+\.tsx?[(:]\d+)/m.test(e)?`tsc`:/^\S+\.\w+:\d+:\d+\s+(error|warning|info)/m.test(e)||/Found \d+ (error|warning)/m.test(e)?`lint`:/^(CONTAINER ID|IMAGE|REPOSITORY|Step \d+\/\d+|--->)/m.test(e)||/docker|Dockerfile/i.test(e)?`docker`:/^(NAME\s+READY|NAMESPACE\s|kubectl)/m.test(e)?`kubectl`:`unknown`}function fn(e,t,n){return[`\n... [${e} chars / ~${t} tokens omitted]\n`,`\n... [${e} chars omitted]\n`,`
19
19
  ... [omitted]
@@ -317,6 +317,15 @@ Load the \`docs\` skill and generate comprehensive documentation:
317
317
 
318
318
  6. **Persist Knowledge** — \`produce_knowledge({ path: "." })\` + \`knowledge({ action: "remember", ... })\` for key findings
319
319
 
320
+ 7. **AGENTS.md** — Generate an agent-friendly project context file at the repo root:
321
+ - Project overview, architecture style, key modules
322
+ - Build/test/run commands
323
+ - Coding conventions and patterns in use
324
+ - Key entry points and data flows
325
+ - Known concerns and tech debt
326
+
327
+ > **Interactive HTML viewers** (C4 diagrams, code tour walkthroughs) are generated by the \`/aikit-docs-site\` command. Use it after this command to produce interactive explorable documentation.
328
+
320
329
  ### Phase 5: Interactive Presentation
321
330
 
322
331
  Present the understanding as a rich interactive dashboard using \`present\`:
@@ -347,91 +356,209 @@ After all phases complete, present a final summary to the user:
347
356
  - **Mark unknowns** with \`[TODO]\` and intent-dependent decisions with \`[ASK USER]\`
348
357
  - **Delegate to specialists**: architecture diagrams → \`c4-architecture\` skill, ADRs → \`adr-skill\`
349
358
  - **Compress between phases** — use \`digest\` and \`stash\` to manage context
350
- - **🛑 STOP after Phase 5** — present results and ask user for feedback before any follow-up work`},"docs-site":{description:`Generate an interactive HTML documentation site with architecture diagrams, process flows, and component docs`,agent:`Orchestrator`,tools:[`onboard`,`analyze`,`produce_knowledge`,`graph`,`search`,`symbol`,`trace`,`file_summary`,`compact`,`digest`,`knowledge`,`browser`,`present`,`check`,`git_context`,`measure`],content:`## Generate Documentation Site
359
+ - **🛑 STOP after Phase 5** — present results and ask user for feedback before any follow-up work`},"docs-site":{description:`Generate interactive HTML documentation C4 architecture viewers and code tour walkthroughs with browser verification`,agent:`Orchestrator`,tools:[`onboard`,`analyze`,`produce_knowledge`,`graph`,`search`,`symbol`,`trace`,`file_summary`,`compact`,`digest`,`knowledge`,`browser`,`present`,`check`,`git_context`,`measure`],content:`## Generate Interactive Documentation Viewers
360
+
361
+ Create interactive HTML documentation using C4 architecture viewers and code tour walkthroughs.
351
362
 
352
- Create a multi-page HTML documentation site using the DocPage manifest system.
363
+ > **Prerequisite:** Run \`/aikit-docs\` first to generate the base markdown documentation and AGENTS.md.
353
364
 
354
- ### Step 1: Analyze Project
365
+ ### Phase 1: Analyze Project
355
366
 
356
367
  \`\`\`
357
- onboard({ path: "." }) # If not done
358
- analyze({ aspect: "structure", path: "." }) # Directory layout
359
- analyze({ aspect: "dependencies", path: "." }) # Module graph
360
- analyze({ aspect: "entry_points", path: "." }) # API surface
361
- analyze({ aspect: "diagram", path: "." }) # Architecture diagram data
368
+ onboard({ path: "." }) # If not done (check status() first)
369
+ analyze({ aspect: "structure", path: "." }) # Directory layout
370
+ analyze({ aspect: "dependencies", path: "." }) # Module graph
371
+ analyze({ aspect: "entry_points", path: "." }) # API surface
372
+ analyze({ aspect: "diagram", path: "." }) # Architecture diagram data
373
+ graph({ action: "find_nodes" }) # Module graph for C4 mapping
374
+ graph({ action: "detect_communities" }) # Natural module clusters
362
375
  \`\`\`
363
376
 
364
- ### Step 2: Determine Pages
377
+ Stash results for use in subsequent phases.
365
378
 
366
- Based on analysis, determine which pages the site needs:
379
+ ### Phase 2: Generate C4 Architecture Data
367
380
 
368
- | Kind | When to include |
369
- |------|-----------------|
370
- | architecture | Always — C4 context + container diagrams |
371
- | process-flow | When the project has workflows, pipelines, or multi-step processes |
372
- | tour | When the project has >5 modules — guided onboarding walkthrough |
373
- | docs-hub | Always — landing page linking all other pages |
374
- | component-detail | For each major module/service (>3 exports) |
375
- | lifecycle-flow | For request lifecycles, event pipelines, build processes |
376
- | data-table-schema | For database schemas, API contracts, config structures |
377
- | report | For metrics dashboards, health reports |
381
+ Create C4 JSON data files for each architectural level. Save to \`docs/architecture/interactive/\`.
378
382
 
379
- ### Step 3: Build Manifest
380
-
381
- Create a DocPage manifest JSON:
383
+ **Required schema MUST match exactly:**
382
384
 
383
385
  \`\`\`json
384
386
  {
385
- "schemaVersion": 1,
386
- "metadata": {
387
- "title": "<Project Name> Documentation",
388
- "description": "Auto-generated documentation site",
389
- "version": "1.0.0",
390
- "generatedAt": "<ISO timestamp>"
391
- },
392
- "pages": [
387
+ "title": "Project Name - C4 Level",
388
+ "description": "What this diagram shows",
389
+ "layout": { "direction": "DOWN", "spacing": 80, "layerSpacing": 120 },
390
+ "nodes": [
393
391
  {
394
- "kind": "docs-hub",
395
- "renderer": "report-template",
396
- "filename": "index.html",
397
- "title": "Documentation Hub",
398
- "payload": { /* docs-hub block data */ }
399
- },
392
+ "id": "unique-string-id",
393
+ "type": "person|system|container|component|database|queue|external",
394
+ "label": "Display Name",
395
+ "description": "What this element does",
396
+ "technology": "Language/framework",
397
+ "parentId": "optional-boundary-id"
398
+ }
399
+ ],
400
+ "edges": [
401
+ {
402
+ "id": "unique-edge-id",
403
+ "source": "source-node-id",
404
+ "target": "target-node-id",
405
+ "label": "Relationship description",
406
+ "technology": "Protocol/transport"
407
+ }
408
+ ]
409
+ }
410
+ \`\`\`
411
+
412
+ **C4 levels to generate:**
413
+ 1. \`system-context.json\` — External actors + the system as a black box
414
+ 2. \`containers.json\` — Major deployable units (services, databases, frontends)
415
+ 3. \`{component-name}-components.json\` — Internal structure of key containers
416
+
417
+ **Critical rules:**
418
+ - Top-level keys are \`nodes\` and \`edges\` (NOT \`elements\`/\`relationships\`)
419
+ - Every edge MUST have a unique \`id\` field (ELK crashes without it)
420
+ - Node \`type\` MUST be one of: person, system, container, component, database, queue, external
421
+ - \`layout.direction\` MUST be: DOWN, UP, LEFT, or RIGHT
422
+ - \`parentId\` references must point to existing node IDs (or omit entirely)
423
+
424
+ ### Phase 3: Generate Tour Data
425
+
426
+ Create code tour JSON files. Save to \`docs/tours/interactive/\`.
427
+
428
+ **Required schema — MUST match exactly:**
429
+
430
+ \`\`\`json
431
+ {
432
+ "title": "Tour Title",
433
+ "description": "What this tour teaches",
434
+ "estimatedTime": "15 min",
435
+ "steps": [
400
436
  {
401
- "kind": "architecture",
402
- "renderer": "canvas",
403
- "filename": "architecture.html",
404
- "title": "System Architecture",
405
- "payload": { /* C4 nodes + edges */ }
437
+ "stepNumber": 1,
438
+ "id": "kebab-case-step-id",
439
+ "title": "Step Title",
440
+ "file": "relative/path/to/file.ts",
441
+ "line": 42,
442
+ "explanation": "What this code does and why it matters",
443
+ "learnsConcept": "Concept name",
444
+ "duration": "2 min",
445
+ "notes": "Optional additional context"
406
446
  }
407
- // ... more pages based on Step 2
408
447
  ],
409
- "navigation": [
410
- { "label": "Home", "href": "index.html", "icon": "🏠" },
411
- { "label": "Architecture", "href": "architecture.html", "icon": "🏗️", "category": "Technical" }
412
- // ... matching pages
448
+ "dependencies": [
449
+ { "source": "step-id-1", "target": "step-id-2" }
413
450
  ]
414
451
  }
415
452
  \`\`\`
416
453
 
417
- ### Step 4: Generate Site
454
+ **Tours to generate:**
455
+ 1. \`architecture-overview.json\` — High-level system walkthrough (entry points → core logic → outputs)
456
+ 2. \`onboarding.json\` — New developer guided tour (most important files in dependency order)
457
+ 3. Additional tours for complex subsystems with >5 modules
458
+
459
+ **Critical rules:**
460
+ - Step content field is \`explanation\` (NOT \`description\`)
461
+ - Every step needs \`id\` (kebab-case) and \`stepNumber\` (integer, 1-based)
462
+ - \`learnsConcept\` is the concept tag (NOT \`highlights\`)
463
+ - \`dependencies\` array uses step \`id\` values in \`{source, target}\` objects
464
+ - Root MUST have \`title\`, \`description\`, \`estimatedTime\`
465
+
466
+ ### Phase 4: Inject Data into HTML Templates
418
467
 
419
- Write the manifest to a temp file, then invoke:
468
+ Use PowerShell to inject JSON data into the viewer template HTML files.
420
469
 
470
+ **Template locations:**
471
+ - C4 viewer: \`C:\\Users\\AnVPX\\.copilot\\skills\\c4-architecture\\assets\\c4-viewer.html\` (tag: \`id="diagram-data"\`)
472
+ - Tour viewer: \`C:\\Users\\AnVPX\\.copilot\\skills\\docs\\assets\\tour-viewer.html\` (tag: \`id="tour-data"\`)
473
+
474
+ **Injection procedure (for EACH JSON file):**
475
+
476
+ \`\`\`powershell
477
+ $template = [System.IO.File]::ReadAllText("TEMPLATE_PATH")
478
+ $startTag = '<script type="application/json" id="TARGET_ID">'
479
+ $startIdx = $template.IndexOf($startTag)
480
+ if ($startIdx -lt 0) { throw "Tag not found" }
481
+ $contentStart = $startIdx + $startTag.Length
482
+ $endIdx = $template.IndexOf('<\/script>', $contentStart)
483
+
484
+ $before = $template.Substring(0, $contentStart)
485
+ $after = $template.Substring($endIdx)
486
+ $data = Get-Content "JSON_PATH" -Raw
487
+
488
+ $output = $before + [char]10 + $data + [char]10 + $after
489
+ [System.IO.File]::WriteAllText("OUTPUT_PATH", $output, [System.Text.Encoding]::UTF8)
490
+ \`\`\`
491
+
492
+ **Output file layout:**
421
493
  \`\`\`
422
- run_in_terminal("node packages/viewers/inject-viewer.mjs --manifest manifest.json --out docs/site/")
494
+ docs/
495
+ architecture/interactive/
496
+ system-context.json # Data
497
+ system-context.html # Injected viewer (from c4-viewer.html)
498
+ containers.json
499
+ containers.html
500
+ tours/interactive/
501
+ architecture-overview.json # Data
502
+ architecture-overview.html # Injected viewer (from tour-viewer.html)
503
+ onboarding.json
504
+ onboarding.html
423
505
  \`\`\`
424
506
 
425
- ### Step 5: Verify & Present
507
+ **Rules:**
508
+ - JSON + HTML MUST be siblings in the same \`interactive/\` directory
509
+ - NEVER use \`inject-viewer.mjs\` — use the PowerShell procedure above
510
+ - Verify \`$startIdx -ge 0\` before proceeding
426
511
 
427
- - Check all output files exist in \`docs/site/\`
428
- - Open the hub page: \`browser({ action: 'open', url: 'file:///path/to/docs/site/index.html' })\`
429
- - Present a summary of generated pages
512
+ ### Phase 5: Browser Verification (MANDATORY)
430
513
 
431
- ### Rules
514
+ **Every generated HTML file MUST be tested before presenting to user.**
515
+
516
+ \`\`\`
517
+ # 1. Serve the docs folder
518
+ run_in_terminal("npx -y serve docs -l 4000 --no-clipboard", mode: "async")
519
+
520
+ # 2. Open each viewer
521
+ browser({ action: 'open', url: 'http://localhost:4000/architecture/interactive/system-context.html', mode: 'ui', waitUntil: 'networkidle' })
522
+
523
+ # 3. Read accessibility snapshot
524
+ browser({ action: 'read', pageId: '<id>', readMode: 'snapshot' })
525
+
526
+ # 4. Verify content renders:
527
+ # C4: nodes with labels, edges, Zoom In/Out/Fit buttons, Mini Map
528
+ # Tour: step numbers + titles, Prev/Next buttons, explanation text, file paths
529
+
530
+ # 5. If blank or errors → fix JSON schema → re-inject → re-test
531
+
532
+ # 6. Clean up
533
+ browser({ action: 'session', sessionAction: 'close', pageId: '<id>' })
534
+ kill_terminal(<serve-terminal-id>)
535
+ \`\`\`
536
+
537
+ **Verification checklist:**
538
+
539
+ | Viewer | Must see in snapshot | Failure indicator |
540
+ |--------|---------------------|-------------------|
541
+ | C4 | Node labels, edge groups, Zoom/Fit buttons, Mini Map | Empty page, "Error", no nodes |
542
+ | Tour | Step numbers + titles, Prev/Next, explanation text | Blank panel, "undefined", no steps |
543
+
544
+ ### Phase 6: Present Results
545
+
546
+ After ALL viewers pass verification:
547
+
548
+ 1. List all generated files (JSON + HTML) with descriptions
549
+ 2. Provide the serve command: \`npx -y serve docs -l 4000 --no-clipboard\`
550
+ 3. List all viewer URLs (e.g., \`http://localhost:4000/architecture/interactive/system-context.html\`)
551
+ 4. Note any issues found during verification
552
+
553
+ ### Critical Rules
432
554
 
433
- - All page data must come from AI Kit analysis tools never fabricate
434
- - Architecture diagrams must follow C4 model conventions
435
- - Process flows must use the correct node types (start-end, manual, automated, integration, decision, prerequisite)
436
- - Every page in the manifest must have a corresponding navigation entry
437
- - Use \`knowledge({ action: "remember" })\` to persist the manifest for incremental updates`}};export{e as PROMPTS};
555
+ 1. **NEVER skip browser verification** a valid JSON can still produce a broken viewer
556
+ 2. **NEVER use \`file:///\` URLs** CORS blocks ES modules; always serve via HTTP
557
+ 3. **NEVER use \`inject-viewer.mjs\`** use the PowerShell injection procedure
558
+ 4. **NEVER use \`elements\`/\`relationships\`** the ReactFlow viewer uses \`nodes\`/\`edges\`
559
+ 5. **NEVER omit \`id\` on edges** ELK layout throws null errors
560
+ 6. **NEVER use \`description\` in tour steps** — template reads \`explanation\`
561
+ 7. **ALWAYS use \`npx -y\`** — without \`-y\` the command hangs on install prompt
562
+ 8. **ALWAYS include \`layout\` object in C4 JSON** — ELK crashes without direction/spacing
563
+ 9. **ALWAYS verify \`$startIdx -ge 0\`** before injection — missing tag = wrong template
564
+ 10. **All data must come from AI Kit analysis tools** — never fabricate architecture`}};export{e as PROMPTS};
@@ -45,7 +45,7 @@ function parseArgs(argv) {
45
45
  }
46
46
 
47
47
  function escapeRegExp(value) {
48
- return value.replace(/[|\\{}()[]^$+*?.]/g, '\\$&');
48
+ return value.replace(/[|\\\\{}()\\[\\]^$+*?.]/g, '\\\\$&');
49
49
  }
50
50
 
51
51
  function buildScriptPattern(id) {
@@ -1497,7 +1497,7 @@ Before finalizing any C4 diagram, verify:
1497
1497
  - [ ] Message topics shown individually (not as single broker)
1498
1498
  - [ ] No infrastructure details in container diagrams
1499
1499
  - [ ] Consistent with other diagrams in the set
1500
- `},{file:`references/html-design-system.md`,content:'# HTML/SVG Architecture Diagram Design System\n\nThis file is the centralized design system for HTML and SVG architecture diagrams.\n\nIt is the single source of truth for visual tokens, component categories, layout rules, and `present` tool composition guidance used by the `c4-architecture` skill and the `present` skill. Update component types, colors, layout rules, and icon slots here only.\n\n## Purpose\n\n- Define a reusable visual language for C4-style architecture diagrams rendered as HTML and inline SVG.\n- Keep category styling extensible through a registry instead of hardcoded component types.\n- Standardize diagram composition for both skill-authored documentation and `present` output.\n\n## Core Design Tokens\n\n### Typography\n\n- Font family: `"JetBrains Mono", monospace`\n- Font source: Google Fonts (`https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap`)\n- Component names: `12px`\n- Sublabels: `9px`\n- Annotations: `8px`\n- Tiny labels: `7px`\n- Legend: `10px`\n- Icon area labels: `11px`\n\n### Background\n\n- Page background: `#020617` (`slate-950`)\n- Background pattern: inline SVG grid pattern over the page background\n- Recommended grid line colors:\n - Major grid: `rgba(148, 163, 184, 0.08)`\n - Minor grid: `rgba(148, 163, 184, 0.04)`\n\n### Component Box Defaults\n\n- Shape: rounded rectangle\n- Border radius: `rx="6"`\n- Stroke width: `1.5px`\n- Fill: category-specific semi-transparent RGBA fill\n- Stroke: category-specific hex stroke\n- Label stack:\n - Line 1: C4 label such as `<<Container>>`\n - Line 2: component name\n - Line 3: subtype or technology summary\n\n## Category Registry\n\nThe registry is hierarchical: categories define shared tokens and C4 intent, while sub-types inherit the category styling and reserve an icon slot for future SVG glyphs.\n\n| Category | Stroke Color | Fill Color | C4 Mapping | Sub-types |\n|---|---|---|---|---|\n| Frontend | `#22d3ee` | `rgba(8, 51, 68, 0.4)` | Container (SPA, web) | SPA, Mobile App, Static Site, Micro-frontend, PWA, Desktop App |\n| Backend | `#34d399` | `rgba(6, 78, 59, 0.4)` | Container (service) | API Service, Worker/Job, BFF, Microservice, Serverless Function, gRPC Service |\n| Data | `#a78bfa` | `rgba(76, 29, 149, 0.4)` | ContainerDb | Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, Time-Series DB |\n| Infrastructure | `#fbbf24` | `rgba(120, 53, 15, 0.3)` | Deployment_Node | CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, Service Mesh |\n| Messaging | `#fb923c` | `rgba(251, 146, 60, 0.3)` | ContainerQueue | Message Queue, Event Bus, Stream, Pub/Sub, Webhook |\n| Security | `#fb7185` | `rgba(136, 19, 55, 0.4)` | System_Ext / boundary | Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, Identity Provider |\n| External | `#94a3b8` | `rgba(30, 41, 59, 0.5)` | System_Ext | Third-party API, SaaS, Legacy System, Partner Service, Payment Provider |\n| Monitoring | `#38bdf8` | `rgba(12, 74, 110, 0.4)` | Container | Logging, Metrics, Tracing, Alerting, APM |\n\n## Sub-type Registry\n\nEach sub-type inherits its category tokens and keeps a placeholder slot for an inline SVG icon.\n\n| Category | Sub-type | C4 Label | Icon Slot |\n|---|---|---|---|\n| Frontend | SPA | `<<Container>>` | `icon-spa` |\n| Frontend | Mobile App | `<<Container>>` | `icon-mobile-app` |\n| Frontend | Static Site | `<<Container>>` | `icon-static-site` |\n| Frontend | Micro-frontend | `<<Container>>` | `icon-micro-frontend` |\n| Frontend | PWA | `<<Container>>` | `icon-pwa` |\n| Frontend | Desktop App | `<<Container>>` | `icon-desktop-app` |\n| Backend | API Service | `<<Container>>` | `icon-api-service` |\n| Backend | Worker/Job | `<<Container>>` | `icon-worker-job` |\n| Backend | BFF | `<<Container>>` | `icon-bff` |\n| Backend | Microservice | `<<Container>>` | `icon-microservice` |\n| Backend | Serverless Function | `<<Container>>` | `icon-serverless-function` |\n| Backend | gRPC Service | `<<Container>>` | `icon-grpc-service` |\n| Data | Relational DB | `<<ContainerDb>>` | `icon-relational-db` |\n| Data | Document DB | `<<ContainerDb>>` | `icon-document-db` |\n| Data | Key-Value Store | `<<ContainerDb>>` | `icon-key-value-store` |\n| Data | Cache | `<<ContainerDb>>` | `icon-cache` |\n| Data | Search Engine | `<<ContainerDb>>` | `icon-search-engine` |\n| Data | Data Warehouse | `<<ContainerDb>>` | `icon-data-warehouse` |\n| Data | Graph DB | `<<ContainerDb>>` | `icon-graph-db` |\n| Data | Time-Series DB | `<<ContainerDb>>` | `icon-time-series-db` |\n| Infrastructure | CDN | `<<Deployment_Node>>` | `icon-cdn` |\n| Infrastructure | Load Balancer | `<<Deployment_Node>>` | `icon-load-balancer` |\n| Infrastructure | DNS | `<<Deployment_Node>>` | `icon-dns` |\n| Infrastructure | Object Storage | `<<Deployment_Node>>` | `icon-object-storage` |\n| Infrastructure | Container Registry | `<<Deployment_Node>>` | `icon-container-registry` |\n| Infrastructure | Reverse Proxy | `<<Deployment_Node>>` | `icon-reverse-proxy` |\n| Infrastructure | Service Mesh | `<<Deployment_Node>>` | `icon-service-mesh` |\n| Messaging | Message Queue | `<<ContainerQueue>>` | `icon-message-queue` |\n| Messaging | Event Bus | `<<ContainerQueue>>` | `icon-event-bus` |\n| Messaging | Stream | `<<ContainerQueue>>` | `icon-stream` |\n| Messaging | Pub/Sub | `<<ContainerQueue>>` | `icon-pub-sub` |\n| Messaging | Webhook | `<<ContainerQueue>>` | `icon-webhook` |\n| Security | Auth Provider | `<<System_Ext>>` | `icon-auth-provider` |\n| Security | API Gateway | `<<System_Ext>>` | `icon-api-gateway` |\n| Security | WAF | `<<System_Ext>>` | `icon-waf` |\n| Security | Secret Manager | `<<System_Ext>>` | `icon-secret-manager` |\n| Security | Certificate Manager | `<<System_Ext>>` | `icon-certificate-manager` |\n| Security | Identity Provider | `<<System_Ext>>` | `icon-identity-provider` |\n| External | Third-party API | `<<System_Ext>>` | `icon-third-party-api` |\n| External | SaaS | `<<System_Ext>>` | `icon-saas` |\n| External | Legacy System | `<<System_Ext>>` | `icon-legacy-system` |\n| External | Partner Service | `<<System_Ext>>` | `icon-partner-service` |\n| External | Payment Provider | `<<System_Ext>>` | `icon-payment-provider` |\n| Monitoring | Logging | `<<Container>>` | `icon-logging` |\n| Monitoring | Metrics | `<<Container>>` | `icon-metrics` |\n| Monitoring | Tracing | `<<Container>>` | `icon-tracing` |\n| Monitoring | Alerting | `<<Container>>` | `icon-alerting` |\n| Monitoring | APM | `<<Container>>` | `icon-apm` |\n\n## Icon Registry\n\nIcons are inline SVG `<symbol>` elements with a 16x16 viewBox, rendered via `<use>` at `(x+W-22, y+4)` inside the component box. They use `currentColor` to inherit the category stroke color.\n\n### Category-Level Icons (active)\n\nEach category has a shared icon defined in `html-template.html` `<defs>`. All sub-types within a category use their category icon by default. Sub-type-specific icons can override these in the future.\n\n| Category | Symbol ID | Shape | Status |\n|---|---|---|---|\n| Frontend | `icon-frontend` | Monitor with stand | **active** |\n| Backend | `icon-backend` | Server rack (3 units) | **active** |\n| Data | `icon-data` | Database cylinder | **active** |\n| Infrastructure | `icon-infrastructure` | Cloud | **active** |\n| Messaging | `icon-messaging` | Envelope | **active** |\n| Security | `icon-security` | Shield with checkmark | **active** |\n| External | `icon-external` | Globe with meridians | **active** |\n| Monitoring | `icon-monitoring` | Line chart with axes | **active** |\n\nUsage pattern:\n```svg\n<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>\n```\n\n### Sub-type Icons (planned)\n\nWhen a sub-type icon is added, it overrides the category icon for that specific component. Until implemented, all sub-types use their category icon.\n\n| Sub-type | Icon | Status |\n|---|---|---|\n| SPA | `icon-spa` | planned |\n| Mobile App | `icon-mobile-app` | planned |\n| Static Site | `icon-static-site` | planned |\n| Micro-frontend | `icon-micro-frontend` | planned |\n| PWA | `icon-pwa` | planned |\n| Desktop App | `icon-desktop-app` | planned |\n| API Service | `icon-api-service` | planned |\n| Worker/Job | `icon-worker-job` | planned |\n| BFF | `icon-bff` | planned |\n| Microservice | `icon-microservice` | planned |\n| Serverless Function | `icon-serverless-function` | planned |\n| gRPC Service | `icon-grpc-service` | planned |\n| Relational DB | `icon-relational-db` | planned |\n| Document DB | `icon-document-db` | planned |\n| Key-Value Store | `icon-key-value-store` | planned |\n| Cache | `icon-cache` | planned |\n| Search Engine | `icon-search-engine` | planned |\n| Data Warehouse | `icon-data-warehouse` | planned |\n| Graph DB | `icon-graph-db` | planned |\n| Time-Series DB | `icon-time-series-db` | planned |\n| CDN | `icon-cdn` | planned |\n| Load Balancer | `icon-load-balancer` | planned |\n| DNS | `icon-dns` | planned |\n| Object Storage | `icon-object-storage` | planned |\n| Container Registry | `icon-container-registry` | planned |\n| Reverse Proxy | `icon-reverse-proxy` | planned |\n| Service Mesh | `icon-service-mesh` | planned |\n| Message Queue | `icon-message-queue` | planned |\n| Event Bus | `icon-event-bus` | planned |\n| Stream | `icon-stream` | planned |\n| Pub/Sub | `icon-pub-sub` | planned |\n| Webhook | `icon-webhook` | planned |\n| Auth Provider | `icon-auth-provider` | planned |\n| API Gateway | `icon-api-gateway` | planned |\n| WAF | `icon-waf` | planned |\n| Secret Manager | `icon-secret-manager` | planned |\n| Certificate Manager | `icon-certificate-manager` | planned |\n| Identity Provider | `icon-identity-provider` | planned |\n| Third-party API | `icon-third-party-api` | planned |\n| SaaS | `icon-saas` | planned |\n| Legacy System | `icon-legacy-system` | planned |\n| Partner Service | `icon-partner-service` | planned |\n| Payment Provider | `icon-payment-provider` | planned |\n| Logging | `icon-logging` | planned |\n| Metrics | `icon-metrics` | planned |\n| Tracing | `icon-tracing` | planned |\n| Alerting | `icon-alerting` | planned |\n| APM | `icon-apm` | planned |\n\n## Technology Icon Registry\n\nThe HTML C4 viewer also supports technology-specific SVG icons. It resolves them from each node\'s `technology` field after normalization. Set `icon` on node data when you need an explicit override; `icon` takes precedence over auto-detection from `technology`. If neither `icon` nor a normalized `technology` value matches a registry key, the viewer falls back to the generic C4 type icon for that node, such as person, database, queue, or container.\n\n### Available Keys\n\n- **Cloud:** `aws`, `azure`, `googlecloud`, `cloudflare`, `vercel`, `netlify`\n- **Languages:** `typescript`, `javascript`, `python`, `java`, `go`, `rust`, `csharp`, `php`, `ruby`, `swift`, `kotlin`\n- **Frontend:** `react`, `vuedotjs`, `angular`, `svelte`, `nextdotjs`, `html5`, `css3`\n- **Backend:** `nodedotjs`, `express`, `nestjs`, `django`, `spring`, `dotnet`\n- **Data:** `postgresql`, `mysql`, `mongodb`, `redis`, `elasticsearch`, `amazondynamodb`, `sqlite`\n- **Infrastructure:** `docker`, `kubernetes`, `nginx`, `linux`, `terraform`, `github`\n- **Messaging/API:** `apachekafka`, `rabbitmq`, `graphql`, `grpc`\n\n### Common Aliases\n\nCommon aliases are normalized before lookup. For example: `node` -> `nodedotjs`, `postgres` -> `postgresql`, `k8s` -> `kubernetes`, `vue` -> `vuedotjs`, `next.js` -> `nextdotjs`, `mongo` -> `mongodb`, `kafka` -> `apachekafka`, `gcp` -> `googlecloud`, `c#` -> `csharp`, and `.net` -> `dotnet`.\n\n## Visual Elements\n\n### Component Box Pattern\n\nUse a rounded component box with semi-transparent fill and category stroke.\n\n```svg\n<g class="node backend">\n <rect x="280" y="210" width="190" height="60" rx="6" />\n <text class="c4-tag" x="294" y="226">&lt;&lt;Container&gt;&gt;</text>\n <text class="node-title" x="294" y="243">API Service</text>\n <text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>\n</g>\n```\n\n### Arrow Masking Technique\n\nUse an opaque background rectangle below the box content to visually hide arrows beneath components without breaking the component fill style.\n\n```svg\n<g class="node-mask-layer">\n <rect x="280" y="210" width="190" height="60" rx="6" fill="#020617" />\n <rect x="280" y="210" width="190" height="60" rx="6"\n fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" />\n</g>\n```\n\n### Security Group Boundary\n\n- Purpose: show auth, gateway, WAF, or identity zones\n- Stroke color: rose (`#fb7185`)\n- Pattern: `stroke-dasharray="4,4"`\n- Suggested label: `Security Boundary`\n\n```svg\n<rect x="700" y="140" width="220" height="180" rx="12"\n fill="transparent" stroke="#fb7185" stroke-width="1.5"\n stroke-dasharray="4,4" />\n```\n\n### Region Boundary\n\n- Purpose: group a deployment region, platform segment, or domain slice\n- Stroke color: amber (`#fbbf24`)\n- Pattern: `stroke-dasharray="8,4"`\n- Radius: `rx="12"`\n\n```svg\n<rect x="70" y="120" width="600" height="430" rx="12"\n fill="transparent" stroke="#fbbf24" stroke-width="1.5"\n stroke-dasharray="8,4" />\n```\n\n### Arrow Marker SVG Definition\n\n```svg\n<defs>\n <marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">\n <path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1" />\n </marker>\n</defs>\n```\n\n### Arrow Z-order Rule\n\nDraw arrows early in the SVG so component boxes and masking layers paint over them. This keeps connectors readable in dense diagrams and avoids arrow overlap across component interiors.\n\n## Spacing Rules\n\n- Standard component height: `60px`\n- Minimum vertical gap between stacked components: `40px`\n- Inline connectors should route through gaps rather than through component interiors\n- Keep labels inside the top `28px` of the box and the subtype line inside the lower third\n- Place legends outside boundaries to prevent classification noise inside the diagram area\n\n## Layout Structure\n\nThe canonical page composition is:\n\n1. Header: title, pulse dot, subtitle\n2. Main SVG diagram: embedded inside a rounded border card\n3. Summary cards: grid of 3 cards beneath the diagram\n4. Footer metadata: generator, scope, rendering notes, last-updated stamp\n\n## Present Tool Integration\n\nCompose architecture diagrams with the `present` tool by embedding the full HTML/SVG diagram in a markdown block and pairing it with metrics or cards blocks as needed.\n\n### `format: "html"`\n\nUse a `markdown` block with embedded `<div>`, inline SVG, and a `<style>` tag containing the full CSS. The `present` html format renders raw HTML in markdown blocks.\n\n### `format: "browser"`\n\nUse the same composition: a `markdown` block containing the full HTML structure. Summary content can also be added with `cards` and `metrics` blocks alongside the SVG diagram block.\n\n### Example `present` Call Structure\n\n```js\npresent({\n format: "html", // or "browser"\n title: "System Architecture",\n content: [\n {\n type: "metrics",\n title: "Overview",\n value: [\n { label: "Services", value: "6" },\n { label: "Data Stores", value: "2" },\n { label: "External Systems", value: "3" }\n ]\n },\n {\n type: "markdown",\n title: "Architecture Diagram",\n value: "<div class=\'arch-diagram\'>...(inline SVG)...</div><style>...(design system CSS)...</style>"\n },\n {\n type: "cards",\n title: "Summary",\n value: [\n { title: "Frontend", body: "React SPA..." },\n { title: "Backend", body: "API + async workers..." },\n { title: "Security", body: "Gateway + IdP..." }\n ]\n }\n ]\n})\n```\n\nThis design system is the single source of truth. The `c4-architecture` skill and `present` skill both reference this file. Update component types, colors, or layout rules here only.\n\n## Adding New Categories\n\n1. Add a new row to the Category Registry with the category name, colors, C4 mapping, and initial subtype set.\n2. Add the new sub-types to the Sub-type Registry with a C4 label and icon slot name.\n3. Add icon placeholders to the Icon Registry.\n4. Update [html-template.html](html-template.html) legend content so the new category appears in the rendered template.\n5. Update summary card accent colors in [html-template.html](html-template.html) if the new category needs a dedicated card treatment.\n\n## Template Pairing\n\nSee [html-template.html](html-template.html) for the complete self-contained reference implementation of this design system.\n'},{file:`references/c4.schema.json`,content:JSON.stringify({$schema:`http://json-schema.org/draft-07/schema#`,title:`AIKIT Architecture Diagram`,description:`Schema for AI Kit C4 interactive architecture diagrams. The agent generates JSON matching this schema, which is injected into c4-viewer.html.`,version:`1.0.0`,type:`object`,required:[`title`,`type`,`nodes`,`edges`],properties:{title:{type:`string`,description:`Diagram title displayed in the viewer header`},description:{type:`string`,description:`Brief diagram description`},type:{type:`string`,enum:[`context`,`container`,`component`,`deployment`],description:`C4 diagram level`},layout:{type:`object`,properties:{direction:{type:`string`,enum:[`TB`,`LR`,`BT`,`RL`],default:`TB`},spacing:{type:`number`,default:80},layerSpacing:{type:`number`,default:120}}},nodes:{type:`array`,items:{type:`object`,required:[`id`,`type`,`label`],properties:{id:{type:`string`,description:`Unique node identifier`},type:{type:`string`,enum:[`person`,`system`,`container`,`component`,`database`,`queue`,`external`,`boundary`,`deploymentNode`],description:`C4 element type - determines visual styling`},label:{type:`string`,description:`Display label`},technology:{type:`string`,description:`Technology tag used for display and icon auto-resolution (e.g., 'React', 'PostgreSQL')`},icon:{type:`string`,description:`Optional icon override key. Takes precedence over auto-detection from the technology field. Use Technology Icon Registry keys such as 'react', 'postgresql', or 'docker'.`},description:{type:`string`,description:`Element description shown on hover/expand`},children:{type:`array`,items:{type:`string`},description:`Child node IDs (for boundary/group nodes only)`},x:{type:`number`,description:`Optional fixed x position`},y:{type:`number`,description:`Optional fixed y position`}}}},edges:{type:`array`,items:{type:`object`,required:[`source`,`target`],properties:{id:{type:`string`,description:`Optional edge identifier`},source:{type:`string`,description:`Source node ID`},target:{type:`string`,description:`Target node ID`},label:{type:`string`,description:`Relationship label`},technology:{type:`string`,description:`Protocol/technology (e.g., 'REST/HTTPS')`},style:{type:`string`,enum:[`solid`,`dashed`,`dotted`],default:`solid`},animated:{type:`boolean`,default:!1,description:`Animate the edge (for async/event flows)`}}}}}},null,2)},{file:`SKILL.md`,content:`---
1500
+ `},{file:`references/html-design-system.md`,content:'# HTML/SVG Architecture Diagram Design System\n\nThis file is the centralized design system for HTML and SVG architecture diagrams.\n\nIt is the single source of truth for visual tokens, component categories, layout rules, and `present` tool composition guidance used by the `c4-architecture` skill and the `present` skill. Update component types, colors, layout rules, and icon slots here only.\n\n## Purpose\n\n- Define a reusable visual language for C4-style architecture diagrams rendered as HTML and inline SVG.\n- Keep category styling extensible through a registry instead of hardcoded component types.\n- Standardize diagram composition for both skill-authored documentation and `present` output.\n\n## Core Design Tokens\n\n### Typography\n\n- Font family: `"JetBrains Mono", monospace`\n- Font source: Google Fonts (`https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700;800&display=swap`)\n- Component names: `12px`\n- Sublabels: `9px`\n- Annotations: `8px`\n- Tiny labels: `7px`\n- Legend: `10px`\n- Icon area labels: `11px`\n\n### Background\n\n- Page background: `#020617` (`slate-950`)\n- Background pattern: inline SVG grid pattern over the page background\n- Recommended grid line colors:\n - Major grid: `rgba(148, 163, 184, 0.08)`\n - Minor grid: `rgba(148, 163, 184, 0.04)`\n\n### Component Box Defaults\n\n- Shape: rounded rectangle\n- Border radius: `rx="6"`\n- Stroke width: `1.5px`\n- Fill: category-specific semi-transparent RGBA fill\n- Stroke: category-specific hex stroke\n- Label stack:\n - Line 1: C4 label such as `<<Container>>`\n - Line 2: component name\n - Line 3: subtype or technology summary\n\n## Category Registry\n\nThe registry is hierarchical: categories define shared tokens and C4 intent, while sub-types inherit the category styling and reserve an icon slot for future SVG glyphs.\n\n| Category | Stroke Color | Fill Color | C4 Mapping | Sub-types |\n|---|---|---|---|---|\n| Frontend | `#22d3ee` | `rgba(8, 51, 68, 0.4)` | Container (SPA, web) | SPA, Mobile App, Static Site, Micro-frontend, PWA, Desktop App |\n| Backend | `#34d399` | `rgba(6, 78, 59, 0.4)` | Container (service) | API Service, Worker/Job, BFF, Microservice, Serverless Function, gRPC Service |\n| Data | `#a78bfa` | `rgba(76, 29, 149, 0.4)` | ContainerDb | Relational DB, Document DB, Key-Value Store, Cache, Search Engine, Data Warehouse, Graph DB, Time-Series DB |\n| Infrastructure | `#fbbf24` | `rgba(120, 53, 15, 0.3)` | Deployment_Node | CDN, Load Balancer, DNS, Object Storage, Container Registry, Reverse Proxy, Service Mesh |\n| Messaging | `#fb923c` | `rgba(251, 146, 60, 0.3)` | ContainerQueue | Message Queue, Event Bus, Stream, Pub/Sub, Webhook |\n| Security | `#fb7185` | `rgba(136, 19, 55, 0.4)` | System_Ext / boundary | Auth Provider, API Gateway, WAF, Secret Manager, Certificate Manager, Identity Provider |\n| External | `#94a3b8` | `rgba(30, 41, 59, 0.5)` | System_Ext | Third-party API, SaaS, Legacy System, Partner Service, Payment Provider |\n| Monitoring | `#38bdf8` | `rgba(12, 74, 110, 0.4)` | Container | Logging, Metrics, Tracing, Alerting, APM |\n\n## Sub-type Registry\n\nEach sub-type inherits its category tokens and keeps a placeholder slot for an inline SVG icon.\n\n| Category | Sub-type | C4 Label | Icon Slot |\n|---|---|---|---|\n| Frontend | SPA | `<<Container>>` | `icon-spa` |\n| Frontend | Mobile App | `<<Container>>` | `icon-mobile-app` |\n| Frontend | Static Site | `<<Container>>` | `icon-static-site` |\n| Frontend | Micro-frontend | `<<Container>>` | `icon-micro-frontend` |\n| Frontend | PWA | `<<Container>>` | `icon-pwa` |\n| Frontend | Desktop App | `<<Container>>` | `icon-desktop-app` |\n| Backend | API Service | `<<Container>>` | `icon-api-service` |\n| Backend | Worker/Job | `<<Container>>` | `icon-worker-job` |\n| Backend | BFF | `<<Container>>` | `icon-bff` |\n| Backend | Microservice | `<<Container>>` | `icon-microservice` |\n| Backend | Serverless Function | `<<Container>>` | `icon-serverless-function` |\n| Backend | gRPC Service | `<<Container>>` | `icon-grpc-service` |\n| Data | Relational DB | `<<ContainerDb>>` | `icon-relational-db` |\n| Data | Document DB | `<<ContainerDb>>` | `icon-document-db` |\n| Data | Key-Value Store | `<<ContainerDb>>` | `icon-key-value-store` |\n| Data | Cache | `<<ContainerDb>>` | `icon-cache` |\n| Data | Search Engine | `<<ContainerDb>>` | `icon-search-engine` |\n| Data | Data Warehouse | `<<ContainerDb>>` | `icon-data-warehouse` |\n| Data | Graph DB | `<<ContainerDb>>` | `icon-graph-db` |\n| Data | Time-Series DB | `<<ContainerDb>>` | `icon-time-series-db` |\n| Infrastructure | CDN | `<<Deployment_Node>>` | `icon-cdn` |\n| Infrastructure | Load Balancer | `<<Deployment_Node>>` | `icon-load-balancer` |\n| Infrastructure | DNS | `<<Deployment_Node>>` | `icon-dns` |\n| Infrastructure | Object Storage | `<<Deployment_Node>>` | `icon-object-storage` |\n| Infrastructure | Container Registry | `<<Deployment_Node>>` | `icon-container-registry` |\n| Infrastructure | Reverse Proxy | `<<Deployment_Node>>` | `icon-reverse-proxy` |\n| Infrastructure | Service Mesh | `<<Deployment_Node>>` | `icon-service-mesh` |\n| Messaging | Message Queue | `<<ContainerQueue>>` | `icon-message-queue` |\n| Messaging | Event Bus | `<<ContainerQueue>>` | `icon-event-bus` |\n| Messaging | Stream | `<<ContainerQueue>>` | `icon-stream` |\n| Messaging | Pub/Sub | `<<ContainerQueue>>` | `icon-pub-sub` |\n| Messaging | Webhook | `<<ContainerQueue>>` | `icon-webhook` |\n| Security | Auth Provider | `<<System_Ext>>` | `icon-auth-provider` |\n| Security | API Gateway | `<<System_Ext>>` | `icon-api-gateway` |\n| Security | WAF | `<<System_Ext>>` | `icon-waf` |\n| Security | Secret Manager | `<<System_Ext>>` | `icon-secret-manager` |\n| Security | Certificate Manager | `<<System_Ext>>` | `icon-certificate-manager` |\n| Security | Identity Provider | `<<System_Ext>>` | `icon-identity-provider` |\n| External | Third-party API | `<<System_Ext>>` | `icon-third-party-api` |\n| External | SaaS | `<<System_Ext>>` | `icon-saas` |\n| External | Legacy System | `<<System_Ext>>` | `icon-legacy-system` |\n| External | Partner Service | `<<System_Ext>>` | `icon-partner-service` |\n| External | Payment Provider | `<<System_Ext>>` | `icon-payment-provider` |\n| Monitoring | Logging | `<<Container>>` | `icon-logging` |\n| Monitoring | Metrics | `<<Container>>` | `icon-metrics` |\n| Monitoring | Tracing | `<<Container>>` | `icon-tracing` |\n| Monitoring | Alerting | `<<Container>>` | `icon-alerting` |\n| Monitoring | APM | `<<Container>>` | `icon-apm` |\n\n## Icon Registry\n\nIcons are inline SVG `<symbol>` elements with a 16x16 viewBox, rendered via `<use>` at `(x+W-22, y+4)` inside the component box. They use `currentColor` to inherit the category stroke color.\n\n### Category-Level Icons (active)\n\nEach category has a shared icon defined in `html-template.html` `<defs>`. All sub-types within a category use their category icon by default. Sub-type-specific icons can override these in the future.\n\n| Category | Symbol ID | Shape | Status |\n|---|---|---|---|\n| Frontend | `icon-frontend` | Monitor with stand | **active** |\n| Backend | `icon-backend` | Server rack (3 units) | **active** |\n| Data | `icon-data` | Database cylinder | **active** |\n| Infrastructure | `icon-infrastructure` | Cloud | **active** |\n| Messaging | `icon-messaging` | Envelope | **active** |\n| Security | `icon-security` | Shield with checkmark | **active** |\n| External | `icon-external` | Globe with meridians | **active** |\n| Monitoring | `icon-monitoring` | Line chart with axes | **active** |\n\nUsage pattern:\n```svg\n<use href="#icon-frontend" class="icon-use" x="448" y="154" width="16" height="16"/>\n```\n\n### Sub-type Icons (planned)\n\nWhen a sub-type icon is added, it overrides the category icon for that specific component. Until implemented, all sub-types use their category icon.\n\n| Sub-type | Icon | Status |\n|---|---|---|\n| SPA | `icon-spa` | planned |\n| Mobile App | `icon-mobile-app` | planned |\n| Static Site | `icon-static-site` | planned |\n| Micro-frontend | `icon-micro-frontend` | planned |\n| PWA | `icon-pwa` | planned |\n| Desktop App | `icon-desktop-app` | planned |\n| API Service | `icon-api-service` | planned |\n| Worker/Job | `icon-worker-job` | planned |\n| BFF | `icon-bff` | planned |\n| Microservice | `icon-microservice` | planned |\n| Serverless Function | `icon-serverless-function` | planned |\n| gRPC Service | `icon-grpc-service` | planned |\n| Relational DB | `icon-relational-db` | planned |\n| Document DB | `icon-document-db` | planned |\n| Key-Value Store | `icon-key-value-store` | planned |\n| Cache | `icon-cache` | planned |\n| Search Engine | `icon-search-engine` | planned |\n| Data Warehouse | `icon-data-warehouse` | planned |\n| Graph DB | `icon-graph-db` | planned |\n| Time-Series DB | `icon-time-series-db` | planned |\n| CDN | `icon-cdn` | planned |\n| Load Balancer | `icon-load-balancer` | planned |\n| DNS | `icon-dns` | planned |\n| Object Storage | `icon-object-storage` | planned |\n| Container Registry | `icon-container-registry` | planned |\n| Reverse Proxy | `icon-reverse-proxy` | planned |\n| Service Mesh | `icon-service-mesh` | planned |\n| Message Queue | `icon-message-queue` | planned |\n| Event Bus | `icon-event-bus` | planned |\n| Stream | `icon-stream` | planned |\n| Pub/Sub | `icon-pub-sub` | planned |\n| Webhook | `icon-webhook` | planned |\n| Auth Provider | `icon-auth-provider` | planned |\n| API Gateway | `icon-api-gateway` | planned |\n| WAF | `icon-waf` | planned |\n| Secret Manager | `icon-secret-manager` | planned |\n| Certificate Manager | `icon-certificate-manager` | planned |\n| Identity Provider | `icon-identity-provider` | planned |\n| Third-party API | `icon-third-party-api` | planned |\n| SaaS | `icon-saas` | planned |\n| Legacy System | `icon-legacy-system` | planned |\n| Partner Service | `icon-partner-service` | planned |\n| Payment Provider | `icon-payment-provider` | planned |\n| Logging | `icon-logging` | planned |\n| Metrics | `icon-metrics` | planned |\n| Tracing | `icon-tracing` | planned |\n| Alerting | `icon-alerting` | planned |\n| APM | `icon-apm` | planned |\n\n## Technology Icon Registry\n\nThe HTML C4 viewer also supports technology-specific SVG icons. It resolves them from each node\'s `technology` field after normalization. Set `icon` on node data when you need an explicit override; `icon` takes precedence over auto-detection from `technology`. If neither `icon` nor a normalized `technology` value matches a registry key, the viewer falls back to the generic C4 type icon for that node, such as person, database, queue, or container.\n\n### Available Keys\n\n- **Cloud:** `aws`, `azure`, `googlecloud`, `cloudflare`, `vercel`, `netlify`\n- **Languages:** `typescript`, `javascript`, `python`, `java`, `go`, `rust`, `csharp`, `php`, `ruby`, `swift`, `kotlin`\n- **Frontend:** `react`, `vuedotjs`, `angular`, `svelte`, `nextdotjs`, `html5`, `css3`\n- **Backend:** `nodedotjs`, `express`, `nestjs`, `django`, `spring`, `dotnet`\n- **Data:** `postgresql`, `mysql`, `mongodb`, `redis`, `elasticsearch`, `amazondynamodb`, `sqlite`\n- **Infrastructure:** `docker`, `kubernetes`, `nginx`, `linux`, `terraform`, `github`\n- **Messaging/API:** `apachekafka`, `rabbitmq`, `graphql`, `grpc`\n\n### Common Aliases\n\nCommon aliases are normalized before lookup. For example: `node` -> `nodedotjs`, `postgres` -> `postgresql`, `k8s` -> `kubernetes`, `vue` -> `vuedotjs`, `next.js` -> `nextdotjs`, `mongo` -> `mongodb`, `kafka` -> `apachekafka`, `gcp` -> `googlecloud`, `c#` -> `csharp`, and `.net` -> `dotnet`.\n\n## Visual Elements\n\n### Component Box Pattern\n\nUse a rounded component box with semi-transparent fill and category stroke.\n\n```svg\n<g class="node backend">\n <rect x="280" y="210" width="190" height="60" rx="6" />\n <text class="c4-tag" x="294" y="226">&lt;&lt;Container&gt;&gt;</text>\n <text class="node-title" x="294" y="243">API Service</text>\n <text class="node-subtitle" x="294" y="257">Backend / HTTPS JSON</text>\n</g>\n```\n\n### Arrow Masking Technique\n\nUse an opaque background rectangle below the box content to visually hide arrows beneath components without breaking the component fill style.\n\n```svg\n<g class="node-mask-layer">\n <rect x="280" y="210" width="190" height="60" rx="6" fill="#020617" />\n <rect x="280" y="210" width="190" height="60" rx="6"\n fill="rgba(6, 78, 59, 0.4)" stroke="#34d399" stroke-width="1.5" />\n</g>\n```\n\n### Security Group Boundary\n\n- Purpose: show auth, gateway, WAF, or identity zones\n- Stroke color: rose (`#fb7185`)\n- Pattern: `stroke-dasharray="4,4"`\n- Suggested label: `Security Boundary`\n\n```svg\n<rect x="700" y="140" width="220" height="180" rx="12"\n fill="transparent" stroke="#fb7185" stroke-width="1.5"\n stroke-dasharray="4,4" />\n```\n\n### Region Boundary\n\n- Purpose: group a deployment region, platform segment, or domain slice\n- Stroke color: amber (`#fbbf24`)\n- Pattern: `stroke-dasharray="8,4"`\n- Radius: `rx="12"`\n\n```svg\n<rect x="70" y="120" width="600" height="430" rx="12"\n fill="transparent" stroke="#fbbf24" stroke-width="1.5"\n stroke-dasharray="8,4" />\n```\n\n### Arrow Marker SVG Definition\n\n```svg\n<defs>\n <marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto">\n <path d="M0,0 L8,4 L0,8 Z" fill="#cbd5e1" />\n </marker>\n</defs>\n```\n\n### Arrow Z-order Rule\n\nDraw arrows early in the SVG so component boxes and masking layers paint over them. This keeps connectors readable in dense diagrams and avoids arrow overlap across component interiors.\n\n## Spacing Rules\n\n- Standard component height: `60px`\n- Minimum vertical gap between stacked components: `40px`\n- Inline connectors should route through gaps rather than through component interiors\n- Keep labels inside the top `28px` of the box and the subtype line inside the lower third\n- Place legends outside boundaries to prevent classification noise inside the diagram area\n\n## Layout Structure\n\nThe canonical page composition is:\n\n1. Header: title, pulse dot, subtitle\n2. Main SVG diagram: embedded inside a rounded border card\n3. Summary cards: grid of 3 cards beneath the diagram\n4. Footer metadata: generator, scope, rendering notes, last-updated stamp\n\n## Present Tool Integration\n\nCompose architecture diagrams with the `present` tool by embedding the full HTML/SVG diagram in a markdown block and pairing it with metrics or cards blocks as needed.\n\n### `format: "html"`\n\nUse a `markdown` block with embedded `<div>`, inline SVG, and a `<style>` tag containing the full CSS. The `present` html format renders raw HTML in markdown blocks.\n\n### `format: "browser"`\n\nUse the same composition: a `markdown` block containing the full HTML structure. Summary content can also be added with `cards` and `metrics` blocks alongside the SVG diagram block.\n\n### Example `present` Call Structure\n\n```js\npresent({\n format: "html", // or "browser"\n title: "System Architecture",\n content: [\n {\n type: "metrics",\n title: "Overview",\n value: [\n { label: "Services", value: "6" },\n { label: "Data Stores", value: "2" },\n { label: "External Systems", value: "3" }\n ]\n },\n {\n type: "markdown",\n title: "Architecture Diagram",\n value: "<div class=\'arch-diagram\'>...(inline SVG)...</div><style>...(design system CSS)...</style>"\n },\n {\n type: "cards",\n title: "Summary",\n value: [\n { title: "Frontend", body: "React SPA..." },\n { title: "Backend", body: "API + async workers..." },\n { title: "Security", body: "Gateway + IdP..." }\n ]\n }\n ]\n})\n```\n\nThis design system is the single source of truth. The `c4-architecture` skill and `present` skill both reference this file. Update component types, colors, or layout rules here only.\n\n## Adding New Categories\n\n1. Add a new row to the Category Registry with the category name, colors, C4 mapping, and initial subtype set.\n2. Add the new sub-types to the Sub-type Registry with a C4 label and icon slot name.\n3. Add icon placeholders to the Icon Registry.\n4. Update [html-template.html](html-template.html) legend content so the new category appears in the rendered template.\n5. Update summary card accent colors in [html-template.html](html-template.html) if the new category needs a dedicated card treatment.\n\n## Template Pairing\n\nSee [html-template.html](html-template.html) for the complete self-contained reference implementation of this design system.\n'},{file:`references/c4.schema.json`,content:JSON.stringify({$schema:`http://json-schema.org/draft-07/schema#`,title:`AIKIT Architecture Diagram`,description:`Schema for AI Kit C4 interactive architecture diagrams. The agent generates JSON matching this schema, which is injected into c4-viewer.html.`,version:`1.0.0`,type:`object`,required:[`title`,`type`,`nodes`,`edges`],properties:{title:{type:`string`,description:`Diagram title displayed in the viewer header`},description:{type:`string`,description:`Brief diagram description`},type:{type:`string`,enum:[`context`,`container`,`component`,`deployment`],description:`C4 diagram level`},layout:{type:`object`,properties:{direction:{type:`string`,enum:[`DOWN`,`UP`,`LEFT`,`RIGHT`],default:`DOWN`},spacing:{type:`number`,default:80},layerSpacing:{type:`number`,default:120}}},nodes:{type:`array`,items:{type:`object`,required:[`id`,`type`,`label`],properties:{id:{type:`string`,description:`Unique node identifier`},type:{type:`string`,enum:[`person`,`system`,`container`,`component`,`database`,`queue`,`external`,`boundary`,`deploymentNode`],description:`C4 element type - determines visual styling`},label:{type:`string`,description:`Display label`},technology:{type:`string`,description:`Technology tag used for display and icon auto-resolution (e.g., 'React', 'PostgreSQL')`},icon:{type:`string`,description:`Optional icon override key. Takes precedence over auto-detection from the technology field. Use Technology Icon Registry keys such as 'react', 'postgresql', or 'docker'.`},description:{type:`string`,description:`Element description shown on hover/expand`},children:{type:`array`,items:{type:`string`},description:`Child node IDs (for boundary/group nodes only)`},x:{type:`number`,description:`Optional fixed x position`},y:{type:`number`,description:`Optional fixed y position`}}}},edges:{type:`array`,items:{type:`object`,required:[`id`,`source`,`target`],properties:{id:{type:`string`,description:`Unique edge identifier (required for ELK layout)`},source:{type:`string`,description:`Source node ID`},target:{type:`string`,description:`Target node ID`},label:{type:`string`,description:`Relationship label`},technology:{type:`string`,description:`Protocol/technology (e.g., 'REST/HTTPS')`},style:{type:`string`,enum:[`solid`,`dashed`,`dotted`],default:`solid`},animated:{type:`boolean`,default:!1,description:`Animate the edge (for async/event flows)`}}}}}},null,2)},{file:`SKILL.md`,content:`---
1501
1501
  name: c4-architecture
1502
1502
  description: "Generate architecture documentation using C4 model diagrams. Supports two output formats: Mermaid (md) for documentation and HTML/SVG for presentations. Use when asked to create architecture diagrams, document system architecture, visualize software structure, create C4 diagrams, or generate context/container/component/deployment diagrams."
1503
1503
  metadata:
@@ -1521,12 +1521,15 @@ metadata:
1521
1521
  \`\`\`json
1522
1522
  {
1523
1523
  "title": "System Name",
1524
- "elements": [
1525
- { "id": "unique-id", "label": "Display Name", "type": "system|container|component|person|database|queue|external",
1526
- "technology": "optional", "description": "optional", "tags": ["optional"], "parentId": "optional-parent-id" }
1524
+ "description": "What this diagram shows",
1525
+ "layout": { "direction": "DOWN", "spacing": 80, "layerSpacing": 120 },
1526
+ "nodes": [
1527
+ { "id": "unique-id", "type": "person|system|container|component|database|queue|external",
1528
+ "label": "Display Name", "technology": "optional", "description": "optional", "parentId": "optional-parent-id" }
1527
1529
  ],
1528
- "relationships": [
1529
- { "sourceId": "from-id", "targetId": "to-id", "label": "optional", "technology": "optional" }
1530
+ "edges": [
1531
+ { "id": "unique-edge-id", "source": "source-node-id", "target": "target-node-id",
1532
+ "label": "optional", "technology": "optional" }
1530
1533
  ]
1531
1534
  }
1532
1535
  \`\`\`