Make /permissions read like the rest of the console

Tighten the /permissions report into the same operator-console style used by
other slash commands, and make permission mode changes read like a structured
CLI confirmation instead of a raw field swap.

Constraint: Must keep the real permission surface limited to read-only, workspace-write, and danger-full-access
Rejected: Add synthetic shortcuts or approval-state variants | would misrepresent actual supported modes
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep /permissions output aligned with other structured slash command reports as new mode metadata is added
Tested: cargo fmt --manifest-path ./rust/Cargo.toml --all; cargo clippy --manifest-path ./rust/Cargo.toml --workspace --all-targets -- -D warnings; cargo test --manifest-path ./rust/Cargo.toml --workspace; manual REPL smoke test for /permissions and /permissions read-only
Not-tested: Interactive approval prompting flows beyond mode report formatting
This commit is contained in:
Yeachan-Heo
2026-03-31 22:19:58 +00:00
parent 346ea0b91b
commit 4d65f5c1a2

View File

@@ -292,22 +292,56 @@ fn format_model_switch_report(previous: &str, next: &str, message_count: usize)
} }
fn format_permissions_report(mode: &str) -> String { fn format_permissions_report(mode: &str) -> String {
let modes = [
("read-only", "Read/search tools only", mode == "read-only"),
(
"workspace-write",
"Edit files inside the workspace",
mode == "workspace-write",
),
(
"danger-full-access",
"Unrestricted tool access",
mode == "danger-full-access",
),
]
.into_iter()
.map(|(name, description, is_current)| {
let marker = if is_current {
"● current"
} else {
"○ available"
};
format!(" {name:<18} {marker:<11} {description}")
})
.collect::<Vec<_>>()
.join(
"
",
);
format!( format!(
"Permissions "Permissions
Current mode {mode} Active mode {mode}
Mode status live session default
Available modes Modes
read-only Allow read/search tools only {modes}
workspace-write Allow editing within the workspace
danger-full-access Allow unrestricted tool access" Usage
Inspect current mode with /permissions
Switch modes with /permissions <mode>"
) )
} }
fn format_permissions_switch_report(previous: &str, next: &str) -> String { fn format_permissions_switch_report(previous: &str, next: &str) -> String {
format!( format!(
"Permissions updated "Permissions updated
Previous {previous} Result mode switched
Current {next}" Previous mode {previous}
Active mode {next}
Applies to subsequent tool calls
Usage /permissions to inspect current mode"
) )
} }
@@ -1566,17 +1600,21 @@ mod tests {
fn permissions_report_uses_sectioned_layout() { fn permissions_report_uses_sectioned_layout() {
let report = format_permissions_report("workspace-write"); let report = format_permissions_report("workspace-write");
assert!(report.contains("Permissions")); assert!(report.contains("Permissions"));
assert!(report.contains("Current mode workspace-write")); assert!(report.contains("Active mode workspace-write"));
assert!(report.contains("Available modes")); assert!(report.contains("Modes"));
assert!(report.contains("danger-full-access")); assert!(report.contains("read-only ○ available Read/search tools only"));
assert!(report.contains("workspace-write ● current Edit files inside the workspace"));
assert!(report.contains("danger-full-access ○ available Unrestricted tool access"));
} }
#[test] #[test]
fn permissions_switch_report_is_structured() { fn permissions_switch_report_is_structured() {
let report = format_permissions_switch_report("read-only", "workspace-write"); let report = format_permissions_switch_report("read-only", "workspace-write");
assert!(report.contains("Permissions updated")); assert!(report.contains("Permissions updated"));
assert!(report.contains("Previous read-only")); assert!(report.contains("Result mode switched"));
assert!(report.contains("Current workspace-write")); assert!(report.contains("Previous mode read-only"));
assert!(report.contains("Active mode workspace-write"));
assert!(report.contains("Applies to subsequent tool calls"));
} }
#[test] #[test]