temporal

package
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package temporal defines shared Temporal signal and query name constants for the Pasture epoch workflow. All signal/query name strings are defined here (D10) to prevent name drift between callers (pasture-msg) and handlers (pastured workflows).

Package temporal implements the Temporal workflow layer for the Pasture epoch protocol. This file defines EpochStateMachine — a pure Go port of the Python state_machine.py. No Temporal SDK dependency; pure state transitions only.

Package temporal implements the Temporal workflow layer for the Pasture epoch protocol. EpochWorkflow is the durable top-level workflow; it wraps EpochStateMachine with signal/query handlers and Temporal search attributes.

Port of Python EpochWorkflow in scripts/aura_protocol/workflow.py.

Index

Constants

View Source
const (
	SignalAdvancePhase    = "advance_phase"
	SignalSubmitVote      = "submit_vote"
	SignalSliceProgress   = "slice_progress"
	SignalRegisterSession = "register_session"
)

Signal name constants for EpochWorkflow signal handlers. These are the Temporal signal names — they must match exactly between the sender (pasture-msg signal subcommands) and the receiver (pastured).

View Source
const (
	// SignalStartSlice configures the slice execution mode before run.
	SignalStartSlice = "start_slice"
	// SignalCompleteSlice provides an external completion override for the slice.
	SignalCompleteSlice = "complete_slice"
)

Signal name constants for SliceWorkflow signal handlers. These are the Temporal signal names for configuring and completing individual implementation slices.

View Source
const (
	QueryCurrentState         = "current_state"
	QueryAvailableTransitions = "available_transitions"
	QueryFullState            = "full_state"
	QuerySliceProgressState   = "slice_progress_state"
	QueryActiveSessions       = "active_sessions"
)

Query name constants for EpochWorkflow query handlers. These are the Temporal query names — they must match exactly between the querier (pasture-msg query subcommands) and the handler (pastured).

View Source
const (
	ActivityCheckConstraints     = "CheckConstraints"
	ActivityRecordTransition     = "RecordTransition"
	ActivityRecordAuditEvent     = "RecordAuditEvent"
	ActivityQueryAuditEvents     = "QueryAuditEvents"
	ActivityRecordSessionEntries = "RecordSessionEntries"
	ActivityQuerySessionEntries  = "QuerySessionEntries"
	ActivityRunAgentSession      = "RunAgentSession"
	ActivityDispatchHook         = "DispatchHook"
)

Activity type names used when referencing activities from workflow code via workflow.ExecuteActivity. These must match the exported method names on *Activities exactly, since Temporal registers struct methods by simple name.

View Source
const (
	EpochWorkflowType  = "EpochWorkflowFn"
	SliceWorkflowType  = "SliceWorkflowFn"
	ReviewWorkflowType = "reviewWorkflowFn"
)

WorkflowName returns the Temporal workflow type name for a given function. Used by pasture-msg signal/query commands to address the workflow.

View Source
const SADomain = "PastureDomain"

SADomain is the Temporal search attribute name for phase domain (KEYWORD).

View Source
const SAEpochId = "PastureEpochId"

SAEpochId is the Temporal search attribute name for epoch ID (TEXT — full-text search).

View Source
const SALastEventType = "PastureLastEventType"

SALastEventType is the Temporal search attribute name for the last audit event type (KEYWORD).

View Source
const SAPhase = "PasturePhase"

SAPhase is the Temporal search attribute name for the current phase (KEYWORD).

View Source
const SARole = "PastureRole"

SARole is the Temporal search attribute name for the current role (KEYWORD).

View Source
const SAStatus = "PastureStatus"

SAStatus is the Temporal search attribute name for workflow status (KEYWORD).

Variables

PhaseSpecs is the canonical transition table for the 12-phase epoch lifecycle. Port of Python PHASE_SPECS from scripts/aura_protocol/types.py.

Gate rules (enforced by EpochStateMachine, not by this table):

  • PhaseReview→PhasePlanReview and PhaseCodeReview→PhaseImplUAT require all 3 review axes to ACCEPT (consensus gate).
  • PhaseCodeReview→PhaseImplUAT additionally requires blocker_count == 0 (BLOCKER gate).
  • At PhaseReview/PhaseCodeReview with any REVISE vote, only the backward transition is available.

Functions

func EnsureSearchAttributes

