skillwiki 0.10.26 → 0.10.28
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/{chunk-EQPU2BPM.js → chunk-23CR4YPL.js} +6 -8
- package/dist/chunk-5XQWYC5K.js +5255 -0
- package/dist/chunk-NOXDRIHM.js +1194 -0
- package/dist/chunk-OJVIND5D.js +126 -0
- package/dist/{chunk-C2DKFJFA.js → chunk-RQARJ6HB.js} +286 -1
- package/dist/{chunk-QNTBNNEL.js → chunk-SGZPIGGX.js} +12 -14
- package/dist/{chunk-QBZYEEBD.js → chunk-UI4SOWI2.js} +7 -123
- package/dist/{chunk-VXMHHXVP.js → chunk-W7NPTDIU.js} +463 -4745
- package/dist/cli.js +107 -703
- package/dist/{index-projection-FRWTZB5Y.js → index-projection-64WW36N3.js} +3 -3
- package/dist/{managed-write-preflight-4LPVMP42.js → managed-write-preflight-2FU5F56H.js} +5 -3
- package/dist/skillwiki-mcp.js +6 -6
- package/dist/sources-7UC6PJEV.js +9 -0
- package/dist/vault-sync/scripts/lib/platform.sh +264 -0
- package/package.json +1 -1
- package/skills/.claude-plugin/plugin.json +1 -1
- package/skills/.codex-plugin/plugin.json +1 -1
- package/skills/package.json +1 -1
- package/dist/chunk-6ZDKTNLA.js +0 -294
- package/dist/chunk-BASWDOQB.js +0 -455
- package/dist/chunk-PQG26AGJ.js +0 -941
- package/dist/sources-L2SQV63E.js +0 -10
package/dist/chunk-BASWDOQB.js
DELETED
|
@@ -1,455 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
FLEET_REL_PATH,
|
|
4
|
-
findReviewRequiredOp,
|
|
5
|
-
git,
|
|
6
|
-
hasActiveGitSequencer,
|
|
7
|
-
hasUnmergedPaths,
|
|
8
|
-
loadFleetManifestAndHost,
|
|
9
|
-
resolveConfiguredSnapshotWorktree,
|
|
10
|
-
runVaultSyncPullHelper,
|
|
11
|
-
supersedeStaleReviewRequiredJournals
|
|
12
|
-
} from "./chunk-PQG26AGJ.js";
|
|
13
|
-
import {
|
|
14
|
-
ExitCode,
|
|
15
|
-
err,
|
|
16
|
-
ok
|
|
17
|
-
} from "./chunk-C2DKFJFA.js";
|
|
18
|
-
|
|
19
|
-
// src/utils/managed-write-preflight.ts
|
|
20
|
-
import { existsSync as existsSync2 } from "fs";
|
|
21
|
-
import { join as join2, resolve as resolve2 } from "path";
|
|
22
|
-
|
|
23
|
-
// src/utils/managed-write-lock.ts
|
|
24
|
-
import { randomBytes } from "crypto";
|
|
25
|
-
import {
|
|
26
|
-
existsSync,
|
|
27
|
-
mkdirSync,
|
|
28
|
-
readFileSync,
|
|
29
|
-
unlinkSync,
|
|
30
|
-
writeFileSync
|
|
31
|
-
} from "fs";
|
|
32
|
-
import { hostname } from "os";
|
|
33
|
-
import { dirname, join, resolve } from "path";
|
|
34
|
-
function managedWriteLockPath(vault) {
|
|
35
|
-
const gitPath = git(vault, ["rev-parse", "--git-path", "vault-sync/managed-write.lock"]);
|
|
36
|
-
if (gitPath) return gitPath.startsWith("/") ? gitPath : join(vault, gitPath);
|
|
37
|
-
return join(vault, ".skillwiki", "managed-write.lock");
|
|
38
|
-
}
|
|
39
|
-
function readLockRecord(path) {
|
|
40
|
-
try {
|
|
41
|
-
return JSON.parse(readFileSync(path, "utf8"));
|
|
42
|
-
} catch {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
function isManagedWriteLockOwnerAlive(pid) {
|
|
47
|
-
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) return false;
|
|
48
|
-
try {
|
|
49
|
-
process.kill(pid, 0);
|
|
50
|
-
return true;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
if (error.code === "EPERM") return true;
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function hasUnsafeGitState(vault) {
|
|
57
|
-
const gitDirRaw = git(vault, ["rev-parse", "--git-dir"]);
|
|
58
|
-
if (!gitDirRaw) return true;
|
|
59
|
-
const gitDir = gitDirRaw.startsWith("/") ? gitDirRaw : join(vault, gitDirRaw);
|
|
60
|
-
for (const rel of ["rebase-merge", "rebase-apply"]) {
|
|
61
|
-
if (existsSync(join(gitDir, rel))) return true;
|
|
62
|
-
}
|
|
63
|
-
for (const rel of ["MERGE_HEAD", "CHERRY_PICK_HEAD", "REVERT_HEAD"]) {
|
|
64
|
-
if (existsSync(join(gitDir, rel))) return true;
|
|
65
|
-
}
|
|
66
|
-
const unmerged = git(vault, ["ls-files", "-u"]);
|
|
67
|
-
return Boolean(unmerged && unmerged.trim().length > 0);
|
|
68
|
-
}
|
|
69
|
-
function isGitBackedVault(vault) {
|
|
70
|
-
return Boolean(git(vault, ["rev-parse", "--absolute-git-dir"]));
|
|
71
|
-
}
|
|
72
|
-
function hasLocalOwnerProof(vault, record) {
|
|
73
|
-
return isGitBackedVault(vault) || typeof record.owner_hostname === "string" && record.owner_hostname === hostname();
|
|
74
|
-
}
|
|
75
|
-
function reclaimDeadManagedWriteLockOwner(vault, options = {}) {
|
|
76
|
-
const path = managedWriteLockPath(vault);
|
|
77
|
-
const gitStateVault = resolve(options.gitStateVault ?? vault);
|
|
78
|
-
if (!existsSync(path)) return ok({ reclaimed: false });
|
|
79
|
-
const record = readLockRecord(path);
|
|
80
|
-
if (!record) {
|
|
81
|
-
return err("SYNC_LOCK_HELD", { path, message: "managed-write lock unreadable" });
|
|
82
|
-
}
|
|
83
|
-
if (!hasLocalOwnerProof(vault, record)) {
|
|
84
|
-
return err("SYNC_LOCK_HELD", {
|
|
85
|
-
path,
|
|
86
|
-
owner_hostname: record.owner_hostname,
|
|
87
|
-
current_hostname: hostname(),
|
|
88
|
-
message: "managed-write lock origin is foreign or unknown"
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
if (isManagedWriteLockOwnerAlive(record.pid)) {
|
|
92
|
-
return err("SYNC_LOCK_HELD", { path, message: "managed-write lock owner is alive" });
|
|
93
|
-
}
|
|
94
|
-
if (hasUnsafeGitState(gitStateVault)) {
|
|
95
|
-
return err("SYNC_LOCK_HELD", {
|
|
96
|
-
path,
|
|
97
|
-
git_state_vault: gitStateVault,
|
|
98
|
-
message: "managed-write lock not reclaimed: unsafe git state"
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
try {
|
|
102
|
-
const recoveryDir = join(dirname(path), "recovery");
|
|
103
|
-
mkdirSync(recoveryDir, { recursive: true });
|
|
104
|
-
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
|
|
105
|
-
const recoveryPath = join(recoveryDir, `stale-managed-write-lock-${stamp}-${process.pid}.json`);
|
|
106
|
-
const meta = {
|
|
107
|
-
recovered_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
108
|
-
recovery_reason: "owner_pid_dead",
|
|
109
|
-
owner_pid_alive: false,
|
|
110
|
-
git_state_vault: gitStateVault,
|
|
111
|
-
lock: record
|
|
112
|
-
};
|
|
113
|
-
writeFileSync(recoveryPath, `${JSON.stringify(meta, null, 2)}
|
|
114
|
-
`, { flag: "wx" });
|
|
115
|
-
unlinkSync(path);
|
|
116
|
-
return ok({ reclaimed: true, recoveryPath });
|
|
117
|
-
} catch (error) {
|
|
118
|
-
return err("WRITE_FAILED", { path, message: String(error) });
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function tryCreateLock(path, command) {
|
|
122
|
-
const ownerToken = randomBytes(16).toString("hex");
|
|
123
|
-
const acquired = (/* @__PURE__ */ new Date()).toISOString();
|
|
124
|
-
try {
|
|
125
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
126
|
-
writeFileSync(
|
|
127
|
-
path,
|
|
128
|
-
`${JSON.stringify({
|
|
129
|
-
pid: process.pid,
|
|
130
|
-
owner_hostname: hostname(),
|
|
131
|
-
owner_token: ownerToken,
|
|
132
|
-
acquired,
|
|
133
|
-
command
|
|
134
|
-
})}
|
|
135
|
-
`,
|
|
136
|
-
{ flag: "wx" }
|
|
137
|
-
);
|
|
138
|
-
return ok({ vault: "", path, ownerToken, acquired });
|
|
139
|
-
} catch (error) {
|
|
140
|
-
if (error.code === "EEXIST") return err("SYNC_LOCK_HELD", { path });
|
|
141
|
-
return err("WRITE_FAILED", { path, message: String(error) });
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
function acquireManagedWriteLock(vault, command, options = {}) {
|
|
145
|
-
const path = managedWriteLockPath(vault);
|
|
146
|
-
const first = tryCreateLock(path, command);
|
|
147
|
-
if (first.ok) {
|
|
148
|
-
return ok({ ...first.data, vault });
|
|
149
|
-
}
|
|
150
|
-
if (first.error !== "SYNC_LOCK_HELD") return first;
|
|
151
|
-
const reclaimed = reclaimDeadManagedWriteLockOwner(vault, options);
|
|
152
|
-
if (!reclaimed.ok || !reclaimed.data.reclaimed) {
|
|
153
|
-
return err("SYNC_LOCK_HELD", { path });
|
|
154
|
-
}
|
|
155
|
-
const second = tryCreateLock(path, command);
|
|
156
|
-
if (second.ok) return ok({ ...second.data, vault });
|
|
157
|
-
return second.ok === false ? second : err("SYNC_LOCK_HELD", { path });
|
|
158
|
-
}
|
|
159
|
-
function releaseManagedWriteLock(handle) {
|
|
160
|
-
try {
|
|
161
|
-
const parsed = JSON.parse(readFileSync(handle.path, "utf8"));
|
|
162
|
-
if (parsed.owner_token !== handle.ownerToken || parsed.acquired !== handle.acquired) {
|
|
163
|
-
return err("SYNC_LOCK_HELD", {
|
|
164
|
-
path: handle.path,
|
|
165
|
-
message: "managed-write lock ownership changed"
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
unlinkSync(handle.path);
|
|
169
|
-
return ok({ released: true });
|
|
170
|
-
} catch (error) {
|
|
171
|
-
return err("WRITE_FAILED", { path: handle.path, message: String(error) });
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// src/utils/managed-write-preflight.ts
|
|
176
|
-
var DEFAULT_DEPS = {
|
|
177
|
-
converge: (input) => runVaultSyncPullHelper(input),
|
|
178
|
-
resolveConfiguredSnapshotWorktree
|
|
179
|
-
};
|
|
180
|
-
function preflightBlocker(vault) {
|
|
181
|
-
const unmerged = hasUnmergedPaths(vault);
|
|
182
|
-
if (unmerged.length > 0) {
|
|
183
|
-
return {
|
|
184
|
-
reason: "unmerged-paths",
|
|
185
|
-
operation_id: findReviewRequiredOp(vault),
|
|
186
|
-
unmerged_paths: unmerged
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
if (hasActiveGitSequencer(vault)) {
|
|
190
|
-
return { reason: "git-operation-in-progress" };
|
|
191
|
-
}
|
|
192
|
-
supersedeStaleReviewRequiredJournals(vault, {
|
|
193
|
-
by: "skillwiki-managed-write-preflight",
|
|
194
|
-
requireClean: false
|
|
195
|
-
});
|
|
196
|
-
const op = findReviewRequiredOp(vault);
|
|
197
|
-
if (op) return { reason: "review-required", operation_id: op };
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
function hasFleetManifest(vault) {
|
|
201
|
-
return existsSync2(join2(vault, FLEET_REL_PATH));
|
|
202
|
-
}
|
|
203
|
-
function isGitVault(vault) {
|
|
204
|
-
return Boolean(git(vault, ["rev-parse", "--absolute-git-dir"]));
|
|
205
|
-
}
|
|
206
|
-
async function runManagedWritePreflight(input, deps = DEFAULT_DEPS) {
|
|
207
|
-
const mutationVault = resolve2(input.vault);
|
|
208
|
-
let convergenceVault = input.convergenceVault && resolve2(input.convergenceVault) !== mutationVault ? resolve2(input.convergenceVault) : void 0;
|
|
209
|
-
let convergenceSource = convergenceVault ? "explicit" : "single-path";
|
|
210
|
-
const mutationBlocker = preflightBlocker(mutationVault);
|
|
211
|
-
if (mutationBlocker) {
|
|
212
|
-
return {
|
|
213
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
214
|
-
result: err("PREFLIGHT_FAILED", {
|
|
215
|
-
reason: mutationBlocker.reason,
|
|
216
|
-
operation_id: mutationBlocker.operation_id,
|
|
217
|
-
unmerged_paths: mutationBlocker.unmerged_paths
|
|
218
|
-
})
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
const fleet = await loadFleetManifestAndHost({
|
|
222
|
-
vault: mutationVault,
|
|
223
|
-
hostId: input.hostId,
|
|
224
|
-
env: input.env,
|
|
225
|
-
home: input.home,
|
|
226
|
-
cwd: input.cwd,
|
|
227
|
-
osHostname: input.osHostname,
|
|
228
|
-
user: input.user
|
|
229
|
-
});
|
|
230
|
-
if (!fleet) {
|
|
231
|
-
const gitVault2 = isGitVault(mutationVault) ? mutationVault : null;
|
|
232
|
-
const head = gitVault2 ? git(gitVault2, ["rev-parse", "HEAD"]) || null : null;
|
|
233
|
-
return {
|
|
234
|
-
exitCode: ExitCode.OK,
|
|
235
|
-
result: ok({
|
|
236
|
-
mode: "standalone",
|
|
237
|
-
mutation_vault: mutationVault,
|
|
238
|
-
git_vault: gitVault2,
|
|
239
|
-
base_oid: head,
|
|
240
|
-
converged: false,
|
|
241
|
-
convergence_source: "single-path"
|
|
242
|
-
})
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
if (fleet.identityStatus === "unknown" || fleet.identityStatus === "invalid" || !fleet.hostId) {
|
|
246
|
-
return {
|
|
247
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
248
|
-
result: err("PREFLIGHT_FAILED", {
|
|
249
|
-
reason: "fleet-identity-unresolved",
|
|
250
|
-
identity_status: fleet.identityStatus,
|
|
251
|
-
host_id: fleet.hostId
|
|
252
|
-
})
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
const host = fleet.manifest.hosts[fleet.hostId];
|
|
256
|
-
if (!host) {
|
|
257
|
-
return {
|
|
258
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
259
|
-
result: err("PREFLIGHT_FAILED", { reason: "fleet-host-missing", host_id: fleet.hostId })
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
const writesGithub = host.writes_to.includes("github");
|
|
263
|
-
if (!writesGithub) {
|
|
264
|
-
return {
|
|
265
|
-
exitCode: ExitCode.OK,
|
|
266
|
-
result: ok({
|
|
267
|
-
mode: "immutable-record",
|
|
268
|
-
host_id: fleet.hostId,
|
|
269
|
-
mutation_vault: mutationVault,
|
|
270
|
-
git_vault: null,
|
|
271
|
-
base_oid: null,
|
|
272
|
-
converged: false,
|
|
273
|
-
...convergenceVault ? { convergence_vault: convergenceVault } : {},
|
|
274
|
-
convergence_source: convergenceSource
|
|
275
|
-
})
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
if (!convergenceVault && host.role === "snapshotter" && host.protected === true) {
|
|
279
|
-
const home = input.home ?? input.env?.HOME ?? process.env.HOME ?? "";
|
|
280
|
-
const configured = (deps.resolveConfiguredSnapshotWorktree ?? resolveConfiguredSnapshotWorktree)(home);
|
|
281
|
-
if (!configured) {
|
|
282
|
-
return {
|
|
283
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
284
|
-
result: err("PREFLIGHT_FAILED", {
|
|
285
|
-
reason: "convergence-vault-not-configured",
|
|
286
|
-
host_id: fleet.hostId,
|
|
287
|
-
mutation_vault: mutationVault
|
|
288
|
-
})
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
convergenceVault = resolve2(configured);
|
|
292
|
-
convergenceSource = "configured";
|
|
293
|
-
if (convergenceVault === mutationVault) {
|
|
294
|
-
return {
|
|
295
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
296
|
-
result: err("PREFLIGHT_FAILED", {
|
|
297
|
-
reason: "convergence-vault-not-distinct",
|
|
298
|
-
host_id: fleet.hostId,
|
|
299
|
-
mutation_vault: mutationVault,
|
|
300
|
-
convergence_vault: convergenceVault
|
|
301
|
-
})
|
|
302
|
-
};
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
const gitVault = convergenceVault ?? mutationVault;
|
|
306
|
-
if (convergenceVault) {
|
|
307
|
-
if (!isGitVault(convergenceVault)) {
|
|
308
|
-
return {
|
|
309
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
310
|
-
result: err("PREFLIGHT_FAILED", {
|
|
311
|
-
reason: "convergence-vault-not-git",
|
|
312
|
-
convergence_vault: convergenceVault
|
|
313
|
-
})
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
const convergenceHasFleet = hasFleetManifest(convergenceVault);
|
|
317
|
-
if (convergenceSource === "configured" && !convergenceHasFleet) {
|
|
318
|
-
return {
|
|
319
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
320
|
-
result: err("PREFLIGHT_FAILED", {
|
|
321
|
-
reason: "convergence-vault-fleet-missing",
|
|
322
|
-
host_id: fleet.hostId,
|
|
323
|
-
convergence_vault: convergenceVault
|
|
324
|
-
})
|
|
325
|
-
};
|
|
326
|
-
}
|
|
327
|
-
const gitBlocker = preflightBlocker(convergenceVault);
|
|
328
|
-
if (gitBlocker) {
|
|
329
|
-
return {
|
|
330
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
331
|
-
result: err("PREFLIGHT_FAILED", {
|
|
332
|
-
reason: gitBlocker.reason,
|
|
333
|
-
operation_id: gitBlocker.operation_id,
|
|
334
|
-
unmerged_paths: gitBlocker.unmerged_paths,
|
|
335
|
-
convergence_vault: convergenceVault
|
|
336
|
-
})
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
if (convergenceVault && hasFleetManifest(convergenceVault)) {
|
|
341
|
-
const convergeFleetCtx = await loadFleetManifestAndHost({
|
|
342
|
-
vault: convergenceVault,
|
|
343
|
-
hostId: input.hostId ?? fleet.hostId,
|
|
344
|
-
env: input.env,
|
|
345
|
-
home: input.home,
|
|
346
|
-
cwd: input.cwd,
|
|
347
|
-
osHostname: input.osHostname,
|
|
348
|
-
user: input.user
|
|
349
|
-
});
|
|
350
|
-
if (!convergeFleetCtx || convergeFleetCtx.identityStatus !== "known" || convergeFleetCtx.hostId !== fleet.hostId) {
|
|
351
|
-
return {
|
|
352
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
353
|
-
result: err("PREFLIGHT_FAILED", {
|
|
354
|
-
reason: "convergence-vault-identity-mismatch",
|
|
355
|
-
host_id: fleet.hostId,
|
|
356
|
-
convergence_host_id: convergeFleetCtx?.hostId,
|
|
357
|
-
convergence_identity_status: convergeFleetCtx?.identityStatus,
|
|
358
|
-
convergence_vault: convergenceVault
|
|
359
|
-
})
|
|
360
|
-
};
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
const dualPathMeta = convergenceVault ? { convergence_vault: convergenceVault } : {};
|
|
364
|
-
const converge = await deps.converge({
|
|
365
|
-
vault: gitVault,
|
|
366
|
-
lockToken: convergenceVault ? void 0 : input.lockToken,
|
|
367
|
-
env: input.env,
|
|
368
|
-
home: input.home
|
|
369
|
-
});
|
|
370
|
-
if (!converge.ok) {
|
|
371
|
-
const exitCode = converge.error === "PREFLIGHT_FAILED" ? ExitCode.PREFLIGHT_FAILED : ExitCode.SYNC_PULL_FAILED;
|
|
372
|
-
return { exitCode, result: converge };
|
|
373
|
-
}
|
|
374
|
-
const baseOid = git(gitVault, ["rev-parse", "HEAD"]);
|
|
375
|
-
if (!baseOid) {
|
|
376
|
-
return {
|
|
377
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
378
|
-
result: err("PREFLIGHT_FAILED", {
|
|
379
|
-
reason: "missing-head-after-converge",
|
|
380
|
-
...dualPathMeta
|
|
381
|
-
})
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
return {
|
|
385
|
-
exitCode: ExitCode.OK,
|
|
386
|
-
result: ok({
|
|
387
|
-
mode: "git-writer",
|
|
388
|
-
host_id: fleet.hostId,
|
|
389
|
-
mutation_vault: mutationVault,
|
|
390
|
-
git_vault: gitVault,
|
|
391
|
-
base_oid: baseOid,
|
|
392
|
-
converged: true,
|
|
393
|
-
helper_path: converge.data.helper_path,
|
|
394
|
-
...dualPathMeta,
|
|
395
|
-
convergence_source: convergenceSource
|
|
396
|
-
})
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
async function runManagedWriteTransaction(input, deps = DEFAULT_DEPS) {
|
|
400
|
-
const mutationVault = resolve2(input.vault);
|
|
401
|
-
const lock = acquireManagedWriteLock(mutationVault, input.command, {
|
|
402
|
-
gitStateVault: input.convergenceVault ? resolve2(input.convergenceVault) : mutationVault
|
|
403
|
-
});
|
|
404
|
-
if (!lock.ok) {
|
|
405
|
-
return { exitCode: ExitCode.SYNC_LOCK_HELD, result: lock };
|
|
406
|
-
}
|
|
407
|
-
const handle = lock.data;
|
|
408
|
-
try {
|
|
409
|
-
const preflightInput = {
|
|
410
|
-
vault: mutationVault,
|
|
411
|
-
command: input.command,
|
|
412
|
-
convergenceVault: input.convergenceVault,
|
|
413
|
-
hostId: input.hostId,
|
|
414
|
-
lockToken: handle.ownerToken,
|
|
415
|
-
env: input.env,
|
|
416
|
-
home: input.home,
|
|
417
|
-
cwd: input.cwd,
|
|
418
|
-
osHostname: input.osHostname,
|
|
419
|
-
user: input.user
|
|
420
|
-
};
|
|
421
|
-
const preflight = input.preflight ? await input.preflight(preflightInput) : await runManagedWritePreflight(preflightInput, deps);
|
|
422
|
-
if (!preflight.result.ok) {
|
|
423
|
-
return { exitCode: preflight.exitCode, result: preflight.result };
|
|
424
|
-
}
|
|
425
|
-
const receipt = preflight.result.data;
|
|
426
|
-
if (receipt.mutation_vault !== mutationVault) {
|
|
427
|
-
return {
|
|
428
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
429
|
-
result: err("PREFLIGHT_FAILED", {
|
|
430
|
-
reason: "mutation-vault-receipt-mismatch",
|
|
431
|
-
expected: mutationVault,
|
|
432
|
-
actual: receipt.mutation_vault
|
|
433
|
-
})
|
|
434
|
-
};
|
|
435
|
-
}
|
|
436
|
-
if (receipt.mode === "immutable-record" && !input.allowImmutableRecord) {
|
|
437
|
-
return {
|
|
438
|
-
exitCode: ExitCode.PREFLIGHT_FAILED,
|
|
439
|
-
result: err("PREFLIGHT_FAILED", {
|
|
440
|
-
reason: "immutable-record-not-enabled",
|
|
441
|
-
message: "Release A rejects immutable-record mode; event mode arrives in Release B",
|
|
442
|
-
host_id: receipt.host_id
|
|
443
|
-
})
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
return await input.mutate(receipt);
|
|
447
|
-
} finally {
|
|
448
|
-
releaseManagedWriteLock(handle);
|
|
449
|
-
}
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
export {
|
|
453
|
-
runManagedWritePreflight,
|
|
454
|
-
runManagedWriteTransaction
|
|
455
|
-
};
|