fix(goal): close human command surface gaps
This commit is contained in:
@@ -15,7 +15,7 @@ Human-facing `/goal` control over [`ctx.goals`](../goal/README.md). The plugin r
|
||||
|
||||
Control words are case-insensitive only when they occupy the complete input. Every other non-empty suffix is an objective, so `/goal pause after verification` creates that literal objective. The goal domain trims and validates objectives. Because the generic command plane has no modal editor or confirmation primitive, `edit` takes its replacement inline and an unfinished replacement returns a direct error instructing the user to edit or clear.
|
||||
|
||||
Expected domain rejections become direct command errors. Unexpected implementation failures still reject dispatch so adapters can report them as command failures. Generic command text and output remain live UI state; every accepted mutation is persisted and made model-visible by `dsh-goal` rather than by this plugin.
|
||||
Expected domain rejections become stable direct command errors without exposing branded ids or revisions. Unexpected implementation failures still reject dispatch so adapters can report them as command failures. Generic command text and output remain live UI state; every accepted mutation is persisted and made model-visible by `dsh-goal` rather than by this plugin.
|
||||
|
||||
## Composition
|
||||
|
||||
@@ -30,7 +30,7 @@ The producer injects `commands` and `goals`. A custom app mounts their owners pl
|
||||
name: '@deepseek-ai/dsh-command-goal'
|
||||
```
|
||||
|
||||
The terminal and ACP demo apps enable the complete persisted-goal stack and this command by default; `goals: false` removes both. The UI-less `agent-spine-demo` requires an explicit `goals: {}` so headless one-shot callers do not silently change from one physical turn to a multi-round operation.
|
||||
The TUI and ACP demo apps enable the complete persisted-goal stack and this command by default; `goals: false` removes both. The terminal app's readline mode keeps the model-mediated goal stack but does not mount this producer because that front door does not consume commands. The UI-less `agent-spine-demo` requires an explicit `goals: {}` so headless one-shot callers do not silently change from one physical turn to a multi-round operation.
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ function commandHint(goal: GoalView): string {
|
||||
case 'usage-limited':
|
||||
return '/goal edit <objective>, /goal resume, /goal clear'
|
||||
case 'budget-limited':
|
||||
return '/goal edit <objective>, /goal clear'
|
||||
return '/goal edit <objective>, /goal clear; after the agent raises the round cap, /goal resume'
|
||||
case 'complete':
|
||||
return '/goal <objective>, /goal clear'
|
||||
/* v8 ignore next 2 -- the active branch and every non-active phase are handled above */
|
||||
@@ -149,7 +149,12 @@ function executeGoalCommand(ctx: Context, invocation: CommandInvocation): Comman
|
||||
default: return assertNever(command, 'goal command')
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof GoalError) return { kind: 'error', text: error.message }
|
||||
if (error instanceof GoalError) {
|
||||
return {
|
||||
kind: 'error',
|
||||
text: 'The goal command is not valid for the current state. Run /goal to view available commands.',
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,8 +197,10 @@ describe('/goal human command', () => {
|
||||
const test = await harness()
|
||||
await run(test, ' work')
|
||||
const redundantResume = await run(test, ' RESUME')
|
||||
expect(redundantResume.kind).toBe('error')
|
||||
expect(redundantResume.text).toContain('already active and armed')
|
||||
expect(redundantResume).toEqual({
|
||||
kind: 'error',
|
||||
text: 'The goal command is not valid for the current state. Run /goal to view available commands.',
|
||||
})
|
||||
const paused = await run(test, ' PAUSE')
|
||||
expect(paused.kind).toBe('success')
|
||||
expect(paused.text).toContain('Goal paused')
|
||||
@@ -238,7 +240,7 @@ describe('/goal human command', () => {
|
||||
goal = test.ctx.goals.markBudgetLimited(test.agent, ref(goal))
|
||||
const limited = await run(test)
|
||||
expect(limited.text).toContain('Status: limited by round budget')
|
||||
expect(limited.text).not.toContain('/goal resume')
|
||||
expect(limited.text).toContain('after the agent raises the round cap, /goal resume')
|
||||
|
||||
goal = test.ctx.goals.complete(test.agent, ref(goal))
|
||||
const complete = await run(test)
|
||||
|
||||
Reference in New Issue
Block a user