@ricsam/r5d-worker 0.0.82 → 0.0.83
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/cjs/main.cjs +422 -30
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/workspace-git-sync.cjs +69 -1
- package/dist/mjs/main.mjs +425 -31
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/workspace-git-sync.mjs +67 -1
- package/dist/types/main.d.ts +332 -0
- package/dist/types/workspace-git-sync.d.ts +28 -0
- package/package.json +1 -1
package/dist/mjs/package.json
CHANGED
|
@@ -15,6 +15,12 @@ const WORKSPACE_GIT_INTEGRATED_REF = "refs/r5d/workspace-local/integrated";
|
|
|
15
15
|
const WORKSPACE_GIT_HYDRATED_RECEIPT = "r5d/workspace-hydrated-head";
|
|
16
16
|
const WORKSPACE_GIT_HYDRATION_TRANSACTION = "r5d/workspace-hydration-transaction";
|
|
17
17
|
const WORKSPACE_GIT_CHECKOUT_DURABILITY = "r5d/workspace-checkout-durability";
|
|
18
|
+
class WorkspaceRemediationAncestryError extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.name = "WorkspaceRemediationAncestryError";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
18
24
|
const NON_RECURSIVE_GIT_CONFIG = [
|
|
19
25
|
"-c",
|
|
20
26
|
"submodule.recurse=false",
|
|
@@ -54,6 +60,29 @@ function revParse(workspacePath, revision) {
|
|
|
54
60
|
const result = gitResult(workspacePath, ["rev-parse", "--verify", revision]);
|
|
55
61
|
return result.exitCode === 0 ? result.stdout : null;
|
|
56
62
|
}
|
|
63
|
+
function requiredWorkspaceAncestorHeads(value) {
|
|
64
|
+
if (value === void 0) return [];
|
|
65
|
+
if (!Array.isArray(value) || value.length === 0 || value.some((head) => typeof head !== "string" || !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(head)) || new Set(value).size !== value.length) {
|
|
66
|
+
throw new WorkspaceRemediationAncestryError("Workspace remediation ancestor requirements are invalid");
|
|
67
|
+
}
|
|
68
|
+
return [...value];
|
|
69
|
+
}
|
|
70
|
+
function assertWorkspaceRemediationAncestry(input) {
|
|
71
|
+
if (input.requiredAncestorHeads.length === 0) return;
|
|
72
|
+
if (!input.currentHead) throw new WorkspaceRemediationAncestryError("Workspace remediation has no resolved HEAD to verify");
|
|
73
|
+
for (const requiredHead of input.requiredAncestorHeads) {
|
|
74
|
+
if (!tryGit(input.workspacePath, ["cat-file", "-e", `${requiredHead}^{commit}`]) || !tryGit(input.workspacePath, ["merge-base", "--is-ancestor", requiredHead, input.currentHead])) {
|
|
75
|
+
throw new WorkspaceRemediationAncestryError(
|
|
76
|
+
`Workspace remediation HEAD does not descend from required conflict commit ${requiredHead}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!input.remoteHead || !tryGit(input.workspacePath, ["cat-file", "-e", `${input.remoteHead}^{commit}`]) || !tryGit(input.workspacePath, ["merge-base", "--is-ancestor", input.remoteHead, input.currentHead])) {
|
|
81
|
+
throw new WorkspaceRemediationAncestryError(
|
|
82
|
+
"Fetched workspace head is not an ancestor of the resolved remediation HEAD; merge it explicitly before synchronizing"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
57
86
|
function updateIntegratedWorkspaceHead(workspacePath, head) {
|
|
58
87
|
git(workspacePath, ["update-ref", WORKSPACE_GIT_INTEGRATED_REF, head], "record integrated workspace head");
|
|
59
88
|
}
|
|
@@ -923,6 +952,15 @@ function configureWorkspaceRepository(input) {
|
|
|
923
952
|
);
|
|
924
953
|
git(input.workspacePath, ["config", "--local", "core.fsyncMethod", "fsync"], "configure workspace fsync method");
|
|
925
954
|
}
|
|
955
|
+
function configureExistingWorkspaceGitForRemediation(input) {
|
|
956
|
+
const workspacePath = path.resolve(input.workspacePath);
|
|
957
|
+
const workspaceStatus = lstatIfExists(workspacePath);
|
|
958
|
+
const gitStatus = lstatIfExists(path.join(workspacePath, ".git"));
|
|
959
|
+
if (!workspaceStatus?.isDirectory() || workspaceStatus.isSymbolicLink() || !gitStatus?.isDirectory() || gitStatus.isSymbolicLink()) {
|
|
960
|
+
throw new Error("Active workspace remediation requires a regular existing canonical synchronization checkout");
|
|
961
|
+
}
|
|
962
|
+
configureWorkspaceRepository({ ...input, workspacePath });
|
|
963
|
+
}
|
|
926
964
|
function fetchWorkspaceHead(workspacePath, remoteUrl, credentialHelper, credentialUsername) {
|
|
927
965
|
const result = gitResult(workspacePath, [
|
|
928
966
|
...gitTransportSecurityArgs(remoteUrl, credentialHelper, credentialUsername),
|
|
@@ -1424,8 +1462,16 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1424
1462
|
const maxDiffBytes = input.maxDiffBytes ?? MAX_WORKSPACE_GIT_DIFF_BYTES;
|
|
1425
1463
|
const maxPushAttempts = Math.max(1, input.maxPushAttempts ?? 4);
|
|
1426
1464
|
validateMounts(workspacePath, input.mounts);
|
|
1465
|
+
const requiredAncestorHeads = requiredWorkspaceAncestorHeads(input.requiredAncestorHeads);
|
|
1427
1466
|
const preserveResolutionInProgress = input.skipMountMirror === true;
|
|
1428
1467
|
const initial = ensureWorkspaceGitClone({ ...input, workspacePath, preserveResolutionInProgress });
|
|
1468
|
+
assertWorkspaceRemediationAncestry({
|
|
1469
|
+
workspacePath,
|
|
1470
|
+
currentHead: initial.localHead,
|
|
1471
|
+
remoteHead: initial.remoteHead,
|
|
1472
|
+
requiredAncestorHeads
|
|
1473
|
+
});
|
|
1474
|
+
const verifiedAncestorHeads = requiredAncestorHeads.length > 0 ? requiredAncestorHeads : void 0;
|
|
1429
1475
|
const startingHead = initial.localHead;
|
|
1430
1476
|
const receiptBeforeInitialHydration = readHydratedWorkspaceReceipt(workspacePath);
|
|
1431
1477
|
const deferredMountIds = /* @__PURE__ */ new Set();
|
|
@@ -1517,6 +1563,7 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1517
1563
|
conflictPaths: merged.conflictPaths,
|
|
1518
1564
|
conflictSnapshotRefs: refs,
|
|
1519
1565
|
conflictKind: "projection_merge",
|
|
1566
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1520
1567
|
error: merged.error
|
|
1521
1568
|
};
|
|
1522
1569
|
}
|
|
@@ -1640,6 +1687,12 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1640
1687
|
let rebaseCount = 0;
|
|
1641
1688
|
let updated = false;
|
|
1642
1689
|
for (let pushAttempt = 0; pushAttempt < maxPushAttempts; pushAttempt += 1) {
|
|
1690
|
+
assertWorkspaceRemediationAncestry({
|
|
1691
|
+
workspacePath,
|
|
1692
|
+
currentHead: revParse(workspacePath, "HEAD"),
|
|
1693
|
+
remoteHead,
|
|
1694
|
+
requiredAncestorHeads
|
|
1695
|
+
});
|
|
1643
1696
|
const reconciled = synchronizeWithFetchedHead({ workspacePath, remoteHead, attemptId });
|
|
1644
1697
|
if (reconciled.kind === "conflict") {
|
|
1645
1698
|
const localHead2 = revParse(workspacePath, "HEAD");
|
|
@@ -1657,6 +1710,7 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1657
1710
|
conflictPaths: reconciled.conflictPaths,
|
|
1658
1711
|
conflictSnapshotRefs: reconciled.refs,
|
|
1659
1712
|
conflictKind: "integration_rebase",
|
|
1713
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1660
1714
|
error: reconciled.error
|
|
1661
1715
|
};
|
|
1662
1716
|
}
|
|
@@ -1676,11 +1730,13 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1676
1730
|
diffSizeBytes: 0,
|
|
1677
1731
|
affectedPaths: [],
|
|
1678
1732
|
...classifiedMounts,
|
|
1733
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1679
1734
|
...projectionWarning ? { error: projectionWarning } : {}
|
|
1680
1735
|
};
|
|
1681
1736
|
}
|
|
1682
1737
|
const paths = changedPaths(workspacePath, remoteHead, localHead);
|
|
1683
|
-
const size = paths.length > 0 ? await diffSizeBytes(workspacePath, remoteHead, localHead, maxDiffBytes) : 0;
|
|
1738
|
+
const size = paths.length > 0 ? await (input.measureDiffSize ?? diffSizeBytes)(workspacePath, remoteHead, localHead, maxDiffBytes) : 0;
|
|
1739
|
+
input.assertStillAdmitted?.();
|
|
1684
1740
|
if (paths.length > 0 && size > maxDiffBytes && !input.allowLargeDiff) {
|
|
1685
1741
|
const classifiedMounts = classifyMounts([...selected.active, ...selected.tombstones]);
|
|
1686
1742
|
return {
|
|
@@ -1693,15 +1749,18 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1693
1749
|
diffSizeBytes: size,
|
|
1694
1750
|
affectedPaths: paths,
|
|
1695
1751
|
...classifiedMounts,
|
|
1752
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1696
1753
|
error: `Workspace diff exceeds the ${maxDiffBytes}-byte automatic publication limit`
|
|
1697
1754
|
};
|
|
1698
1755
|
}
|
|
1699
1756
|
if (localHead === remoteHead) {
|
|
1757
|
+
assertWorkspaceRemediationAncestry({ workspacePath, currentHead: localHead, remoteHead, requiredAncestorHeads });
|
|
1700
1758
|
const completedMounts = completedMountSelection(Boolean(input.skipMountMirror));
|
|
1701
1759
|
await input.afterWorkspacePublished?.({
|
|
1702
1760
|
publishedHead: localHead,
|
|
1703
1761
|
activeMountIds: completedMounts.activeMountIds
|
|
1704
1762
|
});
|
|
1763
|
+
input.assertStillAdmitted?.();
|
|
1705
1764
|
return {
|
|
1706
1765
|
outcome: updated ? "updated" : "no_change",
|
|
1707
1766
|
startingHead,
|
|
@@ -1712,9 +1771,11 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1712
1771
|
diffSizeBytes: size,
|
|
1713
1772
|
affectedPaths: paths,
|
|
1714
1773
|
...completedMounts,
|
|
1774
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1715
1775
|
...projectionWarning ? { error: projectionWarning } : {}
|
|
1716
1776
|
};
|
|
1717
1777
|
}
|
|
1778
|
+
assertWorkspaceRemediationAncestry({ workspacePath, currentHead: localHead, remoteHead, requiredAncestorHeads });
|
|
1718
1779
|
const pushArgs = [
|
|
1719
1780
|
...gitTransportSecurityArgs(input.remoteUrl, input.credentialHelper, input.credentialUsername),
|
|
1720
1781
|
"push",
|
|
@@ -1724,12 +1785,14 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1724
1785
|
pushArgs.push("origin", `HEAD:refs/heads/${WORKSPACE_GIT_BRANCH}`);
|
|
1725
1786
|
const push = gitResult(workspacePath, pushArgs);
|
|
1726
1787
|
if (push.exitCode === 0) {
|
|
1788
|
+
assertWorkspaceRemediationAncestry({ workspacePath, currentHead: localHead, remoteHead, requiredAncestorHeads });
|
|
1727
1789
|
updateIntegratedWorkspaceHead(workspacePath, localHead);
|
|
1728
1790
|
const completedMounts = completedMountSelection(Boolean(input.skipMountMirror));
|
|
1729
1791
|
await input.afterWorkspacePublished?.({
|
|
1730
1792
|
publishedHead: localHead,
|
|
1731
1793
|
activeMountIds: completedMounts.activeMountIds
|
|
1732
1794
|
});
|
|
1795
|
+
input.assertStillAdmitted?.();
|
|
1733
1796
|
return {
|
|
1734
1797
|
outcome: "pushed",
|
|
1735
1798
|
startingHead,
|
|
@@ -1740,6 +1803,7 @@ async function synchronizeWorkspaceGit(input) {
|
|
|
1740
1803
|
diffSizeBytes: size,
|
|
1741
1804
|
affectedPaths: paths,
|
|
1742
1805
|
...completedMounts,
|
|
1806
|
+
...verifiedAncestorHeads ? { verifiedAncestorHeads } : {},
|
|
1743
1807
|
...projectionWarning ? { error: projectionWarning } : {}
|
|
1744
1808
|
};
|
|
1745
1809
|
}
|
|
@@ -1765,6 +1829,8 @@ export {
|
|
|
1765
1829
|
WORKSPACE_GIT_CONFIRMED_LARGE_DIFF_PUSH_OPTION,
|
|
1766
1830
|
WORKSPACE_GIT_HYDRATED_RECEIPT,
|
|
1767
1831
|
WORKSPACE_GIT_HYDRATION_TRANSACTION,
|
|
1832
|
+
WorkspaceRemediationAncestryError,
|
|
1833
|
+
configureExistingWorkspaceGitForRemediation,
|
|
1768
1834
|
ensureWorkspaceGitClone,
|
|
1769
1835
|
hydrateWorkspaceGitMounts,
|
|
1770
1836
|
recoverWorkspaceGitHydration,
|
package/dist/types/main.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { Database } from "bun:sqlite";
|
|
3
|
+
import type { WorkerGitIdentity } from "./git-identity";
|
|
3
4
|
import { configureGitHubRegistryAuthFiles, type PreparedPrivateAuthFileGeneration } from "./registry-auth";
|
|
4
5
|
type WorkerProjectConfig = {
|
|
5
6
|
projectId: string;
|
|
@@ -22,6 +23,53 @@ type WorkerProjectConfig = {
|
|
|
22
23
|
baseCommitHash: string;
|
|
23
24
|
}>;
|
|
24
25
|
};
|
|
26
|
+
type WorkspaceSyncTrigger = {
|
|
27
|
+
type: "connect" | "inbound_head" | "write" | "edit" | "shell_inline" | "process_terminal" | "process_cancel" | "periodic" | "manual" | "remediation" | "remediation_confirm" | "remediation_reset";
|
|
28
|
+
sessionId?: string;
|
|
29
|
+
processRunId?: string;
|
|
30
|
+
toolCallId?: string;
|
|
31
|
+
projectId?: string;
|
|
32
|
+
branchName?: string;
|
|
33
|
+
detail?: string;
|
|
34
|
+
};
|
|
35
|
+
type WorkspaceSyncResult = {
|
|
36
|
+
type: "workspace_sync";
|
|
37
|
+
attemptId: string;
|
|
38
|
+
workerLabel: string;
|
|
39
|
+
trigger: WorkspaceSyncTrigger;
|
|
40
|
+
outcome: "no_change" | "published" | "updated" | "conflict_reset" | "large_diff_blocked" | "conflict_blocked" | "reset" | "failed";
|
|
41
|
+
startingHead: string | null;
|
|
42
|
+
localHead?: string;
|
|
43
|
+
publishedHead?: string;
|
|
44
|
+
rebaseCount: number;
|
|
45
|
+
diffSizeBytes: number;
|
|
46
|
+
gitStatus: string;
|
|
47
|
+
affectedProjects: string[];
|
|
48
|
+
affectedPaths: string[];
|
|
49
|
+
activeMountIds?: string[];
|
|
50
|
+
skippedMountIds?: string[];
|
|
51
|
+
activeProjectBranchPublications?: Array<{
|
|
52
|
+
branchId: string;
|
|
53
|
+
projectId: string;
|
|
54
|
+
branchName: string;
|
|
55
|
+
}>;
|
|
56
|
+
discardedPaths: string[];
|
|
57
|
+
localChangesDiscarded: boolean;
|
|
58
|
+
conflictPaths?: string[];
|
|
59
|
+
conflictSnapshotRefs?: {
|
|
60
|
+
local: string;
|
|
61
|
+
remote: string;
|
|
62
|
+
};
|
|
63
|
+
conflictKind?: "integration_rebase" | "projection_merge";
|
|
64
|
+
verifiedAncestorHeads?: string[];
|
|
65
|
+
telemetry?: {
|
|
66
|
+
totalMs: number;
|
|
67
|
+
queueMs: number;
|
|
68
|
+
prepareMs: number;
|
|
69
|
+
synchronizeMs: number;
|
|
70
|
+
};
|
|
71
|
+
error?: string;
|
|
72
|
+
};
|
|
25
73
|
export type WorkerSessionTarget = {
|
|
26
74
|
type: "project";
|
|
27
75
|
projectId: string;
|
|
@@ -31,6 +79,207 @@ export type WorkerSessionTarget = {
|
|
|
31
79
|
ownerUserId: string;
|
|
32
80
|
rootProfile: "visible_projects" | "canonical_sync";
|
|
33
81
|
};
|
|
82
|
+
type WorkerServerMessage = {
|
|
83
|
+
type: "connected";
|
|
84
|
+
label: string;
|
|
85
|
+
workerId: string;
|
|
86
|
+
} | {
|
|
87
|
+
type: "workspace_config";
|
|
88
|
+
requestId: string;
|
|
89
|
+
projects: WorkerProjectConfig[];
|
|
90
|
+
workspaceRemoteUrl: string;
|
|
91
|
+
gitIdentity: WorkerGitIdentity;
|
|
92
|
+
githubCredential: WorkerGitHubCredential | null;
|
|
93
|
+
deferWorkspaceSyncForIncidentId?: string;
|
|
94
|
+
} | {
|
|
95
|
+
type: "sync_workspace";
|
|
96
|
+
requestId: string;
|
|
97
|
+
attemptId: string;
|
|
98
|
+
trigger: WorkspaceSyncTrigger;
|
|
99
|
+
confirmedLargeDiff?: boolean;
|
|
100
|
+
confirmationReason?: string;
|
|
101
|
+
resetToCanonical?: boolean;
|
|
102
|
+
requiredAncestorHeads?: string[];
|
|
103
|
+
} | {
|
|
104
|
+
type: "create_project_branch";
|
|
105
|
+
requestId: string;
|
|
106
|
+
branchId: string;
|
|
107
|
+
projectId: string;
|
|
108
|
+
sourceBranch: string;
|
|
109
|
+
targetBranch: string;
|
|
110
|
+
} | {
|
|
111
|
+
type: "delete_project_branch";
|
|
112
|
+
requestId: string;
|
|
113
|
+
branchId: string;
|
|
114
|
+
projectId: string;
|
|
115
|
+
branchName: string;
|
|
116
|
+
} | {
|
|
117
|
+
type: "code_list";
|
|
118
|
+
requestId: string;
|
|
119
|
+
target: Extract<WorkerSessionTarget, {
|
|
120
|
+
type: "project";
|
|
121
|
+
}>;
|
|
122
|
+
path: string;
|
|
123
|
+
} | {
|
|
124
|
+
type: "code_read";
|
|
125
|
+
requestId: string;
|
|
126
|
+
target: Extract<WorkerSessionTarget, {
|
|
127
|
+
type: "project";
|
|
128
|
+
}>;
|
|
129
|
+
path: string;
|
|
130
|
+
} | {
|
|
131
|
+
type: "sync_session_artifacts";
|
|
132
|
+
requestId: string;
|
|
133
|
+
sessionId: string;
|
|
134
|
+
} | {
|
|
135
|
+
type: "workspace_incident_updated";
|
|
136
|
+
incidentId: string | null;
|
|
137
|
+
status: "remediating" | "waiting_for_worker" | "resolved" | "confirmed" | "reset" | null;
|
|
138
|
+
originWorkerLabel?: string;
|
|
139
|
+
} | {
|
|
140
|
+
type: "exec_terminal_ack";
|
|
141
|
+
runId: string;
|
|
142
|
+
} | {
|
|
143
|
+
type: "port_forward_connect";
|
|
144
|
+
forwardId: string;
|
|
145
|
+
relayConnectionId: string;
|
|
146
|
+
workerPort: number;
|
|
147
|
+
} | {
|
|
148
|
+
type: "update_clis";
|
|
149
|
+
requestId: string;
|
|
150
|
+
workerPackageSpec: string;
|
|
151
|
+
r5dctlPackageSpec: string;
|
|
152
|
+
targetWorkerVersion: string;
|
|
153
|
+
targetR5dctlVersion: string;
|
|
154
|
+
} | {
|
|
155
|
+
type: "exec";
|
|
156
|
+
requestId: string;
|
|
157
|
+
runId: string;
|
|
158
|
+
target: WorkerSessionTarget;
|
|
159
|
+
sessionId?: string;
|
|
160
|
+
argv: string[];
|
|
161
|
+
cwd?: string;
|
|
162
|
+
env?: Record<string, string>;
|
|
163
|
+
timeoutMs?: number;
|
|
164
|
+
workspaceEffect?: "none";
|
|
165
|
+
} | {
|
|
166
|
+
type: "exec_start";
|
|
167
|
+
requestId: string;
|
|
168
|
+
runId: string;
|
|
169
|
+
target: WorkerSessionTarget;
|
|
170
|
+
sessionId: string;
|
|
171
|
+
argv: string[];
|
|
172
|
+
command: string;
|
|
173
|
+
mode: "foreground" | "detached";
|
|
174
|
+
credentialId?: string;
|
|
175
|
+
cwd?: string;
|
|
176
|
+
env?: Record<string, string>;
|
|
177
|
+
timeoutMs?: number;
|
|
178
|
+
interactive?: boolean;
|
|
179
|
+
workspaceEffect?: "none";
|
|
180
|
+
} | {
|
|
181
|
+
type: "exec_stdin";
|
|
182
|
+
requestId: string;
|
|
183
|
+
runId: string;
|
|
184
|
+
data?: string;
|
|
185
|
+
eof?: boolean;
|
|
186
|
+
} | {
|
|
187
|
+
type: "pty_open";
|
|
188
|
+
requestId: string;
|
|
189
|
+
ptyId: string;
|
|
190
|
+
target: WorkerSessionTarget;
|
|
191
|
+
cols: number;
|
|
192
|
+
rows: number;
|
|
193
|
+
command?: string;
|
|
194
|
+
env?: Record<string, string>;
|
|
195
|
+
envFiles?: Array<{
|
|
196
|
+
path: string;
|
|
197
|
+
content: string;
|
|
198
|
+
mode?: number;
|
|
199
|
+
}>;
|
|
200
|
+
} | {
|
|
201
|
+
type: "pty_input";
|
|
202
|
+
ptyId: string;
|
|
203
|
+
data: string;
|
|
204
|
+
} | {
|
|
205
|
+
type: "pty_resize";
|
|
206
|
+
ptyId: string;
|
|
207
|
+
cols: number;
|
|
208
|
+
rows: number;
|
|
209
|
+
} | {
|
|
210
|
+
type: "pty_close";
|
|
211
|
+
ptyId: string;
|
|
212
|
+
} | {
|
|
213
|
+
type: "read";
|
|
214
|
+
requestId: string;
|
|
215
|
+
target: WorkerSessionTarget;
|
|
216
|
+
sessionId?: string;
|
|
217
|
+
activePlanId?: string;
|
|
218
|
+
filePath: string;
|
|
219
|
+
offset?: number;
|
|
220
|
+
limit?: number;
|
|
221
|
+
} | {
|
|
222
|
+
type: "write";
|
|
223
|
+
requestId: string;
|
|
224
|
+
target: WorkerSessionTarget;
|
|
225
|
+
sessionId?: string;
|
|
226
|
+
activePlanId?: string;
|
|
227
|
+
filePath: string;
|
|
228
|
+
content: string;
|
|
229
|
+
} | {
|
|
230
|
+
type: "edit";
|
|
231
|
+
requestId: string;
|
|
232
|
+
target: WorkerSessionTarget;
|
|
233
|
+
sessionId?: string;
|
|
234
|
+
activePlanId?: string;
|
|
235
|
+
filePath: string;
|
|
236
|
+
edits: Array<{
|
|
237
|
+
oldText: string;
|
|
238
|
+
newText: string;
|
|
239
|
+
}>;
|
|
240
|
+
} | {
|
|
241
|
+
type: "grep";
|
|
242
|
+
requestId: string;
|
|
243
|
+
target: WorkerSessionTarget;
|
|
244
|
+
sessionId?: string;
|
|
245
|
+
activePlanId?: string;
|
|
246
|
+
pattern: string;
|
|
247
|
+
path?: string;
|
|
248
|
+
glob?: string;
|
|
249
|
+
caseSensitive?: boolean;
|
|
250
|
+
limit?: number;
|
|
251
|
+
} | {
|
|
252
|
+
type: "find";
|
|
253
|
+
requestId: string;
|
|
254
|
+
target: WorkerSessionTarget;
|
|
255
|
+
sessionId?: string;
|
|
256
|
+
activePlanId?: string;
|
|
257
|
+
pattern?: string;
|
|
258
|
+
path?: string;
|
|
259
|
+
entryType?: string;
|
|
260
|
+
limit?: number;
|
|
261
|
+
} | {
|
|
262
|
+
type: "ls";
|
|
263
|
+
requestId: string;
|
|
264
|
+
target: WorkerSessionTarget;
|
|
265
|
+
sessionId?: string;
|
|
266
|
+
activePlanId?: string;
|
|
267
|
+
path?: string;
|
|
268
|
+
limit?: number;
|
|
269
|
+
} | {
|
|
270
|
+
type: "view_file_bytes";
|
|
271
|
+
requestId: string;
|
|
272
|
+
target: WorkerSessionTarget;
|
|
273
|
+
sessionId?: string;
|
|
274
|
+
activePlanId?: string;
|
|
275
|
+
filePath: string;
|
|
276
|
+
} | {
|
|
277
|
+
type: "cancel";
|
|
278
|
+
requestId: string;
|
|
279
|
+
runId: string;
|
|
280
|
+
} | {
|
|
281
|
+
type: "ping";
|
|
282
|
+
};
|
|
34
283
|
type WorkerReadFileResult = {
|
|
35
284
|
type: "read";
|
|
36
285
|
kind: "text";
|
|
@@ -151,6 +400,7 @@ export declare const workerPtyTestHarness: {
|
|
|
151
400
|
removeEnvFiles: typeof removePtyEnvFiles;
|
|
152
401
|
resolveEnvFileReferences: typeof resolvePtyEnvFileReferences;
|
|
153
402
|
commandHasWorkspaceEffect: typeof workerCommandHasWorkspaceEffect;
|
|
403
|
+
canonicalSyncTerminalHead: typeof canonicalSyncTerminalHead;
|
|
154
404
|
ptyIsWorkspaceBusy: typeof workerPtyIsWorkspaceBusy;
|
|
155
405
|
parseLinuxForegroundBusy: typeof parseLinuxPtyForegroundBusy;
|
|
156
406
|
};
|
|
@@ -302,6 +552,51 @@ type CredentialReapContractProbe = {
|
|
|
302
552
|
type CredentialReapContractStatus = "direct" | "systemd_unverified" | "verified_systemd";
|
|
303
553
|
declare function credentialReapContractStatus(probe?: CredentialReapContractProbe): CredentialReapContractStatus;
|
|
304
554
|
declare function verifiedCredentialReapContract(probe?: CredentialReapContractProbe): boolean;
|
|
555
|
+
declare function workspaceConfigurationIncidentDeferral(input: {
|
|
556
|
+
requestedIncidentId: string | undefined;
|
|
557
|
+
activeIncidentId: string | null;
|
|
558
|
+
}): {
|
|
559
|
+
incidentId: string | null;
|
|
560
|
+
error?: Error;
|
|
561
|
+
};
|
|
562
|
+
type DeferredWorkspaceConfiguration = {
|
|
563
|
+
incidentId: string;
|
|
564
|
+
serverRefreshExpected: boolean;
|
|
565
|
+
};
|
|
566
|
+
declare function workspaceIncidentTerminalClearDisposition(input: {
|
|
567
|
+
deferredConfiguration: DeferredWorkspaceConfiguration | null;
|
|
568
|
+
clearedIncidentId: string | null;
|
|
569
|
+
}): "ordinary_resume" | "await_server_refresh" | "reconnect_for_refresh";
|
|
570
|
+
declare function deferredWorkspaceTargetIsAllowed(deferredConfiguration: DeferredWorkspaceConfiguration | null, activeIncidentId: string | null, target: WorkerSessionTarget): boolean;
|
|
571
|
+
declare function deferredWorkspaceSyncTriggerIsAllowed(deferredConfiguration: DeferredWorkspaceConfiguration | null, activeIncidentId: string | null, trigger: WorkspaceSyncTrigger): boolean;
|
|
572
|
+
declare function workspaceOperationsAreFenced(deferredConfiguration: DeferredWorkspaceConfiguration | null, activeIncidentId: string | null): boolean;
|
|
573
|
+
declare function workspaceCommandTransportIsAllowed(deferredConfiguration: DeferredWorkspaceConfiguration | null, activeIncidentId: string | null, transport: "exec" | "exec_start"): boolean;
|
|
574
|
+
declare function deferredCredentialTransitionMustWait(input: {
|
|
575
|
+
incidentId: string | null;
|
|
576
|
+
transitionPhase: CredentialGenerationTransitionPhase;
|
|
577
|
+
canonicalRemediationActive: boolean;
|
|
578
|
+
}): boolean;
|
|
579
|
+
declare function workspaceConfigurationIncidentSnapshotIsCurrent(capturedIncidentId: string | null, activeIncidentId: string | null): boolean;
|
|
580
|
+
declare function deferredWorkspaceRefreshWatchdogIsCurrent(input: {
|
|
581
|
+
capturedIncidentId: string;
|
|
582
|
+
deferredConfiguration: DeferredWorkspaceConfiguration | null;
|
|
583
|
+
activeIncidentId: string | null;
|
|
584
|
+
}): boolean;
|
|
585
|
+
declare function incidentDeferredProjectCheckouts(projects: readonly WorkerProjectConfig[]): Array<{
|
|
586
|
+
projectId: string;
|
|
587
|
+
branchName: string;
|
|
588
|
+
}>;
|
|
589
|
+
declare function deferredIncidentWorkspaceConfigurationResult(input: {
|
|
590
|
+
attemptId: string;
|
|
591
|
+
workerLabel: string;
|
|
592
|
+
head: string | null;
|
|
593
|
+
skippedMountIds: string[];
|
|
594
|
+
}): WorkspaceSyncResult;
|
|
595
|
+
declare function workspaceSyncFailureHydrationIsSafe(input: {
|
|
596
|
+
error: unknown;
|
|
597
|
+
resetToCanonical: boolean;
|
|
598
|
+
inspectCurrentHydration: () => boolean;
|
|
599
|
+
}): boolean;
|
|
305
600
|
declare function fenceUnsafeWorkspaceSyncFailure(input: {
|
|
306
601
|
hydrationCurrent: boolean;
|
|
307
602
|
invalidateExecution: () => void;
|
|
@@ -332,7 +627,21 @@ export declare const workerGitSecurityTestHarness: {
|
|
|
332
627
|
credentialReapContractStatus: typeof credentialReapContractStatus;
|
|
333
628
|
verifiedCredentialReapContract: typeof verifiedCredentialReapContract;
|
|
334
629
|
fenceUnsafeWorkspaceSyncFailure: typeof fenceUnsafeWorkspaceSyncFailure;
|
|
630
|
+
workspaceConfigurationIncidentDeferral: typeof workspaceConfigurationIncidentDeferral;
|
|
631
|
+
workspaceIncidentTerminalClearDisposition: typeof workspaceIncidentTerminalClearDisposition;
|
|
632
|
+
deferredWorkspaceTargetIsAllowed: typeof deferredWorkspaceTargetIsAllowed;
|
|
633
|
+
deferredWorkspaceSyncTriggerIsAllowed: typeof deferredWorkspaceSyncTriggerIsAllowed;
|
|
634
|
+
workspaceOperationsAreFenced: typeof workspaceOperationsAreFenced;
|
|
635
|
+
workspaceCommandTransportIsAllowed: typeof workspaceCommandTransportIsAllowed;
|
|
636
|
+
deferredCredentialTransitionMustWait: typeof deferredCredentialTransitionMustWait;
|
|
637
|
+
workspaceConfigurationIncidentSnapshotIsCurrent: typeof workspaceConfigurationIncidentSnapshotIsCurrent;
|
|
638
|
+
deferredWorkspaceRefreshWatchdogIsCurrent: typeof deferredWorkspaceRefreshWatchdogIsCurrent;
|
|
639
|
+
incidentDeferredProjectCheckouts: typeof incidentDeferredProjectCheckouts;
|
|
640
|
+
deferredIncidentWorkspaceConfigurationResult: typeof deferredIncidentWorkspaceConfigurationResult;
|
|
641
|
+
workspaceSyncFailureHydrationIsSafe: typeof workspaceSyncFailureHydrationIsSafe;
|
|
335
642
|
assertWorkerChildAdmission: typeof assertWorkerChildAdmission;
|
|
643
|
+
executeWriteFileOperation: typeof executeWriteFileOperation;
|
|
644
|
+
executeEditFileOperation: typeof executeEditFileOperation;
|
|
336
645
|
terminateCredentialBearingChildren: typeof terminateCredentialBearingChildren;
|
|
337
646
|
terminateCredentialBearingChildrenWithRetention: typeof terminateCredentialBearingChildrenWithRetention;
|
|
338
647
|
commitCredentialGeneration(prepared: PreparedPrivateAuthFileGeneration, credential: WorkerGitHubCredential | null, children: readonly {
|
|
@@ -365,6 +674,7 @@ type ResolvedWorkerSessionTarget = {
|
|
|
365
674
|
rootPath: string;
|
|
366
675
|
config?: WorkerProjectConfig;
|
|
367
676
|
};
|
|
677
|
+
declare function canonicalSyncTerminalHead(resolvedTarget: Pick<ResolvedWorkerSessionTarget, "target" | "rootPath">, readHead?: (rootPath: string) => string): string | undefined;
|
|
368
678
|
export declare function describeWorkerSessionTarget(target: WorkerSessionTarget): string;
|
|
369
679
|
export declare function resolveWorkerSessionTarget(input: {
|
|
370
680
|
target: WorkerSessionTarget;
|
|
@@ -389,6 +699,28 @@ export declare function editWorkerTextFile(branchPath: string, filePath: string,
|
|
|
389
699
|
oldText: string;
|
|
390
700
|
newText: string;
|
|
391
701
|
}>, builtInPaths?: WorkerBuiltInToolPaths): WorkerEditFileResult;
|
|
702
|
+
declare function executeWriteFileOperation(input: {
|
|
703
|
+
message: Extract<WorkerServerMessage, {
|
|
704
|
+
type: "write";
|
|
705
|
+
}>;
|
|
706
|
+
resolvedTarget: ResolvedWorkerSessionTarget;
|
|
707
|
+
baseUrl: string;
|
|
708
|
+
token: string;
|
|
709
|
+
artifactRoot: string;
|
|
710
|
+
planRoot: string;
|
|
711
|
+
assertAdmission: () => void;
|
|
712
|
+
}): Promise<WorkerWriteFileResult>;
|
|
713
|
+
declare function executeEditFileOperation(input: {
|
|
714
|
+
message: Extract<WorkerServerMessage, {
|
|
715
|
+
type: "edit";
|
|
716
|
+
}>;
|
|
717
|
+
resolvedTarget: ResolvedWorkerSessionTarget;
|
|
718
|
+
baseUrl: string;
|
|
719
|
+
token: string;
|
|
720
|
+
artifactRoot: string;
|
|
721
|
+
planRoot: string;
|
|
722
|
+
assertAdmission: () => void;
|
|
723
|
+
}): Promise<WorkerEditFileResult>;
|
|
392
724
|
export declare function grepWorkerFiles(branchPath: string, input: {
|
|
393
725
|
pattern: string;
|
|
394
726
|
path?: string;
|
|
@@ -53,8 +53,13 @@ export type WorkspaceGitSyncResult = {
|
|
|
53
53
|
remote: string;
|
|
54
54
|
};
|
|
55
55
|
conflictKind?: "integration_rebase" | "projection_merge";
|
|
56
|
+
verifiedAncestorHeads?: string[];
|
|
56
57
|
error?: string;
|
|
57
58
|
};
|
|
59
|
+
/** A guarded remediation was rejected before it was allowed to hydrate or publish. */
|
|
60
|
+
export declare class WorkspaceRemediationAncestryError extends Error {
|
|
61
|
+
constructor(message: string);
|
|
62
|
+
}
|
|
58
63
|
declare function gitCommandArgs(args: string[]): string[];
|
|
59
64
|
declare function workspaceCloneCommandArgs(args: string[], remoteUrl: string, credentialHelper?: string | null, credentialUsername?: string | null): string[];
|
|
60
65
|
export declare function workspaceGitHydrationIsCurrent(workspacePath: string, mounts?: readonly WorkspaceGitMount[]): boolean;
|
|
@@ -68,6 +73,22 @@ declare function configureWorkspaceRepository(input: {
|
|
|
68
73
|
email: string;
|
|
69
74
|
};
|
|
70
75
|
}): void;
|
|
76
|
+
/**
|
|
77
|
+
* Rebind only the existing canonical checkout's local Git configuration while
|
|
78
|
+
* an incident owns its HEAD. In particular, this deliberately does not fetch,
|
|
79
|
+
* recover durability, move refs, reset the index/worktree, or inspect/abort an
|
|
80
|
+
* in-progress merge or rebase.
|
|
81
|
+
*/
|
|
82
|
+
export declare function configureExistingWorkspaceGitForRemediation(input: {
|
|
83
|
+
workspacePath: string;
|
|
84
|
+
remoteUrl: string;
|
|
85
|
+
credentialHelper?: string | null;
|
|
86
|
+
credentialUsername?: string | null;
|
|
87
|
+
gitIdentity: {
|
|
88
|
+
name: string;
|
|
89
|
+
email: string;
|
|
90
|
+
};
|
|
91
|
+
}): void;
|
|
71
92
|
export declare function ensureWorkspaceGitClone(input: {
|
|
72
93
|
workspacePath: string;
|
|
73
94
|
remoteUrl: string;
|
|
@@ -113,6 +134,7 @@ export declare function resetWorkspaceGit(input: {
|
|
|
113
134
|
activeMountIds: string[];
|
|
114
135
|
skippedMountIds: string[];
|
|
115
136
|
};
|
|
137
|
+
declare function diffSizeBytes(workspacePath: string, baseRevision: string | null, headRevision: string, limit: number): Promise<number>;
|
|
116
138
|
export declare function synchronizeWorkspaceGit(input: {
|
|
117
139
|
attemptId?: string;
|
|
118
140
|
workerLabel: string;
|
|
@@ -131,6 +153,12 @@ export declare function synchronizeWorkspaceGit(input: {
|
|
|
131
153
|
maxPushAttempts?: number;
|
|
132
154
|
/** Publish edits already made in the outer clone without first projecting visible mounts over them. */
|
|
133
155
|
skipMountMirror?: boolean;
|
|
156
|
+
/** Positive ancestry proof required before a remediation may integrate, publish, or hydrate. */
|
|
157
|
+
requiredAncestorHeads?: readonly string[];
|
|
158
|
+
/** Revalidate the worker/config/incident generation after every async boundary. */
|
|
159
|
+
assertStillAdmitted?: () => void;
|
|
160
|
+
/** Test seam for exercising an incident transition during asynchronous diff measurement. */
|
|
161
|
+
measureDiffSize?: typeof diffSizeBytes;
|
|
134
162
|
afterWorkspacePublished?: (context: {
|
|
135
163
|
publishedHead: string;
|
|
136
164
|
activeMountIds: string[];
|