opencode-swarm 7.144.1 → 7.144.2
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/agents/architect.d.ts +1 -0
- package/dist/agents/coder.d.ts +1 -0
- package/dist/agents/critic.d.ts +1 -0
- package/dist/agents/explorer.d.ts +1 -0
- package/dist/agents/reviewer.d.ts +1 -0
- package/dist/cli/{ast-diff-ypptrcan.js → ast-diff-wbjcazfx.js} +5 -3
- package/dist/cli/{config-doctor-5hj26phk.js → config-doctor-7dfvxwjb.js} +3 -3
- package/dist/cli/{core-aqtegsag.js → core-dwmwdc4y.js} +2 -2
- package/dist/cli/{curator-llm-factory-1rg62kzr.js → curator-llm-factory-rrs1q4hg.js} +20 -20
- package/dist/cli/{curator-vcrcht4h.js → curator-w213v33y.js} +20 -20
- package/dist/cli/{evidence-summary-service-fsh6jfhm.js → evidence-summary-service-t7n2h1he.js} +7 -7
- package/dist/cli/{explorer-18353rhn.js → explorer-zvk5kbcb.js} +3 -1
- package/dist/cli/{gate-evidence-9w2eehnj.js → gate-evidence-xvxn603y.js} +3 -3
- package/dist/cli/{guardrail-explain-6mxn4bj8.js → guardrail-explain-v1mwsnkq.js} +21 -21
- package/dist/cli/{guardrail-log-81c5b018.js → guardrail-log-dn03dpz2.js} +4 -4
- package/dist/cli/{hive-promoter-rxkykddk.js → hive-promoter-asjtj7ga.js} +20 -20
- package/dist/cli/{index-8gs34d2q.js → index-333kvewd.js} +4 -4
- package/dist/cli/{index-xmzmeknp.js → index-70ha9e09.js} +2 -1
- package/dist/cli/{index-dq26vbfp.js → index-7ca3a6gj.js} +3 -3
- package/dist/cli/{index-5n69863d.js → index-7ryh498h.js} +1 -173
- package/dist/cli/{index-g0vr2a4m.js → index-av0f6mm0.js} +5 -5
- package/dist/cli/{index-c3zag2cw.js → index-ckrasab9.js} +4 -4
- package/dist/cli/{index-sqp6349j.js → index-d55crzd4.js} +1 -1
- package/dist/cli/index-ddpkwdcb.js +176 -0
- package/dist/cli/{index-8jrn4rwp.js → index-dg2w0wr4.js} +3 -3
- package/dist/cli/{index-2ht8c7ew.js → index-dhh2j2nd.js} +2 -7
- package/dist/cli/{index-bgdr1ww3.js → index-g1c5fgaw.js} +1 -1
- package/dist/cli/{index-j2eb0x44.js → index-g2ajae1z.js} +2 -2
- package/dist/cli/{index-j3byg0a9.js → index-h3z64mhz.js} +6 -2
- package/dist/cli/{index-4s5htbgq.js → index-hqvt3mhk.js} +1 -1
- package/dist/cli/{index-mz1zwz96.js → index-jb4tchvy.js} +2 -2
- package/dist/cli/{index-n11zkp9g.js → index-jsfghpy2.js} +2 -2
- package/dist/cli/{index-2pmaxbvj.js → index-m6wv2qdr.js} +1 -1
- package/dist/cli/{index-315tnsve.js → index-ne8cfgw5.js} +1 -1
- package/dist/cli/{index-e9w1tfmm.js → index-nretd4qn.js} +6659 -1725
- package/dist/cli/{index-rr2fjfsd.js → index-p3tnmkvc.js} +3 -3
- package/dist/cli/{index-1faydhv8.js → index-qpt8ahph.js} +196 -93
- package/dist/cli/{index-hc25qawy.js → index-tg9fn2dy.js} +22 -22
- package/dist/cli/{index-jqsfsqbx.js → index-whezv7vc.js} +4 -0
- package/dist/cli/{index-4905hd2m.js → index-wx8zdh4a.js} +6 -1
- package/dist/cli/{index-rdb3nr6d.js → index-y95nwsge.js} +1 -1
- package/dist/cli/{index-f79hf8dr.js → index-zr370283.js} +3 -3
- package/dist/cli/index.js +22 -36
- package/dist/cli/{knowledge-escalator-hg4jzbrx.js → knowledge-escalator-cg19dhe5.js} +7 -7
- package/dist/cli/{knowledge-events-wgy7gbct.js → knowledge-events-yzvysaqd.js} +5 -5
- package/dist/cli/{knowledge-store-nd0f0e86.js → knowledge-store-6f77xpmm.js} +1 -1
- package/dist/cli/{knowledge-validator-0ar015bf.js → knowledge-validator-4b28zdxa.js} +2 -2
- package/dist/cli/{runtime-te94z1zb.js → runtime-x10qb3z1.js} +3 -2
- package/dist/cli/{scan-cursor-pqp3bsqv.js → scan-cursor-nqbb1xt6.js} +2 -2
- package/dist/cli/{schema-4ew49zrv.js → schema-jj2pb6zp.js} +2 -2
- package/dist/cli/{scope-persistence-geth2hb1.js → scope-persistence-63nasq0z.js} +5 -5
- package/dist/cli/{skill-generator-8azm6p2y.js → skill-generator-nsymtdqm.js} +8 -8
- package/dist/cli/tree-sitter-431q1bka.js +26 -0
- package/dist/cli/{worktree-isolation-cqxgdk2p.js → worktree-isolation-g54kxw6x.js} +20 -20
- package/dist/config/constants.d.ts +1 -1
- package/dist/config/schema.d.ts +8 -0
- package/dist/hooks/review-receipt-scope.d.ts +42 -15
- package/dist/hooks/reviewer-scope-file-fingerprint.d.ts +58 -6
- package/dist/hooks/reviewer-scope-lifecycle.d.ts +9 -1
- package/dist/hooks/reviewer-scope-mergeback.d.ts +23 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +564 -522
- package/dist/memory/config.d.ts +6 -0
- package/dist/memory/consolidation.d.ts +2 -0
- package/dist/memory/gateway.d.ts +12 -1
- package/dist/memory/index.d.ts +6 -4
- package/dist/memory/jsonl-migration.d.ts +28 -3
- package/dist/memory/local-jsonl-provider.d.ts +16 -1
- package/dist/memory/maintenance.d.ts +5 -0
- package/dist/memory/memory-family-migration.d.ts +12 -0
- package/dist/memory/outcome-events.d.ts +24 -0
- package/dist/memory/provider.d.ts +7 -1
- package/dist/memory/reflection-injection.d.ts +1 -0
- package/dist/memory/reflection-service.d.ts +68 -0
- package/dist/memory/reflection.d.ts +41 -0
- package/dist/memory/schema.d.ts +13 -1
- package/dist/memory/sqlite-provider.d.ts +18 -1
- package/dist/memory/types.d.ts +19 -1
- package/dist/state.d.ts +107 -2
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/manifest.d.ts +1 -0
- package/dist/tools/swarm-memory-outcome.d.ts +11 -0
- package/dist/tools/tool-metadata.d.ts +4 -0
- package/package.json +1 -1
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
readTaskEvidence,
|
|
16
16
|
readTaskEvidenceRaw,
|
|
17
17
|
sanitizeTaskId
|
|
18
|
-
} from "./index-
|
|
18
|
+
} from "./index-d55crzd4.js";
|
|
19
19
|
import {
|
|
20
20
|
LedgerStaleWriterError,
|
|
21
21
|
appendLedgerEvent,
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
replayFromLedgerWithStatus,
|
|
36
36
|
takeSnapshotEvent,
|
|
37
37
|
takeSnapshotWithRetry
|
|
38
|
-
} from "./index-
|
|
38
|
+
} from "./index-g1c5fgaw.js";
|
|
39
39
|
import {
|
|
40
40
|
getWorktreeMergeFailure
|
|
41
41
|
} from "./index-zsrtt42s.js";
|
|
@@ -53,7 +53,7 @@ import {
|
|
|
53
53
|
} from "./index-gprxjmm7.js";
|
|
54
54
|
import {
|
|
55
55
|
PlanSchema
|
|
56
|
-
} from "./index-
|
|
56
|
+
} from "./index-y95nwsge.js";
|
|
57
57
|
import {
|
|
58
58
|
readSwarmFileAsync,
|
|
59
59
|
validateSwarmPath
|
|
@@ -1934,7 +1934,7 @@ var _internals5 = {
|
|
|
1934
1934
|
|
|
1935
1935
|
// src/services/run-memory.ts
|
|
1936
1936
|
import * as crypto2 from "crypto";
|
|
1937
|
-
import * as
|
|
1937
|
+
import * as fs3 from "fs/promises";
|
|
1938
1938
|
|
|
1939
1939
|
// src/hooks/context-sanitizer.ts
|
|
1940
1940
|
function sanitizeContextText(text) {
|
|
@@ -1948,6 +1948,7 @@ function sanitizeContextText(text) {
|
|
|
1948
1948
|
init_logger();
|
|
1949
1949
|
|
|
1950
1950
|
// src/utils/path-security.ts
|
|
1951
|
+
import * as fs2 from "fs";
|
|
1951
1952
|
import * as path5 from "path";
|
|
1952
1953
|
function containsPathTraversal(str) {
|
|
1953
1954
|
if (/\.\.[/\\]/.test(str))
|
|
@@ -1991,6 +1992,23 @@ function containsControlChars(str) {
|
|
|
1991
1992
|
function validateWorkspaceRoot(directory) {
|
|
1992
1993
|
validateProjectDirectory(directory);
|
|
1993
1994
|
}
|
|
1995
|
+
function validateDirectory(directory) {
|
|
1996
|
+
if (!directory || directory.trim() === "") {
|
|
1997
|
+
throw new Error("Invalid directory: empty");
|
|
1998
|
+
}
|
|
1999
|
+
if (containsPathTraversal(directory)) {
|
|
2000
|
+
throw new Error("Invalid directory: path traversal detected");
|
|
2001
|
+
}
|
|
2002
|
+
if (containsControlChars(directory)) {
|
|
2003
|
+
throw new Error("Invalid directory: control characters detected");
|
|
2004
|
+
}
|
|
2005
|
+
if (directory.startsWith("/") || directory.startsWith("\\")) {
|
|
2006
|
+
throw new Error("Invalid directory: absolute path");
|
|
2007
|
+
}
|
|
2008
|
+
if (/^[A-Za-z]:[/\\]/.test(directory)) {
|
|
2009
|
+
throw new Error("Invalid directory: Windows absolute path");
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
1994
2012
|
function validateProjectDirectory(directory) {
|
|
1995
2013
|
if (!directory || directory.trim() === "") {
|
|
1996
2014
|
throw new Error("Invalid project directory: empty");
|
|
@@ -2041,6 +2059,91 @@ function assertNotSystemLocation(directory) {
|
|
|
2041
2059
|
}
|
|
2042
2060
|
}
|
|
2043
2061
|
}
|
|
2062
|
+
function resolveNearestExistingCanonical(inputPath, resolver) {
|
|
2063
|
+
try {
|
|
2064
|
+
return resolver(inputPath);
|
|
2065
|
+
} catch {}
|
|
2066
|
+
const lexicallyResolved = path5.resolve(inputPath);
|
|
2067
|
+
let probe2 = lexicallyResolved;
|
|
2068
|
+
const tail = [];
|
|
2069
|
+
for (let i = 0;i < 4096; i++) {
|
|
2070
|
+
const parent = path5.dirname(probe2);
|
|
2071
|
+
if (parent === probe2) {
|
|
2072
|
+
return lexicallyResolved;
|
|
2073
|
+
}
|
|
2074
|
+
tail.unshift(path5.basename(probe2));
|
|
2075
|
+
probe2 = parent;
|
|
2076
|
+
try {
|
|
2077
|
+
const canonicalAncestor = resolver(probe2);
|
|
2078
|
+
return path5.normalize(path5.join(canonicalAncestor, ...tail));
|
|
2079
|
+
} catch {}
|
|
2080
|
+
}
|
|
2081
|
+
return lexicallyResolved;
|
|
2082
|
+
}
|
|
2083
|
+
function validateSymlinkBoundary(targetPath, rootPath) {
|
|
2084
|
+
const realTarget = resolveNearestExistingCanonical(targetPath, _internals6.realpathSync);
|
|
2085
|
+
const realRoot = resolveNearestExistingCanonical(rootPath, _internals6.realpathSync);
|
|
2086
|
+
const normalizedTarget = path5.normalize(realTarget);
|
|
2087
|
+
const normalizedRoot = path5.normalize(realRoot);
|
|
2088
|
+
if (!normalizedTarget.startsWith(normalizedRoot + path5.sep) && normalizedTarget !== normalizedRoot) {
|
|
2089
|
+
throw new Error(`Symlink resolution escaped boundary: ${realTarget} is not within ${realRoot}`);
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
function isCanonicalPathWithinRoot(targetPath, rootPath) {
|
|
2093
|
+
let canonicalRoot;
|
|
2094
|
+
try {
|
|
2095
|
+
canonicalRoot = fs2.realpathSync(rootPath);
|
|
2096
|
+
} catch {
|
|
2097
|
+
canonicalRoot = path5.normalize(rootPath);
|
|
2098
|
+
}
|
|
2099
|
+
let probe2 = path5.normalize(targetPath);
|
|
2100
|
+
for (let i = 0;i < 4096; i++) {
|
|
2101
|
+
try {
|
|
2102
|
+
const canonicalProbe = fs2.realpathSync(probe2);
|
|
2103
|
+
const relative2 = path5.relative(canonicalRoot, canonicalProbe);
|
|
2104
|
+
return !relative2.startsWith("..") && !path5.isAbsolute(relative2);
|
|
2105
|
+
} catch {
|
|
2106
|
+
const parent = path5.dirname(probe2);
|
|
2107
|
+
if (parent === probe2)
|
|
2108
|
+
return false;
|
|
2109
|
+
probe2 = parent;
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
return false;
|
|
2113
|
+
}
|
|
2114
|
+
function validateTargetWithinRoot(filePath, root) {
|
|
2115
|
+
if (!filePath || filePath.trim() === "") {
|
|
2116
|
+
return "Empty path";
|
|
2117
|
+
}
|
|
2118
|
+
if (path5.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
|
|
2119
|
+
return `Absolute path rejected: ${filePath}`;
|
|
2120
|
+
}
|
|
2121
|
+
if (containsPathTraversal(filePath)) {
|
|
2122
|
+
return `Path traversal detected: ${filePath}`;
|
|
2123
|
+
}
|
|
2124
|
+
if (containsControlChars(filePath)) {
|
|
2125
|
+
return `Control characters detected in path: ${filePath}`;
|
|
2126
|
+
}
|
|
2127
|
+
const resolved = path5.resolve(root, filePath);
|
|
2128
|
+
const relative2 = path5.relative(root, resolved);
|
|
2129
|
+
if (relative2.startsWith("..") || path5.isAbsolute(relative2)) {
|
|
2130
|
+
return `Path escapes root: ${filePath}`;
|
|
2131
|
+
}
|
|
2132
|
+
if (!isCanonicalPathWithinRoot(resolved, root)) {
|
|
2133
|
+
return `Path escapes root via symlink/junction: ${filePath}`;
|
|
2134
|
+
}
|
|
2135
|
+
return null;
|
|
2136
|
+
}
|
|
2137
|
+
var _internals6 = {
|
|
2138
|
+
realpathSync: fs2.realpathSync,
|
|
2139
|
+
containsPathTraversal,
|
|
2140
|
+
containsControlChars,
|
|
2141
|
+
validateDirectory,
|
|
2142
|
+
validateProjectDirectory,
|
|
2143
|
+
validateSymlinkBoundary,
|
|
2144
|
+
isCanonicalPathWithinRoot,
|
|
2145
|
+
validateTargetWithinRoot
|
|
2146
|
+
};
|
|
2044
2147
|
|
|
2045
2148
|
// src/services/run-memory.ts
|
|
2046
2149
|
var RUN_MEMORY_FILENAME = "run-memory.jsonl";
|
|
@@ -2055,7 +2158,7 @@ async function recordOutcome(directory, entry) {
|
|
|
2055
2158
|
const resolvedPath = validateSwarmPath(directory, RUN_MEMORY_FILENAME);
|
|
2056
2159
|
const line = `${JSON.stringify(entry)}
|
|
2057
2160
|
`;
|
|
2058
|
-
await
|
|
2161
|
+
await fs3.appendFile(resolvedPath, line, { encoding: "utf-8" });
|
|
2059
2162
|
}
|
|
2060
2163
|
async function getTaskHistory(directory, taskId) {
|
|
2061
2164
|
validateWorkspaceRoot(directory);
|
|
@@ -2082,14 +2185,14 @@ async function recordTaskAttempt(directory, input) {
|
|
|
2082
2185
|
try {
|
|
2083
2186
|
let history = [];
|
|
2084
2187
|
try {
|
|
2085
|
-
history = await
|
|
2188
|
+
history = await _internals7.getTaskHistory(directory, input.taskId);
|
|
2086
2189
|
} catch (err) {
|
|
2087
2190
|
warn(`[run-memory] history read for task ${input.taskId} failed; recording with attemptNumber 1: ${err instanceof Error ? err.message : String(err)}`);
|
|
2088
2191
|
}
|
|
2089
2192
|
const entry = {
|
|
2090
2193
|
timestamp: new Date().toISOString(),
|
|
2091
2194
|
taskId: input.taskId,
|
|
2092
|
-
taskFingerprint:
|
|
2195
|
+
taskFingerprint: _internals7.generateTaskFingerprint(input.taskId, input.fileTargets ?? []),
|
|
2093
2196
|
agent: input.agent,
|
|
2094
2197
|
outcome: input.outcome,
|
|
2095
2198
|
attemptNumber: history.length + 1
|
|
@@ -2103,7 +2206,7 @@ async function recordTaskAttempt(directory, input) {
|
|
|
2103
2206
|
if (typeof input.durationMs === "number") {
|
|
2104
2207
|
entry.durationMs = input.durationMs;
|
|
2105
2208
|
}
|
|
2106
|
-
await
|
|
2209
|
+
await _internals7.recordOutcome(directory, entry);
|
|
2107
2210
|
} catch (err) {
|
|
2108
2211
|
warn(`[run-memory] failed to record ${input.outcome} for task ${input.taskId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
2109
2212
|
}
|
|
@@ -2167,10 +2270,10 @@ async function getRunMemorySummary(directory) {
|
|
|
2167
2270
|
if (entries.length === 0) {
|
|
2168
2271
|
return null;
|
|
2169
2272
|
}
|
|
2170
|
-
const groups =
|
|
2273
|
+
const groups = _internals7.groupByTaskId(entries);
|
|
2171
2274
|
const summaries = [];
|
|
2172
2275
|
for (const [taskId, taskEntries] of groups) {
|
|
2173
|
-
const summary =
|
|
2276
|
+
const summary = _internals7.summarizeTask(taskId, taskEntries);
|
|
2174
2277
|
if (summary) {
|
|
2175
2278
|
summaries.push(summary);
|
|
2176
2279
|
}
|
|
@@ -2203,7 +2306,7 @@ Use this data to avoid repeating known failure patterns.`;
|
|
|
2203
2306
|
}
|
|
2204
2307
|
return prefix + summaryText + suffix;
|
|
2205
2308
|
}
|
|
2206
|
-
var
|
|
2309
|
+
var _internals7 = {
|
|
2207
2310
|
generateTaskFingerprint,
|
|
2208
2311
|
recordOutcome,
|
|
2209
2312
|
recordTaskAttempt,
|
|
@@ -2215,7 +2318,7 @@ var _internals6 = {
|
|
|
2215
2318
|
|
|
2216
2319
|
// src/turbo/epic/state.ts
|
|
2217
2320
|
init_logger();
|
|
2218
|
-
import * as
|
|
2321
|
+
import * as fs4 from "fs";
|
|
2219
2322
|
import * as path6 from "path";
|
|
2220
2323
|
var STATE_FILE = "epic-state.json";
|
|
2221
2324
|
function nowISO() {
|
|
@@ -2223,8 +2326,8 @@ function nowISO() {
|
|
|
2223
2326
|
}
|
|
2224
2327
|
function ensureSwarmDir(directory) {
|
|
2225
2328
|
const swarmDir = path6.resolve(directory, ".swarm");
|
|
2226
|
-
if (!
|
|
2227
|
-
|
|
2329
|
+
if (!fs4.existsSync(swarmDir)) {
|
|
2330
|
+
fs4.mkdirSync(swarmDir, { recursive: true });
|
|
2228
2331
|
}
|
|
2229
2332
|
return swarmDir;
|
|
2230
2333
|
}
|
|
@@ -2245,16 +2348,16 @@ function markStateUnreadable(directory, reason) {
|
|
|
2245
2348
|
function readPersisted(directory) {
|
|
2246
2349
|
try {
|
|
2247
2350
|
const filePath = path6.join(directory, ".swarm", STATE_FILE);
|
|
2248
|
-
if (!
|
|
2351
|
+
if (!fs4.existsSync(filePath)) {
|
|
2249
2352
|
const seed = emptyPersisted();
|
|
2250
2353
|
try {
|
|
2251
2354
|
ensureSwarmDir(directory);
|
|
2252
|
-
|
|
2355
|
+
fs4.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
2253
2356
|
`, "utf-8");
|
|
2254
2357
|
} catch {}
|
|
2255
2358
|
return seed;
|
|
2256
2359
|
}
|
|
2257
|
-
const raw =
|
|
2360
|
+
const raw = fs4.readFileSync(filePath, "utf-8");
|
|
2258
2361
|
const parsed = JSON.parse(raw);
|
|
2259
2362
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
2260
2363
|
markStateUnreadable(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -2291,14 +2394,14 @@ function writePersisted(directory, persisted) {
|
|
|
2291
2394
|
throw new Error(`Epic state persistence prepare failed: ${msg}`);
|
|
2292
2395
|
}
|
|
2293
2396
|
try {
|
|
2294
|
-
|
|
2295
|
-
|
|
2397
|
+
fs4.writeFileSync(tmpPath, payload, "utf-8");
|
|
2398
|
+
fs4.renameSync(tmpPath, filePath);
|
|
2296
2399
|
} catch (error2) {
|
|
2297
2400
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
2298
2401
|
error(`[turbo/epic/state] Failed to persist ${STATE_FILE} atomically: ${msg}`);
|
|
2299
2402
|
try {
|
|
2300
|
-
if (
|
|
2301
|
-
|
|
2403
|
+
if (fs4.existsSync(tmpPath))
|
|
2404
|
+
fs4.unlinkSync(tmpPath);
|
|
2302
2405
|
} catch {}
|
|
2303
2406
|
throw new Error(`Epic state persistence failed: ${msg}`);
|
|
2304
2407
|
}
|
|
@@ -2329,7 +2432,7 @@ function isEpicModeActive(directory, sessionID) {
|
|
|
2329
2432
|
function isEpicModeActiveForProject(directory) {
|
|
2330
2433
|
if (stateUnreadableMap.get(directory))
|
|
2331
2434
|
return false;
|
|
2332
|
-
if (!
|
|
2435
|
+
if (!fs4.existsSync(path6.join(directory, ".swarm", STATE_FILE))) {
|
|
2333
2436
|
return false;
|
|
2334
2437
|
}
|
|
2335
2438
|
const persisted = readPersisted(directory);
|
|
@@ -2380,11 +2483,11 @@ function isLockContentionError(err) {
|
|
|
2380
2483
|
return INDEX_LOCK_ERROR_RE.test(msg);
|
|
2381
2484
|
}
|
|
2382
2485
|
async function commitTaskCompletion(directory, taskId, description, scopePaths) {
|
|
2383
|
-
if (!
|
|
2486
|
+
if (!_internals8.isGitRepo(directory)) {
|
|
2384
2487
|
return { committed: false, reason: "no-git" };
|
|
2385
2488
|
}
|
|
2386
2489
|
try {
|
|
2387
|
-
if (
|
|
2490
|
+
if (_internals8.hasExistingTaskCommit(directory, taskId)) {
|
|
2388
2491
|
return { committed: true, reason: "idempotent-skip" };
|
|
2389
2492
|
}
|
|
2390
2493
|
} catch {}
|
|
@@ -2405,15 +2508,15 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
|
|
|
2405
2508
|
for (let attempt = 0;attempt <= INDEX_LOCK_BACKOFF_MS.length; attempt++) {
|
|
2406
2509
|
try {
|
|
2407
2510
|
if (paths.length > 0) {
|
|
2408
|
-
|
|
2511
|
+
_internals8.stageScopedPaths(directory, paths);
|
|
2409
2512
|
}
|
|
2410
|
-
|
|
2411
|
-
const sha =
|
|
2513
|
+
_internals8.commitAllowEmpty(directory, message);
|
|
2514
|
+
const sha = _internals8.gitHeadSha(directory);
|
|
2412
2515
|
return { committed: true, reason: "success", sha };
|
|
2413
2516
|
} catch (err) {
|
|
2414
2517
|
lastError = err;
|
|
2415
2518
|
if (attempt < INDEX_LOCK_BACKOFF_MS.length && isLockContentionError(err)) {
|
|
2416
|
-
await
|
|
2519
|
+
await _internals8.sleep(INDEX_LOCK_BACKOFF_MS[attempt]);
|
|
2417
2520
|
continue;
|
|
2418
2521
|
}
|
|
2419
2522
|
break;
|
|
@@ -2423,7 +2526,7 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
|
|
|
2423
2526
|
criticalWarn(`[epic:task-commit] commit for task ${taskId} failed (non-fatal): ${msg}`);
|
|
2424
2527
|
return { committed: false, reason: "commit-failed", error: msg };
|
|
2425
2528
|
}
|
|
2426
|
-
var
|
|
2529
|
+
var _internals8 = {
|
|
2427
2530
|
isGitRepo: (cwd) => isGitRepo(cwd),
|
|
2428
2531
|
stageScopedPaths: (cwd, paths) => {
|
|
2429
2532
|
const CHUNK = 200;
|
|
@@ -2455,7 +2558,7 @@ var _internals7 = {
|
|
|
2455
2558
|
};
|
|
2456
2559
|
|
|
2457
2560
|
// src/turbo/lean/conflicts.ts
|
|
2458
|
-
import * as
|
|
2561
|
+
import * as fs5 from "fs";
|
|
2459
2562
|
import * as path7 from "path";
|
|
2460
2563
|
|
|
2461
2564
|
// src/utils/path.ts
|
|
@@ -2586,10 +2689,10 @@ function isProtectedPath(normalizedPath) {
|
|
|
2586
2689
|
function readTaskScopes(directory, taskId) {
|
|
2587
2690
|
const scopePath = path7.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
|
|
2588
2691
|
try {
|
|
2589
|
-
if (!
|
|
2692
|
+
if (!fs5.existsSync(scopePath)) {
|
|
2590
2693
|
return null;
|
|
2591
2694
|
}
|
|
2592
|
-
const raw =
|
|
2695
|
+
const raw = fs5.readFileSync(scopePath, "utf-8");
|
|
2593
2696
|
const parsed = JSON.parse(raw);
|
|
2594
2697
|
if (!parsed || !Array.isArray(parsed.files)) {
|
|
2595
2698
|
return null;
|
|
@@ -2605,13 +2708,13 @@ import { createHash as createHash3 } from "crypto";
|
|
|
2605
2708
|
import * as fsSync2 from "fs";
|
|
2606
2709
|
import { join as join7 } from "path";
|
|
2607
2710
|
async function computeSpecHash(directory) {
|
|
2608
|
-
const spec =
|
|
2711
|
+
const spec = _internals9.readEffectiveSpecSync(directory);
|
|
2609
2712
|
if (!spec)
|
|
2610
2713
|
return null;
|
|
2611
2714
|
return createHash3("sha256").update(spec.content, "utf-8").digest("hex");
|
|
2612
2715
|
}
|
|
2613
2716
|
async function isSpecStale(directory, plan) {
|
|
2614
|
-
const currentHash = await
|
|
2717
|
+
const currentHash = await _internals9.computeSpecHash(directory);
|
|
2615
2718
|
if (!plan.specHash) {
|
|
2616
2719
|
return { stale: false };
|
|
2617
2720
|
}
|
|
@@ -2640,7 +2743,7 @@ function isObligationPreserving(directory) {
|
|
|
2640
2743
|
} catch {
|
|
2641
2744
|
return false;
|
|
2642
2745
|
}
|
|
2643
|
-
const currentResult =
|
|
2746
|
+
const currentResult = _internals9.readEffectiveSpecSync(directory);
|
|
2644
2747
|
if (!currentResult || !currentResult.content) {
|
|
2645
2748
|
return false;
|
|
2646
2749
|
}
|
|
@@ -2670,7 +2773,7 @@ function isObligationPreserving(directory) {
|
|
|
2670
2773
|
return false;
|
|
2671
2774
|
}
|
|
2672
2775
|
}
|
|
2673
|
-
var
|
|
2776
|
+
var _internals9 = {
|
|
2674
2777
|
computeSpecDiff,
|
|
2675
2778
|
computeSpecHash,
|
|
2676
2779
|
isObligationPreserving,
|
|
@@ -2690,7 +2793,7 @@ function computeSpecDiff(directory) {
|
|
|
2690
2793
|
} catch {
|
|
2691
2794
|
return null;
|
|
2692
2795
|
}
|
|
2693
|
-
const spec =
|
|
2796
|
+
const spec = _internals9.readEffectiveSpecSync(directory);
|
|
2694
2797
|
if (!spec) {
|
|
2695
2798
|
return null;
|
|
2696
2799
|
}
|
|
@@ -2784,7 +2887,7 @@ var startupLedgerCheckedWorkspaces = new Set;
|
|
|
2784
2887
|
var ledgerStaleWorkspaces = new Set;
|
|
2785
2888
|
var recoveryMutexes = new Map;
|
|
2786
2889
|
var PLAN_JSON_CACHE_NAMESPACE = "plan-json:validated:v1";
|
|
2787
|
-
var
|
|
2890
|
+
var _internals10 = {
|
|
2788
2891
|
loadPlan,
|
|
2789
2892
|
loadPlanJsonOnly,
|
|
2790
2893
|
regeneratePlanMarkdown,
|
|
@@ -3037,7 +3140,7 @@ async function loadPlan(directory, cache) {
|
|
|
3037
3140
|
const inSync = await isPlanMdInSync(directory, validated, cache);
|
|
3038
3141
|
if (!inSync) {
|
|
3039
3142
|
try {
|
|
3040
|
-
await
|
|
3143
|
+
await _internals10.regeneratePlanMarkdown(directory, validated);
|
|
3041
3144
|
} catch (regenError) {
|
|
3042
3145
|
warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
|
|
3043
3146
|
}
|
|
@@ -3206,7 +3309,7 @@ async function loadPlan(directory, cache) {
|
|
|
3206
3309
|
const existingMutex = recoveryMutexes.get(resolvedDir);
|
|
3207
3310
|
if (existingMutex) {
|
|
3208
3311
|
await existingMutex;
|
|
3209
|
-
const postRecoveryPlan = await
|
|
3312
|
+
const postRecoveryPlan = await _internals10.loadPlanJsonOnly(directory);
|
|
3210
3313
|
if (postRecoveryPlan)
|
|
3211
3314
|
return postRecoveryPlan;
|
|
3212
3315
|
}
|
|
@@ -3266,7 +3369,7 @@ async function loadPlan(directory, cache) {
|
|
|
3266
3369
|
return null;
|
|
3267
3370
|
}
|
|
3268
3371
|
async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
|
|
3269
|
-
const existing = await
|
|
3372
|
+
const existing = await _internals10.loadPlanJsonOnly(directory);
|
|
3270
3373
|
const newIds = new Set;
|
|
3271
3374
|
for (const phase of plan.phases) {
|
|
3272
3375
|
for (const task of phase.tasks)
|
|
@@ -3316,7 +3419,7 @@ async function savePlan(directory, plan, options) {
|
|
|
3316
3419
|
}
|
|
3317
3420
|
if (options?.preserveCompletedStatuses !== false) {
|
|
3318
3421
|
try {
|
|
3319
|
-
const currentPlan2 = await
|
|
3422
|
+
const currentPlan2 = await _internals10.loadPlanJsonOnly(directory);
|
|
3320
3423
|
if (currentPlan2) {
|
|
3321
3424
|
const completedTaskIds = new Set;
|
|
3322
3425
|
for (const phase of currentPlan2.phases) {
|
|
@@ -3338,7 +3441,7 @@ async function savePlan(directory, plan, options) {
|
|
|
3338
3441
|
} catch {}
|
|
3339
3442
|
}
|
|
3340
3443
|
derivePhaseStatusesInPlace(validated);
|
|
3341
|
-
const currentPlan = await
|
|
3444
|
+
const currentPlan = await _internals10.loadPlanJsonOnly(directory);
|
|
3342
3445
|
const planId = derivePlanId(validated);
|
|
3343
3446
|
const planHashForInit = computePlanHash(validated);
|
|
3344
3447
|
if (!await ledgerExists(directory)) {
|
|
@@ -3520,7 +3623,7 @@ async function savePlan(directory, plan, options) {
|
|
|
3520
3623
|
expectedHash: currentHash,
|
|
3521
3624
|
planHashAfter: hashAfter,
|
|
3522
3625
|
verifyValid: async () => {
|
|
3523
|
-
const onDisk = await
|
|
3626
|
+
const onDisk = await _internals10.loadPlanJsonOnly(directory);
|
|
3524
3627
|
if (!onDisk)
|
|
3525
3628
|
return true;
|
|
3526
3629
|
for (const p of onDisk.phases) {
|
|
@@ -3558,7 +3661,7 @@ async function savePlan(directory, plan, options) {
|
|
|
3558
3661
|
expectedHash: currentHash,
|
|
3559
3662
|
planHashAfter: hashAfter,
|
|
3560
3663
|
verifyValid: async () => {
|
|
3561
|
-
const onDisk = await
|
|
3664
|
+
const onDisk = await _internals10.loadPlanJsonOnly(directory);
|
|
3562
3665
|
if (!onDisk)
|
|
3563
3666
|
return true;
|
|
3564
3667
|
for (const p of onDisk.phases) {
|
|
@@ -3856,7 +3959,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3856
3959
|
return "pending";
|
|
3857
3960
|
};
|
|
3858
3961
|
{
|
|
3859
|
-
const currentPlan = await
|
|
3962
|
+
const currentPlan = await _internals10.loadPlanJsonOnly(directory);
|
|
3860
3963
|
if (currentPlan) {
|
|
3861
3964
|
const currentTask = currentPlan.phases.flatMap((p) => p.tasks).find((t) => t.id === taskId);
|
|
3862
3965
|
const settled = currentTask && currentTask.status !== "pending" && currentTask.status !== "in_progress";
|
|
@@ -3869,7 +3972,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3869
3972
|
}
|
|
3870
3973
|
const MAX_OUTER_RETRIES = 1;
|
|
3871
3974
|
for (let attempt = 0;attempt <= MAX_OUTER_RETRIES; attempt++) {
|
|
3872
|
-
const plan = await
|
|
3975
|
+
const plan = await _internals10.loadPlan(directory);
|
|
3873
3976
|
if (plan === null) {
|
|
3874
3977
|
throw new Error(`Plan not found in directory: ${directory}`);
|
|
3875
3978
|
}
|
|
@@ -3900,7 +4003,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3900
4003
|
if (status === "completed" || status === "blocked") {
|
|
3901
4004
|
const recordedTask = updatedPlan.phases.flatMap((phase) => phase.tasks).find((candidate) => candidate.id === taskId);
|
|
3902
4005
|
try {
|
|
3903
|
-
await
|
|
4006
|
+
await _internals10.recordTaskAttempt(directory, {
|
|
3904
4007
|
taskId,
|
|
3905
4008
|
agent: "plan-status",
|
|
3906
4009
|
outcome: status === "completed" ? "pass" : "fail",
|
|
@@ -3911,8 +4014,8 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3911
4014
|
warn(`[plan/manager] run-memory record for ${taskId} failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
3912
4015
|
}
|
|
3913
4016
|
}
|
|
3914
|
-
if (status === "completed" &&
|
|
3915
|
-
const mergeFailure =
|
|
4017
|
+
if (status === "completed" && _internals10.isGitRepo(directory) && _internals10.isEpicModeActiveForProject(directory)) {
|
|
4018
|
+
const mergeFailure = _internals10.getWorktreeMergeFailure(taskId);
|
|
3916
4019
|
if (mergeFailure) {
|
|
3917
4020
|
criticalWarn(`[plan/manager] Rule 2 auto-commit SKIPPED for ${taskId}: worktree merge-back ${mergeFailure.outcome} at stage '${mergeFailure.stage}'. The task's changes are NOT in the main tree, so no completion marker is written (Rule 3 must not treat this task as satisfied). Resolve the preserved worktree, then re-run the task. Detail: ${mergeFailure.message}`);
|
|
3918
4021
|
return updatedPlan;
|
|
@@ -3926,8 +4029,8 @@ async function updateTaskStatus(directory, taskId, status, options) {
|
|
|
3926
4029
|
break;
|
|
3927
4030
|
}
|
|
3928
4031
|
}
|
|
3929
|
-
const canonicalScope =
|
|
3930
|
-
await
|
|
4032
|
+
const canonicalScope = _internals10.readTaskScopes(directory, taskId);
|
|
4033
|
+
await _internals10.commitTaskCompletion(directory, taskId, taskDescription, canonicalScope ?? undefined);
|
|
3931
4034
|
} catch (commitErr) {
|
|
3932
4035
|
criticalWarn(`[plan/manager] Rule 2 auto-commit for ${taskId} threw (non-fatal): ${commitErr instanceof Error ? commitErr.message : String(commitErr)}`);
|
|
3933
4036
|
}
|
|
@@ -4242,16 +4345,16 @@ init_zod();
|
|
|
4242
4345
|
import {
|
|
4243
4346
|
mkdirSync as mkdirSync5,
|
|
4244
4347
|
readdirSync as readdirSync2,
|
|
4245
|
-
realpathSync,
|
|
4348
|
+
realpathSync as realpathSync2,
|
|
4246
4349
|
renameSync as renameSync3,
|
|
4247
4350
|
rmSync,
|
|
4248
4351
|
statSync as statSync2
|
|
4249
4352
|
} from "fs";
|
|
4250
|
-
import * as
|
|
4353
|
+
import * as fs8 from "fs/promises";
|
|
4251
4354
|
import * as path10 from "path";
|
|
4252
4355
|
|
|
4253
4356
|
// src/evaluation/retention.ts
|
|
4254
|
-
import * as
|
|
4357
|
+
import * as fs6 from "fs/promises";
|
|
4255
4358
|
import * as path9 from "path";
|
|
4256
4359
|
function artifactKey(artifact) {
|
|
4257
4360
|
return `${artifact.namespace}/${artifact.id}`;
|
|
@@ -4263,7 +4366,7 @@ async function evaluationRunCandidates(directory) {
|
|
|
4263
4366
|
const root = path9.join(directory, ".swarm", "evolution", "runs");
|
|
4264
4367
|
let entries = [];
|
|
4265
4368
|
try {
|
|
4266
|
-
entries = await
|
|
4369
|
+
entries = await fs6.readdir(root, { withFileTypes: true });
|
|
4267
4370
|
} catch (error2) {
|
|
4268
4371
|
if (error2.code === "ENOENT") {
|
|
4269
4372
|
return { candidates: [], corrupt: [] };
|
|
@@ -4281,7 +4384,7 @@ async function evaluationRunCandidates(directory) {
|
|
|
4281
4384
|
const artifact = { namespace: "evaluation-run", id };
|
|
4282
4385
|
const target = path9.join(root, entry.name);
|
|
4283
4386
|
try {
|
|
4284
|
-
const run = EvaluationRunV1Schema.parse(JSON.parse(await
|
|
4387
|
+
const run = EvaluationRunV1Schema.parse(JSON.parse(await fs6.readFile(target, "utf8")));
|
|
4285
4388
|
if (run.runId !== id)
|
|
4286
4389
|
throw new Error("run id/path mismatch");
|
|
4287
4390
|
candidates.push({
|
|
@@ -4300,7 +4403,7 @@ async function gateAuditCandidates(directory) {
|
|
|
4300
4403
|
const root = path9.join(directory, ".swarm", "evidence", "gate-audit");
|
|
4301
4404
|
let entries = [];
|
|
4302
4405
|
try {
|
|
4303
|
-
entries = await
|
|
4406
|
+
entries = await fs6.readdir(root, { withFileTypes: true });
|
|
4304
4407
|
} catch (error2) {
|
|
4305
4408
|
if (error2.code === "ENOENT") {
|
|
4306
4409
|
return { candidates: [], corrupt: [] };
|
|
@@ -4315,7 +4418,7 @@ async function gateAuditCandidates(directory) {
|
|
|
4315
4418
|
const artifact = { namespace: "gate-audit", id: entry.name };
|
|
4316
4419
|
const target = path9.join(root, entry.name);
|
|
4317
4420
|
try {
|
|
4318
|
-
const result = GateAuditResultV1Schema.parse(JSON.parse(await
|
|
4421
|
+
const result = GateAuditResultV1Schema.parse(JSON.parse(await fs6.readFile(path9.join(target, "results.json"), "utf8")));
|
|
4319
4422
|
if (result.runId !== entry.name)
|
|
4320
4423
|
throw new Error("run id/path mismatch");
|
|
4321
4424
|
candidates.push({
|
|
@@ -4346,10 +4449,10 @@ async function protectedArtifacts(directory) {
|
|
|
4346
4449
|
}
|
|
4347
4450
|
async function removeCandidate(candidate) {
|
|
4348
4451
|
if (candidate.kind === "directory") {
|
|
4349
|
-
await
|
|
4452
|
+
await fs6.rm(candidate.target, { recursive: true, force: true });
|
|
4350
4453
|
return;
|
|
4351
4454
|
}
|
|
4352
|
-
await
|
|
4455
|
+
await fs6.unlink(candidate.target);
|
|
4353
4456
|
}
|
|
4354
4457
|
var _retentionInternals = {
|
|
4355
4458
|
protectedArtifacts,
|
|
@@ -4406,7 +4509,7 @@ async function archiveEvaluationArtifacts(args) {
|
|
|
4406
4509
|
}
|
|
4407
4510
|
|
|
4408
4511
|
// src/evidence/documents-retention.ts
|
|
4409
|
-
import * as
|
|
4512
|
+
import * as fs7 from "fs";
|
|
4410
4513
|
import * as fsp from "fs/promises";
|
|
4411
4514
|
import * as readline from "readline";
|
|
4412
4515
|
var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
|
|
@@ -4414,13 +4517,13 @@ var MAX_READ_BYTES = 100 * 1024 * 1024;
|
|
|
4414
4517
|
var RENAME_MAX_ATTEMPTS = 5;
|
|
4415
4518
|
var RENAME_BACKOFF_MS = 10;
|
|
4416
4519
|
var RENAME_RETRY_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY", "EACCES"]);
|
|
4417
|
-
var
|
|
4520
|
+
var _internals11 = {
|
|
4418
4521
|
stat: (p) => fsp.stat(p),
|
|
4419
|
-
createReadStream: (p, options) =>
|
|
4420
|
-
openSync: (p, flags) =>
|
|
4421
|
-
writeSync: (fd, data, position) =>
|
|
4422
|
-
fsyncSync: (fd) =>
|
|
4423
|
-
closeSync: (fd) =>
|
|
4522
|
+
createReadStream: (p, options) => fs7.createReadStream(p, options),
|
|
4523
|
+
openSync: (p, flags) => fs7.openSync(p, flags),
|
|
4524
|
+
writeSync: (fd, data, position) => fs7.writeSync(fd, data, position),
|
|
4525
|
+
fsyncSync: (fd) => fs7.fsyncSync(fd),
|
|
4526
|
+
closeSync: (fd) => fs7.closeSync(fd),
|
|
4424
4527
|
renameWithRetry: atomicRenameWithRetry,
|
|
4425
4528
|
unlink: (p) => fsp.unlink(p)
|
|
4426
4529
|
};
|
|
@@ -4456,9 +4559,9 @@ function emptyResult(dryRun) {
|
|
|
4456
4559
|
};
|
|
4457
4560
|
}
|
|
4458
4561
|
async function readCacheRows(filePath) {
|
|
4459
|
-
const stat2 = await
|
|
4562
|
+
const stat2 = await _internals11.stat(filePath);
|
|
4460
4563
|
const bytesBefore = stat2.size;
|
|
4461
|
-
const stream =
|
|
4564
|
+
const stream = _internals11.createReadStream(filePath, {
|
|
4462
4565
|
encoding: "utf8",
|
|
4463
4566
|
highWaterMark: 64 * 1024
|
|
4464
4567
|
});
|
|
@@ -4534,23 +4637,23 @@ async function rewriteAtomic(filePath, survivors) {
|
|
|
4534
4637
|
`)}
|
|
4535
4638
|
` : "";
|
|
4536
4639
|
let succeeded = false;
|
|
4537
|
-
const fd =
|
|
4640
|
+
const fd = _internals11.openSync(tmpPath, "w");
|
|
4538
4641
|
try {
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
await
|
|
4642
|
+
_internals11.writeSync(fd, payload, 0);
|
|
4643
|
+
_internals11.fsyncSync(fd);
|
|
4644
|
+
_internals11.closeSync(fd);
|
|
4645
|
+
await _internals11.renameWithRetry(tmpPath, filePath);
|
|
4543
4646
|
succeeded = true;
|
|
4544
4647
|
} catch (err) {
|
|
4545
4648
|
try {
|
|
4546
|
-
|
|
4649
|
+
_internals11.closeSync(fd);
|
|
4547
4650
|
} catch {}
|
|
4548
4651
|
const msg = err instanceof Error ? err.message : String(err);
|
|
4549
4652
|
throw new Error(`documents-cache rewrite failed: ${msg}`);
|
|
4550
4653
|
} finally {
|
|
4551
4654
|
if (!succeeded) {
|
|
4552
4655
|
try {
|
|
4553
|
-
await
|
|
4656
|
+
await _internals11.unlink(tmpPath);
|
|
4554
4657
|
} catch {}
|
|
4555
4658
|
}
|
|
4556
4659
|
}
|
|
@@ -4563,7 +4666,7 @@ async function pruneEvidenceDocuments(args) {
|
|
|
4563
4666
|
const filePath = validateSwarmPath(args.directory, EVIDENCE_CACHE_FILE);
|
|
4564
4667
|
let stat2;
|
|
4565
4668
|
try {
|
|
4566
|
-
stat2 = await
|
|
4669
|
+
stat2 = await _internals11.stat(filePath);
|
|
4567
4670
|
} catch (err) {
|
|
4568
4671
|
const code = err?.code;
|
|
4569
4672
|
if (code === "ENOENT")
|
|
@@ -4664,17 +4767,17 @@ function isValidEvidenceType(type) {
|
|
|
4664
4767
|
var sanitizeTaskId2 = sanitizeTaskId;
|
|
4665
4768
|
function validateProjectRoot(directory) {
|
|
4666
4769
|
assertProjectRoot(directory, {
|
|
4667
|
-
realpathSync:
|
|
4668
|
-
statSync:
|
|
4770
|
+
realpathSync: _internals12.realpathSync,
|
|
4771
|
+
statSync: _internals12.statSync
|
|
4669
4772
|
}, "evidence");
|
|
4670
4773
|
}
|
|
4671
4774
|
async function saveEvidence(directory, taskId, evidence, abortSignal) {
|
|
4672
4775
|
abortSignal?.throwIfAborted();
|
|
4673
|
-
|
|
4776
|
+
_internals12.validateProjectRoot(directory);
|
|
4674
4777
|
const sanitizedTaskId = sanitizeTaskId2(taskId);
|
|
4675
4778
|
const relativePath = path10.join("evidence", sanitizedTaskId, "evidence.json");
|
|
4676
4779
|
validateSwarmPath(directory, relativePath);
|
|
4677
|
-
|
|
4780
|
+
_internals12.validateEvidence(evidence);
|
|
4678
4781
|
return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
|
|
4679
4782
|
abortSignal?.throwIfAborted();
|
|
4680
4783
|
const evidencePath = validateSwarmPath(directory, relativePath);
|
|
@@ -4784,7 +4887,7 @@ async function loadEvidence(directory, taskId, options) {
|
|
|
4784
4887
|
return { status: "invalid_schema", errors: ["Invalid JSON"] };
|
|
4785
4888
|
}
|
|
4786
4889
|
if (isFlatRetrospective(parsed)) {
|
|
4787
|
-
const wrappedBundle =
|
|
4890
|
+
const wrappedBundle = _internals12.wrapFlatRetrospective(parsed, sanitizedTaskId);
|
|
4788
4891
|
try {
|
|
4789
4892
|
const validated = EvidenceBundleSchema.parse(wrappedBundle);
|
|
4790
4893
|
if (options?.migrate === false) {
|
|
@@ -4798,7 +4901,7 @@ async function loadEvidence(directory, taskId, options) {
|
|
|
4798
4901
|
const tempPath = path10.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
|
|
4799
4902
|
try {
|
|
4800
4903
|
await bunWrite(tempPath, bundleJson);
|
|
4801
|
-
await
|
|
4904
|
+
await fs8.rename(tempPath, evidencePath);
|
|
4802
4905
|
invalidateCachedArtifact(evidencePath);
|
|
4803
4906
|
} catch (writeError) {
|
|
4804
4907
|
try {
|
|
@@ -4883,15 +4986,15 @@ async function checkRequirementCoverage(phase, directory) {
|
|
|
4883
4986
|
const relativePath = path10.join("evidence", `req-coverage-phase-${phase}.json`);
|
|
4884
4987
|
const absolutePath = path10.resolve(directory, ".swarm", relativePath);
|
|
4885
4988
|
try {
|
|
4886
|
-
await
|
|
4989
|
+
await fs8.access(absolutePath);
|
|
4887
4990
|
return { exists: true, path: absolutePath };
|
|
4888
4991
|
} catch {
|
|
4889
4992
|
return { exists: false, path: absolutePath };
|
|
4890
4993
|
}
|
|
4891
4994
|
}
|
|
4892
4995
|
async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
4893
|
-
const taskIds = await
|
|
4894
|
-
const cutoffDate = options?.now ? new Date(options.now) :
|
|
4996
|
+
const taskIds = await _internals12.listEvidenceTaskIds(directory);
|
|
4997
|
+
const cutoffDate = options?.now ? new Date(options.now) : _internals12.now();
|
|
4895
4998
|
cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
|
|
4896
4999
|
const cutoffIso = cutoffDate.toISOString();
|
|
4897
5000
|
const selected = new Set;
|
|
@@ -4903,7 +5006,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
|
4903
5006
|
for (const taskId of taskIds) {
|
|
4904
5007
|
let result;
|
|
4905
5008
|
try {
|
|
4906
|
-
result = await
|
|
5009
|
+
result = await _internals12.loadEvidence(directory, taskId);
|
|
4907
5010
|
} catch {
|
|
4908
5011
|
warn("archive: skipping corrupt or unreadable evidence for task", taskId);
|
|
4909
5012
|
continue;
|
|
@@ -4931,7 +5034,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
|
4931
5034
|
}
|
|
4932
5035
|
if (!options?.dryRun) {
|
|
4933
5036
|
for (const taskId of [...selected].sort()) {
|
|
4934
|
-
const deleted = await
|
|
5037
|
+
const deleted = await _internals12.deleteEvidence(directory, taskId);
|
|
4935
5038
|
if (deleted)
|
|
4936
5039
|
archived.push(taskId);
|
|
4937
5040
|
else
|
|
@@ -4957,7 +5060,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
|
4957
5060
|
};
|
|
4958
5061
|
if (typeof options?.cacheMaxBytes === "number" && options.cacheMaxBytes > 0 || typeof options?.cacheMaxRecords === "number" && options.cacheMaxRecords > 0) {
|
|
4959
5062
|
try {
|
|
4960
|
-
documentsCache = await
|
|
5063
|
+
documentsCache = await _internals12.pruneEvidenceDocuments({
|
|
4961
5064
|
directory,
|
|
4962
5065
|
maxBytes: options?.cacheMaxBytes,
|
|
4963
5066
|
maxRecords: options?.cacheMaxRecords,
|
|
@@ -4985,7 +5088,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
|
|
|
4985
5088
|
function validateEvidence(evidence) {
|
|
4986
5089
|
return EvidenceSchema.parse(evidence);
|
|
4987
5090
|
}
|
|
4988
|
-
var
|
|
5091
|
+
var _internals12 = {
|
|
4989
5092
|
wrapFlatRetrospective,
|
|
4990
5093
|
loadEvidence,
|
|
4991
5094
|
listEvidenceTaskIds,
|
|
@@ -4994,7 +5097,7 @@ var _internals11 = {
|
|
|
4994
5097
|
saveEvidence,
|
|
4995
5098
|
deleteEvidence,
|
|
4996
5099
|
pruneEvidenceDocuments,
|
|
4997
|
-
realpathSync,
|
|
5100
|
+
realpathSync: realpathSync2,
|
|
4998
5101
|
statSync: statSync2,
|
|
4999
5102
|
now: () => new Date
|
|
5000
5103
|
};
|
|
@@ -5109,4 +5212,4 @@ function mergeDurableGateEntriesFromEvidence(taskId, entries, evidence) {
|
|
|
5109
5212
|
return merged;
|
|
5110
5213
|
}
|
|
5111
5214
|
|
|
5112
|
-
export { projectDbExists, getProjectDb, closeProjectDb, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, isValidEnvKey, getExecutor, init_executor, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, containsPathTraversal, containsControlChars, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, normalizePath, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };
|
|
5215
|
+
export { projectDbExists, getProjectDb, closeProjectDb, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, isValidEnvKey, getExecutor, init_executor, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, containsPathTraversal, containsControlChars, validateSymlinkBoundary, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, normalizePath, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };
|