opencode-swarm 7.3.2 → 7.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -1
- package/dist/index.js +59 -42
- package/dist/utils/gitignore-warning.d.ts +35 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.3.
|
|
37
|
+
version: "7.3.3",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ var package_default;
|
|
|
33
33
|
var init_package = __esm(() => {
|
|
34
34
|
package_default = {
|
|
35
35
|
name: "opencode-swarm",
|
|
36
|
-
version: "7.3.
|
|
36
|
+
version: "7.3.3",
|
|
37
37
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
38
38
|
main: "dist/index.js",
|
|
39
39
|
types: "dist/index.d.ts",
|
|
@@ -65374,7 +65374,7 @@ function createAgentActivityHooks(config3, directory) {
|
|
|
65374
65374
|
const duration5 = Date.now() - entry.startTime;
|
|
65375
65375
|
const explicitSuccess = typeof output.success === "boolean" ? output.success : undefined;
|
|
65376
65376
|
const explicitFailure = explicitSuccess === false || !!output.error;
|
|
65377
|
-
const success3 = explicitFailure
|
|
65377
|
+
const success3 = !explicitFailure;
|
|
65378
65378
|
const key = entry.tool;
|
|
65379
65379
|
const existing = swarmState.toolAggregates.get(key) ?? {
|
|
65380
65380
|
tool: key,
|
|
@@ -89684,9 +89684,10 @@ async function validateDiffScope(taskId, directory) {
|
|
|
89684
89684
|
const changedFiles = await getChangedFiles(directory);
|
|
89685
89685
|
if (!changedFiles)
|
|
89686
89686
|
return null;
|
|
89687
|
+
const nonSwarmFiles = changedFiles.filter((f) => !f.replace(/\\/g, "/").startsWith(".swarm/"));
|
|
89687
89688
|
const normalise = (p) => p.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
89688
89689
|
const normScope = new Set(declaredScope.map(normalise));
|
|
89689
|
-
const undeclared =
|
|
89690
|
+
const undeclared = nonSwarmFiles.map(normalise).filter((f) => !normScope.has(f));
|
|
89690
89691
|
if (undeclared.length === 0)
|
|
89691
89692
|
return null;
|
|
89692
89693
|
const scopeStr = declaredScope.join(", ");
|
|
@@ -90812,26 +90813,10 @@ init_write_retro();
|
|
|
90812
90813
|
init_utils();
|
|
90813
90814
|
|
|
90814
90815
|
// src/utils/gitignore-warning.ts
|
|
90816
|
+
init_bun_compat();
|
|
90815
90817
|
import * as fs89 from "node:fs";
|
|
90816
90818
|
import * as path109 from "node:path";
|
|
90817
|
-
var
|
|
90818
|
-
function findGitRoot(startDir) {
|
|
90819
|
-
let current = startDir;
|
|
90820
|
-
while (true) {
|
|
90821
|
-
try {
|
|
90822
|
-
const gitPath = path109.join(current, ".git");
|
|
90823
|
-
const stat6 = fs89.statSync(gitPath);
|
|
90824
|
-
if (stat6.isDirectory()) {
|
|
90825
|
-
return current;
|
|
90826
|
-
}
|
|
90827
|
-
} catch {}
|
|
90828
|
-
const parent = path109.dirname(current);
|
|
90829
|
-
if (parent === current) {
|
|
90830
|
-
return null;
|
|
90831
|
-
}
|
|
90832
|
-
current = parent;
|
|
90833
|
-
}
|
|
90834
|
-
}
|
|
90819
|
+
var _swarmGitExcludedChecked = false;
|
|
90835
90820
|
function fileCoversSwarm(content) {
|
|
90836
90821
|
for (const rawLine of content.split(`
|
|
90837
90822
|
`)) {
|
|
@@ -90843,33 +90828,65 @@ function fileCoversSwarm(content) {
|
|
|
90843
90828
|
}
|
|
90844
90829
|
return false;
|
|
90845
90830
|
}
|
|
90846
|
-
function
|
|
90847
|
-
|
|
90848
|
-
return fs89.readFileSync(filePath, "utf8");
|
|
90849
|
-
} catch {
|
|
90850
|
-
return null;
|
|
90851
|
-
}
|
|
90852
|
-
}
|
|
90853
|
-
function warnIfSwarmNotGitignored(directory, quiet = false) {
|
|
90854
|
-
if (_gitignoreWarningEmitted)
|
|
90831
|
+
async function ensureSwarmGitExcluded(directory, options = {}) {
|
|
90832
|
+
if (_swarmGitExcludedChecked)
|
|
90855
90833
|
return;
|
|
90834
|
+
_swarmGitExcludedChecked = true;
|
|
90835
|
+
const { quiet = false } = options;
|
|
90856
90836
|
try {
|
|
90857
|
-
const
|
|
90837
|
+
const gitRootProc = bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], { stdout: "pipe", stderr: "pipe" });
|
|
90838
|
+
const [gitRootExitCode, gitRootOutput] = await Promise.all([
|
|
90839
|
+
gitRootProc.exited,
|
|
90840
|
+
gitRootProc.stdout.text()
|
|
90841
|
+
]);
|
|
90842
|
+
if (gitRootExitCode !== 0)
|
|
90843
|
+
return;
|
|
90844
|
+
const gitRoot = gitRootOutput.trim();
|
|
90858
90845
|
if (!gitRoot)
|
|
90859
90846
|
return;
|
|
90860
|
-
const
|
|
90861
|
-
|
|
90862
|
-
|
|
90847
|
+
const excludePathProc = bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], { stdout: "pipe", stderr: "pipe" });
|
|
90848
|
+
const [excludePathExitCode, excludePathRaw] = await Promise.all([
|
|
90849
|
+
excludePathProc.exited,
|
|
90850
|
+
excludePathProc.stdout.text()
|
|
90851
|
+
]);
|
|
90852
|
+
if (excludePathExitCode !== 0)
|
|
90863
90853
|
return;
|
|
90864
|
-
|
|
90865
|
-
|
|
90866
|
-
if (excludeContent !== null && fileCoversSwarm(excludeContent)) {
|
|
90867
|
-
_gitignoreWarningEmitted = true;
|
|
90854
|
+
const excludeRelPath = excludePathRaw.trim();
|
|
90855
|
+
if (!excludeRelPath)
|
|
90868
90856
|
return;
|
|
90857
|
+
const excludePath = path109.isAbsolute(excludeRelPath) ? excludeRelPath : path109.join(directory, excludeRelPath);
|
|
90858
|
+
const checkIgnoreProc = bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], { stdout: "pipe", stderr: "pipe" });
|
|
90859
|
+
const checkIgnoreExitCode = await checkIgnoreProc.exited;
|
|
90860
|
+
if (checkIgnoreExitCode !== 0) {
|
|
90861
|
+
try {
|
|
90862
|
+
fs89.mkdirSync(path109.dirname(excludePath), { recursive: true });
|
|
90863
|
+
let existing = "";
|
|
90864
|
+
try {
|
|
90865
|
+
existing = fs89.readFileSync(excludePath, "utf8");
|
|
90866
|
+
} catch {}
|
|
90867
|
+
if (!fileCoversSwarm(existing)) {
|
|
90868
|
+
fs89.appendFileSync(excludePath, `
|
|
90869
|
+
# opencode-swarm local runtime state
|
|
90870
|
+
.swarm/
|
|
90871
|
+
`, "utf8");
|
|
90872
|
+
if (!quiet) {
|
|
90873
|
+
console.warn("[opencode-swarm] Added .swarm/ to .git/info/exclude to prevent runtime state from appearing in git status.");
|
|
90874
|
+
}
|
|
90875
|
+
}
|
|
90876
|
+
} catch {}
|
|
90869
90877
|
}
|
|
90870
|
-
|
|
90871
|
-
|
|
90872
|
-
|
|
90878
|
+
const trackedProc = bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], { stdout: "pipe", stderr: "pipe" });
|
|
90879
|
+
const [trackedExitCode, trackedOutput] = await Promise.all([
|
|
90880
|
+
trackedProc.exited,
|
|
90881
|
+
trackedProc.stdout.text()
|
|
90882
|
+
]);
|
|
90883
|
+
if (trackedExitCode === 0 && trackedOutput.trim().length > 0) {
|
|
90884
|
+
console.warn(`[opencode-swarm] WARNING: .swarm/ files are tracked by Git.
|
|
90885
|
+
` + `.swarm/ contains local runtime state and may contain sensitive session data.
|
|
90886
|
+
` + `Ignoring will not affect already-tracked files. To stop tracking them, run:
|
|
90887
|
+
` + ` git rm -r --cached .swarm
|
|
90888
|
+
` + ` echo ".swarm/" >> .gitignore
|
|
90889
|
+
` + ' git commit -m "Stop tracking opencode-swarm runtime state"');
|
|
90873
90890
|
}
|
|
90874
90891
|
} catch {}
|
|
90875
90892
|
}
|
|
@@ -90977,10 +90994,10 @@ async function initializeOpenCodeSwarm(ctx) {
|
|
|
90977
90994
|
}
|
|
90978
90995
|
repoGraphHook.init().catch(() => {}).finally(() => clearTimeout(watchdog));
|
|
90979
90996
|
});
|
|
90997
|
+
await ensureSwarmGitExcluded(ctx.directory, { quiet: config3.quiet });
|
|
90980
90998
|
initTelemetry(ctx.directory);
|
|
90981
90999
|
writeSwarmConfigExampleIfNew(ctx.directory);
|
|
90982
91000
|
writeProjectConfigIfNew(ctx.directory, config3.quiet);
|
|
90983
|
-
warnIfSwarmNotGitignored(ctx.directory, config3.quiet);
|
|
90984
91001
|
if (config3.version_check !== false) {
|
|
90985
91002
|
scheduleVersionCheck(package_default.version, (msg) => {
|
|
90986
91003
|
if (config3.quiet) {
|
|
@@ -7,11 +7,46 @@ export declare let _gitignoreWarningEmitted: boolean;
|
|
|
7
7
|
* Reset the deduplication flag. Exposed for test isolation only.
|
|
8
8
|
*/
|
|
9
9
|
export declare function resetGitignoreWarningState(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Module-level flag for ensureSwarmGitExcluded deduplication.
|
|
12
|
+
* Exported for test reset purposes only.
|
|
13
|
+
*/
|
|
14
|
+
export declare let _swarmGitExcludedChecked: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Reset the ensureSwarmGitExcluded deduplication flag. Exposed for test isolation only.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resetSwarmGitExcludedState(): void;
|
|
10
19
|
/**
|
|
11
20
|
* Checks whether `.swarm/` is covered by `.gitignore` or `.git/info/exclude`
|
|
12
21
|
* in the git repo rooted at or above `directory`. If not covered, emits a
|
|
13
22
|
* single `console.warn` (unless `quiet` is true). Fires at most once per process.
|
|
14
23
|
*
|
|
15
24
|
* Never throws — any file-system error silently skips the check.
|
|
25
|
+
*
|
|
26
|
+
* @deprecated Use `ensureSwarmGitExcluded` instead. This function only recognises
|
|
27
|
+
* `.git` as a directory and does NOT handle Git worktrees or submodules.
|
|
16
28
|
*/
|
|
17
29
|
export declare function warnIfSwarmNotGitignored(directory: string, quiet?: boolean): void;
|
|
30
|
+
export interface EnsureSwarmGitExcludedOptions {
|
|
31
|
+
quiet?: boolean;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Automatically protect `.swarm/` from Git pollution before any `.swarm/` write.
|
|
35
|
+
*
|
|
36
|
+
* Uses git CLI (not filesystem walks) so it correctly handles Git worktrees
|
|
37
|
+
* and submodules where `.git` is a file rather than a directory.
|
|
38
|
+
*
|
|
39
|
+
* Steps:
|
|
40
|
+
* 1. Resolve git root via `git rev-parse --show-toplevel`
|
|
41
|
+
* 2. Resolve local exclude path via `git rev-parse --git-path info/exclude`
|
|
42
|
+
* 3. Check if `.swarm/` is already ignored via `git check-ignore -q`
|
|
43
|
+
* 4. If not ignored: append `.swarm/` to the local exclude file (idempotent)
|
|
44
|
+
* 5. Detect tracked `.swarm/` files via `git ls-files -- .swarm`
|
|
45
|
+
* 6. If tracked: emit an unsuppressed remediation warning
|
|
46
|
+
*
|
|
47
|
+
* Never throws. Fires at most once per process.
|
|
48
|
+
*
|
|
49
|
+
* quiet option: only suppresses cosmetic logs. The exclude write and tracked-file
|
|
50
|
+
* warning are never suppressed regardless of quiet mode.
|
|
51
|
+
*/
|
|
52
|
+
export declare function ensureSwarmGitExcluded(directory: string, options?: EnsureSwarmGitExcludedOptions): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.3.
|
|
3
|
+
"version": "7.3.3",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|