@sudocode-ai/integration-openspec 0.1.14

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 (41) hide show
  1. package/dist/id-generator.d.ts +114 -0
  2. package/dist/id-generator.d.ts.map +1 -0
  3. package/dist/id-generator.js +165 -0
  4. package/dist/id-generator.js.map +1 -0
  5. package/dist/index.d.ts +29 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +692 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/parser/change-parser.d.ts +164 -0
  10. package/dist/parser/change-parser.d.ts.map +1 -0
  11. package/dist/parser/change-parser.js +339 -0
  12. package/dist/parser/change-parser.js.map +1 -0
  13. package/dist/parser/markdown-utils.d.ts +138 -0
  14. package/dist/parser/markdown-utils.d.ts.map +1 -0
  15. package/dist/parser/markdown-utils.js +283 -0
  16. package/dist/parser/markdown-utils.js.map +1 -0
  17. package/dist/parser/spec-parser.d.ts +116 -0
  18. package/dist/parser/spec-parser.d.ts.map +1 -0
  19. package/dist/parser/spec-parser.js +204 -0
  20. package/dist/parser/spec-parser.js.map +1 -0
  21. package/dist/parser/tasks-parser.d.ts +120 -0
  22. package/dist/parser/tasks-parser.d.ts.map +1 -0
  23. package/dist/parser/tasks-parser.js +176 -0
  24. package/dist/parser/tasks-parser.js.map +1 -0
  25. package/dist/watcher.d.ts +160 -0
  26. package/dist/watcher.d.ts.map +1 -0
  27. package/dist/watcher.js +614 -0
  28. package/dist/watcher.js.map +1 -0
  29. package/dist/writer/index.d.ts +9 -0
  30. package/dist/writer/index.d.ts.map +1 -0
  31. package/dist/writer/index.js +9 -0
  32. package/dist/writer/index.js.map +1 -0
  33. package/dist/writer/spec-writer.d.ts +24 -0
  34. package/dist/writer/spec-writer.d.ts.map +1 -0
  35. package/dist/writer/spec-writer.js +75 -0
  36. package/dist/writer/spec-writer.js.map +1 -0
  37. package/dist/writer/tasks-writer.d.ts +33 -0
  38. package/dist/writer/tasks-writer.d.ts.map +1 -0
  39. package/dist/writer/tasks-writer.js +144 -0
  40. package/dist/writer/tasks-writer.js.map +1 -0
  41. package/package.json +43 -0
@@ -0,0 +1,614 @@
1
+ /**
2
+ * File watcher for OpenSpec integration
3
+ *
4
+ * Watches the OpenSpec directory for changes to spec files and change directories.
5
+ * Detects which entities were created, updated, or deleted.
6
+ *
7
+ * Watch patterns:
8
+ * - specs/ directory (all .md files) - Spec file changes
9
+ * - changes/<name>/proposal.md - Change proposal updates
10
+ * - changes/<name>/tasks.md - Change task updates
11
+ * - changes/archive/<name>/ - Archived change detection
12
+ * - changes/<name>/specs/<cap>/ - Delta directory changes
13
+ */
14
+ import chokidar from "chokidar";
15
+ import * as path from "path";
16
+ import { createHash } from "crypto";
17
+ import { existsSync, readFileSync, readdirSync } from "fs";
18
+ import { parseSpecFile } from "./parser/spec-parser.js";
19
+ import { parseChangeDirectory, scanChangeDirectories, isChangeDirectory, } from "./parser/change-parser.js";
20
+ import { generateSpecId, generateChangeId, parseOpenSpecId, DEFAULT_SPEC_PREFIX, DEFAULT_CHANGE_PREFIX, } from "./id-generator.js";
21
+ /**
22
+ * OpenSpecWatcher monitors the OpenSpec directory for changes
23
+ *
24
+ * Uses content hashing to detect actual changes vs just file touches.
25
+ * This prevents false positives from atomic writes and other file operations.
26
+ */
27
+ export class OpenSpecWatcher {
28
+ watcher = null;
29
+ entityHashes = new Map();
30
+ callback = null;
31
+ isProcessing = false;
32
+ debounceTimer = null;
33
+ isRelevantFile = null;
34
+ // Track pending archive moves to detect status changes vs delete+create
35
+ pendingArchiveMoves = new Map();
36
+ ARCHIVE_MOVE_WINDOW_MS = 500; // Time window to detect archive moves
37
+ openspecPath;
38
+ specPrefix;
39
+ changePrefix;
40
+ trackArchived;
41
+ debounceMs;
42
+ constructor(options) {
43
+ this.openspecPath = options.openspecPath;
44
+ this.specPrefix = options.specPrefix || DEFAULT_SPEC_PREFIX;
45
+ this.changePrefix = options.changePrefix || DEFAULT_CHANGE_PREFIX;
46
+ this.trackArchived = options.trackArchived !== false;
47
+ this.debounceMs = options.debounceMs ?? 100;
48
+ }
49
+ /**
50
+ * Update the cached hash for a specific entity after we wrote to it.
51
+ * This prevents the watcher from detecting our own writes as changes.
52
+ */
53
+ updateEntityHash(entityId, hash) {
54
+ console.log(`[openspec-watcher] Updated hash for ${entityId} after outbound write`);
55
+ this.entityHashes.set(entityId, hash);
56
+ }
57
+ /**
58
+ * Remove an entity from the hash cache (after deletion)
59
+ */
60
+ removeEntityHash(entityId) {
61
+ console.log(`[openspec-watcher] Removed hash for ${entityId} after outbound delete`);
62
+ this.entityHashes.delete(entityId);
63
+ }
64
+ /**
65
+ * Start watching for changes
66
+ *
67
+ * @param callback - Function to call when changes are detected
68
+ */
69
+ start(callback) {
70
+ if (this.watcher) {
71
+ console.warn("[openspec-watcher] Already watching");
72
+ return;
73
+ }
74
+ this.callback = callback;
75
+ // Capture initial state
76
+ this.captureState();
77
+ // Watch paths - use directories for better compatibility with chokidar v4
78
+ const watchPaths = [];
79
+ // Watch specs directory
80
+ const specsDir = path.join(this.openspecPath, "specs");
81
+ if (existsSync(specsDir)) {
82
+ watchPaths.push(specsDir);
83
+ }
84
+ // Watch changes directory
85
+ const changesDir = path.join(this.openspecPath, "changes");
86
+ if (existsSync(changesDir)) {
87
+ watchPaths.push(changesDir);
88
+ }
89
+ if (watchPaths.length === 0) {
90
+ console.warn("[openspec-watcher] No paths to watch");
91
+ return;
92
+ }
93
+ console.log(`[openspec-watcher] Watching paths:`, watchPaths);
94
+ // Filter function to only process relevant files
95
+ const isRelevantFile = (filePath) => {
96
+ const ext = path.extname(filePath).toLowerCase();
97
+ // Only watch .md files
98
+ if (ext !== ".md") {
99
+ return false;
100
+ }
101
+ // Check if it's in specs/ directory
102
+ const relativePath = path.relative(this.openspecPath, filePath);
103
+ if (relativePath.startsWith("specs" + path.sep)) {
104
+ return true;
105
+ }
106
+ // Check if it's in changes/ directory
107
+ if (relativePath.startsWith("changes" + path.sep)) {
108
+ const fileName = path.basename(filePath);
109
+ // Watch proposal.md, tasks.md, design.md in change directories
110
+ if (["proposal.md", "tasks.md", "design.md"].includes(fileName)) {
111
+ return true;
112
+ }
113
+ // Watch spec.md files in changes/[name]/specs/[cap]/spec.md (proposed specs)
114
+ if (fileName === "spec.md" && relativePath.includes(path.sep + "specs" + path.sep)) {
115
+ return true;
116
+ }
117
+ }
118
+ return false;
119
+ };
120
+ this.watcher = chokidar.watch(watchPaths, {
121
+ persistent: true,
122
+ ignoreInitial: true,
123
+ awaitWriteFinish: {
124
+ stabilityThreshold: this.debounceMs,
125
+ pollInterval: 50,
126
+ },
127
+ });
128
+ // Store file filter for use in handlers
129
+ this.isRelevantFile = isRelevantFile;
130
+ this.watcher.on("ready", () => {
131
+ const watched = this.watcher?.getWatched() || {};
132
+ const dirs = Object.keys(watched);
133
+ console.log(`[openspec-watcher] Ready, watching ${dirs.length} directories in ${this.openspecPath}`);
134
+ });
135
+ this.watcher.on("change", (filePath) => this.handleFileChange(filePath));
136
+ this.watcher.on("add", (filePath) => this.handleFileChange(filePath));
137
+ this.watcher.on("unlink", (filePath) => this.handleFileDeleted(filePath));
138
+ // Watch for directory events to detect archive moves
139
+ this.watcher.on("addDir", (dirPath) => this.handleDirectoryAdded(dirPath));
140
+ this.watcher.on("unlinkDir", (dirPath) => this.handleDirectoryRemoved(dirPath));
141
+ this.watcher.on("error", (error) => {
142
+ console.error("[openspec-watcher] Error:", error);
143
+ });
144
+ console.log(`[openspec-watcher] Setting up watcher for ${this.openspecPath}...`);
145
+ }
146
+ /**
147
+ * Stop watching for changes
148
+ */
149
+ stop() {
150
+ if (this.debounceTimer) {
151
+ clearTimeout(this.debounceTimer);
152
+ this.debounceTimer = null;
153
+ }
154
+ if (this.watcher) {
155
+ this.watcher.close();
156
+ this.watcher = null;
157
+ this.callback = null;
158
+ console.log("[openspec-watcher] Stopped");
159
+ }
160
+ }
161
+ /**
162
+ * Check if watcher is active
163
+ */
164
+ isWatching() {
165
+ return this.watcher !== null;
166
+ }
167
+ /**
168
+ * Handle file change event
169
+ */
170
+ handleFileChange(filePath) {
171
+ // Filter out non-relevant files
172
+ if (this.isRelevantFile && !this.isRelevantFile(filePath)) {
173
+ return;
174
+ }
175
+ console.log(`[openspec-watcher] File changed: ${filePath}`);
176
+ this.scheduleProcessChanges();
177
+ }
178
+ /**
179
+ * Handle file deleted event
180
+ */
181
+ handleFileDeleted(filePath) {
182
+ // Filter out non-relevant files
183
+ if (this.isRelevantFile && !this.isRelevantFile(filePath)) {
184
+ return;
185
+ }
186
+ console.log(`[openspec-watcher] File deleted: ${filePath}`);
187
+ this.scheduleProcessChanges();
188
+ }
189
+ /**
190
+ * Handle directory added event
191
+ * Used to detect archive moves (change moved to archive/)
192
+ */
193
+ handleDirectoryAdded(dirPath) {
194
+ const relativePath = path.relative(this.openspecPath, dirPath);
195
+ // Check if this is a new directory in changes/archive/
196
+ if (relativePath.startsWith("changes" + path.sep + "archive" + path.sep) &&
197
+ isChangeDirectory(dirPath)) {
198
+ const changeName = this.extractChangeNameFromArchive(dirPath);
199
+ if (changeName) {
200
+ console.log(`[openspec-watcher] Archive directory added: ${dirPath} (change: ${changeName})`);
201
+ // Check if we have a pending removal for this change
202
+ const pendingKey = changeName;
203
+ const pending = this.pendingArchiveMoves.get(pendingKey);
204
+ const now = Date.now();
205
+ if (pending && now - pending.timestamp < this.ARCHIVE_MOVE_WINDOW_MS) {
206
+ // This is an archive move, not a delete+create
207
+ console.log(`[openspec-watcher] Detected archive move for change: ${changeName}`);
208
+ this.pendingArchiveMoves.delete(pendingKey);
209
+ }
210
+ this.scheduleProcessChanges();
211
+ }
212
+ }
213
+ }
214
+ /**
215
+ * Handle directory removed event
216
+ * Used to detect archive moves (change moved from changes/)
217
+ */
218
+ handleDirectoryRemoved(dirPath) {
219
+ const relativePath = path.relative(this.openspecPath, dirPath);
220
+ // Check if this is a removed directory in changes/ (not archive/)
221
+ if (relativePath.startsWith("changes" + path.sep) &&
222
+ !relativePath.includes(path.sep + "archive" + path.sep)) {
223
+ const changeName = path.basename(dirPath);
224
+ // Don't track removal of the archive directory itself
225
+ if (changeName === "archive") {
226
+ return;
227
+ }
228
+ console.log(`[openspec-watcher] Change directory removed: ${dirPath} (change: ${changeName})`);
229
+ // Track as potential archive move
230
+ this.pendingArchiveMoves.set(changeName, {
231
+ changeName,
232
+ timestamp: Date.now(),
233
+ });
234
+ // Clean up old pending moves
235
+ this.cleanupPendingArchiveMoves();
236
+ this.scheduleProcessChanges();
237
+ }
238
+ }
239
+ /**
240
+ * Extract change name from an archive directory path
241
+ * Archive pattern: changes/archive/YYYY-MM-DD-name/ or changes/archive/name/
242
+ */
243
+ extractChangeNameFromArchive(dirPath) {
244
+ const dirName = path.basename(dirPath);
245
+ // Match YYYY-MM-DD-name pattern
246
+ const dateMatch = dirName.match(/^\d{4}-\d{2}-\d{2}-(.+)$/);
247
+ if (dateMatch) {
248
+ return dateMatch[1];
249
+ }
250
+ // Otherwise, the directory name is the change name
251
+ return dirName;
252
+ }
253
+ /**
254
+ * Clean up old pending archive move entries
255
+ */
256
+ cleanupPendingArchiveMoves() {
257
+ const now = Date.now();
258
+ for (const [key, value] of this.pendingArchiveMoves) {
259
+ if (now - value.timestamp > this.ARCHIVE_MOVE_WINDOW_MS * 2) {
260
+ this.pendingArchiveMoves.delete(key);
261
+ }
262
+ }
263
+ }
264
+ /**
265
+ * Schedule change processing with debouncing
266
+ */
267
+ scheduleProcessChanges() {
268
+ if (this.debounceTimer) {
269
+ clearTimeout(this.debounceTimer);
270
+ }
271
+ this.debounceTimer = setTimeout(() => {
272
+ this.debounceTimer = null;
273
+ this.processChanges();
274
+ }, this.debounceMs);
275
+ }
276
+ /**
277
+ * Process changes by comparing current state to cached hashes
278
+ */
279
+ processChanges() {
280
+ // Prevent concurrent processing
281
+ if (this.isProcessing) {
282
+ console.log("[openspec-watcher] Already processing, scheduling retry");
283
+ this.scheduleProcessChanges();
284
+ return;
285
+ }
286
+ this.isProcessing = true;
287
+ try {
288
+ const changes = this.detectChanges();
289
+ if (changes.length > 0) {
290
+ console.log(`[openspec-watcher] Detected ${changes.length} entity change(s):`, changes.map((c) => `${c.change_type}:${c.entity_id}`).join(", "));
291
+ if (this.callback) {
292
+ this.callback(changes);
293
+ }
294
+ }
295
+ else {
296
+ console.log("[openspec-watcher] No actual content changes (hashes match)");
297
+ }
298
+ }
299
+ catch (error) {
300
+ console.error("[openspec-watcher] Error processing changes:", error);
301
+ }
302
+ finally {
303
+ this.isProcessing = false;
304
+ }
305
+ }
306
+ /**
307
+ * Capture current state (entity hashes) for comparison
308
+ */
309
+ captureState() {
310
+ console.log("[openspec-watcher] Capturing initial state...");
311
+ const entities = this.scanAllEntities();
312
+ this.entityHashes.clear();
313
+ for (const entity of entities) {
314
+ const hash = this.computeEntityHash(entity);
315
+ this.entityHashes.set(entity.id, hash);
316
+ }
317
+ console.log(`[openspec-watcher] Captured state with ${this.entityHashes.size} entities`);
318
+ }
319
+ /**
320
+ * Detect changes by comparing current state to cached state
321
+ */
322
+ detectChanges() {
323
+ const currentEntities = this.scanAllEntities();
324
+ const changes = [];
325
+ const now = new Date().toISOString();
326
+ const currentIds = new Set();
327
+ // Check for created and updated entities
328
+ for (const entity of currentEntities) {
329
+ currentIds.add(entity.id);
330
+ const newHash = this.computeEntityHash(entity);
331
+ const cachedHash = this.entityHashes.get(entity.id);
332
+ if (!cachedHash) {
333
+ // New entity
334
+ changes.push({
335
+ entity_id: entity.id,
336
+ entity_type: entity.type,
337
+ change_type: "created",
338
+ timestamp: entity.created_at || now,
339
+ data: entity,
340
+ });
341
+ this.entityHashes.set(entity.id, newHash);
342
+ }
343
+ else if (newHash !== cachedHash) {
344
+ // Updated entity
345
+ changes.push({
346
+ entity_id: entity.id,
347
+ entity_type: entity.type,
348
+ change_type: "updated",
349
+ timestamp: entity.updated_at || now,
350
+ data: entity,
351
+ });
352
+ this.entityHashes.set(entity.id, newHash);
353
+ }
354
+ }
355
+ // Check for deleted entities
356
+ for (const [id] of this.entityHashes) {
357
+ if (!currentIds.has(id)) {
358
+ // Determine entity type from ID
359
+ const parsed = parseOpenSpecId(id);
360
+ const entityType = parsed?.type === "change" ? "issue" : "spec";
361
+ changes.push({
362
+ entity_id: id,
363
+ entity_type: entityType,
364
+ change_type: "deleted",
365
+ timestamp: now,
366
+ });
367
+ this.entityHashes.delete(id);
368
+ }
369
+ }
370
+ return changes;
371
+ }
372
+ /**
373
+ * Scan all entities in the OpenSpec directory
374
+ * IMPORTANT: Returns specs FIRST, then issues to ensure proper relationship resolution
375
+ */
376
+ scanAllEntities() {
377
+ // IMPORTANT: We collect specs FIRST, then issues
378
+ // This ensures specs exist before issues that reference them are synced
379
+ const specEntities = [];
380
+ const issueEntities = [];
381
+ // Track which specs exist in openspec/specs/ (approved specs)
382
+ const approvedSpecs = new Set();
383
+ // Scan specs directory
384
+ const specsDir = path.join(this.openspecPath, "specs");
385
+ if (existsSync(specsDir)) {
386
+ try {
387
+ const entries = readdirSync(specsDir, { withFileTypes: true });
388
+ for (const entry of entries) {
389
+ if (!entry.isDirectory())
390
+ continue;
391
+ const specPath = path.join(specsDir, entry.name, "spec.md");
392
+ if (!existsSync(specPath))
393
+ continue;
394
+ approvedSpecs.add(entry.name);
395
+ try {
396
+ const spec = parseSpecFile(specPath);
397
+ const specId = generateSpecId(entry.name, this.specPrefix);
398
+ specEntities.push(this.specToExternalEntity(spec, specId));
399
+ }
400
+ catch (error) {
401
+ console.error(`[openspec-watcher] Error parsing spec at ${specPath}:`, error);
402
+ }
403
+ }
404
+ }
405
+ catch (error) {
406
+ console.error("[openspec-watcher] Error scanning specs directory:", error);
407
+ }
408
+ }
409
+ // Scan changes directory
410
+ const changesDir = path.join(this.openspecPath, "changes");
411
+ if (existsSync(changesDir)) {
412
+ try {
413
+ const changePaths = scanChangeDirectories(changesDir, this.trackArchived);
414
+ for (const changePath of changePaths) {
415
+ try {
416
+ const change = parseChangeDirectory(changePath);
417
+ const changeId = generateChangeId(change.name, this.changePrefix);
418
+ issueEntities.push(this.changeToExternalEntity(change, changeId));
419
+ // Scan for proposed specs inside this change
420
+ // These are NEW specs in changes/[name]/specs/[cap]/spec.md
421
+ const changeSpecsDir = path.join(changePath, "specs");
422
+ if (existsSync(changeSpecsDir)) {
423
+ const specDirEntries = readdirSync(changeSpecsDir, { withFileTypes: true });
424
+ for (const specEntry of specDirEntries) {
425
+ if (!specEntry.isDirectory())
426
+ continue;
427
+ const proposedSpecPath = path.join(changeSpecsDir, specEntry.name, "spec.md");
428
+ if (!existsSync(proposedSpecPath))
429
+ continue;
430
+ // Only create a separate spec entity for NEW specs
431
+ // (those not in openspec/specs/)
432
+ const isNewSpec = !approvedSpecs.has(specEntry.name);
433
+ if (isNewSpec) {
434
+ try {
435
+ const proposedSpec = parseSpecFile(proposedSpecPath);
436
+ const proposedSpecId = generateSpecId(specEntry.name, this.specPrefix);
437
+ // Add proposed specs to specEntities so they're synced before issues
438
+ specEntities.push(this.proposedSpecToExternalEntity(proposedSpec, proposedSpecId, change.name));
439
+ }
440
+ catch (error) {
441
+ console.error(`[openspec-watcher] Error parsing proposed spec at ${proposedSpecPath}:`, error);
442
+ }
443
+ }
444
+ }
445
+ }
446
+ }
447
+ catch (error) {
448
+ console.error(`[openspec-watcher] Error parsing change at ${changePath}:`, error);
449
+ }
450
+ }
451
+ }
452
+ catch (error) {
453
+ console.error("[openspec-watcher] Error scanning changes directory:", error);
454
+ }
455
+ }
456
+ // Return specs FIRST, then issues
457
+ // This ensures specs are created before issues that implement them
458
+ return [...specEntities, ...issueEntities];
459
+ }
460
+ /**
461
+ * Compute a hash for an entity to detect changes
462
+ */
463
+ computeEntityHash(entity) {
464
+ const canonical = JSON.stringify({
465
+ id: entity.id,
466
+ type: entity.type,
467
+ title: entity.title,
468
+ description: entity.description,
469
+ status: entity.status,
470
+ priority: entity.priority,
471
+ });
472
+ return createHash("sha256").update(canonical).digest("hex");
473
+ }
474
+ /**
475
+ * Convert a parsed OpenSpec spec to ExternalEntity
476
+ */
477
+ specToExternalEntity(spec, id) {
478
+ // Read raw file content for description
479
+ let rawContent = spec.rawContent;
480
+ try {
481
+ rawContent = readFileSync(spec.filePath, "utf-8");
482
+ }
483
+ catch {
484
+ // Fall back to parsed content
485
+ }
486
+ return {
487
+ id,
488
+ type: "spec",
489
+ title: spec.title,
490
+ description: rawContent,
491
+ priority: 2, // Default priority
492
+ raw: {
493
+ capability: spec.capability,
494
+ purpose: spec.purpose,
495
+ requirements: spec.requirements,
496
+ filePath: spec.filePath,
497
+ },
498
+ };
499
+ }
500
+ /**
501
+ * Convert a proposed spec (from changes/[name]/specs/) to ExternalEntity
502
+ *
503
+ * Proposed specs are NEW specs that don't exist in openspec/specs/ yet.
504
+ * They are marked with isProposed: true in the raw data.
505
+ */
506
+ proposedSpecToExternalEntity(spec, id, changeName) {
507
+ // Read raw file content for description
508
+ let rawContent = spec.rawContent;
509
+ try {
510
+ rawContent = readFileSync(spec.filePath, "utf-8");
511
+ }
512
+ catch {
513
+ // Fall back to parsed content
514
+ }
515
+ return {
516
+ id,
517
+ type: "spec",
518
+ title: spec.title,
519
+ description: rawContent,
520
+ priority: 2,
521
+ raw: {
522
+ capability: spec.capability,
523
+ purpose: spec.purpose,
524
+ requirements: spec.requirements,
525
+ filePath: spec.filePath,
526
+ isProposed: true,
527
+ proposedByChange: changeName,
528
+ },
529
+ };
530
+ }
531
+ /**
532
+ * Convert a parsed OpenSpec change to ExternalEntity (as issue)
533
+ *
534
+ * Changes map to sudocode Issues:
535
+ * - Archived changes → status: "closed"
536
+ * - Active changes with 100% task completion → status: "needs_review"
537
+ * - Active changes with progress → status: "in_progress"
538
+ * - Active changes with no progress → status: "open"
539
+ */
540
+ changeToExternalEntity(change, id) {
541
+ // Determine status based on archive and task completion
542
+ let status;
543
+ if (change.isArchived) {
544
+ status = "closed";
545
+ }
546
+ else if (change.taskCompletion === 100) {
547
+ status = "needs_review";
548
+ }
549
+ else if (change.taskCompletion > 0) {
550
+ status = "in_progress";
551
+ }
552
+ else {
553
+ status = "open";
554
+ }
555
+ // Build description from proposal content
556
+ const descriptionParts = [];
557
+ if (change.why) {
558
+ descriptionParts.push(`## Why\n${change.why}`);
559
+ }
560
+ if (change.whatChanges) {
561
+ descriptionParts.push(`## What Changes\n${change.whatChanges}`);
562
+ }
563
+ if (change.impact) {
564
+ descriptionParts.push(`## Impact\n${change.impact}`);
565
+ }
566
+ // Add task summary
567
+ if (change.tasks.length > 0) {
568
+ const taskSummary = `## Tasks\n- ${change.tasks.length} total tasks\n- ${change.taskCompletion}% complete`;
569
+ descriptionParts.push(taskSummary);
570
+ }
571
+ const description = descriptionParts.join("\n\n");
572
+ // Build relationships from affected specs
573
+ const relationships = change.affectedSpecs.map((specCapability) => ({
574
+ targetId: generateSpecId(specCapability, this.specPrefix),
575
+ targetType: "spec",
576
+ relationshipType: "implements",
577
+ }));
578
+ return {
579
+ id,
580
+ type: "issue",
581
+ title: change.title,
582
+ description,
583
+ status,
584
+ priority: change.isArchived ? 4 : 2, // Lower priority for archived
585
+ created_at: change.archivedAt?.toISOString(),
586
+ relationships: relationships.length > 0 ? relationships : undefined,
587
+ raw: {
588
+ name: change.name,
589
+ why: change.why,
590
+ whatChanges: change.whatChanges,
591
+ impact: change.impact,
592
+ tasks: change.tasks,
593
+ taskCompletion: change.taskCompletion,
594
+ affectedSpecs: change.affectedSpecs,
595
+ isArchived: change.isArchived,
596
+ archivedAt: change.archivedAt,
597
+ filePath: change.filePath,
598
+ },
599
+ };
600
+ }
601
+ /**
602
+ * Get current cached hashes (for testing/debugging)
603
+ */
604
+ getEntityHashes() {
605
+ return new Map(this.entityHashes);
606
+ }
607
+ /**
608
+ * Force refresh of cached state (useful after external sync)
609
+ */
610
+ refreshState() {
611
+ this.captureState();
612
+ }
613
+ }
614
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Writer module for OpenSpec Integration
3
+ *
4
+ * Provides utilities for writing updates back to OpenSpec files
5
+ * during bidirectional synchronization.
6
+ */
7
+ export { updateAllTasksCompletion, updateTaskByLine, updateTaskByDescription, } from "./tasks-writer.js";
8
+ export { updateSpecContent, updateSpecTitle } from "./spec-writer.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/writer/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Writer module for OpenSpec Integration
3
+ *
4
+ * Provides utilities for writing updates back to OpenSpec files
5
+ * during bidirectional synchronization.
6
+ */
7
+ export { updateAllTasksCompletion, updateTaskByLine, updateTaskByDescription, } from "./tasks-writer.js";
8
+ export { updateSpecContent, updateSpecTitle } from "./spec-writer.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/writer/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC"}