@wrongstack/sdd 0.284.1 → 0.286.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 (55) hide show
  1. package/dist/auto-executor.d.ts +89 -0
  2. package/dist/auto-executor.d.ts.map +1 -0
  3. package/dist/board-types.d.ts +144 -0
  4. package/dist/board-types.d.ts.map +1 -0
  5. package/dist/conflict-resolver.d.ts +45 -0
  6. package/dist/conflict-resolver.d.ts.map +1 -0
  7. package/dist/critical-path.d.ts +36 -0
  8. package/dist/critical-path.d.ts.map +1 -0
  9. package/dist/decompose-task.d.ts +20 -0
  10. package/dist/decompose-task.d.ts.map +1 -0
  11. package/dist/index.d.ts +26 -1864
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +192 -76
  14. package/dist/index.js.map +7 -1
  15. package/dist/sdd-board-projector.d.ts +83 -0
  16. package/dist/sdd-board-projector.d.ts.map +1 -0
  17. package/dist/sdd-board-store.d.ts +59 -0
  18. package/dist/sdd-board-store.d.ts.map +1 -0
  19. package/dist/sdd-interview-driver.d.ts +131 -0
  20. package/dist/sdd-interview-driver.d.ts.map +1 -0
  21. package/dist/sdd-lifecycle.d.ts +146 -0
  22. package/dist/sdd-lifecycle.d.ts.map +1 -0
  23. package/dist/sdd-parallel-run.d.ts +427 -0
  24. package/dist/sdd-parallel-run.d.ts.map +1 -0
  25. package/dist/sdd-run-registry.d.ts +68 -0
  26. package/dist/sdd-run-registry.d.ts.map +1 -0
  27. package/dist/sdd-supervisor.d.ts +52 -0
  28. package/dist/sdd-supervisor.d.ts.map +1 -0
  29. package/dist/sdd-task-decomposer.d.ts +89 -0
  30. package/dist/sdd-task-decomposer.d.ts.map +1 -0
  31. package/dist/spec-builder.d.ts +139 -0
  32. package/dist/spec-builder.d.ts.map +1 -0
  33. package/dist/spec-parser.d.ts +14 -0
  34. package/dist/spec-parser.d.ts.map +1 -0
  35. package/dist/spec-store.d.ts +36 -0
  36. package/dist/spec-store.d.ts.map +1 -0
  37. package/dist/spec-templates.d.ts +22 -0
  38. package/dist/spec-templates.d.ts.map +1 -0
  39. package/dist/spec-versioning.d.ts +49 -0
  40. package/dist/spec-versioning.d.ts.map +1 -0
  41. package/dist/start-sdd-run.d.ts +67 -0
  42. package/dist/start-sdd-run.d.ts.map +1 -0
  43. package/dist/task-flow.d.ts +99 -0
  44. package/dist/task-flow.d.ts.map +1 -0
  45. package/dist/task-generator.d.ts +39 -0
  46. package/dist/task-generator.d.ts.map +1 -0
  47. package/dist/task-graph-store.d.ts +33 -0
  48. package/dist/task-graph-store.d.ts.map +1 -0
  49. package/dist/task-tracker.d.ts +2 -0
  50. package/dist/task-tracker.d.ts.map +1 -0
  51. package/dist/task-visualizer.d.ts +26 -0
  52. package/dist/task-visualizer.d.ts.map +1 -0
  53. package/dist/verify-task.d.ts +23 -0
  54. package/dist/verify-task.d.ts.map +1 -0
  55. package/package.json +4 -5
package/dist/index.js CHANGED
@@ -1,15 +1,3 @@
1
- import { SddError, ERROR_CODES, ensureDir, atomicWrite, toErrorMessage, assignNickname, expectDefined, WorktreeManager, truncate, assertNever, parseModelRef, renderInstructionTemplate, readBundledInstructionText } from '@wrongstack/core';
2
- import { DefaultTaskStore, TaskTracker } from '@wrongstack/core/tasking';
3
- export { DefaultTaskStore, TaskTracker } from '@wrongstack/core/tasking';
4
- import * as fsp3 from 'fs/promises';
5
- import { readFile, writeFile } from 'fs/promises';
6
- import * as path3 from 'path';
7
- import { isAbsolute, join } from 'path';
8
- import { randomUUID } from 'crypto';
9
- import { computeTaskProgress, topologicalSort } from '@wrongstack/core/types';
10
- import { DefaultMultiAgentCoordinator, withDisabledToolFiltering, makeAgentSubagentRunner } from '@wrongstack/core/coordination';
11
- import { spawn } from 'child_process';
12
-
13
1
  // src/spec-parser.ts
14
2
  var SpecParser = class {
15
3
  parse(content) {
@@ -237,6 +225,8 @@ var SpecParser = class {
237
225
  };
238
226
  }
239
227
  };
228
+
229
+ // src/task-generator.ts
240
230
  function extractVerificationCommand(criteria) {
241
231
  const marker = /^\s*(?:\$\s+|(?:run|verify|cmd)\s*:\s*)(.+\S)\s*$/i;
242
232
  for (const c of criteria) {
@@ -273,6 +263,16 @@ var TaskGenerator = class {
273
263
  }
274
264
  }
275
265
  };
