squads-cli 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +521 -288
- package/dist/auth-YW3UPFSB.js +23 -0
- package/dist/auth-YW3UPFSB.js.map +1 -0
- package/dist/autonomy-PSVZVX7A.js +105 -0
- package/dist/autonomy-PSVZVX7A.js.map +1 -0
- package/dist/chunk-67RO2HKR.js +174 -0
- package/dist/chunk-67RO2HKR.js.map +1 -0
- package/dist/chunk-7OCVIDC7.js +12 -0
- package/dist/chunk-7OCVIDC7.js.map +1 -0
- package/dist/chunk-BODLDQY7.js +452 -0
- package/dist/chunk-BODLDQY7.js.map +1 -0
- package/dist/chunk-EHQJHRIW.js +103 -0
- package/dist/chunk-EHQJHRIW.js.map +1 -0
- package/dist/chunk-FFFCFZ6A.js +121 -0
- package/dist/chunk-FFFCFZ6A.js.map +1 -0
- package/dist/chunk-FIWT2NMM.js +165 -0
- package/dist/chunk-FIWT2NMM.js.map +1 -0
- package/dist/chunk-HF4WR7RA.js +154 -0
- package/dist/chunk-HF4WR7RA.js.map +1 -0
- package/dist/chunk-J6QF4ZQX.js +230 -0
- package/dist/chunk-J6QF4ZQX.js.map +1 -0
- package/dist/chunk-LOA3KWYJ.js +294 -0
- package/dist/chunk-LOA3KWYJ.js.map +1 -0
- package/dist/chunk-M5FXNY6Y.js +384 -0
- package/dist/chunk-M5FXNY6Y.js.map +1 -0
- package/dist/chunk-QHNUMM4V.js +87 -0
- package/dist/chunk-QHNUMM4V.js.map +1 -0
- package/dist/chunk-QJ7C7CMB.js +223 -0
- package/dist/chunk-QJ7C7CMB.js.map +1 -0
- package/dist/chunk-RM6BWILN.js +74 -0
- package/dist/chunk-RM6BWILN.js.map +1 -0
- package/dist/chunk-TYFTF53O.js +613 -0
- package/dist/chunk-TYFTF53O.js.map +1 -0
- package/dist/chunk-TZXD6WFN.js +420 -0
- package/dist/chunk-TZXD6WFN.js.map +1 -0
- package/dist/chunk-WVOIY5GW.js +621 -0
- package/dist/chunk-WVOIY5GW.js.map +1 -0
- package/dist/chunk-Z2UKDBNL.js +162 -0
- package/dist/chunk-Z2UKDBNL.js.map +1 -0
- package/dist/chunk-ZTQ7ISUR.js +338 -0
- package/dist/chunk-ZTQ7ISUR.js.map +1 -0
- package/dist/cli.js +2483 -5902
- package/dist/cli.js.map +1 -1
- package/dist/context-GWPF4SEY.js +291 -0
- package/dist/context-GWPF4SEY.js.map +1 -0
- package/dist/context-feed-AJGVAR6H.js +394 -0
- package/dist/context-feed-AJGVAR6H.js.map +1 -0
- package/dist/cost-XBCDJ7XC.js +275 -0
- package/dist/cost-XBCDJ7XC.js.map +1 -0
- package/dist/create-BLFGG6PF.js +286 -0
- package/dist/create-BLFGG6PF.js.map +1 -0
- package/dist/dashboard-LGT2B2BL.js +951 -0
- package/dist/dashboard-LGT2B2BL.js.map +1 -0
- package/dist/dashboard-RMK2BOD2.js +794 -0
- package/dist/dashboard-RMK2BOD2.js.map +1 -0
- package/dist/doctor-XPUIIBHJ.js +374 -0
- package/dist/doctor-XPUIIBHJ.js.map +1 -0
- package/dist/env-config-SQEI3Y7Y.js +21 -0
- package/dist/env-config-SQEI3Y7Y.js.map +1 -0
- package/dist/exec-OUXM7JBF.js +223 -0
- package/dist/exec-OUXM7JBF.js.map +1 -0
- package/dist/feedback-KNAOG5QK.js +229 -0
- package/dist/feedback-KNAOG5QK.js.map +1 -0
- package/dist/github-UQTM5KMS.js +23 -0
- package/dist/github-UQTM5KMS.js.map +1 -0
- package/dist/goal-BVHV5573.js +168 -0
- package/dist/goal-BVHV5573.js.map +1 -0
- package/dist/health-4UXN44PF.js +218 -0
- package/dist/health-4UXN44PF.js.map +1 -0
- package/dist/history-ILH3SWHB.js +232 -0
- package/dist/history-ILH3SWHB.js.map +1 -0
- package/dist/index.d.ts +736 -8
- package/dist/index.js +1312 -6
- package/dist/index.js.map +1 -1
- package/dist/init-XQZ7BOGT.js +812 -0
- package/dist/init-XQZ7BOGT.js.map +1 -0
- package/dist/kpi-RQIU7WGK.js +413 -0
- package/dist/kpi-RQIU7WGK.js.map +1 -0
- package/dist/learn-OIFUVZAS.js +269 -0
- package/dist/learn-OIFUVZAS.js.map +1 -0
- package/dist/login-DXZANWZY.js +155 -0
- package/dist/login-DXZANWZY.js.map +1 -0
- package/dist/memory-T3ACCS7E.js +560 -0
- package/dist/memory-T3ACCS7E.js.map +1 -0
- package/dist/memory-VNF2VFRB.js +23 -0
- package/dist/memory-VNF2VFRB.js.map +1 -0
- package/dist/progress-DAUZMT3N.js +202 -0
- package/dist/progress-DAUZMT3N.js.map +1 -0
- package/dist/providers-3P5D2XL5.js +65 -0
- package/dist/providers-3P5D2XL5.js.map +1 -0
- package/dist/results-UECWGLTB.js +224 -0
- package/dist/results-UECWGLTB.js.map +1 -0
- package/dist/run-I6KAXU6U.js +4049 -0
- package/dist/run-I6KAXU6U.js.map +1 -0
- package/dist/session-HBU6KZOD.js +64 -0
- package/dist/session-HBU6KZOD.js.map +1 -0
- package/dist/sessions-CK25VGPL.js +333 -0
- package/dist/sessions-CK25VGPL.js.map +1 -0
- package/dist/squad-parser-DCG65BJS.js +35 -0
- package/dist/squad-parser-DCG65BJS.js.map +1 -0
- package/dist/stats-G6NAU5BD.js +334 -0
- package/dist/stats-G6NAU5BD.js.map +1 -0
- package/dist/status-AQNLDZVN.js +352 -0
- package/dist/status-AQNLDZVN.js.map +1 -0
- package/dist/sync-ZI3MHA4G.js +836 -0
- package/dist/sync-ZI3MHA4G.js.map +1 -0
- package/dist/templates/core/AGENTS.md.template +51 -0
- package/dist/templates/core/BUSINESS_BRIEF.md.template +29 -0
- package/dist/templates/core/CLAUDE.md.template +48 -0
- package/dist/templates/core/provider.yaml.template +5 -0
- package/dist/templates/first-squad/SQUAD.md.template +23 -0
- package/dist/templates/first-squad/lead.md.template +44 -0
- package/dist/templates/memory/getting-started/state.md.template +19 -0
- package/dist/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/dist/templates/seed/CLAUDE.md.template +119 -0
- package/dist/templates/seed/README.md.template +42 -0
- package/dist/templates/seed/config/SYSTEM.md +52 -0
- package/dist/templates/seed/config/provider.yaml +4 -0
- package/dist/templates/seed/hooks/settings.json.template +31 -0
- package/dist/templates/seed/memory/company/directives.md +37 -0
- package/dist/templates/seed/memory/company/manager/state.md +16 -0
- package/dist/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/dist/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/dist/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/dist/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/dist/templates/seed/memory/product/lead/state.md +14 -0
- package/dist/templates/seed/memory/research/lead/state.md +14 -0
- package/dist/templates/seed/skills/gh/SKILL.md +57 -0
- package/dist/templates/seed/skills/squads-cli/SKILL.md +84 -0
- package/dist/templates/seed/squads/company/SQUAD.md +51 -0
- package/dist/templates/seed/squads/company/company-critic.md +49 -0
- package/dist/templates/seed/squads/company/company-eval.md +49 -0
- package/dist/templates/seed/squads/company/event-dispatcher.md +43 -0
- package/dist/templates/seed/squads/company/goal-tracker.md +43 -0
- package/dist/templates/seed/squads/company/manager.md +54 -0
- package/dist/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/dist/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/dist/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/dist/templates/seed/squads/engineering/test-writer.md +50 -0
- package/dist/templates/seed/squads/intelligence/SQUAD.md +38 -0
- package/dist/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/dist/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/dist/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/dist/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/dist/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/dist/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/dist/templates/seed/squads/marketing/social-poster.md +44 -0
- package/dist/templates/seed/squads/operations/SQUAD.md +45 -0
- package/dist/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/dist/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/dist/templates/seed/squads/operations/ops-lead.md +58 -0
- package/dist/templates/seed/squads/product/SQUAD.md +41 -0
- package/dist/templates/seed/squads/product/lead.md +56 -0
- package/dist/templates/seed/squads/product/scanner.md +50 -0
- package/dist/templates/seed/squads/product/worker.md +55 -0
- package/dist/templates/seed/squads/research/SQUAD.md +38 -0
- package/dist/templates/seed/squads/research/analyst.md +50 -0
- package/dist/templates/seed/squads/research/lead.md +52 -0
- package/dist/templates/seed/squads/research/synthesizer.md +59 -0
- package/dist/templates/skills/squads-learn/SKILL.md +86 -0
- package/dist/templates/skills/squads-workflow/instruction.md +70 -0
- package/dist/terminal-FBQFQTKZ.js +55 -0
- package/dist/terminal-FBQFQTKZ.js.map +1 -0
- package/dist/update-D7CGIZ3M.js +18 -0
- package/dist/update-D7CGIZ3M.js.map +1 -0
- package/dist/update-STU276HR.js +83 -0
- package/dist/update-STU276HR.js.map +1 -0
- package/package.json +31 -13
- package/templates/core/AGENTS.md.template +51 -0
- package/templates/core/BUSINESS_BRIEF.md.template +29 -0
- package/templates/core/CLAUDE.md.template +48 -0
- package/templates/core/provider.yaml.template +5 -0
- package/templates/first-squad/SQUAD.md.template +23 -0
- package/templates/first-squad/lead.md.template +44 -0
- package/templates/memory/getting-started/state.md.template +19 -0
- package/templates/seed/BUSINESS_BRIEF.md.template +27 -0
- package/templates/seed/CLAUDE.md.template +119 -0
- package/templates/seed/README.md.template +42 -0
- package/templates/seed/config/SYSTEM.md +52 -0
- package/templates/seed/config/provider.yaml +4 -0
- package/templates/seed/hooks/settings.json.template +31 -0
- package/templates/seed/memory/company/directives.md +37 -0
- package/templates/seed/memory/company/manager/state.md +16 -0
- package/templates/seed/memory/engineering/issue-solver/state.md +12 -0
- package/templates/seed/memory/intelligence/intel-lead/state.md +9 -0
- package/templates/seed/memory/marketing/content-drafter/state.md +12 -0
- package/templates/seed/memory/operations/ops-lead/state.md +12 -0
- package/templates/seed/memory/product/lead/state.md +14 -0
- package/templates/seed/memory/research/lead/state.md +14 -0
- package/templates/seed/skills/gh/SKILL.md +57 -0
- package/templates/seed/skills/squads-cli/SKILL.md +84 -0
- package/templates/seed/squads/company/SQUAD.md +51 -0
- package/templates/seed/squads/company/company-critic.md +49 -0
- package/templates/seed/squads/company/company-eval.md +49 -0
- package/templates/seed/squads/company/event-dispatcher.md +43 -0
- package/templates/seed/squads/company/goal-tracker.md +43 -0
- package/templates/seed/squads/company/manager.md +54 -0
- package/templates/seed/squads/engineering/SQUAD.md +48 -0
- package/templates/seed/squads/engineering/code-reviewer.md +57 -0
- package/templates/seed/squads/engineering/issue-solver.md +58 -0
- package/templates/seed/squads/engineering/test-writer.md +50 -0
- package/templates/seed/squads/intelligence/SQUAD.md +38 -0
- package/templates/seed/squads/intelligence/intel-critic.md +36 -0
- package/templates/seed/squads/intelligence/intel-eval.md +31 -0
- package/templates/seed/squads/intelligence/intel-lead.md +71 -0
- package/templates/seed/squads/marketing/SQUAD.md +47 -0
- package/templates/seed/squads/marketing/content-drafter.md +71 -0
- package/templates/seed/squads/marketing/growth-analyst.md +49 -0
- package/templates/seed/squads/marketing/social-poster.md +44 -0
- package/templates/seed/squads/operations/SQUAD.md +45 -0
- package/templates/seed/squads/operations/finance-tracker.md +47 -0
- package/templates/seed/squads/operations/goal-tracker.md +48 -0
- package/templates/seed/squads/operations/ops-lead.md +58 -0
- package/templates/seed/squads/product/SQUAD.md +41 -0
- package/templates/seed/squads/product/lead.md +56 -0
- package/templates/seed/squads/product/scanner.md +50 -0
- package/templates/seed/squads/product/worker.md +55 -0
- package/templates/seed/squads/research/SQUAD.md +38 -0
- package/templates/seed/squads/research/analyst.md +50 -0
- package/templates/seed/squads/research/lead.md +52 -0
- package/templates/seed/squads/research/synthesizer.md +59 -0
- package/templates/skills/squads-learn/SKILL.md +86 -0
- package/templates/skills/squads-workflow/instruction.md +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/init.ts","../src/lib/setup-checks.ts"],"sourcesContent":["/**\n * squads init - Plant the seed\n *\n * Creates:\n * - Use-case specific squads (Engineering, Marketing, Operations, or all)\n * - CLI skill (teaches agents how to use squads CLI)\n * - Core squads (company + research + intelligence) for all use cases\n * - CLAUDE.md (operating manual for all Claude instances)\n * - BUSINESS_BRIEF.md (from user input)\n * - Memory directories (persistent state)\n * - Claude Code hooks (session tracking)\n */\n\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { execSync } from 'child_process';\nimport { createInterface } from 'readline';\nimport { checkGitStatus, getRepoName } from '../lib/git.js';\nimport { track, Events } from '../lib/telemetry.js';\nimport {\n loadTemplate,\n type TemplateVariables,\n} from '../lib/templates.js';\nimport {\n PROVIDERS,\n checkGhCli,\n runAuthChecks,\n displayCheckResults,\n} from '../lib/setup-checks.js';\nimport { writeLine } from '../lib/terminal.js';\n\nexport interface InitOptions {\n provider?: string;\n skipInfra?: boolean;\n force?: boolean;\n yes?: boolean;\n quick?: boolean;\n pack?: string[];\n}\n\ntype Provider = 'claude' | 'gemini' | 'openai' | 'ollama' | 'cursor' | 'aider' | 'none';\n\ntype UseCase = 'engineering' | 'marketing' | 'operations' | 'full-company' | 'custom';\n\n/**\n * Use-case configuration: squads, files, memory dirs, and display info\n */\ninterface UseCaseConfig {\n label: string;\n description: string;\n squads: SquadConfig[];\n}\n\ninterface SquadConfig {\n name: string;\n description: string;\n agentCount: number;\n agentSummary: string;\n dirs: string[];\n files: [string, string][]; // [destPath, templatePath]\n memoryFiles: [string, string][]; // [destPath, templatePath]\n}\n\n/**\n * Define what each use case creates\n */\nfunction getUseCaseConfig(useCase: UseCase): UseCaseConfig {\n const configs: Record<UseCase, UseCaseConfig> = {\n engineering: {\n label: 'Engineering',\n description: 'Ships code',\n squads: [getEngineeringSquad()],\n },\n marketing: {\n label: 'Marketing',\n description: 'Grows audience',\n squads: [getMarketingSquad()],\n },\n operations: {\n label: 'Operations',\n description: 'Runs the business',\n squads: [getOperationsSquad()],\n },\n 'full-company': {\n label: 'Full Company',\n description: 'Enterprise — Engineering + Marketing + Operations',\n squads: [getEngineeringSquad(), getMarketingSquad(), getOperationsSquad()],\n },\n custom: {\n label: 'Custom',\n description: 'Empty scaffold — you build from scratch',\n squads: [],\n },\n };\n\n return configs[useCase];\n}\n\nfunction getProductSquad(): SquadConfig {\n return {\n name: 'product',\n description: 'Roadmap, specs, user feedback synthesis',\n agentCount: 3,\n agentSummary: 'lead, scanner, worker',\n dirs: [\n '.agents/squads/product',\n '.agents/memory/product/lead',\n '.agents/memory/product/scanner',\n '.agents/memory/product/worker',\n ],\n files: [\n ['.agents/squads/product/SQUAD.md', 'squads/product/SQUAD.md'],\n ['.agents/squads/product/lead.md', 'squads/product/lead.md'],\n ['.agents/squads/product/scanner.md', 'squads/product/scanner.md'],\n ['.agents/squads/product/worker.md', 'squads/product/worker.md'],\n ],\n memoryFiles: [\n ['.agents/memory/product/lead/state.md', 'memory/product/lead/state.md'],\n ],\n };\n}\n\nfunction getEngineeringSquad(): SquadConfig {\n return {\n name: 'engineering',\n description: 'Solves GitHub issues, reviews code, writes tests',\n agentCount: 3,\n agentSummary: 'issue-solver, code-reviewer, test-writer',\n dirs: [\n '.agents/squads/engineering',\n '.agents/memory/engineering/issue-solver',\n '.agents/memory/engineering/code-reviewer',\n '.agents/memory/engineering/test-writer',\n ],\n files: [\n ['.agents/squads/engineering/SQUAD.md', 'squads/engineering/SQUAD.md'],\n ['.agents/squads/engineering/issue-solver.md', 'squads/engineering/issue-solver.md'],\n ['.agents/squads/engineering/code-reviewer.md', 'squads/engineering/code-reviewer.md'],\n ['.agents/squads/engineering/test-writer.md', 'squads/engineering/test-writer.md'],\n ],\n memoryFiles: [\n ['.agents/memory/engineering/issue-solver/state.md', 'memory/engineering/issue-solver/state.md'],\n ],\n };\n}\n\nfunction getMarketingSquad(): SquadConfig {\n return {\n name: 'marketing',\n description: 'Creates content, grows audience, tracks growth',\n agentCount: 3,\n agentSummary: 'content-drafter, social-poster, growth-analyst',\n dirs: [\n '.agents/squads/marketing',\n '.agents/memory/marketing/content-drafter',\n '.agents/memory/marketing/social-poster',\n '.agents/memory/marketing/growth-analyst',\n ],\n files: [\n ['.agents/squads/marketing/SQUAD.md', 'squads/marketing/SQUAD.md'],\n ['.agents/squads/marketing/content-drafter.md', 'squads/marketing/content-drafter.md'],\n ['.agents/squads/marketing/social-poster.md', 'squads/marketing/social-poster.md'],\n ['.agents/squads/marketing/growth-analyst.md', 'squads/marketing/growth-analyst.md'],\n ],\n memoryFiles: [\n ['.agents/memory/marketing/content-drafter/state.md', 'memory/marketing/content-drafter/state.md'],\n ],\n };\n}\n\nfunction getOperationsSquad(): SquadConfig {\n return {\n name: 'operations',\n description: 'Runs daily ops, tracks finances and goals',\n agentCount: 3,\n agentSummary: 'ops-lead, finance-tracker, goal-tracker',\n dirs: [\n '.agents/squads/operations',\n '.agents/memory/operations/ops-lead',\n '.agents/memory/operations/finance-tracker',\n '.agents/memory/operations/goal-tracker',\n ],\n files: [\n ['.agents/squads/operations/SQUAD.md', 'squads/operations/SQUAD.md'],\n ['.agents/squads/operations/ops-lead.md', 'squads/operations/ops-lead.md'],\n ['.agents/squads/operations/finance-tracker.md', 'squads/operations/finance-tracker.md'],\n ['.agents/squads/operations/goal-tracker.md', 'squads/operations/goal-tracker.md'],\n ],\n memoryFiles: [\n ['.agents/memory/operations/ops-lead/state.md', 'memory/operations/ops-lead/state.md'],\n ],\n };\n}\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY === true && process.stdout.isTTY === true;\n}\n\nasync function prompt(question: string, defaultValue = ''): Promise<string> {\n if (!isInteractive()) return defaultValue;\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n const suffix = defaultValue ? chalk.dim(` (${defaultValue})`) : '';\n rl.question(` ${question}${suffix} `, (answer) => {\n rl.close();\n resolve(answer.trim() || defaultValue);\n });\n });\n}\n\nasync function promptProvider(forceProvider?: string): Promise<Provider> {\n if (forceProvider && forceProvider in PROVIDERS) {\n return forceProvider as Provider;\n }\n if (!isInteractive()) return 'claude';\n\n writeLine();\n writeLine(chalk.bold(' Select your AI assistant:'));\n writeLine();\n writeLine(` ${chalk.cyan('1)')} Claude Code ${chalk.dim('(recommended)')}`);\n writeLine(` ${chalk.cyan('2)')} Gemini`);\n writeLine(` ${chalk.cyan('3)')} OpenAI GPT`);\n writeLine(` ${chalk.cyan('4)')} Ollama ${chalk.dim('(local)')}`);\n writeLine(` ${chalk.cyan('5)')} Other/None`);\n writeLine();\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n return new Promise((resolve) => {\n rl.question(` ${chalk.dim('Enter choice [1-5]:')} `, (answer) => {\n rl.close();\n const choice = answer.trim() || '1';\n switch (choice) {\n case '1': resolve('claude'); break;\n case '2': resolve('gemini'); break;\n case '3': resolve('openai'); break;\n case '4': resolve('ollama'); break;\n case '5': resolve('none'); break;\n default: resolve('claude'); break;\n }\n });\n });\n}\n\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Load a seed template from templates/seed/\n * Falls back to bundled templates in dist/templates/seed/\n */\nfunction loadSeedTemplate(templatePath: string, variables: TemplateVariables = {}): string {\n // Try loading from seed directory\n return loadTemplate(`seed/${templatePath}`, variables);\n}\n\n/**\n * Write a file only if it doesn't already exist (safe for re-runs)\n */\nasync function writeIfNew(filePath: string, content: string): Promise<boolean> {\n if (await fileExists(filePath)) return false;\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, content);\n return true;\n}\n\n/**\n * Write a file, creating directories as needed\n */\nasync function writeFile(filePath: string, content: string): Promise<void> {\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, content);\n}\n\n/**\n * Main init command - plant the seed\n */\nexport async function initCommand(options: InitOptions): Promise<void> {\n const cwd = process.cwd();\n\n // 1. Welcome\n writeLine();\n writeLine(chalk.bold(' Plant the seed for your AI workforce'));\n writeLine(chalk.dim(' https://agents-squads.com/docs/getting-started'));\n writeLine();\n\n // 2. Select provider\n const selectedProvider = await promptProvider(options.provider);\n const provider = PROVIDERS[selectedProvider];\n\n // 3. Prerequisite checks\n writeLine();\n writeLine(chalk.bold(' Checking prerequisites...'));\n writeLine();\n\n const checks = [\n ...runAuthChecks(selectedProvider),\n checkGhCli(),\n ];\n\n // Check Git\n const gitStatus = checkGitStatus(cwd);\n if (!gitStatus.isGitRepo) {\n checks.push({\n name: 'Git Repository',\n status: 'missing' as const,\n message: 'Git is the coordination layer',\n hint: 'Run: git init',\n fixCommand: 'git init',\n });\n } else {\n checks.push({ name: 'Git Repository', status: 'ok' as const });\n if (gitStatus.hasRemote) {\n const repoName = getRepoName(gitStatus.remoteUrl);\n checks.push({ name: `Remote: ${repoName || gitStatus.remoteUrl}`, status: 'ok' as const });\n }\n }\n\n const { hasErrors } = displayCheckResults(checks);\n\n if (hasErrors && !options.force) {\n writeLine();\n writeLine(chalk.red(' Fix the errors above before continuing.'));\n writeLine(chalk.dim(' Or run with --force to skip checks.'));\n writeLine();\n process.exit(1);\n }\n\n writeLine();\n\n // 4. Ask about the business\n let businessName: string;\n let businessDescription: string;\n let businessFocus: string;\n let businessCompetitors: string;\n let selectedUseCase: UseCase;\n\n if (options.yes || options.quick || !isInteractive()) {\n businessName = path.basename(cwd);\n businessDescription = 'A startup building and integrating AI smart capabilities for autonomous execution.';\n businessFocus = 'Track the big AI players — Anthropic, OpenAI, Google, Amazon, Meta, and xAI: latest model releases, API changes, pricing shifts, and strategic moves that affect builders.';\n businessCompetitors = '';\n selectedUseCase = 'custom'; // Core 4 squads only; use --pack for more\n } else {\n const dirName = path.basename(cwd);\n\n writeLine(chalk.bold(' Tell us about your business:'));\n writeLine(chalk.dim(' (Agents read this to produce useful output — be specific)'));\n writeLine();\n\n businessName = await prompt(\n 'Company or project name?',\n dirName\n );\n\n writeLine(chalk.dim(' e.g., \"We sell handmade coffee mugs online\" or \"B2B SaaS for construction teams\"'));\n businessDescription = await prompt(\n 'What does it do? (one sentence)',\n ''\n );\n // Require a non-empty description — empty = generic output on first run\n if (!businessDescription) {\n writeLine(chalk.dim(` Tip: Without a description, agents produce generic output. You can edit .agents/BUSINESS_BRIEF.md later.`));\n businessDescription = `${businessName} — add your business description to .agents/BUSINESS_BRIEF.md`;\n }\n\n writeLine();\n writeLine(chalk.dim(' e.g., \"Identify our top 3 competitors and what they do better than us\"'));\n businessFocus = await prompt(\n 'What should your agents research first?',\n 'Our market position, top competitors, and biggest growth opportunity'\n );\n\n writeLine();\n writeLine(chalk.dim(' e.g., \"BlueCart, MarketMan\" — leave blank to skip'));\n businessCompetitors = await prompt(\n 'Who are your main competitors? (optional)',\n ''\n );\n\n // 4b. Additional packs\n if (!options.pack) {\n writeLine();\n writeLine(chalk.bold(' Add squad packs? (optional)'));\n writeLine();\n writeLine(` ${chalk.cyan('1)')} Core only ${chalk.dim('— intelligence, research, product, company')} ${chalk.green('(recommended)')}`);\n writeLine(` ${chalk.cyan('2)')} + Engineering ${chalk.dim('— issue-solver, code-reviewer, test-writer')}`);\n writeLine(` ${chalk.cyan('3)')} + All packs ${chalk.dim('— engineering, marketing, operations')}`);\n writeLine();\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n const packChoice = await new Promise<string>((resolve) => {\n rl.question(` ${chalk.dim('Enter choice [1-3]:')} `, (answer) => {\n rl.close();\n resolve(answer.trim() || '1');\n });\n });\n\n if (packChoice === '2') {\n options.pack = ['engineering'];\n } else if (packChoice === '3') {\n options.pack = ['all'];\n }\n }\n\n selectedUseCase = 'custom'; // Core 4 squads; packs handled separately\n }\n\n const useCaseConfig = getUseCaseConfig(selectedUseCase);\n\n // 4c. Pack support\n if (options.pack && options.pack.length > 0) {\n const additionalSquads: SquadConfig[] = [];\n for (const pack of options.pack) {\n if (pack === 'engineering') additionalSquads.push(getEngineeringSquad());\n if (pack === 'marketing') additionalSquads.push(getMarketingSquad());\n if (pack === 'operations') additionalSquads.push(getOperationsSquad());\n if (pack === 'all') {\n additionalSquads.push(getEngineeringSquad(), getMarketingSquad(), getOperationsSquad());\n }\n }\n // De-duplicate squads by name\n const existingNames = new Set(useCaseConfig.squads.map(s => s.name));\n for (const squad of additionalSquads) {\n if (!existingNames.has(squad.name)) {\n useCaseConfig.squads.push(squad);\n existingNames.add(squad.name);\n }\n }\n }\n\n // Calculate totals (core squads + use-case squads)\n const coreAgentCount = 14; // company(5) + research(3) + intelligence(3) + product(3)\n const coreSquadCount = 4;\n const useCaseAgentCount = useCaseConfig.squads.reduce((sum, s) => sum + s.agentCount, 0);\n const totalAgentCount = coreAgentCount + useCaseAgentCount;\n const totalSquadCount = coreSquadCount + useCaseConfig.squads.length;\n\n writeLine();\n writeLine(` ${chalk.green('✓')} Business: ${chalk.cyan(businessName)}${businessDescription ? chalk.dim(` — ${businessDescription}`) : ''}`);\n writeLine(` ${chalk.green('✓')} Provider: ${chalk.cyan(provider?.name || selectedProvider)}`);\n writeLine(` ${chalk.green('✓')} Research focus: ${chalk.cyan(businessFocus)}`);\n if (businessCompetitors) {\n writeLine(` ${chalk.green('✓')} Competitors: ${chalk.cyan(businessCompetitors)}`);\n }\n if (options.pack && options.pack.length > 0) {\n writeLine(` ${chalk.green('✓')} Packs: ${chalk.cyan(options.pack.join(', '))}`);\n }\n writeLine();\n\n // 5. Create the seed\n const spinner = ora('Planting the seed...').start();\n\n try {\n // Only show PLACEHOLDER sentinel when user skipped the description in interactive mode\n const isPlaceholder = businessDescription.includes('add your business description');\n const variables: TemplateVariables = {\n BUSINESS_NAME: businessName,\n BUSINESS_DESCRIPTION: businessDescription || `${businessName} — details to be added by the manager agent.`,\n BUSINESS_FOCUS: businessFocus,\n COMPETITORS_SECTION: businessCompetitors\n ? `## Competitors\\n\\n${businessCompetitors}\\n\\n`\n : '',\n PLACEHOLDER_SENTINEL: isPlaceholder\n ? '<!-- STATUS: PLACEHOLDER — Edit this file before running agents. -->\\n<!-- Agents that read \"PLACEHOLDER\" in this comment will ask you to fill it in. -->\\n\\n'\n : '',\n PROVIDER: selectedProvider,\n PROVIDER_NAME: provider?.name || 'Unknown',\n };\n\n // Core directories (always created)\n const dirs = [\n '.agents/squads/company',\n '.agents/squads/research',\n '.agents/squads/intelligence',\n '.agents/squads/product',\n '.agents/memory/company/manager',\n '.agents/memory/company/event-dispatcher',\n '.agents/memory/company/goal-tracker',\n '.agents/memory/company/company-eval',\n '.agents/memory/company/company-critic',\n '.agents/memory/research/lead',\n '.agents/memory/research/analyst',\n '.agents/memory/research/synthesizer',\n '.agents/memory/intelligence/intel-lead',\n '.agents/memory/intelligence/intel-eval',\n '.agents/memory/intelligence/intel-critic',\n '.agents/memory/product/lead',\n '.agents/skills/squads-cli',\n '.agents/skills/gh',\n '.agents/config',\n ];\n\n // Add use-case specific directories\n for (const squad of useCaseConfig.squads) {\n dirs.push(...squad.dirs);\n }\n\n if (selectedProvider === 'claude') {\n dirs.push('.claude');\n }\n\n for (const dir of dirs) {\n await fs.mkdir(path.join(cwd, dir), { recursive: true });\n }\n\n spinner.text = 'Creating squad definitions...';\n\n // Core squad files (always created)\n const companyFiles: [string, string][] = [\n ['.agents/squads/company/SQUAD.md', 'squads/company/SQUAD.md'],\n ['.agents/squads/company/manager.md', 'squads/company/manager.md'],\n ['.agents/squads/company/event-dispatcher.md', 'squads/company/event-dispatcher.md'],\n ['.agents/squads/company/goal-tracker.md', 'squads/company/goal-tracker.md'],\n ['.agents/squads/company/company-eval.md', 'squads/company/company-eval.md'],\n ['.agents/squads/company/company-critic.md', 'squads/company/company-critic.md'],\n ];\n\n const researchFiles: [string, string][] = [\n ['.agents/squads/research/SQUAD.md', 'squads/research/SQUAD.md'],\n ['.agents/squads/research/lead.md', 'squads/research/lead.md'],\n ['.agents/squads/research/analyst.md', 'squads/research/analyst.md'],\n ['.agents/squads/research/synthesizer.md', 'squads/research/synthesizer.md'],\n ];\n\n const intelligenceFiles: [string, string][] = [\n ['.agents/squads/intelligence/SQUAD.md', 'squads/intelligence/SQUAD.md'],\n ['.agents/squads/intelligence/intel-lead.md', 'squads/intelligence/intel-lead.md'],\n ['.agents/squads/intelligence/intel-eval.md', 'squads/intelligence/intel-eval.md'],\n ['.agents/squads/intelligence/intel-critic.md', 'squads/intelligence/intel-critic.md'],\n ];\n\n const productFiles: [string, string][] = getProductSquad().files;\n\n // Collect all use-case squad files\n const useCaseFiles: [string, string][] = [];\n for (const squad of useCaseConfig.squads) {\n useCaseFiles.push(...squad.files);\n }\n\n // Write all squad files\n for (const [dest, template] of [...companyFiles, ...researchFiles, ...intelligenceFiles, ...productFiles, ...useCaseFiles]) {\n const content = loadSeedTemplate(template, variables);\n await writeFile(path.join(cwd, dest), content);\n }\n\n spinner.text = 'Creating memory and config...';\n\n // Core memory state files\n const coreMemoryFiles: [string, string][] = [\n ['.agents/memory/company/manager/state.md', 'memory/company/manager/state.md'],\n ['.agents/memory/research/lead/state.md', 'memory/research/lead/state.md'],\n ['.agents/memory/intelligence/intel-lead/state.md', 'memory/intelligence/intel-lead/state.md'],\n ['.agents/memory/product/lead/state.md', 'memory/product/lead/state.md'],\n ];\n\n // Use-case memory state files\n const useCaseMemoryFiles: [string, string][] = [];\n for (const squad of useCaseConfig.squads) {\n useCaseMemoryFiles.push(...squad.memoryFiles);\n }\n\n for (const [dest, template] of [...coreMemoryFiles, ...useCaseMemoryFiles]) {\n await writeIfNew(path.join(cwd, dest), loadSeedTemplate(template, variables));\n }\n\n // Skills\n const skillContent = loadSeedTemplate('skills/squads-cli/SKILL.md', variables);\n await writeFile(path.join(cwd, '.agents/skills/squads-cli/SKILL.md'), skillContent);\n\n const ghSkillContent = loadSeedTemplate('skills/gh/SKILL.md', variables);\n await writeFile(path.join(cwd, '.agents/skills/gh/SKILL.md'), ghSkillContent);\n\n // Provider config\n const providerConfig = loadSeedTemplate('config/provider.yaml', variables);\n await writeFile(path.join(cwd, '.agents/config/provider.yaml'), providerConfig);\n\n // System protocol (Layer 0 of context cascade)\n const systemMd = loadSeedTemplate('config/SYSTEM.md', variables);\n await writeFile(path.join(cwd, '.agents/config/SYSTEM.md'), systemMd);\n\n // Directives (Layer 3 of context cascade)\n const directivesMd = loadSeedTemplate('memory/company/directives.md', variables);\n await writeIfNew(path.join(cwd, '.agents/memory/company/directives.md'), directivesMd);\n\n // Business brief\n const businessBrief = loadSeedTemplate('BUSINESS_BRIEF.md.template', variables);\n await writeFile(path.join(cwd, '.agents/BUSINESS_BRIEF.md'), businessBrief);\n\n // AGENTS.md (repo root — vendor-neutral agent instructions)\n const agentsMd = loadTemplate('core/AGENTS.md.template', variables);\n await writeIfNew(path.join(cwd, 'AGENTS.md'), agentsMd);\n\n // README.md (only if it doesn't already exist or is the default single-line stub)\n const readmePath = path.join(cwd, 'README.md');\n let existingReadme = '';\n try {\n existingReadme = await fs.readFile(readmePath, 'utf-8');\n } catch {\n // File doesn't exist\n }\n const isStub = existingReadme.trim() === '' || /^# [^\\n]+\\s*$/.test(existingReadme.trim());\n if (isStub) {\n const readmeContent = loadSeedTemplate('README.md.template', variables);\n await writeFile(readmePath, readmeContent);\n }\n\n spinner.text = 'Setting up operating manual...';\n\n // CLAUDE.md (the operating manual — only if it doesn't exist)\n if (selectedProvider === 'claude') {\n const claudeMd = loadSeedTemplate('CLAUDE.md.template', variables);\n await writeIfNew(path.join(cwd, 'CLAUDE.md'), claudeMd);\n\n // Claude Code hooks\n const hooksContent = loadSeedTemplate('hooks/settings.json.template', variables);\n await writeIfNew(path.join(cwd, '.claude/settings.json'), hooksContent);\n }\n\n spinner.succeed('Seed planted');\n\n // Track initialization\n await track(Events.CLI_INIT, {\n success: true,\n hasGit: gitStatus.isGitRepo,\n hasRemote: gitStatus.hasRemote,\n provider: selectedProvider,\n useCase: selectedUseCase,\n agentCount: totalAgentCount,\n squadCount: totalSquadCount,\n hasBusinessName: businessName !== path.basename(cwd),\n hasBusinessDescription: businessDescription.length > 0,\n });\n\n } catch (error) {\n spinner.fail('Failed to plant the seed');\n const err = error as NodeJS.ErrnoException;\n if (err?.code === 'EACCES' || err?.code === 'EPERM') {\n writeLine(chalk.red(' Permission denied — cannot write to this directory.'));\n writeLine(chalk.dim(' Try running in a directory you own, or check folder permissions.'));\n } else if (err?.code === 'ENOENT') {\n writeLine(chalk.red(` Could not find or create: ${err.path || 'unknown path'}`));\n writeLine(chalk.dim(' Check that the directory exists and you have write access.'));\n } else {\n const msg = error instanceof Error ? error.message : String(error);\n writeLine(chalk.red(` ${msg}`));\n writeLine(chalk.dim(' Run with --verbose for more details, or check squads doctor.'));\n }\n process.exit(1);\n }\n\n // 5b. Auto-commit scaffolding (agents need at least one commit for worktrees)\n try {\n execSync('git add -A && git commit -q -m \"feat: init AI workforce\\n\\nCo-Authored-By: Claude <noreply@anthropic.com>\"', {\n cwd,\n stdio: 'ignore',\n });\n } catch {\n // Commit may fail if nothing to add or git not configured — non-fatal\n }\n\n // 6. Success message\n writeLine();\n writeLine(chalk.green.bold(` ${businessName}'s AI workforce is ready.`));\n writeLine();\n writeLine(chalk.dim(' Created:'));\n\n // Core squads (always present)\n writeLine(chalk.dim(' • research/ 3 agents — Researches your market, competitors, and opportunities'));\n writeLine(chalk.dim(' • company/ 5 agents — Manages goals, events, and strategy'));\n writeLine(chalk.dim(' • intelligence/ 3 agents — Monitors trends and competitive signals'));\n writeLine(chalk.dim(' • product/ 3 agents — Roadmap, specs, user feedback synthesis'));\n\n // Additional pack squads\n for (const squad of useCaseConfig.squads) {\n const namePad = ' '.repeat(Math.max(0, 14 - squad.name.length));\n writeLine(chalk.dim(` • ${squad.name}/${namePad}${squad.agentCount} agents — ${squad.description}`));\n }\n\n writeLine(chalk.dim(' • .agents/skills/ CLI + GitHub workflow skills'));\n writeLine(chalk.dim(' • .agents/memory/ Persistent state'));\n writeLine(chalk.dim(' • .agents/BUSINESS_BRIEF.md'));\n writeLine(chalk.dim(' • AGENTS.md Agent instructions (vendor-neutral)'));\n if (selectedProvider === 'claude') {\n writeLine(chalk.dim(' • CLAUDE.md Operating manual'));\n writeLine(chalk.dim(' • .claude/settings.json Session hooks'));\n }\n writeLine();\n writeLine(chalk.bold(' Getting started:'));\n writeLine();\n writeLine(` ${chalk.cyan('1.')} ${chalk.yellow('$EDITOR .agents/BUSINESS_BRIEF.md')}`);\n writeLine(chalk.dim(' Set your business context — agents use this for every run'));\n writeLine();\n // Dynamic \"first run\" suggestion based on use case\n const firstRunCommand = getFirstRunCommand(selectedUseCase);\n const squadCommand = firstRunCommand.command.replace(/\\/[^/]+$/, '');\n writeLine(` ${chalk.cyan('2.')} ${chalk.yellow(firstRunCommand.command)}`);\n writeLine(chalk.dim(` ${firstRunCommand.description}`));\n writeLine(chalk.dim(` Full squad (4+ agents, longer): ${squadCommand}`));\n writeLine();\n writeLine(` ${chalk.cyan('3.')} ${chalk.yellow(`squads run`)}`);\n writeLine(chalk.dim(' Autopilot — runs all squads on schedule, learns between cycles'));\n writeLine(chalk.dim(` Options: squads run --once (single cycle), squads run -i 15 --budget 50`));\n writeLine();\n writeLine(chalk.dim(' Docs: https://agents-squads.com/docs/getting-started'));\n writeLine();\n }\n\n/**\n * Get the suggested first command based on installed packs\n */\nfunction getFirstRunCommand(useCase: UseCase): { command: string; description: string } {\n switch (useCase) {\n case 'engineering':\n return {\n command: 'squads run engineering/issue-solver',\n description: 'Run a single agent — finds and solves GitHub issues (~2 min)',\n };\n case 'marketing':\n return {\n command: 'squads run marketing/content-drafter',\n description: 'Run a single agent — drafts content for your business (~2 min)',\n };\n case 'operations':\n return {\n command: 'squads run operations/ops-lead',\n description: 'Run a single agent — coordinates daily operations (~2 min)',\n };\n case 'full-company':\n case 'custom':\n default:\n return {\n command: 'squads run research/lead',\n description: 'Run a single agent — researches the topic you set (~2 min)',\n };\n }\n}\n\n","/**\n * Setup checks and validation for squads setup command\n * Provides prerequisite checking with helpful fix guidance\n */\n\nimport { execSync, spawn } from 'child_process';\nimport {\n colors,\n RESET,\n icons,\n writeLine,\n} from './terminal.js';\n\nexport type CheckStatus = 'ok' | 'missing' | 'warning' | 'error';\n\nexport interface CheckResult {\n name: string;\n status: CheckStatus;\n message?: string;\n hint?: string;\n fixCommand?: string;\n}\n\nexport interface ProviderInfo {\n id: string;\n name: string;\n cliCheck?: string;\n envKey?: string;\n installCmd?: string;\n loginCmd?: string;\n requiresSubscription: boolean;\n requiresApiKey: boolean;\n}\n\nexport const PROVIDERS: Record<string, ProviderInfo> = {\n claude: {\n id: 'claude',\n name: 'Claude Code (Anthropic)',\n cliCheck: 'claude',\n installCmd: 'npm install -g @anthropic-ai/claude-code',\n loginCmd: 'claude login',\n requiresSubscription: true,\n requiresApiKey: false,\n },\n gemini: {\n id: 'gemini',\n name: 'Gemini (Google)',\n cliCheck: 'gemini',\n envKey: 'GEMINI_API_KEY',\n installCmd: 'npm install -g @anthropic-ai/claude-code', // Placeholder - gemini CLI\n requiresSubscription: false,\n requiresApiKey: true,\n },\n openai: {\n id: 'openai',\n name: 'GPT (OpenAI)',\n envKey: 'OPENAI_API_KEY',\n requiresSubscription: false,\n requiresApiKey: true,\n },\n ollama: {\n id: 'ollama',\n name: 'Ollama (Local)',\n cliCheck: 'ollama',\n installCmd: 'brew install ollama',\n requiresSubscription: false,\n requiresApiKey: false,\n },\n cursor: {\n id: 'cursor',\n name: 'Cursor IDE',\n requiresSubscription: true,\n requiresApiKey: false,\n },\n aider: {\n id: 'aider',\n name: 'Aider',\n cliCheck: 'aider',\n installCmd: 'pip install aider-chat',\n requiresSubscription: false,\n requiresApiKey: true,\n },\n none: {\n id: 'none',\n name: 'Planning Only (no agent execution)',\n requiresSubscription: false,\n requiresApiKey: false,\n },\n};\n\n/**\n * Check if a command exists in PATH\n */\nexport function commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Docker is running\n */\nexport function isDockerRunning(): boolean {\n try {\n execSync('docker info', { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Check if Colima is running (alternative to Docker Desktop on macOS)\n */\nexport function isColimaRunning(): boolean {\n try {\n const result = execSync('colima status', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'ignore'] });\n return result.includes('Running');\n } catch {\n return false;\n }\n}\n\n/**\n * Check Docker/Colima prerequisites (informational only, never required)\n */\nexport function checkDockerPrereqs(): CheckResult {\n // Docker is never required for the CLI — purely informational\n if (isDockerRunning()) {\n return { name: 'Docker', status: 'ok', message: 'Available (optional)' };\n }\n\n if (commandExists('docker')) {\n if (commandExists('colima') && isColimaRunning()) {\n return { name: 'Docker (Colima)', status: 'ok', message: 'Available (optional)' };\n }\n }\n\n // Not installed or not running — that's fine\n return {\n name: 'Docker',\n status: 'ok',\n message: 'Not detected (optional — not required for CLI usage)',\n };\n}\n\n/**\n * Check GitHub CLI\n */\nexport function checkGhCli(): CheckResult {\n if (!commandExists('gh')) {\n return {\n name: 'GitHub CLI',\n status: 'warning',\n message: 'Recommended for GitHub integration',\n hint: 'Install: https://cli.github.com',\n };\n }\n\n // Check if authenticated\n try {\n execSync('gh auth status', { stdio: 'ignore' });\n return { name: 'GitHub CLI', status: 'ok' };\n } catch {\n return {\n name: 'GitHub CLI',\n status: 'warning',\n message: 'Installed but not authenticated',\n hint: 'Run: gh auth login',\n fixCommand: 'gh auth login',\n };\n }\n}\n\n/**\n * Check GitHub token permissions\n */\nexport function checkGhPermissions(): CheckResult {\n try {\n // Get current scopes\n const result = execSync('gh auth status 2>&1', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });\n\n // Check for required scopes\n const hasRepo = result.includes('repo') || result.includes('Token scopes:') && !result.includes('none');\n const hasWorkflow = result.includes('workflow');\n\n if (!hasRepo) {\n return {\n name: 'GitHub Permissions',\n status: 'warning',\n message: 'Missing repo scope',\n hint: 'Run: gh auth refresh -s repo,workflow',\n fixCommand: 'gh auth refresh -s repo,workflow',\n };\n }\n\n if (!hasWorkflow) {\n return {\n name: 'GitHub Permissions',\n status: 'warning',\n message: 'Missing workflow scope (optional)',\n hint: 'For Actions: gh auth refresh -s repo,workflow',\n };\n }\n\n return { name: 'GitHub Permissions', status: 'ok' };\n } catch {\n return {\n name: 'GitHub Permissions',\n status: 'warning',\n message: 'Could not verify permissions',\n hint: 'Run: gh auth status',\n };\n }\n}\n\n/**\n * Check Claude CLI\n */\nexport function checkClaudeCli(): CheckResult {\n if (!commandExists('claude')) {\n return {\n name: 'Claude CLI',\n status: 'missing',\n message: 'Required to run agents',\n hint: 'Install: npm install -g @anthropic-ai/claude-code',\n fixCommand: 'npm install -g @anthropic-ai/claude-code',\n };\n }\n\n // Check if logged in by running claude --version\n try {\n execSync('claude --version', { stdio: 'ignore' });\n return { name: 'Claude CLI', status: 'ok' };\n } catch {\n return {\n name: 'Claude CLI',\n status: 'warning',\n message: 'Installed but may need login',\n hint: 'Run: claude login',\n fixCommand: 'claude login',\n };\n }\n}\n\n/**\n * Check provider-specific requirements\n */\nexport function checkProviderAuth(providerId: string): CheckResult {\n const provider = PROVIDERS[providerId];\n if (!provider) {\n return { name: 'Provider', status: 'warning', message: `Unknown provider: ${providerId}` };\n }\n\n // No requirements for none/cursor\n if (providerId === 'none' || providerId === 'cursor') {\n return { name: provider.name, status: 'ok' };\n }\n\n // Check CLI if required\n if (provider.cliCheck) {\n if (!commandExists(provider.cliCheck)) {\n return {\n name: provider.name,\n status: 'missing',\n message: `CLI not installed`,\n hint: provider.installCmd ? `Install: ${provider.installCmd}` : undefined,\n fixCommand: provider.installCmd,\n };\n }\n }\n\n // Check API key if required\n if (provider.envKey && provider.requiresApiKey) {\n if (!process.env[provider.envKey]) {\n return {\n name: provider.name,\n status: 'warning',\n message: `${provider.envKey} not set`,\n hint: `Set environment variable: export ${provider.envKey}=<your-key>`,\n };\n }\n }\n\n return { name: provider.name, status: 'ok' };\n}\n\n/**\n * Run all prerequisite checks\n */\nexport function runPrereqChecks(): CheckResult[] {\n return [\n checkDockerPrereqs(),\n checkGhCli(),\n ];\n}\n\n/**\n * Run all auth checks for a specific provider\n */\nexport function runAuthChecks(providerId: string): CheckResult[] {\n const checks: CheckResult[] = [];\n\n // Provider-specific auth (includes CLI check)\n checks.push(checkProviderAuth(providerId));\n\n // GitHub permissions (for all providers that use GitHub)\n if (providerId !== 'none') {\n checks.push(checkGhPermissions());\n }\n\n return checks;\n}\n\n/**\n * Display check results with formatting\n */\nexport function displayCheckResults(checks: CheckResult[]): {\n hasErrors: boolean;\n hasWarnings: boolean;\n errorChecks: CheckResult[];\n warningChecks: CheckResult[];\n} {\n const errorChecks: CheckResult[] = [];\n const warningChecks: CheckResult[] = [];\n\n for (const check of checks) {\n const icon = getStatusIcon(check.status);\n const statusColor = getStatusColor(check.status);\n\n if (check.status === 'ok') {\n writeLine(` ${icon} ${check.name}`);\n } else {\n const suffix = check.message ? ` ${colors.dim}(${check.message})${RESET}` : '';\n writeLine(` ${icon} ${statusColor}${check.name}${RESET}${suffix}`);\n\n if (check.hint) {\n writeLine(` ${colors.cyan}→ ${check.hint}${RESET}`);\n }\n\n if (check.status === 'error' || check.status === 'missing') {\n errorChecks.push(check);\n } else if (check.status === 'warning') {\n warningChecks.push(check);\n }\n }\n }\n\n return {\n hasErrors: errorChecks.length > 0,\n hasWarnings: warningChecks.length > 0,\n errorChecks,\n warningChecks,\n };\n}\n\nfunction getStatusIcon(status: CheckStatus): string {\n switch (status) {\n case 'ok':\n return `${colors.green}${icons.success}${RESET}`;\n case 'warning':\n return `${colors.yellow}${icons.warning}${RESET}`;\n case 'missing':\n case 'error':\n return `${colors.red}${icons.error}${RESET}`;\n }\n}\n\nfunction getStatusColor(status: CheckStatus): string {\n switch (status) {\n case 'ok':\n return colors.green;\n case 'warning':\n return colors.yellow;\n case 'missing':\n case 'error':\n return colors.red;\n }\n}\n\n/**\n * Attempt to fix a failed check by running its fix command\n */\nexport async function attemptFix(check: CheckResult): Promise<boolean> {\n if (!check.fixCommand) {\n return false;\n }\n\n writeLine();\n writeLine(` ${colors.cyan}${icons.progress}${RESET} Running: ${colors.dim}${check.fixCommand}${RESET}`);\n writeLine();\n\n return new Promise((resolve) => {\n const proc = spawn(check.fixCommand!, [], {\n stdio: 'inherit',\n shell: true,\n });\n\n proc.on('close', (code) => {\n resolve(code === 0);\n });\n\n proc.on('error', () => {\n resolve(false);\n });\n });\n}\n\n/**\n * Wait for a service to be ready with retry\n */\nexport async function waitForService(\n name: string,\n checkFn: () => boolean | Promise<boolean>,\n maxAttempts = 30,\n intervalMs = 1000\n): Promise<boolean> {\n for (let i = 0; i < maxAttempts; i++) {\n const ready = await checkFn();\n if (ready) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n return false;\n}\n"],"mappings":"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","names":["execSync","execSync"]}
|
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
Events,
|
|
4
|
+
track
|
|
5
|
+
} from "./chunk-QJ7C7CMB.js";
|
|
6
|
+
import {
|
|
7
|
+
findSquadsDir,
|
|
8
|
+
listSquads,
|
|
9
|
+
loadSquad
|
|
10
|
+
} from "./chunk-TYFTF53O.js";
|
|
11
|
+
import {
|
|
12
|
+
RESET,
|
|
13
|
+
bold,
|
|
14
|
+
colors,
|
|
15
|
+
gradient,
|
|
16
|
+
icons,
|
|
17
|
+
writeLine
|
|
18
|
+
} from "./chunk-M5FXNY6Y.js";
|
|
19
|
+
import "./chunk-7OCVIDC7.js";
|
|
20
|
+
|
|
21
|
+
// src/lib/kpi.ts
|
|
22
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
23
|
+
import { join, dirname } from "path";
|
|
24
|
+
function getKpiStorePath(squadName) {
|
|
25
|
+
const squadsDir = findSquadsDir();
|
|
26
|
+
if (!squadsDir) {
|
|
27
|
+
throw new Error("No .agents/squads directory found");
|
|
28
|
+
}
|
|
29
|
+
return join(dirname(squadsDir), "memory", squadName, "kpis.json");
|
|
30
|
+
}
|
|
31
|
+
function loadKpiStore(squadName) {
|
|
32
|
+
const path = getKpiStorePath(squadName);
|
|
33
|
+
if (!existsSync(path)) {
|
|
34
|
+
return {
|
|
35
|
+
squadName,
|
|
36
|
+
kpis: {},
|
|
37
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const content = readFileSync(path, "utf-8");
|
|
42
|
+
return JSON.parse(content);
|
|
43
|
+
} catch {
|
|
44
|
+
return {
|
|
45
|
+
squadName,
|
|
46
|
+
kpis: {},
|
|
47
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function saveKpiStore(store) {
|
|
52
|
+
const path = getKpiStorePath(store.squadName);
|
|
53
|
+
const dir = dirname(path);
|
|
54
|
+
if (!existsSync(dir)) {
|
|
55
|
+
mkdirSync(dir, { recursive: true });
|
|
56
|
+
}
|
|
57
|
+
store.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58
|
+
writeFileSync(path, JSON.stringify(store, null, 2));
|
|
59
|
+
}
|
|
60
|
+
function recordKpiValue(squadName, kpiName, value, note) {
|
|
61
|
+
const store = loadKpiStore(squadName);
|
|
62
|
+
if (!store.kpis[kpiName]) {
|
|
63
|
+
store.kpis[kpiName] = [];
|
|
64
|
+
}
|
|
65
|
+
const record = {
|
|
66
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
67
|
+
value,
|
|
68
|
+
note
|
|
69
|
+
};
|
|
70
|
+
store.kpis[kpiName].push(record);
|
|
71
|
+
saveKpiStore(store);
|
|
72
|
+
return record;
|
|
73
|
+
}
|
|
74
|
+
function getKpiHistory(squadName, kpiName, limit) {
|
|
75
|
+
const store = loadKpiStore(squadName);
|
|
76
|
+
const history = store.kpis[kpiName] || [];
|
|
77
|
+
if (limit) {
|
|
78
|
+
return history.slice(-limit);
|
|
79
|
+
}
|
|
80
|
+
return history;
|
|
81
|
+
}
|
|
82
|
+
function calculateTrend(history) {
|
|
83
|
+
if (history.length < 2) return "flat";
|
|
84
|
+
const recent = history.slice(-5);
|
|
85
|
+
if (recent.length < 2) return "flat";
|
|
86
|
+
const first = recent[0].value;
|
|
87
|
+
const last = recent[recent.length - 1].value;
|
|
88
|
+
const change = (last - first) / first * 100;
|
|
89
|
+
if (change > 5) return "up";
|
|
90
|
+
if (change < -5) return "down";
|
|
91
|
+
return "flat";
|
|
92
|
+
}
|
|
93
|
+
function getKpiState(definition, squadName) {
|
|
94
|
+
const history = getKpiHistory(squadName, definition.name);
|
|
95
|
+
const lastValue = history.length > 0 ? history[history.length - 1] : void 0;
|
|
96
|
+
return {
|
|
97
|
+
...definition,
|
|
98
|
+
current: lastValue?.value,
|
|
99
|
+
lastUpdated: lastValue?.timestamp,
|
|
100
|
+
trend: calculateTrend(history),
|
|
101
|
+
percentOfTarget: lastValue ? Math.round(lastValue.value / definition.target * 100) : void 0,
|
|
102
|
+
history
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function generateKpiInsight(kpi) {
|
|
106
|
+
if (!kpi.current || !kpi.percentOfTarget) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const trendEmoji = kpi.trend === "up" ? "\u{1F4C8}" : kpi.trend === "down" ? "\u{1F4C9}" : "\u27A1\uFE0F";
|
|
110
|
+
const statusEmoji = kpi.percentOfTarget >= 100 ? "\u2705" : kpi.percentOfTarget >= 70 ? "\u{1F7E1}" : "\u{1F534}";
|
|
111
|
+
if (kpi.percentOfTarget >= 100) {
|
|
112
|
+
return `${statusEmoji} ${kpi.name}: Target achieved! ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;
|
|
113
|
+
} else if (kpi.percentOfTarget >= 70) {
|
|
114
|
+
return `${statusEmoji} ${kpi.name}: On track - ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;
|
|
115
|
+
} else {
|
|
116
|
+
return `${statusEmoji} ${kpi.name}: Needs attention - ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function getValuesForPeriod(history, period, count = 7) {
|
|
120
|
+
const now = /* @__PURE__ */ new Date();
|
|
121
|
+
const cutoff = /* @__PURE__ */ new Date();
|
|
122
|
+
switch (period) {
|
|
123
|
+
case "daily":
|
|
124
|
+
cutoff.setDate(now.getDate() - count);
|
|
125
|
+
break;
|
|
126
|
+
case "weekly":
|
|
127
|
+
cutoff.setDate(now.getDate() - count * 7);
|
|
128
|
+
break;
|
|
129
|
+
case "monthly":
|
|
130
|
+
cutoff.setMonth(now.getMonth() - count);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
return history.filter((v) => new Date(v.timestamp) >= cutoff);
|
|
134
|
+
}
|
|
135
|
+
function parseKpiDefinitions(frontmatter) {
|
|
136
|
+
if (!frontmatter) return [];
|
|
137
|
+
const kpis = frontmatter.kpis;
|
|
138
|
+
if (!kpis || !Array.isArray(kpis)) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
141
|
+
return kpis.map((k) => ({
|
|
142
|
+
name: String(k.name || ""),
|
|
143
|
+
target: Number(k.target || 0),
|
|
144
|
+
unit: String(k.unit || ""),
|
|
145
|
+
period: k.period || "weekly",
|
|
146
|
+
source: k.source || "manual",
|
|
147
|
+
description: k.description ? String(k.description) : void 0
|
|
148
|
+
})).filter((k) => k.name && k.target > 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/commands/kpi.ts
|
|
152
|
+
async function kpiShowCommand(squadName, options = {}) {
|
|
153
|
+
await track(Events.CLI_KPI_SHOW, { squad: squadName });
|
|
154
|
+
const squad = loadSquad(squadName);
|
|
155
|
+
if (!squad) {
|
|
156
|
+
writeLine(` ${colors.red}Squad "${squadName}" not found${RESET}`);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const definitions = parseKpiDefinitions(squad.frontmatter);
|
|
160
|
+
if (definitions.length === 0) {
|
|
161
|
+
writeLine();
|
|
162
|
+
writeLine(` ${colors.yellow}No KPIs defined for ${squadName}${RESET}`);
|
|
163
|
+
writeLine();
|
|
164
|
+
writeLine(` ${colors.dim}Define KPIs in SQUAD.md frontmatter:${RESET}`);
|
|
165
|
+
writeLine(` ${colors.dim}---${RESET}`);
|
|
166
|
+
writeLine(` ${colors.dim}kpis:${RESET}`);
|
|
167
|
+
writeLine(` ${colors.dim} - name: "leads_generated"${RESET}`);
|
|
168
|
+
writeLine(` ${colors.dim} target: 10${RESET}`);
|
|
169
|
+
writeLine(` ${colors.dim} unit: "leads"${RESET}`);
|
|
170
|
+
writeLine(` ${colors.dim} period: weekly${RESET}`);
|
|
171
|
+
writeLine(` ${colors.dim}---${RESET}`);
|
|
172
|
+
writeLine();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const kpis = definitions.map((def) => getKpiState(def, squadName));
|
|
176
|
+
if (options.json) {
|
|
177
|
+
console.log(JSON.stringify(kpis, null, 2));
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
writeLine();
|
|
181
|
+
writeLine(` ${gradient("squads")} ${colors.dim}kpi show${RESET} ${colors.cyan}${squadName}${RESET}`);
|
|
182
|
+
writeLine();
|
|
183
|
+
for (const kpi of kpis) {
|
|
184
|
+
const insight = generateKpiInsight(kpi);
|
|
185
|
+
if (insight) {
|
|
186
|
+
writeLine(` ${insight}`);
|
|
187
|
+
} else {
|
|
188
|
+
writeLine(` ${colors.dim}\u25CB${RESET} ${kpi.name}: ${colors.dim}No data recorded${RESET}`);
|
|
189
|
+
}
|
|
190
|
+
if (kpi.description) {
|
|
191
|
+
writeLine(` ${colors.dim}${kpi.description}${RESET}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
writeLine();
|
|
195
|
+
}
|
|
196
|
+
async function kpiRecordCommand(squadName, kpiName, value, options = {}) {
|
|
197
|
+
await track(Events.CLI_KPI_RECORD, { squad: squadName, kpi: kpiName });
|
|
198
|
+
const squad = loadSquad(squadName);
|
|
199
|
+
if (!squad) {
|
|
200
|
+
writeLine(` ${colors.red}Squad "${squadName}" not found${RESET}`);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const definitions = parseKpiDefinitions(squad.frontmatter);
|
|
204
|
+
const definition = definitions.find((d) => d.name === kpiName);
|
|
205
|
+
if (!definition) {
|
|
206
|
+
writeLine(` ${colors.red}KPI "${kpiName}" not defined in ${squadName}${RESET}`);
|
|
207
|
+
writeLine();
|
|
208
|
+
writeLine(` ${colors.dim}Available KPIs:${RESET}`);
|
|
209
|
+
for (const def of definitions) {
|
|
210
|
+
writeLine(` ${colors.dim} - ${def.name}${RESET}`);
|
|
211
|
+
}
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const numValue = parseFloat(value);
|
|
215
|
+
if (isNaN(numValue)) {
|
|
216
|
+
writeLine(` ${colors.red}Invalid value: ${value}${RESET}`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
const record = recordKpiValue(squadName, kpiName, numValue, options.note);
|
|
220
|
+
if (options.json) {
|
|
221
|
+
console.log(JSON.stringify(record, null, 2));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
writeLine();
|
|
225
|
+
writeLine(` ${icons.success} Recorded ${colors.cyan}${kpiName}${RESET}: ${bold}${numValue}${RESET} ${definition.unit}`);
|
|
226
|
+
if (options.note) {
|
|
227
|
+
writeLine(` ${colors.dim}Note: ${options.note}${RESET}`);
|
|
228
|
+
}
|
|
229
|
+
const percentOfTarget = Math.round(numValue / definition.target * 100);
|
|
230
|
+
const statusEmoji = percentOfTarget >= 100 ? "\u2705" : percentOfTarget >= 70 ? "\u{1F7E1}" : "\u{1F534}";
|
|
231
|
+
writeLine(` ${statusEmoji} ${percentOfTarget}% of target (${definition.target} ${definition.unit}/${definition.period})`);
|
|
232
|
+
writeLine();
|
|
233
|
+
}
|
|
234
|
+
async function kpiTrendCommand(squadName, kpiName, options = {}) {
|
|
235
|
+
await track(Events.CLI_KPI_TREND, { squad: squadName, kpi: kpiName });
|
|
236
|
+
const squad = loadSquad(squadName);
|
|
237
|
+
if (!squad) {
|
|
238
|
+
writeLine(` ${colors.red}Squad "${squadName}" not found${RESET}`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const definitions = parseKpiDefinitions(squad.frontmatter);
|
|
242
|
+
const definition = definitions.find((d) => d.name === kpiName);
|
|
243
|
+
if (!definition) {
|
|
244
|
+
writeLine(` ${colors.red}KPI "${kpiName}" not defined in ${squadName}${RESET}`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const kpi = getKpiState(definition, squadName);
|
|
248
|
+
const periods = parseInt(options.periods || "7", 10);
|
|
249
|
+
const values = getValuesForPeriod(kpi.history, definition.period, periods);
|
|
250
|
+
if (options.json) {
|
|
251
|
+
console.log(JSON.stringify({
|
|
252
|
+
kpi: kpiName,
|
|
253
|
+
definition,
|
|
254
|
+
trend: kpi.trend,
|
|
255
|
+
values
|
|
256
|
+
}, null, 2));
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
writeLine();
|
|
260
|
+
writeLine(` ${gradient("squads")} ${colors.dim}kpi trend${RESET} ${colors.cyan}${squadName}/${kpiName}${RESET}`);
|
|
261
|
+
writeLine();
|
|
262
|
+
const trendEmoji = kpi.trend === "up" ? "\u{1F4C8}" : kpi.trend === "down" ? "\u{1F4C9}" : "\u27A1\uFE0F";
|
|
263
|
+
writeLine(` ${bold}${kpiName}${RESET} ${trendEmoji} ${kpi.trend}`);
|
|
264
|
+
writeLine(` ${colors.dim}Target: ${definition.target} ${definition.unit}/${definition.period}${RESET}`);
|
|
265
|
+
writeLine();
|
|
266
|
+
if (values.length === 0) {
|
|
267
|
+
writeLine(` ${colors.dim}No data for the last ${periods} ${definition.period} periods${RESET}`);
|
|
268
|
+
} else {
|
|
269
|
+
const maxValue = Math.max(...values.map((v) => v.value), definition.target);
|
|
270
|
+
for (const v of values.slice(-10)) {
|
|
271
|
+
const barLength = Math.round(v.value / maxValue * 30);
|
|
272
|
+
const bar = "\u2588".repeat(barLength);
|
|
273
|
+
const targetMark = v.value >= definition.target ? colors.green : colors.red;
|
|
274
|
+
const date = new Date(v.timestamp).toLocaleDateString("en-US", { month: "short", day: "numeric" });
|
|
275
|
+
writeLine(` ${colors.dim}${date}${RESET} ${targetMark}${bar}${RESET} ${v.value}`);
|
|
276
|
+
}
|
|
277
|
+
writeLine();
|
|
278
|
+
writeLine(` ${colors.dim}Target line: ${definition.target} ${"\u2500".repeat(20)}${RESET}`);
|
|
279
|
+
}
|
|
280
|
+
writeLine();
|
|
281
|
+
}
|
|
282
|
+
async function kpiInsightsCommand(squadName, options = {}) {
|
|
283
|
+
await track(Events.CLI_KPI_INSIGHTS, { squad: squadName || "all" });
|
|
284
|
+
const squadsDir = findSquadsDir();
|
|
285
|
+
if (!squadsDir) {
|
|
286
|
+
writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const squadsToCheck = squadName ? [squadName] : listSquads(squadsDir);
|
|
290
|
+
const allInsights = [];
|
|
291
|
+
for (const name of squadsToCheck) {
|
|
292
|
+
const squad = loadSquad(name);
|
|
293
|
+
if (!squad) continue;
|
|
294
|
+
const definitions = parseKpiDefinitions(squad.frontmatter);
|
|
295
|
+
for (const def of definitions) {
|
|
296
|
+
const kpi = getKpiState(def, name);
|
|
297
|
+
const insight = generateKpiInsight(kpi);
|
|
298
|
+
if (insight && kpi.percentOfTarget !== void 0) {
|
|
299
|
+
allInsights.push({
|
|
300
|
+
squad: name,
|
|
301
|
+
kpi: def.name,
|
|
302
|
+
insight,
|
|
303
|
+
percentOfTarget: kpi.percentOfTarget
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
if (options.json) {
|
|
309
|
+
console.log(JSON.stringify(allInsights, null, 2));
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
writeLine();
|
|
313
|
+
writeLine(` ${gradient("squads")} ${colors.dim}kpi insights${RESET}`);
|
|
314
|
+
writeLine();
|
|
315
|
+
if (allInsights.length === 0) {
|
|
316
|
+
writeLine(` ${colors.dim}No KPI data recorded yet${RESET}`);
|
|
317
|
+
writeLine();
|
|
318
|
+
writeLine(` ${colors.dim}Record KPI values:${RESET}`);
|
|
319
|
+
writeLine(` ${colors.dim}$ squads kpi record <squad> <kpi> <value>${RESET}`);
|
|
320
|
+
writeLine();
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
allInsights.sort((a, b) => a.percentOfTarget - b.percentOfTarget);
|
|
324
|
+
const needsAttention = allInsights.filter((i) => i.percentOfTarget < 70);
|
|
325
|
+
const onTrack = allInsights.filter((i) => i.percentOfTarget >= 70 && i.percentOfTarget < 100);
|
|
326
|
+
const achieved = allInsights.filter((i) => i.percentOfTarget >= 100);
|
|
327
|
+
if (needsAttention.length > 0) {
|
|
328
|
+
writeLine(` ${colors.red}${bold}Needs Attention${RESET}`);
|
|
329
|
+
for (const item of needsAttention) {
|
|
330
|
+
writeLine(` ${item.insight}`);
|
|
331
|
+
writeLine(` ${colors.dim}Squad: ${item.squad}${RESET}`);
|
|
332
|
+
}
|
|
333
|
+
writeLine();
|
|
334
|
+
}
|
|
335
|
+
if (onTrack.length > 0) {
|
|
336
|
+
writeLine(` ${colors.yellow}${bold}On Track${RESET}`);
|
|
337
|
+
for (const item of onTrack) {
|
|
338
|
+
writeLine(` ${item.insight}`);
|
|
339
|
+
}
|
|
340
|
+
writeLine();
|
|
341
|
+
}
|
|
342
|
+
if (achieved.length > 0) {
|
|
343
|
+
writeLine(` ${colors.green}${bold}Target Achieved${RESET}`);
|
|
344
|
+
for (const item of achieved) {
|
|
345
|
+
writeLine(` ${item.insight}`);
|
|
346
|
+
}
|
|
347
|
+
writeLine();
|
|
348
|
+
}
|
|
349
|
+
writeLine(` ${colors.dim}\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500${RESET}`);
|
|
350
|
+
writeLine(` ${colors.red}${needsAttention.length}${RESET} needs attention ${colors.yellow}${onTrack.length}${RESET} on track ${colors.green}${achieved.length}${RESET} achieved`);
|
|
351
|
+
writeLine();
|
|
352
|
+
}
|
|
353
|
+
async function kpiListCommand(options = {}) {
|
|
354
|
+
await track(Events.CLI_KPI_LIST, {});
|
|
355
|
+
const squadsDir = findSquadsDir();
|
|
356
|
+
if (!squadsDir) {
|
|
357
|
+
writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
const squads = listSquads(squadsDir);
|
|
361
|
+
const allKpis = [];
|
|
362
|
+
for (const name of squads) {
|
|
363
|
+
const squad = loadSquad(name);
|
|
364
|
+
if (!squad) continue;
|
|
365
|
+
const definitions = parseKpiDefinitions(squad.frontmatter);
|
|
366
|
+
if (definitions.length > 0) {
|
|
367
|
+
allKpis.push({ squad: name, kpis: definitions });
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (options.json) {
|
|
371
|
+
console.log(JSON.stringify(allKpis, null, 2));
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
writeLine();
|
|
375
|
+
writeLine(` ${gradient("squads")} ${colors.dim}kpi list${RESET}`);
|
|
376
|
+
writeLine();
|
|
377
|
+
if (allKpis.length === 0) {
|
|
378
|
+
writeLine(` ${colors.dim}No KPIs defined in any squad${RESET}`);
|
|
379
|
+
writeLine();
|
|
380
|
+
writeLine(` ${colors.dim}Define KPIs in SQUAD.md frontmatter:${RESET}`);
|
|
381
|
+
writeLine(` ${colors.dim}---${RESET}`);
|
|
382
|
+
writeLine(` ${colors.dim}kpis:${RESET}`);
|
|
383
|
+
writeLine(` ${colors.dim} - name: "metric_name"${RESET}`);
|
|
384
|
+
writeLine(` ${colors.dim} target: 100${RESET}`);
|
|
385
|
+
writeLine(` ${colors.dim} unit: "items"${RESET}`);
|
|
386
|
+
writeLine(` ${colors.dim} period: weekly${RESET}`);
|
|
387
|
+
writeLine(` ${colors.dim}---${RESET}`);
|
|
388
|
+
writeLine();
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
for (const { squad, kpis } of allKpis) {
|
|
392
|
+
writeLine(` ${colors.cyan}${squad}${RESET}`);
|
|
393
|
+
for (const kpi of kpis) {
|
|
394
|
+
const periodIcon = kpi.period === "daily" ? "\u{1F4C5}" : kpi.period === "weekly" ? "\u{1F4C6}" : "\u{1F5D3}\uFE0F";
|
|
395
|
+
writeLine(` ${periodIcon} ${bold}${kpi.name}${RESET}: ${kpi.target} ${kpi.unit}/${kpi.period}`);
|
|
396
|
+
if (kpi.description) {
|
|
397
|
+
writeLine(` ${colors.dim}${kpi.description}${RESET}`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
writeLine();
|
|
401
|
+
}
|
|
402
|
+
const total = allKpis.reduce((sum, s) => sum + s.kpis.length, 0);
|
|
403
|
+
writeLine(` ${colors.dim}${total} KPIs across ${allKpis.length} squads${RESET}`);
|
|
404
|
+
writeLine();
|
|
405
|
+
}
|
|
406
|
+
export {
|
|
407
|
+
kpiInsightsCommand,
|
|
408
|
+
kpiListCommand,
|
|
409
|
+
kpiRecordCommand,
|
|
410
|
+
kpiShowCommand,
|
|
411
|
+
kpiTrendCommand
|
|
412
|
+
};
|
|
413
|
+
//# sourceMappingURL=kpi-RQIU7WGK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/kpi.ts","../src/commands/kpi.ts"],"sourcesContent":["/**\n * KPI Tracking Library\n *\n * Handles KPI definitions, recording values, and generating insights.\n * KPIs are defined in SQUAD.md frontmatter and values stored in memory files.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { findSquadsDir } from './squad-parser.js';\n\n/**\n * KPI definition from SQUAD.md frontmatter\n */\nexport interface KpiDefinition {\n name: string;\n target: number;\n unit: string;\n period: 'daily' | 'weekly' | 'monthly';\n source?: 'manual' | 'postgres' | 'github' | 'api';\n description?: string;\n}\n\n/**\n * Recorded KPI value\n */\nexport interface KpiValue {\n timestamp: string; // ISO date\n value: number;\n note?: string;\n}\n\n/**\n * KPI with current state and history\n */\nexport interface Kpi extends KpiDefinition {\n current?: number;\n lastUpdated?: string;\n trend?: 'up' | 'down' | 'flat';\n percentOfTarget?: number;\n history: KpiValue[];\n}\n\n/**\n * KPI storage file structure\n */\ninterface KpiStore {\n squadName: string;\n kpis: Record<string, KpiValue[]>;\n updatedAt: string;\n}\n\n/**\n * Get path to KPI store file for a squad\n */\nexport function getKpiStorePath(squadName: string): string {\n const squadsDir = findSquadsDir();\n if (!squadsDir) {\n throw new Error('No .agents/squads directory found');\n }\n return join(dirname(squadsDir), 'memory', squadName, 'kpis.json');\n}\n\n/**\n * Load KPI store for a squad\n */\nexport function loadKpiStore(squadName: string): KpiStore {\n const path = getKpiStorePath(squadName);\n\n if (!existsSync(path)) {\n return {\n squadName,\n kpis: {},\n updatedAt: new Date().toISOString(),\n };\n }\n\n try {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as KpiStore;\n } catch {\n return {\n squadName,\n kpis: {},\n updatedAt: new Date().toISOString(),\n };\n }\n}\n\n/**\n * Save KPI store for a squad\n */\nexport function saveKpiStore(store: KpiStore): void {\n const path = getKpiStorePath(store.squadName);\n const dir = dirname(path);\n\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n store.updatedAt = new Date().toISOString();\n writeFileSync(path, JSON.stringify(store, null, 2));\n}\n\n/**\n * Record a KPI value\n */\nexport function recordKpiValue(\n squadName: string,\n kpiName: string,\n value: number,\n note?: string\n): KpiValue {\n const store = loadKpiStore(squadName);\n\n if (!store.kpis[kpiName]) {\n store.kpis[kpiName] = [];\n }\n\n const record: KpiValue = {\n timestamp: new Date().toISOString(),\n value,\n note,\n };\n\n store.kpis[kpiName].push(record);\n saveKpiStore(store);\n\n return record;\n}\n\n/**\n * Get KPI history for a specific metric\n */\nexport function getKpiHistory(\n squadName: string,\n kpiName: string,\n limit?: number\n): KpiValue[] {\n const store = loadKpiStore(squadName);\n const history = store.kpis[kpiName] || [];\n\n if (limit) {\n return history.slice(-limit);\n }\n return history;\n}\n\n/**\n * Calculate trend from history\n */\nexport function calculateTrend(history: KpiValue[]): 'up' | 'down' | 'flat' {\n if (history.length < 2) return 'flat';\n\n const recent = history.slice(-5);\n if (recent.length < 2) return 'flat';\n\n const first = recent[0].value;\n const last = recent[recent.length - 1].value;\n const change = ((last - first) / first) * 100;\n\n if (change > 5) return 'up';\n if (change < -5) return 'down';\n return 'flat';\n}\n\n/**\n * Get current KPI state with trend\n */\nexport function getKpiState(\n definition: KpiDefinition,\n squadName: string\n): Kpi {\n const history = getKpiHistory(squadName, definition.name);\n const lastValue = history.length > 0 ? history[history.length - 1] : undefined;\n\n return {\n ...definition,\n current: lastValue?.value,\n lastUpdated: lastValue?.timestamp,\n trend: calculateTrend(history),\n percentOfTarget: lastValue ? Math.round((lastValue.value / definition.target) * 100) : undefined,\n history,\n };\n}\n\n/**\n * Generate insight from KPI state\n */\nexport function generateKpiInsight(kpi: Kpi): string | null {\n if (!kpi.current || !kpi.percentOfTarget) {\n return null;\n }\n\n const trendEmoji = kpi.trend === 'up' ? '📈' : kpi.trend === 'down' ? '📉' : '➡️';\n const statusEmoji = kpi.percentOfTarget >= 100 ? '✅' : kpi.percentOfTarget >= 70 ? '🟡' : '🔴';\n\n if (kpi.percentOfTarget >= 100) {\n return `${statusEmoji} ${kpi.name}: Target achieved! ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;\n } else if (kpi.percentOfTarget >= 70) {\n return `${statusEmoji} ${kpi.name}: On track - ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;\n } else {\n return `${statusEmoji} ${kpi.name}: Needs attention - ${kpi.current}/${kpi.target} ${kpi.unit} (${kpi.percentOfTarget}%) ${trendEmoji}`;\n }\n}\n\n/**\n * Get values for a specific period\n */\nexport function getValuesForPeriod(\n history: KpiValue[],\n period: 'daily' | 'weekly' | 'monthly',\n count: number = 7\n): KpiValue[] {\n const now = new Date();\n const cutoff = new Date();\n\n switch (period) {\n case 'daily':\n cutoff.setDate(now.getDate() - count);\n break;\n case 'weekly':\n cutoff.setDate(now.getDate() - count * 7);\n break;\n case 'monthly':\n cutoff.setMonth(now.getMonth() - count);\n break;\n }\n\n return history.filter(v => new Date(v.timestamp) >= cutoff);\n}\n\n/**\n * Aggregate values by period\n */\nexport function aggregateByPeriod(\n history: KpiValue[],\n period: 'daily' | 'weekly' | 'monthly'\n): Map<string, number> {\n const aggregated = new Map<string, number[]>();\n\n for (const value of history) {\n const date = new Date(value.timestamp);\n let key: string;\n\n switch (period) {\n case 'daily':\n key = date.toISOString().split('T')[0];\n break;\n case 'weekly': {\n const weekStart = new Date(date);\n weekStart.setDate(date.getDate() - date.getDay());\n key = weekStart.toISOString().split('T')[0];\n break;\n }\n case 'monthly':\n key = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`;\n break;\n }\n\n if (!aggregated.has(key)) {\n aggregated.set(key, []);\n }\n aggregated.get(key)!.push(value.value);\n }\n\n // Sum values for each period\n const result = new Map<string, number>();\n for (const [key, values] of aggregated) {\n result.set(key, values.reduce((a, b) => a + b, 0));\n }\n\n return result;\n}\n\n/**\n * Parse KPI definitions from SQUAD.md frontmatter\n */\nexport function parseKpiDefinitions(frontmatter?: Record<string, unknown>): KpiDefinition[] {\n if (!frontmatter) return [];\n const kpis = frontmatter.kpis as Array<Record<string, unknown>> | undefined;\n if (!kpis || !Array.isArray(kpis)) {\n return [];\n }\n\n return kpis.map(k => ({\n name: String(k.name || ''),\n target: Number(k.target || 0),\n unit: String(k.unit || ''),\n period: (k.period as KpiDefinition['period']) || 'weekly',\n source: (k.source as KpiDefinition['source']) || 'manual',\n description: k.description ? String(k.description) : undefined,\n })).filter(k => k.name && k.target > 0);\n}\n","/**\n * KPI Command\n *\n * Track and analyze squad KPIs defined in SQUAD.md frontmatter.\n * Commands: define, record, show, trend, insights\n */\n\nimport {\n loadSquad,\n findSquadsDir,\n listSquads,\n} from '../lib/squad-parser.js';\nimport {\n KpiDefinition,\n Kpi,\n recordKpiValue,\n getKpiState,\n generateKpiInsight,\n parseKpiDefinitions,\n getValuesForPeriod,\n} from '../lib/kpi.js';\nimport {\n colors,\n bold,\n RESET,\n gradient,\n icons,\n writeLine,\n} from '../lib/terminal.js';\nimport { track, Events } from '../lib/telemetry.js';\n\n/**\n * Show KPI status for a squad\n */\nexport async function kpiShowCommand(\n squadName: string,\n options: { json?: boolean } = {}\n): Promise<void> {\n await track(Events.CLI_KPI_SHOW, { squad: squadName });\n\n const squad = loadSquad(squadName);\n if (!squad) {\n writeLine(` ${colors.red}Squad \"${squadName}\" not found${RESET}`);\n return;\n }\n\n const definitions = parseKpiDefinitions(squad.frontmatter);\n\n if (definitions.length === 0) {\n writeLine();\n writeLine(` ${colors.yellow}No KPIs defined for ${squadName}${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Define KPIs in SQUAD.md frontmatter:${RESET}`);\n writeLine(` ${colors.dim}---${RESET}`);\n writeLine(` ${colors.dim}kpis:${RESET}`);\n writeLine(` ${colors.dim} - name: \"leads_generated\"${RESET}`);\n writeLine(` ${colors.dim} target: 10${RESET}`);\n writeLine(` ${colors.dim} unit: \"leads\"${RESET}`);\n writeLine(` ${colors.dim} period: weekly${RESET}`);\n writeLine(` ${colors.dim}---${RESET}`);\n writeLine();\n return;\n }\n\n const kpis: Kpi[] = definitions.map(def => getKpiState(def, squadName));\n\n if (options.json) {\n console.log(JSON.stringify(kpis, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}kpi show${RESET} ${colors.cyan}${squadName}${RESET}`);\n writeLine();\n\n for (const kpi of kpis) {\n const insight = generateKpiInsight(kpi);\n\n if (insight) {\n writeLine(` ${insight}`);\n } else {\n writeLine(` ${colors.dim}○${RESET} ${kpi.name}: ${colors.dim}No data recorded${RESET}`);\n }\n\n if (kpi.description) {\n writeLine(` ${colors.dim}${kpi.description}${RESET}`);\n }\n }\n\n writeLine();\n}\n\n/**\n * Record a KPI value\n */\nexport async function kpiRecordCommand(\n squadName: string,\n kpiName: string,\n value: string,\n options: { note?: string; json?: boolean } = {}\n): Promise<void> {\n await track(Events.CLI_KPI_RECORD, { squad: squadName, kpi: kpiName });\n\n const squad = loadSquad(squadName);\n if (!squad) {\n writeLine(` ${colors.red}Squad \"${squadName}\" not found${RESET}`);\n return;\n }\n\n const definitions = parseKpiDefinitions(squad.frontmatter);\n const definition = definitions.find(d => d.name === kpiName);\n\n if (!definition) {\n writeLine(` ${colors.red}KPI \"${kpiName}\" not defined in ${squadName}${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Available KPIs:${RESET}`);\n for (const def of definitions) {\n writeLine(` ${colors.dim} - ${def.name}${RESET}`);\n }\n return;\n }\n\n const numValue = parseFloat(value);\n if (isNaN(numValue)) {\n writeLine(` ${colors.red}Invalid value: ${value}${RESET}`);\n return;\n }\n\n const record = recordKpiValue(squadName, kpiName, numValue, options.note);\n\n if (options.json) {\n console.log(JSON.stringify(record, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${icons.success} Recorded ${colors.cyan}${kpiName}${RESET}: ${bold}${numValue}${RESET} ${definition.unit}`);\n if (options.note) {\n writeLine(` ${colors.dim}Note: ${options.note}${RESET}`);\n }\n\n // Show progress toward target\n const percentOfTarget = Math.round((numValue / definition.target) * 100);\n const statusEmoji = percentOfTarget >= 100 ? '✅' : percentOfTarget >= 70 ? '🟡' : '🔴';\n writeLine(` ${statusEmoji} ${percentOfTarget}% of target (${definition.target} ${definition.unit}/${definition.period})`);\n writeLine();\n}\n\n/**\n * Show KPI trend over time\n */\nexport async function kpiTrendCommand(\n squadName: string,\n kpiName: string,\n options: { periods?: string; json?: boolean } = {}\n): Promise<void> {\n await track(Events.CLI_KPI_TREND, { squad: squadName, kpi: kpiName });\n\n const squad = loadSquad(squadName);\n if (!squad) {\n writeLine(` ${colors.red}Squad \"${squadName}\" not found${RESET}`);\n return;\n }\n\n const definitions = parseKpiDefinitions(squad.frontmatter);\n const definition = definitions.find(d => d.name === kpiName);\n\n if (!definition) {\n writeLine(` ${colors.red}KPI \"${kpiName}\" not defined in ${squadName}${RESET}`);\n return;\n }\n\n const kpi = getKpiState(definition, squadName);\n const periods = parseInt(options.periods || '7', 10);\n const values = getValuesForPeriod(kpi.history, definition.period, periods);\n\n if (options.json) {\n console.log(JSON.stringify({\n kpi: kpiName,\n definition,\n trend: kpi.trend,\n values,\n }, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}kpi trend${RESET} ${colors.cyan}${squadName}/${kpiName}${RESET}`);\n writeLine();\n\n const trendEmoji = kpi.trend === 'up' ? '📈' : kpi.trend === 'down' ? '📉' : '➡️';\n writeLine(` ${bold}${kpiName}${RESET} ${trendEmoji} ${kpi.trend}`);\n writeLine(` ${colors.dim}Target: ${definition.target} ${definition.unit}/${definition.period}${RESET}`);\n writeLine();\n\n if (values.length === 0) {\n writeLine(` ${colors.dim}No data for the last ${periods} ${definition.period} periods${RESET}`);\n } else {\n // Simple ASCII chart\n const maxValue = Math.max(...values.map(v => v.value), definition.target);\n\n for (const v of values.slice(-10)) {\n const barLength = Math.round((v.value / maxValue) * 30);\n const bar = '█'.repeat(barLength);\n const targetMark = v.value >= definition.target ? colors.green : colors.red;\n\n const date = new Date(v.timestamp).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });\n writeLine(` ${colors.dim}${date}${RESET} ${targetMark}${bar}${RESET} ${v.value}`);\n }\n\n writeLine();\n writeLine(` ${colors.dim}Target line: ${definition.target} ${'─'.repeat(20)}${RESET}`);\n }\n\n writeLine();\n}\n\n/**\n * Generate insights for all KPIs\n */\nexport async function kpiInsightsCommand(\n squadName?: string,\n options: { json?: boolean } = {}\n): Promise<void> {\n await track(Events.CLI_KPI_INSIGHTS, { squad: squadName || 'all' });\n\n const squadsDir = findSquadsDir();\n if (!squadsDir) {\n writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);\n return;\n }\n\n const squadsToCheck = squadName ? [squadName] : listSquads(squadsDir);\n const allInsights: { squad: string; kpi: string; insight: string; percentOfTarget: number }[] = [];\n\n for (const name of squadsToCheck) {\n const squad = loadSquad(name);\n if (!squad) continue;\n\n const definitions = parseKpiDefinitions(squad.frontmatter);\n\n for (const def of definitions) {\n const kpi = getKpiState(def, name);\n const insight = generateKpiInsight(kpi);\n\n if (insight && kpi.percentOfTarget !== undefined) {\n allInsights.push({\n squad: name,\n kpi: def.name,\n insight,\n percentOfTarget: kpi.percentOfTarget,\n });\n }\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(allInsights, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}kpi insights${RESET}`);\n writeLine();\n\n if (allInsights.length === 0) {\n writeLine(` ${colors.dim}No KPI data recorded yet${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Record KPI values:${RESET}`);\n writeLine(` ${colors.dim}$ squads kpi record <squad> <kpi> <value>${RESET}`);\n writeLine();\n return;\n }\n\n // Sort by percentage (lowest first - needs attention)\n allInsights.sort((a, b) => a.percentOfTarget - b.percentOfTarget);\n\n // Group by status\n const needsAttention = allInsights.filter(i => i.percentOfTarget < 70);\n const onTrack = allInsights.filter(i => i.percentOfTarget >= 70 && i.percentOfTarget < 100);\n const achieved = allInsights.filter(i => i.percentOfTarget >= 100);\n\n if (needsAttention.length > 0) {\n writeLine(` ${colors.red}${bold}Needs Attention${RESET}`);\n for (const item of needsAttention) {\n writeLine(` ${item.insight}`);\n writeLine(` ${colors.dim}Squad: ${item.squad}${RESET}`);\n }\n writeLine();\n }\n\n if (onTrack.length > 0) {\n writeLine(` ${colors.yellow}${bold}On Track${RESET}`);\n for (const item of onTrack) {\n writeLine(` ${item.insight}`);\n }\n writeLine();\n }\n\n if (achieved.length > 0) {\n writeLine(` ${colors.green}${bold}Target Achieved${RESET}`);\n for (const item of achieved) {\n writeLine(` ${item.insight}`);\n }\n writeLine();\n }\n\n // Summary\n writeLine(` ${colors.dim}─────────────────────────────────────${RESET}`);\n writeLine(` ${colors.red}${needsAttention.length}${RESET} needs attention ${colors.yellow}${onTrack.length}${RESET} on track ${colors.green}${achieved.length}${RESET} achieved`);\n writeLine();\n}\n\n/**\n * List all KPIs across squads\n */\nexport async function kpiListCommand(\n options: { json?: boolean } = {}\n): Promise<void> {\n await track(Events.CLI_KPI_LIST, {});\n\n const squadsDir = findSquadsDir();\n if (!squadsDir) {\n writeLine(` ${colors.red}No .agents/squads directory found${RESET}`);\n return;\n }\n\n const squads = listSquads(squadsDir);\n const allKpis: { squad: string; kpis: KpiDefinition[] }[] = [];\n\n for (const name of squads) {\n const squad = loadSquad(name);\n if (!squad) continue;\n\n const definitions = parseKpiDefinitions(squad.frontmatter);\n if (definitions.length > 0) {\n allKpis.push({ squad: name, kpis: definitions });\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(allKpis, null, 2));\n return;\n }\n\n writeLine();\n writeLine(` ${gradient('squads')} ${colors.dim}kpi list${RESET}`);\n writeLine();\n\n if (allKpis.length === 0) {\n writeLine(` ${colors.dim}No KPIs defined in any squad${RESET}`);\n writeLine();\n writeLine(` ${colors.dim}Define KPIs in SQUAD.md frontmatter:${RESET}`);\n writeLine(` ${colors.dim}---${RESET}`);\n writeLine(` ${colors.dim}kpis:${RESET}`);\n writeLine(` ${colors.dim} - name: \"metric_name\"${RESET}`);\n writeLine(` ${colors.dim} target: 100${RESET}`);\n writeLine(` ${colors.dim} unit: \"items\"${RESET}`);\n writeLine(` ${colors.dim} period: weekly${RESET}`);\n writeLine(` ${colors.dim}---${RESET}`);\n writeLine();\n return;\n }\n\n for (const { squad, kpis } of allKpis) {\n writeLine(` ${colors.cyan}${squad}${RESET}`);\n\n for (const kpi of kpis) {\n const periodIcon = kpi.period === 'daily' ? '📅' : kpi.period === 'weekly' ? '📆' : '🗓️';\n writeLine(` ${periodIcon} ${bold}${kpi.name}${RESET}: ${kpi.target} ${kpi.unit}/${kpi.period}`);\n if (kpi.description) {\n writeLine(` ${colors.dim}${kpi.description}${RESET}`);\n }\n }\n writeLine();\n }\n\n const total = allKpis.reduce((sum, s) => sum + s.kpis.length, 0);\n writeLine(` ${colors.dim}${total} KPIs across ${allKpis.length} squads${RESET}`);\n writeLine();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,YAAY,cAAc,eAAe,iBAAiB;AACnE,SAAS,MAAM,eAAe;AA+CvB,SAAS,gBAAgB,WAA2B;AACzD,QAAM,YAAY,cAAc;AAChC,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACA,SAAO,KAAK,QAAQ,SAAS,GAAG,UAAU,WAAW,WAAW;AAClE;AAKO,SAAS,aAAa,WAA6B;AACxD,QAAM,OAAO,gBAAgB,SAAS;AAEtC,MAAI,CAAC,WAAW,IAAI,GAAG;AACrB,WAAO;AAAA,MACL;AAAA,MACA,MAAM,CAAC;AAAA,MACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,aAAa,MAAM,OAAO;AAC1C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,MACL;AAAA,MACA,MAAM,CAAC;AAAA,MACP,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AAAA,EACF;AACF;AAKO,SAAS,aAAa,OAAuB;AAClD,QAAM,OAAO,gBAAgB,MAAM,SAAS;AAC5C,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AAEA,QAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,gBAAc,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACpD;AAKO,SAAS,eACd,WACA,SACA,OACA,MACU;AACV,QAAM,QAAQ,aAAa,SAAS;AAEpC,MAAI,CAAC,MAAM,KAAK,OAAO,GAAG;AACxB,UAAM,KAAK,OAAO,IAAI,CAAC;AAAA,EACzB;AAEA,QAAM,SAAmB;AAAA,IACvB,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC;AAAA,IACA;AAAA,EACF;AAEA,QAAM,KAAK,OAAO,EAAE,KAAK,MAAM;AAC/B,eAAa,KAAK;AAElB,SAAO;AACT;AAKO,SAAS,cACd,WACA,SACA,OACY;AACZ,QAAM,QAAQ,aAAa,SAAS;AACpC,QAAM,UAAU,MAAM,KAAK,OAAO,KAAK,CAAC;AAExC,MAAI,OAAO;AACT,WAAO,QAAQ,MAAM,CAAC,KAAK;AAAA,EAC7B;AACA,SAAO;AACT;AAKO,SAAS,eAAe,SAA6C;AAC1E,MAAI,QAAQ,SAAS,EAAG,QAAO;AAE/B,QAAM,SAAS,QAAQ,MAAM,EAAE;AAC/B,MAAI,OAAO,SAAS,EAAG,QAAO;AAE9B,QAAM,QAAQ,OAAO,CAAC,EAAE;AACxB,QAAM,OAAO,OAAO,OAAO,SAAS,CAAC,EAAE;AACvC,QAAM,UAAW,OAAO,SAAS,QAAS;AAE1C,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;AAKO,SAAS,YACd,YACA,WACK;AACL,QAAM,UAAU,cAAc,WAAW,WAAW,IAAI;AACxD,QAAM,YAAY,QAAQ,SAAS,IAAI,QAAQ,QAAQ,SAAS,CAAC,IAAI;AAErE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,WAAW;AAAA,IACpB,aAAa,WAAW;AAAA,IACxB,OAAO,eAAe,OAAO;AAAA,IAC7B,iBAAiB,YAAY,KAAK,MAAO,UAAU,QAAQ,WAAW,SAAU,GAAG,IAAI;AAAA,IACvF;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,KAAyB;AAC1D,MAAI,CAAC,IAAI,WAAW,CAAC,IAAI,iBAAiB;AACxC,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,IAAI,UAAU,OAAO,cAAO,IAAI,UAAU,SAAS,cAAO;AAC7E,QAAM,cAAc,IAAI,mBAAmB,MAAM,WAAM,IAAI,mBAAmB,KAAK,cAAO;AAE1F,MAAI,IAAI,mBAAmB,KAAK;AAC9B,WAAO,GAAG,WAAW,IAAI,IAAI,IAAI,sBAAsB,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,eAAe,MAAM,UAAU;AAAA,EACtI,WAAW,IAAI,mBAAmB,IAAI;AACpC,WAAO,GAAG,WAAW,IAAI,IAAI,IAAI,gBAAgB,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,eAAe,MAAM,UAAU;AAAA,EAChI,OAAO;AACL,WAAO,GAAG,WAAW,IAAI,IAAI,IAAI,uBAAuB,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK,IAAI,eAAe,MAAM,UAAU;AAAA,EACvI;AACF;AAKO,SAAS,mBACd,SACA,QACA,QAAgB,GACJ;AACZ,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,SAAS,oBAAI,KAAK;AAExB,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,QAAQ,IAAI,QAAQ,IAAI,KAAK;AACpC;AAAA,IACF,KAAK;AACH,aAAO,QAAQ,IAAI,QAAQ,IAAI,QAAQ,CAAC;AACxC;AAAA,IACF,KAAK;AACH,aAAO,SAAS,IAAI,SAAS,IAAI,KAAK;AACtC;AAAA,EACJ;AAEA,SAAO,QAAQ,OAAO,OAAK,IAAI,KAAK,EAAE,SAAS,KAAK,MAAM;AAC5D;AAgDO,SAAS,oBAAoB,aAAwD;AAC1F,MAAI,CAAC,YAAa,QAAO,CAAC;AAC1B,QAAM,OAAO,YAAY;AACzB,MAAI,CAAC,QAAQ,CAAC,MAAM,QAAQ,IAAI,GAAG;AACjC,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,KAAK,IAAI,QAAM;AAAA,IACpB,MAAM,OAAO,EAAE,QAAQ,EAAE;AAAA,IACzB,QAAQ,OAAO,EAAE,UAAU,CAAC;AAAA,IAC5B,MAAM,OAAO,EAAE,QAAQ,EAAE;AAAA,IACzB,QAAS,EAAE,UAAsC;AAAA,IACjD,QAAS,EAAE,UAAsC;AAAA,IACjD,aAAa,EAAE,cAAc,OAAO,EAAE,WAAW,IAAI;AAAA,EACvD,EAAE,EAAE,OAAO,OAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;AACxC;;;ACnQA,eAAsB,eACpB,WACA,UAA8B,CAAC,GAChB;AACf,QAAM,MAAM,OAAO,cAAc,EAAE,OAAO,UAAU,CAAC;AAErD,QAAM,QAAQ,UAAU,SAAS;AACjC,MAAI,CAAC,OAAO;AACV,cAAU,KAAK,OAAO,GAAG,UAAU,SAAS,cAAc,KAAK,EAAE;AACjE;AAAA,EACF;AAEA,QAAM,cAAc,oBAAoB,MAAM,WAAW;AAEzD,MAAI,YAAY,WAAW,GAAG;AAC5B,cAAU;AACV,cAAU,KAAK,OAAO,MAAM,uBAAuB,SAAS,GAAG,KAAK,EAAE;AACtE,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,uCAAuC,KAAK,EAAE;AACvE,cAAU,KAAK,OAAO,GAAG,MAAM,KAAK,EAAE;AACtC,cAAU,KAAK,OAAO,GAAG,QAAQ,KAAK,EAAE;AACxC,cAAU,KAAK,OAAO,GAAG,8BAA8B,KAAK,EAAE;AAC9D,cAAU,KAAK,OAAO,GAAG,iBAAiB,KAAK,EAAE;AACjD,cAAU,KAAK,OAAO,GAAG,oBAAoB,KAAK,EAAE;AACpD,cAAU,KAAK,OAAO,GAAG,qBAAqB,KAAK,EAAE;AACrD,cAAU,KAAK,OAAO,GAAG,MAAM,KAAK,EAAE;AACtC,cAAU;AACV;AAAA,EACF;AAEA,QAAM,OAAc,YAAY,IAAI,SAAO,YAAY,KAAK,SAAS,CAAC;AAEtE,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AACzC;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,WAAW,KAAK,IAAI,OAAO,IAAI,GAAG,SAAS,GAAG,KAAK,EAAE;AACpG,YAAU;AAEV,aAAW,OAAO,MAAM;AACtB,UAAM,UAAU,mBAAmB,GAAG;AAEtC,QAAI,SAAS;AACX,gBAAU,KAAK,OAAO,EAAE;AAAA,IAC1B,OAAO;AACL,gBAAU,KAAK,OAAO,GAAG,SAAI,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,GAAG,mBAAmB,KAAK,EAAE;AAAA,IACzF;AAEA,QAAI,IAAI,aAAa;AACnB,gBAAU,OAAO,OAAO,GAAG,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAAA,IACzD;AAAA,EACF;AAEA,YAAU;AACZ;AAKA,eAAsB,iBACpB,WACA,SACA,OACA,UAA6C,CAAC,GAC/B;AACf,QAAM,MAAM,OAAO,gBAAgB,EAAE,OAAO,WAAW,KAAK,QAAQ,CAAC;AAErE,QAAM,QAAQ,UAAU,SAAS;AACjC,MAAI,CAAC,OAAO;AACV,cAAU,KAAK,OAAO,GAAG,UAAU,SAAS,cAAc,KAAK,EAAE;AACjE;AAAA,EACF;AAEA,QAAM,cAAc,oBAAoB,MAAM,WAAW;AACzD,QAAM,aAAa,YAAY,KAAK,OAAK,EAAE,SAAS,OAAO;AAE3D,MAAI,CAAC,YAAY;AACf,cAAU,KAAK,OAAO,GAAG,QAAQ,OAAO,oBAAoB,SAAS,GAAG,KAAK,EAAE;AAC/E,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,kBAAkB,KAAK,EAAE;AAClD,eAAW,OAAO,aAAa;AAC7B,gBAAU,KAAK,OAAO,GAAG,OAAO,IAAI,IAAI,GAAG,KAAK,EAAE;AAAA,IACpD;AACA;AAAA,EACF;AAEA,QAAM,WAAW,WAAW,KAAK;AACjC,MAAI,MAAM,QAAQ,GAAG;AACnB,cAAU,KAAK,OAAO,GAAG,kBAAkB,KAAK,GAAG,KAAK,EAAE;AAC1D;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,WAAW,SAAS,UAAU,QAAQ,IAAI;AAExE,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAC3C;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,MAAM,OAAO,aAAa,OAAO,IAAI,GAAG,OAAO,GAAG,KAAK,KAAK,IAAI,GAAG,QAAQ,GAAG,KAAK,IAAI,WAAW,IAAI,EAAE;AACvH,MAAI,QAAQ,MAAM;AAChB,cAAU,KAAK,OAAO,GAAG,SAAS,QAAQ,IAAI,GAAG,KAAK,EAAE;AAAA,EAC1D;AAGA,QAAM,kBAAkB,KAAK,MAAO,WAAW,WAAW,SAAU,GAAG;AACvE,QAAM,cAAc,mBAAmB,MAAM,WAAM,mBAAmB,KAAK,cAAO;AAClF,YAAU,KAAK,WAAW,IAAI,eAAe,gBAAgB,WAAW,MAAM,IAAI,WAAW,IAAI,IAAI,WAAW,MAAM,GAAG;AACzH,YAAU;AACZ;AAKA,eAAsB,gBACpB,WACA,SACA,UAAgD,CAAC,GAClC;AACf,QAAM,MAAM,OAAO,eAAe,EAAE,OAAO,WAAW,KAAK,QAAQ,CAAC;AAEpE,QAAM,QAAQ,UAAU,SAAS;AACjC,MAAI,CAAC,OAAO;AACV,cAAU,KAAK,OAAO,GAAG,UAAU,SAAS,cAAc,KAAK,EAAE;AACjE;AAAA,EACF;AAEA,QAAM,cAAc,oBAAoB,MAAM,WAAW;AACzD,QAAM,aAAa,YAAY,KAAK,OAAK,EAAE,SAAS,OAAO;AAE3D,MAAI,CAAC,YAAY;AACf,cAAU,KAAK,OAAO,GAAG,QAAQ,OAAO,oBAAoB,SAAS,GAAG,KAAK,EAAE;AAC/E;AAAA,EACF;AAEA,QAAM,MAAM,YAAY,YAAY,SAAS;AAC7C,QAAM,UAAU,SAAS,QAAQ,WAAW,KAAK,EAAE;AACnD,QAAM,SAAS,mBAAmB,IAAI,SAAS,WAAW,QAAQ,OAAO;AAEzE,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU;AAAA,MACzB,KAAK;AAAA,MACL;AAAA,MACA,OAAO,IAAI;AAAA,MACX;AAAA,IACF,GAAG,MAAM,CAAC,CAAC;AACX;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,YAAY,KAAK,IAAI,OAAO,IAAI,GAAG,SAAS,IAAI,OAAO,GAAG,KAAK,EAAE;AAChH,YAAU;AAEV,QAAM,aAAa,IAAI,UAAU,OAAO,cAAO,IAAI,UAAU,SAAS,cAAO;AAC7E,YAAU,KAAK,IAAI,GAAG,OAAO,GAAG,KAAK,IAAI,UAAU,IAAI,IAAI,KAAK,EAAE;AAClE,YAAU,KAAK,OAAO,GAAG,WAAW,WAAW,MAAM,IAAI,WAAW,IAAI,IAAI,WAAW,MAAM,GAAG,KAAK,EAAE;AACvG,YAAU;AAEV,MAAI,OAAO,WAAW,GAAG;AACvB,cAAU,KAAK,OAAO,GAAG,wBAAwB,OAAO,IAAI,WAAW,MAAM,WAAW,KAAK,EAAE;AAAA,EACjG,OAAO;AAEL,UAAM,WAAW,KAAK,IAAI,GAAG,OAAO,IAAI,OAAK,EAAE,KAAK,GAAG,WAAW,MAAM;AAExE,eAAW,KAAK,OAAO,MAAM,GAAG,GAAG;AACjC,YAAM,YAAY,KAAK,MAAO,EAAE,QAAQ,WAAY,EAAE;AACtD,YAAM,MAAM,SAAI,OAAO,SAAS;AAChC,YAAM,aAAa,EAAE,SAAS,WAAW,SAAS,OAAO,QAAQ,OAAO;AAExE,YAAM,OAAO,IAAI,KAAK,EAAE,SAAS,EAAE,mBAAmB,SAAS,EAAE,OAAO,SAAS,KAAK,UAAU,CAAC;AACjG,gBAAU,KAAK,OAAO,GAAG,GAAG,IAAI,GAAG,KAAK,IAAI,UAAU,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE,KAAK,EAAE;AAAA,IACnF;AAEA,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,gBAAgB,WAAW,MAAM,IAAI,SAAI,OAAO,EAAE,CAAC,GAAG,KAAK,EAAE;AAAA,EACxF;AAEA,YAAU;AACZ;AAKA,eAAsB,mBACpB,WACA,UAA8B,CAAC,GAChB;AACf,QAAM,MAAM,OAAO,kBAAkB,EAAE,OAAO,aAAa,MAAM,CAAC;AAElE,QAAM,YAAY,cAAc;AAChC,MAAI,CAAC,WAAW;AACd,cAAU,KAAK,OAAO,GAAG,oCAAoC,KAAK,EAAE;AACpE;AAAA,EACF;AAEA,QAAM,gBAAgB,YAAY,CAAC,SAAS,IAAI,WAAW,SAAS;AACpE,QAAM,cAA0F,CAAC;AAEjG,aAAW,QAAQ,eAAe;AAChC,UAAM,QAAQ,UAAU,IAAI;AAC5B,QAAI,CAAC,MAAO;AAEZ,UAAM,cAAc,oBAAoB,MAAM,WAAW;AAEzD,eAAW,OAAO,aAAa;AAC7B,YAAM,MAAM,YAAY,KAAK,IAAI;AACjC,YAAM,UAAU,mBAAmB,GAAG;AAEtC,UAAI,WAAW,IAAI,oBAAoB,QAAW;AAChD,oBAAY,KAAK;AAAA,UACf,OAAO;AAAA,UACP,KAAK,IAAI;AAAA,UACT;AAAA,UACA,iBAAiB,IAAI;AAAA,QACvB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAChD;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,eAAe,KAAK,EAAE;AACrE,YAAU;AAEV,MAAI,YAAY,WAAW,GAAG;AAC5B,cAAU,KAAK,OAAO,GAAG,2BAA2B,KAAK,EAAE;AAC3D,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,qBAAqB,KAAK,EAAE;AACrD,cAAU,KAAK,OAAO,GAAG,4CAA4C,KAAK,EAAE;AAC5E,cAAU;AACV;AAAA,EACF;AAGA,cAAY,KAAK,CAAC,GAAG,MAAM,EAAE,kBAAkB,EAAE,eAAe;AAGhE,QAAM,iBAAiB,YAAY,OAAO,OAAK,EAAE,kBAAkB,EAAE;AACrE,QAAM,UAAU,YAAY,OAAO,OAAK,EAAE,mBAAmB,MAAM,EAAE,kBAAkB,GAAG;AAC1F,QAAM,WAAW,YAAY,OAAO,OAAK,EAAE,mBAAmB,GAAG;AAEjE,MAAI,eAAe,SAAS,GAAG;AAC7B,cAAU,KAAK,OAAO,GAAG,GAAG,IAAI,kBAAkB,KAAK,EAAE;AACzD,eAAW,QAAQ,gBAAgB;AACjC,gBAAU,KAAK,KAAK,OAAO,EAAE;AAC7B,gBAAU,OAAO,OAAO,GAAG,UAAU,KAAK,KAAK,GAAG,KAAK,EAAE;AAAA,IAC3D;AACA,cAAU;AAAA,EACZ;AAEA,MAAI,QAAQ,SAAS,GAAG;AACtB,cAAU,KAAK,OAAO,MAAM,GAAG,IAAI,WAAW,KAAK,EAAE;AACrD,eAAW,QAAQ,SAAS;AAC1B,gBAAU,KAAK,KAAK,OAAO,EAAE;AAAA,IAC/B;AACA,cAAU;AAAA,EACZ;AAEA,MAAI,SAAS,SAAS,GAAG;AACvB,cAAU,KAAK,OAAO,KAAK,GAAG,IAAI,kBAAkB,KAAK,EAAE;AAC3D,eAAW,QAAQ,UAAU;AAC3B,gBAAU,KAAK,KAAK,OAAO,EAAE;AAAA,IAC/B;AACA,cAAU;AAAA,EACZ;AAGA,YAAU,KAAK,OAAO,GAAG,iOAAwC,KAAK,EAAE;AACxE,YAAU,KAAK,OAAO,GAAG,GAAG,eAAe,MAAM,GAAG,KAAK,qBAAqB,OAAO,MAAM,GAAG,QAAQ,MAAM,GAAG,KAAK,cAAc,OAAO,KAAK,GAAG,SAAS,MAAM,GAAG,KAAK,WAAW;AACnL,YAAU;AACZ;AAKA,eAAsB,eACpB,UAA8B,CAAC,GAChB;AACf,QAAM,MAAM,OAAO,cAAc,CAAC,CAAC;AAEnC,QAAM,YAAY,cAAc;AAChC,MAAI,CAAC,WAAW;AACd,cAAU,KAAK,OAAO,GAAG,oCAAoC,KAAK,EAAE;AACpE;AAAA,EACF;AAEA,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,UAAsD,CAAC;AAE7D,aAAW,QAAQ,QAAQ;AACzB,UAAM,QAAQ,UAAU,IAAI;AAC5B,QAAI,CAAC,MAAO;AAEZ,UAAM,cAAc,oBAAoB,MAAM,WAAW;AACzD,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,KAAK,EAAE,OAAO,MAAM,MAAM,YAAY,CAAC;AAAA,IACjD;AAAA,EACF;AAEA,MAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAC5C;AAAA,EACF;AAEA,YAAU;AACV,YAAU,KAAK,SAAS,QAAQ,CAAC,IAAI,OAAO,GAAG,WAAW,KAAK,EAAE;AACjE,YAAU;AAEV,MAAI,QAAQ,WAAW,GAAG;AACxB,cAAU,KAAK,OAAO,GAAG,+BAA+B,KAAK,EAAE;AAC/D,cAAU;AACV,cAAU,KAAK,OAAO,GAAG,uCAAuC,KAAK,EAAE;AACvE,cAAU,KAAK,OAAO,GAAG,MAAM,KAAK,EAAE;AACtC,cAAU,KAAK,OAAO,GAAG,QAAQ,KAAK,EAAE;AACxC,cAAU,KAAK,OAAO,GAAG,0BAA0B,KAAK,EAAE;AAC1D,cAAU,KAAK,OAAO,GAAG,kBAAkB,KAAK,EAAE;AAClD,cAAU,KAAK,OAAO,GAAG,oBAAoB,KAAK,EAAE;AACpD,cAAU,KAAK,OAAO,GAAG,qBAAqB,KAAK,EAAE;AACrD,cAAU,KAAK,OAAO,GAAG,MAAM,KAAK,EAAE;AACtC,cAAU;AACV;AAAA,EACF;AAEA,aAAW,EAAE,OAAO,KAAK,KAAK,SAAS;AACrC,cAAU,KAAK,OAAO,IAAI,GAAG,KAAK,GAAG,KAAK,EAAE;AAE5C,eAAW,OAAO,MAAM;AACtB,YAAM,aAAa,IAAI,WAAW,UAAU,cAAO,IAAI,WAAW,WAAW,cAAO;AACpF,gBAAU,OAAO,UAAU,IAAI,IAAI,GAAG,IAAI,IAAI,GAAG,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,IAAI,MAAM,EAAE;AACjG,UAAI,IAAI,aAAa;AACnB,kBAAU,UAAU,OAAO,GAAG,GAAG,IAAI,WAAW,GAAG,KAAK,EAAE;AAAA,MAC5D;AAAA,IACF;AACA,cAAU;AAAA,EACZ;AAEA,QAAM,QAAQ,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,QAAQ,CAAC;AAC/D,YAAU,KAAK,OAAO,GAAG,GAAG,KAAK,gBAAgB,QAAQ,MAAM,UAAU,KAAK,EAAE;AAChF,YAAU;AACZ;","names":[]}
|