harnessx

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package harnessx is the single choke-point every PR-AF reasoner uses to call the AgentField harness. It replaces the Python monkeypatch of app.harness with an explicit generic wrapper:

  • schemaFor[T] resolves the JSON-schema map the harness consumes to build its OUTPUT REQUIREMENTS prompt suffix AND to validate parsed output (design §C.3). For destination types registered by RegisterSchema it returns the committed pydantic-generated schema (parity with the Python SDK); for unknown types it falls back to invopop reflection.
  • Run[T] calls the harness, classifies fatal API errors, and on a schema parse-failure hands the caller a default-seeded value so it can apply its deterministic fallback (design §C.3).

Unlike the SWE-AF harness this is adapted from, PR-AF has no scout-credential store, so Run does NOT inject run-scoped credentials into the subprocess env — opts is passed through unchanged. This is the ONLY way reasoners should reach the harness: it guarantees uniform fatal-error handling across every reasoner.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RegisterSchema

func RegisterSchema(t reflect.Type, fixtureName string)

RegisterSchema associates a destination type with its committed pydantic schema fixture. Call it once per Run[T] destination type (see reasoners/schemas_registry.go). Registration must complete before the first Run[T] for that type; init()-time registration guarantees this because any reasoner that calls Run[T] imports the package whose init() registers T.

func RegisteredSchema

func RegisteredSchema(t reflect.Type) (map[string]any, bool)

RegisteredSchema returns the resolved schema for a registered type, or (nil, false) if t has no registered fixture. Exported for the drift test, which cross-checks every embedded schema against its Go struct's json tags.

func Run

func Run[T any](ctx context.Context, app HarnessCaller, prompt string, opts appx.HarnessOptions) (*T, *appx.HarnessResult, error)

Run is the single generic entry point every reasoner uses to invoke the harness for structured output of type T.

Sequence (design §C.3):

  1. Reflect T into the JSON schema the harness consumes (cached per type).
  2. Call app.Harness with a fresh *T dest. PR-AF has no scout-credential store, so — unlike the SWE-AF harness this is adapted from — Run does NOT inject run-scoped credentials into opts.Env; opts is passed through as-is.
  3. Classify fatal (non-retryable) API errors FIRST, before the Parsed==nil fallback, so the real billing/auth message surfaces past every retry layer as a *fatal.FatalHarnessError (callers must propagate it, not swallow it).
  4. On Result.Parsed == nil (the harness could not parse valid JSON into T), return a default-seeded T plus the Result — NOT an error — so the caller inspects Result.IsError and applies its role-specific deterministic fallback. The seed comes from unmarshaling "{}" into T, which triggers T's UnmarshalJSON default-seeding (schemas §C.1) when present, and yields the Go zero value otherwise.

Returns (*T, *appx.HarnessResult, error). The Result is returned even alongside a non-nil error so callers can inspect diagnostics.

Types

type HarnessCaller

type HarnessCaller interface {
	Harness(ctx context.Context, prompt string, schema map[string]any, dest any, opts appx.HarnessOptions) (*appx.HarnessResult, error)
}

HarnessCaller is the minimal method set Run needs from *agent.Agent. Declaring it as an interface (rather than depending on the concrete *agent.Agent) lets tests supply a mock harness without a live subprocess — the same seam the Python tests get by patching the router's harness. *agent.Agent satisfies it via its Harness method (sdk/go/agent/harness.go).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL