aios-core 4.2.15 → 4.4.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/.aios-core/cli/commands/validate/index.js +1 -1
- package/.aios-core/core/code-intel/code-intel-client.js +19 -5
- package/.aios-core/core/code-intel/helpers/creation-helper.js +183 -0
- package/.aios-core/core/code-intel/helpers/devops-helper.js +166 -0
- package/.aios-core/core/code-intel/helpers/planning-helper.js +248 -0
- package/.aios-core/core/code-intel/helpers/qa-helper.js +187 -0
- package/.aios-core/core/code-intel/helpers/story-helper.js +146 -0
- package/.aios-core/core/code-intel/hook-runtime.js +186 -0
- package/.aios-core/core/code-intel/index.js +2 -0
- package/.aios-core/core/code-intel/providers/code-graph-provider.js +8 -0
- package/.aios-core/core/code-intel/providers/provider-interface.js +9 -0
- package/.aios-core/core/code-intel/providers/registry-provider.js +515 -0
- package/.aios-core/core/config/schemas/framework-config.schema.json +155 -7
- package/.aios-core/core/config/schemas/project-config.schema.json +329 -15
- package/.aios-core/core/config/template-overrides.js +84 -0
- package/.aios-core/core/docs/troubleshooting-guide.md +1 -1
- package/.aios-core/core/doctor/checks/agent-memory.js +63 -0
- package/.aios-core/core/doctor/checks/claude-md.js +56 -0
- package/.aios-core/core/doctor/checks/code-intel.js +131 -0
- package/.aios-core/core/doctor/checks/commands-count.js +81 -0
- package/.aios-core/core/doctor/checks/core-config.js +53 -0
- package/.aios-core/core/doctor/checks/entity-registry.js +53 -0
- package/.aios-core/core/doctor/checks/git-hooks.js +50 -0
- package/.aios-core/core/doctor/checks/graph-dashboard.js +48 -0
- package/.aios-core/core/doctor/checks/hooks-claude-count.js +118 -0
- package/.aios-core/core/doctor/checks/ide-sync.js +85 -0
- package/.aios-core/core/doctor/checks/index.js +46 -0
- package/.aios-core/core/doctor/checks/node-version.js +33 -0
- package/.aios-core/core/doctor/checks/npm-packages.js +35 -0
- package/.aios-core/core/doctor/checks/rules-files.js +61 -0
- package/.aios-core/core/doctor/checks/settings-json.js +121 -0
- package/.aios-core/core/doctor/checks/skills-count.js +72 -0
- package/.aios-core/core/doctor/fix-handler.js +165 -0
- package/.aios-core/core/doctor/formatters/json.js +14 -0
- package/.aios-core/core/doctor/formatters/text.js +59 -0
- package/.aios-core/core/doctor/index.js +94 -0
- package/.aios-core/core/graph-dashboard/cli.js +361 -0
- package/.aios-core/core/graph-dashboard/data-sources/code-intel-source.js +234 -0
- package/.aios-core/core/graph-dashboard/data-sources/metrics-source.js +95 -0
- package/.aios-core/core/graph-dashboard/data-sources/registry-source.js +106 -0
- package/.aios-core/core/graph-dashboard/formatters/dot-formatter.js +45 -0
- package/.aios-core/core/graph-dashboard/formatters/html-formatter.js +1437 -0
- package/.aios-core/core/graph-dashboard/formatters/json-formatter.js +13 -0
- package/.aios-core/core/graph-dashboard/formatters/mermaid-formatter.js +59 -0
- package/.aios-core/core/graph-dashboard/index.js +21 -0
- package/.aios-core/core/graph-dashboard/renderers/stats-renderer.js +217 -0
- package/.aios-core/core/graph-dashboard/renderers/status-renderer.js +125 -0
- package/.aios-core/core/graph-dashboard/renderers/tree-renderer.js +119 -0
- package/.aios-core/core/health-check/base-check.js +1 -1
- package/.aios-core/core/health-check/check-registry.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/build-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/ci-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/deployment-readiness.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/docker-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/env-file.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/index.js +1 -1
- package/.aios-core/core/health-check/checks/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/disk-space.js +1 -1
- package/.aios-core/core/health-check/checks/local/environment-vars.js +1 -1
- package/.aios-core/core/health-check/checks/local/git-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/ide-detection.js +1 -1
- package/.aios-core/core/health-check/checks/local/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/memory.js +1 -1
- package/.aios-core/core/health-check/checks/local/network.js +1 -1
- package/.aios-core/core/health-check/checks/local/npm-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/shell-environment.js +1 -1
- package/.aios-core/core/health-check/checks/project/agent-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/aios-directory.js +1 -1
- package/.aios-core/core/health-check/checks/project/dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/project/framework-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/index.js +1 -1
- package/.aios-core/core/health-check/checks/project/node-version.js +1 -1
- package/.aios-core/core/health-check/checks/project/package-json.js +1 -1
- package/.aios-core/core/health-check/checks/project/task-definitions.js +1 -1
- package/.aios-core/core/health-check/checks/project/workflow-dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/repository/branch-protection.js +1 -1
- package/.aios-core/core/health-check/checks/repository/commit-history.js +1 -1
- package/.aios-core/core/health-check/checks/repository/conflicts.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-repo.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-status.js +1 -1
- package/.aios-core/core/health-check/checks/repository/gitignore.js +1 -1
- package/.aios-core/core/health-check/checks/repository/index.js +1 -1
- package/.aios-core/core/health-check/checks/repository/large-files.js +1 -1
- package/.aios-core/core/health-check/checks/repository/lockfile-integrity.js +1 -1
- package/.aios-core/core/health-check/checks/services/api-endpoints.js +1 -1
- package/.aios-core/core/health-check/checks/services/claude-code.js +1 -1
- package/.aios-core/core/health-check/checks/services/gemini-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/github-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/index.js +1 -1
- package/.aios-core/core/health-check/checks/services/mcp-integration.js +1 -1
- package/.aios-core/core/health-check/engine.js +1 -1
- package/.aios-core/core/health-check/healers/backup-manager.js +1 -1
- package/.aios-core/core/health-check/healers/index.js +1 -1
- package/.aios-core/core/health-check/index.js +9 -2
- package/.aios-core/core/health-check/reporters/console.js +1 -1
- package/.aios-core/core/health-check/reporters/index.js +1 -1
- package/.aios-core/core/health-check/reporters/json.js +1 -1
- package/.aios-core/core/health-check/reporters/markdown.js +1 -1
- package/.aios-core/core/ids/layer-classifier.js +65 -0
- package/.aios-core/core/ids/registry-updater.js +49 -0
- package/.aios-core/core/index.esm.js +1 -1
- package/.aios-core/core/index.js +1 -1
- package/.aios-core/core/session/context-detector.js +2 -7
- package/.aios-core/core/synapse/context/context-tracker.js +9 -1
- package/.aios-core/core/synapse/engine.js +33 -13
- package/.aios-core/core/synapse/memory/memory-bridge.js +17 -43
- package/.aios-core/core/synapse/memory/synapse-memory-provider.js +201 -0
- package/.aios-core/core/synapse/runtime/hook-runtime.js +40 -2
- package/.aios-core/core/synapse/session/session-manager.js +3 -2
- package/.aios-core/core/synapse/utils/atomic-write.js +79 -0
- package/.aios-core/core-config.yaml +34 -1
- package/.aios-core/data/aios-kb.md +2 -2
- package/.aios-core/data/capability-detection.js +290 -0
- package/.aios-core/data/entity-registry.yaml +10450 -2129
- package/.aios-core/data/mcp-discipline.js +166 -0
- package/.aios-core/data/mcp-tool-examples.yaml +215 -0
- package/.aios-core/data/tok2-validation.js +168 -0
- package/.aios-core/data/tok3-token-comparison.js +123 -0
- package/.aios-core/data/tool-registry.yaml +648 -0
- package/.aios-core/data/tool-search-validation.js +174 -0
- package/.aios-core/data/workflow-chains.yaml +156 -0
- package/.aios-core/development/agents/aios-master.md +17 -10
- package/.aios-core/development/agents/analyst/MEMORY.md +33 -0
- package/.aios-core/development/agents/analyst.md +17 -10
- package/.aios-core/development/agents/architect/MEMORY.md +39 -0
- package/.aios-core/development/agents/architect.md +17 -10
- package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
- package/.aios-core/development/agents/data-engineer.md +17 -10
- package/.aios-core/development/agents/dev/MEMORY.md +46 -0
- package/.aios-core/development/agents/dev.md +18 -11
- package/.aios-core/development/agents/devops/MEMORY.md +39 -0
- package/.aios-core/development/agents/devops.md +44 -10
- package/.aios-core/development/agents/pm/MEMORY.md +38 -0
- package/.aios-core/development/agents/pm.md +17 -10
- package/.aios-core/development/agents/po/MEMORY.md +45 -0
- package/.aios-core/development/agents/po.md +17 -10
- package/.aios-core/development/agents/qa/MEMORY.md +42 -0
- package/.aios-core/development/agents/qa.md +18 -11
- package/.aios-core/development/agents/sm/MEMORY.md +31 -0
- package/.aios-core/development/agents/sm.md +17 -10
- package/.aios-core/development/agents/squad-creator.md +18 -9
- package/.aios-core/development/agents/ux/MEMORY.md +31 -0
- package/.aios-core/development/agents/ux-design-expert.md +16 -9
- package/.aios-core/development/checklists/issue-triage-checklist.md +35 -0
- package/.aios-core/development/checklists/memory-audit-checklist.md +53 -0
- package/.aios-core/development/scripts/issue-triage.js +171 -0
- package/.aios-core/development/scripts/populate-entity-registry.js +412 -19
- package/.aios-core/development/scripts/unified-activation-pipeline.js +31 -10
- package/.aios-core/development/tasks/analyze-project-structure.md +48 -0
- package/.aios-core/development/tasks/apply-qa-fixes.md +7 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +8 -1
- package/.aios-core/development/tasks/brownfield-create-epic.md +41 -0
- package/.aios-core/development/tasks/brownfield-create-story.md +7 -0
- package/.aios-core/development/tasks/build-autonomous.md +7 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +7 -0
- package/.aios-core/development/tasks/create-doc.md +44 -0
- package/.aios-core/development/tasks/create-next-story.md +17 -0
- package/.aios-core/development/tasks/create-suite.md +7 -0
- package/.aios-core/development/tasks/dev-develop-story.md +9 -1
- package/.aios-core/development/tasks/execute-checklist.md +7 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +56 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +70 -0
- package/.aios-core/development/tasks/github-issue-triage.md +118 -0
- package/.aios-core/development/tasks/health-check.yaml +206 -171
- package/.aios-core/development/tasks/kb-mode-interaction.md +3 -3
- package/.aios-core/development/tasks/plan-create-context.md +47 -1
- package/.aios-core/development/tasks/plan-create-implementation.md +55 -0
- package/.aios-core/development/tasks/po-close-story.md +7 -0
- package/.aios-core/development/tasks/pr-automation.md +5 -5
- package/.aios-core/development/tasks/qa-create-fix-request.md +7 -0
- package/.aios-core/development/tasks/qa-fix-issues.md +7 -0
- package/.aios-core/development/tasks/qa-gate.md +56 -0
- package/.aios-core/development/tasks/qa-review-story.md +32 -1
- package/.aios-core/development/tasks/release-management.md +7 -0
- package/.aios-core/development/tasks/resolve-github-issue.md +608 -0
- package/.aios-core/development/tasks/review-contributor-pr.md +152 -0
- package/.aios-core/development/tasks/setup-llm-routing.md +1 -1
- package/.aios-core/development/tasks/spec-critique.md +8 -0
- package/.aios-core/development/tasks/spec-gather-requirements.md +7 -0
- package/.aios-core/development/tasks/spec-research-dependencies.md +4 -0
- package/.aios-core/development/tasks/spec-write-spec.md +5 -0
- package/.aios-core/development/tasks/triage-github-issues.md +356 -0
- package/.aios-core/development/tasks/validate-agents.md +4 -0
- package/.aios-core/development/tasks/validate-next-story.md +17 -0
- package/.aios-core/development/templates/agent-handoff-tmpl.yaml +48 -0
- package/.aios-core/development/templates/code-intel-integration-pattern.md +199 -0
- package/.aios-core/development/templates/ptc-entity-validation.md +113 -0
- package/.aios-core/development/templates/ptc-qa-gate.md +100 -0
- package/.aios-core/development/templates/ptc-research-aggregation.md +94 -0
- package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
- package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
- package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
- package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
- package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
- package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
- package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
- package/.aios-core/development/templates/squad/agent-template.md +11 -0
- package/.aios-core/development/templates/squad/task-template.md +21 -0
- package/.aios-core/development/templates/squad-template/LICENSE +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +1 -1
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1 -1
- package/.aios-core/framework-config.yaml +8 -0
- package/.aios-core/index.esm.js +1 -1
- package/.aios-core/index.js +1 -1
- package/.aios-core/infrastructure/integrations/ai-providers/index.js +1 -1
- package/.aios-core/infrastructure/schemas/task-v3-schema.json +6 -0
- package/.aios-core/infrastructure/scripts/collect-tool-usage.js +311 -0
- package/.aios-core/infrastructure/scripts/generate-optimization-report.js +497 -0
- package/.aios-core/infrastructure/scripts/generate-settings-json.js +300 -0
- package/.aios-core/infrastructure/scripts/git-config-detector.js +65 -9
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +3 -1
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/github-copilot.js +184 -0
- package/.aios-core/infrastructure/scripts/repository-detector.js +3 -3
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +182 -182
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
- package/.aios-core/install-manifest.yaml +613 -305
- package/.aios-core/lib/build.json +1 -0
- package/.aios-core/local-config.yaml.template +71 -71
- package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
- package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
- package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
- package/.aios-core/monitor/hooks/notification.py +29 -29
- package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
- package/.aios-core/monitor/hooks/pre_compact.py +29 -29
- package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
- package/.aios-core/monitor/hooks/stop.py +29 -29
- package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
- package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
- package/.aios-core/product/templates/adr.hbs +125 -125
- package/.aios-core/product/templates/dbdr.hbs +241 -241
- package/.aios-core/product/templates/epic.hbs +212 -212
- package/.aios-core/product/templates/ide-rules/claude-rules.md +125 -0
- package/.aios-core/product/templates/pmdr.hbs +186 -186
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
- package/.aios-core/product/templates/prd.hbs +201 -201
- package/.aios-core/product/templates/story.hbs +263 -263
- package/.aios-core/product/templates/task.hbs +170 -170
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
- package/.aios-core/product/templates/tmpl-view.sql +177 -177
- package/.aios-core/scripts/pm.sh +0 -0
- package/.aios-core/user-guide.md +15 -15
- package/.aios-core/utils/filters/constants.js +10 -0
- package/.aios-core/utils/filters/content-filter.js +223 -0
- package/.aios-core/utils/filters/field-filter.js +126 -0
- package/.aios-core/utils/filters/index.js +180 -0
- package/.aios-core/utils/filters/schema-filter.js +157 -0
- package/.claude/CLAUDE.md +62 -0
- package/.claude/hooks/enforce-architecture-first.py +196 -196
- package/.claude/hooks/enforce-git-push-authority.sh +33 -0
- package/.claude/hooks/mind-clone-governance.py +192 -192
- package/.claude/hooks/read-protection.py +151 -151
- package/.claude/hooks/slug-validation.py +176 -176
- package/.claude/hooks/sql-governance.py +182 -182
- package/.claude/hooks/synapse-engine.cjs +28 -5
- package/.claude/hooks/write-path-validation.py +194 -194
- package/.claude/rules/agent-authority.md +105 -0
- package/.claude/rules/agent-handoff.md +97 -0
- package/.claude/rules/agent-memory-imports.md +15 -0
- package/.claude/rules/coderabbit-integration.md +101 -0
- package/.claude/rules/ids-principles.md +119 -0
- package/.claude/rules/story-lifecycle.md +145 -0
- package/.claude/rules/tool-examples.md +64 -0
- package/.claude/rules/tool-response-filtering.md +57 -0
- package/.claude/rules/workflow-execution.md +150 -0
- package/LICENSE +33 -33
- package/bin/aios-graph.js +9 -0
- package/bin/aios-init.js +2 -2
- package/bin/aios-minimal.js +0 -0
- package/bin/aios.js +17 -221
- package/bin/utils/detect-fsmonitor.js +70 -0
- package/bin/utils/framework-guard.js +238 -0
- package/bin/utils/validate-publish.js +108 -0
- package/package.json +6 -3
- package/packages/aios-install/bin/aios-install.js +0 -0
- package/packages/aios-install/bin/edmcp.js +0 -0
- package/packages/aios-pro-cli/bin/aios-pro.js +2 -0
- package/packages/installer/src/config/templates/core-config-template.js +25 -0
- package/packages/installer/src/installer/brownfield-upgrader.js +68 -5
- package/packages/installer/src/merger/index.js +3 -0
- package/packages/installer/src/merger/strategies/index.js +6 -0
- package/packages/installer/src/merger/strategies/yaml-merger.js +181 -0
- package/packages/installer/src/updater/index.js +4 -4
- package/packages/installer/src/wizard/i18n.js +321 -3
- package/packages/installer/src/wizard/ide-config-generator.js +173 -25
- package/packages/installer/src/wizard/index.js +119 -1
- package/packages/installer/src/wizard/pro-setup.js +137 -121
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +271 -0
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +192 -0
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +610 -0
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +134 -0
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +186 -0
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +309 -0
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +230 -0
- package/packages/installer/tests/unit/merger/strategies.test.js +2 -2
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +327 -0
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/dashboard-parallel-dev.sh +0 -0
- package/scripts/dashboard-parallel-phase3.sh +0 -0
- package/scripts/dashboard-parallel-phase4.sh +0 -0
- package/scripts/install-monitor-hooks.sh +0 -0
- package/scripts/package-synapse.js +2 -1
- package/pro/README.md +0 -66
- package/pro/license/degradation.js +0 -220
- package/pro/license/errors.js +0 -450
- package/pro/license/feature-gate.js +0 -354
- package/pro/license/index.js +0 -181
- package/pro/license/license-api.js +0 -651
- package/pro/license/license-cache.js +0 -523
- package/pro/license/license-crypto.js +0 -303
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Check: npm Packages
|
|
3
|
+
*
|
|
4
|
+
* Validates node_modules/ exists in project root (quick sanity check).
|
|
5
|
+
*
|
|
6
|
+
* @module aios-core/doctor/checks/npm-packages
|
|
7
|
+
* @story INS-4.1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const name = 'npm-packages';
|
|
14
|
+
|
|
15
|
+
async function run(context) {
|
|
16
|
+
const nodeModulesPath = path.join(context.projectRoot, 'node_modules');
|
|
17
|
+
|
|
18
|
+
if (fs.existsSync(nodeModulesPath)) {
|
|
19
|
+
return {
|
|
20
|
+
check: name,
|
|
21
|
+
status: 'PASS',
|
|
22
|
+
message: 'node_modules present',
|
|
23
|
+
fixCommand: null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
check: name,
|
|
29
|
+
status: 'FAIL',
|
|
30
|
+
message: 'node_modules not found',
|
|
31
|
+
fixCommand: 'npm install',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = { name, run };
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Check: Rules Files
|
|
3
|
+
*
|
|
4
|
+
* Validates 7 .claude/rules/*.md files present.
|
|
5
|
+
*
|
|
6
|
+
* @module aios-core/doctor/checks/rules-files
|
|
7
|
+
* @story INS-4.1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
|
|
13
|
+
const name = 'rules-files';
|
|
14
|
+
|
|
15
|
+
const EXPECTED_RULES = [
|
|
16
|
+
'agent-authority.md',
|
|
17
|
+
'workflow-execution.md',
|
|
18
|
+
'story-lifecycle.md',
|
|
19
|
+
'ids-principles.md',
|
|
20
|
+
'coderabbit-integration.md',
|
|
21
|
+
'mcp-usage.md',
|
|
22
|
+
'agent-memory-imports.md',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
async function run(context) {
|
|
26
|
+
const rulesDir = path.join(context.projectRoot, '.claude', 'rules');
|
|
27
|
+
|
|
28
|
+
if (!fs.existsSync(rulesDir)) {
|
|
29
|
+
return {
|
|
30
|
+
check: name,
|
|
31
|
+
status: 'FAIL',
|
|
32
|
+
message: `Rules directory not found (expected ${EXPECTED_RULES.length} files)`,
|
|
33
|
+
fixCommand: 'aios doctor --fix',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const missing = EXPECTED_RULES.filter(
|
|
38
|
+
(file) => !fs.existsSync(path.join(rulesDir, file)),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
if (missing.length === 0) {
|
|
42
|
+
return {
|
|
43
|
+
check: name,
|
|
44
|
+
status: 'PASS',
|
|
45
|
+
message: `All ${EXPECTED_RULES.length} rules files present`,
|
|
46
|
+
fixCommand: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const present = EXPECTED_RULES.length - missing.length;
|
|
51
|
+
const severity = missing.length > 3 ? 'FAIL' : 'WARN';
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
check: name,
|
|
55
|
+
status: severity,
|
|
56
|
+
message: `Missing ${missing.length} of ${EXPECTED_RULES.length} rules (${missing.join(', ')})`,
|
|
57
|
+
fixCommand: 'aios doctor --fix',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = { name, run, EXPECTED_RULES };
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Check: settings.json
|
|
3
|
+
*
|
|
4
|
+
* Validates .claude/settings.json exists, deny rules count >= 40,
|
|
5
|
+
* and compares against core-config.yaml boundary paths.
|
|
6
|
+
*
|
|
7
|
+
* @module aios-core/doctor/checks/settings-json
|
|
8
|
+
* @story INS-4.1
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
const name = 'settings-json';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Checks that core-config.yaml boundary.protected paths are covered by deny rules.
|
|
18
|
+
* Returns array of unprotected boundary paths.
|
|
19
|
+
*/
|
|
20
|
+
function checkBoundaryAlignment(context, denyRules) {
|
|
21
|
+
const configPath = path.join(context.projectRoot, '.aios-core', 'core-config.yaml');
|
|
22
|
+
if (!fs.existsSync(configPath)) return []; // No config = skip boundary check
|
|
23
|
+
|
|
24
|
+
let content;
|
|
25
|
+
try {
|
|
26
|
+
content = fs.readFileSync(configPath, 'utf8');
|
|
27
|
+
} catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Extract boundary.protected paths from YAML (simple line parsing)
|
|
32
|
+
const lines = content.split('\n');
|
|
33
|
+
const protectedPaths = [];
|
|
34
|
+
let inProtected = false;
|
|
35
|
+
|
|
36
|
+
for (const line of lines) {
|
|
37
|
+
if (/^\s+protected:\s*$/.test(line)) {
|
|
38
|
+
inProtected = true;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (inProtected) {
|
|
42
|
+
const match = line.match(/^\s+-\s+(.+)$/);
|
|
43
|
+
if (match) {
|
|
44
|
+
protectedPaths.push(match[1].trim());
|
|
45
|
+
} else if (/^\s+\w/.test(line) && !line.match(/^\s+-/)) {
|
|
46
|
+
inProtected = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (protectedPaths.length === 0) return [];
|
|
52
|
+
|
|
53
|
+
// Check each boundary path has at least one matching deny rule
|
|
54
|
+
const denyStr = denyRules.join('\n');
|
|
55
|
+
const unprotected = protectedPaths.filter((bp) => {
|
|
56
|
+
// Strip glob suffixes for base path matching
|
|
57
|
+
const basePath = bp.replace(/\/\*\*$/, '').replace(/\/\*$/, '');
|
|
58
|
+
return !denyStr.includes(basePath);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return unprotected;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function run(context) {
|
|
65
|
+
const settingsPath = path.join(context.projectRoot, '.claude', 'settings.json');
|
|
66
|
+
|
|
67
|
+
if (!fs.existsSync(settingsPath)) {
|
|
68
|
+
return {
|
|
69
|
+
check: name,
|
|
70
|
+
status: 'FAIL',
|
|
71
|
+
message: 'settings.json not found',
|
|
72
|
+
fixCommand: 'npx aios-core install --force',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let settings;
|
|
77
|
+
try {
|
|
78
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
79
|
+
} catch {
|
|
80
|
+
return {
|
|
81
|
+
check: name,
|
|
82
|
+
status: 'FAIL',
|
|
83
|
+
message: 'settings.json is invalid JSON',
|
|
84
|
+
fixCommand: 'npx aios-core install --force',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const denyRules = settings.permissions?.deny || [];
|
|
89
|
+
const allowRules = settings.permissions?.allow || [];
|
|
90
|
+
const denyCount = denyRules.length;
|
|
91
|
+
const allowCount = allowRules.length;
|
|
92
|
+
|
|
93
|
+
if (denyCount < 40) {
|
|
94
|
+
return {
|
|
95
|
+
check: name,
|
|
96
|
+
status: 'WARN',
|
|
97
|
+
message: `Deny rules below threshold (${denyCount} rules, expected >= 40)`,
|
|
98
|
+
fixCommand: 'aios doctor --fix',
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Compare deny rules against core-config.yaml boundary.protected paths
|
|
103
|
+
const boundaryIssues = checkBoundaryAlignment(context, denyRules);
|
|
104
|
+
if (boundaryIssues.length > 0) {
|
|
105
|
+
return {
|
|
106
|
+
check: name,
|
|
107
|
+
status: 'WARN',
|
|
108
|
+
message: `Deny rules present (${denyCount}) but missing boundary coverage: ${boundaryIssues.join(', ')}`,
|
|
109
|
+
fixCommand: 'aios doctor --fix',
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
check: name,
|
|
115
|
+
status: 'PASS',
|
|
116
|
+
message: `Deny rules present (${denyCount} rules, ${allowCount} allows)`,
|
|
117
|
+
fixCommand: null,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = { name, run };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Check: Skills Count
|
|
3
|
+
*
|
|
4
|
+
* Counts skill directories in .claude/skills/ that contain SKILL.md.
|
|
5
|
+
* PASS: >=7, WARN: 1-6, FAIL: 0 or directory missing.
|
|
6
|
+
*
|
|
7
|
+
* @module aios-core/doctor/checks/skills-count
|
|
8
|
+
* @story INS-4.8
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
const name = 'skills-count';
|
|
15
|
+
|
|
16
|
+
async function run(context) {
|
|
17
|
+
const skillsDir = path.join(context.projectRoot, '.claude', 'skills');
|
|
18
|
+
|
|
19
|
+
if (!fs.existsSync(skillsDir)) {
|
|
20
|
+
return {
|
|
21
|
+
check: name,
|
|
22
|
+
status: 'FAIL',
|
|
23
|
+
message: 'Skills directory not found (.claude/skills/)',
|
|
24
|
+
fixCommand: 'npx aios-core install --force',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let entries;
|
|
29
|
+
try {
|
|
30
|
+
entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
31
|
+
} catch {
|
|
32
|
+
return {
|
|
33
|
+
check: name,
|
|
34
|
+
status: 'FAIL',
|
|
35
|
+
message: 'Cannot read skills directory',
|
|
36
|
+
fixCommand: 'npx aios-core install --force',
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const skills = entries.filter(
|
|
41
|
+
(d) => d.isDirectory() && fs.existsSync(path.join(skillsDir, d.name, 'SKILL.md')),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const count = skills.length;
|
|
45
|
+
|
|
46
|
+
if (count === 0) {
|
|
47
|
+
return {
|
|
48
|
+
check: name,
|
|
49
|
+
status: 'FAIL',
|
|
50
|
+
message: 'No skills found (expected >=7)',
|
|
51
|
+
fixCommand: 'npx aios-core install --force',
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (count >= 7) {
|
|
56
|
+
return {
|
|
57
|
+
check: name,
|
|
58
|
+
status: 'PASS',
|
|
59
|
+
message: `${count} skills found`,
|
|
60
|
+
fixCommand: null,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
check: name,
|
|
66
|
+
status: 'WARN',
|
|
67
|
+
message: `Only ${count}/7 skills found`,
|
|
68
|
+
fixCommand: 'npx aios-core install --force',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = { name, run };
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Fix Handler
|
|
3
|
+
*
|
|
4
|
+
* Maps check names to fix functions. Supports --fix and --dry-run modes.
|
|
5
|
+
* All fix operations are idempotent.
|
|
6
|
+
*
|
|
7
|
+
* @module aios-core/doctor/fix-handler
|
|
8
|
+
* @story INS-4.1
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
|
|
14
|
+
const { EXPECTED_RULES } = require('./checks/rules-files');
|
|
15
|
+
const { EXPECTED_AGENTS } = require('./checks/agent-memory');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Apply fixes for WARN/FAIL results
|
|
19
|
+
*
|
|
20
|
+
* @param {Array} results - Check results
|
|
21
|
+
* @param {Object} context - Doctor context
|
|
22
|
+
* @returns {Array} Fix results
|
|
23
|
+
*/
|
|
24
|
+
async function applyFixes(results, context) {
|
|
25
|
+
const { projectRoot, frameworkRoot, options } = context;
|
|
26
|
+
const { dryRun = false } = options;
|
|
27
|
+
const fixResults = [];
|
|
28
|
+
|
|
29
|
+
for (const result of results) {
|
|
30
|
+
if (result.status !== 'WARN' && result.status !== 'FAIL') {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const fixer = FIX_MAP[result.check];
|
|
35
|
+
if (!fixer) {
|
|
36
|
+
fixResults.push({
|
|
37
|
+
check: result.check,
|
|
38
|
+
applied: false,
|
|
39
|
+
message: 'No auto-fix available',
|
|
40
|
+
});
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
if (dryRun) {
|
|
46
|
+
const description = fixer.describe(result, { projectRoot, frameworkRoot });
|
|
47
|
+
fixResults.push({
|
|
48
|
+
check: result.check,
|
|
49
|
+
applied: false,
|
|
50
|
+
message: `[DRY RUN] Would: ${description}`,
|
|
51
|
+
});
|
|
52
|
+
} else {
|
|
53
|
+
const fixMessage = await fixer.apply(result, { projectRoot, frameworkRoot });
|
|
54
|
+
fixResults.push({
|
|
55
|
+
check: result.check,
|
|
56
|
+
applied: true,
|
|
57
|
+
message: fixMessage,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
} catch (error) {
|
|
61
|
+
fixResults.push({
|
|
62
|
+
check: result.check,
|
|
63
|
+
applied: false,
|
|
64
|
+
message: `Fix failed: ${error.message}`,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return fixResults;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const FIX_MAP = {
|
|
73
|
+
'rules-files': {
|
|
74
|
+
describe(result, { projectRoot, frameworkRoot }) {
|
|
75
|
+
const rulesSource = path.join(frameworkRoot, '.claude', 'rules');
|
|
76
|
+
const rulesTarget = path.join(projectRoot, '.claude', 'rules');
|
|
77
|
+
return `Copy missing rules from ${rulesSource} to ${rulesTarget}`;
|
|
78
|
+
},
|
|
79
|
+
async apply(result, { projectRoot, frameworkRoot }) {
|
|
80
|
+
const rulesSource = path.join(frameworkRoot, '.claude', 'rules');
|
|
81
|
+
const rulesTarget = path.join(projectRoot, '.claude', 'rules');
|
|
82
|
+
|
|
83
|
+
if (!fs.existsSync(rulesTarget)) {
|
|
84
|
+
fs.mkdirSync(rulesTarget, { recursive: true });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let copied = 0;
|
|
88
|
+
for (const file of EXPECTED_RULES) {
|
|
89
|
+
const targetFile = path.join(rulesTarget, file);
|
|
90
|
+
const sourceFile = path.join(rulesSource, file);
|
|
91
|
+
|
|
92
|
+
if (!fs.existsSync(targetFile) && fs.existsSync(sourceFile)) {
|
|
93
|
+
fs.copyFileSync(sourceFile, targetFile);
|
|
94
|
+
copied++;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return `Copied ${copied} missing rules files`;
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
'agent-memory': {
|
|
103
|
+
describe() {
|
|
104
|
+
return 'Create missing MEMORY.md stubs for agents';
|
|
105
|
+
},
|
|
106
|
+
async apply(result, { projectRoot }) {
|
|
107
|
+
const agentsDir = path.join(projectRoot, '.aios-core', 'development', 'agents');
|
|
108
|
+
let created = 0;
|
|
109
|
+
|
|
110
|
+
for (const agent of EXPECTED_AGENTS) {
|
|
111
|
+
const memoryPath = path.join(agentsDir, agent, 'MEMORY.md');
|
|
112
|
+
const agentDir = path.join(agentsDir, agent);
|
|
113
|
+
|
|
114
|
+
if (!fs.existsSync(memoryPath)) {
|
|
115
|
+
if (!fs.existsSync(agentDir)) {
|
|
116
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
117
|
+
}
|
|
118
|
+
fs.writeFileSync(memoryPath, `# ${agent} Agent Memory\n\n_Created by aios doctor --fix_\n`);
|
|
119
|
+
created++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return `Created ${created} MEMORY.md stubs`;
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
'claude-md': {
|
|
128
|
+
describe() {
|
|
129
|
+
return 'Regenerate CLAUDE.md with missing sections';
|
|
130
|
+
},
|
|
131
|
+
async apply() {
|
|
132
|
+
return 'CLAUDE.md regeneration requires npx aios-core install --force';
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
|
|
136
|
+
'settings-json': {
|
|
137
|
+
describe() {
|
|
138
|
+
return 'Regenerate settings.json with boundary deny rules';
|
|
139
|
+
},
|
|
140
|
+
async apply(result, { frameworkRoot }) {
|
|
141
|
+
const generatorPath = path.join(
|
|
142
|
+
frameworkRoot,
|
|
143
|
+
'packages',
|
|
144
|
+
'installer',
|
|
145
|
+
'src',
|
|
146
|
+
'generators',
|
|
147
|
+
'generate-settings-json',
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const generator = require(generatorPath);
|
|
152
|
+
if (typeof generator.generateSettingsJson === 'function') {
|
|
153
|
+
await generator.generateSettingsJson();
|
|
154
|
+
return 'settings.json regenerated';
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
// Generator not available
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return 'settings.json regeneration requires npx aios-core install --force';
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
module.exports = { applyFixes };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor JSON Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats doctor results as structured JSON.
|
|
5
|
+
*
|
|
6
|
+
* @module aios-core/doctor/formatters/json
|
|
7
|
+
* @story INS-4.1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
function formatJson(output) {
|
|
11
|
+
return JSON.stringify(output, null, 2);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = { formatJson };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Doctor Text Formatter
|
|
3
|
+
*
|
|
4
|
+
* Formats doctor results as human-readable text output.
|
|
5
|
+
*
|
|
6
|
+
* @module aios-core/doctor/formatters/text
|
|
7
|
+
* @story INS-4.1
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const STATUS_PREFIX = {
|
|
11
|
+
PASS: '[PASS]',
|
|
12
|
+
WARN: '[WARN]',
|
|
13
|
+
FAIL: '[FAIL]',
|
|
14
|
+
INFO: '[INFO]',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function formatText(output, options = {}) {
|
|
18
|
+
const { quiet = false } = options;
|
|
19
|
+
const lines = [];
|
|
20
|
+
|
|
21
|
+
lines.push(`AIOS Doctor v${output.version} — Environment Health Check`);
|
|
22
|
+
lines.push('');
|
|
23
|
+
|
|
24
|
+
for (const result of output.checks) {
|
|
25
|
+
const prefix = STATUS_PREFIX[result.status] || '[????]';
|
|
26
|
+
lines.push(` ${prefix} ${result.check}: ${result.message}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
lines.push('');
|
|
30
|
+
const { pass, warn, fail, info } = output.summary;
|
|
31
|
+
lines.push(`Summary: ${pass} PASS | ${warn} WARN | ${fail} FAIL | ${info} INFO`);
|
|
32
|
+
|
|
33
|
+
if (!quiet) {
|
|
34
|
+
const fixable = output.checks.filter(
|
|
35
|
+
(r) => (r.status === 'WARN' || r.status === 'FAIL') && r.fixCommand,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
if (fixable.length > 0) {
|
|
39
|
+
lines.push('');
|
|
40
|
+
lines.push('Fix suggestions:');
|
|
41
|
+
fixable.forEach((r, i) => {
|
|
42
|
+
lines.push(` ${i + 1}. [${r.status}] ${r.check}: Run \`${r.fixCommand}\``);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (output.fixResults) {
|
|
48
|
+
lines.push('');
|
|
49
|
+
lines.push('Fix results:');
|
|
50
|
+
for (const fr of output.fixResults) {
|
|
51
|
+
const icon = fr.applied ? '✓' : '✗';
|
|
52
|
+
lines.push(` ${icon} ${fr.check}: ${fr.message}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return lines.join('\n');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = { formatText };
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIOS Doctor — Environment Health Check Orchestrator
|
|
3
|
+
*
|
|
4
|
+
* Runs 12 modular checks against the AIOS environment and returns
|
|
5
|
+
* structured results with optional --fix, --json, and --dry-run support.
|
|
6
|
+
*
|
|
7
|
+
* @module aios-core/doctor
|
|
8
|
+
* @version 2.0.0
|
|
9
|
+
* @story INS-4.1
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const { loadChecks } = require('./checks');
|
|
14
|
+
const { formatText } = require('./formatters/text');
|
|
15
|
+
const { formatJson } = require('./formatters/json');
|
|
16
|
+
const { applyFixes } = require('./fix-handler');
|
|
17
|
+
|
|
18
|
+
const DOCTOR_VERSION = '2.0.0';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Run all doctor checks
|
|
22
|
+
*
|
|
23
|
+
* @param {Object} options
|
|
24
|
+
* @param {boolean} [options.fix=false] - Auto-correct fixable issues
|
|
25
|
+
* @param {boolean} [options.json=false] - Output as JSON
|
|
26
|
+
* @param {boolean} [options.dryRun=false] - Show what --fix would do
|
|
27
|
+
* @param {boolean} [options.quiet=false] - Minimal output
|
|
28
|
+
* @param {string} [options.projectRoot] - Project root (defaults to cwd)
|
|
29
|
+
* @returns {Promise<Object>} Doctor results
|
|
30
|
+
*/
|
|
31
|
+
async function runDoctorChecks(options = {}) {
|
|
32
|
+
const {
|
|
33
|
+
fix = false,
|
|
34
|
+
json = false,
|
|
35
|
+
dryRun = false,
|
|
36
|
+
quiet = false,
|
|
37
|
+
projectRoot = process.cwd(),
|
|
38
|
+
} = options;
|
|
39
|
+
|
|
40
|
+
const context = {
|
|
41
|
+
projectRoot,
|
|
42
|
+
frameworkRoot: path.resolve(__dirname, '..', '..', '..'),
|
|
43
|
+
options: { fix, json, dryRun, quiet },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Load and run all checks
|
|
47
|
+
const checks = loadChecks();
|
|
48
|
+
const results = [];
|
|
49
|
+
|
|
50
|
+
for (const checkModule of checks) {
|
|
51
|
+
try {
|
|
52
|
+
const result = await checkModule.run(context);
|
|
53
|
+
results.push(result);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
results.push({
|
|
56
|
+
check: checkModule.name || 'unknown',
|
|
57
|
+
status: 'FAIL',
|
|
58
|
+
message: `Check threw error: ${error.message}`,
|
|
59
|
+
fixCommand: null,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Apply fixes if requested
|
|
65
|
+
let fixResults = null;
|
|
66
|
+
if (fix || dryRun) {
|
|
67
|
+
fixResults = await applyFixes(results, context);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Build summary
|
|
71
|
+
const summary = {
|
|
72
|
+
pass: results.filter((r) => r.status === 'PASS').length,
|
|
73
|
+
warn: results.filter((r) => r.status === 'WARN').length,
|
|
74
|
+
fail: results.filter((r) => r.status === 'FAIL').length,
|
|
75
|
+
info: results.filter((r) => r.status === 'INFO').length,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const output = {
|
|
79
|
+
version: DOCTOR_VERSION,
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
summary,
|
|
82
|
+
checks: results,
|
|
83
|
+
fixResults,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Format output
|
|
87
|
+
if (json) {
|
|
88
|
+
return { formatted: formatJson(output), data: output };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return { formatted: formatText(output, { quiet }), data: output };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
module.exports = { runDoctorChecks, DOCTOR_VERSION };
|