func EnsureSearchAttributes(ctx context.Context, c OperatorServiceProvider, namespace string, logger *slog.Logger) error

EnsureSearchAttributes idempotently registers all required Aura search attributes with the Temporal namespace. Compares requiredSearchAttributes against the namespace's existing custom attributes and adds any that are missing. Safe to call on every pastured startup — already-registered attributes are skipped.

Port of Python ensure_search_attributes() in scripts/aura_protocol/workflow.py.

Args:

ctx:       Context for the gRPC calls.
c:         Temporal client providing OperatorService(). The standard
           client.Client from go.temporal.io/sdk/client satisfies this.
namespace: Temporal namespace name to register attributes in (e.g. "default").
           Must match the namespace used by the pastured worker.
logger:    Logger for the "registered" info message. Pass slog.Default() if nil.

Returns an error if the ListSearchAttributes or AddSearchAttributes call fails. A partial registration failure (adding one of N attributes) returns the error without retrying; call EnsureSearchAttributes again on next startup to catch up.

func RegisterWorkflows

func RegisterWorkflows(r interface {
	RegisterWorkflow(interface{})
	RegisterActivity(interface{})
}, acts *Activities)

RegisterWorkflows registers all Temporal workflows and activities with the given registry. Call this in pastured worker setup before starting the worker.

acts must not be nil. All exported methods on *Activities are registered as Temporal activities under their simple method names (e.g. "CheckConstraints").

Types

type Activities

type Activities struct {
	Trail           audit.Trail
	Tracker         protocol.TaskTracker
	HooksMgr        *hooks.Manager
	WellKnownAgents *tasks.WellKnownAgentCache
}

Activities bundles the dependencies required by all Pasture Temporal activities. Register an instance with the worker via RegisterWorkflows(w, acts).

All exported methods on *Activities are registered as Temporal activities. Temporal uses the simple method name as the activity type (e.g. "CheckConstraints").

