Skip to content

Commit 86b9f13

Browse files
fix(cli): never honor memory agent budgets from workspace scope (#13508)
* fix(cli): never honor memory agent budgets from workspace scope memory.agentMaxTurns and memory.agentTimeoutMinutes cap the turn count and wall-clock time of the auto-approved background memory agents that hold write access to the cross-project memory directory, and 0 disables each limit. A cloned repository could set them in .qwen/settings.json and remove those budgets. Add both keys to WORKSPACE_RESTRICTED_SETTINGS so workspace values are stripped with a warning like the other restricted keys, and state the allowed scopes in the setting descriptions. Closes #13477 Refs #13462 * test(cli): trim duplicated memory-budget scope cases, align descriptions R1-1: main already carries the workspace restriction (#13462) plus it.each([undefined, 0, 25]), which covers the strip, the per-key warning and user-scope 0 survival, so drop the two restating cases and move the list membership assertion into the existing WORKSPACE_RESTRICTED_SETTINGS describe instead of keeping a second describe for the same rule. The list-driven strip test keeps feeding 0 for the two numeric budgets. R1-2: the appended scope sentence named two of the three honored scopes and never stated the consequence; use the docs row wording verbatim. R1-4: name the fifth getMemoryAgentTimeoutMinutes() consumer (memory/metadata-migration.ts) in the timeout description. agentMaxTurns is unaffected because the migrator hardcodes maxTurns: 1. Companion JSON regenerated via scripts/generate-settings-schema.ts. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmuwnio38a6 * docs(settings): name the memory metadata migration in the agentTimeoutMinutes row R1-4 follow-up. On main both surfaces carried the same four-agent enumeration, so the schema-only edit in the previous commit introduced a docs/schema disagreement instead of closing a pre-existing one. Mirror the fifth getMemoryAgentTimeoutMinutes() consumer into the docs row. memory.agentMaxTurns stays at four agents on both surfaces because metadata-migration.ts hardcodes maxTurns: 1. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmuwnio38a6 --------- Co-authored-by: Qwen-Coder <[email protected]>
1 parent 1246dfb commit 86b9f13

4 files changed

Lines changed: 17 additions & 6 deletions

File tree

‎docs/users/configuration/settings.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ The bridge-availability and missing-bridge warning rules below describe direct t
431431
| `memory.enableTeamMemory` | boolean | Enable a project memory tier shared with collaborators via the git-tracked `.qwen/team-memory/` directory. Writes to it are secret-scanned and reviewable in the git diff. | `false` |
432432
| `memory.enableTeamMemorySync` | boolean | When team memory is enabled, automatically commit, fast-forward-pull, and push the `.qwen/team-memory/` directory at session start so collaborators stay in sync. Requires a configured git upstream. | `false` |
433433
| `memory.enableStructuredRecall` | boolean | Switch memory recall from the flat `MEMORY.md` listing to the structured protocol (hierarchical memory tree, focused subtree, `search_memory` tool). While off, the background metadata migration is never scheduled, so the protocol costs no background model calls. Override with `QWEN_CODE_MEMORY_STRUCTURED_RECALL=0\|1`. Requires a restart. | `false` |
434-
| `memory.agentTimeoutMinutes` | number | Max runtime in minutes for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (2–5 minutes); `0` disables the time limit. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning. | unset |
434+
| `memory.agentTimeoutMinutes` | number | Max runtime in minutes for background memory agents (extraction, dream, remember, skill review, memory metadata migration). Unset uses each agent's built-in default (2–5 minutes); `0` disables the time limit. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning. | unset |
435435
| `memory.agentMaxTurns` | number | Max turns for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (5–8); `0` disables the turn limit. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning. | unset |
436436

437437
See [Memory](../features/memory) for details on how auto-memory works and how to use the `/memory`, `/remember`, and `/dream` commands.

‎packages/cli/src/config/settings.test.ts‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4261,6 +4261,15 @@ describe('Settings Loading and Merging', () => {
42614261
},
42624262
);
42634263

4264+
it('lists both memory budgets as workspace-restricted', () => {
4265+
expect(WORKSPACE_RESTRICTED_SETTING_KEYS).toContain(
4266+
'memory.agentMaxTurns',
4267+
);
4268+
expect(WORKSPACE_RESTRICTED_SETTING_KEYS).toContain(
4269+
'memory.agentTimeoutMinutes',
4270+
);
4271+
});
4272+
42644273
it('selects the complete highest-priority operator Mem0 config', () => {
42654274
const mem0 = { baseUrl: 'https://system.example', protocol: 'mem0-v3' };
42664275
(mockFsExistsSync as Mock).mockReturnValue(true);
@@ -4368,7 +4377,9 @@ describe('Settings Loading and Merging', () => {
43684377
workspacePayload[section][key] =
43694378
key === 'allowedInsecureVoiceBaseUrls'
43704379
? ['http://voice.example/v1']
4371-
: true;
4380+
: key === 'agentMaxTurns' || key === 'agentTimeoutMinutes'
4381+
? 0 // numeric budgets; 0 disables the limit, the value being guarded against
4382+
: true;
43724383
}
43734384
(fs.readFileSync as Mock).mockImplementation(
43744385
(p: fs.PathOrFileDescriptor) => {

‎packages/cli/src/config/settingsSchema.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2440,7 +2440,7 @@ const SETTINGS_SCHEMA = {
24402440
default: undefined as number | undefined,
24412441
minimum: 0,
24422442
description:
2443-
"Max runtime in minutes for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (2–5 minutes); 0 disables the time limit. Useful for slow local models that need longer than the defaults.",
2443+
"Max runtime in minutes for background memory agents (extraction, dream, remember, skill review, memory metadata migration). Unset uses each agent's built-in default (2–5 minutes); 0 disables the time limit. Useful for slow local models that need longer than the defaults. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning.",
24442444
showInDialog: false,
24452445
},
24462446
agentMaxTurns: {
@@ -2451,7 +2451,7 @@ const SETTINGS_SCHEMA = {
24512451
default: undefined as number | undefined,
24522452
minimum: 0,
24532453
description:
2454-
"Max turns for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (5–8); 0 disables the turn limit.",
2454+
"Max turns for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (5–8); 0 disables the turn limit. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning.",
24552455
showInDialog: false,
24562456
},
24572457
enableTeamMemory: {

‎packages/vscode-ide-companion/schemas/settings.schema.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,12 +1177,12 @@
11771177
"default": true
11781178
},
11791179
"agentTimeoutMinutes": {
1180-
"description": "Max runtime in minutes for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (2–5 minutes); 0 disables the time limit. Useful for slow local models that need longer than the defaults.",
1180+
"description": "Max runtime in minutes for background memory agents (extraction, dream, remember, skill review, memory metadata migration). Unset uses each agent's built-in default (2–5 minutes); 0 disables the time limit. Useful for slow local models that need longer than the defaults. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning.",
11811181
"type": "number",
11821182
"minimum": 0
11831183
},
11841184
"agentMaxTurns": {
1185-
"description": "Max turns for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (5–8); 0 disables the turn limit.",
1185+
"description": "Max turns for background memory agents (extraction, dream, remember, skill review). Unset uses each agent's built-in default (5–8); 0 disables the turn limit. User/System/SystemDefaults scopes only; Workspace values are ignored with a warning.",
11861186
"type": "number",
11871187
"minimum": 0
11881188
},

0 commit comments

Comments
 (0)