fix(wrapper): clarify remote upgrade state

This commit is contained in:
AkitaOnRails
2026-07-22 00:20:36 -03:00
parent 8f14cb639c
commit b479d31f71
4 changed files with 61 additions and 12 deletions
+10 -2
View File
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Fixed
- Corrected Docker-wrapper upgrade guidance: `ai-memory upgrade` no longer
claims a configured remote server is stale when it cannot inspect that
deployment, and the install guide now makes clear that refreshing Docker
script hooks does not convert them to native capture-policy commands.
## [1.17.2] - 2026-07-22
### Added
@@ -29,8 +35,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
the spool/wire. Optional assistant/Stop capture proposed in #196 remains
disabled. Upgrading the binary is sufficient for native Claude Code installs;
script-fallback installs (Docker wrapper, `AI_MEMORY_HOOK_PLATFORM=posix`)
should run `ai-memory install-hooks --agent claude-code --apply` to migrate to
native commands and close the residual local-wire vector ([#196]).
still send the raw field to the server, which strips it immediately on
receipt. Closing the local-wire vector requires a native client on the agent
host and using it to reinstall hooks; running the installer through the
Docker wrapper only refreshes its scripts ([#196]).
### Fixed
- Removed the unused `syntect` dependency and its `plist`, `quick-xml`,
+6 -8
View File
@@ -181,18 +181,16 @@ cmd_upgrade() {
fi
fi
# If the server runs on a different host (homelab scenario), only
# the local wrapper + image + hook scripts got refreshed here.
# Surface that, because the user still needs to deploy on the
# remote box for the server-side binary to update.
# If the server runs on a different host (homelab scenario), this command
# cannot know or change that host's deployment state.
if [ -n "${AI_MEMORY_SERVER_URL:-}" ] \
&& ! echo "${AI_MEMORY_SERVER_URL}" | grep -qE '^https?://(127\.|localhost|\[?::1\]?)'; then
echo
echo "→ Note: AI_MEMORY_SERVER_URL points at ${AI_MEMORY_SERVER_URL}"
echo " Your local image is now up to date, but the remote server still"
echo " runs the previous version. Redeploy on that host (e.g. \`bin/deploy\`"
echo " or \`docker compose pull && docker compose up -d\` in its deploy dir)"
echo " for the server-side binary to update."
echo " ai-memory upgrade updates this wrapper and local image only; it does not"
echo " inspect or redeploy the remote server. If that host is not already current,"
echo " run \`bin/deploy\` or \`docker compose pull && docker compose up -d\`"
echo " in its deploy directory."
fi
mkdir -p "${CACHE_DIR}"
+38
View File
@@ -276,6 +276,44 @@ fn managed_run_wrapper_uses_host_binary_path_and_remote_server_without_docker()
assert!(!docker_record.exists(), "managed run entered Docker");
}
#[cfg(unix)]
#[test]
fn wrapper_upgrade_does_not_claim_an_updated_remote_server_is_stale() {
let tmp = tempfile::tempdir().unwrap();
let docker = tmp.path().join("docker");
std::fs::write(
&docker,
"#!/usr/bin/env bash\n\
case \"$1\" in\n\
pull | ps) exit 0 ;;\n\
*) exit 1 ;;\n\
esac\n",
)
.unwrap();
{
use std::os::unix::fs::PermissionsExt as _;
std::fs::set_permissions(&docker, std::fs::Permissions::from_mode(0o755)).unwrap();
}
let output = shell_script_command(&repo_root().join("bin/ai-memory"))
.arg("upgrade")
.env("AI_MEMORY_DOCKER", &docker)
.env("AI_MEMORY_SKIP_SELF_UPGRADE", "1")
.env("AI_MEMORY_SERVER_URL", "http://192.168.0.90:49374")
.env("HOME", tmp.path())
.output()
.unwrap();
assert!(
output.status.success(),
"wrapper failed: {}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("does not\n inspect or redeploy the remote server"));
assert!(stdout.contains("If that host is not already current"));
assert!(!stdout.contains("remote server still\n runs the previous version"));
}
#[cfg(unix)]
#[test]
fn docker_wrapper_completions_tolerate_an_early_reader_close() {
+7 -2
View File
@@ -401,8 +401,13 @@ Upgrading the binary is sufficient for native Claude Code installs, and pending
spooled events drain with the field stripped as well. Installs that run the
`.sh`/`.ps1` script fallback (the Docker script bundle or an explicit
`AI_MEMORY_HOOK_PLATFORM=posix`) still POST the raw field on the local wire
until they move to native commands: run `install-hooks --agent claude-code
--apply`, which installs native `ai-memory hook` commands where supported.
until they move to native commands. The Docker wrapper deliberately keeps
script commands because a binary path inside its helper container is not valid
on the host; running `install-hooks` through that wrapper refreshes the scripts
but does not convert them. To close the local-wire exposure, install a native
ai-memory client on the agent host, then use that native executable to run
`install-hooks --agent claude-code --apply`. If the script fallback is retained,
the server still strips the field immediately on receipt before persistence.
Native `ai-memory hook --event ...` commands spool events locally. Session start
does a short bounded cleanup drain before fetching a handoff; cancellation-prone