From 3c9b72f75a65bc95e01182dab7c739afe5d2f73c Mon Sep 17 00:00:00 2001 From: Frank Song Date: Mon, 25 May 2026 08:46:48 +0800 Subject: [PATCH] fix: gate workspace artifact mutation paths --- CHANGELOG.md | 5 ++++- static/workspace.js | 2 +- tests/test_issue2655_frontend.py | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 494f2eca..0f7b27ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ ## [Unreleased] +### Fixed + +- Workspace Artifacts now keeps read-only tool paths out of the “files changed” list by gating structured path extraction to known file-mutation tools. + ## [v0.51.132] — 2026-05-24 — Release DD (stage-batch14 — 4-PR replayed-context + interrupted-response + shutdown affordance + passkey opt-in) ### Added @@ -27,7 +31,6 @@ - CHANGELOG entries added for PR #2685 and PR #2824 (both originally missing despite functional code changes) - Deferred to follow-up: per-turn cumulative live-tool-prompt token cap (#2685 only added per-call cap; aggregate across many tool calls is a separate refactor). - **i18n parity**: 7 new shutdown-affordance keys added across all 11 non-en locales (it, ja, ru, es, de, zh, zh-Hant, pt, ko, fr, tr) so locale parity tests pass on first run. - ## [v0.51.131] — 2026-05-24 — Release DC (stage-batch13 — 6-PR notes-drawer + context-parity + PWA-swipe + locale polish) ### Added diff --git a/static/workspace.js b/static/workspace.js index 7562c0f0..b53c47fe 100644 --- a/static/workspace.js +++ b/static/workspace.js @@ -204,7 +204,7 @@ function _artifactCandidatesFromToolCall(tc){ path = _normalizeArtifactPath(path); if(path) out.push({path, kind:source}); }; - if(args && typeof args === 'object'){ + if(ARTIFACT_MUTATION_TOOLS.has(name) && args && typeof args === 'object'){ for(const key of ['path','file_path','source','destination']) add(args[key]); if(Array.isArray(args.paths)) args.paths.forEach(p=>add(p)); if(Array.isArray(args.edits)) args.edits.forEach(e=>add(e&&e.path)); diff --git a/tests/test_issue2655_frontend.py b/tests/test_issue2655_frontend.py index a7cf2098..b5da3959 100644 --- a/tests/test_issue2655_frontend.py +++ b/tests/test_issue2655_frontend.py @@ -28,6 +28,22 @@ def test_workspace_artifacts_tab_collects_session_files_and_previews_them(): assert ".workspace-artifact-item" in STYLE_CSS +def test_workspace_artifacts_structured_args_are_mutation_gated(): + """Read-only tool args with path fields must not appear as changed files.""" + fn_start = WORKSPACE_JS.index("function _artifactCandidatesFromToolCall(tc)") + fn_end = WORKSPACE_JS.index("function collectSessionArtifacts()", fn_start) + body = WORKSPACE_JS[fn_start:fn_end] + + args_gate = body.index("args && typeof args === 'object'") + mutation_gate = body.rfind("ARTIFACT_MUTATION_TOOLS.has(name)", 0, args_gate) + + assert mutation_gate >= 0, ( + "structured path/file_path/source/destination extraction must be gated " + "on ARTIFACT_MUTATION_TOOLS so read_file/list_dir paths do not appear " + "as created or edited artifacts" + ) + + def test_changelog_mentions_workspace_artifacts_tab(): unreleased = CHANGELOG.split("## [v0.51.103]", 1)[0] assert "Artifacts tab" in unreleased