@vpxa/aikit 0.1.89 → 0.1.90

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/aikit",
3
- "version": "0.1.89",
3
+ "version": "0.1.90",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -1 +1 @@
1
- import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-C5IU9Lau.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-0OCkdgRe.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-CXsoHmuu.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-AMfxaZUw.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`);g=new e(s.kb.indexer,l,s.kb.store),g.start(),s.setSmartScheduler(g),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-C5IU9Lau.js`),import(`./server-CXsoHmuu.js`),import(`./version-check-AMfxaZUw.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(()=>{d.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`smart`?h.then(async()=>{try{if(!f.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.kb.indexer,l,f.kb.store);t.start(),f.setSmartScheduler(t),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};
1
+ import{t as e}from"./curated-manager-CXSPygmJ.js";import{readFileSync as t}from"node:fs";import{dirname as n,resolve as r}from"node:path";import{fileURLToPath as i,pathToFileURL as a}from"node:url";import{parseArgs as o}from"node:util";import{createLogger as s,serializeError as c}from"../../core/dist/index.js";const l=n(i(import.meta.url)),u=(()=>{try{let e=r(l,`..`,`..`,`..`,`package.json`);return JSON.parse(t(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}})(),d=s(`server`);function f(){return process.env.AIKIT_TRANSPORT?process.env.AIKIT_TRANSPORT:process.stdin.isTTY?`http`:`stdio`}const{values:p}=(()=>{let e=process.argv[1];if(!e)return!1;try{return import.meta.url===a(e).href}catch{return!1}})()?o({allowPositionals:!0,options:{transport:{type:`string`,default:f()},port:{type:`string`,default:process.env.AIKIT_PORT??`3210`}}}):{values:{transport:f(),port:process.env.AIKIT_PORT??`3210`}};async function m(){if(process.on(`unhandledRejection`,e=>{d.error(`Unhandled rejection`,c(e))}),d.info(`Starting MCP AI Kit server`,{version:u}),p.transport===`http`){let[{default:e},{loadConfig:t,resolveIndexMode:n},{registerDashboardRoutes:r,resolveDashboardDir:i},{registerSettingsRoutes:a,resolveSettingsDir:o},{createSettingsRouter:s}]=await Promise.all([import(`express`),import(`./config-C5IU9Lau.js`),import(`./dashboard-static-BfIe0Si1.js`),import(`./settings-static-BosGZSPf.js`),import(`./routes-0OCkdgRe.js`)]),l=t();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path});let u=e();u.use(e.json());let f=Number(p.port);u.use((e,t,n)=>{if(t.setHeader(`Access-Control-Allow-Origin`,process.env.AIKIT_CORS_ORIGIN??`http://localhost:${f}`),t.setHeader(`Access-Control-Allow-Methods`,`GET, POST, PUT, PATCH, DELETE, OPTIONS`),t.setHeader(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`){t.status(204).end();return}n()}),r(u,i(),d);let m=new Date().toISOString();u.use(`/settings/api`,s({log:d,mcpInfo:()=>({transport:`http`,port:f,pid:process.pid,startedAt:m})})),a(u,o(),d),u.get(`/health`,(e,t)=>{t.json({status:`ok`})});let h=!1,g=null,_=null,v=null,y=Promise.resolve();u.post(`/mcp`,async(e,t)=>{if(!h||!_||!v){t.status(503).json({jsonrpc:`2.0`,error:{code:-32603,message:`Server initializing — please retry in a few seconds`},id:null});return}let n=y,r;y=new Promise(e=>{r=e}),await n;try{let n=new v({sessionIdGenerator:void 0});await _.connect(n),await n.handleRequest(e,t,e.body),n.close()}catch(e){if(d.error(`MCP handler error`,c(e)),!t.headersSent){let n=e instanceof Error?e.message:String(e),r=n.includes(`Not Acceptable`);t.status(r?406:500).json({jsonrpc:`2.0`,error:{code:r?-32e3:-32603,message:r?n:`Internal server error`},id:null})}}finally{r()}}),u.get(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))}),u.delete(`/mcp`,(e,t)=>{t.writeHead(405).end(JSON.stringify({jsonrpc:`2.0`,error:{code:-32e3,message:`Method not allowed.`},id:null}))});let b=u.listen(f,`127.0.0.1`,()=>{d.info(`MCP server listening`,{url:`http://127.0.0.1:${f}/mcp`,port:f}),setTimeout(async()=>{try{let[{createLazyServer:e,ALL_TOOL_NAMES:t},{StreamableHTTPServerTransport:r},{checkForUpdates:i,autoUpgradeScaffold:a}]=await Promise.all([import(`./server-DZ1V42_x.js`),import(`@modelcontextprotocol/sdk/server/streamableHttp.js`),import(`./version-check-AMfxaZUw.js`)]);i(),a();let o=n(l),s=e(l,o);_=s.server,v=r,h=!0,d.info(`MCP server configured (lazy — AI Kit initializing in background)`,{toolCount:t.length,resourceCount:2}),s.startInit(),o===`auto`?s.ready.then(async()=>{try{let e=l.sources.map(e=>e.path).join(`, `);d.info(`Running initial index`,{sourcePaths:e}),await s.runInitialIndex(),d.info(`Initial index complete`)}catch(e){d.error(`Initial index failed; will retry on aikit_reindex`,c(e))}}).catch(e=>d.error(`AI Kit init or indexing failed`,c(e))):o===`smart`?s.ready.then(async()=>{try{if(!s.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`);g=new e(s.kb.indexer,l,s.kb.store),g.start(),s.setSmartScheduler(g),d.info(`Smart index scheduler started (HTTP mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit initialization failed`,c(e))):(s.ready.catch(e=>d.error(`AI Kit initialization failed`,c(e))),d.info(`Initial full indexing skipped in HTTP mode`,{indexMode:o}))}catch(e){d.error(`Failed to load server modules`,c(e))}},100)}),x=async e=>{d.info(`Shutdown signal received`,{signal:e}),g?.stop(),b.close(),_&&await _.close(),process.exit(0)};process.on(`SIGINT`,()=>x(`SIGINT`)),process.on(`SIGTERM`,()=>x(`SIGTERM`))}else{let[{loadConfig:e,reconfigureForWorkspace:t,resolveIndexMode:n},{createLazyServer:r},{checkForUpdates:a,autoUpgradeScaffold:o},{RootsListChangedNotificationSchema:s}]=await Promise.all([import(`./config-C5IU9Lau.js`),import(`./server-DZ1V42_x.js`),import(`./version-check-AMfxaZUw.js`),import(`@modelcontextprotocol/sdk/types.js`)]),l=e();d.info(`Config loaded`,{sourceCount:l.sources.length,storePath:l.store.path}),a(),o();let u=n(l),f=r(l,u),{server:p,startInit:m,ready:h,runInitialIndex:g}=f,{StdioServerTransport:_}=await import(`@modelcontextprotocol/sdk/server/stdio.js`),v=new _;await p.connect(v),d.info(`MCP server started`,{transport:`stdio`});let y=e=>{if(e.length===0)return!1;let n=e[0].uri,r=n.startsWith(`file://`)?i(n):n;return d.info(`MCP roots resolved`,{rootUri:n,rootPath:r,rootCount:e.length}),t(l,r),l.allRoots=e.map(e=>{let t=e.uri;return t.startsWith(`file://`)?i(t):t}),!0},b=!1;try{b=y((await p.server.listRoots()).roots),b||d.info(`No MCP roots yet; waiting for roots/list_changed notification`)}catch(e){d.warn(`MCP roots/list not supported by client; using cwd fallback`,{cwd:process.cwd(),...c(e)}),b=!0}b||=await new Promise(e=>{let t=setTimeout(()=>{d.warn(`Timed out waiting for MCP roots/list_changed; using cwd fallback`,{cwd:process.cwd()}),e(!1)},5e3);p.server.setNotificationHandler(s,async()=>{clearTimeout(t);try{e(y((await p.server.listRoots()).roots))}catch(t){d.warn(`roots/list retry failed after notification`,c(t)),e(!1)}})}),m();let x=null,S=()=>{x&&clearTimeout(x),x=setTimeout(()=>{d.info(`Auto-shutdown: no activity for 30 minutes — exiting`),process.exit(0)},18e5),x.unref&&x.unref()};S(),process.stdin.on(`data`,()=>S()),h.catch(e=>{d.error(`Initialization failed — server will continue with limited tools`,c(e))}),u===`auto`?g().catch(e=>d.error(`Initial index failed`,c(e))):u===`smart`?h.then(async()=>{try{if(!f.kb)throw Error(`AI Kit components are not available after initialization`);let{SmartIndexScheduler:e}=await import(`../../indexer/dist/index.js`),t=new e(f.kb.indexer,l,f.kb.store);t.start(),f.setSmartScheduler(t),d.info(`Smart index scheduler started (stdio mode)`)}catch(e){d.error(`Failed to start smart index scheduler`,c(e))}}).catch(e=>d.error(`AI Kit init failed for smart scheduler`,c(e))):d.warn(`Initial full indexing skipped; use aikit_reindex to index manually`,{indexMode:u})}}m().catch(e=>{d.error(`Fatal error`,c(e)),process.exit(1)});export{e as CuratedKnowledgeManager};
@@ -558,7 +558,7 @@ The output must:
558
558
 
559
559
  Output ONLY the README.md content, nothing else.`;if(t.available)try{let i=(await t.createMessage({prompt:e,systemPrompt:s,context:o?`Step name: ${r}\nSource format: ${n}\nMetadata:\n${o}`:`Step name: ${r}\nSource format: ${n}`,maxTokens:4096,modelPreferences:{intelligencePriority:.8,speedPriority:.4,costPriority:.2}})).text.trim();if(i.length>0)return i}catch(e){G.debug(`Flow transform sampling failed; using fallback formatting`,{error:q(e),sourceFormat:n,stepName:r})}let c=typeof i?.description==`string`&&i.description.trim().length>0?i.description.trim():null,l=Wo(i?.produces),u=Wo(i?.requires);return[`# ${a}`,``,`## Purpose`,``,c??`${a} step.`,``,`## Instructions`,``,e.trim(),``,`## Artifacts`,``,...l.length>0?l.map(e=>`- ${e}`):[`- ${r}.md`],...u.length>0?[``,`## Prerequisites`,``,...u.map(e=>`- ${e}`)]:[],``].join(`
560
560
  `).trimEnd().concat(`
561
- `)}}function K(e){return{content:[{type:`text`,text:e}]}}function q(e){return e instanceof Error?e.message:String(e)}function Ko(e,t){function n(){return t.sources?.[0]?.path??process.cwd()}function r(){return t.allRoots?.length?t.allRoots:[n()]}function i(){return g(O(),`flows`,`registry.json`)}function d(e){return g(e??n(),`.flows`)}let m={before:[],after:[{id:`_docs-sync`,description:`Synchronize project documentation — update docs/ folder based on changes made during the flow.`,position:`after`,skills:[`docs`]}]};function h(e,t,r){let i=t?.installPath?p(t.installPath):e.replaceAll(`:`,`-`),o=_(Zt(),`.copilot`,`flows`,i).replaceAll(`\\`,`/`);if(a(o))return o;let s=_(Zt(),`.claude`,`flows`,i).replaceAll(`\\`,`/`);if(a(s))return s;let c=_(r??n(),`.github`,`flows`,i).replaceAll(`\\`,`/`);return a(c)?c:t?.installPath&&a(t.installPath)?t.installPath.replaceAll(`\\`,`/`):null}function v(e,t,n){let r=h(e.name,e,n);return r?_(r,t).replaceAll(`\\`,`/`):t}function y(e,t){let r=e.replace(/^_/,``),i=t??n(),o=[g(i,`.github`,`flows`,`_epilogue`,`steps`,r,`README.md`),g(i,`.github`,`flows`,`_epilogue`,r,`README.md`)];for(let e of o)if(a(e))return e.replaceAll(`\\`,`/`);return null}function b(e){return[...m.before.map(e=>e.id),...e.manifest.steps.map(e=>e.id),...m.after.map(e=>e.id)]}function x(e,t,n){let r=t?e.manifest.steps.find(e=>e.id===t)??null:null,i=!r&&t?[...m.before,...m.after].find(e=>e.id===t)??null:null;return{currentStep:r,epilogueStep:i,instructionPath:r&&t?v(e,r.instruction,n):null,description:r?.description??i?.description??null}}function S(){try{let e=g(kn(`npm root -g`,{encoding:`utf-8`}).trim(),`@fission-ai`,`openspec`);if(a(e))return{path:e,sourceType:`npm-global`,isGit:!1}}catch{}return{path:`https://github.com/Fission-AI/OpenSpec.git`,sourceType:`git`,isGit:!0}}function C(e){let t=_(e);if(a(g(t,`.claude-plugin`,`plugin.json`)))return{path:t,sourceType:`claude-plugin`};let n=Zt(),r=g(n,`.claude`,`plugins`,e);if(a(g(r,`.claude-plugin`,`plugin.json`)))return{path:r,sourceType:`claude-plugin`};let i=g(n,`.claude`,`plugins`);if(!a(i))return null;for(let t of c(i,{withFileTypes:!0})){if(!t.isDirectory())continue;let n=g(i,t.name,`.claude-plugin`,`plugin.json`);if(a(n))try{if(JSON.parse(s(n,`utf-8`)).name===e)return{path:g(i,t.name),sourceType:`claude-plugin`}}catch{}}return null}async function w(e){let{FlowRegistryManager:r,FlowStateMachine:a,FlowLoader:o,GitInstaller:s}=await import(`../../flows/dist/index.js`),c=g(t.stateDir??g(n(),`.aikit-state`),`flows`,`installed`);return{registry:new r(i()),stateMachine:new a(d(e),m),loader:new o,installer:new s(c)}}async function T(){let e=r();for(let t of e){let e=d(t);if(a(e))for(let n of c(e,{withFileTypes:!0})){if(!n.isDirectory())continue;let r=g(e,n.name,`meta.json`);if(a(r))try{let e=JSON.parse(s(r,`utf-8`));if(e.status===`active`)return e.primaryRoot?e.primaryRoot:t}catch{}}}return null}async function E(e){return e||(await T()??n())}function D(e,t,n){let r=g(d(t),e,`meta.json`),i=s(r,`utf-8`),a=JSON.parse(i);a.roots=n.map(e=>e.replaceAll(`\\`,`/`)),a.primaryRoot=t.replaceAll(`\\`,`/`),f(r,JSON.stringify(a,null,2),`utf-8`)}function k(e,t){let n=g(d(t),e,`meta.json`);if(!a(n))return;let r=s(n,`utf-8`),i=JSON.parse(r),c=i.roots;if(!c||c.length<=1)return;let l=t.replaceAll(`\\`,`/`);for(let t of c){if(t===l)continue;let n=g(t,`.flows`,e);o(n,{recursive:!0}),f(g(n,`meta.json`),r,`utf-8`),o(g(n,i.artifactsDir??`.spec`),{recursive:!0})}}let ee=L(`flow_list`);e.registerTool(`flow_list`,{title:ee.title,description:`List all installed flows and their steps`,annotations:ee.annotations,inputSchema:{}},async()=>{try{let{registry:e,stateMachine:t,installer:n}=await w(await E()),i=e.list(),a=t.getStatus(),o={flows:i.map(e=>{let t={name:e.name,version:e.version,source:e.source,sourceType:e.sourceType,format:e.format,steps:e.manifest.steps.map(e=>e.id)};if(e.sourceType===`git`&&e.commitSha){let r=n.hasUpdates(e.installPath);return{...t,commitSha:e.commitSha,updateAvailable:r.success&&r.data?r.data.hasUpdates:void 0}}return t}),activeFlow:a.success&&a.data?{flow:a.data.flow,status:a.data.status,currentStep:a.data.currentStep,slug:a.data.slug,topic:a.data.topic,runDir:a.data.runDir}:null,allRoots:r().map(e=>e.replaceAll(`\\`,`/`))};return K(JSON.stringify(o,null,2))}catch(e){return G.error(`flow_list failed`,A(e)),K(`Error: ${q(e)}`)}});let te=L(`flow_info`);e.registerTool(`flow_info`,{title:te.title,description:`Show detailed information about a specific flow`,annotations:te.annotations,inputSchema:{name:P.string().describe(`Flow name to get info for`)}},async({name:e})=>{try{let{registry:t,installer:n}=await w(),r=t.get(e);if(!r)return K(`Flow "${e}" not found. Use flow_list to see available flows.`);let i=r.commitSha??null,a;if(r.sourceType===`git`&&r.installPath){let e=n.hasUpdates(r.installPath);a=e.success&&e.data?e.data.hasUpdates:void 0}let o={name:r.name,version:r.version,description:r.manifest.description,source:r.source,sourceType:r.sourceType,format:r.format,commitSha:i,updateAvailable:a,installPath:h(r.name,r),registeredAt:r.registeredAt,updatedAt:r.updatedAt,steps:r.manifest.steps.map(e=>({id:e.id,name:e.name,instruction:v(r,e.instruction),produces:e.produces,requires:e.requires,description:e.description})),agents:r.manifest.agents,artifactsDir:r.manifest.artifacts_dir,install:r.manifest.install};return K(JSON.stringify(o,null,2))}catch(e){return G.error(`flow_info failed`,A(e)),K(`Error: ${q(e)}`)}});let j=L(`flow_start`);e.registerTool(`flow_start`,{title:j.title,description:`Start a flow. Sets the active flow and positions at the first step.`,annotations:j.annotations,inputSchema:{flow:P.string().describe(`Flow name to start (use flow_list to see options)`),topic:P.string().optional().describe(`Human-readable topic for the run (e.g. "Add authentication"). Used as directory name under .flows/.`),roots:P.array(P.string()).optional().describe(`Workspace roots participating in this flow. For multi-repo tasks, list all repos that need a .flows/<slug>/ directory. Flow state is synchronized across all listed roots. Omit for single-root workspaces (defaults to primary root).`)}},async({flow:e,topic:t,roots:i})=>{try{if(i&&i.length>0){let e=new Set(r().map(e=>e.replaceAll(`\\`,`/`))),t=i.filter(t=>!e.has(t.replaceAll(`\\`,`/`)));if(t.length>0)return K(`Invalid roots — not part of the workspace: ${t.join(`, `)}. Available roots: ${[...e].join(`, `)}`)}let a=i?.[0]??n(),{registry:o,stateMachine:s}=await w(a),c=o.get(e);if(!c)return K(`Flow "${e}" not found. Use flow_list to see available flows.`);let l=s.start(c.name,c.manifest,t);if(!l.success||!l.data)return K(`Cannot start: ${l.error}`);let u=l.data;if(i&&i.length>1)try{D(u.slug,a,i),k(u.slug,a)}catch(e){return s.reset(),K(`Flow created but failed to sync to secondary roots — rolled back. Error: ${e instanceof Error?e.message:String(e)}`)}let{instructionPath:d,description:f}=x(c,u.currentStep,a),p=b(c),m={started:!0,flow:u.flow,slug:u.slug,topic:u.topic,runDir:u.runDir,artifactsPath:g(u.runDir,c.manifest.artifacts_dir).replaceAll(`\\`,`/`),currentStep:u.currentStep,currentStepInstruction:d,currentStepDescription:f,phase:u.phase,isEpilogue:u.isEpilogue,totalSteps:p.length,stepSequence:p,artifactsDir:c.manifest.artifacts_dir,roots:i??[a.replaceAll(`\\`,`/`)]};return K(JSON.stringify(m,null,2))}catch(e){return G.error(`flow_start failed`,A(e)),K(`Error: ${q(e)}`)}});let ne=L(`flow_step`);e.registerTool(`flow_step`,{title:ne.title,description:`Advance the active flow: complete current step and move to next, skip current step, or redo current step.`,annotations:ne.annotations,inputSchema:{action:P.enum([`next`,`skip`,`redo`]).describe(`next: mark current step done and advance. skip: skip current step. redo: repeat current step.`)}},async({action:e})=>{try{let t=await E(),{registry:n,stateMachine:r}=await w(t),i=r.getStatus();if(!i.success||!i.data)return K(`No active flow. Use flow_start first.`);let a=n.get(i.data.flow);if(!a)return K(`Flow "${i.data.flow}" not found in registry.`);let o=r.step(e,a.manifest);if(!o.success||!o.data)return K(`Cannot ${e}: ${o.error}`);k(o.data.slug,t);let s=o.data,{instructionPath:c,description:l}=x(a,s.currentStep,t),u=b(a),d={flow:s.flow,status:s.status,action:e,slug:s.slug,topic:s.topic,runDir:s.runDir,artifactsPath:g(s.runDir,a.manifest.artifacts_dir).replaceAll(`\\`,`/`),currentStep:s.currentStep,currentStepInstruction:c,currentStepDescription:l,phase:s.phase,isEpilogue:s.isEpilogue,completedSteps:s.completedSteps,skippedSteps:s.skippedSteps,totalSteps:u.length,remaining:u.filter(e=>!s.completedSteps.includes(e)&&!s.skippedSteps.includes(e)&&e!==s.currentStep)};return K(JSON.stringify(d,null,2))}catch(e){return G.error(`flow_step failed`,A(e)),K(`Error: ${q(e)}`)}});let re=L(`flow_status`);e.registerTool(`flow_status`,{title:re.title,description:`Show the current flow execution state — which flow is active, current step, completed steps, and artifacts.`,annotations:re.annotations,inputSchema:{}},async()=>{try{let e=await E(),{registry:t,stateMachine:n}=await w(e),i=n.getStatus();if(!i.success||!i.data)return K(`No active flow. Use flow_start to begin one, or flow_list to see available flows.`);let a=i.data,o=t.get(a.flow),s=o?x(o,a.currentStep,e):null,c=o?b(o):[],l=s?.instructionPath??null,u={flow:a.flow,status:a.status,slug:a.slug,topic:a.topic,runDir:a.runDir,artifactsPath:o?g(a.runDir,o.manifest.artifacts_dir).replaceAll(`\\`,`/`):null,currentStep:a.currentStep,currentStepInstruction:l,instructionPath:l,currentStepDescription:s?.description??null,phase:a.phase,isEpilogue:a.isEpilogue,completedSteps:a.completedSteps,skippedSteps:a.skippedSteps,artifacts:a.artifacts,startedAt:a.startedAt,updatedAt:a.updatedAt,totalSteps:c.length,progress:o?`${a.completedSteps.length+a.skippedSteps.length}/${c.length}`:`unknown`,workspaceRoot:e.replaceAll(`\\`,`/`),primaryRoot:(a.primaryRoot??e).replaceAll(`\\`,`/`),roots:a.roots??[e.replaceAll(`\\`,`/`)],allRoots:r().map(e=>e.replaceAll(`\\`,`/`))};return K(JSON.stringify(u,null,2))}catch(e){return G.error(`flow_status failed`,A(e)),K(`Error: ${q(e)}`)}});let M=L(`flow_read_instruction`);e.registerTool(`flow_read_instruction`,{title:M.title===`flow_read_instruction`?`Flow Read Instruction`:M.title,description:`Read the instruction content for a flow step. If step is omitted, reads the current step.`,annotations:M.title===`flow_read_instruction`?{readOnlyHint:!0,idempotentHint:!0}:M.annotations,inputSchema:{step:P.string().optional().describe(`Step id or name to read. Defaults to the current step.`)}},async({step:e})=>{try{let t=await E(),{registry:n,stateMachine:r}=await w(t),i=r.getStatus();if(!i.success||!i.data)return K(`No active flow. Use flow_start to begin one, or flow_list to see available flows.`);let a=i.data,o=n.get(a.flow);if(!o)return K(`Flow "${a.flow}" not found in registry.`);let s=e??a.currentStep;if(!s)return K(`No current step is available for the active flow.`);let c=o.manifest.steps.find(e=>e.id===s||e.name===s);if(!c){let e=y(s,t);if(e){let n=await Yt(e,`utf-8`),r=g(a.runDir,o.manifest.artifacts_dir).replaceAll(`\\`,`/`),i=a.runDir.replaceAll(`\\`,`/`);return n=n.replaceAll(`{{artifacts_path}}`,r).replaceAll(`{{run_dir}}`,i).replaceAll(`{{workspace_root}}`,(a.primaryRoot??t).replaceAll(`\\`,`/`)).replaceAll(`{{all_roots}}`,JSON.stringify(a.roots??[t.replaceAll(`\\`,`/`)],null,2)),K(n)}return K(`Step "${s}" not found in flow "${a.flow}".`)}let l=await Yt(v(o,c.instruction,t),`utf-8`),u=g(a.runDir,o.manifest.artifacts_dir).replaceAll(`\\`,`/`),d=a.runDir.replaceAll(`\\`,`/`);l=l.replaceAll(`{{artifacts_path}}`,u).replaceAll(`{{run_dir}}`,d).replaceAll(`{{workspace_root}}`,(a.primaryRoot??t).replaceAll(`\\`,`/`)).replaceAll(`{{all_roots}}`,JSON.stringify(a.roots??[t.replaceAll(`\\`,`/`)],null,2));for(let e of[`spec-driven`])l=l.replaceAll(`${e}/${a.slug}/`,`${u}/`);return K(l)}catch(e){return G.error(`flow_read_instruction failed`,A(e)),e instanceof Error&&`code`in e&&e.code===`ENOENT`?K(`Could not read instruction file: ${e.message}`):K(`Error: ${q(e)}`)}});let ie=L(`flow_reset`);e.registerTool(`flow_reset`,{title:ie.title,description:`Reset the active flow, clearing all state. Use to start over or switch to a different flow.`,annotations:ie.annotations,inputSchema:{}},async()=>{try{let e=await E(),{stateMachine:t}=await w(e),n=t.getStatus(),r=t.reset();return r.success?(n.success&&n.data&&k(n.data.slug,e),K(`Flow abandoned. Use flow_start to begin a new flow.`)):K(`Reset failed: ${r.error}`)}catch(e){return G.error(`flow_reset failed`,A(e)),K(`Error: ${q(e)}`)}});let ae=L(`flow_runs`);e.registerTool(`flow_runs`,{title:ae.title===`flow_runs`?`Flow Runs`:ae.title,description:`List all flow runs (current and past). Shows topic, flow, status, and progress for each run under .flows/.`,annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{flow:P.string().optional().describe(`Filter by flow name`),status:P.string().optional().describe(`Filter by status (active, completed, abandoned)`)}},async({flow:e,status:t})=>{try{let n=r(),i=[];for(let r of n){let{stateMachine:n}=await w(r),a=n.listRuns({flow:e,status:t});for(let e of a)i.push({...JSON.parse(JSON.stringify(e)),root:r.replaceAll(`\\`,`/`)})}let a=new Set,o=i.filter(e=>{let t=e.id;return a.has(t)?!1:(a.add(t),!0)});return o.length===0?K(`No flow runs found.`):K(JSON.stringify(o,null,2))}catch(e){return G.error(`flow_runs failed`,A(e)),K(`Error: ${q(e)}`)}});let oe=L(`flow_add`);e.registerTool(`flow_add`,{title:oe.title,description:`Install a new development flow from a git repository URL or local directory path. Use when the user wants to add, install, import, or onboard a new workflow — for example: "use this as a flow", "add this flow", "add this flow URL", "install a flow", or "onboard a flow". Accepts git URLs (https://..., git@...) and local filesystem paths. Also accepts the shorthand "openspec" to install the OpenSpec flow (auto-detects local npm global install or clones from GitHub).`,annotations:oe.annotations,inputSchema:{source:P.string().describe(`Git repository URL (https://... or git@...) or absolute/local directory path containing a flow definition. Use "openspec" as a shorthand to auto-resolve the OpenSpec flow.`),name:P.string().optional().describe(`Optional override for the installed flow name. If omitted, the name comes from the flow manifest.`),token:P.string().optional().describe(`Authentication token for private/GHE repositories`)}},async({source:t,name:n,token:r})=>{try{let{registry:i,loader:a,installer:o}=await w(),s=Go(e),c=t===`openspec`||t.startsWith(`openspec:`),l,u=t,d;if(c){let e=S();u=e.path,l=e.sourceType}let f=c?null:C(u);f&&(u=f.path,l=f.sourceType);let m=/^https?:\/\/|^git@/.test(u),h;if(m){let e=o.clone(u,r);if(!e.success||!e.data)return K(`Failed to clone flow: ${e.error}`);h=e.data}else{let e=_(u);d=e;let t=n||p(e)||`custom-flow`,r=o.copyLocal(e,t);if(!r.success||!r.data)return K(`Failed to copy flow: ${r.error}`);h=r.data}let g=await a.load(h,{forceAssetSync:!0,transform:s});if(!g.success||!g.data)return o.remove(h),K(`Failed to load flow manifest: ${g.error}`);let{manifest:v,format:y}=g.data,b=n||v.name,x=l??(m?`git`:`local`);if(i.has(b))return o.remove(h),K(`Flow "${b}" is already installed. Use flow_update to update it, or flow_remove then flow_add to replace.`);if(v.install.length>0){let e=o.runInstallDeps(v.install);if(!e.success)return o.remove(h),K(`Dependency install failed: ${e.error}`)}let T=new Date().toISOString(),E=m?o.getLocalCommit(h):void 0,D=i.register({name:b,version:v.version,source:x===`local`||x===`claude-plugin`?d??t:t,sourceType:x,installPath:h,format:y,registeredAt:T,updatedAt:T,manifest:v,...E?{commitSha:E}:{}});if(!D.success)return o.remove(h),K(`Failed to register flow: ${D.error}`);let O=v.steps.length;return K(`Flow "${b}" installed successfully (${O} steps). Use flow_start({ flow: "${b}" }) to begin.`)}catch(e){return G.error(`flow_add failed`,A(e)),K(`Error: ${q(e)}`)}});let se=L(`flow_remove`);e.registerTool(`flow_remove`,{title:se.title,description:`Remove an installed flow by name. Unregisters it and deletes its files when applicable. Builtin flows cannot be removed.`,annotations:se.annotations,inputSchema:{name:P.string().describe(`Name of the flow to remove.`)}},async({name:e})=>{try{let{registry:t,installer:n}=await w();if(!t.has(e))return K(`Flow "${e}" is not installed.`);let r=t.get(e);if(!r)return K(`Flow "${e}" is not installed.`);if(r.sourceType===`builtin`)return K(`Cannot remove builtin flow "${e}".`);let i=n.remove(r.installPath);if(!i.success)return K(`Failed to remove flow files: ${i.error}`);let a=t.unregister(e);return a.success?K(`Flow "${e}" removed successfully.`):K(`Failed to unregister flow: ${a.error}`)}catch(e){return G.error(`flow_remove failed`,A(e)),K(`Error: ${q(e)}`)}});let ce=L(`flow_update`);e.registerTool(`flow_update`,{title:ce.title,description:`Update an installed flow to its latest version. For git-based flows, pulls the latest changes. For npm-global flows (e.g. OpenSpec), runs npm update.`,annotations:ce.annotations,inputSchema:{name:P.string().describe(`Name of the flow to update.`)}},async({name:t})=>{try{let{registry:n,loader:r,installer:i}=await w(),o=Go(e);if(!n.has(t))return K(`Flow "${t}" is not installed.`);let s=n.get(t);if(!s||s.sourceType!==`git`&&s.sourceType!==`npm-global`&&s.sourceType!==`local`&&s.sourceType!==`claude-plugin`)return K(`Flow "${t}" was not installed from git, npm, or a local source — cannot update. Remove and re-add instead.`);if(s.sourceType===`local`||s.sourceType===`claude-plugin`){let e=_(s.source);if(!a(e))return K(`Source path no longer exists: ${e}`);let t=`${s.installPath}.updating`,c=`${s.installPath}.backup`;a(t)&&u(t,{recursive:!0,force:!0}),a(c)&&u(c,{recursive:!0,force:!0});let d=i.copyLocal(e,p(t));if(!d.success||!d.data)return K(`Failed to copy flow: ${d.error}`);let f=await r.load(t,{forceAssetSync:!0,transform:o});if(!f.success||!f.data)return i.remove(t),K(`Failed to load flow manifest: ${f.error}`);let m=!1;try{l(s.installPath,c),l(t,s.installPath);let e=await r.load(s.installPath,{forceAssetSync:!0,transform:o});if(!e.success||!e.data)throw Error(`Failed to load flow manifest: ${e.error}`);let a=e.data.manifest,d=e.data.format,f=n.register({...s,version:a.version,format:d,installPath:s.installPath,manifest:a,updatedAt:new Date().toISOString()});if(!f.success)throw Error(`Failed to refresh flow registry entry: ${f.error}`);if(m=!0,a.install.length>0){let e=i.runInstallDeps(a.install);if(!e.success)throw Error(`Dependency install failed: ${e.error}`)}u(c,{recursive:!0,force:!0})}catch(e){return a(t)&&u(t,{recursive:!0,force:!0}),a(c)&&(a(s.installPath)&&u(s.installPath,{recursive:!0,force:!0}),l(c,s.installPath)),m&&n.register(s),K(q(e))}return K(`Flow "${s.name}" updated from ${s.sourceType} source successfully.`)}if(s.sourceType===`npm-global`){try{kn(`npm update -g @fission-ai/openspec`,{encoding:`utf-8`,stdio:`pipe`})}catch(e){return K(`npm update failed: ${q(e)}`)}let e=S(),i=await r.load(e.path,{forceAssetSync:!0,transform:o}),a=i.success&&i.data?i.data.manifest:null,c=i.success&&i.data?i.data.format:s.format;if(a){let t=n.register({...s,version:a.version,format:c,installPath:e.path,manifest:a,updatedAt:new Date().toISOString()});if(!t.success)return K(`Failed to refresh flow registry entry: ${t.error}`)}return K(`Flow "${t}" updated via npm successfully.`)}let c=i.update(s.installPath);if(!c.success)return K(`Update failed: ${c.error}`);let d=await r.load(s.installPath,{forceAssetSync:!0,transform:o}),f=d.success&&d.data?d.data.manifest:null,m=d.success&&d.data?d.data.format:s.format;if(f){let e=i.getLocalCommit(s.installPath),t=n.register({...s,version:f.version,format:m,manifest:f,updatedAt:new Date().toISOString(),...e?{commitSha:e}:{}});if(!t.success)return K(`Failed to refresh flow registry entry: ${t.error}`)}let h=f?.install??s.manifest.install;if(h.length>0){let e=i.runInstallDeps(h);if(!e.success)return K(`Dependency install failed: ${e.error}`)}return K(`Flow "${t}" updated successfully.`)}catch(e){return G.error(`flow_update failed`,A(e)),K(`Error: ${q(e)}`)}})}const qo=D(`tools`);function Jo(e){let t=L(`evidence_map`);e.registerTool(`evidence_map`,{title:t.title,description:`Track verified/assumed/unresolved claims for complex tasks. Gate readiness: YIELD (proceed), HOLD (unknowns), HARD_BLOCK (critical gaps). Persists across calls.`,inputSchema:{action:P.enum([`create`,`add`,`update`,`get`,`gate`,`list`,`delete`]).describe(`Operation to perform`),task_id:P.string().optional().describe(`Task identifier (required for all except list)`),tier:P.enum([`floor`,`standard`,`critical`]).optional().describe(`FORGE tier (required for create)`),claim:P.string().optional().describe(`Critical-path claim text (for add)`),status:P.enum([`V`,`A`,`U`]).optional().describe(`Evidence status: V=Verified, A=Assumed, U=Unresolved`),receipt:P.string().optional().describe(`Evidence receipt: tool→ref for V, reasoning for A, attempts for U`),id:P.number().optional().describe(`Entry ID (for update)`),critical_path:P.boolean().default(!0).describe(`Whether this claim is on the critical path`),unknown_type:P.enum([`contract`,`convention`,`freshness`,`runtime`,`data-flow`,`impact`]).optional().describe(`Typed unknown classification`),safety_gate:P.enum([`provenance`,`commitment`,`coverage`]).optional().describe(`Safety gate tag: provenance (claim→evidence), commitment (user-approved), coverage (nothing dropped)`),retry_count:P.number().default(0).describe(`Retry count for gate evaluation (0 = first attempt)`),max_retries:P.number().int().min(0).optional().describe(`Maximum retries before escalating. Default: 3`),timeout_action:P.enum([`iterate`,`retry`,`manual`,`terminate`]).optional().describe(`Action to take when gate retries are exhausted. Default: manual`),cwd:P.string().optional().describe(`Working directory for evidence map storage (default: server cwd). Use root_path from forge_ground to match.`)},annotations:t.annotations},async({action:e,task_id:t,tier:n,claim:r,status:i,receipt:a,id:o,critical_path:s,unknown_type:c,safety_gate:l,retry_count:u,max_retries:d,timeout_action:f,cwd:p})=>{try{switch(e){case`create`:if(!t)throw Error(`task_id required for create`);if(!n)throw Error(`tier required for create`);return Ae({action:`create`,taskId:t,tier:n},p),{content:[{type:`text`,text:`Created evidence map "${t}" (tier: ${n}).\n\n---\n_Next: Use \`evidence_map\` with action "add" to record critical-path claims._`}]};case`add`:{if(!t)throw Error(`task_id required for add`);if(!r)throw Error(`claim required for add`);if(!i)throw Error(`status required for add`);let e=Ae({action:`add`,taskId:t,claim:r,status:i,receipt:a??``,criticalPath:s,unknownType:c,safetyGate:l},p),n=[`Added entry #${e.entry?.id} to "${t}": [${i}] ${r}`];return e.formattedMap&&n.push(``,e.formattedMap),{content:[{type:`text`,text:n.join(`
561
+ `)}}function K(e){return{content:[{type:`text`,text:e}]}}function q(e){return e instanceof Error?e.message:String(e)}function Ko(e,t){function n(){return t.sources?.[0]?.path??process.cwd()}function r(e){let t=[];try{let n=c(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory()||r.name.startsWith(`.`))continue;let n=g(e,r.name);a(g(n,`.git`))&&t.push(n)}}catch{}return t}function i(){let e=t.allRoots?.length?t.allRoots:[n()],i=new Set(e);for(let t of e)for(let e of r(t))i.add(e);return[...i]}function d(e){let r=e.replaceAll(`\\`,`/`);if(i().map(e=>e.replaceAll(`\\`,`/`)).includes(r))return!0;let o=(t.allRoots?.length?t.allRoots:[n()]).map(e=>e.replaceAll(`\\`,`/`));for(let t of o)if(r.startsWith(`${t}/`)&&a(g(e,`.git`)))return!0;return!1}function m(){return g(O(),`flows`,`registry.json`)}function h(e){return g(e??n(),`.flows`)}let v={before:[],after:[{id:`_docs-sync`,description:`Synchronize project documentation — update docs/ folder based on changes made during the flow.`,position:`after`,skills:[`docs`]}]};function y(e,t,r){let i=t?.installPath?p(t.installPath):e.replaceAll(`:`,`-`),o=_(Zt(),`.copilot`,`flows`,i).replaceAll(`\\`,`/`);if(a(o))return o;let s=_(Zt(),`.claude`,`flows`,i).replaceAll(`\\`,`/`);if(a(s))return s;let c=_(r??n(),`.github`,`flows`,i).replaceAll(`\\`,`/`);return a(c)?c:t?.installPath&&a(t.installPath)?t.installPath.replaceAll(`\\`,`/`):null}function b(e,t,n){let r=y(e.name,e,n);return r?_(r,t).replaceAll(`\\`,`/`):t}function x(e,t){let r=e.replace(/^_/,``),i=t??n(),o=[g(i,`.github`,`flows`,`_epilogue`,`steps`,r,`README.md`),g(i,`.github`,`flows`,`_epilogue`,r,`README.md`)];for(let e of o)if(a(e))return e.replaceAll(`\\`,`/`);return null}function S(e){return[...v.before.map(e=>e.id),...e.manifest.steps.map(e=>e.id),...v.after.map(e=>e.id)]}function C(e,t,n){let r=t?e.manifest.steps.find(e=>e.id===t)??null:null,i=!r&&t?[...v.before,...v.after].find(e=>e.id===t)??null:null;return{currentStep:r,epilogueStep:i,instructionPath:r&&t?b(e,r.instruction,n):null,description:r?.description??i?.description??null}}function w(){try{let e=g(kn(`npm root -g`,{encoding:`utf-8`}).trim(),`@fission-ai`,`openspec`);if(a(e))return{path:e,sourceType:`npm-global`,isGit:!1}}catch{}return{path:`https://github.com/Fission-AI/OpenSpec.git`,sourceType:`git`,isGit:!0}}function T(e){let t=_(e);if(a(g(t,`.claude-plugin`,`plugin.json`)))return{path:t,sourceType:`claude-plugin`};let n=Zt(),r=g(n,`.claude`,`plugins`,e);if(a(g(r,`.claude-plugin`,`plugin.json`)))return{path:r,sourceType:`claude-plugin`};let i=g(n,`.claude`,`plugins`);if(!a(i))return null;for(let t of c(i,{withFileTypes:!0})){if(!t.isDirectory())continue;let n=g(i,t.name,`.claude-plugin`,`plugin.json`);if(a(n))try{if(JSON.parse(s(n,`utf-8`)).name===e)return{path:g(i,t.name),sourceType:`claude-plugin`}}catch{}}return null}async function E(e){let{FlowRegistryManager:r,FlowStateMachine:i,FlowLoader:a,GitInstaller:o}=await import(`../../flows/dist/index.js`),s=g(t.stateDir??g(n(),`.aikit-state`),`flows`,`installed`);return{registry:new r(m()),stateMachine:new i(h(e),v),loader:new a,installer:new o(s)}}async function D(){let e=i();for(let t of e){let e=h(t);if(a(e))for(let n of c(e,{withFileTypes:!0})){if(!n.isDirectory())continue;let r=g(e,n.name,`meta.json`);if(a(r))try{let e=JSON.parse(s(r,`utf-8`));if(e.status===`active`)return e.primaryRoot?e.primaryRoot:t}catch{}}}return null}async function k(e){return e||(await D()??n())}function ee(e,t,n){let r=g(h(t),e,`meta.json`),i=s(r,`utf-8`),a=JSON.parse(i);a.roots=n.map(e=>e.replaceAll(`\\`,`/`)),a.primaryRoot=t.replaceAll(`\\`,`/`),f(r,JSON.stringify(a,null,2),`utf-8`)}function te(e,t){let n=g(h(t),e,`meta.json`);if(!a(n))return;let r=s(n,`utf-8`),i=JSON.parse(r),c=i.roots;if(!c||c.length<=1)return;let l=t.replaceAll(`\\`,`/`);for(let t of c){if(t===l)continue;let n=g(t,`.flows`,e);o(n,{recursive:!0}),f(g(n,`meta.json`),r,`utf-8`),o(g(n,i.artifactsDir??`.spec`),{recursive:!0})}}let j=L(`flow_list`);e.registerTool(`flow_list`,{title:j.title,description:`List all installed flows and their steps`,annotations:j.annotations,inputSchema:{}},async()=>{try{let{registry:e,stateMachine:r,installer:a}=await E(await k()),o=e.list(),s=r.getStatus(),c={flows:o.map(e=>{let t={name:e.name,version:e.version,source:e.source,sourceType:e.sourceType,format:e.format,steps:e.manifest.steps.map(e=>e.id)};if(e.sourceType===`git`&&e.commitSha){let n=a.hasUpdates(e.installPath);return{...t,commitSha:e.commitSha,updateAvailable:n.success&&n.data?n.data.hasUpdates:void 0}}return t}),activeFlow:s.success&&s.data?{flow:s.data.flow,status:s.data.status,currentStep:s.data.currentStep,slug:s.data.slug,topic:s.data.topic,runDir:s.data.runDir}:null,allRoots:i().map(e=>e.replaceAll(`\\`,`/`)),discoveredRepos:(()=>{let e=(t.allRoots?.length?t.allRoots:[n()]).map(e=>e.replaceAll(`\\`,`/`)),r=i().map(e=>e.replaceAll(`\\`,`/`)).filter(t=>!e.includes(t));return r.length>0?r:void 0})()};return K(JSON.stringify(c,null,2))}catch(e){return G.error(`flow_list failed`,A(e)),K(`Error: ${q(e)}`)}});let ne=L(`flow_info`);e.registerTool(`flow_info`,{title:ne.title,description:`Show detailed information about a specific flow`,annotations:ne.annotations,inputSchema:{name:P.string().describe(`Flow name to get info for`)}},async({name:e})=>{try{let{registry:t,installer:n}=await E(),r=t.get(e);if(!r)return K(`Flow "${e}" not found. Use flow_list to see available flows.`);let i=r.commitSha??null,a;if(r.sourceType===`git`&&r.installPath){let e=n.hasUpdates(r.installPath);a=e.success&&e.data?e.data.hasUpdates:void 0}let o={name:r.name,version:r.version,description:r.manifest.description,source:r.source,sourceType:r.sourceType,format:r.format,commitSha:i,updateAvailable:a,installPath:y(r.name,r),registeredAt:r.registeredAt,updatedAt:r.updatedAt,steps:r.manifest.steps.map(e=>({id:e.id,name:e.name,instruction:b(r,e.instruction),produces:e.produces,requires:e.requires,description:e.description})),agents:r.manifest.agents,artifactsDir:r.manifest.artifacts_dir,install:r.manifest.install};return K(JSON.stringify(o,null,2))}catch(e){return G.error(`flow_info failed`,A(e)),K(`Error: ${q(e)}`)}});let re=L(`flow_start`);e.registerTool(`flow_start`,{title:re.title,description:`Start a flow. Sets the active flow and positions at the first step.`,annotations:re.annotations,inputSchema:{flow:P.string().describe(`Flow name to start (use flow_list to see options)`),topic:P.string().optional().describe(`Human-readable topic for the run (e.g. "Add authentication"). Used as directory name under .flows/.`),roots:P.array(P.string()).optional().describe(`Workspace roots participating in this flow. For multi-repo tasks, list all repos that need a .flows/<slug>/ directory. Flow state is synchronized across all listed roots. Omit for single-root workspaces (defaults to primary root).`)}},async({flow:e,topic:t,roots:r})=>{try{if(r&&r.length>0){let e=r.filter(e=>!d(e));if(e.length>0)return K(`Invalid roots — not part of the workspace or a recognized sub-repository: ${e.join(`, `)}. Available roots: ${i().map(e=>e.replaceAll(`\\`,`/`)).join(`, `)}`)}let a=r?.[0]??n(),{registry:o,stateMachine:s}=await E(a),c=o.get(e);if(!c)return K(`Flow "${e}" not found. Use flow_list to see available flows.`);let l=s.start(c.name,c.manifest,t);if(!l.success||!l.data)return K(`Cannot start: ${l.error}`);let u=l.data;if(r&&r.length>1)try{ee(u.slug,a,r),te(u.slug,a)}catch(e){return s.reset(),K(`Flow created but failed to sync to secondary roots — rolled back. Error: ${e instanceof Error?e.message:String(e)}`)}let{instructionPath:f,description:p}=C(c,u.currentStep,a),m=S(c),h={started:!0,flow:u.flow,slug:u.slug,topic:u.topic,runDir:u.runDir,artifactsPath:g(u.runDir,c.manifest.artifacts_dir).replaceAll(`\\`,`/`),currentStep:u.currentStep,currentStepInstruction:f,currentStepDescription:p,phase:u.phase,isEpilogue:u.isEpilogue,totalSteps:m.length,stepSequence:m,artifactsDir:c.manifest.artifacts_dir,roots:r??[a.replaceAll(`\\`,`/`)]};return K(JSON.stringify(h,null,2))}catch(e){return G.error(`flow_start failed`,A(e)),K(`Error: ${q(e)}`)}});let M=L(`flow_step`);e.registerTool(`flow_step`,{title:M.title,description:`Advance the active flow: complete current step and move to next, skip current step, or redo current step.`,annotations:M.annotations,inputSchema:{action:P.enum([`next`,`skip`,`redo`]).describe(`next: mark current step done and advance. skip: skip current step. redo: repeat current step.`)}},async({action:e})=>{try{let t=await k(),{registry:n,stateMachine:r}=await E(t),i=r.getStatus();if(!i.success||!i.data)return K(`No active flow. Use flow_start first.`);let a=n.get(i.data.flow);if(!a)return K(`Flow "${i.data.flow}" not found in registry.`);let o=r.step(e,a.manifest);if(!o.success||!o.data)return K(`Cannot ${e}: ${o.error}`);te(o.data.slug,t);let s=o.data,{instructionPath:c,description:l}=C(a,s.currentStep,t),u=S(a),d={flow:s.flow,status:s.status,action:e,slug:s.slug,topic:s.topic,runDir:s.runDir,artifactsPath:g(s.runDir,a.manifest.artifacts_dir).replaceAll(`\\`,`/`),currentStep:s.currentStep,currentStepInstruction:c,currentStepDescription:l,phase:s.phase,isEpilogue:s.isEpilogue,completedSteps:s.completedSteps,skippedSteps:s.skippedSteps,totalSteps:u.length,remaining:u.filter(e=>!s.completedSteps.includes(e)&&!s.skippedSteps.includes(e)&&e!==s.currentStep)};return K(JSON.stringify(d,null,2))}catch(e){return G.error(`flow_step failed`,A(e)),K(`Error: ${q(e)}`)}});let ie=L(`flow_status`);e.registerTool(`flow_status`,{title:ie.title,description:`Show the current flow execution state — which flow is active, current step, completed steps, and artifacts.`,annotations:ie.annotations,inputSchema:{}},async()=>{try{let e=await k(),{registry:r,stateMachine:a}=await E(e),o=a.getStatus();if(!o.success||!o.data)return K(`No active flow. Use flow_start to begin one, or flow_list to see available flows.`);let s=o.data,c=r.get(s.flow),l=c?C(c,s.currentStep,e):null,u=c?S(c):[],d=l?.instructionPath??null,f={flow:s.flow,status:s.status,slug:s.slug,topic:s.topic,runDir:s.runDir,artifactsPath:c?g(s.runDir,c.manifest.artifacts_dir).replaceAll(`\\`,`/`):null,currentStep:s.currentStep,currentStepInstruction:d,instructionPath:d,currentStepDescription:l?.description??null,phase:s.phase,isEpilogue:s.isEpilogue,completedSteps:s.completedSteps,skippedSteps:s.skippedSteps,artifacts:s.artifacts,startedAt:s.startedAt,updatedAt:s.updatedAt,totalSteps:u.length,progress:c?`${s.completedSteps.length+s.skippedSteps.length}/${u.length}`:`unknown`,workspaceRoot:e.replaceAll(`\\`,`/`),primaryRoot:(s.primaryRoot??e).replaceAll(`\\`,`/`),roots:s.roots??[e.replaceAll(`\\`,`/`)],allRoots:i().map(e=>e.replaceAll(`\\`,`/`)),discoveredRepos:(()=>{let e=(t.allRoots?.length?t.allRoots:[n()]).map(e=>e.replaceAll(`\\`,`/`)),r=i().map(e=>e.replaceAll(`\\`,`/`)).filter(t=>!e.includes(t));return r.length>0?r:void 0})()};return K(JSON.stringify(f,null,2))}catch(e){return G.error(`flow_status failed`,A(e)),K(`Error: ${q(e)}`)}});let ae=L(`flow_read_instruction`);e.registerTool(`flow_read_instruction`,{title:ae.title===`flow_read_instruction`?`Flow Read Instruction`:ae.title,description:`Read the instruction content for a flow step. If step is omitted, reads the current step.`,annotations:ae.title===`flow_read_instruction`?{readOnlyHint:!0,idempotentHint:!0}:ae.annotations,inputSchema:{step:P.string().optional().describe(`Step id or name to read. Defaults to the current step.`)}},async({step:e})=>{try{let t=await k(),{registry:n,stateMachine:r}=await E(t),i=r.getStatus();if(!i.success||!i.data)return K(`No active flow. Use flow_start to begin one, or flow_list to see available flows.`);let a=i.data,o=n.get(a.flow);if(!o)return K(`Flow "${a.flow}" not found in registry.`);let s=e??a.currentStep;if(!s)return K(`No current step is available for the active flow.`);let c=o.manifest.steps.find(e=>e.id===s||e.name===s);if(!c){let e=x(s,t);if(e){let n=await Yt(e,`utf-8`),r=g(a.runDir,o.manifest.artifacts_dir).replaceAll(`\\`,`/`),i=a.runDir.replaceAll(`\\`,`/`);return n=n.replaceAll(`{{artifacts_path}}`,r).replaceAll(`{{run_dir}}`,i).replaceAll(`{{workspace_root}}`,(a.primaryRoot??t).replaceAll(`\\`,`/`)).replaceAll(`{{all_roots}}`,JSON.stringify(a.roots??[t.replaceAll(`\\`,`/`)],null,2)),K(n)}return K(`Step "${s}" not found in flow "${a.flow}".`)}let l=await Yt(b(o,c.instruction,t),`utf-8`),u=g(a.runDir,o.manifest.artifacts_dir).replaceAll(`\\`,`/`),d=a.runDir.replaceAll(`\\`,`/`);l=l.replaceAll(`{{artifacts_path}}`,u).replaceAll(`{{run_dir}}`,d).replaceAll(`{{workspace_root}}`,(a.primaryRoot??t).replaceAll(`\\`,`/`)).replaceAll(`{{all_roots}}`,JSON.stringify(a.roots??[t.replaceAll(`\\`,`/`)],null,2));for(let e of[`spec-driven`])l=l.replaceAll(`${e}/${a.slug}/`,`${u}/`);return K(l)}catch(e){return G.error(`flow_read_instruction failed`,A(e)),e instanceof Error&&`code`in e&&e.code===`ENOENT`?K(`Could not read instruction file: ${e.message}`):K(`Error: ${q(e)}`)}});let oe=L(`flow_reset`);e.registerTool(`flow_reset`,{title:oe.title,description:`Reset the active flow, clearing all state. Use to start over or switch to a different flow.`,annotations:oe.annotations,inputSchema:{}},async()=>{try{let e=await k(),{stateMachine:t}=await E(e),n=t.getStatus(),r=t.reset();return r.success?(n.success&&n.data&&te(n.data.slug,e),K(`Flow abandoned. Use flow_start to begin a new flow.`)):K(`Reset failed: ${r.error}`)}catch(e){return G.error(`flow_reset failed`,A(e)),K(`Error: ${q(e)}`)}});let se=L(`flow_runs`);e.registerTool(`flow_runs`,{title:se.title===`flow_runs`?`Flow Runs`:se.title,description:`List all flow runs (current and past). Shows topic, flow, status, and progress for each run under .flows/.`,annotations:{readOnlyHint:!0,idempotentHint:!0},inputSchema:{flow:P.string().optional().describe(`Filter by flow name`),status:P.string().optional().describe(`Filter by status (active, completed, abandoned)`)}},async({flow:e,status:t})=>{try{let n=i(),r=[];for(let i of n){let{stateMachine:n}=await E(i),a=n.listRuns({flow:e,status:t});for(let e of a)r.push({...JSON.parse(JSON.stringify(e)),root:i.replaceAll(`\\`,`/`)})}let a=new Set,o=r.filter(e=>{let t=e.id;return a.has(t)?!1:(a.add(t),!0)});return o.length===0?K(`No flow runs found.`):K(JSON.stringify(o,null,2))}catch(e){return G.error(`flow_runs failed`,A(e)),K(`Error: ${q(e)}`)}});let ce=L(`flow_add`);e.registerTool(`flow_add`,{title:ce.title,description:`Install a new development flow from a git repository URL or local directory path. Use when the user wants to add, install, import, or onboard a new workflow — for example: "use this as a flow", "add this flow", "add this flow URL", "install a flow", or "onboard a flow". Accepts git URLs (https://..., git@...) and local filesystem paths. Also accepts the shorthand "openspec" to install the OpenSpec flow (auto-detects local npm global install or clones from GitHub).`,annotations:ce.annotations,inputSchema:{source:P.string().describe(`Git repository URL (https://... or git@...) or absolute/local directory path containing a flow definition. Use "openspec" as a shorthand to auto-resolve the OpenSpec flow.`),name:P.string().optional().describe(`Optional override for the installed flow name. If omitted, the name comes from the flow manifest.`),token:P.string().optional().describe(`Authentication token for private/GHE repositories`)}},async({source:t,name:n,token:r})=>{try{let{registry:i,loader:a,installer:o}=await E(),s=Go(e),c=t===`openspec`||t.startsWith(`openspec:`),l,u=t,d;if(c){let e=w();u=e.path,l=e.sourceType}let f=c?null:T(u);f&&(u=f.path,l=f.sourceType);let m=/^https?:\/\/|^git@/.test(u),h;if(m){let e=o.clone(u,r);if(!e.success||!e.data)return K(`Failed to clone flow: ${e.error}`);h=e.data}else{let e=_(u);d=e;let t=n||p(e)||`custom-flow`,r=o.copyLocal(e,t);if(!r.success||!r.data)return K(`Failed to copy flow: ${r.error}`);h=r.data}let g=await a.load(h,{forceAssetSync:!0,transform:s});if(!g.success||!g.data)return o.remove(h),K(`Failed to load flow manifest: ${g.error}`);let{manifest:v,format:y}=g.data,b=n||v.name,x=l??(m?`git`:`local`);if(i.has(b))return o.remove(h),K(`Flow "${b}" is already installed. Use flow_update to update it, or flow_remove then flow_add to replace.`);if(v.install.length>0){let e=o.runInstallDeps(v.install);if(!e.success)return o.remove(h),K(`Dependency install failed: ${e.error}`)}let S=new Date().toISOString(),C=m?o.getLocalCommit(h):void 0,D=i.register({name:b,version:v.version,source:x===`local`||x===`claude-plugin`?d??t:t,sourceType:x,installPath:h,format:y,registeredAt:S,updatedAt:S,manifest:v,...C?{commitSha:C}:{}});if(!D.success)return o.remove(h),K(`Failed to register flow: ${D.error}`);let O=v.steps.length;return K(`Flow "${b}" installed successfully (${O} steps). Use flow_start({ flow: "${b}" }) to begin.`)}catch(e){return G.error(`flow_add failed`,A(e)),K(`Error: ${q(e)}`)}});let le=L(`flow_remove`);e.registerTool(`flow_remove`,{title:le.title,description:`Remove an installed flow by name. Unregisters it and deletes its files when applicable. Builtin flows cannot be removed.`,annotations:le.annotations,inputSchema:{name:P.string().describe(`Name of the flow to remove.`)}},async({name:e})=>{try{let{registry:t,installer:n}=await E();if(!t.has(e))return K(`Flow "${e}" is not installed.`);let r=t.get(e);if(!r)return K(`Flow "${e}" is not installed.`);if(r.sourceType===`builtin`)return K(`Cannot remove builtin flow "${e}".`);let i=n.remove(r.installPath);if(!i.success)return K(`Failed to remove flow files: ${i.error}`);let a=t.unregister(e);return a.success?K(`Flow "${e}" removed successfully.`):K(`Failed to unregister flow: ${a.error}`)}catch(e){return G.error(`flow_remove failed`,A(e)),K(`Error: ${q(e)}`)}});let ue=L(`flow_update`);e.registerTool(`flow_update`,{title:ue.title,description:`Update an installed flow to its latest version. For git-based flows, pulls the latest changes. For npm-global flows (e.g. OpenSpec), runs npm update.`,annotations:ue.annotations,inputSchema:{name:P.string().describe(`Name of the flow to update.`)}},async({name:t})=>{try{let{registry:n,loader:r,installer:i}=await E(),o=Go(e);if(!n.has(t))return K(`Flow "${t}" is not installed.`);let s=n.get(t);if(!s||s.sourceType!==`git`&&s.sourceType!==`npm-global`&&s.sourceType!==`local`&&s.sourceType!==`claude-plugin`)return K(`Flow "${t}" was not installed from git, npm, or a local source — cannot update. Remove and re-add instead.`);if(s.sourceType===`local`||s.sourceType===`claude-plugin`){let e=_(s.source);if(!a(e))return K(`Source path no longer exists: ${e}`);let t=`${s.installPath}.updating`,c=`${s.installPath}.backup`;a(t)&&u(t,{recursive:!0,force:!0}),a(c)&&u(c,{recursive:!0,force:!0});let d=i.copyLocal(e,p(t));if(!d.success||!d.data)return K(`Failed to copy flow: ${d.error}`);let f=await r.load(t,{forceAssetSync:!0,transform:o});if(!f.success||!f.data)return i.remove(t),K(`Failed to load flow manifest: ${f.error}`);let m=!1;try{l(s.installPath,c),l(t,s.installPath);let e=await r.load(s.installPath,{forceAssetSync:!0,transform:o});if(!e.success||!e.data)throw Error(`Failed to load flow manifest: ${e.error}`);let a=e.data.manifest,d=e.data.format,f=n.register({...s,version:a.version,format:d,installPath:s.installPath,manifest:a,updatedAt:new Date().toISOString()});if(!f.success)throw Error(`Failed to refresh flow registry entry: ${f.error}`);if(m=!0,a.install.length>0){let e=i.runInstallDeps(a.install);if(!e.success)throw Error(`Dependency install failed: ${e.error}`)}u(c,{recursive:!0,force:!0})}catch(e){return a(t)&&u(t,{recursive:!0,force:!0}),a(c)&&(a(s.installPath)&&u(s.installPath,{recursive:!0,force:!0}),l(c,s.installPath)),m&&n.register(s),K(q(e))}return K(`Flow "${s.name}" updated from ${s.sourceType} source successfully.`)}if(s.sourceType===`npm-global`){try{kn(`npm update -g @fission-ai/openspec`,{encoding:`utf-8`,stdio:`pipe`})}catch(e){return K(`npm update failed: ${q(e)}`)}let e=w(),i=await r.load(e.path,{forceAssetSync:!0,transform:o}),a=i.success&&i.data?i.data.manifest:null,c=i.success&&i.data?i.data.format:s.format;if(a){let t=n.register({...s,version:a.version,format:c,installPath:e.path,manifest:a,updatedAt:new Date().toISOString()});if(!t.success)return K(`Failed to refresh flow registry entry: ${t.error}`)}return K(`Flow "${t}" updated via npm successfully.`)}let c=i.update(s.installPath);if(!c.success)return K(`Update failed: ${c.error}`);let d=await r.load(s.installPath,{forceAssetSync:!0,transform:o}),f=d.success&&d.data?d.data.manifest:null,m=d.success&&d.data?d.data.format:s.format;if(f){let e=i.getLocalCommit(s.installPath),t=n.register({...s,version:f.version,format:m,manifest:f,updatedAt:new Date().toISOString(),...e?{commitSha:e}:{}});if(!t.success)return K(`Failed to refresh flow registry entry: ${t.error}`)}let h=f?.install??s.manifest.install;if(h.length>0){let e=i.runInstallDeps(h);if(!e.success)return K(`Dependency install failed: ${e.error}`)}return K(`Flow "${t}" updated successfully.`)}catch(e){return G.error(`flow_update failed`,A(e)),K(`Error: ${q(e)}`)}})}const qo=D(`tools`);function Jo(e){let t=L(`evidence_map`);e.registerTool(`evidence_map`,{title:t.title,description:`Track verified/assumed/unresolved claims for complex tasks. Gate readiness: YIELD (proceed), HOLD (unknowns), HARD_BLOCK (critical gaps). Persists across calls.`,inputSchema:{action:P.enum([`create`,`add`,`update`,`get`,`gate`,`list`,`delete`]).describe(`Operation to perform`),task_id:P.string().optional().describe(`Task identifier (required for all except list)`),tier:P.enum([`floor`,`standard`,`critical`]).optional().describe(`FORGE tier (required for create)`),claim:P.string().optional().describe(`Critical-path claim text (for add)`),status:P.enum([`V`,`A`,`U`]).optional().describe(`Evidence status: V=Verified, A=Assumed, U=Unresolved`),receipt:P.string().optional().describe(`Evidence receipt: tool→ref for V, reasoning for A, attempts for U`),id:P.number().optional().describe(`Entry ID (for update)`),critical_path:P.boolean().default(!0).describe(`Whether this claim is on the critical path`),unknown_type:P.enum([`contract`,`convention`,`freshness`,`runtime`,`data-flow`,`impact`]).optional().describe(`Typed unknown classification`),safety_gate:P.enum([`provenance`,`commitment`,`coverage`]).optional().describe(`Safety gate tag: provenance (claim→evidence), commitment (user-approved), coverage (nothing dropped)`),retry_count:P.number().default(0).describe(`Retry count for gate evaluation (0 = first attempt)`),max_retries:P.number().int().min(0).optional().describe(`Maximum retries before escalating. Default: 3`),timeout_action:P.enum([`iterate`,`retry`,`manual`,`terminate`]).optional().describe(`Action to take when gate retries are exhausted. Default: manual`),cwd:P.string().optional().describe(`Working directory for evidence map storage (default: server cwd). Use root_path from forge_ground to match.`)},annotations:t.annotations},async({action:e,task_id:t,tier:n,claim:r,status:i,receipt:a,id:o,critical_path:s,unknown_type:c,safety_gate:l,retry_count:u,max_retries:d,timeout_action:f,cwd:p})=>{try{switch(e){case`create`:if(!t)throw Error(`task_id required for create`);if(!n)throw Error(`tier required for create`);return Ae({action:`create`,taskId:t,tier:n},p),{content:[{type:`text`,text:`Created evidence map "${t}" (tier: ${n}).\n\n---\n_Next: Use \`evidence_map\` with action "add" to record critical-path claims._`}]};case`add`:{if(!t)throw Error(`task_id required for add`);if(!r)throw Error(`claim required for add`);if(!i)throw Error(`status required for add`);let e=Ae({action:`add`,taskId:t,claim:r,status:i,receipt:a??``,criticalPath:s,unknownType:c,safetyGate:l},p),n=[`Added entry #${e.entry?.id} to "${t}": [${i}] ${r}`];return e.formattedMap&&n.push(``,e.formattedMap),{content:[{type:`text`,text:n.join(`
562
562
  `)}]}}case`update`:{if(!t)throw Error(`task_id required for update`);if(o===void 0)throw Error(`id required for update`);if(!i)throw Error(`status required for update`);let e=Ae({action:`update`,taskId:t,id:o,status:i,receipt:a??``},p),n=[`Updated entry #${o} in "${t}" → ${i}`];return e.formattedMap&&n.push(``,e.formattedMap),{content:[{type:`text`,text:n.join(`
563
563
  `)}]}}case`get`:{if(!t)throw Error(`task_id required for get`);let e=Ae({action:`get`,taskId:t},p);return e.state?{content:[{type:`text`,text:[`## Evidence Map: ${t} (${e.state.tier})`,``,e.formattedMap??`No entries.`,``,`_${e.state.entries.length} entries — created ${e.state.createdAt}_`].join(`
564
564
  `)}]}:{content:[{type:`text`,text:`Evidence map "${t}" not found.`}]}}case`gate`:{if(!t)throw Error(`task_id required for gate`);let e=Ae({action:`gate`,taskId:t,retryCount:u,maxRetries:d,timeoutAction:f},p);if(!e.gate)return{content:[{type:`text`,text:`Evidence map "${t}" not found.`}]};let n=e.gate,r=[`## FORGE Gate: **${n.verdict}**`,``,`**Reason:** ${n.reason}`,``,`**Stats:** ${n.stats.verified}V / ${n.stats.assumed}A / ${n.stats.unresolved}U (${n.stats.total} total)`];return n.action&&r.push(``,`**Recommended action:** ${n.action}`),n.retriesRemaining!==void 0&&r.push(`**Retries remaining:** ${n.retriesRemaining}`),n.summary&&r.push(``,`**Summary:** ${n.summary}`),n.warnings.length>0&&r.push(``,`**Warnings:**`,...n.warnings.map(e=>`- ⚠️ ${e}`)),n.unresolvedCritical.length>0&&r.push(``,`**Blocking entries:**`,...n.unresolvedCritical.map(e=>`- #${e.id}: ${e.claim} [${e.unknownType??`untyped`}]`)),n.safetyGates&&(r.push(``,`**Safety Gates:**`,`- Provenance: ${n.safetyGates.provenance}`,`- Commitment: ${n.safetyGates.commitment}`,`- Coverage: ${n.safetyGates.coverage}`),n.safetyGates.failures.length>0&&r.push(``,`**Safety failures:**`,...n.safetyGates.failures.map(e=>`- \u{1F6D1} ${e}`))),n.annotation&&r.push(``,`**Annotation:**`,n.annotation),e.formattedMap&&r.push(``,`---`,``,e.formattedMap),r.push(``,`---`,`_Next: ${n.verdict===`YIELD`?`Proceed to implementation.`:n.action===`iterate`?`Re-run the build loop, then evaluate the gate again.`:n.action===`retry`?`Re-evaluate the gate after refreshing evidence.`:n.action===`manual`?`Ask for human review before proceeding.`:`Abort the current path and terminate the task.`}_`),{content:[{type:`text`,text:r.join(`