@ours.network/fleet 0.18.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.
Files changed (79) hide show
  1. package/README.md +57 -91
  2. package/dist/application/fleet-query-service.js +0 -12
  3. package/dist/application/role-creation-service.js +10 -7
  4. package/dist/application/types.d.ts +0 -11
  5. package/dist/briefing.js +6 -15
  6. package/dist/build-info.json +5 -5
  7. package/dist/cli.js +12 -37
  8. package/dist/config.d.ts +8 -6
  9. package/dist/config.js +46 -30
  10. package/dist/creation.d.ts +38 -22
  11. package/dist/creation.js +111 -24
  12. package/dist/docs.d.ts +1 -1
  13. package/dist/docs.js +44 -95
  14. package/dist/doctor.d.ts +5 -1
  15. package/dist/doctor.js +18 -11
  16. package/dist/fleet-proxy.d.ts +0 -5
  17. package/dist/harness/acp-agent.js +6 -11
  18. package/dist/harness/claude-code.js +11 -200
  19. package/dist/harness/codex.d.ts +1 -4
  20. package/dist/harness/codex.js +12 -70
  21. package/dist/harness/types.d.ts +4 -54
  22. package/dist/loops/manager.d.ts +1 -30
  23. package/dist/loops/manager.js +6 -69
  24. package/dist/loops/state.d.ts +0 -18
  25. package/dist/loops/state.js +0 -4
  26. package/dist/monitor.js +1 -1
  27. package/dist/ops.d.ts +3 -0
  28. package/dist/ops.js +8 -3
  29. package/dist/owner-channel/attachments.d.ts +25 -2
  30. package/dist/owner-channel/attachments.js +61 -5
  31. package/dist/owner-channel/channel.d.ts +29 -30
  32. package/dist/owner-channel/channel.js +291 -291
  33. package/dist/owner-channel/commands.js +89 -0
  34. package/dist/owner-channel/message-recovery.d.ts +25 -0
  35. package/dist/owner-channel/message-recovery.js +114 -0
  36. package/dist/owner-channel/notices.d.ts +0 -7
  37. package/dist/owner-channel/notices.js +0 -9
  38. package/dist/owner-channel/ours-client.d.ts +148 -0
  39. package/dist/owner-channel/ours-client.js +231 -0
  40. package/dist/rooms-tasks/cli.d.ts +4 -0
  41. package/dist/rooms-tasks/cli.js +565 -0
  42. package/dist/rooms-tasks/config.d.ts +15 -0
  43. package/dist/rooms-tasks/config.js +171 -0
  44. package/dist/rooms-tasks/cowork-adapter.d.ts +80 -0
  45. package/dist/rooms-tasks/cowork-adapter.js +48 -0
  46. package/dist/rooms-tasks/index.d.ts +7 -0
  47. package/dist/rooms-tasks/index.js +7 -0
  48. package/dist/rooms-tasks/room-state.d.ts +22 -0
  49. package/dist/rooms-tasks/room-state.js +117 -0
  50. package/dist/rooms-tasks/task-state.d.ts +31 -0
  51. package/dist/rooms-tasks/task-state.js +173 -0
  52. package/dist/rooms-tasks/templates.d.ts +6 -0
  53. package/dist/rooms-tasks/templates.js +80 -0
  54. package/dist/rooms-tasks/types.d.ts +153 -0
  55. package/dist/rooms-tasks/types.js +20 -0
  56. package/dist/runner.d.ts +0 -48
  57. package/dist/runner.js +94 -236
  58. package/dist/session/acp.d.ts +0 -104
  59. package/dist/session/acp.js +10 -213
  60. package/dist/session/conversation-normalizer.d.ts +0 -6
  61. package/dist/session/conversation-normalizer.js +10 -153
  62. package/dist/session/conversation-types.d.ts +4 -23
  63. package/dist/session/types.d.ts +0 -35
  64. package/dist/spawn.js +26 -33
  65. package/dist/supervisor/systemd.js +29 -2
  66. package/dist/watchdog/briefing.js +0 -7
  67. package/dist/watchdog/run.js +3 -3
  68. package/dist/web-app/assets/{TerminalView-C_G1ID2P.js → TerminalView-BAVk1Bot.js} +1 -1
  69. package/dist/web-app/assets/{index-BCBK78hw.js → index-C3S-xFRU.js} +5 -5
  70. package/dist/web-app/index.html +1 -1
  71. package/dist/worklog.d.ts +1 -7
  72. package/dist/worklog.js +39 -191
  73. package/package.json +3 -1
  74. package/dist/model-env.d.ts +0 -71
  75. package/dist/model-env.js +0 -106
  76. package/dist/owner-channel/mcp.d.ts +0 -24
  77. package/dist/owner-channel/mcp.js +0 -145
  78. package/dist/session/activity.d.ts +0 -31
  79. package/dist/session/activity.js +0 -48
