fix(workspace-context): restore the no-unrepresented-commit gate after master merge

The master merge rewrote reconcileInstructionContext and dropped this
branch's gate: when no transition survives rendering (tiny budgets
produce notice-only text), emit nothing and commit nothing so the next
pass retries. Restore it, align the inbox one-byte test with that
contract (an unrepresentable change is held back, not committed at 1
byte), and move the nested-retry test's probe assertions to sync time
where reconciliation now runs. Also restore master's markdown spec
casts lost in an earlier merge.
This commit is contained in:
ZiyaZhang
2026-08-06 02:13:43 -07:00
parent a362b41dc9
commit fe2703b641
3 changed files with 15 additions and 4 deletions
@@ -162,7 +162,7 @@ describe('MarkdownText', () => {
expect(() => tokenizer?.call({
parser: { constructs: { attentionMarkers: {} } },
previous: null,
}, {}, () => undefined, () => undefined)).toThrow(
} as never, {} as never, () => undefined, () => undefined)).toThrow(
'micromark CommonMark attention markers are unavailable',
)
})
@@ -405,6 +405,10 @@ export async function reconcileInstructionContext(
}
if (items.length === 0) return undefined
const rendered = renderInstructionChanges(items, resolved.maxBytes)
// When no transition survived rendering (tiny budgets render notice-only
// text), emit nothing and commit nothing — the uncommitted versions make the
// next pass retry instead of spamming notice-only contexts.
if (rendered.text.length === 0 || rendered.changes.length === 0) return undefined
return {
context: workspaceContextHook(rendered.text, rendered.changes),
versionUpdates: retainedInstructionVersionUpdates(versionUpdates, rendered.changes),
@@ -3815,13 +3815,18 @@ describe('dynamic nested workspace context injection', () => {
signal: testToolSignal,
callId: CallId('read-tiny-budget-1'), name: 'read', arguments: { file_path: join('pkg', 'file.txt') }, agent,
})
await syncWorkspaceContext(ctx, agent)
const second = await ctx.tools.execute({
signal: testToolSignal,
callId: CallId('read-tiny-budget-2'), name: 'read', arguments: { file_path: join('pkg', 'file.txt') }, agent,
})
await syncWorkspaceContext(ctx, agent)
expect(first.additionalContexts).toBeUndefined()
expect(second.additionalContexts).toBeUndefined()
// Nothing was emitted, and the uncommitted version made the second sync
// probe the instruction file again — the retry.
expect(agent.inbox.nextStep).toHaveLength(0)
expect(fs.readTargets.filter(path => path === instructionPath)).toHaveLength(2)
} finally {
await ctx.fiber.dispose()
@@ -3916,7 +3921,7 @@ describe('workspace context inbox synchronization', () => {
}
})
it('keeps a dynamic change within a one-byte positive render budget', async () => {
it('holds back a dynamic change a one-byte positive render budget cannot represent', async () => {
const root = await tempRepo()
const home = await tempRepo()
const ctx = new Context()
@@ -3934,8 +3939,10 @@ describe('workspace context inbox synchronization', () => {
await syncWorkspaceContext(ctx, agent)
expect(agent.inbox.nextStep).toHaveLength(1)
expect(Buffer.byteLength(blocksText(agent.inbox.nextStep[0]?.content), 'utf8')).toBeLessThanOrEqual(1)
// One byte cannot semantically represent the transition, so nothing is
// emitted and nothing commits — the uncommitted version retries on the
// next touch instead of committing state the model never saw.
expect(agent.inbox.nextStep).toHaveLength(0)
} finally {
await ctx.fiber.dispose()
await rm(root, { recursive: true, force: true })