opencode-swarm 7.114.8 → 7.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.opencode/skills/ci-fix-monitor/SKILL.md +8 -13
- package/.opencode/skills/commit-pr/SKILL.md +4 -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 +1 -0
- package/dist/cli/{config-doctor-jy3mdh9t.js → config-doctor-htzxe394.js} +2 -2
- package/dist/cli/{curator-qj970412.js → curator-hpc4tsjv.js} +4 -4
- package/dist/cli/{curator-llm-factory-ez48eq02.js → curator-llm-factory-6n9sgaj8.js} +4 -4
- package/dist/cli/{guardrail-explain-x2vaxp6s.js → guardrail-explain-hecpd738.js} +5 -5
- package/dist/cli/{guardrail-log-84wnx273.js → guardrail-log-dzbqcgz9.js} +3 -3
- package/dist/cli/{hive-promoter-ysk5edzw.js → hive-promoter-0kfb4vjk.js} +4 -4
- package/dist/cli/{index-z718bgxe.js → index-2etc05tv.js} +6 -6
- package/dist/cli/{index-yfedche9.js → index-8j5d3ytd.js} +1 -1
- package/dist/cli/{index-ry8nwsq6.js → index-m0rce3x6.js} +2 -2
- package/dist/cli/{index-7jmrbp68.js → index-m43zgtjn.js} +1 -1
- package/dist/cli/{index-cs5765s2.js → index-m766gvdt.js} +640 -583
- package/dist/cli/{index-9bsmzfk3.js → index-m7hc7nn7.js} +5 -1
- package/dist/cli/{index-a45jq4b7.js → index-nvc0nsvg.js} +6 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/{schema-aymfdrsb.js → schema-bqn7g3ez.js} +3 -1
- package/dist/commands/ci-monitor.d.ts +18 -0
- package/dist/commands/registry.d.ts +8 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +9 -0
- package/dist/config/skill-mirrors.d.ts +10 -1
- package/dist/index.js +214 -160
- package/dist/tools/apply-patch.d.ts +21 -0
- package/dist/utils/fuzzy-match.d.ts +115 -0
- package/dist/utils/sequence-matcher.d.ts +83 -0
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
readDoctorArtifact,
|
|
8
8
|
removeStraySwarmDir,
|
|
9
9
|
runConfigDoctor
|
|
10
|
-
} from "./index-
|
|
10
|
+
} from "./index-m7hc7nn7.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENT_TOOL_MAP,
|
|
13
13
|
ALL_SUBAGENT_NAMES,
|
|
@@ -23,7 +23,7 @@ import {
|
|
|
23
23
|
getCanonicalAgentRole,
|
|
24
24
|
resolveExternalSkillsConfig,
|
|
25
25
|
stripKnownSwarmPrefix
|
|
26
|
-
} from "./index-
|
|
26
|
+
} from "./index-nvc0nsvg.js";
|
|
27
27
|
import {
|
|
28
28
|
MAX_TRANSIENT_RETRIES,
|
|
29
29
|
PlanSchema,
|
|
@@ -6426,6 +6426,294 @@ async function handleList2(directory) {
|
|
|
6426
6426
|
}
|
|
6427
6427
|
}
|
|
6428
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
|
+
|
|
6429
6717
|
// src/commands/ci-simulate.ts
|
|
6430
6718
|
import * as fs4 from "fs";
|
|
6431
6719
|
import * as fsPromises2 from "fs/promises";
|
|
@@ -6498,7 +6786,7 @@ function timeoutKillSignal(platform) {
|
|
|
6498
6786
|
}
|
|
6499
6787
|
function killProcess(proc) {
|
|
6500
6788
|
try {
|
|
6501
|
-
proc?.kill(timeoutKillSignal(
|
|
6789
|
+
proc?.kill(timeoutKillSignal(_internals8.platform()));
|
|
6502
6790
|
} catch {}
|
|
6503
6791
|
}
|
|
6504
6792
|
async function runExternalTool(options) {
|
|
@@ -6518,7 +6806,7 @@ async function runExternalTool(options) {
|
|
|
6518
6806
|
let exitSettled = false;
|
|
6519
6807
|
let settledExitCode = null;
|
|
6520
6808
|
try {
|
|
6521
|
-
proc =
|
|
6809
|
+
proc = _internals8.bunSpawn([options.executable, ...options.args], {
|
|
6522
6810
|
cwd: options.cwd,
|
|
6523
6811
|
env: options.env,
|
|
6524
6812
|
stdin: "ignore",
|
|
@@ -6586,7 +6874,7 @@ async function runExternalTool(options) {
|
|
|
6586
6874
|
}
|
|
6587
6875
|
}
|
|
6588
6876
|
}
|
|
6589
|
-
var
|
|
6877
|
+
var _internals8 = {
|
|
6590
6878
|
bunSpawn,
|
|
6591
6879
|
platform: () => process.platform
|
|
6592
6880
|
};
|
|
@@ -6595,7 +6883,7 @@ var _internals7 = {
|
|
|
6595
6883
|
var GIT_TIMEOUT_MS2 = 30000;
|
|
6596
6884
|
var VALIDATION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
6597
6885
|
var OUTPUT_LIMIT_BYTES = 12000;
|
|
6598
|
-
var
|
|
6886
|
+
var _internals9 = {
|
|
6599
6887
|
runExternalTool,
|
|
6600
6888
|
getDefaultBaseBranch,
|
|
6601
6889
|
platform: process.platform,
|
|
@@ -6606,7 +6894,7 @@ var _internals8 = {
|
|
|
6606
6894
|
}
|
|
6607
6895
|
};
|
|
6608
6896
|
async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
|
|
6609
|
-
const result = await
|
|
6897
|
+
const result = await _internals9.runExternalTool({
|
|
6610
6898
|
executable: "git",
|
|
6611
6899
|
args,
|
|
6612
6900
|
cwd,
|
|
@@ -6624,7 +6912,7 @@ async function runGit2(args, cwd, timeoutMs = GIT_TIMEOUT_MS2) {
|
|
|
6624
6912
|
}
|
|
6625
6913
|
async function runValidationCommand(cmd, cwd, timeoutMs = VALIDATION_TIMEOUT_MS) {
|
|
6626
6914
|
const [executable, ...args] = cmd;
|
|
6627
|
-
const result = await
|
|
6915
|
+
const result = await _internals9.runExternalTool({
|
|
6628
6916
|
executable,
|
|
6629
6917
|
args,
|
|
6630
6918
|
cwd,
|
|
@@ -6652,7 +6940,7 @@ async function getCurrentBranchOrRef(directory) {
|
|
|
6652
6940
|
return hashResult.stdout.trim();
|
|
6653
6941
|
}
|
|
6654
6942
|
async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated) {
|
|
6655
|
-
const worktreeBase = path12.join(
|
|
6943
|
+
const worktreeBase = path12.join(_internals9.osTmpdir(), "swarm-ci-simulate");
|
|
6656
6944
|
const worktreeName = `pr-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
6657
6945
|
const worktreePath = path12.join(worktreeBase, worktreeName);
|
|
6658
6946
|
await fsPromises2.mkdir(worktreeBase, { recursive: true });
|
|
@@ -6670,8 +6958,8 @@ async function setupWorktree(projectRoot, prRef, baseBranch, onWorktreeCreated)
|
|
|
6670
6958
|
async function cleanupWorktree(worktreePath, projectRoot) {
|
|
6671
6959
|
const removeResult = await runGit2(["worktree", "remove", "--force", worktreePath], projectRoot);
|
|
6672
6960
|
try {
|
|
6673
|
-
if (
|
|
6674
|
-
|
|
6961
|
+
if (_internals9.fs.existsSync(worktreePath)) {
|
|
6962
|
+
_internals9.fs.rmSync(worktreePath, { recursive: true, force: true });
|
|
6675
6963
|
}
|
|
6676
6964
|
} catch {}
|
|
6677
6965
|
if (removeResult.exitCode !== 0) {
|
|
@@ -6753,7 +7041,7 @@ async function handleCiSimulateCommand(directory, args) {
|
|
|
6753
7041
|
steps: []
|
|
6754
7042
|
};
|
|
6755
7043
|
try {
|
|
6756
|
-
const baseBranch =
|
|
7044
|
+
const baseBranch = _internals9.getDefaultBaseBranch(directory);
|
|
6757
7045
|
if (!isSafeGitRef(baseBranch)) {
|
|
6758
7046
|
throw new Error("Detected default branch is not a safe git reference.");
|
|
6759
7047
|
}
|
|
@@ -6852,7 +7140,7 @@ async function handleClarifyCommand(_directory, args) {
|
|
|
6852
7140
|
}
|
|
6853
7141
|
|
|
6854
7142
|
// src/commands/close.ts
|
|
6855
|
-
import * as
|
|
7143
|
+
import * as child_process3 from "child_process";
|
|
6856
7144
|
import * as fsSync from "fs";
|
|
6857
7145
|
import { promises as fs10 } from "fs";
|
|
6858
7146
|
import path29 from "path";
|
|
@@ -7541,7 +7829,7 @@ async function reviseSkill(params) {
|
|
|
7541
7829
|
}
|
|
7542
7830
|
if (!params.delegate) {
|
|
7543
7831
|
try {
|
|
7544
|
-
const revised =
|
|
7832
|
+
const revised = _internals10.buildDeterministicRevision(params.currentContent, params.currentVersion, params.violationContexts);
|
|
7545
7833
|
const validation = await validateRevisionCandidate(params, revised, "skill_reviser:deterministic");
|
|
7546
7834
|
if (!validation.passed) {
|
|
7547
7835
|
return {
|
|
@@ -7668,7 +7956,7 @@ async function reviseSkill(params) {
|
|
|
7668
7956
|
};
|
|
7669
7957
|
}
|
|
7670
7958
|
}
|
|
7671
|
-
var
|
|
7959
|
+
var _internals10 = {
|
|
7672
7960
|
reviseSkill,
|
|
7673
7961
|
getSkillVersion,
|
|
7674
7962
|
buildDeterministicRevision,
|
|
@@ -7752,7 +8040,7 @@ function resolveLogPath(directory) {
|
|
|
7752
8040
|
function normalizeComplianceVerdict(verdict) {
|
|
7753
8041
|
return verdict === "violation" ? "violated" : verdict;
|
|
7754
8042
|
}
|
|
7755
|
-
var
|
|
8043
|
+
var _internals11 = {
|
|
7756
8044
|
generateId: () => crypto2.randomUUID(),
|
|
7757
8045
|
appendFileSync: fs5.appendFileSync.bind(fs5),
|
|
7758
8046
|
readFileSync: fs5.readFileSync.bind(fs5),
|
|
@@ -7822,9 +8110,9 @@ function parseFeedbackMarker(raw) {
|
|
|
7822
8110
|
function readFeedbackAppliedEntryIds(directory) {
|
|
7823
8111
|
const resolved = resolveLogPath(directory);
|
|
7824
8112
|
const processed = new Set;
|
|
7825
|
-
if (!
|
|
8113
|
+
if (!_internals11.existsSync(resolved))
|
|
7826
8114
|
return processed;
|
|
7827
|
-
const raw =
|
|
8115
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
7828
8116
|
for (const line of raw.split(`
|
|
7829
8117
|
`)) {
|
|
7830
8118
|
const trimmed = line.trim();
|
|
@@ -7845,15 +8133,15 @@ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
|
|
|
7845
8133
|
return;
|
|
7846
8134
|
const resolved = resolveLogPath(directory);
|
|
7847
8135
|
const dir = path15.dirname(resolved);
|
|
7848
|
-
if (!
|
|
7849
|
-
|
|
8136
|
+
if (!_internals11.existsSync(dir)) {
|
|
8137
|
+
_internals11.mkdirSync(dir, { recursive: true });
|
|
7850
8138
|
}
|
|
7851
8139
|
const marker = {
|
|
7852
8140
|
type: "feedback_applied",
|
|
7853
8141
|
timestamp: new Date().toISOString(),
|
|
7854
8142
|
processedEntryIds: [...new Set(processedEntryIds)]
|
|
7855
8143
|
};
|
|
7856
|
-
|
|
8144
|
+
_internals11.appendFileSync(resolved, `${JSON.stringify(marker)}
|
|
7857
8145
|
`, "utf-8");
|
|
7858
8146
|
}
|
|
7859
8147
|
function appendSkillUsageEntry(directory, entry) {
|
|
@@ -7890,11 +8178,11 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
7890
8178
|
}
|
|
7891
8179
|
const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
|
|
7892
8180
|
const dir = path15.dirname(resolved);
|
|
7893
|
-
if (!
|
|
7894
|
-
|
|
8181
|
+
if (!_internals11.existsSync(dir)) {
|
|
8182
|
+
_internals11.mkdirSync(dir, { recursive: true });
|
|
7895
8183
|
}
|
|
7896
8184
|
const fullEntry = {
|
|
7897
|
-
id:
|
|
8185
|
+
id: _internals11.generateId(),
|
|
7898
8186
|
skillPath,
|
|
7899
8187
|
agentName,
|
|
7900
8188
|
taskID,
|
|
@@ -7904,21 +8192,21 @@ function appendSkillUsageEntry(directory, entry) {
|
|
|
7904
8192
|
...reviewerNotes !== undefined && { reviewerNotes },
|
|
7905
8193
|
...skillVersion !== undefined && { skillVersion }
|
|
7906
8194
|
};
|
|
7907
|
-
|
|
8195
|
+
_internals11.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
|
|
7908
8196
|
`, "utf-8");
|
|
7909
8197
|
try {
|
|
7910
|
-
const stat2 =
|
|
8198
|
+
const stat2 = _internals11.statSync(resolved);
|
|
7911
8199
|
if (stat2.size > SKILL_USAGE_LOG_ROTATE_BYTES) {
|
|
7912
|
-
|
|
8200
|
+
_internals11.pruneSkillUsageLog(directory, SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL);
|
|
7913
8201
|
}
|
|
7914
8202
|
} catch {}
|
|
7915
8203
|
}
|
|
7916
8204
|
function readSkillUsageEntries(directory, options) {
|
|
7917
8205
|
const resolved = resolveLogPath(directory);
|
|
7918
|
-
if (!
|
|
8206
|
+
if (!_internals11.existsSync(resolved)) {
|
|
7919
8207
|
return [];
|
|
7920
8208
|
}
|
|
7921
|
-
const raw =
|
|
8209
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
7922
8210
|
const entries = [];
|
|
7923
8211
|
for (const line of raw.split(`
|
|
7924
8212
|
`)) {
|
|
@@ -7961,20 +8249,20 @@ var SKILL_USAGE_LOG_ROTATE_BYTES = 1024 * 1024;
|
|
|
7961
8249
|
var SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL = 500;
|
|
7962
8250
|
function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEFAULT) {
|
|
7963
8251
|
const logPath = resolveLogPath(directory);
|
|
7964
|
-
if (!
|
|
8252
|
+
if (!_internals11.existsSync(logPath))
|
|
7965
8253
|
return [];
|
|
7966
8254
|
try {
|
|
7967
8255
|
const normalizedMaxBytes = Number.isFinite(maxBytes) ? maxBytes : TAIL_BYTES_DEFAULT;
|
|
7968
8256
|
const boundedMaxBytes = Math.min(Math.max(1, normalizedMaxBytes), MAX_TAIL_BYTES);
|
|
7969
|
-
const stat2 =
|
|
8257
|
+
const stat2 = _internals11.statSync(logPath);
|
|
7970
8258
|
const start = Math.max(0, stat2.size - boundedMaxBytes);
|
|
7971
|
-
const fd =
|
|
8259
|
+
const fd = _internals11.openSync(logPath, "r");
|
|
7972
8260
|
try {
|
|
7973
8261
|
const readLen = stat2.size - start;
|
|
7974
8262
|
if (readLen === 0)
|
|
7975
8263
|
return [];
|
|
7976
8264
|
const buf = Buffer.alloc(readLen);
|
|
7977
|
-
|
|
8265
|
+
_internals11.readSync(fd, buf, 0, buf.length, start);
|
|
7978
8266
|
const content = buf.toString("utf-8");
|
|
7979
8267
|
let usable;
|
|
7980
8268
|
if (start > 0) {
|
|
@@ -8001,7 +8289,7 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
|
|
|
8001
8289
|
}
|
|
8002
8290
|
return entries;
|
|
8003
8291
|
} finally {
|
|
8004
|
-
|
|
8292
|
+
_internals11.closeSync(fd);
|
|
8005
8293
|
}
|
|
8006
8294
|
} catch {
|
|
8007
8295
|
return [];
|
|
@@ -8038,10 +8326,10 @@ function computeComplianceByVersion(entries, skillPath) {
|
|
|
8038
8326
|
}
|
|
8039
8327
|
function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
8040
8328
|
const resolved = resolveLogPath(directory);
|
|
8041
|
-
if (!
|
|
8329
|
+
if (!_internals11.existsSync(resolved)) {
|
|
8042
8330
|
return { pruned: 0, remaining: 0 };
|
|
8043
8331
|
}
|
|
8044
|
-
const raw =
|
|
8332
|
+
const raw = _internals11.readFileSync(resolved, "utf-8");
|
|
8045
8333
|
const lines = raw.split(`
|
|
8046
8334
|
`);
|
|
8047
8335
|
const entries = [];
|
|
@@ -8071,13 +8359,13 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8071
8359
|
`).concat(preservedMarkers.length > 0 ? `
|
|
8072
8360
|
` : "");
|
|
8073
8361
|
try {
|
|
8074
|
-
|
|
8075
|
-
|
|
8362
|
+
_internals11.writeFileSync(tmpPath2, content2, "utf-8");
|
|
8363
|
+
_internals11.renameSync(tmpPath2, resolved);
|
|
8076
8364
|
} catch (writeErr) {
|
|
8077
8365
|
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
8078
8366
|
try {
|
|
8079
|
-
if (
|
|
8080
|
-
|
|
8367
|
+
if (_internals11.existsSync(tmpPath2)) {
|
|
8368
|
+
_internals11.writeFileSync(tmpPath2, "", "utf-8");
|
|
8081
8369
|
}
|
|
8082
8370
|
} catch {}
|
|
8083
8371
|
return { pruned: 0, remaining: 0, error: msg };
|
|
@@ -8116,13 +8404,13 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
|
|
|
8116
8404
|
`).concat(`
|
|
8117
8405
|
`);
|
|
8118
8406
|
try {
|
|
8119
|
-
|
|
8120
|
-
|
|
8407
|
+
_internals11.writeFileSync(tmpPath, content, "utf-8");
|
|
8408
|
+
_internals11.renameSync(tmpPath, resolved);
|
|
8121
8409
|
} catch (writeErr) {
|
|
8122
8410
|
const msg = writeErr instanceof Error ? writeErr.message : String(writeErr);
|
|
8123
8411
|
try {
|
|
8124
|
-
if (
|
|
8125
|
-
|
|
8412
|
+
if (_internals11.existsSync(tmpPath)) {
|
|
8413
|
+
_internals11.writeFileSync(tmpPath, "", "utf-8");
|
|
8126
8414
|
}
|
|
8127
8415
|
} catch {}
|
|
8128
8416
|
return { pruned: 0, remaining: entries.length, error: msg };
|
|
@@ -8144,10 +8432,10 @@ async function resolveSourceKnowledgeIds(directory, skillPath) {
|
|
|
8144
8432
|
if (!isContained) {
|
|
8145
8433
|
return [];
|
|
8146
8434
|
}
|
|
8147
|
-
if (!
|
|
8435
|
+
if (!_internals11.existsSync(absolute)) {
|
|
8148
8436
|
return [];
|
|
8149
8437
|
}
|
|
8150
|
-
const content =
|
|
8438
|
+
const content = _internals11.readFileSync(absolute, "utf-8");
|
|
8151
8439
|
return parseGeneratedFromKnowledge(content);
|
|
8152
8440
|
} catch (err) {
|
|
8153
8441
|
log("[skill-usage-log] resolveSourceKnowledgeIds failed (fail-open):", err instanceof Error ? err.message : String(err));
|
|
@@ -8255,7 +8543,7 @@ var DEFAULT_CURATOR_LLM_TIMEOUT_MS = 300000;
|
|
|
8255
8543
|
var MAX_CURATOR_PHASE_DIGESTS = 50;
|
|
8256
8544
|
var MAX_CURATOR_COMPLIANCE_OBSERVATIONS = 200;
|
|
8257
8545
|
var MAX_CURATOR_RECOMMENDATIONS = 200;
|
|
8258
|
-
var
|
|
8546
|
+
var _internals12 = {
|
|
8259
8547
|
parseKnowledgeRecommendations,
|
|
8260
8548
|
parseKnowledgeRecommendationsWithDiagnostics,
|
|
8261
8549
|
readCuratorSummary,
|
|
@@ -8361,9 +8649,9 @@ ${digest.summary}`).join(`
|
|
|
8361
8649
|
async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs) {
|
|
8362
8650
|
const observations = [];
|
|
8363
8651
|
try {
|
|
8364
|
-
const skillListResult = await
|
|
8365
|
-
const usageEntries =
|
|
8366
|
-
const allArchivedIds = await
|
|
8652
|
+
const skillListResult = await _internals12.listSkills(directory);
|
|
8653
|
+
const usageEntries = _internals12.readSkillUsageEntries(directory);
|
|
8654
|
+
const allArchivedIds = await _internals12.getArchivedKnowledgeIds(directory);
|
|
8367
8655
|
for (const active of skillListResult.active) {
|
|
8368
8656
|
if (excludeSlugs?.has(active.slug))
|
|
8369
8657
|
continue;
|
|
@@ -8385,7 +8673,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
8385
8673
|
const violationRate = skillUsage.length > 0 ? violations / skillUsage.length : 0;
|
|
8386
8674
|
if (violationRate > 0.3) {
|
|
8387
8675
|
const reason = `auto-retire: violation rate ${(violationRate * 100).toFixed(0)}% exceeds 30% threshold`;
|
|
8388
|
-
await
|
|
8676
|
+
await _internals12.retireSkill(directory, active.slug, reason);
|
|
8389
8677
|
observations.push(`Skill '${active.slug}' auto-retired: ${reason}`);
|
|
8390
8678
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
8391
8679
|
continue;
|
|
@@ -8393,15 +8681,15 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
|
|
|
8393
8681
|
let archivedSourceMatched = false;
|
|
8394
8682
|
if (allArchivedIds.size > 0) {
|
|
8395
8683
|
try {
|
|
8396
|
-
const content = await
|
|
8397
|
-
const sourceIds =
|
|
8684
|
+
const content = await _internals12.readFileAsync(active.path, "utf-8");
|
|
8685
|
+
const sourceIds = _internals12.parseDraftFrontmatter(content)?.sourceKnowledgeIds ?? [];
|
|
8398
8686
|
archivedSourceMatched = sourceIds.some((id) => allArchivedIds.has(id));
|
|
8399
8687
|
} catch {
|
|
8400
8688
|
archivedSourceMatched = false;
|
|
8401
8689
|
}
|
|
8402
8690
|
}
|
|
8403
8691
|
if (archivedSourceMatched) {
|
|
8404
|
-
const result = await
|
|
8692
|
+
const result = await _internals12.retireOrMarkStale(directory, path16.dirname(active.path), allArchivedIds);
|
|
8405
8693
|
if (result.action === "retire") {
|
|
8406
8694
|
observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
|
|
8407
8695
|
warn(`[curator] ${observations[observations.length - 1]}`);
|
|
@@ -8669,7 +8957,7 @@ async function transactCuratorSummary(directory, mutate) {
|
|
|
8669
8957
|
const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
|
|
8670
8958
|
let invoked = false;
|
|
8671
8959
|
let mutationResult;
|
|
8672
|
-
await
|
|
8960
|
+
await _internals12.transactFile(resolvedPath, _internals12.readCuratorSummaryState, _internals12.writeCuratorSummaryState, (state) => {
|
|
8673
8961
|
invoked = true;
|
|
8674
8962
|
const mutation = mutate(state.summary);
|
|
8675
8963
|
mutationResult = mutation.result;
|
|
@@ -8818,8 +9106,8 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8818
9106
|
const observations = [];
|
|
8819
9107
|
const timestamp = new Date().toISOString();
|
|
8820
9108
|
for (const agent of requiredAgents) {
|
|
8821
|
-
const normalizedAgent =
|
|
8822
|
-
const isDispatched = agentsDispatched.some((a) =>
|
|
9109
|
+
const normalizedAgent = _internals12.normalizeAgentName(agent);
|
|
9110
|
+
const isDispatched = agentsDispatched.some((a) => _internals12.normalizeAgentName(a) === normalizedAgent);
|
|
8823
9111
|
if (!isDispatched) {
|
|
8824
9112
|
observations.push({
|
|
8825
9113
|
phase,
|
|
@@ -8838,7 +9126,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8838
9126
|
if (e.type === "agent.delegation") {
|
|
8839
9127
|
const agent = e.agent;
|
|
8840
9128
|
if (agent && typeof agent === "string") {
|
|
8841
|
-
const normalized =
|
|
9129
|
+
const normalized = _internals12.normalizeAgentName(agent);
|
|
8842
9130
|
if (normalized === "coder") {
|
|
8843
9131
|
coderDelegations.push({ event: e, index: i });
|
|
8844
9132
|
} else if (normalized === "reviewer") {
|
|
@@ -8895,7 +9183,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8895
9183
|
if (e.type === "agent.delegation" && e.agent) {
|
|
8896
9184
|
const agent = e.agent;
|
|
8897
9185
|
if (agent && typeof agent === "string") {
|
|
8898
|
-
const normalized =
|
|
9186
|
+
const normalized = _internals12.normalizeAgentName(agent);
|
|
8899
9187
|
if (normalized === "sme") {
|
|
8900
9188
|
smeDelegations.push({ event: e, index: i });
|
|
8901
9189
|
}
|
|
@@ -8919,7 +9207,7 @@ function checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, pha
|
|
|
8919
9207
|
}
|
|
8920
9208
|
async function runCuratorInit(directory, config, llmDelegate) {
|
|
8921
9209
|
try {
|
|
8922
|
-
const priorSummary = await
|
|
9210
|
+
const priorSummary = await _internals12.readCuratorSummary(directory);
|
|
8923
9211
|
const knowledgePath = resolveSwarmKnowledgePath(directory);
|
|
8924
9212
|
const allEntries = await readKnowledge(knowledgePath);
|
|
8925
9213
|
const highConfidenceEntries = allEntries.filter((e) => typeof e.confidence === "number" && e.confidence >= config.min_knowledge_confidence);
|
|
@@ -8960,7 +9248,7 @@ async function runCuratorInit(directory, config, llmDelegate) {
|
|
|
8960
9248
|
const maxContextChars = config.max_summary_tokens * 2;
|
|
8961
9249
|
briefingParts.push(contextMd.slice(0, maxContextChars));
|
|
8962
9250
|
}
|
|
8963
|
-
const latestPostMortemDigest =
|
|
9251
|
+
const latestPostMortemDigest = _internals12.readLatestPostMortemDigest(directory);
|
|
8964
9252
|
if (latestPostMortemDigest) {
|
|
8965
9253
|
briefingParts.push(`
|
|
8966
9254
|
## Latest Post-Mortem`);
|
|
@@ -9047,7 +9335,7 @@ Could not load prior session context.`,
|
|
|
9047
9335
|
}
|
|
9048
9336
|
async function runCuratorPhase(directory, phase, agentsDispatched, config, knowledgeConfig, llmDelegate) {
|
|
9049
9337
|
try {
|
|
9050
|
-
const priorSummary = await
|
|
9338
|
+
const priorSummary = await _internals12.readCuratorSummary(directory);
|
|
9051
9339
|
if (priorSummary?.phase_digests.some((d) => d.phase === phase)) {
|
|
9052
9340
|
const existingDigest = priorSummary.phase_digests.find((d) => d.phase === phase);
|
|
9053
9341
|
return {
|
|
@@ -9060,10 +9348,10 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9060
9348
|
};
|
|
9061
9349
|
}
|
|
9062
9350
|
const eventsJsonlContent = await readSwarmFileAsync(directory, "events.jsonl");
|
|
9063
|
-
const phaseEvents = eventsJsonlContent ?
|
|
9351
|
+
const phaseEvents = eventsJsonlContent ? _internals12.filterPhaseEvents(eventsJsonlContent, phase) : [];
|
|
9064
9352
|
const contextMd = await readSwarmFileAsync(directory, "context.md");
|
|
9065
9353
|
const requiredAgents = ["reviewer", "test_engineer"];
|
|
9066
|
-
const complianceObservations =
|
|
9354
|
+
const complianceObservations = _internals12.checkPhaseCompliance(phaseEvents, agentsDispatched, requiredAgents, phase);
|
|
9067
9355
|
const plan = await loadPlanJsonOnly(directory);
|
|
9068
9356
|
const phaseData = plan?.phases.find((p) => p.id === phase);
|
|
9069
9357
|
const tasksCompleted = phaseData ? phaseData.tasks.filter((t) => t.status === "completed").length : 0;
|
|
@@ -9087,7 +9375,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9087
9375
|
timestamp: new Date().toISOString(),
|
|
9088
9376
|
summary: `Phase ${phase} completed. ${tasksCompleted}/${tasksTotal} tasks completed. ${complianceObservations.length} compliance observations.`,
|
|
9089
9377
|
agents_used: [
|
|
9090
|
-
...new Set(agentsDispatched.map((a) =>
|
|
9378
|
+
...new Set(agentsDispatched.map((a) => _internals12.normalizeAgentName(a)))
|
|
9091
9379
|
],
|
|
9092
9380
|
tasks_completed: tasksCompleted,
|
|
9093
9381
|
tasks_total: tasksTotal,
|
|
@@ -9139,7 +9427,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9139
9427
|
clearTimeout(timer);
|
|
9140
9428
|
}
|
|
9141
9429
|
if (llmOutput?.trim()) {
|
|
9142
|
-
const parsed =
|
|
9430
|
+
const parsed = _internals12.parseKnowledgeRecommendationsWithDiagnostics(llmOutput);
|
|
9143
9431
|
for (const diagnostic of parsed.diagnostics) {
|
|
9144
9432
|
warn("[curator] skipped malformed recommendation line", {
|
|
9145
9433
|
phase,
|
|
@@ -9184,7 +9472,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9184
9472
|
}
|
|
9185
9473
|
const sessionId = `session-${Date.now()}`;
|
|
9186
9474
|
const now = new Date().toISOString();
|
|
9187
|
-
const summaryUpdated = await
|
|
9475
|
+
const summaryUpdated = await _internals12.mergeCuratorPhaseSummary(directory, {
|
|
9188
9476
|
phase,
|
|
9189
9477
|
phaseDigest,
|
|
9190
9478
|
complianceObservations,
|
|
@@ -9233,8 +9521,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9233
9521
|
}
|
|
9234
9522
|
const revisedSlugs = new Set;
|
|
9235
9523
|
try {
|
|
9236
|
-
const skillListResult = await
|
|
9237
|
-
const usageEntries =
|
|
9524
|
+
const skillListResult = await _internals12.listSkills(directory);
|
|
9525
|
+
const usageEntries = _internals12.readSkillUsageEntries(directory);
|
|
9238
9526
|
let revisionCallsThisPhase = 0;
|
|
9239
9527
|
for (const active of skillListResult.active) {
|
|
9240
9528
|
if (revisionCallsThisPhase >= MAX_REVISION_CALLS_PER_PHASE)
|
|
@@ -9258,8 +9546,8 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9258
9546
|
const violations = skillUsage.filter((e) => e.complianceVerdict === "violated").length;
|
|
9259
9547
|
const violationRate = violations / skillUsage.length;
|
|
9260
9548
|
if (violationRate > REVISION_VIOLATION_THRESHOLD && violationRate <= 0.3) {
|
|
9261
|
-
const content = await
|
|
9262
|
-
const fm =
|
|
9549
|
+
const content = await _internals12.readFileAsync(active.path, "utf-8");
|
|
9550
|
+
const fm = _internals12.parseDraftFrontmatter(content);
|
|
9263
9551
|
if (fm && fm.skillOrigin === "promoted_external")
|
|
9264
9552
|
continue;
|
|
9265
9553
|
const currentVersion = fm?.version ?? 1;
|
|
@@ -9270,7 +9558,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9270
9558
|
reviewerNotes: e.reviewerNotes,
|
|
9271
9559
|
timestamp: e.timestamp
|
|
9272
9560
|
}));
|
|
9273
|
-
const result2 = await
|
|
9561
|
+
const result2 = await _internals12.reviseSkill({
|
|
9274
9562
|
directory,
|
|
9275
9563
|
slug: active.slug,
|
|
9276
9564
|
skillPath: active.path,
|
|
@@ -9289,7 +9577,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
|
|
|
9289
9577
|
} catch (revisionErr) {
|
|
9290
9578
|
warn(`[curator] skill revision check failed: ${revisionErr instanceof Error ? revisionErr.message : String(revisionErr)}`);
|
|
9291
9579
|
}
|
|
9292
|
-
const autoRetireObservations = await
|
|
9580
|
+
const autoRetireObservations = await _internals12.autoRetireSkills(directory, curatorKnowledgePath, revisedSlugs);
|
|
9293
9581
|
if (autoRetireObservations.length > 0) {
|
|
9294
9582
|
const retireNote = ` [${autoRetireObservations.length} skill(s) auto-retired]`;
|
|
9295
9583
|
phaseDigest.summary += retireNote;
|
|
@@ -9852,18 +10140,18 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9852
10140
|
proposals_rejected: 0,
|
|
9853
10141
|
proposals_skipped: 0
|
|
9854
10142
|
};
|
|
9855
|
-
const knowledgeConfig = options.knowledgeConfig ?? await
|
|
10143
|
+
const knowledgeConfig = options.knowledgeConfig ?? await _internals13.loadDefaultKnowledgeConfig();
|
|
9856
10144
|
if (parsed.recommendations.length > 0) {
|
|
9857
10145
|
try {
|
|
9858
|
-
const knowledgeResult = await
|
|
10146
|
+
const knowledgeResult = await _internals13.applyCuratorKnowledgeUpdates(directory, parsed.recommendations, knowledgeConfig);
|
|
9859
10147
|
result.knowledge_applied = knowledgeResult.applied;
|
|
9860
10148
|
result.knowledge_skipped = knowledgeResult.skipped;
|
|
9861
10149
|
} catch (err) {
|
|
9862
10150
|
warnings.push(`Post-mortem knowledge actions failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9863
10151
|
}
|
|
9864
10152
|
try {
|
|
9865
|
-
const entries = await
|
|
9866
|
-
const hiveResult = await
|
|
10153
|
+
const entries = await _internals13.readSwarmKnowledge(directory);
|
|
10154
|
+
const hiveResult = await _internals13.checkHivePromotions(entries, knowledgeConfig);
|
|
9867
10155
|
result.hive_promotions = hiveResult.new_promotions;
|
|
9868
10156
|
result.hive_encounters_incremented = hiveResult.encounters_incremented;
|
|
9869
10157
|
result.hive_advancements = hiveResult.advancements;
|
|
@@ -9873,7 +10161,7 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9873
10161
|
}
|
|
9874
10162
|
if (parsed.queueTriage.length > 0) {
|
|
9875
10163
|
try {
|
|
9876
|
-
const proposalResult = await
|
|
10164
|
+
const proposalResult = await _internals13.applyProposalTriage(directory, parsed.queueTriage);
|
|
9877
10165
|
result.proposals_approved = proposalResult.approved.length;
|
|
9878
10166
|
result.proposals_rejected = proposalResult.rejected.length;
|
|
9879
10167
|
result.proposals_skipped = proposalResult.skipped.length;
|
|
@@ -9886,7 +10174,7 @@ async function executePostMortemActions(directory, parsed, options) {
|
|
|
9886
10174
|
async function verifyPostMortemKnowledgeActions(directory, recommendations) {
|
|
9887
10175
|
if (recommendations.length === 0)
|
|
9888
10176
|
return [];
|
|
9889
|
-
const entries = await
|
|
10177
|
+
const entries = await _internals13.readSwarmKnowledge(directory);
|
|
9890
10178
|
const activeEntries = entries.filter((entry) => isActiveStatus(entry.status));
|
|
9891
10179
|
const exactIds = new Set(activeEntries.map((entry) => entry.id));
|
|
9892
10180
|
const prefixMatches = new Map;
|
|
@@ -9987,7 +10275,7 @@ async function repairPostMortemActions(llmOutput, diagnostics, options) {
|
|
|
9987
10275
|
].join(`
|
|
9988
10276
|
`);
|
|
9989
10277
|
const repaired = await options.llmDelegate("", repairPrompt, ac.signal);
|
|
9990
|
-
const parsed =
|
|
10278
|
+
const parsed = _internals13.parsePostMortemActions(repaired);
|
|
9991
10279
|
if (parsed.diagnostics.length === 0) {
|
|
9992
10280
|
return parsed;
|
|
9993
10281
|
}
|
|
@@ -10040,7 +10328,7 @@ function collectRetrospectives(directory) {
|
|
|
10040
10328
|
}
|
|
10041
10329
|
async function collectDriftReports(directory) {
|
|
10042
10330
|
try {
|
|
10043
|
-
const reports = await
|
|
10331
|
+
const reports = await _internals13.readPriorDriftReports(directory);
|
|
10044
10332
|
return reports.slice(-MAX_DRIFT_REPORTS).map((report) => JSON.stringify(report, null, 2));
|
|
10045
10333
|
} catch {
|
|
10046
10334
|
return [];
|
|
@@ -10263,7 +10551,7 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
10263
10551
|
warnings
|
|
10264
10552
|
};
|
|
10265
10553
|
}
|
|
10266
|
-
const lock = await
|
|
10554
|
+
const lock = await _internals13.acquirePostMortemLock(directory, effectivePlanId);
|
|
10267
10555
|
if (!lock.acquired) {
|
|
10268
10556
|
return {
|
|
10269
10557
|
success: false,
|
|
@@ -10340,20 +10628,20 @@ async function runCuratorPostMortem(directory, options = {}) {
|
|
|
10340
10628
|
} finally {
|
|
10341
10629
|
clearTimeout(timer);
|
|
10342
10630
|
}
|
|
10343
|
-
let parsedActions =
|
|
10631
|
+
let parsedActions = _internals13.parsePostMortemActions(llmOutput);
|
|
10344
10632
|
if (parsedActions.diagnostics.length > 0) {
|
|
10345
10633
|
warnings.push(`Post-mortem structured action parse diagnostics: ${parsedActions.diagnostics.join("; ")}`);
|
|
10346
|
-
const repaired = await
|
|
10634
|
+
const repaired = await _internals13.repairPostMortemActions(llmOutput, parsedActions.diagnostics, options);
|
|
10347
10635
|
if (repaired) {
|
|
10348
10636
|
parsedActions = repaired;
|
|
10349
10637
|
warnings.push("Post-mortem structured actions repaired by LLM.");
|
|
10350
10638
|
}
|
|
10351
10639
|
}
|
|
10352
10640
|
llmSummary = parsedActions.summary;
|
|
10353
|
-
const executed = await
|
|
10641
|
+
const executed = await _internals13.executePostMortemActions(directory, parsedActions, options);
|
|
10354
10642
|
actionResult = executed.result;
|
|
10355
10643
|
warnings.push(...executed.warnings);
|
|
10356
|
-
const knowledgeVerification = await
|
|
10644
|
+
const knowledgeVerification = await _internals13.verifyPostMortemKnowledgeActions(directory, parsedActions.recommendations);
|
|
10357
10645
|
for (const item of knowledgeVerification) {
|
|
10358
10646
|
if (item.status === "not_found" || item.status === "ambiguous_prefix" || item.status === "missing_entry_id") {
|
|
10359
10647
|
warnings.push(`Post-mortem knowledge action ${item.action} for '${item.input_entry_id ?? "new"}' ${item.status}: ${item.reason}`);
|
|
@@ -10392,10 +10680,10 @@ ${actionSummary}`;
|
|
|
10392
10680
|
} catch (err) {
|
|
10393
10681
|
const msg = err instanceof Error ? err.message : String(err);
|
|
10394
10682
|
warnings.push(`LLM delegate failed, falling back to data-only report: ${msg}`);
|
|
10395
|
-
reportContent =
|
|
10683
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
10396
10684
|
}
|
|
10397
10685
|
} else {
|
|
10398
|
-
reportContent =
|
|
10686
|
+
reportContent = _internals13.buildDataOnlyReport(effectivePlanId, planSummary, knowledgeSummary, curatorDigest, proposals, unactionable, retrospectives, driftReports, { scope, sessionID: options.sessionID, planLoaded });
|
|
10399
10687
|
}
|
|
10400
10688
|
try {
|
|
10401
10689
|
const { mkdirSync: mkdirSync8 } = await import("fs");
|
|
@@ -10436,7 +10724,7 @@ ${actionSummary}`;
|
|
|
10436
10724
|
}
|
|
10437
10725
|
}
|
|
10438
10726
|
}
|
|
10439
|
-
var
|
|
10727
|
+
var _internals13 = {
|
|
10440
10728
|
acquirePostMortemLock,
|
|
10441
10729
|
collectKnowledgeSummary,
|
|
10442
10730
|
collectRetrospectives,
|
|
@@ -10453,15 +10741,15 @@ var _internals12 = {
|
|
|
10453
10741
|
verifyPostMortemKnowledgeActions,
|
|
10454
10742
|
repairPostMortemActions,
|
|
10455
10743
|
loadDefaultKnowledgeConfig: async () => {
|
|
10456
|
-
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-
|
|
10744
|
+
const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-bqn7g3ez.js");
|
|
10457
10745
|
return KnowledgeConfigSchema2.parse({});
|
|
10458
10746
|
},
|
|
10459
10747
|
applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
|
|
10460
|
-
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-
|
|
10748
|
+
const { applyCuratorKnowledgeUpdates: applyCuratorKnowledgeUpdates2 } = await import("./curator-hpc4tsjv.js");
|
|
10461
10749
|
return applyCuratorKnowledgeUpdates2(directory, recommendations, knowledgeConfig);
|
|
10462
10750
|
},
|
|
10463
10751
|
checkHivePromotions: async (entries, knowledgeConfig) => {
|
|
10464
|
-
const { checkHivePromotions } = await import("./hive-promoter-
|
|
10752
|
+
const { checkHivePromotions } = await import("./hive-promoter-0kfb4vjk.js");
|
|
10465
10753
|
return checkHivePromotions(entries, knowledgeConfig);
|
|
10466
10754
|
},
|
|
10467
10755
|
applyProposalTriage: async (directory, triage) => {
|
|
@@ -10689,7 +10977,7 @@ async function checkHivePromotions(swarmEntries, config) {
|
|
|
10689
10977
|
total_hive_entries: hiveEntries.length
|
|
10690
10978
|
};
|
|
10691
10979
|
}
|
|
10692
|
-
var
|
|
10980
|
+
var _internals14 = {
|
|
10693
10981
|
readSwarmEntries: (directory) => readKnowledge(resolveSwarmKnowledgePath(directory)),
|
|
10694
10982
|
checkHivePromotions,
|
|
10695
10983
|
readCuratorSummary,
|
|
@@ -10697,15 +10985,15 @@ var _internals13 = {
|
|
|
10697
10985
|
};
|
|
10698
10986
|
function createHivePromoterHook(directory, config) {
|
|
10699
10987
|
const hook = async (_input, _output) => {
|
|
10700
|
-
const swarmEntries = await
|
|
10701
|
-
const promotionSummary = await
|
|
10702
|
-
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);
|
|
10703
10991
|
if (!curatorSummary)
|
|
10704
10992
|
return;
|
|
10705
10993
|
const hasActivity = promotionSummary.new_promotions > 0 || promotionSummary.encounters_incremented > 0 || promotionSummary.advancements > 0;
|
|
10706
10994
|
if (!hasActivity)
|
|
10707
10995
|
return;
|
|
10708
|
-
await
|
|
10996
|
+
await _internals14.appendCuratorRecommendation(directory, {
|
|
10709
10997
|
action: "promote",
|
|
10710
10998
|
lesson: `Hive promotion: ${promotionSummary.new_promotions} new, ${promotionSummary.encounters_incremented} encounters, ${promotionSummary.advancements} advancements, ${promotionSummary.total_hive_entries} total entries`,
|
|
10711
10999
|
reason: JSON.stringify({
|
|
@@ -11046,7 +11334,7 @@ var SKILL_AUDIENCE_RUNNER_PATTERN = /^runner:(opencode|claude|codex)$/;
|
|
|
11046
11334
|
var WORKFLOW_BOOST_MIN_CONTEXT = 0.05;
|
|
11047
11335
|
var RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
|
|
11048
11336
|
var SKILL_FRONTMATTER_READ_BYTES = 16 * 1024;
|
|
11049
|
-
var
|
|
11337
|
+
var _internals15 = {
|
|
11050
11338
|
computeSkillRelevanceScore: null,
|
|
11051
11339
|
rankSkillsForContext: null,
|
|
11052
11340
|
getSkillStats: null,
|
|
@@ -11413,7 +11701,7 @@ function rankSkillsForContext(skills, taskContext, directory) {
|
|
|
11413
11701
|
const results = [];
|
|
11414
11702
|
for (const skillPath of skills) {
|
|
11415
11703
|
const skillEntries = allEntries.filter((e) => e.skillPath === skillPath);
|
|
11416
|
-
const metadata =
|
|
11704
|
+
const metadata = _internals15.readSkillMetadata(skillPath, directory);
|
|
11417
11705
|
const score = computeSkillRelevanceScore(skillPath, taskContext, skillEntries, metadata);
|
|
11418
11706
|
const entriesWithVerdict = skillEntries.filter((e) => e.complianceVerdict !== undefined && e.complianceVerdict !== "not_checked");
|
|
11419
11707
|
const compliantCount = entriesWithVerdict.filter((e) => e.complianceVerdict === "compliant").length;
|
|
@@ -11472,7 +11760,7 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11472
11760
|
} catch {}
|
|
11473
11761
|
if (!hasHistory) {
|
|
11474
11762
|
return skills.map((sp) => {
|
|
11475
|
-
const meta = metadataBySkillPath?.get(sp) ??
|
|
11763
|
+
const meta = metadataBySkillPath?.get(sp) ?? _internals15.readSkillMetadata(sp, directory);
|
|
11476
11764
|
return ` - file:${meta.path} - ${meta.name}: ${meta.description}`;
|
|
11477
11765
|
}).join(`
|
|
11478
11766
|
`);
|
|
@@ -11480,7 +11768,7 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11480
11768
|
const lines = [];
|
|
11481
11769
|
for (const skillPath of skills) {
|
|
11482
11770
|
const stats = getSkillStats(skillPath, directory);
|
|
11483
|
-
const meta = metadataBySkillPath?.get(skillPath) ??
|
|
11771
|
+
const meta = metadataBySkillPath?.get(skillPath) ?? _internals15.readSkillMetadata(skillPath, directory);
|
|
11484
11772
|
const compliancePct = Math.round(stats.complianceRate * 100);
|
|
11485
11773
|
const topAgentNames = stats.topAgents.slice(0, 3).map((a) => a.agent).join(", ");
|
|
11486
11774
|
lines.push(` - file:${meta.path} - ${meta.name}: ${meta.description} (used: ${stats.totalUsage}, compliance: ${compliancePct}%)` + (stats.topAgents.length > 0 ? ` \u2192 ${topAgentNames}` : ""));
|
|
@@ -11488,16 +11776,16 @@ function formatSkillIndexWithContext(skills, directory, metadataBySkillPath) {
|
|
|
11488
11776
|
return lines.join(`
|
|
11489
11777
|
`);
|
|
11490
11778
|
}
|
|
11491
|
-
|
|
11492
|
-
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11496
|
-
|
|
11497
|
-
|
|
11498
|
-
|
|
11499
|
-
|
|
11500
|
-
|
|
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;
|
|
11501
11789
|
|
|
11502
11790
|
// src/hooks/skill-propagation-gate.ts
|
|
11503
11791
|
function parseSimpleYaml(content) {
|
|
@@ -11599,10 +11887,10 @@ function parseYamlValue(value) {
|
|
|
11599
11887
|
}
|
|
11600
11888
|
function loadRoutingSkills(directory, targetAgent) {
|
|
11601
11889
|
const routingPath = path21.join(directory, ".opencode", "skill-routing.yaml");
|
|
11602
|
-
if (!
|
|
11890
|
+
if (!_internals16.existsSync(routingPath))
|
|
11603
11891
|
return [];
|
|
11604
11892
|
try {
|
|
11605
|
-
const content =
|
|
11893
|
+
const content = _internals16.readFileSync(routingPath, "utf-8");
|
|
11606
11894
|
const config = parseSimpleYaml(content);
|
|
11607
11895
|
if (!config?.routing)
|
|
11608
11896
|
return [];
|
|
@@ -11629,7 +11917,7 @@ var SKILL_SEARCH_ROOTS = [
|
|
|
11629
11917
|
".claude/skills"
|
|
11630
11918
|
];
|
|
11631
11919
|
var MAX_SCORING_SESSION_ENTRIES = 500;
|
|
11632
|
-
var
|
|
11920
|
+
var _internals16 = {
|
|
11633
11921
|
readdirSync: fs8.readdirSync.bind(fs8),
|
|
11634
11922
|
existsSync: fs8.existsSync.bind(fs8),
|
|
11635
11923
|
statSync: fs8.statSync.bind(fs8),
|
|
@@ -11662,11 +11950,11 @@ function discoverAvailableSkills(directory) {
|
|
|
11662
11950
|
const results = [];
|
|
11663
11951
|
for (const root of SKILL_SEARCH_ROOTS) {
|
|
11664
11952
|
const rootPath = path21.join(directory, root);
|
|
11665
|
-
if (!
|
|
11953
|
+
if (!_internals16.existsSync(rootPath))
|
|
11666
11954
|
continue;
|
|
11667
11955
|
let entries;
|
|
11668
11956
|
try {
|
|
11669
|
-
entries =
|
|
11957
|
+
entries = _internals16.readdirSync(rootPath);
|
|
11670
11958
|
} catch {
|
|
11671
11959
|
continue;
|
|
11672
11960
|
}
|
|
@@ -11674,11 +11962,11 @@ function discoverAvailableSkills(directory) {
|
|
|
11674
11962
|
if (entry.startsWith("."))
|
|
11675
11963
|
continue;
|
|
11676
11964
|
const skillDir = path21.join(rootPath, entry);
|
|
11677
|
-
if (
|
|
11965
|
+
if (_internals16.existsSync(path21.join(skillDir, "retired.marker")) || _internals16.existsSync(path21.join(skillDir, "stale.marker")))
|
|
11678
11966
|
continue;
|
|
11679
11967
|
const skillFile = path21.join(skillDir, "SKILL.md");
|
|
11680
11968
|
try {
|
|
11681
|
-
if (
|
|
11969
|
+
if (_internals16.statSync(skillDir).isDirectory() && _internals16.existsSync(skillFile)) {
|
|
11682
11970
|
results.push(path21.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
|
|
11683
11971
|
}
|
|
11684
11972
|
} catch (err) {
|
|
@@ -11710,7 +11998,7 @@ function parseDelegationArgs(args) {
|
|
|
11710
11998
|
}
|
|
11711
11999
|
if (!targetAgent)
|
|
11712
12000
|
return null;
|
|
11713
|
-
const skillsField = prompt ?
|
|
12001
|
+
const skillsField = prompt ? _internals16.extractSkillsFieldFromPrompt(prompt) : "";
|
|
11714
12002
|
return { targetAgent, skillsField };
|
|
11715
12003
|
}
|
|
11716
12004
|
function extractSkillsFieldFromPrompt(prompt) {
|
|
@@ -11751,10 +12039,10 @@ function writeWarnEvent(directory, record) {
|
|
|
11751
12039
|
const filePath = path21.join(directory, ".swarm", "events.jsonl");
|
|
11752
12040
|
try {
|
|
11753
12041
|
const dir = path21.dirname(filePath);
|
|
11754
|
-
if (!
|
|
11755
|
-
|
|
12042
|
+
if (!_internals16.existsSync(dir)) {
|
|
12043
|
+
_internals16.mkdirSync(dir, { recursive: true });
|
|
11756
12044
|
}
|
|
11757
|
-
|
|
12045
|
+
_internals16.appendFileSync(filePath, `${JSON.stringify(record)}
|
|
11758
12046
|
`, "utf-8");
|
|
11759
12047
|
} catch (err) {
|
|
11760
12048
|
warn(`[skill-propagation-gate] failed to write warning event: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -11809,7 +12097,7 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11809
12097
|
};
|
|
11810
12098
|
}
|
|
11811
12099
|
try {
|
|
11812
|
-
const root =
|
|
12100
|
+
const root = _internals16.realpathSync(directory);
|
|
11813
12101
|
const lexicalPath = path21.resolve(root, withoutPrefix);
|
|
11814
12102
|
if (!isWithinRoot(root, lexicalPath)) {
|
|
11815
12103
|
return {
|
|
@@ -11817,10 +12105,10 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11817
12105
|
reason: "skill path resolves outside the project"
|
|
11818
12106
|
};
|
|
11819
12107
|
}
|
|
11820
|
-
if (!
|
|
12108
|
+
if (!_internals16.existsSync(lexicalPath) || !_internals16.statSync(lexicalPath).isFile()) {
|
|
11821
12109
|
return { valid: false, reason: "skill file does not exist" };
|
|
11822
12110
|
}
|
|
11823
|
-
const realPath =
|
|
12111
|
+
const realPath = _internals16.realpathSync(lexicalPath);
|
|
11824
12112
|
if (!isWithinRoot(root, realPath)) {
|
|
11825
12113
|
return {
|
|
11826
12114
|
valid: false,
|
|
@@ -11829,7 +12117,7 @@ function validateSkillReference(directory, reference, context, options) {
|
|
|
11829
12117
|
}
|
|
11830
12118
|
const normalizedPath = withoutPrefix.replace(/^\.\//, "");
|
|
11831
12119
|
const validatedMetadataPath = path21.relative(root, realPath).replace(/\\/g, "/");
|
|
11832
|
-
const metadata =
|
|
12120
|
+
const metadata = _internals16.readSkillMetadata(validatedMetadataPath, root);
|
|
11833
12121
|
if (metadata.frontmatterStatus !== "valid" && metadata.frontmatterStatus !== "absent") {
|
|
11834
12122
|
return {
|
|
11835
12123
|
valid: false,
|
|
@@ -11861,18 +12149,18 @@ async function validateExplicitSkillReferencesBefore(directory, input, config) {
|
|
|
11861
12149
|
if (!agentRaw || stripKnownSwarmPrefix(agentRaw) !== "architect") {
|
|
11862
12150
|
return { blocked: false, reason: null };
|
|
11863
12151
|
}
|
|
11864
|
-
const parsed =
|
|
12152
|
+
const parsed = _internals16.parseDelegationArgs(input.args);
|
|
11865
12153
|
if (!parsed)
|
|
11866
12154
|
return { blocked: false, reason: null };
|
|
11867
12155
|
const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
|
|
11868
|
-
if (!
|
|
12156
|
+
if (!_internals16.SKILL_CAPABLE_AGENTS.has(targetBase)) {
|
|
11869
12157
|
return { blocked: false, reason: null };
|
|
11870
12158
|
}
|
|
11871
12159
|
const skillsValue = parsed.skillsField.trim();
|
|
11872
12160
|
if (!skillsValue || skillsValue.toLowerCase() === "none") {
|
|
11873
12161
|
return { blocked: false, reason: null };
|
|
11874
12162
|
}
|
|
11875
|
-
const fileReferences =
|
|
12163
|
+
const fileReferences = _internals16.extractFileSkillReferences(skillsValue);
|
|
11876
12164
|
if (fileReferences.length === 0) {
|
|
11877
12165
|
return { blocked: false, reason: null, validatedSkillPaths: [] };
|
|
11878
12166
|
}
|
|
@@ -11885,7 +12173,7 @@ async function validateExplicitSkillReferencesBefore(directory, input, config) {
|
|
|
11885
12173
|
const context = resolveSkillAudienceContext(config);
|
|
11886
12174
|
const validatedSkillPaths = [];
|
|
11887
12175
|
for (const reference of fileReferences) {
|
|
11888
|
-
const result =
|
|
12176
|
+
const result = _internals16.validateSkillReference(directory, reference, context, {
|
|
11889
12177
|
enforceAudience: true
|
|
11890
12178
|
});
|
|
11891
12179
|
if (!result.valid) {
|
|
@@ -11930,18 +12218,18 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11930
12218
|
const baseAgent = stripKnownSwarmPrefix(agentRaw);
|
|
11931
12219
|
if (baseAgent !== "architect")
|
|
11932
12220
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11933
|
-
const parsed =
|
|
12221
|
+
const parsed = _internals16.parseDelegationArgs(input.args);
|
|
11934
12222
|
if (!parsed)
|
|
11935
12223
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11936
12224
|
const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
|
|
11937
|
-
if (!
|
|
12225
|
+
if (!_internals16.SKILL_CAPABLE_AGENTS.has(targetBase))
|
|
11938
12226
|
return { blocked: false, reason: null, recommendedSkills: undefined };
|
|
11939
12227
|
const sessionID = typeof input.sessionID === "string" ? input.sessionID : "unknown";
|
|
11940
12228
|
const audienceContext = resolveSkillAudienceContext(config);
|
|
11941
12229
|
const availableSkills = [];
|
|
11942
12230
|
const metadataBySkillPath = new Map;
|
|
11943
|
-
for (const skillPath of
|
|
11944
|
-
const validation =
|
|
12231
|
+
for (const skillPath of _internals16.discoverAvailableSkills(directory)) {
|
|
12232
|
+
const validation = _internals16.validateSkillReference(directory, skillPath, audienceContext, { enforceAudience: true, requireFilePrefix: false });
|
|
11945
12233
|
if (!validation.valid || !validation.skillPath)
|
|
11946
12234
|
continue;
|
|
11947
12235
|
availableSkills.push(validation.skillPath);
|
|
@@ -11952,7 +12240,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11952
12240
|
const skillsValue = parsed.skillsField.trim();
|
|
11953
12241
|
if (skillsValue && skillsValue.toLowerCase() !== "none") {
|
|
11954
12242
|
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
11955
|
-
const taskId =
|
|
12243
|
+
const taskId = _internals16.extractTaskIdFromPrompt(prompt);
|
|
11956
12244
|
const skillPaths = explicitIntegrity.validatedSkillPaths ?? [];
|
|
11957
12245
|
let coderSkillPaths = [];
|
|
11958
12246
|
if (prompt) {
|
|
@@ -11961,19 +12249,19 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11961
12249
|
const trimmed = line.trim();
|
|
11962
12250
|
if (trimmed.startsWith("SKILLS_USED_BY_CODER:")) {
|
|
11963
12251
|
const fieldVal = trimmed.slice("SKILLS_USED_BY_CODER:".length).trim();
|
|
11964
|
-
coderSkillPaths =
|
|
12252
|
+
coderSkillPaths = _internals16.parseSkillPaths(fieldVal);
|
|
11965
12253
|
break;
|
|
11966
12254
|
}
|
|
11967
12255
|
}
|
|
11968
12256
|
}
|
|
11969
12257
|
const safeCoderSkillPaths = coderSkillPaths.flatMap((skillPath) => {
|
|
11970
|
-
const validation =
|
|
12258
|
+
const validation = _internals16.validateSkillReference(directory, skillPath, audienceContext, { enforceAudience: false });
|
|
11971
12259
|
return validation.valid && validation.skillPath ? [validation.skillPath] : [];
|
|
11972
12260
|
});
|
|
11973
12261
|
const allPaths = [...new Set([...skillPaths, ...safeCoderSkillPaths])];
|
|
11974
12262
|
for (const skillPath of allPaths) {
|
|
11975
12263
|
try {
|
|
11976
|
-
|
|
12264
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
11977
12265
|
skillPath,
|
|
11978
12266
|
agentName: targetBase,
|
|
11979
12267
|
taskID: taskId,
|
|
@@ -11990,18 +12278,18 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
11990
12278
|
let scored = [];
|
|
11991
12279
|
if (skillsValue.toLowerCase() !== "none" && availableSkills.length > 0) {
|
|
11992
12280
|
try {
|
|
11993
|
-
const sessionEntries =
|
|
12281
|
+
const sessionEntries = _internals16.readSkillUsageEntriesTail(directory, {
|
|
11994
12282
|
sessionID
|
|
11995
12283
|
});
|
|
11996
|
-
if (sessionEntries.length >
|
|
12284
|
+
if (sessionEntries.length > _internals16.MAX_SCORING_SESSION_ENTRIES) {
|
|
11997
12285
|
scoringSkipped = true;
|
|
11998
|
-
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})`);
|
|
11999
12287
|
} else {
|
|
12000
12288
|
const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
|
|
12001
12289
|
scored = availableSkills.map((skillPath) => {
|
|
12002
12290
|
const skillEntries = sessionEntries.filter((e) => e.skillPath === skillPath);
|
|
12003
|
-
const metadata = metadataBySkillPath.get(skillPath) ??
|
|
12004
|
-
const score =
|
|
12291
|
+
const metadata = metadataBySkillPath.get(skillPath) ?? _internals16.readSkillMetadata(skillPath, directory);
|
|
12292
|
+
const score = _internals16.computeSkillRelevanceScore(skillPath, prompt, skillEntries, metadata);
|
|
12005
12293
|
return { skillPath, score, usageCount: skillEntries.length };
|
|
12006
12294
|
}).sort((a, b) => b.score - a.score || b.usageCount - a.usageCount);
|
|
12007
12295
|
if (scored.length > 0) {
|
|
@@ -12015,11 +12303,11 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
12015
12303
|
}
|
|
12016
12304
|
}
|
|
12017
12305
|
try {
|
|
12018
|
-
const routingPaths =
|
|
12306
|
+
const routingPaths = _internals16.loadRoutingSkills(directory, targetBase);
|
|
12019
12307
|
if (routingPaths.length > 0) {
|
|
12020
12308
|
const existingPaths = new Set(scored.map((s) => s.skillPath));
|
|
12021
12309
|
for (const routingPath of routingPaths) {
|
|
12022
|
-
const validation =
|
|
12310
|
+
const validation = _internals16.validateSkillReference(directory, routingPath, audienceContext, { enforceAudience: true, requireFilePrefix: false });
|
|
12023
12311
|
if (!validation.valid || !validation.skillPath)
|
|
12024
12312
|
continue;
|
|
12025
12313
|
const eligibleRoutingPath = validation.skillPath;
|
|
@@ -12027,7 +12315,7 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
12027
12315
|
metadataBySkillPath.set(eligibleRoutingPath, validation.metadata);
|
|
12028
12316
|
}
|
|
12029
12317
|
const routedSkillDir = path21.dirname(path21.join(directory, eligibleRoutingPath));
|
|
12030
|
-
if (
|
|
12318
|
+
if (_internals16.existsSync(path21.join(routedSkillDir, "retired.marker")) || _internals16.existsSync(path21.join(routedSkillDir, "stale.marker")))
|
|
12031
12319
|
continue;
|
|
12032
12320
|
if (!existingPaths.has(eligibleRoutingPath)) {
|
|
12033
12321
|
scored.push({
|
|
@@ -12053,12 +12341,12 @@ async function skillPropagationGateBefore(directory, input, config) {
|
|
|
12053
12341
|
} else if (typeof scored !== "undefined" && scored.length > 0) {
|
|
12054
12342
|
skillsForIndex = scored.map((r) => r.skillPath);
|
|
12055
12343
|
}
|
|
12056
|
-
const formattedIndex =
|
|
12344
|
+
const formattedIndex = _internals16.formatSkillIndexWithContext(skillsForIndex, directory, metadataBySkillPath);
|
|
12057
12345
|
if (formattedIndex.length > 0) {
|
|
12058
12346
|
const contextPath = path21.join(directory, ".swarm", "context.md");
|
|
12059
12347
|
let existingContent = "";
|
|
12060
|
-
if (
|
|
12061
|
-
existingContent =
|
|
12348
|
+
if (_internals16.existsSync(contextPath)) {
|
|
12349
|
+
existingContent = _internals16.readFileSync(contextPath, "utf-8");
|
|
12062
12350
|
}
|
|
12063
12351
|
const sectionHeader = "## Available Skills";
|
|
12064
12352
|
const newSection = `${sectionHeader}
|
|
@@ -12078,10 +12366,10 @@ ${newSection}`;
|
|
|
12078
12366
|
}
|
|
12079
12367
|
}
|
|
12080
12368
|
const swarmDir = path21.dirname(contextPath);
|
|
12081
|
-
if (!
|
|
12082
|
-
|
|
12369
|
+
if (!_internals16.existsSync(swarmDir)) {
|
|
12370
|
+
_internals16.mkdirSync(swarmDir, { recursive: true });
|
|
12083
12371
|
}
|
|
12084
|
-
|
|
12372
|
+
_internals16.writeFileSync(contextPath, updatedContent, "utf-8");
|
|
12085
12373
|
}
|
|
12086
12374
|
} catch (err) {
|
|
12087
12375
|
warn(`[skill-propagation-gate] failed to write skill index to context.md: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -12107,7 +12395,7 @@ ${newSection}`;
|
|
|
12107
12395
|
});
|
|
12108
12396
|
const warningMsg = `Skill propagation warning: Delegating to ${targetBase} without SKILLS field. ` + `Available skills: ${skillNames.join(", ")}`;
|
|
12109
12397
|
try {
|
|
12110
|
-
|
|
12398
|
+
_internals16.writeWarnEvent(directory, {
|
|
12111
12399
|
type: "skill_propagation_warn",
|
|
12112
12400
|
timestamp: new Date().toISOString(),
|
|
12113
12401
|
tool: toolName,
|
|
@@ -12139,17 +12427,17 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12139
12427
|
const validatedProvenancePaths = (fieldValue) => {
|
|
12140
12428
|
if (remainingProvenanceValidationBudget <= 0)
|
|
12141
12429
|
return [];
|
|
12142
|
-
const references =
|
|
12430
|
+
const references = _internals16.parseSkillPaths(fieldValue).slice(0, remainingProvenanceValidationBudget);
|
|
12143
12431
|
remainingProvenanceValidationBudget -= references.length;
|
|
12144
12432
|
return references.flatMap((reference) => {
|
|
12145
|
-
const validation =
|
|
12433
|
+
const validation = _internals16.validateSkillReference(directory, reference, audienceContext, { enforceAudience: true });
|
|
12146
12434
|
return validation.valid && validation.skillPath ? [validation.skillPath] : [];
|
|
12147
12435
|
});
|
|
12148
12436
|
};
|
|
12149
12437
|
let dedupKeys = new Set;
|
|
12150
12438
|
let existingEntries = [];
|
|
12151
12439
|
try {
|
|
12152
|
-
existingEntries =
|
|
12440
|
+
existingEntries = _internals16.readSkillUsageEntriesTail(directory, {
|
|
12153
12441
|
sessionID
|
|
12154
12442
|
});
|
|
12155
12443
|
dedupKeys = new Set(existingEntries.map((e, i) => {
|
|
@@ -12220,7 +12508,7 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12220
12508
|
if (isDuplicate(skillPath, "reviewer", resolvedTaskID))
|
|
12221
12509
|
continue;
|
|
12222
12510
|
try {
|
|
12223
|
-
|
|
12511
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
12224
12512
|
skillPath,
|
|
12225
12513
|
agentName: "reviewer",
|
|
12226
12514
|
taskID: resolvedTaskID,
|
|
@@ -12265,14 +12553,14 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12265
12553
|
}
|
|
12266
12554
|
if (currentTargetAgent && skillsField && skillsField.toLowerCase() !== "none") {
|
|
12267
12555
|
const skillPaths = validatedProvenancePaths(skillsField);
|
|
12268
|
-
const taskId =
|
|
12556
|
+
const taskId = _internals16.extractTaskIdFromPrompt(text);
|
|
12269
12557
|
for (const skillPath of skillPaths) {
|
|
12270
12558
|
if (hadRecordingError)
|
|
12271
12559
|
break;
|
|
12272
12560
|
if (isDuplicate(skillPath, currentTargetAgent, taskId))
|
|
12273
12561
|
continue;
|
|
12274
12562
|
try {
|
|
12275
|
-
|
|
12563
|
+
_internals16.appendSkillUsageEntry(directory, {
|
|
12276
12564
|
skillPath,
|
|
12277
12565
|
agentName: currentTargetAgent,
|
|
12278
12566
|
taskID: taskId,
|
|
@@ -12292,18 +12580,18 @@ async function skillPropagationTransformScan(directory, output, sessionID, confi
|
|
|
12292
12580
|
break;
|
|
12293
12581
|
}
|
|
12294
12582
|
}
|
|
12295
|
-
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
|
|
12305
|
-
|
|
12306
|
-
|
|
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;
|
|
12307
12595
|
|
|
12308
12596
|
// src/hooks/micro-reflector.ts
|
|
12309
12597
|
var REFLECT_OUTCOMES = new Set([
|
|
@@ -12370,7 +12658,7 @@ function hashContent(content) {
|
|
|
12370
12658
|
async function canonicalExistingPath(candidate) {
|
|
12371
12659
|
let resolved = path23.resolve(candidate);
|
|
12372
12660
|
try {
|
|
12373
|
-
resolved = await
|
|
12661
|
+
resolved = await _internals17.realpath(resolved);
|
|
12374
12662
|
} catch {}
|
|
12375
12663
|
return resolved;
|
|
12376
12664
|
}
|
|
@@ -13151,9 +13439,9 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
|
|
|
13151
13439
|
} catch {}
|
|
13152
13440
|
}
|
|
13153
13441
|
if (!options?.skipAutoPromotion) {
|
|
13154
|
-
await
|
|
13442
|
+
await _internals17.runAutoPromotion(directory, config);
|
|
13155
13443
|
if (phaseInfo.phase_number > 0) {
|
|
13156
|
-
await
|
|
13444
|
+
await _internals17.runAutoDemotion(directory, config, phaseInfo.phase_number);
|
|
13157
13445
|
}
|
|
13158
13446
|
}
|
|
13159
13447
|
return { stored, reinforced, skipped, rejected, quarantined };
|
|
@@ -13268,7 +13556,7 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
13268
13556
|
}
|
|
13269
13557
|
inFlightEvidenceEntries.add(evidenceKey);
|
|
13270
13558
|
try {
|
|
13271
|
-
await
|
|
13559
|
+
await _internals17.curateAndStoreSwarm(batch.lessons, batch.projectName, { phase_number: batch.phaseNumber }, directory, config, {
|
|
13272
13560
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
13273
13561
|
enrichmentQuota: options.enrichmentQuota
|
|
13274
13562
|
});
|
|
@@ -13300,14 +13588,14 @@ function createKnowledgeCuratorHook(directory, config, options = {}) {
|
|
|
13300
13588
|
const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
|
|
13301
13589
|
const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
|
|
13302
13590
|
const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
|
|
13303
|
-
await
|
|
13591
|
+
await _internals17.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config, {
|
|
13304
13592
|
llmDelegate: options.llmDelegateFactory?.(trigger.sessionID),
|
|
13305
13593
|
enrichmentQuota: options.enrichmentQuota
|
|
13306
13594
|
});
|
|
13307
13595
|
};
|
|
13308
13596
|
return safeHook(handler);
|
|
13309
13597
|
}
|
|
13310
|
-
var
|
|
13598
|
+
var _internals17 = {
|
|
13311
13599
|
isWriteToEvidenceFile,
|
|
13312
13600
|
curateAndStoreSwarm,
|
|
13313
13601
|
runAutoPromotion,
|
|
@@ -13346,7 +13634,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13346
13634
|
return result;
|
|
13347
13635
|
}
|
|
13348
13636
|
const timestamp = args.timestamp ?? new Date().toISOString();
|
|
13349
|
-
const provider =
|
|
13637
|
+
const provider = _internals18.createConfiguredMemoryProvider(directory, memoryConfig);
|
|
13350
13638
|
try {
|
|
13351
13639
|
result.swept = true;
|
|
13352
13640
|
for (const taskId of taskIds) {
|
|
@@ -13366,7 +13654,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13366
13654
|
}
|
|
13367
13655
|
let taskRewarded = 0;
|
|
13368
13656
|
for (const runId of runIds) {
|
|
13369
|
-
const { memoriesRewarded } = await
|
|
13657
|
+
const { memoriesRewarded } = await _internals18.applyCouncilReward(provider, {
|
|
13370
13658
|
runId,
|
|
13371
13659
|
unitId: taskId,
|
|
13372
13660
|
reward: FINALIZE_NEGATIVE_TERMINAL_REWARD,
|
|
@@ -13392,7 +13680,7 @@ async function runFinalizeRewardSweep(args) {
|
|
|
13392
13680
|
}
|
|
13393
13681
|
return result;
|
|
13394
13682
|
}
|
|
13395
|
-
var
|
|
13683
|
+
var _internals18 = {
|
|
13396
13684
|
createConfiguredMemoryProvider,
|
|
13397
13685
|
applyCouncilReward
|
|
13398
13686
|
};
|
|
@@ -14419,7 +14707,7 @@ async function reconcileStaleActiveSkills(directory, options = {}) {
|
|
|
14419
14707
|
continue;
|
|
14420
14708
|
}
|
|
14421
14709
|
try {
|
|
14422
|
-
const regen = await
|
|
14710
|
+
const regen = await _internals19.regenerateSkill(directory, skill.slug, {
|
|
14423
14711
|
evaluate: false
|
|
14424
14712
|
});
|
|
14425
14713
|
if (regen.regenerated) {
|
|
@@ -14669,7 +14957,7 @@ async function runSkillImprover(req) {
|
|
|
14669
14957
|
autoApply
|
|
14670
14958
|
};
|
|
14671
14959
|
}
|
|
14672
|
-
var
|
|
14960
|
+
var _internals19 = {
|
|
14673
14961
|
runSkillImprover,
|
|
14674
14962
|
buildDeterministicProposal,
|
|
14675
14963
|
buildLLMProposalFrame,
|
|
@@ -15072,13 +15360,13 @@ var write_retro = createSwarmTool({
|
|
|
15072
15360
|
task_id: args.task_id !== undefined ? String(args.task_id) : undefined,
|
|
15073
15361
|
metadata: args.metadata
|
|
15074
15362
|
};
|
|
15075
|
-
return await
|
|
15363
|
+
return await _internals20.executeWriteRetro(writeRetroArgs, directory);
|
|
15076
15364
|
} catch {
|
|
15077
15365
|
return JSON.stringify({ success: false, phase: rawPhase, message: "Invalid arguments" }, null, 2);
|
|
15078
15366
|
}
|
|
15079
15367
|
}
|
|
15080
15368
|
});
|
|
15081
|
-
var
|
|
15369
|
+
var _internals20 = {
|
|
15082
15370
|
executeWriteRetro,
|
|
15083
15371
|
write_retro
|
|
15084
15372
|
};
|
|
@@ -15387,8 +15675,8 @@ async function runFinalizeStage(ctx) {
|
|
|
15387
15675
|
];
|
|
15388
15676
|
ctx.curationSucceeded = false;
|
|
15389
15677
|
try {
|
|
15390
|
-
ctx.curationResult = await
|
|
15391
|
-
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),
|
|
15392
15680
|
enrichmentQuota: {
|
|
15393
15681
|
maxCalls: ctx.config.enrichment.max_calls_per_day,
|
|
15394
15682
|
window: ctx.config.enrichment.quota_window
|
|
@@ -15407,7 +15695,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15407
15695
|
if (ctx.config.hive_enabled === false) {} else {
|
|
15408
15696
|
try {
|
|
15409
15697
|
const entries = await readKnowledge(resolveSwarmKnowledgePath(ctx.directory));
|
|
15410
|
-
const result = await
|
|
15698
|
+
const result = await _internals21.checkHivePromotions(entries, ctx.config);
|
|
15411
15699
|
ctx.hivePromoted = result.new_promotions;
|
|
15412
15700
|
} catch (hiveErr) {
|
|
15413
15701
|
const msg = hiveErr instanceof Error ? hiveErr.message : String(hiveErr);
|
|
@@ -15428,7 +15716,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15428
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.` : "";
|
|
15429
15717
|
if (ctx.runSkillReview) {
|
|
15430
15718
|
try {
|
|
15431
|
-
const { config: loadedConfig } =
|
|
15719
|
+
const { config: loadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15432
15720
|
const skillImproverConfig = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
|
|
15433
15721
|
const skillReviewResult = await runAbortableSkillReview({
|
|
15434
15722
|
directory: ctx.directory,
|
|
@@ -15491,7 +15779,7 @@ async function runFinalizeStage(ctx) {
|
|
|
15491
15779
|
}
|
|
15492
15780
|
if (!ctx.planAlreadyDone || ctx.guaranteeResult.closedPhaseIds.length > 0 || ctx.guaranteeResult.closedTaskIds.length > 0) {
|
|
15493
15781
|
try {
|
|
15494
|
-
await
|
|
15782
|
+
await _internals21.closePlanTerminalState(ctx.directory, ctx.planData, {
|
|
15495
15783
|
closedPhaseIds: ctx.guaranteeResult.closedPhaseIds,
|
|
15496
15784
|
closedTaskIds: ctx.guaranteeResult.closedTaskIds,
|
|
15497
15785
|
originalStatuses: ctx.originalStatuses
|
|
@@ -15507,12 +15795,12 @@ async function runFinalizeStage(ctx) {
|
|
|
15507
15795
|
}
|
|
15508
15796
|
}
|
|
15509
15797
|
try {
|
|
15510
|
-
const { CuratorConfigSchema: CCS } = await import("./schema-
|
|
15511
|
-
const { config: pmLoadedConfig } =
|
|
15798
|
+
const { CuratorConfigSchema: CCS } = await import("./schema-bqn7g3ez.js");
|
|
15799
|
+
const { config: pmLoadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15512
15800
|
const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
|
|
15513
15801
|
if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
|
|
15514
|
-
const pmResult = await
|
|
15515
|
-
llmDelegate:
|
|
15802
|
+
const pmResult = await _internals21.runCuratorPostMortem(ctx.directory, {
|
|
15803
|
+
llmDelegate: _internals21.createCuratorLLMDelegate(ctx.directory, "postmortem", ctx.options.sessionID),
|
|
15516
15804
|
scope: "project",
|
|
15517
15805
|
sessionID: ctx.options.sessionID
|
|
15518
15806
|
});
|
|
@@ -15538,7 +15826,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
|
|
|
15538
15826
|
}
|
|
15539
15827
|
let checkpointVerified = false;
|
|
15540
15828
|
try {
|
|
15541
|
-
const result =
|
|
15829
|
+
const result = _internals21.spawnSync("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
|
|
15542
15830
|
cwd: path29.dirname(srcPath),
|
|
15543
15831
|
encoding: "utf-8",
|
|
15544
15832
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -15709,7 +15997,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
15709
15997
|
let maxAgeDays = 30;
|
|
15710
15998
|
let maxBundles = 10;
|
|
15711
15999
|
try {
|
|
15712
|
-
const { config: evidenceLoadedConfig } =
|
|
16000
|
+
const { config: evidenceLoadedConfig } = _internals21.loadPluginConfigWithMeta(ctx.directory);
|
|
15713
16001
|
const evidenceCfg = evidenceLoadedConfig.evidence ?? {};
|
|
15714
16002
|
if (typeof evidenceCfg.max_age_days === "number") {
|
|
15715
16003
|
maxAgeDays = evidenceCfg.max_age_days;
|
|
@@ -15719,7 +16007,7 @@ async function runArchiveEvidenceRetention(ctx) {
|
|
|
15719
16007
|
}
|
|
15720
16008
|
} catch {}
|
|
15721
16009
|
try {
|
|
15722
|
-
await
|
|
16010
|
+
await _internals21.archiveEvidence(ctx.directory, maxAgeDays, maxBundles);
|
|
15723
16011
|
} catch (error2) {
|
|
15724
16012
|
const msg = error2 instanceof Error ? error2.message : String(error2);
|
|
15725
16013
|
ctx.warnings.push(`Evidence retention archive failed: ${msg}`);
|
|
@@ -15922,9 +16210,9 @@ async function runAlignStage(ctx) {
|
|
|
15922
16210
|
const pruneBranches = ctx.args.includes("--prune-branches");
|
|
15923
16211
|
let gitAlignResult = "";
|
|
15924
16212
|
const prunedBranches = [];
|
|
15925
|
-
const gitStatus =
|
|
16213
|
+
const gitStatus = _internals21.getGitRepositoryStatus(ctx.directory);
|
|
15926
16214
|
if (gitStatus.isRepo) {
|
|
15927
|
-
const aggressiveResult = await
|
|
16215
|
+
const aggressiveResult = await _internals21.resetToMainAfterMerge(ctx.directory, {
|
|
15928
16216
|
pruneBranches
|
|
15929
16217
|
});
|
|
15930
16218
|
if (aggressiveResult.success) {
|
|
@@ -15936,7 +16224,7 @@ async function runAlignStage(ctx) {
|
|
|
15936
16224
|
ctx.warnings.push("Uncommitted changes were discarded during git alignment");
|
|
15937
16225
|
}
|
|
15938
16226
|
} else {
|
|
15939
|
-
const alignResult = await
|
|
16227
|
+
const alignResult = await _internals21.resetToRemoteBranch(ctx.directory, {
|
|
15940
16228
|
pruneBranches
|
|
15941
16229
|
});
|
|
15942
16230
|
gitAlignResult = alignResult.message;
|
|
@@ -15996,7 +16284,7 @@ async function handleCloseCommand(directory, args, options = {}) {
|
|
|
15996
16284
|
let finalizeLock = {
|
|
15997
16285
|
acquired: false
|
|
15998
16286
|
};
|
|
15999
|
-
finalizeLock = await
|
|
16287
|
+
finalizeLock = await _internals21.acquireFinalizeLock(directory);
|
|
16000
16288
|
if (!finalizeLock.acquired) {
|
|
16001
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.`;
|
|
16002
16290
|
}
|
|
@@ -16027,7 +16315,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16027
16315
|
if (planExists) {
|
|
16028
16316
|
planAlreadyDone = phases.length > 0 && phases.every((p) => p.status === "complete" || p.status === "completed" || p.status === "blocked" || p.status === "closed");
|
|
16029
16317
|
}
|
|
16030
|
-
const { config: loadedConfig } =
|
|
16318
|
+
const { config: loadedConfig } = _internals21.loadPluginConfigWithMeta(directory);
|
|
16031
16319
|
const config = KnowledgeConfigSchema.parse(loadedConfig.knowledge ?? {});
|
|
16032
16320
|
const ctx = {
|
|
16033
16321
|
directory,
|
|
@@ -16071,7 +16359,7 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16071
16359
|
args
|
|
16072
16360
|
};
|
|
16073
16361
|
await runFinalizeStage(ctx);
|
|
16074
|
-
await
|
|
16362
|
+
await _internals21.runFinalizeRewardSweep({
|
|
16075
16363
|
directory,
|
|
16076
16364
|
closedTaskIds: ctx.guaranteeResult.closedTaskIds,
|
|
16077
16365
|
memoryConfig: loadedConfig.memory
|
|
@@ -16152,9 +16440,9 @@ This project was already finalized in a previous /swarm close run. The plan has
|
|
|
16152
16440
|
}
|
|
16153
16441
|
const sessionIdsToEnd = [...swarmState.agentSessions.keys()];
|
|
16154
16442
|
for (const sessionId of sessionIdsToEnd) {
|
|
16155
|
-
|
|
16443
|
+
_internals21.endAgentSession(sessionId);
|
|
16156
16444
|
}
|
|
16157
|
-
|
|
16445
|
+
_internals21.resetSwarmStatePreservingSingletons();
|
|
16158
16446
|
const retroWarnings = ctx.warnings.filter((w) => w.includes("Retrospective write") || w.includes("retrospective write") || w.includes("Session retrospective"));
|
|
16159
16447
|
const otherWarnings = ctx.warnings.filter((w) => !w.includes("Retrospective write") && !w.includes("retrospective write") && !w.includes("Session retrospective"));
|
|
16160
16448
|
let warningMsg = "";
|
|
@@ -16223,7 +16511,7 @@ async function acquireFinalizeLock(directory) {
|
|
|
16223
16511
|
}
|
|
16224
16512
|
return { acquired: false };
|
|
16225
16513
|
}
|
|
16226
|
-
var
|
|
16514
|
+
var _internals21 = {
|
|
16227
16515
|
ACTIVE_STATE_DIRS_TO_CLEAN,
|
|
16228
16516
|
countSessionKnowledgeEntries,
|
|
16229
16517
|
CLOSE_SKILL_REVIEW_TIMEOUT_MS,
|
|
@@ -16251,7 +16539,7 @@ var _internals20 = {
|
|
|
16251
16539
|
endAgentSession,
|
|
16252
16540
|
spawnSync: (cmd, args, options) => {
|
|
16253
16541
|
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
16254
|
-
return
|
|
16542
|
+
return child_process3.spawnSync(cmd, args, {
|
|
16255
16543
|
...options,
|
|
16256
16544
|
env: mergedEnv
|
|
16257
16545
|
});
|
|
@@ -16279,7 +16567,7 @@ var MODES = new Set(CODEBASE_REVIEW_MODES);
|
|
|
16279
16567
|
var DEFAULT_MODE = "phase0";
|
|
16280
16568
|
var DEFAULT_SCOPE = "repository root";
|
|
16281
16569
|
var FLAG_VALUE_MISSING = (token) => `Flag "${token}" requires a value`;
|
|
16282
|
-
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]
|
|
16283
16571
|
|
|
16284
16572
|
Run the codebase-review-swarm workflow in the current repository.
|
|
16285
16573
|
|
|
@@ -16372,12 +16660,12 @@ function parseArgs(args) {
|
|
|
16372
16660
|
async function handleCodebaseReviewCommand(_directory, args) {
|
|
16373
16661
|
const parsed = parseArgs(args);
|
|
16374
16662
|
if (parsed.help) {
|
|
16375
|
-
return
|
|
16663
|
+
return USAGE2;
|
|
16376
16664
|
}
|
|
16377
16665
|
if (parsed.error) {
|
|
16378
16666
|
return `Error: ${parsed.error}
|
|
16379
16667
|
|
|
16380
|
-
${
|
|
16668
|
+
${USAGE2}`;
|
|
16381
16669
|
}
|
|
16382
16670
|
const scope = sanitizeText(parsed.rest.join(" "), MAX_SCOPE_LEN) || DEFAULT_SCOPE;
|
|
16383
16671
|
return [
|
|
@@ -16810,7 +17098,7 @@ function parseArgs2(args) {
|
|
|
16810
17098
|
}
|
|
16811
17099
|
return out;
|
|
16812
17100
|
}
|
|
16813
|
-
var
|
|
17101
|
+
var USAGE3 = [
|
|
16814
17102
|
"Usage: /swarm council <question> [--spec-review]",
|
|
16815
17103
|
"",
|
|
16816
17104
|
" question The question to put to the council",
|
|
@@ -16823,7 +17111,7 @@ async function handleCouncilCommand(_directory, args) {
|
|
|
16823
17111
|
const parsed = parseArgs2(args);
|
|
16824
17112
|
const question = sanitizeQuestion(parsed.rest.join(" "));
|
|
16825
17113
|
if (!question) {
|
|
16826
|
-
return
|
|
17114
|
+
return USAGE3;
|
|
16827
17115
|
}
|
|
16828
17116
|
const tokens = ["MODE: COUNCIL"];
|
|
16829
17117
|
if (parsed.preset) {
|
|
@@ -16841,17 +17129,17 @@ import * as fs11 from "fs";
|
|
|
16841
17129
|
import * as path33 from "path";
|
|
16842
17130
|
|
|
16843
17131
|
// src/turbo/epic/cochange-source.ts
|
|
16844
|
-
import * as
|
|
17132
|
+
import * as child_process5 from "child_process";
|
|
16845
17133
|
import { promisify as promisify2 } from "util";
|
|
16846
17134
|
|
|
16847
17135
|
// src/tools/co-change-analyzer.ts
|
|
16848
|
-
import * as
|
|
17136
|
+
import * as child_process4 from "child_process";
|
|
16849
17137
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
16850
17138
|
import { readdir, readFile as readFile10, stat as stat3 } from "fs/promises";
|
|
16851
17139
|
import * as path32 from "path";
|
|
16852
17140
|
import { promisify } from "util";
|
|
16853
17141
|
function getExecFileAsync() {
|
|
16854
|
-
return promisify(
|
|
17142
|
+
return promisify(child_process4.execFile);
|
|
16855
17143
|
}
|
|
16856
17144
|
async function parseGitLog(directory, maxCommits) {
|
|
16857
17145
|
const commitMap = new Map;
|
|
@@ -17069,9 +17357,9 @@ async function detectDarkMatter(directory, options) {
|
|
|
17069
17357
|
} catch {
|
|
17070
17358
|
return [];
|
|
17071
17359
|
}
|
|
17072
|
-
const commitMap = await
|
|
17073
|
-
const matrix =
|
|
17074
|
-
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);
|
|
17075
17363
|
const results = [];
|
|
17076
17364
|
for (const entry of matrix.values()) {
|
|
17077
17365
|
const key = `${entry.fileA}::${entry.fileB}`;
|
|
@@ -17187,11 +17475,11 @@ var co_change_analyzer = createSwarmTool({
|
|
|
17187
17475
|
npmiThreshold,
|
|
17188
17476
|
maxCommitsToAnalyze
|
|
17189
17477
|
};
|
|
17190
|
-
const pairs = await
|
|
17191
|
-
return
|
|
17478
|
+
const pairs = await _internals22.detectDarkMatter(directory, options);
|
|
17479
|
+
return _internals22.formatDarkMatterOutput(pairs);
|
|
17192
17480
|
}
|
|
17193
17481
|
});
|
|
17194
|
-
var
|
|
17482
|
+
var _internals22 = {
|
|
17195
17483
|
parseGitLog,
|
|
17196
17484
|
buildCoChangeMatrix,
|
|
17197
17485
|
getStaticEdges,
|
|
@@ -17201,14 +17489,14 @@ var _internals21 = {
|
|
|
17201
17489
|
};
|
|
17202
17490
|
|
|
17203
17491
|
// src/turbo/epic/cochange-source.ts
|
|
17204
|
-
var execFileAsync = promisify2(
|
|
17492
|
+
var execFileAsync = promisify2(child_process5.execFile);
|
|
17205
17493
|
var MAX_TRACKED_DIRS = 10;
|
|
17206
17494
|
var GIT_HEAD_TIMEOUT_MS = 5000;
|
|
17207
17495
|
var DEFAULT_MAX_COMMITS = 500;
|
|
17208
17496
|
var cache = new Map;
|
|
17209
17497
|
async function readGitHead(directory) {
|
|
17210
17498
|
try {
|
|
17211
|
-
const { stdout } = await
|
|
17499
|
+
const { stdout } = await _internals23.execFile("git", ["rev-parse", "HEAD"], {
|
|
17212
17500
|
cwd: directory,
|
|
17213
17501
|
timeout: GIT_HEAD_TIMEOUT_MS
|
|
17214
17502
|
});
|
|
@@ -17234,9 +17522,9 @@ async function getCoChangeData(directory, options) {
|
|
|
17234
17522
|
let entries;
|
|
17235
17523
|
let commitsObserved;
|
|
17236
17524
|
try {
|
|
17237
|
-
const commitMap = await
|
|
17525
|
+
const commitMap = await _internals23.parseGitLog(directory, maxCommits);
|
|
17238
17526
|
commitsObserved = commitMap.size;
|
|
17239
|
-
const matrix =
|
|
17527
|
+
const matrix = _internals23.buildCoChangeMatrix(commitMap);
|
|
17240
17528
|
entries = Array.from(matrix.values());
|
|
17241
17529
|
} catch {
|
|
17242
17530
|
return { pairs: [], commitsObserved: 0 };
|
|
@@ -17260,10 +17548,10 @@ async function getCoChangePairs(directory, options) {
|
|
|
17260
17548
|
const data = await getCoChangeData(directory, options);
|
|
17261
17549
|
return data.pairs;
|
|
17262
17550
|
}
|
|
17263
|
-
var
|
|
17551
|
+
var _internals23 = {
|
|
17264
17552
|
execFile: execFileAsync,
|
|
17265
|
-
parseGitLog:
|
|
17266
|
-
buildCoChangeMatrix:
|
|
17553
|
+
parseGitLog: _internals22.parseGitLog,
|
|
17554
|
+
buildCoChangeMatrix: _internals22.buildCoChangeMatrix
|
|
17267
17555
|
};
|
|
17268
17556
|
|
|
17269
17557
|
// src/turbo/epic/cochange-conflict.ts
|
|
@@ -17545,7 +17833,7 @@ async function handleCouplingCommand(directory, args) {
|
|
|
17545
17833
|
|
|
17546
17834
|
Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>] [--format markdown|json] [--persist]`;
|
|
17547
17835
|
}
|
|
17548
|
-
const plan = await
|
|
17836
|
+
const plan = await _internals24.loadPlanJsonOnly(directory);
|
|
17549
17837
|
if (plan === null) {
|
|
17550
17838
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` to create one before measuring coupling.";
|
|
17551
17839
|
}
|
|
@@ -17569,7 +17857,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
|
|
|
17569
17857
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
17570
17858
|
return { id: task.id, scope };
|
|
17571
17859
|
});
|
|
17572
|
-
const cochangePairs = await
|
|
17860
|
+
const cochangePairs = await _internals24.getCoChangePairs(directory);
|
|
17573
17861
|
const report = computeCouplingReport(tasks, cochangePairs, {
|
|
17574
17862
|
npmi: parsed.threshold,
|
|
17575
17863
|
minCoChanges: parsed.minCoChanges
|
|
@@ -17608,22 +17896,22 @@ _Warning: failed to persist report (${persistStatus.error})._`;
|
|
|
17608
17896
|
}
|
|
17609
17897
|
return `${formatCouplingReportMarkdown(report)}${persistTrailer}`;
|
|
17610
17898
|
}
|
|
17611
|
-
var
|
|
17899
|
+
var _internals24 = {
|
|
17612
17900
|
loadPlanJsonOnly,
|
|
17613
17901
|
getCoChangePairs
|
|
17614
17902
|
};
|
|
17615
17903
|
|
|
17616
17904
|
// src/commands/curate.ts
|
|
17617
|
-
var
|
|
17905
|
+
var _internals25 = {
|
|
17618
17906
|
checkHivePromotions,
|
|
17619
17907
|
readKnowledge,
|
|
17620
17908
|
resolveSwarmKnowledgePath,
|
|
17621
17909
|
readSwarmFileAsync,
|
|
17622
17910
|
loadCuratorDeps: async () => {
|
|
17623
17911
|
const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
|
|
17624
|
-
import("./schema-
|
|
17625
|
-
import("./curator-
|
|
17626
|
-
import("./curator-llm-factory-
|
|
17912
|
+
import("./schema-bqn7g3ez.js"),
|
|
17913
|
+
import("./curator-hpc4tsjv.js"),
|
|
17914
|
+
import("./curator-llm-factory-6n9sgaj8.js")
|
|
17627
17915
|
]);
|
|
17628
17916
|
return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
|
|
17629
17917
|
}
|
|
@@ -17631,15 +17919,15 @@ var _internals24 = {
|
|
|
17631
17919
|
async function handleCurateCommand(directory, _args, options) {
|
|
17632
17920
|
try {
|
|
17633
17921
|
const config = KnowledgeConfigSchema.parse({});
|
|
17634
|
-
const swarmPath =
|
|
17635
|
-
const swarmEntries = await
|
|
17636
|
-
const summary = await
|
|
17922
|
+
const swarmPath = _internals25.resolveSwarmKnowledgePath(directory);
|
|
17923
|
+
const swarmEntries = await _internals25.readKnowledge(swarmPath) ?? [];
|
|
17924
|
+
const summary = await _internals25.checkHivePromotions(swarmEntries, config);
|
|
17637
17925
|
if (options?.sessionID) {
|
|
17638
17926
|
let onDemandPhase = 1;
|
|
17639
17927
|
try {
|
|
17640
|
-
const { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 } = await
|
|
17928
|
+
const { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 } = await _internals25.loadCuratorDeps();
|
|
17641
17929
|
const curatorConfig = CuratorConfigSchema.parse({});
|
|
17642
|
-
const priorSummary = await
|
|
17930
|
+
const priorSummary = await _internals25.readSwarmFileAsync(directory, "curator-summary.json");
|
|
17643
17931
|
if (priorSummary) {
|
|
17644
17932
|
try {
|
|
17645
17933
|
const parsed = JSON.parse(priorSummary);
|
|
@@ -17650,7 +17938,7 @@ async function handleCurateCommand(directory, _args, options) {
|
|
|
17650
17938
|
}
|
|
17651
17939
|
let planPhaseCount = Infinity;
|
|
17652
17940
|
try {
|
|
17653
|
-
const planRaw = await
|
|
17941
|
+
const planRaw = await _internals25.readSwarmFileAsync(directory, "plan.json");
|
|
17654
17942
|
if (planRaw) {
|
|
17655
17943
|
const plan = JSON.parse(planRaw);
|
|
17656
17944
|
if (Array.isArray(plan.phases))
|
|
@@ -17669,8 +17957,8 @@ async function handleCurateCommand(directory, _args, options) {
|
|
|
17669
17957
|
summary.knowledge_skipped = applied.skipped;
|
|
17670
17958
|
summary.curator_phase = onDemandPhase;
|
|
17671
17959
|
try {
|
|
17672
|
-
const updatedEntries = await
|
|
17673
|
-
const postUpdateHive = await
|
|
17960
|
+
const updatedEntries = await _internals25.readKnowledge(swarmPath) ?? [];
|
|
17961
|
+
const postUpdateHive = await _internals25.checkHivePromotions(updatedEntries, config);
|
|
17674
17962
|
summary.new_promotions += postUpdateHive.new_promotions;
|
|
17675
17963
|
summary.encounters_incremented += postUpdateHive.encounters_incremented;
|
|
17676
17964
|
summary.advancements += postUpdateHive.advancements;
|
|
@@ -17735,7 +18023,7 @@ async function handleDarkMatterCommand(directory, args) {
|
|
|
17735
18023
|
}
|
|
17736
18024
|
let pairs;
|
|
17737
18025
|
try {
|
|
17738
|
-
pairs = await
|
|
18026
|
+
pairs = await _internals22.detectDarkMatter(directory, options);
|
|
17739
18027
|
} catch (err) {
|
|
17740
18028
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
17741
18029
|
return `## Dark Matter Analysis Failed
|
|
@@ -17778,7 +18066,7 @@ var PROFILES = new Set([
|
|
|
17778
18066
|
var DEFAULT_PROFILE = "standard";
|
|
17779
18067
|
var DEFAULT_MAX_EXPLORERS = 6;
|
|
17780
18068
|
var FULL_PROFILE_DEFAULT_MAX_EXPLORERS = 8;
|
|
17781
|
-
var
|
|
18069
|
+
var USAGE4 = `Usage: /swarm deep-dive <scope> [--profile standard|security|ux|architecture|full] [--max-explorers N] [--json] [--skip-update] [--allow-dirty]
|
|
17782
18070
|
|
|
17783
18071
|
Run a bounded, evidence-backed deep dive on an application section.
|
|
17784
18072
|
|
|
@@ -17867,11 +18155,11 @@ async function handleDeepDiveCommand(_directory, args) {
|
|
|
17867
18155
|
if (parsed.error) {
|
|
17868
18156
|
return `Error: ${parsed.error}
|
|
17869
18157
|
|
|
17870
|
-
${
|
|
18158
|
+
${USAGE4}`;
|
|
17871
18159
|
}
|
|
17872
18160
|
const scope = sanitizeScope(parsed.rest.join(" "));
|
|
17873
18161
|
if (!scope) {
|
|
17874
|
-
return
|
|
18162
|
+
return USAGE4;
|
|
17875
18163
|
}
|
|
17876
18164
|
if (parsed.profile === "full" && !parsed.maxExplorersExplicit) {
|
|
17877
18165
|
parsed.maxExplorers = FULL_PROFILE_DEFAULT_MAX_EXPLORERS;
|
|
@@ -17888,7 +18176,7 @@ var DEFAULT_MAX_RESEARCHERS = 3;
|
|
|
17888
18176
|
var EXHAUSTIVE_DEFAULT_MAX_RESEARCHERS = 5;
|
|
17889
18177
|
var DEFAULT_ROUNDS = 2;
|
|
17890
18178
|
var EXHAUSTIVE_DEFAULT_ROUNDS = 3;
|
|
17891
|
-
var
|
|
18179
|
+
var USAGE5 = `Usage: /swarm deep-research <question> [--depth standard|exhaustive] [--max-researchers 1..6] [--rounds 1..4] [--brief]
|
|
17892
18180
|
|
|
17893
18181
|
Run a multi-source, fact-checked deep research pass and synthesize a cited report.
|
|
17894
18182
|
|
|
@@ -17982,11 +18270,11 @@ async function handleDeepResearchCommand(_directory, args) {
|
|
|
17982
18270
|
if (parsed.error) {
|
|
17983
18271
|
return `Error: ${parsed.error}
|
|
17984
18272
|
|
|
17985
|
-
${
|
|
18273
|
+
${USAGE5}`;
|
|
17986
18274
|
}
|
|
17987
18275
|
const question = sanitizeQuestion2(parsed.rest.join(" "));
|
|
17988
18276
|
if (!question) {
|
|
17989
|
-
return
|
|
18277
|
+
return USAGE5;
|
|
17990
18278
|
}
|
|
17991
18279
|
if (parsed.depth === "exhaustive") {
|
|
17992
18280
|
if (!parsed.maxResearchersExplicit)
|
|
@@ -17999,7 +18287,7 @@ ${USAGE4}`;
|
|
|
17999
18287
|
|
|
18000
18288
|
// src/commands/design-docs.ts
|
|
18001
18289
|
var MAX_DESC_LEN = 2000;
|
|
18002
|
-
var
|
|
18290
|
+
var USAGE6 = `Usage: /swarm design-docs <description> [--out <dir>] [--lang <name>] [--update]
|
|
18003
18291
|
|
|
18004
18292
|
Generate or sync language-agnostic design docs for the project under build:
|
|
18005
18293
|
<out>/domain.md, <out>/technical-spec.md, <out>/behavior-spec.md,
|
|
@@ -18091,35 +18379,35 @@ async function handleDesignDocsCommand(directory, args) {
|
|
|
18091
18379
|
if (parsed.error) {
|
|
18092
18380
|
return `Error: ${parsed.error}
|
|
18093
18381
|
|
|
18094
|
-
${
|
|
18382
|
+
${USAGE6}`;
|
|
18095
18383
|
}
|
|
18096
18384
|
try {
|
|
18097
18385
|
const { config } = loadPluginConfigWithMeta(directory);
|
|
18098
18386
|
if (config.design_docs?.enabled !== true) {
|
|
18099
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.
|
|
18100
18388
|
|
|
18101
|
-
` +
|
|
18389
|
+
` + USAGE6;
|
|
18102
18390
|
}
|
|
18103
18391
|
} catch (configErr) {
|
|
18104
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.");
|
|
18105
18393
|
}
|
|
18106
18394
|
const description = sanitizeDescription(parsed.rest.join(" "));
|
|
18107
18395
|
if (!description && !parsed.update) {
|
|
18108
|
-
return
|
|
18396
|
+
return USAGE6;
|
|
18109
18397
|
}
|
|
18110
18398
|
const header = `[MODE: DESIGN_DOCS out=${parsed.out} lang=${parsed.lang} update=${parsed.update}] ${description}`;
|
|
18111
18399
|
return header.trimEnd();
|
|
18112
18400
|
}
|
|
18113
18401
|
|
|
18114
18402
|
// src/services/diagnose-service.ts
|
|
18115
|
-
import * as
|
|
18403
|
+
import * as child_process6 from "child_process";
|
|
18116
18404
|
import { existsSync as existsSync23, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
18117
18405
|
import * as path36 from "path";
|
|
18118
18406
|
import { fileURLToPath } from "url";
|
|
18119
18407
|
// package.json
|
|
18120
18408
|
var package_default = {
|
|
18121
18409
|
name: "opencode-swarm",
|
|
18122
|
-
version: "7.
|
|
18410
|
+
version: "7.115.0",
|
|
18123
18411
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
18124
18412
|
main: "dist/index.js",
|
|
18125
18413
|
types: "dist/index.d.ts",
|
|
@@ -18571,7 +18859,7 @@ function resolveCachePackageRoot(cachePath) {
|
|
|
18571
18859
|
const nestedPackageRoot = path36.join(cachePath, "node_modules", "opencode-swarm");
|
|
18572
18860
|
return existsSync23(nestedPackageRoot) ? nestedPackageRoot : cachePath;
|
|
18573
18861
|
}
|
|
18574
|
-
var
|
|
18862
|
+
var _internals26 = {
|
|
18575
18863
|
detectSandboxCapability: () => sandboxCapabilityProbe.detect(),
|
|
18576
18864
|
getSandboxExecutor: getExecutor
|
|
18577
18865
|
};
|
|
@@ -18827,7 +19115,7 @@ async function checkGitRepository(directory) {
|
|
|
18827
19115
|
detail: "Invalid directory \u2014 cannot check git status"
|
|
18828
19116
|
};
|
|
18829
19117
|
}
|
|
18830
|
-
|
|
19118
|
+
child_process6.execSync("git rev-parse --git-dir", {
|
|
18831
19119
|
cwd: directory,
|
|
18832
19120
|
stdio: "pipe"
|
|
18833
19121
|
});
|
|
@@ -19155,9 +19443,9 @@ async function checkCurator(directory) {
|
|
|
19155
19443
|
}
|
|
19156
19444
|
async function getSandboxStatus() {
|
|
19157
19445
|
try {
|
|
19158
|
-
const capability = await
|
|
19446
|
+
const capability = await _internals26.detectSandboxCapability();
|
|
19159
19447
|
const mechanism = capability.mechanism ?? "none";
|
|
19160
|
-
const executor = await
|
|
19448
|
+
const executor = await _internals26.getSandboxExecutor();
|
|
19161
19449
|
const hasExecutor = executor !== null;
|
|
19162
19450
|
if (hasExecutor) {
|
|
19163
19451
|
const executorStrength = executor?.strength;
|
|
@@ -19588,7 +19876,7 @@ async function handleDoctorCommand(directory, args) {
|
|
|
19588
19876
|
const result = runConfigDoctor(config, directory);
|
|
19589
19877
|
let output;
|
|
19590
19878
|
if (enableAutoFix && result.hasAutoFixableIssues) {
|
|
19591
|
-
const { runConfigDoctorWithFixes } = await import("./config-doctor-
|
|
19879
|
+
const { runConfigDoctorWithFixes } = await import("./config-doctor-htzxe394.js");
|
|
19592
19880
|
const fixResult = await runConfigDoctorWithFixes(directory, config, true);
|
|
19593
19881
|
output = formatDoctorMarkdown(fixResult.result);
|
|
19594
19882
|
} else {
|
|
@@ -19909,7 +20197,7 @@ function readPromotionEvidence(directory) {
|
|
|
19909
20197
|
}
|
|
19910
20198
|
|
|
19911
20199
|
// src/commands/epic.ts
|
|
19912
|
-
var
|
|
20200
|
+
var _internals27 = {
|
|
19913
20201
|
loadPluginConfigWithMeta,
|
|
19914
20202
|
loadPlanJsonOnly,
|
|
19915
20203
|
getCoChangeData,
|
|
@@ -19931,7 +20219,7 @@ async function handleEpicCommand(directory, args, sessionID) {
|
|
|
19931
20219
|
if (!sessionID || sessionID.trim() === "") {
|
|
19932
20220
|
return "Error: No active session context. Epic Mode requires an active session. Use /swarm epic from within an OpenCode session.";
|
|
19933
20221
|
}
|
|
19934
|
-
const session =
|
|
20222
|
+
const session = _internals27.ensureAgentSession(sessionID, undefined, directory);
|
|
19935
20223
|
const arg0 = args[0]?.toLowerCase();
|
|
19936
20224
|
switch (arg0) {
|
|
19937
20225
|
case "status":
|
|
@@ -19958,7 +20246,7 @@ Usage:
|
|
|
19958
20246
|
}
|
|
19959
20247
|
function enableAndAck(directory, sessionID, session) {
|
|
19960
20248
|
try {
|
|
19961
|
-
|
|
20249
|
+
_internals27.enableEpicMode(directory, sessionID);
|
|
19962
20250
|
} catch (err) {
|
|
19963
20251
|
return `Error enabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
19964
20252
|
}
|
|
@@ -19974,7 +20262,7 @@ function enableAndAck(directory, sessionID, session) {
|
|
|
19974
20262
|
}
|
|
19975
20263
|
function disableAndAck(directory, sessionID, session) {
|
|
19976
20264
|
try {
|
|
19977
|
-
|
|
20265
|
+
_internals27.disableEpicMode(directory, sessionID);
|
|
19978
20266
|
} catch (err) {
|
|
19979
20267
|
return `Error disabling Epic Mode: ${err instanceof Error ? err.message : String(err)}`;
|
|
19980
20268
|
}
|
|
@@ -19983,12 +20271,12 @@ function disableAndAck(directory, sessionID, session) {
|
|
|
19983
20271
|
}
|
|
19984
20272
|
function renderStatus(directory, sessionID) {
|
|
19985
20273
|
const lines = ["## Epic Mode \u2014 Status", ""];
|
|
19986
|
-
if (
|
|
20274
|
+
if (_internals27.isStateUnreadable(directory)) {
|
|
19987
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.");
|
|
19988
20276
|
return lines.join(`
|
|
19989
20277
|
`);
|
|
19990
20278
|
}
|
|
19991
|
-
const state =
|
|
20279
|
+
const state = _internals27.loadEpicSessionState(directory, sessionID);
|
|
19992
20280
|
if (!state) {
|
|
19993
20281
|
lines.push("Epic Mode has not been toggled for this session.");
|
|
19994
20282
|
return lines.join(`
|
|
@@ -20040,7 +20328,7 @@ function formatGreenfieldDetail(input) {
|
|
|
20040
20328
|
function renderLast(directory) {
|
|
20041
20329
|
let records;
|
|
20042
20330
|
try {
|
|
20043
|
-
records =
|
|
20331
|
+
records = _internals27.readPromotionEvidence(directory);
|
|
20044
20332
|
} catch (err) {
|
|
20045
20333
|
return `Error reading epic-promotions.jsonl: ${err instanceof Error ? err.message : String(err)}`;
|
|
20046
20334
|
}
|
|
@@ -20095,7 +20383,7 @@ function renderLast(directory) {
|
|
|
20095
20383
|
`);
|
|
20096
20384
|
}
|
|
20097
20385
|
function renderCalibration(directory) {
|
|
20098
|
-
if (
|
|
20386
|
+
if (_internals27.isCalibrationStateUnreadable(directory)) {
|
|
20099
20387
|
return [
|
|
20100
20388
|
"## Epic Mode \u2014 Calibration",
|
|
20101
20389
|
"",
|
|
@@ -20107,11 +20395,11 @@ function renderCalibration(directory) {
|
|
|
20107
20395
|
}
|
|
20108
20396
|
let state;
|
|
20109
20397
|
try {
|
|
20110
|
-
state =
|
|
20398
|
+
state = _internals27.loadCalibrationState(directory);
|
|
20111
20399
|
} catch (err) {
|
|
20112
20400
|
return `Error reading calibration state: ${err instanceof Error ? err.message : String(err)}`;
|
|
20113
20401
|
}
|
|
20114
|
-
const { config } =
|
|
20402
|
+
const { config } = _internals27.loadPluginConfigWithMeta(directory);
|
|
20115
20403
|
const staticThreshold = config.turbo?.epic?.mode?.activation_threshold ?? 0.3;
|
|
20116
20404
|
const calibrationCfg = config.turbo?.epic?.calibration;
|
|
20117
20405
|
const loosenWindow = calibrationCfg?.loosen_window ?? 10;
|
|
@@ -20159,7 +20447,7 @@ function renderCalibration(directory) {
|
|
|
20159
20447
|
lines.push("");
|
|
20160
20448
|
let recentDivergent = [];
|
|
20161
20449
|
try {
|
|
20162
|
-
const all =
|
|
20450
|
+
const all = _internals27.readDivergenceHistory(directory, { limit: 50 });
|
|
20163
20451
|
recentDivergent = all.filter((r) => !r.isClean).slice(-5);
|
|
20164
20452
|
} catch {}
|
|
20165
20453
|
lines.push("### Recent divergent tasks (tightened the threshold)");
|
|
@@ -20176,11 +20464,11 @@ function renderCalibration(directory) {
|
|
|
20176
20464
|
`);
|
|
20177
20465
|
}
|
|
20178
20466
|
async function renderDecide(directory) {
|
|
20179
|
-
const plan = await
|
|
20467
|
+
const plan = await _internals27.loadPlanJsonOnly(directory);
|
|
20180
20468
|
if (!plan) {
|
|
20181
20469
|
return "No plan found at `.swarm/plan.json`. Run `/swarm plan` first.";
|
|
20182
20470
|
}
|
|
20183
|
-
const { config } =
|
|
20471
|
+
const { config } = _internals27.loadPluginConfigWithMeta(directory);
|
|
20184
20472
|
const modeCfg = config.turbo?.epic?.mode;
|
|
20185
20473
|
const cochangeCfg = config.turbo?.epic?.cochange;
|
|
20186
20474
|
const activationThreshold = modeCfg?.activation_threshold ?? 0.3;
|
|
@@ -20190,20 +20478,20 @@ async function renderDecide(directory) {
|
|
|
20190
20478
|
const tasks = [];
|
|
20191
20479
|
for (const phase of plan.phases) {
|
|
20192
20480
|
for (const task of phase.tasks) {
|
|
20193
|
-
const scopeFiles =
|
|
20481
|
+
const scopeFiles = _internals27.readTaskScopes(directory, task.id);
|
|
20194
20482
|
const scope = scopeFiles ?? task.files_touched ?? [];
|
|
20195
20483
|
tasks.push({ id: task.id, scope });
|
|
20196
20484
|
}
|
|
20197
20485
|
}
|
|
20198
|
-
const { pairs, commitsObserved } = await
|
|
20486
|
+
const { pairs, commitsObserved } = await _internals27.getCoChangeData(directory);
|
|
20199
20487
|
const isGitProject = (() => {
|
|
20200
20488
|
try {
|
|
20201
|
-
return
|
|
20489
|
+
return _internals27.isGitRepo(directory);
|
|
20202
20490
|
} catch {
|
|
20203
20491
|
return false;
|
|
20204
20492
|
}
|
|
20205
20493
|
})();
|
|
20206
|
-
const verdict =
|
|
20494
|
+
const verdict = _internals27.decideEpicActivation(tasks, pairs, commitsObserved, {
|
|
20207
20495
|
activationThreshold,
|
|
20208
20496
|
minCommitsForSignal,
|
|
20209
20497
|
cochangeNpmiThreshold,
|
|
@@ -20247,7 +20535,7 @@ function formatVerdict(verdict) {
|
|
|
20247
20535
|
}
|
|
20248
20536
|
|
|
20249
20537
|
// src/services/evidence-service.ts
|
|
20250
|
-
var
|
|
20538
|
+
var _internals28 = {
|
|
20251
20539
|
loadEvidence,
|
|
20252
20540
|
listEvidenceTaskIds
|
|
20253
20541
|
};
|
|
@@ -20292,7 +20580,7 @@ function getVerdictEmoji(verdict) {
|
|
|
20292
20580
|
return getVerdictIcon(verdict);
|
|
20293
20581
|
}
|
|
20294
20582
|
async function getTaskEvidenceData(directory, taskId) {
|
|
20295
|
-
const result = await
|
|
20583
|
+
const result = await _internals28.loadEvidence(directory, taskId);
|
|
20296
20584
|
if (result.status !== "found") {
|
|
20297
20585
|
return {
|
|
20298
20586
|
hasEvidence: false,
|
|
@@ -20315,13 +20603,13 @@ async function getTaskEvidenceData(directory, taskId) {
|
|
|
20315
20603
|
};
|
|
20316
20604
|
}
|
|
20317
20605
|
async function getEvidenceListData(directory) {
|
|
20318
|
-
const taskIds = await
|
|
20606
|
+
const taskIds = await _internals28.listEvidenceTaskIds(directory);
|
|
20319
20607
|
if (taskIds.length === 0) {
|
|
20320
20608
|
return { hasEvidence: false, tasks: [] };
|
|
20321
20609
|
}
|
|
20322
20610
|
const tasks = [];
|
|
20323
20611
|
for (const taskId of taskIds) {
|
|
20324
|
-
const result = await
|
|
20612
|
+
const result = await _internals28.loadEvidence(directory, taskId);
|
|
20325
20613
|
if (result.status === "found") {
|
|
20326
20614
|
tasks.push({
|
|
20327
20615
|
taskId,
|
|
@@ -20949,7 +21237,7 @@ function extractCurrentPhaseFromPlan(plan) {
|
|
|
20949
21237
|
if (!plan) {
|
|
20950
21238
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
20951
21239
|
}
|
|
20952
|
-
if (!
|
|
21240
|
+
if (!_internals29.validatePlanPhases(plan)) {
|
|
20953
21241
|
return { currentPhase: null, currentTask: null, incompleteTasks: [] };
|
|
20954
21242
|
}
|
|
20955
21243
|
let currentPhase = null;
|
|
@@ -21091,9 +21379,9 @@ function extractPhaseMetrics(content) {
|
|
|
21091
21379
|
async function getHandoffData(directory) {
|
|
21092
21380
|
const now = new Date().toISOString();
|
|
21093
21381
|
const sessionContent = await readSwarmFileAsync(directory, "session/state.json");
|
|
21094
|
-
const sessionState =
|
|
21382
|
+
const sessionState = _internals29.parseSessionState(sessionContent);
|
|
21095
21383
|
const plan = await loadPlanJsonOnly(directory);
|
|
21096
|
-
const planInfo =
|
|
21384
|
+
const planInfo = _internals29.extractCurrentPhaseFromPlan(plan);
|
|
21097
21385
|
if (!plan) {
|
|
21098
21386
|
const planMdContent = await readSwarmFileAsync(directory, "plan.md");
|
|
21099
21387
|
if (planMdContent) {
|
|
@@ -21112,8 +21400,8 @@ async function getHandoffData(directory) {
|
|
|
21112
21400
|
}
|
|
21113
21401
|
}
|
|
21114
21402
|
const contextContent = await readSwarmFileAsync(directory, "context.md");
|
|
21115
|
-
const recentDecisions =
|
|
21116
|
-
const rawPhaseMetrics =
|
|
21403
|
+
const recentDecisions = _internals29.extractDecisions(contextContent);
|
|
21404
|
+
const rawPhaseMetrics = _internals29.extractPhaseMetrics(contextContent);
|
|
21117
21405
|
const phaseMetrics = sanitizeString(rawPhaseMetrics, 1000);
|
|
21118
21406
|
let delegationState = null;
|
|
21119
21407
|
if (sessionState?.delegationState) {
|
|
@@ -21277,7 +21565,7 @@ ${lines.join(`
|
|
|
21277
21565
|
`)}
|
|
21278
21566
|
\`\`\``;
|
|
21279
21567
|
}
|
|
21280
|
-
var
|
|
21568
|
+
var _internals29 = {
|
|
21281
21569
|
getHandoffData,
|
|
21282
21570
|
formatHandoffMarkdown,
|
|
21283
21571
|
formatContinuationPrompt,
|
|
@@ -21426,15 +21714,15 @@ async function writeSnapshot(directory, state) {
|
|
|
21426
21714
|
}
|
|
21427
21715
|
function createSnapshotWriterHook(directory) {
|
|
21428
21716
|
return (_input, _output) => {
|
|
21429
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
21717
|
+
_writeInFlight = _writeInFlight.then(() => _internals30.writeSnapshot(directory, swarmState), () => _internals30.writeSnapshot(directory, swarmState));
|
|
21430
21718
|
return _writeInFlight;
|
|
21431
21719
|
};
|
|
21432
21720
|
}
|
|
21433
21721
|
async function flushPendingSnapshot(directory) {
|
|
21434
|
-
_writeInFlight = _writeInFlight.then(() =>
|
|
21722
|
+
_writeInFlight = _writeInFlight.then(() => _internals30.writeSnapshot(directory, swarmState), () => _internals30.writeSnapshot(directory, swarmState));
|
|
21435
21723
|
await _writeInFlight;
|
|
21436
21724
|
}
|
|
21437
|
-
var
|
|
21725
|
+
var _internals30 = {
|
|
21438
21726
|
writeSnapshot,
|
|
21439
21727
|
createSnapshotWriterHook,
|
|
21440
21728
|
flushPendingSnapshot
|
|
@@ -21631,184 +21919,8 @@ async function handleHistoryCommand(directory, _args) {
|
|
|
21631
21919
|
const historyData = await getHistoryData(directory);
|
|
21632
21920
|
return formatHistoryMarkdown(historyData);
|
|
21633
21921
|
}
|
|
21634
|
-
// src/commands/_shared/url-security.ts
|
|
21635
|
-
import * as child_process6 from "child_process";
|
|
21636
|
-
var MAX_URL_LEN = 2048;
|
|
21637
|
-
var IPV4_PRIVATE = /^10\./;
|
|
21638
|
-
var IPV4_LOOPBACK = /^127\./;
|
|
21639
|
-
var IPV4_LINK_LOCAL = /^169\.254\./;
|
|
21640
|
-
var IPV4_PRIVATE_172 = /^172\.(1[6-9]|2\d|3[0-1])\./;
|
|
21641
|
-
var IPV4_PRIVATE_192 = /^192\.168\./;
|
|
21642
|
-
var IPV4_ZERO_NETWORK = /^0\./;
|
|
21643
|
-
var IPV6_LINK_LOCAL = /^fe80:/i;
|
|
21644
|
-
var IPV6_UNIQUE_LOCAL = /^f[cd][0-9a-f]{2}:/i;
|
|
21645
|
-
var _internals30 = {
|
|
21646
|
-
spawnSync: (cmd, args, options) => {
|
|
21647
|
-
const mergedEnv = mergeEnvForChild(options?.env, options?.envOverrides);
|
|
21648
|
-
return child_process6.spawnSync(cmd, args, {
|
|
21649
|
-
...options,
|
|
21650
|
-
env: mergedEnv
|
|
21651
|
-
});
|
|
21652
|
-
}
|
|
21653
|
-
};
|
|
21654
|
-
function sanitizeUrl(raw) {
|
|
21655
|
-
let urlStr = raw.trim();
|
|
21656
|
-
urlStr = urlStr.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
21657
|
-
const fragmentIdx = urlStr.indexOf("#");
|
|
21658
|
-
if (fragmentIdx !== -1) {
|
|
21659
|
-
urlStr = urlStr.slice(0, fragmentIdx);
|
|
21660
|
-
}
|
|
21661
|
-
const queryIdx = urlStr.indexOf("?");
|
|
21662
|
-
if (queryIdx !== -1) {
|
|
21663
|
-
urlStr = urlStr.slice(0, queryIdx);
|
|
21664
|
-
}
|
|
21665
|
-
urlStr = urlStr.replace(/^[A-Za-z][A-Za-z0-9+.-]*:\/\/[^@/]+@/, "https://");
|
|
21666
|
-
if (urlStr.length > MAX_URL_LEN) {
|
|
21667
|
-
urlStr = urlStr.slice(0, MAX_URL_LEN);
|
|
21668
|
-
}
|
|
21669
|
-
return urlStr.trim();
|
|
21670
|
-
}
|
|
21671
|
-
function sanitizeErrorEcho(raw, maxLength = 80) {
|
|
21672
|
-
let stripped = "";
|
|
21673
|
-
for (const ch of raw) {
|
|
21674
|
-
const cp = ch.codePointAt(0);
|
|
21675
|
-
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
21676
|
-
stripped += " ";
|
|
21677
|
-
continue;
|
|
21678
|
-
}
|
|
21679
|
-
stripped += ch;
|
|
21680
|
-
}
|
|
21681
|
-
const collapsed = stripped.replace(/\s+/g, " ").trim();
|
|
21682
|
-
if (collapsed.length <= maxLength)
|
|
21683
|
-
return collapsed;
|
|
21684
|
-
return `${collapsed.slice(0, maxLength)}\u2026`;
|
|
21685
|
-
}
|
|
21686
|
-
function containsControlCharacters(value) {
|
|
21687
|
-
for (const ch of value) {
|
|
21688
|
-
const cp = ch.codePointAt(0);
|
|
21689
|
-
if (cp !== undefined && (cp <= 31 || cp === 127)) {
|
|
21690
|
-
return true;
|
|
21691
|
-
}
|
|
21692
|
-
}
|
|
21693
|
-
return false;
|
|
21694
|
-
}
|
|
21695
|
-
function hasNonAsciiHostname(hostname) {
|
|
21696
|
-
for (const ch of hostname) {
|
|
21697
|
-
const cp = ch.codePointAt(0);
|
|
21698
|
-
if (cp !== undefined && cp > 127)
|
|
21699
|
-
return true;
|
|
21700
|
-
}
|
|
21701
|
-
return false;
|
|
21702
|
-
}
|
|
21703
|
-
function isIpv4MappedPrivateHost(inner) {
|
|
21704
|
-
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)) {
|
|
21705
|
-
return true;
|
|
21706
|
-
}
|
|
21707
|
-
const firstSegment = inner.split(":", 1)[0];
|
|
21708
|
-
if (!firstSegment)
|
|
21709
|
-
return false;
|
|
21710
|
-
const firstWord = Number.parseInt(firstSegment, 16);
|
|
21711
|
-
if (!Number.isFinite(firstWord))
|
|
21712
|
-
return false;
|
|
21713
|
-
return firstWord >= 0 && firstWord <= 255 || firstWord >= 2560 && firstWord <= 2815 || firstWord >= 32512 && firstWord <= 32767 || firstWord === 43518 || firstWord >= 44048 && firstWord <= 44063 || firstWord === 49320;
|
|
21714
|
-
}
|
|
21715
|
-
function isPrivateHost(url) {
|
|
21716
|
-
const host = url.hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
21717
|
-
if (host === "localhost" || host === "::1" || host === "0.0.0.0" || IPV4_LOOPBACK.test(host) || IPV4_ZERO_NETWORK.test(host)) {
|
|
21718
|
-
return true;
|
|
21719
|
-
}
|
|
21720
|
-
if (host.startsWith("localhost") || host === "localhost.com") {
|
|
21721
|
-
return true;
|
|
21722
|
-
}
|
|
21723
|
-
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)) {
|
|
21724
|
-
return true;
|
|
21725
|
-
}
|
|
21726
|
-
if (host.startsWith("::ffff:")) {
|
|
21727
|
-
const inner = host.slice(7);
|
|
21728
|
-
if (isIpv4MappedPrivateHost(inner)) {
|
|
21729
|
-
return true;
|
|
21730
|
-
}
|
|
21731
|
-
}
|
|
21732
|
-
return false;
|
|
21733
|
-
}
|
|
21734
|
-
function validateAndSanitizeGithubUrl(rawUrl, resource) {
|
|
21735
|
-
const sanitized = sanitizeUrl(rawUrl);
|
|
21736
|
-
if (!sanitized) {
|
|
21737
|
-
return { error: "Empty URL" };
|
|
21738
|
-
}
|
|
21739
|
-
if (!sanitized.startsWith("https://")) {
|
|
21740
|
-
return { error: "URL must use HTTPS scheme" };
|
|
21741
|
-
}
|
|
21742
|
-
try {
|
|
21743
|
-
const url = new URL(sanitized);
|
|
21744
|
-
if (hasNonAsciiHostname(url.hostname)) {
|
|
21745
|
-
return { error: "Non-ASCII hostnames are not allowed" };
|
|
21746
|
-
}
|
|
21747
|
-
if (isPrivateHost(url)) {
|
|
21748
|
-
return { error: "Private or localhost URLs are not allowed" };
|
|
21749
|
-
}
|
|
21750
|
-
const githubPattern = new RegExp(`^https:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)\\/${resource}\\/([0-9]+)\\/?$`);
|
|
21751
|
-
if (!githubPattern.test(sanitized)) {
|
|
21752
|
-
return {
|
|
21753
|
-
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)"
|
|
21754
|
-
};
|
|
21755
|
-
}
|
|
21756
|
-
return { sanitized };
|
|
21757
|
-
} catch {
|
|
21758
|
-
return { error: "Invalid URL format" };
|
|
21759
|
-
}
|
|
21760
|
-
}
|
|
21761
|
-
function detectGitRemote(cwd, laneEnv) {
|
|
21762
|
-
try {
|
|
21763
|
-
const result = _internals30.spawnSync("git", ["remote", "get-url", "origin"], {
|
|
21764
|
-
encoding: "utf-8",
|
|
21765
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
21766
|
-
timeout: 5000,
|
|
21767
|
-
...cwd ? { cwd } : {},
|
|
21768
|
-
envOverrides: laneEnv
|
|
21769
|
-
});
|
|
21770
|
-
if (result.status !== 0 || result.error) {
|
|
21771
|
-
return null;
|
|
21772
|
-
}
|
|
21773
|
-
const remoteUrl = (result.stdout ?? "").trim();
|
|
21774
|
-
return remoteUrl || null;
|
|
21775
|
-
} catch {
|
|
21776
|
-
return null;
|
|
21777
|
-
}
|
|
21778
|
-
}
|
|
21779
|
-
function parseGitRemoteUrl(remoteUrl) {
|
|
21780
|
-
const httpsMatch = remoteUrl.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/i);
|
|
21781
|
-
if (httpsMatch) {
|
|
21782
|
-
const owner = httpsMatch[1];
|
|
21783
|
-
const repo = httpsMatch[2].replace(/\.git$/, "");
|
|
21784
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21785
|
-
return null;
|
|
21786
|
-
}
|
|
21787
|
-
return { owner, repo };
|
|
21788
|
-
}
|
|
21789
|
-
const sshMatch = remoteUrl.match(/^git@github\.com:([^/]+)\/([^/]+?)(?:\.git)?$/i);
|
|
21790
|
-
if (sshMatch) {
|
|
21791
|
-
const owner = sshMatch[1];
|
|
21792
|
-
const repo = sshMatch[2].replace(/\.git$/, "");
|
|
21793
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21794
|
-
return null;
|
|
21795
|
-
}
|
|
21796
|
-
return { owner, repo };
|
|
21797
|
-
}
|
|
21798
|
-
const pathMatch = remoteUrl.match(/\/([^/]+)\/([^/]+?)(?:\.git)?\/?$/);
|
|
21799
|
-
if (pathMatch) {
|
|
21800
|
-
const owner = pathMatch[1];
|
|
21801
|
-
const repo = pathMatch[2].replace(/\.git$/, "");
|
|
21802
|
-
if (containsControlCharacters(owner) || containsControlCharacters(repo)) {
|
|
21803
|
-
return null;
|
|
21804
|
-
}
|
|
21805
|
-
return { owner, repo };
|
|
21806
|
-
}
|
|
21807
|
-
return null;
|
|
21808
|
-
}
|
|
21809
|
-
|
|
21810
21922
|
// src/commands/issue.ts
|
|
21811
|
-
var
|
|
21923
|
+
var USAGE7 = [
|
|
21812
21924
|
"Usage: /swarm issue <url|owner/repo#N|N> [--plan] [--trace] [--no-repro]",
|
|
21813
21925
|
"",
|
|
21814
21926
|
"Ingest a GitHub issue into the swarm workflow.",
|
|
@@ -21823,7 +21935,7 @@ var USAGE6 = [
|
|
|
21823
21935
|
" --no-repro Skip reproduction step"
|
|
21824
21936
|
].join(`
|
|
21825
21937
|
`);
|
|
21826
|
-
function
|
|
21938
|
+
function validateAndSanitizeUrl2(rawUrl) {
|
|
21827
21939
|
return validateAndSanitizeGithubUrl(rawUrl, "issues");
|
|
21828
21940
|
}
|
|
21829
21941
|
function parseArgs7(args) {
|
|
@@ -21897,21 +22009,21 @@ function handleIssueCommand(directory, args) {
|
|
|
21897
22009
|
const parsed = parseArgs7(args);
|
|
21898
22010
|
const rawInput = parsed.rest.join(" ").trim();
|
|
21899
22011
|
if (!rawInput) {
|
|
21900
|
-
return
|
|
22012
|
+
return USAGE7;
|
|
21901
22013
|
}
|
|
21902
22014
|
const isFullUrl = /^https?:\/\//i.test(rawInput);
|
|
21903
22015
|
const issueInfo = parseIssueRef(isFullUrl ? sanitizeUrl(rawInput) : rawInput, directory);
|
|
21904
22016
|
if (!issueInfo) {
|
|
21905
22017
|
return `Error: Could not parse issue reference from "${sanitizeErrorEcho(rawInput)}"
|
|
21906
22018
|
|
|
21907
|
-
${
|
|
22019
|
+
${USAGE7}`;
|
|
21908
22020
|
}
|
|
21909
22021
|
const issueUrl = `https://github.com/${issueInfo.owner}/${issueInfo.repo}/issues/${issueInfo.number}`;
|
|
21910
|
-
const result =
|
|
22022
|
+
const result = validateAndSanitizeUrl2(issueUrl);
|
|
21911
22023
|
if ("error" in result) {
|
|
21912
22024
|
return `Error: ${result.error}
|
|
21913
22025
|
|
|
21914
|
-
${
|
|
22026
|
+
${USAGE7}`;
|
|
21915
22027
|
}
|
|
21916
22028
|
const flags = [];
|
|
21917
22029
|
if (parsed.plan)
|
|
@@ -22980,7 +23092,7 @@ async function readLatestLoopState(directory) {
|
|
|
22980
23092
|
var _internals33 = {
|
|
22981
23093
|
readLatestLoopState
|
|
22982
23094
|
};
|
|
22983
|
-
var
|
|
23095
|
+
var USAGE8 = `Usage: /swarm loop <objective> [--max-cycles 1..5] [--autonomy checkpoint|auto] [--depth standard|exhaustive] [--resume]
|
|
22984
23096
|
|
|
22985
23097
|
Run a compound-engineering loop: brainstorm \u2192 plan \u2192 build \u2192 review \u2192 improve,
|
|
22986
23098
|
iterating until the objective is met or a budget stop condition fires.
|
|
@@ -23082,11 +23194,11 @@ async function handleLoopCommand(_directory, args) {
|
|
|
23082
23194
|
if (parsed.error) {
|
|
23083
23195
|
return `Error: ${parsed.error}
|
|
23084
23196
|
|
|
23085
|
-
${
|
|
23197
|
+
${USAGE8}`;
|
|
23086
23198
|
}
|
|
23087
23199
|
const objective = sanitizeObjective(parsed.rest.join(" "));
|
|
23088
23200
|
if (!objective && !parsed.resume) {
|
|
23089
|
-
return
|
|
23201
|
+
return USAGE8;
|
|
23090
23202
|
}
|
|
23091
23203
|
let autonomy = parsed.autonomy;
|
|
23092
23204
|
if (parsed.resume && !parsed.autonomyExplicit) {
|
|
@@ -24257,85 +24369,6 @@ async function handlePostMortemCommand(directory, args, options) {
|
|
|
24257
24369
|
}
|
|
24258
24370
|
}
|
|
24259
24371
|
|
|
24260
|
-
// src/commands/pr-ref.ts
|
|
24261
|
-
var MAX_INSTRUCTIONS_LEN = 1000;
|
|
24262
|
-
function sanitizeInstructions(raw) {
|
|
24263
|
-
const collapsed = raw.replace(/\s+/g, " ").trim();
|
|
24264
|
-
const stripped = collapsed.replace(/\[\s*MODE\s*:[^\]]*\]/gi, "");
|
|
24265
|
-
const normalized = stripped.replace(/\s+/g, " ").trim();
|
|
24266
|
-
if (normalized.length <= MAX_INSTRUCTIONS_LEN)
|
|
24267
|
-
return normalized;
|
|
24268
|
-
return `${normalized.slice(0, MAX_INSTRUCTIONS_LEN)}\u2026`;
|
|
24269
|
-
}
|
|
24270
|
-
function validateAndSanitizeUrl2(rawUrl) {
|
|
24271
|
-
return validateAndSanitizeGithubUrl(rawUrl, "pull");
|
|
24272
|
-
}
|
|
24273
|
-
function parsePrRef(input, cwd) {
|
|
24274
|
-
const urlMatch = input.match(/^https:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)\/?$/i);
|
|
24275
|
-
if (urlMatch) {
|
|
24276
|
-
if (containsControlCharacters(urlMatch[1]) || containsControlCharacters(urlMatch[2])) {
|
|
24277
|
-
return null;
|
|
24278
|
-
}
|
|
24279
|
-
return {
|
|
24280
|
-
owner: urlMatch[1],
|
|
24281
|
-
repo: urlMatch[2],
|
|
24282
|
-
number: parseInt(urlMatch[3], 10)
|
|
24283
|
-
};
|
|
24284
|
-
}
|
|
24285
|
-
const shorthandMatch = input.match(/^([^/]+)\/([^#]+)#(\d+)$/);
|
|
24286
|
-
if (shorthandMatch) {
|
|
24287
|
-
if (containsControlCharacters(shorthandMatch[1]) || containsControlCharacters(shorthandMatch[2])) {
|
|
24288
|
-
return null;
|
|
24289
|
-
}
|
|
24290
|
-
return {
|
|
24291
|
-
owner: shorthandMatch[1],
|
|
24292
|
-
repo: shorthandMatch[2],
|
|
24293
|
-
number: parseInt(shorthandMatch[3], 10)
|
|
24294
|
-
};
|
|
24295
|
-
}
|
|
24296
|
-
const bareMatch = input.match(/^(\d+)$/);
|
|
24297
|
-
if (bareMatch) {
|
|
24298
|
-
const prNumber = parseInt(bareMatch[1], 10);
|
|
24299
|
-
const remoteUrl = detectGitRemote(cwd, undefined);
|
|
24300
|
-
if (!remoteUrl) {
|
|
24301
|
-
return null;
|
|
24302
|
-
}
|
|
24303
|
-
const parsed = parseGitRemoteUrl(remoteUrl);
|
|
24304
|
-
if (!parsed) {
|
|
24305
|
-
return null;
|
|
24306
|
-
}
|
|
24307
|
-
return {
|
|
24308
|
-
owner: parsed.owner,
|
|
24309
|
-
repo: parsed.repo,
|
|
24310
|
-
number: prNumber
|
|
24311
|
-
};
|
|
24312
|
-
}
|
|
24313
|
-
return null;
|
|
24314
|
-
}
|
|
24315
|
-
function looksLikePrRef(token) {
|
|
24316
|
-
return /^https?:\/\//i.test(token) || /^[^/]+\/[^#]+#\d+$/.test(token) || /^\d+$/.test(token);
|
|
24317
|
-
}
|
|
24318
|
-
function resolvePrCommandInput(rest, cwd) {
|
|
24319
|
-
if (rest.length === 0) {
|
|
24320
|
-
return null;
|
|
24321
|
-
}
|
|
24322
|
-
const refToken = rest[0];
|
|
24323
|
-
const instructions = sanitizeInstructions(rest.slice(1).join(" "));
|
|
24324
|
-
const isFullUrl = /^https?:\/\//i.test(refToken);
|
|
24325
|
-
const prInfo = parsePrRef(isFullUrl ? sanitizeUrl(refToken) : refToken, cwd);
|
|
24326
|
-
if (!prInfo) {
|
|
24327
|
-
return {
|
|
24328
|
-
error: `Could not parse PR reference from "${sanitizeErrorEcho(refToken)}"`
|
|
24329
|
-
};
|
|
24330
|
-
}
|
|
24331
|
-
const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
|
|
24332
|
-
const result = validateAndSanitizeUrl2(prUrl);
|
|
24333
|
-
if ("error" in result) {
|
|
24334
|
-
return { error: result.error };
|
|
24335
|
-
}
|
|
24336
|
-
return { prUrl: result.sanitized, instructions };
|
|
24337
|
-
}
|
|
24338
|
-
|
|
24339
24372
|
// src/commands/pr-feedback.ts
|
|
24340
24373
|
function handlePrFeedbackCommand(directory, args) {
|
|
24341
24374
|
const rest = args.filter((t) => t.trim().length > 0);
|
|
@@ -24522,7 +24555,7 @@ async function handlePrMonitorStatusCommand(directory, _args, sessionID, source)
|
|
|
24522
24555
|
}
|
|
24523
24556
|
|
|
24524
24557
|
// src/commands/pr-review.ts
|
|
24525
|
-
var
|
|
24558
|
+
var USAGE9 = [
|
|
24526
24559
|
"Usage: /swarm pr-review <url|owner/repo#N|N> [--council] [instructions...]",
|
|
24527
24560
|
"",
|
|
24528
24561
|
"Run a full swarm PR review on a GitHub pull request.",
|
|
@@ -24560,16 +24593,16 @@ function handlePrReviewCommand(directory, args) {
|
|
|
24560
24593
|
if (parsed.unknownFlag) {
|
|
24561
24594
|
return `Error: Unknown flag "${parsed.unknownFlag}"
|
|
24562
24595
|
|
|
24563
|
-
${
|
|
24596
|
+
${USAGE9}`;
|
|
24564
24597
|
}
|
|
24565
24598
|
const resolved = resolvePrCommandInput(parsed.rest, directory);
|
|
24566
24599
|
if (resolved === null) {
|
|
24567
|
-
return
|
|
24600
|
+
return USAGE9;
|
|
24568
24601
|
}
|
|
24569
24602
|
if ("error" in resolved) {
|
|
24570
24603
|
return `Error: ${resolved.error}
|
|
24571
24604
|
|
|
24572
|
-
${
|
|
24605
|
+
${USAGE9}`;
|
|
24573
24606
|
}
|
|
24574
24607
|
const councilFlag = parsed.council ? "council=true" : "council=false";
|
|
24575
24608
|
const signal = `[MODE: PR_REVIEW pr="${resolved.prUrl}" ${councilFlag}]`;
|
|
@@ -31415,7 +31448,7 @@ var _internals46 = {
|
|
|
31415
31448
|
writeProjectedSpecSync
|
|
31416
31449
|
};
|
|
31417
31450
|
var SWARM_SPEC_REL = path61.join(".swarm", "spec.md");
|
|
31418
|
-
var
|
|
31451
|
+
var USAGE10 = `Usage:
|
|
31419
31452
|
/swarm sdd status [--json] [--source <provider>]
|
|
31420
31453
|
/swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
31421
31454
|
/swarm sdd project [--dry-run] [--overwrite] [--json] [--change <id>] [--source <provider>] [--feature <id>]
|
|
@@ -31528,11 +31561,11 @@ async function handleSddStatusCommand(directory, args) {
|
|
|
31528
31561
|
if (parsed.error)
|
|
31529
31562
|
return `Error: ${parsed.error}
|
|
31530
31563
|
|
|
31531
|
-
${
|
|
31564
|
+
${USAGE10}`;
|
|
31532
31565
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31533
31566
|
return `Error: --feature is only valid with --source speckit
|
|
31534
31567
|
|
|
31535
|
-
${
|
|
31568
|
+
${USAGE10}`;
|
|
31536
31569
|
}
|
|
31537
31570
|
const speckitDetection = detectSpeckit(directory);
|
|
31538
31571
|
const speckitPresent = speckitDetection.features.length > 0;
|
|
@@ -31599,11 +31632,11 @@ async function handleSddValidateCommand(directory, args) {
|
|
|
31599
31632
|
if (parsed.error)
|
|
31600
31633
|
return `Error: ${parsed.error}
|
|
31601
31634
|
|
|
31602
|
-
${
|
|
31635
|
+
${USAGE10}`;
|
|
31603
31636
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31604
31637
|
return `Error: --feature is only valid with --source speckit
|
|
31605
31638
|
|
|
31606
|
-
${
|
|
31639
|
+
${USAGE10}`;
|
|
31607
31640
|
}
|
|
31608
31641
|
let useSpeckit = false;
|
|
31609
31642
|
const nativeSpecExists = fs29.existsSync(path61.join(directory, SWARM_SPEC_REL));
|
|
@@ -31632,7 +31665,7 @@ ${USAGE9}`;
|
|
|
31632
31665
|
const resolution = resolveSpeckitProjection(directory);
|
|
31633
31666
|
return parsed.json ? JSON.stringify({ valid: false, error: formatSpeckitError(resolution) }, null, 2) : `Error: ${formatSpeckitError(resolution)}
|
|
31634
31667
|
|
|
31635
|
-
${
|
|
31668
|
+
${USAGE10}`;
|
|
31636
31669
|
}
|
|
31637
31670
|
}
|
|
31638
31671
|
}
|
|
@@ -31643,7 +31676,7 @@ ${USAGE9}`;
|
|
|
31643
31676
|
if (resolution.kind !== "ok" && resolution.kind !== "zero_requirements") {
|
|
31644
31677
|
return parsed.json ? JSON.stringify({ valid: false, error: formatSpeckitError(resolution) }, null, 2) : `Error: ${formatSpeckitError(resolution)}
|
|
31645
31678
|
|
|
31646
|
-
${
|
|
31679
|
+
${USAGE10}`;
|
|
31647
31680
|
}
|
|
31648
31681
|
const spec = resolution.kind === "ok" ? resolution.spec : null;
|
|
31649
31682
|
const result2 = {
|
|
@@ -31748,16 +31781,16 @@ async function handleSddProjectCommand(directory, args) {
|
|
|
31748
31781
|
if (parsed.error)
|
|
31749
31782
|
return `Error: ${parsed.error}
|
|
31750
31783
|
|
|
31751
|
-
${
|
|
31784
|
+
${USAGE10}`;
|
|
31752
31785
|
if (parsed.feature && parsed.source && parsed.source !== "speckit") {
|
|
31753
31786
|
return `Error: --feature is only valid with --source speckit
|
|
31754
31787
|
|
|
31755
|
-
${
|
|
31788
|
+
${USAGE10}`;
|
|
31756
31789
|
}
|
|
31757
31790
|
if (parsed.source === "swarm") {
|
|
31758
31791
|
return `Error: --source swarm selects the native .swarm/spec.md and does not generate a projection. Use --source openspec or --source speckit.
|
|
31759
31792
|
|
|
31760
|
-
${
|
|
31793
|
+
${USAGE10}`;
|
|
31761
31794
|
}
|
|
31762
31795
|
if (!parsed.dryRun) {
|
|
31763
31796
|
const nativeSpecPath = path61.join(directory, SWARM_SPEC_REL);
|
|
@@ -31767,7 +31800,7 @@ ${USAGE9}`;
|
|
|
31767
31800
|
"Error: .swarm/spec.md already exists.",
|
|
31768
31801
|
"Pass --overwrite to replace it.",
|
|
31769
31802
|
"",
|
|
31770
|
-
|
|
31803
|
+
USAGE10
|
|
31771
31804
|
].join(`
|
|
31772
31805
|
`);
|
|
31773
31806
|
}
|
|
@@ -31794,7 +31827,7 @@ ${USAGE9}`;
|
|
|
31794
31827
|
const resolution = resolveSpeckitProjection(directory);
|
|
31795
31828
|
return `Error: ${formatSpeckitError(resolution)}
|
|
31796
31829
|
|
|
31797
|
-
${
|
|
31830
|
+
${USAGE10}`;
|
|
31798
31831
|
}
|
|
31799
31832
|
}
|
|
31800
31833
|
}
|
|
@@ -31805,7 +31838,7 @@ ${USAGE9}`;
|
|
|
31805
31838
|
if (resolution.kind !== "ok") {
|
|
31806
31839
|
return `Error: ${formatSpeckitError(resolution)}
|
|
31807
31840
|
|
|
31808
|
-
${
|
|
31841
|
+
${USAGE10}`;
|
|
31809
31842
|
}
|
|
31810
31843
|
const result2 = _internals46.writeProjectedSpecSync(directory, {
|
|
31811
31844
|
source: "speckit",
|
|
@@ -31824,7 +31857,7 @@ ${USAGE9}`;
|
|
|
31824
31857
|
}
|
|
31825
31858
|
return `Error: ${result2.error}
|
|
31826
31859
|
|
|
31827
|
-
${
|
|
31860
|
+
${USAGE10}`;
|
|
31828
31861
|
}
|
|
31829
31862
|
if (!result2.projection) {
|
|
31830
31863
|
if (parsed.json) {
|
|
@@ -31838,7 +31871,7 @@ ${USAGE9}`;
|
|
|
31838
31871
|
return [
|
|
31839
31872
|
"SDD projection failed: no valid Spec-Kit projection could be built.",
|
|
31840
31873
|
"",
|
|
31841
|
-
|
|
31874
|
+
USAGE10
|
|
31842
31875
|
].join(`
|
|
31843
31876
|
`);
|
|
31844
31877
|
}
|
|
@@ -31881,7 +31914,7 @@ ${formatList(result2.projection.warnings)}` : ""
|
|
|
31881
31914
|
}
|
|
31882
31915
|
return `Error: ${result.error}
|
|
31883
31916
|
|
|
31884
|
-
${
|
|
31917
|
+
${USAGE10}`;
|
|
31885
31918
|
}
|
|
31886
31919
|
if (!result.projection) {
|
|
31887
31920
|
if (parsed.json) {
|
|
@@ -31895,7 +31928,7 @@ ${USAGE9}`;
|
|
|
31895
31928
|
return [
|
|
31896
31929
|
"SDD projection failed: no valid OpenSpec-compatible projection could be built.",
|
|
31897
31930
|
"",
|
|
31898
|
-
|
|
31931
|
+
USAGE10
|
|
31899
31932
|
].join(`
|
|
31900
31933
|
`);
|
|
31901
31934
|
}
|
|
@@ -31923,7 +31956,7 @@ ${formatList(result.projection.warnings)}` : ""
|
|
|
31923
31956
|
`);
|
|
31924
31957
|
}
|
|
31925
31958
|
async function handleSddCommand(_directory, _args) {
|
|
31926
|
-
return
|
|
31959
|
+
return USAGE10;
|
|
31927
31960
|
}
|
|
31928
31961
|
|
|
31929
31962
|
// src/commands/simulate.ts
|
|
@@ -31946,7 +31979,7 @@ async function handleSimulateCommand(directory, args) {
|
|
|
31946
31979
|
}
|
|
31947
31980
|
let darkMatterPairs;
|
|
31948
31981
|
try {
|
|
31949
|
-
darkMatterPairs = await
|
|
31982
|
+
darkMatterPairs = await _internals22.detectDarkMatter(directory, options);
|
|
31950
31983
|
} catch (err) {
|
|
31951
31984
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
31952
31985
|
return `## Simulate Report
|
|
@@ -33015,7 +33048,7 @@ function buildDetailedHelp(commandName, entry) {
|
|
|
33015
33048
|
async function handleHelpCommand(ctx) {
|
|
33016
33049
|
const targetCommand = ctx.args.join(" ");
|
|
33017
33050
|
if (!targetCommand) {
|
|
33018
|
-
const { buildHelpText } = await import("./index-
|
|
33051
|
+
const { buildHelpText } = await import("./index-2etc05tv.js");
|
|
33019
33052
|
return buildHelpText();
|
|
33020
33053
|
}
|
|
33021
33054
|
const tokens = targetCommand.split(/\s+/);
|
|
@@ -33024,7 +33057,7 @@ async function handleHelpCommand(ctx) {
|
|
|
33024
33057
|
return _internals49.buildDetailedHelp(resolved.key, resolved.entry);
|
|
33025
33058
|
}
|
|
33026
33059
|
const similar = _internals49.findSimilarCommands(targetCommand);
|
|
33027
|
-
const { buildHelpText: fullHelp } = await import("./index-
|
|
33060
|
+
const { buildHelpText: fullHelp } = await import("./index-2etc05tv.js");
|
|
33028
33061
|
if (similar.length > 0) {
|
|
33029
33062
|
return `Command '/swarm ${targetCommand}' not found.
|
|
33030
33063
|
|
|
@@ -33157,7 +33190,7 @@ var COMMAND_REGISTRY = {
|
|
|
33157
33190
|
},
|
|
33158
33191
|
"guardrail explain": {
|
|
33159
33192
|
handler: async (ctx) => {
|
|
33160
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
33193
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-hecpd738.js");
|
|
33161
33194
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
33162
33195
|
},
|
|
33163
33196
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -33167,7 +33200,7 @@ var COMMAND_REGISTRY = {
|
|
|
33167
33200
|
},
|
|
33168
33201
|
"guardrail-explain": {
|
|
33169
33202
|
handler: async (ctx) => {
|
|
33170
|
-
const { handleGuardrailExplain } = await import("./guardrail-explain-
|
|
33203
|
+
const { handleGuardrailExplain } = await import("./guardrail-explain-hecpd738.js");
|
|
33171
33204
|
return handleGuardrailExplain(ctx.directory, ctx.args);
|
|
33172
33205
|
},
|
|
33173
33206
|
description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
|
|
@@ -33177,7 +33210,7 @@ var COMMAND_REGISTRY = {
|
|
|
33177
33210
|
},
|
|
33178
33211
|
"guardrail-log": {
|
|
33179
33212
|
handler: async (ctx) => {
|
|
33180
|
-
const { handleGuardrailLog } = await import("./guardrail-log-
|
|
33213
|
+
const { handleGuardrailLog } = await import("./guardrail-log-dzbqcgz9.js");
|
|
33181
33214
|
return handleGuardrailLog(ctx.directory, ctx.args);
|
|
33182
33215
|
},
|
|
33183
33216
|
description: "Read the guardrail decision log (use --blocks-only for blocks)",
|
|
@@ -33527,6 +33560,14 @@ Subcommands:
|
|
|
33527
33560
|
category: "agent",
|
|
33528
33561
|
toolPolicy: "none"
|
|
33529
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
|
+
},
|
|
33530
33571
|
"pr subscribe": {
|
|
33531
33572
|
handler: (ctx) => handlePrSubscribeCommand(ctx.directory, ctx.args, ctx.sessionID),
|
|
33532
33573
|
description: "Subscribe the current session to PR state-change notifications",
|
|
@@ -34913,6 +34954,22 @@ HARD CONSTRAINTS (apply regardless of skill load success):
|
|
|
34913
34954
|
- Honor any free-text instructions that follow the closing bracket of the signal as additional scope, without dropping any ledger item.
|
|
34914
34955
|
- Quality is the only metric \u2014 time, tokens, and agent dispatches are irrelevant to correctness
|
|
34915
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
|
+
|
|
34916
34973
|
### MODE: ISSUE_INGEST
|
|
34917
34974
|
Activates when the user invokes /swarm issue <url> or the architect receives an ISSUE_INGEST signal.
|
|
34918
34975
|
|
|
@@ -39320,4 +39377,4 @@ function createCuratorLLMDelegate(directory, mode = "init", sessionId) {
|
|
|
39320
39377
|
};
|
|
39321
39378
|
}
|
|
39322
39379
|
|
|
39323
|
-
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 };
|