fix: close alignment review races and preserve local conversation state

This commit is contained in:
Codex committed 2026-10-21 04:55:11 +09:00
1 parent c7231be2c5
commit 37ddb2ce24
14 files changed
+203 -45

No files matched your search

@@ -141,7 +141,7 @@ async function main() {
// Automatic invalid-model repair is unrelated to a failed permission choice.
useChatStore.setState(state => ({ sessions: state.sessions.map(item => item.id === 'a' ? { ...item, modelId:'deleted' } : item) }))
await assert.rejects(useChatStore.getState().send('automatic model fallback must not clear permission failure'), /cannot save downgrade/)
assert.equal(useChatStore.getState().sessions.find(item => item.id === 'a')?.modelId, model.id)
assert.equal(useChatStore.getState().sessions.find(item => item.id === 'a')?.modelId, 'deleted', 'failed settings block automatic repair as well as submission')
await useChatStore.getState().selectAgentMode('plan')
await assert.rejects(useChatStore.getState().send('mode save must not clear permission failure'), /cannot save downgrade/)
await useChatStore.getState().selectAgentMode('craft')
@@ -184,6 +184,35 @@ async function main() {
assert.equal(useChatStore.getState().currentSessionId, null)
assert.equal(useChatStore.getState().draftContext.permissionMode, 'default-sandbox', 'pending creation cannot overwrite newer draft preference')
for (const initialModel of [undefined, 'deleted']) {
for (const queued of [false, true]) {
setup()
const owner = `pending-model-${initialModel}-${queued}`
const chosen = { ...model, id: 'chosen', name: 'Chosen' }
useSettingsStore.setState({ models: [model, chosen], selectedModelId: model.id })
useChatStore.setState({ currentSessionId: owner, sessions: [{ ...session(owner), modelId: initialModel }],
...(queued ? { runs: { existing: { runId: 'existing', assistantId: 'assistant', sessionId: owner } } } : {}) })
const choice = deferred<SessionMeta>()
const writes: Array<{ id: string; modelId?: string }> = []
window.ycode.session.updateContext = async (id, patch) => {
writes.push({ id, modelId: patch.modelId })
if (writes.length === 1) return choice.promise
return { ...session(id), ...patch }
}
if (queued) window.ycode.chat.queue = { enqueue: async (payload: SendPayload) => { sent = payload; return {} } } as any
const choosing = useChatStore.getState().selectModel(chosen.id)
const nextSend = useChatStore.getState().send('explicit pending choice wins')
assert.equal(sent, undefined)
// Switching views while the save is pending must not repair the new owner.
useChatStore.setState({ currentSessionId: 'b' })
choice.resolve({ ...session(owner), modelId: chosen.id })
await choosing; await nextSend
assert.deepEqual(writes, [{ id: owner, modelId: chosen.id }], 'fallback cannot overwrite a pending explicit choice')
assert.equal(sent?.sessionId, owner)
assert.equal(useChatStore.getState().sessions.find(item => item.id === owner)?.modelId, chosen.id)
}
}
assert.equal(renderToStaticMarkup(<ModeChip mode="craft" onClear={() => {}} />), '')
assert.match(renderToStaticMarkup(<ModeChip mode="plan" onClear={() => {}} />), /退出计划模式/)
assert.doesNotMatch(renderToStaticMarkup(<ModeChip mode="ask" disabled onClear={() => {}} />), /<button/)