@wrongstack/sdd 0.292.1 → 0.295.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.
- package/dist/index.js +230 -65
- package/dist/index.js.map +3 -3
- package/dist/sdd-board-projector.d.ts +9 -19
- package/dist/sdd-board-projector.d.ts.map +1 -1
- package/dist/sdd-board-store.d.ts +23 -1
- package/dist/sdd-board-store.d.ts.map +1 -1
- package/dist/sdd-parallel-run.d.ts +3 -3
- package/dist/sdd-parallel-run.d.ts.map +1 -1
- package/dist/sdd-supervisor.d.ts +1 -1
- package/dist/sdd-supervisor.d.ts.map +1 -1
- package/dist/spec-builder.d.ts.map +1 -1
- package/dist/start-sdd-run.d.ts +3 -3
- package/dist/start-sdd-run.d.ts.map +1 -1
- package/dist/task-tracker.d.ts +1 -1
- package/dist/task-tracker.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -356,7 +356,7 @@ import {
|
|
|
356
356
|
} from "@wrongstack/core/tasking";
|
|
357
357
|
|
|
358
358
|
// src/task-flow.ts
|
|
359
|
-
import { SddError, ERROR_CODES } from "@wrongstack/core";
|
|
359
|
+
import { SddError, ERROR_CODES } from "@wrongstack/core/types";
|
|
360
360
|
import { DefaultTaskStore, TaskTracker } from "@wrongstack/core/tasking";
|
|
361
361
|
var TaskFlow = class {
|
|
362
362
|
constructor(opts) {
|
|
@@ -549,7 +549,7 @@ var SpecDrivenDev = class {
|
|
|
549
549
|
import * as fsp from "node:fs/promises";
|
|
550
550
|
import * as path from "node:path";
|
|
551
551
|
import { randomUUID } from "node:crypto";
|
|
552
|
-
import { atomicWrite, ensureDir } from "@wrongstack/core";
|
|
552
|
+
import { atomicWrite, ensureDir } from "@wrongstack/core/utils";
|
|
553
553
|
var SpecStore = class {
|
|
554
554
|
baseDir;
|
|
555
555
|
indexPath;
|
|
@@ -663,7 +663,7 @@ var SpecStore = class {
|
|
|
663
663
|
// src/task-graph-store.ts
|
|
664
664
|
import * as fsp2 from "node:fs/promises";
|
|
665
665
|
import * as path2 from "node:path";
|
|
666
|
-
import { atomicWrite as atomicWrite2, ensureDir as ensureDir2 } from "@wrongstack/core";
|
|
666
|
+
import { atomicWrite as atomicWrite2, ensureDir as ensureDir2 } from "@wrongstack/core/utils";
|
|
667
667
|
function graphToJSON(graph) {
|
|
668
668
|
const serialisable = {
|
|
669
669
|
...graph,
|
|
@@ -762,7 +762,7 @@ var TaskGraphStore = class {
|
|
|
762
762
|
};
|
|
763
763
|
|
|
764
764
|
// src/board-types.ts
|
|
765
|
-
import { computeTaskProgress } from "@wrongstack/core/
|
|
765
|
+
import { computeTaskProgress } from "@wrongstack/core/tasking";
|
|
766
766
|
function shortIdMap(graph) {
|
|
767
767
|
const nodes = Array.from(graph.nodes.values()).sort((a, b) => a.createdAt - b.createdAt);
|
|
768
768
|
const m = /* @__PURE__ */ new Map();
|
|
@@ -854,13 +854,34 @@ function buildBoardSnapshot(graph, run, now) {
|
|
|
854
854
|
// src/sdd-board-store.ts
|
|
855
855
|
import * as fsp3 from "node:fs/promises";
|
|
856
856
|
import * as path3 from "node:path";
|
|
857
|
-
import { atomicWrite as atomicWrite3, ensureDir as ensureDir3 } from "@wrongstack/core";
|
|
857
|
+
import { atomicWrite as atomicWrite3, ensureDir as ensureDir3, withFileLock } from "@wrongstack/core/utils";
|
|
858
|
+
var DEFAULT_EVENT_MAX_BYTES = 16 * 1024 * 1024;
|
|
859
|
+
var DEFAULT_EVENT_KEEP_BYTES = 8 * 1024 * 1024;
|
|
860
|
+
var DEFAULT_EVENT_SIZE_CHECK_EVERY = 100;
|
|
858
861
|
var SddBoardStore = class {
|
|
859
862
|
baseDir;
|
|
860
863
|
indexPath;
|
|
864
|
+
eventMaxBytes;
|
|
865
|
+
eventKeepBytes;
|
|
866
|
+
eventSizeCheckEvery;
|
|
867
|
+
eventChains = /* @__PURE__ */ new Map();
|
|
868
|
+
eventWritesSinceCheck = /* @__PURE__ */ new Map();
|
|
869
|
+
controlDrains = /* @__PURE__ */ new Map();
|
|
870
|
+
baseDirReady;
|
|
871
|
+
cachedIndex;
|
|
872
|
+
cachedIndexSignature = null;
|
|
861
873
|
constructor(opts) {
|
|
862
874
|
this.baseDir = opts.baseDir;
|
|
863
875
|
this.indexPath = path3.join(this.baseDir, "_index.json");
|
|
876
|
+
this.eventMaxBytes = Math.max(1024, Math.floor(opts.eventMaxBytes ?? DEFAULT_EVENT_MAX_BYTES));
|
|
877
|
+
this.eventKeepBytes = Math.min(
|
|
878
|
+
this.eventMaxBytes,
|
|
879
|
+
Math.max(0, Math.floor(opts.eventKeepBytes ?? DEFAULT_EVENT_KEEP_BYTES))
|
|
880
|
+
);
|
|
881
|
+
this.eventSizeCheckEvery = Math.max(
|
|
882
|
+
1,
|
|
883
|
+
Math.floor(opts.eventSizeCheckEvery ?? DEFAULT_EVENT_SIZE_CHECK_EVERY)
|
|
884
|
+
);
|
|
864
885
|
}
|
|
865
886
|
snapshotPath(runId) {
|
|
866
887
|
return path3.join(this.baseDir, `${this.safe(runId)}.json`);
|
|
@@ -872,7 +893,7 @@ var SddBoardStore = class {
|
|
|
872
893
|
return path3.join(this.baseDir, `${this.safe(runId)}.control.jsonl`);
|
|
873
894
|
}
|
|
874
895
|
async saveSnapshot(snapshot) {
|
|
875
|
-
await
|
|
896
|
+
await this.ensureBaseDir();
|
|
876
897
|
await atomicWrite3(this.snapshotPath(snapshot.runId), JSON.stringify(snapshot, null, 2), {
|
|
877
898
|
mode: 384
|
|
878
899
|
});
|
|
@@ -888,7 +909,12 @@ var SddBoardStore = class {
|
|
|
888
909
|
}
|
|
889
910
|
async list() {
|
|
890
911
|
const index = await this.readIndex();
|
|
891
|
-
return index.entries.
|
|
912
|
+
return index.entries.map((entry) => ({ ...entry }));
|
|
913
|
+
}
|
|
914
|
+
/** Latest board metadata without cloning/sorting the complete index. */
|
|
915
|
+
async latest() {
|
|
916
|
+
const entry = (await this.readIndex()).entries[0];
|
|
917
|
+
return entry ? { ...entry } : void 0;
|
|
892
918
|
}
|
|
893
919
|
async loadLatestForSpec(specId) {
|
|
894
920
|
const entry = (await this.list()).find((e) => e.specId === specId);
|
|
@@ -896,63 +922,160 @@ var SddBoardStore = class {
|
|
|
896
922
|
}
|
|
897
923
|
/** Append one line to the board's JSONL event log (best-effort, never throws). */
|
|
898
924
|
async appendEvent(runId, event) {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
925
|
+
const filePath = this.eventsPath(runId);
|
|
926
|
+
const previous = this.eventChains.get(filePath) ?? Promise.resolve();
|
|
927
|
+
const write = previous.then(() => this.appendEventInternal(filePath, event)).catch(() => void 0);
|
|
928
|
+
this.eventChains.set(filePath, write);
|
|
929
|
+
await write;
|
|
930
|
+
if (this.eventChains.get(filePath) === write) this.eventChains.delete(filePath);
|
|
905
931
|
}
|
|
906
932
|
/** Append a control command (used by readers to steer a CLI-owned run). */
|
|
907
933
|
async appendControl(runId, command) {
|
|
908
|
-
await
|
|
909
|
-
|
|
910
|
-
|
|
934
|
+
await this.ensureBaseDir();
|
|
935
|
+
const filePath = this.controlPath(runId);
|
|
936
|
+
await withFileLock(
|
|
937
|
+
filePath,
|
|
938
|
+
() => fsp3.appendFile(filePath, `${JSON.stringify(command)}
|
|
939
|
+
`, { mode: 384 })
|
|
940
|
+
);
|
|
911
941
|
}
|
|
912
942
|
/** Read + truncate the control queue (the run drains it). Returns parsed commands. */
|
|
913
943
|
async drainControl(runId) {
|
|
914
|
-
const
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
} catch {
|
|
944
|
+
const filePath = this.controlPath(runId);
|
|
945
|
+
const active = this.controlDrains.get(filePath);
|
|
946
|
+
if (active) {
|
|
947
|
+
await active;
|
|
919
948
|
return [];
|
|
920
949
|
}
|
|
950
|
+
const drain = this.drainControlInternal(filePath);
|
|
951
|
+
this.controlDrains.set(filePath, drain);
|
|
921
952
|
try {
|
|
922
|
-
await
|
|
923
|
-
}
|
|
953
|
+
return await drain;
|
|
954
|
+
} finally {
|
|
955
|
+
if (this.controlDrains.get(filePath) === drain) this.controlDrains.delete(filePath);
|
|
924
956
|
}
|
|
925
|
-
return raw.split("\n").filter((l) => l.trim()).map((l) => {
|
|
926
|
-
try {
|
|
927
|
-
return JSON.parse(l);
|
|
928
|
-
} catch {
|
|
929
|
-
return null;
|
|
930
|
-
}
|
|
931
|
-
}).filter((c) => c !== null);
|
|
932
957
|
}
|
|
933
958
|
async delete(runId) {
|
|
959
|
+
const eventPath = this.eventsPath(runId);
|
|
960
|
+
await this.eventChains.get(eventPath)?.catch(() => void 0);
|
|
961
|
+
this.eventChains.delete(eventPath);
|
|
934
962
|
await Promise.allSettled([
|
|
935
963
|
fsp3.unlink(this.snapshotPath(runId)),
|
|
936
|
-
fsp3.unlink(
|
|
964
|
+
fsp3.unlink(eventPath),
|
|
937
965
|
fsp3.unlink(this.controlPath(runId))
|
|
938
966
|
]);
|
|
967
|
+
this.eventWritesSinceCheck.delete(eventPath);
|
|
939
968
|
await this.removeFromIndex(runId);
|
|
940
969
|
}
|
|
941
970
|
// ── internal ────────────────────────────────────────────────────────────
|
|
942
971
|
safe(runId) {
|
|
943
972
|
return runId.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
944
973
|
}
|
|
974
|
+
async ensureBaseDir() {
|
|
975
|
+
this.baseDirReady ??= ensureDir3(this.baseDir).catch((error) => {
|
|
976
|
+
this.baseDirReady = void 0;
|
|
977
|
+
throw error;
|
|
978
|
+
});
|
|
979
|
+
await this.baseDirReady;
|
|
980
|
+
}
|
|
981
|
+
async appendEventInternal(filePath, event) {
|
|
982
|
+
await this.ensureBaseDir();
|
|
983
|
+
await fsp3.appendFile(filePath, `${JSON.stringify(event)}
|
|
984
|
+
`, { mode: 384 });
|
|
985
|
+
const writes = (this.eventWritesSinceCheck.get(filePath) ?? 0) + 1;
|
|
986
|
+
if (writes < this.eventSizeCheckEvery) {
|
|
987
|
+
this.eventWritesSinceCheck.set(filePath, writes);
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
this.eventWritesSinceCheck.set(filePath, 0);
|
|
991
|
+
const stat2 = await fsp3.stat(filePath);
|
|
992
|
+
if (stat2.size <= this.eventMaxBytes) return;
|
|
993
|
+
await this.compactEventTail(filePath, stat2.size);
|
|
994
|
+
}
|
|
995
|
+
async compactEventTail(filePath, size) {
|
|
996
|
+
if (this.eventKeepBytes === 0) {
|
|
997
|
+
await atomicWrite3(filePath, "", { mode: 384 });
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const handle = await fsp3.open(filePath, "r");
|
|
1001
|
+
let retained;
|
|
1002
|
+
try {
|
|
1003
|
+
const length = Math.min(size, this.eventKeepBytes);
|
|
1004
|
+
const start = size - length;
|
|
1005
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
1006
|
+
const { bytesRead } = await handle.read(buffer, 0, length, start);
|
|
1007
|
+
retained = buffer.subarray(0, bytesRead);
|
|
1008
|
+
if (start > 0 && retained.length > 0) {
|
|
1009
|
+
const previous = Buffer.allocUnsafe(1);
|
|
1010
|
+
const preceding = await handle.read(previous, 0, 1, start - 1);
|
|
1011
|
+
if (preceding.bytesRead !== 1 || previous[0] !== 10) {
|
|
1012
|
+
const firstNewline = retained.indexOf(10);
|
|
1013
|
+
retained = firstNewline >= 0 ? retained.subarray(firstNewline + 1) : retained.subarray(0, 0);
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
} finally {
|
|
1017
|
+
await handle.close();
|
|
1018
|
+
}
|
|
1019
|
+
await atomicWrite3(filePath, retained, { mode: 384 });
|
|
1020
|
+
}
|
|
1021
|
+
async drainControlInternal(filePath) {
|
|
1022
|
+
try {
|
|
1023
|
+
const stat2 = await fsp3.stat(filePath);
|
|
1024
|
+
if (stat2.size === 0) return [];
|
|
1025
|
+
} catch {
|
|
1026
|
+
return [];
|
|
1027
|
+
}
|
|
1028
|
+
return withFileLock(filePath, async () => {
|
|
1029
|
+
let raw;
|
|
1030
|
+
try {
|
|
1031
|
+
const stat2 = await fsp3.stat(filePath);
|
|
1032
|
+
if (stat2.size === 0) return [];
|
|
1033
|
+
raw = await fsp3.readFile(filePath, "utf8");
|
|
1034
|
+
} catch {
|
|
1035
|
+
return [];
|
|
1036
|
+
}
|
|
1037
|
+
try {
|
|
1038
|
+
await fsp3.truncate(filePath, 0);
|
|
1039
|
+
} catch {
|
|
1040
|
+
return [];
|
|
1041
|
+
}
|
|
1042
|
+
return raw.split("\n").filter((line) => line.trim()).map((line) => {
|
|
1043
|
+
try {
|
|
1044
|
+
return JSON.parse(line);
|
|
1045
|
+
} catch {
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
}).filter(
|
|
1049
|
+
(command) => command !== null
|
|
1050
|
+
);
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
945
1053
|
async readIndex() {
|
|
1054
|
+
const signature = await this.indexSignature();
|
|
1055
|
+
if (this.cachedIndex && sameIndexSignature(signature, this.cachedIndexSignature)) {
|
|
1056
|
+
return this.cachedIndex;
|
|
1057
|
+
}
|
|
946
1058
|
try {
|
|
947
1059
|
const raw = await fsp3.readFile(this.indexPath, "utf8");
|
|
948
1060
|
const parsed = JSON.parse(raw);
|
|
949
|
-
if (parsed?.version === 1)
|
|
1061
|
+
if (parsed?.version === 1) {
|
|
1062
|
+
parsed.entries.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
1063
|
+
this.cachedIndex = parsed;
|
|
1064
|
+
this.cachedIndexSignature = signature;
|
|
1065
|
+
return parsed;
|
|
1066
|
+
}
|
|
950
1067
|
} catch {
|
|
951
1068
|
}
|
|
952
|
-
|
|
1069
|
+
this.cachedIndex = { version: 1, entries: [] };
|
|
1070
|
+
this.cachedIndexSignature = signature;
|
|
1071
|
+
return this.cachedIndex;
|
|
953
1072
|
}
|
|
954
1073
|
async updateIndex(snapshot) {
|
|
955
|
-
const
|
|
1074
|
+
const current = await this.readIndex();
|
|
1075
|
+
const index = {
|
|
1076
|
+
version: 1,
|
|
1077
|
+
entries: current.entries.map((entry2) => ({ ...entry2 }))
|
|
1078
|
+
};
|
|
956
1079
|
const entry = {
|
|
957
1080
|
runId: snapshot.runId,
|
|
958
1081
|
specId: snapshot.specId,
|
|
@@ -965,17 +1088,37 @@ var SddBoardStore = class {
|
|
|
965
1088
|
const idx = index.entries.findIndex((e) => e.runId === snapshot.runId);
|
|
966
1089
|
if (idx >= 0) index.entries[idx] = entry;
|
|
967
1090
|
else index.entries.push(entry);
|
|
1091
|
+
index.entries.sort((a, b) => b.updatedAt - a.updatedAt);
|
|
968
1092
|
await atomicWrite3(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
|
|
1093
|
+
this.cachedIndex = index;
|
|
1094
|
+
this.cachedIndexSignature = await this.indexSignature();
|
|
969
1095
|
}
|
|
970
1096
|
async removeFromIndex(runId) {
|
|
971
|
-
const
|
|
972
|
-
index
|
|
1097
|
+
const current = await this.readIndex();
|
|
1098
|
+
const index = {
|
|
1099
|
+
version: 1,
|
|
1100
|
+
entries: current.entries.filter((entry) => entry.runId !== runId).map((entry) => ({ ...entry }))
|
|
1101
|
+
};
|
|
973
1102
|
await atomicWrite3(this.indexPath, JSON.stringify(index, null, 2), { mode: 384 });
|
|
1103
|
+
this.cachedIndex = index;
|
|
1104
|
+
this.cachedIndexSignature = await this.indexSignature();
|
|
1105
|
+
}
|
|
1106
|
+
async indexSignature() {
|
|
1107
|
+
try {
|
|
1108
|
+
const stat2 = await fsp3.stat(this.indexPath);
|
|
1109
|
+
return { size: stat2.size, mtimeMs: stat2.mtimeMs, ctimeMs: stat2.ctimeMs };
|
|
1110
|
+
} catch {
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
974
1113
|
}
|
|
975
1114
|
};
|
|
1115
|
+
function sameIndexSignature(a, b) {
|
|
1116
|
+
if (a === null || b === null) return a === b;
|
|
1117
|
+
return a.size === b.size && a.mtimeMs === b.mtimeMs && a.ctimeMs === b.ctimeMs;
|
|
1118
|
+
}
|
|
976
1119
|
|
|
977
1120
|
// src/sdd-board-projector.ts
|
|
978
|
-
import { DefaultSecretScrubber } from "@wrongstack/core";
|
|
1121
|
+
import { DefaultSecretScrubber } from "@wrongstack/core/security";
|
|
979
1122
|
function summarizeToolInput(input, scrubber) {
|
|
980
1123
|
if (!input || typeof input !== "object" || Array.isArray(input)) return void 0;
|
|
981
1124
|
const record = input;
|
|
@@ -1020,8 +1163,10 @@ var SddBoardProjector = class _SddBoardProjector {
|
|
|
1020
1163
|
dirty = false;
|
|
1021
1164
|
timer = null;
|
|
1022
1165
|
unsubs = [];
|
|
1023
|
-
/**
|
|
1024
|
-
|
|
1166
|
+
/** Latest snapshot waiting behind an in-flight disk write. */
|
|
1167
|
+
pendingSnapshot;
|
|
1168
|
+
/** At most one persistence loop runs; intermediate snapshots are coalesced. */
|
|
1169
|
+
saveLoop;
|
|
1025
1170
|
constructor(opts) {
|
|
1026
1171
|
this.o = opts;
|
|
1027
1172
|
this.now = opts.now ?? Date.now;
|
|
@@ -1257,7 +1402,12 @@ var SddBoardProjector = class _SddBoardProjector {
|
|
|
1257
1402
|
}
|
|
1258
1403
|
/** Resolve once all in-flight snapshot persistence has settled. */
|
|
1259
1404
|
async drain() {
|
|
1260
|
-
|
|
1405
|
+
for (; ; ) {
|
|
1406
|
+
const observed = this.saveLoop;
|
|
1407
|
+
if (!observed) return;
|
|
1408
|
+
await observed;
|
|
1409
|
+
if (observed === this.saveLoop && !this.pendingSnapshot) return;
|
|
1410
|
+
}
|
|
1261
1411
|
}
|
|
1262
1412
|
/** Stop projecting and release subscriptions. */
|
|
1263
1413
|
dispose() {
|
|
@@ -1345,8 +1495,25 @@ var SddBoardProjector = class _SddBoardProjector {
|
|
|
1345
1495
|
snapshot: snap
|
|
1346
1496
|
});
|
|
1347
1497
|
if (this.o.store) {
|
|
1348
|
-
|
|
1349
|
-
this.
|
|
1498
|
+
this.pendingSnapshot = snap;
|
|
1499
|
+
this.startSaveLoop(this.o.store);
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
startSaveLoop(store) {
|
|
1503
|
+
if (this.saveLoop) return;
|
|
1504
|
+
const loop = this.persistPendingSnapshots(store);
|
|
1505
|
+
this.saveLoop = loop;
|
|
1506
|
+
void loop.finally(() => {
|
|
1507
|
+
if (this.saveLoop !== loop) return;
|
|
1508
|
+
this.saveLoop = void 0;
|
|
1509
|
+
if (this.pendingSnapshot) this.startSaveLoop(store);
|
|
1510
|
+
});
|
|
1511
|
+
}
|
|
1512
|
+
async persistPendingSnapshots(store) {
|
|
1513
|
+
while (this.pendingSnapshot) {
|
|
1514
|
+
const snapshot = this.pendingSnapshot;
|
|
1515
|
+
this.pendingSnapshot = void 0;
|
|
1516
|
+
await store.saveSnapshot(snapshot).catch(() => {
|
|
1350
1517
|
});
|
|
1351
1518
|
}
|
|
1352
1519
|
}
|
|
@@ -1371,9 +1538,8 @@ var SddRunRegistry = class {
|
|
|
1371
1538
|
};
|
|
1372
1539
|
|
|
1373
1540
|
// src/spec-builder.ts
|
|
1374
|
-
import { expectDefined } from "@wrongstack/core";
|
|
1375
|
-
import {
|
|
1376
|
-
import { SddError as SddError2, ERROR_CODES as ERROR_CODES2 } from "@wrongstack/core";
|
|
1541
|
+
import { expectDefined, toErrorMessage } from "@wrongstack/core/utils";
|
|
1542
|
+
import { SddError as SddError2, ERROR_CODES as ERROR_CODES2 } from "@wrongstack/core/types";
|
|
1377
1543
|
function buildQuestioningPrompt(session, min, max) {
|
|
1378
1544
|
const answered = session.answers.length;
|
|
1379
1545
|
const remaining = Math.max(0, min - answered);
|
|
@@ -1595,7 +1761,7 @@ var AISpecBuilder = class {
|
|
|
1595
1761
|
try {
|
|
1596
1762
|
const fsp5 = await import("node:fs/promises");
|
|
1597
1763
|
const path4 = await import("node:path");
|
|
1598
|
-
const { atomicWrite: atomicWrite4 } = await import("@wrongstack/core");
|
|
1764
|
+
const { atomicWrite: atomicWrite4 } = await import("@wrongstack/core/utils");
|
|
1599
1765
|
await fsp5.mkdir(path4.dirname(this.sessionPath), { recursive: true });
|
|
1600
1766
|
await atomicWrite4(this.sessionPath, JSON.stringify(this.session, null, 2));
|
|
1601
1767
|
} catch {
|
|
@@ -2195,14 +2361,13 @@ function isExplanatoryText(text) {
|
|
|
2195
2361
|
}
|
|
2196
2362
|
|
|
2197
2363
|
// src/start-sdd-run.ts
|
|
2198
|
-
import { TOKENS } from "@wrongstack/core";
|
|
2364
|
+
import { TOKENS } from "@wrongstack/core/kernel";
|
|
2199
2365
|
|
|
2200
2366
|
// src/sdd-parallel-run.ts
|
|
2201
|
-
import { expectDefined as expectDefined2 } from "@wrongstack/core";
|
|
2367
|
+
import { expectDefined as expectDefined2 } from "@wrongstack/core/utils";
|
|
2202
2368
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2203
|
-
import { makeAgentSubagentRunner, withDisabledToolFiltering, DefaultMultiAgentCoordinator } from "@wrongstack/core/coordination";
|
|
2204
|
-
import {
|
|
2205
|
-
import { SddError as SddError3, ERROR_CODES as ERROR_CODES3 } from "@wrongstack/core";
|
|
2369
|
+
import { assignNickname, makeAgentSubagentRunner, withDisabledToolFiltering, DefaultMultiAgentCoordinator } from "@wrongstack/core/coordination";
|
|
2370
|
+
import { SddError as SddError3, ERROR_CODES as ERROR_CODES3 } from "@wrongstack/core/types";
|
|
2206
2371
|
|
|
2207
2372
|
// src/sdd-task-decomposer.ts
|
|
2208
2373
|
var SddTaskDecomposer = class {
|
|
@@ -3341,7 +3506,7 @@ function startSddRun(opts) {
|
|
|
3341
3506
|
|
|
3342
3507
|
// src/sdd-lifecycle.ts
|
|
3343
3508
|
import * as fsp4 from "node:fs/promises";
|
|
3344
|
-
import { WorktreeManager } from "@wrongstack/core";
|
|
3509
|
+
import { WorktreeManager } from "@wrongstack/core/worktree";
|
|
3345
3510
|
async function cleanupSddWorktrees(projectRoot) {
|
|
3346
3511
|
const wt = new WorktreeManager({ projectRoot });
|
|
3347
3512
|
return wt.cleanupAllManaged();
|
|
@@ -3581,8 +3746,8 @@ function templateToMarkdown(template, title) {
|
|
|
3581
3746
|
}
|
|
3582
3747
|
|
|
3583
3748
|
// src/task-visualizer.ts
|
|
3584
|
-
import { computeTaskProgress as computeTaskProgress2 } from "@wrongstack/core/
|
|
3585
|
-
import { truncate } from "@wrongstack/core";
|
|
3749
|
+
import { computeTaskProgress as computeTaskProgress2 } from "@wrongstack/core/tasking";
|
|
3750
|
+
import { truncate as truncate2 } from "@wrongstack/core/utils";
|
|
3586
3751
|
var STATUS_ICON = {
|
|
3587
3752
|
pending: "\u25CB",
|
|
3588
3753
|
in_progress: "\u25D0",
|
|
@@ -3649,14 +3814,14 @@ function renderNode(graph, nodeId, lines, rendered, childrenMap, compact, prefix
|
|
|
3649
3814
|
const icon = STATUS_ICON[node.status];
|
|
3650
3815
|
const prioIcon = PRIORITY_ICON[node.priority];
|
|
3651
3816
|
const typeIcon = TYPE_ICON[node.type];
|
|
3652
|
-
const title = compact ?
|
|
3817
|
+
const title = compact ? truncate2(node.title, 40) : node.title;
|
|
3653
3818
|
const blockedBy = childrenMap.get(nodeId) ?? [];
|
|
3654
3819
|
const depsStr = blockedBy.length > 0 ? ` \u2190 [${blockedBy.map((d) => graph.nodes.get(d)?.title?.slice(0, 12) ?? "?").join(", ")}]` : "";
|
|
3655
3820
|
lines.push(`${prefix}${icon} ${typeIcon} ${prioIcon} ${title}${depsStr}`);
|
|
3656
3821
|
if (!compact && node.description) {
|
|
3657
3822
|
const descLines = node.description.split("\n").slice(0, 3);
|
|
3658
3823
|
for (const dl of descLines) {
|
|
3659
|
-
lines.push(`${prefix} \u2514 ${
|
|
3824
|
+
lines.push(`${prefix} \u2514 ${truncate2(dl, 60)}`);
|
|
3660
3825
|
}
|
|
3661
3826
|
}
|
|
3662
3827
|
const dependents = graph.edges.filter((e) => e.type === "depends_on" && e.to === nodeId).map((e) => e.from).filter((id) => graph.nodes.has(id));
|
|
@@ -3734,8 +3899,8 @@ function renderSpecAnalysis(spec, analysis) {
|
|
|
3734
3899
|
}
|
|
3735
3900
|
|
|
3736
3901
|
// src/critical-path.ts
|
|
3737
|
-
import { expectDefined as expectDefined3 } from "@wrongstack/core";
|
|
3738
|
-
import { topologicalSort } from "@wrongstack/core/
|
|
3902
|
+
import { expectDefined as expectDefined3 } from "@wrongstack/core/utils";
|
|
3903
|
+
import { topologicalSort } from "@wrongstack/core/tasking";
|
|
3739
3904
|
function analyzeCriticalPath(graph) {
|
|
3740
3905
|
const nodes = Array.from(graph.nodes.values());
|
|
3741
3906
|
const topoOrder = topologicalSort(graph);
|
|
@@ -3907,7 +4072,7 @@ function computeParallelGroups(graph, blockedByMap) {
|
|
|
3907
4072
|
}
|
|
3908
4073
|
|
|
3909
4074
|
// src/spec-versioning.ts
|
|
3910
|
-
import { assertNever } from "@wrongstack/core";
|
|
4075
|
+
import { assertNever } from "@wrongstack/core/utils";
|
|
3911
4076
|
var SpecVersioning = class {
|
|
3912
4077
|
versions = /* @__PURE__ */ new Map();
|
|
3913
4078
|
/** Record a new version of a spec. */
|
|
@@ -4243,7 +4408,7 @@ function createAutoExecutor(opts) {
|
|
|
4243
4408
|
}
|
|
4244
4409
|
|
|
4245
4410
|
// src/sdd-supervisor.ts
|
|
4246
|
-
import { parseModelRef } from "@wrongstack/core";
|
|
4411
|
+
import { parseModelRef } from "@wrongstack/core/agent";
|
|
4247
4412
|
var SddSupervisor = class {
|
|
4248
4413
|
constructor(opts) {
|
|
4249
4414
|
this.opts = opts;
|
|
@@ -4338,7 +4503,7 @@ function makeCommandVerifier(options = {}) {
|
|
|
4338
4503
|
import {
|
|
4339
4504
|
readBundledInstructionText,
|
|
4340
4505
|
renderInstructionTemplate
|
|
4341
|
-
} from "@wrongstack/core";
|
|
4506
|
+
} from "@wrongstack/core/utils";
|
|
4342
4507
|
var TASK_TYPES2 = /* @__PURE__ */ new Set(["feature", "bugfix", "refactor", "docs", "test", "chore"]);
|
|
4343
4508
|
var PRIORITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low"]);
|
|
4344
4509
|
function extractJsonArray(text) {
|
|
@@ -4398,12 +4563,12 @@ function makeLlmSubtaskGenerator(opts) {
|
|
|
4398
4563
|
}
|
|
4399
4564
|
|
|
4400
4565
|
// src/conflict-resolver.ts
|
|
4401
|
-
import { readFile as readFile4, writeFile
|
|
4566
|
+
import { readFile as readFile4, writeFile } from "node:fs/promises";
|
|
4402
4567
|
import { join as join4, isAbsolute } from "node:path";
|
|
4403
4568
|
import {
|
|
4404
4569
|
readBundledInstructionText as readBundledInstructionText2,
|
|
4405
4570
|
renderInstructionTemplate as renderInstructionTemplate2
|
|
4406
|
-
} from "@wrongstack/core";
|
|
4571
|
+
} from "@wrongstack/core/utils";
|
|
4407
4572
|
var START = "<<<<<<<";
|
|
4408
4573
|
var BASE = "|||||||";
|
|
4409
4574
|
var SEP = "=======";
|
|
@@ -4455,7 +4620,7 @@ function makePreferSideConflictResolver(side) {
|
|
|
4455
4620
|
const resolved = resolveConflictText(content, side);
|
|
4456
4621
|
if (hasConflictMarkers(resolved)) return false;
|
|
4457
4622
|
try {
|
|
4458
|
-
await
|
|
4623
|
+
await writeFile(abs, resolved, "utf8");
|
|
4459
4624
|
} catch {
|
|
4460
4625
|
return false;
|
|
4461
4626
|
}
|
|
@@ -4505,7 +4670,7 @@ function makeLlmConflictResolver(opts) {
|
|
|
4505
4670
|
return false;
|
|
4506
4671
|
}
|
|
4507
4672
|
try {
|
|
4508
|
-
await
|
|
4673
|
+
await writeFile(abs, resolved, "utf8");
|
|
4509
4674
|
} catch {
|
|
4510
4675
|
return false;
|
|
4511
4676
|
}
|