Skip to content
Open
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
48 changes: 25 additions & 23 deletions .agents/skills/choosing-swarm-patterns/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,23 @@ Is cost the primary concern?

These 14 additional patterns exist in `SwarmPattern` (types.ts:114-139). The coordinator has role-based auto-selection heuristics (`coordinator.ts:51-165`), but they only fire when `swarm.pattern` is **omitted** — YAML validation requires it (`runner.ts:2105-2117`), so auto-selection is effectively a programmatic-API feature. In YAML, set `swarm.pattern` explicitly.
Topology is still resolved per-pattern once selected; the "Triggering roles" column reflects what the coordinator looks for to shape edges (per `coordinator.ts:250-450`):
| Pattern | Roles the topology keys off | Topology |

| Pattern | Roles the topology keys off | Topology |
| ----------------- | ------------------------------------------------------- | ---------------------------------------------- |
| `map-reduce` | `mapper` + `reducer` | coordinator → mappers → reducers → coordinator |
| `scatter-gather` | — | hub → workers → hub |
| `supervisor` | `supervisor` | supervisor ↔ workers |
| `reflection` | `critic` or `reviewer` (auto-select uses `critic` only) | producers → critic → producers (loop) |
| `red-team` | `attacker`/`red-team` + `defender`/`blue-team` | adversarial mesh with optional judges |
| `verifier` | `verifier` | producers → verifiers → back to producers |
| `auction` | `auctioneer` | auctioneer → bidders → auctioneer |
| `escalation` | `tier-*` | tiered chain, escalate up / report down |
| `saga` | `saga-orchestrator`, `compensate-handler` | orchestrator ↔ participants |
| `circuit-breaker` | `primary` + `fallback`/`backup` | try primary, fallback on failure |
| `blackboard` | `blackboard` / `shared-workspace` | shared state hub |
| `swarm` | `hive-mind` / `swarm-agent` | stigmergy-style |
| `competitive` | — (declared explicitly) | independent parallel implementations + judge |
| `review-loop` | `implement*` + 2+ `reviewer*` | implementer ↔ reviewers |
| `map-reduce` | `mapper` + `reducer` | coordinator → mappers → reducers → coordinator |
| `scatter-gather` | — | hub → workers → hub |
| `supervisor` | `supervisor` | supervisor ↔ workers |
| `reflection` | `critic` or `reviewer` (auto-select uses `critic` only) | producers → critic → producers (loop) |
| `red-team` | `attacker`/`red-team` + `defender`/`blue-team` | adversarial mesh with optional judges |
| `verifier` | `verifier` | producers → verifiers → back to producers |
| `auction` | `auctioneer` | auctioneer → bidders → auctioneer |
| `escalation` | `tier-*` | tiered chain, escalate up / report down |
| `saga` | `saga-orchestrator`, `compensate-handler` | orchestrator ↔ participants |
| `circuit-breaker` | `primary` + `fallback`/`backup` | try primary, fallback on failure |
| `blackboard` | `blackboard` / `shared-workspace` | shared state hub |
| `swarm` | `hive-mind` / `swarm-agent` | stigmergy-style |
| `competitive` | — (declared explicitly) | independent parallel implementations + judge |
| `review-loop` | `implement*` + 2+ `reviewer*` | implementer ↔ reviewers |

### Structured Squad Review Loop

Expand Down Expand Up @@ -303,15 +304,16 @@ flat names. In a client that decorates MCP tools, the prefix comes from the
configured server key. With the relay broker's `agent-relay` server key, Claude
Code users commonly see `mcp__agent-relay__send_dm`; Codex and opencode users
see the bare canonical name `send_dm`.
| Purpose | Canonical tool | Claude Code form with `agent-relay` key |

