@ours.network/fleet 1.1.0-nightly.3 → 1.1.0-nightly.30
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 +244 -40
- package/dist/agent-recovery-gate.d.ts +17 -0
- package/dist/agent-recovery-gate.js +135 -0
- package/dist/application/capabilities.js +18 -6
- package/dist/application/fleet-query-service.js +20 -5
- package/dist/application/role-command-service.js +9 -0
- package/dist/application/role-creation-service.d.ts +4 -4
- package/dist/application/role-creation-service.js +19 -1
- package/dist/application/role-repository.d.ts +4 -2
- package/dist/application/role-repository.js +6 -3
- package/dist/application/session-control.d.ts +3 -1
- package/dist/application/session-control.js +4 -2
- package/dist/application/task-room-service.d.ts +93 -40
- package/dist/application/task-room-service.js +579 -173
- package/dist/briefing.js +85 -24
- package/dist/build-info.json +4 -4
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +10 -0
- package/dist/cli.js +217 -51
- package/dist/config-yaml.d.ts +1 -1
- package/dist/config.d.ts +38 -3
- package/dist/config.js +240 -28
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +7 -4
- package/dist/daemon-recovery.d.ts +93 -0
- package/dist/daemon-recovery.js +328 -0
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +213 -42
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.js +54 -4
- package/dist/fleet-command-audit.d.ts +181 -0
- package/dist/fleet-command-audit.js +738 -0
- package/dist/fleet-proxy.d.ts +7 -2
- package/dist/harness/agent-session.d.ts +5 -0
- package/dist/harness/claude-code-session.d.ts +2 -0
- package/dist/harness/claude-code-session.js +6 -1
- package/dist/harness/claude-code.js +2 -0
- package/dist/harness/codex-app-server-proxy.d.ts +40 -0
- package/dist/harness/codex-app-server-proxy.js +348 -14
- package/dist/harness/codex-session.d.ts +11 -2
- package/dist/harness/codex-session.js +22 -2
- package/dist/harness/codex.d.ts +5 -1
- package/dist/harness/codex.js +110 -10
- package/dist/harness/types.d.ts +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/init-guidance.d.ts +1 -1
- package/dist/init-guidance.js +4 -3
- package/dist/init-wizard.d.ts +98 -0
- package/dist/init-wizard.js +631 -0
- package/dist/lifecycle-summary.d.ts +134 -0
- package/dist/lifecycle-summary.js +179 -0
- package/dist/loops/config.d.ts +10 -1
- package/dist/loops/config.js +38 -5
- package/dist/model-recovery.d.ts +1 -1
- package/dist/ops.js +2 -17
- package/dist/owner-channel/channel.d.ts +75 -3
- package/dist/owner-channel/channel.js +531 -123
- package/dist/owner-channel/commands.d.ts +28 -6
- package/dist/owner-channel/commands.js +112 -36
- package/dist/owner-channel/lifecycle-outbox.d.ts +24 -0
- package/dist/owner-channel/lifecycle-outbox.js +87 -0
- package/dist/owner-channel/ours-client.d.ts +19 -0
- package/dist/owner-channel/ours-client.js +3 -0
- package/dist/owner-channel/state.d.ts +2 -0
- package/dist/owner-channel/state.js +8 -2
- package/dist/permissions.js +1 -1
- package/dist/preset-bootstrap.d.ts +10 -0
- package/dist/preset-bootstrap.js +85 -0
- package/dist/preset-migration.d.ts +42 -0
- package/dist/preset-migration.js +450 -0
- package/dist/reports/artifact.d.ts +10 -0
- package/dist/reports/artifact.js +32 -0
- package/dist/reports/index.d.ts +5 -0
- package/dist/reports/index.js +5 -0
- package/dist/reports/render.d.ts +6 -0
- package/dist/reports/render.js +240 -0
- package/dist/reports/service.d.ts +42 -0
- package/dist/reports/service.js +57 -0
- package/dist/reports/tasks.d.ts +52 -0
- package/dist/reports/tasks.js +177 -0
- package/dist/reports/types.d.ts +315 -0
- package/dist/reports/types.js +6 -0
- package/dist/resolved-plan.js +13 -1
- package/dist/rooms-tasks/cli.d.ts +2 -0
- package/dist/rooms-tasks/cli.js +519 -261
- package/dist/rooms-tasks/close.d.ts +9 -1
- package/dist/rooms-tasks/close.js +23 -7
- package/dist/rooms-tasks/config.js +16 -29
- package/dist/rooms-tasks/cowork-adapter.d.ts +5 -0
- package/dist/rooms-tasks/cowork-adapter.js +13 -0
- package/dist/rooms-tasks/deletion.d.ts +51 -0
- package/dist/rooms-tasks/deletion.js +217 -0
- package/dist/rooms-tasks/external-worker.d.ts +9 -0
- package/dist/rooms-tasks/external-worker.js +52 -9
- package/dist/rooms-tasks/launch-snapshot.d.ts +19 -0
- package/dist/rooms-tasks/launch-snapshot.js +181 -0
- package/dist/rooms-tasks/member-overrides.d.ts +30 -0
- package/dist/rooms-tasks/member-overrides.js +204 -0
- package/dist/rooms-tasks/member-startup.d.ts +1 -0
- package/dist/rooms-tasks/member-startup.js +9 -2
- package/dist/rooms-tasks/provision.js +146 -56
- package/dist/rooms-tasks/room-state.d.ts +1 -0
- package/dist/rooms-tasks/room-state.js +12 -1
- package/dist/rooms-tasks/task-room-name.d.ts +12 -0
- package/dist/rooms-tasks/task-room-name.js +61 -0
- package/dist/rooms-tasks/task-state.d.ts +115 -3
- package/dist/rooms-tasks/task-state.js +361 -11
- package/dist/rooms-tasks/templates.d.ts +4 -2
- package/dist/rooms-tasks/templates.js +42 -78
- package/dist/rooms-tasks/terminal.d.ts +3 -0
- package/dist/rooms-tasks/terminal.js +10 -4
- package/dist/rooms-tasks/types.d.ts +94 -8
- package/dist/rooms-tasks/types.js +14 -1
- package/dist/runner.d.ts +12 -2
- package/dist/runner.js +167 -56
- package/dist/session/acp.d.ts +9 -1
- package/dist/session/acp.js +35 -9
- package/dist/session/arbiter.d.ts +2 -1
- package/dist/session/arbiter.js +2 -0
- package/dist/session/codex-app-server-transport.d.ts +53 -0
- package/dist/session/codex-app-server-transport.js +184 -0
- package/dist/session/codex-app-server.d.ts +122 -0
- package/dist/session/codex-app-server.js +1031 -0
- package/dist/session/control.d.ts +14 -1
- package/dist/session/control.js +51 -0
- package/dist/session/conversation-types.d.ts +4 -4
- package/dist/session/types.d.ts +24 -6
- package/dist/session/types.js +28 -0
- package/dist/spawn.d.ts +9 -0
- package/dist/spawn.js +77 -9
- package/dist/temp-lifecycle.d.ts +1 -1
- package/dist/web/fleet-config-service.d.ts +1 -0
- package/dist/web/fleet-config-service.js +27 -8
- package/dist/web/runtime.js +11 -6
- package/dist/web/server.js +28 -1
- package/dist/web-app/assets/{index-BbTc5KtZ.js → index-C0h3ALvs.js} +8 -8
- package/dist/web-app/index.html +1 -1
- package/package.json +5 -4
- package/presets/brain-catalog.json +17 -0
- package/presets/fleet/agent_templates/Critic.yaml +5 -0
- package/presets/fleet/agent_templates/Developer.yaml +5 -0
- package/presets/fleet/agent_templates/LocalCoordinator.yaml +50 -0
- package/presets/fleet/agents/FleetCoordinator.yaml +3 -0
- package/presets/fleet/brains/claude-default.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +5 -0
- package/presets/fleet/roles/Coordinator.yaml +30 -0
- package/presets/fleet/roles/Critic.yaml +28 -0
- package/presets/fleet/roles/Developer.yaml +28 -0
- package/presets/fleet/roles/LocalCoordinator.yaml +35 -0
- package/presets/fleet/room_templates/pair.yaml +13 -0
- package/presets/fleet/room_templates/single.yaml +9 -0
- package/presets/fleet/room_templates/team.yaml +16 -0
- package/presets/fleet.yaml +7 -0
- package/presets/manifest.json +6 -0
|
@@ -1,94 +1,58 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
version: 1,
|
|
5
|
-
builtin: true,
|
|
6
|
-
description: 'Phased task pipeline: Architect specifies, Developer implements, Tester verifies',
|
|
7
|
-
room: { quiet_membership: false, anonymous: false },
|
|
8
|
-
contract: [
|
|
9
|
-
'Architect produces a spec and posts it to the room. Work pauses for owner approval.',
|
|
10
|
-
'Developer implements per approved spec.',
|
|
11
|
-
'Tester verifies spec conformance and test coverage.',
|
|
12
|
-
'Completion requires tester sign-off.',
|
|
13
|
-
].join('\n'),
|
|
14
|
-
members: [
|
|
15
|
-
{ slot: 'architect', role: 'Architect', count: 1, agent: { ref: 'Architect' } },
|
|
16
|
-
{ slot: 'developer', role: 'Developer', count: 1, agent: { ref: 'Developer' } },
|
|
17
|
-
{ slot: 'tester', role: 'Tester', count: 1, agent: { ref: 'Tester' } },
|
|
18
|
-
],
|
|
19
|
-
};
|
|
20
|
-
const PAIR = {
|
|
21
|
-
name: 'pair',
|
|
22
|
-
version: 1,
|
|
23
|
-
builtin: true,
|
|
24
|
-
description: 'Deliberation pair: Secretary writes code, Critic reviews — every decision deliberated together',
|
|
25
|
-
room: { quiet_membership: false, anonymous: false },
|
|
26
|
-
contract: [
|
|
27
|
-
'Secretary and Critic deliberate every decision together before acting.',
|
|
28
|
-
'Secretary writes code; Critic reviews and challenges.',
|
|
29
|
-
'No material change lands without both agreeing.',
|
|
30
|
-
'Completion requires joint sign-off.',
|
|
31
|
-
].join('\n'),
|
|
32
|
-
members: [
|
|
33
|
-
{ slot: 'secretary', role: 'Secretary', count: 1, agent: { ref: 'Secretary' } },
|
|
34
|
-
{ slot: 'critic', role: 'Critic', count: 1, agent: { ref: 'Critic' } },
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
const SINGLE = {
|
|
38
|
-
name: 'single',
|
|
39
|
-
version: 1,
|
|
40
|
-
builtin: true,
|
|
41
|
-
description: 'Solo agent: one general-purpose agent works the task with owner oversight',
|
|
42
|
-
room: { quiet_membership: false, anonymous: false },
|
|
43
|
-
contract: [
|
|
44
|
-
'Agent works the task autonomously, consulting the owner when blocked.',
|
|
45
|
-
'Owner reviews and approves completion.',
|
|
46
|
-
].join('\n'),
|
|
47
|
-
members: [
|
|
48
|
-
{ slot: 'agent', role: 'Agent', count: 1, agent: { ref: 'Agent' } },
|
|
49
|
-
],
|
|
50
|
-
};
|
|
51
|
-
export const BUILTIN_TEMPLATES = [TEAM, PAIR, SINGLE];
|
|
2
|
+
import { canonicalJson } from '../canonical-json.js';
|
|
3
|
+
import { redactLaunchDefinition, sealLaunchSnapshot } from './launch-snapshot.js';
|
|
52
4
|
export function hashTemplate(t) {
|
|
53
|
-
const canonical =
|
|
5
|
+
const canonical = canonicalJson({
|
|
54
6
|
name: t.name, version: t.version, description: t.description,
|
|
55
7
|
room: t.room, contract: t.contract, members: t.members,
|
|
56
8
|
});
|
|
57
9
|
return createHash('sha256').update(canonical).digest('hex');
|
|
58
10
|
}
|
|
59
|
-
export function snapshotTemplate(t) {
|
|
60
|
-
|
|
11
|
+
export function snapshotTemplate(t, agentTemplates) {
|
|
12
|
+
const { sourceFile: _, ...semantic } = t;
|
|
13
|
+
return { ...semantic, members: semantic.members.map(member => {
|
|
14
|
+
const definition = agentTemplates?.[member.agent_template];
|
|
15
|
+
return {
|
|
16
|
+
...member,
|
|
17
|
+
...(definition ? {
|
|
18
|
+
agent_projection: redactLaunchDefinition(definition),
|
|
19
|
+
agent_template_hash: createHash('sha256').update(canonicalJson(definition)).digest('hex'),
|
|
20
|
+
} : {}),
|
|
21
|
+
};
|
|
22
|
+
}), content_hash: agentTemplates ? createHash('sha256').update(canonicalJson({
|
|
23
|
+
template: hashTemplate(t),
|
|
24
|
+
members: semantic.members.map(member => ({
|
|
25
|
+
agent_template: member.agent_template,
|
|
26
|
+
agent_template_hash: agentTemplates?.[member.agent_template]
|
|
27
|
+
? createHash('sha256').update(canonicalJson(agentTemplates[member.agent_template])).digest('hex')
|
|
28
|
+
: null,
|
|
29
|
+
})),
|
|
30
|
+
})).digest('hex') : hashTemplate(t) };
|
|
31
|
+
}
|
|
32
|
+
/** Explicit mutation boundary immediately before Task/Room plan persistence. */
|
|
33
|
+
export function sealTemplateSnapshot(snapshot, agentTemplates, launchDefinitions) {
|
|
34
|
+
const referenced = Object.fromEntries([...new Set(snapshot.members.map(member => member.launch_definition_id ?? member.agent_template))]
|
|
35
|
+
.sort().map(id => {
|
|
36
|
+
const member = snapshot.members.find(candidate => (candidate.launch_definition_id ?? candidate.agent_template) === id);
|
|
37
|
+
const definition = launchDefinitions?.[id] ?? agentTemplates[member.agent_template];
|
|
38
|
+
if (!definition)
|
|
39
|
+
throw new Error(`Agent Template '${id}' not found`);
|
|
40
|
+
return [id, definition];
|
|
41
|
+
}));
|
|
42
|
+
return { ...snapshot, launch_snapshot_hash: sealLaunchSnapshot(referenced) };
|
|
61
43
|
}
|
|
62
44
|
export function resolveTemplate(name, customTemplates) {
|
|
63
45
|
const atIdx = name.lastIndexOf('@');
|
|
64
46
|
const baseName = atIdx > 0 ? name.slice(0, atIdx) : name;
|
|
65
47
|
const versionStr = atIdx > 0 ? name.slice(atIdx + 1) : undefined;
|
|
66
48
|
const version = versionStr ? parseInt(versionStr, 10) : undefined;
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return custom;
|
|
72
|
-
}
|
|
73
|
-
const builtin = BUILTIN_TEMPLATES.find(b => b.name === baseName);
|
|
74
|
-
if (builtin) {
|
|
75
|
-
if (version !== undefined && builtin.version !== version)
|
|
76
|
-
return undefined;
|
|
77
|
-
return builtin;
|
|
78
|
-
}
|
|
79
|
-
return undefined;
|
|
49
|
+
const template = customTemplates[baseName];
|
|
50
|
+
if (!template || (version !== undefined && template.version !== version))
|
|
51
|
+
return undefined;
|
|
52
|
+
return template;
|
|
80
53
|
}
|
|
81
54
|
export function listTemplates(customTemplates) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
result.push({ ...t, name });
|
|
86
|
-
if (BUILTIN_TEMPLATES.some(b => b.name === name))
|
|
87
|
-
overridden.add(name);
|
|
88
|
-
}
|
|
89
|
-
for (const b of BUILTIN_TEMPLATES) {
|
|
90
|
-
if (!overridden.has(b.name))
|
|
91
|
-
result.push(b);
|
|
92
|
-
}
|
|
93
|
-
return result.sort((a, b) => a.name.localeCompare(b.name));
|
|
55
|
+
return Object.entries(customTemplates)
|
|
56
|
+
.map(([name, template]) => ({ ...template, name }))
|
|
57
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
94
58
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { type RoomCloseDeps } from './close.js';
|
|
2
2
|
import type { CoworkAdapter } from './cowork-adapter.js';
|
|
3
3
|
import type { TaskOutcome, TaskRecord, TaskTerminalIntent } from './types.js';
|
|
4
|
+
export declare const TASK_OPERATION_LOCK_STALE_MS: number;
|
|
5
|
+
/** Common per-task operation lock serializing terminal, deletion, and recovery acceptance. */
|
|
6
|
+
export declare function taskOperationLockPath(taskId: string): string;
|
|
4
7
|
export interface TaskTerminalInput {
|
|
5
8
|
taskId: string;
|
|
6
9
|
kind: TaskTerminalIntent['kind'];
|
|
@@ -2,10 +2,11 @@ import { join } from 'node:path';
|
|
|
2
2
|
import { withFileLock } from '../atomic-file.js';
|
|
3
3
|
import { stateRoot } from '../paths.js';
|
|
4
4
|
import { deleteManagedRoom } from './close.js';
|
|
5
|
-
import { beginTaskTerminalIntent, finishTaskTerminalIntent, getTask, setTaskTerminalIntentError, } from './task-state.js';
|
|
5
|
+
import { assertNoPendingDeletion, beginTaskTerminalIntent, finishTaskTerminalIntent, getTask, setTaskTerminalIntentError, } from './task-state.js';
|
|
6
6
|
import { getRoomRecord } from './room-state.js';
|
|
7
|
-
const TASK_OPERATION_LOCK_STALE_MS = 10 * 60_000;
|
|
8
|
-
|
|
7
|
+
export const TASK_OPERATION_LOCK_STALE_MS = 10 * 60_000;
|
|
8
|
+
/** Common per-task operation lock serializing terminal, deletion, and recovery acceptance. */
|
|
9
|
+
export function taskOperationLockPath(taskId) {
|
|
9
10
|
return join(stateRoot(), 'locks', 'task-terminal', encodeURIComponent(taskId));
|
|
10
11
|
}
|
|
11
12
|
function errorText(error) {
|
|
@@ -24,6 +25,9 @@ export function acceptTaskTerminalIntent(input) {
|
|
|
24
25
|
export function settleTaskTerminalIntent(input) {
|
|
25
26
|
return withFileLock(taskOperationLockPath(input.taskId), async () => {
|
|
26
27
|
const current = getTask(input.taskId);
|
|
28
|
+
// Deletion supersedes a pending terminal intent: fail boundedly before any
|
|
29
|
+
// room side effect so the deletion worker owns all remaining cleanup.
|
|
30
|
+
assertNoPendingDeletion(current);
|
|
27
31
|
const intent = current.terminal_intent;
|
|
28
32
|
if (!intent)
|
|
29
33
|
throw new Error(`task ${input.taskId} has no accepted terminal intent`);
|
|
@@ -45,7 +49,9 @@ export function settleTaskTerminalIntent(input) {
|
|
|
45
49
|
return finishTaskTerminalIntent(input.taskId);
|
|
46
50
|
}
|
|
47
51
|
catch (error) {
|
|
48
|
-
setTaskTerminalIntentError(input.taskId, errorText(error),
|
|
52
|
+
setTaskTerminalIntentError(input.taskId, errorText(error), intent.kind === 'cancelled'
|
|
53
|
+
? `Retry 'ours-fleet task cancel ${input.taskId} ${input.taskId}'.`
|
|
54
|
+
: `Retry 'ours-fleet task done ${input.taskId}'.`);
|
|
49
55
|
throw error;
|
|
50
56
|
}
|
|
51
57
|
}, {}, TASK_OPERATION_LOCK_STALE_MS);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* membership, and archive. Messenger Server owns owner presentation.
|
|
6
6
|
* Fleet stores only IDs, CIDs, orchestration state, and saga cursors.
|
|
7
7
|
*/
|
|
8
|
+
import type { AgentLaunchConfiguration } from '../lifecycle-summary.js';
|
|
8
9
|
export type TaskState = 'backlog' | 'provisioning' | 'active' | 'review' | 'done' | 'cancelled' | 'failed';
|
|
9
10
|
export declare const TASK_TERMINAL_STATES: readonly TaskState[];
|
|
10
11
|
export declare const TASK_CANCELLABLE_STATES: readonly TaskState[];
|
|
@@ -44,6 +45,47 @@ export interface TaskTerminalIntent {
|
|
|
44
45
|
first_failure?: string;
|
|
45
46
|
first_recovery_hint?: string;
|
|
46
47
|
}
|
|
48
|
+
/** Origin evidence for an accepted deletion; retained until the record is unlinked. */
|
|
49
|
+
export type TaskDeletionActor = {
|
|
50
|
+
kind: 'local_control';
|
|
51
|
+
surface: 'cli' | 'web';
|
|
52
|
+
} | {
|
|
53
|
+
kind: 'authenticated_owner';
|
|
54
|
+
surface: 'messenger';
|
|
55
|
+
cid: string;
|
|
56
|
+
};
|
|
57
|
+
export type TaskDeletionMemberPhase = 'pending' | 'stop_requested' | 'liveness_absent' | 'archive_secured' | 'identity_absent';
|
|
58
|
+
/**
|
|
59
|
+
* Durable retirement cursor for a managed member when no room orchestration
|
|
60
|
+
* record exists to carry the equivalent seat cursor.
|
|
61
|
+
*/
|
|
62
|
+
export interface TaskDeletionMemberCursor {
|
|
63
|
+
name: string;
|
|
64
|
+
identity_cid: string;
|
|
65
|
+
phase: TaskDeletionMemberPhase;
|
|
66
|
+
launch_id?: string;
|
|
67
|
+
archive_path?: string;
|
|
68
|
+
updated_at: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* First-wins durable deletion intent. There is no settled status: settlement
|
|
72
|
+
* ends by unlinking the task record, so physical absence is the completion
|
|
73
|
+
* evidence. While pending, the task is hidden from normal operation and every
|
|
74
|
+
* lifecycle mutation or room publication is rejected.
|
|
75
|
+
*/
|
|
76
|
+
export interface TaskDeletionIntent {
|
|
77
|
+
status: 'pending';
|
|
78
|
+
accepted_at: string;
|
|
79
|
+
actor: TaskDeletionActor;
|
|
80
|
+
room_id?: string;
|
|
81
|
+
/** Snapshot of managed members at acceptance; the missing-room retirement evidence. */
|
|
82
|
+
members: TaskDeletionMemberCursor[];
|
|
83
|
+
error?: string;
|
|
84
|
+
error_at?: string;
|
|
85
|
+
recovery_hint?: string;
|
|
86
|
+
first_failure?: string;
|
|
87
|
+
first_recovery_hint?: string;
|
|
88
|
+
}
|
|
47
89
|
export interface TaskRecord {
|
|
48
90
|
task_id: string;
|
|
49
91
|
/** Stable organizational list identifier. Missing legacy values mean `default`. */
|
|
@@ -56,6 +98,14 @@ export interface TaskRecord {
|
|
|
56
98
|
state: TaskState;
|
|
57
99
|
blocked?: TaskBlocked;
|
|
58
100
|
template?: TaskTemplateRef;
|
|
101
|
+
execution_plan?: {
|
|
102
|
+
schema_version: 1;
|
|
103
|
+
snapshot: TemplateSnapshot;
|
|
104
|
+
room_policy?: RoomLaunchPolicy;
|
|
105
|
+
overrides: Record<string, unknown>;
|
|
106
|
+
overrides_hash: string;
|
|
107
|
+
plan_hash: string;
|
|
108
|
+
};
|
|
59
109
|
no_room?: boolean;
|
|
60
110
|
room_id?: string;
|
|
61
111
|
room_identity_cid?: string;
|
|
@@ -67,6 +117,7 @@ export interface TaskRecord {
|
|
|
67
117
|
ended_at?: string;
|
|
68
118
|
outcome?: TaskOutcome;
|
|
69
119
|
terminal_intent?: TaskTerminalIntent;
|
|
120
|
+
deletion?: TaskDeletionIntent;
|
|
70
121
|
}
|
|
71
122
|
export interface TaskListRecord {
|
|
72
123
|
list_id: string;
|
|
@@ -82,7 +133,7 @@ export interface SagaCursor {
|
|
|
82
133
|
error?: string;
|
|
83
134
|
recovery_hint?: string;
|
|
84
135
|
}
|
|
85
|
-
export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
|
|
136
|
+
export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_authorization' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
|
|
86
137
|
export interface RoomRoleBriefingDefinition {
|
|
87
138
|
role: string;
|
|
88
139
|
text: string;
|
|
@@ -103,6 +154,13 @@ export interface RoomMemberLaunchState {
|
|
|
103
154
|
/** Redacted, deterministic effective Agent launch definition retained for retry inspection. */
|
|
104
155
|
agent_definition?: Record<string, unknown>;
|
|
105
156
|
agent_fingerprint?: string;
|
|
157
|
+
agent_template?: string;
|
|
158
|
+
agent_template_hash?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Operator-facing launch configuration captured from the exact resolved
|
|
161
|
+
* launch state; the single source for later Task/Room lifecycle reports.
|
|
162
|
+
*/
|
|
163
|
+
presentation?: AgentLaunchConfiguration;
|
|
106
164
|
launch_id?: string;
|
|
107
165
|
updated_at: string;
|
|
108
166
|
error?: string;
|
|
@@ -175,6 +233,8 @@ export interface RoomOrchestrationRecord {
|
|
|
175
233
|
goal?: string;
|
|
176
234
|
task_id?: string;
|
|
177
235
|
template_snapshot?: TemplateSnapshot;
|
|
236
|
+
/** Resolved once at launch; legacy absence means non-anonymous. */
|
|
237
|
+
room_policy?: RoomLaunchPolicy;
|
|
178
238
|
saga: SagaCursor;
|
|
179
239
|
provisioning_detail?: ProvisioningDetail;
|
|
180
240
|
owner_seat_cid?: string;
|
|
@@ -192,26 +252,50 @@ export interface TemplateMemberSlot {
|
|
|
192
252
|
slot: string;
|
|
193
253
|
role: string;
|
|
194
254
|
count: number;
|
|
195
|
-
/**
|
|
196
|
-
|
|
197
|
-
ref: string;
|
|
198
|
-
};
|
|
255
|
+
/** Stable reference to an inert Agent Template, never a persistent Agent. */
|
|
256
|
+
agent_template: string;
|
|
199
257
|
}
|
|
200
258
|
export interface TemplateRoomConfig {
|
|
201
259
|
quiet_membership?: boolean;
|
|
202
260
|
anonymous?: boolean;
|
|
203
261
|
}
|
|
262
|
+
export interface RoomLaunchPolicy {
|
|
263
|
+
anonymous: boolean;
|
|
264
|
+
}
|
|
265
|
+
export declare const LEGACY_ROOM_LAUNCH_POLICY: Readonly<RoomLaunchPolicy>;
|
|
266
|
+
/** Validate durable policy before it can influence room creation or recovery. */
|
|
267
|
+
export declare function storedRoomLaunchPolicy(value: RoomLaunchPolicy | undefined): RoomLaunchPolicy;
|
|
204
268
|
export interface TemplateDefinition {
|
|
205
269
|
name: string;
|
|
206
270
|
version: number;
|
|
207
271
|
description: string;
|
|
208
|
-
|
|
272
|
+
/** Authoring provenance only; excluded from snapshots and semantic hashes. */
|
|
273
|
+
sourceFile?: string;
|
|
209
274
|
room?: TemplateRoomConfig;
|
|
210
275
|
contract?: string;
|
|
211
276
|
members: TemplateMemberSlot[];
|
|
212
277
|
}
|
|
213
|
-
export interface
|
|
278
|
+
export interface TemplateSnapshotMember extends TemplateMemberSlot {
|
|
279
|
+
/** Source of the effective temporary-loop policy, independent of its sealed value. */
|
|
280
|
+
loop_source?: 'agent-template' | 'cli' | 'omitted';
|
|
281
|
+
/** Secret-safe public projection; launch material lives in the sealed snapshot. */
|
|
282
|
+
agent_projection?: Record<string, unknown>;
|
|
283
|
+
agent_template_hash?: string;
|
|
284
|
+
/** Private sealed-snapshot lookup key; harmless provenance, not an identity. */
|
|
285
|
+
launch_definition_id?: string;
|
|
286
|
+
role_preset?: {
|
|
287
|
+
id: string;
|
|
288
|
+
hash: string;
|
|
289
|
+
};
|
|
290
|
+
brain_preset?: {
|
|
291
|
+
id: string;
|
|
292
|
+
hash: string;
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
export interface TemplateSnapshot extends Omit<TemplateDefinition, 'members'> {
|
|
296
|
+
members: TemplateSnapshotMember[];
|
|
214
297
|
content_hash: string;
|
|
298
|
+
launch_snapshot_hash?: string;
|
|
215
299
|
}
|
|
216
300
|
export interface RoomsOwnerConfig {
|
|
217
301
|
provider: string;
|
|
@@ -246,4 +330,6 @@ export declare const ROOMS_COWORK_KEYS: readonly ["config"];
|
|
|
246
330
|
export declare const ROOMS_DEFAULTS_KEYS: readonly ["template", "attach_owner", "close_when_task_done"];
|
|
247
331
|
export declare const TASKS_KEYS: readonly ["default_room_template", "create_mode", "close_room_on_done", "retain_completed_for"];
|
|
248
332
|
export declare const TEMPLATE_KEYS: readonly ["version", "description", "room", "contract", "members", "override_builtin"];
|
|
249
|
-
export declare const
|
|
333
|
+
export declare const TEMPLATE_ROOM_KEYS: readonly ["quiet_membership", "anonymous"];
|
|
334
|
+
/** `agent` is accepted only so validation can emit its actionable migration error. */
|
|
335
|
+
export declare const TEMPLATE_MEMBER_KEYS: readonly ["slot", "role", "count", "agent_template", "agent"];
|
|
@@ -7,6 +7,17 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export const TASK_TERMINAL_STATES = ['done', 'cancelled', 'failed'];
|
|
9
9
|
export const TASK_CANCELLABLE_STATES = ['backlog', 'provisioning', 'active', 'review'];
|
|
10
|
+
export const LEGACY_ROOM_LAUNCH_POLICY = Object.freeze({
|
|
11
|
+
anonymous: false,
|
|
12
|
+
});
|
|
13
|
+
/** Validate durable policy before it can influence room creation or recovery. */
|
|
14
|
+
export function storedRoomLaunchPolicy(value) {
|
|
15
|
+
if (value === undefined)
|
|
16
|
+
return { ...LEGACY_ROOM_LAUNCH_POLICY };
|
|
17
|
+
if (typeof value.anonymous !== 'boolean')
|
|
18
|
+
throw new Error('invalid durable Room launch policy; anonymous must be a boolean');
|
|
19
|
+
return { ...value };
|
|
20
|
+
}
|
|
10
21
|
// ── Validation keys ─────────────────────────────────────────────────────
|
|
11
22
|
export const ROOMS_KEYS = ['cowork', 'owner', 'defaults'];
|
|
12
23
|
export const ROOMS_OWNER_KEYS = ['provider', 'public_invite', 'public_invite_file', 'expected_cid', 'role'];
|
|
@@ -14,4 +25,6 @@ export const ROOMS_COWORK_KEYS = ['config'];
|
|
|
14
25
|
export const ROOMS_DEFAULTS_KEYS = ['template', 'attach_owner', 'close_when_task_done'];
|
|
15
26
|
export const TASKS_KEYS = ['default_room_template', 'create_mode', 'close_room_on_done', 'retain_completed_for'];
|
|
16
27
|
export const TEMPLATE_KEYS = ['version', 'description', 'room', 'contract', 'members', 'override_builtin'];
|
|
17
|
-
export const
|
|
28
|
+
export const TEMPLATE_ROOM_KEYS = ['quiet_membership', 'anonymous'];
|
|
29
|
+
/** `agent` is accepted only so validation can emit its actionable migration error. */
|
|
30
|
+
export const TEMPLATE_MEMBER_KEYS = ['slot', 'role', 'count', 'agent_template', 'agent'];
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type ResolvedRole } from './config.js';
|
|
2
2
|
import { type MonitorHandle, type MonitorOpts, type FetchLike } from './monitor.js';
|
|
3
|
+
import { type DaemonGenerationProbe } from './daemon-recovery.js';
|
|
3
4
|
import { type Exec } from './exec.js';
|
|
4
5
|
import { RoleControlServer } from './session/control.js';
|
|
5
6
|
import type { AgentSession, ExitRecord, TurnResult } from './session/types.js';
|
|
6
7
|
import type { AgentSessionAdapter, AgentSessionStartOptions } from './harness/agent-session.js';
|
|
7
8
|
import { type OwnerChannelHandle, type OwnerChannelOptions } from './owner-channel/channel.js';
|
|
8
9
|
import { type OwnerBinderLease } from './owner-channel/binder.js';
|
|
10
|
+
import { ScheduledLoopManager, type ScheduledLoopManagerHandle } from './loops/manager.js';
|
|
9
11
|
export interface RunnerDeps {
|
|
10
12
|
exec: Exec;
|
|
11
13
|
cpuDelegated(): boolean;
|
|
@@ -15,6 +17,7 @@ export interface RunnerDeps {
|
|
|
15
17
|
log(line: string): void;
|
|
16
18
|
/** HTTP transport for the monitor's daemon long-poll (injectable for tests). */
|
|
17
19
|
fetch: FetchLike;
|
|
20
|
+
probeGeneration(env: NodeJS.ProcessEnv): Promise<DaemonGenerationProbe>;
|
|
18
21
|
/** Construct the supervisor mail monitor (injectable so tests stub it out). */
|
|
19
22
|
createMonitor(opts: MonitorOpts): MonitorHandle;
|
|
20
23
|
/** Construct trusted owner ingress (injectable for lifecycle tests). */
|
|
@@ -23,7 +26,9 @@ export interface RunnerDeps {
|
|
|
23
26
|
/** Neutral construction seam for deterministic runner lifecycle tests. */
|
|
24
27
|
startAgentSession(adapter: AgentSessionAdapter, options: AgentSessionStartOptions): Promise<AgentSession>;
|
|
25
28
|
/** Construct the authenticated role control route (injectable where sockets are unavailable). */
|
|
26
|
-
createControlServer(stateDir: string, session: AgentSession, log: (line: string) => void): Pick<RoleControlServer, 'start' | 'close' | 'setFleetSpawner' | 'setOwnerChannel' | 'setConfigReloader' | 'setLoopManager'>;
|
|
29
|
+
createControlServer(stateDir: string, session: AgentSession, log: (line: string) => void): Pick<RoleControlServer, 'start' | 'close' | 'setFleetSpawner' | 'setFleetAuditor' | 'setOwnerChannel' | 'setConfigReloader' | 'setLoopManager'>;
|
|
30
|
+
/** Construct scheduled-loop execution (injectable for fail-closed startup tests). */
|
|
31
|
+
createLoopManager(...args: ConstructorParameters<typeof ScheduledLoopManager>): ScheduledLoopManagerHandle;
|
|
27
32
|
/** Acquire the cross-process owner-channel binder lease before replacing the control socket. */
|
|
28
33
|
acquireOwnerBinder(stateDir: string, role: string, identity: string): Promise<OwnerBinderLease>;
|
|
29
34
|
/** Ask the still-authenticated predecessor to emit the fixed recovery notice. */
|
|
@@ -31,6 +36,11 @@ export interface RunnerDeps {
|
|
|
31
36
|
/** Lets a test (or a shutdown path) end the supervised restart loop. */
|
|
32
37
|
shouldStop?(): boolean;
|
|
33
38
|
}
|
|
39
|
+
export declare const SUPERVISOR_RECYCLE_REQUIRED = "OWNER_CHANNEL_SUPERVISOR_RECYCLE_REQUIRED";
|
|
40
|
+
export declare class SupervisorRecycleRequiredError extends Error {
|
|
41
|
+
readonly code = "OWNER_CHANNEL_SUPERVISOR_RECYCLE_REQUIRED";
|
|
42
|
+
constructor();
|
|
43
|
+
}
|
|
34
44
|
/** Environment injected only into the managed harness process. */
|
|
35
45
|
export declare function managedFleetProxyEnv(role: ResolvedRole, stateDir: string): Record<string, string>;
|
|
36
46
|
/**
|
|
@@ -176,4 +186,4 @@ export declare function runSupervised(name: string, opts?: {
|
|
|
176
186
|
allowResumeRotation?: boolean;
|
|
177
187
|
}, d: Partial<RunnerDeps>) => Promise<AttemptResult>): Promise<RestartLedger>;
|
|
178
188
|
/** Temp-agent entrypoint: run once, journal why it ended, then archive its evidence. */
|
|
179
|
-
export declare function runTemp(name: string, deps?: Partial<RunnerDeps
|
|
189
|
+
export declare function runTemp(name: string, deps?: Partial<RunnerDeps>, attempt?: typeof runOnce): Promise<void>;
|