sinapse-ai 1.8.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/mind-clone-governance.py +212 -212
- package/.claude/hooks/read-protection.py +152 -152
- package/.claude/hooks/slug-validation.py +175 -175
- package/.claude/hooks/sql-governance.py +183 -183
- package/.claude/rules/documentation-first.md +1 -1
- package/.claude/rules/hook-governance.md +1 -1
- package/.claude/rules/mandatory-delegation.md +1 -1
- package/.claude/rules/project-intelligence.md +1 -1
- package/.codex/agents/analyst.md +4 -371
- package/.codex/agents/animations-orqx.md +4 -57
- package/.codex/agents/architect.md +4 -560
- package/.codex/agents/brand-orqx.md +4 -95
- package/.codex/agents/claude-mastery-chief.md +4 -0
- package/.codex/agents/cloning-orqx.md +4 -70
- package/.codex/agents/commercial-orqx.md +4 -67
- package/.codex/agents/config-engineer.md +2 -2
- package/.codex/agents/content-orqx.md +4 -77
- package/.codex/agents/copy-orqx.md +4 -65
- package/.codex/agents/cost-optimizer.md +4 -0
- package/.codex/agents/council-orqx.md +4 -68
- package/.codex/agents/courses-orqx.md +4 -64
- package/.codex/agents/cro-persuasion.md +4 -0
- package/.codex/agents/cyber-orqx.md +4 -67
- package/.codex/agents/data-engineer.md +4 -542
- package/.codex/agents/design-orqx.md +4 -65
- package/.codex/agents/design-system.md +4 -210
- package/.codex/agents/developer.md +4 -666
- package/.codex/agents/devops.md +4 -668
- package/.codex/agents/finance-orqx.md +4 -57
- package/.codex/agents/fiscal-compliance-br.md +4 -0
- package/.codex/agents/forecast-strategist.md +4 -0
- package/.codex/agents/growth-orqx.md +4 -75
- package/.codex/agents/hooks-architect.md +2 -2
- package/.codex/agents/mcp-integrator.md +2 -2
- package/.codex/agents/paidmedia-orqx.md +4 -67
- package/.codex/agents/platform-aesthetic-director.md +4 -0
- package/.codex/agents/premium-packaging-strategist.md +4 -0
- package/.codex/agents/product-lead.md +4 -371
- package/.codex/agents/product-orqx.md +4 -57
- package/.codex/agents/product-surface-director.md +4 -0
- package/.codex/agents/project-integrator.md +2 -2
- package/.codex/agents/project-lead.md +4 -414
- package/.codex/agents/quality-gate.md +4 -547
- package/.codex/agents/research-orqx.md +4 -67
- package/.codex/agents/roadmap-sentinel.md +2 -2
- package/.codex/agents/skill-craftsman.md +2 -2
- package/.codex/agents/snps-orqx.md +4 -684
- package/.codex/agents/sop-extractor.md +4 -61
- package/.codex/agents/sprint-lead.md +4 -324
- package/.codex/agents/squad-creator.md +4 -402
- package/.codex/agents/storytelling-orqx.md +4 -65
- package/.codex/agents/swarm-orqx.md +4 -64
- package/.codex/agents/ux-design-expert.md +4 -532
- package/.codex/agents/ux-designer.md +4 -124
- package/.codex/command-registry.json +9 -9
- package/.codex/delegation-matrix.json +375 -839
- package/.codex/delegation-parity.json +658 -0
- package/.codex/handoff-packet.parity.schema.json +148 -0
- package/.codex/handoff-packet.template.json +26 -0
- package/.codex/instructions.md +8 -8
- package/.codex/scripts/resolve-codex-agent.js +482 -0
- package/.codex/scripts/resolve-codex-command.js +75 -12
- package/.codex/scripts/resolve-codex-delegation.js +131 -92
- package/.codex/skills/sinapse-claude/SKILL.md +3 -3
- package/.codex/skills/sinapse-po/SKILL.md +1 -1
- package/.codex/tasks/resolve-sinapse-conflict.md +1 -1
- package/.sinapse-ai/constitution.md +5 -5
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +163 -19
- package/.sinapse-ai/core/events/dashboard-emitter.js +30 -9
- package/.sinapse-ai/core/execution/subagent-dispatcher.js +1 -1
- package/.sinapse-ai/core/synapse/engine.js +15 -0
- package/.sinapse-ai/core/ui/observability-panel.js +240 -0
- package/.sinapse-ai/core-config.yaml +0 -20
- package/.sinapse-ai/data/entity-registry.yaml +185 -236
- package/.sinapse-ai/development/agents/snps-orqx.md +16 -26
- package/.sinapse-ai/development/tasks/build-autonomous.md +11 -1
- package/.sinapse-ai/development/tasks/build-resume.md +8 -0
- package/.sinapse-ai/development/tasks/build-status.md +8 -0
- package/.sinapse-ai/development/tasks/build.md +8 -0
- package/.sinapse-ai/development/tasks/cleanup-worktrees.md +8 -1
- package/.sinapse-ai/development/tasks/gotcha.md +8 -0
- package/.sinapse-ai/development/tasks/gotchas.md +8 -0
- package/.sinapse-ai/development/tasks/ids-health.md +14 -6
- package/.sinapse-ai/development/tasks/list-mcps.md +15 -0
- package/.sinapse-ai/development/tasks/merge-worktree.md +8 -1
- package/.sinapse-ai/development/tasks/qa-review-build.md +18 -0
- package/.sinapse-ai/development/tasks/remove-mcp.md +8 -1
- package/.sinapse-ai/development/tasks/validate-agents.md +26 -14
- package/.sinapse-ai/development/templates/service-template/README.md.hbs +159 -159
- package/.sinapse-ai/development/templates/service-template/__tests__/index.test.ts.hbs +238 -238
- package/.sinapse-ai/development/templates/service-template/client.ts.hbs +404 -404
- package/.sinapse-ai/development/templates/service-template/errors.ts.hbs +183 -183
- package/.sinapse-ai/development/templates/service-template/index.ts.hbs +121 -121
- package/.sinapse-ai/development/templates/service-template/package.json.hbs +88 -88
- package/.sinapse-ai/development/templates/service-template/types.ts.hbs +146 -146
- package/.sinapse-ai/development/templates/squad-template/LICENSE +22 -22
- package/.sinapse-ai/git-hooks/lib/framework-guard.js +258 -0
- package/.sinapse-ai/git-hooks/lib/secret-scanner-core.js +355 -0
- package/.sinapse-ai/git-hooks/lib/staged-secret-scan.js +179 -0
- package/.sinapse-ai/git-hooks/lib/staged-sql-guard.js +204 -0
- package/.sinapse-ai/git-hooks/post-commit +28 -0
- package/.sinapse-ai/git-hooks/pre-commit +81 -0
- package/.sinapse-ai/git-hooks/pre-push +83 -0
- package/.sinapse-ai/hooks/ids-post-commit.js +13 -11
- package/.sinapse-ai/hooks/ids-pre-push.js +9 -7
- package/.sinapse-ai/infrastructure/scripts/codex-parity/resolve.js +161 -0
- package/.sinapse-ai/infrastructure/scripts/dashboard-status-writer.js +6 -2
- package/.sinapse-ai/infrastructure/scripts/ide-sync/index.js +65 -68
- package/.sinapse-ai/infrastructure/scripts/sync-codex-local-first.js +156 -1
- package/.sinapse-ai/infrastructure/scripts/validate-codex-delegation.js +1 -4
- package/.sinapse-ai/infrastructure/scripts/validate-codex-integration.js +41 -5
- package/.sinapse-ai/infrastructure/templates/coderabbit.yaml.template +280 -280
- package/.sinapse-ai/infrastructure/templates/config/env.example +16 -16
- package/.sinapse-ai/infrastructure/templates/config/gitignore-additions.tmpl +59 -59
- package/.sinapse-ai/infrastructure/templates/github/CODEOWNERS.template +12 -12
- package/.sinapse-ai/infrastructure/templates/github-workflows/ci.yml.template +170 -170
- package/.sinapse-ai/infrastructure/templates/github-workflows/pr-automation.yml.template +331 -331
- package/.sinapse-ai/infrastructure/templates/github-workflows/release.yml.template +197 -197
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +19 -19
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-node.tmpl +86 -86
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-python.tmpl +146 -146
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-sinapse-base.tmpl +64 -64
- package/.sinapse-ai/infrastructure/templates/safe-collab/CODEOWNERS.template +16 -16
- package/.sinapse-ai/infrastructure/templates/sinapse-sync.yaml.template +183 -183
- package/.sinapse-ai/install-manifest.yaml +112 -164
- package/.sinapse-ai/local-config.yaml.template +65 -65
- package/.sinapse-ai/product/templates/adr.hbs +126 -126
- package/.sinapse-ai/product/templates/dbdr.hbs +242 -242
- package/.sinapse-ai/product/templates/epic.hbs +213 -213
- package/.sinapse-ai/product/templates/ide-rules/codex-rules.md +30 -0
- package/.sinapse-ai/product/templates/pmdr.hbs +187 -187
- package/.sinapse-ai/product/templates/prd-v2.0.hbs +217 -217
- package/.sinapse-ai/product/templates/prd.hbs +202 -202
- package/.sinapse-ai/product/templates/statusline/statusline-script.js +31 -8
- package/.sinapse-ai/product/templates/statusline/track-agent-clear.cjs +79 -0
- package/.sinapse-ai/product/templates/statusline/track-agent.cjs +218 -0
- package/.sinapse-ai/product/templates/story.hbs +264 -264
- package/.sinapse-ai/product/templates/task.hbs +171 -171
- package/.sinapse-ai/product/templates/tmpl-comment-on-examples.sql +159 -159
- package/.sinapse-ai/product/templates/tmpl-migration-script.sql +92 -92
- package/.sinapse-ai/product/templates/tmpl-rls-granular-policies.sql +105 -105
- package/.sinapse-ai/product/templates/tmpl-rls-kiss-policy.sql +11 -11
- package/.sinapse-ai/product/templates/tmpl-rls-roles.sql +136 -136
- package/.sinapse-ai/product/templates/tmpl-rls-simple.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-rls-tenant.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-rollback-script.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-seed-data.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-smoke-test.sql +17 -17
- package/.sinapse-ai/product/templates/tmpl-staging-copy-merge.sql +140 -140
- package/.sinapse-ai/product/templates/tmpl-stored-proc.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-trigger.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-view-materialized.sql +134 -134
- package/.sinapse-ai/product/templates/tmpl-view.sql +178 -178
- package/AGENTS.md +193 -0
- package/CHANGELOG.md +1247 -0
- package/LICENSE +63 -63
- package/README.en.md +17 -18
- package/README.md +18 -19
- package/bin/cli.js +1 -1
- package/bin/commands/install.js +194 -22
- package/bin/commands/status.js +14 -1
- package/bin/commands/uninstall.js +2 -2
- package/bin/commands/update.js +52 -0
- package/bin/lib/setup-statusline.js +191 -0
- package/bin/sinapse-init.js +11 -83
- package/bin/utils/framework-guard.js +17 -4
- package/bin/utils/secret-scanner-core.js +109 -7
- package/bin/utils/staged-sql-guard.js +204 -0
- package/bin/utils/validate-publish.js +63 -0
- package/docs/agent-reference-guide.md +5 -7
- package/docs/framework/agent-prefix-convention.md +58 -0
- package/docs/framework/architecture-overview.md +4 -4
- package/docs/framework/collaboration-activation.md +45 -0
- package/docs/framework/guiding-principles.md +9 -9
- package/docs/getting-started.md +1 -1
- package/docs/guides/agent-reference.md +1 -1
- package/docs/guides/codex-config.md +4 -5
- package/docs/pt/architecture/sub-orqx-pattern.md +20 -18
- package/docs/security/overview.md +1 -1
- package/package.json +16 -12
- package/packages/installer/src/index.js +26 -0
- package/packages/installer/src/installer/git-hooks-installer.js +211 -47
- package/packages/installer/src/installer/sinapse-ai-installer.js +71 -0
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +26 -26
- package/packages/installer/src/wizard/index.js +53 -4
- package/packages/sinapse-install/bin/edmcp.js +0 -0
- package/packages/sinapse-install/bin/sinapse-install.js +0 -0
- package/scripts/audit-tasks.cjs +112 -91
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/prepare-hooks.js +58 -0
- package/scripts/regenerate-orqx-stubs.ps1 +2 -3
- package/scripts/sync-counts.js +10 -2
- package/scripts/sync-squad-yaml-components.js +108 -6
- package/scripts/validate-agents-md.js +128 -0
- package/scripts/validate-all.js +1 -0
- package/scripts/validate-squad-orqx.js +19 -9
- package/sinapse/agents/sinapse-orqx.md +16 -26
- package/sinapse/agents/snps-orqx.md +15 -25
- package/sinapse/knowledge-base/routing-catalog.md +1 -1
- package/sinapse/tasks/diagnose-and-route.md +1 -1
- package/sinapse/tasks/squad-status-report.md +1 -1
- package/squads/claude-code-mastery/agents/claude-mastery-chief.md +1 -1
- package/squads/claude-code-mastery/agents/hooks-architect.md +60 -68
- package/squads/claude-code-mastery/knowledge-base/swarm-orchestration-patterns.md +1 -1
- package/squads/claude-code-mastery/squad.yaml +8 -0
- package/squads/claude-code-mastery/tasks/audit-setup.md +1 -1
- package/squads/claude-code-mastery/workflows/optimization-cycle.yaml +4 -4
- package/squads/claude-code-mastery/workflows/project-setup-cycle.yaml +4 -4
- package/squads/squad-animations/README.md +1 -1
- package/squads/squad-animations/squad.yaml +1 -1
- package/squads/squad-brand/squad.yaml +1 -1
- package/squads/squad-cloning/README.md +1 -1
- package/squads/squad-cloning/squad.yaml +1 -1
- package/squads/squad-commercial/README.md +1 -1
- package/squads/squad-commercial/squad.yaml +2 -3
- package/squads/squad-content/README.md +1 -1
- package/squads/squad-content/squad.yaml +1 -1
- package/squads/squad-copy/README.md +1 -1
- package/squads/squad-copy/squad.yaml +2 -3
- package/squads/squad-council/README.md +1 -1
- package/squads/squad-courses/README.md +1 -1
- package/squads/squad-courses/squad.yaml +1 -1
- package/squads/squad-cybersecurity/README.md +1 -1
- package/squads/squad-cybersecurity/squad.yaml +2 -3
- package/squads/squad-design/README.md +1 -1
- package/squads/{squad-artdir → squad-design}/agents/cro-persuasion.md +1 -1
- package/squads/{squad-artdir → squad-design}/agents/platform-aesthetic-director.md +2 -2
- package/squads/{squad-artdir → squad-design}/agents/premium-packaging-strategist.md +2 -2
- package/squads/{squad-artdir → squad-design}/agents/product-surface-director.md +3 -3
- package/squads/squad-design/squad.yaml +6 -3
- package/squads/squad-finance/README.md +1 -1
- package/squads/squad-finance/squad.yaml +7 -1
- package/squads/squad-growth/README.md +1 -1
- package/squads/squad-growth/squad.yaml +1 -1
- package/squads/squad-paidmedia/README.md +1 -1
- package/squads/squad-paidmedia/squad.yaml +2 -3
- package/squads/squad-product/README.md +1 -1
- package/squads/squad-product/squad.yaml +1 -1
- package/squads/squad-research/README.md +1 -1
- package/squads/squad-research/squad.yaml +2 -3
- package/squads/squad-storytelling/README.md +1 -1
- package/squads/squad-storytelling/squad.yaml +2 -3
- package/.codex/agents/brad-frost.md +0 -46
- package/.codex/agents/claude-orqx.md +0 -72
- package/.codex/agents/copy-chief.md +0 -162
- package/.codex/agents/cyber-chief.md +0 -169
- package/.codex/agents/dan-mall.md +0 -43
- package/.codex/agents/data-chief.md +0 -198
- package/.codex/agents/dave-malouf.md +0 -43
- package/.codex/agents/db-sage.md +0 -152
- package/.codex/agents/design-chief.md +0 -226
- package/.codex/agents/dev.md +0 -102
- package/.codex/agents/legal-chief.md +0 -199
- package/.codex/agents/nano-banana-generator.md +0 -42
- package/.codex/agents/pm.md +0 -81
- package/.codex/agents/po.md +0 -85
- package/.codex/agents/qa.md +0 -98
- package/.codex/agents/sm.md +0 -77
- package/.codex/agents/squad-chief.md +0 -1553
- package/.codex/agents/squad.md +0 -66
- package/.codex/agents/story-chief.md +0 -180
- package/.codex/agents/tools-orqx.md +0 -219
- package/.codex/agents/traffic-masters-chief.md +0 -211
- package/.sinapse-ai/core/memory/__tests__/active-modules.verify.js +0 -265
- package/.sinapse-ai/core/permissions/__tests__/permission-mode.test.js +0 -293
- package/.sinapse-ai/data/registry-update-log.jsonl +0 -158
- package/.sinapse-ai/infrastructure/scripts/ide-sync/gemini-commands.js +0 -298
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/antigravity.js +0 -121
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/cursor.js +0 -119
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/github-copilot.js +0 -191
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/kimi.js +0 -448
- package/.sinapse-ai/infrastructure/tests/project-status-loader.test.js +0 -569
- package/.sinapse-ai/infrastructure/tests/regression-suite-v2.md +0 -622
- package/.sinapse-ai/infrastructure/tests/validate-module.js +0 -98
- package/.sinapse-ai/infrastructure/tests/worktree-manager.test.js +0 -620
- package/.sinapse-ai/monitor/hooks/lib/__init__.py +0 -2
- package/.sinapse-ai/monitor/hooks/lib/enrich.py +0 -59
- package/.sinapse-ai/monitor/hooks/lib/send_event.py +0 -48
- package/.sinapse-ai/monitor/hooks/notification.py +0 -30
- package/.sinapse-ai/monitor/hooks/post_tool_use.py +0 -46
- package/.sinapse-ai/monitor/hooks/pre_compact.py +0 -30
- package/.sinapse-ai/monitor/hooks/pre_tool_use.py +0 -41
- package/.sinapse-ai/monitor/hooks/stop.py +0 -30
- package/.sinapse-ai/monitor/hooks/subagent_stop.py +0 -30
- package/.sinapse-ai/monitor/hooks/user_prompt_submit.py +0 -39
- package/.sinapse-ai/product/templates/statusline/track-agent.sh +0 -69
- package/.sinapse-ai/workflow-intelligence/__tests__/confidence-scorer.test.js +0 -335
- package/.sinapse-ai/workflow-intelligence/__tests__/integration.test.js +0 -340
- package/.sinapse-ai/workflow-intelligence/__tests__/suggestion-engine.test.js +0 -438
- package/.sinapse-ai/workflow-intelligence/__tests__/wave-analyzer.test.js +0 -448
- package/.sinapse-ai/workflow-intelligence/__tests__/workflow-registry.test.js +0 -303
- package/bin/sinapse-graph.js +0 -19
- package/docs/codex-integration-process.md +0 -22
- package/docs/codex-parity-program.md +0 -27
- package/packages/installer/src/__tests__/performance-benchmark.js +0 -383
- package/packages/installer/tests/integration/environment-configuration.test.js +0 -332
- package/packages/installer/tests/integration/wizard-detection.test.js +0 -352
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +0 -383
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +0 -193
- package/packages/installer/tests/unit/config-validator.test.js +0 -315
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +0 -539
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +0 -636
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +0 -192
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +0 -186
- package/packages/installer/tests/unit/env-template.test.js +0 -187
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +0 -310
- package/packages/installer/tests/unit/git-hooks-installer.test.js +0 -262
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +0 -231
- package/packages/installer/tests/unit/merger/env-merger.test.js +0 -191
- package/packages/installer/tests/unit/merger/markdown-merger.test.js +0 -262
- package/packages/installer/tests/unit/merger/strategies.test.js +0 -154
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +0 -328
- package/packages/sinapse-install/tests/unit/chrome-brain.smoke.test.js +0 -66
- package/scripts/install-monitor-hooks.sh +0 -82
- package/squads/squad-artdir/README.md +0 -90
- package/squads/squad-artdir/agents/accessibility-guardian.md +0 -184
- package/squads/squad-artdir/agents/artdir-orqx.md +0 -222
- package/squads/squad-artdir/agents/color-psychologist.md +0 -166
- package/squads/squad-artdir/agents/design-system-architect.md +0 -100
- package/squads/squad-artdir/agents/ia-architect.md +0 -169
- package/squads/squad-artdir/agents/interaction-designer.md +0 -162
- package/squads/squad-artdir/agents/layout-engineer.md +0 -163
- package/squads/squad-artdir/agents/motion-architect.md +0 -185
- package/squads/squad-artdir/agents/type-systemist.md +0 -138
- package/squads/squad-artdir/agents/visual-strategist.md +0 -127
- package/squads/squad-artdir/checklists/seven-pillars-validation-checklist.md +0 -172
- package/squads/squad-artdir/knowledge-base/case-nyo-ia-reference.md +0 -289
- package/squads/squad-artdir/knowledge-base/deliverables-templates.md +0 -457
- package/squads/squad-artdir/knowledge-base/motion-technique-catalog.md +0 -247
- package/squads/squad-artdir/knowledge-base/premium-packaging-principles.md +0 -133
- package/squads/squad-artdir/knowledge-base/psychological-toolkit.md +0 -229
- package/squads/squad-artdir/knowledge-base/saas-art-direction-canon.md +0 -242
- package/squads/squad-artdir/knowledge-base/seven-pillars-framework.md +0 -289
- package/squads/squad-artdir/knowledge-base/ten-pillars-framework.md +0 -221
- package/squads/squad-artdir/package.json +0 -20
- package/squads/squad-artdir/squad.yaml +0 -299
- package/squads/squad-artdir/tasks/audit-conversion.md +0 -97
- package/squads/squad-artdir/tasks/audit-drift-multi-surface.md +0 -55
- package/squads/squad-artdir/tasks/consult-saas-canon.md +0 -54
- package/squads/squad-artdir/tasks/create-art-direction-brief.md +0 -110
- package/squads/squad-artdir/tasks/create-premium-packaging-brief.md +0 -61
- package/squads/squad-artdir/tasks/create-wireflow.md +0 -84
- package/squads/squad-artdir/tasks/design-color-system.md +0 -81
- package/squads/squad-artdir/tasks/design-product-surface.md +0 -60
- package/squads/squad-artdir/tasks/design-token-system.md +0 -58
- package/squads/squad-artdir/tasks/diagnose-visual-language.md +0 -92
- package/squads/squad-artdir/tasks/first-5-minutes-choreography.md +0 -65
- package/squads/squad-artdir/tasks/specify-motion-system.md +0 -84
- package/squads/squad-artdir/tasks/validate-against-pillars.md +0 -143
- package/squads/squad-artdir/templates/art-direction-brief-template.md +0 -215
- package/squads/squad-artdir/workflows/conversion-audit-cycle.yaml +0 -142
- package/squads/squad-artdir/workflows/full-art-direction-cycle.yaml +0 -179
- package/squads/squad-artdir/workflows/saas-platform-art-direction-cycle.yaml +0 -338
- package/squads/squad-commercial/agents/legal-chief.md +0 -199
- package/squads/squad-copy/agents/copy-chief.md +0 -162
- package/squads/squad-cybersecurity/agents/cyber-chief.md +0 -169
- package/squads/squad-design/agents/design-chief.md +0 -226
- package/squads/squad-paidmedia/agents/traffic-masters-chief.md +0 -211
- package/squads/squad-research/agents/data-chief.md +0 -198
- package/squads/squad-storytelling/agents/story-chief.md +0 -180
|
@@ -1,636 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit Tests: Doctor Check Modules
|
|
3
|
-
* Story INS-4.1: sinapse doctor rewrite
|
|
4
|
-
* Story INS-4.8: 3 new checks (skills-count, commands-count, hooks-claude-count)
|
|
5
|
-
*
|
|
6
|
-
* Tests all 15 check modules individually with mocked filesystem.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const path = require('path');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
|
|
12
|
-
// Mock fs for controlled test scenarios
|
|
13
|
-
jest.mock('fs');
|
|
14
|
-
|
|
15
|
-
const nodeVersionCheck = require('../../../../../.sinapse-ai/core/doctor/checks/node-version');
|
|
16
|
-
const npmPackagesCheck = require('../../../../../.sinapse-ai/core/doctor/checks/npm-packages');
|
|
17
|
-
const settingsJsonCheck = require('../../../../../.sinapse-ai/core/doctor/checks/settings-json');
|
|
18
|
-
const rulesFilesCheck = require('../../../../../.sinapse-ai/core/doctor/checks/rules-files');
|
|
19
|
-
const agentMemoryCheck = require('../../../../../.sinapse-ai/core/doctor/checks/agent-memory');
|
|
20
|
-
const entityRegistryCheck = require('../../../../../.sinapse-ai/core/doctor/checks/entity-registry');
|
|
21
|
-
const gitHooksCheck = require('../../../../../.sinapse-ai/core/doctor/checks/git-hooks');
|
|
22
|
-
const coreConfigCheck = require('../../../../../.sinapse-ai/core/doctor/checks/core-config');
|
|
23
|
-
const claudeMdCheck = require('../../../../../.sinapse-ai/core/doctor/checks/claude-md');
|
|
24
|
-
const graphDashboardCheck = require('../../../../../.sinapse-ai/core/doctor/checks/graph-dashboard');
|
|
25
|
-
const codeIntelCheck = require('../../../../../.sinapse-ai/core/doctor/checks/code-intel');
|
|
26
|
-
const ideSyncCheck = require('../../../../../.sinapse-ai/core/doctor/checks/ide-sync');
|
|
27
|
-
const skillsCountCheck = require('../../../../../.sinapse-ai/core/doctor/checks/skills-count');
|
|
28
|
-
const commandsCountCheck = require('../../../../../.sinapse-ai/core/doctor/checks/commands-count');
|
|
29
|
-
const hooksClaudeCountCheck = require('../../../../../.sinapse-ai/core/doctor/checks/hooks-claude-count');
|
|
30
|
-
const { loadChecks } = require('../../../../../.sinapse-ai/core/doctor/checks');
|
|
31
|
-
|
|
32
|
-
const mockContext = {
|
|
33
|
-
projectRoot: '/mock/project',
|
|
34
|
-
frameworkRoot: '/mock/framework',
|
|
35
|
-
options: { fix: false, json: false, dryRun: false, quiet: false },
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
beforeEach(() => {
|
|
39
|
-
jest.clearAllMocks();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('node-version check', () => {
|
|
43
|
-
it('should PASS for current Node.js version (>=18)', async () => {
|
|
44
|
-
const result = await nodeVersionCheck.run(mockContext);
|
|
45
|
-
expect(result.check).toBe('node-version');
|
|
46
|
-
expect(result.status).toBe('PASS');
|
|
47
|
-
expect(result.message).toContain('Node.js');
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
describe('npm-packages check', () => {
|
|
52
|
-
// Story 10.48 + v1.4.2: this check no longer treats a missing project-level
|
|
53
|
-
// node_modules/ as a blocker. It validates that the deps DECLARED in
|
|
54
|
-
// .sinapse-ai/package.json are *resolvable* via Node's resolver (which walks
|
|
55
|
-
// parent + global node_modules). PASS unless a declared dep is unresolvable.
|
|
56
|
-
|
|
57
|
-
it('should PASS when .sinapse-ai package has zero declared deps', async () => {
|
|
58
|
-
// existsSync true everywhere → .sinapse-ai/package.json + node_modules present.
|
|
59
|
-
// readFileSync auto-mock returns undefined → JSON.parse throws → caught →
|
|
60
|
-
// falls through to PASS with totalDeps=0 and node_modules present.
|
|
61
|
-
fs.existsSync.mockReturnValue(true);
|
|
62
|
-
const result = await npmPackagesCheck.run(mockContext);
|
|
63
|
-
expect(result.status).toBe('PASS');
|
|
64
|
-
expect(result.message).toContain('.sinapse-ai deps complete');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should PASS (not FAIL) when there is no .sinapse-ai/package.json', async () => {
|
|
68
|
-
fs.existsSync.mockReturnValue(false);
|
|
69
|
-
const result = await npmPackagesCheck.run(mockContext);
|
|
70
|
-
expect(result.status).toBe('PASS');
|
|
71
|
-
expect(result.message).toContain('no .sinapse-ai/package.json');
|
|
72
|
-
expect(result.fixCommand).toBeNull();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should FAIL when a declared .sinapse-ai dep is unresolvable', async () => {
|
|
76
|
-
// .sinapse-ai/package.json present, declaring a dep that cannot resolve.
|
|
77
|
-
fs.existsSync.mockImplementation((p) =>
|
|
78
|
-
String(p).includes('package.json'),
|
|
79
|
-
);
|
|
80
|
-
fs.readFileSync.mockReturnValue(
|
|
81
|
-
JSON.stringify({ dependencies: { '@sinapse/definitely-not-installed-xyz': '^1.0.0' } }),
|
|
82
|
-
);
|
|
83
|
-
const result = await npmPackagesCheck.run(mockContext);
|
|
84
|
-
expect(result.status).toBe('FAIL');
|
|
85
|
-
expect(result.message).toContain('unresolvable');
|
|
86
|
-
expect(result.fixCommand).toBe('cd .sinapse-ai && npm install --production');
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
describe('settings-json check', () => {
|
|
91
|
-
it('should PASS with valid settings and sufficient deny rules', async () => {
|
|
92
|
-
fs.existsSync.mockReturnValue(true);
|
|
93
|
-
const mockSettings = {
|
|
94
|
-
permissions: {
|
|
95
|
-
deny: new Array(50).fill('Edit(.sinapse-ai/core/)'),
|
|
96
|
-
allow: ['Edit(docs/)'],
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
const coreConfig = 'boundary:\n protected:\n - .sinapse-ai/core/**\n exceptions:\n - agents/MEMORY.md';
|
|
100
|
-
fs.readFileSync.mockImplementation((p) => {
|
|
101
|
-
if (p.includes('settings.json')) return JSON.stringify(mockSettings);
|
|
102
|
-
if (p.includes('core-config')) return coreConfig;
|
|
103
|
-
return '';
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
const result = await settingsJsonCheck.run(mockContext);
|
|
107
|
-
expect(result.status).toBe('PASS');
|
|
108
|
-
expect(result.message).toContain('50 rules');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should FAIL when settings.json not found', async () => {
|
|
112
|
-
fs.existsSync.mockReturnValue(false);
|
|
113
|
-
const result = await settingsJsonCheck.run(mockContext);
|
|
114
|
-
expect(result.status).toBe('FAIL');
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
it('should WARN when deny rules below threshold', async () => {
|
|
118
|
-
fs.existsSync.mockReturnValue(true);
|
|
119
|
-
const mockSettings = { permissions: { deny: ['one'], allow: [] } };
|
|
120
|
-
fs.readFileSync.mockReturnValue(JSON.stringify(mockSettings));
|
|
121
|
-
|
|
122
|
-
const result = await settingsJsonCheck.run(mockContext);
|
|
123
|
-
expect(result.status).toBe('WARN');
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should WARN when boundary paths not covered by deny rules', async () => {
|
|
127
|
-
fs.existsSync.mockReturnValue(true);
|
|
128
|
-
const mockSettings = {
|
|
129
|
-
permissions: {
|
|
130
|
-
deny: new Array(50).fill('Edit(docs/)'),
|
|
131
|
-
allow: [],
|
|
132
|
-
},
|
|
133
|
-
};
|
|
134
|
-
const coreConfig = 'boundary:\n protected:\n - .sinapse-ai/core/**\n - bin/sinapse.js\n exceptions:\n - test';
|
|
135
|
-
fs.readFileSync.mockImplementation((p) => {
|
|
136
|
-
if (p.includes('settings.json')) return JSON.stringify(mockSettings);
|
|
137
|
-
if (p.includes('core-config')) return coreConfig;
|
|
138
|
-
return '';
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
const result = await settingsJsonCheck.run(mockContext);
|
|
142
|
-
expect(result.status).toBe('WARN');
|
|
143
|
-
expect(result.message).toContain('boundary coverage');
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
describe('rules-files check', () => {
|
|
148
|
-
it('should PASS when all 7 rules files exist', async () => {
|
|
149
|
-
fs.existsSync.mockReturnValue(true);
|
|
150
|
-
const result = await rulesFilesCheck.run(mockContext);
|
|
151
|
-
expect(result.status).toBe('PASS');
|
|
152
|
-
expect(result.message).toContain('7');
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
it('should FAIL when rules directory missing', async () => {
|
|
156
|
-
fs.existsSync.mockReturnValue(false);
|
|
157
|
-
const result = await rulesFilesCheck.run(mockContext);
|
|
158
|
-
expect(result.status).toBe('FAIL');
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should WARN when some rules missing', async () => {
|
|
162
|
-
fs.existsSync.mockImplementation((p) => {
|
|
163
|
-
// Directory exists
|
|
164
|
-
if (p.endsWith('rules')) return true;
|
|
165
|
-
// Most files exist except 2
|
|
166
|
-
if (p.includes('agent-authority') || p.includes('workflow-execution')) return false;
|
|
167
|
-
return true;
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
const result = await rulesFilesCheck.run(mockContext);
|
|
171
|
-
expect(result.status).toBe('WARN');
|
|
172
|
-
expect(result.message).toContain('Missing 2');
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
describe('agent-memory check', () => {
|
|
177
|
-
it('should PASS when all 10 MEMORY.md files exist', async () => {
|
|
178
|
-
fs.existsSync.mockReturnValue(true);
|
|
179
|
-
const result = await agentMemoryCheck.run(mockContext);
|
|
180
|
-
expect(result.status).toBe('PASS');
|
|
181
|
-
expect(result.message).toContain('10/10');
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
it('should WARN when some MEMORY.md files missing', async () => {
|
|
185
|
-
fs.existsSync.mockImplementation((p) => {
|
|
186
|
-
if (p.endsWith('agents')) return true;
|
|
187
|
-
if (p.includes('analyst') || p.includes('ux')) return false;
|
|
188
|
-
return true;
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
const result = await agentMemoryCheck.run(mockContext);
|
|
192
|
-
expect(result.status).toBe('WARN');
|
|
193
|
-
expect(result.message).toContain('8/10');
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
describe('entity-registry check', () => {
|
|
198
|
-
it('should PASS when registry exists and is fresh', async () => {
|
|
199
|
-
fs.existsSync.mockReturnValue(true);
|
|
200
|
-
fs.statSync.mockReturnValue({ mtimeMs: Date.now() - 1000 });
|
|
201
|
-
fs.readFileSync.mockReturnValue('line1\nline2\nline3');
|
|
202
|
-
|
|
203
|
-
const result = await entityRegistryCheck.run(mockContext);
|
|
204
|
-
expect(result.status).toBe('PASS');
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('should FAIL when registry not found', async () => {
|
|
208
|
-
fs.existsSync.mockReturnValue(false);
|
|
209
|
-
const result = await entityRegistryCheck.run(mockContext);
|
|
210
|
-
expect(result.status).toBe('FAIL');
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
it('should WARN when registry is stale (>48h)', async () => {
|
|
214
|
-
fs.existsSync.mockReturnValue(true);
|
|
215
|
-
fs.statSync.mockReturnValue({ mtimeMs: Date.now() - 72 * 60 * 60 * 1000 });
|
|
216
|
-
fs.readFileSync.mockReturnValue('line1\nline2');
|
|
217
|
-
|
|
218
|
-
const result = await entityRegistryCheck.run(mockContext);
|
|
219
|
-
expect(result.status).toBe('WARN');
|
|
220
|
-
expect(result.message).toContain('72h');
|
|
221
|
-
});
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
describe('git-hooks check', () => {
|
|
225
|
-
it('should PASS when both hooks exist', async () => {
|
|
226
|
-
fs.existsSync.mockReturnValue(true);
|
|
227
|
-
const result = await gitHooksCheck.run(mockContext);
|
|
228
|
-
expect(result.status).toBe('PASS');
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
it('should WARN when .husky directory missing', async () => {
|
|
232
|
-
fs.existsSync.mockReturnValue(false);
|
|
233
|
-
const result = await gitHooksCheck.run(mockContext);
|
|
234
|
-
expect(result.status).toBe('WARN');
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
describe('core-config check', () => {
|
|
239
|
-
it('should PASS when config has all required sections', async () => {
|
|
240
|
-
fs.existsSync.mockReturnValue(true);
|
|
241
|
-
fs.readFileSync.mockReturnValue('boundary:\n test: true\nproject:\n name: test\nide:\n sync: true');
|
|
242
|
-
|
|
243
|
-
const result = await coreConfigCheck.run(mockContext);
|
|
244
|
-
expect(result.status).toBe('PASS');
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should FAIL when config missing', async () => {
|
|
248
|
-
fs.existsSync.mockReturnValue(false);
|
|
249
|
-
const result = await coreConfigCheck.run(mockContext);
|
|
250
|
-
expect(result.status).toBe('FAIL');
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
it('should FAIL when missing required sections', async () => {
|
|
254
|
-
fs.existsSync.mockReturnValue(true);
|
|
255
|
-
fs.readFileSync.mockReturnValue('project:\n name: test');
|
|
256
|
-
|
|
257
|
-
const result = await coreConfigCheck.run(mockContext);
|
|
258
|
-
expect(result.status).toBe('FAIL');
|
|
259
|
-
expect(result.message).toContain('boundary');
|
|
260
|
-
});
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
describe('claude-md check', () => {
|
|
264
|
-
it('should PASS when all sections present', async () => {
|
|
265
|
-
fs.existsSync.mockReturnValue(true);
|
|
266
|
-
fs.readFileSync.mockReturnValue(
|
|
267
|
-
'## Constitution\n## Framework vs Project Boundary\n## Sistema de Agentes',
|
|
268
|
-
);
|
|
269
|
-
|
|
270
|
-
const result = await claudeMdCheck.run(mockContext);
|
|
271
|
-
expect(result.status).toBe('PASS');
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
it('should WARN when sections missing', async () => {
|
|
275
|
-
fs.existsSync.mockReturnValue(true);
|
|
276
|
-
fs.readFileSync.mockReturnValue('## Constitution\nSome content');
|
|
277
|
-
|
|
278
|
-
const result = await claudeMdCheck.run(mockContext);
|
|
279
|
-
expect(result.status).toBe('WARN');
|
|
280
|
-
expect(result.message).toContain('Missing sections');
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
describe('graph-dashboard check', () => {
|
|
285
|
-
it('should PASS when directory has .js files', async () => {
|
|
286
|
-
fs.existsSync.mockReturnValue(true);
|
|
287
|
-
fs.readdirSync.mockReturnValue(['index.js', 'cli.js']);
|
|
288
|
-
|
|
289
|
-
const result = await graphDashboardCheck.run(mockContext);
|
|
290
|
-
expect(result.status).toBe('PASS');
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
it('should WARN when directory missing', async () => {
|
|
294
|
-
fs.existsSync.mockReturnValue(false);
|
|
295
|
-
const result = await graphDashboardCheck.run(mockContext);
|
|
296
|
-
expect(result.status).toBe('WARN');
|
|
297
|
-
});
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
describe('code-intel check', () => {
|
|
301
|
-
// The code-intel check does a real require() of index.js and triggers
|
|
302
|
-
// provider auto-detection. Tests that need provider detection must use
|
|
303
|
-
// the real projectRoot and real fs (jest.requireActual).
|
|
304
|
-
const realFs = jest.requireActual('fs');
|
|
305
|
-
const realProjectRoot = path.join(__dirname, '..', '..', '..', '..', '..');
|
|
306
|
-
|
|
307
|
-
it('should return INFO when code-intel dir does not exist', async () => {
|
|
308
|
-
fs.existsSync.mockReturnValue(false);
|
|
309
|
-
const result = await codeIntelCheck.run(mockContext);
|
|
310
|
-
expect(result.status).toBe('INFO');
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it('should WARN when index.js missing but dir exists', async () => {
|
|
314
|
-
fs.existsSync.mockImplementation((p) => {
|
|
315
|
-
// Dir exists, but index.js does not
|
|
316
|
-
if (p.includes('index.js')) return false;
|
|
317
|
-
return true;
|
|
318
|
-
});
|
|
319
|
-
const result = await codeIntelCheck.run(mockContext);
|
|
320
|
-
expect(result.status).toBe('WARN');
|
|
321
|
-
expect(result.message).toContain('index.js not found');
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('should PASS with RegistryProvider when entity-registry exists', async () => {
|
|
325
|
-
// Use real fs + real project root so require() resolves the actual module
|
|
326
|
-
// and RegistryProvider can load the real entity-registry.yaml
|
|
327
|
-
const realContext = {
|
|
328
|
-
...mockContext,
|
|
329
|
-
projectRoot: realProjectRoot,
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
// Temporarily restore real fs for this test
|
|
333
|
-
fs.existsSync.mockImplementation(realFs.existsSync);
|
|
334
|
-
fs.readFileSync.mockImplementation(realFs.readFileSync);
|
|
335
|
-
fs.statSync.mockImplementation(realFs.statSync);
|
|
336
|
-
|
|
337
|
-
// Only run if entity-registry actually exists (skip in CI without registry)
|
|
338
|
-
const registryPath = path.join(realProjectRoot, '.sinapse-ai', 'data', 'entity-registry.yaml');
|
|
339
|
-
if (!realFs.existsSync(registryPath)) {
|
|
340
|
-
return; // skip — no registry available
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
const result = await codeIntelCheck.run(realContext);
|
|
344
|
-
expect(result.status).toBe('PASS');
|
|
345
|
-
expect(result.message).toContain('RegistryProvider');
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('should WARN when provider detection fails (no valid registry)', async () => {
|
|
349
|
-
// Use real project root so require() works, but mock registry as empty
|
|
350
|
-
const realContext = {
|
|
351
|
-
...mockContext,
|
|
352
|
-
projectRoot: realProjectRoot,
|
|
353
|
-
};
|
|
354
|
-
|
|
355
|
-
// Real existsSync for module resolution, mocked readFileSync for empty registry
|
|
356
|
-
fs.existsSync.mockImplementation((p) => {
|
|
357
|
-
if (p.includes('entity-registry.yaml')) return true;
|
|
358
|
-
return realFs.existsSync(p);
|
|
359
|
-
});
|
|
360
|
-
fs.statSync.mockImplementation((p) => {
|
|
361
|
-
if (p.includes('entity-registry.yaml')) return { mtimeMs: Date.now(), size: 10 };
|
|
362
|
-
return realFs.statSync(p);
|
|
363
|
-
});
|
|
364
|
-
fs.readFileSync.mockImplementation((p, enc) => {
|
|
365
|
-
if (typeof p === 'string' && p.includes('entity-registry.yaml')) {
|
|
366
|
-
return 'metadata:\n entityCount: 0';
|
|
367
|
-
}
|
|
368
|
-
return realFs.readFileSync(p, enc);
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
const result = await codeIntelCheck.run(realContext);
|
|
372
|
-
// Without valid entities, provider won't be available → WARN or INFO
|
|
373
|
-
expect(['WARN', 'INFO']).toContain(result.status);
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
describe('ide-sync check', () => {
|
|
378
|
-
it('should PASS when counts match', async () => {
|
|
379
|
-
fs.existsSync.mockReturnValue(true);
|
|
380
|
-
fs.readdirSync.mockImplementation((p) => {
|
|
381
|
-
if (p.includes('commands')) return ['dev.md', 'qa.md'];
|
|
382
|
-
return ['dev.md', 'qa.md'];
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const result = await ideSyncCheck.run(mockContext);
|
|
386
|
-
expect(result.status).toBe('PASS');
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
it('should WARN when IDE has fewer agents than expected (Audit 1 P1 DOC-1)', async () => {
|
|
390
|
-
// Post-DOC-1 fix: WARN fires when IDE count < (framework + squad orqx).
|
|
391
|
-
// Source dir has 5 framework agents; IDE has only 2 (missing 3 expected).
|
|
392
|
-
fs.existsSync.mockReturnValue(true);
|
|
393
|
-
fs.readdirSync.mockImplementation((p) => {
|
|
394
|
-
if (p.includes('commands')) return ['dev.md', 'qa.md']; // 2 in IDE
|
|
395
|
-
// Source agents dir — 5 framework agents (>= IDE count → expected gap)
|
|
396
|
-
return ['dev.md', 'qa.md', 'pm.md', 'po.md', 'sm.md'];
|
|
397
|
-
});
|
|
398
|
-
|
|
399
|
-
const result = await ideSyncCheck.run(mockContext);
|
|
400
|
-
expect(result.status).toBe('WARN');
|
|
401
|
-
});
|
|
402
|
-
});
|
|
403
|
-
|
|
404
|
-
// === INS-4.8: New checks ===
|
|
405
|
-
|
|
406
|
-
describe('skills-count check', () => {
|
|
407
|
-
// v1.4.2: .claude/skills/ is an OPTIONAL user-installed area, not shipped by
|
|
408
|
-
// `npx sinapse-ai install`. The check never FAILs: it PASSes proportional to
|
|
409
|
-
// however many skills the user installed (>=1), and reports INFO when the
|
|
410
|
-
// directory is absent or empty.
|
|
411
|
-
|
|
412
|
-
it('should PASS when skill directories with SKILL.md exist', async () => {
|
|
413
|
-
fs.existsSync.mockReturnValue(true);
|
|
414
|
-
const dirs = Array.from({ length: 8 }, (_, i) => ({
|
|
415
|
-
name: `skill-${i}`,
|
|
416
|
-
isDirectory: () => true,
|
|
417
|
-
isFile: () => false,
|
|
418
|
-
}));
|
|
419
|
-
fs.readdirSync.mockReturnValue(dirs);
|
|
420
|
-
|
|
421
|
-
const result = await skillsCountCheck.run(mockContext);
|
|
422
|
-
expect(result.check).toBe('skills-count');
|
|
423
|
-
expect(result.status).toBe('PASS');
|
|
424
|
-
expect(result.message).toContain('8');
|
|
425
|
-
});
|
|
426
|
-
|
|
427
|
-
it('should PASS even with a small number of installed skills', async () => {
|
|
428
|
-
fs.existsSync.mockReturnValue(true);
|
|
429
|
-
const dirs = Array.from({ length: 3 }, (_, i) => ({
|
|
430
|
-
name: `skill-${i}`,
|
|
431
|
-
isDirectory: () => true,
|
|
432
|
-
isFile: () => false,
|
|
433
|
-
}));
|
|
434
|
-
fs.readdirSync.mockReturnValue(dirs);
|
|
435
|
-
|
|
436
|
-
const result = await skillsCountCheck.run(mockContext);
|
|
437
|
-
expect(result.status).toBe('PASS');
|
|
438
|
-
expect(result.message).toContain('3');
|
|
439
|
-
});
|
|
440
|
-
|
|
441
|
-
it('should report INFO (not FAIL) when 0 skills found', async () => {
|
|
442
|
-
// skills dir exists, but no subdir has a SKILL.md → count 0.
|
|
443
|
-
fs.existsSync.mockImplementation((p) => !String(p).includes('SKILL.md'));
|
|
444
|
-
const dirs = [{ name: 'empty', isDirectory: () => true, isFile: () => false }];
|
|
445
|
-
fs.readdirSync.mockReturnValue(dirs);
|
|
446
|
-
|
|
447
|
-
const result = await skillsCountCheck.run(mockContext);
|
|
448
|
-
expect(result.status).toBe('INFO');
|
|
449
|
-
expect(result.fixCommand).toBeNull();
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
it('should report INFO (not FAIL) when skills directory missing', async () => {
|
|
453
|
-
fs.existsSync.mockReturnValue(false);
|
|
454
|
-
const result = await skillsCountCheck.run(mockContext);
|
|
455
|
-
expect(result.status).toBe('INFO');
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
describe('commands-count check', () => {
|
|
460
|
-
it('should PASS when >=20 command files', async () => {
|
|
461
|
-
fs.existsSync.mockReturnValue(true);
|
|
462
|
-
const files = Array.from({ length: 22 }, (_, i) => ({
|
|
463
|
-
name: `cmd-${i}.md`,
|
|
464
|
-
isDirectory: () => false,
|
|
465
|
-
isFile: () => true,
|
|
466
|
-
}));
|
|
467
|
-
fs.readdirSync.mockReturnValue(files);
|
|
468
|
-
|
|
469
|
-
const result = await commandsCountCheck.run(mockContext);
|
|
470
|
-
expect(result.check).toBe('commands-count');
|
|
471
|
-
expect(result.status).toBe('PASS');
|
|
472
|
-
expect(result.message).toContain('22');
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
it('should WARN when 12-19 command files', async () => {
|
|
476
|
-
fs.existsSync.mockReturnValue(true);
|
|
477
|
-
const files = Array.from({ length: 15 }, (_, i) => ({
|
|
478
|
-
name: `cmd-${i}.md`,
|
|
479
|
-
isDirectory: () => false,
|
|
480
|
-
isFile: () => true,
|
|
481
|
-
}));
|
|
482
|
-
fs.readdirSync.mockReturnValue(files);
|
|
483
|
-
|
|
484
|
-
const result = await commandsCountCheck.run(mockContext);
|
|
485
|
-
expect(result.status).toBe('WARN');
|
|
486
|
-
expect(result.message).toContain('15/20');
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
it('should FAIL when <12 command files', async () => {
|
|
490
|
-
fs.existsSync.mockReturnValue(true);
|
|
491
|
-
const files = Array.from({ length: 5 }, (_, i) => ({
|
|
492
|
-
name: `cmd-${i}.md`,
|
|
493
|
-
isDirectory: () => false,
|
|
494
|
-
isFile: () => true,
|
|
495
|
-
}));
|
|
496
|
-
fs.readdirSync.mockReturnValue(files);
|
|
497
|
-
|
|
498
|
-
const result = await commandsCountCheck.run(mockContext);
|
|
499
|
-
expect(result.status).toBe('FAIL');
|
|
500
|
-
expect(result.message).toContain('5');
|
|
501
|
-
});
|
|
502
|
-
|
|
503
|
-
it('should FAIL when commands directory missing', async () => {
|
|
504
|
-
fs.existsSync.mockReturnValue(false);
|
|
505
|
-
const result = await commandsCountCheck.run(mockContext);
|
|
506
|
-
expect(result.status).toBe('FAIL');
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
|
|
510
|
-
describe('hooks-claude-count check', () => {
|
|
511
|
-
it('should PASS when >=2 hook files and registered', async () => {
|
|
512
|
-
fs.existsSync.mockReturnValue(true);
|
|
513
|
-
const hookFiles = [
|
|
514
|
-
{ name: 'enforce-git-push.cjs', isFile: () => true, isDirectory: () => false },
|
|
515
|
-
{ name: 'pre-commit-check.cjs', isFile: () => true, isDirectory: () => false },
|
|
516
|
-
];
|
|
517
|
-
fs.readdirSync.mockReturnValue(hookFiles);
|
|
518
|
-
const settingsLocal = {
|
|
519
|
-
hooks: {
|
|
520
|
-
PreToolUse: [{ command: 'node .claude/hooks/enforce-git-push.cjs' }],
|
|
521
|
-
PostToolUse: [{ command: 'node .claude/hooks/pre-commit-check.cjs' }],
|
|
522
|
-
},
|
|
523
|
-
};
|
|
524
|
-
fs.readFileSync.mockReturnValue(JSON.stringify(settingsLocal));
|
|
525
|
-
|
|
526
|
-
const result = await hooksClaudeCountCheck.run(mockContext);
|
|
527
|
-
expect(result.check).toBe('hooks-claude-count');
|
|
528
|
-
expect(result.status).toBe('PASS');
|
|
529
|
-
expect(result.message).toContain('2');
|
|
530
|
-
});
|
|
531
|
-
|
|
532
|
-
it('should WARN when hooks present but not registered', async () => {
|
|
533
|
-
fs.existsSync.mockImplementation((p) => {
|
|
534
|
-
if (p.includes('settings.local.json')) return true;
|
|
535
|
-
return true;
|
|
536
|
-
});
|
|
537
|
-
const hookFiles = [
|
|
538
|
-
{ name: 'hook-a.cjs', isFile: () => true, isDirectory: () => false },
|
|
539
|
-
{ name: 'hook-b.cjs', isFile: () => true, isDirectory: () => false },
|
|
540
|
-
];
|
|
541
|
-
fs.readdirSync.mockReturnValue(hookFiles);
|
|
542
|
-
fs.readFileSync.mockReturnValue(JSON.stringify({ hooks: {} }));
|
|
543
|
-
|
|
544
|
-
const result = await hooksClaudeCountCheck.run(mockContext);
|
|
545
|
-
expect(result.status).toBe('WARN');
|
|
546
|
-
expect(result.message).toContain('not registered');
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
it('should WARN when <2 hook files', async () => {
|
|
550
|
-
fs.existsSync.mockReturnValue(true);
|
|
551
|
-
const hookFiles = [
|
|
552
|
-
{ name: 'single-hook.cjs', isFile: () => true, isDirectory: () => false },
|
|
553
|
-
];
|
|
554
|
-
fs.readdirSync.mockReturnValue(hookFiles);
|
|
555
|
-
fs.readFileSync.mockReturnValue(JSON.stringify({ hooks: {} }));
|
|
556
|
-
|
|
557
|
-
const result = await hooksClaudeCountCheck.run(mockContext);
|
|
558
|
-
expect(result.status).toBe('WARN');
|
|
559
|
-
expect(result.message).toContain('1/2');
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
it('should FAIL when no hook files found', async () => {
|
|
563
|
-
fs.existsSync.mockReturnValue(true);
|
|
564
|
-
fs.readdirSync.mockReturnValue([]);
|
|
565
|
-
|
|
566
|
-
const result = await hooksClaudeCountCheck.run(mockContext);
|
|
567
|
-
expect(result.status).toBe('FAIL');
|
|
568
|
-
});
|
|
569
|
-
|
|
570
|
-
it('should FAIL when hooks directory missing', async () => {
|
|
571
|
-
fs.existsSync.mockReturnValue(false);
|
|
572
|
-
const result = await hooksClaudeCountCheck.run(mockContext);
|
|
573
|
-
expect(result.status).toBe('FAIL');
|
|
574
|
-
});
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
// === INS-4.8: Registry and task validation ===
|
|
578
|
-
|
|
579
|
-
describe('check registry (INS-4.8)', () => {
|
|
580
|
-
it('should load 15 checks total', () => {
|
|
581
|
-
// loadChecks is the real function (not mocked) — verifies registration
|
|
582
|
-
const checks = loadChecks();
|
|
583
|
-
expect(checks).toHaveLength(16);
|
|
584
|
-
});
|
|
585
|
-
|
|
586
|
-
it('should include all 3 new checks', () => {
|
|
587
|
-
const checks = loadChecks();
|
|
588
|
-
const names = checks.map((c) => c.name);
|
|
589
|
-
expect(names).toContain('skills-count');
|
|
590
|
-
expect(names).toContain('commands-count');
|
|
591
|
-
expect(names).toContain('hooks-claude-count');
|
|
592
|
-
});
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
describe('health-check.yaml task (INS-4.8)', () => {
|
|
596
|
-
it('should NOT have *doctor alias', () => {
|
|
597
|
-
const realFs = jest.requireActual('fs');
|
|
598
|
-
const yaml = realFs.readFileSync(
|
|
599
|
-
path.join(__dirname, '..', '..', '..', '..', '..', '.sinapse-ai', 'development', 'tasks', 'health-check.yaml'),
|
|
600
|
-
'utf8',
|
|
601
|
-
);
|
|
602
|
-
// Verify *doctor is not in the aliases list (only *hc should be)
|
|
603
|
-
const aliasMatch = yaml.match(/aliases:\s*\n((?:\s+-\s+.*\n)*)/);
|
|
604
|
-
expect(aliasMatch).toBeTruthy();
|
|
605
|
-
expect(aliasMatch[1]).not.toContain('*doctor');
|
|
606
|
-
expect(aliasMatch[1]).toContain('*hc');
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
it('should reference sinapse doctor --json in instructions', () => {
|
|
610
|
-
const realFs = jest.requireActual('fs');
|
|
611
|
-
const yaml = realFs.readFileSync(
|
|
612
|
-
path.join(__dirname, '..', '..', '..', '..', '..', '.sinapse-ai', 'development', 'tasks', 'health-check.yaml'),
|
|
613
|
-
'utf8',
|
|
614
|
-
);
|
|
615
|
-
expect(yaml).toContain('sinapse doctor --json');
|
|
616
|
-
expect(yaml).toContain('npx sinapse-ai doctor --json');
|
|
617
|
-
});
|
|
618
|
-
|
|
619
|
-
it('should have governance_map with all 15 checks', () => {
|
|
620
|
-
const realFs = jest.requireActual('fs');
|
|
621
|
-
const yaml = realFs.readFileSync(
|
|
622
|
-
path.join(__dirname, '..', '..', '..', '..', '..', '.sinapse-ai', 'development', 'tasks', 'health-check.yaml'),
|
|
623
|
-
'utf8',
|
|
624
|
-
);
|
|
625
|
-
const expectedChecks = [
|
|
626
|
-
'settings-json', 'rules-files', 'agent-memory', 'entity-registry',
|
|
627
|
-
'git-hooks', 'core-config', 'claude-md', 'ide-sync', 'graph-dashboard',
|
|
628
|
-
'code-intel', 'node-version', 'npm-packages', 'skills-count',
|
|
629
|
-
'commands-count', 'hooks-claude-count',
|
|
630
|
-
];
|
|
631
|
-
for (const check of expectedChecks) {
|
|
632
|
-
expect(yaml).toContain(`${check}:`);
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
|