fix(ui): drop the caption from the /permission error text too
Review round: the no-caption rule the Agent Note states applied only to the success texts, leaving `permission · unknown permission preset "bogus" (…)`. The error text now reads `unknown preset "bogus" (…)` and its exact wording is pinned; the fixture mirror drops `JSON.stringify` for the host's own quoting so the two cannot drift on a quoted argument. The Note now states the line it draws: the rule bans a caption for the command's own value, not the vocabulary, so `/plan`'s `Plan mode off.` and `/goal`'s `Goal cleared.` conform as written — recorded with the broader name-ban as a rejected alternative. The web row assertions are scoped to the row so unrelated page text reading `permission` cannot satisfy them.
This commit is contained in:
@@ -1333,7 +1333,7 @@ export function createFixtureApi(options: FixtureOptions = {}): ApiProxy {
|
||||
const current = permissionSelectOf(logOf(id)).currentValue
|
||||
append(id, { type: 'command/done', data: { commandId, kind: 'success', text: `current preset ${current} (available: ${Object.keys(PERMISSION_PRESETS).join(', ')})` } })
|
||||
} else if (spec === undefined) {
|
||||
append(id, { type: 'command/done', data: { commandId, kind: 'error', text: `unknown permission preset ${JSON.stringify(preset)} (available: ${Object.keys(PERMISSION_PRESETS).join(', ')})` } })
|
||||
append(id, { type: 'command/done', data: { commandId, kind: 'error', text: `unknown preset "${preset}" (available: ${Object.keys(PERMISSION_PRESETS).join(', ')})` } })
|
||||
} else {
|
||||
if (permissionSelectOf(logOf(id)).currentValue !== preset) append(id, { type: 'permission/preset', data: { preset } })
|
||||
append(id, { type: 'sandbox/mode', data: { mode: spec.sandbox } })
|
||||
|
||||
@@ -211,16 +211,16 @@ export class PermissionService extends Service {
|
||||
name: 'permission',
|
||||
description: 'Switch the permission preset (sandbox mode + approval policy)',
|
||||
input: { hint: '<preset>' },
|
||||
// The settlement text never repeats the command's own name: a surface
|
||||
// that renders `name · text` (the web command row) would otherwise
|
||||
// read `permission · Permission preset: workspace-write.`
|
||||
// No settlement text labels its value with this command's own name: a
|
||||
// surface that renders `name · text` (the web command row) would
|
||||
// otherwise read `permission · Permission preset: workspace-write.`
|
||||
handler: ({ agent, rawInput }) => {
|
||||
const name = rawInput.trim()
|
||||
if (name === '') {
|
||||
return { kind: 'success', text: `current preset ${this.current(agent.session.events)} (available: ${this.names.join(', ')})` }
|
||||
}
|
||||
if (!this.names.includes(name)) {
|
||||
return { kind: 'error', text: `unknown permission preset "${name}" (available: ${this.names.join(', ')})` }
|
||||
return { kind: 'error', text: `unknown preset "${name}" (available: ${this.names.join(', ')})` }
|
||||
}
|
||||
this.set(agent.session, name)
|
||||
return { kind: 'success', text: `preset ${name}` }
|
||||
|
||||
@@ -110,7 +110,13 @@ describe('/permission command', () => {
|
||||
const { ctx, session } = await harness()
|
||||
const agent = await agentFor(ctx, session)
|
||||
const execution = await ctx.commands.execute(agent, '/permission yolo', new AbortController().signal)
|
||||
expect(execution?.result).toMatchObject({ kind: 'error' })
|
||||
// The error text carries the same no-self-labelling rule as the success
|
||||
// texts: `permission · unknown preset "yolo" (…)`, not `unknown permission
|
||||
// preset`, which the row's own title already says.
|
||||
expect(execution?.result).toEqual({
|
||||
kind: 'error',
|
||||
text: 'unknown preset "yolo" (available: workspace-write, danger-full-access)',
|
||||
})
|
||||
expect(session.events.filter(event => event.type !== 'command/run' && event.type !== 'command/done')).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user