mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-31 22:14:25 +01:00
v1.91.71.0 feat(install): gstack-doctor --check one-line verdict, gstack-capy-install, lazy Chromium (multi-agent wave PR A) (#3116)
* v1.91.71.0 feat(install): gstack-doctor --check one-line verdict, gstack-capy-install, lazy Chromium Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(qa-callers): substitute <plan-path> in the plan-completion acceptance block so the ship caller fixture admits the documented command Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
45a678323b
commit
6681adf7a8
49 files changed
+2700
-98
No files matched your search
@@ -0,0 +1,94 @@
|
||||
# Installing gstack on a Capy cloud machine
|
||||
|
||||
`bin/gstack-capy-install` installs gstack on a fresh Capy cloud machine
|
||||
(Ubuntu) and ends with one line a parent agent greps. It is the repo-owned
|
||||
installer the user-scope Capy skill runs after cloning; nothing in the skill
|
||||
decides what "installed" means.
|
||||
|
||||
```bash
|
||||
git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.local/share/gstack
|
||||
~/.local/share/gstack/bin/gstack-capy-install --for autoplan
|
||||
```
|
||||
|
||||
What it does, in order:
|
||||
|
||||
1. Reuses the checkout it lives in (or clones into `--root <dir>`), under a
|
||||
lock. It never resets or pulls an existing checkout. `--revision <ref>`
|
||||
pins a fresh clone; an existing checkout at another revision is reused and
|
||||
the trailer says `(requested <ref>; run gstack-upgrade to move)`.
|
||||
2. Preflight: `git`, `curl`, `node`, `jq`, then Bun. The default Capy image
|
||||
ships Bun 1.3.14, below gstack's supported minimum (1.4.2), so the installer
|
||||
downloads the exact release archive, verifies its SHA-256 against
|
||||
`bin/gstack-bun-version.sh` and installs it to `$BUN_INSTALL` (default
|
||||
`~/.bun`). It does that only when gstack's minimum and the target project's
|
||||
Bun pin (`--project <path>`, default the git toplevel of the current
|
||||
directory) agree; a conflict prints both constraints and stops
|
||||
(`RUNTIME_PIN_CONFLICT`, exit 3) before anything is installed.
|
||||
3. `./setup --host claude --no-prefix`, then `./setup --host codex --model
|
||||
gpt-6-astra`, both with `--no-browser`: Chromium is lazy by default.
|
||||
4. `gstack-doctor --check` for the requested workflow (`--for <skill>`,
|
||||
`--only <skill>`, or `--require <id,id>`; default `claude,codex,patch`).
|
||||
|
||||
## The one line to grep
|
||||
|
||||
The last line is the doctor's trailer:
|
||||
|
||||
```
|
||||
gstack: ok 1.91.70.0 for=autoplan
|
||||
gstack: fail runtime,pins
|
||||
```
|
||||
|
||||
Exit 0 only with `gstack: ok`. Read the exit status and the trailer directly:
|
||||
|
||||
```bash
|
||||
out=$(~/.local/share/gstack/bin/gstack-capy-install --for autoplan 2>&1); rc=$?
|
||||
printf '%s\n' "$out" | grep '^gstack: '
|
||||
[ "$rc" -eq 0 ]
|
||||
```
|
||||
|
||||
Never pipe `--check` (or the installer) through `tail`, `head` or `grep`
|
||||
alone: the pipe's exit status replaces the doctor's, and a silent failure is
|
||||
the incident this installer exists to end. Every `FAIL <id>` row carries a
|
||||
`fix:` clause and a reason code with its [troubleshooting
|
||||
anchor](troubleshooting.md#install-check-gstack-doctor---check-and-the-capy-installer).
|
||||
A parent agent confirms each subagent machine with this grep; one machine's
|
||||
install never covers another.
|
||||
|
||||
## Browser
|
||||
|
||||
The default install prints `SKIP browser (lazy; gstack-browser-ensure
|
||||
installs on first use)` and downloads nothing. The first browser skill run
|
||||
(`/browse`, `/qa`, `/design-review`, ...) calls `bin/gstack-browser-ensure`
|
||||
from its preflight, which installs Chromium (~115 MiB, about 86 s on a Capy
|
||||
machine) under setup's lock and prints `BROWSER_OK` or `BROWSER_UNAVAILABLE
|
||||
<reason>`. `--with-browser` installs it during the install instead, and the
|
||||
installer then prints the planning-only install time and the browser bootstrap
|
||||
time separately.
|
||||
|
||||
## The launch line
|
||||
|
||||
The installer's last lines include:
|
||||
|
||||
```
|
||||
GSTACK_LAUNCH: GSTACK_SESSION_KIND=unattended GSTACK_STATE_ROOT=<path> GSTACK_EPHEMERAL=1
|
||||
```
|
||||
|
||||
A child shell's `export` cannot configure the parent's later commands, so the
|
||||
parent supplies these assignments to every gstack command it launches (prefix
|
||||
the command, or export them once in the shell that runs it).
|
||||
`GSTACK_EPHEMERAL=1` tells gstack the disk vanishes with the machine, so the
|
||||
doctor's `state root` row reads `durable=no` and unattended runs say
|
||||
`learnings: skipped` instead of writing silently. A durable root is opt-in:
|
||||
set `GSTACK_STATE_ROOT` to a directory that outlives the machine. The
|
||||
installer only prints the option and never writes to the Capy drive (its
|
||||
policy excludes memory and verification evidence). See
|
||||
[docs/state-root.md](state-root.md#ephemeral-machines).
|
||||
|
||||
## Exit codes
|
||||
|
||||
| Exit | Meaning |
|
||||
|-----:|---------|
|
||||
| 0 | `gstack: ok` — every required component passed |
|
||||
| 1 | `gstack: fail <ids>` — a required component failed; each row has a fix |
|
||||
| 2 | usage error |
|
||||
| 3 | preflight stopped before `./setup` (`INSTALL_PREFLIGHT_FAILED`, `RUNTIME_PIN_CONFLICT`); nothing was installed |
|
||||
@@ -134,6 +134,44 @@ yourself, for example in the project's `.claude/settings.local.json`
|
||||
remote, or for a vendored sub-repo that should be its own project. The pin is
|
||||
applied per run and never cached.
|
||||
|
||||
## Ephemeral machines
|
||||
|
||||
A Capy cloud machine, a CI runner or a throwaway VM loses its disk when the
|
||||
run ends, and with it every learning, decision, review-log row and timing
|
||||
record gstack wrote under the default root. gstack does not guess this from
|
||||
the path (a tmpfs and a home directory look alike); the host says so with one
|
||||
environment marker:
|
||||
|
||||
```
|
||||
GSTACK_EPHEMERAL=1
|
||||
```
|
||||
|
||||
What the marker changes:
|
||||
|
||||
- `gstack-doctor` and `gstack-doctor --check` report the `state root` row as
|
||||
`durable=no` (the dashboard warns, the check still passes: an ephemeral root
|
||||
is a fact, not a broken install).
|
||||
- Unattended sessions print `learnings: skipped (state root is ephemeral; set
|
||||
GSTACK_STATE_ROOT)` instead of writing silently to a disk that will vanish.
|
||||
|
||||
A durable root is opt-in: the owner sets `GSTACK_STATE_ROOT` (or `GSTACK_HOME`)
|
||||
to a directory that outlives the machine. The installer never picks one for
|
||||
you. On Capy the drive is governed by Capy's own drive policy, which excludes
|
||||
memory and verification evidence, so `bin/gstack-capy-install` only prints the
|
||||
option and never writes there.
|
||||
|
||||
A child shell's `export` cannot configure the parent's later commands
|
||||
(`lib/state-root.ts` reads each process's own environment), so the installer
|
||||
ends with one machine-readable line the parent supplies to every gstack
|
||||
command it launches:
|
||||
|
||||
```
|
||||
GSTACK_LAUNCH: GSTACK_SESSION_KIND=unattended GSTACK_STATE_ROOT=<path> GSTACK_EPHEMERAL=1
|
||||
```
|
||||
|
||||
Prefix each command with those assignments (or export them once in the shell
|
||||
that runs them). See [docs/capy-install.md](capy-install.md).
|
||||
|
||||
## Uninstall
|
||||
|
||||
`gstack-uninstall` deletes state only at `~/.gstack`.
|
||||
|
||||
@@ -885,6 +885,120 @@ hooks stay.
|
||||
|
||||
---
|
||||
|
||||
## Install check (`gstack-doctor --check`) and the Capy installer
|
||||
|
||||
`gstack-doctor --check` prints one `PASS | FAIL | SKIP <id>` row per component
|
||||
and ends with `gstack: ok <revision> for=<workflow>` (exit 0) or
|
||||
`gstack: fail <id,id>` (exit 1). Every FAIL row carries a `fix:` clause and one
|
||||
of the codes below. Read the trailer directly; never pipe `--check` through
|
||||
`tail` or another command whose exit status would replace the doctor's
|
||||
(docs/capy-install.md).
|
||||
|
||||
<a id="doctor-component-missing"></a>
|
||||
### `FAIL <id> — <detail>; fix: <command> (COMPONENT_MISSING; ...)`
|
||||
|
||||
**Meaning.** A component the selected workflow needs (`--for <skill>`,
|
||||
`--require <csv>`, or by default every host profile installed from this
|
||||
checkout) is not installed, not built, not current, or not authenticated. The
|
||||
row names it: `claude` or `codex` (a host profile missing or stale), `patch`
|
||||
(the Codex render lacks the model behavioral patch), `codex-cli` (the Codex CLI
|
||||
is required and absent or not logged in), `browse-bundle`, `browser` (Chromium
|
||||
does not launch or render), `cso` (the native helper is required and not
|
||||
built).
|
||||
|
||||
**Fix.** Run the command in the row's `fix:` clause. For `browser`, that is
|
||||
`<checkout>/bin/gstack-browser-ensure`, which installs Chromium on first use
|
||||
when the installer skipped it (`SKIP browser (lazy; ...)`).
|
||||
|
||||
**Expected result.** The row turns `PASS` and the trailer reads `gstack: ok`.
|
||||
|
||||
<a id="doctor-runtime-below-minimum"></a>
|
||||
### `FAIL runtime — bun <version> ... (RUNTIME_BELOW_MINIMUM; ...)`
|
||||
|
||||
**Meaning.** The Bun on `PATH` is absent, below gstack's security floor
|
||||
(1.3.3: older Bun ignores the no-autoload compile flags, see
|
||||
[bun-too-old](#bun-too-old)) or below the supported minimum (1.4.2, the CI pin
|
||||
and `engines.bun`). The dashboard (`gstack-doctor` without `--check`) warns on
|
||||
an untested version; `--check` fails it, because a gate run on an untested
|
||||
runtime is the incident this check exists for. The default Capy cloud image
|
||||
ships 1.3.14, so a fresh Capy machine fails here until the installer upgrades
|
||||
Bun.
|
||||
|
||||
**Fix.** `bin/gstack-capy-install` upgrades Bun through setup's
|
||||
checksum-verified recipe before running `./setup`. By hand: download
|
||||
`https://bun.sh/install`, verify its SHA-256 against `GSTACK_BUN_INSTALL_SHA`
|
||||
in `bin/gstack-bun-version.sh`, then `BUN_VERSION=1.4.2 bash <file>` and
|
||||
re-run `./setup`.
|
||||
|
||||
<a id="doctor-project-pin-mismatch"></a>
|
||||
### `FAIL pins — bun <version> outside engines.bun >=1.4.2 (package.json:<line>; ...) (PROJECT_PIN_MISMATCH; ...)`
|
||||
|
||||
**Meaning.** The target project (`--project <path>`, default the git toplevel
|
||||
of the current directory, never the gstack checkout) pins a Bun or Node
|
||||
version the running one does not satisfy. Pins come from `package.json`
|
||||
(`packageManager`, `engines`), `.tool-versions`, `.nvmrc`, `.bun-version` and
|
||||
`bun-version:` / `node-version:` lines in `.github/workflows/*.yml`. A range
|
||||
(`>=1.4.2`) and an exact pin are told apart, and a CI pin keeps its platform
|
||||
lane: a Windows job's pin never fails a Linux run. The dashboard warns; `--check`
|
||||
fails. The row is `SKIP pins (no bun to evaluate the project pins)` when Bun
|
||||
is absent, never silent.
|
||||
|
||||
**Fix.** Install the pinned version for this platform (the row names each
|
||||
constraint with its source), or change the project's pin.
|
||||
|
||||
<a id="doctor-revision-unmet"></a>
|
||||
### `FAIL revision — installed <version> (requested <ref>) (REVISION_UNMET; ...)`
|
||||
|
||||
**Meaning.** `--revision <ref>` asked the doctor to certify a specific gstack
|
||||
revision (a VERSION string, tag, branch or commit) and the checkout is at
|
||||
another. An unmet revision is never `ok`.
|
||||
|
||||
**Fix.** Move the checkout: `/gstack-upgrade`, or
|
||||
`git -C <checkout> fetch origin && git -C <checkout> checkout <ref> && ./setup`.
|
||||
`bin/gstack-capy-install --revision <ref>` never moves an existing checkout; it
|
||||
reports `gstack: ok <installed> (requested <ref>; run gstack-upgrade to move)`.
|
||||
|
||||
<a id="capy-install-runtime-conflict"></a>
|
||||
### `gstack-capy-install: Bun conflict: gstack needs >=<minimum>, <project> pins <constraint> (RUNTIME_PIN_CONFLICT; ...)`
|
||||
|
||||
**Meaning.** The installer upgrades Bun only when gstack's supported minimum
|
||||
and the target project's pin agree on a version. Here they do not (for
|
||||
example the project pins `bun@1.3.14` exactly), so the installer changed
|
||||
nothing and stopped before `./setup`.
|
||||
|
||||
**Fix.** Raise the project's pin to gstack's supported minimum, or install
|
||||
gstack on a machine whose Bun the project accepts. `--project <path>` names
|
||||
the project whose pins apply.
|
||||
|
||||
<a id="browser-ensure-failed"></a>
|
||||
### `gstack-browser-ensure: NEEDS_SETUP ... (BROWSER_UNAVAILABLE; ...)`
|
||||
|
||||
**Meaning.** The first browser skill run on a machine installed without
|
||||
Chromium (`SKIP browser (lazy; gstack-browser-ensure installs on first use)`)
|
||||
tried to install it through `bunx playwright install chromium` under setup's
|
||||
lock, or Chromium is installed but does not launch.
|
||||
|
||||
**Fix.** Read the installer output above: offline or proxied machines need
|
||||
network access to the Playwright CDN; on Ubuntu 24.04+ an AppArmor
|
||||
user-namespace error needs `GSTACK_CHROMIUM_NO_SANDBOX=1`; then re-run
|
||||
`<checkout>/bin/gstack-browser-ensure`. `--with-browser` on the installer
|
||||
front-loads the install on machines that want it now.
|
||||
|
||||
<a id="capy-install-preflight-failed"></a>
|
||||
### `gstack-capy-install: preflight: <tool> not found (INSTALL_PREFLIGHT_FAILED; ...)`
|
||||
|
||||
**Meaning.** The installer checks `git`, `curl`, `node` and `jq` before
|
||||
`./setup`, and installs Bun when it is absent or below the supported minimum.
|
||||
One of them is missing, or the Bun install script's checksum did not match
|
||||
`GSTACK_BUN_INSTALL_SHA` (the download is discarded, nothing runs).
|
||||
|
||||
**Fix.** Install the named tool (`apt-get install -y jq`, Node from nodejs.org
|
||||
or nvm), then re-run `bin/gstack-capy-install`. A checksum mismatch means the
|
||||
upstream installer changed: update `GSTACK_BUN_INSTALL_SHA` only after
|
||||
reviewing the new script.
|
||||
|
||||
---
|
||||
|
||||
## Browser
|
||||
|
||||
<a id="browse-runtime-version-skew"></a>
|
||||
|
||||
Reference in new issue
Block a user