fix(agents-vault): dedupe local-slug formula, drop dead code, widen migration coverage

The slug-migration fallback (used when there is no live symlink to read
the previous slug from) recomputed the local-* candidate by lowercasing
the basename only, while _agents_repo_slug sanitizes it. The two formulas
had drifted, so the fallback silently found nothing for any project
directory whose basename needed sanitizing.

Extract the formula into a single private helper,
_agents_repo_local_slug, and have both _agents_repo_slug's no-remote
branch and agents-vault's migration fallback call it, so there is one
place left to drift.

Also drop two dead lines the review flagged: an unused  local,
and an unreachable mkdir -p (path dirname ...) — slugs never contain a
path separator, so dirname always resolves to a directory that already
exists by that point.

Widen migration test coverage: the current-entry-present-but-empty case,
a remote URL rewrite, a remote removal, and a dirty-basename fallback
test that fails without the sanitization fix and passes with it.
This commit is contained in:
2026-09-03 18:56:45 -04:00
parent b7ff4e0981
commit a018d7997c
4 changed files with 150 additions and 12 deletions
+40
View File
@@ -0,0 +1,40 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# _agents_repo_local_slug <dir>
#
# DESCRIPTION
# Builds the path-derived fallback slug used when a project has no git
# remote: local-<sanitized-basename>-<8 hex of sha256(realpath)>. The
# basename is lowercased and every character outside [a-z0-9._-] is
# mapped to a dash, matching the sanitization the remote-URL branch of
# _agents_repo_slug applies to hostnames and paths.
#
# This is the single source of truth for that formula. It exists so the
# rule is written once: _agents_repo_slug's no-remote branch calls it to
# produce the slug, and agents-vault's slug-migration fallback (used when
# there is no live symlink yet to read the previous slug from) calls it
# to recompute the same candidate. Duplicating the formula in both places
# let them drift once before; this closes that gap for good.
#
# ARGUMENTS
# dir Absolute or relative path to the project directory
#
# EXIT STATUS
# 0 Slug printed
# 1 No directory argument given
#
# RETURNS
# The local-* slug, one line on stdout.
#
# EXAMPLE
# set -l slug (_agents_repo_local_slug /home/user/myproject)
function _agents_repo_local_slug --argument-names dir
test -n "$dir"; or return 1
set -l rp (path resolve "$dir")
set -l base (string lower -- (path basename "$rp") | string replace -ra '[^a-z0-9._-]' '-')
set -l digest (printf '%s' "$rp" | sha256sum | string split -f1 ' ')
printf 'local-%s-%s\n' "$base" (string sub -l 8 -- "$digest")
end
+4 -4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# DEPENDENCIES
# _agents_repo_local_slug
#
# SYNOPSIS
# _agents_repo_slug <dir>
#
@@ -63,8 +66,5 @@ function _agents_repo_slug --argument-names dir
return 0
end
set -l rp (path resolve "$dir")
set -l base (string lower -- (path basename "$rp") | string replace -ra '[^a-z0-9._-]' '-')
set -l digest (printf '%s' "$rp" | sha256sum | string split -f1 ' ')
printf 'local-%s-%s\n' "$base" (string sub -l 8 -- "$digest")
_agents_repo_local_slug "$dir"
end
+4 -8
View File
@@ -5,8 +5,9 @@
# 12-ai-and-developer-tools
#
# DEPENDENCIES
# _agents_vault_dir, _agents_repo_slug, _agents_repo_ensure_symlink,
# _agents_repo_sync, _agents_repo_install_tools, git, hostname
# _agents_vault_dir, _agents_repo_slug, _agents_repo_local_slug,
# _agents_repo_ensure_symlink, _agents_repo_sync,
# _agents_repo_install_tools, git, hostname
#
# SYNOPSIS
# agents-vault [--link] [--push] [--restore] [--status]
@@ -230,17 +231,13 @@ function agents-vault --description 'track curated agent memory in a host-scoped
end
if test -z "$prev_slug"
# No link yet (fresh machine): try the path-derived candidate.
set -l cand_rp (path resolve "$root")
set -l cand_base (string lower -- (path basename "$cand_rp"))
set -l cand_digest (printf '%s' "$cand_rp" | sha256sum | string split -f1 ' ')
set -l cand "local-$cand_base-"(string sub -l 8 -- "$cand_digest")
set -l cand (_agents_repo_local_slug "$root")
if test "$cand" != "$slug"; and test -d "$vault/projects/$cand"
set prev_slug $cand
end
end
if test -n "$prev_slug"; and test "$prev_slug" != "$slug"
set -l prev_mem "$vault/projects/$prev_slug/claude/memory"
set -l cur_content
test -d "$vmem"; and set cur_content (command ls -A "$vmem" 2>/dev/null)
if test (count $cur_content) -gt 0
@@ -249,7 +246,6 @@ function agents-vault --description 'track curated agent memory in a host-scoped
return 1
end
test -d "$vmem"; and rm -rf "$vault/projects/$slug"
mkdir -p (path dirname "$vault/projects/$slug")
if not git -C "$vault" mv "projects/$prev_slug" "projects/$slug" 2>/dev/null
command mv "$vault/projects/$prev_slug" "$vault/projects/$slug"; or return 1
end