sinapse-ai 1.17.0 → 1.19.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/rules/documentation-first.md +6 -0
- package/.sinapse-ai/constitution.md +2 -2
- package/.sinapse-ai/core/code-intel/registry-syncer.js +5 -3
- package/.sinapse-ai/core/doctor/checks/agent-memory.js +7 -5
- package/.sinapse-ai/core/doctor/checks/claude-md.js +13 -0
- package/.sinapse-ai/core/doctor/checks/constitution-consistency.js +1 -0
- package/.sinapse-ai/core/doctor/checks/hooks-claude-count.js +11 -0
- package/.sinapse-ai/core/doctor/checks/settings-json.js +16 -2
- package/.sinapse-ai/core/doctor/index.js +27 -0
- package/.sinapse-ai/core/execution/build-orchestrator.js +192 -8
- package/.sinapse-ai/core/external-executors/delegate-cli.js +6 -2
- package/.sinapse-ai/core/health-check/checks/project/constitution-consistency.js +2 -1
- package/.sinapse-ai/core/ideation/ideation-engine.js +10 -8
- package/.sinapse-ai/core/mcp/config-migrator.js +8 -5
- package/.sinapse-ai/core/mcp/global-config-manager.js +4 -1
- package/.sinapse-ai/core/mcp/symlink-manager.js +6 -3
- package/.sinapse-ai/core/orchestration/bob-orchestrator.js +2 -4
- package/.sinapse-ai/core/orchestration/brownfield-handler.js +5 -4
- package/.sinapse-ai/core/orchestration/executors/epic-4-executor.js +45 -38
- package/.sinapse-ai/core/orchestration/gate-evaluator.js +104 -9
- package/.sinapse-ai/core/orchestration/greenfield-handler.js +14 -46
- package/.sinapse-ai/core/orchestration/index.js +0 -12
- package/.sinapse-ai/core/orchestration/master-orchestrator.js +60 -4
- package/.sinapse-ai/core/orchestration/session-state.js +19 -2
- package/.sinapse-ai/core/orchestration/workflow-executor.js +84 -127
- package/.sinapse-ai/core/quality-gates/focus-area-recommender.js +15 -11
- package/.sinapse-ai/core/registry/build-registry.js +3 -2
- package/.sinapse-ai/core/synapse/scripts/generate-constitution.js +1 -0
- package/.sinapse-ai/core/synapse/utils/atomic-write.js +34 -9
- package/.sinapse-ai/core-config.yaml +5 -1
- package/.sinapse-ai/data/capability-detection.js +3 -3
- package/.sinapse-ai/data/entity-registry.yaml +542 -601
- package/.sinapse-ai/data/mcp-discipline.js +1 -1
- package/.sinapse-ai/data/mcp-tool-examples.yaml +8 -8
- package/.sinapse-ai/data/tok2-validation.js +1 -1
- package/.sinapse-ai/data/tool-registry.yaml +4 -3
- package/.sinapse-ai/development/agents/project-lead/MEMORY.md +1 -1
- package/.sinapse-ai/development/agents/project-lead.md +9 -13
- package/.sinapse-ai/development/agents/snps-orqx.md +5 -5
- package/.sinapse-ai/development/scripts/migrate-task-to-v2.js +1 -1
- package/.sinapse-ai/development/scripts/validate-task-v2.js +67 -4
- package/.sinapse-ai/development/tasks/advanced-elicitation.md +3 -3
- package/.sinapse-ai/development/tasks/analyst-facilitate-brainstorming.md +3 -3
- package/.sinapse-ai/development/tasks/analyze-framework.md +1 -8
- package/.sinapse-ai/development/tasks/analyze-performance.md +1 -8
- package/.sinapse-ai/development/tasks/apply-qa-fixes.md +3 -3
- package/.sinapse-ai/development/tasks/architect-analyze-impact.md +3 -3
- package/.sinapse-ai/development/tasks/audit-codebase.md +1 -8
- package/.sinapse-ai/development/tasks/audit-tailwind-config.md +1 -4
- package/.sinapse-ai/development/tasks/audit-utilities.md +1 -8
- package/.sinapse-ai/development/tasks/bootstrap-shadcn-library.md +3 -3
- package/.sinapse-ai/development/tasks/brownfield-create-epic.md +3 -3
- package/.sinapse-ai/development/tasks/brownfield-create-story.md +3 -3
- package/.sinapse-ai/development/tasks/build-component.md +2 -5
- package/.sinapse-ai/development/tasks/calculate-roi.md +3 -3
- package/.sinapse-ai/development/tasks/ci-cd-configuration.md +1 -1
- package/.sinapse-ai/development/tasks/cleanup-utilities.md +3 -3
- package/.sinapse-ai/development/tasks/collaborative-edit.md +3 -3
- package/.sinapse-ai/development/tasks/compose-molecule.md +2 -5
- package/.sinapse-ai/development/tasks/consolidate-patterns.md +3 -3
- package/.sinapse-ai/development/tasks/correct-course.md +3 -3
- package/.sinapse-ai/development/tasks/create-brownfield-story.md +2 -5
- package/.sinapse-ai/development/tasks/create-deep-research-prompt.md +2 -5
- package/.sinapse-ai/development/tasks/create-doc.md +2 -5
- package/.sinapse-ai/development/tasks/create-next-story.md +2 -5
- package/.sinapse-ai/development/tasks/create-suite.md +2 -5
- package/.sinapse-ai/development/tasks/create-task.md +2 -5
- package/.sinapse-ai/development/tasks/create-workflow.md +2 -5
- package/.sinapse-ai/development/tasks/db-analyze-hotpaths.md +1 -8
- package/.sinapse-ai/development/tasks/db-apply-migration.md +1 -8
- package/.sinapse-ai/development/tasks/db-bootstrap.md +1 -8
- package/.sinapse-ai/development/tasks/db-domain-modeling.md +1 -8
- package/.sinapse-ai/development/tasks/db-dry-run.md +1 -8
- package/.sinapse-ai/development/tasks/db-env-check.md +1 -8
- package/.sinapse-ai/development/tasks/db-explain.md +1 -8
- package/.sinapse-ai/development/tasks/db-impersonate.md +1 -8
- package/.sinapse-ai/development/tasks/db-load-csv.md +1 -8
- package/.sinapse-ai/development/tasks/db-policy-apply.md +1 -8
- package/.sinapse-ai/development/tasks/db-rls-audit.md +1 -8
- package/.sinapse-ai/development/tasks/db-rollback.md +1 -8
- package/.sinapse-ai/development/tasks/db-run-sql.md +1 -8
- package/.sinapse-ai/development/tasks/db-schema-audit.md +1 -8
- package/.sinapse-ai/development/tasks/db-seed.md +1 -8
- package/.sinapse-ai/development/tasks/db-smoke-test.md +1 -8
- package/.sinapse-ai/development/tasks/db-snapshot.md +1 -8
- package/.sinapse-ai/development/tasks/db-squad-integration.md +1 -8
- package/.sinapse-ai/development/tasks/db-supabase-setup.md +1 -8
- package/.sinapse-ai/development/tasks/db-verify-order.md +1 -8
- package/.sinapse-ai/development/tasks/deprecate-component.md +3 -3
- package/.sinapse-ai/development/tasks/dev-apply-qa-fixes.md +3 -3
- package/.sinapse-ai/development/tasks/dev-backlog-debt.md +3 -3
- package/.sinapse-ai/development/tasks/dev-develop-story.md +1 -1
- package/.sinapse-ai/development/tasks/dev-improve-code-quality.md +3 -3
- package/.sinapse-ai/development/tasks/dev-optimize-performance.md +3 -3
- package/.sinapse-ai/development/tasks/dev-suggest-refactoring.md +3 -3
- package/.sinapse-ai/development/tasks/dev-validate-next-story.md +3 -3
- package/.sinapse-ai/development/tasks/document-project.md +3 -3
- package/.sinapse-ai/development/tasks/environment-bootstrap.md +0 -4
- package/.sinapse-ai/development/tasks/execute-checklist.md +3 -3
- package/.sinapse-ai/development/tasks/export-design-tokens-dtcg.md +3 -3
- package/.sinapse-ai/development/tasks/extend-pattern.md +1 -8
- package/.sinapse-ai/development/tasks/extract-tokens.md +3 -3
- package/.sinapse-ai/development/tasks/facilitate-brainstorming-session.md +1 -1
- package/.sinapse-ai/development/tasks/generate-ai-frontend-prompt.md +2 -5
- package/.sinapse-ai/development/tasks/generate-documentation.md +2 -5
- package/.sinapse-ai/development/tasks/generate-migration-strategy.md +2 -5
- package/.sinapse-ai/development/tasks/generate-shock-report.md +2 -5
- package/.sinapse-ai/development/tasks/github-devops-github-pr-automation.md +3 -3
- package/.sinapse-ai/development/tasks/github-devops-repository-cleanup.md +3 -3
- package/.sinapse-ai/development/tasks/github-devops-version-management.md +3 -3
- package/.sinapse-ai/development/tasks/improve-self.md +1 -16
- package/.sinapse-ai/development/tasks/index-docs.md +1 -4
- package/.sinapse-ai/development/tasks/init-project-status.md +1 -7
- package/.sinapse-ai/development/tasks/integrate-squad.md +3 -3
- package/.sinapse-ai/development/tasks/kb-mode-interaction.md +3 -3
- package/.sinapse-ai/development/tasks/learn-patterns.md +3 -3
- package/.sinapse-ai/development/tasks/modify-agent.md +1 -8
- package/.sinapse-ai/development/tasks/modify-task.md +1 -8
- package/.sinapse-ai/development/tasks/modify-workflow.md +1 -8
- package/.sinapse-ai/development/tasks/po-backlog-add.md +3 -3
- package/.sinapse-ai/development/tasks/po-manage-story-backlog.md +3 -3
- package/.sinapse-ai/development/tasks/po-pull-story-from-clickup.md +3 -3
- package/.sinapse-ai/development/tasks/po-pull-story.md +3 -3
- package/.sinapse-ai/development/tasks/po-stories-index.md +3 -3
- package/.sinapse-ai/development/tasks/po-sync-story-to-clickup.md +3 -3
- package/.sinapse-ai/development/tasks/po-sync-story.md +3 -3
- package/.sinapse-ai/development/tasks/pr-automation.md +1 -1
- package/.sinapse-ai/development/tasks/propose-modification.md +3 -3
- package/.sinapse-ai/development/tasks/push-and-pr.md +1 -1
- package/.sinapse-ai/development/tasks/qa-backlog-add-followup.md +1 -8
- package/.sinapse-ai/development/tasks/qa-create-fix-request.md +1 -4
- package/.sinapse-ai/development/tasks/qa-gate.md +1 -8
- package/.sinapse-ai/development/tasks/qa-generate-tests.md +1 -8
- package/.sinapse-ai/development/tasks/qa-nfr-assess.md +1 -8
- package/.sinapse-ai/development/tasks/qa-review-proposal.md +1 -8
- package/.sinapse-ai/development/tasks/qa-review-story.md +1 -8
- package/.sinapse-ai/development/tasks/qa-risk-profile.md +1 -8
- package/.sinapse-ai/development/tasks/qa-run-tests.md +1 -8
- package/.sinapse-ai/development/tasks/qa-test-design.md +1 -8
- package/.sinapse-ai/development/tasks/qa-trace-requirements.md +1 -8
- package/.sinapse-ai/development/tasks/release-management.md +1 -1
- package/.sinapse-ai/development/tasks/security-audit.md +1 -4
- package/.sinapse-ai/development/tasks/security-scan.md +1 -4
- package/.sinapse-ai/development/tasks/setup-database.md +2 -11
- package/.sinapse-ai/development/tasks/setup-design-system.md +2 -11
- package/.sinapse-ai/development/tasks/shard-doc.md +3 -3
- package/.sinapse-ai/development/tasks/sm-create-next-story.md +3 -3
- package/.sinapse-ai/development/tasks/sync-documentation.md +1 -6
- package/.sinapse-ai/development/tasks/tailwind-upgrade.md +3 -3
- package/.sinapse-ai/development/tasks/test-as-user.md +3 -3
- package/.sinapse-ai/development/tasks/undo-last.md +2 -5
- package/.sinapse-ai/development/tasks/update-manifest.md +1 -8
- package/.sinapse-ai/development/tasks/ux-create-wireframe.md +1 -1
- package/.sinapse-ai/development/tasks/ux-ds-scan-artifact.md +3 -3
- package/.sinapse-ai/development/tasks/ux-user-research.md +3 -3
- package/.sinapse-ai/development/tasks/validate-next-story.md +1 -8
- package/.sinapse-ai/development/templates/chrome-brain/scripts/chrome-ensure.cjs +1 -1
- package/.sinapse-ai/development/workflows/development-cycle.yaml +1 -12
- package/.sinapse-ai/git-hooks/post-commit +0 -0
- package/.sinapse-ai/git-hooks/pre-commit +0 -0
- package/.sinapse-ai/git-hooks/pre-push +0 -0
- package/.sinapse-ai/infrastructure/scripts/changelog-generator.js +5 -1
- package/.sinapse-ai/infrastructure/scripts/pattern-extractor.js +11 -2
- package/.sinapse-ai/infrastructure/scripts/test-utilities.js +34 -13
- package/.sinapse-ai/infrastructure/scripts/usage-analytics.js +9 -5
- package/.sinapse-ai/infrastructure/scripts/validate-claude-integration.js +10 -2
- package/.sinapse-ai/install-manifest.yaml +326 -334
- package/.sinapse-ai/lib/build.json +1 -0
- package/.sinapse-ai/product/templates/personalized-task-template-v2.md +4 -2
- package/.sinapse-ai/product/templates/statusline/statusline-script.js +7 -3
- package/CHANGELOG.md +108 -43
- package/README.en.md +5 -5
- package/README.md +5 -5
- package/bin/cli.js +1 -1
- package/bin/commands/install.js +288 -114
- package/bin/commands/local.js +11 -0
- package/bin/lib/command-generator.js +31 -2
- package/docs/README.md +1 -1
- package/docs/agent-reference-guide.md +1 -1
- package/docs/community/README-community-snippet-core.md +1 -1
- package/docs/community/README-community-snippet-mcp.md +1 -1
- package/docs/community/README-community-snippet-squads.md +1 -1
- package/docs/examples/quickstart-recording.md +1 -1
- package/docs/framework/README.md +1 -1
- package/docs/framework/architecture-overview.md +1 -0
- package/docs/framework/coding-standards.md +1 -1
- package/docs/framework/core-architecture.md +1 -1
- package/docs/framework/guiding-principles.md +1 -1
- package/docs/framework/source-tree.md +1 -1
- package/docs/framework/tech-stack.md +1 -1
- package/docs/framework/versioning-and-releases.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/guides/agent-reference.md +1 -1
- package/docs/guides/agent-selection-guide.md +1 -1
- package/docs/guides/api-reference.md +1 -1
- package/docs/guides/contextual-greeting-system-guide.md +1 -1
- package/docs/guides/contributing-squads.md +1 -1
- package/docs/guides/development-setup.md +1 -1
- package/docs/guides/git-workflow-guide.md +1 -1
- package/docs/guides/installation-troubleshooting.md +1 -1
- package/docs/guides/llm-routing.md +1 -1
- package/docs/guides/mcp-global-setup.md +1 -1
- package/docs/guides/meta-agent-commands.md +1 -1
- package/docs/guides/project-status-feature.md +1 -1
- package/docs/guides/quality-dashboard.md +1 -1
- package/docs/guides/quality-gates.md +1 -1
- package/docs/guides/security-hardening.md +1 -1
- package/docs/guides/service-discovery.md +19 -22
- package/docs/guides/squad-examples/README.md +1 -1
- package/docs/guides/squad-migration.md +1 -1
- package/docs/guides/squads-guide.md +1 -1
- package/docs/guides/squads-overview.md +10 -13
- package/docs/guides/template-engine-v2.md +1 -1
- package/docs/guides/testing-guide.md +1 -1
- package/docs/guides/user-guide.md +30 -26
- package/docs/installation/README.md +3 -3
- package/docs/installation/faq.md +1 -1
- package/docs/installation/linux.md +2 -2
- package/docs/installation/macos.md +1 -1
- package/docs/installation/npx-install.md +1 -1
- package/docs/installation/troubleshooting.md +1 -1
- package/docs/installation/uninstallation.md +1 -1
- package/docs/installation/v4-quick-start.md +1 -1
- package/docs/installation/windows.md +2 -2
- package/docs/pt/CHANGELOG.md +1 -1
- package/docs/pt/DOCUMENTATION-ROADMAP.md +1 -1
- package/docs/pt/ENVIRONMENT.md +1 -1
- package/docs/pt/FEATURE_PROCESS.md +2 -2
- package/docs/pt/GUIDING-PRINCIPLES.md +2 -2
- package/docs/pt/agent-reference-guide.md +3 -3
- package/docs/pt/architecture/ARCHITECTURE-INDEX.md +2 -2
- package/docs/pt/architecture/ade-architecture.md +1 -1
- package/docs/pt/architecture/agent-config-audit.md +1 -1
- package/docs/pt/architecture/agent-responsibility-matrix.md +1 -1
- package/docs/pt/architecture/agent-tool-integration-guide.md +1 -1
- package/docs/pt/architecture/ci-cd.md +1 -1
- package/docs/pt/architecture/coding-standards.md +1 -1
- package/docs/pt/architecture/contribution-workflow-research.md +1 -1
- package/docs/pt/architecture/dashboard-architecture.md +1 -1
- package/docs/pt/architecture/dashboard-realtime.md +1 -1
- package/docs/pt/architecture/hcs-check-specifications.md +1 -1
- package/docs/pt/architecture/hcs-execution-modes.md +1 -1
- package/docs/pt/architecture/hcs-self-healing-spec.md +1 -1
- package/docs/pt/architecture/high-level-architecture.md +1 -1
- package/docs/pt/architecture/introduction.md +1 -1
- package/docs/pt/architecture/mcp-api-keys-management.md +3 -3
- package/docs/pt/architecture/mcp-system-diagrams.md +1 -1
- package/docs/pt/architecture/module-system.md +4 -4
- package/docs/pt/architecture/multi-repo-strategy.md +2 -2
- package/docs/pt/architecture/source-tree.md +1 -1
- package/docs/pt/architecture/squad-improvement-analysis.md +1 -1
- package/docs/pt/architecture/squad-improvement-recommended-approach.md +1 -1
- package/docs/pt/architecture/tech-stack.md +1 -1
- package/docs/pt/architecture/utility-integration-guide.md +1 -1
- package/docs/pt/code-of-conduct.md +1 -1
- package/docs/pt/community/README-community-snippet-core.md +1 -1
- package/docs/pt/community/README-community-snippet-mcp.md +2 -2
- package/docs/pt/contributing.md +7 -7
- package/docs/pt/core-architecture.md +1 -1
- package/docs/pt/docker-mcp-setup.md +1 -1
- package/docs/pt/framework/README.md +1 -1
- package/docs/pt/framework/coding-standards.md +1 -1
- package/docs/pt/framework/source-tree.md +1 -1
- package/docs/pt/framework/tech-stack.md +1 -1
- package/docs/pt/getting-started.md +1 -1
- package/docs/pt/git-workflow-guide.md +1 -1
- package/docs/pt/guides/README.md +3 -3
- package/docs/pt/guides/agent-selection-guide.md +2 -2
- package/docs/pt/guides/api-reference.md +1 -1
- package/docs/pt/guides/contextual-greeting-system-guide.md +1 -1
- package/docs/pt/guides/contributing-squads.md +1 -1
- package/docs/pt/guides/development-setup.md +1 -1
- package/docs/pt/guides/installation-troubleshooting.md +1 -1
- package/docs/pt/guides/llm-routing.md +1 -1
- package/docs/pt/guides/mcp/desktop-commander.md +1 -1
- package/docs/pt/guides/mcp/docker-gateway-tutorial.md +1 -1
- package/docs/pt/guides/mcp-global-setup.md +1 -1
- package/docs/pt/guides/project-status-feature.md +1 -1
- package/docs/pt/guides/quality-dashboard.md +1 -1
- package/docs/pt/guides/quality-gates.md +1 -1
- package/docs/pt/guides/security-hardening.md +2 -2
- package/docs/pt/guides/service-discovery.md +19 -22
- package/docs/pt/guides/squad-examples/README.md +1 -1
- package/docs/pt/guides/squad-migration.md +1 -1
- package/docs/pt/guides/squads-guide.md +1 -1
- package/docs/pt/guides/squads-overview.md +11 -13
- package/docs/pt/guides/template-engine-v2.md +1 -1
- package/docs/pt/guides/testing-guide.md +3 -3
- package/docs/pt/guides/user-guide.md +30 -26
- package/docs/pt/guides/workflows-guide.md +1 -1
- package/docs/pt/how-to-contribute-with-pull-requests.md +1 -1
- package/docs/pt/ide-integration.md +2 -2
- package/docs/pt/installation/README.md +1 -1
- package/docs/pt/installation/faq.md +1 -1
- package/docs/pt/installation/linux.md +1 -1
- package/docs/pt/installation/macos.md +1 -1
- package/docs/pt/installation/troubleshooting.md +1 -1
- package/docs/pt/installation/v4-quick-start.md +1 -1
- package/docs/pt/installation/windows.md +1 -1
- package/docs/pt/meta-agent-commands.md +1 -1
- package/docs/pt/migration-guide.md +1 -1
- package/docs/pt/npx-install.md +1 -1
- package/docs/pt/performance-tuning-guide.md +1 -1
- package/docs/pt/platforms/claude-code.md +2 -2
- package/docs/pt/roadmap.md +2 -2
- package/docs/pt/security-best-practices.md +2 -2
- package/docs/pt/security.md +1 -1
- package/docs/pt/sinapse-nomenclature-specification.md +1 -1
- package/docs/pt/troubleshooting.md +1 -1
- package/docs/pt/uninstallation.md +1 -1
- package/docs/pt/versioning-and-releases.md +1 -1
- package/docs/security/overview.md +1 -1
- package/docs/security/security-best-practices.md +2 -2
- package/docs/sinapse-workflows/README.md +1 -1
- package/package.json +2 -1
- package/packages/installer/package.json +1 -0
- package/packages/installer/src/wizard/feedback.js +18 -2
- package/packages/installer/src/wizard/i18n.js +78 -0
- package/packages/installer/src/wizard/ide-config-generator.js +8 -9
- package/packages/installer/src/wizard/index.js +16 -16
- package/packages/installer/src/wizard/validation/report-generator.js +22 -21
- package/packages/installer/src/wizard/validation/troubleshooting-system.js +19 -13
- package/scripts/gen-agent-badges.js +1 -1
- package/scripts/package-synapse.js +14 -5
- package/scripts/prepare-hooks.js +19 -0
- package/scripts/validate-agent-codenames.js +174 -0
- package/scripts/validate-all.js +1 -0
- package/sinapse/agents/sinapse-orqx.md +5 -5
- package/sinapse/agents/snps-orqx.md +5 -5
- package/squads/squad-brand/agents/brand-creative-engineer.md +5 -5
- package/squads/squad-brand/squad.yaml +6 -6
- package/squads/squad-content/agents/content-engineer.md +7 -7
- package/squads/squad-content/squad.yaml +5 -5
- package/squads/squad-courses/agents/production-director.md +5 -5
- package/squads/squad-courses/squad.yaml +1 -1
- package/.sinapse-ai/core/orchestration/terminal-spawner.js +0 -1044
- package/.sinapse-ai/scripts/pm.sh +0 -466
|
@@ -44,6 +44,12 @@ No implementation proceeds without ALL of these:
|
|
|
44
44
|
|
|
45
45
|
**Attempting to write code without a valid story → BLOCKED.**
|
|
46
46
|
|
|
47
|
+
## Enforcement model — floor-reactive by design (honest)
|
|
48
|
+
|
|
49
|
+
Doc-first is enforced by a **deterministic reactive floor**, not by proactive prose: on a build request, `sinapse route` classifies the project type and **blocks** when the required artifacts are missing (story `Ready`; epic/PRD/architecture for large projects). This floor holds even if the agent forgets the rule, and it is covered by passing tests.
|
|
50
|
+
|
|
51
|
+
Audit AF-20260629 **refuted** the earlier "prose without enforcement" hypothesis — the floor genuinely classifies and blocks. What is *not* wired into the prompt is the proactive **layer-2 conduction** (auto-walking the user through PRD → epic → story turn by turn). That layer is intentional **roadmap**, not a missing guardrail: no new always-on hook is added here by design (a reactive floor is lower-risk than a proactive prompt injector).
|
|
52
|
+
|
|
47
53
|
## Project Type Gate (NON-NEGOTIABLE)
|
|
48
54
|
|
|
49
55
|
> **Why this exists:** A bare `epic + story` pipeline is necessary but not sufficient for **large projects**. A site, landing page, SaaS platform, mobile app, or backend service needs *upstream* artifacts (project brief, PRD, architecture, design spec) **before** stories can be written meaningfully. Without this gate, the framework writes stories from a vague verbal description and produces generic / off-brand output.
|
|
@@ -115,7 +115,7 @@ Qualidade não é negociável. Todo código passa por múltiplos gates antes de
|
|
|
115
115
|
- MUST: Story status é "Done" ou "Ready for Review"
|
|
116
116
|
- SHOULD: Cobertura de testes não diminui
|
|
117
117
|
|
|
118
|
-
**Gate:**
|
|
118
|
+
**Gate:** `.sinapse-ai/git-hooks/pre-push` - BLOCK se qualquer check falhar (executa `npm run validate:all`, fail-closed)
|
|
119
119
|
|
|
120
120
|
---
|
|
121
121
|
|
|
@@ -389,5 +389,5 @@ Resultado: nada foi fundido. Dual register preservado. Article XI formalizado pr
|
|
|
389
389
|
|
|
390
390
|
---
|
|
391
391
|
|
|
392
|
-
*SINAPSE Constitution
|
|
392
|
+
*SINAPSE Constitution v2.2.0*
|
|
393
393
|
*CLI First | Agent-Driven | Quality First*
|
|
@@ -6,6 +6,7 @@ const crypto = require('crypto');
|
|
|
6
6
|
const yaml = require('js-yaml');
|
|
7
7
|
const { getClient, isCodeIntelAvailable } = require('../code-intel');
|
|
8
8
|
const { RegistryLoader, DEFAULT_REGISTRY_PATH } = require('../ids/registry-loader');
|
|
9
|
+
const { atomicWriteSync } = require('../synapse/utils/atomic-write');
|
|
9
10
|
|
|
10
11
|
// Role inference from entity path (order matters: more specific patterns first)
|
|
11
12
|
const ROLE_MAP = [
|
|
@@ -366,10 +367,11 @@ class RegistrySyncer {
|
|
|
366
367
|
* @private
|
|
367
368
|
*/
|
|
368
369
|
_atomicWrite(registryPath, registry) {
|
|
369
|
-
const tmpPath = registryPath + '.tmp';
|
|
370
370
|
const content = yaml.dump(registry, { lineWidth: 120, noRefs: true });
|
|
371
|
-
|
|
372
|
-
|
|
371
|
+
// Delegate to the canonical helper: it does unlink-first on Windows and
|
|
372
|
+
// retries the rename on transient EPERM/EBUSY locks (AV / Search indexer /
|
|
373
|
+
// concurrent readers) that POSIX never hits.
|
|
374
|
+
atomicWriteSync(registryPath, content, 'utf8');
|
|
373
375
|
}
|
|
374
376
|
|
|
375
377
|
/**
|
|
@@ -12,13 +12,15 @@ const fs = require('fs');
|
|
|
12
12
|
|
|
13
13
|
const name = 'agent-memory';
|
|
14
14
|
|
|
15
|
+
// Canonical SINAPSE agent ids (current naming, since v6.0.0).
|
|
16
|
+
// These match the directory names under .sinapse-ai/development/agents/.
|
|
15
17
|
const EXPECTED_AGENTS = [
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
+
'developer',
|
|
19
|
+
'quality-gate',
|
|
18
20
|
'architect',
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
21
|
+
'project-lead',
|
|
22
|
+
'product-lead',
|
|
23
|
+
'sprint-lead',
|
|
22
24
|
'analyst',
|
|
23
25
|
'data-engineer',
|
|
24
26
|
'ux',
|
|
@@ -45,6 +45,19 @@ async function run(context) {
|
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// In the framework's own source repo, .claude/CLAUDE.md is the contributor
|
|
49
|
+
// variant (headings like "Framework Boundary", "Agents") rather than the
|
|
50
|
+
// install template (PT section titles). The content exists under different
|
|
51
|
+
// headings, so this is expected — surface as INFO, not WARN.
|
|
52
|
+
if (context.isFrameworkRepo) {
|
|
53
|
+
return {
|
|
54
|
+
check: name,
|
|
55
|
+
status: 'INFO',
|
|
56
|
+
message: `Dev CLAUDE.md variant — install-template sections not required in the source repo (${missingSections.join(', ')})`,
|
|
57
|
+
fixCommand: null,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
return {
|
|
49
62
|
check: name,
|
|
50
63
|
status: 'WARN',
|
|
@@ -99,6 +99,17 @@ async function run(context) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
if (hookCount >= 2 && !registered) {
|
|
102
|
+
// In the framework's own source repo, settings.local.json is gitignored
|
|
103
|
+
// (per-machine) and hook registration is an install-time step. Hook files
|
|
104
|
+
// shipping unregistered is expected here — surface as INFO, not WARN.
|
|
105
|
+
if (context.isFrameworkRepo) {
|
|
106
|
+
return {
|
|
107
|
+
check: name,
|
|
108
|
+
status: 'INFO',
|
|
109
|
+
message: `${hookCount} hook files present — registration is install-time (settings.local.json is gitignored in the source repo)`,
|
|
110
|
+
fixCommand: null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
102
113
|
return {
|
|
103
114
|
check: name,
|
|
104
115
|
status: 'WARN',
|
|
@@ -28,8 +28,11 @@ function checkBoundaryAlignment(context, denyRules) {
|
|
|
28
28
|
return [];
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
// Extract boundary.protected paths from YAML (simple line parsing)
|
|
32
|
-
|
|
31
|
+
// Extract boundary.protected paths from YAML (simple line parsing).
|
|
32
|
+
// Split on /\r?\n/ so a CRLF-saved core-config.yaml (Windows editors,
|
|
33
|
+
// core.autocrlf) does not leave a trailing \r that breaks the path regex
|
|
34
|
+
// below and silently empties protectedPaths (false-negative boundary check).
|
|
35
|
+
const lines = content.split(/\r?\n/);
|
|
33
36
|
const protectedPaths = [];
|
|
34
37
|
let inProtected = false;
|
|
35
38
|
|
|
@@ -91,6 +94,17 @@ async function run(context) {
|
|
|
91
94
|
const allowCount = allowRules.length;
|
|
92
95
|
|
|
93
96
|
if (denyCount < 40) {
|
|
97
|
+
// In the framework's own source repo, boundary protection is OFF by design
|
|
98
|
+
// (core-config boundary.frameworkProtection:false) so contributors can edit
|
|
99
|
+
// core files — 0 deny rules is the expected, correct state here.
|
|
100
|
+
if (context.isFrameworkRepo) {
|
|
101
|
+
return {
|
|
102
|
+
check: name,
|
|
103
|
+
status: 'INFO',
|
|
104
|
+
message: `Deny rules off (${denyCount}) — expected in the framework source repo (frameworkProtection:false)`,
|
|
105
|
+
fixCommand: null,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
94
108
|
return {
|
|
95
109
|
check: name,
|
|
96
110
|
status: 'WARN',
|
|
@@ -69,6 +69,27 @@ function detectInstallState(context) {
|
|
|
69
69
|
return { installed: false };
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Detect whether doctor is running inside the framework's OWN source repo,
|
|
74
|
+
* as opposed to a user project that installed SINAPSE. In the source repo the
|
|
75
|
+
* root package.json name is exactly 'sinapse-ai'. User projects have their own
|
|
76
|
+
* name (with sinapse-ai under node_modules), so this never false-positives for
|
|
77
|
+
* them.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} projectRoot
|
|
80
|
+
* @returns {boolean}
|
|
81
|
+
*/
|
|
82
|
+
function detectFrameworkRepo(projectRoot) {
|
|
83
|
+
try {
|
|
84
|
+
const pkg = JSON.parse(
|
|
85
|
+
fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'),
|
|
86
|
+
);
|
|
87
|
+
return Boolean(pkg) && pkg.name === 'sinapse-ai';
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
72
93
|
const VALID_ON_ERROR = new Set(['fail', 'warn', 'skip']);
|
|
73
94
|
|
|
74
95
|
/**
|
|
@@ -134,6 +155,12 @@ async function runDoctorChecks(options = {}) {
|
|
|
134
155
|
const context = {
|
|
135
156
|
projectRoot,
|
|
136
157
|
frameworkRoot: path.resolve(__dirname, '..', '..', '..'),
|
|
158
|
+
// True when doctor runs inside the framework's OWN source repo (vs a user
|
|
159
|
+
// install). In the source repo some install-time artifacts are absent BY
|
|
160
|
+
// DESIGN — deny rules are off for contributors (frameworkProtection:false),
|
|
161
|
+
// hooks live in gitignored settings.local.json, and CLAUDE.md is the dev
|
|
162
|
+
// variant. Context checks degrade WARN→INFO here to avoid false alarms.
|
|
163
|
+
isFrameworkRepo: detectFrameworkRepo(projectRoot),
|
|
137
164
|
options: { fix, json, dryRun, quiet, deep, homeDir },
|
|
138
165
|
};
|
|
139
166
|
|
|
@@ -227,6 +227,10 @@ class BuildOrchestrator extends EventEmitter {
|
|
|
227
227
|
duration,
|
|
228
228
|
phases: ctx.phases,
|
|
229
229
|
reportPath: ctx.reportPath,
|
|
230
|
+
// F5 (epic: orchestration-consolidation): surface the real plan object so the
|
|
231
|
+
// quality gate can inspect its honesty (degraded/stub/subtasks). Without this
|
|
232
|
+
// the epic4_to_epic6 gate has nothing real to bite on.
|
|
233
|
+
plan: ctx.plan,
|
|
230
234
|
};
|
|
231
235
|
} catch (error) {
|
|
232
236
|
ctx.errors.push(error);
|
|
@@ -850,18 +854,120 @@ The subtask is complete only when verification passes.
|
|
|
850
854
|
}
|
|
851
855
|
|
|
852
856
|
/**
|
|
853
|
-
*
|
|
857
|
+
* Whether real planning-via-agent (spawning `claude`) is allowed.
|
|
858
|
+
*
|
|
859
|
+
* Mirrors {@link EpicExecutor#_realExecutionAllowed}: returns false inside the
|
|
860
|
+
* jest runner unless `SINAPSE_REAL_DISPATCH=1`. This guard is CRITICAL — the
|
|
861
|
+
* `claude` CLI IS on the PATH in this repo, so without it a `generatePlan()`
|
|
862
|
+
* call under unit tests would spawn the real CLI, burn the user's tokens and be
|
|
863
|
+
* non-deterministic.
|
|
864
|
+
*
|
|
865
|
+
* Honesty invariant (epic: orchestration-consolidation, F4): no path returns a
|
|
866
|
+
* "real" plan without doing real work. When this returns false, the caller
|
|
867
|
+
* falls back to a deterministic plan explicitly marked degraded/stub — never a
|
|
868
|
+
* fabricated plan passed off as agent-generated.
|
|
869
|
+
*
|
|
870
|
+
* @returns {boolean}
|
|
871
|
+
* @private
|
|
854
872
|
*/
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
873
|
+
_planningViaAgentAllowed() {
|
|
874
|
+
return (
|
|
875
|
+
process.env.JEST_WORKER_ID === undefined || process.env.SINAPSE_REAL_DISPATCH === '1'
|
|
876
|
+
);
|
|
877
|
+
}
|
|
859
878
|
|
|
860
|
-
|
|
879
|
+
/**
|
|
880
|
+
* Build the planning prompt sent to the `claude` CLI.
|
|
881
|
+
* Feeds the FULL story (prose + ACs) and asks for a structured JSON plan.
|
|
882
|
+
*
|
|
883
|
+
* @param {string} storyId
|
|
884
|
+
* @param {string} storyContent - Full raw story file content
|
|
885
|
+
* @returns {string}
|
|
886
|
+
*/
|
|
887
|
+
buildPlanPrompt(storyId, storyContent) {
|
|
888
|
+
return `You are a senior engineer producing an implementation plan for a development story.
|
|
861
889
|
|
|
862
|
-
|
|
863
|
-
|
|
890
|
+
## Story (${storyId})
|
|
891
|
+
${storyContent}
|
|
892
|
+
|
|
893
|
+
## Task
|
|
894
|
+
Analyze the FULL story above (prose AND acceptance criteria) and produce a structured implementation plan.
|
|
895
|
+
|
|
896
|
+
Respond with ONLY a JSON object (optionally inside a \`\`\`json fenced block), no prose before or after, in EXACTLY this shape:
|
|
897
|
+
|
|
898
|
+
{
|
|
899
|
+
"phases": [
|
|
900
|
+
{
|
|
901
|
+
"id": "phase-id",
|
|
902
|
+
"name": "Human-readable phase name",
|
|
903
|
+
"subtasks": [
|
|
904
|
+
{
|
|
905
|
+
"id": "1.1",
|
|
906
|
+
"description": "What to implement",
|
|
907
|
+
"files": ["path/to/file.js"],
|
|
908
|
+
"verification": "command or check that confirms this subtask is done"
|
|
909
|
+
}
|
|
910
|
+
]
|
|
911
|
+
}
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
Rules:
|
|
916
|
+
- Break the work into logical phases, each with concrete subtasks.
|
|
917
|
+
- Every subtask MUST have a stable id ("phase.subtask", e.g. "1.1"), a clear description, the files it will touch, and a verification step.
|
|
918
|
+
- Ground every subtask in the story's acceptance criteria — do not invent scope.`;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* Robustly parse a plan JSON object out of a raw `claude` response.
|
|
923
|
+
* Tolerates ```json fenced blocks and surrounding prose; returns null when no
|
|
924
|
+
* valid plan object can be extracted (caller then degrades honestly).
|
|
925
|
+
*
|
|
926
|
+
* @param {string} raw - Raw CLI stdout
|
|
927
|
+
* @returns {{phases: Array}|null}
|
|
928
|
+
*/
|
|
929
|
+
parsePlanResponse(raw) {
|
|
930
|
+
if (!raw || typeof raw !== 'string') {
|
|
931
|
+
return null;
|
|
932
|
+
}
|
|
933
|
+
let text = raw.trim();
|
|
934
|
+
|
|
935
|
+
// Prefer a fenced ```json ... ``` block when present.
|
|
936
|
+
const fenceMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
937
|
+
if (fenceMatch) {
|
|
938
|
+
text = fenceMatch[1].trim();
|
|
939
|
+
} else {
|
|
940
|
+
// Otherwise slice from the first `{` to the last `}` (drops surrounding prose).
|
|
941
|
+
const first = text.indexOf('{');
|
|
942
|
+
const last = text.lastIndexOf('}');
|
|
943
|
+
if (first !== -1 && last > first) {
|
|
944
|
+
text = text.slice(first, last + 1);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
864
947
|
|
|
948
|
+
try {
|
|
949
|
+
const obj = JSON.parse(text);
|
|
950
|
+
if (!obj || typeof obj !== 'object' || !Array.isArray(obj.phases)) {
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
return obj;
|
|
954
|
+
} catch {
|
|
955
|
+
return null;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* Build a deterministic, HONESTLY-DEGRADED plan from the story's ACs via regex.
|
|
961
|
+
* Always marked `degraded: true` / `stub: true` with a `reason` so the engine
|
|
962
|
+
* never passes a fallback off as a real agent-generated plan (F4 invariant).
|
|
963
|
+
*
|
|
964
|
+
* @param {Object} ctx
|
|
965
|
+
* @param {string[]} acMatches - Pre-extracted `- [ ] ACn:` lines
|
|
966
|
+
* @param {string} reason - Why we degraded (for honest reporting)
|
|
967
|
+
* @returns {Object}
|
|
968
|
+
* @private
|
|
969
|
+
*/
|
|
970
|
+
_degradedPlan(ctx, acMatches, reason) {
|
|
865
971
|
const subtasks = acMatches.map((ac, i) => ({
|
|
866
972
|
id: `1.${i + 1}`, // Format: phase.subtask (e.g., "1.1", "1.2")
|
|
867
973
|
description: ac.replace(/- \[ \] AC\d+:\s*/, ''),
|
|
@@ -872,6 +978,9 @@ The subtask is complete only when verification passes.
|
|
|
872
978
|
return {
|
|
873
979
|
storyId: ctx.storyId,
|
|
874
980
|
generatedAt: new Date().toISOString(),
|
|
981
|
+
degraded: true,
|
|
982
|
+
stub: true,
|
|
983
|
+
reason,
|
|
875
984
|
phases: [
|
|
876
985
|
{
|
|
877
986
|
id: 'implementation',
|
|
@@ -882,6 +991,81 @@ The subtask is complete only when verification passes.
|
|
|
882
991
|
};
|
|
883
992
|
}
|
|
884
993
|
|
|
994
|
+
/**
|
|
995
|
+
* Generate an implementation plan from a story.
|
|
996
|
+
*
|
|
997
|
+
* Honesty invariant (epic: orchestration-consolidation, F4):
|
|
998
|
+
* - AC1: when real execution is allowed → invoke `claude` over the FULL story
|
|
999
|
+
* and return a rich plan WITHOUT any stub/degraded mark.
|
|
1000
|
+
* - AC2: when real execution is NOT allowed (jest w/o SINAPSE_REAL_DISPATCH),
|
|
1001
|
+
* claude is unavailable/fails, or the response can't be parsed → fall back to
|
|
1002
|
+
* the deterministic regex plan, marked `degraded:true`/`stub:true` + `reason`.
|
|
1003
|
+
* Never throws here; the pipeline proceeds with a degraded plan.
|
|
1004
|
+
* - AC3: missing / empty / non-actionable story → throw explicitly.
|
|
1005
|
+
*
|
|
1006
|
+
* @param {Object} ctx - { storyId, storyPath, config, worktree? }
|
|
1007
|
+
* @returns {Promise<Object>} Plan ({ phases, ... }); degraded plans are marked.
|
|
1008
|
+
*/
|
|
1009
|
+
async generatePlan(ctx) {
|
|
1010
|
+
// AC3: explicit failure when there is no usable story file.
|
|
1011
|
+
if (!ctx || !ctx.storyPath || !fs.existsSync(ctx.storyPath)) {
|
|
1012
|
+
throw new Error(
|
|
1013
|
+
`generatePlan: story file not found (storyId=${ctx && ctx.storyId}, path=${ctx && ctx.storyPath})`,
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
const storyContent = fs.readFileSync(ctx.storyPath, 'utf-8');
|
|
1018
|
+
const trimmed = storyContent.trim();
|
|
1019
|
+
|
|
1020
|
+
// Deterministic AC extraction — shared by both the real and fallback paths.
|
|
1021
|
+
const acMatches = storyContent.match(/- \[ \] AC\d+:.*$/gm) || [];
|
|
1022
|
+
|
|
1023
|
+
// "Actionable" = has ACs OR meaningful prose (more than a bare heading).
|
|
1024
|
+
const proseWithoutHeadings = trimmed
|
|
1025
|
+
.split('\n')
|
|
1026
|
+
.filter((line) => !line.trim().startsWith('#'))
|
|
1027
|
+
.join('\n')
|
|
1028
|
+
.trim();
|
|
1029
|
+
const hasActionableContent = acMatches.length > 0 || proseWithoutHeadings.length >= 20;
|
|
1030
|
+
|
|
1031
|
+
// AC3: empty or non-actionable story → explicit error, never a silent empty plan.
|
|
1032
|
+
if (trimmed.length === 0 || !hasActionableContent) {
|
|
1033
|
+
throw new Error(
|
|
1034
|
+
`generatePlan: story has no actionable content (storyId=${ctx.storyId}, path=${ctx.storyPath})`,
|
|
1035
|
+
);
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// AC1: real planning path — guarded against burning tokens under jest.
|
|
1039
|
+
if (this._planningViaAgentAllowed()) {
|
|
1040
|
+
try {
|
|
1041
|
+
const prompt = this.buildPlanPrompt(ctx.storyId, storyContent);
|
|
1042
|
+
const workDir = (ctx.worktree && ctx.worktree.path) || this.rootPath;
|
|
1043
|
+
const cliResult = await this.runClaudeCLI(prompt, workDir, ctx.config || this.config);
|
|
1044
|
+
const stdout =
|
|
1045
|
+
typeof cliResult === 'string' ? cliResult : (cliResult && cliResult.stdout) || '';
|
|
1046
|
+
const parsed = this.parsePlanResponse(stdout);
|
|
1047
|
+
|
|
1048
|
+
if (parsed && Array.isArray(parsed.phases) && parsed.phases.length > 0) {
|
|
1049
|
+
// AC1: real plan — no stub/degraded mark.
|
|
1050
|
+
return {
|
|
1051
|
+
storyId: ctx.storyId,
|
|
1052
|
+
generatedAt: new Date().toISOString(),
|
|
1053
|
+
phases: parsed.phases,
|
|
1054
|
+
};
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
// AC2: unparseable / empty agent response → honest degraded fallback.
|
|
1058
|
+
return this._degradedPlan(ctx, acMatches, 'agent-response-unparseable');
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
// AC2: claude unavailable / spawn error / timeout → honest degraded fallback (no throw).
|
|
1061
|
+
return this._degradedPlan(ctx, acMatches, `agent-invocation-failed: ${err.message}`);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// AC2: real planning disabled (jest without SINAPSE_REAL_DISPATCH) → honest degraded fallback.
|
|
1066
|
+
return this._degradedPlan(ctx, acMatches, 'real-planning-disabled');
|
|
1067
|
+
}
|
|
1068
|
+
|
|
885
1069
|
/**
|
|
886
1070
|
* Format duration
|
|
887
1071
|
*/
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const {
|
|
3
|
+
const { spawnSync } = require('child_process');
|
|
4
|
+
// cross-spawn resolves Windows .cmd/.bat/.ps1 shims (e.g. an npm-global `codex.cmd`)
|
|
5
|
+
// that native child_process.spawn cannot launch without a shell — it throws ENOENT.
|
|
6
|
+
// It preserves detached + stdio + env semantics, so background spawning is unchanged.
|
|
7
|
+
const crossSpawn = require('cross-spawn');
|
|
4
8
|
|
|
5
9
|
const DEFAULT_RUN_DIR = '.sinapse/external-runs';
|
|
6
10
|
const SUPPORTED_SANDBOXES = new Set([
|
|
@@ -449,7 +453,7 @@ async function spawnExecutor(plan) {
|
|
|
449
453
|
};
|
|
450
454
|
|
|
451
455
|
try {
|
|
452
|
-
child =
|
|
456
|
+
child = crossSpawn(plan.command, plan.args, {
|
|
453
457
|
cwd: plan.options.workdir,
|
|
454
458
|
detached: !plan.options.foreground,
|
|
455
459
|
stdio: ['pipe', logFd, logFd],
|
|
@@ -15,7 +15,7 @@ const path = require('path');
|
|
|
15
15
|
const { BaseCheck, CheckSeverity, CheckDomain } = require('../../base-check');
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* Expected articles in Constitution v2.
|
|
18
|
+
* Expected articles in Constitution v2.2.0
|
|
19
19
|
* Source of truth: .sinapse-ai/constitution.md
|
|
20
20
|
*/
|
|
21
21
|
const EXPECTED_ARTICLES = [
|
|
@@ -29,6 +29,7 @@ const EXPECTED_ARTICLES = [
|
|
|
29
29
|
{ number: 'VIII', title: 'Mandatory Delegation', severity: 'NON-NEGOTIABLE' },
|
|
30
30
|
{ number: 'IX', title: 'Safe Collaboration', severity: 'NON-NEGOTIABLE' },
|
|
31
31
|
{ number: 'X', title: 'Security & Data Protection', severity: 'NON-NEGOTIABLE' },
|
|
32
|
+
{ number: 'XI', title: 'Conservative Default', severity: 'MUST' },
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
/**
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
const fs = require('fs');
|
|
10
10
|
const path = require('path');
|
|
11
|
-
|
|
11
|
+
// cross-spawn.sync resolves npm/npx to their Windows .cmd shims WITHOUT a shell.
|
|
12
|
+
// Native spawnSync('npm.cmd', ...) without shell:true returns EINVAL on modern Node
|
|
13
|
+
// (post CVE-2024-27980), silently no-op'ing the audit/madge checks on Windows.
|
|
14
|
+
const crossSpawn = require('cross-spawn');
|
|
12
15
|
|
|
13
16
|
// Import dependencies with fallbacks
|
|
14
17
|
const GOTCHAS_MEMORY_MODULE = '../memory/gotchas-memory';
|
|
@@ -622,10 +625,9 @@ class SecurityAnalyzer {
|
|
|
622
625
|
const findings = [];
|
|
623
626
|
|
|
624
627
|
try {
|
|
625
|
-
//
|
|
626
|
-
// exist but still prints the JSON report to stdout
|
|
627
|
-
const
|
|
628
|
-
const audit = spawnSync(npmCmd, ['audit', '--json'], {
|
|
628
|
+
// cross-spawn.sync resolves npm's Windows shim without a shell; npm exits
|
|
629
|
+
// non-zero when vulns exist but still prints the JSON report to stdout.
|
|
630
|
+
const audit = crossSpawn.sync('npm', ['audit', '--json'], {
|
|
629
631
|
cwd: this.rootPath,
|
|
630
632
|
encoding: 'utf8',
|
|
631
633
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -866,9 +868,9 @@ class ArchitectureAnalyzer {
|
|
|
866
868
|
const findings = [];
|
|
867
869
|
|
|
868
870
|
try {
|
|
869
|
-
//
|
|
870
|
-
|
|
871
|
-
const proc =
|
|
871
|
+
// cross-spawn.sync resolves npx's Windows shim without a shell (native
|
|
872
|
+
// spawnSync of npx.cmd without shell:true returns EINVAL on modern Node).
|
|
873
|
+
const proc = crossSpawn.sync('npx', ['madge', '--circular', '--warning', path.join(this.rootPath, 'src')], {
|
|
872
874
|
encoding: 'utf8',
|
|
873
875
|
timeout: 30000,
|
|
874
876
|
windowsHide: true,
|
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
createGlobalConfig,
|
|
20
20
|
} = require('./global-config-manager');
|
|
21
21
|
const { getProjectMcpPath, checkLinkStatus, LINK_STATUS, createLink } = require('./symlink-manager');
|
|
22
|
+
const { retrySync } = require('../synapse/utils/atomic-write');
|
|
22
23
|
|
|
23
24
|
/**
|
|
24
25
|
* Migration options
|
|
@@ -267,7 +268,8 @@ function executeMigration(projectRoot = process.cwd(), option = MIGRATION_OPTION
|
|
|
267
268
|
const backupPath = projectMcpPath + '.backup.' + Date.now();
|
|
268
269
|
|
|
269
270
|
try {
|
|
270
|
-
|
|
271
|
+
// retrySync: transient EPERM/EBUSY from AV / Search indexer on Windows.
|
|
272
|
+
retrySync(() => fs.renameSync(projectMcpPath, backupPath));
|
|
271
273
|
results.backupPath = backupPath;
|
|
272
274
|
} catch (error) {
|
|
273
275
|
results.errors.push(`Backup failed: ${error.message}`);
|
|
@@ -315,14 +317,15 @@ function restoreFromBackup(backupPath, projectRoot = process.cwd()) {
|
|
|
315
317
|
if (fs.existsSync(projectMcpPath)) {
|
|
316
318
|
const stats = fs.lstatSync(projectMcpPath);
|
|
317
319
|
if (stats.isSymbolicLink()) {
|
|
318
|
-
fs.unlinkSync(projectMcpPath);
|
|
320
|
+
retrySync(() => fs.unlinkSync(projectMcpPath));
|
|
319
321
|
} else {
|
|
320
|
-
fs.rmSync(projectMcpPath, { recursive: true });
|
|
322
|
+
retrySync(() => fs.rmSync(projectMcpPath, { recursive: true }));
|
|
321
323
|
}
|
|
322
324
|
}
|
|
323
325
|
|
|
324
|
-
// Restore backup
|
|
325
|
-
|
|
326
|
+
// Restore backup — retry transient Windows locks so a legit rollback
|
|
327
|
+
// isn't lost to a momentary AV/indexer handle on the config dir.
|
|
328
|
+
retrySync(() => fs.renameSync(backupPath, projectMcpPath));
|
|
326
329
|
|
|
327
330
|
return { success: true, restored: projectMcpPath };
|
|
328
331
|
} catch (error) {
|
|
@@ -181,7 +181,10 @@ function readGlobalConfig() {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
try {
|
|
184
|
-
|
|
184
|
+
// Strip a leading BOM: a global-config.json saved by a Windows editor
|
|
185
|
+
// (Notepad) starts with U+FEFF and would make JSON.parse throw, silently
|
|
186
|
+
// dropping the user's MCP global config via the catch below.
|
|
187
|
+
const content = fs.readFileSync(configPath, 'utf8').replace(/^\uFEFF/, '');
|
|
185
188
|
return JSON.parse(content);
|
|
186
189
|
} catch (error) {
|
|
187
190
|
console.error(`Error reading global config: ${error.message}`);
|
|
@@ -13,6 +13,7 @@ const fs = require('fs');
|
|
|
13
13
|
const path = require('path');
|
|
14
14
|
const { execSync } = require('child_process');
|
|
15
15
|
const { isWindows, getGlobalMcpDir, getLinkType } = require('./os-detector');
|
|
16
|
+
const { retrySync } = require('../synapse/utils/atomic-write');
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Link status types
|
|
@@ -284,7 +285,9 @@ function createLink(projectRoot = process.cwd(), options = {}) {
|
|
|
284
285
|
const configFile = path.join(linkPath, 'global-config.json');
|
|
285
286
|
if (fs.existsSync(configFile)) {
|
|
286
287
|
const backupPath = linkPath + '.backup.' + Date.now();
|
|
287
|
-
|
|
288
|
+
// retrySync: on Windows the rename of a dir held by AV / Search
|
|
289
|
+
// indexer / a concurrent reader throws transient EPERM/EBUSY.
|
|
290
|
+
retrySync(() => fs.renameSync(linkPath, backupPath));
|
|
288
291
|
return {
|
|
289
292
|
success: false,
|
|
290
293
|
error: `Existing config backed up to ${backupPath}. Run with --migrate to merge configs.`,
|
|
@@ -293,10 +296,10 @@ function createLink(projectRoot = process.cwd(), options = {}) {
|
|
|
293
296
|
backup: backupPath,
|
|
294
297
|
};
|
|
295
298
|
}
|
|
296
|
-
fs.rmSync(linkPath, { recursive: true });
|
|
299
|
+
retrySync(() => fs.rmSync(linkPath, { recursive: true }));
|
|
297
300
|
} else {
|
|
298
301
|
// Remove symlink/junction
|
|
299
|
-
fs.unlinkSync(linkPath);
|
|
302
|
+
retrySync(() => fs.unlinkSync(linkPath));
|
|
300
303
|
}
|
|
301
304
|
} catch (error) {
|
|
302
305
|
return {
|
|
@@ -10,8 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* Integrates all Epic 11 modules:
|
|
12
12
|
* - ExecutorAssignment (11.1) — agent selection
|
|
13
|
-
* -
|
|
14
|
-
* - WorkflowExecutor (11.3) — development cycle
|
|
13
|
+
* - WorkflowExecutor (11.3) — development cycle (honest manual hand-off)
|
|
15
14
|
* - SurfaceChecker (11.4) — human decision criteria
|
|
16
15
|
* - SessionState (11.5) — session persistence
|
|
17
16
|
*
|
|
@@ -1252,8 +1251,7 @@ class BobOrchestrator {
|
|
|
1252
1251
|
*
|
|
1253
1252
|
* Delegates to Epic 11 modules:
|
|
1254
1253
|
* - ExecutorAssignment for agent selection (AC8)
|
|
1255
|
-
* -
|
|
1256
|
-
* - WorkflowExecutor for development cycle (AC10)
|
|
1254
|
+
* - WorkflowExecutor for development cycle, with honest manual hand-off (AC10)
|
|
1257
1255
|
*
|
|
1258
1256
|
* Story 12.5 AC5: Updates session state at each phase transition.
|
|
1259
1257
|
*
|
|
@@ -352,13 +352,14 @@ Quer que eu comece?`;
|
|
|
352
352
|
// Record phase in session state
|
|
353
353
|
await this._recordPhase(BrownfieldPhase.SYSTEM_DOCUMENTATION, context);
|
|
354
354
|
|
|
355
|
-
//
|
|
355
|
+
// Hand the discovery workflow to the executor. executeWorkflow() loads and
|
|
356
|
+
// validates the workflow definition and returns a structured handoff; the
|
|
357
|
+
// per-phase documentation is produced by the agents the workflow assigns.
|
|
358
|
+
// Progress for those agent steps is tracked via _onPhaseStart/_onPhaseComplete/
|
|
359
|
+
// _onPhaseError + handlePhaseFailureAction as the agents report in.
|
|
356
360
|
const result = await workflowExecutor.executeWorkflow(this.workflowPath, {
|
|
357
361
|
projectRoot: this.projectRoot,
|
|
358
362
|
techStack: context.techStack || {},
|
|
359
|
-
onPhaseStart: (phase) => this._onPhaseStart(phase, context),
|
|
360
|
-
onPhaseComplete: (phase, output) => this._onPhaseComplete(phase, output, context),
|
|
361
|
-
onPhaseError: (phase, error) => this._onPhaseError(phase, error, context),
|
|
362
363
|
});
|
|
363
364
|
|
|
364
365
|
// Check if workflow completed successfully
|