@@ -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/dist/runner.d.ts CHANGED
@@ -35,15 +35,6 @@ export interface RunnerDeps {
35
35
  }
36
36
  /** Environment injected only into the managed harness process. */
37
37
  export declare function managedFleetProxyEnv(role: ResolvedRole, stateDir: string): Record<string, string>;
38
- /**
39
- * The environment a managed harness child actually receives, checked at the one
40
- * point where it is composed. `role.env` deliberately wins over harness prep,
41
- * which is exactly how a stale fleet-wide model pin used to outrank the model
42
- * the role was spawned with — so the model pin is verified here rather than
43
- * trusted, and a disagreement stops the launch instead of being reported as a
44
- * success (see src/model-env.ts).
45
- */
46
- export declare function harnessChildEnv(role: ResolvedRole, launchEnv: Record<string, string> | undefined, stateDir: string): Record<string, string>;
47
38
  /**
48
39
  * Record who owns wake delivery for this run. Returning true means a fleet
49
40
  * monitor is taking ownership back from a native harness and must start at the
@@ -70,23 +61,6 @@ export declare function readExitRecord(path: string): ExitRecord | null;
70
61
  export declare const RESTART_LEDGER_FILE = ".restart-ledger.json";
71
62
  /** Consecutive immediate failures tolerated before the agent is held down. */
72
63
  export declare const RESTART_FAIL_THRESHOLD = 5;
73
- /**
74
- * How the previous supervisor process ended.
75
- *
76
- * `abrupt` is the case the ledger used to miss entirely: an OOM-kill or any
77
- * other external signal takes the supervisor down before it can write anything,
78
- * the service manager restarts the unit, and every durable indicator still
79
- * describes the run that died. A health check reading them reported "no
80
- * restarts" for a role that had died and come back.
81
- */
82
- export interface TerminationRecord {
83
- class: 'clean' | 'abrupt' | 'unknown';
84
- detail: string;
85
- /** When the SURVIVING process observed it, not when it happened. */
86
- observedAt: string;
87
- /** Start time of the run that ended, when it was recorded. */
88
- runStartedAt?: string;
89
- }
90
64
  export interface RestartLedger {
91
65
  version: 1;
92
66
  consecutiveImmediateFailures: number;
@@ -98,29 +72,7 @@ export interface RestartLedger {
98
72
  updatedAt: string;
99
73
  /** When the circuit opened, for the held-down status line. */
100
74
  openedAt?: string;
101
- /** How the previous supervisor process ended, including abnormal exits. */
102
- lastTermination?: TerminationRecord;
103
- /** Supervisor processes that died without closing their run marker. */
104
- abruptTerminations?: number;
105
- /** Start of the supervisor run that owns this state directory now. */
106
- supervisorStartedAt?: string;
107
75
  }
108
- /**
109
- * Carried across a supervisor process's life so its successor can tell an
110
- * orderly exit from a kill. Present on disk == "a supervisor believed it was
111
- * running"; the next start finding one that is not its own is proof the
112
- * previous process died without getting to write anything.
113
- */
114
- export declare const RUN_MARKER_FILE = ".supervisor-run.json";
115
- /**
116
- * Claim this state directory for the current supervisor process and report how
117
- * the previous one ended. Runs BEFORE the first attempt, which is the whole
118
- * point: after an abrupt kill nothing else writes until an attempt finishes,
119
- * and an attempt can take minutes.
120
- */
121
- export declare function claimSupervisorRun(dir: string, startedAt: string, pid?: number): TerminationRecord;
122
- /** Orderly exit: the successor must not read this run as a kill. */
123
- export declare function releaseSupervisorRun(dir: string): void;
124
76
  /** Bounded exponential backoff for the nth consecutive immediate failure. */
125
77
  export declare function backoffFor(consecutiveFailures: number): number;
126
78
  /** Read a role's restart ledger; a missing or corrupt one starts clean. */