specweave 0.18.1 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +229 -1817
- package/README.md +68 -0
- package/bin/specweave.js +62 -6
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.d.ts.map +1 -1
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js +3 -0
- package/dist/plugins/specweave/lib/hooks/sync-living-docs.js.map +1 -1
- package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts +21 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.d.ts.map +1 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.js +162 -0
- package/dist/plugins/specweave/lib/hooks/update-ac-status.js.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js +65 -6
- package/dist/plugins/specweave-ado/lib/ado-spec-content-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts +112 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.js +301 -0
- package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -0
- package/dist/plugins/specweave-github/lib/duplicate-detector.d.ts +3 -3
- package/dist/plugins/specweave-github/lib/duplicate-detector.js +3 -3
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +7 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +42 -0
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +14 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-client-v2.js +51 -0
- package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +1 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +87 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +412 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js +64 -13
- package/dist/plugins/specweave-github/lib/github-spec-content-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts +78 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js +237 -0
- package/dist/plugins/specweave-github/lib/progress-comment-builder.js.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts +97 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js +301 -0
- package/dist/plugins/specweave-github/lib/user-story-content-builder.js.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts +83 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js +386 -0
- package/dist/plugins/specweave-github/lib/user-story-issue-builder.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts +8 -6
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js +78 -117
- package/dist/plugins/specweave-jira/lib/enhanced-jira-sync.js.map +1 -1
- package/dist/src/cli/commands/import-docs.js +4 -4
- package/dist/src/cli/commands/import-docs.js.map +1 -1
- package/dist/src/cli/commands/init-multiproject.d.ts.map +1 -1
- package/dist/src/cli/commands/init-multiproject.js +17 -18
- package/dist/src/cli/commands/init-multiproject.js.map +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.d.ts.map +1 -1
- package/dist/src/cli/commands/migrate-to-multiproject.js +8 -4
- package/dist/src/cli/commands/migrate-to-multiproject.js.map +1 -1
- package/dist/src/cli/commands/switch-project.d.ts.map +1 -1
- package/dist/src/cli/commands/switch-project.js +9 -26
- package/dist/src/cli/commands/switch-project.js.map +1 -1
- package/dist/src/cli/commands/sync-spec-content.js +3 -0
- package/dist/src/cli/commands/sync-spec-content.js.map +1 -1
- package/dist/src/core/deduplication/command-deduplicator.d.ts +166 -0
- package/dist/src/core/deduplication/command-deduplicator.d.ts.map +1 -0
- package/dist/src/core/deduplication/command-deduplicator.js +254 -0
- package/dist/src/core/deduplication/command-deduplicator.js.map +1 -0
- package/dist/src/core/increment/active-increment-manager.d.ts +42 -15
- package/dist/src/core/increment/active-increment-manager.d.ts.map +1 -1
- package/dist/src/core/increment/active-increment-manager.js +113 -46
- package/dist/src/core/increment/active-increment-manager.js.map +1 -1
- package/dist/src/core/increment/conflict-resolver.d.ts +40 -0
- package/dist/src/core/increment/conflict-resolver.d.ts.map +1 -0
- package/dist/src/core/increment/conflict-resolver.js +219 -0
- package/dist/src/core/increment/conflict-resolver.js.map +1 -0
- package/dist/src/core/increment/discipline-checker.d.ts.map +1 -1
- package/dist/src/core/increment/discipline-checker.js +7 -1
- package/dist/src/core/increment/discipline-checker.js.map +1 -1
- package/dist/src/core/increment/duplicate-detector.d.ts +52 -0
- package/dist/src/core/increment/duplicate-detector.d.ts.map +1 -0
- package/dist/src/core/increment/duplicate-detector.js +276 -0
- package/dist/src/core/increment/duplicate-detector.js.map +1 -0
- package/dist/src/core/increment/increment-archiver.d.ts +90 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -0
- package/dist/src/core/increment/increment-archiver.js +368 -0
- package/dist/src/core/increment/increment-archiver.js.map +1 -0
- package/dist/src/core/increment/increment-reopener.d.ts +165 -0
- package/dist/src/core/increment/increment-reopener.d.ts.map +1 -0
- package/dist/src/core/increment/increment-reopener.js +390 -0
- package/dist/src/core/increment/increment-reopener.js.map +1 -0
- package/dist/src/core/increment/metadata-manager.d.ts +26 -1
- package/dist/src/core/increment/metadata-manager.d.ts.map +1 -1
- package/dist/src/core/increment/metadata-manager.js +143 -5
- package/dist/src/core/increment/metadata-manager.js.map +1 -1
- package/dist/src/core/increment/recent-work-scanner.d.ts +121 -0
- package/dist/src/core/increment/recent-work-scanner.d.ts.map +1 -0
- package/dist/src/core/increment/recent-work-scanner.js +303 -0
- package/dist/src/core/increment/recent-work-scanner.js.map +1 -0
- package/dist/src/core/increment/types.d.ts +1 -0
- package/dist/src/core/increment/types.d.ts.map +1 -1
- package/dist/src/core/increment-utils.d.ts +112 -0
- package/dist/src/core/increment-utils.d.ts.map +1 -0
- package/dist/src/core/increment-utils.js +210 -0
- package/dist/src/core/increment-utils.js.map +1 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.d.ts +65 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.js +175 -0
- package/dist/src/core/living-docs/ac-project-specific-generator.js.map +1 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts +130 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -0
- package/dist/src/core/living-docs/feature-archiver.js +549 -0
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts +81 -0
- package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -0
- package/dist/src/core/living-docs/feature-id-manager.js +339 -0
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -0
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts +144 -83
- package/dist/src/core/living-docs/hierarchy-mapper.d.ts.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js +488 -270
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/index.d.ts +6 -0
- package/dist/src/core/living-docs/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/index.js +6 -0
- package/dist/src/core/living-docs/index.js.map +1 -1
- package/dist/src/core/living-docs/project-detector.d.ts +6 -0
- package/dist/src/core/living-docs/project-detector.d.ts.map +1 -1
- package/dist/src/core/living-docs/project-detector.js +35 -1
- package/dist/src/core/living-docs/project-detector.js.map +1 -1
- package/dist/src/core/living-docs/spec-distributor.d.ts +100 -26
- package/dist/src/core/living-docs/spec-distributor.d.ts.map +1 -1
- package/dist/src/core/living-docs/spec-distributor.js +1275 -258
- package/dist/src/core/living-docs/spec-distributor.js.map +1 -1
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts +109 -0
- package/dist/src/core/living-docs/task-project-specific-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/task-project-specific-generator.js +221 -0
- package/dist/src/core/living-docs/task-project-specific-generator.js.map +1 -0
- package/dist/src/core/living-docs/types.d.ts +143 -0
- package/dist/src/core/living-docs/types.d.ts.map +1 -1
- package/dist/src/core/project-manager.d.ts +2 -17
- package/dist/src/core/project-manager.d.ts.map +1 -1
- package/dist/src/core/project-manager.js +68 -48
- package/dist/src/core/project-manager.js.map +1 -1
- package/dist/src/core/spec-content-sync.d.ts +1 -1
- package/dist/src/core/spec-content-sync.d.ts.map +1 -1
- package/dist/src/core/sync/enhanced-content-builder.d.ts.map +1 -1
- package/dist/src/core/sync/enhanced-content-builder.js +2 -1
- package/dist/src/core/sync/enhanced-content-builder.js.map +1 -1
- package/dist/src/core/sync/performance-optimizer.d.ts +153 -0
- package/dist/src/core/sync/performance-optimizer.d.ts.map +1 -0
- package/dist/src/core/sync/performance-optimizer.js +220 -0
- package/dist/src/core/sync/performance-optimizer.js.map +1 -0
- package/dist/src/core/sync/retry-handler.d.ts +98 -0
- package/dist/src/core/sync/retry-handler.d.ts.map +1 -0
- package/dist/src/core/sync/retry-handler.js +196 -0
- package/dist/src/core/sync/retry-handler.js.map +1 -0
- package/dist/src/core/types/config.d.ts +94 -0
- package/dist/src/core/types/config.d.ts.map +1 -1
- package/dist/src/core/types/config.js +16 -0
- package/dist/src/core/types/config.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +6 -0
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/increment-metadata.js +10 -1
- package/dist/src/core/types/increment-metadata.js.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-incremental-mapper.js +4 -8
- package/dist/src/integrations/jira/jira-incremental-mapper.js.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.d.ts.map +1 -1
- package/dist/src/integrations/jira/jira-mapper.js +4 -8
- package/dist/src/integrations/jira/jira-mapper.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/COMMANDS.md +13 -4
- package/plugins/specweave/commands/specweave-abandon.md +22 -20
- package/plugins/specweave/commands/specweave-archive-features.md +121 -0
- package/plugins/specweave/commands/specweave-archive-increments.md +82 -0
- package/plugins/specweave/commands/specweave-archive.md +363 -0
- package/plugins/specweave/commands/specweave-backlog.md +211 -0
- package/plugins/specweave/commands/specweave-fix-duplicates.md +517 -0
- package/plugins/specweave/commands/specweave-increment.md +4 -3
- package/plugins/specweave/commands/specweave-progress.md +176 -27
- package/plugins/specweave/commands/specweave-reopen.md +391 -0
- package/plugins/specweave/commands/specweave-restore-feature.md +90 -0
- package/plugins/specweave/commands/specweave-restore.md +309 -0
- package/plugins/specweave/commands/specweave-resume.md +51 -23
- package/plugins/specweave/commands/specweave-status.md +41 -7
- package/plugins/specweave/commands/specweave-sync-specs.md +425 -0
- package/plugins/specweave/hooks/hooks.json +4 -0
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +2 -2
- package/plugins/specweave/hooks/post-task-completion.sh +39 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +83 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
- package/plugins/specweave/lib/hooks/sync-living-docs.js +2 -0
- package/plugins/specweave/lib/hooks/sync-living-docs.ts +4 -0
- package/plugins/specweave/lib/hooks/update-ac-status.js +102 -0
- package/plugins/specweave/lib/hooks/update-ac-status.ts +192 -0
- package/plugins/specweave/skills/archive-increments/SKILL.md +198 -0
- package/plugins/specweave/skills/increment-planner/scripts/feature-utils.js +14 -0
- package/plugins/specweave/skills/smart-reopen-detector/SKILL.md +244 -0
- package/plugins/specweave-ado/lib/ado-spec-content-sync.js +49 -5
- package/plugins/specweave-ado/lib/ado-spec-content-sync.ts +72 -6
- package/plugins/specweave-confluent/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-confluent/README.md +375 -0
- package/plugins/specweave-confluent/agents/confluent-architect/AGENT.md +306 -0
- package/plugins/specweave-confluent/skills/confluent-kafka-connect/SKILL.md +453 -0
- package/plugins/specweave-confluent/skills/confluent-ksqldb/SKILL.md +470 -0
- package/plugins/specweave-confluent/skills/confluent-schema-registry/SKILL.md +316 -0
- package/plugins/specweave-github/agents/github-task-splitter/AGENT.md +2 -2
- package/plugins/specweave-github/agents/user-story-updater/AGENT.md +148 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +1 -1
- package/plugins/specweave-github/commands/specweave-github-update-user-story.md +156 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh +10 -9
- package/plugins/specweave-github/lib/completion-calculator.js +262 -0
- package/plugins/specweave-github/lib/completion-calculator.ts +434 -0
- package/plugins/specweave-github/lib/duplicate-detector.js +3 -3
- package/plugins/specweave-github/lib/duplicate-detector.ts +4 -4
- package/plugins/specweave-github/lib/epic-content-builder.js +38 -0
- package/plugins/specweave-github/lib/epic-content-builder.ts +59 -0
- package/plugins/specweave-github/lib/github-client-v2.js +49 -0
- package/plugins/specweave-github/lib/github-client-v2.ts +59 -0
- package/plugins/specweave-github/lib/github-epic-sync.ts +1 -1
- package/plugins/specweave-github/lib/github-feature-sync.js +381 -0
- package/plugins/specweave-github/lib/github-feature-sync.ts +568 -0
- package/plugins/specweave-github/lib/github-spec-content-sync.js +40 -10
- package/plugins/specweave-github/lib/github-spec-content-sync.ts +82 -14
- package/plugins/specweave-github/lib/progress-comment-builder.js +229 -0
- package/plugins/specweave-github/lib/progress-comment-builder.ts +324 -0
- package/plugins/specweave-github/lib/user-story-content-builder.js +299 -0
- package/plugins/specweave-github/lib/user-story-content-builder.ts +413 -0
- package/plugins/specweave-github/lib/user-story-issue-builder.js +344 -0
- package/plugins/specweave-github/lib/user-story-issue-builder.ts +543 -0
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +189 -0
- package/plugins/{specweave-ado/lib/enhanced-ado-sync.js → specweave-jira/lib/enhanced-jira-sync.js} +25 -61
- package/plugins/specweave-jira/lib/{enhanced-jira-sync.ts.disabled → enhanced-jira-sync.ts} +26 -52
- package/plugins/specweave-kafka/.claude-plugin/plugin.json +26 -0
- package/plugins/specweave-kafka/IMPLEMENTATION-COMPLETE.md +483 -0
- package/plugins/specweave-kafka/README.md +242 -0
- package/plugins/specweave-kafka/agents/kafka-architect/AGENT.md +235 -0
- package/plugins/specweave-kafka/agents/kafka-devops/AGENT.md +209 -0
- package/plugins/specweave-kafka/agents/kafka-observability/AGENT.md +266 -0
- package/plugins/specweave-kafka/commands/deploy.md +99 -0
- package/plugins/specweave-kafka/commands/dev-env.md +176 -0
- package/plugins/specweave-kafka/commands/mcp-configure.md +101 -0
- package/plugins/specweave-kafka/commands/monitor-setup.md +96 -0
- package/plugins/specweave-kafka/docker/kafka-local/docker-compose.yml +187 -0
- package/plugins/specweave-kafka/docker/redpanda/docker-compose.yml +199 -0
- package/plugins/specweave-kafka/docker/templates/consumer-nodejs.js +225 -0
- package/plugins/specweave-kafka/docker/templates/consumer-python.py +220 -0
- package/plugins/specweave-kafka/docker/templates/producer-nodejs.js +168 -0
- package/plugins/specweave-kafka/docker/templates/producer-python.py +167 -0
- package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.js +438 -0
- package/plugins/specweave-kafka/lib/adapters/apache-kafka-adapter.ts +541 -0
- package/plugins/specweave-kafka/lib/adapters/platform-adapter.js +47 -0
- package/plugins/specweave-kafka/lib/adapters/platform-adapter.ts +343 -0
- package/plugins/specweave-kafka/lib/cli/kcat-wrapper.js +258 -0
- package/plugins/specweave-kafka/lib/cli/kcat-wrapper.ts +298 -0
- package/plugins/specweave-kafka/lib/cli/types.js +10 -0
- package/plugins/specweave-kafka/lib/cli/types.ts +92 -0
- package/plugins/specweave-kafka/lib/connectors/connector-catalog.js +305 -0
- package/plugins/specweave-kafka/lib/connectors/connector-catalog.ts +528 -0
- package/plugins/specweave-kafka/lib/documentation/diagram-generator.js +114 -0
- package/plugins/specweave-kafka/lib/documentation/diagram-generator.ts +195 -0
- package/plugins/specweave-kafka/lib/documentation/exporter.js +210 -0
- package/plugins/specweave-kafka/lib/documentation/exporter.ts +338 -0
- package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.js +60 -0
- package/plugins/specweave-kafka/lib/documentation/schema-catalog-generator.ts +130 -0
- package/plugins/specweave-kafka/lib/documentation/topology-generator.js +143 -0
- package/plugins/specweave-kafka/lib/documentation/topology-generator.ts +290 -0
- package/plugins/specweave-kafka/lib/mcp/detector.js +298 -0
- package/plugins/specweave-kafka/lib/mcp/detector.ts +352 -0
- package/plugins/specweave-kafka/lib/mcp/types.js +21 -0
- package/plugins/specweave-kafka/lib/mcp/types.ts +77 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.js +193 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-config-manager.ts +362 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.js +188 -0
- package/plugins/specweave-kafka/lib/multi-cluster/cluster-switcher.ts +359 -0
- package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.js +195 -0
- package/plugins/specweave-kafka/lib/multi-cluster/health-aggregator.ts +380 -0
- package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.js +209 -0
- package/plugins/specweave-kafka/lib/observability/opentelemetry-kafka.ts +358 -0
- package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.js +354 -0
- package/plugins/specweave-kafka/lib/patterns/advanced-ksqldb-patterns.ts +563 -0
- package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.js +259 -0
- package/plugins/specweave-kafka/lib/patterns/circuit-breaker-resilience.ts +516 -0
- package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.js +233 -0
- package/plugins/specweave-kafka/lib/patterns/dead-letter-queue.ts +423 -0
- package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.js +266 -0
- package/plugins/specweave-kafka/lib/patterns/exactly-once-semantics.ts +445 -0
- package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.js +312 -0
- package/plugins/specweave-kafka/lib/patterns/flink-kafka-integration.ts +561 -0
- package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.js +289 -0
- package/plugins/specweave-kafka/lib/patterns/multi-dc-replication.ts +607 -0
- package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.js +264 -0
- package/plugins/specweave-kafka/lib/patterns/rate-limiting-backpressure.ts +498 -0
- package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.js +263 -0
- package/plugins/specweave-kafka/lib/patterns/stream-processing-optimization.ts +549 -0
- package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.js +205 -0
- package/plugins/specweave-kafka/lib/patterns/tiered-storage-compaction.ts +399 -0
- package/plugins/specweave-kafka/lib/performance/performance-optimizer.js +249 -0
- package/plugins/specweave-kafka/lib/performance/performance-optimizer.ts +427 -0
- package/plugins/specweave-kafka/lib/security/kafka-security.js +252 -0
- package/plugins/specweave-kafka/lib/security/kafka-security.ts +494 -0
- package/plugins/specweave-kafka/lib/utils/capacity-planner.js +203 -0
- package/plugins/specweave-kafka/lib/utils/capacity-planner.ts +469 -0
- package/plugins/specweave-kafka/lib/utils/config-validator.js +419 -0
- package/plugins/specweave-kafka/lib/utils/config-validator.ts +564 -0
- package/plugins/specweave-kafka/lib/utils/partitioning.js +329 -0
- package/plugins/specweave-kafka/lib/utils/partitioning.ts +473 -0
- package/plugins/specweave-kafka/lib/utils/sizing.js +221 -0
- package/plugins/specweave-kafka/lib/utils/sizing.ts +374 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-broker-metrics.json +628 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-cluster-overview.json +564 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-consumer-lag.json +509 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-jvm-metrics.json +674 -0
- package/plugins/specweave-kafka/monitoring/grafana/dashboards/kafka-topic-metrics.json +578 -0
- package/plugins/specweave-kafka/monitoring/grafana/provisioning/dashboards/kafka.yml +17 -0
- package/plugins/specweave-kafka/monitoring/grafana/provisioning/datasources/prometheus.yml +17 -0
- package/plugins/specweave-kafka/monitoring/prometheus/kafka-alerts.yml +415 -0
- package/plugins/specweave-kafka/monitoring/prometheus/kafka-jmx-exporter.yml +256 -0
- package/plugins/specweave-kafka/package.json +41 -0
- package/plugins/specweave-kafka/skills/kafka-architecture/SKILL.md +647 -0
- package/plugins/specweave-kafka/skills/kafka-cli-tools/SKILL.md +433 -0
- package/plugins/specweave-kafka/skills/kafka-iac-deployment/SKILL.md +449 -0
- package/plugins/specweave-kafka/skills/kafka-kubernetes/SKILL.md +667 -0
- package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +273 -0
- package/plugins/specweave-kafka/skills/kafka-observability/SKILL.md +576 -0
- package/plugins/specweave-kafka/templates/config/broker-production.properties +254 -0
- package/plugins/specweave-kafka/templates/config/consumer-low-latency.properties +112 -0
- package/plugins/specweave-kafka/templates/config/producer-high-throughput.properties +120 -0
- package/plugins/specweave-kafka/templates/migration/mirrormaker2-config.properties +234 -0
- package/plugins/specweave-kafka/templates/monitoring/grafana/multi-cluster-dashboard.json +686 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/main.tf +347 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/outputs.tf +107 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/templates/kafka-broker-init.sh.tpl +216 -0
- package/plugins/specweave-kafka/terraform/apache-kafka/variables.tf +156 -0
- package/plugins/specweave-kafka/terraform/aws-msk/main.tf +362 -0
- package/plugins/specweave-kafka/terraform/aws-msk/outputs.tf +93 -0
- package/plugins/specweave-kafka/terraform/aws-msk/templates/server.properties.tpl +32 -0
- package/plugins/specweave-kafka/terraform/aws-msk/variables.tf +235 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/main.tf +281 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/outputs.tf +118 -0
- package/plugins/specweave-kafka/terraform/azure-event-hubs/variables.tf +148 -0
- package/plugins/specweave-kafka/tsconfig.json +21 -0
- package/plugins/specweave-kafka-streams/.claude-plugin/plugin.json +23 -0
- package/plugins/specweave-kafka-streams/README.md +310 -0
- package/plugins/specweave-kafka-streams/skills/kafka-streams-topology/SKILL.md +539 -0
- package/plugins/specweave-n8n/.claude-plugin/plugin.json +22 -0
- package/plugins/specweave-n8n/README.md +354 -0
- package/plugins/specweave-n8n/skills/n8n-kafka-workflows/SKILL.md +504 -0
- package/plugins/specweave-release/commands/specweave-release-platform.md +1 -1
- package/plugins/specweave-release/hooks/post-task-completion.sh +2 -2
- package/src/templates/AGENTS.md.template +601 -7
- package/src/templates/CLAUDE.md.template +188 -88
- package/dist/locales/de/.gitkeep +0 -0
- package/dist/locales/de/cli.json +0 -108
- package/dist/locales/en/cli.json +0 -287
- package/dist/locales/en/errors.json +0 -7
- package/dist/locales/en/templates.json +0 -6
- package/dist/locales/es/.gitkeep +0 -0
- package/dist/locales/es/cli.json +0 -41
- package/dist/locales/fr/.gitkeep +0 -0
- package/dist/locales/fr/cli.json +0 -108
- package/dist/locales/ja/.gitkeep +0 -0
- package/dist/locales/ja/cli.json +0 -108
- package/dist/locales/ko/.gitkeep +0 -0
- package/dist/locales/ko/cli.json +0 -108
- package/dist/locales/pt/.gitkeep +0 -0
- package/dist/locales/pt/cli.json +0 -108
- package/dist/locales/ru/.gitkeep +0 -0
- package/dist/locales/ru/cli.json +0 -269
- package/dist/locales/zh/.gitkeep +0 -0
- package/dist/locales/zh/cli.json +0 -108
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts +0 -25
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -191
- package/dist/plugins/specweave-ado/lib/enhanced-ado-sync.js.map +0 -1
- package/dist/spec-parser.js +0 -629
- package/dist/src/core/sync/spec-content-sync.d.ts +0 -88
- package/dist/src/core/sync/spec-content-sync.d.ts.map +0 -1
- package/dist/src/core/sync/spec-content-sync.js +0 -5
- package/dist/src/core/sync/spec-content-sync.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/plugins/specweave-ado/commands/specweave-ado-sync-spec.md +0 -255
- package/plugins/specweave-github/commands/specweave-github-sync-epic.md +0 -248
- package/plugins/specweave-github/commands/specweave-github-sync-from.md +0 -147
- package/plugins/specweave-github/commands/specweave-github-sync-spec.md +0 -208
- package/plugins/specweave-github/commands/specweave-github-sync-tasks.md +0 -530
- package/plugins/specweave-jira/commands/specweave-jira-sync-epic.md +0 -267
- package/plugins/specweave-jira/commands/specweave-jira-sync-spec.md +0 -240
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Story Issue Builder - Creates GitHub issue content for individual User Stories
|
|
3
|
+
*
|
|
4
|
+
* Architecture (Universal Hierarchy):
|
|
5
|
+
* - Feature (FS-033) → GitHub Milestone
|
|
6
|
+
* - User Story (US-001) → GitHub Issue (this builder creates the body)
|
|
7
|
+
* - Tasks (T-001, T-002) → Checkboxes in issue body
|
|
8
|
+
*
|
|
9
|
+
* Key Features:
|
|
10
|
+
* - Reads single us-*.md file
|
|
11
|
+
* - Extracts acceptance criteria as checkboxes
|
|
12
|
+
* - Maps tasks from increment's tasks.md
|
|
13
|
+
* - Generates GitHub issue body with proper formatting
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { readFile } from 'fs/promises';
|
|
17
|
+
import { existsSync } from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import * as yaml from 'yaml';
|
|
20
|
+
|
|
21
|
+
interface UserStoryFrontmatter {
|
|
22
|
+
id: string;
|
|
23
|
+
feature: string;
|
|
24
|
+
title: string;
|
|
25
|
+
status: 'complete' | 'active' | 'planning' | 'not-started';
|
|
26
|
+
project?: string; // ✅ Optional - not all user stories specify project
|
|
27
|
+
priority?: string;
|
|
28
|
+
created: string;
|
|
29
|
+
completed?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface AcceptanceCriteria {
|
|
33
|
+
id: string; // e.g., "AC-US1-01"
|
|
34
|
+
description: string;
|
|
35
|
+
completed: boolean;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface Task {
|
|
39
|
+
id: string; // e.g., "T-001"
|
|
40
|
+
title: string;
|
|
41
|
+
completed: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export class UserStoryIssueBuilder {
|
|
45
|
+
private userStoryPath: string;
|
|
46
|
+
private projectRoot: string;
|
|
47
|
+
private featureId: string;
|
|
48
|
+
private repoOwner?: string;
|
|
49
|
+
private repoName?: string;
|
|
50
|
+
private branch?: string;
|
|
51
|
+
|
|
52
|
+
constructor(
|
|
53
|
+
userStoryPath: string,
|
|
54
|
+
projectRoot: string,
|
|
55
|
+
featureId: string,
|
|
56
|
+
repoInfo?: { owner: string; repo: string; branch?: string }
|
|
57
|
+
) {
|
|
58
|
+
this.userStoryPath = userStoryPath;
|
|
59
|
+
this.projectRoot = projectRoot;
|
|
60
|
+
this.featureId = featureId;
|
|
61
|
+
this.repoOwner = repoInfo?.owner;
|
|
62
|
+
this.repoName = repoInfo?.repo;
|
|
63
|
+
this.branch = repoInfo?.branch || 'develop';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Build GitHub issue body for a single User Story
|
|
68
|
+
*
|
|
69
|
+
* Format:
|
|
70
|
+
* - User Story statement
|
|
71
|
+
* - Acceptance Criteria (checkboxes)
|
|
72
|
+
* - Tasks (checkboxes)
|
|
73
|
+
* - Links (Feature, Increment, Spec file)
|
|
74
|
+
*/
|
|
75
|
+
async buildIssueBody(): Promise<{
|
|
76
|
+
title: string;
|
|
77
|
+
body: string;
|
|
78
|
+
labels: string[];
|
|
79
|
+
userStoryId: string;
|
|
80
|
+
status?: string;
|
|
81
|
+
}> {
|
|
82
|
+
// 1. Read User Story metadata
|
|
83
|
+
const frontmatter = await this.readUserStoryFrontmatter();
|
|
84
|
+
const content = await readFile(this.userStoryPath, 'utf-8');
|
|
85
|
+
const bodyContent = content.slice(content.indexOf('---', 3) + 3).trim();
|
|
86
|
+
|
|
87
|
+
// 2. Extract sections
|
|
88
|
+
const userStoryStatement = this.extractUserStoryStatement(bodyContent);
|
|
89
|
+
const acceptanceCriteria = this.extractAcceptanceCriteria(bodyContent);
|
|
90
|
+
const tasks = await this.extractTasks(bodyContent, frontmatter.id);
|
|
91
|
+
|
|
92
|
+
// 3. Build issue title
|
|
93
|
+
const title = `[${this.featureId}][${frontmatter.id}] ${frontmatter.title}`;
|
|
94
|
+
|
|
95
|
+
// 4. Build issue body
|
|
96
|
+
const body = this.buildBody({
|
|
97
|
+
frontmatter,
|
|
98
|
+
userStoryStatement,
|
|
99
|
+
acceptanceCriteria,
|
|
100
|
+
tasks,
|
|
101
|
+
bodyContent
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// 5. Determine labels
|
|
105
|
+
const labels = this.buildLabels(frontmatter);
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
title,
|
|
109
|
+
body,
|
|
110
|
+
labels,
|
|
111
|
+
userStoryId: frontmatter.id
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Read User Story frontmatter
|
|
117
|
+
*/
|
|
118
|
+
private async readUserStoryFrontmatter(): Promise<UserStoryFrontmatter> {
|
|
119
|
+
const content = await readFile(this.userStoryPath, 'utf-8');
|
|
120
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
121
|
+
|
|
122
|
+
if (!match) {
|
|
123
|
+
throw new Error(`${this.userStoryPath}: Missing YAML frontmatter`);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return yaml.parse(match[1]) as UserStoryFrontmatter;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Extract "As a... I want... So that..." statement
|
|
131
|
+
*/
|
|
132
|
+
private extractUserStoryStatement(content: string): string {
|
|
133
|
+
// Look for "User Story" section or "As a" pattern
|
|
134
|
+
const userStoryMatch = content.match(
|
|
135
|
+
/##\s*User Story\s*\n+([\s\S]*?)(?=\n##|$)/i
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
if (userStoryMatch) {
|
|
139
|
+
return userStoryMatch[1].trim();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Fallback: Look for "As a" pattern
|
|
143
|
+
const asAMatch = content.match(/(\*\*As a\*\*[\s\S]*?\*\*So that\*\*[^\n]*)/i);
|
|
144
|
+
if (asAMatch) {
|
|
145
|
+
return asAMatch[1].trim();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return '';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Extract Acceptance Criteria with AC-IDs and checkbox state
|
|
153
|
+
*/
|
|
154
|
+
private extractAcceptanceCriteria(content: string): AcceptanceCriteria[] {
|
|
155
|
+
const criteria: AcceptanceCriteria[] = [];
|
|
156
|
+
|
|
157
|
+
// Look for "Acceptance Criteria" section
|
|
158
|
+
const acMatch = content.match(
|
|
159
|
+
/##\s*Acceptance Criteria\s*\n+([\s\S]*?)(?=\n##|$)/i
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
if (!acMatch) {
|
|
163
|
+
return criteria;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const acSection = acMatch[1];
|
|
167
|
+
|
|
168
|
+
// ✅ FIX: Extract checkbox state and AC-IDs
|
|
169
|
+
// Supports TWO formats:
|
|
170
|
+
// Format 1 (preferred): AC-US1-01, AC-US1-02, etc.
|
|
171
|
+
// Format 2 (legacy): AC-001, AC-002, etc.
|
|
172
|
+
// Patterns:
|
|
173
|
+
// - [x] **AC-US1-01**: Description (completed)
|
|
174
|
+
// - [ ] **AC-US1-01**: Description (not completed)
|
|
175
|
+
// - [x] **AC-001**: Description (legacy format, completed)
|
|
176
|
+
// - **AC-US1-01**: Description (no checkbox, default to not completed)
|
|
177
|
+
const acPatternWithCheckbox = /(?:^|\n)\s*[-*]\s+\[([x ])\]\s+\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
|
|
178
|
+
const acPatternNoCheckbox = /(?:^|\n)\s*[-*]?\s*\*\*([A-Z]+-(?:[A-Z]+\d+-)?(\d+))\*\*:\s*([^\n]+)/g;
|
|
179
|
+
|
|
180
|
+
// First try pattern with checkboxes
|
|
181
|
+
let match;
|
|
182
|
+
let foundAny = false;
|
|
183
|
+
|
|
184
|
+
while ((match = acPatternWithCheckbox.exec(acSection)) !== null) {
|
|
185
|
+
foundAny = true;
|
|
186
|
+
criteria.push({
|
|
187
|
+
id: match[2], // e.g., "AC-US1-01" or "AC-001"
|
|
188
|
+
description: match[4].trim(),
|
|
189
|
+
completed: match[1] === 'x' // ✅ Read checkbox state from source!
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// If no checkboxes found, try pattern without checkboxes
|
|
194
|
+
if (!foundAny) {
|
|
195
|
+
while ((match = acPatternNoCheckbox.exec(acSection)) !== null) {
|
|
196
|
+
criteria.push({
|
|
197
|
+
id: match[1], // e.g., "AC-US1-01" or "AC-001"
|
|
198
|
+
description: match[3].trim(),
|
|
199
|
+
completed: false // Default to not completed
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return criteria;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Extract tasks from user story's ## Tasks section (NEW architecture)
|
|
209
|
+
*
|
|
210
|
+
* Previously: Read from increment tasks.md (LEGACY)
|
|
211
|
+
* Now: Read from user story's ## Tasks section directly
|
|
212
|
+
*
|
|
213
|
+
* This enables project-specific tasks with completion tracking per user story.
|
|
214
|
+
*/
|
|
215
|
+
private async extractTasks(
|
|
216
|
+
userStoryContent: string,
|
|
217
|
+
userStoryId: string
|
|
218
|
+
): Promise<Task[]> {
|
|
219
|
+
const tasks: Task[] = [];
|
|
220
|
+
|
|
221
|
+
// ✅ NEW: Look for ## Tasks section in user story file
|
|
222
|
+
const tasksMatch = userStoryContent.match(
|
|
223
|
+
/##\s+Tasks\s*\n+([\s\S]*?)(?=\n##|>?\s*\*\*Note\*\*:|---+|$)/i
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
if (!tasksMatch) {
|
|
227
|
+
// FALLBACK: Try old architecture (read from increment tasks.md)
|
|
228
|
+
console.log(` ℹ️ No ## Tasks section found in ${userStoryId}, falling back to legacy extraction`);
|
|
229
|
+
return this.extractTasksLegacy(userStoryContent, userStoryId);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const tasksSection = tasksMatch[1];
|
|
233
|
+
|
|
234
|
+
// Pattern: - [x] **T-001**: Task title or - [ ] **T-001**: Task title
|
|
235
|
+
const taskPattern = /^[-*]\s+\[([x ])\]\s+\*\*(T-\d+)\*\*:\s+(.+)$/gm;
|
|
236
|
+
|
|
237
|
+
let match;
|
|
238
|
+
while ((match = taskPattern.exec(tasksSection)) !== null) {
|
|
239
|
+
const completed = match[1] === 'x';
|
|
240
|
+
const taskId = match[2];
|
|
241
|
+
const taskTitle = match[3].trim();
|
|
242
|
+
|
|
243
|
+
tasks.push({
|
|
244
|
+
id: taskId,
|
|
245
|
+
title: taskTitle,
|
|
246
|
+
completed // ✅ Read checkbox state directly from user story!
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return tasks;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* LEGACY: Extract tasks from increment's tasks.md (backward compatibility)
|
|
255
|
+
*
|
|
256
|
+
* Used as fallback when user story file doesn't have ## Tasks section.
|
|
257
|
+
*/
|
|
258
|
+
private async extractTasksLegacy(
|
|
259
|
+
userStoryContent: string,
|
|
260
|
+
userStoryId: string
|
|
261
|
+
): Promise<Task[]> {
|
|
262
|
+
const tasks: Task[] = [];
|
|
263
|
+
|
|
264
|
+
// Look for "Implementation" section with increment link
|
|
265
|
+
const implMatch = userStoryContent.match(
|
|
266
|
+
/##\s*Implementation\s*\n+([\s\S]*?)(?=\n##|$)/i
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
if (!implMatch) {
|
|
270
|
+
return tasks;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const implSection = implMatch[1];
|
|
274
|
+
|
|
275
|
+
// Extract increment ID from Implementation section
|
|
276
|
+
// Pattern: **Increment**: [0031-external-tool-status-sync](...)
|
|
277
|
+
const incrementMatch = implSection.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
|
|
278
|
+
|
|
279
|
+
if (!incrementMatch) {
|
|
280
|
+
return tasks;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const incrementId = incrementMatch[1];
|
|
284
|
+
|
|
285
|
+
// Try to read increment's tasks.md
|
|
286
|
+
const tasksPath = path.join(
|
|
287
|
+
this.projectRoot,
|
|
288
|
+
'.specweave',
|
|
289
|
+
'increments',
|
|
290
|
+
incrementId,
|
|
291
|
+
'tasks.md'
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
if (!existsSync(tasksPath)) {
|
|
295
|
+
return tasks;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const tasksContent = await readFile(tasksPath, 'utf-8');
|
|
299
|
+
|
|
300
|
+
// Extract tasks that reference this User Story via AC-IDs
|
|
301
|
+
// Pattern: ### T-001: Task Title\n**User Story**: ...\n\n**Status**: [x] (100% - Completed)\n\n**AC**: AC-US1-01
|
|
302
|
+
// Note: Status field format: **Status**: [x] or [ ]
|
|
303
|
+
const taskPattern = /###?\s+(T-\d+):\s*([^\n]+)\n([\s\S]*?)(?=\n###?\s+T-\d+:|$)/g;
|
|
304
|
+
let match;
|
|
305
|
+
|
|
306
|
+
while ((match = taskPattern.exec(tasksContent)) !== null) {
|
|
307
|
+
const taskId = match[1];
|
|
308
|
+
const taskTitle = match[2].trim();
|
|
309
|
+
const taskBody = match[3];
|
|
310
|
+
|
|
311
|
+
// Extract AC list
|
|
312
|
+
const acMatch = taskBody.match(/\*\*AC\*\*:\s*([^\n]+)/);
|
|
313
|
+
if (!acMatch) {
|
|
314
|
+
continue; // Skip tasks without AC field
|
|
315
|
+
}
|
|
316
|
+
const acList = acMatch[1].trim();
|
|
317
|
+
|
|
318
|
+
// Check if any AC in this task belongs to current User Story
|
|
319
|
+
// AC-US1-01 → US-001
|
|
320
|
+
const belongsToThisUS = acList
|
|
321
|
+
.split(',')
|
|
322
|
+
.map((ac) => ac.trim())
|
|
323
|
+
.some((acId) => {
|
|
324
|
+
const usMatch = acId.match(/AC-([A-Z]+\d+)-/);
|
|
325
|
+
if (!usMatch) return false;
|
|
326
|
+
return usMatch[1] === userStoryId.replace('US-', 'US');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
if (!belongsToThisUS) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ✅ Extract completion status from **Status**: [x] or [ ]
|
|
334
|
+
const statusMatch = taskBody.match(/\*\*Status\*\*:\s*\[([x ])\]/);
|
|
335
|
+
const completed = statusMatch ? statusMatch[1] === 'x' : false;
|
|
336
|
+
|
|
337
|
+
tasks.push({
|
|
338
|
+
id: taskId,
|
|
339
|
+
title: taskTitle,
|
|
340
|
+
completed
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return tasks;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Build complete issue body
|
|
349
|
+
*/
|
|
350
|
+
private buildBody(data: {
|
|
351
|
+
frontmatter: UserStoryFrontmatter;
|
|
352
|
+
userStoryStatement: string;
|
|
353
|
+
acceptanceCriteria: AcceptanceCriteria[];
|
|
354
|
+
tasks: Task[];
|
|
355
|
+
bodyContent: string;
|
|
356
|
+
}): string {
|
|
357
|
+
const sections: string[] = [];
|
|
358
|
+
|
|
359
|
+
// Header with metadata
|
|
360
|
+
sections.push(`**Feature**: ${this.featureId}`);
|
|
361
|
+
sections.push(`**Status**: ${this.capitalize(data.frontmatter.status)}`);
|
|
362
|
+
sections.push(`**Priority**: ${data.frontmatter.priority || 'P2'}`);
|
|
363
|
+
// ✅ FIX: Only output Project if defined and not "default"
|
|
364
|
+
if (data.frontmatter.project && data.frontmatter.project !== 'default') {
|
|
365
|
+
sections.push(`**Project**: ${data.frontmatter.project}`);
|
|
366
|
+
}
|
|
367
|
+
sections.push('');
|
|
368
|
+
|
|
369
|
+
// User Story statement
|
|
370
|
+
if (data.userStoryStatement) {
|
|
371
|
+
sections.push('## User Story');
|
|
372
|
+
sections.push('');
|
|
373
|
+
sections.push(data.userStoryStatement);
|
|
374
|
+
sections.push('');
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Acceptance Criteria
|
|
378
|
+
if (data.acceptanceCriteria.length > 0) {
|
|
379
|
+
sections.push('## Acceptance Criteria');
|
|
380
|
+
sections.push('');
|
|
381
|
+
for (const ac of data.acceptanceCriteria) {
|
|
382
|
+
const checkbox = ac.completed ? '[x]' : '[ ]';
|
|
383
|
+
sections.push(`- ${checkbox} **${ac.id}**: ${ac.description}`);
|
|
384
|
+
}
|
|
385
|
+
sections.push('');
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Tasks
|
|
389
|
+
if (data.tasks.length > 0) {
|
|
390
|
+
sections.push('## Tasks');
|
|
391
|
+
sections.push('');
|
|
392
|
+
for (const task of data.tasks) {
|
|
393
|
+
const checkbox = task.completed ? '[x]' : '[ ]';
|
|
394
|
+
sections.push(`- ${checkbox} **${task.id}**: ${task.title}`);
|
|
395
|
+
}
|
|
396
|
+
sections.push('');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Extract Business Rationale if present
|
|
400
|
+
const rationaleMatch = data.bodyContent.match(
|
|
401
|
+
/##\s*Business Rationale\s*\n+([\s\S]*?)(?=\n##|$)/i
|
|
402
|
+
);
|
|
403
|
+
if (rationaleMatch) {
|
|
404
|
+
sections.push('## Business Rationale');
|
|
405
|
+
sections.push('');
|
|
406
|
+
sections.push(rationaleMatch[1].trim());
|
|
407
|
+
sections.push('');
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// ✅ NEW: Extract Related User Stories if present
|
|
411
|
+
const relatedMatch = data.bodyContent.match(
|
|
412
|
+
/##\s*Related User Stories\s*\n+([\s\S]*?)(?=\n##|---+|$)/i
|
|
413
|
+
);
|
|
414
|
+
if (relatedMatch) {
|
|
415
|
+
sections.push('## Related User Stories');
|
|
416
|
+
sections.push('');
|
|
417
|
+
|
|
418
|
+
// Convert relative paths to GitHub blob URLs
|
|
419
|
+
let relatedContent = relatedMatch[1].trim();
|
|
420
|
+
if (this.repoOwner && this.repoName) {
|
|
421
|
+
const baseUrl = `https://github.com/${this.repoOwner}/${this.repoName}/blob/${this.branch}`;
|
|
422
|
+
|
|
423
|
+
// Replace relative links like us-002-*.md to proper GitHub URLs
|
|
424
|
+
// Pattern: - [US-002: Title](us-002-file-name.md)
|
|
425
|
+
relatedContent = relatedContent.replace(
|
|
426
|
+
/\(([^)]+\.md)\)/g,
|
|
427
|
+
(match, filename) => {
|
|
428
|
+
// If it's already an absolute URL, don't change it
|
|
429
|
+
if (filename.startsWith('http')) {
|
|
430
|
+
return match;
|
|
431
|
+
}
|
|
432
|
+
// Get the project folder from the current user story path
|
|
433
|
+
const projectMatch = this.userStoryPath.match(/\/specs\/([^/]+)\/FS-[^/]+\//);
|
|
434
|
+
const project = projectMatch ? projectMatch[1] : 'default';
|
|
435
|
+
const featureId = this.featureId;
|
|
436
|
+
return `(${baseUrl}/.specweave/docs/internal/specs/${project}/${featureId}/${filename})`;
|
|
437
|
+
}
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
sections.push(relatedContent);
|
|
442
|
+
sections.push('');
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// ✅ FIX: Extract Implementation section if present
|
|
446
|
+
const implMatch = data.bodyContent.match(
|
|
447
|
+
/##\s*Implementation\s*\n+([\s\S]*?)(?=\n##|$)/i
|
|
448
|
+
);
|
|
449
|
+
if (implMatch) {
|
|
450
|
+
sections.push('## Implementation');
|
|
451
|
+
sections.push('');
|
|
452
|
+
|
|
453
|
+
// Convert relative paths to GitHub blob URLs
|
|
454
|
+
let implContent = implMatch[1].trim();
|
|
455
|
+
if (this.repoOwner && this.repoName) {
|
|
456
|
+
const baseUrl = `https://github.com/${this.repoOwner}/${this.repoName}/blob/${this.branch}`;
|
|
457
|
+
|
|
458
|
+
// Replace relative paths like ../../../../../increments/0031-*/tasks.md
|
|
459
|
+
// Pattern: ../ repeated multiple times, then increments/XXXX-name/tasks.md or spec.md
|
|
460
|
+
implContent = implContent.replace(
|
|
461
|
+
/\.\.(\/\.\.)+\/increments\/([\w-]+)\/([\w.-]+(?:#[\w-]+)?)/g,
|
|
462
|
+
`${baseUrl}/.specweave/increments/$2/$3`
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
// Replace relative paths to specs like ../../specs/default/FS-XXX/...
|
|
466
|
+
implContent = implContent.replace(
|
|
467
|
+
/\.\.(\/\.\.)+\/specs\/([\w-]+)\/([\w-]+)\/([\w.-]+(?:#[\w-]+)?)/g,
|
|
468
|
+
`${baseUrl}/.specweave/docs/internal/specs/$2/$3/$4`
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
sections.push(implContent);
|
|
473
|
+
sections.push('');
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Links
|
|
477
|
+
sections.push('---');
|
|
478
|
+
sections.push('');
|
|
479
|
+
sections.push('## Links');
|
|
480
|
+
sections.push('');
|
|
481
|
+
|
|
482
|
+
// Generate proper GitHub blob URLs
|
|
483
|
+
if (this.repoOwner && this.repoName) {
|
|
484
|
+
const baseUrl = `https://github.com/${this.repoOwner}/${this.repoName}/blob/${this.branch}`;
|
|
485
|
+
|
|
486
|
+
// Feature Spec link
|
|
487
|
+
sections.push(`- **Feature Spec**: [${this.featureId}](${baseUrl}/.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
|
|
488
|
+
|
|
489
|
+
// User Story File link (relative to project root)
|
|
490
|
+
const relativeUSPath = path.relative(this.projectRoot, this.userStoryPath);
|
|
491
|
+
sections.push(`- **User Story File**: [${path.basename(this.userStoryPath)}](${baseUrl}/${relativeUSPath})`);
|
|
492
|
+
|
|
493
|
+
// Increment link (extracted from Implementation section)
|
|
494
|
+
const incrementMatch = implMatch?.[1]?.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
|
|
495
|
+
if (incrementMatch) {
|
|
496
|
+
const incrementId = incrementMatch[1];
|
|
497
|
+
sections.push(`- **Increment**: [${incrementId}](${baseUrl}/.specweave/increments/${incrementId})`);
|
|
498
|
+
}
|
|
499
|
+
} else {
|
|
500
|
+
// Fallback to relative links if repo info not provided
|
|
501
|
+
sections.push(`- **Feature Spec**: [${this.featureId}](../.specweave/docs/internal/specs/_features/${this.featureId}/FEATURE.md)`);
|
|
502
|
+
sections.push(`- **User Story File**: [${path.basename(this.userStoryPath)}](${this.userStoryPath})`);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
sections.push('');
|
|
506
|
+
sections.push('---');
|
|
507
|
+
sections.push('');
|
|
508
|
+
sections.push('🤖 Auto-created by SpecWeave User Story Sync | Updates automatically');
|
|
509
|
+
|
|
510
|
+
return sections.join('\n');
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/**
|
|
514
|
+
* Build labels for the issue
|
|
515
|
+
*/
|
|
516
|
+
private buildLabels(frontmatter: UserStoryFrontmatter): string[] {
|
|
517
|
+
const labels: string[] = ['user-story', 'specweave'];
|
|
518
|
+
|
|
519
|
+
// Add status label
|
|
520
|
+
if (frontmatter.status) {
|
|
521
|
+
labels.push(`status:${frontmatter.status}`);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Add priority label
|
|
525
|
+
if (frontmatter.priority) {
|
|
526
|
+
labels.push(frontmatter.priority.toLowerCase());
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
// Add project label
|
|
530
|
+
if (frontmatter.project && frontmatter.project !== 'default') {
|
|
531
|
+
labels.push(`project:${frontmatter.project}`);
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
return labels;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Capitalize first letter
|
|
539
|
+
*/
|
|
540
|
+
private capitalize(str: string): string {
|
|
541
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
542
|
+
}
|
|
543
|
+
}
|