Trail (legacy) and Tracker (S8) overlap intentionally during the PROPOSAL-2 transition window. Production wiring (cmd/pastured/main.go) sets BOTH fields against the unified pasture.db backend so that:

  • new code paths (RecordTransition, RecordAuditEvent — post-S8) use Tracker.RecordEventReturningId + AttachContext to land both the audit_events row and its context_edges(EpochContext, epochId) row;
  • legacy code paths (RunAgentSession's IndexingSessionHandler etc.) continue to call Trail.RecordSessionEntries / Trail.RecordEvent unchanged — they share the same SQLite file via the unified tracker (which satisfies audit.Trail by exposing the four audit signatures inline in pkg/protocol/tasktracker.go).

Tracker MAY be nil — when nil, RecordTransition / RecordAuditEvent fall back to the legacy Trail.RecordEvent path with no AttachContext (the pre-S8 behaviour). This is intentional for tests that exercise only the Trail surface (TestRecordTransition_WithTrail etc. in temporal_test.go); the production wiring always populates Tracker.

Trail must not be nil. HooksMgr may be nil — all hook dispatch is best-effort and a nil manager is a no-op.

WellKnownAgents (PROPOSAL-2 §7.7.3, S7) holds the in-memory cache of well-known automaton-name → provenance.AgentID minted at pastured startup. S8 activities consult this cache to attribute audit events to the correct SoftwareAgent (e.g. CheckConstraints uses the "pasture/automaton/check-constraints" AgentId). May be nil when activities are constructed for tests that do not exercise attribution; the activity must check before calling into the cache.

func (*Activities) CheckConstraints

func (a *Activities) CheckConstraints(ctx context.Context, state types.EpochState, toPhase protocol.PhaseId) ([]ConstraintViolation, error)

CheckConstraints validates a proposed phase transition against current epoch state and returns any constraint violations.

Activity: non-deterministic I/O boundary. Runs outside workflow code. Returns an empty slice when the transition is valid.

In v1, delegates to the state machine's ValidateAdvance logic. Future versions may incorporate external constraint sources (e.g. beads task state).

Args:

state:   Current epoch state snapshot.
toPhase: Proposed target phase.

func (*Activities) DispatchHook

func (a *Activities) DispatchHook(ctx context.Context, payload hooks.HookPayload) error

DispatchHook is a Temporal activity that dispatches a HookPayload to all registered handlers via the injected HooksMgr.

Behaviour:

  • If HooksMgr is nil, returns nil immediately. Hooks are optional — their absence must not fail workflows.
  • Otherwise, delegates to HooksMgr.Dispatch(ctx, payload) and returns any combined handler errors so the caller can log them.

Callers in activities and workflows should treat a non-nil return as a best-effort log signal, not as a hard failure.

func (*Activities) QueryAuditEvents

func (a *Activities) QueryAuditEvents(ctx context.Context, epochId string, phase *protocol.PhaseId, role *string) ([]protocol.AuditEvent, error)

QueryAuditEvents retrieves audit events for an epoch, with optional filters.

Activity: non-deterministic I/O boundary (reads from external store).

Args:

epochId: Required — the epoch to query events for.
phase:   Optional phase filter (nil = all phases).
role:    Optional role filter (nil = all roles).

func (*Activities) QuerySessionEntries

func (a *Activities) QuerySessionEntries(ctx context.Context, sessionId string) ([]protocol.SessionEntry, error)

QuerySessionEntries retrieves all session entries for the given sessionId.

Activity: non-deterministic I/O boundary (reads from external store).

Returns an empty (non-nil) slice when no entries exist for sessionId.

func (*Activities) RecordAuditEvent

func (a *Activities) RecordAuditEvent(ctx context.Context, event protocol.AuditEvent) error

RecordAuditEvent persists a generic AuditEvent to the trail.

Activity: non-deterministic I/O boundary. Used for non-transition events (vote recorded, session registered, etc.). When Tracker is wired (production path), this method also attaches a context_edges(EpochContext, epochId) row keyed by event.EpochId so the event is reachable via Timeline lookups alongside the transition events recorded by RecordTransition.

If event.EpochId is empty, the event is treated as free-floating: it lands in audit_events but no context_edges row is written here (free-floating events typically attach a non-epoch ContextKind via the helpers in internal/tasks/free_floating.go — Git/Skill/Session). The activity does NOT fall back to a default ContextKind to avoid silently mis-attributing workflow events.

Tracker may be nil for tests; in that case the activity falls back to the pre-S8 Trail.RecordEvent path with no AttachContext.

func (*Activities) RecordSessionEntries

func (a *Activities) RecordSessionEntries(ctx context.Context, entries []protocol.SessionEntry) error

RecordSessionEntries persists a batch of SessionEntry records to the audit trail.

Activity: non-deterministic I/O boundary. Nil or empty slices are no-ops. All entries are written atomically where the backend supports transactions.

func (*Activities) RecordTransition

func (a *Activities) RecordTransition(ctx context.Context, epochId string, record types.TransitionRecord) error

RecordTransition persists a transition record to the audit trail.

Activity: non-deterministic I/O boundary. PROPOSAL-2 §7.11 wiring:

  1. Validate epochId via provenance.ParseTaskID (§7.12 defense in depth — a malformed ID that slipped past CLI/handler validation is rejected here so no row leaks to audit_events / context_edges / tasks; Scenario 13).
  2. Resolve the agent_id for the canonical "transition-gate/consensus" well-known automaton (S7 cache lookup) so the recorded event is attributed to a SoftwareAgent. The Role field on the AuditEvent is set to the well-known agent's logical name; SqliteAuditTrail's resolveLegacyRoleAgentId re-uses the SAME agents_software row that S7 registered (find-by-name short-circuits before any INSERT runs), so the agent_id stamped on audit_events.agent_id matches the cache entry verifying Scenario 8b.
  3. Persist via Tracker.RecordEventReturningId — bundles the audit_events INSERT and the LastInsertId recovery into a single connection round-trip.
  4. Attach the epoch context via Tracker.AttachContext(eventId, ContextEpoch, epochId) so the event is reachable via Timeline lookups by epoch (PROPOSAL-2 §7.4 / §7.8 / Scenario 1).

Tracker may be nil for tests that exercise only the legacy Trail path; in that case the activity falls back to the pre-S8 Trail.RecordEvent code with no AttachContext. Production wiring (cmd/pastured/main.go) always populates Tracker against the unified pasture.db so the §7.11 happy path runs.

epochId is required to make audit events queryable by epoch. Pass the workflow input EpochId so events can be retrieved via QueryAuditEvents(epochId, ...).

func (*Activities) RunAgentSession

func (a *Activities) RunAgentSession(ctx context.Context, input RunAgentSessionInput) (*RunAgentSessionResult, error)

RunAgentSession starts an ACP-compatible agent process, streams its session updates, indexes them, and persists them to the audit trail on every update.

Activity: long-running I/O boundary. Blocks until the agent process exits or ctx is cancelled. Session entries are written incrementally on each update via the IndexingSessionHandler (per-update flush mode).

type ConstraintViolation

type ConstraintViolation struct {
	// Constraint is the machine-readable constraint ID (e.g. "consensus-gate").
	Constraint string `json:"constraint"`
	// Message is a human-readable description of what violated the constraint.
	Message string `json:"message"`
}

ConstraintViolation describes a single protocol constraint that was violated during a proposed phase transition.

type EpochInput

type EpochInput struct {
	EpochId            string `json:"epochId"`
	RequestDescription string `json:"requestDescription"`
}

EpochInput is the workflow input for EpochWorkflow.

type EpochResult

type EpochResult struct {
	EpochId                   string           `json:"epochId"`
	FinalPhase                protocol.PhaseId `json:"finalPhase"`
	TransitionCount           int              `json:"transitionCount"`
	SuccessfulTransitionCount int              `json:"successfulTransitionCount"`
	ConstraintViolationsTotal int              `json:"constraintViolationsTotal"`
}

EpochResult is the return value of EpochWorkflow when the epoch reaches COMPLETE.

func EpochWorkflowFn

func EpochWorkflowFn(ctx workflow.Context, input EpochInput) (*EpochResult, error)

EpochWorkflowFn is the top-level function registered with Temporal worker. It creates a fresh EpochWorkflow instance per execution (Temporal guarantee).

Signal routing uses workflow.Go goroutines (one per signal channel) because the Go SDK does not provide SetSignalHandlerWithContext. Query registration uses workflow.SetQueryHandler which does not pass ctx to the handler.

Exported so that tests can register and execute it directly via TestWorkflowEnvironment.RegisterWorkflow(temporal.EpochWorkflowFn).

type EpochStateMachine

type EpochStateMachine struct {
	// contains filtered or unexported fields
}

EpochStateMachine manages the 12-phase epoch lifecycle with phase transition validation and vote/blocker gate checks. Pure Go — no Temporal dependency.

Port of Python EpochStateMachine in scripts/aura_protocol/state_machine.py.

Usage:

sm := NewEpochStateMachine("epoch-123")
record, err := sm.Advance(protocol.P2_Elicit, "architect", "classification confirmed")
sm.RecordVote(types.AxisCorrectness, types.VoteAccept)
sm.RecordVote(types.AxisTestQuality, types.VoteAccept)
sm.RecordVote(types.AxisElegance, types.VoteAccept)
record, err = sm.Advance(protocol.P5_Uat, "reviewer", "all 3 vote ACCEPT")

func NewEpochStateMachine

func NewEpochStateMachine(epochId string, specs map[protocol.PhaseId]PhaseSpec) *EpochStateMachine

NewEpochStateMachine creates a new EpochStateMachine initialized to PhaseRequest. Accepts an optional specs map for dependency injection in tests; pass nil to use the canonical PhaseSpecs.

func (*EpochStateMachine) Advance

func (sm *EpochStateMachine) Advance(
	toPhase protocol.PhaseId,
	triggeredBy string,
	conditionMet string,
	timestamp time.Time,
) (*types.TransitionRecord, error)

Advance transitions the epoch to toPhase.

Validates first; returns TransitionError if invalid. On success:

  • Appends the current phase to CompletedPhases.
  • Sets CurrentPhase = toPhase.
  • Appends a TransitionRecord to TransitionHistory.
  • When entering P10_CodeReview, initializes severity tracking (not in Python; handled by S7).
  • Clears ReviewVotes (votes are phase-scoped).
  • Clears LastError.

timestamp is used for the record; pass time.Now() for production or a fixed time for determinism in tests. In the Temporal workflow, pass workflow.Now().

func (*EpochStateMachine) AvailableTransitions

func (sm *EpochStateMachine) AvailableTransitions() []protocol.PhaseId

AvailableTransitions returns the transitions currently available from the current phase, filtered by vote/blocker/consensus state.

Gate rule priority (highest first):

  1. REVISE gate: If at p4/p10 with any REVISE vote, only backward transition.
  2. Consensus gate: p4→p5 / p10→p11 excluded until all 3 axes ACCEPT.
  3. BLOCKER gate: p10→p11 excluded while blocker_count > 0.

Returns empty slice when current phase is Complete or has no spec.

func (*EpochStateMachine) HasConsensus

func (sm *EpochStateMachine) HasConsensus() bool

HasConsensus returns true if all 3 review axes have ACCEPT votes.

func (*EpochStateMachine) RecordBlocker

func (sm *EpochStateMachine) RecordBlocker(resolved bool)

RecordBlocker updates the blocker count. resolved=false: increment (new blocker); resolved=true: decrement (blocker resolved). Clamped to 0; cannot go negative.

func (*EpochStateMachine) RecordFailedTransition

func (sm *EpochStateMachine) RecordFailedTransition(
	fromPhase, toPhase protocol.PhaseId,
	timestamp time.Time,
	triggeredBy string,
	err error,
)

RecordFailedTransition appends a failed TransitionRecord to the transition history and records the error message in LastError.

This is the correct mutation path for failed advances in workflow.go — callers must not mutate State() directly (see State() doc). fromPhase and toPhase describe the attempted transition; err is the failure reason.

func (*EpochStateMachine) RecordVote

func (sm *EpochStateMachine) RecordVote(axis types.ReviewAxis, vote types.VoteType) error

RecordVote records a reviewer vote for the given axis. Overwrites any previous vote for the same axis.

Returns an error if axis is not a valid ReviewAxis value.

func (*EpochStateMachine) State

func (sm *EpochStateMachine) State() *types.EpochState

State returns the current epoch state. Callers must not modify the returned pointer directly; use RecordVote, RecordBlocker, and Advance instead.

func (*EpochStateMachine) ValidateAdvance

func (sm *EpochStateMachine) ValidateAdvance(toPhase protocol.PhaseId) []string

ValidateAdvance returns a list of violation strings for a proposed transition. An empty list means the transition is valid and Advance would succeed.

Checks (in order):

  1. Current phase is not COMPLETE.
  2. to_phase is in the transition table for the current phase.
  3. Consensus gate: p4→p5 / p10→p11 require HasConsensus().
  4. BLOCKER gate: p10→p11 requires BlockerCount == 0.

type EpochWorkflow

type EpochWorkflow struct {
	// contains filtered or unexported fields
}

EpochWorkflow is the durable Temporal workflow that drives the 12-phase epoch lifecycle. It wraps EpochStateMachine with Temporal signal/query handlers and updates search attributes on every phase transition for forensic queryability.

Signals (4):

  • advance_phase (PhaseAdvanceSignal) — request a phase transition
  • submit_vote (ReviewVoteSignal) — record a reviewer vote
  • slice_progress (SliceProgressSignal) — receive progress from child SliceWorkflow
  • register_session (RegisterSessionSignal) — register a Claude Code session

Queries (5):

  • current_state → *types.EpochState
  • available_transitions → []protocol.PhaseId
  • full_state → *types.QueryStateResult
  • slice_progress_state → []types.SliceProgressSignal
  • active_sessions → []types.RegisterSessionSignal

Design invariants:

  • No time.Now() in workflow code — use workflow.Now().
  • No I/O in workflow code — all I/O goes through activities.
  • Signal handlers enqueue; transitions happen in the run loop.
  • Search attributes updated via UpsertTypedSearchAttributes on every transition.

func (*EpochWorkflow) ActiveSessions

func (w *EpochWorkflow) ActiveSessions() []types.RegisterSessionSignal

ActiveSessions returns all registered sessions for this epoch.

func (*EpochWorkflow) AdvancePhase

func (w *EpochWorkflow) AdvancePhase(ctx workflow.Context, sig types.PhaseAdvanceSignal)

AdvancePhase is the signal handler for advance_phase signals.

func (*EpochWorkflow) AvailableTransitionsQuery

func (w *EpochWorkflow) AvailableTransitionsQuery() []protocol.PhaseId

AvailableTransitionsQuery returns the list of currently available phase transitions.

func (*EpochWorkflow) CurrentState

func (w *EpochWorkflow) CurrentState() (*types.EpochState, error)

CurrentState returns a snapshot of the current epoch runtime state.

func (*EpochWorkflow) FullState

func (w *EpochWorkflow) FullState() (*types.QueryStateResult, error)

FullState returns a serialization-safe snapshot of epoch state for CLI consumers.

func (*EpochWorkflow) RegisterSession

func (w *EpochWorkflow) RegisterSession(ctx workflow.Context, sig types.RegisterSessionSignal)

RegisterSession is the signal handler for register_session signals. Idempotent: duplicate session IDs are silently ignored.

func (*EpochWorkflow) Run

func (w *EpochWorkflow) Run(ctx workflow.Context, input EpochInput) (*EpochResult, error)

Run is the EpochWorkflow entry point. Initializes the state machine, sets initial search attributes, then drives the main signal loop until COMPLETE.

func (*EpochWorkflow) SliceProgress

func (w *EpochWorkflow) SliceProgress(ctx workflow.Context, sig types.SliceProgressSignal)

SliceProgress is the signal handler for slice_progress signals from child SliceWorkflows.

func (*EpochWorkflow) SliceProgressState

func (w *EpochWorkflow) SliceProgressState() []types.SliceProgressSignal

SliceProgressState returns all accumulated slice progress signals.

func (*EpochWorkflow) SubmitVote

func (w *EpochWorkflow) SubmitVote(ctx workflow.Context, sig types.ReviewVoteSignal)

SubmitVote is the signal handler for submit_vote signals.

type OperatorServiceProvider

type OperatorServiceProvider interface {
	OperatorService() operatorservice.OperatorServiceClient
}

OperatorServiceProvider is the narrow interface required by EnsureSearchAttributes. client.Client from go.temporal.io/sdk/client satisfies this interface via its OperatorService() method.

Exposing only this narrow interface makes the function trivially testable without depending on the full client.Client type.

type PhaseSpec

type PhaseSpec struct {
	// Transitions lists all target PhaseIds reachable from this phase.
	Transitions []protocol.PhaseId
}

PhaseSpec describes the allowed forward/backward transitions from one phase.

type ReviewInput

type ReviewInput struct {
	EpochId string `json:"epochId"`
	PhaseId string `json:"phaseId"`
}

ReviewInput is the workflow input for ReviewPhaseWorkflow.

type ReviewPhaseWorkflow

type ReviewPhaseWorkflow struct {
	// contains filtered or unexported fields
}

ReviewPhaseWorkflow is the child workflow for P4_Review or P10_CodeReview.

Receives ReviewVoteSignal signals from reviewer agents via SubmitVote(). Waits using workflow.Await() until all 3 ReviewAxis members (Correctness, TestQuality, Elegance) have cast their vote, then returns a ReviewResult with the complete vote mapping.

Signal routing: EpochWorkflow can forward ReviewVoteSignal to this child via the external workflow handle if desired. Alternatively, reviewer agents send signals directly to the ReviewPhaseWorkflow instance.

Port of Python ReviewPhaseWorkflow in scripts/aura_protocol/workflow.py.

func (*ReviewPhaseWorkflow) Run

Run waits for all 3 ReviewAxis members to vote, then returns results.

Blocks via workflow.Await() until all 3 axes (Correctness, TestQuality, Elegance) have submitted votes. Returns a ReviewResult with the full vote mapping.

func (*ReviewPhaseWorkflow) SubmitVote

SubmitVote is the signal handler for reviewer votes. Idempotent: if the same axis votes again, the later vote overwrites.

type ReviewResult

type ReviewResult struct {
	PhaseId    string                              `json:"phaseId"`
	Success    bool                                `json:"success"`
	VoteResult map[types.ReviewAxis]types.VoteType `json:"voteResult"`
}

ReviewResult is the return value of ReviewPhaseWorkflow.

func ReviewWorkflowFn

func ReviewWorkflowFn(ctx workflow.Context, input ReviewInput) (*ReviewResult, error)

ReviewWorkflowFn is the top-level function registered with the Temporal worker. Exported for test registration via TestWorkflowEnvironment.RegisterWorkflow.

type RunAgentSessionInput

type RunAgentSessionInput struct {
	// AgentCmd is the agent binary or command to execute (e.g. "claude").
	AgentCmd string `json:"agentCmd"`
	// AgentArgs are the command-line arguments passed to the agent binary.
	AgentArgs []string `json:"agentArgs"`
	// EpochId is the Pasture epoch this session belongs to.
	// Used to correlate session entries with epoch audit events.
	EpochId string `json:"epochId"`
}

RunAgentSessionInput is the input for the RunAgentSession activity.

type RunAgentSessionResult

type RunAgentSessionResult struct {
	// EntriesRecorded is the total number of SessionEntry rows written to the audit trail.
	EntriesRecorded int `json:"entriesRecorded"`
	// SessionId is the ACP session identifier for the completed session.
	// Empty when the agent produced no session/update messages.
	SessionId string `json:"sessionId,omitempty"`
	// StopReason is the ACP stop_reason from the final session update.
	// Empty when the session ended without an explicit stop reason.
	StopReason string `json:"stopReason,omitempty"`
}

RunAgentSessionResult summarises the outcome of a RunAgentSession activity call.

type SliceCompleteSignal

type SliceCompleteSignal struct {
	Success bool    `json:"success"`
	Output  string  `json:"output,omitempty"`
	Error   *string `json:"error,omitempty"`
}

SliceCompleteSignal is the signal payload for external completion override. When received, the slice adopts the reported outcome instead of the computed one.

type SliceInput

type SliceInput struct {
	EpochId          string `json:"epochId"`
	SliceId          string `json:"sliceId"`
	PhaseSpec        string `json:"phaseSpec"` // human-readable; serializable future
	ParentWorkflowId string `json:"parentWorkflowId"`
}

SliceInput is the workflow input for SliceWorkflow.

type SliceResult

type SliceResult struct {
	SliceId string  `json:"sliceId"`
	Success bool    `json:"success"`
	Output  string  `json:"output,omitempty"`
	Error   *string `json:"error,omitempty"`
}

SliceResult is the return value of SliceWorkflow.

func SliceWorkflowFn

func SliceWorkflowFn(ctx workflow.Context, input SliceInput) (*SliceResult, error)

SliceWorkflowFn is the top-level function registered with the Temporal worker. Exported for test registration via TestWorkflowEnvironment.RegisterWorkflow.

type SliceStartSignal

type SliceStartSignal struct {
	// Mode controls how the slice is executed: "mock", "tmux", or "subprocess".
	Mode string `json:"mode"`
	// Command is the shell command to execute (tmux/subprocess mode only).
	Command string `json:"command"`
	// TimeoutSeconds overrides the default activity start-to-close timeout.
	TimeoutSeconds int `json:"timeoutSeconds"`
}

SliceStartSignal is the signal payload for configuring SliceWorkflow execution mode.

type SliceWorkflow

type SliceWorkflow struct {
	// contains filtered or unexported fields
}

SliceWorkflow is the child workflow for a single P9_Slice implementation slice.

Lifecycle:

  1. Parent (EpochWorkflow) starts SliceWorkflow with SliceInput.
  2. Workflow defaults to mock mode (immediate success) unless a SliceStartSignal is received before run begins.
  3. On completion, signals the parent EpochWorkflow via slice_progress using input.ParentWorkflowId. Signal delivery is best-effort; if the parent has already completed, the exception is caught and ignored (non-fatal).

Port of Python SliceWorkflow in scripts/aura_protocol/workflow.py.

func (*SliceWorkflow) CompleteSlice

func (sw *SliceWorkflow) CompleteSlice(_ workflow.Context, sig SliceCompleteSignal)

CompleteSlice is the signal handler for external completion override.

func (*SliceWorkflow) Run

func (sw *SliceWorkflow) Run(ctx workflow.Context, input SliceInput) (*SliceResult, error)

Run executes a single implementation slice.

Execution modes (from SliceStartSignal, defaults to "mock"):

  • "mock": Returns success immediately. Used in tests and CI mode.
  • "tmux" / "subprocess": Executes command via execute_slice_command activity.

After computation, waits briefly for a SliceCompleteSignal override (1 s timeout). If an override arrives, it replaces the computed result.

On completion, signals the parent EpochWorkflow via slice_progress. Signal delivery failure is non-fatal (parent may have already completed).

Hook dispatch (HookSliceStarted, HookSliceCompleted, HookSliceFailed) runs via DispatchHook activity calls. Hook failures are logged but never fail the workflow — hooks are optional, best-effort observability.

func (*SliceWorkflow) StartSlice

func (sw *SliceWorkflow) StartSlice(_ workflow.Context, sig SliceStartSignal)

StartSlice is the signal handler that configures slice execution before run.

type TransitionError

type TransitionError struct {
	Violations []string
}

TransitionError is returned by Advance when a proposed transition is invalid. Violations is always non-empty when returned.

func (*TransitionError) Error

func (e *TransitionError) Error() string

Jump to

Keyboard shortcuts

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