specweave 0.22.14 → 0.23.0

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.
Files changed (150) hide show
  1. package/CLAUDE.md +178 -1
  2. package/dist/src/cli/commands/import-external.d.ts +22 -0
  3. package/dist/src/cli/commands/import-external.d.ts.map +1 -0
  4. package/dist/src/cli/commands/import-external.js +282 -0
  5. package/dist/src/cli/commands/import-external.js.map +1 -0
  6. package/dist/src/cli/commands/init.d.ts.map +1 -1
  7. package/dist/src/cli/commands/init.js +46 -0
  8. package/dist/src/cli/commands/init.js.map +1 -1
  9. package/dist/src/cli/helpers/github-repo-selector.d.ts +59 -0
  10. package/dist/src/cli/helpers/github-repo-selector.d.ts.map +1 -0
  11. package/dist/src/cli/helpers/github-repo-selector.js +265 -0
  12. package/dist/src/cli/helpers/github-repo-selector.js.map +1 -0
  13. package/dist/src/config/types.d.ts +16 -16
  14. package/dist/src/core/increment/ac-status-manager.d.ts.map +1 -1
  15. package/dist/src/core/increment/ac-status-manager.js +4 -2
  16. package/dist/src/core/increment/ac-status-manager.js.map +1 -1
  17. package/dist/src/core/increment/completion-validator.d.ts +30 -1
  18. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  19. package/dist/src/core/increment/completion-validator.js +151 -3
  20. package/dist/src/core/increment/completion-validator.js.map +1 -1
  21. package/dist/src/core/increment/increment-archiver.d.ts +25 -0
  22. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  23. package/dist/src/core/increment/increment-archiver.js +130 -3
  24. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  25. package/dist/src/core/living-docs/feature-archiver.d.ts +37 -0
  26. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  27. package/dist/src/core/living-docs/feature-archiver.js +262 -18
  28. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  29. package/dist/src/core/living-docs/feature-id-manager.d.ts +17 -0
  30. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  31. package/dist/src/core/living-docs/feature-id-manager.js +25 -0
  32. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  33. package/dist/src/core/living-docs/living-docs-sync.d.ts +14 -0
  34. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  35. package/dist/src/core/living-docs/living-docs-sync.js +46 -0
  36. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  37. package/dist/src/core/sync/sync-event-logger.d.ts +15 -1
  38. package/dist/src/core/sync/sync-event-logger.d.ts.map +1 -1
  39. package/dist/src/core/sync/sync-event-logger.js +39 -1
  40. package/dist/src/core/sync/sync-event-logger.js.map +1 -1
  41. package/dist/src/core/types/sync-config-validator.d.ts +57 -0
  42. package/dist/src/core/types/sync-config-validator.d.ts.map +1 -0
  43. package/dist/src/core/types/sync-config-validator.js +116 -0
  44. package/dist/src/core/types/sync-config-validator.js.map +1 -0
  45. package/dist/src/importers/duplicate-detector.d.ts +107 -0
  46. package/dist/src/importers/duplicate-detector.d.ts.map +1 -0
  47. package/dist/src/importers/duplicate-detector.js +189 -0
  48. package/dist/src/importers/duplicate-detector.js.map +1 -0
  49. package/dist/src/importers/import-coordinator.d.ts +15 -0
  50. package/dist/src/importers/import-coordinator.d.ts.map +1 -1
  51. package/dist/src/importers/import-coordinator.js +43 -1
  52. package/dist/src/importers/import-coordinator.js.map +1 -1
  53. package/dist/src/importers/item-converter.d.ts +5 -0
  54. package/dist/src/importers/item-converter.d.ts.map +1 -1
  55. package/dist/src/importers/item-converter.js +27 -2
  56. package/dist/src/importers/item-converter.js.map +1 -1
  57. package/dist/src/importers/rate-limiter.d.ts +128 -0
  58. package/dist/src/importers/rate-limiter.d.ts.map +1 -0
  59. package/dist/src/importers/rate-limiter.js +200 -0
  60. package/dist/src/importers/rate-limiter.js.map +1 -0
  61. package/dist/src/init/compliance/types.d.ts +2 -2
  62. package/dist/src/integrations/ado/ado-client.d.ts +6 -0
  63. package/dist/src/integrations/ado/ado-client.d.ts.map +1 -1
  64. package/dist/src/integrations/ado/ado-client.js +23 -0
  65. package/dist/src/integrations/ado/ado-client.js.map +1 -1
  66. package/dist/src/integrations/jira/jira-client.d.ts +6 -0
  67. package/dist/src/integrations/jira/jira-client.d.ts.map +1 -1
  68. package/dist/src/integrations/jira/jira-client.js +38 -0
  69. package/dist/src/integrations/jira/jira-client.js.map +1 -1
  70. package/dist/src/sync/external-item-sync-service.d.ts +150 -0
  71. package/dist/src/sync/external-item-sync-service.d.ts.map +1 -0
  72. package/dist/src/sync/external-item-sync-service.js +241 -0
  73. package/dist/src/sync/external-item-sync-service.js.map +1 -0
  74. package/dist/src/sync/format-preservation-sync.d.ts +90 -0
  75. package/dist/src/sync/format-preservation-sync.d.ts.map +1 -0
  76. package/dist/src/sync/format-preservation-sync.js +173 -0
  77. package/dist/src/sync/format-preservation-sync.js.map +1 -0
  78. package/dist/src/sync/index.d.ts +8 -0
  79. package/dist/src/sync/index.d.ts.map +1 -0
  80. package/dist/src/sync/index.js +6 -0
  81. package/dist/src/sync/index.js.map +1 -0
  82. package/dist/src/sync/sync-coordinator.d.ts +49 -0
  83. package/dist/src/sync/sync-coordinator.d.ts.map +1 -0
  84. package/dist/src/sync/sync-coordinator.js +248 -0
  85. package/dist/src/sync/sync-coordinator.js.map +1 -0
  86. package/dist/src/sync/sync-metadata.d.ts +75 -0
  87. package/dist/src/sync/sync-metadata.d.ts.map +1 -0
  88. package/dist/src/sync/sync-metadata.js +100 -0
  89. package/dist/src/sync/sync-metadata.js.map +1 -0
  90. package/dist/src/types/living-docs-us-file.d.ts +63 -0
  91. package/dist/src/types/living-docs-us-file.d.ts.map +1 -0
  92. package/dist/src/types/living-docs-us-file.js +27 -0
  93. package/dist/src/types/living-docs-us-file.js.map +1 -0
  94. package/dist/src/validators/format-preservation-validator.d.ts +127 -0
  95. package/dist/src/validators/format-preservation-validator.d.ts.map +1 -0
  96. package/dist/src/validators/format-preservation-validator.js +187 -0
  97. package/dist/src/validators/format-preservation-validator.js.map +1 -0
  98. package/package.json +3 -2
  99. package/plugins/specweave/.claude-plugin/plugin.json +20 -0
  100. package/plugins/specweave/commands/specweave-archive-features.md +11 -1
  101. package/plugins/specweave/commands/specweave-import-docs.md +88 -278
  102. package/plugins/specweave/commands/specweave-import-external.md +407 -0
  103. package/plugins/specweave/hooks/post-edit-spec.sh +41 -0
  104. package/plugins/specweave/hooks/post-increment-completion.sh +0 -0
  105. package/plugins/specweave/hooks/post-spec-update.sh +0 -0
  106. package/plugins/specweave/hooks/post-task-completion.sh +13 -3
  107. package/plugins/specweave/hooks/post-write-spec.sh +37 -0
  108. package/plugins/specweave/lib/hooks/auto-transition.js +1 -1
  109. package/plugins/specweave/lib/hooks/auto-transition.ts +1 -1
  110. package/plugins/specweave/lib/hooks/invoke-translator-skill.js +1 -1
  111. package/plugins/specweave/lib/hooks/invoke-translator-skill.ts +1 -1
  112. package/plugins/specweave/lib/hooks/sync-living-docs.js +35 -1
  113. package/plugins/specweave/lib/hooks/sync-us-tasks.js +179 -3
  114. package/plugins/specweave/lib/hooks/translate-file.js +1 -1
  115. package/plugins/specweave/lib/hooks/translate-file.ts +1 -1
  116. package/plugins/specweave/lib/hooks/update-ac-status.js +1 -1
  117. package/plugins/specweave/lib/hooks/update-ac-status.ts +1 -1
  118. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.d.ts +115 -0
  119. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js +345 -0
  120. package/plugins/specweave/lib/vendor/core/increment/ac-status-manager.js.map +1 -0
  121. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.d.ts +106 -0
  122. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js +220 -0
  123. package/plugins/specweave/lib/vendor/core/increment/active-increment-manager.js.map +1 -0
  124. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.d.ts +60 -0
  125. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js +192 -0
  126. package/plugins/specweave/lib/vendor/core/increment/auto-transition-manager.js.map +1 -0
  127. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.d.ts +52 -0
  128. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +276 -0
  129. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -0
  130. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.d.ts +163 -0
  131. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js +541 -0
  132. package/plugins/specweave/lib/vendor/core/increment/metadata-manager.js.map +1 -0
  133. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +157 -0
  134. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js +191 -0
  135. package/plugins/specweave/lib/vendor/core/types/increment-metadata.js.map +1 -0
  136. package/plugins/specweave/lib/vendor/generators/spec/task-parser.d.ts +95 -0
  137. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js +301 -0
  138. package/plugins/specweave/lib/vendor/generators/spec/task-parser.js.map +1 -0
  139. package/plugins/specweave/lib/vendor/utils/logger.d.ts +48 -0
  140. package/plugins/specweave/lib/vendor/utils/logger.js +53 -0
  141. package/plugins/specweave/lib/vendor/utils/logger.js.map +1 -0
  142. package/plugins/specweave/lib/vendor/utils/translation.d.ts +187 -0
  143. package/plugins/specweave/lib/vendor/utils/translation.js +414 -0
  144. package/plugins/specweave/lib/vendor/utils/translation.js.map +1 -0
  145. package/plugins/specweave-ado/lib/ado-multi-project-sync.js +0 -1
  146. package/plugins/specweave-github/commands/specweave-github-update-user-story.md +1 -1
  147. package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +1 -1
  148. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
  149. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +0 -170
  150. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +0 -5694
