Merge origin/master into codex/invariant-service-seam

# Conflicts:
#	docs/architecture.md
#	docs/capability-seams.md
#	docs/cordis-catalog/services.md
#	docs/event-producer-consumer.md
#	docs/module-graph.md
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/support/invariants/package.json
#	packages/support/invariants/src/scoped-events.generated.ts
#	packages/support/invariants/tests/invariants.spec.ts
#	packages/support/invariants/tsconfig.json
#	pnpm-lock.yaml
This commit is contained in:
Tianyi Cui
2026-07-21 00:44:39 +08:00
53 changed files with 3914 additions and 13 deletions
+1
View File
@@ -18,6 +18,7 @@ Everything else is documented on a **sub-page**, not here. The rule that draws t
| [llm-streaming.md](llm-streaming.md) | the `StreamChunk` wire protocol + adapter contract, `BlockAssembler`, the `LlmAdapter` seam |
| [token-meter.md](token-meter.md) | immutable scalar and positional replay measurements with consumed-log revisions |
| [scope.md](scope.md) | scoped registration identity, dispatch carriers, and the owned `Scope` context |
| [goal.md](goal.md) | persisted goal identity, lifecycle snapshots, activation, change records, and round attribution |
| [session.md](session.md) | the full `SessionEventMap` variant catalog, `TurnTrigger`/`TurnEndReason`, `deriveMessages()`, the turn-enclosure invariant |
| [persistence.md](persistence.md) | the durability seam: `SessionPersistence`, JSONL + SQLite backends, `session/flush`, crash recovery, `SessionHeader` |
| [session-query.md](session-query.md) | logical records, bounded exact-event reads, and relationship traces |
+143
View File
@@ -0,0 +1,143 @@
# Same-session goals
Types shared by the event-sourced goal domain and its policy consumers. The [goal-domain Agent Note](../../.agents/notes/implemented/feature/2026-07-19-persisted-same-session-goal-domain.md) owns the persistence and activation decisions; this page records the literal shapes from [`packages/goal/goal/src/types.ts`](../../packages/goal/goal/src/types.ts).
## Identity and lifecycle
`GoalId` is a [branded id](core.md#branded-ids). A caller mutates one exact revision through `GoalRef`; every accepted durable mutation increments the revision.
```ts type-equiv
/** Compare-and-set identity for one exact goal revision. */
interface GoalRef {
/** Stable goal identity. */
readonly id: GoalId
/** Positive revision; every durable mutation increments it. */
readonly revision: number
}
```
The durable phase answers what happened to the objective. Process-local activation separately answers whether a continuation consumer may start another round.
```ts type-equiv
/** Durable continuation phase. Activation is process-local and separate. */
type GoalPhase =
| 'active'
| 'paused'
| 'blocked'
| 'complete'
```
Blocking is the single durable stopped-by-a-problem state. Its policy-owned reason carries a stable lower-kebab-case code for routing and a free-form explanation for humans and models.
```ts type-equiv
/** Machine-routable and human-readable explanation for a blocked goal. */
interface GoalBlockReason {
/** Stable lower-kebab-case classification chosen by the blocking policy. */
readonly code: string
/** Non-empty explanation shown to humans and models. */
readonly message: string
}
```
```ts type-equiv
/** Full durable state written by every non-clear goal mutation. */
interface GoalSnapshot extends GoalRef {
/** Human-requested completion objective. */
readonly objective: string
/** Durable lifecycle phase. */
readonly phase: GoalPhase
/** Present exactly while `phase` is `blocked`. */
readonly blockedReason?: GoalBlockReason
/** Total admitted goal-round cap. */
readonly maxGoalRounds: number
}
```
```ts type-equiv
/** Current goal projection, including values derived from the session log. */
interface GoalView extends GoalSnapshot {
/** Highest admitted round number for this goal. */
readonly roundsStarted: number
/** Epoch milliseconds of the create mutation. */
readonly createdAt: number
/** Epoch milliseconds of the latest mutation. */
readonly updatedAt: number
/** Process-local continuation eligibility; never persisted. */
readonly activation: GoalActivation
}
```
## Durable changes
Every mutation is a `context/message` whose metadata is either a complete snapshot or a clear tombstone. The version, metadata, goal source, and verbatim rendered content form one replay invariant.
```ts type-equiv
/** Full-snapshot goal mutation retained in a model-visible context event. */
interface GoalSnapshotChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
readonly operation: Exclude<GoalOperation, 'clear'>
readonly goal: GoalSnapshot
readonly roundsStarted: number
readonly createdAt: number
readonly updatedAt: number
}
```
```ts type-equiv
/** Tombstone retained when the current goal is cleared. */
interface GoalClearChangeMeta {
readonly kind: 'goal/change'
readonly version: 1
readonly operation: 'clear'
readonly cleared: GoalRef
readonly clearedAt: number
}
```
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; replay rejects gaps, stale revisions, stopped phases, and cap overflow.
```ts type-equiv
/** Message attribution for durable goal state and continuation rounds. */
interface GoalMessageSource {
readonly kind: 'goal'
readonly goalId: GoalId
readonly revision: number
/** Zero for state changes; positive for admitted continuation rounds. */
readonly round: number
}
```
## Requests and notifications
Creation separates caller omission from the deployment choice, which `create()` resolves internally. An edit is a partial replacement whose runtime validator requires at least one field. Every mutation notification carries the accepted operation and exact revision; clear omits `goal`.
```ts type-equiv
/** Input whose omitted round cap is resolved by the service configuration. */
interface CreateGoalRequest {
readonly objective: string
readonly maxGoalRounds?: number
}
```
```ts type-equiv
/** Fields changed by an edit; at least one must be present. */
interface EditGoalRequest {
readonly objective?: string
readonly maxGoalRounds?: number
}
```
```ts type-equiv
/** Live notification after one goal mutation has been accepted for logging. */
interface GoalChanged {
readonly operation: GoalOperation
readonly ref: GoalRef
/** Absent for a clear tombstone. */
readonly goal?: GoalView
}
```
## Service behavior
[`GoalService`](../../packages/goal/goal/src/index.ts) resolves creation defaults, folds strict replay, enforces exact-live-agent identity and compare-and-set mutations, overlays deferred injections, and emits contained `goal/changed` notifications. The package [README](../../packages/goal/goal/README.md) owns the callable and model-visible contract.