opencode-swarm 7.98.1 → 7.99.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/README.md +1 -0
- package/dist/cli/{config-doctor-7yrxfa6b.js → config-doctor-9fhfy6p7.js} +2 -2
- package/dist/cli/{evidence-summary-service-g4x5e3e3.js → evidence-summary-service-4hs44n2c.js} +6 -6
- package/dist/cli/{gate-evidence-nphg8hay.js → gate-evidence-ywys9vfs.js} +4 -4
- package/dist/cli/guardrail-explain-ktm6szbm.js +30 -0
- package/dist/cli/{guardrail-log-53z1cf46.js → guardrail-log-ya49kpwn.js} +3 -3
- package/dist/cli/{index-91qtsbce.js → index-3naa2ajc.js} +1 -1
- package/dist/cli/{index-attgb1ma.js → index-4pt2py5p.js} +17 -15
- package/dist/cli/{index-sf08zj91.js → index-5fxjagjt.js} +2 -2
- package/dist/cli/{index-471qxz9g.js → index-7hnwnw5g.js} +11 -1
- package/dist/cli/{index-kv4dd5c5.js → index-9b7qp18e.js} +1 -1
- package/dist/cli/{index-hb10a2g8.js → index-f7nma02k.js} +2 -2
- package/dist/cli/{index-0rgde8qc.js → index-ft4gehk1.js} +2 -2
- package/dist/cli/{index-gnd1280x.js → index-h9ptj4b1.js} +1 -1
- package/dist/cli/{index-zgba613y.js → index-hw8r3e5p.js} +1108 -792
- package/dist/cli/{index-mh1ej70w.js → index-r8f89sm9.js} +2 -2
- package/dist/cli/{index-zy22fg5h.js → index-svf2zjxs.js} +5 -1
- package/dist/cli/{index-xchgryg4.js → index-vn263hqt.js} +16 -2
- package/dist/cli/{index-fjxjb66n.js → index-vwyjkzgs.js} +3 -3
- package/dist/cli/{index-gn8n22th.js → index-we94wkty.js} +19 -3
- package/dist/cli/{index-4c5jpmn9.js → index-wwnjw0fb.js} +11 -11
- package/dist/cli/{index-5z2e78tv.js → index-xsswhy6k.js} +1 -1
- package/dist/cli/index.js +13 -13
- package/dist/cli/{knowledge-store-pa58msy5.js → knowledge-store-tsa8ezka.js} +4 -4
- package/dist/cli/{pending-delegations-shqbvfjc.js → pending-delegations-c785p5n2.js} +3 -3
- package/dist/cli/{pr-subscriptions-2565fpsc.js → pr-subscriptions-fqrzm0tv.js} +4 -4
- package/dist/cli/{schema-mygkbbe9.js → schema-nz638xc3.js} +5 -1
- package/dist/cli/{skill-generator-3tkwcg4x.js → skill-generator-99rrfwae.js} +5 -5
- package/dist/cli/{telemetry-aa1ma1dr.js → telemetry-jm7t8031.js} +1 -1
- package/dist/commands/close.d.ts +2 -1
- package/dist/commands/costs.d.ts +4 -0
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/registry.d.ts +9 -2
- package/dist/config/evidence-schema.d.ts +44 -44
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +24 -0
- package/dist/hooks/system-enhancer.d.ts +1 -1
- package/dist/hooks/utils.d.ts +3 -1
- package/dist/index.js +2978 -2337
- package/dist/plan/manager.d.ts +1 -1
- package/dist/services/cost-accounting.d.ts +65 -0
- package/dist/state.d.ts +3 -3
- package/dist/telemetry.d.ts +2 -1
- package/package.json +1 -1
- package/dist/cli/guardrail-explain-cm08h4mt.js +0 -30
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
validateActionability,
|
|
24
24
|
validateActionableFields,
|
|
25
25
|
validateLesson
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-vwyjkzgs.js";
|
|
27
27
|
import {
|
|
28
28
|
appendKnowledge,
|
|
29
29
|
appendRejectedLesson,
|
|
@@ -51,13 +51,13 @@ import {
|
|
|
51
51
|
transactFile,
|
|
52
52
|
transactKnowledge,
|
|
53
53
|
writeLinkPointer
|
|
54
|
-
} from "./index-
|
|
54
|
+
} from "./index-f7nma02k.js";
|
|
55
55
|
import {
|
|
56
56
|
detectStraySwarmDirs,
|
|
57
57
|
readDoctorArtifact,
|
|
58
58
|
removeStraySwarmDir,
|
|
59
59
|
runConfigDoctor
|
|
60
|
-
} from "./index-
|
|
60
|
+
} from "./index-svf2zjxs.js";
|
|
61
61
|
import {
|
|
62
62
|
AGENT_TOOL_MAP,
|
|
63
63
|
ALL_SUBAGENT_NAMES,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
TOOL_NAME_SET,
|
|
71
71
|
resolveExternalSkillsConfig,
|
|
72
72
|
stripKnownSwarmPrefix
|
|
73
|
-
} from "./index-
|
|
73
|
+
} from "./index-7hnwnw5g.js";
|
|
74
74
|
import {
|
|
75
75
|
MAX_TRANSIENT_RETRIES,
|
|
76
76
|
PlanSchema,
|
|
@@ -114,7 +114,7 @@ import {
|
|
|
114
114
|
transientBackoff,
|
|
115
115
|
validateProjectRoot,
|
|
116
116
|
writeProjectedSpecSync
|
|
117
|
-
} from "./index-
|
|
117
|
+
} from "./index-wwnjw0fb.js";
|
|
118
118
|
import {
|
|
119
119
|
_internals as _internals2,
|
|
120
120
|
_internals1 as _internals3,
|
|
@@ -132,18 +132,18 @@ import {
|
|
|
132
132
|
} from "./index-v4fcn4tr.js";
|
|
133
133
|
import {
|
|
134
134
|
atomicWriteFile
|
|
135
|
-
} from "./index-
|
|
135
|
+
} from "./index-9b7qp18e.js";
|
|
136
136
|
import {
|
|
137
137
|
buildCorrelationId,
|
|
138
138
|
listActive,
|
|
139
139
|
subscribe,
|
|
140
140
|
unsubscribe
|
|
141
|
-
} from "./index-
|
|
141
|
+
} from "./index-5fxjagjt.js";
|
|
142
142
|
import {
|
|
143
143
|
readSwarmFileAsync,
|
|
144
144
|
safeHook,
|
|
145
145
|
validateSwarmPath
|
|
146
|
-
} from "./index-
|
|
146
|
+
} from "./index-we94wkty.js";
|
|
147
147
|
import {
|
|
148
148
|
deepMerge
|
|
149
149
|
} from "./index-p0arc26j.js";
|
|
@@ -156,7 +156,7 @@ import {
|
|
|
156
156
|
import {
|
|
157
157
|
require_proper_lockfile,
|
|
158
158
|
tryAcquireLock
|
|
159
|
-
} from "./index-
|
|
159
|
+
} from "./index-3naa2ajc.js";
|
|
160
160
|
import {
|
|
161
161
|
exports_external
|
|
162
162
|
} from "./index-293f68mj.js";
|
|
@@ -166,7 +166,7 @@ import {
|
|
|
166
166
|
} from "./index-b9v501fr.js";
|
|
167
167
|
import {
|
|
168
168
|
telemetry
|
|
169
|
-
} from "./index-
|
|
169
|
+
} from "./index-vn263hqt.js";
|
|
170
170
|
import {
|
|
171
171
|
__esm,
|
|
172
172
|
__export,
|
|
@@ -909,7 +909,7 @@ var init_executor = __esm(() => {
|
|
|
909
909
|
// package.json
|
|
910
910
|
var package_default = {
|
|
911
911
|
name: "opencode-swarm",
|
|
912
|
-
version: "7.
|
|
912
|
+
version: "7.99.0",
|
|
913
913
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
914
914
|
main: "dist/index.js",
|
|
915
915
|
types: "dist/index.d.ts",
|
|
@@ -3624,15 +3624,30 @@ function classifySwarmCommandToolUse(resolved) {
|
|
|
3624
3624
|
}
|
|
3625
3625
|
}
|
|
3626
3626
|
if (canonicalKey === "benchmark") {
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3627
|
+
for (let i = 0;i < args.length; i++) {
|
|
3628
|
+
const arg = args[i];
|
|
3629
|
+
if (arg === "--cumulative" || arg === "--ci-gate")
|
|
3630
|
+
continue;
|
|
3631
|
+
if (arg === "--max-cost-usd" && i + 1 < args.length && /^\d+(\.\d+)?$/.test(args[i + 1])) {
|
|
3632
|
+
i++;
|
|
3633
|
+
continue;
|
|
3634
|
+
}
|
|
3630
3635
|
return {
|
|
3631
3636
|
allowed: false,
|
|
3632
|
-
message: "Only `--cumulative
|
|
3637
|
+
message: "Only `--cumulative`, `--ci-gate`, and `--max-cost-usd <n>` are supported for `/swarm benchmark` through swarm_command."
|
|
3633
3638
|
};
|
|
3634
3639
|
}
|
|
3635
3640
|
}
|
|
3641
|
+
if (canonicalKey === "costs") {
|
|
3642
|
+
if (args.length === 0)
|
|
3643
|
+
return { allowed: true };
|
|
3644
|
+
if (args.length === 1 && args[0] === "--json")
|
|
3645
|
+
return { allowed: true };
|
|
3646
|
+
return {
|
|
3647
|
+
allowed: false,
|
|
3648
|
+
message: "Usage through swarm_command: `/swarm costs` or `/swarm costs --json`."
|
|
3649
|
+
};
|
|
3650
|
+
}
|
|
3636
3651
|
if (canonicalKey === "show-plan") {
|
|
3637
3652
|
if (args.length > 1 || args[0] && !/^\d+$/.test(args[0])) {
|
|
3638
3653
|
return {
|
|
@@ -5474,6 +5489,9 @@ function startAgentSession(sessionId, agentName, staleDurationMs = 7200000, dire
|
|
|
5474
5489
|
swarmState.pendingRehydrations.add(rehydrationPromise);
|
|
5475
5490
|
}
|
|
5476
5491
|
}
|
|
5492
|
+
function endAgentSession(sessionId) {
|
|
5493
|
+
swarmState.agentSessions.delete(sessionId);
|
|
5494
|
+
}
|
|
5477
5495
|
function getAgentSession(sessionId) {
|
|
5478
5496
|
return swarmState.agentSessions.get(sessionId);
|
|
5479
5497
|
}
|
|
@@ -5978,7 +5996,7 @@ function hasActiveEpicMode(sessionID) {
|
|
|
5978
5996
|
async function rehydratePrSubscriptions(sessionID, directory) {
|
|
5979
5997
|
const map = new Map;
|
|
5980
5998
|
try {
|
|
5981
|
-
const { listActive: listActive2 } = await import("./pr-subscriptions-
|
|
5999
|
+
const { listActive: listActive2 } = await import("./pr-subscriptions-fqrzm0tv.js");
|
|
5982
6000
|
const records = await listActive2(directory);
|
|
5983
6001
|
for (const record of records) {
|
|
5984
6002
|
if (record.sessionID !== sessionID)
|
|
@@ -6055,6 +6073,199 @@ async function handleAutoProceedCommand(_directory, args, sessionID) {
|
|
|
6055
6073
|
}
|
|
6056
6074
|
}
|
|
6057
6075
|
|
|
6076
|
+
// src/services/cost-accounting.ts
|
|
6077
|
+
import * as fs7 from "fs";
|
|
6078
|
+
import * as os6 from "os";
|
|
6079
|
+
import * as path12 from "path";
|
|
6080
|
+
function summarizeTelemetryCosts(directory) {
|
|
6081
|
+
const summary = createEmptySummary();
|
|
6082
|
+
for (const event of readTelemetryEvents(directory)) {
|
|
6083
|
+
if (event.event !== "delegation_end")
|
|
6084
|
+
continue;
|
|
6085
|
+
addDelegationEvent(summary, event);
|
|
6086
|
+
}
|
|
6087
|
+
return finalizeSummary(summary);
|
|
6088
|
+
}
|
|
6089
|
+
function readTelemetryEvents(directory) {
|
|
6090
|
+
const swarmDir = path12.join(directory, ".swarm");
|
|
6091
|
+
const files = [
|
|
6092
|
+
path12.join(swarmDir, "telemetry.jsonl.1"),
|
|
6093
|
+
path12.join(swarmDir, "telemetry.jsonl")
|
|
6094
|
+
];
|
|
6095
|
+
const tmpDir = fs7.mkdtempSync(path12.join(os6.tmpdir(), "telemetry-snapshot-"));
|
|
6096
|
+
const snapshotFiles = [];
|
|
6097
|
+
try {
|
|
6098
|
+
for (const file of files) {
|
|
6099
|
+
if (!fs7.existsSync(file))
|
|
6100
|
+
continue;
|
|
6101
|
+
const snap = path12.join(tmpDir, path12.basename(file));
|
|
6102
|
+
try {
|
|
6103
|
+
fs7.copyFileSync(file, snap);
|
|
6104
|
+
snapshotFiles.push(snap);
|
|
6105
|
+
} catch {}
|
|
6106
|
+
}
|
|
6107
|
+
} catch {}
|
|
6108
|
+
const events = [];
|
|
6109
|
+
for (const file of snapshotFiles) {
|
|
6110
|
+
let content = "";
|
|
6111
|
+
try {
|
|
6112
|
+
content = fs7.readFileSync(file, "utf-8");
|
|
6113
|
+
} catch {
|
|
6114
|
+
continue;
|
|
6115
|
+
}
|
|
6116
|
+
for (const line of content.split(/\r?\n/)) {
|
|
6117
|
+
const trimmed = line.trim();
|
|
6118
|
+
if (!trimmed)
|
|
6119
|
+
continue;
|
|
6120
|
+
try {
|
|
6121
|
+
const parsed = JSON.parse(trimmed);
|
|
6122
|
+
if (isRecord(parsed))
|
|
6123
|
+
events.push(parsed);
|
|
6124
|
+
} catch {}
|
|
6125
|
+
}
|
|
6126
|
+
}
|
|
6127
|
+
try {
|
|
6128
|
+
for (const f of snapshotFiles) {
|
|
6129
|
+
try {
|
|
6130
|
+
fs7.unlinkSync(f);
|
|
6131
|
+
} catch {}
|
|
6132
|
+
}
|
|
6133
|
+
fs7.rmdirSync(tmpDir);
|
|
6134
|
+
} catch {}
|
|
6135
|
+
return events;
|
|
6136
|
+
}
|
|
6137
|
+
function readNumber(record, keys) {
|
|
6138
|
+
for (const key of keys) {
|
|
6139
|
+
const value = record[key];
|
|
6140
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0)
|
|
6141
|
+
return value;
|
|
6142
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
6143
|
+
const parsed = Number(value);
|
|
6144
|
+
if (Number.isFinite(parsed) && parsed >= 0)
|
|
6145
|
+
return parsed;
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
return null;
|
|
6149
|
+
}
|
|
6150
|
+
function isRecord(value) {
|
|
6151
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6152
|
+
}
|
|
6153
|
+
function createEmptySummary() {
|
|
6154
|
+
return {
|
|
6155
|
+
total_cost_usd: 0,
|
|
6156
|
+
total_reported_usd: 0,
|
|
6157
|
+
total_estimated_usd: 0,
|
|
6158
|
+
total_input_tokens: 0,
|
|
6159
|
+
total_output_tokens: 0,
|
|
6160
|
+
total_reasoning_tokens: 0,
|
|
6161
|
+
total_cache_tokens: 0,
|
|
6162
|
+
delegations: 0,
|
|
6163
|
+
unavailable_delegations: 0,
|
|
6164
|
+
by_agent: [],
|
|
6165
|
+
by_task: [],
|
|
6166
|
+
by_gate: [],
|
|
6167
|
+
by_retry: [],
|
|
6168
|
+
by_source: {
|
|
6169
|
+
reported: { delegations: 0, cost_usd: 0 },
|
|
6170
|
+
estimated: { delegations: 0, cost_usd: 0 },
|
|
6171
|
+
unavailable: { delegations: 0, cost_usd: 0 }
|
|
6172
|
+
}
|
|
6173
|
+
};
|
|
6174
|
+
}
|
|
6175
|
+
function addDelegationEvent(summary, event) {
|
|
6176
|
+
const costSource = parseCostSource(event.cost_source);
|
|
6177
|
+
const cost = readNumber(event, ["cost_usd"]) ?? 0;
|
|
6178
|
+
const usage = {
|
|
6179
|
+
tokens_input: readNumber(event, ["tokens_input"]) ?? 0,
|
|
6180
|
+
tokens_output: readNumber(event, ["tokens_output"]) ?? 0,
|
|
6181
|
+
tokens_reasoning: readNumber(event, ["tokens_reasoning"]) ?? 0,
|
|
6182
|
+
tokens_cache: readNumber(event, ["tokens_cache"]) ?? 0
|
|
6183
|
+
};
|
|
6184
|
+
summary.delegations++;
|
|
6185
|
+
summary.total_cost_usd += cost;
|
|
6186
|
+
summary.total_input_tokens += usage.tokens_input;
|
|
6187
|
+
summary.total_output_tokens += usage.tokens_output;
|
|
6188
|
+
summary.total_reasoning_tokens += usage.tokens_reasoning;
|
|
6189
|
+
summary.total_cache_tokens += usage.tokens_cache;
|
|
6190
|
+
summary.by_source[costSource].delegations++;
|
|
6191
|
+
summary.by_source[costSource].cost_usd += cost;
|
|
6192
|
+
if (costSource === "reported")
|
|
6193
|
+
summary.total_reported_usd += cost;
|
|
6194
|
+
if (costSource === "estimated")
|
|
6195
|
+
summary.total_estimated_usd += cost;
|
|
6196
|
+
if (costSource === "unavailable")
|
|
6197
|
+
summary.unavailable_delegations++;
|
|
6198
|
+
addRow(summary.by_agent, String(event.agentName ?? event.agent ?? "unknown"), {
|
|
6199
|
+
cost,
|
|
6200
|
+
costSource,
|
|
6201
|
+
usage
|
|
6202
|
+
});
|
|
6203
|
+
addRow(summary.by_task, String(event.taskId ?? event.task_id ?? "unknown"), {
|
|
6204
|
+
cost,
|
|
6205
|
+
costSource,
|
|
6206
|
+
usage
|
|
6207
|
+
});
|
|
6208
|
+
addRow(summary.by_gate, String(event.gate ?? "unknown"), {
|
|
6209
|
+
cost,
|
|
6210
|
+
costSource,
|
|
6211
|
+
usage
|
|
6212
|
+
});
|
|
6213
|
+
addRow(summary.by_retry, String(readNumber(event, ["retry_index", "retryIndex"]) ?? 0), {
|
|
6214
|
+
cost,
|
|
6215
|
+
costSource,
|
|
6216
|
+
usage
|
|
6217
|
+
});
|
|
6218
|
+
}
|
|
6219
|
+
function addRow(rows, name, input) {
|
|
6220
|
+
let row = rows.find((candidate) => candidate.name === name);
|
|
6221
|
+
if (!row) {
|
|
6222
|
+
row = {
|
|
6223
|
+
name,
|
|
6224
|
+
delegations: 0,
|
|
6225
|
+
cost_usd: 0,
|
|
6226
|
+
input_tokens: 0,
|
|
6227
|
+
output_tokens: 0,
|
|
6228
|
+
reasoning_tokens: 0,
|
|
6229
|
+
cache_tokens: 0,
|
|
6230
|
+
unavailable_delegations: 0
|
|
6231
|
+
};
|
|
6232
|
+
rows.push(row);
|
|
6233
|
+
}
|
|
6234
|
+
row.delegations++;
|
|
6235
|
+
row.cost_usd += input.cost;
|
|
6236
|
+
row.input_tokens += input.usage.tokens_input;
|
|
6237
|
+
row.output_tokens += input.usage.tokens_output;
|
|
6238
|
+
row.reasoning_tokens += input.usage.tokens_reasoning;
|
|
6239
|
+
row.cache_tokens += input.usage.tokens_cache;
|
|
6240
|
+
if (input.costSource === "unavailable")
|
|
6241
|
+
row.unavailable_delegations++;
|
|
6242
|
+
}
|
|
6243
|
+
function finalizeSummary(summary) {
|
|
6244
|
+
summary.total_cost_usd = roundUsd(summary.total_cost_usd);
|
|
6245
|
+
summary.total_reported_usd = roundUsd(summary.total_reported_usd);
|
|
6246
|
+
summary.total_estimated_usd = roundUsd(summary.total_estimated_usd);
|
|
6247
|
+
for (const source of Object.values(summary.by_source)) {
|
|
6248
|
+
source.cost_usd = roundUsd(source.cost_usd);
|
|
6249
|
+
}
|
|
6250
|
+
for (const rows of [
|
|
6251
|
+
summary.by_agent,
|
|
6252
|
+
summary.by_task,
|
|
6253
|
+
summary.by_gate,
|
|
6254
|
+
summary.by_retry
|
|
6255
|
+
]) {
|
|
6256
|
+
for (const row of rows)
|
|
6257
|
+
row.cost_usd = roundUsd(row.cost_usd);
|
|
6258
|
+
rows.sort((a, b) => b.cost_usd - a.cost_usd || b.delegations - a.delegations);
|
|
6259
|
+
}
|
|
6260
|
+
return summary;
|
|
6261
|
+
}
|
|
6262
|
+
function parseCostSource(value) {
|
|
6263
|
+
return value === "reported" || value === "estimated" || value === "unavailable" ? value : "unavailable";
|
|
6264
|
+
}
|
|
6265
|
+
function roundUsd(value) {
|
|
6266
|
+
return Math.round(value * 1e6) / 1e6;
|
|
6267
|
+
}
|
|
6268
|
+
|
|
6058
6269
|
// src/commands/benchmark.ts
|
|
6059
6270
|
var CI = {
|
|
6060
6271
|
review_pass_rate: 70,
|
|
@@ -6070,7 +6281,9 @@ async function handleBenchmarkCommand(directory, args) {
|
|
|
6070
6281
|
let cumulative = args.includes("--cumulative");
|
|
6071
6282
|
if (args.includes("--ci-gate"))
|
|
6072
6283
|
cumulative = true;
|
|
6284
|
+
const maxCostUsd = parseMaxCostUsd(args);
|
|
6073
6285
|
const mode = cumulative ? "cumulative" : "in-memory";
|
|
6286
|
+
const costSummary = cumulative ? summarizeTelemetryCosts(directory) : undefined;
|
|
6074
6287
|
const agentMap = new Map;
|
|
6075
6288
|
for (const [, s] of swarmState.agentSessions) {
|
|
6076
6289
|
const e = agentMap.get(s.agentName) || {
|
|
@@ -6262,6 +6475,15 @@ async function handleBenchmarkCommand(directory, args) {
|
|
|
6262
6475
|
passed: !hasQualityEvidence || testToCodeRatio >= CI.min_test_to_code_ratio
|
|
6263
6476
|
}
|
|
6264
6477
|
];
|
|
6478
|
+
if (maxCostUsd !== null) {
|
|
6479
|
+
checks.push({
|
|
6480
|
+
name: "Total cost",
|
|
6481
|
+
value: costSummary?.total_cost_usd ?? 0,
|
|
6482
|
+
threshold: maxCostUsd,
|
|
6483
|
+
operator: "<=",
|
|
6484
|
+
passed: (costSummary?.total_cost_usd ?? 0) <= maxCostUsd
|
|
6485
|
+
});
|
|
6486
|
+
}
|
|
6265
6487
|
ciGate = { passed: checks.every((c) => c.passed), checks };
|
|
6266
6488
|
}
|
|
6267
6489
|
const lines = [
|
|
@@ -6313,16 +6535,23 @@ async function handleBenchmarkCommand(directory, args) {
|
|
|
6313
6535
|
lines.push(`- Test-to-Code Ratio: ${qualityMetrics.testToCodeRatio}% (min: ${qualityMetrics.thresholds.minTestToCodeRatio}%) ${qualityMetrics.testToCodeRatio >= qualityMetrics.thresholds.minTestToCodeRatio ? "\u2705" : "\u274C"}`);
|
|
6314
6536
|
lines.push("");
|
|
6315
6537
|
}
|
|
6538
|
+
if (costSummary) {
|
|
6539
|
+
lines.push("### Cost Signals");
|
|
6540
|
+
lines.push(`- Total tracked cost: $${costSummary.total_cost_usd.toFixed(6)} (${costSummary.delegations} delegations)`, `- Reported: $${costSummary.total_reported_usd.toFixed(6)}; estimated: $${costSummary.total_estimated_usd.toFixed(6)}; unavailable: ${costSummary.unavailable_delegations}`);
|
|
6541
|
+
lines.push("");
|
|
6542
|
+
}
|
|
6316
6543
|
if (ciGate) {
|
|
6317
6544
|
lines.push("### CI Gate", ciGate.passed ? "\u2705 PASSED" : "\u274C FAILED");
|
|
6318
6545
|
for (const c of ciGate.checks) {
|
|
6319
6546
|
let valueStr;
|
|
6320
6547
|
if (c.name === "Complexity Delta" || c.name === "Public API Delta") {
|
|
6321
6548
|
valueStr = `${c.value}`;
|
|
6549
|
+
} else if (c.name === "Total cost") {
|
|
6550
|
+
valueStr = `$${c.value.toFixed(6)}`;
|
|
6322
6551
|
} else {
|
|
6323
6552
|
valueStr = `${c.value}%`;
|
|
6324
6553
|
}
|
|
6325
|
-
const thresholdStr = c.name === "Complexity Delta" || c.name === "Public API Delta" ? `${c.threshold}` : `${c.threshold}%`;
|
|
6554
|
+
const thresholdStr = c.name === "Complexity Delta" || c.name === "Public API Delta" ? `${c.threshold}` : c.name === "Total cost" ? `$${c.threshold.toFixed(6)}` : `${c.threshold}%`;
|
|
6326
6555
|
lines.push(`- ${c.name}: ${valueStr} ${c.operator} ${thresholdStr} ${c.passed ? "\u2705" : "\u274C"}`);
|
|
6327
6556
|
}
|
|
6328
6557
|
lines.push("");
|
|
@@ -6363,6 +6592,18 @@ async function handleBenchmarkCommand(directory, args) {
|
|
|
6363
6592
|
thresholds: qualityMetrics.thresholds,
|
|
6364
6593
|
has_evidence: qualityMetrics.hasEvidence
|
|
6365
6594
|
};
|
|
6595
|
+
if (costSummary)
|
|
6596
|
+
json.costs = {
|
|
6597
|
+
total_cost_usd: costSummary.total_cost_usd,
|
|
6598
|
+
total_reported_usd: costSummary.total_reported_usd,
|
|
6599
|
+
total_estimated_usd: costSummary.total_estimated_usd,
|
|
6600
|
+
total_input_tokens: costSummary.total_input_tokens,
|
|
6601
|
+
total_output_tokens: costSummary.total_output_tokens,
|
|
6602
|
+
total_reasoning_tokens: costSummary.total_reasoning_tokens,
|
|
6603
|
+
total_cache_tokens: costSummary.total_cache_tokens,
|
|
6604
|
+
delegations: costSummary.delegations,
|
|
6605
|
+
unavailable_delegations: costSummary.unavailable_delegations
|
|
6606
|
+
};
|
|
6366
6607
|
if (ciGate)
|
|
6367
6608
|
json.ci_gate = {
|
|
6368
6609
|
passed: ciGate.passed,
|
|
@@ -6378,6 +6619,20 @@ async function handleBenchmarkCommand(directory, args) {
|
|
|
6378
6619
|
return lines.join(`
|
|
6379
6620
|
`);
|
|
6380
6621
|
}
|
|
6622
|
+
function parseMaxCostUsd(args) {
|
|
6623
|
+
const index = args.indexOf("--max-cost-usd");
|
|
6624
|
+
if (index === -1)
|
|
6625
|
+
return null;
|
|
6626
|
+
const raw = args[index + 1];
|
|
6627
|
+
if (!raw || raw.startsWith("--")) {
|
|
6628
|
+
throw new Error("Invalid --max-cost-usd value: expected a non-negative number.");
|
|
6629
|
+
}
|
|
6630
|
+
const parsed = Number(raw);
|
|
6631
|
+
if (!Number.isFinite(parsed) || parsed < 0) {
|
|
6632
|
+
throw new Error("Invalid --max-cost-usd value: expected a non-negative number.");
|
|
6633
|
+
}
|
|
6634
|
+
return parsed;
|
|
6635
|
+
}
|
|
6381
6636
|
|
|
6382
6637
|
// src/commands/brainstorm.ts
|
|
6383
6638
|
function sanitizeTopic(raw) {
|
|
@@ -6399,8 +6654,8 @@ async function handleBrainstormCommand(_directory, args) {
|
|
|
6399
6654
|
|
|
6400
6655
|
// src/tools/checkpoint.ts
|
|
6401
6656
|
import * as child_process from "child_process";
|
|
6402
|
-
import * as
|
|
6403
|
-
import * as
|
|
6657
|
+
import * as fs8 from "fs";
|
|
6658
|
+
import * as path13 from "path";
|
|
6404
6659
|
|
|
6405
6660
|
// src/tools/create-tool.ts
|
|
6406
6661
|
function classifyToolError(error2) {
|
|
@@ -6487,13 +6742,13 @@ function validateLabel(label) {
|
|
|
6487
6742
|
return null;
|
|
6488
6743
|
}
|
|
6489
6744
|
function getCheckpointLogPath(directory) {
|
|
6490
|
-
return
|
|
6745
|
+
return path13.join(directory, CHECKPOINT_LOG_PATH);
|
|
6491
6746
|
}
|
|
6492
6747
|
function readCheckpointLog(directory) {
|
|
6493
6748
|
const logPath = getCheckpointLogPath(directory);
|
|
6494
6749
|
try {
|
|
6495
|
-
if (
|
|
6496
|
-
const content =
|
|
6750
|
+
if (fs8.existsSync(logPath)) {
|
|
6751
|
+
const content = fs8.readFileSync(logPath, "utf-8");
|
|
6497
6752
|
const parsed = JSON.parse(content);
|
|
6498
6753
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
6499
6754
|
return { version: 1, checkpoints: [] };
|
|
@@ -6505,13 +6760,13 @@ function readCheckpointLog(directory) {
|
|
|
6505
6760
|
}
|
|
6506
6761
|
function writeCheckpointLog(log2, directory) {
|
|
6507
6762
|
const logPath = getCheckpointLogPath(directory);
|
|
6508
|
-
const dir =
|
|
6509
|
-
if (!
|
|
6510
|
-
|
|
6763
|
+
const dir = path13.dirname(logPath);
|
|
6764
|
+
if (!fs8.existsSync(dir)) {
|
|
6765
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
6511
6766
|
}
|
|
6512
6767
|
const tempPath = `${logPath}.tmp`;
|
|
6513
|
-
|
|
6514
|
-
|
|
6768
|
+
fs8.writeFileSync(tempPath, JSON.stringify(log2, null, 2), "utf-8");
|
|
6769
|
+
fs8.renameSync(tempPath, logPath);
|
|
6515
6770
|
}
|
|
6516
6771
|
function gitExec(args, cwd) {
|
|
6517
6772
|
for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
|
|
@@ -6542,10 +6797,10 @@ function gitExec(args, cwd) {
|
|
|
6542
6797
|
}
|
|
6543
6798
|
function appendRetentionEvent(directory, event) {
|
|
6544
6799
|
try {
|
|
6545
|
-
const eventsPath =
|
|
6800
|
+
const eventsPath = path13.join(directory, ".swarm", "events.jsonl");
|
|
6546
6801
|
const line = `${JSON.stringify({ ...event, timestamp: new Date().toISOString() })}
|
|
6547
6802
|
`;
|
|
6548
|
-
|
|
6803
|
+
fs8.appendFileSync(eventsPath, line);
|
|
6549
6804
|
} catch {}
|
|
6550
6805
|
}
|
|
6551
6806
|
function getCurrentSha(directory) {
|
|
@@ -6907,8 +7162,8 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
6907
7162
|
// src/commands/close.ts
|
|
6908
7163
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
6909
7164
|
import * as fsSync2 from "fs";
|
|
6910
|
-
import { promises as
|
|
6911
|
-
import
|
|
7165
|
+
import { promises as fs13 } from "fs";
|
|
7166
|
+
import path26 from "path";
|
|
6912
7167
|
|
|
6913
7168
|
// src/hooks/abort-utils.ts
|
|
6914
7169
|
function isAbortError(err) {
|
|
@@ -7037,8 +7292,8 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
|
7037
7292
|
}
|
|
7038
7293
|
|
|
7039
7294
|
// src/hooks/curator-postmortem.ts
|
|
7040
|
-
import { existsSync as
|
|
7041
|
-
import * as
|
|
7295
|
+
import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync6 } from "fs";
|
|
7296
|
+
import * as path14 from "path";
|
|
7042
7297
|
var MAX_INPUT_TEXT_CHARS = 500;
|
|
7043
7298
|
var MAX_KNOWLEDGE_ENTRIES = 500;
|
|
7044
7299
|
var MAX_PROPOSALS = 50;
|
|
@@ -7083,9 +7338,9 @@ async function collectKnowledgeSummary(directory) {
|
|
|
7083
7338
|
}
|
|
7084
7339
|
function readJsonlFile(filePath, maxLines) {
|
|
7085
7340
|
try {
|
|
7086
|
-
if (!
|
|
7341
|
+
if (!existsSync6(filePath))
|
|
7087
7342
|
return [];
|
|
7088
|
-
const content =
|
|
7343
|
+
const content = readFileSync6(filePath, "utf-8");
|
|
7089
7344
|
const results = [];
|
|
7090
7345
|
const max = maxLines !== undefined && maxLines > 0 ? maxLines : Infinity;
|
|
7091
7346
|
for (const line of content.split(`
|
|
@@ -7105,16 +7360,16 @@ function readJsonlFile(filePath, maxLines) {
|
|
|
7105
7360
|
}
|
|
7106
7361
|
function collectRetrospectives(directory) {
|
|
7107
7362
|
const results = [];
|
|
7108
|
-
const evidenceDir =
|
|
7363
|
+
const evidenceDir = path14.join(directory, ".swarm", "evidence");
|
|
7109
7364
|
try {
|
|
7110
|
-
if (!
|
|
7365
|
+
if (!existsSync6(evidenceDir))
|
|
7111
7366
|
return results;
|
|
7112
7367
|
const retroDirs = readdirSync(evidenceDir, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("retro-")).slice(0, MAX_RETROSPECTIVES);
|
|
7113
7368
|
for (const entry of retroDirs) {
|
|
7114
|
-
const retroPath =
|
|
7115
|
-
if (
|
|
7369
|
+
const retroPath = path14.join(evidenceDir, entry.name, "evidence.json");
|
|
7370
|
+
if (existsSync6(retroPath)) {
|
|
7116
7371
|
try {
|
|
7117
|
-
results.push(
|
|
7372
|
+
results.push(readFileSync6(retroPath, "utf-8"));
|
|
7118
7373
|
} catch {}
|
|
7119
7374
|
}
|
|
7120
7375
|
}
|
|
@@ -7123,14 +7378,14 @@ function collectRetrospectives(directory) {
|
|
|
7123
7378
|
}
|
|
7124
7379
|
function collectDriftReports(directory) {
|
|
7125
7380
|
const results = [];
|
|
7126
|
-
const swarmDir =
|
|
7381
|
+
const swarmDir = path14.join(directory, ".swarm");
|
|
7127
7382
|
try {
|
|
7128
|
-
if (!
|
|
7383
|
+
if (!existsSync6(swarmDir))
|
|
7129
7384
|
return results;
|
|
7130
7385
|
const driftFiles = readdirSync(swarmDir).filter((e) => e.startsWith("drift-report-phase-") && e.endsWith(".json")).slice(0, MAX_DRIFT_REPORTS);
|
|
7131
7386
|
for (const entry of driftFiles) {
|
|
7132
7387
|
try {
|
|
7133
|
-
results.push(
|
|
7388
|
+
results.push(readFileSync6(path14.join(swarmDir, entry), "utf-8"));
|
|
7134
7389
|
} catch {}
|
|
7135
7390
|
}
|
|
7136
7391
|
} catch {}
|
|
@@ -7138,24 +7393,24 @@ function collectDriftReports(directory) {
|
|
|
7138
7393
|
}
|
|
7139
7394
|
function collectPendingProposals(directory) {
|
|
7140
7395
|
const results = [];
|
|
7141
|
-
const insightPath =
|
|
7142
|
-
if (
|
|
7396
|
+
const insightPath = path14.join(directory, ".swarm", "insight-candidates.jsonl");
|
|
7397
|
+
if (existsSync6(insightPath)) {
|
|
7143
7398
|
try {
|
|
7144
7399
|
results.push({
|
|
7145
7400
|
source: "insight-candidates",
|
|
7146
|
-
content:
|
|
7401
|
+
content: readFileSync6(insightPath, "utf-8")
|
|
7147
7402
|
});
|
|
7148
7403
|
} catch {}
|
|
7149
7404
|
}
|
|
7150
|
-
const proposalsDir =
|
|
7405
|
+
const proposalsDir = path14.join(directory, ".swarm", "skills", "proposals");
|
|
7151
7406
|
try {
|
|
7152
|
-
if (
|
|
7407
|
+
if (existsSync6(proposalsDir)) {
|
|
7153
7408
|
const proposalFiles = readdirSync(proposalsDir).filter((e) => e.endsWith(".md") || e.endsWith(".json")).slice(0, MAX_PROPOSALS);
|
|
7154
7409
|
for (const entry of proposalFiles) {
|
|
7155
7410
|
try {
|
|
7156
7411
|
results.push({
|
|
7157
7412
|
source: `proposals/${entry}`,
|
|
7158
|
-
content:
|
|
7413
|
+
content: readFileSync6(path14.join(proposalsDir, entry), "utf-8")
|
|
7159
7414
|
});
|
|
7160
7415
|
} catch {}
|
|
7161
7416
|
}
|
|
@@ -7165,9 +7420,9 @@ function collectPendingProposals(directory) {
|
|
|
7165
7420
|
}
|
|
7166
7421
|
function isReportValid(reportPath) {
|
|
7167
7422
|
try {
|
|
7168
|
-
if (!
|
|
7423
|
+
if (!existsSync6(reportPath))
|
|
7169
7424
|
return false;
|
|
7170
|
-
const content =
|
|
7425
|
+
const content = readFileSync6(reportPath, "utf-8").trim();
|
|
7171
7426
|
if (content.length === 0)
|
|
7172
7427
|
return false;
|
|
7173
7428
|
if (!content.startsWith("# Post-Mortem Report:"))
|
|
@@ -7376,7 +7631,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
7376
7631
|
warnings.push(`Pending proposals capped at ${MAX_PROPOSALS} (had ${proposals.length}); older entries truncated.`);
|
|
7377
7632
|
proposals = proposals.slice(0, MAX_PROPOSALS);
|
|
7378
7633
|
}
|
|
7379
|
-
const unactionablePath =
|
|
7634
|
+
const unactionablePath = path14.join(resolveKnowledgeStoreDir(directory), "knowledge-unactionable.jsonl");
|
|
7380
7635
|
let unactionable = readJsonlFile(unactionablePath, MAX_UNACTIONABLE);
|
|
7381
7636
|
if (unactionable.length > MAX_UNACTIONABLE) {
|
|
7382
7637
|
warnings.push(`Unactionable entries capped at ${MAX_UNACTIONABLE} (had ${unactionable.length}); older entries truncated.`);
|
|
@@ -7426,7 +7681,7 @@ ${llmOutput}`;
|
|
|
7426
7681
|
}
|
|
7427
7682
|
try {
|
|
7428
7683
|
const { mkdirSync: mkdirSync6 } = await import("fs");
|
|
7429
|
-
mkdirSync6(
|
|
7684
|
+
mkdirSync6(path14.dirname(reportPath), { recursive: true });
|
|
7430
7685
|
await atomicWriteFile(reportPath, reportContent);
|
|
7431
7686
|
} catch (err) {
|
|
7432
7687
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -7474,7 +7729,7 @@ var _internals13 = {
|
|
|
7474
7729
|
};
|
|
7475
7730
|
|
|
7476
7731
|
// src/hooks/hive-promoter.ts
|
|
7477
|
-
import
|
|
7732
|
+
import path17 from "path";
|
|
7478
7733
|
|
|
7479
7734
|
// src/background/event-bus.ts
|
|
7480
7735
|
class AutomationEventBus {
|
|
@@ -7978,9 +8233,9 @@ init_logger();
|
|
|
7978
8233
|
|
|
7979
8234
|
// src/services/skill-improver-quota.ts
|
|
7980
8235
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
7981
|
-
import { existsSync as
|
|
8236
|
+
import { existsSync as existsSync7 } from "fs";
|
|
7982
8237
|
import { mkdir as mkdir3, readFile as readFile3, rename, writeFile as writeFile2 } from "fs/promises";
|
|
7983
|
-
import * as
|
|
8238
|
+
import * as path15 from "path";
|
|
7984
8239
|
var LOCK_ACQUIRE_TIMEOUT_MS = 1e4;
|
|
7985
8240
|
var LOCK_RETRY_OPTS = {
|
|
7986
8241
|
retries: {
|
|
@@ -8009,7 +8264,7 @@ async function acquireLock(dir) {
|
|
|
8009
8264
|
}
|
|
8010
8265
|
function resolveQuotaPath(directory, scope = "skill-improver") {
|
|
8011
8266
|
const fileName = scope === "knowledge-enrichment" ? "knowledge-enrichment-quota.json" : "skill-improver-quota.json";
|
|
8012
|
-
return
|
|
8267
|
+
return path15.join(directory, ".swarm", fileName);
|
|
8013
8268
|
}
|
|
8014
8269
|
function todayKey(window, now = new Date) {
|
|
8015
8270
|
if (window === "utc") {
|
|
@@ -8021,7 +8276,7 @@ function todayKey(window, now = new Date) {
|
|
|
8021
8276
|
return `${yr}-${m}-${d}`;
|
|
8022
8277
|
}
|
|
8023
8278
|
async function readState(filePath) {
|
|
8024
|
-
if (!
|
|
8279
|
+
if (!existsSync7(filePath))
|
|
8025
8280
|
return null;
|
|
8026
8281
|
try {
|
|
8027
8282
|
const raw = await readFile3(filePath, "utf-8");
|
|
@@ -8035,7 +8290,7 @@ async function readState(filePath) {
|
|
|
8035
8290
|
}
|
|
8036
8291
|
}
|
|
8037
8292
|
async function writeState(filePath, state) {
|
|
8038
|
-
await mkdir3(
|
|
8293
|
+
await mkdir3(path15.dirname(filePath), { recursive: true });
|
|
8039
8294
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
8040
8295
|
await writeFile2(tmp, JSON.stringify(state, null, 2), "utf-8");
|
|
8041
8296
|
await rename(tmp, filePath);
|
|
@@ -8058,10 +8313,10 @@ async function getQuotaState(directory, opts) {
|
|
|
8058
8313
|
}
|
|
8059
8314
|
async function reserveQuota(directory, opts) {
|
|
8060
8315
|
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
8061
|
-
await mkdir3(
|
|
8316
|
+
await mkdir3(path15.dirname(filePath), { recursive: true });
|
|
8062
8317
|
let release = null;
|
|
8063
8318
|
try {
|
|
8064
|
-
release = await acquireLock(
|
|
8319
|
+
release = await acquireLock(path15.dirname(filePath));
|
|
8065
8320
|
const state = await getQuotaState(directory, opts);
|
|
8066
8321
|
if (state.calls_used + opts.nCalls > opts.maxCalls) {
|
|
8067
8322
|
return {
|
|
@@ -8088,10 +8343,10 @@ async function reserveQuota(directory, opts) {
|
|
|
8088
8343
|
}
|
|
8089
8344
|
async function releaseQuota(directory, opts) {
|
|
8090
8345
|
const filePath = resolveQuotaPath(directory, opts.scope);
|
|
8091
|
-
await mkdir3(
|
|
8346
|
+
await mkdir3(path15.dirname(filePath), { recursive: true });
|
|
8092
8347
|
let release = null;
|
|
8093
8348
|
try {
|
|
8094
|
-
release = await acquireLock(
|
|
8349
|
+
release = await acquireLock(path15.dirname(filePath));
|
|
8095
8350
|
const state = await getQuotaState(directory, opts);
|
|
8096
8351
|
const next = {
|
|
8097
8352
|
...state,
|
|
@@ -8114,8 +8369,8 @@ init_logger();
|
|
|
8114
8369
|
|
|
8115
8370
|
// src/hooks/skill-usage-log.ts
|
|
8116
8371
|
import * as crypto3 from "crypto";
|
|
8117
|
-
import * as
|
|
8118
|
-
import * as
|
|
8372
|
+
import * as fs9 from "fs";
|
|
8373
|
+
import * as path16 from "path";
|
|
8119
8374
|
function resolveLogPath(directory) {
|
|
8120
8375
|
return validateSwarmPath(directory, "skill-usage.jsonl");
|
|
8121
8376
|
}
|
|
@@ -8124,16 +8379,16 @@ function normalizeComplianceVerdict(verdict) {
|
|
|
8124
8379
|
}
|
|
8125
8380
|
var _internals14 = {
|
|
8126
8381
|
generateId: () => crypto3.randomUUID(),
|
|
8127
|
-
appendFileSync:
|
|
8128
|
-
readFileSync:
|
|
8129
|
-
writeFileSync:
|
|
8130
|
-
renameSync:
|
|
8131
|
-
mkdirSync:
|
|
8132
|
-
existsSync:
|
|
8133
|
-
statSync:
|
|
8134
|
-
openSync:
|
|
8135
|
-
readSync:
|
|
8136
|
-
closeSync:
|
|
8382
|
+
appendFileSync: fs9.appendFileSync.bind(fs9),
|
|
8383
|
+
readFileSync: fs9.readFileSync.bind(fs9),
|
|
8384
|
+
writeFileSync: fs9.writeFileSync.bind(fs9),
|
|
8385
|
+
renameSync: fs9.renameSync.bind(fs9),
|
|
8386
|
+
mkdirSync: fs9.mkdirSync.bind(fs9),
|
|
8387
|
+
existsSync: fs9.existsSync.bind(fs9),
|
|
8388
|
+
statSync: fs9.statSync.bind(fs9),
|
|
8389
|
+
openSync: fs9.openSync.bind(fs9),
|
|
8390
|
+
readSync: fs9.readSync.bind(fs9),
|
|
8391
|
+
closeSync: fs9.closeSync.bind(fs9),
|
|
8137
8392
|
pruneSkillUsageLog,
|
|
8138
8393
|
resolveSourceKnowledgeIds,
|
|
8139
8394
|
applySkillUsageFeedback,
|
|
@@ -8214,7 +8469,7 @@ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
|
|
|
8214
8469
|
if (processedEntryIds.length === 0)
|
|
8215
8470
|
return;
|
|
8216
8471
|
const resolved = resolveLogPath(directory);
|
|
8217
|
-
const dir =
|
|
8472
|
+
const dir = path16.dirname(resolved);
|
|
8218
8473
|
if (!_internals14.existsSync(dir)) {
|
|
8219
8474
|
_internals14.mkdirSync(dir, { recursive: true });
|
|
8220
8475
|
}
|
|
@@ -8259,7 +8514,7 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
8259
8514
|
throw new Error("sessionID is required and must be a non-empty string");
|
|
8260
8515
|
}
|
|
8261
8516
|
const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
|
|
8262
|
-
const dir =
|
|
8517
|
+
const dir = path16.dirname(resolved);
|
|
8263
8518
|
if (!_internals14.existsSync(dir)) {
|
|
8264
8519
|
_internals14.mkdirSync(dir, { recursive: true });
|
|
8265
8520
|
}
|
|
@@ -8435,8 +8690,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8435
8690
|
}
|
|
8436
8691
|
if (entries.length === 0) {
|
|
8437
8692
|
if (preservedMarkers.length > 0) {
|
|
8438
|
-
const dir2 =
|
|
8439
|
-
const tmpPath2 =
|
|
8693
|
+
const dir2 = path16.dirname(resolved);
|
|
8694
|
+
const tmpPath2 = path16.join(dir2, `skill-usage-${Date.now()}.tmp`);
|
|
8440
8695
|
const content2 = preservedMarkers.join(`
|
|
8441
8696
|
`).concat(preservedMarkers.length > 0 ? `
|
|
8442
8697
|
` : "");
|
|
@@ -8478,8 +8733,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8478
8733
|
if (pruned === 0) {
|
|
8479
8734
|
return { pruned: 0, remaining: entries.length };
|
|
8480
8735
|
}
|
|
8481
|
-
const dir =
|
|
8482
|
-
const tmpPath =
|
|
8736
|
+
const dir = path16.dirname(resolved);
|
|
8737
|
+
const tmpPath = path16.join(dir, `skill-usage-${Date.now()}.tmp`);
|
|
8483
8738
|
const entryLines = surviving.map((e) => JSON.stringify(e));
|
|
8484
8739
|
const allLines = [...entryLines, ...preservedMarkers];
|
|
8485
8740
|
const content = allLines.join(`
|
|
@@ -8508,9 +8763,9 @@ async function resolveSourceKnowledgeIds(directory, skillPath) {
|
|
|
8508
8763
|
if (/\.\.[/\\]/.test(cleanPath)) {
|
|
8509
8764
|
return [];
|
|
8510
8765
|
}
|
|
8511
|
-
const absolute =
|
|
8512
|
-
const baseDir =
|
|
8513
|
-
const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir +
|
|
8766
|
+
const absolute = path16.normalize(path16.isAbsolute(cleanPath) ? cleanPath : path16.resolve(directory, cleanPath));
|
|
8767
|
+
const baseDir = path16.normalize(path16.resolve(directory));
|
|
8768
|
+
const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir + path16.sep).toLowerCase()) : absolute.startsWith(baseDir + path16.sep);
|
|
8514
8769
|
if (!isContained) {
|
|
8515
8770
|
return [];
|
|
8516
8771
|
}
|
|
@@ -8822,7 +9077,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
8822
9077
|
schema_version: 1,
|
|
8823
9078
|
created_at: new Date().toISOString(),
|
|
8824
9079
|
updated_at: new Date().toISOString(),
|
|
8825
|
-
source_project:
|
|
9080
|
+
source_project: path17.basename(directory) || "unknown",
|
|
8826
9081
|
encounter_score: 1
|
|
8827
9082
|
};
|
|
8828
9083
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -8874,9 +9129,9 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
8874
9129
|
|
|
8875
9130
|
// src/hooks/knowledge-curator.ts
|
|
8876
9131
|
import { createHash as createHash3 } from "crypto";
|
|
8877
|
-
import { existsSync as
|
|
9132
|
+
import { existsSync as existsSync11 } from "fs";
|
|
8878
9133
|
import { appendFile as appendFile2, mkdir as mkdir5, readFile as readFile6, writeFile as writeFile5 } from "fs/promises";
|
|
8879
|
-
import * as
|
|
9134
|
+
import * as path22 from "path";
|
|
8880
9135
|
|
|
8881
9136
|
// src/services/synonym-map.ts
|
|
8882
9137
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
@@ -8888,7 +9143,7 @@ import {
|
|
|
8888
9143
|
unlink as unlink2,
|
|
8889
9144
|
writeFile as writeFile3
|
|
8890
9145
|
} from "fs/promises";
|
|
8891
|
-
import * as
|
|
9146
|
+
import * as path18 from "path";
|
|
8892
9147
|
var SYNONYM_MAP_FILENAME = "synonym-map.json";
|
|
8893
9148
|
var MAX_TOKEN_LENGTH = 64;
|
|
8894
9149
|
var DEFAULT_MAX_PAIRS = 500;
|
|
@@ -9043,7 +9298,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
|
9043
9298
|
}
|
|
9044
9299
|
}
|
|
9045
9300
|
async function writeSynonymMapAtomic(filePath, map) {
|
|
9046
|
-
await mkdir4(
|
|
9301
|
+
await mkdir4(path18.dirname(filePath), { recursive: true });
|
|
9047
9302
|
const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
9048
9303
|
try {
|
|
9049
9304
|
await writeFile3(tmp, JSON.stringify(map, null, 2), "utf-8");
|
|
@@ -9056,7 +9311,7 @@ async function writeSynonymMapAtomic(filePath, map) {
|
|
|
9056
9311
|
}
|
|
9057
9312
|
async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
9058
9313
|
const filePath = resolveSynonymMapPath(directory);
|
|
9059
|
-
const dir =
|
|
9314
|
+
const dir = path18.dirname(filePath);
|
|
9060
9315
|
await mkdir4(dir, { recursive: true });
|
|
9061
9316
|
let release = null;
|
|
9062
9317
|
try {
|
|
@@ -9119,19 +9374,19 @@ function reinforceSwarmKnowledgeEntry(entry, confirmation) {
|
|
|
9119
9374
|
}
|
|
9120
9375
|
|
|
9121
9376
|
// src/hooks/micro-reflector.ts
|
|
9122
|
-
import { existsSync as
|
|
9377
|
+
import { existsSync as existsSync10 } from "fs";
|
|
9123
9378
|
import { readFile as readFile5, writeFile as writeFile4 } from "fs/promises";
|
|
9124
|
-
import * as
|
|
9379
|
+
import * as path21 from "path";
|
|
9125
9380
|
init_logger();
|
|
9126
9381
|
|
|
9127
9382
|
// src/hooks/skill-propagation-gate.ts
|
|
9128
|
-
import * as
|
|
9129
|
-
import * as
|
|
9383
|
+
import * as fs11 from "fs";
|
|
9384
|
+
import * as path20 from "path";
|
|
9130
9385
|
init_logger();
|
|
9131
9386
|
|
|
9132
9387
|
// src/hooks/skill-scoring.ts
|
|
9133
|
-
import * as
|
|
9134
|
-
import * as
|
|
9388
|
+
import * as fs10 from "fs";
|
|
9389
|
+
import * as path19 from "path";
|
|
9135
9390
|
var FREQUENCY_CAP = 10;
|
|
9136
9391
|
var FREQUENCY_WEIGHT = 0.3;
|
|
9137
9392
|
var COMPLIANCE_WEIGHT = 0.3;
|
|
@@ -9159,10 +9414,10 @@ var _internals15 = {
|
|
|
9159
9414
|
computeTriggerMatchBoost: null
|
|
9160
9415
|
};
|
|
9161
9416
|
function extractSkillName(skillPath) {
|
|
9162
|
-
const base =
|
|
9417
|
+
const base = path19.basename(skillPath, path19.extname(skillPath));
|
|
9163
9418
|
if (base !== "SKILL")
|
|
9164
9419
|
return base;
|
|
9165
|
-
const parent =
|
|
9420
|
+
const parent = path19.basename(path19.dirname(skillPath));
|
|
9166
9421
|
return parent;
|
|
9167
9422
|
}
|
|
9168
9423
|
function stripQuotes(value) {
|
|
@@ -9304,25 +9559,25 @@ function parseSkillFrontmatter(content, skillPath) {
|
|
|
9304
9559
|
return meta;
|
|
9305
9560
|
}
|
|
9306
9561
|
function readFilePrefix(filePath) {
|
|
9307
|
-
const fd =
|
|
9562
|
+
const fd = fs10.openSync(filePath, "r");
|
|
9308
9563
|
try {
|
|
9309
9564
|
const buffer = Buffer.alloc(SKILL_FRONTMATTER_READ_BYTES);
|
|
9310
|
-
const bytesRead =
|
|
9565
|
+
const bytesRead = fs10.readSync(fd, buffer, 0, SKILL_FRONTMATTER_READ_BYTES, 0);
|
|
9311
9566
|
return buffer.toString("utf-8", 0, bytesRead);
|
|
9312
9567
|
} finally {
|
|
9313
|
-
|
|
9568
|
+
fs10.closeSync(fd);
|
|
9314
9569
|
}
|
|
9315
9570
|
}
|
|
9316
9571
|
function readSkillMetadata(skillPath, directory) {
|
|
9317
9572
|
const normalizedPath = skillPath.replace(/^file:/, "").replace(/\\/g, "/");
|
|
9318
9573
|
const fallback = parseSkillFrontmatter("", normalizedPath);
|
|
9319
9574
|
try {
|
|
9320
|
-
if (
|
|
9575
|
+
if (path19.isAbsolute(normalizedPath) || normalizedPath.split("/").includes("..")) {
|
|
9321
9576
|
return fallback;
|
|
9322
9577
|
}
|
|
9323
|
-
const root =
|
|
9324
|
-
const absolutePath =
|
|
9325
|
-
if (absolutePath !== root && !absolutePath.startsWith(root +
|
|
9578
|
+
const root = path19.resolve(directory);
|
|
9579
|
+
const absolutePath = path19.resolve(directory, normalizedPath);
|
|
9580
|
+
if (absolutePath !== root && !absolutePath.startsWith(root + path19.sep)) {
|
|
9326
9581
|
return fallback;
|
|
9327
9582
|
}
|
|
9328
9583
|
const content = readFilePrefix(absolutePath);
|
|
@@ -9456,10 +9711,10 @@ function getSkillStats(skillPath, directory) {
|
|
|
9456
9711
|
};
|
|
9457
9712
|
}
|
|
9458
9713
|
function formatSkillIndexWithContext(skills, directory) {
|
|
9459
|
-
const usageLogPath =
|
|
9714
|
+
const usageLogPath = path19.join(directory, ".swarm", "skill-usage.jsonl");
|
|
9460
9715
|
let hasHistory = false;
|
|
9461
9716
|
try {
|
|
9462
|
-
const stat4 =
|
|
9717
|
+
const stat4 = fs10.statSync(usageLogPath);
|
|
9463
9718
|
hasHistory = stat4.size > 0;
|
|
9464
9719
|
} catch {}
|
|
9465
9720
|
if (!hasHistory) {
|
|
@@ -9590,7 +9845,7 @@ function parseYamlValue(value) {
|
|
|
9590
9845
|
return trimmed;
|
|
9591
9846
|
}
|
|
9592
9847
|
function loadRoutingSkills(directory, targetAgent) {
|
|
9593
|
-
const routingPath =
|
|
9848
|
+
const routingPath = path20.join(directory, ".opencode", "skill-routing.yaml");
|
|
9594
9849
|
if (!_internals16.existsSync(routingPath))
|
|
9595
9850
|
return [];
|
|
9596
9851
|
try {
|
|
@@ -9622,13 +9877,13 @@ var SKILL_SEARCH_ROOTS = [
|
|
|
9622
9877
|
];
|
|
9623
9878
|
var MAX_SCORING_SESSION_ENTRIES = 500;
|
|
9624
9879
|
var _internals16 = {
|
|
9625
|
-
readdirSync:
|
|
9626
|
-
existsSync:
|
|
9627
|
-
statSync:
|
|
9628
|
-
mkdirSync:
|
|
9629
|
-
appendFileSync:
|
|
9630
|
-
readFileSync:
|
|
9631
|
-
writeFileSync:
|
|
9880
|
+
readdirSync: fs11.readdirSync.bind(fs11),
|
|
9881
|
+
existsSync: fs11.existsSync.bind(fs11),
|
|
9882
|
+
statSync: fs11.statSync.bind(fs11),
|
|
9883
|
+
mkdirSync: fs11.mkdirSync.bind(fs11),
|
|
9884
|
+
appendFileSync: fs11.appendFileSync.bind(fs11),
|
|
9885
|
+
readFileSync: fs11.readFileSync.bind(fs11),
|
|
9886
|
+
writeFileSync: fs11.writeFileSync.bind(fs11),
|
|
9632
9887
|
skillPropagationGateBefore: null,
|
|
9633
9888
|
skillPropagationTransformScan: null,
|
|
9634
9889
|
SKILL_CAPABLE_AGENTS,
|
|
@@ -9650,7 +9905,7 @@ var _internals16 = {
|
|
|
9650
9905
|
function discoverAvailableSkills(directory) {
|
|
9651
9906
|
const results = [];
|
|
9652
9907
|
for (const root of SKILL_SEARCH_ROOTS) {
|
|
9653
|
-
const rootPath =
|
|
9908
|
+
const rootPath = path20.join(directory, root);
|
|
9654
9909
|
if (!_internals16.existsSync(rootPath))
|
|
9655
9910
|
continue;
|
|
9656
9911
|
let entries;
|
|
@@ -9662,13 +9917,13 @@ function discoverAvailableSkills(directory) {
|
|
|
9662
9917
|
for (const entry of entries) {
|
|
9663
9918
|
if (entry.startsWith("."))
|
|
9664
9919
|
continue;
|
|
9665
|
-
const skillDir =
|
|
9666
|
-
if (_internals16.existsSync(
|
|
9920
|
+
const skillDir = path20.join(rootPath, entry);
|
|
9921
|
+
if (_internals16.existsSync(path20.join(skillDir, "retired.marker")) || _internals16.existsSync(path20.join(skillDir, "stale.marker")))
|
|
9667
9922
|
continue;
|
|
9668
|
-
const skillFile =
|
|
9923
|
+
const skillFile = path20.join(skillDir, "SKILL.md");
|
|
9669
9924
|
try {
|
|
9670
9925
|
if (_internals16.statSync(skillDir).isDirectory() && _internals16.existsSync(skillFile)) {
|
|
9671
|
-
results.push(
|
|
9926
|
+
results.push(path20.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
|
|
9672
9927
|
}
|
|
9673
9928
|
} catch (err) {
|
|
9674
9929
|
warn(`[skill-propagation-gate] failed to stat skill directory ${entry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -9737,9 +9992,9 @@ function extractSkillsFieldFromPrompt(prompt) {
|
|
|
9737
9992
|
return "";
|
|
9738
9993
|
}
|
|
9739
9994
|
function writeWarnEvent(directory, record) {
|
|
9740
|
-
const filePath =
|
|
9995
|
+
const filePath = path20.join(directory, ".swarm", "events.jsonl");
|
|
9741
9996
|
try {
|
|
9742
|
-
const dir =
|
|
9997
|
+
const dir = path20.dirname(filePath);
|
|
9743
9998
|
if (!_internals16.existsSync(dir)) {
|
|
9744
9999
|
_internals16.mkdirSync(dir, { recursive: true });
|
|
9745
10000
|
}
|
|
@@ -9868,8 +10123,8 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
9868
10123
|
if (routingPaths.length > 0) {
|
|
9869
10124
|
const existingPaths = new Set(scored.map((s) => s.skillPath));
|
|
9870
10125
|
for (const routingPath of routingPaths) {
|
|
9871
|
-
const routedSkillDir =
|
|
9872
|
-
if (_internals16.existsSync(
|
|
10126
|
+
const routedSkillDir = path20.dirname(path20.join(directory, routingPath));
|
|
10127
|
+
if (_internals16.existsSync(path20.join(routedSkillDir, "retired.marker")) || _internals16.existsSync(path20.join(routedSkillDir, "stale.marker")))
|
|
9873
10128
|
continue;
|
|
9874
10129
|
if (!existingPaths.has(routingPath)) {
|
|
9875
10130
|
scored.push({
|
|
@@ -9888,8 +10143,8 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
9888
10143
|
let skillsForIndex = availableSkills;
|
|
9889
10144
|
if (scoringSkipped) {
|
|
9890
10145
|
skillsForIndex = [...availableSkills].sort((a, b) => {
|
|
9891
|
-
const nameA =
|
|
9892
|
-
const nameB =
|
|
10146
|
+
const nameA = path20.basename(path20.dirname(a));
|
|
10147
|
+
const nameB = path20.basename(path20.dirname(b));
|
|
9893
10148
|
return nameA.localeCompare(nameB);
|
|
9894
10149
|
});
|
|
9895
10150
|
} else if (typeof scored !== "undefined" && scored.length > 0) {
|
|
@@ -9897,7 +10152,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
9897
10152
|
}
|
|
9898
10153
|
const formattedIndex = _internals16.formatSkillIndexWithContext(skillsForIndex, directory);
|
|
9899
10154
|
if (formattedIndex.length > 0) {
|
|
9900
|
-
const contextPath =
|
|
10155
|
+
const contextPath = path20.join(directory, ".swarm", "context.md");
|
|
9901
10156
|
let existingContent = "";
|
|
9902
10157
|
if (_internals16.existsSync(contextPath)) {
|
|
9903
10158
|
existingContent = _internals16.readFileSync(contextPath, "utf-8");
|
|
@@ -9919,7 +10174,7 @@ ${newSection}`;
|
|
|
9919
10174
|
updatedContent = existingContent + newSection;
|
|
9920
10175
|
}
|
|
9921
10176
|
}
|
|
9922
|
-
const swarmDir =
|
|
10177
|
+
const swarmDir = path20.dirname(contextPath);
|
|
9923
10178
|
if (!_internals16.existsSync(swarmDir)) {
|
|
9924
10179
|
_internals16.mkdirSync(swarmDir, { recursive: true });
|
|
9925
10180
|
}
|
|
@@ -10145,9 +10400,9 @@ function resolveInsightCandidatesPath(directory) {
|
|
|
10145
10400
|
}
|
|
10146
10401
|
async function readTaskTrajectory(directory, taskId) {
|
|
10147
10402
|
try {
|
|
10148
|
-
const rel =
|
|
10403
|
+
const rel = path21.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
|
|
10149
10404
|
const filePath = validateSwarmPath(directory, rel);
|
|
10150
|
-
if (!
|
|
10405
|
+
if (!existsSync10(filePath))
|
|
10151
10406
|
return [];
|
|
10152
10407
|
const content = await readFile5(filePath, "utf-8");
|
|
10153
10408
|
const out = [];
|
|
@@ -10203,7 +10458,7 @@ var WRITE_TOOLS = new Set([
|
|
|
10203
10458
|
"apply_patch",
|
|
10204
10459
|
"swarm_apply_patch"
|
|
10205
10460
|
]);
|
|
10206
|
-
function
|
|
10461
|
+
function isRecord2(value) {
|
|
10207
10462
|
return typeof value === "object" && value !== null;
|
|
10208
10463
|
}
|
|
10209
10464
|
function normalizePathField(value) {
|
|
@@ -10213,13 +10468,13 @@ function firstPathFromRecord(record) {
|
|
|
10213
10468
|
return normalizePathField(record.path) ?? normalizePathField(record.filePath) ?? normalizePathField(record.file);
|
|
10214
10469
|
}
|
|
10215
10470
|
function normalizeWriteTrigger(input, output) {
|
|
10216
|
-
if (!
|
|
10471
|
+
if (!isRecord2(input))
|
|
10217
10472
|
return null;
|
|
10218
10473
|
const toolName = typeof input.toolName === "string" ? input.toolName : typeof input.tool === "string" ? input.tool : null;
|
|
10219
10474
|
if (!toolName || !WRITE_TOOLS.has(toolName))
|
|
10220
10475
|
return null;
|
|
10221
|
-
const inputArgs =
|
|
10222
|
-
const outputArgs =
|
|
10476
|
+
const inputArgs = isRecord2(input.args) ? input.args : null;
|
|
10477
|
+
const outputArgs = isRecord2(output) && isRecord2(output.args) ? output.args : null;
|
|
10223
10478
|
const filePath = firstPathFromRecord(input) ?? (inputArgs ? firstPathFromRecord(inputArgs) : null) ?? (outputArgs ? firstPathFromRecord(outputArgs) : null);
|
|
10224
10479
|
if (!filePath)
|
|
10225
10480
|
return null;
|
|
@@ -10575,8 +10830,8 @@ RETRY: your last output was missing ${result.missing.join("; ")}; produce valid
|
|
|
10575
10830
|
}
|
|
10576
10831
|
async function appendCuratorSkippedEvent(directory, record) {
|
|
10577
10832
|
try {
|
|
10578
|
-
const filePath =
|
|
10579
|
-
await mkdir5(
|
|
10833
|
+
const filePath = path22.join(directory, ".swarm", "events.jsonl");
|
|
10834
|
+
await mkdir5(path22.dirname(filePath), { recursive: true });
|
|
10580
10835
|
await appendFile2(filePath, `${JSON.stringify({
|
|
10581
10836
|
timestamp: new Date().toISOString(),
|
|
10582
10837
|
event: "curator_skipped",
|
|
@@ -10616,7 +10871,7 @@ function readInsightJsonl(content) {
|
|
|
10616
10871
|
async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BATCH_LIMIT) {
|
|
10617
10872
|
try {
|
|
10618
10873
|
const filePath = resolveInsightCandidatesPath(directory);
|
|
10619
|
-
if (!
|
|
10874
|
+
if (!existsSync11(filePath))
|
|
10620
10875
|
return [];
|
|
10621
10876
|
const consumed = [];
|
|
10622
10877
|
await transactFile(filePath, async (p) => readInsightJsonl(await readFile6(p, "utf-8").catch(() => "")), async (p, data) => {
|
|
@@ -11029,8 +11284,8 @@ var _internals17 = {
|
|
|
11029
11284
|
};
|
|
11030
11285
|
|
|
11031
11286
|
// src/services/session-reflection.ts
|
|
11032
|
-
import { promises as
|
|
11033
|
-
import * as
|
|
11287
|
+
import { promises as fs12 } from "fs";
|
|
11288
|
+
import * as path23 from "path";
|
|
11034
11289
|
|
|
11035
11290
|
// src/hooks/skill-improver-llm-factory.ts
|
|
11036
11291
|
function resolveSkillImproverAgentName(sessionId) {
|
|
@@ -11183,13 +11438,13 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
|
|
|
11183
11438
|
const lessons = [];
|
|
11184
11439
|
const taxonomy = {};
|
|
11185
11440
|
try {
|
|
11186
|
-
const evidenceDir =
|
|
11187
|
-
const entries = await
|
|
11441
|
+
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
11442
|
+
const entries = await fs12.readdir(evidenceDir);
|
|
11188
11443
|
const retroDirs = entries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
11189
11444
|
for (const retroDir of retroDirs) {
|
|
11190
|
-
const evidencePath =
|
|
11445
|
+
const evidencePath = path23.join(evidenceDir, retroDir, "evidence.json");
|
|
11191
11446
|
try {
|
|
11192
|
-
const content = await
|
|
11447
|
+
const content = await fs12.readFile(evidencePath, "utf-8");
|
|
11193
11448
|
const parsed = JSON.parse(content);
|
|
11194
11449
|
const bundleEntries = parsed.entries ?? [parsed];
|
|
11195
11450
|
for (const entry of bundleEntries) {
|
|
@@ -11216,14 +11471,14 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
|
|
|
11216
11471
|
async function gatherGateFailures(directory) {
|
|
11217
11472
|
const failures = new Map;
|
|
11218
11473
|
try {
|
|
11219
|
-
const evidenceDir =
|
|
11220
|
-
const entries = await
|
|
11474
|
+
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
11475
|
+
const entries = await fs12.readdir(evidenceDir);
|
|
11221
11476
|
for (const entry of entries) {
|
|
11222
11477
|
if (entry.startsWith("retro-"))
|
|
11223
11478
|
continue;
|
|
11224
|
-
const evidencePath =
|
|
11479
|
+
const evidencePath = path23.join(evidenceDir, entry, "evidence.json");
|
|
11225
11480
|
try {
|
|
11226
|
-
const content = await
|
|
11481
|
+
const content = await fs12.readFile(evidencePath, "utf-8");
|
|
11227
11482
|
const parsed = JSON.parse(content);
|
|
11228
11483
|
const bundleEntries = parsed.entries ?? [parsed];
|
|
11229
11484
|
for (const e of bundleEntries) {
|
|
@@ -11415,19 +11670,19 @@ async function writeSessionReflection(directory, result) {
|
|
|
11415
11670
|
lines.push(result.architectReport);
|
|
11416
11671
|
const content = lines.join(`
|
|
11417
11672
|
`);
|
|
11418
|
-
await
|
|
11673
|
+
await fs12.writeFile(reflectionPath, content, "utf-8");
|
|
11419
11674
|
return reflectionPath;
|
|
11420
11675
|
}
|
|
11421
11676
|
|
|
11422
11677
|
// src/services/skill-improver.ts
|
|
11423
|
-
import { existsSync as
|
|
11678
|
+
import { existsSync as existsSync13 } from "fs";
|
|
11424
11679
|
import { mkdir as mkdir7, readFile as readFile7, rename as rename3, writeFile as writeFile7 } from "fs/promises";
|
|
11425
|
-
import * as
|
|
11680
|
+
import * as path25 from "path";
|
|
11426
11681
|
init_logger();
|
|
11427
11682
|
|
|
11428
11683
|
// src/services/trajectory-cluster.ts
|
|
11429
11684
|
import { mkdir as mkdir6, writeFile as writeFile6 } from "fs/promises";
|
|
11430
|
-
import * as
|
|
11685
|
+
import * as path24 from "path";
|
|
11431
11686
|
init_logger();
|
|
11432
11687
|
var MACRO_TRAJECTORY_WINDOW = 200;
|
|
11433
11688
|
var MOTIF_MIN_TASKS = 2;
|
|
@@ -11559,11 +11814,11 @@ async function writeMotifProposals(directory, opts = {}) {
|
|
|
11559
11814
|
if (motifs.length === 0)
|
|
11560
11815
|
return result;
|
|
11561
11816
|
const max = opts.maxProposals ?? 10;
|
|
11562
|
-
const proposalsDir = validateSwarmPath(directory,
|
|
11817
|
+
const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
|
|
11563
11818
|
await mkdir6(proposalsDir, { recursive: true });
|
|
11564
11819
|
for (const motif of motifs.slice(0, max)) {
|
|
11565
11820
|
const slug = `motif-${slugify(motif.signature)}`;
|
|
11566
|
-
const filePath =
|
|
11821
|
+
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
11567
11822
|
await writeFile6(filePath, buildMotifProposal(motif), "utf-8");
|
|
11568
11823
|
result.proposalsWritten.push(filePath);
|
|
11569
11824
|
}
|
|
@@ -11704,11 +11959,11 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
|
|
|
11704
11959
|
if (motifs.length === 0)
|
|
11705
11960
|
return result;
|
|
11706
11961
|
const max = opts.maxProposals ?? 10;
|
|
11707
|
-
const proposalsDir = validateSwarmPath(directory,
|
|
11962
|
+
const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
|
|
11708
11963
|
await mkdir6(proposalsDir, { recursive: true });
|
|
11709
11964
|
for (const motif of motifs.slice(0, max)) {
|
|
11710
11965
|
const slug = workflowSlug(motif.signature);
|
|
11711
|
-
const filePath =
|
|
11966
|
+
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
11712
11967
|
await writeFile6(filePath, buildWorkflowProposal(motif), "utf-8");
|
|
11713
11968
|
result.proposalsWritten.push(filePath);
|
|
11714
11969
|
}
|
|
@@ -11720,14 +11975,14 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
|
|
|
11720
11975
|
}
|
|
11721
11976
|
|
|
11722
11977
|
// src/services/unactionable-hardening.ts
|
|
11723
|
-
import { existsSync as
|
|
11978
|
+
import { existsSync as existsSync12 } from "fs";
|
|
11724
11979
|
init_logger();
|
|
11725
11980
|
var HARDENING_BATCH_LIMIT = 5;
|
|
11726
11981
|
async function hardenUnactionableEntries(params) {
|
|
11727
11982
|
const result = { hardened: 0, retired: 0, remaining: 0 };
|
|
11728
11983
|
try {
|
|
11729
11984
|
const queuePath = resolveUnactionablePath(params.directory);
|
|
11730
|
-
if (!
|
|
11985
|
+
if (!existsSync12(queuePath))
|
|
11731
11986
|
return result;
|
|
11732
11987
|
const limit = params.batchLimit ?? HARDENING_BATCH_LIMIT;
|
|
11733
11988
|
const dedupThreshold = params.dedupThreshold ?? 0.6;
|
|
@@ -11831,7 +12086,7 @@ function timestampSlug(d) {
|
|
|
11831
12086
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
11832
12087
|
}
|
|
11833
12088
|
async function atomicWrite(p, content) {
|
|
11834
|
-
await mkdir7(
|
|
12089
|
+
await mkdir7(path25.dirname(p), { recursive: true });
|
|
11835
12090
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
11836
12091
|
await writeFile7(tmp, content, "utf-8");
|
|
11837
12092
|
await rename3(tmp, p);
|
|
@@ -11839,7 +12094,7 @@ async function atomicWrite(p, content) {
|
|
|
11839
12094
|
async function gatherInventory(directory) {
|
|
11840
12095
|
const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
|
|
11841
12096
|
const hivePath = resolveHiveKnowledgePath();
|
|
11842
|
-
const hive =
|
|
12097
|
+
const hive = existsSync13(hivePath) ? await readKnowledge(hivePath) : [];
|
|
11843
12098
|
const archived = [...swarm, ...hive].filter((e) => e.status === "archived").length;
|
|
11844
12099
|
const skills = await listSkills(directory);
|
|
11845
12100
|
const knowledgeById = new Map([...swarm, ...hive].map((entry) => [entry.id, entry]));
|
|
@@ -12234,8 +12489,8 @@ async function runSkillImprover(req) {
|
|
|
12234
12489
|
}
|
|
12235
12490
|
throw err;
|
|
12236
12491
|
}
|
|
12237
|
-
const proposalDir =
|
|
12238
|
-
const proposalFile =
|
|
12492
|
+
const proposalDir = path25.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
12493
|
+
const proposalFile = path25.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
12239
12494
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
12240
12495
|
body,
|
|
12241
12496
|
targets,
|
|
@@ -12718,20 +12973,20 @@ function countSessionKnowledgeEntries(entries, sessionStart, fallbackCount) {
|
|
|
12718
12973
|
async function copyDirRecursiveWithFailures(src, dest) {
|
|
12719
12974
|
let count = 0;
|
|
12720
12975
|
const failures = [];
|
|
12721
|
-
const entries = await
|
|
12722
|
-
await
|
|
12976
|
+
const entries = await fs13.readdir(src);
|
|
12977
|
+
await fs13.mkdir(dest, { recursive: true });
|
|
12723
12978
|
for (const entry of entries) {
|
|
12724
|
-
const srcEntry =
|
|
12725
|
-
const destEntry =
|
|
12979
|
+
const srcEntry = path26.join(src, entry);
|
|
12980
|
+
const destEntry = path26.join(dest, entry);
|
|
12726
12981
|
try {
|
|
12727
|
-
const stat4 = await
|
|
12982
|
+
const stat4 = await fs13.stat(srcEntry);
|
|
12728
12983
|
if (stat4.isDirectory()) {
|
|
12729
12984
|
const subResult = await copyDirRecursiveWithFailures(srcEntry, destEntry);
|
|
12730
12985
|
count += subResult.copied;
|
|
12731
12986
|
failures.push(...subResult.failures);
|
|
12732
12987
|
} else {
|
|
12733
12988
|
try {
|
|
12734
|
-
await
|
|
12989
|
+
await fs13.copyFile(srcEntry, destEntry);
|
|
12735
12990
|
count++;
|
|
12736
12991
|
} catch (err) {
|
|
12737
12992
|
const errno = err?.code;
|
|
@@ -12906,20 +13161,20 @@ async function runFinalizeStage(ctx) {
|
|
|
12906
13161
|
ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
12907
13162
|
}
|
|
12908
13163
|
}
|
|
12909
|
-
const lessonsFilePath =
|
|
13164
|
+
const lessonsFilePath = path26.join(ctx.swarmDir, "close-lessons.md");
|
|
12910
13165
|
try {
|
|
12911
|
-
const lessonsText = await
|
|
13166
|
+
const lessonsText = await fs13.readFile(lessonsFilePath, "utf-8");
|
|
12912
13167
|
ctx.explicitLessons = lessonsText.split(`
|
|
12913
13168
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12914
13169
|
} catch {}
|
|
12915
13170
|
try {
|
|
12916
|
-
const evidenceDir =
|
|
12917
|
-
const evidenceEntries = await
|
|
13171
|
+
const evidenceDir = path26.join(ctx.swarmDir, "evidence");
|
|
13172
|
+
const evidenceEntries = await fs13.readdir(evidenceDir);
|
|
12918
13173
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
12919
13174
|
for (const retroDir of retroDirs) {
|
|
12920
|
-
const evidencePath =
|
|
13175
|
+
const evidencePath = path26.join(evidenceDir, retroDir, "evidence.json");
|
|
12921
13176
|
try {
|
|
12922
|
-
const content = await
|
|
13177
|
+
const content = await fs13.readFile(evidencePath, "utf-8");
|
|
12923
13178
|
const parsed = JSON.parse(content);
|
|
12924
13179
|
const entries = parsed.entries ?? [parsed];
|
|
12925
13180
|
for (const entry of entries) {
|
|
@@ -12963,7 +13218,7 @@ async function runFinalizeStage(ctx) {
|
|
|
12963
13218
|
console.warn("[close-command] curateAndStoreSwarm error:", error2);
|
|
12964
13219
|
}
|
|
12965
13220
|
if (ctx.curationSucceeded && ctx.allLessons.length > 0) {
|
|
12966
|
-
await
|
|
13221
|
+
await fs13.unlink(lessonsFilePath).catch(() => {});
|
|
12967
13222
|
}
|
|
12968
13223
|
if (ctx.curationSucceeded) {
|
|
12969
13224
|
if (ctx.config.hive_enabled === false) {} else {
|
|
@@ -13069,7 +13324,7 @@ async function runFinalizeStage(ctx) {
|
|
|
13069
13324
|
}
|
|
13070
13325
|
}
|
|
13071
13326
|
try {
|
|
13072
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
13327
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-nz638xc3.js");
|
|
13073
13328
|
const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
|
|
13074
13329
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
13075
13330
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -13099,7 +13354,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
13099
13354
|
let checkpointVerified = false;
|
|
13100
13355
|
try {
|
|
13101
13356
|
const result = spawnSync5("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
13102
|
-
cwd:
|
|
13357
|
+
cwd: path26.dirname(srcPath),
|
|
13103
13358
|
encoding: "utf-8",
|
|
13104
13359
|
stdio: ["ignore", "pipe", "pipe"],
|
|
13105
13360
|
timeout: 1e4,
|
|
@@ -13110,7 +13365,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
13110
13365
|
const code = result.error.code;
|
|
13111
13366
|
if (code === "ENOENT") {
|
|
13112
13367
|
try {
|
|
13113
|
-
await
|
|
13368
|
+
await fs13.copyFile(srcPath, destPath);
|
|
13114
13369
|
return {
|
|
13115
13370
|
success: true,
|
|
13116
13371
|
reason: "copied without WAL checkpoint (sqlite3 CLI unavailable)"
|
|
@@ -13149,7 +13404,7 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
13149
13404
|
};
|
|
13150
13405
|
}
|
|
13151
13406
|
try {
|
|
13152
|
-
await
|
|
13407
|
+
await fs13.copyFile(srcPath, destPath);
|
|
13153
13408
|
if (checkpointVerified) {
|
|
13154
13409
|
return { success: true };
|
|
13155
13410
|
}
|
|
@@ -13167,9 +13422,9 @@ async function copySqliteSafe(srcPath, destPath) {
|
|
|
13167
13422
|
async function runArchiveStage(ctx) {
|
|
13168
13423
|
ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
13169
13424
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
13170
|
-
ctx.archiveDir =
|
|
13425
|
+
ctx.archiveDir = path26.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
13171
13426
|
try {
|
|
13172
|
-
await
|
|
13427
|
+
await fs13.mkdir(ctx.archiveDir, { recursive: true });
|
|
13173
13428
|
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
13174
13429
|
const linkedKnowledgeShared = isLinked(ctx.directory);
|
|
13175
13430
|
if (linkedKnowledgeShared) {
|
|
@@ -13182,8 +13437,8 @@ async function runArchiveStage(ctx) {
|
|
|
13182
13437
|
if (linkedKnowledgeShared && KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact)) {
|
|
13183
13438
|
continue;
|
|
13184
13439
|
}
|
|
13185
|
-
const srcPath =
|
|
13186
|
-
const destPath =
|
|
13440
|
+
const srcPath = path26.join(ctx.swarmDir, artifact);
|
|
13441
|
+
const destPath = path26.join(ctx.archiveDir, artifact);
|
|
13187
13442
|
if (artifact === "swarm.db") {
|
|
13188
13443
|
const result = await copySqliteSafe(srcPath, destPath);
|
|
13189
13444
|
if (result.skipped) {} else if (result.success) {
|
|
@@ -13199,7 +13454,7 @@ async function runArchiveStage(ctx) {
|
|
|
13199
13454
|
}
|
|
13200
13455
|
} else {
|
|
13201
13456
|
try {
|
|
13202
|
-
await
|
|
13457
|
+
await fs13.copyFile(srcPath, destPath);
|
|
13203
13458
|
ctx.archivedFileCount++;
|
|
13204
13459
|
if (ACTIVE_STATE_TO_CLEAN.includes(artifact)) {
|
|
13205
13460
|
ctx.archivedActiveStateFiles.add(artifact);
|
|
@@ -13215,8 +13470,8 @@ async function runArchiveStage(ctx) {
|
|
|
13215
13470
|
}
|
|
13216
13471
|
}
|
|
13217
13472
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
13218
|
-
const srcDir =
|
|
13219
|
-
const destDir =
|
|
13473
|
+
const srcDir = path26.join(ctx.swarmDir, dirName);
|
|
13474
|
+
const destDir = path26.join(ctx.archiveDir, dirName);
|
|
13220
13475
|
try {
|
|
13221
13476
|
const result = await copyDirRecursiveWithFailures(srcDir, destDir);
|
|
13222
13477
|
ctx.archivedFileCount += result.copied;
|
|
@@ -13289,9 +13544,9 @@ async function runCleanStage(ctx) {
|
|
|
13289
13544
|
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
13290
13545
|
continue;
|
|
13291
13546
|
}
|
|
13292
|
-
const filePath =
|
|
13547
|
+
const filePath = path26.join(ctx.swarmDir, artifact);
|
|
13293
13548
|
try {
|
|
13294
|
-
await
|
|
13549
|
+
await fs13.unlink(filePath);
|
|
13295
13550
|
cleanedFiles.push(artifact);
|
|
13296
13551
|
} catch (err) {
|
|
13297
13552
|
const errno = err?.code;
|
|
@@ -13308,18 +13563,18 @@ async function runCleanStage(ctx) {
|
|
|
13308
13563
|
if (!ctx.archivedActiveStateDirs.has(dirName)) {
|
|
13309
13564
|
continue;
|
|
13310
13565
|
}
|
|
13311
|
-
const dirPath =
|
|
13566
|
+
const dirPath = path26.join(ctx.swarmDir, dirName);
|
|
13312
13567
|
try {
|
|
13313
|
-
await
|
|
13568
|
+
await fs13.rm(dirPath, { recursive: true, force: true });
|
|
13314
13569
|
cleanedFiles.push(`${dirName}/`);
|
|
13315
13570
|
} catch {}
|
|
13316
13571
|
}
|
|
13317
13572
|
try {
|
|
13318
|
-
const swarmFiles = await
|
|
13573
|
+
const swarmFiles = await fs13.readdir(ctx.swarmDir);
|
|
13319
13574
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
13320
13575
|
for (const backup of configBackups) {
|
|
13321
13576
|
try {
|
|
13322
|
-
await
|
|
13577
|
+
await fs13.unlink(path26.join(ctx.swarmDir, backup));
|
|
13323
13578
|
configBackupsRemoved++;
|
|
13324
13579
|
} catch (err) {
|
|
13325
13580
|
const errno = err?.code;
|
|
@@ -13332,7 +13587,7 @@ async function runCleanStage(ctx) {
|
|
|
13332
13587
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
13333
13588
|
for (const sibling of ledgerSiblings) {
|
|
13334
13589
|
try {
|
|
13335
|
-
await
|
|
13590
|
+
await fs13.unlink(path26.join(ctx.swarmDir, sibling));
|
|
13336
13591
|
} catch (err) {
|
|
13337
13592
|
const errno = err?.code;
|
|
13338
13593
|
if (errno === "ENOENT") {} else {
|
|
@@ -13350,16 +13605,16 @@ async function runCleanStage(ctx) {
|
|
|
13350
13605
|
}
|
|
13351
13606
|
let swarmPlanFilesRemoved = 0;
|
|
13352
13607
|
const candidates = [
|
|
13353
|
-
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13608
|
+
path26.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
|
|
13609
|
+
path26.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
|
|
13610
|
+
path26.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
|
|
13611
|
+
path26.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
|
|
13612
|
+
path26.join(ctx.directory, "SWARM_PLAN.json"),
|
|
13613
|
+
path26.join(ctx.directory, "SWARM_PLAN.md")
|
|
13359
13614
|
];
|
|
13360
13615
|
for (const candidate of candidates) {
|
|
13361
13616
|
try {
|
|
13362
|
-
await
|
|
13617
|
+
await fs13.unlink(candidate);
|
|
13363
13618
|
swarmPlanFilesRemoved++;
|
|
13364
13619
|
} catch (err) {
|
|
13365
13620
|
if (err?.code !== "ENOENT") {
|
|
@@ -13369,11 +13624,11 @@ async function runCleanStage(ctx) {
|
|
|
13369
13624
|
}
|
|
13370
13625
|
let tmpFilesRemoved = 0;
|
|
13371
13626
|
try {
|
|
13372
|
-
const swarmFiles = await
|
|
13627
|
+
const swarmFiles = await fs13.readdir(ctx.swarmDir);
|
|
13373
13628
|
const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
|
|
13374
13629
|
for (const tmp of tmpFiles) {
|
|
13375
13630
|
try {
|
|
13376
|
-
await
|
|
13631
|
+
await fs13.unlink(path26.join(ctx.swarmDir, tmp));
|
|
13377
13632
|
tmpFilesRemoved++;
|
|
13378
13633
|
} catch (err) {
|
|
13379
13634
|
const errno = err?.code;
|
|
@@ -13394,7 +13649,7 @@ async function runCleanStage(ctx) {
|
|
|
13394
13649
|
cleanedFiles.push(`${tmpFilesRemoved} .tmp.* file(s)`);
|
|
13395
13650
|
}
|
|
13396
13651
|
clearAllScopes(ctx.directory);
|
|
13397
|
-
const contextPath =
|
|
13652
|
+
const contextPath = path26.join(ctx.swarmDir, "context.md");
|
|
13398
13653
|
const contextContent = [
|
|
13399
13654
|
"# Context",
|
|
13400
13655
|
"",
|
|
@@ -13406,9 +13661,9 @@ async function runCleanStage(ctx) {
|
|
|
13406
13661
|
""
|
|
13407
13662
|
].join(`
|
|
13408
13663
|
`);
|
|
13409
|
-
const contextTempPath =
|
|
13664
|
+
const contextTempPath = path26.join(path26.dirname(contextPath), `${path26.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
13410
13665
|
try {
|
|
13411
|
-
await
|
|
13666
|
+
await fs13.writeFile(contextTempPath, contextContent, "utf-8");
|
|
13412
13667
|
fsSync2.renameSync(contextTempPath, contextPath);
|
|
13413
13668
|
} catch (error2) {
|
|
13414
13669
|
try {
|
|
@@ -13470,7 +13725,7 @@ async function runAlignStage(ctx) {
|
|
|
13470
13725
|
return { gitAlignResult, prunedBranches };
|
|
13471
13726
|
}
|
|
13472
13727
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
13473
|
-
const swarmDir =
|
|
13728
|
+
const swarmDir = path26.join(directory, ".swarm");
|
|
13474
13729
|
try {
|
|
13475
13730
|
const stat4 = fsSync2.lstatSync(swarmDir);
|
|
13476
13731
|
if (stat4.isSymbolicLink()) {
|
|
@@ -13484,18 +13739,18 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
13484
13739
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
13485
13740
|
let planExists = false;
|
|
13486
13741
|
let planData = {
|
|
13487
|
-
title:
|
|
13742
|
+
title: path26.basename(directory) || "Ad-hoc session",
|
|
13488
13743
|
phases: []
|
|
13489
13744
|
};
|
|
13490
13745
|
try {
|
|
13491
|
-
const content = await
|
|
13746
|
+
const content = await fs13.readFile(planPath, "utf-8");
|
|
13492
13747
|
planData = JSON.parse(content);
|
|
13493
13748
|
planExists = true;
|
|
13494
13749
|
} catch (error2) {
|
|
13495
13750
|
if (error2?.code !== "ENOENT") {
|
|
13496
13751
|
return `\u274C Failed to read plan.json: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
13497
13752
|
}
|
|
13498
|
-
const swarmDirExists = await
|
|
13753
|
+
const swarmDirExists = await fs13.access(swarmDir).then(() => true).catch(() => false);
|
|
13499
13754
|
if (!swarmDirExists) {
|
|
13500
13755
|
return `\u274C No .swarm/ directory found in ${directory}. Run /swarm close from the project root, or run /swarm plan first.`;
|
|
13501
13756
|
}
|
|
@@ -13509,15 +13764,15 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
13509
13764
|
}
|
|
13510
13765
|
try {
|
|
13511
13766
|
if (!planExists) {
|
|
13512
|
-
const archiveDir =
|
|
13767
|
+
const archiveDir = path26.join(swarmDir, "archive");
|
|
13513
13768
|
try {
|
|
13514
|
-
const archiveEntries = await
|
|
13769
|
+
const archiveEntries = await fs13.readdir(archiveDir);
|
|
13515
13770
|
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
13516
13771
|
if (hasArchiveBundle) {
|
|
13517
13772
|
const hasActiveState = [
|
|
13518
13773
|
...ACTIVE_STATE_TO_CLEAN,
|
|
13519
13774
|
...ACTIVE_STATE_DIRS_TO_CLEAN
|
|
13520
|
-
].some((entry) => fsSync2.existsSync(
|
|
13775
|
+
].some((entry) => fsSync2.existsSync(path26.join(swarmDir, entry)));
|
|
13521
13776
|
if (!hasActiveState) {
|
|
13522
13777
|
return `\u2705 Already finalized \u2014 nothing to do.
|
|
13523
13778
|
|
|
@@ -13640,9 +13895,9 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
13640
13895
|
...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
|
|
13641
13896
|
].join(`
|
|
13642
13897
|
`);
|
|
13643
|
-
const closeSummaryTempPath =
|
|
13898
|
+
const closeSummaryTempPath = path26.join(path26.dirname(closeSummaryPath), `${path26.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
13644
13899
|
try {
|
|
13645
|
-
await
|
|
13900
|
+
await fs13.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
13646
13901
|
fsSync2.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
13647
13902
|
} catch (error2) {
|
|
13648
13903
|
try {
|
|
@@ -13652,6 +13907,10 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
13652
13907
|
ctx.warnings.push(`Failed to write close-summary.md: ${msg}`);
|
|
13653
13908
|
console.warn("[close-command] Failed to write close-summary.md:", error2);
|
|
13654
13909
|
}
|
|
13910
|
+
const sessionIdsToEnd = [...swarmState.agentSessions.keys()];
|
|
13911
|
+
for (const sessionId of sessionIdsToEnd) {
|
|
13912
|
+
_internals20.endAgentSession(sessionId);
|
|
13913
|
+
}
|
|
13655
13914
|
_internals20.resetSwarmStatePreservingSingletons();
|
|
13656
13915
|
const retroWarnings = ctx.warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
|
|
13657
13916
|
const otherWarnings = ctx.warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
|
|
@@ -13744,7 +14003,8 @@ var _internals20 = {
|
|
|
13744
14003
|
runCleanStage,
|
|
13745
14004
|
runAlignStage,
|
|
13746
14005
|
archiveEvidence,
|
|
13747
|
-
closePlanTerminalState
|
|
14006
|
+
closePlanTerminalState,
|
|
14007
|
+
endAgentSession
|
|
13748
14008
|
};
|
|
13749
14009
|
|
|
13750
14010
|
// src/commands/codebase-review.ts
|
|
@@ -13977,15 +14237,15 @@ function buildStatusMessage(session, plan) {
|
|
|
13977
14237
|
}
|
|
13978
14238
|
|
|
13979
14239
|
// src/commands/config.ts
|
|
13980
|
-
import * as
|
|
13981
|
-
import * as
|
|
14240
|
+
import * as os7 from "os";
|
|
14241
|
+
import * as path27 from "path";
|
|
13982
14242
|
function getUserConfigDir2() {
|
|
13983
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
14243
|
+
return process.env.XDG_CONFIG_HOME || path27.join(os7.homedir(), ".config");
|
|
13984
14244
|
}
|
|
13985
14245
|
async function handleConfigCommand(directory, _args) {
|
|
13986
14246
|
const config = loadPluginConfig(directory);
|
|
13987
|
-
const userConfigPath =
|
|
13988
|
-
const projectConfigPath =
|
|
14247
|
+
const userConfigPath = path27.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
14248
|
+
const projectConfigPath = path27.join(directory, ".opencode", "opencode-swarm.json");
|
|
13989
14249
|
const lines = [
|
|
13990
14250
|
"## Swarm Configuration",
|
|
13991
14251
|
"",
|
|
@@ -14003,9 +14263,9 @@ async function handleConfigCommand(directory, _args) {
|
|
|
14003
14263
|
}
|
|
14004
14264
|
|
|
14005
14265
|
// src/services/skill-consolidation.ts
|
|
14006
|
-
import { existsSync as
|
|
14266
|
+
import { existsSync as existsSync15 } from "fs";
|
|
14007
14267
|
import { mkdir as mkdir8, readFile as readFile8, rename as rename4, writeFile as writeFile8 } from "fs/promises";
|
|
14008
|
-
import * as
|
|
14268
|
+
import * as path28 from "path";
|
|
14009
14269
|
|
|
14010
14270
|
// src/utils/timeout.ts
|
|
14011
14271
|
async function withTimeout(promise, ms, timeoutError) {
|
|
@@ -14030,11 +14290,11 @@ var DEFAULT_CONSOLIDATION_MAX_CALLS_PER_RUN = 1;
|
|
|
14030
14290
|
var CONSOLIDATION_RUN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
14031
14291
|
var runningByDirectory = new Map;
|
|
14032
14292
|
function consolidationStatePath(directory) {
|
|
14033
|
-
return
|
|
14293
|
+
return path28.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
|
|
14034
14294
|
}
|
|
14035
14295
|
async function readState2(directory) {
|
|
14036
14296
|
const filePath = consolidationStatePath(directory);
|
|
14037
|
-
if (!
|
|
14297
|
+
if (!existsSync15(filePath))
|
|
14038
14298
|
return {};
|
|
14039
14299
|
try {
|
|
14040
14300
|
const parsed = JSON.parse(await readFile8(filePath, "utf-8"));
|
|
@@ -14046,7 +14306,7 @@ async function readState2(directory) {
|
|
|
14046
14306
|
}
|
|
14047
14307
|
}
|
|
14048
14308
|
async function atomicWrite2(filePath, content) {
|
|
14049
|
-
await mkdir8(
|
|
14309
|
+
await mkdir8(path28.dirname(filePath), { recursive: true });
|
|
14050
14310
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
14051
14311
|
await writeFile8(tmp, content, "utf-8");
|
|
14052
14312
|
await rename4(tmp, filePath);
|
|
@@ -14126,7 +14386,7 @@ async function runSkillConsolidationInner(req) {
|
|
|
14126
14386
|
};
|
|
14127
14387
|
}
|
|
14128
14388
|
async function runSkillConsolidation(req) {
|
|
14129
|
-
const key =
|
|
14389
|
+
const key = path28.resolve(req.directory);
|
|
14130
14390
|
const existing = runningByDirectory.get(key);
|
|
14131
14391
|
if (existing) {
|
|
14132
14392
|
return {
|
|
@@ -14208,6 +14468,55 @@ async function handleConsolidateCommand(directory, args, options = {}) {
|
|
|
14208
14468
|
}
|
|
14209
14469
|
}
|
|
14210
14470
|
|
|
14471
|
+
// src/commands/costs.ts
|
|
14472
|
+
async function handleCostsCommand(directory, args) {
|
|
14473
|
+
const summary = summarizeTelemetryCosts(directory);
|
|
14474
|
+
const json = args.includes("--json");
|
|
14475
|
+
if (json) {
|
|
14476
|
+
return [
|
|
14477
|
+
"[COSTS_JSON]",
|
|
14478
|
+
JSON.stringify(summary, null, 2),
|
|
14479
|
+
"[/COSTS_JSON]"
|
|
14480
|
+
].join(`
|
|
14481
|
+
`);
|
|
14482
|
+
}
|
|
14483
|
+
return renderCostSummary(summary);
|
|
14484
|
+
}
|
|
14485
|
+
function renderCostSummary(summary) {
|
|
14486
|
+
const lines = [
|
|
14487
|
+
"## Swarm Costs",
|
|
14488
|
+
"",
|
|
14489
|
+
`Total tracked cost: ${formatUsd(summary.total_cost_usd)}`,
|
|
14490
|
+
`Delegations: ${summary.delegations}`,
|
|
14491
|
+
`Tokens: input ${summary.total_input_tokens.toLocaleString()}, output ${summary.total_output_tokens.toLocaleString()}, reasoning ${summary.total_reasoning_tokens.toLocaleString()}, cache ${summary.total_cache_tokens.toLocaleString()}`,
|
|
14492
|
+
`Cost source: reported ${formatUsd(summary.total_reported_usd)}, estimated ${formatUsd(summary.total_estimated_usd)}, unavailable ${summary.unavailable_delegations}`,
|
|
14493
|
+
"",
|
|
14494
|
+
"### By Agent"
|
|
14495
|
+
];
|
|
14496
|
+
appendCostRows(lines, "Agent", summary.by_agent, "No delegation cost telemetry recorded.");
|
|
14497
|
+
lines.push("", "### By Task");
|
|
14498
|
+
appendCostRows(lines, "Task", summary.by_task, "No task cost telemetry recorded.");
|
|
14499
|
+
lines.push("", "### By Gate");
|
|
14500
|
+
appendCostRows(lines, "Gate", summary.by_gate, "No gate cost telemetry recorded.");
|
|
14501
|
+
lines.push("", "### By Retry Loop");
|
|
14502
|
+
appendCostRows(lines, "Retry", summary.by_retry, "No retry-loop cost telemetry recorded.");
|
|
14503
|
+
return lines.join(`
|
|
14504
|
+
`);
|
|
14505
|
+
}
|
|
14506
|
+
function appendCostRows(lines, label, rows, emptyMessage) {
|
|
14507
|
+
if (rows.length === 0) {
|
|
14508
|
+
lines.push(emptyMessage);
|
|
14509
|
+
return;
|
|
14510
|
+
}
|
|
14511
|
+
lines.push(`| ${label} | Delegations | Cost | Input | Output | Reasoning | Cache | Unavailable |`, "|------|-------------|------|-------|--------|-----------|-------|-------------|");
|
|
14512
|
+
for (const row of rows) {
|
|
14513
|
+
lines.push(`| ${row.name} | ${row.delegations} | ${formatUsd(row.cost_usd)} | ${row.input_tokens.toLocaleString()} | ${row.output_tokens.toLocaleString()} | ${row.reasoning_tokens.toLocaleString()} | ${row.cache_tokens.toLocaleString()} | ${row.unavailable_delegations} |`);
|
|
14514
|
+
}
|
|
14515
|
+
}
|
|
14516
|
+
function formatUsd(value) {
|
|
14517
|
+
return `$${value.toFixed(6)}`;
|
|
14518
|
+
}
|
|
14519
|
+
|
|
14211
14520
|
// src/commands/council.ts
|
|
14212
14521
|
var MAX_QUESTION_LEN = 2000;
|
|
14213
14522
|
function sanitizeQuestion(raw) {
|
|
@@ -14278,8 +14587,8 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
14278
14587
|
|
|
14279
14588
|
// src/commands/coupling.ts
|
|
14280
14589
|
import { randomBytes } from "crypto";
|
|
14281
|
-
import * as
|
|
14282
|
-
import * as
|
|
14590
|
+
import * as fs14 from "fs";
|
|
14591
|
+
import * as path30 from "path";
|
|
14283
14592
|
|
|
14284
14593
|
// src/turbo/epic/cochange-source.ts
|
|
14285
14594
|
import * as child_process3 from "child_process";
|
|
@@ -14289,7 +14598,7 @@ import { promisify as promisify2 } from "util";
|
|
|
14289
14598
|
import * as child_process2 from "child_process";
|
|
14290
14599
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
14291
14600
|
import { readdir as readdir4, readFile as readFile9, stat as stat4 } from "fs/promises";
|
|
14292
|
-
import * as
|
|
14601
|
+
import * as path29 from "path";
|
|
14293
14602
|
import { promisify } from "util";
|
|
14294
14603
|
function getExecFileAsync() {
|
|
14295
14604
|
return promisify(child_process2.execFile);
|
|
@@ -14393,7 +14702,7 @@ async function scanSourceFiles(dir) {
|
|
|
14393
14702
|
try {
|
|
14394
14703
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
14395
14704
|
for (const entry of entries) {
|
|
14396
|
-
const fullPath =
|
|
14705
|
+
const fullPath = path29.join(dir, entry.name);
|
|
14397
14706
|
if (entry.isDirectory()) {
|
|
14398
14707
|
if (skipDirs.has(entry.name)) {
|
|
14399
14708
|
continue;
|
|
@@ -14401,7 +14710,7 @@ async function scanSourceFiles(dir) {
|
|
|
14401
14710
|
const subFiles = await scanSourceFiles(fullPath);
|
|
14402
14711
|
results.push(...subFiles);
|
|
14403
14712
|
} else if (entry.isFile()) {
|
|
14404
|
-
const ext =
|
|
14713
|
+
const ext = path29.extname(entry.name);
|
|
14405
14714
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
14406
14715
|
results.push(fullPath);
|
|
14407
14716
|
}
|
|
@@ -14423,8 +14732,8 @@ async function getStaticEdges(directory) {
|
|
|
14423
14732
|
continue;
|
|
14424
14733
|
}
|
|
14425
14734
|
try {
|
|
14426
|
-
const sourceDir =
|
|
14427
|
-
const resolvedPath =
|
|
14735
|
+
const sourceDir = path29.dirname(sourceFile);
|
|
14736
|
+
const resolvedPath = path29.resolve(sourceDir, importPath);
|
|
14428
14737
|
const extensions = [
|
|
14429
14738
|
"",
|
|
14430
14739
|
".ts",
|
|
@@ -14449,8 +14758,8 @@ async function getStaticEdges(directory) {
|
|
|
14449
14758
|
if (!targetFile) {
|
|
14450
14759
|
continue;
|
|
14451
14760
|
}
|
|
14452
|
-
const relSource =
|
|
14453
|
-
const relTarget =
|
|
14761
|
+
const relSource = path29.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
14762
|
+
const relTarget = path29.relative(directory, targetFile).replace(/\\/g, "/");
|
|
14454
14763
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
14455
14764
|
edges.add(key);
|
|
14456
14765
|
} catch {}
|
|
@@ -14462,7 +14771,7 @@ async function getStaticEdges(directory) {
|
|
|
14462
14771
|
function isTestImplementationPair(fileA, fileB) {
|
|
14463
14772
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
14464
14773
|
const getBaseName = (filePath) => {
|
|
14465
|
-
const base =
|
|
14774
|
+
const base = path29.basename(filePath);
|
|
14466
14775
|
for (const pattern of testPatterns) {
|
|
14467
14776
|
if (base.endsWith(pattern)) {
|
|
14468
14777
|
return base.slice(0, -pattern.length);
|
|
@@ -14472,16 +14781,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
14472
14781
|
};
|
|
14473
14782
|
const baseA = getBaseName(fileA);
|
|
14474
14783
|
const baseB = getBaseName(fileB);
|
|
14475
|
-
return baseA === baseB && baseA !==
|
|
14784
|
+
return baseA === baseB && baseA !== path29.basename(fileA) && baseA !== path29.basename(fileB);
|
|
14476
14785
|
}
|
|
14477
14786
|
function hasSharedPrefix(fileA, fileB) {
|
|
14478
|
-
const dirA =
|
|
14479
|
-
const dirB =
|
|
14787
|
+
const dirA = path29.dirname(fileA);
|
|
14788
|
+
const dirB = path29.dirname(fileB);
|
|
14480
14789
|
if (dirA !== dirB) {
|
|
14481
14790
|
return false;
|
|
14482
14791
|
}
|
|
14483
|
-
const baseA =
|
|
14484
|
-
const baseB =
|
|
14792
|
+
const baseA = path29.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
14793
|
+
const baseB = path29.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
14485
14794
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
14486
14795
|
return true;
|
|
14487
14796
|
}
|
|
@@ -14536,8 +14845,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
14536
14845
|
const entries = [];
|
|
14537
14846
|
const now = new Date().toISOString();
|
|
14538
14847
|
for (const pair of pairs.slice(0, 10)) {
|
|
14539
|
-
const baseA =
|
|
14540
|
-
const baseB =
|
|
14848
|
+
const baseA = path29.basename(pair.fileA);
|
|
14849
|
+
const baseB = path29.basename(pair.fileB);
|
|
14541
14850
|
let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
14542
14851
|
if (lesson.length > 280) {
|
|
14543
14852
|
lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
|
|
@@ -14963,17 +15272,17 @@ function parseArgs3(args) {
|
|
|
14963
15272
|
return parsed;
|
|
14964
15273
|
}
|
|
14965
15274
|
function persistReportJson(directory, report) {
|
|
14966
|
-
const epicDir =
|
|
14967
|
-
|
|
14968
|
-
const filePath =
|
|
15275
|
+
const epicDir = path30.join(directory, ".swarm", "epic");
|
|
15276
|
+
fs14.mkdirSync(epicDir, { recursive: true });
|
|
15277
|
+
const filePath = path30.join(epicDir, "coupling-report.json");
|
|
14969
15278
|
const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
|
|
14970
|
-
|
|
15279
|
+
fs14.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
|
|
14971
15280
|
`, "utf-8");
|
|
14972
15281
|
try {
|
|
14973
|
-
|
|
15282
|
+
fs14.renameSync(tmpPath, filePath);
|
|
14974
15283
|
} catch (err) {
|
|
14975
15284
|
try {
|
|
14976
|
-
|
|
15285
|
+
fs14.unlinkSync(tmpPath);
|
|
14977
15286
|
} catch {}
|
|
14978
15287
|
throw err;
|
|
14979
15288
|
}
|
|
@@ -15024,7 +15333,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
15024
15333
|
persistStatus = {
|
|
15025
15334
|
requested: true,
|
|
15026
15335
|
written: true,
|
|
15027
|
-
path:
|
|
15336
|
+
path: path30.relative(directory, writtenAt)
|
|
15028
15337
|
};
|
|
15029
15338
|
} catch (err) {
|
|
15030
15339
|
persistStatus = {
|
|
@@ -15083,7 +15392,7 @@ function formatCurationSummary(summary) {
|
|
|
15083
15392
|
}
|
|
15084
15393
|
|
|
15085
15394
|
// src/commands/dark-matter.ts
|
|
15086
|
-
import
|
|
15395
|
+
import path31 from "path";
|
|
15087
15396
|
async function handleDarkMatterCommand(directory, args) {
|
|
15088
15397
|
const options = {};
|
|
15089
15398
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -15115,7 +15424,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
15115
15424
|
const output = formatDarkMatterOutput(pairs);
|
|
15116
15425
|
if (pairs.length > 0) {
|
|
15117
15426
|
try {
|
|
15118
|
-
const projectName =
|
|
15427
|
+
const projectName = path31.basename(path31.resolve(directory));
|
|
15119
15428
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
15120
15429
|
if (entries.length > 0) {
|
|
15121
15430
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -15481,50 +15790,50 @@ ${USAGE5}`;
|
|
|
15481
15790
|
|
|
15482
15791
|
// src/services/diagnose-service.ts
|
|
15483
15792
|
import * as child_process4 from "child_process";
|
|
15484
|
-
import { existsSync as
|
|
15485
|
-
import
|
|
15793
|
+
import { existsSync as existsSync18, readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
15794
|
+
import path33 from "path";
|
|
15486
15795
|
import { fileURLToPath } from "url";
|
|
15487
15796
|
|
|
15488
15797
|
// src/config/cache-paths.ts
|
|
15489
|
-
import * as
|
|
15490
|
-
import * as
|
|
15798
|
+
import * as os8 from "os";
|
|
15799
|
+
import * as path32 from "path";
|
|
15491
15800
|
function getPluginConfigDir() {
|
|
15492
|
-
return
|
|
15801
|
+
return path32.join(process.env.XDG_CONFIG_HOME || path32.join(os8.homedir(), ".config"), "opencode");
|
|
15493
15802
|
}
|
|
15494
15803
|
function getPluginCachePaths() {
|
|
15495
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
15804
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path32.join(os8.homedir(), ".cache");
|
|
15496
15805
|
const configDir = getPluginConfigDir();
|
|
15497
15806
|
const paths = [
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15807
|
+
path32.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
15808
|
+
path32.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
15809
|
+
path32.join(configDir, "node_modules", "opencode-swarm")
|
|
15501
15810
|
];
|
|
15502
15811
|
if (process.platform === "darwin") {
|
|
15503
|
-
const libCaches =
|
|
15504
|
-
paths.push(
|
|
15812
|
+
const libCaches = path32.join(os8.homedir(), "Library", "Caches");
|
|
15813
|
+
paths.push(path32.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path32.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
15505
15814
|
}
|
|
15506
15815
|
if (process.platform === "win32") {
|
|
15507
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
15508
|
-
const appData = process.env.APPDATA ||
|
|
15509
|
-
paths.push(
|
|
15816
|
+
const localAppData = process.env.LOCALAPPDATA || path32.join(os8.homedir(), "AppData", "Local");
|
|
15817
|
+
const appData = process.env.APPDATA || path32.join(os8.homedir(), "AppData", "Roaming");
|
|
15818
|
+
paths.push(path32.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path32.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path32.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
15510
15819
|
}
|
|
15511
15820
|
return paths;
|
|
15512
15821
|
}
|
|
15513
15822
|
function getPluginLockFilePaths() {
|
|
15514
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
15823
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path32.join(os8.homedir(), ".cache");
|
|
15515
15824
|
const configDir = getPluginConfigDir();
|
|
15516
15825
|
const paths = [
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15826
|
+
path32.join(cacheBase, "opencode", "bun.lock"),
|
|
15827
|
+
path32.join(cacheBase, "opencode", "bun.lockb"),
|
|
15828
|
+
path32.join(configDir, "package-lock.json")
|
|
15520
15829
|
];
|
|
15521
15830
|
if (process.platform === "darwin") {
|
|
15522
|
-
const libCaches =
|
|
15523
|
-
paths.push(
|
|
15831
|
+
const libCaches = path32.join(os8.homedir(), "Library", "Caches");
|
|
15832
|
+
paths.push(path32.join(libCaches, "opencode", "bun.lock"), path32.join(libCaches, "opencode", "bun.lockb"));
|
|
15524
15833
|
}
|
|
15525
15834
|
if (process.platform === "win32") {
|
|
15526
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
15527
|
-
paths.push(
|
|
15835
|
+
const localAppData = process.env.LOCALAPPDATA || path32.join(os8.homedir(), "AppData", "Local");
|
|
15836
|
+
paths.push(path32.join(localAppData, "opencode", "bun.lock"), path32.join(localAppData, "opencode", "bun.lockb"));
|
|
15528
15837
|
}
|
|
15529
15838
|
return paths;
|
|
15530
15839
|
}
|
|
@@ -15534,28 +15843,28 @@ init_capability_probe();
|
|
|
15534
15843
|
init_executor();
|
|
15535
15844
|
|
|
15536
15845
|
// src/services/knowledge-diagnostics.ts
|
|
15537
|
-
import { existsSync as
|
|
15846
|
+
import { existsSync as existsSync17 } from "fs";
|
|
15538
15847
|
import { readFile as readFile10 } from "fs/promises";
|
|
15539
15848
|
|
|
15540
15849
|
// src/services/version-check.ts
|
|
15541
|
-
import { existsSync as
|
|
15850
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
15542
15851
|
import { homedir as homedir4 } from "os";
|
|
15543
|
-
import { join as
|
|
15852
|
+
import { join as join27 } from "path";
|
|
15544
15853
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
15545
15854
|
function cacheDir() {
|
|
15546
15855
|
const xdg = process.env.XDG_CACHE_HOME;
|
|
15547
|
-
const base = xdg && xdg.length > 0 ? xdg :
|
|
15548
|
-
return
|
|
15856
|
+
const base = xdg && xdg.length > 0 ? xdg : join27(homedir4(), ".cache");
|
|
15857
|
+
return join27(base, "opencode-swarm");
|
|
15549
15858
|
}
|
|
15550
15859
|
function cacheFile() {
|
|
15551
|
-
return
|
|
15860
|
+
return join27(cacheDir(), "version-check.json");
|
|
15552
15861
|
}
|
|
15553
15862
|
function readVersionCache() {
|
|
15554
15863
|
try {
|
|
15555
|
-
const
|
|
15556
|
-
if (!
|
|
15864
|
+
const path33 = cacheFile();
|
|
15865
|
+
if (!existsSync16(path33))
|
|
15557
15866
|
return null;
|
|
15558
|
-
const raw =
|
|
15867
|
+
const raw = readFileSync9(path33, "utf-8");
|
|
15559
15868
|
const parsed = JSON.parse(raw);
|
|
15560
15869
|
if (typeof parsed?.checkedAt !== "number")
|
|
15561
15870
|
return null;
|
|
@@ -15594,7 +15903,7 @@ var SEVEN_DAYS_MS2 = 7 * 24 * 60 * 60 * 1000;
|
|
|
15594
15903
|
var UNACTIONABLE_BACKLOG_WARN = 100;
|
|
15595
15904
|
var INSIGHT_BACKLOG_WARN = 50;
|
|
15596
15905
|
async function readRawLines(filePath) {
|
|
15597
|
-
if (!
|
|
15906
|
+
if (!existsSync17(filePath))
|
|
15598
15907
|
return { entries: [], corrupt: 0 };
|
|
15599
15908
|
const content = await readFile10(filePath, "utf-8");
|
|
15600
15909
|
const entries = [];
|
|
@@ -15719,7 +16028,7 @@ async function computeKnowledgeDebug(directory) {
|
|
|
15719
16028
|
};
|
|
15720
16029
|
}
|
|
15721
16030
|
async function safeJsonlCount(filePath) {
|
|
15722
|
-
if (!filePath || !
|
|
16031
|
+
if (!filePath || !existsSync17(filePath))
|
|
15723
16032
|
return 0;
|
|
15724
16033
|
try {
|
|
15725
16034
|
const content = await readFile10(filePath, "utf-8");
|
|
@@ -16040,7 +16349,7 @@ async function checkConfigBackups(directory) {
|
|
|
16040
16349
|
}
|
|
16041
16350
|
async function checkGitRepository(directory) {
|
|
16042
16351
|
try {
|
|
16043
|
-
if (!
|
|
16352
|
+
if (!existsSync18(directory) || !statSync6(directory).isDirectory()) {
|
|
16044
16353
|
return {
|
|
16045
16354
|
name: "Git Repository",
|
|
16046
16355
|
status: "\u274C",
|
|
@@ -16104,8 +16413,8 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
16104
16413
|
};
|
|
16105
16414
|
}
|
|
16106
16415
|
async function checkConfigParseability(directory) {
|
|
16107
|
-
const configPath =
|
|
16108
|
-
if (!
|
|
16416
|
+
const configPath = path33.join(directory, ".opencode/opencode-swarm.json");
|
|
16417
|
+
if (!existsSync18(configPath)) {
|
|
16109
16418
|
return {
|
|
16110
16419
|
name: "Config Parseability",
|
|
16111
16420
|
status: "\u2705",
|
|
@@ -16113,7 +16422,7 @@ async function checkConfigParseability(directory) {
|
|
|
16113
16422
|
};
|
|
16114
16423
|
}
|
|
16115
16424
|
try {
|
|
16116
|
-
const content =
|
|
16425
|
+
const content = readFileSync10(configPath, "utf-8");
|
|
16117
16426
|
JSON.parse(content);
|
|
16118
16427
|
return {
|
|
16119
16428
|
name: "Config Parseability",
|
|
@@ -16133,7 +16442,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
16133
16442
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
16134
16443
|
const isSource = normalized.endsWith("/src/services");
|
|
16135
16444
|
const isCliBundle = normalized.endsWith("/cli");
|
|
16136
|
-
return isSource || isCliBundle ?
|
|
16445
|
+
return isSource || isCliBundle ? path33.join(thisDir, "..", "lang", "grammars") : path33.join(thisDir, "lang", "grammars");
|
|
16137
16446
|
}
|
|
16138
16447
|
async function checkGrammarWasmFiles() {
|
|
16139
16448
|
const grammarFiles = [
|
|
@@ -16157,14 +16466,14 @@ async function checkGrammarWasmFiles() {
|
|
|
16157
16466
|
"tree-sitter-ini.wasm",
|
|
16158
16467
|
"tree-sitter-regex.wasm"
|
|
16159
16468
|
];
|
|
16160
|
-
const thisDir =
|
|
16469
|
+
const thisDir = path33.dirname(fileURLToPath(import.meta.url));
|
|
16161
16470
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
16162
16471
|
const missing = [];
|
|
16163
|
-
if (!
|
|
16472
|
+
if (!existsSync18(path33.join(grammarDir, "tree-sitter.wasm"))) {
|
|
16164
16473
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
16165
16474
|
}
|
|
16166
16475
|
for (const file of grammarFiles) {
|
|
16167
|
-
if (!
|
|
16476
|
+
if (!existsSync18(path33.join(grammarDir, file))) {
|
|
16168
16477
|
missing.push(file);
|
|
16169
16478
|
}
|
|
16170
16479
|
}
|
|
@@ -16182,8 +16491,8 @@ async function checkGrammarWasmFiles() {
|
|
|
16182
16491
|
};
|
|
16183
16492
|
}
|
|
16184
16493
|
async function checkCheckpointManifest(directory) {
|
|
16185
|
-
const manifestPath =
|
|
16186
|
-
if (!
|
|
16494
|
+
const manifestPath = path33.join(directory, ".swarm/checkpoints.json");
|
|
16495
|
+
if (!existsSync18(manifestPath)) {
|
|
16187
16496
|
return {
|
|
16188
16497
|
name: "Checkpoint Manifest",
|
|
16189
16498
|
status: "\u2705",
|
|
@@ -16191,7 +16500,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
16191
16500
|
};
|
|
16192
16501
|
}
|
|
16193
16502
|
try {
|
|
16194
|
-
const content =
|
|
16503
|
+
const content = readFileSync10(manifestPath, "utf-8");
|
|
16195
16504
|
const parsed = JSON.parse(content);
|
|
16196
16505
|
if (!parsed.checkpoints || !Array.isArray(parsed.checkpoints)) {
|
|
16197
16506
|
return {
|
|
@@ -16234,8 +16543,8 @@ async function checkCheckpointManifest(directory) {
|
|
|
16234
16543
|
}
|
|
16235
16544
|
}
|
|
16236
16545
|
async function checkEventStreamIntegrity(directory) {
|
|
16237
|
-
const eventsPath =
|
|
16238
|
-
if (!
|
|
16546
|
+
const eventsPath = path33.join(directory, ".swarm/events.jsonl");
|
|
16547
|
+
if (!existsSync18(eventsPath)) {
|
|
16239
16548
|
return {
|
|
16240
16549
|
name: "Event Stream",
|
|
16241
16550
|
status: "\u2705",
|
|
@@ -16243,7 +16552,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
16243
16552
|
};
|
|
16244
16553
|
}
|
|
16245
16554
|
try {
|
|
16246
|
-
const content =
|
|
16555
|
+
const content = readFileSync10(eventsPath, "utf-8");
|
|
16247
16556
|
const lines = content.split(`
|
|
16248
16557
|
`).filter((line) => line.trim() !== "");
|
|
16249
16558
|
let malformedCount = 0;
|
|
@@ -16275,8 +16584,8 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
16275
16584
|
}
|
|
16276
16585
|
}
|
|
16277
16586
|
async function checkSteeringDirectives(directory) {
|
|
16278
|
-
const eventsPath =
|
|
16279
|
-
if (!
|
|
16587
|
+
const eventsPath = path33.join(directory, ".swarm/events.jsonl");
|
|
16588
|
+
if (!existsSync18(eventsPath)) {
|
|
16280
16589
|
return {
|
|
16281
16590
|
name: "Steering Directives",
|
|
16282
16591
|
status: "\u2705",
|
|
@@ -16284,7 +16593,7 @@ async function checkSteeringDirectives(directory) {
|
|
|
16284
16593
|
};
|
|
16285
16594
|
}
|
|
16286
16595
|
try {
|
|
16287
|
-
const content =
|
|
16596
|
+
const content = readFileSync10(eventsPath, "utf-8");
|
|
16288
16597
|
const lines = content.split(`
|
|
16289
16598
|
`).filter((line) => line.trim() !== "");
|
|
16290
16599
|
const directivesIssued = [];
|
|
@@ -16331,8 +16640,8 @@ async function checkCurator(directory) {
|
|
|
16331
16640
|
detail: "Disabled (enable via curator.enabled)"
|
|
16332
16641
|
};
|
|
16333
16642
|
}
|
|
16334
|
-
const summaryPath =
|
|
16335
|
-
if (!
|
|
16643
|
+
const summaryPath = path33.join(directory, ".swarm/curator-summary.json");
|
|
16644
|
+
if (!existsSync18(summaryPath)) {
|
|
16336
16645
|
return {
|
|
16337
16646
|
name: "Curator",
|
|
16338
16647
|
status: "\u2705",
|
|
@@ -16340,7 +16649,7 @@ async function checkCurator(directory) {
|
|
|
16340
16649
|
};
|
|
16341
16650
|
}
|
|
16342
16651
|
try {
|
|
16343
|
-
const content =
|
|
16652
|
+
const content = readFileSync10(summaryPath, "utf-8");
|
|
16344
16653
|
const parsed = JSON.parse(content);
|
|
16345
16654
|
if (typeof parsed.schema_version !== "number" || parsed.schema_version !== 1) {
|
|
16346
16655
|
return {
|
|
@@ -16533,8 +16842,8 @@ async function getDiagnoseData(directory) {
|
|
|
16533
16842
|
checks.push(await checkCurator(directory));
|
|
16534
16843
|
checks.push(await checkKnowledgeHealth(directory));
|
|
16535
16844
|
try {
|
|
16536
|
-
const evidenceDir =
|
|
16537
|
-
const snapshotFiles =
|
|
16845
|
+
const evidenceDir = path33.join(directory, ".swarm", "evidence");
|
|
16846
|
+
const snapshotFiles = existsSync18(evidenceDir) ? readdirSync3(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
16538
16847
|
if (snapshotFiles.length > 0) {
|
|
16539
16848
|
const latest = snapshotFiles.sort().pop();
|
|
16540
16849
|
checks.push({
|
|
@@ -16567,13 +16876,13 @@ async function getDiagnoseData(directory) {
|
|
|
16567
16876
|
const cacheRows = [];
|
|
16568
16877
|
for (const cachePath of cachePaths) {
|
|
16569
16878
|
try {
|
|
16570
|
-
if (!
|
|
16879
|
+
if (!existsSync18(cachePath)) {
|
|
16571
16880
|
cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
|
|
16572
16881
|
continue;
|
|
16573
16882
|
}
|
|
16574
|
-
const pkgJsonPath =
|
|
16883
|
+
const pkgJsonPath = path33.join(cachePath, "package.json");
|
|
16575
16884
|
try {
|
|
16576
|
-
const raw =
|
|
16885
|
+
const raw = readFileSync10(pkgJsonPath, "utf-8");
|
|
16577
16886
|
const parsed = JSON.parse(raw);
|
|
16578
16887
|
const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
|
|
16579
16888
|
cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
|
|
@@ -16792,7 +17101,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
16792
17101
|
const result = runConfigDoctor(config, directory);
|
|
16793
17102
|
let output;
|
|
16794
17103
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
16795
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
17104
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-9fhfy6p7.js");
|
|
16796
17105
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true);
|
|
16797
17106
|
output = formatDoctorMarkdown(fixResult.result);
|
|
16798
17107
|
} else {
|
|
@@ -16942,10 +17251,10 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
|
|
|
16942
17251
|
|
|
16943
17252
|
// src/turbo/epic/calibration.ts
|
|
16944
17253
|
init_logger();
|
|
16945
|
-
import * as
|
|
16946
|
-
import * as
|
|
17254
|
+
import * as fs15 from "fs";
|
|
17255
|
+
import * as path34 from "path";
|
|
16947
17256
|
var STATE_FILE = "calibration.json";
|
|
16948
|
-
var STATE_REL_DIR =
|
|
17257
|
+
var STATE_REL_DIR = path34.join(".swarm", "epic");
|
|
16949
17258
|
function nowISO() {
|
|
16950
17259
|
return new Date().toISOString();
|
|
16951
17260
|
}
|
|
@@ -16967,13 +17276,13 @@ function markUnreadable(directory, reason) {
|
|
|
16967
17276
|
error(`[epic/calibration] state file unreadable for ${directory}: ${reason} \u2014 failing closed`);
|
|
16968
17277
|
}
|
|
16969
17278
|
function repairCalibrationUnreadable(directory) {
|
|
16970
|
-
const filePath =
|
|
16971
|
-
if (!
|
|
17279
|
+
const filePath = path34.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
17280
|
+
if (!fs15.existsSync(filePath)) {
|
|
16972
17281
|
stateUnreadableMap.delete(directory);
|
|
16973
17282
|
return;
|
|
16974
17283
|
}
|
|
16975
17284
|
try {
|
|
16976
|
-
const raw =
|
|
17285
|
+
const raw = fs15.readFileSync(filePath, "utf-8");
|
|
16977
17286
|
const parsed = JSON.parse(raw);
|
|
16978
17287
|
if (!isValidCalibrationShape(parsed)) {
|
|
16979
17288
|
stateUnreadableMap.set(directory, true);
|
|
@@ -16999,9 +17308,9 @@ function isValidCalibrationShape(candidate) {
|
|
|
16999
17308
|
return true;
|
|
17000
17309
|
}
|
|
17001
17310
|
function ensureSwarmEpicDir(directory) {
|
|
17002
|
-
const dir =
|
|
17003
|
-
if (!
|
|
17004
|
-
|
|
17311
|
+
const dir = path34.resolve(directory, STATE_REL_DIR);
|
|
17312
|
+
if (!fs15.existsSync(dir)) {
|
|
17313
|
+
fs15.mkdirSync(dir, { recursive: true });
|
|
17005
17314
|
}
|
|
17006
17315
|
return dir;
|
|
17007
17316
|
}
|
|
@@ -17011,18 +17320,18 @@ function loadCalibrationState(directory) {
|
|
|
17011
17320
|
if (stateUnreadableMap.get(directory))
|
|
17012
17321
|
return null;
|
|
17013
17322
|
}
|
|
17014
|
-
const filePath =
|
|
17323
|
+
const filePath = path34.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
17015
17324
|
try {
|
|
17016
|
-
if (!
|
|
17325
|
+
if (!fs15.existsSync(filePath)) {
|
|
17017
17326
|
const seed = emptyCalibrationState();
|
|
17018
17327
|
try {
|
|
17019
17328
|
ensureSwarmEpicDir(directory);
|
|
17020
|
-
|
|
17329
|
+
fs15.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
17021
17330
|
`, "utf-8");
|
|
17022
17331
|
} catch {}
|
|
17023
17332
|
return seed;
|
|
17024
17333
|
}
|
|
17025
|
-
const raw =
|
|
17334
|
+
const raw = fs15.readFileSync(filePath, "utf-8");
|
|
17026
17335
|
const parsed = JSON.parse(raw);
|
|
17027
17336
|
if (!isValidCalibrationShape(parsed)) {
|
|
17028
17337
|
markUnreadable(directory, `malformed shape (version=${parsed?.version}, hotModuleAdditions type=${Array.isArray(parsed?.hotModuleAdditions) ? "array" : typeof parsed?.hotModuleAdditions})`);
|
|
@@ -17037,36 +17346,36 @@ function loadCalibrationState(directory) {
|
|
|
17037
17346
|
|
|
17038
17347
|
// src/turbo/epic/divergence-recorder.ts
|
|
17039
17348
|
init_logger();
|
|
17040
|
-
import * as
|
|
17041
|
-
import * as
|
|
17042
|
-
var EVIDENCE_REL_DIR =
|
|
17349
|
+
import * as fs16 from "fs";
|
|
17350
|
+
import * as path35 from "path";
|
|
17351
|
+
var EVIDENCE_REL_DIR = path35.join(".swarm", "epic");
|
|
17043
17352
|
var EVIDENCE_FILE = "divergence.jsonl";
|
|
17044
17353
|
var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
|
|
17045
17354
|
function readDivergenceHistory(directory, options) {
|
|
17046
|
-
const filePath =
|
|
17047
|
-
if (!
|
|
17355
|
+
const filePath = path35.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
|
|
17356
|
+
if (!fs16.existsSync(filePath)) {
|
|
17048
17357
|
return [];
|
|
17049
17358
|
}
|
|
17050
17359
|
const maxBytes = options?.maxBytes ?? MAX_TAIL_BYTES2;
|
|
17051
17360
|
let raw;
|
|
17052
17361
|
let tailTruncated = false;
|
|
17053
17362
|
try {
|
|
17054
|
-
const stat5 =
|
|
17363
|
+
const stat5 = fs16.statSync(filePath);
|
|
17055
17364
|
if (Number.isFinite(maxBytes) && stat5.size > maxBytes) {
|
|
17056
|
-
const fd =
|
|
17365
|
+
const fd = fs16.openSync(filePath, "r");
|
|
17057
17366
|
try {
|
|
17058
17367
|
const buf = Buffer.alloc(maxBytes);
|
|
17059
17368
|
const offset = stat5.size - maxBytes;
|
|
17060
|
-
|
|
17369
|
+
fs16.readSync(fd, buf, 0, maxBytes, offset);
|
|
17061
17370
|
raw = buf.toString("utf-8");
|
|
17062
17371
|
tailTruncated = true;
|
|
17063
17372
|
} finally {
|
|
17064
17373
|
try {
|
|
17065
|
-
|
|
17374
|
+
fs16.closeSync(fd);
|
|
17066
17375
|
} catch {}
|
|
17067
17376
|
}
|
|
17068
17377
|
} else {
|
|
17069
|
-
raw =
|
|
17378
|
+
raw = fs16.readFileSync(filePath, "utf-8");
|
|
17070
17379
|
}
|
|
17071
17380
|
} catch {
|
|
17072
17381
|
return [];
|
|
@@ -17091,16 +17400,16 @@ function readDivergenceHistory(directory, options) {
|
|
|
17091
17400
|
}
|
|
17092
17401
|
|
|
17093
17402
|
// src/turbo/epic/promotion-evidence.ts
|
|
17094
|
-
import * as
|
|
17095
|
-
import * as
|
|
17096
|
-
var EVIDENCE_REL_DIR2 =
|
|
17403
|
+
import * as fs17 from "fs";
|
|
17404
|
+
import * as path36 from "path";
|
|
17405
|
+
var EVIDENCE_REL_DIR2 = path36.join(".swarm", "evidence");
|
|
17097
17406
|
var EVIDENCE_FILE2 = "epic-promotions.jsonl";
|
|
17098
17407
|
function readPromotionEvidence(directory) {
|
|
17099
|
-
const filePath =
|
|
17100
|
-
if (!
|
|
17408
|
+
const filePath = path36.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
|
|
17409
|
+
if (!fs17.existsSync(filePath)) {
|
|
17101
17410
|
return [];
|
|
17102
17411
|
}
|
|
17103
|
-
const raw =
|
|
17412
|
+
const raw = fs17.readFileSync(filePath, "utf-8");
|
|
17104
17413
|
const lines = raw.split(`
|
|
17105
17414
|
`).filter((l) => l.trim().length > 0);
|
|
17106
17415
|
const records = [];
|
|
@@ -17605,7 +17914,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
17605
17914
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
17606
17915
|
}
|
|
17607
17916
|
async function handleEvidenceSummaryCommand(directory) {
|
|
17608
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
17917
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-4hs44n2c.js");
|
|
17609
17918
|
const artifact = await buildEvidenceSummary(directory);
|
|
17610
17919
|
if (!artifact) {
|
|
17611
17920
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -17669,8 +17978,8 @@ async function handleExportCommand(directory, _args) {
|
|
|
17669
17978
|
}
|
|
17670
17979
|
// src/full-auto/state.ts
|
|
17671
17980
|
var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
|
|
17672
|
-
import * as
|
|
17673
|
-
import * as
|
|
17981
|
+
import * as fs18 from "fs";
|
|
17982
|
+
import * as path37 from "path";
|
|
17674
17983
|
init_logger();
|
|
17675
17984
|
var lockfile4 = import_proper_lockfile4.default;
|
|
17676
17985
|
var STATE_FILE2 = "full-auto-state.json";
|
|
@@ -17678,9 +17987,9 @@ function nowISO2() {
|
|
|
17678
17987
|
return new Date().toISOString();
|
|
17679
17988
|
}
|
|
17680
17989
|
function ensureSwarmDir(directory) {
|
|
17681
|
-
const swarmDir =
|
|
17682
|
-
if (!
|
|
17683
|
-
|
|
17990
|
+
const swarmDir = path37.resolve(directory, ".swarm");
|
|
17991
|
+
if (!fs18.existsSync(swarmDir)) {
|
|
17992
|
+
fs18.mkdirSync(swarmDir, { recursive: true });
|
|
17684
17993
|
}
|
|
17685
17994
|
return swarmDir;
|
|
17686
17995
|
}
|
|
@@ -17738,7 +18047,7 @@ function withStateLock(directory, fn) {
|
|
|
17738
18047
|
let release;
|
|
17739
18048
|
try {
|
|
17740
18049
|
const lockTarget = validateSwarmPath(directory, STATE_FILE2);
|
|
17741
|
-
if (!
|
|
18050
|
+
if (!fs18.existsSync(lockTarget)) {
|
|
17742
18051
|
ensureSwarmDir(directory);
|
|
17743
18052
|
const seed = {
|
|
17744
18053
|
version: 2,
|
|
@@ -17746,7 +18055,7 @@ function withStateLock(directory, fn) {
|
|
|
17746
18055
|
oversightSequence: 0,
|
|
17747
18056
|
sessions: {}
|
|
17748
18057
|
};
|
|
17749
|
-
|
|
18058
|
+
fs18.writeFileSync(lockTarget, `${JSON.stringify(seed, null, 2)}
|
|
17750
18059
|
`, "utf-8");
|
|
17751
18060
|
}
|
|
17752
18061
|
release = lockfile4.lockSync(lockTarget, {
|
|
@@ -17796,7 +18105,7 @@ function readPersisted(directory) {
|
|
|
17796
18105
|
const filePath = validateSwarmPath(directory, STATE_FILE2);
|
|
17797
18106
|
let stats;
|
|
17798
18107
|
try {
|
|
17799
|
-
stats =
|
|
18108
|
+
stats = fs18.statSync(filePath);
|
|
17800
18109
|
} catch {
|
|
17801
18110
|
clearStateUnreadable();
|
|
17802
18111
|
readCache.delete(filePath);
|
|
@@ -17807,7 +18116,7 @@ function readPersisted(directory) {
|
|
|
17807
18116
|
clearStateUnreadable();
|
|
17808
18117
|
return structuredClone(cached.state);
|
|
17809
18118
|
}
|
|
17810
|
-
const raw =
|
|
18119
|
+
const raw = fs18.readFileSync(filePath, "utf-8");
|
|
17811
18120
|
const parsed = JSON.parse(raw);
|
|
17812
18121
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 2 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
17813
18122
|
markStateUnreadable(`malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -17832,8 +18141,8 @@ function readPersisted(directory) {
|
|
|
17832
18141
|
error(`[full-auto/state] Failed to read ${STATE_FILE2}: ${reason} \u2014 attempting .bak recovery`);
|
|
17833
18142
|
try {
|
|
17834
18143
|
const bakPath = validateSwarmPath(directory, `${STATE_FILE2}.bak`);
|
|
17835
|
-
if (
|
|
17836
|
-
const raw =
|
|
18144
|
+
if (fs18.existsSync(bakPath)) {
|
|
18145
|
+
const raw = fs18.readFileSync(bakPath, "utf-8");
|
|
17837
18146
|
const parsed = JSON.parse(raw);
|
|
17838
18147
|
if (parsed?.version === 2 && parsed.sessions && !Array.isArray(parsed.sessions)) {
|
|
17839
18148
|
warn(`[full-auto/state] Recovered from ${STATE_FILE2}.bak`);
|
|
@@ -17873,23 +18182,23 @@ function writePersisted(directory, persisted) {
|
|
|
17873
18182
|
throw new Error(`Full-Auto state persistence prepare failed: ${msg}`);
|
|
17874
18183
|
}
|
|
17875
18184
|
try {
|
|
17876
|
-
if (
|
|
17877
|
-
|
|
18185
|
+
if (fs18.existsSync(filePath)) {
|
|
18186
|
+
fs18.copyFileSync(filePath, bakPath);
|
|
17878
18187
|
}
|
|
17879
18188
|
} catch {}
|
|
17880
18189
|
try {
|
|
17881
|
-
|
|
18190
|
+
fs18.writeFileSync(tmpPath, payload, "utf-8");
|
|
17882
18191
|
try {
|
|
17883
|
-
const fd =
|
|
18192
|
+
const fd = fs18.openSync(tmpPath, "r+");
|
|
17884
18193
|
try {
|
|
17885
|
-
|
|
18194
|
+
fs18.fsyncSync(fd);
|
|
17886
18195
|
} finally {
|
|
17887
|
-
|
|
18196
|
+
fs18.closeSync(fd);
|
|
17888
18197
|
}
|
|
17889
18198
|
} catch {}
|
|
17890
|
-
|
|
18199
|
+
fs18.renameSync(tmpPath, filePath);
|
|
17891
18200
|
readCache.delete(filePath);
|
|
17892
|
-
const readback =
|
|
18201
|
+
const readback = fs18.readFileSync(filePath, "utf-8");
|
|
17893
18202
|
const parsed = JSON.parse(readback);
|
|
17894
18203
|
if (parsed?.version !== 2) {
|
|
17895
18204
|
throw new Error("Round-trip readback returned wrong version");
|
|
@@ -18109,7 +18418,7 @@ function buildStatusReport(directory, sessionID, sessionFlag) {
|
|
|
18109
18418
|
|
|
18110
18419
|
// src/commands/handoff.ts
|
|
18111
18420
|
import crypto4 from "crypto";
|
|
18112
|
-
import { renameSync as renameSync9, unlinkSync as
|
|
18421
|
+
import { renameSync as renameSync9, unlinkSync as unlinkSync6 } from "fs";
|
|
18113
18422
|
|
|
18114
18423
|
// src/services/handoff-service.ts
|
|
18115
18424
|
var RTL_OVERRIDE_PATTERN = /[\u202e\u202d\u202c\u200f]/g;
|
|
@@ -18490,7 +18799,7 @@ var _internals27 = {
|
|
|
18490
18799
|
|
|
18491
18800
|
// src/session/snapshot-writer.ts
|
|
18492
18801
|
import { closeSync as closeSync6, fsyncSync as fsyncSync2, mkdirSync as mkdirSync14, openSync as openSync6, renameSync as renameSync8 } from "fs";
|
|
18493
|
-
import * as
|
|
18802
|
+
import * as path38 from "path";
|
|
18494
18803
|
var _writeInFlight = Promise.resolve();
|
|
18495
18804
|
function serializeAgentSession(s) {
|
|
18496
18805
|
const gateLog = {};
|
|
@@ -18597,7 +18906,7 @@ async function writeSnapshot(directory, state) {
|
|
|
18597
18906
|
}
|
|
18598
18907
|
const content = JSON.stringify(snapshot, null, 2);
|
|
18599
18908
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
18600
|
-
const dir =
|
|
18909
|
+
const dir = path38.dirname(resolvedPath);
|
|
18601
18910
|
mkdirSync14(dir, { recursive: true });
|
|
18602
18911
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
18603
18912
|
await bunWrite(tempPath, content);
|
|
@@ -18644,7 +18953,7 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
18644
18953
|
renameSync9(tempPath, resolvedPath);
|
|
18645
18954
|
} catch (renameErr) {
|
|
18646
18955
|
try {
|
|
18647
|
-
|
|
18956
|
+
unlinkSync6(tempPath);
|
|
18648
18957
|
} catch {}
|
|
18649
18958
|
throw renameErr;
|
|
18650
18959
|
}
|
|
@@ -18656,7 +18965,7 @@ async function handleHandoffCommand(directory, _args) {
|
|
|
18656
18965
|
renameSync9(promptTempPath, promptPath);
|
|
18657
18966
|
} catch (renameErr) {
|
|
18658
18967
|
try {
|
|
18659
|
-
|
|
18968
|
+
unlinkSync6(promptTempPath);
|
|
18660
18969
|
} catch {}
|
|
18661
18970
|
throw renameErr;
|
|
18662
18971
|
}
|
|
@@ -19100,15 +19409,15 @@ ${USAGE6}`;
|
|
|
19100
19409
|
}
|
|
19101
19410
|
|
|
19102
19411
|
// src/commands/knowledge.ts
|
|
19103
|
-
import { join as
|
|
19412
|
+
import { join as join32 } from "path";
|
|
19104
19413
|
|
|
19105
19414
|
// src/hooks/knowledge-migrator.ts
|
|
19106
19415
|
init_logger();
|
|
19107
19416
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
19108
|
-
import { existsSync as
|
|
19417
|
+
import { existsSync as existsSync23, readFileSync as readFileSync15 } from "fs";
|
|
19109
19418
|
import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
|
|
19110
|
-
import * as
|
|
19111
|
-
import * as
|
|
19419
|
+
import * as os9 from "os";
|
|
19420
|
+
import * as path39 from "path";
|
|
19112
19421
|
|
|
19113
19422
|
// src/hooks/knowledge-types.ts
|
|
19114
19423
|
var KNOWLEDGE_SCHEMA_VERSION = 2;
|
|
@@ -19138,10 +19447,10 @@ var _internals30 = {
|
|
|
19138
19447
|
resolveLegacyHiveKnowledgePath
|
|
19139
19448
|
};
|
|
19140
19449
|
async function migrateContextToKnowledge(directory, config) {
|
|
19141
|
-
const sentinelPath =
|
|
19142
|
-
const contextPath =
|
|
19450
|
+
const sentinelPath = path39.join(directory, ".swarm", ".knowledge-migrated");
|
|
19451
|
+
const contextPath = path39.join(directory, ".swarm", "context.md");
|
|
19143
19452
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
19144
|
-
if (
|
|
19453
|
+
if (existsSync23(sentinelPath)) {
|
|
19145
19454
|
return {
|
|
19146
19455
|
migrated: false,
|
|
19147
19456
|
entriesMigrated: 0,
|
|
@@ -19150,7 +19459,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
19150
19459
|
skippedReason: "sentinel-exists"
|
|
19151
19460
|
};
|
|
19152
19461
|
}
|
|
19153
|
-
if (!
|
|
19462
|
+
if (!existsSync23(contextPath)) {
|
|
19154
19463
|
return {
|
|
19155
19464
|
migrated: false,
|
|
19156
19465
|
entriesMigrated: 0,
|
|
@@ -19241,8 +19550,8 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
19241
19550
|
async function migrateHiveKnowledgeLegacy(config) {
|
|
19242
19551
|
const legacyHivePath = _internals30.resolveLegacyHiveKnowledgePath();
|
|
19243
19552
|
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
19244
|
-
const sentinelPath =
|
|
19245
|
-
if (
|
|
19553
|
+
const sentinelPath = path39.join(path39.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
19554
|
+
if (existsSync23(sentinelPath)) {
|
|
19246
19555
|
return {
|
|
19247
19556
|
migrated: false,
|
|
19248
19557
|
entriesMigrated: 0,
|
|
@@ -19251,7 +19560,7 @@ async function migrateHiveKnowledgeLegacy(config) {
|
|
|
19251
19560
|
skippedReason: "sentinel-exists"
|
|
19252
19561
|
};
|
|
19253
19562
|
}
|
|
19254
|
-
if (!
|
|
19563
|
+
if (!existsSync23(legacyHivePath)) {
|
|
19255
19564
|
return {
|
|
19256
19565
|
migrated: false,
|
|
19257
19566
|
entriesMigrated: 0,
|
|
@@ -19452,16 +19761,16 @@ function truncateLesson2(text) {
|
|
|
19452
19761
|
return `${text.slice(0, 277)}...`;
|
|
19453
19762
|
}
|
|
19454
19763
|
function inferProjectName(directory) {
|
|
19455
|
-
const packageJsonPath =
|
|
19456
|
-
if (
|
|
19764
|
+
const packageJsonPath = path39.join(directory, "package.json");
|
|
19765
|
+
if (existsSync23(packageJsonPath)) {
|
|
19457
19766
|
try {
|
|
19458
|
-
const pkg = JSON.parse(
|
|
19767
|
+
const pkg = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
|
|
19459
19768
|
if (pkg.name && typeof pkg.name === "string") {
|
|
19460
19769
|
return pkg.name;
|
|
19461
19770
|
}
|
|
19462
19771
|
} catch {}
|
|
19463
19772
|
}
|
|
19464
|
-
return
|
|
19773
|
+
return path39.basename(directory);
|
|
19465
19774
|
}
|
|
19466
19775
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
19467
19776
|
const sentinel = {
|
|
@@ -19473,21 +19782,21 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
19473
19782
|
schema_version: 1,
|
|
19474
19783
|
migration_tool: "knowledge-migrator.ts"
|
|
19475
19784
|
};
|
|
19476
|
-
await mkdir9(
|
|
19785
|
+
await mkdir9(path39.dirname(sentinelPath), { recursive: true });
|
|
19477
19786
|
await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
19478
19787
|
}
|
|
19479
19788
|
function resolveLegacyHiveKnowledgePath() {
|
|
19480
19789
|
const platform = process.platform;
|
|
19481
|
-
const home = process.env.HOME ||
|
|
19790
|
+
const home = process.env.HOME || os9.homedir();
|
|
19482
19791
|
let dataDir;
|
|
19483
19792
|
if (platform === "win32") {
|
|
19484
|
-
dataDir =
|
|
19793
|
+
dataDir = path39.join(process.env.LOCALAPPDATA || path39.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
19485
19794
|
} else if (platform === "darwin") {
|
|
19486
|
-
dataDir =
|
|
19795
|
+
dataDir = path39.join(home, "Library", "Application Support", "opencode-swarm");
|
|
19487
19796
|
} else {
|
|
19488
|
-
dataDir =
|
|
19797
|
+
dataDir = path39.join(process.env.XDG_DATA_HOME || path39.join(home, ".local", "share"), "opencode-swarm");
|
|
19489
19798
|
}
|
|
19490
|
-
return
|
|
19799
|
+
return path39.join(dataDir, "hive-knowledge.jsonl");
|
|
19491
19800
|
}
|
|
19492
19801
|
|
|
19493
19802
|
// src/commands/knowledge.ts
|
|
@@ -19541,7 +19850,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
|
|
|
19541
19850
|
return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
|
|
19542
19851
|
}
|
|
19543
19852
|
try {
|
|
19544
|
-
const quarantinePath =
|
|
19853
|
+
const quarantinePath = join32(resolveKnowledgeStoreDir(directory), "knowledge-quarantined.jsonl");
|
|
19545
19854
|
const entries = await readKnowledge(quarantinePath);
|
|
19546
19855
|
const resolved = resolveEntryByPrefix(entries, inputId);
|
|
19547
19856
|
if ("error" in resolved) {
|
|
@@ -19792,15 +20101,15 @@ var _internals31 = {
|
|
|
19792
20101
|
};
|
|
19793
20102
|
|
|
19794
20103
|
// src/commands/link.ts
|
|
19795
|
-
import { existsSync as
|
|
19796
|
-
import * as
|
|
20104
|
+
import { existsSync as existsSync24 } from "fs";
|
|
20105
|
+
import * as path41 from "path";
|
|
19797
20106
|
|
|
19798
20107
|
// src/knowledge/identity.ts
|
|
19799
20108
|
import * as child_process5 from "child_process";
|
|
19800
20109
|
import { createHash as createHash4 } from "crypto";
|
|
19801
|
-
import * as
|
|
20110
|
+
import * as path40 from "path";
|
|
19802
20111
|
function deriveProjectHash(directory) {
|
|
19803
|
-
const absolutePath =
|
|
20112
|
+
const absolutePath = path40.resolve(directory);
|
|
19804
20113
|
let hashInput;
|
|
19805
20114
|
try {
|
|
19806
20115
|
const remoteUrl = child_process5.execSync("git remote get-url origin", {
|
|
@@ -19820,18 +20129,18 @@ function deriveProjectHash(directory) {
|
|
|
19820
20129
|
// src/commands/link.ts
|
|
19821
20130
|
var DEDUP_THRESHOLD = 0.6;
|
|
19822
20131
|
async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
|
|
19823
|
-
const localPath =
|
|
19824
|
-
const sharedPath =
|
|
19825
|
-
if (!
|
|
20132
|
+
const localPath = path41.join(localSwarmDir, "knowledge.jsonl");
|
|
20133
|
+
const sharedPath = path41.join(linkDir, "knowledge.jsonl");
|
|
20134
|
+
if (!existsSync24(localPath))
|
|
19826
20135
|
return { merged: 0, skipped: 0 };
|
|
19827
20136
|
let merged = 0;
|
|
19828
20137
|
let skipped = 0;
|
|
19829
|
-
const { readFileSync:
|
|
20138
|
+
const { readFileSync: readFileSync16 } = await import("fs");
|
|
19830
20139
|
let changed = false;
|
|
19831
20140
|
await transactKnowledge(sharedPath, (sharedEntries) => {
|
|
19832
20141
|
const localEntries = [];
|
|
19833
20142
|
try {
|
|
19834
|
-
const content =
|
|
20143
|
+
const content = readFileSync16(localPath, "utf-8");
|
|
19835
20144
|
for (const line of content.split(`
|
|
19836
20145
|
`)) {
|
|
19837
20146
|
if (line.trim()) {
|
|
@@ -19919,7 +20228,7 @@ ${formatStatus(directory)}`;
|
|
|
19919
20228
|
const linkDir = resolveLinkDir(linkId);
|
|
19920
20229
|
let merge;
|
|
19921
20230
|
try {
|
|
19922
|
-
merge = await mergeLocalKnowledgeIntoLink(
|
|
20231
|
+
merge = await mergeLocalKnowledgeIntoLink(path41.join(directory, ".swarm"), linkDir);
|
|
19923
20232
|
} catch (error2) {
|
|
19924
20233
|
return `\u274C Failed to merge local knowledge into the link store: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
19925
20234
|
}
|
|
@@ -20063,8 +20372,8 @@ ${USAGE7}`;
|
|
|
20063
20372
|
}
|
|
20064
20373
|
|
|
20065
20374
|
// src/commands/memory.ts
|
|
20066
|
-
import { existsSync as
|
|
20067
|
-
import * as
|
|
20375
|
+
import { existsSync as existsSync27 } from "fs";
|
|
20376
|
+
import * as path48 from "path";
|
|
20068
20377
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20069
20378
|
|
|
20070
20379
|
// src/memory/config.ts
|
|
@@ -20204,13 +20513,13 @@ class MemoryValidationError extends Error {
|
|
|
20204
20513
|
}
|
|
20205
20514
|
}
|
|
20206
20515
|
// src/memory/evaluation.ts
|
|
20207
|
-
import * as
|
|
20208
|
-
import * as
|
|
20209
|
-
import * as
|
|
20516
|
+
import * as fs19 from "fs/promises";
|
|
20517
|
+
import * as os10 from "os";
|
|
20518
|
+
import * as path46 from "path";
|
|
20210
20519
|
|
|
20211
20520
|
// src/memory/local-jsonl-provider.ts
|
|
20212
20521
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
20213
|
-
import { existsSync as
|
|
20522
|
+
import { existsSync as existsSync25 } from "fs";
|
|
20214
20523
|
import {
|
|
20215
20524
|
appendFile as appendFile3,
|
|
20216
20525
|
mkdir as mkdir10,
|
|
@@ -20218,7 +20527,7 @@ import {
|
|
|
20218
20527
|
rename as rename5,
|
|
20219
20528
|
writeFile as writeFile10
|
|
20220
20529
|
} from "fs/promises";
|
|
20221
|
-
import * as
|
|
20530
|
+
import * as path42 from "path";
|
|
20222
20531
|
|
|
20223
20532
|
// src/memory/schema.ts
|
|
20224
20533
|
import { createHash as createHash5 } from "crypto";
|
|
@@ -21079,7 +21388,7 @@ class LocalJsonlMemoryProvider {
|
|
|
21079
21388
|
pathFor(file) {
|
|
21080
21389
|
const storageDir = this.config.storageDir.replace(/^\.swarm[/\\]?/, "");
|
|
21081
21390
|
const filename = file === "memories" ? "memories.jsonl" : file === "proposals" ? "proposals.jsonl" : "audit.jsonl";
|
|
21082
|
-
return validateSwarmPath(this.rootDirectory,
|
|
21391
|
+
return validateSwarmPath(this.rootDirectory, path42.join(storageDir, filename));
|
|
21083
21392
|
}
|
|
21084
21393
|
async initialize() {
|
|
21085
21394
|
if (this.initialized)
|
|
@@ -21406,7 +21715,7 @@ function validateLoadedProposals(values, config) {
|
|
|
21406
21715
|
return { records, invalidCount };
|
|
21407
21716
|
}
|
|
21408
21717
|
async function readJsonl(filePath) {
|
|
21409
|
-
if (!
|
|
21718
|
+
if (!existsSync25(filePath))
|
|
21410
21719
|
return [];
|
|
21411
21720
|
const content = await readFile12(filePath, "utf-8");
|
|
21412
21721
|
const records = [];
|
|
@@ -21462,12 +21771,12 @@ function parseRecallUsageEvent(event) {
|
|
|
21462
21771
|
}
|
|
21463
21772
|
}
|
|
21464
21773
|
async function appendJsonl(filePath, value) {
|
|
21465
|
-
await mkdir10(
|
|
21774
|
+
await mkdir10(path42.dirname(filePath), { recursive: true });
|
|
21466
21775
|
await appendFile3(filePath, `${JSON.stringify(value)}
|
|
21467
21776
|
`, "utf-8");
|
|
21468
21777
|
}
|
|
21469
21778
|
async function writeJsonlAtomic(filePath, values) {
|
|
21470
|
-
await mkdir10(
|
|
21779
|
+
await mkdir10(path42.dirname(filePath), { recursive: true });
|
|
21471
21780
|
const tmp = `${filePath}.tmp.${randomUUID5()}`;
|
|
21472
21781
|
const content = values.map((value) => JSON.stringify(value)).join(`
|
|
21473
21782
|
`) + (values.length > 0 ? `
|
|
@@ -21478,18 +21787,18 @@ async function writeJsonlAtomic(filePath, values) {
|
|
|
21478
21787
|
|
|
21479
21788
|
// src/memory/provider-pool.ts
|
|
21480
21789
|
import { realpathSync as realpathSync2 } from "fs";
|
|
21481
|
-
import * as
|
|
21790
|
+
import * as path45 from "path";
|
|
21482
21791
|
|
|
21483
21792
|
// src/memory/sqlite-provider.ts
|
|
21484
21793
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
21485
21794
|
import { mkdirSync as mkdirSync15 } from "fs";
|
|
21486
21795
|
import { createRequire as createRequire2 } from "module";
|
|
21487
|
-
import * as
|
|
21796
|
+
import * as path44 from "path";
|
|
21488
21797
|
|
|
21489
21798
|
// src/memory/jsonl-migration.ts
|
|
21490
|
-
import { existsSync as
|
|
21799
|
+
import { existsSync as existsSync26, renameSync as renameSync10, unlinkSync as unlinkSync7 } from "fs";
|
|
21491
21800
|
import { copyFile as copyFile2, mkdir as mkdir11, readFile as readFile13, stat as stat5, writeFile as writeFile11 } from "fs/promises";
|
|
21492
|
-
import * as
|
|
21801
|
+
import * as path43 from "path";
|
|
21493
21802
|
var LEGACY_JSONL_MIGRATION_VERSION = 2;
|
|
21494
21803
|
var LEGACY_JSONL_MIGRATION_NAME = "legacy_jsonl_import_complete";
|
|
21495
21804
|
function resolveMemoryStorageDir(rootDirectory, config = {}) {
|
|
@@ -21505,8 +21814,8 @@ function resolveSqliteDatabasePath(rootDirectory, config = {}) {
|
|
|
21505
21814
|
async function readLegacyJsonl(rootDirectory, config = {}) {
|
|
21506
21815
|
const resolved = resolveConfig(config);
|
|
21507
21816
|
const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
|
|
21508
|
-
const memoryLoad = await readMemoryJsonl(
|
|
21509
|
-
const proposalLoad = await readProposalJsonl(
|
|
21817
|
+
const memoryLoad = await readMemoryJsonl(path43.join(storageDir, "memories.jsonl"), resolved);
|
|
21818
|
+
const proposalLoad = await readProposalJsonl(path43.join(storageDir, "proposals.jsonl"), resolved);
|
|
21510
21819
|
return {
|
|
21511
21820
|
memories: memoryLoad.records,
|
|
21512
21821
|
proposals: proposalLoad.records,
|
|
@@ -21516,15 +21825,15 @@ async function readLegacyJsonl(rootDirectory, config = {}) {
|
|
|
21516
21825
|
}
|
|
21517
21826
|
async function backupLegacyJsonl(rootDirectory, config = {}) {
|
|
21518
21827
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config);
|
|
21519
|
-
const backupDir =
|
|
21828
|
+
const backupDir = path43.join(storageDir, "backups");
|
|
21520
21829
|
await mkdir11(backupDir, { recursive: true });
|
|
21521
21830
|
const results = [];
|
|
21522
21831
|
for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
|
|
21523
|
-
const source =
|
|
21524
|
-
if (!
|
|
21832
|
+
const source = path43.join(storageDir, filename);
|
|
21833
|
+
if (!existsSync26(source))
|
|
21525
21834
|
continue;
|
|
21526
|
-
const backup =
|
|
21527
|
-
if (
|
|
21835
|
+
const backup = path43.join(backupDir, `${filename}.pre-sqlite-migration`);
|
|
21836
|
+
if (existsSync26(backup)) {
|
|
21528
21837
|
results.push({ source, backup, created: false });
|
|
21529
21838
|
continue;
|
|
21530
21839
|
}
|
|
@@ -21534,51 +21843,51 @@ async function backupLegacyJsonl(rootDirectory, config = {}) {
|
|
|
21534
21843
|
return results;
|
|
21535
21844
|
}
|
|
21536
21845
|
async function writeJsonlExport(rootDirectory, config, memories, proposals) {
|
|
21537
|
-
const exportDir =
|
|
21846
|
+
const exportDir = path43.join(resolveMemoryStorageDir(rootDirectory, config), "export");
|
|
21538
21847
|
await mkdir11(exportDir, { recursive: true });
|
|
21539
|
-
const memoriesPath =
|
|
21540
|
-
const proposalsPath =
|
|
21541
|
-
const memoriesTempPath =
|
|
21848
|
+
const memoriesPath = path43.join(exportDir, "memories.jsonl");
|
|
21849
|
+
const proposalsPath = path43.join(exportDir, "proposals.jsonl");
|
|
21850
|
+
const memoriesTempPath = path43.join(path43.dirname(memoriesPath), `${path43.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
21542
21851
|
try {
|
|
21543
21852
|
await writeFile11(memoriesTempPath, toJsonl(memories), "utf-8");
|
|
21544
21853
|
renameSync10(memoriesTempPath, memoriesPath);
|
|
21545
21854
|
} catch (err) {
|
|
21546
21855
|
try {
|
|
21547
|
-
|
|
21856
|
+
unlinkSync7(memoriesTempPath);
|
|
21548
21857
|
} catch {}
|
|
21549
21858
|
throw err;
|
|
21550
21859
|
}
|
|
21551
|
-
const proposalsTempPath =
|
|
21860
|
+
const proposalsTempPath = path43.join(path43.dirname(proposalsPath), `${path43.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
21552
21861
|
try {
|
|
21553
21862
|
await writeFile11(proposalsTempPath, toJsonl(proposals), "utf-8");
|
|
21554
21863
|
renameSync10(proposalsTempPath, proposalsPath);
|
|
21555
21864
|
} catch (err) {
|
|
21556
21865
|
try {
|
|
21557
|
-
|
|
21866
|
+
unlinkSync7(proposalsTempPath);
|
|
21558
21867
|
} catch {}
|
|
21559
21868
|
throw err;
|
|
21560
21869
|
}
|
|
21561
21870
|
return { directory: exportDir, memoriesPath, proposalsPath };
|
|
21562
21871
|
}
|
|
21563
21872
|
async function writeMigrationReport(rootDirectory, report, config = {}) {
|
|
21564
|
-
const reportPath =
|
|
21565
|
-
await mkdir11(
|
|
21566
|
-
const reportTempPath =
|
|
21873
|
+
const reportPath = path43.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
21874
|
+
await mkdir11(path43.dirname(reportPath), { recursive: true });
|
|
21875
|
+
const reportTempPath = path43.join(path43.dirname(reportPath), `${path43.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
21567
21876
|
try {
|
|
21568
21877
|
await writeFile11(reportTempPath, `${JSON.stringify(report, null, 2)}
|
|
21569
21878
|
`, "utf-8");
|
|
21570
21879
|
renameSync10(reportTempPath, reportPath);
|
|
21571
21880
|
} catch (err) {
|
|
21572
21881
|
try {
|
|
21573
|
-
|
|
21882
|
+
unlinkSync7(reportTempPath);
|
|
21574
21883
|
} catch {}
|
|
21575
21884
|
throw err;
|
|
21576
21885
|
}
|
|
21577
21886
|
return reportPath;
|
|
21578
21887
|
}
|
|
21579
21888
|
async function readMigrationReport(rootDirectory, config = {}) {
|
|
21580
|
-
const reportPath =
|
|
21581
|
-
if (!
|
|
21889
|
+
const reportPath = path43.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
|
|
21890
|
+
if (!existsSync26(reportPath))
|
|
21582
21891
|
return null;
|
|
21583
21892
|
try {
|
|
21584
21893
|
return JSON.parse(await readFile13(reportPath, "utf-8"));
|
|
@@ -21590,15 +21899,15 @@ async function getLegacyJsonlFileStatus(rootDirectory, config = {}) {
|
|
|
21590
21899
|
const storageDir = resolveMemoryStorageDir(rootDirectory, config);
|
|
21591
21900
|
const statuses = [];
|
|
21592
21901
|
for (const file of ["memories.jsonl", "proposals.jsonl"]) {
|
|
21593
|
-
const filePath =
|
|
21902
|
+
const filePath = path43.join(storageDir, file);
|
|
21594
21903
|
let sizeBytes = 0;
|
|
21595
|
-
if (
|
|
21904
|
+
if (existsSync26(filePath)) {
|
|
21596
21905
|
sizeBytes = (await stat5(filePath)).size;
|
|
21597
21906
|
}
|
|
21598
21907
|
statuses.push({
|
|
21599
21908
|
file,
|
|
21600
21909
|
path: filePath,
|
|
21601
|
-
exists:
|
|
21910
|
+
exists: existsSync26(filePath),
|
|
21602
21911
|
sizeBytes
|
|
21603
21912
|
});
|
|
21604
21913
|
}
|
|
@@ -21679,7 +21988,7 @@ async function readProposalJsonl(filePath, config) {
|
|
|
21679
21988
|
return { records, invalidRows, totalRows: rows.totalRows };
|
|
21680
21989
|
}
|
|
21681
21990
|
async function readJsonlRows(filePath) {
|
|
21682
|
-
if (!
|
|
21991
|
+
if (!existsSync26(filePath)) {
|
|
21683
21992
|
return { rows: [], invalidRows: [], totalRows: 0 };
|
|
21684
21993
|
}
|
|
21685
21994
|
const content = await readFile13(filePath, "utf-8");
|
|
@@ -21898,7 +22207,7 @@ class SQLiteMemoryProvider {
|
|
|
21898
22207
|
}
|
|
21899
22208
|
async doInitialize() {
|
|
21900
22209
|
const dbPath = this.databasePath();
|
|
21901
|
-
mkdirSync15(
|
|
22210
|
+
mkdirSync15(path44.dirname(dbPath), { recursive: true });
|
|
21902
22211
|
const Db = loadDatabaseCtor2();
|
|
21903
22212
|
this.db = new Db(dbPath);
|
|
21904
22213
|
this.db.run("PRAGMA journal_mode = WAL;");
|
|
@@ -22927,7 +23236,7 @@ function resolvePoolKey(directory) {
|
|
|
22927
23236
|
try {
|
|
22928
23237
|
return realpathSync2(directory);
|
|
22929
23238
|
} catch {
|
|
22930
|
-
return
|
|
23239
|
+
return path45.resolve(directory);
|
|
22931
23240
|
}
|
|
22932
23241
|
}
|
|
22933
23242
|
|
|
@@ -22999,7 +23308,7 @@ var DEFAULT_MODES = [
|
|
|
22999
23308
|
];
|
|
23000
23309
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
23001
23310
|
async function evaluateMemoryRecallFixtures(options) {
|
|
23002
|
-
const fixtureDirectory =
|
|
23311
|
+
const fixtureDirectory = path46.resolve(options.fixtureDirectory);
|
|
23003
23312
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
23004
23313
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
23005
23314
|
const generatedAt = new Date().toISOString();
|
|
@@ -23008,7 +23317,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
23008
23317
|
for (const fixture of fixtures) {
|
|
23009
23318
|
const materialized = materializeFixture(fixture);
|
|
23010
23319
|
for (const providerName of providers) {
|
|
23011
|
-
const tempRoot = await
|
|
23320
|
+
const tempRoot = await fs19.realpath(await fs19.mkdtemp(path46.join(os10.tmpdir(), "swarm-memory-eval-")));
|
|
23012
23321
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
23013
23322
|
try {
|
|
23014
23323
|
await provider.initialize?.();
|
|
@@ -23032,7 +23341,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
23032
23341
|
} finally {
|
|
23033
23342
|
await provider.close?.();
|
|
23034
23343
|
if (!options.keepTempRoots) {
|
|
23035
|
-
await
|
|
23344
|
+
await fs19.rm(tempRoot, { recursive: true, force: true });
|
|
23036
23345
|
}
|
|
23037
23346
|
}
|
|
23038
23347
|
}
|
|
@@ -23048,11 +23357,11 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
23048
23357
|
};
|
|
23049
23358
|
}
|
|
23050
23359
|
async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
23051
|
-
const entries = await
|
|
23360
|
+
const entries = await fs19.readdir(fixtureDirectory, { withFileTypes: true });
|
|
23052
23361
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
23053
23362
|
const fixtures = [];
|
|
23054
23363
|
for (const file of files) {
|
|
23055
|
-
const raw = await
|
|
23364
|
+
const raw = await fs19.readFile(path46.join(fixtureDirectory, file), "utf-8");
|
|
23056
23365
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
23057
23366
|
}
|
|
23058
23367
|
return fixtures;
|
|
@@ -23329,8 +23638,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
23329
23638
|
}).passthrough();
|
|
23330
23639
|
// src/memory/consolidation-log.ts
|
|
23331
23640
|
import { appendFile as appendFile4, mkdir as mkdir12, readFile as readFile15 } from "fs/promises";
|
|
23332
|
-
import * as
|
|
23333
|
-
var LOG_RELATIVE_PATH =
|
|
23641
|
+
import * as path47 from "path";
|
|
23642
|
+
var LOG_RELATIVE_PATH = path47.join("memory", "consolidation-log.jsonl");
|
|
23334
23643
|
async function readConsolidationLog(directory) {
|
|
23335
23644
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
23336
23645
|
let raw;
|
|
@@ -23353,7 +23662,7 @@ async function readConsolidationLog(directory) {
|
|
|
23353
23662
|
}
|
|
23354
23663
|
|
|
23355
23664
|
// src/commands/memory.ts
|
|
23356
|
-
var PACKAGE_ROOT =
|
|
23665
|
+
var PACKAGE_ROOT = path48.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
23357
23666
|
async function handleMemoryCommand(_directory, _args) {
|
|
23358
23667
|
return [
|
|
23359
23668
|
"## Swarm Memory",
|
|
@@ -23411,7 +23720,7 @@ async function handleMemoryStatusCommand(directory, _args) {
|
|
|
23411
23720
|
`- Provider: \`${config.provider}\``,
|
|
23412
23721
|
`- Storage: \`${storageDir}\``,
|
|
23413
23722
|
`- SQLite path: \`${sqlitePath}\``,
|
|
23414
|
-
`- SQLite database exists: \`${
|
|
23723
|
+
`- SQLite database exists: \`${existsSync27(sqlitePath)}\``,
|
|
23415
23724
|
`- Automatic destructive cleanup: \`disabled\``,
|
|
23416
23725
|
"",
|
|
23417
23726
|
"### Legacy JSONL"
|
|
@@ -23651,7 +23960,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
23651
23960
|
}
|
|
23652
23961
|
function parseEvaluateArgs(directory, args) {
|
|
23653
23962
|
let json = false;
|
|
23654
|
-
let fixtureDirectory =
|
|
23963
|
+
let fixtureDirectory = path48.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
23655
23964
|
for (let i = 0;i < args.length; i++) {
|
|
23656
23965
|
const arg = args[i];
|
|
23657
23966
|
if (arg === "--json") {
|
|
@@ -23665,10 +23974,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
23665
23974
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
23666
23975
|
};
|
|
23667
23976
|
}
|
|
23668
|
-
const resolvedFixtures =
|
|
23669
|
-
const canonical =
|
|
23670
|
-
const allowedRootA =
|
|
23671
|
-
const allowedRootB =
|
|
23977
|
+
const resolvedFixtures = path48.resolve(directory, next);
|
|
23978
|
+
const canonical = path48.normalize(resolvedFixtures) + path48.sep;
|
|
23979
|
+
const allowedRootA = path48.normalize(directory) + path48.sep;
|
|
23980
|
+
const allowedRootB = path48.normalize(path48.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path48.sep;
|
|
23672
23981
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
23673
23982
|
return {
|
|
23674
23983
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -23707,15 +24016,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
23707
24016
|
return { limit, confirm };
|
|
23708
24017
|
}
|
|
23709
24018
|
function resolvePackageRootFromModule(modulePath) {
|
|
23710
|
-
const moduleDir =
|
|
23711
|
-
const leaf =
|
|
24019
|
+
const moduleDir = path48.dirname(modulePath);
|
|
24020
|
+
const leaf = path48.basename(moduleDir);
|
|
23712
24021
|
if (leaf === "commands" || leaf === "cli") {
|
|
23713
|
-
return
|
|
24022
|
+
return path48.resolve(moduleDir, "..", "..");
|
|
23714
24023
|
}
|
|
23715
24024
|
if (leaf === "dist") {
|
|
23716
|
-
return
|
|
24025
|
+
return path48.resolve(moduleDir, "..");
|
|
23717
24026
|
}
|
|
23718
|
-
return
|
|
24027
|
+
return path48.resolve(moduleDir, "..");
|
|
23719
24028
|
}
|
|
23720
24029
|
function formatMigrationResult(label, report) {
|
|
23721
24030
|
if (!report) {
|
|
@@ -24409,12 +24718,12 @@ var _internals36 = {
|
|
|
24409
24718
|
};
|
|
24410
24719
|
|
|
24411
24720
|
// src/services/preflight-service.ts
|
|
24412
|
-
import * as
|
|
24413
|
-
import * as
|
|
24721
|
+
import * as fs26 from "fs";
|
|
24722
|
+
import * as path55 from "path";
|
|
24414
24723
|
|
|
24415
24724
|
// src/tools/lint.ts
|
|
24416
|
-
import * as
|
|
24417
|
-
import * as
|
|
24725
|
+
import * as fs20 from "fs";
|
|
24726
|
+
import * as path49 from "path";
|
|
24418
24727
|
|
|
24419
24728
|
// src/utils/path-security.ts
|
|
24420
24729
|
function containsPathTraversal(str) {
|
|
@@ -24470,9 +24779,9 @@ function validateArgs(args) {
|
|
|
24470
24779
|
}
|
|
24471
24780
|
function getLinterCommand(linter, mode, projectDir) {
|
|
24472
24781
|
const isWindows = process.platform === "win32";
|
|
24473
|
-
const binDir =
|
|
24474
|
-
const biomeBin = isWindows ?
|
|
24475
|
-
const eslintBin = isWindows ?
|
|
24782
|
+
const binDir = path49.join(projectDir, "node_modules", ".bin");
|
|
24783
|
+
const biomeBin = isWindows ? path49.join(binDir, "biome.EXE") : path49.join(binDir, "biome");
|
|
24784
|
+
const eslintBin = isWindows ? path49.join(binDir, "eslint.cmd") : path49.join(binDir, "eslint");
|
|
24476
24785
|
switch (linter) {
|
|
24477
24786
|
case "biome":
|
|
24478
24787
|
if (mode === "fix") {
|
|
@@ -24488,7 +24797,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
24488
24797
|
}
|
|
24489
24798
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
24490
24799
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
24491
|
-
const gradlew =
|
|
24800
|
+
const gradlew = fs20.existsSync(path49.join(cwd, gradlewName)) ? path49.join(cwd, gradlewName) : null;
|
|
24492
24801
|
switch (linter) {
|
|
24493
24802
|
case "ruff":
|
|
24494
24803
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -24522,12 +24831,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
24522
24831
|
}
|
|
24523
24832
|
}
|
|
24524
24833
|
function detectRuff(cwd) {
|
|
24525
|
-
if (
|
|
24834
|
+
if (fs20.existsSync(path49.join(cwd, "ruff.toml")))
|
|
24526
24835
|
return isCommandAvailable("ruff");
|
|
24527
24836
|
try {
|
|
24528
|
-
const pyproject =
|
|
24529
|
-
if (
|
|
24530
|
-
const content =
|
|
24837
|
+
const pyproject = path49.join(cwd, "pyproject.toml");
|
|
24838
|
+
if (fs20.existsSync(pyproject)) {
|
|
24839
|
+
const content = fs20.readFileSync(pyproject, "utf-8");
|
|
24531
24840
|
if (content.includes("[tool.ruff]"))
|
|
24532
24841
|
return isCommandAvailable("ruff");
|
|
24533
24842
|
}
|
|
@@ -24535,21 +24844,21 @@ function detectRuff(cwd) {
|
|
|
24535
24844
|
return false;
|
|
24536
24845
|
}
|
|
24537
24846
|
function detectClippy(cwd) {
|
|
24538
|
-
return
|
|
24847
|
+
return fs20.existsSync(path49.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
24539
24848
|
}
|
|
24540
24849
|
function detectGolangciLint(cwd) {
|
|
24541
|
-
return
|
|
24850
|
+
return fs20.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
24542
24851
|
}
|
|
24543
24852
|
function detectCheckstyle(cwd) {
|
|
24544
|
-
const hasMaven =
|
|
24545
|
-
const hasGradle =
|
|
24546
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (
|
|
24853
|
+
const hasMaven = fs20.existsSync(path49.join(cwd, "pom.xml"));
|
|
24854
|
+
const hasGradle = fs20.existsSync(path49.join(cwd, "build.gradle")) || fs20.existsSync(path49.join(cwd, "build.gradle.kts"));
|
|
24855
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs20.existsSync(path49.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
24547
24856
|
return (hasMaven || hasGradle) && hasBinary;
|
|
24548
24857
|
}
|
|
24549
24858
|
function detectKtlint(cwd) {
|
|
24550
|
-
const hasKotlin =
|
|
24859
|
+
const hasKotlin = fs20.existsSync(path49.join(cwd, "build.gradle.kts")) || fs20.existsSync(path49.join(cwd, "build.gradle")) || (() => {
|
|
24551
24860
|
try {
|
|
24552
|
-
return
|
|
24861
|
+
return fs20.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
|
|
24553
24862
|
} catch {
|
|
24554
24863
|
return false;
|
|
24555
24864
|
}
|
|
@@ -24558,7 +24867,7 @@ function detectKtlint(cwd) {
|
|
|
24558
24867
|
}
|
|
24559
24868
|
function detectDotnetFormat(cwd) {
|
|
24560
24869
|
try {
|
|
24561
|
-
const files =
|
|
24870
|
+
const files = fs20.readdirSync(cwd);
|
|
24562
24871
|
const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
|
|
24563
24872
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
24564
24873
|
} catch {
|
|
@@ -24566,14 +24875,14 @@ function detectDotnetFormat(cwd) {
|
|
|
24566
24875
|
}
|
|
24567
24876
|
}
|
|
24568
24877
|
function detectCppcheck(cwd) {
|
|
24569
|
-
if (
|
|
24878
|
+
if (fs20.existsSync(path49.join(cwd, "CMakeLists.txt"))) {
|
|
24570
24879
|
return isCommandAvailable("cppcheck");
|
|
24571
24880
|
}
|
|
24572
24881
|
try {
|
|
24573
|
-
const dirsToCheck = [cwd,
|
|
24882
|
+
const dirsToCheck = [cwd, path49.join(cwd, "src")];
|
|
24574
24883
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
24575
24884
|
try {
|
|
24576
|
-
return
|
|
24885
|
+
return fs20.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
24577
24886
|
} catch {
|
|
24578
24887
|
return false;
|
|
24579
24888
|
}
|
|
@@ -24584,13 +24893,13 @@ function detectCppcheck(cwd) {
|
|
|
24584
24893
|
}
|
|
24585
24894
|
}
|
|
24586
24895
|
function detectSwiftlint(cwd) {
|
|
24587
|
-
return
|
|
24896
|
+
return fs20.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
24588
24897
|
}
|
|
24589
24898
|
function detectDartAnalyze(cwd) {
|
|
24590
|
-
return
|
|
24899
|
+
return fs20.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
24591
24900
|
}
|
|
24592
24901
|
function detectRubocop(cwd) {
|
|
24593
|
-
return (
|
|
24902
|
+
return (fs20.existsSync(path49.join(cwd, "Gemfile")) || fs20.existsSync(path49.join(cwd, "gems.rb")) || fs20.existsSync(path49.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
24594
24903
|
}
|
|
24595
24904
|
function detectAdditionalLinter(cwd) {
|
|
24596
24905
|
if (detectRuff(cwd))
|
|
@@ -24618,10 +24927,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
24618
24927
|
function findBinInAncestors(startDir, binName) {
|
|
24619
24928
|
let dir = startDir;
|
|
24620
24929
|
while (true) {
|
|
24621
|
-
const candidate =
|
|
24622
|
-
if (
|
|
24930
|
+
const candidate = path49.join(dir, "node_modules", ".bin", binName);
|
|
24931
|
+
if (fs20.existsSync(candidate))
|
|
24623
24932
|
return candidate;
|
|
24624
|
-
const parent =
|
|
24933
|
+
const parent = path49.dirname(dir);
|
|
24625
24934
|
if (parent === dir)
|
|
24626
24935
|
break;
|
|
24627
24936
|
dir = parent;
|
|
@@ -24630,11 +24939,11 @@ function findBinInAncestors(startDir, binName) {
|
|
|
24630
24939
|
}
|
|
24631
24940
|
function findBinInEnvPath(binName) {
|
|
24632
24941
|
const searchPath = process.env.PATH ?? "";
|
|
24633
|
-
for (const dir of searchPath.split(
|
|
24942
|
+
for (const dir of searchPath.split(path49.delimiter)) {
|
|
24634
24943
|
if (!dir)
|
|
24635
24944
|
continue;
|
|
24636
|
-
const candidate =
|
|
24637
|
-
if (
|
|
24945
|
+
const candidate = path49.join(dir, binName);
|
|
24946
|
+
if (fs20.existsSync(candidate))
|
|
24638
24947
|
return candidate;
|
|
24639
24948
|
}
|
|
24640
24949
|
return null;
|
|
@@ -24642,17 +24951,17 @@ function findBinInEnvPath(binName) {
|
|
|
24642
24951
|
async function detectAvailableLinter(directory) {
|
|
24643
24952
|
if (!directory)
|
|
24644
24953
|
return null;
|
|
24645
|
-
if (!
|
|
24954
|
+
if (!fs20.existsSync(directory))
|
|
24646
24955
|
return null;
|
|
24647
24956
|
const projectDir = directory;
|
|
24648
24957
|
const isWindows = process.platform === "win32";
|
|
24649
|
-
const biomeBin = isWindows ?
|
|
24650
|
-
const eslintBin = isWindows ?
|
|
24958
|
+
const biomeBin = isWindows ? path49.join(projectDir, "node_modules", ".bin", "biome.EXE") : path49.join(projectDir, "node_modules", ".bin", "biome");
|
|
24959
|
+
const eslintBin = isWindows ? path49.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path49.join(projectDir, "node_modules", ".bin", "eslint");
|
|
24651
24960
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
24652
24961
|
if (localResult)
|
|
24653
24962
|
return localResult;
|
|
24654
|
-
const biomeAncestor = findBinInAncestors(
|
|
24655
|
-
const eslintAncestor = findBinInAncestors(
|
|
24963
|
+
const biomeAncestor = findBinInAncestors(path49.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
24964
|
+
const eslintAncestor = findBinInAncestors(path49.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
24656
24965
|
if (biomeAncestor || eslintAncestor) {
|
|
24657
24966
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
24658
24967
|
}
|
|
@@ -24675,7 +24984,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
24675
24984
|
const result = await Promise.race([biomeExit, timeout]);
|
|
24676
24985
|
if (result === "timeout") {
|
|
24677
24986
|
biomeProc.kill();
|
|
24678
|
-
} else if (biomeProc.exitCode === 0 &&
|
|
24987
|
+
} else if (biomeProc.exitCode === 0 && fs20.existsSync(biomeBin)) {
|
|
24679
24988
|
return "biome";
|
|
24680
24989
|
}
|
|
24681
24990
|
} catch {}
|
|
@@ -24689,7 +24998,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
|
|
|
24689
24998
|
const result = await Promise.race([eslintExit, timeout]);
|
|
24690
24999
|
if (result === "timeout") {
|
|
24691
25000
|
eslintProc.kill();
|
|
24692
|
-
} else if (eslintProc.exitCode === 0 &&
|
|
25001
|
+
} else if (eslintProc.exitCode === 0 && fs20.existsSync(eslintBin)) {
|
|
24693
25002
|
return "eslint";
|
|
24694
25003
|
}
|
|
24695
25004
|
} catch {}
|
|
@@ -24865,8 +25174,8 @@ var _internals37 = {
|
|
|
24865
25174
|
};
|
|
24866
25175
|
|
|
24867
25176
|
// src/tools/secretscan.ts
|
|
24868
|
-
import * as
|
|
24869
|
-
import * as
|
|
25177
|
+
import * as fs21 from "fs";
|
|
25178
|
+
import * as path50 from "path";
|
|
24870
25179
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
24871
25180
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
24872
25181
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -25093,11 +25402,11 @@ function isGlobOrPathPattern(pattern) {
|
|
|
25093
25402
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
25094
25403
|
}
|
|
25095
25404
|
function loadSecretScanIgnore(scanDir) {
|
|
25096
|
-
const ignorePath =
|
|
25405
|
+
const ignorePath = path50.join(scanDir, ".secretscanignore");
|
|
25097
25406
|
try {
|
|
25098
|
-
if (!
|
|
25407
|
+
if (!fs21.existsSync(ignorePath))
|
|
25099
25408
|
return [];
|
|
25100
|
-
const content =
|
|
25409
|
+
const content = fs21.readFileSync(ignorePath, "utf8");
|
|
25101
25410
|
const patterns = [];
|
|
25102
25411
|
for (const rawLine of content.split(/\r?\n/)) {
|
|
25103
25412
|
const line = rawLine.trim();
|
|
@@ -25116,7 +25425,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
25116
25425
|
if (exactNames.has(entry))
|
|
25117
25426
|
return true;
|
|
25118
25427
|
for (const pattern of globPatterns) {
|
|
25119
|
-
if (
|
|
25428
|
+
if (path50.matchesGlob(relPath, pattern))
|
|
25120
25429
|
return true;
|
|
25121
25430
|
}
|
|
25122
25431
|
return false;
|
|
@@ -25137,7 +25446,7 @@ function validateDirectoryInput(dir) {
|
|
|
25137
25446
|
return null;
|
|
25138
25447
|
}
|
|
25139
25448
|
function isBinaryFile(filePath, buffer) {
|
|
25140
|
-
const ext =
|
|
25449
|
+
const ext = path50.extname(filePath).toLowerCase();
|
|
25141
25450
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
25142
25451
|
return true;
|
|
25143
25452
|
}
|
|
@@ -25212,11 +25521,11 @@ function createRedactedContext(line, findings) {
|
|
|
25212
25521
|
result += line.slice(lastEnd);
|
|
25213
25522
|
return result;
|
|
25214
25523
|
}
|
|
25215
|
-
var O_NOFOLLOW = process.platform !== "win32" ?
|
|
25524
|
+
var O_NOFOLLOW = process.platform !== "win32" ? fs21.constants.O_NOFOLLOW : undefined;
|
|
25216
25525
|
function scanFileForSecrets(filePath) {
|
|
25217
25526
|
const findings = [];
|
|
25218
25527
|
try {
|
|
25219
|
-
const lstat2 =
|
|
25528
|
+
const lstat2 = fs21.lstatSync(filePath);
|
|
25220
25529
|
if (lstat2.isSymbolicLink()) {
|
|
25221
25530
|
return findings;
|
|
25222
25531
|
}
|
|
@@ -25225,14 +25534,14 @@ function scanFileForSecrets(filePath) {
|
|
|
25225
25534
|
}
|
|
25226
25535
|
let buffer;
|
|
25227
25536
|
if (O_NOFOLLOW !== undefined) {
|
|
25228
|
-
const fd =
|
|
25537
|
+
const fd = fs21.openSync(filePath, "r", O_NOFOLLOW);
|
|
25229
25538
|
try {
|
|
25230
|
-
buffer =
|
|
25539
|
+
buffer = fs21.readFileSync(fd);
|
|
25231
25540
|
} finally {
|
|
25232
|
-
|
|
25541
|
+
fs21.closeSync(fd);
|
|
25233
25542
|
}
|
|
25234
25543
|
} else {
|
|
25235
|
-
buffer =
|
|
25544
|
+
buffer = fs21.readFileSync(filePath);
|
|
25236
25545
|
}
|
|
25237
25546
|
if (isBinaryFile(filePath, buffer)) {
|
|
25238
25547
|
return findings;
|
|
@@ -25274,9 +25583,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
25274
25583
|
return false;
|
|
25275
25584
|
}
|
|
25276
25585
|
function isPathWithinScope(realPath, scanDir) {
|
|
25277
|
-
const resolvedScanDir =
|
|
25278
|
-
const resolvedRealPath =
|
|
25279
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
25586
|
+
const resolvedScanDir = path50.resolve(scanDir);
|
|
25587
|
+
const resolvedRealPath = path50.resolve(realPath);
|
|
25588
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path50.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
25280
25589
|
}
|
|
25281
25590
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
25282
25591
|
skippedDirs: 0,
|
|
@@ -25287,7 +25596,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25287
25596
|
const files = [];
|
|
25288
25597
|
let entries;
|
|
25289
25598
|
try {
|
|
25290
|
-
entries =
|
|
25599
|
+
entries = fs21.readdirSync(dir);
|
|
25291
25600
|
} catch {
|
|
25292
25601
|
stats.fileErrors++;
|
|
25293
25602
|
return files;
|
|
@@ -25302,15 +25611,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25302
25611
|
return a.localeCompare(b);
|
|
25303
25612
|
});
|
|
25304
25613
|
for (const entry of entries) {
|
|
25305
|
-
const fullPath =
|
|
25306
|
-
const relPath =
|
|
25614
|
+
const fullPath = path50.join(dir, entry);
|
|
25615
|
+
const relPath = path50.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
25307
25616
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
25308
25617
|
stats.skippedDirs++;
|
|
25309
25618
|
continue;
|
|
25310
25619
|
}
|
|
25311
25620
|
let lstat2;
|
|
25312
25621
|
try {
|
|
25313
|
-
lstat2 =
|
|
25622
|
+
lstat2 = fs21.lstatSync(fullPath);
|
|
25314
25623
|
} catch {
|
|
25315
25624
|
stats.fileErrors++;
|
|
25316
25625
|
continue;
|
|
@@ -25322,7 +25631,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25322
25631
|
if (lstat2.isDirectory()) {
|
|
25323
25632
|
let realPath;
|
|
25324
25633
|
try {
|
|
25325
|
-
realPath =
|
|
25634
|
+
realPath = fs21.realpathSync(fullPath);
|
|
25326
25635
|
} catch {
|
|
25327
25636
|
stats.fileErrors++;
|
|
25328
25637
|
continue;
|
|
@@ -25338,7 +25647,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
25338
25647
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
25339
25648
|
files.push(...subFiles);
|
|
25340
25649
|
} else if (lstat2.isFile()) {
|
|
25341
|
-
const ext =
|
|
25650
|
+
const ext = path50.extname(fullPath).toLowerCase();
|
|
25342
25651
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
25343
25652
|
files.push(fullPath);
|
|
25344
25653
|
} else {
|
|
@@ -25404,15 +25713,15 @@ var secretscan = createSwarmTool({
|
|
|
25404
25713
|
}
|
|
25405
25714
|
}
|
|
25406
25715
|
try {
|
|
25407
|
-
const _scanDirRaw =
|
|
25716
|
+
const _scanDirRaw = path50.resolve(directory);
|
|
25408
25717
|
const scanDir = (() => {
|
|
25409
25718
|
try {
|
|
25410
|
-
return
|
|
25719
|
+
return fs21.realpathSync(_scanDirRaw);
|
|
25411
25720
|
} catch {
|
|
25412
25721
|
return _scanDirRaw;
|
|
25413
25722
|
}
|
|
25414
25723
|
})();
|
|
25415
|
-
if (!
|
|
25724
|
+
if (!fs21.existsSync(scanDir)) {
|
|
25416
25725
|
const errorResult = {
|
|
25417
25726
|
error: "directory not found",
|
|
25418
25727
|
scan_dir: directory,
|
|
@@ -25423,7 +25732,7 @@ var secretscan = createSwarmTool({
|
|
|
25423
25732
|
};
|
|
25424
25733
|
return JSON.stringify(errorResult, null, 2);
|
|
25425
25734
|
}
|
|
25426
|
-
const dirStat =
|
|
25735
|
+
const dirStat = fs21.statSync(scanDir);
|
|
25427
25736
|
if (!dirStat.isDirectory()) {
|
|
25428
25737
|
const errorResult = {
|
|
25429
25738
|
error: "target must be a directory, not a file",
|
|
@@ -25474,7 +25783,7 @@ var secretscan = createSwarmTool({
|
|
|
25474
25783
|
break;
|
|
25475
25784
|
const fileFindings = scanFileForSecrets(filePath);
|
|
25476
25785
|
try {
|
|
25477
|
-
const stat6 =
|
|
25786
|
+
const stat6 = fs21.statSync(filePath);
|
|
25478
25787
|
if (stat6.size > MAX_FILE_SIZE_BYTES) {
|
|
25479
25788
|
skippedFiles++;
|
|
25480
25789
|
continue;
|
|
@@ -25566,12 +25875,12 @@ var _internals38 = {
|
|
|
25566
25875
|
};
|
|
25567
25876
|
|
|
25568
25877
|
// src/tools/test-runner.ts
|
|
25569
|
-
import * as
|
|
25570
|
-
import * as
|
|
25878
|
+
import * as fs25 from "fs";
|
|
25879
|
+
import * as path54 from "path";
|
|
25571
25880
|
|
|
25572
25881
|
// src/test-impact/analyzer.ts
|
|
25573
|
-
import
|
|
25574
|
-
import
|
|
25882
|
+
import fs22 from "fs";
|
|
25883
|
+
import path51 from "path";
|
|
25575
25884
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
25576
25885
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
25577
25886
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -25598,7 +25907,7 @@ function sharedTrailingSegments(a, b) {
|
|
|
25598
25907
|
function isCacheStale(impactMap, generatedAtMs) {
|
|
25599
25908
|
for (const sourcePath of Object.keys(impactMap)) {
|
|
25600
25909
|
try {
|
|
25601
|
-
const stat6 =
|
|
25910
|
+
const stat6 = fs22.statSync(sourcePath);
|
|
25602
25911
|
if (stat6.mtimeMs > generatedAtMs) {
|
|
25603
25912
|
return true;
|
|
25604
25913
|
}
|
|
@@ -25612,15 +25921,15 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
25612
25921
|
if (!importPath.startsWith(".")) {
|
|
25613
25922
|
return null;
|
|
25614
25923
|
}
|
|
25615
|
-
const resolved =
|
|
25616
|
-
if (
|
|
25617
|
-
if (
|
|
25924
|
+
const resolved = path51.resolve(fromDir, importPath);
|
|
25925
|
+
if (path51.extname(resolved)) {
|
|
25926
|
+
if (fs22.existsSync(resolved) && fs22.statSync(resolved).isFile()) {
|
|
25618
25927
|
return normalizePath2(resolved);
|
|
25619
25928
|
}
|
|
25620
25929
|
} else {
|
|
25621
25930
|
for (const ext of EXTENSIONS_TO_TRY) {
|
|
25622
25931
|
const withExt = resolved + ext;
|
|
25623
|
-
if (
|
|
25932
|
+
if (fs22.existsSync(withExt) && fs22.statSync(withExt).isFile()) {
|
|
25624
25933
|
return normalizePath2(withExt);
|
|
25625
25934
|
}
|
|
25626
25935
|
}
|
|
@@ -25633,30 +25942,30 @@ function resolvePythonImport(fromDir, module) {
|
|
|
25633
25942
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
25634
25943
|
let baseDir = fromDir;
|
|
25635
25944
|
for (let i = 1;i < leadingDots; i++) {
|
|
25636
|
-
baseDir =
|
|
25945
|
+
baseDir = path51.dirname(baseDir);
|
|
25637
25946
|
}
|
|
25638
25947
|
const rest = module.slice(leadingDots);
|
|
25639
25948
|
if (rest.length === 0) {
|
|
25640
|
-
const initPath =
|
|
25641
|
-
if (
|
|
25949
|
+
const initPath = path51.join(baseDir, "__init__.py");
|
|
25950
|
+
if (fs22.existsSync(initPath) && fs22.statSync(initPath).isFile()) {
|
|
25642
25951
|
return normalizePath2(initPath);
|
|
25643
25952
|
}
|
|
25644
25953
|
return null;
|
|
25645
25954
|
}
|
|
25646
|
-
const subpath = rest.replace(/\./g,
|
|
25955
|
+
const subpath = rest.replace(/\./g, path51.sep);
|
|
25647
25956
|
const candidates = [
|
|
25648
|
-
`${
|
|
25649
|
-
|
|
25957
|
+
`${path51.join(baseDir, subpath)}.py`,
|
|
25958
|
+
path51.join(baseDir, subpath, "__init__.py")
|
|
25650
25959
|
];
|
|
25651
25960
|
for (const c of candidates) {
|
|
25652
|
-
if (
|
|
25961
|
+
if (fs22.existsSync(c) && fs22.statSync(c).isFile())
|
|
25653
25962
|
return normalizePath2(c);
|
|
25654
25963
|
}
|
|
25655
25964
|
return null;
|
|
25656
25965
|
}
|
|
25657
25966
|
var goModuleCache = new Map;
|
|
25658
25967
|
function findGoModule(fromDir) {
|
|
25659
|
-
const resolved =
|
|
25968
|
+
const resolved = path51.resolve(fromDir);
|
|
25660
25969
|
let cur = resolved;
|
|
25661
25970
|
const walked = [];
|
|
25662
25971
|
for (let i = 0;i < 16; i++) {
|
|
@@ -25668,8 +25977,8 @@ function findGoModule(fromDir) {
|
|
|
25668
25977
|
}
|
|
25669
25978
|
walked.push(cur);
|
|
25670
25979
|
try {
|
|
25671
|
-
const goMod =
|
|
25672
|
-
const content =
|
|
25980
|
+
const goMod = path51.join(cur, "go.mod");
|
|
25981
|
+
const content = fs22.readFileSync(goMod, "utf-8");
|
|
25673
25982
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
25674
25983
|
if (moduleMatch) {
|
|
25675
25984
|
const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
|
|
@@ -25679,10 +25988,10 @@ function findGoModule(fromDir) {
|
|
|
25679
25988
|
}
|
|
25680
25989
|
} catch {}
|
|
25681
25990
|
try {
|
|
25682
|
-
|
|
25991
|
+
fs22.accessSync(path51.join(cur, ".git"));
|
|
25683
25992
|
break;
|
|
25684
25993
|
} catch {}
|
|
25685
|
-
const parent =
|
|
25994
|
+
const parent = path51.dirname(cur);
|
|
25686
25995
|
if (parent === cur)
|
|
25687
25996
|
break;
|
|
25688
25997
|
cur = parent;
|
|
@@ -25694,20 +26003,20 @@ function findGoModule(fromDir) {
|
|
|
25694
26003
|
function resolveGoImport(fromDir, importPath) {
|
|
25695
26004
|
let dir = null;
|
|
25696
26005
|
if (importPath.startsWith(".")) {
|
|
25697
|
-
dir =
|
|
26006
|
+
dir = path51.resolve(fromDir, importPath);
|
|
25698
26007
|
} else {
|
|
25699
26008
|
const mod = findGoModule(fromDir);
|
|
25700
26009
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
25701
26010
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
25702
|
-
dir =
|
|
26011
|
+
dir = path51.join(mod.moduleRoot, subpath);
|
|
25703
26012
|
}
|
|
25704
26013
|
}
|
|
25705
26014
|
if (dir === null)
|
|
25706
26015
|
return [];
|
|
25707
|
-
if (!
|
|
26016
|
+
if (!fs22.existsSync(dir) || !fs22.statSync(dir).isDirectory())
|
|
25708
26017
|
return [];
|
|
25709
26018
|
try {
|
|
25710
|
-
return
|
|
26019
|
+
return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path51.join(dir, f)));
|
|
25711
26020
|
} catch {
|
|
25712
26021
|
return [];
|
|
25713
26022
|
}
|
|
@@ -25727,13 +26036,13 @@ function findTestFilesSync(cwd) {
|
|
|
25727
26036
|
function walk(dir, visitedInodes) {
|
|
25728
26037
|
let entries;
|
|
25729
26038
|
try {
|
|
25730
|
-
entries =
|
|
26039
|
+
entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
25731
26040
|
} catch {
|
|
25732
26041
|
return;
|
|
25733
26042
|
}
|
|
25734
26043
|
let dirInode;
|
|
25735
26044
|
try {
|
|
25736
|
-
dirInode =
|
|
26045
|
+
dirInode = fs22.statSync(dir).ino;
|
|
25737
26046
|
} catch {
|
|
25738
26047
|
return;
|
|
25739
26048
|
}
|
|
@@ -25746,15 +26055,15 @@ function findTestFilesSync(cwd) {
|
|
|
25746
26055
|
for (const entry of entries) {
|
|
25747
26056
|
if (entry.isDirectory()) {
|
|
25748
26057
|
if (!skipDirs.has(entry.name)) {
|
|
25749
|
-
walk(
|
|
26058
|
+
walk(path51.join(dir, entry.name), visitedInodes);
|
|
25750
26059
|
}
|
|
25751
26060
|
} else if (entry.isFile()) {
|
|
25752
26061
|
const name = entry.name;
|
|
25753
26062
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
25754
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
26063
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path51.sep}tests${path51.sep}`) && name.endsWith(".py");
|
|
25755
26064
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
25756
26065
|
if (isTsTest || isPyTest || isGoTest) {
|
|
25757
|
-
testFiles.push(normalizePath2(
|
|
26066
|
+
testFiles.push(normalizePath2(path51.join(dir, entry.name)));
|
|
25758
26067
|
}
|
|
25759
26068
|
}
|
|
25760
26069
|
}
|
|
@@ -25779,8 +26088,8 @@ function extractImports(content) {
|
|
|
25779
26088
|
];
|
|
25780
26089
|
}
|
|
25781
26090
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
25782
|
-
const ext =
|
|
25783
|
-
const testDir =
|
|
26091
|
+
const ext = path51.extname(testFile).toLowerCase();
|
|
26092
|
+
const testDir = path51.dirname(testFile);
|
|
25784
26093
|
function addEdge(source) {
|
|
25785
26094
|
if (!impactMap[source])
|
|
25786
26095
|
impactMap[source] = [];
|
|
@@ -25822,7 +26131,7 @@ async function buildImpactMapInternal(cwd) {
|
|
|
25822
26131
|
for (const testFile of testFiles) {
|
|
25823
26132
|
let content;
|
|
25824
26133
|
try {
|
|
25825
|
-
content =
|
|
26134
|
+
content = fs22.readFileSync(testFile, "utf-8");
|
|
25826
26135
|
} catch {
|
|
25827
26136
|
continue;
|
|
25828
26137
|
}
|
|
@@ -25853,10 +26162,10 @@ async function buildImpactMap(cwd) {
|
|
|
25853
26162
|
return impactMap;
|
|
25854
26163
|
}
|
|
25855
26164
|
async function loadImpactMap(cwd, options) {
|
|
25856
|
-
const cachePath =
|
|
25857
|
-
if (
|
|
26165
|
+
const cachePath = path51.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
26166
|
+
if (fs22.existsSync(cachePath)) {
|
|
25858
26167
|
try {
|
|
25859
|
-
const content =
|
|
26168
|
+
const content = fs22.readFileSync(cachePath, "utf-8");
|
|
25860
26169
|
const data = JSON.parse(content);
|
|
25861
26170
|
if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
|
|
25862
26171
|
const map = data.map;
|
|
@@ -25886,21 +26195,21 @@ async function loadImpactMap(cwd, options) {
|
|
|
25886
26195
|
return _internals39.buildImpactMap(cwd);
|
|
25887
26196
|
}
|
|
25888
26197
|
async function saveImpactMap(cwd, impactMap) {
|
|
25889
|
-
if (!
|
|
26198
|
+
if (!path51.isAbsolute(cwd)) {
|
|
25890
26199
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
25891
26200
|
}
|
|
25892
26201
|
_internals39.validateProjectRoot(cwd);
|
|
25893
|
-
const cacheDir2 =
|
|
25894
|
-
const cachePath =
|
|
25895
|
-
if (!
|
|
25896
|
-
|
|
26202
|
+
const cacheDir2 = path51.join(cwd, ".swarm", "cache");
|
|
26203
|
+
const cachePath = path51.join(cacheDir2, "impact-map.json");
|
|
26204
|
+
if (!fs22.existsSync(cacheDir2)) {
|
|
26205
|
+
fs22.mkdirSync(cacheDir2, { recursive: true });
|
|
25897
26206
|
}
|
|
25898
26207
|
const data = {
|
|
25899
26208
|
generatedAt: new Date().toISOString(),
|
|
25900
26209
|
fileCount: Object.keys(impactMap).length,
|
|
25901
26210
|
map: impactMap
|
|
25902
26211
|
};
|
|
25903
|
-
|
|
26212
|
+
fs22.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
|
|
25904
26213
|
}
|
|
25905
26214
|
async function analyzeImpact(changedFiles, cwd, budget) {
|
|
25906
26215
|
if (!Array.isArray(changedFiles)) {
|
|
@@ -25923,7 +26232,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25923
26232
|
budgetExceeded = true;
|
|
25924
26233
|
break;
|
|
25925
26234
|
}
|
|
25926
|
-
const normalizedChanged = normalizePath2(
|
|
26235
|
+
const normalizedChanged = normalizePath2(path51.resolve(changedFile));
|
|
25927
26236
|
const tests = impactMap[normalizedChanged];
|
|
25928
26237
|
if (tests && tests.length > 0) {
|
|
25929
26238
|
for (const test of tests) {
|
|
@@ -25937,13 +26246,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25937
26246
|
if (budgetExceeded)
|
|
25938
26247
|
break;
|
|
25939
26248
|
} else {
|
|
25940
|
-
const changedDir = normalizePath2(
|
|
25941
|
-
const changedInputDir = normalizePath2(
|
|
26249
|
+
const changedDir = normalizePath2(path51.dirname(normalizedChanged));
|
|
26250
|
+
const changedInputDir = normalizePath2(path51.dirname(changedFile));
|
|
25942
26251
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
25943
26252
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
25944
26253
|
}).sort(([sourceA], [sourceB]) => {
|
|
25945
|
-
const sourceDirA = normalizePath2(
|
|
25946
|
-
const sourceDirB = normalizePath2(
|
|
26254
|
+
const sourceDirA = normalizePath2(path51.dirname(sourceA));
|
|
26255
|
+
const sourceDirB = normalizePath2(path51.dirname(sourceB));
|
|
25947
26256
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
25948
26257
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
25949
26258
|
if (exactA !== exactB)
|
|
@@ -26269,8 +26578,8 @@ function detectFlakyTests(allHistory) {
|
|
|
26269
26578
|
}
|
|
26270
26579
|
|
|
26271
26580
|
// src/test-impact/history-store.ts
|
|
26272
|
-
import
|
|
26273
|
-
import
|
|
26581
|
+
import fs23 from "fs";
|
|
26582
|
+
import path52 from "path";
|
|
26274
26583
|
var MAX_HISTORY_PER_TEST = 20;
|
|
26275
26584
|
var MAX_ERROR_LENGTH = 500;
|
|
26276
26585
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -26282,10 +26591,10 @@ function getHistoryPath(workingDir) {
|
|
|
26282
26591
|
if (!workingDir) {
|
|
26283
26592
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
26284
26593
|
}
|
|
26285
|
-
if (!
|
|
26594
|
+
if (!path52.isAbsolute(workingDir)) {
|
|
26286
26595
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
26287
26596
|
}
|
|
26288
|
-
return
|
|
26597
|
+
return path52.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
26289
26598
|
}
|
|
26290
26599
|
function sanitizeErrorMessage(errorMessage) {
|
|
26291
26600
|
if (errorMessage === undefined) {
|
|
@@ -26377,10 +26686,10 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
26377
26686
|
}
|
|
26378
26687
|
}
|
|
26379
26688
|
const historyPath = getHistoryPath(workingDir);
|
|
26380
|
-
const historyDir =
|
|
26689
|
+
const historyDir = path52.dirname(historyPath);
|
|
26381
26690
|
_internals40.validateProjectRoot(workingDir);
|
|
26382
|
-
if (!
|
|
26383
|
-
|
|
26691
|
+
if (!fs23.existsSync(historyDir)) {
|
|
26692
|
+
fs23.mkdirSync(historyDir, { recursive: true });
|
|
26384
26693
|
}
|
|
26385
26694
|
withHistoryWriteLock(historyPath, () => {
|
|
26386
26695
|
const existingRecords = readAllRecords(historyPath);
|
|
@@ -26414,13 +26723,13 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
26414
26723
|
`)}
|
|
26415
26724
|
`;
|
|
26416
26725
|
const tempPath = `${historyPath}.tmp`;
|
|
26417
|
-
|
|
26418
|
-
|
|
26726
|
+
fs23.writeFileSync(tempPath, content, "utf-8");
|
|
26727
|
+
fs23.renameSync(tempPath, historyPath);
|
|
26419
26728
|
} catch (err) {
|
|
26420
26729
|
try {
|
|
26421
26730
|
const tempPath = `${historyPath}.tmp`;
|
|
26422
|
-
if (
|
|
26423
|
-
|
|
26731
|
+
if (fs23.existsSync(tempPath)) {
|
|
26732
|
+
fs23.unlinkSync(tempPath);
|
|
26424
26733
|
}
|
|
26425
26734
|
} catch {}
|
|
26426
26735
|
throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -26432,7 +26741,7 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26432
26741
|
const deadline = Date.now() + HISTORY_WRITE_LOCK_TIMEOUT_MS;
|
|
26433
26742
|
while (true) {
|
|
26434
26743
|
try {
|
|
26435
|
-
|
|
26744
|
+
fs23.mkdirSync(lockPath);
|
|
26436
26745
|
break;
|
|
26437
26746
|
} catch (error2) {
|
|
26438
26747
|
const code = error2 instanceof Error && "code" in error2 ? error2.code : undefined;
|
|
@@ -26443,9 +26752,9 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26443
26752
|
throw new Error(`Timed out waiting for test history lock: ${historyPath}`);
|
|
26444
26753
|
}
|
|
26445
26754
|
try {
|
|
26446
|
-
const lockStat =
|
|
26755
|
+
const lockStat = fs23.statSync(lockPath);
|
|
26447
26756
|
if (Date.now() - lockStat.mtimeMs >= HISTORY_WRITE_LOCK_STALE_MS) {
|
|
26448
|
-
|
|
26757
|
+
fs23.rmSync(lockPath, { recursive: true, force: true });
|
|
26449
26758
|
continue;
|
|
26450
26759
|
}
|
|
26451
26760
|
} catch {}
|
|
@@ -26460,7 +26769,7 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26460
26769
|
return fn();
|
|
26461
26770
|
} finally {
|
|
26462
26771
|
try {
|
|
26463
|
-
|
|
26772
|
+
fs23.rmSync(lockPath, { recursive: true, force: true });
|
|
26464
26773
|
} catch {}
|
|
26465
26774
|
}
|
|
26466
26775
|
function sleepSync(ms) {
|
|
@@ -26469,11 +26778,11 @@ function withHistoryWriteLock(historyPath, fn) {
|
|
|
26469
26778
|
}
|
|
26470
26779
|
}
|
|
26471
26780
|
function readAllRecords(historyPath) {
|
|
26472
|
-
if (!
|
|
26781
|
+
if (!fs23.existsSync(historyPath)) {
|
|
26473
26782
|
return [];
|
|
26474
26783
|
}
|
|
26475
26784
|
try {
|
|
26476
|
-
const content =
|
|
26785
|
+
const content = fs23.readFileSync(historyPath, "utf-8");
|
|
26477
26786
|
const lines = content.split(`
|
|
26478
26787
|
`);
|
|
26479
26788
|
const records = [];
|
|
@@ -26506,8 +26815,8 @@ var _internals40 = {
|
|
|
26506
26815
|
};
|
|
26507
26816
|
|
|
26508
26817
|
// src/tools/resolve-working-directory.ts
|
|
26509
|
-
import * as
|
|
26510
|
-
import * as
|
|
26818
|
+
import * as fs24 from "fs";
|
|
26819
|
+
import * as path53 from "path";
|
|
26511
26820
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
26512
26821
|
if (workingDirectory == null || workingDirectory === "") {
|
|
26513
26822
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -26539,18 +26848,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26539
26848
|
};
|
|
26540
26849
|
}
|
|
26541
26850
|
}
|
|
26542
|
-
const rawPathParts = workingDirectory.split(
|
|
26851
|
+
const rawPathParts = workingDirectory.split(path53.sep);
|
|
26543
26852
|
if (rawPathParts.includes("..")) {
|
|
26544
26853
|
return {
|
|
26545
26854
|
success: false,
|
|
26546
26855
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
26547
26856
|
};
|
|
26548
26857
|
}
|
|
26549
|
-
const normalizedDir =
|
|
26550
|
-
const resolvedDir =
|
|
26858
|
+
const normalizedDir = path53.normalize(workingDirectory);
|
|
26859
|
+
const resolvedDir = path53.resolve(normalizedDir);
|
|
26551
26860
|
let statResult;
|
|
26552
26861
|
try {
|
|
26553
|
-
statResult =
|
|
26862
|
+
statResult = fs24.statSync(resolvedDir);
|
|
26554
26863
|
} catch {
|
|
26555
26864
|
return {
|
|
26556
26865
|
success: false,
|
|
@@ -26566,16 +26875,16 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
26566
26875
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
26567
26876
|
return { success: true, directory: resolvedDir };
|
|
26568
26877
|
}
|
|
26569
|
-
const resolvedFallback =
|
|
26878
|
+
const resolvedFallback = path53.resolve(fallbackDirectory);
|
|
26570
26879
|
let fallbackExists = false;
|
|
26571
26880
|
try {
|
|
26572
|
-
|
|
26881
|
+
fs24.statSync(resolvedFallback);
|
|
26573
26882
|
fallbackExists = true;
|
|
26574
26883
|
} catch {
|
|
26575
26884
|
fallbackExists = false;
|
|
26576
26885
|
}
|
|
26577
26886
|
if (fallbackExists) {
|
|
26578
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
26887
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path53.sep);
|
|
26579
26888
|
if (isSubdirectory) {
|
|
26580
26889
|
return {
|
|
26581
26890
|
success: false,
|
|
@@ -26598,7 +26907,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
26598
26907
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
26599
26908
|
const uniqueTestFiles = new Set;
|
|
26600
26909
|
for (const sourceFile of sourceFiles) {
|
|
26601
|
-
const resolvedPath =
|
|
26910
|
+
const resolvedPath = path54.resolve(cwd, sourceFile);
|
|
26602
26911
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
26603
26912
|
const testFiles = impactMap[normalizedPath];
|
|
26604
26913
|
if (testFiles) {
|
|
@@ -26683,19 +26992,19 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
26683
26992
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
26684
26993
|
}
|
|
26685
26994
|
function detectGoTest(cwd) {
|
|
26686
|
-
return
|
|
26995
|
+
return fs25.existsSync(path54.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
26687
26996
|
}
|
|
26688
26997
|
function detectJavaMaven(cwd) {
|
|
26689
|
-
return
|
|
26998
|
+
return fs25.existsSync(path54.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
26690
26999
|
}
|
|
26691
27000
|
function detectGradle(cwd) {
|
|
26692
|
-
const hasBuildFile =
|
|
26693
|
-
const hasGradlew =
|
|
27001
|
+
const hasBuildFile = fs25.existsSync(path54.join(cwd, "build.gradle")) || fs25.existsSync(path54.join(cwd, "build.gradle.kts"));
|
|
27002
|
+
const hasGradlew = fs25.existsSync(path54.join(cwd, "gradlew")) || fs25.existsSync(path54.join(cwd, "gradlew.bat"));
|
|
26694
27003
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
26695
27004
|
}
|
|
26696
27005
|
function detectDotnetTest(cwd) {
|
|
26697
27006
|
try {
|
|
26698
|
-
const files =
|
|
27007
|
+
const files = fs25.readdirSync(cwd);
|
|
26699
27008
|
const hasCsproj = files.some((f) => f.endsWith(".csproj"));
|
|
26700
27009
|
return hasCsproj && isCommandAvailable("dotnet");
|
|
26701
27010
|
} catch {
|
|
@@ -26703,25 +27012,25 @@ function detectDotnetTest(cwd) {
|
|
|
26703
27012
|
}
|
|
26704
27013
|
}
|
|
26705
27014
|
function detectCTest(cwd) {
|
|
26706
|
-
const hasSource =
|
|
26707
|
-
const hasBuildCache =
|
|
27015
|
+
const hasSource = fs25.existsSync(path54.join(cwd, "CMakeLists.txt"));
|
|
27016
|
+
const hasBuildCache = fs25.existsSync(path54.join(cwd, "CMakeCache.txt")) || fs25.existsSync(path54.join(cwd, "build", "CMakeCache.txt"));
|
|
26708
27017
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
26709
27018
|
}
|
|
26710
27019
|
function detectSwiftTest(cwd) {
|
|
26711
|
-
return
|
|
27020
|
+
return fs25.existsSync(path54.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
26712
27021
|
}
|
|
26713
27022
|
function detectDartTest(cwd) {
|
|
26714
|
-
return
|
|
27023
|
+
return fs25.existsSync(path54.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
26715
27024
|
}
|
|
26716
27025
|
function detectRSpec(cwd) {
|
|
26717
|
-
const hasRSpecFile =
|
|
26718
|
-
const hasGemfile =
|
|
26719
|
-
const hasSpecDir =
|
|
27026
|
+
const hasRSpecFile = fs25.existsSync(path54.join(cwd, ".rspec"));
|
|
27027
|
+
const hasGemfile = fs25.existsSync(path54.join(cwd, "Gemfile"));
|
|
27028
|
+
const hasSpecDir = fs25.existsSync(path54.join(cwd, "spec"));
|
|
26720
27029
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
26721
27030
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
26722
27031
|
}
|
|
26723
27032
|
function detectMinitest(cwd) {
|
|
26724
|
-
return
|
|
27033
|
+
return fs25.existsSync(path54.join(cwd, "test")) && (fs25.existsSync(path54.join(cwd, "Gemfile")) || fs25.existsSync(path54.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
26725
27034
|
}
|
|
26726
27035
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
26727
27036
|
bun: "bun",
|
|
@@ -26806,9 +27115,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
26806
27115
|
async function detectTestFramework(cwd) {
|
|
26807
27116
|
const baseDir = cwd;
|
|
26808
27117
|
try {
|
|
26809
|
-
const packageJsonPath =
|
|
26810
|
-
if (
|
|
26811
|
-
const content =
|
|
27118
|
+
const packageJsonPath = path54.join(baseDir, "package.json");
|
|
27119
|
+
if (fs25.existsSync(packageJsonPath)) {
|
|
27120
|
+
const content = fs25.readFileSync(packageJsonPath, "utf-8");
|
|
26812
27121
|
const pkg = JSON.parse(content);
|
|
26813
27122
|
const _deps = pkg.dependencies || {};
|
|
26814
27123
|
const devDeps = pkg.devDependencies || {};
|
|
@@ -26827,38 +27136,38 @@ async function detectTestFramework(cwd) {
|
|
|
26827
27136
|
return "jest";
|
|
26828
27137
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
26829
27138
|
return "mocha";
|
|
26830
|
-
if (
|
|
27139
|
+
if (fs25.existsSync(path54.join(baseDir, "bun.lockb")) || fs25.existsSync(path54.join(baseDir, "bun.lock"))) {
|
|
26831
27140
|
if (scripts.test?.includes("bun"))
|
|
26832
27141
|
return "bun";
|
|
26833
27142
|
}
|
|
26834
27143
|
}
|
|
26835
27144
|
} catch {}
|
|
26836
27145
|
try {
|
|
26837
|
-
const pyprojectTomlPath =
|
|
26838
|
-
const setupCfgPath =
|
|
26839
|
-
const requirementsTxtPath =
|
|
26840
|
-
if (
|
|
26841
|
-
const content =
|
|
27146
|
+
const pyprojectTomlPath = path54.join(baseDir, "pyproject.toml");
|
|
27147
|
+
const setupCfgPath = path54.join(baseDir, "setup.cfg");
|
|
27148
|
+
const requirementsTxtPath = path54.join(baseDir, "requirements.txt");
|
|
27149
|
+
if (fs25.existsSync(pyprojectTomlPath)) {
|
|
27150
|
+
const content = fs25.readFileSync(pyprojectTomlPath, "utf-8");
|
|
26842
27151
|
if (content.includes("[tool.pytest"))
|
|
26843
27152
|
return "pytest";
|
|
26844
27153
|
if (content.includes("pytest"))
|
|
26845
27154
|
return "pytest";
|
|
26846
27155
|
}
|
|
26847
|
-
if (
|
|
26848
|
-
const content =
|
|
27156
|
+
if (fs25.existsSync(setupCfgPath)) {
|
|
27157
|
+
const content = fs25.readFileSync(setupCfgPath, "utf-8");
|
|
26849
27158
|
if (content.includes("[pytest]"))
|
|
26850
27159
|
return "pytest";
|
|
26851
27160
|
}
|
|
26852
|
-
if (
|
|
26853
|
-
const content =
|
|
27161
|
+
if (fs25.existsSync(requirementsTxtPath)) {
|
|
27162
|
+
const content = fs25.readFileSync(requirementsTxtPath, "utf-8");
|
|
26854
27163
|
if (content.includes("pytest"))
|
|
26855
27164
|
return "pytest";
|
|
26856
27165
|
}
|
|
26857
27166
|
} catch {}
|
|
26858
27167
|
try {
|
|
26859
|
-
const cargoTomlPath =
|
|
26860
|
-
if (
|
|
26861
|
-
const content =
|
|
27168
|
+
const cargoTomlPath = path54.join(baseDir, "Cargo.toml");
|
|
27169
|
+
if (fs25.existsSync(cargoTomlPath)) {
|
|
27170
|
+
const content = fs25.readFileSync(cargoTomlPath, "utf-8");
|
|
26862
27171
|
if (content.includes("[dev-dependencies]")) {
|
|
26863
27172
|
if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
|
|
26864
27173
|
return "cargo";
|
|
@@ -26867,10 +27176,10 @@ async function detectTestFramework(cwd) {
|
|
|
26867
27176
|
}
|
|
26868
27177
|
} catch {}
|
|
26869
27178
|
try {
|
|
26870
|
-
const pesterConfigPath =
|
|
26871
|
-
const pesterConfigJsonPath =
|
|
26872
|
-
const pesterPs1Path =
|
|
26873
|
-
if (
|
|
27179
|
+
const pesterConfigPath = path54.join(baseDir, "pester.config.ps1");
|
|
27180
|
+
const pesterConfigJsonPath = path54.join(baseDir, "pester.config.ps1.json");
|
|
27181
|
+
const pesterPs1Path = path54.join(baseDir, "tests.ps1");
|
|
27182
|
+
if (fs25.existsSync(pesterConfigPath) || fs25.existsSync(pesterConfigJsonPath) || fs25.existsSync(pesterPs1Path)) {
|
|
26874
27183
|
return "pester";
|
|
26875
27184
|
}
|
|
26876
27185
|
} catch {}
|
|
@@ -26912,12 +27221,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
26912
27221
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
26913
27222
|
}
|
|
26914
27223
|
function resolveWorkspacePath(file, workingDir) {
|
|
26915
|
-
return
|
|
27224
|
+
return path54.isAbsolute(file) ? path54.resolve(file) : path54.resolve(workingDir, file);
|
|
26916
27225
|
}
|
|
26917
27226
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
26918
27227
|
if (!preferRelative)
|
|
26919
27228
|
return absolutePath;
|
|
26920
|
-
return
|
|
27229
|
+
return path54.relative(workingDir, absolutePath);
|
|
26921
27230
|
}
|
|
26922
27231
|
function dedupePush(target, value) {
|
|
26923
27232
|
if (!target.includes(value)) {
|
|
@@ -26954,18 +27263,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
26954
27263
|
}
|
|
26955
27264
|
}
|
|
26956
27265
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
26957
|
-
const relativeDir =
|
|
27266
|
+
const relativeDir = path54.dirname(relativePath);
|
|
26958
27267
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
26959
27268
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
26960
|
-
const rootDir =
|
|
26961
|
-
return nestedRelativeDir ? [rootDir,
|
|
27269
|
+
const rootDir = path54.join(workingDir, dirName);
|
|
27270
|
+
return nestedRelativeDir ? [rootDir, path54.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
26962
27271
|
});
|
|
26963
27272
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
26964
27273
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
26965
|
-
directories.push(
|
|
27274
|
+
directories.push(path54.join(workingDir, "src/test/java", path54.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
26966
27275
|
}
|
|
26967
27276
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
26968
|
-
directories.push(
|
|
27277
|
+
directories.push(path54.join(workingDir, "src/test/kotlin", path54.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
26969
27278
|
}
|
|
26970
27279
|
return [...new Set(directories)];
|
|
26971
27280
|
}
|
|
@@ -26973,19 +27282,19 @@ function hasCompoundTestExtension(filename) {
|
|
|
26973
27282
|
const lower = filename.toLowerCase();
|
|
26974
27283
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
26975
27284
|
}
|
|
26976
|
-
function isLanguageSpecificTestFile(
|
|
26977
|
-
const lower =
|
|
27285
|
+
function isLanguageSpecificTestFile(basename10) {
|
|
27286
|
+
const lower = basename10.toLowerCase();
|
|
26978
27287
|
if (lower.endsWith("_test.go"))
|
|
26979
27288
|
return true;
|
|
26980
27289
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
26981
27290
|
return true;
|
|
26982
27291
|
if (lower.endsWith("_spec.rb"))
|
|
26983
27292
|
return true;
|
|
26984
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
27293
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename10) || basename10.endsWith("Test.java") || basename10.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
26985
27294
|
return true;
|
|
26986
27295
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
26987
27296
|
return true;
|
|
26988
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
27297
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename10) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
26989
27298
|
return true;
|
|
26990
27299
|
if (lower.endsWith(".tests.ps1"))
|
|
26991
27300
|
return true;
|
|
@@ -26993,23 +27302,23 @@ function isLanguageSpecificTestFile(basename9) {
|
|
|
26993
27302
|
}
|
|
26994
27303
|
function isConventionTestFilePath(filePath) {
|
|
26995
27304
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26996
|
-
const
|
|
26997
|
-
return hasCompoundTestExtension(
|
|
27305
|
+
const basename10 = path54.basename(filePath);
|
|
27306
|
+
return hasCompoundTestExtension(basename10) || basename10.includes(".spec.") || basename10.includes(".test.") || isLanguageSpecificTestFile(basename10) || isTestDirectoryPath(normalizedPath);
|
|
26998
27307
|
}
|
|
26999
27308
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
27000
27309
|
const testFiles = [];
|
|
27001
27310
|
for (const file of sourceFiles) {
|
|
27002
27311
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
27003
|
-
const relativeFile =
|
|
27004
|
-
const
|
|
27005
|
-
const dirname25 =
|
|
27006
|
-
const preferRelativeOutput = !
|
|
27312
|
+
const relativeFile = path54.relative(workingDir, absoluteFile);
|
|
27313
|
+
const basename10 = path54.basename(absoluteFile);
|
|
27314
|
+
const dirname25 = path54.dirname(absoluteFile);
|
|
27315
|
+
const preferRelativeOutput = !path54.isAbsolute(file);
|
|
27007
27316
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
27008
27317
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
27009
27318
|
continue;
|
|
27010
27319
|
}
|
|
27011
|
-
const nameWithoutExt =
|
|
27012
|
-
const ext =
|
|
27320
|
+
const nameWithoutExt = basename10.replace(/\.[^.]+$/, "");
|
|
27321
|
+
const ext = path54.extname(basename10);
|
|
27013
27322
|
const genericTestNames = [
|
|
27014
27323
|
`${nameWithoutExt}.spec${ext}`,
|
|
27015
27324
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -27018,20 +27327,20 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
27018
27327
|
const colocatedCandidates = [
|
|
27019
27328
|
...genericTestNames,
|
|
27020
27329
|
...languageSpecificTestNames
|
|
27021
|
-
].map((candidateName) =>
|
|
27330
|
+
].map((candidateName) => path54.join(dirname25, candidateName));
|
|
27022
27331
|
const testDirectoryNames = [
|
|
27023
|
-
|
|
27332
|
+
basename10,
|
|
27024
27333
|
...genericTestNames,
|
|
27025
27334
|
...languageSpecificTestNames
|
|
27026
27335
|
];
|
|
27027
27336
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
27028
27337
|
const possibleTestFiles = [
|
|
27029
27338
|
...colocatedCandidates,
|
|
27030
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
27031
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
27339
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path54.join(dirname25, dirName, candidateName))),
|
|
27340
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path54.join(candidateDir, candidateName)))
|
|
27032
27341
|
];
|
|
27033
27342
|
for (const testFile of possibleTestFiles) {
|
|
27034
|
-
if (
|
|
27343
|
+
if (fs25.existsSync(testFile)) {
|
|
27035
27344
|
dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
|
|
27036
27345
|
}
|
|
27037
27346
|
}
|
|
@@ -27048,8 +27357,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27048
27357
|
for (const testFile of candidateTestFiles) {
|
|
27049
27358
|
try {
|
|
27050
27359
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
27051
|
-
const content =
|
|
27052
|
-
const testDir =
|
|
27360
|
+
const content = fs25.readFileSync(absoluteTestFile, "utf-8");
|
|
27361
|
+
const testDir = path54.dirname(absoluteTestFile);
|
|
27053
27362
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
27054
27363
|
let match;
|
|
27055
27364
|
match = importRegex.exec(content);
|
|
@@ -27057,8 +27366,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27057
27366
|
const importPath = match[1];
|
|
27058
27367
|
let resolvedImport;
|
|
27059
27368
|
if (importPath.startsWith(".")) {
|
|
27060
|
-
resolvedImport =
|
|
27061
|
-
const existingExt =
|
|
27369
|
+
resolvedImport = path54.resolve(testDir, importPath);
|
|
27370
|
+
const existingExt = path54.extname(resolvedImport);
|
|
27062
27371
|
if (!existingExt) {
|
|
27063
27372
|
for (const extToTry of [
|
|
27064
27373
|
".ts",
|
|
@@ -27069,7 +27378,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27069
27378
|
".cjs"
|
|
27070
27379
|
]) {
|
|
27071
27380
|
const withExt = resolvedImport + extToTry;
|
|
27072
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
27381
|
+
if (absoluteSourceFiles.includes(withExt) || fs25.existsSync(withExt)) {
|
|
27073
27382
|
resolvedImport = withExt;
|
|
27074
27383
|
break;
|
|
27075
27384
|
}
|
|
@@ -27078,12 +27387,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27078
27387
|
} else {
|
|
27079
27388
|
continue;
|
|
27080
27389
|
}
|
|
27081
|
-
const importBasename =
|
|
27082
|
-
const importDir =
|
|
27390
|
+
const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
|
|
27391
|
+
const importDir = path54.dirname(resolvedImport);
|
|
27083
27392
|
for (const sourceFile of absoluteSourceFiles) {
|
|
27084
|
-
const sourceDir =
|
|
27085
|
-
const sourceBasename =
|
|
27086
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
27393
|
+
const sourceDir = path54.dirname(sourceFile);
|
|
27394
|
+
const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
|
|
27395
|
+
const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
|
|
27087
27396
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
27088
27397
|
dedupePush(testFiles, testFile);
|
|
27089
27398
|
break;
|
|
@@ -27096,8 +27405,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27096
27405
|
while (match !== null) {
|
|
27097
27406
|
const importPath = match[1];
|
|
27098
27407
|
if (importPath.startsWith(".")) {
|
|
27099
|
-
let resolvedImport =
|
|
27100
|
-
const existingExt =
|
|
27408
|
+
let resolvedImport = path54.resolve(testDir, importPath);
|
|
27409
|
+
const existingExt = path54.extname(resolvedImport);
|
|
27101
27410
|
if (!existingExt) {
|
|
27102
27411
|
for (const extToTry of [
|
|
27103
27412
|
".ts",
|
|
@@ -27108,18 +27417,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
27108
27417
|
".cjs"
|
|
27109
27418
|
]) {
|
|
27110
27419
|
const withExt = resolvedImport + extToTry;
|
|
27111
|
-
if (absoluteSourceFiles.includes(withExt) ||
|
|
27420
|
+
if (absoluteSourceFiles.includes(withExt) || fs25.existsSync(withExt)) {
|
|
27112
27421
|
resolvedImport = withExt;
|
|
27113
27422
|
break;
|
|
27114
27423
|
}
|
|
27115
27424
|
}
|
|
27116
27425
|
}
|
|
27117
|
-
const importDir =
|
|
27118
|
-
const importBasename =
|
|
27426
|
+
const importDir = path54.dirname(resolvedImport);
|
|
27427
|
+
const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
|
|
27119
27428
|
for (const sourceFile of absoluteSourceFiles) {
|
|
27120
|
-
const sourceDir =
|
|
27121
|
-
const sourceBasename =
|
|
27122
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
27429
|
+
const sourceDir = path54.dirname(sourceFile);
|
|
27430
|
+
const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
|
|
27431
|
+
const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
|
|
27123
27432
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
27124
27433
|
dedupePush(testFiles, testFile);
|
|
27125
27434
|
break;
|
|
@@ -27239,8 +27548,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
27239
27548
|
return ["mvn", "test"];
|
|
27240
27549
|
case "gradle": {
|
|
27241
27550
|
const isWindows = process.platform === "win32";
|
|
27242
|
-
const hasGradlewBat =
|
|
27243
|
-
const hasGradlew =
|
|
27551
|
+
const hasGradlewBat = fs25.existsSync(path54.join(baseDir, "gradlew.bat"));
|
|
27552
|
+
const hasGradlew = fs25.existsSync(path54.join(baseDir, "gradlew"));
|
|
27244
27553
|
if (hasGradlewBat && isWindows)
|
|
27245
27554
|
return ["gradlew.bat", "test"];
|
|
27246
27555
|
if (hasGradlew)
|
|
@@ -27257,7 +27566,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
27257
27566
|
"cmake-build-release",
|
|
27258
27567
|
"out"
|
|
27259
27568
|
];
|
|
27260
|
-
const actualBuildDir = buildDirCandidates.find((d) =>
|
|
27569
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs25.existsSync(path54.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
27261
27570
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
27262
27571
|
}
|
|
27263
27572
|
case "swift-test":
|
|
@@ -27691,13 +28000,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27691
28000
|
};
|
|
27692
28001
|
}
|
|
27693
28002
|
const startTime = Date.now();
|
|
27694
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
28003
|
+
const vitestJsonOutputPath = framework === "vitest" ? path54.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
27695
28004
|
try {
|
|
27696
28005
|
if (vitestJsonOutputPath) {
|
|
27697
28006
|
try {
|
|
27698
|
-
|
|
27699
|
-
if (
|
|
27700
|
-
|
|
28007
|
+
fs25.mkdirSync(path54.dirname(vitestJsonOutputPath), { recursive: true });
|
|
28008
|
+
if (fs25.existsSync(vitestJsonOutputPath)) {
|
|
28009
|
+
fs25.unlinkSync(vitestJsonOutputPath);
|
|
27701
28010
|
}
|
|
27702
28011
|
} catch {}
|
|
27703
28012
|
}
|
|
@@ -27723,8 +28032,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
27723
28032
|
}
|
|
27724
28033
|
if (vitestJsonOutputPath) {
|
|
27725
28034
|
try {
|
|
27726
|
-
if (
|
|
27727
|
-
const vitestJsonOutput =
|
|
28035
|
+
if (fs25.existsSync(vitestJsonOutputPath)) {
|
|
28036
|
+
const vitestJsonOutput = fs25.readFileSync(vitestJsonOutputPath, "utf-8");
|
|
27728
28037
|
if (vitestJsonOutput.trim().length > 0) {
|
|
27729
28038
|
output += (output ? `
|
|
27730
28039
|
` : "") + vitestJsonOutput;
|
|
@@ -27863,10 +28172,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
27863
28172
|
]);
|
|
27864
28173
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
27865
28174
|
const normalized = testFile.replace(/\\/g, "/");
|
|
27866
|
-
if (!
|
|
28175
|
+
if (!path54.isAbsolute(testFile))
|
|
27867
28176
|
return normalized;
|
|
27868
|
-
const relative8 =
|
|
27869
|
-
if (relative8.startsWith("..") ||
|
|
28177
|
+
const relative8 = path54.relative(workingDir, testFile);
|
|
28178
|
+
if (relative8.startsWith("..") || path54.isAbsolute(relative8)) {
|
|
27870
28179
|
return normalized;
|
|
27871
28180
|
}
|
|
27872
28181
|
return relative8.replace(/\\/g, "/");
|
|
@@ -28105,7 +28414,7 @@ var test_runner = createSwarmTool({
|
|
|
28105
28414
|
const sourceFiles = args.files.filter((file) => {
|
|
28106
28415
|
if (directTestFiles.includes(file))
|
|
28107
28416
|
return false;
|
|
28108
|
-
const ext =
|
|
28417
|
+
const ext = path54.extname(file).toLowerCase();
|
|
28109
28418
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28110
28419
|
});
|
|
28111
28420
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -28151,7 +28460,7 @@ var test_runner = createSwarmTool({
|
|
|
28151
28460
|
if (isConventionTestFilePath(f)) {
|
|
28152
28461
|
return false;
|
|
28153
28462
|
}
|
|
28154
|
-
const ext =
|
|
28463
|
+
const ext = path54.extname(f).toLowerCase();
|
|
28155
28464
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28156
28465
|
});
|
|
28157
28466
|
if (sourceFiles.length === 0) {
|
|
@@ -28201,7 +28510,7 @@ var test_runner = createSwarmTool({
|
|
|
28201
28510
|
if (isConventionTestFilePath(f)) {
|
|
28202
28511
|
return false;
|
|
28203
28512
|
}
|
|
28204
|
-
const ext =
|
|
28513
|
+
const ext = path54.extname(f).toLowerCase();
|
|
28205
28514
|
return SOURCE_EXTENSIONS.has(ext);
|
|
28206
28515
|
});
|
|
28207
28516
|
if (sourceFiles.length === 0) {
|
|
@@ -28253,8 +28562,8 @@ var test_runner = createSwarmTool({
|
|
|
28253
28562
|
}
|
|
28254
28563
|
if (impactResult.impactedTests.length > 0) {
|
|
28255
28564
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
28256
|
-
const relativePath =
|
|
28257
|
-
return
|
|
28565
|
+
const relativePath = path54.relative(workingDir, absPath);
|
|
28566
|
+
return path54.isAbsolute(relativePath) ? absPath : relativePath;
|
|
28258
28567
|
});
|
|
28259
28568
|
} else {
|
|
28260
28569
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -28349,8 +28658,8 @@ function validateDirectoryPath(dir) {
|
|
|
28349
28658
|
if (dir.includes("..")) {
|
|
28350
28659
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
28351
28660
|
}
|
|
28352
|
-
const normalized =
|
|
28353
|
-
const absolutePath =
|
|
28661
|
+
const normalized = path55.normalize(dir);
|
|
28662
|
+
const absolutePath = path55.isAbsolute(normalized) ? normalized : path55.resolve(normalized);
|
|
28354
28663
|
return absolutePath;
|
|
28355
28664
|
}
|
|
28356
28665
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -28373,9 +28682,9 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
28373
28682
|
}
|
|
28374
28683
|
function getPackageVersion(dir) {
|
|
28375
28684
|
try {
|
|
28376
|
-
const packagePath =
|
|
28377
|
-
if (
|
|
28378
|
-
const content =
|
|
28685
|
+
const packagePath = path55.join(dir, "package.json");
|
|
28686
|
+
if (fs26.existsSync(packagePath)) {
|
|
28687
|
+
const content = fs26.readFileSync(packagePath, "utf-8");
|
|
28379
28688
|
const pkg = JSON.parse(content);
|
|
28380
28689
|
return pkg.version ?? null;
|
|
28381
28690
|
}
|
|
@@ -28384,9 +28693,9 @@ function getPackageVersion(dir) {
|
|
|
28384
28693
|
}
|
|
28385
28694
|
function getChangelogVersion(dir) {
|
|
28386
28695
|
try {
|
|
28387
|
-
const changelogPath =
|
|
28388
|
-
if (
|
|
28389
|
-
const content =
|
|
28696
|
+
const changelogPath = path55.join(dir, "CHANGELOG.md");
|
|
28697
|
+
if (fs26.existsSync(changelogPath)) {
|
|
28698
|
+
const content = fs26.readFileSync(changelogPath, "utf-8");
|
|
28390
28699
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
28391
28700
|
if (match) {
|
|
28392
28701
|
return match[1];
|
|
@@ -28398,10 +28707,10 @@ function getChangelogVersion(dir) {
|
|
|
28398
28707
|
function getVersionFileVersion(dir) {
|
|
28399
28708
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
28400
28709
|
for (const file of possibleFiles) {
|
|
28401
|
-
const filePath =
|
|
28402
|
-
if (
|
|
28710
|
+
const filePath = path55.join(dir, file);
|
|
28711
|
+
if (fs26.existsSync(filePath)) {
|
|
28403
28712
|
try {
|
|
28404
|
-
const content =
|
|
28713
|
+
const content = fs26.readFileSync(filePath, "utf-8").trim();
|
|
28405
28714
|
const match = content.match(/(\d+\.\d+\.\d+)/);
|
|
28406
28715
|
if (match) {
|
|
28407
28716
|
return match[1];
|
|
@@ -29135,8 +29444,8 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
29135
29444
|
}
|
|
29136
29445
|
|
|
29137
29446
|
// src/commands/reset.ts
|
|
29138
|
-
import * as
|
|
29139
|
-
import * as
|
|
29447
|
+
import * as fs27 from "fs";
|
|
29448
|
+
import * as path56 from "path";
|
|
29140
29449
|
|
|
29141
29450
|
// src/background/circuit-breaker.ts
|
|
29142
29451
|
class CircuitBreaker {
|
|
@@ -29843,8 +30152,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29843
30152
|
for (const filename of filesToReset) {
|
|
29844
30153
|
try {
|
|
29845
30154
|
const resolvedPath = validateSwarmPath(directory, filename);
|
|
29846
|
-
if (
|
|
29847
|
-
|
|
30155
|
+
if (fs27.existsSync(resolvedPath)) {
|
|
30156
|
+
fs27.unlinkSync(resolvedPath);
|
|
29848
30157
|
results.push(`- \u2705 Deleted ${filename}`);
|
|
29849
30158
|
} else {
|
|
29850
30159
|
results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
|
|
@@ -29855,9 +30164,9 @@ async function handleResetCommand(directory, args) {
|
|
|
29855
30164
|
}
|
|
29856
30165
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
29857
30166
|
try {
|
|
29858
|
-
const rootPath =
|
|
29859
|
-
if (
|
|
29860
|
-
|
|
30167
|
+
const rootPath = path56.join(directory, filename);
|
|
30168
|
+
if (fs27.existsSync(rootPath)) {
|
|
30169
|
+
fs27.unlinkSync(rootPath);
|
|
29861
30170
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
29862
30171
|
}
|
|
29863
30172
|
} catch (err) {
|
|
@@ -29872,8 +30181,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29872
30181
|
}
|
|
29873
30182
|
try {
|
|
29874
30183
|
const summariesPath = validateSwarmPath(directory, "summaries");
|
|
29875
|
-
if (
|
|
29876
|
-
|
|
30184
|
+
if (fs27.existsSync(summariesPath)) {
|
|
30185
|
+
fs27.rmSync(summariesPath, { recursive: true, force: true });
|
|
29877
30186
|
results.push("- \u2705 Deleted summaries/ directory");
|
|
29878
30187
|
} else {
|
|
29879
30188
|
results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
|
|
@@ -29892,8 +30201,8 @@ async function handleResetCommand(directory, args) {
|
|
|
29892
30201
|
}
|
|
29893
30202
|
|
|
29894
30203
|
// src/commands/reset-session.ts
|
|
29895
|
-
import * as
|
|
29896
|
-
import * as
|
|
30204
|
+
import * as fs29 from "fs";
|
|
30205
|
+
import * as path58 from "path";
|
|
29897
30206
|
|
|
29898
30207
|
// src/hooks/trajectory-logger.ts
|
|
29899
30208
|
var callStartTimes = new Map;
|
|
@@ -30299,17 +30608,17 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
30299
30608
|
};
|
|
30300
30609
|
}
|
|
30301
30610
|
// src/prm/replay.ts
|
|
30302
|
-
import { promises as
|
|
30303
|
-
import
|
|
30611
|
+
import { promises as fs28 } from "fs";
|
|
30612
|
+
import path57 from "path";
|
|
30304
30613
|
function isPathSafe(targetPath, basePath) {
|
|
30305
|
-
const resolvedTarget =
|
|
30306
|
-
const resolvedBase =
|
|
30307
|
-
const rel =
|
|
30308
|
-
return !rel.startsWith("..") && !
|
|
30614
|
+
const resolvedTarget = path57.resolve(targetPath);
|
|
30615
|
+
const resolvedBase = path57.resolve(basePath);
|
|
30616
|
+
const rel = path57.relative(resolvedBase, resolvedTarget);
|
|
30617
|
+
return !rel.startsWith("..") && !path57.isAbsolute(rel);
|
|
30309
30618
|
}
|
|
30310
30619
|
function isWithinReplaysDir(targetPath) {
|
|
30311
|
-
const resolved =
|
|
30312
|
-
const parts = resolved.split(
|
|
30620
|
+
const resolved = path57.resolve(targetPath);
|
|
30621
|
+
const parts = resolved.split(path57.sep);
|
|
30313
30622
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
30314
30623
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
30315
30624
|
return true;
|
|
@@ -30322,15 +30631,15 @@ function sanitizeFilename(input) {
|
|
|
30322
30631
|
}
|
|
30323
30632
|
async function startReplayRecording(sessionID, directory) {
|
|
30324
30633
|
try {
|
|
30325
|
-
const replayDir =
|
|
30634
|
+
const replayDir = path57.join(directory, ".swarm", "replays");
|
|
30326
30635
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
30327
30636
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
30328
|
-
const filepath =
|
|
30637
|
+
const filepath = path57.join(replayDir, filename);
|
|
30329
30638
|
if (!isPathSafe(filepath, replayDir)) {
|
|
30330
30639
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
30331
30640
|
return null;
|
|
30332
30641
|
}
|
|
30333
|
-
await
|
|
30642
|
+
await fs28.mkdir(replayDir, { recursive: true });
|
|
30334
30643
|
return filepath;
|
|
30335
30644
|
} catch (err) {
|
|
30336
30645
|
console.warn(`[replay] Failed to start recording for session ${sessionID}: ${err}`);
|
|
@@ -30350,7 +30659,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
|
|
|
30350
30659
|
};
|
|
30351
30660
|
const line = `${JSON.stringify(fullEntry)}
|
|
30352
30661
|
`;
|
|
30353
|
-
await
|
|
30662
|
+
await fs28.appendFile(artifactPath, line, "utf-8");
|
|
30354
30663
|
} catch (err) {
|
|
30355
30664
|
console.warn(`[replay] Failed to record entry: ${err}`);
|
|
30356
30665
|
}
|
|
@@ -30394,8 +30703,8 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30394
30703
|
const results = [];
|
|
30395
30704
|
try {
|
|
30396
30705
|
const statePath = validateSwarmPath(directory, "session/state.json");
|
|
30397
|
-
if (
|
|
30398
|
-
|
|
30706
|
+
if (fs29.existsSync(statePath)) {
|
|
30707
|
+
fs29.unlinkSync(statePath);
|
|
30399
30708
|
results.push("\u2705 Deleted .swarm/session/state.json");
|
|
30400
30709
|
} else {
|
|
30401
30710
|
results.push("\u23ED\uFE0F state.json not found (already clean)");
|
|
@@ -30403,11 +30712,11 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30403
30712
|
} catch {
|
|
30404
30713
|
results.push("\u274C Failed to delete state.json");
|
|
30405
30714
|
}
|
|
30406
|
-
const sessionDir =
|
|
30715
|
+
const sessionDir = path58.dirname(validateSwarmPath(directory, "session/state.json"));
|
|
30407
30716
|
let sessionFiles = [];
|
|
30408
|
-
if (
|
|
30717
|
+
if (fs29.existsSync(sessionDir)) {
|
|
30409
30718
|
try {
|
|
30410
|
-
sessionFiles =
|
|
30719
|
+
sessionFiles = fs29.readdirSync(sessionDir);
|
|
30411
30720
|
} catch (err) {
|
|
30412
30721
|
results.push(`\u274C Failed to read session directory: ${errorMessage(err)}`);
|
|
30413
30722
|
}
|
|
@@ -30415,13 +30724,13 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30415
30724
|
for (const file of sessionFiles) {
|
|
30416
30725
|
if (file === "state.json")
|
|
30417
30726
|
continue;
|
|
30418
|
-
const filePath =
|
|
30727
|
+
const filePath = path58.join(sessionDir, file);
|
|
30419
30728
|
try {
|
|
30420
|
-
if (!
|
|
30729
|
+
if (!fs29.existsSync(filePath))
|
|
30421
30730
|
continue;
|
|
30422
|
-
if (!
|
|
30731
|
+
if (!fs29.lstatSync(filePath).isFile())
|
|
30423
30732
|
continue;
|
|
30424
|
-
|
|
30733
|
+
fs29.unlinkSync(filePath);
|
|
30425
30734
|
results.push(`\u2713 Deleted ${file}`);
|
|
30426
30735
|
} catch (err) {
|
|
30427
30736
|
results.push(`\u274C Failed to delete ${file}: ${errorMessage(err)}`);
|
|
@@ -30450,7 +30759,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
30450
30759
|
}
|
|
30451
30760
|
|
|
30452
30761
|
// src/summaries/manager.ts
|
|
30453
|
-
import * as
|
|
30762
|
+
import * as path59 from "path";
|
|
30454
30763
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
30455
30764
|
function sanitizeSummaryId(id) {
|
|
30456
30765
|
if (!id || id.length === 0) {
|
|
@@ -30474,7 +30783,7 @@ function sanitizeSummaryId(id) {
|
|
|
30474
30783
|
}
|
|
30475
30784
|
async function loadFullOutput(directory, id) {
|
|
30476
30785
|
const sanitizedId = sanitizeSummaryId(id);
|
|
30477
|
-
const relativePath =
|
|
30786
|
+
const relativePath = path59.join("summaries", `${sanitizedId}.json`);
|
|
30478
30787
|
validateSwarmPath(directory, relativePath);
|
|
30479
30788
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
30480
30789
|
if (content === null) {
|
|
@@ -30526,18 +30835,18 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
30526
30835
|
}
|
|
30527
30836
|
|
|
30528
30837
|
// src/commands/rollback.ts
|
|
30529
|
-
import * as
|
|
30530
|
-
import * as
|
|
30838
|
+
import * as fs30 from "fs";
|
|
30839
|
+
import * as path60 from "path";
|
|
30531
30840
|
async function handleRollbackCommand(directory, args) {
|
|
30532
30841
|
const phaseArg = args[0];
|
|
30533
30842
|
if (!phaseArg) {
|
|
30534
30843
|
const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
30535
|
-
if (!
|
|
30844
|
+
if (!fs30.existsSync(manifestPath2)) {
|
|
30536
30845
|
return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
|
|
30537
30846
|
}
|
|
30538
30847
|
let manifest2;
|
|
30539
30848
|
try {
|
|
30540
|
-
manifest2 = JSON.parse(
|
|
30849
|
+
manifest2 = JSON.parse(fs30.readFileSync(manifestPath2, "utf-8"));
|
|
30541
30850
|
} catch {
|
|
30542
30851
|
return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
|
|
30543
30852
|
}
|
|
@@ -30559,12 +30868,12 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30559
30868
|
return "Error: Phase number must be a positive integer.";
|
|
30560
30869
|
}
|
|
30561
30870
|
const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
|
|
30562
|
-
if (!
|
|
30871
|
+
if (!fs30.existsSync(manifestPath)) {
|
|
30563
30872
|
return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
|
|
30564
30873
|
}
|
|
30565
30874
|
let manifest;
|
|
30566
30875
|
try {
|
|
30567
|
-
manifest = JSON.parse(
|
|
30876
|
+
manifest = JSON.parse(fs30.readFileSync(manifestPath, "utf-8"));
|
|
30568
30877
|
} catch {
|
|
30569
30878
|
return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
|
|
30570
30879
|
}
|
|
@@ -30574,10 +30883,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30574
30883
|
return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
|
|
30575
30884
|
}
|
|
30576
30885
|
const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
|
|
30577
|
-
if (!
|
|
30886
|
+
if (!fs30.existsSync(checkpointDir)) {
|
|
30578
30887
|
return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
|
|
30579
30888
|
}
|
|
30580
|
-
const checkpointFiles =
|
|
30889
|
+
const checkpointFiles = fs30.readdirSync(checkpointDir);
|
|
30581
30890
|
if (checkpointFiles.length === 0) {
|
|
30582
30891
|
return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
|
|
30583
30892
|
}
|
|
@@ -30593,10 +30902,10 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30593
30902
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
30594
30903
|
continue;
|
|
30595
30904
|
}
|
|
30596
|
-
const src =
|
|
30597
|
-
const dest =
|
|
30905
|
+
const src = path60.join(checkpointDir, file);
|
|
30906
|
+
const dest = path60.join(swarmDir, file);
|
|
30598
30907
|
try {
|
|
30599
|
-
|
|
30908
|
+
fs30.cpSync(src, dest, { recursive: true, force: true });
|
|
30600
30909
|
successes.push(file);
|
|
30601
30910
|
} catch (error2) {
|
|
30602
30911
|
failures.push({ file, error: error2.message });
|
|
@@ -30613,11 +30922,11 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30613
30922
|
].join(`
|
|
30614
30923
|
`);
|
|
30615
30924
|
}
|
|
30616
|
-
const existingLedgerPath =
|
|
30925
|
+
const existingLedgerPath = path60.join(swarmDir, "plan-ledger.jsonl");
|
|
30617
30926
|
let ledgerDeletionFailed = false;
|
|
30618
|
-
if (
|
|
30927
|
+
if (fs30.existsSync(existingLedgerPath)) {
|
|
30619
30928
|
try {
|
|
30620
|
-
|
|
30929
|
+
fs30.unlinkSync(existingLedgerPath);
|
|
30621
30930
|
} catch (err) {
|
|
30622
30931
|
ledgerDeletionFailed = true;
|
|
30623
30932
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -30626,9 +30935,9 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30626
30935
|
}
|
|
30627
30936
|
if (!ledgerDeletionFailed) {
|
|
30628
30937
|
try {
|
|
30629
|
-
const planJsonPath =
|
|
30630
|
-
if (
|
|
30631
|
-
const planRaw =
|
|
30938
|
+
const planJsonPath = path60.join(swarmDir, "plan.json");
|
|
30939
|
+
if (fs30.existsSync(planJsonPath)) {
|
|
30940
|
+
const planRaw = fs30.readFileSync(planJsonPath, "utf-8");
|
|
30632
30941
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
30633
30942
|
const planId = derivePlanId(plan);
|
|
30634
30943
|
const planHash = computePlanHash(plan);
|
|
@@ -30656,7 +30965,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30656
30965
|
timestamp: new Date().toISOString()
|
|
30657
30966
|
};
|
|
30658
30967
|
try {
|
|
30659
|
-
|
|
30968
|
+
fs30.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
|
|
30660
30969
|
`);
|
|
30661
30970
|
} catch (error2) {
|
|
30662
30971
|
console.error("Failed to write rollback event:", error2 instanceof Error ? error2.message : String(error2));
|
|
@@ -30838,7 +31147,7 @@ async function handleSddCommand(_directory, _args) {
|
|
|
30838
31147
|
}
|
|
30839
31148
|
|
|
30840
31149
|
// src/commands/simulate.ts
|
|
30841
|
-
import { renameSync as renameSync11, unlinkSync as
|
|
31150
|
+
import { renameSync as renameSync11, unlinkSync as unlinkSync12 } from "fs";
|
|
30842
31151
|
async function handleSimulateCommand(directory, args) {
|
|
30843
31152
|
const thresholdIndex = args.indexOf("--threshold");
|
|
30844
31153
|
const minCommitsIndex = args.indexOf("--min-commits");
|
|
@@ -30886,17 +31195,17 @@ Ensure this is a git repository with commit history.`;
|
|
|
30886
31195
|
const report = reportLines.filter(Boolean).join(`
|
|
30887
31196
|
`);
|
|
30888
31197
|
try {
|
|
30889
|
-
const
|
|
30890
|
-
const
|
|
30891
|
-
const reportPath =
|
|
30892
|
-
await
|
|
30893
|
-
const reportTempPath =
|
|
31198
|
+
const fs31 = await import("fs/promises");
|
|
31199
|
+
const path61 = await import("path");
|
|
31200
|
+
const reportPath = path61.join(directory, ".swarm", "simulate-report.md");
|
|
31201
|
+
await fs31.mkdir(path61.dirname(reportPath), { recursive: true });
|
|
31202
|
+
const reportTempPath = path61.join(path61.dirname(reportPath), `${path61.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
30894
31203
|
try {
|
|
30895
|
-
await
|
|
31204
|
+
await fs31.writeFile(reportTempPath, report, "utf-8");
|
|
30896
31205
|
renameSync11(reportTempPath, reportPath);
|
|
30897
31206
|
} catch (err) {
|
|
30898
31207
|
try {
|
|
30899
|
-
|
|
31208
|
+
unlinkSync12(reportTempPath);
|
|
30900
31209
|
} catch {}
|
|
30901
31210
|
throw err;
|
|
30902
31211
|
}
|
|
@@ -30919,20 +31228,20 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
30919
31228
|
// src/services/status-service.ts
|
|
30920
31229
|
import * as fsSync3 from "fs";
|
|
30921
31230
|
import { readFile as readFile16 } from "fs/promises";
|
|
30922
|
-
import * as
|
|
31231
|
+
import * as path62 from "path";
|
|
30923
31232
|
|
|
30924
31233
|
// src/turbo/lean/state.ts
|
|
30925
31234
|
init_logger();
|
|
30926
|
-
import * as
|
|
30927
|
-
import * as
|
|
31235
|
+
import * as fs31 from "fs";
|
|
31236
|
+
import * as path61 from "path";
|
|
30928
31237
|
var STATE_FILE3 = "turbo-state.json";
|
|
30929
31238
|
function nowISO3() {
|
|
30930
31239
|
return new Date().toISOString();
|
|
30931
31240
|
}
|
|
30932
31241
|
function ensureSwarmDir2(directory) {
|
|
30933
|
-
const swarmDir =
|
|
30934
|
-
if (!
|
|
30935
|
-
|
|
31242
|
+
const swarmDir = path61.resolve(directory, ".swarm");
|
|
31243
|
+
if (!fs31.existsSync(swarmDir)) {
|
|
31244
|
+
fs31.mkdirSync(swarmDir, { recursive: true });
|
|
30936
31245
|
}
|
|
30937
31246
|
return swarmDir;
|
|
30938
31247
|
}
|
|
@@ -30975,17 +31284,17 @@ function markStateUnreadable2(directory, reason) {
|
|
|
30975
31284
|
}
|
|
30976
31285
|
function readPersisted2(directory) {
|
|
30977
31286
|
try {
|
|
30978
|
-
const filePath =
|
|
30979
|
-
if (!
|
|
31287
|
+
const filePath = path61.join(directory, ".swarm", STATE_FILE3);
|
|
31288
|
+
if (!fs31.existsSync(filePath)) {
|
|
30980
31289
|
const seed = emptyPersisted2();
|
|
30981
31290
|
try {
|
|
30982
31291
|
ensureSwarmDir2(directory);
|
|
30983
|
-
|
|
31292
|
+
fs31.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
|
|
30984
31293
|
`, "utf-8");
|
|
30985
31294
|
} catch {}
|
|
30986
31295
|
return seed;
|
|
30987
31296
|
}
|
|
30988
|
-
const raw =
|
|
31297
|
+
const raw = fs31.readFileSync(filePath, "utf-8");
|
|
30989
31298
|
const parsed = JSON.parse(raw);
|
|
30990
31299
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
|
|
30991
31300
|
markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
|
|
@@ -31011,7 +31320,7 @@ function writePersisted2(directory, persisted) {
|
|
|
31011
31320
|
let payload;
|
|
31012
31321
|
try {
|
|
31013
31322
|
ensureSwarmDir2(directory);
|
|
31014
|
-
filePath =
|
|
31323
|
+
filePath = path61.join(directory, ".swarm", STATE_FILE3);
|
|
31015
31324
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
31016
31325
|
persisted.updatedAt = nowISO3();
|
|
31017
31326
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -31022,14 +31331,14 @@ function writePersisted2(directory, persisted) {
|
|
|
31022
31331
|
throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
|
|
31023
31332
|
}
|
|
31024
31333
|
try {
|
|
31025
|
-
|
|
31026
|
-
|
|
31334
|
+
fs31.writeFileSync(tmpPath, payload, "utf-8");
|
|
31335
|
+
fs31.renameSync(tmpPath, filePath);
|
|
31027
31336
|
} catch (error2) {
|
|
31028
31337
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
31029
31338
|
error(`[turbo/lean/state] Failed to persist ${STATE_FILE3} atomically: ${msg}`);
|
|
31030
31339
|
try {
|
|
31031
|
-
if (
|
|
31032
|
-
|
|
31340
|
+
if (fs31.existsSync(tmpPath)) {
|
|
31341
|
+
fs31.unlinkSync(tmpPath);
|
|
31033
31342
|
}
|
|
31034
31343
|
} catch {}
|
|
31035
31344
|
throw new Error(`Lean Turbo state persistence failed: ${msg}`);
|
|
@@ -31129,7 +31438,7 @@ var _internals43 = {
|
|
|
31129
31438
|
};
|
|
31130
31439
|
function readSpecStalenessSnapshot(directory) {
|
|
31131
31440
|
try {
|
|
31132
|
-
const p =
|
|
31441
|
+
const p = path62.join(directory, ".swarm", "spec-staleness.json");
|
|
31133
31442
|
if (!fsSync3.existsSync(p))
|
|
31134
31443
|
return { stale: false };
|
|
31135
31444
|
const raw = fsSync3.readFileSync(p, "utf-8");
|
|
@@ -31661,13 +31970,13 @@ function buildStatusMessage2(session, directory, sessionID) {
|
|
|
31661
31970
|
}
|
|
31662
31971
|
|
|
31663
31972
|
// src/commands/unlink.ts
|
|
31664
|
-
import { existsSync as
|
|
31665
|
-
import * as
|
|
31973
|
+
import { existsSync as existsSync37 } from "fs";
|
|
31974
|
+
import * as path63 from "path";
|
|
31666
31975
|
var DEDUP_THRESHOLD2 = 0.6;
|
|
31667
31976
|
async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
|
|
31668
|
-
const sharedPath =
|
|
31669
|
-
const localPath =
|
|
31670
|
-
if (!
|
|
31977
|
+
const sharedPath = path63.join(linkDir, "knowledge.jsonl");
|
|
31978
|
+
const localPath = path63.join(localSwarmDir, "knowledge.jsonl");
|
|
31979
|
+
if (!existsSync37(sharedPath))
|
|
31671
31980
|
return 0;
|
|
31672
31981
|
const sharedEntries = await readKnowledge(sharedPath);
|
|
31673
31982
|
if (sharedEntries.length === 0)
|
|
@@ -31701,7 +32010,7 @@ async function handleUnlinkCommand(directory, args) {
|
|
|
31701
32010
|
let copied = 0;
|
|
31702
32011
|
if (copyBack) {
|
|
31703
32012
|
try {
|
|
31704
|
-
copied = await copySharedKnowledgeToLocal(linkDir,
|
|
32013
|
+
copied = await copySharedKnowledgeToLocal(linkDir, path63.join(directory, ".swarm"));
|
|
31705
32014
|
} catch (error2) {
|
|
31706
32015
|
return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
31707
32016
|
}
|
|
@@ -31856,7 +32165,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
31856
32165
|
async function handleHelpCommand(ctx) {
|
|
31857
32166
|
const targetCommand = ctx.args.join(" ");
|
|
31858
32167
|
if (!targetCommand) {
|
|
31859
|
-
const { buildHelpText } = await import("./index-
|
|
32168
|
+
const { buildHelpText } = await import("./index-4pt2py5p.js");
|
|
31860
32169
|
return buildHelpText();
|
|
31861
32170
|
}
|
|
31862
32171
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -31865,7 +32174,7 @@ async function handleHelpCommand(ctx) {
|
|
|
31865
32174
|
return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
|
|
31866
32175
|
}
|
|
31867
32176
|
const similar = _internals45.findSimilarCommands(targetCommand);
|
|
31868
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
32177
|
+
const { buildHelpText: fullHelp } = await import("./index-4pt2py5p.js");
|
|
31869
32178
|
if (similar.length > 0) {
|
|
31870
32179
|
return `Command '/swarm ${targetCommand}' not found.
|
|
31871
32180
|
|
|
@@ -31998,7 +32307,7 @@ var COMMAND_REGISTRY = {
|
|
|
31998
32307
|
},
|
|
31999
32308
|
"guardrail explain": {
|
|
32000
32309
|
handler: async (ctx) => {
|
|
32001
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32310
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-ktm6szbm.js");
|
|
32002
32311
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
32003
32312
|
},
|
|
32004
32313
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -32008,7 +32317,7 @@ var COMMAND_REGISTRY = {
|
|
|
32008
32317
|
},
|
|
32009
32318
|
"guardrail-log": {
|
|
32010
32319
|
handler: async (ctx) => {
|
|
32011
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
32320
|
+
const { handleGuardrailLog } = await import("./guardrail-log-ya49kpwn.js");
|
|
32012
32321
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
32013
32322
|
},
|
|
32014
32323
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -32033,8 +32342,15 @@ var COMMAND_REGISTRY = {
|
|
|
32033
32342
|
},
|
|
32034
32343
|
benchmark: {
|
|
32035
32344
|
handler: (ctx) => handleBenchmarkCommand(ctx.directory, ctx.args),
|
|
32036
|
-
description: "Show performance metrics [--cumulative] [--ci-gate]",
|
|
32037
|
-
args: "--cumulative, --ci-gate",
|
|
32345
|
+
description: "Show performance metrics [--cumulative] [--ci-gate] [--max-cost-usd <n>]",
|
|
32346
|
+
args: "--cumulative, --ci-gate, --max-cost-usd <n>",
|
|
32347
|
+
category: "diagnostics",
|
|
32348
|
+
toolPolicy: "agent"
|
|
32349
|
+
},
|
|
32350
|
+
costs: {
|
|
32351
|
+
handler: (ctx) => handleCostsCommand(ctx.directory, ctx.args),
|
|
32352
|
+
description: "Show per-agent and per-task token/cost telemetry [--json]",
|
|
32353
|
+
args: "--json",
|
|
32038
32354
|
category: "diagnostics",
|
|
32039
32355
|
toolPolicy: "agent"
|
|
32040
32356
|
},
|
|
@@ -32769,24 +33085,24 @@ function validateAliases() {
|
|
|
32769
33085
|
}
|
|
32770
33086
|
aliasTargets.get(target).push(name);
|
|
32771
33087
|
const visited = new Set;
|
|
32772
|
-
const
|
|
33088
|
+
const path64 = [];
|
|
32773
33089
|
let current = target;
|
|
32774
33090
|
while (current) {
|
|
32775
33091
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
32776
33092
|
if (!currentEntry)
|
|
32777
33093
|
break;
|
|
32778
33094
|
if (visited.has(current)) {
|
|
32779
|
-
const cycleStart =
|
|
33095
|
+
const cycleStart = path64.indexOf(current);
|
|
32780
33096
|
const fullChain = [
|
|
32781
33097
|
name,
|
|
32782
|
-
...
|
|
33098
|
+
...path64.slice(0, cycleStart > 0 ? cycleStart : path64.length),
|
|
32783
33099
|
current
|
|
32784
33100
|
].join(" \u2192 ");
|
|
32785
33101
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
32786
33102
|
break;
|
|
32787
33103
|
}
|
|
32788
33104
|
visited.add(current);
|
|
32789
|
-
|
|
33105
|
+
path64.push(current);
|
|
32790
33106
|
current = currentEntry.aliasOf || "";
|
|
32791
33107
|
}
|
|
32792
33108
|
}
|
|
@@ -32952,4 +33268,4 @@ ${text}`;
|
|
|
32952
33268
|
};
|
|
32953
33269
|
}
|
|
32954
33270
|
|
|
32955
|
-
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals45 as _internals, resolveCommand };
|
|
33271
|
+
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals45 as _internals, resolveCommand };
|