claude-autopm 2.8.2 ā 2.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +399 -637
- package/package.json +2 -1
- package/packages/plugin-ai/LICENSE +21 -0
- package/packages/plugin-ai/README.md +316 -0
- package/packages/plugin-ai/agents/anthropic-claude-expert.md +579 -0
- package/packages/plugin-ai/agents/azure-openai-expert.md +1411 -0
- package/packages/plugin-ai/agents/gemini-api-expert.md +880 -0
- package/packages/plugin-ai/agents/google-a2a-expert.md +1445 -0
- package/packages/plugin-ai/agents/huggingface-expert.md +2131 -0
- package/packages/plugin-ai/agents/langchain-expert.md +1427 -0
- package/packages/plugin-ai/agents/langgraph-workflow-expert.md +520 -0
- package/packages/plugin-ai/agents/openai-python-expert.md +1087 -0
- package/packages/plugin-ai/commands/a2a-setup.md +886 -0
- package/packages/plugin-ai/commands/ai-model-deployment.md +481 -0
- package/packages/plugin-ai/commands/anthropic-optimize.md +793 -0
- package/packages/plugin-ai/commands/huggingface-deploy.md +789 -0
- package/packages/plugin-ai/commands/langchain-optimize.md +807 -0
- package/packages/plugin-ai/commands/llm-optimize.md +348 -0
- package/packages/plugin-ai/commands/openai-optimize.md +863 -0
- package/packages/plugin-ai/commands/rag-optimize.md +841 -0
- package/packages/plugin-ai/commands/rag-setup-scaffold.md +382 -0
- package/packages/plugin-ai/package.json +66 -0
- package/packages/plugin-ai/plugin.json +519 -0
- package/packages/plugin-ai/rules/ai-model-standards.md +449 -0
- package/packages/plugin-ai/rules/prompt-engineering-standards.md +509 -0
- package/packages/plugin-ai/scripts/examples/huggingface-inference-example.py +145 -0
- package/packages/plugin-ai/scripts/examples/langchain-rag-example.py +366 -0
- package/packages/plugin-ai/scripts/examples/mlflow-tracking-example.py +224 -0
- package/packages/plugin-ai/scripts/examples/openai-chat-example.py +425 -0
- package/packages/plugin-cloud/README.md +268 -0
- package/packages/plugin-cloud/agents/README.md +55 -0
- package/packages/plugin-cloud/agents/aws-cloud-architect.md +521 -0
- package/packages/plugin-cloud/agents/azure-cloud-architect.md +436 -0
- package/packages/plugin-cloud/agents/gcp-cloud-architect.md +385 -0
- package/packages/plugin-cloud/agents/gcp-cloud-functions-engineer.md +306 -0
- package/packages/plugin-cloud/agents/gemini-api-expert.md +880 -0
- package/packages/plugin-cloud/agents/kubernetes-orchestrator.md +566 -0
- package/packages/plugin-cloud/agents/openai-python-expert.md +1087 -0
- package/packages/plugin-cloud/agents/terraform-infrastructure-expert.md +454 -0
- package/packages/plugin-cloud/commands/cloud-cost-optimize.md +243 -0
- package/packages/plugin-cloud/commands/cloud-validate.md +196 -0
- package/packages/plugin-cloud/commands/infra-deploy.md +38 -0
- package/packages/plugin-cloud/commands/k8s-deploy.md +37 -0
- package/packages/plugin-cloud/commands/ssh-security.md +65 -0
- package/packages/plugin-cloud/commands/traefik-setup.md +65 -0
- package/packages/plugin-cloud/hooks/pre-cloud-deploy.js +456 -0
- package/packages/plugin-cloud/package.json +64 -0
- package/packages/plugin-cloud/plugin.json +338 -0
- package/packages/plugin-cloud/rules/cloud-security-compliance.md +313 -0
- package/packages/plugin-cloud/rules/infrastructure-pipeline.md +128 -0
- package/packages/plugin-cloud/scripts/examples/aws-validate.sh +30 -0
- package/packages/plugin-cloud/scripts/examples/azure-setup.sh +33 -0
- package/packages/plugin-cloud/scripts/examples/gcp-setup.sh +39 -0
- package/packages/plugin-cloud/scripts/examples/k8s-validate.sh +40 -0
- package/packages/plugin-cloud/scripts/examples/terraform-init.sh +26 -0
- package/packages/plugin-core/README.md +274 -0
- package/packages/plugin-core/agents/core/agent-manager.md +296 -0
- package/packages/plugin-core/agents/core/code-analyzer.md +131 -0
- package/packages/plugin-core/agents/core/file-analyzer.md +162 -0
- package/packages/plugin-core/agents/core/test-runner.md +200 -0
- package/packages/plugin-core/commands/code-rabbit.md +128 -0
- package/packages/plugin-core/commands/prompt.md +9 -0
- package/packages/plugin-core/commands/re-init.md +9 -0
- package/packages/plugin-core/hooks/context7-reminder.md +29 -0
- package/packages/plugin-core/hooks/enforce-agents.js +125 -0
- package/packages/plugin-core/hooks/enforce-agents.sh +35 -0
- package/packages/plugin-core/hooks/pre-agent-context7.js +224 -0
- package/packages/plugin-core/hooks/pre-command-context7.js +229 -0
- package/packages/plugin-core/hooks/strict-enforce-agents.sh +39 -0
- package/packages/plugin-core/hooks/test-hook.sh +21 -0
- package/packages/plugin-core/hooks/unified-context7-enforcement.sh +38 -0
- package/packages/plugin-core/package.json +45 -0
- package/packages/plugin-core/plugin.json +387 -0
- package/packages/plugin-core/rules/agent-coordination.md +549 -0
- package/packages/plugin-core/rules/agent-mandatory.md +170 -0
- package/packages/plugin-core/rules/ai-integration-patterns.md +219 -0
- package/packages/plugin-core/rules/command-pipelines.md +208 -0
- package/packages/plugin-core/rules/context-optimization.md +176 -0
- package/packages/plugin-core/rules/context7-enforcement.md +327 -0
- package/packages/plugin-core/rules/datetime.md +122 -0
- package/packages/plugin-core/rules/definition-of-done.md +272 -0
- package/packages/plugin-core/rules/development-environments.md +19 -0
- package/packages/plugin-core/rules/development-workflow.md +198 -0
- package/packages/plugin-core/rules/framework-path-rules.md +180 -0
- package/packages/plugin-core/rules/frontmatter-operations.md +64 -0
- package/packages/plugin-core/rules/git-strategy.md +237 -0
- package/packages/plugin-core/rules/golden-rules.md +181 -0
- package/packages/plugin-core/rules/naming-conventions.md +111 -0
- package/packages/plugin-core/rules/no-pr-workflow.md +183 -0
- package/packages/plugin-core/rules/performance-guidelines.md +403 -0
- package/packages/plugin-core/rules/pipeline-mandatory.md +109 -0
- package/packages/plugin-core/rules/security-checklist.md +318 -0
- package/packages/plugin-core/rules/standard-patterns.md +197 -0
- package/packages/plugin-core/rules/strip-frontmatter.md +85 -0
- package/packages/plugin-core/rules/tdd.enforcement.md +103 -0
- package/packages/plugin-core/rules/use-ast-grep.md +113 -0
- package/packages/plugin-core/scripts/lib/datetime-utils.sh +254 -0
- package/packages/plugin-core/scripts/lib/frontmatter-utils.sh +294 -0
- package/packages/plugin-core/scripts/lib/github-utils.sh +221 -0
- package/packages/plugin-core/scripts/lib/logging-utils.sh +199 -0
- package/packages/plugin-core/scripts/lib/validation-utils.sh +339 -0
- package/packages/plugin-core/scripts/mcp/add.sh +7 -0
- package/packages/plugin-core/scripts/mcp/disable.sh +12 -0
- package/packages/plugin-core/scripts/mcp/enable.sh +12 -0
- package/packages/plugin-core/scripts/mcp/list.sh +7 -0
- package/packages/plugin-core/scripts/mcp/sync.sh +8 -0
- package/packages/plugin-data/README.md +315 -0
- package/packages/plugin-data/agents/airflow-orchestration-expert.md +158 -0
- package/packages/plugin-data/agents/kedro-pipeline-expert.md +304 -0
- package/packages/plugin-data/agents/langgraph-workflow-expert.md +530 -0
- package/packages/plugin-data/commands/airflow-dag-scaffold.md +413 -0
- package/packages/plugin-data/commands/kafka-pipeline-scaffold.md +503 -0
- package/packages/plugin-data/package.json +66 -0
- package/packages/plugin-data/plugin.json +294 -0
- package/packages/plugin-data/rules/data-quality-standards.md +373 -0
- package/packages/plugin-data/rules/etl-pipeline-standards.md +255 -0
- package/packages/plugin-data/scripts/examples/airflow-dag-example.py +245 -0
- package/packages/plugin-data/scripts/examples/dbt-transform-example.sql +238 -0
- package/packages/plugin-data/scripts/examples/kafka-streaming-example.py +257 -0
- package/packages/plugin-data/scripts/examples/pandas-etl-example.py +332 -0
- package/packages/plugin-databases/README.md +330 -0
- package/packages/plugin-databases/agents/README.md +50 -0
- package/packages/plugin-databases/agents/bigquery-expert.md +401 -0
- package/packages/plugin-databases/agents/cosmosdb-expert.md +375 -0
- package/packages/plugin-databases/agents/mongodb-expert.md +407 -0
- package/packages/plugin-databases/agents/postgresql-expert.md +329 -0
- package/packages/plugin-databases/agents/redis-expert.md +74 -0
- package/packages/plugin-databases/commands/db-optimize.md +612 -0
- package/packages/plugin-databases/package.json +60 -0
- package/packages/plugin-databases/plugin.json +237 -0
- package/packages/plugin-databases/rules/database-management-strategy.md +146 -0
- package/packages/plugin-databases/rules/database-pipeline.md +316 -0
- package/packages/plugin-databases/scripts/examples/bigquery-cost-analyze.sh +160 -0
- package/packages/plugin-databases/scripts/examples/cosmosdb-ru-optimize.sh +163 -0
- package/packages/plugin-databases/scripts/examples/mongodb-shard-check.sh +120 -0
- package/packages/plugin-databases/scripts/examples/postgres-index-analyze.sh +95 -0
- package/packages/plugin-databases/scripts/examples/redis-cache-stats.sh +121 -0
- package/packages/plugin-devops/README.md +367 -0
- package/packages/plugin-devops/agents/README.md +52 -0
- package/packages/plugin-devops/agents/azure-devops-specialist.md +308 -0
- package/packages/plugin-devops/agents/docker-containerization-expert.md +298 -0
- package/packages/plugin-devops/agents/github-operations-specialist.md +335 -0
- package/packages/plugin-devops/agents/mcp-context-manager.md +319 -0
- package/packages/plugin-devops/agents/observability-engineer.md +574 -0
- package/packages/plugin-devops/agents/ssh-operations-expert.md +1093 -0
- package/packages/plugin-devops/agents/traefik-proxy-expert.md +444 -0
- package/packages/plugin-devops/commands/ci-pipeline-create.md +581 -0
- package/packages/plugin-devops/commands/docker-optimize.md +493 -0
- package/packages/plugin-devops/commands/workflow-create.md +42 -0
- package/packages/plugin-devops/hooks/pre-docker-build.js +472 -0
- package/packages/plugin-devops/package.json +61 -0
- package/packages/plugin-devops/plugin.json +302 -0
- package/packages/plugin-devops/rules/ci-cd-kubernetes-strategy.md +25 -0
- package/packages/plugin-devops/rules/devops-troubleshooting-playbook.md +450 -0
- package/packages/plugin-devops/rules/docker-first-development.md +404 -0
- package/packages/plugin-devops/rules/github-operations.md +92 -0
- package/packages/plugin-devops/scripts/examples/docker-build-multistage.sh +43 -0
- package/packages/plugin-devops/scripts/examples/docker-compose-validate.sh +74 -0
- package/packages/plugin-devops/scripts/examples/github-workflow-validate.sh +48 -0
- package/packages/plugin-devops/scripts/examples/prometheus-health-check.sh +58 -0
- package/packages/plugin-devops/scripts/examples/ssh-key-setup.sh +74 -0
- package/packages/plugin-frameworks/README.md +309 -0
- package/packages/plugin-frameworks/agents/README.md +64 -0
- package/packages/plugin-frameworks/agents/e2e-test-engineer.md +579 -0
- package/packages/plugin-frameworks/agents/nats-messaging-expert.md +254 -0
- package/packages/plugin-frameworks/agents/react-frontend-engineer.md +393 -0
- package/packages/plugin-frameworks/agents/react-ui-expert.md +226 -0
- package/packages/plugin-frameworks/agents/tailwindcss-expert.md +1021 -0
- package/packages/plugin-frameworks/agents/ux-design-expert.md +244 -0
- package/packages/plugin-frameworks/commands/app-scaffold.md +50 -0
- package/packages/plugin-frameworks/commands/nextjs-optimize.md +692 -0
- package/packages/plugin-frameworks/commands/react-optimize.md +583 -0
- package/packages/plugin-frameworks/commands/tailwind-system.md +64 -0
- package/packages/plugin-frameworks/package.json +59 -0
- package/packages/plugin-frameworks/plugin.json +224 -0
- package/packages/plugin-frameworks/rules/performance-guidelines.md +403 -0
- package/packages/plugin-frameworks/rules/ui-development-standards.md +281 -0
- package/packages/plugin-frameworks/rules/ui-framework-rules.md +151 -0
- package/packages/plugin-frameworks/scripts/examples/react-component-perf.sh +34 -0
- package/packages/plugin-frameworks/scripts/examples/tailwind-optimize.sh +44 -0
- package/packages/plugin-frameworks/scripts/examples/vue-composition-check.sh +41 -0
- package/packages/plugin-languages/README.md +333 -0
- package/packages/plugin-languages/agents/README.md +50 -0
- package/packages/plugin-languages/agents/bash-scripting-expert.md +541 -0
- package/packages/plugin-languages/agents/javascript-frontend-engineer.md +197 -0
- package/packages/plugin-languages/agents/nodejs-backend-engineer.md +226 -0
- package/packages/plugin-languages/agents/python-backend-engineer.md +214 -0
- package/packages/plugin-languages/agents/python-backend-expert.md +289 -0
- package/packages/plugin-languages/commands/javascript-optimize.md +636 -0
- package/packages/plugin-languages/commands/nodejs-api-scaffold.md +341 -0
- package/packages/plugin-languages/commands/nodejs-optimize.md +689 -0
- package/packages/plugin-languages/commands/python-api-scaffold.md +261 -0
- package/packages/plugin-languages/commands/python-optimize.md +593 -0
- package/packages/plugin-languages/package.json +65 -0
- package/packages/plugin-languages/plugin.json +265 -0
- package/packages/plugin-languages/rules/code-quality-standards.md +496 -0
- package/packages/plugin-languages/rules/testing-standards.md +768 -0
- package/packages/plugin-languages/scripts/examples/bash-production-script.sh +520 -0
- package/packages/plugin-languages/scripts/examples/javascript-es6-patterns.js +291 -0
- package/packages/plugin-languages/scripts/examples/nodejs-async-iteration.js +360 -0
- package/packages/plugin-languages/scripts/examples/python-async-patterns.py +289 -0
- package/packages/plugin-languages/scripts/examples/typescript-patterns.ts +432 -0
- package/packages/plugin-ml/README.md +430 -0
- package/packages/plugin-ml/agents/automl-expert.md +326 -0
- package/packages/plugin-ml/agents/computer-vision-expert.md +550 -0
- package/packages/plugin-ml/agents/gradient-boosting-expert.md +455 -0
- package/packages/plugin-ml/agents/neural-network-architect.md +1228 -0
- package/packages/plugin-ml/agents/nlp-transformer-expert.md +584 -0
- package/packages/plugin-ml/agents/pytorch-expert.md +412 -0
- package/packages/plugin-ml/agents/reinforcement-learning-expert.md +2088 -0
- package/packages/plugin-ml/agents/scikit-learn-expert.md +228 -0
- package/packages/plugin-ml/agents/tensorflow-keras-expert.md +509 -0
- package/packages/plugin-ml/agents/time-series-expert.md +303 -0
- package/packages/plugin-ml/commands/ml-automl.md +572 -0
- package/packages/plugin-ml/commands/ml-train-optimize.md +657 -0
- package/packages/plugin-ml/package.json +52 -0
- package/packages/plugin-ml/plugin.json +338 -0
- package/packages/plugin-pm/README.md +368 -0
- package/packages/plugin-pm/claudeautopm-plugin-pm-2.0.0.tgz +0 -0
- package/packages/plugin-pm/commands/azure/COMMANDS.md +107 -0
- package/packages/plugin-pm/commands/azure/COMMAND_MAPPING.md +252 -0
- package/packages/plugin-pm/commands/azure/INTEGRATION_FIX.md +103 -0
- package/packages/plugin-pm/commands/azure/README.md +246 -0
- package/packages/plugin-pm/commands/azure/active-work.md +198 -0
- package/packages/plugin-pm/commands/azure/aliases.md +143 -0
- package/packages/plugin-pm/commands/azure/blocked-items.md +287 -0
- package/packages/plugin-pm/commands/azure/clean.md +93 -0
- package/packages/plugin-pm/commands/azure/docs-query.md +48 -0
- package/packages/plugin-pm/commands/azure/feature-decompose.md +380 -0
- package/packages/plugin-pm/commands/azure/feature-list.md +61 -0
- package/packages/plugin-pm/commands/azure/feature-new.md +115 -0
- package/packages/plugin-pm/commands/azure/feature-show.md +205 -0
- package/packages/plugin-pm/commands/azure/feature-start.md +130 -0
- package/packages/plugin-pm/commands/azure/fix-integration-example.md +93 -0
- package/packages/plugin-pm/commands/azure/help.md +150 -0
- package/packages/plugin-pm/commands/azure/import-us.md +269 -0
- package/packages/plugin-pm/commands/azure/init.md +211 -0
- package/packages/plugin-pm/commands/azure/next-task.md +262 -0
- package/packages/plugin-pm/commands/azure/search.md +160 -0
- package/packages/plugin-pm/commands/azure/sprint-status.md +235 -0
- package/packages/plugin-pm/commands/azure/standup.md +260 -0
- package/packages/plugin-pm/commands/azure/sync-all.md +99 -0
- package/packages/plugin-pm/commands/azure/task-analyze.md +186 -0
- package/packages/plugin-pm/commands/azure/task-close.md +329 -0
- package/packages/plugin-pm/commands/azure/task-edit.md +145 -0
- package/packages/plugin-pm/commands/azure/task-list.md +263 -0
- package/packages/plugin-pm/commands/azure/task-new.md +84 -0
- package/packages/plugin-pm/commands/azure/task-reopen.md +79 -0
- package/packages/plugin-pm/commands/azure/task-show.md +126 -0
- package/packages/plugin-pm/commands/azure/task-start.md +301 -0
- package/packages/plugin-pm/commands/azure/task-status.md +65 -0
- package/packages/plugin-pm/commands/azure/task-sync.md +67 -0
- package/packages/plugin-pm/commands/azure/us-edit.md +164 -0
- package/packages/plugin-pm/commands/azure/us-list.md +202 -0
- package/packages/plugin-pm/commands/azure/us-new.md +265 -0
- package/packages/plugin-pm/commands/azure/us-parse.md +253 -0
- package/packages/plugin-pm/commands/azure/us-show.md +188 -0
- package/packages/plugin-pm/commands/azure/us-status.md +320 -0
- package/packages/plugin-pm/commands/azure/validate.md +86 -0
- package/packages/plugin-pm/commands/azure/work-item-sync.md +47 -0
- package/packages/plugin-pm/commands/blocked.md +28 -0
- package/packages/plugin-pm/commands/clean.md +119 -0
- package/packages/plugin-pm/commands/context-create.md +136 -0
- package/packages/plugin-pm/commands/context-prime.md +170 -0
- package/packages/plugin-pm/commands/context-update.md +292 -0
- package/packages/plugin-pm/commands/context.md +28 -0
- package/packages/plugin-pm/commands/epic-close.md +86 -0
- package/packages/plugin-pm/commands/epic-decompose.md +370 -0
- package/packages/plugin-pm/commands/epic-edit.md +83 -0
- package/packages/plugin-pm/commands/epic-list.md +30 -0
- package/packages/plugin-pm/commands/epic-merge.md +222 -0
- package/packages/plugin-pm/commands/epic-oneshot.md +119 -0
- package/packages/plugin-pm/commands/epic-refresh.md +119 -0
- package/packages/plugin-pm/commands/epic-show.md +28 -0
- package/packages/plugin-pm/commands/epic-split.md +120 -0
- package/packages/plugin-pm/commands/epic-start.md +195 -0
- package/packages/plugin-pm/commands/epic-status.md +28 -0
- package/packages/plugin-pm/commands/epic-sync-modular.md +338 -0
- package/packages/plugin-pm/commands/epic-sync-original.md +473 -0
- package/packages/plugin-pm/commands/epic-sync.md +486 -0
- package/packages/plugin-pm/commands/github/workflow-create.md +42 -0
- package/packages/plugin-pm/commands/help.md +28 -0
- package/packages/plugin-pm/commands/import.md +115 -0
- package/packages/plugin-pm/commands/in-progress.md +28 -0
- package/packages/plugin-pm/commands/init.md +28 -0
- package/packages/plugin-pm/commands/issue-analyze.md +202 -0
- package/packages/plugin-pm/commands/issue-close.md +119 -0
- package/packages/plugin-pm/commands/issue-edit.md +93 -0
- package/packages/plugin-pm/commands/issue-reopen.md +87 -0
- package/packages/plugin-pm/commands/issue-show.md +41 -0
- package/packages/plugin-pm/commands/issue-start.md +234 -0
- package/packages/plugin-pm/commands/issue-status.md +95 -0
- package/packages/plugin-pm/commands/issue-sync.md +411 -0
- package/packages/plugin-pm/commands/next.md +28 -0
- package/packages/plugin-pm/commands/prd-edit.md +82 -0
- package/packages/plugin-pm/commands/prd-list.md +28 -0
- package/packages/plugin-pm/commands/prd-new.md +55 -0
- package/packages/plugin-pm/commands/prd-parse.md +42 -0
- package/packages/plugin-pm/commands/prd-status.md +28 -0
- package/packages/plugin-pm/commands/search.md +28 -0
- package/packages/plugin-pm/commands/standup.md +28 -0
- package/packages/plugin-pm/commands/status.md +28 -0
- package/packages/plugin-pm/commands/sync.md +99 -0
- package/packages/plugin-pm/commands/test-reference-update.md +151 -0
- package/packages/plugin-pm/commands/validate.md +28 -0
- package/packages/plugin-pm/commands/what-next.md +28 -0
- package/packages/plugin-pm/package.json +57 -0
- package/packages/plugin-pm/plugin.json +503 -0
- package/packages/plugin-pm/scripts/pm/analytics.js +425 -0
- package/packages/plugin-pm/scripts/pm/blocked.js +164 -0
- package/packages/plugin-pm/scripts/pm/blocked.sh +78 -0
- package/packages/plugin-pm/scripts/pm/clean.js +464 -0
- package/packages/plugin-pm/scripts/pm/context-create.js +216 -0
- package/packages/plugin-pm/scripts/pm/context-prime.js +335 -0
- package/packages/plugin-pm/scripts/pm/context-update.js +344 -0
- package/packages/plugin-pm/scripts/pm/context.js +338 -0
- package/packages/plugin-pm/scripts/pm/epic-close.js +347 -0
- package/packages/plugin-pm/scripts/pm/epic-edit.js +382 -0
- package/packages/plugin-pm/scripts/pm/epic-list.js +273 -0
- package/packages/plugin-pm/scripts/pm/epic-list.sh +109 -0
- package/packages/plugin-pm/scripts/pm/epic-show.js +291 -0
- package/packages/plugin-pm/scripts/pm/epic-show.sh +105 -0
- package/packages/plugin-pm/scripts/pm/epic-split.js +522 -0
- package/packages/plugin-pm/scripts/pm/epic-start/epic-start.js +183 -0
- package/packages/plugin-pm/scripts/pm/epic-start/epic-start.sh +94 -0
- package/packages/plugin-pm/scripts/pm/epic-status.js +291 -0
- package/packages/plugin-pm/scripts/pm/epic-status.sh +104 -0
- package/packages/plugin-pm/scripts/pm/epic-sync/README.md +208 -0
- package/packages/plugin-pm/scripts/pm/epic-sync/create-epic-issue.sh +77 -0
- package/packages/plugin-pm/scripts/pm/epic-sync/create-task-issues.sh +86 -0
- package/packages/plugin-pm/scripts/pm/epic-sync/update-epic-file.sh +79 -0
- package/packages/plugin-pm/scripts/pm/epic-sync/update-references.sh +89 -0
- package/packages/plugin-pm/scripts/pm/epic-sync.sh +137 -0
- package/packages/plugin-pm/scripts/pm/help.js +92 -0
- package/packages/plugin-pm/scripts/pm/help.sh +90 -0
- package/packages/plugin-pm/scripts/pm/in-progress.js +178 -0
- package/packages/plugin-pm/scripts/pm/in-progress.sh +93 -0
- package/packages/plugin-pm/scripts/pm/init.js +321 -0
- package/packages/plugin-pm/scripts/pm/init.sh +178 -0
- package/packages/plugin-pm/scripts/pm/issue-close.js +232 -0
- package/packages/plugin-pm/scripts/pm/issue-edit.js +310 -0
- package/packages/plugin-pm/scripts/pm/issue-show.js +272 -0
- package/packages/plugin-pm/scripts/pm/issue-start.js +181 -0
- package/packages/plugin-pm/scripts/pm/issue-sync/format-comment.sh +468 -0
- package/packages/plugin-pm/scripts/pm/issue-sync/gather-updates.sh +460 -0
- package/packages/plugin-pm/scripts/pm/issue-sync/post-comment.sh +330 -0
- package/packages/plugin-pm/scripts/pm/issue-sync/preflight-validation.sh +348 -0
- package/packages/plugin-pm/scripts/pm/issue-sync/update-frontmatter.sh +387 -0
- package/packages/plugin-pm/scripts/pm/lib/README.md +85 -0
- package/packages/plugin-pm/scripts/pm/lib/epic-discovery.js +119 -0
- package/packages/plugin-pm/scripts/pm/lib/logger.js +78 -0
- package/packages/plugin-pm/scripts/pm/next.js +189 -0
- package/packages/plugin-pm/scripts/pm/next.sh +72 -0
- package/packages/plugin-pm/scripts/pm/optimize.js +407 -0
- package/packages/plugin-pm/scripts/pm/pr-create.js +337 -0
- package/packages/plugin-pm/scripts/pm/pr-list.js +257 -0
- package/packages/plugin-pm/scripts/pm/prd-list.js +242 -0
- package/packages/plugin-pm/scripts/pm/prd-list.sh +103 -0
- package/packages/plugin-pm/scripts/pm/prd-new.js +684 -0
- package/packages/plugin-pm/scripts/pm/prd-parse.js +547 -0
- package/packages/plugin-pm/scripts/pm/prd-status.js +152 -0
- package/packages/plugin-pm/scripts/pm/prd-status.sh +63 -0
- package/packages/plugin-pm/scripts/pm/release.js +460 -0
- package/packages/plugin-pm/scripts/pm/search.js +192 -0
- package/packages/plugin-pm/scripts/pm/search.sh +89 -0
- package/packages/plugin-pm/scripts/pm/standup.js +362 -0
- package/packages/plugin-pm/scripts/pm/standup.sh +95 -0
- package/packages/plugin-pm/scripts/pm/status.js +148 -0
- package/packages/plugin-pm/scripts/pm/status.sh +59 -0
- package/packages/plugin-pm/scripts/pm/sync-batch.js +337 -0
- package/packages/plugin-pm/scripts/pm/sync.js +343 -0
- package/packages/plugin-pm/scripts/pm/template-list.js +141 -0
- package/packages/plugin-pm/scripts/pm/template-new.js +366 -0
- package/packages/plugin-pm/scripts/pm/validate.js +274 -0
- package/packages/plugin-pm/scripts/pm/validate.sh +106 -0
- package/packages/plugin-pm/scripts/pm/what-next.js +660 -0
- package/packages/plugin-testing/README.md +401 -0
- package/packages/plugin-testing/agents/frontend-testing-engineer.md +768 -0
- package/packages/plugin-testing/commands/jest-optimize.md +800 -0
- package/packages/plugin-testing/commands/playwright-optimize.md +887 -0
- package/packages/plugin-testing/commands/test-coverage.md +512 -0
- package/packages/plugin-testing/commands/test-performance.md +1041 -0
- package/packages/plugin-testing/commands/test-setup.md +414 -0
- package/packages/plugin-testing/package.json +40 -0
- package/packages/plugin-testing/plugin.json +197 -0
- package/packages/plugin-testing/rules/test-coverage-requirements.md +581 -0
- package/packages/plugin-testing/rules/testing-standards.md +529 -0
- package/packages/plugin-testing/scripts/examples/react-testing-example.test.jsx +460 -0
- package/packages/plugin-testing/scripts/examples/vitest-config-example.js +352 -0
- package/packages/plugin-testing/scripts/examples/vue-testing-example.test.js +586 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { logError } = require('./lib/logger');
|
|
4
|
+
const { findAllEpicDirs } = require('./lib/epic-discovery');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* PM Next Script (Node.js version)
|
|
8
|
+
* Migrated from bash script with 100% backward compatibility
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
async function next() {
|
|
12
|
+
const result = {
|
|
13
|
+
availableTasks: [],
|
|
14
|
+
found: 0,
|
|
15
|
+
suggestions: [],
|
|
16
|
+
messages: []
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// Helper function to add messages
|
|
20
|
+
function addMessage(message) {
|
|
21
|
+
result.messages.push(message);
|
|
22
|
+
// Only log if running as CLI
|
|
23
|
+
if (require.main === module) {
|
|
24
|
+
console.log(message);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Header messages to match bash output exactly
|
|
29
|
+
addMessage('Getting status...');
|
|
30
|
+
addMessage('');
|
|
31
|
+
addMessage('');
|
|
32
|
+
|
|
33
|
+
addMessage('š Next Available Tasks');
|
|
34
|
+
addMessage('=======================');
|
|
35
|
+
addMessage('');
|
|
36
|
+
|
|
37
|
+
// Find tasks that are open and have no dependencies or whose dependencies are closed
|
|
38
|
+
try {
|
|
39
|
+
const availableTasks = await findAvailableTasks();
|
|
40
|
+
result.availableTasks = availableTasks;
|
|
41
|
+
result.found = availableTasks.length;
|
|
42
|
+
|
|
43
|
+
if (availableTasks.length > 0) {
|
|
44
|
+
for (const task of availableTasks) {
|
|
45
|
+
addMessage(`ā
Ready: #${task.taskNum} - ${task.name}`);
|
|
46
|
+
addMessage(` Epic: ${task.epicName}`);
|
|
47
|
+
if (task.parallel) {
|
|
48
|
+
addMessage(' š Can run in parallel');
|
|
49
|
+
}
|
|
50
|
+
addMessage('');
|
|
51
|
+
}
|
|
52
|
+
} else {
|
|
53
|
+
addMessage('No available tasks found.');
|
|
54
|
+
addMessage('');
|
|
55
|
+
|
|
56
|
+
// Add suggestions
|
|
57
|
+
const suggestions = [
|
|
58
|
+
'Check blocked tasks: /pm:blocked',
|
|
59
|
+
'View all tasks: /pm:epic-list'
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
result.suggestions = suggestions;
|
|
63
|
+
|
|
64
|
+
addMessage('š” Suggestions:');
|
|
65
|
+
for (const suggestion of suggestions) {
|
|
66
|
+
addMessage(` ⢠${suggestion}`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
addMessage('No available tasks found.');
|
|
71
|
+
addMessage('');
|
|
72
|
+
addMessage('š” Suggestions:');
|
|
73
|
+
addMessage(' ⢠Check blocked tasks: /pm:blocked');
|
|
74
|
+
addMessage(' ⢠View all tasks: /pm:epic-list');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
addMessage('');
|
|
78
|
+
|
|
79
|
+
// Display TDD reminder if tasks are available
|
|
80
|
+
if (result.found > 0) {
|
|
81
|
+
displayTddReminder(addMessage);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
addMessage(`š Summary: ${result.found} tasks ready to start`);
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Display TDD reminder to ensure test-driven development practices
|
|
91
|
+
* Extracted to maintain single responsibility and improve testability
|
|
92
|
+
* @param {Function} addMessage - Function to add messages to the output
|
|
93
|
+
*/
|
|
94
|
+
function displayTddReminder(addMessage) {
|
|
95
|
+
addMessage('ā ļø TDD REMINDER - Before starting work:');
|
|
96
|
+
addMessage('');
|
|
97
|
+
addMessage(' šØ ALWAYS follow Test-Driven Development:');
|
|
98
|
+
addMessage(' 1. RED: Write failing test first');
|
|
99
|
+
addMessage(' 2. GREEN: Write minimal code to pass');
|
|
100
|
+
addMessage(' 3. REFACTOR: Clean up while keeping tests green');
|
|
101
|
+
addMessage('');
|
|
102
|
+
addMessage(' See .claude/rules/tdd.enforcement.md for details');
|
|
103
|
+
addMessage('');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Helper function to find available tasks
|
|
107
|
+
async function findAvailableTasks() {
|
|
108
|
+
const availableTasks = [];
|
|
109
|
+
|
|
110
|
+
// Use shared epic discovery utility
|
|
111
|
+
const epicDirs = findAllEpicDirs();
|
|
112
|
+
|
|
113
|
+
for (const epicDir of epicDirs) {
|
|
114
|
+
const { name: epicName, path: epicPath } = epicDir;
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const taskFiles = fs.readdirSync(epicPath)
|
|
118
|
+
.filter(file => /^\d+.*\.md$/.test(file))
|
|
119
|
+
.sort();
|
|
120
|
+
|
|
121
|
+
for (const taskFile of taskFiles) {
|
|
122
|
+
const taskPath = path.join(epicPath, taskFile);
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const content = fs.readFileSync(taskPath, 'utf8');
|
|
126
|
+
|
|
127
|
+
// Check if task is open (case-insensitive)
|
|
128
|
+
const statusMatch = content.match(/^status:\s*(.+)$/m);
|
|
129
|
+
const status = statusMatch ? statusMatch[1].trim().toLowerCase() : '';
|
|
130
|
+
|
|
131
|
+
// Skip non-open tasks (only open tasks or tasks without status are available)
|
|
132
|
+
if (status !== 'open' && status !== '') {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Check dependencies
|
|
137
|
+
const depsMatch = content.match(/^depends_on:\s*\[(.*?)\]/m);
|
|
138
|
+
const depsStr = depsMatch ? depsMatch[1].trim() : '';
|
|
139
|
+
|
|
140
|
+
// If no dependencies or empty dependencies, task is available
|
|
141
|
+
if (!depsStr || depsStr === '') {
|
|
142
|
+
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
143
|
+
const name = nameMatch ? nameMatch[1].trim() : 'Unnamed Task';
|
|
144
|
+
|
|
145
|
+
const parallelMatch = content.match(/^parallel:\s*(.+)$/m);
|
|
146
|
+
const parallel = parallelMatch ? parallelMatch[1].trim() === 'true' : false;
|
|
147
|
+
|
|
148
|
+
const taskNum = path.basename(taskFile, '.md');
|
|
149
|
+
|
|
150
|
+
availableTasks.push({
|
|
151
|
+
taskNum,
|
|
152
|
+
name,
|
|
153
|
+
epicName,
|
|
154
|
+
parallel
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
// Log file read errors in DEBUG mode
|
|
159
|
+
if (process.env.DEBUG) {
|
|
160
|
+
console.error(`Error reading task file ${taskPath}:`, err.message);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} catch (err) {
|
|
165
|
+
// Log directory read errors in DEBUG mode
|
|
166
|
+
if (process.env.DEBUG) {
|
|
167
|
+
console.error(`Error reading epic directory ${epicPath}:`, err.message);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return availableTasks;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Export for use as module
|
|
176
|
+
module.exports = {
|
|
177
|
+
next,
|
|
178
|
+
findAvailableTasks
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
// CLI execution
|
|
182
|
+
if (require.main === module) {
|
|
183
|
+
module.exports.next().then(() => {
|
|
184
|
+
process.exit(0);
|
|
185
|
+
}).catch(err => {
|
|
186
|
+
logError('Next tasks command failed', err);
|
|
187
|
+
process.exit(1);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# PM Next Script - Wrapper for Node.js implementation
|
|
4
|
+
# This wrapper maintains backward compatibility while delegating to the Node.js version
|
|
5
|
+
|
|
6
|
+
# Get the directory of this script
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
|
|
9
|
+
# Check if Node.js is available
|
|
10
|
+
if command -v node >/dev/null 2>&1; then
|
|
11
|
+
# Use the Node.js implementation
|
|
12
|
+
node "$SCRIPT_DIR/next.js"
|
|
13
|
+
exit $?
|
|
14
|
+
else
|
|
15
|
+
# Fallback to the original bash implementation if Node.js is not available
|
|
16
|
+
echo "ā ļø Node.js not found, falling back to bash implementation"
|
|
17
|
+
echo ""
|
|
18
|
+
|
|
19
|
+
# Original bash implementation (preserved for fallback)
|
|
20
|
+
echo "Getting status..."
|
|
21
|
+
echo ""
|
|
22
|
+
echo ""
|
|
23
|
+
|
|
24
|
+
echo "š Next Available Tasks"
|
|
25
|
+
echo "======================="
|
|
26
|
+
echo ""
|
|
27
|
+
|
|
28
|
+
# Find tasks that are open and have no dependencies or whose dependencies are closed
|
|
29
|
+
found=0
|
|
30
|
+
|
|
31
|
+
for epic_dir in .claude/epics/*/; do
|
|
32
|
+
[ -d "$epic_dir" ] || continue
|
|
33
|
+
epic_name=$(basename "$epic_dir")
|
|
34
|
+
|
|
35
|
+
for task_file in "$epic_dir"[0-9]*.md; do
|
|
36
|
+
[ -f "$task_file" ] || continue
|
|
37
|
+
|
|
38
|
+
# Check if task is open
|
|
39
|
+
status=$(grep "^status:" "$task_file" | head -1 | sed 's/^status: *//')
|
|
40
|
+
[ "$status" != "open" ] && [ -n "$status" ] && continue
|
|
41
|
+
|
|
42
|
+
# Check dependencies
|
|
43
|
+
deps=$(grep "^depends_on:" "$task_file" | head -1 | sed 's/^depends_on: *\[//' | sed 's/\]//')
|
|
44
|
+
|
|
45
|
+
# If no dependencies or empty, task is available
|
|
46
|
+
if [ -z "$deps" ] || [ "$deps" = "depends_on:" ]; then
|
|
47
|
+
task_name=$(grep "^name:" "$task_file" | head -1 | sed 's/^name: *//')
|
|
48
|
+
task_num=$(basename "$task_file" .md)
|
|
49
|
+
parallel=$(grep "^parallel:" "$task_file" | head -1 | sed 's/^parallel: *//')
|
|
50
|
+
|
|
51
|
+
echo "ā
Ready: #$task_num - $task_name"
|
|
52
|
+
echo " Epic: $epic_name"
|
|
53
|
+
[ "$parallel" = "true" ] && echo " š Can run in parallel"
|
|
54
|
+
echo ""
|
|
55
|
+
((found++))
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
done
|
|
59
|
+
|
|
60
|
+
if [ $found -eq 0 ]; then
|
|
61
|
+
echo "No available tasks found."
|
|
62
|
+
echo ""
|
|
63
|
+
echo "š” Suggestions:"
|
|
64
|
+
echo " ⢠Check blocked tasks: /pm:blocked"
|
|
65
|
+
echo " ⢠View all tasks: /pm:epic-list"
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
echo ""
|
|
69
|
+
echo "š Summary: $found tasks ready to start"
|
|
70
|
+
|
|
71
|
+
exit 0
|
|
72
|
+
fi
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Optimize - Analyze and optimize project for better performance
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const path = require('path');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
class ProjectOptimizer {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.claudeDir = '.claude';
|
|
13
|
+
this.stats = {
|
|
14
|
+
contextFiles: 0,
|
|
15
|
+
agentFiles: 0,
|
|
16
|
+
issueFiles: 0,
|
|
17
|
+
epicFiles: 0,
|
|
18
|
+
totalSize: 0,
|
|
19
|
+
duplicates: [],
|
|
20
|
+
largeFiles: [],
|
|
21
|
+
oldFiles: [],
|
|
22
|
+
suggestions: []
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
execCommand(command, options = {}) {
|
|
27
|
+
try {
|
|
28
|
+
return execSync(command, { encoding: 'utf8', ...options }).trim();
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (!options.ignoreError) {
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
formatBytes(bytes) {
|
|
38
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
39
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
40
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
analyzeDirectory(dir, type) {
|
|
44
|
+
if (!fs.existsSync(dir)) return;
|
|
45
|
+
|
|
46
|
+
const files = fs.readdirSync(dir);
|
|
47
|
+
let count = 0;
|
|
48
|
+
let totalSize = 0;
|
|
49
|
+
|
|
50
|
+
files.forEach(file => {
|
|
51
|
+
const filePath = path.join(dir, file);
|
|
52
|
+
const stats = fs.statSync(filePath);
|
|
53
|
+
|
|
54
|
+
if (stats.isFile()) {
|
|
55
|
+
count++;
|
|
56
|
+
totalSize += stats.size;
|
|
57
|
+
|
|
58
|
+
// Check for large files (>100KB)
|
|
59
|
+
if (stats.size > 100 * 1024) {
|
|
60
|
+
this.stats.largeFiles.push({
|
|
61
|
+
path: filePath,
|
|
62
|
+
size: stats.size
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Check for old files (>30 days)
|
|
67
|
+
const ageInDays = (Date.now() - stats.mtime) / (1000 * 60 * 60 * 24);
|
|
68
|
+
if (ageInDays > 30) {
|
|
69
|
+
this.stats.oldFiles.push({
|
|
70
|
+
path: filePath,
|
|
71
|
+
age: Math.floor(ageInDays)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
return { count, totalSize };
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
findDuplicates() {
|
|
81
|
+
const fileHashes = new Map();
|
|
82
|
+
const duplicates = [];
|
|
83
|
+
|
|
84
|
+
const processDir = (dir) => {
|
|
85
|
+
if (!fs.existsSync(dir)) return;
|
|
86
|
+
|
|
87
|
+
const files = fs.readdirSync(dir);
|
|
88
|
+
files.forEach(file => {
|
|
89
|
+
const filePath = path.join(dir, file);
|
|
90
|
+
const stats = fs.statSync(filePath);
|
|
91
|
+
|
|
92
|
+
if (stats.isDirectory() && !filePath.includes('node_modules')) {
|
|
93
|
+
processDir(filePath);
|
|
94
|
+
} else if (stats.isFile()) {
|
|
95
|
+
// Simple duplicate detection based on size and name
|
|
96
|
+
const key = `${file}-${stats.size}`;
|
|
97
|
+
if (fileHashes.has(key)) {
|
|
98
|
+
duplicates.push({
|
|
99
|
+
original: fileHashes.get(key),
|
|
100
|
+
duplicate: filePath,
|
|
101
|
+
size: stats.size
|
|
102
|
+
});
|
|
103
|
+
} else {
|
|
104
|
+
fileHashes.set(key, filePath);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
processDir(this.claudeDir);
|
|
111
|
+
return duplicates;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
analyzeContextOptimization() {
|
|
115
|
+
const suggestions = [];
|
|
116
|
+
const contextDir = path.join(this.claudeDir, 'contexts');
|
|
117
|
+
|
|
118
|
+
if (fs.existsSync(contextDir)) {
|
|
119
|
+
const files = fs.readdirSync(contextDir);
|
|
120
|
+
|
|
121
|
+
// Check for redundant contexts
|
|
122
|
+
const contextTypes = new Map();
|
|
123
|
+
files.forEach(file => {
|
|
124
|
+
const match = file.match(/^(.+?)-/);
|
|
125
|
+
if (match) {
|
|
126
|
+
const type = match[1];
|
|
127
|
+
if (!contextTypes.has(type)) {
|
|
128
|
+
contextTypes.set(type, []);
|
|
129
|
+
}
|
|
130
|
+
contextTypes.get(type).push(file);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
contextTypes.forEach((files, type) => {
|
|
135
|
+
if (files.length > 3) {
|
|
136
|
+
suggestions.push({
|
|
137
|
+
type: 'consolidation',
|
|
138
|
+
message: `Consider consolidating ${files.length} ${type} contexts`,
|
|
139
|
+
impact: 'high',
|
|
140
|
+
files: files
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return suggestions;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
analyzeAgentUsage() {
|
|
150
|
+
const suggestions = [];
|
|
151
|
+
const agentsDir = path.join(this.claudeDir, 'agents');
|
|
152
|
+
|
|
153
|
+
if (fs.existsSync(agentsDir)) {
|
|
154
|
+
// Check for unused agents (no recent modifications)
|
|
155
|
+
const analyzeAgentDir = (dir) => {
|
|
156
|
+
const files = fs.readdirSync(dir);
|
|
157
|
+
|
|
158
|
+
files.forEach(file => {
|
|
159
|
+
const filePath = path.join(dir, file);
|
|
160
|
+
const stats = fs.statSync(filePath);
|
|
161
|
+
|
|
162
|
+
if (stats.isFile() && file.endsWith('.md')) {
|
|
163
|
+
const ageInDays = (Date.now() - stats.atime) / (1000 * 60 * 60 * 24);
|
|
164
|
+
if (ageInDays > 60) {
|
|
165
|
+
suggestions.push({
|
|
166
|
+
type: 'unused',
|
|
167
|
+
message: `Agent not used in ${Math.floor(ageInDays)} days: ${file}`,
|
|
168
|
+
impact: 'low',
|
|
169
|
+
path: filePath
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
} else if (stats.isDirectory()) {
|
|
173
|
+
analyzeAgentDir(filePath);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
analyzeAgentDir(agentsDir);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return suggestions;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
analyzeGitOptimization() {
|
|
185
|
+
const suggestions = [];
|
|
186
|
+
|
|
187
|
+
// Check git repo size
|
|
188
|
+
try {
|
|
189
|
+
const repoSize = this.execCommand('du -sh .git', { ignoreError: true });
|
|
190
|
+
if (repoSize) {
|
|
191
|
+
const sizeMatch = repoSize.match(/(\d+)([MG])/);
|
|
192
|
+
if (sizeMatch) {
|
|
193
|
+
const size = parseInt(sizeMatch[1]);
|
|
194
|
+
const unit = sizeMatch[2];
|
|
195
|
+
|
|
196
|
+
if ((unit === 'G') || (unit === 'M' && size > 100)) {
|
|
197
|
+
suggestions.push({
|
|
198
|
+
type: 'git',
|
|
199
|
+
message: `Large git repository (${repoSize}). Consider running 'git gc --aggressive'`,
|
|
200
|
+
impact: 'high',
|
|
201
|
+
command: 'git gc --aggressive'
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
} catch {}
|
|
207
|
+
|
|
208
|
+
// Check for large files in git history
|
|
209
|
+
try {
|
|
210
|
+
const largeFiles = this.execCommand(
|
|
211
|
+
'git rev-list --all --objects | git cat-file --batch-check="%(objecttype) %(objectname) %(objectsize) %(rest)" | awk \'$1=="blob" && $3>1000000 {print $4, $3}\' | head -5',
|
|
212
|
+
{ ignoreError: true }
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
if (largeFiles) {
|
|
216
|
+
suggestions.push({
|
|
217
|
+
type: 'git',
|
|
218
|
+
message: 'Large files found in git history',
|
|
219
|
+
impact: 'medium',
|
|
220
|
+
details: largeFiles
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
} catch {}
|
|
224
|
+
|
|
225
|
+
return suggestions;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async optimize(options = {}) {
|
|
229
|
+
console.log(`\nš§ Project Optimization Analysis`);
|
|
230
|
+
console.log(`${'ā'.repeat(50)}\n`);
|
|
231
|
+
|
|
232
|
+
// 1. Analyze directories
|
|
233
|
+
console.log('š Analyzing project structure...');
|
|
234
|
+
|
|
235
|
+
const contexts = this.analyzeDirectory(path.join(this.claudeDir, 'contexts'), 'context');
|
|
236
|
+
const issues = this.analyzeDirectory(path.join(this.claudeDir, 'issues'), 'issue');
|
|
237
|
+
const epics = this.analyzeDirectory(path.join(this.claudeDir, 'epics'), 'epic');
|
|
238
|
+
const prds = this.analyzeDirectory(path.join(this.claudeDir, 'prds'), 'prd');
|
|
239
|
+
|
|
240
|
+
// 2. Find duplicates
|
|
241
|
+
if (!options.skipDuplicates) {
|
|
242
|
+
console.log('š Checking for duplicates...');
|
|
243
|
+
this.stats.duplicates = this.findDuplicates();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 3. Analyze optimizations
|
|
247
|
+
console.log('š” Generating optimization suggestions...');
|
|
248
|
+
const contextSuggestions = this.analyzeContextOptimization();
|
|
249
|
+
const agentSuggestions = this.analyzeAgentUsage();
|
|
250
|
+
const gitSuggestions = this.analyzeGitOptimization();
|
|
251
|
+
|
|
252
|
+
this.stats.suggestions = [
|
|
253
|
+
...contextSuggestions,
|
|
254
|
+
...agentSuggestions,
|
|
255
|
+
...gitSuggestions
|
|
256
|
+
];
|
|
257
|
+
|
|
258
|
+
// 4. Display results
|
|
259
|
+
console.log(`\n${'ā'.repeat(50)}`);
|
|
260
|
+
console.log('š Analysis Results:');
|
|
261
|
+
console.log(`${'ā'.repeat(50)}\n`);
|
|
262
|
+
|
|
263
|
+
// File counts
|
|
264
|
+
console.log('š File Statistics:');
|
|
265
|
+
if (contexts) console.log(` ⢠Contexts: ${contexts.count} files (${this.formatBytes(contexts.totalSize)})`);
|
|
266
|
+
if (issues) console.log(` ⢠Issues: ${issues.count} files (${this.formatBytes(issues.totalSize)})`);
|
|
267
|
+
if (epics) console.log(` ⢠Epics: ${epics.count} files (${this.formatBytes(epics.totalSize)})`);
|
|
268
|
+
if (prds) console.log(` ⢠PRDs: ${prds.count} files (${this.formatBytes(prds.totalSize)})`);
|
|
269
|
+
|
|
270
|
+
// Large files
|
|
271
|
+
if (this.stats.largeFiles.length > 0) {
|
|
272
|
+
console.log('\nš¦ Large Files (>100KB):');
|
|
273
|
+
this.stats.largeFiles.slice(0, 5).forEach(file => {
|
|
274
|
+
console.log(` ⢠${path.relative('.', file.path)}: ${this.formatBytes(file.size)}`);
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Old files
|
|
279
|
+
if (this.stats.oldFiles.length > 0) {
|
|
280
|
+
console.log('\nš
Old Files (>30 days):');
|
|
281
|
+
this.stats.oldFiles.slice(0, 5).forEach(file => {
|
|
282
|
+
console.log(` ⢠${path.relative('.', file.path)}: ${file.age} days old`);
|
|
283
|
+
});
|
|
284
|
+
if (this.stats.oldFiles.length > 5) {
|
|
285
|
+
console.log(` ... and ${this.stats.oldFiles.length - 5} more`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Duplicates
|
|
290
|
+
if (this.stats.duplicates.length > 0) {
|
|
291
|
+
console.log('\nš Duplicate Files:');
|
|
292
|
+
this.stats.duplicates.slice(0, 5).forEach(dup => {
|
|
293
|
+
console.log(` ⢠${path.basename(dup.duplicate)}`);
|
|
294
|
+
console.log(` Original: ${path.relative('.', dup.original)}`);
|
|
295
|
+
console.log(` Duplicate: ${path.relative('.', dup.duplicate)}`);
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Optimization suggestions
|
|
300
|
+
if (this.stats.suggestions.length > 0) {
|
|
301
|
+
console.log('\nš” Optimization Suggestions:');
|
|
302
|
+
console.log(`${'ā'.repeat(50)}`);
|
|
303
|
+
|
|
304
|
+
// Group by impact
|
|
305
|
+
const highImpact = this.stats.suggestions.filter(s => s.impact === 'high');
|
|
306
|
+
const mediumImpact = this.stats.suggestions.filter(s => s.impact === 'medium');
|
|
307
|
+
const lowImpact = this.stats.suggestions.filter(s => s.impact === 'low');
|
|
308
|
+
|
|
309
|
+
if (highImpact.length > 0) {
|
|
310
|
+
console.log('\nš“ High Impact:');
|
|
311
|
+
highImpact.forEach(s => {
|
|
312
|
+
console.log(` ⢠${s.message}`);
|
|
313
|
+
if (s.command) console.log(` Run: ${s.command}`);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (mediumImpact.length > 0) {
|
|
318
|
+
console.log('\nš” Medium Impact:');
|
|
319
|
+
mediumImpact.forEach(s => {
|
|
320
|
+
console.log(` ⢠${s.message}`);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (lowImpact.length > 0) {
|
|
325
|
+
console.log('\nš¢ Low Impact:');
|
|
326
|
+
lowImpact.slice(0, 3).forEach(s => {
|
|
327
|
+
console.log(` ⢠${s.message}`);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
} else {
|
|
331
|
+
console.log('\nā
No optimization issues found!');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Actions
|
|
335
|
+
if (this.stats.oldFiles.length > 0 || this.stats.duplicates.length > 0) {
|
|
336
|
+
console.log(`\n${'ā'.repeat(50)}`);
|
|
337
|
+
console.log('šÆ Recommended Actions:');
|
|
338
|
+
console.log(' 1. Run: pm clean # Archive old files');
|
|
339
|
+
console.log(' 2. Run: pm validate # Check system integrity');
|
|
340
|
+
console.log(' 3. Run: git gc --aggressive # Optimize git repository');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Apply optimizations if requested
|
|
344
|
+
if (options.apply) {
|
|
345
|
+
console.log('\nš§ Applying optimizations...');
|
|
346
|
+
await this.applyOptimizations();
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async applyOptimizations() {
|
|
353
|
+
let applied = 0;
|
|
354
|
+
|
|
355
|
+
// Clean old files
|
|
356
|
+
if (this.stats.oldFiles.length > 10) {
|
|
357
|
+
console.log(' ⢠Archiving old files...');
|
|
358
|
+
this.execCommand('pm clean --days=30', { ignoreError: true });
|
|
359
|
+
applied++;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Run git gc if needed
|
|
363
|
+
const gitOptimization = this.stats.suggestions.find(s => s.command === 'git gc --aggressive');
|
|
364
|
+
if (gitOptimization) {
|
|
365
|
+
console.log(' ⢠Optimizing git repository...');
|
|
366
|
+
this.execCommand('git gc', { ignoreError: true });
|
|
367
|
+
applied++;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
console.log(`\nā
Applied ${applied} optimization${applied !== 1 ? 's' : ''}`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
async run(args) {
|
|
374
|
+
const options = {};
|
|
375
|
+
|
|
376
|
+
// Parse arguments
|
|
377
|
+
args.forEach(arg => {
|
|
378
|
+
if (arg === '--apply' || arg === '-a') {
|
|
379
|
+
options.apply = true;
|
|
380
|
+
} else if (arg === '--skip-duplicates') {
|
|
381
|
+
options.skipDuplicates = true;
|
|
382
|
+
} else if (arg === '--help' || arg === '-h') {
|
|
383
|
+
console.log('Usage: pm optimize [options]');
|
|
384
|
+
console.log('\nOptions:');
|
|
385
|
+
console.log(' -a, --apply Apply recommended optimizations');
|
|
386
|
+
console.log(' --skip-duplicates Skip duplicate file detection');
|
|
387
|
+
console.log('\nExamples:');
|
|
388
|
+
console.log(' pm optimize # Analyze project');
|
|
389
|
+
console.log(' pm optimize --apply # Analyze and apply optimizations');
|
|
390
|
+
process.exit(0);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
await this.optimize(options);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Main execution
|
|
399
|
+
if (require.main === module) {
|
|
400
|
+
const optimizer = new ProjectOptimizer();
|
|
401
|
+
optimizer.run(process.argv.slice(2)).catch(error => {
|
|
402
|
+
console.error('ā Error:', error.message);
|
|
403
|
+
process.exit(1);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
module.exports = ProjectOptimizer;
|