266
+
267
+ // src/index.ts
268
+ import {
269
+ TaskTracker as TaskTracker3,
270
+ DefaultTaskStore as DefaultTaskStore3
271
+ } from "@wrongstack/core/tasking";
272
+
273
+ // src/task-flow.ts
274
+ import { SddError, ERROR_CODES } from "@wrongstack/core";
275
+ import { DefaultTaskStore, TaskTracker } from "@wrongstack/core/tasking";
276
276
  var TaskFlow = class {
277
277
  constructor(opts) {
278
278
  this.opts = opts;
@@ -459,12 +459,18 @@ var SpecDrivenDev = class {
459
459
  }));
460
460
  }
461
461
  };
462
+
463
+ // src/spec-store.ts
464
+ import * as fsp from "node:fs/promises";
465
+ import * as path from "node:path";
466
+ import { randomUUID } from "node:crypto";
467
+ import { atomicWrite, ensureDir } from "@wrongstack/core";
462
468
  var SpecStore = class {
463
469
  baseDir;
464
470
  indexPath;
465
471
  constructor(opts) {
466
472
  this.baseDir = opts.baseDir;
467
- this.indexPath = path3.join(this.baseDir, "_index.json");
473
+ this.indexPath = path.join(this.baseDir, "_index.json");
468
474
  }
469
475
  async save(spec) {
470
476
  await ensureDir(this.baseDir);
@@ -474,7 +480,7 @@ var SpecStore = class {
474
480
  }
475
481
  async load(id) {
476
482
  try {
477
- const raw = await fsp3.readFile(this.filePath(id), "utf8");
483
+ const raw = await fsp.readFile(this.filePath(id), "utf8");
478
484
  return JSON.parse(raw);
479
485
  } catch {
480
486
  return null;
@@ -486,7 +492,7 @@ var SpecStore = class {
486
492
  }
487
493
  async delete(id) {
488
494
  try {
489
- await fsp3.unlink(this.filePath(id));
495
+ await fsp.unlink(this.filePath(id));
490
496
  await this.removeFromIndex(id);
491
497
  return true;
492
498
  } catch {
@@ -495,7 +501,7 @@ var SpecStore = class {
495
501
  }
496
502
  async exists(id) {
497
503
  try {
498
- await fsp3.access(this.filePath(id));
504
+ await fsp.access(this.filePath(id));
499
505
  return true;
500
506
  } catch {
501
507
  return false;
@@ -533,11 +539,11 @@ var SpecStore = class {
533
539
  return updated;
534
540
  }
535
541
  filePath(id) {
536
- return path3.join(this.baseDir, `${id}.json`);
542
+ return path.join(this.baseDir, `${id}.json`);
537
543
  }
538
544
  async readIndex() {
539
545
  try {
540
- const raw = await fsp3.readFile(this.indexPath, "utf8");
546
+ const raw = await fsp.readFile(this.indexPath, "utf8");
541
547
  const parsed = JSON.parse(raw);
542
548
  if (parsed?.version === 1) return parsed;
543
549
  } catch {
@@ -568,6 +574,11 @@ var SpecStore = class {
568
574
  await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
569
575
  }
570
576
  };
577
+
578
+ // src/task-graph-store.ts
579
+ import * as fsp2 from "node:fs/promises";
580
+ import * as path2 from "node:path";
581
+ import { atomicWrite as atomicWrite2, ensureDir as ensureDir2 } from "@wrongstack/core";
571
582
  function graphToJSON(graph) {
572
583
  const serialisable = {
573
584
  ...graph,
@@ -587,17 +598,17 @@ var TaskGraphStore = class {
587
598
  indexPath;
588
599
  constructor(opts) {
589
600
  this.baseDir = opts.baseDir;
590
- this.indexPath = path3.join(this.baseDir, "_index.json");
601
+ this.indexPath = path2.join(this.baseDir, "_index.json");
591
602
  }
592
603
  async save(graph) {
593
- await ensureDir(this.baseDir);
604
+ await ensureDir2(this.baseDir);
594
605
  const filePath = this.filePath(graph.id);
595
- await atomicWrite(filePath, graphToJSON(graph), { mode: 384 });
606
+ await atomicWrite2(filePath, graphToJSON(graph), { mode: 384 });
596
607
  await this.updateIndex(graph);
597
608
  }
598
609
  async load(id) {
599
610
  try {
600
- const raw = await fsp3.readFile(this.filePath(id), "utf8");
611
+ const raw = await fsp2.readFile(this.filePath(id), "utf8");
601
612
  return graphFromJSON(raw);
602
613
  } catch {
603
614
  return null;
@@ -609,7 +620,7 @@ var TaskGraphStore = class {
609
620
  }
610
621
  async delete(id) {
611
622
  try {
612
- await fsp3.unlink(this.filePath(id));
623
+ await fsp2.unlink(this.filePath(id));
613
624
  await this.removeFromIndex(id);
614
625
  return true;
615
626
  } catch {
@@ -618,18 +629,18 @@ var TaskGraphStore = class {
618
629
  }
619
630
  async exists(id) {
620
631
  try {
621
- await fsp3.access(this.filePath(id));
632
+ await fsp2.access(this.filePath(id));
622
633
  return true;
623
634
  } catch {
624
635
  return false;
625
636
  }
626
637
  }
627
638
  filePath(id) {
628
- return path3.join(this.baseDir, `${id}.json`);
639
+ return path2.join(this.baseDir, `${id}.json`);
629
640
  }
630
641
  async readIndex() {
631
642
  try {
632
- const raw = await fsp3.readFile(this.indexPath, "utf8");
643
+ const raw = await fsp2.readFile(this.indexPath, "utf8");
633
644
  const parsed = JSON.parse(raw);
634
645
  if (parsed?.version === 1) return parsed;
635
646
  } catch {
@@ -656,14 +667,17 @@ var TaskGraphStore = class {
656
667
  } else {
657
668
  index.entries.push(entry);
658
669
  }
659
- await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
670
+ await atomicWrite2(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
660
671
  }
661
672
  async removeFromIndex(id) {
662
673
  const index = await this.readIndex();
663
674
  index.entries = index.entries.filter((e) => e.id !== id);
664
- await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
675
+ await atomicWrite2(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
665
676
  }
666
677
  };
678
+
679
+ // src/board-types.ts
680
+ import { computeTaskProgress } from "@wrongstack/core/types";
667
681
  function shortIdMap(graph) {
668
682
  const nodes = Array.from(graph.nodes.values()).sort((a, b) => a.createdAt - b.createdAt);
669
683
  const m = /* @__PURE__ */ new Map();
@@ -751,6 +765,11 @@ function buildBoardSnapshot(graph, run, now) {
751
765
  mergedCommits: run.mergedCommits?.length ? run.mergedCommits : void 0
752
766
  };
753
767
  }
768
+
769
+ // src/sdd-board-store.ts
770
+ import * as fsp3 from "node:fs/promises";
771
+ import * as path3 from "node:path";
772
+ import { atomicWrite as atomicWrite3, ensureDir as ensureDir3 } from "@wrongstack/core";
754
773
  var SddBoardStore = class {
755
774
  baseDir;
756
775
  indexPath;
@@ -768,8 +787,8 @@ var SddBoardStore = class {
768
787
  return path3.join(this.baseDir, `${this.safe(runId)}.control.jsonl`);
769
788
  }
770
789
  async saveSnapshot(snapshot) {
771
- await ensureDir(this.baseDir);
772
- await atomicWrite(this.snapshotPath(snapshot.runId), JSON.stringify(snapshot, null, 2), {
790
+ await ensureDir3(this.baseDir);
791
+ await atomicWrite3(this.snapshotPath(snapshot.runId), JSON.stringify(snapshot, null, 2), {
773
792
  mode: 384
774
793
  });
775
794
  await this.updateIndex(snapshot);
@@ -793,7 +812,7 @@ var SddBoardStore = class {
793
812
  /** Append one line to the board's JSONL event log (best-effort, never throws). */
794
813
  async appendEvent(runId, event) {
795
814
  try {
796
- await ensureDir(this.baseDir);
815
+ await ensureDir3(this.baseDir);
797
816
  await fsp3.appendFile(this.eventsPath(runId), `${JSON.stringify(event)}
798
817
  `, { mode: 384 });
799
818
  } catch {
@@ -801,7 +820,7 @@ var SddBoardStore = class {
801
820
  }
802
821
  /** Append a control command (used by readers to steer a CLI-owned run). */
803
822
  async appendControl(runId, command) {
804
- await ensureDir(this.baseDir);
823
+ await ensureDir3(this.baseDir);
805
824
  await fsp3.appendFile(this.controlPath(runId), `${JSON.stringify(command)}
806
825
  `, { mode: 384 });
807
826
  }
@@ -861,12 +880,12 @@ var SddBoardStore = class {
861
880
  const idx = index.entries.findIndex((e) => e.runId === snapshot.runId);
862
881
  if (idx >= 0) index.entries[idx] = entry;
863
882
  else index.entries.push(entry);
864
- await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
883
+ await atomicWrite3(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
865
884
  }
866
885
  async removeFromIndex(runId) {
867
886
  const index = await this.readIndex();
868
887
  index.entries = index.entries.filter((e) => e.runId !== runId);
869
- await atomicWrite(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
888
+ await atomicWrite3(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
870
889
  }
871
890
  };
872
891
 
@@ -1143,6 +1162,11 @@ var SddRunRegistry = class {
1143
1162
  return this.current;
1144
1163
  }
1145
1164
  };
1165
+
1166
+ // src/spec-builder.ts
1167
+ import { expectDefined } from "@wrongstack/core";
1168
+ import { toErrorMessage } from "@wrongstack/core";
1169
+ import { SddError as SddError2, ERROR_CODES as ERROR_CODES2 } from "@wrongstack/core";
1146
1170
  function buildQuestioningPrompt(session, min, max) {
1147
1171
  const answered = session.answers.length;
1148
1172
  const remaining = Math.max(0, min - answered);
@@ -1362,9 +1386,9 @@ var AISpecBuilder = class {
1362
1386
  async saveSession() {
1363
1387
  if (!this.sessionPath) return;
1364
1388
  try {
1365
- const fsp5 = await import('fs/promises');
1366
- const path4 = await import('path');
1367
- const { atomicWrite: atomicWrite4 } = await import('@wrongstack/core');
1389
+ const fsp5 = await import("node:fs/promises");
1390
+ const path4 = await import("node:path");
1391
+ const { atomicWrite: atomicWrite4 } = await import("@wrongstack/core");
1368
1392
  await fsp5.mkdir(path4.dirname(this.sessionPath), { recursive: true });
1369
1393
  await atomicWrite4(this.sessionPath, JSON.stringify(this.session, null, 2));
1370
1394
  } catch {
@@ -1374,7 +1398,7 @@ var AISpecBuilder = class {
1374
1398
  async loadSession() {
1375
1399
  if (!this.sessionPath) return false;
1376
1400
  try {
1377
- const fsp5 = await import('fs/promises');
1401
+ const fsp5 = await import("node:fs/promises");
1378
1402
  const raw = await fsp5.readFile(this.sessionPath, "utf8");
1379
1403
  const loaded = JSON.parse(raw);
1380
1404
  if (loaded?.id && loaded?.phase && loaded?.title) {
@@ -1389,7 +1413,7 @@ var AISpecBuilder = class {
1389
1413
  async deleteSession() {
1390
1414
  if (!this.sessionPath) return;
1391
1415
  try {
1392
- const fsp5 = await import('fs/promises');
1416
+ const fsp5 = await import("node:fs/promises");
1393
1417
  await fsp5.unlink(this.sessionPath);
1394
1418
  } catch {
1395
1419
  }
@@ -1491,9 +1515,9 @@ var AISpecBuilder = class {
1491
1515
  switch (this.session.phase) {
1492
1516
  case "questioning":
1493
1517
  if (!this.session.spec) {
1494
- throw new SddError({
1518
+ throw new SddError2({
1495
1519
  message: "Cannot approve: no spec generated yet.",
1496
- code: ERROR_CODES.SDD_INVALID_STATE,
1520
+ code: ERROR_CODES2.SDD_INVALID_STATE,
1497
1521
  context: { phase: "questioning", sessionId: this.session.id }
1498
1522
  });
1499
1523
  }
@@ -1511,6 +1535,8 @@ var AISpecBuilder = class {
1511
1535
  case "executing":
1512
1536
  this.session.phase = "done";
1513
1537
  break;
1538
+ case "done":
1539
+ break;
1514
1540
  }
1515
1541
  this.session.approved = true;
1516
1542
  this.session.updatedAt = Date.now();
@@ -1553,9 +1579,9 @@ var AISpecBuilder = class {
1553
1579
  */
1554
1580
  async saveSpec() {
1555
1581
  if (!this.session.spec) {
1556
- throw new SddError({
1582
+ throw new SddError2({
1557
1583
  message: "No spec to save.",
1558
- code: ERROR_CODES.SDD_NOT_READY,
1584
+ code: ERROR_CODES2.SDD_NOT_READY,
1559
1585
  context: { sessionId: this.session.id }
1560
1586
  });
1561
1587
  }
@@ -1572,17 +1598,17 @@ var AISpecBuilder = class {
1572
1598
  try {
1573
1599
  parsed = JSON.parse(jsonStr);
1574
1600
  } catch (e) {
1575
- throw new SddError({
1601
+ throw new SddError2({
1576
1602
  message: "Invalid JSON for spec",
1577
- code: ERROR_CODES.SDD_PARSE_FAILED,
1603
+ code: ERROR_CODES2.SDD_PARSE_FAILED,
1578
1604
  cause: e,
1579
1605
  context: { detail: e instanceof Error ? e.message : "parse error" }
1580
1606
  });
1581
1607
  }
1582
1608
  if (!parsed || typeof parsed !== "object") {
1583
- throw new SddError({
1609
+ throw new SddError2({
1584
1610
  message: "Spec JSON must be an object",
1585
- code: ERROR_CODES.SDD_VALIDATION_FAILED,
1611
+ code: ERROR_CODES2.SDD_VALIDATION_FAILED,
1586
1612
  context: { actualType: typeof parsed }
1587
1613
  });
1588
1614
  }
@@ -1591,9 +1617,9 @@ var AISpecBuilder = class {
1591
1617
  const title = String(raw.title ?? this.session.title ?? "Untitled");
1592
1618
  const overview = String(raw.overview ?? "");
1593
1619
  if (!overview || overview === "undefined") {
1594
- throw new SddError({
1620
+ throw new SddError2({
1595
1621
  message: "Spec must have an overview",
1596
- code: ERROR_CODES.SDD_VALIDATION_FAILED,
1622
+ code: ERROR_CODES2.SDD_VALIDATION_FAILED,
1597
1623
  context: { field: "overview", title }
1598
1624
  });
1599
1625
  }
@@ -1694,6 +1720,9 @@ var AISpecBuilder = class {
1694
1720
  return null;
1695
1721
  }
1696
1722
  };
1723
+
1724
+ // src/sdd-interview-driver.ts
1725
+ import { TaskTracker as TaskTracker2, DefaultTaskStore as DefaultTaskStore2 } from "@wrongstack/core/tasking";
1697
1726
  var SddInterviewDriver = class {
1698
1727
  builder;
1699
1728
  o;
@@ -1732,7 +1761,7 @@ var SddInterviewDriver = class {
1732
1761
  const graph = await this.o.graphStore.load(graphId);
1733
1762
  if (graph) {
1734
1763
  this.graph = graph;
1735
- const tracker = new TaskTracker({ store: new DefaultTaskStore() });
1764
+ const tracker = new TaskTracker2({ store: new DefaultTaskStore2() });
1736
1765
  tracker.setGraph(graph);
1737
1766
  this.tracker = tracker;
1738
1767
  }
@@ -1814,7 +1843,7 @@ var SddInterviewDriver = class {
1814
1843
  if (this.graph) return this.graph;
1815
1844
  const spec = this.builder.getSession().spec;
1816
1845
  if (!spec) return null;
1817
- const tracker = new TaskTracker({ store: new DefaultTaskStore() });
1846
+ const tracker = new TaskTracker2({ store: new DefaultTaskStore2() });
1818
1847
  const generator = new TaskGenerator({
1819
1848
  taskTracker: tracker,
1820
1849
  verificationFromAcceptance: process.env["WRONGSTACK_SDD_VERIFY_FROM_ACCEPTANCE"] === "1"
@@ -1908,7 +1937,7 @@ var SddInterviewDriver = class {
1908
1937
  const spec = this.builder.getSession().spec;
1909
1938
  if (!spec) return void 0;
1910
1939
  if (!this.tracker || !this.graph) {
1911
- const tracker = new TaskTracker({ store: new DefaultTaskStore() });
1940
+ const tracker = new TaskTracker2({ store: new DefaultTaskStore2() });
1912
1941
  this.graph = await tracker.createGraph(spec.id, spec.title);
1913
1942
  this.tracker = tracker;
1914
1943
  }
@@ -1958,6 +1987,13 @@ function isExplanatoryText(text) {
1958
1987
  return lower.startsWith("i'") || lower.startsWith("i will") || lower.startsWith("let me") || lower.startsWith("here's my") || lower.startsWith("here is my") || lower.startsWith("i'm going to") || lower.startsWith("first, let me") || lower.startsWith("sure") || lower.startsWith("of course") || lower.startsWith("okay") || lower.startsWith("ok,") || lower.startsWith("sounds good") || lower.startsWith("no problem") || text.split("\n").length < 3 && !text.includes(".");
1959
1988
  }
1960
1989
 
1990
+ // src/sdd-parallel-run.ts
1991
+ import { expectDefined as expectDefined2 } from "@wrongstack/core";
1992
+ import { randomUUID as randomUUID2 } from "node:crypto";
1993
+ import { makeAgentSubagentRunner, withDisabledToolFiltering, DefaultMultiAgentCoordinator } from "@wrongstack/core/coordination";
1994
+ import { assignNickname } from "@wrongstack/core";
1995
+ import { SddError as SddError3, ERROR_CODES as ERROR_CODES3 } from "@wrongstack/core";
1996
+
1961
1997
  // src/sdd-task-decomposer.ts
1962
1998
  var SddTaskDecomposer = class {
1963
1999
  constructor(tracker, _graph, opts = {}) {
@@ -2074,7 +2110,7 @@ var SddParallelRun = class {
2074
2110
  this.maxRetries = Math.max(0, opts.maxRetries ?? 3);
2075
2111
  this.maxSupervisorEscalations = Math.max(0, opts.maxSupervisorEscalations ?? 2);
2076
2112
  this.maxFailedSweeps = Math.max(0, opts.maxFailedRetrySweeps ?? 2);
2077
- this.runId = opts.runId ?? `sdd-${randomUUID().slice(0, 8)}`;
2113
+ this.runId = opts.runId ?? `sdd-${randomUUID2().slice(0, 8)}`;
2078
2114
  this.events = opts.events;
2079
2115
  this.sessionIdSource = opts.sessionId;
2080
2116
  this.maxTotalWaves = opts.maxTotalWaves ?? opts.graph.nodes.size * (this.maxRetries + 2) + 10;
@@ -2555,7 +2591,7 @@ var SddParallelRun = class {
2555
2591
  // -------------------------------------------------------------------
2556
2592
  buildCoordinator() {
2557
2593
  const config = {
2558
- coordinatorId: `sdd-parallel-${randomUUID().slice(0, 8)}`,
2594
+ coordinatorId: `sdd-parallel-${randomUUID2().slice(0, 8)}`,
2559
2595
  maxConcurrent: this.slots,
2560
2596
  doneCondition: { type: "all_tasks_done" },
2561
2597
  // Default budget guard for every spawned worker: idle reaper (resets on
@@ -2619,13 +2655,13 @@ var SddParallelRun = class {
2619
2655
  }
2620
2656
  this.opts.tracker.updateNodeStatus(taskId, "in_progress");
2621
2657
  await this.allocateWorktrees([task]);
2622
- if (!this.coordinator) throw new SddError({
2658
+ if (!this.coordinator) throw new SddError3({
2623
2659
  message: "SDD parallel runner requires a coordinator",
2624
- code: ERROR_CODES.SDD_INVALID_STATE
2660
+ code: ERROR_CODES3.SDD_INVALID_STATE
2625
2661
  });
2626
2662
  const coordinator = this.coordinator;
2627
2663
  const subagentId = `sdd-d${this.dispatchSeq++}`;
2628
- const correlationId = randomUUID();
2664
+ const correlationId = randomUUID2();
2629
2665
  const meta = task.metadata ?? {};
2630
2666
  const model = (typeof meta.model === "string" ? meta.model : void 0) ?? this.opts.defaultModel;
2631
2667
  const provider = (typeof meta.provider === "string" ? meta.provider : void 0) ?? this.opts.defaultProvider;
@@ -2644,9 +2680,9 @@ var SddParallelRun = class {
2644
2680
  ...fallbackModels?.length ? { fallbackModels } : {}
2645
2681
  });
2646
2682
  if (!spawnResult.subagentId) {
2647
- throw new SddError({
2683
+ throw new SddError3({
2648
2684
  message: "One or more subagent spawns failed",
2649
- code: ERROR_CODES.SDD_INVALID_STATE
2685
+ code: ERROR_CODES3.SDD_INVALID_STATE
2650
2686
  });
2651
2687
  }
2652
2688
  this.taskSubagents.set(taskId, subagentId);
@@ -2684,7 +2720,7 @@ var SddParallelRun = class {
2684
2720
  let result;
2685
2721
  try {
2686
2722
  const got = await coordinator.awaitTasks([correlationId]);
2687
- result = expectDefined(got[0]);
2723
+ result = expectDefined2(got[0]);
2688
2724
  } catch (err) {
2689
2725
  result = {
2690
2726
  subagentId,
@@ -3083,6 +3119,10 @@ function startSddRun(opts) {
3083
3119
  stop: () => run.stop()
3084
3120
  };
3085
3121
  }
3122
+
3123
+ // src/sdd-lifecycle.ts
3124
+ import * as fsp4 from "node:fs/promises";
3125
+ import { WorktreeManager } from "@wrongstack/core";
3086
3126
  async function cleanupSddWorktrees(projectRoot) {
3087
3127
  const wt = new WorktreeManager({ projectRoot });
3088
3128
  return wt.cleanupAllManaged();
@@ -3149,14 +3189,14 @@ async function destroySddProject(opts) {
3149
3189
  const deleted = [];
3150
3190
  const rmDir = async (dir, label) => {
3151
3191
  try {
3152
- await fsp3.rm(dir, { recursive: true, force: true });
3192
+ await fsp4.rm(dir, { recursive: true, force: true });
3153
3193
  deleted.push(label);
3154
3194
  } catch {
3155
3195
  }
3156
3196
  };
3157
3197
  const rmFile = async (file, label) => {
3158
3198
  try {
3159
- await fsp3.unlink(file);
3199
+ await fsp4.unlink(file);
3160
3200
  deleted.push(label);
3161
3201
  } catch {
3162
3202
  }
@@ -3320,6 +3360,10 @@ function templateToMarkdown(template, title) {
3320
3360
  }
3321
3361
  return lines.join("\n");
3322
3362
  }
3363
+
3364
+ // src/task-visualizer.ts
3365
+ import { computeTaskProgress as computeTaskProgress2 } from "@wrongstack/core/types";
3366
+ import { truncate } from "@wrongstack/core";
3323
3367
  var STATUS_ICON = {
3324
3368
  pending: "\u25CB",
3325
3369
  in_progress: "\u25D0",
@@ -3349,7 +3393,7 @@ function renderTaskGraph(graph, opts) {
3349
3393
  lines.push(`\u2502 Spec: ${graph.specId.slice(0, 8)}... \u2502 Nodes: ${graph.nodes.size} \u2502 Edges: ${graph.edges.length} \u2502`);
3350
3394
  lines.push("\u2570" + "\u2500".repeat(Math.max(50, graph.title.length + 30)) + "\u256F");
3351
3395
  lines.push("");
3352
- const progress = computeTaskProgress(graph);
3396
+ const progress = computeTaskProgress2(graph);
3353
3397
  lines.push(renderProgress(progress));
3354
3398
  lines.push("");
3355
3399
  const childrenMap = /* @__PURE__ */ new Map();
@@ -3469,6 +3513,10 @@ function renderSpecAnalysis(spec, analysis) {
3469
3513
  }
3470
3514
  return lines.join("\n");
3471
3515
  }
3516
+
3517
+ // src/critical-path.ts
3518
+ import { expectDefined as expectDefined3 } from "@wrongstack/core";
3519
+ import { topologicalSort } from "@wrongstack/core/types";
3472
3520
  function analyzeCriticalPath(graph) {
3473
3521
  const nodes = Array.from(graph.nodes.values());
3474
3522
  const topoOrder = topologicalSort(graph);
@@ -3544,7 +3592,7 @@ function getTransitiveBlocked(_graph, taskId, blocksMap) {
3544
3592
  const visited = /* @__PURE__ */ new Set();
3545
3593
  const queue = [taskId];
3546
3594
  while (queue.length > 0) {
3547
- const current = expectDefined(queue.shift());
3595
+ const current = expectDefined3(queue.shift());
3548
3596
  const blocked = blocksMap.get(current);
3549
3597
  if (!blocked) continue;
3550
3598
  for (const id of blocked) {
@@ -3590,7 +3638,7 @@ function computeCriticalPath(graph, _topoOrder, blockedByMap) {
3590
3638
  if (!changed) break;
3591
3639
  }
3592
3640
  let maxDist = 0;
3593
- let maxId = expectDefined(allIds[0]);
3641
+ let maxId = expectDefined3(allIds[0]);
3594
3642
  for (const id of allIds) {
3595
3643
  const d = dist.get(id) ?? 0;
3596
3644
  if (d > maxDist) {
@@ -3638,6 +3686,9 @@ function computeParallelGroups(graph, blockedByMap) {
3638
3686
  }
3639
3687
  return groups;
3640
3688
  }
3689
+
3690
+ // src/spec-versioning.ts
3691
+ import { assertNever } from "@wrongstack/core";
3641
3692
  var SpecVersioning = class {
3642
3693
  versions = /* @__PURE__ */ new Map();
3643
3694
  /** Record a new version of a spec. */
@@ -3971,6 +4022,9 @@ function createAutoExecutor(opts) {
3971
4022
  maxRetries: opts.maxRetries
3972
4023
  });
3973
4024
  }
4025
+
4026
+ // src/sdd-supervisor.ts
4027
+ import { parseModelRef } from "@wrongstack/core";
3974
4028
  var SddSupervisor = class {
3975
4029
  constructor(opts) {
3976
4030
  this.opts = opts;
@@ -4021,6 +4075,9 @@ Supervisor rescues already used: ${attempts}`,
4021
4075
  return { action: "retry" };
4022
4076
  };
4023
4077
  };
4078
+
4079
+ // src/verify-task.ts
4080
+ import { spawn } from "node:child_process";
4024
4081
  function makeCommandVerifier(options = {}) {
4025
4082
  const metadataKey = options.metadataKey ?? "verificationCommand";
4026
4083
  const timeoutMs = options.timeoutMs ?? 18e4;
@@ -4057,6 +4114,12 @@ function makeCommandVerifier(options = {}) {
4057
4114
  });
4058
4115
  };
4059
4116
  }
4117
+
4118
+ // src/decompose-task.ts
4119
+ import {
4120
+ readBundledInstructionText,
4121
+ renderInstructionTemplate
4122
+ } from "@wrongstack/core";
4060
4123
  var TASK_TYPES2 = /* @__PURE__ */ new Set(["feature", "bugfix", "refactor", "docs", "test", "chore"]);
4061
4124
  var PRIORITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low"]);
4062
4125
  function extractJsonArray(text) {
@@ -4114,6 +4177,14 @@ function makeLlmSubtaskGenerator(opts) {
4114
4177
  return specs.length >= min ? specs : [];
4115
4178
  };
4116
4179
  }
4180
+
4181
+ // src/conflict-resolver.ts
4182
+ import { readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
4183
+ import { join as join4, isAbsolute } from "node:path";
4184
+ import {
4185
+ readBundledInstructionText as readBundledInstructionText2,
4186
+ renderInstructionTemplate as renderInstructionTemplate2
4187
+ } from "@wrongstack/core";
4117
4188
  var START = "<<<<<<<";
4118
4189
  var BASE = "|||||||";
4119
4190
  var SEP = "=======";
@@ -4155,17 +4226,17 @@ function makePreferSideConflictResolver(side) {
4155
4226
  return async function conflictResolver(info) {
4156
4227
  if (info.conflictFiles.length === 0) return false;
4157
4228
  for (const rel of info.conflictFiles) {
4158
- const abs = isAbsolute(rel) ? rel : join(info.cwd, rel);
4229
+ const abs = isAbsolute(rel) ? rel : join4(info.cwd, rel);
4159
4230
  let content;
4160
4231
  try {
4161
- content = await readFile(abs, "utf8");
4232
+ content = await readFile4(abs, "utf8");
4162
4233
  } catch {
4163
4234
  return false;
4164
4235
  }
4165
4236
  const resolved = resolveConflictText(content, side);
4166
4237
  if (hasConflictMarkers(resolved)) return false;
4167
4238
  try {
4168
- await writeFile(abs, resolved, "utf8");
4239
+ await writeFile2(abs, resolved, "utf8");
4169
4240
  } catch {
4170
4241
  return false;
4171
4242
  }
@@ -4188,16 +4259,16 @@ function makeLlmConflictResolver(opts) {
4188
4259
  return async function conflictResolver(info) {
4189
4260
  if (info.conflictFiles.length === 0) return false;
4190
4261
  for (const rel of info.conflictFiles) {
4191
- const abs = isAbsolute(rel) ? rel : join(info.cwd, rel);
4262
+ const abs = isAbsolute(rel) ? rel : join4(info.cwd, rel);
4192
4263
  let content;
4193
4264
  try {
4194
- content = await readFile(abs, "utf8");
4265
+ content = await readFile4(abs, "utf8");
4195
4266
  } catch {
4196
4267
  return false;
4197
4268
  }
4198
4269
  if (!hasConflictMarkers(content)) continue;
4199
- const prompt = renderInstructionTemplate(
4200
- readBundledInstructionText("sdd/merge-conflict-resolver.md"),
4270
+ const prompt = renderInstructionTemplate2(
4271
+ readBundledInstructionText2("sdd/merge-conflict-resolver.md"),
4201
4272
  {
4202
4273
  file: rel,
4203
4274
  content
@@ -4215,7 +4286,7 @@ function makeLlmConflictResolver(opts) {
4215
4286
  return false;
4216
4287
  }
4217
4288
  try {
4218
- await writeFile(abs, resolved, "utf8");
4289
+ await writeFile2(abs, resolved, "utf8");
4219
4290
  } catch {
4220
4291
  return false;
4221
4292
  }
@@ -4223,7 +4294,52 @@ function makeLlmConflictResolver(opts) {
4223
4294
  return true;
4224
4295
  };
4225
4296
  }
4226
-
4227
- export { AISpecBuilder, AutoExecutor, SPEC_TEMPLATES, SddBoardProjector, SddBoardStore, SddInterviewDriver, SddParallelRun, SddRunRegistry, SddSupervisor, SddTaskDecomposer, SpecDrivenDev, SpecParser, SpecStore, SpecVersioning, TaskFlow, TaskGenerator, TaskGraphStore, analyzeCriticalPath, applySddLifecycle, buildBoardSnapshot, buildBoardTasks, cleanupSddWorktrees, cleanupStaleSddWorktrees, cleanupStaleWorktrees, createAutoExecutor, destroySddProject, extractVerificationCommand, getTemplate, hasConflictMarkers, isExplanatoryText, listTemplates, makeCommandVerifier, makeLlmConflictResolver, makeLlmSubtaskGenerator, makePreferSideConflictResolver, renderProgress, renderSpecAnalysis, renderTaskGraph, renderTaskList, resolveConflictText, rollbackSddRunFromDisk, shortIdMap, startSddRun, templateToMarkdown };
4297
+ export {
4298
+ AISpecBuilder,
4299
+ AutoExecutor,
4300
+ DefaultTaskStore3 as DefaultTaskStore,
4301
+ SPEC_TEMPLATES,
4302
+ SddBoardProjector,
4303
+ SddBoardStore,
4304
+ SddInterviewDriver,
4305
+ SddParallelRun,
4306
+ SddRunRegistry,
4307
+ SddSupervisor,
4308
+ SddTaskDecomposer,
4309
+ SpecDrivenDev,
4310
+ SpecParser,
4311
+ SpecStore,
4312
+ SpecVersioning,
4313
+ TaskFlow,
4314
+ TaskGenerator,
4315
+ TaskGraphStore,
4316
+ TaskTracker3 as TaskTracker,
4317
+ analyzeCriticalPath,
4318
+ applySddLifecycle,
4319
+ buildBoardSnapshot,
4320
+ buildBoardTasks,
4321
+ cleanupSddWorktrees,
4322
+ cleanupStaleSddWorktrees,
4323
+ cleanupStaleWorktrees,
4324
+ createAutoExecutor,
4325
+ destroySddProject,
4326
+ extractVerificationCommand,
4327
+ getTemplate,
4328
+ hasConflictMarkers,
4329
+ isExplanatoryText,
4330
+ listTemplates,
4331
+ makeCommandVerifier,
4332
+ makeLlmConflictResolver,
4333
+ makeLlmSubtaskGenerator,
4334
+ makePreferSideConflictResolver,
4335
+ renderProgress,
4336
+ renderSpecAnalysis,
4337
+ renderTaskGraph,
4338
+ renderTaskList,
4339
+ resolveConflictText,
4340
+ rollbackSddRunFromDisk,
4341
+ shortIdMap,
4342
+ startSddRun,
4343
+ templateToMarkdown
4344
+ };
4228
4345
  //# sourceMappingURL=index.js.map
4229
- //# sourceMappingURL=index.js.map