refactor(goal): persist state with domain events

This commit is contained in:
_Kerman
2026-07-31 22:52:18 +08:00
parent b6cf9298e3
commit 1a09174987
48 changed files with 354 additions and 650 deletions

View File

@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write docs/core-data-structures/goal.md
goal.md: bb8b4525f7e12a904b1ba77cdefa4e4e1650ffe8
goal.zh.md: c61bfcf7683b3aa835ee7cca58aba861af847d17
goal.md: fc6a7e63e58fc7cd4bc524be1e66515593680d95
goal.zh.md: e6350a4b6307f117361167a532d558d3be8cb367

View File

@@ -71,10 +71,10 @@ interface GoalView extends GoalSnapshot {
## Durable changes
Every mutation is a round-zero goal-sourced message whose metadata is either a complete snapshot or a clear tombstone. It commits when `agent.inject()` records that message in the `inserted` payload of a durable `agent/inbox/spliced` event. The strict fold and persisted projection derive mutations only from these insertions, so deleting the queued context does not roll back goal state. A later `user/message` with the same id verifies the source, metadata, and verbatim rendered content against the insertion without applying the mutation again.
Every mutation is a durable `goal/change` session event whose payload is either a complete post-mutation snapshot or a clear tombstone. The strict fold and persisted projection derive lifecycle state only from these events; inbox mutations do not affect goal state.
```ts type-equiv
/** Full-snapshot goal mutation committed by an injected inbox message. */
/** Full-snapshot goal mutation committed by a durable `goal/change` event. */
interface GoalSnapshotChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
@@ -97,18 +97,16 @@ interface GoalClearChangeMeta {
}
```
Goal state changes use round `0`. A continuation consumer attributes each admitted user-message turn with a positive, sequential round number and the current revision; only these admitted `user/message` events advance `roundsStarted`. Replay rejects gaps, stale revisions, stopped phases, and cap overflow.
A continuation consumer attributes each admitted user-message turn with a positive, sequential round number and the current revision; only these admitted `user/message` events advance `roundsStarted`. Replay rejects non-positive rounds, gaps, stale revisions, stopped phases, and cap overflow.
```ts type-equiv
/** Message attribution for durable goal state and continuation rounds. */
/** Message attribution for admitted continuation rounds. */
interface GoalMessageSource {
readonly kind: 'goal'
readonly goalId: GoalId
readonly revision: number
/** Zero for state changes; positive for admitted continuation rounds. */
/** Positive admitted continuation round. */
readonly round: number
/** Complete durable mutation carried only by round-zero state-change messages. */
readonly change?: GoalChangeMeta
}
```
@@ -133,7 +131,7 @@ interface EditGoalRequest {
```
```ts type-equiv
/** Live notification after one goal mutation commits through inbox insertion. */
/** Live notification after one durable goal mutation commits. */
interface GoalChanged {
readonly operation: GoalOperation
readonly ref: GoalRef
@@ -144,4 +142,4 @@ interface GoalChanged {
## Service behavior
[`GoalService`](../../packages/goal/goal/src/index.ts) resolves creation defaults, folds strict replay from durable inbox insertions, enforces exact-live-agent identity and compare-and-set mutations, reconciles later admission by message id, and emits contained `goal/changed` notifications. The package [README](../../packages/goal/goal/README.md) owns the callable and model-visible contract.
[`GoalService`](../../packages/goal/goal/src/index.ts) resolves creation defaults, folds strict replay from durable `goal/change` events, enforces exact-live-agent identity and compare-and-set mutations, and emits contained `goal/changed` notifications. The package [README](../../packages/goal/goal/README.md) owns the callable and model-visible contract.

View File

@@ -71,10 +71,10 @@ interface GoalView extends GoalSnapshot {
## 持久变更
每次变更都是 Round 编号为 0、来源为目标的消息其元数据要么是完整快照要么是清除墓碑。当 `agent.inject()` 将该消息记录到持久 `agent/inbox/spliced` 事件的 `inserted` 载荷时,变更即已提交。严格折叠与持久投影只从这些插入项派生变更,因此删除队列中的上下文不会回滚目标状态。随后具有相同 id 的 `user/message` 会对照插入项验证来源、元数据和逐字渲染内容,而不会再次应用变更
每次变更都是持久的 `goal/change` 会话事件其载荷要么是变更后的完整快照要么是清除墓碑。严格折叠与持久投影只从这些事件派生生命周期状态inbox 变更不会影响 goal 状态
```ts type-equiv
/** Full-snapshot goal mutation committed by an injected inbox message. */
/** Full-snapshot goal mutation committed by a durable `goal/change` event. */
interface GoalSnapshotChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
@@ -97,18 +97,16 @@ interface GoalClearChangeMeta {
}
```
目标状态变更使用 Round `0`。续跑消费方会为每个获准的用户消息轮次标注正数且连续的 Round 编号和当前修订号;只有这些获准的 `user/message` 事件会推进 `roundsStarted`。回放会拒绝编号缺口、陈旧修订号、已停止阶段和超出上限。
续跑消费方会为每个获准的用户消息轮次标注正数且连续的 Round 编号和当前修订号;只有这些获准的 `user/message` 事件会推进 `roundsStarted`。回放会拒绝非正数 Round、编号缺口、陈旧修订号、已停止阶段和超出上限。
```ts type-equiv
/** Message attribution for durable goal state and continuation rounds. */
/** Message attribution for admitted continuation rounds. */
interface GoalMessageSource {
readonly kind: 'goal'
readonly goalId: GoalId
readonly revision: number
/** Zero for state changes; positive for admitted continuation rounds. */
/** Positive admitted continuation round. */
readonly round: number
/** Complete durable mutation carried only by round-zero state-change messages. */
readonly change?: GoalChangeMeta
}
```
@@ -133,7 +131,7 @@ interface EditGoalRequest {
```
```ts type-equiv
/** Live notification after one goal mutation commits through inbox insertion. */
/** Live notification after one durable goal mutation commits. */
interface GoalChanged {
readonly operation: GoalOperation
readonly ref: GoalRef
@@ -144,4 +142,4 @@ interface GoalChanged {
## 服务行为
[`GoalService`](../../packages/goal/goal/src/index.ts) 解析创建默认值、从持久 inbox 插入项执行严格回放折叠、校验确切的活跃 agent 身份、以比较并设置方式执行变更、按消息 id 对账后续准入,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](../../packages/goal/goal/README.md) 负责记录可调用契约和面向模型的契约。
[`GoalService`](../../packages/goal/goal/src/index.ts) 解析创建默认值、从持久 `goal/change` 事件执行严格回放折叠、校验确切的活跃 agent 身份、以比较并设置方式执行变更,并发出 `goal/changed` 通知;监听器故障会被隔离。包 [README](../../packages/goal/goal/README.md) 负责记录可调用契约和面向模型的契约。