From 6820dbf0ff5bea9a93a2cdb8467c5e355aecd2b6 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Tue, 16 Jun 2026 10:37:51 -0700 Subject: [PATCH] =?UTF-8?q?fix(verbs):=20green=20the=203=20failing=20CI=20?= =?UTF-8?q?shards=20=E2=80=94=203-seg=20migration=20version,=20hermetic=20?= =?UTF-8?q?synthesize=20test,=20fresh=20llms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three real CI-shard failures from the propagation commit + master merges: - migrations-registry (shard 10): v0_43_0 used a 4-segment version 0.43.0.0, but the registry enforces 3-segment semver (/^\d+\.\d+\.\d+$/). Changed the migration version to 0.43.0 (the RELEASE stays 0.43.0.0; migrations have always used 3-seg, e.g. 0.32.2). apply-migrations future-list fixtures updated to match. - synthesize conformance test (shard 5): asserted a successful answer via the chat seam, but runThink builds its client through a real-key check (not the seam), so CI (credential-free) took the NO_ANTHROPIC_API_KEY path → the verb's unavailable conversion → isError. Now wraps the call in withEnv with a fake key AND the chat seam, so it's deterministic regardless of ambient credentials. - build-llms (shard 8): the v0.42.44.0 master merge changed an inlined doc; regenerated llms.txt/llms-full.txt. Cathedral 1 CI fixes (#cathedral-1) Co-Authored-By: Claude Fable 5 --- llms-full.txt | 7 ++++++- src/commands/migrations/v0_43_0.ts | 4 ++-- test/apply-migrations.test.ts | 4 ++-- test/memory-verbs-conformance.test.ts | 16 ++++++++++------ 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/llms-full.txt b/llms-full.txt index 183d24777..c160a8d11 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -3486,11 +3486,16 @@ for remote clients over OAuth 2.1. ### Local stdio (zero setup) ```bash -gbrain serve +gbrain serve # full operation catalog (default) +gbrain serve --surface verbs # just the 5 memory verbs (quickstart surface) ``` Works with Claude Code, Cursor, Windsurf, and any MCP client that supports stdio. No server, no tunnel, no token needed. Works on both PGLite and Postgres engines. +`--surface verbs` exposes exactly the five-verb memory protocol (`recall`, +`remember`, `entity`, `synthesize`, `forget` — +[MEMORY_VERBS v1](../protocol/MEMORY_VERBS_v1.md)) instead of the full catalog; +omit the flag (default `full`) for every operation. ### Remote over OAuth 2.1 (recommended, v0.26.0+) diff --git a/src/commands/migrations/v0_43_0.ts b/src/commands/migrations/v0_43_0.ts index a73e4c0d8..e8c337091 100644 --- a/src/commands/migrations/v0_43_0.ts +++ b/src/commands/migrations/v0_43_0.ts @@ -18,11 +18,11 @@ import type { Migration, OrchestratorOpts, OrchestratorResult } from './types.ts async function orchestrator(_opts: OrchestratorOpts): Promise { // No schema/data work — MEMORY_VERBS v1 is a façade over existing tables. - return { version: '0.43.0.0', status: 'complete', phases: [] }; + return { version: '0.43.0', status: 'complete', phases: [] }; } export const v0_43_0: Migration = { - version: '0.43.0.0', + version: '0.43.0', featurePitch: { headline: 'Five memory verbs — recall, remember, entity, synthesize, forget — are now the agent-facing memory protocol (MEMORY_VERBS v1).', diff --git a/test/apply-migrations.test.ts b/test/apply-migrations.test.ts index 455f772a5..7e50fc86e 100644 --- a/test/apply-migrations.test.ts +++ b/test/apply-migrations.test.ts @@ -108,7 +108,7 @@ describe('buildPlan — diff against completed + installed VERSION', () => { // autopilot cooperative, v0.16.0 = subagent runtime, v0.18.0 = multi- // source brains, v0.18.1 = RLS hardening, v0.21.0 = Cathedral II // (renumbered from v0.20.0 after master shipped v0.20.x in parallel). - expect(plan.skippedFuture.map(m => m.version)).toEqual(['0.12.0', '0.12.2', '0.13.0', '0.13.1', '0.14.0', '0.16.0', '0.18.0', '0.18.1', '0.21.0', '0.22.4', '0.28.0', '0.29.1', '0.31.0', '0.32.2', '0.43.0.0']); + expect(plan.skippedFuture.map(m => m.version)).toEqual(['0.12.0', '0.12.2', '0.13.0', '0.13.1', '0.14.0', '0.16.0', '0.18.0', '0.18.1', '0.21.0', '0.22.4', '0.28.0', '0.29.1', '0.31.0', '0.32.2', '0.43.0']); }); test('already applied → v0.11.0 lands in `applied` bucket, not pending', () => { @@ -148,7 +148,7 @@ describe('buildPlan — diff against completed + installed VERSION', () => { // v0.22.4, v0.28.0, v0.29.1, v0.31.0 were added later; installed=0.12.0 // means they belong in skippedFuture, not pending. v0.11.0 and v0.12.0 // stay pending despite being ≤ installed — that is the H9 invariant. - expect(plan.skippedFuture.map(m => m.version)).toEqual(['0.12.2', '0.13.0', '0.13.1', '0.14.0', '0.16.0', '0.18.0', '0.18.1', '0.21.0', '0.22.4', '0.28.0', '0.29.1', '0.31.0', '0.32.2', '0.43.0.0']); + expect(plan.skippedFuture.map(m => m.version)).toEqual(['0.12.2', '0.13.0', '0.13.1', '0.14.0', '0.16.0', '0.18.0', '0.18.1', '0.21.0', '0.22.4', '0.28.0', '0.29.1', '0.31.0', '0.32.2', '0.43.0']); }); test('--migration filter narrows to one version', () => { diff --git a/test/memory-verbs-conformance.test.ts b/test/memory-verbs-conformance.test.ts index e086c2ac6..8b1e9b501 100644 --- a/test/memory-verbs-conformance.test.ts +++ b/test/memory-verbs-conformance.test.ts @@ -44,6 +44,7 @@ import { __setEmbedTransportForTests, } from '../src/core/ai/gateway.ts'; import { __setUsageLogPathForTests } from '../src/core/verbs/usage-log.ts'; +import { withEnv } from './helpers/with-env.ts'; let engine: PGLiteEngine; let home: string; @@ -295,11 +296,12 @@ describe('synthesize — marked expensive + unavailable conversion [c10]', () => }); it('delegates to runThink and returns the frozen envelope with a priced cost block (chat seam — no real LLM)', async () => { - // Hermetic: the chat transport seam answers deterministically. (The - // keyless `unavailable` conversion [c10] is covered end-to-end by the CI - // conformance step, which runs `protocol conformance --synthesize` in a - // credential-free environment — a unit-level trigger here would depend on - // the developer machine NOT having keys, the opposite of hermetic.) + // Fully hermetic regardless of the dev/CI machine's ambient credentials: + // runThink builds its client via a real-key check (hasAnthropicKey reads + // process.env), NOT the gateway chat seam — so we must BOTH provide a fake + // key via withEnv (so the client builds) AND install the chat seam (so no + // real API call fires). Without the env key, CI (credential-free) takes the + // NO_ANTHROPIC_API_KEY path → the verb's `unavailable` conversion → isError. __setChatTransportForTests(async () => ({ text: JSON.stringify({ answer: 'Synthesized test answer.', citations: [], gaps: ['none'] }), blocks: [], @@ -308,7 +310,9 @@ describe('synthesize — marked expensive + unavailable conversion [c10]', () => model: 'anthropic:claude-haiku-4-5-20251001', providerId: 'anthropic', })); - const { isError, body } = await callRemote('synthesize', { question: 'what do we know?' }); + const { isError, body } = await withEnv({ ANTHROPIC_API_KEY: 'sk-test-hermetic' }, async () => + callRemote('synthesize', { question: 'what do we know?' }), + ); expect(isError).toBe(false); expect(body.answer).toBe('Synthesized test answer.'); expect(body.protocol_version).toBe(1);