@ours.network/fleet 1.2.0-nightly.53 → 1.2.0-nightly.55
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 +22 -12
- package/dist/agent-ours/bridge.js +10 -3
- package/dist/agent-ours/file-rpc.d.ts +8 -0
- package/dist/agent-ours/file-rpc.js +11 -1
- package/dist/agent-ours/harness.js +47 -3
- package/dist/agent-ours/mcp-endpoint.d.ts +5 -0
- package/dist/agent-ours/mcp-endpoint.js +4 -0
- package/dist/agent-ours/service.d.ts +6 -1
- package/dist/agent-ours/service.js +73 -8
- package/dist/application/conversation-history.d.ts +2 -0
- package/dist/application/conversation-history.js +25 -2
- package/dist/application/log-service.js +8 -8
- package/dist/application/role-creation-service.js +2 -1
- package/dist/application/role-removal-service.js +7 -1
- package/dist/application/role-repository.js +17 -0
- package/dist/application/supervisor-ours-tools.js +3 -1
- package/dist/application/task-layouts.js +12 -2
- package/dist/application/task-room-service.js +19 -17
- package/dist/application/types.d.ts +2 -0
- package/dist/build-info.json +4 -4
- package/dist/cli.js +31 -3
- package/dist/config.d.ts +11 -0
- package/dist/config.js +13 -2
- package/dist/file-delivery/reader.d.ts +17 -0
- package/dist/file-delivery/reader.js +94 -0
- package/dist/file-delivery/store.d.ts +15 -0
- package/dist/file-delivery/store.js +124 -0
- package/dist/file-delivery/types.d.ts +19 -0
- package/dist/file-delivery/types.js +1 -0
- package/dist/harness/agent-session.d.ts +2 -0
- package/dist/harness/claude-code-session.js +1 -1
- package/dist/harness/codex-app-server-proxy.js +6 -2
- package/dist/harness/codex-file-inventory.d.ts +15 -0
- package/dist/harness/codex-file-inventory.js +113 -0
- package/dist/harness/codex-session.js +2 -2
- package/dist/harness/codex.js +2 -1
- package/dist/isolation/policy.js +4 -1
- package/dist/managed-recovery.d.ts +13 -0
- package/dist/managed-recovery.js +31 -0
- package/dist/ops.d.ts +2 -0
- package/dist/ops.js +15 -2
- package/dist/rooms-tasks/cli.js +21 -0
- package/dist/rooms-tasks/close.d.ts +2 -0
- package/dist/rooms-tasks/close.js +66 -1
- package/dist/rooms-tasks/deletion.js +10 -0
- package/dist/rooms-tasks/erasure.js +4 -2
- package/dist/rooms-tasks/layout-member-retirement.d.ts +10 -0
- package/dist/rooms-tasks/layout-member-retirement.js +90 -0
- package/dist/rooms-tasks/layout-service.d.ts +1 -0
- package/dist/rooms-tasks/layout-service.js +31 -13
- package/dist/rooms-tasks/layout.d.ts +7 -0
- package/dist/rooms-tasks/layout.js +35 -0
- package/dist/rooms-tasks/legacy-task-member.d.ts +19 -0
- package/dist/rooms-tasks/legacy-task-member.js +116 -0
- package/dist/rooms-tasks/member-ownership.d.ts +5 -0
- package/dist/rooms-tasks/member-ownership.js +40 -0
- package/dist/rooms-tasks/provision.js +26 -1
- package/dist/rooms-tasks/recovery.d.ts +19 -0
- package/dist/rooms-tasks/recovery.js +110 -0
- package/dist/rooms-tasks/task-service-retirement.d.ts +11 -0
- package/dist/rooms-tasks/task-service-retirement.js +21 -0
- package/dist/rooms-tasks/task-state.d.ts +1 -0
- package/dist/rooms-tasks/task-state.js +16 -1
- package/dist/rooms-tasks/types.d.ts +3 -0
- package/dist/rooms-tasks/workspace.d.ts +2 -0
- package/dist/rooms-tasks/workspace.js +5 -0
- package/dist/runner.d.ts +6 -0
- package/dist/runner.js +161 -22
- package/dist/session/acp.d.ts +5 -0
- package/dist/session/acp.js +68 -8
- package/dist/session/arbiter.d.ts +5 -0
- package/dist/session/arbiter.js +16 -2
- package/dist/session/codex-app-server.d.ts +1 -0
- package/dist/session/codex-app-server.js +5 -0
- package/dist/session/conversation-types.d.ts +4 -2
- package/dist/session/types.d.ts +3 -0
- package/dist/spawn.d.ts +5 -1
- package/dist/spawn.js +32 -3
- package/dist/startup-readiness.d.ts +1 -1
- package/dist/startup-readiness.js +3 -3
- package/dist/supervisor/adoption.d.ts +8 -0
- package/dist/supervisor/adoption.js +78 -0
- package/dist/supervisor/catalog.d.ts +62 -0
- package/dist/supervisor/catalog.js +254 -0
- package/dist/supervisor/fleet.d.ts +8 -0
- package/dist/supervisor/fleet.js +89 -0
- package/dist/supervisor/index.js +3 -6
- package/dist/supervisor/launchd.d.ts +1 -1
- package/dist/supervisor/launchd.js +24 -12
- package/dist/supervisor/legacy.d.ts +35 -0
- package/dist/supervisor/legacy.js +524 -0
- package/dist/supervisor/manager.d.ts +15 -0
- package/dist/supervisor/manager.js +258 -0
- package/dist/supervisor/scope.d.ts +4 -0
- package/dist/supervisor/scope.js +10 -0
- package/dist/supervisor/systemd.d.ts +2 -2
- package/dist/supervisor/systemd.js +14 -14
- package/dist/task-supervision.d.ts +9 -0
- package/dist/task-supervision.js +145 -0
- package/dist/temp-lifecycle.d.ts +17 -7
- package/dist/temp-lifecycle.js +85 -53
- package/dist/temp-supervisor-recovery.d.ts +1 -1
- package/dist/temp-supervisor-recovery.js +2 -2
- package/dist/web/server.js +24 -0
- package/docs/acp-files.md +102 -0
- package/docs/fleet-migration.md +54 -0
- package/docs/task-workspaces.md +26 -0
- package/package.json +7 -3
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type Exec } from '../exec.js';
|
|
2
|
+
import type { SupervisorBackend } from './types.js';
|
|
3
|
+
export declare function fleetHostBackend(exec?: Exec, platform?: NodeJS.Platform): SupervisorBackend;
|
|
4
|
+
/** Registration only starts an explicitly installed parent; it cannot repoint
|
|
5
|
+
* the fleet at the invoking task/development binary or rewrite user settings. */
|
|
6
|
+
export declare function ensureFleetParent(exec?: Exec, platform?: NodeJS.Platform): Promise<void>;
|
|
7
|
+
/** OS operations refer only to the Fleet parent; member operations refer only to its catalog. */
|
|
8
|
+
export declare function makeFleetBackend(exec?: Exec, platform?: NodeJS.Platform): SupervisorBackend;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { agentDir } from '../paths.js';
|
|
4
|
+
import { realExec } from '../exec.js';
|
|
5
|
+
import { home } from '../paths.js';
|
|
6
|
+
import { makeSystemdBackend } from './systemd.js';
|
|
7
|
+
import { makeLaunchdBackend } from './launchd.js';
|
|
8
|
+
import { catalogLiveness, memberKey, readMember, registerMember, stopMember, unregisterMember, waitMember } from './catalog.js';
|
|
9
|
+
export function fleetHostBackend(exec = realExec, platform = process.platform) {
|
|
10
|
+
if (platform === 'linux')
|
|
11
|
+
return makeSystemdBackend(exec);
|
|
12
|
+
if (platform === 'darwin')
|
|
13
|
+
return makeLaunchdBackend(exec);
|
|
14
|
+
throw Error('Fleet service requires Linux or macOS');
|
|
15
|
+
}
|
|
16
|
+
/** Registration only starts an explicitly installed parent; it cannot repoint
|
|
17
|
+
* the fleet at the invoking task/development binary or rewrite user settings. */
|
|
18
|
+
export async function ensureFleetParent(exec = realExec, platform = process.platform) {
|
|
19
|
+
const host = fleetHostBackend(exec, platform);
|
|
20
|
+
const path = platform === 'linux' ? join(home(), '.config/systemd/user/ours-fleet.service')
|
|
21
|
+
: join(home(), 'Library/LaunchAgents/network.ours.fleet.plist');
|
|
22
|
+
if (!existsSync(path))
|
|
23
|
+
throw Error('FLEET_SERVICE_NOT_INSTALLED: run ours-fleet init');
|
|
24
|
+
const live = await host.liveness('fleet');
|
|
25
|
+
if (live.state === 'unknown')
|
|
26
|
+
throw Error('FLEET_SERVICE_LIVENESS_UNKNOWN');
|
|
27
|
+
if (live.state === 'stopped')
|
|
28
|
+
await host.install('fleet', '');
|
|
29
|
+
}
|
|
30
|
+
/** OS operations refer only to the Fleet parent; member operations refer only to its catalog. */
|
|
31
|
+
export function makeFleetBackend(exec = realExec, platform = process.platform) {
|
|
32
|
+
const host = fleetHostBackend(exec, platform);
|
|
33
|
+
return {
|
|
34
|
+
id: host.id,
|
|
35
|
+
async init(binPath) {
|
|
36
|
+
const messages = await host.init(binPath);
|
|
37
|
+
const { adoptConfiguredFleet } = await import('./adoption.js');
|
|
38
|
+
await adoptConfiguredFleet(binPath, exec, platform);
|
|
39
|
+
return messages;
|
|
40
|
+
},
|
|
41
|
+
async install(name, binPath) {
|
|
42
|
+
const { adoptConfiguredFleet } = await import('./adoption.js');
|
|
43
|
+
let configPath;
|
|
44
|
+
try {
|
|
45
|
+
configPath = readFileSync(join(agentDir(name), '.config-path'), 'utf8').trim() || undefined;
|
|
46
|
+
}
|
|
47
|
+
catch { /* a new state directory may not carry a config marker yet */ }
|
|
48
|
+
await adoptConfiguredFleet(binPath, exec, platform, configPath, name);
|
|
49
|
+
const result = await registerMember({ name, kind: 'permanent', dir: agentDir(name) });
|
|
50
|
+
try {
|
|
51
|
+
await waitMember(result.member.key, 'running', { exec });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
// Preserve existing intent. New registration rollback is exact and waits
|
|
55
|
+
// for process quiescence before its creation evidence can be discarded.
|
|
56
|
+
if (result.created)
|
|
57
|
+
await unregisterMember(result.member.key, { exec });
|
|
58
|
+
throw error;
|
|
59
|
+
}
|
|
60
|
+
return { created: result.created, detail: `Fleet member ${name} registered` };
|
|
61
|
+
},
|
|
62
|
+
async start(name) {
|
|
63
|
+
const key = memberKey(name, 'permanent'), member = readMember(key);
|
|
64
|
+
if (!member)
|
|
65
|
+
throw Error('Fleet member not registered; use up');
|
|
66
|
+
await registerMember(member);
|
|
67
|
+
await ensureFleetParent(exec, platform);
|
|
68
|
+
await waitMember(key, 'running', { exec });
|
|
69
|
+
},
|
|
70
|
+
async stop(name) { await stopMember(memberKey(name, 'permanent'), { exec }); },
|
|
71
|
+
async restart(name) {
|
|
72
|
+
await this.stop(name);
|
|
73
|
+
await this.start(name);
|
|
74
|
+
},
|
|
75
|
+
async status(name) { return (await this.liveness(name)).detail; },
|
|
76
|
+
liveness(name) {
|
|
77
|
+
const key = memberKey(name, 'permanent');
|
|
78
|
+
if (!readMember(key) && existsSync(agentDir(name)))
|
|
79
|
+
return Promise.resolve({ state: 'unknown', detail: 'unmigrated member; preserving context until legacy inspection' });
|
|
80
|
+
return catalogLiveness(key, exec);
|
|
81
|
+
},
|
|
82
|
+
async inspect(name) { return { backend: host.id, ...await this.liveness(name), nativeState: 'fleet-member' }; },
|
|
83
|
+
async uninstall(name) {
|
|
84
|
+
const { retirePermanentRegistration } = await import('./adoption.js');
|
|
85
|
+
return { removed: await retirePermanentRegistration(name, exec), detail: `Fleet member ${name} unregistered` };
|
|
86
|
+
},
|
|
87
|
+
logsArgs(name, follow) { return { cmd: 'tail', args: [follow ? '-f' : '-n', ...(follow ? [] : ['200']), join(agentDir(name), 'supervisor.log')] }; },
|
|
88
|
+
};
|
|
89
|
+
}
|
package/dist/supervisor/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { realExec } from '../exec.js';
|
|
2
|
-
import {
|
|
3
|
-
import { makeLaunchdBackend } from './launchd.js';
|
|
2
|
+
import { makeFleetBackend } from './fleet.js';
|
|
4
3
|
import { makeNoneBackend } from './none.js';
|
|
5
4
|
export { makeSystemdBackend, unitFor } from './systemd.js';
|
|
6
5
|
export { makeLaunchdBackend, labelFor } from './launchd.js';
|
|
@@ -8,9 +7,7 @@ export { makeNoneBackend } from './none.js';
|
|
|
8
7
|
export function pickBackend(exec = realExec, platform = process.platform) {
|
|
9
8
|
if (process.env.OURS_FLEET_SUPERVISOR === 'none')
|
|
10
9
|
return makeNoneBackend(exec);
|
|
11
|
-
if (platform === 'darwin')
|
|
12
|
-
return
|
|
13
|
-
if (platform === 'linux')
|
|
14
|
-
return makeSystemdBackend(exec);
|
|
10
|
+
if (platform === 'darwin' || platform === 'linux')
|
|
11
|
+
return makeFleetBackend(exec, platform);
|
|
15
12
|
throw new Error(`unsupported platform '${platform}' (linux and darwin only)`);
|
|
16
13
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Exec } from '../exec.js';
|
|
2
2
|
import type { SupervisorBackend } from './types.js';
|
|
3
|
-
export declare const labelFor: (
|
|
3
|
+
export declare const labelFor: (_name: string) => string;
|
|
4
4
|
/**
|
|
5
5
|
* What `launchctl print` said about a job, parsed ONCE so that the two questions
|
|
6
6
|
* asked of it cannot drift apart. They are not the same question:
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { assertNativeFleetScope } from './scope.js';
|
|
1
2
|
import { clientConfigPath } from '../client-profile.js';
|
|
2
3
|
import { existsSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
3
4
|
import { join } from 'node:path';
|
|
4
5
|
import { home, logsRoot } from '../paths.js';
|
|
5
6
|
import { realExec } from '../exec.js';
|
|
6
|
-
export const labelFor = (
|
|
7
|
+
export const labelFor = (_name) => 'network.ours.fleet';
|
|
7
8
|
/**
|
|
8
9
|
* The spelling of the last-exit line is not stable across macOS releases
|
|
9
10
|
* (`last exit code`, `last exit status`, `last exit reason`), so match the
|
|
@@ -22,16 +23,17 @@ const xml = (value) => value
|
|
|
22
23
|
.replaceAll('"', '"')
|
|
23
24
|
.replaceAll("'", ''');
|
|
24
25
|
function plist(name, binPath) {
|
|
25
|
-
const log = join(logsRoot(),
|
|
26
|
+
const log = join(logsRoot(), 'fleet.log');
|
|
26
27
|
const config = clientConfigPath(process.env);
|
|
28
|
+
const env = { OURS_CONFIG: config, ...Object.fromEntries(['PATH', 'OURS_FLEET_HOME', 'OURS_FLEET_SOCKET_ROOT', 'CODEX_HOME', 'CODEX_PATH'].flatMap(key => process.env[key] !== undefined ? [[key, process.env[key]]] : [])) };
|
|
27
29
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
28
30
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
29
31
|
<plist version="1.0">
|
|
30
32
|
<dict>
|
|
31
33
|
<key>Label</key><string>${labelFor(name)}</string>
|
|
32
34
|
<key>ProgramArguments</key>
|
|
33
|
-
<array><string>${
|
|
34
|
-
${
|
|
35
|
+
<array><string>${xml(process.execPath)}</string><string>${xml(binPath)}</string><string>_run-fleet</string></array>
|
|
36
|
+
${` <key>EnvironmentVariables</key><dict>${Object.entries(env).map(([key, value]) => `<key>${key}</key><string>${xml(value)}</string>`).join('')}</dict>\n`} <!-- The runner owns the child-session restart loop. launchd must only
|
|
35
37
|
recover the runner PROCESS crashing: a bare KeepAlive would resume the
|
|
36
38
|
uncounted relaunch loop and restart a deliberately held-down agent. -->
|
|
37
39
|
<key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>
|
|
@@ -80,6 +82,7 @@ export function makeLaunchdBackend(exec = realExec, uid = process.getuid?.() ??
|
|
|
80
82
|
const domain = `gui/${uid}`;
|
|
81
83
|
/** Read `launchctl print` once; both callers classify it for their own question. */
|
|
82
84
|
const printJob = async (name) => {
|
|
85
|
+
assertNativeFleetScope(exec);
|
|
83
86
|
const r = await exec('launchctl', ['print', `${domain}/${labelFor(name)}`]);
|
|
84
87
|
const out = `${r.stdout}\n${r.stderr}`;
|
|
85
88
|
if (r.code !== 0)
|
|
@@ -97,21 +100,26 @@ export function makeLaunchdBackend(exec = realExec, uid = process.getuid?.() ??
|
|
|
97
100
|
};
|
|
98
101
|
return {
|
|
99
102
|
id: 'launchd',
|
|
100
|
-
async init() {
|
|
103
|
+
async init(binPath) {
|
|
104
|
+
assertNativeFleetScope(exec);
|
|
101
105
|
mkdirSync(agentsDir(), { recursive: true });
|
|
102
106
|
mkdirSync(logsRoot(), { recursive: true });
|
|
107
|
+
writeFileSync(plistPath('fleet'), plist('fleet', binPath));
|
|
103
108
|
return [
|
|
104
109
|
`LaunchAgents dir ready: ${agentsDir()}`,
|
|
105
110
|
'note: launchd agents start at login (macOS has no linger equivalent)',
|
|
106
111
|
];
|
|
107
112
|
},
|
|
108
113
|
async install(name, binPath) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const existed =
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
assertNativeFleetScope(exec);
|
|
115
|
+
if (!existsSync(plistPath(name)))
|
|
116
|
+
throw Error('FLEET_SERVICE_NOT_INSTALLED: run ours-fleet init');
|
|
117
|
+
const existed = true;
|
|
118
|
+
const loaded = await printJob(name);
|
|
119
|
+
if (loaded.loaded)
|
|
120
|
+
return { created: !existed, detail: 'Fleet service already loaded' };
|
|
121
|
+
if (!loaded.notFound)
|
|
122
|
+
throw new Error('Fleet launchd liveness unknown');
|
|
115
123
|
// Undo only what WE wrote. A plist that was already there belongs to
|
|
116
124
|
// whoever put it there, and rollback may never remove it.
|
|
117
125
|
const undo = async () => {
|
|
@@ -154,16 +162,19 @@ export function makeLaunchdBackend(exec = realExec, uid = process.getuid?.() ??
|
|
|
154
162
|
: { created: true, detail: `installed ${labelFor(name)} (${start.detail})` };
|
|
155
163
|
},
|
|
156
164
|
async start(name) {
|
|
165
|
+
assertNativeFleetScope(exec);
|
|
157
166
|
const r = await exec('launchctl', ['bootstrap', domain, plistPath(name)]);
|
|
158
167
|
if (r.code !== 0)
|
|
159
168
|
await exec('launchctl', ['kickstart', `${domain}/${labelFor(name)}`]);
|
|
160
169
|
},
|
|
161
170
|
async stop(name) {
|
|
171
|
+
assertNativeFleetScope(exec);
|
|
162
172
|
const r = await exec('launchctl', ['bootout', `${domain}/${labelFor(name)}`]);
|
|
163
173
|
if (r.code !== 0)
|
|
164
174
|
throw new Error(`launchctl bootout ${labelFor(name)} failed: ${r.stderr.trim()}`);
|
|
165
175
|
},
|
|
166
176
|
async restart(name) {
|
|
177
|
+
assertNativeFleetScope(exec);
|
|
167
178
|
const r = await exec('launchctl', ['kickstart', '-k', `${domain}/${labelFor(name)}`]);
|
|
168
179
|
if (r.code !== 0)
|
|
169
180
|
throw new Error(`launchctl kickstart ${labelFor(name)} failed: ${r.stderr.trim()}`);
|
|
@@ -203,6 +214,7 @@ export function makeLaunchdBackend(exec = realExec, uid = process.getuid?.() ??
|
|
|
203
214
|
};
|
|
204
215
|
},
|
|
205
216
|
async uninstall(name) {
|
|
217
|
+
assertNativeFleetScope(exec);
|
|
206
218
|
const existed = existsSync(plistPath(name));
|
|
207
219
|
await exec('launchctl', ['bootout', `${domain}/${labelFor(name)}`]); // idempotent
|
|
208
220
|
rmSync(plistPath(name), { force: true });
|
|
@@ -211,7 +223,7 @@ export function makeLaunchdBackend(exec = realExec, uid = process.getuid?.() ??
|
|
|
211
223
|
: { removed: false, detail: `${labelFor(name)} was not installed` };
|
|
212
224
|
},
|
|
213
225
|
logsArgs(name, follow) {
|
|
214
|
-
const log = join(logsRoot(),
|
|
226
|
+
const log = join(logsRoot(), 'fleet.log');
|
|
215
227
|
return { cmd: 'tail', args: follow ? ['-f', log] : ['-n', '200', log] };
|
|
216
228
|
},
|
|
217
229
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Exec } from '../exec.js';
|
|
2
|
+
import type { ResolvedRole } from '../config.js';
|
|
3
|
+
type Desired = 'running' | 'stopped';
|
|
4
|
+
export interface LegacyReadinessGate {
|
|
5
|
+
path: string;
|
|
6
|
+
argv: string[];
|
|
7
|
+
timeoutStartSec: number;
|
|
8
|
+
restartSec: number;
|
|
9
|
+
}
|
|
10
|
+
export interface LegacyPermanentMigrationInput {
|
|
11
|
+
roles: Pick<ResolvedRole, 'name' | 'identity'>[];
|
|
12
|
+
binPath: string;
|
|
13
|
+
platform: NodeJS.Platform;
|
|
14
|
+
configPath?: string;
|
|
15
|
+
exec?: Exec;
|
|
16
|
+
/** All-role preflight precedes this hook. Ensure the singleton is running and
|
|
17
|
+
* preserves every gate before returning; failure prevents native retirement. */
|
|
18
|
+
prepareParent(gates: LegacyReadinessGate[]): Promise<void>;
|
|
19
|
+
/** Isolated process-environment seam; production reads only OURS_FLEET_HOME. */
|
|
20
|
+
processHome?(pid: number): string;
|
|
21
|
+
/** Create if absent; an existing registration's desired state must survive retry. */
|
|
22
|
+
register(name: string, desired: Desired, configPath?: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface LegacyPermanentMigrationResult {
|
|
25
|
+
name: string;
|
|
26
|
+
status: 'migrated' | 'already-migrated' | 'not-installed' | 'disabled';
|
|
27
|
+
}
|
|
28
|
+
/** Start the common parent after all-role preflight and before retirement. Only configured,
|
|
29
|
+
* identity-proven legacy registrations transfer; no identity/session writes.
|
|
30
|
+
* A receipt survives removal of the old native job and preserves its original
|
|
31
|
+
* running/stopped intent across retries. Native services are never inferred
|
|
32
|
+
* from role names alone. Uncertain or conflicting proof fails closed.
|
|
33
|
+
*/
|
|
34
|
+
export declare function migrateLegacyPermanentMembers(input: LegacyPermanentMigrationInput): Promise<LegacyPermanentMigrationResult[]>;
|
|
35
|
+
export {};
|