Same-session goals
Identity and lifecycle
Section titled “Identity and lifecycle”GoalId is a branded id. A caller mutates one exact revision through GoalRef; every accepted durable mutation increments the revision.
/** 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.
/** 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.
/** 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}/** 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}/** 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
Section titled “Durable changes”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.
/** Full-snapshot goal mutation committed by a durable `goal/change` 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}/** 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}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.
/** Message attribution for admitted continuation rounds. */interface GoalMessageSource { readonly kind: 'goal' readonly goalId: GoalId readonly revision: number /** Positive admitted continuation round. */ readonly round: number}Requests and notifications
Section titled “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.
/** Input whose omitted round cap is resolved by the service configuration. */interface CreateGoalRequest { readonly objective: string readonly maxGoalRounds?: number}/** Fields changed by an edit; at least one must be present. */interface EditGoalRequest { readonly objective?: string readonly maxGoalRounds?: number}/** Live notification after one durable goal mutation commits. */interface GoalChanged { readonly operation: GoalOperation readonly ref: GoalRef /** Absent for a clear tombstone. */ readonly goal?: GoalView}Service behavior
Section titled “Service behavior”GoalService 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 defines the callable API and model-visible contract.
Cordis API
Section titled “Cordis API”Generated from source by scripts/gen-cordis-catalog.ts (verified fresh by pnpm run verify-cordis-catalog in doc-sync; regenerate with pnpm run gen-cordis-catalog) — this section is byte-identical in both language sides of the page. Signature blocks use a ts cordis-catalog fence and keep the original source JSDoc; dispatch modes are defined in the primer, and the framework-inherited ctx API lives in cordis-api/inherited.md.
ctx.goals — GoalService
Section titled “ctx.goals — GoalService”Goal service (ctx.goals) backed exclusively by the owning session log.
/** * Read the current goal for one exact live agent. * @param agent - owning live agent. * @returns a fresh view or `undefined` when no goal is current. * @throws {@link GoalError} when the agent is not the registry's live instance. */get(agent: Agent): GoalView | undefined
/** * Remove process-local continuation authority without changing durable goal * phase or revision. Lifecycle owners use this before unloading a driver; * a later human-authorized {@link resume} records the new activation edge. * @param agent - owning live agent. * @returns a fresh disarmed view, or `undefined` when no goal is current. */disarm(agent: Agent): GoalView | undefined
/** * Create and arm a goal. A completed goal may be replaced; every other * current phase must be cleared or resumed instead. * @param agent - owning live agent. * @param request - objective and optional round cap. * @returns the created live view. */create(agent: Agent, request: CreateGoalRequest): GoalView
/** * Edit objective and/or round cap without changing phase. * @param agent - owning live agent. * @param ref - expected current revision. * @param request - at least one replacement field. * @returns the edited view. */@Remote('edit') edit(agent: Agent, ref: GoalRef, request: EditGoalRequest): GoalView
/** * Pause an active goal and disarm automatic continuation. * @param agent - owning live agent. * @param ref - expected current revision. * @returns the paused view. */@Remote('pause') pause(agent: Agent, ref: GoalRef): GoalView
/** * Resume and arm a stopped goal, or rearm an active goal after a * session-start edge, while its round budget still has capacity. * @param agent - owning live agent. * @param ref - expected current revision. * @returns the active view. */@Remote('resume') resume(agent: Agent, ref: GoalRef): GoalView
/** * Mark a current non-complete goal complete and disarm it. * @param agent - owning live agent. * @param ref - expected current revision. * @returns the completed view. */@Remote('complete') complete(agent: Agent, ref: GoalRef): GoalView
/** * Mark an active goal blocked and disarm it. * @param agent - owning live agent. * @param ref - expected current revision. * @param reason - policy-owned stable code and human-readable explanation. * @returns the blocked view with its durable reason. */block(agent: Agent, ref: GoalRef, reason: GoalBlockReason): GoalView
/** * Clear the current goal while retaining a durable tombstone and history. * @param agent - owning live agent. * @param ref - expected current revision. * @returns the tombstone ref whose revision is one past the cleared snapshot. */@Remote('clear') clear(agent: Agent, ref: GoalRef): GoalRef
/** * Create one Goal through the remote boundary. * @param agent - exact live Agent resolved from the wire identity. * @param request - objective and optional round cap. * @returns the created Goal identity. */@Remote('create') remoteExportCreate(agent: Agent, request: CreateGoalRequest): CreateGoalResultTypes: Agent
Source: packages/goal/goal/src/index.ts:183
goal/* events
Section titled “goal/* events”goal/changed — emit
Section titled “goal/changed — emit”Goal mutation accepted by one live agent. The matching goal/change session event has already committed. Listener failures are contained. Scope-filtered dispatch (@deepseek-ai/dsh-scope): agent-scoped listeners receive only that agent.
/** * Goal mutation accepted by one live agent. The matching `goal/change` * session event has already committed. Listener failures are contained. * Scope-filtered dispatch (`@deepseek-ai/dsh-scope`): agent-scoped listeners receive only that agent. * @param payload.agent - agent whose session owns the goal. * @param payload.change - fresh current projection or clear tombstone. * @mode emit */'goal/changed'(this: import('@deepseek-ai/dsh-scope').Scoped<Agent>, payload: { agent: Agent; change: GoalChanged }): void