| Purpose | Canonical tool | Claude Code form with `agent-relay` key |
| ------------------------ | ----------------- | --------------------------------------- |
| Send DM to another agent | `send_dm` | `mcp__agent-relay__send_dm` |
| Check inbox | `check_inbox` | `mcp__agent-relay__check_inbox` |
| List agents | `list_agents` | `mcp__agent-relay__list_agents` |
| Post to a channel | `post_message` | `mcp__agent-relay__post_message` |
| Reply in a thread | `reply_to_thread` | `mcp__agent-relay__reply_to_thread` |
| Spawn sub-agent | `add_agent` | `mcp__agent-relay__add_agent` |
| Remove sub-agent | `remove_agent` | `mcp__agent-relay__remove_agent` |
| Send DM to another agent | `send_dm` | `mcp__agent-relay__send_dm` |
| Check inbox | `check_inbox` | `mcp__agent-relay__check_inbox` |
| List agents | `list_agents` | `mcp__agent-relay__list_agents` |
| Post to a channel | `post_message` | `mcp__agent-relay__post_message` |
| Reply in a thread | `reply_to_thread` | `mcp__agent-relay__reply_to_thread` |
| Spawn sub-agent | `add_agent` | `mcp__agent-relay__add_agent` |
| Remove sub-agent | `remove_agent` | `mcp__agent-relay__remove_agent` |

> `interactive: false` agents run as non-interactive subprocesses with no relay connection. They must not call Relay MCP tools.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Trajectory: Keep executable release identity out of compiled messaging libraries

> **Status:** ✅ Completed
> **Confidence:** 90%
> **Started:** November 4, 2026 at 08:49 AM
> **Completed:** November 4, 2026 at 08:53 AM

---

## Summary

Added library-only embedded identity accessors and immutable startup installation; default constants/stamping preserved. Site/scheme remain compile-time, executable metadata/resource inputs no longer watched. Strict/fixture/build-script tests pass; all integration test targets compile with fixture. Isolated desktop version-only prototype67.342s ->1.149s, only executable rebuilt; production desktop adoption awaits profile/restructure handoff.

**Approach:** Standard approach

---

## Key Decisions

### Make build identity an executable-owned value
- **Chose:** Make build identity an executable-owned value
- **Reasoning:** A metadata dependency would propagate Cargo fingerprints into large libraries. Optional library-only embedded mode removes version/revision watches and exposes immutable startup initialization; standalone node behavior and compile-time site/scheme stay unchanged. Isolated desktop package split reduced version-only rebuild67.342s to1.149s with both libraries Fresh and executable reporting new baked identity.

---

## Chapters

### 1. Initial work
*Agent: codex-relay-desktop-speed-up*

- Make build identity an executable-owned value: Make build identity an executable-owned value
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"id": "traj_bjhvd5dhdi87",
"version": 1,
"task": {
"title": "Keep executable release identity out of compiled messaging libraries"
},
"status": "completed",
"startedAt": "2026-11-04T16:49:54.626Z",
"completedAt": "2026-11-04T16:53:53.135Z",
"agents": [
{
"name": "codex-relay-desktop-speed-up",
"role": "lead",
"joinedAt": "2026-11-04T16:49:54.728Z"
}
],
"chapters": [
{
"id": "chap_or3b4rv9bqch",
"title": "Initial work",
"agentName": "codex-relay-desktop-speed-up",
"startedAt": "2026-11-04T16:49:54.728Z",
"endedAt": "2026-11-04T16:53:53.135Z",
"events": [
{
"ts": 1793811192903,
"type": "decision",
"content": "Make build identity an executable-owned value: Make build identity an executable-owned value",
"raw": {
"question": "Make build identity an executable-owned value",
"chosen": "Make build identity an executable-owned value",
"alternatives": [],
"reasoning": "A metadata dependency would propagate Cargo fingerprints into large libraries. Optional library-only embedded mode removes version/revision watches and exposes immutable startup initialization; standalone node behavior and compile-time site/scheme stay unchanged. Isolated desktop package split reduced version-only rebuild67.342s to1.149s with both libraries Fresh and executable reporting new baked identity."
},
"significance": "high"
}
]
}
],
"retrospective": {
"summary": "Added library-only embedded identity accessors and immutable startup installation; default constants/stamping preserved. Site/scheme remain compile-time, executable metadata/resource inputs no longer watched. Strict/fixture/build-script tests pass; all integration test targets compile with fixture. Isolated desktop version-only prototype67.342s ->1.149s, only executable rebuilt; production desktop adoption awaits profile/restructure handoff.",
"approach": "Standard approach",
"confidence": 0.9
},
"commits": [],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This completed trace has no commit or changed-file provenance, and _trace points to the same parent revision at both ends. Regenerate it after the implementation commit so commits, filesChanged, startRef, and endRef describe this work; otherwise the completed trajectory cannot be audited.

