fix(workspace-context): deduplicate baseline on resume

This commit is contained in:
fz
2026-08-04 19:55:27 +08:00
parent 237b80f4e4
commit 207c45d15f
16 files changed
+358 -53

No files matched your search

@@ -72,22 +72,12 @@ export function apply(ctx: Context, config: Config): void {
// interval before an injected baseline becomes a durable surface event.
const baselineSettledGeneration = new WeakMap<object, number>()
const baselineQueuedGeneration = new WeakMap<object, number>()
// Sessions whose lifecycle start this mount witnessed. A startup or resume
// emits agent/session-start before the first step; a hot remount attaches to
// an already-live session and never sees it. Resumes always re-compose the
// baseline from current files. Hot remounts retain a baseline only while its
// typed event remains model-visible.
const lifecycleWitnessed = new WeakSet<object>()
const pendingByParent = new Map<ToolExecutionToken, {
agent: Agent
changes: WorkspaceInstructionChange[]
versionUpdates: InstructionVersionUpdate[]
}>()
ctx.on('agent/session-start', (agent: Agent) => {
lifecycleWitnessed.add(agent.session)
})
ctx.on('session/event', (session, event) => {
observeInstructionSessionEvent(session, event, pendingNestedChanges, instructionVersions)
if (event.type === 'user/message'
@@ -136,7 +126,7 @@ export function apply(ctx: Context, config: Config): void {
pendingNestedChanges,
instructionVersions,
fileSystem,
{ includeBaselineScopes: false, ...signal === undefined ? {} : { signal } },
{ includeBaselineScopes: keepVisibleBaseline, ...signal === undefined ? {} : { signal } },
)
signal?.throwIfAborted()
const generation = agent.session.surface.replaceGeneration
@@ -175,7 +165,7 @@ export function apply(ctx: Context, config: Config): void {
ctx.on('agent/step', async (agent: Agent, _turn, _step, signal): Promise<void> => {
if (baselineLoaded.has(agent.session)) return
const keepVisibleBaseline = !lifecycleWitnessed.has(agent.session) && hasVisibleBaseline(agent.session)
const keepVisibleBaseline = hasVisibleBaseline(agent.session)
await prepareBaseline(agent, signal, keepVisibleBaseline)
})
@@ -39,7 +39,7 @@ const FILE_TOUCH_TOOL_NAMES = new Set(['read', 'write', 'edit'])
/** Durable provenance and reconciliation facts for one workspace context. */
export interface WorkspaceInstructionSource {
kind: 'workspace-instructions'
/** Marks the complete startup/resume baseline rather than a later delta. */
/** Marks a complete baseline rather than a later delta. */
baseline?: true
changes: WorkspaceInstructionChange[]
}