opencode-swarm 7.114.7 → 7.114.9
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-fix-monitor/SKILL.md +8 -13
- package/.opencode/skills/commit-pr/SKILL.md +4 -0
- package/.opencode/skills/engineering-conventions/SKILL.md +33 -0
- package/.opencode/skills/execute/SKILL.md +2 -0
- package/.opencode/skills/swarm-ci-monitor/SKILL.md +5 -0
- package/.opencode/skills/swarm-pr-feedback/SKILL.md +2 -0
- package/.opencode/skills/writing-tests/SKILL.md +2 -0
- package/README.md +16 -14
- package/dist/agents/template.d.ts +40 -20
- package/dist/cli/{curator-qshyr2tc.js → curator-5xt89z05.js} +7 -7
- package/dist/cli/{curator-llm-factory-2xgznxyw.js → curator-llm-factory-pnhvf3s3.js} +7 -7
- package/dist/cli/{evidence-summary-service-8g594znj.js → evidence-summary-service-fehwj116.js} +1 -1
- package/dist/cli/{guardrail-explain-4t8fnysh.js → guardrail-explain-7aztgtyh.js} +8 -8
- package/dist/cli/{hive-promoter-5ngbmnrw.js → hive-promoter-q899q2m6.js} +7 -7
- package/dist/cli/{index-z01r5483.js → index-54sevh81.js} +8 -8
- package/dist/cli/{index-7stsmndb.js → index-6f6y2rbp.js} +3 -3
- package/dist/cli/{index-kjbfry6m.js → index-8f2270hc.js} +1 -1
- package/dist/cli/{index-gmjrwz34.js → index-m9m7p49w.js} +1 -1
- package/dist/cli/{index-qrnhvhmg.js → index-n18yy0z1.js} +26 -2
- package/dist/cli/{index-91qesget.js → index-rk6qhyng.js} +2 -2
- package/dist/cli/{index-6ctejje2.js → index-typ408f4.js} +710 -630
- package/dist/cli/{index-vjvdvjd3.js → index-x12hvfpf.js} +3 -3
- package/dist/cli/{index-f6y341yk.js → index-yrrqs4b0.js} +82 -21
- package/dist/cli/index.d.ts +34 -0
- package/dist/cli/index.js +105 -28
- package/dist/cli/{knowledge-escalator-qn7ew687.js → knowledge-escalator-5gwp1ar8.js} +3 -3
- package/dist/cli/{knowledge-events-k2xsz5bh.js → knowledge-events-m304swh6.js} +1 -1
- package/dist/cli/{knowledge-store-ksa1dr2z.js → knowledge-store-9babt8rd.js} +1 -1
- package/dist/cli/{knowledge-validator-2knz0d2t.js → knowledge-validator-t9sym59g.js} +4 -2
- package/dist/cli/{skill-generator-w6qd9mde.js → skill-generator-tav44xpm.js} +4 -4
- package/dist/commands/ci-monitor.d.ts +18 -0
- package/dist/commands/registry.d.ts +8 -0
- package/dist/config/skill-mirrors.d.ts +22 -1
- package/dist/hooks/adversarial-detector.d.ts +6 -0
- package/dist/hooks/delegation-gate.d.ts +19 -0
- package/dist/hooks/guardrails/index.d.ts +2 -2
- package/dist/hooks/knowledge-validator.d.ts +22 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +194 -169
- package/dist/plan/ledger.d.ts +83 -20
- package/dist/types/delegation.d.ts +24 -0
- package/package.json +1 -1
- package/dist/graph/graph-builder.d.ts +0 -39
- package/dist/graph/graph-query.d.ts +0 -42
- package/dist/graph/graph-store.d.ts +0 -27
- package/dist/graph/import-extractor.d.ts +0 -44
- package/dist/graph/index.d.ts +0 -16
- package/dist/graph/symbol-extractor.d.ts +0 -17
- package/dist/graph/types.d.ts +0 -84
- package/dist/sandbox/win32/restricted-token-executor.d.ts +0 -9
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
savePlan,
|
|
69
69
|
transientBackoff,
|
|
70
70
|
validateProjectRoot
|
|
71
|
-
} from "./index-
|
|
71
|
+
} from "./index-yrrqs4b0.js";
|
|
72
72
|
import {
|
|
73
73
|
buildOpenSpecProjectionSync,
|
|
74
74
|
detectSpeckit,
|
|
@@ -111,7 +111,7 @@ import {
|
|
|
111
111
|
retireSkill,
|
|
112
112
|
selectCandidateEntries,
|
|
113
113
|
syncBundledProjectSkillsIfMissingAsync
|
|
114
|
-
} from "./index-
|
|
114
|
+
} from "./index-x12hvfpf.js";
|
|
115
115
|
import {
|
|
116
116
|
appendUnactionable,
|
|
117
117
|
quarantineEntry,
|
|
@@ -121,10 +121,10 @@ import {
|
|
|
121
121
|
validateActionability,
|
|
122
122
|
validateActionableFields,
|
|
123
123
|
validateLesson
|
|
124
|
-
} from "./index-
|
|
124
|
+
} from "./index-n18yy0z1.js";
|
|
125
125
|
import {
|
|
126
126
|
readRecentEscalations
|
|
127
|
-
} from "./index-
|
|
127
|
+
} from "./index-6f6y2rbp.js";
|
|
128
128
|
import {
|
|
129
129
|
effectiveRetrievalOutcomes,
|
|
130
130
|
readKnowledgeCounterRollups,
|
|
@@ -132,7 +132,7 @@ import {
|
|
|
132
132
|
recordHiveKnowledgeEvent,
|
|
133
133
|
recordKnowledgeEvent,
|
|
134
134
|
resolveKnowledgeEventsPath
|
|
135
|
-
} from "./index-
|
|
135
|
+
} from "./index-8f2270hc.js";
|
|
136
136
|
import {
|
|
137
137
|
appendKnowledge,
|
|
138
138
|
appendRejectedLesson,
|
|
@@ -156,7 +156,7 @@ import {
|
|
|
156
156
|
rewriteKnowledge,
|
|
157
157
|
transactFile,
|
|
158
158
|
transactKnowledge
|
|
159
|
-
} from "./index-
|
|
159
|
+
} from "./index-rk6qhyng.js";
|
|
160
160
|
import {
|
|
161
161
|
KNOWLEDGE_SCHEMA_VERSION,
|
|
162
162
|
OUTCOME_BLOCK_THRESHOLD,
|
|
@@ -3064,50 +3064,60 @@ class SQLiteMemoryProvider {
|
|
|
3064
3064
|
mkdirSync4(path5.dirname(dbPath), { recursive: true });
|
|
3065
3065
|
const Db = loadDatabaseCtor2();
|
|
3066
3066
|
this.db = new Db(dbPath);
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3067
|
+
try {
|
|
3068
|
+
this.db.run("PRAGMA journal_mode = WAL;");
|
|
3069
|
+
this.db.run("PRAGMA synchronous = NORMAL;");
|
|
3070
|
+
const busyTimeoutMs = Math.min(60000, Math.max(0, Math.trunc(this.config.sqlite.busyTimeoutMs)));
|
|
3071
|
+
this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
|
|
3072
|
+
this.db.run("PRAGMA foreign_keys = ON;");
|
|
3073
|
+
this.runMigrations();
|
|
3074
|
+
this.backfillScopeKeys();
|
|
3075
|
+
this.backfillRecallRunIds();
|
|
3076
|
+
this.ftsAvailable = this.initializeFtsIndex();
|
|
3077
|
+
this.initializeVecExtension();
|
|
3078
|
+
if (this.config.embeddings.enabled && !this.embeddingProvider) {
|
|
3079
|
+
try {
|
|
3080
|
+
this.embeddingProvider = new LocalEmbeddingProvider({
|
|
3081
|
+
model: this.config.embeddings.model,
|
|
3082
|
+
dimension: this.config.embeddings.dimension,
|
|
3083
|
+
version: this.config.embeddings.version
|
|
3084
|
+
});
|
|
3085
|
+
} catch (err) {
|
|
3086
|
+
this.embeddingProvider = null;
|
|
3087
|
+
warn("Failed to construct embedding provider \u2014 dense retrieval disabled", {
|
|
3088
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3089
|
+
});
|
|
3090
|
+
}
|
|
3091
|
+
try {
|
|
3092
|
+
this.embeddingCache = new EmbeddingCache(this.config.embeddings.cacheSize);
|
|
3093
|
+
} catch (err) {
|
|
3094
|
+
this.embeddingCache = null;
|
|
3095
|
+
warn("Failed to construct embedding cache \u2014 recall works without cache", {
|
|
3096
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
3097
|
+
});
|
|
3098
|
+
}
|
|
3089
3099
|
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3100
|
+
this.lastAutomaticJsonlMigration = null;
|
|
3101
|
+
await this.migrateLegacyJsonlIfNeeded();
|
|
3102
|
+
const memoryLoad = this.loadMemories();
|
|
3103
|
+
const proposalLoad = this.loadProposals();
|
|
3104
|
+
this.memories = new Map(memoryLoad.records.map((record) => [record.id, record]));
|
|
3105
|
+
this.proposals = new Map(proposalLoad.records.map((proposal) => [proposal.id, proposal]));
|
|
3106
|
+
this.initialized = true;
|
|
3107
|
+
if (memoryLoad.invalidCount > 0) {
|
|
3108
|
+
await this.event("invalid_load", "memory_items", `${memoryLoad.invalidCount} invalid SQLite memory row(s) skipped`);
|
|
3097
3109
|
}
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
if (proposalLoad.invalidCount > 0) {
|
|
3110
|
-
await this.event("invalid_load", "memory_proposals", `${proposalLoad.invalidCount} invalid SQLite proposal row(s) skipped`);
|
|
3110
|
+
if (proposalLoad.invalidCount > 0) {
|
|
3111
|
+
await this.event("invalid_load", "memory_proposals", `${proposalLoad.invalidCount} invalid SQLite proposal row(s) skipped`);
|
|
3112
|
+
}
|
|
3113
|
+
} catch (err) {
|
|
3114
|
+
try {
|
|
3115
|
+
this.db?.close();
|
|
3116
|
+
} catch {}
|
|
3117
|
+
this.db = null;
|
|
3118
|
+
this.ftsAvailable = false;
|
|
3119
|
+
this.initialized = false;
|
|
3120
|
+
throw err;
|
|
3111
3121
|
}
|
|
3112
3122
|
}
|
|
3113
3123
|
async upsert(record) {
|
|
@@ -3132,7 +3142,20 @@ class SQLiteMemoryProvider {
|
|
|
3132
3142
|
}
|
|
3133
3143
|
async withTransaction(fn) {
|
|
3134
3144
|
const db = this.requireDb();
|
|
3135
|
-
|
|
3145
|
+
if (db.inTransaction) {
|
|
3146
|
+
return await fn({});
|
|
3147
|
+
}
|
|
3148
|
+
db.run("BEGIN IMMEDIATE");
|
|
3149
|
+
try {
|
|
3150
|
+
const result = await fn({});
|
|
3151
|
+
db.run("COMMIT");
|
|
3152
|
+
return result;
|
|
3153
|
+
} catch (err) {
|
|
3154
|
+
try {
|
|
3155
|
+
db.run("ROLLBACK");
|
|
3156
|
+
} catch {}
|
|
3157
|
+
throw err;
|
|
3158
|
+
}
|
|
3136
3159
|
}
|
|
3137
3160
|
async delete(id, reason) {
|
|
3138
3161
|
await this.initialize();
|
|
@@ -6403,6 +6426,294 @@ async function handleList2(directory) {
|
|
|
6403
6426
|
}
|
|
6404
6427
|
}
|
|
6405
6428
|
|
|
6429
|
+
// src/commands/_shared/url-security.ts
|
|
6430
|
+
import * as child_process2 from "child_process";
|
|
6431
|
+
var MAX_URL_LEN = 2048;
|
|
6432
|
+
var IPV4_PRIVATE = /^10\./;
|
|
6433
|
+
var IPV4_LOOPBACK = /^127\./;
|
|
6434
|
+
var IPV4_LINK_LOCAL = /^169\.254\./;
|
|
6435
|
+
var IPV4_PRIVATE_172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
|
|
6436
|
+
var IPV4_PRIVATE_192 = /^192\.168\./;
|
|
6437
|
+
var IPV4_ZERO_NETWORK = /^0\./;
|
|
6438
|
+
var IPV6_LINK_LOCAL = /^fe80:/i;
|
|
6439
|
+
var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
|
|
6440
|
+
var _internals7 = {
|
|
6441
|
+
spawnSync: (cmd, args, options) => {
|
|
6442
|
+
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
6443
|
+
return child_process2.spawnSync(cmd, args, {
|
|
6444
|
+
...options,
|
|
6445
|
+
env: mergedEnv
|
|
6446
|
+
});
|
|
6447
|
+
}
|
|
6448
|
+
};
|
|
6449
|
+
function sanitizeUrl(raw) {
|
|
6450
|
+
let urlStr = raw.trim();
|
|
6451
|
+
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
6452
|
+
const fragmentIdx = urlStr.indexOf("#");
|
|
6453
|
+
if (fragmentIdx !== -1) {
|
|
6454
|
+
urlStr = urlStr.slice(0, fragmentIdx);
|
|
6455
|
+
}
|
|
6456
|
+
const queryIdx = urlStr.indexOf("?");
|
|
6457
|
+
if (queryIdx !== -1) {
|
|
6458
|
+
urlStr = urlStr.slice(0, queryIdx);
|
|
6459
|
+
}
|
|
6460
|
+
urlStr = urlStr.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^@/]+@/, "https://");
|
|
6461
|
+
if (urlStr.length > MAX_URL_LEN) {
|
|
6462
|
+
urlStr = urlStr.slice(0, MAX_URL_LEN);
|
|
6463
|
+
}
|
|
6464
|
+
return urlStr.trim();
|
|
6465
|
+
}
|
|
6466
|
+
function sanitizeErrorEcho(raw, maxLength = 80) {
|
|
6467
|
+
let stripped = "";
|
|
6468
|
+
for (const ch of raw) {
|
|
6469
|
+
const cp = ch.codePointAt(0);
|
|
6470
|
+
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
6471
|
+
stripped += " ";
|
|
6472
|
+
continue;
|
|
6473
|
+
}
|
|
6474
|
+
stripped += ch;
|
|
6475
|
+
}
|
|
6476
|
+
const collapsed = stripped.replace(/\s+/g, " ").trim();
|
|
6477
|
+
if (collapsed.length <= maxLength)
|
|
6478
|
+
return collapsed;
|
|
6479
|
+
return `${collapsed.slice(0, maxLength)}\u2026`;
|
|
6480
|
+
}
|
|
6481
|
+
function containsControlCharacters(value) {
|
|
6482
|
+
for (const ch of value) {
|
|
6483
|
+
const cp = ch.codePointAt(0);
|
|
6484
|
+
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
6485
|
+
return true;
|
|
6486
|
+
}
|
|
6487
|
+
}
|
|
6488
|
+
return false;
|
|
6489
|
+
}
|
|
6490
|
+
function hasNonAsciiHostname(hostname) {
|
|
6491
|
+
for (const ch of hostname) {
|
|
6492
|
+
const cp = ch.codePointAt(0);
|
|
6493
|
+
if (cp !== undefined && cp > 127)
|
|
6494
|
+
return true;
|
|
6495
|
+
}
|
|
6496
|
+
return false;
|
|
6497
|
+
}
|
|
6498
|
+
function isIpv4MappedPrivateHost(inner) {
|
|
6499
|
+
if (IPV4_PRIVATE.test(inner) || IPV4_LOOPBACK.test(inner) || IPV4_LINK_LOCAL.test(inner) || IPV4_PRIVATE_172.test(inner) || IPV4_PRIVATE_192.test(inner) || IPV4_ZERO_NETWORK.test(inner)) {
|
|
6500
|
+
return true;
|
|
6501
|
+
}
|
|
6502
|
+
const firstSegment = inner.split(":", 1)[0];
|
|
6503
|
+
if (!firstSegment)
|
|
6504
|
+
return false;
|
|
6505
|
+
const firstWord = Number.parseInt(firstSegment, 16);
|
|
6506
|
+
if (!Number.isFinite(firstWord))
|
|
6507
|
+
return false;
|
|
6508
|
+
return firstWord >= 0 && firstWord <= 255 || firstWord >= 2560 && firstWord <= 2815 || firstWord >= 32512 && firstWord <= 32767 || firstWord === 43518 || firstWord >= 44048 && firstWord <= 44063 || firstWord === 49320;
|
|
6509
|
+
}
|
|
6510
|
+
function isPrivateHost(url) {
|
|
6511
|
+
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
6512
|
+
if (host === "localhost" || host === "::1" || host === "0.0.0.0" || IPV4_LOOPBACK.test(host) || IPV4_ZERO_NETWORK.test(host)) {
|
|
6513
|
+
return true;
|
|
6514
|
+
}
|
|
6515
|
+
if (host.startsWith("localhost") || host === "localhost.com") {
|
|
6516
|
+
return true;
|
|
6517
|
+
}
|
|
6518
|
+
if (IPV4_PRIVATE.test(host) || IPV4_LINK_LOCAL.test(host) || IPV4_PRIVATE_172.test(host) || IPV4_PRIVATE_192.test(host) || IPV6_LINK_LOCAL.test(host) || IPV6_UNIQUE_LOCAL.test(host)) {
|
|
6519
|
+
return true;
|
|
6520
|
+
}
|
|
6521
|
+
if (host.startsWith("::ffff:")) {
|
|
6522
|
+
const inner = host.slice(7);
|
|
6523
|
+
if (isIpv4MappedPrivateHost(inner)) {
|
|
6524
|
+
return true;
|
|
6525
|
+
}
|
|
6526
|
+
}
|
|
6527
|
+
return false;
|
|
6528
|
+
}
|
|
6529
|
+
function validateAndSanitizeGithubUrl(rawUrl, resource) {
|
|
6530
|
+
const sanitized = sanitizeUrl(rawUrl);
|
|
6531
|
+
if (!sanitized) {
|
|
6532
|
+
return { error: "Empty URL" };
|
|
6533
|
+
}
|
|
6534
|
+
if (!sanitized.startsWith("https://")) {
|
|
6535
|
+
return { error: "URL must use HTTPS scheme" };
|
|
6536
|
+
}
|
|
6537
|
+
try {
|
|
6538
|
+
const url = new URL(sanitized);
|
|
6539
|
+
if (hasNonAsciiHostname(url.hostname)) {
|
|
6540
|
+
return { error: "Non-ASCII hostnames are not allowed" };
|
|
6541
|
+
}
|
|
6542
|
+
if (isPrivateHost(url)) {
|
|
6543
|
+
return { error: "Private or localhost URLs are not allowed" };
|
|
6544
|
+
}
|
|
6545
|
+
const githubPattern = new RegExp(`^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/${resource}\\/([0-9]+)\\/?$`);
|
|
6546
|
+
if (!githubPattern.test(sanitized)) {
|
|
6547
|
+
return {
|
|
6548
|
+
error: resource === "issues" ? "URL must be a GitHub issue URL (https://github.com/owner/repo/issues/N)" : "URL must be a GitHub pull request URL (https://github.com/owner/repo/pull/N)"
|
|
6549
|
+
};
|
|
6550
|
+
}
|
|
6551
|
+
return { sanitized };
|
|
6552
|
+
} catch {
|
|
6553
|
+
return { error: "Invalid URL format" };
|
|
6554
|
+
}
|
|
6555
|
+
}
|
|
6556
|
+
function detectGitRemote(cwd, laneEnv) {
|
|
6557
|
+
try {
|
|
6558
|
+
const result = _internals7.spawnSync("git", ["remote", "get-url", "origin"], {
|
|
6559
|
+
encoding: "utf-8",
|
|
6560
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6561
|
+
timeout: 5000,
|
|
6562
|
+
...cwd ? { cwd } : {},
|
|
6563
|
+
envOverrides: laneEnv
|
|
6564
|
+
});
|
|
6565
|
+
if (result.status !== 0 || result.error) {
|
|
6566
|
+
return null;
|
|
6567
|
+
}
|
|
6568
|
+
const remoteUrl = (result.stdout ?? "").trim();
|
|
6569
|
+
return remoteUrl || null;
|
|
6570
|
+
} catch {
|
|
6571
|
+
return null;
|
|
6572
|
+
}
|
|
6573
|
+
}
|
|
6574
|
+
function parseGitRemoteUrl(remoteUrl) {
|
|
6575
|
+
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
6576
|
+
if (httpsMatch) {
|
|
6577
|
+
const owner = httpsMatch[1];
|
|
6578
|
+
const repo = httpsMatch[2].replace(/\.git$/, "");
|
|
6579
|
+
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
6580
|
+
return null;
|
|
6581
|
+
}
|
|
6582
|
+
return { owner, repo };
|
|
6583
|
+
}
|
|
6584
|
+
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
6585
|
+
if (sshMatch) {
|
|
6586
|
+
const owner = sshMatch[1];
|
|
6587
|
+
const repo = sshMatch[2].replace(/\.git$/, "");
|
|
6588
|
+
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
6589
|
+
return null;
|
|
6590
|
+
}
|
|
6591
|
+
return { owner, repo };
|
|
6592
|
+
}
|
|
6593
|
+
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
6594
|
+
if (pathMatch) {
|
|
6595
|
+
const owner = pathMatch[1];
|
|
6596
|
+
const repo = pathMatch[2].replace(/\.git$/, "");
|
|
6597
|
+
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
6598
|
+
return null;
|
|
6599
|
+
}
|
|
6600
|
+
return { owner, repo };
|
|
6601
|
+
}
|
|
6602
|
+
return null;
|
|
6603
|
+
}
|
|
6604
|
+
|
|
6605
|
+
// src/commands/pr-ref.ts
|
|
6606
|
+
var MAX_INSTRUCTIONS_LEN = 1000;
|
|
6607
|
+
function sanitizeInstructions(raw) {
|
|
6608
|
+
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
6609
|
+
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
6610
|
+
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
6611
|
+
if (normalized.length <= MAX_INSTRUCTIONS_LEN)
|
|
6612
|
+
return normalized;
|
|
6613
|
+
return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}\u2026`;
|
|
6614
|
+
}
|
|
6615
|
+
function validateAndSanitizeUrl(rawUrl) {
|
|
6616
|
+
return validateAndSanitizeGithubUrl(rawUrl, "pull");
|
|
6617
|
+
}
|
|
6618
|
+
function parsePrRef(input, cwd) {
|
|
6619
|
+
const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
|
|
6620
|
+
if (urlMatch) {
|
|
6621
|
+
if (containsControlCharacters(urlMatch[1]) || containsControlCharacters(urlMatch[2])) {
|
|
6622
|
+
return null;
|
|
6623
|
+
}
|
|
6624
|
+
return {
|
|
6625
|
+
owner: urlMatch[1],
|
|
6626
|
+
repo: urlMatch[2],
|
|
6627
|
+
number: parseInt(urlMatch[3], 10)
|
|
6628
|
+
};
|
|
6629
|
+
}
|
|
6630
|
+
const shorthandMatch = input.match(/^([^/]+)\/([^#]+)#(\d+)$/);
|
|
6631
|
+
if (shorthandMatch) {
|
|
6632
|
+
if (containsControlCharacters(shorthandMatch[1]) || containsControlCharacters(shorthandMatch[2])) {
|
|
6633
|
+
return null;
|
|
6634
|
+
}
|
|
6635
|
+
return {
|
|
6636
|
+
owner: shorthandMatch[1],
|
|
6637
|
+
repo: shorthandMatch[2],
|
|
6638
|
+
number: parseInt(shorthandMatch[3], 10)
|
|
6639
|
+
};
|
|
6640
|
+
}
|
|
6641
|
+
const bareMatch = input.match(/^(\d+)$/);
|
|
6642
|
+
if (bareMatch) {
|
|
6643
|
+
const prNumber = parseInt(bareMatch[1], 10);
|
|
6644
|
+
const remoteUrl = detectGitRemote(cwd, undefined);
|
|
6645
|
+
if (!remoteUrl) {
|
|
6646
|
+
return null;
|
|
6647
|
+
}
|
|
6648
|
+
const parsed = parseGitRemoteUrl(remoteUrl);
|
|
6649
|
+
if (!parsed) {
|
|
6650
|
+
return null;
|
|
6651
|
+
}
|
|
6652
|
+
return {
|
|
6653
|
+
owner: parsed.owner,
|
|
6654
|
+
repo: parsed.repo,
|
|
6655
|
+
number: prNumber
|
|
6656
|
+
};
|
|
6657
|
+
}
|
|
6658
|
+
return null;
|
|
6659
|
+
}
|
|
6660
|
+
function looksLikePrRef(token) {
|
|
6661
|
+
return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
|
|
6662
|
+
}
|
|
6663
|
+
function resolvePrCommandInput(rest, cwd) {
|
|
6664
|
+
if (rest.length === 0) {
|
|
6665
|
+
return null;
|
|
6666
|
+
}
|
|
6667
|
+
const refToken = rest[0];
|
|
6668
|
+
const instructions = sanitizeInstructions(rest.slice(1).join(" "));
|
|
6669
|
+
const isFullUrl = /^https?:\/\//i.test(refToken);
|
|
6670
|
+
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl(refToken) : refToken, cwd);
|
|
6671
|
+
if (!prInfo) {
|
|
6672
|
+
return {
|
|
6673
|
+
error: `Could not parse PR reference from "${sanitizeErrorEcho(refToken)}"`
|
|
6674
|
+
};
|
|
6675
|
+
}
|
|
6676
|
+
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
6677
|
+
const result = validateAndSanitizeUrl(prUrl);
|
|
6678
|
+
if ("error" in result) {
|
|
6679
|
+
return { error: result.error };
|
|
6680
|
+
}
|
|
6681
|
+
return { prUrl: result.sanitized, instructions };
|
|
6682
|
+
}
|
|
6683
|
+
|
|
6684
|
+
// src/commands/ci-monitor.ts
|
|
6685
|
+
var USAGE = [
|
|
6686
|
+
"Usage: /swarm ci-monitor <pr-url|owner/repo#N|N>",
|
|
6687
|
+
"",
|
|
6688
|
+
"Drive an already human-reviewed, approved pull request to green and",
|
|
6689
|
+
"merged: monitors CI, exhaustively researches and fixes each failure,",
|
|
6690
|
+
"iterates until all required checks are green (max 5 fix cycles), then",
|
|
6691
|
+
"merges. Only invoke after human review is complete.",
|
|
6692
|
+
"",
|
|
6693
|
+
" /swarm ci-monitor https://github.com/owner/repo/pull/42",
|
|
6694
|
+
" /swarm ci-monitor owner/repo#42",
|
|
6695
|
+
" /swarm ci-monitor 42"
|
|
6696
|
+
].join(`
|
|
6697
|
+
`);
|
|
6698
|
+
function handleCiMonitorCommand(directory, args) {
|
|
6699
|
+
const rest = args.filter((token) => token.trim().length > 0);
|
|
6700
|
+
const resolved = resolvePrCommandInput(rest, directory);
|
|
6701
|
+
if (resolved === null) {
|
|
6702
|
+
return USAGE;
|
|
6703
|
+
}
|
|
6704
|
+
if ("error" in resolved) {
|
|
6705
|
+
return `Error: ${resolved.error}
|
|
6706
|
+
|
|
6707
|
+
${USAGE}`;
|
|
6708
|
+
}
|
|
6709
|
+
if (resolved.instructions) {
|
|
6710
|
+
return `Error: /swarm ci-monitor takes only a PR reference \u2014 no trailing instructions. Got: "${resolved.instructions}"
|
|
6711
|
+
|
|
6712
|
+
${USAGE}`;
|
|
6713
|
+
}
|
|
6714
|
+
return `[MODE: CI_MONITOR pr="${resolved.prUrl}"]`;
|
|
6715
|
+
}
|
|
6716
|
+
|
|
6406
6717
|
// src/commands/ci-simulate.ts
|
|
6407
6718
|
import * as fs4 from "fs";
|
|
6408
6719
|
import * as fsPromises2 from "fs/promises";
|
|
@@ -6475,7 +6786,7 @@ function timeoutKillSignal(platform) {
|
|
|
6475
6786
|
}
|
|
6476
6787
|
function killProcess(proc) {
|
|
6477
6788
|
try {
|
|
6478
|
-
proc?.kill(timeoutKillSignal(
|
|
6789
|
+
proc?.kill(timeoutKillSignal(_internals8.platform()));
|
|
6479
6790
|
} catch {}
|
|
6480
6791
|
}
|
|
6481
6792
|
async function runExternalTool(options) {
|
|
@@ -6495,7 +6806,7 @@ async function runExternalTool(options) {
|
|
|
6495
6806
|
let exitSettled = false;
|
|
6496
6807
|
let settledExitCode = null;
|
|
6497
6808
|
try {
|
|
6498
|
-
proc =
|
|
6809
|
+
proc = _internals8.bunSpawn([options.executable, ...options.args], {
|
|
6499
6810
|
cwd: options.cwd,
|
|
6500
6811
|
env: options.env,
|
|
6501
6812
|
stdin: "ignore",
|
|
@@ -6563,7 +6874,7 @@ async function runExternalTool(options) {
|
|
|
6563
6874
|
}
|
|
6564
6875
|
}
|
|
6565
6876
|
}
|
|
6566
|
-
var
|
|
6877
|
+
var _internals8 = {
|
|
6567
6878
|
bunSpawn,
|
|
6568
6879
|
platform: () => process.platform
|
|
6569
6880
|
};
|
|
@@ -6572,7 +6883,7 @@ var _internals7 = {
|
|
|
6572
6883
|
var GIT_TIMEOUT_MS2 = 30000;
|
|
6573
6884
|
var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
6574
6885
|
var OUTPUT_LIMIT_BYTES = 12000;
|
|
6575
|
-
var
|
|
6886
|
+
var _internals9 = {
|
|
6576
6887
|
runExternalTool,
|
|
6577
6888
|
getDefaultBaseBranch,
|
|
6578
6889
|
platform: process.platform,
|
|
@@ -6583,7 +6894,7 @@ var _internals8 = {
|
|
|
6583
6894
|
}
|
|
6584
6895
|
};
|
|
6585
6896
|
async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
|
|
6586
|
-
const result = await
|
|
6897
|
+
const result = await _internals9.runExternalTool({
|
|
6587
6898
|
executable: "git",
|
|
6588
6899
|
args,
|
|
6589
6900
|
cwd,
|
|
@@ -6601,7 +6912,7 @@ async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
|
|
|
6601
6912
|
}
|
|
6602
6913
|
async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
|
|
6603
6914
|
const [executable, ...args] = cmd;
|
|
6604
|
-
const result = await
|
|
6915
|
+
const result = await _internals9.runExternalTool({
|
|
6605
6916
|
executable,
|
|
6606
6917
|
args,
|
|
6607
6918
|
cwd,
|
|
@@ -6629,7 +6940,7 @@ async function getCurrentBranchOrRef(directory) {
|
|
|
6629
6940
|
return hashResult.stdout.trim();
|
|
6630
6941
|
}
|
|
6631
6942
|
async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
|
|
6632
|
-
const worktreeBase = path12.join(
|
|
6943
|
+
const worktreeBase = path12.join(_internals9.osTmpdir(), "swarm-ci-simulate");
|
|
6633
6944
|
const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
6634
6945
|
const worktreePath = path12.join(worktreeBase, worktreeName);
|
|
6635
6946
|
await fsPromises2.mkdir(worktreeBase, { recursive: true });
|
|
@@ -6647,8 +6958,8 @@ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated)
|
|
|
6647
6958
|
async function cleanupWorktree(worktreePath, projectRoot) {
|
|
6648
6959
|
const removeResult = await runGit2(["worktree", "remove", "--force", worktreePath], projectRoot);
|
|
6649
6960
|
try {
|
|
6650
|
-
if (
|
|
6651
|
-
|
|
6961
|
+
if (_internals9.fs.existsSync(worktreePath)) {
|
|
6962
|
+
_internals9.fs.rmSync(worktreePath, { recursive: true, force: true });
|
|
6652
6963
|
}
|
|
6653
6964
|
} catch {}
|
|
6654
6965
|
if (removeResult.exitCode !== 0) {
|
|
@@ -6730,7 +7041,7 @@ async function handleCiSimulateCommand(directory, args) {
|
|
|
6730
7041
|
steps: []
|
|
6731
7042
|
};
|
|
6732
7043
|
try {
|
|
6733
|
-
const baseBranch =
|
|
7044
|
+
const baseBranch = _internals9.getDefaultBaseBranch(directory);
|
|
6734
7045
|
if (!isSafeGitRef(baseBranch)) {
|
|
6735
7046
|
throw new Error("Detected default branch is not a safe git reference.");
|
|
6736
7047
|
}
|
|
@@ -6829,7 +7140,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
6829
7140
|
}
|
|
6830
7141
|
|
|
6831
7142
|
// src/commands/close.ts
|
|
6832
|
-
import * as
|
|
7143
|
+
import * as child_process3 from "child_process";
|
|
6833
7144
|
import * as fsSync from "fs";
|
|
6834
7145
|
import { promises as fs10 } from "fs";
|
|
6835
7146
|
import path29 from "path";
|
|
@@ -7518,7 +7829,7 @@ async function reviseSkill(params) {
|
|
|
7518
7829
|
}
|
|
7519
7830
|
if (!params.delegate) {
|
|
7520
7831
|
try {
|
|
7521
|
-
const revised =
|
|
7832
|
+
const revised = _internals10.buildDeterministicRevision(params.currentContent, params.currentVersion, params.violationContexts);
|
|
7522
7833
|
const validation = await validateRevisionCandidate(params, revised, "skill_reviser:deterministic");
|
|
7523
7834
|
if (!validation.passed) {
|
|
7524
7835
|
return {
|
|
@@ -7645,7 +7956,7 @@ async function reviseSkill(params) {
|
|
|
7645
7956
|
};
|
|
7646
7957
|
}
|
|
7647
7958
|
}
|
|
7648
|
-
var
|
|
7959
|
+
var _internals10 = {
|
|
7649
7960
|
reviseSkill,
|
|
7650
7961
|
getSkillVersion,
|
|
7651
7962
|
buildDeterministicRevision,
|
|
@@ -7729,7 +8040,7 @@ function resolveLogPath(directory) {
|
|
|
7729
8040
|
function normalizeComplianceVerdict(verdict) {
|
|
7730
8041
|
return verdict === "violation" ? "violated" : verdict;
|
|
7731
8042
|
}
|
|
7732
|
-
var
|
|
8043
|
+
var _internals11 = {
|
|
7733
8044
|
generateId: () => crypto2.randomUUID(),
|
|
7734
8045
|
appendFileSync: fs5.appendFileSync.bind(fs5),
|
|
7735
8046
|
readFileSync: fs5.readFileSync.bind(fs5),
|
|
@@ -7799,9 +8110,9 @@ function parseFeedbackMarker(raw) {
|
|
|
7799
8110
|
function readFeedbackAppliedEntryIds(directory) {
|
|
7800
8111
|
const resolved = resolveLogPath(directory);
|
|
7801
8112
|
const processed = new Set;
|
|
7802
|
-
if (!
|
|
8113
|
+
if (!_internals11.existsSync(resolved))
|
|
7803
8114
|
return processed;
|
|
7804
|
-
const raw =
|
|
8115
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
7805
8116
|
for (const line of raw.split(`
|
|
7806
8117
|
`)) {
|
|
7807
8118
|
const trimmed = line.trim();
|
|
@@ -7822,15 +8133,15 @@ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
|
|
|
7822
8133
|
return;
|
|
7823
8134
|
const resolved = resolveLogPath(directory);
|
|
7824
8135
|
const dir = path15.dirname(resolved);
|
|
7825
|
-
if (!
|
|
7826
|
-
|
|
8136
|
+
if (!_internals11.existsSync(dir)) {
|
|
8137
|
+
_internals11.mkdirSync(dir, { recursive: true });
|
|
7827
8138
|
}
|
|
7828
8139
|
const marker = {
|
|
7829
8140
|
type: "feedback_applied",
|
|
7830
8141
|
timestamp: new Date().toISOString(),
|
|
7831
8142
|
processedEntryIds: [...new Set(processedEntryIds)]
|
|
7832
8143
|
};
|
|
7833
|
-
|
|
8144
|
+
_internals11.appendFileSync(resolved, `${JSON.stringify(marker)}
|
|
7834
8145
|
`, "utf-8");
|
|
7835
8146
|
}
|
|
7836
8147
|
function appendSkillUsageEntry(directory, entry) {
|
|
@@ -7867,11 +8178,11 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
7867
8178
|
}
|
|
7868
8179
|
const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
|
|
7869
8180
|
const dir = path15.dirname(resolved);
|
|
7870
|
-
if (!
|
|
7871
|
-
|
|
8181
|
+
if (!_internals11.existsSync(dir)) {
|
|
8182
|
+
_internals11.mkdirSync(dir, { recursive: true });
|
|
7872
8183
|
}
|
|
7873
8184
|
const fullEntry = {
|
|
7874
|
-
id:
|
|
8185
|
+
id: _internals11.generateId(),
|
|
7875
8186
|
skillPath,
|
|
7876
8187
|
agentName,
|
|
7877
8188
|
taskID,
|
|
@@ -7881,21 +8192,21 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
7881
8192
|
...reviewerNotes !== undefined && { reviewerNotes },
|
|
7882
8193
|
...skillVersion !== undefined && { skillVersion }
|
|
7883
8194
|
};
|
|
7884
|
-
|
|
8195
|
+
_internals11.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
|
|
7885
8196
|
`, "utf-8");
|
|
7886
8197
|
try {
|
|
7887
|
-
const stat2 =
|
|
8198
|
+
const stat2 = _internals11.statSync(resolved);
|
|
7888
8199
|
if (stat2.size > SKILL_USAGE_LOG_ROTATE_BYTES) {
|
|
7889
|
-
|
|
8200
|
+
_internals11.pruneSkillUsageLog(directory, SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL);
|
|
7890
8201
|
}
|
|
7891
8202
|
} catch {}
|
|
7892
8203
|
}
|
|
7893
8204
|
function readSkillUsageEntries(directory, options) {
|
|
7894
8205
|
const resolved = resolveLogPath(directory);
|
|
7895
|
-
if (!
|
|
8206
|
+
if (!_internals11.existsSync(resolved)) {
|
|
7896
8207
|
return [];
|
|
7897
8208
|
}
|
|
7898
|
-
const raw =
|
|
8209
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
7899
8210
|
const entries = [];
|
|
7900
8211
|
for (const line of raw.split(`
|
|
7901
8212
|
`)) {
|
|
@@ -7938,20 +8249,20 @@ var SKILL_USAGE_LOG_ROTATE_BYTES = 1024 * 1024;
|
|
|
7938
8249
|
var SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL = 500;
|
|
7939
8250
|
function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEFAULT) {
|
|
7940
8251
|
const logPath = resolveLogPath(directory);
|
|
7941
|
-
if (!
|
|
8252
|
+
if (!_internals11.existsSync(logPath))
|
|
7942
8253
|
return [];
|
|
7943
8254
|
try {
|
|
7944
8255
|
const normalizedMaxBytes = Number.isFinite(maxBytes) ? maxBytes : TAIL_BYTES_DEFAULT;
|
|
7945
8256
|
const boundedMaxBytes = Math.min(Math.max(1, normalizedMaxBytes), MAX_TAIL_BYTES);
|
|
7946
|
-
const stat2 =
|
|
8257
|
+
const stat2 = _internals11.statSync(logPath);
|
|
7947
8258
|
const start = Math.max(0, stat2.size - boundedMaxBytes);
|
|
7948
|
-
const fd =
|
|
8259
|
+
const fd = _internals11.openSync(logPath, "r");
|
|
7949
8260
|
try {
|
|
7950
8261
|
const readLen = stat2.size - start;
|
|
7951
8262
|
if (readLen === 0)
|
|
7952
8263
|
return [];
|
|
7953
8264
|
const buf = Buffer.alloc(readLen);
|
|
7954
|
-
|
|
8265
|
+
_internals11.readSync(fd, buf, 0, buf.length, start);
|
|
7955
8266
|
const content = buf.toString("utf-8");
|
|
7956
8267
|
let usable;
|
|
7957
8268
|
if (start > 0) {
|
|
@@ -7978,7 +8289,7 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
|
|
|
7978
8289
|
}
|
|
7979
8290
|
return entries;
|
|
7980
8291
|
} finally {
|
|
7981
|
-
|
|
8292
|
+
_internals11.closeSync(fd);
|
|
7982
8293
|
}
|
|
7983
8294
|
} catch {
|
|
7984
8295
|
return [];
|
|
@@ -8015,10 +8326,10 @@ function computeComplianceByVersion(entries, skillPath) {
|
|
|
8015
8326
|
}
|
|
8016
8327
|
function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
8017
8328
|
const resolved = resolveLogPath(directory);
|
|
8018
|
-
if (!
|
|
8329
|
+
if (!_internals11.existsSync(resolved)) {
|
|
8019
8330
|
return { pruned: 0, remaining: 0 };
|
|
8020
8331
|
}
|
|
8021
|
-
const raw =
|
|
8332
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
8022
8333
|
const lines = raw.split(`
|
|
8023
8334
|
`);
|
|
8024
8335
|
const entries = [];
|
|
@@ -8048,13 +8359,13 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8048
8359
|
`).concat(preservedMarkers.length > 0 ? `
|
|
8049
8360
|
` : "");
|
|
8050
8361
|
try {
|
|
8051
|
-
|
|
8052
|
-
|
|
8362
|
+
_internals11.writeFileSync(tmpPath2, content2, "utf-8");
|
|
8363
|
+
_internals11.renameSync(tmpPath2, resolved);
|
|
8053
8364
|
} catch (writeErr) {
|
|
8054
8365
|
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
8055
8366
|
try {
|
|
8056
|
-
if (
|
|
8057
|
-
|
|
8367
|
+
if (_internals11.existsSync(tmpPath2)) {
|
|
8368
|
+
_internals11.writeFileSync(tmpPath2, "", "utf-8");
|
|
8058
8369
|
}
|
|
8059
8370
|
} catch {}
|
|
8060
8371
|
return { pruned: 0, remaining: 0, error: msg };
|
|
@@ -8093,13 +8404,13 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8093
8404
|
`).concat(`
|
|
8094
8405
|
`);
|
|
8095
8406
|
try {
|
|
8096
|
-
|
|
8097
|
-
|
|
8407
|
+
_internals11.writeFileSync(tmpPath, content, "utf-8");
|
|
8408
|
+
_internals11.renameSync(tmpPath, resolved);
|
|
8098
8409
|
} catch (writeErr) {
|
|
8099
8410
|
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
8100
8411
|
try {
|
|
8101
|
-
if (
|
|
8102
|
-
|
|
8412
|
+
if (_internals11.existsSync(tmpPath)) {
|
|
8413
|
+
_internals11.writeFileSync(tmpPath, "", "utf-8");
|
|
8103
8414
|
}
|
|
8104
8415
|
} catch {}
|
|
8105
8416
|
return { pruned: 0, remaining: entries.length, error: msg };
|
|
@@ -8121,10 +8432,10 @@ async function resolveSourceKnowledgeIds(directory, skillPath) {
|
|
|
8121
8432
|
if (!isContained) {
|
|
8122
8433
|
return [];
|
|
8123
8434
|
}
|
|
8124
|
-
if (!
|
|
8435
|
+
if (!_internals11.existsSync(absolute)) {
|
|
8125
8436
|
return [];
|
|
8126
8437
|
}
|
|
8127
|
-
const content =
|
|
8438
|
+
const content = _internals11.readFileSync(absolute, "utf-8");
|
|
8128
8439
|
return parseGeneratedFromKnowledge(content);
|
|
8129
8440
|
} catch (err) {
|
|
8130
8441
|
log("[skill-usage-log] resolveSourceKnowledgeIds failed (fail-open):", err instanceof Error ? err.message : String(err));
|
|
@@ -8232,7 +8543,7 @@ var DEFAULT_CURATOR_LLM_TIMEOUT_MS = 300000;
|
|
|
8232
8543
|
var MAX_CURATOR_PHASE_DIGESTS = 50;
|
|
8233
8544
|
var MAX_CURATOR_COMPLIANCE_OBSERVATIONS = 200;
|
|
8234
8545
|
var MAX_CURATOR_RECOMMENDATIONS = 200;
|
|
8235
|
-
var
|
|
8546
|
+
var _internals12 = {
|
|
8236
8547
|
parseKnowledgeRecommendations,
|
|
8237
8548
|
parseKnowledgeRecommendationsWithDiagnostics,
|
|
8238
8549
|
readCuratorSummary,
|
|
@@ -8338,9 +8649,9 @@ ${digest.summary}`).join(`
|
|
|
8338
8649
|
async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs) {
|
|
8339
8650
|
const observations = [];
|
|
8340
8651
|
try {
|
|
8341
|
-
const skillListResult = await
|
|
8342
|
-
const usageEntries =
|
|
8343
|
-
const allArchivedIds = await
|
|
8652
|
+
const skillListResult = await _internals12.listSkills(directory);
|
|
8653
|
+
const usageEntries = _internals12.readSkillUsageEntries(directory);
|
|
8654
|
+
const allArchivedIds = await _internals12.getArchivedKnowledgeIds(directory);
|
|
8344
8655
|
for (const active of skillListResult.active) {
|
|
8345
8656
|
if (excludeSlugs?.has(active.slug))
|
|
8346
8657
|
continue;
|
|
@@ -8362,7 +8673,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
8362
8673
|
const violationRate = skillUsage.length > 0 ? violations / skillUsage.length : 0;
|
|
8363
8674
|
if (violationRate > 0.3) {
|
|
8364
8675
|
const reason = `auto-retire: violation rate ${(violationRate * 100).toFixed(0)}% exceeds 30% threshold`;
|
|
8365
|
-
await
|
|
8676
|
+
await _internals12.retireSkill(directory, active.slug, reason);
|
|
8366
8677
|
observations.push(`Skill '${active.slug}' auto-retired: ${reason}`);
|
|
8367
8678
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
8368
8679
|
continue;
|
|
@@ -8370,15 +8681,15 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
8370
8681
|
let archivedSourceMatched = false;
|
|
8371
8682
|
if (allArchivedIds.size > 0) {
|
|
8372
8683
|
try {
|
|
8373
|
-
const content = await
|
|
8374
|
-
const sourceIds =
|
|
8684
|
+
const content = await _internals12.readFileAsync(active.path, "utf-8");
|
|
8685
|
+
const sourceIds = _internals12.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
|
|
8375
8686
|
archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
|
|
8376
8687
|
} catch {
|
|
8377
8688
|
archivedSourceMatched = false;
|
|
8378
8689
|
}
|
|
8379
8690
|
}
|
|
8380
8691
|
if (archivedSourceMatched) {
|
|
8381
|
-
const result = await
|
|
8692
|
+
const result = await _internals12.retireOrMarkStale(directory, path16.dirname(active.path), allArchivedIds);
|
|
8382
8693
|
if (result.action === "retire") {
|
|
8383
8694
|
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
8384
8695
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
@@ -8646,7 +8957,7 @@ async function transactCuratorSummary(directory, mutate) {
|
|
|
8646
8957
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
8647
8958
|
let invoked = false;
|
|
8648
8959
|
let mutationResult;
|
|
8649
|
-
await
|
|
8960
|
+
await _internals12.transactFile(resolvedPath, _internals12.readCuratorSummaryState, _internals12.writeCuratorSummaryState, (state) => {
|
|
8650
8961
|
invoked = true;
|
|
8651
8962
|
const mutation = mutate(state.summary);
|
|
8652
8963
|
mutationResult = mutation.result;
|
|
@@ -8795,8 +9106,8 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8795
9106
|
const observations = [];
|
|
8796
9107
|
const timestamp = new Date().toISOString();
|
|
8797
9108
|
for (const agent of requiredAgents) {
|
|
8798
|
-
const normalizedAgent =
|
|
8799
|
-
const isDispatched = agentsDispatched.some((a) =>
|
|
9109
|
+
const normalizedAgent = _internals12.normalizeAgentName(agent);
|
|
9110
|
+
const isDispatched = agentsDispatched.some((a) => _internals12.normalizeAgentName(a) === normalizedAgent);
|
|
8800
9111
|
if (!isDispatched) {
|
|
8801
9112
|
observations.push({
|
|
8802
9113
|
phase,
|
|
@@ -8815,7 +9126,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8815
9126
|
if (e.type === "agent.delegation") {
|
|
8816
9127
|
const agent = e.agent;
|
|
8817
9128
|
if (agent && typeof agent === "string") {
|
|
8818
|
-
const normalized =
|
|
9129
|
+
const normalized = _internals12.normalizeAgentName(agent);
|
|
8819
9130
|
if (normalized === "coder") {
|
|
8820
9131
|
coderDelegations.push({ event: e, index: i });
|
|
8821
9132
|
} else if (normalized === "reviewer") {
|
|
@@ -8872,7 +9183,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8872
9183
|
if (e.type === "agent.delegation" && e.agent) {
|
|
8873
9184
|
const agent = e.agent;
|
|
8874
9185
|
if (agent && typeof agent === "string") {
|
|
8875
|
-
const normalized =
|
|
9186
|
+
const normalized = _internals12.normalizeAgentName(agent);
|
|
8876
9187
|
if (normalized === "sme") {
|
|
8877
9188
|
smeDelegations.push({ event: e, index: i });
|
|
8878
9189
|
}
|
|
@@ -8896,7 +9207,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8896
9207
|
}
|
|
8897
9208
|
async function runCuratorInit(directory, config, llmDelegate) {
|
|
8898
9209
|
try {
|
|
8899
|
-
const priorSummary = await
|
|
9210
|
+
const priorSummary = await _internals12.readCuratorSummary(directory);
|
|
8900
9211
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
8901
9212
|
const allEntries = await readKnowledge(knowledgePath);
|
|
8902
9213
|
const highConfidenceEntries = allEntries.filter((e) => typeof e.confidence === "number" && e.confidence >= config.min_knowledge_confidence);
|
|
@@ -8937,7 +9248,7 @@ async function runCuratorInit(directory, config, llmDelegate) {
|
|
|
8937
9248
|
const maxContextChars = config.max_summary_tokens * 2;
|
|
8938
9249
|
briefingParts.push(contextMd.slice(0, maxContextChars));
|
|
8939
9250
|
}
|
|
8940
|
-
const latestPostMortemDigest =
|
|
9251
|
+
const latestPostMortemDigest = _internals12.readLatestPostMortemDigest(directory);
|
|
8941
9252
|
if (latestPostMortemDigest) {
|
|
8942
9253
|
briefingParts.push(`
|
|
8943
9254
|
## Latest Post-Mortem`);
|
|
@@ -9024,7 +9335,7 @@ Could not load prior session context.`,
|
|
|
9024
9335
|
}
|
|
9025
9336
|
async function runCuratorPhase(directory, phase, agentsDispatched, config, knowledgeConfig, llmDelegate) {
|
|
9026
9337
|
try {
|
|
9027
|
-
const priorSummary = await
|
|
9338
|
+
const priorSummary = await _internals12.readCuratorSummary(directory);
|
|
9028
9339
|
if (priorSummary?.phase_digests.some((d) => d.phase === phase)) {
|
|
9029
9340
|
const existingDigest = priorSummary.phase_digests.find((d) => d.phase === phase);
|
|
9030
9341
|
return {
|
|
@@ -9037,10 +9348,10 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9037
9348
|
};
|
|
9038
9349
|
}
|
|
9039
9350
|
const eventsJsonlContent = await readSwarmFileAsync(directory, "events.jsonl");
|
|
9040
|
-
const phaseEvents = eventsJsonlContent ?
|
|
9351
|
+
const phaseEvents = eventsJsonlContent ? _internals12.filterPhaseEvents(eventsJsonlContent, phase) : [];
|
|
9041
9352
|
const contextMd = await readSwarmFileAsync(directory, "context.md");
|
|
9042
9353
|
const requiredAgents = ["reviewer", "test_engineer"];
|
|
9043
|
-
const complianceObservations =
|
|
9354
|
+
const complianceObservations = _internals12.checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
|
|
9044
9355
|
const plan = await loadPlanJsonOnly(directory);
|
|
9045
9356
|
const phaseData = plan?.phases.find((p) => p.id === phase);
|
|
9046
9357
|
const tasksCompleted = phaseData ? phaseData.tasks.filter((t) => t.status === "completed").length : 0;
|
|
@@ -9064,7 +9375,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9064
9375
|
timestamp: new Date().toISOString(),
|
|
9065
9376
|
summary: `Phase ${phase} completed. ${tasksCompleted}/${tasksTotal} tasks completed. ${complianceObservations.length} compliance observations.`,
|
|
9066
9377
|
agents_used: [
|
|
9067
|
-
...new Set(agentsDispatched.map((a) =>
|
|
9378
|
+
...new Set(agentsDispatched.map((a) => _internals12.normalizeAgentName(a)))
|
|
9068
9379
|
],
|
|
9069
9380
|
tasks_completed: tasksCompleted,
|
|
9070
9381
|
tasks_total: tasksTotal,
|
|
@@ -9116,7 +9427,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9116
9427
|
clearTimeout(timer);
|
|
9117
9428
|
}
|
|
9118
9429
|
if (llmOutput?.trim()) {
|
|
9119
|
-
const parsed =
|
|
9430
|
+
const parsed = _internals12.parseKnowledgeRecommendationsWithDiagnostics(llmOutput);
|
|
9120
9431
|
for (const diagnostic of parsed.diagnostics) {
|
|
9121
9432
|
warn("[curator] skipped malformed recommendation line", {
|
|
9122
9433
|
phase,
|
|
@@ -9161,7 +9472,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9161
9472
|
}
|
|
9162
9473
|
const sessionId = `session-${Date.now()}`;
|
|
9163
9474
|
const now = new Date().toISOString();
|
|
9164
|
-
const summaryUpdated = await
|
|
9475
|
+
const summaryUpdated = await _internals12.mergeCuratorPhaseSummary(directory, {
|
|
9165
9476
|
phase,
|
|
9166
9477
|
phaseDigest,
|
|
9167
9478
|
complianceObservations,
|
|
@@ -9192,7 +9503,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9192
9503
|
}
|
|
9193
9504
|
if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
|
|
9194
9505
|
try {
|
|
9195
|
-
const skillModule = await import("./skill-generator-
|
|
9506
|
+
const skillModule = await import("./skill-generator-tav44xpm.js");
|
|
9196
9507
|
for (const cand of skillCandidates) {
|
|
9197
9508
|
if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
|
|
9198
9509
|
continue;
|
|
@@ -9210,8 +9521,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9210
9521
|
}
|
|
9211
9522
|
const revisedSlugs = new Set;
|
|
9212
9523
|
try {
|
|
9213
|
-
const skillListResult = await
|
|
9214
|
-
const usageEntries =
|
|
9524
|
+
const skillListResult = await _internals12.listSkills(directory);
|
|
9525
|
+
const usageEntries = _internals12.readSkillUsageEntries(directory);
|
|
9215
9526
|
let revisionCallsThisPhase = 0;
|
|
9216
9527
|
for (const active of skillListResult.active) {
|
|
9217
9528
|
if (revisionCallsThisPhase >= MAX_REVISION_CALLS_PER_PHASE)
|
|
@@ -9235,8 +9546,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9235
9546
|
const violations = skillUsage.filter((e) => e.complianceVerdict === "violated").length;
|
|
9236
9547
|
const violationRate = violations / skillUsage.length;
|
|
9237
9548
|
if (violationRate > REVISION_VIOLATION_THRESHOLD && violationRate <= 0.3) {
|
|
9238
|
-
const content = await
|
|
9239
|
-
const fm =
|
|
9549
|
+
const content = await _internals12.readFileAsync(active.path, "utf-8");
|
|
9550
|
+
const fm = _internals12.parseDraftFrontmatter(content);
|
|
9240
9551
|
if (fm && fm.skillOrigin === "promoted_external")
|
|
9241
9552
|
continue;
|
|
9242
9553
|
const currentVersion = fm?.version ?? 1;
|
|
@@ -9247,7 +9558,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9247
9558
|
reviewerNotes: e.reviewerNotes,
|
|
9248
9559
|
timestamp: e.timestamp
|
|
9249
9560
|
}));
|
|
9250
|
-
const result2 = await
|
|
9561
|
+
const result2 = await _internals12.reviseSkill({
|
|
9251
9562
|
directory,
|
|
9252
9563
|
slug: active.slug,
|
|
9253
9564
|
skillPath: active.path,
|
|
@@ -9266,7 +9577,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9266
9577
|
} catch (revisionErr) {
|
|
9267
9578
|
warn(`[curator] skill revision check failed: ${revisionErr instanceof Error ? revisionErr.message : String(revisionErr)}`);
|
|
9268
9579
|
}
|
|
9269
|
-
const autoRetireObservations = await
|
|
9580
|
+
const autoRetireObservations = await _internals12.autoRetireSkills(directory, curatorKnowledgePath, revisedSlugs);
|
|
9270
9581
|
if (autoRetireObservations.length > 0) {
|
|
9271
9582
|
const retireNote = ` [${autoRetireObservations.length} skill(s) auto-retired]`;
|
|
9272
9583
|
phaseDigest.summary += retireNote;
|
|
@@ -9473,7 +9784,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
|
|
|
9473
9784
|
} catch {}
|
|
9474
9785
|
}
|
|
9475
9786
|
if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
|
|
9476
|
-
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-
|
|
9787
|
+
const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-5gwp1ar8.js");
|
|
9477
9788
|
for (const { id } of contradictedEntries) {
|
|
9478
9789
|
try {
|
|
9479
9790
|
await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
|
|
@@ -9829,18 +10140,18 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9829
10140
|
proposals_rejected: 0,
|
|
9830
10141
|
proposals_skipped: 0
|
|
9831
10142
|
};
|
|
9832
|
-
const knowledgeConfig = options.knowledgeConfig ?? await
|
|
10143
|
+
const knowledgeConfig = options.knowledgeConfig ?? await _internals13.loadDefaultKnowledgeConfig();
|
|
9833
10144
|
if (parsed.recommendations.length > 0) {
|
|
9834
10145
|
try {
|
|
9835
|
-
const knowledgeResult = await
|
|
10146
|
+
const knowledgeResult = await _internals13.applyCuratorKnowledgeUpdates(directory, parsed.recommendations, knowledgeConfig);
|
|
9836
10147
|
result.knowledge_applied = knowledgeResult.applied;
|
|
9837
10148
|
result.knowledge_skipped = knowledgeResult.skipped;
|
|
9838
10149
|
} catch (err) {
|
|
9839
10150
|
warnings.push(`Post-mortem knowledge actions failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9840
10151
|
}
|
|
9841
10152
|
try {
|
|
9842
|
-
const entries = await
|
|
9843
|
-
const hiveResult = await
|
|
10153
|
+
const entries = await _internals13.readSwarmKnowledge(directory);
|
|
10154
|
+
const hiveResult = await _internals13.checkHivePromotions(entries, knowledgeConfig);
|
|
9844
10155
|
result.hive_promotions = hiveResult.new_promotions;
|
|
9845
10156
|
result.hive_encounters_incremented = hiveResult.encounters_incremented;
|
|
9846
10157
|
result.hive_advancements = hiveResult.advancements;
|
|
@@ -9850,7 +10161,7 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9850
10161
|
}
|
|
9851
10162
|
if (parsed.queueTriage.length > 0) {
|
|
9852
10163
|
try {
|
|
9853
|
-
const proposalResult = await
|
|
10164
|
+
const proposalResult = await _internals13.applyProposalTriage(directory, parsed.queueTriage);
|
|
9854
10165
|
result.proposals_approved = proposalResult.approved.length;
|
|
9855
10166
|
result.proposals_rejected = proposalResult.rejected.length;
|
|
9856
10167
|
result.proposals_skipped = proposalResult.skipped.length;
|
|
@@ -9863,7 +10174,7 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9863
10174
|
async function verifyPostMortemKnowledgeActions(directory, recommendations) {
|
|
9864
10175
|
if (recommendations.length === 0)
|
|
9865
10176
|
return [];
|
|
9866
|
-
const entries = await
|
|
10177
|
+
const entries = await _internals13.readSwarmKnowledge(directory);
|
|
9867
10178
|
const activeEntries = entries.filter((entry) => isActiveStatus(entry.status));
|
|
9868
10179
|
const exactIds = new Set(activeEntries.map((entry) => entry.id));
|
|
9869
10180
|
const prefixMatches = new Map;
|
|
@@ -9964,7 +10275,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
|
|
|
9964
10275
|
].join(`
|
|
9965
10276
|
`);
|
|
9966
10277
|
const repaired = await options.llmDelegate("", repairPrompt, ac.signal);
|
|
9967
|
-
const parsed =
|
|
10278
|
+
const parsed = _internals13.parsePostMortemActions(repaired);
|
|
9968
10279
|
if (parsed.diagnostics.length === 0) {
|
|
9969
10280
|
return parsed;
|
|
9970
10281
|
}
|
|
@@ -10017,7 +10328,7 @@ function collectRetrospectives(directory) {
|
|
|
10017
10328
|
}
|
|
10018
10329
|
async function collectDriftReports(directory) {
|
|
10019
10330
|
try {
|
|
10020
|
-
const reports = await
|
|
10331
|
+
const reports = await _internals13.readPriorDriftReports(directory);
|
|
10021
10332
|
return reports.slice(-MAX_DRIFT_REPORTS).map((report) => JSON.stringify(report, null, 2));
|
|
10022
10333
|
} catch {
|
|
10023
10334
|
return [];
|
|
@@ -10240,7 +10551,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
10240
10551
|
warnings
|
|
10241
10552
|
};
|
|
10242
10553
|
}
|
|
10243
|
-
const lock = await
|
|
10554
|
+
const lock = await _internals13.acquirePostMortemLock(directory, effectivePlanId);
|
|
10244
10555
|
if (!lock.acquired) {
|
|
10245
10556
|
return {
|
|
10246
10557
|
success: false,
|
|
@@ -10317,20 +10628,20 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
10317
10628
|
} finally {
|
|
10318
10629
|
clearTimeout(timer);
|
|
10319
10630
|
}
|
|
10320
|
-
let parsedActions =
|
|
10631
|
+
let parsedActions = _internals13.parsePostMortemActions(llmOutput);
|
|
10321
10632
|
if (parsedActions.diagnostics.length > 0) {
|
|
10322
10633
|
warnings.push(`Post-mortem structured action parse diagnostics: ${parsedActions.diagnostics.join("; ")}`);
|
|
10323
|
-
const repaired = await
|
|
10634
|
+
const repaired = await _internals13.repairPostMortemActions(llmOutput, parsedActions.diagnostics, options);
|
|
10324
10635
|
if (repaired) {
|
|
10325
10636
|
parsedActions = repaired;
|
|
10326
10637
|
warnings.push("Post-mortem structured actions repaired by LLM.");
|
|
10327
10638
|
}
|
|
10328
10639
|
}
|
|
10329
10640
|
llmSummary = parsedActions.summary;
|
|
10330
|
-
const executed = await
|
|
10641
|
+
const executed = await _internals13.executePostMortemActions(directory, parsedActions, options);
|
|
10331
10642
|
actionResult = executed.result;
|
|
10332
10643
|
warnings.push(...executed.warnings);
|
|
10333
|
-
const knowledgeVerification = await
|
|
10644
|
+
const knowledgeVerification = await _internals13.verifyPostMortemKnowledgeActions(directory, parsedActions.recommendations);
|
|
10334
10645
|
for (const item of knowledgeVerification) {
|
|
10335
10646
|
if (item.status === "not_found" || item.status === "ambiguous_prefix" || item.status === "missing_entry_id") {
|
|
10336
10647
|
warnings.push(`Post-mortem knowledge action ${item.action} for '${item.input_entry_id ?? "new"}' ${item.status}: ${item.reason}`);
|
|
@@ -10369,10 +10680,10 @@ ${actionSummary}`;
|
|
|
10369
10680
|
} catch (err) {
|
|
10370
10681
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10371
10682
|
warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
|
|
10372
|
-
reportContent =
|
|
10683
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
10373
10684
|
}
|
|
10374
10685
|
} else {
|
|
10375
|
-
reportContent =
|
|
10686
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
10376
10687
|
}
|
|
10377
10688
|
try {
|
|
10378
10689
|
const { mkdirSync: mkdirSync8 } = await import("fs");
|
|
@@ -10413,7 +10724,7 @@ ${actionSummary}`;
|
|
|
10413
10724
|
}
|
|
10414
10725
|
}
|
|
10415
10726
|
}
|
|
10416
|
-
var
|
|
10727
|
+
var _internals13 = {
|
|
10417
10728
|
acquirePostMortemLock,
|
|
10418
10729
|
collectKnowledgeSummary,
|
|
10419
10730
|
collectRetrospectives,
|
|
@@ -10434,11 +10745,11 @@ var _internals12 = {
|
|
|
10434
10745
|
return KnowledgeConfigSchema2.parse({});
|
|
10435
10746
|
},
|
|
10436
10747
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
10437
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
10748
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-5xt89z05.js");
|
|
10438
10749
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
|
|
10439
10750
|
},
|
|
10440
10751
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
10441
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
10752
|
+
const { checkHivePromotions } = await import("./hive-promoter-q899q2m6.js");
|
|
10442
10753
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
10443
10754
|
},
|
|
10444
10755
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -10447,7 +10758,7 @@ var _internals12 = {
|
|
|
10447
10758
|
activateProposal,
|
|
10448
10759
|
listSkills: listSkills2,
|
|
10449
10760
|
sanitizeSlug
|
|
10450
|
-
} = await import("./skill-generator-
|
|
10761
|
+
} = await import("./skill-generator-tav44xpm.js");
|
|
10451
10762
|
const result = {
|
|
10452
10763
|
approved: [],
|
|
10453
10764
|
rejected: [],
|
|
@@ -10666,7 +10977,7 @@ async function checkHivePromotions(swarmEntries, config) {
|
|
|
10666
10977
|
total_hive_entries: hiveEntries.length
|
|
10667
10978
|
};
|
|
10668
10979
|
}
|
|
10669
|
-
var
|
|
10980
|
+
var _internals14 = {
|
|
10670
10981
|
readSwarmEntries: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory)),
|
|
10671
10982
|
checkHivePromotions,
|
|
10672
10983
|
readCuratorSummary,
|
|
@@ -10674,15 +10985,15 @@ var _internals13 = {
|
|
|
10674
10985
|
};
|
|
10675
10986
|
function createHivePromoterHook(directory, config) {
|
|
10676
10987
|
const hook = async (_input, _output) => {
|
|
10677
|
-
const swarmEntries = await
|
|
10678
|
-
const promotionSummary = await
|
|
10679
|
-
const curatorSummary = await
|
|
10988
|
+
const swarmEntries = await _internals14.readSwarmEntries(directory);
|
|
10989
|
+
const promotionSummary = await _internals14.checkHivePromotions(swarmEntries, config);
|
|
10990
|
+
const curatorSummary = await _internals14.readCuratorSummary(directory);
|
|
10680
10991
|
if (!curatorSummary)
|
|
10681
10992
|
return;
|
|
10682
10993
|
const hasActivity = promotionSummary.new_promotions > 0 || promotionSummary.encounters_incremented > 0 || promotionSummary.advancements > 0;
|
|
10683
10994
|
if (!hasActivity)
|
|
10684
10995
|
return;
|
|
10685
|
-
await
|
|
10996
|
+
await _internals14.appendCuratorRecommendation(directory, {
|
|
10686
10997
|
action: "promote",
|
|
10687
10998
|
lesson: `Hive promotion: ${promotionSummary.new_promotions} new, ${promotionSummary.encounters_incremented} encounters, ${promotionSummary.advancements} advancements, ${promotionSummary.total_hive_entries} total entries`,
|
|
10688
10999
|
reason: JSON.stringify({
|
|
@@ -11023,7 +11334,7 @@ var SKILL_AUDIENCE_RUNNER_PATTERN = /^runner:(opencode|claude|codex)$/;
|
|
|
11023
11334
|
var WORKFLOW_BOOST_MIN_CONTEXT = 0.05;
|
|
11024
11335
|
var RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
|
|
11025
11336
|
var SKILL_FRONTMATTER_READ_BYTES = 16 * 1024;
|
|
11026
|
-
var
|
|
11337
|
+
var _internals15 = {
|
|
11027
11338
|
computeSkillRelevanceScore: null,
|
|
11028
11339
|
rankSkillsForContext: null,
|
|
11029
11340
|
getSkillStats: null,
|
|
@@ -11390,7 +11701,7 @@ function rankSkillsForContext(skills, taskContext, directory) {
|
|
|
11390
11701
|
const results = [];
|
|
11391
11702
|
for (const skillPath of skills) {
|
|
11392
11703
|
const skillEntries = allEntries.filter((e) => e.skillPath === skillPath);
|
|
11393
|
-
const metadata =
|
|
11704
|
+
const metadata = _internals15.readSkillMetadata(skillPath, directory);
|
|
11394
11705
|
const score = computeSkillRelevanceScore(skillPath, taskContext, skillEntries, metadata);
|
|
11395
11706
|
const entriesWithVerdict = skillEntries.filter((e) => e.complianceVerdict !== undefined && e.complianceVerdict !== "not_checked");
|
|
11396
11707
|
const compliantCount = entriesWithVerdict.filter((e) => e.complianceVerdict === "compliant").length;
|
|
@@ -11449,7 +11760,7 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11449
11760
|
} catch {}
|
|
11450
11761
|
if (!hasHistory) {
|
|
11451
11762
|
return skills.map((sp) => {
|
|
11452
|
-
const meta = metadataBySkillPath?.get(sp) ??
|
|
11763
|
+
const meta = metadataBySkillPath?.get(sp) ?? _internals15.readSkillMetadata(sp, directory);
|
|
11453
11764
|
return ` - file:${meta.path} - ${meta.name}: ${meta.description}`;
|
|
11454
11765
|
}).join(`
|
|
11455
11766
|
`);
|
|
@@ -11457,7 +11768,7 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11457
11768
|
const lines = [];
|
|
11458
11769
|
for (const skillPath of skills) {
|
|
11459
11770
|
const stats = getSkillStats(skillPath, directory);
|
|
11460
|
-
const meta = metadataBySkillPath?.get(skillPath) ??
|
|
11771
|
+
const meta = metadataBySkillPath?.get(skillPath) ?? _internals15.readSkillMetadata(skillPath, directory);
|
|
11461
11772
|
const compliancePct = Math.round(stats.complianceRate * 100);
|
|
11462
11773
|
const topAgentNames = stats.topAgents.slice(0, 3).map((a) => a.agent).join(", ");
|
|
11463
11774
|
lines.push(` - file:${meta.path} - ${meta.name}: ${meta.description} (used: ${stats.totalUsage}, compliance: ${compliancePct}%)` + (stats.topAgents.length > 0 ? ` \u2192 ${topAgentNames}` : ""));
|
|
@@ -11465,16 +11776,16 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11465
11776
|
return lines.join(`
|
|
11466
11777
|
`);
|
|
11467
11778
|
}
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11779
|
+
_internals15.computeSkillRelevanceScore = computeSkillRelevanceScore;
|
|
11780
|
+
_internals15.rankSkillsForContext = rankSkillsForContext;
|
|
11781
|
+
_internals15.getSkillStats = getSkillStats;
|
|
11782
|
+
_internals15.formatSkillIndexWithContext = formatSkillIndexWithContext;
|
|
11783
|
+
_internals15.parseSkillFrontmatter = parseSkillFrontmatter;
|
|
11784
|
+
_internals15.readSkillMetadata = readSkillMetadata;
|
|
11785
|
+
_internals15.extractSkillName = extractSkillName;
|
|
11786
|
+
_internals15.computeRecencyScore = computeRecencyScore;
|
|
11787
|
+
_internals15.computeContextMatchScore = computeContextMatchScore;
|
|
11788
|
+
_internals15.computeTriggerMatchBoost = computeTriggerMatchBoost;
|
|
11478
11789
|
|
|
11479
11790
|
// src/hooks/skill-propagation-gate.ts
|
|
11480
11791
|
function parseSimpleYaml(content) {
|
|
@@ -11576,10 +11887,10 @@ function parseYamlValue(value) {
|
|
|
11576
11887
|
}
|
|
11577
11888
|
function loadRoutingSkills(directory, targetAgent) {
|
|
11578
11889
|
const routingPath = path21.join(directory, ".opencode", "skill-routing.yaml");
|
|
11579
|
-
if (!
|
|
11890
|
+
if (!_internals16.existsSync(routingPath))
|
|
11580
11891
|
return [];
|
|
11581
11892
|
try {
|
|
11582
|
-
const content =
|
|
11893
|
+
const content = _internals16.readFileSync(routingPath, "utf-8");
|
|
11583
11894
|
const config = parseSimpleYaml(content);
|
|
11584
11895
|
if (!config?.routing)
|
|
11585
11896
|
return [];
|
|
@@ -11606,7 +11917,7 @@ var SKILL_SEARCH_ROOTS = [
|
|
|
11606
11917
|
".claude/skills"
|
|
11607
11918
|
];
|
|
11608
11919
|
var MAX_SCORING_SESSION_ENTRIES = 500;
|
|
11609
|
-
var
|
|
11920
|
+
var _internals16 = {
|
|
11610
11921
|
readdirSync: fs8.readdirSync.bind(fs8),
|
|
11611
11922
|
existsSync: fs8.existsSync.bind(fs8),
|
|
11612
11923
|
statSync: fs8.statSync.bind(fs8),
|
|
@@ -11639,11 +11950,11 @@ function discoverAvailableSkills(directory) {
|
|
|
11639
11950
|
const results = [];
|
|
11640
11951
|
for (const root of SKILL_SEARCH_ROOTS) {
|
|
11641
11952
|
const rootPath = path21.join(directory, root);
|
|
11642
|
-
if (!
|
|
11953
|
+
if (!_internals16.existsSync(rootPath))
|
|
11643
11954
|
continue;
|
|
11644
11955
|
let entries;
|
|
11645
11956
|
try {
|
|
11646
|
-
entries =
|
|
11957
|
+
entries = _internals16.readdirSync(rootPath);
|
|
11647
11958
|
} catch {
|
|
11648
11959
|
continue;
|
|
11649
11960
|
}
|
|
@@ -11651,11 +11962,11 @@ function discoverAvailableSkills(directory) {
|
|
|
11651
11962
|
if (entry.startsWith("."))
|
|
11652
11963
|
continue;
|
|
11653
11964
|
const skillDir = path21.join(rootPath, entry);
|
|
11654
|
-
if (
|
|
11965
|
+
if (_internals16.existsSync(path21.join(skillDir, "retired.marker")) || _internals16.existsSync(path21.join(skillDir, "stale.marker")))
|
|
11655
11966
|
continue;
|
|
11656
11967
|
const skillFile = path21.join(skillDir, "SKILL.md");
|
|
11657
11968
|
try {
|
|
11658
|
-
if (
|
|
11969
|
+
if (_internals16.statSync(skillDir).isDirectory() && _internals16.existsSync(skillFile)) {
|
|
11659
11970
|
results.push(path21.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
|
|
11660
11971
|
}
|
|
11661
11972
|
} catch (err) {
|
|
@@ -11687,7 +11998,7 @@ function parseDelegationArgs(args) {
|
|
|
11687
11998
|
}
|
|
11688
11999
|
if (!targetAgent)
|
|
11689
12000
|
return null;
|
|
11690
|
-
const skillsField = prompt ?
|
|
12001
|
+
const skillsField = prompt ? _internals16.extractSkillsFieldFromPrompt(prompt) : "";
|
|
11691
12002
|
return { targetAgent, skillsField };
|
|
11692
12003
|
}
|
|
11693
12004
|
function extractSkillsFieldFromPrompt(prompt) {
|
|
@@ -11728,10 +12039,10 @@ function writeWarnEvent(directory, record) {
|
|
|
11728
12039
|
const filePath = path21.join(directory, ".swarm", "events.jsonl");
|
|
11729
12040
|
try {
|
|
11730
12041
|
const dir = path21.dirname(filePath);
|
|
11731
|
-
if (!
|
|
11732
|
-
|
|
12042
|
+
if (!_internals16.existsSync(dir)) {
|
|
12043
|
+
_internals16.mkdirSync(dir, { recursive: true });
|
|
11733
12044
|
}
|
|
11734
|
-
|
|
12045
|
+
_internals16.appendFileSync(filePath, `${JSON.stringify(record)}
|
|
11735
12046
|
`, "utf-8");
|
|
11736
12047
|
} catch (err) {
|
|
11737
12048
|
warn(`[skill-propagation-gate] failed to write warning event: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -11786,7 +12097,7 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11786
12097
|
};
|
|
11787
12098
|
}
|
|
11788
12099
|
try {
|
|
11789
|
-
const root =
|
|
12100
|
+
const root = _internals16.realpathSync(directory);
|
|
11790
12101
|
const lexicalPath = path21.resolve(root, withoutPrefix);
|
|
11791
12102
|
if (!isWithinRoot(root, lexicalPath)) {
|
|
11792
12103
|
return {
|
|
@@ -11794,10 +12105,10 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11794
12105
|
reason: "skill path resolves outside the project"
|
|
11795
12106
|
};
|
|
11796
12107
|
}
|
|
11797
|
-
if (!
|
|
12108
|
+
if (!_internals16.existsSync(lexicalPath) || !_internals16.statSync(lexicalPath).isFile()) {
|
|
11798
12109
|
return { valid: false, reason: "skill file does not exist" };
|
|
11799
12110
|
}
|
|
11800
|
-
const realPath =
|
|
12111
|
+
const realPath = _internals16.realpathSync(lexicalPath);
|
|
11801
12112
|
if (!isWithinRoot(root, realPath)) {
|
|
11802
12113
|
return {
|
|
11803
12114
|
valid: false,
|
|
@@ -11806,7 +12117,7 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11806
12117
|
}
|
|
11807
12118
|
const normalizedPath = withoutPrefix.replace(/^\.\//, "");
|
|
11808
12119
|
const validatedMetadataPath = path21.relative(root, realPath).replace(/\\/g, "/");
|
|
11809
|
-
const metadata =
|
|
12120
|
+
const metadata = _internals16.readSkillMetadata(validatedMetadataPath, root);
|
|
11810
12121
|
if (metadata.frontmatterStatus !== "valid" && metadata.frontmatterStatus !== "absent") {
|
|
11811
12122
|
return {
|
|
11812
12123
|
valid: false,
|
|
@@ -11838,18 +12149,18 @@ async function validateExplicitSkillReferencesBefore(directory, input, config) {
|
|
|
11838
12149
|
if (!agentRaw || stripKnownSwarmPrefix(agentRaw) !== "architect") {
|
|
11839
12150
|
return { blocked: false, reason: null };
|
|
11840
12151
|
}
|
|
11841
|
-
const parsed =
|
|
12152
|
+
const parsed = _internals16.parseDelegationArgs(input.args);
|
|
11842
12153
|
if (!parsed)
|
|
11843
12154
|
return { blocked: false, reason: null };
|
|
11844
12155
|
const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
|
|
11845
|
-
if (!
|
|
12156
|
+
if (!_internals16.SKILL_CAPABLE_AGENTS.has(targetBase)) {
|
|
11846
12157
|
return { blocked: false, reason: null };
|
|
11847
12158
|
}
|
|
11848
12159
|
const skillsValue = parsed.skillsField.trim();
|
|
11849
12160
|
if (!skillsValue || skillsValue.toLowerCase() === "none") {
|
|
11850
12161
|
return { blocked: false, reason: null };
|
|
11851
12162
|
}
|
|
11852
|
-
const fileReferences =
|
|
12163
|
+
const fileReferences = _internals16.extractFileSkillReferences(skillsValue);
|
|
11853
12164
|
if (fileReferences.length === 0) {
|
|
11854
12165
|
return { blocked: false, reason: null, validatedSkillPaths: [] };
|
|
11855
12166
|
}
|
|
@@ -11862,7 +12173,7 @@ async function validateExplicitSkillReferencesBefore(directory, input, config) {
|
|
|
11862
12173
|
const context = resolveSkillAudienceContext(config);
|
|
11863
12174
|
const validatedSkillPaths = [];
|
|
11864
12175
|
for (const reference of fileReferences) {
|
|
11865
|
-
const result =
|
|
12176
|
+
const result = _internals16.validateSkillReference(directory, reference, context, {
|
|
11866
12177
|
enforceAudience: true
|
|
11867
12178
|
});
|
|
11868
12179
|
if (!result.valid) {
|
|
@@ -11907,18 +12218,18 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11907
12218
|
const baseAgent = stripKnownSwarmPrefix(agentRaw);
|
|
11908
12219
|
if (baseAgent !== "architect")
|
|
11909
12220
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11910
|
-
const parsed =
|
|
12221
|
+
const parsed = _internals16.parseDelegationArgs(input.args);
|
|
11911
12222
|
if (!parsed)
|
|
11912
12223
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11913
12224
|
const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
|
|
11914
|
-
if (!
|
|
12225
|
+
if (!_internals16.SKILL_CAPABLE_AGENTS.has(targetBase))
|
|
11915
12226
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11916
12227
|
const sessionID = typeof input.sessionID === "string" ? input.sessionID : "unknown";
|
|
11917
12228
|
const audienceContext = resolveSkillAudienceContext(config);
|
|
11918
12229
|
const availableSkills = [];
|
|
11919
12230
|
const metadataBySkillPath = new Map;
|
|
11920
|
-
for (const skillPath of
|
|
11921
|
-
const validation =
|
|
12231
|
+
for (const skillPath of _internals16.discoverAvailableSkills(directory)) {
|
|
12232
|
+
const validation = _internals16.validateSkillReference(directory, skillPath, audienceContext, { enforceAudience: true, requireFilePrefix: false });
|
|
11922
12233
|
if (!validation.valid || !validation.skillPath)
|
|
11923
12234
|
continue;
|
|
11924
12235
|
availableSkills.push(validation.skillPath);
|
|
@@ -11929,7 +12240,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11929
12240
|
const skillsValue = parsed.skillsField.trim();
|
|
11930
12241
|
if (skillsValue && skillsValue.toLowerCase() !== "none") {
|
|
11931
12242
|
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
11932
|
-
const taskId =
|
|
12243
|
+
const taskId = _internals16.extractTaskIdFromPrompt(prompt);
|
|
11933
12244
|
const skillPaths = explicitIntegrity.validatedSkillPaths ?? [];
|
|
11934
12245
|
let coderSkillPaths = [];
|
|
11935
12246
|
if (prompt) {
|
|
@@ -11938,19 +12249,19 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11938
12249
|
const trimmed = line.trim();
|
|
11939
12250
|
if (trimmed.startsWith("SKILLS_USED_BY_CODER:")) {
|
|
11940
12251
|
const fieldVal = trimmed.slice("SKILLS_USED_BY_CODER:".length).trim();
|
|
11941
|
-
coderSkillPaths =
|
|
12252
|
+
coderSkillPaths = _internals16.parseSkillPaths(fieldVal);
|
|
11942
12253
|
break;
|
|
11943
12254
|
}
|
|
11944
12255
|
}
|
|
11945
12256
|
}
|
|
11946
12257
|
const safeCoderSkillPaths = coderSkillPaths.flatMap((skillPath) => {
|
|
11947
|
-
const validation =
|
|
12258
|
+
const validation = _internals16.validateSkillReference(directory, skillPath, audienceContext, { enforceAudience: false });
|
|
11948
12259
|
return validation.valid && validation.skillPath ? [validation.skillPath] : [];
|
|
11949
12260
|
});
|
|
11950
12261
|
const allPaths = [...new Set([...skillPaths, ...safeCoderSkillPaths])];
|
|
11951
12262
|
for (const skillPath of allPaths) {
|
|
11952
12263
|
try {
|
|
11953
|
-
|
|
12264
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
11954
12265
|
skillPath,
|
|
11955
12266
|
agentName: targetBase,
|
|
11956
12267
|
taskID: taskId,
|
|
@@ -11967,18 +12278,18 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11967
12278
|
let scored = [];
|
|
11968
12279
|
if (skillsValue.toLowerCase() !== "none" && availableSkills.length > 0) {
|
|
11969
12280
|
try {
|
|
11970
|
-
const sessionEntries =
|
|
12281
|
+
const sessionEntries = _internals16.readSkillUsageEntriesTail(directory, {
|
|
11971
12282
|
sessionID
|
|
11972
12283
|
});
|
|
11973
|
-
if (sessionEntries.length >
|
|
12284
|
+
if (sessionEntries.length > _internals16.MAX_SCORING_SESSION_ENTRIES) {
|
|
11974
12285
|
scoringSkipped = true;
|
|
11975
|
-
warn(`[skill-propagation-gate] skipping scoring \u2014 tail window has ${sessionEntries.length} session entries (limit: ${
|
|
12286
|
+
warn(`[skill-propagation-gate] skipping scoring \u2014 tail window has ${sessionEntries.length} session entries (limit: ${_internals16.MAX_SCORING_SESSION_ENTRIES})`);
|
|
11976
12287
|
} else {
|
|
11977
12288
|
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
11978
12289
|
scored = availableSkills.map((skillPath) => {
|
|
11979
12290
|
const skillEntries = sessionEntries.filter((e) => e.skillPath === skillPath);
|
|
11980
|
-
const metadata = metadataBySkillPath.get(skillPath) ??
|
|
11981
|
-
const score =
|
|
12291
|
+
const metadata = metadataBySkillPath.get(skillPath) ?? _internals16.readSkillMetadata(skillPath, directory);
|
|
12292
|
+
const score = _internals16.computeSkillRelevanceScore(skillPath, prompt, skillEntries, metadata);
|
|
11982
12293
|
return { skillPath, score, usageCount: skillEntries.length };
|
|
11983
12294
|
}).sort((a, b) => b.score - a.score || b.usageCount - a.usageCount);
|
|
11984
12295
|
if (scored.length > 0) {
|
|
@@ -11992,11 +12303,11 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11992
12303
|
}
|
|
11993
12304
|
}
|
|
11994
12305
|
try {
|
|
11995
|
-
const routingPaths =
|
|
12306
|
+
const routingPaths = _internals16.loadRoutingSkills(directory, targetBase);
|
|
11996
12307
|
if (routingPaths.length > 0) {
|
|
11997
12308
|
const existingPaths = new Set(scored.map((s) => s.skillPath));
|
|
11998
12309
|
for (const routingPath of routingPaths) {
|
|
11999
|
-
const validation =
|
|
12310
|
+
const validation = _internals16.validateSkillReference(directory, routingPath, audienceContext, { enforceAudience: true, requireFilePrefix: false });
|
|
12000
12311
|
if (!validation.valid || !validation.skillPath)
|
|
12001
12312
|
continue;
|
|
12002
12313
|
const eligibleRoutingPath = validation.skillPath;
|
|
@@ -12004,7 +12315,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
12004
12315
|
metadataBySkillPath.set(eligibleRoutingPath, validation.metadata);
|
|
12005
12316
|
}
|
|
12006
12317
|
const routedSkillDir = path21.dirname(path21.join(directory, eligibleRoutingPath));
|
|
12007
|
-
if (
|
|
12318
|
+
if (_internals16.existsSync(path21.join(routedSkillDir, "retired.marker")) || _internals16.existsSync(path21.join(routedSkillDir, "stale.marker")))
|
|
12008
12319
|
continue;
|
|
12009
12320
|
if (!existingPaths.has(eligibleRoutingPath)) {
|
|
12010
12321
|
scored.push({
|
|
@@ -12030,12 +12341,12 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
12030
12341
|
} else if (typeof scored !== "undefined" && scored.length > 0) {
|
|
12031
12342
|
skillsForIndex = scored.map((r) => r.skillPath);
|
|
12032
12343
|
}
|
|
12033
|
-
const formattedIndex =
|
|
12344
|
+
const formattedIndex = _internals16.formatSkillIndexWithContext(skillsForIndex, directory, metadataBySkillPath);
|
|
12034
12345
|
if (formattedIndex.length > 0) {
|
|
12035
12346
|
const contextPath = path21.join(directory, ".swarm", "context.md");
|
|
12036
12347
|
let existingContent = "";
|
|
12037
|
-
if (
|
|
12038
|
-
existingContent =
|
|
12348
|
+
if (_internals16.existsSync(contextPath)) {
|
|
12349
|
+
existingContent = _internals16.readFileSync(contextPath, "utf-8");
|
|
12039
12350
|
}
|
|
12040
12351
|
const sectionHeader = "## Available Skills";
|
|
12041
12352
|
const newSection = `${sectionHeader}
|
|
@@ -12055,10 +12366,10 @@ ${newSection}`;
|
|
|
12055
12366
|
}
|
|
12056
12367
|
}
|
|
12057
12368
|
const swarmDir = path21.dirname(contextPath);
|
|
12058
|
-
if (!
|
|
12059
|
-
|
|
12369
|
+
if (!_internals16.existsSync(swarmDir)) {
|
|
12370
|
+
_internals16.mkdirSync(swarmDir, { recursive: true });
|
|
12060
12371
|
}
|
|
12061
|
-
|
|
12372
|
+
_internals16.writeFileSync(contextPath, updatedContent, "utf-8");
|
|
12062
12373
|
}
|
|
12063
12374
|
} catch (err) {
|
|
12064
12375
|
warn(`[skill-propagation-gate] failed to write skill index to context.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12084,7 +12395,7 @@ ${newSection}`;
|
|
|
12084
12395
|
});
|
|
12085
12396
|
const warningMsg = `Skill propagation warning: Delegating to ${targetBase} without SKILLS field. ` + `Available skills: ${skillNames.join(", ")}`;
|
|
12086
12397
|
try {
|
|
12087
|
-
|
|
12398
|
+
_internals16.writeWarnEvent(directory, {
|
|
12088
12399
|
type: "skill_propagation_warn",
|
|
12089
12400
|
timestamp: new Date().toISOString(),
|
|
12090
12401
|
tool: toolName,
|
|
@@ -12116,17 +12427,17 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12116
12427
|
const validatedProvenancePaths = (fieldValue) => {
|
|
12117
12428
|
if (remainingProvenanceValidationBudget <= 0)
|
|
12118
12429
|
return [];
|
|
12119
|
-
const references =
|
|
12430
|
+
const references = _internals16.parseSkillPaths(fieldValue).slice(0, remainingProvenanceValidationBudget);
|
|
12120
12431
|
remainingProvenanceValidationBudget -= references.length;
|
|
12121
12432
|
return references.flatMap((reference) => {
|
|
12122
|
-
const validation =
|
|
12433
|
+
const validation = _internals16.validateSkillReference(directory, reference, audienceContext, { enforceAudience: true });
|
|
12123
12434
|
return validation.valid && validation.skillPath ? [validation.skillPath] : [];
|
|
12124
12435
|
});
|
|
12125
12436
|
};
|
|
12126
12437
|
let dedupKeys = new Set;
|
|
12127
12438
|
let existingEntries = [];
|
|
12128
12439
|
try {
|
|
12129
|
-
existingEntries =
|
|
12440
|
+
existingEntries = _internals16.readSkillUsageEntriesTail(directory, {
|
|
12130
12441
|
sessionID
|
|
12131
12442
|
});
|
|
12132
12443
|
dedupKeys = new Set(existingEntries.map((e, i) => {
|
|
@@ -12197,7 +12508,7 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12197
12508
|
if (isDuplicate(skillPath, "reviewer", resolvedTaskID))
|
|
12198
12509
|
continue;
|
|
12199
12510
|
try {
|
|
12200
|
-
|
|
12511
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
12201
12512
|
skillPath,
|
|
12202
12513
|
agentName: "reviewer",
|
|
12203
12514
|
taskID: resolvedTaskID,
|
|
@@ -12242,14 +12553,14 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12242
12553
|
}
|
|
12243
12554
|
if (currentTargetAgent && skillsField && skillsField.toLowerCase() !== "none") {
|
|
12244
12555
|
const skillPaths = validatedProvenancePaths(skillsField);
|
|
12245
|
-
const taskId =
|
|
12556
|
+
const taskId = _internals16.extractTaskIdFromPrompt(text);
|
|
12246
12557
|
for (const skillPath of skillPaths) {
|
|
12247
12558
|
if (hadRecordingError)
|
|
12248
12559
|
break;
|
|
12249
12560
|
if (isDuplicate(skillPath, currentTargetAgent, taskId))
|
|
12250
12561
|
continue;
|
|
12251
12562
|
try {
|
|
12252
|
-
|
|
12563
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
12253
12564
|
skillPath,
|
|
12254
12565
|
agentName: currentTargetAgent,
|
|
12255
12566
|
taskID: taskId,
|
|
@@ -12269,18 +12580,18 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12269
12580
|
break;
|
|
12270
12581
|
}
|
|
12271
12582
|
}
|
|
12272
|
-
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12583
|
+
_internals16.skillPropagationGateBefore = skillPropagationGateBefore;
|
|
12584
|
+
_internals16.skillPropagationTransformScan = skillPropagationTransformScan;
|
|
12585
|
+
_internals16.writeWarnEvent = writeWarnEvent;
|
|
12586
|
+
_internals16.discoverAvailableSkills = discoverAvailableSkills;
|
|
12587
|
+
_internals16.parseDelegationArgs = parseDelegationArgs;
|
|
12588
|
+
_internals16.parseSkillPaths = parseSkillPaths;
|
|
12589
|
+
_internals16.extractFileSkillReferences = extractFileSkillReferences;
|
|
12590
|
+
_internals16.validateSkillReference = validateSkillReference;
|
|
12591
|
+
_internals16.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
|
|
12592
|
+
_internals16.extractSkillsFieldFromPrompt = extractSkillsFieldFromPrompt;
|
|
12593
|
+
_internals16.formatSkillIndexWithContext = formatSkillIndexWithContext;
|
|
12594
|
+
_internals16.loadRoutingSkills = loadRoutingSkills;
|
|
12284
12595
|
|
|
12285
12596
|
// src/hooks/micro-reflector.ts
|
|
12286
12597
|
var REFLECT_OUTCOMES = new Set([
|
|
@@ -12347,7 +12658,7 @@ function hashContent(content) {
|
|
|
12347
12658
|
async function canonicalExistingPath(candidate) {
|
|
12348
12659
|
let resolved = path23.resolve(candidate);
|
|
12349
12660
|
try {
|
|
12350
|
-
resolved = await
|
|
12661
|
+
resolved = await _internals17.realpath(resolved);
|
|
12351
12662
|
} catch {}
|
|
12352
12663
|
return resolved;
|
|
12353
12664
|
}
|
|
@@ -13128,9 +13439,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
13128
13439
|
} catch {}
|
|
13129
13440
|
}
|
|
13130
13441
|
if (!options?.skipAutoPromotion) {
|
|
13131
|
-
await
|
|
13442
|
+
await _internals17.runAutoPromotion(directory, config);
|
|
13132
13443
|
if (phaseInfo.phase_number > 0) {
|
|
13133
|
-
await
|
|
13444
|
+
await _internals17.runAutoDemotion(directory, config, phaseInfo.phase_number);
|
|
13134
13445
|
}
|
|
13135
13446
|
}
|
|
13136
13447
|
return { stored, reinforced, skipped, rejected, quarantined };
|
|
@@ -13245,7 +13556,7 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
13245
13556
|
}
|
|
13246
13557
|
inFlightEvidenceEntries.add(evidenceKey);
|
|
13247
13558
|
try {
|
|
13248
|
-
await
|
|
13559
|
+
await _internals17.curateAndStoreSwarm(batch.lessons, batch.projectName, { phase_number: batch.phaseNumber }, directory, config, {
|
|
13249
13560
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
13250
13561
|
enrichmentQuota: options.enrichmentQuota
|
|
13251
13562
|
});
|
|
@@ -13277,14 +13588,14 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
13277
13588
|
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
13278
13589
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
13279
13590
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
13280
|
-
await
|
|
13591
|
+
await _internals17.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config, {
|
|
13281
13592
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
13282
13593
|
enrichmentQuota: options.enrichmentQuota
|
|
13283
13594
|
});
|
|
13284
13595
|
};
|
|
13285
13596
|
return safeHook(handler);
|
|
13286
13597
|
}
|
|
13287
|
-
var
|
|
13598
|
+
var _internals17 = {
|
|
13288
13599
|
isWriteToEvidenceFile,
|
|
13289
13600
|
curateAndStoreSwarm,
|
|
13290
13601
|
runAutoPromotion,
|
|
@@ -13323,7 +13634,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13323
13634
|
return result;
|
|
13324
13635
|
}
|
|
13325
13636
|
const timestamp = args.timestamp ?? new Date().toISOString();
|
|
13326
|
-
const provider =
|
|
13637
|
+
const provider = _internals18.createConfiguredMemoryProvider(directory, memoryConfig);
|
|
13327
13638
|
try {
|
|
13328
13639
|
result.swept = true;
|
|
13329
13640
|
for (const taskId of taskIds) {
|
|
@@ -13343,7 +13654,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13343
13654
|
}
|
|
13344
13655
|
let taskRewarded = 0;
|
|
13345
13656
|
for (const runId of runIds) {
|
|
13346
|
-
const { memoriesRewarded } = await
|
|
13657
|
+
const { memoriesRewarded } = await _internals18.applyCouncilReward(provider, {
|
|
13347
13658
|
runId,
|
|
13348
13659
|
unitId: taskId,
|
|
13349
13660
|
reward: FINALIZE_NEGATIVE_TERMINAL_REWARD,
|
|
@@ -13369,7 +13680,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13369
13680
|
}
|
|
13370
13681
|
return result;
|
|
13371
13682
|
}
|
|
13372
|
-
var
|
|
13683
|
+
var _internals18 = {
|
|
13373
13684
|
createConfiguredMemoryProvider,
|
|
13374
13685
|
applyCouncilReward
|
|
13375
13686
|
};
|
|
@@ -14396,7 +14707,7 @@ async function reconcileStaleActiveSkills(directory, options = {}) {
|
|
|
14396
14707
|
continue;
|
|
14397
14708
|
}
|
|
14398
14709
|
try {
|
|
14399
|
-
const regen = await
|
|
14710
|
+
const regen = await _internals19.regenerateSkill(directory, skill.slug, {
|
|
14400
14711
|
evaluate: false
|
|
14401
14712
|
});
|
|
14402
14713
|
if (regen.regenerated) {
|
|
@@ -14646,7 +14957,7 @@ async function runSkillImprover(req) {
|
|
|
14646
14957
|
autoApply
|
|
14647
14958
|
};
|
|
14648
14959
|
}
|
|
14649
|
-
var
|
|
14960
|
+
var _internals19 = {
|
|
14650
14961
|
runSkillImprover,
|
|
14651
14962
|
buildDeterministicProposal,
|
|
14652
14963
|
buildLLMProposalFrame,
|
|
@@ -15049,13 +15360,13 @@ var write_retro = createSwarmTool({
|
|
|
15049
15360
|
task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
|
|
15050
15361
|
metadata: args.metadata
|
|
15051
15362
|
};
|
|
15052
|
-
return await
|
|
15363
|
+
return await _internals20.executeWriteRetro(writeRetroArgs, directory);
|
|
15053
15364
|
} catch {
|
|
15054
15365
|
return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
|
|
15055
15366
|
}
|
|
15056
15367
|
}
|
|
15057
15368
|
});
|
|
15058
|
-
var
|
|
15369
|
+
var _internals20 = {
|
|
15059
15370
|
executeWriteRetro,
|
|
15060
15371
|
write_retro
|
|
15061
15372
|
};
|
|
@@ -15364,8 +15675,8 @@ async function runFinalizeStage(ctx) {
|
|
|
15364
15675
|
];
|
|
15365
15676
|
ctx.curationSucceeded = false;
|
|
15366
15677
|
try {
|
|
15367
|
-
ctx.curationResult = await
|
|
15368
|
-
llmDelegate:
|
|
15678
|
+
ctx.curationResult = await _internals21.curateAndStoreSwarm(ctx.allLessons, ctx.projectName, { phase_number: 0 }, ctx.directory, ctx.config, {
|
|
15679
|
+
llmDelegate: _internals21.createCuratorLLMDelegate(ctx.directory, "phase", ctx.options.sessionID),
|
|
15369
15680
|
enrichmentQuota: {
|
|
15370
15681
|
maxCalls: ctx.config.enrichment.max_calls_per_day,
|
|
15371
15682
|
window: ctx.config.enrichment.quota_window
|
|
@@ -15384,7 +15695,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15384
15695
|
if (ctx.config.hive_enabled === false) {} else {
|
|
15385
15696
|
try {
|
|
15386
15697
|
const entries = await readKnowledge(resolveSwarmKnowledgePath(ctx.directory));
|
|
15387
|
-
const result = await
|
|
15698
|
+
const result = await _internals21.checkHivePromotions(entries, ctx.config);
|
|
15388
15699
|
ctx.hivePromoted = result.new_promotions;
|
|
15389
15700
|
} catch (hiveErr) {
|
|
15390
15701
|
const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
|
|
@@ -15405,7 +15716,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15405
15716
|
ctx.knowledgeSkillHint = ctx.sessionKnowledgeCreated > 0 ? `${ctx.sessionKnowledgeCreated} knowledge entries created this session. Consider running skill_improve or skill_generate to compile mature entries into skills.` : "";
|
|
15406
15717
|
if (ctx.runSkillReview) {
|
|
15407
15718
|
try {
|
|
15408
|
-
const { config: loadedConfig } =
|
|
15719
|
+
const { config: loadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15409
15720
|
const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
|
|
15410
15721
|
const skillReviewResult = await runAbortableSkillReview({
|
|
15411
15722
|
directory: ctx.directory,
|
|
@@ -15468,7 +15779,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15468
15779
|
}
|
|
15469
15780
|
if (!ctx.planAlreadyDone || ctx.guaranteeResult.closedPhaseIds.length > 0 || ctx.guaranteeResult.closedTaskIds.length > 0) {
|
|
15470
15781
|
try {
|
|
15471
|
-
await
|
|
15782
|
+
await _internals21.closePlanTerminalState(ctx.directory, ctx.planData, {
|
|
15472
15783
|
closedPhaseIds: ctx.guaranteeResult.closedPhaseIds,
|
|
15473
15784
|
closedTaskIds: ctx.guaranteeResult.closedTaskIds,
|
|
15474
15785
|
originalStatuses: ctx.originalStatuses
|
|
@@ -15485,11 +15796,11 @@ async function runFinalizeStage(ctx) {
|
|
|
15485
15796
|
}
|
|
15486
15797
|
try {
|
|
15487
15798
|
const { CuratorConfigSchema: CCS } = await import("./schema-aymfdrsb.js");
|
|
15488
|
-
const { config: pmLoadedConfig } =
|
|
15799
|
+
const { config: pmLoadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15489
15800
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
15490
15801
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
15491
|
-
const pmResult = await
|
|
15492
|
-
llmDelegate:
|
|
15802
|
+
const pmResult = await _internals21.runCuratorPostMortem(ctx.directory, {
|
|
15803
|
+
llmDelegate: _internals21.createCuratorLLMDelegate(ctx.directory, "postmortem", ctx.options.sessionID),
|
|
15493
15804
|
scope: "project",
|
|
15494
15805
|
sessionID: ctx.options.sessionID
|
|
15495
15806
|
});
|
|
@@ -15515,7 +15826,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
|
|
|
15515
15826
|
}
|
|
15516
15827
|
let checkpointVerified = false;
|
|
15517
15828
|
try {
|
|
15518
|
-
const result =
|
|
15829
|
+
const result = _internals21.spawnSync("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
15519
15830
|
cwd: path29.dirname(srcPath),
|
|
15520
15831
|
encoding: "utf-8",
|
|
15521
15832
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -15686,7 +15997,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
15686
15997
|
let maxAgeDays = 30;
|
|
15687
15998
|
let maxBundles = 10;
|
|
15688
15999
|
try {
|
|
15689
|
-
const { config: evidenceLoadedConfig } =
|
|
16000
|
+
const { config: evidenceLoadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15690
16001
|
const evidenceCfg = evidenceLoadedConfig.evidence ?? {};
|
|
15691
16002
|
if (typeof evidenceCfg.max_age_days === "number") {
|
|
15692
16003
|
maxAgeDays = evidenceCfg.max_age_days;
|
|
@@ -15696,7 +16007,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
15696
16007
|
}
|
|
15697
16008
|
} catch {}
|
|
15698
16009
|
try {
|
|
15699
|
-
await
|
|
16010
|
+
await _internals21.archiveEvidence(ctx.directory, maxAgeDays, maxBundles);
|
|
15700
16011
|
} catch (error2) {
|
|
15701
16012
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
15702
16013
|
ctx.warnings.push(`Evidence retention archive failed: ${msg}`);
|
|
@@ -15899,9 +16210,9 @@ async function runAlignStage(ctx) {
|
|
|
15899
16210
|
const pruneBranches = ctx.args.includes("--prune-branches");
|
|
15900
16211
|
let gitAlignResult = "";
|
|
15901
16212
|
const prunedBranches = [];
|
|
15902
|
-
const gitStatus =
|
|
16213
|
+
const gitStatus = _internals21.getGitRepositoryStatus(ctx.directory);
|
|
15903
16214
|
if (gitStatus.isRepo) {
|
|
15904
|
-
const aggressiveResult = await
|
|
16215
|
+
const aggressiveResult = await _internals21.resetToMainAfterMerge(ctx.directory, {
|
|
15905
16216
|
pruneBranches
|
|
15906
16217
|
});
|
|
15907
16218
|
if (aggressiveResult.success) {
|
|
@@ -15913,7 +16224,7 @@ async function runAlignStage(ctx) {
|
|
|
15913
16224
|
ctx.warnings.push("Uncommitted changes were discarded during git alignment");
|
|
15914
16225
|
}
|
|
15915
16226
|
} else {
|
|
15916
|
-
const alignResult = await
|
|
16227
|
+
const alignResult = await _internals21.resetToRemoteBranch(ctx.directory, {
|
|
15917
16228
|
pruneBranches
|
|
15918
16229
|
});
|
|
15919
16230
|
gitAlignResult = alignResult.message;
|
|
@@ -15973,7 +16284,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15973
16284
|
let finalizeLock = {
|
|
15974
16285
|
acquired: false
|
|
15975
16286
|
};
|
|
15976
|
-
finalizeLock = await
|
|
16287
|
+
finalizeLock = await _internals21.acquireFinalizeLock(directory);
|
|
15977
16288
|
if (!finalizeLock.acquired) {
|
|
15978
16289
|
return `\u274C Another /swarm finalize is already running for this project. If you are certain no other run is active, wait for the lock to expire or remove the stale lock and retry.`;
|
|
15979
16290
|
}
|
|
@@ -16004,7 +16315,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16004
16315
|
if (planExists) {
|
|
16005
16316
|
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
16006
16317
|
}
|
|
16007
|
-
const { config: loadedConfig } =
|
|
16318
|
+
const { config: loadedConfig } = _internals21.loadPluginConfigWithMeta(directory);
|
|
16008
16319
|
const config = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
|
|
16009
16320
|
const ctx = {
|
|
16010
16321
|
directory,
|
|
@@ -16048,7 +16359,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16048
16359
|
args
|
|
16049
16360
|
};
|
|
16050
16361
|
await runFinalizeStage(ctx);
|
|
16051
|
-
await
|
|
16362
|
+
await _internals21.runFinalizeRewardSweep({
|
|
16052
16363
|
directory,
|
|
16053
16364
|
closedTaskIds: ctx.guaranteeResult.closedTaskIds,
|
|
16054
16365
|
memoryConfig: loadedConfig.memory
|
|
@@ -16129,9 +16440,9 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16129
16440
|
}
|
|
16130
16441
|
const sessionIdsToEnd = [...swarmState.agentSessions.keys()];
|
|
16131
16442
|
for (const sessionId of sessionIdsToEnd) {
|
|
16132
|
-
|
|
16443
|
+
_internals21.endAgentSession(sessionId);
|
|
16133
16444
|
}
|
|
16134
|
-
|
|
16445
|
+
_internals21.resetSwarmStatePreservingSingletons();
|
|
16135
16446
|
const retroWarnings = ctx.warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
|
|
16136
16447
|
const otherWarnings = ctx.warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
|
|
16137
16448
|
let warningMsg = "";
|
|
@@ -16200,7 +16511,7 @@ async function acquireFinalizeLock(directory) {
|
|
|
16200
16511
|
}
|
|
16201
16512
|
return { acquired: false };
|
|
16202
16513
|
}
|
|
16203
|
-
var
|
|
16514
|
+
var _internals21 = {
|
|
16204
16515
|
ACTIVE_STATE_DIRS_TO_CLEAN,
|
|
16205
16516
|
countSessionKnowledgeEntries,
|
|
16206
16517
|
CLOSE_SKILL_REVIEW_TIMEOUT_MS,
|
|
@@ -16228,7 +16539,7 @@ var _internals20 = {
|
|
|
16228
16539
|
endAgentSession,
|
|
16229
16540
|
spawnSync: (cmd, args, options) => {
|
|
16230
16541
|
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
16231
|
-
return
|
|
16542
|
+
return child_process3.spawnSync(cmd, args, {
|
|
16232
16543
|
...options,
|
|
16233
16544
|
env: mergedEnv
|
|
16234
16545
|
});
|
|
@@ -16256,7 +16567,7 @@ var MODES = new Set(CODEBASE_REVIEW_MODES);
|
|
|
16256
16567
|
var DEFAULT_MODE = "phase0";
|
|
16257
16568
|
var DEFAULT_SCOPE = "repository root";
|
|
16258
16569
|
var FLAG_VALUE_MISSING = (token) => `Flag "${token}" requires a value`;
|
|
16259
|
-
var
|
|
16570
|
+
var USAGE2 = `Usage: /swarm codebase-review [scope] [--mode phase0|complete|defect|security|correctness|testing|ui|performance|ai-slop|enhancements|custom] [--tracks <list>] [--continue <run-id>] [--json] [--skip-update] [--allow-dirty]
|
|
16260
16571
|
|
|
16261
16572
|
Run the codebase-review-swarm workflow in the current repository.
|
|
16262
16573
|
|
|
@@ -16349,12 +16660,12 @@ function parseArgs(args) {
|
|
|
16349
16660
|
async function handleCodebaseReviewCommand(_directory, args) {
|
|
16350
16661
|
const parsed = parseArgs(args);
|
|
16351
16662
|
if (parsed.help) {
|
|
16352
|
-
return
|
|
16663
|
+
return USAGE2;
|
|
16353
16664
|
}
|
|
16354
16665
|
if (parsed.error) {
|
|
16355
16666
|
return `Error: ${parsed.error}
|
|
16356
16667
|
|
|
16357
|
-
${
|
|
16668
|
+
${USAGE2}`;
|
|
16358
16669
|
}
|
|
16359
16670
|
const scope = sanitizeText(parsed.rest.join(" "), MAX_SCOPE_LEN) || DEFAULT_SCOPE;
|
|
16360
16671
|
return [
|
|
@@ -16787,7 +17098,7 @@ function parseArgs2(args) {
|
|
|
16787
17098
|
}
|
|
16788
17099
|
return out;
|
|
16789
17100
|
}
|
|
16790
|
-
var
|
|
17101
|
+
var USAGE3 = [
|
|
16791
17102
|
"Usage: /swarm council <question> [--spec-review]",
|
|
16792
17103
|
"",
|
|
16793
17104
|
" question The question to put to the council",
|
|
@@ -16800,7 +17111,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
16800
17111
|
const parsed = parseArgs2(args);
|
|
16801
17112
|
const question = sanitizeQuestion(parsed.rest.join(" "));
|
|
16802
17113
|
if (!question) {
|
|
16803
|
-
return
|
|
17114
|
+
return USAGE3;
|
|
16804
17115
|
}
|
|
16805
17116
|
const tokens = ["MODE: COUNCIL"];
|
|
16806
17117
|
if (parsed.preset) {
|
|
@@ -16818,17 +17129,17 @@ import * as fs11 from "fs";
|
|
|
16818
17129
|
import * as path33 from "path";
|
|
16819
17130
|
|
|
16820
17131
|
// src/turbo/epic/cochange-source.ts
|
|
16821
|
-
import * as
|
|
17132
|
+
import * as child_process5 from "child_process";
|
|
16822
17133
|
import { promisify as promisify2 } from "util";
|
|
16823
17134
|
|
|
16824
17135
|
// src/tools/co-change-analyzer.ts
|
|
16825
|
-
import * as
|
|
17136
|
+
import * as child_process4 from "child_process";
|
|
16826
17137
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
16827
17138
|
import { readdir, readFile as readFile10, stat as stat3 } from "fs/promises";
|
|
16828
17139
|
import * as path32 from "path";
|
|
16829
17140
|
import { promisify } from "util";
|
|
16830
17141
|
function getExecFileAsync() {
|
|
16831
|
-
return promisify(
|
|
17142
|
+
return promisify(child_process4.execFile);
|
|
16832
17143
|
}
|
|
16833
17144
|
async function parseGitLog(directory, maxCommits) {
|
|
16834
17145
|
const commitMap = new Map;
|
|
@@ -17046,9 +17357,9 @@ async function detectDarkMatter(directory, options) {
|
|
|
17046
17357
|
} catch {
|
|
17047
17358
|
return [];
|
|
17048
17359
|
}
|
|
17049
|
-
const commitMap = await
|
|
17050
|
-
const matrix =
|
|
17051
|
-
const staticEdges = await
|
|
17360
|
+
const commitMap = await _internals22.parseGitLog(directory, maxCommitsToAnalyze);
|
|
17361
|
+
const matrix = _internals22.buildCoChangeMatrix(commitMap, maxFilesPerCommit);
|
|
17362
|
+
const staticEdges = await _internals22.getStaticEdges(directory);
|
|
17052
17363
|
const results = [];
|
|
17053
17364
|
for (const entry of matrix.values()) {
|
|
17054
17365
|
const key = `${entry.fileA}::${entry.fileB}`;
|
|
@@ -17164,11 +17475,11 @@ var co_change_analyzer = createSwarmTool({
|
|
|
17164
17475
|
npmiThreshold,
|
|
17165
17476
|
maxCommitsToAnalyze
|
|
17166
17477
|
};
|
|
17167
|
-
const pairs = await
|
|
17168
|
-
return
|
|
17478
|
+
const pairs = await _internals22.detectDarkMatter(directory, options);
|
|
17479
|
+
return _internals22.formatDarkMatterOutput(pairs);
|
|
17169
17480
|
}
|
|
17170
17481
|
});
|
|
17171
|
-
var
|
|
17482
|
+
var _internals22 = {
|
|
17172
17483
|
parseGitLog,
|
|
17173
17484
|
buildCoChangeMatrix,
|
|
17174
17485
|
getStaticEdges,
|
|
@@ -17178,14 +17489,14 @@ var _internals21 = {
|
|
|
17178
17489
|
};
|
|
17179
17490
|
|
|
17180
17491
|
// src/turbo/epic/cochange-source.ts
|
|
17181
|
-
var execFileAsync = promisify2(
|
|
17492
|
+
var execFileAsync = promisify2(child_process5.execFile);
|
|
17182
17493
|
var MAX_TRACKED_DIRS = 10;
|
|
17183
17494
|
var GIT_HEAD_TIMEOUT_MS = 5000;
|
|
17184
17495
|
var DEFAULT_MAX_COMMITS = 500;
|
|
17185
17496
|
var cache = new Map;
|
|
17186
17497
|
async function readGitHead(directory) {
|
|
17187
17498
|
try {
|
|
17188
|
-
const { stdout } = await
|
|
17499
|
+
const { stdout } = await _internals23.execFile("git", ["rev-parse", "HEAD"], {
|
|
17189
17500
|
cwd: directory,
|
|
17190
17501
|
timeout: GIT_HEAD_TIMEOUT_MS
|
|
17191
17502
|
});
|
|
@@ -17211,9 +17522,9 @@ async function getCoChangeData(directory, options) {
|
|
|
17211
17522
|
let entries;
|
|
17212
17523
|
let commitsObserved;
|
|
17213
17524
|
try {
|
|
17214
|
-
const commitMap = await
|
|
17525
|
+
const commitMap = await _internals23.parseGitLog(directory, maxCommits);
|
|
17215
17526
|
commitsObserved = commitMap.size;
|
|
17216
|
-
const matrix =
|
|
17527
|
+
const matrix = _internals23.buildCoChangeMatrix(commitMap);
|
|
17217
17528
|
entries = Array.from(matrix.values());
|
|
17218
17529
|
} catch {
|
|
17219
17530
|
return { pairs: [], commitsObserved: 0 };
|
|
@@ -17237,10 +17548,10 @@ async function getCoChangePairs(directory, options) {
|
|
|
17237
17548
|
const data = await getCoChangeData(directory, options);
|
|
17238
17549
|
return data.pairs;
|
|
17239
17550
|
}
|
|
17240
|
-
var
|
|
17551
|
+
var _internals23 = {
|
|
17241
17552
|
execFile: execFileAsync,
|
|
17242
|
-
parseGitLog:
|
|
17243
|
-
buildCoChangeMatrix:
|
|
17553
|
+
parseGitLog: _internals22.parseGitLog,
|
|
17554
|
+
buildCoChangeMatrix: _internals22.buildCoChangeMatrix
|
|
17244
17555
|
};
|
|
17245
17556
|
|
|
17246
17557
|
// src/turbo/epic/cochange-conflict.ts
|
|
@@ -17522,7 +17833,7 @@ async function handleCouplingCommand(directory, args) {
|
|
|
17522
17833
|
|
|
17523
17834
|
Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>] [--format markdown|json] [--persist]`;
|
|
17524
17835
|
}
|
|
17525
|
-
const plan = await
|
|
17836
|
+
const plan = await _internals24.loadPlanJsonOnly(directory);
|
|
17526
17837
|
if (plan === null) {
|
|
17527
17838
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` to create one before measuring coupling.";
|
|
17528
17839
|
}
|
|
@@ -17546,7 +17857,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
17546
17857
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
17547
17858
|
return { id: task.id, scope };
|
|
17548
17859
|
});
|
|
17549
|
-
const cochangePairs = await
|
|
17860
|
+
const cochangePairs = await _internals24.getCoChangePairs(directory);
|
|
17550
17861
|
const report = computeCouplingReport(tasks, cochangePairs, {
|
|
17551
17862
|
npmi: parsed.threshold,
|
|
17552
17863
|
minCoChanges: parsed.minCoChanges
|
|
@@ -17585,13 +17896,13 @@ _Warning: failed to persist report (${persistStatus.error})._`;
|
|
|
17585
17896
|
}
|
|
17586
17897
|
return `${formatCouplingReportMarkdown(report)}${persistTrailer}`;
|
|
17587
17898
|
}
|
|
17588
|
-
var
|
|
17899
|
+
var _internals24 = {
|
|
17589
17900
|
loadPlanJsonOnly,
|
|
17590
17901
|
getCoChangePairs
|
|
17591
17902
|
};
|
|
17592
17903
|
|
|
17593
17904
|
// src/commands/curate.ts
|
|
17594
|
-
var
|
|
17905
|
+
var _internals25 = {
|
|
17595
17906
|
checkHivePromotions,
|
|
17596
17907
|
readKnowledge,
|
|
17597
17908
|
resolveSwarmKnowledgePath,
|
|
@@ -17599,8 +17910,8 @@ var _internals24 = {
|
|
|
17599
17910
|
loadCuratorDeps: async () => {
|
|
17600
17911
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17601
17912
|
import("./schema-aymfdrsb.js"),
|
|
17602
|
-
import("./curator-
|
|
17603
|
-
import("./curator-llm-factory-
|
|
17913
|
+
import("./curator-5xt89z05.js"),
|
|
17914
|
+
import("./curator-llm-factory-pnhvf3s3.js")
|
|
17604
17915
|
]);
|
|
17605
17916
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17606
17917
|
}
|
|
@@ -17608,15 +17919,15 @@ var _internals24 = {
|
|
|
17608
17919
|
async function handleCurateCommand(directory, _args, options) {
|
|
17609
17920
|
try {
|
|
17610
17921
|
const config = KnowledgeConfigSchema.parse({});
|
|
17611
|
-
const swarmPath =
|
|
17612
|
-
const swarmEntries = await
|
|
17613
|
-
const summary = await
|
|
17922
|
+
const swarmPath = _internals25.resolveSwarmKnowledgePath(directory);
|
|
17923
|
+
const swarmEntries = await _internals25.readKnowledge(swarmPath) ?? [];
|
|
17924
|
+
const summary = await _internals25.checkHivePromotions(swarmEntries, config);
|
|
17614
17925
|
if (options?.sessionID) {
|
|
17615
17926
|
let onDemandPhase = 1;
|
|
17616
17927
|
try {
|
|
17617
|
-
const { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 } = await
|
|
17928
|
+
const { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 } = await _internals25.loadCuratorDeps();
|
|
17618
17929
|
const curatorConfig = CuratorConfigSchema.parse({});
|
|
17619
|
-
const priorSummary = await
|
|
17930
|
+
const priorSummary = await _internals25.readSwarmFileAsync(directory, "curator-summary.json");
|
|
17620
17931
|
if (priorSummary) {
|
|
17621
17932
|
try {
|
|
17622
17933
|
const parsed = JSON.parse(priorSummary);
|
|
@@ -17627,7 +17938,7 @@ async function handleCurateCommand(directory, _args, options) {
|
|
|
17627
17938
|
}
|
|
17628
17939
|
let planPhaseCount = Infinity;
|
|
17629
17940
|
try {
|
|
17630
|
-
const planRaw = await
|
|
17941
|
+
const planRaw = await _internals25.readSwarmFileAsync(directory, "plan.json");
|
|
17631
17942
|
if (planRaw) {
|
|
17632
17943
|
const plan = JSON.parse(planRaw);
|
|
17633
17944
|
if (Array.isArray(plan.phases))
|
|
@@ -17646,8 +17957,8 @@ async function handleCurateCommand(directory, _args, options) {
|
|
|
17646
17957
|
summary.knowledge_skipped = applied.skipped;
|
|
17647
17958
|
summary.curator_phase = onDemandPhase;
|
|
17648
17959
|
try {
|
|
17649
|
-
const updatedEntries = await
|
|
17650
|
-
const postUpdateHive = await
|
|
17960
|
+
const updatedEntries = await _internals25.readKnowledge(swarmPath) ?? [];
|
|
17961
|
+
const postUpdateHive = await _internals25.checkHivePromotions(updatedEntries, config);
|
|
17651
17962
|
summary.new_promotions += postUpdateHive.new_promotions;
|
|
17652
17963
|
summary.encounters_incremented += postUpdateHive.encounters_incremented;
|
|
17653
17964
|
summary.advancements += postUpdateHive.advancements;
|
|
@@ -17712,7 +18023,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
17712
18023
|
}
|
|
17713
18024
|
let pairs;
|
|
17714
18025
|
try {
|
|
17715
|
-
pairs = await
|
|
18026
|
+
pairs = await _internals22.detectDarkMatter(directory, options);
|
|
17716
18027
|
} catch (err) {
|
|
17717
18028
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
17718
18029
|
return `## Dark Matter Analysis Failed
|
|
@@ -17755,7 +18066,7 @@ var PROFILES = new Set([
|
|
|
17755
18066
|
var DEFAULT_PROFILE = "standard";
|
|
17756
18067
|
var DEFAULT_MAX_EXPLORERS = 6;
|
|
17757
18068
|
var FULL_PROFILE_DEFAULT_MAX_EXPLORERS = 8;
|
|
17758
|
-
var
|
|
18069
|
+
var USAGE4 = `Usage: /swarm deep-dive <scope> [--profile standard|security|ux|architecture|full] [--max-explorers N] [--json] [--skip-update] [--allow-dirty]
|
|
17759
18070
|
|
|
17760
18071
|
Run a bounded, evidence-backed deep dive on an application section.
|
|
17761
18072
|
|
|
@@ -17844,11 +18155,11 @@ async function handleDeepDiveCommand(_directory, args) {
|
|
|
17844
18155
|
if (parsed.error) {
|
|
17845
18156
|
return `Error: ${parsed.error}
|
|
17846
18157
|
|
|
17847
|
-
${
|
|
18158
|
+
${USAGE4}`;
|
|
17848
18159
|
}
|
|
17849
18160
|
const scope = sanitizeScope(parsed.rest.join(" "));
|
|
17850
18161
|
if (!scope) {
|
|
17851
|
-
return
|
|
18162
|
+
return USAGE4;
|
|
17852
18163
|
}
|
|
17853
18164
|
if (parsed.profile === "full" && !parsed.maxExplorersExplicit) {
|
|
17854
18165
|
parsed.maxExplorers = FULL_PROFILE_DEFAULT_MAX_EXPLORERS;
|
|
@@ -17865,7 +18176,7 @@ var DEFAULT_MAX_RESEARCHERS = 3;
|
|
|
17865
18176
|
var EXHAUSTIVE_DEFAULT_MAX_RESEARCHERS = 5;
|
|
17866
18177
|
var DEFAULT_ROUNDS = 2;
|
|
17867
18178
|
var EXHAUSTIVE_DEFAULT_ROUNDS = 3;
|
|
17868
|
-
var
|
|
18179
|
+
var USAGE5 = `Usage: /swarm deep-research <question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]
|
|
17869
18180
|
|
|
17870
18181
|
Run a multi-source, fact-checked deep research pass and synthesize a cited report.
|
|
17871
18182
|
|
|
@@ -17959,11 +18270,11 @@ async function handleDeepResearchCommand(_directory, args) {
|
|
|
17959
18270
|
if (parsed.error) {
|
|
17960
18271
|
return `Error: ${parsed.error}
|
|
17961
18272
|
|
|
17962
|
-
${
|
|
18273
|
+
${USAGE5}`;
|
|
17963
18274
|
}
|
|
17964
18275
|
const question = sanitizeQuestion2(parsed.rest.join(" "));
|
|
17965
18276
|
if (!question) {
|
|
17966
|
-
return
|
|
18277
|
+
return USAGE5;
|
|
17967
18278
|
}
|
|
17968
18279
|
if (parsed.depth === "exhaustive") {
|
|
17969
18280
|
if (!parsed.maxResearchersExplicit)
|
|
@@ -17976,7 +18287,7 @@ ${USAGE4}`;
|
|
|
17976
18287
|
|
|
17977
18288
|
// src/commands/design-docs.ts
|
|
17978
18289
|
var MAX_DESC_LEN = 2000;
|
|
17979
|
-
var
|
|
18290
|
+
var USAGE6 = `Usage: /swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]
|
|
17980
18291
|
|
|
17981
18292
|
Generate or sync language-agnostic design docs for the project under build:
|
|
17982
18293
|
<out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md,
|
|
@@ -18068,35 +18379,35 @@ async function handleDesignDocsCommand(directory, args) {
|
|
|
18068
18379
|
if (parsed.error) {
|
|
18069
18380
|
return `Error: ${parsed.error}
|
|
18070
18381
|
|
|
18071
|
-
${
|
|
18382
|
+
${USAGE6}`;
|
|
18072
18383
|
}
|
|
18073
18384
|
try {
|
|
18074
18385
|
const { config } = loadPluginConfigWithMeta(directory);
|
|
18075
18386
|
if (config.design_docs?.enabled !== true) {
|
|
18076
18387
|
return "Error: design docs are disabled. Set `design_docs.enabled: true` in " + `opencode-swarm.json to enable the docs_design agent and this command.
|
|
18077
18388
|
|
|
18078
|
-
` +
|
|
18389
|
+
` + USAGE6;
|
|
18079
18390
|
}
|
|
18080
18391
|
} catch (configErr) {
|
|
18081
18392
|
console.warn(`[design-docs] Could not read opencode-swarm.json (${String(configErr)}). ` + "Falling through \u2014 the architect will abort if docs_design is not registered.");
|
|
18082
18393
|
}
|
|
18083
18394
|
const description = sanitizeDescription(parsed.rest.join(" "));
|
|
18084
18395
|
if (!description && !parsed.update) {
|
|
18085
|
-
return
|
|
18396
|
+
return USAGE6;
|
|
18086
18397
|
}
|
|
18087
18398
|
const header = `[MODE: DESIGN_DOCS out=${parsed.out} lang=${parsed.lang} update=${parsed.update}] ${description}`;
|
|
18088
18399
|
return header.trimEnd();
|
|
18089
18400
|
}
|
|
18090
18401
|
|
|
18091
18402
|
// src/services/diagnose-service.ts
|
|
18092
|
-
import * as
|
|
18403
|
+
import * as child_process6 from "child_process";
|
|
18093
18404
|
import { existsSync as existsSync23, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
18094
18405
|
import * as path36 from "path";
|
|
18095
18406
|
import { fileURLToPath } from "url";
|
|
18096
18407
|
// package.json
|
|
18097
18408
|
var package_default = {
|
|
18098
18409
|
name: "opencode-swarm",
|
|
18099
|
-
version: "7.114.
|
|
18410
|
+
version: "7.114.9",
|
|
18100
18411
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18101
18412
|
main: "dist/index.js",
|
|
18102
18413
|
types: "dist/index.d.ts",
|
|
@@ -18548,7 +18859,7 @@ function resolveCachePackageRoot(cachePath) {
|
|
|
18548
18859
|
const nestedPackageRoot = path36.join(cachePath, "node_modules", "opencode-swarm");
|
|
18549
18860
|
return existsSync23(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
18550
18861
|
}
|
|
18551
|
-
var
|
|
18862
|
+
var _internals26 = {
|
|
18552
18863
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
18553
18864
|
getSandboxExecutor: getExecutor
|
|
18554
18865
|
};
|
|
@@ -18804,7 +19115,7 @@ async function checkGitRepository(directory) {
|
|
|
18804
19115
|
detail: "Invalid directory \u2014 cannot check git status"
|
|
18805
19116
|
};
|
|
18806
19117
|
}
|
|
18807
|
-
|
|
19118
|
+
child_process6.execSync("git rev-parse --git-dir", {
|
|
18808
19119
|
cwd: directory,
|
|
18809
19120
|
stdio: "pipe"
|
|
18810
19121
|
});
|
|
@@ -19132,9 +19443,9 @@ async function checkCurator(directory) {
|
|
|
19132
19443
|
}
|
|
19133
19444
|
async function getSandboxStatus() {
|
|
19134
19445
|
try {
|
|
19135
|
-
const capability = await
|
|
19446
|
+
const capability = await _internals26.detectSandboxCapability();
|
|
19136
19447
|
const mechanism = capability.mechanism ?? "none";
|
|
19137
|
-
const executor = await
|
|
19448
|
+
const executor = await _internals26.getSandboxExecutor();
|
|
19138
19449
|
const hasExecutor = executor !== null;
|
|
19139
19450
|
if (hasExecutor) {
|
|
19140
19451
|
const executorStrength = executor?.strength;
|
|
@@ -19886,7 +20197,7 @@ function readPromotionEvidence(directory) {
|
|
|
19886
20197
|
}
|
|
19887
20198
|
|
|
19888
20199
|
// src/commands/epic.ts
|
|
19889
|
-
var
|
|
20200
|
+
var _internals27 = {
|
|
19890
20201
|
loadPluginConfigWithMeta,
|
|
19891
20202
|
loadPlanJsonOnly,
|
|
19892
20203
|
getCoChangeData,
|
|
@@ -19908,7 +20219,7 @@ async function handleEpicCommand(directory, args, sessionID) {
|
|
|
19908
20219
|
if (!sessionID || sessionID.trim() === "") {
|
|
19909
20220
|
return "Error: No active session context. Epic Mode requires an active session. Use /swarm epic from within an OpenCode session.";
|
|
19910
20221
|
}
|
|
19911
|
-
const session =
|
|
20222
|
+
const session = _internals27.ensureAgentSession(sessionID, undefined, directory);
|
|
19912
20223
|
const arg0 = args[0]?.toLowerCase();
|
|
19913
20224
|
switch (arg0) {
|
|
19914
20225
|
case "status":
|
|
@@ -19935,7 +20246,7 @@ Usage:
|
|
|
19935
20246
|
}
|
|
19936
20247
|
function enableAndAck(directory, sessionID, session) {
|
|
19937
20248
|
try {
|
|
19938
|
-
|
|
20249
|
+
_internals27.enableEpicMode(directory, sessionID);
|
|
19939
20250
|
} catch (err) {
|
|
19940
20251
|
return `Error enabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
19941
20252
|
}
|
|
@@ -19951,7 +20262,7 @@ function enableAndAck(directory, sessionID, session) {
|
|
|
19951
20262
|
}
|
|
19952
20263
|
function disableAndAck(directory, sessionID, session) {
|
|
19953
20264
|
try {
|
|
19954
|
-
|
|
20265
|
+
_internals27.disableEpicMode(directory, sessionID);
|
|
19955
20266
|
} catch (err) {
|
|
19956
20267
|
return `Error disabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
19957
20268
|
}
|
|
@@ -19960,12 +20271,12 @@ function disableAndAck(directory, sessionID, session) {
|
|
|
19960
20271
|
}
|
|
19961
20272
|
function renderStatus(directory, sessionID) {
|
|
19962
20273
|
const lines = ["## Epic Mode \u2014 Status", ""];
|
|
19963
|
-
if (
|
|
20274
|
+
if (_internals27.isStateUnreadable(directory)) {
|
|
19964
20275
|
lines.push("**Epic Mode state is unreadable** (`.swarm/epic-state.json` is corrupt or has an unexpected shape). Status cannot be reported until the file is repaired or removed. The fail-closed marker means `epic_decide_phase` will refuse to compute a verdict in this state.");
|
|
19965
20276
|
return lines.join(`
|
|
19966
20277
|
`);
|
|
19967
20278
|
}
|
|
19968
|
-
const state =
|
|
20279
|
+
const state = _internals27.loadEpicSessionState(directory, sessionID);
|
|
19969
20280
|
if (!state) {
|
|
19970
20281
|
lines.push("Epic Mode has not been toggled for this session.");
|
|
19971
20282
|
return lines.join(`
|
|
@@ -20017,7 +20328,7 @@ function formatGreenfieldDetail(input) {
|
|
|
20017
20328
|
function renderLast(directory) {
|
|
20018
20329
|
let records;
|
|
20019
20330
|
try {
|
|
20020
|
-
records =
|
|
20331
|
+
records = _internals27.readPromotionEvidence(directory);
|
|
20021
20332
|
} catch (err) {
|
|
20022
20333
|
return `Error reading epic-promotions.jsonl: ${err instanceof Error ? err.message : String(err)}`;
|
|
20023
20334
|
}
|
|
@@ -20072,7 +20383,7 @@ function renderLast(directory) {
|
|
|
20072
20383
|
`);
|
|
20073
20384
|
}
|
|
20074
20385
|
function renderCalibration(directory) {
|
|
20075
|
-
if (
|
|
20386
|
+
if (_internals27.isCalibrationStateUnreadable(directory)) {
|
|
20076
20387
|
return [
|
|
20077
20388
|
"## Epic Mode \u2014 Calibration",
|
|
20078
20389
|
"",
|
|
@@ -20084,11 +20395,11 @@ function renderCalibration(directory) {
|
|
|
20084
20395
|
}
|
|
20085
20396
|
let state;
|
|
20086
20397
|
try {
|
|
20087
|
-
state =
|
|
20398
|
+
state = _internals27.loadCalibrationState(directory);
|
|
20088
20399
|
} catch (err) {
|
|
20089
20400
|
return `Error reading calibration state: ${err instanceof Error ? err.message : String(err)}`;
|
|
20090
20401
|
}
|
|
20091
|
-
const { config } =
|
|
20402
|
+
const { config } = _internals27.loadPluginConfigWithMeta(directory);
|
|
20092
20403
|
const staticThreshold = config.turbo?.epic?.mode?.activation_threshold ?? 0.3;
|
|
20093
20404
|
const calibrationCfg = config.turbo?.epic?.calibration;
|
|
20094
20405
|
const loosenWindow = calibrationCfg?.loosen_window ?? 10;
|
|
@@ -20136,7 +20447,7 @@ function renderCalibration(directory) {
|
|
|
20136
20447
|
lines.push("");
|
|
20137
20448
|
let recentDivergent = [];
|
|
20138
20449
|
try {
|
|
20139
|
-
const all =
|
|
20450
|
+
const all = _internals27.readDivergenceHistory(directory, { limit: 50 });
|
|
20140
20451
|
recentDivergent = all.filter((r) => !r.isClean).slice(-5);
|
|
20141
20452
|
} catch {}
|
|
20142
20453
|
lines.push("### Recent divergent tasks (tightened the threshold)");
|
|
@@ -20153,11 +20464,11 @@ function renderCalibration(directory) {
|
|
|
20153
20464
|
`);
|
|
20154
20465
|
}
|
|
20155
20466
|
async function renderDecide(directory) {
|
|
20156
|
-
const plan = await
|
|
20467
|
+
const plan = await _internals27.loadPlanJsonOnly(directory);
|
|
20157
20468
|
if (!plan) {
|
|
20158
20469
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` first.";
|
|
20159
20470
|
}
|
|
20160
|
-
const { config } =
|
|
20471
|
+
const { config } = _internals27.loadPluginConfigWithMeta(directory);
|
|
20161
20472
|
const modeCfg = config.turbo?.epic?.mode;
|
|
20162
20473
|
const cochangeCfg = config.turbo?.epic?.cochange;
|
|
20163
20474
|
const activationThreshold = modeCfg?.activation_threshold ?? 0.3;
|
|
@@ -20167,20 +20478,20 @@ async function renderDecide(directory) {
|
|
|
20167
20478
|
const tasks = [];
|
|
20168
20479
|
for (const phase of plan.phases) {
|
|
20169
20480
|
for (const task of phase.tasks) {
|
|
20170
|
-
const scopeFiles =
|
|
20481
|
+
const scopeFiles = _internals27.readTaskScopes(directory, task.id);
|
|
20171
20482
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
20172
20483
|
tasks.push({ id: task.id, scope });
|
|
20173
20484
|
}
|
|
20174
20485
|
}
|
|
20175
|
-
const { pairs, commitsObserved } = await
|
|
20486
|
+
const { pairs, commitsObserved } = await _internals27.getCoChangeData(directory);
|
|
20176
20487
|
const isGitProject = (() => {
|
|
20177
20488
|
try {
|
|
20178
|
-
return
|
|
20489
|
+
return _internals27.isGitRepo(directory);
|
|
20179
20490
|
} catch {
|
|
20180
20491
|
return false;
|
|
20181
20492
|
}
|
|
20182
20493
|
})();
|
|
20183
|
-
const verdict =
|
|
20494
|
+
const verdict = _internals27.decideEpicActivation(tasks, pairs, commitsObserved, {
|
|
20184
20495
|
activationThreshold,
|
|
20185
20496
|
minCommitsForSignal,
|
|
20186
20497
|
cochangeNpmiThreshold,
|
|
@@ -20224,7 +20535,7 @@ function formatVerdict(verdict) {
|
|
|
20224
20535
|
}
|
|
20225
20536
|
|
|
20226
20537
|
// src/services/evidence-service.ts
|
|
20227
|
-
var
|
|
20538
|
+
var _internals28 = {
|
|
20228
20539
|
loadEvidence,
|
|
20229
20540
|
listEvidenceTaskIds
|
|
20230
20541
|
};
|
|
@@ -20269,7 +20580,7 @@ function getVerdictEmoji(verdict) {
|
|
|
20269
20580
|
return getVerdictIcon(verdict);
|
|
20270
20581
|
}
|
|
20271
20582
|
async function getTaskEvidenceData(directory, taskId) {
|
|
20272
|
-
const result = await
|
|
20583
|
+
const result = await _internals28.loadEvidence(directory, taskId);
|
|
20273
20584
|
if (result.status !== "found") {
|
|
20274
20585
|
return {
|
|
20275
20586
|
hasEvidence: false,
|
|
@@ -20292,13 +20603,13 @@ async function getTaskEvidenceData(directory, taskId) {
|
|
|
20292
20603
|
};
|
|
20293
20604
|
}
|
|
20294
20605
|
async function getEvidenceListData(directory) {
|
|
20295
|
-
const taskIds = await
|
|
20606
|
+
const taskIds = await _internals28.listEvidenceTaskIds(directory);
|
|
20296
20607
|
if (taskIds.length === 0) {
|
|
20297
20608
|
return { hasEvidence: false, tasks: [] };
|
|
20298
20609
|
}
|
|
20299
20610
|
const tasks = [];
|
|
20300
20611
|
for (const taskId of taskIds) {
|
|
20301
|
-
const result = await
|
|
20612
|
+
const result = await _internals28.loadEvidence(directory, taskId);
|
|
20302
20613
|
if (result.status === "found") {
|
|
20303
20614
|
tasks.push({
|
|
20304
20615
|
taskId,
|
|
@@ -20378,7 +20689,7 @@ async function handleEvidenceCommand(directory, args) {
|
|
|
20378
20689
|
return formatTaskEvidenceMarkdown(evidenceData);
|
|
20379
20690
|
}
|
|
20380
20691
|
async function handleEvidenceSummaryCommand(directory) {
|
|
20381
|
-
const { buildEvidenceSummary } = await import("./evidence-summary-service-
|
|
20692
|
+
const { buildEvidenceSummary } = await import("./evidence-summary-service-fehwj116.js");
|
|
20382
20693
|
const artifact = await buildEvidenceSummary(directory);
|
|
20383
20694
|
if (!artifact) {
|
|
20384
20695
|
return "No plan found. Run `/swarm plan` to check plan status.";
|
|
@@ -20926,7 +21237,7 @@ function extractCurrentPhaseFromPlan(plan) {
|
|
|
20926
21237
|
if (!plan) {
|
|
20927
21238
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
20928
21239
|
}
|
|
20929
|
-
if (!
|
|
21240
|
+
if (!_internals29.validatePlanPhases(plan)) {
|
|
20930
21241
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
20931
21242
|
}
|
|
20932
21243
|
let currentPhase = null;
|
|
@@ -21068,9 +21379,9 @@ function extractPhaseMetrics(content) {
|
|
|
21068
21379
|
async function getHandoffData(directory) {
|
|
21069
21380
|
const now = new Date().toISOString();
|
|
21070
21381
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
21071
|
-
const sessionState =
|
|
21382
|
+
const sessionState = _internals29.parseSessionState(sessionContent);
|
|
21072
21383
|
const plan = await loadPlanJsonOnly(directory);
|
|
21073
|
-
const planInfo =
|
|
21384
|
+
const planInfo = _internals29.extractCurrentPhaseFromPlan(plan);
|
|
21074
21385
|
if (!plan) {
|
|
21075
21386
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
21076
21387
|
if (planMdContent) {
|
|
@@ -21089,8 +21400,8 @@ async function getHandoffData(directory) {
|
|
|
21089
21400
|
}
|
|
21090
21401
|
}
|
|
21091
21402
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
21092
|
-
const recentDecisions =
|
|
21093
|
-
const rawPhaseMetrics =
|
|
21403
|
+
const recentDecisions = _internals29.extractDecisions(contextContent);
|
|
21404
|
+
const rawPhaseMetrics = _internals29.extractPhaseMetrics(contextContent);
|
|
21094
21405
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
21095
21406
|
let delegationState = null;
|
|
21096
21407
|
if (sessionState?.delegationState) {
|
|
@@ -21254,7 +21565,7 @@ ${lines.join(`
|
|
|
21254
21565
|
`)}
|
|
21255
21566
|
\`\`\``;
|
|
21256
21567
|
}
|
|
21257
|
-
var
|
|
21568
|
+
var _internals29 = {
|
|
21258
21569
|
getHandoffData,
|
|
21259
21570
|
formatHandoffMarkdown,
|
|
21260
21571
|
formatContinuationPrompt,
|
|
@@ -21403,15 +21714,15 @@ async function writeSnapshot(directory, state) {
|
|
|
21403
21714
|
}
|
|
21404
21715
|
function createSnapshotWriterHook(directory) {
|
|
21405
21716
|
return (_input, _output) => {
|
|
21406
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
21717
|
+
_writeInFlight = _writeInFlight.then(() => _internals30.writeSnapshot(directory, swarmState), () => _internals30.writeSnapshot(directory, swarmState));
|
|
21407
21718
|
return _writeInFlight;
|
|
21408
21719
|
};
|
|
21409
21720
|
}
|
|
21410
21721
|
async function flushPendingSnapshot(directory) {
|
|
21411
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
21722
|
+
_writeInFlight = _writeInFlight.then(() => _internals30.writeSnapshot(directory, swarmState), () => _internals30.writeSnapshot(directory, swarmState));
|
|
21412
21723
|
await _writeInFlight;
|
|
21413
21724
|
}
|
|
21414
|
-
var
|
|
21725
|
+
var _internals30 = {
|
|
21415
21726
|
writeSnapshot,
|
|
21416
21727
|
createSnapshotWriterHook,
|
|
21417
21728
|
flushPendingSnapshot
|
|
@@ -21608,184 +21919,8 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
21608
21919
|
const historyData = await getHistoryData(directory);
|
|
21609
21920
|
return formatHistoryMarkdown(historyData);
|
|
21610
21921
|
}
|
|
21611
|
-
// src/commands/_shared/url-security.ts
|
|
21612
|
-
import * as child_process6 from "child_process";
|
|
21613
|
-
var MAX_URL_LEN = 2048;
|
|
21614
|
-
var IPV4_PRIVATE = /^10\./;
|
|
21615
|
-
var IPV4_LOOPBACK = /^127\./;
|
|
21616
|
-
var IPV4_LINK_LOCAL = /^169\.254\./;
|
|
21617
|
-
var IPV4_PRIVATE_172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
|
|
21618
|
-
var IPV4_PRIVATE_192 = /^192\.168\./;
|
|
21619
|
-
var IPV4_ZERO_NETWORK = /^0\./;
|
|
21620
|
-
var IPV6_LINK_LOCAL = /^fe80:/i;
|
|
21621
|
-
var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
|
|
21622
|
-
var _internals30 = {
|
|
21623
|
-
spawnSync: (cmd, args, options) => {
|
|
21624
|
-
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
21625
|
-
return child_process6.spawnSync(cmd, args, {
|
|
21626
|
-
...options,
|
|
21627
|
-
env: mergedEnv
|
|
21628
|
-
});
|
|
21629
|
-
}
|
|
21630
|
-
};
|
|
21631
|
-
function sanitizeUrl(raw) {
|
|
21632
|
-
let urlStr = raw.trim();
|
|
21633
|
-
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
21634
|
-
const fragmentIdx = urlStr.indexOf("#");
|
|
21635
|
-
if (fragmentIdx !== -1) {
|
|
21636
|
-
urlStr = urlStr.slice(0, fragmentIdx);
|
|
21637
|
-
}
|
|
21638
|
-
const queryIdx = urlStr.indexOf("?");
|
|
21639
|
-
if (queryIdx !== -1) {
|
|
21640
|
-
urlStr = urlStr.slice(0, queryIdx);
|
|
21641
|
-
}
|
|
21642
|
-
urlStr = urlStr.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^@/]+@/, "https://");
|
|
21643
|
-
if (urlStr.length > MAX_URL_LEN) {
|
|
21644
|
-
urlStr = urlStr.slice(0, MAX_URL_LEN);
|
|
21645
|
-
}
|
|
21646
|
-
return urlStr.trim();
|
|
21647
|
-
}
|
|
21648
|
-
function sanitizeErrorEcho(raw, maxLength = 80) {
|
|
21649
|
-
let stripped = "";
|
|
21650
|
-
for (const ch of raw) {
|
|
21651
|
-
const cp = ch.codePointAt(0);
|
|
21652
|
-
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
21653
|
-
stripped += " ";
|
|
21654
|
-
continue;
|
|
21655
|
-
}
|
|
21656
|
-
stripped += ch;
|
|
21657
|
-
}
|
|
21658
|
-
const collapsed = stripped.replace(/\s+/g, " ").trim();
|
|
21659
|
-
if (collapsed.length <= maxLength)
|
|
21660
|
-
return collapsed;
|
|
21661
|
-
return `${collapsed.slice(0, maxLength)}\u2026`;
|
|
21662
|
-
}
|
|
21663
|
-
function containsControlCharacters(value) {
|
|
21664
|
-
for (const ch of value) {
|
|
21665
|
-
const cp = ch.codePointAt(0);
|
|
21666
|
-
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
21667
|
-
return true;
|
|
21668
|
-
}
|
|
21669
|
-
}
|
|
21670
|
-
return false;
|
|
21671
|
-
}
|
|
21672
|
-
function hasNonAsciiHostname(hostname) {
|
|
21673
|
-
for (const ch of hostname) {
|
|
21674
|
-
const cp = ch.codePointAt(0);
|
|
21675
|
-
if (cp !== undefined && cp > 127)
|
|
21676
|
-
return true;
|
|
21677
|
-
}
|
|
21678
|
-
return false;
|
|
21679
|
-
}
|
|
21680
|
-
function isIpv4MappedPrivateHost(inner) {
|
|
21681
|
-
if (IPV4_PRIVATE.test(inner) || IPV4_LOOPBACK.test(inner) || IPV4_LINK_LOCAL.test(inner) || IPV4_PRIVATE_172.test(inner) || IPV4_PRIVATE_192.test(inner) || IPV4_ZERO_NETWORK.test(inner)) {
|
|
21682
|
-
return true;
|
|
21683
|
-
}
|
|
21684
|
-
const firstSegment = inner.split(":", 1)[0];
|
|
21685
|
-
if (!firstSegment)
|
|
21686
|
-
return false;
|
|
21687
|
-
const firstWord = Number.parseInt(firstSegment, 16);
|
|
21688
|
-
if (!Number.isFinite(firstWord))
|
|
21689
|
-
return false;
|
|
21690
|
-
return firstWord >= 0 && firstWord <= 255 || firstWord >= 2560 && firstWord <= 2815 || firstWord >= 32512 && firstWord <= 32767 || firstWord === 43518 || firstWord >= 44048 && firstWord <= 44063 || firstWord === 49320;
|
|
21691
|
-
}
|
|
21692
|
-
function isPrivateHost(url) {
|
|
21693
|
-
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
21694
|
-
if (host === "localhost" || host === "::1" || host === "0.0.0.0" || IPV4_LOOPBACK.test(host) || IPV4_ZERO_NETWORK.test(host)) {
|
|
21695
|
-
return true;
|
|
21696
|
-
}
|
|
21697
|
-
if (host.startsWith("localhost") || host === "localhost.com") {
|
|
21698
|
-
return true;
|
|
21699
|
-
}
|
|
21700
|
-
if (IPV4_PRIVATE.test(host) || IPV4_LINK_LOCAL.test(host) || IPV4_PRIVATE_172.test(host) || IPV4_PRIVATE_192.test(host) || IPV6_LINK_LOCAL.test(host) || IPV6_UNIQUE_LOCAL.test(host)) {
|
|
21701
|
-
return true;
|
|
21702
|
-
}
|
|
21703
|
-
if (host.startsWith("::ffff:")) {
|
|
21704
|
-
const inner = host.slice(7);
|
|
21705
|
-
if (isIpv4MappedPrivateHost(inner)) {
|
|
21706
|
-
return true;
|
|
21707
|
-
}
|
|
21708
|
-
}
|
|
21709
|
-
return false;
|
|
21710
|
-
}
|
|
21711
|
-
function validateAndSanitizeGithubUrl(rawUrl, resource) {
|
|
21712
|
-
const sanitized = sanitizeUrl(rawUrl);
|
|
21713
|
-
if (!sanitized) {
|
|
21714
|
-
return { error: "Empty URL" };
|
|
21715
|
-
}
|
|
21716
|
-
if (!sanitized.startsWith("https://")) {
|
|
21717
|
-
return { error: "URL must use HTTPS scheme" };
|
|
21718
|
-
}
|
|
21719
|
-
try {
|
|
21720
|
-
const url = new URL(sanitized);
|
|
21721
|
-
if (hasNonAsciiHostname(url.hostname)) {
|
|
21722
|
-
return { error: "Non-ASCII hostnames are not allowed" };
|
|
21723
|
-
}
|
|
21724
|
-
if (isPrivateHost(url)) {
|
|
21725
|
-
return { error: "Private or localhost URLs are not allowed" };
|
|
21726
|
-
}
|
|
21727
|
-
const githubPattern = new RegExp(`^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/${resource}\\/([0-9]+)\\/?$`);
|
|
21728
|
-
if (!githubPattern.test(sanitized)) {
|
|
21729
|
-
return {
|
|
21730
|
-
error: resource === "issues" ? "URL must be a GitHub issue URL (https://github.com/owner/repo/issues/N)" : "URL must be a GitHub pull request URL (https://github.com/owner/repo/pull/N)"
|
|
21731
|
-
};
|
|
21732
|
-
}
|
|
21733
|
-
return { sanitized };
|
|
21734
|
-
} catch {
|
|
21735
|
-
return { error: "Invalid URL format" };
|
|
21736
|
-
}
|
|
21737
|
-
}
|
|
21738
|
-
function detectGitRemote(cwd, laneEnv) {
|
|
21739
|
-
try {
|
|
21740
|
-
const result = _internals30.spawnSync("git", ["remote", "get-url", "origin"], {
|
|
21741
|
-
encoding: "utf-8",
|
|
21742
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
21743
|
-
timeout: 5000,
|
|
21744
|
-
...cwd ? { cwd } : {},
|
|
21745
|
-
envOverrides: laneEnv
|
|
21746
|
-
});
|
|
21747
|
-
if (result.status !== 0 || result.error) {
|
|
21748
|
-
return null;
|
|
21749
|
-
}
|
|
21750
|
-
const remoteUrl = (result.stdout ?? "").trim();
|
|
21751
|
-
return remoteUrl || null;
|
|
21752
|
-
} catch {
|
|
21753
|
-
return null;
|
|
21754
|
-
}
|
|
21755
|
-
}
|
|
21756
|
-
function parseGitRemoteUrl(remoteUrl) {
|
|
21757
|
-
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
21758
|
-
if (httpsMatch) {
|
|
21759
|
-
const owner = httpsMatch[1];
|
|
21760
|
-
const repo = httpsMatch[2].replace(/\.git$/, "");
|
|
21761
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21762
|
-
return null;
|
|
21763
|
-
}
|
|
21764
|
-
return { owner, repo };
|
|
21765
|
-
}
|
|
21766
|
-
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
21767
|
-
if (sshMatch) {
|
|
21768
|
-
const owner = sshMatch[1];
|
|
21769
|
-
const repo = sshMatch[2].replace(/\.git$/, "");
|
|
21770
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21771
|
-
return null;
|
|
21772
|
-
}
|
|
21773
|
-
return { owner, repo };
|
|
21774
|
-
}
|
|
21775
|
-
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
21776
|
-
if (pathMatch) {
|
|
21777
|
-
const owner = pathMatch[1];
|
|
21778
|
-
const repo = pathMatch[2].replace(/\.git$/, "");
|
|
21779
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21780
|
-
return null;
|
|
21781
|
-
}
|
|
21782
|
-
return { owner, repo };
|
|
21783
|
-
}
|
|
21784
|
-
return null;
|
|
21785
|
-
}
|
|
21786
|
-
|
|
21787
21922
|
// src/commands/issue.ts
|
|
21788
|
-
var
|
|
21923
|
+
var USAGE7 = [
|
|
21789
21924
|
"Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
|
|
21790
21925
|
"",
|
|
21791
21926
|
"Ingest a GitHub issue into the swarm workflow.",
|
|
@@ -21800,7 +21935,7 @@ var USAGE6 = [
|
|
|
21800
21935
|
" --no-repro Skip reproduction step"
|
|
21801
21936
|
].join(`
|
|
21802
21937
|
`);
|
|
21803
|
-
function
|
|
21938
|
+
function validateAndSanitizeUrl2(rawUrl) {
|
|
21804
21939
|
return validateAndSanitizeGithubUrl(rawUrl, "issues");
|
|
21805
21940
|
}
|
|
21806
21941
|
function parseArgs7(args) {
|
|
@@ -21874,21 +22009,21 @@ function handleIssueCommand(directory, args) {
|
|
|
21874
22009
|
const parsed = parseArgs7(args);
|
|
21875
22010
|
const rawInput = parsed.rest.join(" ").trim();
|
|
21876
22011
|
if (!rawInput) {
|
|
21877
|
-
return
|
|
22012
|
+
return USAGE7;
|
|
21878
22013
|
}
|
|
21879
22014
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
21880
22015
|
const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput, directory);
|
|
21881
22016
|
if (!issueInfo) {
|
|
21882
22017
|
return `Error: Could not parse issue reference from "${sanitizeErrorEcho(rawInput)}"
|
|
21883
22018
|
|
|
21884
|
-
${
|
|
22019
|
+
${USAGE7}`;
|
|
21885
22020
|
}
|
|
21886
22021
|
const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
|
|
21887
|
-
const result =
|
|
22022
|
+
const result = validateAndSanitizeUrl2(issueUrl);
|
|
21888
22023
|
if ("error" in result) {
|
|
21889
22024
|
return `Error: ${result.error}
|
|
21890
22025
|
|
|
21891
|
-
${
|
|
22026
|
+
${USAGE7}`;
|
|
21892
22027
|
}
|
|
21893
22028
|
const flags = [];
|
|
21894
22029
|
if (parsed.plan)
|
|
@@ -22957,7 +23092,7 @@ async function readLatestLoopState(directory) {
|
|
|
22957
23092
|
var _internals33 = {
|
|
22958
23093
|
readLatestLoopState
|
|
22959
23094
|
};
|
|
22960
|
-
var
|
|
23095
|
+
var USAGE8 = `Usage: /swarm loop <objective> [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]
|
|
22961
23096
|
|
|
22962
23097
|
Run a compound-engineering loop: brainstorm \u2192 plan \u2192 build \u2192 review \u2192 improve,
|
|
22963
23098
|
iterating until the objective is met or a budget stop condition fires.
|
|
@@ -23059,11 +23194,11 @@ async function handleLoopCommand(_directory, args) {
|
|
|
23059
23194
|
if (parsed.error) {
|
|
23060
23195
|
return `Error: ${parsed.error}
|
|
23061
23196
|
|
|
23062
|
-
${
|
|
23197
|
+
${USAGE8}`;
|
|
23063
23198
|
}
|
|
23064
23199
|
const objective = sanitizeObjective(parsed.rest.join(" "));
|
|
23065
23200
|
if (!objective && !parsed.resume) {
|
|
23066
|
-
return
|
|
23201
|
+
return USAGE8;
|
|
23067
23202
|
}
|
|
23068
23203
|
let autonomy = parsed.autonomy;
|
|
23069
23204
|
if (parsed.resume && !parsed.autonomyExplicit) {
|
|
@@ -24234,85 +24369,6 @@ async function handlePostMortemCommand(directory, args, options) {
|
|
|
24234
24369
|
}
|
|
24235
24370
|
}
|
|
24236
24371
|
|
|
24237
|
-
// src/commands/pr-ref.ts
|
|
24238
|
-
var MAX_INSTRUCTIONS_LEN = 1000;
|
|
24239
|
-
function sanitizeInstructions(raw) {
|
|
24240
|
-
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
24241
|
-
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
24242
|
-
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
24243
|
-
if (normalized.length <= MAX_INSTRUCTIONS_LEN)
|
|
24244
|
-
return normalized;
|
|
24245
|
-
return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}\u2026`;
|
|
24246
|
-
}
|
|
24247
|
-
function validateAndSanitizeUrl2(rawUrl) {
|
|
24248
|
-
return validateAndSanitizeGithubUrl(rawUrl, "pull");
|
|
24249
|
-
}
|
|
24250
|
-
function parsePrRef(input, cwd) {
|
|
24251
|
-
const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
|
|
24252
|
-
if (urlMatch) {
|
|
24253
|
-
if (containsControlCharacters(urlMatch[1]) || containsControlCharacters(urlMatch[2])) {
|
|
24254
|
-
return null;
|
|
24255
|
-
}
|
|
24256
|
-
return {
|
|
24257
|
-
owner: urlMatch[1],
|
|
24258
|
-
repo: urlMatch[2],
|
|
24259
|
-
number: parseInt(urlMatch[3], 10)
|
|
24260
|
-
};
|
|
24261
|
-
}
|
|
24262
|
-
const shorthandMatch = input.match(/^([^/]+)\/([^#]+)#(\d+)$/);
|
|
24263
|
-
if (shorthandMatch) {
|
|
24264
|
-
if (containsControlCharacters(shorthandMatch[1]) || containsControlCharacters(shorthandMatch[2])) {
|
|
24265
|
-
return null;
|
|
24266
|
-
}
|
|
24267
|
-
return {
|
|
24268
|
-
owner: shorthandMatch[1],
|
|
24269
|
-
repo: shorthandMatch[2],
|
|
24270
|
-
number: parseInt(shorthandMatch[3], 10)
|
|
24271
|
-
};
|
|
24272
|
-
}
|
|
24273
|
-
const bareMatch = input.match(/^(\d+)$/);
|
|
24274
|
-
if (bareMatch) {
|
|
24275
|
-
const prNumber = parseInt(bareMatch[1], 10);
|
|
24276
|
-
const remoteUrl = detectGitRemote(cwd, undefined);
|
|
24277
|
-
if (!remoteUrl) {
|
|
24278
|
-
return null;
|
|
24279
|
-
}
|
|
24280
|
-
const parsed = parseGitRemoteUrl(remoteUrl);
|
|
24281
|
-
if (!parsed) {
|
|
24282
|
-
return null;
|
|
24283
|
-
}
|
|
24284
|
-
return {
|
|
24285
|
-
owner: parsed.owner,
|
|
24286
|
-
repo: parsed.repo,
|
|
24287
|
-
number: prNumber
|
|
24288
|
-
};
|
|
24289
|
-
}
|
|
24290
|
-
return null;
|
|
24291
|
-
}
|
|
24292
|
-
function looksLikePrRef(token) {
|
|
24293
|
-
return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
|
|
24294
|
-
}
|
|
24295
|
-
function resolvePrCommandInput(rest, cwd) {
|
|
24296
|
-
if (rest.length === 0) {
|
|
24297
|
-
return null;
|
|
24298
|
-
}
|
|
24299
|
-
const refToken = rest[0];
|
|
24300
|
-
const instructions = sanitizeInstructions(rest.slice(1).join(" "));
|
|
24301
|
-
const isFullUrl = /^https?:\/\//i.test(refToken);
|
|
24302
|
-
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl(refToken) : refToken, cwd);
|
|
24303
|
-
if (!prInfo) {
|
|
24304
|
-
return {
|
|
24305
|
-
error: `Could not parse PR reference from "${sanitizeErrorEcho(refToken)}"`
|
|
24306
|
-
};
|
|
24307
|
-
}
|
|
24308
|
-
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
24309
|
-
const result = validateAndSanitizeUrl2(prUrl);
|
|
24310
|
-
if ("error" in result) {
|
|
24311
|
-
return { error: result.error };
|
|
24312
|
-
}
|
|
24313
|
-
return { prUrl: result.sanitized, instructions };
|
|
24314
|
-
}
|
|
24315
|
-
|
|
24316
24372
|
// src/commands/pr-feedback.ts
|
|
24317
24373
|
function handlePrFeedbackCommand(directory, args) {
|
|
24318
24374
|
const rest = args.filter((t) => t.trim().length > 0);
|
|
@@ -24499,7 +24555,7 @@ async function handlePrMonitorStatusCommand(directory, _args, sessionID, source)
|
|
|
24499
24555
|
}
|
|
24500
24556
|
|
|
24501
24557
|
// src/commands/pr-review.ts
|
|
24502
|
-
var
|
|
24558
|
+
var USAGE9 = [
|
|
24503
24559
|
"Usage: /swarm pr-review <url|owner/repo#N|N> [--council] [instructions...]",
|
|
24504
24560
|
"",
|
|
24505
24561
|
"Run a full swarm PR review on a GitHub pull request.",
|
|
@@ -24537,16 +24593,16 @@ function handlePrReviewCommand(directory, args) {
|
|
|
24537
24593
|
if (parsed.unknownFlag) {
|
|
24538
24594
|
return `Error: Unknown flag "${parsed.unknownFlag}"
|
|
24539
24595
|
|
|
24540
|
-
${
|
|
24596
|
+
${USAGE9}`;
|
|
24541
24597
|
}
|
|
24542
24598
|
const resolved = resolvePrCommandInput(parsed.rest, directory);
|
|
24543
24599
|
if (resolved === null) {
|
|
24544
|
-
return
|
|
24600
|
+
return USAGE9;
|
|
24545
24601
|
}
|
|
24546
24602
|
if ("error" in resolved) {
|
|
24547
24603
|
return `Error: ${resolved.error}
|
|
24548
24604
|
|
|
24549
|
-
${
|
|
24605
|
+
${USAGE9}`;
|
|
24550
24606
|
}
|
|
24551
24607
|
const councilFlag = parsed.council ? "council=true" : "council=false";
|
|
24552
24608
|
const signal = `[MODE: PR_REVIEW pr="${resolved.prUrl}" ${councilFlag}]`;
|
|
@@ -31392,7 +31448,7 @@ var _internals46 = {
|
|
|
31392
31448
|
writeProjectedSpecSync
|
|
31393
31449
|
};
|
|
31394
31450
|
var SWARM_SPEC_REL = path61.join(".swarm", "spec.md");
|
|
31395
|
-
var
|
|
31451
|
+
var USAGE10 = `Usage:
|
|
31396
31452
|
/swarm sdd status [--json] [--source <provider>]
|
|
31397
31453
|
/swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
31398
31454
|
/swarm sdd project [--dry-run] [--overwrite] [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
@@ -31505,11 +31561,11 @@ async function handleSddStatusCommand(directory, args) {
|
|
|
31505
31561
|
if (parsed.error)
|
|
31506
31562
|
return `Error: ${parsed.error}
|
|
31507
31563
|
|
|
31508
|
-
${
|
|
31564
|
+
${USAGE10}`;
|
|
31509
31565
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31510
31566
|
return `Error: --feature is only valid with --source speckit
|
|
31511
31567
|
|
|
31512
|
-
${
|
|
31568
|
+
${USAGE10}`;
|
|
31513
31569
|
}
|
|
31514
31570
|
const speckitDetection = detectSpeckit(directory);
|
|
31515
31571
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
@@ -31576,11 +31632,11 @@ async function handleSddValidateCommand(directory, args) {
|
|
|
31576
31632
|
if (parsed.error)
|
|
31577
31633
|
return `Error: ${parsed.error}
|
|
31578
31634
|
|
|
31579
|
-
${
|
|
31635
|
+
${USAGE10}`;
|
|
31580
31636
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31581
31637
|
return `Error: --feature is only valid with --source speckit
|
|
31582
31638
|
|
|
31583
|
-
${
|
|
31639
|
+
${USAGE10}`;
|
|
31584
31640
|
}
|
|
31585
31641
|
let useSpeckit = false;
|
|
31586
31642
|
const nativeSpecExists = fs29.existsSync(path61.join(directory, SWARM_SPEC_REL));
|
|
@@ -31609,7 +31665,7 @@ ${USAGE9}`;
|
|
|
31609
31665
|
const resolution = resolveSpeckitProjection(directory);
|
|
31610
31666
|
return parsed.json ? JSON.stringify({ valid: false, error: formatSpeckitError(resolution) }, null, 2) : `Error: ${formatSpeckitError(resolution)}
|
|
31611
31667
|
|
|
31612
|
-
${
|
|
31668
|
+
${USAGE10}`;
|
|
31613
31669
|
}
|
|
31614
31670
|
}
|
|
31615
31671
|
}
|
|
@@ -31620,7 +31676,7 @@ ${USAGE9}`;
|
|
|
31620
31676
|
if (resolution.kind !== "ok" && resolution.kind !== "zero_requirements") {
|
|
31621
31677
|
return parsed.json ? JSON.stringify({ valid: false, error: formatSpeckitError(resolution) }, null, 2) : `Error: ${formatSpeckitError(resolution)}
|
|
31622
31678
|
|
|
31623
|
-
${
|
|
31679
|
+
${USAGE10}`;
|
|
31624
31680
|
}
|
|
31625
31681
|
const spec = resolution.kind === "ok" ? resolution.spec : null;
|
|
31626
31682
|
const result2 = {
|
|
@@ -31725,16 +31781,16 @@ async function handleSddProjectCommand(directory, args) {
|
|
|
31725
31781
|
if (parsed.error)
|
|
31726
31782
|
return `Error: ${parsed.error}
|
|
31727
31783
|
|
|
31728
|
-
${
|
|
31784
|
+
${USAGE10}`;
|
|
31729
31785
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31730
31786
|
return `Error: --feature is only valid with --source speckit
|
|
31731
31787
|
|
|
31732
|
-
${
|
|
31788
|
+
${USAGE10}`;
|
|
31733
31789
|
}
|
|
31734
31790
|
if (parsed.source === "swarm") {
|
|
31735
31791
|
return `Error: --source swarm selects the native .swarm/spec.md and does not generate a projection. Use --source openspec or --source speckit.
|
|
31736
31792
|
|
|
31737
|
-
${
|
|
31793
|
+
${USAGE10}`;
|
|
31738
31794
|
}
|
|
31739
31795
|
if (!parsed.dryRun) {
|
|
31740
31796
|
const nativeSpecPath = path61.join(directory, SWARM_SPEC_REL);
|
|
@@ -31744,7 +31800,7 @@ ${USAGE9}`;
|
|
|
31744
31800
|
"Error: .swarm/spec.md already exists.",
|
|
31745
31801
|
"Pass --overwrite to replace it.",
|
|
31746
31802
|
"",
|
|
31747
|
-
|
|
31803
|
+
USAGE10
|
|
31748
31804
|
].join(`
|
|
31749
31805
|
`);
|
|
31750
31806
|
}
|
|
@@ -31771,7 +31827,7 @@ ${USAGE9}`;
|
|
|
31771
31827
|
const resolution = resolveSpeckitProjection(directory);
|
|
31772
31828
|
return `Error: ${formatSpeckitError(resolution)}
|
|
31773
31829
|
|
|
31774
|
-
${
|
|
31830
|
+
${USAGE10}`;
|
|
31775
31831
|
}
|
|
31776
31832
|
}
|
|
31777
31833
|
}
|
|
@@ -31782,7 +31838,7 @@ ${USAGE9}`;
|
|
|
31782
31838
|
if (resolution.kind !== "ok") {
|
|
31783
31839
|
return `Error: ${formatSpeckitError(resolution)}
|
|
31784
31840
|
|
|
31785
|
-
${
|
|
31841
|
+
${USAGE10}`;
|
|
31786
31842
|
}
|
|
31787
31843
|
const result2 = _internals46.writeProjectedSpecSync(directory, {
|
|
31788
31844
|
source: "speckit",
|
|
@@ -31801,7 +31857,7 @@ ${USAGE9}`;
|
|
|
31801
31857
|
}
|
|
31802
31858
|
return `Error: ${result2.error}
|
|
31803
31859
|
|
|
31804
|
-
${
|
|
31860
|
+
${USAGE10}`;
|
|
31805
31861
|
}
|
|
31806
31862
|
if (!result2.projection) {
|
|
31807
31863
|
if (parsed.json) {
|
|
@@ -31815,7 +31871,7 @@ ${USAGE9}`;
|
|
|
31815
31871
|
return [
|
|
31816
31872
|
"SDD projection failed: no valid Spec-Kit projection could be built.",
|
|
31817
31873
|
"",
|
|
31818
|
-
|
|
31874
|
+
USAGE10
|
|
31819
31875
|
].join(`
|
|
31820
31876
|
`);
|
|
31821
31877
|
}
|
|
@@ -31858,7 +31914,7 @@ ${formatList(result2.projection.warnings)}` : ""
|
|
|
31858
31914
|
}
|
|
31859
31915
|
return `Error: ${result.error}
|
|
31860
31916
|
|
|
31861
|
-
${
|
|
31917
|
+
${USAGE10}`;
|
|
31862
31918
|
}
|
|
31863
31919
|
if (!result.projection) {
|
|
31864
31920
|
if (parsed.json) {
|
|
@@ -31872,7 +31928,7 @@ ${USAGE9}`;
|
|
|
31872
31928
|
return [
|
|
31873
31929
|
"SDD projection failed: no valid OpenSpec-compatible projection could be built.",
|
|
31874
31930
|
"",
|
|
31875
|
-
|
|
31931
|
+
USAGE10
|
|
31876
31932
|
].join(`
|
|
31877
31933
|
`);
|
|
31878
31934
|
}
|
|
@@ -31900,7 +31956,7 @@ ${formatList(result.projection.warnings)}` : ""
|
|
|
31900
31956
|
`);
|
|
31901
31957
|
}
|
|
31902
31958
|
async function handleSddCommand(_directory, _args) {
|
|
31903
|
-
return
|
|
31959
|
+
return USAGE10;
|
|
31904
31960
|
}
|
|
31905
31961
|
|
|
31906
31962
|
// src/commands/simulate.ts
|
|
@@ -31923,7 +31979,7 @@ async function handleSimulateCommand(directory, args) {
|
|
|
31923
31979
|
}
|
|
31924
31980
|
let darkMatterPairs;
|
|
31925
31981
|
try {
|
|
31926
|
-
darkMatterPairs = await
|
|
31982
|
+
darkMatterPairs = await _internals22.detectDarkMatter(directory, options);
|
|
31927
31983
|
} catch (err) {
|
|
31928
31984
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
31929
31985
|
return `## Simulate Report
|
|
@@ -32992,7 +33048,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
32992
33048
|
async function handleHelpCommand(ctx) {
|
|
32993
33049
|
const targetCommand = ctx.args.join(" ");
|
|
32994
33050
|
if (!targetCommand) {
|
|
32995
|
-
const { buildHelpText } = await import("./index-
|
|
33051
|
+
const { buildHelpText } = await import("./index-54sevh81.js");
|
|
32996
33052
|
return buildHelpText();
|
|
32997
33053
|
}
|
|
32998
33054
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -33001,7 +33057,7 @@ async function handleHelpCommand(ctx) {
|
|
|
33001
33057
|
return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
|
|
33002
33058
|
}
|
|
33003
33059
|
const similar = _internals49.findSimilarCommands(targetCommand);
|
|
33004
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
33060
|
+
const { buildHelpText: fullHelp } = await import("./index-54sevh81.js");
|
|
33005
33061
|
if (similar.length > 0) {
|
|
33006
33062
|
return `Command '/swarm ${targetCommand}' not found.
|
|
33007
33063
|
|
|
@@ -33134,7 +33190,7 @@ var COMMAND_REGISTRY = {
|
|
|
33134
33190
|
},
|
|
33135
33191
|
"guardrail explain": {
|
|
33136
33192
|
handler: async (ctx) => {
|
|
33137
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
33193
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-7aztgtyh.js");
|
|
33138
33194
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
33139
33195
|
},
|
|
33140
33196
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -33144,7 +33200,7 @@ var COMMAND_REGISTRY = {
|
|
|
33144
33200
|
},
|
|
33145
33201
|
"guardrail-explain": {
|
|
33146
33202
|
handler: async (ctx) => {
|
|
33147
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
33203
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-7aztgtyh.js");
|
|
33148
33204
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
33149
33205
|
},
|
|
33150
33206
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -33504,6 +33560,14 @@ Subcommands:
|
|
|
33504
33560
|
category: "agent",
|
|
33505
33561
|
toolPolicy: "none"
|
|
33506
33562
|
},
|
|
33563
|
+
"ci-monitor": {
|
|
33564
|
+
handler: (ctx) => handleModeCommandWithBundledSkills(ctx, handleCiMonitorCommand),
|
|
33565
|
+
description: "Drive an already-reviewed, approved PR to green and merged (monitor CI, fix, merge) [pr]",
|
|
33566
|
+
args: "<pr-url|owner/repo#N|N>",
|
|
33567
|
+
details: "Triggers MODE: CI_MONITOR \u2014 takes an already human-reviewed, approved PR, exhaustively researches every CI failure, fixes it end-to-end, iterates until all required checks are green (max 5 fix cycles), then merges via `gh pr merge` with no merge-strategy flag. Invoke only after human review is complete; the skill re-verifies reviewDecision: APPROVED and mergeable state before doing anything destructive. Distinct from /swarm pr-subscribe, which passively watches a PR without a merge terminal. Supports full GitHub URL, owner/repo#N shorthand, or bare PR number (resolved against origin).",
|
|
33568
|
+
category: "agent",
|
|
33569
|
+
toolPolicy: "none"
|
|
33570
|
+
},
|
|
33507
33571
|
"pr subscribe": {
|
|
33508
33572
|
handler: (ctx) => handlePrSubscribeCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
33509
33573
|
description: "Subscribe the current session to PR state-change notifications",
|
|
@@ -34544,6 +34608,7 @@ FILE: src/auth/login.ts
|
|
|
34544
34608
|
INPUT: Validate email format, password >= 8 chars
|
|
34545
34609
|
OUTPUT: Modified file
|
|
34546
34610
|
CONSTRAINT: Do not modify other functions
|
|
34611
|
+
ACCEPTANCE: Populate from the plan task's acceptance criteria / FR / SC when the task has them (one item per line, or FR-/SC-style references), so the coder can gate its implementation on each. Omit the field entirely when the task has no structured acceptance criteria.
|
|
34547
34612
|
SKILLS: file:.claude/skills/engineering-conventions/SKILL.md
|
|
34548
34613
|
|
|
34549
34614
|
{{AGENT_PREFIX}}reviewer
|
|
@@ -34889,6 +34954,22 @@ HARD CONSTRAINTS (apply regardless of skill load success):
|
|
|
34889
34954
|
- Honor any free-text instructions that follow the closing bracket of the signal as additional scope, without dropping any ledger item.
|
|
34890
34955
|
- Quality is the only metric \u2014 time, tokens, and agent dispatches are irrelevant to correctness
|
|
34891
34956
|
|
|
34957
|
+
### MODE: CI_MONITOR
|
|
34958
|
+
Activates when: architect receives \`[MODE: CI_MONITOR pr="https://github.com/..."]\` signal from the ci-monitor command handler.
|
|
34959
|
+
|
|
34960
|
+
Purpose: Drive an already human-reviewed, approved PR to a merged state \u2014 monitor its CI, exhaustively research and fix every failure, iterate until all required checks are green (max 5 fix cycles), then merge. This is the terminal closeout hop for a PR that just needs to get green and merge; it is NOT a review or feedback-ingestion mode. It is the first mode in this workflow that performs a merge, so it carries extra safety gates.
|
|
34961
|
+
|
|
34962
|
+
ACTION: Load skill ${bundledProjectSkillFileReference("swarm-ci-monitor")} immediately and follow its protocol.
|
|
34963
|
+
|
|
34964
|
+
HARD CONSTRAINTS (apply regardless of skill load success):
|
|
34965
|
+
- Do NOT invoke this mode's merge path without the user having named the PR explicitly \u2014 no auto-discovery.
|
|
34966
|
+
- Verify \`reviewDecision: APPROVED\` before entering the fix loop; abort with "human review not complete" if not.
|
|
34967
|
+
- Verify \`mergeable: MERGEABLE\` and an acceptable \`mergeStateStatus\` before entering the fix loop; do not bypass these gates even under time pressure.
|
|
34968
|
+
- Never use \`--admin\`, a forced merge strategy, or \`--delete-branch\` \u2014 let branch protection determine the merge method.
|
|
34969
|
+
- Re-verify review approval and mergeable state immediately before every merge attempt (Step 3 of the loaded skill) \u2014 a check that was green earlier is not sufficient.
|
|
34970
|
+
- Confirm the merge via the local git object DB (Step 4b), not only the GitHub API response, before reporting success.
|
|
34971
|
+
- Hard-stop at 5 fix-push cycles; escalate to the user rather than exceeding the budget.
|
|
34972
|
+
|
|
34892
34973
|
### MODE: ISSUE_INGEST
|
|
34893
34974
|
Activates when the user invokes /swarm issue <url> or the architect receives an ISSUE_INGEST signal.
|
|
34894
34975
|
|
|
@@ -38293,7 +38374,6 @@ function resolveWriteTargets(command, writes, cwd) {
|
|
|
38293
38374
|
};
|
|
38294
38375
|
});
|
|
38295
38376
|
}
|
|
38296
|
-
|
|
38297
38377
|
// src/hooks/guardrails/index.ts
|
|
38298
38378
|
var SPEC_DRIFT_BLOCKED_TOOLS = new Set([
|
|
38299
38379
|
"save_plan",
|
|
@@ -39297,4 +39377,4 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
|
39297
39377
|
};
|
|
39298
39378
|
}
|
|
39299
39379
|
|
|
39300
|
-
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate,
|
|
39380
|
+
export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleCiSimulateCommand, handleClarifyCommand, createCuratorLLMDelegate, _internals12 as _internals, normalizeRecommendationEntryIdToken, parseKnowledgeRecommendations, parseKnowledgeRecommendationsWithDiagnostics, parseStructuredCuratorBlocks, readCuratorSummary, writeCuratorSummary, appendCuratorRecommendation, mergeCuratorPhaseSummary, filterPhaseEvents, checkPhaseCompliance, runCuratorInit, runCuratorPhase, applyCuratorKnowledgeUpdates, isHiveEligible, checkHivePromotions, _internals14 as _internals1, createHivePromoterHook, promoteToHive, promoteFromSwarm, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryValueLogCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals49 as _internals2, resolveCommand };
|