fix: harden and de-slop the merged contribution batch
Follow-ups promised on merge, plus review findings on the batch itself: - chat: task-tool output now respects the 512KiB render cap; quick-open icon is visible at rest on coarse pointers and reachable by keyboard (row keydown no longer swallows inner-button Enter/Space); composer inline-code decoration drops the metric-shifting padding; a btw fork send carries only the boundary instruction, never the promotion notice - sync: cascade revert/unrevert aborts busy descendants, busy state is read from every child store at the moment of use; rule 9 documents redo clearing all descendant revert markers - electron: renderer recovery keeps memory-eviction (a valid render-process-gone reason) and both windows share one attachRendererRecovery helper - vscode: process registry is a thin re-export of the web module (provider-env-aliases precedent) with ordered register/unregister writes and an awaited close - server/cli: managed-process registry takes injectable deps (fixes the unreaped-orphans ReferenceError), corrupt settings errors name the file, getWorktrees test restores console.warn - tests: module-mock harnesses removed (AgentsSidebar, SettingsView mobile focus — behaviors stay live but uncovered, accepted trade), QuestionMarkdown asserts rendered DOM - i18n: German gains the debug-panel request keys, Japanese/German drop removed worktree keys, Ukrainian unit spacing fixed - changelog: Copilot AI Credits entries (main + VS Code)
This commit is contained in:
@@ -40,9 +40,17 @@ export const createSettingsAccessors = ({ fsPromises, path, dataDir, settingsFil
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
const parsed = JSON.parse(raw);
|
||||
const corruptSettingsError = (cause) =>
|
||||
new Error(`Settings file is corrupt or unreadable: ${settingsPath} (fix or remove it, then retry)`, { cause });
|
||||
|
||||
let parsed;
|
||||
try {
|
||||
parsed = JSON.parse(raw);
|
||||
} catch (error) {
|
||||
throw corruptSettingsError(error);
|
||||
}
|
||||
if (!parsed || typeof parsed !== 'object') {
|
||||
throw new Error('Settings file is malformed (non-object payload)');
|
||||
throw corruptSettingsError(new Error('non-object payload'));
|
||||
}
|
||||
return parsed;
|
||||
};
|
||||
|
||||
@@ -144,7 +144,16 @@ describe('cli settings accessors', () => {
|
||||
await withTempDir(async (dir) => {
|
||||
const accessors = makeAccessors(dir);
|
||||
fs.writeFileSync(path.join(dir, 'settings.json'), '"just a string"');
|
||||
await expect(accessors.readSettingsStrict()).rejects.toThrow(/non-object payload/);
|
||||
await expect(accessors.readSettingsStrict()).rejects.toThrow(/corrupt or unreadable/);
|
||||
});
|
||||
});
|
||||
|
||||
it('names the settings file in the strict read failure', async () => {
|
||||
await withTempDir(async (dir) => {
|
||||
const accessors = makeAccessors(dir);
|
||||
const filePath = path.join(dir, 'settings.json');
|
||||
fs.writeFileSync(filePath, '{"unfinished": "trunc');
|
||||
await expect(accessors.readSettingsStrict()).rejects.toThrow(filePath);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user