Skip to content

gstack-slug inherits outer-repo slug when project is a subdirectory; cache is unrecoverable #1125

@yoelf22

Description

@yoelf22

Title: gstack-slug inherits outer-repo slug when project is a subdirectory; poisoned cache is unrecoverable

Summary

bin/gstack-slug derives the project slug from git remote get-url origin. When the current working directory is a subdirectory of a larger git repo (e.g., a standalone project living inside a shared workspace repo), git walks up and returns the outer repo's remote. The resulting slug belongs to the outer repo, not the actual project. That slug is then cached at ~/.gstack/slug-cache/{pwd-encoded} with no TTL, no invalidation path, and no override — so once it's wrong, it stays wrong across every future session for that path.

Repro

  1. Have a git repo at /Users/me/workspace with remote origin pointing to me/workspace.
  2. Create a new project dir at /Users/me/workspace/IoTopia/ (no .git of its own).
  3. cd /Users/me/workspace/IoTopia && gstack-slug

Expected

Slug reflects the IoTopia project — either prompt the user, or fall back to basename since this dir is not the repo root.

Actual

SLUG=me-workspace

The outer repo's slug. ~/.gstack/projects/me-workspace/ now collects artifacts for an unrelated project, and ~/.gstack/slug-cache/_Users_me_workspace_IoTopia locks that mistake in.

Root cause

bin/gstack-slug lines ~22–28:

REMOTE_URL=$(git remote get-url origin 2>/dev/null) || REMOTE_URL=""
if [[ -n "$REMOTE_URL" ]]; then
  RAW_SLUG=$(printf '%s' "$REMOTE_URL" | sed '...')
  SLUG=$(printf '%s' "$RAW_SLUG" | tr -cd 'a-zA-Z0-9._-')
fi

There is no check for whether $PWD is actually the repo's top-level. Any subdirectory inherits the parent repo's identity.

Impact

Downstream skills (office-hours, plan-ceo-review, plan-eng-review, autoplan, design-consultation, etc.) read/write under ~/.gstack/projects/{slug}/. When slug is wrong, artifacts land in the wrong project's folder and cross-contaminate unrelated work. Users only notice after the fact, and manual cleanup of both ~/.gstack/projects/ and ~/.gstack/slug-cache/ is needed.

Suggested fixes (in order of increasing ambition)

  1. Subdir guard. Before trusting the remote URL, check git rev-parse --show-toplevel against $PWD. If they differ, don't inherit the outer slug — fall through to basename, or prompt.
  2. Per-project override. If a .gstack-slug file exists in $PWD, use its contents verbatim and skip all inference. Cheap, user-controllable, survives gstack-upgrade.
  3. Cache management. Add gstack-slug --reset to clear the cache entry for $PWD, and gstack-slug --set <slug> to write one explicitly. Also consider a TTL or a staleness warning when the cached slug doesn't match what the resolver would compute today.
  4. Interactive first-run. For a new path that has no cache entry and ambiguous inference (subdir of another repo, no .git, etc.), prompt once and persist the choice to .gstack-slug.

Environment

  • gstack version: 1.5.1.0
  • OS: macOS (Darwin 25.3.0)
  • Shell: zsh

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions