contract

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package contract provides import-isolated machine contracts for ax-go consumers.

It owns deterministic exit codes, output mode resolution, context metadata, success envelopes, strict JSON writers, and the structured error envelope. The package does not import the root ax facade or runtime telemetry, logging, transport, or execution adapters.

Consequently this package provides no live tracing: TraceIDFromContext and SpanIDFromContext read back metadata a caller already stored with WithMetadata, never an active OpenTelemetry span context. Real trace IDs come from the root ax package, where StartTelemetry installs W3C propagation and Execute opens a recording root span.

Index

Examples

Constants

View Source
const (
	// ExitSuccess indicates successful completion.
	ExitSuccess = 0
	// ExitInternal indicates an unknown or internal error.
	ExitInternal = 1
	// ExitValidation indicates invalid input or failed validation.
	ExitValidation = 2
	// ExitNetwork indicates a network failure or timeout.
	ExitNetwork = 3
	// ExitAuth indicates an authentication or permission failure.
	ExitAuth = 4
)
View Source
const (
	// ZeroTraceID is a valid zero-value W3C trace ID for no-active-span cases.
	ZeroTraceID = "00000000000000000000000000000000"
	// ZeroSpanID is a valid zero-value W3C span ID for no-active-span cases.
	ZeroSpanID = "0000000000000000"
)
View Source
const (
	// ErrorSchemaVersion is the current SemVer version of the error envelope.
	ErrorSchemaVersion = "1.0.0"
)
View Source
const ModeDetectionRule = "--format flag > AGENT_MODE env > TTY detection"

ModeDetectionRule documents the output-mode resolution precedence applied by ResolveMode. It is surfaced verbatim in schema output.

Variables

This section is empty.

Functions

func ApprovalFromContext added in v0.5.0

func ApprovalFromContext(ctx context.Context) bool

ApprovalFromContext reports whether explicit confirmation was granted.

func DryRunFromContext

func DryRunFromContext(ctx context.Context) bool

DryRunFromContext reports whether dry-run behavior is active.

func ErrorExitCode

func ErrorExitCode(err error) int

ErrorExitCode maps an error to the deterministic ax-go process exit code.

func IdempotencyKeyFromContext

func IdempotencyKeyFromContext(ctx context.Context) (string, bool)

IdempotencyKeyFromContext returns the idempotency key stored in ctx.

func SpanIDFromContext

func SpanIDFromContext(ctx context.Context) string

SpanIDFromContext returns the explicit span ID stored in ctx or ZeroSpanID when no span metadata is present.

Like TraceIDFromContext, this reads back metadata a caller already stored with WithMetadata rather than resolving an active OpenTelemetry span context. This package provides no live tracing; the root ax package does.

func TraceIDFromContext

func TraceIDFromContext(ctx context.Context) string

TraceIDFromContext returns the explicit trace ID stored in ctx or ZeroTraceID when no trace metadata is present.

This reads back metadata a caller already stored with WithMetadata. It does not resolve an active OpenTelemetry span context: this package is import-isolated from the OpenTelemetry SDK and provides no live tracing, so a context that was never populated yields ZeroTraceID rather than a real trace ID. Live tracing comes from the root ax package, where ax.StartTelemetry installs W3C propagation and extracts TRACEPARENT, and ax.Execute opens a recording root span around the command.

func WithApproval added in v0.5.0

func WithApproval(ctx context.Context, granted bool) context.Context

WithApproval returns a context carrying the per-invocation confirmation decision.

func WithDryRun

func WithDryRun(ctx context.Context, dryRun bool) context.Context

WithDryRun returns a context carrying the dry-run state.

func WithIdempotencyKey

func WithIdempotencyKey(ctx context.Context, key string) context.Context

WithIdempotencyKey returns a context carrying the idempotency key for the run.

func WithMetadata

func WithMetadata(ctx context.Context, metadata Metadata) context.Context

WithMetadata returns a context carrying explicit machine-envelope metadata. Stored values are normalized on read by MetadataFromContext, so they are kept here as supplied.

func WithMode

func WithMode(ctx context.Context, mode Mode) context.Context

WithMode returns a context carrying the resolved output mode.

func WriteError

func WriteError(w io.Writer, err error) error

WriteError writes err as a strict minified JSON error envelope followed by a newline.

func WriteJSON

func WriteJSON(w io.Writer, v any) error

WriteJSON writes v as strict minified JSON followed by a newline.

func WriteJSONLine

func WriteJSONLine(w io.Writer, v any) error

WriteJSONLine writes a single NDJSON line.

Types

type Envelope

type Envelope[T any] struct {
	Data T        `json:"data"`
	Meta Metadata `json:"meta"`
}

Envelope is the standard bounded JSON success payload shape.

Example

ExampleEnvelope shows the generic success-envelope shape directly.

package main

import (
	"fmt"
	"os"

	"github.com/rshade/ax-go/contract"
)

func main() {
	env := contract.Envelope[string]{
		Data: "hello",
		Meta: contract.Metadata{TraceID: contract.ZeroTraceID},
	}
	if err := contract.WriteJSON(os.Stdout, env); err != nil {
		fmt.Println("error:", err)
	}
}
Output:
{"data":"hello","meta":{"trace_id":"00000000000000000000000000000000"}}

func NewEnvelope

func NewEnvelope[T any](ctx context.Context, data T) Envelope[T]

NewEnvelope wraps data with standard AX metadata from ctx.

Example

ExampleNewEnvelope shows the strict success envelope produced by the import-isolated contract package.

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/rshade/ax-go/contract"
)

func main() {
	type result struct {
		ID string `json:"id"`
	}

	env := contract.NewEnvelope(context.Background(), result{ID: "abc"})
	if err := contract.WriteJSON(os.Stdout, env); err != nil {
		fmt.Println("error:", err)
	}
}
Output:
{"data":{"id":"abc"},"meta":{"trace_id":"00000000000000000000000000000000","span_id":"0000000000000000"}}

type Error

type Error struct {
	ErrorCode     string         `json:"error_code"`
	Message       string         `json:"message"`
	TraceID       string         `json:"trace_id"`
	Tool          string         `json:"tool"`
	Version       string         `json:"version"`
	SchemaVersion string         `json:"schema_version"`
	ActionableFix string         `json:"actionable_fix,omitempty"`
	Context       map[string]any `json:"context,omitempty"`
	Suggestions   []string       `json:"suggestions,omitempty"`

	// Retryable is a tri-state retry-safety signal: a non-nil true means a naive
	// re-run of the same command is safe, a non-nil false means it MUST NOT be
	// retried, and nil (omitted) means unspecified. Absence is distinguishable
	// from explicit false so a consumer can tell "do not retry" from "unknown".
	Retryable *bool `json:"retryable,omitempty"`
	// RetryAfterSeconds is an advisory, relative backoff in whole seconds before
	// a retry should be attempted (delta-seconds, never an absolute timestamp, so
	// output stays byte-identical across runs). Meaningful only when Retryable is
	// true; omitted when unset or zero.
	RetryAfterSeconds int64 `json:"retry_after_seconds,omitempty"`
	// contains filtered or unexported fields
}

Error is the structured error envelope emitted to stderr.

func NewError

func NewError(ctx context.Context, code, message string, opts ...ErrorOption) *Error

NewError builds a structured error envelope using explicit metadata from ctx.

Example

ExampleNewError shows a structured error envelope and its deterministic exit code without importing the root runtime package.

package main

import (
	"context"
	"fmt"

	"github.com/rshade/ax-go/contract"
)

func main() {
	err := contract.NewError(
		context.Background(),
		"config_too_large",
		"config exceeds maximum size of 1048576 bytes",
		contract.WithActionableFix("reduce the config or raise the limit"),
		contract.WithErrorExitCode(contract.ExitValidation),
	)

	fmt.Println(err)
	fmt.Println(contract.ErrorExitCode(err))
}
Output:
config exceeds maximum size of 1048576 bytes
2

