@loucompanion/forge-bridge 0.1.3-dev.f66395c3ac21 → 0.1.3-dev.fbe15023cdfe
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 +78 -0
- package/dist/bridge/bridge.base.d.ts +6 -1
- package/dist/bridge/bridge.service.d.ts +60 -3
- package/dist/bridge/bridge.service.js +970 -24
- package/dist/bridge/bridge.types.d.ts +172 -1
- package/dist/cleanup/cleanup.service.d.ts +13 -2
- package/dist/cleanup/cleanup.service.js +435 -3
- package/dist/cleanup/cleanup.types.d.ts +10 -0
- package/dist/cleanup/index.d.ts +1 -1
- package/dist/cleanup/index.js +1 -1
- package/dist/cleanup/internals.d.ts +2 -2
- package/dist/cleanup/internals.js +1 -1
- package/dist/cli/cli.help.d.ts +2 -0
- package/dist/cli/cli.help.js +217 -0
- package/dist/cli/cli.service.d.ts +42 -2
- package/dist/cli/cli.service.js +356 -205
- package/dist/cli/local-config.d.ts +6 -0
- package/dist/cli/local-config.js +47 -3
- package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
- package/dist/runtime/attempt-node-runtime-launcher.js +101 -0
- package/dist/runtime/attempt-process-supervisor-registry.d.ts +20 -0
- package/dist/runtime/attempt-process-supervisor-registry.js +64 -0
- package/dist/runtime/attempt-process-supervisor.d.ts +86 -0
- package/dist/runtime/attempt-process-supervisor.js +350 -0
- package/dist/runtime/generated-output-reset.d.ts +10 -0
- package/dist/runtime/generated-output-reset.js +103 -0
- package/dist/runtime/host-listener-inspector.d.ts +44 -0
- package/dist/runtime/host-listener-inspector.js +324 -0
- package/dist/runtime/host-port-broker.d.ts +76 -0
- package/dist/runtime/host-port-broker.js +333 -0
- package/dist/runtime/host-runtime-contract.d.ts +47 -0
- package/dist/runtime/host-runtime-contract.js +700 -0
- package/dist/runtime/host-runtime-lease.d.ts +133 -0
- package/dist/runtime/host-runtime-lease.js +1460 -0
- package/dist/runtime/host-runtime-promotion.d.ts +23 -0
- package/dist/runtime/host-runtime-promotion.js +159 -0
- package/dist/runtime/node-host-runtime-adapter.d.ts +51 -0
- package/dist/runtime/node-host-runtime-adapter.js +268 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +20 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +220 -0
- package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
- package/dist/runtime/runtime-isolation-lease.js +158 -0
- package/dist/sandbox/command-runner.d.ts +4 -0
- package/dist/sandbox/command-runner.js +47 -0
- package/dist/sandbox/contract.d.ts +5 -0
- package/dist/sandbox/contract.js +276 -0
- package/dist/sandbox/event-budget.d.ts +11 -0
- package/dist/sandbox/event-budget.js +27 -0
- package/dist/sandbox/image-policy.d.ts +35 -0
- package/dist/sandbox/image-policy.js +247 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/lease-watchdog.d.ts +18 -0
- package/dist/sandbox/lease-watchdog.js +67 -0
- package/dist/sandbox/preflight.d.ts +54 -0
- package/dist/sandbox/preflight.js +335 -0
- package/dist/sandbox/process.d.ts +20 -0
- package/dist/sandbox/process.js +209 -0
- package/dist/sandbox/provider-auth/codex.d.ts +26 -0
- package/dist/sandbox/provider-auth/codex.js +212 -0
- package/dist/sandbox/repository-lock.d.ts +5 -0
- package/dist/sandbox/repository-lock.js +119 -0
- package/dist/sandbox/runtime.d.ts +297 -0
- package/dist/sandbox/runtime.js +2338 -0
- package/dist/sandbox/sandbox.types.d.ts +86 -0
- package/dist/sandbox/sandbox.types.js +1 -0
- package/dist/sandbox/smoke.d.ts +76 -0
- package/dist/sandbox/smoke.js +380 -0
- package/dist/sandbox/worker-supervisor.d.ts +13 -0
- package/dist/sandbox/worker-supervisor.js +36 -0
- package/dist/sandbox/worker.d.ts +1 -0
- package/dist/sandbox/worker.js +225 -0
- package/dist/sandbox/workspace.service.d.ts +13 -0
- package/dist/sandbox/workspace.service.js +72 -0
- package/dist/session/managed-attempt-tools.d.ts +12 -0
- package/dist/session/managed-attempt-tools.js +561 -0
- package/dist/session/phase-completion.artifacts.d.ts +10 -0
- package/dist/session/phase-completion.artifacts.js +627 -0
- package/dist/session/phase-completion.d.ts +43 -42
- package/dist/session/phase-completion.helpers.d.ts +112 -0
- package/dist/session/phase-completion.helpers.js +684 -0
- package/dist/session/phase-completion.js +114 -3007
- package/dist/session/phase-completion.prompts.d.ts +14 -0
- package/dist/session/phase-completion.prompts.js +234 -0
- package/dist/session/phase-completion.runtime.d.ts +47 -0
- package/dist/session/phase-completion.runtime.js +731 -0
- package/dist/session/phase-completion.schemas.d.ts +3 -0
- package/dist/session/phase-completion.schemas.js +812 -0
- package/dist/session/phase-completion.validation.d.ts +37 -0
- package/dist/session/phase-completion.validation.js +828 -0
- package/dist/session/provider-cli/ci-repair-readiness.d.ts +8 -0
- package/dist/session/provider-cli/ci-repair-readiness.js +90 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +93 -0
- package/dist/session/provider-cli/provider-cli.artifacts.js +778 -0
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.d.ts +12 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.js +279 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +14 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +375 -0
- package/dist/session/provider-cli/provider-cli.process.d.ts +48 -0
- package/dist/session/provider-cli/provider-cli.process.js +474 -0
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +47 -0
- package/dist/session/provider-cli/provider-cli.prompts.js +595 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.d.ts +11 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +66 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +9 -0
- package/dist/session/provider-cli/provider-cli.runtime.js +41 -0
- package/dist/session/provider-cli/provider-cli.service.d.ts +22 -53
- package/dist/session/provider-cli/provider-cli.service.js +587 -2530
- package/dist/session/provider-cli/provider-cli.types.d.ts +6 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +22 -0
- package/dist/session/provider-cli/provider-output-state.js +473 -0
- package/dist/session/session-redaction.d.ts +3 -0
- package/dist/session/session-redaction.js +23 -0
- package/dist/session/session.base.d.ts +6 -1
- package/dist/session/session.service.d.ts +8 -2
- package/dist/session/session.service.js +463 -58
- package/dist/session/session.types.d.ts +177 -1
- package/dist/session/session.types.js +352 -3
- package/dist/shared/path/path.js +3 -1
- package/dist/shared/process/host-process-recovery.d.ts +12 -0
- package/dist/shared/process/host-process-recovery.js +78 -0
- package/dist/shared/process/host-process-supervisor.d.ts +57 -0
- package/dist/shared/process/host-process-supervisor.js +282 -0
- package/dist/shared/process/process.d.ts +1 -0
- package/dist/shared/process/process.js +1 -0
- package/dist/shared/process/windows-launch.d.ts +8 -0
- package/dist/shared/process/windows-launch.js +41 -0
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +10 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/artifact-injector.d.ts +3 -2
- package/dist/worktree/artifact-injector.js +82 -10
- package/dist/worktree/dependency-warmer.d.ts +21 -1
- package/dist/worktree/dependency-warmer.js +138 -5
- package/dist/worktree/index.d.ts +1 -0
- package/dist/worktree/index.js +1 -0
- package/dist/worktree/prior-phase-artifact-hydrator.d.ts +2 -0
- package/dist/worktree/prior-phase-artifact-hydrator.js +136 -0
- package/dist/worktree/worktree-paths.d.ts +4 -0
- package/dist/worktree/worktree-paths.js +30 -0
- package/dist/worktree/worktree.base.d.ts +3 -0
- package/dist/worktree/worktree.service.d.ts +9 -3
- package/dist/worktree/worktree.service.js +100 -52
- package/dist/worktree/worktree.types.d.ts +3 -1
- package/package.json +6 -3
- package/runtime/windows-job-supervisor.ps1 +356 -0
- package/runtime/windows-listener-owner.ps1 +33 -0
|
@@ -2,11 +2,11 @@ import path from "node:path";
|
|
|
2
2
|
export function parseRunOnceDispatchPacket(value) {
|
|
3
3
|
const packet = asObject(value, "dispatch packet");
|
|
4
4
|
const schemaVersion = requiredNumber(packet, "schemaVersion");
|
|
5
|
-
if (schemaVersion !== 1) {
|
|
5
|
+
if (schemaVersion !== 1 && schemaVersion !== 2) {
|
|
6
6
|
throw new Error(`Unsupported dispatch schemaVersion: ${schemaVersion}`);
|
|
7
7
|
}
|
|
8
8
|
return {
|
|
9
|
-
schemaVersion
|
|
9
|
+
schemaVersion,
|
|
10
10
|
userId: requiredString(packet, "userId"),
|
|
11
11
|
workItem: parseWorkItem(packet.workItem),
|
|
12
12
|
repo: parseRepo(packet.repo),
|
|
@@ -14,19 +14,163 @@ export function parseRunOnceDispatchPacket(value) {
|
|
|
14
14
|
session: parseSession(packet.session),
|
|
15
15
|
lease: parseLease(packet.lease),
|
|
16
16
|
execution: parseExecution(packet.execution),
|
|
17
|
+
runtimeIntent: parseRuntimeIntent(packet.runtimeIntent),
|
|
17
18
|
serverLocal: parseServerLocal(packet.serverLocal),
|
|
19
|
+
sandbox: parseSandbox(packet.sandbox, schemaVersion),
|
|
18
20
|
pullRequest: parsePullRequest(packet.pullRequest),
|
|
19
21
|
apiKeySecretGrant: parseApiKeySecretGrant(packet.apiKeySecretGrant),
|
|
22
|
+
apiKeySecretGrantHandle: parseApiKeySecretGrantHandle(packet.apiKeySecretGrantHandle),
|
|
20
23
|
artifacts: parseArtifacts(packet.artifacts),
|
|
24
|
+
priorPhaseArtifacts: parsePriorPhaseArtifacts(packet.priorPhaseArtifacts),
|
|
21
25
|
warmPathOverrides: parseWarmPathOverrides(packet.warmPathOverrides),
|
|
22
26
|
qaBrowser: parseQaBrowser(packet.qaBrowser),
|
|
27
|
+
qaScope: parseQaScope(packet.qaScope ?? packet.qa_scope),
|
|
23
28
|
qaRework: parseQaRework(packet.qaRework),
|
|
24
29
|
architectRevision: parseArchitectRevision(packet.architectRevision),
|
|
30
|
+
architectDependencies: parseArchitectDependencies(packet.architectDependencies),
|
|
25
31
|
storyDevelop: parseStoryDevelop(packet.storyDevelop),
|
|
26
32
|
storyQa: parseStoryQa(packet.storyQa),
|
|
33
|
+
designerRefs: parseDesignerRefs(packet.designerRefs ?? packet.designer_refs),
|
|
27
34
|
draft: parseDraftPrompt(packet.draft)
|
|
28
35
|
};
|
|
29
36
|
}
|
|
37
|
+
function parseRuntimeIntent(value) {
|
|
38
|
+
if (value === undefined || value === null) {
|
|
39
|
+
return { executionClass: "managed_runtime", applicationRuntimeRequired: true };
|
|
40
|
+
}
|
|
41
|
+
const intent = asObject(value, "runtimeIntent");
|
|
42
|
+
const executionClass = requiredString(intent, "executionClass").trim().toLowerCase();
|
|
43
|
+
if (executionClass !== "analysis_only" && executionClass !== "managed_runtime") {
|
|
44
|
+
throw new Error("runtimeIntent.executionClass must be analysis_only or managed_runtime.");
|
|
45
|
+
}
|
|
46
|
+
const applicationRuntimeRequired = requiredBoolean(intent, "applicationRuntimeRequired");
|
|
47
|
+
if ((executionClass === "analysis_only") === applicationRuntimeRequired) {
|
|
48
|
+
throw new Error("runtimeIntent execution class and application runtime requirement are inconsistent.");
|
|
49
|
+
}
|
|
50
|
+
return { executionClass, applicationRuntimeRequired };
|
|
51
|
+
}
|
|
52
|
+
function parseSandbox(value, schemaVersion) {
|
|
53
|
+
if (value === undefined || value === null) {
|
|
54
|
+
if (schemaVersion === 2) {
|
|
55
|
+
throw new Error("sandbox is required for dispatch schemaVersion 2.");
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const sandbox = asObject(value, "sandbox");
|
|
60
|
+
const executionMode = requiredString(sandbox, "executionMode");
|
|
61
|
+
if (executionMode !== "host" && executionMode !== "docker") {
|
|
62
|
+
throw new Error("sandbox.executionMode must be host or docker.");
|
|
63
|
+
}
|
|
64
|
+
const executionPolicy = requiredString(sandbox, "executionPolicy");
|
|
65
|
+
if (executionPolicy !== "host_allowed" && executionPolicy !== "sandbox_preferred" && executionPolicy !== "sandbox_required") {
|
|
66
|
+
throw new Error("sandbox.executionPolicy is invalid.");
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
dispatchAttemptId: requiredString(sandbox, "dispatchAttemptId"),
|
|
70
|
+
executionLeaseId: requiredString(sandbox, "executionLeaseId"),
|
|
71
|
+
runnerInstanceId: requiredString(sandbox, "runnerInstanceId"),
|
|
72
|
+
executionMode,
|
|
73
|
+
executionPolicy,
|
|
74
|
+
networkPolicy: parseSandboxNetworkPolicy(sandbox.networkPolicy),
|
|
75
|
+
requestedResources: parseSandboxResourceRequest(sandbox.requestedResources),
|
|
76
|
+
runtime: optionalString(sandbox, "runtime"),
|
|
77
|
+
sandboxConfigCommitSha: optionalString(sandbox, "sandboxConfigCommitSha"),
|
|
78
|
+
inputCommitSha: optionalString(sandbox, "inputCommitSha"),
|
|
79
|
+
contractDigest: optionalString(sandbox, "contractDigest"),
|
|
80
|
+
imageDigest: optionalString(sandbox, "imageDigest"),
|
|
81
|
+
publicationMode: parsePublicationMode(sandbox.publicationMode),
|
|
82
|
+
publishGrantHandle: parsePublishGrantHandle(sandbox.publishGrantHandle)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function parsePublicationMode(value) {
|
|
86
|
+
if (value === undefined || value === null)
|
|
87
|
+
return "shared_filesystem";
|
|
88
|
+
if (value !== "bridge_push" && value !== "shared_filesystem")
|
|
89
|
+
throw new Error("sandbox.publicationMode is invalid.");
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
function parsePublishGrantHandle(value) {
|
|
93
|
+
if (value === undefined || value === null)
|
|
94
|
+
return null;
|
|
95
|
+
const handle = asObject(value, "sandbox.publishGrantHandle");
|
|
96
|
+
const grantId = requiredString(handle, "grantId");
|
|
97
|
+
const branch = requiredString(handle, "branch");
|
|
98
|
+
const expiresAt = requiredString(handle, "expiresAt");
|
|
99
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(grantId)) {
|
|
100
|
+
throw new Error("sandbox.publishGrantHandle.grantId is invalid.");
|
|
101
|
+
}
|
|
102
|
+
if (branch.length > 240)
|
|
103
|
+
throw new Error("sandbox.publishGrantHandle.branch is too long.");
|
|
104
|
+
if (!Number.isFinite(Date.parse(expiresAt)))
|
|
105
|
+
throw new Error("sandbox.publishGrantHandle.expiresAt is invalid.");
|
|
106
|
+
return { grantId, branch, expiresAt };
|
|
107
|
+
}
|
|
108
|
+
function parseSandboxResourceRequest(value) {
|
|
109
|
+
if (value === undefined || value === null) {
|
|
110
|
+
return {
|
|
111
|
+
sandboxSlots: 1,
|
|
112
|
+
cpuMillis: 2000,
|
|
113
|
+
workerMemoryLimitBytes: 2 * 1024 ** 3,
|
|
114
|
+
serviceMemoryLimitBytes: 0,
|
|
115
|
+
runtimeOverheadBytes: 128 * 1024 ** 2,
|
|
116
|
+
memoryBytes: 2 * 1024 ** 3 + 128 * 1024 ** 2,
|
|
117
|
+
workspaceBytes: 10 * 1024 ** 3,
|
|
118
|
+
pids: 512,
|
|
119
|
+
buildSlots: 1
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const resources = asObject(value, "sandbox.requestedResources");
|
|
123
|
+
const memoryBytes = boundedInteger(resources, "memoryBytes", 128 * 1024 ** 2, 512 * 1024 ** 3);
|
|
124
|
+
const hasMemoryBreakdown = ["workerMemoryLimitBytes", "serviceMemoryLimitBytes", "runtimeOverheadBytes"]
|
|
125
|
+
.some(key => resources[key] !== undefined && resources[key] !== null);
|
|
126
|
+
const workerMemoryLimitBytes = hasMemoryBreakdown
|
|
127
|
+
? boundedInteger(resources, "workerMemoryLimitBytes", 128 * 1024 ** 2, 512 * 1024 ** 3)
|
|
128
|
+
: memoryBytes;
|
|
129
|
+
const serviceMemoryLimitBytes = hasMemoryBreakdown
|
|
130
|
+
? boundedInteger(resources, "serviceMemoryLimitBytes", 0, 512 * 1024 ** 3)
|
|
131
|
+
: 0;
|
|
132
|
+
const runtimeOverheadBytes = hasMemoryBreakdown
|
|
133
|
+
? boundedInteger(resources, "runtimeOverheadBytes", 0, 64 * 1024 ** 3)
|
|
134
|
+
: 0;
|
|
135
|
+
if (workerMemoryLimitBytes + serviceMemoryLimitBytes + runtimeOverheadBytes !== memoryBytes) {
|
|
136
|
+
throw new Error("sandbox.requestedResources memory breakdown must equal memoryBytes.");
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
sandboxSlots: boundedInteger(resources, "sandboxSlots", 1, 4),
|
|
140
|
+
cpuMillis: boundedInteger(resources, "cpuMillis", 100, 64_000),
|
|
141
|
+
workerMemoryLimitBytes,
|
|
142
|
+
serviceMemoryLimitBytes,
|
|
143
|
+
runtimeOverheadBytes,
|
|
144
|
+
memoryBytes,
|
|
145
|
+
workspaceBytes: boundedInteger(resources, "workspaceBytes", 1024 ** 3, 10 * 1024 ** 4),
|
|
146
|
+
pids: boundedInteger(resources, "pids", 32, 65_536),
|
|
147
|
+
buildSlots: boundedInteger(resources, "buildSlots", 0, 4)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function parseSandboxNetworkPolicy(value) {
|
|
151
|
+
if (value === undefined || value === null)
|
|
152
|
+
return { mode: "offline", allowedHosts: [] };
|
|
153
|
+
const policy = asObject(value, "sandbox.networkPolicy");
|
|
154
|
+
const mode = requiredString(policy, "mode");
|
|
155
|
+
if (mode !== "offline" && mode !== "public_allowlist" && mode !== "open_public") {
|
|
156
|
+
throw new Error("sandbox.networkPolicy.mode is invalid.");
|
|
157
|
+
}
|
|
158
|
+
const rawHosts = policy.allowedHosts ?? [];
|
|
159
|
+
if (!Array.isArray(rawHosts) || rawHosts.some((host) => typeof host !== "string")) {
|
|
160
|
+
throw new Error("sandbox.networkPolicy.allowedHosts must be a string array.");
|
|
161
|
+
}
|
|
162
|
+
const allowedHosts = [...new Set(rawHosts.map(host => host.trim().toLowerCase()).filter(Boolean))];
|
|
163
|
+
if (allowedHosts.length > 128 || allowedHosts.some(host => !/^(?:\*\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/u.test(host))) {
|
|
164
|
+
throw new Error("sandbox.networkPolicy.allowedHosts contains an invalid hostname.");
|
|
165
|
+
}
|
|
166
|
+
if (mode !== "public_allowlist" && allowedHosts.length > 0) {
|
|
167
|
+
throw new Error("sandbox.networkPolicy.allowedHosts requires public_allowlist mode.");
|
|
168
|
+
}
|
|
169
|
+
if (mode === "public_allowlist" && allowedHosts.length === 0) {
|
|
170
|
+
return { mode: "offline", allowedHosts: [] };
|
|
171
|
+
}
|
|
172
|
+
return { mode, allowedHosts };
|
|
173
|
+
}
|
|
30
174
|
export function failureResult(summary, events = []) {
|
|
31
175
|
return {
|
|
32
176
|
schemaVersion: 1,
|
|
@@ -118,9 +262,45 @@ function parseDraftPrompt(value) {
|
|
|
118
262
|
return {
|
|
119
263
|
kind: requiredString(draft, "kind"),
|
|
120
264
|
systemPrompt: requiredString(draft, "systemPrompt"),
|
|
121
|
-
userPrompt: requiredString(draft, "userPrompt")
|
|
265
|
+
userPrompt: requiredString(draft, "userPrompt"),
|
|
266
|
+
projectName: optionalString(draft, "projectName"),
|
|
267
|
+
repoName: optionalString(draft, "repoName"),
|
|
268
|
+
attachments: parseDraftAttachments(draft.attachments)
|
|
122
269
|
};
|
|
123
270
|
}
|
|
271
|
+
function parseDraftAttachments(value) {
|
|
272
|
+
if (value === undefined || value === null) {
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
if (!Array.isArray(value)) {
|
|
276
|
+
throw new Error("draft.attachments must be an array when provided.");
|
|
277
|
+
}
|
|
278
|
+
return value.map((entry, index) => {
|
|
279
|
+
const attachment = asObject(entry, `draft.attachments[${index}]`);
|
|
280
|
+
const kind = requiredString(attachment, "kind").trim().toLowerCase();
|
|
281
|
+
if (kind !== "text" && kind !== "image") {
|
|
282
|
+
throw new Error(`draft.attachments[${index}].kind must be text or image.`);
|
|
283
|
+
}
|
|
284
|
+
const textContent = optionalString(attachment, "textContent");
|
|
285
|
+
const contentBase64 = optionalString(attachment, "contentBase64");
|
|
286
|
+
if (kind === "text" && textContent === null) {
|
|
287
|
+
throw new Error(`draft.attachments[${index}].textContent is required for text attachments.`);
|
|
288
|
+
}
|
|
289
|
+
if (kind === "image" && contentBase64 === null) {
|
|
290
|
+
throw new Error(`draft.attachments[${index}].contentBase64 is required for image attachments.`);
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
index: optionalNonNegativeInteger(attachment, "index") ?? index,
|
|
294
|
+
fileName: requiredString(attachment, "fileName"),
|
|
295
|
+
contentType: optionalString(attachment, "contentType") ?? "",
|
|
296
|
+
kind,
|
|
297
|
+
byteCount: optionalNonNegativeInteger(attachment, "byteCount") ?? 0,
|
|
298
|
+
summary: optionalString(attachment, "summary") ?? "",
|
|
299
|
+
textContent,
|
|
300
|
+
contentBase64
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
}
|
|
124
304
|
function parseApiKeySecretGrant(value) {
|
|
125
305
|
if (value === undefined || value === null) {
|
|
126
306
|
return null;
|
|
@@ -133,6 +313,16 @@ function parseApiKeySecretGrant(value) {
|
|
|
133
313
|
expiresAt: requiredString(grant, "expiresAt")
|
|
134
314
|
};
|
|
135
315
|
}
|
|
316
|
+
function parseApiKeySecretGrantHandle(value) {
|
|
317
|
+
if (value === undefined || value === null)
|
|
318
|
+
return null;
|
|
319
|
+
const grant = asObject(value, "apiKeySecretGrantHandle");
|
|
320
|
+
return {
|
|
321
|
+
grantId: requiredString(grant, "grantId"),
|
|
322
|
+
provider: requiredString(grant, "provider"),
|
|
323
|
+
expiresAt: requiredString(grant, "expiresAt")
|
|
324
|
+
};
|
|
325
|
+
}
|
|
136
326
|
function parseServerLocal(value) {
|
|
137
327
|
const serverLocal = asObject(value, "serverLocal");
|
|
138
328
|
return {
|
|
@@ -197,6 +387,27 @@ function parseQaBrowser(value) {
|
|
|
197
387
|
missingTargetReason: optionalString(qaBrowser, "missingTargetReason") ?? optionalString(qaBrowser, "missing_target_reason")
|
|
198
388
|
};
|
|
199
389
|
}
|
|
390
|
+
function parseQaScope(value) {
|
|
391
|
+
if (value === undefined || value === null) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
const qaScope = asObject(value, "qaScope");
|
|
395
|
+
return {
|
|
396
|
+
schema_version: requiredNumber(qaScope, "schema_version"),
|
|
397
|
+
surface: parseOptionalStringArray(qaScope.surface, "qaScope.surface"),
|
|
398
|
+
required_evidence: parseOptionalStringArray(qaScope.required_evidence, "qaScope.required_evidence"),
|
|
399
|
+
not_applicable: parseOptionalStringArray(qaScope.not_applicable, "qaScope.not_applicable"),
|
|
400
|
+
browser_required: optionalBoolean(qaScope, "browser_required") ?? optionalBoolean(qaScope, "browserRequired") ?? false,
|
|
401
|
+
api_required: optionalBoolean(qaScope, "api_required") ?? optionalBoolean(qaScope, "apiRequired") ?? false,
|
|
402
|
+
source: optionalString(qaScope, "source"),
|
|
403
|
+
authority: optionalString(qaScope, "authority"),
|
|
404
|
+
confidence: optionalString(qaScope, "confidence"),
|
|
405
|
+
confirmed_by_user: optionalBoolean(qaScope, "confirmed_by_user") ?? optionalBoolean(qaScope, "confirmedByUser"),
|
|
406
|
+
locked: optionalBoolean(qaScope, "locked"),
|
|
407
|
+
derived_from: parseOptionalObject(qaScope.derived_from ?? qaScope.derivedFrom, "qaScope.derived_from"),
|
|
408
|
+
rationale: optionalString(qaScope, "rationale")
|
|
409
|
+
};
|
|
410
|
+
}
|
|
200
411
|
function parseQaAppLaunchTarget(value) {
|
|
201
412
|
if (value === undefined || value === null) {
|
|
202
413
|
return null;
|
|
@@ -211,6 +422,7 @@ function parseQaAppLaunchTarget(value) {
|
|
|
211
422
|
command: optionalString(launchTarget, "command"),
|
|
212
423
|
working_directory: optionalString(launchTarget, "working_directory"),
|
|
213
424
|
ready_url: optionalString(launchTarget, "ready_url"),
|
|
425
|
+
managed_runtime_port: optionalString(launchTarget, "managed_runtime_port"),
|
|
214
426
|
routes: Array.isArray(routes)
|
|
215
427
|
? routes.map((entry, index) => {
|
|
216
428
|
if (typeof entry !== "string") {
|
|
@@ -260,6 +472,34 @@ function parseArchitectRevision(value) {
|
|
|
260
472
|
feedback: requiredString(revision, "feedback")
|
|
261
473
|
};
|
|
262
474
|
}
|
|
475
|
+
function parseArchitectDependencies(value) {
|
|
476
|
+
if (value === undefined || value === null) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const context = asObject(value, "architectDependencies");
|
|
480
|
+
const prerequisites = context.prerequisites;
|
|
481
|
+
if (!Array.isArray(prerequisites)) {
|
|
482
|
+
throw new Error("architectDependencies.prerequisites must be an array.");
|
|
483
|
+
}
|
|
484
|
+
return {
|
|
485
|
+
baseBranch: requiredString(context, "baseBranch").trim(),
|
|
486
|
+
prerequisites: prerequisites.map((entry, index) => {
|
|
487
|
+
const prerequisite = asObject(entry, `architectDependencies.prerequisites[${index}]`);
|
|
488
|
+
return {
|
|
489
|
+
storyId: requiredString(prerequisite, "storyId").trim(),
|
|
490
|
+
title: requiredString(prerequisite, "title").trim(),
|
|
491
|
+
scheduleIndex: optionalNonNegativeInteger(prerequisite, "scheduleIndex"),
|
|
492
|
+
waveIndex: optionalNonNegativeInteger(prerequisite, "waveIndex"),
|
|
493
|
+
featureScheduleIndex: optionalNonNegativeInteger(prerequisite, "featureScheduleIndex"),
|
|
494
|
+
expectedOutput: optionalString(prerequisite, "expectedOutput"),
|
|
495
|
+
handoffSummary: optionalString(prerequisite, "handoffSummary"),
|
|
496
|
+
dependencyReason: optionalString(prerequisite, "dependencyReason"),
|
|
497
|
+
pullRequestNumber: optionalPositiveInteger(prerequisite, "pullRequestNumber"),
|
|
498
|
+
targetBranch: requiredString(prerequisite, "targetBranch").trim()
|
|
499
|
+
};
|
|
500
|
+
})
|
|
501
|
+
};
|
|
502
|
+
}
|
|
263
503
|
function parseStoryDevelop(value) {
|
|
264
504
|
if (value === undefined || value === null) {
|
|
265
505
|
return null;
|
|
@@ -365,6 +605,58 @@ function parseStoryQaDependencies(value) {
|
|
|
365
605
|
};
|
|
366
606
|
});
|
|
367
607
|
}
|
|
608
|
+
function parseDesignerRefs(value) {
|
|
609
|
+
if (value === undefined || value === null) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
const context = asObject(value, "designerRefs");
|
|
613
|
+
const refs = context.refs;
|
|
614
|
+
if (!Array.isArray(refs)) {
|
|
615
|
+
throw new Error("designerRefs.refs must be an array.");
|
|
616
|
+
}
|
|
617
|
+
return {
|
|
618
|
+
schemaVersion: requiredNumber(context, "schemaVersion"),
|
|
619
|
+
kind: requiredString(context, "kind"),
|
|
620
|
+
ownerType: requiredString(context, "ownerType"),
|
|
621
|
+
ownerId: requiredString(context, "ownerId"),
|
|
622
|
+
projectId: requiredString(context, "projectId"),
|
|
623
|
+
repoId: requiredString(context, "repoId"),
|
|
624
|
+
title: requiredString(context, "title"),
|
|
625
|
+
refs: refs.map((entry, index) => parseDesignerRefAttachment(entry, index))
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
function parseDesignerRefAttachment(value, index) {
|
|
629
|
+
const attachment = asObject(value, `designerRefs.refs[${index}]`);
|
|
630
|
+
return {
|
|
631
|
+
ref: parseDesignerRef(attachment.ref, index),
|
|
632
|
+
reason: optionalString(attachment, "reason") ?? "",
|
|
633
|
+
required: requiredBoolean(attachment, "required"),
|
|
634
|
+
source: optionalString(attachment, "source") ?? "",
|
|
635
|
+
lineageKind: optionalString(attachment, "lineageKind") ?? optionalString(attachment, "lineage_kind") ?? "",
|
|
636
|
+
inheritedFromItemType: optionalString(attachment, "inheritedFromItemType") ?? optionalString(attachment, "inherited_from_item_type"),
|
|
637
|
+
inheritedFromItemId: optionalString(attachment, "inheritedFromItemId") ?? optionalString(attachment, "inherited_from_item_id"),
|
|
638
|
+
inheritedFromDesignerRefId: optionalString(attachment, "inheritedFromDesignerRefId") ?? optionalString(attachment, "inherited_from_designer_ref_id"),
|
|
639
|
+
addedByLane: optionalString(attachment, "addedByLane") ?? optionalString(attachment, "added_by_lane") ?? "",
|
|
640
|
+
sortOrder: requiredNumber(attachment, "sortOrder"),
|
|
641
|
+
createdAt: requiredString(attachment, "createdAt")
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function parseDesignerRef(value, index) {
|
|
645
|
+
const designerRef = asObject(value, `designerRefs.refs[${index}].ref`);
|
|
646
|
+
return {
|
|
647
|
+
id: requiredString(designerRef, "id"),
|
|
648
|
+
projectId: requiredString(designerRef, "projectId"),
|
|
649
|
+
repoId: requiredString(designerRef, "repoId"),
|
|
650
|
+
refKey: requiredString(designerRef, "refKey"),
|
|
651
|
+
kind: requiredString(designerRef, "kind"),
|
|
652
|
+
path: requiredString(designerRef, "path"),
|
|
653
|
+
anchor: optionalString(designerRef, "anchor"),
|
|
654
|
+
title: optionalString(designerRef, "title") ?? "",
|
|
655
|
+
contentHash: requiredString(designerRef, "contentHash"),
|
|
656
|
+
commitSha: requiredString(designerRef, "commitSha"),
|
|
657
|
+
createdAt: requiredString(designerRef, "createdAt")
|
|
658
|
+
};
|
|
659
|
+
}
|
|
368
660
|
function parseStringArray(value, label) {
|
|
369
661
|
if (!Array.isArray(value)) {
|
|
370
662
|
throw new Error(`${label} must be an array.`);
|
|
@@ -376,6 +668,18 @@ function parseStringArray(value, label) {
|
|
|
376
668
|
return entry.trim();
|
|
377
669
|
});
|
|
378
670
|
}
|
|
671
|
+
function parseOptionalStringArray(value, label) {
|
|
672
|
+
if (value === undefined || value === null) {
|
|
673
|
+
return [];
|
|
674
|
+
}
|
|
675
|
+
return parseStringArray(value, label);
|
|
676
|
+
}
|
|
677
|
+
function parseOptionalObject(value, label) {
|
|
678
|
+
if (value === undefined || value === null) {
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
return asObject(value, label);
|
|
682
|
+
}
|
|
379
683
|
function parseArtifacts(value) {
|
|
380
684
|
if (value === undefined || value === null) {
|
|
381
685
|
return [];
|
|
@@ -397,6 +701,34 @@ function parseArtifacts(value) {
|
|
|
397
701
|
};
|
|
398
702
|
});
|
|
399
703
|
}
|
|
704
|
+
function parsePriorPhaseArtifacts(value) {
|
|
705
|
+
if (value === undefined || value === null) {
|
|
706
|
+
return [];
|
|
707
|
+
}
|
|
708
|
+
if (!Array.isArray(value)) {
|
|
709
|
+
throw new Error("priorPhaseArtifacts must be an array when provided.");
|
|
710
|
+
}
|
|
711
|
+
return value.map((entry, index) => {
|
|
712
|
+
const artifact = asObject(entry, `priorPhaseArtifacts[${index}]`);
|
|
713
|
+
const phase = requiredString(artifact, "phase").trim().toLowerCase().replace(/-/g, "_");
|
|
714
|
+
if (phase !== "implementation" && phase !== "self_review" && phase !== "validation") {
|
|
715
|
+
throw new Error(`priorPhaseArtifacts[${index}].phase must be implementation, self_review, or validation.`);
|
|
716
|
+
}
|
|
717
|
+
return {
|
|
718
|
+
workItemId: requiredString(artifact, "workItemId"),
|
|
719
|
+
artifactId: requiredString(artifact, "artifactId"),
|
|
720
|
+
cycleRunId: requiredString(artifact, "cycleRunId"),
|
|
721
|
+
phase,
|
|
722
|
+
status: requiredString(artifact, "status"),
|
|
723
|
+
producedAt: requiredString(artifact, "producedAt"),
|
|
724
|
+
sourcePath: requiredString(artifact, "sourcePath"),
|
|
725
|
+
verdictJson: requiredString(artifact, "verdictJson"),
|
|
726
|
+
report: optionalString(artifact, "report") ?? "",
|
|
727
|
+
verdictContentHash: requiredString(artifact, "verdictContentHash").toLowerCase(),
|
|
728
|
+
reportContentHash: requiredString(artifact, "reportContentHash").toLowerCase()
|
|
729
|
+
};
|
|
730
|
+
});
|
|
731
|
+
}
|
|
400
732
|
function asObject(value, label) {
|
|
401
733
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
402
734
|
throw new Error(`${label} must be an object.`);
|
|
@@ -447,6 +779,16 @@ function optionalPositiveInteger(source, key) {
|
|
|
447
779
|
}
|
|
448
780
|
return value;
|
|
449
781
|
}
|
|
782
|
+
function optionalNonNegativeInteger(source, key) {
|
|
783
|
+
const value = source[key];
|
|
784
|
+
if (value === undefined || value === null) {
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
788
|
+
throw new Error(`${key} must be a non-negative integer when provided.`);
|
|
789
|
+
}
|
|
790
|
+
return value;
|
|
791
|
+
}
|
|
450
792
|
function requiredNumber(source, key) {
|
|
451
793
|
const value = source[key];
|
|
452
794
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
@@ -454,3 +796,10 @@ function requiredNumber(source, key) {
|
|
|
454
796
|
}
|
|
455
797
|
return value;
|
|
456
798
|
}
|
|
799
|
+
function boundedInteger(source, key, minimum, maximum) {
|
|
800
|
+
const value = requiredNumber(source, key);
|
|
801
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
|
|
802
|
+
throw new Error(`${key} must be an integer from ${minimum} through ${maximum}.`);
|
|
803
|
+
}
|
|
804
|
+
return value;
|
|
805
|
+
}
|
package/dist/shared/path/path.js
CHANGED
|
@@ -4,7 +4,9 @@ export function isSubPath(root, candidate) {
|
|
|
4
4
|
const normalizedRoot = path.resolve(root);
|
|
5
5
|
const normalizedCandidate = path.resolve(candidate);
|
|
6
6
|
const relative = path.relative(normalizedRoot, normalizedCandidate);
|
|
7
|
-
return relative === "" || (
|
|
7
|
+
return relative === "" || (relative !== ".."
|
|
8
|
+
&& !relative.startsWith(`..${path.sep}`)
|
|
9
|
+
&& !path.isAbsolute(relative));
|
|
8
10
|
}
|
|
9
11
|
export async function resolveExistingDirectoryPath(inputPath) {
|
|
10
12
|
const stat = await fs.stat(inputPath);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HostProcessSupervisorMetadata } from "./host-process-supervisor.js";
|
|
2
|
+
export type HostProcessRecoveryOutcome = "absent" | "terminated" | "pid_reused" | "unverifiable";
|
|
3
|
+
export interface HostProcessRecovery {
|
|
4
|
+
recover(metadata: HostProcessSupervisorMetadata): Promise<HostProcessRecoveryOutcome>;
|
|
5
|
+
}
|
|
6
|
+
/** Exact, birth-marker-fenced recovery for a process tree left by an old bridge. */
|
|
7
|
+
export declare class ExactHostProcessRecovery implements HostProcessRecovery {
|
|
8
|
+
private readonly platform;
|
|
9
|
+
private readonly graceMs;
|
|
10
|
+
constructor(platform?: NodeJS.Platform, graceMs?: number);
|
|
11
|
+
recover(metadata: HostProcessSupervisorMetadata): Promise<HostProcessRecoveryOutcome>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { captureHostProcessIdentity } from "./host-process-supervisor.js";
|
|
2
|
+
/** Exact, birth-marker-fenced recovery for a process tree left by an old bridge. */
|
|
3
|
+
export class ExactHostProcessRecovery {
|
|
4
|
+
platform;
|
|
5
|
+
graceMs;
|
|
6
|
+
constructor(platform = process.platform, graceMs = 2_000) {
|
|
7
|
+
this.platform = platform;
|
|
8
|
+
this.graceMs = graceMs;
|
|
9
|
+
}
|
|
10
|
+
async recover(metadata) {
|
|
11
|
+
if (!processExists(metadata.rootPid))
|
|
12
|
+
return "absent";
|
|
13
|
+
if (!metadata.rootIdentity)
|
|
14
|
+
return "unverifiable";
|
|
15
|
+
const currentIdentity = captureHostProcessIdentity(metadata.rootPid, this.platform);
|
|
16
|
+
if (!currentIdentity)
|
|
17
|
+
return processExists(metadata.rootPid) ? "unverifiable" : "absent";
|
|
18
|
+
if (currentIdentity !== metadata.rootIdentity)
|
|
19
|
+
return "pid_reused";
|
|
20
|
+
if (this.platform === "win32") {
|
|
21
|
+
signalExactProcess(metadata.rootPid, "SIGTERM");
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
signalExactProcessGroup(metadata.rootPid, "SIGTERM");
|
|
25
|
+
}
|
|
26
|
+
await waitForExit(metadata.rootPid, this.graceMs);
|
|
27
|
+
if (processExists(metadata.rootPid)) {
|
|
28
|
+
if (captureHostProcessIdentity(metadata.rootPid, this.platform) !== metadata.rootIdentity) {
|
|
29
|
+
return "pid_reused";
|
|
30
|
+
}
|
|
31
|
+
if (this.platform === "win32") {
|
|
32
|
+
signalExactProcess(metadata.rootPid, "SIGKILL");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
signalExactProcessGroup(metadata.rootPid, "SIGKILL");
|
|
36
|
+
}
|
|
37
|
+
await waitForExit(metadata.rootPid, this.graceMs);
|
|
38
|
+
}
|
|
39
|
+
if (processExists(metadata.rootPid)
|
|
40
|
+
&& captureHostProcessIdentity(metadata.rootPid, this.platform) === metadata.rootIdentity) {
|
|
41
|
+
throw new Error("host_process_recovery_degraded: exact supervised process tree did not stop.");
|
|
42
|
+
}
|
|
43
|
+
return "terminated";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function processExists(pid) {
|
|
47
|
+
try {
|
|
48
|
+
process.kill(pid, 0);
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return error.code === "EPERM";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function signalExactProcess(pid, signal) {
|
|
56
|
+
try {
|
|
57
|
+
process.kill(pid, signal);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error.code !== "ESRCH")
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function signalExactProcessGroup(pid, signal) {
|
|
65
|
+
try {
|
|
66
|
+
process.kill(-pid, signal);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error.code !== "ESRCH")
|
|
70
|
+
throw error;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async function waitForExit(pid, timeoutMs) {
|
|
74
|
+
const deadline = Date.now() + timeoutMs;
|
|
75
|
+
while (Date.now() < deadline && processExists(pid)) {
|
|
76
|
+
await new Promise(resolve => setTimeout(resolve, 25));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
export type HostProcessSupervisorStrategy = "windows_job_object" | "unix_process_group";
|
|
3
|
+
export interface HostProcessSupervisionRequest {
|
|
4
|
+
readonly command: string;
|
|
5
|
+
readonly args: readonly string[];
|
|
6
|
+
readonly cwd: string;
|
|
7
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
8
|
+
}
|
|
9
|
+
export interface HostProcessSupervisedLaunch {
|
|
10
|
+
readonly command: string;
|
|
11
|
+
readonly args: readonly string[];
|
|
12
|
+
readonly detached: boolean;
|
|
13
|
+
readonly supervisorId: string;
|
|
14
|
+
readonly strategy: HostProcessSupervisorStrategy;
|
|
15
|
+
readonly metadataPath: string;
|
|
16
|
+
readonly payloadPath?: string;
|
|
17
|
+
readonly readyPath?: string;
|
|
18
|
+
readonly startGrantPath?: string;
|
|
19
|
+
readonly commandDigest: string;
|
|
20
|
+
}
|
|
21
|
+
export interface HostProcessProviderReady {
|
|
22
|
+
readonly schemaVersion: 1;
|
|
23
|
+
readonly supervisorId: string;
|
|
24
|
+
readonly rootPid?: number;
|
|
25
|
+
readonly rootIdentity?: string | null;
|
|
26
|
+
readonly providerPid: number;
|
|
27
|
+
readonly providerCreatedAt: string;
|
|
28
|
+
readonly providerIdentity?: string | null;
|
|
29
|
+
readonly startAttempt: number;
|
|
30
|
+
}
|
|
31
|
+
export interface HostProcessSupervisorMetadata {
|
|
32
|
+
readonly schemaVersion: 1;
|
|
33
|
+
readonly supervisorId: string;
|
|
34
|
+
readonly strategy: HostProcessSupervisorStrategy;
|
|
35
|
+
readonly rootPid: number;
|
|
36
|
+
readonly rootCreatedAt: string;
|
|
37
|
+
readonly rootIdentity?: string | null;
|
|
38
|
+
readonly commandDigest: string;
|
|
39
|
+
readonly worktreePath: string;
|
|
40
|
+
readonly runtimeLeaseId: string;
|
|
41
|
+
readonly dispatchAttemptId: string;
|
|
42
|
+
readonly fencingToken: string;
|
|
43
|
+
readonly bridgePid: number;
|
|
44
|
+
readonly providerPid?: number;
|
|
45
|
+
readonly providerCreatedAt?: string;
|
|
46
|
+
readonly providerIdentity?: string | null;
|
|
47
|
+
readonly providerStartAttempt?: number;
|
|
48
|
+
}
|
|
49
|
+
export declare function resolveHostProcessSupervisedLaunch(request: HostProcessSupervisionRequest, resolvedCommand: string, resolvedArgs: readonly string[], platform?: NodeJS.Platform): HostProcessSupervisedLaunch | null;
|
|
50
|
+
export declare function persistHostProcessSupervisorMetadata(launch: HostProcessSupervisedLaunch, request: HostProcessSupervisionRequest, rootPid: number, rootCreatedAt: string, providerReady?: HostProcessProviderReady): HostProcessSupervisorMetadata;
|
|
51
|
+
/**
|
|
52
|
+
* Captures an OS-issued process birth marker. Recovery compares this marker
|
|
53
|
+
* before signalling a persisted PID so PID reuse can never redirect cleanup
|
|
54
|
+
* at an unrelated process.
|
|
55
|
+
*/
|
|
56
|
+
export declare function captureHostProcessIdentity(pid: number, platform?: NodeJS.Platform): string | null;
|
|
57
|
+
export declare function terminateHostProcessTree(child: ChildProcess, launch: HostProcessSupervisedLaunch | null, graceMs?: number): Promise<void>;
|