(Based on your team's feedback about completed trajectory trace metadata.)

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At .agentworkforce/trajectories/codex-build-identity/completed/2026-11/traj_bjhvd5dhdi87/trajectory.json, line 45:

<comment>This completed trace has no commit or changed-file provenance, and `_trace` points to the same parent revision at both ends. Regenerate it after the implementation commit so `commits`, `filesChanged`, `startRef`, and `endRef` describe this work; otherwise the completed trajectory cannot be audited.

(Based on your team's feedback about completed trajectory trace metadata.) </comment>

<file context>
@@ -0,0 +1,53 @@
+    "approach": "Standard approach",
+    "confidence": 0.9
+  },
+  "commits": [],
+  "filesChanged": [],
+  "projectId": "AgentWorkforce/relay",
</file context>

"filesChanged": [],
"projectId": "AgentWorkforce/relay",
"tags": [],
"_trace": {
"startRef": "ad983d7278bab88b0a7d541494521146b869f78a",
"endRef": "ad983d7278bab88b0a7d541494521146b869f78a"
}
}
3 changes: 1 addition & 2 deletions .claude/skills/creating-claude-rules-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ alwaysApply: true
paths:
- **/*.ts
---

# ✅ CORRECT - quote glob patterns
---
paths:
- "**/*.ts"
- '**/*.ts'
---
```

Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/relay-node-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ jobs:
export HOME="$RUNNER_TEMP/relay-node-home"
mkdir -p "$HOME"
cargo test --locked --no-default-features -- --test-threads=4
- name: Embedded executable identity
run: cargo test --locked --no-default-features --features embedded-build-info --test embedded_build_info --test embedded_build_script
- name: Explicit downstream test identity fixture
run: |
cargo check --locked --no-default-features --features test-build-info --tests
cargo test --locked --no-default-features --features test-build-info --test test_build_info

macos:
name: macOS arm64 build + test
Expand Down
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ Publishing (npm, crates, GitHub releases) is gated on chief green-light.
delete chief's orgchart env-unset workaround when fixed), #1383
(non-Error rejections render as `[object Object]`).
- Also pending: 64 dependabot alerts on main (1 critical); skills repo
relay-team/relay-pipeline/relay-fanout SKILL.mds still instruct printing
raw observer URLs — unsatisfiable once #1380 lands.
relay-team/relay-pipeline/relay-fanout SKILL.mds still instruct printing
raw observer URLs — unsatisfiable once #1380 lands.

<!-- PRPM_MANIFEST_START -->

<skills_system priority="1">
Expand Down
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ All notable changes to Agent Relay will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [Unreleased - Minor]

### Added

- Applications embedding `agent-relay-node` can install their compiled version and revision at startup, so changing release identity only rebuilds their executable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: Name the public API here: the entry should identify install_build_info(BuildInfo) instead of describing installation generically. Lead with the benefit that release-identity changes rebuild only the embedding executable.

(Based on your team's feedback about impact-first changelog entries that name the concrete API.) [c2e76b35-7371-486a-a7a9-01de3a8d962c]

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At CHANGELOG.md, line 12:

<comment>Name the public API here: the entry should identify `install_build_info(BuildInfo)` instead of describing installation generically. Lead with the benefit that release-identity changes rebuild only the embedding executable.

(Based on your team's feedback about impact-first changelog entries that name the concrete API.) [c2e76b35-7371-486a-a7a9-01de3a8d962c]</comment>

<file context>
@@ -5,7 +5,11 @@ All notable changes to Agent Relay will be documented in this file.
+
+### Added
+
+- Applications embedding `agent-relay-node` can install their compiled version and revision at startup, so changing release identity only rebuilds their executable.
 
 ## [17.0.0] - 2026-11-05
</file context>
Suggested change
- Applications embedding `agent-relay-node` can install their compiled version and revision at startup, so changing release identity only rebuilds their executable.
- Changing release identity only rebuilds the embedding executable: `agent-relay-node` exposes `install_build_info(BuildInfo)` for applications to provide their compiled version and revision at startup.


## [17.0.0] - 2026-11-05

Expand Down
5 changes: 5 additions & 0 deletions crates/relay-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ name = "relay_core_binary"
required-features = ["production-binaries"]

[features]
# Library embedders bake identity into their executable instead of this crate.
# Install BuildInfo before calling the core. Use with default-features = false.
embedded-build-info = []
Comment on lines +28 to +30

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Embedded identity API missing from changelog

Downstream builders can use embedded-build-info, but the existing Unreleased changelog omits this new library API. Readers of the release notes miss the executable identity setup requirement.

Learn more

The root changelog is the release narrative for user-visible package and API changes. The existing [Unreleased - Major] section already has a Changed subsection, but it does not cover the new library mode or its startup requirement. The new mode is consumed by executable builders rather than the standalone CLI.

Example: A desktop integrator updating its pinned core sees no changelog entry explaining that embedded builds use BuildInfo instead of the stamped constants.

Recommended fix: Add one concise impact-first bullet under the existing Unreleased Changed section naming the new embedding API and its required startup installation.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Embedded builds still send CARGO_PKG_VERSION (0.1.0) from several client handshakes, so the installed executable identity is not propagated consistently. Replace those product-facing version fields with crate::version().

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At crates/relay-node/Cargo.toml, line 30:

<comment>Embedded builds still send `CARGO_PKG_VERSION` (`0.1.0`) from several client handshakes, so the installed executable identity is not propagated consistently. Replace those product-facing version fields with `crate::version()`.</comment>

<file context>
@@ -25,6 +25,11 @@ name = "relay_core_binary"
 [features]
+# Library embedders bake identity into their executable instead of this crate.
+# Install BuildInfo before calling the core. Use with default-features = false.
+embedded-build-info = []
+# Deterministic identity fixture for downstream dev-dependencies only.
+test-build-info = ["embedded-build-info"]
</file context>

# Deterministic identity fixture for downstream dev-dependencies only.
test-build-info = ["embedded-build-info"]
Comment on lines +30 to +32

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Document executable-owned identity in the root changelog

This adds a downstream-facing embedding feature and public identity APIs, but CHANGELOG.md has no corresponding entry under [Unreleased - Major]. The repository requires user-visible package/API changes to be recorded in the root release narrative; the crate README alone does not satisfy that requirement. Add a concise Added entry explaining executable-owned identity and its rebuild benefit, retaining the existing Major heading.

AGENTS.md reference: AGENTS.md:L31-L34

Useful? React with 👍 / 👎.

# Ordinary builds keep every production executable. The desktop apps'
# crates opt out with --no-default-features when they only need the library.
default = ["production-binaries", "relay-cli"]
Expand Down
34 changes: 34 additions & 0 deletions crates/relay-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,40 @@ The internal Cargo package version is never reported as a release on its
own. On Windows, `AGENT_RELAY_WINDOWS_ICON` additionally embeds an icon and
version resource.

### Executable-owned identity

An embedding application can enable `embedded-build-info` with
`default-features = false`. In this mode the node library does not read or watch
release version, Git revision, changelog, or Windows resource inputs. It still
validates and bakes in the site and URL scheme. The feature is incompatible with
`production-binaries`, whose standalone executables use the default stamping.

The executable must install its compiled identity before calling the CLI,
constructing a node, or reading identity:

```rust,ignore
agent_relay_node::install_build_info(agent_relay_node::BuildInfo {
version: env!("APP_RELEASE_VERSION"),
revision: env!("APP_SOURCE_REVISION"),
}).expect("build identity is installed once at startup");
```

The executable's build script supplies these values at compile time. They are
not read from the environment at startup. Getters `version()` and
`build_revision()` fail if initialization was omitted, and a second install is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P3: The getters panic when identity is missing, they do not return an error. Say "panic" here so embedders know to install identity before any read.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At crates/relay-node/README.md, line 112:

<comment>The getters panic when identity is missing, they do not return an error. Say "panic" here so embedders know to install identity before any read.</comment>

<file context>
@@ -89,6 +89,40 @@ The internal Cargo package version is never reported as a release on its
+
+The executable's build script supplies these values at compile time. They are
+not read from the environment at startup. Getters `version()` and
+`build_revision()` fail if initialization was omitted, and a second install is
+rejected. These APIs do not configure the site, scheme, or branding.
+
</file context>

rejected. These APIs do not configure the site, scheme, or branding.

Keep the identity build script and Windows resources in an executable-only
Cargo package. Putting changing metadata in a dependency of the heavy libraries
would still invalidate them. The default node build continues to expose the
existing `VERSION` and `BUILD_REVISION` constants; embedded builds use the getters.

Downstream test suites can enable `test-build-info` through dev-dependencies
only. It lazily installs a deterministic `0.0.0-dev+test` / `test-fixture`
identity when a test does not install one explicitly. Production dependencies
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
Resolved
must use only `embedded-build-info`; verify real-binary startup separately
without the fixture feature so missing initialization still fails closed.

### The bridge contract

The bridge's methods, events and types are declared once in Rust
Expand Down
13 changes: 10 additions & 3 deletions crates/relay-node/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,20 @@ fn git_path(name: &str) -> Option<PathBuf> {
}

fn main() {
println!("cargo:rerun-if-env-changed=AGENT_RELAY_SITE_URL");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_URL_SCHEME");
println!("cargo:rerun-if-changed=build_site.rs");
if env::var_os("CARGO_FEATURE_EMBEDDED_BUILD_INFO").is_some() {
// Only the executable owns release identity and Windows resources.
// Site and scheme remain compile-time properties of the core.
println!("cargo:rerun-if-changed=build.rs");
built_in_site();
return;
}
println!("cargo:rerun-if-env-changed=AGENT_RELAY_PROBE_VERSION");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_PROBE_BASE_VERSION");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_PROBE_CHANGELOG");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_PROBE_GIT_DIR");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_SITE_URL");
println!("cargo:rerun-if-env-changed=AGENT_RELAY_URL_SCHEME");
println!("cargo:rerun-if-changed=build_site.rs");
println!("cargo:rerun-if-changed=Cargo.lock");
println!("cargo:rerun-if-changed=build_version.rs");
// Resolve through git so linked worktrees also track their own HEAD.
Expand Down
76 changes: 76 additions & 0 deletions crates/relay-node/src/build_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//! Identity supplied by an embedding executable, before it starts the node.
//!
//! Only the executable's version and source revision belong here. Site,
//! scheme and other build-profile values remain checked at compile time.
//!
//! `test-build-info` is an explicit dev-dependency-only fixture: its first
//! identity query installs a deterministic test identity unless an executable
//! already initialized one. Production bootstrap must be tested separately
//! with `embedded-build-info` and without that fixture feature.

#[cfg(feature = "embedded-build-info")]
use std::sync::OnceLock;

/// The embedding executable's compiled identity. Static strings keep the
/// identity immutable for the process without reading runtime configuration.
#[cfg(feature = "embedded-build-info")]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct BuildInfo {
pub version: &'static str,
pub revision: &'static str,
}

#[cfg(feature = "embedded-build-info")]
static BUILD_INFO: OnceLock<BuildInfo> = OnceLock::new();

/// Install the executable's identity before calling the CLI or constructing
/// a node. The first caller wins; a later call returns its rejected identity,
/// including when it supplies the same strings as the first call.
#[cfg(feature = "embedded-build-info")]
pub fn install_build_info(info: BuildInfo) -> Result<(), BuildInfo> {
BUILD_INFO.set(info)
}

#[cfg(feature = "embedded-build-info")]
fn installed() -> &'static BuildInfo {
#[cfg(feature = "test-build-info")]
{
BUILD_INFO.get_or_init(|| BuildInfo {
version: "0.0.0-dev+test",
revision: "test-fixture",
})
}
#[cfg(not(feature = "test-build-info"))]
{
BUILD_INFO
.get()
.expect("embedded build identity must be installed before use")
}
}

/// The release version, or Git-identified development version, of the node's
/// executable. Embedded builds require `install_build_info` before access,
/// except when the explicit `test-build-info` fixture feature is enabled.
pub fn version() -> &'static str {
#[cfg(feature = "embedded-build-info")]
{
installed().version
}
#[cfg(not(feature = "embedded-build-info"))]
{
crate::VERSION
}
}

/// The source revision of the node's executable. Embedded builds require
/// `install_build_info` before access, except with the `test-build-info` fixture.
pub fn build_revision() -> &'static str {
#[cfg(feature = "embedded-build-info")]
{
installed().revision
}
#[cfg(not(feature = "embedded-build-info"))]
{
crate::BUILD_REVISION
}
}
2 changes: 1 addition & 1 deletion crates/relay-node/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(
name = "agent-relay-node",
version = crate::VERSION,
version = crate::version(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: This clap attribute now calls crate::version(), which panics in embedded-build-info builds unless identity was installed. The #[cfg(test)] modules below call Cli::try_parse_from / Cli::command() without installing identity, so they will panic in strict embedding test runs of the lib unit tests. Install a fixed test identity in those tests, or keep the CLI unit tests out of the strict embedded configuration.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At crates/relay-node/src/cli.rs, line 16:

<comment>This clap attribute now calls `crate::version()`, which panics in `embedded-build-info` builds unless identity was installed. The `#[cfg(test)]` modules below call `Cli::try_parse_from` / `Cli::command()` without installing identity, so they will panic in strict embedding test runs of the lib unit tests. Install a fixed test identity in those tests, or keep the CLI unit tests out of the strict embedded configuration.</comment>

