sinapse-ai 9.4.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 +10 -4
- 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/hook-governance.md +1 -0
- package/.claude/rules/mandatory-delegation.md +24 -0
- package/.claude/rules/project-intelligence.md +63 -0
- package/.claude/rules/response-format.md +4 -0
- package/.claude/rules/safe-collaboration.md +4 -2
- package/.claude/rules/security-data-protection.md +18 -0
- package/.claude/rules/squad-awareness.md +93 -67
- package/.claude/rules/token-economy.md +148 -0
- package/.codex/agents/analyst.md +90 -0
- package/.codex/agents/architect.md +78 -0
- package/.codex/agents/data-engineer.md +38 -0
- package/.codex/agents/developer.md +97 -0
- package/.codex/agents/devops.md +121 -0
- package/.codex/agents/product-lead.md +27 -0
- package/.codex/agents/project-lead.md +28 -0
- package/.codex/agents/quality-gate.md +89 -0
- package/.codex/agents/sprint-lead.md +28 -0
- package/.codex/agents/squad-creator.md +58 -0
- package/.codex/agents/ux-design-expert.md +28 -0
- 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 +1384 -944
- package/.sinapse-ai/development/agents/architect.md +5 -0
- package/.sinapse-ai/development/agents/data-engineer.md +38 -0
- package/.sinapse-ai/development/agents/developer.md +28 -0
- package/.sinapse-ai/development/agents/devops.md +4 -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 +4 -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/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/deploy-readiness.md +93 -0
- package/.sinapse-ai/development/skills/model-router.md +92 -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/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-template/LICENSE +22 -22
- 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-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 +275 -140
- 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/framework/orqx-plan.md +1 -1
- 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/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/squad.yaml +20 -6
- package/squads/squad-claude/knowledge-base/context-window-optimization.md +1 -1
- package/squads/squad-claude/knowledge-base/swarm-orchestration-patterns.md +2 -2
- package/squads/squad-content/knowledge-base/ai-native-content-loop.md +220 -0
- package/squads/squad-content/knowledge-base/signal-intelligence-v2.md +234 -0
- package/squads/squad-content/knowledge-base/task-ownership-map.md +235 -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/squad.yaml +19 -4
- package/squads/squad-design/knowledge-base/cross-surface-token-canon.md +209 -0
- package/squads/squad-design/squad.yaml +19 -4
- package/.sinapse-ai/core/registry/service-registry.json +0 -6346
- package/.sinapse-ai/data/registry-update-log.jsonl +0 -1323
- 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/squad-growth/tasks/calculate-sample-size.md +0 -121
- package/squads/squad-paidmedia/tasks/calculate-sample-size.md +0 -57
package/.claude/CLAUDE.md
CHANGED
|
@@ -87,11 +87,17 @@ Use Grep (not grep), Read (not cat), Edit (not sed), Glob (not find). Prefer nat
|
|
|
87
87
|
- Agent memory in `.sinapse-ai/development/agents/{id}/MEMORY.md`
|
|
88
88
|
- **Memory as hints:** Memory entries are hints, NOT ground truth. Always verify against actual codebase before acting on remembered facts.
|
|
89
89
|
|
|
90
|
-
##
|
|
90
|
+
## Token Economy & Response Format (NON-NEGOTIABLE)
|
|
91
91
|
|
|
92
|
-
-
|
|
93
|
-
|
|
94
|
-
|
|
92
|
+
Auto-applied to all agents: `~/.claude/rules/token-economy.md` + `~/.claude/rules/response-format.md`. Compact at 60%, model route haiku/sonnet/opus, no preamble, no trailing summary.
|
|
93
|
+
|
|
94
|
+
## Delegation & Anti-Hallucination
|
|
95
|
+
|
|
96
|
+
- Persona switch for sequential work, sub-agent only for parallel (20K+ tokens each)
|
|
97
|
+
- Model routing: `haiku` routine, `sonnet` standard, `opus` complex
|
|
98
|
+
- Sub-agents announce their model for visual verification via statusline
|
|
99
|
+
- `npm view {pkg}` before adding deps. Cite file:line for claims.
|
|
100
|
+
- Mark uncertain claims with [NEEDS VERIFICATION]. Compact at 60%.
|
|
95
101
|
|
|
96
102
|
---
|
|
97
103
|
*SINAPSE v6.0 — CLI First | Observability Second | UI Third*
|
|
@@ -1,197 +1,197 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Hook: Enforce Architecture-First Development
|
|
4
|
-
|
|
5
|
-
REGRA: Código só pode ser criado/editado se existir documentação prévia.
|
|
6
|
-
|
|
7
|
-
Este hook intercepta Write/Edit em paths de código e verifica se existe
|
|
8
|
-
documentação aprovada antes de permitir a operação.
|
|
9
|
-
|
|
10
|
-
Exit Codes:
|
|
11
|
-
- 0: Permitido (doc existe ou path não requer doc)
|
|
12
|
-
- 2: Bloqueado (doc não existe para path protegido)
|
|
13
|
-
"""
|
|
14
|
-
|
|
15
|
-
import json
|
|
16
|
-
import sys
|
|
17
|
-
import os
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
# =============================================================================
|
|
21
|
-
# CONFIGURAÇÃO: Paths que EXIGEM documentação prévia
|
|
22
|
-
# =============================================================================
|
|
23
|
-
|
|
24
|
-
PROTECTED_PATHS = [
|
|
25
|
-
# Edge Functions - exigem docs/architecture/{function-name}.md
|
|
26
|
-
{
|
|
27
|
-
"pattern": "supabase/functions/",
|
|
28
|
-
"doc_patterns": [
|
|
29
|
-
"docs/architecture/{name}.md",
|
|
30
|
-
"docs/architecture/{name}-architecture.md",
|
|
31
|
-
"docs/approved-plans/{name}.md",
|
|
32
|
-
],
|
|
33
|
-
"extract_name": lambda p: p.split("supabase/functions/")[1].split("/")[0] if "supabase/functions/" in p else None,
|
|
34
|
-
},
|
|
35
|
-
# Migrations - exigem documentação de schema changes
|
|
36
|
-
{
|
|
37
|
-
"pattern": "supabase/migrations/",
|
|
38
|
-
"doc_patterns": [
|
|
39
|
-
"docs/approved-plans/migration-{name}.md",
|
|
40
|
-
"docs/architecture/database-changes.md",
|
|
41
|
-
],
|
|
42
|
-
"extract_name": lambda p: Path(p).stem if "supabase/migrations/" in p else None,
|
|
43
|
-
"allow_if_exists": True, # Permite editar migrations existentes
|
|
44
|
-
},
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
# Paths que são SEMPRE permitidos (não exigem doc)
|
|
48
|
-
ALWAYS_ALLOWED = [
|
|
49
|
-
".claude/",
|
|
50
|
-
"docs/",
|
|
51
|
-
"outputs/",
|
|
52
|
-
"squads/",
|
|
53
|
-
".sinapse-ai/",
|
|
54
|
-
".sinapse-custom/",
|
|
55
|
-
"node_modules/",
|
|
56
|
-
".git/",
|
|
57
|
-
"package.json",
|
|
58
|
-
"package-lock.json",
|
|
59
|
-
"tsconfig.json",
|
|
60
|
-
".env",
|
|
61
|
-
"README.md",
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
# =============================================================================
|
|
65
|
-
# LÓGICA DO HOOK
|
|
66
|
-
# =============================================================================
|
|
67
|
-
|
|
68
|
-
def get_project_root():
|
|
69
|
-
"""Obtém o root do projeto via variável de ambiente ou cwd."""
|
|
70
|
-
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
71
|
-
|
|
72
|
-
def is_always_allowed(file_path: str) -> bool:
|
|
73
|
-
"""Verifica se o path está na lista de sempre permitidos."""
|
|
74
|
-
for allowed in ALWAYS_ALLOWED:
|
|
75
|
-
if allowed in file_path:
|
|
76
|
-
return True
|
|
77
|
-
return False
|
|
78
|
-
|
|
79
|
-
def find_matching_protection(file_path: str) -> dict | None:
|
|
80
|
-
"""Encontra a regra de proteção que corresponde ao path."""
|
|
81
|
-
for protection in PROTECTED_PATHS:
|
|
82
|
-
if protection["pattern"] in file_path:
|
|
83
|
-
return protection
|
|
84
|
-
return None
|
|
85
|
-
|
|
86
|
-
def check_documentation_exists(file_path: str, protection: dict, project_root: str) -> tuple[bool, str]:
|
|
87
|
-
"""
|
|
88
|
-
Verifica se existe documentação para o path protegido.
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
(exists: bool, doc_path: str | None)
|
|
92
|
-
"""
|
|
93
|
-
extract_fn = protection.get("extract_name")
|
|
94
|
-
if not extract_fn:
|
|
95
|
-
return True, None
|
|
96
|
-
|
|
97
|
-
name = extract_fn(file_path)
|
|
98
|
-
if not name:
|
|
99
|
-
return True, None
|
|
100
|
-
|
|
101
|
-
# Verificar cada padrão de documentação
|
|
102
|
-
for doc_pattern in protection["doc_patterns"]:
|
|
103
|
-
doc_path = doc_pattern.format(name=name)
|
|
104
|
-
full_doc_path = os.path.join(project_root, doc_path)
|
|
105
|
-
|
|
106
|
-
if os.path.exists(full_doc_path):
|
|
107
|
-
return True, doc_path
|
|
108
|
-
|
|
109
|
-
# Se allow_if_exists e o arquivo já existe, permitir edição
|
|
110
|
-
if protection.get("allow_if_exists"):
|
|
111
|
-
full_file_path = os.path.join(project_root, file_path) if not file_path.startswith("/") else file_path
|
|
112
|
-
if os.path.exists(full_file_path):
|
|
113
|
-
return True, "(arquivo existente)"
|
|
114
|
-
|
|
115
|
-
return False, None
|
|
116
|
-
|
|
117
|
-
def format_required_docs(protection: dict, name: str) -> str:
|
|
118
|
-
"""Formata a lista de documentos aceitos."""
|
|
119
|
-
docs = []
|
|
120
|
-
for pattern in protection["doc_patterns"]:
|
|
121
|
-
docs.append(f" - {pattern.format(name=name)}")
|
|
122
|
-
return "\n".join(docs)
|
|
123
|
-
|
|
124
|
-
def main():
|
|
125
|
-
# Ler input do stdin
|
|
126
|
-
try:
|
|
127
|
-
input_data = json.load(sys.stdin)
|
|
128
|
-
except json.JSONDecodeError:
|
|
129
|
-
# Se não conseguir parsear, permitir (fail-open)
|
|
130
|
-
sys.exit(0)
|
|
131
|
-
|
|
132
|
-
tool_name = input_data.get("tool_name", "")
|
|
133
|
-
tool_input = input_data.get("tool_input", {})
|
|
134
|
-
file_path = tool_input.get("file_path", "")
|
|
135
|
-
|
|
136
|
-
# Só processar Write e Edit
|
|
137
|
-
if tool_name not in ["Write", "Edit"]:
|
|
138
|
-
sys.exit(0)
|
|
139
|
-
|
|
140
|
-
# Normalizar path (remover prefixo absoluto se presente)
|
|
141
|
-
project_root = get_project_root()
|
|
142
|
-
relative_path = file_path
|
|
143
|
-
if file_path.startswith(project_root):
|
|
144
|
-
relative_path = file_path[len(project_root):].lstrip("/")
|
|
145
|
-
|
|
146
|
-
# Verificar se é sempre permitido
|
|
147
|
-
if is_always_allowed(relative_path):
|
|
148
|
-
sys.exit(0)
|
|
149
|
-
|
|
150
|
-
# Verificar se path está protegido
|
|
151
|
-
protection = find_matching_protection(relative_path)
|
|
152
|
-
if not protection:
|
|
153
|
-
# Path não protegido, permitir
|
|
154
|
-
sys.exit(0)
|
|
155
|
-
|
|
156
|
-
# Verificar se documentação existe
|
|
157
|
-
doc_exists, doc_path = check_documentation_exists(relative_path, protection, project_root)
|
|
158
|
-
|
|
159
|
-
if doc_exists:
|
|
160
|
-
# Documentação existe, permitir
|
|
161
|
-
sys.exit(0)
|
|
162
|
-
|
|
163
|
-
# BLOQUEAR: Documentação não existe
|
|
164
|
-
name = protection["extract_name"](relative_path) or "unknown"
|
|
165
|
-
required_docs = format_required_docs(protection, name)
|
|
166
|
-
|
|
167
|
-
error_message = f"""
|
|
168
|
-
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
169
|
-
║ 🛑 ARCHITECTURE-FIRST: Documentação obrigatória antes de código ║
|
|
170
|
-
╠══════════════════════════════════════════════════════════════════════════════╣
|
|
171
|
-
║ ║
|
|
172
|
-
║ Arquivo bloqueado: {relative_path[:50]:<50} ║
|
|
173
|
-
║ ║
|
|
174
|
-
║ REGRA: Antes de criar/editar código em paths protegidos, você DEVE: ║
|
|
175
|
-
║ ║
|
|
176
|
-
║ 1. Documentar o plano de arquitetura ║
|
|
177
|
-
║ 2. Obter aprovação do usuário ║
|
|
178
|
-
║ 3. Criar o arquivo de documentação ║
|
|
179
|
-
║ ║
|
|
180
|
-
║ Documentos aceitos para '{name}': ║
|
|
181
|
-
{required_docs}
|
|
182
|
-
║ ║
|
|
183
|
-
║ AÇÃO: Crie um dos documentos acima com o plano aprovado, depois tente ║
|
|
184
|
-
║ novamente a operação de código. ║
|
|
185
|
-
║ ║
|
|
186
|
-
║ DICA: Use `*create-doc architecture` para criar doc de arquitetura ║
|
|
187
|
-
║ Ou crie docs/approved-plans/{name}.md com o plano resumido ║
|
|
188
|
-
║ ║
|
|
189
|
-
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
190
|
-
"""
|
|
191
|
-
|
|
192
|
-
print(error_message, file=sys.stderr)
|
|
193
|
-
sys.exit(2) # Exit code 2 = bloqueia o tool
|
|
194
|
-
|
|
195
|
-
if __name__ == "__main__":
|
|
196
|
-
main()
|
|
197
|
-
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Hook: Enforce Architecture-First Development
|
|
4
|
+
|
|
5
|
+
REGRA: Código só pode ser criado/editado se existir documentação prévia.
|
|
6
|
+
|
|
7
|
+
Este hook intercepta Write/Edit em paths de código e verifica se existe
|
|
8
|
+
documentação aprovada antes de permitir a operação.
|
|
9
|
+
|
|
10
|
+
Exit Codes:
|
|
11
|
+
- 0: Permitido (doc existe ou path não requer doc)
|
|
12
|
+
- 2: Bloqueado (doc não existe para path protegido)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
import sys
|
|
17
|
+
import os
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
|
|
20
|
+
# =============================================================================
|
|
21
|
+
# CONFIGURAÇÃO: Paths que EXIGEM documentação prévia
|
|
22
|
+
# =============================================================================
|
|
23
|
+
|
|
24
|
+
PROTECTED_PATHS = [
|
|
25
|
+
# Edge Functions - exigem docs/architecture/{function-name}.md
|
|
26
|
+
{
|
|
27
|
+
"pattern": "supabase/functions/",
|
|
28
|
+
"doc_patterns": [
|
|
29
|
+
"docs/architecture/{name}.md",
|
|
30
|
+
"docs/architecture/{name}-architecture.md",
|
|
31
|
+
"docs/approved-plans/{name}.md",
|
|
32
|
+
],
|
|
33
|
+
"extract_name": lambda p: p.split("supabase/functions/")[1].split("/")[0] if "supabase/functions/" in p else None,
|
|
34
|
+
},
|
|
35
|
+
# Migrations - exigem documentação de schema changes
|
|
36
|
+
{
|
|
37
|
+
"pattern": "supabase/migrations/",
|
|
38
|
+
"doc_patterns": [
|
|
39
|
+
"docs/approved-plans/migration-{name}.md",
|
|
40
|
+
"docs/architecture/database-changes.md",
|
|
41
|
+
],
|
|
42
|
+
"extract_name": lambda p: Path(p).stem if "supabase/migrations/" in p else None,
|
|
43
|
+
"allow_if_exists": True, # Permite editar migrations existentes
|
|
44
|
+
},
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
# Paths que são SEMPRE permitidos (não exigem doc)
|
|
48
|
+
ALWAYS_ALLOWED = [
|
|
49
|
+
".claude/",
|
|
50
|
+
"docs/",
|
|
51
|
+
"outputs/",
|
|
52
|
+
"squads/",
|
|
53
|
+
".sinapse-ai/",
|
|
54
|
+
".sinapse-custom/",
|
|
55
|
+
"node_modules/",
|
|
56
|
+
".git/",
|
|
57
|
+
"package.json",
|
|
58
|
+
"package-lock.json",
|
|
59
|
+
"tsconfig.json",
|
|
60
|
+
".env",
|
|
61
|
+
"README.md",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
# =============================================================================
|
|
65
|
+
# LÓGICA DO HOOK
|
|
66
|
+
# =============================================================================
|
|
67
|
+
|
|
68
|
+
def get_project_root():
|
|
69
|
+
"""Obtém o root do projeto via variável de ambiente ou cwd."""
|
|
70
|
+
return os.environ.get("CLAUDE_PROJECT_DIR", os.getcwd())
|
|
71
|
+
|
|
72
|
+
def is_always_allowed(file_path: str) -> bool:
|
|
73
|
+
"""Verifica se o path está na lista de sempre permitidos."""
|
|
74
|
+
for allowed in ALWAYS_ALLOWED:
|
|
75
|
+
if allowed in file_path:
|
|
76
|
+
return True
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
def find_matching_protection(file_path: str) -> dict | None:
|
|
80
|
+
"""Encontra a regra de proteção que corresponde ao path."""
|
|
81
|
+
for protection in PROTECTED_PATHS:
|
|
82
|
+
if protection["pattern"] in file_path:
|
|
83
|
+
return protection
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def check_documentation_exists(file_path: str, protection: dict, project_root: str) -> tuple[bool, str]:
|
|
87
|
+
"""
|
|
88
|
+
Verifica se existe documentação para o path protegido.
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
(exists: bool, doc_path: str | None)
|
|
92
|
+
"""
|
|
93
|
+
extract_fn = protection.get("extract_name")
|
|
94
|
+
if not extract_fn:
|
|
95
|
+
return True, None
|
|
96
|
+
|
|
97
|
+
name = extract_fn(file_path)
|
|
98
|
+
if not name:
|
|
99
|
+
return True, None
|
|
100
|
+
|
|
101
|
+
# Verificar cada padrão de documentação
|
|
102
|
+
for doc_pattern in protection["doc_patterns"]:
|
|
103
|
+
doc_path = doc_pattern.format(name=name)
|
|
104
|
+
full_doc_path = os.path.join(project_root, doc_path)
|
|
105
|
+
|
|
106
|
+
if os.path.exists(full_doc_path):
|
|
107
|
+
return True, doc_path
|
|
108
|
+
|
|
109
|
+
# Se allow_if_exists e o arquivo já existe, permitir edição
|
|
110
|
+
if protection.get("allow_if_exists"):
|
|
111
|
+
full_file_path = os.path.join(project_root, file_path) if not file_path.startswith("/") else file_path
|
|
112
|
+
if os.path.exists(full_file_path):
|
|
113
|
+
return True, "(arquivo existente)"
|
|
114
|
+
|
|
115
|
+
return False, None
|
|
116
|
+
|
|
117
|
+
def format_required_docs(protection: dict, name: str) -> str:
|
|
118
|
+
"""Formata a lista de documentos aceitos."""
|
|
119
|
+
docs = []
|
|
120
|
+
for pattern in protection["doc_patterns"]:
|
|
121
|
+
docs.append(f" - {pattern.format(name=name)}")
|
|
122
|
+
return "\n".join(docs)
|
|
123
|
+
|
|
124
|
+
def main():
|
|
125
|
+
# Ler input do stdin
|
|
126
|
+
try:
|
|
127
|
+
input_data = json.load(sys.stdin)
|
|
128
|
+
except json.JSONDecodeError:
|
|
129
|
+
# Se não conseguir parsear, permitir (fail-open)
|
|
130
|
+
sys.exit(0)
|
|
131
|
+
|
|
132
|
+
tool_name = input_data.get("tool_name", "")
|
|
133
|
+
tool_input = input_data.get("tool_input", {})
|
|
134
|
+
file_path = tool_input.get("file_path", "")
|
|
135
|
+
|
|
136
|
+
# Só processar Write e Edit
|
|
137
|
+
if tool_name not in ["Write", "Edit"]:
|
|
138
|
+
sys.exit(0)
|
|
139
|
+
|
|
140
|
+
# Normalizar path (remover prefixo absoluto se presente)
|
|
141
|
+
project_root = get_project_root()
|
|
142
|
+
relative_path = file_path
|
|
143
|
+
if file_path.startswith(project_root):
|
|
144
|
+
relative_path = file_path[len(project_root):].lstrip("/")
|
|
145
|
+
|
|
146
|
+
# Verificar se é sempre permitido
|
|
147
|
+
if is_always_allowed(relative_path):
|
|
148
|
+
sys.exit(0)
|
|
149
|
+
|
|
150
|
+
# Verificar se path está protegido
|
|
151
|
+
protection = find_matching_protection(relative_path)
|
|
152
|
+
if not protection:
|
|
153
|
+
# Path não protegido, permitir
|
|
154
|
+
sys.exit(0)
|
|
155
|
+
|
|
156
|
+
# Verificar se documentação existe
|
|
157
|
+
doc_exists, doc_path = check_documentation_exists(relative_path, protection, project_root)
|
|
158
|
+
|
|
159
|
+
if doc_exists:
|
|
160
|
+
# Documentação existe, permitir
|
|
161
|
+
sys.exit(0)
|
|
162
|
+
|
|
163
|
+
# BLOQUEAR: Documentação não existe
|
|
164
|
+
name = protection["extract_name"](relative_path) or "unknown"
|
|
165
|
+
required_docs = format_required_docs(protection, name)
|
|
166
|
+
|
|
167
|
+
error_message = f"""
|
|
168
|
+
╔══════════════════════════════════════════════════════════════════════════════╗
|
|
169
|
+
║ 🛑 ARCHITECTURE-FIRST: Documentação obrigatória antes de código ║
|
|
170
|
+
╠══════════════════════════════════════════════════════════════════════════════╣
|
|
171
|
+
║ ║
|
|
172
|
+
║ Arquivo bloqueado: {relative_path[:50]:<50} ║
|
|
173
|
+
║ ║
|
|
174
|
+
║ REGRA: Antes de criar/editar código em paths protegidos, você DEVE: ║
|
|
175
|
+
║ ║
|
|
176
|
+
║ 1. Documentar o plano de arquitetura ║
|
|
177
|
+
║ 2. Obter aprovação do usuário ║
|
|
178
|
+
║ 3. Criar o arquivo de documentação ║
|
|
179
|
+
║ ║
|
|
180
|
+
║ Documentos aceitos para '{name}': ║
|
|
181
|
+
{required_docs}
|
|
182
|
+
║ ║
|
|
183
|
+
║ AÇÃO: Crie um dos documentos acima com o plano aprovado, depois tente ║
|
|
184
|
+
║ novamente a operação de código. ║
|
|
185
|
+
║ ║
|
|
186
|
+
║ DICA: Use `*create-doc architecture` para criar doc de arquitetura ║
|
|
187
|
+
║ Ou crie docs/approved-plans/{name}.md com o plano resumido ║
|
|
188
|
+
║ ║
|
|
189
|
+
╚══════════════════════════════════════════════════════════════════════════════╝
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
print(error_message, file=sys.stderr)
|
|
193
|
+
sys.exit(2) # Exit code 2 = bloqueia o tool
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
main()
|
|
197
|
+
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# enforce-git-push-authority.sh
|
|
3
|
-
# PreToolUse hook: blocks "git push" commands in Bash tool
|
|
4
|
-
#
|
|
3
|
+
# PreToolUse hook: blocks "git push" commands in Bash tool unless active agent is @devops
|
|
4
|
+
# Detects active agent via .sinapse/session-state.json (same pattern as enforce-delegation.cjs)
|
|
5
5
|
# Uses node (not jq) for JSON parsing — works on Windows/Git Bash
|
|
6
|
-
# FAIL-CLOSED: if parsing fails, blocks the command
|
|
7
|
-
# Hardened
|
|
6
|
+
# FAIL-CLOSED: if parsing fails OR session-state is missing/unreadable, blocks the command
|
|
7
|
+
# Hardened v3: adds real agent detection (Story 10.15), retains indirect-execution checks
|
|
8
8
|
|
|
9
9
|
INPUT=$(cat)
|
|
10
10
|
|
|
11
|
+
# Resolve project root consistently with other hooks
|
|
12
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
13
|
+
|
|
14
|
+
# Detect active agent from session state (fail-closed: empty string on any error)
|
|
15
|
+
AGENT=$(node -e "
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
try {
|
|
19
|
+
const p = path.join(process.argv[1], '.sinapse', 'session-state.json');
|
|
20
|
+
const s = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
21
|
+
console.log(s.lastAgent || '');
|
|
22
|
+
} catch (e) {
|
|
23
|
+
console.log('');
|
|
24
|
+
}
|
|
25
|
+
" "$PROJECT_ROOT" 2>/dev/null)
|
|
26
|
+
|
|
27
|
+
# If active agent is @devops, allow the command immediately (AC 1)
|
|
28
|
+
if [ "$AGENT" = "devops" ]; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
11
32
|
# Extract command from JSON using node (available on all SINAPSE systems)
|
|
12
33
|
COMMAND=$(echo "$INPUT" | node -e "
|
|
13
34
|
let d='';
|