Synchroniser gbrain

Maintenir gbrain à jour avec le code du dépôt et actualiser les conseils de recherche de l'agent dans AGENTS.md. Ré-exécutable et idempotent.

Spar Skills Guide Bot
DeveloppementAvancé
0024/07/2026
Claude Code
#gbrain#code-indexing#repository-sync#agent-search#idempotent

Recommandé pour


name: sync-gbrain preamble-tier: 2 version: 1.0.0 description: | Keep gbrain current with this repo's code and refresh agent search guidance in AGENTS.md. Wraps the gstack-gbrain-sync orchestrator with state probing, native code-surface registration, capability checks, and a verdict block. Re-runnable, idempotent. Use when: "sync gbrain", "refresh gbrain", "re-index this repo", "gbrain search isn't finding things". (gstack) triggers:

  • sync gbrain
  • refresh gbrain
  • reindex repo
  • update gbrain allowed-tools:
  • Bash
  • Read
  • Write
  • Edit
  • Glob
  • Grep
  • ask the user in chat

{{PREAMBLE}}

/skill:sync-gbrain — Keep gbrain current and teach the agent to use it

You are running the canonical "keep this brain up to date" verb. /skill:setup-gbrain installs gbrain once; /skill:sync-gbrain runs every time the user wants the brain refreshed against this repo's current state, and refreshes the agent-side guidance in AGENTS.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 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). It does NOT touch ~/.gstack/ indexing (the existing gstack-gbrain-source-wireup owns that — never double-store).

User-invocable

When the user types /skill:sync-gbrain, run this skill. Argument modes (parsed by the skill itself, not a dispatcher binary):

  • /skill:sync-gbrain — incremental sync (default; mtime fast-path; ~50ms steady-state)
  • /skill:sync-gbrain --full — full code reindex via gbrain reindex-code (~25-35 min on a big repo). Auto-builds the call graph (gbrain dream) only when it was never built.
  • /skill:sync-gbrain --dream — build this source's call graph (gbrain code-callers/code-callees) via a source-scoped gbrain dream --source <id> cycle; ~minutes; runs lock-free after the sync stages. Always forces, even if already built. Only produces a graph on a code-aware schema pack; otherwise the run reports a WARN explaining why the graph is still empty.
  • /skill:sync-gbrain --no-dream — skip the dream cycle that --full would otherwise auto-run.
  • /skill:sync-gbrain --code-only — only run the code stage; skip memory + brain-sync
  • /skill:sync-gbrain --dry-run — preview what would sync; no writes anywhere
  • /skill:sync-gbrain --no-memory / --no-brain-sync — selectively skip stages
  • /skill:sync-gbrain --quiet — suppress per-stage output
  • /skill: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>.
  • /skill:sync-gbrain --audit — emit summary of gstack-owned pages per project + sensitive-content audit (v1.48 / D10 lifecycle). Read-only.

Pass-through args go straight to the orchestrator at {{BIN_DIR}}/gstack-gbrain-sync.ts.

--refresh-cache short-circuit: when this flag is present, the skill runs ONLY the cache refresh (gstack-brain-cache refresh --project <slug> for the current worktree's slug, plus a cross-project refresh of user-profile if gstack/user-profile/<user-slug> exists). Code + memory + brain-sync stages are skipped. Useful when the user knows the 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 modifications to brain or cache.


Step 1: State probe

Before doing anything, check that /skill:setup-gbrain has been run on this Mac.

~/.pi/agent/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null

Brain trust policy gate (v1.48 / Phase 1.5 / D4 — added by T13+T5c): 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 the per-transport default table.

_HASH=$(~/.pi/agent/skills/gstack/bin/gstack-config endpoint-hash 2>/dev/null)
_POLICY=$(~/.pi/agent/skills/gstack/bin/gstack-config get brain_trust_policy@$_HASH 2>/dev/null || echo unset)
echo "BRAIN_TRUST_POLICY[$_HASH]: $_POLICY"

If _POLICY == "unset" AND _HASH != "local", ask the user in chat per the Step 9.5 wording in /skill:setup-gbrain (personal vs shared, with persistence to brain_trust_policy@<hash> and conditional artifacts_sync_mode=full flip for personal). Then continue.

If _POLICY == "unset" AND _HASH == "local", auto-set personal:

~/.pi/agent/skills/gstack/bin/gstack-config set brain_trust_policy@$_HASH personal

Split-engine model (v1.34.0.0+). 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 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.

Also check the per-repo trust policy. If gstack-gbrain-repo-policy get for this repo returns deny, STOP:

"This repo's gbrain trust policy is deny. Run /skill:setup-gbrain --repo to change it before syncing."


Step 1.5: Local engine pre-flight (plan D12)

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 probe timed out (>15s) — proceeding; raise GSTACK_GBRAIN_PROBE_TIMEOUT_MS if your pooler is slow." Do NOT treat this as a broken config.
  • engine-locked: STOP. "The local PGLite database is busy, usually because gbrain serve from a live Claude session owns it. Stop that process or run /skill:sync-gbrain outside the live session, then retry. This identifies the conflict but does not remove PGLite's single-process limit."
  • no-cli: STOP. "Local gbrain CLI not installed. Run /skill:setup-gbrain first."
  • 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 /skill:setup-gbrain and pick 'Yes' at the new 'local code index' prompt (Step 4.5), 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() will run. Do NOT abort.
  • missing-config AND gbrain_mcp_mode != "remote-http": STOP. "Local gbrain CLI is installed but no engine config. Run /skill:setup-gbrain first."
  • broken-config OR broken-db: STOP with a clear message:
    Local gbrain config at ~/.gbrain/config.json points at an unreachable
    engine (status: {gbrain_local_status}). Two options:
      1. Re-run /skill:setup-gbrain — Step 1.5 offers Retry / Switch to PGLite /
         Switch brain mode / Quit (plan D4).
      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)
    Re-run /skill:sync-gbrain after.
    
    Do NOT continue — the orchestrator would skip code+memory and only run brain-sync, which is a degraded state the user should fix explicitly.

