Repository navigation
feat(core): let embedding executables own build identity #2082
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8a7969a
0cef627
cea0fc0
11da9e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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": [], | ||
| "filesChanged": [], | ||
| "projectId": "AgentWorkforce/relay", | ||
| "tags": [], | ||
| "_trace": { | ||
| "startRef": "ad983d7278bab88b0a7d541494521146b869f78a", | ||
| "endRef": "ad983d7278bab88b0a7d541494521146b869f78a" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -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. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Name the public API here: the entry should identify (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
Suggested change
|
||||||
|
|
||||||
| ## [17.0.0] - 2026-11-05 | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Embedded identity API missing from changelog Downstream builders can use Learn moreThe 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 Recommended fix: Add one concise impact-first bullet under the existing Unreleased Changed section naming the new embedding API and its required startup installation. Was this helpful? React with 👍 or 👎 to provide feedback.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Embedded builds still send Prompt for AI agents |
||
| # Deterministic identity fixture for downstream dev-dependencies only. | ||
| test-build-info = ["embedded-build-info"] | ||
|
Comment on lines
+30
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This adds a downstream-facing embedding feature and public identity APIs, but 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"] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
| 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 | ||
|
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 | ||
|
|
||
| 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 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,7 +13,7 @@ use clap::{Parser, Subcommand}; | |
| #[derive(Parser)] | ||
| #[command( | ||
| name = "agent-relay-node", | ||
| version = crate::VERSION, | ||
| version = crate::version(), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: This clap attribute now calls Prompt for AI agents |
||
| propagate_version = true, | ||
| about = "Connect coding sessions to Agent Relay" | ||
| )] | ||
|
|
||
There was a problem hiding this comment.
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
_tracepoints to the same parent revision at both ends. Regenerate it after the implementation commit socommits,filesChanged,startRef, andendRefdescribe this work; otherwise the completed trajectory cannot be audited.(Based on your team's feedback about completed trajectory trace metadata.)
Prompt for AI agents