@ours.network/fleet 1.0.1 → 1.0.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.
@@ -1,4 +1,4 @@
1
- import type { RoomOrchestrationRecord, RoomOrchestrationState, SagaPhase, RoomMemberSeat, ProvisioningDetail, MemberRetirementPhase, RoomClosePhase, RoomRoleBriefingDefinition, RoomMemberLaunchState, RoomMemberBriefingState } from './types.js';
1
+ import type { RoomOrchestrationRecord, RoomOrchestrationState, SagaPhase, RoomMemberSeat, ProvisioningDetail, MemberRetirementPhase, RoomClosePhase, RoomRoleBriefingDefinition, RoomMemberLaunchState } from './types.js';
2
2
  export declare const roomsDir: () => string;
3
3
  export declare class RoomStateError extends Error {
4
4
  }
@@ -26,7 +26,6 @@ export declare function updateRoomRoleBriefing(id: string, role: string, definit
26
26
  export declare function updateRoomHistoryCursor(id: string, cursor: number): RoomOrchestrationRecord;
27
27
  export declare function updateMemberStartup(id: string, roleName: string, update: {
28
28
  launch?: RoomMemberLaunchState;
29
- briefing?: RoomMemberBriefingState;
30
29
  }): RoomOrchestrationRecord;
31
30
  export declare function activateRoom(id: string): RoomOrchestrationRecord;
32
31
  export declare function closeRoom(id: string): RoomOrchestrationRecord;
@@ -122,9 +122,6 @@ export function updateRoomHistoryCursor(id, cursor) {
122
122
  const LAUNCH_ORDER = [
123
123
  'pending', 'intent', 'launched', 'stopped', 'failed',
124
124
  ];
125
- const BRIEFING_ORDER = [
126
- 'pending', 'relay_queued', 'relay_failed', 'acknowledged',
127
- ];
128
125
  export function updateMemberStartup(id, roleName, update) {
129
126
  const r = readRoom(id);
130
127
  const seat = r.member_seats.find(candidate => candidate.role_name === roleName);
@@ -136,14 +133,8 @@ export function updateMemberStartup(id, roleName, update) {
136
133
  && !(seat.launch.state === 'failed' && update.launch.state === 'intent')) {
137
134
  throw new RoomStateError(`room ${id} member ${roleName} launch cannot move backward to ${update.launch.state}`);
138
135
  }
139
- if (update.briefing && seat.briefing
140
- && BRIEFING_ORDER.indexOf(update.briefing.state) < BRIEFING_ORDER.indexOf(seat.briefing.state)) {
141
- throw new RoomStateError(`room ${id} member ${roleName} briefing cannot move backward to ${update.briefing.state}`);
142
- }
143
136
  if (update.launch)
144
137
  seat.launch = update.launch;
145
- if (update.briefing)
146
- seat.briefing = update.briefing;
147
138
  writeRoom(r);
148
139
  return r;
149
140
  }
@@ -65,14 +65,14 @@ export interface TaskRecord {
65
65
  terminal_intent?: TaskTerminalIntent;
66
66
  }
67
67
  export type RoomOrchestrationState = 'provisioning' | 'active' | 'closing' | 'closed';
68
- export type SagaPhase = 'persist_intent' | 'create_room' | 'attach_owner' | 'create_members' | 'configure_briefings' | 'join_role_groups' | 'wait_seats' | 'launch_work' | 'wait_briefing_acks' | 'activate' | 'completed' | 'failed';
68
+ export type SagaPhase = 'persist_intent' | 'create_room' | 'attach_owner' | 'create_members' | 'join_role_groups' | 'wait_seats' | 'launch_work' | 'activate' | 'completed' | 'failed';
69
69
  export interface SagaCursor {
70
70
  phase: SagaPhase;
71
71
  step_index: number;
72
72
  error?: string;
73
73
  recovery_hint?: string;
74
74
  }
75
- export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'waiting_briefing_delivery' | 'waiting_briefing_acks' | 'briefing_delivery_failed' | 'uncertain';
75
+ export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
76
76
  export interface RoomRoleBriefingDefinition {
77
77
  role: string;
78
78
  text: string;
@@ -92,22 +92,6 @@ export interface RoomMemberLaunchState {
92
92
  updated_at: string;
93
93
  error?: string;
94
94
  }
95
- export interface RoomMemberBriefingState {
96
- role: string;
97
- state: 'pending' | 'relay_queued' | 'relay_failed' | 'acknowledged';
98
- message_id?: string;
99
- relay_intent_record_id?: string;
100
- relay_result_record_id?: string;
101
- relay_wire_id?: string;
102
- checked_at?: string;
103
- acknowledged_at?: string;
104
- acknowledgement_message_id?: string;
105
- acknowledgement_seq?: number;
106
- rejected_ack_count: number;
107
- last_rejected_ack_reason?: string;
108
- last_rejected_ack_seq?: number;
109
- last_processed_seq?: number;
110
- }
111
95
  export type RoomHistoryEvidence = {
112
96
  kind: 'message';
113
97
  seq: number;
@@ -161,12 +145,12 @@ export interface RoomCloseCursor {
161
145
  }
162
146
  export interface RoomMemberSeat {
163
147
  role_name: string;
164
- identity_cid: string;
148
+ identity_cid?: string;
149
+ invite_id?: string;
165
150
  slot: string;
166
151
  cowork_role: string;
167
152
  seat_state: 'pending' | 'active' | 'removed';
168
153
  launch?: RoomMemberLaunchState;
169
- briefing?: RoomMemberBriefingState;
170
154
  retirement?: MemberRetirement;
171
155
  }
172
156
  export interface RoomOrchestrationRecord {
@@ -39,9 +39,9 @@ export interface AcpSessionOptions {
39
39
  /** Adapter-authenticated request-metadata vocabulary; never inferred from ACP `_meta`. */
40
40
  permissionMetadataSource?: 'codex-acp';
41
41
  /**
42
- * MCP servers the ROLE declares, for every session/new, resume and load. Empty
43
- * or omitted sends `[]`, which is what fleet has always sent and leaves the
44
- * agent's own configuration untouched.
42
+ * MCP servers the ROLE declares, for every session/new, resume and load.
43
+ * Omitted preserves inherited configuration; an explicit empty array disables
44
+ * every inherited server.
45
45
  */
46
46
  mcpServers?: AcpMcpServer[];
47
47
  /**
@@ -258,14 +258,7 @@ export declare class AcpSession implements SessionHandle {
258
258
  private settlePendingAutomatically;
259
259
  exitResult(): ExitRecord | null;
260
260
  close(): Promise<void>;
261
- /**
262
- * The role's declared MCP servers, or `[]`.
263
- *
264
- * Sent on resume and load as well as on new: the agent builds its server set
265
- * once per session, so a resumed session that omitted them would come back
266
- * without the tools the role's config declares — which is exactly the shape of
267
- * silent drop this plumbing exists to end.
268
- */
261
+ /** Preserve inheritance on omission; carry even an explicit empty override. */
269
262
  private declaredMcpServers;
270
263
  private initialize;
271
264
  private captureRuntimeMetadata;
@@ -991,16 +991,11 @@ export class AcpSession {
991
991
  });
992
992
  this.conversation.close();
993
993
  }
994
- /**
995
- * The role's declared MCP servers, or `[]`.
996
- *
997
- * Sent on resume and load as well as on new: the agent builds its server set
998
- * once per session, so a resumed session that omitted them would come back
999
- * without the tools the role's config declares — which is exactly the shape of
1000
- * silent drop this plumbing exists to end.
1001
- */
994
+ /** Preserve inheritance on omission; carry even an explicit empty override. */
1002
995
  declaredMcpServers() {
1003
- return this.options.mcpServers ?? [];
996
+ return this.options.mcpServers === undefined
997
+ ? {}
998
+ : { mcpServers: this.options.mcpServers };
1004
999
  }
1005
1000
  async initialize() {
1006
1001
  const initialized = await this.connection.agent.request(acp.methods.agent.initialize, {
@@ -1021,7 +1016,7 @@ export class AcpSession {
1021
1016
  const resumed = await this.connection.agent.request(acp.methods.agent.session.resume, {
1022
1017
  sessionId: persisted,
1023
1018
  cwd: this.options.cwd,
1024
- mcpServers: this.declaredMcpServers(),
1019
+ ...this.declaredMcpServers(),
1025
1020
  });
1026
1021
  this.captureRuntimeMetadata(resumed.configOptions);
1027
1022
  this.sessionId = persisted;
@@ -1034,7 +1029,7 @@ export class AcpSession {
1034
1029
  const loaded = await this.connection.agent.request(acp.methods.agent.session.load, {
1035
1030
  sessionId: persisted,
1036
1031
  cwd: this.options.cwd,
1037
- mcpServers: this.declaredMcpServers(),
1032
+ ...this.declaredMcpServers(),
1038
1033
  });
1039
1034
  this.captureRuntimeMetadata(loaded.configOptions);
1040
1035
  }
@@ -1046,7 +1041,7 @@ export class AcpSession {
1046
1041
  else {
1047
1042
  const created = await this.connection.agent.request(acp.methods.agent.session.new, {
1048
1043
  cwd: this.options.cwd,
1049
- mcpServers: this.declaredMcpServers(),
1044
+ ...this.declaredMcpServers(),
1050
1045
  ...(this.options.sessionMeta ? { _meta: this.options.sessionMeta } : {}),
1051
1046
  });
1052
1047
  this.sessionId = created.sessionId;
package/dist/spawn.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { IsolationConfig } from './isolation/types.js';
2
- import { type ApprovalMode, type FilesystemMode, type ResolvedRole, type RoleConfig, type MonitorConfig, type SessionBackendId, type UnattendedMode, type RoomStartupGate } from './config.js';
2
+ import { type ApprovalMode, type FilesystemMode, type ResolvedRole, type RoleConfig, type MonitorConfig, type SessionBackendId, type UnattendedMode, type RoomMemberStartup } from './config.js';
3
3
  import { type OpsDeps } from './ops.js';
4
4
  import { type CreationDeps, type CreationProvenance } from './creation.js';
5
5
  import './harness/claude-code.js';
@@ -46,8 +46,8 @@ export interface SpawnOpts {
46
46
  creationActionId?: string;
47
47
  /** Set only by a live role supervisor after a role-scoped proxy request. */
48
48
  callerRole?: string;
49
- /** Trusted Fleet-internal gate for a Cowork room member; not a CLI/config surface. */
50
- roomStartupGate?: RoomStartupGate;
49
+ /** Trusted Fleet-internal first-boot payload for a Cowork room member. */
50
+ roomMemberStartup?: RoomMemberStartup;
51
51
  /** Internal provenance labels for values filled by the caller's supervisor. */
52
52
  inheritedFromCaller?: string[];
53
53
  /**
package/dist/spawn.js CHANGED
@@ -8,7 +8,7 @@ import { loadConfig, resolveAuthProxy, resolveModelChain, resolveMonitorConfig,
8
8
  import { resolveRoleModelEnv } from './model-env.js';
9
9
  import { applyRole, up } from './ops.js';
10
10
  import { START_STAGGER_FILE } from './runner.js';
11
- import { buildProvenance, daemonIdentityInventoryProvisioner, daemonIdentityProvisioner, ensureIdentity, provenanceOf, withCreationTransaction, writeProvenance, writeRoleFile, } from './creation.js';
11
+ import { buildProvenance, daemonIdentityProvisioner, ensureIdentity, provenanceOf, withCreationTransaction, writeProvenance, writeRoleFile, } from './creation.js';
12
12
  import { VERSION } from './version.js';
13
13
  import './harness/claude-code.js';
14
14
  import './harness/codex.js';
@@ -389,21 +389,13 @@ export async function spawnTemp(o, binPath, launch = independentSupervisor, crea
389
389
  return withCreationTransaction({ role: o.name, identity: effectiveIdentity(o) }, async (tx) => {
390
390
  creation.onStage?.('checking_identity');
391
391
  assertNameFree(o);
392
- const guarantee = await ensureIdentity(effectiveIdentity(o), profileValues(o), creation.identityProvisioner ?? daemonIdentityInventoryProvisioner(), creation.log);
393
392
  creation.onStage?.('checking_identity', {
394
- result: guarantee.evidence, guarantee: guarantee.state,
393
+ result: 'unknown', guarantee: 'unverified',
395
394
  });
396
- if (guarantee.state === 'created')
397
- tx.record({
398
- stage: `ours identity ${effectiveIdentity(o)}`,
399
- undo: async () => {
400
- await creation.identityProvisioner?.remove?.(effectiveIdentity(o));
401
- },
402
- });
403
- return spawnTempInner(o, binPath, launch, tx, guarantee, creation.onStage);
395
+ return spawnTempInner(o, binPath, launch, tx, creation.onStage);
404
396
  }, creation);
405
397
  }
406
- async function spawnTempInner(o, binPath, launch, tx, guarantee, onStage) {
398
+ async function spawnTempInner(o, binPath, launch, tx, onStage) {
407
399
  const cfg = loadConfig(o.configPath);
408
400
  const defaultHarness = cfg.defaults.harness;
409
401
  const fromOpts = buildRoleConfig(o, defaultHarness);
@@ -445,13 +437,13 @@ async function spawnTempInner(o, binPath, launch, tx, guarantee, onStage) {
445
437
  worklog: resolveWorklogPolicy(cfg.defaults.worklog, fromOpts.worklog),
446
438
  auth_proxy: tempAuthProxy,
447
439
  sourceFile: '(temp)',
448
- roomStartupGate: o.roomStartupGate,
440
+ roomMemberStartup: o.roomMemberStartup,
449
441
  };
450
442
  role.env = modelEnv.env;
451
443
  if (role.auth_proxy && role.harness !== 'claude-code')
452
444
  throw new Error('auth_proxy is supported only by claude-code');
453
445
  onStage?.('writing_role');
454
- const dir = applyRole(role, { temp: true, identityGuarantee: guarantee.state });
446
+ const dir = applyRole(role, { temp: true, identityGuarantee: 'unverified' });
455
447
  const provenance = buildProvenance({
456
448
  role: o.name, lifetime: 'temporary', fleetVersion: VERSION,
457
449
  settings: provenanceSettings(o, cfg.defaults),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/fleet",
3
- "version": "1.0.1",
3
+ "version": "1.0.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",