From 2d69e040006fe6cd6dc7cef60b631168c6e5f648 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 1 Nov 2026 10:25:12 -0800 Subject: [PATCH 1/4] Rename ChatGPT adapter and accept both paired-client sockets --- crates/fractal-chatgpt/Cargo.toml | 2 +- crates/fractal-chatgpt/src/lib.rs | 6 ++-- crates/fractal-chatgpt/src/tests.rs | 15 ++++++++++ docs/site/reference/mcp-server.md | 28 +++++++++---------- flake.nix | 16 +++++++---- .../fractal-chatgpt-reader-rename.json | 11 ++++++++ 6 files changed, 55 insertions(+), 23 deletions(-) create mode 100644 release-notes/fractal-chatgpt-reader-rename.json diff --git a/crates/fractal-chatgpt/Cargo.toml b/crates/fractal-chatgpt/Cargo.toml index b1bb7db2d33..3a7f6b9271f 100644 --- a/crates/fractal-chatgpt/Cargo.toml +++ b/crates/fractal-chatgpt/Cargo.toml @@ -21,5 +21,5 @@ tempfile = "3" parking_lot = "0.12" [[bin]] -name = "st-chatgpt" +name = "fractal-chatgpt" path = "src/main.rs" diff --git a/crates/fractal-chatgpt/src/lib.rs b/crates/fractal-chatgpt/src/lib.rs index ea216343c26..0715c0c3359 100644 --- a/crates/fractal-chatgpt/src/lib.rs +++ b/crates/fractal-chatgpt/src/lib.rs @@ -10,8 +10,8 @@ use std::{io::{self, Read}, path::Path, os::unix::fs::{OpenOptionsExt, MetadataE pub struct Adapter { client: reqwest::Client, bearer: String } impl Adapter { pub fn new(socket: &Path, credential_file: &Path) -> Result> { - if socket.file_name().and_then(|name| name.to_str()) != Some("st3-client.sock") { - return Err("only the paired gateway st3-client.sock is permitted".into()); + if !matches!(socket.file_name().and_then(|name| name.to_str()), Some("fractal-client.sock" | "st3-client.sock")) { + return Err("only the paired gateways fractal-client.sock and st3-client.sock are permitted".into()); } let bearer = read_credential(credential_file)?; let client = reqwest::Client::builder().unix_socket(socket).build()?; @@ -296,7 +296,7 @@ async fn dispatch(adapter: &Adapter, name: &str, args: &Value, observation: &mut impl ServerHandler for Adapter { fn get_info(&self) -> ServerConfig { ServerConfig::new(ServerCapabilities::builder().enable_tools().build()) - .with_server_info(Implementation::new("st-chatgpt",env!("CARGO_PKG_VERSION"))) + .with_server_info(Implementation::new("fractal-chatgpt",env!("CARGO_PKG_VERSION"))) } async fn list_tools(&self, _:Option, _:RequestContext) -> Result { Ok(ListToolsResult { tools: tool_definitions(), ..Default::default() }) diff --git a/crates/fractal-chatgpt/src/tests.rs b/crates/fractal-chatgpt/src/tests.rs index 43774a7a2c1..f48fb0b9071 100644 --- a/crates/fractal-chatgpt/src/tests.rs +++ b/crates/fractal-chatgpt/src/tests.rs @@ -10,6 +10,21 @@ fn disconnected_adapter() -> Adapter { } } +#[test] +fn adapter_accepts_only_paired_gateway_socket_names() { + let dir = tempfile::tempdir().unwrap(); + let credential = dir.path().join("credential"); + std::fs::write(&credential, "test-token\n").unwrap(); + std::fs::set_permissions(&credential, std::fs::Permissions::from_mode(0o600)).unwrap(); + for name in ["fractal-client.sock", "st3-client.sock"] { + assert!(Adapter::new(&dir.path().join(name), &credential).is_ok(), "{name}"); + } + for name in ["fractal.sock", "st3.sock", "other.sock", "fractal-client.sock.bak", ""] { + let error = Adapter::new(&dir.path().join(name), &credential).err().unwrap().to_string(); + assert_eq!(error, "only the paired gateways fractal-client.sock and st3-client.sock are permitted", "{name}"); + } +} + #[test] fn discovery_has_exactly_eleven_closed_tools_and_correct_hints() { let expected = [ diff --git a/docs/site/reference/mcp-server.md b/docs/site/reference/mcp-server.md index 799f8095983..a650356b1ae 100644 --- a/docs/site/reference/mcp-server.md +++ b/docs/site/reference/mcp-server.md @@ -8,7 +8,7 @@ order: 6 The Fractal MCP server connects an MCP client to the daemon's paired-client gateway. It exposes a closed set of tools for alerts, missions, agents, conversations, and explicitly scoped writes. It does not expose daemon control or give an assistant person authority. -The Rust package is `fractal-chatgpt`; its executable is `st-chatgpt`. The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. +The Rust package and executable are `fractal-chatgpt`. The Nix package also provides the temporary `st-chatgpt` executable alias for existing consumers. The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. The [external-assistant contract](https://github.com/compoundingtech/fractal/blob/main/docs/st3/external-assistants.md) defines the authority and wire behavior. Remote access is a restricted dogfood path, not an authenticated public service. @@ -19,16 +19,16 @@ Install and configure [Fractal](../getting-started/install.md) first. The daemon Build the adapter from the repository root with Rust and the repository's build prerequisites: ```sh -cargo build --release -p fractal-chatgpt --bin st-chatgpt +cargo build --release -p fractal-chatgpt --bin fractal-chatgpt ``` -The binary is `target/release/st-chatgpt`. Alternatively, obtain it from the repository's Nix package: +The binary is `target/release/fractal-chatgpt`. Alternatively, obtain it from the repository's Nix package: ```sh -nix build github:compoundingtech/fractal#st-chatgpt +nix build github:compoundingtech/fractal#fractal-chatgpt ``` -That binary is `result/bin/st-chatgpt`. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. +That binary is `result/bin/fractal-chatgpt`. The temporary `#st-chatgpt` package alias selects the same derivation; both packages include `bin/fractal-chatgpt` and `bin/st-chatgpt`. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. ## Pair and prepare a grant @@ -83,12 +83,12 @@ CLI pairing selects `caller-bound-allow`: reads within the sealed scopes, consen Use stdio when the MCP client launches a local process: ```sh -st-chatgpt --transport stdio \ - --socket /PATH/TO/st3-client.sock \ +fractal-chatgpt --transport stdio \ + --socket /PATH/TO/fractal-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` -Use the daemon's **paired-client** socket, whose filename must be `st3-client.sock`, not its control socket. All paths in the examples are placeholders, not defaults. +Use the daemon's **paired-client** socket, whose filename must be `fractal-client.sock` or `st3-client.sock`, not its control socket (`fractal.sock` or `st3.sock`). Use whichever paired-client name your daemon provides; both are accepted. All paths in the examples are placeholders, not defaults. A generic MCP client configuration looks like this; adapt the outer configuration format to your client. Use absolute paths and keep the bearer out of the configuration: @@ -96,10 +96,10 @@ A generic MCP client configuration looks like this; adapt the outer configuratio { "mcpServers": { "fractal": { - "command": "/PATH/TO/st-chatgpt", + "command": "/PATH/TO/fractal-chatgpt", "args": [ "--transport", "stdio", - "--socket", "/PATH/TO/st3-client.sock", + "--socket", "/PATH/TO/fractal-client.sock", "--credential-file", "/PATH/TO/mcp-private/credential" ] } @@ -112,8 +112,8 @@ A generic MCP client configuration looks like this; adapt the outer configuratio HTTP is the default transport. The default listen address is `127.0.0.1:8787`: ```sh -st-chatgpt --transport http --listen 127.0.0.1:8787 \ - --socket /PATH/TO/st3-client.sock \ +fractal-chatgpt --transport http --listen 127.0.0.1:8787 \ + --socket /PATH/TO/fractal-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` @@ -147,7 +147,7 @@ The table summarizes the descriptions published by the adapter. A scope listed h | `fractal_conversation_read` | `read.assistant.conversation` | Read | Read one bounded revision-pinned conversation content range. | | `fractal_message_send` | `write.assistant.messages` | Write | Send one exact message to any existing agent; person recipients are refused. | -The corresponding `st_*` tool names are hidden, deprecated aliases for cached clients and are removed in `fractal-chatgpt` 0.2.0. Refresh client tool discovery and use `fractal_*`; aliases do not grant additional authority. This deprecation concerns MCP tool names, not the `st-chatgpt` executable name. +The corresponding `st_*` tool names are hidden, deprecated aliases for cached clients and are removed in `fractal-chatgpt` 0.2.0. Refresh client tool discovery and use `fractal_*`; aliases do not grant additional authority. This tool-name deprecation is separate from the temporary `st-chatgpt` executable alias. ## Limits and grant lifecycle @@ -182,7 +182,7 @@ The corresponding `st_*` tool names are hidden, deprecated aliases for cached cl | Missing-scope denial | Inspect the exact grant. Replace policy explicitly if the owner authorizes the scope; do not substitute a person credential. | | `response-budget-exceeded` | Request a smaller page or content range, or raise the requested byte budget within the policy maximum. A single oversized item may still fail. | | `page-cursor-expired` or stale content revision | Restart discovery and use newly returned cursors/read handles. Do not manufacture a cursor or reference. | -| Socket rejected or unavailable | Use the current daemon's `st3-client.sock`, run the adapter on that machine, and check local ownership/access. A control socket is intentionally rejected. | +| Socket rejected or unavailable | Use the current daemon's `fractal-client.sock` or `st3-client.sock`, run the adapter on that machine, and check local ownership/access. Control sockets (`fractal.sock` and `st3.sock`) are intentionally rejected. | | Tunnel connects but tools are unavailable | Check the loopback adapter and grant first, then the operator-owned tunnel's forwarding to `/mcp` and the client's MCP support. Do not expose a non-loopback listener to bypass the problem. | For authority, consent, proof-gated reads, write semantics, and remote-access requirements, read the [external-assistant engineering contract](https://github.com/compoundingtech/fractal/blob/main/docs/st3/external-assistants.md). diff --git a/flake.nix b/flake.nix index 0c8ff945084..5a92cbf0464 100644 --- a/flake.nix +++ b/flake.nix @@ -718,20 +718,23 @@ st3 = fractal; # LIVE-MIGRATION END arn:lmig:smalltalk:2026-10-16-fractal-binary-aliases - stChatgpt = pkgs.rustPlatform.buildRustPackage { - pname = "st-chatgpt"; + fractalChatgpt = pkgs.rustPlatform.buildRustPackage { + pname = "fractal-chatgpt"; inherit version cargoDeps; src = self; - cargoBuildFlags = [ "-p" "fractal-chatgpt" "--bin" "st-chatgpt" ]; + cargoBuildFlags = [ "-p" "fractal-chatgpt" "--bin" "fractal-chatgpt" ]; # .cargo/config.toml links Linux targets with mold. nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.mold ]; # The shared daemon check runs the adapter's Rust tests. doCheck = false; + # LIVE-MIGRATION BRIDGE arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias — DELETE at contraction — https://github.com/compoundingtech/fractal/issues/3032 + postInstall = ''ln -s fractal-chatgpt "$out/bin/st-chatgpt"''; + # LIVE-MIGRATION END arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias meta = { description = "Standalone Fractal ChatGPT MCP adapter"; homepage = "https://github.com/compoundingtech/fractal"; license = pkgs.lib.licenses.mit; - mainProgram = "st-chatgpt"; + mainProgram = "fractal-chatgpt"; }; }; @@ -1099,7 +1102,10 @@ packages.st3 = st3; packages.fractal-web = fractalWeb; packages.fractal = fractal; - packages.st-chatgpt = stChatgpt; + packages.fractal-chatgpt = fractalChatgpt; + # LIVE-MIGRATION BRIDGE arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias — DELETE at contraction — https://github.com/compoundingtech/fractal/issues/3032 + packages.st-chatgpt = fractalChatgpt; + # LIVE-MIGRATION END arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias packages.st-fabric-adapter = stFabricAdapter; # Isolated bootstrap/live proofs use the exact pairing API revision. packages.fabric-pairing = fabric.packages.${system}.default; diff --git a/release-notes/fractal-chatgpt-reader-rename.json b/release-notes/fractal-chatgpt-reader-rename.json new file mode 100644 index 00000000000..6a2233759d4 --- /dev/null +++ b/release-notes/fractal-chatgpt-reader-rename.json @@ -0,0 +1,11 @@ +{ + "version": 1, + "summary": "Name the MCP adapter fractal-chatgpt and accept both paired-client socket names", + "replay": {"status": "none", "detail": "No graph replay or data changes."}, + "schema": {"status": "none", "detail": "No storage schema changes."}, + "rules": {"status": "none", "detail": "No checkpoint or coordination rule changes."}, + "compatibility": {"status": "changed", "detail": "The adapter accepts fractal-client.sock and st3-client.sock; control sockets and other names remain rejected. The canonical Cargo binary and Nix package are fractal-chatgpt. Nix retains the st-chatgpt package alias and executable symlink in the same derivation for existing consumers. MCP server identity is fractal-chatgpt; tools and grant authority are unchanged."}, + "downtime": {"status": "none", "detail": "No daemon restart or service interruption is required by this adapter change."}, + "manual": {"status": "changed", "detail": "Source builds should select --bin fractal-chatgpt. Existing Nix consumers may keep using the st-chatgpt package and executable during the rename bridge. Select the paired-client socket name provided by the running daemon."}, + "recovery": {"status": "none", "detail": "No persistent data is changed. An older adapter can still connect through st3-client.sock while the daemon provides that name."} +} From b65d0c6669b8f1e72357c3d3c96ff3343321c0af Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 1 Nov 2026 22:17:25 -0800 Subject: [PATCH 2/4] Scope adapter rename to package and executable names --- crates/fractal-chatgpt/src/lib.rs | 6 +++--- crates/fractal-chatgpt/src/tests.rs | 15 --------------- docs/site/reference/mcp-server.md | 14 +++++++------- release-notes/fractal-chatgpt-reader-rename.json | 10 +++++----- 4 files changed, 15 insertions(+), 30 deletions(-) diff --git a/crates/fractal-chatgpt/src/lib.rs b/crates/fractal-chatgpt/src/lib.rs index 0715c0c3359..ea216343c26 100644 --- a/crates/fractal-chatgpt/src/lib.rs +++ b/crates/fractal-chatgpt/src/lib.rs @@ -10,8 +10,8 @@ use std::{io::{self, Read}, path::Path, os::unix::fs::{OpenOptionsExt, MetadataE pub struct Adapter { client: reqwest::Client, bearer: String } impl Adapter { pub fn new(socket: &Path, credential_file: &Path) -> Result> { - if !matches!(socket.file_name().and_then(|name| name.to_str()), Some("fractal-client.sock" | "st3-client.sock")) { - return Err("only the paired gateways fractal-client.sock and st3-client.sock are permitted".into()); + if socket.file_name().and_then(|name| name.to_str()) != Some("st3-client.sock") { + return Err("only the paired gateway st3-client.sock is permitted".into()); } let bearer = read_credential(credential_file)?; let client = reqwest::Client::builder().unix_socket(socket).build()?; @@ -296,7 +296,7 @@ async fn dispatch(adapter: &Adapter, name: &str, args: &Value, observation: &mut impl ServerHandler for Adapter { fn get_info(&self) -> ServerConfig { ServerConfig::new(ServerCapabilities::builder().enable_tools().build()) - .with_server_info(Implementation::new("fractal-chatgpt",env!("CARGO_PKG_VERSION"))) + .with_server_info(Implementation::new("st-chatgpt",env!("CARGO_PKG_VERSION"))) } async fn list_tools(&self, _:Option, _:RequestContext) -> Result { Ok(ListToolsResult { tools: tool_definitions(), ..Default::default() }) diff --git a/crates/fractal-chatgpt/src/tests.rs b/crates/fractal-chatgpt/src/tests.rs index f48fb0b9071..43774a7a2c1 100644 --- a/crates/fractal-chatgpt/src/tests.rs +++ b/crates/fractal-chatgpt/src/tests.rs @@ -10,21 +10,6 @@ fn disconnected_adapter() -> Adapter { } } -#[test] -fn adapter_accepts_only_paired_gateway_socket_names() { - let dir = tempfile::tempdir().unwrap(); - let credential = dir.path().join("credential"); - std::fs::write(&credential, "test-token\n").unwrap(); - std::fs::set_permissions(&credential, std::fs::Permissions::from_mode(0o600)).unwrap(); - for name in ["fractal-client.sock", "st3-client.sock"] { - assert!(Adapter::new(&dir.path().join(name), &credential).is_ok(), "{name}"); - } - for name in ["fractal.sock", "st3.sock", "other.sock", "fractal-client.sock.bak", ""] { - let error = Adapter::new(&dir.path().join(name), &credential).err().unwrap().to_string(); - assert_eq!(error, "only the paired gateways fractal-client.sock and st3-client.sock are permitted", "{name}"); - } -} - #[test] fn discovery_has_exactly_eleven_closed_tools_and_correct_hints() { let expected = [ diff --git a/docs/site/reference/mcp-server.md b/docs/site/reference/mcp-server.md index a650356b1ae..335eafcbc1d 100644 --- a/docs/site/reference/mcp-server.md +++ b/docs/site/reference/mcp-server.md @@ -8,7 +8,7 @@ order: 6 The Fractal MCP server connects an MCP client to the daemon's paired-client gateway. It exposes a closed set of tools for alerts, missions, agents, conversations, and explicitly scoped writes. It does not expose daemon control or give an assistant person authority. -The Rust package and executable are `fractal-chatgpt`. The Nix package also provides the temporary `st-chatgpt` executable alias for existing consumers. The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. +The Rust package and canonical executable are `fractal-chatgpt`. The temporary `st-chatgpt` executable alias remains available for existing consumers. The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. The [external-assistant contract](https://github.com/compoundingtech/fractal/blob/main/docs/st3/external-assistants.md) defines the authority and wire behavior. Remote access is a restricted dogfood path, not an authenticated public service. @@ -28,7 +28,7 @@ The binary is `target/release/fractal-chatgpt`. Alternatively, obtain it from th nix build github:compoundingtech/fractal#fractal-chatgpt ``` -That binary is `result/bin/fractal-chatgpt`. The temporary `#st-chatgpt` package alias selects the same derivation; both packages include `bin/fractal-chatgpt` and `bin/st-chatgpt`. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. +That binary is `result/bin/fractal-chatgpt`. The temporary `#st-chatgpt` package alias selects the same derivation and includes both executables. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. ## Pair and prepare a grant @@ -84,11 +84,11 @@ Use stdio when the MCP client launches a local process: ```sh fractal-chatgpt --transport stdio \ - --socket /PATH/TO/fractal-client.sock \ + --socket /PATH/TO/st3-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` -Use the daemon's **paired-client** socket, whose filename must be `fractal-client.sock` or `st3-client.sock`, not its control socket (`fractal.sock` or `st3.sock`). Use whichever paired-client name your daemon provides; both are accepted. All paths in the examples are placeholders, not defaults. +Use the daemon's **paired-client** socket, whose filename must be `st3-client.sock`, not its control socket. All paths in the examples are placeholders, not defaults. A generic MCP client configuration looks like this; adapt the outer configuration format to your client. Use absolute paths and keep the bearer out of the configuration: @@ -99,7 +99,7 @@ A generic MCP client configuration looks like this; adapt the outer configuratio "command": "/PATH/TO/fractal-chatgpt", "args": [ "--transport", "stdio", - "--socket", "/PATH/TO/fractal-client.sock", + "--socket", "/PATH/TO/st3-client.sock", "--credential-file", "/PATH/TO/mcp-private/credential" ] } @@ -113,7 +113,7 @@ HTTP is the default transport. The default listen address is `127.0.0.1:8787`: ```sh fractal-chatgpt --transport http --listen 127.0.0.1:8787 \ - --socket /PATH/TO/fractal-client.sock \ + --socket /PATH/TO/st3-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` @@ -182,7 +182,7 @@ The corresponding `st_*` tool names are hidden, deprecated aliases for cached cl | Missing-scope denial | Inspect the exact grant. Replace policy explicitly if the owner authorizes the scope; do not substitute a person credential. | | `response-budget-exceeded` | Request a smaller page or content range, or raise the requested byte budget within the policy maximum. A single oversized item may still fail. | | `page-cursor-expired` or stale content revision | Restart discovery and use newly returned cursors/read handles. Do not manufacture a cursor or reference. | -| Socket rejected or unavailable | Use the current daemon's `fractal-client.sock` or `st3-client.sock`, run the adapter on that machine, and check local ownership/access. Control sockets (`fractal.sock` and `st3.sock`) are intentionally rejected. | +| Socket rejected or unavailable | Use the current daemon's `st3-client.sock`, run the adapter on that machine, and check local ownership/access. A control socket is intentionally rejected. | | Tunnel connects but tools are unavailable | Check the loopback adapter and grant first, then the operator-owned tunnel's forwarding to `/mcp` and the client's MCP support. Do not expose a non-loopback listener to bypass the problem. | For authority, consent, proof-gated reads, write semantics, and remote-access requirements, read the [external-assistant engineering contract](https://github.com/compoundingtech/fractal/blob/main/docs/st3/external-assistants.md). diff --git a/release-notes/fractal-chatgpt-reader-rename.json b/release-notes/fractal-chatgpt-reader-rename.json index 6a2233759d4..10fd6bfd4cb 100644 --- a/release-notes/fractal-chatgpt-reader-rename.json +++ b/release-notes/fractal-chatgpt-reader-rename.json @@ -1,11 +1,11 @@ { "version": 1, - "summary": "Name the MCP adapter fractal-chatgpt and accept both paired-client socket names", + "summary": "Rename the ChatGPT adapter package and executable to fractal-chatgpt", "replay": {"status": "none", "detail": "No graph replay or data changes."}, "schema": {"status": "none", "detail": "No storage schema changes."}, "rules": {"status": "none", "detail": "No checkpoint or coordination rule changes."}, - "compatibility": {"status": "changed", "detail": "The adapter accepts fractal-client.sock and st3-client.sock; control sockets and other names remain rejected. The canonical Cargo binary and Nix package are fractal-chatgpt. Nix retains the st-chatgpt package alias and executable symlink in the same derivation for existing consumers. MCP server identity is fractal-chatgpt; tools and grant authority are unchanged."}, - "downtime": {"status": "none", "detail": "No daemon restart or service interruption is required by this adapter change."}, - "manual": {"status": "changed", "detail": "Source builds should select --bin fractal-chatgpt. Existing Nix consumers may keep using the st-chatgpt package and executable during the rename bridge. Select the paired-client socket name provided by the running daemon."}, - "recovery": {"status": "none", "detail": "No persistent data is changed. An older adapter can still connect through st3-client.sock while the daemon provides that name."} + "compatibility": {"status": "changed", "detail": "The canonical Cargo binary and Nix package are fractal-chatgpt. Nix retains the st-chatgpt package alias and executable symlink in the same derivation for existing consumers. Tools, grant authority, and socket acceptance are unchanged."}, + "downtime": {"status": "none", "detail": "No daemon restart or service interruption is required by this package rename."}, + "manual": {"status": "changed", "detail": "Source builds should select --bin fractal-chatgpt. Existing Nix consumers may keep using the st-chatgpt package and executable during the rename bridge."}, + "recovery": {"status": "none", "detail": "No persistent data is changed. The retained st-chatgpt executable alias continues to invoke the same adapter."} } From 2e896cb3f76c137af490293e6ca40dff7d7cee95 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 1 Nov 2026 22:26:16 -0800 Subject: [PATCH 3/4] Point source builds at fractal-chatgpt --- docs/site/reference/mcp-server.md | 4 ++-- docs/st3/client-v0/README.md | 2 +- scripts/chatgpt-prototype-e2e.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/site/reference/mcp-server.md b/docs/site/reference/mcp-server.md index 335eafcbc1d..6a4c7aa922f 100644 --- a/docs/site/reference/mcp-server.md +++ b/docs/site/reference/mcp-server.md @@ -83,7 +83,7 @@ CLI pairing selects `caller-bound-allow`: reads within the sealed scopes, consen Use stdio when the MCP client launches a local process: ```sh -fractal-chatgpt --transport stdio \ +st-chatgpt --transport stdio \ --socket /PATH/TO/st3-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` @@ -112,7 +112,7 @@ A generic MCP client configuration looks like this; adapt the outer configuratio HTTP is the default transport. The default listen address is `127.0.0.1:8787`: ```sh -fractal-chatgpt --transport http --listen 127.0.0.1:8787 \ +st-chatgpt --transport http --listen 127.0.0.1:8787 \ --socket /PATH/TO/st3-client.sock \ --credential-file /PATH/TO/mcp-private/credential ``` diff --git a/docs/st3/client-v0/README.md b/docs/st3/client-v0/README.md index ed86377f21b..e623f003e91 100644 --- a/docs/st3/client-v0/README.md +++ b/docs/st3/client-v0/README.md @@ -1764,7 +1764,7 @@ The shared `checks.st3` suite includes the adapter's Rust tests. Rerun the scratch exercise (no live daemon or ChatGPT application is touched): ```sh -nix develop -c bash -c 'export CARGO_TARGET_DIR=tmp/target; cargo run -p fractal-client-codegen && cargo build -j 2 -p fractal-chatgpt -p fractal --features fractal/test-support --bin st-chatgpt --bin fractal --example chatgpt_fixture && cargo test -j 2 -p fractal-chatgpt && cargo test -j 2 -p fractal --test assistant_native && python3 scripts/chatgpt-prototype-e2e.py' +nix develop -c bash -c 'export CARGO_TARGET_DIR=tmp/target; cargo run -p fractal-client-codegen && cargo build -j 2 -p fractal-chatgpt -p fractal --features fractal/test-support --bin fractal-chatgpt --bin fractal --example chatgpt_fixture && cargo test -j 2 -p fractal-chatgpt && cargo test -j 2 -p fractal --test assistant_native && python3 scripts/chatgpt-prototype-e2e.py' ``` The script starts the repository API harness with its own persistent store, paired gateway, diff --git a/scripts/chatgpt-prototype-e2e.py b/scripts/chatgpt-prototype-e2e.py index 8e4386c7abd..9565fbafcdf 100755 --- a/scripts/chatgpt-prototype-e2e.py +++ b/scripts/chatgpt-prototype-e2e.py @@ -120,7 +120,7 @@ def replace_expired_grant(): with socket.socket() as listener: listener.bind(('127.0.0.1',0)); port=listener.getsockname()[1] endpoint='http://127.0.0.1:'+str(port)+'/mcp' - adapter_args=[str(BIN/'st-chatgpt'),'--socket',str(STATE/'st3-client.sock'),'--credential-file',str(credential)] + adapter_args=[str(BIN/'fractal-chatgpt'),'--socket',str(STATE/'st3-client.sock'),'--credential-file',str(credential)] adapter=start(adapter_args+['--listen','127.0.0.1:'+str(port)],'adapter.log') def listening(): try: From 9f76b750edb0c96af7afa97317489006a6945887 Mon Sep 17 00:00:00 2001 From: schickling-assistant <261620128+schickling-assistant@users.noreply.github.com> Date: Sun, 1 Nov 2026 22:49:04 -0800 Subject: [PATCH 4/4] Build fractal-chatgpt and keep the st-chatgpt binary alias --- crates/fractal-chatgpt/Cargo.toml | 5 +++++ docs/site/reference/mcp-server.md | 10 +++++----- docs/st3/client-v0/README.md | 2 +- flake.nix | 16 +++++----------- release-notes/fractal-chatgpt-reader-rename.json | 10 +++++----- scripts/chatgpt-prototype-e2e.py | 2 +- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/crates/fractal-chatgpt/Cargo.toml b/crates/fractal-chatgpt/Cargo.toml index 3a7f6b9271f..85efd3dc54a 100644 --- a/crates/fractal-chatgpt/Cargo.toml +++ b/crates/fractal-chatgpt/Cargo.toml @@ -23,3 +23,8 @@ parking_lot = "0.12" [[bin]] name = "fractal-chatgpt" path = "src/main.rs" + +# Keep the existing Nix package buildable until its package-name cutover. +[[bin]] +name = "st-chatgpt" +path = "src/main.rs" diff --git a/docs/site/reference/mcp-server.md b/docs/site/reference/mcp-server.md index 6a4c7aa922f..603978e46eb 100644 --- a/docs/site/reference/mcp-server.md +++ b/docs/site/reference/mcp-server.md @@ -8,7 +8,7 @@ order: 6 The Fractal MCP server connects an MCP client to the daemon's paired-client gateway. It exposes a closed set of tools for alerts, missions, agents, conversations, and explicitly scoped writes. It does not expose daemon control or give an assistant person authority. -The Rust package and canonical executable are `fractal-chatgpt`. The temporary `st-chatgpt` executable alias remains available for existing consumers. The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. +The Rust package is `fractal-chatgpt`; its binary is `fractal-chatgpt` (`st-chatgpt` kept as an alias binary). The supported assistant principal is `assistant/chatgpt`, including when a generic MCP client uses the adapter. Pairing requires the configured owning person's explicit consent to disclose assistant reads to OpenAI. Do not use a person credential for this server. The [external-assistant contract](https://github.com/compoundingtech/fractal/blob/main/docs/st3/external-assistants.md) defines the authority and wire behavior. Remote access is a restricted dogfood path, not an authenticated public service. @@ -22,13 +22,13 @@ Build the adapter from the repository root with Rust and the repository's build cargo build --release -p fractal-chatgpt --bin fractal-chatgpt ``` -The binary is `target/release/fractal-chatgpt`. Alternatively, obtain it from the repository's Nix package: +The binary is `target/release/fractal-chatgpt` (`st-chatgpt` kept as an alias binary). Alternatively, obtain the current Nix package: ```sh -nix build github:compoundingtech/fractal#fractal-chatgpt +nix build github:compoundingtech/fractal#st-chatgpt ``` -That binary is `result/bin/fractal-chatgpt`. The temporary `#st-chatgpt` package alias selects the same derivation and includes both executables. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. +That binary is `result/bin/st-chatgpt`. Use a matching Fractal revision. The examples below assume the binary is on `PATH`. ## Pair and prepare a grant @@ -147,7 +147,7 @@ The table summarizes the descriptions published by the adapter. A scope listed h | `fractal_conversation_read` | `read.assistant.conversation` | Read | Read one bounded revision-pinned conversation content range. | | `fractal_message_send` | `write.assistant.messages` | Write | Send one exact message to any existing agent; person recipients are refused. | -The corresponding `st_*` tool names are hidden, deprecated aliases for cached clients and are removed in `fractal-chatgpt` 0.2.0. Refresh client tool discovery and use `fractal_*`; aliases do not grant additional authority. This tool-name deprecation is separate from the temporary `st-chatgpt` executable alias. +The corresponding `st_*` tool names are hidden, deprecated aliases for cached clients and are removed in `fractal-chatgpt` 0.2.0. Refresh client tool discovery and use `fractal_*`; aliases do not grant additional authority. This tool-name deprecation is separate from the `st-chatgpt` alias binary. ## Limits and grant lifecycle diff --git a/docs/st3/client-v0/README.md b/docs/st3/client-v0/README.md index 25496f4a0f5..f9c49f0695a 100644 --- a/docs/st3/client-v0/README.md +++ b/docs/st3/client-v0/README.md @@ -1779,7 +1779,7 @@ The shared `checks.st3` suite includes the adapter's Rust tests. Rerun the scratch exercise (no live daemon or ChatGPT application is touched): ```sh -nix develop -c bash -c 'export CARGO_TARGET_DIR=tmp/target; cargo run -p fractal-client-codegen && cargo build -j 2 -p fractal-chatgpt -p fractal -p fractal-cli --features fractal/test-support --bin fractal-chatgpt --bin fractal --example chatgpt_fixture && cargo test -j 2 -p fractal-chatgpt && cargo test -j 2 -p fractal --test assistant_native && python3 scripts/chatgpt-prototype-e2e.py' +nix develop -c bash -c 'export CARGO_TARGET_DIR=tmp/target; cargo run -p fractal-client-codegen && cargo build -j 2 -p fractal-chatgpt -p fractal -p fractal-cli --features fractal/test-support --bin st-chatgpt --bin fractal --example chatgpt_fixture && cargo test -j 2 -p fractal-chatgpt && cargo test -j 2 -p fractal --test assistant_native && python3 scripts/chatgpt-prototype-e2e.py' ``` The script starts the repository API harness with its own persistent store, paired gateway, diff --git a/flake.nix b/flake.nix index a2fa551eeeb..493331b74a1 100644 --- a/flake.nix +++ b/flake.nix @@ -722,23 +722,20 @@ st3 = fractal; # LIVE-MIGRATION END arn:lmig:smalltalk:2026-10-16-fractal-binary-aliases - fractalChatgpt = pkgs.rustPlatform.buildRustPackage { - pname = "fractal-chatgpt"; + stChatgpt = pkgs.rustPlatform.buildRustPackage { + pname = "st-chatgpt"; inherit version cargoDeps; src = self; - cargoBuildFlags = [ "-p" "fractal-chatgpt" "--bin" "fractal-chatgpt" ]; + cargoBuildFlags = [ "-p" "fractal-chatgpt" "--bin" "st-chatgpt" ]; # .cargo/config.toml links Linux targets with mold. nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.mold ]; # The shared daemon check runs the adapter's Rust tests. doCheck = false; - # LIVE-MIGRATION BRIDGE arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias — DELETE at contraction — https://github.com/compoundingtech/fractal/issues/3032 - postInstall = ''ln -s fractal-chatgpt "$out/bin/st-chatgpt"''; - # LIVE-MIGRATION END arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias meta = { description = "Standalone Fractal ChatGPT MCP adapter"; homepage = "https://github.com/compoundingtech/fractal"; license = pkgs.lib.licenses.mit; - mainProgram = "fractal-chatgpt"; + mainProgram = "st-chatgpt"; }; }; @@ -1106,10 +1103,7 @@ packages.st3 = st3; packages.fractal-web = fractalWeb; packages.fractal = fractal; - packages.fractal-chatgpt = fractalChatgpt; - # LIVE-MIGRATION BRIDGE arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias — DELETE at contraction — https://github.com/compoundingtech/fractal/issues/3032 - packages.st-chatgpt = fractalChatgpt; - # LIVE-MIGRATION END arn:lmig:smalltalk:2026-11-01-fractal-chatgpt-alias + packages.st-chatgpt = stChatgpt; packages.st-fabric-adapter = stFabricAdapter; # Isolated bootstrap/live proofs use the exact pairing API revision. packages.fabric-pairing = fabric.packages.${system}.default; diff --git a/release-notes/fractal-chatgpt-reader-rename.json b/release-notes/fractal-chatgpt-reader-rename.json index 10fd6bfd4cb..7790b759521 100644 --- a/release-notes/fractal-chatgpt-reader-rename.json +++ b/release-notes/fractal-chatgpt-reader-rename.json @@ -1,11 +1,11 @@ { "version": 1, - "summary": "Rename the ChatGPT adapter package and executable to fractal-chatgpt", + "summary": "Add the fractal-chatgpt adapter binary and keep st-chatgpt as an alias binary", "replay": {"status": "none", "detail": "No graph replay or data changes."}, "schema": {"status": "none", "detail": "No storage schema changes."}, "rules": {"status": "none", "detail": "No checkpoint or coordination rule changes."}, - "compatibility": {"status": "changed", "detail": "The canonical Cargo binary and Nix package are fractal-chatgpt. Nix retains the st-chatgpt package alias and executable symlink in the same derivation for existing consumers. Tools, grant authority, and socket acceptance are unchanged."}, - "downtime": {"status": "none", "detail": "No daemon restart or service interruption is required by this package rename."}, - "manual": {"status": "changed", "detail": "Source builds should select --bin fractal-chatgpt. Existing Nix consumers may keep using the st-chatgpt package and executable during the rename bridge."}, - "recovery": {"status": "none", "detail": "No persistent data is changed. The retained st-chatgpt executable alias continues to invoke the same adapter."} + "compatibility": {"status": "changed", "detail": "The package builds binary fractal-chatgpt (st-chatgpt kept as an alias binary). Both targets compile the same source. Nix package names and lane inputs are unchanged."}, + "downtime": {"status": "none", "detail": "No daemon restart or service interruption is required."}, + "manual": {"status": "changed", "detail": "Source builds can select --bin fractal-chatgpt. Existing --bin st-chatgpt builds and the current Nix package continue to produce the alias binary."}, + "recovery": {"status": "none", "detail": "No persistent data is changed. The alias binary continues to invoke the same adapter."} } diff --git a/scripts/chatgpt-prototype-e2e.py b/scripts/chatgpt-prototype-e2e.py index 9565fbafcdf..8e4386c7abd 100755 --- a/scripts/chatgpt-prototype-e2e.py +++ b/scripts/chatgpt-prototype-e2e.py @@ -120,7 +120,7 @@ def replace_expired_grant(): with socket.socket() as listener: listener.bind(('127.0.0.1',0)); port=listener.getsockname()[1] endpoint='http://127.0.0.1:'+str(port)+'/mcp' - adapter_args=[str(BIN/'fractal-chatgpt'),'--socket',str(STATE/'st3-client.sock'),'--credential-file',str(credential)] + adapter_args=[str(BIN/'st-chatgpt'),'--socket',str(STATE/'st3-client.sock'),'--credential-file',str(credential)] adapter=start(adapter_args+['--listen','127.0.0.1:'+str(port)],'adapter.log') def listening(): try: