opencode-swarm 7.82.2 → 7.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/cli/capability-probe-jevmgwmf.js +18 -0
- package/dist/cli/config-doctor-4tcdd9vt.js +35 -0
- package/dist/cli/dispatch-k86d928w.js +477 -0
- package/dist/cli/evidence-summary-service-g2znnd33.js +320 -0
- package/dist/cli/explorer-gz70sm9b.js +16 -0
- package/dist/cli/gate-evidence-y8zn7fe2.js +29 -0
- package/dist/cli/guardrail-explain-tcamcdfy.js +30 -0
- package/dist/cli/guardrail-log-fd14n96q.js +15 -0
- package/dist/cli/index-293f68mj.js +13538 -0
- package/dist/cli/index-8ra2qpk8.js +29027 -0
- package/dist/cli/index-a76rekgs.js +67 -0
- package/dist/cli/index-a82d6d87.js +1241 -0
- package/dist/cli/index-b9v501fr.js +371 -0
- package/dist/cli/index-bcp79s17.js +1673 -0
- package/dist/cli/index-ckntc5gf.js +91 -0
- package/dist/cli/index-d9fbxaqd.js +2314 -0
- package/dist/cli/index-e7h9bb6v.js +233 -0
- package/dist/cli/index-e8pk68cc.js +540 -0
- package/dist/cli/index-eb85wtx9.js +242 -0
- package/dist/cli/index-f8r50m3h.js +14505 -0
- package/dist/cli/index-fjwwrwr5.js +37 -0
- package/dist/cli/index-hz59hg4h.js +452 -0
- package/dist/cli/index-j710h2ge.js +412 -0
- package/dist/cli/index-jfgr5gye.js +110 -0
- package/dist/cli/index-jtqkh8jf.js +119 -0
- package/dist/cli/index-p0arc26j.js +28 -0
- package/dist/cli/index-p0ye10nd.js +222 -0
- package/dist/cli/index-pv2xmc9k.js +2391 -0
- package/dist/cli/index-red8fm8p.js +2914 -0
- package/dist/cli/index-wg3r6acj.js +2042 -0
- package/dist/cli/index-xw0bcy0v.js +583 -0
- package/dist/cli/index-yhsmmv2z.js +339 -0
- package/dist/cli/index-yx44zd0p.js +40 -0
- package/dist/cli/index-zfsbaaqh.js +29 -0
- package/dist/cli/index.js +73 -69703
- package/dist/cli/knowledge-store-n4x6zyk7.js +73 -0
- package/dist/cli/pending-delegations-pz61mrsz.js +255 -0
- package/dist/cli/pr-subscriptions-y1nn36e5.js +33 -0
- package/dist/cli/schema-c2dbzhm8.js +168 -0
- package/dist/cli/skill-generator-a5ehggyg.js +55 -0
- package/dist/cli/task-envelope-qn0qtnh0.js +90 -0
- package/dist/cli/telemetry-9bbyxrvn.js +20 -0
- package/dist/cli/workspace-snapshot-w58jr2ga.js +90 -0
- package/dist/commands/guardrail-explain.d.ts +1 -0
- package/dist/commands/guardrail-log.d.ts +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/registry.d.ts +14 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +7 -0
- package/dist/hooks/guardrails/audit-log.d.ts +114 -0
- package/dist/hooks/repo-graph-builder.d.ts +4 -1
- package/dist/index.js +3615 -2378
- package/dist/services/diagnose-service.d.ts +5 -0
- package/dist/services/guardrail-explain-service.d.ts +42 -0
- package/dist/services/guardrail-log-service.d.ts +10 -0
- package/dist/tools/repo-graph/types.d.ts +6 -0
- package/package.json +2 -2
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
atomicWriteFile,
|
|
4
|
+
taskEvidencePath,
|
|
5
|
+
withTaskEvidenceLock
|
|
6
|
+
} from "./index-fjwwrwr5.js";
|
|
7
|
+
import {
|
|
8
|
+
exports_external
|
|
9
|
+
} from "./index-293f68mj.js";
|
|
10
|
+
import {
|
|
11
|
+
telemetry
|
|
12
|
+
} from "./index-p0ye10nd.js";
|
|
13
|
+
|
|
14
|
+
// src/gate-evidence.ts
|
|
15
|
+
import { mkdirSync, readFileSync, realpathSync } from "fs";
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
|
|
18
|
+
// src/validation/task-id.ts
|
|
19
|
+
var STRICT_TASK_ID_PATTERN = /^\d+\.\d+(\.\d+)*$/;
|
|
20
|
+
var RETRO_TASK_ID_REGEX = /^retro-\d+$/;
|
|
21
|
+
var INTERNAL_TOOL_ID_REGEX = /^(?:sast_scan|quality_budget|syntax_check|placeholder_scan|sbom_generate|build|secretscan)$/;
|
|
22
|
+
var GENERAL_TASK_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
23
|
+
function checkUnsafeChars(taskId) {
|
|
24
|
+
if (!taskId || taskId.length === 0) {
|
|
25
|
+
return "Invalid task ID: empty string";
|
|
26
|
+
}
|
|
27
|
+
if (/\0/.test(taskId)) {
|
|
28
|
+
return "Invalid task ID: contains null bytes";
|
|
29
|
+
}
|
|
30
|
+
for (let i = 0;i < taskId.length; i++) {
|
|
31
|
+
if (taskId.charCodeAt(i) < 32) {
|
|
32
|
+
return "Invalid task ID: contains control characters";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (taskId.includes("..") || taskId.includes("/") || taskId.includes("\\")) {
|
|
36
|
+
return "Invalid task ID: path traversal detected";
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
function isStrictTaskId(taskId) {
|
|
41
|
+
if (!taskId)
|
|
42
|
+
return false;
|
|
43
|
+
const unsafeMsg = checkUnsafeChars(taskId);
|
|
44
|
+
if (unsafeMsg)
|
|
45
|
+
return false;
|
|
46
|
+
return STRICT_TASK_ID_PATTERN.test(taskId);
|
|
47
|
+
}
|
|
48
|
+
function assertStrictTaskId(taskId) {
|
|
49
|
+
if (!isStrictTaskId(taskId)) {
|
|
50
|
+
throw new Error(`Invalid taskId: "${taskId}". Must match N.M or N.M.P (e.g. "1.1", "1.2.3").`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function sanitizeTaskId(taskId) {
|
|
54
|
+
const unsafeMsg = checkUnsafeChars(taskId);
|
|
55
|
+
if (unsafeMsg) {
|
|
56
|
+
throw new Error(unsafeMsg);
|
|
57
|
+
}
|
|
58
|
+
if (STRICT_TASK_ID_PATTERN.test(taskId) || RETRO_TASK_ID_REGEX.test(taskId) || INTERNAL_TOOL_ID_REGEX.test(taskId) || GENERAL_TASK_ID_REGEX.test(taskId)) {
|
|
59
|
+
return taskId;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Invalid task ID: must be alphanumeric (ASCII) with optional hyphens, underscores, or dots, got "${taskId}"`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/gate-evidence.ts
|
|
65
|
+
var GateEvidenceSchema = exports_external.object({
|
|
66
|
+
sessionId: exports_external.string(),
|
|
67
|
+
timestamp: exports_external.string(),
|
|
68
|
+
agent: exports_external.string()
|
|
69
|
+
}).passthrough();
|
|
70
|
+
var TaskEvidenceSchema = exports_external.object({
|
|
71
|
+
taskId: exports_external.string(),
|
|
72
|
+
required_gates: exports_external.array(exports_external.string()).default([]),
|
|
73
|
+
gates: exports_external.record(exports_external.string(), GateEvidenceSchema),
|
|
74
|
+
turbo: exports_external.boolean().optional()
|
|
75
|
+
});
|
|
76
|
+
var DEFAULT_REQUIRED_GATES = ["reviewer", "test_engineer"];
|
|
77
|
+
function isValidTaskId(taskId) {
|
|
78
|
+
return isStrictTaskId(taskId);
|
|
79
|
+
}
|
|
80
|
+
function assertValidTaskId(taskId) {
|
|
81
|
+
assertStrictTaskId(taskId);
|
|
82
|
+
}
|
|
83
|
+
function deriveRequiredGates(agentType) {
|
|
84
|
+
switch (agentType) {
|
|
85
|
+
case "coder":
|
|
86
|
+
return ["reviewer", "test_engineer"];
|
|
87
|
+
case "docs":
|
|
88
|
+
return ["docs"];
|
|
89
|
+
case "designer":
|
|
90
|
+
return ["designer", "reviewer", "test_engineer"];
|
|
91
|
+
case "explorer":
|
|
92
|
+
return ["explorer"];
|
|
93
|
+
case "sme":
|
|
94
|
+
return ["sme"];
|
|
95
|
+
case "reviewer":
|
|
96
|
+
return ["reviewer"];
|
|
97
|
+
case "test_engineer":
|
|
98
|
+
return ["test_engineer"];
|
|
99
|
+
case "critic":
|
|
100
|
+
return ["critic"];
|
|
101
|
+
case "critic_sounding_board":
|
|
102
|
+
return ["critic_sounding_board"];
|
|
103
|
+
case "critic_drift_verifier":
|
|
104
|
+
return ["critic_drift_verifier"];
|
|
105
|
+
case "critic_hallucination_verifier":
|
|
106
|
+
return ["critic_hallucination_verifier"];
|
|
107
|
+
case "critic_architecture_supervisor":
|
|
108
|
+
return ["critic_architecture_supervisor"];
|
|
109
|
+
default:
|
|
110
|
+
return ["reviewer", "test_engineer"];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function expandRequiredGates(existingGates, newAgentType) {
|
|
114
|
+
const newGates = deriveRequiredGates(newAgentType);
|
|
115
|
+
const combined = [...new Set([...existingGates ?? [], ...newGates])];
|
|
116
|
+
return combined.sort();
|
|
117
|
+
}
|
|
118
|
+
function getEvidenceDir(directory) {
|
|
119
|
+
const swarmDir = path.resolve(directory, ".swarm");
|
|
120
|
+
const evidenceDir = path.join(swarmDir, "evidence");
|
|
121
|
+
mkdirSync(evidenceDir, { recursive: true });
|
|
122
|
+
let resolvedSwarmDir;
|
|
123
|
+
let resolvedEvidenceDir;
|
|
124
|
+
try {
|
|
125
|
+
resolvedSwarmDir = path.normalize(realpathSync(swarmDir));
|
|
126
|
+
resolvedEvidenceDir = path.normalize(realpathSync(evidenceDir));
|
|
127
|
+
} catch (error) {
|
|
128
|
+
throw new Error(`Unable to resolve evidence directory: ${error.message}`);
|
|
129
|
+
}
|
|
130
|
+
const swarmPrefix = `${resolvedSwarmDir}${path.sep}`;
|
|
131
|
+
const withinSwarmBoundary = process.platform === "win32" ? resolvedEvidenceDir.toLowerCase().startsWith(swarmPrefix.toLowerCase()) : resolvedEvidenceDir.startsWith(swarmPrefix);
|
|
132
|
+
if (!withinSwarmBoundary) {
|
|
133
|
+
throw new Error(`Evidence path escapes .swarm boundary: ${resolvedEvidenceDir}`);
|
|
134
|
+
}
|
|
135
|
+
return resolvedEvidenceDir;
|
|
136
|
+
}
|
|
137
|
+
function getEvidencePath(directory, taskId) {
|
|
138
|
+
assertValidTaskId(taskId);
|
|
139
|
+
return taskEvidencePath(directory, taskId);
|
|
140
|
+
}
|
|
141
|
+
function readExisting(evidencePath, taskId) {
|
|
142
|
+
try {
|
|
143
|
+
const raw = readFileSync(evidencePath, "utf-8");
|
|
144
|
+
return TaskEvidenceSchema.parse(JSON.parse(raw));
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if (error.code === "ENOENT")
|
|
147
|
+
return null;
|
|
148
|
+
telemetry.gateParseError(taskId, error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async function recordGateEvidence(directory, taskId, gate, sessionId, turbo) {
|
|
153
|
+
assertValidTaskId(taskId);
|
|
154
|
+
await withTaskEvidenceLock(directory, taskId, gate, async () => {
|
|
155
|
+
const resolvedEvidenceDir = getEvidenceDir(directory);
|
|
156
|
+
const evidencePath = path.join(resolvedEvidenceDir, `${taskId}.json`);
|
|
157
|
+
let existing = null;
|
|
158
|
+
try {
|
|
159
|
+
existing = readExisting(evidencePath, taskId);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
telemetry.gateParseError(taskId, error);
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
164
|
+
const requiredGates = existing ? expandRequiredGates(existing.required_gates, gate) : deriveRequiredGates(gate);
|
|
165
|
+
const updated = {
|
|
166
|
+
taskId,
|
|
167
|
+
required_gates: requiredGates,
|
|
168
|
+
turbo: turbo === true ? true : existing?.turbo,
|
|
169
|
+
gates: {
|
|
170
|
+
...existing?.gates ?? {},
|
|
171
|
+
[gate]: {
|
|
172
|
+
sessionId,
|
|
173
|
+
timestamp: new Date().toISOString(),
|
|
174
|
+
agent: gate
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
await atomicWriteFile(evidencePath, JSON.stringify(updated, null, 2));
|
|
179
|
+
});
|
|
180
|
+
telemetry.gatePassed(sessionId, gate, taskId);
|
|
181
|
+
}
|
|
182
|
+
async function recordAgentDispatch(directory, taskId, agentType, turbo) {
|
|
183
|
+
assertValidTaskId(taskId);
|
|
184
|
+
await withTaskEvidenceLock(directory, taskId, agentType, async () => {
|
|
185
|
+
const resolvedEvidenceDir = getEvidenceDir(directory);
|
|
186
|
+
const evidencePath = path.join(resolvedEvidenceDir, `${taskId}.json`);
|
|
187
|
+
let existing = null;
|
|
188
|
+
try {
|
|
189
|
+
existing = readExisting(evidencePath, taskId);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
telemetry.gateParseError(taskId, error);
|
|
192
|
+
throw error;
|
|
193
|
+
}
|
|
194
|
+
const requiredGates = existing ? expandRequiredGates(existing.required_gates, agentType) : deriveRequiredGates(agentType);
|
|
195
|
+
const updated = {
|
|
196
|
+
taskId,
|
|
197
|
+
required_gates: requiredGates,
|
|
198
|
+
turbo: turbo === true ? true : existing?.turbo,
|
|
199
|
+
gates: existing?.gates ?? {}
|
|
200
|
+
};
|
|
201
|
+
await atomicWriteFile(evidencePath, JSON.stringify(updated, null, 2));
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
async function readTaskEvidence(directory, taskId) {
|
|
205
|
+
try {
|
|
206
|
+
assertValidTaskId(taskId);
|
|
207
|
+
return readExisting(getEvidencePath(directory, taskId), taskId);
|
|
208
|
+
} catch {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function readTaskEvidenceRaw(directory, taskId) {
|
|
213
|
+
assertValidTaskId(taskId);
|
|
214
|
+
const evidencePath = getEvidencePath(directory, taskId);
|
|
215
|
+
try {
|
|
216
|
+
const raw = readFileSync(evidencePath, "utf-8");
|
|
217
|
+
return TaskEvidenceSchema.parse(JSON.parse(raw));
|
|
218
|
+
} catch (error) {
|
|
219
|
+
if (error.code === "ENOENT")
|
|
220
|
+
return null;
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async function hasPassedAllGates(directory, taskId) {
|
|
225
|
+
const evidence = await readTaskEvidence(directory, taskId);
|
|
226
|
+
if (!evidence)
|
|
227
|
+
return false;
|
|
228
|
+
if (!Array.isArray(evidence.required_gates) || evidence.required_gates.length === 0)
|
|
229
|
+
return false;
|
|
230
|
+
return evidence.required_gates.every((gate) => evidence.gates[gate] != null);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export { sanitizeTaskId, DEFAULT_REQUIRED_GATES, isValidTaskId, deriveRequiredGates, expandRequiredGates, recordGateEvidence, recordAgentDispatch, readTaskEvidence, readTaskEvidenceRaw, hasPassedAllGates };
|