@ours.network/fleet 0.19.0-nightly.1 → 0.19.0-nightly.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +4 -4
- package/dist/cli.js +5 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +32 -2
- package/dist/owner-channel/commands.js +89 -0
- package/dist/rooms-tasks/cli.d.ts +4 -0
- package/dist/rooms-tasks/cli.js +565 -0
- package/dist/rooms-tasks/config.d.ts +15 -0
- package/dist/rooms-tasks/config.js +171 -0
- package/dist/rooms-tasks/cowork-adapter.d.ts +80 -0
- package/dist/rooms-tasks/cowork-adapter.js +48 -0
- package/dist/rooms-tasks/index.d.ts +7 -0
- package/dist/rooms-tasks/index.js +7 -0
- package/dist/rooms-tasks/room-state.d.ts +22 -0
- package/dist/rooms-tasks/room-state.js +117 -0
- package/dist/rooms-tasks/task-state.d.ts +31 -0
- package/dist/rooms-tasks/task-state.js +173 -0
- package/dist/rooms-tasks/templates.d.ts +6 -0
- package/dist/rooms-tasks/templates.js +80 -0
- package/dist/rooms-tasks/types.d.ts +153 -0
- package/dist/rooms-tasks/types.js +20 -0
- package/package.json +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
const DEVELOPMENT_TEAM = {
|
|
3
|
+
name: 'development-team',
|
|
4
|
+
version: 1,
|
|
5
|
+
builtin: true,
|
|
6
|
+
description: 'Four equal Developer peers: implement, review, test, and cross-validate',
|
|
7
|
+
room: { quiet_membership: false, anonymous: false },
|
|
8
|
+
contract: [
|
|
9
|
+
'Work in the room. Preserve evidence. Review independently before consensus.',
|
|
10
|
+
'Every material change needs independent review from another peer.',
|
|
11
|
+
'Peers reproduce, test, stress, criticize, and cross-validate each other\'s work.',
|
|
12
|
+
'Evidence and decisions are posted into the Room; detailed scratch work stays in role worklogs.',
|
|
13
|
+
'Completion requires the room\'s agreed acceptance criteria, not merely one agent declaring success.',
|
|
14
|
+
].join('\n'),
|
|
15
|
+
members: [
|
|
16
|
+
{ slot: 'developer', role: 'Developer', count: 4, role_ref: 'Developer' },
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
const RESEARCH_DECISION = {
|
|
20
|
+
name: 'research-decision',
|
|
21
|
+
version: 1,
|
|
22
|
+
builtin: true,
|
|
23
|
+
description: 'Two Researchers, one Critic, one Synthesizer for evidence-based decisions',
|
|
24
|
+
room: { quiet_membership: false, anonymous: false },
|
|
25
|
+
contract: [
|
|
26
|
+
'Researchers gather independent evidence. Critic attacks assumptions and missing cases.',
|
|
27
|
+
'Synthesizer produces the final decision record with cited evidence, alternatives, and recommendation.',
|
|
28
|
+
'No code mutation is implied by this template.',
|
|
29
|
+
'Completion requires cited evidence, alternatives considered, and an explicit recommendation.',
|
|
30
|
+
].join('\n'),
|
|
31
|
+
members: [
|
|
32
|
+
{ slot: 'researcher', role: 'Researcher', count: 2, role_ref: 'Researcher' },
|
|
33
|
+
{ slot: 'critic', role: 'Critic', count: 1, role_ref: 'Critic' },
|
|
34
|
+
{ slot: 'synthesizer', role: 'Synthesizer', count: 1, role_ref: 'Synthesizer' },
|
|
35
|
+
],
|
|
36
|
+
};
|
|
37
|
+
export const BUILTIN_TEMPLATES = [DEVELOPMENT_TEAM, RESEARCH_DECISION];
|
|
38
|
+
export function hashTemplate(t) {
|
|
39
|
+
const canonical = JSON.stringify({
|
|
40
|
+
name: t.name, version: t.version, description: t.description,
|
|
41
|
+
room: t.room, contract: t.contract, members: t.members,
|
|
42
|
+
});
|
|
43
|
+
return createHash('sha256').update(canonical).digest('hex');
|
|
44
|
+
}
|
|
45
|
+
export function snapshotTemplate(t) {
|
|
46
|
+
return { ...t, content_hash: hashTemplate(t) };
|
|
47
|
+
}
|
|
48
|
+
export function resolveTemplate(name, customTemplates) {
|
|
49
|
+
const atIdx = name.lastIndexOf('@');
|
|
50
|
+
const baseName = atIdx > 0 ? name.slice(0, atIdx) : name;
|
|
51
|
+
const versionStr = atIdx > 0 ? name.slice(atIdx + 1) : undefined;
|
|
52
|
+
const version = versionStr ? parseInt(versionStr, 10) : undefined;
|
|
53
|
+
const custom = customTemplates[baseName];
|
|
54
|
+
if (custom) {
|
|
55
|
+
if (version !== undefined && custom.version !== version)
|
|
56
|
+
return undefined;
|
|
57
|
+
return custom;
|
|
58
|
+
}
|
|
59
|
+
const builtin = BUILTIN_TEMPLATES.find(b => b.name === baseName);
|
|
60
|
+
if (builtin) {
|
|
61
|
+
if (version !== undefined && builtin.version !== version)
|
|
62
|
+
return undefined;
|
|
63
|
+
return builtin;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
export function listTemplates(customTemplates) {
|
|
68
|
+
const result = [];
|
|
69
|
+
const overridden = new Set();
|
|
70
|
+
for (const [name, t] of Object.entries(customTemplates)) {
|
|
71
|
+
result.push({ ...t, name });
|
|
72
|
+
if (BUILTIN_TEMPLATES.some(b => b.name === name))
|
|
73
|
+
overridden.add(name);
|
|
74
|
+
}
|
|
75
|
+
for (const b of BUILTIN_TEMPLATES) {
|
|
76
|
+
if (!overridden.has(b.name))
|
|
77
|
+
result.push(b);
|
|
78
|
+
}
|
|
79
|
+
return result.sort((a, b) => a.name.localeCompare(b.name));
|
|
80
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rooms & Tasks domain types for ours-fleet.
|
|
3
|
+
*
|
|
4
|
+
* Task and Room are Fleet orchestration records. Cowork owns room content,
|
|
5
|
+
* membership, and archive. Messenger Server owns owner presentation.
|
|
6
|
+
* Fleet stores only IDs, CIDs, orchestration state, and saga cursors.
|
|
7
|
+
*/
|
|
8
|
+
export type TaskState = 'backlog' | 'provisioning' | 'active' | 'review' | 'done' | 'cancelled' | 'failed';
|
|
9
|
+
export declare const TASK_TERMINAL_STATES: readonly TaskState[];
|
|
10
|
+
export declare const TASK_CANCELLABLE_STATES: readonly TaskState[];
|
|
11
|
+
export interface TaskBlocked {
|
|
12
|
+
reason: string;
|
|
13
|
+
at: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TaskTemplateRef {
|
|
16
|
+
name: string;
|
|
17
|
+
version: number;
|
|
18
|
+
content_hash: string;
|
|
19
|
+
}
|
|
20
|
+
export interface TaskMemberRole {
|
|
21
|
+
name: string;
|
|
22
|
+
identity_cid: string;
|
|
23
|
+
slot: string;
|
|
24
|
+
cowork_role: string;
|
|
25
|
+
}
|
|
26
|
+
export interface TaskOrigin {
|
|
27
|
+
type: 'cli' | 'owner_channel';
|
|
28
|
+
owner_cid?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface TaskOutcome {
|
|
31
|
+
summary: string;
|
|
32
|
+
artifacts?: string[];
|
|
33
|
+
}
|
|
34
|
+
export interface TaskRecord {
|
|
35
|
+
task_id: string;
|
|
36
|
+
title: string;
|
|
37
|
+
brief?: string;
|
|
38
|
+
brief_file?: string;
|
|
39
|
+
state: TaskState;
|
|
40
|
+
blocked?: TaskBlocked;
|
|
41
|
+
template?: TaskTemplateRef;
|
|
42
|
+
room_id?: string;
|
|
43
|
+
room_identity_cid?: string;
|
|
44
|
+
member_roles: TaskMemberRole[];
|
|
45
|
+
origin: TaskOrigin;
|
|
46
|
+
idempotency_key: string;
|
|
47
|
+
created_at: string;
|
|
48
|
+
started_at?: string;
|
|
49
|
+
ended_at?: string;
|
|
50
|
+
outcome?: TaskOutcome;
|
|
51
|
+
}
|
|
52
|
+
export type RoomOrchestrationState = 'provisioning' | 'active' | 'closing' | 'closed';
|
|
53
|
+
export type SagaPhase = 'persist_intent' | 'create_room' | 'attach_owner' | 'create_members' | 'join_role_groups' | 'wait_seats' | 'launch_work' | 'activate' | 'completed' | 'failed';
|
|
54
|
+
export interface SagaCursor {
|
|
55
|
+
phase: SagaPhase;
|
|
56
|
+
step_index: number;
|
|
57
|
+
error?: string;
|
|
58
|
+
recovery_hint?: string;
|
|
59
|
+
}
|
|
60
|
+
export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
|
|
61
|
+
export interface RoomMemberSeat {
|
|
62
|
+
role_name: string;
|
|
63
|
+
identity_cid: string;
|
|
64
|
+
slot: string;
|
|
65
|
+
cowork_role: string;
|
|
66
|
+
seat_state: 'pending' | 'active' | 'removed';
|
|
67
|
+
}
|
|
68
|
+
export interface RoomOrchestrationRecord {
|
|
69
|
+
room_id: string;
|
|
70
|
+
room_identity_cid?: string;
|
|
71
|
+
room_name: string;
|
|
72
|
+
task_id?: string;
|
|
73
|
+
template_snapshot?: TemplateSnapshot;
|
|
74
|
+
saga: SagaCursor;
|
|
75
|
+
provisioning_detail?: ProvisioningDetail;
|
|
76
|
+
owner_seat_cid?: string;
|
|
77
|
+
owner_invite_fingerprint?: string;
|
|
78
|
+
member_seats: RoomMemberSeat[];
|
|
79
|
+
state: RoomOrchestrationState;
|
|
80
|
+
created_at: string;
|
|
81
|
+
activated_at?: string;
|
|
82
|
+
closed_at?: string;
|
|
83
|
+
}
|
|
84
|
+
export interface TemplateMemberSlot {
|
|
85
|
+
slot: string;
|
|
86
|
+
role: string;
|
|
87
|
+
count: number;
|
|
88
|
+
role_ref: string;
|
|
89
|
+
overrides?: TemplateRoleOverrides;
|
|
90
|
+
}
|
|
91
|
+
export interface TemplateRoleOverrides {
|
|
92
|
+
harness?: string;
|
|
93
|
+
model?: string;
|
|
94
|
+
model_chain?: string[];
|
|
95
|
+
permissions?: Record<string, unknown>;
|
|
96
|
+
isolation?: Record<string, unknown>;
|
|
97
|
+
cwd?: string;
|
|
98
|
+
env?: Record<string, string>;
|
|
99
|
+
persona?: string;
|
|
100
|
+
mission?: string;
|
|
101
|
+
}
|
|
102
|
+
export interface TemplateRoomConfig {
|
|
103
|
+
quiet_membership?: boolean;
|
|
104
|
+
anonymous?: boolean;
|
|
105
|
+
}
|
|
106
|
+
export interface TemplateDefinition {
|
|
107
|
+
name: string;
|
|
108
|
+
version: number;
|
|
109
|
+
description: string;
|
|
110
|
+
builtin?: boolean;
|
|
111
|
+
room?: TemplateRoomConfig;
|
|
112
|
+
contract?: string;
|
|
113
|
+
members: TemplateMemberSlot[];
|
|
114
|
+
}
|
|
115
|
+
export interface TemplateSnapshot extends TemplateDefinition {
|
|
116
|
+
content_hash: string;
|
|
117
|
+
}
|
|
118
|
+
export interface RoomsOwnerConfig {
|
|
119
|
+
provider: string;
|
|
120
|
+
public_invite?: string;
|
|
121
|
+
public_invite_file?: string;
|
|
122
|
+
expected_cid: string;
|
|
123
|
+
role: string;
|
|
124
|
+
}
|
|
125
|
+
export interface RoomsCoworkConfig {
|
|
126
|
+
config?: string;
|
|
127
|
+
}
|
|
128
|
+
export interface RoomsDefaults {
|
|
129
|
+
template?: string;
|
|
130
|
+
attach_owner?: boolean;
|
|
131
|
+
close_when_task_done?: boolean;
|
|
132
|
+
}
|
|
133
|
+
export interface RoomsConfig {
|
|
134
|
+
provider: string;
|
|
135
|
+
cowork?: RoomsCoworkConfig;
|
|
136
|
+
owner: RoomsOwnerConfig;
|
|
137
|
+
defaults?: RoomsDefaults;
|
|
138
|
+
}
|
|
139
|
+
export interface TasksConfig {
|
|
140
|
+
default_room_template?: string;
|
|
141
|
+
create_mode?: 'start' | 'backlog';
|
|
142
|
+
close_room_on_done?: boolean;
|
|
143
|
+
retain_completed_for?: string;
|
|
144
|
+
}
|
|
145
|
+
export type RoomTemplatesConfig = Record<string, TemplateDefinition>;
|
|
146
|
+
export declare const ROOMS_KEYS: readonly ["provider", "cowork", "owner", "defaults"];
|
|
147
|
+
export declare const ROOMS_OWNER_KEYS: readonly ["provider", "public_invite", "public_invite_file", "expected_cid", "role"];
|
|
148
|
+
export declare const ROOMS_COWORK_KEYS: readonly ["config"];
|
|
149
|
+
export declare const ROOMS_DEFAULTS_KEYS: readonly ["template", "attach_owner", "close_when_task_done"];
|
|
150
|
+
export declare const TASKS_KEYS: readonly ["default_room_template", "create_mode", "close_room_on_done", "retain_completed_for"];
|
|
151
|
+
export declare const TEMPLATE_KEYS: readonly ["version", "description", "room", "contract", "members", "override_builtin"];
|
|
152
|
+
export declare const TEMPLATE_MEMBER_KEYS: readonly ["slot", "role", "count", "role_ref", "overrides"];
|
|
153
|
+
export declare const TEMPLATE_OVERRIDE_KEYS: readonly ["harness", "model", "model_chain", "permissions", "isolation", "cwd", "env", "persona", "mission"];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rooms & Tasks domain types for ours-fleet.
|
|
3
|
+
*
|
|
4
|
+
* Task and Room are Fleet orchestration records. Cowork owns room content,
|
|
5
|
+
* membership, and archive. Messenger Server owns owner presentation.
|
|
6
|
+
* Fleet stores only IDs, CIDs, orchestration state, and saga cursors.
|
|
7
|
+
*/
|
|
8
|
+
export const TASK_TERMINAL_STATES = ['done', 'cancelled', 'failed'];
|
|
9
|
+
export const TASK_CANCELLABLE_STATES = ['backlog', 'provisioning', 'active', 'review'];
|
|
10
|
+
// ── Validation keys ─────────────────────────────────────────────────────
|
|
11
|
+
export const ROOMS_KEYS = ['provider', 'cowork', 'owner', 'defaults'];
|
|
12
|
+
export const ROOMS_OWNER_KEYS = ['provider', 'public_invite', 'public_invite_file', 'expected_cid', 'role'];
|
|
13
|
+
export const ROOMS_COWORK_KEYS = ['config'];
|
|
14
|
+
export const ROOMS_DEFAULTS_KEYS = ['template', 'attach_owner', 'close_when_task_done'];
|
|
15
|
+
export const TASKS_KEYS = ['default_room_template', 'create_mode', 'close_room_on_done', 'retain_completed_for'];
|
|
16
|
+
export const TEMPLATE_KEYS = ['version', 'description', 'room', 'contract', 'members', 'override_builtin'];
|
|
17
|
+
export const TEMPLATE_MEMBER_KEYS = ['slot', 'role', 'count', 'role_ref', 'overrides'];
|
|
18
|
+
export const TEMPLATE_OVERRIDE_KEYS = [
|
|
19
|
+
'harness', 'model', 'model_chain', 'permissions', 'isolation', 'cwd', 'env', 'persona', 'mission',
|
|
20
|
+
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/fleet",
|
|
3
|
-
"version": "0.19.0-nightly.
|
|
3
|
+
"version": "0.19.0-nightly.2",
|
|
4
4
|
"description": "Harness-agnostic fleet of persistent, identity-bound AI agents. Declarative fleet.yaml, tmux or ACP sessions, supervision, and ours.network messaging.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-Apache-2.0",
|