Support session-aware repo-local loop state for concurrent same-repo workflows
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
## Problem
Some repo-local workflow state in gstack-style loops is effectively single-writer:
- one mutable `current` state file
- one mutable `STATE.md` view
That works for a single active task in a repo, but it breaks down when two AI sessions are working in the same repo at once.
Failure mode:
1. Session A starts a repo-local loop for task A.
2. Session B starts a repo-local loop for task B in the same repo.
3. Session B overwrites the repo-local `current` state.
4. Session A now sees the wrong active task/stage, or cannot safely update its own loop.
This is not hypothetical — it shows up immediately in real multi-session / multi-agent usage, especially when parallel planning/review/shipping work happens in the same repo checkout.
## Why this matters
gstack increasingly supports:
- long-running multi-step workflows
- resumable context
- multi-session usage
- workspace-aware behavior
But repo-local loop state is still vulnerable to silent clobbering if it assumes one active loop per repo checkout.
That causes two problems:
1. **state corruption / confusion** — one session silently hijacks another session's workflow state
2. **bad tool guidance** — guards/hooks may warn against the wrong task because they resolve only the most recently written repo-local state
## Desired behavior
Parallel sessions in the same repo should be able to maintain independent loop state without destroying each other.
A good default model would be:
- durable per-loop state files
- explicit session-to-loop binding
- backward-compatible `current` alias for old tooling
- `list` / `activate` / `status --loop-id` style affordances
## Proposed design
### 1. Durable per-loop state
Instead of only:
- `.gstack/current.json`
- `.gstack/STATE.md`
store canonical loop state under something like:
- `.gstack/loops/.json`
- `.gstack/loops/.md`
Where `loop-id` is unique and human-auditable (timestamp + slug is enough).
### 2. Session binding
Bind the current session to one loop via a lightweight mapping under something like:
- `.gstack/sessions/.json`
Then `status` / `update` can resolve in this order:
1. explicit `--loop-id`
2. session binding
3. legacy/current alias fallback
### 3. Compatibility alias
Keep:
- `.gstack/current.json`
- `.gstack/STATE.md`
as compatibility mirrors of the most recently activated/touched loop.
This avoids breaking older tooling while making the canonical model multi-loop.
### 4. Minimal commands
A small surface is enough:
```bash
gstack loop list
gstack loop activate
gstack loop status [--loop-id ...]
```
(or equivalent within the existing command structure)
## Important implementation point
The upstream version should use a **generic session abstraction**, not host-specific env hacks.
A local overlay can get away with using environment-specific values from the surrounding shell/tooling, but upstream should define a clean `GSTACK_SESSION_ID`-style mechanism first, then optionally allow fallbacks where appropriate.
## Non-goals
This does **not** solve all parallel-work problems.
If two sessions are editing the same checkout and touching the same files, you still have working-tree collisions.
This proposal only fixes the workflow-state collision layer.
The right higher-order pattern is still:
- session-aware loop state for lightweight same-repo concurrency
- separate worktrees for truly parallel implementation
## Why this seems upstream-worthy
The need is generic, not user-specific:
- multi-agent / multi-session work is becoming normal
- silent state clobbering is a predictable failure mode
- a single mutable repo-local loop state becomes the wrong abstraction once concurrency exists
This feels aligned with gstack’s broader direction around workspaces, saved context, and multi-session workflows.
## Concrete acceptance criteria
A good fix would satisfy:
- Session A and Session B can each start loops in the same repo without destroying each other
- `status` in each session resolves to the correct bound loop by default
- `update` advances only the intended loop
- `list` shows all loops in the repo
- old repos with only `current.json` migrate or fall back cleanly
- tooling that only reads `current.json` still works, even if it is only a compatibility alias
## Suggested next step
Open as design/RFC first, then decide whether to implement in core gstack state management or in the specific loop/workspace subsystem that owns repo-local workflow state.
Contributor guide
Research direction
Start by locating the repo-local loop state management and the existing status, update, list, and activation command entry points. Inspect how .gstack/current.json and .gstack/STATE.md are read or written, then define the session-aware behavior and migration compatibility against the listed acceptance criteria.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100