fix: gate workspace artifact mutation paths

This commit is contained in:
Frank Song 2026-05-25 08:46:48 +08:00
parent 4132085e0c
commit 3c9b72f75a
3 changed files with 21 additions and 2 deletions

View file

@ -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

View file

@ -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));

View file

@ -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