From 49fe934e7483c546e60d94a341bf8eeae85253ac Mon Sep 17 00:00:00 2001 From: calendar-assistant Date: Thu, 2 Jul 2026 15:15:52 +0800 Subject: [PATCH] fix: update minutes permission hints to guide apply-permission with user confirmation Replace "Ask the minute owner for permission" hints with actionable commands that direct the agent to confirm with the user before running `minutes +apply-permission`. This ensures permission requests are user-initiated rather than automatically executed by AI agents. Change-Id: I2df45e1e1786e7e868db2d4991d8cd60121b2c21 --- shortcuts/minutes/minutes_detail.go | 2 +- shortcuts/minutes/minutes_speaker_replace.go | 2 +- shortcuts/minutes/minutes_speaker_replace_test.go | 4 ++-- shortcuts/minutes/minutes_summary_todo_test.go | 4 ++-- shortcuts/minutes/minutes_todo.go | 2 +- shortcuts/minutes/minutes_update.go | 2 +- shortcuts/minutes/minutes_update_test.go | 4 ++-- shortcuts/minutes/minutes_word_replace.go | 2 +- shortcuts/vc/vc_notes.go | 2 +- shortcuts/vc/vc_notes_test.go | 2 +- 10 files changed, 13 insertions(+), 13 deletions(-) diff --git a/shortcuts/minutes/minutes_detail.go b/shortcuts/minutes/minutes_detail.go index 8a7f4f1a..ca55cb54 100644 --- a/shortcuts/minutes/minutes_detail.go +++ b/shortcuts/minutes/minutes_detail.go @@ -53,7 +53,7 @@ func fetchMinuteDetail(ctx context.Context, runtime *common.RuntimeContext, minu if err != nil { result := &minuteDetailItem{MinuteToken: minuteToken} if p, ok := errs.ProblemOf(err); ok && p.Code == minutesDetailNoReadPermissionCode { - result.Error = fmt.Sprintf("No read permission for minute %s. Ask the minute owner for minute file read permission", minuteToken) + result.Error = fmt.Sprintf("No read permission for minute %s. Ask the user before running: minutes +apply-permission --minute-token %s --perm view", minuteToken, minuteToken) } else { result.Error = fmt.Sprintf("failed to query minute: %v", err) } diff --git a/shortcuts/minutes/minutes_speaker_replace.go b/shortcuts/minutes/minutes_speaker_replace.go index 716230d3..42e3d287 100644 --- a/shortcuts/minutes/minutes_speaker_replace.go +++ b/shortcuts/minutes/minutes_speaker_replace.go @@ -148,7 +148,7 @@ func minutesSpeakerReplaceError(err error, minuteToken, sourceSpeaker string) er switch p.Code { case minutesSpeakerReplaceNoEditPermission: p.Message = fmt.Sprintf("No edit permission for minute %q: cannot replace the transcript speaker.", minuteToken) - p.Hint = "Ask the minute owner for minute edit permission" + p.Hint = fmt.Sprintf("Ask the user before running: minutes +apply-permission --minute-token %s --perm edit", minuteToken) case minutesSpeakerReplaceSpeakerNotFoundCode: p.Subtype = errs.SubtypeNotFound p.Message = fmt.Sprintf("Speaker not found in minute %q: source speaker %q does not match an existing speaker in the transcript.", minuteToken, sourceSpeaker) diff --git a/shortcuts/minutes/minutes_speaker_replace_test.go b/shortcuts/minutes/minutes_speaker_replace_test.go index 5b028a24..c00057bb 100644 --- a/shortcuts/minutes/minutes_speaker_replace_test.go +++ b/shortcuts/minutes/minutes_speaker_replace_test.go @@ -404,7 +404,7 @@ func TestMinutesSpeakerReplace_NoEditPermission(t *testing.T) { if !strings.Contains(p.Message, minutesSpeakerReplaceTestToken) { t.Errorf("message should include minute token, got: %s", p.Message) } - if !strings.Contains(p.Hint, "edit permission") { - t.Errorf("hint should mention edit permission, got: %s", p.Hint) + if !strings.Contains(p.Hint, "+apply-permission") { + t.Errorf("hint should mention apply-permission, got: %s", p.Hint) } } diff --git a/shortcuts/minutes/minutes_summary_todo_test.go b/shortcuts/minutes/minutes_summary_todo_test.go index 0ebd3d29..ca41db97 100644 --- a/shortcuts/minutes/minutes_summary_todo_test.go +++ b/shortcuts/minutes/minutes_summary_todo_test.go @@ -400,8 +400,8 @@ func TestMinutesTodo_NoEditPermission(t *testing.T) { if !strings.Contains(p.Message, minutesSummaryTodoTestToken) { t.Errorf("message should include minute token, got: %s", p.Message) } - if !strings.Contains(p.Hint, "edit permission") { - t.Errorf("hint should mention edit permission, got: %s", p.Hint) + if !strings.Contains(p.Hint, "+apply-permission") { + t.Errorf("hint should mention apply-permission, got: %s", p.Hint) } } diff --git a/shortcuts/minutes/minutes_todo.go b/shortcuts/minutes/minutes_todo.go index 70730b43..93c84ea0 100644 --- a/shortcuts/minutes/minutes_todo.go +++ b/shortcuts/minutes/minutes_todo.go @@ -288,6 +288,6 @@ func minutesTodoError(err error, minuteToken string) error { } p.Subtype = errs.SubtypePermissionDenied p.Message = fmt.Sprintf("No edit permission for minute %q: cannot update todos.", minuteToken) - p.Hint = "Ask the minute owner for minute edit permission" + p.Hint = fmt.Sprintf("Ask the user before running: minutes +apply-permission --minute-token %s --perm edit", minuteToken) return err } diff --git a/shortcuts/minutes/minutes_update.go b/shortcuts/minutes/minutes_update.go index b7fa2bf6..6b9f9378 100644 --- a/shortcuts/minutes/minutes_update.go +++ b/shortcuts/minutes/minutes_update.go @@ -79,6 +79,6 @@ func minutesUpdateError(err error, minuteToken string) error { return err } p.Message = fmt.Sprintf("No edit permission for minute %q: cannot update the title.", minuteToken) - p.Hint = "Ask the minute owner for minute edit permission" + p.Hint = fmt.Sprintf("Ask the user before running: minutes +apply-permission --minute-token %s --perm edit", minuteToken) return err } diff --git a/shortcuts/minutes/minutes_update_test.go b/shortcuts/minutes/minutes_update_test.go index 22264936..7356aaed 100644 --- a/shortcuts/minutes/minutes_update_test.go +++ b/shortcuts/minutes/minutes_update_test.go @@ -171,7 +171,7 @@ func TestMinutesUpdate_NoEditPermission(t *testing.T) { if !strings.Contains(p.Message, minutesUpdateTestToken) { t.Errorf("message should include minute token, got: %s", p.Message) } - if !strings.Contains(p.Hint, "edit permission") { - t.Errorf("hint should mention edit permission, got: %s", p.Hint) + if !strings.Contains(p.Hint, "+apply-permission") { + t.Errorf("hint should mention apply-permission, got: %s", p.Hint) } } diff --git a/shortcuts/minutes/minutes_word_replace.go b/shortcuts/minutes/minutes_word_replace.go index 2cae38eb..db7f2a9b 100644 --- a/shortcuts/minutes/minutes_word_replace.go +++ b/shortcuts/minutes/minutes_word_replace.go @@ -139,7 +139,7 @@ func minutesWordReplaceError(err error, minuteToken string) error { case minutesWordReplaceNoEditPermission: p.Subtype = errs.SubtypePermissionDenied p.Message = fmt.Sprintf("No edit permission for minute %q: cannot replace transcript words.", minuteToken) - p.Hint = "Ask the minute owner for minute edit permission" + p.Hint = fmt.Sprintf("Ask the user before running: minutes +apply-permission --minute-token %s --perm edit", minuteToken) case minutesWordReplaceOthersEditing: p.Subtype = errs.SubtypeConflict p.Message = fmt.Sprintf("Minute %q transcript is being edited by someone else.", minuteToken) diff --git a/shortcuts/vc/vc_notes.go b/shortcuts/vc/vc_notes.go index 555acc70..0d1b0325 100644 --- a/shortcuts/vc/vc_notes.go +++ b/shortcuts/vc/vc_notes.go @@ -68,7 +68,7 @@ func minutesReadError(err error, minuteToken string) error { return err } p.Message = fmt.Sprintf("No read permission for minute %s: cannot query the minute.", minuteToken) - p.Hint = "Ask the minute owner for minute file read permission" + p.Hint = fmt.Sprintf("Ask the user before running: minutes +apply-permission --minute-token %s --perm view", minuteToken) return err } diff --git a/shortcuts/vc/vc_notes_test.go b/shortcuts/vc/vc_notes_test.go index 992c5f2d..d87ae13a 100644 --- a/shortcuts/vc/vc_notes_test.go +++ b/shortcuts/vc/vc_notes_test.go @@ -1255,7 +1255,7 @@ func TestMinutesReadError_ProblemOf_EnrichesMessage(t *testing.T) { t.Errorf("error message not enriched: %q", errMsg) } hint, _ := note["hint"].(string) - if !strings.Contains(hint, "minute file read permission") { + if !strings.Contains(hint, "+apply-permission") { t.Errorf("hint not surfaced: %q", hint) } }