Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Trajectory: Review and fix PR 1028

> **Status:** ✅ Completed
> **Confidence:** 86%
> **Started:** June 3, 2026 at 05:35 AM
> **Completed:** June 3, 2026 at 05:41 AM

---

## Summary

Reviewed PR 1028 path rename, kept new .agentworkforce/relay behavior, added legacy installer cleanup for uninstall, and validated TS tests/typecheck.

**Approach:** Standard approach

---

## Key Decisions

### Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts

- **Chose:** Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts
- **Reasoning:** The PR intentionally moves new runtime/global paths to ~/.agentworkforce/relay, but users upgrading from old installer layouts still need uninstall to remove old dashboard assets and bin directories.

---

## Chapters

### 1. Work

_Agent: default_

- Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts: Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"id": "traj_4md0a6r9hjtd",
"version": 1,
"task": {
"title": "Review and fix PR 1028"
},
"status": "completed",
"startedAt": "2026-06-03T05:35:04.174Z",
"completedAt": "2026-06-03T05:41:21.816Z",
"agents": [
{
"name": "default",
"role": "lead",
"joinedAt": "2026-06-03T05:39:59.848Z"
}
],
"chapters": [
{
"id": "chap_jfgf7qdbqv3z",
"title": "Work",
"agentName": "default",
"startedAt": "2026-06-03T05:39:59.848Z",
"endedAt": "2026-06-03T05:41:21.816Z",
"events": [
{
"ts": 1780465199849,
"type": "decision",
"content": "Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts: Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Decision event content field has duplicated text — the same phrase appears both before and after the colon separator

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .agentworkforce/trajectories/completed/2026-06/traj_4md0a6r9hjtd/trajectory.json, line 28:

<comment>Decision event `content` field has duplicated text — the same phrase appears both before and after the colon separator</comment>

<file context>
@@ -0,0 +1,53 @@
+        {
+          "ts": 1780465199849,
+          "type": "decision",
+          "content": "Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts: Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts",
+          "raw": {
+            "question": "Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts",
</file context>

"raw": {
"question": "Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts",
"chosen": "Kept uninstall cleanup for legacy ~/.agent-relay installer artifacts",
"alternatives": [],
"reasoning": "The PR intentionally moves new runtime/global paths to ~/.agentworkforce/relay, but users upgrading from old installer layouts still need uninstall to remove old dashboard assets and bin directories."
},
"significance": "high"
}
]
}
],
"retrospective": {
"summary": "Reviewed PR 1028 path rename, kept new .agentworkforce/relay behavior, added legacy installer cleanup for uninstall, and validated TS tests/typecheck.",
"approach": "Standard approach",
"confidence": 0.86
},
"commits": [],
"filesChanged": [],
"projectId": "AgentWorkforce/relay",
"tags": [],
"_trace": {
"startRef": "be1f0dc5ec01a3b6f4bfdbb3921f7b8b089b0281",
"endRef": "be1f0dc5ec01a3b6f4bfdbb3921f7b8b089b0281"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Trajectory: Review and fix PR 1028

> **Status:** ✅ Completed
> **Confidence:** 86%
> **Started:** June 3, 2026 at 05:30 AM
> **Completed:** June 3, 2026 at 05:34 AM

---

## Summary

Reviewed PR 1028 path rename, ran stale path sweeps, built TypeScript packages, and verified full Vitest plus typecheck. No code fixes were required after local review.

**Approach:** Standard approach
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"id": "traj_7vb67ogdp9x7",
"version": 1,
"task": {
"title": "Review and fix PR 1028"
},
"status": "completed",
"startedAt": "2026-06-03T05:30:21.088Z",
"completedAt": "2026-06-03T05:34:56.500Z",
"agents": [],
"chapters": [],
"retrospective": {
"summary": "Reviewed PR 1028 path rename, ran stale path sweeps, built TypeScript packages, and verified full Vitest plus typecheck. No code fixes were required after local review.",
"approach": "Standard approach",
"confidence": 0.86
},
"commits": [],
"filesChanged": [],
"projectId": "AgentWorkforce/relay",
"tags": [],
"_trace": {
"startRef": "3387f9f4d6e2dfc700a1133246dbff16b0722acc",
"endRef": "3387f9f4d6e2dfc700a1133246dbff16b0722acc"
}
}
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ __pycache__/
*.egg-info/
.pytest_cache/

.agent-relay/
.agentworkforce/relay/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Ignore nested runtime state directories

When Relay is started from a package/subproject inside a monorepo, findProjectRoot() can choose that subdirectory because it contains its own package.json, so state is created at packages/foo/.agentworkforce/relay. This new ignore pattern contains a slash, so Git only ignores the root .agentworkforce/relay/ path; the old .agent-relay/ pattern matched directories at any depth. Because ensureGitExclude() also only writes an exclude when the chosen project root has its own .git, nested state files can now show up as untracked files in the outer repo.

Useful? React with 👍 / 👎.

.relay/

.sst
Expand Down
2 changes: 1 addition & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ packages/*/tests/
.relay/
.openskills/
.trails/
.agent-relay/
.agentworkforce/relay/
.turbo/
.cursor/
.mcp.json
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Relay stores per-project runtime state in `.agentworkforce/relay/` (was `.agent-relay/`), and the global data/log home moves from `~/.agent-relay`, `$XDG_DATA_HOME/agent-relay`, and platform equivalents to `agentworkforce/relay`. The `~/.config/agent-relay` config directory is unchanged.
- Upgraded relaycast to 2.x (`@relaycast/sdk` and the `relaycast` Rust crate): spawn/release now run as relaycast actions. The broker registers `spawn`/`release` actions on startup and handles `action.invoked` (reading input via the actions API and reporting completion) in place of the removed `command.invoked` protocol; `@agent-relay/openclaw` surfaces `action.invoked` instead of channel slash-commands.
- `agent-relay`, `@agent-relay/sdk`, and `@agent-relay/openclaw` now consume `@relaycast/sdk` 2.1.x for Relaycast's latest inbox delivery behavior.
- `README.md` and `packages/sdk/README.md` now present Agent Relay around three public SDK categories: messaging, delivery, and actions.
Expand All @@ -44,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking Changes

- Relay's on-disk state directory is renamed from `.agent-relay/` to `.agentworkforce/relay/`, and the global `~/.agent-relay`, `$XDG_DATA_HOME/agent-relay`, platform data dirs, and broker log dirs move under `agentworkforce/relay`. Existing brokers and state under the old paths are not migrated.
- `@agent-relay/sdk` is scoped to communication primitives; managed broker startup, PTY/headless harness spawning, workflow supervision, and harness lifecycle helpers move to optional `@agent-relay/harness-driver`.
- `@agent-relay/sdk` removes root and subpath exports for broker clients, spawn facades, PTY/headless helpers, workflow/consensus/shadow helpers, communicate adapters, browser/worker entry points, and GitHub/Slack primitive adapters.
- `agent-relay` removes spawn-first, workflow/swarm, DLQ, activity, log, and `on` command trees from the default CLI package.
Expand All @@ -58,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Migration Guidance

- Stop any running broker before upgrading, then remove the stale `.agent-relay/` directory (and `~/.agent-relay`, `$XDG_DATA_HOME/agent-relay` if present) and restart with `agent-relay up`; state is recreated under `.agentworkforce/relay/`. The broker re-adds `.agentworkforce/relay/` to `.git/info/exclude`, leaving any tracked `.agentworkforce/trajectories/` untouched.
- Install `@agent-relay/harness-driver` for code that starts brokers, spawns PTY/headless agents, waits for managed harness state, or runs supervised workflows; keep `@agent-relay/sdk` for identities, messages, delivery/read state, presence, and commands.
- Replace `agent-relay up/status/down` with `agent-relay driver up/status/down` when you want Agent Relay to manage the local harness boundary.
- Replace SDK spawn calls with driver actions (`agent.create`, `agent.release`, `agent.status`) when agents need to request managed harness work through MCP.
Expand All @@ -71,6 +74,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `sdk-swift`: replace `RelayCast(apiKey:baseURL:)` with `AgentRelayClient(apiKey:baseURL:)`. The public API surface is otherwise unchanged.
- Import `HarnessDriverClient` (was `AgentRelayClient`) from `@agent-relay/harness-driver`; the `connect()`/`spawn()` API is unchanged. Update companion type names (`HarnessDriverClientOptions`, `RuntimeSpawnOptions`, `BrokerInitArgs`, `HarnessDriverEvents`, `HarnessDriverProtocolError`) at import sites.

### Removed

- `@agent-relay/config` removes the unused `getGlobalPaths()` and `listProjects()` exports (legacy global-storage helpers) and drops the `.agent-relay.json` project-root config fallback; shadow config now loads only from `.agentworkforce/relay/config.json`.
- `@agent-relay/config` removes the legacy `/tmp/relay-outbox` symlink: `RelayFileWriter` no longer creates it on `ensureDirectories()`, and the `getLegacyOutboxPath()` method and `RelayPaths.legacyOutboxDir` field are gone.
- `agent-relay` drops the legacy `~/.agent-relay/dashboard` static-asset fallback from broker startup; dashboard assets resolve only from `~/.relay/dashboard`. (Uninstall still purges legacy install dirs.)

### Fixed

- `@agent-relay/cloud`: CLI browser login ignores stray localhost callbacks with an invalid state parameter, so first-time sign-ins are not shown a false hosted error or aborted before the real OAuth callback returns.
Expand Down
2 changes: 1 addition & 1 deletion TELEMETRY.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export DO_NOT_TRACK=1

**Option 3: Configuration file**

Create or edit `~/.agent-relay/telemetry.json`:
Create or edit `~/.agentworkforce/relay/telemetry.json`:

```json
{
Expand Down
10 changes: 5 additions & 5 deletions crates/broker/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,16 +140,16 @@ pub(crate) struct DumpPtyCommand {
pub(crate) format: DumpPtyFormat,

/// Override the broker base URL. Falls back to RELAY_BROKER_URL, then to
/// reading `.agent-relay/connection.json` in the current directory.
/// reading `.agentworkforce/relay/connection.json` in the current directory.
#[arg(long)]
pub(crate) broker_url: Option<String>,

/// Override the broker API key. Falls back to RELAY_BROKER_API_KEY, then
/// to reading `.agent-relay/connection.json` in the current directory.
/// to reading `.agentworkforce/relay/connection.json` in the current directory.
#[arg(long)]
pub(crate) api_key: Option<String>,

/// Override the directory containing `.agent-relay/connection.json` when
/// Override the directory containing `.agentworkforce/relay/connection.json` when
/// auto-discovering the broker.
#[arg(long)]
pub(crate) state_dir: Option<PathBuf>,
Expand Down Expand Up @@ -232,7 +232,7 @@ pub(crate) struct InitCommand {
pub(crate) api_bind: String,

/// Enable persistence: write state, pending-deliveries, lock, and PID files
/// to `.agent-relay/` in the working directory. MCP configuration is injected
/// to `.agentworkforce/relay/` in the working directory. MCP configuration is injected
/// into spawned agents at launch time instead of being written to project
/// config files. When omitted (the default), runtime files are written to a
/// deterministic temp directory and cleaned up opportunistically; identity
Expand All @@ -242,7 +242,7 @@ pub(crate) struct InitCommand {
pub(crate) persist: bool,

/// Override the directory used for broker state files (connection.json,
/// locks, state, pending-deliveries). Defaults to `.agent-relay/` in the
/// locks, state, pending-deliveries). Defaults to `.agentworkforce/relay/` in the
/// working directory when `--persist` is set, or a temp directory otherwise.
#[arg(long)]
pub(crate) state_dir: Option<String>,
Expand Down
10 changes: 5 additions & 5 deletions crates/broker/src/runtime/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ pub(crate) struct BrokerConnection {
///
/// 1. Explicit CLI args (`--broker-url`, `--api-key`). When `--broker-url`
/// is supplied without an API key, we still attempt to fall back to the
/// API key from env / `.agent-relay/connection.json` so users don't have
/// API key from env / `.agentworkforce/relay/connection.json` so users don't have
/// to repeat `--api-key` for every dump-pty invocation.
/// 2. Env vars `RELAY_BROKER_URL` / `RELAY_BROKER_API_KEY`.
/// 3. `connection.json` in the supplied state dir, otherwise
/// `.agent-relay/connection.json` directly under the current working
/// `.agentworkforce/relay/connection.json` directly under the current working
/// directory. The bare `cwd` is intentionally NOT probed — an unrelated
/// `connection.json` sitting in the user's repo root must not silently
/// redirect the snapshot request (and its broker API key) elsewhere.
Expand All @@ -31,7 +31,7 @@ pub(crate) fn discover_broker_connection(
let cwd = std::env::current_dir().ok()?;
let roots: Vec<PathBuf> = match state_dir {
Some(dir) => vec![dir.to_path_buf()],
None => vec![cwd.join(".agent-relay")],
None => vec![cwd.join(".agentworkforce/relay")],
};
for root in roots {
let path = root.join("connection.json");
Expand Down Expand Up @@ -77,7 +77,7 @@ pub(crate) fn discover_broker_connection(
let cwd = std::env::current_dir().context("failed to read current directory")?;
let search_roots: Vec<PathBuf> = match state_dir {
Some(dir) => vec![dir.to_path_buf()],
None => vec![cwd.join(".agent-relay")],
None => vec![cwd.join(".agentworkforce/relay")],
};

for root in &search_roots {
Expand Down Expand Up @@ -112,7 +112,7 @@ pub(crate) fn discover_broker_connection(

anyhow::bail!(
"could not locate broker connection. Pass --broker-url, set RELAY_BROKER_URL, \
or run from a directory containing .agent-relay/connection.json"
or run from a directory containing .agentworkforce/relay/connection.json"
);
}

Expand Down
10 changes: 5 additions & 5 deletions crates/broker/src/runtime/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@ pub(crate) async fn run_init(cmd: InitCommand, telemetry: TelemetryClient) -> Re
let paths = if cmd.persist || custom_state_dir.is_some() {
ensure_runtime_paths(&runtime_cwd, &resolved_name, custom_state_dir.as_deref())?
} else {
// Warn only if there is *actual broker state* in .agent-relay/ from a
// Warn only if there is *actual broker state* in .agentworkforce/relay/ from a
// prior `--persist` run that could confuse this ephemeral run.
//
// The SDK workflow runner ALWAYS writes .agent-relay/step-outputs/ and
// .agent-relay/team/worker-logs/ regardless of broker mode (those are
// The SDK workflow runner ALWAYS writes .agentworkforce/relay/step-outputs/ and
// .agentworkforce/relay/team/worker-logs/ regardless of broker mode (those are
// durable artifacts, not broker state), so a bare directory check fires
// on virtually every workflow run — a noisy false positive.
//
// The discriminator is the broker's state file. `ensure_runtime_paths`
// (the persist-mode helper in runtime/paths.rs) writes it as
// `state-{safe_name}.json`, where `safe_name` is the sanitized broker
// name — so the exact filename varies by run. Glob for any
// `state-*.json` entry in `.agent-relay/` and surface every match so
// `state-*.json` entry in `.agentworkforce/relay/` and surface every match so
// the user can see exactly what's stale regardless of broker name.
let stale_dir = runtime_cwd.join(".agent-relay");
let stale_dir = runtime_cwd.join(".agentworkforce/relay");
let stale_state_files: Vec<PathBuf> = std::fs::read_dir(&stale_dir)
.ok()
.into_iter()
Expand Down
8 changes: 4 additions & 4 deletions crates/broker/src/runtime/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ pub(crate) struct RuntimePaths {
}

/// Returns the continuity directory path derived from the state file path.
/// State path is always `{cwd}/.agent-relay/state.json`, so parent is `{cwd}/.agent-relay/`.
/// State path is always `{cwd}/.agentworkforce/relay/state.json`, so parent is `{cwd}/.agentworkforce/relay/`.
pub(crate) fn continuity_dir(state_path: &Path) -> PathBuf {
state_path
.parent()
.expect("state_path always has a parent (.agent-relay/)")
.expect("state_path always has a parent (.agentworkforce/relay/)")
.join("continuity")
}

Expand Down Expand Up @@ -74,7 +74,7 @@ pub(crate) fn ensure_runtime_paths(
) -> Result<RuntimePaths> {
let root = state_dir
.map(PathBuf::from)
.unwrap_or_else(|| cwd.join(".agent-relay"));
.unwrap_or_else(|| cwd.join(".agentworkforce/relay"));
std::fs::create_dir_all(&root)
.with_context(|| format!("failed to create runtime dir {}", root.display()))?;

Expand Down Expand Up @@ -150,7 +150,7 @@ pub(crate) fn ensure_runtime_paths(
}
}
// PID file missing or unreadable while lock is held — treat as stale.
// This happens when the user deletes .agent-relay/ while an old broker
// This happens when the user deletes .agentworkforce/relay/ while an old broker
// is still alive, or during the shutdown race (PID deleted before flock
// released).
tracing::warn!(
Expand Down
16 changes: 10 additions & 6 deletions crates/broker/src/runtime/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1893,29 +1893,33 @@ fn is_pid_alive_eperm_means_alive() {

#[test]
fn continuity_dir_derives_correct_path_from_state_json() {
let state_path = std::path::Path::new("/project/.agent-relay/state.json");
let state_path = std::path::Path::new("/project/.agentworkforce/relay/state.json");
let result = continuity_dir(state_path);
assert_eq!(
result,
std::path::PathBuf::from("/project/.agent-relay/continuity")
std::path::PathBuf::from("/project/.agentworkforce/relay/continuity")
);
}

#[test]
fn continuity_dir_works_with_nested_project_path() {
let state_path = std::path::Path::new("/home/user/projects/my-app/.agent-relay/state.json");
let state_path =
std::path::Path::new("/home/user/projects/my-app/.agentworkforce/relay/state.json");
let result = continuity_dir(state_path);
assert_eq!(
result,
std::path::PathBuf::from("/home/user/projects/my-app/.agent-relay/continuity")
std::path::PathBuf::from("/home/user/projects/my-app/.agentworkforce/relay/continuity")
);
}

#[test]
fn continuity_dir_preserves_relative_paths() {
let state_path = std::path::Path::new(".agent-relay/state.json");
let state_path = std::path::Path::new(".agentworkforce/relay/state.json");
let result = continuity_dir(state_path);
assert_eq!(result, std::path::PathBuf::from(".agent-relay/continuity"));
assert_eq!(
result,
std::path::PathBuf::from(".agentworkforce/relay/continuity")
);
}

#[test]
Expand Down
Loading
Loading