func (*Error) Error

func (e *Error) Error() string

Error returns the human-readable error message.

func (*Error) ExitCode

func (e *Error) ExitCode() int

ExitCode returns the deterministic process exit code associated with e.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap returns the underlying cause attached via WithErrorCause.

type ErrorOption

type ErrorOption func(*Error)

ErrorOption configures a structured Error.

func WithActionableFix

func WithActionableFix(fix string) ErrorOption

WithActionableFix sets a best-effort remediation hint.

func WithErrorCause

func WithErrorCause(err error) ErrorOption

WithErrorCause attaches the underlying source error to the envelope.

func WithErrorContext

func WithErrorContext(fields map[string]any) ErrorOption

WithErrorContext merges domain-specific context fields into the envelope.

func WithErrorExitCode

func WithErrorExitCode(code int) ErrorOption

WithErrorExitCode sets the deterministic process exit code.

func WithErrorTool

func WithErrorTool(tool string) ErrorOption

WithErrorTool sets the emitting tool name.

func WithErrorVersion

func WithErrorVersion(version string) ErrorOption

WithErrorVersion sets the emitting tool version.

func WithRetryAfterSeconds added in v0.3.0

func WithRetryAfterSeconds(seconds int64) ErrorOption

WithRetryAfterSeconds sets a relative backoff hint, in whole seconds, before a retry should be attempted. The value is relative (delta-seconds), never an absolute timestamp, to preserve byte-identical output. A negative value is treated as no hint.

func WithRetryable added in v0.3.0

func WithRetryable(retryable bool) ErrorOption

WithRetryable records whether a naive retry of the failed command is safe. Passing true marks the failure as retryable, false marks it as explicitly non-retryable; not calling the option leaves the signal unspecified (omitted). The bool is stored as a tri-state so an explicit false is distinguishable from absence on the wire.

func WithSuggestions

func WithSuggestions(suggestions ...string) ErrorOption

WithSuggestions sets optional candidate recovery actions.

type Metadata

type Metadata struct {
	TraceID        string `json:"trace_id"                  ax:"nondeterministic"`
	SpanID         string `json:"span_id,omitempty"         ax:"nondeterministic"`
	IdempotencyKey string `json:"idempotency_key,omitempty" ax:"nondeterministic"`
	DryRun         bool   `json:"dry_run,omitempty"`
}

Metadata carries common machine-readable envelope fields.

func MetadataFromContext

func MetadataFromContext(ctx context.Context) Metadata

MetadataFromContext returns explicit metadata from ctx merged with dry-run and idempotency-key context helpers.

type Mode

type Mode string

Mode describes whether output should be optimized for agents or humans.

Example

ExampleMode shows output-mode precedence in the isolated contract package.

package main

import (
	"fmt"

	"github.com/rshade/ax-go/contract"
)

func main() {
	mode, err := contract.ResolveMode("", "", false)
	if err != nil {
		fmt.Println("error:", err)
		return
	}
	fmt.Println(mode)
}
Output:
json
const (
	// ModeJSON is the machine-readable mode used by agents and pipelines.
	ModeJSON Mode = "json"
	// ModeHuman is the human-readable mode used for interactive terminals.
	ModeHuman Mode = "human"
)

func ModeFromContext

func ModeFromContext(ctx context.Context) (Mode, bool)

ModeFromContext returns the resolved output mode stored in ctx.

func ParseMode

func ParseMode(value string) (Mode, error)

ParseMode parses an explicit output mode.

func ResolveMode

func ResolveMode(explicitFormat, agentMode string, stdoutIsTTY bool) (Mode, error)

ResolveMode applies output-mode precedence: explicit --format flag, then AGENT_MODE, then TTY detection.

func (Mode) String

func (m Mode) String() string

String returns the wire value for the mode.

Jump to

Keyboard shortcuts

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