@@ -0,0 +1,241 @@
1
+ /**
2
+ * External Item Sync Service
3
+ *
4
+ * Handles synchronization with external tools (GitHub, JIRA, ADO) while
5
+ * preserving original item format and preventing unintended modifications.
6
+ *
7
+ * Key Features:
8
+ * - Comment-based updates for external items (format preservation)
9
+ * - Full sync for internal items (title, description, ACs)
10
+ * - Format preservation validation
11
+ * - External title immutability
12
+ *
13
+ * Part of increment 0047-us-task-linkage (T-034B)
14
+ */
15
+ import fs from 'fs-extra';
16
+ import path from 'path';
17
+ import matter from 'gray-matter';
18
+ import { consoleLogger } from '../utils/logger.js';
19
+ import { FormatPreservationValidator } from '../validators/format-preservation-validator.js';
20
+ /**
21
+ * External Item Sync Service
22
+ *
23
+ * Routes sync operations based on format_preservation flag.
24
+ * External items (format_preservation=true) → comment-only sync
25
+ * Internal items (format_preservation=false) → full sync
26
+ */
27
+ export class ExternalItemSyncService {
28
+ constructor(options = {}) {
29
+ this.logger = options.logger ?? consoleLogger;
30
+ this.validator = new FormatPreservationValidator({ logger: this.logger });
31
+ }
32
+ /**
33
+ * Sync task completion to external tool
34
+ *
35
+ * Routes to comment-only or full sync based on format_preservation flag
36
+ *
37
+ * @param completionData - Task completion data
38
+ * @param options - Sync options
39
+ * @returns Sync result
40
+ */
41
+ async syncTaskCompletion(completionData, options) {
42
+ try {
43
+ this.logger.log(` 🔄 Syncing task ${completionData.taskId} completion for ${completionData.usId}...`);
44
+ // Read format preservation flag from living docs
45
+ const formatPreservation = await this.getFormatPreservation(completionData.usId, completionData.featureId, options.projectRoot);
46
+ // Force full sync if requested (e.g., for internal items or testing)
47
+ if (options.forceFullSync) {
48
+ this.logger.log(` 📝 Full sync mode (force flag enabled)`);
49
+ return await this.fullSync(completionData, options);
50
+ }
51
+ // Route based on format_preservation flag
52
+ if (formatPreservation) {
53
+ this.logger.log(` 💬 Comment-only mode (format preservation enabled)`);
54
+ return await this.commentOnlySync(completionData, options);
55
+ }
56
+ else {
57
+ this.logger.log(` 📝 Full sync mode (format preservation disabled)`);
58
+ return await this.fullSync(completionData, options);
59
+ }
60
+ }
61
+ catch (error) {
62
+ this.logger.error(` ❌ Sync failed for ${completionData.taskId}:`, error);
63
+ return {
64
+ success: false,
65
+ mode: 'skipped',
66
+ reason: 'Error during sync',
67
+ error: error.message
68
+ };
69
+ }
70
+ }
71
+ /**
72
+ * Get format_preservation flag from living docs User Story file
73
+ *
74
+ * @param usId - User Story ID (e.g., "US-009")
75
+ * @param featureId - Feature ID (e.g., "FS-047")
76
+ * @param projectRoot - Project root directory
77
+ * @returns True if format preservation enabled
78
+ */
79
+ async getFormatPreservation(usId, featureId, projectRoot) {
80
+ try {
81
+ // Find US file in living docs
82
+ const usFilePath = await this.findUSFile(projectRoot, featureId, usId);
83
+ if (!usFilePath) {
84
+ this.logger.warn(` ⚠️ Living docs file not found for ${usId}, defaulting to full sync`);
85
+ return false;
86
+ }
87
+ // Parse frontmatter
88
+ const content = await fs.readFile(usFilePath, 'utf-8');
89
+ const parsed = matter(content);
90
+ const frontmatter = parsed.data;
91
+ // Default to false (full sync) if not specified
92
+ return frontmatter.format_preservation === true;
93
+ }
94
+ catch (error) {
95
+ this.logger.warn(` ⚠️ Failed to read format_preservation for ${usId}: ${error.message}`);
96
+ return false; // Default to full sync on error
97
+ }
98
+ }
99
+ /**
100
+ * Find User Story file in living docs
101
+ *
102
+ * @param projectRoot - Project root
103
+ * @param featureId - Feature ID (e.g., "FS-047")
104
+ * @param usId - User Story ID (e.g., "US-009")
105
+ * @returns Path to US file or null if not found
106
+ */
107
+ async findUSFile(projectRoot, featureId, usId) {
108
+ // Pattern: .specweave/docs/internal/specs/{project}/{feature}/us-{id}-*.md
109
+ const specsDir = path.join(projectRoot, '.specweave', 'docs', 'internal', 'specs');
110
+ // Search in all projects (default and multi-project)
111
+ const projectDirs = await this.getProjectDirs(specsDir);
112
+ for (const projectDir of projectDirs) {
113
+ const featureDir = path.join(projectDir, featureId);
114
+ if (!await fs.pathExists(featureDir))
115
+ continue;
116
+ const files = await fs.readdir(featureDir);
117
+ const usFile = files.find(f => f.toLowerCase().startsWith(`${usId.toLowerCase()}-`));
118
+ if (usFile) {
119
+ return path.join(featureDir, usFile);
120
+ }
121
+ }
122
+ return null;
123
+ }
124
+ /**
125
+ * Get all project directories in specs
126
+ *
127
+ * @param specsDir - Specs directory
128
+ * @returns Array of project directory paths
129
+ */
130
+ async getProjectDirs(specsDir) {
131
+ if (!await fs.pathExists(specsDir)) {
132
+ return [];
133
+ }
134
+ const entries = await fs.readdir(specsDir, { withFileTypes: true });
135
+ const projectDirs = entries
136
+ .filter(e => e.isDirectory() && !e.name.startsWith('_'))
137
+ .map(e => path.join(specsDir, e.name));
138
+ return projectDirs;
139
+ }
140
+ /**
141
+ * Comment-only sync: Post completion update as comment
142
+ *
143
+ * Does NOT modify external item title, description, or acceptance criteria.
144
+ * Only posts a comment with task completion status.
145
+ *
146
+ * @param completionData - Task completion data
147
+ * @param options - Sync options
148
+ * @returns Sync result
149
+ */
150
+ async commentOnlySync(completionData, options) {
151
+ // Format completion comment
152
+ const comment = this.formatCompletionComment(completionData);
153
+ if (options.dryRun) {
154
+ this.logger.log(` 🔍 [DRY RUN] Would post comment:\n${comment}`);
155
+ return {
156
+ success: true,
157
+ mode: 'comment-only',
158
+ reason: 'Format preservation enabled (external item)',
159
+ comment
160
+ };
161
+ }
162
+ // TODO: Integrate with external tool APIs (GitHub, JIRA, ADO)
163
+ // For now, just log the comment that would be posted
164
+ this.logger.log(` 💬 Comment to post:\n${comment}`);
165
+ return {
166
+ success: true,
167
+ mode: 'comment-only',
168
+ reason: 'Format preservation enabled (external item)',
169
+ comment
170
+ };
171
+ }
172
+ /**
173
+ * Full sync: Update external item title, description, ACs
174
+ *
175
+ * Used for internal items or when format preservation disabled.
176
+ *
177
+ * @param completionData - Task completion data
178
+ * @param options - Sync options
179
+ * @returns Sync result
180
+ */
181
+ async fullSync(completionData, options) {
182
+ const updatedFields = [];
183
+ // Validate sync operation (NEW - T-034C)
184
+ const formatPreservation = await this.getFormatPreservation(completionData.usId, completionData.featureId, options.projectRoot);
185
+ const syncOperation = {
186
+ usId: completionData.usId,
187
+ formatPreservation,
188
+ updates: ['title', 'description', 'acceptance_criteria'],
189
+ origin: formatPreservation ? 'external' : 'internal'
190
+ };
191
+ const validation = this.validator.validate(syncOperation);
192
+ if (!validation.valid) {
193
+ this.logger.error(` ❌ Full sync blocked by format preservation validation:`, validation.errors?.join(', '));
194
+ return {
195
+ success: false,
196
+ mode: 'skipped',
197
+ reason: 'Format preservation validation failed',
198
+ error: validation.errors?.join('; ')
199
+ };
200
+ }
201
+ if (options.dryRun) {
202
+ this.logger.log(` 🔍 [DRY RUN] Would perform full sync for ${completionData.usId}`);
203
+ return {
204
+ success: true,
205
+ mode: 'full-sync',
206
+ reason: 'Format preservation disabled (internal item)',
207
+ updatedFields: validation.allowedFields
208
+ };
209
+ }
210
+ // TODO: Implement full sync logic
211
+ // - Update external item title
212
+ // - Update external item description
213
+ // - Update acceptance criteria checkboxes
214
+ this.logger.log(` 📝 Full sync for ${completionData.usId} (not yet implemented)`);
215
+ return {
216
+ success: true,
217
+ mode: 'full-sync',
218
+ reason: 'Format preservation disabled (internal item)',
219
+ updatedFields: validation.allowedFields
220
+ };
221
+ }
222
+ /**
223
+ * Format completion comment for external tool
224
+ *
225
+ * @param data - Task completion data
226
+ * @returns Formatted comment
227
+ */
228
+ formatCompletionComment(data) {
229
+ const statusEmoji = data.status === 'completed' ? '✅' : '🔄';
230
+ return `${statusEmoji} **[${data.featureId}][${data.taskId}]** ${data.taskTitle}
231
+
232
+ **Status**: ${data.status}
233
+ **Acceptance Criteria Satisfied**: ${data.satisfiesACs.length > 0 ? data.satisfiesACs.join(', ') : 'None'}
234
+ **Progress**: ${data.completedTasks}/${data.totalTasks} tasks (${data.percentage}%)
235
+ ${data.livingDocsUrl ? `**Living Docs**: [View spec](${data.livingDocsUrl})` : ''}
236
+
237
+ ---
238
+ *Auto-posted by SpecWeave format preservation sync*`;
239
+ }
240
+ }
241
+ //# sourceMappingURL=external-item-sync-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-item-sync-service.js","sourceRoot":"","sources":["../../../src/sync/external-item-sync-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Format Preservation Sync Service (T-034B)
3
+ *
4
+ * Routes sync to comment-only mode for external items (preserves original format)
5
+ * and full sync mode for internal items (allows title/description updates).
6
+ *
7
+ * Architecture:
8
+ * - External US (origin=external): Comment-only sync (no title/description changes)
9
+ * - Internal US (origin=internal): Full sync (title, description, status, comments)
10
+ */
11
+ import { LivingDocsUSFile } from '../types/living-docs-us-file.js';
12
+ import { GitHubClientV2 } from '../../plugins/specweave-github/lib/github-client-v2.js';
13
+ import { JiraClient } from '../integrations/jira/jira-client.js';
14
+ import { AdoClient } from '../integrations/ado/ado-client.js';
15
+ import { Logger } from '../utils/logger.js';
16
+ export interface SyncConfig {
17
+ /** Allow updating external items from SpecWeave (Internal → External) */
18
+ canUpdateExternalItems?: boolean;
19
+ /** Allow upserting internal items from external tools (External → Internal) */
20
+ canUpsertInternalItems?: boolean;
21
+ /** Allow status updates (both directions) */
22
+ canUpdateStatus?: boolean;
23
+ }
24
+ export interface TaskCompletionInfo {
25
+ taskId: string;
26
+ title: string;
27
+ completed: boolean;
28
+ }
29
+ export interface ACCompletionInfo {
30
+ acId: string;
31
+ description: string;
32
+ satisfied: boolean;
33
+ }
34
+ export interface CompletionCommentData {
35
+ tasks: TaskCompletionInfo[];
36
+ acceptanceCriteria: ACCompletionInfo[];
37
+ progressPercentage: number;
38
+ livingDocsUrl?: string;
39
+ }
40
+ export declare class FormatPreservationSyncService {
41
+ private logger;
42
+ private config;
43
+ constructor(config?: SyncConfig, options?: {
44
+ logger?: Logger;
45
+ });
46
+ /**
47
+ * Sync User Story to external tool with origin-based routing
48
+ *
49
+ * - External US (origin=external) → Comment-only sync
50
+ * - Internal US (origin=internal) → Full sync
51
+ */
52
+ syncUserStory(usFile: LivingDocsUSFile, completionData: CompletionCommentData, externalClient: GitHubClientV2 | JiraClient | AdoClient): Promise<void>;
53
+ /**
54
+ * Sync External US (Comment-only mode)
55
+ *
56
+ * Preserves original title/description, only adds completion comments
57
+ */
58
+ private syncExternalUS;
59
+ /**
60
+ * Sync Internal US (Full sync mode)
61
+ *
62
+ * Allows updating title, description, status, and comments
63
+ */
64
+ private syncInternalUS;
65
+ /**
66
+ * Build completion comment with task/AC progress
67
+ *
68
+ * Format:
69
+ * ## Progress Update
70
+ *
71
+ * ### Completed Tasks
72
+ * - ✅ [T-001] Task title
73
+ * - ✅ [T-002] Another task
74
+ *
75
+ * ### Acceptance Criteria
76
+ * - ✅ **AC-US1-01**: Criteria description
77
+ * - ✅ **AC-US1-02**: Another criteria
78
+ *
79
+ * **Progress**: 8/11 tasks completed (73%)
80
+ *
81
+ * [View Living Docs](url)
82
+ */
83
+ buildCompletionComment(data: CompletionCommentData): string;
84
+ /**
85
+ * Extract issue number from external_id
86
+ * Examples: "GH-#123" → 123, "#456" → 456
87
+ */
88
+ private extractIssueNumber;
89
+ }
90
+ //# sourceMappingURL=format-preservation-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-preservation-sync.d.ts","sourceRoot":"","sources":["../../../src/sync/format-preservation-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,gBAAgB,EAAa,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,UAAU;IACzB,yEAAyE;IACzE,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,+EAA+E;IAC/E,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC,6CAA6C;IAC7C,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;IACvC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,6BAA6B;IACxC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAa;gBAGzB,MAAM,GAAE,UAAe,EACvB,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO;IAUnC;;;;;OAKG;IACG,aAAa,CACjB,MAAM,EAAE,gBAAgB,EACxB,cAAc,EAAE,qBAAqB,EACrC,cAAc,EAAE,cAAc,GAAG,UAAU,GAAG,SAAS,GACtD,OAAO,CAAC,IAAI,CAAC;IAchB;;;;OAIG;YACW,cAAc;IA+B5B;;;;OAIG;YACW,cAAc;IAuC5B;;;;;;;;;;;;;;;;;OAiBG;IACH,sBAAsB,CAAC,IAAI,EAAE,qBAAqB,GAAG,MAAM;IA0C3D;;;OAGG;IACH,OAAO,CAAC,kBAAkB;CAI3B"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Format Preservation Sync Service (T-034B)
3
+ *
4
+ * Routes sync to comment-only mode for external items (preserves original format)
5
+ * and full sync mode for internal items (allows title/description updates).
6
+ *
7
+ * Architecture:
8
+ * - External US (origin=external): Comment-only sync (no title/description changes)
9
+ * - Internal US (origin=internal): Full sync (title, description, status, comments)
10
+ */
11
+ import { getOrigin } from '../types/living-docs-us-file.js';
12
+ import { GitHubClientV2 } from '../../plugins/specweave-github/lib/github-client-v2.js';
13
+ import { JiraClient } from '../integrations/jira/jira-client.js';
14
+ import { AdoClient } from '../integrations/ado/ado-client.js';
15
+ import { consoleLogger } from '../utils/logger.js';
16
+ export class FormatPreservationSyncService {
17
+ constructor(config = {}, options = {}) {
18
+ this.config = {
19
+ canUpdateExternalItems: config.canUpdateExternalItems ?? false,
20
+ canUpsertInternalItems: config.canUpsertInternalItems ?? false,
21
+ canUpdateStatus: config.canUpdateStatus ?? false
22
+ };
23
+ this.logger = options.logger ?? consoleLogger;
24
+ }
25
+ /**
26
+ * Sync User Story to external tool with origin-based routing
27
+ *
28
+ * - External US (origin=external) → Comment-only sync
29
+ * - Internal US (origin=internal) → Full sync
30
+ */
31
+ async syncUserStory(usFile, completionData, externalClient) {
32
+ const origin = getOrigin(usFile);
33
+ this.logger.log(`📊 Syncing ${usFile.id} (origin: ${origin})`);
34
+ if (origin === 'external') {
35
+ // External US: Comment-only sync (preserves format)
36
+ await this.syncExternalUS(usFile, completionData, externalClient);
37
+ }
38
+ else {
39
+ // Internal US: Full sync (allows updates)
40
+ await this.syncInternalUS(usFile, completionData, externalClient);
41
+ }
42
+ }
43
+ /**
44
+ * Sync External US (Comment-only mode)
45
+ *
46
+ * Preserves original title/description, only adds completion comments
47
+ */
48
+ async syncExternalUS(usFile, completionData, externalClient) {
49
+ this.logger.log(` 💬 External US: Comment-only sync (format preserved)`);
50
+ // Build completion comment
51
+ const comment = this.buildCompletionComment(completionData);
52
+ // Post comment to external tool
53
+ if (externalClient instanceof GitHubClientV2) {
54
+ const issueNumber = this.extractIssueNumber(usFile.external_id || '');
55
+ await externalClient.addComment(issueNumber, comment);
56
+ }
57
+ else if (externalClient instanceof JiraClient) {
58
+ const issueKey = usFile.external_id || '';
59
+ await externalClient.addComment(issueKey, comment);
60
+ }
61
+ else if (externalClient instanceof AdoClient) {
62
+ const workItemId = parseInt(usFile.external_id || '0', 10);
63
+ await externalClient.addComment(workItemId, comment);
64
+ }
65
+ // Conditional status update (only if config allows)
66
+ if (this.config.canUpdateStatus) {
67
+ this.logger.log(` ✅ Status update enabled`);
68
+ // TODO: Implement status update logic
69
+ }
70
+ else {
71
+ this.logger.log(` ⏭️ Status update skipped (canUpdateStatus=false)`);
72
+ }
73
+ }
74
+ /**
75
+ * Sync Internal US (Full sync mode)
76
+ *
77
+ * Allows updating title, description, status, and comments
78
+ */
79
+ async syncInternalUS(usFile, completionData, externalClient) {
80
+ this.logger.log(` 🔄 Internal US: Full sync (updates allowed)`);
81
+ // Full sync: Update title, description, comments, status
82
+ if (this.config.canUpdateExternalItems) {
83
+ this.logger.log(` ✅ External updates enabled`);
84
+ // Build completion comment
85
+ const comment = this.buildCompletionComment(completionData);
86
+ // Post comment
87
+ if (externalClient instanceof GitHubClientV2) {
88
+ const issueNumber = this.extractIssueNumber(usFile.external_id || '');
89
+ await externalClient.addComment(issueNumber, comment);
90
+ // Update title/description if needed
91
+ // TODO: Implement title/description update logic
92
+ }
93
+ else if (externalClient instanceof JiraClient) {
94
+ const issueKey = usFile.external_id || '';
95
+ await externalClient.addComment(issueKey, comment);
96
+ }
97
+ else if (externalClient instanceof AdoClient) {
98
+ const workItemId = parseInt(usFile.external_id || '0', 10);
99
+ await externalClient.addComment(workItemId, comment);
100
+ }
101
+ // Update status if allowed
102
+ if (this.config.canUpdateStatus) {
103
+ this.logger.log(` ✅ Status update enabled`);
104
+ // TODO: Implement status update logic
105
+ }
106
+ }
107
+ else {
108
+ this.logger.log(` ⏭️ External updates skipped (canUpdateExternalItems=false)`);
109
+ }
110
+ }
111
+ /**
112
+ * Build completion comment with task/AC progress
113
+ *
114
+ * Format:
115
+ * ## Progress Update
116
+ *
117
+ * ### Completed Tasks
118
+ * - ✅ [T-001] Task title
119
+ * - ✅ [T-002] Another task
120
+ *
121
+ * ### Acceptance Criteria
122
+ * - ✅ **AC-US1-01**: Criteria description
123
+ * - ✅ **AC-US1-02**: Another criteria
124
+ *
125
+ * **Progress**: 8/11 tasks completed (73%)
126
+ *
127
+ * [View Living Docs](url)
128
+ */
129
+ buildCompletionComment(data) {
130
+ const lines = [];
131
+ lines.push('## Progress Update');
132
+ lines.push('');
133
+ // Completed tasks
134
+ const completedTasks = data.tasks.filter(t => t.completed);
135
+ if (completedTasks.length > 0) {
136
+ lines.push('### Completed Tasks');
137
+ lines.push('');
138
+ for (const task of completedTasks) {
139
+ lines.push(`- ✅ [${task.taskId}] ${task.title}`);
140
+ }
141
+ lines.push('');
142
+ }
143
+ // Acceptance criteria
144
+ const satisfiedACs = data.acceptanceCriteria.filter(ac => ac.satisfied);
145
+ if (satisfiedACs.length > 0) {
146
+ lines.push('### Acceptance Criteria');
147
+ lines.push('');
148
+ for (const ac of satisfiedACs) {
149
+ lines.push(`- ✅ **${ac.acId}**: ${ac.description}`);
150
+ }
151
+ lines.push('');
152
+ }
153
+ // Progress summary
154
+ const totalTasks = data.tasks.length;
155
+ const completed = completedTasks.length;
156
+ lines.push(`**Progress**: ${completed}/${totalTasks} tasks completed (${data.progressPercentage}%)`);
157
+ lines.push('');
158
+ // Living docs link
159
+ if (data.livingDocsUrl) {
160
+ lines.push(`[View Living Docs](${data.livingDocsUrl})`);
161
+ }
162
+ return lines.join('\n');
163
+ }
164
+ /**
165
+ * Extract issue number from external_id
166
+ * Examples: "GH-#123" → 123, "#456" → 456
167
+ */
168
+ extractIssueNumber(externalId) {
169
+ const match = externalId.match(/#(\d+)/);
170
+ return match ? parseInt(match[1], 10) : 0;
171
+ }
172
+ }
173
+ //# sourceMappingURL=format-preservation-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-preservation-sync.js","sourceRoot":"","sources":["../../../src/sync/format-preservation-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Sync Module Exports
3
+ */
4
+ export { FormatPreservationSyncService } from './format-preservation-sync.js';
5
+ export { SyncCoordinator } from './sync-coordinator.js';
6
+ export type { SyncConfig, CompletionCommentData } from './format-preservation-sync.js';
7
+ export type { SyncCoordinatorOptions, SyncResult } from './sync-coordinator.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,YAAY,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACvF,YAAY,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sync Module Exports
3
+ */
4
+ export { FormatPreservationSyncService } from './format-preservation-sync.js';
5
+ export { SyncCoordinator } from './sync-coordinator.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/sync/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Sync Coordinator (T-034E)
3
+ *
4
+ * High-level coordinator that integrates FormatPreservationSyncService
5
+ * with living docs sync workflow. Called by post-task-completion hook.
6
+ */
7
+ import { Logger } from '../utils/logger.js';
8
+ export interface SyncCoordinatorOptions {
9
+ projectRoot: string;
10
+ incrementId: string;
11
+ logger?: Logger;
12
+ }
13
+ export interface SyncResult {
14
+ success: boolean;
15
+ userStoriesSynced: number;
16
+ syncMode: 'comment-only' | 'full-sync' | 'read-only';
17
+ errors: string[];
18
+ }
19
+ export declare class SyncCoordinator {
20
+ private projectRoot;
21
+ private incrementId;
22
+ private logger;
23
+ constructor(options: SyncCoordinatorOptions);
24
+ /**
25
+ * Sync increment completion to external tools using format preservation
26
+ */
27
+ syncIncrementCompletion(): Promise<SyncResult>;
28
+ /**
29
+ * Sync individual user story
30
+ */
31
+ private syncUserStory;
32
+ /**
33
+ * Load completion data for user story
34
+ */
35
+ private loadCompletionData;
36
+ /**
37
+ * Load user stories affected by this increment
38
+ */
39
+ private loadUserStoriesForIncrement;
40
+ /**
41
+ * Load config
42
+ */
43
+ private loadConfig;
44
+ /**
45
+ * Detect GitHub repository from config or git
46
+ */
47
+ private detectGitHubRepo;
48
+ }
49
+ //# sourceMappingURL=sync-coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-coordinator.d.ts","sourceRoot":"","sources":["../../../src/sync/sync-coordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,MAAM,EAAiB,MAAM,oBAAoB,CAAC;AAE3D,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,EAAE,sBAAsB;IAM3C;;OAEG;IACG,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC;IA4EpD;;OAEG;YACW,aAAa;IA8B3B;;OAEG;YACW,kBAAkB;IAmEhC;;OAEG;YACW,2BAA2B;IAqEzC;;OAEG;YACW,UAAU;IAWxB;;OAEG;YACW,gBAAgB;CAyB/B"}