<file context>
@@ -13,7 +13,7 @@ use clap::{Parser, Subcommand};
 #[command(
     name = "agent-relay-node",
-    version = crate::VERSION,
+    version = crate::version(),
     propagate_version = true,
     about = "Connect coding sessions to Agent Relay"
</file context>

propagate_version = true,
about = "Connect coding sessions to Agent Relay"
)]
Expand Down
10 changes: 10 additions & 0 deletions crates/relay-node/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
//! The Agent Relay core: the messaging runtime (`relay`) and Relay Connect
//! rooms. `agent-relay-node` (src/cli) is its binary.
#[cfg(all(feature = "embedded-build-info", feature = "production-binaries"))]
compile_error!("embedded-build-info is library-only; disable default features and initialize identity from the embedding executable");

/// The stamped release (AGENT_RELAY_PROBE_VERSION), or a Git-identified development build. The internal
/// Cargo package version is never presented as a separate product release.
#[cfg(not(feature = "embedded-build-info"))]
pub const VERSION: &str = env!("RELAY_DESKTOP_VERSION");
#[cfg(not(feature = "embedded-build-info"))]
pub const BUILD_REVISION: &str = env!("RELAY_DESKTOP_REVISION");

mod build_info;
pub use build_info::{build_revision, version};
#[cfg(feature = "embedded-build-info")]
pub use build_info::{install_build_info, BuildInfo};

/// The build-time check of `AGENT_RELAY_SITE_URL` and `AGENT_RELAY_URL_SCHEME`
/// (`build.rs`), tested here.
#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion crates/relay-node/src/relay/cloud_http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ pub fn send_raw_blocking(
.set("Accept", "application/json")
.set(
"User-Agent",
&format!("AgentRelayDesktop/{}", crate::VERSION),
&format!("AgentRelayDesktop/{}", crate::version()),
);
if let Some(bearer) = bearer {
request = request.set("Authorization", &format!("Bearer {bearer}"));
Expand Down
Loading