observe

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jul 26, 2026 License: Apache-2.0 Imports: 3 Imported by: 0

Documentation

Overview

Package observe implements the minimum slice of Chatwright's Observation Model: a platform-neutral projection of a chat's visible conversation and available actions, built from a Platform Emulator's structured journal (platform.JournalEntry) rather than from any platform's own wire types.

An Engine turns a chat's journal into a sequence of Observations. Each Observation carries the chat's currently visible messages, their currently available actions, and the explicit Changes since the Engine's previous Observation — an actor is never required to diff two Observations by hand (see spec/features/chatwright/observation-model/observation-lineage). Raw platform payloads (Telegram callback data, native message IDs, wire envelopes, ...) never reach this package's exported types: they stay on platform.JournalEntry and remain available to developers only through the emulator's Transcript/Journal trace, never through an Observation or AvailableAction (see spec/features/chatwright/observation-model/actor-actions).

This is the minimum working slice — visible messages, generic actions and explicit changes. Semantic history windows, summaries, goals and journey memory (observation-context) are a later slice; so is the actual observe-plan-act-validate actor loop, which is not wired into this package.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActionProposal

type ActionProposal struct {
	ObservationSequence int64
	ActionID            string
}

ActionProposal is an actor's intent to activate a previously observed action: the Observation it was chosen from, and the action's stable ID. Validate checks it against the Engine's CURRENT journal state — the actor proposes intent, it never makes that intent authoritative by asserting it (see spec/features/chatwright/observation-model/actor-actions).

type Actor

type Actor string

Actor identifies which side of a conversation produced a VisibleMessage. It is a string type, not an int enum, so it marshals to human-readable JSON (see AGENTS.md's "JSON artefacts carry human-readable string constants" convention) rather than a bare, meaningless integer.

const (
	ActorUser Actor = "user"
	ActorBot  Actor = "bot"
)

func (Actor) String

func (a Actor) String() string

String renders a for diagnostics and test failure messages.

type AvailableAction

type AvailableAction struct {
	ID     string `json:"id"`     // opaque, stable Chatwright action identity
	Label  string `json:"label"`  // user-visible text
	SeenAt int64  `json:"seenAt"` // the Observation.Sequence this action was (re)issued at; copy this into an ActionProposal
}

AvailableAction is a generic, opaque interaction an actor can take: a stable Chatwright ID and its user-visible label. Platform-native callback data, request payloads and button coordinates are never exposed here — an authorised developer inspector reaches those through the platform's Journal/Transcript trace, not through this type (see spec/features/chatwright/observation-model/actor-actions).

type Change

type Change struct {
	Kind      ChangeKind `json:"kind"`
	MessageID string     `json:"messageId"`
	Actor     Actor      `json:"actor"`
	// PreviousVersion is set for ChangeMessageEdited: the message's Version
	// before this change.
	PreviousVersion int `json:"previousVersion"`
	// Version is the message's Version after this change (ChangeNewMessage,
	// ChangeMessageEdited) or its current, unchanged Version
	// (ChangeActionsChanged).
	Version int `json:"version"`
}

Change is one explicit, structured difference between an Observation and the Engine's previous Observation, computed by the Engine so actors reason about what changed without diffing two Observations themselves (see spec/features/chatwright/observation-model/observation-lineage).

type ChangeKind

type ChangeKind string

ChangeKind classifies one entry in an Observation's Changes feed. It is a string type, not an int enum, so it marshals to human-readable JSON (see AGENTS.md's "JSON artefacts carry human-readable string constants" convention) rather than a bare, meaningless integer.

const (
	// ChangeNewMessage: a logical message not present in the Engine's
	// previous Observation now exists.
	ChangeNewMessage ChangeKind = "new-message"
	// ChangeMessageEdited: an existing logical message's Version advanced.
	ChangeMessageEdited ChangeKind = "edited-message"
	// ChangeActionsChanged: an existing logical message's available actions
	// changed without its Version advancing.
	ChangeActionsChanged ChangeKind = "actions-changed"
)

func (ChangeKind) String

func (k ChangeKind) String() string

String renders k for diagnostics and test failure messages.

type ChatRef

type ChatRef struct {
	ChatID int64 `json:"chatId"`
}

ChatRef identifies the chat an Observation projects. It carries Chatwright's own chat identity (see cw.Chat.PrivateChat) — never a raw platform chat ID scraped from the wire.

type Engine

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

