javi-forge 0.1.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.
- package/.gitignore.template +105 -0
- package/.releaserc +44 -0
- package/README.md +45 -0
- package/ai-config/.skillignore +15 -0
- package/ai-config/AUTO_INVOKE.md +300 -0
- package/ai-config/agents/_TEMPLATE.md +93 -0
- package/ai-config/agents/business/api-designer.md +1657 -0
- package/ai-config/agents/business/business-analyst.md +1331 -0
- package/ai-config/agents/business/product-strategist.md +206 -0
- package/ai-config/agents/business/project-manager.md +178 -0
- package/ai-config/agents/business/requirements-analyst.md +1277 -0
- package/ai-config/agents/business/technical-writer.md +1679 -0
- package/ai-config/agents/creative/ux-designer.md +205 -0
- package/ai-config/agents/data-ai/ai-engineer.md +487 -0
- package/ai-config/agents/data-ai/analytics-engineer.md +953 -0
- package/ai-config/agents/data-ai/data-engineer.md +173 -0
- package/ai-config/agents/data-ai/data-scientist.md +672 -0
- package/ai-config/agents/data-ai/mlops-engineer.md +814 -0
- package/ai-config/agents/data-ai/prompt-engineer.md +772 -0
- package/ai-config/agents/development/angular-expert.md +620 -0
- package/ai-config/agents/development/backend-architect.md +795 -0
- package/ai-config/agents/development/database-specialist.md +212 -0
- package/ai-config/agents/development/frontend-specialist.md +686 -0
- package/ai-config/agents/development/fullstack-engineer.md +668 -0
- package/ai-config/agents/development/golang-pro.md +338 -0
- package/ai-config/agents/development/java-enterprise.md +400 -0
- package/ai-config/agents/development/javascript-pro.md +422 -0
- package/ai-config/agents/development/nextjs-pro.md +474 -0
- package/ai-config/agents/development/python-pro.md +570 -0
- package/ai-config/agents/development/react-pro.md +487 -0
- package/ai-config/agents/development/rust-pro.md +246 -0
- package/ai-config/agents/development/spring-boot-4-expert.md +326 -0
- package/ai-config/agents/development/typescript-pro.md +336 -0
- package/ai-config/agents/development/vue-specialist.md +605 -0
- package/ai-config/agents/infrastructure/cloud-architect.md +472 -0
- package/ai-config/agents/infrastructure/deployment-manager.md +358 -0
- package/ai-config/agents/infrastructure/devops-engineer.md +455 -0
- package/ai-config/agents/infrastructure/incident-responder.md +519 -0
- package/ai-config/agents/infrastructure/kubernetes-expert.md +705 -0
- package/ai-config/agents/infrastructure/monitoring-specialist.md +674 -0
- package/ai-config/agents/infrastructure/performance-engineer.md +658 -0
- package/ai-config/agents/orchestrator.md +241 -0
- package/ai-config/agents/quality/accessibility-auditor.md +1204 -0
- package/ai-config/agents/quality/code-reviewer-compact.md +123 -0
- package/ai-config/agents/quality/code-reviewer.md +363 -0
- package/ai-config/agents/quality/dependency-manager.md +743 -0
- package/ai-config/agents/quality/e2e-test-specialist.md +1005 -0
- package/ai-config/agents/quality/performance-tester.md +1086 -0
- package/ai-config/agents/quality/security-auditor.md +133 -0
- package/ai-config/agents/quality/test-engineer.md +453 -0
- package/ai-config/agents/specialists/api-designer.md +87 -0
- package/ai-config/agents/specialists/backend-architect.md +73 -0
- package/ai-config/agents/specialists/code-reviewer.md +77 -0
- package/ai-config/agents/specialists/db-optimizer.md +75 -0
- package/ai-config/agents/specialists/devops-engineer.md +83 -0
- package/ai-config/agents/specialists/documentation-writer.md +78 -0
- package/ai-config/agents/specialists/frontend-developer.md +75 -0
- package/ai-config/agents/specialists/performance-analyst.md +82 -0
- package/ai-config/agents/specialists/refactor-specialist.md +74 -0
- package/ai-config/agents/specialists/security-auditor.md +74 -0
- package/ai-config/agents/specialists/test-engineer.md +81 -0
- package/ai-config/agents/specialists/ux-consultant.md +76 -0
- package/ai-config/agents/specialized/agent-generator.md +1190 -0
- package/ai-config/agents/specialized/blockchain-developer.md +149 -0
- package/ai-config/agents/specialized/code-migrator.md +892 -0
- package/ai-config/agents/specialized/context-manager.md +978 -0
- package/ai-config/agents/specialized/documentation-writer.md +1078 -0
- package/ai-config/agents/specialized/ecommerce-expert.md +1756 -0
- package/ai-config/agents/specialized/embedded-engineer.md +1714 -0
- package/ai-config/agents/specialized/error-detective.md +1034 -0
- package/ai-config/agents/specialized/fintech-specialist.md +1659 -0
- package/ai-config/agents/specialized/freelance-project-planner-v2.md +1988 -0
- package/ai-config/agents/specialized/freelance-project-planner-v3.md +2136 -0
- package/ai-config/agents/specialized/freelance-project-planner-v4.md +4503 -0
- package/ai-config/agents/specialized/freelance-project-planner.md +722 -0
- package/ai-config/agents/specialized/game-developer.md +1963 -0
- package/ai-config/agents/specialized/healthcare-dev.md +1620 -0
- package/ai-config/agents/specialized/mobile-developer.md +188 -0
- package/ai-config/agents/specialized/parallel-plan-executor.md +506 -0
- package/ai-config/agents/specialized/plan-executor.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/00-INDEX.md +485 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/01-CORE.md +3493 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/02-SELF-CORRECTION.md +778 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/03-PROGRESSIVE-SETUP.md +918 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/04-DEPLOYMENT.md +1537 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/05-TESTING.md +2633 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/06-OPERATIONS.md +5610 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/INSTALL.md +335 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/QUICK-REFERENCE.txt +215 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/README.md +260 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/START-HERE.md +379 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/WORKFLOW-DIAGRAM.md +355 -0
- package/ai-config/agents/specialized/solo-dev-planner-modular/solo-dev-planner.md +279 -0
- package/ai-config/agents/specialized/template-writer.md +347 -0
- package/ai-config/agents/specialized/test-runner.md +99 -0
- package/ai-config/agents/specialized/vibekanban-smart-worker.md +244 -0
- package/ai-config/agents/specialized/wave-executor.md +138 -0
- package/ai-config/agents/specialized/workflow-optimizer.md +1114 -0
- package/ai-config/commands/git/changelog.md +32 -0
- package/ai-config/commands/git/ci-local.md +70 -0
- package/ai-config/commands/git/commit.md +35 -0
- package/ai-config/commands/git/fix-issue.md +23 -0
- package/ai-config/commands/git/pr-create.md +42 -0
- package/ai-config/commands/git/pr-review.md +50 -0
- package/ai-config/commands/git/worktree.md +39 -0
- package/ai-config/commands/refactoring/cleanup.md +24 -0
- package/ai-config/commands/refactoring/dead-code.md +40 -0
- package/ai-config/commands/refactoring/extract.md +31 -0
- package/ai-config/commands/testing/e2e.md +30 -0
- package/ai-config/commands/testing/tdd.md +36 -0
- package/ai-config/commands/testing/test-coverage.md +30 -0
- package/ai-config/commands/testing/test-fix.md +24 -0
- package/ai-config/commands/workflow/generate-agents-md.md +85 -0
- package/ai-config/commands/workflow/planning.md +47 -0
- package/ai-config/commands/workflows/compound.md +89 -0
- package/ai-config/commands/workflows/plan.md +77 -0
- package/ai-config/commands/workflows/review.md +78 -0
- package/ai-config/commands/workflows/work.md +75 -0
- package/ai-config/config.yaml +18 -0
- package/ai-config/hooks/_TEMPLATE.md +96 -0
- package/ai-config/hooks/block-dangerous-commands.md +75 -0
- package/ai-config/hooks/commit-guard.md +90 -0
- package/ai-config/hooks/context-loader.md +73 -0
- package/ai-config/hooks/improve-prompt.md +91 -0
- package/ai-config/hooks/learning-log.md +72 -0
- package/ai-config/hooks/model-router.md +86 -0
- package/ai-config/hooks/secret-scanner.md +64 -0
- package/ai-config/hooks/skill-validator.md +102 -0
- package/ai-config/hooks/task-artifact.md +114 -0
- package/ai-config/hooks/validate-workflow.md +100 -0
- package/ai-config/prompts/base.md +71 -0
- package/ai-config/prompts/modes/debug.md +34 -0
- package/ai-config/prompts/modes/deploy.md +40 -0
- package/ai-config/prompts/modes/research.md +32 -0
- package/ai-config/prompts/modes/review.md +33 -0
- package/ai-config/prompts/review-policy.md +79 -0
- package/ai-config/skills/_TEMPLATE.md +157 -0
- package/ai-config/skills/backend/api-gateway/SKILL.md +254 -0
- package/ai-config/skills/backend/bff-concepts/SKILL.md +239 -0
- package/ai-config/skills/backend/bff-spring/SKILL.md +364 -0
- package/ai-config/skills/backend/chi-router/SKILL.md +396 -0
- package/ai-config/skills/backend/error-handling/SKILL.md +255 -0
- package/ai-config/skills/backend/exceptions-spring/SKILL.md +323 -0
- package/ai-config/skills/backend/fastapi/SKILL.md +302 -0
- package/ai-config/skills/backend/gateway-spring/SKILL.md +390 -0
- package/ai-config/skills/backend/go-backend/SKILL.md +457 -0
- package/ai-config/skills/backend/gradle-multimodule/SKILL.md +274 -0
- package/ai-config/skills/backend/graphql-concepts/SKILL.md +352 -0
- package/ai-config/skills/backend/graphql-spring/SKILL.md +398 -0
- package/ai-config/skills/backend/grpc-concepts/SKILL.md +283 -0
- package/ai-config/skills/backend/grpc-spring/SKILL.md +445 -0
- package/ai-config/skills/backend/jwt-auth/SKILL.md +412 -0
- package/ai-config/skills/backend/notifications-concepts/SKILL.md +259 -0
- package/ai-config/skills/backend/recommendations-concepts/SKILL.md +261 -0
- package/ai-config/skills/backend/search-concepts/SKILL.md +263 -0
- package/ai-config/skills/backend/search-spring/SKILL.md +375 -0
- package/ai-config/skills/backend/spring-boot-4/SKILL.md +172 -0
- package/ai-config/skills/backend/websockets/SKILL.md +532 -0
- package/ai-config/skills/data-ai/ai-ml/SKILL.md +423 -0
- package/ai-config/skills/data-ai/analytics-concepts/SKILL.md +195 -0
- package/ai-config/skills/data-ai/analytics-spring/SKILL.md +340 -0
- package/ai-config/skills/data-ai/duckdb-analytics/SKILL.md +440 -0
- package/ai-config/skills/data-ai/langchain/SKILL.md +238 -0
- package/ai-config/skills/data-ai/mlflow/SKILL.md +302 -0
- package/ai-config/skills/data-ai/onnx-inference/SKILL.md +290 -0
- package/ai-config/skills/data-ai/powerbi/SKILL.md +352 -0
- package/ai-config/skills/data-ai/pytorch/SKILL.md +274 -0
- package/ai-config/skills/data-ai/scikit-learn/SKILL.md +321 -0
- package/ai-config/skills/data-ai/vector-db/SKILL.md +301 -0
- package/ai-config/skills/database/graph-databases/SKILL.md +218 -0
- package/ai-config/skills/database/graph-spring/SKILL.md +361 -0
- package/ai-config/skills/database/pgx-postgres/SKILL.md +512 -0
- package/ai-config/skills/database/redis-cache/SKILL.md +343 -0
- package/ai-config/skills/database/sqlite-embedded/SKILL.md +388 -0
- package/ai-config/skills/database/timescaledb/SKILL.md +320 -0
- package/ai-config/skills/docs/api-documentation/SKILL.md +293 -0
- package/ai-config/skills/docs/docs-spring/SKILL.md +377 -0
- package/ai-config/skills/docs/mustache-templates/SKILL.md +190 -0
- package/ai-config/skills/docs/technical-docs/SKILL.md +447 -0
- package/ai-config/skills/frontend/astro-ssr/SKILL.md +441 -0
- package/ai-config/skills/frontend/frontend-design/SKILL.md +54 -0
- package/ai-config/skills/frontend/frontend-web/SKILL.md +368 -0
- package/ai-config/skills/frontend/mantine-ui/SKILL.md +396 -0
- package/ai-config/skills/frontend/tanstack-query/SKILL.md +439 -0
- package/ai-config/skills/frontend/zod-validation/SKILL.md +417 -0
- package/ai-config/skills/frontend/zustand-state/SKILL.md +350 -0
- package/ai-config/skills/infrastructure/chaos-engineering/SKILL.md +244 -0
- package/ai-config/skills/infrastructure/chaos-spring/SKILL.md +378 -0
- package/ai-config/skills/infrastructure/devops-infra/SKILL.md +435 -0
- package/ai-config/skills/infrastructure/docker-containers/SKILL.md +420 -0
- package/ai-config/skills/infrastructure/kubernetes/SKILL.md +456 -0
- package/ai-config/skills/infrastructure/opentelemetry/SKILL.md +546 -0
- package/ai-config/skills/infrastructure/traefik-proxy/SKILL.md +474 -0
- package/ai-config/skills/infrastructure/woodpecker-ci/SKILL.md +315 -0
- package/ai-config/skills/mobile/ionic-capacitor/SKILL.md +504 -0
- package/ai-config/skills/mobile/mobile-ionic/SKILL.md +448 -0
- package/ai-config/skills/prompt-improver/SKILL.md +125 -0
- package/ai-config/skills/quality/ghagga-review/SKILL.md +216 -0
- package/ai-config/skills/references/hooks-patterns/SKILL.md +238 -0
- package/ai-config/skills/references/mcp-servers/SKILL.md +275 -0
- package/ai-config/skills/references/plugins-reference/SKILL.md +110 -0
- package/ai-config/skills/references/skills-reference/SKILL.md +420 -0
- package/ai-config/skills/references/subagent-templates/SKILL.md +193 -0
- package/ai-config/skills/systems-iot/modbus-protocol/SKILL.md +410 -0
- package/ai-config/skills/systems-iot/mqtt-rumqttc/SKILL.md +408 -0
- package/ai-config/skills/systems-iot/rust-systems/SKILL.md +386 -0
- package/ai-config/skills/systems-iot/tokio-async/SKILL.md +324 -0
- package/ai-config/skills/testing/playwright-e2e/SKILL.md +289 -0
- package/ai-config/skills/testing/testcontainers/SKILL.md +299 -0
- package/ai-config/skills/testing/vitest-testing/SKILL.md +381 -0
- package/ai-config/skills/workflow/ci-local-guide/SKILL.md +118 -0
- package/ai-config/skills/workflow/claude-automation-recommender/SKILL.md +299 -0
- package/ai-config/skills/workflow/claude-md-improver/SKILL.md +158 -0
- package/ai-config/skills/workflow/finishing-a-development-branch/SKILL.md +117 -0
- package/ai-config/skills/workflow/git-github/SKILL.md +334 -0
- package/ai-config/skills/workflow/git-github/references/examples.md +160 -0
- package/ai-config/skills/workflow/git-workflow/SKILL.md +214 -0
- package/ai-config/skills/workflow/ide-plugins/SKILL.md +277 -0
- package/ai-config/skills/workflow/ide-plugins-intellij/SKILL.md +401 -0
- package/ai-config/skills/workflow/obsidian-brain-workflow/SKILL.md +199 -0
- package/ai-config/skills/workflow/using-git-worktrees/SKILL.md +100 -0
- package/ai-config/skills/workflow/verification-before-completion/SKILL.md +73 -0
- package/ai-config/skills/workflow/wave-workflow/SKILL.md +178 -0
- package/ci-local/README.md +170 -0
- package/ci-local/ci-local.sh +297 -0
- package/ci-local/hooks/commit-msg +74 -0
- package/ci-local/hooks/pre-commit +162 -0
- package/ci-local/hooks/pre-push +41 -0
- package/ci-local/install.sh +49 -0
- package/ci-local/semgrep.yml +214 -0
- package/dist/commands/analyze.d.ts +9 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +55 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/analyze.test.d.ts +2 -0
- package/dist/commands/analyze.test.d.ts.map +1 -0
- package/dist/commands/analyze.test.js +145 -0
- package/dist/commands/analyze.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +7 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +158 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +200 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +283 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/init.test.d.ts +2 -0
- package/dist/commands/init.test.d.ts.map +1 -0
- package/dist/commands/init.test.js +271 -0
- package/dist/commands/init.test.js.map +1 -0
- package/dist/commands/sync.d.ts +8 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +201 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +57 -0
- package/dist/constants.js.map +1 -0
- package/dist/e2e/aggressive.e2e.test.d.ts +2 -0
- package/dist/e2e/aggressive.e2e.test.d.ts.map +1 -0
- package/dist/e2e/aggressive.e2e.test.js +350 -0
- package/dist/e2e/aggressive.e2e.test.js.map +1 -0
- package/dist/e2e/commands.e2e.test.d.ts +2 -0
- package/dist/e2e/commands.e2e.test.d.ts.map +1 -0
- package/dist/e2e/commands.e2e.test.js +213 -0
- package/dist/e2e/commands.e2e.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/common.d.ts +17 -0
- package/dist/lib/common.d.ts.map +1 -0
- package/dist/lib/common.js +111 -0
- package/dist/lib/common.js.map +1 -0
- package/dist/lib/common.test.d.ts +2 -0
- package/dist/lib/common.test.d.ts.map +1 -0
- package/dist/lib/common.test.js +316 -0
- package/dist/lib/common.test.js.map +1 -0
- package/dist/lib/frontmatter.d.ts +18 -0
- package/dist/lib/frontmatter.d.ts.map +1 -0
- package/dist/lib/frontmatter.js +61 -0
- package/dist/lib/frontmatter.js.map +1 -0
- package/dist/lib/frontmatter.test.d.ts +2 -0
- package/dist/lib/frontmatter.test.d.ts.map +1 -0
- package/dist/lib/frontmatter.test.js +257 -0
- package/dist/lib/frontmatter.test.js.map +1 -0
- package/dist/lib/template.d.ts +24 -0
- package/dist/lib/template.d.ts.map +1 -0
- package/dist/lib/template.js +78 -0
- package/dist/lib/template.js.map +1 -0
- package/dist/lib/template.test.d.ts +2 -0
- package/dist/lib/template.test.d.ts.map +1 -0
- package/dist/lib/template.test.js +201 -0
- package/dist/lib/template.test.js.map +1 -0
- package/dist/types/index.d.ts +48 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/AnalyzeUI.d.ts +7 -0
- package/dist/ui/AnalyzeUI.d.ts.map +1 -0
- package/dist/ui/AnalyzeUI.js +100 -0
- package/dist/ui/AnalyzeUI.js.map +1 -0
- package/dist/ui/App.d.ts +13 -0
- package/dist/ui/App.d.ts.map +1 -0
- package/dist/ui/App.js +100 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/CIContext.d.ts +9 -0
- package/dist/ui/CIContext.d.ts.map +1 -0
- package/dist/ui/CIContext.js +9 -0
- package/dist/ui/CIContext.js.map +1 -0
- package/dist/ui/CISelector.d.ts +8 -0
- package/dist/ui/CISelector.d.ts.map +1 -0
- package/dist/ui/CISelector.js +45 -0
- package/dist/ui/CISelector.js.map +1 -0
- package/dist/ui/Doctor.d.ts +3 -0
- package/dist/ui/Doctor.d.ts.map +1 -0
- package/dist/ui/Doctor.js +89 -0
- package/dist/ui/Doctor.js.map +1 -0
- package/dist/ui/Header.d.ts +8 -0
- package/dist/ui/Header.d.ts.map +1 -0
- package/dist/ui/Header.js +30 -0
- package/dist/ui/Header.js.map +1 -0
- package/dist/ui/MemorySelector.d.ts +8 -0
- package/dist/ui/MemorySelector.d.ts.map +1 -0
- package/dist/ui/MemorySelector.js +46 -0
- package/dist/ui/MemorySelector.js.map +1 -0
- package/dist/ui/NameInput.d.ts +8 -0
- package/dist/ui/NameInput.d.ts.map +1 -0
- package/dist/ui/NameInput.js +69 -0
- package/dist/ui/NameInput.js.map +1 -0
- package/dist/ui/OptionSelector.d.ts +12 -0
- package/dist/ui/OptionSelector.d.ts.map +1 -0
- package/dist/ui/OptionSelector.js +69 -0
- package/dist/ui/OptionSelector.js.map +1 -0
- package/dist/ui/Progress.d.ts +11 -0
- package/dist/ui/Progress.d.ts.map +1 -0
- package/dist/ui/Progress.js +58 -0
- package/dist/ui/Progress.js.map +1 -0
- package/dist/ui/StackSelector.d.ts +9 -0
- package/dist/ui/StackSelector.d.ts.map +1 -0
- package/dist/ui/StackSelector.js +65 -0
- package/dist/ui/StackSelector.js.map +1 -0
- package/dist/ui/Summary.d.ts +12 -0
- package/dist/ui/Summary.d.ts.map +1 -0
- package/dist/ui/Summary.js +114 -0
- package/dist/ui/Summary.js.map +1 -0
- package/dist/ui/SyncUI.d.ts +10 -0
- package/dist/ui/SyncUI.d.ts.map +1 -0
- package/dist/ui/SyncUI.js +64 -0
- package/dist/ui/SyncUI.js.map +1 -0
- package/dist/ui/Welcome.d.ts +7 -0
- package/dist/ui/Welcome.d.ts.map +1 -0
- package/dist/ui/Welcome.js +45 -0
- package/dist/ui/Welcome.js.map +1 -0
- package/dist/ui/theme.d.ts +10 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +9 -0
- package/dist/ui/theme.js.map +1 -0
- package/modules/engram/.gitignore-snippet.txt +6 -0
- package/modules/engram/.mcp-config-snippet.json +11 -0
- package/modules/engram/README.md +146 -0
- package/modules/engram/install-engram.sh +216 -0
- package/modules/ghagga/.env.example +43 -0
- package/modules/ghagga/README.md +153 -0
- package/modules/ghagga/docker-compose.yml +80 -0
- package/modules/ghagga/setup-ghagga.sh +139 -0
- package/modules/memory-simple/.project/NOTES.md +22 -0
- package/modules/memory-simple/README.md +23 -0
- package/modules/obsidian-brain/.obsidian/app.json +23 -0
- package/modules/obsidian-brain/.obsidian/appearance.json +5 -0
- package/modules/obsidian-brain/.obsidian/bookmarks.json +34 -0
- package/modules/obsidian-brain/.obsidian/community-plugins.json +1 -0
- package/modules/obsidian-brain/.obsidian/core-plugins-migration.json +21 -0
- package/modules/obsidian-brain/.obsidian/core-plugins.json +18 -0
- package/modules/obsidian-brain/.obsidian/daily-notes.json +5 -0
- package/modules/obsidian-brain/.obsidian/graph.json +37 -0
- package/modules/obsidian-brain/.obsidian/hotkeys.json +14 -0
- package/modules/obsidian-brain/.obsidian/plugins/dataview/data.json +25 -0
- package/modules/obsidian-brain/.obsidian/plugins/obsidian-kanban/data.json +29 -0
- package/modules/obsidian-brain/.obsidian/plugins/templater-obsidian/data.json +18 -0
- package/modules/obsidian-brain/.obsidian/snippets/project-memory.css +71 -0
- package/modules/obsidian-brain/.obsidian-gitignore-snippet.txt +8 -0
- package/modules/obsidian-brain/.project/Attachments/.gitkeep +0 -0
- package/modules/obsidian-brain/.project/Memory/BLOCKERS.md +78 -0
- package/modules/obsidian-brain/.project/Memory/CONTEXT.md +102 -0
- package/modules/obsidian-brain/.project/Memory/DASHBOARD.md +73 -0
- package/modules/obsidian-brain/.project/Memory/DECISIONS.md +87 -0
- package/modules/obsidian-brain/.project/Memory/KANBAN.md +15 -0
- package/modules/obsidian-brain/.project/Memory/README.md +61 -0
- package/modules/obsidian-brain/.project/Memory/WAVES.md +78 -0
- package/modules/obsidian-brain/.project/Sessions/TEMPLATE.md +99 -0
- package/modules/obsidian-brain/.project/Templates/ADR.md +33 -0
- package/modules/obsidian-brain/.project/Templates/Blocker.md +21 -0
- package/modules/obsidian-brain/.project/Templates/Session.md +88 -0
- package/modules/obsidian-brain/README.md +268 -0
- package/modules/obsidian-brain/new-wave.sh +182 -0
- package/package.json +51 -0
- package/schemas/agent.schema.json +34 -0
- package/schemas/ai-config.schema.json +28 -0
- package/schemas/skill.schema.json +44 -0
- package/src/commands/analyze.test.ts +145 -0
- package/src/commands/analyze.ts +69 -0
- package/src/commands/doctor.test.ts +208 -0
- package/src/commands/doctor.ts +163 -0
- package/src/commands/init.test.ts +298 -0
- package/src/commands/init.ts +285 -0
- package/src/constants.ts +69 -0
- package/src/e2e/aggressive.e2e.test.ts +557 -0
- package/src/e2e/commands.e2e.test.ts +298 -0
- package/src/index.tsx +106 -0
- package/src/lib/common.test.ts +318 -0
- package/src/lib/common.ts +127 -0
- package/src/lib/frontmatter.test.ts +291 -0
- package/src/lib/frontmatter.ts +77 -0
- package/src/lib/template.test.ts +226 -0
- package/src/lib/template.ts +99 -0
- package/src/types/index.ts +53 -0
- package/src/ui/AnalyzeUI.tsx +133 -0
- package/src/ui/App.tsx +175 -0
- package/src/ui/CIContext.tsx +25 -0
- package/src/ui/CISelector.tsx +72 -0
- package/src/ui/Doctor.tsx +122 -0
- package/src/ui/Header.tsx +48 -0
- package/src/ui/MemorySelector.tsx +73 -0
- package/src/ui/NameInput.tsx +82 -0
- package/src/ui/OptionSelector.tsx +100 -0
- package/src/ui/Progress.tsx +88 -0
- package/src/ui/StackSelector.tsx +101 -0
- package/src/ui/Summary.tsx +134 -0
- package/src/ui/Welcome.tsx +54 -0
- package/src/ui/theme.ts +10 -0
- package/stryker.config.json +19 -0
- package/tasks/_TEMPLATE/files-edited.md +3 -0
- package/tasks/_TEMPLATE/plan.md +3 -0
- package/tasks/_TEMPLATE/research.md +3 -0
- package/tasks/_TEMPLATE/verification.md +5 -0
- package/templates/common/dependabot/cargo.yml +11 -0
- package/templates/common/dependabot/github-actions.yml +16 -0
- package/templates/common/dependabot/gomod.yml +15 -0
- package/templates/common/dependabot/gradle.yml +15 -0
- package/templates/common/dependabot/header.yml +3 -0
- package/templates/common/dependabot/maven.yml +15 -0
- package/templates/common/dependabot/npm.yml +20 -0
- package/templates/common/dependabot/pip.yml +11 -0
- package/templates/dependabot.yml +162 -0
- package/templates/github/ci-go.yml +41 -0
- package/templates/github/ci-java.yml +45 -0
- package/templates/github/ci-monorepo.yml +150 -0
- package/templates/github/ci-node.yml +42 -0
- package/templates/github/ci-python.yml +42 -0
- package/templates/github/ci-rust.yml +42 -0
- package/templates/github/dependabot-automerge.yml +40 -0
- package/templates/gitlab/gitlab-ci-go.yml +88 -0
- package/templates/gitlab/gitlab-ci-java.yml +79 -0
- package/templates/gitlab/gitlab-ci-monorepo.yml +126 -0
- package/templates/gitlab/gitlab-ci-node.yml +63 -0
- package/templates/gitlab/gitlab-ci-python.yml +147 -0
- package/templates/gitlab/gitlab-ci-rust.yml +67 -0
- package/templates/global/claude-settings.json +98 -0
- package/templates/global/codex-config.toml +8 -0
- package/templates/global/copilot-instructions/base-rules.instructions.md +13 -0
- package/templates/global/copilot-instructions/sdd-orchestrator.instructions.md +37 -0
- package/templates/global/gemini-commands/cleanup.toml +20 -0
- package/templates/global/gemini-commands/commit.toml +15 -0
- package/templates/global/gemini-commands/dead-code.toml +22 -0
- package/templates/global/gemini-commands/plan.toml +30 -0
- package/templates/global/gemini-commands/review.toml +17 -0
- package/templates/global/gemini-commands/sdd-apply.toml +22 -0
- package/templates/global/gemini-commands/sdd-ff.toml +14 -0
- package/templates/global/gemini-commands/sdd-new.toml +21 -0
- package/templates/global/gemini-commands/sdd-verify.toml +21 -0
- package/templates/global/gemini-commands/tdd.toml +26 -0
- package/templates/global/gemini-settings.json +8 -0
- package/templates/global/opencode-config.json +44 -0
- package/templates/global/sdd-instructions.md +47 -0
- package/templates/global/sdd-orchestrator-claude.md +46 -0
- package/templates/global/sdd-orchestrator-copilot.md +34 -0
- package/templates/renovate.json +69 -0
- package/templates/woodpecker/monorepo/backend.yml +34 -0
- package/templates/woodpecker/monorepo/frontend.yml +34 -0
- package/templates/woodpecker/monorepo/summary.yml +25 -0
- package/templates/woodpecker/woodpecker-go.yml +51 -0
- package/templates/woodpecker/woodpecker-java.yml +67 -0
- package/templates/woodpecker/woodpecker-node.yml +47 -0
- package/templates/woodpecker/woodpecker-python.yml +108 -0
- package/templates/woodpecker/woodpecker-rust.yml +57 -0
- package/tsconfig.json +19 -0
- package/vitest.config.ts +16 -0
- package/workflows/reusable-build-go.yml +111 -0
- package/workflows/reusable-build-java.yml +120 -0
- package/workflows/reusable-build-node.yml +145 -0
- package/workflows/reusable-build-python.yml +159 -0
- package/workflows/reusable-build-rust.yml +135 -0
- package/workflows/reusable-docker.yml +120 -0
- package/workflows/reusable-ghagga-review.yml +165 -0
- package/workflows/reusable-release.yml +91 -0
|
@@ -0,0 +1,743 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dependency-manager
|
|
3
|
+
description: Expert in dependency management, security auditing, version optimization, and license compliance
|
|
4
|
+
trigger: >
|
|
5
|
+
dependency update, npm audit, outdated packages, license compliance, version upgrade,
|
|
6
|
+
bundle size, security vulnerabilities, package management, monorepo sync
|
|
7
|
+
category: quality
|
|
8
|
+
color: yellow
|
|
9
|
+
tools: Read, Bash, Grep, Glob
|
|
10
|
+
config:
|
|
11
|
+
model: sonnet
|
|
12
|
+
metadata:
|
|
13
|
+
version: "2.0"
|
|
14
|
+
updated: "2026-02"
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
You are a dependency management specialist focused on keeping projects secure, up-to-date, and optimized.
|
|
18
|
+
|
|
19
|
+
## Core Expertise
|
|
20
|
+
- Security vulnerability detection and remediation
|
|
21
|
+
- Dependency version optimization and upgrades
|
|
22
|
+
- License compliance checking and auditing
|
|
23
|
+
- Bundle size optimization and tree shaking
|
|
24
|
+
- Monorepo dependency management
|
|
25
|
+
- Lock file analysis and optimization
|
|
26
|
+
- Supply chain security
|
|
27
|
+
|
|
28
|
+
## Security Scanning
|
|
29
|
+
```bash
|
|
30
|
+
# Multi-tool vulnerability scanning
|
|
31
|
+
|
|
32
|
+
# NPM ecosystem
|
|
33
|
+
npm audit --json > npm-audit.json
|
|
34
|
+
npx better-npm-audit audit
|
|
35
|
+
npx snyk test --json > snyk-report.json
|
|
36
|
+
npx audit-ci --config audit-ci.json
|
|
37
|
+
|
|
38
|
+
# Yarn
|
|
39
|
+
yarn audit --json > yarn-audit.json
|
|
40
|
+
|
|
41
|
+
# PNPM
|
|
42
|
+
pnpm audit --json > pnpm-audit.json
|
|
43
|
+
|
|
44
|
+
# Python ecosystem
|
|
45
|
+
pip-audit --format json > pip-audit.json
|
|
46
|
+
safety check --json > safety-report.json
|
|
47
|
+
bandit -r ./src -f json > bandit-report.json
|
|
48
|
+
|
|
49
|
+
# Go
|
|
50
|
+
govulncheck ./...
|
|
51
|
+
nancy sleuth < go.sum
|
|
52
|
+
|
|
53
|
+
# Rust
|
|
54
|
+
cargo audit --json > cargo-audit.json
|
|
55
|
+
|
|
56
|
+
# Ruby
|
|
57
|
+
bundle audit check --format json > bundle-audit.json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Vulnerability Analysis Script
|
|
61
|
+
```typescript
|
|
62
|
+
// scripts/analyze-vulnerabilities.ts
|
|
63
|
+
import * as fs from 'fs';
|
|
64
|
+
|
|
65
|
+
interface Vulnerability {
|
|
66
|
+
id: string;
|
|
67
|
+
package: string;
|
|
68
|
+
version: string;
|
|
69
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
70
|
+
title: string;
|
|
71
|
+
recommendation: string;
|
|
72
|
+
patchedVersions?: string;
|
|
73
|
+
cwe?: string[];
|
|
74
|
+
cvss?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
interface AuditReport {
|
|
78
|
+
vulnerabilities: Vulnerability[];
|
|
79
|
+
summary: {
|
|
80
|
+
critical: number;
|
|
81
|
+
high: number;
|
|
82
|
+
medium: number;
|
|
83
|
+
low: number;
|
|
84
|
+
total: number;
|
|
85
|
+
};
|
|
86
|
+
recommendations: string[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class VulnerabilityAnalyzer {
|
|
90
|
+
async analyzeNpmAudit(reportPath: string): Promise<AuditReport> {
|
|
91
|
+
const report = JSON.parse(fs.readFileSync(reportPath, 'utf-8'));
|
|
92
|
+
const vulnerabilities: Vulnerability[] = [];
|
|
93
|
+
|
|
94
|
+
for (const [name, advisory] of Object.entries(report.vulnerabilities || {})) {
|
|
95
|
+
const adv = advisory as any;
|
|
96
|
+
vulnerabilities.push({
|
|
97
|
+
id: adv.via?.[0]?.source || `npm-${name}`,
|
|
98
|
+
package: name,
|
|
99
|
+
version: adv.range || '*',
|
|
100
|
+
severity: this.normalizeSeverity(adv.severity),
|
|
101
|
+
title: adv.via?.[0]?.title || 'Unknown vulnerability',
|
|
102
|
+
recommendation: adv.fixAvailable
|
|
103
|
+
? `Update to ${adv.fixAvailable.version}`
|
|
104
|
+
: 'Manual review required',
|
|
105
|
+
patchedVersions: adv.fixAvailable?.version,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return this.generateReport(vulnerabilities);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async analyzeSnykReport(reportPath: string): Promise<AuditReport> {
|
|
113
|
+
const report = JSON.parse(fs.readFileSync(reportPath, 'utf-8'));
|
|
114
|
+
const vulnerabilities: Vulnerability[] = [];
|
|
115
|
+
|
|
116
|
+
for (const vuln of report.vulnerabilities || []) {
|
|
117
|
+
vulnerabilities.push({
|
|
118
|
+
id: vuln.id,
|
|
119
|
+
package: vuln.packageName,
|
|
120
|
+
version: vuln.version,
|
|
121
|
+
severity: this.normalizeSeverity(vuln.severity),
|
|
122
|
+
title: vuln.title,
|
|
123
|
+
recommendation: vuln.fixedIn?.[0]
|
|
124
|
+
? `Upgrade to ${vuln.fixedIn[0]}`
|
|
125
|
+
: 'No fix available',
|
|
126
|
+
patchedVersions: vuln.fixedIn?.join(', '),
|
|
127
|
+
cwe: vuln.identifiers?.CWE,
|
|
128
|
+
cvss: vuln.cvssScore,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return this.generateReport(vulnerabilities);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private normalizeSeverity(severity: string): Vulnerability['severity'] {
|
|
136
|
+
const normalized = severity.toLowerCase();
|
|
137
|
+
if (['critical'].includes(normalized)) return 'critical';
|
|
138
|
+
if (['high'].includes(normalized)) return 'high';
|
|
139
|
+
if (['moderate', 'medium'].includes(normalized)) return 'medium';
|
|
140
|
+
return 'low';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private generateReport(vulnerabilities: Vulnerability[]): AuditReport {
|
|
144
|
+
const summary = {
|
|
145
|
+
critical: vulnerabilities.filter(v => v.severity === 'critical').length,
|
|
146
|
+
high: vulnerabilities.filter(v => v.severity === 'high').length,
|
|
147
|
+
medium: vulnerabilities.filter(v => v.severity === 'medium').length,
|
|
148
|
+
low: vulnerabilities.filter(v => v.severity === 'low').length,
|
|
149
|
+
total: vulnerabilities.length,
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const recommendations = this.generateRecommendations(vulnerabilities);
|
|
153
|
+
|
|
154
|
+
return { vulnerabilities, summary, recommendations };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private generateRecommendations(vulnerabilities: Vulnerability[]): string[] {
|
|
158
|
+
const recommendations: string[] = [];
|
|
159
|
+
|
|
160
|
+
// Group by package
|
|
161
|
+
const byPackage = new Map<string, Vulnerability[]>();
|
|
162
|
+
for (const vuln of vulnerabilities) {
|
|
163
|
+
const existing = byPackage.get(vuln.package) || [];
|
|
164
|
+
existing.push(vuln);
|
|
165
|
+
byPackage.set(vuln.package, existing);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Priority: critical > high > medium > low
|
|
169
|
+
const critical = vulnerabilities.filter(v => v.severity === 'critical');
|
|
170
|
+
if (critical.length > 0) {
|
|
171
|
+
recommendations.push(
|
|
172
|
+
`URGENT: ${critical.length} critical vulnerabilities require immediate attention`
|
|
173
|
+
);
|
|
174
|
+
for (const vuln of critical.slice(0, 5)) {
|
|
175
|
+
recommendations.push(` - ${vuln.package}: ${vuln.recommendation}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const high = vulnerabilities.filter(v => v.severity === 'high');
|
|
180
|
+
if (high.length > 0) {
|
|
181
|
+
recommendations.push(
|
|
182
|
+
`HIGH PRIORITY: ${high.length} high severity vulnerabilities`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return recommendations;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Dependency Update Strategy
|
|
192
|
+
```typescript
|
|
193
|
+
// scripts/dependency-updater.ts
|
|
194
|
+
import { exec } from 'child_process';
|
|
195
|
+
import { promisify } from 'util';
|
|
196
|
+
import * as semver from 'semver';
|
|
197
|
+
|
|
198
|
+
const execAsync = promisify(exec);
|
|
199
|
+
|
|
200
|
+
interface UpdatePlan {
|
|
201
|
+
package: string;
|
|
202
|
+
currentVersion: string;
|
|
203
|
+
targetVersion: string;
|
|
204
|
+
updateType: 'patch' | 'minor' | 'major';
|
|
205
|
+
breaking: boolean;
|
|
206
|
+
changelog?: string;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
interface UpdateResult {
|
|
210
|
+
success: boolean;
|
|
211
|
+
package: string;
|
|
212
|
+
from: string;
|
|
213
|
+
to: string;
|
|
214
|
+
error?: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export class DependencyUpdater {
|
|
218
|
+
async checkOutdated(): Promise<UpdatePlan[]> {
|
|
219
|
+
const { stdout } = await execAsync('npm outdated --json');
|
|
220
|
+
const outdated = JSON.parse(stdout || '{}');
|
|
221
|
+
const plans: UpdatePlan[] = [];
|
|
222
|
+
|
|
223
|
+
for (const [pkg, info] of Object.entries(outdated)) {
|
|
224
|
+
const i = info as any;
|
|
225
|
+
const current = i.current;
|
|
226
|
+
const latest = i.latest;
|
|
227
|
+
|
|
228
|
+
if (!current || !latest) continue;
|
|
229
|
+
|
|
230
|
+
const updateType = this.determineUpdateType(current, latest);
|
|
231
|
+
plans.push({
|
|
232
|
+
package: pkg,
|
|
233
|
+
currentVersion: current,
|
|
234
|
+
targetVersion: latest,
|
|
235
|
+
updateType,
|
|
236
|
+
breaking: updateType === 'major',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return plans.sort((a, b) => {
|
|
241
|
+
const order = { major: 2, minor: 1, patch: 0 };
|
|
242
|
+
return order[b.updateType] - order[a.updateType];
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
private determineUpdateType(current: string, target: string): UpdatePlan['updateType'] {
|
|
247
|
+
const currentParsed = semver.parse(current);
|
|
248
|
+
const targetParsed = semver.parse(target);
|
|
249
|
+
|
|
250
|
+
if (!currentParsed || !targetParsed) return 'patch';
|
|
251
|
+
|
|
252
|
+
if (targetParsed.major > currentParsed.major) return 'major';
|
|
253
|
+
if (targetParsed.minor > currentParsed.minor) return 'minor';
|
|
254
|
+
return 'patch';
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
async updateDependency(pkg: string, version: string): Promise<UpdateResult> {
|
|
258
|
+
try {
|
|
259
|
+
await execAsync(`npm install ${pkg}@${version}`);
|
|
260
|
+
|
|
261
|
+
// Run tests to verify update
|
|
262
|
+
const testResult = await this.runTests();
|
|
263
|
+
|
|
264
|
+
if (!testResult.success) {
|
|
265
|
+
// Rollback
|
|
266
|
+
await execAsync(`npm install ${pkg}@${version}`);
|
|
267
|
+
return {
|
|
268
|
+
success: false,
|
|
269
|
+
package: pkg,
|
|
270
|
+
from: version,
|
|
271
|
+
to: version,
|
|
272
|
+
error: `Tests failed after update: ${testResult.error}`,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
success: true,
|
|
278
|
+
package: pkg,
|
|
279
|
+
from: version,
|
|
280
|
+
to: version,
|
|
281
|
+
};
|
|
282
|
+
} catch (error) {
|
|
283
|
+
return {
|
|
284
|
+
success: false,
|
|
285
|
+
package: pkg,
|
|
286
|
+
from: version,
|
|
287
|
+
to: version,
|
|
288
|
+
error: error.message,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async updateAll(type: 'patch' | 'minor' | 'all'): Promise<UpdateResult[]> {
|
|
294
|
+
const plans = await this.checkOutdated();
|
|
295
|
+
const results: UpdateResult[] = [];
|
|
296
|
+
|
|
297
|
+
const filtered = plans.filter(p => {
|
|
298
|
+
if (type === 'all') return true;
|
|
299
|
+
if (type === 'minor') return p.updateType !== 'major';
|
|
300
|
+
return p.updateType === 'patch';
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
for (const plan of filtered) {
|
|
304
|
+
const result = await this.updateDependency(plan.package, plan.targetVersion);
|
|
305
|
+
results.push(result);
|
|
306
|
+
|
|
307
|
+
if (!result.success && plan.breaking) {
|
|
308
|
+
console.warn(`Breaking update failed for ${plan.package}, skipping remaining majors`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return results;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private async runTests(): Promise<{ success: boolean; error?: string }> {
|
|
316
|
+
try {
|
|
317
|
+
await execAsync('npm test', { timeout: 300000 }); // 5 minute timeout
|
|
318
|
+
return { success: true };
|
|
319
|
+
} catch (error) {
|
|
320
|
+
return { success: false, error: error.message };
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## License Compliance Checker
|
|
327
|
+
```typescript
|
|
328
|
+
// scripts/license-checker.ts
|
|
329
|
+
import * as fs from 'fs';
|
|
330
|
+
import * as path from 'path';
|
|
331
|
+
|
|
332
|
+
interface LicenseInfo {
|
|
333
|
+
package: string;
|
|
334
|
+
version: string;
|
|
335
|
+
license: string;
|
|
336
|
+
repository?: string;
|
|
337
|
+
compliant: boolean;
|
|
338
|
+
issues: string[];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
interface LicensePolicy {
|
|
342
|
+
allowed: string[];
|
|
343
|
+
forbidden: string[];
|
|
344
|
+
requireReview: string[];
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const DEFAULT_POLICY: LicensePolicy = {
|
|
348
|
+
allowed: [
|
|
349
|
+
'MIT', 'ISC', 'BSD-2-Clause', 'BSD-3-Clause',
|
|
350
|
+
'Apache-2.0', 'Unlicense', '0BSD', 'CC0-1.0'
|
|
351
|
+
],
|
|
352
|
+
forbidden: [
|
|
353
|
+
'GPL-2.0', 'GPL-3.0', 'AGPL-3.0', 'LGPL-2.1', 'LGPL-3.0',
|
|
354
|
+
'CC-BY-SA-4.0', 'CC-BY-NC-4.0'
|
|
355
|
+
],
|
|
356
|
+
requireReview: [
|
|
357
|
+
'MPL-2.0', 'EPL-1.0', 'EPL-2.0', 'CDDL-1.0',
|
|
358
|
+
'Artistic-2.0', 'OFL-1.1'
|
|
359
|
+
],
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
export class LicenseChecker {
|
|
363
|
+
private policy: LicensePolicy;
|
|
364
|
+
|
|
365
|
+
constructor(policy: LicensePolicy = DEFAULT_POLICY) {
|
|
366
|
+
this.policy = policy;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
async checkLicenses(projectPath: string): Promise<LicenseInfo[]> {
|
|
370
|
+
const packageLock = path.join(projectPath, 'package-lock.json');
|
|
371
|
+
const lockFile = JSON.parse(fs.readFileSync(packageLock, 'utf-8'));
|
|
372
|
+
const results: LicenseInfo[] = [];
|
|
373
|
+
|
|
374
|
+
for (const [name, info] of Object.entries(lockFile.packages || {})) {
|
|
375
|
+
if (name === '' || !(info as any).license) continue;
|
|
376
|
+
|
|
377
|
+
const pkg = info as any;
|
|
378
|
+
const license = this.normalizeLicense(pkg.license);
|
|
379
|
+
const issues: string[] = [];
|
|
380
|
+
|
|
381
|
+
let compliant = true;
|
|
382
|
+
|
|
383
|
+
if (this.policy.forbidden.includes(license)) {
|
|
384
|
+
compliant = false;
|
|
385
|
+
issues.push(`Forbidden license: ${license}`);
|
|
386
|
+
} else if (this.policy.requireReview.includes(license)) {
|
|
387
|
+
issues.push(`Requires legal review: ${license}`);
|
|
388
|
+
} else if (!this.policy.allowed.includes(license)) {
|
|
389
|
+
issues.push(`Unknown license: ${license}`);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const packageName = name.replace(/^node_modules\//, '');
|
|
393
|
+
results.push({
|
|
394
|
+
package: packageName,
|
|
395
|
+
version: pkg.version,
|
|
396
|
+
license,
|
|
397
|
+
repository: pkg.repository?.url,
|
|
398
|
+
compliant,
|
|
399
|
+
issues,
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return results;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
private normalizeLicense(license: string | { type: string }): string {
|
|
407
|
+
if (typeof license === 'object') {
|
|
408
|
+
return license.type;
|
|
409
|
+
}
|
|
410
|
+
return license.replace(/\s+/g, '-').toUpperCase();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
generateReport(results: LicenseInfo[]): string {
|
|
414
|
+
const compliant = results.filter(r => r.compliant);
|
|
415
|
+
const nonCompliant = results.filter(r => !r.compliant);
|
|
416
|
+
const needsReview = results.filter(r => r.issues.some(i => i.includes('review')));
|
|
417
|
+
|
|
418
|
+
let report = '# License Compliance Report\n\n';
|
|
419
|
+
|
|
420
|
+
report += `## Summary\n`;
|
|
421
|
+
report += `- Total packages: ${results.length}\n`;
|
|
422
|
+
report += `- Compliant: ${compliant.length}\n`;
|
|
423
|
+
report += `- Non-compliant: ${nonCompliant.length}\n`;
|
|
424
|
+
report += `- Needs review: ${needsReview.length}\n\n`;
|
|
425
|
+
|
|
426
|
+
if (nonCompliant.length > 0) {
|
|
427
|
+
report += `## Non-Compliant Packages\n\n`;
|
|
428
|
+
for (const pkg of nonCompliant) {
|
|
429
|
+
report += `### ${pkg.package}@${pkg.version}\n`;
|
|
430
|
+
report += `- License: ${pkg.license}\n`;
|
|
431
|
+
report += `- Issues:\n`;
|
|
432
|
+
for (const issue of pkg.issues) {
|
|
433
|
+
report += ` - ${issue}\n`;
|
|
434
|
+
}
|
|
435
|
+
report += '\n';
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (needsReview.length > 0) {
|
|
440
|
+
report += `## Packages Requiring Review\n\n`;
|
|
441
|
+
for (const pkg of needsReview) {
|
|
442
|
+
report += `- ${pkg.package}@${pkg.version}: ${pkg.license}\n`;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return report;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## Bundle Size Analyzer
|
|
452
|
+
```typescript
|
|
453
|
+
// scripts/bundle-analyzer.ts
|
|
454
|
+
import * as fs from 'fs';
|
|
455
|
+
import * as zlib from 'zlib';
|
|
456
|
+
|
|
457
|
+
interface BundleAnalysis {
|
|
458
|
+
package: string;
|
|
459
|
+
size: number;
|
|
460
|
+
gzipSize: number;
|
|
461
|
+
percentOfBundle: number;
|
|
462
|
+
dependencies: string[];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export class BundleAnalyzer {
|
|
466
|
+
async analyzeBundle(statsPath: string): Promise<BundleAnalysis[]> {
|
|
467
|
+
const stats = JSON.parse(fs.readFileSync(statsPath, 'utf-8'));
|
|
468
|
+
const modulesByPackage = new Map<string, { size: number; deps: Set<string> }>();
|
|
469
|
+
|
|
470
|
+
// Group modules by package
|
|
471
|
+
for (const module of stats.modules || []) {
|
|
472
|
+
const packageName = this.extractPackageName(module.name);
|
|
473
|
+
if (!packageName) continue;
|
|
474
|
+
|
|
475
|
+
const existing = modulesByPackage.get(packageName) || { size: 0, deps: new Set() };
|
|
476
|
+
existing.size += module.size || 0;
|
|
477
|
+
|
|
478
|
+
// Track dependencies
|
|
479
|
+
for (const reason of module.reasons || []) {
|
|
480
|
+
const depPackage = this.extractPackageName(reason.moduleName);
|
|
481
|
+
if (depPackage && depPackage !== packageName) {
|
|
482
|
+
existing.deps.add(depPackage);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
modulesByPackage.set(packageName, existing);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
const totalSize = Array.from(modulesByPackage.values()).reduce((sum, m) => sum + m.size, 0);
|
|
490
|
+
const results: BundleAnalysis[] = [];
|
|
491
|
+
|
|
492
|
+
for (const [pkg, info] of modulesByPackage) {
|
|
493
|
+
const content = Buffer.alloc(info.size); // Simulated for gzip estimation
|
|
494
|
+
const gzipSize = zlib.gzipSync(content).length;
|
|
495
|
+
|
|
496
|
+
results.push({
|
|
497
|
+
package: pkg,
|
|
498
|
+
size: info.size,
|
|
499
|
+
gzipSize,
|
|
500
|
+
percentOfBundle: (info.size / totalSize) * 100,
|
|
501
|
+
dependencies: Array.from(info.deps),
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return results.sort((a, b) => b.size - a.size);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private extractPackageName(modulePath: string): string | null {
|
|
509
|
+
if (!modulePath) return null;
|
|
510
|
+
|
|
511
|
+
const nodeModulesMatch = modulePath.match(/node_modules\/(@[^/]+\/[^/]+|[^/]+)/);
|
|
512
|
+
if (nodeModulesMatch) {
|
|
513
|
+
return nodeModulesMatch[1];
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
return null;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
findDuplicates(analysis: BundleAnalysis[]): Map<string, string[]> {
|
|
520
|
+
const duplicates = new Map<string, string[]>();
|
|
521
|
+
|
|
522
|
+
// Check for multiple versions of same base package
|
|
523
|
+
const packageVersions = new Map<string, Set<string>>();
|
|
524
|
+
|
|
525
|
+
for (const item of analysis) {
|
|
526
|
+
const baseName = item.package.split('@')[0];
|
|
527
|
+
const versions = packageVersions.get(baseName) || new Set();
|
|
528
|
+
versions.add(item.package);
|
|
529
|
+
packageVersions.set(baseName, versions);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
for (const [baseName, versions] of packageVersions) {
|
|
533
|
+
if (versions.size > 1) {
|
|
534
|
+
duplicates.set(baseName, Array.from(versions));
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
return duplicates;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
generateOptimizationSuggestions(analysis: BundleAnalysis[]): string[] {
|
|
542
|
+
const suggestions: string[] = [];
|
|
543
|
+
|
|
544
|
+
// Large packages
|
|
545
|
+
const largePackages = analysis.filter(a => a.size > 100000); // > 100KB
|
|
546
|
+
for (const pkg of largePackages) {
|
|
547
|
+
suggestions.push(
|
|
548
|
+
`Consider lazy loading ${pkg.package} (${this.formatSize(pkg.size)})`
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Unused exports check
|
|
553
|
+
const heavyDeps = analysis.filter(a => a.percentOfBundle > 10);
|
|
554
|
+
for (const pkg of heavyDeps) {
|
|
555
|
+
suggestions.push(
|
|
556
|
+
`${pkg.package} is ${pkg.percentOfBundle.toFixed(1)}% of bundle. Consider tree-shaking.`
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
return suggestions;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
private formatSize(bytes: number): string {
|
|
564
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
565
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
566
|
+
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
## Monorepo Dependency Sync
|
|
572
|
+
```typescript
|
|
573
|
+
// scripts/monorepo-sync.ts
|
|
574
|
+
import * as fs from 'fs';
|
|
575
|
+
import * as path from 'path';
|
|
576
|
+
import * as glob from 'glob';
|
|
577
|
+
|
|
578
|
+
interface PackageJson {
|
|
579
|
+
name: string;
|
|
580
|
+
version: string;
|
|
581
|
+
dependencies?: Record<string, string>;
|
|
582
|
+
devDependencies?: Record<string, string>;
|
|
583
|
+
peerDependencies?: Record<string, string>;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
interface SyncIssue {
|
|
587
|
+
package: string;
|
|
588
|
+
dependency: string;
|
|
589
|
+
locations: { workspace: string; version: string }[];
|
|
590
|
+
recommendation: string;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export class MonorepoSync {
|
|
594
|
+
private workspaceRoot: string;
|
|
595
|
+
|
|
596
|
+
constructor(workspaceRoot: string) {
|
|
597
|
+
this.workspaceRoot = workspaceRoot;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
findVersionMismatches(): SyncIssue[] {
|
|
601
|
+
const packages = this.loadAllPackages();
|
|
602
|
+
const issues: SyncIssue[] = [];
|
|
603
|
+
|
|
604
|
+
// Collect all dependency versions across workspaces
|
|
605
|
+
const depVersions = new Map<string, Map<string, string>>();
|
|
606
|
+
|
|
607
|
+
for (const [workspace, pkg] of packages) {
|
|
608
|
+
const allDeps = {
|
|
609
|
+
...pkg.dependencies,
|
|
610
|
+
...pkg.devDependencies,
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
for (const [dep, version] of Object.entries(allDeps)) {
|
|
614
|
+
if (!depVersions.has(dep)) {
|
|
615
|
+
depVersions.set(dep, new Map());
|
|
616
|
+
}
|
|
617
|
+
depVersions.get(dep)!.set(workspace, version);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// Find mismatches
|
|
622
|
+
for (const [dep, versions] of depVersions) {
|
|
623
|
+
const uniqueVersions = new Set(versions.values());
|
|
624
|
+
if (uniqueVersions.size > 1) {
|
|
625
|
+
const locations = Array.from(versions.entries()).map(([workspace, version]) => ({
|
|
626
|
+
workspace,
|
|
627
|
+
version,
|
|
628
|
+
}));
|
|
629
|
+
|
|
630
|
+
const latestVersion = this.getLatestVersion(Array.from(uniqueVersions));
|
|
631
|
+
|
|
632
|
+
issues.push({
|
|
633
|
+
package: dep,
|
|
634
|
+
dependency: dep,
|
|
635
|
+
locations,
|
|
636
|
+
recommendation: `Align all workspaces to ${latestVersion}`,
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
return issues;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
private loadAllPackages(): Map<string, PackageJson> {
|
|
645
|
+
const packages = new Map<string, PackageJson>();
|
|
646
|
+
|
|
647
|
+
// Load root package.json
|
|
648
|
+
const rootPkg = this.loadPackageJson(this.workspaceRoot);
|
|
649
|
+
packages.set('root', rootPkg);
|
|
650
|
+
|
|
651
|
+
// Find all workspace packages
|
|
652
|
+
const workspaces = rootPkg.workspaces || [];
|
|
653
|
+
for (const pattern of workspaces) {
|
|
654
|
+
const matches = glob.sync(pattern, { cwd: this.workspaceRoot });
|
|
655
|
+
for (const match of matches) {
|
|
656
|
+
const pkgPath = path.join(this.workspaceRoot, match);
|
|
657
|
+
if (fs.existsSync(path.join(pkgPath, 'package.json'))) {
|
|
658
|
+
const pkg = this.loadPackageJson(pkgPath);
|
|
659
|
+
packages.set(pkg.name || match, pkg);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return packages;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
private loadPackageJson(dir: string): PackageJson {
|
|
668
|
+
const pkgPath = path.join(dir, 'package.json');
|
|
669
|
+
return JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
private getLatestVersion(versions: string[]): string {
|
|
673
|
+
// Simple version comparison - production would use semver
|
|
674
|
+
return versions.sort().pop() || versions[0];
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async syncVersions(targetVersion?: string): Promise<void> {
|
|
678
|
+
const issues = this.findVersionMismatches();
|
|
679
|
+
const packages = this.loadAllPackages();
|
|
680
|
+
|
|
681
|
+
for (const issue of issues) {
|
|
682
|
+
const version = targetVersion || issue.recommendation.split(' ').pop()!;
|
|
683
|
+
|
|
684
|
+
for (const { workspace } of issue.locations) {
|
|
685
|
+
const pkg = packages.get(workspace)!;
|
|
686
|
+
|
|
687
|
+
if (pkg.dependencies?.[issue.dependency]) {
|
|
688
|
+
pkg.dependencies[issue.dependency] = version;
|
|
689
|
+
}
|
|
690
|
+
if (pkg.devDependencies?.[issue.dependency]) {
|
|
691
|
+
pkg.devDependencies[issue.dependency] = version;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
// Write back
|
|
695
|
+
const pkgPath = this.getPackagePath(workspace);
|
|
696
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
private getPackagePath(workspace: string): string {
|
|
702
|
+
if (workspace === 'root') {
|
|
703
|
+
return path.join(this.workspaceRoot, 'package.json');
|
|
704
|
+
}
|
|
705
|
+
return path.join(this.workspaceRoot, 'packages', workspace, 'package.json');
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
## Strict Security Rules
|
|
711
|
+
- **NEVER** auto-update dependencies in production without testing.
|
|
712
|
+
- **ALWAYS** review changelogs before major version upgrades.
|
|
713
|
+
- **CREATE** lockfile backups before any dependency changes.
|
|
714
|
+
- **VERIFY** package integrity using checksums and signatures.
|
|
715
|
+
- **SCAN** for vulnerabilities before deploying.
|
|
716
|
+
- **AUDIT** licenses for compliance before adding new dependencies.
|
|
717
|
+
- **REJECT** packages from untrusted sources or with suspicious code.
|
|
718
|
+
- **MONITOR** for supply chain attacks and typosquatting.
|
|
719
|
+
|
|
720
|
+
## Best Practices
|
|
721
|
+
1. **Pin versions**: Use exact versions in production
|
|
722
|
+
2. **Regular audits**: Run security scans weekly
|
|
723
|
+
3. **Staged updates**: Test updates in CI before merging
|
|
724
|
+
4. **License compliance**: Check licenses before adding dependencies
|
|
725
|
+
5. **Bundle analysis**: Monitor bundle size impact
|
|
726
|
+
6. **Lockfile hygiene**: Keep lockfiles clean and committed
|
|
727
|
+
7. **Dependency minimization**: Remove unused dependencies
|
|
728
|
+
|
|
729
|
+
## Approach
|
|
730
|
+
1. Scan for security vulnerabilities
|
|
731
|
+
2. Identify outdated dependencies
|
|
732
|
+
3. Check license compliance
|
|
733
|
+
4. Analyze bundle size impact
|
|
734
|
+
5. Create update plan with priorities
|
|
735
|
+
6. Test updates in isolation
|
|
736
|
+
7. Document changes and decisions
|
|
737
|
+
|
|
738
|
+
## Output Format
|
|
739
|
+
- Provide vulnerability reports with severity
|
|
740
|
+
- Include update recommendations with risk assessment
|
|
741
|
+
- Document license compliance status
|
|
742
|
+
- Add bundle size analysis
|
|
743
|
+
- Include migration steps for major updates
|