Merge pull request #1130 from deepseek-harness/fix/goal-ref-shape

fix(goal): emit bare GoalRef in fold lastRef and goal/changed notifications
This commit is contained in:
Tianyi Cui
2026-08-02 02:52:18 +08:00
committed by GitHub
2 changed files with 23 additions and 2 deletions

View File

@@ -261,7 +261,9 @@ function validateSnapshotTransition(
* @returns stable identity used to reconcile a deferred change with its log event.
*/
export function goalChangeRef(change: GoalChangeMeta): GoalRef {
return change.operation === 'clear' ? change.cleared : change.goal
return change.operation === 'clear'
? change.cleared
: { id: change.goal.id, revision: change.goal.revision }
}
/**

View File

@@ -11,7 +11,7 @@ import GoalService, {
foldGoal,
renderGoalChange,
} from '@deepseek-ai/dsh-goal'
import type { GoalChangeMeta, GoalRef, GoalSnapshotChangeMeta } from '@deepseek-ai/dsh-goal'
import type { GoalChangeMeta, GoalChanged, GoalRef, GoalSnapshotChangeMeta } from '@deepseek-ai/dsh-goal'
type DeferredInjection = UserMessage
@@ -381,6 +381,25 @@ describe('GoalService mutations', () => {
expect(next.id).not.toBe(goal.id)
})
it('emits bare compare-and-set refs in folded lastRef and goal/changed notifications', async () => {
const { ctx, agent, session } = await harness()
const seen: GoalChanged['ref'][] = []
ctx.on('goal/changed', (_subject, change) => { seen.push(change.ref) })
const created = ctx.goals.create(agent, { objective: 'bare refs', maxGoalRounds: 3 })
const edited = ctx.goals.edit(agent, created, { objective: 'bare refs edited' })
const blocked = ctx.goals.block(agent, edited, { code: 'bare-blocker', message: 'Bare refs.' })
// GoalRef is exactly { id, revision }: every notification ref must be bare.
for (const ref of seen) {
expect(Object.keys(ref).sort()).toEqual(['id', 'revision'])
expect(ref).toEqual({ id: created.id, revision: ref.revision })
}
expect(seen).toHaveLength(3)
// The durable fold's lastRef is the same bare ref, not a full snapshot.
const folded = foldGoal(session.events)
expect(folded.lastRef).toEqual({ id: blocked.id, revision: blocked.revision })
expect(Object.keys(folded.lastRef as object).sort()).toEqual(['id', 'revision'])
})
it('keeps per-goal mutation timestamps monotonic when the wall clock moves backward', async () => {
vi.useFakeTimers()
vi.setSystemTime(100)