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,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Increment Reopener
|
|
3
|
+
*
|
|
4
|
+
* Handles reopening of completed increments, tasks, and user stories
|
|
5
|
+
* when issues are discovered after completion.
|
|
6
|
+
*
|
|
7
|
+
* Part of smart reopen functionality (increment 0032)
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs-extra';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { MetadataManager } from './metadata-manager.js';
|
|
12
|
+
import { ActiveIncrementManager } from './active-increment-manager.js';
|
|
13
|
+
import { IncrementStatus, TYPE_LIMITS } from '../types/increment-metadata.js';
|
|
14
|
+
/**
|
|
15
|
+
* Reopen target types
|
|
16
|
+
*/
|
|
17
|
+
export var ReopenTarget;
|
|
18
|
+
(function (ReopenTarget) {
|
|
19
|
+
/** Reopen entire increment */
|
|
20
|
+
ReopenTarget["INCREMENT"] = "increment";
|
|
21
|
+
/** Reopen specific task(s) */
|
|
22
|
+
ReopenTarget["TASK"] = "task";
|
|
23
|
+
/** Reopen user story + related tasks */
|
|
24
|
+
ReopenTarget["USER_STORY"] = "user-story";
|
|
25
|
+
})(ReopenTarget || (ReopenTarget = {}));
|
|
26
|
+
/**
|
|
27
|
+
* Increment Reopener
|
|
28
|
+
*
|
|
29
|
+
* Provides smart reopen functionality for increments, tasks, and user stories
|
|
30
|
+
*/
|
|
31
|
+
export class IncrementReopener {
|
|
32
|
+
/**
|
|
33
|
+
* Reopen a completed increment
|
|
34
|
+
*
|
|
35
|
+
* @param context - Reopen context
|
|
36
|
+
* @returns Reopen result
|
|
37
|
+
*/
|
|
38
|
+
static async reopenIncrement(context) {
|
|
39
|
+
const { incrementId, reason, force } = context;
|
|
40
|
+
const result = {
|
|
41
|
+
success: false,
|
|
42
|
+
itemsReopened: [],
|
|
43
|
+
warnings: [],
|
|
44
|
+
errors: []
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
// 1. Validate increment exists
|
|
48
|
+
if (!MetadataManager.exists(incrementId)) {
|
|
49
|
+
result.errors.push(`Increment ${incrementId} not found`);
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
// 2. Read metadata
|
|
53
|
+
const metadata = MetadataManager.read(incrementId);
|
|
54
|
+
// 3. Check current status
|
|
55
|
+
if (metadata.status !== IncrementStatus.COMPLETED) {
|
|
56
|
+
result.errors.push(`Cannot reopen: increment status is ${metadata.status}, not completed`);
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
// 4. Validate WIP limits
|
|
60
|
+
const wipValidation = this.validateWIPLimits(metadata, force);
|
|
61
|
+
if (!wipValidation.allowed && !force) {
|
|
62
|
+
result.errors.push(wipValidation.message || 'WIP limit exceeded');
|
|
63
|
+
result.wipLimitExceeded = true;
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
if (wipValidation.warning) {
|
|
67
|
+
result.warnings.push(wipValidation.message || 'WIP limit will be exceeded');
|
|
68
|
+
result.wipLimitExceeded = true;
|
|
69
|
+
}
|
|
70
|
+
// 5. Update metadata: COMPLETED → ACTIVE
|
|
71
|
+
const previousStatus = metadata.status;
|
|
72
|
+
metadata.status = IncrementStatus.ACTIVE;
|
|
73
|
+
metadata.lastActivity = new Date().toISOString();
|
|
74
|
+
// 6. Add reopen history (audit trail)
|
|
75
|
+
if (!metadata.reopened) {
|
|
76
|
+
metadata.reopened = { count: 0, history: [] };
|
|
77
|
+
}
|
|
78
|
+
metadata.reopened.count++;
|
|
79
|
+
metadata.reopened.history.push({
|
|
80
|
+
date: new Date().toISOString(),
|
|
81
|
+
reason,
|
|
82
|
+
previousStatus,
|
|
83
|
+
by: 'user'
|
|
84
|
+
});
|
|
85
|
+
// 7. Write metadata
|
|
86
|
+
MetadataManager.write(incrementId, metadata);
|
|
87
|
+
// 8. Update active increment cache
|
|
88
|
+
const activeManager = new ActiveIncrementManager();
|
|
89
|
+
activeManager.setActive(incrementId);
|
|
90
|
+
// 9. Reopen uncompleted tasks (if any)
|
|
91
|
+
const tasksReopened = await this.reopenUncompletedTasks(incrementId, reason);
|
|
92
|
+
result.itemsReopened.push(...tasksReopened);
|
|
93
|
+
// Success!
|
|
94
|
+
result.success = true;
|
|
95
|
+
result.itemsReopened.push(`Increment ${incrementId}`);
|
|
96
|
+
result.metadata = metadata;
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
result.errors.push(`Failed to reopen increment: ${error instanceof Error ? error.message : String(error)}`);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Reopen specific task(s) in an increment
|
|
106
|
+
*
|
|
107
|
+
* @param context - Reopen context
|
|
108
|
+
* @returns Reopen result
|
|
109
|
+
*/
|
|
110
|
+
static async reopenTask(context) {
|
|
111
|
+
const { incrementId, taskId, reason } = context;
|
|
112
|
+
const result = {
|
|
113
|
+
success: false,
|
|
114
|
+
itemsReopened: [],
|
|
115
|
+
warnings: [],
|
|
116
|
+
errors: []
|
|
117
|
+
};
|
|
118
|
+
try {
|
|
119
|
+
// 1. Validate increment exists
|
|
120
|
+
if (!MetadataManager.exists(incrementId)) {
|
|
121
|
+
result.errors.push(`Increment ${incrementId} not found`);
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
// 2. Validate task ID provided
|
|
125
|
+
if (!taskId) {
|
|
126
|
+
result.errors.push('Task ID required for task reopen');
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
// 3. Read tasks.md
|
|
130
|
+
const incrementPath = path.join(process.cwd(), '.specweave', 'increments', incrementId);
|
|
131
|
+
const tasksPath = path.join(incrementPath, 'tasks.md');
|
|
132
|
+
if (!fs.existsSync(tasksPath)) {
|
|
133
|
+
result.errors.push(`tasks.md not found for increment ${incrementId}`);
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
let tasksContent = fs.readFileSync(tasksPath, 'utf-8');
|
|
137
|
+
// 4. Find task and reopen it
|
|
138
|
+
const taskPattern = new RegExp(`^(#{2,3}) (${taskId}): (.+)$`, 'gm');
|
|
139
|
+
let taskFound = false;
|
|
140
|
+
tasksContent = tasksContent.replace(taskPattern, (match, hashes, id, title) => {
|
|
141
|
+
taskFound = true;
|
|
142
|
+
return `${hashes} ${id}: ${title}`;
|
|
143
|
+
});
|
|
144
|
+
if (!taskFound) {
|
|
145
|
+
result.errors.push(`Task ${taskId} not found in tasks.md`);
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
// 5. Update task status: [x] → [ ]
|
|
149
|
+
// Find the Status line after the task heading
|
|
150
|
+
const statusPattern = new RegExp(`(#{2,3} ${taskId}:[^\\n]+\\n[^\\n]*?\\n\\*\\*Status\\*\\*: )\\[x\\]`, 'gi');
|
|
151
|
+
tasksContent = tasksContent.replace(statusPattern, (match, prefix) => {
|
|
152
|
+
return `${prefix}[ ] (Reopened: ${new Date().toISOString().split('T')[0]} - ${reason})`;
|
|
153
|
+
});
|
|
154
|
+
// 6. Write updated tasks.md
|
|
155
|
+
fs.writeFileSync(tasksPath, tasksContent, 'utf-8');
|
|
156
|
+
// 7. Touch increment (update lastActivity)
|
|
157
|
+
MetadataManager.touch(incrementId);
|
|
158
|
+
// Success!
|
|
159
|
+
result.success = true;
|
|
160
|
+
result.itemsReopened.push(`Task ${taskId}`);
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
result.errors.push(`Failed to reopen task: ${error instanceof Error ? error.message : String(error)}`);
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Reopen user story + related tasks
|
|
170
|
+
*
|
|
171
|
+
* @param context - Reopen context
|
|
172
|
+
* @returns Reopen result
|
|
173
|
+
*/
|
|
174
|
+
static async reopenUserStory(context) {
|
|
175
|
+
const { incrementId, userStoryId, reason } = context;
|
|
176
|
+
const result = {
|
|
177
|
+
success: false,
|
|
178
|
+
itemsReopened: [],
|
|
179
|
+
warnings: [],
|
|
180
|
+
errors: []
|
|
181
|
+
};
|
|
182
|
+
try {
|
|
183
|
+
// 1. Validate user story ID provided
|
|
184
|
+
if (!userStoryId) {
|
|
185
|
+
result.errors.push('User story ID required for user story reopen');
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
// 2. Find tasks related to user story (AC field matching)
|
|
189
|
+
const tasks = await this.findTasksForUserStory(incrementId, userStoryId);
|
|
190
|
+
if (tasks.length === 0) {
|
|
191
|
+
result.warnings.push(`No tasks found for user story ${userStoryId}`);
|
|
192
|
+
// Still proceed to mark user story as reopened in living docs
|
|
193
|
+
}
|
|
194
|
+
// 3. Reopen each task
|
|
195
|
+
for (const taskId of tasks) {
|
|
196
|
+
const taskResult = await this.reopenTask({
|
|
197
|
+
target: ReopenTarget.TASK,
|
|
198
|
+
incrementId,
|
|
199
|
+
taskId,
|
|
200
|
+
reason: `Reopened via user story ${userStoryId}: ${reason}`,
|
|
201
|
+
force: context.force
|
|
202
|
+
});
|
|
203
|
+
if (taskResult.success) {
|
|
204
|
+
result.itemsReopened.push(...taskResult.itemsReopened);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
result.warnings.push(`Failed to reopen task ${taskId}: ${taskResult.errors.join(', ')}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// 4. Update user story status in living docs (if exists)
|
|
211
|
+
const userStoryUpdated = await this.updateUserStoryStatus(incrementId, userStoryId, 'reopened', reason);
|
|
212
|
+
if (userStoryUpdated) {
|
|
213
|
+
result.itemsReopened.push(`User story ${userStoryId}`);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
result.warnings.push(`Could not update user story ${userStoryId} in living docs`);
|
|
217
|
+
}
|
|
218
|
+
// Success if at least one item reopened
|
|
219
|
+
result.success = result.itemsReopened.length > 0;
|
|
220
|
+
return result;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
result.errors.push(`Failed to reopen user story: ${error instanceof Error ? error.message : String(error)}`);
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Validate WIP limits before reopening
|
|
229
|
+
*
|
|
230
|
+
* @param metadata - Increment metadata
|
|
231
|
+
* @param force - Force reopen?
|
|
232
|
+
* @returns Validation result
|
|
233
|
+
*/
|
|
234
|
+
static validateWIPLimits(metadata, force) {
|
|
235
|
+
const type = metadata.type;
|
|
236
|
+
const limit = TYPE_LIMITS[type];
|
|
237
|
+
// If unlimited type (hotfix, bug, experiment), allow
|
|
238
|
+
if (limit === null) {
|
|
239
|
+
return { allowed: true, warning: false };
|
|
240
|
+
}
|
|
241
|
+
// Count current active of same type
|
|
242
|
+
const activeCount = MetadataManager.getActive()
|
|
243
|
+
.filter(m => m.type === type)
|
|
244
|
+
.length;
|
|
245
|
+
// If reopening would exceed limit, warn or block
|
|
246
|
+
if (activeCount >= limit) {
|
|
247
|
+
const message = `Reopening will exceed WIP limit (${activeCount + 1}/${limit} active ${type}s). Complete or pause another ${type} first, or use --force.`;
|
|
248
|
+
if (force) {
|
|
249
|
+
return {
|
|
250
|
+
allowed: true,
|
|
251
|
+
warning: true,
|
|
252
|
+
message,
|
|
253
|
+
activeCount,
|
|
254
|
+
limit
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return {
|
|
258
|
+
allowed: false,
|
|
259
|
+
warning: true,
|
|
260
|
+
message,
|
|
261
|
+
activeCount,
|
|
262
|
+
limit
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
return { allowed: true, warning: false, activeCount, limit };
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Reopen uncompleted tasks in increment
|
|
269
|
+
*
|
|
270
|
+
* @param incrementId - Increment ID
|
|
271
|
+
* @param reason - Reason for reopening
|
|
272
|
+
* @returns List of reopened task IDs
|
|
273
|
+
*/
|
|
274
|
+
static async reopenUncompletedTasks(incrementId, reason) {
|
|
275
|
+
const incrementPath = path.join(process.cwd(), '.specweave', 'increments', incrementId);
|
|
276
|
+
const tasksPath = path.join(incrementPath, 'tasks.md');
|
|
277
|
+
if (!fs.existsSync(tasksPath)) {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
let tasksContent = fs.readFileSync(tasksPath, 'utf-8');
|
|
281
|
+
const reopenedTasks = [];
|
|
282
|
+
// Find all completed tasks: **Status**: [x]
|
|
283
|
+
const completedTaskPattern = /^(#{2,3}) (T-\d+): (.+)$[\s\S]*?\*\*Status\*\*: \[x\]/gm;
|
|
284
|
+
const matches = tasksContent.matchAll(completedTaskPattern);
|
|
285
|
+
for (const match of matches) {
|
|
286
|
+
const taskId = match[2];
|
|
287
|
+
reopenedTasks.push(taskId);
|
|
288
|
+
}
|
|
289
|
+
// Reopen all completed tasks
|
|
290
|
+
if (reopenedTasks.length > 0) {
|
|
291
|
+
tasksContent = tasksContent.replace(/\*\*Status\*\*: \[x\]/g, `**Status**: [ ] (Reopened: ${new Date().toISOString().split('T')[0]} - ${reason})`);
|
|
292
|
+
fs.writeFileSync(tasksPath, tasksContent, 'utf-8');
|
|
293
|
+
}
|
|
294
|
+
return reopenedTasks;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Find tasks that implement a user story (by AC field)
|
|
298
|
+
*
|
|
299
|
+
* @param incrementId - Increment ID
|
|
300
|
+
* @param userStoryId - User story ID (e.g., "US-001")
|
|
301
|
+
* @returns List of task IDs
|
|
302
|
+
*/
|
|
303
|
+
static async findTasksForUserStory(incrementId, userStoryId) {
|
|
304
|
+
const incrementPath = path.join(process.cwd(), '.specweave', 'increments', incrementId);
|
|
305
|
+
const tasksPath = path.join(incrementPath, 'tasks.md');
|
|
306
|
+
if (!fs.existsSync(tasksPath)) {
|
|
307
|
+
return [];
|
|
308
|
+
}
|
|
309
|
+
const tasksContent = fs.readFileSync(tasksPath, 'utf-8');
|
|
310
|
+
const tasks = [];
|
|
311
|
+
// Extract user story number (US-001 → 001 or 1)
|
|
312
|
+
const usNumber = userStoryId.replace(/^US-0*/, '');
|
|
313
|
+
// Find tasks with AC field referencing this user story
|
|
314
|
+
// Pattern: **AC**: AC-US1-01, AC-US1-02, ...
|
|
315
|
+
const acPattern = new RegExp(`^#{2,3} (T-\\d+):[^\\n]+[\\s\\S]*?\\*\\*AC\\*\\*:[^\\n]*AC-US${usNumber}-`, 'gm');
|
|
316
|
+
const matches = tasksContent.matchAll(acPattern);
|
|
317
|
+
for (const match of matches) {
|
|
318
|
+
tasks.push(match[1]);
|
|
319
|
+
}
|
|
320
|
+
return tasks;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Update user story status in living docs
|
|
324
|
+
*
|
|
325
|
+
* @param incrementId - Increment ID
|
|
326
|
+
* @param userStoryId - User story ID
|
|
327
|
+
* @param status - New status
|
|
328
|
+
* @param reason - Reason
|
|
329
|
+
* @returns Success flag
|
|
330
|
+
*/
|
|
331
|
+
static async updateUserStoryStatus(incrementId, userStoryId, status, reason) {
|
|
332
|
+
try {
|
|
333
|
+
// Find user story file in living docs
|
|
334
|
+
const specPath = path.join(process.cwd(), '.specweave', 'docs', 'internal', 'specs');
|
|
335
|
+
// Search for user story file (pattern: us-001-*.md)
|
|
336
|
+
const usFiles = await this.findUserStoryFiles(specPath, userStoryId);
|
|
337
|
+
if (usFiles.length === 0) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
// Update status in each file
|
|
341
|
+
for (const usFile of usFiles) {
|
|
342
|
+
let content = fs.readFileSync(usFile, 'utf-8');
|
|
343
|
+
// Update frontmatter status
|
|
344
|
+
content = content.replace(/^status: .+$/m, `status: ${status}`);
|
|
345
|
+
// Add reopen note
|
|
346
|
+
const reopenNote = `\n\n---\n**Reopened**: ${new Date().toISOString().split('T')[0]} - ${reason}\n`;
|
|
347
|
+
if (!content.includes('**Reopened**')) {
|
|
348
|
+
content += reopenNote;
|
|
349
|
+
}
|
|
350
|
+
fs.writeFileSync(usFile, content, 'utf-8');
|
|
351
|
+
}
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
console.error(`Failed to update user story status: ${error}`);
|
|
356
|
+
return false;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Find user story files in living docs
|
|
361
|
+
*
|
|
362
|
+
* @param basePath - Base search path
|
|
363
|
+
* @param userStoryId - User story ID (e.g., "US-001")
|
|
364
|
+
* @returns List of file paths
|
|
365
|
+
*/
|
|
366
|
+
static async findUserStoryFiles(basePath, userStoryId) {
|
|
367
|
+
const files = [];
|
|
368
|
+
if (!fs.existsSync(basePath)) {
|
|
369
|
+
return files;
|
|
370
|
+
}
|
|
371
|
+
// Extract user story number (US-001 → 001)
|
|
372
|
+
const usNumber = userStoryId.replace(/^US-/, '').toLowerCase();
|
|
373
|
+
// Recursively search for us-XXX-*.md files
|
|
374
|
+
const searchDir = (dir) => {
|
|
375
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
376
|
+
for (const entry of entries) {
|
|
377
|
+
const fullPath = path.join(dir, entry.name);
|
|
378
|
+
if (entry.isDirectory()) {
|
|
379
|
+
searchDir(fullPath);
|
|
380
|
+
}
|
|
381
|
+
else if (entry.isFile() && entry.name.match(new RegExp(`^us-${usNumber}-.*\\.md$`, 'i'))) {
|
|
382
|
+
files.push(fullPath);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
searchDir(basePath);
|
|
387
|
+
return files;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
//# sourceMappingURL=increment-reopener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"increment-reopener.js","sourceRoot":"","sources":["../../../../src/core/increment/increment-reopener.ts"],"names":[],"mappings":"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"}
|
|
@@ -36,6 +36,21 @@ export declare class MetadataManager {
|
|
|
36
36
|
* Creates default metadata if file doesn't exist (lazy initialization)
|
|
37
37
|
*/
|
|
38
38
|
static read(incrementId: string): IncrementMetadata;
|
|
39
|
+
/**
|
|
40
|
+
* Reserved increment IDs that cannot be used
|
|
41
|
+
* These are status values, special folders, and state files
|
|
42
|
+
*/
|
|
43
|
+
private static readonly RESERVED_INCREMENT_IDS;
|
|
44
|
+
/**
|
|
45
|
+
* Validate increment ID is not a reserved name
|
|
46
|
+
* Throws if ID is reserved
|
|
47
|
+
*/
|
|
48
|
+
private static validateNotReserved;
|
|
49
|
+
/**
|
|
50
|
+
* Validate increment before creation (check for duplicates and reserved names)
|
|
51
|
+
* Throws if duplicates exist in other locations or ID is reserved
|
|
52
|
+
*/
|
|
53
|
+
static validateBeforeCreate(incrementId: string, rootDir?: string): Promise<void>;
|
|
39
54
|
/**
|
|
40
55
|
* Write metadata to file
|
|
41
56
|
* Uses atomic write (temp file → rename)
|
|
@@ -69,9 +84,19 @@ export declare class MetadataManager {
|
|
|
69
84
|
*/
|
|
70
85
|
static getByStatus(status: IncrementStatus): IncrementMetadata[];
|
|
71
86
|
/**
|
|
72
|
-
* Get active increments
|
|
87
|
+
* Get active increments (FAST: cache-first strategy)
|
|
88
|
+
*
|
|
89
|
+
* **PERFORMANCE UPGRADE**: Uses ActiveIncrementManager cache instead of scanning all increments
|
|
90
|
+
* - Old: Scan 31 metadata files (~50ms)
|
|
91
|
+
* - New: Read 1 cache file + 1-2 metadata files (~5ms) = **10x faster**
|
|
92
|
+
*
|
|
93
|
+
* Fallback to full scan if cache is stale or missing
|
|
73
94
|
*/
|
|
74
95
|
static getActive(): IncrementMetadata[];
|
|
96
|
+
/**
|
|
97
|
+
* Get backlog increments
|
|
98
|
+
*/
|
|
99
|
+
static getBacklog(): IncrementMetadata[];
|
|
75
100
|
/**
|
|
76
101
|
* Get paused increments
|
|
77
102
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata-manager.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/metadata-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,eAAe,EACf,aAAa,EAKd,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"metadata-manager.d.ts","sourceRoot":"","sources":["../../../../src/core/increment/metadata-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,eAAe,EACf,aAAa,EAKd,MAAM,gCAAgC,CAAC;AAIxC;;GAEG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACF,WAAW,EAAE,MAAM;IAAS,KAAK,CAAC,EAAE,KAAK;gBAAjE,OAAO,EAAE,MAAM,EAAS,WAAW,EAAE,MAAM,EAAS,KAAK,CAAC,EAAE,KAAK;CAI9E;AAED;;;;GAIG;AACH,qBAAa,eAAe;IAC1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAK9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAK/B;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAK3C;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB;IA+CnD;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAY5C;IAEF;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAmClC;;;OAGG;WACU,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BvF;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IA8BpE;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAmBxC;;;;;OAKG;IACH,MAAM,CAAC,YAAY,CACjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,eAAe,EAC1B,MAAM,CAAC,EAAE,MAAM,GACd,iBAAiB;IAsDpB;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,iBAAiB;IAQ9E;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB;IAOpD;;OAEG;IACH,MAAM,CAAC,MAAM,IAAI,iBAAiB,EAAE;IAyBpC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,iBAAiB,EAAE;IAIhE;;;;;;;;OAQG;IACH,MAAM,CAAC,SAAS,IAAI,iBAAiB,EAAE;IA6DvC;;OAEG;IACH,MAAM,CAAC,UAAU,IAAI,iBAAiB,EAAE;IAIxC;;OAEG;IACH,MAAM,CAAC,SAAS,IAAI,iBAAiB,EAAE;IAIvC;;OAEG;IACH,MAAM,CAAC,YAAY,IAAI,iBAAiB,EAAE;IAI1C;;OAEG;IACH,MAAM,CAAC,YAAY,IAAI,iBAAiB,EAAE;IAI1C;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,aAAa,GAAG,iBAAiB,EAAE;IAI1D;;OAEG;IACH,MAAM,CAAC,QAAQ,IAAI,iBAAiB,EAAE;IAItC;;OAEG;IACH,MAAM,CAAC,oBAAoB,IAAI,iBAAiB,EAAE;IAIlD;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,yBAAyB;IAyClE;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAwBrD;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,eAAe,GAAG,OAAO;IAIzE;;OAEG;IACH,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,eAAe,GAAG,MAAM;CAe9E"}
|
|
@@ -8,6 +8,7 @@ import fs from 'fs-extra';
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import { IncrementStatus, IncrementType, createDefaultMetadata, isValidTransition, isStale, shouldAutoAbandon } from '../types/increment-metadata.js';
|
|
10
10
|
import { ActiveIncrementManager } from './active-increment-manager.js';
|
|
11
|
+
import { detectDuplicatesByNumber } from './duplicate-detector.js';
|
|
11
12
|
/**
|
|
12
13
|
* Error thrown when metadata operations fail
|
|
13
14
|
*/
|
|
@@ -64,9 +65,10 @@ export class MetadataManager {
|
|
|
64
65
|
this.write(incrementId, defaultMetadata);
|
|
65
66
|
// **CRITICAL**: Update active increment state if default status is ACTIVE
|
|
66
67
|
// This ensures that newly created increments are immediately tracked for status line
|
|
68
|
+
// Skip validation to prevent circular dependency during lazy initialization
|
|
67
69
|
if (defaultMetadata.status === IncrementStatus.ACTIVE) {
|
|
68
70
|
const activeManager = new ActiveIncrementManager();
|
|
69
|
-
activeManager.setActive(incrementId);
|
|
71
|
+
activeManager.setActive(incrementId, true); // skipValidation = true
|
|
70
72
|
}
|
|
71
73
|
return defaultMetadata;
|
|
72
74
|
}
|
|
@@ -82,6 +84,57 @@ export class MetadataManager {
|
|
|
82
84
|
throw new MetadataError(`Failed to read metadata for ${incrementId}: ${errorMessage}`, incrementId, error instanceof Error ? error : new Error(String(error)));
|
|
83
85
|
}
|
|
84
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* Validate increment ID is not a reserved name
|
|
89
|
+
* Throws if ID is reserved
|
|
90
|
+
*/
|
|
91
|
+
static validateNotReserved(incrementId) {
|
|
92
|
+
// Check exact match
|
|
93
|
+
if (this.RESERVED_INCREMENT_IDS.includes(incrementId)) {
|
|
94
|
+
throw new MetadataError(`Invalid increment ID "${incrementId}": This is a reserved name.\n\n` +
|
|
95
|
+
`Reserved names include:\n` +
|
|
96
|
+
` - Status values: active, backlog, paused, completed, abandoned\n` +
|
|
97
|
+
` - Special folders: _archive, _templates, _config\n` +
|
|
98
|
+
` - State files: active-increment, state, config\n\n` +
|
|
99
|
+
`Please use a descriptive name like "0035-my-feature" instead.`, incrementId);
|
|
100
|
+
}
|
|
101
|
+
// Check if it starts with underscore (reserved for special folders)
|
|
102
|
+
if (incrementId.startsWith('_')) {
|
|
103
|
+
throw new MetadataError(`Invalid increment ID "${incrementId}": Increment IDs cannot start with underscore.\n` +
|
|
104
|
+
`Names starting with "_" are reserved for special folders like _archive.\n\n` +
|
|
105
|
+
`Please use a name like "0035-my-feature" instead.`, incrementId);
|
|
106
|
+
}
|
|
107
|
+
// Check base name (before first hyphen) is not reserved
|
|
108
|
+
const baseName = incrementId.split('-')[0];
|
|
109
|
+
if (this.RESERVED_INCREMENT_IDS.includes(baseName)) {
|
|
110
|
+
throw new MetadataError(`Invalid increment ID "${incrementId}": Base name "${baseName}" is reserved.\n\n` +
|
|
111
|
+
`Please use a 4-digit number prefix like "0035-my-feature".`, incrementId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Validate increment before creation (check for duplicates and reserved names)
|
|
116
|
+
* Throws if duplicates exist in other locations or ID is reserved
|
|
117
|
+
*/
|
|
118
|
+
static async validateBeforeCreate(incrementId, rootDir) {
|
|
119
|
+
// Check for reserved names first
|
|
120
|
+
this.validateNotReserved(incrementId);
|
|
121
|
+
// Extract increment number from ID (e.g., "0033-feature-name" → "0033")
|
|
122
|
+
const numberMatch = incrementId.match(/^(\d+)/);
|
|
123
|
+
if (!numberMatch) {
|
|
124
|
+
throw new MetadataError(`Invalid increment ID format: ${incrementId}. Expected format: ####-name`, incrementId);
|
|
125
|
+
}
|
|
126
|
+
const incrementNumber = numberMatch[1];
|
|
127
|
+
// Check for duplicates
|
|
128
|
+
const duplicates = await detectDuplicatesByNumber(incrementNumber, rootDir || process.cwd());
|
|
129
|
+
if (duplicates.length > 0) {
|
|
130
|
+
const locations = duplicates.map(d => d.path).join('\n - ');
|
|
131
|
+
throw new MetadataError(`Cannot create increment ${incrementId}: Increment number ${incrementNumber} already exists in other location(s):\n - ${locations}\n\n` +
|
|
132
|
+
`Resolution options:\n` +
|
|
133
|
+
` 1. Use a different increment number\n` +
|
|
134
|
+
` 2. Delete/archive the existing increment(s)\n` +
|
|
135
|
+
` 3. Run /specweave:fix-duplicates to resolve conflicts`, incrementId);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
85
138
|
/**
|
|
86
139
|
* Write metadata to file
|
|
87
140
|
* Uses atomic write (temp file → rename)
|
|
@@ -138,12 +191,18 @@ export class MetadataManager {
|
|
|
138
191
|
metadata.status = newStatus;
|
|
139
192
|
metadata.lastActivity = new Date().toISOString();
|
|
140
193
|
// Update status-specific fields
|
|
141
|
-
if (newStatus === IncrementStatus.
|
|
194
|
+
if (newStatus === IncrementStatus.BACKLOG) {
|
|
195
|
+
metadata.backlogReason = reason || 'Planned for future work';
|
|
196
|
+
metadata.backlogAt = new Date().toISOString();
|
|
197
|
+
}
|
|
198
|
+
else if (newStatus === IncrementStatus.PAUSED) {
|
|
142
199
|
metadata.pausedReason = reason || 'No reason provided';
|
|
143
200
|
metadata.pausedAt = new Date().toISOString();
|
|
144
201
|
}
|
|
145
202
|
else if (newStatus === IncrementStatus.ACTIVE) {
|
|
146
|
-
// Clear paused fields when
|
|
203
|
+
// Clear backlog/paused fields when activating
|
|
204
|
+
metadata.backlogReason = undefined;
|
|
205
|
+
metadata.backlogAt = undefined;
|
|
147
206
|
metadata.pausedReason = undefined;
|
|
148
207
|
metadata.pausedAt = undefined;
|
|
149
208
|
}
|
|
@@ -159,6 +218,7 @@ export class MetadataManager {
|
|
|
159
218
|
activeManager.setActive(incrementId);
|
|
160
219
|
}
|
|
161
220
|
else if (newStatus === IncrementStatus.COMPLETED ||
|
|
221
|
+
newStatus === IncrementStatus.BACKLOG ||
|
|
162
222
|
newStatus === IncrementStatus.PAUSED ||
|
|
163
223
|
newStatus === IncrementStatus.ABANDONED) {
|
|
164
224
|
// Increment no longer active → smart update (find next active or clear)
|
|
@@ -217,10 +277,74 @@ export class MetadataManager {
|
|
|
217
277
|
return this.getAll().filter(m => m.status === status);
|
|
218
278
|
}
|
|
219
279
|
/**
|
|
220
|
-
* Get active increments
|
|
280
|
+
* Get active increments (FAST: cache-first strategy)
|
|
281
|
+
*
|
|
282
|
+
* **PERFORMANCE UPGRADE**: Uses ActiveIncrementManager cache instead of scanning all increments
|
|
283
|
+
* - Old: Scan 31 metadata files (~50ms)
|
|
284
|
+
* - New: Read 1 cache file + 1-2 metadata files (~5ms) = **10x faster**
|
|
285
|
+
*
|
|
286
|
+
* Fallback to full scan if cache is stale or missing
|
|
221
287
|
*/
|
|
222
288
|
static getActive() {
|
|
223
|
-
|
|
289
|
+
const activeManager = new ActiveIncrementManager();
|
|
290
|
+
// FAST PATH: Read from cache
|
|
291
|
+
const cachedIds = activeManager.getActive();
|
|
292
|
+
if (cachedIds.length > 0) {
|
|
293
|
+
// Validate cache is correct
|
|
294
|
+
const isValid = activeManager.validate();
|
|
295
|
+
if (isValid) {
|
|
296
|
+
// Cache is good! Read only the cached increments
|
|
297
|
+
return cachedIds
|
|
298
|
+
.map(id => {
|
|
299
|
+
try {
|
|
300
|
+
return this.read(id);
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
// Stale cache entry, trigger rebuild
|
|
304
|
+
activeManager.smartUpdate();
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
.filter((m) => m !== null);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
// SLOW PATH: Cache miss or invalid, scan all increments
|
|
312
|
+
const allActive = this.getByStatus(IncrementStatus.ACTIVE);
|
|
313
|
+
// Rebuild cache from scan results (DIRECTLY without calling smartUpdate to avoid circular dependency)
|
|
314
|
+
if (allActive.length > 0) {
|
|
315
|
+
// Sort by lastActivity (most recent first)
|
|
316
|
+
const sorted = allActive.sort((a, b) => {
|
|
317
|
+
const aTime = new Date(a.lastActivity).getTime();
|
|
318
|
+
const bTime = new Date(b.lastActivity).getTime();
|
|
319
|
+
return bTime - aTime; // Descending
|
|
320
|
+
});
|
|
321
|
+
// Take max 2 and write state directly
|
|
322
|
+
const activeIds = sorted.slice(0, 2).map(m => m.id);
|
|
323
|
+
const state = {
|
|
324
|
+
ids: activeIds,
|
|
325
|
+
lastUpdated: new Date().toISOString()
|
|
326
|
+
};
|
|
327
|
+
// Write state directly using private method (copy logic from ActiveIncrementManager.writeState)
|
|
328
|
+
const stateFile = activeManager.getStateFilePath();
|
|
329
|
+
const stateDir = path.dirname(stateFile);
|
|
330
|
+
if (!fs.existsSync(stateDir)) {
|
|
331
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
332
|
+
}
|
|
333
|
+
const tempFile = `${stateFile}.tmp`;
|
|
334
|
+
fs.writeFileSync(tempFile, JSON.stringify(state, null, 2), 'utf-8');
|
|
335
|
+
fs.renameSync(tempFile, stateFile);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// No active increments, clear cache
|
|
339
|
+
activeManager.clearActive();
|
|
340
|
+
}
|
|
341
|
+
return allActive;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Get backlog increments
|
|
345
|
+
*/
|
|
346
|
+
static getBacklog() {
|
|
347
|
+
return this.getByStatus(IncrementStatus.BACKLOG);
|
|
224
348
|
}
|
|
225
349
|
/**
|
|
226
350
|
* Get paused increments
|
|
@@ -338,4 +462,18 @@ export class MetadataManager {
|
|
|
338
462
|
return `Invalid transition: ${from} → ${to}`;
|
|
339
463
|
}
|
|
340
464
|
}
|
|
465
|
+
/**
|
|
466
|
+
* Reserved increment IDs that cannot be used
|
|
467
|
+
* These are status values, special folders, and state files
|
|
468
|
+
*/
|
|
469
|
+
MetadataManager.RESERVED_INCREMENT_IDS = [
|
|
470
|
+
// Status values (would confuse state management)
|
|
471
|
+
'active', 'backlog', 'paused', 'completed', 'abandoned',
|
|
472
|
+
// Special folders (file system conflicts)
|
|
473
|
+
'_archive', '_templates', '_config',
|
|
474
|
+
// State files (would overwrite critical files)
|
|
475
|
+
'active-increment', 'state', 'config',
|
|
476
|
+
// Common terms that should not be IDs
|
|
477
|
+
'current', 'latest', 'new', 'temp', 'test'
|
|
478
|
+
];
|
|
341
479
|
//# sourceMappingURL=metadata-manager.js.map
|