opencode-swarm 7.109.2 → 7.109.4
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/.opencode/skills/ci-failure-batching/SKILL.md +39 -0
- package/.opencode/skills/gate-attribution/SKILL.md +31 -0
- package/.opencode/skills/merge-queue-readiness/SKILL.md +37 -0
- package/.opencode/skills/skill-edit-validation/SKILL.md +29 -0
- package/.opencode/skills/worktree-retry-cleanup/SKILL.md +24 -0
- package/dist/cli/{config-doctor-q354tb2w.js → config-doctor-9vjyj9m3.js} +2 -2
- package/dist/cli/{curator-llm-factory-wqbm9mwr.js → curator-llm-factory-3hf9xpnd.js} +9 -9
- package/dist/cli/{curator-6p9tpprq.js → curator-zn1kmwmz.js} +9 -9
- package/dist/cli/{guardrail-explain-ynge4ww3.js → guardrail-explain-hjz1k6w0.js} +10 -10
- package/dist/cli/{guardrail-log-8mqqsssq.js → guardrail-log-5240bawg.js} +3 -3
- package/dist/cli/{hive-promoter-qh2rh8x2.js → hive-promoter-j81yj97d.js} +9 -9
- package/dist/cli/{index-h4c4rrwx.js → index-18690p15.js} +23 -2
- package/dist/cli/{index-fz1jgbvw.js → index-41fgssqr.js} +22 -2
- package/dist/cli/{index-wg0665ft.js → index-8f10r7ay.js} +2 -2
- package/dist/cli/{index-9qxntjtx.js → index-b15qbvph.js} +190 -41
- package/dist/cli/{index-wj4jeavn.js → index-d3txrx5q.js} +1 -1
- package/dist/cli/{index-5gnp8fyw.js → index-mtzjbaaa.js} +3 -3
- package/dist/cli/{index-3qwaydq1.js → index-nvmy7xmj.js} +11 -11
- package/dist/cli/{index-vx76tcxe.js → index-p5vm9gy9.js} +1 -1
- package/dist/cli/{index-cqbqynzp.js → index-y3nx3ss0.js} +710 -557
- package/dist/cli/{index-mmny81g1.js → index-y5z2qdvk.js} +1 -1
- package/dist/cli/{index-8a8b5wjf.js → index-zh3qh6m7.js} +2 -2
- package/dist/cli/{index-fm7xz1ne.js → index-zjh648z4.js} +81 -1
- package/dist/cli/index.js +9 -9
- package/dist/cli/{knowledge-escalator-6v7sjprx.js → knowledge-escalator-9ksrgq7h.js} +3 -3
- package/dist/cli/{knowledge-events-6n3x3he2.js → knowledge-events-ymysgtrr.js} +1 -1
- package/dist/cli/{knowledge-store-exkw6yb1.js → knowledge-store-562fefjy.js} +1 -1
- package/dist/cli/{knowledge-validator-exymfcb9.js → knowledge-validator-b9nvmzjc.js} +4 -2
- package/dist/cli/{schema-x17zmd03.js → schema-5vmb5dh8.js} +3 -1
- package/dist/cli/{skill-generator-mx9br4ty.js → skill-generator-mjfqvnn0.js} +15 -5
- package/dist/config/bundled-skills.d.ts +1 -1
- package/dist/config/schema.d.ts +12 -4
- package/dist/hooks/knowledge-types.d.ts +6 -0
- package/dist/hooks/knowledge-validator.d.ts +5 -0
- package/dist/hooks/skill-invalidator.d.ts +48 -0
- package/dist/index.js +217 -216
- package/dist/services/skill-generator.d.ts +47 -2
- package/dist/tools/knowledge-remove.d.ts +3 -8
- package/package.json +6 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
readRecentEscalations
|
|
4
|
-
} from "./index-
|
|
4
|
+
} from "./index-mtzjbaaa.js";
|
|
5
5
|
import {
|
|
6
6
|
getGlobalEventBus
|
|
7
7
|
} from "./index-c8s9a3zh.js";
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
readDoctorArtifact,
|
|
11
11
|
removeStraySwarmDir,
|
|
12
12
|
runConfigDoctor
|
|
13
|
-
} from "./index-
|
|
13
|
+
} from "./index-zjh648z4.js";
|
|
14
14
|
import {
|
|
15
15
|
MAX_TRANSIENT_RETRIES,
|
|
16
16
|
PlanSchema,
|
|
@@ -85,6 +85,8 @@ import {
|
|
|
85
85
|
AGENT_TOOL_MAP,
|
|
86
86
|
ALL_SUBAGENT_NAMES,
|
|
87
87
|
ExternalSkillsConfigSchema,
|
|
88
|
+
GATE_CONFIG_KNOWN_SECTION_KEYS,
|
|
89
|
+
GateConfigSchema,
|
|
88
90
|
KnowledgeConfigSchema,
|
|
89
91
|
ORCHESTRATOR_NAME,
|
|
90
92
|
PluginConfigSchema,
|
|
@@ -94,7 +96,7 @@ import {
|
|
|
94
96
|
getCanonicalAgentRole,
|
|
95
97
|
resolveExternalSkillsConfig,
|
|
96
98
|
stripKnownSwarmPrefix
|
|
97
|
-
} from "./index-
|
|
99
|
+
} from "./index-18690p15.js";
|
|
98
100
|
import {
|
|
99
101
|
DEFAULT_SKILL_MIN_CONFIDENCE,
|
|
100
102
|
DEFAULT_SKILL_MIN_CONFIRMATIONS,
|
|
@@ -102,6 +104,8 @@ import {
|
|
|
102
104
|
appendSkillChangelog,
|
|
103
105
|
autoApplyProposals,
|
|
104
106
|
evaluateSkillChange,
|
|
107
|
+
findSkillsBySourceKnowledgeId,
|
|
108
|
+
findStaleSkillsBySourceKnowledgeId,
|
|
105
109
|
generateSkills,
|
|
106
110
|
listSkills,
|
|
107
111
|
parseDraftFrontmatter,
|
|
@@ -109,14 +113,15 @@ import {
|
|
|
109
113
|
retireOrMarkStale,
|
|
110
114
|
retireSkill,
|
|
111
115
|
selectCandidateEntries
|
|
112
|
-
} from "./index-
|
|
116
|
+
} from "./index-b15qbvph.js";
|
|
113
117
|
import {
|
|
114
118
|
effectiveRetrievalOutcomes,
|
|
115
119
|
readKnowledgeCounterRollups,
|
|
116
120
|
readKnowledgeEvents,
|
|
121
|
+
recordHiveKnowledgeEvent,
|
|
117
122
|
recordKnowledgeEvent,
|
|
118
123
|
resolveKnowledgeEventsPath
|
|
119
|
-
} from "./index-
|
|
124
|
+
} from "./index-y5z2qdvk.js";
|
|
120
125
|
import {
|
|
121
126
|
appendUnactionable,
|
|
122
127
|
quarantineEntry,
|
|
@@ -126,7 +131,7 @@ import {
|
|
|
126
131
|
validateActionability,
|
|
127
132
|
validateActionableFields,
|
|
128
133
|
validateLesson
|
|
129
|
-
} from "./index-
|
|
134
|
+
} from "./index-41fgssqr.js";
|
|
130
135
|
import {
|
|
131
136
|
appendKnowledge,
|
|
132
137
|
appendRejectedLesson,
|
|
@@ -148,7 +153,7 @@ import {
|
|
|
148
153
|
rewriteKnowledge,
|
|
149
154
|
transactFile,
|
|
150
155
|
transactKnowledge
|
|
151
|
-
} from "./index-
|
|
156
|
+
} from "./index-8f10r7ay.js";
|
|
152
157
|
import {
|
|
153
158
|
isLinked,
|
|
154
159
|
readLinkPointer,
|
|
@@ -211,7 +216,7 @@ import {
|
|
|
211
216
|
|
|
212
217
|
// src/state.ts
|
|
213
218
|
import * as fs30 from "fs/promises";
|
|
214
|
-
import * as
|
|
219
|
+
import * as path66 from "path";
|
|
215
220
|
|
|
216
221
|
// src/db/qa-gate-profile.ts
|
|
217
222
|
import { createHash } from "crypto";
|
|
@@ -4856,6 +4861,62 @@ function sanitizeExternalSkillsConfig(raw) {
|
|
|
4856
4861
|
delete cleaned.external_skills;
|
|
4857
4862
|
return cleaned;
|
|
4858
4863
|
}
|
|
4864
|
+
function sanitizeGatesConfig(raw) {
|
|
4865
|
+
if (!("gates" in raw) || raw.gates === undefined) {
|
|
4866
|
+
return raw;
|
|
4867
|
+
}
|
|
4868
|
+
if (typeof raw.gates !== "object" || raw.gates === null || Array.isArray(raw.gates)) {
|
|
4869
|
+
console.warn("[opencode-swarm] gates config validation failed: expected an object. Quality gates will use defaults; other config sections remain active.");
|
|
4870
|
+
const cleaned2 = { ...raw };
|
|
4871
|
+
delete cleaned2.gates;
|
|
4872
|
+
return cleaned2;
|
|
4873
|
+
}
|
|
4874
|
+
const gateSchemas = GateConfigSchema.shape;
|
|
4875
|
+
const cleanedGates = { ...raw.gates };
|
|
4876
|
+
for (const [key, value] of Object.entries(cleanedGates)) {
|
|
4877
|
+
const schema = gateSchemas[key];
|
|
4878
|
+
if (!schema) {
|
|
4879
|
+
console.warn(`[opencode-swarm] Unknown gates config section "gates.${key}" ignored. Other config sections remain active.`);
|
|
4880
|
+
delete cleanedGates[key];
|
|
4881
|
+
continue;
|
|
4882
|
+
}
|
|
4883
|
+
const knownFields = GATE_CONFIG_KNOWN_SECTION_KEYS[key];
|
|
4884
|
+
let sectionValue = value;
|
|
4885
|
+
if (knownFields && typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
4886
|
+
const cleanedSection = { ...value };
|
|
4887
|
+
const knownFieldSet = new Set(knownFields);
|
|
4888
|
+
for (const fieldName of Object.keys(cleanedSection)) {
|
|
4889
|
+
if (!knownFieldSet.has(fieldName)) {
|
|
4890
|
+
console.warn(`[opencode-swarm] Unknown gates config key "gates.${key}.${fieldName}" ignored. Other config sections remain active.`);
|
|
4891
|
+
delete cleanedSection[fieldName];
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
sectionValue = cleanedSection;
|
|
4895
|
+
cleanedGates[key] = cleanedSection;
|
|
4896
|
+
}
|
|
4897
|
+
const sectionResult = schema.safeParse(sectionValue);
|
|
4898
|
+
if (!sectionResult.success) {
|
|
4899
|
+
console.warn(`[opencode-swarm] gates.${key} config validation failed; that gate section will use defaults and other config sections remain active:`);
|
|
4900
|
+
console.warn(sectionResult.error.format());
|
|
4901
|
+
delete cleanedGates[key];
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
const gatesResult = GateConfigSchema.safeParse(cleanedGates);
|
|
4905
|
+
if (gatesResult.success) {
|
|
4906
|
+
return {
|
|
4907
|
+
...raw,
|
|
4908
|
+
gates: gatesResult.data
|
|
4909
|
+
};
|
|
4910
|
+
}
|
|
4911
|
+
console.warn("[opencode-swarm] gates config validation failed after section cleanup; quality gates will use defaults and other config sections remain active:");
|
|
4912
|
+
console.warn(gatesResult.error.format());
|
|
4913
|
+
const cleaned = { ...raw };
|
|
4914
|
+
delete cleaned.gates;
|
|
4915
|
+
return cleaned;
|
|
4916
|
+
}
|
|
4917
|
+
function sanitizeSectionConfigs(raw) {
|
|
4918
|
+
return sanitizeGatesConfig(sanitizeExternalSkillsConfig(raw));
|
|
4919
|
+
}
|
|
4859
4920
|
function rawFullAutoLocked(raw) {
|
|
4860
4921
|
if (!raw || typeof raw !== "object")
|
|
4861
4922
|
return false;
|
|
@@ -4886,11 +4947,11 @@ function loadPluginConfig(directory) {
|
|
|
4886
4947
|
};
|
|
4887
4948
|
}
|
|
4888
4949
|
mergedRaw = migratePresetsConfig(mergedRaw);
|
|
4889
|
-
mergedRaw =
|
|
4950
|
+
mergedRaw = sanitizeSectionConfigs(mergedRaw);
|
|
4890
4951
|
const result = PluginConfigSchema.safeParse(mergedRaw);
|
|
4891
4952
|
if (!result.success) {
|
|
4892
4953
|
if (rawUserConfig) {
|
|
4893
|
-
const userParseResult = PluginConfigSchema.safeParse(
|
|
4954
|
+
const userParseResult = PluginConfigSchema.safeParse(sanitizeSectionConfigs(rawUserConfig ?? {}));
|
|
4894
4955
|
if (userParseResult.success) {
|
|
4895
4956
|
console.warn("[opencode-swarm] Project config ignored due to validation errors. Using user config.");
|
|
4896
4957
|
return userParseResult.data;
|
|
@@ -4958,7 +5019,12 @@ var BUNDLED_PROJECT_SKILLS = [
|
|
|
4958
5019
|
"writing-tests",
|
|
4959
5020
|
"running-tests",
|
|
4960
5021
|
"engineering-conventions",
|
|
4961
|
-
"commit-pr"
|
|
5022
|
+
"commit-pr",
|
|
5023
|
+
"worktree-retry-cleanup",
|
|
5024
|
+
"skill-edit-validation",
|
|
5025
|
+
"merge-queue-readiness",
|
|
5026
|
+
"gate-attribution",
|
|
5027
|
+
"ci-failure-batching"
|
|
4962
5028
|
];
|
|
4963
5029
|
var MAX_SKILL_FILES = 64;
|
|
4964
5030
|
var MAX_SKILL_BYTES = 512000;
|
|
@@ -6484,7 +6550,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
6484
6550
|
import * as child_process2 from "child_process";
|
|
6485
6551
|
import * as fsSync from "fs";
|
|
6486
6552
|
import { promises as fs9 } from "fs";
|
|
6487
|
-
import
|
|
6553
|
+
import path28 from "path";
|
|
6488
6554
|
|
|
6489
6555
|
// src/hooks/curator-postmortem.ts
|
|
6490
6556
|
import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync4 } from "fs";
|
|
@@ -7199,15 +7265,15 @@ var _internals7 = {
|
|
|
7199
7265
|
executePostMortemActions,
|
|
7200
7266
|
repairPostMortemActions,
|
|
7201
7267
|
loadDefaultKnowledgeConfig: async () => {
|
|
7202
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
7268
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5vmb5dh8.js");
|
|
7203
7269
|
return KnowledgeConfigSchema2.parse({});
|
|
7204
7270
|
},
|
|
7205
7271
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
7206
|
-
const { applyCuratorKnowledgeUpdates } = await import("./curator-
|
|
7272
|
+
const { applyCuratorKnowledgeUpdates } = await import("./curator-zn1kmwmz.js");
|
|
7207
7273
|
return applyCuratorKnowledgeUpdates(directory, recommendations, knowledgeConfig);
|
|
7208
7274
|
},
|
|
7209
7275
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
7210
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
7276
|
+
const { checkHivePromotions } = await import("./hive-promoter-j81yj97d.js");
|
|
7211
7277
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
7212
7278
|
},
|
|
7213
7279
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -7216,7 +7282,7 @@ var _internals7 = {
|
|
|
7216
7282
|
activateProposal,
|
|
7217
7283
|
listSkills: listSkills2,
|
|
7218
7284
|
sanitizeSlug
|
|
7219
|
-
} = await import("./skill-generator-
|
|
7285
|
+
} = await import("./skill-generator-mjfqvnn0.js");
|
|
7220
7286
|
const result = {
|
|
7221
7287
|
approved: [],
|
|
7222
7288
|
rejected: [],
|
|
@@ -7233,7 +7299,8 @@ var _internals7 = {
|
|
|
7233
7299
|
if (item.action === "apply") {
|
|
7234
7300
|
const activation = await activateProposal(directory, slug, false, {
|
|
7235
7301
|
evaluate: true,
|
|
7236
|
-
operation: "post_mortem_queue_triage"
|
|
7302
|
+
operation: "post_mortem_queue_triage",
|
|
7303
|
+
confirmUnevaluated: true
|
|
7237
7304
|
});
|
|
7238
7305
|
if (activation.activated) {
|
|
7239
7306
|
result.approved.push(slug);
|
|
@@ -7264,12 +7331,12 @@ var _internals7 = {
|
|
|
7264
7331
|
};
|
|
7265
7332
|
|
|
7266
7333
|
// src/hooks/hive-promoter.ts
|
|
7267
|
-
import
|
|
7334
|
+
import path17 from "path";
|
|
7268
7335
|
|
|
7269
7336
|
// src/hooks/curator.ts
|
|
7270
7337
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
7271
7338
|
import * as fs5 from "fs";
|
|
7272
|
-
import * as
|
|
7339
|
+
import * as path16 from "path";
|
|
7273
7340
|
|
|
7274
7341
|
// src/services/learning-metrics.ts
|
|
7275
7342
|
var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -8087,10 +8154,69 @@ var _internals8 = {
|
|
|
8087
8154
|
// src/hooks/curator.ts
|
|
8088
8155
|
init_logger();
|
|
8089
8156
|
|
|
8157
|
+
// src/hooks/skill-invalidator.ts
|
|
8158
|
+
import * as path14 from "path";
|
|
8159
|
+
init_logger();
|
|
8160
|
+
async function writeArchiveTombstoneAndInvalidateSkills(ctx) {
|
|
8161
|
+
const label = ctx.sourceLabel ?? "skill-invalidator";
|
|
8162
|
+
if (!ctx.skipTombstone) {
|
|
8163
|
+
const tombstone = {
|
|
8164
|
+
type: "archived",
|
|
8165
|
+
entry_id: ctx.entryId,
|
|
8166
|
+
tier: ctx.tier,
|
|
8167
|
+
actor: ctx.actor,
|
|
8168
|
+
reason: ctx.reason,
|
|
8169
|
+
mode: ctx.mode,
|
|
8170
|
+
evidence: ctx.evidence,
|
|
8171
|
+
previous_status: ctx.previousStatus
|
|
8172
|
+
};
|
|
8173
|
+
if (ctx.tier === "hive") {
|
|
8174
|
+
await recordHiveKnowledgeEvent(tombstone);
|
|
8175
|
+
} else {
|
|
8176
|
+
await recordKnowledgeEvent(ctx.directory, tombstone);
|
|
8177
|
+
}
|
|
8178
|
+
}
|
|
8179
|
+
const allArchivedIds = ctx.precomputedArchivedIds ? new Set(ctx.precomputedArchivedIds) : await getArchivedKnowledgeIds(ctx.directory);
|
|
8180
|
+
allArchivedIds.add(ctx.entryId);
|
|
8181
|
+
queueMicrotask(async () => {
|
|
8182
|
+
try {
|
|
8183
|
+
const affectedSkillDirs = await findSkillsBySourceKnowledgeId(ctx.directory, ctx.entryId);
|
|
8184
|
+
const staleSkillDirs = await findStaleSkillsBySourceKnowledgeId(ctx.directory, allArchivedIds);
|
|
8185
|
+
const allSkillDirs = new Set([...affectedSkillDirs, ...staleSkillDirs]);
|
|
8186
|
+
if (allSkillDirs.size === 0)
|
|
8187
|
+
return;
|
|
8188
|
+
const slugSet = new Set;
|
|
8189
|
+
let retiredCount = 0;
|
|
8190
|
+
let staleCount = 0;
|
|
8191
|
+
for (const skillDir of allSkillDirs) {
|
|
8192
|
+
const slug = path14.basename(skillDir);
|
|
8193
|
+
if (slugSet.has(slug))
|
|
8194
|
+
continue;
|
|
8195
|
+
slugSet.add(slug);
|
|
8196
|
+
const result = await retireOrMarkStale(ctx.directory, skillDir, allArchivedIds);
|
|
8197
|
+
if (result.action === "retire")
|
|
8198
|
+
retiredCount++;
|
|
8199
|
+
else
|
|
8200
|
+
staleCount++;
|
|
8201
|
+
}
|
|
8202
|
+
const batchEvent = {
|
|
8203
|
+
type: "skill-stale-batch",
|
|
8204
|
+
skillIds: Array.from(slugSet),
|
|
8205
|
+
archivedIds: Array.from(allArchivedIds),
|
|
8206
|
+
retiredCount,
|
|
8207
|
+
staleCount
|
|
8208
|
+
};
|
|
8209
|
+
await recordKnowledgeEvent(ctx.directory, batchEvent);
|
|
8210
|
+
} catch (err) {
|
|
8211
|
+
warn(`[${label}] post-archive skill invalidation failed for entry '${ctx.entryId}': ${err instanceof Error ? err.message : String(err)}`);
|
|
8212
|
+
}
|
|
8213
|
+
});
|
|
8214
|
+
}
|
|
8215
|
+
|
|
8090
8216
|
// src/hooks/skill-usage-log.ts
|
|
8091
8217
|
import * as crypto2 from "crypto";
|
|
8092
8218
|
import * as fs4 from "fs";
|
|
8093
|
-
import * as
|
|
8219
|
+
import * as path15 from "path";
|
|
8094
8220
|
function resolveLogPath(directory) {
|
|
8095
8221
|
return validateSwarmPath(directory, "skill-usage.jsonl");
|
|
8096
8222
|
}
|
|
@@ -8189,7 +8315,7 @@ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
|
|
|
8189
8315
|
if (processedEntryIds.length === 0)
|
|
8190
8316
|
return;
|
|
8191
8317
|
const resolved = resolveLogPath(directory);
|
|
8192
|
-
const dir =
|
|
8318
|
+
const dir = path15.dirname(resolved);
|
|
8193
8319
|
if (!_internals9.existsSync(dir)) {
|
|
8194
8320
|
_internals9.mkdirSync(dir, { recursive: true });
|
|
8195
8321
|
}
|
|
@@ -8234,7 +8360,7 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
8234
8360
|
throw new Error("sessionID is required and must be a non-empty string");
|
|
8235
8361
|
}
|
|
8236
8362
|
const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
|
|
8237
|
-
const dir =
|
|
8363
|
+
const dir = path15.dirname(resolved);
|
|
8238
8364
|
if (!_internals9.existsSync(dir)) {
|
|
8239
8365
|
_internals9.mkdirSync(dir, { recursive: true });
|
|
8240
8366
|
}
|
|
@@ -8410,8 +8536,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8410
8536
|
}
|
|
8411
8537
|
if (entries.length === 0) {
|
|
8412
8538
|
if (preservedMarkers.length > 0) {
|
|
8413
|
-
const dir2 =
|
|
8414
|
-
const tmpPath2 =
|
|
8539
|
+
const dir2 = path15.dirname(resolved);
|
|
8540
|
+
const tmpPath2 = path15.join(dir2, `skill-usage-${Date.now()}.tmp`);
|
|
8415
8541
|
const content2 = preservedMarkers.join(`
|
|
8416
8542
|
`).concat(preservedMarkers.length > 0 ? `
|
|
8417
8543
|
` : "");
|
|
@@ -8453,8 +8579,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8453
8579
|
if (pruned === 0) {
|
|
8454
8580
|
return { pruned: 0, remaining: entries.length };
|
|
8455
8581
|
}
|
|
8456
|
-
const dir =
|
|
8457
|
-
const tmpPath =
|
|
8582
|
+
const dir = path15.dirname(resolved);
|
|
8583
|
+
const tmpPath = path15.join(dir, `skill-usage-${Date.now()}.tmp`);
|
|
8458
8584
|
const entryLines = surviving.map((e) => JSON.stringify(e));
|
|
8459
8585
|
const allLines = [...entryLines, ...preservedMarkers];
|
|
8460
8586
|
const content = allLines.join(`
|
|
@@ -8483,9 +8609,9 @@ async function resolveSourceKnowledgeIds(directory, skillPath) {
|
|
|
8483
8609
|
if (/\.\.[/\\]/.test(cleanPath)) {
|
|
8484
8610
|
return [];
|
|
8485
8611
|
}
|
|
8486
|
-
const absolute =
|
|
8487
|
-
const baseDir =
|
|
8488
|
-
const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir +
|
|
8612
|
+
const absolute = path15.normalize(path15.isAbsolute(cleanPath) ? cleanPath : path15.resolve(directory, cleanPath));
|
|
8613
|
+
const baseDir = path15.normalize(path15.resolve(directory));
|
|
8614
|
+
const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir + path15.sep).toLowerCase()) : absolute.startsWith(baseDir + path15.sep);
|
|
8489
8615
|
if (!isContained) {
|
|
8490
8616
|
return [];
|
|
8491
8617
|
}
|
|
@@ -8679,7 +8805,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
8679
8805
|
}
|
|
8680
8806
|
}
|
|
8681
8807
|
if (archivedSourceMatched) {
|
|
8682
|
-
const result = await _internals10.retireOrMarkStale(directory,
|
|
8808
|
+
const result = await _internals10.retireOrMarkStale(directory, path16.dirname(active.path), allArchivedIds);
|
|
8683
8809
|
if (result.action === "retire") {
|
|
8684
8810
|
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
8685
8811
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
@@ -8876,11 +9002,11 @@ function arrayOfStrings(v) {
|
|
|
8876
9002
|
}
|
|
8877
9003
|
function readLatestPostMortemDigest(directory) {
|
|
8878
9004
|
try {
|
|
8879
|
-
const swarmDir =
|
|
9005
|
+
const swarmDir = path16.join(directory, ".swarm");
|
|
8880
9006
|
if (!fs5.existsSync(swarmDir))
|
|
8881
9007
|
return null;
|
|
8882
9008
|
const candidates = fs5.readdirSync(swarmDir).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name)).map((name) => {
|
|
8883
|
-
const filePath =
|
|
9009
|
+
const filePath = path16.join(swarmDir, name);
|
|
8884
9010
|
return { name, filePath, mtimeMs: fs5.statSync(filePath).mtimeMs };
|
|
8885
9011
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
8886
9012
|
const latest = candidates[0];
|
|
@@ -8923,7 +9049,7 @@ async function readCuratorSummary(directory) {
|
|
|
8923
9049
|
}
|
|
8924
9050
|
async function writeCuratorSummary(directory, summary) {
|
|
8925
9051
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
8926
|
-
fs5.mkdirSync(
|
|
9052
|
+
fs5.mkdirSync(path16.dirname(resolvedPath), { recursive: true });
|
|
8927
9053
|
await bunWrite(resolvedPath, JSON.stringify(summary, null, 2));
|
|
8928
9054
|
}
|
|
8929
9055
|
function normalizeAgentName(name) {
|
|
@@ -9363,15 +9489,15 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9363
9489
|
await _internals10.writeCuratorSummary(directory, updatedSummary);
|
|
9364
9490
|
if (knowledgeApplicationFindings.length > 0) {
|
|
9365
9491
|
try {
|
|
9366
|
-
const evidenceDir =
|
|
9492
|
+
const evidenceDir = path16.join(directory, ".swarm", "evidence", String(phase));
|
|
9367
9493
|
fs5.mkdirSync(evidenceDir, { recursive: true });
|
|
9368
|
-
const findingsPath =
|
|
9494
|
+
const findingsPath = path16.join(evidenceDir, "curator-findings.json");
|
|
9369
9495
|
await bunWrite(findingsPath, JSON.stringify({ findings: knowledgeApplicationFindings }, null, 2));
|
|
9370
9496
|
} catch (err) {
|
|
9371
9497
|
warn(`[curator] failed to persist application findings: ${err instanceof Error ? err.message : String(err)}`);
|
|
9372
9498
|
}
|
|
9373
9499
|
}
|
|
9374
|
-
const eventsPath =
|
|
9500
|
+
const eventsPath = path16.join(directory, ".swarm", "events.jsonl");
|
|
9375
9501
|
for (const obs of complianceObservations) {
|
|
9376
9502
|
await appendKnowledge(eventsPath, {
|
|
9377
9503
|
type: "curator_compliance",
|
|
@@ -9384,7 +9510,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9384
9510
|
}
|
|
9385
9511
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
9386
9512
|
try {
|
|
9387
|
-
const skillModule = await import("./skill-generator-
|
|
9513
|
+
const skillModule = await import("./skill-generator-mjfqvnn0.js");
|
|
9388
9514
|
for (const cand of skillCandidates) {
|
|
9389
9515
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
9390
9516
|
continue;
|
|
@@ -9552,10 +9678,12 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9552
9678
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
9553
9679
|
const appliedIds = new Set;
|
|
9554
9680
|
const foundIds = new Set;
|
|
9681
|
+
const archivedPrevStatus = new Map;
|
|
9555
9682
|
const contradictedEntries = [];
|
|
9556
9683
|
await transactKnowledge(knowledgePath, (entries) => {
|
|
9557
9684
|
appliedIds.clear();
|
|
9558
9685
|
foundIds.clear();
|
|
9686
|
+
archivedPrevStatus.clear();
|
|
9559
9687
|
contradictedEntries.length = 0;
|
|
9560
9688
|
let txApplied = 0;
|
|
9561
9689
|
let modified = false;
|
|
@@ -9581,6 +9709,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9581
9709
|
return entry;
|
|
9582
9710
|
}
|
|
9583
9711
|
appliedIds.add(entry.id);
|
|
9712
|
+
archivedPrevStatus.set(entry.id, entry.status);
|
|
9584
9713
|
txApplied++;
|
|
9585
9714
|
modified = true;
|
|
9586
9715
|
return {
|
|
@@ -9654,7 +9783,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9654
9783
|
} catch {}
|
|
9655
9784
|
}
|
|
9656
9785
|
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
9657
|
-
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-
|
|
9786
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-9ksrgq7h.js");
|
|
9658
9787
|
for (const { id } of contradictedEntries) {
|
|
9659
9788
|
try {
|
|
9660
9789
|
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
@@ -9669,6 +9798,25 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9669
9798
|
skipped++;
|
|
9670
9799
|
}
|
|
9671
9800
|
}
|
|
9801
|
+
const archivedRecs = validRecommendations.filter((r) => r.action === "archive" && r.entry_id && appliedIds.has(r.entry_id));
|
|
9802
|
+
const precomputedArchivedIds = archivedRecs.length > 0 ? await getArchivedKnowledgeIds(directory) : undefined;
|
|
9803
|
+
for (const rec of archivedRecs) {
|
|
9804
|
+
try {
|
|
9805
|
+
await writeArchiveTombstoneAndInvalidateSkills({
|
|
9806
|
+
directory,
|
|
9807
|
+
entryId: rec.entry_id,
|
|
9808
|
+
tier: "swarm",
|
|
9809
|
+
actor: "curator",
|
|
9810
|
+
reason: rec.reason ?? "curator archive recommendation",
|
|
9811
|
+
mode: "archive",
|
|
9812
|
+
previousStatus: archivedPrevStatus.get(rec.entry_id),
|
|
9813
|
+
sourceLabel: "curator",
|
|
9814
|
+
precomputedArchivedIds
|
|
9815
|
+
});
|
|
9816
|
+
} catch (err) {
|
|
9817
|
+
warn(`[curator] archive invalidation for entry '${rec.entry_id}' failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9818
|
+
}
|
|
9819
|
+
}
|
|
9672
9820
|
const currentEntries = await readKnowledge(knowledgePath);
|
|
9673
9821
|
const currentLessons = currentEntries.map((e) => e.lesson);
|
|
9674
9822
|
for (const rec of validRecommendations) {
|
|
@@ -9718,7 +9866,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9718
9866
|
created_at: now,
|
|
9719
9867
|
updated_at: now,
|
|
9720
9868
|
auto_generated: true,
|
|
9721
|
-
project_name:
|
|
9869
|
+
project_name: path16.basename(directory)
|
|
9722
9870
|
};
|
|
9723
9871
|
if (!validateActionability(newEntry).actionable) {
|
|
9724
9872
|
try {
|
|
@@ -9964,7 +10112,7 @@ async function promoteToHive(directory, lesson, category) {
|
|
|
9964
10112
|
schema_version: 1,
|
|
9965
10113
|
created_at: new Date().toISOString(),
|
|
9966
10114
|
updated_at: new Date().toISOString(),
|
|
9967
|
-
source_project:
|
|
10115
|
+
source_project: path17.basename(directory) || "unknown",
|
|
9968
10116
|
encounter_score: 1
|
|
9969
10117
|
};
|
|
9970
10118
|
await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
|
|
@@ -10018,7 +10166,7 @@ async function promoteFromSwarm(directory, lessonId) {
|
|
|
10018
10166
|
import { createHash as createHash4 } from "crypto";
|
|
10019
10167
|
import { existsSync as existsSync13 } from "fs";
|
|
10020
10168
|
import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
|
|
10021
|
-
import * as
|
|
10169
|
+
import * as path22 from "path";
|
|
10022
10170
|
|
|
10023
10171
|
// src/services/synonym-map.ts
|
|
10024
10172
|
var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
|
|
@@ -10030,7 +10178,7 @@ import {
|
|
|
10030
10178
|
unlink,
|
|
10031
10179
|
writeFile as writeFile6
|
|
10032
10180
|
} from "fs/promises";
|
|
10033
|
-
import * as
|
|
10181
|
+
import * as path18 from "path";
|
|
10034
10182
|
var SYNONYM_MAP_FILENAME = "synonym-map.json";
|
|
10035
10183
|
var MAX_TOKEN_LENGTH = 64;
|
|
10036
10184
|
var DEFAULT_MAX_PAIRS = 500;
|
|
@@ -10185,7 +10333,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
|
10185
10333
|
}
|
|
10186
10334
|
}
|
|
10187
10335
|
async function writeSynonymMapAtomic(filePath, map) {
|
|
10188
|
-
await mkdir5(
|
|
10336
|
+
await mkdir5(path18.dirname(filePath), { recursive: true });
|
|
10189
10337
|
const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
10190
10338
|
try {
|
|
10191
10339
|
await writeFile6(tmp, JSON.stringify(map, null, 2), "utf-8");
|
|
@@ -10198,7 +10346,7 @@ async function writeSynonymMapAtomic(filePath, map) {
|
|
|
10198
10346
|
}
|
|
10199
10347
|
async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIRS) {
|
|
10200
10348
|
const filePath = resolveSynonymMapPath(directory);
|
|
10201
|
-
const dir =
|
|
10349
|
+
const dir = path18.dirname(filePath);
|
|
10202
10350
|
await mkdir5(dir, { recursive: true });
|
|
10203
10351
|
let release = null;
|
|
10204
10352
|
try {
|
|
@@ -10258,17 +10406,17 @@ function reinforceSwarmKnowledgeEntry(entry, confirmation) {
|
|
|
10258
10406
|
// src/hooks/micro-reflector.ts
|
|
10259
10407
|
import { existsSync as existsSync12 } from "fs";
|
|
10260
10408
|
import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
|
|
10261
|
-
import * as
|
|
10409
|
+
import * as path21 from "path";
|
|
10262
10410
|
init_logger();
|
|
10263
10411
|
|
|
10264
10412
|
// src/hooks/skill-propagation-gate.ts
|
|
10265
10413
|
import * as fs7 from "fs";
|
|
10266
|
-
import * as
|
|
10414
|
+
import * as path20 from "path";
|
|
10267
10415
|
init_logger();
|
|
10268
10416
|
|
|
10269
10417
|
// src/hooks/skill-scoring.ts
|
|
10270
10418
|
import * as fs6 from "fs";
|
|
10271
|
-
import * as
|
|
10419
|
+
import * as path19 from "path";
|
|
10272
10420
|
var FREQUENCY_CAP = 10;
|
|
10273
10421
|
var FREQUENCY_WEIGHT = 0.3;
|
|
10274
10422
|
var COMPLIANCE_WEIGHT = 0.3;
|
|
@@ -10296,10 +10444,10 @@ var _internals11 = {
|
|
|
10296
10444
|
computeTriggerMatchBoost: null
|
|
10297
10445
|
};
|
|
10298
10446
|
function extractSkillName(skillPath) {
|
|
10299
|
-
const base =
|
|
10447
|
+
const base = path19.basename(skillPath, path19.extname(skillPath));
|
|
10300
10448
|
if (base !== "SKILL")
|
|
10301
10449
|
return base;
|
|
10302
|
-
const parent =
|
|
10450
|
+
const parent = path19.basename(path19.dirname(skillPath));
|
|
10303
10451
|
return parent;
|
|
10304
10452
|
}
|
|
10305
10453
|
function stripQuotes(value) {
|
|
@@ -10457,12 +10605,12 @@ function readSkillMetadata(skillPath, directory) {
|
|
|
10457
10605
|
const normalizedPath = skillPath.replace(/^file:/, "").replace(/\\/g, "/");
|
|
10458
10606
|
const fallback = parseSkillFrontmatter("", normalizedPath);
|
|
10459
10607
|
try {
|
|
10460
|
-
if (
|
|
10608
|
+
if (path19.isAbsolute(normalizedPath) || normalizedPath.split("/").includes("..")) {
|
|
10461
10609
|
return fallback;
|
|
10462
10610
|
}
|
|
10463
|
-
const root =
|
|
10464
|
-
const absolutePath =
|
|
10465
|
-
if (absolutePath !== root && !absolutePath.startsWith(root +
|
|
10611
|
+
const root = path19.resolve(directory);
|
|
10612
|
+
const absolutePath = path19.resolve(directory, normalizedPath);
|
|
10613
|
+
if (absolutePath !== root && !absolutePath.startsWith(root + path19.sep)) {
|
|
10466
10614
|
return fallback;
|
|
10467
10615
|
}
|
|
10468
10616
|
const content = readFilePrefix(absolutePath);
|
|
@@ -10600,7 +10748,7 @@ function getSkillStats(skillPath, directory) {
|
|
|
10600
10748
|
};
|
|
10601
10749
|
}
|
|
10602
10750
|
function formatSkillIndexWithContext(skills, directory) {
|
|
10603
|
-
const usageLogPath =
|
|
10751
|
+
const usageLogPath = path19.join(directory, ".swarm", "skill-usage.jsonl");
|
|
10604
10752
|
let hasHistory = false;
|
|
10605
10753
|
try {
|
|
10606
10754
|
const stat4 = fs6.statSync(usageLogPath);
|
|
@@ -10734,7 +10882,7 @@ function parseYamlValue(value) {
|
|
|
10734
10882
|
return trimmed;
|
|
10735
10883
|
}
|
|
10736
10884
|
function loadRoutingSkills(directory, targetAgent) {
|
|
10737
|
-
const routingPath =
|
|
10885
|
+
const routingPath = path20.join(directory, ".opencode", "skill-routing.yaml");
|
|
10738
10886
|
if (!_internals12.existsSync(routingPath))
|
|
10739
10887
|
return [];
|
|
10740
10888
|
try {
|
|
@@ -10794,7 +10942,7 @@ var _internals12 = {
|
|
|
10794
10942
|
function discoverAvailableSkills(directory) {
|
|
10795
10943
|
const results = [];
|
|
10796
10944
|
for (const root of SKILL_SEARCH_ROOTS) {
|
|
10797
|
-
const rootPath =
|
|
10945
|
+
const rootPath = path20.join(directory, root);
|
|
10798
10946
|
if (!_internals12.existsSync(rootPath))
|
|
10799
10947
|
continue;
|
|
10800
10948
|
let entries;
|
|
@@ -10806,13 +10954,13 @@ function discoverAvailableSkills(directory) {
|
|
|
10806
10954
|
for (const entry of entries) {
|
|
10807
10955
|
if (entry.startsWith("."))
|
|
10808
10956
|
continue;
|
|
10809
|
-
const skillDir =
|
|
10810
|
-
if (_internals12.existsSync(
|
|
10957
|
+
const skillDir = path20.join(rootPath, entry);
|
|
10958
|
+
if (_internals12.existsSync(path20.join(skillDir, "retired.marker")) || _internals12.existsSync(path20.join(skillDir, "stale.marker")))
|
|
10811
10959
|
continue;
|
|
10812
|
-
const skillFile =
|
|
10960
|
+
const skillFile = path20.join(skillDir, "SKILL.md");
|
|
10813
10961
|
try {
|
|
10814
10962
|
if (_internals12.statSync(skillDir).isDirectory() && _internals12.existsSync(skillFile)) {
|
|
10815
|
-
results.push(
|
|
10963
|
+
results.push(path20.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
|
|
10816
10964
|
}
|
|
10817
10965
|
} catch (err) {
|
|
10818
10966
|
warn(`[skill-propagation-gate] failed to stat skill directory ${entry}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -10881,9 +11029,9 @@ function extractSkillsFieldFromPrompt(prompt) {
|
|
|
10881
11029
|
return "";
|
|
10882
11030
|
}
|
|
10883
11031
|
function writeWarnEvent(directory, record) {
|
|
10884
|
-
const filePath =
|
|
11032
|
+
const filePath = path20.join(directory, ".swarm", "events.jsonl");
|
|
10885
11033
|
try {
|
|
10886
|
-
const dir =
|
|
11034
|
+
const dir = path20.dirname(filePath);
|
|
10887
11035
|
if (!_internals12.existsSync(dir)) {
|
|
10888
11036
|
_internals12.mkdirSync(dir, { recursive: true });
|
|
10889
11037
|
}
|
|
@@ -11012,8 +11160,8 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11012
11160
|
if (routingPaths.length > 0) {
|
|
11013
11161
|
const existingPaths = new Set(scored.map((s) => s.skillPath));
|
|
11014
11162
|
for (const routingPath of routingPaths) {
|
|
11015
|
-
const routedSkillDir =
|
|
11016
|
-
if (_internals12.existsSync(
|
|
11163
|
+
const routedSkillDir = path20.dirname(path20.join(directory, routingPath));
|
|
11164
|
+
if (_internals12.existsSync(path20.join(routedSkillDir, "retired.marker")) || _internals12.existsSync(path20.join(routedSkillDir, "stale.marker")))
|
|
11017
11165
|
continue;
|
|
11018
11166
|
if (!existingPaths.has(routingPath)) {
|
|
11019
11167
|
scored.push({
|
|
@@ -11032,8 +11180,8 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11032
11180
|
let skillsForIndex = availableSkills;
|
|
11033
11181
|
if (scoringSkipped) {
|
|
11034
11182
|
skillsForIndex = [...availableSkills].sort((a, b) => {
|
|
11035
|
-
const nameA =
|
|
11036
|
-
const nameB =
|
|
11183
|
+
const nameA = path20.basename(path20.dirname(a));
|
|
11184
|
+
const nameB = path20.basename(path20.dirname(b));
|
|
11037
11185
|
return nameA.localeCompare(nameB);
|
|
11038
11186
|
});
|
|
11039
11187
|
} else if (typeof scored !== "undefined" && scored.length > 0) {
|
|
@@ -11041,7 +11189,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11041
11189
|
}
|
|
11042
11190
|
const formattedIndex = _internals12.formatSkillIndexWithContext(skillsForIndex, directory);
|
|
11043
11191
|
if (formattedIndex.length > 0) {
|
|
11044
|
-
const contextPath =
|
|
11192
|
+
const contextPath = path20.join(directory, ".swarm", "context.md");
|
|
11045
11193
|
let existingContent = "";
|
|
11046
11194
|
if (_internals12.existsSync(contextPath)) {
|
|
11047
11195
|
existingContent = _internals12.readFileSync(contextPath, "utf-8");
|
|
@@ -11063,7 +11211,7 @@ ${newSection}`;
|
|
|
11063
11211
|
updatedContent = existingContent + newSection;
|
|
11064
11212
|
}
|
|
11065
11213
|
}
|
|
11066
|
-
const swarmDir =
|
|
11214
|
+
const swarmDir = path20.dirname(contextPath);
|
|
11067
11215
|
if (!_internals12.existsSync(swarmDir)) {
|
|
11068
11216
|
_internals12.mkdirSync(swarmDir, { recursive: true });
|
|
11069
11217
|
}
|
|
@@ -11289,7 +11437,7 @@ function resolveInsightCandidatesPath(directory) {
|
|
|
11289
11437
|
}
|
|
11290
11438
|
async function readTaskTrajectory(directory, taskId) {
|
|
11291
11439
|
try {
|
|
11292
|
-
const rel =
|
|
11440
|
+
const rel = path21.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
|
|
11293
11441
|
const filePath = validateSwarmPath(directory, rel);
|
|
11294
11442
|
if (!existsSync12(filePath))
|
|
11295
11443
|
return [];
|
|
@@ -11719,8 +11867,8 @@ RETRY: your last output was missing ${result.missing.join("; ")}; produce valid
|
|
|
11719
11867
|
}
|
|
11720
11868
|
async function appendCuratorSkippedEvent(directory, record) {
|
|
11721
11869
|
try {
|
|
11722
|
-
const filePath =
|
|
11723
|
-
await mkdir6(
|
|
11870
|
+
const filePath = path22.join(directory, ".swarm", "events.jsonl");
|
|
11871
|
+
await mkdir6(path22.dirname(filePath), { recursive: true });
|
|
11724
11872
|
await appendFile2(filePath, `${JSON.stringify({
|
|
11725
11873
|
timestamp: new Date().toISOString(),
|
|
11726
11874
|
event: "curator_skipped",
|
|
@@ -12287,7 +12435,7 @@ var _internals14 = {
|
|
|
12287
12435
|
|
|
12288
12436
|
// src/services/session-reflection.ts
|
|
12289
12437
|
import { promises as fs8 } from "fs";
|
|
12290
|
-
import * as
|
|
12438
|
+
import * as path23 from "path";
|
|
12291
12439
|
|
|
12292
12440
|
// src/hooks/abort-utils.ts
|
|
12293
12441
|
function isAbortError(err) {
|
|
@@ -12448,11 +12596,11 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
|
|
|
12448
12596
|
const lessons = [];
|
|
12449
12597
|
const taxonomy = {};
|
|
12450
12598
|
try {
|
|
12451
|
-
const evidenceDir =
|
|
12599
|
+
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
12452
12600
|
const entries = await fs8.readdir(evidenceDir);
|
|
12453
12601
|
const retroDirs = entries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
12454
12602
|
for (const retroDir of retroDirs) {
|
|
12455
|
-
const evidencePath =
|
|
12603
|
+
const evidencePath = path23.join(evidenceDir, retroDir, "evidence.json");
|
|
12456
12604
|
try {
|
|
12457
12605
|
const content = await fs8.readFile(evidencePath, "utf-8");
|
|
12458
12606
|
const parsed = JSON.parse(content);
|
|
@@ -12481,12 +12629,12 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
|
|
|
12481
12629
|
async function gatherGateFailures(directory) {
|
|
12482
12630
|
const failures = new Map;
|
|
12483
12631
|
try {
|
|
12484
|
-
const evidenceDir =
|
|
12632
|
+
const evidenceDir = path23.join(directory, ".swarm", "evidence");
|
|
12485
12633
|
const entries = await fs8.readdir(evidenceDir);
|
|
12486
12634
|
for (const entry of entries) {
|
|
12487
12635
|
if (entry.startsWith("retro-"))
|
|
12488
12636
|
continue;
|
|
12489
|
-
const evidencePath =
|
|
12637
|
+
const evidencePath = path23.join(evidenceDir, entry, "evidence.json");
|
|
12490
12638
|
try {
|
|
12491
12639
|
const content = await fs8.readFile(evidencePath, "utf-8");
|
|
12492
12640
|
const parsed = JSON.parse(content);
|
|
@@ -12687,12 +12835,12 @@ async function writeSessionReflection(directory, result) {
|
|
|
12687
12835
|
// src/services/skill-improver.ts
|
|
12688
12836
|
import { existsSync as existsSync15 } from "fs";
|
|
12689
12837
|
import { mkdir as mkdir8, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
|
|
12690
|
-
import * as
|
|
12838
|
+
import * as path25 from "path";
|
|
12691
12839
|
init_logger();
|
|
12692
12840
|
|
|
12693
12841
|
// src/services/trajectory-cluster.ts
|
|
12694
12842
|
import { mkdir as mkdir7, writeFile as writeFile9 } from "fs/promises";
|
|
12695
|
-
import * as
|
|
12843
|
+
import * as path24 from "path";
|
|
12696
12844
|
init_logger();
|
|
12697
12845
|
var MACRO_TRAJECTORY_WINDOW = 200;
|
|
12698
12846
|
var MOTIF_MIN_TASKS = 2;
|
|
@@ -12824,11 +12972,11 @@ async function writeMotifProposals(directory, opts = {}) {
|
|
|
12824
12972
|
if (motifs.length === 0)
|
|
12825
12973
|
return result;
|
|
12826
12974
|
const max = opts.maxProposals ?? 10;
|
|
12827
|
-
const proposalsDir = validateSwarmPath(directory,
|
|
12975
|
+
const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
|
|
12828
12976
|
await mkdir7(proposalsDir, { recursive: true });
|
|
12829
12977
|
for (const motif of motifs.slice(0, max)) {
|
|
12830
12978
|
const slug = `motif-${slugify(motif.signature)}`;
|
|
12831
|
-
const filePath =
|
|
12979
|
+
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
12832
12980
|
await writeFile9(filePath, buildMotifProposal(motif), "utf-8");
|
|
12833
12981
|
result.proposalsWritten.push(filePath);
|
|
12834
12982
|
}
|
|
@@ -12969,11 +13117,11 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
|
|
|
12969
13117
|
if (motifs.length === 0)
|
|
12970
13118
|
return result;
|
|
12971
13119
|
const max = opts.maxProposals ?? 10;
|
|
12972
|
-
const proposalsDir = validateSwarmPath(directory,
|
|
13120
|
+
const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
|
|
12973
13121
|
await mkdir7(proposalsDir, { recursive: true });
|
|
12974
13122
|
for (const motif of motifs.slice(0, max)) {
|
|
12975
13123
|
const slug = workflowSlug(motif.signature);
|
|
12976
|
-
const filePath =
|
|
13124
|
+
const filePath = path24.join(proposalsDir, `${slug}.md`);
|
|
12977
13125
|
await writeFile9(filePath, buildWorkflowProposal(motif), "utf-8");
|
|
12978
13126
|
result.proposalsWritten.push(filePath);
|
|
12979
13127
|
}
|
|
@@ -13096,7 +13244,7 @@ function timestampSlug(d) {
|
|
|
13096
13244
|
return d.toISOString().replace(/[:.]/g, "-");
|
|
13097
13245
|
}
|
|
13098
13246
|
async function atomicWrite(p, content) {
|
|
13099
|
-
await mkdir8(
|
|
13247
|
+
await mkdir8(path25.dirname(p), { recursive: true });
|
|
13100
13248
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
13101
13249
|
await writeFile10(tmp, content, "utf-8");
|
|
13102
13250
|
await rename6(tmp, p);
|
|
@@ -13499,8 +13647,8 @@ async function runSkillImprover(req) {
|
|
|
13499
13647
|
}
|
|
13500
13648
|
throw err;
|
|
13501
13649
|
}
|
|
13502
|
-
const proposalDir =
|
|
13503
|
-
const proposalFile =
|
|
13650
|
+
const proposalDir = path25.join(req.directory, ".swarm", "skill-improver", "proposals");
|
|
13651
|
+
const proposalFile = path25.join(proposalDir, `${timestampSlug(now)}.md`);
|
|
13504
13652
|
const finalBody = source === "llm" ? buildLLMProposalFrame({
|
|
13505
13653
|
body,
|
|
13506
13654
|
targets,
|
|
@@ -13570,13 +13718,13 @@ var _internals15 = {
|
|
|
13570
13718
|
|
|
13571
13719
|
// src/session/session-start-store.ts
|
|
13572
13720
|
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
|
|
13573
|
-
import * as
|
|
13721
|
+
import * as path26 from "path";
|
|
13574
13722
|
var SESSION_START_FILE = "session-start.jsonl";
|
|
13575
13723
|
function recordSessionStart(directory, startMs) {
|
|
13576
13724
|
try {
|
|
13577
|
-
const swarmDir =
|
|
13578
|
-
const sessionDir =
|
|
13579
|
-
const filePath =
|
|
13725
|
+
const swarmDir = path26.join(directory, ".swarm");
|
|
13726
|
+
const sessionDir = path26.join(swarmDir, "session");
|
|
13727
|
+
const filePath = path26.join(sessionDir, SESSION_START_FILE);
|
|
13580
13728
|
const line = JSON.stringify({ startMs, ts: Date.now() });
|
|
13581
13729
|
mkdirSync9(sessionDir, { recursive: true });
|
|
13582
13730
|
writeFileSync4(filePath, `${line}
|
|
@@ -13585,7 +13733,7 @@ function recordSessionStart(directory, startMs) {
|
|
|
13585
13733
|
}
|
|
13586
13734
|
function readEarliestSessionStart(directory) {
|
|
13587
13735
|
try {
|
|
13588
|
-
const filePath =
|
|
13736
|
+
const filePath = path26.join(directory, ".swarm", "session", SESSION_START_FILE);
|
|
13589
13737
|
if (!existsSync16(filePath))
|
|
13590
13738
|
return null;
|
|
13591
13739
|
const content = readFileSync8(filePath, "utf-8");
|
|
@@ -13612,7 +13760,7 @@ function readEarliestSessionStart(directory) {
|
|
|
13612
13760
|
|
|
13613
13761
|
// src/tools/write-retro.ts
|
|
13614
13762
|
import { existsSync as existsSync17 } from "fs";
|
|
13615
|
-
import
|
|
13763
|
+
import path27 from "path";
|
|
13616
13764
|
async function executeWriteRetro(args, directory) {
|
|
13617
13765
|
if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
|
|
13618
13766
|
return JSON.stringify({
|
|
@@ -13620,7 +13768,7 @@ async function executeWriteRetro(args, directory) {
|
|
|
13620
13768
|
message: "Invalid directory: reserved device name"
|
|
13621
13769
|
}, null, 2);
|
|
13622
13770
|
}
|
|
13623
|
-
if (!existsSync17(
|
|
13771
|
+
if (!existsSync17(path27.join(directory, ".swarm"))) {
|
|
13624
13772
|
return JSON.stringify({
|
|
13625
13773
|
success: false,
|
|
13626
13774
|
message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
|
|
@@ -14036,8 +14184,8 @@ async function copyDirRecursiveWithFailures(src, dest) {
|
|
|
14036
14184
|
const entries = await fs9.readdir(src);
|
|
14037
14185
|
await fs9.mkdir(dest, { recursive: true });
|
|
14038
14186
|
for (const entry of entries) {
|
|
14039
|
-
const srcEntry =
|
|
14040
|
-
const destEntry =
|
|
14187
|
+
const srcEntry = path28.join(src, entry);
|
|
14188
|
+
const destEntry = path28.join(dest, entry);
|
|
14041
14189
|
try {
|
|
14042
14190
|
const stat4 = await fs9.stat(srcEntry);
|
|
14043
14191
|
if (stat4.isDirectory()) {
|
|
@@ -14222,18 +14370,18 @@ async function runFinalizeStage(ctx) {
|
|
|
14222
14370
|
ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
|
|
14223
14371
|
}
|
|
14224
14372
|
}
|
|
14225
|
-
const lessonsFilePath =
|
|
14373
|
+
const lessonsFilePath = path28.join(ctx.swarmDir, "close-lessons.md");
|
|
14226
14374
|
try {
|
|
14227
14375
|
const lessonsText = await fs9.readFile(lessonsFilePath, "utf-8");
|
|
14228
14376
|
ctx.explicitLessons = lessonsText.split(`
|
|
14229
14377
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
14230
14378
|
} catch {}
|
|
14231
14379
|
try {
|
|
14232
|
-
const evidenceDir =
|
|
14380
|
+
const evidenceDir = path28.join(ctx.swarmDir, "evidence");
|
|
14233
14381
|
const evidenceEntries = await fs9.readdir(evidenceDir);
|
|
14234
14382
|
const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
|
|
14235
14383
|
for (const retroDir of retroDirs) {
|
|
14236
|
-
const evidencePath =
|
|
14384
|
+
const evidencePath = path28.join(evidenceDir, retroDir, "evidence.json");
|
|
14237
14385
|
try {
|
|
14238
14386
|
const content = await fs9.readFile(evidencePath, "utf-8");
|
|
14239
14387
|
const parsed = JSON.parse(content);
|
|
@@ -14385,7 +14533,7 @@ async function runFinalizeStage(ctx) {
|
|
|
14385
14533
|
}
|
|
14386
14534
|
}
|
|
14387
14535
|
try {
|
|
14388
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
14536
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-5vmb5dh8.js");
|
|
14389
14537
|
const { config: pmLoadedConfig } = _internals17.loadPluginConfigWithMeta(ctx.directory);
|
|
14390
14538
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
14391
14539
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
@@ -14417,7 +14565,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
|
|
|
14417
14565
|
let checkpointVerified = false;
|
|
14418
14566
|
try {
|
|
14419
14567
|
const result = _internals17.spawnSync("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
14420
|
-
cwd:
|
|
14568
|
+
cwd: path28.dirname(srcPath),
|
|
14421
14569
|
encoding: "utf-8",
|
|
14422
14570
|
stdio: ["ignore", "pipe", "pipe"],
|
|
14423
14571
|
timeout: 1e4,
|
|
@@ -14486,7 +14634,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
|
|
|
14486
14634
|
async function runArchiveStage(ctx) {
|
|
14487
14635
|
ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
14488
14636
|
ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
|
|
14489
|
-
ctx.archiveDir =
|
|
14637
|
+
ctx.archiveDir = path28.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
|
|
14490
14638
|
try {
|
|
14491
14639
|
await fs9.mkdir(ctx.archiveDir, { recursive: true });
|
|
14492
14640
|
const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
|
|
@@ -14501,8 +14649,8 @@ async function runArchiveStage(ctx) {
|
|
|
14501
14649
|
if (linkedKnowledgeShared && KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact)) {
|
|
14502
14650
|
continue;
|
|
14503
14651
|
}
|
|
14504
|
-
const srcPath =
|
|
14505
|
-
const destPath =
|
|
14652
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
14653
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
14506
14654
|
if (artifact === "swarm.db") {
|
|
14507
14655
|
const result = await copySqliteSafe(srcPath, destPath, undefined);
|
|
14508
14656
|
if (result.skipped) {} else if (result.success) {
|
|
@@ -14535,8 +14683,8 @@ async function runArchiveStage(ctx) {
|
|
|
14535
14683
|
}
|
|
14536
14684
|
const dynamicArchiveArtifacts = (await fs9.readdir(ctx.swarmDir).catch(() => [])).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name) || /^drift-report-phase-\d+\.json$/.test(name));
|
|
14537
14685
|
for (const artifact of dynamicArchiveArtifacts) {
|
|
14538
|
-
const srcPath =
|
|
14539
|
-
const destPath =
|
|
14686
|
+
const srcPath = path28.join(ctx.swarmDir, artifact);
|
|
14687
|
+
const destPath = path28.join(ctx.archiveDir, artifact);
|
|
14540
14688
|
try {
|
|
14541
14689
|
await fs9.copyFile(srcPath, destPath);
|
|
14542
14690
|
ctx.archivedFileCount++;
|
|
@@ -14551,8 +14699,8 @@ async function runArchiveStage(ctx) {
|
|
|
14551
14699
|
}
|
|
14552
14700
|
}
|
|
14553
14701
|
for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
|
|
14554
|
-
const srcDir =
|
|
14555
|
-
const destDir =
|
|
14702
|
+
const srcDir = path28.join(ctx.swarmDir, dirName);
|
|
14703
|
+
const destDir = path28.join(ctx.archiveDir, dirName);
|
|
14556
14704
|
try {
|
|
14557
14705
|
const result = await copyDirRecursiveWithFailures(srcDir, destDir);
|
|
14558
14706
|
ctx.archivedFileCount += result.copied;
|
|
@@ -14629,7 +14777,7 @@ async function runCleanStage(ctx) {
|
|
|
14629
14777
|
ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
|
|
14630
14778
|
continue;
|
|
14631
14779
|
}
|
|
14632
|
-
const filePath =
|
|
14780
|
+
const filePath = path28.join(ctx.swarmDir, artifact);
|
|
14633
14781
|
try {
|
|
14634
14782
|
await fs9.unlink(filePath);
|
|
14635
14783
|
cleanedFiles.push(artifact);
|
|
@@ -14649,7 +14797,7 @@ async function runCleanStage(ctx) {
|
|
|
14649
14797
|
continue;
|
|
14650
14798
|
}
|
|
14651
14799
|
try {
|
|
14652
|
-
await fs9.unlink(
|
|
14800
|
+
await fs9.unlink(path28.join(ctx.swarmDir, artifact));
|
|
14653
14801
|
cleanedFiles.push(artifact);
|
|
14654
14802
|
} catch (err) {
|
|
14655
14803
|
const errno = err?.code;
|
|
@@ -14663,7 +14811,7 @@ async function runCleanStage(ctx) {
|
|
|
14663
14811
|
if (!ctx.archivedActiveStateDirs.has(dirName)) {
|
|
14664
14812
|
continue;
|
|
14665
14813
|
}
|
|
14666
|
-
const dirPath =
|
|
14814
|
+
const dirPath = path28.join(ctx.swarmDir, dirName);
|
|
14667
14815
|
try {
|
|
14668
14816
|
await fs9.rm(dirPath, { recursive: true, force: true });
|
|
14669
14817
|
cleanedFiles.push(`${dirName}/`);
|
|
@@ -14674,7 +14822,7 @@ async function runCleanStage(ctx) {
|
|
|
14674
14822
|
const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
|
|
14675
14823
|
for (const backup of configBackups) {
|
|
14676
14824
|
try {
|
|
14677
|
-
await fs9.unlink(
|
|
14825
|
+
await fs9.unlink(path28.join(ctx.swarmDir, backup));
|
|
14678
14826
|
configBackupsRemoved++;
|
|
14679
14827
|
} catch (err) {
|
|
14680
14828
|
const errno = err?.code;
|
|
@@ -14687,7 +14835,7 @@ async function runCleanStage(ctx) {
|
|
|
14687
14835
|
const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
|
|
14688
14836
|
for (const sibling of ledgerSiblings) {
|
|
14689
14837
|
try {
|
|
14690
|
-
await fs9.unlink(
|
|
14838
|
+
await fs9.unlink(path28.join(ctx.swarmDir, sibling));
|
|
14691
14839
|
} catch (err) {
|
|
14692
14840
|
const errno = err?.code;
|
|
14693
14841
|
if (errno === "ENOENT") {} else {
|
|
@@ -14705,12 +14853,12 @@ async function runCleanStage(ctx) {
|
|
|
14705
14853
|
}
|
|
14706
14854
|
let swarmPlanFilesRemoved = 0;
|
|
14707
14855
|
const candidates = [
|
|
14708
|
-
|
|
14709
|
-
|
|
14710
|
-
|
|
14711
|
-
|
|
14712
|
-
|
|
14713
|
-
|
|
14856
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
|
|
14857
|
+
path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
|
|
14858
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
|
|
14859
|
+
path28.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
|
|
14860
|
+
path28.join(ctx.directory, "SWARM_PLAN.json"),
|
|
14861
|
+
path28.join(ctx.directory, "SWARM_PLAN.md")
|
|
14714
14862
|
];
|
|
14715
14863
|
for (const candidate of candidates) {
|
|
14716
14864
|
try {
|
|
@@ -14728,7 +14876,7 @@ async function runCleanStage(ctx) {
|
|
|
14728
14876
|
const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
|
|
14729
14877
|
for (const tmp of tmpFiles) {
|
|
14730
14878
|
try {
|
|
14731
|
-
await fs9.unlink(
|
|
14879
|
+
await fs9.unlink(path28.join(ctx.swarmDir, tmp));
|
|
14732
14880
|
tmpFilesRemoved++;
|
|
14733
14881
|
} catch (err) {
|
|
14734
14882
|
const errno = err?.code;
|
|
@@ -14750,7 +14898,7 @@ async function runCleanStage(ctx) {
|
|
|
14750
14898
|
}
|
|
14751
14899
|
for (const terminalFile of TERMINAL_STATE_FILES) {
|
|
14752
14900
|
try {
|
|
14753
|
-
await fs9.unlink(
|
|
14901
|
+
await fs9.unlink(path28.join(ctx.swarmDir, terminalFile));
|
|
14754
14902
|
if (!cleanedFiles.includes(terminalFile)) {
|
|
14755
14903
|
cleanedFiles.push(terminalFile);
|
|
14756
14904
|
}
|
|
@@ -14763,7 +14911,7 @@ async function runCleanStage(ctx) {
|
|
|
14763
14911
|
}
|
|
14764
14912
|
}
|
|
14765
14913
|
clearAllScopes(ctx.directory);
|
|
14766
|
-
const contextPath =
|
|
14914
|
+
const contextPath = path28.join(ctx.swarmDir, "context.md");
|
|
14767
14915
|
const contextContent = [
|
|
14768
14916
|
"# Context",
|
|
14769
14917
|
"",
|
|
@@ -14775,7 +14923,7 @@ async function runCleanStage(ctx) {
|
|
|
14775
14923
|
""
|
|
14776
14924
|
].join(`
|
|
14777
14925
|
`);
|
|
14778
|
-
const contextTempPath =
|
|
14926
|
+
const contextTempPath = path28.join(path28.dirname(contextPath), `${path28.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
14779
14927
|
try {
|
|
14780
14928
|
await fs9.writeFile(contextTempPath, contextContent, "utf-8");
|
|
14781
14929
|
fsSync.renameSync(contextTempPath, contextPath);
|
|
@@ -14839,7 +14987,7 @@ async function runAlignStage(ctx) {
|
|
|
14839
14987
|
return { gitAlignResult, prunedBranches };
|
|
14840
14988
|
}
|
|
14841
14989
|
async function handleCloseCommand(directory, args, options = {}) {
|
|
14842
|
-
const swarmDir =
|
|
14990
|
+
const swarmDir = path28.join(directory, ".swarm");
|
|
14843
14991
|
try {
|
|
14844
14992
|
const stat4 = fsSync.lstatSync(swarmDir);
|
|
14845
14993
|
if (stat4.isSymbolicLink()) {
|
|
@@ -14853,7 +15001,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
14853
15001
|
const planPath = validateSwarmPath(directory, "plan.json");
|
|
14854
15002
|
let planExists = false;
|
|
14855
15003
|
let planData = {
|
|
14856
|
-
title:
|
|
15004
|
+
title: path28.basename(directory) || "Ad-hoc session",
|
|
14857
15005
|
phases: []
|
|
14858
15006
|
};
|
|
14859
15007
|
try {
|
|
@@ -14878,7 +15026,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
14878
15026
|
}
|
|
14879
15027
|
try {
|
|
14880
15028
|
if (!planExists) {
|
|
14881
|
-
const archiveDir =
|
|
15029
|
+
const archiveDir = path28.join(swarmDir, "archive");
|
|
14882
15030
|
try {
|
|
14883
15031
|
const archiveEntries = await fs9.readdir(archiveDir);
|
|
14884
15032
|
const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
|
|
@@ -14886,7 +15034,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
14886
15034
|
const hasActiveState = [
|
|
14887
15035
|
...ACTIVE_STATE_TO_CLEAN,
|
|
14888
15036
|
...ACTIVE_STATE_DIRS_TO_CLEAN
|
|
14889
|
-
].some((entry) => fsSync.existsSync(
|
|
15037
|
+
].some((entry) => fsSync.existsSync(path28.join(swarmDir, entry)));
|
|
14890
15038
|
if (!hasActiveState) {
|
|
14891
15039
|
return `\u2705 Already finalized \u2014 nothing to do.
|
|
14892
15040
|
|
|
@@ -15014,7 +15162,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
15014
15162
|
...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
|
|
15015
15163
|
].join(`
|
|
15016
15164
|
`);
|
|
15017
|
-
const closeSummaryTempPath =
|
|
15165
|
+
const closeSummaryTempPath = path28.join(path28.dirname(closeSummaryPath), `${path28.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
15018
15166
|
try {
|
|
15019
15167
|
await fs9.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
|
|
15020
15168
|
fsSync.renameSync(closeSummaryTempPath, closeSummaryPath);
|
|
@@ -15365,14 +15513,14 @@ function buildStatusMessage(session, plan) {
|
|
|
15365
15513
|
|
|
15366
15514
|
// src/commands/config.ts
|
|
15367
15515
|
import * as os5 from "os";
|
|
15368
|
-
import * as
|
|
15516
|
+
import * as path29 from "path";
|
|
15369
15517
|
function getUserConfigDir2() {
|
|
15370
|
-
return process.env.XDG_CONFIG_HOME ||
|
|
15518
|
+
return process.env.XDG_CONFIG_HOME || path29.join(os5.homedir(), ".config");
|
|
15371
15519
|
}
|
|
15372
15520
|
async function handleConfigCommand(directory, _args) {
|
|
15373
15521
|
const config = loadPluginConfig(directory);
|
|
15374
|
-
const userConfigPath =
|
|
15375
|
-
const projectConfigPath =
|
|
15522
|
+
const userConfigPath = path29.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
|
|
15523
|
+
const projectConfigPath = path29.join(directory, ".opencode", "opencode-swarm.json");
|
|
15376
15524
|
const lines = [
|
|
15377
15525
|
"## Swarm Configuration",
|
|
15378
15526
|
"",
|
|
@@ -15392,7 +15540,7 @@ async function handleConfigCommand(directory, _args) {
|
|
|
15392
15540
|
// src/services/skill-consolidation.ts
|
|
15393
15541
|
import { existsSync as existsSync19 } from "fs";
|
|
15394
15542
|
import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
|
|
15395
|
-
import * as
|
|
15543
|
+
import * as path30 from "path";
|
|
15396
15544
|
|
|
15397
15545
|
// src/utils/timeout.ts
|
|
15398
15546
|
async function withTimeout(promise, ms, timeoutError) {
|
|
@@ -15417,7 +15565,7 @@ var DEFAULT_CONSOLIDATION_MAX_CALLS_PER_RUN = 1;
|
|
|
15417
15565
|
var CONSOLIDATION_RUN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
15418
15566
|
var runningByDirectory = new Map;
|
|
15419
15567
|
function consolidationStatePath(directory) {
|
|
15420
|
-
return
|
|
15568
|
+
return path30.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
|
|
15421
15569
|
}
|
|
15422
15570
|
async function readState2(directory) {
|
|
15423
15571
|
const filePath = consolidationStatePath(directory);
|
|
@@ -15433,7 +15581,7 @@ async function readState2(directory) {
|
|
|
15433
15581
|
}
|
|
15434
15582
|
}
|
|
15435
15583
|
async function atomicWrite2(filePath, content) {
|
|
15436
|
-
await mkdir9(
|
|
15584
|
+
await mkdir9(path30.dirname(filePath), { recursive: true });
|
|
15437
15585
|
const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
15438
15586
|
await writeFile11(tmp, content, "utf-8");
|
|
15439
15587
|
await rename7(tmp, filePath);
|
|
@@ -15513,7 +15661,7 @@ async function runSkillConsolidationInner(req) {
|
|
|
15513
15661
|
};
|
|
15514
15662
|
}
|
|
15515
15663
|
async function runSkillConsolidation(req) {
|
|
15516
|
-
const key =
|
|
15664
|
+
const key = path30.resolve(req.directory);
|
|
15517
15665
|
const existing = runningByDirectory.get(key);
|
|
15518
15666
|
if (existing) {
|
|
15519
15667
|
return {
|
|
@@ -15715,7 +15863,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
15715
15863
|
// src/commands/coupling.ts
|
|
15716
15864
|
import { randomBytes } from "crypto";
|
|
15717
15865
|
import * as fs10 from "fs";
|
|
15718
|
-
import * as
|
|
15866
|
+
import * as path32 from "path";
|
|
15719
15867
|
|
|
15720
15868
|
// src/turbo/epic/cochange-source.ts
|
|
15721
15869
|
import * as child_process4 from "child_process";
|
|
@@ -15725,7 +15873,7 @@ import { promisify as promisify2 } from "util";
|
|
|
15725
15873
|
import * as child_process3 from "child_process";
|
|
15726
15874
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
15727
15875
|
import { readdir as readdir2, readFile as readFile11, stat as stat4 } from "fs/promises";
|
|
15728
|
-
import * as
|
|
15876
|
+
import * as path31 from "path";
|
|
15729
15877
|
import { promisify } from "util";
|
|
15730
15878
|
function getExecFileAsync() {
|
|
15731
15879
|
return promisify(child_process3.execFile);
|
|
@@ -15829,7 +15977,7 @@ async function scanSourceFiles(dir) {
|
|
|
15829
15977
|
try {
|
|
15830
15978
|
const entries = await readdir2(dir, { withFileTypes: true });
|
|
15831
15979
|
for (const entry of entries) {
|
|
15832
|
-
const fullPath =
|
|
15980
|
+
const fullPath = path31.join(dir, entry.name);
|
|
15833
15981
|
if (entry.isDirectory()) {
|
|
15834
15982
|
if (skipDirs.has(entry.name)) {
|
|
15835
15983
|
continue;
|
|
@@ -15837,7 +15985,7 @@ async function scanSourceFiles(dir) {
|
|
|
15837
15985
|
const subFiles = await scanSourceFiles(fullPath);
|
|
15838
15986
|
results.push(...subFiles);
|
|
15839
15987
|
} else if (entry.isFile()) {
|
|
15840
|
-
const ext =
|
|
15988
|
+
const ext = path31.extname(entry.name);
|
|
15841
15989
|
if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
|
|
15842
15990
|
results.push(fullPath);
|
|
15843
15991
|
}
|
|
@@ -15859,8 +16007,8 @@ async function getStaticEdges(directory) {
|
|
|
15859
16007
|
continue;
|
|
15860
16008
|
}
|
|
15861
16009
|
try {
|
|
15862
|
-
const sourceDir =
|
|
15863
|
-
const resolvedPath =
|
|
16010
|
+
const sourceDir = path31.dirname(sourceFile);
|
|
16011
|
+
const resolvedPath = path31.resolve(sourceDir, importPath);
|
|
15864
16012
|
const extensions = [
|
|
15865
16013
|
"",
|
|
15866
16014
|
".ts",
|
|
@@ -15885,8 +16033,8 @@ async function getStaticEdges(directory) {
|
|
|
15885
16033
|
if (!targetFile) {
|
|
15886
16034
|
continue;
|
|
15887
16035
|
}
|
|
15888
|
-
const relSource =
|
|
15889
|
-
const relTarget =
|
|
16036
|
+
const relSource = path31.relative(directory, sourceFile).replace(/\\/g, "/");
|
|
16037
|
+
const relTarget = path31.relative(directory, targetFile).replace(/\\/g, "/");
|
|
15890
16038
|
const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
|
|
15891
16039
|
edges.add(key);
|
|
15892
16040
|
} catch {}
|
|
@@ -15898,7 +16046,7 @@ async function getStaticEdges(directory) {
|
|
|
15898
16046
|
function isTestImplementationPair(fileA, fileB) {
|
|
15899
16047
|
const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
|
|
15900
16048
|
const getBaseName = (filePath) => {
|
|
15901
|
-
const base =
|
|
16049
|
+
const base = path31.basename(filePath);
|
|
15902
16050
|
for (const pattern of testPatterns) {
|
|
15903
16051
|
if (base.endsWith(pattern)) {
|
|
15904
16052
|
return base.slice(0, -pattern.length);
|
|
@@ -15908,16 +16056,16 @@ function isTestImplementationPair(fileA, fileB) {
|
|
|
15908
16056
|
};
|
|
15909
16057
|
const baseA = getBaseName(fileA);
|
|
15910
16058
|
const baseB = getBaseName(fileB);
|
|
15911
|
-
return baseA === baseB && baseA !==
|
|
16059
|
+
return baseA === baseB && baseA !== path31.basename(fileA) && baseA !== path31.basename(fileB);
|
|
15912
16060
|
}
|
|
15913
16061
|
function hasSharedPrefix(fileA, fileB) {
|
|
15914
|
-
const dirA =
|
|
15915
|
-
const dirB =
|
|
16062
|
+
const dirA = path31.dirname(fileA);
|
|
16063
|
+
const dirB = path31.dirname(fileB);
|
|
15916
16064
|
if (dirA !== dirB) {
|
|
15917
16065
|
return false;
|
|
15918
16066
|
}
|
|
15919
|
-
const baseA =
|
|
15920
|
-
const baseB =
|
|
16067
|
+
const baseA = path31.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
16068
|
+
const baseB = path31.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
|
|
15921
16069
|
if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
|
|
15922
16070
|
return true;
|
|
15923
16071
|
}
|
|
@@ -15972,8 +16120,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
|
|
|
15972
16120
|
const entries = [];
|
|
15973
16121
|
const now = new Date().toISOString();
|
|
15974
16122
|
for (const pair of pairs.slice(0, 10)) {
|
|
15975
|
-
const baseA =
|
|
15976
|
-
const baseB =
|
|
16123
|
+
const baseA = path31.basename(pair.fileA);
|
|
16124
|
+
const baseB = path31.basename(pair.fileB);
|
|
15977
16125
|
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.`;
|
|
15978
16126
|
if (lesson.length > 280) {
|
|
15979
16127
|
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.`;
|
|
@@ -16399,9 +16547,9 @@ function parseArgs3(args) {
|
|
|
16399
16547
|
return parsed;
|
|
16400
16548
|
}
|
|
16401
16549
|
function persistReportJson(directory, report) {
|
|
16402
|
-
const epicDir =
|
|
16550
|
+
const epicDir = path32.join(directory, ".swarm", "epic");
|
|
16403
16551
|
fs10.mkdirSync(epicDir, { recursive: true });
|
|
16404
|
-
const filePath =
|
|
16552
|
+
const filePath = path32.join(epicDir, "coupling-report.json");
|
|
16405
16553
|
const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
|
|
16406
16554
|
fs10.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
|
|
16407
16555
|
`, "utf-8");
|
|
@@ -16460,7 +16608,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
16460
16608
|
persistStatus = {
|
|
16461
16609
|
requested: true,
|
|
16462
16610
|
written: true,
|
|
16463
|
-
path:
|
|
16611
|
+
path: path32.relative(directory, writtenAt).replace(/\\/g, "/")
|
|
16464
16612
|
};
|
|
16465
16613
|
} catch (err) {
|
|
16466
16614
|
persistStatus = {
|
|
@@ -16498,9 +16646,9 @@ var _internals21 = {
|
|
|
16498
16646
|
readSwarmFileAsync,
|
|
16499
16647
|
loadCuratorDeps: async () => {
|
|
16500
16648
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
16501
|
-
import("./schema-
|
|
16502
|
-
import("./curator-
|
|
16503
|
-
import("./curator-llm-factory-
|
|
16649
|
+
import("./schema-5vmb5dh8.js"),
|
|
16650
|
+
import("./curator-zn1kmwmz.js"),
|
|
16651
|
+
import("./curator-llm-factory-3hf9xpnd.js")
|
|
16504
16652
|
]);
|
|
16505
16653
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
16506
16654
|
}
|
|
@@ -16592,7 +16740,7 @@ function formatCurationSummary(summary) {
|
|
|
16592
16740
|
}
|
|
16593
16741
|
|
|
16594
16742
|
// src/commands/dark-matter.ts
|
|
16595
|
-
import
|
|
16743
|
+
import path33 from "path";
|
|
16596
16744
|
async function handleDarkMatterCommand(directory, args) {
|
|
16597
16745
|
const options = {};
|
|
16598
16746
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -16624,7 +16772,7 @@ Ensure this is a git repository with commit history.`;
|
|
|
16624
16772
|
const output = formatDarkMatterOutput(pairs);
|
|
16625
16773
|
if (pairs.length > 0) {
|
|
16626
16774
|
try {
|
|
16627
|
-
const projectName =
|
|
16775
|
+
const projectName = path33.basename(path33.resolve(directory));
|
|
16628
16776
|
const entries = darkMatterToKnowledgeEntries(pairs, projectName);
|
|
16629
16777
|
if (entries.length > 0) {
|
|
16630
16778
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
@@ -16991,12 +17139,12 @@ ${USAGE5}`;
|
|
|
16991
17139
|
// src/services/diagnose-service.ts
|
|
16992
17140
|
import * as child_process5 from "child_process";
|
|
16993
17141
|
import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
16994
|
-
import * as
|
|
17142
|
+
import * as path35 from "path";
|
|
16995
17143
|
import { fileURLToPath } from "url";
|
|
16996
17144
|
// package.json
|
|
16997
17145
|
var package_default = {
|
|
16998
17146
|
name: "opencode-swarm",
|
|
16999
|
-
version: "7.109.
|
|
17147
|
+
version: "7.109.4",
|
|
17000
17148
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
17001
17149
|
main: "dist/index.js",
|
|
17002
17150
|
types: "dist/index.d.ts",
|
|
@@ -17063,6 +17211,11 @@ var package_default = {
|
|
|
17063
17211
|
".opencode/skills/running-tests",
|
|
17064
17212
|
".opencode/skills/engineering-conventions",
|
|
17065
17213
|
".opencode/skills/commit-pr",
|
|
17214
|
+
".opencode/skills/worktree-retry-cleanup",
|
|
17215
|
+
".opencode/skills/skill-edit-validation",
|
|
17216
|
+
".opencode/skills/merge-queue-readiness",
|
|
17217
|
+
".opencode/skills/gate-attribution",
|
|
17218
|
+
".opencode/skills/ci-failure-batching",
|
|
17066
17219
|
"tests/fixtures/memory-recall",
|
|
17067
17220
|
"README.md",
|
|
17068
17221
|
"LICENSE"
|
|
@@ -17105,44 +17258,44 @@ var package_default = {
|
|
|
17105
17258
|
|
|
17106
17259
|
// src/config/cache-paths.ts
|
|
17107
17260
|
import * as os6 from "os";
|
|
17108
|
-
import * as
|
|
17261
|
+
import * as path34 from "path";
|
|
17109
17262
|
function getPluginConfigDir() {
|
|
17110
|
-
return
|
|
17263
|
+
return path34.join(process.env.XDG_CONFIG_HOME || path34.join(os6.homedir(), ".config"), "opencode");
|
|
17111
17264
|
}
|
|
17112
17265
|
function getPluginCachePaths() {
|
|
17113
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17266
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os6.homedir(), ".cache");
|
|
17114
17267
|
const configDir = getPluginConfigDir();
|
|
17115
17268
|
const paths = [
|
|
17116
|
-
|
|
17117
|
-
|
|
17118
|
-
|
|
17269
|
+
path34.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
|
|
17270
|
+
path34.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
|
|
17271
|
+
path34.join(configDir, "node_modules", "opencode-swarm")
|
|
17119
17272
|
];
|
|
17120
17273
|
if (process.platform === "darwin") {
|
|
17121
|
-
const libCaches =
|
|
17122
|
-
paths.push(
|
|
17274
|
+
const libCaches = path34.join(os6.homedir(), "Library", "Caches");
|
|
17275
|
+
paths.push(path34.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path34.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
|
|
17123
17276
|
}
|
|
17124
17277
|
if (process.platform === "win32") {
|
|
17125
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17126
|
-
const appData = process.env.APPDATA ||
|
|
17127
|
-
paths.push(
|
|
17278
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os6.homedir(), "AppData", "Local");
|
|
17279
|
+
const appData = process.env.APPDATA || path34.join(os6.homedir(), "AppData", "Roaming");
|
|
17280
|
+
paths.push(path34.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path34.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path34.join(appData, "opencode", "node_modules", "opencode-swarm"));
|
|
17128
17281
|
}
|
|
17129
17282
|
return paths;
|
|
17130
17283
|
}
|
|
17131
17284
|
function getPluginLockFilePaths() {
|
|
17132
|
-
const cacheBase = process.env.XDG_CACHE_HOME ||
|
|
17285
|
+
const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os6.homedir(), ".cache");
|
|
17133
17286
|
const configDir = getPluginConfigDir();
|
|
17134
17287
|
const paths = [
|
|
17135
|
-
|
|
17136
|
-
|
|
17137
|
-
|
|
17288
|
+
path34.join(cacheBase, "opencode", "bun.lock"),
|
|
17289
|
+
path34.join(cacheBase, "opencode", "bun.lockb"),
|
|
17290
|
+
path34.join(configDir, "package-lock.json")
|
|
17138
17291
|
];
|
|
17139
17292
|
if (process.platform === "darwin") {
|
|
17140
|
-
const libCaches =
|
|
17141
|
-
paths.push(
|
|
17293
|
+
const libCaches = path34.join(os6.homedir(), "Library", "Caches");
|
|
17294
|
+
paths.push(path34.join(libCaches, "opencode", "bun.lock"), path34.join(libCaches, "opencode", "bun.lockb"));
|
|
17142
17295
|
}
|
|
17143
17296
|
if (process.platform === "win32") {
|
|
17144
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
17145
|
-
paths.push(
|
|
17297
|
+
const localAppData = process.env.LOCALAPPDATA || path34.join(os6.homedir(), "AppData", "Local");
|
|
17298
|
+
paths.push(path34.join(localAppData, "opencode", "bun.lock"), path34.join(localAppData, "opencode", "bun.lockb"));
|
|
17146
17299
|
}
|
|
17147
17300
|
return paths;
|
|
17148
17301
|
}
|
|
@@ -17172,10 +17325,10 @@ function cacheFile() {
|
|
|
17172
17325
|
}
|
|
17173
17326
|
function readVersionCache() {
|
|
17174
17327
|
try {
|
|
17175
|
-
const
|
|
17176
|
-
if (!existsSync20(
|
|
17328
|
+
const path35 = cacheFile();
|
|
17329
|
+
if (!existsSync20(path35))
|
|
17177
17330
|
return null;
|
|
17178
|
-
const raw = readFileSync9(
|
|
17331
|
+
const raw = readFileSync9(path35, "utf-8");
|
|
17179
17332
|
const parsed = JSON.parse(raw);
|
|
17180
17333
|
if (typeof parsed?.checkedAt !== "number")
|
|
17181
17334
|
return null;
|
|
@@ -17430,7 +17583,7 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
|
|
|
17430
17583
|
"tree-sitter-typescript.wasm"
|
|
17431
17584
|
];
|
|
17432
17585
|
function resolveCachePackageRoot(cachePath) {
|
|
17433
|
-
const nestedPackageRoot =
|
|
17586
|
+
const nestedPackageRoot = path35.join(cachePath, "node_modules", "opencode-swarm");
|
|
17434
17587
|
return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
17435
17588
|
}
|
|
17436
17589
|
var _internals22 = {
|
|
@@ -17746,7 +17899,7 @@ async function checkSpecStaleness(directory, plan) {
|
|
|
17746
17899
|
};
|
|
17747
17900
|
}
|
|
17748
17901
|
async function checkConfigParseability(directory) {
|
|
17749
|
-
const configPath =
|
|
17902
|
+
const configPath = path35.join(directory, ".opencode/opencode-swarm.json");
|
|
17750
17903
|
if (!existsSync22(configPath)) {
|
|
17751
17904
|
return {
|
|
17752
17905
|
name: "Config Parseability",
|
|
@@ -17775,7 +17928,7 @@ function resolveGrammarDir(thisDir) {
|
|
|
17775
17928
|
const normalized = thisDir.replace(/\\/g, "/");
|
|
17776
17929
|
const isSource = normalized.endsWith("/src/services");
|
|
17777
17930
|
const isCliBundle = normalized.endsWith("/cli");
|
|
17778
|
-
return isSource || isCliBundle ?
|
|
17931
|
+
return isSource || isCliBundle ? path35.join(thisDir, "..", "lang", "grammars") : path35.join(thisDir, "lang", "grammars");
|
|
17779
17932
|
}
|
|
17780
17933
|
async function checkGrammarWasmFiles() {
|
|
17781
17934
|
const grammarFiles = [
|
|
@@ -17799,14 +17952,14 @@ async function checkGrammarWasmFiles() {
|
|
|
17799
17952
|
"tree-sitter-ini.wasm",
|
|
17800
17953
|
"tree-sitter-regex.wasm"
|
|
17801
17954
|
];
|
|
17802
|
-
const thisDir =
|
|
17955
|
+
const thisDir = path35.dirname(fileURLToPath(import.meta.url));
|
|
17803
17956
|
const grammarDir = resolveGrammarDir(thisDir);
|
|
17804
17957
|
const missing = [];
|
|
17805
|
-
if (!existsSync22(
|
|
17958
|
+
if (!existsSync22(path35.join(grammarDir, "tree-sitter.wasm"))) {
|
|
17806
17959
|
missing.push("tree-sitter.wasm (core runtime)");
|
|
17807
17960
|
}
|
|
17808
17961
|
for (const file of grammarFiles) {
|
|
17809
|
-
if (!existsSync22(
|
|
17962
|
+
if (!existsSync22(path35.join(grammarDir, file))) {
|
|
17810
17963
|
missing.push(file);
|
|
17811
17964
|
}
|
|
17812
17965
|
}
|
|
@@ -17824,7 +17977,7 @@ async function checkGrammarWasmFiles() {
|
|
|
17824
17977
|
};
|
|
17825
17978
|
}
|
|
17826
17979
|
async function checkCheckpointManifest(directory) {
|
|
17827
|
-
const manifestPath =
|
|
17980
|
+
const manifestPath = path35.join(directory, ".swarm/checkpoints.json");
|
|
17828
17981
|
if (!existsSync22(manifestPath)) {
|
|
17829
17982
|
return {
|
|
17830
17983
|
name: "Checkpoint Manifest",
|
|
@@ -17876,7 +18029,7 @@ async function checkCheckpointManifest(directory) {
|
|
|
17876
18029
|
}
|
|
17877
18030
|
}
|
|
17878
18031
|
async function checkEventStreamIntegrity(directory) {
|
|
17879
|
-
const eventsPath =
|
|
18032
|
+
const eventsPath = path35.join(directory, ".swarm/events.jsonl");
|
|
17880
18033
|
if (!existsSync22(eventsPath)) {
|
|
17881
18034
|
return {
|
|
17882
18035
|
name: "Event Stream",
|
|
@@ -17917,7 +18070,7 @@ async function checkEventStreamIntegrity(directory) {
|
|
|
17917
18070
|
}
|
|
17918
18071
|
}
|
|
17919
18072
|
async function checkSteeringDirectives(directory) {
|
|
17920
|
-
const eventsPath =
|
|
18073
|
+
const eventsPath = path35.join(directory, ".swarm/events.jsonl");
|
|
17921
18074
|
if (!existsSync22(eventsPath)) {
|
|
17922
18075
|
return {
|
|
17923
18076
|
name: "Steering Directives",
|
|
@@ -17973,7 +18126,7 @@ async function checkCurator(directory) {
|
|
|
17973
18126
|
detail: "Disabled (enable via curator.enabled)"
|
|
17974
18127
|
};
|
|
17975
18128
|
}
|
|
17976
|
-
const summaryPath =
|
|
18129
|
+
const summaryPath = path35.join(directory, ".swarm/curator-summary.json");
|
|
17977
18130
|
if (!existsSync22(summaryPath)) {
|
|
17978
18131
|
return {
|
|
17979
18132
|
name: "Curator",
|
|
@@ -18175,7 +18328,7 @@ async function getDiagnoseData(directory) {
|
|
|
18175
18328
|
checks.push(await checkCurator(directory));
|
|
18176
18329
|
checks.push(await checkKnowledgeHealth(directory));
|
|
18177
18330
|
try {
|
|
18178
|
-
const evidenceDir =
|
|
18331
|
+
const evidenceDir = path35.join(directory, ".swarm", "evidence");
|
|
18179
18332
|
const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
|
|
18180
18333
|
if (snapshotFiles.length > 0) {
|
|
18181
18334
|
const latest = snapshotFiles.sort().pop();
|
|
@@ -18215,8 +18368,8 @@ async function getDiagnoseData(directory) {
|
|
|
18215
18368
|
}
|
|
18216
18369
|
const packageRoot = resolveCachePackageRoot(cachePath);
|
|
18217
18370
|
const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
|
|
18218
|
-
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(
|
|
18219
|
-
const pkgJsonPath =
|
|
18371
|
+
const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path35.join(packageRoot, "dist", "lang", "grammars", file)));
|
|
18372
|
+
const pkgJsonPath = path35.join(packageRoot, "package.json");
|
|
18220
18373
|
try {
|
|
18221
18374
|
const raw = readFileSync10(pkgJsonPath, "utf-8");
|
|
18222
18375
|
const parsed = JSON.parse(raw);
|
|
@@ -18441,7 +18594,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
18441
18594
|
const result = runConfigDoctor(config, directory);
|
|
18442
18595
|
let output;
|
|
18443
18596
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
18444
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
18597
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-9vjyj9m3.js");
|
|
18445
18598
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true);
|
|
18446
18599
|
output = formatDoctorMarkdown(fixResult.result);
|
|
18447
18600
|
} else {
|
|
@@ -18592,9 +18745,9 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
|
|
|
18592
18745
|
// src/turbo/epic/calibration.ts
|
|
18593
18746
|
init_logger();
|
|
18594
18747
|
import * as fs11 from "fs";
|
|
18595
|
-
import * as
|
|
18748
|
+
import * as path36 from "path";
|
|
18596
18749
|
var STATE_FILE = "calibration.json";
|
|
18597
|
-
var STATE_REL_DIR =
|
|
18750
|
+
var STATE_REL_DIR = path36.join(".swarm", "epic");
|
|
18598
18751
|
function nowISO() {
|
|
18599
18752
|
return new Date().toISOString();
|
|
18600
18753
|
}
|
|
@@ -18616,7 +18769,7 @@ function markUnreadable(directory, reason) {
|
|
|
18616
18769
|
error(`[epic/calibration] state file unreadable for ${directory}: ${reason} \u2014 failing closed`);
|
|
18617
18770
|
}
|
|
18618
18771
|
function repairCalibrationUnreadable(directory) {
|
|
18619
|
-
const filePath =
|
|
18772
|
+
const filePath = path36.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
18620
18773
|
if (!fs11.existsSync(filePath)) {
|
|
18621
18774
|
stateUnreadableMap.delete(directory);
|
|
18622
18775
|
return;
|
|
@@ -18648,7 +18801,7 @@ function isValidCalibrationShape(candidate) {
|
|
|
18648
18801
|
return true;
|
|
18649
18802
|
}
|
|
18650
18803
|
function ensureSwarmEpicDir(directory) {
|
|
18651
|
-
const dir =
|
|
18804
|
+
const dir = path36.resolve(directory, STATE_REL_DIR);
|
|
18652
18805
|
if (!fs11.existsSync(dir)) {
|
|
18653
18806
|
fs11.mkdirSync(dir, { recursive: true });
|
|
18654
18807
|
}
|
|
@@ -18660,7 +18813,7 @@ function loadCalibrationState(directory) {
|
|
|
18660
18813
|
if (stateUnreadableMap.get(directory))
|
|
18661
18814
|
return null;
|
|
18662
18815
|
}
|
|
18663
|
-
const filePath =
|
|
18816
|
+
const filePath = path36.join(directory, STATE_REL_DIR, STATE_FILE);
|
|
18664
18817
|
try {
|
|
18665
18818
|
if (!fs11.existsSync(filePath)) {
|
|
18666
18819
|
const seed = emptyCalibrationState();
|
|
@@ -18687,12 +18840,12 @@ function loadCalibrationState(directory) {
|
|
|
18687
18840
|
// src/turbo/epic/divergence-recorder.ts
|
|
18688
18841
|
init_logger();
|
|
18689
18842
|
import * as fs12 from "fs";
|
|
18690
|
-
import * as
|
|
18691
|
-
var EVIDENCE_REL_DIR =
|
|
18843
|
+
import * as path37 from "path";
|
|
18844
|
+
var EVIDENCE_REL_DIR = path37.join(".swarm", "epic");
|
|
18692
18845
|
var EVIDENCE_FILE = "divergence.jsonl";
|
|
18693
18846
|
var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
|
|
18694
18847
|
function readDivergenceHistory(directory, options) {
|
|
18695
|
-
const filePath =
|
|
18848
|
+
const filePath = path37.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
|
|
18696
18849
|
if (!fs12.existsSync(filePath)) {
|
|
18697
18850
|
return [];
|
|
18698
18851
|
}
|
|
@@ -18741,11 +18894,11 @@ function readDivergenceHistory(directory, options) {
|
|
|
18741
18894
|
|
|
18742
18895
|
// src/turbo/epic/promotion-evidence.ts
|
|
18743
18896
|
import * as fs13 from "fs";
|
|
18744
|
-
import * as
|
|
18745
|
-
var EVIDENCE_REL_DIR2 =
|
|
18897
|
+
import * as path38 from "path";
|
|
18898
|
+
var EVIDENCE_REL_DIR2 = path38.join(".swarm", "evidence");
|
|
18746
18899
|
var EVIDENCE_FILE2 = "epic-promotions.jsonl";
|
|
18747
18900
|
function readPromotionEvidence(directory) {
|
|
18748
|
-
const filePath =
|
|
18901
|
+
const filePath = path38.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
|
|
18749
18902
|
if (!fs13.existsSync(filePath)) {
|
|
18750
18903
|
return [];
|
|
18751
18904
|
}
|
|
@@ -19319,7 +19472,7 @@ async function handleExportCommand(directory, _args) {
|
|
|
19319
19472
|
// src/full-auto/state.ts
|
|
19320
19473
|
var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
|
|
19321
19474
|
import * as fs14 from "fs";
|
|
19322
|
-
import * as
|
|
19475
|
+
import * as path39 from "path";
|
|
19323
19476
|
init_logger();
|
|
19324
19477
|
var lockfile3 = import_proper_lockfile3.default;
|
|
19325
19478
|
var STATE_FILE2 = "full-auto-state.json";
|
|
@@ -19327,7 +19480,7 @@ function nowISO2() {
|
|
|
19327
19480
|
return new Date().toISOString();
|
|
19328
19481
|
}
|
|
19329
19482
|
function ensureSwarmDir(directory) {
|
|
19330
|
-
const swarmDir =
|
|
19483
|
+
const swarmDir = path39.resolve(directory, ".swarm");
|
|
19331
19484
|
if (!fs14.existsSync(swarmDir)) {
|
|
19332
19485
|
fs14.mkdirSync(swarmDir, { recursive: true });
|
|
19333
19486
|
}
|
|
@@ -20139,7 +20292,7 @@ var _internals25 = {
|
|
|
20139
20292
|
|
|
20140
20293
|
// src/session/snapshot-writer.ts
|
|
20141
20294
|
import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync16, openSync as openSync5, renameSync as renameSync8 } from "fs";
|
|
20142
|
-
import * as
|
|
20295
|
+
import * as path40 from "path";
|
|
20143
20296
|
var _writeInFlight = Promise.resolve();
|
|
20144
20297
|
function serializeAgentSession(s) {
|
|
20145
20298
|
const gateLog = {};
|
|
@@ -20252,7 +20405,7 @@ async function writeSnapshot(directory, state) {
|
|
|
20252
20405
|
}
|
|
20253
20406
|
const content = JSON.stringify(snapshot, null, 2);
|
|
20254
20407
|
const resolvedPath = validateSwarmPath(directory, "session/state.json");
|
|
20255
|
-
const dir =
|
|
20408
|
+
const dir = path40.dirname(resolvedPath);
|
|
20256
20409
|
mkdirSync16(dir, { recursive: true });
|
|
20257
20410
|
const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
|
|
20258
20411
|
await bunWrite(tempPath, content);
|
|
@@ -20780,10 +20933,10 @@ import { randomUUID as randomUUID7 } from "crypto";
|
|
|
20780
20933
|
import { existsSync as existsSync27, readFileSync as readFileSync15 } from "fs";
|
|
20781
20934
|
import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
|
|
20782
20935
|
import * as os7 from "os";
|
|
20783
|
-
import * as
|
|
20936
|
+
import * as path41 from "path";
|
|
20784
20937
|
async function migrateKnowledgeToExternal(_directory, _config) {
|
|
20785
|
-
const externalSentinelPath =
|
|
20786
|
-
const contextPath =
|
|
20938
|
+
const externalSentinelPath = path41.join(_directory, ".swarm", ".knowledge-external-migrated");
|
|
20939
|
+
const contextPath = path41.join(_directory, ".swarm", "context.md");
|
|
20787
20940
|
if (_internals28.existsSync(externalSentinelPath)) {
|
|
20788
20941
|
return {
|
|
20789
20942
|
migrated: false,
|
|
@@ -20848,8 +21001,8 @@ var _internals28 = {
|
|
|
20848
21001
|
writeFile: writeFile12
|
|
20849
21002
|
};
|
|
20850
21003
|
async function migrateContextToKnowledge(directory, config) {
|
|
20851
|
-
const sentinelPath =
|
|
20852
|
-
const contextPath =
|
|
21004
|
+
const sentinelPath = path41.join(directory, ".swarm", ".knowledge-migrated");
|
|
21005
|
+
const contextPath = path41.join(directory, ".swarm", "context.md");
|
|
20853
21006
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
20854
21007
|
if (existsSync27(sentinelPath)) {
|
|
20855
21008
|
return {
|
|
@@ -20951,7 +21104,7 @@ async function migrateContextToKnowledge(directory, config) {
|
|
|
20951
21104
|
async function migrateHiveKnowledgeLegacy(config) {
|
|
20952
21105
|
const legacyHivePath = _internals28.resolveLegacyHiveKnowledgePath();
|
|
20953
21106
|
const canonicalHivePath = resolveHiveKnowledgePath();
|
|
20954
|
-
const sentinelPath =
|
|
21107
|
+
const sentinelPath = path41.join(path41.dirname(canonicalHivePath), ".hive-knowledge-migrated");
|
|
20955
21108
|
if (existsSync27(sentinelPath)) {
|
|
20956
21109
|
return {
|
|
20957
21110
|
migrated: false,
|
|
@@ -21162,7 +21315,7 @@ function truncateLesson2(text) {
|
|
|
21162
21315
|
return `${text.slice(0, 277)}...`;
|
|
21163
21316
|
}
|
|
21164
21317
|
function inferProjectName(directory) {
|
|
21165
|
-
const packageJsonPath =
|
|
21318
|
+
const packageJsonPath = path41.join(directory, "package.json");
|
|
21166
21319
|
if (existsSync27(packageJsonPath)) {
|
|
21167
21320
|
try {
|
|
21168
21321
|
const pkg = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
|
|
@@ -21171,7 +21324,7 @@ function inferProjectName(directory) {
|
|
|
21171
21324
|
}
|
|
21172
21325
|
} catch {}
|
|
21173
21326
|
}
|
|
21174
|
-
return
|
|
21327
|
+
return path41.basename(directory);
|
|
21175
21328
|
}
|
|
21176
21329
|
async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
21177
21330
|
const sentinel = {
|
|
@@ -21183,7 +21336,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
|
|
|
21183
21336
|
schema_version: 1,
|
|
21184
21337
|
migration_tool: "knowledge-migrator.ts"
|
|
21185
21338
|
};
|
|
21186
|
-
await _internals28.mkdir(
|
|
21339
|
+
await _internals28.mkdir(path41.dirname(sentinelPath), { recursive: true });
|
|
21187
21340
|
await _internals28.writeFile(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
|
|
21188
21341
|
}
|
|
21189
21342
|
function resolveLegacyHiveKnowledgePath() {
|
|
@@ -21191,13 +21344,13 @@ function resolveLegacyHiveKnowledgePath() {
|
|
|
21191
21344
|
const home = process.env.HOME || os7.homedir();
|
|
21192
21345
|
let dataDir;
|
|
21193
21346
|
if (platform === "win32") {
|
|
21194
|
-
dataDir =
|
|
21347
|
+
dataDir = path41.join(process.env.LOCALAPPDATA || path41.join(home, "AppData", "Local"), "opencode-swarm", "Data");
|
|
21195
21348
|
} else if (platform === "darwin") {
|
|
21196
|
-
dataDir =
|
|
21349
|
+
dataDir = path41.join(home, "Library", "Application Support", "opencode-swarm");
|
|
21197
21350
|
} else {
|
|
21198
|
-
dataDir =
|
|
21351
|
+
dataDir = path41.join(process.env.XDG_DATA_HOME || path41.join(home, ".local", "share"), "opencode-swarm");
|
|
21199
21352
|
}
|
|
21200
|
-
return
|
|
21353
|
+
return path41.join(dataDir, "hive-knowledge.jsonl");
|
|
21201
21354
|
}
|
|
21202
21355
|
|
|
21203
21356
|
// src/commands/knowledge.ts
|
|
@@ -21628,14 +21781,14 @@ var _internals29 = {
|
|
|
21628
21781
|
|
|
21629
21782
|
// src/commands/link.ts
|
|
21630
21783
|
import { existsSync as existsSync28 } from "fs";
|
|
21631
|
-
import * as
|
|
21784
|
+
import * as path43 from "path";
|
|
21632
21785
|
|
|
21633
21786
|
// src/knowledge/identity.ts
|
|
21634
21787
|
import * as child_process7 from "child_process";
|
|
21635
21788
|
import { createHash as createHash5 } from "crypto";
|
|
21636
|
-
import * as
|
|
21789
|
+
import * as path42 from "path";
|
|
21637
21790
|
function deriveProjectHash(directory) {
|
|
21638
|
-
const absolutePath =
|
|
21791
|
+
const absolutePath = path42.resolve(directory);
|
|
21639
21792
|
let hashInput;
|
|
21640
21793
|
try {
|
|
21641
21794
|
const remoteUrl = child_process7.execSync("git remote get-url origin", {
|
|
@@ -21655,8 +21808,8 @@ function deriveProjectHash(directory) {
|
|
|
21655
21808
|
// src/commands/link.ts
|
|
21656
21809
|
var DEDUP_THRESHOLD = 0.6;
|
|
21657
21810
|
async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
|
|
21658
|
-
const localPath =
|
|
21659
|
-
const sharedPath =
|
|
21811
|
+
const localPath = path43.join(localSwarmDir, "knowledge.jsonl");
|
|
21812
|
+
const sharedPath = path43.join(linkDir, "knowledge.jsonl");
|
|
21660
21813
|
if (!existsSync28(localPath))
|
|
21661
21814
|
return { merged: 0, skipped: 0 };
|
|
21662
21815
|
let merged = 0;
|
|
@@ -21754,7 +21907,7 @@ ${formatStatus(directory)}`;
|
|
|
21754
21907
|
const linkDir = resolveLinkDir(linkId);
|
|
21755
21908
|
let merge;
|
|
21756
21909
|
try {
|
|
21757
|
-
merge = await mergeLocalKnowledgeIntoLink(
|
|
21910
|
+
merge = await mergeLocalKnowledgeIntoLink(path43.join(directory, ".swarm"), linkDir);
|
|
21758
21911
|
} catch (error2) {
|
|
21759
21912
|
return `\u274C Failed to merge local knowledge into the link store: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
21760
21913
|
}
|
|
@@ -21951,12 +22104,12 @@ ${USAGE7}`;
|
|
|
21951
22104
|
|
|
21952
22105
|
// src/commands/memory.ts
|
|
21953
22106
|
import { existsSync as existsSync29 } from "fs";
|
|
21954
|
-
import * as
|
|
22107
|
+
import * as path46 from "path";
|
|
21955
22108
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
21956
22109
|
// src/memory/evaluation.ts
|
|
21957
22110
|
import * as fs15 from "fs/promises";
|
|
21958
22111
|
import * as os8 from "os";
|
|
21959
|
-
import * as
|
|
22112
|
+
import * as path44 from "path";
|
|
21960
22113
|
var DEFAULT_PROVIDERS = [
|
|
21961
22114
|
"local-jsonl",
|
|
21962
22115
|
"sqlite"
|
|
@@ -21968,7 +22121,7 @@ var DEFAULT_MODES = [
|
|
|
21968
22121
|
];
|
|
21969
22122
|
var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
|
|
21970
22123
|
async function evaluateMemoryRecallFixtures(options) {
|
|
21971
|
-
const fixtureDirectory =
|
|
22124
|
+
const fixtureDirectory = path44.resolve(options.fixtureDirectory);
|
|
21972
22125
|
const providers = options.providers ?? DEFAULT_PROVIDERS;
|
|
21973
22126
|
const modes = options.modes ?? DEFAULT_MODES;
|
|
21974
22127
|
const generatedAt = new Date().toISOString();
|
|
@@ -21977,7 +22130,7 @@ async function evaluateMemoryRecallFixtures(options) {
|
|
|
21977
22130
|
for (const fixture of fixtures) {
|
|
21978
22131
|
const materialized = materializeFixture(fixture);
|
|
21979
22132
|
for (const providerName of providers) {
|
|
21980
|
-
const tempRoot = await fs15.realpath(await fs15.mkdtemp(
|
|
22133
|
+
const tempRoot = await fs15.realpath(await fs15.mkdtemp(path44.join(os8.tmpdir(), "swarm-memory-eval-")));
|
|
21981
22134
|
const provider = createEvaluationProvider(providerName, tempRoot);
|
|
21982
22135
|
try {
|
|
21983
22136
|
await provider.initialize?.();
|
|
@@ -22034,7 +22187,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
|
|
|
22034
22187
|
const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
|
|
22035
22188
|
const fixtures = [];
|
|
22036
22189
|
for (const file of files) {
|
|
22037
|
-
const raw = await fs15.readFile(
|
|
22190
|
+
const raw = await fs15.readFile(path44.join(fixtureDirectory, file), "utf-8");
|
|
22038
22191
|
fixtures.push(validateFixture(JSON.parse(raw), file));
|
|
22039
22192
|
}
|
|
22040
22193
|
return fixtures;
|
|
@@ -22311,8 +22464,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
|
|
|
22311
22464
|
}).passthrough();
|
|
22312
22465
|
// src/memory/consolidation-log.ts
|
|
22313
22466
|
import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
|
|
22314
|
-
import * as
|
|
22315
|
-
var LOG_RELATIVE_PATH =
|
|
22467
|
+
import * as path45 from "path";
|
|
22468
|
+
var LOG_RELATIVE_PATH = path45.join("memory", "consolidation-log.jsonl");
|
|
22316
22469
|
async function readConsolidationLog(directory) {
|
|
22317
22470
|
const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
|
|
22318
22471
|
let raw;
|
|
@@ -22335,7 +22488,7 @@ async function readConsolidationLog(directory) {
|
|
|
22335
22488
|
}
|
|
22336
22489
|
|
|
22337
22490
|
// src/commands/memory.ts
|
|
22338
|
-
var PACKAGE_ROOT =
|
|
22491
|
+
var PACKAGE_ROOT = path46.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
|
|
22339
22492
|
async function handleMemoryCommand(_directory, _args) {
|
|
22340
22493
|
return [
|
|
22341
22494
|
"## Swarm Memory",
|
|
@@ -22692,7 +22845,7 @@ function resolveCommandMemoryConfig(directory) {
|
|
|
22692
22845
|
}
|
|
22693
22846
|
function parseEvaluateArgs(directory, args) {
|
|
22694
22847
|
let json = false;
|
|
22695
|
-
let fixtureDirectory =
|
|
22848
|
+
let fixtureDirectory = path46.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
|
|
22696
22849
|
for (let i = 0;i < args.length; i++) {
|
|
22697
22850
|
const arg = args[i];
|
|
22698
22851
|
if (arg === "--json") {
|
|
@@ -22706,10 +22859,10 @@ function parseEvaluateArgs(directory, args) {
|
|
|
22706
22859
|
error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
|
|
22707
22860
|
};
|
|
22708
22861
|
}
|
|
22709
|
-
const resolvedFixtures =
|
|
22710
|
-
const canonical =
|
|
22711
|
-
const allowedRootA =
|
|
22712
|
-
const allowedRootB =
|
|
22862
|
+
const resolvedFixtures = path46.resolve(directory, next);
|
|
22863
|
+
const canonical = path46.normalize(resolvedFixtures) + path46.sep;
|
|
22864
|
+
const allowedRootA = path46.normalize(directory) + path46.sep;
|
|
22865
|
+
const allowedRootB = path46.normalize(path46.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path46.sep;
|
|
22713
22866
|
if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
|
|
22714
22867
|
return {
|
|
22715
22868
|
error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
|
|
@@ -22748,15 +22901,15 @@ function parseMaintenanceArgs(args, options) {
|
|
|
22748
22901
|
return { limit, confirm };
|
|
22749
22902
|
}
|
|
22750
22903
|
function resolvePackageRootFromModule(modulePath) {
|
|
22751
|
-
const moduleDir =
|
|
22752
|
-
const leaf =
|
|
22904
|
+
const moduleDir = path46.dirname(modulePath);
|
|
22905
|
+
const leaf = path46.basename(moduleDir);
|
|
22753
22906
|
if (leaf === "commands" || leaf === "cli") {
|
|
22754
|
-
return
|
|
22907
|
+
return path46.resolve(moduleDir, "..", "..");
|
|
22755
22908
|
}
|
|
22756
22909
|
if (leaf === "dist") {
|
|
22757
|
-
return
|
|
22910
|
+
return path46.resolve(moduleDir, "..");
|
|
22758
22911
|
}
|
|
22759
|
-
return
|
|
22912
|
+
return path46.resolve(moduleDir, "..");
|
|
22760
22913
|
}
|
|
22761
22914
|
function formatMigrationResult(label, report) {
|
|
22762
22915
|
if (!report) {
|
|
@@ -23491,11 +23644,11 @@ var _internals35 = {
|
|
|
23491
23644
|
|
|
23492
23645
|
// src/services/preflight-service.ts
|
|
23493
23646
|
import * as fs22 from "fs";
|
|
23494
|
-
import * as
|
|
23647
|
+
import * as path53 from "path";
|
|
23495
23648
|
|
|
23496
23649
|
// src/tools/lint.ts
|
|
23497
23650
|
import * as fs16 from "fs";
|
|
23498
|
-
import * as
|
|
23651
|
+
import * as path47 from "path";
|
|
23499
23652
|
|
|
23500
23653
|
// src/utils/path-security.ts
|
|
23501
23654
|
function containsPathTraversal(str) {
|
|
@@ -23551,9 +23704,9 @@ function validateArgs(args) {
|
|
|
23551
23704
|
}
|
|
23552
23705
|
function getLinterCommand(linter, mode, projectDir) {
|
|
23553
23706
|
const isWindows = process.platform === "win32";
|
|
23554
|
-
const binDir =
|
|
23555
|
-
const biomeBin = isWindows ?
|
|
23556
|
-
const eslintBin = isWindows ?
|
|
23707
|
+
const binDir = path47.join(projectDir, "node_modules", ".bin");
|
|
23708
|
+
const biomeBin = isWindows ? path47.join(binDir, "biome.EXE") : path47.join(binDir, "biome");
|
|
23709
|
+
const eslintBin = isWindows ? path47.join(binDir, "eslint.cmd") : path47.join(binDir, "eslint");
|
|
23557
23710
|
switch (linter) {
|
|
23558
23711
|
case "biome":
|
|
23559
23712
|
if (mode === "fix") {
|
|
@@ -23569,7 +23722,7 @@ function getLinterCommand(linter, mode, projectDir) {
|
|
|
23569
23722
|
}
|
|
23570
23723
|
function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
23571
23724
|
const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
|
|
23572
|
-
const gradlew = fs16.existsSync(
|
|
23725
|
+
const gradlew = fs16.existsSync(path47.join(cwd, gradlewName)) ? path47.join(cwd, gradlewName) : null;
|
|
23573
23726
|
switch (linter) {
|
|
23574
23727
|
case "ruff":
|
|
23575
23728
|
return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
|
|
@@ -23611,10 +23764,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
|
|
|
23611
23764
|
}
|
|
23612
23765
|
}
|
|
23613
23766
|
function detectRuff(cwd) {
|
|
23614
|
-
if (fs16.existsSync(
|
|
23767
|
+
if (fs16.existsSync(path47.join(cwd, "ruff.toml")))
|
|
23615
23768
|
return isCommandAvailable("ruff");
|
|
23616
23769
|
try {
|
|
23617
|
-
const pyproject =
|
|
23770
|
+
const pyproject = path47.join(cwd, "pyproject.toml");
|
|
23618
23771
|
if (fs16.existsSync(pyproject)) {
|
|
23619
23772
|
const content = fs16.readFileSync(pyproject, "utf-8");
|
|
23620
23773
|
if (content.includes("[tool.ruff]"))
|
|
@@ -23624,10 +23777,10 @@ function detectRuff(cwd) {
|
|
|
23624
23777
|
return false;
|
|
23625
23778
|
}
|
|
23626
23779
|
function detectClippy(cwd) {
|
|
23627
|
-
return fs16.existsSync(
|
|
23780
|
+
return fs16.existsSync(path47.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
|
|
23628
23781
|
}
|
|
23629
23782
|
function detectGolangciLint(cwd) {
|
|
23630
|
-
return fs16.existsSync(
|
|
23783
|
+
return fs16.existsSync(path47.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
|
|
23631
23784
|
}
|
|
23632
23785
|
function readTextFileSafe(filePath) {
|
|
23633
23786
|
try {
|
|
@@ -23638,18 +23791,18 @@ function readTextFileSafe(filePath) {
|
|
|
23638
23791
|
}
|
|
23639
23792
|
function phpVendorBin(_cwd, name) {
|
|
23640
23793
|
const fileName = process.platform === "win32" ? `${name}.bat` : name;
|
|
23641
|
-
return
|
|
23794
|
+
return path47.join("vendor", "bin", fileName);
|
|
23642
23795
|
}
|
|
23643
23796
|
function phpVendorBinExists(cwd, name) {
|
|
23644
|
-
const local =
|
|
23645
|
-
const localWin =
|
|
23797
|
+
const local = path47.join(cwd, "vendor", "bin", name);
|
|
23798
|
+
const localWin = path47.join(cwd, "vendor", "bin", `${name}.bat`);
|
|
23646
23799
|
return fs16.existsSync(local) || fs16.existsSync(localWin);
|
|
23647
23800
|
}
|
|
23648
23801
|
function detectCheckstyle(cwd) {
|
|
23649
|
-
const hasMaven = fs16.existsSync(
|
|
23650
|
-
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) =>
|
|
23651
|
-
const hasGradleCheckstyleSignal = fs16.existsSync(
|
|
23652
|
-
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs16.existsSync(
|
|
23802
|
+
const hasMaven = fs16.existsSync(path47.join(cwd, "pom.xml"));
|
|
23803
|
+
const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path47.join(cwd, file)).filter((file) => fs16.existsSync(file));
|
|
23804
|
+
const hasGradleCheckstyleSignal = fs16.existsSync(path47.join(cwd, "checkstyle.xml")) || fs16.existsSync(path47.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
|
|
23805
|
+
const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs16.existsSync(path47.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
|
|
23653
23806
|
return (hasMaven || hasGradleCheckstyleSignal) && hasBinary;
|
|
23654
23807
|
}
|
|
23655
23808
|
function hasRootKotlinFile(cwd) {
|
|
@@ -23660,24 +23813,24 @@ function hasRootKotlinFile(cwd) {
|
|
|
23660
23813
|
}
|
|
23661
23814
|
}
|
|
23662
23815
|
function buildGradleHasKotlinSignal(cwd) {
|
|
23663
|
-
const content = readTextFileSafe(
|
|
23816
|
+
const content = readTextFileSafe(path47.join(cwd, "build.gradle"));
|
|
23664
23817
|
return /\b(kotlin|org\.jetbrains\.kotlin|ktlint)\b/i.test(content);
|
|
23665
23818
|
}
|
|
23666
23819
|
function detectKtlint(cwd) {
|
|
23667
|
-
const hasKotlin = fs16.existsSync(
|
|
23820
|
+
const hasKotlin = fs16.existsSync(path47.join(cwd, "build.gradle.kts")) || fs16.existsSync(path47.join(cwd, "build.gradle")) && buildGradleHasKotlinSignal(cwd) || hasRootKotlinFile(cwd);
|
|
23668
23821
|
return hasKotlin && isCommandAvailable("ktlint");
|
|
23669
23822
|
}
|
|
23670
23823
|
function detectPhpLinter(cwd) {
|
|
23671
|
-
if ((fs16.existsSync(
|
|
23824
|
+
if ((fs16.existsSync(path47.join(cwd, "phpstan.neon")) || fs16.existsSync(path47.join(cwd, "phpstan.neon.dist"))) && phpVendorBinExists(cwd, "phpstan")) {
|
|
23672
23825
|
return "phpstan";
|
|
23673
23826
|
}
|
|
23674
|
-
if (fs16.existsSync(
|
|
23827
|
+
if (fs16.existsSync(path47.join(cwd, "pint.json")) && phpVendorBinExists(cwd, "pint")) {
|
|
23675
23828
|
return "pint";
|
|
23676
23829
|
}
|
|
23677
|
-
if (fs16.existsSync(
|
|
23830
|
+
if (fs16.existsSync(path47.join(cwd, ".php-cs-fixer.php")) && phpVendorBinExists(cwd, "php-cs-fixer")) {
|
|
23678
23831
|
return "php-cs-fixer";
|
|
23679
23832
|
}
|
|
23680
|
-
if (fs16.existsSync(
|
|
23833
|
+
if (fs16.existsSync(path47.join(cwd, "phpcs.xml")) && phpVendorBinExists(cwd, "phpcs")) {
|
|
23681
23834
|
return "phpcs";
|
|
23682
23835
|
}
|
|
23683
23836
|
return null;
|
|
@@ -23692,11 +23845,11 @@ function detectDotnetFormat(cwd) {
|
|
|
23692
23845
|
}
|
|
23693
23846
|
}
|
|
23694
23847
|
function detectCppcheck(cwd) {
|
|
23695
|
-
if (fs16.existsSync(
|
|
23848
|
+
if (fs16.existsSync(path47.join(cwd, "CMakeLists.txt"))) {
|
|
23696
23849
|
return isCommandAvailable("cppcheck");
|
|
23697
23850
|
}
|
|
23698
23851
|
try {
|
|
23699
|
-
const dirsToCheck = [cwd,
|
|
23852
|
+
const dirsToCheck = [cwd, path47.join(cwd, "src")];
|
|
23700
23853
|
const hasCpp = dirsToCheck.some((dir) => {
|
|
23701
23854
|
try {
|
|
23702
23855
|
return fs16.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
|
|
@@ -23710,13 +23863,13 @@ function detectCppcheck(cwd) {
|
|
|
23710
23863
|
}
|
|
23711
23864
|
}
|
|
23712
23865
|
function detectSwiftlint(cwd) {
|
|
23713
|
-
return fs16.existsSync(
|
|
23866
|
+
return fs16.existsSync(path47.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
|
|
23714
23867
|
}
|
|
23715
23868
|
function detectDartAnalyze(cwd) {
|
|
23716
|
-
return fs16.existsSync(
|
|
23869
|
+
return fs16.existsSync(path47.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
23717
23870
|
}
|
|
23718
23871
|
function detectRubocop(cwd) {
|
|
23719
|
-
return (fs16.existsSync(
|
|
23872
|
+
return (fs16.existsSync(path47.join(cwd, "Gemfile")) || fs16.existsSync(path47.join(cwd, "gems.rb")) || fs16.existsSync(path47.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
|
|
23720
23873
|
}
|
|
23721
23874
|
function detectAdditionalLinter(cwd) {
|
|
23722
23875
|
if (detectRuff(cwd))
|
|
@@ -23747,10 +23900,10 @@ function detectAdditionalLinter(cwd) {
|
|
|
23747
23900
|
function findBinInAncestors(startDir, binName) {
|
|
23748
23901
|
let dir = startDir;
|
|
23749
23902
|
while (true) {
|
|
23750
|
-
const candidate =
|
|
23903
|
+
const candidate = path47.join(dir, "node_modules", ".bin", binName);
|
|
23751
23904
|
if (fs16.existsSync(candidate))
|
|
23752
23905
|
return candidate;
|
|
23753
|
-
const parent =
|
|
23906
|
+
const parent = path47.dirname(dir);
|
|
23754
23907
|
if (parent === dir)
|
|
23755
23908
|
break;
|
|
23756
23909
|
dir = parent;
|
|
@@ -23759,10 +23912,10 @@ function findBinInAncestors(startDir, binName) {
|
|
|
23759
23912
|
}
|
|
23760
23913
|
function findBinInEnvPath(binName) {
|
|
23761
23914
|
const searchPath = process.env.PATH ?? "";
|
|
23762
|
-
for (const dir of searchPath.split(
|
|
23915
|
+
for (const dir of searchPath.split(path47.delimiter)) {
|
|
23763
23916
|
if (!dir)
|
|
23764
23917
|
continue;
|
|
23765
|
-
const candidate =
|
|
23918
|
+
const candidate = path47.join(dir, binName);
|
|
23766
23919
|
if (fs16.existsSync(candidate))
|
|
23767
23920
|
return candidate;
|
|
23768
23921
|
}
|
|
@@ -23775,13 +23928,13 @@ async function detectAvailableLinter(directory) {
|
|
|
23775
23928
|
return null;
|
|
23776
23929
|
const projectDir = directory;
|
|
23777
23930
|
const isWindows = process.platform === "win32";
|
|
23778
|
-
const biomeBin = isWindows ?
|
|
23779
|
-
const eslintBin = isWindows ?
|
|
23931
|
+
const biomeBin = isWindows ? path47.join(projectDir, "node_modules", ".bin", "biome.EXE") : path47.join(projectDir, "node_modules", ".bin", "biome");
|
|
23932
|
+
const eslintBin = isWindows ? path47.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path47.join(projectDir, "node_modules", ".bin", "eslint");
|
|
23780
23933
|
const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
|
|
23781
23934
|
if (localResult)
|
|
23782
23935
|
return localResult;
|
|
23783
|
-
const biomeAncestor = findBinInAncestors(
|
|
23784
|
-
const eslintAncestor = findBinInAncestors(
|
|
23936
|
+
const biomeAncestor = findBinInAncestors(path47.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
|
|
23937
|
+
const eslintAncestor = findBinInAncestors(path47.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
|
|
23785
23938
|
if (biomeAncestor || eslintAncestor) {
|
|
23786
23939
|
return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
|
|
23787
23940
|
}
|
|
@@ -23995,7 +24148,7 @@ var _internals36 = {
|
|
|
23995
24148
|
|
|
23996
24149
|
// src/tools/secretscan.ts
|
|
23997
24150
|
import * as fs17 from "fs";
|
|
23998
|
-
import * as
|
|
24151
|
+
import * as path48 from "path";
|
|
23999
24152
|
var MAX_FILE_PATH_LENGTH = 500;
|
|
24000
24153
|
var MAX_FILE_SIZE_BYTES = 512 * 1024;
|
|
24001
24154
|
var MAX_FILES_SCANNED = 1000;
|
|
@@ -24222,7 +24375,7 @@ function isGlobOrPathPattern(pattern) {
|
|
|
24222
24375
|
return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
|
|
24223
24376
|
}
|
|
24224
24377
|
function loadSecretScanIgnore(scanDir) {
|
|
24225
|
-
const ignorePath =
|
|
24378
|
+
const ignorePath = path48.join(scanDir, ".secretscanignore");
|
|
24226
24379
|
try {
|
|
24227
24380
|
if (!fs17.existsSync(ignorePath))
|
|
24228
24381
|
return [];
|
|
@@ -24245,7 +24398,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
|
|
|
24245
24398
|
if (exactNames.has(entry))
|
|
24246
24399
|
return true;
|
|
24247
24400
|
for (const pattern of globPatterns) {
|
|
24248
|
-
if (
|
|
24401
|
+
if (path48.matchesGlob(relPath, pattern))
|
|
24249
24402
|
return true;
|
|
24250
24403
|
}
|
|
24251
24404
|
return false;
|
|
@@ -24266,7 +24419,7 @@ function validateDirectoryInput(dir) {
|
|
|
24266
24419
|
return null;
|
|
24267
24420
|
}
|
|
24268
24421
|
function isBinaryFile(filePath, buffer) {
|
|
24269
|
-
const ext =
|
|
24422
|
+
const ext = path48.extname(filePath).toLowerCase();
|
|
24270
24423
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24271
24424
|
return true;
|
|
24272
24425
|
}
|
|
@@ -24403,9 +24556,9 @@ function isSymlinkLoop(realPath, visited) {
|
|
|
24403
24556
|
return false;
|
|
24404
24557
|
}
|
|
24405
24558
|
function isPathWithinScope(realPath, scanDir) {
|
|
24406
|
-
const resolvedScanDir =
|
|
24407
|
-
const resolvedRealPath =
|
|
24408
|
-
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir +
|
|
24559
|
+
const resolvedScanDir = path48.resolve(scanDir);
|
|
24560
|
+
const resolvedRealPath = path48.resolve(realPath);
|
|
24561
|
+
return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path48.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
|
|
24409
24562
|
}
|
|
24410
24563
|
function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
|
|
24411
24564
|
skippedDirs: 0,
|
|
@@ -24431,8 +24584,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24431
24584
|
return a.localeCompare(b);
|
|
24432
24585
|
});
|
|
24433
24586
|
for (const entry of entries) {
|
|
24434
|
-
const fullPath =
|
|
24435
|
-
const relPath =
|
|
24587
|
+
const fullPath = path48.join(dir, entry);
|
|
24588
|
+
const relPath = path48.relative(scanDir, fullPath).replace(/\\/g, "/");
|
|
24436
24589
|
if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
|
|
24437
24590
|
stats.skippedDirs++;
|
|
24438
24591
|
continue;
|
|
@@ -24467,7 +24620,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
|
|
|
24467
24620
|
const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
|
|
24468
24621
|
files.push(...subFiles);
|
|
24469
24622
|
} else if (lstat2.isFile()) {
|
|
24470
|
-
const ext =
|
|
24623
|
+
const ext = path48.extname(fullPath).toLowerCase();
|
|
24471
24624
|
if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24472
24625
|
files.push(fullPath);
|
|
24473
24626
|
} else {
|
|
@@ -24533,7 +24686,7 @@ var secretscan = createSwarmTool({
|
|
|
24533
24686
|
}
|
|
24534
24687
|
}
|
|
24535
24688
|
try {
|
|
24536
|
-
const _scanDirRaw =
|
|
24689
|
+
const _scanDirRaw = path48.resolve(directory);
|
|
24537
24690
|
const scanDir = (() => {
|
|
24538
24691
|
try {
|
|
24539
24692
|
return fs17.realpathSync(_scanDirRaw);
|
|
@@ -24699,12 +24852,12 @@ async function runSecretscanOnFiles(files, directory) {
|
|
|
24699
24852
|
skippedFiles++;
|
|
24700
24853
|
continue;
|
|
24701
24854
|
}
|
|
24702
|
-
const resolvedPath =
|
|
24855
|
+
const resolvedPath = path48.isAbsolute(file) ? path48.resolve(file) : path48.resolve(directory, file);
|
|
24703
24856
|
if (!isPathWithinScope(resolvedPath, directory)) {
|
|
24704
24857
|
skippedFiles++;
|
|
24705
24858
|
continue;
|
|
24706
24859
|
}
|
|
24707
|
-
const ext =
|
|
24860
|
+
const ext = path48.extname(resolvedPath).toLowerCase();
|
|
24708
24861
|
if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
|
|
24709
24862
|
skippedFiles++;
|
|
24710
24863
|
continue;
|
|
@@ -24755,11 +24908,11 @@ var _internals37 = {
|
|
|
24755
24908
|
|
|
24756
24909
|
// src/tools/test-runner.ts
|
|
24757
24910
|
import * as fs21 from "fs";
|
|
24758
|
-
import * as
|
|
24911
|
+
import * as path52 from "path";
|
|
24759
24912
|
|
|
24760
24913
|
// src/test-impact/analyzer.ts
|
|
24761
24914
|
import fs18 from "fs";
|
|
24762
|
-
import
|
|
24915
|
+
import path49 from "path";
|
|
24763
24916
|
var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
24764
24917
|
var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
|
|
24765
24918
|
var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
|
|
@@ -24800,8 +24953,8 @@ function resolveRelativeImport(fromDir, importPath) {
|
|
|
24800
24953
|
if (!importPath.startsWith(".")) {
|
|
24801
24954
|
return null;
|
|
24802
24955
|
}
|
|
24803
|
-
const resolved =
|
|
24804
|
-
if (
|
|
24956
|
+
const resolved = path49.resolve(fromDir, importPath);
|
|
24957
|
+
if (path49.extname(resolved)) {
|
|
24805
24958
|
if (fs18.existsSync(resolved) && fs18.statSync(resolved).isFile()) {
|
|
24806
24959
|
return normalizePath2(resolved);
|
|
24807
24960
|
}
|
|
@@ -24821,20 +24974,20 @@ function resolvePythonImport(fromDir, module) {
|
|
|
24821
24974
|
const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
|
|
24822
24975
|
let baseDir = fromDir;
|
|
24823
24976
|
for (let i = 1;i < leadingDots; i++) {
|
|
24824
|
-
baseDir =
|
|
24977
|
+
baseDir = path49.dirname(baseDir);
|
|
24825
24978
|
}
|
|
24826
24979
|
const rest = module.slice(leadingDots);
|
|
24827
24980
|
if (rest.length === 0) {
|
|
24828
|
-
const initPath =
|
|
24981
|
+
const initPath = path49.join(baseDir, "__init__.py");
|
|
24829
24982
|
if (fs18.existsSync(initPath) && fs18.statSync(initPath).isFile()) {
|
|
24830
24983
|
return normalizePath2(initPath);
|
|
24831
24984
|
}
|
|
24832
24985
|
return null;
|
|
24833
24986
|
}
|
|
24834
|
-
const subpath = rest.replace(/\./g,
|
|
24987
|
+
const subpath = rest.replace(/\./g, path49.sep);
|
|
24835
24988
|
const candidates = [
|
|
24836
|
-
`${
|
|
24837
|
-
|
|
24989
|
+
`${path49.join(baseDir, subpath)}.py`,
|
|
24990
|
+
path49.join(baseDir, subpath, "__init__.py")
|
|
24838
24991
|
];
|
|
24839
24992
|
for (const c of candidates) {
|
|
24840
24993
|
if (fs18.existsSync(c) && fs18.statSync(c).isFile())
|
|
@@ -24844,7 +24997,7 @@ function resolvePythonImport(fromDir, module) {
|
|
|
24844
24997
|
}
|
|
24845
24998
|
var goModuleCache = new Map;
|
|
24846
24999
|
function findGoModule(fromDir) {
|
|
24847
|
-
const resolved =
|
|
25000
|
+
const resolved = path49.resolve(fromDir);
|
|
24848
25001
|
let cur = resolved;
|
|
24849
25002
|
const walked = [];
|
|
24850
25003
|
for (let i = 0;i < 16; i++) {
|
|
@@ -24856,7 +25009,7 @@ function findGoModule(fromDir) {
|
|
|
24856
25009
|
}
|
|
24857
25010
|
walked.push(cur);
|
|
24858
25011
|
try {
|
|
24859
|
-
const goMod =
|
|
25012
|
+
const goMod = path49.join(cur, "go.mod");
|
|
24860
25013
|
const content = fs18.readFileSync(goMod, "utf-8");
|
|
24861
25014
|
const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
|
|
24862
25015
|
if (moduleMatch) {
|
|
@@ -24867,10 +25020,10 @@ function findGoModule(fromDir) {
|
|
|
24867
25020
|
}
|
|
24868
25021
|
} catch {}
|
|
24869
25022
|
try {
|
|
24870
|
-
fs18.accessSync(
|
|
25023
|
+
fs18.accessSync(path49.join(cur, ".git"));
|
|
24871
25024
|
break;
|
|
24872
25025
|
} catch {}
|
|
24873
|
-
const parent =
|
|
25026
|
+
const parent = path49.dirname(cur);
|
|
24874
25027
|
if (parent === cur)
|
|
24875
25028
|
break;
|
|
24876
25029
|
cur = parent;
|
|
@@ -24882,12 +25035,12 @@ function findGoModule(fromDir) {
|
|
|
24882
25035
|
function resolveGoImport(fromDir, importPath) {
|
|
24883
25036
|
let dir = null;
|
|
24884
25037
|
if (importPath.startsWith(".")) {
|
|
24885
|
-
dir =
|
|
25038
|
+
dir = path49.resolve(fromDir, importPath);
|
|
24886
25039
|
} else {
|
|
24887
25040
|
const mod = findGoModule(fromDir);
|
|
24888
25041
|
if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
|
|
24889
25042
|
const subpath = importPath.slice(mod.modulePath.length);
|
|
24890
|
-
dir =
|
|
25043
|
+
dir = path49.join(mod.moduleRoot, subpath);
|
|
24891
25044
|
}
|
|
24892
25045
|
}
|
|
24893
25046
|
if (dir === null)
|
|
@@ -24895,7 +25048,7 @@ function resolveGoImport(fromDir, importPath) {
|
|
|
24895
25048
|
if (!fs18.existsSync(dir) || !fs18.statSync(dir).isDirectory())
|
|
24896
25049
|
return [];
|
|
24897
25050
|
try {
|
|
24898
|
-
return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(
|
|
25051
|
+
return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path49.join(dir, f)));
|
|
24899
25052
|
} catch {
|
|
24900
25053
|
return [];
|
|
24901
25054
|
}
|
|
@@ -24934,15 +25087,15 @@ function findTestFilesSync(cwd) {
|
|
|
24934
25087
|
for (const entry of entries) {
|
|
24935
25088
|
if (entry.isDirectory()) {
|
|
24936
25089
|
if (!skipDirs.has(entry.name)) {
|
|
24937
|
-
walk(
|
|
25090
|
+
walk(path49.join(dir, entry.name), visitedInodes);
|
|
24938
25091
|
}
|
|
24939
25092
|
} else if (entry.isFile()) {
|
|
24940
25093
|
const name = entry.name;
|
|
24941
25094
|
const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
|
|
24942
|
-
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${
|
|
25095
|
+
const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path49.sep}tests${path49.sep}`) && name.endsWith(".py");
|
|
24943
25096
|
const isGoTest = /.+_test\.go$/.test(name);
|
|
24944
25097
|
if (isTsTest || isPyTest || isGoTest) {
|
|
24945
|
-
testFiles.push(normalizePath2(
|
|
25098
|
+
testFiles.push(normalizePath2(path49.join(dir, entry.name)));
|
|
24946
25099
|
}
|
|
24947
25100
|
}
|
|
24948
25101
|
}
|
|
@@ -24967,8 +25120,8 @@ function extractImports(content) {
|
|
|
24967
25120
|
];
|
|
24968
25121
|
}
|
|
24969
25122
|
function addImpactEdgesForTestFile(testFile, content, impactMap) {
|
|
24970
|
-
const ext =
|
|
24971
|
-
const testDir =
|
|
25123
|
+
const ext = path49.extname(testFile).toLowerCase();
|
|
25124
|
+
const testDir = path49.dirname(testFile);
|
|
24972
25125
|
function addEdge(source) {
|
|
24973
25126
|
if (!impactMap[source])
|
|
24974
25127
|
impactMap[source] = [];
|
|
@@ -25042,7 +25195,7 @@ async function buildImpactMap(cwd) {
|
|
|
25042
25195
|
return impactMap;
|
|
25043
25196
|
}
|
|
25044
25197
|
async function loadImpactMap(cwd, options) {
|
|
25045
|
-
const cachePath =
|
|
25198
|
+
const cachePath = path49.join(cwd, ".swarm", "cache", "impact-map.json");
|
|
25046
25199
|
if (fs18.existsSync(cachePath)) {
|
|
25047
25200
|
try {
|
|
25048
25201
|
const content = fs18.readFileSync(cachePath, "utf-8");
|
|
@@ -25075,12 +25228,12 @@ async function loadImpactMap(cwd, options) {
|
|
|
25075
25228
|
return _internals38.buildImpactMap(cwd);
|
|
25076
25229
|
}
|
|
25077
25230
|
async function saveImpactMap(cwd, impactMap) {
|
|
25078
|
-
if (!
|
|
25231
|
+
if (!path49.isAbsolute(cwd)) {
|
|
25079
25232
|
throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
|
|
25080
25233
|
}
|
|
25081
25234
|
_internals38.validateProjectRoot(cwd);
|
|
25082
|
-
const cacheDir2 =
|
|
25083
|
-
const cachePath =
|
|
25235
|
+
const cacheDir2 = path49.join(cwd, ".swarm", "cache");
|
|
25236
|
+
const cachePath = path49.join(cacheDir2, "impact-map.json");
|
|
25084
25237
|
if (!fs18.existsSync(cacheDir2)) {
|
|
25085
25238
|
fs18.mkdirSync(cacheDir2, { recursive: true });
|
|
25086
25239
|
}
|
|
@@ -25112,7 +25265,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25112
25265
|
budgetExceeded = true;
|
|
25113
25266
|
break;
|
|
25114
25267
|
}
|
|
25115
|
-
const normalizedChanged = normalizePath2(
|
|
25268
|
+
const normalizedChanged = normalizePath2(path49.resolve(changedFile));
|
|
25116
25269
|
const tests = impactMap[normalizedChanged];
|
|
25117
25270
|
if (tests && tests.length > 0) {
|
|
25118
25271
|
for (const test of tests) {
|
|
@@ -25126,13 +25279,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
|
|
|
25126
25279
|
if (budgetExceeded)
|
|
25127
25280
|
break;
|
|
25128
25281
|
} else {
|
|
25129
|
-
const changedDir = normalizePath2(
|
|
25130
|
-
const changedInputDir = normalizePath2(
|
|
25282
|
+
const changedDir = normalizePath2(path49.dirname(normalizedChanged));
|
|
25283
|
+
const changedInputDir = normalizePath2(path49.dirname(changedFile));
|
|
25131
25284
|
const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
|
|
25132
25285
|
return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
|
|
25133
25286
|
}).sort(([sourceA], [sourceB]) => {
|
|
25134
|
-
const sourceDirA = normalizePath2(
|
|
25135
|
-
const sourceDirB = normalizePath2(
|
|
25287
|
+
const sourceDirA = normalizePath2(path49.dirname(sourceA));
|
|
25288
|
+
const sourceDirB = normalizePath2(path49.dirname(sourceB));
|
|
25136
25289
|
const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
|
|
25137
25290
|
const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
|
|
25138
25291
|
if (exactA !== exactB)
|
|
@@ -25464,7 +25617,7 @@ function detectFlakyTests(allHistory) {
|
|
|
25464
25617
|
|
|
25465
25618
|
// src/test-impact/history-store.ts
|
|
25466
25619
|
import fs19 from "fs";
|
|
25467
|
-
import
|
|
25620
|
+
import path50 from "path";
|
|
25468
25621
|
var MAX_HISTORY_PER_TEST = 20;
|
|
25469
25622
|
var MAX_ERROR_LENGTH = 500;
|
|
25470
25623
|
var MAX_STACK_LENGTH = 200;
|
|
@@ -25476,10 +25629,10 @@ function getHistoryPath(workingDir) {
|
|
|
25476
25629
|
if (!workingDir) {
|
|
25477
25630
|
throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
|
|
25478
25631
|
}
|
|
25479
|
-
if (!
|
|
25632
|
+
if (!path50.isAbsolute(workingDir)) {
|
|
25480
25633
|
throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
|
|
25481
25634
|
}
|
|
25482
|
-
return
|
|
25635
|
+
return path50.join(workingDir, ".swarm", "cache", "test-history.jsonl");
|
|
25483
25636
|
}
|
|
25484
25637
|
function sanitizeErrorMessage(errorMessage) {
|
|
25485
25638
|
if (errorMessage === undefined) {
|
|
@@ -25571,7 +25724,7 @@ function batchAppendTestRuns(records, workingDir) {
|
|
|
25571
25724
|
}
|
|
25572
25725
|
}
|
|
25573
25726
|
const historyPath = getHistoryPath(workingDir);
|
|
25574
|
-
const historyDir =
|
|
25727
|
+
const historyDir = path50.dirname(historyPath);
|
|
25575
25728
|
_internals39.validateProjectRoot(workingDir);
|
|
25576
25729
|
if (!fs19.existsSync(historyDir)) {
|
|
25577
25730
|
fs19.mkdirSync(historyDir, { recursive: true });
|
|
@@ -25701,7 +25854,7 @@ var _internals39 = {
|
|
|
25701
25854
|
|
|
25702
25855
|
// src/tools/resolve-working-directory.ts
|
|
25703
25856
|
import * as fs20 from "fs";
|
|
25704
|
-
import * as
|
|
25857
|
+
import * as path51 from "path";
|
|
25705
25858
|
function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
25706
25859
|
if (workingDirectory == null || workingDirectory === "") {
|
|
25707
25860
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
@@ -25738,8 +25891,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
25738
25891
|
message: "Invalid working_directory: path traversal sequences (..) are not allowed"
|
|
25739
25892
|
};
|
|
25740
25893
|
}
|
|
25741
|
-
const normalizedDir =
|
|
25742
|
-
const resolvedDir =
|
|
25894
|
+
const normalizedDir = path51.normalize(workingDirectory);
|
|
25895
|
+
const resolvedDir = path51.resolve(normalizedDir);
|
|
25743
25896
|
let statResult;
|
|
25744
25897
|
try {
|
|
25745
25898
|
statResult = fs20.statSync(resolvedDir);
|
|
@@ -25758,7 +25911,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
25758
25911
|
if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
|
|
25759
25912
|
return { success: true, directory: resolvedDir };
|
|
25760
25913
|
}
|
|
25761
|
-
const resolvedFallback =
|
|
25914
|
+
const resolvedFallback = path51.resolve(fallbackDirectory);
|
|
25762
25915
|
let fallbackExists = false;
|
|
25763
25916
|
try {
|
|
25764
25917
|
fs20.statSync(resolvedFallback);
|
|
@@ -25767,7 +25920,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
|
|
|
25767
25920
|
fallbackExists = false;
|
|
25768
25921
|
}
|
|
25769
25922
|
if (fallbackExists) {
|
|
25770
|
-
const isSubdirectory = resolvedDir.startsWith(resolvedFallback +
|
|
25923
|
+
const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path51.sep);
|
|
25771
25924
|
if (isSubdirectory) {
|
|
25772
25925
|
return {
|
|
25773
25926
|
success: false,
|
|
@@ -25790,7 +25943,7 @@ async function estimateFanOut(sourceFiles, cwd) {
|
|
|
25790
25943
|
const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
|
|
25791
25944
|
const uniqueTestFiles = new Set;
|
|
25792
25945
|
for (const sourceFile of sourceFiles) {
|
|
25793
|
-
const resolvedPath =
|
|
25946
|
+
const resolvedPath = path52.resolve(cwd, sourceFile);
|
|
25794
25947
|
const normalizedPath = resolvedPath.replace(/\\/g, "/");
|
|
25795
25948
|
const testFiles = impactMap[normalizedPath];
|
|
25796
25949
|
if (testFiles) {
|
|
@@ -25875,14 +26028,14 @@ function hasDevDependency(devDeps, ...patterns) {
|
|
|
25875
26028
|
return hasPackageJsonDependency(devDeps, ...patterns);
|
|
25876
26029
|
}
|
|
25877
26030
|
function detectGoTest(cwd) {
|
|
25878
|
-
return fs21.existsSync(
|
|
26031
|
+
return fs21.existsSync(path52.join(cwd, "go.mod")) && isCommandAvailable("go");
|
|
25879
26032
|
}
|
|
25880
26033
|
function detectJavaMaven(cwd) {
|
|
25881
|
-
return fs21.existsSync(
|
|
26034
|
+
return fs21.existsSync(path52.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
|
|
25882
26035
|
}
|
|
25883
26036
|
function detectGradle(cwd) {
|
|
25884
|
-
const hasBuildFile = fs21.existsSync(
|
|
25885
|
-
const hasGradlew = fs21.existsSync(
|
|
26037
|
+
const hasBuildFile = fs21.existsSync(path52.join(cwd, "build.gradle")) || fs21.existsSync(path52.join(cwd, "build.gradle.kts"));
|
|
26038
|
+
const hasGradlew = fs21.existsSync(path52.join(cwd, "gradlew")) || fs21.existsSync(path52.join(cwd, "gradlew.bat"));
|
|
25886
26039
|
return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
|
|
25887
26040
|
}
|
|
25888
26041
|
function detectDotnetTest(cwd) {
|
|
@@ -25895,25 +26048,25 @@ function detectDotnetTest(cwd) {
|
|
|
25895
26048
|
}
|
|
25896
26049
|
}
|
|
25897
26050
|
function detectCTest(cwd) {
|
|
25898
|
-
const hasSource = fs21.existsSync(
|
|
25899
|
-
const hasBuildCache = fs21.existsSync(
|
|
26051
|
+
const hasSource = fs21.existsSync(path52.join(cwd, "CMakeLists.txt"));
|
|
26052
|
+
const hasBuildCache = fs21.existsSync(path52.join(cwd, "CMakeCache.txt")) || fs21.existsSync(path52.join(cwd, "build", "CMakeCache.txt"));
|
|
25900
26053
|
return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
|
|
25901
26054
|
}
|
|
25902
26055
|
function detectSwiftTest(cwd) {
|
|
25903
|
-
return fs21.existsSync(
|
|
26056
|
+
return fs21.existsSync(path52.join(cwd, "Package.swift")) && isCommandAvailable("swift");
|
|
25904
26057
|
}
|
|
25905
26058
|
function detectDartTest(cwd) {
|
|
25906
|
-
return fs21.existsSync(
|
|
26059
|
+
return fs21.existsSync(path52.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
|
|
25907
26060
|
}
|
|
25908
26061
|
function detectRSpec(cwd) {
|
|
25909
|
-
const hasRSpecFile = fs21.existsSync(
|
|
25910
|
-
const hasGemfile = fs21.existsSync(
|
|
25911
|
-
const hasSpecDir = fs21.existsSync(
|
|
26062
|
+
const hasRSpecFile = fs21.existsSync(path52.join(cwd, ".rspec"));
|
|
26063
|
+
const hasGemfile = fs21.existsSync(path52.join(cwd, "Gemfile"));
|
|
26064
|
+
const hasSpecDir = fs21.existsSync(path52.join(cwd, "spec"));
|
|
25912
26065
|
const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
|
|
25913
26066
|
return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
|
|
25914
26067
|
}
|
|
25915
26068
|
function detectMinitest(cwd) {
|
|
25916
|
-
return fs21.existsSync(
|
|
26069
|
+
return fs21.existsSync(path52.join(cwd, "test")) && (fs21.existsSync(path52.join(cwd, "Gemfile")) || fs21.existsSync(path52.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
|
|
25917
26070
|
}
|
|
25918
26071
|
var DISPATCH_FRAMEWORK_MAP = {
|
|
25919
26072
|
bun: "bun",
|
|
@@ -26003,7 +26156,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
|
|
|
26003
26156
|
async function detectTestFramework(cwd) {
|
|
26004
26157
|
const baseDir = cwd;
|
|
26005
26158
|
try {
|
|
26006
|
-
const packageJsonPath =
|
|
26159
|
+
const packageJsonPath = path52.join(baseDir, "package.json");
|
|
26007
26160
|
if (fs21.existsSync(packageJsonPath)) {
|
|
26008
26161
|
const content = fs21.readFileSync(packageJsonPath, "utf-8");
|
|
26009
26162
|
const pkg = JSON.parse(content);
|
|
@@ -26024,16 +26177,16 @@ async function detectTestFramework(cwd) {
|
|
|
26024
26177
|
return "jest";
|
|
26025
26178
|
if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
|
|
26026
26179
|
return "mocha";
|
|
26027
|
-
if (fs21.existsSync(
|
|
26180
|
+
if (fs21.existsSync(path52.join(baseDir, "bun.lockb")) || fs21.existsSync(path52.join(baseDir, "bun.lock"))) {
|
|
26028
26181
|
if (scripts.test?.includes("bun"))
|
|
26029
26182
|
return "bun";
|
|
26030
26183
|
}
|
|
26031
26184
|
}
|
|
26032
26185
|
} catch {}
|
|
26033
26186
|
try {
|
|
26034
|
-
const pyprojectTomlPath =
|
|
26035
|
-
const setupCfgPath =
|
|
26036
|
-
const requirementsTxtPath =
|
|
26187
|
+
const pyprojectTomlPath = path52.join(baseDir, "pyproject.toml");
|
|
26188
|
+
const setupCfgPath = path52.join(baseDir, "setup.cfg");
|
|
26189
|
+
const requirementsTxtPath = path52.join(baseDir, "requirements.txt");
|
|
26037
26190
|
if (fs21.existsSync(pyprojectTomlPath)) {
|
|
26038
26191
|
const content = fs21.readFileSync(pyprojectTomlPath, "utf-8");
|
|
26039
26192
|
if (content.includes("[tool.pytest"))
|
|
@@ -26053,7 +26206,7 @@ async function detectTestFramework(cwd) {
|
|
|
26053
26206
|
}
|
|
26054
26207
|
} catch {}
|
|
26055
26208
|
try {
|
|
26056
|
-
const cargoTomlPath =
|
|
26209
|
+
const cargoTomlPath = path52.join(baseDir, "Cargo.toml");
|
|
26057
26210
|
if (fs21.existsSync(cargoTomlPath)) {
|
|
26058
26211
|
const content = fs21.readFileSync(cargoTomlPath, "utf-8");
|
|
26059
26212
|
if (content.includes("[dev-dependencies]")) {
|
|
@@ -26064,9 +26217,9 @@ async function detectTestFramework(cwd) {
|
|
|
26064
26217
|
}
|
|
26065
26218
|
} catch {}
|
|
26066
26219
|
try {
|
|
26067
|
-
const pesterConfigPath =
|
|
26068
|
-
const pesterConfigJsonPath =
|
|
26069
|
-
const pesterPs1Path =
|
|
26220
|
+
const pesterConfigPath = path52.join(baseDir, "pester.config.ps1");
|
|
26221
|
+
const pesterConfigJsonPath = path52.join(baseDir, "pester.config.ps1.json");
|
|
26222
|
+
const pesterPs1Path = path52.join(baseDir, "tests.ps1");
|
|
26070
26223
|
if (fs21.existsSync(pesterConfigPath) || fs21.existsSync(pesterConfigJsonPath) || fs21.existsSync(pesterPs1Path)) {
|
|
26071
26224
|
return "pester";
|
|
26072
26225
|
}
|
|
@@ -26095,12 +26248,12 @@ async function detectTestFramework(cwd) {
|
|
|
26095
26248
|
return "none";
|
|
26096
26249
|
}
|
|
26097
26250
|
function detectPhpTest(cwd) {
|
|
26098
|
-
if (fs21.existsSync(
|
|
26251
|
+
if (fs21.existsSync(path52.join(cwd, "artisan")) && fs21.existsSync(path52.join(cwd, "composer.json"))) {
|
|
26099
26252
|
return "php-artisan";
|
|
26100
26253
|
}
|
|
26101
|
-
if (fs21.existsSync(
|
|
26254
|
+
if (fs21.existsSync(path52.join(cwd, "Pest.php")))
|
|
26102
26255
|
return "pest";
|
|
26103
|
-
if (fs21.existsSync(
|
|
26256
|
+
if (fs21.existsSync(path52.join(cwd, "phpunit.xml")) || fs21.existsSync(path52.join(cwd, "phpunit.xml.dist"))) {
|
|
26104
26257
|
return "phpunit";
|
|
26105
26258
|
}
|
|
26106
26259
|
return null;
|
|
@@ -26123,12 +26276,12 @@ function isTestDirectoryPath(normalizedPath) {
|
|
|
26123
26276
|
return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
|
|
26124
26277
|
}
|
|
26125
26278
|
function resolveWorkspacePath(file, workingDir) {
|
|
26126
|
-
return
|
|
26279
|
+
return path52.isAbsolute(file) ? path52.resolve(file) : path52.resolve(workingDir, file);
|
|
26127
26280
|
}
|
|
26128
26281
|
function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
|
|
26129
26282
|
if (!preferRelative)
|
|
26130
26283
|
return absolutePath;
|
|
26131
|
-
return
|
|
26284
|
+
return path52.relative(workingDir, absolutePath);
|
|
26132
26285
|
}
|
|
26133
26286
|
function dedupePush(target, value) {
|
|
26134
26287
|
if (!target.includes(value)) {
|
|
@@ -26171,18 +26324,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
|
|
|
26171
26324
|
}
|
|
26172
26325
|
}
|
|
26173
26326
|
function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
|
|
26174
|
-
const relativeDir =
|
|
26327
|
+
const relativeDir = path52.dirname(relativePath);
|
|
26175
26328
|
const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
|
|
26176
26329
|
const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
|
|
26177
|
-
const rootDir =
|
|
26178
|
-
return nestedRelativeDir ? [rootDir,
|
|
26330
|
+
const rootDir = path52.join(workingDir, dirName);
|
|
26331
|
+
return nestedRelativeDir ? [rootDir, path52.join(rootDir, nestedRelativeDir)] : [rootDir];
|
|
26179
26332
|
});
|
|
26180
26333
|
const normalizedRelativePath = relativePath.replace(/\\/g, "/");
|
|
26181
26334
|
if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
|
|
26182
|
-
directories.push(
|
|
26335
|
+
directories.push(path52.join(workingDir, "src/test/java", path52.dirname(normalizedRelativePath.slice("src/main/java/".length))));
|
|
26183
26336
|
}
|
|
26184
26337
|
if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
|
|
26185
|
-
directories.push(
|
|
26338
|
+
directories.push(path52.join(workingDir, "src/test/kotlin", path52.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
|
|
26186
26339
|
}
|
|
26187
26340
|
return [...new Set(directories)];
|
|
26188
26341
|
}
|
|
@@ -26190,21 +26343,21 @@ function hasCompoundTestExtension(filename) {
|
|
|
26190
26343
|
const lower = filename.toLowerCase();
|
|
26191
26344
|
return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
|
26192
26345
|
}
|
|
26193
|
-
function isLanguageSpecificTestFile(
|
|
26194
|
-
const lower =
|
|
26346
|
+
function isLanguageSpecificTestFile(basename12) {
|
|
26347
|
+
const lower = basename12.toLowerCase();
|
|
26195
26348
|
if (lower.endsWith("_test.go"))
|
|
26196
26349
|
return true;
|
|
26197
26350
|
if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
|
|
26198
26351
|
return true;
|
|
26199
26352
|
if (lower.endsWith("_spec.rb"))
|
|
26200
26353
|
return true;
|
|
26201
|
-
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(
|
|
26354
|
+
if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename12) || basename12.endsWith("Test.java") || basename12.endsWith("Tests.java") || lower.endsWith("it.java")))
|
|
26202
26355
|
return true;
|
|
26203
26356
|
if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
|
|
26204
26357
|
return true;
|
|
26205
|
-
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(
|
|
26358
|
+
if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename12) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
|
|
26206
26359
|
return true;
|
|
26207
|
-
if (lower.endsWith(".php") && (/^Test[A-Z]/.test(
|
|
26360
|
+
if (lower.endsWith(".php") && (/^Test[A-Z]/.test(basename12) || basename12.endsWith("Test.php") || basename12.endsWith("Tests.php")))
|
|
26208
26361
|
return true;
|
|
26209
26362
|
if (lower.endsWith(".tests.ps1"))
|
|
26210
26363
|
return true;
|
|
@@ -26212,23 +26365,23 @@ function isLanguageSpecificTestFile(basename11) {
|
|
|
26212
26365
|
}
|
|
26213
26366
|
function isConventionTestFilePath(filePath) {
|
|
26214
26367
|
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
26215
|
-
const
|
|
26216
|
-
return hasCompoundTestExtension(
|
|
26368
|
+
const basename12 = path52.basename(filePath);
|
|
26369
|
+
return hasCompoundTestExtension(basename12) || basename12.includes(".spec.") || basename12.includes(".test.") || isLanguageSpecificTestFile(basename12) || isTestDirectoryPath(normalizedPath);
|
|
26217
26370
|
}
|
|
26218
26371
|
function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
26219
26372
|
const testFiles = [];
|
|
26220
26373
|
for (const file of sourceFiles) {
|
|
26221
26374
|
const absoluteFile = resolveWorkspacePath(file, workingDir);
|
|
26222
|
-
const relativeFile =
|
|
26223
|
-
const
|
|
26224
|
-
const dirname25 =
|
|
26225
|
-
const preferRelativeOutput = !
|
|
26375
|
+
const relativeFile = path52.relative(workingDir, absoluteFile);
|
|
26376
|
+
const basename12 = path52.basename(absoluteFile);
|
|
26377
|
+
const dirname25 = path52.dirname(absoluteFile);
|
|
26378
|
+
const preferRelativeOutput = !path52.isAbsolute(file);
|
|
26226
26379
|
if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
|
|
26227
26380
|
dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
|
|
26228
26381
|
continue;
|
|
26229
26382
|
}
|
|
26230
|
-
const nameWithoutExt =
|
|
26231
|
-
const ext =
|
|
26383
|
+
const nameWithoutExt = basename12.replace(/\.[^.]+$/, "");
|
|
26384
|
+
const ext = path52.extname(basename12);
|
|
26232
26385
|
const genericTestNames = [
|
|
26233
26386
|
`${nameWithoutExt}.spec${ext}`,
|
|
26234
26387
|
`${nameWithoutExt}.test${ext}`
|
|
@@ -26237,17 +26390,17 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
|
|
|
26237
26390
|
const colocatedCandidates = [
|
|
26238
26391
|
...genericTestNames,
|
|
26239
26392
|
...languageSpecificTestNames
|
|
26240
|
-
].map((candidateName) =>
|
|
26393
|
+
].map((candidateName) => path52.join(dirname25, candidateName));
|
|
26241
26394
|
const testDirectoryNames = [
|
|
26242
|
-
|
|
26395
|
+
basename12,
|
|
26243
26396
|
...genericTestNames,
|
|
26244
26397
|
...languageSpecificTestNames
|
|
26245
26398
|
];
|
|
26246
26399
|
const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
|
|
26247
26400
|
const possibleTestFiles = [
|
|
26248
26401
|
...colocatedCandidates,
|
|
26249
|
-
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) =>
|
|
26250
|
-
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) =>
|
|
26402
|
+
...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path52.join(dirname25, dirName, candidateName))),
|
|
26403
|
+
...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path52.join(candidateDir, candidateName)))
|
|
26251
26404
|
];
|
|
26252
26405
|
for (const testFile of possibleTestFiles) {
|
|
26253
26406
|
if (fs21.existsSync(testFile)) {
|
|
@@ -26268,7 +26421,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26268
26421
|
try {
|
|
26269
26422
|
const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
|
|
26270
26423
|
const content = fs21.readFileSync(absoluteTestFile, "utf-8");
|
|
26271
|
-
const testDir =
|
|
26424
|
+
const testDir = path52.dirname(absoluteTestFile);
|
|
26272
26425
|
const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
|
|
26273
26426
|
let match;
|
|
26274
26427
|
match = importRegex.exec(content);
|
|
@@ -26276,8 +26429,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26276
26429
|
const importPath = match[1];
|
|
26277
26430
|
let resolvedImport;
|
|
26278
26431
|
if (importPath.startsWith(".")) {
|
|
26279
|
-
resolvedImport =
|
|
26280
|
-
const existingExt =
|
|
26432
|
+
resolvedImport = path52.resolve(testDir, importPath);
|
|
26433
|
+
const existingExt = path52.extname(resolvedImport);
|
|
26281
26434
|
if (!existingExt) {
|
|
26282
26435
|
for (const extToTry of [
|
|
26283
26436
|
".ts",
|
|
@@ -26297,12 +26450,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26297
26450
|
} else {
|
|
26298
26451
|
continue;
|
|
26299
26452
|
}
|
|
26300
|
-
const importBasename =
|
|
26301
|
-
const importDir =
|
|
26453
|
+
const importBasename = path52.basename(resolvedImport, path52.extname(resolvedImport));
|
|
26454
|
+
const importDir = path52.dirname(resolvedImport);
|
|
26302
26455
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26303
|
-
const sourceDir =
|
|
26304
|
-
const sourceBasename =
|
|
26305
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26456
|
+
const sourceDir = path52.dirname(sourceFile);
|
|
26457
|
+
const sourceBasename = path52.basename(sourceFile, path52.extname(sourceFile));
|
|
26458
|
+
const isRelatedDir = importDir === sourceDir || importDir === path52.join(sourceDir, "__tests__") || importDir === path52.join(sourceDir, "tests") || importDir === path52.join(sourceDir, "test") || importDir === path52.join(sourceDir, "spec");
|
|
26306
26459
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26307
26460
|
dedupePush(testFiles, testFile);
|
|
26308
26461
|
break;
|
|
@@ -26315,8 +26468,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26315
26468
|
while (match !== null) {
|
|
26316
26469
|
const importPath = match[1];
|
|
26317
26470
|
if (importPath.startsWith(".")) {
|
|
26318
|
-
let resolvedImport =
|
|
26319
|
-
const existingExt =
|
|
26471
|
+
let resolvedImport = path52.resolve(testDir, importPath);
|
|
26472
|
+
const existingExt = path52.extname(resolvedImport);
|
|
26320
26473
|
if (!existingExt) {
|
|
26321
26474
|
for (const extToTry of [
|
|
26322
26475
|
".ts",
|
|
@@ -26333,12 +26486,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
|
|
|
26333
26486
|
}
|
|
26334
26487
|
}
|
|
26335
26488
|
}
|
|
26336
|
-
const importDir =
|
|
26337
|
-
const importBasename =
|
|
26489
|
+
const importDir = path52.dirname(resolvedImport);
|
|
26490
|
+
const importBasename = path52.basename(resolvedImport, path52.extname(resolvedImport));
|
|
26338
26491
|
for (const sourceFile of absoluteSourceFiles) {
|
|
26339
|
-
const sourceDir =
|
|
26340
|
-
const sourceBasename =
|
|
26341
|
-
const isRelatedDir = importDir === sourceDir || importDir ===
|
|
26492
|
+
const sourceDir = path52.dirname(sourceFile);
|
|
26493
|
+
const sourceBasename = path52.basename(sourceFile, path52.extname(sourceFile));
|
|
26494
|
+
const isRelatedDir = importDir === sourceDir || importDir === path52.join(sourceDir, "__tests__") || importDir === path52.join(sourceDir, "tests") || importDir === path52.join(sourceDir, "test") || importDir === path52.join(sourceDir, "spec");
|
|
26342
26495
|
if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
|
|
26343
26496
|
dedupePush(testFiles, testFile);
|
|
26344
26497
|
break;
|
|
@@ -26458,8 +26611,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26458
26611
|
return ["mvn", "test"];
|
|
26459
26612
|
case "gradle": {
|
|
26460
26613
|
const isWindows = process.platform === "win32";
|
|
26461
|
-
const hasGradlewBat = fs21.existsSync(
|
|
26462
|
-
const hasGradlew = fs21.existsSync(
|
|
26614
|
+
const hasGradlewBat = fs21.existsSync(path52.join(baseDir, "gradlew.bat"));
|
|
26615
|
+
const hasGradlew = fs21.existsSync(path52.join(baseDir, "gradlew"));
|
|
26463
26616
|
if (hasGradlewBat && isWindows)
|
|
26464
26617
|
return ["gradlew.bat", "test"];
|
|
26465
26618
|
if (hasGradlew)
|
|
@@ -26476,7 +26629,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26476
26629
|
"cmake-build-release",
|
|
26477
26630
|
"out"
|
|
26478
26631
|
];
|
|
26479
|
-
const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(
|
|
26632
|
+
const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(path52.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
|
|
26480
26633
|
return ["ctest", "--test-dir", actualBuildDir];
|
|
26481
26634
|
}
|
|
26482
26635
|
case "swift-test":
|
|
@@ -26526,7 +26679,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
|
|
|
26526
26679
|
}
|
|
26527
26680
|
}
|
|
26528
26681
|
function phpVendorBin2(name) {
|
|
26529
|
-
return
|
|
26682
|
+
return path52.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
|
|
26530
26683
|
}
|
|
26531
26684
|
function mapFrameworkStatusToResult(status) {
|
|
26532
26685
|
if (typeof status !== "string")
|
|
@@ -26949,11 +27102,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
|
|
|
26949
27102
|
};
|
|
26950
27103
|
}
|
|
26951
27104
|
const startTime = Date.now();
|
|
26952
|
-
const vitestJsonOutputPath = framework === "vitest" ?
|
|
27105
|
+
const vitestJsonOutputPath = framework === "vitest" ? path52.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
|
|
26953
27106
|
try {
|
|
26954
27107
|
if (vitestJsonOutputPath) {
|
|
26955
27108
|
try {
|
|
26956
|
-
fs21.mkdirSync(
|
|
27109
|
+
fs21.mkdirSync(path52.dirname(vitestJsonOutputPath), { recursive: true });
|
|
26957
27110
|
if (fs21.existsSync(vitestJsonOutputPath)) {
|
|
26958
27111
|
fs21.unlinkSync(vitestJsonOutputPath);
|
|
26959
27112
|
}
|
|
@@ -27122,10 +27275,10 @@ var SKIP_DIRECTORIES = new Set([
|
|
|
27122
27275
|
]);
|
|
27123
27276
|
function normalizeHistoryTestFile(testFile, workingDir) {
|
|
27124
27277
|
const normalized = testFile.replace(/\\/g, "/");
|
|
27125
|
-
if (!
|
|
27278
|
+
if (!path52.isAbsolute(testFile))
|
|
27126
27279
|
return normalized;
|
|
27127
|
-
const relative6 =
|
|
27128
|
-
if (relative6.startsWith("..") ||
|
|
27280
|
+
const relative6 = path52.relative(workingDir, testFile);
|
|
27281
|
+
if (relative6.startsWith("..") || path52.isAbsolute(relative6)) {
|
|
27129
27282
|
return normalized;
|
|
27130
27283
|
}
|
|
27131
27284
|
return relative6.replace(/\\/g, "/");
|
|
@@ -27364,7 +27517,7 @@ var test_runner = createSwarmTool({
|
|
|
27364
27517
|
const sourceFiles = args.files.filter((file) => {
|
|
27365
27518
|
if (directTestFiles.includes(file))
|
|
27366
27519
|
return false;
|
|
27367
|
-
const ext =
|
|
27520
|
+
const ext = path52.extname(file).toLowerCase();
|
|
27368
27521
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27369
27522
|
});
|
|
27370
27523
|
const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
|
|
@@ -27410,7 +27563,7 @@ var test_runner = createSwarmTool({
|
|
|
27410
27563
|
if (isConventionTestFilePath(f)) {
|
|
27411
27564
|
return false;
|
|
27412
27565
|
}
|
|
27413
|
-
const ext =
|
|
27566
|
+
const ext = path52.extname(f).toLowerCase();
|
|
27414
27567
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27415
27568
|
});
|
|
27416
27569
|
if (sourceFiles.length === 0) {
|
|
@@ -27460,7 +27613,7 @@ var test_runner = createSwarmTool({
|
|
|
27460
27613
|
if (isConventionTestFilePath(f)) {
|
|
27461
27614
|
return false;
|
|
27462
27615
|
}
|
|
27463
|
-
const ext =
|
|
27616
|
+
const ext = path52.extname(f).toLowerCase();
|
|
27464
27617
|
return SOURCE_EXTENSIONS.has(ext);
|
|
27465
27618
|
});
|
|
27466
27619
|
if (sourceFiles.length === 0) {
|
|
@@ -27512,8 +27665,8 @@ var test_runner = createSwarmTool({
|
|
|
27512
27665
|
}
|
|
27513
27666
|
if (impactResult.impactedTests.length > 0) {
|
|
27514
27667
|
testFiles = impactResult.impactedTests.map((absPath) => {
|
|
27515
|
-
const relativePath =
|
|
27516
|
-
return
|
|
27668
|
+
const relativePath = path52.relative(workingDir, absPath);
|
|
27669
|
+
return path52.isAbsolute(relativePath) ? absPath : relativePath;
|
|
27517
27670
|
});
|
|
27518
27671
|
} else {
|
|
27519
27672
|
graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
|
|
@@ -27608,8 +27761,8 @@ function validateDirectoryPath(dir) {
|
|
|
27608
27761
|
if (dir.includes("..")) {
|
|
27609
27762
|
throw new Error("Directory path must not contain path traversal sequences");
|
|
27610
27763
|
}
|
|
27611
|
-
const normalized =
|
|
27612
|
-
const absolutePath =
|
|
27764
|
+
const normalized = path53.normalize(dir);
|
|
27765
|
+
const absolutePath = path53.isAbsolute(normalized) ? normalized : path53.resolve(normalized);
|
|
27613
27766
|
return absolutePath;
|
|
27614
27767
|
}
|
|
27615
27768
|
function validateTimeout(timeoutMs, defaultValue) {
|
|
@@ -27632,7 +27785,7 @@ function validateTimeout(timeoutMs, defaultValue) {
|
|
|
27632
27785
|
}
|
|
27633
27786
|
function getPackageVersion(dir) {
|
|
27634
27787
|
try {
|
|
27635
|
-
const packagePath =
|
|
27788
|
+
const packagePath = path53.join(dir, "package.json");
|
|
27636
27789
|
if (fs22.existsSync(packagePath)) {
|
|
27637
27790
|
const content = fs22.readFileSync(packagePath, "utf-8");
|
|
27638
27791
|
const pkg = JSON.parse(content);
|
|
@@ -27643,7 +27796,7 @@ function getPackageVersion(dir) {
|
|
|
27643
27796
|
}
|
|
27644
27797
|
function getChangelogVersion(dir) {
|
|
27645
27798
|
try {
|
|
27646
|
-
const changelogPath =
|
|
27799
|
+
const changelogPath = path53.join(dir, "CHANGELOG.md");
|
|
27647
27800
|
if (fs22.existsSync(changelogPath)) {
|
|
27648
27801
|
const content = fs22.readFileSync(changelogPath, "utf-8");
|
|
27649
27802
|
const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
|
|
@@ -27657,7 +27810,7 @@ function getChangelogVersion(dir) {
|
|
|
27657
27810
|
function getVersionFileVersion(dir) {
|
|
27658
27811
|
const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
|
|
27659
27812
|
for (const file of possibleFiles) {
|
|
27660
|
-
const filePath =
|
|
27813
|
+
const filePath = path53.join(dir, file);
|
|
27661
27814
|
if (fs22.existsSync(filePath)) {
|
|
27662
27815
|
try {
|
|
27663
27816
|
const content = fs22.readFileSync(filePath, "utf-8").trim();
|
|
@@ -28395,7 +28548,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
|
|
|
28395
28548
|
|
|
28396
28549
|
// src/commands/reset.ts
|
|
28397
28550
|
import * as fs23 from "fs";
|
|
28398
|
-
import * as
|
|
28551
|
+
import * as path54 from "path";
|
|
28399
28552
|
|
|
28400
28553
|
// src/background/circuit-breaker.ts
|
|
28401
28554
|
class CircuitBreaker {
|
|
@@ -29114,7 +29267,7 @@ async function handleResetCommand(directory, args) {
|
|
|
29114
29267
|
}
|
|
29115
29268
|
for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
|
|
29116
29269
|
try {
|
|
29117
|
-
const rootPath =
|
|
29270
|
+
const rootPath = path54.join(directory, filename);
|
|
29118
29271
|
if (fs23.existsSync(rootPath)) {
|
|
29119
29272
|
fs23.unlinkSync(rootPath);
|
|
29120
29273
|
results.push(`- \u2705 Deleted ${filename} (root)`);
|
|
@@ -29152,14 +29305,14 @@ async function handleResetCommand(directory, args) {
|
|
|
29152
29305
|
|
|
29153
29306
|
// src/commands/reset-session.ts
|
|
29154
29307
|
import * as fs26 from "fs";
|
|
29155
|
-
import * as
|
|
29308
|
+
import * as path57 from "path";
|
|
29156
29309
|
|
|
29157
29310
|
// src/prm/trajectory-store.ts
|
|
29158
29311
|
import * as fs24 from "fs/promises";
|
|
29159
|
-
import * as
|
|
29312
|
+
import * as path55 from "path";
|
|
29160
29313
|
var MAX_TRACKED_TRAJECTORY_SESSIONS = 500;
|
|
29161
29314
|
function getTrajectoryPath(sessionId, directory) {
|
|
29162
|
-
const relativePath =
|
|
29315
|
+
const relativePath = path55.join("trajectories", `${sessionId}.jsonl`);
|
|
29163
29316
|
return validateSwarmPath(directory, relativePath);
|
|
29164
29317
|
}
|
|
29165
29318
|
var _inMemoryTrajectoryCache = new Map;
|
|
@@ -29218,7 +29371,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
|
|
|
29218
29371
|
for (const entry of entries) {
|
|
29219
29372
|
if (!entry.isFile())
|
|
29220
29373
|
continue;
|
|
29221
|
-
const filePath =
|
|
29374
|
+
const filePath = path55.join(dirPath, entry.name);
|
|
29222
29375
|
try {
|
|
29223
29376
|
const stat6 = await fs24.stat(filePath);
|
|
29224
29377
|
if (now - stat6.mtimeMs > cutoffMs) {
|
|
@@ -29645,16 +29798,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
|
|
|
29645
29798
|
}
|
|
29646
29799
|
// src/prm/replay.ts
|
|
29647
29800
|
import { promises as fs25 } from "fs";
|
|
29648
|
-
import
|
|
29801
|
+
import path56 from "path";
|
|
29649
29802
|
function isPathSafe(targetPath, basePath) {
|
|
29650
|
-
const resolvedTarget =
|
|
29651
|
-
const resolvedBase =
|
|
29652
|
-
const rel =
|
|
29653
|
-
return !rel.startsWith("..") && !
|
|
29803
|
+
const resolvedTarget = path56.resolve(targetPath);
|
|
29804
|
+
const resolvedBase = path56.resolve(basePath);
|
|
29805
|
+
const rel = path56.relative(resolvedBase, resolvedTarget);
|
|
29806
|
+
return !rel.startsWith("..") && !path56.isAbsolute(rel);
|
|
29654
29807
|
}
|
|
29655
29808
|
function isWithinReplaysDir(targetPath) {
|
|
29656
|
-
const resolved =
|
|
29657
|
-
const parts = resolved.split(
|
|
29809
|
+
const resolved = path56.resolve(targetPath);
|
|
29810
|
+
const parts = resolved.split(path56.sep);
|
|
29658
29811
|
for (let i = 0;i < parts.length - 1; i++) {
|
|
29659
29812
|
if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
|
|
29660
29813
|
return true;
|
|
@@ -29667,10 +29820,10 @@ function sanitizeFilename(input) {
|
|
|
29667
29820
|
}
|
|
29668
29821
|
async function startReplayRecording(sessionID, directory) {
|
|
29669
29822
|
try {
|
|
29670
|
-
const replayDir =
|
|
29823
|
+
const replayDir = path56.join(directory, ".swarm", "replays");
|
|
29671
29824
|
const safeSessionID = sanitizeFilename(sessionID);
|
|
29672
29825
|
const filename = `${safeSessionID}-${Date.now()}.jsonl`;
|
|
29673
|
-
const filepath =
|
|
29826
|
+
const filepath = path56.join(replayDir, filename);
|
|
29674
29827
|
if (!isPathSafe(filepath, replayDir)) {
|
|
29675
29828
|
console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
|
|
29676
29829
|
return null;
|
|
@@ -29752,7 +29905,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
29752
29905
|
} catch {
|
|
29753
29906
|
results.push("\u274C Failed to delete state.json");
|
|
29754
29907
|
}
|
|
29755
|
-
const sessionDir = statePath ?
|
|
29908
|
+
const sessionDir = statePath ? path57.dirname(statePath) : undefined;
|
|
29756
29909
|
let sessionFiles = [];
|
|
29757
29910
|
if (sessionDir && fs26.existsSync(sessionDir)) {
|
|
29758
29911
|
try {
|
|
@@ -29764,7 +29917,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
29764
29917
|
for (const file of sessionFiles) {
|
|
29765
29918
|
if (file === "state.json")
|
|
29766
29919
|
continue;
|
|
29767
|
-
const filePath =
|
|
29920
|
+
const filePath = path57.join(sessionDir, file);
|
|
29768
29921
|
try {
|
|
29769
29922
|
if (!fs26.existsSync(filePath))
|
|
29770
29923
|
continue;
|
|
@@ -29786,7 +29939,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
29786
29939
|
const chainCount = swarmState.delegationChains.size;
|
|
29787
29940
|
swarmState.delegationChains.clear();
|
|
29788
29941
|
results.push(`\u2705 Cleared ${chainCount} delegation chain(s)`);
|
|
29789
|
-
const worktreesDir =
|
|
29942
|
+
const worktreesDir = path57.resolve(path57.dirname(directory), ".swarm-worktrees");
|
|
29790
29943
|
try {
|
|
29791
29944
|
if (fs26.existsSync(worktreesDir)) {
|
|
29792
29945
|
fs26.rmSync(worktreesDir, { recursive: true, force: true });
|
|
@@ -29819,7 +29972,7 @@ async function handleResetSessionCommand(directory, _args) {
|
|
|
29819
29972
|
}
|
|
29820
29973
|
|
|
29821
29974
|
// src/summaries/manager.ts
|
|
29822
|
-
import * as
|
|
29975
|
+
import * as path58 from "path";
|
|
29823
29976
|
var SUMMARY_ID_REGEX = /^S\d+$/;
|
|
29824
29977
|
function sanitizeSummaryId(id) {
|
|
29825
29978
|
if (!id || id.length === 0) {
|
|
@@ -29843,7 +29996,7 @@ function sanitizeSummaryId(id) {
|
|
|
29843
29996
|
}
|
|
29844
29997
|
async function loadFullOutput(directory, id) {
|
|
29845
29998
|
const sanitizedId = sanitizeSummaryId(id);
|
|
29846
|
-
const relativePath =
|
|
29999
|
+
const relativePath = path58.join("summaries", `${sanitizedId}.json`);
|
|
29847
30000
|
validateSwarmPath(directory, relativePath);
|
|
29848
30001
|
const content = await readSwarmFileAsync(directory, relativePath);
|
|
29849
30002
|
if (content === null) {
|
|
@@ -29896,7 +30049,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
|
29896
30049
|
|
|
29897
30050
|
// src/commands/rollback.ts
|
|
29898
30051
|
import * as fs27 from "fs";
|
|
29899
|
-
import * as
|
|
30052
|
+
import * as path59 from "path";
|
|
29900
30053
|
function safeParseToolJson(result) {
|
|
29901
30054
|
try {
|
|
29902
30055
|
const jsonStr = typeof result === "string" ? result : result.output;
|
|
@@ -30051,8 +30204,8 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30051
30204
|
if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
|
|
30052
30205
|
continue;
|
|
30053
30206
|
}
|
|
30054
|
-
const src =
|
|
30055
|
-
const dest =
|
|
30207
|
+
const src = path59.join(checkpointDir, file);
|
|
30208
|
+
const dest = path59.join(swarmDir, file);
|
|
30056
30209
|
try {
|
|
30057
30210
|
fs27.cpSync(src, dest, { recursive: true, force: true });
|
|
30058
30211
|
successes.push(file);
|
|
@@ -30071,7 +30224,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30071
30224
|
].join(`
|
|
30072
30225
|
`);
|
|
30073
30226
|
}
|
|
30074
|
-
const existingLedgerPath =
|
|
30227
|
+
const existingLedgerPath = path59.join(swarmDir, "plan-ledger.jsonl");
|
|
30075
30228
|
let ledgerDeletionFailed = false;
|
|
30076
30229
|
if (fs27.existsSync(existingLedgerPath)) {
|
|
30077
30230
|
try {
|
|
@@ -30084,7 +30237,7 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30084
30237
|
}
|
|
30085
30238
|
if (!ledgerDeletionFailed) {
|
|
30086
30239
|
try {
|
|
30087
|
-
const planJsonPath =
|
|
30240
|
+
const planJsonPath = path59.join(swarmDir, "plan.json");
|
|
30088
30241
|
if (fs27.existsSync(planJsonPath)) {
|
|
30089
30242
|
const planRaw = fs27.readFileSync(planJsonPath, "utf-8");
|
|
30090
30243
|
const plan = PlanSchema.parse(JSON.parse(planRaw));
|
|
@@ -30132,11 +30285,11 @@ async function handleRollbackCommand(directory, args) {
|
|
|
30132
30285
|
|
|
30133
30286
|
// src/commands/sdd.ts
|
|
30134
30287
|
import * as fs28 from "fs";
|
|
30135
|
-
import * as
|
|
30288
|
+
import * as path60 from "path";
|
|
30136
30289
|
var _internals43 = {
|
|
30137
30290
|
writeProjectedSpecSync
|
|
30138
30291
|
};
|
|
30139
|
-
var SWARM_SPEC_REL =
|
|
30292
|
+
var SWARM_SPEC_REL = path60.join(".swarm", "spec.md");
|
|
30140
30293
|
var USAGE9 = `Usage:
|
|
30141
30294
|
/swarm sdd status [--json] [--source <provider>]
|
|
30142
30295
|
/swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
@@ -30258,7 +30411,7 @@ ${USAGE9}`;
|
|
|
30258
30411
|
}
|
|
30259
30412
|
const speckitDetection = detectSpeckit(directory);
|
|
30260
30413
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
30261
|
-
const nativeSpecExists = fs28.existsSync(
|
|
30414
|
+
const nativeSpecExists = fs28.existsSync(path60.join(directory, SWARM_SPEC_REL));
|
|
30262
30415
|
if (speckitPresent && !parsed.source && !nativeSpecExists) {
|
|
30263
30416
|
const openspecProjection = buildOpenSpecProjectionSync(directory);
|
|
30264
30417
|
if (openspecProjection !== null) {
|
|
@@ -30328,7 +30481,7 @@ ${USAGE9}`;
|
|
|
30328
30481
|
${USAGE9}`;
|
|
30329
30482
|
}
|
|
30330
30483
|
let useSpeckit = false;
|
|
30331
|
-
const nativeSpecExists = fs28.existsSync(
|
|
30484
|
+
const nativeSpecExists = fs28.existsSync(path60.join(directory, SWARM_SPEC_REL));
|
|
30332
30485
|
if (parsed.source === "speckit") {
|
|
30333
30486
|
useSpeckit = true;
|
|
30334
30487
|
} else if (!parsed.source && !nativeSpecExists) {
|
|
@@ -30482,7 +30635,7 @@ ${USAGE9}`;
|
|
|
30482
30635
|
${USAGE9}`;
|
|
30483
30636
|
}
|
|
30484
30637
|
if (!parsed.dryRun) {
|
|
30485
|
-
const nativeSpecPath =
|
|
30638
|
+
const nativeSpecPath = path60.join(directory, SWARM_SPEC_REL);
|
|
30486
30639
|
if (fs28.existsSync(nativeSpecPath)) {
|
|
30487
30640
|
if (!parsed.overwrite) {
|
|
30488
30641
|
return [
|
|
@@ -30698,10 +30851,10 @@ Ensure this is a git repository with commit history.`;
|
|
|
30698
30851
|
`);
|
|
30699
30852
|
try {
|
|
30700
30853
|
const fs29 = await import("fs/promises");
|
|
30701
|
-
const
|
|
30702
|
-
const reportPath =
|
|
30703
|
-
await fs29.mkdir(
|
|
30704
|
-
const reportTempPath =
|
|
30854
|
+
const path61 = await import("path");
|
|
30855
|
+
const reportPath = path61.join(directory, ".swarm", "simulate-report.md");
|
|
30856
|
+
await fs29.mkdir(path61.dirname(reportPath), { recursive: true });
|
|
30857
|
+
const reportTempPath = path61.join(path61.dirname(reportPath), `${path61.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
|
|
30705
30858
|
try {
|
|
30706
30859
|
await fs29.writeFile(reportTempPath, report, "utf-8");
|
|
30707
30860
|
renameSync10(reportTempPath, reportPath);
|
|
@@ -30730,7 +30883,7 @@ async function handleSpecifyCommand(_directory, args) {
|
|
|
30730
30883
|
// src/services/status-service.ts
|
|
30731
30884
|
import * as fsSync2 from "fs";
|
|
30732
30885
|
import { readFile as readFile17 } from "fs/promises";
|
|
30733
|
-
import * as
|
|
30886
|
+
import * as path62 from "path";
|
|
30734
30887
|
|
|
30735
30888
|
// src/hooks/extractors.ts
|
|
30736
30889
|
function extractCurrentPhase(planContent) {
|
|
@@ -30775,13 +30928,13 @@ function extractCurrentPhaseFromPlan2(plan) {
|
|
|
30775
30928
|
// src/turbo/lean/state.ts
|
|
30776
30929
|
init_logger();
|
|
30777
30930
|
import * as fs29 from "fs";
|
|
30778
|
-
import * as
|
|
30931
|
+
import * as path61 from "path";
|
|
30779
30932
|
var STATE_FILE3 = "turbo-state.json";
|
|
30780
30933
|
function nowISO3() {
|
|
30781
30934
|
return new Date().toISOString();
|
|
30782
30935
|
}
|
|
30783
30936
|
function ensureSwarmDir2(directory) {
|
|
30784
|
-
const swarmDir =
|
|
30937
|
+
const swarmDir = path61.resolve(directory, ".swarm");
|
|
30785
30938
|
if (!fs29.existsSync(swarmDir)) {
|
|
30786
30939
|
fs29.mkdirSync(swarmDir, { recursive: true });
|
|
30787
30940
|
}
|
|
@@ -30826,7 +30979,7 @@ function markStateUnreadable2(directory, reason) {
|
|
|
30826
30979
|
}
|
|
30827
30980
|
function readPersisted2(directory) {
|
|
30828
30981
|
try {
|
|
30829
|
-
const filePath =
|
|
30982
|
+
const filePath = path61.join(directory, ".swarm", STATE_FILE3);
|
|
30830
30983
|
if (!fs29.existsSync(filePath)) {
|
|
30831
30984
|
const seed = emptyPersisted2();
|
|
30832
30985
|
try {
|
|
@@ -30862,7 +31015,7 @@ function writePersisted2(directory, persisted) {
|
|
|
30862
31015
|
let payload;
|
|
30863
31016
|
try {
|
|
30864
31017
|
ensureSwarmDir2(directory);
|
|
30865
|
-
filePath =
|
|
31018
|
+
filePath = path61.join(directory, ".swarm", STATE_FILE3);
|
|
30866
31019
|
tmpPath = `${filePath}.tmp.${Date.now()}`;
|
|
30867
31020
|
persisted.updatedAt = nowISO3();
|
|
30868
31021
|
payload = `${JSON.stringify(persisted, null, 2)}
|
|
@@ -30980,7 +31133,7 @@ var _internals44 = {
|
|
|
30980
31133
|
};
|
|
30981
31134
|
function readSpecStalenessSnapshot(directory) {
|
|
30982
31135
|
try {
|
|
30983
|
-
const p =
|
|
31136
|
+
const p = path62.join(directory, ".swarm", "spec-staleness.json");
|
|
30984
31137
|
if (!fsSync2.existsSync(p))
|
|
30985
31138
|
return { stale: false };
|
|
30986
31139
|
const raw = fsSync2.readFileSync(p, "utf-8");
|
|
@@ -31513,11 +31666,11 @@ function buildStatusMessage2(session, directory, sessionID) {
|
|
|
31513
31666
|
|
|
31514
31667
|
// src/commands/unlink.ts
|
|
31515
31668
|
import { existsSync as existsSync40 } from "fs";
|
|
31516
|
-
import * as
|
|
31669
|
+
import * as path63 from "path";
|
|
31517
31670
|
var DEDUP_THRESHOLD2 = 0.6;
|
|
31518
31671
|
async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
|
|
31519
|
-
const sharedPath =
|
|
31520
|
-
const localPath =
|
|
31672
|
+
const sharedPath = path63.join(linkDir, "knowledge.jsonl");
|
|
31673
|
+
const localPath = path63.join(localSwarmDir, "knowledge.jsonl");
|
|
31521
31674
|
if (!existsSync40(sharedPath))
|
|
31522
31675
|
return 0;
|
|
31523
31676
|
const sharedEntries = await readKnowledge(sharedPath);
|
|
@@ -31552,7 +31705,7 @@ async function handleUnlinkCommand(directory, args) {
|
|
|
31552
31705
|
let copied = 0;
|
|
31553
31706
|
if (copyBack) {
|
|
31554
31707
|
try {
|
|
31555
|
-
copied = await copySharedKnowledgeToLocal(linkDir,
|
|
31708
|
+
copied = await copySharedKnowledgeToLocal(linkDir, path63.join(directory, ".swarm"));
|
|
31556
31709
|
} catch (error2) {
|
|
31557
31710
|
return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
|
|
31558
31711
|
}
|
|
@@ -31714,7 +31867,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
31714
31867
|
async function handleHelpCommand(ctx) {
|
|
31715
31868
|
const targetCommand = ctx.args.join(" ");
|
|
31716
31869
|
if (!targetCommand) {
|
|
31717
|
-
const { buildHelpText } = await import("./index-
|
|
31870
|
+
const { buildHelpText } = await import("./index-nvmy7xmj.js");
|
|
31718
31871
|
return buildHelpText();
|
|
31719
31872
|
}
|
|
31720
31873
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -31723,7 +31876,7 @@ async function handleHelpCommand(ctx) {
|
|
|
31723
31876
|
return _internals46.buildDetailedHelp(resolved.key, resolved.entry);
|
|
31724
31877
|
}
|
|
31725
31878
|
const similar = _internals46.findSimilarCommands(targetCommand);
|
|
31726
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
31879
|
+
const { buildHelpText: fullHelp } = await import("./index-nvmy7xmj.js");
|
|
31727
31880
|
if (similar.length > 0) {
|
|
31728
31881
|
return `Command '/swarm ${targetCommand}' not found.
|
|
31729
31882
|
|
|
@@ -31856,7 +32009,7 @@ var COMMAND_REGISTRY = {
|
|
|
31856
32009
|
},
|
|
31857
32010
|
"guardrail explain": {
|
|
31858
32011
|
handler: async (ctx) => {
|
|
31859
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
32012
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-hjz1k6w0.js");
|
|
31860
32013
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
31861
32014
|
},
|
|
31862
32015
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -31866,7 +32019,7 @@ var COMMAND_REGISTRY = {
|
|
|
31866
32019
|
},
|
|
31867
32020
|
"guardrail-log": {
|
|
31868
32021
|
handler: async (ctx) => {
|
|
31869
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
32022
|
+
const { handleGuardrailLog } = await import("./guardrail-log-5240bawg.js");
|
|
31870
32023
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
31871
32024
|
},
|
|
31872
32025
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -32646,24 +32799,24 @@ function validateAliases() {
|
|
|
32646
32799
|
continue;
|
|
32647
32800
|
}
|
|
32648
32801
|
const visited = new Set;
|
|
32649
|
-
const
|
|
32802
|
+
const path64 = [];
|
|
32650
32803
|
let current = target;
|
|
32651
32804
|
while (current) {
|
|
32652
32805
|
const currentEntry = COMMAND_REGISTRY[current];
|
|
32653
32806
|
if (!currentEntry)
|
|
32654
32807
|
break;
|
|
32655
32808
|
if (visited.has(current)) {
|
|
32656
|
-
const cycleStart =
|
|
32809
|
+
const cycleStart = path64.indexOf(current);
|
|
32657
32810
|
const fullChain = [
|
|
32658
32811
|
name,
|
|
32659
|
-
...
|
|
32812
|
+
...path64.slice(0, cycleStart > 0 ? cycleStart : path64.length),
|
|
32660
32813
|
current
|
|
32661
32814
|
].join(" \u2192 ");
|
|
32662
32815
|
errors.push(`Circular alias detected: ${fullChain}`);
|
|
32663
32816
|
break;
|
|
32664
32817
|
}
|
|
32665
32818
|
visited.add(current);
|
|
32666
|
-
|
|
32819
|
+
path64.push(current);
|
|
32667
32820
|
current = currentEntry.aliasOf || "";
|
|
32668
32821
|
}
|
|
32669
32822
|
}
|
|
@@ -34002,7 +34155,7 @@ init_logger();
|
|
|
34002
34155
|
|
|
34003
34156
|
// src/hooks/guardrails/destructive-command.ts
|
|
34004
34157
|
import * as fsSync3 from "fs";
|
|
34005
|
-
import * as
|
|
34158
|
+
import * as path64 from "path";
|
|
34006
34159
|
var DC_MAX_UNWRAP_DEPTH = 5;
|
|
34007
34160
|
var DC_SAFE_TARGETS = new Set([
|
|
34008
34161
|
"node_modules",
|
|
@@ -34166,16 +34319,16 @@ function dcIsRemotePath(p) {
|
|
|
34166
34319
|
return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
|
|
34167
34320
|
}
|
|
34168
34321
|
function dcLstatAncestorWalk(targetPath, cwd) {
|
|
34169
|
-
const normalizedTarget =
|
|
34170
|
-
const normalizedCwd =
|
|
34322
|
+
const normalizedTarget = path64.resolve(cwd, targetPath);
|
|
34323
|
+
const normalizedCwd = path64.resolve(cwd);
|
|
34171
34324
|
const ancestors = [];
|
|
34172
34325
|
let current = normalizedTarget;
|
|
34173
34326
|
while (true) {
|
|
34174
34327
|
ancestors.push(current);
|
|
34175
|
-
const parent =
|
|
34328
|
+
const parent = path64.dirname(current);
|
|
34176
34329
|
if (parent === current)
|
|
34177
34330
|
break;
|
|
34178
|
-
const rel =
|
|
34331
|
+
const rel = path64.relative(normalizedCwd, current);
|
|
34179
34332
|
if (rel === "" || rel.startsWith(".."))
|
|
34180
34333
|
break;
|
|
34181
34334
|
current = parent;
|
|
@@ -34214,14 +34367,14 @@ function dcValidateTargets(targets, cwd) {
|
|
|
34214
34367
|
const lstatBlock = dcLstatAncestorWalk(t, cwd);
|
|
34215
34368
|
if (lstatBlock)
|
|
34216
34369
|
return lstatBlock;
|
|
34217
|
-
const
|
|
34218
|
-
if (t ===
|
|
34370
|
+
const basename13 = path64.basename(t);
|
|
34371
|
+
if (t === basename13 && DC_SAFE_TARGETS.has(t)) {
|
|
34219
34372
|
continue;
|
|
34220
34373
|
}
|
|
34221
34374
|
if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
|
|
34222
34375
|
return `BLOCKED: Destructive command targets filesystem root "${t}"`;
|
|
34223
34376
|
}
|
|
34224
|
-
if (
|
|
34377
|
+
if (path64.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
|
|
34225
34378
|
for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
|
|
34226
34379
|
if (t.startsWith(blocked)) {
|
|
34227
34380
|
return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
|
|
@@ -34236,9 +34389,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34236
34389
|
if (mklinkMatch) {
|
|
34237
34390
|
const target = mklinkMatch[2].trim();
|
|
34238
34391
|
if (!dcHasUnresolvableVars(target)) {
|
|
34239
|
-
const resolved =
|
|
34240
|
-
const rel =
|
|
34241
|
-
if (rel.startsWith("..") ||
|
|
34392
|
+
const resolved = path64.resolve(cwd, target);
|
|
34393
|
+
const rel = path64.relative(cwd, resolved);
|
|
34394
|
+
if (rel.startsWith("..") || path64.isAbsolute(rel)) {
|
|
34242
34395
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
|
|
34243
34396
|
}
|
|
34244
34397
|
}
|
|
@@ -34250,9 +34403,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34250
34403
|
if (newItemMatch) {
|
|
34251
34404
|
const target = newItemMatch[1].trim();
|
|
34252
34405
|
if (!dcHasUnresolvableVars(target)) {
|
|
34253
|
-
const resolved =
|
|
34254
|
-
const rel =
|
|
34255
|
-
if (rel.startsWith("..") ||
|
|
34406
|
+
const resolved = path64.resolve(cwd, target);
|
|
34407
|
+
const rel = path64.relative(cwd, resolved);
|
|
34408
|
+
if (rel.startsWith("..") || path64.isAbsolute(rel)) {
|
|
34256
34409
|
return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
|
|
34257
34410
|
}
|
|
34258
34411
|
}
|
|
@@ -34262,9 +34415,9 @@ function dcCheckJunctionCreation(segment, cwd) {
|
|
|
34262
34415
|
if (lnMatch) {
|
|
34263
34416
|
const target = lnMatch[1].trim();
|
|
34264
34417
|
if (!dcHasUnresolvableVars(target)) {
|
|
34265
|
-
const resolved =
|
|
34266
|
-
const rel =
|
|
34267
|
-
if (rel.startsWith("..") ||
|
|
34418
|
+
const resolved = path64.resolve(cwd, target);
|
|
34419
|
+
const rel = path64.relative(cwd, resolved);
|
|
34420
|
+
if (rel.startsWith("..") || path64.isAbsolute(rel)) {
|
|
34268
34421
|
return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
|
|
34269
34422
|
}
|
|
34270
34423
|
}
|
|
@@ -34635,10 +34788,10 @@ function classifySwarmCommandChatFallbackUse(resolved) {
|
|
|
34635
34788
|
init_executor();
|
|
34636
34789
|
|
|
34637
34790
|
// src/hooks/shell-write-detect.ts
|
|
34638
|
-
import * as
|
|
34791
|
+
import * as path65 from "path";
|
|
34639
34792
|
import parse from "bash-parser";
|
|
34640
|
-
function buildDedupeKey(category, operator,
|
|
34641
|
-
return `${category}|${operator}|${
|
|
34793
|
+
function buildDedupeKey(category, operator, path66) {
|
|
34794
|
+
return `${category}|${operator}|${path66 ?? "null"}`;
|
|
34642
34795
|
}
|
|
34643
34796
|
var REDIRECT_WRITE_TOKENS = new Set([
|
|
34644
34797
|
"GREAT",
|
|
@@ -34698,16 +34851,16 @@ function detectProcessSubstitutionWrites(command) {
|
|
|
34698
34851
|
results.push(builtinResult);
|
|
34699
34852
|
const appendMatch = stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);
|
|
34700
34853
|
if (appendMatch) {
|
|
34701
|
-
const
|
|
34702
|
-
if (
|
|
34703
|
-
results.push({ category: "redirect", operator: ">>", path:
|
|
34854
|
+
const path66 = appendMatch[3];
|
|
34855
|
+
if (path66 && !isNullDevice(path66)) {
|
|
34856
|
+
results.push({ category: "redirect", operator: ">>", path: path66 });
|
|
34704
34857
|
}
|
|
34705
34858
|
} else {
|
|
34706
34859
|
const writeMatch = stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);
|
|
34707
34860
|
if (writeMatch) {
|
|
34708
|
-
const
|
|
34709
|
-
if (
|
|
34710
|
-
results.push({ category: "redirect", operator: ">", path:
|
|
34861
|
+
const path66 = writeMatch[3];
|
|
34862
|
+
if (path66 && !isNullDevice(path66)) {
|
|
34863
|
+
results.push({ category: "redirect", operator: ">", path: path66 });
|
|
34711
34864
|
}
|
|
34712
34865
|
}
|
|
34713
34866
|
}
|
|
@@ -34881,8 +35034,8 @@ function extractRedirectPath(fileNode) {
|
|
|
34881
35034
|
return null;
|
|
34882
35035
|
return text;
|
|
34883
35036
|
}
|
|
34884
|
-
function isNullDevice(
|
|
34885
|
-
return
|
|
35037
|
+
function isNullDevice(path66) {
|
|
35038
|
+
return path66 === "/dev/null" || path66 === "/dev/zero" || path66 === "/dev/urandom";
|
|
34886
35039
|
}
|
|
34887
35040
|
function isNumeric(s) {
|
|
34888
35041
|
return /^\d+$/.test(s);
|
|
@@ -34902,12 +35055,12 @@ function detectRedirects(cmd) {
|
|
|
34902
35055
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
34903
35056
|
continue;
|
|
34904
35057
|
const fileNode = r.file;
|
|
34905
|
-
const
|
|
35058
|
+
const path66 = extractRedirectPath(fileNode);
|
|
34906
35059
|
const opLabel = operatorLabel(opNode);
|
|
34907
35060
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
34908
|
-
results.push({ category: "redirect", operator: opLabel, path:
|
|
35061
|
+
results.push({ category: "redirect", operator: opLabel, path: path66 });
|
|
34909
35062
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
34910
|
-
results.push({ category: "here_doc", operator: opLabel, path:
|
|
35063
|
+
results.push({ category: "here_doc", operator: opLabel, path: path66 });
|
|
34911
35064
|
}
|
|
34912
35065
|
}
|
|
34913
35066
|
return results;
|
|
@@ -34950,9 +35103,9 @@ function detectBuiltinWrites(cmd) {
|
|
|
34950
35103
|
const suffixWords2 = getSuffixWords(cmd);
|
|
34951
35104
|
for (const word of suffixWords2) {
|
|
34952
35105
|
if (word.startsWith("of=")) {
|
|
34953
|
-
const
|
|
34954
|
-
if (
|
|
34955
|
-
results.push({ category: "builtin_write", operator: "dd of=", path:
|
|
35106
|
+
const path66 = word.slice(3);
|
|
35107
|
+
if (path66 && !isNullDevice(path66)) {
|
|
35108
|
+
results.push({ category: "builtin_write", operator: "dd of=", path: path66 });
|
|
34956
35109
|
}
|
|
34957
35110
|
}
|
|
34958
35111
|
}
|
|
@@ -35071,12 +35224,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35071
35224
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35072
35225
|
const word = suffixWords[i];
|
|
35073
35226
|
if (word === "-o" && i + 1 < suffixWords.length) {
|
|
35074
|
-
const
|
|
35075
|
-
if (!
|
|
35227
|
+
const path66 = suffixWords[i + 1];
|
|
35228
|
+
if (!path66.startsWith("-")) {
|
|
35076
35229
|
results.push({
|
|
35077
35230
|
category: "network_download",
|
|
35078
35231
|
operator: "curl -o",
|
|
35079
|
-
path:
|
|
35232
|
+
path: path66
|
|
35080
35233
|
});
|
|
35081
35234
|
}
|
|
35082
35235
|
} else if (word.startsWith("-o") && word.length > 2) {
|
|
@@ -35091,12 +35244,12 @@ function detectNetworkDownloaders(cmd) {
|
|
|
35091
35244
|
for (let i = 0;i < suffixWords.length; i++) {
|
|
35092
35245
|
const word = suffixWords[i];
|
|
35093
35246
|
if (word === "-O" && i + 1 < suffixWords.length) {
|
|
35094
|
-
const
|
|
35095
|
-
if (!
|
|
35247
|
+
const path66 = suffixWords[i + 1];
|
|
35248
|
+
if (!path66.startsWith("-")) {
|
|
35096
35249
|
results.push({
|
|
35097
35250
|
category: "network_download",
|
|
35098
35251
|
operator: "wget -O",
|
|
35099
|
-
path:
|
|
35252
|
+
path: path66
|
|
35100
35253
|
});
|
|
35101
35254
|
}
|
|
35102
35255
|
} else if (word.startsWith("-O") && word.length > 2) {
|
|
@@ -35205,9 +35358,9 @@ function detectGitDestructive(cmd) {
|
|
|
35205
35358
|
if (first === "checkout") {
|
|
35206
35359
|
const dashDashIdx = suffixWords.indexOf("--");
|
|
35207
35360
|
if (dashDashIdx !== -1 && dashDashIdx + 1 < suffixWords.length) {
|
|
35208
|
-
const
|
|
35209
|
-
const op =
|
|
35210
|
-
results.push({ category: "git_destructive", operator: op, path:
|
|
35361
|
+
const path66 = suffixWords[dashDashIdx + 1];
|
|
35362
|
+
const op = path66 === "." ? "git checkout -- ." : "git checkout --";
|
|
35363
|
+
results.push({ category: "git_destructive", operator: op, path: path66 });
|
|
35211
35364
|
}
|
|
35212
35365
|
} else if (first === "restore") {
|
|
35213
35366
|
const hasHard = suffixWords.some((w) => w === "--hard" || w === "-H" || w.startsWith("-") && w.includes("H"));
|
|
@@ -35327,10 +35480,10 @@ function detectPowerShellWrites(command) {
|
|
|
35327
35480
|
if (redirectMatch) {
|
|
35328
35481
|
const beforeRedirect = redirectMatch[1];
|
|
35329
35482
|
const op = redirectMatch[2];
|
|
35330
|
-
const
|
|
35483
|
+
const path66 = redirectMatch[3];
|
|
35331
35484
|
const fdRedirectPattern = /\d>\s*$|\s\d>&$/;
|
|
35332
35485
|
if (!fdRedirectPattern.test(`${beforeRedirect} ${op}`)) {
|
|
35333
|
-
results.push({ category: "redirect", operator: op, path:
|
|
35486
|
+
results.push({ category: "redirect", operator: op, path: path66 });
|
|
35334
35487
|
}
|
|
35335
35488
|
}
|
|
35336
35489
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35343,12 +35496,12 @@ function detectPowerShellWrites(command) {
|
|
|
35343
35496
|
}
|
|
35344
35497
|
const iwrMatch = trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);
|
|
35345
35498
|
if (iwrMatch) {
|
|
35346
|
-
const
|
|
35347
|
-
if (
|
|
35499
|
+
const path66 = iwrMatch[1] || iwrMatch[2];
|
|
35500
|
+
if (path66) {
|
|
35348
35501
|
results.push({
|
|
35349
35502
|
category: "network_download",
|
|
35350
35503
|
operator: "Invoke-WebRequest -OutFile",
|
|
35351
|
-
path:
|
|
35504
|
+
path: path66
|
|
35352
35505
|
});
|
|
35353
35506
|
}
|
|
35354
35507
|
}
|
|
@@ -35360,15 +35513,15 @@ function detectPowerShellWrites(command) {
|
|
|
35360
35513
|
const rest = cmd.slice(cmdletMatch[0].length).trim();
|
|
35361
35514
|
const pathFlagMatch = rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+("([^"]+)"|'([^']+)'|(\S+))/i);
|
|
35362
35515
|
if (pathFlagMatch) {
|
|
35363
|
-
const
|
|
35364
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35516
|
+
const path66 = pathFlagMatch[2] ?? pathFlagMatch[3] ?? pathFlagMatch[4] ?? "";
|
|
35517
|
+
return { category: "redirect", operator: cmdletName, path: path66 };
|
|
35365
35518
|
}
|
|
35366
35519
|
const tokens = rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35367
35520
|
for (const token of tokens) {
|
|
35368
35521
|
if (token.startsWith("-"))
|
|
35369
35522
|
continue;
|
|
35370
|
-
const
|
|
35371
|
-
return { category: "redirect", operator: cmdletName, path:
|
|
35523
|
+
const path66 = token.replace(/^["']|["']$/g, "");
|
|
35524
|
+
return { category: "redirect", operator: cmdletName, path: path66 };
|
|
35372
35525
|
}
|
|
35373
35526
|
return null;
|
|
35374
35527
|
}
|
|
@@ -35384,9 +35537,9 @@ function detectPowerShellWrites(command) {
|
|
|
35384
35537
|
for (const token of tokens) {
|
|
35385
35538
|
if (token.startsWith("-"))
|
|
35386
35539
|
continue;
|
|
35387
|
-
const
|
|
35388
|
-
if (
|
|
35389
|
-
results.push({ category: "redirect", operator: cmdletName, path:
|
|
35540
|
+
const path66 = token.replace(/^["']|["']$/g, "");
|
|
35541
|
+
if (path66) {
|
|
35542
|
+
results.push({ category: "redirect", operator: cmdletName, path: path66 });
|
|
35390
35543
|
break;
|
|
35391
35544
|
}
|
|
35392
35545
|
}
|
|
@@ -35399,8 +35552,8 @@ function detectPowerShellWrites(command) {
|
|
|
35399
35552
|
const rest = cmd.slice(opMatch[0].length).trim();
|
|
35400
35553
|
const destFlagMatch = rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35401
35554
|
if (destFlagMatch) {
|
|
35402
|
-
const
|
|
35403
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35555
|
+
const path66 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
35556
|
+
return { category: "builtin_write", operator: cmdletName, path: path66 };
|
|
35404
35557
|
}
|
|
35405
35558
|
const tokens = [];
|
|
35406
35559
|
const flagTakingValue = new Set([
|
|
@@ -35439,11 +35592,11 @@ function detectPowerShellWrites(command) {
|
|
|
35439
35592
|
}
|
|
35440
35593
|
}
|
|
35441
35594
|
if (tokens.length >= 2) {
|
|
35442
|
-
const
|
|
35443
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35595
|
+
const path66 = tokens[tokens.length - 1].replace(/^["']|["']$/g, "");
|
|
35596
|
+
return { category: "builtin_write", operator: cmdletName, path: path66 };
|
|
35444
35597
|
} else if (tokens.length === 1) {
|
|
35445
|
-
const
|
|
35446
|
-
return { category: "builtin_write", operator: cmdletName, path:
|
|
35598
|
+
const path66 = tokens[0].replace(/^["']|["']$/g, "");
|
|
35599
|
+
return { category: "builtin_write", operator: cmdletName, path: path66 };
|
|
35447
35600
|
}
|
|
35448
35601
|
return null;
|
|
35449
35602
|
}
|
|
@@ -35457,14 +35610,14 @@ function detectPowerShellWrites(command) {
|
|
|
35457
35610
|
const afterCmdlet = pipeFileOpMatch[2].trim();
|
|
35458
35611
|
const destFlagMatch = afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
|
|
35459
35612
|
if (destFlagMatch) {
|
|
35460
|
-
const
|
|
35461
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
35613
|
+
const path66 = destFlagMatch[1].replace(/^["']|["']$/g, "");
|
|
35614
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path66 });
|
|
35462
35615
|
} else {
|
|
35463
35616
|
const tokens = afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
|
|
35464
35617
|
const nonFlagTokens = tokens.filter((t) => !t.startsWith("-") && t.length > 0);
|
|
35465
35618
|
if (nonFlagTokens.length > 0) {
|
|
35466
|
-
const
|
|
35467
|
-
results.push({ category: "builtin_write", operator: cmdletName, path:
|
|
35619
|
+
const path66 = nonFlagTokens[nonFlagTokens.length - 1].replace(/^["']|["']$/g, "");
|
|
35620
|
+
results.push({ category: "builtin_write", operator: cmdletName, path: path66 });
|
|
35468
35621
|
}
|
|
35469
35622
|
}
|
|
35470
35623
|
}
|
|
@@ -35517,10 +35670,10 @@ function detectCmdWrites(command) {
|
|
|
35517
35670
|
if (redirectMatch) {
|
|
35518
35671
|
const beforeRedirect = redirectMatch[1];
|
|
35519
35672
|
const op = redirectMatch[2];
|
|
35520
|
-
const
|
|
35673
|
+
const path66 = redirectMatch[3];
|
|
35521
35674
|
const fdRedirectPattern = /\d>&?$/;
|
|
35522
35675
|
if (!fdRedirectPattern.test(beforeRedirect)) {
|
|
35523
|
-
results.push({ category: "redirect", operator: op, path:
|
|
35676
|
+
results.push({ category: "redirect", operator: op, path: path66 });
|
|
35524
35677
|
}
|
|
35525
35678
|
}
|
|
35526
35679
|
const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
|
|
@@ -35578,8 +35731,8 @@ function detectCmdWrites(command) {
|
|
|
35578
35731
|
const rawTokens = rest.match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g) ?? [];
|
|
35579
35732
|
const tokens = rawTokens.filter((t) => !t.startsWith("/"));
|
|
35580
35733
|
if (tokens.length > 0) {
|
|
35581
|
-
const
|
|
35582
|
-
return { category: "builtin_write", operator: "del", path:
|
|
35734
|
+
const path66 = tokens[0].replace(/^["']|["']$/g, "");
|
|
35735
|
+
return { category: "builtin_write", operator: "del", path: path66 };
|
|
35583
35736
|
}
|
|
35584
35737
|
return null;
|
|
35585
35738
|
}
|
|
@@ -35589,16 +35742,16 @@ function detectCmdWrites(command) {
|
|
|
35589
35742
|
}
|
|
35590
35743
|
const rdMatch = innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);
|
|
35591
35744
|
if (rdMatch) {
|
|
35592
|
-
const
|
|
35593
|
-
if (!
|
|
35594
|
-
results.push({ category: "builtin_write", operator: "rd", path:
|
|
35745
|
+
const path66 = rdMatch[1].replace(/^["']|["']$/g, "");
|
|
35746
|
+
if (!path66.startsWith("/")) {
|
|
35747
|
+
results.push({ category: "builtin_write", operator: "rd", path: path66 });
|
|
35595
35748
|
}
|
|
35596
35749
|
}
|
|
35597
35750
|
const mdMatch = trimmed.match(/^md\s+(\S+)/i);
|
|
35598
35751
|
if (mdMatch) {
|
|
35599
|
-
const
|
|
35600
|
-
if (!
|
|
35601
|
-
results.push({ category: "builtin_write", operator: "md", path:
|
|
35752
|
+
const path66 = mdMatch[1].replace(/^["']|["']$/g, "");
|
|
35753
|
+
if (!path66.startsWith("/")) {
|
|
35754
|
+
results.push({ category: "builtin_write", operator: "md", path: path66 });
|
|
35602
35755
|
}
|
|
35603
35756
|
}
|
|
35604
35757
|
const echoMatch = trimmed.match(/^echo\s+(\S+.*?)\s+((?:>){1,2})\s*(\S+)$/i);
|
|
@@ -35714,10 +35867,10 @@ function resolvePath(pathText, cwd) {
|
|
|
35714
35867
|
return null;
|
|
35715
35868
|
const isWindowsPath = /^[a-zA-Z]:[\\\\/]/.test(cwd) || cwd.includes("\\");
|
|
35716
35869
|
if (isWindowsPath) {
|
|
35717
|
-
return
|
|
35870
|
+
return path65.win32.resolve(cwd, pathText);
|
|
35718
35871
|
}
|
|
35719
|
-
const normalizedRelativeWindowsPath = !
|
|
35720
|
-
return
|
|
35872
|
+
const normalizedRelativeWindowsPath = !path65.posix.isAbsolute(pathText) && !/^[a-zA-Z]:[\\/]/.test(pathText) ? pathText.replace(/\\/g, "/") : pathText;
|
|
35873
|
+
return path65.posix.resolve(cwd, normalizedRelativeWindowsPath);
|
|
35721
35874
|
}
|
|
35722
35875
|
function getCdTarget(cmd) {
|
|
35723
35876
|
if (!cmd || typeof cmd !== "object")
|
|
@@ -35784,7 +35937,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
35784
35937
|
for (const cmd of node.commands) {
|
|
35785
35938
|
const cdTarget = getCdTarget(cmd);
|
|
35786
35939
|
if (cdTarget) {
|
|
35787
|
-
currentStack[0] =
|
|
35940
|
+
currentStack[0] = path65.posix.resolve(currentStack[0] ?? "/", cdTarget);
|
|
35788
35941
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
35789
35942
|
} else {
|
|
35790
35943
|
collectWritesWithNodes(cmd, out, currentStack);
|
|
@@ -35830,7 +35983,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
|
|
|
35830
35983
|
const effectiveCwd = cwdStack[0] ?? "/";
|
|
35831
35984
|
const cdTarget = getCdTarget(node);
|
|
35832
35985
|
if (cdTarget) {
|
|
35833
|
-
cwdStack[0] =
|
|
35986
|
+
cwdStack[0] = path65.posix.resolve(cwdStack[0] ?? "/", cdTarget);
|
|
35834
35987
|
return;
|
|
35835
35988
|
}
|
|
35836
35989
|
const writesFromRedirs = getWritesFromCommandRedirs(node, effectiveCwd);
|
|
@@ -35876,12 +36029,12 @@ function getWritesFromRedirectNode(redirect, _context) {
|
|
|
35876
36029
|
if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
|
|
35877
36030
|
return [];
|
|
35878
36031
|
const fileNode = r.file;
|
|
35879
|
-
const
|
|
36032
|
+
const path66 = extractRedirectPath(fileNode);
|
|
35880
36033
|
const opLabel = operatorLabel(opNode);
|
|
35881
36034
|
if (REDIRECT_WRITE_TOKENS.has(opType)) {
|
|
35882
|
-
return [{ category: "redirect", operator: opLabel, path:
|
|
36035
|
+
return [{ category: "redirect", operator: opLabel, path: path66 }];
|
|
35883
36036
|
} else if (REDIRECT_HERE_TOKENS.has(opType)) {
|
|
35884
|
-
return [{ category: "here_doc", operator: opLabel, path:
|
|
36037
|
+
return [{ category: "here_doc", operator: opLabel, path: path66 }];
|
|
35885
36038
|
}
|
|
35886
36039
|
return [];
|
|
35887
36040
|
}
|
|
@@ -36635,7 +36788,7 @@ function evidenceToWorkflowState(evidence) {
|
|
|
36635
36788
|
}
|
|
36636
36789
|
async function readPlanFromDisk(directory) {
|
|
36637
36790
|
try {
|
|
36638
|
-
const planPath =
|
|
36791
|
+
const planPath = path66.join(directory, ".swarm", "plan.json");
|
|
36639
36792
|
const content = await fs30.readFile(planPath, "utf-8");
|
|
36640
36793
|
const parsed = JSON.parse(content);
|
|
36641
36794
|
return PlanSchema.parse(parsed);
|
|
@@ -36646,7 +36799,7 @@ async function readPlanFromDisk(directory) {
|
|
|
36646
36799
|
async function readGateEvidenceFromDisk(directory) {
|
|
36647
36800
|
const evidenceMap = new Map;
|
|
36648
36801
|
try {
|
|
36649
|
-
const evidenceDir =
|
|
36802
|
+
const evidenceDir = path66.join(directory, ".swarm", "evidence");
|
|
36650
36803
|
const entries = await fs30.readdir(evidenceDir, { withFileTypes: true });
|
|
36651
36804
|
for (const entry of entries) {
|
|
36652
36805
|
if (!entry.isFile() || !entry.name.endsWith(".json")) {
|
|
@@ -36657,7 +36810,7 @@ async function readGateEvidenceFromDisk(directory) {
|
|
|
36657
36810
|
continue;
|
|
36658
36811
|
}
|
|
36659
36812
|
try {
|
|
36660
|
-
const filePath =
|
|
36813
|
+
const filePath = path66.join(evidenceDir, entry.name);
|
|
36661
36814
|
const content = await fs30.readFile(filePath, "utf-8");
|
|
36662
36815
|
const parsed = JSON.parse(content);
|
|
36663
36816
|
if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {
|