Skip to content

Guard against wrong-directory broker split-brain and reduce stale-mount startup noise #122

Description

@kjgbot

Summary

Running factory start from the wrong directory silently misbehaves, and startup emits confusing per-clone-path "local mount is stale … refreshing" noise. Both trace back to the daemon anchoring broker/mount discovery to the current working directory. This issue proposes two focused, low-risk improvements.

Background

Factory anchors two things to process.cwd():

  1. Broker discoveryresolveBrokerConnectionPath(cwd) (src/cli/fleet.ts:1004) walks up from cwd looking for .agentworkforce/relay/connection.json. When it returns undefined, ensureRelayBroker (src/fleet/ensure-relay-broker.ts:41) fails to attach to the operator's existing broker and spawns a second broker joining the same workspace. The operator's real agent state (in-flight, dead-letters, dedup) lives on the original broker, so the newly-launched daemon talks to an empty one — it "starts but nothing happens."
  2. The .integrations mount — created at resolve(cwd, '.integrations') (src/cli/fleet.ts:635).

Symptom observed: factory start run from a parent directory that has no .agentworkforce/ never appeared to work, with no actionable error explaining why. Separately, on a normal start after ~15 min idle, the console fills with repeated:

[factory] local mount is stale (last reconcile 612m ago); refreshing
[factory] local mount refreshed
[factory] local mount is stale (last reconcile 613m ago); refreshing
...

Proposed changes

A. Guard against split-brain when launched from the wrong directory

In buildFleet (src/cli/fleet.ts, around line 968), when globals.backend === 'internal', connectionPath === undefined, and ensureRelayBroker is about to spawn a fresh broker (started === true), emit a clear warning to stderr, e.g.:

[factory] no existing relay broker connection found under <cwd> (.agentworkforce/relay/connection.json);
starting a NEW broker. If you expected to attach to an already-running Factory, you are likely running
from the wrong directory — cd to the checkout that owns .agentworkforce/relay/ and retry.

Behavior otherwise unchanged (still spawns, so existing legitimate first-run flows keep working). This turns a silent misconfiguration into an actionable message.

Acceptance criteria

  • When internal backend + no connection.json found up-tree + broker had to be spawned, the warning above is printed once.
  • When an existing broker is reused, or a connection.json is found, no warning is printed.
  • Covered by a unit test in src/cli/fleet.test.ts (inject ensureRelayBroker returning { started: true } with connectionPath undefined; assert stderr warning; and the reuse/started:false case asserts no warning).

B. Reduce the stale-mount refresh noise

Root cause: the mount does one reconcile at launch then its worker processes exit, so after STALE_RECONCILE_MS (15 min, src/mount/relayfile-binary.ts:3) the next start finds it stale, and ensureClonePathMounts (src/cli/fleet.ts:728) re-launches a mount per clone path, one log line each.

Minimum viable fix (this issue): dedupe/quiet the logging so the stale→refresh cycle is summarized once rather than emitted per clone path — e.g. collect the set of paths that needed a refresh and print a single line:

[factory] refreshed N stale local mount(s) (last reconcile ~612m ago)

Acceptance criteria

  • Starting with multiple stale clone-path mounts prints a single summary line, not one pair of lines per path.
  • The per-path detail is still available at debug verbosity.
  • No change to the actual refresh behavior (mounts are still re-launched); logging only.

Out of scope (follow-ups, not required here)

  • Making STALE_RECONCILE_MS configurable.
  • Keeping the mount alive/heartbeating between runs so it never goes stale (the deeper fix for B).

Notes for the implementer

  • Keep changes behavior-preserving except for the new warning (A) and log consolidation (B).
  • Run npm test (vitest); add/extend tests in src/cli/fleet.test.ts and, if touched, src/mount/*.test.ts.
  • Do not change mergePolicy/terminal-state behavior; this is a small, self-contained fleet-CLI + mount-preflight change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    factory-readyApproved for the Factory to pick up and implementfactory:in-progressFactory agents are working on this issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions