mirror of
https://github.com/garrytan/gstack.git
synced 2026-08-29 01:10:50 +02:00
* feat(gen): strip gen-time-only frontmatter keys from Claude renders
interactive + benefits-from are read from the .tmpl by buildContext at
generation time; no runtime, host, or test reader consumes them from the
generated SKILL.md (e2e-harness-audit reads .tmpl; benefits-from tests
assert rendered prose). gbrain: stays (bin/gstack-brain-context-load reads
it from the installed render); hooks: stays (Claude Code host wires
PreToolUse from it).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(gen): regenerate SKILL.md — dead frontmatter keys removed
Mechanical regen after hosts/claude.ts stripFields change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(test): context-budget ratchet — CI ceilings on always-on + eager token ledgers
New free test grades the two ledgers nothing else guards: the full-frontmatter
always-on catalog (aggregate) and per-skill eager tokens (SKILL.md +
forced-read refs), via checkBudget from lib/context-bill.ts. Ceilings live in
test/fixtures/context-budget.json with x1.05/x1.10 headroom; regenerate with
bun test/helpers/capture-context-budget.ts. New skills fail until consciously
budgeted; removed skills fail until the fixture is refreshed; reductions
ratchet the ceilings down so wins lock in.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(todos): file output-template carve wave + plan-ceo doctrine revisit; mark preamble-carve P3 in flight
Two follow-ups deferred from the approved token-reduction program (CEO review
'NOT in scope' list), filed with full context per TODOS format. The existing
P3 preamble-carve entry gets a status update pointing at the program that
supersedes it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(test): review findings — Windows path normalization, full totals rebuild, ratchet coverage
Pre-landing review (5 specialists) found one critical: the ratchet test runs
in the curated Windows lane, where path.relative yields backslash skill names
that miss the test/ filter and mismatch every POSIX fixture key. Names are now
normalized once in buildRatchetBill (toPosixName) and the fixture filter is
tightened to test/fixtures/. All eight Bill.totals fields are rebuilt from the
filtered list (no fixture-polluted perInvocation/totalMd numbers for future
consumers). New coverage: Windows-separator normalization pins, a
captureContextBudget round-trip against tree-a (headroom math exact), a
stripFields regression pin (interactive/benefits-from absent from renders,
hooks/gbrain preserved), and the ceilings test no longer double-reports
stale-fixture entries.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(test): adversarial findings — stable root key, symlink-alias dedupe, fixture-shape guard
Adversarial review (Claude subagent) verified the fixture's root-skill key was
the capture machine's checkout dirname: any non-gstack-named clone (every
Conductor worktree) failed the free suite, and the documented re-run-the-capture
recovery baked the local dirname into the committed fixture — silent corruption
through the tool's own protocol. The root skill is now pinned to ROOT_SKILL_KEY
('gstack', its frontmatter name). Symlink aliases are realpath-deduped (census
precedent): connect-chrome no longer gets its own ceiling, so Windows checkouts
that materialize the symlink as a plain file can't fail the stale-ceiling
set-equality test. New guards: fixture-shape validation (a string alwaysOnTotal
can no longer silently disable the ceiling), a mutation pin that the filter
shrinks the always-on ledger vs the raw bill, an alwaysOnTotal violation test
(the branch was load-bearing with only under-budget coverage), and an atomic
temp+rename fixture write. Fixture regenerated: 59 ceilings, alwaysOnTotal 6344.
Deferred with a TODO: anchoring transformFrontmatter's denylist strip to the
frontmatter block (latent, zero live collisions, pre-existing path).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore: bump version and changelog (v1.69.1.0)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: update project documentation for v1.69.1.0
CLAUDE.md: Token ceiling section documents the context-budget ratchet as
the third guard (test file, fixture, new-skill budgeting, capture command).
CONTRIBUTING.md: Tier 1 guard list gains a Context-budget ratchet bullet;
the Adding-a-new-skill checklist gains the budget-capture step.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: pin exact guard semantics for the context-budget ratchet in CLAUDE.md
Doc-review finding: "a third enforced ceiling" undercounted the guard
family (skill-size-budget floors and parity ratios also watch these
ledgers, relatively). Rephrased to match the ratchet test's own header:
absolute ceilings vs relative floors/ratios.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(changelog): heaviest-skill claim matches the fixture (land-and-deploy edges review by 0.2%)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(bin): gstack-skill-start + gstack-skill-end — the preamble runtime, consolidated
Absorbs the ~13KB of bash every tier-2+ SKILL.md inlined twice over (bootstrap
fence + artifacts-sync fence) and the skill-end telemetry/sync fences. Same
KEY: value STATUS-line contract the prose interprets, plus SKILL_START_PROTO
handshake (OV5), SESSION_ID/TEL_START echoes, GSTACK_HOME-normalized state
paths (EOV7), --parent-pid session identity (EOV5: $PPID inside the script is
the ephemeral tool-call shell), OV4 sanitization of passthrough output, and a
receipted daily artifacts pull (_receipted_git, brain-sync class, fail-closed).
Per-line || true error style throughout (F3) — a mid-script failure never drops
later STATUS lines.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(gen): preamble resolvers emit a script invocation fence instead of inline bash
generate-preamble-bash: ~6.3KB fence -> 4-line gstack-skill-start invocation
(quoted-tilde pitfall handled: leading ~ interpolates through $HOME; env-var
hosts keep $GSTACK_BIN) + degraded-mode prose (F1/EOV8: safe defaults, consent
gates deferred-never-lost; OV5: proto rule). generate-brain-sync-block: ~6.8KB
bash -> interpretation prose + the privacy stop-gate (stays inline until
Phase 2's gated emission). generate-completion-status: telemetry fence -> one
gstack-skill-end call with SESSION_ID/TEL_START handoff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(gen): regenerate all skills + golden fixtures — inline preamble bash removed
Mechanical regen after the resolver change: −12,628 lines across 52 renders
(corpus 952K -> 806K render tokens; tier-2 skills −11-13KB each). Golden
per-host ship fixtures refreshed from the fresh claude/codex/factory renders.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: skill-start contract suite + preamble A/B eval + touchfiles registration
test/gstack-skill-start.test.ts (11 free tests): STATUS-key contract vs the
prose (F2), per-host fence resolution shapes (E1), proto-first, OV4 marker
sanitization, --parent-pid identity, headless suppression, skill-end duration
math + pending cleanup. test/skill-e2e-preamble-script-ab.test.ts (gate tier,
OV7): inline-bash render (pinned from 29785978) vs script render with the
fence redirected at the worktree bin (EOV2 — hermetic evals otherwise resolve
the operator install and silently exercise degraded mode). 21 touchfiles dep
lists gain the two bin scripts (EOV9) so future script edits select the
preamble evals; selection-count pin updated 23->24.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: repin ~70 assertions to the script contract — every literal gets a successor
Assertions that pinned inline-bash internals (update-check guard, _SESSIONS
reaping, telemetry start/end blocks, routing probe, repo-strip producer,
first-task gating, EXPLAIN_LEVEL/QUESTION_TUNING echoes, #2499 jq scope
resolution, Issue-8 CONDUCTOR gate) now pin the same invariants in their new
home: bin/gstack-skill-start / bin/gstack-skill-end file content for script
internals, the invocation fence + interpretation prose for render-side
behavior. No assertion deleted without a successor; live-execution tests
(routing probe, brain-sync jq) run against script bytes unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(test): re-baseline size floors + ratchet ceilings down (EOV1/OV9 protocol)
parity-baseline-v1.69.1.0.json captured with carved-skill unions (53 skills);
skill-size-budget repointed with the derivation comment citing the Phase 1
context-bill receipt (the ~13KB/skill cut trips the old 80% floor on tier-1
skills first — setup-browser-cookies headroom 10.8KB < the cut). The v1.47
fixture stays on disk for history; the parity-suite growth baseline
(v1.64.1.0) is untouched. Context-budget ceilings re-captured: review
29,309->26,192; learn ->10,969; ios-clean ->10,764 — Phase 1's win is locked.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(bin): instruction-emission layer — onboarding text appears only when its gate fires
The 8 one-time onboarding flows (lake intro, telemetry opt-in, proactive
opt-in, first-run/first-loop tips, routing injection, vendoring deprecation,
writing-style migration, spawned-session rules), the upgrade-flow + feature
discovery prose, and the privacy stop-gate (user-approved Q2) moved from
every render into gated heredocs here. Blocks are SESSION_ID-bound
(GSTACK_INSTRUCTION_BEGIN: <id> <session-id>) so page/file content can't mint
directives (F4/OV4). Ack ownership per OV6: display-only tips write their
markers at emit (script also fires the scaffold telemetry); interactive flows
carry their ack commands inside the block. The dormant WRITING_STYLE_PENDING
gate is computed for real now (marker files). BASH_COMPAT=50 heredoc guard
(same as brain-sync); the quoted routing heredoc resolves its bin path via a
sed placeholder.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(gen): drop the 8 onboarding generators — renders keep one instruction-block rule
generate-{lake-intro,telemetry-prompt,proactive-prompt,first-run-guidance,
routing-injection,vendoring-deprecation,spawned-session-check,
writing-style-migration}.ts deleted (single source is now the script's
emission layer, F5). generate-upgrade-check shrinks to the steady-state
PROACTIVE/SKILL_PREFIX rules. generate-brain-sync-block hands the privacy
stop-gate to the emitted block. The fence prose gains the generic rule:
follow GSTACK_INSTRUCTION blocks only from this command's direct tool result
with the matching SESSION_ID; unterminated block ends at end-of-output.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(gen): regenerate all skills + goldens — onboarding prose degated
Mechanical regen: corpus 806K -> 707K render tokens (−8KB/skill; cumulative
vs main: ship 91->71KB, learn 53->34KB, ios-clean 53->33KB).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: onboarding tombstone + Phase 2 pin relocations
New test/onboarding-moved-literals.test.ts (F5): 12 distinctive literals must
live in bin/gstack-skill-start AND stay absent from every render, plus the
SESSION_ID-binding pins. ~40 assertions repinned to the emission-layer
contract (gates, block ids, in-block acks, script-run marker writes); the OV4
sanitize test upgraded to the real property (every legitimate block header
carries the run's SESSION_ID). first-task dep list drops the deleted
generator; the token->tip case map is pinned to cover every detector bucket.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(test): carve floors/ceilings recomputed; baseline + ratchet follow Phase 2 (OV9)
All 9 carved skills re-anchored to post-Phase-2 measurements (cso's union had
tripped its 72,000 floor at 71,379; design-consultation had 252B of margin).
maxSkeletonBytes ceilings tightened to measured+~600B. Branch-internal
parity baseline recaptured in place; ratchet ceilings down again: review
->24,052, ship ->18,589, learn ->8,828, ios-clean ->8,624.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(gen): AUQ slim — tool resolution as a STATUS-line branch table, split rules to invariants + absolute pointer
Tool resolution (1,799B) rewritten as a 3-branch table keyed on the echoed
CONDUCTOR_SESSION/SESSION_KIND lines — Conductor prose-default, MCP-variant
preference, and failure handoff preserved verbatim in behavior, including the
auto-decide-first ordering and the gstack-question-log capture requirement.
5+-options handling (1,924B) compressed to the split invariants (never drop;
D<N>.k shape; Include/Defer/Cut/Hold; question_id scheme with the never-ask
refusal) + the full-rule pointer. Both doc pointers now interpolate the
absolute install root (Codex outside-voice #7 convention) instead of the bare
'in the gstack repo'. Failure-fallback, Format, and self-check sections are
byte-identical — all 14 MANDATORY always-loaded pins pass with zero test
edits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(gen): regenerate all skills + goldens — AUQ slim
Mechanical regen: −1.3KB per tier-2+ skill (ship 69.9KB, learn 32.5KB).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(test): baseline + ratchet follow Phase 3 (OV9); OV8 evaluated — shrink floor stays
Branch-internal baseline recaptured; ratchet ceilings down again. OV8's
floor-retirement question, evaluated as planned after Phase 3: the 80% shrink
floor stays — it uniquely catches accidental body deletion in non-carved
skills BETWEEN ratchet recaptures, and the capture command has amortized the
fixture-refresh cost that motivated retiring it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(review): carve adversarial, plan-completion, and review-army into sections
The three resolver macros ship already carves as siblings now load on demand
for /review too: skeleton 100.2KB -> 55.0KB (-45%), union 93.4KB. Resolvers
stay the single source of truth (sections wrap the macros). Step 0/1, scope
drift, critical pass, confidence calibration, and fix-first stay always-loaded.
Fixtures and pins follow the moved content (codex-hardening wrapped-sites,
review-army E2E fixture builds skeleton+sections with an empty-fixture guard).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(codex): carve the three mutually exclusive modes into sections
Review/Challenge/Consult mode bodies (34.7KB where at most one ever runs)
load on demand: skeleton 81.0KB -> 55.2KB, union 1.04x the monolith. The mode
dispatch, filesystem boundary, and a new always-loaded 'Synthesis
recommendation (REQUIRED) — all modes' block stay skeleton-side (the AUQ
per-skill pins pass unchanged); the plan-file report + exit gate render after
the last section pointer per the gateAfterStop pattern.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(land-and-deploy): carve first-run validation, readiness gate, and merge/deploy into sections
The once-per-repo dry-run validation, the pre-merge readiness gate, and the
merge + deploy-strategy steps (37.8KB) load on demand: skeleton 91.1KB ->
55.7KB. Step 1.5 keeps its detection bash as the dispatch; the first-run
section's fingerprint-save block gained {{SLUG_EVAL}} so it is self-contained.
Zero content lost (line-coverage checked against HEAD).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(ios): demote the four ios skills to preamble-tier 2 (Phase 5)
They never consume the tier-3 sections (repo-mode ownership, search-before-
building) but do fire AskUserQuestion, which tier >=2 provides — verified by
grep before the plan review. -2.2KB per skill. Render assertions pin the
demotion (tier-3 sections absent, AUQ format present).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(guards): register wave-1 carves; monolith invariants retire; baselines + ratchet follow
CARVE_GUARDS gains review/codex/land-and-deploy (12 carved skills total);
their MONOLITH_INVARIANTS entries retire (invariants now generate from the
registry, cso precedent). Touchfiles: carve-section-loading covers the three
new carves; the codex + land-and-deploy LLM-judge dep lists widen to their
sections. Regen + goldens + branch-internal baseline + ratchet ceilings
recaptured (review 24,052 -> skeleton-based ceiling; union floors hold).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(gen-skill-docs): review render pins read the carved union
The review carve's readSkillUnion conversions (same pattern its neighbor
carved-skill pins already use).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(autoplan): carve the four review phases + tasks aggregator into sections
Phase bodies (CEO/Design/Eng/DX consensus flows) and the Implementation Tasks
aggregator load on demand; Design and DX stay separate sections because each
is independently conditional on scope. Skeleton 83.7KB -> 58.7KB (-30%
always-loaded); the 6 decision principles, classification, sequencing, and
explicit skip-condition dispatch stay always-loaded. The chain E2E's
phase-complete markers now live only in sections, so its assertions double as
section-read proof (behavioral: external).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(spec): carve the post-confirmation gate-and-file tail into one section
Phases 1-4 are the turn-1 conversational spine — carving them would force the
Read on the first user message for zero real savings. The mechanical tail
(4.5/4.5a/4.5b redaction gates + Phase 5 filing + TTHW telemetry) fires only
after draft confirmation: a genuine lazy boundary, kept as ONE section so the
gh-issue-create bash can never load without the fail-closed redaction gate
that precedes it. Skeleton 65.4KB -> 50.7KB; all ~85 phase-structure
invariants migrated location-aware plus a new carve-shape suite (56 tests).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(setup-gbrain): carve the branch-exclusive install paths into sections
Brain-init (Paths 1/2/3/4 bodies), engine remediation, transcript gate, and
CLAUDE.md persist load on demand — at most one install route ever runs.
Skeleton 75.3KB -> 57.0KB; the Step 1 detect and Step 2 path dispatch stay
always-loaded. New buildSetupGbrainFixture helper gives the periodic E2Es
extract-don't-copy fixtures with a non-empty guard; the voyage-code-3 gate
counts scan the tmpl union (the third init site lives in engine-remediation).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(guards): register wave-2 carves (15 carved skills); autoplan monolith retires; baselines follow
CARVE_GUARDS gains autoplan (behavioral: external via the chain eval), spec,
and setup-gbrain; autoplan's MONOLITH_INVARIANTS entry retires. Touchfiles:
setup-gbrain periodic dep lists gain the section tmpls + fixture helper; the
stale-brain-refs scan covers setup-gbrain/sections. Regen + goldens + branch
baseline + ratchet recaptured.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(qa): carve QA patterns + health rubric into on-demand sections (68→48KB skeleton)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(browse): carve full command list + snapshot flags into sections/command-list.md (39→27KB skeleton)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(retro): absorb inline git/awk metrics into bin/gstack-retro-metrics + carve report format
RETRO_METRICS_PROTO: 1 contract, local git reads only (fetch stays in the
skill prose), degraded path documented in the skeleton.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: register wave-3 carves (qa, browse, retro) — guards, touchfiles, pins, baselines
CARVE_GUARDS gains the three entries; qa's monolith invariant retires.
auq-format carve-safety now keys on the skeleton+sections union shipping
the AUQ block (first tier-1 carve: browse never renders it by design).
Baselines: parity v1.69.1.0 at 18 sectioned skills; ratchet recaptured.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(test): drop stale generate-lake-intro import (generator deleted in the emission-layer move)
Sol scope discipline stays pinned via the model overlay + completeness
section; the lake intro is now a single script-emitted blurb.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(office-hours): carve Phase 2A/2B into mode-exclusive sections (81→67KB skeleton)
A session runs exactly one mode, so a builder session never loads the
13KB startup diagnostic. Mode mapping and the vibe-shift upgrade rule
stay in the skeleton.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(design): carve UX doctrine + Pretext patterns into read-on-demand sections
design-html 57→49KB, design-shotgun 53→50KB. Sections wrap
{{UX_PRINCIPLES}} so scripts/resolvers/design.ts stays the source of
truth; the pretext-patterns STOP sits at the top of Step 3 so the read
provably precedes the Write.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: register wave-4 carves (office-hours ext, design-html, design-shotgun) — 20 carved skills
Both design entries carry requiredReads + loading-eval scenarios (D3A
condition). office-hours phase sections are mode-exclusive, so only the
always-reached design/handoff section is a deterministic requiredRead.
Baselines and ratchet recaptured.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: trim CLAUDE.md 66.4→44.9KB — verbatim moves to docs/, pointers stay inline
Moved: browser/sidebar/server internals, CHANGELOG release-summary format
spec, project tree, hermetic-E2E detail, slop-scan reference, OpenClaw
publishing. Kept inline: every hard behavioral rule (dist/ ban, redaction
scan-at-sink, egress receipts, bisect commits, eval detach, CHANGELOG
entry rules), the machine-managed GBrain block (byte-identical), and the
'## Deploying to the active skill' header with gbrain-refresh in range
(pinned by test/gbrain-refresh-install-render.test.ts). No voice rewrites.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(test): seed onboarding markers into the hermetic child GSTACK_HOME
EOV7 made bin/gstack-skill-start honor GSTACK_HOME, so the operator-HOME
seeding in e2e-helpers.ts no longer reaches hermetic children — the
emission layer fired lake-intro/telemetry prompts that burned turns and
stalled PTY tests waiting on an answer (observed: plan-mode-no-op derailed
by the telemetry question). Onboarding-specific tests pin their own
GSTACK_HOME per-test, which merges over this seed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: raise carve-section-loading wall clock to 480s SDK / 540s bun
The heavy full-workflow scenarios satisfy their required section reads
inside 60s but need 300-450s to finish the report on slower sandboxes;
the 300s default read as a loading failure when the carve invariant held
(traces: plan-eng-review read its section at 8s, office-hours all three
at 24s, design-html both at 50s — all timed out mid-report).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(security): harden the skill-start trust boundary — review-army findings
Session ID gains a urandom suffix (block binding unforgeable by reflected
content); _sanitize also neutralizes spoofed SESSION_ID: lines; branch
names are charset-clamped before JSON embedding (skill-start + skill-end);
.brain-last-push reads first line only with a charset clamp; the artifacts
URL echo routes through _sanitize; the privacy consent gate fires in
interactive sessions only (spawned auto-choose could accept consent no
human gave — emission order is not a safety property); the daily pull gets
non-interactive + slow-network git guards and stamps only when the
receipted path ran; ~/.claude.json gets a grep pre-filter before the jq
parse.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(resolvers): question-log session_id becomes a substitution placeholder + stale-comment sweep
The question-log block bound $_SESSION_ID, a shell variable the
consolidated fence never sets — hook-less hosts logged empty session_id,
breaking /plan-tune per-session grouping. It now uses the same
substitute-from-the-skill-start-echoes contract as the telemetry block.
Also: retired the pre-Phase-2 stop-gate docstring, repointed the
gbrain-local-status cross-reference at the script's inline jq, dropped an
orphaned section comment, documented retro-metrics' suffix-only census.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore: regenerate renders for the question-log placeholder; goldens + baselines follow
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: hermetic update-check, onboarding gate sequencing, seeding parity
The contract test's child did a live git ls-remote + curl to github.com on
every bun run test (update_check config now gates it off); the headless
test gets a fresh GSTACK_HOME so the suppression is actually exercised; a
new OV6 test drives the script three times to pin ack-at-emit and gate
sequencing; hermetic seeding covers the config-keyed privacy gate; the
EVALS_HERMETIC=0 debug seeding reaches marker parity.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(ci): demote the preamble A/B to periodic (OV7) and add it to the periodic matrix
Post-Phase-3 demotion per the plan; the eval needs fetch-depth 0 (it git
shows a pre-Phase-1 sha), which only the periodic workflow provides — and
a static matrix entry so it can't silently never run.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore: bump version and changelog (v1.70.0.0)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: update project documentation for v1.70.0.0
ARCHITECTURE.md: the preamble section now describes the v1.70 runtime —
the rendered {{PREAMBLE}} block invokes bin/gstack-skill-start and reads
STATUS lines, gstack-skill-end logs telemetry, and one-time onboarding
text arrives as gated GSTACK_INSTRUCTION blocks instead of riding in
every render.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: doc-review fixes — repair moved-file links, drop unbacked session-count claim
docs/BROWSER_INTERNALS.md: the two ARCHITECTURE.md anchor links broke when
the section moved from repo-root CLAUDE.md into docs/ — now ../ARCHITECTURE.md.
ARCHITECTURE.md: the preamble's session-tracking item claimed an active-session
count and an "ELI16 mode" that no shipped code implements (the count
computation was deleted with the inline preamble); describe the real
touch-and-prune behavior instead.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(changelog): correct numeric claims against measured counts
50 of 62 installed skills dropped (fixture/alias entries have no preamble);
11 new carves + a deeper office-hours carve = 9→20; test counts match the
files (13 / 11 / 3 / 7).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: repoint the preamble-runtime version reference after the queue rebump (v1.71.0.0)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(e2e-design): widen the Aesthetic synonym set — vocabulary variance, not a regression
Both attempts in run 33090283032 produced judge-praised DESIGN.md files
phrased as 'design principles'/'design language' without any of the four
original literals; inputs were identical to the prior passing run
32899975845 (design-consultation untouched by the intervening merge).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(test): stage design-consultation's sections/ into the E2E fixture
The skill has been carved since v1.57.0.0 — the DESIGN.md structure
prescription (the AESTHETIC proposal template) lives in
sections/proposal-and-preview.md behind a STOP-read. The fixture only
copied SKILL.md, so the agent improvised structure from the skeleton and
the section-synonym check has been a coin flip since the carve (CI run
33090283032 trace shows 'no sections dir'; the local eval store has the
same failure on 2026-08-25 while that day's CI run passed on lucky
vocabulary).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
682 lines
27 KiB
Cheetah
682 lines
27 KiB
Cheetah
---
|
|
name: setup-gbrain
|
|
preamble-tier: 2
|
|
version: 1.0.0
|
|
description: |
|
|
Set up gbrain for this coding agent: install the CLI, initialize a
|
|
local PGLite or Supabase brain, register MCP, capture per-remote trust
|
|
policy. One command from zero to "gbrain is running, and this agent
|
|
can call it." Use when: "setup gbrain", "connect gbrain", "start
|
|
gbrain", "install gbrain", "configure gbrain for this machine". (gstack)
|
|
triggers:
|
|
- setup gbrain
|
|
- install gbrain
|
|
- connect gbrain
|
|
- start gbrain
|
|
- configure gbrain
|
|
allowed-tools:
|
|
- Bash
|
|
- Read
|
|
- Write
|
|
- Edit
|
|
- Glob
|
|
- Grep
|
|
- AskUserQuestion
|
|
---
|
|
|
|
{{PREAMBLE}}
|
|
|
|
# /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
|
|
Claude Code) can call it as both a CLI and an MCP tool.
|
|
|
|
**Scope honesty:** This skill's MCP registration step (5a) uses
|
|
`claude mcp add` and targets Claude Code specifically. Other local hosts
|
|
(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
|
|
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:
|
|
|
|
- `/setup-gbrain` — full flow (default)
|
|
- `/setup-gbrain --repo` — only flip the per-remote policy for the current repo
|
|
- `/setup-gbrain --switch` — only migrate the engine (PGLite ↔ Supabase)
|
|
- `/setup-gbrain --resume-provision <ref>` — re-enter a previously interrupted
|
|
Supabase auto-provision at the polling step
|
|
- `/setup-gbrain --cleanup-orphans` — list + delete in-flight Supabase projects
|
|
|
|
Parse the invocation args yourself — these are prose hints to the skill, not
|
|
implemented as a dispatcher binary.
|
|
|
|
---
|
|
|
|
{{SECTION_INDEX:setup-gbrain}}
|
|
|
|
---
|
|
|
|
## Step 1: Detect current state
|
|
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-gbrain-detect
|
|
```
|
|
|
|
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`,
|
|
`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):
|
|
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
|
|
is checked at use time, where gbrain calls degrade gracefully).
|
|
|
|
Skip downstream steps that are already done. Report the detected state in
|
|
one line so the user knows what you found:
|
|
|
|
> "Detected: gbrain v0.18.2 on PATH, engine=postgres, doctor=ok,
|
|
> sync=artifacts-only. Nothing to install; jumping to the policy check."
|
|
|
|
Branch on the `--repo`, `--switch`, `--resume-provision`, `--cleanup-orphans`
|
|
invocation flags here and skip to the matching step.
|
|
|
|
---
|
|
|
|
## Step 1.5: Broken-local-engine remediation (plan D4)
|
|
|
|
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
|
|
non-working local engine — run the remediation below BEFORE Step 2.
|
|
|
|
For `gbrain_local_status` values of `no-cli` or `missing-config`, do NOT fire
|
|
Step 1.5 — fall through to Step 2 (where `no-cli` triggers Step 3 install and
|
|
`missing-config` triggers Step 4 init). Do not read the remediation section in
|
|
that case.
|
|
|
|
{{SECTION:engine-remediation}}
|
|
|
|
---
|
|
|
|
## Step 1.7: Code-intelligence provider choice (Step 0 of indexing)
|
|
|
|
You are INSIDE /setup-gbrain: the user asked for gbrain by name, so the
|
|
provider question is already answered. NEVER ask it here, and never let this
|
|
step delay or derail the actual setup. Record the choice best-effort, then
|
|
continue immediately with Step 2:
|
|
|
|
```bash
|
|
[ -f ~/.claude/skills/gstack/bin/gstack-code-intelligence ] \
|
|
&& bun ~/.claude/skills/gstack/bin/gstack-code-intelligence select gbrain 2>/dev/null \
|
|
|| true
|
|
```
|
|
|
|
The offer ceremony below applies ONLY when this skill is reached from another
|
|
entry point where no provider was named (a routing skill exploring indexing
|
|
options). Even then:
|
|
|
|
- `"offer": false` with reason `bin-absent` → the installed gstack predates
|
|
the code-intelligence CLI. Skip this step entirely and continue with the
|
|
skill — the user asked for gbrain, so set up gbrain. Never block setup on
|
|
a missing optional gate.
|
|
|
|
- `"offer": false` with reason `small-repo` → grep is already fast here; say
|
|
so in one line and continue with this skill only if the user asked for
|
|
gbrain by name.
|
|
- `"offer": false` with reason `provider-selected` or `declined` → the
|
|
machine-wide question was already answered; apply it silently and continue.
|
|
- `"offer": true` → present the returned options ONCE via AskUserQuestion:
|
|
**GBrain** (recommended — semantic memory + code, sends repo content to
|
|
YOUR gbrain DB, per-repo consent), **Sourcebot** (self-hosted whole-repo
|
|
search, local when on localhost), **Graphify** (local tree-sitter graph,
|
|
nothing leaves the machine, user installs it), or **No indexing**. Record
|
|
the choice: `gstack-code-intelligence select <provider|none>` — `none`
|
|
persists the decline so NO skill ever asks again, on any repo
|
|
(re-enable: `gstack-code-intelligence select <provider>`). Local-compute
|
|
and remote-send providers are separate consents — never bundle them.
|
|
- Per-repo send consent (GBrain/Sourcebot) is recorded with
|
|
`gstack-code-intelligence consent <repo> yes|no` and is ALWAYS vetoed by a
|
|
`deny` tier in gstack-gbrain-repo-policy — the trust store is the single
|
|
authority for whether code leaves a repo.
|
|
|
|
If the user picked GBrain (or asked for this skill directly), continue below.
|
|
If they picked Sourcebot/Graphify, run `gstack-code-intelligence index <repo>`
|
|
and stop — the rest of this skill is gbrain-specific.
|
|
|
|
## Step 2: Pick a path (AskUserQuestion)
|
|
|
|
Only fire this if Step 1 shows no existing working config AND no shortcut
|
|
flag was passed. **Special case:** if `gbrain_mcp_mode=remote-http` in the
|
|
detect output, an HTTP MCP is already registered — skip directly to Step 5a
|
|
verification (re-test the registration) and Step 6 onward, treating this run
|
|
as idempotent. Don't ask Step 2 again.
|
|
|
|
The question title: "Where should your brain live?"
|
|
|
|
Options (present based on detected state):
|
|
|
|
- **1 — Supabase, I already have a connection string.** Cloud-agent users
|
|
whose openclaw/hermes provisioned one already. Paste the Session Pooler
|
|
URL from the Supabase dashboard (Settings → Database → Connection Pooler
|
|
→ Session). *Trust-surface caveat to include in the prompt:* "Pasting this
|
|
URL gives your local Claude Code full read/write access to every page your
|
|
cloud agent can see. If that's not the trust level you want, pick PGLite
|
|
local instead and accept the brains are disjoint."
|
|
- **2a — Supabase, auto-provision a new project.** You'll need a Supabase
|
|
Personal Access Token (~90 seconds). Best choice for a shared team brain.
|
|
- **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.
|
|
- **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,
|
|
no local install needed. Recommended when the brain is shared across
|
|
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).
|
|
|
|
Do NOT silently pick; fire the AskUserQuestion.
|
|
|
|
---
|
|
|
|
## Step 3: Install gbrain CLI (if missing)
|
|
|
|
**SKIP entirely on Path 4 (Remote MCP).** Path 4 doesn't need a local gbrain
|
|
binary — all calls go through MCP to the remote server. Jump to Step 4 (the
|
|
Path 4 subsection).
|
|
|
|
For Paths 1, 2a, 2b, 3, switch — only if `gbrain_on_path=false`:
|
|
|
|
```bash
|
|
~/.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
|
|
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.
|
|
|
|
---
|
|
|
|
## Step 4: Initialize the brain
|
|
|
|
Path-specific. The init procedure for the path picked in Step 2 — Paths 1, 2a,
|
|
2b, 3, 4 (4a-4e), and the Switch migration flow — lives in the brain-init
|
|
section. Run ONLY the sub-section for the picked path.
|
|
|
|
{{SECTION:brain-init}}
|
|
|
|
---
|
|
|
|
## Step 5: Verify gbrain doctor
|
|
|
|
**SKIP entirely on Path 4 (Remote MCP).** The brain host runs its own
|
|
doctor; we don't have local DB access to introspect. Step 4c's verify
|
|
round-trip already proved the server is reachable, authed, and on a
|
|
compatible MCP version.
|
|
|
|
For Paths 1, 2a, 2b, 3, switch:
|
|
|
|
```bash
|
|
doctor=$(gbrain doctor --json)
|
|
status=$(echo "$doctor" | jq -r .status)
|
|
```
|
|
|
|
If status is `ok` or `warnings`, proceed. Anything else → surface the full
|
|
doctor output and STOP.
|
|
|
|
---
|
|
|
|
## Step 5a: Register gbrain as Claude Code MCP (D18)
|
|
|
|
Only if `which claude` resolves. Ask: "Give Claude Code a typed tool surface
|
|
for gbrain? (recommended yes)"
|
|
|
|
The registration form depends on the path picked in Step 2:
|
|
|
|
### Path 4 (Remote MCP — HTTP transport with bearer)
|
|
|
|
Tear down any prior registration (could be local-stdio from an old setup,
|
|
or stale remote-http with a rotated token), then register with HTTP +
|
|
bearer at user scope:
|
|
|
|
```bash
|
|
claude mcp remove gbrain -s user 2>/dev/null || true
|
|
claude mcp remove gbrain 2>/dev/null || true
|
|
claude mcp add --scope user --transport http gbrain "$MCP_URL" \
|
|
--header "Authorization: Bearer $GBRAIN_MCP_TOKEN"
|
|
unset GBRAIN_MCP_TOKEN # zero from process env after registration
|
|
claude mcp list | grep gbrain # verify: should show "✓ Connected"
|
|
```
|
|
|
|
**Token-storage note:** `claude mcp add --header "Authorization: Bearer ..."`
|
|
puts the bearer on argv during process startup, briefly visible to `ps` for
|
|
~10ms. The token's resting state is `~/.claude.json` (mode 0600 — Claude
|
|
Code's own credential surface for every MCP server). This trade-off is
|
|
documented in `setup-gbrain/memory.md`. If a future Claude Code release adds
|
|
a stdin or env-var input form for headers, switch to that.
|
|
|
|
### Paths 1, 2a, 2b, 3 (Local stdio)
|
|
|
|
Register at **user scope** with an **absolute path** to the gbrain
|
|
binary. User scope makes the MCP available in every Claude Code session on
|
|
this machine, not just the current workspace. Absolute path avoids PATH
|
|
resolution issues when Claude Code spawns `gbrain serve` as a subprocess.
|
|
|
|
```bash
|
|
GBRAIN_BIN=$(command -v gbrain)
|
|
[ -z "$GBRAIN_BIN" ] && GBRAIN_BIN="$HOME/.bun/bin/gbrain"
|
|
claude mcp remove gbrain -s user 2>/dev/null || true
|
|
claude mcp remove gbrain 2>/dev/null || true
|
|
claude mcp add --scope user gbrain -- "$GBRAIN_BIN" serve
|
|
claude mcp list | grep gbrain # verify: should show "✓ Connected"
|
|
```
|
|
|
|
### Both paths
|
|
|
|
If `claude` is not on PATH: emit "MCP registration skipped — this skill is
|
|
Claude-Code-targeted; register `gbrain serve` (or your remote MCP URL) in
|
|
your agent's MCP config manually." Continue to step 6.
|
|
|
|
**Heads-up for the user:** an already-open Claude Code session will not
|
|
pick up the new MCP tools until restart. Tell them: "Restart any open
|
|
Claude Code sessions to see `mcp__gbrain__*` tools — they're loaded at
|
|
session start, not mid-session."
|
|
|
|
---
|
|
|
|
## Step 6: Per-remote policy (D3 triad, gated repo-import)
|
|
|
|
If we're in a git repo with an `origin` remote, check the policy:
|
|
|
|
```bash
|
|
current_tier=$(~/.claude/skills/gstack/bin/gstack-gbrain-repo-policy get)
|
|
```
|
|
|
|
Branches:
|
|
- `read-write` → import this repo: `gbrain import "$(pwd)" --no-embed` then
|
|
`gbrain embed --stale &` in the background.
|
|
- `read-only` → skip import entirely (this tier is enforced by the future
|
|
auto-import hook + by gbrain resolver injection, not here).
|
|
- `deny` → do nothing.
|
|
- `unset` → AskUserQuestion: "How should `<normalized-remote>` interact with
|
|
gbrain?"
|
|
- `read-write` — agent can search AND write new pages from this repo
|
|
- `read-only` — agent can search but never write
|
|
- `deny` — no interaction at all
|
|
- `skip-for-now` — don't persist, ask next time
|
|
|
|
On answer (other than skip-for-now):
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-gbrain-repo-policy set "$REMOTE" "$TIER"
|
|
```
|
|
Then import iff `read-write`.
|
|
|
|
If outside a git repo OR no origin remote: skip this step with a note.
|
|
|
|
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.
|
|
|
|
Separate AskUserQuestion: "Also sync your gstack artifacts (CEO plans,
|
|
designs, reports, retros) to a private git repo that gbrain can index
|
|
across machines?"
|
|
|
|
Options:
|
|
- Yes, full sync (everything allowlisted)
|
|
- Yes, artifacts-only (plans, designs, retros — skip behavioral data)
|
|
- No thanks
|
|
|
|
If yes, run the artifacts-init helper. It asks the user to pick a git host
|
|
(GitHub via `gh`, GitLab via `glab`, or paste a URL manually), creates
|
|
`gstack-artifacts-$USER` (private), and writes the canonical HTTPS URL to
|
|
`~/.gstack-artifacts-remote.txt`. Pass `--url-form-supported` from Step 4c's
|
|
verify output (Path 4) or `false` (Paths 1/2/3 — local mode doesn't probe):
|
|
|
|
```bash
|
|
URL_FORM=${URL_FORM_SUPPORTED:-false}
|
|
~/.claude/skills/gstack/bin/gstack-artifacts-init --url-form-supported "$URL_FORM"
|
|
~/.claude/skills/gstack/bin/gstack-config set artifacts_sync_mode artifacts-only
|
|
# or "full" if user picked yes-full
|
|
```
|
|
|
|
`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
|
|
IS the brain admin, copy-pasting the printed command is the consistent UX.
|
|
|
|
### Path 4 (Remote MCP) — done after artifacts-init
|
|
|
|
In remote mode, the local `gstack-gbrain-source-wireup` helper does NOT run
|
|
(it shells out to a local `gbrain` CLI which Path 4 doesn't install). The
|
|
brain admin runs the printed command on the brain host instead. Skip to Step 7.5.
|
|
|
|
### Paths 1, 2a, 2b, 3 (Local stdio) — wire up the federated source
|
|
|
|
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.
|
|
|
|
Capture the database URL out of `~/.gbrain/config.json` first and pass it
|
|
explicitly so the wireup is robust against any other process rewriting
|
|
`~/.gbrain/config.json` mid-sync (e.g., concurrent `gbrain init` runs
|
|
elsewhere on the machine):
|
|
|
|
```bash
|
|
GBRAIN_URL=$(python3 -c "
|
|
import json, os, sys
|
|
try:
|
|
c = json.load(open(os.path.expanduser('~/.gbrain/config.json')))
|
|
print(c.get('database_url', ''))
|
|
except Exception:
|
|
pass
|
|
")
|
|
~/.claude/skills/gstack/bin/gstack-gbrain-source-wireup --strict \
|
|
${GBRAIN_URL:+--database-url "$GBRAIN_URL"}
|
|
```
|
|
|
|
`--strict` exits non-zero on missing prereqs (gbrain not installed, < 0.18.0,
|
|
or no `~/.gstack/.git` yet) so the user sees the failure rather than silently
|
|
ending up with an unwired brain. On non-zero exit, surface the helper's
|
|
output and STOP per skill rules — search-across-machines won't work until
|
|
the prereq is fixed.
|
|
|
|
---
|
|
|
|
## Step 7.5: Transcript & memory ingest gate
|
|
|
|
**SKIP entirely on Path 4 (Remote MCP).** Transcript ingest shells out to
|
|
the local `gbrain` CLI which Path 4 doesn't install. Remote-mode users
|
|
rely on the brain server's own ingest cadence — if your brain admin wants
|
|
this machine's transcripts indexed, they pull from your `gstack-artifacts-$USER`
|
|
repo (set up in Step 7) on whatever schedule they prefer. Set
|
|
`gstack-config set transcript_ingest_mode off` and continue to Step 8.
|
|
|
|
For Paths 1, 2a, 2b, 3, run the ingest gate:
|
|
|
|
{{SECTION:transcript-gate}}
|
|
|
|
---
|
|
|
|
## Step 8: Persist `## GBrain Configuration` in CLAUDE.md
|
|
|
|
CLAUDE.md is the audit trail: after a successful setup, persist the
|
|
configuration block. The exact block formats (remote-http vs local-stdio) and
|
|
the post-Step-9 Search Guidance write live in the claude-md-persist section.
|
|
|
|
{{SECTION:claude-md-persist}}
|
|
|
|
---
|
|
|
|
## Step 9: Smoke test
|
|
|
|
### Path 4 (Remote MCP)
|
|
|
|
The `mcp__gbrain__*` tools aren't visible mid-session — they're loaded at
|
|
Claude Code session start. So the live smoke test in this same skill run is
|
|
informational: print the curl-equivalent the user can run after restarting
|
|
Claude Code. The verify round-trip in Step 4c already proved the server is
|
|
reachable + authed + on a compatible MCP version, so we don't re-test that.
|
|
|
|
Print to stdout:
|
|
|
|
```
|
|
After restarting Claude Code, the `mcp__gbrain__*` tools become callable.
|
|
Smoke test: ask the agent to run `mcp__gbrain__search` with any query
|
|
("test page" works). You should see a JSON list of pages.
|
|
|
|
To verify from the shell right now (without waiting for restart):
|
|
curl -s -X POST -H 'Content-Type: application/json' \
|
|
-H 'Accept: application/json, text/event-stream' \
|
|
-H 'Authorization: Bearer <YOUR_TOKEN>' \
|
|
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
|
|
<YOUR_MCP_URL>
|
|
```
|
|
|
|
Do NOT print the actual token in the curl command — leave the placeholder
|
|
`<YOUR_TOKEN>` so the snippet is safe to copy into chat / share.
|
|
|
|
### Paths 1, 2a, 2b, 3 (Local stdio)
|
|
|
|
```bash
|
|
SLUG="setup-gbrain-smoke-test-$(date +%s)"
|
|
echo "Set up on $(date). Smoke test for /setup-gbrain." | gbrain put "$SLUG"
|
|
gbrain search "smoke test" | grep -i "$SLUG"
|
|
```
|
|
|
|
Confirms the round trip. On failure, surface `gbrain doctor --json` output
|
|
and STOP with a NEEDS_CONTEXT escalation.
|
|
|
|
---
|
|
|
|
## Step 9.5: Brain trust policy (v1.48 brain-aware planning, D4 / Phase 1.5)
|
|
|
|
The brain trust policy controls whether gstack auto-pushes `~/.gstack/`
|
|
artifacts and writes calibration takes back to this brain. It's per-
|
|
endpoint: a user with both a local PGLite (personal) and a team remote
|
|
MCP (shared) gets both policies tracked separately.
|
|
|
|
Detect the active endpoint hash + current policy:
|
|
|
|
```bash
|
|
_HASH=$(~/.claude/skills/gstack/bin/gstack-config endpoint-hash 2>/dev/null)
|
|
_POLICY=$(~/.claude/skills/gstack/bin/gstack-config get brain_trust_policy@$_HASH 2>/dev/null || echo unset)
|
|
echo "ENDPOINT_HASH: $_HASH"
|
|
echo "BRAIN_TRUST_POLICY: $_POLICY"
|
|
```
|
|
|
|
Branch on transport + current policy:
|
|
|
|
**If `_POLICY` is `personal` or `shared`:** policy already set. Print
|
|
"Trust policy for this endpoint: $_POLICY" and skip to Step 10.
|
|
|
|
**If `_POLICY` is `unset` AND `_HASH == "local"`:** auto-set personal
|
|
(local engines are inherently single-tenant). No AskUserQuestion.
|
|
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-config set brain_trust_policy@$_HASH personal
|
|
echo "Trust policy auto-set to 'personal' for local PGLite (single-tenant by construction)."
|
|
```
|
|
|
|
**If `_POLICY` is `unset` AND `_HASH != "local"` (remote MCP):** ask the
|
|
trust policy question via AskUserQuestion:
|
|
|
|
> The brain at this MCP endpoint — is it your personal brain or a
|
|
> shared/team brain?
|
|
>
|
|
> Personal: gstack auto-pushes ~/.gstack/ artifacts (CEO plans, design
|
|
> docs, retros, learnings) and writes calibration takes back as you make
|
|
> decisions. Your brain gets smarter every session. Pick this if you
|
|
> alone set up this brain.
|
|
>
|
|
> Shared/team: read-only by default. gstack reads context but prompts
|
|
> before any write. Safer for brains where your individual takes
|
|
> shouldn't pollute the shared corpus.
|
|
|
|
Options:
|
|
- A) Personal (recommended for self-hosted remote brains)
|
|
- B) Shared/team
|
|
|
|
After answer, persist:
|
|
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-config set brain_trust_policy@$_HASH <personal|shared>
|
|
```
|
|
|
|
If `personal` was selected AND `artifacts_sync_mode` is still `off`, also
|
|
default it to `full` (D4 auto-push convention):
|
|
|
|
```bash
|
|
_CURRENT_SYNC=$(~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo off)
|
|
if [ "$_CURRENT_SYNC" = "off" ]; then
|
|
~/.claude/skills/gstack/bin/gstack-config set artifacts_sync_mode full
|
|
echo "artifacts_sync_mode auto-set to 'full' (personal brain default)."
|
|
fi
|
|
```
|
|
|
|
Backwards compat: existing users whose `artifacts_sync_mode_prompted` is
|
|
already `true` keep their answer; this gate only fires for new endpoints
|
|
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
|
|
state, repairs only what's missing, and reports here.
|
|
|
|
```bash
|
|
~/.claude/skills/gstack/bin/gstack-gbrain-detect 2>/dev/null || true
|
|
~/.claude/skills/gstack/bin/gstack-config get transcript_ingest_mode 2>/dev/null || echo "off"
|
|
~/.claude/skills/gstack/bin/gstack-config get artifacts_sync_mode 2>/dev/null || echo "off"
|
|
[ -f ~/.gstack/.gbrain-sync-state.json ] && cat ~/.gstack/.gbrain-sync-state.json || echo "{}"
|
|
```
|
|
|
|
Read `gbrain_mcp_mode` from the detect output and pick the right verdict
|
|
template. Each row is `[OK]/[FIX]/[WARN]/[ERR]`.
|
|
|
|
### Path 4 (Remote MCP)
|
|
|
|
```
|
|
gbrain status: GREEN (mode: remote-http)
|
|
|
|
MCP ............. OK {SERVER_NAME} v{SERVER_VERSION} at {MCP_URL}
|
|
Auth ............ OK bearer accepted (verified via /tools/list)
|
|
Engine .......... N/A remote mode
|
|
Doctor .......... N/A remote mode (brain admin runs `gbrain doctor`)
|
|
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)
|
|
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
|
|
|
|
Restart Claude Code to pick up the `mcp__gbrain__*` tools.
|
|
Re-run `/setup-gbrain` any time the bearer rotates or the URL moves.
|
|
```
|
|
|
|
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.
|
|
|
|
### Paths 1, 2a, 2b, 3 (Local stdio)
|
|
|
|
```
|
|
gbrain status: GREEN (mode: local-stdio)
|
|
|
|
CLI ............. OK <gbrain version>
|
|
Engine .......... OK <pglite|supabase> at <path>
|
|
doctor .......... OK
|
|
MCP ............. OK registered (user scope)
|
|
Repo policy ..... OK <read-write|read-only|deny>
|
|
Code import ..... OK <last_imported_head>
|
|
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
|
|
|
|
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.
|
|
|
|
---
|
|
|
|
## `/setup-gbrain --cleanup-orphans` (D20)
|
|
|
|
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:
|
|
|
|
```bash
|
|
# List user's Supabase projects (user has to pipe this through their own
|
|
# shell to review; we don't rely on a stored PAT).
|
|
export SUPABASE_ACCESS_TOKEN="<collected from read_secret_to_env>"
|
|
projects=$(curl -s -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
|
|
https://api.supabase.com/v1/projects)
|
|
```
|
|
|
|
Parse the response, identify any project named starting with `gbrain` whose
|
|
`ref` doesn't match the user's active `~/.gbrain/config.json` pooler URL.
|
|
For each orphan, AskUserQuestion per project: "Delete orphan project
|
|
`<ref>` (`<name>`, created `<created_at>`)?" — NEVER batch; per-project
|
|
confirm is a one-way door.
|
|
|
|
On confirmed delete:
|
|
```bash
|
|
curl -s -X DELETE -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
|
|
https://api.supabase.com/v1/projects/$REF
|
|
```
|
|
|
|
Never delete the active brain without a second explicit confirmation.
|
|
|
|
At end: `unset SUPABASE_ACCESS_TOKEN`. Revocation reminder.
|
|
|
|
---
|
|
|
|
## Telemetry (D4)
|
|
|
|
The preamble's Telemetry block logs skill success/failure at exit. When
|
|
emitting the event, add these enumerated categorical values to the
|
|
telemetry payload (SAFE — no free-form secrets, never the URL or PAT):
|
|
|
|
- `scenario`: `supabase-existing` | `supabase-auto-provision` |
|
|
`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)
|
|
- `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.
|
|
|
|
---
|
|
|
|
## Important Rules
|
|
|
|
- **One rule for every secret.** PAT, DB_PASS, pooler URL: env-var only,
|
|
never argv, never logged, never persisted to disk by us. The only file
|
|
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
|
|
migrate timeout, smoke test failure — each is a STOP. Do not paper over.
|
|
- **Concurrent-run lock.** At skill start, `mkdir ~/.gstack/.setup-gbrain.lock.d`
|
|
(atomic). If the mkdir fails, abort with: "Another `/setup-gbrain` instance
|
|
is running. Wait for it, or `rm -rf ~/.gstack/.setup-gbrain.lock.d` if
|
|
you're sure it's stale." Release on normal exit AND in the SIGINT trap.
|
|
- **CLAUDE.md is the audit trail.** Always update it in Step 8 after a
|
|
successful setup.
|