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
- Variables
- func BindEngineGovernedAllocation(tracker interface{}, runner composedAllocationRunner) error
- func CheckSchemaVersion(db *sql.DB, dbPath string) error
- func CreateSliceAuditParticipant(ctx context.Context, tx provenance.GovernedAllocationTransaction, ...) error
- func DecodeDecision[T any](catalog DecisionCatalog, descriptor DecisionDescriptor[T], ...) (T, error)
- func DefaultDBPath() string
- func DefaultNamespace() (string, error)
- func EvaluatePlanDeferral(in PlanDeferralInput) error
- func EvaluateRatify(policy PolicySet, in RatifyInput) error
- func GovernedAllocationAuditParticipant(ctx context.Context, tx provenance.GovernedAllocationTransaction, ...) error
- func LifecycleSession(bindings []model.NativeBinding) (string, error)
- func MapMaterialEvent(ev MaterialEvent) (provenance.Effect, error)
- func NewGateReader(tracker protocol.TaskTracker, harness ir.HarnessID, session string) (gateauthority.Reader, error)
- func NewLifecycleBlobStore(tracker protocol.TaskTracker) (receipt.SQLiteBlobStore, error)
- func NewLifecycleReader(tracker protocol.TaskTracker) (model.LifecycleReader, error)
- func NewLifecycleReceiptService(tracker protocol.TaskTracker, clock receipt.Clock, ...) (receipt.Service, error)
- func NewLifecycleReceiptServiceWithProfile(tracker protocol.TaskTracker, clock receipt.Clock, ...) (receipt.Service, error)
- func OpenAuditDBForFreeFloating(dbPath string) (*sql.DB, error)
- func OpenTaskTracker(dbPath string) (protocol.TaskTracker, error)
- func OpenTaskTrackerWithOptions(dbPath string, opts ...OpenTaskTrackerOption) (protocol.TaskTracker, error)
- func OpenTracker(dbPath string) (provenance.Tracker, error)
- func RebuildLifecycleOccurrences(ctx context.Context, tracker protocol.TaskTracker) error
- func RebuildLifecycleOccurrencesReporting(ctx context.Context, tracker protocol.TaskTracker) (projection.ReclaimOutcome, error)
- func RecordGitEvent(ctx context.Context, tracker protocol.TaskTracker, auditDB *sql.DB, sha string, ...) (int64, error)
- func RecordSessionEvent(ctx context.Context, tracker protocol.TaskTracker, auditDB *sql.DB, ...) (int64, error)
- func RecordSkillEvent(ctx context.Context, tracker protocol.TaskTracker, auditDB *sql.DB, ...) (int64, error)
- func RegisterWellKnownAgents(ctx context.Context, tracker protocol.TaskTracker, cache *WellKnownAgentCache) error
- func ResolveDBPoolSize() (int, error)
- func ResolveNamespace(explicit string) (string, error)
- func SupportsEngineGovernedAllocation(tracker interface{}) bool
- func UnbindEngineGovernedAllocation(tracker interface{}, runner composedAllocationRunner)
- func VerifyCoverage(stored CoverageDigest, spec CoverageDigestSpec) error
- type ActivityInterval
- type ActorClaim
- type AssertedHumanActor
- type AssignmentAuthenticationError
- type AssignmentCompletedEvent
- type AssignmentEpisode
- type AssignmentProjection
- type AssignmentRole
- type AssignmentStartedEvent
- type AssignmentTransition
- type AssignmentTransitionKind
- type AtomicTaskUpdater
- type CandidateResult
- type CanonicalDecisionPayload
- type CloseSliceInput
- type CommandMeta
- type CommandResult
- type CoverageDigest
- type CoverageDigestSpec
- type CoverageInput
- type CreateIntegrationCandidateInput
- type CreateSliceInput
- type DatabaseFilename
- type DecisionAttribution
- type DecisionBinding
- type DecisionCatalog
- type DecisionCatalogEntry
- type DecisionCodecID
- type DecisionDescriptor
- type DecisionDraft
- type DecisionEncoding
- type DecisionKindID
- type DecisionLedgerEntry
- type DecisionLedgerEntryID
- type DecisionQuery
- type DecisionResult
- type DecisionSchemaDigest
- type DeferredFeedbackResolution
- type DocumentRevisionID
- type DocumentRevisionSubject
- type EpochAssignmentService
- type EpochDecisionRecordedEvent
- type EpochHumanService
- type EpochHumanServiceFactory
- type EpochLanded
- type EpochMutationKind
- type EpochRaceBarrier
- type EpochRootID
- type EpochService
- type EpochServiceFactory
- type EpochServiceOptions
- type EpochServiceSynchronization
- type FinalizeReviewInput
- type FindingDisposition
- type FindingResolution
- type FindingSeverity
- type GateClaimMalformedError
- type GateReadError
- type GateReadIntegrityError
- type GateReadStage
- type GateReaderCapabilityError
- type GateReaderScopeError
- type GateRoleSourceError
- type GateSnapshotClosedError
- type GitRef
- type GitRemoteRefVerifiedEvent
- type HeldQuestionResolution
- type HeldUATQuestion
- type HeldUATQuestionID
- type ImplUATPayload
- type ImplementationCandidateID
- type ImplementationCandidateSubject
- type ImplementationReviewSubmission
- type ImplementationUATDecision
- type ImplementationUATInput
- type ImplementationUATVerdict
- type IntegrationCandidateReplacement
- type IntegrationCandidateResult
- type IntegrationCandidateSetID
- type InteractionMode
- type InteractionModeChanged
- type InteractionModeCursor
- type LandInput
- type LedgerDecisionResolution
- type LegacyActorResolver
- type LegacyAuditImportedEvent
- type LegacyAuditImporter
- type LegacyImportOutcome
- type MaterialEvent
- type MaterialEventFamily
- type OpenTaskTrackerOption
- type PlanAccepted
- type PlanChangesRequested
- type PlanDeferralInput
- type PlanDeferredByAFK
- type PlanRatified
- type PlanReviewFeedback
- type PlanReviewSubmission
- type PlanUATDecision
- type PlanUATDecisionID
- type PlanUATInput
- type PlanUATPayload
- type PlanUATSnapshot
- type PlanUATVerdict
- type PlannedEdge
- type PlannedTask
- type PolicySet
- func (s PolicySet) DraftImplementationUAT(verdict ImplementationUATVerdict, p ImplUATPayload) (DecisionDraft, error)
- func (s PolicySet) DraftLanded(v EpochLanded) (DecisionDraft, error)
- func (s PolicySet) DraftModeChange(c InteractionModeChanged) (DecisionDraft, error)
- func (s PolicySet) DraftPlanRatified(v PlanRatified) (DecisionDraft, error)
- func (s PolicySet) DraftPlanUAT(d PlanUATDecision) (DecisionDraft, error)
- func (s PolicySet) ImplementationUATDescriptor() DecisionDescriptor[implementationUATRecord]
- func (s PolicySet) ModeChangedDescriptor() DecisionDescriptor[InteractionModeChanged]
- func (s PolicySet) PlanAcceptedDescriptor() DecisionDescriptor[PlanAccepted]
- func (s PolicySet) PlanChangesRequestedDescriptor() DecisionDescriptor[PlanChangesRequested]
- func (s PolicySet) PlanDeferredByAFKDescriptor() DecisionDescriptor[PlanDeferredByAFK]
- type PublicationResult
- type PublishRepositoryInput
- type RatifyInput
- type RatifyPlanInput
- type RepositoryCandidate
- type RepositoryID
- type RequiredRef
- type RequiredRefKind
- type ResolutionKind
- type ReviewAxis
- type ReviewFinalizeResult
- type ReviewFinding
- type ReviewRecordedEvent
- type ReviewRelation
- type ReviewRoundFinalizedEvent
- type ReviewRoundID
- type ReviewRoundPlan
- type ReviewStartResult
- type ReviewSubject
- type ReviewSubjectKind
- type ReviewSubjectRef
- type ReviewSubmission
- type ReviewSubmitResult
- type ReviewTaskKind
- type ReworkIntegrationCandidateInput
- type ReworkSliceInput
- type ReworkSubmission
- type SessionClaimOutcome
- type SessionClaimState
- type SetInteractionModeInput
- type SetSliceCandidateInput
- type SkillOutcome
- type SkillRunEvent
- type SliceCandidateReplacement
- type SliceCloseAuthorization
- type SliceResult
- type StartReviewInput
- type StatusReader
- type SubjectKind
- type SubmitReviewInput
- type TaskClosedEvent
- type TimelineEntry
- type TimelineEntryKind
- type TimelineSource
- type UATFeedbackID
- type UATFeedbackItem
- type UATInteraction
- type UATRecordedEvent
- type Verdict
- type WellKnownAgentCache
- type WellKnownAgentSpec
Constants ¶
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.
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.
const DBPathEnv = "PASTURE_DB_PATH"
DBPathEnv is the environment variable users can set to override the default unified pasture database location (see DefaultDBPath).
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).
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.
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
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.
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.
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 ¶
var FindingSeverities = [3]FindingSeverity{SeverityBlocker, SeverityImportant, SeverityMinor}
FindingSeverities is the canonical ordered triple of severities.
var ReviewAxes = [3]ReviewAxis{AxisCorrectness, AxisTestQuality, AxisElegance}
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
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
func CreateSliceAuditParticipant(ctx context.Context, tx provenance.GovernedAllocationTransaction, request provenance.GovernedAllocationRequest, closure provenance.OperationClosure) error
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:
- $PASTURE_DB_PATH
- $XDG_DATA_HOME/pasture/pasture.db
- $HOME/.local/share/pasture/pasture.db
- .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 ¶
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
func GovernedAllocationAuditParticipant(ctx context.Context, tx provenance.GovernedAllocationTransaction, request provenance.GovernedAllocationRequest, closure provenance.OperationClosure) error
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 OpenAuditDBForFreeFloating ¶
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
ResolveDBPoolSize resolves the effective connection-pool size for the pasture-owned audit handle from two sources, highest-priority first:
- $PASTURE_DB_POOL_SIZE (non-empty, parses as a positive int).
- 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 ¶
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
func (e *AssignmentAuthenticationError) Error() string
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
func (e *AssignmentAuthenticationError) Unwrap() error
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) Family() MaterialEventFamily
func (AssignmentCompletedEvent) SourceTask ¶ added in v0.0.5
func (e AssignmentCompletedEvent) SourceTask() provenance.TaskID
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
func (p AssignmentProjection) OwnerOf(task provenance.TaskID) (provenance.ActorID, bool)
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) Family() MaterialEventFamily
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
func (d DecisionDescriptor[T]) Schema() DecisionSchemaDigest
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
func (s DocumentRevisionSubject) Ref() ReviewSubjectRef
Ref derives the document-revision subject reference.
type EpochAssignmentService ¶ added in v0.0.5
type EpochAssignmentService interface {
StartReview(context.Context, StartReviewInput) (ReviewStartResult, error)
SubmitReview(context.Context, SubmitReviewInput) (ReviewSubmitResult, error)
FinalizeReview(context.Context, FinalizeReviewInput) (ReviewFinalizeResult, error)
CreateSlice(context.Context, CreateSliceInput) (SliceResult, error)
SetSliceCandidate(context.Context, SetSliceCandidateInput) (CandidateResult, error)
ReworkSlice(context.Context, ReworkSliceInput) (CandidateResult, error)
CloseSlice(context.Context, CloseSliceInput) (CommandResult, error)
CreateIntegrationCandidate(context.Context, CreateIntegrationCandidateInput) (IntegrationCandidateResult, error)
ReworkIntegrationCandidate(context.Context, ReworkIntegrationCandidateInput) (IntegrationCandidateResult, error)
PublishRepository(context.Context, PublishRepositoryInput) (PublicationResult, error)
}
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) Family() MaterialEventFamily
func (EpochDecisionRecordedEvent) SourceTask ¶ added in v0.0.5
func (e EpochDecisionRecordedEvent) SourceTask() provenance.TaskID
type EpochHumanService ¶ added in v0.0.5
type EpochHumanService interface {
SetInteractionMode(context.Context, SetInteractionModeInput) (DecisionResult, error)
ShowInteractionMode(context.Context, EpochRootID) (InteractionModeCursor, error)
RecordPlanUAT(context.Context, PlanUATInput) (DecisionResult, error)
RatifyPlan(context.Context, RatifyPlanInput) (DecisionResult, error)
RecordImplementationUAT(context.Context, ImplementationUATInput) (DecisionResult, error)
Land(context.Context, LandInput) (DecisionResult, error)
}
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
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) Family() MaterialEventFamily
func (GitRemoteRefVerifiedEvent) SourceTask ¶ added in v0.0.5
func (e GitRemoteRefVerifiedEvent) SourceTask() provenance.TaskID
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
func (s ImplementationCandidateSubject) Ref() ReviewSubjectRef
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
func (s ImplementationReviewSubmission) Validate() error
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) Family() MaterialEventFamily
func (LegacyAuditImportedEvent) SourceTask ¶ added in v0.0.5
func (e LegacyAuditImportedEvent) SourceTask() provenance.TaskID
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
func (f MaterialEventFamily) EventKind() provenance.EventKind
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
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) Family() MaterialEventFamily
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) Family() MaterialEventFamily
func (ReviewRoundFinalizedEvent) SourceTask ¶ added in v0.0.5
func (e ReviewRoundFinalizedEvent) SourceTask() provenance.TaskID
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) Family() MaterialEventFamily
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
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) Family() MaterialEventFamily
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
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) Family() MaterialEventFamily
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 )
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 ¶
func (c *WellKnownAgentCache) Get(name string) (provenance.AgentID, bool)
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.
Source Files
¶
- afk_ratify.go
- assignment_authentication.go
- assignment_authority.go
- assignment_transfer.go
- decision_ledger.go
- epoch_assignment_service.go
- epoch_authority.go
- epoch_candidate_commands.go
- epoch_human_service.go
- epoch_review_commands.go
- epoch_service.go
- free_floating.go
- gate_reader.go
- governed_create_slice.go
- interaction_mode.go
- legacy_import.go
- lifecycle_identity.go
- material_events.go
- open.go
- open_ro.go
- open_unified.go
- paths.go
- policy_set.go
- pool.go
- review_projection.go
- session_claim.go
- system_identity.go
- task_update_atomic.go
- timeline_projection.go
- tracker.go
- uat_coverage.go
- uat_policy.go
- well_known.go
- well_known_cache.go
- well_known_registry.go