Documentation
¶
Overview ¶
Package adaptertest is the conformance suite for the driver SPI. It verifies implementations of driver.Driver directly and has no dependency on the root package's consumer API.
Usage follows the fstest.TestFS / nettest.TestConn idiom:
func TestMyDriverConformance(t *testing.T) {
adaptertest.TestDriver(t, func() driver.Driver {
return mydriver.Driver(mydriver.Config{Model: "m-1"})
},
adaptertest.WithConfig(mydriver.Config{Model: "m-1"}),
adaptertest.WithSessionState(&driver.SessionState{...}),
adaptertest.WithGuardKeys("cwd"),
)
}
Probes for the optional capability interfaces skip when an interface is not implemented, and the suite never exercises a capability the Descriptor does not declare. NewReferenceDriver returns a fully compliant in-memory implementation that doubles as the suite's self-proof and as a template for driver authors.
Contract clause catalogue ¶
Every failure message carries one of the numbered clauses below. The authority for each clause is the godoc in package driver (file noted per group); clauses marked (opt-in) run only when the corresponding Option is passed, and clauses marked (live) require WithLiveRun.
Core driver and config (driver/driver.go: Driver, Descriptor):
DRV-01 Descriptor().Type and DisplayName are non-empty.
DRV-02 Descriptor() is deterministic across calls and across factory
instances (the descriptor is a static declaration).
CFG-01 ValidateConfig(nil) must not panic.
CFG-02 ValidateConfig accepts the suite-supplied config.
CFG-03 (opt-in, ExpectRejectForeignConfig) ValidateConfig rejects a
config value of an unknown type.
Capability-declaration truthfulness (driver/driver.go capability interfaces; driver/environment.go report types):
CAP-01 Sessions.SupportsResume is true iff SessionCodecProvider returns
a non-nil, stable codec; resume-capable Drivers also implement
SessionConfigFingerprinter with a stable, non-empty result.
CAP-02 Skills.Supported implies SkillSupport and a declared Mode of
ephemeral|persistent; unsupported skills must not declare a mode.
CAP-03 CheckEnvironment succeeds hermetically; DriverType matches the
descriptor; Status is pass|warn|fail; pass implies Healthy;
checks carry stable Codes.
CAP-04 ListModels succeeds hermetically; every ModelInfo.ID non-empty.
CAP-05 DetectModel succeeds hermetically; a non-nil result carries a
non-empty Model (and matches WithExpectedDetectedModel).
CAP-06 GetProfile: DriverType matches; Supported implies non-empty Dir
and Source.
CAP-07 GetQuota succeeds hermetically; DriverType matches; window
labels non-empty.
CAP-08 ConfigSchema succeeds; field names non-empty and unique;
contains WithRequiredConfigFields.
CAP-09 SkillSupport echo laws on the empty catalogue: Supported=true,
DriverType matches, valid Mode, Selected mirrors the (empty)
selection. SyncSkills half is opt-in (WithSyncSkillsProbe).
CAP-10 StreamCapability() is deterministic.
CAP-11 Process.Persistent implies ProcessLifecycleDriver, so Agent.Close
can reap every process owned by the configured Driver.
Structured output (driver/driver.go StructuredOutputCapability, driver/output.go; engine resolution in internal/engine/structured.go):
SO-01 WorksWith* flags require a declared JSONSchema* mechanism, and a
declared mechanism requires WorksWithRun for v1's one execution
pipeline. Core selects native enforcement first and Prompt
validation as the fallback. Provider streaming and effective HITL
Ask additionally require WorksWithStreaming and WorksWithHITL.
SO-02 (live, opt-in) a native structured run yields StructuredOutput with
Source=native, Valid=true and parseable RawJSON.
SO-03 Suite guarantee: no probe requests a mechanism or transport shape
the descriptor does not declare.
Session codec (driver/session_codec.go; driver/run.go SessionState):
SES-01 Name() is non-empty and stable.
SES-02 ToParams(nil) is the zero SessionParams; FromParams(zero) is nil.
SES-03 ToParams preserves ResumeID and all Data entries; DisplayID is
non-empty for a resumable state.
SES-04 params -> FromParams -> ToParams is lossless (DeepEqual).
SES-05 GuardFingerprint is non-empty and deterministic.
SES-06 (opt-in, WithGuardKeys) mutating a guard value changes the
fingerprint (resume-guard doctrine in the SessionCodec godoc).
SES-07 nil/zero codec inputs never panic.
SES-08 (opt-in, WithSessionKeys) required keys survive the round-trip.
SES-09 Resume and persistent-process guards use
ProfilePayload.SessionFingerprint(); exact Fingerprint and payload
remain authoritative for current-invocation materialization.
Stream event timing (live; driver/events.go StreamKind, StreamPayload field-usage table, Role; driver/driver.go EventSink):
EVT-01 run.started is emitted exactly once and before every other payload,
including vendor extensions and provider-side drop reports.
EVT-02 exactly one run.finished or run.error is emitted, it is last,
and run.error carries Error.
EVT-03 text lifecycles: MessageID required, opened once by text.start,
content/end only while open.
EVT-04 text.content carries a non-empty Delta.
EVT-05 tool_call lifecycles: start requires ToolCallID+Name; args
require an open lifecycle and non-empty Delta; end/result
require a known ToolCallID.
EVT-06 reasoning lifecycles mirror EVT-03/EVT-04.
EVT-07 step.started / step.finished require Name.
EVT-08 hitl.requested / hitl.resolved carry their decision envelopes.
EVT-09 Role is left at the zero value on every driver-emitted payload.
EVT-10 Sequence, Seq, and Timestamp are left zero by drivers (the SDK
backfills them in EmitStream).
EVT-11 every opened lifecycle is closed before run.finished.
EVT-12 StreamCapability negatives hold: no tool_call.args when
ToolCallArgs=false, no reasoning.* when Reasoning=false, no
hitl.* when HITL=false.
EVT-13 run.* frames leave MessageID and ToolCallID empty.
Vendor-specific StreamKinds and RunEventTypes outside the declared enums are tolerated for field validation, but no payload may follow a terminal.
RunEvent envelope and transcript (live; driver/events.go RunEvent, TranscriptItem):
RUN-01 chunk events carry Stream "stdout"|"stderr".
RUN-02 item events carry a non-nil Item obeying the TRN rules.
RUN-03 drivers leave RunEvent.Seq zero (SDK-assigned).
RUN-04 the RunEventItem sequence exactly mirrors Response.Transcript.
TRN-01 text-bearing kinds (assistant/thinking/user/stdout/stderr/
system/summary/question/failure) require Text.
TRN-02 tool_call requires ToolName.
TRN-03 tool_result requires ToolUseID.
TRN-04 Delta is allowed on assistant and thinking only.
Response invariants (live; driver/run.go):
RSP-01 Checkpoint.Valid=true requires State with a ResumeID and a clean
outcome (Driver.Run error nil, exit 0, no signal/timeout/Failure).
RSP-02 Failure.HumanDecision is non-nil exactly when Code is
decision_rejected or decision_timeout.
RSP-03 Output is never the raw protocol-shaped stdout dump.
RSP-04 a valid checkpoint round-trips through the session codec with
its ResumeID and a non-empty guard fingerprint.
RSP-05 when a provider exposes terminal JSON, RawStreams.Terminal carries
its non-empty official event name and valid exact JSON payload.
These clauses are normative. The driver package states the lifecycle, codec-empty mapping, core-owned sequence, transcript mirror, resume-codec, checkpoint, structured-output transport and HumanDecision requirements as MUST rules; this suite does not offer lenient/advisory escape hatches.
Index ¶
- Constants
- func NewReferenceDriver(cfg ReferenceConfig) driver.Driver
- func TestDriver(t *testing.T, newDriver func() driver.Driver, opts ...Option)
- type Option
- func ExpectRejectForeignConfig() Option
- func SkipLiveRun(reason string) Option
- func WithConfig(cfg any) Option
- func WithExpectedDetectedModel(model string) Option
- func WithGuardKeys(keys ...string) Option
- func WithLiveRun(prompt string) Option
- func WithLiveRunTimeout(d time.Duration) Option
- func WithLiveStructuredOutput() Option
- func WithRequiredConfigFields(names ...string) Option
- func WithSessionKeys(keys ...string) Option
- func WithSessionState(state *driver.SessionState) Option
- func WithSyncSkillsProbe() Option
- func WithWorkspace(cwd string) Option
- type RecordingSink
- type ReferenceConfig
- type Violation
- func VerifyCheckpointCodec(d driver.Driver, resp *driver.Response) (out []Violation)
- func VerifyOutcome(resp *driver.Response, runErr error) []Violation
- func VerifyProcessCapability(d driver.Driver) []Violation
- func VerifyResponse(resp *driver.Response) []Violation
- func VerifyRunEvents(events []driver.RunEvent) []Violation
- func VerifySessionCapability(d driver.Driver) (out []Violation)
- func VerifyStreamCapability(capability driver.StreamCapability, payloads []driver.StreamPayload) []Violation
- func VerifyStreamSequence(payloads []driver.StreamPayload) []Violation
- func VerifyStructuredOutputCapability(capability driver.StructuredOutputCapability) []Violation
- func VerifyTranscript(items []driver.TranscriptItem) []Violation
- func VerifyTranscriptMirror(events []driver.RunEvent, transcript []driver.TranscriptItem) []Violation
Constants ¶
const DefaultLivePrompt = "Reply with exactly: OK"
DefaultLivePrompt is used by WithLiveRun("").
Variables ¶
This section is empty.
Functions ¶
func NewReferenceDriver ¶
func NewReferenceDriver(cfg ReferenceConfig) driver.Driver
NewReferenceDriver returns the suite's reference driver.Driver: a fully in-memory implementation that satisfies every clause TestDriver enforces and implements all optional capability interfaces. It is both the suite's self-proof (see the package tests) and a template for third-party driver authors — every emission below is annotated with the clause it upholds.
func TestDriver ¶
TestDriver runs the v1 driver conformance suite against drivers produced by newDriver, in the style of fstest.TestFS / nettest.TestConn. Probes for optional capability interfaces skip when the driver does not implement them; capability declarations in the Descriptor are cross-checked against the implemented interfaces (truthfulness), and the suite never probes a capability the descriptor does not declare. Failure messages carry the numbered contract clauses catalogued in the package documentation.
Types ¶
type Option ¶
type Option func(*suiteConfig)
Option configures TestDriver.
func ExpectRejectForeignConfig ¶
func ExpectRejectForeignConfig() Option
ExpectRejectForeignConfig asserts that ValidateConfig rejects a config value of a type the driver has never seen (CFG-03). All built-in drivers satisfy this; it is opt-in because the SPI does not mandate it.
func SkipLiveRun ¶
SkipLiveRun records why the live probes are skipped (for example "codex CLI not in PATH") and wins over WithLiveRun.
func WithConfig ¶
WithConfig supplies the driver-specific config value passed to every probe (ValidateConfig, CheckEnvironment, ListModels, ...) and to live runs via Request.Config. v1 drivers built with <pkg>.Driver(cfg) may receive nil here; they inject their captured config themselves.
func WithExpectedDetectedModel ¶
WithExpectedDetectedModel asserts the ModelDetector result (CAP-05).
func WithGuardKeys ¶
WithGuardKeys lists session parameter keys that participate in the codec's GuardFingerprint; mutating any of them must change the fingerprint (SES-06). Without this option SES-06 is skipped, because which keys are guard-relevant is driver-specific.
func WithLiveRun ¶
WithLiveRun enables the live execution probes (EVT-*, RUN-*, TRN-*, RSP-*): the suite invokes Run against the real provider with prompt. An empty prompt selects DefaultLivePrompt. Callers gate this on CLI availability; see SkipLiveRun.
func WithLiveRunTimeout ¶
WithLiveRunTimeout overrides the live run deadline (default 5 minutes).
func WithLiveStructuredOutput ¶
func WithLiveStructuredOutput() Option
WithLiveStructuredOutput additionally runs the native structured-output probe (SO-02) when the descriptor declares JSONSchemaNative for Run. The suite never requests a mechanism the descriptor does not declare (SO-03).
func WithRequiredConfigFields ¶
WithRequiredConfigFields asserts that the hydrated ConfigSchema contains these field names (CAP-08).
func WithSessionKeys ¶
WithSessionKeys lists SessionState.Data keys that must survive the codec round-trip (SES-08). Keys must be present in the seeded session state.
func WithSessionState ¶
func WithSessionState(state *driver.SessionState) Option
WithSessionState seeds the session-codec round-trip probes (SES-*). When omitted the suite uses a generic resumable state.
func WithSyncSkillsProbe ¶
func WithSyncSkillsProbe() Option
WithSyncSkillsProbe additionally exercises SyncSkills with the empty catalogue (CAP-09). Opt-in because SyncSkills reconciles host-side state and may write into the driver profile directory.
func WithWorkspace ¶
WithWorkspace sets the workspace CWD used for live runs.
type RecordingSink ¶
type RecordingSink struct {
// contains filtered or unexported fields
}
RecordingSink is a concurrency-safe driver.EventSink that records every RunEvent and StreamPayload exactly as the driver emitted them. Unlike the SDK's production sink it performs no Sequence/Seq/Timestamp backfill, so the verifiers can check the driver-side halves of the contract (EVT-10, RUN-03: drivers leave those fields zero).
func NewRecordingSink ¶
func NewRecordingSink() *RecordingSink
NewRecordingSink returns an empty RecordingSink.
func (*RecordingSink) Emit ¶
func (s *RecordingSink) Emit(event driver.RunEvent) error
Emit records event and never fails.
func (*RecordingSink) EmitStream ¶
func (s *RecordingSink) EmitStream(payload driver.StreamPayload) error
EmitStream records payload and never fails.
func (*RecordingSink) Events ¶
func (s *RecordingSink) Events() []driver.RunEvent
Events returns a copy of the recorded RunEvents in emission order.
func (*RecordingSink) Stream ¶
func (s *RecordingSink) Stream() []driver.StreamPayload
Stream returns a copy of the recorded StreamPayloads in emission order.
type ReferenceConfig ¶
type ReferenceConfig struct {
// Model is the configured model; defaults to "reference-1".
Model string
// CWD is the fallback working directory when the request carries no
// workspace lease.
CWD string
// FailRun makes Run report a provider-level failure (FailureAgentError
// plus a run.error terminal frame) instead of a successful run.
FailRun bool
}
ReferenceConfig configures the in-memory reference driver returned by NewReferenceDriver.
type Violation ¶
Violation is one contract breach detected by a verifier. Clause is the numbered contract rule from the catalogue in the package documentation; each clause cites the driver-package godoc it is grounded in.
func VerifyCheckpointCodec ¶
VerifyCheckpointCodec checks RSP-04 without running a paid/live probe. A valid checkpoint is meaningful only when the same Driver exposes a codec that accepts its resume identity and derives a non-empty guard.
func VerifyOutcome ¶
VerifyOutcome checks Response-level structural invariants (clauses RSP-01 .. RSP-03 plus TRN-* for the transcript) together with the error returned by Driver.Run. A non-nil runErr makes a valid checkpoint unsafe even when the Response's process fields happen to look successful.
func VerifyProcessCapability ¶
VerifyProcessCapability checks that a Driver advertising a persistent process also exposes the lifecycle hook Agent.Close needs to reap it.
func VerifyResponse ¶
VerifyResponse checks the invariants observable from Response alone. Use VerifyOutcome when the Driver.Run error is available.
func VerifyRunEvents ¶
VerifyRunEvents checks the driver-side RunEvent envelope contract (clauses RUN-01 .. RUN-03; TRN-* for embedded transcript items) against events exactly as the driver emitted them.
func VerifySessionCapability ¶
VerifySessionCapability checks the declaration and support-interface half of CAP-01 without starting a provider process. Resume support requires both a stable, non-nil SessionCodec and a stable, non-empty construction-config fingerprint; Thread correctness depends on both identities.
func VerifyStreamCapability ¶
func VerifyStreamCapability(capability driver.StreamCapability, payloads []driver.StreamPayload) []Violation
VerifyStreamCapability cross-checks a driver's declared StreamCapability against the payloads it actually emitted (clause EVT-12). Only negative declarations are enforced: a false capability flag means the corresponding kinds must not appear (StreamCapability docs: every field is additive).
func VerifyStreamSequence ¶
func VerifyStreamSequence(payloads []driver.StreamPayload) []Violation
VerifyStreamSequence checks the driver-side stream event timing contract (clauses EVT-01 .. EVT-11, EVT-13) against payloads exactly as the driver emitted them (before SDK Sequence/Timestamp backfill). The authority for each clause is the godoc in package driver (StreamKind, StreamPayload, Role, EventSink); see the package documentation for the catalogue.
func VerifyStructuredOutputCapability ¶
func VerifyStructuredOutputCapability(capability driver.StructuredOutputCapability) []Violation
VerifyStructuredOutputCapability checks the declaration half of the structured-output matrix (SO-01). The optional live probe verifies the native, non-streaming baseline; core's structured contract tests own automatic selection and rejection across provider-streaming and HITL.
func VerifyTranscript ¶
func VerifyTranscript(items []driver.TranscriptItem) []Violation
VerifyTranscript checks TranscriptItem kind field rules (clauses TRN-01 .. TRN-04) for a full transcript slice.
func VerifyTranscriptMirror ¶
func VerifyTranscriptMirror(events []driver.RunEvent, transcript []driver.TranscriptItem) []Violation
VerifyTranscriptMirror checks the hard SPI invariant that collecting every driver-emitted RunEventItem in emission order exactly reproduces Response.Transcript. Streaming deltas participate when and only when the driver also includes them in the final Transcript.