specweave 1.0.506 → 1.0.508
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-plugin/README.md +25 -32
- package/.claude-plugin/marketplace.json +1 -78
- package/dist/plugins/specweave/lib/features/release/dashboard-generator.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/features/release/dashboard-generator.js.map +1 -0
- package/dist/plugins/specweave/lib/features/release/dora-tracker.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/features/release/dora-tracker.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.d.ts +44 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.js +236 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-board-resolver.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-client-v2.d.ts +139 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-client-v2.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-client-v2.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-client.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-client.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.d.ts +100 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.js +292 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-permission-gate.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-permission-gate.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-profile-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-profile-resolver.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-pull-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-pull-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-rate-limiter.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-rate-limiter.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.d.ts +38 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.js +210 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.d.ts +28 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.js +300 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-sync.d.ts +147 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-sync.js +749 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-spec-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-status-sync.d.ts +79 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-status-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-status-sync.js +162 -0
- package/dist/plugins/specweave/lib/integrations/ado/ado-status-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/conflict-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/conflict-resolver.js +439 -0
- package/dist/plugins/specweave/lib/integrations/ado/conflict-resolver.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/per-us-sync.d.ts +131 -0
- package/dist/plugins/specweave/lib/integrations/ado/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/ado/per-us-sync.js +322 -0
- package/dist/plugins/specweave/lib/integrations/ado/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/CodeValidator.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/CodeValidator.js +219 -0
- package/dist/plugins/specweave/lib/integrations/github/CodeValidator.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/IssueStateManager.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/IssueStateManager.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/completion-calculator.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/completion-calculator.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/duplicate-detector.js +423 -0
- package/dist/plugins/specweave/lib/integrations/github/duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.d.ts +54 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.js +305 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-comment-poster.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-comment-poster.js +232 -0
- package/dist/plugins/specweave/lib/integrations/github/github-ac-comment-poster.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-batch-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-batch-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-board-resolver-v2.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-board-resolver-v2.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts +214 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js +812 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client-v2.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-client.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-conflict-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-conflict-resolver.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-cross-repo-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-cross-repo-sync.js +172 -0
- package/dist/plugins/specweave/lib/integrations/github/github-cross-repo-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-feature-sync-cli.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-feature-sync-cli.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-feature-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-feature-sync.js +1112 -0
- package/dist/plugins/specweave/lib/integrations/github/github-feature-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-field-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-field-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-graphql-client.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-graphql-client.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-body-generator.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-body-generator.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-body-parser.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-body-parser.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-updater.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-updater.js +339 -0
- package/dist/plugins/specweave/lib/integrations/github/github-issue-updater.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-pull-sync.d.ts +94 -0
- package/dist/plugins/specweave/lib/integrations/github/github-pull-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-pull-sync.js +232 -0
- package/dist/plugins/specweave/lib/integrations/github/github-pull-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-push-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-push-sync.js +127 -0
- package/dist/plugins/specweave/lib/integrations/github/github-push-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-rate-limiter.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-rate-limiter.js +109 -0
- package/dist/plugins/specweave/lib/integrations/github/github-rate-limiter.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-commit-sync.d.ts +37 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-commit-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-commit-sync.js +209 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-commit-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-content-sync.d.ts +28 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-content-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-content-sync.js +365 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-content-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-frontmatter-updater.d.ts +21 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-frontmatter-updater.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-frontmatter-updater.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-sync.d.ts +225 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-sync.js +974 -0
- package/dist/plugins/specweave/lib/integrations/github/github-spec-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-sync-orchestrator.d.ts +47 -0
- package/dist/plugins/specweave/lib/integrations/github/github-sync-orchestrator.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-sync-orchestrator.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-us-auto-closer.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/github-us-auto-closer.js +219 -0
- package/dist/plugins/specweave/lib/integrations/github/github-us-auto-closer.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/index.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/index.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/per-us-sync.d.ts +126 -0
- package/dist/plugins/specweave/lib/integrations/github/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/per-us-sync.js +394 -0
- package/dist/plugins/specweave/lib/integrations/github/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/progress-comment-builder.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/progress-comment-builder.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/types.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/types.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/user-story-content-builder.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/user-story-content-builder.js +310 -0
- package/dist/plugins/specweave/lib/integrations/github/user-story-content-builder.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/user-story-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/github/user-story-issue-builder.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/content-format-adapter.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/content-format-adapter.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.d.ts +47 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.js +307 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-board-resolver.d.ts +50 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-board-resolver.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-deployment-detector.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-deployment-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.d.ts +103 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.js +295 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-epic-sync.d.ts +67 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-epic-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-epic-sync.js +286 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-epic-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-field-discovery.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-field-discovery.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-paginated-search.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-paginated-search.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-permission-gate.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-permission-gate.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.d.ts +43 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.js +284 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.d.ts +33 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.js +294 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-sync.d.ts +180 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-sync.js +757 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-spec-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-status-sync.d.ts +116 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-status-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-status-sync.js +302 -0
- package/dist/plugins/specweave/lib/integrations/jira/jira-status-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/metadata-paths.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/metadata-paths.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/per-us-sync.d.ts +117 -0
- package/dist/plugins/specweave/lib/integrations/jira/per-us-sync.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/per-us-sync.js +274 -0
- package/dist/plugins/specweave/lib/integrations/jira/per-us-sync.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/reorganization-detector.d.ts +80 -0
- package/dist/plugins/specweave/lib/integrations/jira/reorganization-detector.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/reorganization-detector.js.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/setup-wizard.d.ts +29 -0
- package/dist/plugins/specweave/lib/integrations/jira/setup-wizard.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/integrations/jira/setup-wizard.js +198 -0
- package/dist/plugins/specweave/lib/integrations/jira/setup-wizard.js.map +1 -0
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +1 -1
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js +2 -2
- package/dist/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.js +9 -1
- package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
- package/dist/src/cli/commands/sync-progress.js +1 -1
- package/dist/src/cli/commands/sync-progress.js.map +1 -1
- package/dist/src/cli/helpers/async-project-loader.js +1 -1
- package/dist/src/cli/helpers/async-project-loader.js.map +1 -1
- package/dist/src/cli/helpers/cancelation-handler.d.ts +1 -1
- package/dist/src/cli/helpers/cancelation-handler.js +1 -1
- package/dist/src/cli/helpers/init/ado-repo-cloning.js +1 -1
- package/dist/src/cli/helpers/init/ado-repo-cloning.js.map +1 -1
- package/dist/src/cli/helpers/init/github-repo-cloning.js +1 -1
- package/dist/src/cli/helpers/init/github-repo-cloning.js.map +1 -1
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +2 -2
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +2 -2
- package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -1
- package/dist/src/cli/helpers/init/plugin-installer.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/plugin-installer.js +11 -3
- package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado.js +3 -3
- package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js +1 -1
- package/dist/src/cli/helpers/issue-tracker/github-multi-repo.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/github.js +4 -4
- package/dist/src/cli/helpers/issue-tracker/github.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js +1 -1
- package/dist/src/cli/helpers/issue-tracker/index.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js +1 -1
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js.map +1 -1
- package/dist/src/core/ac-progress-sync.js +5 -5
- package/dist/src/core/ac-progress-sync.js.map +1 -1
- package/dist/src/core/analytics/types.d.ts +1 -1
- package/dist/src/core/analytics/types.d.ts.map +1 -1
- package/dist/src/core/config/types.d.ts +1 -1
- package/dist/src/core/hooks/github-project-sync.js +4 -4
- package/dist/src/core/hooks/github-project-sync.js.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +5 -5
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/types/plugin.d.ts +1 -1
- package/dist/src/core/types/plugin.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client-factory.d.ts +1 -1
- package/dist/src/integrations/ado/ado-client-factory.d.ts.map +1 -1
- package/dist/src/integrations/ado/ado-client-factory.js +1 -1
- package/dist/src/integrations/ado/ado-client-factory.js.map +1 -1
- package/dist/src/integrations/ado/ado-dependency-loader.js +1 -1
- package/dist/src/integrations/ado/ado-dependency-loader.js.map +1 -1
- package/dist/src/living-docs/smart-doc-organizer.js +1 -1
- package/dist/src/living-docs/smart-doc-organizer.js.map +1 -1
- package/dist/src/sync/ado-reconciler.d.ts +1 -1
- package/dist/src/sync/ado-reconciler.js +1 -1
- package/dist/src/sync/external-change-puller.js +1 -1
- package/dist/src/sync/external-change-puller.js.map +1 -1
- package/dist/src/sync/external-issue-auto-creator.js +1 -1
- package/dist/src/sync/external-issue-auto-creator.js.map +1 -1
- package/dist/src/sync/external-item-sync-service.js +2 -2
- package/dist/src/sync/external-item-sync-service.js.map +1 -1
- package/dist/src/sync/format-preservation-sync.d.ts +1 -1
- package/dist/src/sync/format-preservation-sync.d.ts.map +1 -1
- package/dist/src/sync/format-preservation-sync.js +1 -1
- package/dist/src/sync/format-preservation-sync.js.map +1 -1
- package/dist/src/sync/github-reconciler.d.ts +1 -1
- package/dist/src/sync/github-reconciler.js +2 -2
- package/dist/src/sync/github-reconciler.js.map +1 -1
- package/dist/src/sync/github-sync-wrapper.d.ts +2 -2
- package/dist/src/sync/github-sync-wrapper.d.ts.map +1 -1
- package/dist/src/sync/github-sync-wrapper.js +1 -1
- package/dist/src/sync/github-sync-wrapper.js.map +1 -1
- package/dist/src/sync/jira-reconciler.d.ts +1 -1
- package/dist/src/sync/jira-reconciler.js +1 -1
- package/dist/src/sync/living-docs-updater.d.ts +1 -1
- package/dist/src/sync/living-docs-updater.d.ts.map +1 -1
- package/dist/src/sync/living-docs-updater.js +1 -1
- package/dist/src/sync/living-docs-updater.js.map +1 -1
- package/dist/src/sync/pr-linker.js +1 -1
- package/dist/src/sync/pr-linker.js.map +1 -1
- package/dist/src/sync/providers/github.d.ts +1 -1
- package/dist/src/sync/providers/github.js +1 -1
- package/dist/src/sync/sync-coordinator.js +4 -4
- package/dist/src/sync/sync-coordinator.js.map +1 -1
- package/dist/src/utils/cleanup-stale-plugins.d.ts.map +1 -1
- package/dist/src/utils/cleanup-stale-plugins.js +7 -0
- package/dist/src/utils/cleanup-stale-plugins.js.map +1 -1
- package/dist/src/utils/docs-validator.js +1 -1
- package/dist/src/utils/docs-validator.js.map +1 -1
- package/dist/src/utils/plugin-copier.d.ts +16 -0
- package/dist/src/utils/plugin-copier.d.ts.map +1 -1
- package/dist/src/utils/plugin-copier.js +79 -0
- package/dist/src/utils/plugin-copier.js.map +1 -1
- package/package.json +1 -1
- package/plugins/PLUGINS-INDEX.md +23 -42
- package/plugins/specweave/.claude-plugin/plugin.json +9 -2
- package/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.js +241 -0
- package/plugins/specweave/lib/integrations/ado/ado-ac-checkbox-sync.ts +311 -0
- package/plugins/specweave/lib/integrations/ado/ado-client-v2.d.ts +134 -0
- package/plugins/specweave/lib/integrations/ado/ado-client-v2.ts +742 -0
- package/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.js +279 -0
- package/plugins/specweave/lib/integrations/ado/ado-duplicate-detector.ts +408 -0
- package/plugins/specweave/lib/integrations/ado/ado-hierarchical-sync.d.ts +40 -0
- package/plugins/specweave/lib/integrations/ado/ado-hierarchical-sync.js +300 -0
- package/plugins/specweave/lib/integrations/ado/ado-hierarchical-sync.ts +554 -0
- package/plugins/specweave/lib/integrations/ado/ado-multi-project-sync.js +486 -0
- package/plugins/specweave/lib/integrations/ado/ado-multi-project-sync.ts +675 -0
- package/plugins/specweave/lib/integrations/ado/ado-project-detector.js +502 -0
- package/plugins/specweave/lib/integrations/ado/ado-project-detector.ts +560 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.d.ts +38 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.js +189 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-commit-sync.ts +288 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.js +249 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-content-sync.ts +379 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-sync.d.ts +100 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-sync.js +681 -0
- package/plugins/specweave/lib/integrations/ado/ado-spec-sync.ts +893 -0
- package/plugins/specweave/lib/integrations/ado/ado-status-sync.js +150 -0
- package/plugins/specweave/lib/integrations/ado/ado-status-sync.ts +213 -0
- package/plugins/specweave/lib/integrations/ado/conflict-resolver.js +400 -0
- package/plugins/specweave/lib/integrations/ado/conflict-resolver.ts +583 -0
- package/plugins/specweave/lib/integrations/ado/per-us-sync.js +272 -0
- package/plugins/specweave/lib/integrations/ado/per-us-sync.ts +457 -0
- package/plugins/specweave/lib/integrations/ado/project-selector.d.ts +42 -0
- package/plugins/specweave/lib/integrations/ado/project-selector.ts +304 -0
- package/plugins/specweave/lib/integrations/github/CodeValidator.js +195 -0
- package/plugins/specweave/lib/integrations/github/CodeValidator.ts +284 -0
- package/plugins/specweave/lib/integrations/github/duplicate-detector.js +397 -0
- package/plugins/specweave/lib/integrations/github/duplicate-detector.ts +561 -0
- package/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.js +287 -0
- package/plugins/specweave/lib/integrations/github/github-ac-checkbox-sync.ts +391 -0
- package/plugins/specweave/lib/integrations/github/github-ac-comment-poster.js +191 -0
- package/plugins/specweave/lib/integrations/github/github-ac-comment-poster.ts +315 -0
- package/plugins/specweave/lib/integrations/github/github-board-resolver.js +81 -0
- package/plugins/specweave/lib/integrations/github/github-board-resolver.ts +175 -0
- package/plugins/specweave/lib/integrations/github/github-client-v2.js +814 -0
- package/plugins/specweave/lib/integrations/github/github-client-v2.ts +1035 -0
- package/plugins/specweave/lib/integrations/github/github-cross-repo-sync.js +182 -0
- package/plugins/specweave/lib/integrations/github/github-cross-repo-sync.ts +265 -0
- package/plugins/specweave/lib/integrations/github/github-feature-sync.js +1007 -0
- package/plugins/specweave/lib/integrations/github/github-feature-sync.ts +1403 -0
- package/plugins/specweave/lib/integrations/github/github-hierarchical-sync.d.ts +29 -0
- package/plugins/specweave/lib/integrations/github/github-hierarchical-sync.js +190 -0
- package/plugins/specweave/lib/integrations/github/github-hierarchical-sync.ts +355 -0
- package/plugins/specweave/lib/integrations/github/github-issue-updater.js +275 -0
- package/plugins/specweave/lib/integrations/github/github-issue-updater.ts +462 -0
- package/plugins/specweave/lib/integrations/github/github-multi-project-sync.js +409 -0
- package/plugins/specweave/lib/integrations/github/github-multi-project-sync.ts +555 -0
- package/plugins/specweave/lib/integrations/github/github-pull-sync.js +185 -0
- package/plugins/specweave/lib/integrations/github/github-pull-sync.ts +343 -0
- package/plugins/specweave/lib/integrations/github/github-push-sync.js +129 -0
- package/plugins/specweave/lib/integrations/github/github-push-sync.ts +188 -0
- package/plugins/specweave/lib/integrations/github/github-rate-limiter.js +96 -0
- package/plugins/specweave/lib/integrations/github/github-rate-limiter.ts +143 -0
- package/plugins/specweave/lib/integrations/github/github-spec-commit-sync.d.ts +37 -0
- package/plugins/specweave/lib/integrations/github/github-spec-commit-sync.js +186 -0
- package/plugins/specweave/lib/integrations/github/github-spec-commit-sync.ts +285 -0
- package/plugins/specweave/lib/integrations/github/github-spec-content-sync.js +298 -0
- package/plugins/specweave/lib/integrations/github/github-spec-content-sync.ts +465 -0
- package/plugins/specweave/lib/integrations/github/github-spec-frontmatter-updater.ts +306 -0
- package/plugins/specweave/lib/integrations/github/github-spec-sync.d.ts +108 -0
- package/plugins/specweave/lib/integrations/github/github-spec-sync.js +900 -0
- package/plugins/specweave/lib/integrations/github/github-spec-sync.ts +1281 -0
- package/plugins/specweave/lib/integrations/github/github-sync-orchestrator.ts +158 -0
- package/plugins/specweave/lib/integrations/github/github-us-auto-closer.js +190 -0
- package/plugins/specweave/lib/integrations/github/github-us-auto-closer.ts +313 -0
- package/plugins/specweave/lib/integrations/github/per-us-sync.js +330 -0
- package/plugins/specweave/lib/integrations/github/per-us-sync.ts +515 -0
- package/plugins/specweave/lib/integrations/github/user-story-content-builder.js +306 -0
- package/plugins/specweave/lib/integrations/github/user-story-content-builder.ts +424 -0
- package/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.js +300 -0
- package/plugins/specweave/lib/integrations/jira/jira-ac-checkbox-sync.ts +380 -0
- package/plugins/specweave/lib/integrations/jira/jira-board-resolver.d.ts +50 -0
- package/plugins/specweave/lib/integrations/jira/jira-board-resolver.ts +127 -0
- package/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.js +279 -0
- package/plugins/specweave/lib/integrations/jira/jira-duplicate-detector.ts +420 -0
- package/plugins/specweave/lib/integrations/jira/jira-epic-sync.js +314 -0
- package/plugins/specweave/lib/integrations/jira/jira-epic-sync.ts +474 -0
- package/plugins/specweave/lib/integrations/jira/jira-hierarchical-sync.d.ts +33 -0
- package/plugins/specweave/lib/integrations/jira/jira-hierarchical-sync.js +144 -0
- package/plugins/specweave/lib/integrations/jira/jira-hierarchical-sync.ts +294 -0
- package/plugins/specweave/lib/integrations/jira/jira-multi-project-sync.js +279 -0
- package/plugins/specweave/lib/integrations/jira/jira-multi-project-sync.ts +398 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.d.ts +43 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.js +262 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-commit-sync.ts +370 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.js +260 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-content-sync.ts +367 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-sync.d.ts +105 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-sync.js +689 -0
- package/plugins/specweave/lib/integrations/jira/jira-spec-sync.ts +947 -0
- package/plugins/specweave/lib/integrations/jira/jira-status-sync.js +215 -0
- package/plugins/specweave/lib/integrations/jira/jira-status-sync.ts +375 -0
- package/plugins/specweave/lib/integrations/jira/per-us-sync.js +235 -0
- package/plugins/specweave/lib/integrations/jira/per-us-sync.ts +384 -0
- package/plugins/specweave/lib/integrations/jira/project-selector.d.ts +42 -0
- package/plugins/specweave/lib/integrations/jira/project-selector.ts +310 -0
- package/plugins/specweave/lib/integrations/jira/reorganization-detector.d.ts +67 -0
- package/plugins/specweave/lib/integrations/jira/reorganization-detector.ts +449 -0
- package/plugins/specweave/lib/integrations/jira/setup-wizard.d.js +4 -0
- package/plugins/specweave/lib/integrations/jira/setup-wizard.d.ts +29 -0
- package/plugins/specweave/lib/integrations/jira/setup-wizard.js +156 -0
- package/plugins/specweave/lib/integrations/jira/setup-wizard.ts +238 -0
- package/plugins/specweave/lib/vendor/sync/github-reconciler.d.ts +1 -1
- package/plugins/specweave/lib/vendor/sync/github-reconciler.js +2 -2
- package/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -1
- package/plugins/specweave/skills/team-lead/SKILL.md +10 -5
- package/plugins/specweave/skills/team-lead/agents/brainstorm-advocate.md +12 -6
- package/plugins/specweave/skills/team-lead/agents/brainstorm-critic.md +12 -6
- package/plugins/specweave/skills/team-lead/agents/brainstorm-pragmatist.md +12 -6
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts +0 -44
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +0 -236
- package/dist/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-client-v2.d.ts +0 -139
- package/dist/plugins/specweave-ado/lib/ado-client-v2.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-client-v2.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-client.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-client.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts +0 -100
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js +0 -292
- package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-permission-gate.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-permission-gate.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-profile-resolver.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-profile-resolver.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-pull-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-pull-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-rate-limiter.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-rate-limiter.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts +0 -38
- package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.js +0 -210
- package/dist/plugins/specweave-ado/lib/ado-spec-commit-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts +0 -28
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +0 -300
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts +0 -147
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js +0 -749
- package/dist/plugins/specweave-ado/lib/ado-spec-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts +0 -79
- package/dist/plugins/specweave-ado/lib/ado-status-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js +0 -162
- package/dist/plugins/specweave-ado/lib/ado-status-sync.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/conflict-resolver.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/conflict-resolver.js +0 -439
- package/dist/plugins/specweave-ado/lib/conflict-resolver.js.map +0 -1
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts +0 -131
- package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/per-us-sync.js +0 -322
- package/dist/plugins/specweave-ado/lib/per-us-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/CodeValidator.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/CodeValidator.js +0 -219
- package/dist/plugins/specweave-github/lib/CodeValidator.js.map +0 -1
- package/dist/plugins/specweave-github/lib/IssueStateManager.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/IssueStateManager.js.map +0 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.js.map +0 -1
- package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/duplicate-detector.js +0 -423
- package/dist/plugins/specweave-github/lib/duplicate-detector.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.d.ts +0 -54
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js +0 -305
- package/dist/plugins/specweave-github/lib/github-ac-checkbox-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js +0 -232
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-batch-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-batch-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +0 -214
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +0 -812
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-client.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-client.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js +0 -172
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync-cli.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync-cli.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +0 -1112
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-field-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-field-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-graphql-client.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-graphql-client.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-updater.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-issue-updater.js +0 -339
- package/dist/plugins/specweave-github/lib/github-issue-updater.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts +0 -94
- package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-pull-sync.js +0 -232
- package/dist/plugins/specweave-github/lib/github-pull-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-push-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-push-sync.js +0 -127
- package/dist/plugins/specweave-github/lib/github-push-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-rate-limiter.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-rate-limiter.js +0 -109
- package/dist/plugins/specweave-github/lib/github-rate-limiter.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-commit-sync.d.ts +0 -37
- package/dist/plugins/specweave-github/lib/github-spec-commit-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-commit-sync.js +0 -209
- package/dist/plugins/specweave-github/lib/github-spec-commit-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts +0 -28
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +0 -365
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts +0 -21
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-sync.d.ts +0 -225
- package/dist/plugins/specweave-github/lib/github-spec-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-spec-sync.js +0 -974
- package/dist/plugins/specweave-github/lib/github-spec-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts +0 -47
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.js +0 -219
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.js.map +0 -1
- package/dist/plugins/specweave-github/lib/index.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/index.js.map +0 -1
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts +0 -126
- package/dist/plugins/specweave-github/lib/per-us-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/per-us-sync.js +0 -394
- package/dist/plugins/specweave-github/lib/per-us-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +0 -1
- package/dist/plugins/specweave-github/lib/types.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/types.js.map +0 -1
- package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js +0 -310
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +0 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/content-format-adapter.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/content-format-adapter.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts +0 -47
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +0 -307
- package/dist/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts +0 -50
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-deployment-detector.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-deployment-detector.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts +0 -103
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js +0 -295
- package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts +0 -67
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js +0 -286
- package/dist/plugins/specweave-jira/lib/jira-epic-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-field-discovery.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-field-discovery.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-paginated-search.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-paginated-search.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-permission-gate.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts +0 -43
- package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.js +0 -284
- package/dist/plugins/specweave-jira/lib/jira-spec-commit-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.d.ts +0 -33
- package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.js +0 -294
- package/dist/plugins/specweave-jira/lib/jira-spec-content-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts +0 -180
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js +0 -757
- package/dist/plugins/specweave-jira/lib/jira-spec-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts +0 -116
- package/dist/plugins/specweave-jira/lib/jira-status-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js +0 -302
- package/dist/plugins/specweave-jira/lib/jira-status-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/metadata-paths.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/metadata-paths.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts +0 -117
- package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/per-us-sync.js +0 -274
- package/dist/plugins/specweave-jira/lib/per-us-sync.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/reorganization-detector.d.ts +0 -80
- package/dist/plugins/specweave-jira/lib/reorganization-detector.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/reorganization-detector.js.map +0 -1
- package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts +0 -29
- package/dist/plugins/specweave-jira/lib/setup-wizard.d.ts.map +0 -1
- package/dist/plugins/specweave-jira/lib/setup-wizard.js +0 -198
- package/dist/plugins/specweave-jira/lib/setup-wizard.js.map +0 -1
- package/dist/plugins/specweave-release/lib/dashboard-generator.d.ts.map +0 -1
- package/dist/plugins/specweave-release/lib/dashboard-generator.js.map +0 -1
- package/dist/plugins/specweave-release/lib/dora-tracker.d.ts.map +0 -1
- package/dist/plugins/specweave-release/lib/dora-tracker.js.map +0 -1
- package/plugins/specweave-ado/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-ado/PLUGIN.md +0 -39
- package/plugins/specweave-ado/hooks/README.md +0 -201
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.js +0 -241
- package/plugins/specweave-ado/lib/ado-ac-checkbox-sync.ts +0 -311
- package/plugins/specweave-ado/lib/ado-client-v2.d.ts +0 -134
- package/plugins/specweave-ado/lib/ado-client-v2.ts +0 -742
- package/plugins/specweave-ado/lib/ado-duplicate-detector.js +0 -279
- package/plugins/specweave-ado/lib/ado-duplicate-detector.ts +0 -408
- package/plugins/specweave-ado/lib/ado-hierarchical-sync.d.ts +0 -40
- package/plugins/specweave-ado/lib/ado-hierarchical-sync.js +0 -300
- package/plugins/specweave-ado/lib/ado-hierarchical-sync.ts +0 -554
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -486
- package/plugins/specweave-ado/lib/ado-multi-project-sync.ts +0 -675
- package/plugins/specweave-ado/lib/ado-project-detector.js +0 -502
- package/plugins/specweave-ado/lib/ado-project-detector.ts +0 -560
- package/plugins/specweave-ado/lib/ado-spec-commit-sync.d.ts +0 -38
- package/plugins/specweave-ado/lib/ado-spec-commit-sync.js +0 -189
- package/plugins/specweave-ado/lib/ado-spec-commit-sync.ts +0 -288
- package/plugins/specweave-ado/lib/ado-spec-content-sync.js +0 -249
- package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +0 -379
- package/plugins/specweave-ado/lib/ado-spec-sync.d.ts +0 -100
- package/plugins/specweave-ado/lib/ado-spec-sync.js +0 -681
- package/plugins/specweave-ado/lib/ado-spec-sync.ts +0 -893
- package/plugins/specweave-ado/lib/ado-status-sync.js +0 -150
- package/plugins/specweave-ado/lib/ado-status-sync.ts +0 -213
- package/plugins/specweave-ado/lib/conflict-resolver.js +0 -400
- package/plugins/specweave-ado/lib/conflict-resolver.ts +0 -583
- package/plugins/specweave-ado/lib/per-us-sync.js +0 -272
- package/plugins/specweave-ado/lib/per-us-sync.ts +0 -457
- package/plugins/specweave-ado/lib/project-selector.d.ts +0 -42
- package/plugins/specweave-ado/lib/project-selector.ts +0 -304
- package/plugins/specweave-diagrams/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-diagrams/PLUGIN.md +0 -32
- package/plugins/specweave-docs/.claude-plugin/plugin.json +0 -10
- package/plugins/specweave-docs/PLUGIN.md +0 -27
- package/plugins/specweave-github/.claude-plugin/plugin.json +0 -19
- package/plugins/specweave-github/MULTI-PROJECT-SYNC-ARCHITECTURE.md +0 -744
- package/plugins/specweave-github/PLUGIN.md +0 -29
- package/plugins/specweave-github/SYNC-ARCHITECTURE-FIX-SUMMARY.md +0 -302
- package/plugins/specweave-github/hooks/README.md +0 -289
- package/plugins/specweave-github/lib/CodeValidator.js +0 -195
- package/plugins/specweave-github/lib/CodeValidator.ts +0 -284
- package/plugins/specweave-github/lib/duplicate-detector.js +0 -397
- package/plugins/specweave-github/lib/duplicate-detector.ts +0 -561
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.js +0 -287
- package/plugins/specweave-github/lib/github-ac-checkbox-sync.ts +0 -391
- package/plugins/specweave-github/lib/github-ac-comment-poster.js +0 -191
- package/plugins/specweave-github/lib/github-ac-comment-poster.ts +0 -315
- package/plugins/specweave-github/lib/github-board-resolver.js +0 -81
- package/plugins/specweave-github/lib/github-board-resolver.ts +0 -175
- package/plugins/specweave-github/lib/github-client-v2.js +0 -814
- package/plugins/specweave-github/lib/github-client-v2.ts +0 -1035
- package/plugins/specweave-github/lib/github-cross-repo-sync.js +0 -182
- package/plugins/specweave-github/lib/github-cross-repo-sync.ts +0 -265
- package/plugins/specweave-github/lib/github-feature-sync.js +0 -1007
- package/plugins/specweave-github/lib/github-feature-sync.ts +0 -1403
- package/plugins/specweave-github/lib/github-hierarchical-sync.d.ts +0 -29
- package/plugins/specweave-github/lib/github-hierarchical-sync.js +0 -190
- package/plugins/specweave-github/lib/github-hierarchical-sync.ts +0 -355
- package/plugins/specweave-github/lib/github-issue-updater.js +0 -275
- package/plugins/specweave-github/lib/github-issue-updater.ts +0 -462
- package/plugins/specweave-github/lib/github-multi-project-sync.js +0 -409
- package/plugins/specweave-github/lib/github-multi-project-sync.ts +0 -555
- package/plugins/specweave-github/lib/github-pull-sync.js +0 -185
- package/plugins/specweave-github/lib/github-pull-sync.ts +0 -343
- package/plugins/specweave-github/lib/github-push-sync.js +0 -129
- package/plugins/specweave-github/lib/github-push-sync.ts +0 -188
- package/plugins/specweave-github/lib/github-rate-limiter.js +0 -96
- package/plugins/specweave-github/lib/github-rate-limiter.ts +0 -143
- package/plugins/specweave-github/lib/github-spec-commit-sync.d.ts +0 -37
- package/plugins/specweave-github/lib/github-spec-commit-sync.js +0 -186
- package/plugins/specweave-github/lib/github-spec-commit-sync.ts +0 -285
- package/plugins/specweave-github/lib/github-spec-content-sync.js +0 -298
- package/plugins/specweave-github/lib/github-spec-content-sync.ts +0 -465
- package/plugins/specweave-github/lib/github-spec-frontmatter-updater.ts +0 -306
- package/plugins/specweave-github/lib/github-spec-sync.d.ts +0 -108
- package/plugins/specweave-github/lib/github-spec-sync.js +0 -900
- package/plugins/specweave-github/lib/github-spec-sync.ts +0 -1281
- package/plugins/specweave-github/lib/github-sync-orchestrator.ts +0 -158
- package/plugins/specweave-github/lib/github-us-auto-closer.js +0 -190
- package/plugins/specweave-github/lib/github-us-auto-closer.ts +0 -313
- package/plugins/specweave-github/lib/per-us-sync.js +0 -330
- package/plugins/specweave-github/lib/per-us-sync.ts +0 -515
- package/plugins/specweave-github/lib/user-story-content-builder.js +0 -306
- package/plugins/specweave-github/lib/user-story-content-builder.ts +0 -424
- package/plugins/specweave-jira/.claude-plugin/plugin.json +0 -20
- package/plugins/specweave-jira/PLUGIN.md +0 -28
- package/plugins/specweave-jira/hooks/README.md +0 -201
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.js +0 -300
- package/plugins/specweave-jira/lib/jira-ac-checkbox-sync.ts +0 -380
- package/plugins/specweave-jira/lib/jira-board-resolver.d.ts +0 -50
- package/plugins/specweave-jira/lib/jira-board-resolver.ts +0 -127
- package/plugins/specweave-jira/lib/jira-duplicate-detector.js +0 -279
- package/plugins/specweave-jira/lib/jira-duplicate-detector.ts +0 -420
- package/plugins/specweave-jira/lib/jira-epic-sync.js +0 -314
- package/plugins/specweave-jira/lib/jira-epic-sync.ts +0 -474
- package/plugins/specweave-jira/lib/jira-hierarchical-sync.d.ts +0 -33
- package/plugins/specweave-jira/lib/jira-hierarchical-sync.js +0 -144
- package/plugins/specweave-jira/lib/jira-hierarchical-sync.ts +0 -294
- package/plugins/specweave-jira/lib/jira-multi-project-sync.js +0 -279
- package/plugins/specweave-jira/lib/jira-multi-project-sync.ts +0 -398
- package/plugins/specweave-jira/lib/jira-spec-commit-sync.d.ts +0 -43
- package/plugins/specweave-jira/lib/jira-spec-commit-sync.js +0 -262
- package/plugins/specweave-jira/lib/jira-spec-commit-sync.ts +0 -370
- package/plugins/specweave-jira/lib/jira-spec-content-sync.js +0 -260
- package/plugins/specweave-jira/lib/jira-spec-content-sync.ts +0 -367
- package/plugins/specweave-jira/lib/jira-spec-sync.d.ts +0 -105
- package/plugins/specweave-jira/lib/jira-spec-sync.js +0 -689
- package/plugins/specweave-jira/lib/jira-spec-sync.ts +0 -947
- package/plugins/specweave-jira/lib/jira-status-sync.js +0 -215
- package/plugins/specweave-jira/lib/jira-status-sync.ts +0 -375
- package/plugins/specweave-jira/lib/per-us-sync.js +0 -235
- package/plugins/specweave-jira/lib/per-us-sync.ts +0 -384
- package/plugins/specweave-jira/lib/project-selector.d.ts +0 -42
- package/plugins/specweave-jira/lib/project-selector.ts +0 -310
- package/plugins/specweave-jira/lib/reorganization-detector.d.ts +0 -67
- package/plugins/specweave-jira/lib/reorganization-detector.ts +0 -449
- package/plugins/specweave-jira/lib/setup-wizard.d.js +0 -4
- package/plugins/specweave-jira/lib/setup-wizard.d.ts +0 -29
- package/plugins/specweave-jira/lib/setup-wizard.js +0 -156
- package/plugins/specweave-jira/lib/setup-wizard.ts +0 -238
- package/plugins/specweave-media/.claude-plugin/plugin.json +0 -24
- package/plugins/specweave-media/PLUGIN.md +0 -37
- package/plugins/specweave-media/test-providers.sh +0 -308
- package/plugins/specweave-release/.claude-plugin/plugin.json +0 -29
- package/plugins/specweave-release/IMPLEMENTATION.md +0 -446
- package/plugins/specweave-release/PLUGIN.md +0 -38
- package/plugins/specweave-release/README.md +0 -508
- package/plugins/specweave-release/hooks/post-task-completion.sh +0 -113
- /package/dist/plugins/{specweave-release/lib → specweave/lib/features/release}/dashboard-generator.d.ts +0 -0
- /package/dist/plugins/{specweave-release/lib → specweave/lib/features/release}/dashboard-generator.js +0 -0
- /package/dist/plugins/{specweave-release/lib → specweave/lib/features/release}/dora-tracker.d.ts +0 -0
- /package/dist/plugins/{specweave-release/lib → specweave/lib/features/release}/dora-tracker.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client-v2.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-permission-gate.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-permission-gate.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-profile-resolver.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-profile-resolver.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-pull-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-pull-sync.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-rate-limiter.d.ts +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-rate-limiter.js +0 -0
- /package/dist/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/conflict-resolver.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/CodeValidator.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/IssueStateManager.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/IssueStateManager.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/completion-calculator.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/completion-calculator.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/duplicate-detector.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-ac-comment-poster.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-batch-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-batch-sync.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver-v2.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver-v2.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-conflict-resolver.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-conflict-resolver.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-cross-repo-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-feature-sync-cli.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-feature-sync-cli.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-feature-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-field-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-field-sync.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-graphql-client.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-graphql-client.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-generator.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-generator.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-parser.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-parser.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-updater.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-push-sync.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-rate-limiter.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-frontmatter-updater.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-sync-orchestrator.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-us-auto-closer.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/progress-comment-builder.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/progress-comment-builder.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.js +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/user-story-content-builder.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/user-story-issue-builder.d.ts +0 -0
- /package/dist/plugins/{specweave-github/lib → specweave/lib/integrations/github}/user-story-issue-builder.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/content-format-adapter.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/content-format-adapter.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-board-resolver.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-deployment-detector.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-deployment-detector.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-field-discovery.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-field-discovery.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-paginated-search.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-paginated-search.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-permission-gate.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-permission-gate.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/metadata-paths.d.ts +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/metadata-paths.js +0 -0
- /package/dist/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/reorganization-detector.js +0 -0
- /package/plugins/{specweave-ado/commands/cleanup-duplicates.md → specweave/commands/ado-cleanup-duplicates.md} +0 -0
- /package/plugins/{specweave-ado/commands/clone.md → specweave/commands/ado-clone.md} +0 -0
- /package/plugins/{specweave-ado/commands/close.md → specweave/commands/ado-close.md} +0 -0
- /package/plugins/{specweave-ado/commands/create.md → specweave/commands/ado-create.md} +0 -0
- /package/plugins/{specweave-ado/commands/import-areas.md → specweave/commands/ado-import-areas.md} +0 -0
- /package/plugins/{specweave-ado/commands/import-projects.md → specweave/commands/ado-import-projects.md} +0 -0
- /package/plugins/{specweave-ado/commands/pull.md → specweave/commands/ado-pull.md} +0 -0
- /package/plugins/{specweave-ado/commands/push.md → specweave/commands/ado-push.md} +0 -0
- /package/plugins/{specweave-ado/commands/reconcile.md → specweave/commands/ado-reconcile.md} +0 -0
- /package/plugins/{specweave-ado/commands/status.md → specweave/commands/ado-status.md} +0 -0
- /package/plugins/{specweave-ado/commands/sync.md → specweave/commands/ado-sync.md} +0 -0
- /package/plugins/{specweave-diagrams → specweave}/commands/diagrams-generate.md +0 -0
- /package/plugins/{specweave-docs/commands/build.md → specweave/commands/docs-build.md} +0 -0
- /package/plugins/{specweave-docs/commands/generate.md → specweave/commands/docs-generate.md} +0 -0
- /package/plugins/{specweave-docs/commands/health.md → specweave/commands/docs-health.md} +0 -0
- /package/plugins/{specweave-docs/commands/init.md → specweave/commands/docs-init.md} +0 -0
- /package/plugins/{specweave-docs/commands/organize.md → specweave/commands/docs-organize.md} +0 -0
- /package/plugins/{specweave-docs/commands/validate.md → specweave/commands/docs-validate.md} +0 -0
- /package/plugins/{specweave-docs/commands/view.md → specweave/commands/docs-view.md} +0 -0
- /package/plugins/{specweave-github/commands/cleanup-duplicates.md → specweave/commands/github-cleanup-duplicates.md} +0 -0
- /package/plugins/{specweave-github/commands/clone.md → specweave/commands/github-clone.md} +0 -0
- /package/plugins/{specweave-github/commands/close.md → specweave/commands/github-close.md} +0 -0
- /package/plugins/{specweave-github/commands/create.md → specweave/commands/github-create.md} +0 -0
- /package/plugins/{specweave-github/commands/pull.md → specweave/commands/github-pull.md} +0 -0
- /package/plugins/{specweave-github/commands/push.md → specweave/commands/github-push.md} +0 -0
- /package/plugins/{specweave-github/commands/reconcile.md → specweave/commands/github-reconcile.md} +0 -0
- /package/plugins/{specweave-github/commands/status.md → specweave/commands/github-status.md} +0 -0
- /package/plugins/{specweave-github/commands/sync.md → specweave/commands/github-sync.md} +0 -0
- /package/plugins/{specweave-github/commands/update-user-story.md → specweave/commands/github-update-user-story.md} +0 -0
- /package/plugins/{specweave-jira/commands/cleanup-duplicates.md → specweave/commands/jira-cleanup-duplicates.md} +0 -0
- /package/plugins/{specweave-jira/commands/close.md → specweave/commands/jira-close.md} +0 -0
- /package/plugins/{specweave-jira/commands/create.md → specweave/commands/jira-create.md} +0 -0
- /package/plugins/{specweave-jira/commands/import-boards.md → specweave/commands/jira-import-boards.md} +0 -0
- /package/plugins/{specweave-jira/commands/import-projects-full.md → specweave/commands/jira-import-projects-full.md} +0 -0
- /package/plugins/{specweave-jira/commands/import-projects.md → specweave/commands/jira-import-projects.md} +0 -0
- /package/plugins/{specweave-jira/commands/pull.md → specweave/commands/jira-pull.md} +0 -0
- /package/plugins/{specweave-jira/commands/push.md → specweave/commands/jira-push.md} +0 -0
- /package/plugins/{specweave-jira/commands/reconcile.md → specweave/commands/jira-reconcile.md} +0 -0
- /package/plugins/{specweave-jira/commands/status.md → specweave/commands/jira-status.md} +0 -0
- /package/plugins/{specweave-jira/commands/sync.md → specweave/commands/jira-sync.md} +0 -0
- /package/plugins/{specweave-release/commands/align.md → specweave/commands/release-align.md} +0 -0
- /package/plugins/{specweave-release/commands/init.md → specweave/commands/release-init.md} +0 -0
- /package/plugins/{specweave-release/commands/npm.md → specweave/commands/release-npm.md} +0 -0
- /package/plugins/{specweave-release/commands/platform.md → specweave/commands/release-platform.md} +0 -0
- /package/plugins/{specweave-release/commands/rc.md → specweave/commands/release-rc.md} +0 -0
- /package/plugins/{specweave-ado/hooks/post-living-docs-update.sh → specweave/hooks/v2/integrations/ado-post-living-docs-update.sh} +0 -0
- /package/plugins/{specweave-ado/hooks/post-task-completion.sh → specweave/hooks/v2/integrations/ado-post-task.sh} +0 -0
- /package/plugins/{specweave-github/hooks → specweave/hooks/v2/integrations}/github-auto-create-handler.sh +0 -0
- /package/plugins/{specweave-github/hooks/post-task-completion.sh → specweave/hooks/v2/integrations/github-post-task.sh} +0 -0
- /package/plugins/{specweave-jira/hooks/post-task-completion.sh → specweave/hooks/v2/integrations/jira-post-task.sh} +0 -0
- /package/plugins/{specweave-release/lib → specweave/lib/features/release}/dashboard-generator.js +0 -0
- /package/plugins/{specweave-release/lib → specweave/lib/features/release}/dashboard-generator.ts +0 -0
- /package/plugins/{specweave-release/lib → specweave/lib/features/release}/dora-tracker.js +0 -0
- /package/plugins/{specweave-release/lib → specweave/lib/features/release}/dora-tracker.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.d.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-board-resolver.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client-v2.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client-v2.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client-v2.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client-v2.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.d.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-client.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-hierarchical-sync.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-hierarchical-sync.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-hierarchical-sync.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-permission-gate.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-permission-gate.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-profile-resolver.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-profile-resolver.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-pull-sync.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-pull-sync.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-rate-limiter.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-rate-limiter.ts +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-commit-sync.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-commit-sync.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-commit-sync.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-sync.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-sync.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/ado-spec-sync.js.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/project-selector.d.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/project-selector.d.ts.map +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/project-selector.js +0 -0
- /package/plugins/{specweave-ado/lib → specweave/lib/integrations/ado}/project-selector.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/IssueStateManager.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/IssueStateManager.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/completion-calculator.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/completion-calculator.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-batch-sync.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-batch-sync.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver-v2.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver-v2.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-board-resolver.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-client.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-conflict-resolver.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-conflict-resolver.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-feature-sync-cli.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-feature-sync-cli.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-field-sync.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-field-sync.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-graphql-client.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-graphql-client.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-hierarchical-sync.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-hierarchical-sync.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-hierarchical-sync.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-generator.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-generator.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-parser.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-body-parser.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-updater.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-updater.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-updater.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-issue-updater.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-commit-sync.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-commit-sync.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-commit-sync.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-frontmatter-updater.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-sync.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-sync.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-spec-sync.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/github-sync-orchestrator.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/index.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/progress-comment-builder.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/progress-comment-builder.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/repo-selector.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.d.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.d.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.d.ts.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.js.map +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/types.ts +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/user-story-issue-builder.js +0 -0
- /package/plugins/{specweave-github/lib → specweave/lib/integrations/github}/user-story-issue-builder.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/content-format-adapter.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/content-format-adapter.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-board-resolver.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-board-resolver.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-board-resolver.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-board-resolver.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-deployment-detector.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-deployment-detector.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-field-discovery.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-field-discovery.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-hierarchical-sync.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-hierarchical-sync.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-hierarchical-sync.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-paginated-search.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-paginated-search.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-permission-gate.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-permission-gate.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-profile-resolver.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-profile-resolver.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-commit-sync.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-commit-sync.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-commit-sync.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-sync.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-sync.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/jira-spec-sync.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/metadata-paths.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/metadata-paths.ts +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/project-selector.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/project-selector.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/project-selector.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/project-selector.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/reorganization-detector.d.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/reorganization-detector.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/reorganization-detector.js +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/reorganization-detector.js.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/setup-wizard.d.ts.map +0 -0
- /package/plugins/{specweave-jira/lib → specweave/lib/integrations/jira}/setup-wizard.js.map +0 -0
- /package/plugins/{specweave-ado/reference → specweave/reference/ado}/ado-specweave-mapping.md +0 -0
- /package/plugins/{specweave-github/reference → specweave/reference/github}/github-specweave-mapping.md +0 -0
- /package/plugins/{specweave-jira/reference → specweave/reference/jira}/confluence-page-api.md +0 -0
- /package/plugins/{specweave-jira/reference → specweave/reference/jira}/jira-specweave-mapping.md +0 -0
- /package/plugins/{specweave-ado/scripts → specweave/scripts/ado}/refresh-cache.js +0 -0
- /package/plugins/{specweave-ado/scripts → specweave/scripts/ado}/refresh-cache.ts +0 -0
- /package/plugins/{specweave-jira/scripts → specweave/scripts/jira}/import-projects.js +0 -0
- /package/plugins/{specweave-jira/scripts → specweave/scripts/jira}/import-projects.ts +0 -0
- /package/plugins/{specweave-jira/scripts → specweave/scripts/jira}/refresh-cache.js +0 -0
- /package/plugins/{specweave-jira/scripts → specweave/scripts/jira}/refresh-cache.ts +0 -0
- /package/plugins/{specweave-ado → specweave}/skills/ado-mapper/SKILL.md +0 -0
- /package/plugins/{specweave-ado → specweave}/skills/ado-multi-project/SKILL.md +0 -0
- /package/plugins/{specweave-ado → specweave}/skills/ado-resource-validator/SKILL.md +0 -0
- /package/plugins/{specweave-ado → specweave}/skills/ado-sync/README.md +0 -0
- /package/plugins/{specweave-ado → specweave}/skills/ado-sync/SKILL.md +0 -0
- /package/plugins/{specweave-diagrams → specweave}/skills/diagrams/SKILL.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/github-issue-standard/SKILL.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/github-multi-project/SKILL.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/github-sync/SKILL.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/github-sync/evals/HOW-TO-RUN-EVALS.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/github-sync/evals/evals.json +0 -0
- /package/plugins/{specweave-media → specweave}/skills/image/SKILL.md +0 -0
- /package/plugins/{specweave-jira → specweave}/skills/jira-mapper/SKILL.md +0 -0
- /package/plugins/{specweave-jira → specweave}/skills/jira-resource-validator/SKILL.md +0 -0
- /package/plugins/{specweave-jira → specweave}/skills/jira-sync/README.md +0 -0
- /package/plugins/{specweave-jira → specweave}/skills/jira-sync/SKILL.md +0 -0
- /package/plugins/{specweave-github → specweave}/skills/pr-review/SKILL.md +0 -0
- /package/plugins/{specweave-release → specweave}/skills/release-expert/SKILL.md +0 -0
- /package/plugins/{specweave-media → specweave}/skills/remotion/SKILL.md +0 -0
- /package/plugins/{specweave-media → specweave}/skills/video/SKILL.md +0 -0
|
@@ -0,0 +1,1403 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Feature Sync - Universal Hierarchy Implementation
|
|
3
|
+
*
|
|
4
|
+
* Architecture:
|
|
5
|
+
* - Feature (FS-XXX) → GitHub Milestone (Container)
|
|
6
|
+
* - User Story (US-XXX) → GitHub Issue with format [FS-XXX][US-YYY] Title
|
|
7
|
+
* - Tasks (T-XXX) → Checkboxes in User Story issue body
|
|
8
|
+
*
|
|
9
|
+
* This implements the Universal Hierarchy architecture for GitHub sync.
|
|
10
|
+
* Creates ONE issue PER user story file from specs/{project}/FS-XXX/us-*.md
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { readdir, readFile, writeFile, mkdir } from 'fs/promises';
|
|
14
|
+
import { existsSync } from 'fs';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import * as yaml from 'yaml';
|
|
17
|
+
import { GitHubClientV2 } from './github-client-v2.js';
|
|
18
|
+
import { UserStoryIssueBuilder } from './user-story-issue-builder.js';
|
|
19
|
+
import { CompletionCalculator } from './completion-calculator.js';
|
|
20
|
+
import { DuplicateDetector } from './duplicate-detector.js';
|
|
21
|
+
import { execFileNoThrow } from '../../vendor/utils/execFileNoThrow.js';
|
|
22
|
+
import { getGitHubAuthFromProject } from '../../vendor/utils/auth-helpers.js';
|
|
23
|
+
|
|
24
|
+
interface FeatureFrontmatter {
|
|
25
|
+
id: string;
|
|
26
|
+
title: string;
|
|
27
|
+
type: 'feature' | 'epic';
|
|
28
|
+
status: 'complete' | 'active' | 'planning' | 'archived';
|
|
29
|
+
projects?: string[];
|
|
30
|
+
created: string;
|
|
31
|
+
last_updated: string;
|
|
32
|
+
external_tools?: {
|
|
33
|
+
github?: {
|
|
34
|
+
type: 'milestone';
|
|
35
|
+
id: number | null;
|
|
36
|
+
url: string | null;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface UserStoryInfo {
|
|
42
|
+
id: string; // e.g., "US-001"
|
|
43
|
+
title: string;
|
|
44
|
+
filePath: string;
|
|
45
|
+
project: string;
|
|
46
|
+
status: string;
|
|
47
|
+
existingIssue?: number | null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class GitHubFeatureSync {
|
|
51
|
+
private client: GitHubClientV2;
|
|
52
|
+
private specsDir: string;
|
|
53
|
+
private projectRoot: string;
|
|
54
|
+
private calculator: CompletionCalculator;
|
|
55
|
+
private token?: string;
|
|
56
|
+
|
|
57
|
+
// Cached default branch for the sync session (one API call per session)
|
|
58
|
+
private defaultBranch: string | null = null;
|
|
59
|
+
|
|
60
|
+
// SYNC LOCK: Prevent concurrent syncs of the same feature
|
|
61
|
+
// Maps featureId → last sync timestamp
|
|
62
|
+
private static syncLocks: Map<string, number> = new Map();
|
|
63
|
+
private static readonly LOCK_DURATION_MS = 30000; // 30 seconds
|
|
64
|
+
|
|
65
|
+
constructor(client: GitHubClientV2, specsDir: string, projectRoot: string) {
|
|
66
|
+
this.client = client;
|
|
67
|
+
this.specsDir = specsDir;
|
|
68
|
+
this.projectRoot = projectRoot;
|
|
69
|
+
this.calculator = new CompletionCalculator(projectRoot);
|
|
70
|
+
// Get token from .env for gh CLI passthrough
|
|
71
|
+
this.token = getGitHubAuthFromProject(projectRoot).token;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Detect the default branch from the GitHub API.
|
|
76
|
+
* Caches the result per sync session to avoid repeated API calls.
|
|
77
|
+
* Falls back to 'main' if API call fails.
|
|
78
|
+
*/
|
|
79
|
+
private async detectDefaultBranch(): Promise<string> {
|
|
80
|
+
if (this.defaultBranch) {
|
|
81
|
+
return this.defaultBranch;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const owner = this.client.getOwner();
|
|
85
|
+
const repo = this.client.getRepo();
|
|
86
|
+
|
|
87
|
+
const result = await execFileNoThrow('gh', [
|
|
88
|
+
'api', `repos/${owner}/${repo}`, '--jq', '.default_branch'
|
|
89
|
+
], { env: this.getGhEnv() });
|
|
90
|
+
|
|
91
|
+
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
92
|
+
this.defaultBranch = result.stdout.trim();
|
|
93
|
+
} else {
|
|
94
|
+
console.warn(` ⚠️ Failed to detect default branch, falling back to 'main': ${result.stderr}`);
|
|
95
|
+
this.defaultBranch = 'main';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return this.defaultBranch;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get environment object with GH_TOKEN for gh CLI commands.
|
|
103
|
+
* This ensures the token from .env is passed to all gh operations,
|
|
104
|
+
* regardless of `gh auth` status.
|
|
105
|
+
*/
|
|
106
|
+
private getGhEnv(): NodeJS.ProcessEnv {
|
|
107
|
+
return this.token
|
|
108
|
+
? { ...process.env, GH_TOKEN: this.token }
|
|
109
|
+
: process.env;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Get the repo slug (owner/repo) for `-R` flag in gh CLI commands.
|
|
114
|
+
* CRITICAL: All gh issue commands MUST use `-R` to target the correct repo,
|
|
115
|
+
* not the repo inferred from the current working directory.
|
|
116
|
+
*/
|
|
117
|
+
private getRepoSlug(): string {
|
|
118
|
+
return `${this.client.getOwner()}/${this.client.getRepo()}`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Sync Feature folder to GitHub (Milestone + User Story Issues)
|
|
123
|
+
*
|
|
124
|
+
* Process:
|
|
125
|
+
* 1. Create/update GitHub Milestone for Feature
|
|
126
|
+
* 2. Find all us-*.md files across all projects
|
|
127
|
+
* 3. Create/update GitHub Issue for EACH user story
|
|
128
|
+
* 4. Update frontmatter with GitHub issue links
|
|
129
|
+
*/
|
|
130
|
+
async syncFeatureToGitHub(featureId: string, projectName?: string): Promise<{
|
|
131
|
+
milestoneNumber: number;
|
|
132
|
+
milestoneUrl: string;
|
|
133
|
+
issuesCreated: number;
|
|
134
|
+
issuesUpdated: number;
|
|
135
|
+
userStoriesProcessed: number;
|
|
136
|
+
}> {
|
|
137
|
+
// SYNC LOCK CHECK: Prevent concurrent/rapid syncs of the same feature+repo
|
|
138
|
+
// Root cause: Two sync paths (task completion + status change) can fire simultaneously
|
|
139
|
+
// Result: Duplicate GitHub comments due to race condition
|
|
140
|
+
// Key includes owner/repo so cross-project syncs (same featureId, different repos) aren't throttled
|
|
141
|
+
const lockKey = `${this.client.getOwner()}/${this.client.getRepo()}:${featureId}`;
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
const lastSync = GitHubFeatureSync.syncLocks.get(lockKey);
|
|
144
|
+
|
|
145
|
+
if (lastSync && (now - lastSync) < GitHubFeatureSync.LOCK_DURATION_MS) {
|
|
146
|
+
const secondsRemaining = Math.ceil((GitHubFeatureSync.LOCK_DURATION_MS - (now - lastSync)) / 1000);
|
|
147
|
+
console.log(`\n⏭️ Sync already in progress for ${featureId} (or completed ${Math.floor((now - lastSync) / 1000)}s ago)`);
|
|
148
|
+
console.log(` ℹ️ Sync will be available in ${secondsRemaining}s to prevent duplicates`);
|
|
149
|
+
console.log(` 💡 This prevents race conditions between task completion and status change syncs`);
|
|
150
|
+
|
|
151
|
+
// Return placeholder result (sync was skipped, not failed)
|
|
152
|
+
return {
|
|
153
|
+
milestoneNumber: 0,
|
|
154
|
+
milestoneUrl: '',
|
|
155
|
+
issuesCreated: 0,
|
|
156
|
+
issuesUpdated: 0,
|
|
157
|
+
userStoriesProcessed: 0
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Acquire lock
|
|
162
|
+
GitHubFeatureSync.syncLocks.set(lockKey, now);
|
|
163
|
+
console.log(`\n🔄 Syncing Feature ${featureId} to GitHub...`);
|
|
164
|
+
|
|
165
|
+
// 1. Load Feature FEATURE.md
|
|
166
|
+
const featureFolder = await this.findFeatureFolder(featureId, projectName);
|
|
167
|
+
if (!featureFolder) {
|
|
168
|
+
console.log(` ⚠️ Feature ${featureId} not found in ${this.specsDir} (no living docs and auto-create failed)`);
|
|
169
|
+
console.log(` 💡 Run /sw:sync-docs or /sw:living-docs to generate living docs first`);
|
|
170
|
+
return {
|
|
171
|
+
milestoneNumber: 0,
|
|
172
|
+
milestoneUrl: '',
|
|
173
|
+
issuesCreated: 0,
|
|
174
|
+
issuesUpdated: 0,
|
|
175
|
+
userStoriesProcessed: 0,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const featurePath = path.join(featureFolder, 'FEATURE.md');
|
|
180
|
+
const featureData = await this.parseFeatureMd(featurePath);
|
|
181
|
+
|
|
182
|
+
console.log(` 📦 Feature: ${featureData.title}`);
|
|
183
|
+
console.log(` 📊 Status: ${featureData.status}`);
|
|
184
|
+
|
|
185
|
+
// 2. Create or update GitHub Milestone
|
|
186
|
+
let milestoneNumber = featureData.external_tools?.github?.id;
|
|
187
|
+
let milestoneUrl = featureData.external_tools?.github?.url;
|
|
188
|
+
|
|
189
|
+
if (!milestoneNumber) {
|
|
190
|
+
console.log(` 🚀 Creating GitHub Milestone...`);
|
|
191
|
+
const milestone = await this.createMilestone(featureData);
|
|
192
|
+
milestoneNumber = milestone.number;
|
|
193
|
+
milestoneUrl = milestone.url;
|
|
194
|
+
console.log(` ✅ Created Milestone #${milestoneNumber}`);
|
|
195
|
+
|
|
196
|
+
// Update FEATURE.md with Milestone ID
|
|
197
|
+
await this.updateFeatureMd(featurePath, {
|
|
198
|
+
type: 'milestone',
|
|
199
|
+
id: milestoneNumber,
|
|
200
|
+
url: milestoneUrl,
|
|
201
|
+
});
|
|
202
|
+
} else {
|
|
203
|
+
console.log(` ♻️ Using existing Milestone #${milestoneNumber}`);
|
|
204
|
+
milestoneUrl = featureData.external_tools?.github?.url || milestoneUrl;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// 3. Find User Story files (scoped to projectName in cross-project mode)
|
|
208
|
+
const userStories = await this.findUserStories(featureId, projectName);
|
|
209
|
+
console.log(`\n 📝 Found ${userStories.length} User Stories to sync...`);
|
|
210
|
+
|
|
211
|
+
// 4. Sync each User Story as GitHub Issue
|
|
212
|
+
let issuesCreated = 0;
|
|
213
|
+
let issuesUpdated = 0;
|
|
214
|
+
|
|
215
|
+
// Detect default branch once per sync session
|
|
216
|
+
const detectedBranch = await this.detectDefaultBranch();
|
|
217
|
+
console.log(` 🌿 Default branch: ${detectedBranch}`);
|
|
218
|
+
|
|
219
|
+
for (const userStory of userStories) {
|
|
220
|
+
console.log(`\n 🔹 Processing ${userStory.id}: ${userStory.title}`);
|
|
221
|
+
|
|
222
|
+
// Build issue content using UserStoryIssueBuilder
|
|
223
|
+
const repoInfo = {
|
|
224
|
+
owner: this.client.getOwner(),
|
|
225
|
+
repo: this.client.getRepo(),
|
|
226
|
+
branch: detectedBranch
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const builder = new UserStoryIssueBuilder(
|
|
230
|
+
userStory.filePath,
|
|
231
|
+
this.projectRoot,
|
|
232
|
+
featureId,
|
|
233
|
+
repoInfo
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
const issueContent = await builder.buildIssueBody();
|
|
237
|
+
|
|
238
|
+
// ✅ FIX: Add status to issue content for sync
|
|
239
|
+
issueContent.status = userStory.status;
|
|
240
|
+
|
|
241
|
+
// ✅ DUPLICATE PROTECTION WITH GLOBAL DETECTOR
|
|
242
|
+
// Uses proven 3-phase protection: Detection → Verification → Reflection
|
|
243
|
+
//
|
|
244
|
+
// WHY THIS MATTERS:
|
|
245
|
+
// - Previous implementation had race conditions (--limit 1, eventual consistency)
|
|
246
|
+
// - DuplicateDetector handles all edge cases automatically
|
|
247
|
+
// - Auto-closes duplicates if they slip through
|
|
248
|
+
//
|
|
249
|
+
// @see .specweave/increments/0047-us-task-linkage/reports/DUPLICATE-GITHUB-ISSUES-ROOT-CAUSE.md
|
|
250
|
+
|
|
251
|
+
let issueNumber: number;
|
|
252
|
+
let wasUpdated = false;
|
|
253
|
+
|
|
254
|
+
// Check 1: User Story frontmatter has issue number
|
|
255
|
+
if (userStory.existingIssue) {
|
|
256
|
+
console.log(` ♻️ Issue #${userStory.existingIssue} exists in frontmatter`);
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
// Verify issue still exists on GitHub
|
|
260
|
+
await this.client.getIssue(userStory.existingIssue);
|
|
261
|
+
|
|
262
|
+
// Issue exists, update it with verification
|
|
263
|
+
await this.updateUserStoryIssue(userStory.existingIssue, issueContent, userStory.filePath);
|
|
264
|
+
issuesUpdated++;
|
|
265
|
+
console.log(` ✅ Updated Issue #${userStory.existingIssue}`);
|
|
266
|
+
continue;
|
|
267
|
+
} catch (err) {
|
|
268
|
+
// Issue deleted on GitHub, fall through to create new
|
|
269
|
+
console.log(` ⚠️ Issue #${userStory.existingIssue} deleted on GitHub, creating new`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Check 2 & 3: Use DuplicateDetector for robust duplicate prevention
|
|
274
|
+
// This handles:
|
|
275
|
+
// - Search with proper limits (not --limit 1)
|
|
276
|
+
// - Post-create verification
|
|
277
|
+
// - Auto-close duplicates
|
|
278
|
+
// - Eventual consistency race conditions
|
|
279
|
+
const titlePattern = `[${featureId}][${userStory.id}]`;
|
|
280
|
+
const milestoneTitle = `${featureData.id}: ${featureData.title}`;
|
|
281
|
+
|
|
282
|
+
console.log(` 🛡️ Using DuplicateDetector (pattern: ${titlePattern})`);
|
|
283
|
+
|
|
284
|
+
const result = await DuplicateDetector.createWithProtection({
|
|
285
|
+
title: issueContent.title,
|
|
286
|
+
body: issueContent.body,
|
|
287
|
+
titlePattern,
|
|
288
|
+
incrementId: userStory.id,
|
|
289
|
+
labels: issueContent.labels,
|
|
290
|
+
milestone: milestoneTitle,
|
|
291
|
+
repo: `${this.client.getOwner()}/${this.client.getRepo()}`
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
issueNumber = result.issue.number;
|
|
295
|
+
|
|
296
|
+
// Log duplicate protection results
|
|
297
|
+
if (result.wasReused) {
|
|
298
|
+
console.log(` ♻️ Reused existing issue #${issueNumber} (duplicate prevented!)`);
|
|
299
|
+
wasUpdated = true;
|
|
300
|
+
} else {
|
|
301
|
+
console.log(` ✅ Created issue #${issueNumber}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (result.duplicatesFound > 0) {
|
|
305
|
+
console.log(` 🛡️ Duplicates detected: ${result.duplicatesFound}, auto-closed: ${result.duplicatesClosed}`);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Update User Story frontmatter with issue link
|
|
309
|
+
await this.updateUserStoryFrontmatter(userStory.filePath, issueNumber);
|
|
310
|
+
|
|
311
|
+
// v1.0.240 FIX: Backfill increment metadata.json for reconciler compatibility
|
|
312
|
+
// Previously only US frontmatter was updated, leaving metadata.json empty.
|
|
313
|
+
// This caused reconciler and closure flows to miss these issues.
|
|
314
|
+
await this.backfillIncrementMetadata(featureId, userStory.id, issueNumber, milestoneNumber!);
|
|
315
|
+
|
|
316
|
+
// ✅ CRITICAL FIX (2025-11-24): Check completion for ALL issues (new AND reused)
|
|
317
|
+
// BUG: Previously only checked completion for reused issues, not new ones
|
|
318
|
+
// RESULT: New issues stayed OPEN even if status:complete
|
|
319
|
+
//
|
|
320
|
+
// Now we always call updateUserStoryIssue() which:
|
|
321
|
+
// 1. Calculates ACTUAL completion from [x] checkboxes
|
|
322
|
+
// 2. Closes issue if all ACs and tasks verified complete
|
|
323
|
+
// 3. Updates status labels automatically
|
|
324
|
+
await this.updateUserStoryIssue(issueNumber, issueContent, userStory.filePath);
|
|
325
|
+
|
|
326
|
+
// Update completion tracking
|
|
327
|
+
if (result.wasReused) {
|
|
328
|
+
issuesUpdated++;
|
|
329
|
+
} else {
|
|
330
|
+
issuesCreated++;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
console.log(`\n✅ Feature sync complete!`);
|
|
335
|
+
console.log(` Milestone: ${milestoneUrl}`);
|
|
336
|
+
console.log(` User Stories: ${userStories.length}`);
|
|
337
|
+
console.log(` Issues created: ${issuesCreated}`);
|
|
338
|
+
console.log(` Issues updated: ${issuesUpdated}`);
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
milestoneNumber: milestoneNumber!,
|
|
342
|
+
milestoneUrl: milestoneUrl!,
|
|
343
|
+
issuesCreated,
|
|
344
|
+
issuesUpdated,
|
|
345
|
+
userStoriesProcessed: userStories.length,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Find Feature folder in specs directory.
|
|
351
|
+
* Falls back to auto-creating from increment spec.md if living docs don't exist.
|
|
352
|
+
*/
|
|
353
|
+
private async findFeatureFolder(featureId: string, projectName?: string): Promise<string | null> {
|
|
354
|
+
// v5.0.0+: NO _features folder - features live in project folders
|
|
355
|
+
// In cross-project mode, look in the specific project folder first
|
|
356
|
+
if (projectName) {
|
|
357
|
+
const projectSpecific = path.join(this.specsDir, projectName, featureId);
|
|
358
|
+
if (existsSync(projectSpecific) && existsSync(path.join(projectSpecific, 'FEATURE.md'))) {
|
|
359
|
+
return projectSpecific;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Search all project folders for the feature
|
|
364
|
+
const projectFolders = await this.findProjectFolders();
|
|
365
|
+
|
|
366
|
+
for (const projectFolder of projectFolders) {
|
|
367
|
+
const featureFolder = path.join(projectFolder, featureId);
|
|
368
|
+
if (existsSync(featureFolder) && existsSync(path.join(featureFolder, 'FEATURE.md'))) {
|
|
369
|
+
return featureFolder;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Legacy fallback: Check _features folder (for brownfield migration)
|
|
374
|
+
const legacyFolder = path.join(this.specsDir, '_features', featureId);
|
|
375
|
+
if (existsSync(legacyFolder)) {
|
|
376
|
+
console.log(` ⚠️ Found feature in legacy _features folder - consider migrating to project folder`);
|
|
377
|
+
return legacyFolder;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// FALLBACK (v1.0.302): Auto-create feature folder from increment spec.md
|
|
381
|
+
// Most increments never get living docs created, so sync silently fails.
|
|
382
|
+
// This makes sync self-healing by creating minimal living docs on-the-fly.
|
|
383
|
+
console.log(` ℹ️ Feature folder not found in living docs, attempting auto-create from spec.md...`);
|
|
384
|
+
const created = await this.createFeatureFolderFromSpec(featureId, projectFolders);
|
|
385
|
+
if (created) {
|
|
386
|
+
return created;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return null;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Find the increment folder for a given feature ID.
|
|
394
|
+
* Converts FS-271 -> finds 0271-xxx-xxx/ in .specweave/increments/
|
|
395
|
+
*/
|
|
396
|
+
private async findIncrementFolder(featureId: string): Promise<string | null> {
|
|
397
|
+
const numMatch = featureId.match(/FS-0*(\d+)E?/i);
|
|
398
|
+
if (!numMatch) return null;
|
|
399
|
+
|
|
400
|
+
const num = parseInt(numMatch[1], 10);
|
|
401
|
+
const paddedNum = String(num).padStart(4, '0');
|
|
402
|
+
|
|
403
|
+
const incrementsDir = path.join(this.projectRoot, '.specweave/increments');
|
|
404
|
+
if (!existsSync(incrementsDir)) return null;
|
|
405
|
+
|
|
406
|
+
const entries = await readdir(incrementsDir);
|
|
407
|
+
const match = entries.find(e => e.startsWith(paddedNum + '-'));
|
|
408
|
+
if (!match) return null;
|
|
409
|
+
|
|
410
|
+
return path.join(incrementsDir, match);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Auto-create a feature folder (FEATURE.md + us-NNN.md files) from an
|
|
415
|
+
* increment's spec.md. This enables GitHub sync even when the living docs
|
|
416
|
+
* builder hasn't run yet.
|
|
417
|
+
*/
|
|
418
|
+
private async createFeatureFolderFromSpec(
|
|
419
|
+
featureId: string,
|
|
420
|
+
projectFolders: string[]
|
|
421
|
+
): Promise<string | null> {
|
|
422
|
+
try {
|
|
423
|
+
const incrementFolder = await this.findIncrementFolder(featureId);
|
|
424
|
+
if (!incrementFolder) {
|
|
425
|
+
console.log(` ⚠️ No increment folder found for ${featureId}`);
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const specPath = path.join(incrementFolder, 'spec.md');
|
|
430
|
+
if (!existsSync(specPath)) {
|
|
431
|
+
console.log(` ⚠️ No spec.md found in ${path.basename(incrementFolder)}`);
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const specContent = await readFile(specPath, 'utf-8');
|
|
436
|
+
|
|
437
|
+
// Parse frontmatter (optional — many specs don't have YAML frontmatter)
|
|
438
|
+
const fmMatch = specContent.match(/^---\n([\s\S]*?)\n---/);
|
|
439
|
+
let frontmatter: Record<string, string> = {};
|
|
440
|
+
if (fmMatch) {
|
|
441
|
+
try {
|
|
442
|
+
frontmatter = yaml.parse(fmMatch[1]) || {};
|
|
443
|
+
} catch {
|
|
444
|
+
// Invalid YAML — proceed without frontmatter
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const incrementBasename = path.basename(incrementFolder);
|
|
449
|
+
const title = frontmatter.title
|
|
450
|
+
|| specContent.match(/^#\s+(.+)/m)?.[1]?.trim()
|
|
451
|
+
|| incrementBasename.replace(/^\d+-/, '').replace(/-/g, ' ');
|
|
452
|
+
const status = frontmatter.status || 'active';
|
|
453
|
+
const priority = frontmatter.priority || 'P2';
|
|
454
|
+
const created = frontmatter.created || new Date().toISOString().split('T')[0];
|
|
455
|
+
const incrementId = frontmatter.increment || incrementBasename;
|
|
456
|
+
|
|
457
|
+
// Determine target project folder from spec.md user stories or first available
|
|
458
|
+
let targetProjectFolder = projectFolders[0]; // Default: first project folder
|
|
459
|
+
const projectMatch = specContent.match(/\*\*Project\*\*:\s*(\S+)/);
|
|
460
|
+
if (projectMatch) {
|
|
461
|
+
const projectName = projectMatch[1];
|
|
462
|
+
const matchingFolder = projectFolders.find(f => path.basename(f) === projectName);
|
|
463
|
+
if (matchingFolder) {
|
|
464
|
+
targetProjectFolder = matchingFolder;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (!targetProjectFolder) {
|
|
469
|
+
console.log(` ⚠️ No project folder available for feature creation`);
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Create feature folder
|
|
474
|
+
const featureFolder = path.join(targetProjectFolder, featureId);
|
|
475
|
+
await mkdir(featureFolder, { recursive: true });
|
|
476
|
+
|
|
477
|
+
// Parse user stories from spec.md body
|
|
478
|
+
const userStories = this.parseUserStoriesFromSpec(specContent, featureId);
|
|
479
|
+
|
|
480
|
+
// Create FEATURE.md
|
|
481
|
+
const featureMd = this.buildFeatureMd(featureId, title, status, priority, created, incrementId, userStories);
|
|
482
|
+
await writeFile(path.join(featureFolder, 'FEATURE.md'), featureMd, 'utf-8');
|
|
483
|
+
|
|
484
|
+
// Create us-NNN.md files
|
|
485
|
+
for (const us of userStories) {
|
|
486
|
+
const usFilename = `us-${us.id.replace('US-', '').padStart(3, '0')}-${this.slugify(us.title)}.md`;
|
|
487
|
+
const usMd = this.buildUserStoryMd(us, featureId, incrementId);
|
|
488
|
+
await writeFile(path.join(featureFolder, usFilename), usMd, 'utf-8');
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
console.log(` ✅ Auto-created feature folder with ${userStories.length} user stories`);
|
|
492
|
+
return featureFolder;
|
|
493
|
+
} catch (error) {
|
|
494
|
+
console.log(` ⚠️ Failed to auto-create feature folder: ${(error as Error).message}`);
|
|
495
|
+
return null;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Parse user stories from spec.md markdown content.
|
|
501
|
+
*/
|
|
502
|
+
private parseUserStoriesFromSpec(
|
|
503
|
+
specContent: string,
|
|
504
|
+
featureId: string
|
|
505
|
+
): Array<{
|
|
506
|
+
id: string;
|
|
507
|
+
title: string;
|
|
508
|
+
priority: string;
|
|
509
|
+
project: string;
|
|
510
|
+
storyText: string;
|
|
511
|
+
acceptanceCriteria: string[];
|
|
512
|
+
status: string;
|
|
513
|
+
}> {
|
|
514
|
+
const stories: Array<{
|
|
515
|
+
id: string;
|
|
516
|
+
title: string;
|
|
517
|
+
priority: string;
|
|
518
|
+
project: string;
|
|
519
|
+
storyText: string;
|
|
520
|
+
acceptanceCriteria: string[];
|
|
521
|
+
status: string;
|
|
522
|
+
}> = [];
|
|
523
|
+
|
|
524
|
+
// Match ### US-NNN: Title (Priority) sections
|
|
525
|
+
const usRegex = /### (US-\d+):\s*(.+?)(?:\s*\((P\d)\))?\s*\n([\s\S]*?)(?=\n### US-|\n## |\n---\s*\n### US-|$)/g;
|
|
526
|
+
let match;
|
|
527
|
+
|
|
528
|
+
while ((match = usRegex.exec(specContent)) !== null) {
|
|
529
|
+
const usId = match[1];
|
|
530
|
+
const rawTitle = match[2].trim();
|
|
531
|
+
const priority = match[3] || 'P2';
|
|
532
|
+
const body = match[4];
|
|
533
|
+
|
|
534
|
+
// Skip template placeholders
|
|
535
|
+
if (rawTitle === '[Story Title]') continue;
|
|
536
|
+
|
|
537
|
+
// Extract project
|
|
538
|
+
const projectMatch = body.match(/\*\*Project\*\*:\s*(\S+)/);
|
|
539
|
+
const project = projectMatch ? projectMatch[1] : 'specweave';
|
|
540
|
+
|
|
541
|
+
// Extract story text (As a... I want... So that...)
|
|
542
|
+
const storyMatch = body.match(/\*\*As a\*\*\s+([\s\S]*?)(?=\n\*\*Acceptance Criteria|$)/);
|
|
543
|
+
const storyText = storyMatch ? storyMatch[1].trim() : '';
|
|
544
|
+
|
|
545
|
+
// Extract acceptance criteria
|
|
546
|
+
const acs: string[] = [];
|
|
547
|
+
const acRegex = /- \[[ x]\] \*\*AC-[^*]+\*\*:\s*(.+)/g;
|
|
548
|
+
let acMatch;
|
|
549
|
+
while ((acMatch = acRegex.exec(body)) !== null) {
|
|
550
|
+
acs.push(acMatch[0]);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Determine status from ACs
|
|
554
|
+
const totalAcs = acs.length;
|
|
555
|
+
const completedAcs = acs.filter(ac => ac.startsWith('- [x]')).length;
|
|
556
|
+
let status = 'not-started';
|
|
557
|
+
if (totalAcs > 0 && completedAcs === totalAcs) status = 'complete';
|
|
558
|
+
else if (completedAcs > 0) status = 'active';
|
|
559
|
+
|
|
560
|
+
stories.push({
|
|
561
|
+
id: usId,
|
|
562
|
+
title: rawTitle,
|
|
563
|
+
priority,
|
|
564
|
+
project,
|
|
565
|
+
storyText,
|
|
566
|
+
acceptanceCriteria: acs,
|
|
567
|
+
status,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return stories;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/**
|
|
575
|
+
* Build FEATURE.md content matching the living docs format.
|
|
576
|
+
*/
|
|
577
|
+
private buildFeatureMd(
|
|
578
|
+
featureId: string,
|
|
579
|
+
title: string,
|
|
580
|
+
status: string,
|
|
581
|
+
priority: string,
|
|
582
|
+
created: string,
|
|
583
|
+
incrementId: string,
|
|
584
|
+
userStories: Array<{ id: string; title: string }>
|
|
585
|
+
): string {
|
|
586
|
+
const now = new Date().toISOString().split('T')[0];
|
|
587
|
+
const mappedStatus = status === 'planned' ? 'planning'
|
|
588
|
+
: status === 'completed' ? 'complete'
|
|
589
|
+
: status === 'active' ? 'active'
|
|
590
|
+
: 'planning';
|
|
591
|
+
|
|
592
|
+
const fm: Record<string, unknown> = {
|
|
593
|
+
id: featureId,
|
|
594
|
+
title,
|
|
595
|
+
type: 'feature',
|
|
596
|
+
status: mappedStatus,
|
|
597
|
+
priority,
|
|
598
|
+
created,
|
|
599
|
+
lastUpdated: now,
|
|
600
|
+
tldr: title,
|
|
601
|
+
complexity: 'medium',
|
|
602
|
+
auto_created: true,
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
const yamlFm = yaml.stringify(fm);
|
|
606
|
+
|
|
607
|
+
let body = `\n# ${title}\n\n## TL;DR\n\n**What**: ${title}\n**Status**: ${mappedStatus} | **Priority**: ${priority}\n**User Stories**: ${userStories.length}\n\n## Overview\n\n${title}\n\n## Implementation History\n\n| Increment | Status |\n|-----------|--------|\n| [${incrementId}](../../../../../increments/${incrementId}/spec.md) | ${mappedStatus} |\n\n## User Stories\n`;
|
|
608
|
+
|
|
609
|
+
for (const us of userStories) {
|
|
610
|
+
body += `\n- [${us.id}: ${us.title}](./${us.id.toLowerCase()}.md)`;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
return `---\n${yamlFm}---${body}\n`;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Build us-NNN.md content matching the living docs format.
|
|
618
|
+
*/
|
|
619
|
+
private buildUserStoryMd(
|
|
620
|
+
us: {
|
|
621
|
+
id: string;
|
|
622
|
+
title: string;
|
|
623
|
+
priority: string;
|
|
624
|
+
project: string;
|
|
625
|
+
storyText: string;
|
|
626
|
+
acceptanceCriteria: string[];
|
|
627
|
+
status: string;
|
|
628
|
+
},
|
|
629
|
+
featureId: string,
|
|
630
|
+
incrementId: string
|
|
631
|
+
): string {
|
|
632
|
+
const now = new Date().toISOString().split('T')[0];
|
|
633
|
+
|
|
634
|
+
const fm: Record<string, unknown> = {
|
|
635
|
+
id: us.id,
|
|
636
|
+
feature: featureId,
|
|
637
|
+
title: us.title,
|
|
638
|
+
status: us.status,
|
|
639
|
+
priority: us.priority,
|
|
640
|
+
created: now,
|
|
641
|
+
project: us.project,
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
const yamlFm = yaml.stringify(fm);
|
|
645
|
+
|
|
646
|
+
let body = `\n# ${us.id}: ${us.title}\n\n**Feature**: [${featureId}](./FEATURE.md)\n\n`;
|
|
647
|
+
|
|
648
|
+
if (us.storyText) {
|
|
649
|
+
body += `${us.storyText}\n\n`;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
body += `---\n\n## Acceptance Criteria\n\n`;
|
|
653
|
+
|
|
654
|
+
if (us.acceptanceCriteria.length > 0) {
|
|
655
|
+
body += us.acceptanceCriteria.join('\n') + '\n';
|
|
656
|
+
} else {
|
|
657
|
+
body += `- [ ] **AC-${us.id.replace('US-', 'US')}-01**: Pending specification\n`;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
body += `\n---\n\n## Implementation\n\n**Increment**: [${incrementId}](../../../../../increments/${incrementId}/spec.md)\n`;
|
|
661
|
+
|
|
662
|
+
return `---\n${yamlFm}---${body}\n`;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Convert a title to a URL-safe slug.
|
|
667
|
+
*/
|
|
668
|
+
private slugify(text: string): string {
|
|
669
|
+
return text
|
|
670
|
+
.toLowerCase()
|
|
671
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
672
|
+
.replace(/^-+|-+$/g, '')
|
|
673
|
+
.substring(0, 60);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* Backfill increment metadata.json with GitHub issue reference (v1.0.240)
|
|
678
|
+
*
|
|
679
|
+
* Writes in BOTH formats:
|
|
680
|
+
* - OLD format (metadata.github.issues[]) for backward compatibility
|
|
681
|
+
* - NEW format (metadata.externalLinks.github) for reconciler/closure flows
|
|
682
|
+
* Non-blocking — errors are logged but don't halt sync.
|
|
683
|
+
*/
|
|
684
|
+
private async backfillIncrementMetadata(
|
|
685
|
+
featureId: string,
|
|
686
|
+
userStoryId: string,
|
|
687
|
+
issueNumber: number,
|
|
688
|
+
milestoneNumber: number
|
|
689
|
+
): Promise<void> {
|
|
690
|
+
try {
|
|
691
|
+
// Derive increment ID from feature ID (reverse of deriveFeatureId)
|
|
692
|
+
const featureNumMatch = featureId.match(/FS-0*(\d+)E?/i);
|
|
693
|
+
if (!featureNumMatch) return;
|
|
694
|
+
|
|
695
|
+
const num = parseInt(featureNumMatch[1], 10);
|
|
696
|
+
const paddedNum = String(num).padStart(4, '0');
|
|
697
|
+
|
|
698
|
+
// Find the increment directory
|
|
699
|
+
const incrementsDir = path.join(this.projectRoot, '.specweave/increments');
|
|
700
|
+
if (!existsSync(incrementsDir)) return;
|
|
701
|
+
|
|
702
|
+
const entries = await readdir(incrementsDir);
|
|
703
|
+
const match = entries.find(e => e.startsWith(paddedNum + '-'));
|
|
704
|
+
if (!match) return;
|
|
705
|
+
|
|
706
|
+
const metadataPath = path.join(incrementsDir, match, 'metadata.json');
|
|
707
|
+
if (!existsSync(metadataPath)) return;
|
|
708
|
+
|
|
709
|
+
const metadata = JSON.parse(await readFile(metadataPath, 'utf-8'));
|
|
710
|
+
const issueUrl = `https://github.com/${this.client.getOwner()}/${this.client.getRepo()}/issues/${issueNumber}`;
|
|
711
|
+
let changed = false;
|
|
712
|
+
|
|
713
|
+
// Write in OLD format for backward compatibility
|
|
714
|
+
if (!metadata.github) metadata.github = {};
|
|
715
|
+
if (!metadata.github.issues) metadata.github.issues = [];
|
|
716
|
+
|
|
717
|
+
const existsOld = metadata.github.issues.some(
|
|
718
|
+
(i: { userStory: string }) => i.userStory === userStoryId
|
|
719
|
+
);
|
|
720
|
+
|
|
721
|
+
if (!existsOld) {
|
|
722
|
+
metadata.github.issues.push({
|
|
723
|
+
userStory: userStoryId,
|
|
724
|
+
number: issueNumber,
|
|
725
|
+
url: issueUrl,
|
|
726
|
+
createdAt: new Date().toISOString(),
|
|
727
|
+
});
|
|
728
|
+
metadata.github.lastSync = new Date().toISOString();
|
|
729
|
+
changed = true;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// Write in NEW format (externalLinks.github) for reconciler/closure flows
|
|
733
|
+
if (!metadata.externalLinks) metadata.externalLinks = {};
|
|
734
|
+
if (!metadata.externalLinks.github) metadata.externalLinks.github = {};
|
|
735
|
+
if (!metadata.externalLinks.github.issues) metadata.externalLinks.github.issues = {};
|
|
736
|
+
|
|
737
|
+
const existsNew = metadata.externalLinks.github.issues[userStoryId];
|
|
738
|
+
|
|
739
|
+
if (!existsNew) {
|
|
740
|
+
metadata.externalLinks.github.issues[userStoryId] = {
|
|
741
|
+
issueNumber,
|
|
742
|
+
issueUrl,
|
|
743
|
+
status: 'active',
|
|
744
|
+
};
|
|
745
|
+
changed = true;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// Always set milestone and syncedAt on the new format
|
|
749
|
+
if (milestoneNumber && metadata.externalLinks.github.milestone !== milestoneNumber) {
|
|
750
|
+
metadata.externalLinks.github.milestone = milestoneNumber;
|
|
751
|
+
changed = true;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
if (changed) {
|
|
755
|
+
metadata.externalLinks.github.syncedAt = new Date().toISOString();
|
|
756
|
+
await writeFile(metadataPath, JSON.stringify(metadata, null, 2) + '\n', 'utf-8');
|
|
757
|
+
console.log(` 📝 Backfilled metadata.json for ${userStoryId} (dual-format)`);
|
|
758
|
+
}
|
|
759
|
+
} catch (error) {
|
|
760
|
+
// Non-blocking
|
|
761
|
+
console.warn(` ⚠️ Metadata backfill failed: ${(error as Error).message}`);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
/**
|
|
766
|
+
* Parse FEATURE.md frontmatter
|
|
767
|
+
*/
|
|
768
|
+
private async parseFeatureMd(featurePath: string): Promise<FeatureFrontmatter> {
|
|
769
|
+
const content = await readFile(featurePath, 'utf-8');
|
|
770
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
771
|
+
|
|
772
|
+
if (!match) {
|
|
773
|
+
throw new Error(`${featurePath}: Missing YAML frontmatter`);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
return yaml.parse(match[1]) as FeatureFrontmatter;
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
/**
|
|
780
|
+
* Find all User Story files for this feature across all projects
|
|
781
|
+
*/
|
|
782
|
+
private async findUserStories(featureId: string, projectName?: string): Promise<UserStoryInfo[]> {
|
|
783
|
+
const userStories: UserStoryInfo[] = [];
|
|
784
|
+
|
|
785
|
+
// In cross-project mode, only look in the target project's folder
|
|
786
|
+
let projectFolders: string[];
|
|
787
|
+
if (projectName) {
|
|
788
|
+
const projectSpecific = path.join(this.specsDir, projectName);
|
|
789
|
+
projectFolders = existsSync(projectSpecific) ? [projectSpecific] : [];
|
|
790
|
+
} else {
|
|
791
|
+
projectFolders = await this.findProjectFolders();
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
for (const projectFolder of projectFolders) {
|
|
795
|
+
const featureSpecsFolder = path.join(projectFolder, featureId);
|
|
796
|
+
|
|
797
|
+
if (!existsSync(featureSpecsFolder)) {
|
|
798
|
+
continue; // Feature not present in this project
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Read all us-*.md files
|
|
802
|
+
const files = await readdir(featureSpecsFolder);
|
|
803
|
+
const usFiles = files.filter((f) => f.startsWith('us-') && f.endsWith('.md'));
|
|
804
|
+
|
|
805
|
+
for (const file of usFiles.sort()) {
|
|
806
|
+
const filePath = path.join(featureSpecsFolder, file);
|
|
807
|
+
const content = await readFile(filePath, 'utf-8');
|
|
808
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
809
|
+
|
|
810
|
+
if (!match) {
|
|
811
|
+
console.warn(` ⚠️ ${file}: Missing frontmatter, skipping`);
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
const frontmatter = yaml.parse(match[1]);
|
|
816
|
+
const projectName = path.basename(projectFolder);
|
|
817
|
+
|
|
818
|
+
userStories.push({
|
|
819
|
+
id: frontmatter.id || file.match(/us-(\d+)/)?.[0]?.toUpperCase() || 'UNKNOWN',
|
|
820
|
+
title: frontmatter.title || 'Untitled User Story',
|
|
821
|
+
filePath,
|
|
822
|
+
project: projectName,
|
|
823
|
+
status: frontmatter.status || 'not-started',
|
|
824
|
+
existingIssue: frontmatter.external?.github?.issue || null,
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
return userStories;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Find all project folders (default, backend, frontend, etc.)
|
|
834
|
+
*/
|
|
835
|
+
private async findProjectFolders(): Promise<string[]> {
|
|
836
|
+
const folders: string[] = [];
|
|
837
|
+
const specsRoot = this.specsDir;
|
|
838
|
+
|
|
839
|
+
// Read all directories in specs root
|
|
840
|
+
const entries = await readdir(specsRoot, { withFileTypes: true });
|
|
841
|
+
|
|
842
|
+
for (const entry of entries) {
|
|
843
|
+
if (entry.isDirectory() && !entry.name.startsWith('_')) {
|
|
844
|
+
folders.push(path.join(specsRoot, entry.name));
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
return folders;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* Create GitHub Milestone for Feature (with duplicate detection)
|
|
853
|
+
*/
|
|
854
|
+
private async createMilestone(featureData: FeatureFrontmatter): Promise<{
|
|
855
|
+
number: number;
|
|
856
|
+
url: string;
|
|
857
|
+
}> {
|
|
858
|
+
const title = `${featureData.id}: ${featureData.title}`;
|
|
859
|
+
|
|
860
|
+
// CRITICAL: Check if milestone already exists before creating
|
|
861
|
+
// NOTE: Must use per_page=100 to handle repos with 30+ milestones (GitHub default is 30)
|
|
862
|
+
// BUG FIX: Without pagination, milestone #31+ won't be found → false "not found" → HTTP 422 duplicate error
|
|
863
|
+
// FIX (v1.0.302): Use explicit owner/repo from config, not :owner/:repo which resolves from git remote
|
|
864
|
+
const owner = this.client.getOwner();
|
|
865
|
+
const repo = this.client.getRepo();
|
|
866
|
+
|
|
867
|
+
const existingResult = await execFileNoThrow('gh', [
|
|
868
|
+
'api',
|
|
869
|
+
`repos/${owner}/${repo}/milestones?per_page=100&state=all`,
|
|
870
|
+
'--paginate',
|
|
871
|
+
'--jq',
|
|
872
|
+
`.[] | select(.title == "${title}") | {number, html_url}`,
|
|
873
|
+
], { env: this.getGhEnv() });
|
|
874
|
+
|
|
875
|
+
// DEBUG: Log detection result
|
|
876
|
+
console.log(` 🔍 Milestone detection: exitCode=${existingResult.exitCode}, stdout length=${existingResult.stdout.length}`);
|
|
877
|
+
if (existingResult.exitCode !== 0) {
|
|
878
|
+
console.log(` ⚠️ Detection failed: ${existingResult.stderr}`);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
if (existingResult.exitCode === 0 && existingResult.stdout.trim()) {
|
|
882
|
+
const existing = JSON.parse(existingResult.stdout);
|
|
883
|
+
console.log(` ♻️ Reusing existing Milestone #${existing.number}`);
|
|
884
|
+
return {
|
|
885
|
+
number: existing.number,
|
|
886
|
+
url: existing.html_url,
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
console.log(` ℹ️ No existing milestone found, creating new one...`);
|
|
891
|
+
|
|
892
|
+
// Milestone doesn't exist, create new one
|
|
893
|
+
const description = `Feature ${featureData.id}\n\nStatus: ${featureData.status}\nCreated: ${featureData.created}`;
|
|
894
|
+
|
|
895
|
+
const result = await execFileNoThrow('gh', [
|
|
896
|
+
'api',
|
|
897
|
+
`repos/${owner}/${repo}/milestones`,
|
|
898
|
+
'-X',
|
|
899
|
+
'POST',
|
|
900
|
+
'-f',
|
|
901
|
+
`title=${title}`,
|
|
902
|
+
'-f',
|
|
903
|
+
`description=${description}`,
|
|
904
|
+
'-f',
|
|
905
|
+
'state=open',
|
|
906
|
+
], { env: this.getGhEnv() });
|
|
907
|
+
|
|
908
|
+
if (result.exitCode !== 0) {
|
|
909
|
+
throw new Error(`Failed to create Milestone: ${result.stderr || result.stdout}`);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
const milestone = JSON.parse(result.stdout);
|
|
913
|
+
return {
|
|
914
|
+
number: milestone.number,
|
|
915
|
+
url: milestone.html_url,
|
|
916
|
+
};
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Create GitHub Issue for User Story with AC/Task Verification
|
|
921
|
+
*
|
|
922
|
+
* ✅ VERIFICATION GATE FIX:
|
|
923
|
+
* - Verifies actual completion before closing
|
|
924
|
+
* - Prevents premature closure on creation
|
|
925
|
+
*/
|
|
926
|
+
private async createUserStoryIssue(
|
|
927
|
+
issueContent: {
|
|
928
|
+
title: string;
|
|
929
|
+
body: string;
|
|
930
|
+
labels: string[];
|
|
931
|
+
status?: string;
|
|
932
|
+
},
|
|
933
|
+
milestoneTitle: string,
|
|
934
|
+
userStoryPath: string
|
|
935
|
+
): Promise<number> {
|
|
936
|
+
// Step 0: Ensure all required labels exist in the target repo
|
|
937
|
+
const repoSlug = `${this.client.getOwner()}/${this.client.getRepo()}`;
|
|
938
|
+
for (const label of issueContent.labels) {
|
|
939
|
+
await execFileNoThrow('gh', [
|
|
940
|
+
'label', 'create', label, '--repo', repoSlug,
|
|
941
|
+
'--color', 'ededed', '--description', 'SpecWeave auto-label', '--force'
|
|
942
|
+
], { env: this.getGhEnv() });
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// Step 1: Create issue (always open initially - gh CLI limitation)
|
|
946
|
+
const result = await execFileNoThrow('gh', [
|
|
947
|
+
'issue',
|
|
948
|
+
'create',
|
|
949
|
+
'--repo',
|
|
950
|
+
repoSlug,
|
|
951
|
+
'--title',
|
|
952
|
+
issueContent.title,
|
|
953
|
+
'--body',
|
|
954
|
+
issueContent.body,
|
|
955
|
+
'--milestone',
|
|
956
|
+
milestoneTitle,
|
|
957
|
+
...issueContent.labels.flatMap((label) => ['--label', label]),
|
|
958
|
+
], { env: this.getGhEnv() });
|
|
959
|
+
|
|
960
|
+
if (result.exitCode !== 0) {
|
|
961
|
+
throw new Error(`Failed to create GitHub Issue: ${result.stderr || result.stdout}`);
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
// Parse issue number from output
|
|
965
|
+
// Format: "https://github.com/owner/repo/issues/123"
|
|
966
|
+
const match = result.stdout.match(/issues\/(\d+)/);
|
|
967
|
+
if (!match) {
|
|
968
|
+
throw new Error(`Failed to parse issue number from: ${result.stdout}`);
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
const issueNumber = parseInt(match[1], 10);
|
|
972
|
+
|
|
973
|
+
// Step 2: VERIFICATION GATE - Close only if ACs/tasks verified
|
|
974
|
+
const completion = await this.calculator.calculateCompletion(userStoryPath);
|
|
975
|
+
|
|
976
|
+
if (completion.overallComplete) {
|
|
977
|
+
// ✅ SAFE TO CLOSE - All ACs and tasks verified [x]
|
|
978
|
+
await execFileNoThrow('gh', [
|
|
979
|
+
'issue',
|
|
980
|
+
'close',
|
|
981
|
+
issueNumber.toString(),
|
|
982
|
+
'--comment',
|
|
983
|
+
this.calculator.buildCompletionComment(completion),
|
|
984
|
+
'-R',
|
|
985
|
+
repoSlug,
|
|
986
|
+
], { env: this.getGhEnv() });
|
|
987
|
+
console.log(
|
|
988
|
+
` ✅ Created and verified complete: ${completion.acsCompleted}/${completion.acsTotal} ACs, ${completion.tasksCompleted}/${completion.tasksTotal} tasks`
|
|
989
|
+
);
|
|
990
|
+
} else {
|
|
991
|
+
// ⚠️ INCOMPLETE - Leave open with progress comment (with deduplication)
|
|
992
|
+
// Note: For newly created issues, this is the first comment so deduplication
|
|
993
|
+
// will likely pass through, but the logic is here for consistency
|
|
994
|
+
await this.postProgressCommentIfChanged(issueNumber, completion);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
return issueNumber;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
/**
|
|
1001
|
+
* Update existing GitHub Issue for User Story with AC/Task Verification
|
|
1002
|
+
*
|
|
1003
|
+
* ✅ VERIFICATION GATE FIX:
|
|
1004
|
+
* - OLD: Closed based on frontmatter `status: complete`
|
|
1005
|
+
* - NEW: Closes ONLY if all ACs and tasks are [x]
|
|
1006
|
+
*
|
|
1007
|
+
* This prevents Issue #574 type bugs (premature closure)
|
|
1008
|
+
*/
|
|
1009
|
+
private async updateUserStoryIssue(
|
|
1010
|
+
issueNumber: number,
|
|
1011
|
+
issueContent: {
|
|
1012
|
+
title: string;
|
|
1013
|
+
body: string;
|
|
1014
|
+
labels: string[];
|
|
1015
|
+
status?: string;
|
|
1016
|
+
},
|
|
1017
|
+
userStoryPath: string
|
|
1018
|
+
): Promise<void> {
|
|
1019
|
+
// Update issue body
|
|
1020
|
+
const repoSlug = this.getRepoSlug();
|
|
1021
|
+
await execFileNoThrow('gh', [
|
|
1022
|
+
'issue',
|
|
1023
|
+
'edit',
|
|
1024
|
+
issueNumber.toString(),
|
|
1025
|
+
'--title',
|
|
1026
|
+
issueContent.title,
|
|
1027
|
+
'--body',
|
|
1028
|
+
issueContent.body,
|
|
1029
|
+
'-R',
|
|
1030
|
+
repoSlug,
|
|
1031
|
+
], { env: this.getGhEnv() });
|
|
1032
|
+
|
|
1033
|
+
// ✅ VERIFICATION GATE: Calculate ACTUAL completion from checkboxes
|
|
1034
|
+
const completion = await this.calculator.calculateCompletion(userStoryPath);
|
|
1035
|
+
|
|
1036
|
+
// Get current issue state
|
|
1037
|
+
const issueData = await this.client.getIssue(issueNumber);
|
|
1038
|
+
const currentlyClosed = issueData.state === 'closed';
|
|
1039
|
+
|
|
1040
|
+
// DECISION LOGIC: Close/Reopen/Update based on VERIFIED completion
|
|
1041
|
+
if (completion.overallComplete) {
|
|
1042
|
+
// ✅ SAFE TO CLOSE - All ACs and tasks verified [x]
|
|
1043
|
+
if (!currentlyClosed) {
|
|
1044
|
+
// Idempotency check: skip completion comment if already posted by another sync path
|
|
1045
|
+
const lastComment = await this.client.getLastComment(issueNumber);
|
|
1046
|
+
const commentAlreadyPosted = lastComment?.body?.includes('✅ User Story Complete');
|
|
1047
|
+
if (commentAlreadyPosted) {
|
|
1048
|
+
// Close without duplicate comment
|
|
1049
|
+
await execFileNoThrow('gh', [
|
|
1050
|
+
'issue',
|
|
1051
|
+
'close',
|
|
1052
|
+
issueNumber.toString(),
|
|
1053
|
+
'-R',
|
|
1054
|
+
repoSlug,
|
|
1055
|
+
], { env: this.getGhEnv() });
|
|
1056
|
+
console.log(
|
|
1057
|
+
` ✅ Verified complete (comment already posted): ${completion.acsCompleted}/${completion.acsTotal} ACs, ${completion.tasksCompleted}/${completion.tasksTotal} tasks`
|
|
1058
|
+
);
|
|
1059
|
+
} else {
|
|
1060
|
+
await execFileNoThrow('gh', [
|
|
1061
|
+
'issue',
|
|
1062
|
+
'close',
|
|
1063
|
+
issueNumber.toString(),
|
|
1064
|
+
'--comment',
|
|
1065
|
+
this.calculator.buildCompletionComment(completion),
|
|
1066
|
+
'-R',
|
|
1067
|
+
repoSlug,
|
|
1068
|
+
], { env: this.getGhEnv() });
|
|
1069
|
+
console.log(
|
|
1070
|
+
` ✅ Verified complete: ${completion.acsCompleted}/${completion.acsTotal} ACs, ${completion.tasksCompleted}/${completion.tasksTotal} tasks`
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
} else {
|
|
1075
|
+
// ⚠️ INCOMPLETE - Keep open or reopen if needed
|
|
1076
|
+
if (currentlyClosed) {
|
|
1077
|
+
// Issue was closed prematurely - REOPEN
|
|
1078
|
+
await execFileNoThrow('gh', [
|
|
1079
|
+
'issue',
|
|
1080
|
+
'reopen',
|
|
1081
|
+
issueNumber.toString(),
|
|
1082
|
+
'--comment',
|
|
1083
|
+
this.calculator.buildReopenComment(completion, 'Work verification failed'),
|
|
1084
|
+
'-R',
|
|
1085
|
+
repoSlug,
|
|
1086
|
+
], { env: this.getGhEnv() });
|
|
1087
|
+
console.log(
|
|
1088
|
+
` ⚠️ Reopened: ${completion.blockingAcs.length + completion.blockingTasks.length} items incomplete`
|
|
1089
|
+
);
|
|
1090
|
+
} else {
|
|
1091
|
+
// Update progress comment (with deduplication)
|
|
1092
|
+
await this.postProgressCommentIfChanged(issueNumber, completion);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
// **NEW (2025-11-24)**: Update status labels based on completion
|
|
1097
|
+
await this.updateStatusLabels(issueNumber, completion);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Update status labels on GitHub issue based on completion state
|
|
1102
|
+
*
|
|
1103
|
+
* SMART LABEL MANAGEMENT:
|
|
1104
|
+
* - Only manages status:* labels (status:not_started, status:in-progress, status:completed)
|
|
1105
|
+
* - Preserves all other labels (priority, type, custom labels)
|
|
1106
|
+
* - Ensures exactly one status label is present
|
|
1107
|
+
*/
|
|
1108
|
+
private async updateStatusLabels(
|
|
1109
|
+
issueNumber: number,
|
|
1110
|
+
completion: {
|
|
1111
|
+
overallComplete: boolean;
|
|
1112
|
+
acsPercentage: number;
|
|
1113
|
+
tasksPercentage: number;
|
|
1114
|
+
acsTotal?: number;
|
|
1115
|
+
acsCompleted?: number;
|
|
1116
|
+
tasksTotal?: number;
|
|
1117
|
+
tasksCompleted?: number;
|
|
1118
|
+
frontmatterStatus?: string;
|
|
1119
|
+
}
|
|
1120
|
+
): Promise<void> {
|
|
1121
|
+
try {
|
|
1122
|
+
// Get current issue labels
|
|
1123
|
+
const issueData = await this.client.getIssue(issueNumber);
|
|
1124
|
+
const currentLabels = issueData.labels || [];
|
|
1125
|
+
|
|
1126
|
+
// Separate status labels from other labels
|
|
1127
|
+
const statusLabels = currentLabels.filter((label: string) => label.startsWith('status:'));
|
|
1128
|
+
const otherLabels = currentLabels.filter((label: string) => !label.startsWith('status:'));
|
|
1129
|
+
|
|
1130
|
+
// Determine correct status label based on completion
|
|
1131
|
+
// NOTE: Label names must match repository labels exactly
|
|
1132
|
+
let newStatusLabel: string;
|
|
1133
|
+
if (completion.overallComplete) {
|
|
1134
|
+
newStatusLabel = 'status:complete'; // Repository uses "complete" not "completed"
|
|
1135
|
+
} else if (completion.acsPercentage > 0 || completion.tasksPercentage > 0) {
|
|
1136
|
+
newStatusLabel = 'status:active'; // Repository uses "active" not "in-progress"
|
|
1137
|
+
} else if (
|
|
1138
|
+
// v0.35.1 FIX: For external-origin USs without ACs/tasks, use frontmatter status
|
|
1139
|
+
// This fixes issue #889 where external USs always showed "not_started"
|
|
1140
|
+
(completion.acsTotal === 0 || completion.acsTotal === undefined) &&
|
|
1141
|
+
(completion.tasksTotal === 0 || completion.tasksTotal === undefined) &&
|
|
1142
|
+
completion.frontmatterStatus
|
|
1143
|
+
) {
|
|
1144
|
+
// Map frontmatter status to GitHub label
|
|
1145
|
+
switch (completion.frontmatterStatus) {
|
|
1146
|
+
case 'complete':
|
|
1147
|
+
case 'completed':
|
|
1148
|
+
newStatusLabel = 'status:complete';
|
|
1149
|
+
break;
|
|
1150
|
+
case 'active':
|
|
1151
|
+
case 'in-progress':
|
|
1152
|
+
newStatusLabel = 'status:active';
|
|
1153
|
+
break;
|
|
1154
|
+
case 'planning':
|
|
1155
|
+
case 'not-started':
|
|
1156
|
+
default:
|
|
1157
|
+
newStatusLabel = 'status:not_started';
|
|
1158
|
+
}
|
|
1159
|
+
console.log(` ℹ️ Using frontmatter status (no ACs/tasks): ${completion.frontmatterStatus} → ${newStatusLabel}`);
|
|
1160
|
+
} else {
|
|
1161
|
+
newStatusLabel = 'status:not_started';
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// Check if update needed
|
|
1165
|
+
const needsUpdate = statusLabels.length !== 1 || !statusLabels.includes(newStatusLabel);
|
|
1166
|
+
|
|
1167
|
+
if (!needsUpdate) {
|
|
1168
|
+
return; // Status label already correct
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
// Update labels using gh CLI
|
|
1172
|
+
// Strategy: Remove old status labels first (if any), then add new one
|
|
1173
|
+
|
|
1174
|
+
// Step 1: Remove old status labels (only if they exist)
|
|
1175
|
+
if (statusLabels.length > 0) {
|
|
1176
|
+
await execFileNoThrow('gh', [
|
|
1177
|
+
'issue',
|
|
1178
|
+
'edit',
|
|
1179
|
+
issueNumber.toString(),
|
|
1180
|
+
'-R', this.getRepoSlug(),
|
|
1181
|
+
'--remove-label',
|
|
1182
|
+
...statusLabels,
|
|
1183
|
+
], { env: this.getGhEnv() });
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// Step 2: Add new status label
|
|
1187
|
+
const result = await execFileNoThrow('gh', [
|
|
1188
|
+
'issue',
|
|
1189
|
+
'edit',
|
|
1190
|
+
issueNumber.toString(),
|
|
1191
|
+
'-R', this.getRepoSlug(),
|
|
1192
|
+
'--add-label',
|
|
1193
|
+
newStatusLabel,
|
|
1194
|
+
], { env: this.getGhEnv() });
|
|
1195
|
+
|
|
1196
|
+
if (result.exitCode === 0) {
|
|
1197
|
+
console.log(` 🏷️ Updated label: ${newStatusLabel}`);
|
|
1198
|
+
} else {
|
|
1199
|
+
console.warn(` ⚠️ Failed to add label ${newStatusLabel}: ${result.stderr}`);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// Step 3: Auto-close issue when status:complete and issue still OPEN
|
|
1203
|
+
// This ensures closure happens atomically with the label update,
|
|
1204
|
+
// preventing issues like #1198 where label is applied but issue stays open
|
|
1205
|
+
if (newStatusLabel === 'status:complete' && issueData.state.toLowerCase() !== 'closed') {
|
|
1206
|
+
try {
|
|
1207
|
+
// Re-fetch issue state to avoid race with updateUserStoryIssue close
|
|
1208
|
+
const freshIssueData = await this.client.getIssue(issueNumber);
|
|
1209
|
+
if (freshIssueData.state.toLowerCase() === 'closed') {
|
|
1210
|
+
console.log(` ⏭️ Issue #${issueNumber} already closed (skipping duplicate close)`);
|
|
1211
|
+
} else {
|
|
1212
|
+
// Idempotency check: skip completion comment if already posted
|
|
1213
|
+
const lastComment = await this.client.getLastComment(issueNumber);
|
|
1214
|
+
if (lastComment?.body?.includes('✅ User Story Complete')) {
|
|
1215
|
+
// Comment already exists — close without posting duplicate
|
|
1216
|
+
await execFileNoThrow('gh', [
|
|
1217
|
+
'issue',
|
|
1218
|
+
'close',
|
|
1219
|
+
issueNumber.toString(),
|
|
1220
|
+
'-R', this.getRepoSlug(),
|
|
1221
|
+
], { env: this.getGhEnv() });
|
|
1222
|
+
console.log(` ✅ Auto-closed issue #${issueNumber} (comment already posted)`);
|
|
1223
|
+
} else {
|
|
1224
|
+
const completionComment = this.calculator.buildCompletionComment(completion as any);
|
|
1225
|
+
await execFileNoThrow('gh', [
|
|
1226
|
+
'issue',
|
|
1227
|
+
'close',
|
|
1228
|
+
issueNumber.toString(),
|
|
1229
|
+
'-R', this.getRepoSlug(),
|
|
1230
|
+
'--comment',
|
|
1231
|
+
completionComment,
|
|
1232
|
+
], { env: this.getGhEnv() });
|
|
1233
|
+
console.log(` ✅ Auto-closed issue #${issueNumber} (status:complete)`);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
} catch (closeError) {
|
|
1237
|
+
// Non-blocking: close failure shouldn't break sync
|
|
1238
|
+
console.warn(` ⚠️ Failed to auto-close issue #${issueNumber}: ${(closeError as Error).message}`);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
// Non-blocking: Label update failure shouldn't break sync
|
|
1243
|
+
console.warn(` ⚠️ Failed to update status labels: ${(error as Error).message}`);
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* Post progress comment only if it differs from the last comment
|
|
1249
|
+
*
|
|
1250
|
+
* DEDUPLICATION FIX (2025-11-24):
|
|
1251
|
+
* - Prevents posting identical consecutive comments
|
|
1252
|
+
* - Fetches last comment from issue
|
|
1253
|
+
* - Compares content (ignoring timestamps)
|
|
1254
|
+
* - Only posts if progress has changed
|
|
1255
|
+
*
|
|
1256
|
+
* Root Cause: updateUserStoryIssue() was posting progress comments on EVERY sync,
|
|
1257
|
+
* even when progress hadn't changed, causing 4+ duplicate comments.
|
|
1258
|
+
*
|
|
1259
|
+
* @param issueNumber - GitHub issue number
|
|
1260
|
+
* @param completion - Completion status with AC/task metrics
|
|
1261
|
+
*/
|
|
1262
|
+
private async postProgressCommentIfChanged(
|
|
1263
|
+
issueNumber: number,
|
|
1264
|
+
completion: any
|
|
1265
|
+
): Promise<void> {
|
|
1266
|
+
try {
|
|
1267
|
+
// 1. Fetch last comment from the issue
|
|
1268
|
+
const repoSlug = this.getRepoSlug();
|
|
1269
|
+
const commentsResult = await execFileNoThrow('gh', [
|
|
1270
|
+
'api',
|
|
1271
|
+
`repos/${repoSlug}/issues/${issueNumber}/comments`,
|
|
1272
|
+
'--jq',
|
|
1273
|
+
'.[-1] | {body: .body, created_at: .created_at}', // Get last comment only
|
|
1274
|
+
], { env: this.getGhEnv() });
|
|
1275
|
+
|
|
1276
|
+
let lastCommentBody = '';
|
|
1277
|
+
if (commentsResult.exitCode === 0 && commentsResult.stdout.trim()) {
|
|
1278
|
+
try {
|
|
1279
|
+
const lastComment = JSON.parse(commentsResult.stdout);
|
|
1280
|
+
lastCommentBody = lastComment.body || '';
|
|
1281
|
+
} catch {
|
|
1282
|
+
// No valid last comment, proceed with posting
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// 2. Build new progress comment
|
|
1287
|
+
const newCommentBody = this.calculator.buildProgressComment(completion);
|
|
1288
|
+
|
|
1289
|
+
// 3. Normalize both comments for comparison (remove timestamps, whitespace differences)
|
|
1290
|
+
const normalizeComment = (text: string): string => {
|
|
1291
|
+
return text
|
|
1292
|
+
.replace(/🤖 Auto-updated by SpecWeave AC Completion Gate/g, '')
|
|
1293
|
+
.replace(/\s+/g, ' ')
|
|
1294
|
+
.trim();
|
|
1295
|
+
};
|
|
1296
|
+
|
|
1297
|
+
const normalizedLast = normalizeComment(lastCommentBody);
|
|
1298
|
+
const normalizedNew = normalizeComment(newCommentBody);
|
|
1299
|
+
|
|
1300
|
+
// 4. Check if comments are identical (ignoring formatting differences)
|
|
1301
|
+
if (normalizedLast === normalizedNew) {
|
|
1302
|
+
console.log(
|
|
1303
|
+
` ⏭️ Progress unchanged (${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks) - skipping duplicate comment`
|
|
1304
|
+
);
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
// 5. Post new comment only if progress has changed
|
|
1309
|
+
await execFileNoThrow('gh', [
|
|
1310
|
+
'issue',
|
|
1311
|
+
'comment',
|
|
1312
|
+
issueNumber.toString(),
|
|
1313
|
+
'-R', repoSlug,
|
|
1314
|
+
'--body',
|
|
1315
|
+
newCommentBody,
|
|
1316
|
+
], { env: this.getGhEnv() });
|
|
1317
|
+
console.log(
|
|
1318
|
+
` 📊 Progress: ${completion.acsPercentage.toFixed(0)}% ACs, ${completion.tasksPercentage.toFixed(0)}% tasks (updated)`
|
|
1319
|
+
);
|
|
1320
|
+
|
|
1321
|
+
} catch (error) {
|
|
1322
|
+
// Non-blocking: Log error but don't break sync
|
|
1323
|
+
console.error(` ⚠️ Failed to check/post progress comment: ${(error as Error).message}`);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
/**
|
|
1328
|
+
* Update FEATURE.md with GitHub Milestone link
|
|
1329
|
+
*/
|
|
1330
|
+
private async updateFeatureMd(
|
|
1331
|
+
featurePath: string,
|
|
1332
|
+
milestone: {
|
|
1333
|
+
type: 'milestone';
|
|
1334
|
+
id: number;
|
|
1335
|
+
url: string;
|
|
1336
|
+
}
|
|
1337
|
+
): Promise<void> {
|
|
1338
|
+
const content = await readFile(featurePath, 'utf-8');
|
|
1339
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1340
|
+
|
|
1341
|
+
if (!match) {
|
|
1342
|
+
throw new Error(`${featurePath}: Missing YAML frontmatter`);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
const frontmatter = yaml.parse(match[1]);
|
|
1346
|
+
|
|
1347
|
+
// Update external_tools.github
|
|
1348
|
+
if (!frontmatter.external_tools) {
|
|
1349
|
+
frontmatter.external_tools = {};
|
|
1350
|
+
}
|
|
1351
|
+
frontmatter.external_tools.github = milestone;
|
|
1352
|
+
|
|
1353
|
+
// Rebuild content
|
|
1354
|
+
const newFrontmatter = yaml.stringify(frontmatter);
|
|
1355
|
+
const bodyContent = content.slice(match[0].length);
|
|
1356
|
+
const newContent = `---\n${newFrontmatter}---${bodyContent}`;
|
|
1357
|
+
|
|
1358
|
+
await writeFile(featurePath, newContent, 'utf-8');
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/**
|
|
1362
|
+
* Update User Story frontmatter with GitHub issue link
|
|
1363
|
+
*/
|
|
1364
|
+
private async updateUserStoryFrontmatter(
|
|
1365
|
+
userStoryPath: string,
|
|
1366
|
+
issueNumber: number
|
|
1367
|
+
): Promise<void> {
|
|
1368
|
+
const content = await readFile(userStoryPath, 'utf-8');
|
|
1369
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
1370
|
+
|
|
1371
|
+
if (!match) {
|
|
1372
|
+
throw new Error(`${userStoryPath}: Missing YAML frontmatter`);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
const frontmatter = yaml.parse(match[1]);
|
|
1376
|
+
|
|
1377
|
+
// Update external_tools.github (consistent with JIRA/ADO write-back)
|
|
1378
|
+
if (!frontmatter.external_tools) {
|
|
1379
|
+
frontmatter.external_tools = {};
|
|
1380
|
+
}
|
|
1381
|
+
if (!frontmatter.external_tools.github) {
|
|
1382
|
+
frontmatter.external_tools.github = {};
|
|
1383
|
+
}
|
|
1384
|
+
frontmatter.external_tools.github.issue = issueNumber;
|
|
1385
|
+
frontmatter.external_tools.github.url = `https://github.com/${this.client.getOwner()}/${this.client.getRepo()}/issues/${issueNumber}`;
|
|
1386
|
+
// Also keep legacy external.github for backwards compatibility
|
|
1387
|
+
if (!frontmatter.external) {
|
|
1388
|
+
frontmatter.external = {};
|
|
1389
|
+
}
|
|
1390
|
+
if (!frontmatter.external.github) {
|
|
1391
|
+
frontmatter.external.github = {};
|
|
1392
|
+
}
|
|
1393
|
+
frontmatter.external.github.issue = issueNumber;
|
|
1394
|
+
frontmatter.external.github.url = frontmatter.external_tools.github.url;
|
|
1395
|
+
|
|
1396
|
+
// Rebuild content
|
|
1397
|
+
const newFrontmatter = yaml.stringify(frontmatter);
|
|
1398
|
+
const bodyContent = content.slice(match[0].length);
|
|
1399
|
+
const newContent = `---\n${newFrontmatter}---${bodyContent}`;
|
|
1400
|
+
|
|
1401
|
+
await writeFile(userStoryPath, newContent, 'utf-8');
|
|
1402
|
+
}
|
|
1403
|
+
}
|