Skip to content

feat: project-local .gstack/ data storage with auto-migration#505

Open
alfadb wants to merge 7 commits intogarrytan:mainfrom
alfadb:feat/project-local-gstack-data
Open

feat: project-local .gstack/ data storage with auto-migration#505
alfadb wants to merge 7 commits intogarrytan:mainfrom
alfadb:feat/project-local-gstack-data

Conversation

@alfadb
Copy link

@alfadb alfadb commented Mar 26, 2026

Summary

Moves project-scoped data from ~/.gstack/projects/$SLUG/ to {git-root}/.gstack/, enabling:

  • Team collaboration: design docs, review logs, test plans are now git-tracked and visible to all team members
  • Data portability: project data follows the repo when cloned to a new machine
  • Clean separation: machine-local state (browse daemon, logs, caches) lives in .gstack/local/ (gitignored), shared data lives in .gstack/ root (tracked)
  • Zero-friction migration: auto-migrates on first gstack use per project — handles both legacy global data AND existing flat-structure local files

Directory structure

{project}/.gstack/
├── {BRANCH}-reviews.jsonl      ← git-tracked
├── designs/                     ← git-tracked (design docs, architecture, audits)
├── plans/                       ← git-tracked (test plans, autoplan, eng review, CEO plans)
├── evals/                       ← git-tracked (E2E test baselines)
├── local/                       ← gitignored (machine-local)
│   ├── browse.json
│   ├── browse-*.log
│   └── repo-mode.json
├── .gitignore                   ← contains "local/" and ".migrated"
└── .migrated                    ← gitignored, marks auto-migration done

Auto-migration (two phases, fully automatic)

On first gstack skill invocation per project, the preamble runs gstack-migrate-local:

Phase 1 — Global → Local: ~/.gstack/projects/$SLUG/*.gstack/{designs,plans,...}/
Phase 2 — Flat → Organized: .gstack/*-design-*.md.gstack/designs/ (reorganize existing files in place)

  • Deduplicates automatically (same-name files → keep the one in the subdirectory)
  • Handles browse.json/logs → .gstack/local/, architecture docs, implementation plans, roadmaps
  • Creates .migrated marker to skip on subsequent runs
  • Manual: ~/.claude/skills/gstack/bin/gstack-migrate-local [--dry-run]

Changes

New files:

  • bin/gstack-migrate-local: standalone migration script (idempotent, --dry-run supported)

Core infrastructure:

  • bin/gstack-slug: new PROJECT_DATA_DIR output variable
  • scripts/resolvers/preamble.ts + scripts/gen-skill-docs.ts: auto-runs migration in preamble

Data path updates:

  • bin/gstack-review-log, bin/gstack-review-read, bin/gstack-repo-mode: use project-local paths
  • browse/src/config.ts: browse state moves to .gstack/local/; .gitignore management creates .gstack/.gitignore instead of blanket exclusion
  • test/helpers/eval-store.ts: evals write to .gstack/evals/
  • All resolvers (utility.ts, design.ts, testing.ts, review.ts) and 12 .tmpl files updated
  • All 28 SKILL.md files regenerated

Backward compatibility

  • Reads: all read paths check project-local first, fall back to ~/.gstack/projects/$SLUG/
  • Writes: only write to project-local paths
  • Auto-migration: runs once per project, idempotent, non-blocking on failure
  • Browse daemon: old daemon auto-recovers on next invocation at new path

Breaking changes

  • Running browse daemons will not be found after upgrade (auto-recovers on restart)
  • Projects with .gstack/ in .gitignore will have that line removed and replaced with .gstack/.gitignore containing local/

Test plan

  • bun run gen:skill-docs generates all 28 SKILL.md files successfully
  • bun test passes (only pre-existing "Contributor mode" failures, unrelated)
  • gstack-slug outputs 3 variables: SLUG, BRANCH, PROJECT_DATA_DIR
  • All .tmpl legacy path references are in fallback positions only (verified via grep)
  • gstack-migrate-local --dry-run correctly identifies files to migrate
  • Migration tested on real project (uamp) — both phases work correctly

🤖 Generated with Claude Code

alfadb and others added 5 commits March 26, 2026 10:29
gstack-slug now outputs a third variable PROJECT_DATA_DIR pointing to
{git-root}/.gstack, enabling project-local data storage instead of the
global ~/.gstack/projects/$SLUG path. Falls back to the legacy global
path for non-git environments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- gstack-review-log: writes to $PROJECT_DATA_DIR instead of
  ~/.gstack/projects/$SLUG
- gstack-review-read: reads from project-local first, falls back to
  legacy global path for backward compatibility
- gstack-repo-mode: caches repo-mode.json to .gstack/local/ (gitignored)
  instead of ~/.gstack/projects/$SLUG

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…gement

Browse daemon state (browse.json, logs) now lives in .gstack/local/
instead of .gstack/ root. The .gitignore strategy changes from blanket
.gstack/ exclusion to a .gstack/.gitignore containing only "local/",
enabling git-tracked shared data (designs, plans, reviews) in .gstack/.

Migration: automatically removes .gstack/ line from project .gitignore
and creates .gstack/.gitignore with local/ entry.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
getProjectEvalDir() now resolves via git root first (.gstack/evals/),
falling back to the legacy slug-based ~/.gstack/projects/$SLUG/evals/
path for backward compatibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- utility.ts: generateSlugSetup uses $PROJECT_DATA_DIR
- design.ts: design audit docs write to .gstack/designs/
- testing.ts: test plans write to .gstack/plans/
- review.ts: design doc lookup checks .gstack/designs/ first,
  falls back to legacy ~/.gstack/projects/$SLUG/
- gen-skill-docs.ts: sync local resolver copies with the above

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alfadb
Copy link
Author

alfadb commented Mar 26, 2026

Merge conflict analysis (updated)

Reviewed all 50 open PRs for file-level overlap. 8 PRs intersect with this one:

High risk (manual merge needed)

PR Conflict files Nature
#472 (JSON validation for review-log) bin/gstack-review-log They add JSON validation, we change the write path. Both changes should coexist: validate → write to $PROJECT_DATA_DIR
#440 (launchPersistentContext + cookie persistence) browse/src/config.ts They add storageFile path + cookie persistence, we restructure stateDir to .gstack/local/. Needs careful merge — both modify resolveConfig() and ensureStateDir()
#445 (add bin/ to .gitignore) bin/gstack-slug, bin/gstack-review-log, bin/gstack-review-read, bin/gstack-repo-mode They git rm --cached all bin/ scripts. Structural conflict — if they go first, our bin changes need to be re-added after

Medium risk (different lines, likely auto-merge)

PR Conflict files Nature
#471 (Codex -C flag) scripts/resolvers/design.ts, review.ts Different lines: codex exec flags vs data paths
#470 (temp file cleanup) scripts/resolvers/design.ts, review.ts Different lines: rm -f cleanup vs path changes
#500/#501 (install root inference) scripts/gen-skill-docs.ts Different areas: setup/install logic vs preamble/path changes

Low risk (cosmetic overlap)

PR Conflict files Nature
#452 (review section in CLAUDE.md) docs/skills.md Different lines
#416 (community telemetry) scripts/gen-skill-docs.ts Large PR but touches telemetry, not data paths. Needs regen (bun run gen:skill-docs) after rebase

No overlap

No other PR addresses project-local data storage or the ~/.gstack/projects/.gstack/ migration. This PR is unique in scope.

Happy to rebase against any of these after they land.

@alfadb alfadb changed the title feat: project-local .gstack/ data storage for collaboration feat: project-local .gstack/ data storage with auto-migration Mar 26, 2026
alfadb and others added 2 commits March 26, 2026 11:18
…nd docs

- 12 .tmpl files: all ~/.gstack/projects/$SLUG/ references replaced with
  $PROJECT_DATA_DIR paths, legacy paths kept as fallback for reads
- 28 SKILL.md files regenerated from updated templates
- test/skill-validation.test.ts: adapt assertions for 3-line gstack-slug
  output and $PROJECT_DATA_DIR greptile patterns
- review/greptile-triage.md: use gstack-slug for PROJECT_DATA_DIR
- docs/skills.md: update path references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bin/gstack-migrate-local: standalone migration script (--dry-run supported)
that handles two phases:
- Phase 1: ~/.gstack/projects/$SLUG/ → .gstack/{designs,plans,evals,...}/
- Phase 2: .gstack/ root flat files → subdirectories (reorganize in place)

Deduplicates automatically, handles browse.json/logs → .gstack/local/,
architecture docs, implementation plans, and roadmaps.

Integrated into preamble: auto-runs on first gstack use per project,
creates .migrated marker to skip on subsequent runs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@alfadb alfadb force-pushed the feat/project-local-gstack-data branch from 9645db5 to db02aac Compare March 26, 2026 03:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant