setup-gbrain, sync-gbrain: fix stale facts and strip plan archaeology

Applies s09 H1a, H1c (Mac-only wording; the installer supports Linux and
Windows), H2 (smoke test has no delete step), H3 (five invocation modes),
H4 (no CI grep test backs the telemetry claim), H7 (Step 4.5 does not exist;
the prompt is Path 4 step 4d), M11, M12, M13, M15, M18, M19 (plan codes,
issue numbers, version pins, rename story), M14 (restore-from-sync never
shipped), M16 (draft self-dialogue in the Supabase steps), M17 (passed
sunset date, manual merge into both sections).

W7a: retires the setup-gbrain-bin-invocation-paths 'now persists staged
transcripts' change-detector (t06 #17); the no-bare-invocation regex tests
keep the contract.
This commit is contained in:
garrytan committed 2026-10-03 00:08:46 +00:00
1 parent 4222e13a68
commit 26c6bf263f
5 files changed
+81 -92

No files matched your search

+37 -42
View File
@@ -29,7 +29,7 @@ allowed-tools:
# /setup-gbrain — Coding-Agent Onboarding for gbrain
You are setting up gbrain (https://github.com/garrytan/gbrain), a persistent
knowledge base, on the user's local Mac so that this coding agent (typically
knowledge base, on the user's machine so that this coding agent (typically
Claude Code) can call it as both a CLI and an MCP tool.
**Scope honesty:** This skill's MCP registration step (5a) uses
@@ -37,12 +37,12 @@ Claude Code) can call it as both a CLI and an MCP tool.
(Cursor, Codex CLI, etc.) will still get the gbrain CLI on PATH — they can
register `gbrain serve` in their own MCP config manually after setup.
**Audience:** local-Mac users. openclaw/hermes agents typically run in cloud
**Audience:** local machines (macOS, Linux, Windows). openclaw/hermes agents typically run in cloud
docker containers with their own gbrain; "sharing" a brain between them and
local Claude Code is only possible through shared Postgres (Supabase).
## User-invocable
When the user types `/setup-gbrain`, run this skill. Three shortcut modes:
When the user types `/setup-gbrain`, run this skill. Invocation modes:
- `/setup-gbrain` — full flow (default)
- `/setup-gbrain --repo` — only flip the per-remote policy for the current repo
@@ -69,10 +69,10 @@ implemented as a dispatcher binary.
Capture the JSON output. It contains: `gbrain_on_path`, `gbrain_version`,
`gbrain_config_exists`, `gbrain_engine`, `gbrain_doctor_ok`, `gbrain_mcp_mode`,
`gstack_brain_sync_mode`, `gstack_brain_git`, `gstack_artifacts_remote`, and
the v1.34.0.0+ `gbrain_local_status` field (one of: `ok`, `no-cli`,
the `gbrain_local_status` field (one of: `ok`, `no-cli`,
`missing-config`, `broken-config`, `broken-db`, `engine-locked`, `timeout`,
`thin-client`). Treat `timeout` like `ok` (slow-but-healthy engine, #1964) — it
never triggers Step 1.5 remediation. Treat `thin-client` like `ok` too (#2051):
`thin-client`). Treat `timeout` like `ok` (slow-but-healthy engine) — it
never triggers Step 1.5 remediation. Treat `thin-client` like `ok` too:
the machine is a thin client of a remote-HTTP MCP brain, no local engine by
design — brain-aware blocks render, and the detect JSON carries
`gbrain_thin_client: {probed: false}` (config verified; remote reachability
@@ -89,7 +89,7 @@ invocation flags here and skip to the matching step.
---
## Step 1.5: Broken-local-engine remediation (plan D4)
## Step 1.5: Broken-local-engine remediation
Read `gbrain_local_status` from the Step 1 detect output. **If it's `broken-db`
or `broken-config` AND no shortcut flag was passed**, the user has a
@@ -173,7 +173,7 @@ Options (present based on detected state):
- **2b — Supabase, create manually.** Walk through supabase.com signup
yourself; paste the URL back when ready.
- **3 — PGLite local.** Zero accounts, ~30 seconds. Isolated brain on this
Mac only. Best for try-first.
machine only. Best for try-first.
- **4 — Remote gbrain MCP.** Someone else (or another machine of yours) is
already running `gbrain serve` with HTTP transport. You paste the MCP URL
+ a bearer token; this skill registers it as your MCP. No local brain DB,
@@ -181,7 +181,7 @@ Options (present based on detected state):
machines or run by a teammate.
- **Switch** (only if Step 1 detected an existing engine): "You already have
a `<engine>` brain. Migrate it to the other engine?" → runs
`gbrain migrate --to <other>` wrapped in `timeout 180s` (D9).
`gbrain migrate --to <other>` wrapped in `timeout 180s`.
Do NOT silently pick; fire the AskUserQuestion.
@@ -199,9 +199,9 @@ For Paths 1, 2a, 2b, 3, switch — only if `gbrain_on_path=false`:
~/.claude/skills/gstack/bin/gstack-gbrain-install
```
The installer runs D5 detect-first (probes `~/git/gbrain`, `~/gbrain` first),
then D19 PATH-shadow validation (post-link `gbrain --version` must match
install-dir `package.json`). On D19 failure the installer exits 3 with a
The installer reuses an existing checkout first (probes `~/git/gbrain`, `~/gbrain`),
then validates PATH shadowing (post-link `gbrain --version` must match
install-dir `package.json`). On a PATH-shadow failure the installer exits 3 with a
clear remediation menu; surface the full output to the user and STOP. Do not
continue the skill — the environment is broken until the user fixes PATH.
@@ -236,7 +236,7 @@ doctor output and STOP.
---
## Step 5a: Register gbrain as Claude Code MCP (D18)
## Step 5a: Register gbrain as Claude Code MCP
Only if `which claude` resolves. Ask: "Give Claude Code a typed tool surface
for gbrain? (recommended yes)"
@@ -294,7 +294,7 @@ session start, not mid-session."
---
## Step 6: Per-remote policy (D3 triad, gated repo-import)
## Step 6: Per-remote policy (gated repo-import)
If we're in a git repo with an `origin` remote, check the policy:
@@ -329,11 +329,7 @@ For `/setup-gbrain --repo` invocations, execute ONLY Step 6 and exit.
## Step 7: Offer artifacts sync + wire it into gbrain
Renamed from "session memory sync" in v1.27.0.0 — the on-disk concept is
artifacts (CEO plans, designs, /investigate reports, retros) rather than
"session memory," which was a confusing name for what was always a
human-readable artifact bucket. Behavioral transcript ingest is its own
step (7.5) with its own option set.
Behavioral transcript ingest is a separate step (7.5).
Separate AskUserQuestion: "Also sync your gstack artifacts (CEO plans,
designs, reports, retros) to a private git repo that gbrain can index
@@ -358,8 +354,8 @@ URL_FORM=${URL_FORM_SUPPORTED:-false}
```
`gstack-artifacts-init` always prints a "Send this to your brain admin" block
at the end with the exact `gbrain sources add` command. Per codex Finding #3:
the skill never auto-executes server-side gbrain commands; even if the user
at the end with the exact `gbrain sources add` command. The skill
never auto-executes server-side gbrain commands; even if the user
IS the brain admin, copy-pasting the printed command is the consistent UX.
### Path 4 (Remote MCP) — done after artifacts-init
@@ -373,7 +369,7 @@ brain admin runs the printed command on the brain host instead. Skip to Step 7.5
Then wire the artifacts repo into gbrain so its content is searchable from
any gbrain client. The helper creates a `git worktree` of `~/.gstack/`,
registers it as a federated source via `gbrain sources add --path
--federated`, and runs an initial `gbrain sync`. Local-Mac only.
--federated`, and runs an initial `gbrain sync`. Local-stdio paths only.
Capture the database URL out of `~/.gbrain/config.json` first and pass it
explicitly so the wireup is robust against any other process rewriting
@@ -467,7 +463,7 @@ and STOP with a NEEDS_CONTEXT escalation.
---
## Step 9.5: Brain trust policy (v1.48 brain-aware planning, D4 / Phase 1.5)
## Step 9.5: Brain trust policy
The brain trust policy controls whether gstack auto-pushes `~/.gstack/`
artifacts and writes calibration takes back to this brain. It's per-
@@ -522,7 +518,7 @@ After answer, persist:
```
If `personal` was selected AND `artifacts_sync_mode` is still `off`, also
default it to `full` (D4 auto-push convention):
default it to `full` (personal brains auto-push):
```bash
_CURRENT_SYNC=$(~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo off)
@@ -539,7 +535,7 @@ or first-time-after-upgrade users.
## Step 10: GREEN/YELLOW/RED verdict block (idempotent doctor output)
After Steps 1-9 complete, summarize. Re-running `/setup-gbrain` on a
configured Mac is a first-class doctor path: every step detects existing
configured machine is a first-class doctor path: every step detects existing
state, repairs only what's missing, and reports here.
```bash
@@ -565,7 +561,7 @@ gbrain status: GREEN (mode: remote-http)
Repo policy ..... OK {read-write|read-only|deny}
Artifacts repo .. OK {gstack_artifacts_remote URL}
Artifacts sync .. OK {artifacts_sync_mode}
Transcripts ..... OK route to artifacts repo → remote brain (plan D11)
Transcripts ..... OK route to artifacts repo → remote brain
Code search ..... {OK local-pglite (~/.gbrain/pglite) | N/A declined at Step 4d}
CLAUDE.md ....... OK
Smoke test ...... INFO printed for post-restart manual verification
@@ -578,11 +574,11 @@ The **Code search** row reflects the choice at Step 4d:
- If user picked A (Yes): `OK local-pglite` and `gbrain_local_status == "ok"` going forward.
- If user picked B (No): `N/A declined at Step 4d` — `gstack-config set local_code_index_offered true` to silence future migration notices.
The **Transcripts** row changed in v1.34.0.0: in remote-http mode,
gstack-memory-ingest now persists staged transcripts to
`~/.gstack/transcripts/run-<pid>-<ts>/` and gstack-brain-sync pushes them
to the artifacts repo. Brain admin's pull job indexes into the remote brain.
Local PGLite (when present) stays code-only — no transcript pollution.
The **Transcripts** row: in remote-http mode, gstack-memory-ingest persists
staged transcripts to `~/.gstack/transcripts/run-<pid>-<ts>/` and
gstack-brain-sync pushes them to the artifacts repo; the brain admin's pull
job indexes them into the remote brain. Local PGLite (when present) stays
code-only.
### Paths 1, 2a, 2b, 3 (Local stdio)
@@ -598,21 +594,21 @@ gbrain status: GREEN (mode: local-stdio)
Artifacts sync .. OK <artifacts_sync_mode> to <remote>
Transcripts ..... OK <N> sessions, last ingest <when>
CLAUDE.md ....... OK
Smoke test ...... OK put → search → delete round-trip
Smoke test ...... OK put → search round-trip
Run `/setup-gbrain` again any time gbrain feels off; it's safe and idempotent.
```
If any row is YELLOW or RED, the verdict line says so and the failing rows
surface a one-line "next action" (e.g.,
`Engine .......... ERR PGLite corrupt — run \`gbrain restore-from-sync\` (V1.5)`).
For V1, restore-from-sync is a V1.5 P0 cross-repo TODO; until it ships,
the user's brain remote (with brain-sync enabled) holds curated artifacts
as markdown + git, recoverable manually via `gbrain import` from a clone.
`Engine .......... ERR PGLite corrupt — re-import from a clone of your brain remote with \`gbrain import\``).
There is no automatic restore: with brain-sync enabled, the brain remote holds
curated artifacts as markdown + git, recoverable via `gbrain import` from a
clone.
---
## `/setup-gbrain --cleanup-orphans` (D20)
## `/setup-gbrain --cleanup-orphans`
Re-collect a PAT (show the Path 2a PAT scope disclosure — it lives in the
brain-init section; read that section if it isn't already loaded), then:
@@ -643,7 +639,7 @@ At end: `unset SUPABASE_ACCESS_TOKEN`. Revocation reminder.
---
## Telemetry (D4)
## Telemetry
The preamble's Telemetry block logs skill success/failure at exit. When
emitting the event, add these enumerated categorical values to the
@@ -653,15 +649,14 @@ telemetry payload (SAFE — no free-form secrets, never the URL or PAT):
`supabase-manual` | `pglite-local` | `switch-to-supabase` |
`switch-to-pglite` | `repo-flip-only` | `cleanup-orphans` |
`resume-provision`
- `install_performed`: `yes` | `no` (D5 reuse) | `skipped` (pre-existing)
- `install_performed`: `yes` | `no` (existing checkout reused) | `skipped` (pre-existing)
- `mcp_registered`: `yes` | `no` | `claude-missing`
- `trust_tier_set`: `read-write` | `read-only` | `deny` |
`skip-for-now` | `n/a` (outside git repo)
Never pass `SUPABASE_ACCESS_TOKEN`, `DB_PASS`, `GBRAIN_POOLER_URL`,
`GBRAIN_DATABASE_URL`, or any `postgresql://` substring to the telemetry
invocation. The CI grep test in `test/skill-validation.test.ts` enforces
this at build time.
invocation.
---
@@ -672,7 +667,7 @@ this at build time.
that holds the pooler URL long-term is `~/.gbrain/config.json`, written
by gbrain's own `init` at mode 0600 — that's gbrain's discipline, not
ours.
- **STOP points are hard.** Gbrain doctor not healthy, D19 PATH shadow, D9
- **STOP points are hard.** Gbrain doctor not healthy, installer PATH shadow,
migrate timeout, smoke test failure — each is a STOP. Do not paper over.
- **Concurrent-run lock.** At skill start, create the parent before acquiring
the lock atomically. Keep mkdir's error output; missing parents and filesystem
+18 -19
View File
@@ -20,7 +20,7 @@ printf '%s' "$GBRAIN_POOLER_URL" | ~/.claude/skills/gstack/bin/gstack-gbrain-sup
If the verify exit code is 3 (direct-connection URL), the verifier's own
message explains the fix; surface it and re-prompt for a Session Pooler URL.
On success, hand off to gbrain via env var (D10, never argv):
On success, hand off to gbrain via env var (never argv):
```bash
GBRAIN_DATABASE_URL="$GBRAIN_POOLER_URL" gbrain init --non-interactive --json
@@ -29,9 +29,9 @@ GBRAIN_DATABASE_URL="$GBRAIN_POOLER_URL" gbrain init --non-interactive --json
Then `unset GBRAIN_POOLER_URL GBRAIN_DATABASE_URL` immediately. The URL is
now persisted in `~/.gbrain/config.json` at mode 0600 by gbrain itself.
### Path 2a (Supabase, auto-provision — D7)
### Path 2a (Supabase, auto-provision)
Show the D11 PAT scope disclosure verbatim BEFORE collecting the token:
Show this PAT scope disclosure verbatim BEFORE collecting the token:
> *This Supabase Personal Access Token grants full read/write/delete access
> to every project in your Supabase account, not just the `gbrain` one we're
@@ -49,7 +49,7 @@ Then:
read_secret_to_env SUPABASE_ACCESS_TOKEN "Paste PAT: "
```
Ask the D17 tier prompt via AskUserQuestion: "Which Supabase tier?" Present
Ask the tier question via AskUserQuestion: "Which Supabase tier?" Present
Free (2-project limit, pauses after 7d inactivity) vs Pro ($25/mo, no
pauses, recommended for real use). Explain that tier is **org-level** (per
the Management API contract) — user picks their org based on its current
@@ -75,7 +75,7 @@ Generate the DB password (never shown to the user):
export DB_PASS=$(openssl rand -base64 24)
```
Set up a SIGINT trap (D12 basic recovery):
Set up a SIGINT trap so an interrupted provision can be resumed or deleted:
```bash
trap 'echo ""; echo "gstack-gbrain: interrupted. In-flight ref: $INFLIGHT_REF"; \
@@ -111,9 +111,9 @@ After success, emit the PAT revocation reminder:
Walk the user through the supabase.com steps:
1. Login at https://supabase.com/dashboard
2. Click "New Project," name it `gbrain`, pick a region, copy the generated
database password (you'll need it for paste-back? no — it's embedded in
the pooler URL we collect next)
2. Click "New Project," name it `gbrain`, pick a region, and copy the
generated database password — the pooler URL in step 4 must carry it
(replace any `[YOUR-PASSWORD]` placeholder before pasting)
3. Wait ~2 min for the project to initialize
4. Settings → Database → Connection Pooler → Session → copy the URL (port
6543)
@@ -126,8 +126,8 @@ Then follow the same secret-read + verify + init flow as Path 1.
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — code
# retrieval beats general-purpose embeddings on real code queries (validated
# A/B). Without the key, gbrain auto-selects (OpenAI 1536d when available).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
# Never select gbrain's legacy zeroentropyai recipe for a new brain: its hosted
# API's sunset date (September 4, 2026) has passed; the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
@@ -155,7 +155,7 @@ Read with plain `read -r` (no secret hygiene needed — the URL alone isn't
a credential). Validate it starts with `https://` (require TLS for any
non-loopback host); refuse `http://` for non-localhost.
**4b. Collect bearer token via the secret-read helper (D10, never argv).**
**4b. Collect bearer token via the secret-read helper (never argv).**
```bash
. ~/.claude/skills/gstack/bin/gstack-gbrain-lib.sh
@@ -184,7 +184,7 @@ Capture two values from the verify output for downstream steps:
- `URL_FORM_SUPPORTED` (`true|false`) — passed to `gstack-artifacts-init` in
Step 7 to control which form of the brain-admin hookup command is printed.
**4d. (Path 4) Offer local PGLite for code search.** Per plan D10/D11, ask:
**4d. (Path 4) Offer local PGLite for code search.** Ask:
> D# — Want symbol-aware code search on this machine?
> Project/branch/task: <one-sentence grounding using detected slug + branch>
@@ -206,7 +206,7 @@ Capture two values from the verify output for downstream steps:
> ❌ Symbol code queries fall back to Grep in this repo's worktrees
> Net: A = full split-engine; B = remote-only.
**If A (Yes)**: install + init local PGLite with rollback-safe semantics (D7):
**If A (Yes)**: install + init local PGLite with rollback-safe semantics:
```bash
~/.claude/skills/gstack/bin/gstack-gbrain-install || exit $?
@@ -231,21 +231,20 @@ if ! gbrain init --pglite --json "$@"; then
fi
```
Then continue to Step 5a. The remote-http MCP registration in 5a runs as
today; the local PGLite is independent of MCP registration (Claude Code talks
Then continue to Step 5a. The remote-http MCP registration in 5a runs
unchanged; the local PGLite is independent of MCP registration (Claude Code talks
to the remote brain via MCP for queries; `gbrain` CLI talks to local PGLite
for code-def/refs/callers).
**If B (No)**: skip the install + init. The local engine stays absent.
`gbrain_local_status` will be `missing-config` (or `no-cli` if gbrain isn't
installed). `/sync-gbrain` will SKIP the code stage cleanly per plan D12.
installed). `/sync-gbrain` will SKIP the code stage cleanly.
**4e. Skip Steps 3, 4 (other paths) and 5 (local doctor) when B was picked.**
When A was picked, Step 3 already ran (via gstack-gbrain-install) and Step 4
already ran (via `gbrain init --pglite`); jump straight to Step 5a. When B
was picked, Steps 3/4/5 are no-ops; also skip Step 7.5 (transcript ingest)
since memory-stage routes through the artifacts pipeline in remote-http mode
per plan D11.
since memory-stage routes through the artifacts pipeline in remote-http mode.
The bearer token (`GBRAIN_MCP_TOKEN`) stays in process env until Step 5a's
`claude mcp add --header` consumes it; then `unset GBRAIN_MCP_TOKEN`
@@ -262,7 +261,7 @@ timeout 180s gbrain migrate --to supabase --url "$URL" --json
timeout 180s gbrain migrate --to pglite --json
```
If `timeout` returns 124 (exit code for timeout): surface D9 message
If `timeout` returns 124 (exit code for timeout): surface this message
("Migration didn't complete in 3 minutes — another gstack session may be
holding a lock on the source brain. Close other workspaces and re-run
`/setup-gbrain --switch`. Your original brain is untouched."). STOP.
@@ -1,6 +1,6 @@
### Step 1.5 remediation: broken-engine AskUserQuestion + repair branches
The user has a non-working local engine (Garry's repro: `~/.gbrain/config.json`
The user has a non-working local engine (for example, `~/.gbrain/config.json`
points at a dead Postgres URL). Fire a targeted AskUserQuestion BEFORE Step 2:
> D# — Your local gbrain engine isn't responding. How do you want to fix it?
@@ -37,7 +37,7 @@ with `GSTACK_DETECT_NO_CACHE=1` (busts the 60s cache). If the new
`gbrain_local_status` is `ok`, continue to Step 2. If still `broken-db` or
`broken-config`, fire the same AskUserQuestion again (the user picks again).
**If B (Switch to PGLite)** — execute the rollback-safe init sequence (plan D7):
**If B (Switch to PGLite)** — execute the rollback-safe init sequence:
```bash
BACKUP="$HOME/.gbrain/config.json.gstack-bak-$(date +%s)"
@@ -45,8 +45,8 @@ mv "$HOME/.gbrain/config.json" "$BACKUP"
# gstack default: voyage-code-3 (1024d) when VOYAGE_API_KEY is set — best for
# code retrieval. Without the key, fall back to gbrain's own auto-selected
# embedding provider chain (OpenAI 1536d when OPENAI_API_KEY is present, etc.).
# Never select gbrain's legacy zeroentropyai recipe for a new brain: the hosted
# API sunsets September 4, 2026 (#2365); the wireup helper warns existing installs.
# Never select gbrain's legacy zeroentropyai recipe for a new brain: its hosted
# API's sunset date (September 4, 2026) has passed; the wireup helper warns existing installs.
set -- # flags ride the positional params — unquoted $VAR breaks under zsh word-splitting (#1798)
if [ -n "${VOYAGE_API_KEY:-}" ]; then
set -- --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024
+22 -23
View File
@@ -34,7 +34,7 @@ refreshed against this repo's current state, and refreshes the agent-side
guidance in CLAUDE.md so the coding agent knows when to prefer `gbrain`
search over Grep.
**Architecture (post-codex review):** This skill uses gbrain v0.20.0+'s
**Architecture:** This skill uses gbrain v0.20.0+'s
**native code surfaces** (`gbrain sources add`, `gbrain sync --strategy code`,
`gbrain reindex-code`, `gbrain code-def/code-refs/code-callers/code-callees`).
It does NOT use `gbrain import` (that path is for markdown directories).
@@ -55,8 +55,8 @@ the skill itself, not a dispatcher binary):
- `/sync-gbrain --no-memory` / `--no-brain-sync` — selectively skip stages
- `/sync-gbrain --sources <types|all>` — memory types to ingest (env `GSTACK_MEMORY_INGEST_SOURCES`); by default, types a federated gstack source already indexes are skipped
- `/sync-gbrain --quiet` — suppress per-stage output
- `/sync-gbrain --refresh-cache` — force-rebuild brain-aware planning cache (v1.48; replaces /brain-refresh-context per D1 fold). Skips code + memory stages; routes to `gstack-brain-cache refresh --project <slug>`.
- `/sync-gbrain --audit` — emit summary of gstack-owned pages per project + sensitive-content audit (v1.48 / D10 lifecycle). Read-only.
- `/sync-gbrain --refresh-cache` — force-rebuild brain-aware planning cache. Skips code + memory stages; routes to `gstack-brain-cache refresh --project <slug>`.
- `/sync-gbrain --audit` — emit summary of gstack-owned pages per project + sensitive-content audit. Read-only.
Pass-through args go straight to the orchestrator at
`{{BIN_DIR}}/gstack-gbrain-sync.ts`.
@@ -71,20 +71,20 @@ brain has new info gstack should pick up before the next planning skill.
**`--audit` short-circuit:** when this flag is present, the skill runs
`gstack-brain-cache list --project <slug> --json`, summarizes by page
type, then scans for any cached salience entries that ended up outside
the SALIENCE_DEFAULT_ALLOWLIST (T17 / D9 leak check). Read-only; no
the SALIENCE_DEFAULT_ALLOWLIST (leak check). Read-only; no
modifications to brain or cache.
---
## Step 1: State probe
Before doing anything, check that /setup-gbrain has been run on this Mac.
Before doing anything, check that /setup-gbrain has been run on this machine.
```bash
~/.claude/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null
```
**Brain trust policy gate (v1.48 / Phase 1.5 / D4 — added by T13+T5c):**
**Brain trust policy gate:**
If `gbrain_mcp_mode == "remote-http"` from the detect output AND the per-
endpoint policy is `unset`, the policy question MUST fire here before
the orchestrator runs. Local engines auto-set to `personal` silently per
@@ -107,20 +107,20 @@ If `_POLICY == "unset"` AND `_HASH == "local"`, auto-set personal:
~/.claude/skills/gstack/bin/gstack-config set brain_trust_policy@$_HASH personal
```
**Split-engine model (v1.34.0.0+).** Code stage runs locally against the
**Split-engine model.** Code stage runs locally against the
per-machine gbrain engine (PGLite or whatever `gbrain config` points to),
with each worktree of a repo registered as its own source. **Memory stage
also runs locally** in local-stdio MCP mode — `gstack-memory-ingest` shells
out to `gbrain import` against the same local engine. In remote-http MCP
mode (Path 4), the memory stage instead persists staged markdown to
`~/.gstack/transcripts/<run-id>/` and the artifacts pipeline pushes it to
the brain admin's pull job (plan D11). Brain-sync (the `gstack-brain-sync`
the brain admin's pull job. Brain-sync (the `gstack-brain-sync`
push to git) is the one stage that never touches local engine and runs
regardless of mode.
Practically: local PGLite stays code-only on remote-http machines; the
remote brain holds everything else. Local-stdio machines mix code +
transcripts in one local engine, as they always have.
transcripts in one local engine.
Also check the per-repo trust policy. If `gstack-gbrain-repo-policy get` for
this repo returns `deny`, STOP:
@@ -130,18 +130,18 @@ this repo returns `deny`, STOP:
---
## Step 1.5: Local engine pre-flight (plan D12)
## Step 1.5: Local engine pre-flight
Read `gbrain_local_status` from the Step 1 detect output. Branch as follows
BEFORE invoking the orchestrator:
- **`ok`**: proceed to Step 2 normally.
- **`timeout`**: proceed to Step 2 — the engine is most likely healthy but
slow (cold pooler connection, #1964). Tell the user in one line: "Engine
slow (cold pooler connection). Tell the user in one line: "Engine
probe timed out (>15s) — proceeding; raise `GSTACK_GBRAIN_PROBE_TIMEOUT_MS`
if your pooler is slow." Do NOT treat this as a broken config.
- **`thin-client`**: proceed to Step 2 — this machine is a thin client of a
remote-HTTP MCP brain (#2051): no local engine BY DESIGN, so the code,
remote-HTTP MCP brain: no local engine BY DESIGN, so the code,
memory, and dream stages will SKIP with a thin-client reason (code indexing
runs on the brain server; memory syncs via the remote brain's artifacts
pull). Only the brain-sync push runs locally. Tell the user in one line:
@@ -157,12 +157,12 @@ BEFORE invoking the orchestrator:
- **`missing-config`** AND `gbrain_mcp_mode == "remote-http"`: tell the user
"Your brain queries (the `mcp__gbrain__*` tools) work via remote MCP, but
symbol code search needs a local PGLite. Run `/setup-gbrain` and pick
'Yes' at the new 'local code index' prompt (Step 4.5), or run
'Yes' at the local code-search prompt (Path 4, step 4d), or run
`gbrain init --pglite --json --embedding-model voyage:voyage-code-3 --embedding-dimensions 1024`
directly (drop the voyage flags if `VOYAGE_API_KEY` isn't set). Continuing
without code stage."
Then proceed to Step 2 — the orchestrator's `runCodeImport()` and
`runMemoryIngest()` will return SKIP per plan D12; only `runBrainSyncPush()`
`runMemoryIngest()` will return SKIP; only `runBrainSyncPush()`
will run. Do NOT abort.
- **`missing-config`** AND `gbrain_mcp_mode != "remote-http"`: STOP. "Local
gbrain CLI is installed but no engine config. Run `/setup-gbrain` first."
@@ -171,7 +171,7 @@ BEFORE invoking the orchestrator:
Local gbrain config at ~/.gbrain/config.json points at an unreachable
engine (status: {gbrain_local_status}). Two options:
1. Re-run /setup-gbrain — Step 1.5 offers Retry / Switch to PGLite /
Switch brain mode / Quit (plan D4).
Switch brain mode / Quit.
2. Repair manually: mv ~/.gbrain/config.json ~/.gbrain/config.json.bak
&& gbrain init --pglite --json --embedding-model voyage:voyage-code-3 \
--embedding-dimensions 1024 (drop voyage flags if VOYAGE_API_KEY unset)
@@ -196,8 +196,7 @@ as-is.
bun run ~/.claude/skills/gstack/bin/gstack-gbrain-sync.ts <user-args>
```
The orchestrator runs three stages: code → memory → brain-sync (per the
plan's storage tiering). Each stage failure is non-fatal; subsequent stages
The orchestrator runs three stages: code → memory → brain-sync. Each stage failure is non-fatal; subsequent stages
still run. State is persisted to `~/.gstack/.gbrain-sync-state.json` via
tmp-file + atomic rename. Concurrent runs are blocked by a lock file at
`~/.gstack/.sync-gbrain.lock` (5-min stale-takeover).
@@ -227,7 +226,7 @@ the preamble:
>
> ELI10: gbrain hasn't indexed this repo's code yet. The semantic search
> tools (`gbrain search`, `code-def`, `code-refs`) will return nothing
> until we run a full pass. Takes ~25-35 minutes on a big Mac.
> until we run a full pass. Takes ~25-35 minutes on a big repo.
>
> Recommendation: A — the brain is unusable for code search until indexed,
> and Step 2 of this skill already verified gbrain is configured correctly.
@@ -318,7 +317,7 @@ only that a cycle has run, not that edges exist (a non-code-aware pack reports
## Step 4: Refresh `## GBrain Search Guidance` block in CLAUDE.md
Capability check (per /plan-eng-review §6):
Capability check:
```bash
bun run ~/.claude/skills/gstack/bin/gstack-gbrain-read-capability.ts <user-args>
@@ -432,8 +431,8 @@ continue.
Print a status block matching `/setup-gbrain` Step 10 conventions. Each row
is `[OK]/[FIX]/[WARN]/[ERR]`. Reuse `gbrain doctor --json --fast` for
informational rows but DO NOT gate the guidance block on doctor (per
/plan-eng-review §6 — doctor is too strict for unrelated reasons).
informational rows but DO NOT gate the guidance block on doctor (doctor
fails for reasons unrelated to code search).
```
gbrain status: GREEN
@@ -481,7 +480,7 @@ A `never`/`unknown` Call graph row flips the verdict to YELLOW.
## Concurrency note
This skill is safe to run concurrently from multiple terminals on the same
Mac. The orchestrator acquires a lock at `~/.gstack/.sync-gbrain.lock` before
machine. The orchestrator acquires a lock at `~/.gstack/.sync-gbrain.lock` before
any state-file or CLAUDE.md mutation and exits with code 2 if another sync is
in flight. Stale locks (process died) auto-clear after 5 minutes.
@@ -489,7 +488,7 @@ in flight. Stale locks (process died) auto-clear after 5 minutes.
The `## GBrain Search Guidance` block is committed to the repo's CLAUDE.md
and travels with `git push`/`git pull` — NOT through `~/.gstack/.brain-allowlist`
(which is for `~/.gstack/` brain-sync only). On a different Mac with a synced
(which is for `~/.gstack/` brain-sync only). On a different machine with a synced
CLAUDE.md but no local gbrain, /sync-gbrain reports an unknown read and
preserves the block rather than deleting committed instructions based on a
transient or machine-local failure. Agents must not treat unknown as ready.
@@ -97,10 +97,6 @@ describe('setup-gbrain templates (skeleton + sections) — bin invocation paths'
'~/.claude/skills/gstack/bin/gstack-config set transcript_ingest_mode <choice>'
);
});
test('the prose-only mention naming the tool as a sentence subject is left unchanged (KTD4 — not a literal invocation; Step 10 verdict, skeleton)', () => {
expect(tmpl).toContain('gstack-memory-ingest now persists staged transcripts to');
});
});
describe('setup-gbrain/memory.md — bin invocation paths', () => {