tasks

package
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

gate_reader.go is the read side of the gate decision: one snapshot of who holds which assignment episode, under which session claim.

A lifecycle hook asks the gate "may this actor act now?". This file answers that question from the store and nothing else. It reads, it never writes, and it never runs a policy: the decision is taken by the gate policy from the value this file seals.

The read has two halves with different owners. The SESSION CLAIM is a Pasture-owned table (pasture_session_claim), so it is read with Pasture's own SQL under Pasture's own busy tier. The ACTIVE OWNERSHIP is Provenance's, so it is read with exactly one call into Provenance's public query API. That single call is the whole read-side contract: no paging loop, no catch-up tail, no completeness certificate, and no private SQL against Provenance's tables.

The claim connection is RELEASED before the Provenance call, because both subsystems borrow the same *sql.DB (open_unified.go, the Provenance open) and the default pool is one connection. A public call issued while Pasture still held its claim lease would queue behind the connection the reader itself holds, and the borrowed handle's liveness precheck pings with a background context, so nothing in the caller's context ends that wait.

The release is a MECHANISM, not a guarantee, and the two-store read it belongs to has a semantic cost that is stated at the read itself in Snapshot: two reads, two snapshots, one decision.

Package tasks — open_ro.go

StatusReader is a lightweight, read-only reader for the audit trail used by the `pasture status` verb. It deliberately does NOT open a full protocol.TaskTracker (which runs schema migrations and creates directories): a pure-read status view must never modify the database.

Callers open the database themselves (typically via dbconn.OpenReadOnlyDB), verify the schema version with CheckSchemaVersion, and then wrap the handle with NewStatusReaderFromDB. The caller retains ownership of the *sql.DB and is responsible for closing it; StatusReader.Close is a no-op.

All queries are forwarded to the underlying *sql.DB in read-only mode.

Package tasks provides the small wiring layer between pasture's CLI and the Provenance task tracker library. It resolves the default database path, derives the default namespace, and centralises Tracker open semantics so every subcommand uses the same conventions.

Index

Constants

View Source
const (
	// EventGitCommit fires after a git commit completes (e.g., from a
	// Claude Code Stop hook firing after `git agent-commit`). Payload should
	// contain at least {"sha": "<commit-sha>"}.
	EventGitCommit protocol.EventType = "GitCommit"

	// EventGitPush fires after a git push completes. Payload should contain
	// at least {"refs": ["<branch>"], "remote": "<remote>"}.
	EventGitPush protocol.EventType = "GitPush"

	// EventGitRebase fires after a git rebase completes. Payload should
	// contain at least {"onto": "<base-ref>", "head": "<head-ref>"}.
	EventGitRebase protocol.EventType = "GitRebase"

	// EventSkillInvoked fires when a /pasture:* skill is invoked (per Pasture
	// URD R9). Payload should contain at least {"skill": "pasture:<name>"}.
	EventSkillInvoked protocol.EventType = "SkillInvoked"

	// EventSessionRecorded fires when a Claude Code session is recorded.
	// Payload should contain at least {"sessionId": "<id>"}.
	EventSessionRecorded protocol.EventType = "SessionRecorded"
)

Free-floating event types are open-string by design (§7.3 / §7.5). These constants are the canonical spellings used by the in-tree hook handlers and skill entry points; external plugins MAY define their own event_type values.

View Source
const (
	// DefaultGitRole is the canonical Role string written into
	// audit_events.role for git events recorded via RecordGitEvent. Matches
	// PROPOSAL-2 §7.7.2's pattern "pasture/automaton/hook/<hook-name>".
	DefaultGitRole = "pasture/automaton/hook/git-recorder"

	// DefaultSkillRole is the canonical Role string written into
	// audit_events.role for skill-invocation events recorded via
	// RecordSkillEvent.
	DefaultSkillRole = "pasture/automaton/hook/skill-recorder"

	// DefaultSessionRole is the canonical Role string written into
	// audit_events.role for Claude Code session events recorded via
	// RecordSessionEvent.
	DefaultSessionRole = "pasture/automaton/hook/session-recorder"
)

─── Default role attribution for free-floating events ──────────────────────

PROPOSAL-2 §7.7.2 enumerates well-known automaton names. The in-tree recorders in this file use the corresponding hook-handler names so that once S3's audit-side legacy-role compatibility shim resolves Role to an agent_id (and post-S8 when the workflow boundary supplies agent_id directly), free-floating events flow into the right pasture_agent_categories row. The role is overridable per call so plugins can attribute their own hook handlers without re-entering this file.

View Source
const DBPathEnv = "PASTURE_DB_PATH"

DBPathEnv is the environment variable users can set to override the default unified pasture database location (see DefaultDBPath).

View Source
const DBPoolSizeEnv = "PASTURE_DB_POOL_SIZE"

DBPoolSizeEnv is the environment variable that overrides the connection-pool size for the pasture-owned audit handle. When set, its integer value is used instead of DefaultDBPoolSize.

This is a production tuning knob. Tests should leave it unset (default 1).

View Source
const DefaultDBPoolSize = 1

DefaultDBPoolSize is the default connection-pool size for the pasture-owned audit handle.

A pool of 1 serialises writes at the Go level and is the proven-safe default: zero escaped SQLITE_BUSY errors under the cross-subsystem race test. SQLite WAL + the busy-timeout retry prevent data corruption at any pool size; this cap is a contention-serialisation choice only.

For production tuning, override with PASTURE_DB_POOL_SIZE after validating your storage throughput. A higher pool raises write concurrency but may surface SQLITE_BUSY under heavy contention.

View Source
const WellKnownAgentCount = 15

WellKnownAgentCount is the total number of canonical well-known agents registered at daemon startup (PROPOSAL-2 §7.7.2). It is exported so tests can assert the table size without re-counting; a divergence between this constant and len(WellKnownAgents()) is a programming error caught by init-time assertion in well_known_registry_init.go (or, equivalently, by the unit tests in well_known_test.go).

The breakdown is documented in the package-level comment above:

1 (ConstraintChecker)
+ 3 (TransitionGate)
+ 9 (HookHandler)
+ 1 (ConsensusReached)
+ 1 (CreateFollowup)
= 15
View Source
const WellKnownAgentNamespace = "pasture"

WellKnownAgentNamespace is the namespace string passed to `provenance.Tracker.RegisterSoftwareAgent`. All well-known agents live under the `pasture` namespace; this distinguishes them from human and ML agents (which use other namespaces) and from external software agents registered by other tools.

View Source
const WellKnownAgentSource = "github.com/dayvidpham/pasture"

WellKnownAgentSource is the `source` column written to `agents_software` when minting a well-known agent's Provenance row. It is set to the pasture repo URL so downstream PROV-O queries can discover the agent's provenance.

View Source
const WellKnownAgentVersion = "v1"

WellKnownAgentVersion is the `version` column written to `agents_software` when minting a well-known agent's Provenance row. It moves in lockstep with the daemon binary: bumping the daemon version does NOT re-register agents (idempotency is keyed on logical name, not version), so this string is effectively a stamp recording which binary version first observed the agent's absence.

Variables

FindingSeverities is the canonical ordered triple of severities.

ReviewAxes is the canonical ordered triple of axes a round is composed of.

Functions

func BindEngineGovernedAllocation added in v0.0.5

func BindEngineGovernedAllocation(tracker interface{}, runner composedAllocationRunner) error

BindEngineGovernedAllocation installs the narrow allocation capability built by the durable engine. It intentionally accepts no DBOS or SQL handle.

func CheckSchemaVersion added in v0.0.5

func CheckSchemaVersion(db *sql.DB, dbPath string) error

CheckSchemaVersion reads the audit schema version from an already-open read-only handle and returns a CategoryStorage error when it does not match audit.MaxKnownSchemaVersion.

This function is SELECT-only: it issues no writes, DDL, migration, or any operation that could alter the database. It is safe to call on a read-only handle opened next to a running daemon.

func CreateSliceAuditParticipant added in v0.0.5

CreateSliceAuditParticipant is retained for callers compiled against the initial narrow binding name. All governed allocations share the participant.

func DecodeDecision added in v0.0.5

func DecodeDecision[T any](
	catalog DecisionCatalog,
	descriptor DecisionDescriptor[T],
	encoding DecisionEncoding,
) (T, error)

DecodeDecision decodes a stored encoding to its typed value using the supplied descriptor, but only after confirming the catalog registers that exact descriptor token for the encoding's kind and that the identities agree; it then decodes, validates, and requires the re-encoding to be byte-identical.

func DefaultDBPath

func DefaultDBPath() string

DefaultDBPath returns the conventional path for the unified pasture database, used by both the `pasture` CLI and the `pastured` daemon (PROPOSAL-2 §7.1).

Resolution order:

  1. $PASTURE_DB_PATH
  2. $XDG_DATA_HOME/pasture/pasture.db
  3. $HOME/.local/share/pasture/pasture.db
  4. .pasture/pasture.db (last-resort relative fallback when $HOME is unset)

The directory is NOT created here; the caller (typically OpenTaskTracker or OpenTracker) calls os.MkdirAll on filepath.Dir of the result before the file is opened for writing.

func DefaultNamespace

func DefaultNamespace() (string, error)

DefaultNamespace returns the namespace URI that pasture uses when the user has not specified --namespace explicitly. It delegates to the Provenance namespace package so the same derivation rules apply across the toolkit.

func EvaluatePlanDeferral added in v0.0.5

func EvaluatePlanDeferral(in PlanDeferralInput) error

EvaluatePlanDeferral reports whether an AFK Plan deferral is eligible to be recorded. It returns nil when eligible and an actionable error naming the exact failed precondition otherwise.

func EvaluateRatify added in v0.0.5

func EvaluateRatify(policy PolicySet, in RatifyInput) error

EvaluateRatify reports whether a recorded AFK Plan deferral may be ratified against the current ledger. It folds the current ledger's effective mode cursor and requires that cursor to still be AFK and anchored to the exact mode entry the deferral recorded. Any later mode entry (of any target mode) makes the deferral ineligible; a fresh deferral is then required. It returns nil when eligible and an actionable error otherwise.

policy is passed through to EffectiveMode explicitly; EvaluateRatify holds no package-level or process-global PolicySet of its own.

func GovernedAllocationAuditParticipant added in v0.0.5

GovernedAllocationAuditParticipant persists Pasture's projection inside the governed allocation transaction. Engine.New is its sole production composition site.

func LifecycleSession added in v0.0.9

func LifecycleSession(bindings []model.NativeBinding) (string, error)

LifecycleSession is the exported face of the helper above, and it exists for the one caller that cannot reach an unexported name in this package: the lifecycle gate, which asks the SAME question of the SAME bindings before it reads a claim. Two loops over the bindings could disagree about which one is the session — one reading a verified binding as an identity and the other skipping it — and the gate would then look up a session nobody ever claimed, which reads as an unbound session and proceeds. So the answer has one home.

func MapMaterialEvent added in v0.0.5

func MapMaterialEvent(ev MaterialEvent) (provenance.Effect, error)

MapMaterialEvent validates a material event and maps it to exactly one journal EffectTaskEvent: the family's fixed EventKind, the event's source task, its opaque canonical payload, and its validated secondary contexts. Family() is a method on each sealed concrete type and returns a compile-time constant, so a value cannot carry a family that disagrees with its payload shape; a family that fails to resolve to a legal journal kind (the zero/unknown sentinel, or a fixed kind that somehow breaks the journal grammar) is rejected rather than journaled under a wrong or empty kind. This is the single place the portable material-event domain and the durable journal domain meet.

func NewGateReader added in v0.0.9

func NewGateReader(tracker protocol.TaskTracker, harness ir.HarnessID, session string) (gateauthority.Reader, error)

NewGateReader returns the reader the lifecycle gate consults. harness and session are the identity the hook was invoked with; the reader answers about exactly that session and no other.

The tracker must be the unified Pasture store. A reader that cannot reach the Pasture-owned claim table would answer about ownership without knowing who it is answering for, so construction refuses such a tracker instead of deferring the fault to the first lifecycle invocation.

func NewLifecycleBlobStore added in v0.0.9

func NewLifecycleBlobStore(tracker protocol.TaskTracker) (receipt.SQLiteBlobStore, error)

NewLifecycleBlobStore binds the payload blob store to the unified database for READ-ONLY inspection. It is the seam an operator read surface uses to ask how many payload blobs no occurrence names; it grants no write path that receipt.Service does not already own.

func NewLifecycleReader added in v0.0.5

func NewLifecycleReader(tracker protocol.TaskTracker) (model.LifecycleReader, error)

NewLifecycleReader returns the public bounded lifecycle reader backed by the disposable replay-derived projection.

func NewLifecycleReceiptService added in v0.0.5

func NewLifecycleReceiptService(tracker protocol.TaskTracker, clock receipt.Clock, operations receipt.OperationIDSource) (receipt.Service, error)

NewLifecycleReceiptService wires the production receipt path to the unified database and Provenance journal while keeping clocks and operation IDs injected.

func NewLifecycleReceiptServiceWithProfile added in v0.0.5

func NewLifecycleReceiptServiceWithProfile(tracker protocol.TaskTracker, clock receipt.Clock, operations receipt.OperationIDSource, profile timeouts.Profile) (receipt.Service, error)

func OpenAuditDBForFreeFloating

func OpenAuditDBForFreeFloating(dbPath string) (*sql.DB, error)

OpenAuditDBForFreeFloating opens an auxiliary *sql.DB handle on the same pasture.db file that protocol.TaskTracker writes to, with the same WAL + busy_timeout pragmas openTaskTrackerImpl applies. It exists so callers outside internal/tasks (e.g. cmd/pastured wiring code, test code) can obtain a direct SQL handle for ad-hoc queries or pasture-specific table writes without depending on internal trackerImpl details.