This pre-flight short-circuits the orchestrator before it spends ~80ms probing the engine again. The orchestrator independently runs the same classifier for defense-in-depth, but Step 1.5's STOP is where the user gets the actionable remediation message.


Step 2: Run the orchestrator

Pass user args to the orchestrator. Do not paraphrase them — pass through as-is.

bun run ~/.pi/agent/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 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).


Step 3: Code-index health check

After the sync run, query gbrain for the cwd source's page_count:

SOURCE_ID=$(grep -o '"source_id":"[^"]*"' ~/.gstack/.gbrain-sync-state.json 2>/dev/null \
  | head -1 | sed 's/.*"source_id":"//;s/".*//')
PAGES=$(gbrain sources list --json 2>/dev/null \
  | jq -r --arg id "$SOURCE_ID" '.sources[] | select(.id==$id) | .page_count' 2>/dev/null \
  || echo 0)
echo "cwd source: $SOURCE_ID, page_count: $PAGES"

If PAGES is 0 or empty AND the user did NOT pass --no-code AND mode was not --full, ask the user in chat via the format in the preamble:

D1 — This repo has 0 indexed pages in gbrain. Run a full code reindex now?

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.

Recommendation: A — the brain is unusable for code search until indexed, and Step 2 of this skill already verified gbrain is configured correctly.

Note: options differ in kind, not coverage — no completeness score.

A) Run /skill:sync-gbrain --full now (recommended) B) Skip — I'll run it later

If A: re-invoke the orchestrator with --full --code-only. If B: continue to Step 4 with the empty-corpus state recorded.


Step 3.5: Call-graph health check (offer --dream)

gbrain code-callers / code-callees (who-calls-this / what-this-calls) return count: 0 until a gbrain dream cycle runs the resolve_symbol_edges phase for this source — not done by the code import in Step 2.

One hard prerequisite: building a call graph requires this source's active schema pack to extract code symbols (the extract_atoms phase). On a pack that doesn't declare it (e.g. gbrain-base / gbrain-base-v2), a dream cycle completes but resolve_symbol_edges matches nothing — the graph stays empty no matter how many times you run it. So "build the call graph" is only meaningful on a code-aware pack. The --dream stage detects this and reports it honestly (a WARN row) rather than claiming a build that didn't happen. gbrain exposes pack capability only at cycle runtime (no pre-flight query as of 0.41.x), so we can't detect it before running. code-def / code-refs need the same symbol extraction; they are NOT free "direct lookups" on a non-code-aware pack.

Detect whether this source's call graph is built via doctor's cycle_freshness check, matching the cwd SOURCE_ID literally:

SOURCE_ID=$(grep -o '"source_id":"[^"]*"' ~/.gstack/.gbrain-sync-state.json 2>/dev/null \
  | head -1 | sed 's/.*"source_id":"//;s/".*//')
