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 ¶
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.
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 (*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 verdict with a reason. Validate does not execute anything, and it does not itself issue or count as a new Observation.
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 {
Verdict Verdict
// Reason explains the verdict; 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 Verdict is
// VerdictFresh.
Current *AvailableAction
}
ValidationResult is the deterministic result of validating an ActionProposal.
type Verdict ¶
type Verdict string
Verdict is the deterministic outcome of validating an ActionProposal. 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 ( // VerdictFresh: the proposed action is present, unchanged, in the // Engine's current projection. VerdictFresh Verdict = "fresh" // VerdictStale: 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. VerdictStale Verdict = "stale" )
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).