Note: the free-floating recording helpers (RecordGitEvent / RecordSkillEvent / RecordSessionEvent) no longer require this handle internally — they now use tracker.RecordEventReturningId which bundles the write + id recovery. The handle is still accepted as a parameter by those helpers for API compatibility.

The returned handle MUST be closed by the caller; typically callers cache it for the lifetime of the daemon and Close it at shutdown.

dbPath: the SAME path used to open the TaskTracker. Empty string resolves to DefaultDBPath() (matching openTaskTrackerImpl's behaviour).

Errors are *pasterrors.StructuredError with CategoryConnection (file open failure) or CategoryStorage (PRAGMA failure).

This helper is a thin re-export of openAuditHandle so the rest of the tree (cmd/pastured, hooks/git_recorder.go) doesn't need access to package-private names.

func OpenTaskTracker

func OpenTaskTracker(dbPath string) (protocol.TaskTracker, error)

OpenTaskTracker opens the unified pasture.db SQLite file at dbPath, runs the audit migrator, opens the Provenance tracker on the same file, and returns a wrapped protocol.TaskTracker.

dbPath: filesystem path to the unified database. Empty string resolves to DefaultDBPath (honours $PASTURE_DB_PATH and $XDG_DATA_HOME). Parent directories are created if they do not exist.

Errors are *pasterrors.StructuredError with category:

  • CategoryConnection (exit 2): file/dir cannot be opened.
  • CategoryStorage (exit 5): migration or DDL failure.
  • CategoryValidation (exit 1): newer-schema rejection.

Callers MUST call Close on the returned tracker to release file handles.

This is the in-package entry point. External callers should use protocol.OpenTaskTracker, which is wired through init() above.

func OpenTaskTrackerWithOptions added in v0.0.5

func OpenTaskTrackerWithOptions(dbPath string, opts ...OpenTaskTrackerOption) (protocol.TaskTracker, error)

OpenTaskTrackerWithOptions opens the unified tracker with explicit opt-in behavior for tests that copy a current golden database.

func OpenTracker

func OpenTracker(dbPath string) (provenance.Tracker, error)

OpenTracker opens the Provenance tracker at dbPath, creating any missing parent directories along the way. An empty dbPath resolves to DefaultDBPath.

On failure the returned error is a *pasterrors.StructuredError with CategoryConnection, so callers can map it to exit code 2 via pasterrors.ExitCode.

func RebuildLifecycleOccurrences added in v0.0.5

func RebuildLifecycleOccurrences(ctx context.Context, tracker protocol.TaskTracker) error

RebuildLifecycleOccurrences derives the disposable occurrence projection exclusively from journal truth and, inside the same transaction, reclaims orphan payload blobs older than the writer window, up to the projection package's cap. Every read command that rebuilds the projection reaches the reclaim through here; there is no rebuild without it. A reclaim failure never fails the rebuild: this wrapper prints the ONE failure line on the store's own diagnostic sink and returns nil, and it prints nothing on success. Callers that report the numbers use RebuildLifecycleOccurrencesReporting.

func RebuildLifecycleOccurrencesReporting added in v0.0.9

func RebuildLifecycleOccurrencesReporting(ctx context.Context, tracker protocol.TaskTracker) (projection.ReclaimOutcome, error)

RebuildLifecycleOccurrencesReporting is RebuildLifecycleOccurrences with the reclaim's outcome returned, so a command that reports orphans can print what this run reclaimed from data rather than from a side effect. The options the rebuild needs come from what the store already holds: its timeout profile for the window, its clock for the snapshot instant. The failure line, if any, has already been written to the store's sink when this returns.

func RecordGitEvent

func RecordGitEvent(
	ctx context.Context,
	tracker protocol.TaskTracker,
	auditDB *sql.DB,
	sha string,
	eventType protocol.EventType,
	payload map[string]any,
) (int64, error)

RecordGitEvent records a free-floating git event (commit, push, rebase) to audit_events and attaches a ContextGit edge keyed by the supplied SHA / ref.

Parameters:

  • ctx: context for cancellation; propagates to RecordEventReturningId and AttachContext.
  • tracker: the unified TaskTracker (typically obtained from OpenTaskTracker). MUST be non-nil.
  • auditDB: retained for API compatibility with existing callers; no longer used by the implementation (RecordEventReturningId bundles write + id recovery atomically, removing the need for a separate SELECT MAX round-trip). MAY be nil without causing a validation error.
  • sha: the git commit SHA (or remote ref for pushes / base-ref for rebases). Used as the context_id of the ContextGit edge. MUST be non-empty; an empty sha would create a row no Timeline lookup can match.
  • eventType: usually one of EventGitCommit / EventGitPush / EventGitRebase above; callers MAY pass any non-empty string per §7.3 / §7.5 open-string convention.
  • payload: free-form key/value pairs. Should include {"sha": sha} for symmetry with the context edge; not enforced.

The recorded AuditEvent's Role field is set to DefaultGitRole — the canonical hook-handler name from PROPOSAL-2 §7.7.2's "pasture/automaton/hook/<name>" pattern. S3's audit-side legacy-role shim resolves this to an agent_id; post-S8 the workflow boundary will supply agent_id directly.

On success returns the int64 audit_events.id of the newly-inserted row so callers can attach further contexts (e.g., a post-epoch commit citing epoch X also gets ContextEpoch — see §11 Scenario 7 multi-context attachment).

Errors are *pasterrors.StructuredError with one of:

  • CategoryValidation: nil tracker, empty sha, or an empty eventType (the underlying audit store would silently accept these but they're programming errors here).
  • CategoryStorage: RecordEventReturningId / AttachContext write failure (file unwritable, schema drift, etc.). Underlying error wrapped via pasterrors.StructuredError.Why.

func RecordSessionEvent

func RecordSessionEvent(
	ctx context.Context,
	tracker protocol.TaskTracker,
	auditDB *sql.DB,
	sessionId string,
	eventType protocol.EventType,
	payload map[string]any,
) (int64, error)

RecordSessionEvent records a free-floating Claude Code session event to audit_events and attaches a ContextSession edge keyed by the supplied session id.

See RecordGitEvent for the parameter / error contract; only the context kind (ContextSession) and the suggested EventType (EventSessionRecorded) differ.

Note: pasture also has a separate session_entries table (R6 — sub-PROV-O granularity for ACP SessionUpdate streams) reached via tracker.RecordSessionEntries; that path is for storing the streamed session content. RecordSessionEvent here records the higher-level "a session happened" event so it shows up in the audit timeline alongside epoch transitions and git events.

func RecordSkillEvent

func RecordSkillEvent(
	ctx context.Context,
	tracker protocol.TaskTracker,
	auditDB *sql.DB,
	skillRunId string,
	eventType protocol.EventType,
	payload map[string]any,
) (int64, error)

RecordSkillEvent records a free-floating skill-invocation event to audit_events and attaches a ContextSkill edge keyed by the supplied skill run id (e.g., "pasture:user-elicit-<run-id>").

See RecordGitEvent for the parameter / error contract; only the context kind (ContextSkill) and the suggested EventType (EventSkillInvoked) differ.

`skillRunId` is the canonical id of the skill invocation. Per PROPOSAL-2 §7.3 example: "pasture:user-elicit-<run-id>" — the wire string is whatever the caller wants to use for Timeline lookups via `pasture task events --context-kind=SkillContext --context-id=<run-id>`.

func RegisterWellKnownAgents

func RegisterWellKnownAgents(ctx context.Context, tracker protocol.TaskTracker, cache *WellKnownAgentCache) error

RegisterWellKnownAgents mints (or recovers) every entry in WellKnownAgents() against the supplied tracker and populates cache.

Idempotency contract: two consecutive calls against the same underlying database produce identical row counts in `agents`, `agents_software`, `pasture_well_known_agents`, and `pasture_agent_categories`, AND identical AgentIDs in `pasture_well_known_agents` (pointwise across startups).

tracker MUST implement auditDBHolder (i.e. it must expose an audit *sql.DB handle via auditDBHandle). Both the production *trackerImpl and any test fake that wires up a real *sql.DB satisfy this. Callers that pass a tracker without the method get a CategoryConfig *StructuredError pointing at the wiring error.

cache MUST be non-nil. After successful return, cache contains exactly WellKnownAgentCount entries; on any error, cache may contain a strict subset (entries up to and including the failure point are populated; later entries are not). Partial population is safe for restart recovery — the missing entries get filled in on the next call because of the fast-path on lookup hit.

Errors are *pasterrors.StructuredError categorised as:

  • CategoryConfig (exit 4): tracker is nil, does not implement auditDBHolder, or its auditDBHandle() returns nil; cache is nil.
  • CategoryStorage (exit 5): SQLite read/write or transaction failure.
  • CategoryWorkflow (exit 3): Provenance RegisterSoftwareAgent failure.

The function takes ctx for cancellation; long-running registrations (15 entries × {1 SELECT + maybe 1 RegisterSoftwareAgent + 2 INSERTs}) take well under a second on local SQLite, so context-deadline rejection is primarily about clean shutdown if the daemon is killed during startup.

func ResolveDBPoolSize added in v0.0.5

func ResolveDBPoolSize() (int, error)

ResolveDBPoolSize resolves the effective connection-pool size for the pasture-owned audit handle from two sources, highest-priority first:

  1. $PASTURE_DB_POOL_SIZE (non-empty, parses as a positive int).
  2. DefaultDBPoolSize (1).

If the env var is set but not a valid positive integer, the function returns an actionable validation error (the caller should surface it and exit 1).

Tradeoff: the default of 1 is the proven-safe pool size (zero escaped SQLITE_BUSY in the cross-subsystem race test). A pool > 1 raises write concurrency on the pasture-owned handle but may surface SQLITE_BUSY under heavy contention. SQLite WAL + the busy-timeout retry prevent data corruption at any pool size; this setting is purely about contention serialisation.

This governs ONLY the pasture-owned audit handle (AttachContext, EventContexts, SetAgentCategories, Timeline). The audit-trail handle (RecordEvent) and the provenance handle each manage their own connection pool and are not affected.

func ResolveNamespace

func ResolveNamespace(explicit string) (string, error)

ResolveNamespace returns the namespace to use for a `create` operation. Explicit takes precedence; an empty value falls back to DefaultNamespace.

Errors from DefaultNamespace are wrapped as CategoryValidation so that the user is prompted to supply --namespace explicitly.

func SupportsEngineGovernedAllocation added in v0.0.5

func SupportsEngineGovernedAllocation(tracker interface{}) bool

SupportsEngineGovernedAllocation reports whether tracker can receive the engine-owned allocation capability. Activity-only sinks intentionally return false: recording transition activity must not require governed task creation.

func UnbindEngineGovernedAllocation added in v0.0.8

func UnbindEngineGovernedAllocation(tracker interface{}, runner composedAllocationRunner)

UnbindEngineGovernedAllocation removes a capability installed by BindEngineGovernedAllocation, so the tracker can accept another engine. Its caller is the durable engine's own construction-failure path: a half-built engine that kept the slot would leave the tracker pointing at a stopped durable context, and would make every later engine on that tracker fail to bind.

It removes the slot only when runner is the exact value that occupies it, so a stale unbind cannot detach a live engine. Removing an already-empty or differently-owned slot is a no-op; there is no error to act on.

func VerifyCoverage added in v0.0.5

func VerifyCoverage(stored CoverageDigest, spec CoverageDigestSpec) error

VerifyCoverage recomputes the coverage digest from spec and compares it to the stored digest, returning an actionable error on any mismatch. It is the pure core of land's invalidation check: the live land command reloads the accepted Implementation-UAT entry, recomputes its required set from the exact accepted inputs, and calls VerifyCoverage; a later ledger append changes the required set and fails this comparison.

Types

type ActivityInterval added in v0.0.5

type ActivityInterval struct {
	ActivityID provenance.ActivityID
	StartAt    int64
	EndAt      *int64
}

ActivityInterval is a task-linked Activity's duration. StartAt is the open stamp; EndAt is nil for a still-open interval and equal to StartAt for a point interval.

func (ActivityInterval) IsOpen added in v0.0.5

func (i ActivityInterval) IsOpen() bool

IsOpen reports an interval with no recorded end.

func (ActivityInterval) IsPoint added in v0.0.5

func (i ActivityInterval) IsPoint() bool

IsPoint reports a zero-duration interval (start == end).

type ActorClaim added in v0.0.9

type ActorClaim string

ActorClaim is the actor identifier supplied by the host environment. Its zero value means no claim. It is session state, never a receipt author. An unknown actor is retained as claimed; the authority reader decides whether it exists.

type AssertedHumanActor added in v0.0.5

type AssertedHumanActor struct {
	ActorID provenance.ActorID
}

AssertedHumanActor is the registered human explicitly selected for a user gate. It is asserted attribution; authentication may be attached as separate evidence.

type AssignmentAuthenticationError added in v0.0.9

type AssignmentAuthenticationError struct {
	// Function is the function in this file that raised the refusal. The Where
	// clause of the message names it, so every raise site supplies the function
	// it is written in as a literal and never the name of a caller: a caller is
	// not on the stack of the check, and a second caller would make one name
	// untrue for the other.
	Function string
	Step     string
	Cause    error
}

AssignmentAuthenticationError is a refusal before any write, never a policy denial. It is raised when a command could not authenticate the assignment it acts under.

func (*AssignmentAuthenticationError) Error added in v0.0.9

Error names what could not be authenticated, why the check exists, where it ran, when it ran relative to the write, what the caller lost, and what to do about it.

func (*AssignmentAuthenticationError) Unwrap added in v0.0.9

type AssignmentCompletedEvent added in v0.0.5

type AssignmentCompletedEvent struct {
	Task       provenance.TaskID
	Assignment provenance.AssignmentID
	Activity   provenance.ActivityID
	Occupant   provenance.ActorID
}

AssignmentCompletedEvent is a worker's typed completion record. It accompanies EndTaskActivity and never mutates task status. It carries the assignment and the activity it ended, plus the completing occupant.

func (AssignmentCompletedEvent) Family added in v0.0.5

func (AssignmentCompletedEvent) SourceTask added in v0.0.5

type AssignmentEpisode added in v0.0.5

type AssignmentEpisode struct {
	ID          provenance.AssignmentID
	Task        provenance.TaskID
	Role        AssignmentRole
	Occupant    provenance.ActorID
	Predecessor provenance.AssignmentID
	Parent      provenance.AssignmentID
	Active      bool
}

AssignmentEpisode is one projected assignment episode.

type AssignmentProjection added in v0.0.5

type AssignmentProjection struct {
	Episodes    map[provenance.AssignmentID]AssignmentEpisode
	OwnerByTask map[provenance.TaskID]provenance.ActorID
}

AssignmentProjection is the folded assignment state: every episode by id, and the derived current owner per task (the active owner-responsibility occupant).

func ProjectAssignments added in v0.0.5

func ProjectAssignments(transitions []AssignmentTransition) AssignmentProjection

ProjectAssignments folds transitions (applied in ascending Ordinal) into the current episodes and derived owner. A Started transition opens/re-activates an episode; an Ended transition deactivates it. Task.Owner is the occupant of the single active owner-responsibility episode for the task, so a responsibility transfer (end predecessor, start successor) atomically moves the owner. The input is never mutated.

func (AssignmentProjection) OwnerOf added in v0.0.5

OwnerOf returns the current owner of task and whether one is set.

type AssignmentRole added in v0.0.5

type AssignmentRole int

AssignmentRole is the closed set of Pasture assignment roles. It distinguishes the owner-responsibility, governing-parent supervisor, and axis-reviewer slots the issue names; it is a Pasture-level classification carried in the material payload and is distinct from any Provenance assignment slot id.

const (

	// RoleOwnerResponsibility is the atomic authority for Task.Owner.
	RoleOwnerResponsibility AssignmentRole
	// RoleGoverningSupervisor is the governing-parent supervisor slot.
	RoleGoverningSupervisor
	// RoleAxisReviewer is one of the three axis reviewer slots.
	RoleAxisReviewer
)

func (AssignmentRole) String added in v0.0.5

func (r AssignmentRole) String() string

String renders the role as its canonical payload token.

type AssignmentStartedEvent added in v0.0.5

type AssignmentStartedEvent struct {
	Task       provenance.TaskID
	Assignment provenance.AssignmentID
	Role       AssignmentRole
	Occupant   provenance.ActorID
}

AssignmentStartedEvent records a Provenance-backed assignment episode opening. It carries the assignment id, the distinct role, and the occupant actor; the occupant is journaled both in the payload and as an actor context.

func (AssignmentStartedEvent) Family added in v0.0.5

func (AssignmentStartedEvent) SourceTask added in v0.0.5

func (e AssignmentStartedEvent) SourceTask() provenance.TaskID

type AssignmentTransition added in v0.0.5

type AssignmentTransition struct {
	Assignment  provenance.AssignmentID
	Task        provenance.TaskID
	Role        AssignmentRole
	Occupant    provenance.ActorID
	Predecessor provenance.AssignmentID
	Parent      provenance.AssignmentID
	Kind        AssignmentTransitionKind
	Ordinal     provenance.JournalID
}

AssignmentTransition is one ordered assignment start/end the projection folds. Ordinal is the journal order (JournalID); the projection applies transitions in ascending Ordinal.

type AssignmentTransitionKind added in v0.0.5

type AssignmentTransitionKind int

AssignmentTransitionKind is the closed kind of an assignment episode transition.

const (

	// AssignmentStarted opens an episode.
	AssignmentStarted AssignmentTransitionKind
	// AssignmentEnded closes an episode.
	AssignmentEnded
)

type AtomicTaskUpdater added in v0.0.5

type AtomicTaskUpdater interface {
	// UpdateTaskAtomic applies metadata fields and an optional target status to a task
	// as one all-or-none journaled operation. See the method for full semantics.
	UpdateTaskAtomic(id provenance.TaskID, fields provenance.UpdateFields, targetStatus *provenance.Status) (provenance.Task, error)
}

AtomicTaskUpdater is the capability the journaled task tracker exposes for a combined metadata+status `pasture task update`. OpenTaskTracker's concrete tracker satisfies it; the CLI handler type-asserts the returned protocol.TaskTracker to drive the update so a rejected (FSM-illegal) status change also rolls back the metadata write.

type CandidateResult added in v0.0.5

type CandidateResult struct {
	CommandResult
	Slice     provenance.TaskID
	Candidate ImplementationCandidateID
}

CandidateResult identifies the immutable candidate selected for a slice.

type CanonicalDecisionPayload added in v0.0.5

type CanonicalDecisionPayload []byte

CanonicalDecisionPayload is the opaque, canonical encoded bytes of one decision value.

type CloseSliceInput added in v0.0.5

type CloseSliceInput struct {
	Meta        CommandMeta
	Epoch       EpochRootID
	Slice       provenance.TaskID
	Candidate   ImplementationCandidateID
	ReviewRound ReviewRoundID
	Assignment  provenance.AssignmentID
}

CloseSliceInput closes a slice under the exact governing assignment and finalized review round. The aggregate derives the round's canonical review events atomically.

type CommandMeta added in v0.0.5

type CommandMeta struct {
	OperationID provenance.OperationID
}

CommandMeta carries the internal idempotency identity shared by direct and adapter invocations. It is not part of the ordinary CLI grammar.

type CommandResult added in v0.0.5

type CommandResult struct {
	OperationID provenance.OperationID
	Replayed    bool
	Epoch       EpochRootID
	ActivityID  provenance.ActivityID
	EventIDs    []provenance.JournalID
}

CommandResult identifies one committed aggregate operation and its material records. Replayed distinguishes an exact idempotent replay without changing any identifiers.

type CoverageDigest added in v0.0.5

type CoverageDigest [32]byte

CoverageDigest is the accepted coverage digest a UAT records and land recomputes/ compares. Its text form is "sha256:<hex>".

func ComputeCoverageDigest added in v0.0.5

func ComputeCoverageDigest(spec CoverageDigestSpec) (CoverageDigest, error)

ComputeCoverageDigest computes the deterministic coverage digest for a spec using a version-prefixed, length-delimited encoding. Every variable-length field is written as uvarint(len) followed by its bytes, so no two distinct field boundaries can alias, and the required refs and the three resolution domains are sorted canonically so input permutation does not change the digest. Duplicate targets within a domain are rejected upstream (validateImplUATPayload), so the encoded resolution list is a set.

Scope: the digest folds each resolution's (domain, target, kind) plus the authoritative verdict — it deliberately excludes the free-text Note (and interaction/feedback bodies). This is intentionally decision-bearing-only: (domain, target, kind) is the exact information VerifyCoverage's mismatch check needs (a later ledger append changes the required-ref set, or a resolution's disposition changes, and either flips the digest); Note is documentation attached to a resolution, not itself a decision, so a Note-only edit does not stale a previously accepted coverage digest.

func ParseCoverageDigest added in v0.0.5

func ParseCoverageDigest(text []byte) (CoverageDigest, error)

ParseCoverageDigest parses a "sha256:<hex>" coverage digest, rejecting a missing prefix or a wrong-length hex body.

func (CoverageDigest) MarshalText added in v0.0.5

func (d CoverageDigest) MarshalText() ([]byte, error)

MarshalText renders the digest as "sha256:<hex>".

func (*CoverageDigest) UnmarshalText added in v0.0.5

func (d *CoverageDigest) UnmarshalText(text []byte) error

UnmarshalText parses a "sha256:<hex>" digest so CoverageDigest round-trips through JSON.

type CoverageDigestSpec added in v0.0.5

type CoverageDigestSpec struct {
	RequiredRefs   []RequiredRef
	Outcome        ImplementationUATVerdict
	Payload        ImplUATPayload
	PlanDecision   PlanUATDecisionID
	IntegrationSet IntegrationCandidateSetID
	InputLedger    DocumentRevisionID
}

CoverageDigestSpec is the exact set of inputs a coverage digest is computed over. The required refs and resolutions are sorted canonically inside ComputeCoverageDigest, so a caller need not pre-sort; the digest is invariant under input permutation but changes under any value change.

type CoverageInput added in v0.0.5

type CoverageInput struct {
	LedgerEntries    []DecisionLedgerEntry
	DeferredPlan     *PlanDeferredByAFK
	PriorResolutions []ImplUATPayload
}

CoverageInput is the exact typed input the required-decision set is computed from. The entire current epoch ledger is scanned for material agent-judgments; the deferred Plan decision supplies the held questions and deferred feedback; PriorResolutions are the resolutions from earlier canonical Implementation-UAT payloads whose targets are removed.

type CreateIntegrationCandidateInput added in v0.0.5

type CreateIntegrationCandidateInput struct {
	Meta         CommandMeta
	Epoch        EpochRootID
	Plan         provenance.TaskID
	Assignment   provenance.AssignmentID
	Repositories []RepositoryCandidate
}

CreateIntegrationCandidateInput creates one exact multi-repository candidate set.

type CreateSliceInput added in v0.0.5

type CreateSliceInput struct {
	Meta       CommandMeta
	Epoch      EpochRootID
	Plan       provenance.TaskID
	Assignment provenance.AssignmentID
}

CreateSliceInput creates a slice under the exact active governing assignment.

type DatabaseFilename added in v0.0.5

type DatabaseFilename string

DatabaseFilename is a typed unified database filename.

const DefaultDBFilename DatabaseFilename = "pasture.db"

DefaultDBFilename is the filename portion of the unified pasture database. PROPOSAL-2 §7.1 binds this to `pasture.db` so both the Provenance subsystem (task CRUD, agents, edges, labels, comments, activities) and the audit subsystem (audit_events, context_edges, sessions) open the same file.

Pre-PROPOSAL-2 the `pasture` CLI defaulted to `provenance.db` and `pastured` defaulted to `audit.db`; SLICE-10 collapses both to `pasture.db`. See PROPOSAL-2 §7.1 + §11 Scenario 9 for the unification rationale and the hjsdt-CLI byte-identical-output requirement that drives the migration.

func (DatabaseFilename) String added in v0.0.5

func (f DatabaseFilename) String() string

type DecisionAttribution added in v0.0.5

type DecisionAttribution struct {
	Decider      provenance.ActorID   `json:"decider"`
	DeciderKind  provenance.AgentKind `json:"deciderKind"`
	Recorder     provenance.ActorID   `json:"recorder"`
	RecorderKind provenance.AgentKind `json:"recorderKind"`
}

DecisionAttribution is the decider/recorder attribution stored on a projected ledger entry. Explicit human gates use the selected registered human for both fields; other decision producers may distinguish the deciding and recording actors. Kinds use provenance.AgentKind.

type DecisionBinding added in v0.0.5

type DecisionBinding interface {
	// contains filtered or unexported methods
}

DecisionBinding is a type-erased catalog binding produced by BindDecision. Its concrete type is private so a caller cannot fabricate one.

func BindDecision added in v0.0.5

func BindDecision[T any](d DecisionDescriptor[T]) DecisionBinding

BindDecision type-erases a descriptor into a catalog binding.

type DecisionCatalog added in v0.0.5

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

DecisionCatalog is an immutable set of registered decision bindings keyed by kind. It is constructed once by NewDecisionCatalog and never mutated.

func NewDecisionCatalog added in v0.0.5

func NewDecisionCatalog(bindings ...DecisionBinding) (DecisionCatalog, error)

NewDecisionCatalog validates and freezes a set of bindings. It rejects an empty or duplicate kind and any codec/schema conflict independent of registration order. The concrete reserved-kind policy is #49's; #43's base construction rejects only empty and duplicate kinds.

func (DecisionCatalog) Manifest added in v0.0.5

func (c DecisionCatalog) Manifest() []DecisionCatalogEntry

Manifest returns the registered entries in registration order. The returned slice never aliases the catalog's own storage.

func (DecisionCatalog) ValidateDraft added in v0.0.5

func (c DecisionCatalog) ValidateDraft(draft DecisionDraft) error

ValidateDraft accepts a draft only if the catalog registers a binding whose token is the draft's exact descriptor token and whose kind/codec/schema match. This is the runtime-append gate: a draft from an unregistered descriptor is rejected.

func (DecisionCatalog) ValidateStored added in v0.0.5

func (c DecisionCatalog) ValidateStored(encoding DecisionEncoding) error

ValidateStored validates a persisted encoding against its registered descriptor: the kind must be registered, and the type-erased binding decodes/revalidates/re-encodes and requires byte-identical canonical output.

type DecisionCatalogEntry added in v0.0.5

type DecisionCatalogEntry struct {
	Kind   DecisionKindID       `json:"kind"`
	Codec  DecisionCodecID      `json:"codec"`
	Schema DecisionSchemaDigest `json:"schema"`
}

DecisionCatalogEntry is the public, serializable manifest row for one registered kind.

type DecisionCodecID added in v0.0.5

type DecisionCodecID string

DecisionCodecID names the canonical codec a decision's payload is encoded with.

type DecisionDescriptor added in v0.0.5

type DecisionDescriptor[T any] struct {
	// contains filtered or unexported fields
}

DecisionDescriptor is a compile-time typed, validated codec for one decision value type T. It is constructed by NewDecisionDescriptor, which mints its opaque token; only a successfully constructed descriptor can produce a draft. Its function fields are construction-time behavior, never serialized and never codec identity.

func NewDecisionDescriptor added in v0.0.5

func NewDecisionDescriptor[T any](
	kind DecisionKindID,
	codec DecisionCodecID,
	schema DecisionSchemaDigest,
	validate func(T) error,
	encode func(T) (CanonicalDecisionPayload, error),
	decode func(CanonicalDecisionPayload) (T, error),
) (DecisionDescriptor[T], error)

NewDecisionDescriptor validates a decision codec's own kind/codec/schema/functions and mints an opaque token. It rejects an empty kind or codec, a zero schema digest, and any nil function; it does NOT pretend an isolated constructor can detect another descriptor's kind (catalog construction owns cross-descriptor conflict detection).

func (DecisionDescriptor[T]) Codec added in v0.0.5

func (d DecisionDescriptor[T]) Codec() DecisionCodecID

func (DecisionDescriptor[T]) Draft added in v0.0.5

func (d DecisionDescriptor[T]) Draft(value T) (DecisionDraft, error)

Draft validates a typed value and canonically encodes it, retaining the descriptor's token so only a catalog-registered descriptor's draft can later be appended. It copies the encoded payload defensively so the returned draft owns its bytes.

func (DecisionDescriptor[T]) Kind added in v0.0.5

func (d DecisionDescriptor[T]) Kind() DecisionKindID

Kind, Codec, Schema expose the descriptor's stored identity for manifest/inspection.

func (DecisionDescriptor[T]) Schema added in v0.0.5

type DecisionDraft added in v0.0.5

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

DecisionDraft is an opaque, catalog-issued pending decision. Callers never construct a DecisionEncoding directly; a draft is the only carrier a ledger mutation (#49) accepts.

type DecisionEncoding added in v0.0.5

type DecisionEncoding struct {
	Kind    DecisionKindID           `json:"kind"`
	Codec   DecisionCodecID          `json:"codec"`
	Schema  DecisionSchemaDigest     `json:"schema"`
	Payload CanonicalDecisionPayload `json:"payload"`
}

DecisionEncoding is the persisted, serializable form of one decision: its identity plus canonical payload bytes. Callers never construct it directly (a draft or the append path does); it is public so the ledger entry can carry it.

type DecisionKindID added in v0.0.5

type DecisionKindID string

DecisionKindID is a decision's stable kind identity (the ledger row's kind column).

const (

	// DecisionPlanUATAccepted / ...ChangesRequested / ...DeferredByAFK are the three Plan-UAT
	// decision kinds; DecisionImplementationUAT is the single Implementation-UAT kind.
	DecisionPlanUATAccepted         DecisionKindID = "pasture.plan-uat.accepted/v1"
	DecisionPlanUATChangesRequested DecisionKindID = "pasture.plan-uat.changes-requested/v1"
	DecisionPlanUATDeferredByAFK    DecisionKindID = "pasture.plan-uat.deferred-by-afk/v1"
	DecisionImplementationUAT       DecisionKindID = "pasture.implementation-uat/v1"
	DecisionPlanRatified            DecisionKindID = "pasture.plan.ratified/v1"
	DecisionLanded                  DecisionKindID = "pasture.epoch.landed/v1"
)

Canonical codec + kind identities for the #49 decision descriptors.

const DecisionInteractionModeChanged DecisionKindID = "pasture.interaction-mode.changed/v1"

DecisionInteractionModeChanged is the stable decision-ledger kind of a mode change. It is a DecisionKindID (an internal decision-codec identity), NOT a provenance EventKind, so it retains the issue's canonical "/v1" spelling; the journal namespaced-name grammar (which forbids '/') governs only material EventKinds.

type DecisionLedgerEntry added in v0.0.5

type DecisionLedgerEntry struct {
	ID            DecisionLedgerEntryID     `json:"id"`
	Epoch         EpochRootID               `json:"epoch"`
	Actor         DecisionAttribution       `json:"actor"`
	SourceRequest *ir.UserDecisionRequestID `json:"sourceRequest,omitempty"`
	Context       *DecisionEncoding         `json:"context,omitempty"`
	Decision      DecisionEncoding          `json:"decision"`
}

DecisionLedgerEntry is one immutable ledger entry. Decision is the sole purpose-specific stored payload, so question/options/verbatim/rationale/resolution fields cannot drift beside it. SourceRequest and Context are optional.

type DecisionLedgerEntryID added in v0.0.5

type DecisionLedgerEntryID string

DecisionLedgerEntryID identifies one immutable ledger entry.

func MaterialAgentJudgments added in v0.0.5

func MaterialAgentJudgments(entries []DecisionLedgerEntry) []DecisionLedgerEntryID

MaterialAgentJudgments returns the sorted, unique ids of the material agent-judgment entries in a ledger. It is exposed so a caller can inspect the raw judgment set independently of the resolution subtraction RequiredDecisions performs.

type DecisionQuery added in v0.0.5

type DecisionQuery struct {
	Deciders      []provenance.ActorID   `json:"deciders,omitempty"`
	Recorders     []provenance.ActorID   `json:"recorders,omitempty"`
	DeciderKinds  []provenance.AgentKind `json:"deciderKinds,omitempty"`
	RecorderKinds []provenance.AgentKind `json:"recorderKinds,omitempty"`
	Kinds         []DecisionKindID       `json:"kinds,omitempty"`
}

DecisionQuery is a read-only projection filter over ledger entries by decider/recorder actor, actor-kind, and decision kind. Empty slices match everything on that axis.

type DecisionResult added in v0.0.5

type DecisionResult struct {
	CommandResult
	DecisionID DecisionLedgerEntryID
	ActorID    provenance.ActorID
}

DecisionResult is the common result of all five explicit-human decisions.

type DecisionSchemaDigest added in v0.0.5

type DecisionSchemaDigest [32]byte

DecisionSchemaDigest pins the exact schema a codec targets; changing the encoding forces a new digest, which golden fixtures verify.

type DeferredFeedbackResolution added in v0.0.5

type DeferredFeedbackResolution struct {
	Target UATFeedbackID  `json:"target"`
	Kind   ResolutionKind `json:"kind"`
	Note   string         `json:"note"`
}

DeferredFeedbackResolution resolves one carried-forward deferred Plan-feedback item.

type DocumentRevisionID added in v0.0.5

type DocumentRevisionID string

DocumentRevisionID identifies one document revision (proposal/ledger revision). It is deliberately named DocumentRevisionID, not TaskRevisionID, to avoid confusion with a Provenance CAS token.

type DocumentRevisionSubject added in v0.0.5

type DocumentRevisionSubject struct {
	ID            DocumentRevisionID
	DocumentTask  provenance.TaskID
	ContentDigest [32]byte
}

DocumentRevisionSubject snapshots a reviewed document revision.

func (DocumentRevisionSubject) Ref added in v0.0.5

Ref derives the document-revision subject reference.

type EpochAssignmentService added in v0.0.5

EpochAssignmentService is the assignment-authorized portion of the aggregate.

type EpochDecisionRecordedEvent added in v0.0.5

type EpochDecisionRecordedEvent struct {
	Subject  provenance.TaskID
	Epoch    provenance.TaskID
	Activity provenance.ActivityID
	Actor    provenance.ActorID
	Decision DecisionLedgerEntryID
	Kind     DecisionKindID
}

EpochDecisionRecordedEvent records the lifecycle/material reference to a canonical decision fact. The event never carries decision detail: Facts().QueryDecisions is the sole authority for reopen-safe decision reconstruction.

func (EpochDecisionRecordedEvent) Family added in v0.0.5

func (EpochDecisionRecordedEvent) SourceTask added in v0.0.5

type EpochHumanService added in v0.0.5

EpochHumanService is the explicit-human portion of the workflow aggregate.

type EpochHumanServiceFactory added in v0.0.5

type EpochHumanServiceFactory interface {
	NewEpochHumanService(EpochServiceOptions) (EpochHumanService, error)
}

EpochHumanServiceFactory constructs the production human-decision aggregate without requiring placeholder implementations of assignment-controlled operations.

type EpochLanded added in v0.0.5

type EpochLanded struct {
	Candidate         IntegrationCandidateSetID `json:"candidate"`
	ImplementationUAT DecisionLedgerEntryID     `json:"implementationUat"`
}

EpochLanded is the immutable decision payload binding landing to the exact candidate and accepted Implementation UAT decision.

type EpochMutationKind added in v0.0.5

type EpochMutationKind int

EpochMutationKind is the closed mutation identity exposed to synchronization seams.

const (
	MutationSetInteractionMode EpochMutationKind
	MutationStartReview
	MutationSubmitReview
	MutationFinalizeReview
	MutationCreateSlice
	MutationSetSliceCandidate
	MutationReworkSlice
	MutationCloseSlice
	MutationCreateIntegrationCandidate
	MutationReworkIntegrationCandidate
	MutationPublishRepository
	MutationRecordPlanUAT
	MutationRatifyPlan
	MutationRecordImplementationUAT
	MutationLand
)

type EpochRaceBarrier added in v0.0.5

type EpochRaceBarrier interface {
	AfterPreflight(context.Context, EpochMutationKind) error
}

EpochRaceBarrier is an injected deterministic synchronization seam. Implementations call AfterPreflight after authoritative reads and immediately before atomic Apply. Production supplies an inert barrier; synchronized tests may hold contenders here.

type EpochRootID added in v0.0.5

type EpochRootID string

EpochRootID identifies the protected epoch-root/REQUEST the ledger belongs to.

type EpochService added in v0.0.5

type EpochService interface {
	EpochHumanService
	EpochAssignmentService
}

EpochService is the one public workflow contract composed from its two authority families. Production composition does not permit either family to fake the other.

type EpochServiceFactory added in v0.0.5

type EpochServiceFactory interface {
	NewEpochService(EpochServiceOptions) (EpochService, error)
}

EpochServiceFactory is the production construction boundary for the composed service. The assignment implementation composes its service with EpochHumanService.

type EpochServiceOptions added in v0.0.5

type EpochServiceOptions struct {
	Synchronization EpochServiceSynchronization
	// contains filtered or unexported fields
}

EpochServiceOptions carries optional aggregate behavior dependencies. Its zero value is production-safe: a nil race barrier means no synchronization pause. CLI commands never receive these options.

type EpochServiceSynchronization added in v0.0.5

type EpochServiceSynchronization struct {
	RaceBarrier EpochRaceBarrier
}

EpochServiceSynchronization groups synchronization dependencies separately from all ordinary command inputs and results.

type FinalizeReviewInput added in v0.0.5

type FinalizeReviewInput struct {
	Meta       CommandMeta
	Epoch      EpochRootID
	Round      ReviewRoundID
	Assignment provenance.AssignmentID
}

FinalizeReviewInput is authorized by the exact active governing assignment.

type FindingDisposition added in v0.0.5

type FindingDisposition int

FindingDisposition is the closed resolution of a finding during candidate rework.

const (
	FindingFixed FindingDisposition
	FindingDeferred
)

type FindingResolution added in v0.0.5

type FindingResolution struct {
	Finding  provenance.TaskID
	Outcome  FindingDisposition
	Evidence []provenance.JournalID
}

FindingResolution ties a finding to its disposition and journaled fix evidence.

type FindingSeverity added in v0.0.5

type FindingSeverity int

FindingSeverity is the closed eager severity-group set an implementation review axis is blocked by. Plan reviews create no groups.

const (

	// SeverityBlocker is a merge-blocking finding.
	SeverityBlocker FindingSeverity
	// SeverityImportant is a should-fix finding.
	SeverityImportant
	// SeverityMinor is an optional finding.
	SeverityMinor
)

func (FindingSeverity) String added in v0.0.5

func (s FindingSeverity) String() string

type GateClaimMalformedError added in v0.0.9

type GateClaimMalformedError struct {
	Harness ir.HarnessID
	Session string
	Cause   error
}

GateClaimMalformedError is a fault on a claim row that exists but whose actor is not an actor identifier. A malformed claim is never downgraded to an unbound or an unknown session, because both of those are policy answers and this is a store fault.

func (*GateClaimMalformedError) Error added in v0.0.9

func (e *GateClaimMalformedError) Error() string

func (*GateClaimMalformedError) Unwrap added in v0.0.9

func (e *GateClaimMalformedError) Unwrap() error

Unwrap keeps the parse cause reachable through errors.As.

type GateReadError added in v0.0.9

type GateReadError struct {
	Stage   GateReadStage
	Harness ir.HarnessID
	Session string
	Cause   error
}

GateReadError is a read fault that is not an integrity fault: the store was reachable but could not answer, the context ended, or the query was refused. It is never a policy denial.

func (*GateReadError) Error added in v0.0.9

func (e *GateReadError) Error() string

func (*GateReadError) Unwrap added in v0.0.9

func (e *GateReadError) Unwrap() error

Unwrap keeps the cause reachable, so errors.Is finds the context and store sentinels and errors.As finds a typed store or driver error.

type GateReadIntegrityError added in v0.0.9

type GateReadIntegrityError struct {
	Stage provenance.ActorOwnershipStage
	Cause error
}

GateReadIntegrityError is a read fault caused by store contents that a supported writer cannot produce. Stage carries the Provenance read stage, so the operator's line names which part of the result was damaged.

A ZERO Stage means the store read named none: the fault is a subtype fault that reached this boundary without the typed carrier that carries the stage, and the reader reports it as unreported rather than naming one of the three stages on the store's behalf. The field holds no Provenance stage in that case rather than a made-up one, so a programmatic reader sees "none" and an operator reads "unreported".

func (*GateReadIntegrityError) Error added in v0.0.9

func (e *GateReadIntegrityError) Error() string

func (*GateReadIntegrityError) Unwrap added in v0.0.9

func (e *GateReadIntegrityError) Unwrap() error

Unwrap keeps the Provenance limit, projection-mismatch and subtype causes reachable through errors.As, and their sentinels through errors.Is.

type GateReadStage added in v0.0.9

type GateReadStage uint8

GateReadStage names the read step that failed. It is a closed set because a caller acts on the two differently: a claim-stage fault means the session could not be identified at all, and an ownership-stage fault means the identity was known and its episodes could not be read.

const (

	// GateReadStageClaim is the Pasture-owned session-claim read.
	GateReadStageClaim GateReadStage
	// GateReadStageOwnership is the Provenance-owned active-ownership read.
	GateReadStageOwnership
)

func (GateReadStage) String added in v0.0.9

func (s GateReadStage) String() string

String renders the stage as the operator-facing token.

type GateReaderCapabilityError added in v0.0.9

type GateReaderCapabilityError struct {
	Missing string
}

GateReaderCapabilityError is a build-time fault: the store's journal does not carry the public active-ownership query. There is no fallback read, because a second read path would answer the gate from a different source than the one this design binds it to.

func (*GateReaderCapabilityError) Error added in v0.0.9

func (e *GateReaderCapabilityError) Error() string

type GateReaderScopeError added in v0.0.9

type GateReaderScopeError struct {
	Operation string
}

GateReaderScopeError is API misuse: the reader was asked something outside the one session and one actor it was bound to, or it was asked without a context.

func (*GateReaderScopeError) Error added in v0.0.9

func (e *GateReaderScopeError) Error() string

type GateRoleSourceError added in v0.0.9

type GateRoleSourceError struct {
	Task       provenance.TaskID
	Assignment provenance.AssignmentID
	Reason     string
}

GateRoleSourceError is a fault on the role of one owned episode. The episode exists, but the role that decides whether the actor may act was written by no source the reader accepts.

func (*GateRoleSourceError) Error added in v0.0.9

func (e *GateRoleSourceError) Error() string

type GateSnapshotClosedError added in v0.0.9

type GateSnapshotClosedError struct{}

GateSnapshotClosedError is a lifecycle fault on an already-sealed snapshot. The reader released everything it held when it was closed, so it has nothing left to answer with.

func (*GateSnapshotClosedError) Error added in v0.0.9

func (e *GateSnapshotClosedError) Error() string

type GitRef added in v0.0.5

type GitRef string

GitRef identifies the remote ref verified for one published repository member. Git object identity remains provenance.GitOID.

type GitRemoteRefVerifiedEvent added in v0.0.5

type GitRemoteRefVerifiedEvent struct {
	Task       provenance.TaskID
	Repository string
	Ref        string
	CommitOID  provenance.GitOID
}

GitRemoteRefVerifiedEvent is the land-time evidence that a repository's remote ref was verified at an exact commit. It is the typed pasture.git.remote-ref-verified/v1 event #49's land handler requires (one per repository).

func (GitRemoteRefVerifiedEvent) Family added in v0.0.5

func (GitRemoteRefVerifiedEvent) SourceTask added in v0.0.5

type HeldQuestionResolution added in v0.0.5

type HeldQuestionResolution struct {
	Target HeldUATQuestionID `json:"target"`
	Kind   ResolutionKind    `json:"kind"`
	Note   string            `json:"note"`
}

HeldQuestionResolution resolves one carried-forward held question.

type HeldUATQuestion added in v0.0.5

type HeldUATQuestion struct {
	ID       HeldUATQuestionID `json:"id"`
	Question string            `json:"question"`
	Stable   bool              `json:"stable"`
}

HeldUATQuestion is a question held open during a UAT session. Stable gates only whether an AFK Plan deferral is ELIGIBLE to be recorded (at least one held question must be stable); it does not filter which held questions are carried forward — RequiredDecisions (uat_coverage.go) carries every held question from the deferred Plan decision forward regardless of Stable, matching issue #49's literal "every unresolved held question".

type HeldUATQuestionID added in v0.0.5

type HeldUATQuestionID string

HeldUATQuestionID identifies one held (unanswered) UAT question.

type ImplUATPayload added in v0.0.5

type ImplUATPayload struct {
	Interactions    []UATInteraction             `json:"interactions"`
	Feedback        []UATFeedbackItem            `json:"feedback"`
	HeldAnswers     []HeldQuestionResolution     `json:"heldAnswers"`
	PlanFeedback    []DeferredFeedbackResolution `json:"planFeedback"`
	LedgerDecisions []LedgerDecisionResolution   `json:"ledgerDecisions"`
}

ImplUATPayload is the single structured Implementation-UAT payload: verbatim interactions, feedback, and the three carry-forward resolution domains. The authoritative verdict is supplied separately to validation and drafting, so it cannot disagree with a second payload field. Actor attribution is likewise stored separately.

type ImplementationCandidateID added in v0.0.5

type ImplementationCandidateID string

DocumentRevisionID/ImplementationCandidateID identify the two review-subject snapshots. ImplementationCandidateID is the const-string id wrapping the implementation candidate snapshot task; DocumentRevisionID (decision_ledger.go) plays the same role for documents.

type ImplementationCandidateSubject added in v0.0.5

type ImplementationCandidateSubject struct {
	ID         ImplementationCandidateID
	SliceTask  provenance.TaskID
	Repository string
	CommitOID  provenance.GitOID
	TreeDigest [32]byte
}

ImplementationCandidateSubject snapshots a reviewed implementation candidate.

func (ImplementationCandidateSubject) Ref added in v0.0.5

Ref derives the implementation-candidate subject reference.

type ImplementationReviewSubmission added in v0.0.5

type ImplementationReviewSubmission struct {
	Verdict  Verdict
	Findings []ReviewFinding
}

ImplementationReviewSubmission carries a binary implementation verdict and severity- classified findings. It cannot carry plan feedback by construction.

func (ImplementationReviewSubmission) Validate added in v0.0.5

Validate applies the code-review threshold: ACCEPT permits non-blocking follow-up findings, while REVISE requires at least one actionable BLOCKER.

type ImplementationUATDecision added in v0.0.5

type ImplementationUATDecision struct {
	UATTaskID      provenance.TaskID
	IntegrationSet IntegrationCandidateSetID
	DecisionEntry  DecisionLedgerEntryID
	InputLedger    DocumentRevisionID
	OutputLedger   DocumentRevisionID
	PlanDecision   PlanUATDecisionID
	Outcome        ImplementationUATVerdict
	Payload        ImplUATPayload
	Coverage       CoverageDigest
}

ImplementationUATDecision is the command-level Implementation-UAT record: the UAT task, integration candidate set, the decision ledger entry it will append, the exact input and post-command output ledger revisions, the deferred Plan decision it carries forward from, the single canonical payload, and the accepted coverage digest land recomputes.

type ImplementationUATInput added in v0.0.5

type ImplementationUATInput struct {
	Meta      CommandMeta
	Epoch     EpochRootID
	Candidate IntegrationCandidateSetID
	Outcome   ImplementationUATVerdict
	Actor     AssertedHumanActor
	Payload   *ImplUATPayload
}

ImplementationUATInput records one explicit human decision over an integration candidate. Payload carries only structured feedback and carry-forward resolution.

type ImplementationUATVerdict added in v0.0.5

type ImplementationUATVerdict int

ImplementationUATVerdict is the closed set of Implementation-UAT dispositions.

const (

	// ImplUATAccepted accepts the integration candidate for landing.
	ImplUATAccepted ImplementationUATVerdict
	// ImplUATChangesRequested returns the candidate for further work.
	ImplUATChangesRequested
)

func (ImplementationUATVerdict) String added in v0.0.5

func (v ImplementationUATVerdict) String() string

type IntegrationCandidateReplacement added in v0.0.5

type IntegrationCandidateReplacement struct {
	Repositories []RepositoryCandidate
}

IntegrationCandidateReplacement is the complete repository set that atomically replaces an existing integration candidate.

type IntegrationCandidateResult added in v0.0.5

type IntegrationCandidateResult struct {
	CommandResult
	Candidate IntegrationCandidateSetID
}

IntegrationCandidateResult identifies the immutable integration candidate set.

type IntegrationCandidateSetID added in v0.0.5

type IntegrationCandidateSetID string

IntegrationCandidateSetID identifies the exact integration candidate set an Implementation-UAT decision ranges over.

type InteractionMode added in v0.0.5

type InteractionMode string

InteractionMode is the per-epoch autonomous-interaction policy. It is a string enum (matching the issue's canonical wire spelling) with exactly two members; the empty value is not a mode, and the default effective mode is InteractionNormal.

const (
	// InteractionNormal is the default, full-interaction policy.
	InteractionNormal InteractionMode = "normal"
	// InteractionAFK is the reduced-interaction, autonomous-progress policy.
	InteractionAFK InteractionMode = "afk"
)

type InteractionModeChanged added in v0.0.5

type InteractionModeChanged struct {
	From InteractionMode `json:"from"`
	To   InteractionMode `json:"to"`
}

InteractionModeChanged is the typed payload of a mode-change decision: the exact source and target modes. It is the sole codec payload of DecisionInteractionModeChanged.

type InteractionModeCursor added in v0.0.5

type InteractionModeCursor struct {
	Entry *DecisionLedgerEntryID
	Mode  InteractionMode
}

InteractionModeCursor is the effective mode plus the ledger entry that established it. Entry is nil exactly when the mode is the default normal (no mode entry has been appended); after a mode change, Entry is that change entry's immutable id.

func EffectiveMode added in v0.0.5

func EffectiveMode(policy PolicySet, entries []DecisionLedgerEntry) (InteractionModeCursor, error)

EffectiveMode folds an immutable, ledger-ordered slice of decision entries into the current interaction-mode cursor. It selects the latest valid interaction-mode entry; absence of any mode entry returns the default normal/nil cursor. Non-mode entries are ignored. The fold verifies the mode chain is consistent — each change's recorded source mode must equal the running effective mode — so a corrupted or mis-ordered ledger is reported rather than silently yielding a wrong mode. The input is never mutated.

policy is the explicit PolicySet the caller constructed (typically via NewProductionPolicySet once and reused); EffectiveMode holds no package-level or process-global PolicySet of its own, matching policy_set.go's "constructed explicitly, passed by value" contract.

type LandInput added in v0.0.5

type LandInput struct {
	Meta              CommandMeta
	Epoch             EpochRootID
	Candidate         IntegrationCandidateSetID
	ImplementationUAT DecisionLedgerEntryID
	Actor             AssertedHumanActor
}

LandInput records landing as a first-class human decision over an accepted implementation UAT decision and its exact integration candidate.

type LedgerDecisionResolution added in v0.0.5

type LedgerDecisionResolution struct {
	Target DecisionLedgerEntryID `json:"target"`
	Kind   ResolutionKind        `json:"kind"`
	Note   string                `json:"note"`
}

LedgerDecisionResolution resolves one material agent-judgment ledger entry.

type LegacyActorResolver added in v0.0.5

type LegacyActorResolver struct {
	// Map resolves an exact legacy actor string to a registered ActorID.
	Map map[string]provenance.ActorID
	// Fallback is used when the raw actor text is empty or not present in Map.
	Fallback provenance.ActorID
}

LegacyActorResolver resolves a legacy row's raw actor text to a registered ActorID, falling back to Fallback when the text is empty or absent from Map. Fallback must be a valid, registered actor because every imported event is attributed to a resolvable actor; a zero Fallback is rejected before any journal write.

type LegacyAuditImportedEvent added in v0.0.5

type LegacyAuditImportedEvent struct {
	Task            provenance.TaskID
	SourceTable     string
	LegacyRowID     string
	RawActor        string
	AttributedActor provenance.ActorID
	RawContexts     []string
	SourcePayload   json.RawMessage
}

LegacyAuditImportedEvent carries one pre-journal legacy audit row, attached to exactly one referenced task. Its canonical payload embeds the source payload as an embedded JSON value (value-preserving canonical JSON — encoding/json compacts the embedded json.RawMessage, so the stored envelope holds the value-equivalent form, not the exact source bytes) alongside the row's source identity, its original raw actor text, and its original raw context strings, so no legacy VALUE is lost. The exact original bytes bind the canonical command digest through legacyImportCommandBytes, though they are not byte-recoverable from the stored event. AttributedActor is the resolved (mapped-or-fallback) actor the import derived from RawActor; the committing actor of the operation is the pasture-system actor, and this attributed actor is journaled as an actor context.

func (LegacyAuditImportedEvent) Family added in v0.0.5

func (LegacyAuditImportedEvent) SourceTask added in v0.0.5

type LegacyAuditImporter added in v0.0.5

type LegacyAuditImporter interface {
	// ImportLegacyAuditRow imports one raw legacy audit row as a single atomic journal
	// operation. See the method for full semantics.
	ImportLegacyAuditRow(row provadapter.LegacyAuditEvent, resolver LegacyActorResolver) (LegacyImportOutcome, error)
}

LegacyAuditImporter is the capability an open task tracker exposes for the atomic legacy audit-row import. OpenTaskTracker's concrete tracker satisfies it; a caller (the CLI, #40 runtime bindings) type-asserts the returned protocol.TaskTracker to this interface to drive the import.

type LegacyImportOutcome added in v0.0.5

type LegacyImportOutcome struct {
	Outcome         provadapter.Outcome
	OperationID     provenance.OperationID
	Tasks           []provenance.TaskID
	AttributedActor provenance.ActorID
	FallbackApplied bool
}

LegacyImportOutcome reports how one atomic import resolved. Outcome is the facade result (Committed — fresh or idempotent replay — or Conflict); OperationID is the stable source-derived operation identity; Tasks is the sorted unique fan-out set the row was attached to; AttributedActor is the resolved actor and FallbackApplied records whether the actor-text fallback was used.

type MaterialEvent added in v0.0.5

type MaterialEvent interface {
	// Family returns the closed family discriminator; the fixed EventKind derives
	// from it alone.
	Family() MaterialEventFamily
	// SourceTask is the task the event is authorized against and attributed to (§9.3);
	// it is the effect's TaskID.
	SourceTask() provenance.TaskID
	// contains filtered or unexported methods
}

MaterialEvent is the sealed sum of every pasture.* material event. Concrete family structs live in this package and cannot be added from outside (the unexported isMaterialEvent marker seals the set), so the exhaustive mapping switch is total against a fixed, compile-checked universe. Every implementation is validated and mapped to exactly one journal Effect by MapMaterialEvent.

type MaterialEventFamily added in v0.0.5

type MaterialEventFamily int

MaterialEventFamily is the closed set of pasture.* material-event families. It is the single discriminator the fixed-kind mapping switches on; every value has exactly one EventKind and exactly one typed payload shape. The zero value is a deliberately invalid sentinel so an uninitialised family cannot silently map to a real kind.

const (

	// FamilyAssignmentStarted marks a Provenance-backed assignment episode opening
	// under a distinct owner/supervisor/reviewer role (§ "Metadata, work, and contexts").
	FamilyAssignmentStarted MaterialEventFamily
	// FamilyAssignmentCompleted is a worker's typed completion record. It accompanies
	// EndTaskActivity and, per the issue, does NOT mutate task status.
	FamilyAssignmentCompleted
	// FamilyReviewRecorded records one axis's binary plan/implementation review outcome.
	FamilyReviewRecorded
	// FamilyUATRecorded records a plan or implementation UAT resolution.
	FamilyUATRecorded
	// FamilySkillRun records a skill-run material event bound to a task.
	FamilySkillRun
	// FamilyGitRemoteRefVerified is the land-time evidence that a repository's remote
	// ref was verified at an exact commit ("pasture.git.remote-ref-verified/v1").
	FamilyGitRemoteRefVerified
	// FamilyTaskClosed is the task-closed domain marker ("pasture.task.closed/v1").
	FamilyTaskClosed
	// FamilyLegacyAuditImported carries one pre-journal legacy audit row, preserved
	// verbatim, attached to one referenced task (see legacy_import.go). It is the
	// material representation the atomic ImportLegacyAuditRow command fans out.
	FamilyLegacyAuditImported
	// FamilyEpochDecisionRecorded records a typed lifecycle/material reference to the
	// canonical decision fact and real Activity row produced by the same operation.
	FamilyEpochDecisionRecorded
	// FamilyReviewRoundFinalized is the accepted/revising review-round projection consumed
	// by ratification. The assignment-authorized review service produces it.
	FamilyReviewRoundFinalized
)

func (MaterialEventFamily) EventKind added in v0.0.5

EventKind returns the one fixed journal EventKind for this family. The kind is a total function of the family alone (never of any payload field), so the fixed-kind discipline cannot be subverted by data. materialEventInvalid and any unknown value return the empty kind, which MapMaterialEvent rejects.

func (MaterialEventFamily) String added in v0.0.5

func (f MaterialEventFamily) String() string

String renders the family for diagnostics.

type OpenTaskTrackerOption added in v0.0.5

type OpenTaskTrackerOption func(*openTaskTrackerOptions)

OpenTaskTrackerOption configures OpenTaskTrackerWithOptions.

func WithDiagnosticSink added in v0.0.9

func WithDiagnosticSink(sink io.Writer) OpenTaskTrackerOption

WithDiagnosticSink replaces the stream the store writes its one housekeeping diagnostic to (a failed orphan reclaim). It is a TEST-ONLY option: production opens with the process stderr. A nil sink is refused at open, not defaulted.

func WithMaxOpenConns added in v0.0.5

func WithMaxOpenConns(n int) OpenTaskTrackerOption

WithMaxOpenConns overrides the pasture-owned audit handle's connection-pool size. It is intended for tests that need one goroutine to hold a connection while another observes the same database. Production callers should leave it unset, preserving the single-connection writer cap.

func WithSkipMigrations added in v0.0.5

func WithSkipMigrations() OpenTaskTrackerOption

WithSkipMigrations opens a pre-migrated database without running the audit migrator. The audit layer still asserts the schema version loudly. This is an opt-in test performance hook; production callers should use OpenTaskTracker.

func WithStoreClock added in v0.0.9

func WithStoreClock(clock receipt.Clock) OpenTaskTrackerOption

WithStoreClock replaces the clock the store holds for its own housekeeping (the snapshot instant the orphan reclaim ages payload blobs against). It is a TEST-ONLY option: production opens with the wall clock, and a test that scripts this clock must script the payload store's clock as well, because the age bound reads both.

func WithTimeoutProfile added in v0.0.5

func WithTimeoutProfile(profile timeouts.Profile) OpenTaskTrackerOption

type PlanAccepted added in v0.0.5

type PlanAccepted struct {
	Snapshot     PlanUATSnapshot   `json:"snapshot"`
	Interactions []UATInteraction  `json:"interactions"`
	Feedback     []UATFeedbackItem `json:"feedback"`
}

PlanAccepted is the typed payload of an accepted Plan-UAT decision.

type PlanChangesRequested added in v0.0.5

type PlanChangesRequested struct {
	Snapshot     PlanUATSnapshot   `json:"snapshot"`
	Interactions []UATInteraction  `json:"interactions"`
	Feedback     []UATFeedbackItem `json:"feedback"`
}

PlanChangesRequested is the typed payload of a changes-requested Plan-UAT decision.

type PlanDeferralInput added in v0.0.5

type PlanDeferralInput struct {
	Mode          InteractionModeCursor
	HeldQuestions []HeldUATQuestion
	Feedback      []UATFeedbackItem
	Snapshot      PlanUATSnapshot
}

PlanDeferralInput is the exact state EvaluatePlanDeferral checks before a deferral is recorded. Mode is the current effective interaction-mode cursor (as folded by EffectiveMode); it must be AFK and anchored to a concrete mode entry.

type PlanDeferredByAFK added in v0.0.5

type PlanDeferredByAFK struct {
	Snapshot      PlanUATSnapshot       `json:"snapshot"`
	Interactions  []UATInteraction      `json:"interactions"`
	Feedback      []UATFeedbackItem     `json:"feedback"`
	HeldQuestions []HeldUATQuestion     `json:"heldQuestions"`
	ModeEntry     DecisionLedgerEntryID `json:"modeEntry"`
}

PlanDeferredByAFK is the typed payload of an AFK-deferred Plan-UAT decision. It records the exact AFK mode cursor entry in effect at deferral (ModeEntry): ratification later requires that exact entry to still be the latest mode entry with an AFK result.

type PlanRatified added in v0.0.5

type PlanRatified struct {
	Proposal    string                `json:"proposal"`
	ReviewRound ReviewRoundID         `json:"reviewRound"`
	PlanUAT     DecisionLedgerEntryID `json:"planUat"`
}

PlanRatified is the immutable decision payload binding ratification to its exact proposal, accepted review round, and accepted Plan UAT decision.

type PlanReviewFeedback added in v0.0.5

type PlanReviewFeedback struct {
	Body string
}

PlanReviewFeedback is one severity-free actionable revision requested by a plan review.

type PlanReviewSubmission added in v0.0.5

type PlanReviewSubmission struct {
	Verdict  Verdict
	Feedback []PlanReviewFeedback
}

PlanReviewSubmission carries a binary plan verdict and severity-free feedback.

func (PlanReviewSubmission) Validate added in v0.0.5

func (s PlanReviewSubmission) Validate() error

Validate requires actionable feedback exactly for a revising plan review.

type PlanUATDecision added in v0.0.5

type PlanUATDecision struct {
	Snapshot        PlanUATSnapshot
	ReportedVerdict PlanUATVerdict
	Interactions    []UATInteraction
	Feedback        []UATFeedbackItem
	HeldQuestions   []HeldUATQuestion
	Mode            InteractionModeCursor
}

PlanUATDecision is the higher-level command input a Plan-UAT gate receives. Its ReportedVerdict selects which of the three typed payloads is drafted; PolicySet.DraftPlanUAT validates the cross-field rules and lowers it to the matching canonical decision.

type PlanUATDecisionID added in v0.0.5

type PlanUATDecisionID string

PlanUATDecisionID identifies one Plan-UAT snapshot reference.

type PlanUATInput added in v0.0.5

type PlanUATInput struct {
	Meta     CommandMeta
	Epoch    EpochRootID
	Proposal provenance.TaskID
	Outcome  PlanUATVerdict
	Actor    AssertedHumanActor
	Payload  *PlanUATPayload
}

PlanUATInput records one explicit human Plan UAT decision.

type PlanUATPayload added in v0.0.5

type PlanUATPayload struct {
	Interactions  []UATInteraction
	Feedback      []UATFeedbackItem
	HeldQuestions []HeldUATQuestion
}

PlanUATPayload is the structured content required by non-trivial Plan UAT outcomes. The proposal and outcome remain first-class fields of PlanUATInput.

type PlanUATSnapshot added in v0.0.5

type PlanUATSnapshot struct {
	ID            PlanUATDecisionID     `json:"id"`
	UATTaskID     provenance.TaskID     `json:"uatTaskId"`
	Proposal      DocumentRevisionID    `json:"proposal"`
	DecisionEntry DecisionLedgerEntryID `json:"decisionEntry"`
	InputLedger   DocumentRevisionID    `json:"inputLedger"`
	OutputLedger  DocumentRevisionID    `json:"outputLedger"`
}

PlanUATSnapshot is an immutable reference tying a Plan-UAT decision entry to its subject proposal revision and the input/output ledger revisions land compares.

type PlanUATVerdict added in v0.0.5

type PlanUATVerdict int

PlanUATVerdict is the closed set of Plan-UAT dispositions.

const (

	// PlanUATAccepted ratifies the proposal revision.
	PlanUATAccepted PlanUATVerdict
	// PlanUATChangesRequested returns the proposal for revision.
	PlanUATChangesRequested
	// PlanUATDeferredByAFK is an agent-attributed AFK deferral held for later ratification.
	PlanUATDeferredByAFK
)

func (PlanUATVerdict) String added in v0.0.5

func (v PlanUATVerdict) String() string

type PlannedEdge added in v0.0.5

type PlannedEdge struct {
	From     string
	To       string
	Relation ReviewRelation
}

PlannedEdge is one typed relationship the batch wires between two batch-local handles. For RelationBlockedBy the From handle is the parent (blocked) and To is the child (must finish first), matching parent-blocked-by-child direction.

type PlannedTask added in v0.0.5

type PlannedTask struct {
	Handle   string
	Kind     ReviewTaskKind
	Axis     ReviewAxis      // set for axis and group tasks
	Severity FindingSeverity // set for group tasks
}

PlannedTask is one task the review-start batch mints, named by a stable batch-local handle (the real TaskID is assigned by the batch).

type PolicySet added in v0.0.5

type PolicySet struct {
	Catalog DecisionCatalog
	// contains filtered or unexported fields
}

PolicySet is the explicit production set of #49 decision descriptors plus the immutable #43 catalog that registers them. It is constructed once by NewProductionPolicySet and passed by value; its descriptor fields are unexported so only this package can mint a draft, but each is reachable through an exported accessor for the #40 lowering consumer.

func NewProductionPolicySet added in v0.0.5

func NewProductionPolicySet() (PolicySet, error)

NewProductionPolicySet constructs the explicit production PolicySet. It builds the registered concrete descriptors and freezes them into one immutable catalog; a construction failure (an invalid descriptor or a catalog conflict) is returned rather than panicked.

func (PolicySet) DraftImplementationUAT added in v0.0.5

func (s PolicySet) DraftImplementationUAT(verdict ImplementationUATVerdict, p ImplUATPayload) (DecisionDraft, error)

DraftImplementationUAT validates the authoritative verdict with its structured payload, then drafts the payload through the production descriptor.

func (PolicySet) DraftLanded added in v0.0.5

func (s PolicySet) DraftLanded(v EpochLanded) (DecisionDraft, error)

func (PolicySet) DraftModeChange added in v0.0.5

func (s PolicySet) DraftModeChange(c InteractionModeChanged) (DecisionDraft, error)

DraftModeChange validates and canonically encodes a mode change into a catalog-registered draft. It is the sole typed construction point for a mode-change decision.

func (PolicySet) DraftPlanRatified added in v0.0.5

func (s PolicySet) DraftPlanRatified(v PlanRatified) (DecisionDraft, error)

func (PolicySet) DraftPlanUAT added in v0.0.5

func (s PolicySet) DraftPlanUAT(d PlanUATDecision) (DecisionDraft, error)

DraftPlanUAT lowers a PlanUATDecision to the matching typed payload and drafts it. It enforces the cross-field rules the verdict implies: a deferral must be AFK-anchored with a stable held question and no FIX-NOW feedback (EvaluatePlanDeferral); an acceptance carries no FIX-NOW feedback. The Mode cursor is consumed only for the deferred branch.

func (PolicySet) ImplementationUATDescriptor added in v0.0.5

func (s PolicySet) ImplementationUATDescriptor() DecisionDescriptor[implementationUATRecord]

func (PolicySet) ModeChangedDescriptor added in v0.0.5

func (s PolicySet) ModeChangedDescriptor() DecisionDescriptor[InteractionModeChanged]

ModeChangedDescriptor / Plan*Descriptor / ImplementationUATDescriptor expose the registered descriptors for the #40 lowering consumer. They return the descriptor by value; because the underlying struct fields are unexported, the returned descriptor can only decode/draft through this package's registered catalog.

func (PolicySet) PlanAcceptedDescriptor added in v0.0.5

func (s PolicySet) PlanAcceptedDescriptor() DecisionDescriptor[PlanAccepted]

func (PolicySet) PlanChangesRequestedDescriptor added in v0.0.5

func (s PolicySet) PlanChangesRequestedDescriptor() DecisionDescriptor[PlanChangesRequested]

func (PolicySet) PlanDeferredByAFKDescriptor added in v0.0.5

func (s PolicySet) PlanDeferredByAFKDescriptor() DecisionDescriptor[PlanDeferredByAFK]

type PublicationResult added in v0.0.5

type PublicationResult struct {
	CommandResult
	Candidate  IntegrationCandidateSetID
	Repository RepositoryID
	Evidence   provenance.JournalID
}

PublicationResult identifies the exact publication-evidence event.

type PublishRepositoryInput added in v0.0.5

type PublishRepositoryInput struct {
	Meta       CommandMeta
	Epoch      EpochRootID
	Candidate  IntegrationCandidateSetID
	Repository RepositoryID
	Ref        GitRef
	Commit     provenance.GitOID
	Assignment provenance.AssignmentID
}

PublishRepositoryInput records verified remote publication evidence for one member.

type RatifyInput added in v0.0.5

type RatifyInput struct {
	Deferred      PlanDeferredByAFK
	CurrentLedger []DecisionLedgerEntry
}

RatifyInput is the state EvaluateRatify checks: the recorded deferral and the current ledger it is being ratified against.

type RatifyPlanInput added in v0.0.5

type RatifyPlanInput struct {
	Meta        CommandMeta
	Epoch       EpochRootID
	Proposal    provenance.TaskID
	ReviewRound ReviewRoundID
	PlanUAT     DecisionLedgerEntryID
	Actor       AssertedHumanActor
}

RatifyPlanInput records ratification as a first-class human decision over the accepted review round and Plan UAT decision.

type RepositoryCandidate added in v0.0.5

type RepositoryCandidate struct {
	Repository RepositoryID
	Candidate  ImplementationCandidateID
	Commit     provenance.GitOID
}

RepositoryCandidate is one repository commit included in an integration candidate.

type RepositoryID added in v0.0.5

type RepositoryID string

RepositoryID identifies one repository participating in an integration candidate or publication. It is intentionally distinct from GitOID.

type RequiredRef added in v0.0.5

type RequiredRef struct {
	Kind RequiredRefKind
	ID   string
}

RequiredRef is one required-decision target: its domain and its id string.

func RequiredDecisions added in v0.0.5

func RequiredDecisions(in CoverageInput) []RequiredRef

RequiredDecisions computes the sorted, unique required-decision set from a CoverageInput. The result is the union of the three domains minus every target resolved by a prior canonical Implementation-UAT payload. The input is never mutated.

type RequiredRefKind added in v0.0.5

type RequiredRefKind int

RequiredRefKind is the closed discriminator of a required-decision reference. It records which carry-forward domain a target belongs to so two domains that happen to share an id string never collide.

const (

	// RequiredLedgerDecision is a material agent-judgment ledger entry.
	RequiredLedgerDecision RequiredRefKind
	// RequiredHeldQuestion is a held question carried from the deferred Plan decision.
	RequiredHeldQuestion
	// RequiredDeferredFeedback is a deferred Plan-feedback item carried forward.
	RequiredDeferredFeedback
)

func (RequiredRefKind) String added in v0.0.5

func (k RequiredRefKind) String() string

type ResolutionKind added in v0.0.5

type ResolutionKind int

ResolutionKind is the closed set of carry-forward resolution dispositions. CONFIRM, DEFER, and REPLACE each resolve a target permanently; REPLACE additionally forces a changes-requested verdict (like FIX-NOW feedback) because it records that new work is required.

const (

	// ResolutionConfirm confirms the target as-is.
	ResolutionConfirm ResolutionKind
	// ResolutionDefer resolves the target by deferring it to follow-up work.
	ResolutionDefer
	// ResolutionReplace resolves the target by superseding it, forcing changes-requested.
	ResolutionReplace
)

func (ResolutionKind) String added in v0.0.5

func (k ResolutionKind) String() string

type ReviewAxis added in v0.0.5

type ReviewAxis int

ReviewAxis is the closed set of the three review axes every round has exactly one of.

const (

	// AxisCorrectness reviews behavioral correctness.
	AxisCorrectness ReviewAxis
	// AxisTestQuality reviews test adequacy.
	AxisTestQuality
	// AxisElegance reviews design elegance.
	AxisElegance
)

func (ReviewAxis) String added in v0.0.5

func (a ReviewAxis) String() string

type ReviewFinalizeResult added in v0.0.5

type ReviewFinalizeResult struct {
	CommandResult
	Round        ReviewRoundID
	ReviewEvents [3]provenance.JournalID
}

ReviewFinalizeResult identifies the finalized round and its three axis events.

type ReviewFinding added in v0.0.5

type ReviewFinding struct {
	Task     provenance.TaskID
	Severity FindingSeverity
	Summary  string
}

ReviewFinding is one typed finding submitted only for an implementation review.

type ReviewRecordedEvent added in v0.0.5

type ReviewRecordedEvent struct {
	ReviewedTask provenance.TaskID
	AxisTask     provenance.TaskID
	Kind         SubjectKind
	Verdict      Verdict
}

ReviewRecordedEvent records one axis's binary plan/implementation review outcome against a reviewed task.

func (ReviewRecordedEvent) Family added in v0.0.5

func (ReviewRecordedEvent) SourceTask added in v0.0.5

func (e ReviewRecordedEvent) SourceTask() provenance.TaskID

type ReviewRelation added in v0.0.5

type ReviewRelation int

ReviewRelation is the closed set of typed relationships a review-round plan wires.

const (

	// RelationSubject links the round to its reviewed subject.
	RelationSubject ReviewRelation
	// RelationContains links the round to an axis it contains.
	RelationContains
	// RelationBlockedBy is the parent-blocked-by-child edge (parent first).
	RelationBlockedBy
)

func (ReviewRelation) String added in v0.0.5

func (r ReviewRelation) String() string

type ReviewRoundFinalizedEvent added in v0.0.5

type ReviewRoundFinalizedEvent struct {
	Subject provenance.TaskID
	Epoch   provenance.TaskID
	Round   ReviewRoundID
	Verdict Verdict
}

ReviewRoundFinalizedEvent is the persisted review projection ratification reads.

func (ReviewRoundFinalizedEvent) Family added in v0.0.5

func (ReviewRoundFinalizedEvent) SourceTask added in v0.0.5

type ReviewRoundID added in v0.0.5

type ReviewRoundID string

ReviewRoundID identifies one review round.

type ReviewRoundPlan added in v0.0.5

type ReviewRoundPlan struct {
	ReviewedTask provenance.TaskID
	Subject      ReviewSubjectRef
	Kind         SubjectKind
	RoundHandle  string
	AxisHandles  [3]string
	Tasks        []PlannedTask
	Edges        []PlannedEdge
}

ReviewRoundPlan is the deterministic shape of one review round: the round task, exactly three axis tasks, the eager severity groups for an implementation review, and every typed subject/contains/blocked-by edge. The reviewed task is blocked by the round; the round is blocked by its three axes; each implementation axis is blocked by its three severity groups. Batch-local handles are stable and canonical so a re-plan is identical.

func PlanReviewRound added in v0.0.5

func PlanReviewRound(reviewedTask provenance.TaskID, subject ReviewSubjectRef, kind SubjectKind) (ReviewRoundPlan, error)

PlanReviewRound computes the deterministic review-round graph for a reviewed task and subject. kind must be SubjectPlan or SubjectImplementation; an implementation review eagerly adds the three severity groups per axis. It touches no journal.

type ReviewStartResult added in v0.0.5

type ReviewStartResult struct {
	CommandResult
	Round   ReviewRoundID
	Subject ReviewSubjectRef
}

ReviewStartResult identifies the created review round and its reviewed subject.

type ReviewSubject added in v0.0.5

type ReviewSubject interface {
	// Ref derives the closed sum-level reference.
	Ref() ReviewSubjectRef
	// contains filtered or unexported methods
}

ReviewSubject is the sealed sum of review subjects. Each variant has exactly one canonical id wrapping its snapshot TaskID and derives its own ReviewSubjectRef.

type ReviewSubjectKind added in v0.0.5

type ReviewSubjectKind int

ReviewSubjectKind is the closed discriminator of the review-subject sum.

const (

	// ReviewSubjectDocumentRevision is a document-revision snapshot subject.
	ReviewSubjectDocumentRevision ReviewSubjectKind
	// ReviewSubjectImplementationCandidate is an implementation-candidate snapshot subject.
	ReviewSubjectImplementationCandidate
)

func (ReviewSubjectKind) String added in v0.0.5

func (k ReviewSubjectKind) String() string

type ReviewSubjectRef added in v0.0.5

type ReviewSubjectRef struct {
	Kind       ReviewSubjectKind
	SnapshotID string
}

ReviewSubjectRef is the closed sum-level reference {Kind, SnapshotID}. It is DERIVED from a concrete subject's Ref() — never independently supplied — so the kind and snapshot id cannot drift apart.

type ReviewSubmission added in v0.0.5

type ReviewSubmission interface {
	Validate() error
	// contains filtered or unexported methods
}

ReviewSubmission is the closed sum of plan and implementation review submissions. Its package-private marker prevents a caller from adding an unvalidated variant.

type ReviewSubmitResult added in v0.0.5

type ReviewSubmitResult struct {
	CommandResult
	Round ReviewRoundID
	Axis  ReviewAxis
	Event provenance.JournalID
}

ReviewSubmitResult identifies the immutable event for one axis submission.

type ReviewTaskKind added in v0.0.5

type ReviewTaskKind int

ReviewTaskKind classifies a planned review task by its role in the graph.

const (

	// ReviewTaskRound is the review-round task.
	ReviewTaskRound ReviewTaskKind
	// ReviewTaskAxis is one of the three axis tasks.
	ReviewTaskAxis
	// ReviewTaskGroup is one eager severity group task (implementation reviews only).
	ReviewTaskGroup
)

type ReworkIntegrationCandidateInput added in v0.0.5

type ReworkIntegrationCandidateInput struct {
	Meta        CommandMeta
	Epoch       EpochRootID
	Candidate   IntegrationCandidateSetID
	Assignment  provenance.AssignmentID
	Replacement IntegrationCandidateReplacement
	Rework      ReworkSubmission
}

ReworkIntegrationCandidateInput replaces an integration candidate after findings.

type ReworkSliceInput added in v0.0.5

type ReworkSliceInput struct {
	Meta        CommandMeta
	Epoch       EpochRootID
	Slice       provenance.TaskID
	Candidate   ImplementationCandidateID
	Assignment  provenance.AssignmentID
	Replacement SliceCandidateReplacement
	Rework      ReworkSubmission
}

ReworkSliceInput replaces a slice candidate after complete finding disposition.

type ReworkSubmission added in v0.0.5

type ReworkSubmission struct {
	Findings []FindingResolution
}

ReworkSubmission is the complete typed finding disposition set for one rework.

type SessionClaimOutcome added in v0.0.12

type SessionClaimOutcome struct {
	State SessionClaimState
	// StoredActor is the actor the store now holds for the session: the actor
	// read before a write that found an existing row, the actor this invocation
	// wrote, or the winner read back after a lost race. It is empty when no
	// claim row exists or the winner could not be read back.
	StoredActor string
}

SessionClaimOutcome is what one session-claim attempt did, plus the actor the store holds for the session afterwards. It is returned beside an error, and the error is reserved for a genuine fault: the three ordinary results — a written claim, an already-claimed session, and a claim that lost the race — are all nil-error outcomes, because none of them may fail the hook.

func RecordLifecycleSessionClaim added in v0.0.9

func RecordLifecycleSessionClaim(ctx context.Context, tracker protocol.TaskTracker, harness ir.HarnessID, event model.ContractEventKind, bindings []model.NativeBinding, claim ActorClaim, clock receipt.Clock) (SessionClaimOutcome, error)

RecordLifecycleSessionClaim stores a claim the first time a session is observed. It reads the row for the event's session and, only when no row exists, performs one INSERT ... ON CONFLICT DO NOTHING with no retry.

THE TRIGGER IS FIRST OBSERVATION, NOT THE SESSION-START EVENT. A host that publishes its session-start event before its plugins can subscribe leaves that first session unclaimed for its whole life — OpenCode v2 publishes session.created inside Session.create, and the plugin's subscription is established later with no replay — and every gate on it records UNBOUND and fails open. Binding on the first event that carries the session makes the claim independent of which event arrived first; a session-start event still binds when it is the first one observed. The rule is the same on every harness.

A zero claim, an event with no session binding, and an event for a session that already has a claim all return a nil error without reading a clock or taking a write lock beyond the claim read. The supplied actor is deliberately not resolved here: an unknown claim is still a claim, and is not an unbound session. The first claim wins; a claim that loses the race between this read and this insert reports SessionClaimLostRace rather than a fault, because the hot hook path must not fail every subsequent event of an already-claimed session. The typed outcome is what lets a caller name the winner that the silent no-op used to discard.

func (SessionClaimOutcome) Mismatch added in v0.0.12

func (o SessionClaimOutcome) Mismatch(attempted ActorClaim) bool

Mismatch reports whether this outcome names a stored actor different from the attempted one. It is true only for an already-claimed session or a lost race whose stored actor differs; a written claim and a skipped claim are never a mismatch. The comparison is deliberately not attempted for a state that stores nobody, so a non-empty actor on a sessionless event cannot manufacture a diagnostic about an actor nobody recorded.

type SessionClaimState added in v0.0.12

type SessionClaimState int

SessionClaimState names what ONE session-claim attempt did. It is the typed half of the claim write's result: the hook path may never fail because a claim was not stored, so the caller that wants to know what happened reads this instead of an error.

const (
	// SessionClaimNotAttempted is the zero value: the invocation carried no
	// actor, carried no session binding, or was refused before the store was
	// reached, so no claim row was read or written. It is the zero value on
	// purpose, so a caller that ignores the outcome cannot mistake a skipped
	// claim for a written one.
	SessionClaimNotAttempted SessionClaimState = iota
	// SessionClaimWrote means this invocation inserted the claim row, so the
	// store now holds the actor it attempted.
	SessionClaimWrote
	// SessionClaimAlreadyClaimed means a claim row already existed; this
	// invocation read it and wrote nothing.
	SessionClaimAlreadyClaimed
	// SessionClaimLostRace means the INSERT ... ON CONFLICT DO NOTHING changed
	// no row because another writer claimed the session between this
	// invocation's read and its insert. StoredActor names the winner when it
	// could be read back.
	SessionClaimLostRace
)

func (SessionClaimState) String added in v0.0.12

func (s SessionClaimState) String() string

String returns the stable, lower-case spelling of the state, for a diagnostic a maintainer can grep. The zero value answers "not_attempted" rather than the empty string, so a member that was never set is distinguishable in text.

type SetInteractionModeInput added in v0.0.5

type SetInteractionModeInput struct {
	Meta  CommandMeta
	Epoch EpochRootID
	Mode  InteractionMode
	Actor AssertedHumanActor
}

SetInteractionModeInput records an explicit human choice of epoch interaction mode.

type SetSliceCandidateInput added in v0.0.5

type SetSliceCandidateInput struct {
	Meta       CommandMeta
	Epoch      EpochRootID
	Slice      provenance.TaskID
	Repository RepositoryID
	Commit     provenance.GitOID
	Assignment provenance.AssignmentID
}

SetSliceCandidateInput records an immutable repository candidate for one slice.

type SkillOutcome added in v0.0.5

type SkillOutcome int

SkillOutcome is the closed outcome of a recorded skill run.

const (

	// SkillSucceeded marks a skill run that completed successfully.
	SkillSucceeded SkillOutcome
	// SkillFailed marks a skill run that failed.
	SkillFailed
)

func (SkillOutcome) String added in v0.0.5

func (o SkillOutcome) String() string

type SkillRunEvent added in v0.0.5

type SkillRunEvent struct {
	Task    provenance.TaskID
	Skill   string
	Actor   provenance.ActorID
	Outcome SkillOutcome
}

SkillRunEvent records a skill-run material event bound to a task and an actor.

func (SkillRunEvent) Family added in v0.0.5

func (SkillRunEvent) SourceTask added in v0.0.5

func (e SkillRunEvent) SourceTask() provenance.TaskID

type SliceCandidateReplacement added in v0.0.5

type SliceCandidateReplacement struct {
	Repository RepositoryID
	Commit     provenance.GitOID
}

SliceCandidateReplacement is the complete immutable replacement value for one slice. The aggregate allocates its ImplementationCandidateID when committing this value.

type SliceCloseAuthorization added in v0.0.5

type SliceCloseAuthorization struct {
	GoverningSupervisor provenance.AssignmentID
	ReviewRound         ReviewRoundID
	Candidate           ImplementationCandidateID
	ReviewEvents        [3]provenance.JournalID
}

SliceCloseAuthorization is the typed authorization a slice close requires: the governing supervisor's owner-responsibility assignment, the clean review round, the canonical candidate, and the three canonical review EventIDs (one per axis). It carries no caller actor override — closure derives the actor from the governing assignment.

func (SliceCloseAuthorization) Validate added in v0.0.5

func (a SliceCloseAuthorization) Validate() error

Validate rejects a malformed authorization: a missing supervisor/round/candidate, or review events that are not three distinct non-zero journal ids.

type SliceResult added in v0.0.5

type SliceResult struct {
	CommandResult
	Slice provenance.TaskID
}

SliceResult identifies a created slice task.

type StartReviewInput added in v0.0.5

type StartReviewInput struct {
	Meta    CommandMeta
	Epoch   EpochRootID
	Subject ReviewSubjectRef
}

StartReviewInput starts a round after resolving the unique active governing assignment from the epoch graph. The caller cannot substitute a human actor.

type StatusReader added in v0.0.5

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

StatusReader is a read-only audit-trail reader for the status verb. The zero value is invalid; use NewStatusReaderFromDB to construct one.

func NewStatusReaderFromDB added in v0.0.5

func NewStatusReaderFromDB(db *sql.DB) *StatusReader

NewStatusReaderFromDB wraps an already-open *sql.DB as a StatusReader. The caller retains ownership of db and is responsible for closing it; Close on the returned reader is a no-op. This constructor exists so callers that have already verified the schema version and opened the database (e.g. EpochStatus) can reuse the handle for enrichment queries without a second open.

func (*StatusReader) Close added in v0.0.5

func (r *StatusReader) Close() error

Close is a no-op. StatusReader does not own its database handle — the caller that constructed it via NewStatusReaderFromDB retains ownership and is responsible for closing the underlying *sql.DB. Safe to call multiple times.

func (*StatusReader) CountEventsByEpoch added in v0.0.5

func (r *StatusReader) CountEventsByEpoch(ctx context.Context) (map[string]int, error)

CountEventsByEpoch returns a map from epochId to event count for all epochs that have at least one event. A single COUNT(*) GROUP BY query avoids the N+1 anti-pattern of loading every event payload for the listing view.

func (*StatusReader) QueryEvents added in v0.0.5

func (r *StatusReader) QueryEvents(ctx context.Context, epochId string, phase *protocol.PhaseId, role *string) ([]protocol.AuditEvent, error)

QueryEvents returns all audit events for epochId, oldest first, filtered optionally by phase and role (nil = no filter).

Delegates to audit.QueryEventsOn, the single canonical query implementation. Both StatusReader and SqliteAuditTrail use the same shared function so any schema change (v5+) is applied in one place.

type SubjectKind added in v0.0.5

type SubjectKind int

SubjectKind is the closed review/UAT subject discriminator: a plan document or an implementation slice. The issue fixes review kind to exactly plan or implementation; UAT reuses the same two-valued distinction.

const (

	// SubjectPlan is a plan-document review or plan UAT.
	SubjectPlan SubjectKind
	// SubjectImplementation is a slice/implementation review or implementation UAT.
	SubjectImplementation
)

func (SubjectKind) String added in v0.0.5

func (k SubjectKind) String() string

type SubmitReviewInput added in v0.0.5

type SubmitReviewInput struct {
	Meta       CommandMeta
	Epoch      EpochRootID
	Round      ReviewRoundID
	Axis       ReviewAxis
	Assignment provenance.AssignmentID
	Submission ReviewSubmission
}

SubmitReviewInput is authorized by the exact active axis-reviewer assignment.

type TaskClosedEvent added in v0.0.5

type TaskClosedEvent struct {
	Task   provenance.TaskID
	Reason string
}

TaskClosedEvent is the task-closed domain marker (pasture.task.closed/v1). It is a non-lifecycle domain record; the authorized close policy separately drives the journal's own status transition.

func (TaskClosedEvent) Family added in v0.0.5

func (TaskClosedEvent) SourceTask added in v0.0.5

func (e TaskClosedEvent) SourceTask() provenance.TaskID

type TimelineEntry added in v0.0.5

type TimelineEntry struct {
	EventID    provenance.JournalID
	Task       provenance.TaskID
	RecordedAt int64
	Kind       string
	EntryKind  TimelineEntryKind
	Interval   *ActivityInterval
}

TimelineEntry is one composed timeline row. EventID is the preserved source id; Interval is set only for activity entries.

func ComposeTimeline added in v0.0.5

func ComposeTimeline(sources []TimelineSource) []TimelineEntry

ComposeTimeline composes sources into the deterministic (RecordedAt, EventID) timeline, de-duplicating by EventID (a source event appears once) and preserving each source EventID. The input slice is never mutated. Overlapping activity intervals are preserved unchanged; they are not merged or split.

type TimelineEntryKind added in v0.0.5

type TimelineEntryKind int

TimelineEntryKind classifies a composed timeline entry.

const (
	// TimelineEvent is a point task-event (no activity interval).
	TimelineEvent TimelineEntryKind = iota
	// TimelineActivity is an Activity interval (point/open/closed).
	TimelineActivity
)

type TimelineSource added in v0.0.5

type TimelineSource struct {
	EventID    provenance.JournalID
	Task       provenance.TaskID
	RecordedAt int64
	Kind       string
	Activity   *ActivityInterval
}

TimelineSource is one raw journal task-event, optionally carrying an Activity interval.

type UATFeedbackID added in v0.0.5

type UATFeedbackID string

UATFeedbackID identifies one UAT feedback item so a later gate can resolve or carry it.

type UATFeedbackItem added in v0.0.5

type UATFeedbackItem struct {
	ID     UATFeedbackID `json:"id"`
	Body   string        `json:"body"`
	FixNow bool          `json:"fixNow"`
}

UATFeedbackItem is one piece of UAT feedback. FixNow marks blocking (FIX-NOW) feedback, which forces a changes-requested verdict and makes an AFK deferral ineligible.

type UATInteraction added in v0.0.5

type UATInteraction struct {
	Prompt   string `json:"prompt"`
	Response string `json:"response"`
}

UATInteraction is one verbatim prompt/response exchange from a UAT session. Both halves are preserved exactly so a restart decode reproduces every interaction.

type UATRecordedEvent added in v0.0.5

type UATRecordedEvent struct {
	Subject    provenance.TaskID
	Kind       SubjectKind
	Resolution Verdict
}

UATRecordedEvent records a plan or implementation UAT resolution against a subject task.

func (UATRecordedEvent) Family added in v0.0.5

func (UATRecordedEvent) SourceTask added in v0.0.5

func (e UATRecordedEvent) SourceTask() provenance.TaskID

type Verdict added in v0.0.5

type Verdict int

Verdict is the closed binary review/UAT verdict. The issue fixes review submit to one binary ACCEPT/REVISE and UAT to an accept/revise resolution; both reuse this two-valued enum rather than duplicating a per-context boolean.

const (

	// VerdictAccept is the accepting disposition.
	VerdictAccept Verdict
	// VerdictRevise is the revising disposition.
	VerdictRevise
)

func (Verdict) String added in v0.0.5

func (v Verdict) String() string

type WellKnownAgentCache

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

WellKnownAgentCache holds the well-known-name → AgentId mapping. Construct via NewWellKnownAgentCache and populate via RegisterWellKnownAgents. Cache lookups (Get / MustGet / Names) are safe for concurrent use after population.

A nil *WellKnownAgentCache is NOT a valid cache: all methods other than Len would panic. RegisterWellKnownAgents asserts the pointer is non-nil before populating.

func NewWellKnownAgentCache

func NewWellKnownAgentCache() *WellKnownAgentCache

NewWellKnownAgentCache returns an empty cache ready for population by RegisterWellKnownAgents. The initial capacity is sized to fit the canonical 15-entry registry without a rehash.

func (*WellKnownAgentCache) Get

Get returns the AgentId for name. The boolean is true when name is a known entry, false otherwise. Callers that have a static guarantee that name is in the registry (e.g. a constant from well_known_registry.go) may prefer MustGet; callers reading user-provided strings should prefer this method.

func (*WellKnownAgentCache) Len

func (c *WellKnownAgentCache) Len() int

Len returns the number of entries in the cache. A nil receiver returns 0 so the daemon can safely log `cache.Len()` before construction completes (defensive for failure paths in main.go that may have a nil cache pointer).

func (*WellKnownAgentCache) MustGet

func (c *WellKnownAgentCache) MustGet(name string) (provenance.AgentID, error)

MustGet returns the AgentId for name or returns a *StructuredError of CategoryValidation if name is not in the cache. Use from activity hot paths where the caller statically knows which well-known name it wants (e.g. CheckConstraints always wants check-constraints) — a missing entry then indicates a wiring bug (the cache was not populated, or the registry was edited without re-registering).

Returns the actionable error rather than panicking so the caller can surface it as a failed step without crashing the daemon.

func (*WellKnownAgentCache) Names

func (c *WellKnownAgentCache) Names() []string

Names returns the sorted slice of all well-known names currently in the cache. Sorted output makes test assertions stable (no map iteration nondeterminism) and supports diff-friendly debug logging. The returned slice is a fresh copy; callers may mutate it without affecting the cache.

type WellKnownAgentSpec

type WellKnownAgentSpec struct {
	// Name is the stable logical name. It survives across restarts and is
	// minted exactly once per database (idempotency anchor on the UNIQUE
	// constraint over `pasture_well_known_agents.name`). Convention:
	// `pasture/automaton/<role-kebab>` (or `pasture/automaton/hook/<HookName>`).
	Name string

	// Role is the AutomatonRole this agent fulfils. MUST be one of
	// `protocol.AllAutomatonRoles` minus `AutomatonRoleNone` (every
	// concrete automaton has a non-None role). Validated at registration
	// time by ensureWellKnownAgent via Role.IsValid().
	Role protocol.AutomatonRole
}

WellKnownAgentSpec pairs a stable logical name (the PK in `pasture_well_known_agents`) with its `protocol.AutomatonRole` (the value stored in `pasture_agent_categories.automaton_role`). The PastureRole for every well-known automaton is `None` (per §7.7.2 — these are software automata, not workflow agents).

func WellKnownAgents

func WellKnownAgents() []WellKnownAgentSpec

WellKnownAgents returns the canonical 15-entry slice of well-known agents in PROPOSAL-2 §7.7.2 row order. The returned slice is a fresh copy; callers may not assume it shares storage with package internals (this keeps the canonical list immutable from outside the package).

Order:

0:    ConstraintChecker — pasture/automaton/check-constraints
1-3:  TransitionGate    — pasture/automaton/transition-gate/{consensus,vote-threshold,exit-condition}
4-12: HookHandler       — pasture/automaton/hook/<HookName> × 9
13:   ConsensusReached  — pasture/automaton/consensus-reached
14:   CreateFollowup    — pasture/automaton/create-followup

Total: 15. Length-checked by the WellKnownAgentCount constant below.

Jump to

Keyboard shortcuts

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