CYCLE=$(gbrain doctor --json --fast 2>/dev/null \
  | jq -r --arg id "$SOURCE_ID" '
      (.checks[] | select(.name=="cycle_freshness")) as $c
      | if $c.status=="ok" then "completed"
        elif ($c.message | index($id)) then "never"
        else "unknown" end' 2>/dev/null || echo unknown)
# index($id) = literal substring (NOT test() regex), matching the lib reader in
# cycleCompleted(). A fail/warn that doesn't name this source → "unknown" (don't
# mask other-source failures).
echo "call graph for $SOURCE_ID: $CYCLE"

If CYCLE == never AND the user did NOT pass --dream/--full AND Step 3 PAGES > 0, ask the user in chat via the format in the preamble:

D2 — This repo's call graph isn't built. Build it now?

ELI10: gbrain code-callers/code-callees (who calls this function / what it calls) return nothing until the resolve_symbol_edges phase runs for this source. gbrain dream --source <this source> runs it (scoped to this worktree's code, takes a few minutes). It only produces a graph if this source's schema pack extracts code symbols; if it doesn't, the run completes but the graph stays empty and the dream row will say so.

Recommendation: A — call-graph queries return 0 until this runs, and the code index is already populated. If A comes back as a WARN ("pack does not extract code symbols"), the fix is a code-aware schema pack, not re-running dream.

Note: options differ in kind, not coverage — no completeness score.

A) Run /skill:sync-gbrain --dream now (recommended) B) Skip — I'll run it later

