Discussion: should a nested repo with its own remote be able to declare itself a project?
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
**Version checked:** v1.68.2.0 (`51932ece`), unmodified.
**Asking about:** `bin/gstack-slug`, `lib/bin-context.ts`.
## Context: how I hit this
I keep my Laravel projects as separate git repos checked out inside a workspace repo that
carries my notes and cross-project docs:
```
~/projects/ git@gitlab.example.com:me/projects-workspace.git
├── app-one/ git@gitlab.example.com:org/app-one.git
├── app-two/ git@gitlab.example.com:org/app-two.git
├── vendor-tool/ https://github.com/some-org/vendor-tool.git
└── ops-tooling/ git@gitlab.example.com:org/ops-tooling.git
```
Every inner directory is an independent repository with its own `origin`. They are not
vendored copies and not submodules — they are separate products that happen to live under
one workspace checkout.
All of them resolve to the workspace's slug, so their session state (checkpoints,
learnings, decisions, timeline) files into one shared `~/.gstack/projects//`
directory.
## Reproduction on unmodified v1.68.2.0
```bash
mkdir -p /tmp/ws && cd /tmp/ws
git init -q -b main && git remote add origin git@github.com:me/workspace.git
git commit -q --allow-empty -m init
mkdir -p proj && cd proj
git init -q -b main && git remote add origin git@github.com:org/proj.git
git commit -q --allow-empty -m init
mkdir -p app
```
Actual output (`GSTACK_HOME` pointed at a scratch dir):
```
/tmp/ws SLUG=me-workspace
/tmp/ws/proj SLUG=me-workspace <- has its own origin: org/proj
/tmp/ws/proj/app SLUG=me-workspace
```
## What I understand to be intentional
I am not reporting this as a defect, because the code says plainly that it is on purpose:
- `bin/gstack-slug:144-146` — *"Nested-repo semantics preserved: an inner repo under an
outer canonical-remote repo still resolves to the OUTER repo's remote (outermost wins),
same as before."*
- `test/gstack-slug-parity.test.ts:183` pins it:
`'walk-up preserved: nested inner repo WITH its own remote still resolves to the OUTER repo slug'`.
- `bin/gstack-slug:64-65` documents the way out: `GSTACK_PROJECT_SLUG` is the
*"Escape hatch for vendored sub-repos and other genuine 'subdir IS its own project' edge cases."*
So the use case is recognised and there is an official answer for it. My question is about
the shape of that answer, not about the default.
## The gap I keep running into
The escape hatch is per-invocation and deliberately never persisted
(`bin/gstack-slug:69-72`), with a reason I agree with: persisting it would rebind that
cwd's slug for every later env-less run.
```
/tmp/ws/proj GSTACK_PROJECT_SLUG=org-proj -> SLUG=org-proj
/tmp/ws/proj (next run, no env) -> SLUG=me-workspace
```
That leaves no declarative way to say "this directory is its own project" once and have it
hold. With N projects under a workspace, the identity has to be re-exported in every shell,
for every project, forever — and any session that forgets it silently files state into the
workspace bucket. Silently is the part that costs: nothing errors, the wrong directory is
just used, so it is noticed late.
## The question
Would you accept a **persistent, per-directory** form of the identity override — something
that expresses the same intent as `GSTACK_PROJECT_SLUG` but survives a new shell?
I am explicitly **not** asking to change the default. Outermost-wins is the right default
for the common case, and I am not proposing to touch the walk-up or the canonical-remote
resolution.
Shapes that would solve it for me, in rough order of how little they change:
1. **An opt-in marker file** the walk-up already understands — e.g. a `.gstack-project`
file (empty, or containing an explicit slug) that stops the walk at that directory.
Nothing changes for anyone who does not create one.
2. **A config key** in `~/.gstack/config.yaml` mapping paths to slugs.
3. **A documented convention** for making the override durable that I have missed — in
which case this is a docs question and I will happily close it.
If the answer is "use `GSTACK_PROJECT_SLUG`, per shell, that is the intended workflow",
that is a fine answer and worth stating explicitly in the docs, since the current wording
frames it as an edge-case escape hatch rather than the supported path for this layout.
## Why this matters enough to ask
On my machine this is not hypothetical. Of 16 nested repos, 5 collapse onto the workspace
slug. Two of them are my highest-traffic projects — one has 73 checkpoints, another 17.
When their identity moves, `/context-restore` stops seeing that history: it is not deleted,
just filed under a name nothing looks up any more.
I am running a local patch for this and I am not proposing it here; it makes tradeoffs I
am not confident are right for everyone, and an adversarial review of it turned up enough
problems that I would not want it merged as-is. I would rather agree on the contract first
and implement whatever you prefer.
Happy to do the implementation and tests for whichever shape you pick.
Contributor guide
Research direction
Read bin/gstack-slug:64-72 and 144-146, then inspect lib/bin-context.ts and test/gstack-slug-parity.test.ts:183 to understand the current override and nested-repository behavior. Agree on the durable identity contract before implementing; done means the chosen behavior is covered by tests and, if the existing escape hatch remains intended, its supported workflow is documented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- git, typescript
- Domain
- cli, developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100