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
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
const fs = require('fs-extra');
|
|
15
15
|
const path = require('path');
|
|
16
|
+
const yaml = require('js-yaml');
|
|
16
17
|
const EpicExecutor = require('./epic-executor');
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -115,6 +116,9 @@ class Epic4Executor extends EpicExecutor {
|
|
|
115
116
|
return this._completeExecution({
|
|
116
117
|
implementationPath: planPath,
|
|
117
118
|
planPath,
|
|
119
|
+
// F5 (epic: orchestration-consolidation): propagate the real plan object
|
|
120
|
+
// so the downstream epic4_to_epic6 gate can verify it is not degraded/stub.
|
|
121
|
+
plan: buildResult.plan,
|
|
118
122
|
build: buildResult,
|
|
119
123
|
reportPath: buildResult.reportPath,
|
|
120
124
|
phases: buildResult.phases,
|
|
@@ -212,44 +216,47 @@ class Epic4Executor extends EpicExecutor {
|
|
|
212
216
|
* @private
|
|
213
217
|
*/
|
|
214
218
|
async _createStubPlan(planPath, storyId, specPath) {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
219
|
+
const now = new Date().toISOString();
|
|
220
|
+
|
|
221
|
+
// Build the plan as an object and serialize via yaml.dump. This is robust to
|
|
222
|
+
// any content — notably Windows absolute paths in `specPath`
|
|
223
|
+
// (e.g. "C:\Users\...\AppData\...") which, when hand-written into a
|
|
224
|
+
// double-quoted YAML scalar, contain invalid escape sequences (`\U`, `\A`)
|
|
225
|
+
// that make `yaml.load` throw and kill the whole build path on Windows.
|
|
226
|
+
// yaml.dump escapes/quotes correctly for any value (Story: FIX windows-path-yaml-plan).
|
|
227
|
+
const planObject = {
|
|
228
|
+
metadata: {
|
|
229
|
+
storyId,
|
|
230
|
+
specPath: specPath || 'N/A',
|
|
231
|
+
status: 'draft',
|
|
232
|
+
createdAt: now,
|
|
233
|
+
},
|
|
234
|
+
phases: [
|
|
235
|
+
{
|
|
236
|
+
phase: 1,
|
|
237
|
+
name: 'Setup',
|
|
238
|
+
subtasks: [{ id: '1.1', name: 'Initialize project structure', status: 'pending' }],
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
phase: 2,
|
|
242
|
+
name: 'Implementation',
|
|
243
|
+
subtasks: [{ id: '2.1', name: 'Implement core functionality', status: 'pending' }],
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
phase: 3,
|
|
247
|
+
name: 'Testing',
|
|
248
|
+
subtasks: [{ id: '3.1', name: 'Write tests', status: 'pending' }],
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
phase: 4,
|
|
252
|
+
name: 'Documentation',
|
|
253
|
+
subtasks: [{ id: '4.1', name: 'Update documentation', status: 'pending' }],
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const header = `# Implementation Plan: ${storyId}\n# Generated: ${now}\n\n`;
|
|
259
|
+
const stubPlan = header + yaml.dump(planObject, { lineWidth: -1, noRefs: true });
|
|
253
260
|
|
|
254
261
|
await fs.ensureDir(path.dirname(planPath));
|
|
255
262
|
await fs.writeFile(planPath, stubPlan);
|
|
@@ -54,7 +54,9 @@ const DEFAULT_GATE_CONFIG = {
|
|
|
54
54
|
blocking: true,
|
|
55
55
|
requireTests: true,
|
|
56
56
|
minTestCoverage: 0,
|
|
57
|
-
|
|
57
|
+
// F5 (epic: orchestration-consolidation): `plan_is_real` gives this gate teeth —
|
|
58
|
+
// a degraded/stub/absent/subtask-less plan is BLOCKED, not waved through.
|
|
59
|
+
checks: ['plan_complete', 'plan_is_real', 'implementation_exists', 'no_critical_errors'],
|
|
58
60
|
},
|
|
59
61
|
};
|
|
60
62
|
|
|
@@ -148,11 +150,7 @@ class GateEvaluator {
|
|
|
148
150
|
const checks = await this._runGateChecks(fromEpic, toEpic, epicResult, gateConfig);
|
|
149
151
|
result.checks = checks;
|
|
150
152
|
|
|
151
|
-
//
|
|
152
|
-
const passedChecks = checks.filter((c) => c.passed).length;
|
|
153
|
-
result.score = checks.length > 0 ? (passedChecks / checks.length) * 5 : 5;
|
|
154
|
-
|
|
155
|
-
// Collect issues
|
|
153
|
+
// Collect issues from failed checks
|
|
156
154
|
result.issues = checks
|
|
157
155
|
.filter((c) => !c.passed)
|
|
158
156
|
.map((c) => ({
|
|
@@ -161,6 +159,22 @@ class GateEvaluator {
|
|
|
161
159
|
severity: c.severity || 'medium',
|
|
162
160
|
}));
|
|
163
161
|
|
|
162
|
+
// Calculate score — honesty invariant (F5, epic: orchestration-consolidation):
|
|
163
|
+
// a gate that evaluated ZERO checks verified NOTHING. It must NOT receive the
|
|
164
|
+
// max score (the old `: 5` was theater — an unconfigured gate always passed).
|
|
165
|
+
// Score 0 + an explicit issue so the verdict reflects "no real verification".
|
|
166
|
+
if (checks.length === 0) {
|
|
167
|
+
result.score = 0;
|
|
168
|
+
result.issues.push({
|
|
169
|
+
check: 'no_checks_evaluated',
|
|
170
|
+
message: 'Gate evaluated zero checks — nothing was actually verified',
|
|
171
|
+
severity: this.strictMode ? 'critical' : 'high',
|
|
172
|
+
});
|
|
173
|
+
} else {
|
|
174
|
+
const passedChecks = checks.filter((c) => c.passed).length;
|
|
175
|
+
result.score = (passedChecks / checks.length) * 5;
|
|
176
|
+
}
|
|
177
|
+
|
|
164
178
|
// Determine verdict (AC2)
|
|
165
179
|
result.verdict = this._determineVerdict(result, gateConfig);
|
|
166
180
|
|
|
@@ -188,6 +202,22 @@ class GateEvaluator {
|
|
|
188
202
|
async _runGateChecks(fromEpic, toEpic, epicResult, gateConfig) {
|
|
189
203
|
const checks = [];
|
|
190
204
|
|
|
205
|
+
// Universal honesty guard (master/gate leak fix, epic: orchestration-consolidation):
|
|
206
|
+
// a gate must NEVER approve a result that itself signals failure. The e2e checkpoint
|
|
207
|
+
// caught the gate approving (score 5.0) a QA report whose verdict was BLOCKED, because
|
|
208
|
+
// the existence checks (qa_report_exists / verdict_generated) never inspected the VALUE.
|
|
209
|
+
// This runs on EVERY gate, but ONLY adds a (failing, critical) check when a real failure
|
|
210
|
+
// signal is present — so it never inflates an honest zero-check gate (F5 invariant).
|
|
211
|
+
const failureSignal = this._detectFailureSignal(epicResult);
|
|
212
|
+
if (failureSignal) {
|
|
213
|
+
checks.push({
|
|
214
|
+
name: 'result_not_failed',
|
|
215
|
+
passed: false,
|
|
216
|
+
message: failureSignal,
|
|
217
|
+
severity: 'critical',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
191
221
|
// Get check list for this gate
|
|
192
222
|
const checkNames = gateConfig.checks || this._getDefaultChecks(fromEpic, toEpic);
|
|
193
223
|
|
|
@@ -240,6 +270,36 @@ class GateEvaluator {
|
|
|
240
270
|
return checks;
|
|
241
271
|
}
|
|
242
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Detect whether an epic result itself signals failure (master/gate leak fix).
|
|
275
|
+
*
|
|
276
|
+
* Returns a human-readable reason string when the result is NOT sound, or null when
|
|
277
|
+
* no failure signal is present. Used by `_runGateChecks` to add a critical, blocking
|
|
278
|
+
* check so a gate can never APPROVE a failed/blocked upstream result.
|
|
279
|
+
*
|
|
280
|
+
* @param {Object} epicResult - Result from the source epic
|
|
281
|
+
* @returns {string|null} Failure reason, or null if the result shows no failure signal
|
|
282
|
+
* @private
|
|
283
|
+
*/
|
|
284
|
+
_detectFailureSignal(epicResult) {
|
|
285
|
+
if (!epicResult || typeof epicResult !== 'object') {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
if (epicResult.success === false || epicResult.status === 'failed') {
|
|
289
|
+
return 'Epic result signals failure (success:false / status:failed)';
|
|
290
|
+
}
|
|
291
|
+
const norm = (v) => (typeof v === 'string' ? v.toLowerCase() : null);
|
|
292
|
+
const verdict = norm(epicResult.verdict);
|
|
293
|
+
if (verdict === 'blocked' || verdict === 'failed') {
|
|
294
|
+
return `Epic verdict is "${epicResult.verdict}"`;
|
|
295
|
+
}
|
|
296
|
+
const qaVerdict = epicResult.qaReport ? norm(epicResult.qaReport.verdict) : null;
|
|
297
|
+
if (qaVerdict === 'blocked' || qaVerdict === 'failed') {
|
|
298
|
+
return `QA report verdict is "${epicResult.qaReport.verdict}"`;
|
|
299
|
+
}
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
243
303
|
/**
|
|
244
304
|
* Run a single check
|
|
245
305
|
* @private
|
|
@@ -279,11 +339,46 @@ class GateEvaluator {
|
|
|
279
339
|
break;
|
|
280
340
|
|
|
281
341
|
// Epic 4 checks
|
|
282
|
-
case 'plan_complete':
|
|
283
|
-
|
|
342
|
+
case 'plan_complete': {
|
|
343
|
+
// F5: hardened but backward-compatible. When a real plan OBJECT is present
|
|
344
|
+
// (wired in via epic-4-executor), require real phases. When only a path/flag
|
|
345
|
+
// is present (legacy callers), keep the old signal so existing behavior holds.
|
|
346
|
+
const plan = epicResult.plan;
|
|
347
|
+
if (plan && typeof plan === 'object') {
|
|
348
|
+
result.passed = Array.isArray(plan.phases) && plan.phases.length > 0;
|
|
349
|
+
} else {
|
|
350
|
+
result.passed = !!epicResult.planPath || epicResult.planComplete === true;
|
|
351
|
+
}
|
|
284
352
|
result.message = result.passed ? 'Implementation plan complete' : 'Plan not complete';
|
|
285
353
|
result.severity = 'high';
|
|
286
354
|
break;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
case 'plan_is_real': {
|
|
358
|
+
// F5 (epic: orchestration-consolidation) — the gate's teeth. Honesty
|
|
359
|
+
// invariant: a degraded/stub/absent/subtask-less plan is NOT a real artifact
|
|
360
|
+
// and MUST block, not slip through. Critical severity → verdict BLOCKED.
|
|
361
|
+
const plan = epicResult.plan;
|
|
362
|
+
if (!plan || typeof plan !== 'object') {
|
|
363
|
+
result.passed = false;
|
|
364
|
+
result.message = 'No real plan object to inspect (plan absent)';
|
|
365
|
+
} else if (plan.degraded === true || plan.stub === true) {
|
|
366
|
+
result.passed = false;
|
|
367
|
+
result.message = `Plan is degraded/stub${plan.reason ? ` (${plan.reason})` : ''}`;
|
|
368
|
+
} else {
|
|
369
|
+
const phases = Array.isArray(plan.phases) ? plan.phases : [];
|
|
370
|
+
const subtaskCount = phases.reduce(
|
|
371
|
+
(n, p) => n + (Array.isArray(p.subtasks) ? p.subtasks.length : 0),
|
|
372
|
+
0,
|
|
373
|
+
);
|
|
374
|
+
result.passed = phases.length > 0 && subtaskCount > 0;
|
|
375
|
+
result.message = result.passed
|
|
376
|
+
? `Plan is real (${phases.length} phase(s), ${subtaskCount} subtask(s))`
|
|
377
|
+
: 'Plan has no subtasks';
|
|
378
|
+
}
|
|
379
|
+
result.severity = 'critical';
|
|
380
|
+
break;
|
|
381
|
+
}
|
|
287
382
|
|
|
288
383
|
case 'implementation_exists':
|
|
289
384
|
result.passed = !!epicResult.implementationPath || epicResult.codeChanges?.length > 0;
|
|
@@ -342,7 +437,7 @@ class GateEvaluator {
|
|
|
342
437
|
case 3:
|
|
343
438
|
return ['spec_exists', 'complexity_assessed'];
|
|
344
439
|
case 4:
|
|
345
|
-
return ['plan_complete', 'no_critical_errors'];
|
|
440
|
+
return ['plan_complete', 'plan_is_real', 'no_critical_errors'];
|
|
346
441
|
case 6:
|
|
347
442
|
return ['qa_report_exists', 'verdict_generated'];
|
|
348
443
|
default:
|
|
@@ -624,62 +624,30 @@ class GreenfieldHandler extends EventEmitter {
|
|
|
624
624
|
// ═══════════════════════════════════════════════════════════════════════════════════
|
|
625
625
|
|
|
626
626
|
/**
|
|
627
|
-
*
|
|
627
|
+
* Resolves agent execution to an honest manual hand-off (AC6 selection only).
|
|
628
|
+
*
|
|
629
|
+
* The legacy visual-terminal lineage (TerminalSpawner → pm.sh) was a verified stub that
|
|
630
|
+
* never invoked claude, so spawning it fabricated success in headless-with-bash. It has
|
|
631
|
+
* been removed (STORY-F3C); execution is now handed off honestly to the user. Routing to
|
|
632
|
+
* the canonical `dispatcher → claude` lineage is intentionally out of scope here.
|
|
628
633
|
*
|
|
629
634
|
* @param {string} agent - Agent ID (e.g., '@devops')
|
|
630
635
|
* @param {string} task - Task to execute
|
|
631
636
|
* @param {Object} spawnContext - Spawn context
|
|
632
|
-
* @returns {Promise<Object>}
|
|
637
|
+
* @returns {Promise<Object>} Honest manual hand-off result
|
|
633
638
|
* @private
|
|
634
639
|
*/
|
|
635
640
|
async _spawnAgent(agent, task, spawnContext = {}) {
|
|
636
|
-
this._log(`
|
|
641
|
+
this._log(`Handing off ${agent} for ${task} (manual execution)`);
|
|
637
642
|
|
|
638
643
|
this.emit('agentSpawn', { agent, task, context: spawnContext });
|
|
639
644
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
const result = await TerminalSpawner.spawnAgent(agentId, task, {
|
|
647
|
-
context: {
|
|
648
|
-
instructions: spawnContext.instructions || `Execute ${task}`,
|
|
649
|
-
creates: spawnContext.creates || [],
|
|
650
|
-
requires: spawnContext.requires || [],
|
|
651
|
-
metadata: spawnContext.previousResults || {},
|
|
652
|
-
},
|
|
653
|
-
timeout: 7200000, // 2 hours
|
|
654
|
-
debug: this.options.debug,
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
if (result.pid) {
|
|
658
|
-
this.emit('terminalSpawn', { agent, pid: result.pid, task });
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
return {
|
|
662
|
-
success: result.success !== false,
|
|
663
|
-
pid: result.pid,
|
|
664
|
-
output: result.output,
|
|
665
|
-
outputFile: result.outputFile,
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
// Fallback: Return instructions for manual execution
|
|
670
|
-
this._log(`TerminalSpawner not available, returning manual instructions for ${agent}`);
|
|
671
|
-
return {
|
|
672
|
-
success: true,
|
|
673
|
-
manual: true,
|
|
674
|
-
instructions: `Spawn ${agent} manually and execute: *${task}`,
|
|
675
|
-
};
|
|
676
|
-
} catch (error) {
|
|
677
|
-
this._log(`Failed to spawn ${agent}: ${error.message}`, 'error');
|
|
678
|
-
return {
|
|
679
|
-
success: false,
|
|
680
|
-
error: error.message,
|
|
681
|
-
};
|
|
682
|
-
}
|
|
645
|
+
// Honest hand-off: return instructions for manual execution (no fabricated success).
|
|
646
|
+
return {
|
|
647
|
+
success: true,
|
|
648
|
+
manual: true,
|
|
649
|
+
instructions: `Spawn ${agent} manually and execute: *${task}`,
|
|
650
|
+
};
|
|
683
651
|
}
|
|
684
652
|
|
|
685
653
|
// ═══════════════════════════════════════════════════════════════════════════════════
|
|
@@ -41,9 +41,6 @@ const cliCommands = require('./cli-commands');
|
|
|
41
41
|
// Story 11.1: Executor Assignment (Projeto Bob)
|
|
42
42
|
const ExecutorAssignment = require('./executor-assignment');
|
|
43
43
|
|
|
44
|
-
// Story 11.2: Terminal Spawner (Projeto Bob)
|
|
45
|
-
const TerminalSpawner = require('./terminal-spawner');
|
|
46
|
-
|
|
47
44
|
// Story 11.3: Workflow Executor (Projeto Bob)
|
|
48
45
|
const {
|
|
49
46
|
WorkflowExecutor,
|
|
@@ -216,15 +213,6 @@ module.exports = {
|
|
|
216
213
|
validateExecutorAssignment: ExecutorAssignment.validateExecutorAssignment,
|
|
217
214
|
EXECUTOR_ASSIGNMENT_TABLE: ExecutorAssignment.EXECUTOR_ASSIGNMENT_TABLE,
|
|
218
215
|
|
|
219
|
-
// Story 11.2: Terminal Spawner (Projeto Bob)
|
|
220
|
-
TerminalSpawner,
|
|
221
|
-
spawnAgent: TerminalSpawner.spawnAgent,
|
|
222
|
-
createContextFile: TerminalSpawner.createContextFile,
|
|
223
|
-
pollForOutput: TerminalSpawner.pollForOutput,
|
|
224
|
-
isSpawnerAvailable: TerminalSpawner.isSpawnerAvailable,
|
|
225
|
-
getPlatform: TerminalSpawner.getPlatform,
|
|
226
|
-
cleanupOldFiles: TerminalSpawner.cleanupOldFiles,
|
|
227
|
-
|
|
228
216
|
// Story 11.3: Workflow Executor (Projeto Bob)
|
|
229
217
|
WorkflowExecutor,
|
|
230
218
|
createWorkflowExecutor,
|
|
@@ -478,10 +478,15 @@ class MasterOrchestrator extends EventEmitter {
|
|
|
478
478
|
} else {
|
|
479
479
|
pipelineResult.epicsFailed.push(epicNum);
|
|
480
480
|
|
|
481
|
-
//
|
|
481
|
+
// Honesty invariant (master/gate leak fix): ANY failed epic means the
|
|
482
|
+
// pipeline did not fully succeed — not only critical/strict ones. A
|
|
483
|
+
// non-critical failure (e.g. QA/Epic 6) must still flip success:false so
|
|
484
|
+
// finalize() never reports an overall green build over a red epic.
|
|
485
|
+
pipelineResult.success = false;
|
|
486
|
+
|
|
487
|
+
// In strict mode or if epic is critical, also STOP the pipeline now.
|
|
482
488
|
if (this.strictGates || this._isEpicCritical(epicNum)) {
|
|
483
489
|
this._log(`Critical epic ${epicNum} failed, halting pipeline`);
|
|
484
|
-
pipelineResult.success = false;
|
|
485
490
|
break;
|
|
486
491
|
}
|
|
487
492
|
}
|
|
@@ -604,6 +609,45 @@ class MasterOrchestrator extends EventEmitter {
|
|
|
604
609
|
orchestrator: this,
|
|
605
610
|
});
|
|
606
611
|
|
|
612
|
+
// Honesty invariant (epic: orchestration-consolidation — master/gate leak fix):
|
|
613
|
+
// an executor may signal failure by RETURNING { success:false } / { status:'failed' }
|
|
614
|
+
// WITHOUT throwing. The old code fell straight through to "mark COMPLETED" + logged
|
|
615
|
+
// "completed successfully" + returned { success:true } for any non-stub result — so a
|
|
616
|
+
// failed epic leaked a green pipeline (the e2e "Epic 4 failed" → "Epic 4 completed
|
|
617
|
+
// successfully" → exit 0 symptom). The `catch` below only handles THROWN errors, so a
|
|
618
|
+
// returned failure must be detected explicitly here and treated as a real failure.
|
|
619
|
+
const isStubResult = result && result.status === 'stub';
|
|
620
|
+
const isFailedResult =
|
|
621
|
+
result && !isStubResult && (result.success === false || result.status === 'failed');
|
|
622
|
+
|
|
623
|
+
if (isFailedResult) {
|
|
624
|
+
this.executionState.epics[epicNum] = {
|
|
625
|
+
...this.executionState.epics[epicNum],
|
|
626
|
+
status: EpicStatus.FAILED,
|
|
627
|
+
completedAt: new Date().toISOString(),
|
|
628
|
+
result,
|
|
629
|
+
errors: [
|
|
630
|
+
...(this.executionState.epics[epicNum]?.errors || []),
|
|
631
|
+
{
|
|
632
|
+
message: result.error || `Epic ${epicNum} returned a non-success result`,
|
|
633
|
+
timestamp: new Date().toISOString(),
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
await this._saveState();
|
|
639
|
+
|
|
640
|
+
this.emit('epicComplete', { epicNum, result, gateResult: null });
|
|
641
|
+
this.onEpicComplete(epicNum, result);
|
|
642
|
+
|
|
643
|
+
this._log(`Epic ${epicNum} failed (executor returned non-success result)`, {
|
|
644
|
+
level: 'error',
|
|
645
|
+
icon: '❌',
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
return { success: false, status: 'failed', epicNum, result };
|
|
649
|
+
}
|
|
650
|
+
|
|
607
651
|
// Mark as completed
|
|
608
652
|
this.executionState.epics[epicNum] = {
|
|
609
653
|
...this.executionState.epics[epicNum],
|
|
@@ -614,8 +658,8 @@ class MasterOrchestrator extends EventEmitter {
|
|
|
614
658
|
|
|
615
659
|
// Evaluate quality gate (Story 0.6) - only in full pipeline mode
|
|
616
660
|
// Skip gate evaluation if result is from stub executor
|
|
661
|
+
// (isStubResult already computed above with the failure-detection guard).
|
|
617
662
|
let gateResult = null;
|
|
618
|
-
const isStubResult = result && result.status === 'stub';
|
|
619
663
|
if (this._inFullPipeline && result && result.success !== false && !isStubResult) {
|
|
620
664
|
gateResult = await this._evaluateGate(epicNum, result);
|
|
621
665
|
|
|
@@ -1486,13 +1530,25 @@ class MasterOrchestrator extends EventEmitter {
|
|
|
1486
1530
|
const seconds = Math.floor((duration % 60000) / 1000);
|
|
1487
1531
|
|
|
1488
1532
|
const hasStubs = pipelineResult.hasStubs || (pipelineResult.epicsStubbed || []).length > 0;
|
|
1533
|
+
// Honesty invariant (master/gate leak fix): a pipeline with ANY failed epic, or a
|
|
1534
|
+
// final state of BLOCKED/FAILED, can never report success:true — even if a stale
|
|
1535
|
+
// optimistic flag survived. `blocked` is surfaced so the CLI shows BLOCKED (exit 2)
|
|
1536
|
+
// instead of "ORCHESTRATION COMPLETE" / exit 0.
|
|
1537
|
+
const hasFailures = (pipelineResult.epicsFailed || []).length > 0;
|
|
1538
|
+
const blocked = this._state === OrchestratorState.BLOCKED;
|
|
1489
1539
|
return {
|
|
1490
1540
|
workflowId: this.executionState.workflowId,
|
|
1491
1541
|
storyId: this.storyId,
|
|
1492
1542
|
status: this._state,
|
|
1543
|
+
blocked,
|
|
1493
1544
|
// Honesty invariant (epic: orchestration-consolidation, F0a): a pipeline that ran
|
|
1494
1545
|
// any epic in STUB mode did NOT really build anything — it must not report success:true.
|
|
1495
|
-
|
|
1546
|
+
// A failed epic or a non-COMPLETE terminal state is likewise never a success.
|
|
1547
|
+
success:
|
|
1548
|
+
(pipelineResult.success ?? this._state === OrchestratorState.COMPLETE) &&
|
|
1549
|
+
!hasStubs &&
|
|
1550
|
+
!hasFailures &&
|
|
1551
|
+
!blocked,
|
|
1496
1552
|
mode: hasStubs ? 'stub' : 'real',
|
|
1497
1553
|
stubbedEpics: pipelineResult.epicsStubbed || [],
|
|
1498
1554
|
...(hasStubs
|
|
@@ -20,6 +20,23 @@ const fsSync = require('fs');
|
|
|
20
20
|
const path = require('path');
|
|
21
21
|
const yaml = require('js-yaml');
|
|
22
22
|
|
|
23
|
+
// On Windows a concurrent reader / AV / Search indexer can hold a transient lock
|
|
24
|
+
// that makes fs.rename throw EPERM/EBUSY where POSIX would succeed. A short
|
|
25
|
+
// bounded retry clears virtually all of these so persistence degrades gracefully.
|
|
26
|
+
const TRANSIENT_LOCK_CODES = new Set(['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY']);
|
|
27
|
+
async function renameWithRetry(oldPath, newPath, retries = 3, delayMs = 120) {
|
|
28
|
+
for (let attempt = 0; ; attempt++) {
|
|
29
|
+
try {
|
|
30
|
+
return await fs.rename(oldPath, newPath);
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if (!TRANSIENT_LOCK_CODES.has(err.code) || attempt >= retries) {
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs * (attempt + 1)));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
23
40
|
// Constants
|
|
24
41
|
const SESSION_STATE_VERSION = '1.2';
|
|
25
42
|
const SESSION_STATE_FILENAME = '.session-state.yaml';
|
|
@@ -729,7 +746,7 @@ O que você quer fazer?
|
|
|
729
746
|
for (const file of stateFiles) {
|
|
730
747
|
const oldPath = path.join(this.legacyStatePath, file);
|
|
731
748
|
const newPath = path.join(this.legacyStatePath, `${file}.migrated`);
|
|
732
|
-
await
|
|
749
|
+
await renameWithRetry(oldPath, newPath);
|
|
733
750
|
}
|
|
734
751
|
|
|
735
752
|
if (this.options.debug) {
|
|
@@ -775,7 +792,7 @@ O que você quer fazer?
|
|
|
775
792
|
if (await this.exists()) {
|
|
776
793
|
// Archive instead of delete
|
|
777
794
|
const archivePath = `${this.stateFilePath}.discarded.${Date.now()}`;
|
|
778
|
-
await
|
|
795
|
+
await renameWithRetry(this.stateFilePath, archivePath);
|
|
779
796
|
|
|
780
797
|
if (this.options.debug) {
|
|
781
798
|
console.log(`[SessionState] Session archived to: ${archivePath}`);
|