Engine projects Observations for one chat from a Journaler's structured journal. It owns the per-Engine observation sequence and remembers every Observation it has issued, so Changes are always computed by the Engine — never by the actor — and a later action proposal can be validated against the Observation it was chosen from (see Validate).

func NewEngine

func NewEngine(j Journaler, chat ChatRef) *Engine

NewEngine constructs an Engine that projects chat's conversation from j.

func (*Engine) Observe

func (e *Engine) Observe() (*Observation, error)

Observe projects the chat's current journal state into a new Observation. Its Changes are computed against the Engine's previously issued Observation, if any — the actor is never asked to diff two Observations itself.

func (*Engine) Validate

func (e *Engine) Validate(proposal ActionProposal) (ValidationResult, error)

Validate checks proposal against the Engine's CURRENT journal state — never against the (possibly outdated) Observation the actor originally saw — and returns a deterministic fresh/stale Freshness with a reason. Validate does not execute anything, and it does not itself issue or count as a new Observation.

type Freshness added in v0.5.0

type Freshness string

Freshness is the deterministic outcome of validating an ActionProposal: is the proposed action still present, unchanged, in the Engine's current projection? It is a validity check against the Engine's own state, not a judgement against a criterion — see the chatwright/chatwright glossary's "verdict" entry for that (the AI-judged assertion outcome). It is a string type, not an int enum, so it marshals to human-readable JSON (see AGENTS.md's "JSON artefacts carry human-readable string constants" convention) rather than a bare, meaningless integer.

const (
	// FreshnessFresh: the proposed action is present, unchanged, in the
	// Engine's current projection.
	FreshnessFresh Freshness = "fresh"
	// FreshnessStale: the proposed action is not present in the Engine's
	// current projection — its source observation is out of date, or was
	// never issued by this Engine at all.
	FreshnessStale Freshness = "stale"
)

func (Freshness) String added in v0.5.0

func (f Freshness) String() string

String renders f for diagnostics and test failure messages.

type Journaler

type Journaler interface {
	// Journal returns chatID's chronological, structured journal entries.
	Journal(chatID int64) ([]platform.JournalEntry, error)
}

Journaler is the read seam an Engine projects Observations from — the subset of platform.Emulator this package depends on. Any platform.Emulator satisfies it; tests may supply a narrower fake without running an emulator.

type Observation

type Observation struct {
	// Sequence is monotonic per Engine, starting at 1.
	Sequence int64 `json:"sequence"`
	// PreviousSequence is the Sequence of the Observation this one
	// supersedes; 0 for an Engine's first Observation.
	PreviousSequence int64   `json:"previousSequence"`
	Chat             ChatRef `json:"chat"`
	// Messages is chronological, oldest to newest: one entry per currently
	// visible logical message, at its current (possibly-edited) version.
	Messages []VisibleMessage `json:"messages"`
	// Changes is empty for an Engine's first Observation; otherwise the
	// explicit differences since PreviousSequence.
	Changes []Change `json:"changes"`
}

Observation is one platform-neutral snapshot of a chat's visible conversation and available actions, with explicit lineage back to the Engine's previous Observation. Observations are produced by an Engine — actors never build or diff one by hand.

type ValidationResult

type ValidationResult struct {
	Freshness Freshness
	// Reason explains Freshness; always set, safe to surface to a scripted
	// actor's assertion, an AI actor's recovery prompt, or Studio.
	Reason string
	// Current is the action's current form; set only when Freshness is
	// FreshnessFresh.
	Current *AvailableAction
}

ValidationResult is the deterministic result of validating an ActionProposal.

type VisibleMessage

type VisibleMessage struct {
	ID      string            `json:"id"`      // stable synthetic Chatwright identity for this logical message, e.g. "msg7"
	Version int               `json:"version"` // monotonic version of this logical message; 0 for the original send
	Edited  bool              `json:"edited"`  // true once Version has advanced past 0
	Actor   Actor             `json:"actor"`   // who produced the message
	Text    string            `json:"text"`
	Actions []AvailableAction `json:"actions"` // interactions currently attached to this message
}

VisibleMessage is one user-visible logical message: stable identity across edits, a monotonic version and an edited flag, plus the actions currently attached to it. Only normalized text and action labels are carried — no platform-native message IDs, callback data or wire payloads (see spec/features/chatwright/observation-model/visible-conversation).

Jump to

Keyboard shortcuts

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