Skip to content

core: the four core seams have no contract suite a third-party provider can run #342

Closed

Description

@schlessera

Context

Part of #56. Found by the 1.0 surface audit (#319), against main @ 550a41ef.

#56's definition of done is a third-party provider, written against the
previous minor, that "still compiles and still passes the interface's contract
test". Of the nine documented seams, only AgentBackend has a contract test a
third party can run (runBackendContract, @schlessera/brain-ui-sdk/testing).
The four core seams have none:

Seam Declared What the seam promises beyond its type
EmbeddingProvider packages/core/src/lib/seams.ts:54 dimensions matches every vector returned; embedQuery honours or tolerates opts.signal (added in cc48069); an absent embedImage / embedPdf degrades to the text description (docs/extending/README.md:50-58)
CompletionProvider seams.ts:22 capabilities.vision: false means image parts are not sent, and core falls back to title-only descriptions
AgentRunner seams.ts:37 capabilities.streaming agrees with whether runStreaming exists; timeoutMs is honoured
SkillEmitter seams.ts:97 the emitted layout for a SkillManifest (seams.ts:79)

The promises are written in docs/extending/embeddings.md, completions.md,
agent-runners.md and skill-emitters.md. Only the built-ins are tested
against them, in files a third party cannot import:
packages/core/tests/gemini-query.test.ts, claude-runner-*.test.ts,
skills-*-emitter.test.ts. The promotion bar (docs/extending/README.md:191-198)
asks a community provider for "keyless, deterministic tests that exercise the
runtime" and points to gemini-query.test.ts as the model. It cannot point to
a suite, because there is none.

Scope

  • Add a ./testing subpath export to @schlessera/brain, shaped like
    @schlessera/brain-ui-sdk/testing: test-runner primitives are injected,
    there is no runtime dependency on a test runner, and nothing needs a key or
    the network.
  • One suite per core seam, asserting the promises in the table above and in
    each seam's page under docs/extending/. Where a page's promise is too vague
    to assert, record that on this issue rather than inventing a stricter one.
  • Run every built-in through its suite in this repository's tests: gemini
    embeddings, gemini-flash and anthropic-haiku completions, the built-in
    agent runners, and BUILTIN_EMITTERS. Use isolated fetch or fake
    binaries, as the existing tests do.
  • Point the promotion bar and each seam page at its suite.

Out of scope

Acceptance criteria

  • @schlessera/brain/testing exports one suite per core seam, and the
    packaging smoke test imports it from the built package.
  • Every built-in listed under Scope runs through its suite in CI, with no
    key and no network.
  • Each suite has at least one case shown failing against a deliberately
    non-conforming fake, for example an embedder whose vectors are not
    dimensions wide. The mutation and the failing assertion are recorded
    in the PR.
  • docs/extending/README.md (promotion bar, item 3) and the four seam pages
    name the suite.

Verification

bun run test; bun run build and the packaging smoke test; the mutation
receipts in the PR.

Contract impact

  • This touches the integration contract, so it needs the contract label, a CONTRACT: commit prefix, and the doc updated in the same commit.
  • This changes a published package's behaviour, so it needs a changeset.

A new subpath export is additive. A new export must also be added to
api-report/core.txt (bun run api-report).

Activity

  1. added
    type: featA new capability or a change in user-visible behaviour.
    area: corepackages/core: the brain CLI, indexer, hybrid search, config, taxonomy, skills.
    agent-readyContext and acceptance criteria are complete enough for an agent to take this unattended.
    on Sep 25, 2026
  2. schlessera commented on Sep 25, 2026

    @schlessera
    OwnerAuthor

    Promises on the four seam pages that were too vague to assert, recorded here as the Scope asks, rather than turned into stricter checks in @schlessera/brain/testing:

    All four seams

    • id (and SkillEmitter.agent) is only typed string. No page says it must be non-empty, although core puts it in composite ids and in the vector-table metadata. The suites check the type only.
    • EmbeddingProvider.dimensions is only typed number. No page says it is a positive integer; the suites check that every vector matches it, not what it is.

    EmbeddingProvider (embeddings.md)

    • Nothing says embed returns vectors in the order of its texts. The indexer relies on it (it zips vectors back onto chunks), but the suite checks count and width only.
    • Nothing says what embed([]) returns.
    • "Honours or tolerates opts.signal" is two promises. The suite checks the tolerant half for every provider. It checks the honouring half only when the harness supplies hanging(), which declares that the provider forwards the signal.

    CompletionProvider (completions.md)

    • Whether system and maxTokens must be honoured, or only accepted, is unstated. The suite checks that they are accepted.
    • vision: true says a provider "can look at image/PDF parts". That cannot be observed through a fake vendor. The suite checks that core then hands it the part, and that its answer becomes the description.

    AgentRunner (agent-runners.md)

    • The page does not say what run does when the agent fails (exit non-zero): reject, or resolve to the text it has. The built-ins reject. The suite does not check it.
    • capabilities.skills ("the agent discovers the brain's skills") cannot be observed without a real agent. The suite checks the type only.
    • runStreaming takes no timeoutMs, so it makes no timeout promise, and the suite checks none.

    SkillEmitter (skill-emitters.md)

    • "The agent's expected layout" is per agent. The suite checks that each skill can be reached from what was written (a path names it, or a written file mentions it) and that a dropped skill no longer can. It does not check the layout itself.
    • Never clobbering a real file or directory at the target is stated only in the claude and pi emitters' source. Preserving content outside the managed block is stated only for the codex and gemini index-block emitters. Neither is on the page as a promise of the seam, so neither is in the suite.
  3. added this to the 0.38.0 milestone on Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent-readyContext and acceptance criteria are complete enough for an agent to take this unattended.area: corepackages/core: the brain CLI, indexer, hybrid search, config, taxonomy, skills.type: featA new capability or a change in user-visible behaviour.

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions