# internal/core/session

Package session defines the append-only evidence ledger and replay model.

## EntryWorkspaceBaseline

```go
const (
	// EntryWorkspaceBaseline records dirty workspace state before task execution begins.
	EntryWorkspaceBaseline = "workspace_baseline"
	// EntryManualEvidence records an operator disposition for a manual acceptance criterion.
	EntryManualEvidence = "manual_evidence"
	// EntryReceipt records a signed gate receipt in the append-only ledger.
	EntryReceipt = "receipt"
)
```

## EntryManualEvidence

```go
const (
	// EntryWorkspaceBaseline records dirty workspace state before task execution begins.
	EntryWorkspaceBaseline = "workspace_baseline"
	// EntryManualEvidence records an operator disposition for a manual acceptance criterion.
	EntryManualEvidence = "manual_evidence"
	// EntryReceipt records a signed gate receipt in the append-only ledger.
	EntryReceipt = "receipt"
)
```

## EntryReceipt

```go
const (
	// EntryWorkspaceBaseline records dirty workspace state before task execution begins.
	EntryWorkspaceBaseline = "workspace_baseline"
	// EntryManualEvidence records an operator disposition for a manual acceptance criterion.
	EntryManualEvidence = "manual_evidence"
	// EntryReceipt records a signed gate receipt in the append-only ledger.
	EntryReceipt = "receipt"
)
```

## AppendEntryWithOptions

```go
func AppendEntryWithOptions(s Session, entry Entry, opts ReplayOptions) Session
```

AppendEntryWithOptions advances a previously replayed session by one entry without replaying older entries. Callers must pass a trusted replayed session or fall back to ReplayWithOptions first.

## FirstWorkspaceBaseline

```go
func FirstWorkspaceBaseline(s Session) (Entry, bool)
```

FirstWorkspaceBaseline returns the first captured task workspace baseline.

## LatestCriterionEntry

```go
func LatestCriterionEntry(s Session, criterionID string) (Entry, bool)
```

LatestCriterionEntry returns the newest ledger event for criterionID. Callers must still validate the event against the current criterion contract.

## LatestManualEvidence

```go
func LatestManualEvidence(s Session, criterionID, phaseID, expectedKind, criterionType string) (Entry, bool)
```

LatestManualEvidence returns the newest manual-evidence event that matches the current criterion contract. A stale event is evidence history, not a passing disposition for a changed criterion.

## LedgerGenesisHead

```go
func LedgerGenesisHead() string
```

LedgerGenesisHead returns the starting head for sessions with no receipts.

## New

```go
func New(taskID string, now string) Session
```

New creates an empty session ledger for taskID.

## NextLedgerHead

```go
func NextLedgerHead(priorLedgerHead string, receiptDigest string) string
```

NextLedgerHead derives the next receipt-chain head from the prior head and receipt digest.

## OrderedCriterionIDs

```go
func OrderedCriterionIDs(s Session) []string
```

OrderedCriterionIDs returns criterion state keys in deterministic order.

## Replay

```go
func Replay(s Session) Session
```

Replay rebuilds derived criterion and phase state from session entries.

## ReplayWithOptions

```go
func ReplayWithOptions(s Session, opts ReplayOptions) Session
```

ReplayWithOptions rebuilds derived state and optionally checks receipt trust.

## WorkspaceBaselineSnapshot

```go
func WorkspaceBaselineSnapshot(entry Entry) []string
```

WorkspaceBaselineSnapshot decodes the raw changed-file snapshot from an entry.

## Entry

