garrytan / garrytan/gstack

Factory Droid skill discovery is broken for gstack installs

Open
#661 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
133k
Forks
19.9k
Avg merge
18h 46m
Merged PRs (30d)
26

Description

## Problem

Skills installed via `cd ~/gstack && ./setup --host factory` are not reliably discoverable by Factory Droid. The generated skill files exist on disk, but Droid cannot discover or load them. As a result, gstack skills do not appear in the `/` menu.

## Reproduction

```bash
cd ~/gstack && ./setup --host factory
# Then restart Droid and type /
# Expected: gstack skills (qa, review, ship, etc.) appear
# Actual: no gstack skills visible
```

## Root Cause

The installation produces three incompatibilities with Droid's discovery model:

### 1. Wrong symlink type

Droid follows only **relative** symlinks in `~/.factory/skills/`. The current setup creates **absolute** symlinks:

```bash
ln -snf /Users/will/gstack/.factory/skills/gstack-qa ~/.factory/skills/gstack-qa
```

Absolute symlinks are ignored by Droid.

### 2. Skills not in Droid's read directory

Droid reads skill files from `~/.agents/skills/`. The current setup installs skills to `~/gstack/.factory/skills/` (a project subdirectory) and creates symlinks from `~/.factory/skills/` pointing back into the repo. Even if the symlinks were correct, Droid would need skills to exist as real directories in `~/.agents/skills/`.

### 3. Wrong `sourceType` in lockfile

The lockfile registration uses `sourceType: "local"`:

```json
{
"sourceType": "local",
"sourceUrl": "file:///Users/will/gstack/.factory/skills/gstack-qa"
}
```

Droid's lockfile reader **completely ignores** entries with `sourceType: "local"`. Every working skill (57 total in the registry) uses `sourceType: "github"`.

## How Droid Discovers Skills

Droid uses a two-tier discovery system:

- `~/.factory/skills/` — Droid scans here, follows relative symlinks
- `~/.agents/skills/` — Droid reads skill files from here
- `~/.agents/.skill-lock.json` — Droid's skill registry (only sourceType=github loaded)

A skill appears in `/` when **both**:
1. A relative symlink exists in `~/.factory/skills/` pointing to `~/.agents/skills/{skill}`
2. The lockfile entry has `sourceType: "github"`

## Proposed Fix

The `link_factory_skill_dirs()` function needs to:

1. **Copy** skills as real directories into `~/.agents/skills/` (not symlink from repo)
2. **Create relative symlinks** in `~/.factory/skills/` pointing to `../../.agents/skills/{skill}`
3. **Register** in `~/.agents/.skill-lock.json` with `sourceType: "github"`

Note: On a fresh profile (no existing `~/.agents/.skill-lock.json`), the lockfile registration would be skipped unless the existing lockfile check is made conditional or the lockfile is created.

## Verification

After a fix is applied, these commands should show the correct state:

```bash
# Relative symlinks exist
ls -l ~/.factory/skills/ | grep gstack

# Real directories exist
ls -l ~/.agents/skills/ | grep gstack

# Lockfile entries use sourceType=github
python3 -c "
import json
with open('$HOME/.agents/.skill-lock.json') as f:
lock = json.load(f)
for name, entry in lock['skills'].items():
if name.startswith('gstack'):
print(f'{name}: sourceType={entry[\"sourceType\"]}')"
```

## Skill Name

After fixing, skills are invoked by their `name:` field in `SKILL.md`, not the directory name:

| Directory | name field | Invoked as |
|-----------|-----------|------------|
| gstack-qa | qa | /qa |
| gstack-review | review | /review |

## References

- Droid skill discovery: `~/.factory/skills/` (relative symlinks only)
- Droid skill files: `~/.agents/skills/` (real directories)
- Droid registry: `~/.agents/.skill-lock.json` (sourceType=github required)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.