@ours.network/fleet 0.15.5 → 0.15.6

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.
@@ -19,7 +19,17 @@ export class OursMcpClient {
19
19
  async start() {
20
20
  if (this.child && this.child.exitCode === null)
21
21
  return;
22
- const child = spawn(this.command, ['proxy'], {
22
+ // ours-mcp normally records the long-lived client PID so an identity lease
23
+ // survives connector churn. An owner-channel connector has the opposite
24
+ // lifecycle: each supervised attempt owns a fresh connector and must make
25
+ // its lease reclaimable when that connector exits, even though the fleet
26
+ // supervisor itself remains alive. POSIX exec preserves the shell PID as
27
+ // the proxy PID, giving the daemon an exact process-lifetime fence without
28
+ // interpolating the command path into shell text.
29
+ const child = spawn('/bin/sh', [
30
+ '-c', 'OURS_CLIENT_PID=$$; export OURS_CLIENT_PID; exec "$1" "$2"',
31
+ 'ours-fleet-owner-proxy', this.command, 'proxy',
32
+ ], {
23
33
  env: {
24
34
  ...process.env,
25
35
  ...this.env,
@@ -34,6 +44,9 @@ export class OursMcpClient {
34
44
  child.once('error', reject);
35
45
  });
36
46
  this.child = child;
47
+ child.once('exit', (code, signal) => {
48
+ this.log(`ours-mcp proxy launcher exited (${code ?? signal ?? 'unknown'})`);
49
+ });
37
50
  child.stdin.on('error', error => this.log(`ours-mcp stdin: ${error.message}`));
38
51
  createInterface({ input: child.stderr }).on('line', line => this.log(`ours-mcp: ${line}`));
39
52
  try {
@@ -70,9 +83,8 @@ export class OursMcpClient {
70
83
  this.child = undefined;
71
84
  if (!child || child.exitCode !== null)
72
85
  return;
73
- // EOF lets the proxy close its HTTP MCP transport and release the daemon
74
- // lease explicitly. SIGTERM used to leave that release racing the next
75
- // supervised start, which is the owner-channel collision this path guards.
86
+ // EOF asks the proxy to close normally. Once this exact process exits, the
87
+ // daemon can reclaim its lease even while the supervisor stays alive.
76
88
  child.stdin.end();
77
89
  const exited = await new Promise(resolve => {
78
90
  const timer = setTimeout(() => resolve(false), 1_000);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/fleet",
3
- "version": "0.15.5",
3
+ "version": "0.15.6",
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",