@triedotdev/mcp 1.0.166 → 1.0.167
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +337 -801
- package/dist/chunk-2HF65EHQ.js +311 -0
- package/dist/chunk-2HF65EHQ.js.map +1 -0
- package/dist/{chunk-JNUOW2JS.js → chunk-4MXH2ZPT.js} +12 -12
- package/dist/chunk-4MXH2ZPT.js.map +1 -0
- package/dist/{chunk-LR5M4RTN.js → chunk-575YT2SD.js} +1 -1
- package/dist/chunk-575YT2SD.js.map +1 -0
- package/dist/{chunk-ZKKKLRZZ.js → chunk-5BRRRTN6.js} +4 -4
- package/dist/{chunk-TQOO6A4G.js → chunk-7WITSO22.js} +3 -3
- package/dist/{chunk-ACU2RJUJ.js → chunk-F6WFNUAY.js} +2 -2
- package/dist/{chunk-VR4VWXXU.js → chunk-G2TGF6TR.js} +9 -2
- package/dist/chunk-G2TGF6TR.js.map +1 -0
- package/dist/{chunk-ZBXW244P.js → chunk-HVCDY3AK.js} +3 -3
- package/dist/chunk-HVCDY3AK.js.map +1 -0
- package/dist/{chunk-HOGKPDZA.js → chunk-LQIMKE3P.js} +678 -151
- package/dist/chunk-LQIMKE3P.js.map +1 -0
- package/dist/{chunk-2Z3TQNNK.js → chunk-MRHKX5M5.js} +3 -3
- package/dist/{chunk-OLNZJ3XV.js → chunk-Q63FFI6D.js} +2 -2
- package/dist/{chunk-S36IO3EE.js → chunk-XE6KQRKZ.js} +9 -8
- package/dist/chunk-XE6KQRKZ.js.map +1 -0
- package/dist/{chunk-GDWA3CH3.js → chunk-XPZZFPBZ.js} +30 -6
- package/dist/chunk-XPZZFPBZ.js.map +1 -0
- package/dist/{chunk-JEZ7XJQN.js → chunk-XTFWT2XM.js} +2 -2
- package/dist/{chunk-UXRW2YSP.js → chunk-YDHUCDHM.js} +18 -112
- package/dist/chunk-YDHUCDHM.js.map +1 -0
- package/dist/{chunk-LG5CBK6A.js → chunk-YZ6Y2H3P.js} +21 -196
- package/dist/chunk-YZ6Y2H3P.js.map +1 -0
- package/dist/{chunk-MVVPJ73K.js → chunk-ZJF5FTBX.js} +126 -358
- package/dist/chunk-ZJF5FTBX.js.map +1 -0
- package/dist/cli/create-agent.js +1 -1
- package/dist/cli/create-agent.js.map +1 -1
- package/dist/cli/main.js +194 -849
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +15 -14
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{fast-analyzer-NJQO3TFD.js → fast-analyzer-XXYMOXRK.js} +3 -3
- package/dist/git-EO5SRFMN.js +28 -0
- package/dist/{github-ingester-TFBDUDIY.js → github-ingester-ZOKK6GRS.js} +3 -3
- package/dist/{goal-manager-DVX24UPZ.js → goal-manager-YOB7VWK7.js} +5 -4
- package/dist/{goal-validator-6Y5CDEMJ.js → goal-validator-ULKIBDPX.js} +5 -4
- package/dist/{hypothesis-UKPGOYY2.js → hypothesis-7BFFT5JY.js} +5 -4
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-UZAPI5DU.js → issue-store-ZIRP23EP.js} +4 -3
- package/dist/{ledger-CNFCJKHX.js → ledger-TWZTGDFA.js} +3 -2
- package/dist/{linear-ingester-PLES2BRS.js → linear-ingester-XXPAZZRW.js} +3 -3
- package/dist/{output-manager-JNMEAXFO.js → output-manager-RVJ37XKA.js} +2 -2
- package/dist/server/mcp-server.js +19 -18
- package/dist/{tiered-storage-OP74NPJY.js → tiered-storage-Z3YCR465.js} +2 -2
- package/dist/{trie-agent-6SWUHCVO.js → trie-agent-3YDPEGHJ.js} +9 -8
- package/dist/trie-agent-3YDPEGHJ.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-GDWA3CH3.js.map +0 -1
- package/dist/chunk-HOGKPDZA.js.map +0 -1
- package/dist/chunk-JNUOW2JS.js.map +0 -1
- package/dist/chunk-LG5CBK6A.js.map +0 -1
- package/dist/chunk-LR5M4RTN.js.map +0 -1
- package/dist/chunk-MVVPJ73K.js.map +0 -1
- package/dist/chunk-S36IO3EE.js.map +0 -1
- package/dist/chunk-UXRW2YSP.js.map +0 -1
- package/dist/chunk-VR4VWXXU.js.map +0 -1
- package/dist/chunk-ZBXW244P.js.map +0 -1
- /package/dist/{chunk-ZKKKLRZZ.js.map → chunk-5BRRRTN6.js.map} +0 -0
- /package/dist/{chunk-TQOO6A4G.js.map → chunk-7WITSO22.js.map} +0 -0
- /package/dist/{chunk-ACU2RJUJ.js.map → chunk-F6WFNUAY.js.map} +0 -0
- /package/dist/{chunk-2Z3TQNNK.js.map → chunk-MRHKX5M5.js.map} +0 -0
- /package/dist/{chunk-OLNZJ3XV.js.map → chunk-Q63FFI6D.js.map} +0 -0
- /package/dist/{chunk-JEZ7XJQN.js.map → chunk-XTFWT2XM.js.map} +0 -0
- /package/dist/{fast-analyzer-NJQO3TFD.js.map → fast-analyzer-XXYMOXRK.js.map} +0 -0
- /package/dist/{github-ingester-TFBDUDIY.js.map → git-EO5SRFMN.js.map} +0 -0
- /package/dist/{goal-manager-DVX24UPZ.js.map → github-ingester-ZOKK6GRS.js.map} +0 -0
- /package/dist/{goal-validator-6Y5CDEMJ.js.map → goal-manager-YOB7VWK7.js.map} +0 -0
- /package/dist/{hypothesis-UKPGOYY2.js.map → goal-validator-ULKIBDPX.js.map} +0 -0
- /package/dist/{issue-store-UZAPI5DU.js.map → hypothesis-7BFFT5JY.js.map} +0 -0
- /package/dist/{ledger-CNFCJKHX.js.map → issue-store-ZIRP23EP.js.map} +0 -0
- /package/dist/{linear-ingester-PLES2BRS.js.map → ledger-TWZTGDFA.js.map} +0 -0
- /package/dist/{output-manager-JNMEAXFO.js.map → linear-ingester-XXPAZZRW.js.map} +0 -0
- /package/dist/{tiered-storage-OP74NPJY.js.map → output-manager-RVJ37XKA.js.map} +0 -0
- /package/dist/{trie-agent-6SWUHCVO.js.map → tiered-storage-Z3YCR465.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/output-manager.ts"],"sourcesContent":["/**\n * OutputManager - Unified output abstraction for all UI modes\n * \n * Routes content to the appropriate renderer based on current mode:\n * - TUI: Routes to InteractiveDashboard\n * - Console: Routes to console.error with ANSI colors\n * - MCP: Accumulates for markdown response\n * - JSON: Accumulates for JSON response\n * - Silent: Discards output\n * \n * This solves the problem of skills suppressing content in interactive mode\n * by redirecting it to the dashboard instead.\n */\n\nimport type { Issue } from '../types/index.js';\nimport type { StreamingManager } from './streaming.js';\nimport { isInteractiveMode } from './progress.js';\nimport * as pc from 'picocolors';\n\n// Output content types\nexport type OutputContentType = \n | 'banner' // ASCII art banner from skills\n | 'progress' // Progress update\n | 'issue' // Issue found\n | 'snippet' // Code snippet with context\n | 'cost' // Cost estimate from Moneybags\n | 'readiness' // Production readiness score\n | 'semantic' // Semantic analysis (data flow, race conditions)\n | 'attack' // Attack surface analysis\n | 'activity' // Activity log message\n | 'report' // Full markdown report section\n | 'log' // Raw log message\n | 'nudge'; // Proactive notification\n\n// Nudge content for proactive notifications\nexport interface NudgeContent {\n message: string;\n severity: 'critical' | 'warning' | 'info';\n file?: string;\n autoHideMs?: number; // Auto-dismiss after this many milliseconds\n}\n\nexport interface BannerContent {\n skill: string;\n art: string;\n quote?: string;\n version?: string;\n}\n\nexport interface SnippetContent {\n file: string;\n lines: string[];\n highlightLine?: number;\n startLine: number;\n}\n\nexport interface CostContent {\n fixNowCost: number;\n productionCost: number;\n savings: number;\n perIssue?: Array<{ issue: string; cost: number }>;\n}\n\nexport interface ReadinessContent {\n score: number;\n requirementsMet: number;\n total: number;\n status: 'ready' | 'caution' | 'not-ready';\n requirements?: Array<{ name: string; met: boolean }>;\n}\n\nexport interface SemanticContent {\n dataFlowIssues: number;\n raceConditions: number;\n authIssues: number;\n details?: Array<{ type: string; description: string; file: string; line?: number }>;\n}\n\nexport interface AttackSurfaceContent {\n totalEndpoints: number;\n unprotected: number;\n riskScore: number;\n endpoints?: Array<{ path: string; method: string; auth: boolean; sensitive: boolean }>;\n}\n\nexport interface OutputContent {\n type: OutputContentType;\n content: any;\n timestamp?: number;\n metadata?: {\n severity?: 'critical' | 'serious' | 'moderate' | 'low';\n agent?: string;\n file?: string;\n };\n}\n\nexport type OutputMode = 'tui' | 'console' | 'mcp' | 'json' | 'silent';\n\n/**\n * Central output manager - singleton\n */\nclass OutputManagerImpl {\n private mode: OutputMode = 'console';\n private streamingManager?: StreamingManager;\n private markdownBuffer: string[] = [];\n private jsonBuffer: OutputContent[] = [];\n private rawLogBuffer: Array<{ time: string; level: string; message: string }> = [];\n \n // Callbacks for TUI integration (explicitly allow undefined for exactOptionalPropertyTypes)\n private onBanner: ((content: BannerContent) => void) | undefined = undefined;\n private onSnippet: ((content: SnippetContent) => void) | undefined = undefined;\n private onCost: ((content: CostContent) => void) | undefined = undefined;\n private onReadiness: ((content: ReadinessContent) => void) | undefined = undefined;\n private onSemantic: ((content: SemanticContent) => void) | undefined = undefined;\n private onAttack: ((content: AttackSurfaceContent) => void) | undefined = undefined;\n private onActivity: ((message: string) => void) | undefined = undefined;\n private onLog: ((level: string, message: string) => void) | undefined = undefined;\n private onNudge: ((content: NudgeContent) => void) | undefined = undefined;\n\n /**\n * Set the output mode\n */\n setMode(mode: OutputMode): void {\n this.mode = mode;\n }\n\n /**\n * Get current output mode\n */\n getMode(): OutputMode {\n return this.mode;\n }\n\n /**\n * Set streaming manager for TUI updates\n */\n setStreamingManager(manager: StreamingManager): void {\n this.streamingManager = manager;\n }\n\n /**\n * Register TUI callbacks for rich content\n */\n registerTUICallbacks(callbacks: {\n onBanner?: (content: BannerContent) => void;\n onSnippet?: (content: SnippetContent) => void;\n onCost?: (content: CostContent) => void;\n onReadiness?: (content: ReadinessContent) => void;\n onSemantic?: (content: SemanticContent) => void;\n onAttack?: (content: AttackSurfaceContent) => void;\n onActivity?: (message: string) => void;\n onLog?: (level: string, message: string) => void;\n onNudge?: (content: NudgeContent) => void;\n }): void {\n this.onBanner = callbacks.onBanner;\n this.onSnippet = callbacks.onSnippet;\n this.onCost = callbacks.onCost;\n this.onReadiness = callbacks.onReadiness;\n this.onSemantic = callbacks.onSemantic;\n this.onAttack = callbacks.onAttack;\n this.onActivity = callbacks.onActivity;\n this.onLog = callbacks.onLog;\n this.onNudge = callbacks.onNudge;\n }\n\n /**\n * Clear TUI callbacks (when dashboard stops)\n */\n clearTUICallbacks(): void {\n this.onBanner = undefined;\n this.onSnippet = undefined;\n this.onCost = undefined;\n this.onReadiness = undefined;\n this.onSemantic = undefined;\n this.onAttack = undefined;\n this.onActivity = undefined;\n this.onLog = undefined;\n this.onNudge = undefined;\n }\n\n /**\n * Emit content - routes to appropriate handler based on mode\n */\n emit(content: OutputContent): void {\n content.timestamp = content.timestamp ?? Date.now();\n \n switch (this.mode) {\n case 'tui':\n this.routeToTUI(content);\n break;\n case 'console':\n this.routeToConsole(content);\n break;\n case 'mcp':\n this.routeToMarkdown(content);\n break;\n case 'json':\n this.routeToJson(content);\n break;\n case 'silent':\n // Discard\n break;\n }\n \n // Always capture in raw log buffer\n this.captureRawLog(content);\n }\n\n /**\n * Route content to TUI (dashboard callbacks)\n */\n private routeToTUI(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n this.onBanner?.(content.content as BannerContent);\n break;\n case 'snippet':\n this.onSnippet?.(content.content as SnippetContent);\n break;\n case 'cost':\n this.onCost?.(content.content as CostContent);\n break;\n case 'readiness':\n this.onReadiness?.(content.content as ReadinessContent);\n break;\n case 'semantic':\n this.onSemantic?.(content.content as SemanticContent);\n break;\n case 'attack':\n this.onAttack?.(content.content as AttackSurfaceContent);\n break;\n case 'activity':\n this.onActivity?.(content.content as string);\n break;\n case 'log':\n const level = content.metadata?.severity ?? 'info';\n this.onLog?.(level, content.content as string);\n break;\n case 'issue':\n // Issues go through streaming manager\n this.streamingManager?.reportIssue(content.content as Issue);\n break;\n case 'progress':\n // Progress goes through streaming manager\n break;\n case 'report':\n // Reports are captured but not directly displayed\n break;\n case 'nudge':\n // Proactive notifications go to dashboard\n this.onNudge?.(content.content as NudgeContent);\n break;\n }\n }\n\n /**\n * Route content to console (ANSI formatted)\n */\n private routeToConsole(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n const banner = content.content as BannerContent;\n console.error('\\n' + '='.repeat(60));\n console.error(banner.art);\n if (banner.version) {\n console.error(` ${banner.skill} v${banner.version}`);\n }\n console.error('');\n if (banner.quote) {\n console.error(` \"${banner.quote}\"`);\n }\n console.error('='.repeat(60) + '\\n');\n break;\n \n case 'snippet':\n const snippet = content.content as SnippetContent;\n console.error(`\\n${pc.dim('File:')} ${snippet.file}`);\n for (let i = 0; i < snippet.lines.length; i++) {\n const lineNum = snippet.startLine + i;\n const isHighlight = lineNum === snippet.highlightLine;\n const prefix = isHighlight ? pc.red('→') : ' ';\n const lineNumStr = pc.dim(lineNum.toString().padStart(4));\n const line = isHighlight ? pc.yellow(snippet.lines[i]) : snippet.lines[i];\n console.error(`${prefix} ${lineNumStr} | ${line}`);\n }\n console.error('');\n break;\n \n case 'cost':\n const cost = content.content as CostContent;\n console.error('\\n' + pc.cyan('[$] Cost Estimate:'));\n console.error(` Fix now: ${pc.green(this.formatCurrency(cost.fixNowCost))}`);\n console.error(` If production: ${pc.red(this.formatCurrency(cost.productionCost))}`);\n console.error(` Savings: ${pc.yellow(this.formatCurrency(cost.savings))}`);\n console.error('');\n break;\n \n case 'readiness':\n const readiness = content.content as ReadinessContent;\n const statusColor = readiness.status === 'ready' ? pc.green : \n readiness.status === 'caution' ? pc.yellow : pc.red;\n console.error('\\n' + pc.cyan('[%] Production Readiness:'));\n console.error(` Score: ${statusColor(readiness.score + '/100')}`);\n console.error(` Requirements: ${readiness.requirementsMet}/${readiness.total}`);\n console.error(` Status: ${statusColor(readiness.status.toUpperCase())}`);\n console.error('');\n break;\n \n case 'semantic':\n const semantic = content.content as SemanticContent;\n console.error('\\n' + pc.cyan('[?] Semantic Analysis:'));\n if (semantic.dataFlowIssues > 0) {\n console.error(` ${pc.red('[!]')} ${semantic.dataFlowIssues} data flow vulnerabilities`);\n }\n if (semantic.raceConditions > 0) {\n console.error(` ${pc.yellow('[~]')} ${semantic.raceConditions} race conditions`);\n }\n if (semantic.authIssues > 0) {\n console.error(` ${pc.red('[!]')} ${semantic.authIssues} authentication issues`);\n }\n console.error('');\n break;\n \n case 'attack':\n const attack = content.content as AttackSurfaceContent;\n console.error('\\n' + pc.cyan('[>] Attack Surface:'));\n console.error(` Endpoints: ${attack.totalEndpoints}`);\n if (attack.unprotected > 0) {\n console.error(` ${pc.red('Unprotected:')} ${attack.unprotected}`);\n }\n console.error(` Risk Score: ${attack.riskScore}/100`);\n console.error('');\n break;\n \n case 'activity':\n console.error(pc.dim(`[${this.formatTime()}]`) + ` ${content.content}`);\n break;\n \n case 'log':\n // For log content, severity can be any string (info, warn, error, debug)\n const logLevel = String(content.metadata?.severity ?? 'info');\n const levelColor = logLevel === 'error' || logLevel === 'critical' ? pc.red :\n logLevel === 'warn' || logLevel === 'serious' ? pc.yellow :\n logLevel === 'info' || logLevel === 'moderate' ? pc.blue : pc.dim;\n console.error(levelColor(`[${logLevel.toUpperCase()}]`) + ` ${content.content}`);\n break;\n \n case 'issue':\n const issue = content.content as Issue;\n const sevColor = issue.severity === 'critical' ? pc.red :\n issue.severity === 'serious' ? pc.yellow :\n issue.severity === 'moderate' ? pc.blue : pc.dim;\n console.error(`${sevColor(`[${issue.severity.toUpperCase()}]`)} ${issue.issue}`);\n console.error(` ${pc.dim('File:')} ${issue.file}:${issue.line ?? '?'}`);\n break;\n \n case 'report':\n // Reports are printed as-is (already formatted)\n console.error(content.content);\n break;\n \n case 'nudge':\n // Proactive notifications in console mode\n const nudge = content.content as NudgeContent;\n // Get color function based on severity\n let nudgeColor: (text: string) => string;\n if (nudge.severity === 'critical') {\n nudgeColor = pc.red;\n } else if (nudge.severity === 'warning') {\n nudgeColor = pc.yellow;\n } else {\n nudgeColor = pc.cyan;\n }\n const nudgeIcon = nudge.severity === 'critical' ? '[!!!]' :\n nudge.severity === 'warning' ? '[!]' : '[>]';\n console.error('');\n console.error(nudgeColor('━'.repeat(60)));\n console.error(nudgeColor(`${nudgeIcon} TRIE AGENT SAYS:`));\n console.error(nudgeColor('━'.repeat(60)));\n console.error('');\n console.error(` ${pc.bold(nudge.message)}`);\n if (nudge.file) {\n console.error(` ${pc.dim('File:')} ${nudge.file}`);\n }\n console.error('');\n console.error(nudgeColor('━'.repeat(60)));\n console.error('');\n break;\n }\n }\n\n /**\n * Route content to markdown buffer\n */\n private routeToMarkdown(content: OutputContent): void {\n switch (content.type) {\n case 'banner':\n const banner = content.content as BannerContent;\n this.markdownBuffer.push(`## ${banner.skill}\\n`);\n if (banner.quote) {\n this.markdownBuffer.push(`> ${banner.quote}\\n`);\n }\n break;\n \n case 'snippet':\n const snippet = content.content as SnippetContent;\n this.markdownBuffer.push(`\\n**File:** \\`${snippet.file}\\`\\n`);\n this.markdownBuffer.push('```\\n');\n for (let i = 0; i < snippet.lines.length; i++) {\n const lineNum = snippet.startLine + i;\n const prefix = lineNum === snippet.highlightLine ? '→' : ' ';\n this.markdownBuffer.push(`${prefix} ${lineNum.toString().padStart(4)} | ${snippet.lines[i]}\\n`);\n }\n this.markdownBuffer.push('```\\n');\n break;\n \n case 'cost':\n const cost = content.content as CostContent;\n this.markdownBuffer.push(`\\n### Cost Estimate\\n`);\n this.markdownBuffer.push(`- Fix now: ${this.formatCurrency(cost.fixNowCost)}\\n`);\n this.markdownBuffer.push(`- If production: ${this.formatCurrency(cost.productionCost)}\\n`);\n this.markdownBuffer.push(`- Savings: ${this.formatCurrency(cost.savings)}\\n`);\n break;\n \n case 'readiness':\n const readiness = content.content as ReadinessContent;\n this.markdownBuffer.push(`\\n### Production Readiness\\n`);\n this.markdownBuffer.push(`- Score: ${readiness.score}/100\\n`);\n this.markdownBuffer.push(`- Requirements: ${readiness.requirementsMet}/${readiness.total}\\n`);\n this.markdownBuffer.push(`- Status: **${readiness.status.toUpperCase()}**\\n`);\n break;\n \n case 'semantic':\n const semantic = content.content as SemanticContent;\n this.markdownBuffer.push(`\\n### Semantic Analysis\\n`);\n if (semantic.dataFlowIssues > 0) {\n this.markdownBuffer.push(`- [CRITICAL] ${semantic.dataFlowIssues} data flow vulnerabilities\\n`);\n }\n if (semantic.raceConditions > 0) {\n this.markdownBuffer.push(`- [WARN] ${semantic.raceConditions} race conditions\\n`);\n }\n if (semantic.authIssues > 0) {\n this.markdownBuffer.push(`- [CRITICAL] ${semantic.authIssues} authentication issues\\n`);\n }\n break;\n \n case 'attack':\n const attack = content.content as AttackSurfaceContent;\n this.markdownBuffer.push(`\\n### Attack Surface\\n`);\n this.markdownBuffer.push(`- Endpoints: ${attack.totalEndpoints}\\n`);\n this.markdownBuffer.push(`- Unprotected: ${attack.unprotected}\\n`);\n this.markdownBuffer.push(`- Risk Score: ${attack.riskScore}/100\\n`);\n break;\n \n case 'report':\n this.markdownBuffer.push(content.content);\n break;\n \n default:\n // Other types are captured in JSON buffer\n this.jsonBuffer.push(content);\n }\n }\n\n /**\n * Route content to JSON buffer\n */\n private routeToJson(content: OutputContent): void {\n this.jsonBuffer.push(content);\n }\n\n /**\n * Capture content in raw log buffer\n */\n private captureRawLog(content: OutputContent): void {\n const time = this.formatTime(content.timestamp);\n const level = content.metadata?.severity ?? content.type;\n let message = '';\n \n switch (content.type) {\n case 'banner':\n message = `[BANNER] ${(content.content as BannerContent).skill}`;\n break;\n case 'activity':\n case 'log':\n message = content.content as string;\n break;\n case 'issue':\n const issue = content.content as Issue;\n message = `[${issue.severity.toUpperCase()}] ${issue.issue}`;\n break;\n default:\n message = `[${content.type.toUpperCase()}] Content received`;\n }\n \n this.rawLogBuffer.push({ time, level, message });\n \n // Keep buffer size reasonable\n if (this.rawLogBuffer.length > 500) {\n this.rawLogBuffer = this.rawLogBuffer.slice(-500);\n }\n }\n\n /**\n * Get raw log buffer for display\n */\n getRawLog(): Array<{ time: string; level: string; message: string }> {\n return [...this.rawLogBuffer];\n }\n\n /**\n * Get accumulated markdown output\n */\n getMarkdown(): string {\n return this.markdownBuffer.join('\\n');\n }\n\n /**\n * Get accumulated JSON output\n */\n getJson(): OutputContent[] {\n return [...this.jsonBuffer];\n }\n\n /**\n * Clear buffers\n */\n clearBuffers(): void {\n this.markdownBuffer = [];\n this.jsonBuffer = [];\n }\n\n // ============================================\n // Convenience methods for common output types\n // ============================================\n\n /**\n * Display a skill banner\n */\n banner(skill: string, art: string, options?: { quote?: string; version?: string }): void {\n this.emit({\n type: 'banner',\n content: { skill, art, quote: options?.quote, version: options?.version } as BannerContent,\n metadata: { agent: skill }\n });\n }\n\n /**\n * Display a code snippet\n */\n snippet(file: string, lines: string[], startLine: number, highlightLine?: number): void {\n this.emit({\n type: 'snippet',\n content: { file, lines, startLine, highlightLine } as SnippetContent,\n metadata: { file }\n });\n }\n\n /**\n * Display cost estimate\n */\n cost(fixNowCost: number, productionCost: number, savings: number, perIssue?: Array<{ issue: string; cost: number }>): void {\n this.emit({\n type: 'cost',\n content: { fixNowCost, productionCost, savings, perIssue } as CostContent\n });\n }\n\n /**\n * Display production readiness\n */\n readiness(\n score: number, \n requirementsMet: number, \n total: number, \n status: 'ready' | 'caution' | 'not-ready',\n requirements?: Array<{ name: string; met: boolean }>\n ): void {\n const content: ReadinessContent = { score, requirementsMet, total, status };\n if (requirements) {\n content.requirements = requirements;\n }\n this.emit({\n type: 'readiness',\n content\n });\n }\n\n /**\n * Display semantic analysis results\n */\n semantic(dataFlowIssues: number, raceConditions: number, authIssues: number): void {\n this.emit({\n type: 'semantic',\n content: { dataFlowIssues, raceConditions, authIssues } as SemanticContent\n });\n }\n\n /**\n * Display attack surface analysis\n */\n attack(totalEndpoints: number, unprotected: number, riskScore: number): void {\n this.emit({\n type: 'attack',\n content: { totalEndpoints, unprotected, riskScore } as AttackSurfaceContent\n });\n }\n\n /**\n * Log an activity message\n */\n activity(message: string): void {\n this.emit({\n type: 'activity',\n content: message\n });\n }\n\n /**\n * Log a message at specified level\n */\n log(level: 'info' | 'warn' | 'error' | 'debug', message: string): void {\n this.emit({\n type: 'log',\n content: message,\n metadata: { severity: level as any }\n });\n }\n\n /**\n * Log info message\n */\n info(message: string): void {\n this.log('info', message);\n }\n\n /**\n * Log warning message\n */\n warn(message: string): void {\n this.log('warn', message);\n }\n\n /**\n * Log error message\n */\n error(message: string): void {\n this.log('error', message);\n }\n\n /**\n * Log debug message\n */\n debug(message: string): void {\n this.log('debug', message);\n }\n\n /**\n * Report an issue\n */\n issue(issue: Issue): void {\n this.emit({\n type: 'issue',\n content: issue,\n metadata: { severity: issue.severity, agent: issue.agent, file: issue.file }\n });\n }\n\n /**\n * Add a report section\n */\n report(content: string): void {\n this.emit({\n type: 'report',\n content\n });\n }\n\n /**\n * Send a proactive notification/nudge to the user\n * This creates a prominent popup in TUI mode or a boxed message in console mode\n */\n nudge(message: string, severity: 'critical' | 'warning' | 'info' = 'warning', file?: string, autoHideMs?: number): void {\n const metadata: { severity?: 'critical' | 'serious' | 'moderate' | 'low'; agent?: string; file?: string } = {};\n // Map nudge severity to issue severity\n if (severity === 'critical') metadata.severity = 'critical';\n else if (severity === 'warning') metadata.severity = 'moderate';\n else metadata.severity = 'low';\n if (file !== undefined) metadata.file = file;\n this.emit({\n type: 'nudge',\n content: { message, severity, file, autoHideMs } as NudgeContent,\n metadata,\n });\n }\n\n // ============================================\n // Helpers\n // ============================================\n\n private formatCurrency(amount: number): string {\n if (amount >= 1000000) return `$${(amount / 1000000).toFixed(2)}M`;\n if (amount >= 1000) return `$${(amount / 1000).toFixed(1)}k`;\n return `$${amount}`;\n }\n\n private formatTime(timestamp?: number): string {\n const date = timestamp ? new Date(timestamp) : new Date();\n return date.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });\n }\n}\n\n// Singleton instance\nlet instance: OutputManagerImpl | null = null;\n\n/**\n * Get the OutputManager instance\n */\nexport function getOutputManager(): OutputManagerImpl {\n if (!instance) {\n instance = new OutputManagerImpl();\n \n // Auto-detect mode based on interactive mode flag\n if (isInteractiveMode()) {\n instance.setMode('tui');\n }\n }\n return instance;\n}\n\n/**\n * Convenience function - shorthand for getOutputManager()\n */\nexport function output(): OutputManagerImpl {\n return getOutputManager();\n}\n\n/**\n * Reset the OutputManager (for testing)\n */\nexport function resetOutputManager(): void {\n instance = null;\n}\n"],"mappings":";;;;;AAiBA,YAAY,QAAQ;AAoFpB,IAAM,oBAAN,MAAwB;AAAA,EACd,OAAmB;AAAA,EACnB;AAAA,EACA,iBAA2B,CAAC;AAAA,EAC5B,aAA8B,CAAC;AAAA,EAC/B,eAAwE,CAAC;AAAA;AAAA,EAGzE,WAA2D;AAAA,EAC3D,YAA6D;AAAA,EAC7D,SAAuD;AAAA,EACvD,cAAiE;AAAA,EACjE,aAA+D;AAAA,EAC/D,WAAkE;AAAA,EAClE,aAAsD;AAAA,EACtD,QAAgE;AAAA,EAChE,UAAyD;AAAA;AAAA;AAAA;AAAA,EAKjE,QAAQ,MAAwB;AAC9B,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,SAAiC;AACnD,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,WAUZ;AACP,SAAK,WAAW,UAAU;AAC1B,SAAK,YAAY,UAAU;AAC3B,SAAK,SAAS,UAAU;AACxB,SAAK,cAAc,UAAU;AAC7B,SAAK,aAAa,UAAU;AAC5B,SAAK,WAAW,UAAU;AAC1B,SAAK,aAAa,UAAU;AAC5B,SAAK,QAAQ,UAAU;AACvB,SAAK,UAAU,UAAU;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA0B;AACxB,SAAK,WAAW;AAChB,SAAK,YAAY;AACjB,SAAK,SAAS;AACd,SAAK,cAAc;AACnB,SAAK,aAAa;AAClB,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,SAA8B;AACjC,YAAQ,YAAY,QAAQ,aAAa,KAAK,IAAI;AAElD,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,aAAK,WAAW,OAAO;AACvB;AAAA,MACF,KAAK;AACH,aAAK,eAAe,OAAO;AAC3B;AAAA,MACF,KAAK;AACH,aAAK,gBAAgB,OAAO;AAC5B;AAAA,MACF,KAAK;AACH,aAAK,YAAY,OAAO;AACxB;AAAA,MACF,KAAK;AAEH;AAAA,IACJ;AAGA,SAAK,cAAc,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,SAA8B;AAC/C,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,aAAK,WAAW,QAAQ,OAAwB;AAChD;AAAA,MACF,KAAK;AACH,aAAK,YAAY,QAAQ,OAAyB;AAClD;AAAA,MACF,KAAK;AACH,aAAK,SAAS,QAAQ,OAAsB;AAC5C;AAAA,MACF,KAAK;AACH,aAAK,cAAc,QAAQ,OAA2B;AACtD;AAAA,MACF,KAAK;AACH,aAAK,aAAa,QAAQ,OAA0B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,WAAW,QAAQ,OAA+B;AACvD;AAAA,MACF,KAAK;AACH,aAAK,aAAa,QAAQ,OAAiB;AAC3C;AAAA,MACF,KAAK;AACH,cAAM,QAAQ,QAAQ,UAAU,YAAY;AAC5C,aAAK,QAAQ,OAAO,QAAQ,OAAiB;AAC7C;AAAA,MACF,KAAK;AAEH,aAAK,kBAAkB,YAAY,QAAQ,OAAgB;AAC3D;AAAA,MACF,KAAK;AAEH;AAAA,MACF,KAAK;AAEH;AAAA,MACF,KAAK;AAEH,aAAK,UAAU,QAAQ,OAAuB;AAC9C;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,SAA8B;AACnD,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,cAAM,SAAS,QAAQ;AACvB,gBAAQ,MAAM,OAAO,IAAI,OAAO,EAAE,CAAC;AACnC,gBAAQ,MAAM,OAAO,GAAG;AACxB,YAAI,OAAO,SAAS;AAClB,kBAAQ,MAAM,WAAW,OAAO,KAAK,KAAK,OAAO,OAAO,EAAE;AAAA,QAC5D;AACA,gBAAQ,MAAM,EAAE;AAChB,YAAI,OAAO,OAAO;AAChB,kBAAQ,MAAM,OAAO,OAAO,KAAK,GAAG;AAAA,QACtC;AACA,gBAAQ,MAAM,IAAI,OAAO,EAAE,IAAI,IAAI;AACnC;AAAA,MAEF,KAAK;AACH,cAAM,UAAU,QAAQ;AACxB,gBAAQ,MAAM;AAAA,EAAQ,OAAI,OAAO,CAAC,IAAI,QAAQ,IAAI,EAAE;AACpD,iBAAS,IAAI,GAAG,IAAI,QAAQ,MAAM,QAAQ,KAAK;AAC7C,gBAAM,UAAU,QAAQ,YAAY;AACpC,gBAAM,cAAc,YAAY,QAAQ;AACxC,gBAAM,SAAS,cAAiB,OAAI,QAAG,IAAI;AAC3C,gBAAM,aAAgB,OAAI,QAAQ,SAAS,EAAE,SAAS,CAAC,CAAC;AACxD,gBAAM,OAAO,cAAiB,UAAO,QAAQ,MAAM,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC;AACxE,kBAAQ,MAAM,GAAG,MAAM,IAAI,UAAU,MAAM,IAAI,EAAE;AAAA,QACnD;AACA,gBAAQ,MAAM,EAAE;AAChB;AAAA,MAEF,KAAK;AACH,cAAM,OAAO,QAAQ;AACrB,gBAAQ,MAAM,OAAU,QAAK,oBAAoB,CAAC;AAClD,gBAAQ,MAAM,eAAkB,SAAM,KAAK,eAAe,KAAK,UAAU,CAAC,CAAC,EAAE;AAC7E,gBAAQ,MAAM,qBAAwB,OAAI,KAAK,eAAe,KAAK,cAAc,CAAC,CAAC,EAAE;AACrF,gBAAQ,MAAM,eAAkB,UAAO,KAAK,eAAe,KAAK,OAAO,CAAC,CAAC,EAAE;AAC3E,gBAAQ,MAAM,EAAE;AAChB;AAAA,MAEF,KAAK;AACH,cAAM,YAAY,QAAQ;AAC1B,cAAM,cAAc,UAAU,WAAW,UAAa,WACnC,UAAU,WAAW,YAAe,YAAY;AACnE,gBAAQ,MAAM,OAAU,QAAK,2BAA2B,CAAC;AACzD,gBAAQ,MAAM,aAAa,YAAY,UAAU,QAAQ,MAAM,CAAC,EAAE;AAClE,gBAAQ,MAAM,oBAAoB,UAAU,eAAe,IAAI,UAAU,KAAK,EAAE;AAChF,gBAAQ,MAAM,cAAc,YAAY,UAAU,OAAO,YAAY,CAAC,CAAC,EAAE;AACzE,gBAAQ,MAAM,EAAE;AAChB;AAAA,MAEF,KAAK;AACH,cAAM,WAAW,QAAQ;AACzB,gBAAQ,MAAM,OAAU,QAAK,wBAAwB,CAAC;AACtD,YAAI,SAAS,iBAAiB,GAAG;AAC/B,kBAAQ,MAAM,MAAS,OAAI,KAAK,CAAC,IAAI,SAAS,cAAc,4BAA4B;AAAA,QAC1F;AACA,YAAI,SAAS,iBAAiB,GAAG;AAC/B,kBAAQ,MAAM,MAAS,UAAO,KAAK,CAAC,IAAI,SAAS,cAAc,kBAAkB;AAAA,QACnF;AACA,YAAI,SAAS,aAAa,GAAG;AAC3B,kBAAQ,MAAM,MAAS,OAAI,KAAK,CAAC,IAAI,SAAS,UAAU,wBAAwB;AAAA,QAClF;AACA,gBAAQ,MAAM,EAAE;AAChB;AAAA,MAEF,KAAK;AACH,cAAM,SAAS,QAAQ;AACvB,gBAAQ,MAAM,OAAU,QAAK,qBAAqB,CAAC;AACnD,gBAAQ,MAAM,iBAAiB,OAAO,cAAc,EAAE;AACtD,YAAI,OAAO,cAAc,GAAG;AAC1B,kBAAQ,MAAM,MAAS,OAAI,cAAc,CAAC,IAAI,OAAO,WAAW,EAAE;AAAA,QACpE;AACA,gBAAQ,MAAM,kBAAkB,OAAO,SAAS,MAAM;AACtD,gBAAQ,MAAM,EAAE;AAChB;AAAA,MAEF,KAAK;AACH,gBAAQ,MAAS,OAAI,IAAI,KAAK,WAAW,CAAC,GAAG,IAAI,IAAI,QAAQ,OAAO,EAAE;AACtE;AAAA,MAEF,KAAK;AAEH,cAAM,WAAW,OAAO,QAAQ,UAAU,YAAY,MAAM;AAC5D,cAAM,aAAa,aAAa,WAAW,aAAa,aAAgB,SACtD,aAAa,UAAU,aAAa,YAAe,YACnD,aAAa,UAAU,aAAa,aAAgB,UAAU;AAChF,gBAAQ,MAAM,WAAW,IAAI,SAAS,YAAY,CAAC,GAAG,IAAI,IAAI,QAAQ,OAAO,EAAE;AAC/E;AAAA,MAEF,KAAK;AACH,cAAM,QAAQ,QAAQ;AACtB,cAAM,WAAW,MAAM,aAAa,aAAgB,SACpC,MAAM,aAAa,YAAe,YAClC,MAAM,aAAa,aAAgB,UAAU;AAC7D,gBAAQ,MAAM,GAAG,SAAS,IAAI,MAAM,SAAS,YAAY,CAAC,GAAG,CAAC,IAAI,MAAM,KAAK,EAAE;AAC/E,gBAAQ,MAAM,MAAS,OAAI,OAAO,CAAC,IAAI,MAAM,IAAI,IAAI,MAAM,QAAQ,GAAG,EAAE;AACxE;AAAA,MAEF,KAAK;AAEH,gBAAQ,MAAM,QAAQ,OAAO;AAC7B;AAAA,MAEF,KAAK;AAEH,cAAM,QAAQ,QAAQ;AAEtB,YAAI;AACJ,YAAI,MAAM,aAAa,YAAY;AACjC,uBAAgB;AAAA,QAClB,WAAW,MAAM,aAAa,WAAW;AACvC,uBAAgB;AAAA,QAClB,OAAO;AACL,uBAAgB;AAAA,QAClB;AACA,cAAM,YAAY,MAAM,aAAa,aAAa,UACjC,MAAM,aAAa,YAAY,QAAQ;AACxD,gBAAQ,MAAM,EAAE;AAChB,gBAAQ,MAAM,WAAW,SAAI,OAAO,EAAE,CAAC,CAAC;AACxC,gBAAQ,MAAM,WAAW,GAAG,SAAS,oBAAoB,CAAC;AAC1D,gBAAQ,MAAM,WAAW,SAAI,OAAO,EAAE,CAAC,CAAC;AACxC,gBAAQ,MAAM,EAAE;AAChB,gBAAQ,MAAM,MAAS,QAAK,MAAM,OAAO,CAAC,EAAE;AAC5C,YAAI,MAAM,MAAM;AACd,kBAAQ,MAAM,MAAS,OAAI,OAAO,CAAC,IAAI,MAAM,IAAI,EAAE;AAAA,QACrD;AACA,gBAAQ,MAAM,EAAE;AAChB,gBAAQ,MAAM,WAAW,SAAI,OAAO,EAAE,CAAC,CAAC;AACxC,gBAAQ,MAAM,EAAE;AAChB;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,SAA8B;AACpD,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,cAAM,SAAS,QAAQ;AACvB,aAAK,eAAe,KAAK,MAAM,OAAO,KAAK;AAAA,CAAI;AAC/C,YAAI,OAAO,OAAO;AAChB,eAAK,eAAe,KAAK,KAAK,OAAO,KAAK;AAAA,CAAI;AAAA,QAChD;AACA;AAAA,MAEF,KAAK;AACH,cAAM,UAAU,QAAQ;AACxB,aAAK,eAAe,KAAK;AAAA,cAAiB,QAAQ,IAAI;AAAA,CAAM;AAC5D,aAAK,eAAe,KAAK,OAAO;AAChC,iBAAS,IAAI,GAAG,IAAI,QAAQ,MAAM,QAAQ,KAAK;AAC7C,gBAAM,UAAU,QAAQ,YAAY;AACpC,gBAAM,SAAS,YAAY,QAAQ,gBAAgB,WAAM;AACzD,eAAK,eAAe,KAAK,GAAG,MAAM,IAAI,QAAQ,SAAS,EAAE,SAAS,CAAC,CAAC,MAAM,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAAA,QAChG;AACA,aAAK,eAAe,KAAK,OAAO;AAChC;AAAA,MAEF,KAAK;AACH,cAAM,OAAO,QAAQ;AACrB,aAAK,eAAe,KAAK;AAAA;AAAA,CAAuB;AAChD,aAAK,eAAe,KAAK,cAAc,KAAK,eAAe,KAAK,UAAU,CAAC;AAAA,CAAI;AAC/E,aAAK,eAAe,KAAK,oBAAoB,KAAK,eAAe,KAAK,cAAc,CAAC;AAAA,CAAI;AACzF,aAAK,eAAe,KAAK,cAAc,KAAK,eAAe,KAAK,OAAO,CAAC;AAAA,CAAI;AAC5E;AAAA,MAEF,KAAK;AACH,cAAM,YAAY,QAAQ;AAC1B,aAAK,eAAe,KAAK;AAAA;AAAA,CAA8B;AACvD,aAAK,eAAe,KAAK,YAAY,UAAU,KAAK;AAAA,CAAQ;AAC5D,aAAK,eAAe,KAAK,mBAAmB,UAAU,eAAe,IAAI,UAAU,KAAK;AAAA,CAAI;AAC5F,aAAK,eAAe,KAAK,eAAe,UAAU,OAAO,YAAY,CAAC;AAAA,CAAM;AAC5E;AAAA,MAEF,KAAK;AACH,cAAM,WAAW,QAAQ;AACzB,aAAK,eAAe,KAAK;AAAA;AAAA,CAA2B;AACpD,YAAI,SAAS,iBAAiB,GAAG;AAC/B,eAAK,eAAe,KAAK,gBAAgB,SAAS,cAAc;AAAA,CAA8B;AAAA,QAChG;AACA,YAAI,SAAS,iBAAiB,GAAG;AAC/B,eAAK,eAAe,KAAK,YAAY,SAAS,cAAc;AAAA,CAAoB;AAAA,QAClF;AACA,YAAI,SAAS,aAAa,GAAG;AAC3B,eAAK,eAAe,KAAK,gBAAgB,SAAS,UAAU;AAAA,CAA0B;AAAA,QACxF;AACA;AAAA,MAEF,KAAK;AACH,cAAM,SAAS,QAAQ;AACvB,aAAK,eAAe,KAAK;AAAA;AAAA,CAAwB;AACjD,aAAK,eAAe,KAAK,gBAAgB,OAAO,cAAc;AAAA,CAAI;AAClE,aAAK,eAAe,KAAK,kBAAkB,OAAO,WAAW;AAAA,CAAI;AACjE,aAAK,eAAe,KAAK,iBAAiB,OAAO,SAAS;AAAA,CAAQ;AAClE;AAAA,MAEF,KAAK;AACH,aAAK,eAAe,KAAK,QAAQ,OAAO;AACxC;AAAA,MAEF;AAEE,aAAK,WAAW,KAAK,OAAO;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,SAA8B;AAChD,SAAK,WAAW,KAAK,OAAO;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,SAA8B;AAClD,UAAM,OAAO,KAAK,WAAW,QAAQ,SAAS;AAC9C,UAAM,QAAQ,QAAQ,UAAU,YAAY,QAAQ;AACpD,QAAI,UAAU;AAEd,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,kBAAU,YAAa,QAAQ,QAA0B,KAAK;AAC9D;AAAA,MACF,KAAK;AAAA,MACL,KAAK;AACH,kBAAU,QAAQ;AAClB;AAAA,MACF,KAAK;AACH,cAAM,QAAQ,QAAQ;AACtB,kBAAU,IAAI,MAAM,SAAS,YAAY,CAAC,KAAK,MAAM,KAAK;AAC1D;AAAA,MACF;AACE,kBAAU,IAAI,QAAQ,KAAK,YAAY,CAAC;AAAA,IAC5C;AAEA,SAAK,aAAa,KAAK,EAAE,MAAM,OAAO,QAAQ,CAAC;AAG/C,QAAI,KAAK,aAAa,SAAS,KAAK;AAClC,WAAK,eAAe,KAAK,aAAa,MAAM,IAAI;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqE;AACnE,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAsB;AACpB,WAAO,KAAK,eAAe,KAAK,IAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,UAA2B;AACzB,WAAO,CAAC,GAAG,KAAK,UAAU;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,SAAK,iBAAiB,CAAC;AACvB,SAAK,aAAa,CAAC;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,OAAe,KAAa,SAAsD;AACvF,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,OAAO,KAAK,OAAO,SAAS,OAAO,SAAS,SAAS,QAAQ;AAAA,MACxE,UAAU,EAAE,OAAO,MAAM;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAAc,OAAiB,WAAmB,eAA8B;AACtF,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,MAAM,OAAO,WAAW,cAAc;AAAA,MACjD,UAAU,EAAE,KAAK;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,YAAoB,gBAAwB,SAAiB,UAAyD;AACzH,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,YAAY,gBAAgB,SAAS,SAAS;AAAA,IAC3D,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,UACE,OACA,iBACA,OACA,QACA,cACM;AACN,UAAM,UAA4B,EAAE,OAAO,iBAAiB,OAAO,OAAO;AAC1E,QAAI,cAAc;AAChB,cAAQ,eAAe;AAAA,IACzB;AACA,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,gBAAwB,gBAAwB,YAA0B;AACjF,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,gBAAgB,gBAAgB,WAAW;AAAA,IACxD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,gBAAwB,aAAqB,WAAyB;AAC3E,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,gBAAgB,aAAa,UAAU;AAAA,IACpD,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,SAAuB;AAC9B,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,OAA4C,SAAuB;AACrE,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU,EAAE,UAAU,MAAa;AAAA,IACrC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,SAAuB;AAC1B,SAAK,IAAI,QAAQ,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,SAAuB;AAC1B,SAAK,IAAI,QAAQ,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAuB;AAC3B,SAAK,IAAI,SAAS,OAAO;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAuB;AAC3B,SAAK,IAAI,SAAS,OAAO;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAoB;AACxB,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU,EAAE,UAAU,MAAM,UAAU,OAAO,MAAM,OAAO,MAAM,MAAM,KAAK;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,SAAuB;AAC5B,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAiB,WAA4C,WAAW,MAAe,YAA2B;AACtH,UAAM,WAAsG,CAAC;AAE7G,QAAI,aAAa,WAAY,UAAS,WAAW;AAAA,aACxC,aAAa,UAAW,UAAS,WAAW;AAAA,QAChD,UAAS,WAAW;AACzB,QAAI,SAAS,OAAW,UAAS,OAAO;AACxC,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,SAAS,EAAE,SAAS,UAAU,MAAM,WAAW;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,QAAwB;AAC7C,QAAI,UAAU,IAAS,QAAO,KAAK,SAAS,KAAS,QAAQ,CAAC,CAAC;AAC/D,QAAI,UAAU,IAAM,QAAO,KAAK,SAAS,KAAM,QAAQ,CAAC,CAAC;AACzD,WAAO,IAAI,MAAM;AAAA,EACnB;AAAA,EAEQ,WAAW,WAA4B;AAC7C,UAAM,OAAO,YAAY,IAAI,KAAK,SAAS,IAAI,oBAAI,KAAK;AACxD,WAAO,KAAK,mBAAmB,SAAS,EAAE,QAAQ,OAAO,MAAM,WAAW,QAAQ,WAAW,QAAQ,UAAU,CAAC;AAAA,EAClH;AACF;AAGA,IAAI,WAAqC;AAKlC,SAAS,mBAAsC;AACpD,MAAI,CAAC,UAAU;AACb,eAAW,IAAI,kBAAkB;AAGjC,QAAI,kBAAkB,GAAG;AACvB,eAAS,QAAQ,KAAK;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAKO,SAAS,SAA4B;AAC1C,SAAO,iBAAiB;AAC1B;AAKO,SAAS,qBAA2B;AACzC,aAAW;AACb;","names":[]}
|
|
@@ -247,7 +247,7 @@ function getDefaultState() {
|
|
|
247
247
|
return {
|
|
248
248
|
lastScan: null,
|
|
249
249
|
activePriorities: [
|
|
250
|
-
"Initial setup required - run
|
|
250
|
+
"Initial setup required - run `trie watch` to start monitoring",
|
|
251
251
|
"Configure agents in `.trie/config.json`",
|
|
252
252
|
"Set up CI/CD integration"
|
|
253
253
|
],
|
|
@@ -824,7 +824,7 @@ function getBootstrapTemplate(stack) {
|
|
|
824
824
|
lines.push(skillCommands || "# No specific skills detected - browse https://skills.sh");
|
|
825
825
|
lines.push("```", "", "### 2. Agents to Enable", `Your stack suggests these agents: ${agentList || "security, bugs"}`, "");
|
|
826
826
|
lines.push("### 3. Configure Rules", "Add your coding standards to `.trie/RULES.md`.", "");
|
|
827
|
-
lines.push("### 4.
|
|
827
|
+
lines.push("### 4. Start Monitoring", "```bash", "trie watch", "```", "");
|
|
828
828
|
lines.push("---", "", "**Delete this file after completing setup.** Run:", "```bash", "rm .trie/BOOTSTRAP.md", "```");
|
|
829
829
|
return lines.join("\n");
|
|
830
830
|
}
|
|
@@ -847,4 +847,4 @@ export {
|
|
|
847
847
|
loadContextState,
|
|
848
848
|
getContextForAI
|
|
849
849
|
};
|
|
850
|
-
//# sourceMappingURL=chunk-
|
|
850
|
+
//# sourceMappingURL=chunk-HVCDY3AK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/project-info.ts","../src/utils/context-state.ts","../src/bootstrap/files.ts","../src/bootstrap/stack-detector.ts"],"sourcesContent":["/**\n * Project Info Manager\n * \n * Manages the .trie/PROJECT.md file that stores user-defined project context.\n * Unlike AGENTS.md (auto-generated), PROJECT.md is fully user-controlled.\n */\n\nimport { readFile, writeFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\n\nconst PROJECT_MD_PATH = 'PROJECT.md';\n\n/**\n * Default PROJECT.md template\n */\nexport function getProjectTemplate(): string {\n return `# Project Information\n\n> This file stores important project context for AI assistants.\n> Edit freely - this file is yours, not auto-generated.\n> Available via MCP resource: \\`trie://project\\`\n\n---\n\n## Project Overview\n\n<!-- Describe your project's purpose and goals -->\n\n[Add project description here]\n\n---\n\n## Technology Stack\n\n<!-- List frameworks, languages, databases, cloud services, etc. -->\n\n- **Language:** \n- **Framework:** \n- **Database:** \n- **Hosting:** \n\n---\n\n## Architecture\n\n<!-- Key patterns, architectural decisions, and system design -->\n\n[Describe your architecture here]\n\n---\n\n## Coding Conventions\n\n<!-- Style guidelines, naming conventions, patterns to follow -->\n\n- \n- \n- \n\n---\n\n## Environment\n\n<!-- URLs, API endpoints, deployment info -->\n\n| Environment | URL | Notes |\n|-------------|-----|-------|\n| Development | | |\n| Staging | | |\n| Production | | |\n\n---\n\n## Team\n\n<!-- Ownership, contacts, responsibilities -->\n\n- **Owner:** \n- **Team:** \n\n---\n\n## Compliance\n\n<!-- HIPAA, SOC2, GDPR, PCI-DSS requirements if applicable -->\n\n- [ ] GDPR\n- [ ] SOC2\n- [ ] HIPAA\n- [ ] PCI-DSS\n\n---\n\n## AI Instructions\n\n<!-- Special instructions for AI assistants working on this project -->\n\nWhen working on this project, AI assistants should:\n\n1. \n2. \n3. \n\n---\n\n*This file is read by Trie agents and exposed via \\`trie://project\\` MCP resource.*\n*Edit this file to provide context to Claude Code, Cursor, GitHub Actions, and other AI tools.*\n`;\n}\n\n/**\n * Check if PROJECT.md exists\n */\nexport function projectInfoExists(workDir?: string): boolean {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n return existsSync(projectPath);\n}\n\n/**\n * Load PROJECT.md content\n */\nexport async function loadProjectInfo(workDir?: string): Promise<string | null> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n \n try {\n if (!existsSync(projectPath)) {\n return null;\n }\n return await readFile(projectPath, 'utf-8');\n } catch {\n return null;\n }\n}\n\n/**\n * Save PROJECT.md content\n */\nexport async function saveProjectInfo(content: string, workDir?: string): Promise<void> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(dir);\n const projectPath = join(trieDir, PROJECT_MD_PATH);\n \n // Ensure .trie directory exists\n await mkdir(trieDir, { recursive: true });\n \n await writeFile(projectPath, content, 'utf-8');\n}\n\n/**\n * Initialize PROJECT.md with template\n */\nexport async function initProjectInfo(workDir?: string): Promise<{ created: boolean; path: string }> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n \n if (existsSync(projectPath)) {\n return { created: false, path: projectPath };\n }\n \n await saveProjectInfo(getProjectTemplate(), dir);\n return { created: true, path: projectPath };\n}\n\n/**\n * Get a specific section from PROJECT.md\n */\nexport async function getProjectSection(sectionName: string, workDir?: string): Promise<string | null> {\n const content = await loadProjectInfo(workDir);\n if (!content) return null;\n \n // Find section by header\n const sectionRegex = new RegExp(\n `## ${escapeRegex(sectionName)}\\\\s*\\\\n([\\\\s\\\\S]*?)(?=\\\\n## |\\\\n---\\\\s*$|$)`,\n 'i'\n );\n \n const match = content.match(sectionRegex);\n if (match?.[1]) {\n return match[1].trim();\n }\n \n return null;\n}\n\n/**\n * Update a specific section in PROJECT.md\n */\nexport async function updateProjectSection(\n sectionName: string, \n newContent: string, \n workDir?: string\n): Promise<boolean> {\n let content = await loadProjectInfo(workDir);\n \n if (!content) {\n // Initialize with template first\n await initProjectInfo(workDir);\n content = await loadProjectInfo(workDir);\n if (!content) return false;\n }\n \n // Find and replace section content\n const sectionRegex = new RegExp(\n `(## ${escapeRegex(sectionName)}\\\\s*\\\\n)([\\\\s\\\\S]*?)((?=\\\\n## )|(?=\\\\n---\\\\s*$)|$)`,\n 'i'\n );\n \n if (content.match(sectionRegex)) {\n const updatedContent = content.replace(sectionRegex, `$1\\n${newContent}\\n\\n$3`);\n await saveProjectInfo(updatedContent, workDir);\n return true;\n }\n \n return false;\n}\n\n/**\n * Append content to a section\n */\nexport async function appendToSection(\n sectionName: string,\n contentToAdd: string,\n workDir?: string\n): Promise<boolean> {\n const currentContent = await getProjectSection(sectionName, workDir);\n if (currentContent === null) return false;\n \n const newContent = currentContent + '\\n' + contentToAdd;\n return updateProjectSection(sectionName, newContent, workDir);\n}\n\n/**\n * Get all section names from PROJECT.md\n */\nexport async function getProjectSections(workDir?: string): Promise<string[]> {\n const content = await loadProjectInfo(workDir);\n if (!content) return [];\n \n const sectionRegex = /^## (.+)$/gm;\n const sections: string[] = [];\n let match;\n \n while ((match = sectionRegex.exec(content)) !== null) {\n if (match[1]) {\n sections.push(match[1].trim());\n }\n }\n \n return sections;\n}\n\n/**\n * Get project info as structured data (for JSON responses)\n */\nexport async function getProjectInfoStructured(workDir?: string): Promise<{\n exists: boolean;\n path: string;\n sections: Record<string, string>;\n raw: string | null;\n}> {\n const dir = workDir || getWorkingDirectory(undefined, true);\n const projectPath = join(getTrieDirectory(dir), PROJECT_MD_PATH);\n const content = await loadProjectInfo(dir);\n \n if (!content) {\n return {\n exists: false,\n path: projectPath,\n sections: {},\n raw: null,\n };\n }\n \n const sectionNames = await getProjectSections(dir);\n const sections: Record<string, string> = {};\n \n for (const name of sectionNames) {\n const sectionContent = await getProjectSection(name, dir);\n if (sectionContent) {\n sections[name] = sectionContent;\n }\n }\n \n return {\n exists: true,\n path: projectPath,\n sections,\n raw: content,\n };\n}\n\n/**\n * Escape special regex characters\n */\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/**\n * Context State Manager\n * \n * Manages the .trie/AGENTS.md file that provides context to AI coding assistants.\n * Updates automatically when agents run to keep context current.\n * Also integrates with issue memory and cross-project tracking.\n * \n * Phase 1 Hardening:\n * - Atomic writes to prevent corruption\n */\n\nimport { readFile, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join, basename } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from './workspace.js';\nimport type { AgentResult } from '../types/index.js';\nimport type { SkillRecord } from '../types/external-skill.js';\nimport { loadProjectInfo, projectInfoExists } from './project-info.js';\nimport { storeIssues, autoResolveIssues, getIssueHash } from '../memory/issue-store.js';\nimport { recordToGlobalMemory, updateGlobalMemoryMd } from '../memory/global-memory.js';\nimport { atomicWriteJSON, atomicWriteFile } from './atomic-write.js';\n\nexport interface ScanSummary {\n timestamp: string;\n agents: string[];\n filesScanned: number;\n issues: {\n critical: number;\n serious: number;\n moderate: number;\n low: number;\n total: number;\n };\n duration: number;\n hotFiles: Array<{ file: string; issueCount: number }>;\n}\n\nexport interface ContextState {\n lastScan: ScanSummary | null;\n activePriorities: string[];\n contextSignals: Record<string, boolean>;\n agentStatus: Record<string, {\n lastRun: string | null;\n issuesFound: number;\n skillsApplied?: string[];\n }>;\n scanHistory: ScanSummary[];\n customAgents: string[];\n skills: Record<string, SkillRecord>;\n environment?: string;\n}\n\nconst AGENTS_MD_PATH = 'AGENTS.md';\nconst STATE_JSON_PATH = 'state.json';\n\n/**\n * Load current context state\n */\nexport async function loadContextState(): Promise<ContextState> {\n const workDir = getWorkingDirectory(undefined, true);\n const statePath = join(getTrieDirectory(workDir), STATE_JSON_PATH);\n const defaults = getDefaultState();\n \n try {\n if (existsSync(statePath)) {\n const content = await readFile(statePath, 'utf-8');\n const loaded = JSON.parse(content);\n const { healthScore: _dropped, ...loadedRest } = loaded;\n // Merge with defaults to ensure new fields exist (omit legacy healthScore)\n return {\n ...defaults,\n ...loadedRest,\n skills: loaded.skills || defaults.skills,\n };\n }\n } catch {\n // Return default state\n }\n \n return defaults;\n}\n\n/**\n * Save context state using atomic write\n */\nexport async function saveContextState(state: ContextState): Promise<void> {\n const workDir = getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(workDir);\n const statePath = join(trieDir, STATE_JSON_PATH);\n \n // Ensure directory exists\n await mkdir(trieDir, { recursive: true });\n \n // Use atomic write to prevent corruption\n await atomicWriteJSON(statePath, state);\n}\n\n/**\n * Update context state after a scan\n */\nexport async function updateContextAfterScan(\n results: AgentResult[],\n filesScanned: number,\n contextSignals: Record<string, boolean>,\n duration: number,\n scannedFiles?: string[]\n): Promise<void> {\n const state = await loadContextState();\n const workDir = getWorkingDirectory(undefined, true);\n const now = new Date().toISOString();\n \n // Calculate issue counts\n const allIssues = results.flatMap(r => r.issues);\n const issueCounts = {\n critical: allIssues.filter(i => i.severity === 'critical').length,\n serious: allIssues.filter(i => i.severity === 'serious').length,\n moderate: allIssues.filter(i => i.severity === 'moderate').length,\n low: allIssues.filter(i => i.severity === 'low').length,\n total: allIssues.length,\n };\n \n // Find hot files\n const fileIssueMap = new Map<string, number>();\n for (const issue of allIssues) {\n const count = fileIssueMap.get(issue.file) || 0;\n fileIssueMap.set(issue.file, count + 1);\n }\n const hotFiles = Array.from(fileIssueMap.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, 10)\n .map(([file, issueCount]) => ({ file, issueCount }));\n \n // Create scan summary\n const scanSummary: ScanSummary = {\n timestamp: now,\n agents: results.map(r => r.agent),\n filesScanned,\n issues: issueCounts,\n duration,\n hotFiles,\n };\n \n // Update agent status\n for (const result of results) {\n state.agentStatus[result.agent] = {\n lastRun: now,\n issuesFound: result.issues.length,\n };\n }\n \n // Update priorities based on issues\n state.activePriorities = generatePriorities(issueCounts, contextSignals);\n \n // Update context signals\n state.contextSignals = { ...state.contextSignals, ...contextSignals };\n \n // Update scan history (keep last 20)\n state.scanHistory = [scanSummary, ...state.scanHistory.slice(0, 19)];\n state.lastScan = scanSummary;\n \n // Save state\n await saveContextState(state);\n \n // Update AGENTS.md\n await updateAgentsMd(state);\n \n // Store issues to memory\n const projectName = basename(workDir);\n if (allIssues.length > 0) {\n try {\n await storeIssues(allIssues, projectName, workDir);\n await recordToGlobalMemory(allIssues, projectName, workDir);\n await updateGlobalMemoryMd();\n } catch {\n // Memory storage is non-critical, don't fail the scan\n }\n }\n \n // Auto-resolve issues that are no longer detected in scanned files\n if (scannedFiles && scannedFiles.length > 0) {\n try {\n // Build set of hashes from current scan\n const currentHashes = new Set(allIssues.map(issue => getIssueHash(issue)));\n const { resolved } = await autoResolveIssues(currentHashes, scannedFiles, workDir);\n if (resolved > 0) {\n // Log auto-resolution in non-interactive mode\n const { isInteractiveMode } = await import('./progress.js');\n if (!isInteractiveMode()) {\n console.error(` ✓ Auto-resolved ${resolved} issue${resolved > 1 ? 's' : ''} no longer detected`);\n }\n }\n } catch {\n // Auto-resolution is non-critical\n }\n }\n}\n\n/**\n * Update the AGENTS.md file with current state\n */\nasync function updateAgentsMd(state: ContextState): Promise<void> {\n const workDir = getWorkingDirectory(undefined, true);\n const mdPath = join(getTrieDirectory(workDir), AGENTS_MD_PATH);\n \n let content: string;\n try {\n content = await readFile(mdPath, 'utf-8');\n } catch {\n // Use template if file doesn't exist\n content = getAgentsMdTemplate();\n }\n \n // Update sections\n content = updateSection(content, 'Project State', generateProjectStateTable(state));\n content = updateSection(content, 'Active Priorities', generatePrioritiesList(state));\n content = updateSection(content, 'Agent Status', generateAgentStatusTable(state));\n content = updateSection(content, 'Recent Scan History', generateScanHistoryTable(state));\n content = updateSection(content, 'Context Signals Detected', generateContextSignals(state));\n content = updateSection(content, 'Risk Assessment', generateRiskAssessment(state));\n content = updateSection(content, 'Hot Files', generateHotFilesSection(state));\n \n // Update last updated timestamp\n content = content.replace(\n /Last updated:.*$/m,\n `Last updated: ${new Date().toISOString()}`\n );\n \n // Use atomic write to prevent corruption\n await atomicWriteFile(mdPath, content);\n}\n\n/**\n * Update a specific section in the markdown\n */\nfunction updateSection(content: string, sectionName: string, newContent: string): string {\n // Look for the section header and replace content until the next section\n const sectionRegex = new RegExp(\n `(### ${sectionName}[\\\\s\\\\S]*?)(?=###|---|\\n## |$)`,\n 'g'\n );\n \n const replacement = `### ${sectionName}\\n${newContent}\\n\\n`;\n \n if (content.match(sectionRegex)) {\n return content.replace(sectionRegex, replacement);\n }\n \n // Section doesn't exist, don't add it\n return content;\n}\n\n/**\n * Generate the project state table\n */\nfunction generateProjectStateTable(state: ContextState): string {\n const lastScan = state.lastScan;\n const lastScanDate = lastScan ? new Date(lastScan.timestamp).toLocaleString() : 'Never';\n const criticalCount = lastScan?.issues.critical ?? 0;\n const totalTasks = lastScan?.issues.total ?? 0;\n \n return `| Metric | Value | Updated |\n|--------|-------|---------|\n| Last Scan | ${lastScanDate} | ${lastScan ? 'Auto' : '-'} |\n| Critical Issues | ${criticalCount} | ${lastScan ? 'Auto' : '-'} |\n| Open Tasks | ${totalTasks} | ${lastScan ? 'Auto' : '-'} |`;\n}\n\n/**\n * Generate priorities list\n */\nfunction generatePrioritiesList(state: ContextState): string {\n if (state.activePriorities.length === 0) {\n return '_No active priorities. Run a scan to identify issues._';\n }\n \n return state.activePriorities\n .map((p, i) => `${i + 1}. ${p}`)\n .join('\\n');\n}\n\n/**\n * Generate priorities based on scan results\n */\nfunction generatePriorities(\n issues: { critical: number; serious: number; moderate: number; low: number },\n contextSignals: Record<string, boolean>\n): string[] {\n const priorities: string[] = [];\n \n if (issues.critical > 0) {\n priorities.push(`Fix ${issues.critical} critical security issue${issues.critical > 1 ? 's' : ''} immediately`);\n }\n \n if (issues.serious > 0) {\n priorities.push(`Address ${issues.serious} serious issue${issues.serious > 1 ? 's' : ''} before deployment`);\n }\n \n if (contextSignals.touchesAuth && issues.critical === 0) {\n priorities.push('Auth code reviewed - continue monitoring');\n }\n \n if (contextSignals.touchesPayments) {\n priorities.push('💳 Payment code detected - ensure PCI compliance');\n }\n \n if (issues.moderate > 5) {\n priorities.push(`Schedule time to address ${issues.moderate} moderate issues`);\n }\n \n if (priorities.length === 0) {\n priorities.push('No critical issues - focus on feature development');\n }\n \n return priorities.slice(0, 5);\n}\n\n/**\n * Generate agent status table\n */\nfunction generateAgentStatusTable(state: ContextState): string {\n const builtInAgents = [\n 'security', 'legal', 'accessibility', 'bugs',\n 'design', 'architecture', 'performance', 'devops', 'soc2',\n 'e2e', 'typecheck', 'visual-qa', 'data-flow'\n ];\n \n let table = `| Agent | Status | Last Run | Issues Found |\n|-------|--------|----------|--------------|`;\n \n for (const agent of builtInAgents) {\n const status = state.agentStatus[agent];\n const lastRun = status?.lastRun \n ? new Date(status.lastRun).toLocaleDateString()\n : 'Never';\n const issues = status?.issuesFound ?? '-';\n const statusEmoji = status ? '✅' : '⏸️';\n \n table += `\\n| ${agent} | ${statusEmoji} Ready | ${lastRun} | ${issues} |`;\n }\n \n return table;\n}\n\n/**\n * Generate scan history table\n */\nfunction generateScanHistoryTable(state: ContextState): string {\n if (state.scanHistory.length === 0) {\n return `| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|\n| - | - | - | - | - |`;\n }\n \n let table = `| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|`;\n \n for (const scan of state.scanHistory.slice(0, 10)) {\n const date = new Date(scan.timestamp).toLocaleDateString();\n const agents = scan.agents.slice(0, 3).join(', ') + (scan.agents.length > 3 ? '...' : '');\n const duration = `${(scan.duration / 1000).toFixed(1)}s`;\n \n table += `\\n| ${date} | ${agents} | ${scan.filesScanned} | ${scan.issues.total} | ${duration} |`;\n }\n \n return table;\n}\n\n/**\n * Generate context signals section\n */\nfunction generateContextSignals(state: ContextState): string {\n const signals = [\n 'touchesAuth',\n 'touchesPayments', \n 'touchesUserData',\n 'touchesAPI',\n 'touchesDatabase',\n 'touchesCrypto'\n ];\n \n return signals\n .map(s => {\n const value = state.contextSignals[s];\n const emoji = value === true ? '✅' : value === false ? '❌' : '❓';\n return `- \\`${s}\\`: ${emoji} ${value === undefined ? 'Unknown' : value ? 'Yes' : 'No'}`;\n })\n .join('\\n');\n}\n\n/**\n * Generate risk assessment section\n */\nfunction generateRiskAssessment(state: ContextState): string {\n if (state.lastScan === null) {\n return `- Overall Risk: Unknown\n- Confidence: 0%`;\n }\n\n const { critical, serious, total } = state.lastScan.issues;\n let riskLevel: string;\n let confidence: number;\n\n if (critical > 0) {\n riskLevel = '🔴 Critical';\n confidence = 90;\n } else if (serious > 2 || total > 20) {\n riskLevel = '🟠 High';\n confidence = 80;\n } else if (serious > 0 || total > 10) {\n riskLevel = '🟡 Medium';\n confidence = 85;\n } else {\n riskLevel = '🟢 Low';\n confidence = 95;\n }\n\n return `- Overall Risk: ${riskLevel}\n- Confidence: ${confidence}%`;\n}\n\n/**\n * Generate hot files section\n */\nfunction generateHotFilesSection(state: ContextState): string {\n if (!state.lastScan || state.lastScan.hotFiles.length === 0) {\n return '_Run a scan to identify hot files._';\n }\n \n return state.lastScan.hotFiles\n .map(f => `- \\`${f.file}\\` - ${f.issueCount} issue${f.issueCount > 1 ? 's' : ''}`)\n .join('\\n');\n}\n\n/**\n * Get default state\n */\nfunction getDefaultState(): ContextState {\n return {\n lastScan: null,\n activePriorities: [\n 'Initial setup required - run `trie watch` to start monitoring',\n 'Configure agents in `.trie/config.json`',\n 'Set up CI/CD integration'\n ],\n contextSignals: {},\n agentStatus: {},\n scanHistory: [],\n customAgents: [],\n skills: {},\n environment: detectEnvironment(),\n };\n}\n\n/**\n * Detect the current execution environment\n */\nexport function detectEnvironment(): string {\n if (process.env.GITHUB_ACTIONS) return 'github-actions';\n if (process.env.GITLAB_CI) return 'gitlab-ci';\n if (process.env.CI) return 'ci';\n const parent = process.env._ || '';\n if (parent.includes('cursor')) return 'cursor';\n if (parent.includes('claude')) return 'claude-code';\n return 'cli';\n}\n\n/**\n * Record skill installation in context state\n */\nexport async function recordSkillInstalled(params: {\n name: string;\n source: string;\n}): Promise<void> {\n const state = await loadContextState();\n state.skills[params.name] = {\n source: params.source,\n installedAt: new Date().toISOString(),\n timesApplied: 0,\n appliedBy: [],\n };\n await saveContextState(state);\n}\n\n/**\n * Record skill usage by an agent\n */\nexport async function recordSkillUsage(params: {\n skillNames: string[];\n agentName: string;\n}): Promise<void> {\n const state = await loadContextState();\n const now = new Date().toISOString();\n \n for (const skillName of params.skillNames) {\n const skillRecord = state.skills[skillName];\n if (skillRecord) {\n skillRecord.timesApplied++;\n skillRecord.lastApplied = now;\n if (!skillRecord.appliedBy.includes(params.agentName)) {\n skillRecord.appliedBy.push(params.agentName);\n }\n }\n }\n \n const agentStatus = state.agentStatus[params.agentName];\n if (agentStatus) {\n agentStatus.skillsApplied = params.skillNames;\n }\n \n await saveContextState(state);\n}\n\n/**\n * Get the AGENTS.md template\n */\nfunction getAgentsMdTemplate(): string {\n return `# Trie Agent Context\n\n> **Auto-generated file** - Updated automatically when agents run.\n> Last updated: Never (initial state)\n\nThis file provides prioritized context for all AI coding assistants working with this codebase.\nAgents should read this file first and update it after completing scans.\n\n---\n\n## Quick Context (Read First)\n\n### Project State\n| Metric | Value | Updated |\n|--------|-------|---------|\n| Last Scan | Never | - |\n| Critical Issues | 0 | - |\n| Open Tasks | 0 | - |\n| Health Score | Unknown | - |\n\n### Active Priorities\n1. Initial setup required - run \\`trie watch\\` to start monitoring\n2. Configure agents in \\`.trie/config.json\\`\n3. Set up CI/CD integration\n\n### Hot Files\n_Run a scan to identify hot files._\n\n---\n\n## Agent Status\n\n### Agent Status\n| Agent | Status | Last Run | Issues Found |\n|-------|--------|----------|--------------|\n| security | Ready | Never | - |\n| bugs | Ready | Never | - |\n\n### Recent Scan History\n| Date | Agents | Files | Issues | Duration |\n|------|--------|-------|--------|----------|\n| - | - | - | - | - |\n\n---\n\n## Context Analysis\n\n### Context Signals Detected\n- \\`touchesAuth\\`: Unknown\n- \\`touchesPayments\\`: Unknown\n- \\`touchesUserData\\`: Unknown\n- \\`touchesAPI\\`: Unknown\n- \\`touchesDatabase\\`: Unknown\n- \\`touchesCrypto\\`: Unknown\n\n### Risk Assessment\n- Overall Risk: Unknown\n- Confidence: 0%\n\n---\n\n*This file is maintained by Trie agents. Manual edits will be preserved in non-auto sections.*\n`;\n}\n\n/**\n * Add custom skill to context state\n */\nexport async function addCustomAgentToContext(agentName: string): Promise<void> {\n const state = await loadContextState();\n \n if (!state.customAgents.includes(agentName)) {\n state.customAgents.push(agentName);\n await saveContextState(state);\n }\n}\n\n/**\n * Get context state for AI assistants (formatted summary)\n */\nexport async function getContextForAI(): Promise<string> {\n const state = await loadContextState();\n const workDir = getWorkingDirectory(undefined, true);\n \n const lines: string[] = [];\n \n // Include PROJECT.md content first (user-defined context takes priority)\n if (projectInfoExists(workDir)) {\n const projectInfo = await loadProjectInfo(workDir);\n if (projectInfo) {\n lines.push(projectInfo);\n lines.push('');\n lines.push('---');\n lines.push('');\n }\n }\n \n // Add Trie scan context\n lines.push(\n '## Trie Scan Context',\n '',\n `**Last Scan:** ${state.lastScan ? new Date(state.lastScan.timestamp).toLocaleString() : 'Never'}`,\n '',\n '**Active Priorities:**',\n ...state.activePriorities.map(p => `- ${p}`),\n ''\n );\n \n if (state.lastScan) {\n lines.push(\n '**Recent Issues:**',\n `- Critical: ${state.lastScan.issues.critical}`,\n `- Serious: ${state.lastScan.issues.serious}`,\n `- Moderate: ${state.lastScan.issues.moderate}`,\n `- Low: ${state.lastScan.issues.low}`,\n ''\n );\n \n if (state.lastScan.hotFiles.length > 0) {\n lines.push(\n '**Hot Files (most issues):**',\n ...state.lastScan.hotFiles.slice(0, 5).map(f => `- ${f.file}: ${f.issueCount} issues`),\n ''\n );\n }\n }\n \n return lines.join('\\n');\n}\n","/**\n * Bootstrap File System\n * \n * Manages workspace files that inject context at scan start.\n * Files: BOOTSTRAP.md, RULES.md, TEAM.md\n */\n\nimport { readFile, writeFile, unlink, mkdir } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { getWorkingDirectory, getTrieDirectory } from '../utils/workspace.js';\nimport { detectStack, type DetectedStack } from './stack-detector.js';\n\nexport interface BootstrapFile {\n name: string;\n path: string;\n type: 'user' | 'auto' | 'one-time';\n exists: boolean;\n content?: string;\n}\n\nexport interface BootstrapContext {\n files: BootstrapFile[];\n injectedContent: string;\n needsBootstrap: boolean;\n}\n\ninterface BootstrapFileSpec {\n name: string;\n type: 'user' | 'auto' | 'one-time';\n description: string;\n}\n\nconst BOOTSTRAP_FILES: BootstrapFileSpec[] = [\n { name: 'PROJECT.md', type: 'user', description: 'Project overview and conventions' },\n { name: 'RULES.md', type: 'user', description: 'Coding standards agents enforce' },\n { name: 'TEAM.md', type: 'user', description: 'Team ownership and escalation' },\n { name: 'BOOTSTRAP.md', type: 'one-time', description: 'First-run setup (deleted after)' },\n { name: 'AGENTS.md', type: 'auto', description: 'Auto-generated scan context' },\n];\n\n/**\n * Load bootstrap files and inject into agent context\n */\nexport async function loadBootstrapContext(workDir?: string): Promise<BootstrapContext> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(projectDir);\n const files: BootstrapFile[] = [];\n const contentParts: string[] = [];\n let needsBootstrap = false;\n\n for (const file of BOOTSTRAP_FILES) {\n const filePath = join(trieDir, file.name);\n const exists = existsSync(filePath);\n \n if (file.name === 'BOOTSTRAP.md' && exists) {\n needsBootstrap = true;\n }\n \n let content: string | undefined;\n if (exists) {\n try {\n content = await readFile(filePath, 'utf-8');\n if (content.trim() && file.type !== 'one-time') {\n contentParts.push(`<!-- ${file.name} -->\\n${content}`);\n }\n } catch {\n // Skip files that can't be read\n }\n }\n\n const fileEntry: BootstrapFile = {\n name: file.name,\n path: filePath,\n type: file.type,\n exists,\n };\n if (content) fileEntry.content = content;\n files.push(fileEntry);\n }\n\n return {\n files,\n injectedContent: contentParts.join('\\n\\n---\\n\\n'),\n needsBootstrap,\n };\n}\n\n/**\n * Initialize bootstrap files for a new project\n */\nexport async function initializeBootstrapFiles(options: {\n workDir?: string;\n force?: boolean;\n skipBootstrap?: boolean;\n} = {}): Promise<{ created: string[]; skipped: string[]; stack: DetectedStack }> {\n const projectDir = options.workDir || getWorkingDirectory(undefined, true);\n const trieDir = getTrieDirectory(projectDir);\n await mkdir(trieDir, { recursive: true });\n\n const created: string[] = [];\n const skipped: string[] = [];\n\n const stack = await detectStack(projectDir);\n\n for (const file of BOOTSTRAP_FILES) {\n const filePath = join(trieDir, file.name);\n const exists = existsSync(filePath);\n\n if (exists && !options.force) {\n skipped.push(file.name);\n continue;\n }\n\n if (file.name === 'BOOTSTRAP.md' && options.skipBootstrap) {\n skipped.push(file.name);\n continue;\n }\n\n if (file.name === 'AGENTS.md') {\n skipped.push(file.name);\n continue;\n }\n\n const template = getFileTemplate(file.name, stack);\n if (template) {\n await writeFile(filePath, template);\n created.push(file.name);\n }\n }\n\n return { created, skipped, stack };\n}\n\n/**\n * Mark bootstrap as complete (delete BOOTSTRAP.md)\n */\nexport async function completeBootstrap(workDir?: string): Promise<boolean> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const bootstrapPath = join(getTrieDirectory(projectDir), 'BOOTSTRAP.md');\n\n try {\n await unlink(bootstrapPath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if bootstrap is needed (BOOTSTRAP.md exists)\n */\nexport function needsBootstrap(workDir?: string): boolean {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const bootstrapPath = join(getTrieDirectory(projectDir), 'BOOTSTRAP.md');\n return existsSync(bootstrapPath);\n}\n\n/**\n * Get rules from RULES.md\n */\nexport async function loadRules(workDir?: string): Promise<string | null> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const rulesPath = join(getTrieDirectory(projectDir), 'RULES.md');\n \n try {\n if (existsSync(rulesPath)) {\n return await readFile(rulesPath, 'utf-8');\n }\n } catch {\n // Rules file doesn't exist or can't be read\n }\n \n return null;\n}\n\n/**\n * Get team info from TEAM.md\n */\nexport async function loadTeamInfo(workDir?: string): Promise<string | null> {\n const projectDir = workDir || getWorkingDirectory(undefined, true);\n const teamPath = join(getTrieDirectory(projectDir), 'TEAM.md');\n \n try {\n if (existsSync(teamPath)) {\n return await readFile(teamPath, 'utf-8');\n }\n } catch {\n // Team file doesn't exist or can't be read\n }\n \n return null;\n}\n\nfunction getFileTemplate(fileName: string, stack: DetectedStack): string | null {\n switch (fileName) {\n case 'PROJECT.md':\n return getProjectTemplate(stack);\n case 'RULES.md':\n return getRulesTemplate(stack);\n case 'TEAM.md':\n return getTeamTemplate();\n case 'BOOTSTRAP.md':\n return getBootstrapTemplate(stack);\n default:\n return null;\n }\n}\n\nfunction getProjectTemplate(stack: DetectedStack): string {\n const lines: string[] = ['# Project Overview', '', '> Define your project context here. AI assistants read this first.', ''];\n \n lines.push('## Description', '', '[Describe what this project does and who it\\'s for]', '');\n \n lines.push('## Technology Stack', '');\n if (stack.framework) lines.push(`- **Framework:** ${stack.framework}`);\n if (stack.language) lines.push(`- **Language:** ${stack.language}`);\n if (stack.database) lines.push(`- **Database:** ${stack.database}`);\n if (stack.auth) lines.push(`- **Auth:** ${stack.auth}`);\n if (!stack.framework && !stack.language && !stack.database) {\n lines.push('[Add your technology stack]');\n }\n lines.push('');\n \n lines.push('## Architecture', '', '[Key patterns and design decisions]', '');\n lines.push('## Coding Conventions', '', '[Style rules agents should follow]', '');\n lines.push('## AI Instructions', '', 'When working on this project:', '1. [Instruction 1]', '2. [Instruction 2]', '3. [Instruction 3]', '');\n lines.push('---', '', '*Edit this file to provide project context to AI assistants.*');\n \n return lines.join('\\n');\n}\n\nfunction getRulesTemplate(stack: DetectedStack): string {\n const packageManager = stack.packageManager || 'npm';\n \n return `# Project Rules\n\n> These rules are enforced by Trie agents during scans.\n> Violations appear as issues with [RULES] prefix.\n\n## Code Style\n\n1. Use named exports, not default exports\n2. Prefer \\`${packageManager}\\` for package management\n3. Maximum file length: 300 lines\n4. Use TypeScript strict mode\n\n## Testing Requirements\n\n1. Critical paths require unit tests\n2. API endpoints require integration tests\n3. Minimum coverage: 70%\n\n## Security Rules\n\n1. Never log sensitive data (passwords, tokens, PII)\n2. All API routes require authentication\n3. Rate limiting required on public endpoints\n4. SQL queries must use parameterized statements\n\n## Review Requirements\n\n1. All PRs require at least 1 reviewer\n2. Security-sensitive changes require security review\n3. Database migrations require review\n\n---\n\n*Edit this file to define your project's coding standards.*\n`;\n}\n\nfunction getTeamTemplate(): string {\n return `# Team Structure\n\n## Code Ownership\n\n| Area | Owner | Backup | Review Required |\n|------|-------|--------|-----------------|\n| \\`/src/api/\\` | @backend-team | - | 1 approver |\n| \\`/src/ui/\\` | @frontend-team | - | 1 approver |\n| \\`/src/auth/\\` | @security-team | - | Security review |\n\n## Escalation\n\n| Severity | First Contact | Escalate To | SLA |\n|----------|--------------|-------------|-----|\n| Critical | Team lead | CTO | 1 hour |\n| Serious | PR reviewer | Team lead | 4 hours |\n| Moderate | Self-serve | - | 1 day |\n\n## Contacts\n\n- **Security:** [email/slack]\n- **Privacy:** [email/slack]\n- **Emergencies:** [phone/pager]\n\n---\n\n*Edit this file to define your team structure.*\n`;\n}\n\nfunction getBootstrapTemplate(stack: DetectedStack): string {\n const skillCommands = stack.suggestedSkills\n .map(s => `trie skills add ${s}`)\n .join('\\n');\n\n const agentList = stack.suggestedAgents.join(', ');\n\n const lines: string[] = [\n '# Trie Bootstrap Checklist',\n '',\n 'This file guides your first scan setup. **Delete when complete.**',\n '',\n '## Auto-Detected Stack',\n '',\n 'Based on your project, Trie detected:',\n ];\n \n if (stack.framework) lines.push(`- **Framework:** ${stack.framework}`);\n if (stack.language) lines.push(`- **Language:** ${stack.language}`);\n if (stack.database) lines.push(`- **Database:** ${stack.database}`);\n if (stack.auth) lines.push(`- **Auth:** ${stack.auth}`);\n \n lines.push('', '## Recommended Actions', '', '### 1. Skills to Install', 'Based on your stack, consider installing:', '```bash');\n lines.push(skillCommands || '# No specific skills detected - browse https://skills.sh');\n lines.push('```', '', '### 2. Agents to Enable', `Your stack suggests these agents: ${agentList || 'security, bugs'}`, '');\n lines.push('### 3. Configure Rules', 'Add your coding standards to `.trie/RULES.md`.', '');\n lines.push('### 4. Start Monitoring', '```bash', 'trie watch', '```', '');\n lines.push('---', '', '**Delete this file after completing setup.** Run:', '```bash', 'rm .trie/BOOTSTRAP.md', '```');\n \n return lines.join('\\n');\n}\n","/**\n * Stack Detector\n * \n * Detects project technology stack from config files.\n * Used by bootstrap system to suggest skills and agents.\n * \n * Skills data sourced from:\n * - https://skills.sh (leaderboard)\n * - https://github.com/anthropics/skills\n * - Partner repositories (Expo, Stripe, Supabase, etc.)\n */\n\nimport { readFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\n\nexport interface DetectedStack {\n framework?: string;\n language?: string;\n database?: string;\n auth?: string;\n packageManager?: string;\n suggestedSkills: string[];\n suggestedAgents: string[];\n dependencies: Set<string>;\n}\n\n/**\n * Comprehensive dependency-to-skill mappings\n * Format: dependency name -> array of skill identifiers\n */\nconst SKILL_MAPPINGS: Record<string, string[]> = {\n // Frontend Frameworks - React/Next.js\n 'next': [\n 'vercel-labs/agent-skills vercel-react-best-practices',\n 'vercel-labs/agent-skills web-design-guidelines',\n 'anthropics/skills frontend-design',\n 'wshobson/agents nextjs-app-router-patterns',\n ],\n 'react': [\n 'vercel-labs/agent-skills vercel-react-best-practices',\n 'anthropics/skills frontend-design',\n 'wshobson/agents react-state-management',\n ],\n\n // Vue/Nuxt Ecosystem\n 'vue': [\n 'hyf0/vue-skills vue-best-practices',\n 'hyf0/vue-skills pinia-best-practices',\n 'hyf0/vue-skills vueuse-best-practices',\n 'onmax/nuxt-skills vue',\n ],\n 'nuxt': [\n 'onmax/nuxt-skills nuxt',\n 'onmax/nuxt-skills nuxt-ui',\n 'onmax/nuxt-skills nuxt-content',\n 'onmax/nuxt-skills nuxt-modules',\n 'onmax/nuxt-skills nuxt-better-auth',\n 'onmax/nuxt-skills nuxthub',\n ],\n 'pinia': [\n 'hyf0/vue-skills pinia-best-practices',\n ],\n '@vueuse/core': [\n 'hyf0/vue-skills vueuse-best-practices',\n 'onmax/nuxt-skills vueuse',\n ],\n\n // Mobile - Expo\n 'expo': [\n 'expo/skills building-native-ui',\n 'expo/skills upgrading-expo',\n 'expo/skills native-data-fetching',\n 'expo/skills expo-dev-client',\n 'expo/skills expo-deployment',\n 'expo/skills expo-api-routes',\n 'expo/skills expo-tailwind-setup',\n 'expo/skills expo-cicd-workflows',\n 'expo/skills use-dom',\n ],\n\n // Mobile - React Native\n 'react-native': [\n 'callstackincubator/agent-skills react-native-best-practices',\n 'wshobson/agents react-native-architecture',\n ],\n\n // Backend Frameworks\n '@nestjs/core': [\n 'kadajett/agent-nestjs-skills nestjs-best-practices',\n ],\n 'nestjs': [\n 'kadajett/agent-nestjs-skills nestjs-best-practices',\n ],\n 'elysia': [\n 'elysiajs/skills elysiajs',\n ],\n 'hono': [\n 'elysiajs/skills elysiajs',\n ],\n\n // Database/BaaS\n '@supabase/supabase-js': [\n 'supabase/agent-skills supabase-postgres-best-practices',\n ],\n 'convex': [\n 'waynesutton/convexskills convex-best-practices',\n ],\n 'pg': [\n 'wshobson/agents postgresql-table-design',\n ],\n 'postgres': [\n 'wshobson/agents postgresql-table-design',\n ],\n\n // Auth\n 'better-auth': [\n 'better-auth/skills better-auth-best-practices',\n 'better-auth/skills create-auth-skill',\n ],\n\n // Payments\n 'stripe': [\n 'stripe/ai stripe-best-practices',\n ],\n '@stripe/stripe-js': [\n 'stripe/ai stripe-best-practices',\n ],\n\n // Media/Graphics\n 'remotion': [\n 'remotion-dev/skills remotion-best-practices',\n ],\n 'three': [\n 'cloudai-x/threejs-skills threejs-fundamentals',\n 'cloudai-x/threejs-skills threejs-animation',\n 'cloudai-x/threejs-skills threejs-materials',\n 'cloudai-x/threejs-skills threejs-shaders',\n 'cloudai-x/threejs-skills threejs-lighting',\n 'cloudai-x/threejs-skills threejs-geometry',\n 'cloudai-x/threejs-skills threejs-textures',\n 'cloudai-x/threejs-skills threejs-loaders',\n 'cloudai-x/threejs-skills threejs-interaction',\n 'cloudai-x/threejs-skills threejs-postprocessing',\n ],\n\n // UI Libraries\n 'tailwindcss': [\n 'wshobson/agents tailwind-design-system',\n 'jezweb/claude-skills tailwind-v4-shadcn',\n 'wshobson/agents responsive-design',\n ],\n '@shadcn/ui': [\n 'giuseppe-trisciuoglio/developer-kit shadcn-ui',\n ],\n 'shadcn': [\n 'giuseppe-trisciuoglio/developer-kit shadcn-ui',\n ],\n '@radix-ui/react-slot': [\n 'onmax/nuxt-skills reka-ui',\n ],\n\n // State Management\n '@tanstack/react-query': [\n 'jezweb/claude-skills tanstack-query',\n ],\n\n // Testing\n 'playwright': [\n 'anthropics/skills webapp-testing',\n 'wshobson/agents e2e-testing-patterns',\n ],\n 'puppeteer': [\n 'anthropics/skills webapp-testing',\n ],\n 'vitest': [\n 'wshobson/agents e2e-testing-patterns',\n ],\n 'jest': [\n 'wshobson/agents e2e-testing-patterns',\n ],\n\n // DevTools/MCP\n '@modelcontextprotocol/sdk': [\n 'anthropics/skills mcp-builder',\n ],\n\n // Security\n 'semgrep': [\n 'trailofbits/skills semgrep',\n ],\n\n // Monorepos\n 'turbo': [\n 'wshobson/agents monorepo-management',\n ],\n 'nx': [\n 'wshobson/agents monorepo-management',\n ],\n 'lerna': [\n 'wshobson/agents monorepo-management',\n ],\n\n // TypeScript (handled separately based on tsconfig.json)\n 'typescript': [\n 'wshobson/agents typescript-advanced-types',\n ],\n};\n\n/**\n * Skills categories for user opt-in browsing\n */\nexport const SKILL_CATEGORIES: Record<string, string[]> = {\n documents: [\n 'anthropics/skills pdf',\n 'anthropics/skills xlsx',\n 'anthropics/skills pptx',\n 'anthropics/skills docx',\n 'anthropics/skills doc-coauthoring',\n ],\n design: [\n 'anthropics/skills canvas-design',\n 'anthropics/skills theme-factory',\n 'anthropics/skills web-artifacts-builder',\n 'anthropics/skills algorithmic-art',\n 'anthropics/skills brand-guidelines',\n 'anthropics/skills slack-gif-creator',\n 'nextlevelbuilder/ui-ux-pro-max ui-ux-pro-max',\n 'superdesigndev/superdesign-skill superdesign',\n 'wshobson/agents design-system-patterns',\n ],\n marketing: [\n 'coreyhaines31/marketingskills seo-audit',\n 'coreyhaines31/marketingskills copywriting',\n 'coreyhaines31/marketingskills marketing-psychology',\n 'coreyhaines31/marketingskills programmatic-seo',\n 'coreyhaines31/marketingskills marketing-ideas',\n 'coreyhaines31/marketingskills copy-editing',\n 'coreyhaines31/marketingskills pricing-strategy',\n 'coreyhaines31/marketingskills social-content',\n 'coreyhaines31/marketingskills launch-strategy',\n 'coreyhaines31/marketingskills page-cro',\n 'coreyhaines31/marketingskills competitor-alternatives',\n 'coreyhaines31/marketingskills analytics-tracking',\n 'coreyhaines31/marketingskills schema-markup',\n 'coreyhaines31/marketingskills onboarding-cro',\n 'coreyhaines31/marketingskills email-sequence',\n 'coreyhaines31/marketingskills paid-ads',\n 'coreyhaines31/marketingskills signup-flow-cro',\n 'coreyhaines31/marketingskills free-tool-strategy',\n 'coreyhaines31/marketingskills form-cro',\n 'coreyhaines31/marketingskills paywall-upgrade-cro',\n 'coreyhaines31/marketingskills referral-program',\n 'coreyhaines31/marketingskills popup-cro',\n 'coreyhaines31/marketingskills ab-test-setup',\n ],\n development: [\n 'obra/superpowers brainstorming',\n 'obra/superpowers test-driven-development',\n 'obra/superpowers systematic-debugging',\n 'obra/superpowers writing-plans',\n 'obra/superpowers executing-plans',\n 'obra/superpowers verification-before-completion',\n 'obra/superpowers using-superpowers',\n 'obra/superpowers subagent-driven-development',\n 'obra/superpowers requesting-code-review',\n 'obra/superpowers writing-skills',\n 'obra/superpowers dispatching-parallel-agents',\n 'obra/superpowers receiving-code-review',\n 'obra/superpowers using-git-worktrees',\n 'obra/superpowers finishing-a-development-branch',\n 'wshobson/agents code-review-excellence',\n 'wshobson/agents api-design-principles',\n 'wshobson/agents architecture-patterns',\n 'wshobson/agents error-handling-patterns',\n 'wshobson/agents nodejs-backend-patterns',\n 'wshobson/agents microservices-patterns',\n 'wshobson/agents modern-javascript-patterns',\n 'wshobson/agents web-component-design',\n 'wshobson/agents async-python-patterns',\n 'wshobson/agents python-testing-patterns',\n 'boristane/agent-skills logging-best-practices',\n ],\n productivity: [\n 'softaworks/agent-toolkit daily-meeting-update',\n 'softaworks/agent-toolkit agent-md-refactor',\n 'softaworks/agent-toolkit session-handoff',\n 'softaworks/agent-toolkit meme-factory',\n 'softaworks/agent-toolkit qa-test-planner',\n 'softaworks/agent-toolkit writing-clearly-and-concisely',\n 'softaworks/agent-toolkit commit-work',\n 'softaworks/agent-toolkit mermaid-diagrams',\n 'softaworks/agent-toolkit dependency-updater',\n 'softaworks/agent-toolkit crafting-effective-readmes',\n 'softaworks/agent-toolkit reducing-entropy',\n 'softaworks/agent-toolkit feedback-mastery',\n 'softaworks/agent-toolkit marp-slide',\n 'softaworks/agent-toolkit professional-communication',\n 'softaworks/agent-toolkit difficult-workplace-conversations',\n 'anthropics/skills internal-comms',\n 'othmanadi/planning-with-files planning-with-files',\n ],\n security: [\n 'trailofbits/skills semgrep',\n 'trailofbits/skills secure-workflow-guide',\n 'trailofbits/skills codeql',\n 'trailofbits/skills property-based-testing',\n 'trailofbits/skills variant-analysis',\n 'trailofbits/skills guidelines-advisor',\n 'trailofbits/skills sharp-edges',\n 'trailofbits/skills differential-review',\n 'trailofbits/skills ask-questions-if-underspecified',\n 'squirrelscan/skills audit-website',\n ],\n mobile: [\n 'wshobson/agents mobile-ios-design',\n 'wshobson/agents mobile-android-design',\n 'dimillian/skills swiftui-ui-patterns',\n 'dimillian/skills swiftui-liquid-glass',\n ],\n obsidian: [\n 'kepano/obsidian-skills obsidian-markdown',\n 'kepano/obsidian-skills obsidian-bases',\n 'kepano/obsidian-skills json-canvas',\n ],\n prompts: [\n 'f/awesome-chatgpt-prompts skill-lookup',\n 'f/awesome-chatgpt-prompts prompt-lookup',\n 'wshobson/agents prompt-engineering-patterns',\n ],\n browser: [\n 'vercel-labs/agent-browser agent-browser',\n ],\n content: [\n 'op7418/humanizer-zh humanizer-zh',\n 'blader/humanizer humanizer',\n 'op7418/youtube-clipper-skill youtube-clipper',\n 'jimliu/baoyu-skills baoyu-slide-deck',\n 'jimliu/baoyu-skills baoyu-article-illustrator',\n 'jimliu/baoyu-skills baoyu-cover-image',\n 'jimliu/baoyu-skills baoyu-comic',\n 'jimliu/baoyu-skills baoyu-infographic',\n 'jimliu/baoyu-skills baoyu-image-gen',\n ],\n integrations: [\n 'intellectronica/agent-skills context7',\n 'softaworks/agent-toolkit gemini',\n 'softaworks/agent-toolkit codex',\n ],\n};\n\nexport async function detectStack(projectDir: string): Promise<DetectedStack> {\n const stack: DetectedStack = {\n suggestedSkills: [],\n suggestedAgents: ['security', 'bugs'],\n dependencies: new Set(),\n };\n\n // Detect language\n if (existsSync(join(projectDir, 'tsconfig.json'))) {\n stack.language = 'TypeScript';\n stack.suggestedSkills.push('wshobson/agents typescript-advanced-types');\n } else if (existsSync(join(projectDir, 'package.json'))) {\n stack.language = 'JavaScript';\n } else if (existsSync(join(projectDir, 'requirements.txt')) || existsSync(join(projectDir, 'pyproject.toml'))) {\n stack.language = 'Python';\n } else if (existsSync(join(projectDir, 'go.mod'))) {\n stack.language = 'Go';\n } else if (existsSync(join(projectDir, 'Cargo.toml'))) {\n stack.language = 'Rust';\n }\n\n // Detect Swift/iOS projects\n if (existsSync(join(projectDir, 'Package.swift')) || \n existsSync(join(projectDir, 'project.pbxproj')) ||\n existsSync(join(projectDir, '*.xcodeproj'))) {\n stack.language = 'Swift';\n stack.suggestedSkills.push('dimillian/skills swiftui-ui-patterns');\n stack.suggestedSkills.push('dimillian/skills swiftui-liquid-glass');\n }\n\n // Detect package manager\n if (existsSync(join(projectDir, 'pnpm-lock.yaml'))) {\n stack.packageManager = 'pnpm';\n } else if (existsSync(join(projectDir, 'yarn.lock'))) {\n stack.packageManager = 'yarn';\n } else if (existsSync(join(projectDir, 'bun.lockb'))) {\n stack.packageManager = 'bun';\n } else if (existsSync(join(projectDir, 'package-lock.json'))) {\n stack.packageManager = 'npm';\n }\n\n // Check for GitHub Actions\n if (existsSync(join(projectDir, '.github', 'workflows'))) {\n stack.suggestedSkills.push('wshobson/agents github-actions-templates');\n }\n\n // Parse package.json for framework detection\n try {\n const pkgPath = join(projectDir, 'package.json');\n if (existsSync(pkgPath)) {\n const pkgContent = await readFile(pkgPath, 'utf-8');\n const pkg = JSON.parse(pkgContent);\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n\n // Store all dependencies\n for (const dep of Object.keys(deps)) {\n stack.dependencies.add(dep);\n }\n\n // Add skills based on dependency mappings\n for (const dep of Object.keys(deps)) {\n const skills = SKILL_MAPPINGS[dep];\n if (skills) {\n stack.suggestedSkills.push(...skills);\n }\n }\n\n // Framework detection (for display purposes)\n if (deps['next']) {\n stack.framework = `Next.js ${deps['next'].replace('^', '')}`;\n stack.suggestedAgents.push('accessibility', 'design');\n } else if (deps['react']) {\n stack.framework = `React ${deps['react'].replace('^', '')}`;\n stack.suggestedAgents.push('accessibility');\n } else if (deps['vue']) {\n stack.framework = `Vue ${deps['vue'].replace('^', '')}`;\n } else if (deps['nuxt']) {\n stack.framework = `Nuxt ${deps['nuxt'].replace('^', '')}`;\n } else if (deps['svelte']) {\n stack.framework = 'Svelte';\n } else if (deps['express']) {\n stack.framework = 'Express.js';\n } else if (deps['fastify']) {\n stack.framework = 'Fastify';\n } else if (deps['hono']) {\n stack.framework = 'Hono';\n } else if (deps['elysia']) {\n stack.framework = 'Elysia';\n } else if (deps['@nestjs/core']) {\n stack.framework = 'NestJS';\n }\n\n // Auth detection\n if (deps['next-auth'] || deps['@auth/core']) {\n stack.auth = 'NextAuth.js';\n } else if (deps['passport']) {\n stack.auth = 'Passport.js';\n } else if (deps['@clerk/nextjs'] || deps['@clerk/clerk-react']) {\n stack.auth = 'Clerk';\n } else if (deps['better-auth']) {\n stack.auth = 'Better Auth';\n }\n\n // Database detection\n if (deps['prisma'] || deps['@prisma/client']) {\n stack.database = 'Prisma ORM';\n } else if (deps['drizzle-orm']) {\n stack.database = 'Drizzle ORM';\n } else if (deps['@supabase/supabase-js']) {\n stack.database = 'Supabase';\n } else if (deps['mongoose']) {\n stack.database = 'MongoDB (Mongoose)';\n } else if (deps['pg']) {\n stack.database = 'PostgreSQL';\n } else if (deps['convex']) {\n stack.database = 'Convex';\n }\n\n }\n } catch {\n // package.json parsing failed\n }\n\n // Database from other sources\n if (!stack.database) {\n if (existsSync(join(projectDir, 'prisma', 'schema.prisma'))) {\n stack.database = 'Prisma ORM';\n } else if (existsSync(join(projectDir, 'drizzle.config.ts'))) {\n stack.database = 'Drizzle ORM';\n }\n }\n\n // Deduplicate\n stack.suggestedSkills = [...new Set(stack.suggestedSkills)];\n stack.suggestedAgents = [...new Set(stack.suggestedAgents)];\n\n return stack;\n}\n\n/**\n * Get skills for a specific category\n */\nexport function getSkillsByCategory(category: string): string[] {\n return SKILL_CATEGORIES[category] || [];\n}\n\n/**\n * Get all available skill categories\n */\nexport function getSkillCategories(): { name: string; count: number }[] {\n return Object.entries(SKILL_CATEGORIES).map(([name, skills]) => ({\n name,\n count: skills.length,\n }));\n}\n\n/**\n * Get project dependencies from package.json\n */\nexport async function getProjectDependencies(projectDir: string): Promise<Set<string>> {\n try {\n const pkgPath = join(projectDir, 'package.json');\n if (!existsSync(pkgPath)) {\n return new Set();\n }\n \n const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'));\n return new Set([\n ...Object.keys(pkg.dependencies || {}),\n ...Object.keys(pkg.devDependencies || {}),\n ]);\n } catch {\n return new Set();\n }\n}\n"],"mappings":"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","names":["readFile","mkdir","existsSync","join","join","existsSync","readFile","readFile","writeFile","mkdir","existsSync","join","readFile","existsSync","join","existsSync","join","readFile","needsBootstrap","join","existsSync","readFile","mkdir","writeFile","getProjectTemplate"]}
|