v1.91.50.0 fix(install): skills only for the agents you installed, every runtime-root file their skills read (#1694, #1077)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
garrytanandcapy-ai[bot] committed 2026-10-08 08:33:16 +00:00
1 parent 4faf399538
commit 9b39cc6906
11 files changed
+176 -11

No files matched your search

+40
View File
@@ -1,5 +1,45 @@
# Changelog
## [1.91.50.0] - 2026-10-08
**A gstack install carries skills only for the agents you installed: a global Claude install drops from 632 SKILL.md files (34.7 MB) to 63 (2.5 MB).**
**Codex and the other non-Claude agents get every file their skills read, instead of failing those reads silently.**
`./setup` rendered every agent's copy of the skills inside the install (#1694). A global Claude install at `~/.claude/skills/gstack` held Codex, Factory, Kiro, OpenCode, Cursor, Copilot, Slate, OpenClaw, Hermes and GBrain renders next to its own skills. Claude Code and Cursor-agent scan that tree, and Cursor-agent freezes above about 11 MB of skill files. Separately, the runtime directories setup builds for Codex, Factory, Kiro, OpenCode, Cursor and Copilot were missing files the skills read on demand: the jargon list, the question registry, the AskUserQuestion guides, the review checklists, the DX Hall of Fame and more (#1077's remaining part).
### The numbers that matter
Measured on Linux with a sandboxed HOME, installing from a fresh clone of the commit before this release (4637fae) and of this branch. The setup builds were real; Chromium and fonts were skipped.
| Install | Before | After |
|---|---|---|
| Global Claude install (`./setup`) | 632 `SKILL.md`, 34,738,066 bytes | 63 `SKILL.md`, 2,520,330 bytes |
| Existing install upgraded, then `./setup` | 632 `SKILL.md`, 34,738,066 bytes | 63 `SKILL.md`, 2,520,330 bytes; 569 generated `SKILL.md` (36.3 MB with their other files) moved to the backup |
| Development checkout with `./setup --host codex` | 632 `SKILL.md`, 34,738,066 bytes | 119 `SKILL.md`, 5,772,984 bytes (Claude plus Codex) |
| Same checkout, `GSTACK_RENDER_HOSTS=all bun run build` | 632 | 632; the next `./setup` prunes back to 119 |
| `$GSTACK_ROOT` paths missing from the Codex runtime root | 10 of 80 | 1 of 80 (`scripts/ship-measure.ts`, deferred) |
### What this means for you
Run `/gstack-upgrade` (or `git pull && ./setup`). The first setup prints one `pruned <dir>` line per agent you don't use from this checkout and a `host-render backup:` line naming where the generated files went; the next `./setup` prints none. `./setup --status` lists your agents, and `./setup --host <name>` adds one back. Nothing gstack can't prove it generated is removed.
### Itemized changes
#### Fixed
- An install renders skills only for the agents installed from it. setup records them in `.gstack-installed-hosts` in the checkout and never drops one, so `./setup --host codex` keeps a Factory render. The first run seeds the record from what the checkout already serves: install registry rows, install directories that resolve to it, agent skills that link into its renders, and legacy copy installs. `scripts/build.sh` renders Claude plus the recorded agents and prints which and why. A checkout with no record (a development checkout) still renders every agent, and `GSTACK_RENDER_HOSTS=all` forces that inside an install. (#1694)
- Every `./setup`, and a migration for upgrades, prunes the renders of agents missing from the record, using `gstack-relink`'s proof rules. Links into the checkout are removed. Files proven generated (gstack's generated-file banner, the generator's exact `openai.yaml`, or byte identity) are moved to `~/.gstack/backups/host-renders/<time>-<id>/`. Every other file stays where it is, and only emptied directories are removed. setup prints each kept file and a summary per agent, and `prune.log` in the backup lists every path. Two installs that share one state root are each cleaned. (#1694)
- The Codex `.agents/` render is made only when Codex is installed or recorded; a Claude-only setup used to make it every time. (#1694)
- Codex, Factory, Kiro, OpenCode, Cursor and Copilot runtime roots carry every file their skills read as `$GSTACK_ROOT/<path>`: `VERSION`, `scripts/jargon-list.json`, `scripts/question-registry.ts`, the AskUserQuestion split and CJK guides, `docs/test-value-bar.md`, all four review checklists and the review specialists, `plan-devex-review/dx-hall-of-fame.md`, design-html's vendored `pretext.js`, and host-rendered `office-hours` and `plan-design-review` `SKILL.md` copies. Cursor had two of the four checklists and only OpenCode had the specialists. (#1077)
#### Added
- README and `docs/troubleshooting.md` explain the record, the prune and its backup, and how to get an agent back. `docs/ADDING_A_HOST.md` documents the render contract and the new host checklist step. setup's Hermes, OpenClaw and GBrain hints say to add the agent to the record before rendering it by hand.
#### For contributors
- `bin/gstack-host-renders.sh` owns the record, the build's host selection and the prune; `scripts/build.sh`, setup, `bin/dev-setup` and `gstack-upgrade/migrations/v1.91.50.0.sh` source it. `bin/dev-setup` records Codex because it serves the repo's `.agents/`. `hosts/define-host.ts`' `sharedRuntimeRoot()` mirrors setup's new `_link_runtime_dists` list and `_copy_runtime_skill_refs`.
- New tests: `test/runtime-root-assets.test.ts` builds each runtime root with setup's own functions and checks every `$GSTACK_ROOT` literal in that agent's render on disk (it fails on the previous setup for all five roots); `test/host-renders.test.ts` (record, build selection, sequential installs, the upgrade refresh path); `test/host-renders-prune.test.ts` (a real all-agent render with a customized file, a user file, a look-alike skill and links; two installs on one state root; link-based seeding; the migration).
- Not verified: Cursor-agent and Claude Code were not re-run against the trimmed tree; the numbers are on-disk counts. The Windows copy-install paths are covered by stubbed tests only.
- Thanks to @vschoener for reporting #1694 and for the first fix attempt in #1695, @skyzer for the relocation approach in #1819 (both closed in favor of this one), @Saisreenivas for the Cursor-agent freeze report, and @el-analista for #1077.
## [1.91.43.0] - 2026-10-08
**Windows setup finishes when the optional /cso helper fails to build, and it tells you when Smart App Control blocks gstack's binaries.**
+7
View File
@@ -516,6 +516,13 @@ The active skill lives at `~/.claude/skills/gstack/`. After making changes:
2. Fetch and reset in the skill directory: `cd ~/.claude/skills/gstack && git fetch origin && git reset --hard origin/main`
3. Rebuild: `cd ~/.claude/skills/gstack && bun run build`
`bun run build` renders every host in a checkout setup never ran in. In an
install (any checkout with `.gstack-installed-hosts`, including one set up with
`bin/dev-setup`, which records Claude and Codex) it renders only the recorded
hosts and prints them (#1694); `GSTACK_RENDER_HOSTS=all bun run build` renders
every host there, and the next `./setup` prunes the extra renders to
`$GSTACK_STATE_ROOT/backups/host-renders/` again.
**If you use gbrain:** the `git reset --hard` in step 2 reverts the brain-aware
(`GBRAIN_CONTEXT_LOAD` / `GBRAIN_SAVE_RESULTS`) blocks that `gstack-config
gbrain-refresh` renders into the install (those generated blocks differ from
+1 -1
View File
@@ -828,7 +828,7 @@ When Conductor creates a new workspace, `bin/dev-setup` runs automatically. It d
- **`.claude/skills/` is gitignored.** The symlinks never get committed.
- **Never write raw `ln -snf` in `setup`.** Every link site in `setup` MUST route through the `_link_or_copy SRC DST` helper near the `IS_WINDOWS` detection. The helper preserves `ln -snf` on Unix and switches to `cp -R` / `cp -f` on Windows without Developer Mode, where plain `ln -snf` produces frozen file copies that don't refresh on `git pull`. `test/setup-windows-fallback.test.ts` enforces this with a static invariant — a single raw `ln` call outside the helper body fails CI.
- **Synchronous subagent dispatches must state the flag.** Claude Code runs Agent-tool subagents in the background by default (since v2.1.198), so any template step that dispatches a subagent and consumes its output must carry `run_in_background: false`. Use the `{{FOREGROUND_DISPATCH_NOTE}}` placeholder (`scripts/resolvers/constants.ts`) instead of hand-writing the guidance, and add the generated carrier file to `GENERATED_WITH_GUIDANCE` in `test/run-in-background-guidance.test.ts` in the same commit — its structural scanner fails CI on any generated dispatch imperative that lacks the flag.
- **Never delete or link over a skill entry `setup` cannot prove is gstack's.** Every destructive site in `setup` (the linker, the alias installer, both prefix-flip cleanups) and in `bin/gstack-relink` goes through the ownership helpers (`_claude_entry_is_ours` / `_claude_entry_owned_strongly` in `setup`, `_entry_is_ours` / `_entry_owned_strongly` in relink). The retired-skill prune (`_prune_stale_generated`) applies the same strong/weak split through its own gate: a real host directory is a candidate only when its SKILL.md carries the generated banner (`_owned_for_windows_refresh`), a host symlink is removed only when it resolves into gstack (`_gstack_target_is_ours`), a bannered real directory is cleaned through `_cleanup_weak_dir`, and a symlink inside the render tree is never followed. A symlink into gstack or the `.gstack-owned` marker proves the whole directory; a byte-identical or generated-banner SKILL.md proves only that file, and a differing one is moved to `~/.gstack/backups/skills/<ts>/` first. `test/setup-link-ownership.test.ts`, `test/setup-cleanup-orphans.test.ts`, `test/setup-prune-stale-generated.test.ts`, and `test/relink.test.ts` pin it. The rule is duplicated in the two scripts until the shared helper filed in TODOS.md lands: change both.
- **Never delete or link over a skill entry `setup` cannot prove is gstack's.** Every destructive site in `setup` (the linker, the alias installer, both prefix-flip cleanups) and in `bin/gstack-relink` goes through the ownership helpers (`_claude_entry_is_ours` / `_claude_entry_owned_strongly` in `setup`, `_entry_is_ours` / `_entry_owned_strongly` in relink). The retired-skill prune (`_prune_stale_generated`) applies the same strong/weak split through its own gate: a real host directory is a candidate only when its SKILL.md carries the generated banner (`_owned_for_windows_refresh`), a host symlink is removed only when it resolves into gstack (`_gstack_target_is_ours`), a bannered real directory is cleaned through `_cleanup_weak_dir`, and a symlink inside the render tree is never followed. A symlink into gstack or the `.gstack-owned` marker proves the whole directory; a byte-identical or generated-banner SKILL.md proves only that file, and a differing one is moved to `~/.gstack/backups/skills/<ts>/` first. `test/setup-link-ownership.test.ts`, `test/setup-cleanup-orphans.test.ts`, `test/setup-prune-stale-generated.test.ts`, and `test/relink.test.ts` pin it. The rule is duplicated in the two scripts until the shared helper filed in TODOS.md lands: change both. The host-render prune (`gstack_prune_host_renders` in `bin/gstack-host-renders.sh`, #1694) applies the same split to the render dirs of hosts a checkout does not serve: a link into the checkout goes, a file proven generated moves to `~/.gstack/backups/host-renders/<ts>-<id>/`, anything else stays, and only emptied directories are removed (`test/host-renders-prune.test.ts`).
- **`./setup` never fails on Chromium.** The Playwright bootstrap (section `# 2` of `setup`) is best-effort and bounded: every failure becomes a reason code (`skipped`, `chromium-install`, `chromium-install-timeout`, `chromium-install-locked`, `windows-no-node`, `windows-node-modules`, `post-install-launch`) printed in the final summary alongside the browser-dependent skills, and skill registration always runs. `GSTACK_PLAYWRIGHT_INSTALL_TIMEOUT=<seconds>` (default 600) bounds the download; `GSTACK_SKIP_PLAYWRIGHT=1` skips it, the right knob for a no-browser box or a setup-only test loop. `GSTACK_SKIP_ASIDE=1` makes the browser summary (like the skills' probe and the renderer) treat Aside as absent, so the summary never promises a fallback the bootstrap did not deliver (`test/setup-browser-hint.test.ts`). Anything you add after the bootstrap must stay independent of the browser. `test/setup-playwright-best-effort.test.ts` pins the block.
## Testing your changes in a real project
+12
View File
@@ -119,6 +119,16 @@ An explicit `--host X` installs for X only and never changes another agent's
install. `/gstack-upgrade` refreshes every install it registered, one row per
host, and says which ones failed.
A checkout carries skills only for the agents installed from it. Setup records
them in `.gstack-installed-hosts` and never drops one, so adding an agent later
is just `./setup --host <name>`. Copies rendered for other agents are pruned:
generated files move to `~/.gstack/backups/host-renders/`, and files gstack
can't prove it generated stay where they are. A global Claude install went
from 632 `SKILL.md` files (34.7 MB) to its own 63 (2.5 MB), which keeps Cursor-agent
from freezing on the skills tree (#1694). In a development checkout,
`bun run build` still renders every agent; inside an install it renders the
recorded ones, and `GSTACK_RENDER_HOSTS=all bun run build` renders them all.
Tiers: **full** is certified by a real workflow run (see
[Certify your host](docs/ADDING_A_HOST.md#certify-your-host)); **experimental**
installs and passes the conformance tests but has no certification run yet;
@@ -673,6 +683,8 @@ it. The usual fix is to re-run setup from that row's source for that host, e.g.
A project install lives in the project's `.claude/skills/gstack` or
`.agents/skills/gstack`; run its `setup` from inside the project.
**Cursor freezes on load, or an agent's gstack skills went missing after an upgrade?** Each checkout now renders skills only for the agents installed from it (#1694). `./setup --status` lists them; `./setup --host <name>` adds one back. Pruned copies are in `~/.gstack/backups/host-renders/<time>-<id>/`, with every path in its `prune.log` ([troubleshooting](docs/troubleshooting.md#host-renders-pruned)).
**`/browse` (or `/qa`, `/design-review`) says `NEEDS_ASIDE` or `ASIDE_NOT_RUNNING`?** That's the probe telling you it's about to use the fallback browser. Want Aside? Open the app and sign in — `aside --version` should print a version and `aside repl 'console.log("ok")'` should print `ok` — then re-run. gstack never installs it for you. Want the fallback on purpose while Aside is open? `GSTACK_SKIP_ASIDE=1` makes every skill, the renderer, and `./setup` treat Aside as absent. When Aside is absent the probe prints `NEEDS_ASIDE: <OS>` and skills trust that line for the macOS-only download pitch; `GSTACK_PLATFORM` overrides the OS it names, for tests and unusual hosts (set it in your shell — gstack never reads it from a project `.env`).
**`/browse` fails on the fallback browser?** `cd ~/.claude/skills/gstack && bun install && bun run build`
+37
View File
@@ -245,6 +245,43 @@ From the approved 2026-10 test/eval/CI audit plan; the audit PR files these.
application-control messages as blocked from reporters' captures; nobody has
run it on an enforcing machine. **Effort:** S. **Priority:** P3.
### P2/P3: install footprint follow-ups from the October fix wave (PR C2, v1.91.50.0)
- **`scripts/ship-measure.ts` on env-var hosts** — /ship's measure loop runs
`$GSTACK_ROOT/scripts/ship-measure.ts`, which imports gstack's test helpers
and eval harness, so a Codex/Factory/... runtime root would need most of the
development tree. It is the one `$GSTACK_ROOT` path
`test/runtime-root-assets.test.ts` defers. Either make ship-measure
self-contained or have the skill call it from the source checkout
(`.source-path`). **Effort:** M. **Priority:** P3.
- **Rendered `SKILL.md` copies inside runtime roots are discoverable** —
`office-hours/SKILL.md` (#2449) and now `plan-design-review/SKILL.md` sit in
`~/.codex/skills/gstack/<skill>/` because skills read them as
`$GSTACK_ROOT/<skill>/SKILL.md`. A host that scans its skills dir
recursively may list them beside `gstack-<skill>`. Pointing those reads at
the sibling registry path, as /autoplan does, removes the copies; that is a
prompt change and needs its evals. **Effort:** M. **Priority:** P3.
- **Removing one host from a checkout** — the installed-hosts record only
grows, and `gstack-uninstall` removes every install. A per-host uninstall
should drop the host from `.gstack-installed-hosts` so its render is pruned;
today that is a hand edit. **Effort:** S. **Priority:** P3.
- **Recording an instruction-only host from setup** — Hermes, OpenClaw and
GBrain renders made by hand inside an install survive only when the user adds
the host to `.gstack-installed-hosts` first (setup's hint says so). A
`./setup --host hermes --render`-style path would record and render in one
step; it needs a product call because those tiers install nothing today.
**Effort:** S. **Priority:** P3.
- **Host-render backups never expire** — each install's first pruning setup
moves about 36 MB of generated files to
`$GSTACK_STATE_ROOT/backups/host-renders/`. Add a retention rule (for example
keep 30 days) once nobody has asked for a restore. **Effort:** S.
**Priority:** P3.
- **Verify the Cursor-agent freeze and Claude Code's listing on a real
install** — #1694's symptoms (Cursor-agent freezing above about 11 MB, Claude
Code dropping skill descriptions) were measured as on-disk bytes only: 632
`SKILL.md` / 34.7 MB before, 63 / 2.5 MB after. Nobody re-ran Cursor or
Claude Code against the trimmed tree. **Effort:** S. **Priority:** P3.
### P2/P3: severe fix wave follow-ups (filed 2026-10-03, v1.91.19.0)
Deferred from the approved severe fix wave (docs/designs/SEVERE_FIX_WAVE_2026_10.md), each with its reason.
+1 -1
View File
@@ -1 +1 @@
1.91.43.0
1.91.50.0
+1 -1
View File
@@ -1,4 +1,4 @@
# gstack digest v1.91.43.0 — regenerate/re-copy after upgrading gstack
# gstack digest v1.91.50.0 — regenerate/re-copy after upgrading gstack
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
for agent hosts without a full skill install. The full skills add workflows,
+40 -6
View File
@@ -75,7 +75,9 @@ Inventory of every setup side effect, by phase (line numbers are approximate):
| Phase | Writes | Scope |
|---|---|---|
| Build | `browse/dist`, `design/dist`, `make-pdf/dist`, `bin/gstack-cso-*` in the source checkout | source |
| Generation | `.agents/`, `.kiro/`, `.factory/`, `.opencode/`, `.cursor/` renders in the source checkout; `gstack-patch-names` rewrites Claude `name:` fields in place | source |
| Hosts record | `.gstack-installed-hosts` in the source checkout: every host setup installed from it, additive (#1694) | source |
| Generation | renders for the recorded hosts only (`.agents/`, `.kiro/`, `.factory/`, `.opencode/`, `.cursor/`, `.copilot/`) in the source checkout; `gstack-patch-names` rewrites Claude `name:` fields in place | source |
| Render prune | renders of hosts the record does not name: links into the checkout removed, generated files moved to `$GSTACK_STATE_ROOT/backups/host-renders/<ts>-<id>/`, other files kept | source / state root |
| Chromium | Playwright cache (`~/.cache/ms-playwright`), lock under the state root | machine |
| Config | `skill_prefix`, `timeline_stop_hook`, team-mode keys in `$GSTACK_STATE_ROOT/config.yaml` | state root |
| Claude arm | `~/.claude/skills/gstack` link, one dir per skill with a `SKILL.md` link, alias copies | selected host |
@@ -114,6 +116,29 @@ shell metacharacters) is named through a `<host>-<id>.root` alias symlink:
worktree-isolated Claude Code refuses a command path containing a space in any
quoting.
### Host renders in an install (#1694)
A checkout renders skills only for the hosts installed from it.
`bin/gstack-host-renders.sh` owns the record, `.gstack-installed-hosts` in the
checkout: setup adds each host it installs and never removes one, so
`./setup --host codex` keeps a `--host factory` render. The first run after an
upgrade seeds it from the hosts the checkout already serves (registry rows,
install roots that resolve to it, host skills that link into its renders, and
legacy copies with no runtime root). `scripts/build.sh` renders claude plus
the recorded hosts and prints which hosts and why; a checkout with no record (a
development checkout) or `GSTACK_RENDER_HOSTS=all` renders every host.
Every setup run then prunes the renders of unrecorded hosts with
`bin/gstack-relink`'s proof rules: a symlink into the checkout (strong proof)
is removed; a file proven generated (weak proof: the gen-skill-docs banner, the
generator's exact `openai.yaml` shape, byte identity with the checkout) is
moved to `$GSTACK_STATE_ROOT/backups/host-renders/<ts>-<id>/`; every other file
stays where it is, and only directories left empty are removed. The backup's
`prune.log` lists every path. A gstack-upgrade migration runs
the same prune for an install upgraded without a setup run. Instruction-only
hosts (Hermes, OpenClaw, GBrain) are never installed by setup, so a user who
renders one by hand inside an install adds its name to the record first.
## Host tiers and capabilities
Every host declares `tier` and `capabilities` (`scripts/host-config.ts`).
@@ -257,8 +282,14 @@ That expands to the full `HostConfig` with these defaults:
(`~/.claude/skills/gstack` → `~/{globalRoot}`, `.claude/skills/gstack` →
`{localSkillRoot}`, `.claude/skills` → `{hostSubdir}/skills`)
- `suppressedResolvers`: the GBrain pair (`GBRAIN_CONTEXT_LOAD`, `GBRAIN_SAVE_RESULTS`)
- `runtimeRoot`: the shared asset list (`bin`, `browse/dist`, `browse/bin`,
`gstack-upgrade`, `ETHOS.md` + review checklist files)
- `runtimeRoot`: `sharedRuntimeRoot()`, every file the skills run or read as
`$GSTACK_ROOT/<path>` (`bin`, `lib`, the compiled tools, `freeze/bin`, the
review checklists and specialists, the jargon list and question registry,
the AskUserQuestion docs, the DX Hall of Fame, `VERSION`, and the
office-hours and plan-design-review `SKILL.md` copies). It mirrors setup's
`_link_runtime_dists` and `_copy_runtime_skill_refs`;
`test/runtime-root-assets.test.ts` checks each staged root on disk. A host
with extra assets passes them: `sharedRuntimeRoot(['qa/templates'])`.
- `install`: `{ linkingStrategy: 'symlink-generated' }`
- `learningsMode: 'basic'`
@@ -280,7 +311,7 @@ Review Army), `GBRAIN_RESOLVERS` (the default
suppression pair), and `EXEC_STYLE_TOOL_REWRITES` (the OpenClaw-style
lowercase-tool rewrites shared by openclaw and gbrain).
Good examples: `hosts/opencode.ts` (path + runtimeRoot overrides),
Good examples: `hosts/opencode.ts` (path + extra runtime assets),
`hosts/factory.ts` (tool rewrites and conditional fields), `hosts/hermes.ts`
(AGENTS.md host with custom tool rewrites and resolver composition).
@@ -300,9 +331,12 @@ export const ALL_HOST_CONFIGS: HostConfig[] = [
export { claude, codex, factory, kiro, opencode, slate, cursor, openclaw, hermes, gbrain, myhost };
```
### 3. Add to .gitignore
### 3. Add to .gitignore and the render table
Add `.myhost/` to `.gitignore` (generated skill docs are gitignored).
Add `.myhost/` to `.gitignore` (generated skill docs are gitignored), and add
`myhost:.myhost` to `GSTACK_HOST_RENDER_DIRS` in `bin/gstack-host-renders.sh`
so an install renders it only when it is installed and prunes it otherwise
(#1694; `test/host-renders.test.ts` checks the table against `hosts/*.ts`).
### 4. Generate and verify
+30
View File
@@ -647,6 +647,36 @@ whose hooks parse. This is a gstack bug: report the printed `<file>:<line>`.
cannot be checked before the pull; setup then refuses the broken hook (see the
entry above).
<a id="host-renders-pruned"></a>
### `pruned <dir> (<host> is not installed from this checkout): ...` / `kept <path>: not proven generated (...)` / `host-render backup: <dir> (...)`
**Meaning.** A gstack checkout keeps skills only for the agents installed from
it, listed in `.gstack-installed-hosts` in the checkout (#1694). Older installs
rendered every agent's copy, so a global Claude install carried 632 `SKILL.md`
files (34.7 MB) that Claude Code and Cursor-agent scan. setup removed the copy
for an agent that is not installed from this checkout. Generated files were
moved to the backup directory it printed; links into the checkout were removed;
files it could not prove gstack generated (`kept ...`) were left in place.
`prune.log` in the backup lists every path. The same prune runs once from the
upgrade migration. Agents in the record are never pruned.
**Fix.** Nothing, if you don't use that agent. To get an agent back, install
it from this checkout, which records it and renders its skills:
```bash
./setup --host <name>
```
For an instruction-only agent you render by hand (Hermes, OpenClaw, GBrain),
add its name to `.gstack-installed-hosts` first, then run
`bun run gen:skill-docs --host <name>`. To restore one file, `mv` it back from
the backup. A `kept` file is yours: move or delete it when you no longer need it.
The backup sits in gstack's state root, which no agent scans; delete it once
you are sure you don't need it (about 36 MB for a pre-1.91.50 Claude install).
**Expected result.** The next `./setup` prints no `pruned` line, and
`./setup --status` lists the agents you use.
<a id="cso-windows-msvc-compile"></a>
### `CSO unavailable: its native helper was not built (windows-msvc-compile)`
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "gstack",
"version": "1.91.43",
"version": "1.91.50",
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
"license": "MIT",
"type": "module",
+6 -1
View File
@@ -122,8 +122,13 @@ describe.skipIf(process.platform === 'win32')('gstack-upgrade migration prunes e
const migrations = fs.readdirSync(path.join(ROOT, 'gstack-upgrade/migrations'))
.filter(n => fs.readFileSync(path.join(ROOT, 'gstack-upgrade/migrations', n), 'utf8').includes('gstack-host-renders.sh'));
test('exactly one migration owns the prune', () => {
test('exactly one migration owns the prune, and setup runs it (not newer than VERSION)', () => {
expect(migrations).toEqual([expect.stringMatching(/^v\d+\.\d+\.\d+\.\d+\.sh$/)]);
const parts = (v: string) => v.split('.').map(Number);
const mine = parts(migrations[0]!.slice(1, -3));
const version = parts(fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf8').trim());
const cmp = mine.map((n, i) => n - version[i]!).find(d => d !== 0) ?? 0;
expect(cmp).toBeLessThanOrEqual(0);
});
function migrate(f: Fixture, install: string) {