sinapse-ai 9.3.0 → 9.5.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/.claude/CLAUDE.md +60 -341
- package/.claude/hooks/enforce-architecture-first.py +197 -197
- package/.claude/hooks/enforce-git-push-authority.sh +25 -4
- package/.claude/hooks/mind-clone-governance.py +193 -193
- package/.claude/hooks/read-protection.py +152 -152
- package/.claude/hooks/sql-governance.py +183 -183
- package/.claude/hooks/verify-packages.cjs +83 -0
- package/.claude/hooks/write-path-validation.py +195 -195
- package/.claude/rules/agent-authority.md +6 -0
- package/.claude/rules/agent-handoff.md +5 -0
- package/.claude/rules/cross-squad-routing.md +5 -0
- package/.claude/rules/hook-governance.md +7 -0
- package/.claude/rules/mandatory-delegation.md +24 -0
- package/.claude/rules/mcp-usage.md +3 -1
- package/.claude/rules/project-intelligence.md +63 -0
- package/.claude/rules/response-format.md +4 -0
- package/.claude/rules/safe-collaboration.md +14 -2
- package/.claude/rules/security-data-protection.md +27 -0
- package/.claude/rules/squad-awareness.md +96 -68
- package/.claude/rules/token-economy.md +148 -0
- package/.claude/rules/tool-examples.md +6 -0
- package/.claude/rules/workflow-execution.md +7 -0
- package/.codex/agents/analyst.md +342 -71
- package/.codex/agents/architect.md +533 -68
- package/.codex/agents/data-engineer.md +530 -106
- package/.codex/agents/developer.md +657 -0
- package/.codex/agents/devops.md +639 -69
- package/.codex/agents/product-lead.md +362 -0
- package/.codex/agents/project-lead.md +405 -0
- package/.codex/agents/quality-gate.md +538 -0
- package/.codex/agents/sinapse-orqx.md +9 -7
- package/.codex/agents/sprint-lead.md +315 -0
- package/.codex/agents/squad-creator.md +402 -0
- package/.codex/agents/ux-design-expert.md +523 -0
- package/.codex/delegation-matrix.json +756 -44
- package/.codex/handoff-packet.schema.json +30 -6
- package/.sinapse-ai/core/code-intel/registry-syncer.js +56 -3
- package/.sinapse-ai/core/doctor/checks/agent-memory.js +5 -1
- package/.sinapse-ai/core/doctor/checks/claude-md.js +4 -1
- package/.sinapse-ai/core/doctor/checks/code-intel.js +5 -1
- package/.sinapse-ai/core/doctor/checks/commands-count.js +4 -1
- package/.sinapse-ai/core/doctor/checks/constitution-consistency.js +4 -1
- package/.sinapse-ai/core/doctor/checks/core-config.js +4 -1
- package/.sinapse-ai/core/doctor/checks/entity-registry.js +6 -1
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +5 -1
- package/.sinapse-ai/core/doctor/checks/graph-dashboard.js +4 -1
- package/.sinapse-ai/core/doctor/checks/hooks-claude-count.js +5 -1
- package/.sinapse-ai/core/doctor/checks/ide-sync.js +4 -1
- package/.sinapse-ai/core/doctor/checks/node-version.js +4 -1
- package/.sinapse-ai/core/doctor/checks/npm-packages.js +4 -1
- package/.sinapse-ai/core/doctor/checks/rules-files.js +4 -1
- package/.sinapse-ai/core/doctor/checks/settings-json.js +4 -1
- package/.sinapse-ai/core/doctor/checks/skills-count.js +4 -1
- package/.sinapse-ai/core/doctor/index.js +157 -50
- package/.sinapse-ai/core/ids/registry-updater.js +6 -1
- package/.sinapse-ai/core/logger/index.js +319 -0
- package/.sinapse-ai/core/orchestration/terminal-spawner.js +2 -2
- package/.sinapse-ai/core/telemetry/index.js +247 -0
- package/.sinapse-ai/data/entity-registry.yaml +1060 -808
- package/.sinapse-ai/development/agents/analyst.md +90 -0
- package/.sinapse-ai/development/agents/architect.md +78 -0
- package/.sinapse-ai/development/agents/data-engineer.md +38 -0
- package/.sinapse-ai/development/agents/developer.md +97 -0
- package/.sinapse-ai/development/agents/devops.md +121 -0
- package/.sinapse-ai/development/agents/product-lead.md +27 -0
- package/.sinapse-ai/development/agents/project-lead.md +28 -0
- package/.sinapse-ai/development/agents/quality-gate.md +89 -0
- package/.sinapse-ai/development/agents/sprint-lead/MEMORY.md +8 -0
- package/.sinapse-ai/development/agents/sprint-lead.md +28 -0
- package/.sinapse-ai/development/agents/squad-creator.md +58 -0
- package/.sinapse-ai/development/agents/ux-design-expert.md +28 -0
- package/.sinapse-ai/development/checklists/agent-quality-gate.md +27 -0
- package/.sinapse-ai/development/checklists/brownfield-compatibility-checklist.md +20 -0
- package/.sinapse-ai/development/checklists/code-review-checklist.md +106 -0
- package/.sinapse-ai/development/checklists/issue-triage-checklist.md +9 -0
- package/.sinapse-ai/development/checklists/memory-audit-checklist.md +16 -0
- package/.sinapse-ai/development/checklists/pr-quality-checklist.md +72 -0
- package/.sinapse-ai/development/checklists/security-deployment-checklist.md +54 -0
- package/.sinapse-ai/development/checklists/self-critique-checklist.md +19 -1
- package/.sinapse-ai/development/knowledge-base/agent-communication-protocol.md +127 -0
- package/.sinapse-ai/development/knowledge-base/database-scaling-patterns.md +374 -0
- package/.sinapse-ai/development/knowledge-base/environment-deployment-patterns.md +353 -0
- package/.sinapse-ai/development/knowledge-base/gotchas-patterns.md +224 -0
- package/.sinapse-ai/development/knowledge-base/infrastructure-decision-framework.md +221 -0
- package/.sinapse-ai/development/knowledge-base/security-pre-deploy-checklist.md +410 -0
- package/.sinapse-ai/development/knowledge-base/software-architecture-patterns.md +299 -0
- package/.sinapse-ai/development/knowledge-base/token-economy-guide.md +198 -0
- package/.sinapse-ai/development/scripts/populate-entity-registry.js +5 -1
- package/.sinapse-ai/development/skills/captcha-handler.md +82 -0
- package/.sinapse-ai/development/skills/chrome-brain.md +81 -0
- package/.sinapse-ai/development/skills/debug.md +57 -0
- package/.sinapse-ai/development/skills/deploy-readiness.md +93 -0
- package/.sinapse-ai/development/skills/fast-review.md +69 -0
- package/.sinapse-ai/development/skills/model-router.md +92 -0
- package/.sinapse-ai/development/skills/research-synthesis.md +77 -0
- package/.sinapse-ai/development/skills/security-scan.md +73 -0
- package/.sinapse-ai/development/skills/sinapse-methodology.md +175 -0
- package/.sinapse-ai/development/skills/story-fast-track.md +71 -0
- package/.sinapse-ai/development/skills/verify.md +53 -0
- package/.sinapse-ai/development/tasks/dev-develop-story.md +10 -0
- package/.sinapse-ai/development/tasks/environment-promotion-pipeline.md +582 -0
- package/.sinapse-ai/development/tasks/generate-agent-handoff.md +223 -0
- package/.sinapse-ai/development/tasks/infrastructure-assessment.md +432 -0
- package/.sinapse-ai/development/tasks/load-testing-setup.md +611 -0
- package/.sinapse-ai/development/tasks/observability-blueprint.md +562 -0
- package/.sinapse-ai/development/templates/legal/breach-notification-tmpl.md +113 -0
- package/.sinapse-ai/development/templates/legal/privacy-policy-tmpl.md +93 -0
- package/.sinapse-ai/development/templates/legal/terms-of-service-tmpl.md +85 -0
- 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/agent-template.md +17 -4
- package/.sinapse-ai/development/templates/squad/checklist-template.md +13 -5
- package/.sinapse-ai/development/templates/squad/task-template.md +7 -0
- package/.sinapse-ai/development/templates/squad/workflow-template.yaml +7 -0
- package/.sinapse-ai/development/templates/squad-template/LICENSE +22 -22
- package/.sinapse-ai/development/workflows/fast-track.yaml +87 -0
- package/.sinapse-ai/development/workflows/story-development-cycle.yaml +40 -1
- package/.sinapse-ai/hooks/ids-post-commit.js +22 -0
- package/.sinapse-ai/infrastructure/contracts/compatibility/README.md +42 -0
- package/.sinapse-ai/infrastructure/contracts/compatibility/sinapse-current.yaml +35 -0
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/claude-free-tracked.cmd +127 -127
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-proxy.cmd +71 -71
- package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-usage.cmd +51 -51
- package/.sinapse-ai/infrastructure/scripts/pr-review-ai.js +16 -13
- package/.sinapse-ai/infrastructure/scripts/setup-project-infra.js +128 -0
- package/.sinapse-ai/infrastructure/scripts/test-discovery.js +8 -3
- package/.sinapse-ai/infrastructure/scripts/validate-codex-delegation.js +3 -1
- package/.sinapse-ai/infrastructure/scripts/validate-manifest-parity.js +380 -0
- package/.sinapse-ai/infrastructure/scripts/validate-parity.js +76 -25
- package/.sinapse-ai/infrastructure/templates/coderabbit.yaml.template +280 -280
- package/.sinapse-ai/infrastructure/templates/config/env.example +16 -0
- package/.sinapse-ai/infrastructure/templates/config/gitignore-additions.tmpl +59 -0
- package/.sinapse-ai/infrastructure/templates/github/CODEOWNERS.template +12 -0
- package/.sinapse-ai/infrastructure/templates/github/PULL_REQUEST_TEMPLATE.md +29 -0
- package/.sinapse-ai/infrastructure/templates/github/ci-template.yml +77 -0
- package/.sinapse-ai/infrastructure/templates/github/issue-templates/bug_report.md +34 -0
- package/.sinapse-ai/infrastructure/templates/github/issue-templates/feature_request.md +19 -0
- 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/sinapse-sync.yaml.template +183 -183
- package/.sinapse-ai/install-manifest.yaml +333 -162
- package/.sinapse-ai/local-config.yaml.template +65 -65
- package/.sinapse-ai/monitor/hooks/lib/__init__.py +2 -2
- package/.sinapse-ai/monitor/hooks/lib/enrich.py +59 -59
- package/.sinapse-ai/monitor/hooks/lib/send_event.py +48 -48
- package/.sinapse-ai/monitor/hooks/notification.py +30 -30
- package/.sinapse-ai/monitor/hooks/post_tool_use.py +46 -46
- package/.sinapse-ai/monitor/hooks/pre_compact.py +30 -30
- package/.sinapse-ai/monitor/hooks/pre_tool_use.py +41 -41
- package/.sinapse-ai/monitor/hooks/stop.py +30 -30
- package/.sinapse-ai/monitor/hooks/subagent_stop.py +30 -30
- package/.sinapse-ai/monitor/hooks/user_prompt_submit.py +39 -39
- 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/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/story-tmpl.yaml +59 -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/.sinapse-ai/scripts/diagnostics/health-dashboard/package-lock.json +427 -355
- package/LICENSE +34 -34
- package/README.en.md +167 -20
- package/README.md +190 -22
- package/bin/cli.js +510 -196
- package/bin/postinstall.js +564 -0
- package/bin/sinapse-cli +283 -283
- package/bin/sinapse-graph.js +9 -0
- package/bin/sinapse-init.js +36 -4
- package/bin/sinapse-minimal.js +20 -9
- package/bin/sinapse.js +202 -122
- package/bin/utils/deprecation-warning.js +46 -0
- package/bin/utils/pre-push-safety.js +14 -0
- package/docs/TELEMETRY.md +131 -0
- package/docs/chrome-brain-upgrade-plan.md +624 -0
- package/docs/codex-integration-process.md +22 -0
- package/docs/codex-parity-program.md +27 -0
- package/docs/framework/orqx-plan.md +1 -1
- package/docs/ide-integration.md +36 -0
- package/docs/installation/chrome-brain.md +17 -7
- package/docs/mega-upgrade-orchestration-plan.md +71 -0
- package/docs/pt/contributing.md +20 -0
- package/docs/research-synthesis-for-upgrade.md +511 -0
- package/docs/security-audit-report.md +306 -0
- package/package.json +20 -8
- package/packages/installer/src/config/configure-environment.js +19 -44
- package/packages/installer/src/detection/detect-project-type.js +181 -63
- package/packages/installer/src/installer/manifest-signature.js +32 -17
- package/packages/installer/src/wizard/i18n.js +12 -0
- package/packages/installer/src/wizard/ide-config-generator.js +8 -39
- package/packages/installer/src/wizard/index.js +119 -14
- package/packages/installer/src/wizard/questions.js +2 -3
- package/packages/installer/tests/integration/environment-configuration.test.js +7 -5
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +138 -1
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +3 -3
- package/packages/sinapse-install/bin/edmcp.js +0 -0
- package/packages/sinapse-install/bin/sinapse-install.js +0 -0
- package/packages/sinapse-pro-cli/bin/sinapse-pro.js +0 -0
- package/scripts/check-markdown-links.py +353 -353
- package/scripts/coverage-report-summary.js +169 -0
- package/scripts/generate-install-manifest.js +6 -2
- package/scripts/release-readiness.js +169 -0
- package/scripts/test-install-matrix-local.sh +153 -0
- package/scripts/validate-install-docs.js +394 -0
- package/scripts/validate-no-external-refs.js +376 -0
- package/scripts/validate-squad-orqx.js +302 -0
- package/scripts/validate-story-meta.js +263 -0
- package/squads/claude-code-mastery/CHANGELOG.md +1 -1
- package/squads/claude-code-mastery/README.md +2 -2
- package/squads/claude-code-mastery/knowledge-base/claude-code-internals-reference.md +927 -0
- package/squads/claude-code-mastery/squad.yaml +1 -1
- package/squads/squad-artdir/README.md +90 -0
- package/squads/squad-artdir/agents/accessibility-guardian.md +184 -0
- package/squads/squad-artdir/agents/artdir-orqx.md +145 -0
- package/squads/squad-artdir/agents/color-psychologist.md +166 -0
- package/squads/squad-artdir/agents/cro-persuasion.md +161 -0
- package/squads/squad-artdir/agents/design-system-architect.md +100 -0
- package/squads/squad-artdir/agents/ia-architect.md +169 -0
- package/squads/squad-artdir/agents/interaction-designer.md +162 -0
- package/squads/squad-artdir/agents/layout-engineer.md +163 -0
- package/squads/squad-artdir/agents/motion-architect.md +185 -0
- package/squads/squad-artdir/agents/platform-aesthetic-director.md +84 -0
- package/squads/squad-artdir/agents/premium-packaging-strategist.md +107 -0
- package/squads/squad-artdir/agents/product-surface-director.md +86 -0
- package/squads/squad-artdir/agents/type-systemist.md +138 -0
- package/squads/squad-artdir/agents/visual-strategist.md +127 -0
- package/squads/squad-artdir/checklists/seven-pillars-validation-checklist.md +172 -0
- package/squads/squad-artdir/knowledge-base/case-nyo-ia-reference.md +289 -0
- package/squads/squad-artdir/knowledge-base/deliverables-templates.md +457 -0
- package/squads/squad-artdir/knowledge-base/motion-technique-catalog.md +247 -0
- package/squads/squad-artdir/knowledge-base/premium-packaging-principles.md +133 -0
- package/squads/squad-artdir/knowledge-base/psychological-toolkit.md +229 -0
- package/squads/squad-artdir/knowledge-base/saas-art-direction-canon.md +242 -0
- package/squads/squad-artdir/knowledge-base/seven-pillars-framework.md +289 -0
- package/squads/squad-artdir/knowledge-base/ten-pillars-framework.md +221 -0
- package/squads/squad-artdir/package.json +20 -0
- package/squads/squad-artdir/squad.yaml +271 -0
- package/squads/squad-artdir/tasks/audit-conversion.md +97 -0
- package/squads/squad-artdir/tasks/audit-drift-multi-surface.md +55 -0
- package/squads/squad-artdir/tasks/consult-saas-canon.md +54 -0
- package/squads/squad-artdir/tasks/create-art-direction-brief.md +110 -0
- package/squads/squad-artdir/tasks/create-premium-packaging-brief.md +61 -0
- package/squads/squad-artdir/tasks/create-wireflow.md +84 -0
- package/squads/squad-artdir/tasks/design-color-system.md +81 -0
- package/squads/squad-artdir/tasks/design-product-surface.md +60 -0
- package/squads/squad-artdir/tasks/design-token-system.md +58 -0
- package/squads/squad-artdir/tasks/diagnose-visual-language.md +92 -0
- package/squads/squad-artdir/tasks/first-5-minutes-choreography.md +65 -0
- package/squads/squad-artdir/tasks/specify-motion-system.md +84 -0
- package/squads/squad-artdir/tasks/validate-against-pillars.md +143 -0
- package/squads/squad-artdir/templates/art-direction-brief-template.md +215 -0
- package/squads/squad-artdir/workflows/conversion-audit-cycle.yaml +78 -0
- package/squads/squad-artdir/workflows/full-art-direction-cycle.yaml +98 -0
- package/squads/squad-artdir/workflows/saas-platform-art-direction-cycle.yaml +174 -0
- package/squads/squad-brand/knowledge-base/ai-visual-generation-canon.md +234 -0
- package/squads/squad-brand/knowledge-base/archetype-brand-mapping.md +12 -1
- package/squads/squad-brand/knowledge-base/brand-activism-cultural-branding.md +216 -0
- package/squads/squad-brand/knowledge-base/brand-audit-criteria.md +58 -0
- package/squads/squad-brand/knowledge-base/brand-digital-strategy.md +188 -0
- package/squads/squad-brand/knowledge-base/brand-legal-ip.md +222 -0
- package/squads/squad-brand/knowledge-base/brand-naming-framework.md +163 -0
- package/squads/squad-brand/knowledge-base/branding-master-reference.md +1001 -0
- package/squads/squad-brand/knowledge-base/color-psychology.md +25 -12
- package/squads/squad-brand/knowledge-base/employer-personal-branding.md +206 -0
- package/squads/squad-brand/knowledge-base/routing-catalog.md +34 -0
- package/squads/squad-brand/knowledge-base/sonic-branding-principles.md +6 -1
- package/squads/squad-brand/knowledge-base/typography-personality.md +34 -0
- package/squads/squad-brand/squad.yaml +20 -6
- package/squads/squad-claude/knowledge-base/context-window-optimization.md +334 -0
- package/squads/squad-claude/knowledge-base/knowledge-architecture-reference.md +403 -0
- package/squads/squad-claude/knowledge-base/memory-systems-reference.md +412 -0
- package/squads/squad-claude/knowledge-base/obsidian-claude-integration.md +423 -0
- package/squads/squad-claude/knowledge-base/retrieval-augmented-generation.md +320 -0
- package/squads/squad-claude/knowledge-base/skill-creation-patterns.md +380 -0
- package/squads/squad-claude/knowledge-base/swarm-orchestration-patterns.md +411 -0
- package/squads/squad-cloning/knowledge-base/clone-quality-assurance.md +211 -0
- package/squads/squad-cloning/knowledge-base/confidence-scoring.md +51 -0
- package/squads/squad-cloning/knowledge-base/cross-squad-deployment.md +47 -0
- package/squads/squad-cloning/knowledge-base/ethical-guidelines.md +237 -0
- package/squads/squad-cloning/knowledge-base/knowledge-graph-for-clones.md +295 -0
- package/squads/squad-cloning/knowledge-base/memory-architecture-for-clones.md +229 -0
- package/squads/squad-cloning/knowledge-base/multi-agent-deployment-patterns.md +320 -0
- package/squads/squad-cloning/knowledge-base/skill-standard-for-clones.md +262 -0
- package/squads/squad-cloning/knowledge-base/sop-extraction-guide.md +243 -0
- package/squads/squad-commercial/knowledge-base/account-based-selling.md +206 -0
- package/squads/squad-commercial/knowledge-base/ai-as-competitive-infrastructure.md +14 -0
- package/squads/squad-commercial/knowledge-base/ai-in-sales.md +199 -0
- package/squads/squad-commercial/knowledge-base/brazilian-sales-context.md +195 -0
- package/squads/squad-commercial/knowledge-base/customer-success-operations.md +83 -2
- package/squads/squad-commercial/knowledge-base/prospecting-pipeline-generation.md +69 -0
- package/squads/squad-commercial/knowledge-base/sales-enablement-playbook.md +260 -0
- package/squads/squad-commercial/knowledge-base/sales-methodology-comparison.md +185 -0
- package/squads/squad-commercial/knowledge-base/sales-revenue-master-reference.md +1123 -0
- package/squads/squad-content/knowledge-base/ai-native-content-loop.md +220 -0
- package/squads/squad-content/knowledge-base/brazilian-content-context.md +176 -0
- package/squads/squad-content/knowledge-base/competitor-analysis-methods.md +40 -1
- package/squads/squad-content/knowledge-base/content-architecture-taxonomy.md +206 -0
- package/squads/squad-content/knowledge-base/content-formats-encyclopedia.md +58 -1
- package/squads/squad-content/knowledge-base/content-references-bibliography.md +130 -0
- package/squads/squad-content/knowledge-base/content-strategy-master-reference.md +1097 -0
- package/squads/squad-content/knowledge-base/content-tech-stack.md +150 -0
- package/squads/squad-content/knowledge-base/copywriting-formulas-library.md +188 -0
- package/squads/squad-content/knowledge-base/email-newsletter-strategy.md +161 -0
- package/squads/squad-content/knowledge-base/platform-algorithm-intelligence.md +86 -1
- package/squads/squad-content/knowledge-base/signal-intelligence-v2.md +234 -0
- package/squads/squad-content/knowledge-base/social-algorithms-master-reference.md +1007 -0
- package/squads/squad-content/knowledge-base/task-ownership-map.md +235 -0
- package/squads/squad-content/knowledge-base/video-audio-content-playbook.md +218 -0
- package/squads/squad-content/squad.yaml +187 -27
- package/squads/squad-copy/knowledge-base/ai-copy-human-loop-canon.md +235 -0
- package/squads/squad-copy/knowledge-base/ai-copy-production.md +254 -0
- package/squads/squad-copy/knowledge-base/brazilian-copywriting-context.md +242 -0
- package/squads/squad-copy/knowledge-base/email-copywriting-system.md +299 -0
- package/squads/squad-copy/knowledge-base/landing-page-copy-architecture.md +267 -0
- package/squads/squad-copy/knowledge-base/power-words-catalog.md +205 -0
- package/squads/squad-copy/knowledge-base/seo-copywriting.md +255 -0
- package/squads/squad-copy/knowledge-base/video-script-copywriting.md +239 -0
- package/squads/squad-copy/squad.yaml +19 -4
- package/squads/squad-council/knowledge-base/brand-strategy-models.md +193 -0
- package/squads/squad-council/knowledge-base/growth-strategy-models.md +267 -0
- package/squads/squad-council/knowledge-base/innovation-disruption-frameworks.md +193 -0
- package/squads/squad-council/knowledge-base/market-analysis-frameworks.md +240 -0
- package/squads/squad-council/knowledge-base/organizational-leadership-models.md +212 -0
- package/squads/squad-council/knowledge-base/sales-strategy-models.md +215 -0
- package/squads/squad-courses/knowledge-base/course-launch-strategy.md +251 -0
- package/squads/squad-courses/knowledge-base/domain-advocacia-curriculum.md +385 -0
- package/squads/squad-courses/knowledge-base/domain-contabilidade-curriculum.md +266 -0
- package/squads/squad-courses/knowledge-base/platform-comparison.md +68 -0
- package/squads/squad-courses/knowledge-base/video-production-guide.md +70 -0
- package/squads/squad-cybersecurity/knowledge-base/cloud-security-reference.md +363 -0
- package/squads/squad-cybersecurity/knowledge-base/compliance-frameworks.md +273 -0
- package/squads/squad-cybersecurity/knowledge-base/database-security.md +438 -0
- package/squads/squad-cybersecurity/knowledge-base/incident-response-playbook.md +420 -0
- package/squads/squad-cybersecurity/knowledge-base/network-security-reference.md +477 -0
- package/squads/squad-cybersecurity/knowledge-base/penetration-testing-methodology.md +350 -0
- package/squads/squad-cybersecurity/knowledge-base/vulnerability-management.md +349 -0
- package/squads/squad-design/knowledge-base/brazilian-design-context.md +223 -0
- package/squads/squad-design/knowledge-base/component-api-patterns.md +208 -4
- package/squads/squad-design/knowledge-base/cross-surface-token-canon.md +209 -0
- package/squads/squad-design/knowledge-base/design-system-master-reference.md +1302 -0
- package/squads/squad-design/knowledge-base/design-systems-frameworks.md +91 -1
- package/squads/squad-design/knowledge-base/responsive-modern-css.md +96 -4
- package/squads/squad-design/knowledge-base/wcag-aria-reference.md +117 -5
- package/squads/squad-design/knowledge-base/web-performance-reference.md +127 -4
- package/squads/squad-design/squad.yaml +19 -4
- package/squads/squad-finance/knowledge-base/brazilian-taxation.md +263 -0
- package/squads/squad-finance/knowledge-base/contabilidade-master-reference.md +998 -0
- package/squads/squad-finance/knowledge-base/finance-master-reference.md +946 -0
- package/squads/squad-finance/knowledge-base/financial-reporting-analysis.md +316 -0
- package/squads/squad-finance/knowledge-base/fintech-brazilian-context.md +242 -0
- package/squads/squad-finance/knowledge-base/fpa-planning-frameworks.md +286 -0
- package/squads/squad-finance/knowledge-base/ma-and-transactions.md +285 -0
- package/squads/squad-finance/knowledge-base/risk-management.md +233 -0
- package/squads/squad-finance/knowledge-base/startups-venture-capital.md +337 -0
- package/squads/squad-growth/knowledge-base/ai-growth-playbook.md +216 -0
- package/squads/squad-growth/knowledge-base/attribution-models.md +78 -0
- package/squads/squad-growth/knowledge-base/brazilian-growth-context.md +208 -0
- package/squads/squad-growth/knowledge-base/community-led-growth.md +175 -0
- package/squads/squad-growth/knowledge-base/content-marketing-flywheel.md +190 -0
- package/squads/squad-growth/knowledge-base/email-lifecycle-framework.md +192 -0
- package/squads/squad-growth/knowledge-base/growth-frameworks-catalog.md +82 -0
- package/squads/squad-growth/knowledge-base/growth-master-reference.md +1168 -0
- package/squads/squad-growth/knowledge-base/routing-catalog.md +53 -11
- package/squads/squad-paidmedia/knowledge-base/audiences-segmentation-deep.md +285 -0
- package/squads/squad-paidmedia/knowledge-base/creative-strategy-deep.md +294 -0
- package/squads/squad-paidmedia/knowledge-base/google-ads-account-architecture.md +87 -0
- package/squads/squad-paidmedia/knowledge-base/meta-ads-campaign-architecture.md +76 -0
- package/squads/squad-paidmedia/knowledge-base/paid-media-metrics-reference.md +117 -0
- package/squads/squad-paidmedia/knowledge-base/paid-traffic-master-reference.md +1308 -0
- package/squads/squad-paidmedia/knowledge-base/routing-catalog.md +95 -18
- package/squads/squad-paidmedia/knowledge-base/traffic-masters-frameworks.md +71 -0
- package/squads/squad-product/knowledge-base/brazilian-product-context.md +284 -0
- package/squads/squad-product/knowledge-base/discovery-methodology-playbook.md +141 -0
- package/squads/squad-product/knowledge-base/pm-frameworks-reference.md +125 -9
- package/squads/squad-product/knowledge-base/product-analytics-formulas.md +72 -0
- package/squads/squad-product/knowledge-base/product-led-growth-reference.md +155 -13
- package/squads/squad-product/knowledge-base/product-market-fit-framework.md +222 -0
- package/squads/squad-product/knowledge-base/routing-catalog.md +32 -0
- package/squads/squad-research/knowledge-base/agentic-second-brain-reference.md +591 -0
- package/squads/squad-research/knowledge-base/ai-augmented-research.md +212 -0
- package/squads/squad-research/knowledge-base/brazilian-market-research-sources.md +197 -0
- package/squads/squad-research/knowledge-base/community-platforms-reference.md +786 -0
- package/squads/squad-research/knowledge-base/community-research-methods.md +194 -0
- package/squads/squad-research/knowledge-base/mixed-methods-research-design.md +168 -0
- package/squads/squad-research/knowledge-base/network-effects-analysis.md +192 -0
- package/squads/squad-research/knowledge-base/qualitative-research-deep-methods.md +202 -0
- package/squads/squad-research/knowledge-base/quantitative-research-methods.md +208 -0
- package/squads/squad-research/knowledge-base/research-frameworks-encyclopedia.md +40 -0
- package/squads/squad-research/knowledge-base/research-synthesis-frameworks.md +223 -0
- package/squads/squad-storytelling/knowledge-base/brand-mythology-framework.md +236 -0
- package/squads/squad-storytelling/knowledge-base/brazilian-storytelling-context.md +237 -0
- package/squads/squad-storytelling/knowledge-base/data-storytelling.md +232 -0
- package/squads/squad-storytelling/knowledge-base/improv-storytelling.md +226 -0
- package/squads/squad-storytelling/knowledge-base/persuasion-narrative-techniques.md +269 -0
- package/squads/squad-storytelling/knowledge-base/social-movement-narratives.md +191 -0
- package/squads/squad-storytelling/knowledge-base/video-storytelling.md +252 -0
- package/.sinapse-ai/core/registry/service-registry.json +0 -6346
- package/.sinapse-ai/data/registry-update-log.jsonl +0 -1307
- package/.sinapse-ai/manifests/agents.csv +0 -29
- package/.sinapse-ai/manifests/tasks.csv +0 -204
- package/.sinapse-ai/manifests/workers.csv +0 -196
- package/squads/claude-code-mastery/data/swarm-orchestration-patterns.yaml +0 -378
- package/squads/squad-animations/knowledge-base/framer-motion-complete-reference.md +0 -710
- package/squads/squad-animations/knowledge-base/web-animations-api-view-transitions.md +0 -478
- package/squads/squad-growth/tasks/calculate-sample-size.md +0 -121
- package/squads/squad-paidmedia/tasks/calculate-sample-size.md +0 -57
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* validate-no-external-refs.js
|
|
5
|
+
*
|
|
6
|
+
* Story 10.17 — Authorial Hygiene & Competitive Reference Guard.
|
|
7
|
+
*
|
|
8
|
+
* Scans the repository for any reference to a competing framework name and
|
|
9
|
+
* fails (exit 1) if any match is found outside an explicit allow-list.
|
|
10
|
+
*
|
|
11
|
+
* The guard keeps the SINAPSE codebase in a 100% authorial voice: the only
|
|
12
|
+
* places in the entire repo where competitive names may legally appear are
|
|
13
|
+
* the MIT `LICENSE` file (legal attribution requirement), the historical
|
|
14
|
+
* process document `docs/research-synthesis-for-upgrade.md`, and a small set
|
|
15
|
+
* of pre-existing upstream-attribution files inherited from the BMAD fork
|
|
16
|
+
* lineage (flagged for future per-file review — see follow-up backlog in
|
|
17
|
+
* `.sinapse-ai/internal/aiox-feature-map.md`).
|
|
18
|
+
*
|
|
19
|
+
* === Source of truth: `git ls-files` (QA v1.1 fix) ===
|
|
20
|
+
*
|
|
21
|
+
* The original implementation parsed `.gitignore` with a custom (naive)
|
|
22
|
+
* matcher. That matcher was too aggressive: because artifact-ignore rules
|
|
23
|
+
* (e.g. `.test.cache/`, `coverage/`) happened to match prefixes that also
|
|
24
|
+
* appeared inside legitimate tracked directories, entire trees like
|
|
25
|
+
* `squads/`, `tests/`, and `scripts/` were incorrectly pruned from the scan.
|
|
26
|
+
* Out of 4493 files tracked by git, the scanner only visited ~1623 (36 %)
|
|
27
|
+
* — which means it was silently blind to the real repo state and missed
|
|
28
|
+
* pre-existing upstream references that QA later caught by hand.
|
|
29
|
+
*
|
|
30
|
+
* The fix replaces the custom walker with a single call to `git ls-files`,
|
|
31
|
+
* which is the exact set of files that will be published to GitHub / npm.
|
|
32
|
+
* This is correct for three reasons:
|
|
33
|
+
*
|
|
34
|
+
* 1. Publishability — `git ls-files` is EXACTLY what ships. Any file we
|
|
35
|
+
* miss there cannot reach a user, so scanning it is meaningless.
|
|
36
|
+
* 2. Zero parser bugs — git does gitignore resolution natively; we don't
|
|
37
|
+
* need to approximate it.
|
|
38
|
+
* 3. Deterministic — no filesystem walk, no binary sniffing of files that
|
|
39
|
+
* aren't even tracked, no accidental inclusion of `node_modules/`.
|
|
40
|
+
*
|
|
41
|
+
* Behavior:
|
|
42
|
+
* - Shells out to `git ls-files` in `rootDir` to get the tracked set.
|
|
43
|
+
* - Skips the hardcoded allow-list paths.
|
|
44
|
+
* - Scans only text files (binary files and a small set of known-binary
|
|
45
|
+
* extensions are skipped).
|
|
46
|
+
* - Applies the regex `\b(aiox|synkra|synkraai|bmad)\b` (case-insensitive)
|
|
47
|
+
* line-by-line so the reporter can point at the exact file:line:match.
|
|
48
|
+
* - Returns a structured result for unit tests; the CLI wraps it.
|
|
49
|
+
*
|
|
50
|
+
* Output on violation (one block per match, matches AC 4 exactly):
|
|
51
|
+
*
|
|
52
|
+
* ❌ External reference detected
|
|
53
|
+
* File: <path>
|
|
54
|
+
* Line: <num>
|
|
55
|
+
* Match: <text>
|
|
56
|
+
*
|
|
57
|
+
* Fix: Remove the reference. This repo uses authorial SINAPSE voice only.
|
|
58
|
+
* Only LICENSE may contain these references (legal requirement).
|
|
59
|
+
*
|
|
60
|
+
* Usage:
|
|
61
|
+
* node scripts/validate-no-external-refs.js [--root <dir>]
|
|
62
|
+
*
|
|
63
|
+
* Exit codes:
|
|
64
|
+
* 0 = clean
|
|
65
|
+
* 1 = at least one violation
|
|
66
|
+
* 2 = usage / filesystem / git error
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
'use strict';
|
|
70
|
+
|
|
71
|
+
const fs = require('fs');
|
|
72
|
+
const path = require('path');
|
|
73
|
+
const { execSync } = require('child_process');
|
|
74
|
+
|
|
75
|
+
// ── Configuration ───────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Case-insensitive regex for any forbidden reference word. Uses `\b` to avoid
|
|
79
|
+
* matching inside longer identifiers (e.g., `sinapse-ai` must not hit even
|
|
80
|
+
* though it contains `ai`).
|
|
81
|
+
*/
|
|
82
|
+
const FORBIDDEN_REGEX = /\b(aiox|synkra|synkraai|bmad)\b/gi;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Hardcoded allow-list. Every entry is a POSIX-style path relative to the
|
|
86
|
+
* repo root. These paths are skipped by the scanner.
|
|
87
|
+
*
|
|
88
|
+
* - LICENSE: MIT attribution may legally require naming upstream authors.
|
|
89
|
+
* - docs/research-synthesis-for-upgrade.md: historical process document.
|
|
90
|
+
* - squads/claude-code-mastery/agents/skill-craftsman.md: PERMANENT.
|
|
91
|
+
* The agent's documented purpose is to study and adapt external
|
|
92
|
+
* agile-AI methodologies, so the references serve the framework
|
|
93
|
+
* rather than inheriting from a fork. Story 10.23 audited the file
|
|
94
|
+
* and decided to keep it allow-listed indefinitely.
|
|
95
|
+
*
|
|
96
|
+
* Each entry is an EXACT path match. Directory prefixes are NOT used — this
|
|
97
|
+
* forces future files under `squads/claude-code-mastery/` to be BLOCKED
|
|
98
|
+
* until they are explicitly added, which is what we want: a new file with a
|
|
99
|
+
* forbidden literal should fail the validator loudly.
|
|
100
|
+
*/
|
|
101
|
+
const HARDCODED_ALLOW_LIST = [
|
|
102
|
+
'LICENSE', // MIT legal requirement
|
|
103
|
+
'docs/research-synthesis-for-upgrade.md', // Historical process doc
|
|
104
|
+
|
|
105
|
+
// ── The validator itself + its tests ─────────────────────────────────
|
|
106
|
+
// These files MUST literally contain the forbidden strings: the script
|
|
107
|
+
// defines the regex that matches them, and the test suite builds fixtures
|
|
108
|
+
// that assert the regex catches each term. Without this exemption the
|
|
109
|
+
// validator would fail on its own source code.
|
|
110
|
+
'scripts/validate-no-external-refs.js',
|
|
111
|
+
'tests/scripts/validate-no-external-refs.test.js',
|
|
112
|
+
|
|
113
|
+
// ── PERMANENT: skill-craftsman methodology study ─────────────────────
|
|
114
|
+
// Story 10.23 audited the 6 pre-existing fork attribution files from
|
|
115
|
+
// Story 10.17. Five were rewritten in authorial voice and removed from
|
|
116
|
+
// the allow-list. This one stays: the agent's identity is built around
|
|
117
|
+
// studying external agile-AI methodologies and the references are
|
|
118
|
+
// load-bearing, not inherited noise.
|
|
119
|
+
'squads/claude-code-mastery/agents/skill-craftsman.md',
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* File extensions we treat as binary and never scan. A line-by-line regex
|
|
124
|
+
* scan on binary content is slow, noisy, and can produce false positives
|
|
125
|
+
* (e.g. a byte sequence that happens to spell a forbidden word).
|
|
126
|
+
*/
|
|
127
|
+
const BINARY_EXTENSIONS = new Set([
|
|
128
|
+
'.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico', '.bmp',
|
|
129
|
+
'.pdf', '.zip', '.tar', '.gz', '.tgz', '.7z', '.rar',
|
|
130
|
+
'.mp3', '.mp4', '.mov', '.avi', '.webm', '.ogg',
|
|
131
|
+
'.woff', '.woff2', '.ttf', '.otf', '.eot',
|
|
132
|
+
'.exe', '.dll', '.so', '.dylib',
|
|
133
|
+
'.lock', '.lockb',
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Maximum file size we scan (8 MB). Anything larger is almost certainly a
|
|
138
|
+
* binary blob or a generated artifact and is not worth the IO cost.
|
|
139
|
+
*/
|
|
140
|
+
const MAX_SCAN_BYTES = 8 * 1024 * 1024;
|
|
141
|
+
|
|
142
|
+
// ── Allow-list matching ─────────────────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Exact-match allow-list check. Directory prefixes are NOT supported by
|
|
146
|
+
* design: see the comment on HARDCODED_ALLOW_LIST.
|
|
147
|
+
*/
|
|
148
|
+
function isAllowListed(relPath) {
|
|
149
|
+
const normalized = relPath.replace(/\\/g, '/');
|
|
150
|
+
return HARDCODED_ALLOW_LIST.indexOf(normalized) !== -1;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ── File discovery ──────────────────────────────────────────────────────────
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Return the list of files tracked by git in `rootDir`, as POSIX-style
|
|
157
|
+
* relative paths. This is the exact set of files that will be published.
|
|
158
|
+
*
|
|
159
|
+
* We use `git ls-files -z` (null-delimited) so filenames with spaces or
|
|
160
|
+
* other special chars are handled correctly on Windows and Unix.
|
|
161
|
+
*
|
|
162
|
+
* @param {string} rootDir absolute path to a git repository root
|
|
163
|
+
* @returns {string[]}
|
|
164
|
+
* @throws if `git ls-files` cannot be run (no git, not a repo, etc.)
|
|
165
|
+
*/
|
|
166
|
+
function listTrackedFiles(rootDir) {
|
|
167
|
+
let raw;
|
|
168
|
+
try {
|
|
169
|
+
raw = execSync('git ls-files -z', {
|
|
170
|
+
cwd: rootDir,
|
|
171
|
+
encoding: 'utf8',
|
|
172
|
+
maxBuffer: 64 * 1024 * 1024, // 64 MB — plenty for any repo we care about
|
|
173
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
174
|
+
});
|
|
175
|
+
} catch (err) {
|
|
176
|
+
const msg = err && err.message ? err.message : String(err);
|
|
177
|
+
throw new Error(
|
|
178
|
+
'git ls-files failed in ' + rootDir + ': ' + msg +
|
|
179
|
+
'\n(The validator requires a git repository as its root.)',
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
// Split on NUL; drop the trailing empty entry that `-z` always leaves.
|
|
183
|
+
return raw
|
|
184
|
+
.split('\0')
|
|
185
|
+
.filter((entry) => entry.length > 0)
|
|
186
|
+
.map((entry) => entry.replace(/\\/g, '/'));
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ── Scanner ─────────────────────────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Detect whether a file is likely binary by checking its extension and a
|
|
193
|
+
* quick sniff of the first 4 KB for null bytes.
|
|
194
|
+
*/
|
|
195
|
+
function isBinaryFile(absPath) {
|
|
196
|
+
const ext = path.extname(absPath).toLowerCase();
|
|
197
|
+
if (BINARY_EXTENSIONS.has(ext)) return true;
|
|
198
|
+
try {
|
|
199
|
+
const fd = fs.openSync(absPath, 'r');
|
|
200
|
+
const buf = Buffer.alloc(4096);
|
|
201
|
+
const n = fs.readSync(fd, buf, 0, 4096, 0);
|
|
202
|
+
fs.closeSync(fd);
|
|
203
|
+
for (let i = 0; i < n; i++) {
|
|
204
|
+
if (buf[i] === 0) return true;
|
|
205
|
+
}
|
|
206
|
+
} catch {
|
|
207
|
+
return true; // unreadable → treat as binary
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Scan a single file. Returns an array of violation objects; empty if clean.
|
|
214
|
+
*/
|
|
215
|
+
function scanFile(rootDir, relPath) {
|
|
216
|
+
if (isAllowListed(relPath)) return [];
|
|
217
|
+
const absPath = path.join(rootDir, relPath);
|
|
218
|
+
let stat;
|
|
219
|
+
try {
|
|
220
|
+
stat = fs.statSync(absPath);
|
|
221
|
+
} catch {
|
|
222
|
+
return [];
|
|
223
|
+
}
|
|
224
|
+
if (!stat.isFile()) return [];
|
|
225
|
+
if (stat.size > MAX_SCAN_BYTES) return [];
|
|
226
|
+
if (isBinaryFile(absPath)) return [];
|
|
227
|
+
|
|
228
|
+
let content;
|
|
229
|
+
try {
|
|
230
|
+
content = fs.readFileSync(absPath, 'utf8');
|
|
231
|
+
} catch {
|
|
232
|
+
return [];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const lines = content.split(/\r?\n/);
|
|
236
|
+
const violations = [];
|
|
237
|
+
for (let i = 0; i < lines.length; i++) {
|
|
238
|
+
const line = lines[i];
|
|
239
|
+
// Reset regex state for each line; /g keeps lastIndex sticky.
|
|
240
|
+
FORBIDDEN_REGEX.lastIndex = 0;
|
|
241
|
+
let match;
|
|
242
|
+
while ((match = FORBIDDEN_REGEX.exec(line)) !== null) {
|
|
243
|
+
violations.push({
|
|
244
|
+
file: relPath,
|
|
245
|
+
line: i + 1,
|
|
246
|
+
match: match[0],
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return violations;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Public API: scan the repository rooted at `rootDir` and return
|
|
255
|
+
* { ok, scanned, violations }
|
|
256
|
+
*
|
|
257
|
+
* The function uses `git ls-files` to determine the scan set, so `rootDir`
|
|
258
|
+
* MUST be a git repository root (or a directory inside one). Tests should
|
|
259
|
+
* create a fixture with `git init` + `git add` to exercise this.
|
|
260
|
+
*
|
|
261
|
+
* @param {string} rootDir
|
|
262
|
+
* @returns {{ok: boolean, scanned: string[], violations: Array<{file: string, line: number, match: string}>}}
|
|
263
|
+
*/
|
|
264
|
+
function validateNoExternalRefs(rootDir) {
|
|
265
|
+
const files = listTrackedFiles(rootDir);
|
|
266
|
+
const violations = [];
|
|
267
|
+
for (const relPath of files) {
|
|
268
|
+
violations.push(...scanFile(rootDir, relPath));
|
|
269
|
+
}
|
|
270
|
+
return { ok: violations.length === 0, scanned: files, violations };
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// ── Reporter ────────────────────────────────────────────────────────────────
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Format a violation block exactly as AC 4 specifies.
|
|
277
|
+
*/
|
|
278
|
+
function formatViolation(v) {
|
|
279
|
+
return [
|
|
280
|
+
'❌ External reference detected',
|
|
281
|
+
'File: ' + v.file,
|
|
282
|
+
'Line: ' + v.line,
|
|
283
|
+
'Match: ' + v.match,
|
|
284
|
+
'',
|
|
285
|
+
'Fix: Remove the reference. This repo uses authorial SINAPSE voice only.',
|
|
286
|
+
'Only LICENSE may contain these references (legal requirement).',
|
|
287
|
+
'',
|
|
288
|
+
].join('\n');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function formatReport(result) {
|
|
292
|
+
if (result.ok) {
|
|
293
|
+
return (
|
|
294
|
+
'\n=== validate-no-external-refs ===\n' +
|
|
295
|
+
'Scanned ' + result.scanned.length + ' file(s).\n' +
|
|
296
|
+
'OK — no external references detected.\n\n'
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
const blocks = result.violations.map(formatViolation);
|
|
300
|
+
return (
|
|
301
|
+
'\n=== validate-no-external-refs ===\n' +
|
|
302
|
+
'Scanned ' + result.scanned.length + ' file(s).\n' +
|
|
303
|
+
'FAIL — ' + result.violations.length + ' external reference(s):\n\n' +
|
|
304
|
+
blocks.join('\n')
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// ── CLI entry point ─────────────────────────────────────────────────────────
|
|
309
|
+
|
|
310
|
+
function parseArgs(argv) {
|
|
311
|
+
const args = { root: process.cwd() };
|
|
312
|
+
for (let i = 0; i < argv.length; i++) {
|
|
313
|
+
const a = argv[i];
|
|
314
|
+
if (a === '--root' || a === '-r') {
|
|
315
|
+
args.root = argv[++i];
|
|
316
|
+
} else if (a === '--help' || a === '-h') {
|
|
317
|
+
args.help = true;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return args;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function printUsage() {
|
|
324
|
+
process.stdout.write(
|
|
325
|
+
[
|
|
326
|
+
'Usage: node scripts/validate-no-external-refs.js [--root <dir>]',
|
|
327
|
+
'',
|
|
328
|
+
'Scans the repo for any competitive framework reference and fails if',
|
|
329
|
+
'any match is found outside the hardcoded allow-list (LICENSE, historical',
|
|
330
|
+
'process doc, pre-existing upstream fork attribution). Uses `git ls-files`',
|
|
331
|
+
'as the source of truth so only publishable tracked files are scanned.',
|
|
332
|
+
'',
|
|
333
|
+
'Options:',
|
|
334
|
+
' --root, -r <dir> Root directory to scan (defaults to cwd).',
|
|
335
|
+
' --help, -h Show this help.',
|
|
336
|
+
'',
|
|
337
|
+
].join('\n'),
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function main() {
|
|
342
|
+
const args = parseArgs(process.argv.slice(2));
|
|
343
|
+
if (args.help) {
|
|
344
|
+
printUsage();
|
|
345
|
+
process.exit(0);
|
|
346
|
+
}
|
|
347
|
+
try {
|
|
348
|
+
const rootAbs = path.resolve(args.root);
|
|
349
|
+
if (!fs.existsSync(rootAbs)) {
|
|
350
|
+
process.stderr.write('error: root directory not found: ' + rootAbs + '\n');
|
|
351
|
+
process.exit(2);
|
|
352
|
+
}
|
|
353
|
+
const result = validateNoExternalRefs(rootAbs);
|
|
354
|
+
process.stdout.write(formatReport(result));
|
|
355
|
+
process.exit(result.ok ? 0 : 1);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
process.stderr.write('error: ' + (err && err.message ? err.message : err) + '\n');
|
|
358
|
+
process.exit(2);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Exports for unit testing.
|
|
363
|
+
module.exports = {
|
|
364
|
+
FORBIDDEN_REGEX,
|
|
365
|
+
HARDCODED_ALLOW_LIST,
|
|
366
|
+
isAllowListed,
|
|
367
|
+
listTrackedFiles,
|
|
368
|
+
scanFile,
|
|
369
|
+
validateNoExternalRefs,
|
|
370
|
+
formatViolation,
|
|
371
|
+
formatReport,
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
if (require.main === module) {
|
|
375
|
+
main();
|
|
376
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* validate-squad-orqx — Story 10.28
|
|
4
|
+
*
|
|
5
|
+
* Verifies that every squad under `squads/` exposes a reachable
|
|
6
|
+
* orchestrator agent (`*-orqx.md`) with the minimum required YAML
|
|
7
|
+
* metadata block. Companion to the existing scripts/validate-agents.js
|
|
8
|
+
* which validates the 12 core framework agents under
|
|
9
|
+
* `.sinapse-ai/development/agents/`.
|
|
10
|
+
*
|
|
11
|
+
* Checks per orqx file:
|
|
12
|
+
* 1. File exists at squads/{squad}/agents/{name}-orqx.md
|
|
13
|
+
* 2. Contains a YAML code block with `agent:` mapping
|
|
14
|
+
* 3. agent.name is a non-empty string
|
|
15
|
+
* 4. agent.id is a non-empty string and matches `{squad}/{name}-orqx`
|
|
16
|
+
* 5. agent.title is a non-empty string
|
|
17
|
+
* 6. persona.role exists
|
|
18
|
+
*
|
|
19
|
+
* Squad-level checks:
|
|
20
|
+
* - Every directory under squads/ that has agents/ MUST have at least
|
|
21
|
+
* one *-orqx.md file inside.
|
|
22
|
+
*
|
|
23
|
+
* Exit codes:
|
|
24
|
+
* 0 all squads have reachable orqx agents with valid metadata
|
|
25
|
+
* 1 any squad missing an orqx OR any orqx fails metadata checks
|
|
26
|
+
*
|
|
27
|
+
* Usage:
|
|
28
|
+
* node scripts/validate-squad-orqx.js
|
|
29
|
+
* node scripts/validate-squad-orqx.js --json
|
|
30
|
+
* node scripts/validate-squad-orqx.js --quiet
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
'use strict';
|
|
34
|
+
|
|
35
|
+
const fs = require('fs');
|
|
36
|
+
const path = require('path');
|
|
37
|
+
|
|
38
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
|
39
|
+
const SQUADS_DIR = path.join(PROJECT_ROOT, 'squads');
|
|
40
|
+
|
|
41
|
+
function parseArgs(argv = process.argv.slice(2)) {
|
|
42
|
+
const args = new Set(argv);
|
|
43
|
+
return {
|
|
44
|
+
quiet: args.has('--quiet') || args.has('-q'),
|
|
45
|
+
json: args.has('--json'),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function listSquads(squadsDir = SQUADS_DIR) {
|
|
50
|
+
if (!fs.existsSync(squadsDir)) return [];
|
|
51
|
+
return fs
|
|
52
|
+
.readdirSync(squadsDir, { withFileTypes: true })
|
|
53
|
+
.filter((d) => d.isDirectory())
|
|
54
|
+
.map((d) => d.name)
|
|
55
|
+
.sort();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function findOrqxFiles(squadName, squadsDir = SQUADS_DIR) {
|
|
59
|
+
const agentsDir = path.join(squadsDir, squadName, 'agents');
|
|
60
|
+
if (!fs.existsSync(agentsDir)) return [];
|
|
61
|
+
return fs
|
|
62
|
+
.readdirSync(agentsDir)
|
|
63
|
+
.filter((f) => f.endsWith('-orqx.md'))
|
|
64
|
+
.map((f) => path.join(agentsDir, f));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// parseOrqxFormat detects either of the two valid orqx file formats:
|
|
68
|
+
// 1. YAML block (`\`\`\`yaml ... \`\`\``) with agent: + persona: keys
|
|
69
|
+
// 2. Markdown headings (`# Agent: ...`, `## Identidade`, `## Role`)
|
|
70
|
+
// Returns { format, agent, persona } or null if neither shape recognized.
|
|
71
|
+
function parseOrqxFormat(content) {
|
|
72
|
+
// Format 0: YAML frontmatter (--- ... ---)
|
|
73
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
74
|
+
if (frontmatterMatch) {
|
|
75
|
+
const block = frontmatterMatch[1];
|
|
76
|
+
const data = { format: 'frontmatter', agent: {}, persona: {} };
|
|
77
|
+
const nameMatch = block.match(/^name:\s*"?([^"\n]+?)"?\s*$/m);
|
|
78
|
+
if (nameMatch) {
|
|
79
|
+
data.agent.id = nameMatch[1].trim();
|
|
80
|
+
data.agent.name = nameMatch[1].trim();
|
|
81
|
+
}
|
|
82
|
+
const descMatch = block.match(/^description:\s*\|?\s*\n((?:\s{2}.+\n?)+)/);
|
|
83
|
+
if (descMatch) {
|
|
84
|
+
data.agent.title = descMatch[1].trim().split('\n')[0].trim();
|
|
85
|
+
data.persona.role = descMatch[1].trim().split('\n')[0].trim();
|
|
86
|
+
} else {
|
|
87
|
+
const inlineDescMatch = block.match(/^description:\s*(.+)$/m);
|
|
88
|
+
if (inlineDescMatch) {
|
|
89
|
+
data.agent.title = inlineDescMatch[1].trim();
|
|
90
|
+
data.persona.role = inlineDescMatch[1].trim();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (Object.keys(data.agent).length > 0) return data;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const yamlMatch = content.match(/```yaml\n([\s\S]*?)\n```/);
|
|
97
|
+
if (yamlMatch) {
|
|
98
|
+
const block = yamlMatch[1];
|
|
99
|
+
const data = { format: 'yaml', agent: {}, persona: {} };
|
|
100
|
+
const agentMatch = block.match(/agent:\s*\n((?:\s{2}.+\n?)+)/);
|
|
101
|
+
if (agentMatch) {
|
|
102
|
+
const lines = agentMatch[1].split('\n');
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
const m = line.match(/^\s{2}(\w+):\s*"?([^"\n]+?)"?\s*$/);
|
|
105
|
+
if (m) data.agent[m[1]] = m[2];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const roleMatch = block.match(/persona:[\s\S]*?role:\s*"?([^"\n]+?)"?$/m);
|
|
109
|
+
if (roleMatch) data.persona.role = roleMatch[1].trim();
|
|
110
|
+
// Fall through to markdown branch if YAML extraction yielded nothing.
|
|
111
|
+
if (Object.keys(data.agent).length > 0) return data;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Markdown-headings format (squad-design and friends)
|
|
115
|
+
if (/^#\s+Agent:\s/m.test(content) || /\*\*ID:\*\*/.test(content)) {
|
|
116
|
+
const data = { format: 'markdown', agent: {}, persona: {} };
|
|
117
|
+
const titleMatch = content.match(/^#\s+(?:Agent:\s+)?(.+?)$/m);
|
|
118
|
+
if (titleMatch) data.agent.title = titleMatch[1].trim();
|
|
119
|
+
|
|
120
|
+
const idMatch = content.match(/\*\*ID:\*\*\s*`?([^\s`]+)`?/);
|
|
121
|
+
if (idMatch) data.agent.id = idMatch[1].trim();
|
|
122
|
+
|
|
123
|
+
const nameMatch = content.match(/\*\*Nome:\*\*\s*([^\n]+)/);
|
|
124
|
+
if (nameMatch) data.agent.name = nameMatch[1].trim();
|
|
125
|
+
|
|
126
|
+
const roleHeadingMatch = content.match(/^##\s+Role\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
|
|
127
|
+
if (roleHeadingMatch) data.persona.role = roleHeadingMatch[1].trim().split('\n')[0];
|
|
128
|
+
|
|
129
|
+
return data;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Table-based identity format (squad-claude orqx files)
|
|
133
|
+
if (/\*\*Agent ID\*\*/.test(content) || /\*\*Name\*\*\s*\|/.test(content)) {
|
|
134
|
+
const data = { format: 'markdown-table', agent: {}, persona: {} };
|
|
135
|
+
const titleMatch = content.match(/^#\s+(.+?)$/m);
|
|
136
|
+
if (titleMatch) data.agent.title = titleMatch[1].trim();
|
|
137
|
+
|
|
138
|
+
const nameMatch = content.match(/\*\*Name\*\*\s*\|\s*([^|\n]+)/);
|
|
139
|
+
if (nameMatch) data.agent.name = nameMatch[1].trim();
|
|
140
|
+
|
|
141
|
+
const idMatch = content.match(/\*\*Agent ID\*\*\s*\|\s*`?@?([^|`\n]+?)`?\s*\|/);
|
|
142
|
+
if (idMatch) data.agent.id = idMatch[1].trim();
|
|
143
|
+
|
|
144
|
+
const roleHeadingMatch = content.match(/^##\s+Role\s*\n+([\s\S]+?)(?:\n##|\n$)/m);
|
|
145
|
+
if (roleHeadingMatch) data.persona.role = roleHeadingMatch[1].trim().split('\n')[0];
|
|
146
|
+
|
|
147
|
+
return data;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function validateOrqxFile(filePath) {
|
|
154
|
+
const findings = [];
|
|
155
|
+
const fileName = path.basename(filePath);
|
|
156
|
+
const relPath = path.relative(PROJECT_ROOT, filePath).replace(/\\/g, '/');
|
|
157
|
+
const squadName = relPath.split('/')[1];
|
|
158
|
+
const expectedId = `${squadName}/${fileName.replace('.md', '')}`;
|
|
159
|
+
|
|
160
|
+
let content;
|
|
161
|
+
try {
|
|
162
|
+
content = fs.readFileSync(filePath, 'utf8');
|
|
163
|
+
} catch (err) {
|
|
164
|
+
findings.push({ level: 'error', rule: 'read', message: `cannot read: ${err.message}` });
|
|
165
|
+
return findings;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const data = parseOrqxFormat(content);
|
|
169
|
+
if (!data) {
|
|
170
|
+
findings.push({
|
|
171
|
+
level: 'error',
|
|
172
|
+
rule: 'unrecognized-format',
|
|
173
|
+
message: 'no YAML block and no Markdown identity heading found',
|
|
174
|
+
});
|
|
175
|
+
return findings;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// At least one of name/id/title must be present so the agent is reachable.
|
|
179
|
+
const hasIdentity = Boolean(data.agent.name || data.agent.id || data.agent.title);
|
|
180
|
+
if (!hasIdentity) {
|
|
181
|
+
findings.push({
|
|
182
|
+
level: 'error',
|
|
183
|
+
rule: 'agent-identity',
|
|
184
|
+
message: 'no agent.name / agent.id / agent.title found in either format',
|
|
185
|
+
});
|
|
186
|
+
return findings;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ID match is a soft check — Markdown format often uses bare ID like
|
|
190
|
+
// "design-orqx" without the squad prefix. Warn but don't error.
|
|
191
|
+
if (data.agent.id && data.agent.id !== expectedId) {
|
|
192
|
+
const fileBaseId = path.basename(filePath, '.md');
|
|
193
|
+
if (data.agent.id !== fileBaseId) {
|
|
194
|
+
findings.push({
|
|
195
|
+
level: 'warn',
|
|
196
|
+
rule: 'id-mismatch',
|
|
197
|
+
message: `agent.id="${data.agent.id}" does not match "${expectedId}" or "${fileBaseId}"`,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (!data.persona || !data.persona.role) {
|
|
203
|
+
findings.push({
|
|
204
|
+
level: 'warn',
|
|
205
|
+
rule: 'persona-role',
|
|
206
|
+
message: 'persona.role / Role section is missing',
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return findings;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function validateAllSquads(squadsDir = SQUADS_DIR) {
|
|
214
|
+
const squads = listSquads(squadsDir);
|
|
215
|
+
const results = [];
|
|
216
|
+
for (const squad of squads) {
|
|
217
|
+
const orqxFiles = findOrqxFiles(squad, squadsDir);
|
|
218
|
+
if (orqxFiles.length === 0) {
|
|
219
|
+
// Some squad directories don't have agents/ at all (legacy/utility),
|
|
220
|
+
// skip those silently. Only flag as ERROR if agents/ exists but no orqx.
|
|
221
|
+
const agentsDir = path.join(squadsDir, squad, 'agents');
|
|
222
|
+
if (fs.existsSync(agentsDir)) {
|
|
223
|
+
results.push({
|
|
224
|
+
squad,
|
|
225
|
+
orqxFiles: [],
|
|
226
|
+
findings: [
|
|
227
|
+
{ level: 'error', rule: 'no-orqx', message: 'squad has agents/ but no *-orqx.md' },
|
|
228
|
+
],
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
for (const filePath of orqxFiles) {
|
|
234
|
+
results.push({ squad, orqxFile: filePath, findings: validateOrqxFile(filePath) });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return results;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function summarize(results) {
|
|
241
|
+
const summary = { total: results.length, pass: 0, warn: 0, error: 0 };
|
|
242
|
+
for (const r of results) {
|
|
243
|
+
const hasError = r.findings.some((f) => f.level === 'error');
|
|
244
|
+
const hasWarn = r.findings.some((f) => f.level === 'warn');
|
|
245
|
+
if (hasError) summary.error += 1;
|
|
246
|
+
else if (hasWarn) summary.warn += 1;
|
|
247
|
+
else summary.pass += 1;
|
|
248
|
+
}
|
|
249
|
+
return summary;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function formatReport(results, summary) {
|
|
253
|
+
const lines = [];
|
|
254
|
+
for (const r of results) {
|
|
255
|
+
const tag = r.findings.some((f) => f.level === 'error')
|
|
256
|
+
? 'ERROR'
|
|
257
|
+
: r.findings.some((f) => f.level === 'warn')
|
|
258
|
+
? 'WARN '
|
|
259
|
+
: 'PASS ';
|
|
260
|
+
const label = r.orqxFile ? path.relative(PROJECT_ROOT, r.orqxFile).replace(/\\/g, '/') : `${r.squad} (no orqx)`;
|
|
261
|
+
lines.push(`${tag} ${label}`);
|
|
262
|
+
for (const f of r.findings) {
|
|
263
|
+
lines.push(` [${f.level}] ${f.rule}: ${f.message}`);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
lines.push('');
|
|
267
|
+
lines.push(
|
|
268
|
+
`Summary: ${summary.total} orqx file(s) — ${summary.pass} pass, ${summary.warn} warn, ${summary.error} error`,
|
|
269
|
+
);
|
|
270
|
+
return lines.join('\n');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function main() {
|
|
274
|
+
const args = parseArgs();
|
|
275
|
+
const results = validateAllSquads();
|
|
276
|
+
const summary = summarize(results);
|
|
277
|
+
|
|
278
|
+
if (args.json) {
|
|
279
|
+
console.log(JSON.stringify({ results, summary }, null, 2));
|
|
280
|
+
} else if (!args.quiet) {
|
|
281
|
+
console.log('=== validate-squad-orqx ===');
|
|
282
|
+
console.log(formatReport(results, summary));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return summary.error > 0 ? 1 : 0;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (require.main === module) {
|
|
289
|
+
process.exitCode = main();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
module.exports = {
|
|
293
|
+
parseArgs,
|
|
294
|
+
listSquads,
|
|
295
|
+
findOrqxFiles,
|
|
296
|
+
parseOrqxFormat,
|
|
297
|
+
validateOrqxFile,
|
|
298
|
+
validateAllSquads,
|
|
299
|
+
summarize,
|
|
300
|
+
formatReport,
|
|
301
|
+
main,
|
|
302
|
+
};
|