@3lineas/grooveskills 1.5.0 → 1.7.0

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.
Files changed (27) hide show
  1. package/README.md +8 -0
  2. package/dist/{chunk-PLMYUKGW.js → chunk-E63GTCOE.js} +475 -146
  3. package/dist/chunk-E63GTCOE.js.map +1 -0
  4. package/dist/cli.js +23 -3
  5. package/dist/cli.js.map +1 -1
  6. package/dist/main.js +1 -1
  7. package/package.json +3 -2
  8. package/skills/auth-rbac-policies/SKILL.md +100 -0
  9. package/skills/auth-rbac-policies/references/auth-adapters-examples.md +99 -0
  10. package/skills/caching-rate-limiting/SKILL.md +109 -0
  11. package/skills/caching-rate-limiting/references/cache-rate-limit-examples.md +129 -0
  12. package/skills/clean-architecture-ddd/SKILL.md +1 -0
  13. package/skills/controller-orchestration-queues/SKILL.md +109 -0
  14. package/skills/controller-orchestration-queues/references/controller-queue-examples.md +115 -0
  15. package/skills/docs-standards/SKILL.md +113 -0
  16. package/skills/docs-standards/references/adr-template-and-lifecycle.md +111 -0
  17. package/skills/docs-standards/references/code-comments-and-docstrings.md +147 -0
  18. package/skills/docs-standards/references/relative-paths-and-diagrams.md +123 -0
  19. package/skills/env-feature-flags/SKILL.md +94 -0
  20. package/skills/env-feature-flags/references/env-feature-flags-examples.md +93 -0
  21. package/skills/external-service-adapters/SKILL.md +148 -0
  22. package/skills/external-service-adapters/references/email-and-payment-examples.md +198 -0
  23. package/skills/storage-file-adapters/SKILL.md +125 -0
  24. package/skills/storage-file-adapters/references/storage-adapters-examples.md +164 -0
  25. package/skills/webhook-idempotency/SKILL.md +104 -0
  26. package/skills/webhook-idempotency/references/webhook-idempotency-examples.md +112 -0
  27. package/dist/chunk-PLMYUKGW.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/domains/detector/project-detector.ts","../src/domains/detector/detect-agents.ts","../src/domains/detector/detect-dependencies.ts","../src/domains/registry/skill-catalog.ts","../src/domains/ui/ui-orchestrator.ts","../src/domains/ui/banners.ts","../src/domains/ui/prompt-skills.ts","../src/domains/ui/prompt-agents.ts","../src/domains/ui/prompt-language.ts","../src/domains/ui/prompt-confirm-overwrite.ts","../src/domains/installer/verify-skill-exists.ts","../src/domains/installer/install-orchestrator.ts","../src/domains/adapters/skill-reference-builder.ts","../src/domains/project-store/project-paths.ts","../src/domains/fs/safe-file-writer.ts","../src/errors/file-permission-error.ts","../src/domains/adapters/antigravity.adapter.ts","../src/domains/adapters/claude.adapter.ts","../src/domains/adapters/cursor.adapter.ts","../src/domains/adapters/gemini.adapter.ts","../src/domains/project-store/sync-project-store.ts","../src/domains/installer/resolve-skills-source.ts","../src/domains/harness/install-harness.ts","../src/domains/harness/harness-languages.ts","../src/domains/harness/harness-templates.ts","../src/domains/harness/scan-project-onboarding.ts","../src/domains/harness/upsert-agent-instructions.ts","../src/domains/harness/write-project-config.ts","../src/domains/fs/install-transaction.ts","../src/errors/install-transaction-error.ts","../src/domains/ui/render-onboarding-prompt.ts","../src/main.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { detectAgents } from \"@/domains/detector/detect-agents\";\nimport { detectDependencies } from \"@/domains/detector/detect-dependencies\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { ProjectContext } from \"@/types/context.types\";\nimport type { GrooveSkillsConfig, ProjectLanguage } from \"@/types/harness.types\";\n\nfunction readConfiguredLanguage(targetPath: string): ProjectLanguage | undefined {\n const configPath = join(targetPath, \".grooveskills\", \"config.json\");\n if (!existsSync(configPath)) {\n return undefined;\n }\n\n try {\n const raw = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<GrooveSkillsConfig>;\n return typeof parsed.language === \"string\" ? (parsed.language as ProjectLanguage) : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function detectProjectContext(targetPath: string): ProjectContext {\n const detectedAgents = detectAgents(targetPath);\n const { dependencies, exists } = detectDependencies(targetPath);\n\n const suggestedSkillIds: string[] = [\n \"odd-ai\",\n \"best-practices\",\n \"ux-writing\",\n \"docs-standards\",\n \"error-handling-logging\",\n \"clean-architecture-ddd\",\n \"external-service-adapters\",\n \"storage-file-adapters\",\n \"auth-rbac-policies\",\n \"controller-orchestration-queues\",\n \"webhook-idempotency\",\n \"caching-rate-limiting\",\n \"env-feature-flags\",\n ];\n\n for (const skill of SKILL_CATALOG) {\n if (skill.dependencies.length === 0) {\n continue;\n }\n const hasMatch = skill.dependencies.some((dep) => dependencies.includes(dep));\n if (hasMatch && !suggestedSkillIds.includes(skill.id)) {\n suggestedSkillIds.push(skill.id);\n }\n }\n\n const harnessExists = existsSync(join(targetPath, \".grooveskills\", \"memory\", \"context.md\"));\n const configuredLanguage = readConfiguredLanguage(targetPath);\n\n return {\n targetPath,\n detectedDependencies: dependencies,\n suggestedSkillIds,\n detectedAgents,\n packageJsonExists: exists,\n harnessExists,\n configuredLanguage,\n };\n}\n","import { readdirSync } from \"node:fs\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport function detectAgents(targetPath: string): AgentId[] {\n const detected: AgentId[] = [];\n\n try {\n const entries = new Set(readdirSync(targetPath));\n\n if (entries.has(\".agents\")) {\n detected.push(\"antigravity\");\n }\n if (entries.has(\".claude\")) {\n detected.push(\"claude\");\n }\n if (entries.has(\".cursor\")) {\n detected.push(\"cursor\");\n }\n if (entries.has(\".gemini\")) {\n detected.push(\"gemini\");\n }\n } catch {\n // If directory cannot be read, return empty list gracefully\n }\n\n return detected;\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface PackageJsonDetection {\n dependencies: string[];\n exists: boolean;\n}\n\nexport function detectDependencies(targetPath: string): PackageJsonDetection {\n const detected = new Set<string>();\n let hasManifest = false;\n\n const packageJsonPath = join(targetPath, \"package.json\");\n if (existsSync(packageJsonPath)) {\n hasManifest = true;\n try {\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n for (const dep of Object.keys(parsed.dependencies ?? {})) {\n detected.add(dep);\n }\n for (const dep of Object.keys(parsed.devDependencies ?? {})) {\n detected.add(dep);\n }\n } catch {\n // Ignore JSON parse errors gracefully\n }\n }\n\n const cargoPath = join(targetPath, \"Cargo.toml\");\n if (existsSync(cargoPath)) {\n hasManifest = true;\n detected.add(\"rust\");\n }\n\n const pyprojectPath = join(targetPath, \"pyproject.toml\");\n const requirementsPath = join(targetPath, \"requirements.txt\");\n if (existsSync(pyprojectPath) || existsSync(requirementsPath)) {\n hasManifest = true;\n detected.add(\"python\");\n }\n\n return {\n dependencies: Array.from(detected),\n exists: hasManifest,\n };\n}\n","import type { SkillMetadata } from \"@/types/skill.types\";\n\nexport const SKILL_CATALOG: SkillMetadata[] = [\n {\n id: \"groove-harness\",\n name: \"GrooveSkills Harness\",\n description: \"Lightweight project harness, context memory, and ODD 3-lane task execution (Answer, Task, Spec) for AI coding agents\",\n dependencies: [],\n directoryName: \"groove-harness\",\n isCoreHarness: true,\n },\n {\n id: \"odd-ai\",\n name: \"Organic & Outcome-Driven Development (ODD)\",\n description: \"7-step ODD protocol for AI agents: authorize, explore, classify, outcome hypotheses, and verifiable evidence receipts\",\n dependencies: [],\n directoryName: \"odd-ai\",\n },\n {\n id: \"best-practices\",\n name: \"Universal Best Practices\",\n description: \"Multi-language clean code standards, early returns, no barrel files, strict typing, <200 lines\",\n dependencies: [],\n directoryName: \"best-practices\",\n },\n {\n id: \"ux-writing\",\n name: \"UX Writing & Microcopy Standards\",\n description: \"Persuasive, empathetic, professional bilingual microcopy (ES/EN) for error messages, forms, CTAs, toasts, and empty states\",\n dependencies: [],\n directoryName: \"ux-writing\",\n },\n {\n id: \"docs-standards\",\n name: \"Documentation & ADR Standards\",\n description: \"English documentation standard, relative POSIX links, resilient Mermaid diagrams, ADR lifecycle, and intent-focused docstrings\",\n dependencies: [],\n directoryName: \"docs-standards\",\n },\n {\n id: \"typescript-clean\",\n name: \"TypeScript Clean Code (TS 5.5+)\",\n description: \"Advanced strict TypeScript, discriminated unions, satisfies, const generics, unknown over any, and zero unsafe casts\",\n dependencies: [\"typescript\"],\n directoryName: \"typescript-clean\",\n },\n {\n id: \"rust-clean\",\n name: \"Rust Clean Code (Rust 2024)\",\n description: \"Idiomatic Rust clean code: let-else guard clauses, no unwrap in production, thiserror typed errors, Newtypes, zero barrel files, <200 lines\",\n dependencies: [\"rust\"],\n directoryName: \"rust-clean\",\n },\n {\n id: \"python-clean\",\n name: \"Python Clean Code (Python 3.12+)\",\n description: \"Modern Python standards: guard clauses (no nested ifs), strict typing (zero Any), uv, Ruff, Pyright, Pydantic v2 boundaries, <200 lines\",\n dependencies: [\"python\"],\n directoryName: \"python-clean\",\n },\n {\n id: \"error-handling-logging\",\n name: \"Error Handling & Structured Logging\",\n description: \"Deterministic error management with AppError, Result/ActionResponse contracts, and structured context logging\",\n dependencies: [],\n directoryName: \"error-handling-logging\",\n },\n {\n id: \"valibot-validation\",\n name: \"Valibot Schema Validation\",\n description: \"Boundary schema validation with Valibot (* as v from 'valibot'), strict type inference, and friendly error messages\",\n dependencies: [\"valibot\"],\n directoryName: \"valibot-validation\",\n },\n {\n id: \"clean-architecture-ddd\",\n name: \"Clean Architecture & DDD\",\n description: \"Domain-driven design, isolated single-purpose Actions, pure functions, immutability, zero barrel files, <200 lines per file\",\n dependencies: [],\n directoryName: \"clean-architecture-ddd\",\n },\n {\n id: \"external-service-adapters\",\n name: \"External Service Adapters & Wrappers\",\n description: \"Standardized adapter and wrapper architecture for external services (payment gateways, emails, SMS, cloud storage)\",\n dependencies: [],\n directoryName: \"external-service-adapters\",\n },\n {\n id: \"storage-file-adapters\",\n name: \"Storage & File Adapters (S3, R2, Supabase)\",\n description: \"Standardized wrapper & adapter architecture for object storage, uploads, presigned URLs, and streaming without repositories\",\n dependencies: [],\n directoryName: \"storage-file-adapters\",\n },\n {\n id: \"auth-rbac-policies\",\n name: \"Auth Adapters & RBAC/ABAC Policies\",\n description: \"Authentication adapter architecture and pure domain authorization policies (RBAC/ABAC) with AuthenticatedActor contract\",\n dependencies: [],\n directoryName: \"auth-rbac-policies\",\n },\n {\n id: \"controller-orchestration-queues\",\n name: \"Controller Orchestration & Queue Adapters\",\n description: \"Strict orchestration rules for Controllers, atomic Actions, DB Transactions, and background Queue Adapters (Cloudflare, BullMQ, SQS)\",\n dependencies: [],\n directoryName: \"controller-orchestration-queues\",\n },\n {\n id: \"webhook-idempotency\",\n name: \"Webhook Verifiers & Idempotency Guards\",\n description: \"Incoming webhook HMAC verification adapters and atomic idempotency guards guaranteeing at-most-once processing\",\n dependencies: [],\n directoryName: \"webhook-idempotency\",\n },\n {\n id: \"caching-rate-limiting\",\n name: \"Cache-Aside & Rate Limiting Adapters\",\n description: \"Cache-aside remember wrapper and interchangeable sliding-window rate limiter adapters (Redis, Cloudflare KV, In-Memory)\",\n dependencies: [],\n directoryName: \"caching-rate-limiting\",\n },\n {\n id: \"env-feature-flags\",\n name: \"Fail-Fast Env & Feature Flags Adapters\",\n description: \"Fail-fast environment schema validation with Valibot and decoupled feature flags adapters (PostHog, LaunchDarkly, Unleash)\",\n dependencies: [],\n directoryName: \"env-feature-flags\",\n },\n {\n id: \"testing-vitest\",\n name: \"Vitest Testing Standards\",\n description: \"Clean unit and integration testing with Vitest: AAA pattern, behavioral testing over mocks, and boundary edge cases\",\n dependencies: [\"vitest\"],\n directoryName: \"testing-vitest\",\n },\n {\n id: \"hono\",\n name: \"Hono Architecture (Valibot)\",\n description: \"Enterprise Hono API standard with Valibot validation, isolated Actions layer, and RPC bindings\",\n dependencies: [\"hono\", \"@hono/valibot-validator\", \"@hono/standard-validator\"],\n directoryName: \"hono\",\n },\n {\n id: \"react-core\",\n name: \"React Core Fundamentals\",\n description: \"Opinionated React fundamentals: function components, JSX, immutable state, core hooks, lists, and controlled inputs\",\n dependencies: [\"react\", \"react-dom\"],\n directoryName: \"react-core\",\n },\n {\n id: \"react-advanced\",\n name: \"React 19 Advanced & Compiler Architecture\",\n description: \"Modern React 19 platform features: React Compiler auto-memoization, concurrent rendering, use(), Actions, virtualization, and RSC boundaries\",\n dependencies: [\"react\", \"react-dom\"],\n directoryName: \"react-advanced\",\n },\n {\n id: \"react-create-page\",\n name: \"React Page & View Architecture\",\n description: \"Clean architecture for React pages: declarative page coordinators, domain hooks, isolated API actions, Valibot + Formisch forms, and atomic co-location\",\n dependencies: [\"react\", \"react-dom\"],\n directoryName: \"react-create-page\",\n },\n];\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { renderBanner } from \"@/domains/ui/banners\";\nimport { promptSkills } from \"@/domains/ui/prompt-skills\";\nimport { promptAgents } from \"@/domains/ui/prompt-agents\";\nimport { promptLanguage } from \"@/domains/ui/prompt-language\";\nimport { promptConfirmOverwrite } from \"@/domains/ui/prompt-confirm-overwrite\";\nimport { verifySkillExists } from \"@/domains/installer/verify-skill-exists\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport { formatOnboardingPrompt } from \"@/domains/ui/render-onboarding-prompt\";\nimport { InstallTransactionError } from \"@/errors/install-transaction-error\";\nimport type { ProjectContext } from \"@/types/context.types\";\nimport type { AgentId } from \"@/types/agent.types\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\nasync function resolveLanguageSelection(\n harnessExists: boolean,\n configuredLanguage?: ProjectLanguage,\n forceOnboarding?: boolean\n): Promise<ProjectLanguage> {\n if (harnessExists && !forceOnboarding) {\n return configuredLanguage ?? \"es\";\n }\n\n const langChoice = await promptLanguage(configuredLanguage ?? \"es\");\n if (p.isCancel(langChoice)) {\n p.cancel(\"Instalación cancelada. ¡Que tengas un excelente día!\");\n process.exit(0);\n }\n\n return langChoice as ProjectLanguage;\n}\n\nasync function resolveOverwriteConfirmation(\n targetPath: string,\n selectedSkills: string[],\n selectedAgents: AgentId[]\n): Promise<boolean> {\n const anyExists = selectedSkills.some((skillId) => {\n const meta = SKILL_CATALOG.find((s) => s.id === skillId);\n return meta ? verifySkillExists(targetPath, meta.directoryName, selectedAgents) : false;\n });\n\n if (!anyExists) {\n return true;\n }\n\n const confirm = await promptConfirmOverwrite();\n if (p.isCancel(confirm) || !confirm) {\n p.cancel(\"Instalación detenida para proteger las skills existentes.\");\n process.exit(0);\n }\n\n return Boolean(confirm);\n}\n\nfunction renderInstallFailure(error: InstallTransactionError): void {\n const { stage, causeError, rollbackReport, suggestedFix } = error;\n const rawMsg = causeError instanceof Error ? causeError.message : String(causeError);\n\n const lines: string[] = [\n `${pc.bold(\"Fase afectada:\")} ${pc.yellow(stage)}`,\n `${pc.bold(\"Causa:\")} ${pc.red(rawMsg)}`,\n \"\",\n pc.bold(\"Reporte de Rollback automático:\"),\n ` • Archivos restaurados a su estado previo: ${pc.cyan(String(rollbackReport.restoredFiles.length))}`,\n ` • Archivos temporales eliminados: ${pc.cyan(String(rollbackReport.removedFiles.length))}`,\n ` • Directorios vacíos eliminados: ${pc.cyan(String(rollbackReport.removedDirs.length))}`,\n ];\n\n if (suggestedFix) {\n lines.push(\n \"\",\n pc.bold(\"Solución recomendada:\"),\n ` Ejecuta en tu terminal: ${pc.green(suggestedFix)}`\n );\n }\n\n p.note(lines.join(\"\\n\"), \"Detalles de la interrupción y reversión\");\n p.outro(pc.yellow(\"Tu proyecto no sufrió alteraciones y se preservó intacto. Corrige la causa y vuelve a intentarlo cuando gustes.\"));\n}\n\nexport async function runInteractiveUi(\n context: ProjectContext,\n forceOnboarding: boolean = false\n): Promise<void> {\n console.log(renderBanner());\n p.intro(pc.magenta(\"¡Bienvenido a GrooveSkills! Configuremos tus agentes de IA con estándares limpios de arquitectura.\"));\n\n if (context.detectedDependencies.length > 0) {\n const harnessInfo = context.harnessExists && !forceOnboarding\n ? pc.green(`Activo (.grooveskills/memory, idioma: ${context.configuredLanguage ?? \"es\"})`)\n : pc.cyan(\"Será inicializado\");\n\n p.note(\n `Dependencias detectadas: ${context.detectedDependencies.map((d) => pc.bold(d)).join(\", \")}\\n` +\n `Carpetas de IA activas: ${context.detectedAgents.map((a) => pc.green(a)).join(\", \") || \"Ninguna (se crearán)\"}\\n` +\n `GrooveSkills Harness: ${harnessInfo}`,\n \"Entorno del Proyecto\"\n );\n }\n\n const selectedSkills = await promptSkills(context.suggestedSkillIds);\n if (p.isCancel(selectedSkills)) {\n p.cancel(\"Instalación cancelada. ¡Que tengas un excelente día!\");\n process.exit(0);\n }\n\n const selectedAgents = await promptAgents(context.detectedAgents);\n if (p.isCancel(selectedAgents)) {\n p.cancel(\"Instalación cancelada. ¡Que tengas un excelente día!\");\n process.exit(0);\n }\n\n const selectedLanguage = await resolveLanguageSelection(\n context.harnessExists,\n context.configuredLanguage,\n forceOnboarding\n );\n\n const forceOverwrite = await resolveOverwriteConfirmation(\n context.targetPath,\n selectedSkills as string[],\n selectedAgents as AgentId[]\n );\n\n const s = p.spinner();\n s.start(\"Instalando y adaptando skills para tus agentes de IA configurados...\");\n\n try {\n const result = await installSkills({\n targetPath: context.targetPath,\n selectedSkillIds: selectedSkills as string[],\n selectedAgents: selectedAgents as AgentId[],\n forceOverwrite,\n enableHarness: true,\n detectedDependencies: context.detectedDependencies,\n language: selectedLanguage,\n forceOnboarding,\n });\n\n s.stop(pc.green(\"¡Todas las skills y el harness fueron configurados exitosamente!\"));\n\n const harnessStatus = result.harnessInitialized\n ? pc.green(`Inicializado en .grooveskills/ (Idioma: ${selectedLanguage})`)\n : pc.cyan(`Preservado en .grooveskills/ (Idioma: ${selectedLanguage})`);\n\n p.note(\n `Skills configuradas: ${result.installedSkills.map((sk) => pc.bold(sk)).join(\", \")}\\n` +\n `Agentes objetivo: ${result.configuredAgents.map((a) => pc.cyan(a)).join(\", \")}\\n` +\n `GrooveSkills Harness: ${harnessStatus}`,\n \"Resumen de Instalación\"\n );\n\n if (result.harnessInitialized) {\n const promptRender = formatOnboardingPrompt(selectedLanguage);\n p.note(\n pc.green(promptRender.prompt),\n promptRender.title\n );\n }\n\n p.outro(pc.green(\"¡Tus agentes de IA ahora están potenciados con los hábitos arquitectónicos de tu equipo! 🚀\"));\n } catch (error) {\n s.stop(pc.yellow(\"La instalación no pudo completarse.\"));\n\n if (error instanceof InstallTransactionError) {\n renderInstallFailure(error);\n return;\n }\n\n throw error;\n }\n}\n","import pc from \"picocolors\";\n\nexport function renderBanner(): string {\n const title = pc.bold(pc.white(\" GROOVE SKILLS \"));\n const badge = pc.bgMagenta(pc.black(title));\n const subtitle = pc.dim(\"Multi-Agent AI Skills & Architectural Standards\");\n\n return `${badge} ${subtitle}\\n`;\n}\n","import * as p from \"@clack/prompts\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\n\nexport async function promptSkills(suggestedSkillIds: string[]): Promise<string[] | symbol> {\n const selectableSkills = SKILL_CATALOG.filter((skill) => !skill.isCoreHarness);\n const options = selectableSkills.map((skill) => {\n const isSuggested = suggestedSkillIds.includes(skill.id);\n return {\n value: skill.id,\n label: skill.name,\n hint: isSuggested ? \"Suggested based on your project stack\" : skill.description,\n };\n });\n\n const selected = await p.multiselect({\n message: \"Which skills would you like to install in this project?\",\n options,\n initialValues: suggestedSkillIds,\n required: true,\n });\n\n return selected;\n}\n","import * as p from \"@clack/prompts\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport async function promptAgents(detectedAgents: AgentId[]): Promise<AgentId[] | symbol> {\n const options: Array<{ value: AgentId; label: string; hint: string }> = [\n { value: \"antigravity\", label: \"Antigravity\", hint: \".agents/skills (Google Agentic IDE)\" },\n { value: \"claude\", label: \"Claude Code\", hint: \".claude/skills (Anthropic Claude Code)\" },\n { value: \"cursor\", label: \"Cursor\", hint: \".cursor/rules/*.mdc (Cursor IDE Rules)\" },\n { value: \"gemini\", label: \"Gemini Code Assist\", hint: \".gemini/skills (Google Gemini)\" },\n ];\n\n const initialValues: AgentId[] = detectedAgents.length > 0 ? detectedAgents : [\"antigravity\"];\n\n const selected = await p.multiselect({\n message: \"Which AI agents should be configured?\",\n options,\n initialValues,\n required: true,\n });\n\n return selected as AgentId[] | symbol;\n}\n","import * as p from \"@clack/prompts\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\nexport async function promptLanguage(defaultLanguage: ProjectLanguage = \"es\"): Promise<ProjectLanguage | symbol> {\n const options = [\n { value: \"es\", label: \"Español (Spanish)\", hint: \"Recomendado para proyectos en español\" },\n { value: \"en\", label: \"English\", hint: \"Standard international English\" },\n { value: \"pt\", label: \"Português (Portuguese)\", hint: \"Português para o Brasil e Portugal\" },\n { value: \"it\", label: \"Italiano (Italian)\", hint: \"Comunicazione in lingua italiana\" },\n { value: \"fr\", label: \"Français (French)\", hint: \"Communication en langue française\" },\n ];\n\n const selected = await p.select({\n message: \"Which language should AI agents use for user-facing copy and communication?\",\n options,\n initialValue: defaultLanguage,\n });\n\n return selected as ProjectLanguage | symbol;\n}\n","import * as p from \"@clack/prompts\";\n\nexport async function promptConfirmOverwrite(): Promise<boolean | symbol> {\n return await p.confirm({\n message: \"Some skills already exist in this project. Would you like to overwrite them with the latest version?\",\n initialValue: true,\n });\n}\n","import { lstatSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst AGENT_DESTINATION_MAP: Record<AgentId, (dir: string) => string> = {\n antigravity: (dir) => join(\".agents\", \"skills\", dir),\n claude: (dir) => join(\".claude\", \"skills\", dir),\n cursor: (dir) => join(\".cursor\", \"rules\", `${dir}.mdc`),\n gemini: (dir) => join(\".gemini\", \"skills\", dir),\n};\n\nexport function verifySkillExists(\n targetPath: string,\n skillDirectoryName: string,\n agents: AgentId[]\n): boolean {\n for (const agent of agents) {\n const relativePathResolver = AGENT_DESTINATION_MAP[agent];\n const destination = join(targetPath, relativePathResolver(skillDirectoryName));\n\n try {\n lstatSync(destination);\n return true;\n } catch {\n // Path does not exist\n }\n }\n\n return false;\n}\n","import { join } from \"node:path\";\nimport { AntigravityAdapter } from \"@/domains/adapters/antigravity.adapter\";\nimport { ClaudeAdapter } from \"@/domains/adapters/claude.adapter\";\nimport { CursorAdapter } from \"@/domains/adapters/cursor.adapter\";\nimport { GeminiAdapter } from \"@/domains/adapters/gemini.adapter\";\nimport { syncProjectStore } from \"@/domains/project-store/sync-project-store\";\nimport { getProjectSkillsDir } from \"@/domains/project-store/project-paths\";\nimport { installHarness } from \"@/domains/harness/install-harness\";\nimport { writeProjectConfig } from \"@/domains/harness/write-project-config\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport { InstallTransaction } from \"@/domains/fs/install-transaction\";\nimport { InstallTransactionError } from \"@/errors/install-transaction-error\";\nimport { FilePermissionError } from \"@/errors/file-permission-error\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { InstallOptions, InstallResult } from \"@/types/installer.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst ADAPTER_REGISTRY: Record<AgentId, AgentAdapter> = {\n antigravity: new AntigravityAdapter(),\n claude: new ClaudeAdapter(),\n cursor: new CursorAdapter(),\n gemini: new GeminiAdapter(),\n};\n\nfunction formatSuggestedFix(cause: unknown): string | undefined {\n if (cause instanceof FilePermissionError) {\n return cause.suggestedFixCommand;\n }\n const err = cause as NodeJS.ErrnoException;\n if (err?.code === \"EACCES\" || err?.code === \"EPERM\") {\n if (err.path) {\n return `chmod u+w \"${err.path}\"`;\n }\n }\n return undefined;\n}\n\nexport async function installSkills(options: InstallOptions): Promise<InstallResult> {\n const transaction = new InstallTransaction();\n const skillsToInstall = [...options.selectedSkillIds];\n\n if (!skillsToInstall.includes(\"groove-harness\")) {\n skillsToInstall.push(\"groove-harness\");\n }\n\n if (!skillsToInstall.includes(\"odd-ai\")) {\n skillsToInstall.push(\"odd-ai\");\n }\n\n let currentStage = \"Sincronización del almacén de skills (.grooveskills/skills)\";\n try {\n syncProjectStore(options.targetPath, skillsToInstall, options.selectedAgents, transaction);\n\n const projectSkillsDir = getProjectSkillsDir(options.targetPath);\n const createdFiles: string[] = [];\n\n currentStage = \"Configuración de referencias de agentes (.agents, .claude, etc.)\";\n for (const skillId of skillsToInstall) {\n const skill = SKILL_CATALOG.find((item) => item.id === skillId);\n if (!skill) {\n continue;\n }\n\n const skillSourceDir = join(projectSkillsDir, skill.directoryName);\n\n for (const agentId of options.selectedAgents) {\n const adapter = ADAPTER_REGISTRY[agentId];\n if (!adapter) {\n continue;\n }\n\n const files = await adapter.installSkill(\n options.targetPath,\n skill,\n skillSourceDir,\n transaction\n );\n createdFiles.push(...files);\n }\n }\n\n currentStage = \"Instalación del Groove Harness (contexto, decisiones, tareas e instrucciones)\";\n const harnessResult = installHarness({\n targetPath: options.targetPath,\n selectedAgents: options.selectedAgents,\n selectedSkillIds: skillsToInstall,\n detectedDependencies: options.detectedDependencies || [],\n language: options.language,\n forceOnboarding: options.forceOnboarding,\n transaction,\n });\n createdFiles.push(...harnessResult.createdFiles);\n\n currentStage = \"Persistencia de la configuración del proyecto (.grooveskills/config.json)\";\n const configPath = writeProjectConfig(\n options.targetPath,\n skillsToInstall,\n options.selectedAgents,\n true,\n options.language,\n transaction\n );\n createdFiles.push(configPath);\n\n return {\n installedSkills: skillsToInstall,\n configuredAgents: options.selectedAgents,\n createdFiles,\n harnessInitialized: harnessResult.onboardingInitialized,\n language: options.language,\n };\n } catch (cause) {\n const rollbackReport = transaction.rollback();\n const suggestedFix = formatSuggestedFix(cause);\n throw new InstallTransactionError({\n stage: currentStage,\n cause,\n rollbackReport,\n suggestedFix,\n });\n }\n}\n","import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, unlinkSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getProjectSkillsDir } from \"@/domains/project-store/project-paths\";\nimport { safeWriteFileSync } from \"@/domains/fs/safe-file-writer\";\nimport type { InstallTransaction } from \"@/domains/fs/install-transaction\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nfunction removeExistingPathSafely(path: string): void {\n const fileExists = existsSync(path);\n\n if (!fileExists) {\n try {\n const lstat = lstatSync(path);\n if (lstat.isSymbolicLink()) {\n unlinkSync(path);\n }\n } catch {\n // Ignored if file really does not exist\n }\n return;\n }\n\n try {\n const lstat = lstatSync(path);\n if (lstat.isSymbolicLink()) {\n unlinkSync(path);\n return;\n }\n\n if (lstat.isDirectory()) {\n rmSync(path, { recursive: true, force: true });\n return;\n }\n\n unlinkSync(path);\n } catch {\n // Graceful fallback\n }\n}\n\nfunction extractSkillDescription(canonicalSkillMdPath: string, fallback: string): string {\n if (!existsSync(canonicalSkillMdPath)) {\n return fallback;\n }\n\n try {\n const content = readFileSync(canonicalSkillMdPath, \"utf-8\");\n const match = content.match(/^description:\\s*(.+)$/m);\n const hasMatchedDesc = Boolean(match && match[1]);\n if (hasMatchedDesc && match?.[1]) {\n return match[1].trim();\n }\n } catch {\n // Use fallback on error\n }\n\n return fallback;\n}\n\nexport function writeAgentSkillReference(\n targetPath: string,\n agentRelativeSkillsDir: string,\n skill: SkillMetadata,\n transaction?: InstallTransaction\n): string {\n const agentSkillFolder = join(targetPath, agentRelativeSkillsDir, skill.directoryName);\n const targetFile = join(agentSkillFolder, \"SKILL.md\");\n if (transaction) {\n transaction.recordCreatedDir(join(targetPath, agentRelativeSkillsDir));\n transaction.recordCreatedDir(agentSkillFolder);\n transaction.recordBeforeWrite(targetFile);\n }\n\n removeExistingPathSafely(agentSkillFolder);\n\n mkdirSync(agentSkillFolder, { recursive: true });\n\n const canonicalSkillMd = join(getProjectSkillsDir(targetPath), skill.directoryName, \"SKILL.md\");\n const description = extractSkillDescription(canonicalSkillMd, skill.description);\n\n const referenceContent = `---\nname: ${skill.id}\ndescription: ${description}\n---\n\n# ${skill.name} — Skill Reference\n\nCanonical skill specification stored in \\`.grooveskills/\\`.\n\n- **Specification**: [\\`.grooveskills/skills/${skill.directoryName}/SKILL.md\\`](../../../.grooveskills/skills/${skill.directoryName}/SKILL.md)\n- **References & Templates**: \\`.grooveskills/skills/${skill.directoryName}/\\`\n\n> **Instruction**: Read \\`.grooveskills/skills/${skill.directoryName}/SKILL.md\\` before executing tasks matching this skill.\n`;\n\n safeWriteFileSync(targetFile, referenceContent);\n\n return targetFile;\n}\n\nexport function writeCursorRuleReference(\n targetPath: string,\n cursorRelativeRulesDir: string,\n skill: SkillMetadata,\n transaction?: InstallTransaction\n): string {\n const rulesDir = join(targetPath, cursorRelativeRulesDir);\n const targetFile = join(rulesDir, `${skill.id}.mdc`);\n if (transaction) {\n transaction.recordCreatedDir(rulesDir);\n transaction.recordBeforeWrite(targetFile);\n }\n if (!existsSync(rulesDir)) {\n mkdirSync(rulesDir, { recursive: true });\n }\n\n removeExistingPathSafely(targetFile);\n\n const canonicalSkillMd = join(getProjectSkillsDir(targetPath), skill.directoryName, \"SKILL.md\");\n const description = extractSkillDescription(canonicalSkillMd, skill.description);\n\n const referenceContent = `---\ndescription: ${description}\nglobs: [\"**/*\"]\nalwaysApply: false\n---\n\n# ${skill.name} — Rule Reference\n\nCanonical rule specification stored in \\`.grooveskills/\\`.\n\n- **Specification**: \\`.grooveskills/skills/${skill.directoryName}/SKILL.md\\`\n- **References & Templates**: \\`.grooveskills/skills/${skill.directoryName}/\\`\n\n> **Instruction**: Read \\`.grooveskills/skills/${skill.directoryName}/SKILL.md\\` before executing tasks matching this rule.\n`;\n\n safeWriteFileSync(targetFile, referenceContent);\n\n return targetFile;\n}\n","import { join } from \"node:path\";\n\nexport function getProjectStoreDir(targetPath: string): string {\n return join(targetPath, \".grooveskills\");\n}\n\nexport function getProjectSkillsDir(targetPath: string): string {\n return join(getProjectStoreDir(targetPath), \"skills\");\n}\n\nexport function getProjectMemoryDir(targetPath: string): string {\n return join(getProjectStoreDir(targetPath), \"memory\");\n}\n\nexport function getProjectTasksDir(targetPath: string): string {\n return join(getProjectMemoryDir(targetPath), \"tasks\");\n}\n\nexport function getProjectConfigPath(targetPath: string): string {\n return join(getProjectStoreDir(targetPath), \"config.json\");\n}\n","import { chmodSync, existsSync, writeFileSync } from \"node:fs\";\nimport { FilePermissionError } from \"@/errors/file-permission-error\";\n\nexport function safeWriteFileSync(filePath: string, content: string): void {\n try {\n writeFileSync(filePath, content, \"utf-8\");\n } catch (error: unknown) {\n const err = error as NodeJS.ErrnoException;\n if (err.code === \"EACCES\" || err.code === \"EPERM\") {\n if (existsSync(filePath)) {\n try {\n chmodSync(filePath, 0o644);\n writeFileSync(filePath, content, \"utf-8\");\n return;\n } catch {\n // Si chmod falla, lanzamos FilePermissionError abajo\n }\n }\n throw new FilePermissionError(filePath);\n }\n throw error;\n }\n}\n","export class FilePermissionError extends Error {\n readonly code = \"EACCES\";\n readonly filePath: string;\n readonly suggestedFixCommand: string;\n\n constructor(filePath: string) {\n super(`No tienes permisos de escritura para modificar '${filePath}'.`);\n this.name = \"FilePermissionError\";\n this.filePath = filePath;\n this.suggestedFixCommand = `chmod u+w \"${filePath}\"`;\n }\n}\n","import type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport { writeAgentSkillReference } from \"@/domains/adapters/skill-reference-builder\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class AntigravityAdapter implements AgentAdapter {\n readonly id = \"antigravity\" as const;\n readonly name = \"Antigravity\";\n readonly targetRelativeDir = \".agents/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string,\n transaction?: import(\"@/domains/fs/install-transaction\").InstallTransaction\n ): Promise<string[]> {\n const file = writeAgentSkillReference(targetPath, this.targetRelativeDir, skill, transaction);\n return [file];\n }\n}\n","import type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport { writeAgentSkillReference } from \"@/domains/adapters/skill-reference-builder\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class ClaudeAdapter implements AgentAdapter {\n readonly id = \"claude\" as const;\n readonly name = \"Claude Code\";\n readonly targetRelativeDir = \".claude/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string,\n transaction?: import(\"@/domains/fs/install-transaction\").InstallTransaction\n ): Promise<string[]> {\n const file = writeAgentSkillReference(targetPath, this.targetRelativeDir, skill, transaction);\n return [file];\n }\n}\n","import type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport { writeCursorRuleReference } from \"@/domains/adapters/skill-reference-builder\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class CursorAdapter implements AgentAdapter {\n readonly id = \"cursor\" as const;\n readonly name = \"Cursor\";\n readonly targetRelativeDir = \".cursor/rules\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string,\n transaction?: import(\"@/domains/fs/install-transaction\").InstallTransaction\n ): Promise<string[]> {\n const file = writeCursorRuleReference(targetPath, this.targetRelativeDir, skill, transaction);\n return [file];\n }\n}\n","import type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport { writeAgentSkillReference } from \"@/domains/adapters/skill-reference-builder\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class GeminiAdapter implements AgentAdapter {\n readonly id = \"gemini\" as const;\n readonly name = \"Gemini Code Assist\";\n readonly targetRelativeDir = \".gemini/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string,\n transaction?: import(\"@/domains/fs/install-transaction\").InstallTransaction\n ): Promise<string[]> {\n const file = writeAgentSkillReference(targetPath, this.targetRelativeDir, skill, transaction);\n return [file];\n }\n}\n","import { cpSync, existsSync, mkdirSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { resolveSkillsSourceRoot } from \"@/domains/installer/resolve-skills-source\";\nimport { getProjectSkillsDir } from \"@/domains/project-store/project-paths\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { InstallTransaction } from \"@/domains/fs/install-transaction\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport function syncProjectStore(\n targetPath: string,\n selectedSkillIds: string[],\n _selectedAgents: AgentId[],\n transaction?: InstallTransaction\n): void {\n const bundledSkillsDir = resolveSkillsSourceRoot();\n const projectSkillsDir = getProjectSkillsDir(targetPath);\n\n if (transaction) {\n transaction.recordCreatedDir(projectSkillsDir);\n }\n\n if (!existsSync(projectSkillsDir)) {\n mkdirSync(projectSkillsDir, { recursive: true });\n }\n\n // Clean legacy cursor-rules directory if it exists\n const legacyCursorRules = join(targetPath, \".grooveskills\", \"cursor-rules\");\n if (existsSync(legacyCursorRules)) {\n try {\n rmSync(legacyCursorRules, { recursive: true, force: true });\n } catch {\n // Ignore cleanup error\n }\n }\n\n for (const skillId of selectedSkillIds) {\n const skill = SKILL_CATALOG.find((item) => item.id === skillId);\n if (!skill) {\n continue;\n }\n\n const sourceSkillDir = join(bundledSkillsDir, skill.directoryName);\n const destSkillDir = join(projectSkillsDir, skill.directoryName);\n\n if (transaction) {\n transaction.recordCreatedDir(destSkillDir);\n }\n\n if (existsSync(sourceSkillDir)) {\n cpSync(sourceSkillDir, destSkillDir, { recursive: true });\n }\n }\n}\n","import { fileURLToPath } from \"node:url\";\nimport { dirname, resolve, join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\nexport function resolveSkillsSourceRoot(): string {\n const currentFilePath = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFilePath);\n\n // 1. From dist/ in published npm package or local build: dist/../skills\n const candidateFromDist = resolve(currentDir, \"../skills\");\n if (existsSync(candidateFromDist)) {\n return candidateFromDist;\n }\n\n // 2. From src/domains/installer/ during development: ../../../skills\n const candidateFromSrc = resolve(currentDir, \"../../../skills\");\n if (existsSync(candidateFromSrc)) {\n return candidateFromSrc;\n }\n\n // 3. Search upward for the package root containing a skills directory\n let searchDir = currentDir;\n for (let i = 0; i < 5; i++) {\n const candidate = join(searchDir, \"skills\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(searchDir);\n if (parent === searchDir) {\n break;\n }\n searchDir = parent;\n }\n\n throw new Error(\n `GrooveSkills internal error: Unable to locate bundled skills directory from ${currentDir}`\n );\n}\n","import { existsSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport {\n getProjectMemoryDir,\n getProjectTasksDir,\n} from \"@/domains/project-store/project-paths\";\nimport {\n buildContextTemplate,\n buildDecisionsTemplate,\n buildOnboardingTaskTemplate,\n buildTaskTemplate,\n} from \"@/domains/harness/harness-templates\";\nimport { scanProjectOnboarding } from \"@/domains/harness/scan-project-onboarding\";\nimport { upsertAgentInstructions } from \"@/domains/harness/upsert-agent-instructions\";\nimport { safeWriteFileSync } from \"@/domains/fs/safe-file-writer\";\nimport type {\n HarnessInstallOptions,\n HarnessInstallResult,\n} from \"@/types/harness.types\";\n\nexport function installHarness(options: HarnessInstallOptions): HarnessInstallResult {\n const memoryDir = getProjectMemoryDir(options.targetPath);\n const tasksDir = getProjectTasksDir(options.targetPath);\n const language = options.language ?? \"es\";\n const forceOnboarding = Boolean(options.forceOnboarding);\n const tx = options.transaction;\n\n if (tx) {\n tx.recordCreatedDir(memoryDir);\n tx.recordCreatedDir(tasksDir);\n }\n\n if (!existsSync(tasksDir)) {\n mkdirSync(tasksDir, { recursive: true });\n }\n\n const createdFiles: string[] = [];\n const contextPath = join(memoryDir, \"context.md\");\n const shouldWriteContext = !existsSync(contextPath) || forceOnboarding;\n\n if (shouldWriteContext) {\n if (tx) {\n tx.recordBeforeWrite(contextPath);\n }\n const profile = scanProjectOnboarding(options.targetPath);\n const contextContent = buildContextTemplate(\n options.detectedDependencies,\n language,\n profile\n );\n safeWriteFileSync(contextPath, contextContent);\n createdFiles.push(contextPath);\n\n const onboardingTaskPath = join(tasksDir, \"00-onboarding.md\");\n if (tx) {\n tx.recordBeforeWrite(onboardingTaskPath);\n }\n safeWriteFileSync(\n onboardingTaskPath,\n buildOnboardingTaskTemplate(profile.projectName)\n );\n createdFiles.push(onboardingTaskPath);\n }\n\n const decisionsPath = join(memoryDir, \"decisions.md\");\n if (!existsSync(decisionsPath)) {\n if (tx) {\n tx.recordBeforeWrite(decisionsPath);\n }\n safeWriteFileSync(decisionsPath, buildDecisionsTemplate(language));\n createdFiles.push(decisionsPath);\n }\n\n const templateTaskPath = join(tasksDir, \"_template.md\");\n if (!existsSync(templateTaskPath)) {\n if (tx) {\n tx.recordBeforeWrite(templateTaskPath);\n }\n safeWriteFileSync(templateTaskPath, buildTaskTemplate());\n createdFiles.push(templateTaskPath);\n }\n\n const instructions = upsertAgentInstructions(\n options.targetPath,\n options.selectedAgents,\n language,\n tx\n );\n createdFiles.push(...instructions);\n\n return {\n createdFiles,\n onboardingInitialized: shouldWriteContext,\n };\n}\n","import type { ProjectLanguage } from \"@/types/harness.types\";\n\nexport interface LanguageDefinition {\n code: ProjectLanguage;\n name: string;\n nativeName: string;\n instruction: string;\n onboardingPromptTitle: string;\n onboardingPrompt: string;\n}\n\nexport const SUPPORTED_LANGUAGES: Record<ProjectLanguage, LanguageDefinition> = {\n es: {\n code: \"es\",\n name: \"Spanish\",\n nativeName: \"Español\",\n instruction: \"Todos los mensajes, validaciones, errores, CTAs y comunicaciones con el usuario deben redactarse estrictamente en Español. El tono debe ser empático, amable, persuasivo y profesional.\",\n onboardingPromptTitle: \"Prompt de inicialización para tu Agente IA (Copia y pega en el chat):\",\n onboardingPrompt: \"Hola. Acabo de configurar GrooveSkills Harness en este proyecto. Por favor lee `.grooveskills/memory/tasks/00-onboarding.md`, `.grooveskills/memory/context.md` y las skills instaladas en `.agents/skills/`. Hazme preguntas interactivas paso a paso para detectar vacíos de arquitectura, aclarar objetivos y adaptar el proyecto a mis necesidades antes de continuar.\",\n },\n en: {\n code: \"en\",\n name: \"English\",\n nativeName: \"English\",\n instruction: \"All user-facing messages, form validations, errors, CTAs, and notifications must be written strictly in English. Tone must be empathetic, friendly, persuasive, and professional.\",\n onboardingPromptTitle: \"Initialization prompt for your AI Agent (Copy and paste into your chat):\",\n onboardingPrompt: \"Hello. I just configured GrooveSkills Harness in this project. Please review `.grooveskills/memory/tasks/00-onboarding.md`, `.grooveskills/memory/context.md`, and the skills installed in `.agents/skills/`. Ask me step-by-step interactive questions to identify architectural gaps, clarify priorities, and adapt the project to my needs before continuing.\",\n },\n pt: {\n code: \"pt\",\n name: \"Portuguese\",\n nativeName: \"Português\",\n instruction: \"Todas as mensagens, validações, erros, CTAs e comunicações voltadas para o usuário devem ser redigidas estritamente em Português. O tom deve ser empático, amigável, persuasivo e profissional.\",\n onboardingPromptTitle: \"Prompt de inicialização para o seu Agente de IA (Copie e cole no chat):\",\n onboardingPrompt: \"Olá. Acabei de configurar o GrooveSkills Harness neste projeto. Por favor leia `.grooveskills/memory/tasks/00-onboarding.md`, `.grooveskills/memory/context.md` e as skills instaladas em `.agents/skills/`. Faça-me perguntas interativas passo a passo para mapear lacunas de arquitetura, alinhar prioridades e adaptar o projeto às minhas necessidades antes de prosseguir.\",\n },\n it: {\n code: \"it\",\n name: \"Italian\",\n nativeName: \"Italiano\",\n instruction: \"Tutti i messaggi, le convalide, gli errori, i pulsanti/CTA e le comunicazioni rivolte all'utente devono essere scritti rigorosamente in Italiano. Il tono deve essere empatico, cordiale, persuasivo e professionale.\",\n onboardingPromptTitle: \"Prompt di inizializzazione per il tuo Agente AI (Copia e incolla nella chat):\",\n onboardingPrompt: \"Ciao. Ho appena configurato GrooveSkills Harness in questo progetto. Ti prego di leggere `.grooveskills/memory/tasks/00-onboarding.md`, `.grooveskills/memory/context.md` e le skills installate in `.agents/skills/`. Fammi domande interattive passo dopo passo per identificare lacune architetturali, allineare le priorità e adattare il progetto alle mie esigenze prima di continuare.\",\n },\n fr: {\n code: \"fr\",\n name: \"French\",\n nativeName: \"Français\",\n instruction: \"Tous les messages, validations, erreurs, boutons d'appel à l'action (CTA) et notifications destinés à l'utilisateur doivent être rédigés strictement en Français. Le ton doit être empathique, courtois, persuasif et professionnel.\",\n onboardingPromptTitle: \"Prompt d'initialisation pour votre Agent IA (Copiez et collez dans le chat) :\",\n onboardingPrompt: \"Bonjour. Je viens de configurer GrooveSkills Harness sur ce projet. Veuillez consulter `.grooveskills/memory/tasks/00-onboarding.md`, `.grooveskills/memory/context.md` et les skills installées dans `.agents/skills/`. Posez-moi des questions interactives étape par étape pour identifier les lacunes d'architecture, préciser les priorités et adapter le projet à mes besoins avant de continuer.\",\n },\n};\n","import type { ProjectLanguage } from \"@/types/harness.types\";\nimport { SUPPORTED_LANGUAGES } from \"@/domains/harness/harness-languages\";\nimport type { ProjectOnboardingProfile } from \"@/domains/harness/scan-project-onboarding\";\n\nexport function buildContextTemplate(\n detectedDependencies: string[],\n language: ProjectLanguage = \"es\",\n profile?: ProjectOnboardingProfile\n): string {\n const depsFormatted = detectedDependencies.length > 0\n ? detectedDependencies.map((d) => `- \\`${d}\\``).join(\"\\n\")\n : \"- (No external dependencies detected)\";\n\n const langConfig = SUPPORTED_LANGUAGES[language];\n const projectName = profile?.projectName ?? \"Project\";\n const pkgManager = profile?.packageManager ?? \"npm\";\n\n const commandLines: string[] = [];\n if (profile?.commands) {\n for (const [key, cmd] of Object.entries(profile.commands)) {\n commandLines.push(`- **${key}**: \\`${cmd}\\``);\n }\n }\n const commandsSection = commandLines.length > 0\n ? commandLines.join(\"\\n\")\n : `- Build: Refer to \\`package.json\\` scripts.\\n- Typecheck: Refer to TypeScript configuration.\\n- Tests: Refer to test runner configuration.`;\n\n const aliasLines: string[] = [];\n if (profile?.pathAliases) {\n for (const [alias, target] of Object.entries(profile.pathAliases)) {\n aliasLines.push(`- \\`${alias}\\` -> \\`${target}\\``);\n }\n }\n const aliasesSection = aliasLines.length > 0\n ? `\\n### Path Aliases\\n${aliasLines.join(\"\\n\")}\\n`\n : \"\";\n\n const dirLines: string[] = [];\n if (profile?.sourceDirectories && profile.sourceDirectories.length > 0) {\n for (const dir of profile.sourceDirectories) {\n dirLines.push(`- \\`${dir}/\\``);\n }\n }\n const dirsSection = dirLines.length > 0\n ? `\\n### Source Modules\\n${dirLines.join(\"\\n\")}\\n`\n : \"\";\n\n return `# Project Context & Architecture: ${projectName}\n\nThis file provides AI agents with instant architectural orientation for this project.\n\n## 1. Stack & Dependencies\n- **Package Manager**: \\`${pkgManager}\\`\n${depsFormatted}\n\n## 2. Directory Structure Conventions\n- Follow single-responsibility per file (<200 lines).\n- Maintain direct imports with path aliases; avoid barrel files.\n- Keep domain boundaries explicit and clean.\n${aliasesSection}${dirsSection}\n## 3. Communication & User Copy Language\n- **Configured Language**: ${langConfig.nativeName} (\\`${language}\\`).\n- **Policy**: ${langConfig.instruction}\n\n## 4. Essential Commands\n${commandsSection}\n`;\n}\n\nexport function buildDecisionsTemplate(language: ProjectLanguage = \"es\"): string {\n const now = new Date().toISOString().split(\"T\")[0];\n const langConfig = SUPPORTED_LANGUAGES[language];\n\n return `# Architecture Decision Records (ADR)\n\nAn append-only log of significant technical and architectural choices.\n\n| Date | Title | Decision | Reason & Consequences |\n| :--- | :--- | :--- | :--- |\n| ${now} | Adopt GrooveSkills Harness | Initialized \\`.grooveskills/\\` control plane with ODD | Clean, encapsulated agent memory, 3-lane ODD flow, and ${langConfig.nativeName} copy standard |\n`;\n}\n\nexport function buildOnboardingTaskTemplate(projectName: string = \"Project\"): string {\n const now = new Date().toISOString().split(\"T\")[0];\n\n return `---\nstatus: pending\ncreatedAt: ${now}\n---\n\n# 00 — Initial Project Onboarding & Architecture Exploration: ${projectName}\n\n## Outcome Hypothesis\nBy scanning dependencies, entry points, configuration manifests, and module layout, the AI agent will gain a verified architectural understanding of \\`${projectName}\\`, proven by filling out \\`.grooveskills/memory/context.md\\`, formulating interactive alignment questions with the user, and validating the essential build/typecheck commands.\n\n## Scope\n- In scope: Inspect project manifests, entry points, directory conventions, ask interactive alignment questions, and verify script execution.\n- Out of scope: Refactoring business logic or modifying functional code before alignment.\n\n## Checklist\n- [ ] Verify package manager and essential scripts (\\`build\\`, \\`test\\`, \\`typecheck\\`).\n- [ ] Map high-level module architecture and data flow in \\`.grooveskills/memory/context.md\\`.\n- [ ] Ask the user step-by-step interactive questions to clarify goals, domain scope, and adapt project conventions.\n- [ ] Document agreed technical decisions in \\`.grooveskills/memory/decisions.md\\`.\n- [ ] Verify test runner or static checks pass cleanly.\n- [ ] Switch status to \\`completed\\` once project context is fully verified.\n\n## Evidence\n- Observed command runs and outputs during the initial onboarding pass.\n- User answers to alignment questions captured in memory.\n\n## Next\n- Once onboarding is marked completed, proceed with domain tasks following the 3-lane ODD protocol.\n`;\n}\n\nexport function buildTaskTemplate(): string {\n return `---\nstatus: in-progress\ncreatedAt: \\${CURRENT_DATE}\n---\n\n# Feature / Task Title\n\n## Outcome Hypothesis\nDescribe the expected behavioral outcome:\nBy [Output / Technical Change], [Outcome / Verifiable Behavior] will occur, proven by [Evidence / Test / Build Command].\n\n## Scope\n- In scope:\n- Out of scope:\n\n## Checklist\n- [ ] Task 1: (Define expected observed proof)\n- [ ] Task 2: (Define expected observed proof)\n\n## Evidence\n- Observed test/typecheck/build commands or runtime outputs proving completion.\n\n## Next\n- Next concrete step if interrupted.\n`;\n}\n\nexport function buildAgentHarnessBlock(language: ProjectLanguage = \"es\"): string {\n const langConfig = SUPPORTED_LANGUAGES[language];\n\n return `<!-- grooveskills:harness:start -->\n# GrooveSkills Harness — Agent Rules & Memory\n\nThis project uses the **GrooveSkills Harness** located in \\`.grooveskills/\\`.\n\n## 1. Three-Lane ODD Protocol\n- **Onboarding Check**: If \\`.grooveskills/memory/tasks/00-onboarding.md\\` has \\`status: pending\\`, complete its checklist to enrich \\`context.md\\` and set its status to \\`completed\\`.\n- **Authorize & Explore**: Follow the 7-step ODD protocol (Authorize, Explore, Resolve, Classify, Track & Hypothesize, Execute, Verify).\n- **Lane 1 (Answer)**: Explanations, audits, or questions. Read-only; write zero code.\n- **Lane 2 (Task)**: Direct implementation. Declare Outcome Hypothesis and checklist in \\`.grooveskills/memory/tasks/<slug>.md\\`. Only check off tasks with observed evidence under \\`Evidence\\`.\n- **Lane 3 (Spec)**: Ambiguous or high-impact architecture. Clarify and validate the spec in \\`.grooveskills/memory/tasks/<slug>.md\\` before writing code.\n\n## 2. User Communication Language (${langConfig.nativeName})\n- **Language**: \\`${language}\\` (${langConfig.nativeName}).\n- **Requirement**: ${langConfig.instruction}\n\n## 3. Memory Locations\n- Architecture context: \\`.grooveskills/memory/context.md\\`\n- Technical decisions (ADR): \\`.grooveskills/memory/decisions.md\\`\n- Active tasks & evidence: \\`.grooveskills/memory/tasks/\\`\n<!-- grooveskills:harness:end -->`;\n}\n","import { existsSync, readdirSync, readFileSync } from \"node:fs\";\nimport { basename, join } from \"node:path\";\n\nexport interface ProjectOnboardingProfile {\n projectName: string;\n packageManager: string;\n commands: Record<string, string>;\n pathAliases: Record<string, string>;\n sourceDirectories: string[];\n}\n\nfunction detectProjectName(targetPath: string): string {\n const packageJsonPath = join(targetPath, \"package.json\");\n if (existsSync(packageJsonPath)) {\n try {\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as { name?: string };\n if (typeof parsed.name === \"string\" && parsed.name.trim().length > 0) {\n return parsed.name.trim();\n }\n } catch {\n // Fall through to other manifests\n }\n }\n\n const cargoPath = join(targetPath, \"Cargo.toml\");\n if (existsSync(cargoPath)) {\n try {\n const cargoRaw = readFileSync(cargoPath, \"utf-8\");\n const nameMatch = cargoRaw.match(/name\\s*=\\s*\"([^\"]+)\"/);\n if (nameMatch?.[1]) {\n return nameMatch[1];\n }\n } catch {\n // Fall through\n }\n }\n\n const pyprojectPath = join(targetPath, \"pyproject.toml\");\n if (existsSync(pyprojectPath)) {\n try {\n const pyRaw = readFileSync(pyprojectPath, \"utf-8\");\n const pyMatch = pyRaw.match(/name\\s*=\\s*\"([^\"]+)\"/);\n if (pyMatch?.[1]) {\n return pyMatch[1];\n }\n } catch {\n // Fall through\n }\n }\n\n return basename(targetPath) || \"project\";\n}\n\nfunction detectPackageManager(targetPath: string): string {\n if (existsSync(join(targetPath, \"pnpm-lock.yaml\"))) {\n return \"pnpm\";\n }\n if (existsSync(join(targetPath, \"bun.lockb\")) || existsSync(join(targetPath, \"bun.lock\"))) {\n return \"bun\";\n }\n if (existsSync(join(targetPath, \"yarn.lock\"))) {\n return \"yarn\";\n }\n if (existsSync(join(targetPath, \"package-lock.json\"))) {\n return \"npm\";\n }\n if (existsSync(join(targetPath, \"Cargo.lock\")) || existsSync(join(targetPath, \"Cargo.toml\"))) {\n return \"cargo\";\n }\n if (existsSync(join(targetPath, \"uv.lock\"))) {\n return \"uv\";\n }\n if (existsSync(join(targetPath, \"poetry.lock\"))) {\n return \"poetry\";\n }\n return \"npm\";\n}\n\nfunction detectCommands(targetPath: string, pkgManager: string): Record<string, string> {\n const packageJsonPath = join(targetPath, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return {};\n }\n\n try {\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as { scripts?: Record<string, string> };\n const scripts = parsed.scripts ?? {};\n const commands: Record<string, string> = {};\n\n const runner = pkgManager === \"npm\" ? \"npm run\" : pkgManager;\n\n if (scripts.build) {\n commands.build = `${runner} build`;\n }\n if (scripts[\"check-types\"]) {\n commands.typecheck = `${runner} check-types`;\n } else if (scripts.typecheck) {\n commands.typecheck = `${runner} typecheck`;\n } else if (scripts.tsc) {\n commands.typecheck = `${runner} tsc`;\n }\n\n if (scripts.test) {\n commands.test = `${runner} test`;\n }\n if (scripts.lint) {\n commands.lint = `${runner} lint`;\n }\n if (scripts.dev) {\n commands.dev = `${runner} dev`;\n }\n\n return commands;\n } catch {\n return {};\n }\n}\n\nfunction detectPathAliases(targetPath: string): Record<string, string> {\n const tsconfigPath = join(targetPath, \"tsconfig.json\");\n if (!existsSync(tsconfigPath)) {\n return {};\n }\n\n try {\n const raw = readFileSync(tsconfigPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n compilerOptions?: {\n paths?: Record<string, string[]>;\n };\n };\n const paths = parsed.compilerOptions?.paths ?? {};\n const aliases: Record<string, string> = {};\n\n for (const [key, targets] of Object.entries(paths)) {\n if (Array.isArray(targets) && typeof targets[0] === \"string\") {\n aliases[key] = targets[0];\n }\n }\n\n return aliases;\n } catch {\n return {};\n }\n}\n\nfunction detectSourceDirectories(targetPath: string): string[] {\n const srcPath = join(targetPath, \"src\");\n const scanTarget = existsSync(srcPath) ? srcPath : targetPath;\n\n try {\n const entries = readdirSync(scanTarget, { withFileTypes: true });\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => entry.name)\n .filter((name) => !name.startsWith(\".\") && name !== \"node_modules\" && name !== \"dist\");\n } catch {\n return [];\n }\n}\n\nexport function scanProjectOnboarding(targetPath: string): ProjectOnboardingProfile {\n const projectName = detectProjectName(targetPath);\n const packageManager = detectPackageManager(targetPath);\n const commands = detectCommands(targetPath, packageManager);\n const pathAliases = detectPathAliases(targetPath);\n const sourceDirectories = detectSourceDirectories(targetPath);\n\n return {\n projectName,\n packageManager,\n commands,\n pathAliases,\n sourceDirectories,\n };\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { buildAgentHarnessBlock } from \"@/domains/harness/harness-templates\";\nimport { safeWriteFileSync } from \"@/domains/fs/safe-file-writer\";\nimport type { InstallTransaction } from \"@/domains/fs/install-transaction\";\nimport type { AgentId } from \"@/types/agent.types\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\nconst START_MARKER = \"<!-- grooveskills:harness:start -->\";\nconst END_MARKER = \"<!-- grooveskills:harness:end -->\";\n\nfunction applyHarnessBlock(\n filePath: string,\n language: ProjectLanguage = \"es\",\n transaction?: InstallTransaction\n): void {\n if (transaction) {\n transaction.recordBeforeWrite(filePath);\n }\n\n const block = buildAgentHarnessBlock(language);\n\n if (!existsSync(filePath)) {\n safeWriteFileSync(filePath, `${block}\\n`);\n return;\n }\n\n const existingContent = readFileSync(filePath, \"utf-8\");\n\n if (existingContent.includes(START_MARKER) && existingContent.includes(END_MARKER)) {\n const regex = new RegExp(`${START_MARKER}[\\\\s\\\\S]*?${END_MARKER}`, \"g\");\n const updated = existingContent.replace(regex, block);\n safeWriteFileSync(filePath, updated);\n return;\n }\n\n const separator = existingContent.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n safeWriteFileSync(filePath, `${existingContent}${separator}${block}\\n`);\n}\n\nexport function upsertAgentInstructions(\n targetPath: string,\n selectedAgents: AgentId[],\n language: ProjectLanguage = \"es\",\n transaction?: InstallTransaction\n): string[] {\n const updatedFiles: string[] = [];\n\n const agentsMdPath = join(targetPath, \"AGENTS.md\");\n applyHarnessBlock(agentsMdPath, language, transaction);\n updatedFiles.push(agentsMdPath);\n\n if (selectedAgents.includes(\"claude\")) {\n const claudeMdPath = join(targetPath, \"CLAUDE.md\");\n applyHarnessBlock(claudeMdPath, language, transaction);\n updatedFiles.push(claudeMdPath);\n }\n\n return updatedFiles;\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { getProjectConfigPath } from \"@/domains/project-store/project-paths\";\nimport { safeWriteFileSync } from \"@/domains/fs/safe-file-writer\";\nimport type { InstallTransaction } from \"@/domains/fs/install-transaction\";\nimport type { GrooveSkillsConfig, ProjectLanguage } from \"@/types/harness.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\ninterface ParsedConfigState {\n skills: string[];\n agents: AgentId[];\n harness: boolean;\n language?: ProjectLanguage;\n}\n\nfunction readExistingConfig(configPath: string): ParsedConfigState {\n const fallback: ParsedConfigState = {\n skills: [],\n agents: [],\n harness: false,\n };\n\n if (!existsSync(configPath)) {\n return fallback;\n }\n\n try {\n const raw = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<GrooveSkillsConfig>;\n\n return {\n skills: Array.isArray(parsed.skills) ? parsed.skills : [],\n agents: Array.isArray(parsed.agents) ? parsed.agents : [],\n harness: typeof parsed.harness === \"boolean\" ? parsed.harness : false,\n language: typeof parsed.language === \"string\" ? (parsed.language as ProjectLanguage) : undefined,\n };\n } catch {\n return fallback;\n }\n}\n\nexport function writeProjectConfig(\n targetPath: string,\n newSkills: string[],\n newAgents: AgentId[],\n harnessEnabled: boolean,\n language?: ProjectLanguage,\n transaction?: InstallTransaction\n): string {\n const configPath = getProjectConfigPath(targetPath);\n if (transaction) {\n transaction.recordBeforeWrite(configPath);\n }\n\n const existing = readExistingConfig(configPath);\n\n const mergedSkills = Array.from(new Set([...existing.skills, ...newSkills]));\n const mergedAgents = Array.from(new Set([...existing.agents, ...newAgents]));\n const resolvedLanguage = language ?? existing.language ?? \"es\";\n const isHarnessActive = existing.harness || harnessEnabled;\n\n const config: GrooveSkillsConfig = {\n version: 1,\n harness: isHarnessActive,\n ...(isHarnessActive ? { language: resolvedLanguage } : {}),\n agents: mergedAgents,\n skills: mergedSkills,\n updatedAt: new Date().toISOString(),\n };\n\n safeWriteFileSync(configPath, `${JSON.stringify(config, null, 2)}\\n`);\n\n return configPath;\n}\n","import { existsSync, readdirSync, readFileSync, rmSync } from \"node:fs\";\nimport { safeWriteFileSync } from \"@/domains/fs/safe-file-writer\";\n\nexport interface RollbackReport {\n restoredFiles: string[];\n removedFiles: string[];\n removedDirs: string[];\n}\n\nexport class InstallTransaction {\n private originalFiles = new Map<string, string | null>();\n private createdDirs: string[] = [];\n\n recordBeforeWrite(filePath: string): void {\n if (this.originalFiles.has(filePath)) {\n return;\n }\n if (existsSync(filePath)) {\n try {\n this.originalFiles.set(filePath, readFileSync(filePath, \"utf-8\"));\n } catch {\n this.originalFiles.set(filePath, null);\n }\n } else {\n this.originalFiles.set(filePath, null);\n }\n }\n\n recordCreatedDir(dirPath: string): void {\n if (!existsSync(dirPath) && !this.createdDirs.includes(dirPath)) {\n this.createdDirs.push(dirPath);\n }\n }\n\n rollback(): RollbackReport {\n const restoredFiles: string[] = [];\n const removedFiles: string[] = [];\n const removedDirs: string[] = [];\n\n for (const [filePath, content] of this.originalFiles.entries()) {\n try {\n if (content === null) {\n if (existsSync(filePath)) {\n rmSync(filePath, { force: true });\n removedFiles.push(filePath);\n }\n } else {\n safeWriteFileSync(filePath, content);\n restoredFiles.push(filePath);\n }\n } catch {\n // Ignorar fallos individuales para maximizar la restauración del resto\n }\n }\n\n const sortedDirs = [...this.createdDirs].sort((a, b) => b.length - a.length);\n for (const dir of sortedDirs) {\n try {\n if (existsSync(dir) && readdirSync(dir).length === 0) {\n rmSync(dir, { recursive: true, force: true });\n removedDirs.push(dir);\n }\n } catch {\n // Ignorar si no se puede eliminar\n }\n }\n\n return { restoredFiles, removedFiles, removedDirs };\n }\n}\n","import type { RollbackReport } from \"@/domains/fs/install-transaction\";\n\nexport interface InstallTransactionErrorOptions {\n stage: string;\n cause: unknown;\n rollbackReport: RollbackReport;\n suggestedFix?: string;\n}\n\nexport class InstallTransactionError extends Error {\n readonly stage: string;\n readonly causeError: unknown;\n readonly rollbackReport: RollbackReport;\n readonly suggestedFix?: string;\n\n constructor(options: InstallTransactionErrorOptions) {\n const rawMessage =\n options.cause instanceof Error ? options.cause.message : String(options.cause);\n super(`Error durante la etapa '${options.stage}': ${rawMessage}`);\n this.name = \"InstallTransactionError\";\n this.stage = options.stage;\n this.causeError = options.cause;\n this.rollbackReport = options.rollbackReport;\n this.suggestedFix = options.suggestedFix;\n }\n}\n","import pc from \"picocolors\";\nimport { SUPPORTED_LANGUAGES } from \"@/domains/harness/harness-languages\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\nexport interface OnboardingPromptRender {\n title: string;\n prompt: string;\n formattedOutput: string;\n}\n\nexport function formatOnboardingPrompt(\n language: ProjectLanguage = \"es\"\n): OnboardingPromptRender {\n const langConfig = SUPPORTED_LANGUAGES[language] ?? SUPPORTED_LANGUAGES.es;\n const title = langConfig.onboardingPromptTitle;\n const prompt = langConfig.onboardingPrompt;\n\n const separator = pc.cyan(\"─\".repeat(60));\n const formattedOutput = [\n separator,\n pc.bold(pc.yellow(title)),\n \"\",\n pc.green(prompt),\n separator,\n ].join(\"\\n\");\n\n return {\n title,\n prompt,\n formattedOutput,\n };\n}\n","import { detectProjectContext } from \"@/domains/detector/project-detector\";\nimport { runInteractiveUi } from \"@/domains/ui/ui-orchestrator\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport { formatOnboardingPrompt } from \"@/domains/ui/render-onboarding-prompt\";\nimport type { AgentId } from \"@/types/agent.types\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\nexport interface CliOptions {\n skills?: string[];\n agents?: AgentId[];\n yes?: boolean;\n harness?: boolean;\n language?: ProjectLanguage;\n forceOnboarding?: boolean;\n}\n\nexport async function runGrooveSkills(options: CliOptions = {}): Promise<void> {\n const targetPath = process.cwd();\n const context = detectProjectContext(targetPath);\n\n const hasSkills = options.skills && options.skills.length > 0;\n const hasAgents = options.agents && options.agents.length > 0;\n const isDirectHarness = Boolean(options.harness) && hasAgents;\n const isDirectInit = Boolean(options.forceOnboarding) && hasAgents;\n\n if ((hasSkills && hasAgents) || isDirectHarness || isDirectInit) {\n const language = options.language ?? context.configuredLanguage ?? \"es\";\n const result = await installSkills({\n targetPath,\n selectedSkillIds: options.skills || [],\n selectedAgents: options.agents || [],\n forceOverwrite: Boolean(options.yes),\n enableHarness: true,\n detectedDependencies: context.detectedDependencies,\n language,\n forceOnboarding: options.forceOnboarding,\n });\n\n if (result.harnessInitialized) {\n const promptRender = formatOnboardingPrompt(language);\n console.log(`\\n${promptRender.formattedOutput}\\n`);\n }\n\n return;\n }\n\n await runInteractiveUi(context, Boolean(options.forceOnboarding));\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","join","existsSync","readFileSync","p","pc","p","p","p","join","join","existsSync","lstatSync","readFileSync","join","join","existsSync","existsSync","existsSync","lstatSync","readFileSync","join","existsSync","mkdirSync","rmSync","join","join","existsSync","existsSync","mkdirSync","join","rmSync","existsSync","mkdirSync","join","existsSync","readdirSync","readFileSync","join","existsSync","readFileSync","join","existsSync","readFileSync","join","existsSync","mkdirSync","join","existsSync","readFileSync","existsSync","readFileSync","existsSync","readdirSync","readFileSync","rmSync","existsSync","readFileSync","rmSync","readdirSync","join","pc","pc","confirm","pc"]}