If A: re-invoke the orchestrator with --dream --code-only (skips memory + brain-sync; the dream stage still runs because it's gated on --dream). Then report the dream stage's ACTUAL row — OK call graph built (N edges) vs a WARN that names why the graph is still empty (non-code-aware pack, missing embedding key, or 0 edges matched). Do not claim success on a WARN. If B: continue to Step 4 with the call-graph-not-built state recorded for the verdict.

If CYCLE == completed or unknown, do not prompt — but note completed means only that a cycle has run, not that edges exist (a non-code-aware pack reports completed with an empty graph). Step 5's verdict row surfaces the real state.


Step 4: Refresh ## GBrain Search Guidance block in AGENTS.md

Capability check (per /skill:plan-eng-review §6):

SLUG="_capability_check_$$"
CAPABILITY_OK=0
if [ -f ~/.gbrain/config.json ] && \
   gbrain --version 2>/dev/null | grep -q '^gbrain '; then
  # Do NOT export GBRAIN_PREPARE here (#1965). gbrain auto-disables prepared
  # statements on transaction-mode poolers (port 6543) — forcing them on
  # breaks every write with "prepared statement does not exist". Users on a
  # session-mode pooler at 6543 can set GBRAIN_PREPARE=true themselves (the
  # gbrain banner documents this override).
  if echo "ping" | gbrain put "$SLUG" >/dev/null 2>&1; then
    # Retry search up to 3 times with 1s delay — under transaction-mode
    # pooling the search index may not be visible on the next connection
    # immediately after the put.
    for _attempt in 1 2 3; do
      if gbrain search "ping" 2>/dev/null | grep -q "$SLUG"; then
        CAPABILITY_OK=1
        break
      fi
      sleep 1
    done
  fi
fi
gbrain delete "$SLUG" 2>/dev/null || true

Then update AGENTS.md based on capability state:

If CAPABILITY_OK=1 — write or update the block. Idempotent: find the HTML-comment-delimited block; replace its body if it exists; append at the end of AGENTS.md if it doesn't. NEVER duplicate. Block is machine-AGNOSTIC (no engine, no page counts, no last-sync time — those are in the existing ## GBrain Configuration block).

Verbatim block content (copy exactly):

## GBrain Search Guidance (configured by /skill:sync-gbrain)
<!-- gstack-gbrain-search-guidance:start -->

GBrain is set up and synced on this machine. The agent should prefer gbrain
over Grep when the question is semantic or when you don't know the exact
identifier yet.

**This worktree is pinned to a worktree-scoped code source** via the
`.gbrain-source` file in the repo root (kubectl-style context).
`gbrain code-def`, `code-refs`, `code-callers`, `code-callees`, `search`, and
`query` from anywhere under this worktree route to that source by default —
no `--source` flag needed (gbrain >= 0.41.38.0; on older gbrain the call-graph
commands need `--source "$(cat .gbrain-source)"`). Conductor sibling worktrees
of the same repo each have their own pin and their own indexed pages, so
semantic results match the code on disk here.

Call-graph queries (`code-callers`/`code-callees`) also need the graph to be
built first — run `/skill:sync-gbrain --dream` (or `--full`) if they return
`count: 0`. This only works if this source's gbrain schema pack extracts code
symbols; on a non-code-aware pack `--dream` completes but the graph stays empty
and reports a WARN. `code-def`/`code-refs` need the same extraction.

Two indexed corpora available via the `gbrain` CLI:
- This worktree's code (auto-pinned via `.gbrain-source`).
- `~/.gstack/` curated memory (registered as `gstack-brain-<user>` source via
  the existing federation pipeline).

Prefer gbrain when:
- "Where is X handled?" / semantic intent, no exact string yet:
    `gbrain search "<terms>"` or `gbrain query "<question>"`
- "Where is symbol Y defined?" / symbol-based code questions:
    `gbrain code-def <symbol>` or `gbrain code-refs <symbol>`
- "What calls Y?" / "What does Y depend on?":
    `gbrain code-callers <symbol>` / `gbrain code-callees <symbol>`
- "What did we decide last time?" / past plans, retros, learnings:
    `gbrain search "<terms>" --source gstack-brain-<user>`

Grep is still right for known exact strings, regex, multiline patterns, and
file globs. Run `/skill:sync-gbrain` after meaningful code changes; for ongoing
auto-sync across all worktrees, run `gbrain autopilot --install` once per
machine — gbrain's daemon handles incremental refresh on a schedule.

Safety: don't run `/skill:sync-gbrain` while `gbrain autopilot` is active — the
orchestrator refuses destructive source ops when it detects a running autopilot
to avoid racing it (#1734). Prefer registering user repos with `gbrain sources
add --path <dir>` (no `--url`): URL-managed sources can auto-reclone, and the
sync code walk for them requires an explicit `--allow-reclone` opt-in.

<!-- gstack-gbrain-search-guidance:end -->

Use the Read + Edit tools. The find-and-replace target is the entire region from <!-- gstack-gbrain-search-guidance:start --> through <!-- gstack-gbrain-search-guidance:end -->. If those markers are missing, search for ## GBrain Search Guidance (configured by /skill:sync-gbrain) heading and replace from there to the next ## or EOF. If no heading exists, append the entire block at the end of AGENTS.md.

Atomic write: write the new AGENTS.md content to a tmp file alongside it (e.g., AGENTS.md.sync-gbrain.tmp) then mv to atomic-rename, so a crash mid-write never leaves the file half-modified.

If CAPABILITY_OK=0 — REMOVE the block entirely if present. Use the same Edit tool to strip the start/end-marker region. The ## GBrain Configuration block stays in place (it's a record of the install, not a capability claim).

Do NOT crash if AGENTS.md is missing or unwritable — log a warning and continue.


Step 5: Verdict block (idempotent doctor output)

Print a status block matching /skill: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 /skill:plan-eng-review §6 — doctor is too strict for unrelated reasons).

gbrain status: GREEN

  CLI ............. OK   <gbrain version>
  Engine .......... OK   <pglite|supabase>
  Capability ...... OK   write+search round-trip
  CWD source ...... OK   <gstack-code-{repo_slug}> (page_count=<N>)
  Call graph ...... OK   <N> edges resolved (code-callers/callees live)
  ~/.gstack source. OK   <gstack-brain-{user}> (page_count=<N>) — managed by /skill:setup-gbrain
  Memory sync ..... OK   <artifacts_sync_mode>
  AGENTS.md ....... OK   ## GBrain Search Guidance present
  Last sync ....... OK   <last_sync from state file>

Run `/skill:sync-gbrain` again any time gbrain feels off; safe and idempotent.

The Call graph row reports the most authoritative signal available:

  1. If a dream stage ran this invocation (--dream, or --full auto-build), mirror its row verbatim — it's the ground truth for this run:
    • OK <N> edges resolved (code-callers/callees live)
    • WARN dream ran but this source's schema pack does not extract code symbols — switch to a code-aware pack (\gbrain schema use <pack>`)`
    • WARN dream ran but the embed phase failed (missing embedding key)
    • WARN dream ran but resolved 0 edges (no code symbols matched yet)
  2. Otherwise fall back to the CYCLE value from Step 3.5, with honest wording (a completed cycle proves a cycle ran, NOT that edges exist):
    • completedOK cycle complete — code-callers/callees live IF this source's pack extracts code symbols
    • neverWARN call graph not built — run /skill:sync-gbrain --dream
    • unknownWARN could not probe call graph (doctor unavailable) — run /skill:sync-gbrain --dream if code-callers returns 0

Any WARN Call graph row flips the verdict to YELLOW.

If any row is YELLOW or RED, the verdict line says so and the failing rows surface a one-line "next action" (e.g., Capability ...... ERR capability check failed; AGENTS.md guidance block REMOVED — run /skill:setup-gbrain to repair). 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 any state-file or AGENTS.md mutation and exits with code 2 if another sync is in flight. Stale locks (process died) auto-clear after 5 minutes.

Cross-machine note

The ## GBrain Search Guidance block is committed to the repo's AGENTS.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 AGENTS.md but no local gbrain, /skill:sync-gbrain detects the mismatch via the capability check and REMOVES the block (the local agent shouldn't be told to use a tool that isn't installed).

Status reporting

End with a Completion Status (per the preamble protocol):

  • DONE — all stages green, AGENTS.md guidance block present, verdict GREEN.
  • DONE_WITH_CONCERNS — sync ran but at least one stage failed or capability check failed. List which.
  • BLOCKED — could not acquire lock, gbrain not on PATH, or per-repo policy is deny. State the blocker.
  • NEEDS_CONTEXT — /skill:setup-gbrain has not been run, or gbrain doctor shows a state that requires user decision (e.g., engine migration).
Skills similaires