opencode-swarm 7.121.4 → 7.122.1
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/{config-doctor-404c8mf8.js → config-doctor-3ksh1534.js} +2 -2
- package/dist/cli/{core-xnwasfpc.js → core-cwgb7ev8.js} +1 -1
- package/dist/cli/{curation-policy-10wnhpwn.js → curation-policy-4j4qce5a.js} +5 -5
- package/dist/cli/{curator-llm-factory-6rafny5e.js → curator-llm-factory-x769hn66.js} +22 -20
- package/dist/cli/{curator-3azybqrw.js → curator-qfh07497.js} +22 -20
- package/dist/cli/{evidence-summary-service-k14ykm03.js → evidence-summary-service-96ndczbk.js} +7 -5
- package/dist/cli/{gate-evidence-tbpezk28.js → gate-evidence-xqks3kk2.js} +3 -3
- package/dist/cli/{guardrail-explain-d1m747g5.js → guardrail-explain-kj0e9r25.js} +23 -21
- package/dist/cli/{guardrail-log-dhpp0kmn.js → guardrail-log-z291m4gw.js} +3 -3
- package/dist/cli/{hive-promoter-4xnj3fdk.js → hive-promoter-00mktxkk.js} +22 -20
- package/dist/cli/{index-zvae4m8g.js → index-17eybc3z.js} +1 -1
- package/dist/cli/{index-kyvg2cmp.js → index-19zn67q6.js} +1 -1
- package/dist/cli/{index-rbfq77sz.js → index-2j25br0p.js} +12 -10
- package/dist/cli/{index-9xpgytj9.js → index-3rr0ese8.js} +1 -1
- package/dist/cli/{index-x4fwtd59.js → index-5he0kwnx.js} +3 -3
- package/dist/cli/{index-982hhpcm.js → index-6srk9a5q.js} +2 -2
- package/dist/cli/{index-qg11yf8q.js → index-6xnxz6z0.js} +1 -1
- package/dist/cli/{index-emkb0bbe.js → index-7cspygmb.js} +277 -673
- package/dist/cli/{index-5a3xsnzg.js → index-cqsak7bf.js} +2 -2
- package/dist/cli/index-ctpgsj84.js +547 -0
- package/dist/cli/index-d6h5hq91.js +564 -0
- package/dist/cli/{index-vqcgmy4y.js → index-det5jwfk.js} +1 -1
- package/dist/cli/{index-35xyj7gn.js → index-dywekeen.js} +28 -5
- package/dist/cli/{index-wtn8wf7h.js → index-gw3m5fw0.js} +1 -1
- package/dist/cli/{index-j8349ac0.js → index-hns7xjm7.js} +2 -2
- package/dist/cli/{index-ft6jw816.js → index-j9kxwshw.js} +5 -5
- package/dist/cli/{index-2k6z335c.js → index-jm81nhks.js} +24 -22
- package/dist/cli/{index-q0fv0xec.js → index-kanrv3sv.js} +280 -119
- package/dist/cli/{index-db82jxt7.js → index-m0bmh3w0.js} +4 -4
- package/dist/cli/index-m1abzg93.js +68 -0
- package/dist/cli/{index-0f800qg7.js → index-n2712byd.js} +6 -6
- package/dist/cli/{index-3jvqw5hy.js → index-q27bajqb.js} +1 -1
- package/dist/cli/{index-qt2yaghg.js → index-vcgfqd8f.js} +1 -63
- package/dist/cli/{index-tftv9xh9.js → index-wr8qgpz5.js} +1 -1
- package/dist/cli/index.js +22 -20
- package/dist/cli/{knowledge-escalator-8ajq1fhb.js → knowledge-escalator-dyxsm78k.js} +6 -6
- package/dist/cli/{knowledge-events-2sjy3aa7.js → knowledge-events-36q6nvae.js} +6 -4
- package/dist/cli/{knowledge-link-sy85fw3w.js → knowledge-link-4yd2z8ev.js} +3 -3
- package/dist/cli/{knowledge-store-27cesthc.js → knowledge-store-e07b4s54.js} +4 -4
- package/dist/cli/{knowledge-validator-9keh3p8j.js → knowledge-validator-sfyf7wn2.js} +7 -7
- package/dist/cli/pr-subscriptions-x653151h.js +1 -1
- package/dist/cli/{scan-cursor-qmsmmg1b.js → scan-cursor-hm0aqqae.js} +5 -5
- package/dist/cli/{schema-vwxpsk6j.js → schema-13bnng2n.js} +1 -1
- package/dist/cli/scope-persistence-d9erwnvb.js +36 -0
- package/dist/cli/{skill-generator-hkyxdc3j.js → skill-generator-g6r52x94.js} +8 -8
- package/dist/config/constants.d.ts +3 -2
- package/dist/hooks/cohort-cache.d.ts +44 -0
- package/dist/hooks/delegation-gate.d.ts +19 -1
- package/dist/hooks/guardrails/nontransient-circuit.d.ts +47 -0
- package/dist/hooks/hive-promoter.d.ts +4 -3
- package/dist/hooks/host-boundary.d.ts +147 -0
- package/dist/hooks/incremental-verify.d.ts +3 -0
- package/dist/hooks/knowledge-events.d.ts +25 -2
- package/dist/hooks/knowledge-injector.d.ts +9 -1
- package/dist/hooks/knowledge-receipt-validator.d.ts +98 -0
- package/dist/hooks/micro-reflector.d.ts +3 -0
- package/dist/hooks/pr-auto-subscribe.d.ts +3 -0
- package/dist/hooks/promotion-evidence-store.d.ts +33 -0
- package/dist/hooks/scope-guard.d.ts +9 -2
- package/dist/hooks/write-target-resolver.d.ts +30 -0
- package/dist/index.js +423 -380
- package/dist/sandbox/win32/restricted-environment-executor.d.ts +3 -2
- package/dist/scope/scope-binding.d.ts +89 -0
- package/dist/scope/scope-persistence.d.ts +53 -12
- package/dist/services/knowledge-diagnostics.d.ts +12 -0
- package/dist/session/snapshot-writer.d.ts +5 -0
- package/dist/state.d.ts +36 -1
- package/dist/tools/declare-scope.d.ts +5 -1
- package/dist/tools/file-extractor-planner.d.ts +31 -0
- package/dist/tools/file-extractor.d.ts +2 -7
- package/package.json +1 -1
- package/dist/cli/index-51gg9947.js +0 -254
- package/dist/cli/scope-persistence-mfr36yc9.js +0 -20
- package/dist/cli/{index-h07wn84h.js → index-7mkpsw6g.js} +3 -3
- package/dist/cli/{pending-delegations-0z3znsec.js → pending-delegations-68cbaqv2.js} +1 -1
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
computePlanStructureHash,
|
|
4
|
+
derivePlanId
|
|
5
|
+
} from "./index-ctpgsj84.js";
|
|
6
|
+
import {
|
|
7
|
+
PlanSchema
|
|
8
|
+
} from "./index-m1abzg93.js";
|
|
9
|
+
import {
|
|
10
|
+
require_proper_lockfile
|
|
11
|
+
} from "./index-7g4c7s5r.js";
|
|
12
|
+
import {
|
|
13
|
+
bunWrite
|
|
14
|
+
} from "./index-qe3v54nb.js";
|
|
15
|
+
import {
|
|
16
|
+
__toESM
|
|
17
|
+
} from "./index-a76rekgs.js";
|
|
18
|
+
|
|
19
|
+
// src/scope/scope-persistence.ts
|
|
20
|
+
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
21
|
+
import { createHash } from "crypto";
|
|
22
|
+
import * as fs2 from "fs";
|
|
23
|
+
import * as path2 from "path";
|
|
24
|
+
|
|
25
|
+
// src/scope/scope-binding.ts
|
|
26
|
+
import * as fs from "fs";
|
|
27
|
+
import * as path from "path";
|
|
28
|
+
var MAX_PENDING_SCOPE_BINDINGS = 256;
|
|
29
|
+
var DEFAULT_SCOPE_BINDING_TTL_MS = 60 * 60 * 1000;
|
|
30
|
+
var pendingScopeBindings = new Map;
|
|
31
|
+
function canonicalWorkspaceIdentity(directory) {
|
|
32
|
+
try {
|
|
33
|
+
const real = fs.realpathSync(directory).replace(/\\/g, "/");
|
|
34
|
+
return process.platform === "win32" ? real.toLowerCase() : real;
|
|
35
|
+
} catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function isStrictTaskId(value) {
|
|
40
|
+
return /^\d+\.\d+(?:\.\d+)*$/.test(value);
|
|
41
|
+
}
|
|
42
|
+
function normalizeScopePath(value) {
|
|
43
|
+
if (typeof value !== "string")
|
|
44
|
+
return null;
|
|
45
|
+
const trimmed = value.trim().replace(/\\/g, "/");
|
|
46
|
+
if (trimmed.length === 0 || trimmed.includes("\x00") || path.posix.isAbsolute(trimmed) || /^[A-Za-z]:\//.test(trimmed))
|
|
47
|
+
return null;
|
|
48
|
+
const normalized = path.posix.normalize(trimmed).replace(/^\.\//, "");
|
|
49
|
+
if (normalized === "." || normalized === ".." || normalized.startsWith("../"))
|
|
50
|
+
return null;
|
|
51
|
+
return normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
|
|
52
|
+
}
|
|
53
|
+
function normalizeScopeFiles(files) {
|
|
54
|
+
if (!Array.isArray(files) || files.length === 0 || files.length > 1e4)
|
|
55
|
+
return null;
|
|
56
|
+
const normalized = new Set;
|
|
57
|
+
for (const file of files) {
|
|
58
|
+
const candidate = normalizeScopePath(file);
|
|
59
|
+
if (!candidate)
|
|
60
|
+
return null;
|
|
61
|
+
normalized.add(candidate);
|
|
62
|
+
}
|
|
63
|
+
return normalized.size > 0 ? [...normalized].sort() : null;
|
|
64
|
+
}
|
|
65
|
+
function bindingKey(binding) {
|
|
66
|
+
return [
|
|
67
|
+
binding.workspaceIdentity,
|
|
68
|
+
binding.planStructureHash,
|
|
69
|
+
binding.taskId,
|
|
70
|
+
binding.ownerSessionId,
|
|
71
|
+
binding.ownerMessageId ?? ""
|
|
72
|
+
].join("\x00");
|
|
73
|
+
}
|
|
74
|
+
function sweepExpired(now = Date.now()) {
|
|
75
|
+
for (const [key, binding] of pendingScopeBindings) {
|
|
76
|
+
if (binding.expiresAt <= now)
|
|
77
|
+
pendingScopeBindings.delete(key);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function registerScopeBinding(binding) {
|
|
81
|
+
sweepExpired();
|
|
82
|
+
if (binding.activation === "declaration" && binding.dispatchCallId === undefined) {
|
|
83
|
+
for (const [existingKey, existing] of pendingScopeBindings) {
|
|
84
|
+
if (existing.activation === "declaration" && existing.dispatchCallId === undefined && existing.workspaceIdentity === binding.workspaceIdentity && existing.taskId === binding.taskId && existing.ownerSessionId === binding.ownerSessionId)
|
|
85
|
+
pendingScopeBindings.delete(existingKey);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const key = bindingKey(binding);
|
|
89
|
+
pendingScopeBindings.delete(key);
|
|
90
|
+
pendingScopeBindings.set(key, binding);
|
|
91
|
+
while (pendingScopeBindings.size > MAX_PENDING_SCOPE_BINDINGS) {
|
|
92
|
+
const oldest = pendingScopeBindings.keys().next().value;
|
|
93
|
+
if (!oldest)
|
|
94
|
+
break;
|
|
95
|
+
pendingScopeBindings.delete(oldest);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function getAuthorizedScopeBinding(input) {
|
|
99
|
+
return getAuthorizedScopeBindingByPlanIdentity({
|
|
100
|
+
directory: input.directory,
|
|
101
|
+
planId: derivePlanId(input.plan),
|
|
102
|
+
planStructureHash: computePlanStructureHash(input.plan),
|
|
103
|
+
taskId: input.taskId,
|
|
104
|
+
activeSessionId: input.activeSessionId
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function getAuthorizedScopeBindingByPlanIdentity(input) {
|
|
108
|
+
sweepExpired();
|
|
109
|
+
const workspaceIdentity = canonicalWorkspaceIdentity(input.directory);
|
|
110
|
+
if (!workspaceIdentity || !isStrictTaskId(input.taskId))
|
|
111
|
+
return null;
|
|
112
|
+
const matches = [...pendingScopeBindings.values()].filter((binding) => binding.workspaceIdentity === workspaceIdentity && binding.planId === input.planId && binding.planStructureHash === input.planStructureHash && binding.taskId === input.taskId && binding.ownerSessionId === input.activeSessionId && binding.activation === "active" && typeof binding.dispatchCallId === "string" && binding.dispatchCallId.length > 0 && binding.ownerMessageId === binding.dispatchCallId && typeof binding.parentOwnerSessionId === "string" && binding.parentOwnerSessionId.length > 0 && binding.ownerSessionId !== binding.parentOwnerSessionId && binding.parentCallId === binding.dispatchCallId);
|
|
113
|
+
return matches.length === 1 ? matches[0] : null;
|
|
114
|
+
}
|
|
115
|
+
function clearScopeBindings(predicate) {
|
|
116
|
+
const removed = [];
|
|
117
|
+
if (!predicate) {
|
|
118
|
+
removed.push(...pendingScopeBindings.values());
|
|
119
|
+
pendingScopeBindings.clear();
|
|
120
|
+
return removed;
|
|
121
|
+
}
|
|
122
|
+
for (const [key, binding] of pendingScopeBindings) {
|
|
123
|
+
if (predicate(binding)) {
|
|
124
|
+
removed.push(binding);
|
|
125
|
+
pendingScopeBindings.delete(key);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return removed;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// src/scope/scope-persistence.ts
|
|
132
|
+
var SCOPE_SCHEMA_VERSION = 1;
|
|
133
|
+
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1000;
|
|
134
|
+
var LOCK_STALE_MS = 30 * 1000;
|
|
135
|
+
var SCOPES_DIR = ".swarm/scopes";
|
|
136
|
+
var MAX_FILES_PER_SCOPE = 1e4;
|
|
137
|
+
var MAX_PLAN_BYTES = 10 * 1024 * 1024;
|
|
138
|
+
var MAX_SCOPE_BYTES = 2 * 1024 * 1024;
|
|
139
|
+
var WINDOWS_RESERVED = new Set([
|
|
140
|
+
"CON",
|
|
141
|
+
"PRN",
|
|
142
|
+
"AUX",
|
|
143
|
+
"NUL",
|
|
144
|
+
"COM1",
|
|
145
|
+
"COM2",
|
|
146
|
+
"COM3",
|
|
147
|
+
"COM4",
|
|
148
|
+
"COM5",
|
|
149
|
+
"COM6",
|
|
150
|
+
"COM7",
|
|
151
|
+
"COM8",
|
|
152
|
+
"COM9",
|
|
153
|
+
"LPT1",
|
|
154
|
+
"LPT2",
|
|
155
|
+
"LPT3",
|
|
156
|
+
"LPT4",
|
|
157
|
+
"LPT5",
|
|
158
|
+
"LPT6",
|
|
159
|
+
"LPT7",
|
|
160
|
+
"LPT8",
|
|
161
|
+
"LPT9"
|
|
162
|
+
]);
|
|
163
|
+
function getScopesDir(directory) {
|
|
164
|
+
return path2.join(directory, SCOPES_DIR);
|
|
165
|
+
}
|
|
166
|
+
function normalizePathForComparison(value) {
|
|
167
|
+
const normalized = path2.resolve(value);
|
|
168
|
+
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
169
|
+
}
|
|
170
|
+
function isSafeTaskId(taskId) {
|
|
171
|
+
if (typeof taskId !== "string")
|
|
172
|
+
return false;
|
|
173
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(taskId))
|
|
174
|
+
return false;
|
|
175
|
+
const head = taskId.replace(/\.+$/, "").split(".")[0].toUpperCase();
|
|
176
|
+
if (WINDOWS_RESERVED.has(head))
|
|
177
|
+
return false;
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
function isScopesDirSafe(directory, scopesDir) {
|
|
181
|
+
try {
|
|
182
|
+
const resolvedWorkspace = fs2.realpathSync(directory);
|
|
183
|
+
const expectedSwarmDir = path2.join(resolvedWorkspace, ".swarm");
|
|
184
|
+
const expectedScopesDir = path2.join(expectedSwarmDir, "scopes");
|
|
185
|
+
const swarmStat = fs2.lstatSync(expectedSwarmDir);
|
|
186
|
+
const scopesStat = fs2.lstatSync(expectedScopesDir);
|
|
187
|
+
if (!swarmStat.isDirectory() || swarmStat.isSymbolicLink() || !scopesStat.isDirectory() || scopesStat.isSymbolicLink())
|
|
188
|
+
return false;
|
|
189
|
+
const resolvedScopes = fs2.realpathSync(scopesDir);
|
|
190
|
+
if (normalizePathForComparison(resolvedScopes) !== normalizePathForComparison(expectedScopesDir))
|
|
191
|
+
return false;
|
|
192
|
+
const rel = path2.relative(resolvedWorkspace, resolvedScopes);
|
|
193
|
+
return rel.length > 0 && !rel.startsWith("..") && !path2.isAbsolute(rel);
|
|
194
|
+
} catch {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function resolveSafeScopeFileForUnlink(directory, targetPath) {
|
|
199
|
+
try {
|
|
200
|
+
const resolvedWorkspace = fs2.realpathSync(directory);
|
|
201
|
+
const scopesDir = path2.join(resolvedWorkspace, SCOPES_DIR);
|
|
202
|
+
if (!isScopesDirSafe(resolvedWorkspace, scopesDir))
|
|
203
|
+
return null;
|
|
204
|
+
const candidate = path2.resolve(targetPath);
|
|
205
|
+
const resolvedCandidate = fs2.realpathSync(candidate);
|
|
206
|
+
if (normalizePathForComparison(path2.dirname(candidate)) !== normalizePathForComparison(scopesDir) || normalizePathForComparison(resolvedCandidate) !== normalizePathForComparison(candidate))
|
|
207
|
+
return null;
|
|
208
|
+
const relative2 = path2.relative(resolvedWorkspace, resolvedCandidate);
|
|
209
|
+
if (relative2.length === 0 || relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative2))
|
|
210
|
+
return null;
|
|
211
|
+
const leafStat = fs2.lstatSync(candidate);
|
|
212
|
+
if (!leafStat.isFile() || leafStat.isSymbolicLink())
|
|
213
|
+
return null;
|
|
214
|
+
if (!isScopesDirSafe(resolvedWorkspace, scopesDir))
|
|
215
|
+
return null;
|
|
216
|
+
const finalResolvedCandidate = fs2.realpathSync(candidate);
|
|
217
|
+
const finalLeafStat = fs2.lstatSync(candidate);
|
|
218
|
+
if (normalizePathForComparison(finalResolvedCandidate) !== normalizePathForComparison(candidate) || !finalLeafStat.isFile() || finalLeafStat.isSymbolicLink() || finalLeafStat.dev !== leafStat.dev || finalLeafStat.ino !== leafStat.ino)
|
|
219
|
+
return null;
|
|
220
|
+
return candidate;
|
|
221
|
+
} catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
function getScopeFilePath(directory, taskId) {
|
|
226
|
+
if (!isSafeTaskId(taskId)) {
|
|
227
|
+
throw new Error(`Invalid taskId for scope persistence: ${taskId}`);
|
|
228
|
+
}
|
|
229
|
+
return path2.join(getScopesDir(directory), `scope-${taskId}.json`);
|
|
230
|
+
}
|
|
231
|
+
function getBindingFilePath(directory, taskId, ownerSessionId) {
|
|
232
|
+
if (!isSafeTaskId(taskId) || !ownerSessionId.trim()) {
|
|
233
|
+
throw new Error("Invalid identity for scope binding persistence");
|
|
234
|
+
}
|
|
235
|
+
const ownerHash = createHash("sha256").update(ownerSessionId).digest("hex").slice(0, 24);
|
|
236
|
+
return path2.join(getScopesDir(directory), `binding-${taskId}-${ownerHash}.json`);
|
|
237
|
+
}
|
|
238
|
+
async function writeScopeToDisk(directory, taskId, files, ttlMs = DEFAULT_TTL_MS) {
|
|
239
|
+
if (!isSafeTaskId(taskId))
|
|
240
|
+
return;
|
|
241
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
242
|
+
return;
|
|
243
|
+
if (files.length > MAX_FILES_PER_SCOPE)
|
|
244
|
+
return;
|
|
245
|
+
const scopesDir = getScopesDir(directory);
|
|
246
|
+
const scopePath = getScopeFilePath(directory, taskId);
|
|
247
|
+
try {
|
|
248
|
+
fs2.mkdirSync(scopesDir, { recursive: true });
|
|
249
|
+
} catch {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
if (!isScopesDirSafe(directory, scopesDir))
|
|
253
|
+
return;
|
|
254
|
+
const now = Date.now();
|
|
255
|
+
const payload = {
|
|
256
|
+
version: SCOPE_SCHEMA_VERSION,
|
|
257
|
+
taskId,
|
|
258
|
+
declaredAt: now,
|
|
259
|
+
expiresAt: now + ttlMs,
|
|
260
|
+
files: [...files]
|
|
261
|
+
};
|
|
262
|
+
const content = JSON.stringify(payload, null, 2);
|
|
263
|
+
try {
|
|
264
|
+
const flags = fs2.constants.O_WRONLY | fs2.constants.O_CREAT;
|
|
265
|
+
const nofollow = fs2.constants.O_NOFOLLOW ?? 0;
|
|
266
|
+
const fd = fs2.openSync(scopePath, flags | nofollow);
|
|
267
|
+
fs2.closeSync(fd);
|
|
268
|
+
} catch {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
let release;
|
|
272
|
+
try {
|
|
273
|
+
release = await import_proper_lockfile.default.lock(scopePath, {
|
|
274
|
+
stale: LOCK_STALE_MS,
|
|
275
|
+
retries: { retries: 3, minTimeout: 50, maxTimeout: 200 },
|
|
276
|
+
realpath: false
|
|
277
|
+
});
|
|
278
|
+
await atomicWrite(scopePath, content);
|
|
279
|
+
} catch {} finally {
|
|
280
|
+
if (release) {
|
|
281
|
+
try {
|
|
282
|
+
await release();
|
|
283
|
+
} catch {}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
async function writeScopeBindingToDisk(directory, binding) {
|
|
288
|
+
if (!isSafeTaskId(binding.taskId) || binding.version !== 2)
|
|
289
|
+
return;
|
|
290
|
+
const workspaceIdentity = canonicalWorkspaceIdentity(directory);
|
|
291
|
+
const files = normalizeScopeFiles(binding.files);
|
|
292
|
+
if (!workspaceIdentity || workspaceIdentity !== binding.workspaceIdentity || !files || !binding.ownerSessionId || !binding.ownerMessageId || binding.expiresAt <= Date.now())
|
|
293
|
+
return;
|
|
294
|
+
const scopesDir = getScopesDir(directory);
|
|
295
|
+
const scopePath = getBindingFilePath(directory, binding.taskId, binding.ownerSessionId);
|
|
296
|
+
try {
|
|
297
|
+
fs2.mkdirSync(scopesDir, { recursive: true });
|
|
298
|
+
} catch {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (!isScopesDirSafe(directory, scopesDir))
|
|
302
|
+
return;
|
|
303
|
+
const content = JSON.stringify({ ...binding, files }, null, 2);
|
|
304
|
+
try {
|
|
305
|
+
const flags = fs2.constants.O_WRONLY | fs2.constants.O_CREAT;
|
|
306
|
+
const nofollow = fs2.constants.O_NOFOLLOW ?? 0;
|
|
307
|
+
const fd = fs2.openSync(scopePath, flags | nofollow);
|
|
308
|
+
fs2.closeSync(fd);
|
|
309
|
+
} catch {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
let release;
|
|
313
|
+
try {
|
|
314
|
+
release = await import_proper_lockfile.default.lock(scopePath, {
|
|
315
|
+
stale: LOCK_STALE_MS,
|
|
316
|
+
retries: { retries: 3, minTimeout: 50, maxTimeout: 200 },
|
|
317
|
+
realpath: false
|
|
318
|
+
});
|
|
319
|
+
await atomicWrite(scopePath, content);
|
|
320
|
+
} catch {} finally {
|
|
321
|
+
if (release) {
|
|
322
|
+
try {
|
|
323
|
+
await release();
|
|
324
|
+
} catch {}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function readScopeBindingFromDisk(input) {
|
|
329
|
+
if (!isSafeTaskId(input.taskId))
|
|
330
|
+
return null;
|
|
331
|
+
const scopesDir = getScopesDir(input.directory);
|
|
332
|
+
if (!isScopesDirSafe(input.directory, scopesDir))
|
|
333
|
+
return null;
|
|
334
|
+
let scopePath;
|
|
335
|
+
try {
|
|
336
|
+
scopePath = getBindingFilePath(input.directory, input.taskId, input.ownerSessionId);
|
|
337
|
+
} catch {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
const nofollow = fs2.constants.O_NOFOLLOW ?? 0;
|
|
341
|
+
let fd;
|
|
342
|
+
try {
|
|
343
|
+
fd = fs2.openSync(scopePath, fs2.constants.O_RDONLY | nofollow);
|
|
344
|
+
} catch {
|
|
345
|
+
return null;
|
|
346
|
+
}
|
|
347
|
+
let raw = "";
|
|
348
|
+
try {
|
|
349
|
+
const stat = fs2.fstatSync(fd);
|
|
350
|
+
if (!stat.isFile() || stat.size > MAX_SCOPE_BYTES)
|
|
351
|
+
return null;
|
|
352
|
+
const buffer = Buffer.alloc(stat.size);
|
|
353
|
+
fs2.readSync(fd, buffer, 0, stat.size, 0);
|
|
354
|
+
raw = buffer.toString("utf8");
|
|
355
|
+
} catch {
|
|
356
|
+
return null;
|
|
357
|
+
} finally {
|
|
358
|
+
try {
|
|
359
|
+
fs2.closeSync(fd);
|
|
360
|
+
} catch {}
|
|
361
|
+
}
|
|
362
|
+
let parsed;
|
|
363
|
+
try {
|
|
364
|
+
parsed = JSON.parse(raw);
|
|
365
|
+
} catch {
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
368
|
+
const now = Date.now();
|
|
369
|
+
const workspaceIdentity = canonicalWorkspaceIdentity(input.directory);
|
|
370
|
+
const files = Array.isArray(parsed.files) ? normalizeScopeFiles(parsed.files.filter((file) => typeof file === "string")) : null;
|
|
371
|
+
if (parsed.version !== 2 || parsed.taskId !== input.taskId || !workspaceIdentity || parsed.workspaceIdentity !== workspaceIdentity || parsed.planId !== derivePlanId(input.plan) || parsed.planStructureHash !== computePlanStructureHash(input.plan) || typeof parsed.declaredAt !== "number" || parsed.declaredAt > now || typeof parsed.expiresAt !== "number" || parsed.expiresAt <= now || !parsed.ownerSessionId || !parsed.ownerMessageId || !parsed.source || !files || parsed.ownerSessionId !== input.ownerSessionId || input.requireDispatchCorrelation === true && (typeof parsed.dispatchCallId !== "string" || parsed.dispatchCallId.length === 0 || parsed.activation !== "active" || parsed.ownerMessageId !== parsed.dispatchCallId || typeof parsed.parentOwnerSessionId !== "string" || parsed.parentOwnerSessionId.length === 0 || parsed.ownerSessionId === parsed.parentOwnerSessionId || parsed.parentCallId !== parsed.dispatchCallId) || input.requireDeclaration === true && (parsed.activation !== "declaration" || parsed.dispatchCallId !== undefined) || input.parentCallId !== undefined && parsed.parentCallId !== input.parentCallId)
|
|
372
|
+
return null;
|
|
373
|
+
return { ...parsed, files };
|
|
374
|
+
}
|
|
375
|
+
function clearScopeBindingFromDisk(input) {
|
|
376
|
+
try {
|
|
377
|
+
const resolvedWorkspace = fs2.realpathSync(input.directory);
|
|
378
|
+
const scopePath = getBindingFilePath(resolvedWorkspace, input.taskId, input.ownerSessionId);
|
|
379
|
+
const safePath = resolveSafeScopeFileForUnlink(resolvedWorkspace, scopePath);
|
|
380
|
+
if (!safePath)
|
|
381
|
+
return;
|
|
382
|
+
fs2.unlinkSync(safePath);
|
|
383
|
+
} catch {}
|
|
384
|
+
}
|
|
385
|
+
function readCurrentPlan(directory) {
|
|
386
|
+
try {
|
|
387
|
+
const planPath = path2.join(directory, ".swarm", "plan.json");
|
|
388
|
+
const stat = fs2.statSync(planPath);
|
|
389
|
+
if (!stat.isFile() || stat.size > MAX_PLAN_BYTES)
|
|
390
|
+
return null;
|
|
391
|
+
const parsed = PlanSchema.safeParse(JSON.parse(fs2.readFileSync(planPath, "utf8")));
|
|
392
|
+
return parsed.success ? parsed.data : null;
|
|
393
|
+
} catch {
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
function resolveAuthorizedScopeBindingForPlan(input) {
|
|
398
|
+
const inMemory = getAuthorizedScopeBinding(input);
|
|
399
|
+
if (inMemory)
|
|
400
|
+
return inMemory;
|
|
401
|
+
const durable = readScopeBindingFromDisk({
|
|
402
|
+
directory: input.directory,
|
|
403
|
+
taskId: input.taskId,
|
|
404
|
+
plan: input.plan,
|
|
405
|
+
ownerSessionId: input.activeSessionId,
|
|
406
|
+
requireDispatchCorrelation: true
|
|
407
|
+
});
|
|
408
|
+
if (durable)
|
|
409
|
+
registerScopeBinding(durable);
|
|
410
|
+
return durable;
|
|
411
|
+
}
|
|
412
|
+
function resolveAuthorizedScopeBinding(input) {
|
|
413
|
+
const plan = readCurrentPlan(input.directory);
|
|
414
|
+
return plan ? resolveAuthorizedScopeBindingForPlan({ ...input, plan }) : null;
|
|
415
|
+
}
|
|
416
|
+
function resolveAuthorizedScopeBindingForSession(input) {
|
|
417
|
+
const plan = readCurrentPlan(input.directory);
|
|
418
|
+
if (!plan)
|
|
419
|
+
return null;
|
|
420
|
+
const matches = [];
|
|
421
|
+
for (const task of plan.phases.flatMap((phase) => phase.tasks)) {
|
|
422
|
+
const binding = resolveAuthorizedScopeBindingForPlan({
|
|
423
|
+
directory: input.directory,
|
|
424
|
+
plan,
|
|
425
|
+
taskId: task.id,
|
|
426
|
+
activeSessionId: input.activeSessionId
|
|
427
|
+
});
|
|
428
|
+
if (binding)
|
|
429
|
+
matches.push(binding);
|
|
430
|
+
if (matches.length > 1)
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
return matches[0] ?? null;
|
|
434
|
+
}
|
|
435
|
+
async function atomicWrite(targetPath, content) {
|
|
436
|
+
const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
|
|
437
|
+
try {
|
|
438
|
+
await bunWrite(tempPath, content);
|
|
439
|
+
fs2.renameSync(tempPath, targetPath);
|
|
440
|
+
} finally {
|
|
441
|
+
try {
|
|
442
|
+
fs2.unlinkSync(tempPath);
|
|
443
|
+
} catch {}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
function readScopeFromDisk(directory, taskId) {
|
|
447
|
+
if (!isSafeTaskId(taskId))
|
|
448
|
+
return null;
|
|
449
|
+
const scopesDir = getScopesDir(directory);
|
|
450
|
+
if (!isScopesDirSafe(directory, scopesDir))
|
|
451
|
+
return null;
|
|
452
|
+
const scopePath = getScopeFilePath(directory, taskId);
|
|
453
|
+
const nofollow = fs2.constants.O_NOFOLLOW ?? 0;
|
|
454
|
+
let fd;
|
|
455
|
+
try {
|
|
456
|
+
fd = fs2.openSync(scopePath, fs2.constants.O_RDONLY | nofollow);
|
|
457
|
+
} catch {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
let raw;
|
|
461
|
+
try {
|
|
462
|
+
const stat = fs2.fstatSync(fd);
|
|
463
|
+
if (!stat.isFile())
|
|
464
|
+
return null;
|
|
465
|
+
if (stat.size > MAX_SCOPE_BYTES)
|
|
466
|
+
return null;
|
|
467
|
+
const buf = Buffer.alloc(stat.size);
|
|
468
|
+
fs2.readSync(fd, buf, 0, stat.size, 0);
|
|
469
|
+
raw = buf.toString("utf-8");
|
|
470
|
+
} catch {
|
|
471
|
+
return null;
|
|
472
|
+
} finally {
|
|
473
|
+
try {
|
|
474
|
+
fs2.closeSync(fd);
|
|
475
|
+
} catch {}
|
|
476
|
+
}
|
|
477
|
+
if (!raw.trim())
|
|
478
|
+
return null;
|
|
479
|
+
let parsed;
|
|
480
|
+
try {
|
|
481
|
+
parsed = JSON.parse(raw);
|
|
482
|
+
} catch {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
if (parsed.version !== SCOPE_SCHEMA_VERSION)
|
|
486
|
+
return null;
|
|
487
|
+
if (parsed.taskId !== taskId)
|
|
488
|
+
return null;
|
|
489
|
+
const now = Date.now();
|
|
490
|
+
if (typeof parsed.declaredAt !== "number" || parsed.declaredAt > now) {
|
|
491
|
+
return null;
|
|
492
|
+
}
|
|
493
|
+
if (typeof parsed.expiresAt !== "number" || now >= parsed.expiresAt) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
if (!Array.isArray(parsed.files))
|
|
497
|
+
return null;
|
|
498
|
+
if (parsed.files.length > MAX_FILES_PER_SCOPE)
|
|
499
|
+
return null;
|
|
500
|
+
const files = parsed.files.filter((f) => typeof f === "string");
|
|
501
|
+
return files.length > 0 ? files : null;
|
|
502
|
+
}
|
|
503
|
+
function readPlanScope(directory, taskId) {
|
|
504
|
+
if (!isSafeTaskId(taskId))
|
|
505
|
+
return null;
|
|
506
|
+
try {
|
|
507
|
+
const planPath = path2.join(directory, ".swarm", "plan.json");
|
|
508
|
+
const stat = fs2.statSync(planPath);
|
|
509
|
+
if (!stat.isFile())
|
|
510
|
+
return null;
|
|
511
|
+
if (stat.size > MAX_PLAN_BYTES)
|
|
512
|
+
return null;
|
|
513
|
+
const raw = fs2.readFileSync(planPath, "utf-8");
|
|
514
|
+
const plan = JSON.parse(raw);
|
|
515
|
+
for (const phase of plan.phases ?? []) {
|
|
516
|
+
for (const task of phase.tasks ?? []) {
|
|
517
|
+
if (task.id !== taskId)
|
|
518
|
+
continue;
|
|
519
|
+
const ft = task.files_touched;
|
|
520
|
+
if (Array.isArray(ft) && ft.length > 0) {
|
|
521
|
+
if (ft.length > MAX_FILES_PER_SCOPE)
|
|
522
|
+
return null;
|
|
523
|
+
return ft.filter((f) => typeof f === "string");
|
|
524
|
+
}
|
|
525
|
+
if (typeof ft === "string" && ft.length > 0)
|
|
526
|
+
return [ft];
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return null;
|
|
531
|
+
} catch {
|
|
532
|
+
return null;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
function clearScopeForTask(directory, taskId) {
|
|
536
|
+
if (!isSafeTaskId(taskId))
|
|
537
|
+
return;
|
|
538
|
+
try {
|
|
539
|
+
fs2.unlinkSync(getScopeFilePath(directory, taskId));
|
|
540
|
+
} catch {}
|
|
541
|
+
}
|
|
542
|
+
function clearAllScopes(directory) {
|
|
543
|
+
try {
|
|
544
|
+
fs2.rmSync(getScopesDir(directory), { recursive: true, force: true });
|
|
545
|
+
} catch {}
|
|
546
|
+
}
|
|
547
|
+
function resolveScopeWithFallbacks(input) {
|
|
548
|
+
const { directory, taskId, inMemoryScope, pendingMapScope } = input;
|
|
549
|
+
if (inMemoryScope && inMemoryScope.length > 0)
|
|
550
|
+
return inMemoryScope;
|
|
551
|
+
if (taskId) {
|
|
552
|
+
const disk = readScopeFromDisk(directory, taskId);
|
|
553
|
+
if (disk && disk.length > 0)
|
|
554
|
+
return disk;
|
|
555
|
+
const plan = readPlanScope(directory, taskId);
|
|
556
|
+
if (plan && plan.length > 0)
|
|
557
|
+
return plan;
|
|
558
|
+
}
|
|
559
|
+
if (pendingMapScope && pendingMapScope.length > 0)
|
|
560
|
+
return pendingMapScope;
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export { MAX_PENDING_SCOPE_BINDINGS, clearScopeBindings, writeScopeToDisk, writeScopeBindingToDisk, readScopeBindingFromDisk, clearScopeBindingFromDisk, resolveAuthorizedScopeBinding, resolveAuthorizedScopeBindingForSession, readScopeFromDisk, readPlanScope, clearScopeForTask, clearAllScopes, resolveScopeWithFallbacks };
|
|
@@ -4,14 +4,14 @@ import {
|
|
|
4
4
|
} from "./index-ae75rja9.js";
|
|
5
5
|
import {
|
|
6
6
|
resolveKnowledgeStoreDir
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-q27bajqb.js";
|
|
8
8
|
import {
|
|
9
9
|
init_logger,
|
|
10
10
|
warn
|
|
11
11
|
} from "./index-zgwm4ryv.js";
|
|
12
12
|
import {
|
|
13
13
|
atomicWriteFile
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-7mkpsw6g.js";
|
|
15
15
|
import {
|
|
16
16
|
require_proper_lockfile
|
|
17
17
|
} from "./index-7g4c7s5r.js";
|
|
@@ -38,7 +38,8 @@ var RECEIPT_EVENT_TYPES = new Set([
|
|
|
38
38
|
"contradicted",
|
|
39
39
|
"violated",
|
|
40
40
|
"n_a",
|
|
41
|
-
"override"
|
|
41
|
+
"override",
|
|
42
|
+
"no_relevant"
|
|
42
43
|
]);
|
|
43
44
|
function resolveKnowledgeEventsPath(directory) {
|
|
44
45
|
return path.join(resolveKnowledgeStoreDir(directory), "knowledge-events.jsonl");
|
|
@@ -367,32 +368,46 @@ function recomputeCounters(events, legacyRecords = [], baseline = new Map) {
|
|
|
367
368
|
break;
|
|
368
369
|
}
|
|
369
370
|
case "acknowledged": {
|
|
371
|
+
if (!e.knowledge_id)
|
|
372
|
+
break;
|
|
370
373
|
const r = get(map, e.knowledge_id);
|
|
371
374
|
r.acknowledged_count += 1;
|
|
372
375
|
r.last_acknowledged_at = maxIso(r.last_acknowledged_at, e.timestamp);
|
|
373
376
|
break;
|
|
374
377
|
}
|
|
375
378
|
case "applied": {
|
|
379
|
+
if (!e.knowledge_id)
|
|
380
|
+
break;
|
|
376
381
|
const r = get(map, e.knowledge_id);
|
|
377
382
|
r.applied_explicit_count += 1;
|
|
378
383
|
r.last_applied_at = maxIso(r.last_applied_at, e.timestamp);
|
|
379
384
|
break;
|
|
380
385
|
}
|
|
381
386
|
case "ignored":
|
|
387
|
+
if (!e.knowledge_id)
|
|
388
|
+
break;
|
|
382
389
|
get(map, e.knowledge_id).ignored_count += 1;
|
|
383
390
|
break;
|
|
384
391
|
case "violated": {
|
|
392
|
+
if (!e.knowledge_id)
|
|
393
|
+
break;
|
|
385
394
|
const r = get(map, e.knowledge_id);
|
|
386
395
|
r.violated_count += 1;
|
|
387
396
|
r.violation_timestamps.push(e.timestamp);
|
|
388
397
|
break;
|
|
389
398
|
}
|
|
390
399
|
case "contradicted":
|
|
400
|
+
if (!e.knowledge_id)
|
|
401
|
+
break;
|
|
391
402
|
get(map, e.knowledge_id).contradicted_count += 1;
|
|
392
403
|
break;
|
|
393
404
|
case "n_a":
|
|
405
|
+
if (!e.knowledge_id)
|
|
406
|
+
break;
|
|
394
407
|
get(map, e.knowledge_id).n_a_count += 1;
|
|
395
408
|
break;
|
|
409
|
+
case "no_relevant":
|
|
410
|
+
break;
|
|
396
411
|
case "outcome": {
|
|
397
412
|
if (!e.knowledge_id)
|
|
398
413
|
break;
|
|
@@ -446,6 +461,14 @@ function countViolationsInWindow(timestamps, windowDays, now = new Date) {
|
|
|
446
461
|
}
|
|
447
462
|
return count;
|
|
448
463
|
}
|
|
464
|
+
function countEmptyTraceTerminals(events) {
|
|
465
|
+
let n = 0;
|
|
466
|
+
for (const e of events) {
|
|
467
|
+
if (e.type === "no_relevant")
|
|
468
|
+
n += 1;
|
|
469
|
+
}
|
|
470
|
+
return n;
|
|
471
|
+
}
|
|
449
472
|
async function countEntryViolationsInWindow(directory, entryId, windowDays, now = new Date) {
|
|
450
473
|
try {
|
|
451
474
|
const cutoff = now.getTime() - windowDays * 24 * 60 * 60 * 1000;
|
|
@@ -585,7 +608,7 @@ async function applyKnowledgeVerdictFeedback(directory, options) {
|
|
|
585
608
|
deltas.push({ id, delta });
|
|
586
609
|
}
|
|
587
610
|
if (deltas.length > 0) {
|
|
588
|
-
const { bumpKnowledgeConfidenceBatch } = await import("./knowledge-store-
|
|
611
|
+
const { bumpKnowledgeConfidenceBatch } = await import("./knowledge-store-e07b4s54.js");
|
|
589
612
|
await bumpKnowledgeConfidenceBatch(directory, deltas, options?.floorOptions);
|
|
590
613
|
}
|
|
591
614
|
return {
|
|
@@ -620,4 +643,4 @@ var _internals = {
|
|
|
620
643
|
mergeRollupInto
|
|
621
644
|
};
|
|
622
645
|
|
|
623
|
-
export { KNOWLEDGE_EVENT_SCHEMA_VERSION, MAX_EVENT_LOG_ENTRIES, RECEIPT_EVENT_TYPES, resolveKnowledgeEventsPath, resolveKnowledgeCounterBaselinePath, resolveHiveEventsPath2 as resolveHiveEventsPath, resolveLegacyApplicationLogPath, newTraceId, newEventId, appendKnowledgeEvent, recordKnowledgeEvent, appendHiveKnowledgeEvent, recordHiveKnowledgeEvent, readKnowledgeEvents, readHiveKnowledgeEvents, readLegacyApplicationRecords, MAX_VIOLATION_TIMESTAMPS, recomputeCounters, countViolationsInWindow, countEntryViolationsInWindow, countEntryContradictionsInWindow, readKnowledgeCounterRollups, effectiveRetrievalOutcomes, applyKnowledgeVerdictFeedback, _internals };
|
|
646
|
+
export { KNOWLEDGE_EVENT_SCHEMA_VERSION, MAX_EVENT_LOG_ENTRIES, RECEIPT_EVENT_TYPES, resolveKnowledgeEventsPath, resolveKnowledgeCounterBaselinePath, resolveHiveEventsPath2 as resolveHiveEventsPath, resolveLegacyApplicationLogPath, newTraceId, newEventId, appendKnowledgeEvent, recordKnowledgeEvent, appendHiveKnowledgeEvent, recordHiveKnowledgeEvent, readKnowledgeEvents, readHiveKnowledgeEvents, readLegacyApplicationRecords, MAX_VIOLATION_TIMESTAMPS, recomputeCounters, countViolationsInWindow, countEmptyTraceTerminals, countEntryViolationsInWindow, countEntryContradictionsInWindow, readKnowledgeCounterRollups, effectiveRetrievalOutcomes, applyKnowledgeVerdictFeedback, _internals };
|
|
@@ -37,7 +37,7 @@ var _internals = {
|
|
|
37
37
|
symlinkSync: fs.symlinkSync
|
|
38
38
|
},
|
|
39
39
|
writeScopeToDisk: async (directory, taskId, files) => {
|
|
40
|
-
const { writeScopeToDisk: realWrite } = await import("./scope-persistence-
|
|
40
|
+
const { writeScopeToDisk: realWrite } = await import("./scope-persistence-d9erwnvb.js");
|
|
41
41
|
return realWrite(directory, taskId, files);
|
|
42
42
|
},
|
|
43
43
|
writeLaneProfileToDisk: async (_worktreePath, _laneIndex, _envOverrides) => {
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
readKnowledge,
|
|
4
4
|
transactKnowledge
|
|
5
|
-
} from "./index-
|
|
5
|
+
} from "./index-n2712byd.js";
|
|
6
6
|
import {
|
|
7
7
|
resolveKnowledgeStoreDir
|
|
8
|
-
} from "./index-
|
|
8
|
+
} from "./index-q27bajqb.js";
|
|
9
9
|
import {
|
|
10
10
|
isActiveStatus
|
|
11
11
|
} from "./index-4rhcth7a.js";
|