package/dist/cli.js CHANGED
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ InstallTransactionError,
3
4
  runGrooveSkills
4
- } from "./chunk-PLMYUKGW.js";
5
+ } from "./chunk-E63GTCOE.js";
5
6
 
6
7
  // bin/cli.ts
7
8
  import { Command } from "commander";
9
+ import pc from "picocolors";
8
10
  var program = new Command();
9
- program.name("grooveskills").description("Multi-agent AI skills, ODD workflow, and persistent project harness installer").version("1.5.0").argument("[command]", "Optional command: use 'init' to initialize or re-run full project onboarding").option("-s, --skills <skills...>", "Specific skill IDs to install (e.g. odd-ai best-practices hono)").option("-a, --agents <agents...>", "Target AI agents (antigravity claude cursor gemini)").option("-y, --yes", "Automatically confirm overwrite of existing skills", false).option("-l, --language <lang>", "Project user copy language (es, en, pt, it, fr)").action(async (command, options) => {
11
+ program.name("grooveskills").description("Multi-agent AI skills, ODD workflow, and persistent project harness installer").version("1.7.0").argument("[command]", "Optional command: use 'init' to initialize or re-run full project onboarding").option("-s, --skills <skills...>", "Specific skill IDs to install (e.g. odd-ai best-practices hono)").option("-a, --agents <agents...>", "Target AI agents (antigravity claude cursor gemini)").option("-y, --yes", "Automatically confirm overwrite of existing skills", false).option("-l, --language <lang>", "Project user copy language (es, en, pt, it, fr)").action(async (command, options) => {
10
12
  try {
11
13
  const forceOnboarding = command === "init";
12
14
  await runGrooveSkills({
@@ -18,7 +20,25 @@ program.name("grooveskills").description("Multi-agent AI skills, ODD workflow, a
18
20
  forceOnboarding
19
21
  });
20
22
  } catch (error) {
21
- console.error("An unexpected error occurred while running GrooveSkills:", error);
23
+ if (error instanceof InstallTransactionError) {
24
+ const { stage, causeError, rollbackReport, suggestedFix } = error;
25
+ const rawMsg = causeError instanceof Error ? causeError.message : String(causeError);
26
+ console.error(pc.red(`
27
+ \u2716 La instalaci\xF3n se interrumpi\xF3 en la fase: ${stage}`));
28
+ console.error(pc.red(` Causa: ${rawMsg}`));
29
+ console.error(pc.yellow("\nReporte de Rollback autom\xE1tico:"));
30
+ console.error(` \u2022 Archivos restaurados a su estado previo: ${rollbackReport.restoredFiles.length}`);
31
+ console.error(` \u2022 Archivos temporales eliminados: ${rollbackReport.removedFiles.length}`);
32
+ console.error(` \u2022 Directorios vac\xEDos eliminados: ${rollbackReport.removedDirs.length}`);
33
+ if (suggestedFix) {
34
+ console.error(pc.green(`
35
+ Soluci\xF3n sugerida:
36
+ ${suggestedFix}`));
37
+ }
38
+ console.error(pc.dim("\nTu proyecto se preserv\xF3 intacto.\n"));
39
+ process.exit(1);
40
+ }
41
+ console.error(pc.red("Ocurri\xF3 un error inesperado al ejecutar GrooveSkills:"), error);
22
42
  process.exit(1);
23
43
  }
24
44
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../bin/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { runGrooveSkills } from \"@/main\";\nimport type { AgentId } from \"@/types/agent.types\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\ninterface CliRawOptions {\n skills?: string[];\n agents?: string[];\n yes?: boolean;\n language?: string;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"grooveskills\")\n .description(\"Multi-agent AI skills, ODD workflow, and persistent project harness installer\")\n .version(__VERSION__)\n .argument(\"[command]\", \"Optional command: use 'init' to initialize or re-run full project onboarding\")\n .option(\"-s, --skills <skills...>\", \"Specific skill IDs to install (e.g. odd-ai best-practices hono)\")\n .option(\"-a, --agents <agents...>\", \"Target AI agents (antigravity claude cursor gemini)\")\n .option(\"-y, --yes\", \"Automatically confirm overwrite of existing skills\", false)\n .option(\"-l, --language <lang>\", \"Project user copy language (es, en, pt, it, fr)\")\n .action(async (command: string | undefined, options: CliRawOptions) => {\n try {\n const forceOnboarding = command === \"init\";\n await runGrooveSkills({\n skills: options.skills,\n agents: options.agents as AgentId[] | undefined,\n yes: options.yes,\n harness: true,\n language: options.language as ProjectLanguage | undefined,\n forceOnboarding,\n });\n } catch (error) {\n console.error(\"An unexpected error occurred while running GrooveSkills:\", error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"],"mappings":";;;;;;AACA,SAAS,eAAe;AAYxB,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,cAAc,EACnB,YAAY,+EAA+E,EAC3F,QAAQ,OAAW,EACnB,SAAS,aAAa,8EAA8E,EACpG,OAAO,4BAA4B,iEAAiE,EACpG,OAAO,4BAA4B,qDAAqD,EACxF,OAAO,aAAa,sDAAsD,KAAK,EAC/E,OAAO,yBAAyB,iDAAiD,EACjF,OAAO,OAAO,SAA6B,YAA2B;AACrE,MAAI;AACF,UAAM,kBAAkB,YAAY;AACpC,UAAM,gBAAgB;AAAA,MACpB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,MACT,UAAU,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,4DAA4D,KAAK;AAC/E,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QAAQ,MAAM;","names":[]}
1
+ {"version":3,"sources":["../bin/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { runGrooveSkills } from \"@/main\";\nimport { InstallTransactionError } from \"@/errors/install-transaction-error\";\nimport type { AgentId } from \"@/types/agent.types\";\nimport type { ProjectLanguage } from \"@/types/harness.types\";\n\ninterface CliRawOptions {\n skills?: string[];\n agents?: string[];\n yes?: boolean;\n language?: string;\n}\n\nconst program = new Command();\n\nprogram\n .name(\"grooveskills\")\n .description(\"Multi-agent AI skills, ODD workflow, and persistent project harness installer\")\n .version(__VERSION__)\n .argument(\"[command]\", \"Optional command: use 'init' to initialize or re-run full project onboarding\")\n .option(\"-s, --skills <skills...>\", \"Specific skill IDs to install (e.g. odd-ai best-practices hono)\")\n .option(\"-a, --agents <agents...>\", \"Target AI agents (antigravity claude cursor gemini)\")\n .option(\"-y, --yes\", \"Automatically confirm overwrite of existing skills\", false)\n .option(\"-l, --language <lang>\", \"Project user copy language (es, en, pt, it, fr)\")\n .action(async (command: string | undefined, options: CliRawOptions) => {\n try {\n const forceOnboarding = command === \"init\";\n await runGrooveSkills({\n skills: options.skills,\n agents: options.agents as AgentId[] | undefined,\n yes: options.yes,\n harness: true,\n language: options.language as ProjectLanguage | undefined,\n forceOnboarding,\n });\n } catch (error) {\n if (error instanceof InstallTransactionError) {\n const { stage, causeError, rollbackReport, suggestedFix } = error;\n const rawMsg = causeError instanceof Error ? causeError.message : String(causeError);\n\n console.error(pc.red(`\\n✖ La instalación se interrumpió en la fase: ${stage}`));\n console.error(pc.red(` Causa: ${rawMsg}`));\n console.error(pc.yellow(\"\\nReporte de Rollback automático:\"));\n console.error(` • Archivos restaurados a su estado previo: ${rollbackReport.restoredFiles.length}`);\n console.error(` • Archivos temporales eliminados: ${rollbackReport.removedFiles.length}`);\n console.error(` • Directorios vacíos eliminados: ${rollbackReport.removedDirs.length}`);\n\n if (suggestedFix) {\n console.error(pc.green(`\\nSolución sugerida:\\n ${suggestedFix}`));\n }\n console.error(pc.dim(\"\\nTu proyecto se preservó intacto.\\n\"));\n process.exit(1);\n }\n\n console.error(pc.red(\"Ocurrió un error inesperado al ejecutar GrooveSkills:\"), error);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"],"mappings":";;;;;;;AACA,SAAS,eAAe;AACxB,OAAO,QAAQ;AAaf,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,cAAc,EACnB,YAAY,+EAA+E,EAC3F,QAAQ,OAAW,EACnB,SAAS,aAAa,8EAA8E,EACpG,OAAO,4BAA4B,iEAAiE,EACpG,OAAO,4BAA4B,qDAAqD,EACxF,OAAO,aAAa,sDAAsD,KAAK,EAC/E,OAAO,yBAAyB,iDAAiD,EACjF,OAAO,OAAO,SAA6B,YAA2B;AACrE,MAAI;AACF,UAAM,kBAAkB,YAAY;AACpC,UAAM,gBAAgB;AAAA,MACpB,QAAQ,QAAQ;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,KAAK,QAAQ;AAAA,MACb,SAAS;AAAA,MACT,UAAU,QAAQ;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH,SAAS,OAAO;AACd,QAAI,iBAAiB,yBAAyB;AAC5C,YAAM,EAAE,OAAO,YAAY,gBAAgB,aAAa,IAAI;AAC5D,YAAM,SAAS,sBAAsB,QAAQ,WAAW,UAAU,OAAO,UAAU;AAEnF,cAAQ,MAAM,GAAG,IAAI;AAAA,yDAAiD,KAAK,EAAE,CAAC;AAC9E,cAAQ,MAAM,GAAG,IAAI,YAAY,MAAM,EAAE,CAAC;AAC1C,cAAQ,MAAM,GAAG,OAAO,sCAAmC,CAAC;AAC5D,cAAQ,MAAM,oDAA+C,eAAe,cAAc,MAAM,EAAE;AAClG,cAAQ,MAAM,2CAAsC,eAAe,aAAa,MAAM,EAAE;AACxF,cAAQ,MAAM,6CAAqC,eAAe,YAAY,MAAM,EAAE;AAEtF,UAAI,cAAc;AAChB,gBAAQ,MAAM,GAAG,MAAM;AAAA;AAAA,IAA2B,YAAY,EAAE,CAAC;AAAA,MACnE;AACA,cAAQ,MAAM,GAAG,IAAI,yCAAsC,CAAC;AAC5D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,YAAQ,MAAM,GAAG,IAAI,0DAAuD,GAAG,KAAK;AACpF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF,CAAC;AAEH,QAAQ,MAAM;","names":[]}
package/dist/main.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runGrooveSkills
3
- } from "./chunk-PLMYUKGW.js";
3
+ } from "./chunk-E63GTCOE.js";
4
4
  export {
5
5
  runGrooveSkills
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3lineas/grooveskills",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "description": "Multi-agent CLI to install opinionated AI coding skills and architectural standards (Hono, React, Next.js, and more)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,8 @@
11
11
  "build": "tsup",
12
12
  "dev": "tsup --watch",
13
13
  "check-types": "tsc --noEmit",
14
- "prepublishOnly": "pnpm run check-types && pnpm run build"
14
+ "test": "tsup src/domains/fs/safe-fs.test.ts --format esm --out-dir dist-test && node dist-test/safe-fs.test.js && rm -rf dist-test",
15
+ "prepublishOnly": "pnpm run check-types && pnpm run test && pnpm run build"
15
16
  },
16
17
  "publishConfig": {
17
18
  "access": "public"
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: auth-rbac-policies
3
+ description: Standardized authentication adapter architecture and pure domain authorization policies (RBAC/ABAC). Replaces coupling to auth vendors (Supabase Auth, Clerk, Auth0, Lucia, JWT) with an AuthenticatedActor domain contract and isolated, pure boolean policy functions. TRIGGER when implementing login, session extraction, role-based access control, resource ownership checks, permission gates, or user token verification.
4
+ ---
5
+
6
+ # Authentication Adapters & Pure Authorization Policies (RBAC/ABAC)
7
+
8
+ Opinionated architectural standard decoupling authentication identity extraction (via vendor adapters) from authorization logic (via pure domain policy functions).
9
+
10
+ ---
11
+
12
+ ## 1. Architectural Distinction: AuthN vs. AuthZ
13
+
14
+ | Dimension | Authentication (AuthN) | Authorization (AuthZ) |
15
+ | :--- | :--- | :--- |
16
+ | **Question** | *Who is calling the system?* | *Is this actor permitted to perform this action on this resource?* |
17
+ | **Layer** | Infrastructure Adapter (`src/infrastructure/adapters/auth/`) | Pure Domain Policy (`src/domains/<domain>/policies/`) |
18
+ | **Mechanism** | JWT verify, Clerk/Supabase session token parser | Pure boolean logic: `(actor, resource) => boolean` |
19
+ | **Side Effects** | I/O, network tokens, crypto signature checks | Zero I/O, deterministic, 100% testable without mocks |
20
+
21
+ ---
22
+
23
+ ## 2. Standardized AuthenticatedActor Contract
24
+
25
+ ```ts
26
+ // src/domains/auth/authenticated-actor.ts
27
+ export interface AuthenticatedActor {
28
+ readonly id: string;
29
+ readonly role: "admin" | "member" | "viewer" | "guest";
30
+ readonly permissions: readonly string[];
31
+ readonly organizationId?: string;
32
+ }
33
+
34
+ export interface AuthAdapterPort {
35
+ authenticateBearerToken(headerValue?: string): Promise<AuthenticatedActor>;
36
+ }
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 3. Pure Authorization Policies (Zero Side Effects)
42
+
43
+ Policies must be standalone pure functions. Never instantiate an external database or call network APIs inside a policy.
44
+
45
+ ```ts
46
+ // src/domains/documents/policies/document.policy.ts
47
+ import type { AuthenticatedActor } from "@/domains/auth/authenticated-actor";
48
+
49
+ export interface DocumentResource {
50
+ id: string;
51
+ authorId: string;
52
+ organizationId: string;
53
+ isPublished: boolean;
54
+ }
55
+
56
+ export const DocumentPolicy = {
57
+ canView(actor: AuthenticatedActor, doc: DocumentResource): boolean {
58
+ if (actor.role === "admin") return true;
59
+ if (doc.isPublished && actor.organizationId === doc.organizationId) return true;
60
+ return actor.id === doc.authorId;
61
+ },
62
+
63
+ canEdit(actor: AuthenticatedActor, doc: DocumentResource): boolean {
64
+ if (actor.role === "admin") return true;
65
+ return actor.id === doc.authorId;
66
+ },
67
+
68
+ canDelete(actor: AuthenticatedActor, doc: DocumentResource): boolean {
69
+ return actor.role === "admin" || actor.id === doc.authorId;
70
+ },
71
+ };
72
+ ```
73
+
74
+ ---
75
+
76
+ ## 4. Enforcement in Actions or Route Middleware
77
+
78
+ ```ts
79
+ import { AppError } from "@/errors/app-error";
80
+ import { DocumentPolicy, type DocumentResource } from "@/domains/documents/policies/document.policy";
81
+ import type { AuthenticatedActor } from "@/domains/auth/authenticated-actor";
82
+
83
+ export function authorizeOrThrow(actor: AuthenticatedActor, resource: DocumentResource): void {
84
+ const allowed = DocumentPolicy.canEdit(actor, resource);
85
+ if (!allowed) {
86
+ throw new AppError({
87
+ message: "No tienes permiso para modificar este documento.",
88
+ statusCode: 403,
89
+ context: { actorId: actor.id, docId: resource.id },
90
+ });
91
+ }
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## 5. Detailed Adapters Reference
98
+
99
+ For real implementations of Supabase Auth, Clerk, Custom JWT, and In-Memory testing actors, see:
100
+ - `references/auth-adapters-examples.md`
@@ -0,0 +1,99 @@
1
+ # Implementation Reference: Auth Adapters & Policies
2
+
3
+ Real adapter implementations (Clerk, Supabase, JWT) converting provider-specific tokens into `AuthenticatedActor`.
4
+
5
+ ---
6
+
7
+ ## 1. Clerk Authentication Adapter (`@clerk/backend`)
8
+
9
+ ```ts
10
+ // src/infrastructure/adapters/auth/clerk-auth.adapter.ts
11
+ import { verifyToken } from "@clerk/backend";
12
+ import type { AuthAdapterPort, AuthenticatedActor } from "@/domains/auth/authenticated-actor";
13
+ import { AppError } from "@/errors/app-error";
14
+
15
+ export class ClerkAuthAdapter implements AuthAdapterPort {
16
+ constructor(private jwtKey: string) {}
17
+
18
+ async authenticateBearerToken(headerValue?: string): Promise<AuthenticatedActor> {
19
+ const token = headerValue?.replace(/^Bearer\s+/i, "");
20
+ if (!token) {
21
+ throw new AppError({ message: "Token de autorización requerido.", statusCode: 401 });
22
+ }
23
+
24
+ try {
25
+ const payload = await verifyToken(token, { jwtKey: this.jwtKey });
26
+ const role = (payload.metadata as { role?: "admin" | "member" })?.role ?? "member";
27
+ return {
28
+ id: payload.sub,
29
+ role,
30
+ permissions: (payload.permissions as string[]) ?? [],
31
+ organizationId: payload.org_id as string | undefined,
32
+ };
33
+ } catch (err) {
34
+ throw new AppError({ message: "Token de autorización inválido o expirado.", statusCode: 401, cause: err });
35
+ }
36
+ }
37
+ }
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 2. Supabase Auth Adapter (`@supabase/supabase-js`)
43
+
44
+ ```ts
45
+ // src/infrastructure/adapters/auth/supabase-auth.adapter.ts
46
+ import type { SupabaseClient } from "@supabase/supabase-js";
47
+ import type { AuthAdapterPort, AuthenticatedActor } from "@/domains/auth/authenticated-actor";
48
+ import { AppError } from "@/errors/app-error";
49
+
50
+ export class SupabaseAuthAdapter implements AuthAdapterPort {
51
+ constructor(private supabase: SupabaseClient) {}
52
+
53
+ async authenticateBearerToken(headerValue?: string): Promise<AuthenticatedActor> {
54
+ const token = headerValue?.replace(/^Bearer\s+/i, "");
55
+ if (!token) {
56
+ throw new AppError({ message: "Sesión requerida.", statusCode: 401 });
57
+ }
58
+
59
+ const { data: { user }, error } = await this.supabase.auth.getUser(token);
60
+ if (error || !user) {
61
+ throw new AppError({ message: "Sesión no válida o expirada.", statusCode: 401, cause: error });
62
+ }
63
+
64
+ const appRole = (user.app_metadata?.role as "admin" | "member") ?? "member";
65
+ return {
66
+ id: user.id,
67
+ role: appRole,
68
+ permissions: (user.app_metadata?.permissions as string[]) ?? [],
69
+ organizationId: user.app_metadata?.org_id as string | undefined,
70
+ };
71
+ }
72
+ }
73
+ ```
74
+
75
+ ---
76
+
77
+ ## 3. In-Memory Mock Adapter (Deterministic Testing)
78
+
79
+ ```ts
80
+ // src/infrastructure/adapters/auth/memory-auth.adapter.ts
81
+ import type { AuthAdapterPort, AuthenticatedActor } from "@/domains/auth/authenticated-actor";
82
+ import { AppError } from "@/errors/app-error";
83
+
84
+ export class MemoryAuthAdapter implements AuthAdapterPort {
85
+ private users = new Map<string, AuthenticatedActor>();
86
+
87
+ seedUser(token: string, actor: AuthenticatedActor): void {
88
+ this.users.set(token, actor);
89
+ }
90
+
91
+ async authenticateBearerToken(headerValue?: string): Promise<AuthenticatedActor> {
92
+ const token = headerValue?.replace(/^Bearer\s+/i, "");
93
+ if (!token) throw new AppError({ message: "Falta token.", statusCode: 401 });
94
+ const actor = this.users.get(token);
95
+ if (!actor) throw new AppError({ message: "Token inválido.", statusCode: 401 });
96
+ return actor;
97
+ }
98
+ }
99
+ ```