```go
type Entry struct {
	ID                      string   `json:"id,omitempty"`
	Type                    string   `json:"type"`
	RecordedAt              string   `json:"recorded_at"`
	CriterionID             string   `json:"criterion_id,omitempty"`
	PhaseID                 string   `json:"phase_id,omitempty"`
	Status                  string   `json:"status,omitempty"`
	Reason                  string   `json:"reason,omitempty"`
	Provider                string   `json:"provider,omitempty"`
	Command                 string   `json:"command,omitempty"`
	ExpectedKind            string   `json:"expected_kind,omitempty"`
	CriterionType           string   `json:"criterion_type,omitempty"`
	ExitCode                int      `json:"exit_code,omitempty"`
	Output                  string   `json:"output,omitempty"`
	Path                    string   `json:"path,omitempty"`
	ReceiptDigest           string   `json:"receipt_digest,omitempty"`
	LedgerHead              string   `json:"ledger_head,omitempty"`
	TrustStatus             string   `json:"trust_status,omitempty"`
	TrustReason             string   `json:"trust_reason,omitempty"`
	ReviewPacket            string   `json:"review_packet,omitempty"`
	CanonicalResponseSHA256 string   `json:"canonical_response_sha256,omitempty"`
	ProviderModel           string   `json:"provider_model,omitempty"`
	ProviderSession         string   `json:"provider_session,omitempty"`
	AttemptID               string   `json:"attempt_id,omitempty"`
	LeaseExpiresAt          string   `json:"lease_expires_at,omitempty"`
	ReviewMode              string   `json:"review_mode,omitempty"`
	ReviewPassCount         int      `json:"review_pass_count,omitempty"`
	EvidenceDigest          string   `json:"evidence_digest,omitempty"`
	EvidenceActor           string   `json:"evidence_actor,omitempty"`
	ReviewedHead            string   `json:"reviewed_head,omitempty"`
	ReviewedDirty           string   `json:"reviewed_dirty,omitempty"`
	ReviewedDiff            string   `json:"reviewed_diff,omitempty"`
	ReviewedSpec            string   `json:"reviewed_spec,omitempty"`
	ReviewedScope           []string `json:"reviewed_scope,omitempty"`
	ReviewedMaterialDigest  string   `json:"reviewed_material_digest,omitempty"`
}
```

Entry is one append-only evidence event in a session ledger.

- `ID: string` (json:"id,omitempty"): 
- `Type: string` (json:"type"): 
- `RecordedAt: string` (json:"recorded_at"): 
- `CriterionID: string` (json:"criterion_id,omitempty"): 
- `PhaseID: string` (json:"phase_id,omitempty"): 
- `Status: string` (json:"status,omitempty"): 
- `Reason: string` (json:"reason,omitempty"): 
- `Provider: string` (json:"provider,omitempty"): 
- `Command: string` (json:"command,omitempty"): 
- `ExpectedKind: string` (json:"expected_kind,omitempty"): 
- `CriterionType: string` (json:"criterion_type,omitempty"): 
- `ExitCode: int` (json:"exit_code,omitempty"): 
- `Output: string` (json:"output,omitempty"): 
- `Path: string` (json:"path,omitempty"): 
- `ReceiptDigest: string` (json:"receipt_digest,omitempty"): 
- `LedgerHead: string` (json:"ledger_head,omitempty"): 
- `TrustStatus: string` (json:"trust_status,omitempty"): 
- `TrustReason: string` (json:"trust_reason,omitempty"): 
- `ReviewPacket: string` (json:"review_packet,omitempty"): 
- `CanonicalResponseSHA256: string` (json:"canonical_response_sha256,omitempty"): 
- `ProviderModel: string` (json:"provider_model,omitempty"): 
- `ProviderSession: string` (json:"provider_session,omitempty"): 
- `AttemptID: string` (json:"attempt_id,omitempty"): 
- `LeaseExpiresAt: string` (json:"lease_expires_at,omitempty"): 
- `ReviewMode: string` (json:"review_mode,omitempty"): 
- `ReviewPassCount: int` (json:"review_pass_count,omitempty"): 
- `EvidenceDigest: string` (json:"evidence_digest,omitempty"): 
- `EvidenceActor: string` (json:"evidence_actor,omitempty"): 
- `ReviewedHead: string` (json:"reviewed_head,omitempty"): 
- `ReviewedDirty: string` (json:"reviewed_dirty,omitempty"): 
- `ReviewedDiff: string` (json:"reviewed_diff,omitempty"): 
- `ReviewedSpec: string` (json:"reviewed_spec,omitempty"): 
- `ReviewedScope: []string` (json:"reviewed_scope,omitempty"): 
- `ReviewedMaterialDigest: string` (json:"reviewed_material_digest,omitempty"): 

