fix(verbs): green the 3 failing CI shards — 3-seg migration version, hermetic synthesize test, fresh llms

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 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-06-16 10:37:51 -07:00
co-authored by Claude Fable 5
parent 49ee3a7e7c
commit 6820dbf0ff
4 changed files with 20 additions and 11 deletions
+6 -1
View File
@@ -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+)
+2 -2
View File
@@ -18,11 +18,11 @@ import type { Migration, OrchestratorOpts, OrchestratorResult } from './types.ts
async function orchestrator(_opts: OrchestratorOpts): Promise<OrchestratorResult> {
// 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).',
+2 -2
View File
@@ -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', () => {
+10 -6
View File
@@ -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);