sinapse-ai 1.8.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/mind-clone-governance.py +212 -212
- package/.claude/hooks/read-protection.py +152 -152
- package/.claude/hooks/slug-validation.py +175 -175
- package/.claude/hooks/sql-governance.py +183 -183
- package/.claude/rules/documentation-first.md +1 -1
- package/.claude/rules/hook-governance.md +1 -1
- package/.claude/rules/mandatory-delegation.md +1 -1
- package/.claude/rules/project-intelligence.md +1 -1
- package/.codex/agents/analyst.md +4 -371
- package/.codex/agents/animations-orqx.md +4 -57
- package/.codex/agents/architect.md +4 -560
- package/.codex/agents/brand-orqx.md +4 -95
- package/.codex/agents/claude-mastery-chief.md +4 -0
- package/.codex/agents/cloning-orqx.md +4 -70
- package/.codex/agents/commercial-orqx.md +4 -67
- package/.codex/agents/config-engineer.md +2 -2
- package/.codex/agents/content-orqx.md +4 -77
- package/.codex/agents/copy-orqx.md +4 -65
- package/.codex/agents/cost-optimizer.md +4 -0
- package/.codex/agents/council-orqx.md +4 -68
- package/.codex/agents/courses-orqx.md +4 -64
- package/.codex/agents/cro-persuasion.md +4 -0
- package/.codex/agents/cyber-orqx.md +4 -67
- package/.codex/agents/data-engineer.md +4 -542
- package/.codex/agents/design-orqx.md +4 -65
- package/.codex/agents/design-system.md +4 -210
- package/.codex/agents/developer.md +4 -666
- package/.codex/agents/devops.md +4 -668
- package/.codex/agents/finance-orqx.md +4 -57
- package/.codex/agents/fiscal-compliance-br.md +4 -0
- package/.codex/agents/forecast-strategist.md +4 -0
- package/.codex/agents/growth-orqx.md +4 -75
- package/.codex/agents/hooks-architect.md +2 -2
- package/.codex/agents/mcp-integrator.md +2 -2
- package/.codex/agents/paidmedia-orqx.md +4 -67
- package/.codex/agents/platform-aesthetic-director.md +4 -0
- package/.codex/agents/premium-packaging-strategist.md +4 -0
- package/.codex/agents/product-lead.md +4 -371
- package/.codex/agents/product-orqx.md +4 -57
- package/.codex/agents/product-surface-director.md +4 -0
- package/.codex/agents/project-integrator.md +2 -2
- package/.codex/agents/project-lead.md +4 -414
- package/.codex/agents/quality-gate.md +4 -547
- package/.codex/agents/research-orqx.md +4 -67
- package/.codex/agents/roadmap-sentinel.md +2 -2
- package/.codex/agents/skill-craftsman.md +2 -2
- package/.codex/agents/snps-orqx.md +4 -684
- package/.codex/agents/sop-extractor.md +4 -61
- package/.codex/agents/sprint-lead.md +4 -324
- package/.codex/agents/squad-creator.md +4 -402
- package/.codex/agents/storytelling-orqx.md +4 -65
- package/.codex/agents/swarm-orqx.md +4 -64
- package/.codex/agents/ux-design-expert.md +4 -532
- package/.codex/agents/ux-designer.md +4 -124
- package/.codex/command-registry.json +9 -9
- package/.codex/delegation-matrix.json +375 -839
- package/.codex/delegation-parity.json +658 -0
- package/.codex/handoff-packet.parity.schema.json +148 -0
- package/.codex/handoff-packet.template.json +26 -0
- package/.codex/instructions.md +8 -8
- package/.codex/scripts/resolve-codex-agent.js +482 -0
- package/.codex/scripts/resolve-codex-command.js +75 -12
- package/.codex/scripts/resolve-codex-delegation.js +131 -92
- package/.codex/skills/sinapse-claude/SKILL.md +3 -3
- package/.codex/skills/sinapse-po/SKILL.md +1 -1
- package/.codex/tasks/resolve-sinapse-conflict.md +1 -1
- package/.sinapse-ai/constitution.md +5 -5
- package/.sinapse-ai/core/doctor/checks/git-hooks.js +163 -19
- package/.sinapse-ai/core/events/dashboard-emitter.js +30 -9
- package/.sinapse-ai/core/execution/subagent-dispatcher.js +1 -1
- package/.sinapse-ai/core/synapse/engine.js +15 -0
- package/.sinapse-ai/core/ui/observability-panel.js +240 -0
- package/.sinapse-ai/core-config.yaml +0 -20
- package/.sinapse-ai/data/entity-registry.yaml +185 -236
- package/.sinapse-ai/development/agents/snps-orqx.md +16 -26
- package/.sinapse-ai/development/tasks/build-autonomous.md +11 -1
- package/.sinapse-ai/development/tasks/build-resume.md +8 -0
- package/.sinapse-ai/development/tasks/build-status.md +8 -0
- package/.sinapse-ai/development/tasks/build.md +8 -0
- package/.sinapse-ai/development/tasks/cleanup-worktrees.md +8 -1
- package/.sinapse-ai/development/tasks/gotcha.md +8 -0
- package/.sinapse-ai/development/tasks/gotchas.md +8 -0
- package/.sinapse-ai/development/tasks/ids-health.md +14 -6
- package/.sinapse-ai/development/tasks/list-mcps.md +15 -0
- package/.sinapse-ai/development/tasks/merge-worktree.md +8 -1
- package/.sinapse-ai/development/tasks/qa-review-build.md +18 -0
- package/.sinapse-ai/development/tasks/remove-mcp.md +8 -1
- package/.sinapse-ai/development/tasks/validate-agents.md +26 -14
- package/.sinapse-ai/development/templates/service-template/README.md.hbs +159 -159
- package/.sinapse-ai/development/templates/service-template/__tests__/index.test.ts.hbs +238 -238
- package/.sinapse-ai/development/templates/service-template/client.ts.hbs +404 -404
- package/.sinapse-ai/development/templates/service-template/errors.ts.hbs +183 -183
- package/.sinapse-ai/development/templates/service-template/index.ts.hbs +121 -121
- package/.sinapse-ai/development/templates/service-template/package.json.hbs +88 -88
- package/.sinapse-ai/development/templates/service-template/types.ts.hbs +146 -146
- package/.sinapse-ai/development/templates/squad-template/LICENSE +22 -22
- package/.sinapse-ai/git-hooks/lib/framework-guard.js +258 -0
- package/.sinapse-ai/git-hooks/lib/secret-scanner-core.js +355 -0
- package/.sinapse-ai/git-hooks/lib/staged-secret-scan.js +179 -0
- package/.sinapse-ai/git-hooks/lib/staged-sql-guard.js +204 -0
- package/.sinapse-ai/git-hooks/post-commit +28 -0
- package/.sinapse-ai/git-hooks/pre-commit +81 -0
- package/.sinapse-ai/git-hooks/pre-push +83 -0
- package/.sinapse-ai/hooks/ids-post-commit.js +13 -11
- package/.sinapse-ai/hooks/ids-pre-push.js +9 -7
- package/.sinapse-ai/infrastructure/scripts/codex-parity/resolve.js +161 -0
- package/.sinapse-ai/infrastructure/scripts/dashboard-status-writer.js +6 -2
- package/.sinapse-ai/infrastructure/scripts/ide-sync/index.js +65 -68
- package/.sinapse-ai/infrastructure/scripts/sync-codex-local-first.js +156 -1
- package/.sinapse-ai/infrastructure/scripts/validate-codex-delegation.js +1 -4
- package/.sinapse-ai/infrastructure/scripts/validate-codex-integration.js +41 -5
- package/.sinapse-ai/infrastructure/templates/coderabbit.yaml.template +280 -280
- package/.sinapse-ai/infrastructure/templates/config/env.example +16 -16
- package/.sinapse-ai/infrastructure/templates/config/gitignore-additions.tmpl +59 -59
- package/.sinapse-ai/infrastructure/templates/github/CODEOWNERS.template +12 -12
- package/.sinapse-ai/infrastructure/templates/github-workflows/ci.yml.template +170 -170
- package/.sinapse-ai/infrastructure/templates/github-workflows/pr-automation.yml.template +331 -331
- package/.sinapse-ai/infrastructure/templates/github-workflows/release.yml.template +197 -197
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +19 -19
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-node.tmpl +86 -86
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-python.tmpl +146 -146
- package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-sinapse-base.tmpl +64 -64
- package/.sinapse-ai/infrastructure/templates/safe-collab/CODEOWNERS.template +16 -16
- package/.sinapse-ai/infrastructure/templates/sinapse-sync.yaml.template +183 -183
- package/.sinapse-ai/install-manifest.yaml +112 -164
- package/.sinapse-ai/local-config.yaml.template +65 -65
- package/.sinapse-ai/product/templates/adr.hbs +126 -126
- package/.sinapse-ai/product/templates/dbdr.hbs +242 -242
- package/.sinapse-ai/product/templates/epic.hbs +213 -213
- package/.sinapse-ai/product/templates/ide-rules/codex-rules.md +30 -0
- package/.sinapse-ai/product/templates/pmdr.hbs +187 -187
- package/.sinapse-ai/product/templates/prd-v2.0.hbs +217 -217
- package/.sinapse-ai/product/templates/prd.hbs +202 -202
- package/.sinapse-ai/product/templates/statusline/statusline-script.js +31 -8
- package/.sinapse-ai/product/templates/statusline/track-agent-clear.cjs +79 -0
- package/.sinapse-ai/product/templates/statusline/track-agent.cjs +218 -0
- package/.sinapse-ai/product/templates/story.hbs +264 -264
- package/.sinapse-ai/product/templates/task.hbs +171 -171
- package/.sinapse-ai/product/templates/tmpl-comment-on-examples.sql +159 -159
- package/.sinapse-ai/product/templates/tmpl-migration-script.sql +92 -92
- package/.sinapse-ai/product/templates/tmpl-rls-granular-policies.sql +105 -105
- package/.sinapse-ai/product/templates/tmpl-rls-kiss-policy.sql +11 -11
- package/.sinapse-ai/product/templates/tmpl-rls-roles.sql +136 -136
- package/.sinapse-ai/product/templates/tmpl-rls-simple.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-rls-tenant.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-rollback-script.sql +78 -78
- package/.sinapse-ai/product/templates/tmpl-seed-data.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-smoke-test.sql +17 -17
- package/.sinapse-ai/product/templates/tmpl-staging-copy-merge.sql +140 -140
- package/.sinapse-ai/product/templates/tmpl-stored-proc.sql +141 -141
- package/.sinapse-ai/product/templates/tmpl-trigger.sql +153 -153
- package/.sinapse-ai/product/templates/tmpl-view-materialized.sql +134 -134
- package/.sinapse-ai/product/templates/tmpl-view.sql +178 -178
- package/AGENTS.md +193 -0
- package/CHANGELOG.md +1247 -0
- package/LICENSE +63 -63
- package/README.en.md +17 -18
- package/README.md +18 -19
- package/bin/cli.js +1 -1
- package/bin/commands/install.js +194 -22
- package/bin/commands/status.js +14 -1
- package/bin/commands/uninstall.js +2 -2
- package/bin/commands/update.js +52 -0
- package/bin/lib/setup-statusline.js +191 -0
- package/bin/sinapse-init.js +11 -83
- package/bin/utils/framework-guard.js +17 -4
- package/bin/utils/secret-scanner-core.js +109 -7
- package/bin/utils/staged-sql-guard.js +204 -0
- package/bin/utils/validate-publish.js +63 -0
- package/docs/agent-reference-guide.md +5 -7
- package/docs/framework/agent-prefix-convention.md +58 -0
- package/docs/framework/architecture-overview.md +4 -4
- package/docs/framework/collaboration-activation.md +45 -0
- package/docs/framework/guiding-principles.md +9 -9
- package/docs/getting-started.md +1 -1
- package/docs/guides/agent-reference.md +1 -1
- package/docs/guides/codex-config.md +4 -5
- package/docs/pt/architecture/sub-orqx-pattern.md +20 -18
- package/docs/security/overview.md +1 -1
- package/package.json +16 -12
- package/packages/installer/src/index.js +26 -0
- package/packages/installer/src/installer/git-hooks-installer.js +211 -47
- package/packages/installer/src/installer/sinapse-ai-installer.js +71 -0
- package/packages/installer/src/wizard/feedback.js +1 -1
- package/packages/installer/src/wizard/ide-config-generator.js +26 -26
- package/packages/installer/src/wizard/index.js +53 -4
- package/packages/sinapse-install/bin/edmcp.js +0 -0
- package/packages/sinapse-install/bin/sinapse-install.js +0 -0
- package/scripts/audit-tasks.cjs +112 -91
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/prepare-hooks.js +58 -0
- package/scripts/regenerate-orqx-stubs.ps1 +2 -3
- package/scripts/sync-counts.js +10 -2
- package/scripts/sync-squad-yaml-components.js +108 -6
- package/scripts/validate-agents-md.js +128 -0
- package/scripts/validate-all.js +1 -0
- package/scripts/validate-squad-orqx.js +19 -9
- package/sinapse/agents/sinapse-orqx.md +16 -26
- package/sinapse/agents/snps-orqx.md +15 -25
- package/sinapse/knowledge-base/routing-catalog.md +1 -1
- package/sinapse/tasks/diagnose-and-route.md +1 -1
- package/sinapse/tasks/squad-status-report.md +1 -1
- package/squads/claude-code-mastery/agents/claude-mastery-chief.md +1 -1
- package/squads/claude-code-mastery/agents/hooks-architect.md +60 -68
- package/squads/claude-code-mastery/knowledge-base/swarm-orchestration-patterns.md +1 -1
- package/squads/claude-code-mastery/squad.yaml +8 -0
- package/squads/claude-code-mastery/tasks/audit-setup.md +1 -1
- package/squads/claude-code-mastery/workflows/optimization-cycle.yaml +4 -4
- package/squads/claude-code-mastery/workflows/project-setup-cycle.yaml +4 -4
- package/squads/squad-animations/README.md +1 -1
- package/squads/squad-animations/squad.yaml +1 -1
- package/squads/squad-brand/squad.yaml +1 -1
- package/squads/squad-cloning/README.md +1 -1
- package/squads/squad-cloning/squad.yaml +1 -1
- package/squads/squad-commercial/README.md +1 -1
- package/squads/squad-commercial/squad.yaml +2 -3
- package/squads/squad-content/README.md +1 -1
- package/squads/squad-content/squad.yaml +1 -1
- package/squads/squad-copy/README.md +1 -1
- package/squads/squad-copy/squad.yaml +2 -3
- package/squads/squad-council/README.md +1 -1
- package/squads/squad-courses/README.md +1 -1
- package/squads/squad-courses/squad.yaml +1 -1
- package/squads/squad-cybersecurity/README.md +1 -1
- package/squads/squad-cybersecurity/squad.yaml +2 -3
- package/squads/squad-design/README.md +1 -1
- package/squads/{squad-artdir → squad-design}/agents/cro-persuasion.md +1 -1
- package/squads/{squad-artdir → squad-design}/agents/platform-aesthetic-director.md +2 -2
- package/squads/{squad-artdir → squad-design}/agents/premium-packaging-strategist.md +2 -2
- package/squads/{squad-artdir → squad-design}/agents/product-surface-director.md +3 -3
- package/squads/squad-design/squad.yaml +6 -3
- package/squads/squad-finance/README.md +1 -1
- package/squads/squad-finance/squad.yaml +7 -1
- package/squads/squad-growth/README.md +1 -1
- package/squads/squad-growth/squad.yaml +1 -1
- package/squads/squad-paidmedia/README.md +1 -1
- package/squads/squad-paidmedia/squad.yaml +2 -3
- package/squads/squad-product/README.md +1 -1
- package/squads/squad-product/squad.yaml +1 -1
- package/squads/squad-research/README.md +1 -1
- package/squads/squad-research/squad.yaml +2 -3
- package/squads/squad-storytelling/README.md +1 -1
- package/squads/squad-storytelling/squad.yaml +2 -3
- package/.codex/agents/brad-frost.md +0 -46
- package/.codex/agents/claude-orqx.md +0 -72
- package/.codex/agents/copy-chief.md +0 -162
- package/.codex/agents/cyber-chief.md +0 -169
- package/.codex/agents/dan-mall.md +0 -43
- package/.codex/agents/data-chief.md +0 -198
- package/.codex/agents/dave-malouf.md +0 -43
- package/.codex/agents/db-sage.md +0 -152
- package/.codex/agents/design-chief.md +0 -226
- package/.codex/agents/dev.md +0 -102
- package/.codex/agents/legal-chief.md +0 -199
- package/.codex/agents/nano-banana-generator.md +0 -42
- package/.codex/agents/pm.md +0 -81
- package/.codex/agents/po.md +0 -85
- package/.codex/agents/qa.md +0 -98
- package/.codex/agents/sm.md +0 -77
- package/.codex/agents/squad-chief.md +0 -1553
- package/.codex/agents/squad.md +0 -66
- package/.codex/agents/story-chief.md +0 -180
- package/.codex/agents/tools-orqx.md +0 -219
- package/.codex/agents/traffic-masters-chief.md +0 -211
- package/.sinapse-ai/core/memory/__tests__/active-modules.verify.js +0 -265
- package/.sinapse-ai/core/permissions/__tests__/permission-mode.test.js +0 -293
- package/.sinapse-ai/data/registry-update-log.jsonl +0 -158
- package/.sinapse-ai/infrastructure/scripts/ide-sync/gemini-commands.js +0 -298
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/antigravity.js +0 -121
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/cursor.js +0 -119
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/github-copilot.js +0 -191
- package/.sinapse-ai/infrastructure/scripts/ide-sync/transformers/kimi.js +0 -448
- package/.sinapse-ai/infrastructure/tests/project-status-loader.test.js +0 -569
- package/.sinapse-ai/infrastructure/tests/regression-suite-v2.md +0 -622
- package/.sinapse-ai/infrastructure/tests/validate-module.js +0 -98
- package/.sinapse-ai/infrastructure/tests/worktree-manager.test.js +0 -620
- package/.sinapse-ai/monitor/hooks/lib/__init__.py +0 -2
- package/.sinapse-ai/monitor/hooks/lib/enrich.py +0 -59
- package/.sinapse-ai/monitor/hooks/lib/send_event.py +0 -48
- package/.sinapse-ai/monitor/hooks/notification.py +0 -30
- package/.sinapse-ai/monitor/hooks/post_tool_use.py +0 -46
- package/.sinapse-ai/monitor/hooks/pre_compact.py +0 -30
- package/.sinapse-ai/monitor/hooks/pre_tool_use.py +0 -41
- package/.sinapse-ai/monitor/hooks/stop.py +0 -30
- package/.sinapse-ai/monitor/hooks/subagent_stop.py +0 -30
- package/.sinapse-ai/monitor/hooks/user_prompt_submit.py +0 -39
- package/.sinapse-ai/product/templates/statusline/track-agent.sh +0 -69
- package/.sinapse-ai/workflow-intelligence/__tests__/confidence-scorer.test.js +0 -335
- package/.sinapse-ai/workflow-intelligence/__tests__/integration.test.js +0 -340
- package/.sinapse-ai/workflow-intelligence/__tests__/suggestion-engine.test.js +0 -438
- package/.sinapse-ai/workflow-intelligence/__tests__/wave-analyzer.test.js +0 -448
- package/.sinapse-ai/workflow-intelligence/__tests__/workflow-registry.test.js +0 -303
- package/bin/sinapse-graph.js +0 -19
- package/docs/codex-integration-process.md +0 -22
- package/docs/codex-parity-program.md +0 -27
- package/packages/installer/src/__tests__/performance-benchmark.js +0 -383
- package/packages/installer/tests/integration/environment-configuration.test.js +0 -332
- package/packages/installer/tests/integration/wizard-detection.test.js +0 -352
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +0 -383
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +0 -193
- package/packages/installer/tests/unit/config-validator.test.js +0 -315
- package/packages/installer/tests/unit/detection/detect-project-type.test.js +0 -539
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +0 -636
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +0 -192
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +0 -186
- package/packages/installer/tests/unit/env-template.test.js +0 -187
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +0 -310
- package/packages/installer/tests/unit/git-hooks-installer.test.js +0 -262
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +0 -231
- package/packages/installer/tests/unit/merger/env-merger.test.js +0 -191
- package/packages/installer/tests/unit/merger/markdown-merger.test.js +0 -262
- package/packages/installer/tests/unit/merger/strategies.test.js +0 -154
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +0 -328
- package/packages/sinapse-install/tests/unit/chrome-brain.smoke.test.js +0 -66
- package/scripts/install-monitor-hooks.sh +0 -82
- package/squads/squad-artdir/README.md +0 -90
- package/squads/squad-artdir/agents/accessibility-guardian.md +0 -184
- package/squads/squad-artdir/agents/artdir-orqx.md +0 -222
- package/squads/squad-artdir/agents/color-psychologist.md +0 -166
- package/squads/squad-artdir/agents/design-system-architect.md +0 -100
- package/squads/squad-artdir/agents/ia-architect.md +0 -169
- package/squads/squad-artdir/agents/interaction-designer.md +0 -162
- package/squads/squad-artdir/agents/layout-engineer.md +0 -163
- package/squads/squad-artdir/agents/motion-architect.md +0 -185
- package/squads/squad-artdir/agents/type-systemist.md +0 -138
- package/squads/squad-artdir/agents/visual-strategist.md +0 -127
- package/squads/squad-artdir/checklists/seven-pillars-validation-checklist.md +0 -172
- package/squads/squad-artdir/knowledge-base/case-nyo-ia-reference.md +0 -289
- package/squads/squad-artdir/knowledge-base/deliverables-templates.md +0 -457
- package/squads/squad-artdir/knowledge-base/motion-technique-catalog.md +0 -247
- package/squads/squad-artdir/knowledge-base/premium-packaging-principles.md +0 -133
- package/squads/squad-artdir/knowledge-base/psychological-toolkit.md +0 -229
- package/squads/squad-artdir/knowledge-base/saas-art-direction-canon.md +0 -242
- package/squads/squad-artdir/knowledge-base/seven-pillars-framework.md +0 -289
- package/squads/squad-artdir/knowledge-base/ten-pillars-framework.md +0 -221
- package/squads/squad-artdir/package.json +0 -20
- package/squads/squad-artdir/squad.yaml +0 -299
- package/squads/squad-artdir/tasks/audit-conversion.md +0 -97
- package/squads/squad-artdir/tasks/audit-drift-multi-surface.md +0 -55
- package/squads/squad-artdir/tasks/consult-saas-canon.md +0 -54
- package/squads/squad-artdir/tasks/create-art-direction-brief.md +0 -110
- package/squads/squad-artdir/tasks/create-premium-packaging-brief.md +0 -61
- package/squads/squad-artdir/tasks/create-wireflow.md +0 -84
- package/squads/squad-artdir/tasks/design-color-system.md +0 -81
- package/squads/squad-artdir/tasks/design-product-surface.md +0 -60
- package/squads/squad-artdir/tasks/design-token-system.md +0 -58
- package/squads/squad-artdir/tasks/diagnose-visual-language.md +0 -92
- package/squads/squad-artdir/tasks/first-5-minutes-choreography.md +0 -65
- package/squads/squad-artdir/tasks/specify-motion-system.md +0 -84
- package/squads/squad-artdir/tasks/validate-against-pillars.md +0 -143
- package/squads/squad-artdir/templates/art-direction-brief-template.md +0 -215
- package/squads/squad-artdir/workflows/conversion-audit-cycle.yaml +0 -142
- package/squads/squad-artdir/workflows/full-art-direction-cycle.yaml +0 -179
- package/squads/squad-artdir/workflows/saas-platform-art-direction-cycle.yaml +0 -338
- package/squads/squad-commercial/agents/legal-chief.md +0 -199
- package/squads/squad-copy/agents/copy-chief.md +0 -162
- package/squads/squad-cybersecurity/agents/cyber-chief.md +0 -169
- package/squads/squad-design/agents/design-chief.md +0 -226
- package/squads/squad-paidmedia/agents/traffic-masters-chief.md +0 -211
- package/squads/squad-research/agents/data-chief.md +0 -198
- package/squads/squad-storytelling/agents/story-chief.md +0 -180
|
@@ -1,55 +1,199 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Doctor Check: Git Hooks
|
|
3
3
|
*
|
|
4
|
-
* Validates
|
|
4
|
+
* Validates that the ACTIVE git hook system is wired and populated. The single
|
|
5
|
+
* IDE-agnostic security backstop is the managed `core.hooksPath` directory
|
|
6
|
+
* (`.sinapse-ai/git-hooks/`) containing a `pre-commit` guard. A common failure
|
|
7
|
+
* mode (the one this check exists to catch): `core.hooksPath` points at
|
|
8
|
+
* `.sinapse-ai/git-hooks` but that directory is EMPTY/MISSING — so every guard
|
|
9
|
+
* is silently INERT and secrets/destructive SQL pass at commit time.
|
|
10
|
+
*
|
|
11
|
+
* Beyond mere existence, this check also confirms the guard is PLAUSIBLE rather
|
|
12
|
+
* than a hollow shell:
|
|
13
|
+
* 1. core.hooksPath actually RESOLVES to the managed dir (.sinapse-ai/git-hooks).
|
|
14
|
+
* A hooksPath pointing somewhere else means the framework backstop is not the
|
|
15
|
+
* active hook system, even if some pre-commit exists there.
|
|
16
|
+
* 2. The pre-commit (and any present pre-push) guard is NON-EMPTY. A zero-byte /
|
|
17
|
+
* whitespace-only hook file passes existsSync but runs nothing — the same
|
|
18
|
+
* INERT trap with a file present to disguise it.
|
|
19
|
+
*
|
|
20
|
+
* Verdicts:
|
|
21
|
+
* - FAIL: core.hooksPath is set but the dir is missing, has no pre-commit, the
|
|
22
|
+
* pre-commit is empty, OR hooksPath resolves outside the managed dir
|
|
23
|
+
* (the inert-trap states — security off without anyone noticing).
|
|
24
|
+
* - WARN: no core.hooksPath set and no .husky fallback (hooks not installed),
|
|
25
|
+
* or pre-push present-but-empty / missing.
|
|
26
|
+
* - PASS: managed hooksPath populated with a non-empty pre-commit (and ideally
|
|
27
|
+
* pre-push), OR a husky fallback with the expected hooks exists.
|
|
5
28
|
*
|
|
6
29
|
* @module sinapse-ai/doctor/checks/git-hooks
|
|
7
|
-
* @story INS-4.1
|
|
30
|
+
* @story INS-4.1, E8-SECURITY
|
|
8
31
|
*/
|
|
9
32
|
|
|
10
33
|
const path = require('path');
|
|
11
34
|
const fs = require('fs');
|
|
35
|
+
const { execFileSync } = require('child_process');
|
|
12
36
|
|
|
13
37
|
const name = 'git-hooks';
|
|
14
38
|
|
|
15
|
-
const
|
|
39
|
+
const MANAGED_HOOKS_DIR = path.join('.sinapse-ai', 'git-hooks');
|
|
40
|
+
const EXPECTED_MANAGED = ['pre-commit', 'pre-push'];
|
|
41
|
+
const EXPECTED_HUSKY = ['pre-commit', 'pre-push'];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Read core.hooksPath from git config (null if unset / not a repo).
|
|
45
|
+
* @param {string} projectRoot
|
|
46
|
+
* @returns {string|null}
|
|
47
|
+
*/
|
|
48
|
+
function readHooksPath(projectRoot) {
|
|
49
|
+
try {
|
|
50
|
+
const out = execFileSync('git', ['-C', projectRoot, 'config', '--get', 'core.hooksPath'], {
|
|
51
|
+
encoding: 'utf8',
|
|
52
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
53
|
+
}).trim();
|
|
54
|
+
return out || null;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* True when a hook file exists AND carries real (non-whitespace) content.
|
|
62
|
+
* A zero-byte / blank hook passes existsSync but executes nothing — the same
|
|
63
|
+
* INERT trap with a file present to disguise it.
|
|
64
|
+
* @param {string} hookFile absolute path
|
|
65
|
+
* @returns {boolean}
|
|
66
|
+
*/
|
|
67
|
+
function hasContent(hookFile) {
|
|
68
|
+
try {
|
|
69
|
+
return fs.readFileSync(hookFile, 'utf8').trim().length > 0;
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* True when the configured hooksPath resolves to the managed git-hooks dir
|
|
77
|
+
* (.sinapse-ai/git-hooks), regardless of whether it was given as a relative or
|
|
78
|
+
* absolute path. If it points elsewhere, the framework backstop is not the
|
|
79
|
+
* active hook system even if some pre-commit happens to exist there.
|
|
80
|
+
* @param {string} projectRoot
|
|
81
|
+
* @param {string} hooksPath value from core.hooksPath
|
|
82
|
+
* @returns {boolean}
|
|
83
|
+
*/
|
|
84
|
+
function resolvesToManaged(projectRoot, hooksPath) {
|
|
85
|
+
const resolved = path.resolve(projectRoot, hooksPath);
|
|
86
|
+
const managed = path.resolve(projectRoot, MANAGED_HOOKS_DIR);
|
|
87
|
+
return resolved === managed;
|
|
88
|
+
}
|
|
16
89
|
|
|
17
90
|
async function run(context) {
|
|
18
|
-
const
|
|
91
|
+
const projectRoot = context.projectRoot;
|
|
92
|
+
const hooksPath = readHooksPath(projectRoot);
|
|
19
93
|
|
|
20
|
-
|
|
94
|
+
// --- Case 1: core.hooksPath is configured -> it MUST be populated ---------
|
|
95
|
+
if (hooksPath) {
|
|
96
|
+
const hooksDirAbs = path.resolve(projectRoot, hooksPath);
|
|
97
|
+
const preCommit = path.join(hooksDirAbs, 'pre-commit');
|
|
98
|
+
|
|
99
|
+
if (!fs.existsSync(hooksDirAbs)) {
|
|
100
|
+
return {
|
|
101
|
+
check: name,
|
|
102
|
+
status: 'FAIL',
|
|
103
|
+
message: `core.hooksPath -> "${hooksPath}" but that directory is MISSING. Git guards are INERT (secret-scan/SQL/boundary do not run). Run the installer to populate it.`,
|
|
104
|
+
fixCommand: 'sinapse init # repopulates .sinapse-ai/git-hooks and re-wires core.hooksPath',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// hooksPath points at a real dir, but does it point at OUR managed dir? If it
|
|
109
|
+
// resolves elsewhere, the framework backstop is not the active hook system.
|
|
110
|
+
if (!resolvesToManaged(projectRoot, hooksPath)) {
|
|
111
|
+
return {
|
|
112
|
+
check: name,
|
|
113
|
+
status: 'FAIL',
|
|
114
|
+
message: `core.hooksPath -> "${hooksPath}" resolves OUTSIDE the managed dir (${MANAGED_HOOKS_DIR}). The framework's secret-scan/SQL/boundary guards are not the active hook system. Re-wire core.hooksPath to the managed dir.`,
|
|
115
|
+
fixCommand: 'sinapse init # re-wires core.hooksPath to .sinapse-ai/git-hooks',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!fs.existsSync(preCommit)) {
|
|
120
|
+
return {
|
|
121
|
+
check: name,
|
|
122
|
+
status: 'FAIL',
|
|
123
|
+
message: `core.hooksPath -> "${hooksPath}" exists but has NO pre-commit guard. The secret-scan backstop is INERT.`,
|
|
124
|
+
fixCommand: 'sinapse init # regenerates the managed pre-commit guard',
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// pre-commit exists but is empty/whitespace -> runs nothing -> still INERT.
|
|
129
|
+
if (!hasContent(preCommit)) {
|
|
130
|
+
return {
|
|
131
|
+
check: name,
|
|
132
|
+
status: 'FAIL',
|
|
133
|
+
message: `core.hooksPath -> "${hooksPath}" has a pre-commit file but it is EMPTY. The guard executes nothing — secret-scan/SQL/boundary are INERT despite the file being present.`,
|
|
134
|
+
fixCommand: 'sinapse init # regenerates the managed pre-commit guard',
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Populated with a plausible (non-empty) pre-commit. Report present hooks,
|
|
139
|
+
// treating a present-but-empty hook as missing (it does nothing).
|
|
140
|
+
const present = EXPECTED_MANAGED.filter(
|
|
141
|
+
(h) => fs.existsSync(path.join(hooksDirAbs, h)) && hasContent(path.join(hooksDirAbs, h)),
|
|
142
|
+
);
|
|
143
|
+
const missing = EXPECTED_MANAGED.filter((h) => !present.includes(h));
|
|
144
|
+
|
|
145
|
+
if (missing.length === 0) {
|
|
146
|
+
return {
|
|
147
|
+
check: name,
|
|
148
|
+
status: 'PASS',
|
|
149
|
+
message: `managed git guards active at ${hooksPath} (${present.join(' + ')})`,
|
|
150
|
+
fixCommand: null,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// pre-commit present and non-empty (security backstop active) but pre-push
|
|
155
|
+
// missing or empty -> WARN.
|
|
21
156
|
return {
|
|
22
157
|
check: name,
|
|
23
158
|
status: 'WARN',
|
|
24
|
-
message:
|
|
25
|
-
fixCommand: '
|
|
159
|
+
message: `managed pre-commit active at ${hooksPath}; missing/empty: ${missing.join(', ')}`,
|
|
160
|
+
fixCommand: 'sinapse init # writes the missing managed hook(s)',
|
|
26
161
|
};
|
|
27
162
|
}
|
|
28
163
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
)
|
|
164
|
+
// --- Case 2: no core.hooksPath -> fall back to husky detection ------------
|
|
165
|
+
const huskyDir = path.join(projectRoot, '.husky');
|
|
166
|
+
if (!fs.existsSync(huskyDir)) {
|
|
167
|
+
return {
|
|
168
|
+
check: name,
|
|
169
|
+
status: 'FAIL',
|
|
170
|
+
message: 'No git hook system active: core.hooksPath is unset and .husky/ is absent. Commit-time guards (secret-scan/SQL/boundary) do not run.',
|
|
171
|
+
fixCommand: 'sinapse init # installs the managed git guards',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
32
174
|
|
|
33
|
-
|
|
175
|
+
const missingHusky = EXPECTED_HUSKY.filter((h) => !fs.existsSync(path.join(huskyDir, h)));
|
|
176
|
+
if (missingHusky.length === 0) {
|
|
34
177
|
return {
|
|
35
178
|
check: name,
|
|
36
|
-
status: '
|
|
37
|
-
message:
|
|
38
|
-
fixCommand:
|
|
179
|
+
status: 'WARN',
|
|
180
|
+
message: 'husky hooks present but core.hooksPath is not set to the managed dir — the framework backstop is not the active hook system. Run the installer to consolidate.',
|
|
181
|
+
fixCommand: 'sinapse init # consolidates onto .sinapse-ai/git-hooks via core.hooksPath',
|
|
39
182
|
};
|
|
40
183
|
}
|
|
41
184
|
|
|
42
185
|
return {
|
|
43
186
|
check: name,
|
|
44
187
|
status: 'WARN',
|
|
45
|
-
message: `
|
|
46
|
-
fixCommand: '
|
|
188
|
+
message: `husky present but missing hooks: ${missingHusky.join(', ')}; managed core.hooksPath not set.`,
|
|
189
|
+
fixCommand: 'sinapse init',
|
|
47
190
|
};
|
|
48
191
|
}
|
|
49
192
|
|
|
50
|
-
//
|
|
51
|
-
//
|
|
193
|
+
// E8-SECURITY: a missing/inert hook dir is now a hard FAIL (the whole point of
|
|
194
|
+
// this check is to catch the silent-INERT trap). But on a fresh global install
|
|
195
|
+
// with no git repo at all, readHooksPath() returns null and we fall to the
|
|
196
|
+
// husky branch; to avoid a false alarm there, thrown exceptions stay WARN.
|
|
52
197
|
const onError = 'warn';
|
|
53
198
|
|
|
54
199
|
module.exports = { name, run, onError };
|
|
55
|
-
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard Event Emitter
|
|
3
3
|
*
|
|
4
|
-
* Singleton
|
|
5
|
-
*
|
|
4
|
+
* Singleton for high-level orchestration events (agent activation, command
|
|
5
|
+
* lifecycle, story status, Bob phases). Kept as a stable API consumed by the
|
|
6
|
+
* orchestrator (dashboard-integration.js, bob-orchestrator.js).
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
* -
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
8
|
+
* Transport status:
|
|
9
|
+
* - The legacy web monitor server (POST http://localhost:4001/events) was
|
|
10
|
+
* ARCHIVED (16/06/2026, Etapa 7 / decisão D6). That server never shipped in
|
|
11
|
+
* this repo, so emit() is a SAFE NO-OP by default — it never opens a socket.
|
|
12
|
+
* - The full event API (emit + emitXxx helpers) is preserved 1:1 so existing
|
|
13
|
+
* importers keep working without changes.
|
|
14
|
+
* - To opt back in to an HTTP sink later, set SINAPSE_MONITOR_URL in the env.
|
|
15
|
+
* When set, events POST to that URL (non-blocking, 500ms timeout, silent
|
|
16
|
+
* fail, fallback to a local .jsonl file). When unset (the normal case), the
|
|
17
|
+
* emitter does nothing — no network, no file writes.
|
|
12
18
|
*
|
|
13
19
|
* @module core/events/dashboard-emitter
|
|
14
20
|
*/
|
|
@@ -18,7 +24,9 @@ const fs = require('fs-extra');
|
|
|
18
24
|
const path = require('path');
|
|
19
25
|
const { DashboardEventType } = require('./types');
|
|
20
26
|
|
|
21
|
-
|
|
27
|
+
// No default endpoint: the web monitor was archived. The emitter only attempts
|
|
28
|
+
// a POST when SINAPSE_MONITOR_URL is explicitly provided. null => fail-silent no-op.
|
|
29
|
+
const MONITOR_SERVER_URL = process.env.SINAPSE_MONITOR_URL || null;
|
|
22
30
|
const EMIT_TIMEOUT_MS = 500;
|
|
23
31
|
|
|
24
32
|
/**
|
|
@@ -93,6 +101,13 @@ class DashboardEmitter {
|
|
|
93
101
|
async emit(type, data = {}) {
|
|
94
102
|
if (!this.enabled) return;
|
|
95
103
|
|
|
104
|
+
// Web monitor archived (Etapa 7 / D6): with no sink configured, emit() is a
|
|
105
|
+
// safe no-op. Build nothing, open no sockets, write no files. Opt back in by
|
|
106
|
+
// setting SINAPSE_MONITOR_URL. This keeps the public API identical for all
|
|
107
|
+
// callers (dashboard-integration.js, bob-orchestrator.js, tests) while
|
|
108
|
+
// killing the dead POST to localhost:4001.
|
|
109
|
+
if (!MONITOR_SERVER_URL) return;
|
|
110
|
+
|
|
96
111
|
const event = {
|
|
97
112
|
id: randomUUID(),
|
|
98
113
|
type,
|
|
@@ -303,11 +318,17 @@ class DashboardEmitter {
|
|
|
303
318
|
}
|
|
304
319
|
|
|
305
320
|
/**
|
|
306
|
-
* POST event to
|
|
321
|
+
* POST event to an external sink with timeout.
|
|
322
|
+
* No-op when SINAPSE_MONITOR_URL is unset (the archived web monitor case) —
|
|
323
|
+
* never opens a socket. Only runs when an endpoint is explicitly configured.
|
|
307
324
|
* @private
|
|
308
325
|
* @param {Object} event
|
|
309
326
|
*/
|
|
310
327
|
async _postEvent(event) {
|
|
328
|
+
// Defense-in-depth: emit() already short-circuits, but guard here too so a
|
|
329
|
+
// direct call can't resurrect the dead localhost:4001 POST.
|
|
330
|
+
if (!MONITOR_SERVER_URL) return;
|
|
331
|
+
|
|
311
332
|
const controller = new AbortController();
|
|
312
333
|
const timeout = setTimeout(() => controller.abort(), EMIT_TIMEOUT_MS);
|
|
313
334
|
|
|
@@ -12,7 +12,7 @@ const EventEmitter = require('events');
|
|
|
12
12
|
const _path = require('path');
|
|
13
13
|
const { runSafe } = require('../utils/spawn-safe');
|
|
14
14
|
|
|
15
|
-
// epic: orchestration-consolidation, F2 — resolves any of the
|
|
15
|
+
// epic: orchestration-consolidation, F2 — resolves any of the 172 agent ids to
|
|
16
16
|
// its real persona on disk (squads/ + framework agents). Optional: degrades to a
|
|
17
17
|
// generic prompt if the module is missing.
|
|
18
18
|
let SquadAgentResolver;
|
|
@@ -222,6 +222,13 @@ class SynapseEngine {
|
|
|
222
222
|
* @param {object} [config={}] - Configuration from manifest / caller
|
|
223
223
|
* @param {object} [config.manifest] - Parsed manifest object
|
|
224
224
|
* @param {boolean} [config.devmode] - Enable DEVMODE debug output
|
|
225
|
+
* @param {Array<object>} [config.layers] - Optional pre-instantiated layer
|
|
226
|
+
* instances (dependency injection). When provided, these are used verbatim
|
|
227
|
+
* instead of loading + instantiating the L0-L7 modules from disk. Each
|
|
228
|
+
* instance must expose `name`, `layer`, and `_safeProcess(context)`. This is
|
|
229
|
+
* the seam used by tests to inject isolated mock layers without relying on
|
|
230
|
+
* `jest.mock` hoisting or module-cache state. Production never passes this,
|
|
231
|
+
* so default behavior is unchanged.
|
|
225
232
|
*/
|
|
226
233
|
constructor(synapsePath, config = {}) {
|
|
227
234
|
this.synapsePath = synapsePath;
|
|
@@ -233,6 +240,14 @@ class SynapseEngine {
|
|
|
233
240
|
/** @type {MemoryBridge} Feature-gated MIS consumer (SYN-10) */
|
|
234
241
|
this.memoryBridge = new MemoryBridge();
|
|
235
242
|
|
|
243
|
+
// Dependency injection seam: when caller supplies ready layer instances,
|
|
244
|
+
// use them directly and skip module loading entirely (production default
|
|
245
|
+
// = no config.layers → identical behavior to before).
|
|
246
|
+
if (Array.isArray(config.layers)) {
|
|
247
|
+
this.layers = config.layers.filter(Boolean);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
|
|
236
251
|
for (const mod of LAYER_MODULES) {
|
|
237
252
|
const LayerClass = loadLayerModule(mod.path);
|
|
238
253
|
if (LayerClass) {
|
|
@@ -19,8 +19,50 @@
|
|
|
19
19
|
|
|
20
20
|
'use strict';
|
|
21
21
|
|
|
22
|
+
const fs = require('fs');
|
|
23
|
+
const os = require('os');
|
|
24
|
+
const path = require('path');
|
|
22
25
|
const { PanelRenderer } = require('./panel-renderer');
|
|
23
26
|
|
|
27
|
+
/**
|
|
28
|
+
* TTL (seconds) for session-cache entries. Mirrors the read-side contract
|
|
29
|
+
* shared with the statusline/panel: imperator/specialists older than this
|
|
30
|
+
* are treated as inactive. 6 hours.
|
|
31
|
+
* @constant {number}
|
|
32
|
+
*/
|
|
33
|
+
const SESSION_CACHE_TTL_SECONDS = 21600;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Stable 32-bit string hash. MUST stay byte-identical to the implementation
|
|
37
|
+
* in track-agent.sh and statusline-script.js so all peers resolve the same
|
|
38
|
+
* per-cwd session-cache file.
|
|
39
|
+
* @param {string} str - Input string (typically process.cwd()).
|
|
40
|
+
* @returns {string} Hex hash.
|
|
41
|
+
*/
|
|
42
|
+
function simpleHash(str) {
|
|
43
|
+
let hash = 0;
|
|
44
|
+
for (let i = 0; i < str.length; i++) {
|
|
45
|
+
const char = str.charCodeAt(i);
|
|
46
|
+
hash = ((hash << 5) - hash) + char;
|
|
47
|
+
hash |= 0;
|
|
48
|
+
}
|
|
49
|
+
return Math.abs(hash).toString(16);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Reads + parses a JSON file, returning null on any failure (fail-open).
|
|
54
|
+
* @param {string} filePath - Absolute path to the JSON file.
|
|
55
|
+
* @returns {Object|null} Parsed object or null.
|
|
56
|
+
*/
|
|
57
|
+
function readJsonSafe(filePath) {
|
|
58
|
+
try {
|
|
59
|
+
if (!fs.existsSync(filePath)) return null;
|
|
60
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
24
66
|
/**
|
|
25
67
|
* Panel modes
|
|
26
68
|
* @enum {string}
|
|
@@ -374,6 +416,202 @@ class ObservabilityPanel {
|
|
|
374
416
|
? this.renderer.renderDetailed(this.state)
|
|
375
417
|
: this.renderer.renderMinimal(this.state);
|
|
376
418
|
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Live-watches the runtime status sources and drives a panel from them.
|
|
422
|
+
*
|
|
423
|
+
* Decision D2 (MERGE): on every tick it reads BOTH the Bob dashboard status
|
|
424
|
+
* file and the per-cwd session-cache, then maps whichever describes an
|
|
425
|
+
* active orchestration:
|
|
426
|
+
* - If `bob.orchestration.active` → Bob owns the panel (pipeline,
|
|
427
|
+
* current_agent, active_terminals from the dashboard).
|
|
428
|
+
* - Otherwise → the session-cache drives it (imperator → coordinator,
|
|
429
|
+
* TTL-filtered specialists → active terminals).
|
|
430
|
+
* D7 populates light, state-aware `next_steps` suggestions.
|
|
431
|
+
*
|
|
432
|
+
* Reuses the existing render/start/stop loop — it does NOT spin its own
|
|
433
|
+
* setInterval. Fail-open: any read/parse error leaves prior state intact.
|
|
434
|
+
*
|
|
435
|
+
* @param {string} projectRoot - Project root used to locate bob-status.json.
|
|
436
|
+
* @param {Object} [opts] - Options.
|
|
437
|
+
* @param {number} [opts.refreshRate=1000] - Refresh interval in ms.
|
|
438
|
+
* @returns {{ stop: function(): void, panel: ObservabilityPanel }} Handle.
|
|
439
|
+
*/
|
|
440
|
+
static watchFromStatusFile(projectRoot, { refreshRate = 1000 } = {}) {
|
|
441
|
+
const panel = new ObservabilityPanel({ refreshRate });
|
|
442
|
+
|
|
443
|
+
const bobStatusPath = path.join(
|
|
444
|
+
projectRoot || process.cwd(),
|
|
445
|
+
'.sinapse',
|
|
446
|
+
'dashboard',
|
|
447
|
+
'bob-status.json',
|
|
448
|
+
);
|
|
449
|
+
const sessionCachePath = path.join(
|
|
450
|
+
os.homedir(),
|
|
451
|
+
'.claude',
|
|
452
|
+
'session-cache',
|
|
453
|
+
`${simpleHash(process.cwd())}.json`,
|
|
454
|
+
);
|
|
455
|
+
|
|
456
|
+
const tick = () => {
|
|
457
|
+
try {
|
|
458
|
+
const updates = ObservabilityPanel._buildUpdatesFromSources(
|
|
459
|
+
bobStatusPath,
|
|
460
|
+
sessionCachePath,
|
|
461
|
+
);
|
|
462
|
+
if (updates) panel.updateState(updates);
|
|
463
|
+
} catch {
|
|
464
|
+
// Fail-open: keep last good state.
|
|
465
|
+
}
|
|
466
|
+
};
|
|
467
|
+
|
|
468
|
+
// Prime once before the loop so the first frame reflects current state.
|
|
469
|
+
tick();
|
|
470
|
+
panel.start();
|
|
471
|
+
|
|
472
|
+
// Reuse the panel's render loop for tick() too — no second setInterval.
|
|
473
|
+
const watchInterval = setInterval(tick, refreshRate);
|
|
474
|
+
|
|
475
|
+
return {
|
|
476
|
+
panel,
|
|
477
|
+
stop() {
|
|
478
|
+
clearInterval(watchInterval);
|
|
479
|
+
panel.stop();
|
|
480
|
+
},
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Pure mapper: reads both status sources and returns an updateState() patch.
|
|
486
|
+
* Bob wins when its orchestration is active (D2 MERGE), else session-cache.
|
|
487
|
+
*
|
|
488
|
+
* @param {string} bobStatusPath - Absolute path to bob-status.json.
|
|
489
|
+
* @param {string} sessionCachePath - Absolute path to the session-cache.
|
|
490
|
+
* @returns {Object|null} updateState patch, or null when nothing to apply.
|
|
491
|
+
* @private
|
|
492
|
+
*/
|
|
493
|
+
static _buildUpdatesFromSources(bobStatusPath, sessionCachePath) {
|
|
494
|
+
const bob = readJsonSafe(bobStatusPath);
|
|
495
|
+
const cache = readJsonSafe(sessionCachePath);
|
|
496
|
+
|
|
497
|
+
if (bob && bob.orchestration && bob.orchestration.active) {
|
|
498
|
+
return ObservabilityPanel._mapBob(bob);
|
|
499
|
+
}
|
|
500
|
+
return ObservabilityPanel._mapSessionCache(cache);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Maps a Bob dashboard status object to an updateState() patch.
|
|
505
|
+
* @param {Object} bob - Parsed bob-status.json.
|
|
506
|
+
* @returns {Object} updateState patch.
|
|
507
|
+
* @private
|
|
508
|
+
*/
|
|
509
|
+
static _mapBob(bob) {
|
|
510
|
+
const updates = {};
|
|
511
|
+
|
|
512
|
+
if (bob.pipeline) {
|
|
513
|
+
updates.pipeline = bob.pipeline;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (bob.current_agent) {
|
|
517
|
+
updates.current_agent = bob.current_agent;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
const terminals = bob.active_terminals;
|
|
521
|
+
if (terminals) {
|
|
522
|
+
const list = Array.isArray(terminals.list)
|
|
523
|
+
? terminals.list
|
|
524
|
+
: (Array.isArray(terminals) ? terminals : []);
|
|
525
|
+
updates.active_terminals = {
|
|
526
|
+
list,
|
|
527
|
+
count: typeof terminals.count === 'number' ? terminals.count : list.length,
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
updates.next_steps = ObservabilityPanel._suggestNextSteps({
|
|
532
|
+
imperatorActive: false,
|
|
533
|
+
specialistNames: (updates.active_terminals?.list || []).map(
|
|
534
|
+
(t) => t.agent || t.id || t.label,
|
|
535
|
+
).filter(Boolean),
|
|
536
|
+
bobActive: true,
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
return updates;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Maps a per-cwd session-cache object to an updateState() patch.
|
|
544
|
+
* imperator.active → coordinator; TTL-filtered specialists → terminals.
|
|
545
|
+
* @param {Object|null} cache - Parsed session-cache (v2 shape) or null.
|
|
546
|
+
* @returns {Object} updateState patch.
|
|
547
|
+
* @private
|
|
548
|
+
*/
|
|
549
|
+
static _mapSessionCache(cache) {
|
|
550
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
551
|
+
const updates = {};
|
|
552
|
+
|
|
553
|
+
const imperator = cache && cache.imperator;
|
|
554
|
+
const imperatorActive = !!(
|
|
555
|
+
imperator
|
|
556
|
+
&& imperator.active
|
|
557
|
+
&& typeof imperator.ts === 'number'
|
|
558
|
+
&& (nowSec - imperator.ts) <= SESSION_CACHE_TTL_SECONDS
|
|
559
|
+
);
|
|
560
|
+
|
|
561
|
+
const specialists = Array.isArray(cache && cache.specialists)
|
|
562
|
+
? cache.specialists.filter(
|
|
563
|
+
(s) => s
|
|
564
|
+
&& typeof s.ts === 'number'
|
|
565
|
+
&& (nowSec - s.ts) <= SESSION_CACHE_TTL_SECONDS,
|
|
566
|
+
)
|
|
567
|
+
: [];
|
|
568
|
+
|
|
569
|
+
if (imperatorActive) {
|
|
570
|
+
updates.current_agent = { id: 'coordinator', name: null, task: null, reason: null };
|
|
571
|
+
} else {
|
|
572
|
+
updates.current_agent = { id: null, name: null, task: null, reason: null };
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
updates.active_terminals = {
|
|
576
|
+
list: specialists.map((s) => ({
|
|
577
|
+
agent: s.label || s.id,
|
|
578
|
+
pid: null,
|
|
579
|
+
task: null,
|
|
580
|
+
})),
|
|
581
|
+
count: specialists.length,
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
updates.next_steps = ObservabilityPanel._suggestNextSteps({
|
|
585
|
+
imperatorActive,
|
|
586
|
+
specialistNames: specialists.map((s) => s.label || s.id).filter(Boolean),
|
|
587
|
+
bobActive: false,
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
return updates;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* D7 — derives light, state-aware next-step suggestions.
|
|
595
|
+
* @param {Object} ctx - State context.
|
|
596
|
+
* @param {boolean} ctx.imperatorActive - Coordinator is active.
|
|
597
|
+
* @param {string[]} ctx.specialistNames - Active specialist labels.
|
|
598
|
+
* @param {boolean} ctx.bobActive - Bob orchestration is active.
|
|
599
|
+
* @returns {string[]} Suggestions.
|
|
600
|
+
* @private
|
|
601
|
+
*/
|
|
602
|
+
static _suggestNextSteps({ imperatorActive, specialistNames = [], bobActive = false }) {
|
|
603
|
+
if (specialistNames.length > 0) {
|
|
604
|
+
return ['Especialistas trabalhando: ' + specialistNames.join(', ')];
|
|
605
|
+
}
|
|
606
|
+
if (imperatorActive || bobActive) {
|
|
607
|
+
return ['Coordenador montando o plano'];
|
|
608
|
+
}
|
|
609
|
+
return [
|
|
610
|
+
'Rode os testes',
|
|
611
|
+
'Crie/valide a story',
|
|
612
|
+
'Invoque @sinapse para orquestrar',
|
|
613
|
+
];
|
|
614
|
+
}
|
|
377
615
|
}
|
|
378
616
|
|
|
379
617
|
/**
|
|
@@ -391,5 +629,7 @@ module.exports = {
|
|
|
391
629
|
PanelMode,
|
|
392
630
|
PipelineStage,
|
|
393
631
|
createDefaultState,
|
|
632
|
+
simpleHash,
|
|
633
|
+
SESSION_CACHE_TTL_SECONDS,
|
|
394
634
|
};
|
|
395
635
|
|
|
@@ -306,26 +306,6 @@ ideSync:
|
|
|
306
306
|
enabled: true
|
|
307
307
|
path: .codex/agents
|
|
308
308
|
format: full-markdown-yaml
|
|
309
|
-
gemini:
|
|
310
|
-
enabled: true
|
|
311
|
-
path: .gemini/rules/SINAPSE/agents
|
|
312
|
-
format: full-markdown-yaml
|
|
313
|
-
github-copilot:
|
|
314
|
-
enabled: true
|
|
315
|
-
path: .github/agents
|
|
316
|
-
format: github-copilot
|
|
317
|
-
cursor:
|
|
318
|
-
enabled: true
|
|
319
|
-
path: .cursor/rules/agents
|
|
320
|
-
format: condensed-rules
|
|
321
|
-
antigravity:
|
|
322
|
-
enabled: true
|
|
323
|
-
path: .antigravity/rules/agents
|
|
324
|
-
format: cursor-style
|
|
325
|
-
kimi:
|
|
326
|
-
enabled: true
|
|
327
|
-
path: .kimi/skills
|
|
328
|
-
format: kimi-skill
|
|
329
309
|
redirects: {}
|
|
330
310
|
validation:
|
|
331
311
|
strictMode: true
|