## ReceiptTrustChecker

```go
type ReceiptTrustChecker interface {
	CheckReceiptTrust(receipt.Envelope) error
}
```

ReceiptTrustChecker validates receipt key trust at replay time. The core session package owns replay mechanics but not trust-anchor loading, so callers inject key lifecycle checks through this narrow port.

- `CheckReceiptTrust: func(receipt.Envelope) error`: 

## ReplayOptions

```go
type ReplayOptions struct {
	ReceiptTrustChecker ReceiptTrustChecker
	SkipReceiptDecode   bool
}
```

ReplayOptions configures optional replay checks.

- `ReceiptTrustChecker: ReceiptTrustChecker`: 
- `SkipReceiptDecode: bool`: 

## Session

```go
type Session struct {
	SchemaVersion   int                    `json:"schema_version"`
	TaskID          string                 `json:"task_id"`
	CreatedAt       string                 `json:"created_at,omitempty"`
	UpdatedAt       string                 `json:"updated_at,omitempty"`
	Entries         []Entry                `json:"entries"`
	CriterionStates map[string]StateRecord `json:"criterion_states,omitempty"`
	PhaseBlocks     map[string]StateRecord `json:"phase_blocks,omitempty"`
	LedgerHead      string                 `json:"ledger_head,omitempty"`
	LedgerValid     bool                   `json:"ledger_valid,omitempty"`
	LedgerError     string                 `json:"ledger_error,omitempty"`
}
```

Session is the durable task evidence ledger plus replayed state indexes.

- `SchemaVersion: int` (json:"schema_version"): 
- `TaskID: string` (json:"task_id"): 
- `CreatedAt: string` (json:"created_at,omitempty"): 
- `UpdatedAt: string` (json:"updated_at,omitempty"): 
- `Entries: []Entry` (json:"entries"): 
- `CriterionStates: map[string]StateRecord` (json:"criterion_states,omitempty"): 
- `PhaseBlocks: map[string]StateRecord` (json:"phase_blocks,omitempty"): 
- `LedgerHead: string` (json:"ledger_head,omitempty"): 
- `LedgerValid: bool` (json:"ledger_valid,omitempty"): 
- `LedgerError: string` (json:"ledger_error,omitempty"): 

## AppendEntry

```go
func (s Session) AppendEntry(entry Entry) Session
```

AppendEntry advances a previously replayed session by one entry.

## WithEntry

```go
func (s Session) WithEntry(entry Entry) Session
```

WithEntry returns a replayed copy of the session with entry appended.

## StateRecord

```go
type StateRecord struct {
	Status         string `json:"status"`
	Reason         string `json:"reason,omitempty"`
	UpdatedAt      string `json:"updated_at,omitempty"`
	SourceID       string `json:"source_id,omitempty"`
	Command        string `json:"command,omitempty"`
	ExpectedKind   string `json:"expected_kind,omitempty"`
	CriterionType  string `json:"criterion_type,omitempty"`
	PhaseID        string `json:"phase_id,omitempty"`
	EvidenceDigest string `json:"evidence_digest,omitempty"`
	EvidenceActor  string `json:"evidence_actor,omitempty"`
}
```

StateRecord is the replayed state for a criterion or phase.

- `Status: string` (json:"status"): 
- `Reason: string` (json:"reason,omitempty"): 
- `UpdatedAt: string` (json:"updated_at,omitempty"): 
- `SourceID: string` (json:"source_id,omitempty"): 
- `Command: string` (json:"command,omitempty"): 
- `ExpectedKind: string` (json:"expected_kind,omitempty"): 
- `CriterionType: string` (json:"criterion_type,omitempty"): 
- `PhaseID: string` (json:"phase_id,omitempty"): 
- `EvidenceDigest: string` (json:"evidence_digest,omitempty"): 
- `EvidenceActor: string` (json:"evidence_actor,omitempty"):
