Documentation
¶
Overview ¶
Package fake provides an in-memory scripted agent.Adapter implementation. Used by Phase 5 conformance tests (Buckets 12/13/15) and by slice 5.2's dispatcher unit tests. Mirrors the container/fake pattern — scripted- result table keyed on the invocation index, plus a Calls() history for dispatcher-side assertions (e.g., gate feedback substitution on attempt 2).
Phase 5 design decision 10: builder API. fake.New(ref).Script(0, ...). Script(1, ...).WithCaps(...).WithTranscriptExtractor(...) chains, returning the same *Fake. Goroutine-safe via sync.Mutex.
The fake honors agent.Adapter's streaming contract: Launch emits each scripted AgentEvent on the returned channel, closes the channel, and returns AgentResult synchronously. Slice 5.2 dispatcher tests range over the channel and assert event ordering.
Index ¶
- type Fake
- func (f *Fake) Calls() []agent.AgentInvocation
- func (f *Fake) Capabilities() agent.Caps
- func (f *Fake) Extractor() func(transcript string) (map[string]any, error)
- func (f *Fake) Launch(ctx context.Context, _ container.Handle, inv agent.AgentInvocation) (<-chan agent.AgentEvent, <-chan agent.AgentOutcome, error)
- func (f *Fake) Ref() string
- func (f *Fake) RunToolLoop(_ context.Context, inv agent.ToolLoopInvocation) (agent.ToolLoopResult, error)
- func (f *Fake) Script(n int, r Result) *Fake
- func (f *Fake) ScriptToolLoop(n int, r agent.ToolLoopResult) *Fake
- func (f *Fake) ToolLoopCalls() []agent.ToolLoopInvocation
- func (*Fake) ValidateConfig(_ ir.RawConfig) error
- func (f *Fake) Version(_ context.Context, _ container.Handle) (string, error)
- func (f *Fake) WithCaps(c agent.Caps) *Fake
- func (f *Fake) WithEmitDelay(d time.Duration) *Fake
- func (f *Fake) WithToolLoopTripwire(committedRounds int) *Fake
- func (f *Fake) WithTranscriptExtractor(fn func(transcript string) (map[string]any, error)) *Fake
- func (f *Fake) WithVersion(v string) *Fake
- type Result
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Fake ¶
type Fake struct {
// contains filtered or unexported fields
}
Fake is the in-memory scripted adapter. Zero value is NOT usable — call New(ref) so Ref() returns a non-empty string.
func New ¶
New mints a Fake for the given ref. Default Capabilities() returns {NativeSchema: true} — matching what the real Claude Code adapter declares in slice 5.3. Override with WithCaps for Bucket 15 layer-2 tests.
func NewBenignOracle ¶
func NewBenignOracle() *Fake
NewBenignOracle returns a pre-scripted Fake adapter intended for Phase 5 Bucket 13 gate tests (and Phase 5.4 benign-payload-oracle fixtures). The adapter is registered under ref "test/oracle" (NOT "anthropic/claude-code") so test fixtures distinguish it from the real claude ref.
Script (position-driven — NOT feedback-driven):
- Call index 0: {verified: false, fooled_by_benign: true, feedback: "exploit was fake — only matched a version string"}
- Call index 1: {verified: true, fooled_by_benign: false, feedback: ""}
IMPORTANT: This fake is purely POSITIONAL. It does NOT inspect AgentInvocation.Feedback or AgentInvocation.With to decide which result to return — it just consumes scripts in call order. The narrative ("the generator produced a real exploit after the gate threaded feedback into attempt 2") only HOLDS if the slice 5.2 dispatcher correctly threads feedback. This fake doesn't verify that threading happened.
To verify feedback threading in slice 5.2's Bucket 13b, inspect fake.Calls() AFTER the gate runs: Calls()[1].With (the attempt-2 generator input) should contain the prior verdict's "feedback" field substituted in. That's the assertion slice 5.2's test makes — NOT this fake's responsibility.
Gate `until` expression for the workflow: `evaluate.verified && !evaluate.fooled_by_benign`. Call 0 → until is false → gate repairs. Call 1 → until is true → gate passes.
max_attempts: 2 minimum (slice 5.4 fixture sets this). Adding more Script entries here is harmless — Launch consumes the scripts in order and returns an out-of-bounds error after they're exhausted.
func (*Fake) Calls ¶
func (f *Fake) Calls() []agent.AgentInvocation
Calls returns a defensive copy of every AgentInvocation Launch has received. Slice 5.2 dispatcher tests inspect this to assert gate feedback substitution and AgentInvocation field threading.
func (*Fake) Capabilities ¶
Capabilities returns the static caps (override with WithCaps).
func (*Fake) Extractor ¶
Extractor returns the extractor closure set via WithTranscriptExtractor (or nil). Bucket 15 tests use this to drive the layer-2 contract.
func (*Fake) Launch ¶
func (f *Fake) Launch(ctx context.Context, _ container.Handle, inv agent.AgentInvocation) (<-chan agent.AgentEvent, <-chan agent.AgentOutcome, error)
Launch honors the slice 5.3 γ contract: returns IMMEDIATELY with events and outcome channels OPEN. An emitter goroutine writes each scripted event to the events channel (with optional inter-event delay), closes events, then sends AgentOutcome and closes outcomeCh. Caller MUST drain events before reading outcome (the standard `for range events; outcome := <-outcomeCh` pattern).
func (*Fake) RunToolLoop ¶
func (f *Fake) RunToolLoop(_ context.Context, inv agent.ToolLoopInvocation) (agent.ToolLoopResult, error)
RunToolLoop satisfies agent.ToolLoopRunner. It is mutex-guarded, returns the scripted result for the current call index, and records every invocation.
Tripwire: if WithToolLoopTripwire(N) was set and the current index < N, RunToolLoop returns an error immediately — hard-failing to prove the engine is not re-sampling a committed model round.
Missing script: if no result was programmed for the current index, RunToolLoop returns an error (mirrors Launch's missing-script contract).
func (*Fake) Script ¶
Script programs the result for the Nth Launch call (zero-indexed). Returns *Fake for chaining. Calling Script twice on the same index silently overwrites — the latest wins, matching container/fake's ProgramExec convention.
func (*Fake) ScriptToolLoop ¶
func (f *Fake) ScriptToolLoop(n int, r agent.ToolLoopResult) *Fake
ScriptToolLoop programs the ToolLoopResult for the Nth RunToolLoop call (zero-indexed). Returns *Fake for chaining. Calling ScriptToolLoop twice on the same index silently overwrites — the latest wins (mirrors Script).
func (*Fake) ToolLoopCalls ¶
func (f *Fake) ToolLoopCalls() []agent.ToolLoopInvocation
ToolLoopCalls returns a defensive copy of every ToolLoopInvocation that RunToolLoop has received. Resume conformance tests inspect this to assert that the round-2 invocation's messages contain the round-1 IDs verbatim.
func (*Fake) ValidateConfig ¶
ValidateConfig is permissive by default — accepts any RawConfig. Slice 5.3's real claude adapter is strict; fixtures targeting the fake don't have to mirror the real schema.
func (*Fake) Version ¶
Version returns the fake's version string. Default is "fake-v1"; override with WithVersion for drift-test fixtures.
func (*Fake) WithCaps ¶
WithCaps overrides the default Capabilities(). Used by Bucket 15 tests to construct a `Caps{NativeSchema: false}` fake.
func (*Fake) WithEmitDelay ¶
WithEmitDelay sets the inter-event delay used by Launch's emitter goroutine. Realtime tests (TestClaudeAdapterRealtimeStreaming and the fake's own TestFake_Launch_EmitDelay_RealtimeProgression) use this to produce verifiable wall-clock progression. Default 0 (no delay).
func (*Fake) WithToolLoopTripwire ¶
WithToolLoopTripwire arms a resume tripwire: if RunToolLoop is invoked for any call index < committedRounds, it hard-fails with an error. This proves the engine never re-samples committed model rounds on resume (the model-not- re-sampled invariant from spec §4.1). committedRounds is the number of rounds that were already committed in a prior lifetime (= len(ReactRounds[R])).
The fake's call index is advanced to committedRounds so that ScriptToolLoop entries for the resume run can be keyed starting at committedRounds (= the first non-committed round index). The tripwire fires if the engine somehow calls RunToolLoop for a committed index despite the resume cursor advancing.
func (*Fake) WithTranscriptExtractor ¶
WithTranscriptExtractor sets the layer-2 extractor closure. The fake itself doesn't use it in Launch (Launch just consults the script table); the closure is exposed to test callers via Extractor() so Bucket 15 tests can verify the contract without coupling the fake to a real layer-2 implementation.
(Phase 5 design Appendix H: the real structuring-call helper is deferred to whichever future non-native-schema adapter ships first. The fake simulates the contract via this opt-in closure.)
func (*Fake) WithVersion ¶
WithVersion overrides the default Version() return value. Used by the drift-test fixture in cli/resume_test.go.
type Result ¶
type Result struct {
Output map[string]any
Events []agent.AgentEvent
Cost float64 // dollars; stamped into AgentResult.Metrics.Cost.Total
Tokens agent.MetricTokens
Files map[string][]byte
Live *agent.LiveDispatch
Transcript agent.ThreadTurn // scriptable verbatim pair; copied into AgentResult.Transcript by Launch
// Err, when non-nil, makes Launch emit it as AgentOutcome.Err (after any
// scripted Events) instead of a success AgentResult — lets tests script
// transient/permanent launch failures (e.g. *agent.ErrAgentLaunch with a
// RetryHint) and drive the dispatcher's failure classification.
Err error
}
Result is one scripted Launch outcome — the typed Output the fake's Launch returns, optional Events emitted on the channel before the result, and optional Cost the fake stamps into AgentResult.Metrics.