sinapse-ai 1.7.0 → 1.9.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 +5 -11
- package/.claude/hooks/README.md +14 -1
- package/.claude/hooks/code-intel-pretool.cjs +115 -0
- package/.claude/hooks/enforce-delegation.cjs +31 -3
- package/.claude/hooks/enforce-framework-boundary.cjs +324 -0
- package/.claude/hooks/enforce-permission-mode.cjs +249 -0
- package/.claude/hooks/mind-clone-governance.py +212 -212
- package/.claude/hooks/read-protection.py +152 -152
- package/.claude/hooks/secret-scanning.cjs +34 -43
- package/.claude/hooks/slug-validation.py +175 -175
- package/.claude/hooks/sql-governance.py +183 -183
- package/.claude/hooks/synapse-engine.cjs +23 -23
- package/.claude/hooks/telemetry-post-tool.cjs +128 -0
- package/.claude/hooks/telemetry-stop.cjs +132 -0
- package/.claude/hooks/verify-packages.cjs +9 -2
- package/.claude/rules/documentation-first.md +1 -1
- package/.claude/rules/hook-governance.md +3 -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 +373 -838
- package/.codex/delegation-parity.json +657 -0
- package/.codex/handoff-packet.parity.schema.json +148 -0
- package/.codex/handoff-packet.template.json +26 -0
- package/.codex/instructions.md +6 -6
- 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/cli/commands/health/index.js +24 -0
- package/.sinapse-ai/constitution.md +5 -5
- package/.sinapse-ai/core/README.md +11 -0
- package/.sinapse-ai/core/config/config-loader.js +19 -0
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +97 -19
- package/.sinapse-ai/core/events/dashboard-emitter.js +30 -9
- package/.sinapse-ai/core/execution/build-orchestrator.js +4 -1
- package/.sinapse-ai/core/execution/parallel-executor.js +7 -1
- package/.sinapse-ai/core/execution/subagent-dispatcher.js +126 -28
- package/.sinapse-ai/core/execution/wave-executor.js +4 -1
- package/.sinapse-ai/core/grounding/README.md +71 -11
- package/.sinapse-ai/core/health-check/checks/project/framework-config.js +38 -2
- package/.sinapse-ai/core/health-check/checks/project/package-json.js +47 -3
- package/.sinapse-ai/core/health-check/checks/services/gemini-cli.js +117 -0
- package/.sinapse-ai/core/health-check/checks/services/index.js +2 -0
- package/.sinapse-ai/core/health-check/healers/index.js +40 -3
- package/.sinapse-ai/core/ideation/ideation-engine.js +170 -121
- package/.sinapse-ai/core/ids/gate-evaluator.js +318 -0
- package/.sinapse-ai/core/ids/gates/g5-semantic-handshake.js +190 -0
- package/.sinapse-ai/core/ids/gates/g6-ci-integrity.js +162 -0
- package/.sinapse-ai/core/ids/index.js +30 -0
- package/.sinapse-ai/core/memory/__tests__/active-modules.verify.js +11 -0
- package/.sinapse-ai/core/orchestration/agent-invoker.js +29 -6
- package/.sinapse-ai/core/orchestration/brownfield-handler.js +36 -3
- package/.sinapse-ai/core/orchestration/executors/epic-3-executor.js +76 -5
- package/.sinapse-ai/core/orchestration/executors/epic-4-executor.js +63 -17
- package/.sinapse-ai/core/orchestration/executors/epic-6-executor.js +153 -41
- package/.sinapse-ai/core/orchestration/executors/epic-executor.js +40 -0
- package/.sinapse-ai/core/orchestration/greenfield-handler.js +87 -3
- package/.sinapse-ai/core/orchestration/master-orchestrator.js +105 -7
- package/.sinapse-ai/core/orchestration/parallel-executor.js +6 -1
- package/.sinapse-ai/core/orchestration/workflow-executor.js +41 -0
- package/.sinapse-ai/core/registry/squad-agent-resolver.js +253 -0
- package/.sinapse-ai/core/telemetry/ids-sink.js +188 -0
- package/.sinapse-ai/core/ui/observability-panel.js +240 -0
- package/.sinapse-ai/core/utils/output-formatter.js +8 -290
- package/.sinapse-ai/core-config.yaml +29 -1
- package/.sinapse-ai/data/entity-registry.yaml +15056 -13761
- package/.sinapse-ai/development/agents/developer.md +2 -0
- package/.sinapse-ai/development/agents/devops.md +9 -0
- package/.sinapse-ai/development/agents/snps-orqx.md +12 -22
- package/.sinapse-ai/development/external-executors/README.md +18 -0
- package/.sinapse-ai/development/external-executors/codex.md +56 -0
- package/.sinapse-ai/development/scripts/populate-entity-registry.js +65 -9
- package/.sinapse-ai/development/scripts/squad/squad-downloader.js +54 -11
- 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/delegate-to-external-executor.md +152 -0
- package/.sinapse-ai/development/tasks/github-devops-pre-push-quality-gate.md +46 -29
- 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/update-sinapse.md +3 -3
- 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 +283 -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 +77 -0
- package/.sinapse-ai/hooks/ids-post-commit.js +13 -11
- package/.sinapse-ai/hooks/ids-pre-push.js +9 -7
- package/.sinapse-ai/hooks/sinapse-brand-grounding.cjs +4 -7
- package/.sinapse-ai/hooks/sinapse-ds-grounding.cjs +4 -7
- package/.sinapse-ai/hooks/sinapse-vault-grounding.cjs +4 -7
- package/.sinapse-ai/infrastructure/integrations/ai-providers/ai-provider-factory.js +4 -1
- package/.sinapse-ai/infrastructure/integrations/ai-providers/claude-provider.js +57 -55
- 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 +139 -21
- package/.sinapse-ai/infrastructure/scripts/ide-sync/persona-renderer.js +97 -0
- 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 +239 -223
- 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/.sinapse-ai/scripts/pm.sh +18 -6
- package/AGENTS.md +193 -0
- package/LICENSE +63 -63
- package/README.en.md +17 -18
- package/README.md +18 -19
- package/bin/cli.js +18 -1
- package/bin/commands/agents.js +96 -0
- package/bin/commands/doctor.js +15 -0
- package/bin/commands/ideate.js +129 -0
- package/bin/commands/install.js +194 -22
- package/bin/commands/status.js +14 -1
- package/bin/commands/uninstall.js +40 -0
- package/bin/commands/update.js +52 -0
- package/bin/lib/setup-statusline.js +191 -0
- package/bin/postinstall.js +50 -4
- package/bin/sinapse-init.js +11 -83
- package/bin/sinapse.js +146 -2
- package/bin/utils/framework-guard.js +17 -4
- package/bin/utils/secret-scanner-core.js +283 -0
- package/bin/utils/staged-secret-scan.js +106 -40
- package/bin/utils/staged-sql-guard.js +204 -0
- package/bin/utils/validate-publish.js +63 -0
- package/docs/agent-reference-guide.md +4 -6
- package/docs/framework/agent-prefix-convention.md +58 -0
- package/docs/framework/collaboration-activation.md +45 -0
- package/docs/security/overview.md +1 -1
- package/package.json +16 -8
- package/packages/installer/src/index.js +26 -0
- package/packages/installer/src/installer/git-hooks-installer.js +546 -0
- package/packages/installer/src/installer/sinapse-ai-installer.js +87 -0
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +40 -25
- package/packages/installer/src/wizard/index.js +50 -0
- package/packages/installer/src/wizard/validators.js +38 -1
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +24 -1
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +42 -3
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +10 -4
- package/packages/installer/tests/unit/git-hooks-installer.test.js +262 -0
- 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/eval-runner.js +422 -0
- package/scripts/generate-install-manifest.js +13 -9
- package/scripts/generate-synapse-runtime.js +51 -0
- package/scripts/prepare-hooks.js +58 -0
- package/scripts/regenerate-orqx-stubs.ps1 +2 -2
- package/scripts/validate-agents-md.js +128 -0
- package/scripts/validate-all.js +2 -0
- package/scripts/validate-evals.js +466 -0
- package/scripts/validate-schemas.js +539 -0
- package/scripts/validate-squad-orqx.js +9 -2
- package/sinapse/agents/sinapse-orqx.md +12 -22
- package/sinapse/agents/snps-orqx.md +11 -21
- package/squads/claude-code-mastery/squad.yaml +8 -0
- package/squads/squad-animations/squad.yaml +1 -1
- package/squads/squad-brand/squad.yaml +1 -1
- package/squads/squad-cloning/squad.yaml +1 -1
- package/squads/squad-commercial/squad.yaml +2 -3
- package/squads/squad-content/squad.yaml +1 -1
- package/squads/squad-copy/squad.yaml +2 -3
- package/squads/squad-courses/squad.yaml +1 -1
- package/squads/squad-cybersecurity/squad.yaml +2 -3
- 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/squad.yaml +7 -1
- package/squads/squad-growth/squad.yaml +1 -1
- package/squads/squad-paidmedia/squad.yaml +2 -3
- package/squads/squad-product/squad.yaml +1 -1
- package/squads/squad-research/squad.yaml +2 -3
- 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/data/registry-update-log.jsonl +0 -72
- package/.sinapse-ai/development/scripts/elicitation-engine.js +0 -385
- package/.sinapse-ai/development/scripts/elicitation-session-manager.js +0 -300
- package/.sinapse-ai/development/tasks/test-validation-task.md +0 -172
- 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/bin/sinapse-graph.js +0 -19
- package/docs/codex-integration-process.md +0 -22
- package/docs/codex-parity-program.md +0 -27
- 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
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Staged Secret Scan — git pre-commit guard.
|
|
5
|
+
*
|
|
6
|
+
* Reads EXCLUSIVELY the staged blob of each changed file (`git show :<path>`),
|
|
7
|
+
* so only what is actually being committed is measured (the working-tree copy,
|
|
8
|
+
* which may differ, is never read — no stash dance required).
|
|
9
|
+
*
|
|
10
|
+
* Detection is delegated to the shared core (`secret-scanner-core.js`):
|
|
11
|
+
* - all 20+ named patterns
|
|
12
|
+
* - Shannon-entropy backstop for unnamed high-entropy tokens
|
|
13
|
+
* - placeholder allowlist (.env.example values, your-key-here, CHANGEME, …)
|
|
14
|
+
* - lockfile-hash context allowlist
|
|
15
|
+
* - redacted output (secrets never printed in full)
|
|
16
|
+
*
|
|
17
|
+
* fail-CLOSED: if the scanner cannot run (load error, git error mid-scan), the
|
|
18
|
+
* commit is BLOCKED (exit 1) rather than silently allowed.
|
|
19
|
+
*
|
|
20
|
+
* @module bin/utils/staged-secret-scan
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const path = require('path');
|
|
24
|
+
const { execFileSync, execSync } = require('child_process');
|
|
25
|
+
|
|
26
|
+
let core;
|
|
27
|
+
try {
|
|
28
|
+
core = require(path.join(__dirname, 'secret-scanner-core.js'));
|
|
29
|
+
} catch (err) {
|
|
30
|
+
// fail-CLOSED: the scanner itself is broken — refuse to let a commit through
|
|
31
|
+
// unscanned.
|
|
32
|
+
process.stderr.write('\nStaged Secret Scan: scanner failed to load — commit blocked (fail-closed).\n');
|
|
33
|
+
process.stderr.write(String(err && err.message ? err.message : err) + '\n');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { scanContent, redactMatch } = core;
|
|
38
|
+
|
|
39
|
+
const BLOCKED_ENV_FILE_PATTERN = /(^|\/)\.env(\..+)?$/i;
|
|
40
|
+
const SAFE_ENV_FILE_PATTERN = /(^|\/)\.env\.(example|sample|template)$/i;
|
|
41
|
+
|
|
42
|
+
// Files that legitimately carry secret-shaped strings by design:
|
|
43
|
+
// - the scanner's own source (named-pattern regexes embed token shapes like
|
|
44
|
+
// the JWT header), which would otherwise self-trip the entropy backstop;
|
|
45
|
+
// - any test/spec file (intentional fixtures that prove detection works).
|
|
46
|
+
// These are PATH-exempt so the guard never blocks committing the guard itself
|
|
47
|
+
// or its tests. All production code paths remain fully scanned.
|
|
48
|
+
const SCANNER_SELF_FILES = new Set([
|
|
49
|
+
'bin/utils/secret-scanner-core.js',
|
|
50
|
+
'bin/utils/staged-secret-scan.js',
|
|
51
|
+
'.claude/hooks/secret-scanning.cjs',
|
|
52
|
+
]);
|
|
53
|
+
const TEST_FILE_PATTERN = /(^|\/)(tests?|__tests__)\/|\.(test|spec)\.[cm]?[jt]s$/i;
|
|
54
|
+
|
|
55
|
+
function isScanExemptPath(filePath) {
|
|
56
|
+
const norm = String(filePath).replace(/\\/g, '/');
|
|
57
|
+
return SCANNER_SELF_FILES.has(norm) || TEST_FILE_PATTERN.test(norm);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Back-compat shim: the previous public API exposed { SECRET_PATTERNS,
|
|
62
|
+
* findSecretMatches }. They now resolve through the shared core so any external
|
|
63
|
+
* importer keeps working while gaining the hardened detection.
|
|
64
|
+
*/
|
|
65
|
+
const SECRET_PATTERNS = core.NAMED_PATTERNS.map((p) => ({ label: p.name, pattern: p.pattern }));
|
|
66
|
+
|
|
67
|
+
function findSecretMatches(content, filePath) {
|
|
68
|
+
return scanContent(content, { filePath: filePath || '' }).map((f) => f.name);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getStagedFiles() {
|
|
72
|
+
try {
|
|
73
|
+
const output = execSync('git diff --cached --name-only --diff-filter=ACMR', {
|
|
74
|
+
encoding: 'utf8',
|
|
75
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
76
|
+
}).trim();
|
|
77
|
+
return output ? output.split('\n').filter(Boolean) : [];
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isBlockedEnvFile(filePath) {
|
|
84
|
+
return BLOCKED_ENV_FILE_PATTERN.test(filePath) && !SAFE_ENV_FILE_PATTERN.test(filePath);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function readStagedFile(filePath) {
|
|
88
|
+
// Throws on failure so the caller can fail-CLOSED instead of scanning "".
|
|
89
|
+
return execFileSync('git', ['show', `:${filePath}`], {
|
|
90
|
+
encoding: 'utf8',
|
|
91
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
92
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function scanStagedFiles(files) {
|
|
97
|
+
const findings = [];
|
|
98
|
+
|
|
99
|
+
for (const filePath of files) {
|
|
100
|
+
// A non-safe .env file is blocked outright (its values are real by design).
|
|
101
|
+
if (isBlockedEnvFile(filePath)) {
|
|
102
|
+
findings.push({ filePath, reason: 'environment file (use .env.example with placeholders)', redacted: null });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Skip the scanner's own source + any test/spec file (intentional fixtures).
|
|
107
|
+
if (isScanExemptPath(filePath)) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
let content;
|
|
112
|
+
try {
|
|
113
|
+
content = readStagedFile(filePath);
|
|
114
|
+
} catch {
|
|
115
|
+
// Could not read the staged blob (binary, deleted-then-readded race, etc.)
|
|
116
|
+
// — skip silently; binary/secret content of unreadable blobs is rare and
|
|
117
|
+
// the named .env rule above already covers the common dotfile leak.
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const matches = scanContent(content, { filePath });
|
|
122
|
+
for (const match of matches) {
|
|
123
|
+
findings.push({ filePath, reason: match.name, redacted: match.redacted, entropy: match.entropy });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return findings;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function main() {
|
|
131
|
+
let stagedFiles;
|
|
132
|
+
let findings;
|
|
133
|
+
try {
|
|
134
|
+
stagedFiles = getStagedFiles();
|
|
135
|
+
if (stagedFiles.length === 0) {
|
|
136
|
+
process.exit(0);
|
|
137
|
+
}
|
|
138
|
+
findings = scanStagedFiles(stagedFiles);
|
|
139
|
+
} catch (err) {
|
|
140
|
+
// fail-CLOSED on any unexpected scanner error.
|
|
141
|
+
console.error('');
|
|
142
|
+
console.error('Staged Secret Scan: unexpected error — commit blocked (fail-closed).');
|
|
143
|
+
console.error(String(err && err.message ? err.message : err));
|
|
144
|
+
console.error('');
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (findings.length === 0) {
|
|
149
|
+
process.exit(0);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
console.error('');
|
|
153
|
+
console.error('Staged Secret Scan: commit blocked.');
|
|
154
|
+
console.error('');
|
|
155
|
+
for (const finding of findings) {
|
|
156
|
+
const sample = finding.redacted ? ` [${finding.redacted}]` : '';
|
|
157
|
+
const ent = finding.entropy ? ` (entropy ${finding.entropy})` : '';
|
|
158
|
+
console.error(`- ${finding.filePath}: ${finding.reason}${sample}${ent}`);
|
|
159
|
+
}
|
|
160
|
+
console.error('');
|
|
161
|
+
console.error('Remove the sensitive content before committing.');
|
|
162
|
+
console.error('Use .env (gitignored) for local dev and .env.example with placeholders for templates.');
|
|
163
|
+
console.error('');
|
|
164
|
+
process.exit(1);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
module.exports = {
|
|
168
|
+
SECRET_PATTERNS,
|
|
169
|
+
findSecretMatches,
|
|
170
|
+
getStagedFiles,
|
|
171
|
+
isBlockedEnvFile,
|
|
172
|
+
isScanExemptPath,
|
|
173
|
+
scanStagedFiles,
|
|
174
|
+
redactMatch,
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
if (require.main === module) {
|
|
178
|
+
main();
|
|
179
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Staged SQL Guard — git pre-commit guard for destructive DDL/DML.
|
|
5
|
+
*
|
|
6
|
+
* Ports the DANGEROUS_PATTERNS from `.claude/hooks/sql-governance.py` (which is
|
|
7
|
+
* IDE-bound: it only fires on Claude Code Bash tool calls) into an IDE-agnostic
|
|
8
|
+
* Node guard that runs at the git layer. It scans the STAGED blob of every
|
|
9
|
+
* changed `.sql` / migration-bearing file and BLOCKS the commit (exit 1) if it
|
|
10
|
+
* finds destructive schema/data operations:
|
|
11
|
+
*
|
|
12
|
+
* - DROP TABLE/VIEW/FUNCTION/TRIGGER/INDEX/SCHEMA/POLICY
|
|
13
|
+
* - TRUNCATE
|
|
14
|
+
* - DELETE ... (without a WHERE clause)
|
|
15
|
+
* - CREATE TABLE ... AS SELECT (disallowed backup pattern)
|
|
16
|
+
*
|
|
17
|
+
* Scope decision: this guard targets the genuinely IRREVERSIBLE / data-loss
|
|
18
|
+
* operations (the same ones a destructive migration would carry). Plain
|
|
19
|
+
* CREATE/ALTER are intentionally NOT blocked at the git layer — they are the
|
|
20
|
+
* normal content of forward migrations and blocking them would make every
|
|
21
|
+
* legitimate schema change require `--no-verify`. The Claude-Code-level
|
|
22
|
+
* sql-governance.py still gates CREATE/ALTER at authoring time interactively.
|
|
23
|
+
*
|
|
24
|
+
* Only `.sql` files and files under a `migrations/` path are scanned, so SQL
|
|
25
|
+
* embedded in prose/docs or string literals in application code does not trip
|
|
26
|
+
* the guard. SQL comments (line and block) are stripped before matching.
|
|
27
|
+
*
|
|
28
|
+
* fail-CLOSED on scanner error (a broken guard must never silently pass
|
|
29
|
+
* destructive SQL). fail-OPEN only when there is genuinely nothing to scan.
|
|
30
|
+
*
|
|
31
|
+
* @module bin/utils/staged-sql-guard
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const { execFileSync, execSync } = require('child_process');
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Destructive patterns. Mirrors the irreversible subset of
|
|
38
|
+
* sql-governance.py DANGEROUS_PATTERNS. Each entry: [regex, humanLabel].
|
|
39
|
+
* Regexes are case-insensitive and operate on comment-stripped SQL text.
|
|
40
|
+
* @constant {Array<[RegExp, string]>}
|
|
41
|
+
*/
|
|
42
|
+
const DANGEROUS_PATTERNS = [
|
|
43
|
+
// DDL — destructive drops
|
|
44
|
+
[/\bDROP\s+TABLE\b/i, 'DROP TABLE'],
|
|
45
|
+
[/\bDROP\s+VIEW\b/i, 'DROP VIEW'],
|
|
46
|
+
[/\bDROP\s+MATERIALIZED\s+VIEW\b/i, 'DROP MATERIALIZED VIEW'],
|
|
47
|
+
[/\bDROP\s+FUNCTION\b/i, 'DROP FUNCTION'],
|
|
48
|
+
[/\bDROP\s+TRIGGER\b/i, 'DROP TRIGGER'],
|
|
49
|
+
[/\bDROP\s+INDEX\b/i, 'DROP INDEX'],
|
|
50
|
+
[/\bDROP\s+SCHEMA\b/i, 'DROP SCHEMA'],
|
|
51
|
+
[/\bDROP\s+POLICY\b/i, 'DROP POLICY'],
|
|
52
|
+
[/\bDROP\s+DATABASE\b/i, 'DROP DATABASE'],
|
|
53
|
+
// DML — data loss
|
|
54
|
+
[/\bTRUNCATE\b/i, 'TRUNCATE'],
|
|
55
|
+
// DELETE without a WHERE clause (whole-table wipe).
|
|
56
|
+
[/\bDELETE\s+FROM\s+[^;]*?(?:;|$)(?<!\bWHERE\b[^;]*)/i, 'DELETE without WHERE'],
|
|
57
|
+
// Disallowed backup pattern (table copy).
|
|
58
|
+
[/\bCREATE\s+TABLE\b[\s\S]*?\bAS\s+SELECT\b/i, 'CREATE TABLE AS SELECT (backup pattern)'],
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const SQL_FILE_PATTERN = /\.sql$/i;
|
|
62
|
+
const MIGRATION_PATH_PATTERN = /(^|\/)migrations?\//i;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Should this path be SQL-scanned?
|
|
66
|
+
* @param {string} filePath
|
|
67
|
+
* @returns {boolean}
|
|
68
|
+
*/
|
|
69
|
+
function isSqlScanTarget(filePath) {
|
|
70
|
+
const norm = String(filePath).replace(/\\/g, '/');
|
|
71
|
+
return SQL_FILE_PATTERN.test(norm) || MIGRATION_PATH_PATTERN.test(norm);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Strip SQL comments so `-- DROP TABLE foo` (commented out) is ignored.
|
|
76
|
+
* Removes `--` line comments and `/* ... *\/` block comments.
|
|
77
|
+
* @param {string} sql
|
|
78
|
+
* @returns {string}
|
|
79
|
+
*/
|
|
80
|
+
function stripSqlComments(sql) {
|
|
81
|
+
return String(sql == null ? '' : sql)
|
|
82
|
+
.replace(/\/\*[\s\S]*?\*\//g, ' ') // block comments
|
|
83
|
+
.replace(/--[^\n\r]*/g, ' '); // line comments
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Detect destructive SQL in a blob. Operates per-statement (split on ';') so a
|
|
88
|
+
* `DELETE FROM a WHERE x; DELETE FROM b;` correctly flags only the second.
|
|
89
|
+
* @param {string} content
|
|
90
|
+
* @returns {string[]} list of human labels for findings (deduped)
|
|
91
|
+
*/
|
|
92
|
+
function detectDangerousSql(content) {
|
|
93
|
+
const cleaned = stripSqlComments(content);
|
|
94
|
+
const statements = cleaned.split(';');
|
|
95
|
+
const found = new Set();
|
|
96
|
+
|
|
97
|
+
for (const rawStmt of statements) {
|
|
98
|
+
const stmt = rawStmt.trim();
|
|
99
|
+
if (!stmt) continue;
|
|
100
|
+
|
|
101
|
+
for (const [pattern, label] of DANGEROUS_PATTERNS) {
|
|
102
|
+
if (label === 'DELETE without WHERE') {
|
|
103
|
+
// Per-statement WHERE check: flag a DELETE FROM only when this
|
|
104
|
+
// statement has no WHERE.
|
|
105
|
+
if (/\bDELETE\s+FROM\b/i.test(stmt) && !/\bWHERE\b/i.test(stmt)) {
|
|
106
|
+
found.add(label);
|
|
107
|
+
}
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
if (pattern.test(stmt)) {
|
|
111
|
+
found.add(label);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return Array.from(found);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function getStagedFiles() {
|
|
120
|
+
try {
|
|
121
|
+
const output = execSync('git diff --cached --name-only --diff-filter=ACMR', {
|
|
122
|
+
encoding: 'utf8',
|
|
123
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
124
|
+
}).trim();
|
|
125
|
+
return output ? output.split('\n').filter(Boolean) : [];
|
|
126
|
+
} catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function readStagedFile(filePath) {
|
|
132
|
+
// Throws on failure so the caller can fail-CLOSED instead of scanning "".
|
|
133
|
+
return execFileSync('git', ['show', `:${filePath}`], {
|
|
134
|
+
encoding: 'utf8',
|
|
135
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
136
|
+
maxBuffer: 5 * 1024 * 1024,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Scan the given staged files for destructive SQL.
|
|
142
|
+
* @param {string[]} files
|
|
143
|
+
* @returns {Array<{ filePath: string, reasons: string[] }>}
|
|
144
|
+
*/
|
|
145
|
+
function scanStagedFiles(files) {
|
|
146
|
+
const findings = [];
|
|
147
|
+
|
|
148
|
+
for (const filePath of files) {
|
|
149
|
+
if (!isSqlScanTarget(filePath)) continue;
|
|
150
|
+
|
|
151
|
+
let content;
|
|
152
|
+
try {
|
|
153
|
+
content = readStagedFile(filePath);
|
|
154
|
+
} catch {
|
|
155
|
+
// Unreadable blob (binary/deleted-readded race) — skip; SQL files are text.
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const reasons = detectDangerousSql(content);
|
|
160
|
+
if (reasons.length > 0) {
|
|
161
|
+
findings.push({ filePath, reasons });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return findings;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function main() {
|
|
169
|
+
let findings;
|
|
170
|
+
try {
|
|
171
|
+
const files = getStagedFiles();
|
|
172
|
+
if (files.length === 0) process.exit(0);
|
|
173
|
+
findings = scanStagedFiles(files);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
// fail-CLOSED on unexpected scanner error.
|
|
176
|
+
process.stderr.write('\nStaged SQL Guard: unexpected error — commit blocked (fail-closed).\n');
|
|
177
|
+
process.stderr.write(String(err && err.message ? err.message : err) + '\n');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (findings.length === 0) process.exit(0);
|
|
182
|
+
|
|
183
|
+
process.stderr.write('\nStaged SQL Guard: commit blocked (destructive SQL detected).\n\n');
|
|
184
|
+
for (const f of findings) {
|
|
185
|
+
process.stderr.write(`- ${f.filePath}: ${f.reasons.join(', ')}\n`);
|
|
186
|
+
}
|
|
187
|
+
process.stderr.write('\nDestructive schema/data operations must go through a reviewed migration,\n');
|
|
188
|
+
process.stderr.write('not a raw commit. If this is an intentional, reviewed migration:\n');
|
|
189
|
+
process.stderr.write(' git commit --no-verify (framework contributors / reviewed migrations only)\n\n');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
module.exports = {
|
|
194
|
+
DANGEROUS_PATTERNS,
|
|
195
|
+
isSqlScanTarget,
|
|
196
|
+
stripSqlComments,
|
|
197
|
+
detectDangerousSql,
|
|
198
|
+
getStagedFiles,
|
|
199
|
+
scanStagedFiles,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
if (require.main === module) {
|
|
203
|
+
main();
|
|
204
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/* SINAPSE-MANAGED-GIT-HOOK — Auto-generated by SINAPSE git-hooks-installer. Do not edit manually. */
|
|
4
|
+
/* Re-run `sinapse init` (or the greenfield bootstrap) to regenerate. */
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const projectRoot = process.cwd();
|
|
11
|
+
|
|
12
|
+
// Migrated from .husky/post-commit (non-blocking, best-effort).
|
|
13
|
+
const POST_COMMIT_SCRIPTS = [
|
|
14
|
+
path.join('.sinapse-ai', 'infrastructure', 'scripts', 'git-hooks', 'post-commit.js'),
|
|
15
|
+
path.join('.sinapse-ai', 'hooks', 'ids-post-commit.js'),
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
for (const rel of POST_COMMIT_SCRIPTS) {
|
|
19
|
+
const abs = path.join(projectRoot, rel);
|
|
20
|
+
if (!fs.existsSync(abs)) continue;
|
|
21
|
+
try {
|
|
22
|
+
spawnSync(process.execPath, [abs], { stdio: 'ignore', cwd: projectRoot });
|
|
23
|
+
} catch {
|
|
24
|
+
// Never block on post-commit failures.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
process.exit(0);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/* SINAPSE-MANAGED-GIT-HOOK — Auto-generated by SINAPSE git-hooks-installer. Do not edit manually. */
|
|
4
|
+
/* Re-run `sinapse init` (or the greenfield bootstrap) to regenerate. */
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const projectRoot = process.cwd();
|
|
11
|
+
const libDir = path.join(__dirname, 'lib');
|
|
12
|
+
|
|
13
|
+
// --- 1-3. SINAPSE staged guards (each fail-CLOSED) ---------------------------
|
|
14
|
+
// Order: secret scan, then destructive-SQL guard, then framework-boundary guard.
|
|
15
|
+
// framework-guard self-disables when boundary.frameworkProtection is false.
|
|
16
|
+
const GUARDS = [
|
|
17
|
+
{ file: 'staged-secret-scan.js', label: 'Secret Scan' },
|
|
18
|
+
{ file: 'staged-sql-guard.js', label: 'SQL Guard' },
|
|
19
|
+
{ file: 'framework-guard.js', label: 'Framework Boundary' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
for (const guard of GUARDS) {
|
|
23
|
+
const guardPath = path.join(libDir, guard.file);
|
|
24
|
+
if (!fs.existsSync(guardPath)) {
|
|
25
|
+
// A bundled guard vanished — fail-CLOSED rather than skip silently.
|
|
26
|
+
process.stderr.write('SINAPSE ' + guard.label + ': guard missing at ' + guardPath + ' — blocking commit (fail-closed).\n');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const res = spawnSync(process.execPath, [guardPath], { stdio: 'inherit', cwd: projectRoot });
|
|
30
|
+
if (res.error) {
|
|
31
|
+
process.stderr.write('SINAPSE ' + guard.label + ': guard failed to run — blocking commit (fail-closed).\n');
|
|
32
|
+
process.stderr.write(' ' + res.error.message + '\n');
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (typeof res.status === 'number' && res.status !== 0) {
|
|
36
|
+
// Non-zero from a guard = commit blocked. A clean guard prints its own
|
|
37
|
+
// reason; a crashed guard (e.g. corrupted lib) does not, so emit an
|
|
38
|
+
// explicit fail-closed line so the block is never silent.
|
|
39
|
+
process.stderr.write('SINAPSE ' + guard.label + ': blocking commit (fail-closed, exit ' + res.status + ').\n');
|
|
40
|
+
process.exit(res.status);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// --- 4. Chain to a pre-existing hook (husky or backed-up prior hook) --------
|
|
45
|
+
const explicitChain = null;
|
|
46
|
+
const candidates = [];
|
|
47
|
+
if (explicitChain) {
|
|
48
|
+
candidates.push(path.resolve(projectRoot, explicitChain));
|
|
49
|
+
}
|
|
50
|
+
candidates.push(path.join(projectRoot, '.husky', 'pre-commit'));
|
|
51
|
+
|
|
52
|
+
const selfPath = __filename;
|
|
53
|
+
for (const candidate of candidates) {
|
|
54
|
+
if (!candidate || !fs.existsSync(candidate)) continue;
|
|
55
|
+
if (path.resolve(candidate) === path.resolve(selfPath)) continue; // never recurse into self
|
|
56
|
+
|
|
57
|
+
const isJs = candidate.endsWith('.js') || candidate.endsWith('.cjs');
|
|
58
|
+
const cmd = isJs ? process.execPath : candidate;
|
|
59
|
+
const args = isJs ? [candidate] : [];
|
|
60
|
+
const res = spawnSync(cmd, args, { stdio: 'inherit', cwd: projectRoot });
|
|
61
|
+
|
|
62
|
+
if (res.error) {
|
|
63
|
+
// A shell-script hook (.husky uses sh) may not be directly executable via
|
|
64
|
+
// spawnSync on Windows. Try 'sh' as an interpreter before giving up.
|
|
65
|
+
if (!isJs) {
|
|
66
|
+
const shRes = spawnSync('sh', [candidate], { stdio: 'inherit', cwd: projectRoot });
|
|
67
|
+
if (!shRes.error) {
|
|
68
|
+
if (typeof shRes.status === 'number' && shRes.status !== 0) process.exit(shRes.status);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
process.stderr.write('SINAPSE pre-commit: failed to run chained hook ' + candidate + ': ' + res.error.message + '\n');
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
if (typeof res.status === 'number' && res.status !== 0) {
|
|
76
|
+
process.exit(res.status);
|
|
77
|
+
}
|
|
78
|
+
break; // only chain to the first existing prior hook
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
process.exit(0);
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/* SINAPSE-MANAGED-GIT-HOOK — Auto-generated by SINAPSE git-hooks-installer. Do not edit manually. */
|
|
4
|
+
/* Re-run `sinapse init` (or the greenfield bootstrap) to regenerate. */
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const projectRoot = process.cwd();
|
|
11
|
+
|
|
12
|
+
// --- 1. Run validate:all (or validate) if the project defines it -----------
|
|
13
|
+
function pickValidateScript() {
|
|
14
|
+
try {
|
|
15
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
16
|
+
if (!fs.existsSync(pkgPath)) return null;
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
18
|
+
const scripts = (pkg && pkg.scripts) || {};
|
|
19
|
+
for (const name of ['validate:all', 'validate']) {
|
|
20
|
+
if (typeof scripts[name] === 'string' && scripts[name].length > 0) return name;
|
|
21
|
+
}
|
|
22
|
+
} catch {
|
|
23
|
+
// Unreadable package.json — treat as "no validate script" (allow).
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const script = pickValidateScript();
|
|
29
|
+
if (script) {
|
|
30
|
+
const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
31
|
+
const res = spawnSync(npmCmd, ['run', '--silent', script], { stdio: 'inherit', cwd: projectRoot });
|
|
32
|
+
if (res.error) {
|
|
33
|
+
process.stderr.write('SINAPSE pre-push: could not run "npm run ' + script + '" — blocking push (fail-closed).\n');
|
|
34
|
+
process.stderr.write(' ' + res.error.message + '\n');
|
|
35
|
+
process.stderr.write(' Bypass (emergency only): git push --no-verify\n');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
if (typeof res.status === 'number' && res.status !== 0) {
|
|
39
|
+
process.stderr.write('\nSINAPSE pre-push: validation failed (see output above). Push blocked.\n');
|
|
40
|
+
process.stderr.write(' Bypass (emergency only): git push --no-verify\n\n');
|
|
41
|
+
process.exit(res.status);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// --- 2. Chain to a pre-existing pre-push hook ------------------------------
|
|
46
|
+
const explicitChain = ".husky\\pre-push";
|
|
47
|
+
const candidates = [];
|
|
48
|
+
if (explicitChain) {
|
|
49
|
+
candidates.push(path.resolve(projectRoot, explicitChain));
|
|
50
|
+
}
|
|
51
|
+
candidates.push(path.join(projectRoot, '.husky', 'pre-push'));
|
|
52
|
+
|
|
53
|
+
const selfPath = __filename;
|
|
54
|
+
for (const candidate of candidates) {
|
|
55
|
+
if (!candidate || !fs.existsSync(candidate)) continue;
|
|
56
|
+
if (path.resolve(candidate) === path.resolve(selfPath)) continue;
|
|
57
|
+
|
|
58
|
+
const isJs = candidate.endsWith('.js') || candidate.endsWith('.cjs');
|
|
59
|
+
const cmd = isJs ? process.execPath : candidate;
|
|
60
|
+
const args = isJs ? [candidate] : [];
|
|
61
|
+
const res = spawnSync(cmd, args, { stdio: 'inherit', cwd: projectRoot });
|
|
62
|
+
if (res.error) {
|
|
63
|
+
if (!isJs) {
|
|
64
|
+
const shRes = spawnSync('sh', [candidate], { stdio: 'inherit', cwd: projectRoot });
|
|
65
|
+
if (!shRes.error) {
|
|
66
|
+
if (typeof shRes.status === 'number' && shRes.status !== 0) process.exit(shRes.status);
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
process.stderr.write('SINAPSE pre-push: failed to run chained hook ' + candidate + ': ' + res.error.message + '\n');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
if (typeof res.status === 'number' && res.status !== 0) process.exit(res.status);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
process.exit(0);
|
|
@@ -96,17 +96,19 @@ async function main() {
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
try {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
99
|
+
// Use the canonical deterministic generator (populate-entity-registry.js),
|
|
100
|
+
// NOT the incremental RegistryUpdater. The updater emits a divergent schema
|
|
101
|
+
// (categories-first, dropping the metadata/resolutionRate block) which
|
|
102
|
+
// flipped the entire ~30k-line registry on every commit — the recurring
|
|
103
|
+
// drift. populate() is a fixed point: it preserves lastUpdated/lastVerified
|
|
104
|
+
// when content is unchanged, so an unchanged repo regenerates byte-identical
|
|
105
|
+
// (zero churn).
|
|
106
|
+
const { populate } = require(
|
|
107
|
+
path.resolve(REPO_ROOT, '.sinapse-ai/development/scripts/populate-entity-registry.js'),
|
|
108
|
+
);
|
|
109
|
+
const registry = populate();
|
|
110
|
+
const count = registry && registry.metadata ? registry.metadata.entityCount : 0;
|
|
111
|
+
console.log(`[IDS-Hook] Registry regenerated (canonical schema, ${count} entities).`);
|
|
110
112
|
} catch (err) {
|
|
111
113
|
// Post-commit hook should NEVER block workflow
|
|
112
114
|
console.error(`[IDS-Hook] Registry update failed (non-blocking): ${err.message}`);
|
|
@@ -105,13 +105,15 @@ async function main() {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
108
|
+
// Canonical deterministic generator (see ids-post-commit.js for why the
|
|
109
|
+
// incremental RegistryUpdater is NOT used: it emits a divergent schema that
|
|
110
|
+
// churned the whole registry). populate() is a fixed point.
|
|
111
|
+
const { populate } = require(
|
|
112
|
+
path.resolve(REPO_ROOT, '.sinapse-ai/development/scripts/populate-entity-registry.js'),
|
|
113
|
+
);
|
|
114
|
+
const registry = populate();
|
|
115
|
+
const count = registry && registry.metadata ? registry.metadata.entityCount : 0;
|
|
116
|
+
console.log(`[IDS-Hook] Registry synced before push (canonical, ${count} entities).`);
|
|
115
117
|
} catch (err) {
|
|
116
118
|
// Pre-push hook should warn but NOT block push
|
|
117
119
|
console.warn(`[IDS-Hook] Registry sync failed (non-blocking): ${err.message}`);
|
|
@@ -39,15 +39,12 @@ function readStdin() {
|
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// Story 10.47: delegate to the shared grounding config loader instead of
|
|
43
|
+
// duplicating the read+parse. The require is guarded so the hook stays
|
|
44
|
+
// fail-open even if the shared module is somehow absent at runtime.
|
|
42
45
|
function loadConfig() {
|
|
43
46
|
try {
|
|
44
|
-
|
|
45
|
-
const raw = fs.readFileSync(CONFIG_PATH, 'utf8');
|
|
46
|
-
let yaml;
|
|
47
|
-
try { yaml = require('js-yaml'); } catch { return null; }
|
|
48
|
-
const parsed = yaml.load(raw);
|
|
49
|
-
if (!parsed || typeof parsed !== 'object') return null;
|
|
50
|
-
return parsed;
|
|
47
|
+
return require('../core/grounding/config-loader.cjs').loadGroundingConfig(CONFIG_PATH);
|
|
51
48
|
} catch {
|
|
52
49
|
return null;
|
|
53
50
|
}
|
|
@@ -66,15 +66,12 @@ function readStdin() {
|
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
// Story 10.47: delegate to the shared grounding config loader instead of
|
|
70
|
+
// duplicating the read+parse. The require is guarded so the hook stays
|
|
71
|
+
// fail-open even if the shared module is somehow absent at runtime.
|
|
69
72
|
function loadConfig() {
|
|
70
73
|
try {
|
|
71
|
-
|
|
72
|
-
const raw = fs.readFileSync(CONFIG_PATH, 'utf8');
|
|
73
|
-
let yaml;
|
|
74
|
-
try { yaml = require('js-yaml'); } catch { return null; }
|
|
75
|
-
const parsed = yaml.load(raw);
|
|
76
|
-
if (!parsed || typeof parsed !== 'object') return null;
|
|
77
|
-
return parsed;
|
|
74
|
+
return require('../core/grounding/config-loader.cjs').loadGroundingConfig(CONFIG_PATH);
|
|
78
75
|
} catch {
|
|
79
76
|
return null;
|
|
80
77
|
}
|